{"version":3,"sources":["node_modules/browser-pack/_prelude.js","node_modules/bootstrap/js/dist/base-component.js","node_modules/bootstrap/js/dist/collapse.js","node_modules/bootstrap/js/dist/dom/data.js","node_modules/bootstrap/js/dist/dom/event-handler.js","node_modules/bootstrap/js/dist/dom/manipulator.js","node_modules/bootstrap/js/dist/dom/selector-engine.js","node_modules/bootstrap/js/dist/util/config.js","node_modules/bootstrap/js/dist/util/index.js","node_modules/ev-emitter/ev-emitter.js","node_modules/fizzy-ui-utils/utils.js","node_modules/flickity/js/add-remove-cell.js","node_modules/flickity/js/animate.js","node_modules/flickity/js/cell.js","node_modules/flickity/js/core.js","node_modules/flickity/js/drag.js","node_modules/flickity/js/imagesloaded.js","node_modules/flickity/js/index.js","node_modules/flickity/js/lazyload.js","node_modules/flickity/js/page-dots.js","node_modules/flickity/js/player.js","node_modules/flickity/js/prev-next-button.js","node_modules/flickity/js/slide.js","node_modules/get-size/get-size.js","node_modules/imagesloaded/imagesloaded.js","node_modules/unidragger/unidragger.js","source/theme/js/app.js","source/theme/js/components/global/bgDots.js","source/theme/js/components/global/carousels.js","source/theme/js/components/global/mainMenu.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;;ACpGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;;AChFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACv3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;ACzIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;;AC/UA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC3RA;;AAWA;;AACA;;AACA;;;;AAnBA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAKA,IAAM,OAAO,GAAG,SAAV,OAAU,GAAM;AACpB,MAAM,MAAM,GAAG,QAAQ,CAAC,oBAAT,CAA8B,MAA9B,EAAsC,CAAtC,CAAf,CADoB,CAGpB;;AACA,MAAM,MAAM,GAAG,IAAI,cAAJ,EAAf;AACA,EAAA,MAAM,CAAC,IAAP;AAEA,MAAM,SAAS,GAAG,IAAI,oBAAJ,EAAlB;AACA,EAAA,SAAS,CAAC,IAAV;AAEA,MAAM,QAAQ,GAAG,IAAI,kBAAJ,CAAa,iBAAb,CAAjB;AACA,EAAA,QAAQ,CAAC,IAAT,GAXoB,CAapB;AACA;AACA;AACA;AACA;AACD,CAlBD;;AAoBA,CAAC,YAAY;AACX,EAAA,QAAQ,CAAC,eAAT,CAAyB,SAAzB,CAAmC,MAAnC,CAA0C,OAA1C;AACA,EAAA,OAAO;AACR,CAHD;;;;;;;;;;ACzCO,SAAS,MAAT,GAAkB;AAAA;;AACvB,MAAI,cAAc,GAAG,KAArB;AAEA,MAAM,UAAU,GAAG,GAAnB;;AAEA,MAAM,IAAI,GAAG,SAAP,IAAO,GAAM;AACjB,IAAA,cAAc,GAAG,QAAQ,CAAC,gBAAT,CAA0B,UAA1B,CAAjB;AAEA,QAAI,CAAC,cAAL,EAAqB,OAAO,KAAP;;AAErB,IAAA,aAAa;;AACb,IAAA,SAAS,GANQ,CAOjB;;AACD,GARD;;AAUA,MAAM,aAAa,GAAG,SAAhB,aAAgB,GAAM;AAC1B,IAAA,MAAM,CAAC,gBAAP,CACE,QADF,EAEE,SAAS,CAAC,YAAY;AACpB,MAAA,SAAS;AACV,KAFQ,CAFX,EAKE,KALF,EAD0B,CAS1B;AACA;AACA;AACD,GAZD;;AAcA,MAAM,SAAS,GAAG,SAAZ,SAAY,GAAM;AACtB,IAAA,cAAc,CAAC,OAAf,CAAuB,UAAC,EAAD,EAAK,CAAL,EAAW;AAChC,UAAI,MAAM,GAAG,EAAb;AACA,UAAI,OAAO,GAAG,EAAd;AACA,UAAI,OAAO,GAAG,EAAd;AACA,UAAI,WAAW,GAAG,IAAlB;AACA,UAAI,WAAW,GAAG,KAAlB;AAEA,UAAM,cAAc,GAAG,EAAE,CAAC,WAA1B;AACA,UAAM,eAAe,GAAG,EAAE,CAAC,YAA3B;AAEA,MAAA,EAAE,CAAC,SAAH,GAAe,EAAf;;AAEA,UAAI,EAAE,CAAC,SAAH,CAAa,QAAb,CAAsB,eAAtB,CAAJ,EAA4C;AAC1C,QAAA,OAAO,GAAG,EAAV;AACA,QAAA,OAAO,GAAG,EAAV;AACD;;AAED,WAAK,IAAI,CAAC,GAAG,EAAb,EAAiB,CAAC,GAAG,cAArB,EAAqC,CAAC,IAAI,MAA1C,EAAkD;AAChD,aAAK,IAAI,CAAC,GAAG,EAAb,EAAiB,CAAC,GAAG,eAArB,EAAsC,CAAC,IAAI,MAA3C,EAAmD;AACjD,cAAM,GAAG,GAAG,QAAQ,CAAC,aAAT,CAAuB,KAAvB,CAAZ;AAEA,UAAA,GAAG,CAAC,SAAJ,CAAc,GAAd,CAAkB,cAAlB;AACA,UAAA,GAAG,CAAC,KAAJ,CAAU,WAAV,CAAsB,QAAtB,EAAgC,CAAC,GAAG,IAApC;AACA,UAAA,GAAG,CAAC,KAAJ,CAAU,WAAV,CAAsB,QAAtB,EAAgC,CAAC,GAAG,IAApC;AACA,UAAA,GAAG,CAAC,KAAJ,CAAU,WAAV,CAAsB,OAAtB,EAA+B,YAAY,CAAC,OAAD,EAAU,OAAV,CAAZ,GAAiC,IAAhE;AACA,UAAA,GAAG,CAAC,KAAJ,CAAU,WAAV,CAAsB,OAAtB,EAA+B,YAAY,CAAC,WAAD,EAAc,WAAd,CAAZ,GAAyC,IAAxE;AAEA,UAAA,EAAE,CAAC,WAAH,CAAe,GAAf;AACD;AACF;AACF,KA9BD;AA+BD,GAhCD,CA7BuB,CA+DvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAEA,MAAM,YAAY,GAAG,SAAf,YAAe,CAAC,GAAD,EAAM,GAAN,EAAc;AACjC,WAAO,IAAI,CAAC,MAAL,MAAiB,GAAG,GAAG,GAAvB,IAA8B,GAArC;AACD,GAFD;;AAIA,MAAM,SAAS,GAAG,SAAZ,SAAY,CAAC,IAAD,EAAyB;AAAA,QAAlB,OAAkB,uEAAR,GAAQ;AACzC,QAAI,KAAJ;AAEA,WAAO,YAAa;AAAA,wCAAT,IAAS;AAAT,QAAA,IAAS;AAAA;;AAClB,MAAA,YAAY,CAAC,KAAD,CAAZ;AACA,MAAA,KAAK,GAAG,UAAU,CAAC,YAAM;AACvB,QAAA,IAAI,CAAC,KAAL,CAAW,KAAX,EAAiB,IAAjB;AACD,OAFiB,EAEf,OAFe,CAAlB;AAGD,KALD;AAMD,GATD;;AAWA,SAAO;AAAE,IAAA,IAAI,EAAJ;AAAF,GAAP;AACD;;;;;;;;;;ACxFD;;;;AAEO,SAAS,SAAT,GAAqB;AAC1B,MAAI,UAAJ;;AAEA,MAAM,IAAI,GAAG,SAAP,IAAO,GAAM;AACjB,IAAA,gBAAgB;;AAChB,IAAA,cAAc;AACf,GAHD;;AAKA,MAAM,gBAAgB,GAAG,SAAnB,gBAAmB,GAAM;AAC7B,IAAA,UAAU,GAAG,QAAQ,CAAC,gBAAT,CAA0B,WAA1B,CAAb;AACD,GAFD;;AAIA,MAAM,cAAc,GAAG,SAAjB,cAAiB,GAAM;AAC3B,QAAI,UAAU,CAAC,MAAf,EAAuB;AACrB,MAAA,UAAU,CAAC,OAAX,CAAmB,UAAC,EAAD,EAAQ;AACzB,YAAI,KAAK,GAAG,IAAI,iBAAJ,CAAa,EAAb,EAAiB;AAC3B,UAAA,YAAY,EAAE,iBADa;AAE3B,UAAA,UAAU,EAAE,EAAE,CAAC,SAAH,CAAa,QAAb,CAAsB,gBAAtB,IAA0C,KAA1C,GAAkD,IAFnC;AAG3B,UAAA,OAAO,EAAE,EAAE,CAAC,SAAH,CAAa,QAAb,CAAsB,gBAAtB,IAA0C,IAA1C,GAAiD,KAH/B;AAI3B,UAAA,YAAY,EAAE,EAAE,CAAC,SAAH,CAAa,QAAb,CAAsB,gBAAtB,IAA0C,IAA1C,GAAiD,KAJpC;AAK3B,UAAA,QAAQ,EAAE,EAAE,CAAC,SAAH,CAAa,QAAb,CAAsB,gBAAtB,IAA0C,KAA1C,GAAkD,KALjC;AAM3B,UAAA,QAAQ,EAAE,EAAE,CAAC,SAAH,CAAa,QAAb,CAAsB,gBAAtB,IAA0C,IAA1C,GAAiD,KANhC;AAO3B,UAAA,cAAc,EAAE,EAAE,CAAC,SAAH,CAAa,QAAb,CAAsB,gBAAtB,IAA0C,KAA1C,GAAkD,KAPvC;AAQ3B,UAAA,QAAQ,EAAE,EAAE,CAAC,SAAH,CAAa,QAAb,CAAsB,gBAAtB,IAA0C,KAA1C,GAAkD,IARjC;AAS3B,UAAA,eAAe,EAAE;AATU,SAAjB,CAAZ;AAWD,OAZD;AAaD;AACF,GAhBD;;AAkBA,SAAO;AAAE,IAAA,IAAI,EAAJ;AAAF,GAAP;AACD;;;;;;;;;;ACjCM,SAAS,QAAT,CAAkB,QAAlB,EAA4B;AACjC;AACA,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAT,CAAwB,WAAxB,CAAjB;AACA,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAT,CAAuB,SAAvB,CAAf;AACA,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAT,CAAuB,iBAAvB,CAAhB;AACA,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAT,CAAuB,OAAvB,CAAb;AAEA,MAAM,UAAU,GAAG,GAAnB;AAEA,MAAI,IAAJ,CATiC,CAWjC;;AACA,MAAM,IAAI,GAAG,SAAP,IAAO,GAAM;AACjB,QAAI,CAAC,QAAL,EAAe,OAAO,KAAP;AAEf,IAAA,IAAI,GAAG,IAAI,QAAJ,CAAa,QAAb,EAAuB;AAC5B,MAAA,MAAM,EAAE;AADoB,KAAvB,CAAP;;AAIA,IAAA,aAAa;;AACb,IAAA,YAAY;AACb,GATD;;AAWA,MAAM,aAAa,GAAG,SAAhB,aAAgB,GAAM;AAC1B,IAAA,MAAM,CAAC,gBAAP,CAAwB,QAAxB,EAAkC,UAAC,CAAD,EAAO;AACvC,MAAA,YAAY;AACb,KAFD;AAGD,GAJD;;AAMA,MAAM,YAAY,GAAG,SAAf,YAAe,CAAC,CAAD,EAAO;AAC1B,QAAI,MAAM,CAAC,UAAP,GAAoB,UAAxB,EAAoC;AAClC,MAAA,WAAW;AACZ,KAFD,MAEO;AACL,MAAA,YAAY;AACb;AACF,GAND;;AAQA,MAAM,WAAW,GAAG,SAAd,WAAc,GAAM;AACxB,IAAA,gBAAgB;;AAEhB,IAAA,MAAM,CAAC,SAAP,CAAiB,MAAjB,CAAwB,sBAAxB;AAEA,IAAA,QAAQ,CAAC,gBAAT,CAA0B,kBAA1B,EAA8C,mBAA9C,EAAmE,KAAnE;AACA,IAAA,QAAQ,CAAC,gBAAT,CAA0B,kBAA1B,EAA8C,mBAA9C,EAAmE,KAAnE;AAEA,IAAA,MAAM,CAAC,gBAAP,CAAwB,QAAxB,EAAkC,UAAC,CAAD,EAAO;AACvC,MAAA,gBAAgB;AACjB,KAFD;AAGD,GAXD;;AAaA,MAAM,YAAY,GAAG,SAAf,YAAe,GAAM;AACzB,IAAA,gBAAgB;;AAChB,IAAA,IAAI,CAAC,IAAL;AAEA,IAAA,QAAQ,CAAC,IAAT,CAAc,SAAd,CAAwB,MAAxB,CAA+B,WAA/B;AAEA,IAAA,QAAQ,CAAC,mBAAT,CAA6B,kBAA7B,EAAiD,mBAAjD,EAAsE,KAAtE;AACA,IAAA,QAAQ,CAAC,mBAAT,CAA6B,kBAA7B,EAAiD,mBAAjD,EAAsE,KAAtE;AAEA,IAAA,MAAM,CAAC,gBAAP,CAAwB,QAAxB,EAAkC,UAAC,CAAD,EAAO;AACvC,MAAA,gBAAgB;AACjB,KAFD;AAGD,GAZD;;AAcA,MAAM,gBAAgB,GAAG,SAAnB,gBAAmB,GAAM;AAC7B,QAAI,IAAI,CAAC,YAAL,KAAsB,CAA1B,EAA6B;AAC3B;AACA,UAAI,MAAM,CAAC,OAAP,GAAiB,GAArB,EAA0B;AACxB,QAAA,MAAM,CAAC,SAAP,CAAiB,MAAjB,CAAwB,gBAAxB;AACD,OAFD,MAEO;AACL,QAAA,MAAM,CAAC,SAAP,CAAiB,GAAjB,CAAqB,gBAArB;AACD;AACF,KAPD,MAOO;AACL,UAAI,MAAM,GAAG,IAAI,CAAC,SAAL,CAAe,QAAf,CAAwB,eAAxB,IAA2C,GAA3C,GAAiD,GAA9D;;AAEA,UAAI,MAAM,CAAC,OAAP,GAAiB,IAAI,CAAC,YAAL,GAAoB,MAAzC,EAAiD;AAC/C,QAAA,MAAM,CAAC,SAAP,CAAiB,MAAjB,CAAwB,gBAAxB;AACD,OAFD,MAEO;AACL,QAAA,MAAM,CAAC,SAAP,CAAiB,GAAjB,CAAqB,gBAArB;AACD;AACF;AACF,GAjBD;;AAmBA,MAAM,mBAAmB,GAAG,SAAtB,mBAAsB,CAAC,CAAD,EAAO;AACjC,IAAA,QAAQ,CAAC,IAAT,CAAc,SAAd,CAAwB,GAAxB,CAA4B,WAA5B;AACA,IAAA,OAAO,CAAC,SAAR,CAAkB,GAAlB,CAAsB,WAAtB;AACD,GAHD;;AAKA,MAAM,mBAAmB,GAAG,SAAtB,mBAAsB,CAAC,CAAD,EAAO;AACjC,IAAA,QAAQ,CAAC,IAAT,CAAc,SAAd,CAAwB,MAAxB,CAA+B,WAA/B;AACA,IAAA,OAAO,CAAC,SAAR,CAAkB,MAAlB,CAAyB,WAAzB;AACD,GAHD;;AAKA,SAAO;AAAE,IAAA,IAAI,EAAJ;AAAF,GAAP;AACD","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 e && typeof e === 'object' && 'default' in e ? e : { default: e };\n\n const Data__default = /*#__PURE__*/_interopDefaultLegacy(Data);\n const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);\n const Config__default = /*#__PURE__*/_interopDefaultLegacy(Config);\n\n /**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.2.0): base-component.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n /**\n * Constants\n */\n\n const VERSION = '5.2.0';\n /**\n * Class definition\n */\n\n class BaseComponent extends Config__default.default {\n constructor(element, config) {\n super();\n element = index.getElement(element);\n\n if (!element) {\n return;\n }\n\n this._element = element;\n this._config = this._getConfig(config);\n Data__default.default.set(this._element, this.constructor.DATA_KEY, this);\n } // Public\n\n\n dispose() {\n Data__default.default.remove(this._element, this.constructor.DATA_KEY);\n EventHandler__default.default.off(this._element, this.constructor.EVENT_KEY);\n\n for (const propertyName of Object.getOwnPropertyNames(this)) {\n this[propertyName] = null;\n }\n }\n\n _queueCallback(callback, element, isAnimated = true) {\n index.executeAfterTransition(callback, element, isAnimated);\n }\n\n _getConfig(config) {\n config = this._mergeConfigObj(config, this._element);\n config = this._configAfterMerge(config);\n\n this._typeCheckConfig(config);\n\n return config;\n } // Static\n\n\n static getInstance(element) {\n return Data__default.default.get(index.getElement(element), this.DATA_KEY);\n }\n\n static getOrCreateInstance(element, config = {}) {\n return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null);\n }\n\n static get VERSION() {\n return VERSION;\n }\n\n static get DATA_KEY() {\n return `bs.${this.NAME}`;\n }\n\n static get EVENT_KEY() {\n return `.${this.DATA_KEY}`;\n }\n\n static eventName(name) {\n return `${name}${this.EVENT_KEY}`;\n }\n\n }\n\n return BaseComponent;\n\n}));\n//# sourceMappingURL=base-component.js.map\n","/*!\n * Bootstrap collapse.js v5.2.0 (https://getbootstrap.com/)\n * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./util/index'), require('./dom/event-handler'), require('./dom/selector-engine'), require('./base-component')) :\n typeof define === 'function' && define.amd ? define(['./util/index', './dom/event-handler', './dom/selector-engine', './base-component'], factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Collapse = factory(global.Index, global.EventHandler, global.SelectorEngine, global.BaseComponent));\n})(this, (function (index, EventHandler, SelectorEngine, BaseComponent) { 'use strict';\n\n const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };\n\n const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);\n const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);\n const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);\n\n /**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.2.0): collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n /**\n * Constants\n */\n\n const NAME = 'collapse';\n const DATA_KEY = 'bs.collapse';\n const EVENT_KEY = `.${DATA_KEY}`;\n const DATA_API_KEY = '.data-api';\n const EVENT_SHOW = `show${EVENT_KEY}`;\n const EVENT_SHOWN = `shown${EVENT_KEY}`;\n const EVENT_HIDE = `hide${EVENT_KEY}`;\n const EVENT_HIDDEN = `hidden${EVENT_KEY}`;\n const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;\n const CLASS_NAME_SHOW = 'show';\n const CLASS_NAME_COLLAPSE = 'collapse';\n const CLASS_NAME_COLLAPSING = 'collapsing';\n const CLASS_NAME_COLLAPSED = 'collapsed';\n const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`;\n const CLASS_NAME_HORIZONTAL = 'collapse-horizontal';\n const WIDTH = 'width';\n const HEIGHT = 'height';\n const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing';\n const SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"collapse\"]';\n const Default = {\n parent: null,\n toggle: true\n };\n const DefaultType = {\n parent: '(null|element)',\n toggle: 'boolean'\n };\n /**\n * Class definition\n */\n\n class Collapse extends BaseComponent__default.default {\n constructor(element, config) {\n super(element, config);\n this._isTransitioning = false;\n this._triggerArray = [];\n const toggleList = SelectorEngine__default.default.find(SELECTOR_DATA_TOGGLE);\n\n for (const elem of toggleList) {\n const selector = index.getSelectorFromElement(elem);\n const filterElement = SelectorEngine__default.default.find(selector).filter(foundElement => foundElement === this._element);\n\n if (selector !== null && filterElement.length) {\n this._triggerArray.push(elem);\n }\n }\n\n this._initializeChildren();\n\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._triggerArray, this._isShown());\n }\n\n if (this._config.toggle) {\n this.toggle();\n }\n } // Getters\n\n\n static get Default() {\n return Default;\n }\n\n static get DefaultType() {\n return DefaultType;\n }\n\n static get NAME() {\n return NAME;\n } // Public\n\n\n toggle() {\n if (this._isShown()) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n show() {\n if (this._isTransitioning || this._isShown()) {\n return;\n }\n\n let activeChildren = []; // find active children\n\n if (this._config.parent) {\n activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES).filter(element => element !== this._element).map(element => Collapse.getOrCreateInstance(element, {\n toggle: false\n }));\n }\n\n if (activeChildren.length && activeChildren[0]._isTransitioning) {\n return;\n }\n\n const startEvent = EventHandler__default.default.trigger(this._element, EVENT_SHOW);\n\n if (startEvent.defaultPrevented) {\n return;\n }\n\n for (const activeInstance of activeChildren) {\n activeInstance.hide();\n }\n\n const dimension = this._getDimension();\n\n this._element.classList.remove(CLASS_NAME_COLLAPSE);\n\n this._element.classList.add(CLASS_NAME_COLLAPSING);\n\n this._element.style[dimension] = 0;\n\n this._addAriaAndCollapsedClass(this._triggerArray, true);\n\n this._isTransitioning = true;\n\n const complete = () => {\n this._isTransitioning = false;\n\n this._element.classList.remove(CLASS_NAME_COLLAPSING);\n\n this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW);\n\n this._element.style[dimension] = '';\n EventHandler__default.default.trigger(this._element, EVENT_SHOWN);\n };\n\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);\n const scrollSize = `scroll${capitalizedDimension}`;\n\n this._queueCallback(complete, this._element, true);\n\n this._element.style[dimension] = `${this._element[scrollSize]}px`;\n }\n\n hide() {\n if (this._isTransitioning || !this._isShown()) {\n return;\n }\n\n const startEvent = EventHandler__default.default.trigger(this._element, EVENT_HIDE);\n\n if (startEvent.defaultPrevented) {\n return;\n }\n\n const dimension = this._getDimension();\n\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`;\n index.reflow(this._element);\n\n this._element.classList.add(CLASS_NAME_COLLAPSING);\n\n this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW);\n\n for (const trigger of this._triggerArray) {\n const element = index.getElementFromSelector(trigger);\n\n if (element && !this._isShown(element)) {\n this._addAriaAndCollapsedClass([trigger], false);\n }\n }\n\n this._isTransitioning = true;\n\n const complete = () => {\n this._isTransitioning = false;\n\n this._element.classList.remove(CLASS_NAME_COLLAPSING);\n\n this._element.classList.add(CLASS_NAME_COLLAPSE);\n\n EventHandler__default.default.trigger(this._element, EVENT_HIDDEN);\n };\n\n this._element.style[dimension] = '';\n\n this._queueCallback(complete, this._element, true);\n }\n\n _isShown(element = this._element) {\n return element.classList.contains(CLASS_NAME_SHOW);\n } // Private\n\n\n _configAfterMerge(config) {\n config.toggle = Boolean(config.toggle); // Coerce string values\n\n config.parent = index.getElement(config.parent);\n return config;\n }\n\n _getDimension() {\n return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT;\n }\n\n _initializeChildren() {\n if (!this._config.parent) {\n return;\n }\n\n const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE);\n\n for (const element of children) {\n const selected = index.getElementFromSelector(element);\n\n if (selected) {\n this._addAriaAndCollapsedClass([element], this._isShown(selected));\n }\n }\n }\n\n _getFirstLevelChildren(selector) {\n const children = SelectorEngine__default.default.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent); // remove children if greater depth\n\n return SelectorEngine__default.default.find(selector, this._config.parent).filter(element => !children.includes(element));\n }\n\n _addAriaAndCollapsedClass(triggerArray, isOpen) {\n if (!triggerArray.length) {\n return;\n }\n\n for (const element of triggerArray) {\n element.classList.toggle(CLASS_NAME_COLLAPSED, !isOpen);\n element.setAttribute('aria-expanded', isOpen);\n }\n } // Static\n\n\n static jQueryInterface(config) {\n const _config = {};\n\n if (typeof config === 'string' && /show|hide/.test(config)) {\n _config.toggle = false;\n }\n\n return this.each(function () {\n const data = Collapse.getOrCreateInstance(this, _config);\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`);\n }\n\n data[config]();\n }\n });\n }\n\n }\n /**\n * Data API implementation\n */\n\n\n EventHandler__default.default.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n // preventDefault only for elements (which change the URL) not inside the collapsible element\n if (event.target.tagName === 'A' || event.delegateTarget && event.delegateTarget.tagName === 'A') {\n event.preventDefault();\n }\n\n const selector = index.getSelectorFromElement(this);\n const selectorElements = SelectorEngine__default.default.find(selector);\n\n for (const element of selectorElements) {\n Collapse.getOrCreateInstance(element, {\n toggle: false\n }).toggle();\n }\n });\n /**\n * jQuery\n */\n\n index.defineJQueryPlugin(Collapse);\n\n return Collapse;\n\n}));\n//# sourceMappingURL=collapse.js.map\n","/*!\n * Bootstrap data.js v5.2.0 (https://getbootstrap.com/)\n * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Data = factory());\n})(this, (function () { 'use strict';\n\n /**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.2.0): dom/data.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n /**\n * Constants\n */\n const elementMap = new Map();\n const data = {\n set(element, key, instance) {\n if (!elementMap.has(element)) {\n elementMap.set(element, new Map());\n }\n\n const instanceMap = elementMap.get(element); // make it clear we only want one instance per element\n // can be removed later when multiple key/instances are fine to be used\n\n if (!instanceMap.has(key) && instanceMap.size !== 0) {\n // eslint-disable-next-line no-console\n console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`);\n return;\n }\n\n instanceMap.set(key, instance);\n },\n\n get(element, key) {\n if (elementMap.has(element)) {\n return elementMap.get(element).get(key) || null;\n }\n\n return null;\n },\n\n remove(element, key) {\n if (!elementMap.has(element)) {\n return;\n }\n\n const instanceMap = elementMap.get(element);\n instanceMap.delete(key); // free up element references if there are no instances left for an element\n\n if (instanceMap.size === 0) {\n elementMap.delete(element);\n }\n }\n\n };\n\n return data;\n\n}));\n//# sourceMappingURL=data.js.map\n","/*!\n * Bootstrap event-handler.js v5.2.0 (https://getbootstrap.com/)\n * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('../util/index')) :\n typeof define === 'function' && define.amd ? define(['../util/index'], factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.EventHandler = factory(global.Index));\n})(this, (function (index) { 'use strict';\n\n /**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.2.0): dom/event-handler.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n /**\n * Constants\n */\n\n const namespaceRegex = /[^.]*(?=\\..*)\\.|.*/;\n const stripNameRegex = /\\..*/;\n const stripUidRegex = /::\\d+$/;\n const eventRegistry = {}; // Events storage\n\n let uidEvent = 1;\n const customEvents = {\n mouseenter: 'mouseover',\n mouseleave: 'mouseout'\n };\n const nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']);\n /**\n * Private methods\n */\n\n function makeEventUid(element, uid) {\n return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++;\n }\n\n function getElementEvents(element) {\n const uid = makeEventUid(element);\n element.uidEvent = uid;\n eventRegistry[uid] = eventRegistry[uid] || {};\n return eventRegistry[uid];\n }\n\n function bootstrapHandler(element, fn) {\n return function handler(event) {\n hydrateObj(event, {\n delegateTarget: element\n });\n\n if (handler.oneOff) {\n EventHandler.off(element, event.type, fn);\n }\n\n return fn.apply(element, [event]);\n };\n }\n\n function bootstrapDelegationHandler(element, selector, fn) {\n return function handler(event) {\n const domElements = element.querySelectorAll(selector);\n\n for (let {\n target\n } = event; target && target !== this; target = target.parentNode) {\n for (const domElement of domElements) {\n if (domElement !== target) {\n continue;\n }\n\n hydrateObj(event, {\n delegateTarget: target\n });\n\n if (handler.oneOff) {\n EventHandler.off(element, event.type, selector, fn);\n }\n\n return fn.apply(target, [event]);\n }\n }\n };\n }\n\n function findHandler(events, callable, delegationSelector = null) {\n return Object.values(events).find(event => event.callable === callable && event.delegationSelector === delegationSelector);\n }\n\n function normalizeParameters(originalTypeEvent, handler, delegationFunction) {\n const isDelegated = typeof handler === 'string'; // todo: tooltip passes `false` instead of selector, so we need to check\n\n const callable = isDelegated ? delegationFunction : handler || delegationFunction;\n let typeEvent = getTypeEvent(originalTypeEvent);\n\n if (!nativeEvents.has(typeEvent)) {\n typeEvent = originalTypeEvent;\n }\n\n return [isDelegated, callable, typeEvent];\n }\n\n function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) {\n if (typeof originalTypeEvent !== 'string' || !element) {\n return;\n }\n\n let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction); // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position\n // this prevents the handler from being dispatched the same way as mouseover or mouseout does\n\n if (originalTypeEvent in customEvents) {\n const wrapFunction = fn => {\n return function (event) {\n if (!event.relatedTarget || event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget)) {\n return fn.call(this, event);\n }\n };\n };\n\n callable = wrapFunction(callable);\n }\n\n const events = getElementEvents(element);\n const handlers = events[typeEvent] || (events[typeEvent] = {});\n const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null);\n\n if (previousFunction) {\n previousFunction.oneOff = previousFunction.oneOff && oneOff;\n return;\n }\n\n const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, ''));\n const fn = isDelegated ? bootstrapDelegationHandler(element, handler, callable) : bootstrapHandler(element, callable);\n fn.delegationSelector = isDelegated ? handler : null;\n fn.callable = callable;\n fn.oneOff = oneOff;\n fn.uidEvent = uid;\n handlers[uid] = fn;\n element.addEventListener(typeEvent, fn, isDelegated);\n }\n\n function removeHandler(element, events, typeEvent, handler, delegationSelector) {\n const fn = findHandler(events[typeEvent], handler, delegationSelector);\n\n if (!fn) {\n return;\n }\n\n element.removeEventListener(typeEvent, fn, Boolean(delegationSelector));\n delete events[typeEvent][fn.uidEvent];\n }\n\n function removeNamespacedHandlers(element, events, typeEvent, namespace) {\n const storeElementEvent = events[typeEvent] || {};\n\n for (const handlerKey of Object.keys(storeElementEvent)) {\n if (handlerKey.includes(namespace)) {\n const event = storeElementEvent[handlerKey];\n removeHandler(element, events, typeEvent, event.callable, event.delegationSelector);\n }\n }\n }\n\n function getTypeEvent(event) {\n // allow to get the native events from namespaced events ('click.bs.button' --> 'click')\n event = event.replace(stripNameRegex, '');\n return customEvents[event] || event;\n }\n\n const EventHandler = {\n on(element, event, handler, delegationFunction) {\n addHandler(element, event, handler, delegationFunction, false);\n },\n\n one(element, event, handler, delegationFunction) {\n addHandler(element, event, handler, delegationFunction, true);\n },\n\n off(element, originalTypeEvent, handler, delegationFunction) {\n if (typeof originalTypeEvent !== 'string' || !element) {\n return;\n }\n\n const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction);\n const inNamespace = typeEvent !== originalTypeEvent;\n const events = getElementEvents(element);\n const storeElementEvent = events[typeEvent] || {};\n const isNamespace = originalTypeEvent.startsWith('.');\n\n if (typeof callable !== 'undefined') {\n // Simplest case: handler is passed, remove that listener ONLY.\n if (!Object.keys(storeElementEvent).length) {\n return;\n }\n\n removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null);\n return;\n }\n\n if (isNamespace) {\n for (const elementEvent of Object.keys(events)) {\n removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1));\n }\n }\n\n for (const keyHandlers of Object.keys(storeElementEvent)) {\n const handlerKey = keyHandlers.replace(stripUidRegex, '');\n\n if (!inNamespace || originalTypeEvent.includes(handlerKey)) {\n const event = storeElementEvent[keyHandlers];\n removeHandler(element, events, typeEvent, event.callable, event.delegationSelector);\n }\n }\n },\n\n trigger(element, event, args) {\n if (typeof event !== 'string' || !element) {\n return null;\n }\n\n const $ = index.getjQuery();\n const typeEvent = getTypeEvent(event);\n const inNamespace = event !== typeEvent;\n let jQueryEvent = null;\n let bubbles = true;\n let nativeDispatch = true;\n let defaultPrevented = false;\n\n if (inNamespace && $) {\n jQueryEvent = $.Event(event, args);\n $(element).trigger(jQueryEvent);\n bubbles = !jQueryEvent.isPropagationStopped();\n nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();\n defaultPrevented = jQueryEvent.isDefaultPrevented();\n }\n\n let evt = new Event(event, {\n bubbles,\n cancelable: true\n });\n evt = hydrateObj(evt, args);\n\n if (defaultPrevented) {\n evt.preventDefault();\n }\n\n if (nativeDispatch) {\n element.dispatchEvent(evt);\n }\n\n if (evt.defaultPrevented && jQueryEvent) {\n jQueryEvent.preventDefault();\n }\n\n return evt;\n }\n\n };\n\n function hydrateObj(obj, meta) {\n for (const [key, value] of Object.entries(meta || {})) {\n try {\n obj[key] = value;\n } catch (_unused) {\n Object.defineProperty(obj, key, {\n configurable: true,\n\n get() {\n return value;\n }\n\n });\n }\n }\n\n return obj;\n }\n\n return EventHandler;\n\n}));\n//# sourceMappingURL=event-handler.js.map\n","/*!\n * Bootstrap manipulator.js v5.2.0 (https://getbootstrap.com/)\n * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Manipulator = factory());\n})(this, (function () { 'use strict';\n\n /**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.2.0): dom/manipulator.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n function normalizeData(value) {\n if (value === 'true') {\n return true;\n }\n\n if (value === 'false') {\n return false;\n }\n\n if (value === Number(value).toString()) {\n return Number(value);\n }\n\n if (value === '' || value === 'null') {\n return null;\n }\n\n if (typeof value !== 'string') {\n return value;\n }\n\n try {\n return JSON.parse(decodeURIComponent(value));\n } catch (_unused) {\n return value;\n }\n }\n\n function normalizeDataKey(key) {\n return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`);\n }\n\n const Manipulator = {\n setDataAttribute(element, key, value) {\n element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value);\n },\n\n removeDataAttribute(element, key) {\n element.removeAttribute(`data-bs-${normalizeDataKey(key)}`);\n },\n\n getDataAttributes(element) {\n if (!element) {\n return {};\n }\n\n const attributes = {};\n const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig'));\n\n for (const key of bsKeys) {\n let pureKey = key.replace(/^bs/, '');\n pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length);\n attributes[pureKey] = normalizeData(element.dataset[key]);\n }\n\n return attributes;\n },\n\n getDataAttribute(element, key) {\n return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`));\n }\n\n };\n\n return Manipulator;\n\n}));\n//# sourceMappingURL=manipulator.js.map\n","/*!\n * Bootstrap selector-engine.js v5.2.0 (https://getbootstrap.com/)\n * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('../util/index')) :\n typeof define === 'function' && define.amd ? define(['../util/index'], factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.SelectorEngine = factory(global.Index));\n})(this, (function (index) { 'use strict';\n\n /**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.2.0): dom/selector-engine.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n /**\n * Constants\n */\n\n const SelectorEngine = {\n find(selector, element = document.documentElement) {\n return [].concat(...Element.prototype.querySelectorAll.call(element, selector));\n },\n\n findOne(selector, element = document.documentElement) {\n return Element.prototype.querySelector.call(element, selector);\n },\n\n children(element, selector) {\n return [].concat(...element.children).filter(child => child.matches(selector));\n },\n\n parents(element, selector) {\n const parents = [];\n let ancestor = element.parentNode.closest(selector);\n\n while (ancestor) {\n parents.push(ancestor);\n ancestor = ancestor.parentNode.closest(selector);\n }\n\n return parents;\n },\n\n prev(element, selector) {\n let previous = element.previousElementSibling;\n\n while (previous) {\n if (previous.matches(selector)) {\n return [previous];\n }\n\n previous = previous.previousElementSibling;\n }\n\n return [];\n },\n\n // TODO: this is now unused; remove later along with prev()\n next(element, selector) {\n let next = element.nextElementSibling;\n\n while (next) {\n if (next.matches(selector)) {\n return [next];\n }\n\n next = next.nextElementSibling;\n }\n\n return [];\n },\n\n focusableChildren(element) {\n const focusables = ['a', 'button', 'input', 'textarea', 'select', 'details', '[tabindex]', '[contenteditable=\"true\"]'].map(selector => `${selector}:not([tabindex^=\"-\"])`).join(',');\n return this.find(focusables, element).filter(el => !index.isDisabled(el) && index.isVisible(el));\n }\n\n };\n\n return SelectorEngine;\n\n}));\n//# sourceMappingURL=selector-engine.js.map\n","/*!\n * Bootstrap config.js v5.2.0 (https://getbootstrap.com/)\n * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./index'), require('../dom/manipulator')) :\n typeof define === 'function' && define.amd ? define(['./index', '../dom/manipulator'], factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Config = factory(global.Index, global.Manipulator));\n})(this, (function (index, Manipulator) { 'use strict';\n\n const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };\n\n const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);\n\n /**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.2.0): util/config.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n /**\n * Class definition\n */\n\n class Config {\n // Getters\n static get Default() {\n return {};\n }\n\n static get DefaultType() {\n return {};\n }\n\n static get NAME() {\n throw new Error('You have to implement the static method \"NAME\", for each component!');\n }\n\n _getConfig(config) {\n config = this._mergeConfigObj(config);\n config = this._configAfterMerge(config);\n\n this._typeCheckConfig(config);\n\n return config;\n }\n\n _configAfterMerge(config) {\n return config;\n }\n\n _mergeConfigObj(config, element) {\n const jsonConfig = index.isElement(element) ? Manipulator__default.default.getDataAttribute(element, 'config') : {}; // try to parse\n\n return { ...this.constructor.Default,\n ...(typeof jsonConfig === 'object' ? jsonConfig : {}),\n ...(index.isElement(element) ? Manipulator__default.default.getDataAttributes(element) : {}),\n ...(typeof config === 'object' ? config : {})\n };\n }\n\n _typeCheckConfig(config, configTypes = this.constructor.DefaultType) {\n for (const property of Object.keys(configTypes)) {\n const expectedTypes = configTypes[property];\n const value = config[property];\n const valueType = index.isElement(value) ? 'element' : index.toType(value);\n\n if (!new RegExp(expectedTypes).test(valueType)) {\n throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option \"${property}\" provided type \"${valueType}\" but expected type \"${expectedTypes}\".`);\n }\n }\n }\n\n }\n\n return Config;\n\n}));\n//# sourceMappingURL=config.js.map\n","/*!\n * Bootstrap index.js v5.2.0 (https://getbootstrap.com/)\n * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n typeof define === 'function' && define.amd ? define(['exports'], factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Index = {}));\n})(this, (function (exports) { 'use strict';\n\n /**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.2.0): util/index.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n const MAX_UID = 1000000;\n const MILLISECONDS_MULTIPLIER = 1000;\n const TRANSITION_END = 'transitionend'; // Shout-out Angus Croll (https://goo.gl/pxwQGp)\n\n const toType = object => {\n if (object === null || object === undefined) {\n return `${object}`;\n }\n\n return Object.prototype.toString.call(object).match(/\\s([a-z]+)/i)[1].toLowerCase();\n };\n /**\n * Public Util API\n */\n\n\n const getUID = prefix => {\n do {\n prefix += Math.floor(Math.random() * MAX_UID);\n } while (document.getElementById(prefix));\n\n return prefix;\n };\n\n const getSelector = element => {\n let selector = element.getAttribute('data-bs-target');\n\n if (!selector || selector === '#') {\n let hrefAttribute = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes,\n // so everything starting with `#` or `.`. If a \"real\" URL is used as the selector,\n // `document.querySelector` will rightfully complain it is invalid.\n // See https://github.com/twbs/bootstrap/issues/32273\n\n if (!hrefAttribute || !hrefAttribute.includes('#') && !hrefAttribute.startsWith('.')) {\n return null;\n } // Just in case some CMS puts out a full URL with the anchor appended\n\n\n if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {\n hrefAttribute = `#${hrefAttribute.split('#')[1]}`;\n }\n\n selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null;\n }\n\n return selector;\n };\n\n const getSelectorFromElement = element => {\n const selector = getSelector(element);\n\n if (selector) {\n return document.querySelector(selector) ? selector : null;\n }\n\n return null;\n };\n\n const getElementFromSelector = element => {\n const selector = getSelector(element);\n return selector ? document.querySelector(selector) : null;\n };\n\n const getTransitionDurationFromElement = element => {\n if (!element) {\n return 0;\n } // Get transition-duration of the element\n\n\n let {\n transitionDuration,\n transitionDelay\n } = window.getComputedStyle(element);\n const floatTransitionDuration = Number.parseFloat(transitionDuration);\n const floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found\n\n if (!floatTransitionDuration && !floatTransitionDelay) {\n return 0;\n } // If multiple durations are defined, take the first\n\n\n transitionDuration = transitionDuration.split(',')[0];\n transitionDelay = transitionDelay.split(',')[0];\n return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;\n };\n\n const triggerTransitionEnd = element => {\n element.dispatchEvent(new Event(TRANSITION_END));\n };\n\n const isElement = object => {\n if (!object || typeof object !== 'object') {\n return false;\n }\n\n if (typeof object.jquery !== 'undefined') {\n object = object[0];\n }\n\n return typeof object.nodeType !== 'undefined';\n };\n\n const getElement = object => {\n // it's a jQuery object or a node element\n if (isElement(object)) {\n return object.jquery ? object[0] : object;\n }\n\n if (typeof object === 'string' && object.length > 0) {\n return document.querySelector(object);\n }\n\n return null;\n };\n\n const isVisible = element => {\n if (!isElement(element) || element.getClientRects().length === 0) {\n return false;\n }\n\n const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'; // Handle `details` element as its content may falsie appear visible when it is closed\n\n const closedDetails = element.closest('details:not([open])');\n\n if (!closedDetails) {\n return elementIsVisible;\n }\n\n if (closedDetails !== element) {\n const summary = element.closest('summary');\n\n if (summary && summary.parentNode !== closedDetails) {\n return false;\n }\n\n if (summary === null) {\n return false;\n }\n }\n\n return elementIsVisible;\n };\n\n const isDisabled = element => {\n if (!element || element.nodeType !== Node.ELEMENT_NODE) {\n return true;\n }\n\n if (element.classList.contains('disabled')) {\n return true;\n }\n\n if (typeof element.disabled !== 'undefined') {\n return element.disabled;\n }\n\n return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';\n };\n\n const findShadowRoot = element => {\n if (!document.documentElement.attachShadow) {\n return null;\n } // Can find the shadow root otherwise it'll return the document\n\n\n if (typeof element.getRootNode === 'function') {\n const root = element.getRootNode();\n return root instanceof ShadowRoot ? root : null;\n }\n\n if (element instanceof ShadowRoot) {\n return element;\n } // when we don't find a shadow root\n\n\n if (!element.parentNode) {\n return null;\n }\n\n return findShadowRoot(element.parentNode);\n };\n\n const noop = () => {};\n /**\n * Trick to restart an element's animation\n *\n * @param {HTMLElement} element\n * @return void\n *\n * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation\n */\n\n\n const reflow = element => {\n element.offsetHeight; // eslint-disable-line no-unused-expressions\n };\n\n const getjQuery = () => {\n if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {\n return window.jQuery;\n }\n\n return null;\n };\n\n const DOMContentLoadedCallbacks = [];\n\n const onDOMContentLoaded = callback => {\n if (document.readyState === 'loading') {\n // add listener on the first call when the document is in loading state\n if (!DOMContentLoadedCallbacks.length) {\n document.addEventListener('DOMContentLoaded', () => {\n for (const callback of DOMContentLoadedCallbacks) {\n callback();\n }\n });\n }\n\n DOMContentLoadedCallbacks.push(callback);\n } else {\n callback();\n }\n };\n\n const isRTL = () => document.documentElement.dir === 'rtl';\n\n const defineJQueryPlugin = plugin => {\n onDOMContentLoaded(() => {\n const $ = getjQuery();\n /* istanbul ignore if */\n\n if ($) {\n const name = plugin.NAME;\n const JQUERY_NO_CONFLICT = $.fn[name];\n $.fn[name] = plugin.jQueryInterface;\n $.fn[name].Constructor = plugin;\n\n $.fn[name].noConflict = () => {\n $.fn[name] = JQUERY_NO_CONFLICT;\n return plugin.jQueryInterface;\n };\n }\n });\n };\n\n const execute = callback => {\n if (typeof callback === 'function') {\n callback();\n }\n };\n\n const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {\n if (!waitForTransition) {\n execute(callback);\n return;\n }\n\n const durationPadding = 5;\n const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;\n let called = false;\n\n const handler = ({\n target\n }) => {\n if (target !== transitionElement) {\n return;\n }\n\n called = true;\n transitionElement.removeEventListener(TRANSITION_END, handler);\n execute(callback);\n };\n\n transitionElement.addEventListener(TRANSITION_END, handler);\n setTimeout(() => {\n if (!called) {\n triggerTransitionEnd(transitionElement);\n }\n }, emulatedDuration);\n };\n /**\n * Return the previous/next element of a list.\n *\n * @param {array} list The list of elements\n * @param activeElement The active element\n * @param shouldGetNext Choose to get next or previous element\n * @param isCycleAllowed\n * @return {Element|elem} The proper element\n */\n\n\n const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {\n const listLength = list.length;\n let index = list.indexOf(activeElement); // if the element does not exist in the list return an element\n // depending on the direction and if cycle is allowed\n\n if (index === -1) {\n return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];\n }\n\n index += shouldGetNext ? 1 : -1;\n\n if (isCycleAllowed) {\n index = (index + listLength) % listLength;\n }\n\n return list[Math.max(0, Math.min(index, listLength - 1))];\n };\n\n exports.defineJQueryPlugin = defineJQueryPlugin;\n exports.execute = execute;\n exports.executeAfterTransition = executeAfterTransition;\n exports.findShadowRoot = findShadowRoot;\n exports.getElement = getElement;\n exports.getElementFromSelector = getElementFromSelector;\n exports.getNextActiveElement = getNextActiveElement;\n exports.getSelectorFromElement = getSelectorFromElement;\n exports.getTransitionDurationFromElement = getTransitionDurationFromElement;\n exports.getUID = getUID;\n exports.getjQuery = getjQuery;\n exports.isDisabled = isDisabled;\n exports.isElement = isElement;\n exports.isRTL = isRTL;\n exports.isVisible = isVisible;\n exports.noop = noop;\n exports.onDOMContentLoaded = onDOMContentLoaded;\n exports.reflow = reflow;\n exports.toType = toType;\n exports.triggerTransitionEnd = triggerTransitionEnd;\n\n Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });\n\n}));\n//# sourceMappingURL=index.js.map\n","/**\n * EvEmitter v2.1.1\n * Lil' event emitter\n * MIT License\n */\n\n( function( global, factory ) {\n // universal module definition\n 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\nfunction EvEmitter() {}\n\nlet proto = EvEmitter.prototype;\n\nproto.on = function( eventName, listener ) {\n if ( !eventName || !listener ) return this;\n\n // set events hash\n let events = this._events = this._events || {};\n // set listeners array\n let listeners = events[ eventName ] = events[ eventName ] || [];\n // only add once\n if ( !listeners.includes( listener ) ) {\n listeners.push( listener );\n }\n\n return this;\n};\n\nproto.once = function( eventName, listener ) {\n if ( !eventName || !listener ) return this;\n\n // add event\n this.on( eventName, listener );\n // set once flag\n // set onceEvents hash\n let onceEvents = this._onceEvents = this._onceEvents || {};\n // set onceListeners object\n let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};\n // set flag\n onceListeners[ listener ] = true;\n\n return this;\n};\n\nproto.off = function( eventName, listener ) {\n let listeners = this._events && this._events[ eventName ];\n if ( !listeners || !listeners.length ) return this;\n\n let 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 let listeners = this._events && this._events[ eventName ];\n if ( !listeners || !listeners.length ) return this;\n\n // copy over to avoid interference if .off() in listener\n listeners = listeners.slice( 0 );\n args = args || [];\n // once stuff\n let onceListeners = this._onceEvents && this._onceEvents[ eventName ];\n\n for ( let listener of listeners ) {\n let 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 return this;\n};\n\nreturn EvEmitter;\n\n} ) );\n","/**\n * Fizzy UI utils v3.0.0\n * MIT license\n */\n\n( function( global, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory( global );\n } else {\n // browser global\n global.fizzyUIUtils = factory( global );\n }\n\n}( this, function factory( global ) {\n\nlet utils = {};\n\n// ----- extend ----- //\n\n// extends objects\nutils.extend = function( a, b ) {\n return Object.assign( a, b );\n};\n\n// ----- modulo ----- //\n\nutils.modulo = function( num, div ) {\n return ( ( num % div ) + div ) % div;\n};\n\n// ----- makeArray ----- //\n\n// turn element or nodeList into an array\nutils.makeArray = function( obj ) {\n // use object if already an array\n if ( Array.isArray( obj ) ) return obj;\n\n // return empty array if undefined or null. #6\n if ( obj === null || obj === undefined ) return [];\n\n let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';\n // convert nodeList to array\n if ( isArrayLike ) return [ ...obj ];\n\n // array of single index\n return [ obj ];\n};\n\n// ----- removeFrom ----- //\n\nutils.removeFrom = function( ary, obj ) {\n let index = ary.indexOf( obj );\n if ( index != -1 ) {\n ary.splice( index, 1 );\n }\n};\n\n// ----- getParent ----- //\n\nutils.getParent = function( elem, selector ) {\n while ( elem.parentNode && elem != document.body ) {\n elem = elem.parentNode;\n if ( elem.matches( selector ) ) return elem;\n }\n};\n\n// ----- getQueryElement ----- //\n\n// use element as selector string\nutils.getQueryElement = function( elem ) {\n if ( typeof elem == 'string' ) {\n return document.querySelector( elem );\n }\n return elem;\n};\n\n// ----- handleEvent ----- //\n\n// enable .ontype to trigger from .addEventListener( elem, 'type' )\nutils.handleEvent = function( event ) {\n let method = 'on' + event.type;\n if ( this[ method ] ) {\n this[ method ]( event );\n }\n};\n\n// ----- filterFindElements ----- //\n\nutils.filterFindElements = function( elems, selector ) {\n // make array of elems\n elems = utils.makeArray( elems );\n\n return elems\n // check that elem is an actual element\n .filter( ( elem ) => elem instanceof HTMLElement )\n .reduce( ( ffElems, elem ) => {\n // add elem if no selector\n if ( !selector ) {\n ffElems.push( elem );\n return ffElems;\n }\n // filter & find items if we have a selector\n // filter\n if ( elem.matches( selector ) ) {\n ffElems.push( elem );\n }\n // find children\n let childElems = elem.querySelectorAll( selector );\n // concat childElems to filterFound array\n ffElems = ffElems.concat( ...childElems );\n return ffElems;\n }, [] );\n};\n\n// ----- debounceMethod ----- //\n\nutils.debounceMethod = function( _class, methodName, threshold ) {\n threshold = threshold || 100;\n // original method\n let method = _class.prototype[ methodName ];\n let timeoutName = methodName + 'Timeout';\n\n _class.prototype[ methodName ] = function() {\n clearTimeout( this[ timeoutName ] );\n\n let args = arguments;\n this[ timeoutName ] = setTimeout( () => {\n method.apply( this, args );\n delete this[ timeoutName ];\n }, threshold );\n };\n};\n\n// ----- docReady ----- //\n\nutils.docReady = function( onDocReady ) {\n let readyState = document.readyState;\n if ( readyState == 'complete' || readyState == 'interactive' ) {\n // do async to allow for other scripts to run. metafizzy/flickity#441\n setTimeout( onDocReady );\n } else {\n document.addEventListener( 'DOMContentLoaded', onDocReady );\n }\n};\n\n// ----- htmlInit ----- //\n\n// http://bit.ly/3oYLusc\nutils.toDashed = function( str ) {\n return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {\n return $1 + '-' + $2;\n } ).toLowerCase();\n};\n\nlet console = global.console;\n\n// allow user to initialize classes via [data-namespace] or .js-namespace class\n// htmlInit( Widget, 'widgetName' )\n// options are parsed from data-namespace-options\nutils.htmlInit = function( WidgetClass, namespace ) {\n utils.docReady( function() {\n let dashedNamespace = utils.toDashed( namespace );\n let dataAttr = 'data-' + dashedNamespace;\n let dataAttrElems = document.querySelectorAll( `[${dataAttr}]` );\n let jQuery = global.jQuery;\n\n [ ...dataAttrElems ].forEach( ( elem ) => {\n let attr = elem.getAttribute( dataAttr );\n let options;\n try {\n options = attr && JSON.parse( attr );\n } catch ( error ) {\n // log error, do not initialize\n if ( console ) {\n console.error( `Error parsing ${dataAttr} on ${elem.className}: ${error}` );\n }\n return;\n }\n // initialize\n let instance = new WidgetClass( elem, options );\n // make available via $().data('namespace')\n if ( jQuery ) {\n jQuery.data( elem, namespace, instance );\n }\n } );\n\n } );\n};\n\n// ----- ----- //\n\nreturn utils;\n\n} ) );\n","// add, remove cell\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('./core'),\n require('fizzy-ui-utils'),\n );\n } else {\n // browser global\n factory(\n window.Flickity,\n window.fizzyUIUtils,\n );\n }\n\n}( typeof window != 'undefined' ? window : this, function factory( Flickity, utils ) {\n\n// append cells to a document fragment\nfunction getCellsFragment( cells ) {\n let fragment = document.createDocumentFragment();\n cells.forEach( ( cell ) => fragment.appendChild( cell.element ) );\n return fragment;\n}\n\n// -------------------------- add/remove cell prototype -------------------------- //\n\nlet proto = Flickity.prototype;\n\n/**\n * Insert, prepend, or append cells\n * @param {[Element, Array, NodeList]} elems - Elements to insert\n * @param {Integer} index - Zero-based number to insert\n */\nproto.insert = function( elems, index ) {\n let cells = this._makeCells( elems );\n if ( !cells || !cells.length ) return;\n\n let len = this.cells.length;\n // default to append\n index = index === undefined ? len : index;\n // add cells with document fragment\n let fragment = getCellsFragment( cells );\n // append to slider\n let isAppend = index === len;\n if ( isAppend ) {\n this.slider.appendChild( fragment );\n } else {\n let insertCellElement = this.cells[ index ].element;\n this.slider.insertBefore( fragment, insertCellElement );\n }\n // add to this.cells\n if ( index === 0 ) {\n // prepend, add to start\n this.cells = cells.concat( this.cells );\n } else if ( isAppend ) {\n // append, add to end\n this.cells = this.cells.concat( cells );\n } else {\n // insert in this.cells\n let endCells = this.cells.splice( index, len - index );\n this.cells = this.cells.concat( cells ).concat( endCells );\n }\n\n this._sizeCells( cells );\n this.cellChange( index );\n this.positionSliderAtSelected();\n};\n\nproto.append = function( elems ) {\n this.insert( elems, this.cells.length );\n};\n\nproto.prepend = function( elems ) {\n this.insert( elems, 0 );\n};\n\n/**\n * Remove cells\n * @param {[Element, Array, NodeList]} elems - ELements to remove\n */\nproto.remove = function( elems ) {\n let cells = this.getCells( elems );\n if ( !cells || !cells.length ) return;\n\n let minCellIndex = this.cells.length - 1;\n // remove cells from collection & DOM\n cells.forEach( ( cell ) => {\n cell.remove();\n let index = this.cells.indexOf( cell );\n minCellIndex = Math.min( index, minCellIndex );\n utils.removeFrom( this.cells, cell );\n } );\n\n this.cellChange( minCellIndex );\n this.positionSliderAtSelected();\n};\n\n/**\n * logic to be run after a cell's size changes\n * @param {Element} elem - cell's element\n */\nproto.cellSizeChange = function( elem ) {\n let cell = this.getCell( elem );\n if ( !cell ) return;\n\n cell.getSize();\n\n let index = this.cells.indexOf( cell );\n this.cellChange( index );\n // do not position slider after lazy load\n};\n\n/**\n * logic any time a cell is changed: added, removed, or size changed\n * @param {Integer} changedCellIndex - index of the changed cell, optional\n */\nproto.cellChange = function( changedCellIndex ) {\n let prevSelectedElem = this.selectedElement;\n this._positionCells( changedCellIndex );\n this._updateWrapShiftCells();\n this.setGallerySize();\n // update selectedIndex, try to maintain position & select previous selected element\n let cell = this.getCell( prevSelectedElem );\n if ( cell ) this.selectedIndex = this.getCellSlideIndex( cell );\n this.selectedIndex = Math.min( this.slides.length - 1, this.selectedIndex );\n\n this.emitEvent( 'cellChange', [ changedCellIndex ] );\n // position slider\n this.select( this.selectedIndex );\n};\n\n// ----- ----- //\n\nreturn Flickity;\n\n} ) );\n","// animate\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory( require('fizzy-ui-utils') );\n } else {\n // browser global\n window.Flickity = window.Flickity || {};\n window.Flickity.animatePrototype = factory( window.fizzyUIUtils );\n }\n\n}( typeof window != 'undefined' ? window : this, function factory( utils ) {\n\n// -------------------------- animate -------------------------- //\n\nlet proto = {};\n\nproto.startAnimation = function() {\n if ( this.isAnimating ) return;\n\n this.isAnimating = true;\n this.restingFrames = 0;\n this.animate();\n};\n\nproto.animate = function() {\n this.applyDragForce();\n this.applySelectedAttraction();\n\n let previousX = this.x;\n\n this.integratePhysics();\n this.positionSlider();\n this.settle( previousX );\n // animate next frame\n if ( this.isAnimating ) requestAnimationFrame( () => this.animate() );\n};\n\nproto.positionSlider = function() {\n let x = this.x;\n // wrap position around\n if ( this.isWrapping ) {\n x = utils.modulo( x, this.slideableWidth ) - this.slideableWidth;\n this.shiftWrapCells( x );\n }\n\n this.setTranslateX( x, this.isAnimating );\n this.dispatchScrollEvent();\n};\n\nproto.setTranslateX = function( x, is3d ) {\n x += this.cursorPosition;\n // reverse if right-to-left and using transform\n if ( this.options.rightToLeft ) x = -x;\n let translateX = this.getPositionValue( x );\n // use 3D transforms for hardware acceleration on iOS\n // but use 2D when settled, for better font-rendering\n this.slider.style.transform = is3d ?\n `translate3d(${translateX},0,0)` : `translateX(${translateX})`;\n};\n\nproto.dispatchScrollEvent = function() {\n let firstSlide = this.slides[0];\n if ( !firstSlide ) return;\n\n let positionX = -this.x - firstSlide.target;\n let progress = positionX / this.slidesWidth;\n this.dispatchEvent( 'scroll', null, [ progress, positionX ] );\n};\n\nproto.positionSliderAtSelected = function() {\n if ( !this.cells.length ) return;\n\n this.x = -this.selectedSlide.target;\n this.velocity = 0; // stop wobble\n this.positionSlider();\n};\n\nproto.getPositionValue = function( position ) {\n if ( this.options.percentPosition ) {\n // percent position, round to 2 digits, like 12.34%\n return ( Math.round( ( position / this.size.innerWidth ) * 10000 ) * 0.01 ) + '%';\n } else {\n // pixel positioning\n return Math.round( position ) + 'px';\n }\n};\n\nproto.settle = function( previousX ) {\n // keep track of frames where x hasn't moved\n let isResting = !this.isPointerDown &&\n Math.round( this.x * 100 ) === Math.round( previousX * 100 );\n if ( isResting ) this.restingFrames++;\n // stop animating if resting for 3 or more frames\n if ( this.restingFrames > 2 ) {\n this.isAnimating = false;\n delete this.isFreeScrolling;\n // render position with translateX when settled\n this.positionSlider();\n this.dispatchEvent( 'settle', null, [ this.selectedIndex ] );\n }\n};\n\nproto.shiftWrapCells = function( x ) {\n // shift before cells\n let beforeGap = this.cursorPosition + x;\n this._shiftCells( this.beforeShiftCells, beforeGap, -1 );\n // shift after cells\n let afterGap = this.size.innerWidth - ( x + this.slideableWidth + this.cursorPosition );\n this._shiftCells( this.afterShiftCells, afterGap, 1 );\n};\n\nproto._shiftCells = function( cells, gap, shift ) {\n cells.forEach( ( cell ) => {\n let cellShift = gap > 0 ? shift : 0;\n this._wrapShiftCell( cell, cellShift );\n gap -= cell.size.outerWidth;\n } );\n};\n\nproto._unshiftCells = function( cells ) {\n if ( !cells || !cells.length ) return;\n\n cells.forEach( ( cell ) => this._wrapShiftCell( cell, 0 ) );\n};\n\n// @param {Integer} shift - 0, 1, or -1\nproto._wrapShiftCell = function( cell, shift ) {\n this._renderCellPosition( cell, cell.x + this.slideableWidth * shift );\n};\n\n// -------------------------- physics -------------------------- //\n\nproto.integratePhysics = function() {\n this.x += this.velocity;\n this.velocity *= this.getFrictionFactor();\n};\n\nproto.applyForce = function( force ) {\n this.velocity += force;\n};\n\nproto.getFrictionFactor = function() {\n return 1 - this.options[ this.isFreeScrolling ? 'freeScrollFriction' : 'friction' ];\n};\n\nproto.getRestingPosition = function() {\n // my thanks to Steven Wittens, who simplified this math greatly\n return this.x + this.velocity / ( 1 - this.getFrictionFactor() );\n};\n\nproto.applyDragForce = function() {\n if ( !this.isDraggable || !this.isPointerDown ) return;\n\n // change the position to drag position by applying force\n let dragVelocity = this.dragX - this.x;\n let dragForce = dragVelocity - this.velocity;\n this.applyForce( dragForce );\n};\n\nproto.applySelectedAttraction = function() {\n // do not attract if pointer down or no slides\n let dragDown = this.isDraggable && this.isPointerDown;\n if ( dragDown || this.isFreeScrolling || !this.slides.length ) return;\n\n let distance = this.selectedSlide.target * -1 - this.x;\n let force = distance * this.options.selectedAttraction;\n this.applyForce( force );\n};\n\nreturn proto;\n\n} ) );\n","// Flickity.Cell\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory( require('get-size') );\n } else {\n // browser global\n window.Flickity = window.Flickity || {};\n window.Flickity.Cell = factory( window.getSize );\n }\n\n}( typeof window != 'undefined' ? window : this, function factory( getSize ) {\n\nconst cellClassName = 'flickity-cell';\n\nfunction Cell( elem ) {\n this.element = elem;\n this.element.classList.add( cellClassName );\n\n this.x = 0;\n this.unselect();\n}\n\nlet proto = Cell.prototype;\n\nproto.destroy = function() {\n // reset style\n this.unselect();\n this.element.classList.remove( cellClassName );\n this.element.style.transform = '';\n this.element.removeAttribute('aria-hidden');\n};\n\nproto.getSize = function() {\n this.size = getSize( this.element );\n};\n\nproto.select = function() {\n this.element.classList.add('is-selected');\n this.element.removeAttribute('aria-hidden');\n};\n\nproto.unselect = function() {\n this.element.classList.remove('is-selected');\n this.element.setAttribute( 'aria-hidden', 'true' );\n};\n\nproto.remove = function() {\n this.element.remove();\n};\n\nreturn Cell;\n\n} ) );\n","// Flickity main\n/* eslint-disable max-params */\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n window,\n require('ev-emitter'),\n require('get-size'),\n require('fizzy-ui-utils'),\n require('./cell'),\n require('./slide'),\n require('./animate'),\n );\n } else {\n // browser global\n let _Flickity = window.Flickity;\n\n window.Flickity = factory(\n window,\n window.EvEmitter,\n window.getSize,\n window.fizzyUIUtils,\n _Flickity.Cell,\n _Flickity.Slide,\n _Flickity.animatePrototype,\n );\n }\n\n}( typeof window != 'undefined' ? window : this,\n function factory( window, EvEmitter, getSize, utils, Cell, Slide, animatePrototype ) {\n/* eslint-enable max-params */\n\n// vars\nconst { getComputedStyle, console } = window;\nlet { jQuery } = window;\n\n// -------------------------- Flickity -------------------------- //\n\n// globally unique identifiers\nlet GUID = 0;\n// internal store of all Flickity intances\nlet instances = {};\n\nfunction Flickity( element, options ) {\n let queryElement = utils.getQueryElement( element );\n if ( !queryElement ) {\n if ( console ) console.error(`Bad element for Flickity: ${queryElement || element}`);\n return;\n }\n this.element = queryElement;\n // do not initialize twice on same element\n if ( this.element.flickityGUID ) {\n let instance = instances[ this.element.flickityGUID ];\n if ( instance ) instance.option( options );\n return instance;\n }\n\n // add jQuery\n if ( jQuery ) {\n this.$element = jQuery( this.element );\n }\n // options\n this.options = { ...this.constructor.defaults };\n this.option( options );\n\n // kick things off\n this._create();\n}\n\nFlickity.defaults = {\n accessibility: true,\n // adaptiveHeight: false,\n cellAlign: 'center',\n // cellSelector: undefined,\n // contain: false,\n freeScrollFriction: 0.075, // friction when free-scrolling\n friction: 0.28, // friction when selecting\n namespaceJQueryEvents: true,\n // initialIndex: 0,\n percentPosition: true,\n resize: true,\n selectedAttraction: 0.025,\n setGallerySize: true,\n // watchCSS: false,\n // wrapAround: false\n};\n\n// hash of methods triggered on _create()\nFlickity.create = {};\n\nlet proto = Flickity.prototype;\n// inherit EventEmitter\nObject.assign( proto, EvEmitter.prototype );\n\nproto._create = function() {\n let { resize, watchCSS, rightToLeft } = this.options;\n // add id for Flickity.data\n let id = this.guid = ++GUID;\n this.element.flickityGUID = id; // expando\n instances[ id ] = this; // associate via id\n // initial properties\n this.selectedIndex = 0;\n // how many frames slider has been in same position\n this.restingFrames = 0;\n // initial physics properties\n this.x = 0;\n this.velocity = 0;\n this.beginMargin = rightToLeft ? 'marginRight' : 'marginLeft';\n this.endMargin = rightToLeft ? 'marginLeft' : 'marginRight';\n // create viewport & slider\n this.viewport = document.createElement('div');\n this.viewport.className = 'flickity-viewport';\n this._createSlider();\n // used for keyboard navigation\n this.focusableElems = [ this.element ];\n\n if ( resize || watchCSS ) {\n window.addEventListener( 'resize', this );\n }\n\n // add listeners from on option\n for ( let eventName in this.options.on ) {\n let listener = this.options.on[ eventName ];\n this.on( eventName, listener );\n }\n\n for ( let method in Flickity.create ) {\n Flickity.create[ method ].call( this );\n }\n\n if ( watchCSS ) {\n this.watchCSS();\n } else {\n this.activate();\n }\n};\n\n/**\n * set options\n * @param {Object} opts - options to extend\n */\nproto.option = function( opts ) {\n Object.assign( this.options, opts );\n};\n\nproto.activate = function() {\n if ( this.isActive ) return;\n\n this.isActive = true;\n this.element.classList.add('flickity-enabled');\n if ( this.options.rightToLeft ) {\n this.element.classList.add('flickity-rtl');\n }\n\n this.getSize();\n // move initial cell elements so they can be loaded as cells\n let cellElems = this._filterFindCellElements( this.element.children );\n this.slider.append( ...cellElems );\n this.viewport.append( this.slider );\n this.element.append( this.viewport );\n // get cells from children\n this.reloadCells();\n\n if ( this.options.accessibility ) {\n // allow element to focusable\n this.element.tabIndex = 0;\n // listen for key presses\n this.element.addEventListener( 'keydown', this );\n }\n\n this.emitEvent('activate');\n this.selectInitialIndex();\n // flag for initial activation, for using initialIndex\n this.isInitActivated = true;\n // ready event. #493\n this.dispatchEvent('ready');\n};\n\n// slider positions the cells\nproto._createSlider = function() {\n // slider element does all the positioning\n let slider = document.createElement('div');\n slider.className = 'flickity-slider';\n this.slider = slider;\n};\n\nproto._filterFindCellElements = function( elems ) {\n return utils.filterFindElements( elems, this.options.cellSelector );\n};\n\n// goes through all children\nproto.reloadCells = function() {\n // collection of item elements\n this.cells = this._makeCells( this.slider.children );\n this.positionCells();\n this._updateWrapShiftCells();\n this.setGallerySize();\n};\n\n/**\n * turn elements into Flickity.Cells\n * @param {[Array, NodeList, HTMLElement]} elems - elements to make into cells\n * @returns {Array} items - collection of new Flickity Cells\n */\nproto._makeCells = function( elems ) {\n let cellElems = this._filterFindCellElements( elems );\n\n // create new Cells for collection\n return cellElems.map( ( cellElem ) => new Cell( cellElem ) );\n};\n\nproto.getLastCell = function() {\n return this.cells[ this.cells.length - 1 ];\n};\n\nproto.getLastSlide = function() {\n return this.slides[ this.slides.length - 1 ];\n};\n\n// positions all cells\nproto.positionCells = function() {\n // size all cells\n this._sizeCells( this.cells );\n // position all cells\n this._positionCells( 0 );\n};\n\n/**\n * position certain cells\n * @param {Integer} index - which cell to start with\n */\nproto._positionCells = function( index ) {\n index = index || 0;\n // also measure maxCellHeight\n // start 0 if positioning all cells\n this.maxCellHeight = index ? this.maxCellHeight || 0 : 0;\n let cellX = 0;\n // get cellX\n if ( index > 0 ) {\n let startCell = this.cells[ index - 1 ];\n cellX = startCell.x + startCell.size.outerWidth;\n }\n\n this.cells.slice( index ).forEach( ( cell ) => {\n cell.x = cellX;\n this._renderCellPosition( cell, cellX );\n cellX += cell.size.outerWidth;\n this.maxCellHeight = Math.max( cell.size.outerHeight, this.maxCellHeight );\n } );\n // keep track of cellX for wrap-around\n this.slideableWidth = cellX;\n // slides\n this.updateSlides();\n // contain slides target\n this._containSlides();\n // update slidesWidth\n this.slidesWidth = this.cells.length ?\n this.getLastSlide().target - this.slides[0].target : 0;\n};\n\nproto._renderCellPosition = function( cell, x ) {\n // render position of cell with in slider\n let sideOffset = this.options.rightToLeft ? -1 : 1;\n let renderX = x * sideOffset;\n if ( this.options.percentPosition ) renderX *= this.size.innerWidth / cell.size.width;\n let positionValue = this.getPositionValue( renderX );\n cell.element.style.transform = `translateX( ${positionValue} )`;\n};\n\n/**\n * cell.getSize() on multiple cells\n * @param {Array} cells - cells to size\n */\nproto._sizeCells = function( cells ) {\n cells.forEach( ( cell ) => cell.getSize() );\n};\n\n// -------------------------- -------------------------- //\n\nproto.updateSlides = function() {\n this.slides = [];\n if ( !this.cells.length ) return;\n\n let { beginMargin, endMargin } = this;\n let slide = new Slide( beginMargin, endMargin, this.cellAlign );\n this.slides.push( slide );\n\n let canCellFit = this._getCanCellFit();\n\n this.cells.forEach( ( cell, i ) => {\n // just add cell if first cell in slide\n if ( !slide.cells.length ) {\n slide.addCell( cell );\n return;\n }\n\n let slideWidth = ( slide.outerWidth - slide.firstMargin ) +\n ( cell.size.outerWidth - cell.size[ endMargin ] );\n\n if ( canCellFit( i, slideWidth ) ) {\n slide.addCell( cell );\n } else {\n // doesn't fit, new slide\n slide.updateTarget();\n\n slide = new Slide( beginMargin, endMargin, this.cellAlign );\n this.slides.push( slide );\n slide.addCell( cell );\n }\n } );\n // last slide\n slide.updateTarget();\n // update .selectedSlide\n this.updateSelectedSlide();\n};\n\nproto._getCanCellFit = function() {\n let { groupCells } = this.options;\n if ( !groupCells ) return () => false;\n\n if ( typeof groupCells == 'number' ) {\n // group by number. 3 -> [0,1,2], [3,4,5], ...\n let number = parseInt( groupCells, 10 );\n return ( i ) => ( i % number ) !== 0;\n }\n // default, group by width of slide\n let percent = 1;\n // parse '75%\n let percentMatch = typeof groupCells == 'string' && groupCells.match( /^(\\d+)%$/ );\n if ( percentMatch ) percent = parseInt( percentMatch[1], 10 ) / 100;\n let groupWidth = ( this.size.innerWidth + 1 ) * percent;\n return ( i, slideWidth ) => slideWidth <= groupWidth;\n};\n\n// alias _init for jQuery plugin .flickity()\nproto._init =\nproto.reposition = function() {\n this.positionCells();\n this.positionSliderAtSelected();\n};\n\nproto.getSize = function() {\n this.size = getSize( this.element );\n this.setCellAlign();\n this.cursorPosition = this.size.innerWidth * this.cellAlign;\n};\n\nlet cellAlignShorthands = {\n left: 0,\n center: 0.5,\n right: 1,\n};\n\nproto.setCellAlign = function() {\n let { cellAlign, rightToLeft } = this.options;\n let shorthand = cellAlignShorthands[ cellAlign ];\n this.cellAlign = shorthand !== undefined ? shorthand : cellAlign;\n if ( rightToLeft ) this.cellAlign = 1 - this.cellAlign;\n};\n\nproto.setGallerySize = function() {\n if ( !this.options.setGallerySize ) return;\n\n let height = this.options.adaptiveHeight && this.selectedSlide ?\n this.selectedSlide.height : this.maxCellHeight;\n this.viewport.style.height = `${height}px`;\n};\n\nproto._updateWrapShiftCells = function() {\n // update isWrapping\n this.isWrapping = this.getIsWrapping();\n // only for wrap-around\n if ( !this.isWrapping ) return;\n\n // unshift previous cells\n this._unshiftCells( this.beforeShiftCells );\n this._unshiftCells( this.afterShiftCells );\n // get before cells\n // initial gap\n let beforeGapX = this.cursorPosition;\n let lastIndex = this.cells.length - 1;\n this.beforeShiftCells = this._getGapCells( beforeGapX, lastIndex, -1 );\n // get after cells\n // ending gap between last cell and end of gallery viewport\n let afterGapX = this.size.innerWidth - this.cursorPosition;\n // start cloning at first cell, working forwards\n this.afterShiftCells = this._getGapCells( afterGapX, 0, 1 );\n};\n\nproto.getIsWrapping = function() {\n let { wrapAround } = this.options;\n if ( !wrapAround || this.slides.length < 2 ) return false;\n\n if ( wrapAround !== 'fill' ) return true;\n // check that slides can fit\n\n let gapWidth = this.slideableWidth - this.size.innerWidth;\n if ( gapWidth > this.size.innerWidth ) return true; // gap * 2x big, all good\n // check that content width - shifting cell is bigger than viewport width\n for ( let cell of this.cells ) {\n if ( cell.size.outerWidth > gapWidth ) return false;\n }\n return true;\n};\n\nproto._getGapCells = function( gapX, cellIndex, increment ) {\n // keep adding cells until the cover the initial gap\n let cells = [];\n while ( gapX > 0 ) {\n let cell = this.cells[ cellIndex ];\n if ( !cell ) break;\n\n cells.push( cell );\n cellIndex += increment;\n gapX -= cell.size.outerWidth;\n }\n return cells;\n};\n\n// ----- contain & wrap ----- //\n\n// contain cell targets so no excess sliding\nproto._containSlides = function() {\n let isContaining = this.options.contain && !this.isWrapping &&\n this.cells.length;\n if ( !isContaining ) return;\n\n let contentWidth = this.slideableWidth - this.getLastCell().size[ this.endMargin ];\n // content is less than gallery size\n let isContentSmaller = contentWidth < this.size.innerWidth;\n if ( isContentSmaller ) {\n // all cells fit inside gallery\n this.slides.forEach( ( slide ) => {\n slide.target = contentWidth * this.cellAlign;\n } );\n } else {\n // contain to bounds\n let beginBound = this.cursorPosition + this.cells[0].size[ this.beginMargin ];\n let endBound = contentWidth - this.size.innerWidth * ( 1 - this.cellAlign );\n this.slides.forEach( ( slide ) => {\n slide.target = Math.max( slide.target, beginBound );\n slide.target = Math.min( slide.target, endBound );\n } );\n }\n};\n\n// ----- events ----- //\n\n/**\n * emits events via eventEmitter and jQuery events\n * @param {String} type - name of event\n * @param {Event} event - original event\n * @param {Array} args - extra arguments\n */\nproto.dispatchEvent = function( type, event, args ) {\n let emitArgs = event ? [ event ].concat( args ) : args;\n this.emitEvent( type, emitArgs );\n\n if ( jQuery && this.$element ) {\n // default trigger with type if no event\n type += this.options.namespaceJQueryEvents ? '.flickity' : '';\n let $event = type;\n if ( event ) {\n // create jQuery event\n let jQEvent = new jQuery.Event( event );\n jQEvent.type = type;\n $event = jQEvent;\n }\n this.$element.trigger( $event, args );\n }\n};\n\nconst unidraggerEvents = [\n 'dragStart',\n 'dragMove',\n 'dragEnd',\n 'pointerDown',\n 'pointerMove',\n 'pointerEnd',\n 'staticClick',\n];\n\nlet _emitEvent = proto.emitEvent;\nproto.emitEvent = function( eventName, args ) {\n if ( eventName === 'staticClick' ) {\n // add cellElem and cellIndex args to staticClick\n let clickedCell = this.getParentCell( args[0].target );\n let cellElem = clickedCell && clickedCell.element;\n let cellIndex = clickedCell && this.cells.indexOf( clickedCell );\n args = args.concat( cellElem, cellIndex );\n }\n // do regular thing\n _emitEvent.call( this, eventName, args );\n // duck-punch in jQuery events for Unidragger events\n let isUnidraggerEvent = unidraggerEvents.includes( eventName );\n if ( !isUnidraggerEvent || !jQuery || !this.$element ) return;\n\n eventName += this.options.namespaceJQueryEvents ? '.flickity' : '';\n let event = args.shift( 0 );\n let jQEvent = new jQuery.Event( event );\n jQEvent.type = eventName;\n this.$element.trigger( jQEvent, args );\n};\n\n// -------------------------- select -------------------------- //\n\n/**\n * @param {Integer} index - index of the slide\n * @param {Boolean} isWrap - will wrap-around to last/first if at the end\n * @param {Boolean} isInstant - will immediately set position at selected cell\n */\nproto.select = function( index, isWrap, isInstant ) {\n if ( !this.isActive ) return;\n\n index = parseInt( index, 10 );\n this._wrapSelect( index );\n\n if ( this.isWrapping || isWrap ) {\n index = utils.modulo( index, this.slides.length );\n }\n // bail if invalid index\n if ( !this.slides[ index ] ) return;\n\n let prevIndex = this.selectedIndex;\n this.selectedIndex = index;\n this.updateSelectedSlide();\n if ( isInstant ) {\n this.positionSliderAtSelected();\n } else {\n this.startAnimation();\n }\n if ( this.options.adaptiveHeight ) {\n this.setGallerySize();\n }\n // events\n this.dispatchEvent( 'select', null, [ index ] );\n // change event if new index\n if ( index !== prevIndex ) {\n this.dispatchEvent( 'change', null, [ index ] );\n }\n};\n\n// wraps position for wrapAround, to move to closest slide. #113\nproto._wrapSelect = function( index ) {\n if ( !this.isWrapping ) return;\n\n const { selectedIndex, slideableWidth, slides: { length } } = this;\n // shift index for wrap, do not wrap dragSelect\n if ( !this.isDragSelect ) {\n let wrapIndex = utils.modulo( index, length );\n // go to shortest\n let delta = Math.abs( wrapIndex - selectedIndex );\n let backWrapDelta = Math.abs( ( wrapIndex + length ) - selectedIndex );\n let forewardWrapDelta = Math.abs( ( wrapIndex - length ) - selectedIndex );\n if ( backWrapDelta < delta ) {\n index += length;\n } else if ( forewardWrapDelta < delta ) {\n index -= length;\n }\n }\n\n // wrap position so slider is within normal area\n if ( index < 0 ) {\n this.x -= slideableWidth;\n } else if ( index >= length ) {\n this.x += slideableWidth;\n }\n};\n\nproto.previous = function( isWrap, isInstant ) {\n this.select( this.selectedIndex - 1, isWrap, isInstant );\n};\n\nproto.next = function( isWrap, isInstant ) {\n this.select( this.selectedIndex + 1, isWrap, isInstant );\n};\n\nproto.updateSelectedSlide = function() {\n let slide = this.slides[ this.selectedIndex ];\n // selectedIndex could be outside of slides, if triggered before resize()\n if ( !slide ) return;\n\n // unselect previous selected slide\n this.unselectSelectedSlide();\n // update new selected slide\n this.selectedSlide = slide;\n slide.select();\n this.selectedCells = slide.cells;\n this.selectedElements = slide.getCellElements();\n // HACK: selectedCell & selectedElement is first cell in slide, backwards compatibility\n this.selectedCell = slide.cells[0];\n this.selectedElement = this.selectedElements[0];\n};\n\nproto.unselectSelectedSlide = function() {\n if ( this.selectedSlide ) this.selectedSlide.unselect();\n};\n\nproto.selectInitialIndex = function() {\n let initialIndex = this.options.initialIndex;\n // already activated, select previous selectedIndex\n if ( this.isInitActivated ) {\n this.select( this.selectedIndex, false, true );\n return;\n }\n // select with selector string\n if ( initialIndex && typeof initialIndex == 'string' ) {\n let cell = this.queryCell( initialIndex );\n if ( cell ) {\n this.selectCell( initialIndex, false, true );\n return;\n }\n }\n\n let index = 0;\n // select with number\n if ( initialIndex && this.slides[ initialIndex ] ) {\n index = initialIndex;\n }\n // select instantly\n this.select( index, false, true );\n};\n\n/**\n * select slide from number or cell element\n * @param {[Element, Number]} value - zero-based index or element to select\n * @param {Boolean} isWrap - enables wrapping around for extra index\n * @param {Boolean} isInstant - disables slide animation\n */\nproto.selectCell = function( value, isWrap, isInstant ) {\n // get cell\n let cell = this.queryCell( value );\n if ( !cell ) return;\n\n let index = this.getCellSlideIndex( cell );\n this.select( index, isWrap, isInstant );\n};\n\nproto.getCellSlideIndex = function( cell ) {\n // get index of slide that has cell\n let cellSlide = this.slides.find( ( slide ) => slide.cells.includes( cell ) );\n return this.slides.indexOf( cellSlide );\n};\n\n// -------------------------- get cells -------------------------- //\n\n/**\n * get Flickity.Cell, given an Element\n * @param {Element} elem - matching cell element\n * @returns {Flickity.Cell} cell - matching cell\n */\nproto.getCell = function( elem ) {\n // loop through cells to get the one that matches\n for ( let cell of this.cells ) {\n if ( cell.element === elem ) return cell;\n }\n};\n\n/**\n * get collection of Flickity.Cells, given Elements\n * @param {[Element, Array, NodeList]} elems - multiple elements\n * @returns {Array} cells - Flickity.Cells\n */\nproto.getCells = function( elems ) {\n elems = utils.makeArray( elems );\n return elems.map( ( elem ) => this.getCell( elem ) ).filter( Boolean );\n};\n\n/**\n * get cell elements\n * @returns {Array} cellElems\n */\nproto.getCellElements = function() {\n return this.cells.map( ( cell ) => cell.element );\n};\n\n/**\n * get parent cell from an element\n * @param {Element} elem - child element\n * @returns {Flickit.Cell} cell - parent cell\n */\nproto.getParentCell = function( elem ) {\n // first check if elem is cell\n let cell = this.getCell( elem );\n if ( cell ) return cell;\n\n // try to get parent cell elem\n let closest = elem.closest('.flickity-slider > *');\n return this.getCell( closest );\n};\n\n/**\n * get cells adjacent to a slide\n * @param {Integer} adjCount - number of adjacent slides\n * @param {Integer} index - index of slide to start\n * @returns {Array} cells - array of Flickity.Cells\n */\nproto.getAdjacentCellElements = function( adjCount, index ) {\n if ( !adjCount ) return this.selectedSlide.getCellElements();\n\n index = index === undefined ? this.selectedIndex : index;\n\n let len = this.slides.length;\n if ( 1 + ( adjCount * 2 ) >= len ) {\n return this.getCellElements(); // get all\n }\n\n let cellElems = [];\n for ( let i = index - adjCount; i <= index + adjCount; i++ ) {\n let slideIndex = this.isWrapping ? utils.modulo( i, len ) : i;\n let slide = this.slides[ slideIndex ];\n if ( slide ) {\n cellElems = cellElems.concat( slide.getCellElements() );\n }\n }\n return cellElems;\n};\n\n/**\n * select slide from number or cell element\n * @param {[Element, String, Number]} selector - element, selector string, or index\n * @returns {Flickity.Cell} - matching cell\n */\nproto.queryCell = function( selector ) {\n if ( typeof selector == 'number' ) {\n // use number as index\n return this.cells[ selector ];\n }\n // do not select invalid selectors from hash: #123, #/. #791\n let isSelectorString = typeof selector == 'string' && !selector.match( /^[#.]?[\\d/]/ );\n if ( isSelectorString ) {\n // use string as selector, get element\n selector = this.element.querySelector( selector );\n }\n // get cell from element\n return this.getCell( selector );\n};\n\n// -------------------------- events -------------------------- //\n\nproto.uiChange = function() {\n this.emitEvent('uiChange');\n};\n\n// ----- resize ----- //\n\nproto.onresize = function() {\n this.watchCSS();\n this.resize();\n};\n\nutils.debounceMethod( Flickity, 'onresize', 150 );\n\nproto.resize = function() {\n // #1177 disable resize behavior when animating or dragging for iOS 15\n if ( !this.isActive || this.isAnimating || this.isDragging ) return;\n this.getSize();\n // wrap values\n if ( this.isWrapping ) {\n this.x = utils.modulo( this.x, this.slideableWidth );\n }\n this.positionCells();\n this._updateWrapShiftCells();\n this.setGallerySize();\n this.emitEvent('resize');\n // update selected index for group slides, instant\n // TODO: position can be lost between groups of various numbers\n let selectedElement = this.selectedElements && this.selectedElements[0];\n this.selectCell( selectedElement, false, true );\n};\n\n// watches the :after property, activates/deactivates\nproto.watchCSS = function() {\n if ( !this.options.watchCSS ) return;\n\n let afterContent = getComputedStyle( this.element, ':after' ).content;\n // activate if :after { content: 'flickity' }\n if ( afterContent.includes('flickity') ) {\n this.activate();\n } else {\n this.deactivate();\n }\n};\n\n// ----- keydown ----- //\n\n// go previous/next if left/right keys pressed\nproto.onkeydown = function( event ) {\n let { activeElement } = document;\n let handler = Flickity.keyboardHandlers[ event.key ];\n // only work if element is in focus\n if ( !this.options.accessibility || !activeElement || !handler ) return;\n\n let isFocused = this.focusableElems.some( ( elem ) => activeElement === elem );\n if ( isFocused ) handler.call( this );\n};\n\nFlickity.keyboardHandlers = {\n ArrowLeft: function() {\n this.uiChange();\n let leftMethod = this.options.rightToLeft ? 'next' : 'previous';\n this[ leftMethod ]();\n },\n ArrowRight: function() {\n this.uiChange();\n let rightMethod = this.options.rightToLeft ? 'previous' : 'next';\n this[ rightMethod ]();\n },\n};\n\n// ----- focus ----- //\n\nproto.focus = function() {\n this.element.focus({ preventScroll: true });\n};\n\n// -------------------------- destroy -------------------------- //\n\n// deactivate all Flickity functionality, but keep stuff available\nproto.deactivate = function() {\n if ( !this.isActive ) return;\n\n this.element.classList.remove('flickity-enabled');\n this.element.classList.remove('flickity-rtl');\n this.unselectSelectedSlide();\n // destroy cells\n this.cells.forEach( ( cell ) => cell.destroy() );\n this.viewport.remove();\n // move child elements back into element\n this.element.append( ...this.slider.children );\n if ( this.options.accessibility ) {\n this.element.removeAttribute('tabIndex');\n this.element.removeEventListener( 'keydown', this );\n }\n // set flags\n this.isActive = false;\n this.emitEvent('deactivate');\n};\n\nproto.destroy = function() {\n this.deactivate();\n window.removeEventListener( 'resize', this );\n this.allOff();\n this.emitEvent('destroy');\n if ( jQuery && this.$element ) {\n jQuery.removeData( this.element, 'flickity' );\n }\n delete this.element.flickityGUID;\n delete instances[ this.guid ];\n};\n\n// -------------------------- prototype -------------------------- //\n\nObject.assign( proto, animatePrototype );\n\n// -------------------------- extras -------------------------- //\n\n/**\n * get Flickity instance from element\n * @param {[Element, String]} elem - element or selector string\n * @returns {Flickity} - Flickity instance\n */\nFlickity.data = function( elem ) {\n elem = utils.getQueryElement( elem );\n if ( elem ) return instances[ elem.flickityGUID ];\n};\n\nutils.htmlInit( Flickity, 'flickity' );\n\nlet { jQueryBridget } = window;\nif ( jQuery && jQueryBridget ) {\n jQueryBridget( 'flickity', Flickity, jQuery );\n}\n\n// set internal jQuery, for Webpack + jQuery v3, #478\nFlickity.setJQuery = function( jq ) {\n jQuery = jq;\n};\n\nFlickity.Cell = Cell;\nFlickity.Slide = Slide;\n\nreturn Flickity;\n\n} ) );\n","// drag\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n window,\n require('./core'),\n require('unidragger'),\n require('fizzy-ui-utils'),\n );\n } else {\n // browser global\n window.Flickity = factory(\n window,\n window.Flickity,\n window.Unidragger,\n window.fizzyUIUtils,\n );\n }\n\n}( typeof window != 'undefined' ? window : this,\n function factory( window, Flickity, Unidragger, utils ) {\n\n// ----- defaults ----- //\n\nObject.assign( Flickity.defaults, {\n draggable: '>1',\n dragThreshold: 3,\n} );\n\n// -------------------------- drag prototype -------------------------- //\n\nlet proto = Flickity.prototype;\nObject.assign( proto, Unidragger.prototype ); // inherit Unidragger\nproto.touchActionValue = '';\n\n// -------------------------- -------------------------- //\n\nFlickity.create.drag = function() {\n this.on( 'activate', this.onActivateDrag );\n this.on( 'uiChange', this._uiChangeDrag );\n this.on( 'deactivate', this.onDeactivateDrag );\n this.on( 'cellChange', this.updateDraggable );\n this.on( 'pointerDown', this.handlePointerDown );\n this.on( 'pointerUp', this.handlePointerUp );\n this.on( 'pointerDown', this.handlePointerDone );\n this.on( 'dragStart', this.handleDragStart );\n this.on( 'dragMove', this.handleDragMove );\n this.on( 'dragEnd', this.handleDragEnd );\n this.on( 'staticClick', this.handleStaticClick );\n // TODO updateDraggable on resize? if groupCells & slides change\n};\n\nproto.onActivateDrag = function() {\n this.handles = [ this.viewport ];\n this.bindHandles();\n this.updateDraggable();\n};\n\nproto.onDeactivateDrag = function() {\n this.unbindHandles();\n this.element.classList.remove('is-draggable');\n};\n\nproto.updateDraggable = function() {\n // disable dragging if less than 2 slides. #278\n if ( this.options.draggable === '>1' ) {\n this.isDraggable = this.slides.length > 1;\n } else {\n this.isDraggable = this.options.draggable;\n }\n this.element.classList.toggle( 'is-draggable', this.isDraggable );\n};\n\nproto._uiChangeDrag = function() {\n delete this.isFreeScrolling;\n};\n\n// -------------------------- pointer events -------------------------- //\n\nproto.handlePointerDown = function( event ) {\n if ( !this.isDraggable ) {\n // proceed for staticClick\n this.bindActivePointerEvents( event );\n return;\n }\n\n let isTouchStart = event.type === 'touchstart';\n let isTouchPointer = event.pointerType === 'touch';\n let isFocusNode = event.target.matches('input, textarea, select');\n if ( !isTouchStart && !isTouchPointer && !isFocusNode ) event.preventDefault();\n if ( !isFocusNode ) this.focus();\n // blur\n if ( document.activeElement !== this.element ) document.activeElement.blur();\n // stop if it was moving\n this.dragX = this.x;\n this.viewport.classList.add('is-pointer-down');\n // track scrolling\n this.pointerDownScroll = getScrollPosition();\n window.addEventListener( 'scroll', this );\n this.bindActivePointerEvents( event );\n};\n\n// ----- move ----- //\n\nproto.hasDragStarted = function( moveVector ) {\n return Math.abs( moveVector.x ) > this.options.dragThreshold;\n};\n\n// ----- up ----- //\n\nproto.handlePointerUp = function() {\n delete this.isTouchScrolling;\n this.viewport.classList.remove('is-pointer-down');\n};\n\nproto.handlePointerDone = function() {\n window.removeEventListener( 'scroll', this );\n delete this.pointerDownScroll;\n};\n\n// -------------------------- dragging -------------------------- //\n\nproto.handleDragStart = function() {\n if ( !this.isDraggable ) return;\n\n this.dragStartPosition = this.x;\n this.startAnimation();\n window.removeEventListener( 'scroll', this );\n};\n\nproto.handleDragMove = function( event, pointer, moveVector ) {\n if ( !this.isDraggable ) return;\n\n event.preventDefault();\n\n this.previousDragX = this.dragX;\n // reverse if right-to-left\n let direction = this.options.rightToLeft ? -1 : 1;\n // wrap around move. #589\n if ( this.isWrapping ) moveVector.x %= this.slideableWidth;\n let dragX = this.dragStartPosition + moveVector.x * direction;\n\n if ( !this.isWrapping ) {\n // slow drag\n let originBound = Math.max( -this.slides[0].target, this.dragStartPosition );\n dragX = dragX > originBound ? ( dragX + originBound ) * 0.5 : dragX;\n let endBound = Math.min( -this.getLastSlide().target, this.dragStartPosition );\n dragX = dragX < endBound ? ( dragX + endBound ) * 0.5 : dragX;\n }\n\n this.dragX = dragX;\n this.dragMoveTime = new Date();\n};\n\nproto.handleDragEnd = function() {\n if ( !this.isDraggable ) return;\n\n let { freeScroll } = this.options;\n if ( freeScroll ) this.isFreeScrolling = true;\n // set selectedIndex based on where flick will end up\n let index = this.dragEndRestingSelect();\n\n if ( freeScroll && !this.isWrapping ) {\n // if free-scroll & not wrap around\n // do not free-scroll if going outside of bounding slides\n // so bounding slides can attract slider, and keep it in bounds\n let restingX = this.getRestingPosition();\n this.isFreeScrolling = -restingX > this.slides[0].target &&\n -restingX < this.getLastSlide().target;\n } else if ( !freeScroll && index === this.selectedIndex ) {\n // boost selection if selected index has not changed\n index += this.dragEndBoostSelect();\n }\n delete this.previousDragX;\n // apply selection\n // HACK, set flag so dragging stays in correct direction\n this.isDragSelect = this.isWrapping;\n this.select( index );\n delete this.isDragSelect;\n};\n\nproto.dragEndRestingSelect = function() {\n let restingX = this.getRestingPosition();\n // how far away from selected slide\n let distance = Math.abs( this.getSlideDistance( -restingX, this.selectedIndex ) );\n // get closet resting going up and going down\n let positiveResting = this._getClosestResting( restingX, distance, 1 );\n let negativeResting = this._getClosestResting( restingX, distance, -1 );\n // use closer resting for wrap-around\n return positiveResting.distance < negativeResting.distance ?\n positiveResting.index : negativeResting.index;\n};\n\n/**\n * given resting X and distance to selected cell\n * get the distance and index of the closest cell\n * @param {Number} restingX - estimated post-flick resting position\n * @param {Number} distance - distance to selected cell\n * @param {Integer} increment - +1 or -1, going up or down\n * @returns {Object} - { distance: {Number}, index: {Integer} }\n */\nproto._getClosestResting = function( restingX, distance, increment ) {\n let index = this.selectedIndex;\n let minDistance = Infinity;\n let condition = this.options.contain && !this.isWrapping ?\n // if containing, keep going if distance is equal to minDistance\n ( dist, minDist ) => dist <= minDist :\n ( dist, minDist ) => dist < minDist;\n\n while ( condition( distance, minDistance ) ) {\n // measure distance to next cell\n index += increment;\n minDistance = distance;\n distance = this.getSlideDistance( -restingX, index );\n if ( distance === null ) break;\n\n distance = Math.abs( distance );\n }\n return {\n distance: minDistance,\n // selected was previous index\n index: index - increment,\n };\n};\n\n/**\n * measure distance between x and a slide target\n * @param {Number} x - horizontal position\n * @param {Integer} index - slide index\n * @returns {Number} - slide distance\n */\nproto.getSlideDistance = function( x, index ) {\n let len = this.slides.length;\n // wrap around if at least 2 slides\n let isWrapAround = this.options.wrapAround && len > 1;\n let slideIndex = isWrapAround ? utils.modulo( index, len ) : index;\n let slide = this.slides[ slideIndex ];\n if ( !slide ) return null;\n\n // add distance for wrap-around slides\n let wrap = isWrapAround ? this.slideableWidth * Math.floor( index/len ) : 0;\n return x - ( slide.target + wrap );\n};\n\nproto.dragEndBoostSelect = function() {\n // do not boost if no previousDragX or dragMoveTime\n if ( this.previousDragX === undefined || !this.dragMoveTime ||\n // or if drag was held for 100 ms\n new Date() - this.dragMoveTime > 100 ) {\n return 0;\n }\n\n let distance = this.getSlideDistance( -this.dragX, this.selectedIndex );\n let delta = this.previousDragX - this.dragX;\n if ( distance > 0 && delta > 0 ) {\n // boost to next if moving towards the right, and positive velocity\n return 1;\n } else if ( distance < 0 && delta < 0 ) {\n // boost to previous if moving towards the left, and negative velocity\n return -1;\n }\n return 0;\n};\n\n// ----- scroll ----- //\n\nproto.onscroll = function() {\n let scroll = getScrollPosition();\n let scrollMoveX = this.pointerDownScroll.x - scroll.x;\n let scrollMoveY = this.pointerDownScroll.y - scroll.y;\n // cancel click/tap if scroll is too much\n if ( Math.abs( scrollMoveX ) > 3 || Math.abs( scrollMoveY ) > 3 ) {\n this.pointerDone();\n }\n};\n\n// ----- utils ----- //\n\nfunction getScrollPosition() {\n return {\n x: window.pageXOffset,\n y: window.pageYOffset,\n };\n}\n\n// ----- ----- //\n\nreturn Flickity;\n\n} ) );\n","// imagesloaded\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('./core'),\n require('imagesloaded'),\n );\n } else {\n // browser global\n factory(\n window.Flickity,\n window.imagesLoaded,\n );\n }\n\n}( typeof window != 'undefined' ? window : this,\n function factory( Flickity, imagesLoaded ) {\n\nFlickity.create.imagesLoaded = function() {\n this.on( 'activate', this.imagesLoaded );\n};\n\nFlickity.prototype.imagesLoaded = function() {\n if ( !this.options.imagesLoaded ) return;\n\n let onImagesLoadedProgress = ( instance, image ) => {\n let cell = this.getParentCell( image.img );\n this.cellSizeChange( cell && cell.element );\n if ( !this.options.freeScroll ) this.positionSliderAtSelected();\n };\n imagesLoaded( this.slider ).on( 'progress', onImagesLoadedProgress );\n};\n\nreturn Flickity;\n\n} ) );\n","/*!\n * Flickity v3.0.0\n * Touch, responsive, flickable carousels\n *\n * Licensed GPLv3 for open source use\n * or Flickity Commercial License for commercial use\n *\n * https://flickity.metafizzy.co\n * Copyright 2015-2022 Metafizzy\n */\n\nif ( typeof module == 'object' && module.exports ) {\n const Flickity = require('./core');\n require('./drag');\n require('./prev-next-button');\n require('./page-dots');\n require('./player');\n require('./add-remove-cell');\n require('./lazyload');\n require('./imagesloaded');\n\n module.exports = Flickity;\n}\n","// lazyload\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('./core'),\n require('fizzy-ui-utils'),\n );\n } else {\n // browser global\n factory(\n window.Flickity,\n window.fizzyUIUtils,\n );\n }\n\n}( typeof window != 'undefined' ? window : this, function factory( Flickity, utils ) {\n\nconst lazyAttr = 'data-flickity-lazyload';\nconst lazySrcAttr = `${lazyAttr}-src`;\nconst lazySrcsetAttr = `${lazyAttr}-srcset`;\nconst imgSelector = `img[${lazyAttr}], img[${lazySrcAttr}], ` +\n `img[${lazySrcsetAttr}], source[${lazySrcsetAttr}]`;\n\nFlickity.create.lazyLoad = function() {\n this.on( 'select', this.lazyLoad );\n\n this.handleLazyLoadComplete = this.onLazyLoadComplete.bind( this );\n};\n\nlet proto = Flickity.prototype;\n\nproto.lazyLoad = function() {\n let { lazyLoad } = this.options;\n if ( !lazyLoad ) return;\n\n // get adjacent cells, use lazyLoad option for adjacent count\n let adjCount = typeof lazyLoad == 'number' ? lazyLoad : 0;\n // lazy load images\n this.getAdjacentCellElements( adjCount )\n .map( getCellLazyImages )\n .flat()\n .forEach( ( img ) => new LazyLoader( img, this.handleLazyLoadComplete ) );\n};\n\nfunction getCellLazyImages( cellElem ) {\n // check if cell element is lazy image\n if ( cellElem.matches('img') ) {\n let cellAttr = cellElem.getAttribute( lazyAttr );\n let cellSrcAttr = cellElem.getAttribute( lazySrcAttr );\n let cellSrcsetAttr = cellElem.getAttribute( lazySrcsetAttr );\n if ( cellAttr || cellSrcAttr || cellSrcsetAttr ) {\n return cellElem;\n }\n }\n // select lazy images in cell\n return [ ...cellElem.querySelectorAll( imgSelector ) ];\n}\n\nproto.onLazyLoadComplete = function( img, event ) {\n let cell = this.getParentCell( img );\n let cellElem = cell && cell.element;\n this.cellSizeChange( cellElem );\n\n this.dispatchEvent( 'lazyLoad', event, cellElem );\n};\n\n// -------------------------- LazyLoader -------------------------- //\n\n/**\n * class to handle loading images\n * @param {Image} img - Image element\n * @param {Function} onComplete - callback function\n */\nfunction LazyLoader( img, onComplete ) {\n this.img = img;\n this.onComplete = onComplete;\n this.load();\n}\n\nLazyLoader.prototype.handleEvent = utils.handleEvent;\n\nLazyLoader.prototype.load = function() {\n this.img.addEventListener( 'load', this );\n this.img.addEventListener( 'error', this );\n // get src & srcset\n let src = this.img.getAttribute( lazyAttr ) ||\n this.img.getAttribute( lazySrcAttr );\n let srcset = this.img.getAttribute( lazySrcsetAttr );\n // set src & serset\n this.img.src = src;\n if ( srcset ) this.img.setAttribute( 'srcset', srcset );\n // remove attr\n this.img.removeAttribute( lazyAttr );\n this.img.removeAttribute( lazySrcAttr );\n this.img.removeAttribute( lazySrcsetAttr );\n};\n\nLazyLoader.prototype.onload = function( event ) {\n this.complete( event, 'flickity-lazyloaded' );\n};\n\nLazyLoader.prototype.onerror = function( event ) {\n this.complete( event, 'flickity-lazyerror' );\n};\n\nLazyLoader.prototype.complete = function( event, className ) {\n // unbind events\n this.img.removeEventListener( 'load', this );\n this.img.removeEventListener( 'error', this );\n let mediaElem = this.img.parentNode.matches('picture') ? this.img.parentNode : this.img;\n mediaElem.classList.add( className );\n\n this.onComplete( this.img, event );\n};\n\n// ----- ----- //\n\nFlickity.LazyLoader = LazyLoader;\n\nreturn Flickity;\n\n} ) );\n","// page dots\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory(\n require('./core'),\n require('fizzy-ui-utils'),\n );\n } else {\n // browser global\n factory(\n window.Flickity,\n window.fizzyUIUtils,\n );\n }\n\n}( typeof window != 'undefined' ? window : this, function factory( Flickity, utils ) {\n\n// -------------------------- PageDots -------------------------- //\n\nfunction PageDots() {\n // create holder element\n this.holder = document.createElement('div');\n this.holder.className = 'flickity-page-dots';\n // create dots, array of elements\n this.dots = [];\n}\n\nPageDots.prototype.setDots = function( slidesLength ) {\n // get difference between number of slides and number of dots\n let delta = slidesLength - this.dots.length;\n if ( delta > 0 ) {\n this.addDots( delta );\n } else if ( delta < 0 ) {\n this.removeDots( -delta );\n }\n};\n\nPageDots.prototype.addDots = function( count ) {\n let newDots = new Array( count ).fill()\n .map( ( item, i ) => {\n let dot = document.createElement('button');\n dot.setAttribute( 'type', 'button' );\n let num = i + 1 + this.dots.length;\n dot.className = 'flickity-page-dot';\n dot.textContent = `View slide ${num}`;\n return dot;\n } );\n\n this.holder.append( ...newDots );\n this.dots = this.dots.concat( newDots );\n};\n\nPageDots.prototype.removeDots = function( count ) {\n // remove from this.dots collection\n let removeDots = this.dots.splice( this.dots.length - count, count );\n // remove from DOM\n removeDots.forEach( ( dot ) => dot.remove() );\n};\n\nPageDots.prototype.updateSelected = function( index ) {\n // remove selected class on previous\n if ( this.selectedDot ) {\n this.selectedDot.classList.remove('is-selected');\n this.selectedDot.removeAttribute('aria-current');\n }\n // don't proceed if no dots\n if ( !this.dots.length ) return;\n\n this.selectedDot = this.dots[ index ];\n this.selectedDot.classList.add('is-selected');\n this.selectedDot.setAttribute( 'aria-current', 'step' );\n};\n\nFlickity.PageDots = PageDots;\n\n// -------------------------- Flickity -------------------------- //\n\nObject.assign( Flickity.defaults, {\n pageDots: true,\n} );\n\nFlickity.create.pageDots = function() {\n if ( !this.options.pageDots ) return;\n\n this.pageDots = new PageDots();\n this.handlePageDotsClick = this.onPageDotsClick.bind( this );\n // events\n this.on( 'activate', this.activatePageDots );\n this.on( 'select', this.updateSelectedPageDots );\n this.on( 'cellChange', this.updatePageDots );\n this.on( 'resize', this.updatePageDots );\n this.on( 'deactivate', this.deactivatePageDots );\n};\n\nlet proto = Flickity.prototype;\n\nproto.activatePageDots = function() {\n this.pageDots.setDots( this.slides.length );\n this.focusableElems.push( ...this.pageDots.dots );\n this.pageDots.holder.addEventListener( 'click', this.handlePageDotsClick );\n this.element.append( this.pageDots.holder );\n};\n\nproto.onPageDotsClick = function( event ) {\n let index = this.pageDots.dots.indexOf( event.target );\n if ( index === -1 ) return; // only dot clicks\n\n this.uiChange();\n this.select( index );\n};\n\nproto.updateSelectedPageDots = function() {\n this.pageDots.updateSelected( this.selectedIndex );\n};\n\nproto.updatePageDots = function() {\n this.pageDots.dots.forEach( ( dot ) => {\n utils.removeFrom( this.focusableElems, dot );\n } );\n this.pageDots.setDots( this.slides.length );\n this.focusableElems.push( ...this.pageDots.dots );\n};\n\nproto.deactivatePageDots = function() {\n this.pageDots.holder.remove();\n this.pageDots.holder.removeEventListener( 'click', this.handlePageDotsClick );\n};\n\n// ----- ----- //\n\nFlickity.PageDots = PageDots;\n\nreturn Flickity;\n\n} ) );\n","// player & autoPlay\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory( require('./core') );\n } else {\n // browser global\n factory( window.Flickity );\n }\n\n}( typeof window != 'undefined' ? window : this, function factory( Flickity ) {\n\n// -------------------------- Player -------------------------- //\n\nfunction Player( autoPlay, onTick ) {\n this.autoPlay = autoPlay;\n this.onTick = onTick;\n this.state = 'stopped';\n // visibility change event handler\n this.onVisibilityChange = this.visibilityChange.bind( this );\n this.onVisibilityPlay = this.visibilityPlay.bind( this );\n}\n\n// start play\nPlayer.prototype.play = function() {\n if ( this.state === 'playing' ) return;\n\n // do not play if page is hidden, start playing when page is visible\n let isPageHidden = document.hidden;\n if ( isPageHidden ) {\n document.addEventListener( 'visibilitychange', this.onVisibilityPlay );\n return;\n }\n\n this.state = 'playing';\n // listen to visibility change\n document.addEventListener( 'visibilitychange', this.onVisibilityChange );\n // start ticking\n this.tick();\n};\n\nPlayer.prototype.tick = function() {\n // do not tick if not playing\n if ( this.state !== 'playing' ) return;\n\n // default to 3 seconds\n let time = typeof this.autoPlay == 'number' ? this.autoPlay : 3000;\n // HACK: reset ticks if stopped and started within interval\n this.clear();\n this.timeout = setTimeout( () => {\n this.onTick();\n this.tick();\n }, time );\n};\n\nPlayer.prototype.stop = function() {\n this.state = 'stopped';\n this.clear();\n // remove visibility change event\n document.removeEventListener( 'visibilitychange', this.onVisibilityChange );\n};\n\nPlayer.prototype.clear = function() {\n clearTimeout( this.timeout );\n};\n\nPlayer.prototype.pause = function() {\n if ( this.state === 'playing' ) {\n this.state = 'paused';\n this.clear();\n }\n};\n\nPlayer.prototype.unpause = function() {\n // re-start play if paused\n if ( this.state === 'paused' ) this.play();\n};\n\n// pause if page visibility is hidden, unpause if visible\nPlayer.prototype.visibilityChange = function() {\n let isPageHidden = document.hidden;\n this[ isPageHidden ? 'pause' : 'unpause' ]();\n};\n\nPlayer.prototype.visibilityPlay = function() {\n this.play();\n document.removeEventListener( 'visibilitychange', this.onVisibilityPlay );\n};\n\n// -------------------------- Flickity -------------------------- //\n\nObject.assign( Flickity.defaults, {\n pauseAutoPlayOnHover: true,\n} );\n\nFlickity.create.player = function() {\n this.player = new Player( this.options.autoPlay, () => {\n this.next( true );\n } );\n\n this.on( 'activate', this.activatePlayer );\n this.on( 'uiChange', this.stopPlayer );\n this.on( 'pointerDown', this.stopPlayer );\n this.on( 'deactivate', this.deactivatePlayer );\n};\n\nlet proto = Flickity.prototype;\n\nproto.activatePlayer = function() {\n if ( !this.options.autoPlay ) return;\n\n this.player.play();\n this.element.addEventListener( 'mouseenter', this );\n};\n\n// Player API, don't hate the ... thanks I know where the door is\n\nproto.playPlayer = function() {\n this.player.play();\n};\n\nproto.stopPlayer = function() {\n this.player.stop();\n};\n\nproto.pausePlayer = function() {\n this.player.pause();\n};\n\nproto.unpausePlayer = function() {\n this.player.unpause();\n};\n\nproto.deactivatePlayer = function() {\n this.player.stop();\n this.element.removeEventListener( 'mouseenter', this );\n};\n\n// ----- mouseenter/leave ----- //\n\n// pause auto-play on hover\nproto.onmouseenter = function() {\n if ( !this.options.pauseAutoPlayOnHover ) return;\n\n this.player.pause();\n this.element.addEventListener( 'mouseleave', this );\n};\n\n// resume auto-play on hover off\nproto.onmouseleave = function() {\n this.player.unpause();\n this.element.removeEventListener( 'mouseleave', this );\n};\n\n// ----- ----- //\n\nFlickity.Player = Player;\n\nreturn Flickity;\n\n} ) );\n","// prev/next buttons\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory( require('./core') );\n } else {\n // browser global\n factory( window.Flickity );\n }\n\n}( typeof window != 'undefined' ? window : this, function factory( Flickity ) {\n\nconst svgURI = 'http://www.w3.org/2000/svg';\n\n// -------------------------- PrevNextButton -------------------------- //\n\nfunction PrevNextButton( increment, direction, arrowShape ) {\n this.increment = increment;\n this.direction = direction;\n this.isPrevious = increment === 'previous';\n this.isLeft = direction === 'left';\n this._create( arrowShape );\n}\n\nPrevNextButton.prototype._create = function( arrowShape ) {\n // properties\n let element = this.element = document.createElement('button');\n element.className = `flickity-button flickity-prev-next-button ${this.increment}`;\n let label = this.isPrevious ? 'Previous' : 'Next';\n // prevent button from submitting form https://stackoverflow.com/a/10836076/182183\n element.setAttribute( 'type', 'button' );\n element.setAttribute( 'aria-label', label );\n // init as disabled\n this.disable();\n // create arrow\n let svg = this.createSVG( label, arrowShape );\n element.append( svg );\n};\n\nPrevNextButton.prototype.createSVG = function( label, arrowShape ) {\n let svg = document.createElementNS( svgURI, 'svg' );\n svg.setAttribute( 'class', 'flickity-button-icon' );\n svg.setAttribute( 'viewBox', '0 0 100 100' );\n // add title #1189\n let title = document.createElementNS( svgURI, 'title' );\n title.append( label );\n // add path\n let path = document.createElementNS( svgURI, 'path' );\n let pathMovements = getArrowMovements( arrowShape );\n path.setAttribute( 'd', pathMovements );\n path.setAttribute( 'class', 'arrow' );\n // rotate arrow\n if ( !this.isLeft ) {\n path.setAttribute( 'transform', 'translate(100, 100) rotate(180)' );\n }\n svg.append( title, path );\n return svg;\n};\n\n// get SVG path movmement\nfunction getArrowMovements( shape ) {\n // use shape as movement if string\n if ( typeof shape == 'string' ) return shape;\n\n let { x0, x1, x2, x3, y1, y2 } = shape;\n\n // create movement string\n return `M ${x0}, 50\n L ${x1}, ${y1 + 50}\n L ${x2}, ${y2 + 50}\n L ${x3}, 50\n L ${x2}, ${50 - y2}\n L ${x1}, ${50 - y1}\n Z`;\n}\n\n// ----- ----- //\n\nPrevNextButton.prototype.enable = function() {\n this.element.removeAttribute('disabled');\n};\n\nPrevNextButton.prototype.disable = function() {\n this.element.setAttribute( 'disabled', true );\n};\n\n// -------------------------- Flickity prototype -------------------------- //\n\nObject.assign( Flickity.defaults, {\n prevNextButtons: true,\n arrowShape: {\n x0: 10,\n x1: 60, y1: 50,\n x2: 70, y2: 40,\n x3: 30,\n },\n} );\n\nFlickity.create.prevNextButtons = function() {\n if ( !this.options.prevNextButtons ) return;\n\n let { rightToLeft, arrowShape } = this.options;\n let prevDirection = rightToLeft ? 'right' : 'left';\n let nextDirection = rightToLeft ? 'left' : 'right';\n this.prevButton = new PrevNextButton( 'previous', prevDirection, arrowShape );\n this.nextButton = new PrevNextButton( 'next', nextDirection, arrowShape );\n this.focusableElems.push( this.prevButton.element );\n this.focusableElems.push( this.nextButton.element );\n\n this.handlePrevButtonClick = () => {\n this.uiChange();\n this.previous();\n };\n\n this.handleNextButtonClick = () => {\n this.uiChange();\n this.next();\n };\n\n this.on( 'activate', this.activatePrevNextButtons );\n this.on( 'select', this.updatePrevNextButtons );\n};\n\nlet proto = Flickity.prototype;\n\nproto.updatePrevNextButtons = function() {\n let lastIndex = this.slides.length ? this.slides.length - 1 : 0;\n this.updatePrevNextButton( this.prevButton, 0 );\n this.updatePrevNextButton( this.nextButton, lastIndex );\n};\n\nproto.updatePrevNextButton = function( button, disabledIndex ) {\n // enable is wrapAround and at least 2 slides\n if ( this.isWrapping && this.slides.length > 1 ) {\n button.enable();\n return;\n }\n\n let isEnabled = this.selectedIndex !== disabledIndex;\n button[ isEnabled ? 'enable' : 'disable' ]();\n // if disabling button that is focused,\n // shift focus to element to maintain keyboard accessibility\n let isDisabledFocused = !isEnabled && document.activeElement === button.element;\n if ( isDisabledFocused ) this.focus();\n};\n\nproto.activatePrevNextButtons = function() {\n this.prevButton.element.addEventListener( 'click', this.handlePrevButtonClick );\n this.nextButton.element.addEventListener( 'click', this.handleNextButtonClick );\n this.element.append( this.prevButton.element, this.nextButton.element );\n this.on( 'deactivate', this.deactivatePrevNextButtons );\n};\n\nproto.deactivatePrevNextButtons = function() {\n this.prevButton.element.remove();\n this.nextButton.element.remove();\n this.prevButton.element.removeEventListener( 'click', this.handlePrevButtonClick );\n this.nextButton.element.removeEventListener( 'click', this.handleNextButtonClick );\n this.off( 'deactivate', this.deactivatePrevNextButtons );\n};\n\n// -------------------------- -------------------------- //\n\nFlickity.PrevNextButton = PrevNextButton;\n\nreturn Flickity;\n\n} ) );\n","// slide\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory();\n } else {\n // browser global\n window.Flickity = window.Flickity || {};\n window.Flickity.Slide = factory();\n }\n\n}( typeof window != 'undefined' ? window : this, function factory() {\n\nfunction Slide( beginMargin, endMargin, cellAlign ) {\n this.beginMargin = beginMargin;\n this.endMargin = endMargin;\n this.cellAlign = cellAlign;\n this.cells = [];\n this.outerWidth = 0;\n this.height = 0;\n}\n\nlet proto = Slide.prototype;\n\nproto.addCell = function( cell ) {\n this.cells.push( cell );\n this.outerWidth += cell.size.outerWidth;\n this.height = Math.max( cell.size.outerHeight, this.height );\n // first cell stuff\n if ( this.cells.length === 1 ) {\n this.x = cell.x; // x comes from first cell\n this.firstMargin = cell.size[ this.beginMargin ];\n }\n};\n\nproto.updateTarget = function() {\n let lastCell = this.getLastCell();\n let lastMargin = lastCell ? lastCell.size[ this.endMargin ] : 0;\n let slideWidth = this.outerWidth - ( this.firstMargin + lastMargin );\n this.target = this.x + this.firstMargin + slideWidth * this.cellAlign;\n};\n\nproto.getLastCell = function() {\n return this.cells[ this.cells.length - 1 ];\n};\n\nproto.select = function() {\n this.cells.forEach( ( cell ) => cell.select() );\n};\n\nproto.unselect = function() {\n this.cells.forEach( ( cell ) => cell.unselect() );\n};\n\nproto.getCellElements = function() {\n return this.cells.map( ( cell ) => cell.element );\n};\n\nreturn Slide;\n\n} ) );\n","/*!\n * Infinite Scroll v2.0.4\n * measure size of elements\n * MIT license\n */\n\n( function( window, factory ) {\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory();\n } else {\n // browser global\n window.getSize = factory();\n }\n\n} )( window, function factory() {\n\n// -------------------------- helpers -------------------------- //\n\n// get a number from a string, not a percentage\nfunction getStyleSize( value ) {\n let num = parseFloat( value );\n // not a percent like '100%', and a number\n let isValid = value.indexOf('%') == -1 && !isNaN( num );\n return isValid && num;\n}\n\n// -------------------------- measurements -------------------------- //\n\nlet measurements = [\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'paddingBottom',\n 'marginLeft',\n 'marginRight',\n 'marginTop',\n 'marginBottom',\n 'borderLeftWidth',\n 'borderRightWidth',\n 'borderTopWidth',\n 'borderBottomWidth',\n];\n\nlet measurementsLength = measurements.length;\n\nfunction getZeroSize() {\n let size = {\n width: 0,\n height: 0,\n innerWidth: 0,\n innerHeight: 0,\n outerWidth: 0,\n outerHeight: 0,\n };\n measurements.forEach( ( measurement ) => {\n size[ measurement ] = 0;\n } );\n return size;\n}\n\n// -------------------------- getSize -------------------------- //\n\nfunction getSize( elem ) {\n // use querySeletor if elem is string\n if ( typeof elem == 'string' ) elem = document.querySelector( elem );\n\n // do not proceed on non-objects\n let isElement = elem && typeof elem == 'object' && elem.nodeType;\n if ( !isElement ) return;\n\n let style = getComputedStyle( elem );\n\n // if hidden, everything is 0\n if ( style.display == 'none' ) return getZeroSize();\n\n let size = {};\n size.width = elem.offsetWidth;\n size.height = elem.offsetHeight;\n\n let isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';\n\n // get all measurements\n measurements.forEach( ( measurement ) => {\n let value = style[ measurement ];\n let num = parseFloat( value );\n // any 'auto', 'medium' value will be 0\n size[ measurement ] = !isNaN( num ) ? num : 0;\n } );\n\n let paddingWidth = size.paddingLeft + size.paddingRight;\n let paddingHeight = size.paddingTop + size.paddingBottom;\n let marginWidth = size.marginLeft + size.marginRight;\n let marginHeight = size.marginTop + size.marginBottom;\n let borderWidth = size.borderLeftWidth + size.borderRightWidth;\n let borderHeight = size.borderTopWidth + size.borderBottomWidth;\n\n // overwrite width and height if we can get it from style\n let styleWidth = getStyleSize( style.width );\n if ( styleWidth !== false ) {\n size.width = styleWidth +\n // add padding and border unless it's already including it\n ( isBorderBox ? 0 : paddingWidth + borderWidth );\n }\n\n let styleHeight = getStyleSize( style.height );\n if ( styleHeight !== false ) {\n size.height = styleHeight +\n // add padding and border unless it's already including it\n ( isBorderBox ? 0 : paddingHeight + borderHeight );\n }\n\n size.innerWidth = size.width - ( paddingWidth + borderWidth );\n size.innerHeight = size.height - ( paddingHeight + borderHeight );\n\n size.outerWidth = size.width + marginWidth;\n size.outerHeight = size.height + marginHeight;\n\n return size;\n}\n\nreturn getSize;\n\n} );\n","/*!\n * imagesLoaded v5.0.0\n * JavaScript is all like \"You images are done yet or what?\"\n * MIT License\n */\n\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory( window, require('ev-emitter') );\n } else {\n // browser global\n window.imagesLoaded = factory( window, window.EvEmitter );\n }\n\n} )( typeof window !== 'undefined' ? window : this,\n function factory( window, EvEmitter ) {\n\nlet $ = window.jQuery;\nlet console = window.console;\n\n// -------------------------- helpers -------------------------- //\n\n// turn element or nodeList into an array\nfunction makeArray( obj ) {\n // use object if already an array\n if ( Array.isArray( obj ) ) return obj;\n\n let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';\n // convert nodeList to array\n if ( isArrayLike ) return [ ...obj ];\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, Function]} options - if function, use as callback\n * @param {Function} onAlways - callback function\n * @returns {ImagesLoaded}\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 let 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 = {};\n // shift arguments if no options set\n if ( typeof options == 'function' ) {\n onAlways = options;\n } else {\n Object.assign( this.options, options );\n }\n\n if ( onAlways ) this.on( 'always', onAlways );\n\n this.getImages();\n // add jQuery Deferred object\n if ( $ ) this.jqDeferred = new $.Deferred();\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.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\nconst elementNodeTypes = [ 1, 9, 11 ];\n\n/**\n * @param {Node} elem\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 let { nodeType } = elem;\n if ( !nodeType || !elementNodeTypes.includes( nodeType ) ) return;\n\n let childImgs = elem.querySelectorAll('img');\n // concat childElems to filterFound array\n for ( let img of childImgs ) {\n this.addImage( img );\n }\n\n // get child background images\n if ( typeof this.options.background == 'string' ) {\n let children = elem.querySelectorAll( this.options.background );\n for ( let child of children ) {\n this.addElementBackgroundImages( child );\n }\n }\n};\n\nconst reURL = /url\\((['\"])?(.*?)\\1\\)/gi;\n\nImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {\n let style = getComputedStyle( elem );\n // Firefox returns null if in a hidden iframe https://bugzil.la/548397\n if ( !style ) return;\n\n // get url inside url(\"...\")\n let matches = reURL.exec( style.backgroundImage );\n while ( matches !== null ) {\n let 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 let loadingImage = new LoadingImage( img );\n this.images.push( loadingImage );\n};\n\nImagesLoaded.prototype.addBackground = function( url, elem ) {\n let background = new Background( url, elem );\n this.images.push( background );\n};\n\nImagesLoaded.prototype.check = function() {\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 /* eslint-disable-next-line func-style */\n let onProgress = ( image, elem, message ) => {\n // HACK - Chrome triggers event before object properties have changed. #83\n setTimeout( () => {\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 let eventName = this.hasAnyBroken ? 'fail' : 'done';\n this.isComplete = true;\n this.emitEvent( eventName, [ this ] );\n this.emitEvent( 'always', [ this ] );\n if ( this.jqDeferred ) {\n let 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 let 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 // add crossOrigin attribute. #204\n if ( this.img.crossOrigin ) {\n this.proxyImage.crossOrigin = this.img.crossOrigin;\n }\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.currentSrc || 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 let { parentNode } = this.img;\n // emit progress with parent or self \n let elem = parentNode.nodeName === 'PICTURE' ? parentNode : this.img;\n this.emitEvent( 'progress', [ this, elem, message ] );\n};\n\n// ----- events ----- //\n\n// trigger specified handler for event type\nLoadingImage.prototype.handleEvent = function( event ) {\n let 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 let 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 ) return;\n\n // set local variable\n $ = jQuery;\n // $().imagesLoaded()\n $.fn.imagesLoaded = function( options, onAlways ) {\n let instance = new ImagesLoaded( this, options, onAlways );\n return instance.jqDeferred.promise( $( this ) );\n };\n};\n// try making plugin\nImagesLoaded.makeJQueryPlugin();\n\n// -------------------------- -------------------------- //\n\nreturn ImagesLoaded;\n\n} );\n","/*!\n * Unidragger v3.0.1\n * Draggable base class\n * MIT license\n */\n\n( function( window, factory ) {\n // universal module definition\n 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.Unidragger = factory(\n window,\n window.EvEmitter,\n );\n }\n\n}( typeof window != 'undefined' ? window : this, function factory( window, EvEmitter ) {\n\nfunction Unidragger() {}\n\n// inherit EvEmitter\nlet proto = Unidragger.prototype = Object.create( EvEmitter.prototype );\n\n// ----- bind start ----- //\n\n// trigger handler methods for events\nproto.handleEvent = function( event ) {\n let method = 'on' + event.type;\n if ( this[ method ] ) {\n this[ method ]( event );\n }\n};\n\nlet startEvent, activeEvents;\nif ( 'ontouchstart' in window ) {\n // HACK prefer Touch Events as you can preventDefault on touchstart to\n // disable scroll in iOS & mobile Chrome metafizzy/flickity#1177\n startEvent = 'touchstart';\n activeEvents = [ 'touchmove', 'touchend', 'touchcancel' ];\n} else if ( window.PointerEvent ) {\n // Pointer Events\n startEvent = 'pointerdown';\n activeEvents = [ 'pointermove', 'pointerup', 'pointercancel' ];\n} else {\n // mouse events\n startEvent = 'mousedown';\n activeEvents = [ 'mousemove', 'mouseup' ];\n}\n\n// prototype so it can be overwriteable by Flickity\nproto.touchActionValue = 'none';\n\nproto.bindHandles = function() {\n this._bindHandles( 'addEventListener', this.touchActionValue );\n};\n\nproto.unbindHandles = function() {\n this._bindHandles( 'removeEventListener', '' );\n};\n\n/**\n * Add or remove start event\n * @param {String} bindMethod - addEventListener or removeEventListener\n * @param {String} touchAction - value for touch-action CSS property\n */\nproto._bindHandles = function( bindMethod, touchAction ) {\n this.handles.forEach( ( handle ) => {\n handle[ bindMethod ]( startEvent, this );\n handle[ bindMethod ]( 'click', this );\n // touch-action: none to override browser touch gestures. metafizzy/flickity#540\n if ( window.PointerEvent ) handle.style.touchAction = touchAction;\n } );\n};\n\nproto.bindActivePointerEvents = function() {\n activeEvents.forEach( ( eventName ) => {\n window.addEventListener( eventName, this );\n } );\n};\n\nproto.unbindActivePointerEvents = function() {\n activeEvents.forEach( ( eventName ) => {\n window.removeEventListener( eventName, this );\n } );\n};\n\n// ----- event handler helpers ----- //\n\n// trigger method with matching pointer\nproto.withPointer = function( methodName, event ) {\n if ( event.pointerId === this.pointerIdentifier ) {\n this[ methodName ]( event, event );\n }\n};\n\n// trigger method with matching touch\nproto.withTouch = function( methodName, event ) {\n let touch;\n for ( let changedTouch of event.changedTouches ) {\n if ( changedTouch.identifier === this.pointerIdentifier ) {\n touch = changedTouch;\n }\n }\n if ( touch ) this[ methodName ]( event, touch );\n};\n\n// ----- start event ----- //\n\nproto.onmousedown = function( event ) {\n this.pointerDown( event, event );\n};\n\nproto.ontouchstart = function( event ) {\n this.pointerDown( event, event.changedTouches[0] );\n};\n\nproto.onpointerdown = function( event ) {\n this.pointerDown( event, event );\n};\n\n// nodes that have text fields\nconst cursorNodes = [ 'TEXTAREA', 'INPUT', 'SELECT', 'OPTION' ];\n// input types that do not have text fields\nconst clickTypes = [ 'radio', 'checkbox', 'button', 'submit', 'image', 'file' ];\n\n/**\n * any time you set `event, pointer` it refers to:\n * @param {Event} event\n * @param {Event | Touch} pointer\n */\nproto.pointerDown = function( event, pointer ) {\n // dismiss multi-touch taps, right clicks, and clicks on text fields\n let isCursorNode = cursorNodes.includes( event.target.nodeName );\n let isClickType = clickTypes.includes( event.target.type );\n let isOkayElement = !isCursorNode || isClickType;\n let isOkay = !this.isPointerDown && !event.button && isOkayElement;\n if ( !isOkay ) return;\n\n this.isPointerDown = true;\n // save pointer identifier to match up touch events\n this.pointerIdentifier = pointer.pointerId !== undefined ?\n // pointerId for pointer events, touch.indentifier for touch events\n pointer.pointerId : pointer.identifier;\n // track position for move\n this.pointerDownPointer = {\n pageX: pointer.pageX,\n pageY: pointer.pageY,\n };\n\n this.bindActivePointerEvents();\n this.emitEvent( 'pointerDown', [ event, pointer ] );\n};\n\n// ----- move ----- //\n\nproto.onmousemove = function( event ) {\n this.pointerMove( event, event );\n};\n\nproto.onpointermove = function( event ) {\n this.withPointer( 'pointerMove', event );\n};\n\nproto.ontouchmove = function( event ) {\n this.withTouch( 'pointerMove', event );\n};\n\nproto.pointerMove = function( event, pointer ) {\n let moveVector = {\n x: pointer.pageX - this.pointerDownPointer.pageX,\n y: pointer.pageY - this.pointerDownPointer.pageY,\n };\n this.emitEvent( 'pointerMove', [ event, pointer, moveVector ] );\n // start drag if pointer has moved far enough to start drag\n let isDragStarting = !this.isDragging && this.hasDragStarted( moveVector );\n if ( isDragStarting ) this.dragStart( event, pointer );\n if ( this.isDragging ) this.dragMove( event, pointer, moveVector );\n};\n\n// condition if pointer has moved far enough to start drag\nproto.hasDragStarted = function( moveVector ) {\n return Math.abs( moveVector.x ) > 3 || Math.abs( moveVector.y ) > 3;\n};\n\n// ----- drag ----- //\n\nproto.dragStart = function( event, pointer ) {\n this.isDragging = true;\n this.isPreventingClicks = true; // set flag to prevent clicks\n this.emitEvent( 'dragStart', [ event, pointer ] );\n};\n\nproto.dragMove = function( event, pointer, moveVector ) {\n this.emitEvent( 'dragMove', [ event, pointer, moveVector ] );\n};\n\n// ----- end ----- //\n\nproto.onmouseup = function( event ) {\n this.pointerUp( event, event );\n};\n\nproto.onpointerup = function( event ) {\n this.withPointer( 'pointerUp', event );\n};\n\nproto.ontouchend = function( event ) {\n this.withTouch( 'pointerUp', event );\n};\n\nproto.pointerUp = function( event, pointer ) {\n this.pointerDone();\n this.emitEvent( 'pointerUp', [ event, pointer ] );\n\n if ( this.isDragging ) {\n this.dragEnd( event, pointer );\n } else {\n // pointer didn't move enough for drag to start\n this.staticClick( event, pointer );\n }\n};\n\nproto.dragEnd = function( event, pointer ) {\n this.isDragging = false; // reset flag\n // re-enable clicking async\n setTimeout( () => delete this.isPreventingClicks );\n\n this.emitEvent( 'dragEnd', [ event, pointer ] );\n};\n\n// triggered on pointer up & pointer cancel\nproto.pointerDone = function() {\n this.isPointerDown = false;\n delete this.pointerIdentifier;\n this.unbindActivePointerEvents();\n this.emitEvent('pointerDone');\n};\n\n// ----- cancel ----- //\n\nproto.onpointercancel = function( event ) {\n this.withPointer( 'pointerCancel', event );\n};\n\nproto.ontouchcancel = function( event ) {\n this.withTouch( 'pointerCancel', event );\n};\n\nproto.pointerCancel = function( event, pointer ) {\n this.pointerDone();\n this.emitEvent( 'pointerCancel', [ event, pointer ] );\n};\n\n// ----- click ----- //\n\n// handle all clicks and prevent clicks when dragging\nproto.onclick = function( event ) {\n if ( this.isPreventingClicks ) event.preventDefault();\n};\n\n// triggered after pointer down & up with no/tiny movement\nproto.staticClick = function( event, pointer ) {\n // ignore emulated mouse up clicks\n let isMouseup = event.type === 'mouseup';\n if ( isMouseup && this.isIgnoringMouseUp ) return;\n\n this.emitEvent( 'staticClick', [ event, pointer ] );\n\n // set flag for emulated clicks 300ms after touchend\n if ( isMouseup ) {\n this.isIgnoringMouseUp = true;\n // reset flag after 400ms\n setTimeout( () => {\n delete this.isIgnoringMouseUp;\n }, 400 );\n }\n};\n\n// ----- ----- //\n\nreturn Unidragger;\n\n} ) );\n","// var templateUrl = site.theme_url; // this comes from functions.php\n\n// Customize BootStrap - import only what we need\n// import Alert from 'bootstrap/js/dist/alert';\n// import Button from 'bootstrap/js/dist/button';\n// import Carousel from 'bootstrap/js/dist/carousel';\nimport Collapse from 'bootstrap/js/dist/collapse';\n// import Dropdown from 'bootstrap/js/dist/dropdown';\n// import Modal from 'bootstrap/js/dist/modal';\n// import Offcanvas from 'bootstrap/js/dist/offcanvas';\n// import Popover from 'bootstrap/js/dist/popover';\n// import ScrollSpy from 'bootstrap/js/dist/scrollspy';\n// import Tab from 'bootstrap/js/dist/tab';\n// import Toast from 'bootstrap/js/dist/toast';\n// import Tooltip from 'bootstrap/js/dist/tooltip';\n\n// App\nimport { BgDots } from './components/global/bgDots';\nimport { Carousels } from './components/global/carousels';\nimport { MainMenu } from './components/global/mainMenu';\n\nconst initApp = () => {\n const bodyEl = document.getElementsByTagName('body')[0];\n\n // GLOBAL\n const bgDots = new BgDots();\n bgDots.init();\n\n const carousels = new Carousels();\n carousels.init();\n\n const mainMenu = new MainMenu(Collapse);\n mainMenu.init();\n\n // PAGE DETECTION\n // if (bodyEl.classList.contains('home')) {\n // const frontPage = new FrontPage();\n // frontPage.init();\n // }\n};\n\n(function () {\n document.documentElement.classList.remove('no-js');\n initApp();\n})();\n","export function BgDots() {\n let dotsContainers = false;\n\n const breakpoint = 992;\n\n const init = () => {\n dotsContainers = document.querySelectorAll('.bg-dots');\n\n if (!dotsContainers) return false;\n\n _addListeners();\n _initDots();\n // _checkWindow();\n };\n\n const _addListeners = () => {\n window.addEventListener(\n 'resize',\n _debounce(function () {\n _initDots();\n }),\n false,\n );\n\n // window.addEventListener('resize', (e) => {\n // _checkWindow();\n // });\n };\n\n const _initDots = () => {\n dotsContainers.forEach((el, i) => {\n let offset = 35;\n let minSize = 12;\n let maxSize = 15;\n let minDuration = 5000;\n let maxDuration = 15000;\n\n const containerWidth = el.offsetWidth;\n const containerHeight = el.offsetHeight;\n\n el.innerHTML = '';\n\n if (el.classList.contains('bg-dots--dark')) {\n minSize = 23;\n maxSize = 23;\n }\n\n for (var x = 10; x < containerWidth; x += offset) {\n for (var y = 10; y < containerHeight; y += offset) {\n const dot = document.createElement('div');\n\n dot.classList.add('bg-dots__dot');\n dot.style.setProperty('--posx', x + 'px');\n dot.style.setProperty('--posy', y + 'px');\n dot.style.setProperty('--rad', _randomRange(minSize, maxSize) + 'px');\n dot.style.setProperty('--dur', _randomRange(minDuration, maxDuration) + 'ms');\n\n el.appendChild(dot);\n }\n }\n });\n };\n\n // const _checkWindow = (e) => {\n // remove bg dots animation on small screens\n // if (window.innerWidth < breakpoint) {\n // dotsContainers.forEach((el, i) => {\n // el.classList.remove('bg-dots--animate');\n // });\n // }\n // };\n\n const _randomRange = (min, max) => {\n return Math.random() * (max - min) + min;\n };\n\n const _debounce = (func, timeout = 250) => {\n let timer;\n\n return (...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n func.apply(this, args);\n }, timeout);\n };\n };\n\n return { init };\n}\n","import Flickity from 'flickity';\n\nexport function Carousels() {\n let _carousels;\n\n const init = () => {\n _selectCarousels();\n _initCarousels();\n };\n\n const _selectCarousels = () => {\n _carousels = document.querySelectorAll('.carousel');\n };\n\n const _initCarousels = () => {\n if (_carousels.length) {\n _carousels.forEach((el) => {\n let flkty = new Flickity(el, {\n cellSelector: '.carousel__cell',\n wrapAround: el.classList.contains('carousel--imgs') ? false : true,\n contain: el.classList.contains('carousel--imgs') ? true : false,\n imagesLoaded: el.classList.contains('carousel--imgs') ? true : false,\n autoPlay: el.classList.contains('carousel--imgs') ? false : 10000,\n lazyLoad: el.classList.contains('carousel--imgs') ? true : false,\n adaptiveHeight: el.classList.contains('carousel--imgs') ? false : false,\n pageDots: el.classList.contains('carousel--imgs') ? false : true,\n prevNextButtons: false,\n });\n });\n }\n };\n\n return { init };\n}\n","export function MainMenu(Collapse) {\n // DOM\n const mainMenu = document.getElementById('main-menu');\n const navbar = document.querySelector('.navbar');\n const toggler = document.querySelector('.navbar-toggler');\n const hero = document.querySelector('.hero');\n\n const breakpoint = 992;\n\n let menu;\n\n // Methods\n const init = () => {\n if (!mainMenu) return false;\n\n menu = new Collapse(mainMenu, {\n toggle: false,\n });\n\n _addListeners();\n _checkWindow();\n };\n\n const _addListeners = () => {\n window.addEventListener('resize', (e) => {\n _checkWindow();\n });\n };\n\n const _checkWindow = (e) => {\n if (window.innerWidth < breakpoint) {\n _initMobile();\n } else {\n _initDesktop();\n }\n };\n\n const _initMobile = () => {\n _checkMenuScroll();\n\n navbar.classList.remove('navbar--submenu-open');\n\n mainMenu.addEventListener('show.bs.collapse', _handleShowCollapse, false);\n mainMenu.addEventListener('hide.bs.collapse', _handleHideCollapse, false);\n\n window.addEventListener('scroll', (e) => {\n _checkMenuScroll();\n });\n };\n\n const _initDesktop = () => {\n _checkMenuScroll();\n menu.hide();\n\n document.body.classList.remove('menu-open');\n\n mainMenu.removeEventListener('show.bs.collapse', _handleShowCollapse, false);\n mainMenu.removeEventListener('hide.bs.collapse', _handleHideCollapse, false);\n\n window.addEventListener('scroll', (e) => {\n _checkMenuScroll();\n });\n };\n\n const _checkMenuScroll = () => {\n if (hero.offsetHeight === 0) {\n // page has no hero\n if (window.scrollY < 150) {\n navbar.classList.remove('navbar--sticky');\n } else {\n navbar.classList.add('navbar--sticky');\n }\n } else {\n let offset = hero.classList.contains('hero--compact') ? 100 : 200;\n\n if (window.scrollY < hero.offsetHeight - offset) {\n navbar.classList.remove('navbar--sticky');\n } else {\n navbar.classList.add('navbar--sticky');\n }\n }\n };\n\n const _handleShowCollapse = (e) => {\n document.body.classList.add('menu-open');\n toggler.classList.add('is-active');\n };\n\n const _handleHideCollapse = (e) => {\n document.body.classList.remove('menu-open');\n toggler.classList.remove('is-active');\n };\n\n return { init };\n}\n"],"preExistingComment":"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2Rpc3QvYmFzZS1jb21wb25lbnQuanMiLCJub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2Rpc3QvY29sbGFwc2UuanMiLCJub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2Rpc3QvZG9tL2RhdGEuanMiLCJub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2Rpc3QvZG9tL2V2ZW50LWhhbmRsZXIuanMiLCJub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2Rpc3QvZG9tL21hbmlwdWxhdG9yLmpzIiwibm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9kaXN0L2RvbS9zZWxlY3Rvci1lbmdpbmUuanMiLCJub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2Rpc3QvdXRpbC9jb25maWcuanMiLCJub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2Rpc3QvdXRpbC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9ldi1lbWl0dGVyL2V2LWVtaXR0ZXIuanMiLCJub2RlX21vZHVsZXMvZml6enktdWktdXRpbHMvdXRpbHMuanMiLCJub2RlX21vZHVsZXMvZmxpY2tpdHkvanMvYWRkLXJlbW92ZS1jZWxsLmpzIiwibm9kZV9tb2R1bGVzL2ZsaWNraXR5L2pzL2FuaW1hdGUuanMiLCJub2RlX21vZHVsZXMvZmxpY2tpdHkvanMvY2VsbC5qcyIsIm5vZGVfbW9kdWxlcy9mbGlja2l0eS9qcy9jb3JlLmpzIiwibm9kZV9tb2R1bGVzL2ZsaWNraXR5L2pzL2RyYWcuanMiLCJub2RlX21vZHVsZXMvZmxpY2tpdHkvanMvaW1hZ2VzbG9hZGVkLmpzIiwibm9kZV9tb2R1bGVzL2ZsaWNraXR5L2pzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2ZsaWNraXR5L2pzL2xhenlsb2FkLmpzIiwibm9kZV9tb2R1bGVzL2ZsaWNraXR5L2pzL3BhZ2UtZG90cy5qcyIsIm5vZGVfbW9kdWxlcy9mbGlja2l0eS9qcy9wbGF5ZXIuanMiLCJub2RlX21vZHVsZXMvZmxpY2tpdHkvanMvcHJldi1uZXh0LWJ1dHRvbi5qcyIsIm5vZGVfbW9kdWxlcy9mbGlja2l0eS9qcy9zbGlkZS5qcyIsIm5vZGVfbW9kdWxlcy9nZXQtc2l6ZS9nZXQtc2l6ZS5qcyIsIm5vZGVfbW9kdWxlcy9pbWFnZXNsb2FkZWQvaW1hZ2VzbG9hZGVkLmpzIiwibm9kZV9tb2R1bGVzL3VuaWRyYWdnZXIvdW5pZHJhZ2dlci5qcyIsInNvdXJjZS90aGVtZS9qcy9hcHAuanMiLCJzb3VyY2UvdGhlbWUvanMvY29tcG9uZW50cy9nbG9iYWwvYmdEb3RzLmpzIiwic291cmNlL3RoZW1lL2pzL2NvbXBvbmVudHMvZ2xvYmFsL2Nhcm91c2Vscy5qcyIsInNvdXJjZS90aGVtZS9qcy9jb21wb25lbnRzL2dsb2JhbC9tYWluTWVudS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2VEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcE1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3YzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDektBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9VQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDM1JBOztBQVdBOztBQUNBOztBQUNBOzs7O0FBbkJBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFLQSxJQUFNLE9BQU8sR0FBRyxTQUFWLE9BQVUsR0FBTTtBQUNwQixNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsb0JBQVQsQ0FBOEIsTUFBOUIsRUFBc0MsQ0FBdEMsQ0FBZixDQURvQixDQUdwQjs7QUFDQSxNQUFNLE1BQU0sR0FBRyxJQUFJLGNBQUosRUFBZjtBQUNBLEVBQUEsTUFBTSxDQUFDLElBQVA7QUFFQSxNQUFNLFNBQVMsR0FBRyxJQUFJLG9CQUFKLEVBQWxCO0FBQ0EsRUFBQSxTQUFTLENBQUMsSUFBVjtBQUVBLE1BQU0sUUFBUSxHQUFHLElBQUksa0JBQUosQ0FBYSxpQkFBYixDQUFqQjtBQUNBLEVBQUEsUUFBUSxDQUFDLElBQVQsR0FYb0IsQ0FhcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNELENBbEJEOztBQW9CQSxDQUFDLFlBQVk7QUFDWCxFQUFBLFFBQVEsQ0FBQyxlQUFULENBQXlCLFNBQXpCLENBQW1DLE1BQW5DLENBQTBDLE9BQTFDO0FBQ0EsRUFBQSxPQUFPO0FBQ1IsQ0FIRDs7Ozs7Ozs7OztBQ3pDTyxTQUFTLE1BQVQsR0FBa0I7QUFBQTs7QUFDdkIsTUFBSSxjQUFjLEdBQUcsS0FBckI7QUFFQSxNQUFNLFVBQVUsR0FBRyxHQUFuQjs7QUFFQSxNQUFNLElBQUksR0FBRyxTQUFQLElBQU8sR0FBTTtBQUNqQixJQUFBLGNBQWMsR0FBRyxRQUFRLENBQUMsZ0JBQVQsQ0FBMEIsVUFBMUIsQ0FBakI7QUFFQSxRQUFJLENBQUMsY0FBTCxFQUFxQixPQUFPLEtBQVA7O0FBRXJCLElBQUEsYUFBYTs7QUFDYixJQUFBLFNBQVMsR0FOUSxDQU9qQjs7QUFDRCxHQVJEOztBQVVBLE1BQU0sYUFBYSxHQUFHLFNBQWhCLGFBQWdCLEdBQU07QUFDMUIsSUFBQSxNQUFNLENBQUMsZ0JBQVAsQ0FDRSxRQURGLEVBRUUsU0FBUyxDQUFDLFlBQVk7QUFDcEIsTUFBQSxTQUFTO0FBQ1YsS0FGUSxDQUZYLEVBS0UsS0FMRixFQUQwQixDQVMxQjtBQUNBO0FBQ0E7QUFDRCxHQVpEOztBQWNBLE1BQU0sU0FBUyxHQUFHLFNBQVosU0FBWSxHQUFNO0FBQ3RCLElBQUEsY0FBYyxDQUFDLE9BQWYsQ0FBdUIsVUFBQyxFQUFELEVBQUssQ0FBTCxFQUFXO0FBQ2hDLFVBQUksTUFBTSxHQUFHLEVBQWI7QUFDQSxVQUFJLE9BQU8sR0FBRyxFQUFkO0FBQ0EsVUFBSSxPQUFPLEdBQUcsRUFBZDtBQUNBLFVBQUksV0FBVyxHQUFHLElBQWxCO0FBQ0EsVUFBSSxXQUFXLEdBQUcsS0FBbEI7QUFFQSxVQUFNLGNBQWMsR0FBRyxFQUFFLENBQUMsV0FBMUI7QUFDQSxVQUFNLGVBQWUsR0FBRyxFQUFFLENBQUMsWUFBM0I7QUFFQSxNQUFBLEVBQUUsQ0FBQyxTQUFILEdBQWUsRUFBZjs7QUFFQSxVQUFJLEVBQUUsQ0FBQyxTQUFILENBQWEsUUFBYixDQUFzQixlQUF0QixDQUFKLEVBQTRDO0FBQzFDLFFBQUEsT0FBTyxHQUFHLEVBQVY7QUFDQSxRQUFBLE9BQU8sR0FBRyxFQUFWO0FBQ0Q7O0FBRUQsV0FBSyxJQUFJLENBQUMsR0FBRyxFQUFiLEVBQWlCLENBQUMsR0FBRyxjQUFyQixFQUFxQyxDQUFDLElBQUksTUFBMUMsRUFBa0Q7QUFDaEQsYUFBSyxJQUFJLENBQUMsR0FBRyxFQUFiLEVBQWlCLENBQUMsR0FBRyxlQUFyQixFQUFzQyxDQUFDLElBQUksTUFBM0MsRUFBbUQ7QUFDakQsY0FBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLGFBQVQsQ0FBdUIsS0FBdkIsQ0FBWjtBQUVBLFVBQUEsR0FBRyxDQUFDLFNBQUosQ0FBYyxHQUFkLENBQWtCLGNBQWxCO0FBQ0EsVUFBQSxHQUFHLENBQUMsS0FBSixDQUFVLFdBQVYsQ0FBc0IsUUFBdEIsRUFBZ0MsQ0FBQyxHQUFHLElBQXBDO0FBQ0EsVUFBQSxHQUFHLENBQUMsS0FBSixDQUFVLFdBQVYsQ0FBc0IsUUFBdEIsRUFBZ0MsQ0FBQyxHQUFHLElBQXBDO0FBQ0EsVUFBQSxHQUFHLENBQUMsS0FBSixDQUFVLFdBQVYsQ0FBc0IsT0FBdEIsRUFBK0IsWUFBWSxDQUFDLE9BQUQsRUFBVSxPQUFWLENBQVosR0FBaUMsSUFBaEU7QUFDQSxVQUFBLEdBQUcsQ0FBQyxLQUFKLENBQVUsV0FBVixDQUFzQixPQUF0QixFQUErQixZQUFZLENBQUMsV0FBRCxFQUFjLFdBQWQsQ0FBWixHQUF5QyxJQUF4RTtBQUVBLFVBQUEsRUFBRSxDQUFDLFdBQUgsQ0FBZSxHQUFmO0FBQ0Q7QUFDRjtBQUNGLEtBOUJEO0FBK0JELEdBaENELENBN0J1QixDQStEdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBRUEsTUFBTSxZQUFZLEdBQUcsU0FBZixZQUFlLENBQUMsR0FBRCxFQUFNLEdBQU4sRUFBYztBQUNqQyxXQUFPLElBQUksQ0FBQyxNQUFMLE1BQWlCLEdBQUcsR0FBRyxHQUF2QixJQUE4QixHQUFyQztBQUNELEdBRkQ7O0FBSUEsTUFBTSxTQUFTLEdBQUcsU0FBWixTQUFZLENBQUMsSUFBRCxFQUF5QjtBQUFBLFFBQWxCLE9BQWtCLHVFQUFSLEdBQVE7QUFDekMsUUFBSSxLQUFKO0FBRUEsV0FBTyxZQUFhO0FBQUEsd0NBQVQsSUFBUztBQUFULFFBQUEsSUFBUztBQUFBOztBQUNsQixNQUFBLFlBQVksQ0FBQyxLQUFELENBQVo7QUFDQSxNQUFBLEtBQUssR0FBRyxVQUFVLENBQUMsWUFBTTtBQUN2QixRQUFBLElBQUksQ0FBQyxLQUFMLENBQVcsS0FBWCxFQUFpQixJQUFqQjtBQUNELE9BRmlCLEVBRWYsT0FGZSxDQUFsQjtBQUdELEtBTEQ7QUFNRCxHQVREOztBQVdBLFNBQU87QUFBRSxJQUFBLElBQUksRUFBSjtBQUFGLEdBQVA7QUFDRDs7Ozs7Ozs7OztBQ3hGRDs7OztBQUVPLFNBQVMsU0FBVCxHQUFxQjtBQUMxQixNQUFJLFVBQUo7O0FBRUEsTUFBTSxJQUFJLEdBQUcsU0FBUCxJQUFPLEdBQU07QUFDakIsSUFBQSxnQkFBZ0I7O0FBQ2hCLElBQUEsY0FBYztBQUNmLEdBSEQ7O0FBS0EsTUFBTSxnQkFBZ0IsR0FBRyxTQUFuQixnQkFBbUIsR0FBTTtBQUM3QixJQUFBLFVBQVUsR0FBRyxRQUFRLENBQUMsZ0JBQVQsQ0FBMEIsV0FBMUIsQ0FBYjtBQUNELEdBRkQ7O0FBSUEsTUFBTSxjQUFjLEdBQUcsU0FBakIsY0FBaUIsR0FBTTtBQUMzQixRQUFJLFVBQVUsQ0FBQyxNQUFmLEVBQXVCO0FBQ3JCLE1BQUEsVUFBVSxDQUFDLE9BQVgsQ0FBbUIsVUFBQyxFQUFELEVBQVE7QUFDekIsWUFBSSxLQUFLLEdBQUcsSUFBSSxpQkFBSixDQUFhLEVBQWIsRUFBaUI7QUFDM0IsVUFBQSxZQUFZLEVBQUUsaUJBRGE7QUFFM0IsVUFBQSxVQUFVLEVBQUUsRUFBRSxDQUFDLFNBQUgsQ0FBYSxRQUFiLENBQXNCLGdCQUF0QixJQUEwQyxLQUExQyxHQUFrRCxJQUZuQztBQUczQixVQUFBLE9BQU8sRUFBRSxFQUFFLENBQUMsU0FBSCxDQUFhLFFBQWIsQ0FBc0IsZ0JBQXRCLElBQTBDLElBQTFDLEdBQWlELEtBSC9CO0FBSTNCLFVBQUEsWUFBWSxFQUFFLEVBQUUsQ0FBQyxTQUFILENBQWEsUUFBYixDQUFzQixnQkFBdEIsSUFBMEMsSUFBMUMsR0FBaUQsS0FKcEM7QUFLM0IsVUFBQSxRQUFRLEVBQUUsRUFBRSxDQUFDLFNBQUgsQ0FBYSxRQUFiLENBQXNCLGdCQUF0QixJQUEwQyxLQUExQyxHQUFrRCxLQUxqQztBQU0zQixVQUFBLFFBQVEsRUFBRSxFQUFFLENBQUMsU0FBSCxDQUFhLFFBQWIsQ0FBc0IsZ0JBQXRCLElBQTBDLElBQTFDLEdBQWlELEtBTmhDO0FBTzNCLFVBQUEsY0FBYyxFQUFFLEVBQUUsQ0FBQyxTQUFILENBQWEsUUFBYixDQUFzQixnQkFBdEIsSUFBMEMsS0FBMUMsR0FBa0QsS0FQdkM7QUFRM0IsVUFBQSxRQUFRLEVBQUUsRUFBRSxDQUFDLFNBQUgsQ0FBYSxRQUFiLENBQXNCLGdCQUF0QixJQUEwQyxLQUExQyxHQUFrRCxJQVJqQztBQVMzQixVQUFBLGVBQWUsRUFBRTtBQVRVLFNBQWpCLENBQVo7QUFXRCxPQVpEO0FBYUQ7QUFDRixHQWhCRDs7QUFrQkEsU0FBTztBQUFFLElBQUEsSUFBSSxFQUFKO0FBQUYsR0FBUDtBQUNEOzs7Ozs7Ozs7O0FDakNNLFNBQVMsUUFBVCxDQUFrQixRQUFsQixFQUE0QjtBQUNqQztBQUNBLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxjQUFULENBQXdCLFdBQXhCLENBQWpCO0FBQ0EsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQVQsQ0FBdUIsU0FBdkIsQ0FBZjtBQUNBLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxhQUFULENBQXVCLGlCQUF2QixDQUFoQjtBQUNBLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxhQUFULENBQXVCLE9BQXZCLENBQWI7QUFFQSxNQUFNLFVBQVUsR0FBRyxHQUFuQjtBQUVBLE1BQUksSUFBSixDQVRpQyxDQVdqQzs7QUFDQSxNQUFNLElBQUksR0FBRyxTQUFQLElBQU8sR0FBTTtBQUNqQixRQUFJLENBQUMsUUFBTCxFQUFlLE9BQU8sS0FBUDtBQUVmLElBQUEsSUFBSSxHQUFHLElBQUksUUFBSixDQUFhLFFBQWIsRUFBdUI7QUFDNUIsTUFBQSxNQUFNLEVBQUU7QUFEb0IsS0FBdkIsQ0FBUDs7QUFJQSxJQUFBLGFBQWE7O0FBQ2IsSUFBQSxZQUFZO0FBQ2IsR0FURDs7QUFXQSxNQUFNLGFBQWEsR0FBRyxTQUFoQixhQUFnQixHQUFNO0FBQzFCLElBQUEsTUFBTSxDQUFDLGdCQUFQLENBQXdCLFFBQXhCLEVBQWtDLFVBQUMsQ0FBRCxFQUFPO0FBQ3ZDLE1BQUEsWUFBWTtBQUNiLEtBRkQ7QUFHRCxHQUpEOztBQU1BLE1BQU0sWUFBWSxHQUFHLFNBQWYsWUFBZSxDQUFDLENBQUQsRUFBTztBQUMxQixRQUFJLE1BQU0sQ0FBQyxVQUFQLEdBQW9CLFVBQXhCLEVBQW9DO0FBQ2xDLE1BQUEsV0FBVztBQUNaLEtBRkQsTUFFTztBQUNMLE1BQUEsWUFBWTtBQUNiO0FBQ0YsR0FORDs7QUFRQSxNQUFNLFdBQVcsR0FBRyxTQUFkLFdBQWMsR0FBTTtBQUN4QixJQUFBLGdCQUFnQjs7QUFFaEIsSUFBQSxNQUFNLENBQUMsU0FBUCxDQUFpQixNQUFqQixDQUF3QixzQkFBeEI7QUFFQSxJQUFBLFFBQVEsQ0FBQyxnQkFBVCxDQUEwQixrQkFBMUIsRUFBOEMsbUJBQTlDLEVBQW1FLEtBQW5FO0FBQ0EsSUFBQSxRQUFRLENBQUMsZ0JBQVQsQ0FBMEIsa0JBQTFCLEVBQThDLG1CQUE5QyxFQUFtRSxLQUFuRTtBQUVBLElBQUEsTUFBTSxDQUFDLGdCQUFQLENBQXdCLFFBQXhCLEVBQWtDLFVBQUMsQ0FBRCxFQUFPO0FBQ3ZDLE1BQUEsZ0JBQWdCO0FBQ2pCLEtBRkQ7QUFHRCxHQVhEOztBQWFBLE1BQU0sWUFBWSxHQUFHLFNBQWYsWUFBZSxHQUFNO0FBQ3pCLElBQUEsZ0JBQWdCOztBQUNoQixJQUFBLElBQUksQ0FBQyxJQUFMO0FBRUEsSUFBQSxRQUFRLENBQUMsSUFBVCxDQUFjLFNBQWQsQ0FBd0IsTUFBeEIsQ0FBK0IsV0FBL0I7QUFFQSxJQUFBLFFBQVEsQ0FBQyxtQkFBVCxDQUE2QixrQkFBN0IsRUFBaUQsbUJBQWpELEVBQXNFLEtBQXRFO0FBQ0EsSUFBQSxRQUFRLENBQUMsbUJBQVQsQ0FBNkIsa0JBQTdCLEVBQWlELG1CQUFqRCxFQUFzRSxLQUF0RTtBQUVBLElBQUEsTUFBTSxDQUFDLGdCQUFQLENBQXdCLFFBQXhCLEVBQWtDLFVBQUMsQ0FBRCxFQUFPO0FBQ3ZDLE1BQUEsZ0JBQWdCO0FBQ2pCLEtBRkQ7QUFHRCxHQVpEOztBQWNBLE1BQU0sZ0JBQWdCLEdBQUcsU0FBbkIsZ0JBQW1CLEdBQU07QUFDN0IsUUFBSSxJQUFJLENBQUMsWUFBTCxLQUFzQixDQUExQixFQUE2QjtBQUMzQjtBQUNBLFVBQUksTUFBTSxDQUFDLE9BQVAsR0FBaUIsR0FBckIsRUFBMEI7QUFDeEIsUUFBQSxNQUFNLENBQUMsU0FBUCxDQUFpQixNQUFqQixDQUF3QixnQkFBeEI7QUFDRCxPQUZELE1BRU87QUFDTCxRQUFBLE1BQU0sQ0FBQyxTQUFQLENBQWlCLEdBQWpCLENBQXFCLGdCQUFyQjtBQUNEO0FBQ0YsS0FQRCxNQU9PO0FBQ0wsVUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQUwsQ0FBZSxRQUFmLENBQXdCLGVBQXhCLElBQTJDLEdBQTNDLEdBQWlELEdBQTlEOztBQUVBLFVBQUksTUFBTSxDQUFDLE9BQVAsR0FBaUIsSUFBSSxDQUFDLFlBQUwsR0FBb0IsTUFBekMsRUFBaUQ7QUFDL0MsUUFBQSxNQUFNLENBQUMsU0FBUCxDQUFpQixNQUFqQixDQUF3QixnQkFBeEI7QUFDRCxPQUZELE1BRU87QUFDTCxRQUFBLE1BQU0sQ0FBQyxTQUFQLENBQWlCLEdBQWpCLENBQXFCLGdCQUFyQjtBQUNEO0FBQ0Y7QUFDRixHQWpCRDs7QUFtQkEsTUFBTSxtQkFBbUIsR0FBRyxTQUF0QixtQkFBc0IsQ0FBQyxDQUFELEVBQU87QUFDakMsSUFBQSxRQUFRLENBQUMsSUFBVCxDQUFjLFNBQWQsQ0FBd0IsR0FBeEIsQ0FBNEIsV0FBNUI7QUFDQSxJQUFBLE9BQU8sQ0FBQyxTQUFSLENBQWtCLEdBQWxCLENBQXNCLFdBQXRCO0FBQ0QsR0FIRDs7QUFLQSxNQUFNLG1CQUFtQixHQUFHLFNBQXRCLG1CQUFzQixDQUFDLENBQUQsRUFBTztBQUNqQyxJQUFBLFFBQVEsQ0FBQyxJQUFULENBQWMsU0FBZCxDQUF3QixNQUF4QixDQUErQixXQUEvQjtBQUNBLElBQUEsT0FBTyxDQUFDLFNBQVIsQ0FBa0IsTUFBbEIsQ0FBeUIsV0FBekI7QUFDRCxHQUhEOztBQUtBLFNBQU87QUFBRSxJQUFBLElBQUksRUFBSjtBQUFGLEdBQVA7QUFDRCIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsIi8qIVxuICAqIEJvb3RzdHJhcCBiYXNlLWNvbXBvbmVudC5qcyB2NS4yLjAgKGh0dHBzOi8vZ2V0Ym9vdHN0cmFwLmNvbS8pXG4gICogQ29weXJpZ2h0IDIwMTEtMjAyMiBUaGUgQm9vdHN0cmFwIEF1dGhvcnMgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ncmFwaHMvY29udHJpYnV0b3JzKVxuICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAqL1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoJy4vZG9tL2RhdGEnKSwgcmVxdWlyZSgnLi91dGlsL2luZGV4JyksIHJlcXVpcmUoJy4vZG9tL2V2ZW50LWhhbmRsZXInKSwgcmVxdWlyZSgnLi91dGlsL2NvbmZpZycpKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4vZG9tL2RhdGEnLCAnLi91dGlsL2luZGV4JywgJy4vZG9tL2V2ZW50LWhhbmRsZXInLCAnLi91dGlsL2NvbmZpZyddLCBmYWN0b3J5KSA6XG4gIChnbG9iYWwgPSB0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWxUaGlzIDogZ2xvYmFsIHx8IHNlbGYsIGdsb2JhbC5CYXNlQ29tcG9uZW50ID0gZmFjdG9yeShnbG9iYWwuRGF0YSwgZ2xvYmFsLkluZGV4LCBnbG9iYWwuRXZlbnRIYW5kbGVyLCBnbG9iYWwuQ29uZmlnKSk7XG59KSh0aGlzLCAoZnVuY3Rpb24gKERhdGEsIGluZGV4LCBFdmVudEhhbmRsZXIsIENvbmZpZykgeyAndXNlIHN0cmljdCc7XG5cbiAgY29uc3QgX2ludGVyb3BEZWZhdWx0TGVnYWN5ID0gZSA9PiBlICYmIHR5cGVvZiBlID09PSAnb2JqZWN0JyAmJiAnZGVmYXVsdCcgaW4gZSA/IGUgOiB7IGRlZmF1bHQ6IGUgfTtcblxuICBjb25zdCBEYXRhX19kZWZhdWx0ID0gLyojX19QVVJFX18qL19pbnRlcm9wRGVmYXVsdExlZ2FjeShEYXRhKTtcbiAgY29uc3QgRXZlbnRIYW5kbGVyX19kZWZhdWx0ID0gLyojX19QVVJFX18qL19pbnRlcm9wRGVmYXVsdExlZ2FjeShFdmVudEhhbmRsZXIpO1xuICBjb25zdCBDb25maWdfX2RlZmF1bHQgPSAvKiNfX1BVUkVfXyovX2ludGVyb3BEZWZhdWx0TGVnYWN5KENvbmZpZyk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMi4wKTogYmFzZS1jb21wb25lbnQuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYWluL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICAvKipcbiAgICogQ29uc3RhbnRzXG4gICAqL1xuXG4gIGNvbnN0IFZFUlNJT04gPSAnNS4yLjAnO1xuICAvKipcbiAgICogQ2xhc3MgZGVmaW5pdGlvblxuICAgKi9cblxuICBjbGFzcyBCYXNlQ29tcG9uZW50IGV4dGVuZHMgQ29uZmlnX19kZWZhdWx0LmRlZmF1bHQge1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQsIGNvbmZpZykge1xuICAgICAgc3VwZXIoKTtcbiAgICAgIGVsZW1lbnQgPSBpbmRleC5nZXRFbGVtZW50KGVsZW1lbnQpO1xuXG4gICAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgIHRoaXMuX2NvbmZpZyA9IHRoaXMuX2dldENvbmZpZyhjb25maWcpO1xuICAgICAgRGF0YV9fZGVmYXVsdC5kZWZhdWx0LnNldCh0aGlzLl9lbGVtZW50LCB0aGlzLmNvbnN0cnVjdG9yLkRBVEFfS0VZLCB0aGlzKTtcbiAgICB9IC8vIFB1YmxpY1xuXG5cbiAgICBkaXNwb3NlKCkge1xuICAgICAgRGF0YV9fZGVmYXVsdC5kZWZhdWx0LnJlbW92ZSh0aGlzLl9lbGVtZW50LCB0aGlzLmNvbnN0cnVjdG9yLkRBVEFfS0VZKTtcbiAgICAgIEV2ZW50SGFuZGxlcl9fZGVmYXVsdC5kZWZhdWx0Lm9mZih0aGlzLl9lbGVtZW50LCB0aGlzLmNvbnN0cnVjdG9yLkVWRU5UX0tFWSk7XG5cbiAgICAgIGZvciAoY29uc3QgcHJvcGVydHlOYW1lIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKSB7XG4gICAgICAgIHRoaXNbcHJvcGVydHlOYW1lXSA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuXG4gICAgX3F1ZXVlQ2FsbGJhY2soY2FsbGJhY2ssIGVsZW1lbnQsIGlzQW5pbWF0ZWQgPSB0cnVlKSB7XG4gICAgICBpbmRleC5leGVjdXRlQWZ0ZXJUcmFuc2l0aW9uKGNhbGxiYWNrLCBlbGVtZW50LCBpc0FuaW1hdGVkKTtcbiAgICB9XG5cbiAgICBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgY29uZmlnID0gdGhpcy5fbWVyZ2VDb25maWdPYmooY29uZmlnLCB0aGlzLl9lbGVtZW50KTtcbiAgICAgIGNvbmZpZyA9IHRoaXMuX2NvbmZpZ0FmdGVyTWVyZ2UoY29uZmlnKTtcblxuICAgICAgdGhpcy5fdHlwZUNoZWNrQ29uZmlnKGNvbmZpZyk7XG5cbiAgICAgIHJldHVybiBjb25maWc7XG4gICAgfSAvLyBTdGF0aWNcblxuXG4gICAgc3RhdGljIGdldEluc3RhbmNlKGVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBEYXRhX19kZWZhdWx0LmRlZmF1bHQuZ2V0KGluZGV4LmdldEVsZW1lbnQoZWxlbWVudCksIHRoaXMuREFUQV9LRVkpO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXRPckNyZWF0ZUluc3RhbmNlKGVsZW1lbnQsIGNvbmZpZyA9IHt9KSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRJbnN0YW5jZShlbGVtZW50KSB8fCBuZXcgdGhpcyhlbGVtZW50LCB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyA/IGNvbmZpZyA6IG51bGwpO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXQgVkVSU0lPTigpIHtcbiAgICAgIHJldHVybiBWRVJTSU9OO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXQgREFUQV9LRVkoKSB7XG4gICAgICByZXR1cm4gYGJzLiR7dGhpcy5OQU1FfWA7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldCBFVkVOVF9LRVkoKSB7XG4gICAgICByZXR1cm4gYC4ke3RoaXMuREFUQV9LRVl9YDtcbiAgICB9XG5cbiAgICBzdGF0aWMgZXZlbnROYW1lKG5hbWUpIHtcbiAgICAgIHJldHVybiBgJHtuYW1lfSR7dGhpcy5FVkVOVF9LRVl9YDtcbiAgICB9XG5cbiAgfVxuXG4gIHJldHVybiBCYXNlQ29tcG9uZW50O1xuXG59KSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1iYXNlLWNvbXBvbmVudC5qcy5tYXBcbiIsIi8qIVxuICAqIEJvb3RzdHJhcCBjb2xsYXBzZS5qcyB2NS4yLjAgKGh0dHBzOi8vZ2V0Ym9vdHN0cmFwLmNvbS8pXG4gICogQ29weXJpZ2h0IDIwMTEtMjAyMiBUaGUgQm9vdHN0cmFwIEF1dGhvcnMgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ncmFwaHMvY29udHJpYnV0b3JzKVxuICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAqL1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoJy4vdXRpbC9pbmRleCcpLCByZXF1aXJlKCcuL2RvbS9ldmVudC1oYW5kbGVyJyksIHJlcXVpcmUoJy4vZG9tL3NlbGVjdG9yLWVuZ2luZScpLCByZXF1aXJlKCcuL2Jhc2UtY29tcG9uZW50JykpIDpcbiAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi91dGlsL2luZGV4JywgJy4vZG9tL2V2ZW50LWhhbmRsZXInLCAnLi9kb20vc2VsZWN0b3ItZW5naW5lJywgJy4vYmFzZS1jb21wb25lbnQnXSwgZmFjdG9yeSkgOlxuICAoZ2xvYmFsID0gdHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsVGhpcyA6IGdsb2JhbCB8fCBzZWxmLCBnbG9iYWwuQ29sbGFwc2UgPSBmYWN0b3J5KGdsb2JhbC5JbmRleCwgZ2xvYmFsLkV2ZW50SGFuZGxlciwgZ2xvYmFsLlNlbGVjdG9yRW5naW5lLCBnbG9iYWwuQmFzZUNvbXBvbmVudCkpO1xufSkodGhpcywgKGZ1bmN0aW9uIChpbmRleCwgRXZlbnRIYW5kbGVyLCBTZWxlY3RvckVuZ2luZSwgQmFzZUNvbXBvbmVudCkgeyAndXNlIHN0cmljdCc7XG5cbiAgY29uc3QgX2ludGVyb3BEZWZhdWx0TGVnYWN5ID0gZSA9PiBlICYmIHR5cGVvZiBlID09PSAnb2JqZWN0JyAmJiAnZGVmYXVsdCcgaW4gZSA/IGUgOiB7IGRlZmF1bHQ6IGUgfTtcblxuICBjb25zdCBFdmVudEhhbmRsZXJfX2RlZmF1bHQgPSAvKiNfX1BVUkVfXyovX2ludGVyb3BEZWZhdWx0TGVnYWN5KEV2ZW50SGFuZGxlcik7XG4gIGNvbnN0IFNlbGVjdG9yRW5naW5lX19kZWZhdWx0ID0gLyojX19QVVJFX18qL19pbnRlcm9wRGVmYXVsdExlZ2FjeShTZWxlY3RvckVuZ2luZSk7XG4gIGNvbnN0IEJhc2VDb21wb25lbnRfX2RlZmF1bHQgPSAvKiNfX1BVUkVfXyovX2ludGVyb3BEZWZhdWx0TGVnYWN5KEJhc2VDb21wb25lbnQpO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY1LjIuMCk6IGNvbGxhcHNlLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgLyoqXG4gICAqIENvbnN0YW50c1xuICAgKi9cblxuICBjb25zdCBOQU1FID0gJ2NvbGxhcHNlJztcbiAgY29uc3QgREFUQV9LRVkgPSAnYnMuY29sbGFwc2UnO1xuICBjb25zdCBFVkVOVF9LRVkgPSBgLiR7REFUQV9LRVl9YDtcbiAgY29uc3QgREFUQV9BUElfS0VZID0gJy5kYXRhLWFwaSc7XG4gIGNvbnN0IEVWRU5UX1NIT1cgPSBgc2hvdyR7RVZFTlRfS0VZfWA7XG4gIGNvbnN0IEVWRU5UX1NIT1dOID0gYHNob3duJHtFVkVOVF9LRVl9YDtcbiAgY29uc3QgRVZFTlRfSElERSA9IGBoaWRlJHtFVkVOVF9LRVl9YDtcbiAgY29uc3QgRVZFTlRfSElEREVOID0gYGhpZGRlbiR7RVZFTlRfS0VZfWA7XG4gIGNvbnN0IEVWRU5UX0NMSUNLX0RBVEFfQVBJID0gYGNsaWNrJHtFVkVOVF9LRVl9JHtEQVRBX0FQSV9LRVl9YDtcbiAgY29uc3QgQ0xBU1NfTkFNRV9TSE9XID0gJ3Nob3cnO1xuICBjb25zdCBDTEFTU19OQU1FX0NPTExBUFNFID0gJ2NvbGxhcHNlJztcbiAgY29uc3QgQ0xBU1NfTkFNRV9DT0xMQVBTSU5HID0gJ2NvbGxhcHNpbmcnO1xuICBjb25zdCBDTEFTU19OQU1FX0NPTExBUFNFRCA9ICdjb2xsYXBzZWQnO1xuICBjb25zdCBDTEFTU19OQU1FX0RFRVBFUl9DSElMRFJFTiA9IGA6c2NvcGUgLiR7Q0xBU1NfTkFNRV9DT0xMQVBTRX0gLiR7Q0xBU1NfTkFNRV9DT0xMQVBTRX1gO1xuICBjb25zdCBDTEFTU19OQU1FX0hPUklaT05UQUwgPSAnY29sbGFwc2UtaG9yaXpvbnRhbCc7XG4gIGNvbnN0IFdJRFRIID0gJ3dpZHRoJztcbiAgY29uc3QgSEVJR0hUID0gJ2hlaWdodCc7XG4gIGNvbnN0IFNFTEVDVE9SX0FDVElWRVMgPSAnLmNvbGxhcHNlLnNob3csIC5jb2xsYXBzZS5jb2xsYXBzaW5nJztcbiAgY29uc3QgU0VMRUNUT1JfREFUQV9UT0dHTEUgPSAnW2RhdGEtYnMtdG9nZ2xlPVwiY29sbGFwc2VcIl0nO1xuICBjb25zdCBEZWZhdWx0ID0ge1xuICAgIHBhcmVudDogbnVsbCxcbiAgICB0b2dnbGU6IHRydWVcbiAgfTtcbiAgY29uc3QgRGVmYXVsdFR5cGUgPSB7XG4gICAgcGFyZW50OiAnKG51bGx8ZWxlbWVudCknLFxuICAgIHRvZ2dsZTogJ2Jvb2xlYW4nXG4gIH07XG4gIC8qKlxuICAgKiBDbGFzcyBkZWZpbml0aW9uXG4gICAqL1xuXG4gIGNsYXNzIENvbGxhcHNlIGV4dGVuZHMgQmFzZUNvbXBvbmVudF9fZGVmYXVsdC5kZWZhdWx0IHtcbiAgICBjb25zdHJ1Y3RvcihlbGVtZW50LCBjb25maWcpIHtcbiAgICAgIHN1cGVyKGVsZW1lbnQsIGNvbmZpZyk7XG4gICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSBmYWxzZTtcbiAgICAgIHRoaXMuX3RyaWdnZXJBcnJheSA9IFtdO1xuICAgICAgY29uc3QgdG9nZ2xlTGlzdCA9IFNlbGVjdG9yRW5naW5lX19kZWZhdWx0LmRlZmF1bHQuZmluZChTRUxFQ1RPUl9EQVRBX1RPR0dMRSk7XG5cbiAgICAgIGZvciAoY29uc3QgZWxlbSBvZiB0b2dnbGVMaXN0KSB7XG4gICAgICAgIGNvbnN0IHNlbGVjdG9yID0gaW5kZXguZ2V0U2VsZWN0b3JGcm9tRWxlbWVudChlbGVtKTtcbiAgICAgICAgY29uc3QgZmlsdGVyRWxlbWVudCA9IFNlbGVjdG9yRW5naW5lX19kZWZhdWx0LmRlZmF1bHQuZmluZChzZWxlY3RvcikuZmlsdGVyKGZvdW5kRWxlbWVudCA9PiBmb3VuZEVsZW1lbnQgPT09IHRoaXMuX2VsZW1lbnQpO1xuXG4gICAgICAgIGlmIChzZWxlY3RvciAhPT0gbnVsbCAmJiBmaWx0ZXJFbGVtZW50Lmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMuX3RyaWdnZXJBcnJheS5wdXNoKGVsZW0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2luaXRpYWxpemVDaGlsZHJlbigpO1xuXG4gICAgICBpZiAoIXRoaXMuX2NvbmZpZy5wYXJlbnQpIHtcbiAgICAgICAgdGhpcy5fYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzKHRoaXMuX3RyaWdnZXJBcnJheSwgdGhpcy5faXNTaG93bigpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2NvbmZpZy50b2dnbGUpIHtcbiAgICAgICAgdGhpcy50b2dnbGUoKTtcbiAgICAgIH1cbiAgICB9IC8vIEdldHRlcnNcblxuXG4gICAgc3RhdGljIGdldCBEZWZhdWx0KCkge1xuICAgICAgcmV0dXJuIERlZmF1bHQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldCBEZWZhdWx0VHlwZSgpIHtcbiAgICAgIHJldHVybiBEZWZhdWx0VHlwZTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0IE5BTUUoKSB7XG4gICAgICByZXR1cm4gTkFNRTtcbiAgICB9IC8vIFB1YmxpY1xuXG5cbiAgICB0b2dnbGUoKSB7XG4gICAgICBpZiAodGhpcy5faXNTaG93bigpKSB7XG4gICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgc2hvdygpIHtcbiAgICAgIGlmICh0aGlzLl9pc1RyYW5zaXRpb25pbmcgfHwgdGhpcy5faXNTaG93bigpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgbGV0IGFjdGl2ZUNoaWxkcmVuID0gW107IC8vIGZpbmQgYWN0aXZlIGNoaWxkcmVuXG5cbiAgICAgIGlmICh0aGlzLl9jb25maWcucGFyZW50KSB7XG4gICAgICAgIGFjdGl2ZUNoaWxkcmVuID0gdGhpcy5fZ2V0Rmlyc3RMZXZlbENoaWxkcmVuKFNFTEVDVE9SX0FDVElWRVMpLmZpbHRlcihlbGVtZW50ID0+IGVsZW1lbnQgIT09IHRoaXMuX2VsZW1lbnQpLm1hcChlbGVtZW50ID0+IENvbGxhcHNlLmdldE9yQ3JlYXRlSW5zdGFuY2UoZWxlbWVudCwge1xuICAgICAgICAgIHRvZ2dsZTogZmFsc2VcbiAgICAgICAgfSkpO1xuICAgICAgfVxuXG4gICAgICBpZiAoYWN0aXZlQ2hpbGRyZW4ubGVuZ3RoICYmIGFjdGl2ZUNoaWxkcmVuWzBdLl9pc1RyYW5zaXRpb25pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdGFydEV2ZW50ID0gRXZlbnRIYW5kbGVyX19kZWZhdWx0LmRlZmF1bHQudHJpZ2dlcih0aGlzLl9lbGVtZW50LCBFVkVOVF9TSE9XKTtcblxuICAgICAgaWYgKHN0YXJ0RXZlbnQuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgYWN0aXZlSW5zdGFuY2Ugb2YgYWN0aXZlQ2hpbGRyZW4pIHtcbiAgICAgICAgYWN0aXZlSW5zdGFuY2UuaGlkZSgpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLl9nZXREaW1lbnNpb24oKTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKENMQVNTX05BTUVfQ09MTEFQU0UpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9DT0xMQVBTSU5HKTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZVtkaW1lbnNpb25dID0gMDtcblxuICAgICAgdGhpcy5fYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzKHRoaXMuX3RyaWdnZXJBcnJheSwgdHJ1ZSk7XG5cbiAgICAgIHRoaXMuX2lzVHJhbnNpdGlvbmluZyA9IHRydWU7XG5cbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gKCkgPT4ge1xuICAgICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoQ0xBU1NfTkFNRV9DT0xMQVBTSU5HKTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9DT0xMQVBTRSwgQ0xBU1NfTkFNRV9TSE9XKTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSAnJztcbiAgICAgICAgRXZlbnRIYW5kbGVyX19kZWZhdWx0LmRlZmF1bHQudHJpZ2dlcih0aGlzLl9lbGVtZW50LCBFVkVOVF9TSE9XTik7XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBjYXBpdGFsaXplZERpbWVuc2lvbiA9IGRpbWVuc2lvblswXS50b1VwcGVyQ2FzZSgpICsgZGltZW5zaW9uLnNsaWNlKDEpO1xuICAgICAgY29uc3Qgc2Nyb2xsU2l6ZSA9IGBzY3JvbGwke2NhcGl0YWxpemVkRGltZW5zaW9ufWA7XG5cbiAgICAgIHRoaXMuX3F1ZXVlQ2FsbGJhY2soY29tcGxldGUsIHRoaXMuX2VsZW1lbnQsIHRydWUpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSBgJHt0aGlzLl9lbGVtZW50W3Njcm9sbFNpemVdfXB4YDtcbiAgICB9XG5cbiAgICBoaWRlKCkge1xuICAgICAgaWYgKHRoaXMuX2lzVHJhbnNpdGlvbmluZyB8fCAhdGhpcy5faXNTaG93bigpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RhcnRFdmVudCA9IEV2ZW50SGFuZGxlcl9fZGVmYXVsdC5kZWZhdWx0LnRyaWdnZXIodGhpcy5fZWxlbWVudCwgRVZFTlRfSElERSk7XG5cbiAgICAgIGlmIChzdGFydEV2ZW50LmRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLl9nZXREaW1lbnNpb24oKTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZVtkaW1lbnNpb25dID0gYCR7dGhpcy5fZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVtkaW1lbnNpb25dfXB4YDtcbiAgICAgIGluZGV4LnJlZmxvdyh0aGlzLl9lbGVtZW50KTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuYWRkKENMQVNTX05BTUVfQ09MTEFQU0lORyk7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShDTEFTU19OQU1FX0NPTExBUFNFLCBDTEFTU19OQU1FX1NIT1cpO1xuXG4gICAgICBmb3IgKGNvbnN0IHRyaWdnZXIgb2YgdGhpcy5fdHJpZ2dlckFycmF5KSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSBpbmRleC5nZXRFbGVtZW50RnJvbVNlbGVjdG9yKHRyaWdnZXIpO1xuXG4gICAgICAgIGlmIChlbGVtZW50ICYmICF0aGlzLl9pc1Nob3duKGVsZW1lbnQpKSB7XG4gICAgICAgICAgdGhpcy5fYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzKFt0cmlnZ2VyXSwgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2lzVHJhbnNpdGlvbmluZyA9IHRydWU7XG5cbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gKCkgPT4ge1xuICAgICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoQ0xBU1NfTkFNRV9DT0xMQVBTSU5HKTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5hZGQoQ0xBU1NfTkFNRV9DT0xMQVBTRSk7XG5cbiAgICAgICAgRXZlbnRIYW5kbGVyX19kZWZhdWx0LmRlZmF1bHQudHJpZ2dlcih0aGlzLl9lbGVtZW50LCBFVkVOVF9ISURERU4pO1xuICAgICAgfTtcblxuICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZVtkaW1lbnNpb25dID0gJyc7XG5cbiAgICAgIHRoaXMuX3F1ZXVlQ2FsbGJhY2soY29tcGxldGUsIHRoaXMuX2VsZW1lbnQsIHRydWUpO1xuICAgIH1cblxuICAgIF9pc1Nob3duKGVsZW1lbnQgPSB0aGlzLl9lbGVtZW50KSB7XG4gICAgICByZXR1cm4gZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9TSE9XKTtcbiAgICB9IC8vIFByaXZhdGVcblxuXG4gICAgX2NvbmZpZ0FmdGVyTWVyZ2UoY29uZmlnKSB7XG4gICAgICBjb25maWcudG9nZ2xlID0gQm9vbGVhbihjb25maWcudG9nZ2xlKTsgLy8gQ29lcmNlIHN0cmluZyB2YWx1ZXNcblxuICAgICAgY29uZmlnLnBhcmVudCA9IGluZGV4LmdldEVsZW1lbnQoY29uZmlnLnBhcmVudCk7XG4gICAgICByZXR1cm4gY29uZmlnO1xuICAgIH1cblxuICAgIF9nZXREaW1lbnNpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfTkFNRV9IT1JJWk9OVEFMKSA/IFdJRFRIIDogSEVJR0hUO1xuICAgIH1cblxuICAgIF9pbml0aWFsaXplQ2hpbGRyZW4oKSB7XG4gICAgICBpZiAoIXRoaXMuX2NvbmZpZy5wYXJlbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjaGlsZHJlbiA9IHRoaXMuX2dldEZpcnN0TGV2ZWxDaGlsZHJlbihTRUxFQ1RPUl9EQVRBX1RPR0dMRSk7XG5cbiAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBjaGlsZHJlbikge1xuICAgICAgICBjb25zdCBzZWxlY3RlZCA9IGluZGV4LmdldEVsZW1lbnRGcm9tU2VsZWN0b3IoZWxlbWVudCk7XG5cbiAgICAgICAgaWYgKHNlbGVjdGVkKSB7XG4gICAgICAgICAgdGhpcy5fYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzKFtlbGVtZW50XSwgdGhpcy5faXNTaG93bihzZWxlY3RlZCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgX2dldEZpcnN0TGV2ZWxDaGlsZHJlbihzZWxlY3Rvcikge1xuICAgICAgY29uc3QgY2hpbGRyZW4gPSBTZWxlY3RvckVuZ2luZV9fZGVmYXVsdC5kZWZhdWx0LmZpbmQoQ0xBU1NfTkFNRV9ERUVQRVJfQ0hJTERSRU4sIHRoaXMuX2NvbmZpZy5wYXJlbnQpOyAvLyByZW1vdmUgY2hpbGRyZW4gaWYgZ3JlYXRlciBkZXB0aFxuXG4gICAgICByZXR1cm4gU2VsZWN0b3JFbmdpbmVfX2RlZmF1bHQuZGVmYXVsdC5maW5kKHNlbGVjdG9yLCB0aGlzLl9jb25maWcucGFyZW50KS5maWx0ZXIoZWxlbWVudCA9PiAhY2hpbGRyZW4uaW5jbHVkZXMoZWxlbWVudCkpO1xuICAgIH1cblxuICAgIF9hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3ModHJpZ2dlckFycmF5LCBpc09wZW4pIHtcbiAgICAgIGlmICghdHJpZ2dlckFycmF5Lmxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiB0cmlnZ2VyQXJyYXkpIHtcbiAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QudG9nZ2xlKENMQVNTX05BTUVfQ09MTEFQU0VELCAhaXNPcGVuKTtcbiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCBpc09wZW4pO1xuICAgICAgfVxuICAgIH0gLy8gU3RhdGljXG5cblxuICAgIHN0YXRpYyBqUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICBjb25zdCBfY29uZmlnID0ge307XG5cbiAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJyAmJiAvc2hvd3xoaWRlLy50ZXN0KGNvbmZpZykpIHtcbiAgICAgICAgX2NvbmZpZy50b2dnbGUgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBDb2xsYXBzZS5nZXRPckNyZWF0ZUluc3RhbmNlKHRoaXMsIF9jb25maWcpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YVtjb25maWddID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgTm8gbWV0aG9kIG5hbWVkIFwiJHtjb25maWd9XCJgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBkYXRhW2NvbmZpZ10oKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gIH1cbiAgLyoqXG4gICAqIERhdGEgQVBJIGltcGxlbWVudGF0aW9uXG4gICAqL1xuXG5cbiAgRXZlbnRIYW5kbGVyX19kZWZhdWx0LmRlZmF1bHQub24oZG9jdW1lbnQsIEVWRU5UX0NMSUNLX0RBVEFfQVBJLCBTRUxFQ1RPUl9EQVRBX1RPR0dMRSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgLy8gcHJldmVudERlZmF1bHQgb25seSBmb3IgPGE+IGVsZW1lbnRzICh3aGljaCBjaGFuZ2UgdGhlIFVSTCkgbm90IGluc2lkZSB0aGUgY29sbGFwc2libGUgZWxlbWVudFxuICAgIGlmIChldmVudC50YXJnZXQudGFnTmFtZSA9PT0gJ0EnIHx8IGV2ZW50LmRlbGVnYXRlVGFyZ2V0ICYmIGV2ZW50LmRlbGVnYXRlVGFyZ2V0LnRhZ05hbWUgPT09ICdBJykge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICBjb25zdCBzZWxlY3RvciA9IGluZGV4LmdldFNlbGVjdG9yRnJvbUVsZW1lbnQodGhpcyk7XG4gICAgY29uc3Qgc2VsZWN0b3JFbGVtZW50cyA9IFNlbGVjdG9yRW5naW5lX19kZWZhdWx0LmRlZmF1bHQuZmluZChzZWxlY3Rvcik7XG5cbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2Ygc2VsZWN0b3JFbGVtZW50cykge1xuICAgICAgQ29sbGFwc2UuZ2V0T3JDcmVhdGVJbnN0YW5jZShlbGVtZW50LCB7XG4gICAgICAgIHRvZ2dsZTogZmFsc2VcbiAgICAgIH0pLnRvZ2dsZSgpO1xuICAgIH1cbiAgfSk7XG4gIC8qKlxuICAgKiBqUXVlcnlcbiAgICovXG5cbiAgaW5kZXguZGVmaW5lSlF1ZXJ5UGx1Z2luKENvbGxhcHNlKTtcblxuICByZXR1cm4gQ29sbGFwc2U7XG5cbn0pKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWNvbGxhcHNlLmpzLm1hcFxuIiwiLyohXG4gICogQm9vdHN0cmFwIGRhdGEuanMgdjUuMi4wIChodHRwczovL2dldGJvb3RzdHJhcC5jb20vKVxuICAqIENvcHlyaWdodCAyMDExLTIwMjIgVGhlIEJvb3RzdHJhcCBBdXRob3JzIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvZ3JhcGhzL2NvbnRyaWJ1dG9ycylcbiAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgKi9cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpIDpcbiAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKGZhY3RvcnkpIDpcbiAgKGdsb2JhbCA9IHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbFRoaXMgOiBnbG9iYWwgfHwgc2VsZiwgZ2xvYmFsLkRhdGEgPSBmYWN0b3J5KCkpO1xufSkodGhpcywgKGZ1bmN0aW9uICgpIHsgJ3VzZSBzdHJpY3QnO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY1LjIuMCk6IGRvbS9kYXRhLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICAvKipcbiAgICogQ29uc3RhbnRzXG4gICAqL1xuICBjb25zdCBlbGVtZW50TWFwID0gbmV3IE1hcCgpO1xuICBjb25zdCBkYXRhID0ge1xuICAgIHNldChlbGVtZW50LCBrZXksIGluc3RhbmNlKSB7XG4gICAgICBpZiAoIWVsZW1lbnRNYXAuaGFzKGVsZW1lbnQpKSB7XG4gICAgICAgIGVsZW1lbnRNYXAuc2V0KGVsZW1lbnQsIG5ldyBNYXAoKSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGluc3RhbmNlTWFwID0gZWxlbWVudE1hcC5nZXQoZWxlbWVudCk7IC8vIG1ha2UgaXQgY2xlYXIgd2Ugb25seSB3YW50IG9uZSBpbnN0YW5jZSBwZXIgZWxlbWVudFxuICAgICAgLy8gY2FuIGJlIHJlbW92ZWQgbGF0ZXIgd2hlbiBtdWx0aXBsZSBrZXkvaW5zdGFuY2VzIGFyZSBmaW5lIHRvIGJlIHVzZWRcblxuICAgICAgaWYgKCFpbnN0YW5jZU1hcC5oYXMoa2V5KSAmJiBpbnN0YW5jZU1hcC5zaXplICE9PSAwKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYEJvb3RzdHJhcCBkb2Vzbid0IGFsbG93IG1vcmUgdGhhbiBvbmUgaW5zdGFuY2UgcGVyIGVsZW1lbnQuIEJvdW5kIGluc3RhbmNlOiAke0FycmF5LmZyb20oaW5zdGFuY2VNYXAua2V5cygpKVswXX0uYCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaW5zdGFuY2VNYXAuc2V0KGtleSwgaW5zdGFuY2UpO1xuICAgIH0sXG5cbiAgICBnZXQoZWxlbWVudCwga2V5KSB7XG4gICAgICBpZiAoZWxlbWVudE1hcC5oYXMoZWxlbWVudCkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnRNYXAuZ2V0KGVsZW1lbnQpLmdldChrZXkpIHx8IG51bGw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0sXG5cbiAgICByZW1vdmUoZWxlbWVudCwga2V5KSB7XG4gICAgICBpZiAoIWVsZW1lbnRNYXAuaGFzKGVsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaW5zdGFuY2VNYXAgPSBlbGVtZW50TWFwLmdldChlbGVtZW50KTtcbiAgICAgIGluc3RhbmNlTWFwLmRlbGV0ZShrZXkpOyAvLyBmcmVlIHVwIGVsZW1lbnQgcmVmZXJlbmNlcyBpZiB0aGVyZSBhcmUgbm8gaW5zdGFuY2VzIGxlZnQgZm9yIGFuIGVsZW1lbnRcblxuICAgICAgaWYgKGluc3RhbmNlTWFwLnNpemUgPT09IDApIHtcbiAgICAgICAgZWxlbWVudE1hcC5kZWxldGUoZWxlbWVudCk7XG4gICAgICB9XG4gICAgfVxuXG4gIH07XG5cbiAgcmV0dXJuIGRhdGE7XG5cbn0pKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGEuanMubWFwXG4iLCIvKiFcbiAgKiBCb290c3RyYXAgZXZlbnQtaGFuZGxlci5qcyB2NS4yLjAgKGh0dHBzOi8vZ2V0Ym9vdHN0cmFwLmNvbS8pXG4gICogQ29weXJpZ2h0IDIwMTEtMjAyMiBUaGUgQm9vdHN0cmFwIEF1dGhvcnMgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ncmFwaHMvY29udHJpYnV0b3JzKVxuICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAqL1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoJy4uL3V0aWwvaW5kZXgnKSkgOlxuICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi91dGlsL2luZGV4J10sIGZhY3RvcnkpIDpcbiAgKGdsb2JhbCA9IHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbFRoaXMgOiBnbG9iYWwgfHwgc2VsZiwgZ2xvYmFsLkV2ZW50SGFuZGxlciA9IGZhY3RvcnkoZ2xvYmFsLkluZGV4KSk7XG59KSh0aGlzLCAoZnVuY3Rpb24gKGluZGV4KSB7ICd1c2Ugc3RyaWN0JztcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NS4yLjApOiBkb20vZXZlbnQtaGFuZGxlci5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIC8qKlxuICAgKiBDb25zdGFudHNcbiAgICovXG5cbiAgY29uc3QgbmFtZXNwYWNlUmVnZXggPSAvW14uXSooPz1cXC4uKilcXC58LiovO1xuICBjb25zdCBzdHJpcE5hbWVSZWdleCA9IC9cXC4uKi87XG4gIGNvbnN0IHN0cmlwVWlkUmVnZXggPSAvOjpcXGQrJC87XG4gIGNvbnN0IGV2ZW50UmVnaXN0cnkgPSB7fTsgLy8gRXZlbnRzIHN0b3JhZ2VcblxuICBsZXQgdWlkRXZlbnQgPSAxO1xuICBjb25zdCBjdXN0b21FdmVudHMgPSB7XG4gICAgbW91c2VlbnRlcjogJ21vdXNlb3ZlcicsXG4gICAgbW91c2VsZWF2ZTogJ21vdXNlb3V0J1xuICB9O1xuICBjb25zdCBuYXRpdmVFdmVudHMgPSBuZXcgU2V0KFsnY2xpY2snLCAnZGJsY2xpY2snLCAnbW91c2V1cCcsICdtb3VzZWRvd24nLCAnY29udGV4dG1lbnUnLCAnbW91c2V3aGVlbCcsICdET01Nb3VzZVNjcm9sbCcsICdtb3VzZW92ZXInLCAnbW91c2VvdXQnLCAnbW91c2Vtb3ZlJywgJ3NlbGVjdHN0YXJ0JywgJ3NlbGVjdGVuZCcsICdrZXlkb3duJywgJ2tleXByZXNzJywgJ2tleXVwJywgJ29yaWVudGF0aW9uY2hhbmdlJywgJ3RvdWNoc3RhcnQnLCAndG91Y2htb3ZlJywgJ3RvdWNoZW5kJywgJ3RvdWNoY2FuY2VsJywgJ3BvaW50ZXJkb3duJywgJ3BvaW50ZXJtb3ZlJywgJ3BvaW50ZXJ1cCcsICdwb2ludGVybGVhdmUnLCAncG9pbnRlcmNhbmNlbCcsICdnZXN0dXJlc3RhcnQnLCAnZ2VzdHVyZWNoYW5nZScsICdnZXN0dXJlZW5kJywgJ2ZvY3VzJywgJ2JsdXInLCAnY2hhbmdlJywgJ3Jlc2V0JywgJ3NlbGVjdCcsICdzdWJtaXQnLCAnZm9jdXNpbicsICdmb2N1c291dCcsICdsb2FkJywgJ3VubG9hZCcsICdiZWZvcmV1bmxvYWQnLCAncmVzaXplJywgJ21vdmUnLCAnRE9NQ29udGVudExvYWRlZCcsICdyZWFkeXN0YXRlY2hhbmdlJywgJ2Vycm9yJywgJ2Fib3J0JywgJ3Njcm9sbCddKTtcbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kc1xuICAgKi9cblxuICBmdW5jdGlvbiBtYWtlRXZlbnRVaWQoZWxlbWVudCwgdWlkKSB7XG4gICAgcmV0dXJuIHVpZCAmJiBgJHt1aWR9Ojoke3VpZEV2ZW50Kyt9YCB8fCBlbGVtZW50LnVpZEV2ZW50IHx8IHVpZEV2ZW50Kys7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRFbGVtZW50RXZlbnRzKGVsZW1lbnQpIHtcbiAgICBjb25zdCB1aWQgPSBtYWtlRXZlbnRVaWQoZWxlbWVudCk7XG4gICAgZWxlbWVudC51aWRFdmVudCA9IHVpZDtcbiAgICBldmVudFJlZ2lzdHJ5W3VpZF0gPSBldmVudFJlZ2lzdHJ5W3VpZF0gfHwge307XG4gICAgcmV0dXJuIGV2ZW50UmVnaXN0cnlbdWlkXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGJvb3RzdHJhcEhhbmRsZXIoZWxlbWVudCwgZm4pIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gaGFuZGxlcihldmVudCkge1xuICAgICAgaHlkcmF0ZU9iaihldmVudCwge1xuICAgICAgICBkZWxlZ2F0ZVRhcmdldDogZWxlbWVudFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChoYW5kbGVyLm9uZU9mZikge1xuICAgICAgICBFdmVudEhhbmRsZXIub2ZmKGVsZW1lbnQsIGV2ZW50LnR5cGUsIGZuKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGZuLmFwcGx5KGVsZW1lbnQsIFtldmVudF0pO1xuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBib290c3RyYXBEZWxlZ2F0aW9uSGFuZGxlcihlbGVtZW50LCBzZWxlY3RvciwgZm4pIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gaGFuZGxlcihldmVudCkge1xuICAgICAgY29uc3QgZG9tRWxlbWVudHMgPSBlbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpO1xuXG4gICAgICBmb3IgKGxldCB7XG4gICAgICAgIHRhcmdldFxuICAgICAgfSA9IGV2ZW50OyB0YXJnZXQgJiYgdGFyZ2V0ICE9PSB0aGlzOyB0YXJnZXQgPSB0YXJnZXQucGFyZW50Tm9kZSkge1xuICAgICAgICBmb3IgKGNvbnN0IGRvbUVsZW1lbnQgb2YgZG9tRWxlbWVudHMpIHtcbiAgICAgICAgICBpZiAoZG9tRWxlbWVudCAhPT0gdGFyZ2V0KSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBoeWRyYXRlT2JqKGV2ZW50LCB7XG4gICAgICAgICAgICBkZWxlZ2F0ZVRhcmdldDogdGFyZ2V0XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAoaGFuZGxlci5vbmVPZmYpIHtcbiAgICAgICAgICAgIEV2ZW50SGFuZGxlci5vZmYoZWxlbWVudCwgZXZlbnQudHlwZSwgc2VsZWN0b3IsIGZuKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gZm4uYXBwbHkodGFyZ2V0LCBbZXZlbnRdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBmaW5kSGFuZGxlcihldmVudHMsIGNhbGxhYmxlLCBkZWxlZ2F0aW9uU2VsZWN0b3IgPSBudWxsKSB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXMoZXZlbnRzKS5maW5kKGV2ZW50ID0+IGV2ZW50LmNhbGxhYmxlID09PSBjYWxsYWJsZSAmJiBldmVudC5kZWxlZ2F0aW9uU2VsZWN0b3IgPT09IGRlbGVnYXRpb25TZWxlY3Rvcik7XG4gIH1cblxuICBmdW5jdGlvbiBub3JtYWxpemVQYXJhbWV0ZXJzKG9yaWdpbmFsVHlwZUV2ZW50LCBoYW5kbGVyLCBkZWxlZ2F0aW9uRnVuY3Rpb24pIHtcbiAgICBjb25zdCBpc0RlbGVnYXRlZCA9IHR5cGVvZiBoYW5kbGVyID09PSAnc3RyaW5nJzsgLy8gdG9kbzogdG9vbHRpcCBwYXNzZXMgYGZhbHNlYCBpbnN0ZWFkIG9mIHNlbGVjdG9yLCBzbyB3ZSBuZWVkIHRvIGNoZWNrXG5cbiAgICBjb25zdCBjYWxsYWJsZSA9IGlzRGVsZWdhdGVkID8gZGVsZWdhdGlvbkZ1bmN0aW9uIDogaGFuZGxlciB8fCBkZWxlZ2F0aW9uRnVuY3Rpb247XG4gICAgbGV0IHR5cGVFdmVudCA9IGdldFR5cGVFdmVudChvcmlnaW5hbFR5cGVFdmVudCk7XG5cbiAgICBpZiAoIW5hdGl2ZUV2ZW50cy5oYXModHlwZUV2ZW50KSkge1xuICAgICAgdHlwZUV2ZW50ID0gb3JpZ2luYWxUeXBlRXZlbnQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIFtpc0RlbGVnYXRlZCwgY2FsbGFibGUsIHR5cGVFdmVudF07XG4gIH1cblxuICBmdW5jdGlvbiBhZGRIYW5kbGVyKGVsZW1lbnQsIG9yaWdpbmFsVHlwZUV2ZW50LCBoYW5kbGVyLCBkZWxlZ2F0aW9uRnVuY3Rpb24sIG9uZU9mZikge1xuICAgIGlmICh0eXBlb2Ygb3JpZ2luYWxUeXBlRXZlbnQgIT09ICdzdHJpbmcnIHx8ICFlbGVtZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IFtpc0RlbGVnYXRlZCwgY2FsbGFibGUsIHR5cGVFdmVudF0gPSBub3JtYWxpemVQYXJhbWV0ZXJzKG9yaWdpbmFsVHlwZUV2ZW50LCBoYW5kbGVyLCBkZWxlZ2F0aW9uRnVuY3Rpb24pOyAvLyBpbiBjYXNlIG9mIG1vdXNlZW50ZXIgb3IgbW91c2VsZWF2ZSB3cmFwIHRoZSBoYW5kbGVyIHdpdGhpbiBhIGZ1bmN0aW9uIHRoYXQgY2hlY2tzIGZvciBpdHMgRE9NIHBvc2l0aW9uXG4gICAgLy8gdGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRpc3BhdGNoZWQgdGhlIHNhbWUgd2F5IGFzIG1vdXNlb3ZlciBvciBtb3VzZW91dCBkb2VzXG5cbiAgICBpZiAob3JpZ2luYWxUeXBlRXZlbnQgaW4gY3VzdG9tRXZlbnRzKSB7XG4gICAgICBjb25zdCB3cmFwRnVuY3Rpb24gPSBmbiA9PiB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICBpZiAoIWV2ZW50LnJlbGF0ZWRUYXJnZXQgfHwgZXZlbnQucmVsYXRlZFRhcmdldCAhPT0gZXZlbnQuZGVsZWdhdGVUYXJnZXQgJiYgIWV2ZW50LmRlbGVnYXRlVGFyZ2V0LmNvbnRhaW5zKGV2ZW50LnJlbGF0ZWRUYXJnZXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gZm4uY2FsbCh0aGlzLCBldmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfTtcblxuICAgICAgY2FsbGFibGUgPSB3cmFwRnVuY3Rpb24oY2FsbGFibGUpO1xuICAgIH1cblxuICAgIGNvbnN0IGV2ZW50cyA9IGdldEVsZW1lbnRFdmVudHMoZWxlbWVudCk7XG4gICAgY29uc3QgaGFuZGxlcnMgPSBldmVudHNbdHlwZUV2ZW50XSB8fCAoZXZlbnRzW3R5cGVFdmVudF0gPSB7fSk7XG4gICAgY29uc3QgcHJldmlvdXNGdW5jdGlvbiA9IGZpbmRIYW5kbGVyKGhhbmRsZXJzLCBjYWxsYWJsZSwgaXNEZWxlZ2F0ZWQgPyBoYW5kbGVyIDogbnVsbCk7XG5cbiAgICBpZiAocHJldmlvdXNGdW5jdGlvbikge1xuICAgICAgcHJldmlvdXNGdW5jdGlvbi5vbmVPZmYgPSBwcmV2aW91c0Z1bmN0aW9uLm9uZU9mZiAmJiBvbmVPZmY7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdWlkID0gbWFrZUV2ZW50VWlkKGNhbGxhYmxlLCBvcmlnaW5hbFR5cGVFdmVudC5yZXBsYWNlKG5hbWVzcGFjZVJlZ2V4LCAnJykpO1xuICAgIGNvbnN0IGZuID0gaXNEZWxlZ2F0ZWQgPyBib290c3RyYXBEZWxlZ2F0aW9uSGFuZGxlcihlbGVtZW50LCBoYW5kbGVyLCBjYWxsYWJsZSkgOiBib290c3RyYXBIYW5kbGVyKGVsZW1lbnQsIGNhbGxhYmxlKTtcbiAgICBmbi5kZWxlZ2F0aW9uU2VsZWN0b3IgPSBpc0RlbGVnYXRlZCA/IGhhbmRsZXIgOiBudWxsO1xuICAgIGZuLmNhbGxhYmxlID0gY2FsbGFibGU7XG4gICAgZm4ub25lT2ZmID0gb25lT2ZmO1xuICAgIGZuLnVpZEV2ZW50ID0gdWlkO1xuICAgIGhhbmRsZXJzW3VpZF0gPSBmbjtcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIodHlwZUV2ZW50LCBmbiwgaXNEZWxlZ2F0ZWQpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtb3ZlSGFuZGxlcihlbGVtZW50LCBldmVudHMsIHR5cGVFdmVudCwgaGFuZGxlciwgZGVsZWdhdGlvblNlbGVjdG9yKSB7XG4gICAgY29uc3QgZm4gPSBmaW5kSGFuZGxlcihldmVudHNbdHlwZUV2ZW50XSwgaGFuZGxlciwgZGVsZWdhdGlvblNlbGVjdG9yKTtcblxuICAgIGlmICghZm4pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodHlwZUV2ZW50LCBmbiwgQm9vbGVhbihkZWxlZ2F0aW9uU2VsZWN0b3IpKTtcbiAgICBkZWxldGUgZXZlbnRzW3R5cGVFdmVudF1bZm4udWlkRXZlbnRdO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtb3ZlTmFtZXNwYWNlZEhhbmRsZXJzKGVsZW1lbnQsIGV2ZW50cywgdHlwZUV2ZW50LCBuYW1lc3BhY2UpIHtcbiAgICBjb25zdCBzdG9yZUVsZW1lbnRFdmVudCA9IGV2ZW50c1t0eXBlRXZlbnRdIHx8IHt9O1xuXG4gICAgZm9yIChjb25zdCBoYW5kbGVyS2V5IG9mIE9iamVjdC5rZXlzKHN0b3JlRWxlbWVudEV2ZW50KSkge1xuICAgICAgaWYgKGhhbmRsZXJLZXkuaW5jbHVkZXMobmFtZXNwYWNlKSkge1xuICAgICAgICBjb25zdCBldmVudCA9IHN0b3JlRWxlbWVudEV2ZW50W2hhbmRsZXJLZXldO1xuICAgICAgICByZW1vdmVIYW5kbGVyKGVsZW1lbnQsIGV2ZW50cywgdHlwZUV2ZW50LCBldmVudC5jYWxsYWJsZSwgZXZlbnQuZGVsZWdhdGlvblNlbGVjdG9yKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBnZXRUeXBlRXZlbnQoZXZlbnQpIHtcbiAgICAvLyBhbGxvdyB0byBnZXQgdGhlIG5hdGl2ZSBldmVudHMgZnJvbSBuYW1lc3BhY2VkIGV2ZW50cyAoJ2NsaWNrLmJzLmJ1dHRvbicgLS0+ICdjbGljaycpXG4gICAgZXZlbnQgPSBldmVudC5yZXBsYWNlKHN0cmlwTmFtZVJlZ2V4LCAnJyk7XG4gICAgcmV0dXJuIGN1c3RvbUV2ZW50c1tldmVudF0gfHwgZXZlbnQ7XG4gIH1cblxuICBjb25zdCBFdmVudEhhbmRsZXIgPSB7XG4gICAgb24oZWxlbWVudCwgZXZlbnQsIGhhbmRsZXIsIGRlbGVnYXRpb25GdW5jdGlvbikge1xuICAgICAgYWRkSGFuZGxlcihlbGVtZW50LCBldmVudCwgaGFuZGxlciwgZGVsZWdhdGlvbkZ1bmN0aW9uLCBmYWxzZSk7XG4gICAgfSxcblxuICAgIG9uZShlbGVtZW50LCBldmVudCwgaGFuZGxlciwgZGVsZWdhdGlvbkZ1bmN0aW9uKSB7XG4gICAgICBhZGRIYW5kbGVyKGVsZW1lbnQsIGV2ZW50LCBoYW5kbGVyLCBkZWxlZ2F0aW9uRnVuY3Rpb24sIHRydWUpO1xuICAgIH0sXG5cbiAgICBvZmYoZWxlbWVudCwgb3JpZ2luYWxUeXBlRXZlbnQsIGhhbmRsZXIsIGRlbGVnYXRpb25GdW5jdGlvbikge1xuICAgICAgaWYgKHR5cGVvZiBvcmlnaW5hbFR5cGVFdmVudCAhPT0gJ3N0cmluZycgfHwgIWVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBbaXNEZWxlZ2F0ZWQsIGNhbGxhYmxlLCB0eXBlRXZlbnRdID0gbm9ybWFsaXplUGFyYW1ldGVycyhvcmlnaW5hbFR5cGVFdmVudCwgaGFuZGxlciwgZGVsZWdhdGlvbkZ1bmN0aW9uKTtcbiAgICAgIGNvbnN0IGluTmFtZXNwYWNlID0gdHlwZUV2ZW50ICE9PSBvcmlnaW5hbFR5cGVFdmVudDtcbiAgICAgIGNvbnN0IGV2ZW50cyA9IGdldEVsZW1lbnRFdmVudHMoZWxlbWVudCk7XG4gICAgICBjb25zdCBzdG9yZUVsZW1lbnRFdmVudCA9IGV2ZW50c1t0eXBlRXZlbnRdIHx8IHt9O1xuICAgICAgY29uc3QgaXNOYW1lc3BhY2UgPSBvcmlnaW5hbFR5cGVFdmVudC5zdGFydHNXaXRoKCcuJyk7XG5cbiAgICAgIGlmICh0eXBlb2YgY2FsbGFibGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIC8vIFNpbXBsZXN0IGNhc2U6IGhhbmRsZXIgaXMgcGFzc2VkLCByZW1vdmUgdGhhdCBsaXN0ZW5lciBPTkxZLlxuICAgICAgICBpZiAoIU9iamVjdC5rZXlzKHN0b3JlRWxlbWVudEV2ZW50KS5sZW5ndGgpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICByZW1vdmVIYW5kbGVyKGVsZW1lbnQsIGV2ZW50cywgdHlwZUV2ZW50LCBjYWxsYWJsZSwgaXNEZWxlZ2F0ZWQgPyBoYW5kbGVyIDogbnVsbCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzTmFtZXNwYWNlKSB7XG4gICAgICAgIGZvciAoY29uc3QgZWxlbWVudEV2ZW50IG9mIE9iamVjdC5rZXlzKGV2ZW50cykpIHtcbiAgICAgICAgICByZW1vdmVOYW1lc3BhY2VkSGFuZGxlcnMoZWxlbWVudCwgZXZlbnRzLCBlbGVtZW50RXZlbnQsIG9yaWdpbmFsVHlwZUV2ZW50LnNsaWNlKDEpKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGtleUhhbmRsZXJzIG9mIE9iamVjdC5rZXlzKHN0b3JlRWxlbWVudEV2ZW50KSkge1xuICAgICAgICBjb25zdCBoYW5kbGVyS2V5ID0ga2V5SGFuZGxlcnMucmVwbGFjZShzdHJpcFVpZFJlZ2V4LCAnJyk7XG5cbiAgICAgICAgaWYgKCFpbk5hbWVzcGFjZSB8fCBvcmlnaW5hbFR5cGVFdmVudC5pbmNsdWRlcyhoYW5kbGVyS2V5KSkge1xuICAgICAgICAgIGNvbnN0IGV2ZW50ID0gc3RvcmVFbGVtZW50RXZlbnRba2V5SGFuZGxlcnNdO1xuICAgICAgICAgIHJlbW92ZUhhbmRsZXIoZWxlbWVudCwgZXZlbnRzLCB0eXBlRXZlbnQsIGV2ZW50LmNhbGxhYmxlLCBldmVudC5kZWxlZ2F0aW9uU2VsZWN0b3IpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcblxuICAgIHRyaWdnZXIoZWxlbWVudCwgZXZlbnQsIGFyZ3MpIHtcbiAgICAgIGlmICh0eXBlb2YgZXZlbnQgIT09ICdzdHJpbmcnIHx8ICFlbGVtZW50KSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCAkID0gaW5kZXguZ2V0alF1ZXJ5KCk7XG4gICAgICBjb25zdCB0eXBlRXZlbnQgPSBnZXRUeXBlRXZlbnQoZXZlbnQpO1xuICAgICAgY29uc3QgaW5OYW1lc3BhY2UgPSBldmVudCAhPT0gdHlwZUV2ZW50O1xuICAgICAgbGV0IGpRdWVyeUV2ZW50ID0gbnVsbDtcbiAgICAgIGxldCBidWJibGVzID0gdHJ1ZTtcbiAgICAgIGxldCBuYXRpdmVEaXNwYXRjaCA9IHRydWU7XG4gICAgICBsZXQgZGVmYXVsdFByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgICBpZiAoaW5OYW1lc3BhY2UgJiYgJCkge1xuICAgICAgICBqUXVlcnlFdmVudCA9ICQuRXZlbnQoZXZlbnQsIGFyZ3MpO1xuICAgICAgICAkKGVsZW1lbnQpLnRyaWdnZXIoalF1ZXJ5RXZlbnQpO1xuICAgICAgICBidWJibGVzID0gIWpRdWVyeUV2ZW50LmlzUHJvcGFnYXRpb25TdG9wcGVkKCk7XG4gICAgICAgIG5hdGl2ZURpc3BhdGNoID0gIWpRdWVyeUV2ZW50LmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkKCk7XG4gICAgICAgIGRlZmF1bHRQcmV2ZW50ZWQgPSBqUXVlcnlFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKTtcbiAgICAgIH1cblxuICAgICAgbGV0IGV2dCA9IG5ldyBFdmVudChldmVudCwge1xuICAgICAgICBidWJibGVzLFxuICAgICAgICBjYW5jZWxhYmxlOiB0cnVlXG4gICAgICB9KTtcbiAgICAgIGV2dCA9IGh5ZHJhdGVPYmooZXZ0LCBhcmdzKTtcblxuICAgICAgaWYgKGRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChuYXRpdmVEaXNwYXRjaCkge1xuICAgICAgICBlbGVtZW50LmRpc3BhdGNoRXZlbnQoZXZ0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGV2dC5kZWZhdWx0UHJldmVudGVkICYmIGpRdWVyeUV2ZW50KSB7XG4gICAgICAgIGpRdWVyeUV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBldnQ7XG4gICAgfVxuXG4gIH07XG5cbiAgZnVuY3Rpb24gaHlkcmF0ZU9iaihvYmosIG1ldGEpIHtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhtZXRhIHx8IHt9KSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgb2JqW2tleV0gPSB2YWx1ZTtcbiAgICAgIH0gY2F0Y2ggKF91bnVzZWQpIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwga2V5LCB7XG4gICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuXG4gICAgICAgICAgZ2V0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgIH1cblxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb2JqO1xuICB9XG5cbiAgcmV0dXJuIEV2ZW50SGFuZGxlcjtcblxufSkpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZXZlbnQtaGFuZGxlci5qcy5tYXBcbiIsIi8qIVxuICAqIEJvb3RzdHJhcCBtYW5pcHVsYXRvci5qcyB2NS4yLjAgKGh0dHBzOi8vZ2V0Ym9vdHN0cmFwLmNvbS8pXG4gICogQ29weXJpZ2h0IDIwMTEtMjAyMiBUaGUgQm9vdHN0cmFwIEF1dGhvcnMgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ncmFwaHMvY29udHJpYnV0b3JzKVxuICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAqL1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCkgOlxuICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoZmFjdG9yeSkgOlxuICAoZ2xvYmFsID0gdHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsVGhpcyA6IGdsb2JhbCB8fCBzZWxmLCBnbG9iYWwuTWFuaXB1bGF0b3IgPSBmYWN0b3J5KCkpO1xufSkodGhpcywgKGZ1bmN0aW9uICgpIHsgJ3VzZSBzdHJpY3QnO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY1LjIuMCk6IGRvbS9tYW5pcHVsYXRvci5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZURhdGEodmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT09ICd0cnVlJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlID09PSAnZmFsc2UnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlID09PSBOdW1iZXIodmFsdWUpLnRvU3RyaW5nKCkpIHtcbiAgICAgIHJldHVybiBOdW1iZXIodmFsdWUpO1xuICAgIH1cblxuICAgIGlmICh2YWx1ZSA9PT0gJycgfHwgdmFsdWUgPT09ICdudWxsJykge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEpTT04ucGFyc2UoZGVjb2RlVVJJQ29tcG9uZW50KHZhbHVlKSk7XG4gICAgfSBjYXRjaCAoX3VudXNlZCkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZURhdGFLZXkoa2V5KSB7XG4gICAgcmV0dXJuIGtleS5yZXBsYWNlKC9bQS1aXS9nLCBjaHIgPT4gYC0ke2Noci50b0xvd2VyQ2FzZSgpfWApO1xuICB9XG5cbiAgY29uc3QgTWFuaXB1bGF0b3IgPSB7XG4gICAgc2V0RGF0YUF0dHJpYnV0ZShlbGVtZW50LCBrZXksIHZhbHVlKSB7XG4gICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShgZGF0YS1icy0ke25vcm1hbGl6ZURhdGFLZXkoa2V5KX1gLCB2YWx1ZSk7XG4gICAgfSxcblxuICAgIHJlbW92ZURhdGFBdHRyaWJ1dGUoZWxlbWVudCwga2V5KSB7XG4gICAgICBlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZShgZGF0YS1icy0ke25vcm1hbGl6ZURhdGFLZXkoa2V5KX1gKTtcbiAgICB9LFxuXG4gICAgZ2V0RGF0YUF0dHJpYnV0ZXMoZWxlbWVudCkge1xuICAgICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICAgIHJldHVybiB7fTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYXR0cmlidXRlcyA9IHt9O1xuICAgICAgY29uc3QgYnNLZXlzID0gT2JqZWN0LmtleXMoZWxlbWVudC5kYXRhc2V0KS5maWx0ZXIoa2V5ID0+IGtleS5zdGFydHNXaXRoKCdicycpICYmICFrZXkuc3RhcnRzV2l0aCgnYnNDb25maWcnKSk7XG5cbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIGJzS2V5cykge1xuICAgICAgICBsZXQgcHVyZUtleSA9IGtleS5yZXBsYWNlKC9eYnMvLCAnJyk7XG4gICAgICAgIHB1cmVLZXkgPSBwdXJlS2V5LmNoYXJBdCgwKS50b0xvd2VyQ2FzZSgpICsgcHVyZUtleS5zbGljZSgxLCBwdXJlS2V5Lmxlbmd0aCk7XG4gICAgICAgIGF0dHJpYnV0ZXNbcHVyZUtleV0gPSBub3JtYWxpemVEYXRhKGVsZW1lbnQuZGF0YXNldFtrZXldKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGF0dHJpYnV0ZXM7XG4gICAgfSxcblxuICAgIGdldERhdGFBdHRyaWJ1dGUoZWxlbWVudCwga2V5KSB7XG4gICAgICByZXR1cm4gbm9ybWFsaXplRGF0YShlbGVtZW50LmdldEF0dHJpYnV0ZShgZGF0YS1icy0ke25vcm1hbGl6ZURhdGFLZXkoa2V5KX1gKSk7XG4gICAgfVxuXG4gIH07XG5cbiAgcmV0dXJuIE1hbmlwdWxhdG9yO1xuXG59KSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1tYW5pcHVsYXRvci5qcy5tYXBcbiIsIi8qIVxuICAqIEJvb3RzdHJhcCBzZWxlY3Rvci1lbmdpbmUuanMgdjUuMi4wIChodHRwczovL2dldGJvb3RzdHJhcC5jb20vKVxuICAqIENvcHlyaWdodCAyMDExLTIwMjIgVGhlIEJvb3RzdHJhcCBBdXRob3JzIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvZ3JhcGhzL2NvbnRyaWJ1dG9ycylcbiAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgKi9cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKCcuLi91dGlsL2luZGV4JykpIDpcbiAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vdXRpbC9pbmRleCddLCBmYWN0b3J5KSA6XG4gIChnbG9iYWwgPSB0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWxUaGlzIDogZ2xvYmFsIHx8IHNlbGYsIGdsb2JhbC5TZWxlY3RvckVuZ2luZSA9IGZhY3RvcnkoZ2xvYmFsLkluZGV4KSk7XG59KSh0aGlzLCAoZnVuY3Rpb24gKGluZGV4KSB7ICd1c2Ugc3RyaWN0JztcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NS4yLjApOiBkb20vc2VsZWN0b3ItZW5naW5lLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgLyoqXG4gICAqIENvbnN0YW50c1xuICAgKi9cblxuICBjb25zdCBTZWxlY3RvckVuZ2luZSA9IHtcbiAgICBmaW5kKHNlbGVjdG9yLCBlbGVtZW50ID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICByZXR1cm4gW10uY29uY2F0KC4uLkVsZW1lbnQucHJvdG90eXBlLnF1ZXJ5U2VsZWN0b3JBbGwuY2FsbChlbGVtZW50LCBzZWxlY3RvcikpO1xuICAgIH0sXG5cbiAgICBmaW5kT25lKHNlbGVjdG9yLCBlbGVtZW50ID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICByZXR1cm4gRWxlbWVudC5wcm90b3R5cGUucXVlcnlTZWxlY3Rvci5jYWxsKGVsZW1lbnQsIHNlbGVjdG9yKTtcbiAgICB9LFxuXG4gICAgY2hpbGRyZW4oZWxlbWVudCwgc2VsZWN0b3IpIHtcbiAgICAgIHJldHVybiBbXS5jb25jYXQoLi4uZWxlbWVudC5jaGlsZHJlbikuZmlsdGVyKGNoaWxkID0+IGNoaWxkLm1hdGNoZXMoc2VsZWN0b3IpKTtcbiAgICB9LFxuXG4gICAgcGFyZW50cyhlbGVtZW50LCBzZWxlY3Rvcikge1xuICAgICAgY29uc3QgcGFyZW50cyA9IFtdO1xuICAgICAgbGV0IGFuY2VzdG9yID0gZWxlbWVudC5wYXJlbnROb2RlLmNsb3Nlc3Qoc2VsZWN0b3IpO1xuXG4gICAgICB3aGlsZSAoYW5jZXN0b3IpIHtcbiAgICAgICAgcGFyZW50cy5wdXNoKGFuY2VzdG9yKTtcbiAgICAgICAgYW5jZXN0b3IgPSBhbmNlc3Rvci5wYXJlbnROb2RlLmNsb3Nlc3Qoc2VsZWN0b3IpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcGFyZW50cztcbiAgICB9LFxuXG4gICAgcHJldihlbGVtZW50LCBzZWxlY3Rvcikge1xuICAgICAgbGV0IHByZXZpb3VzID0gZWxlbWVudC5wcmV2aW91c0VsZW1lbnRTaWJsaW5nO1xuXG4gICAgICB3aGlsZSAocHJldmlvdXMpIHtcbiAgICAgICAgaWYgKHByZXZpb3VzLm1hdGNoZXMoc2VsZWN0b3IpKSB7XG4gICAgICAgICAgcmV0dXJuIFtwcmV2aW91c107XG4gICAgICAgIH1cblxuICAgICAgICBwcmV2aW91cyA9IHByZXZpb3VzLnByZXZpb3VzRWxlbWVudFNpYmxpbmc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBbXTtcbiAgICB9LFxuXG4gICAgLy8gVE9ETzogdGhpcyBpcyBub3cgdW51c2VkOyByZW1vdmUgbGF0ZXIgYWxvbmcgd2l0aCBwcmV2KClcbiAgICBuZXh0KGVsZW1lbnQsIHNlbGVjdG9yKSB7XG4gICAgICBsZXQgbmV4dCA9IGVsZW1lbnQubmV4dEVsZW1lbnRTaWJsaW5nO1xuXG4gICAgICB3aGlsZSAobmV4dCkge1xuICAgICAgICBpZiAobmV4dC5tYXRjaGVzKHNlbGVjdG9yKSkge1xuICAgICAgICAgIHJldHVybiBbbmV4dF07XG4gICAgICAgIH1cblxuICAgICAgICBuZXh0ID0gbmV4dC5uZXh0RWxlbWVudFNpYmxpbmc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBbXTtcbiAgICB9LFxuXG4gICAgZm9jdXNhYmxlQ2hpbGRyZW4oZWxlbWVudCkge1xuICAgICAgY29uc3QgZm9jdXNhYmxlcyA9IFsnYScsICdidXR0b24nLCAnaW5wdXQnLCAndGV4dGFyZWEnLCAnc2VsZWN0JywgJ2RldGFpbHMnLCAnW3RhYmluZGV4XScsICdbY29udGVudGVkaXRhYmxlPVwidHJ1ZVwiXSddLm1hcChzZWxlY3RvciA9PiBgJHtzZWxlY3Rvcn06bm90KFt0YWJpbmRleF49XCItXCJdKWApLmpvaW4oJywnKTtcbiAgICAgIHJldHVybiB0aGlzLmZpbmQoZm9jdXNhYmxlcywgZWxlbWVudCkuZmlsdGVyKGVsID0+ICFpbmRleC5pc0Rpc2FibGVkKGVsKSAmJiBpbmRleC5pc1Zpc2libGUoZWwpKTtcbiAgICB9XG5cbiAgfTtcblxuICByZXR1cm4gU2VsZWN0b3JFbmdpbmU7XG5cbn0pKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNlbGVjdG9yLWVuZ2luZS5qcy5tYXBcbiIsIi8qIVxuICAqIEJvb3RzdHJhcCBjb25maWcuanMgdjUuMi4wIChodHRwczovL2dldGJvb3RzdHJhcC5jb20vKVxuICAqIENvcHlyaWdodCAyMDExLTIwMjIgVGhlIEJvb3RzdHJhcCBBdXRob3JzIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvZ3JhcGhzL2NvbnRyaWJ1dG9ycylcbiAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgKi9cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKCcuL2luZGV4JyksIHJlcXVpcmUoJy4uL2RvbS9tYW5pcHVsYXRvcicpKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4vaW5kZXgnLCAnLi4vZG9tL21hbmlwdWxhdG9yJ10sIGZhY3RvcnkpIDpcbiAgKGdsb2JhbCA9IHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbFRoaXMgOiBnbG9iYWwgfHwgc2VsZiwgZ2xvYmFsLkNvbmZpZyA9IGZhY3RvcnkoZ2xvYmFsLkluZGV4LCBnbG9iYWwuTWFuaXB1bGF0b3IpKTtcbn0pKHRoaXMsIChmdW5jdGlvbiAoaW5kZXgsIE1hbmlwdWxhdG9yKSB7ICd1c2Ugc3RyaWN0JztcblxuICBjb25zdCBfaW50ZXJvcERlZmF1bHRMZWdhY3kgPSBlID0+IGUgJiYgdHlwZW9mIGUgPT09ICdvYmplY3QnICYmICdkZWZhdWx0JyBpbiBlID8gZSA6IHsgZGVmYXVsdDogZSB9O1xuXG4gIGNvbnN0IE1hbmlwdWxhdG9yX19kZWZhdWx0ID0gLyojX19QVVJFX18qL19pbnRlcm9wRGVmYXVsdExlZ2FjeShNYW5pcHVsYXRvcik7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjUuMi4wKTogdXRpbC9jb25maWcuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYWluL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICAvKipcbiAgICogQ2xhc3MgZGVmaW5pdGlvblxuICAgKi9cblxuICBjbGFzcyBDb25maWcge1xuICAgIC8vIEdldHRlcnNcbiAgICBzdGF0aWMgZ2V0IERlZmF1bHQoKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgc3RhdGljIGdldCBEZWZhdWx0VHlwZSgpIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0IE5BTUUoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBoYXZlIHRvIGltcGxlbWVudCB0aGUgc3RhdGljIG1ldGhvZCBcIk5BTUVcIiwgZm9yIGVhY2ggY29tcG9uZW50IScpO1xuICAgIH1cblxuICAgIF9nZXRDb25maWcoY29uZmlnKSB7XG4gICAgICBjb25maWcgPSB0aGlzLl9tZXJnZUNvbmZpZ09iaihjb25maWcpO1xuICAgICAgY29uZmlnID0gdGhpcy5fY29uZmlnQWZ0ZXJNZXJnZShjb25maWcpO1xuXG4gICAgICB0aGlzLl90eXBlQ2hlY2tDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICB9XG5cbiAgICBfY29uZmlnQWZ0ZXJNZXJnZShjb25maWcpIHtcbiAgICAgIHJldHVybiBjb25maWc7XG4gICAgfVxuXG4gICAgX21lcmdlQ29uZmlnT2JqKGNvbmZpZywgZWxlbWVudCkge1xuICAgICAgY29uc3QganNvbkNvbmZpZyA9IGluZGV4LmlzRWxlbWVudChlbGVtZW50KSA/IE1hbmlwdWxhdG9yX19kZWZhdWx0LmRlZmF1bHQuZ2V0RGF0YUF0dHJpYnV0ZShlbGVtZW50LCAnY29uZmlnJykgOiB7fTsgLy8gdHJ5IHRvIHBhcnNlXG5cbiAgICAgIHJldHVybiB7IC4uLnRoaXMuY29uc3RydWN0b3IuRGVmYXVsdCxcbiAgICAgICAgLi4uKHR5cGVvZiBqc29uQ29uZmlnID09PSAnb2JqZWN0JyA/IGpzb25Db25maWcgOiB7fSksXG4gICAgICAgIC4uLihpbmRleC5pc0VsZW1lbnQoZWxlbWVudCkgPyBNYW5pcHVsYXRvcl9fZGVmYXVsdC5kZWZhdWx0LmdldERhdGFBdHRyaWJ1dGVzKGVsZW1lbnQpIDoge30pLFxuICAgICAgICAuLi4odHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgPyBjb25maWcgOiB7fSlcbiAgICAgIH07XG4gICAgfVxuXG4gICAgX3R5cGVDaGVja0NvbmZpZyhjb25maWcsIGNvbmZpZ1R5cGVzID0gdGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0VHlwZSkge1xuICAgICAgZm9yIChjb25zdCBwcm9wZXJ0eSBvZiBPYmplY3Qua2V5cyhjb25maWdUeXBlcykpIHtcbiAgICAgICAgY29uc3QgZXhwZWN0ZWRUeXBlcyA9IGNvbmZpZ1R5cGVzW3Byb3BlcnR5XTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBjb25maWdbcHJvcGVydHldO1xuICAgICAgICBjb25zdCB2YWx1ZVR5cGUgPSBpbmRleC5pc0VsZW1lbnQodmFsdWUpID8gJ2VsZW1lbnQnIDogaW5kZXgudG9UeXBlKHZhbHVlKTtcblxuICAgICAgICBpZiAoIW5ldyBSZWdFeHAoZXhwZWN0ZWRUeXBlcykudGVzdCh2YWx1ZVR5cGUpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgJHt0aGlzLmNvbnN0cnVjdG9yLk5BTUUudG9VcHBlckNhc2UoKX06IE9wdGlvbiBcIiR7cHJvcGVydHl9XCIgcHJvdmlkZWQgdHlwZSBcIiR7dmFsdWVUeXBlfVwiIGJ1dCBleHBlY3RlZCB0eXBlIFwiJHtleHBlY3RlZFR5cGVzfVwiLmApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gIH1cblxuICByZXR1cm4gQ29uZmlnO1xuXG59KSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jb25maWcuanMubWFwXG4iLCIvKiFcbiAgKiBCb290c3RyYXAgaW5kZXguanMgdjUuMi4wIChodHRwczovL2dldGJvb3RzdHJhcC5jb20vKVxuICAqIENvcHlyaWdodCAyMDExLTIwMjIgVGhlIEJvb3RzdHJhcCBBdXRob3JzIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvZ3JhcGhzL2NvbnRyaWJ1dG9ycylcbiAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21haW4vTElDRU5TRSlcbiAgKi9cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcbiAgKGdsb2JhbCA9IHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbFRoaXMgOiBnbG9iYWwgfHwgc2VsZiwgZmFjdG9yeShnbG9iYWwuSW5kZXggPSB7fSkpO1xufSkodGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NS4yLjApOiB1dGlsL2luZGV4LmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFpbi9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgY29uc3QgTUFYX1VJRCA9IDEwMDAwMDA7XG4gIGNvbnN0IE1JTExJU0VDT05EU19NVUxUSVBMSUVSID0gMTAwMDtcbiAgY29uc3QgVFJBTlNJVElPTl9FTkQgPSAndHJhbnNpdGlvbmVuZCc7IC8vIFNob3V0LW91dCBBbmd1cyBDcm9sbCAoaHR0cHM6Ly9nb28uZ2wvcHh3UUdwKVxuXG4gIGNvbnN0IHRvVHlwZSA9IG9iamVjdCA9PiB7XG4gICAgaWYgKG9iamVjdCA9PT0gbnVsbCB8fCBvYmplY3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGAke29iamVjdH1gO1xuICAgIH1cblxuICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqZWN0KS5tYXRjaCgvXFxzKFthLXpdKykvaSlbMV0udG9Mb3dlckNhc2UoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFB1YmxpYyBVdGlsIEFQSVxuICAgKi9cblxuXG4gIGNvbnN0IGdldFVJRCA9IHByZWZpeCA9PiB7XG4gICAgZG8ge1xuICAgICAgcHJlZml4ICs9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIE1BWF9VSUQpO1xuICAgIH0gd2hpbGUgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHByZWZpeCkpO1xuXG4gICAgcmV0dXJuIHByZWZpeDtcbiAgfTtcblxuICBjb25zdCBnZXRTZWxlY3RvciA9IGVsZW1lbnQgPT4ge1xuICAgIGxldCBzZWxlY3RvciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLWJzLXRhcmdldCcpO1xuXG4gICAgaWYgKCFzZWxlY3RvciB8fCBzZWxlY3RvciA9PT0gJyMnKSB7XG4gICAgICBsZXQgaHJlZkF0dHJpYnV0ZSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdocmVmJyk7IC8vIFRoZSBvbmx5IHZhbGlkIGNvbnRlbnQgdGhhdCBjb3VsZCBkb3VibGUgYXMgYSBzZWxlY3RvciBhcmUgSURzIG9yIGNsYXNzZXMsXG4gICAgICAvLyBzbyBldmVyeXRoaW5nIHN0YXJ0aW5nIHdpdGggYCNgIG9yIGAuYC4gSWYgYSBcInJlYWxcIiBVUkwgaXMgdXNlZCBhcyB0aGUgc2VsZWN0b3IsXG4gICAgICAvLyBgZG9jdW1lbnQucXVlcnlTZWxlY3RvcmAgd2lsbCByaWdodGZ1bGx5IGNvbXBsYWluIGl0IGlzIGludmFsaWQuXG4gICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2lzc3Vlcy8zMjI3M1xuXG4gICAgICBpZiAoIWhyZWZBdHRyaWJ1dGUgfHwgIWhyZWZBdHRyaWJ1dGUuaW5jbHVkZXMoJyMnKSAmJiAhaHJlZkF0dHJpYnV0ZS5zdGFydHNXaXRoKCcuJykpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9IC8vIEp1c3QgaW4gY2FzZSBzb21lIENNUyBwdXRzIG91dCBhIGZ1bGwgVVJMIHdpdGggdGhlIGFuY2hvciBhcHBlbmRlZFxuXG5cbiAgICAgIGlmIChocmVmQXR0cmlidXRlLmluY2x1ZGVzKCcjJykgJiYgIWhyZWZBdHRyaWJ1dGUuc3RhcnRzV2l0aCgnIycpKSB7XG4gICAgICAgIGhyZWZBdHRyaWJ1dGUgPSBgIyR7aHJlZkF0dHJpYnV0ZS5zcGxpdCgnIycpWzFdfWA7XG4gICAgICB9XG5cbiAgICAgIHNlbGVjdG9yID0gaHJlZkF0dHJpYnV0ZSAmJiBocmVmQXR0cmlidXRlICE9PSAnIycgPyBocmVmQXR0cmlidXRlLnRyaW0oKSA6IG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbGVjdG9yO1xuICB9O1xuXG4gIGNvbnN0IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQgPSBlbGVtZW50ID0+IHtcbiAgICBjb25zdCBzZWxlY3RvciA9IGdldFNlbGVjdG9yKGVsZW1lbnQpO1xuXG4gICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3RvcikgPyBzZWxlY3RvciA6IG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH07XG5cbiAgY29uc3QgZ2V0RWxlbWVudEZyb21TZWxlY3RvciA9IGVsZW1lbnQgPT4ge1xuICAgIGNvbnN0IHNlbGVjdG9yID0gZ2V0U2VsZWN0b3IoZWxlbWVudCk7XG4gICAgcmV0dXJuIHNlbGVjdG9yID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3RvcikgOiBudWxsO1xuICB9O1xuXG4gIGNvbnN0IGdldFRyYW5zaXRpb25EdXJhdGlvbkZyb21FbGVtZW50ID0gZWxlbWVudCA9PiB7XG4gICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9IC8vIEdldCB0cmFuc2l0aW9uLWR1cmF0aW9uIG9mIHRoZSBlbGVtZW50XG5cblxuICAgIGxldCB7XG4gICAgICB0cmFuc2l0aW9uRHVyYXRpb24sXG4gICAgICB0cmFuc2l0aW9uRGVsYXlcbiAgICB9ID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XG4gICAgY29uc3QgZmxvYXRUcmFuc2l0aW9uRHVyYXRpb24gPSBOdW1iZXIucGFyc2VGbG9hdCh0cmFuc2l0aW9uRHVyYXRpb24pO1xuICAgIGNvbnN0IGZsb2F0VHJhbnNpdGlvbkRlbGF5ID0gTnVtYmVyLnBhcnNlRmxvYXQodHJhbnNpdGlvbkRlbGF5KTsgLy8gUmV0dXJuIDAgaWYgZWxlbWVudCBvciB0cmFuc2l0aW9uIGR1cmF0aW9uIGlzIG5vdCBmb3VuZFxuXG4gICAgaWYgKCFmbG9hdFRyYW5zaXRpb25EdXJhdGlvbiAmJiAhZmxvYXRUcmFuc2l0aW9uRGVsYXkpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gLy8gSWYgbXVsdGlwbGUgZHVyYXRpb25zIGFyZSBkZWZpbmVkLCB0YWtlIHRoZSBmaXJzdFxuXG5cbiAgICB0cmFuc2l0aW9uRHVyYXRpb24gPSB0cmFuc2l0aW9uRHVyYXRpb24uc3BsaXQoJywnKVswXTtcbiAgICB0cmFuc2l0aW9uRGVsYXkgPSB0cmFuc2l0aW9uRGVsYXkuc3BsaXQoJywnKVswXTtcbiAgICByZXR1cm4gKE51bWJlci5wYXJzZUZsb2F0KHRyYW5zaXRpb25EdXJhdGlvbikgKyBOdW1iZXIucGFyc2VGbG9hdCh0cmFuc2l0aW9uRGVsYXkpKSAqIE1JTExJU0VDT05EU19NVUxUSVBMSUVSO1xuICB9O1xuXG4gIGNvbnN0IHRyaWdnZXJUcmFuc2l0aW9uRW5kID0gZWxlbWVudCA9PiB7XG4gICAgZWxlbWVudC5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudChUUkFOU0lUSU9OX0VORCkpO1xuICB9O1xuXG4gIGNvbnN0IGlzRWxlbWVudCA9IG9iamVjdCA9PiB7XG4gICAgaWYgKCFvYmplY3QgfHwgdHlwZW9mIG9iamVjdCAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9iamVjdC5qcXVlcnkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBvYmplY3QgPSBvYmplY3RbMF07XG4gICAgfVxuXG4gICAgcmV0dXJuIHR5cGVvZiBvYmplY3Qubm9kZVR5cGUgIT09ICd1bmRlZmluZWQnO1xuICB9O1xuXG4gIGNvbnN0IGdldEVsZW1lbnQgPSBvYmplY3QgPT4ge1xuICAgIC8vIGl0J3MgYSBqUXVlcnkgb2JqZWN0IG9yIGEgbm9kZSBlbGVtZW50XG4gICAgaWYgKGlzRWxlbWVudChvYmplY3QpKSB7XG4gICAgICByZXR1cm4gb2JqZWN0LmpxdWVyeSA/IG9iamVjdFswXSA6IG9iamVjdDtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9iamVjdCA9PT0gJ3N0cmluZycgJiYgb2JqZWN0Lmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKG9iamVjdCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH07XG5cbiAgY29uc3QgaXNWaXNpYmxlID0gZWxlbWVudCA9PiB7XG4gICAgaWYgKCFpc0VsZW1lbnQoZWxlbWVudCkgfHwgZWxlbWVudC5nZXRDbGllbnRSZWN0cygpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGVsZW1lbnRJc1Zpc2libGUgPSBnZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoJ3Zpc2liaWxpdHknKSA9PT0gJ3Zpc2libGUnOyAvLyBIYW5kbGUgYGRldGFpbHNgIGVsZW1lbnQgYXMgaXRzIGNvbnRlbnQgbWF5IGZhbHNpZSBhcHBlYXIgdmlzaWJsZSB3aGVuIGl0IGlzIGNsb3NlZFxuXG4gICAgY29uc3QgY2xvc2VkRGV0YWlscyA9IGVsZW1lbnQuY2xvc2VzdCgnZGV0YWlsczpub3QoW29wZW5dKScpO1xuXG4gICAgaWYgKCFjbG9zZWREZXRhaWxzKSB7XG4gICAgICByZXR1cm4gZWxlbWVudElzVmlzaWJsZTtcbiAgICB9XG5cbiAgICBpZiAoY2xvc2VkRGV0YWlscyAhPT0gZWxlbWVudCkge1xuICAgICAgY29uc3Qgc3VtbWFyeSA9IGVsZW1lbnQuY2xvc2VzdCgnc3VtbWFyeScpO1xuXG4gICAgICBpZiAoc3VtbWFyeSAmJiBzdW1tYXJ5LnBhcmVudE5vZGUgIT09IGNsb3NlZERldGFpbHMpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBpZiAoc3VtbWFyeSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnRJc1Zpc2libGU7XG4gIH07XG5cbiAgY29uc3QgaXNEaXNhYmxlZCA9IGVsZW1lbnQgPT4ge1xuICAgIGlmICghZWxlbWVudCB8fCBlbGVtZW50Lm5vZGVUeXBlICE9PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCdkaXNhYmxlZCcpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGVsZW1lbnQuZGlzYWJsZWQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gZWxlbWVudC5kaXNhYmxlZDtcbiAgICB9XG5cbiAgICByZXR1cm4gZWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJykgJiYgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2Rpc2FibGVkJykgIT09ICdmYWxzZSc7XG4gIH07XG5cbiAgY29uc3QgZmluZFNoYWRvd1Jvb3QgPSBlbGVtZW50ID0+IHtcbiAgICBpZiAoIWRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5hdHRhY2hTaGFkb3cpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gLy8gQ2FuIGZpbmQgdGhlIHNoYWRvdyByb290IG90aGVyd2lzZSBpdCdsbCByZXR1cm4gdGhlIGRvY3VtZW50XG5cblxuICAgIGlmICh0eXBlb2YgZWxlbWVudC5nZXRSb290Tm9kZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY29uc3Qgcm9vdCA9IGVsZW1lbnQuZ2V0Um9vdE5vZGUoKTtcbiAgICAgIHJldHVybiByb290IGluc3RhbmNlb2YgU2hhZG93Um9vdCA/IHJvb3QgOiBudWxsO1xuICAgIH1cblxuICAgIGlmIChlbGVtZW50IGluc3RhbmNlb2YgU2hhZG93Um9vdCkge1xuICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgfSAvLyB3aGVuIHdlIGRvbid0IGZpbmQgYSBzaGFkb3cgcm9vdFxuXG5cbiAgICBpZiAoIWVsZW1lbnQucGFyZW50Tm9kZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZpbmRTaGFkb3dSb290KGVsZW1lbnQucGFyZW50Tm9kZSk7XG4gIH07XG5cbiAgY29uc3Qgbm9vcCA9ICgpID0+IHt9O1xuICAvKipcbiAgICogVHJpY2sgdG8gcmVzdGFydCBhbiBlbGVtZW50J3MgYW5pbWF0aW9uXG4gICAqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHJldHVybiB2b2lkXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly93d3cuY2hhcmlzdGhlby5pby9ibG9nLzIwMjEvMDIvcmVzdGFydC1hLWNzcy1hbmltYXRpb24td2l0aC1qYXZhc2NyaXB0LyNyZXN0YXJ0aW5nLWEtY3NzLWFuaW1hdGlvblxuICAgKi9cblxuXG4gIGNvbnN0IHJlZmxvdyA9IGVsZW1lbnQgPT4ge1xuICAgIGVsZW1lbnQub2Zmc2V0SGVpZ2h0OyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC1leHByZXNzaW9uc1xuICB9O1xuXG4gIGNvbnN0IGdldGpRdWVyeSA9ICgpID0+IHtcbiAgICBpZiAod2luZG93LmpRdWVyeSAmJiAhZG9jdW1lbnQuYm9keS5oYXNBdHRyaWJ1dGUoJ2RhdGEtYnMtbm8tanF1ZXJ5JykpIHtcbiAgICAgIHJldHVybiB3aW5kb3cualF1ZXJ5O1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9O1xuXG4gIGNvbnN0IERPTUNvbnRlbnRMb2FkZWRDYWxsYmFja3MgPSBbXTtcblxuICBjb25zdCBvbkRPTUNvbnRlbnRMb2FkZWQgPSBjYWxsYmFjayA9PiB7XG4gICAgaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdsb2FkaW5nJykge1xuICAgICAgLy8gYWRkIGxpc3RlbmVyIG9uIHRoZSBmaXJzdCBjYWxsIHdoZW4gdGhlIGRvY3VtZW50IGlzIGluIGxvYWRpbmcgc3RhdGVcbiAgICAgIGlmICghRE9NQ29udGVudExvYWRlZENhbGxiYWNrcy5sZW5ndGgpIHtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHtcbiAgICAgICAgICBmb3IgKGNvbnN0IGNhbGxiYWNrIG9mIERPTUNvbnRlbnRMb2FkZWRDYWxsYmFja3MpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgRE9NQ29udGVudExvYWRlZENhbGxiYWNrcy5wdXNoKGNhbGxiYWNrKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG4gIH07XG5cbiAgY29uc3QgaXNSVEwgPSAoKSA9PiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZGlyID09PSAncnRsJztcblxuICBjb25zdCBkZWZpbmVKUXVlcnlQbHVnaW4gPSBwbHVnaW4gPT4ge1xuICAgIG9uRE9NQ29udGVudExvYWRlZCgoKSA9PiB7XG4gICAgICBjb25zdCAkID0gZ2V0alF1ZXJ5KCk7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cblxuICAgICAgaWYgKCQpIHtcbiAgICAgICAgY29uc3QgbmFtZSA9IHBsdWdpbi5OQU1FO1xuICAgICAgICBjb25zdCBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkLmZuW25hbWVdO1xuICAgICAgICAkLmZuW25hbWVdID0gcGx1Z2luLmpRdWVyeUludGVyZmFjZTtcbiAgICAgICAgJC5mbltuYW1lXS5Db25zdHJ1Y3RvciA9IHBsdWdpbjtcblxuICAgICAgICAkLmZuW25hbWVdLm5vQ29uZmxpY3QgPSAoKSA9PiB7XG4gICAgICAgICAgJC5mbltuYW1lXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICAgICAgICByZXR1cm4gcGx1Z2luLmpRdWVyeUludGVyZmFjZTtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICBjb25zdCBleGVjdXRlID0gY2FsbGJhY2sgPT4ge1xuICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGNhbGxiYWNrKCk7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGV4ZWN1dGVBZnRlclRyYW5zaXRpb24gPSAoY2FsbGJhY2ssIHRyYW5zaXRpb25FbGVtZW50LCB3YWl0Rm9yVHJhbnNpdGlvbiA9IHRydWUpID0+IHtcbiAgICBpZiAoIXdhaXRGb3JUcmFuc2l0aW9uKSB7XG4gICAgICBleGVjdXRlKGNhbGxiYWNrKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBkdXJhdGlvblBhZGRpbmcgPSA1O1xuICAgIGNvbnN0IGVtdWxhdGVkRHVyYXRpb24gPSBnZXRUcmFuc2l0aW9uRHVyYXRpb25Gcm9tRWxlbWVudCh0cmFuc2l0aW9uRWxlbWVudCkgKyBkdXJhdGlvblBhZGRpbmc7XG4gICAgbGV0IGNhbGxlZCA9IGZhbHNlO1xuXG4gICAgY29uc3QgaGFuZGxlciA9ICh7XG4gICAgICB0YXJnZXRcbiAgICB9KSA9PiB7XG4gICAgICBpZiAodGFyZ2V0ICE9PSB0cmFuc2l0aW9uRWxlbWVudCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNhbGxlZCA9IHRydWU7XG4gICAgICB0cmFuc2l0aW9uRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFRSQU5TSVRJT05fRU5ELCBoYW5kbGVyKTtcbiAgICAgIGV4ZWN1dGUoY2FsbGJhY2spO1xuICAgIH07XG5cbiAgICB0cmFuc2l0aW9uRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFRSQU5TSVRJT05fRU5ELCBoYW5kbGVyKTtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGlmICghY2FsbGVkKSB7XG4gICAgICAgIHRyaWdnZXJUcmFuc2l0aW9uRW5kKHRyYW5zaXRpb25FbGVtZW50KTtcbiAgICAgIH1cbiAgICB9LCBlbXVsYXRlZER1cmF0aW9uKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgcHJldmlvdXMvbmV4dCBlbGVtZW50IG9mIGEgbGlzdC5cbiAgICpcbiAgICogQHBhcmFtIHthcnJheX0gbGlzdCAgICBUaGUgbGlzdCBvZiBlbGVtZW50c1xuICAgKiBAcGFyYW0gYWN0aXZlRWxlbWVudCAgIFRoZSBhY3RpdmUgZWxlbWVudFxuICAgKiBAcGFyYW0gc2hvdWxkR2V0TmV4dCAgIENob29zZSB0byBnZXQgbmV4dCBvciBwcmV2aW91cyBlbGVtZW50XG4gICAqIEBwYXJhbSBpc0N5Y2xlQWxsb3dlZFxuICAgKiBAcmV0dXJuIHtFbGVtZW50fGVsZW19IFRoZSBwcm9wZXIgZWxlbWVudFxuICAgKi9cblxuXG4gIGNvbnN0IGdldE5leHRBY3RpdmVFbGVtZW50ID0gKGxpc3QsIGFjdGl2ZUVsZW1lbnQsIHNob3VsZEdldE5leHQsIGlzQ3ljbGVBbGxvd2VkKSA9PiB7XG4gICAgY29uc3QgbGlzdExlbmd0aCA9IGxpc3QubGVuZ3RoO1xuICAgIGxldCBpbmRleCA9IGxpc3QuaW5kZXhPZihhY3RpdmVFbGVtZW50KTsgLy8gaWYgdGhlIGVsZW1lbnQgZG9lcyBub3QgZXhpc3QgaW4gdGhlIGxpc3QgcmV0dXJuIGFuIGVsZW1lbnRcbiAgICAvLyBkZXBlbmRpbmcgb24gdGhlIGRpcmVjdGlvbiBhbmQgaWYgY3ljbGUgaXMgYWxsb3dlZFxuXG4gICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgcmV0dXJuICFzaG91bGRHZXROZXh0ICYmIGlzQ3ljbGVBbGxvd2VkID8gbGlzdFtsaXN0TGVuZ3RoIC0gMV0gOiBsaXN0WzBdO1xuICAgIH1cblxuICAgIGluZGV4ICs9IHNob3VsZEdldE5leHQgPyAxIDogLTE7XG5cbiAgICBpZiAoaXNDeWNsZUFsbG93ZWQpIHtcbiAgICAgIGluZGV4ID0gKGluZGV4ICsgbGlzdExlbmd0aCkgJSBsaXN0TGVuZ3RoO1xuICAgIH1cblxuICAgIHJldHVybiBsaXN0W01hdGgubWF4KDAsIE1hdGgubWluKGluZGV4LCBsaXN0TGVuZ3RoIC0gMSkpXTtcbiAgfTtcblxuICBleHBvcnRzLmRlZmluZUpRdWVyeVBsdWdpbiA9IGRlZmluZUpRdWVyeVBsdWdpbjtcbiAgZXhwb3J0cy5leGVjdXRlID0gZXhlY3V0ZTtcbiAgZXhwb3J0cy5leGVjdXRlQWZ0ZXJUcmFuc2l0aW9uID0gZXhlY3V0ZUFmdGVyVHJhbnNpdGlvbjtcbiAgZXhwb3J0cy5maW5kU2hhZG93Um9vdCA9IGZpbmRTaGFkb3dSb290O1xuICBleHBvcnRzLmdldEVsZW1lbnQgPSBnZXRFbGVtZW50O1xuICBleHBvcnRzLmdldEVsZW1lbnRGcm9tU2VsZWN0b3IgPSBnZXRFbGVtZW50RnJvbVNlbGVjdG9yO1xuICBleHBvcnRzLmdldE5leHRBY3RpdmVFbGVtZW50ID0gZ2V0TmV4dEFjdGl2ZUVsZW1lbnQ7XG4gIGV4cG9ydHMuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCA9IGdldFNlbGVjdG9yRnJvbUVsZW1lbnQ7XG4gIGV4cG9ydHMuZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQgPSBnZXRUcmFuc2l0aW9uRHVyYXRpb25Gcm9tRWxlbWVudDtcbiAgZXhwb3J0cy5nZXRVSUQgPSBnZXRVSUQ7XG4gIGV4cG9ydHMuZ2V0alF1ZXJ5ID0gZ2V0alF1ZXJ5O1xuICBleHBvcnRzLmlzRGlzYWJsZWQgPSBpc0Rpc2FibGVkO1xuICBleHBvcnRzLmlzRWxlbWVudCA9IGlzRWxlbWVudDtcbiAgZXhwb3J0cy5pc1JUTCA9IGlzUlRMO1xuICBleHBvcnRzLmlzVmlzaWJsZSA9IGlzVmlzaWJsZTtcbiAgZXhwb3J0cy5ub29wID0gbm9vcDtcbiAgZXhwb3J0cy5vbkRPTUNvbnRlbnRMb2FkZWQgPSBvbkRPTUNvbnRlbnRMb2FkZWQ7XG4gIGV4cG9ydHMucmVmbG93ID0gcmVmbG93O1xuICBleHBvcnRzLnRvVHlwZSA9IHRvVHlwZTtcbiAgZXhwb3J0cy50cmlnZ2VyVHJhbnNpdGlvbkVuZCA9IHRyaWdnZXJUcmFuc2l0aW9uRW5kO1xuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKGV4cG9ydHMsIHsgX19lc01vZHVsZTogeyB2YWx1ZTogdHJ1ZSB9LCBbU3ltYm9sLnRvU3RyaW5nVGFnXTogeyB2YWx1ZTogJ01vZHVsZScgfSB9KTtcblxufSkpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwXG4iLCIvKipcbiAqIEV2RW1pdHRlciB2Mi4xLjFcbiAqIExpbCcgZXZlbnQgZW1pdHRlclxuICogTUlUIExpY2Vuc2VcbiAqL1xuXG4oIGZ1bmN0aW9uKCBnbG9iYWwsIGZhY3RvcnkgKSB7XG4gIC8vIHVuaXZlcnNhbCBtb2R1bGUgZGVmaW5pdGlvblxuICBpZiAoIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG4gICAgLy8gQ29tbW9uSlMgLSBCcm93c2VyaWZ5LCBXZWJwYWNrXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCk7XG4gIH0gZWxzZSB7XG4gICAgLy8gQnJvd3NlciBnbG9iYWxzXG4gICAgZ2xvYmFsLkV2RW1pdHRlciA9IGZhY3RvcnkoKTtcbiAgfVxuXG59KCB0eXBlb2Ygd2luZG93ICE9ICd1bmRlZmluZWQnID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24oKSB7XG5cbmZ1bmN0aW9uIEV2RW1pdHRlcigpIHt9XG5cbmxldCBwcm90byA9IEV2RW1pdHRlci5wcm90b3R5cGU7XG5cbnByb3RvLm9uID0gZnVuY3Rpb24oIGV2ZW50TmFtZSwgbGlzdGVuZXIgKSB7XG4gIGlmICggIWV2ZW50TmFtZSB8fCAhbGlzdGVuZXIgKSByZXR1cm4gdGhpcztcblxuICAvLyBzZXQgZXZlbnRzIGhhc2hcbiAgbGV0IGV2ZW50cyA9IHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgLy8gc2V0IGxpc3RlbmVycyBhcnJheVxuICBsZXQgbGlzdGVuZXJzID0gZXZlbnRzWyBldmVudE5hbWUgXSA9IGV2ZW50c1sgZXZlbnROYW1lIF0gfHwgW107XG4gIC8vIG9ubHkgYWRkIG9uY2VcbiAgaWYgKCAhbGlzdGVuZXJzLmluY2x1ZGVzKCBsaXN0ZW5lciApICkge1xuICAgIGxpc3RlbmVycy5wdXNoKCBsaXN0ZW5lciApO1xuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5wcm90by5vbmNlID0gZnVuY3Rpb24oIGV2ZW50TmFtZSwgbGlzdGVuZXIgKSB7XG4gIGlmICggIWV2ZW50TmFtZSB8fCAhbGlzdGVuZXIgKSByZXR1cm4gdGhpcztcblxuICAvLyBhZGQgZXZlbnRcbiAgdGhpcy5vbiggZXZlbnROYW1lLCBsaXN0ZW5lciApO1xuICAvLyBzZXQgb25jZSBmbGFnXG4gIC8vIHNldCBvbmNlRXZlbnRzIGhhc2hcbiAgbGV0IG9uY2VFdmVudHMgPSB0aGlzLl9vbmNlRXZlbnRzID0gdGhpcy5fb25jZUV2ZW50cyB8fCB7fTtcbiAgLy8gc2V0IG9uY2VMaXN0ZW5lcnMgb2JqZWN0XG4gIGxldCBvbmNlTGlzdGVuZXJzID0gb25jZUV2ZW50c1sgZXZlbnROYW1lIF0gPSBvbmNlRXZlbnRzWyBldmVudE5hbWUgXSB8fCB7fTtcbiAgLy8gc2V0IGZsYWdcbiAgb25jZUxpc3RlbmVyc1sgbGlzdGVuZXIgXSA9IHRydWU7XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5wcm90by5vZmYgPSBmdW5jdGlvbiggZXZlbnROYW1lLCBsaXN0ZW5lciApIHtcbiAgbGV0IGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50cyAmJiB0aGlzLl9ldmVudHNbIGV2ZW50TmFtZSBdO1xuICBpZiAoICFsaXN0ZW5lcnMgfHwgIWxpc3RlbmVycy5sZW5ndGggKSByZXR1cm4gdGhpcztcblxuICBsZXQgaW5kZXggPSBsaXN0ZW5lcnMuaW5kZXhPZiggbGlzdGVuZXIgKTtcbiAgaWYgKCBpbmRleCAhPSAtMSApIHtcbiAgICBsaXN0ZW5lcnMuc3BsaWNlKCBpbmRleCwgMSApO1xuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5wcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiggZXZlbnROYW1lLCBhcmdzICkge1xuICBsZXQgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzICYmIHRoaXMuX2V2ZW50c1sgZXZlbnROYW1lIF07XG4gIGlmICggIWxpc3RlbmVycyB8fCAhbGlzdGVuZXJzLmxlbmd0aCApIHJldHVybiB0aGlzO1xuXG4gIC8vIGNvcHkgb3ZlciB0byBhdm9pZCBpbnRlcmZlcmVuY2UgaWYgLm9mZigpIGluIGxpc3RlbmVyXG4gIGxpc3RlbmVycyA9IGxpc3RlbmVycy5zbGljZSggMCApO1xuICBhcmdzID0gYXJncyB8fCBbXTtcbiAgLy8gb25jZSBzdHVmZlxuICBsZXQgb25jZUxpc3RlbmVycyA9IHRoaXMuX29uY2VFdmVudHMgJiYgdGhpcy5fb25jZUV2ZW50c1sgZXZlbnROYW1lIF07XG5cbiAgZm9yICggbGV0IGxpc3RlbmVyIG9mIGxpc3RlbmVycyApIHtcbiAgICBsZXQgaXNPbmNlID0gb25jZUxpc3RlbmVycyAmJiBvbmNlTGlzdGVuZXJzWyBsaXN0ZW5lciBdO1xuICAgIGlmICggaXNPbmNlICkge1xuICAgICAgLy8gcmVtb3ZlIGxpc3RlbmVyXG4gICAgICAvLyByZW1vdmUgYmVmb3JlIHRyaWdnZXIgdG8gcHJldmVudCByZWN1cnNpb25cbiAgICAgIHRoaXMub2ZmKCBldmVudE5hbWUsIGxpc3RlbmVyICk7XG4gICAgICAvLyB1bnNldCBvbmNlIGZsYWdcbiAgICAgIGRlbGV0ZSBvbmNlTGlzdGVuZXJzWyBsaXN0ZW5lciBdO1xuICAgIH1cbiAgICAvLyB0cmlnZ2VyIGxpc3RlbmVyXG4gICAgbGlzdGVuZXIuYXBwbHkoIHRoaXMsIGFyZ3MgKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxucHJvdG8uYWxsT2ZmID0gZnVuY3Rpb24oKSB7XG4gIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gIGRlbGV0ZSB0aGlzLl9vbmNlRXZlbnRzO1xuICByZXR1cm4gdGhpcztcbn07XG5cbnJldHVybiBFdkVtaXR0ZXI7XG5cbn0gKSApO1xuIiwiLyoqXG4gKiBGaXp6eSBVSSB1dGlscyB2My4wLjBcbiAqIE1JVCBsaWNlbnNlXG4gKi9cblxuKCBmdW5jdGlvbiggZ2xvYmFsLCBmYWN0b3J5ICkge1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cbiAgaWYgKCB0eXBlb2YgbW9kdWxlID09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzICkge1xuICAgIC8vIENvbW1vbkpTXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCBnbG9iYWwgKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBicm93c2VyIGdsb2JhbFxuICAgIGdsb2JhbC5maXp6eVVJVXRpbHMgPSBmYWN0b3J5KCBnbG9iYWwgKTtcbiAgfVxuXG59KCB0aGlzLCBmdW5jdGlvbiBmYWN0b3J5KCBnbG9iYWwgKSB7XG5cbmxldCB1dGlscyA9IHt9O1xuXG4vLyAtLS0tLSBleHRlbmQgLS0tLS0gLy9cblxuLy8gZXh0ZW5kcyBvYmplY3RzXG51dGlscy5leHRlbmQgPSBmdW5jdGlvbiggYSwgYiApIHtcbiAgcmV0dXJuIE9iamVjdC5hc3NpZ24oIGEsIGIgKTtcbn07XG5cbi8vIC0tLS0tIG1vZHVsbyAtLS0tLSAvL1xuXG51dGlscy5tb2R1bG8gPSBmdW5jdGlvbiggbnVtLCBkaXYgKSB7XG4gIHJldHVybiAoICggbnVtICUgZGl2ICkgKyBkaXYgKSAlIGRpdjtcbn07XG5cbi8vIC0tLS0tIG1ha2VBcnJheSAtLS0tLSAvL1xuXG4vLyB0dXJuIGVsZW1lbnQgb3Igbm9kZUxpc3QgaW50byBhbiBhcnJheVxudXRpbHMubWFrZUFycmF5ID0gZnVuY3Rpb24oIG9iaiApIHtcbiAgLy8gdXNlIG9iamVjdCBpZiBhbHJlYWR5IGFuIGFycmF5XG4gIGlmICggQXJyYXkuaXNBcnJheSggb2JqICkgKSByZXR1cm4gb2JqO1xuXG4gIC8vIHJldHVybiBlbXB0eSBhcnJheSBpZiB1bmRlZmluZWQgb3IgbnVsbC4gIzZcbiAgaWYgKCBvYmogPT09IG51bGwgfHwgb2JqID09PSB1bmRlZmluZWQgKSByZXR1cm4gW107XG5cbiAgbGV0IGlzQXJyYXlMaWtlID0gdHlwZW9mIG9iaiA9PSAnb2JqZWN0JyAmJiB0eXBlb2Ygb2JqLmxlbmd0aCA9PSAnbnVtYmVyJztcbiAgLy8gY29udmVydCBub2RlTGlzdCB0byBhcnJheVxuICBpZiAoIGlzQXJyYXlMaWtlICkgcmV0dXJuIFsgLi4ub2JqIF07XG5cbiAgLy8gYXJyYXkgb2Ygc2luZ2xlIGluZGV4XG4gIHJldHVybiBbIG9iaiBdO1xufTtcblxuLy8gLS0tLS0gcmVtb3ZlRnJvbSAtLS0tLSAvL1xuXG51dGlscy5yZW1vdmVGcm9tID0gZnVuY3Rpb24oIGFyeSwgb2JqICkge1xuICBsZXQgaW5kZXggPSBhcnkuaW5kZXhPZiggb2JqICk7XG4gIGlmICggaW5kZXggIT0gLTEgKSB7XG4gICAgYXJ5LnNwbGljZSggaW5kZXgsIDEgKTtcbiAgfVxufTtcblxuLy8gLS0tLS0gZ2V0UGFyZW50IC0tLS0tIC8vXG5cbnV0aWxzLmdldFBhcmVudCA9IGZ1bmN0aW9uKCBlbGVtLCBzZWxlY3RvciApIHtcbiAgd2hpbGUgKCBlbGVtLnBhcmVudE5vZGUgJiYgZWxlbSAhPSBkb2N1bWVudC5ib2R5ICkge1xuICAgIGVsZW0gPSBlbGVtLnBhcmVudE5vZGU7XG4gICAgaWYgKCBlbGVtLm1hdGNoZXMoIHNlbGVjdG9yICkgKSByZXR1cm4gZWxlbTtcbiAgfVxufTtcblxuLy8gLS0tLS0gZ2V0UXVlcnlFbGVtZW50IC0tLS0tIC8vXG5cbi8vIHVzZSBlbGVtZW50IGFzIHNlbGVjdG9yIHN0cmluZ1xudXRpbHMuZ2V0UXVlcnlFbGVtZW50ID0gZnVuY3Rpb24oIGVsZW0gKSB7XG4gIGlmICggdHlwZW9mIGVsZW0gPT0gJ3N0cmluZycgKSB7XG4gICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIGVsZW0gKTtcbiAgfVxuICByZXR1cm4gZWxlbTtcbn07XG5cbi8vIC0tLS0tIGhhbmRsZUV2ZW50IC0tLS0tIC8vXG5cbi8vIGVuYWJsZSAub250eXBlIHRvIHRyaWdnZXIgZnJvbSAuYWRkRXZlbnRMaXN0ZW5lciggZWxlbSwgJ3R5cGUnIClcbnV0aWxzLmhhbmRsZUV2ZW50ID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuICBsZXQgbWV0aG9kID0gJ29uJyArIGV2ZW50LnR5cGU7XG4gIGlmICggdGhpc1sgbWV0aG9kIF0gKSB7XG4gICAgdGhpc1sgbWV0aG9kIF0oIGV2ZW50ICk7XG4gIH1cbn07XG5cbi8vIC0tLS0tIGZpbHRlckZpbmRFbGVtZW50cyAtLS0tLSAvL1xuXG51dGlscy5maWx0ZXJGaW5kRWxlbWVudHMgPSBmdW5jdGlvbiggZWxlbXMsIHNlbGVjdG9yICkge1xuICAvLyBtYWtlIGFycmF5IG9mIGVsZW1zXG4gIGVsZW1zID0gdXRpbHMubWFrZUFycmF5KCBlbGVtcyApO1xuXG4gIHJldHVybiBlbGVtc1xuICAgIC8vIGNoZWNrIHRoYXQgZWxlbSBpcyBhbiBhY3R1YWwgZWxlbWVudFxuICAgIC5maWx0ZXIoICggZWxlbSApID0+IGVsZW0gaW5zdGFuY2VvZiBIVE1MRWxlbWVudCApXG4gICAgLnJlZHVjZSggKCBmZkVsZW1zLCBlbGVtICkgPT4ge1xuICAgICAgLy8gYWRkIGVsZW0gaWYgbm8gc2VsZWN0b3JcbiAgICAgIGlmICggIXNlbGVjdG9yICkge1xuICAgICAgICBmZkVsZW1zLnB1c2goIGVsZW0gKTtcbiAgICAgICAgcmV0dXJuIGZmRWxlbXM7XG4gICAgICB9XG4gICAgICAvLyBmaWx0ZXIgJiBmaW5kIGl0ZW1zIGlmIHdlIGhhdmUgYSBzZWxlY3RvclxuICAgICAgLy8gZmlsdGVyXG4gICAgICBpZiAoIGVsZW0ubWF0Y2hlcyggc2VsZWN0b3IgKSApIHtcbiAgICAgICAgZmZFbGVtcy5wdXNoKCBlbGVtICk7XG4gICAgICB9XG4gICAgICAvLyBmaW5kIGNoaWxkcmVuXG4gICAgICBsZXQgY2hpbGRFbGVtcyA9IGVsZW0ucXVlcnlTZWxlY3RvckFsbCggc2VsZWN0b3IgKTtcbiAgICAgIC8vIGNvbmNhdCBjaGlsZEVsZW1zIHRvIGZpbHRlckZvdW5kIGFycmF5XG4gICAgICBmZkVsZW1zID0gZmZFbGVtcy5jb25jYXQoIC4uLmNoaWxkRWxlbXMgKTtcbiAgICAgIHJldHVybiBmZkVsZW1zO1xuICAgIH0sIFtdICk7XG59O1xuXG4vLyAtLS0tLSBkZWJvdW5jZU1ldGhvZCAtLS0tLSAvL1xuXG51dGlscy5kZWJvdW5jZU1ldGhvZCA9IGZ1bmN0aW9uKCBfY2xhc3MsIG1ldGhvZE5hbWUsIHRocmVzaG9sZCApIHtcbiAgdGhyZXNob2xkID0gdGhyZXNob2xkIHx8IDEwMDtcbiAgLy8gb3JpZ2luYWwgbWV0aG9kXG4gIGxldCBtZXRob2QgPSBfY2xhc3MucHJvdG90eXBlWyBtZXRob2ROYW1lIF07XG4gIGxldCB0aW1lb3V0TmFtZSA9IG1ldGhvZE5hbWUgKyAnVGltZW91dCc7XG5cbiAgX2NsYXNzLnByb3RvdHlwZVsgbWV0aG9kTmFtZSBdID0gZnVuY3Rpb24oKSB7XG4gICAgY2xlYXJUaW1lb3V0KCB0aGlzWyB0aW1lb3V0TmFtZSBdICk7XG5cbiAgICBsZXQgYXJncyA9IGFyZ3VtZW50cztcbiAgICB0aGlzWyB0aW1lb3V0TmFtZSBdID0gc2V0VGltZW91dCggKCkgPT4ge1xuICAgICAgbWV0aG9kLmFwcGx5KCB0aGlzLCBhcmdzICk7XG4gICAgICBkZWxldGUgdGhpc1sgdGltZW91dE5hbWUgXTtcbiAgICB9LCB0aHJlc2hvbGQgKTtcbiAgfTtcbn07XG5cbi8vIC0tLS0tIGRvY1JlYWR5IC0tLS0tIC8vXG5cbnV0aWxzLmRvY1JlYWR5ID0gZnVuY3Rpb24oIG9uRG9jUmVhZHkgKSB7XG4gIGxldCByZWFkeVN0YXRlID0gZG9jdW1lbnQucmVhZHlTdGF0ZTtcbiAgaWYgKCByZWFkeVN0YXRlID09ICdjb21wbGV0ZScgfHwgcmVhZHlTdGF0ZSA9PSAnaW50ZXJhY3RpdmUnICkge1xuICAgIC8vIGRvIGFzeW5jIHRvIGFsbG93IGZvciBvdGhlciBzY3JpcHRzIHRvIHJ1bi4gbWV0YWZpenp5L2ZsaWNraXR5IzQ0MVxuICAgIHNldFRpbWVvdXQoIG9uRG9jUmVhZHkgKTtcbiAgfSBlbHNlIHtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCAnRE9NQ29udGVudExvYWRlZCcsIG9uRG9jUmVhZHkgKTtcbiAgfVxufTtcblxuLy8gLS0tLS0gaHRtbEluaXQgLS0tLS0gLy9cblxuLy8gaHR0cDovL2JpdC5seS8zb1lMdXNjXG51dGlscy50b0Rhc2hlZCA9IGZ1bmN0aW9uKCBzdHIgKSB7XG4gIHJldHVybiBzdHIucmVwbGFjZSggLyguKShbQS1aXSkvZywgZnVuY3Rpb24oIG1hdGNoLCAkMSwgJDIgKSB7XG4gICAgcmV0dXJuICQxICsgJy0nICsgJDI7XG4gIH0gKS50b0xvd2VyQ2FzZSgpO1xufTtcblxubGV0IGNvbnNvbGUgPSBnbG9iYWwuY29uc29sZTtcblxuLy8gYWxsb3cgdXNlciB0byBpbml0aWFsaXplIGNsYXNzZXMgdmlhIFtkYXRhLW5hbWVzcGFjZV0gb3IgLmpzLW5hbWVzcGFjZSBjbGFzc1xuLy8gaHRtbEluaXQoIFdpZGdldCwgJ3dpZGdldE5hbWUnIClcbi8vIG9wdGlvbnMgYXJlIHBhcnNlZCBmcm9tIGRhdGEtbmFtZXNwYWNlLW9wdGlvbnNcbnV0aWxzLmh0bWxJbml0ID0gZnVuY3Rpb24oIFdpZGdldENsYXNzLCBuYW1lc3BhY2UgKSB7XG4gIHV0aWxzLmRvY1JlYWR5KCBmdW5jdGlvbigpIHtcbiAgICBsZXQgZGFzaGVkTmFtZXNwYWNlID0gdXRpbHMudG9EYXNoZWQoIG5hbWVzcGFjZSApO1xuICAgIGxldCBkYXRhQXR0ciA9ICdkYXRhLScgKyBkYXNoZWROYW1lc3BhY2U7XG4gICAgbGV0IGRhdGFBdHRyRWxlbXMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCBgWyR7ZGF0YUF0dHJ9XWAgKTtcbiAgICBsZXQgalF1ZXJ5ID0gZ2xvYmFsLmpRdWVyeTtcblxuICAgIFsgLi4uZGF0YUF0dHJFbGVtcyBdLmZvckVhY2goICggZWxlbSApID0+IHtcbiAgICAgIGxldCBhdHRyID0gZWxlbS5nZXRBdHRyaWJ1dGUoIGRhdGFBdHRyICk7XG4gICAgICBsZXQgb3B0aW9ucztcbiAgICAgIHRyeSB7XG4gICAgICAgIG9wdGlvbnMgPSBhdHRyICYmIEpTT04ucGFyc2UoIGF0dHIgKTtcbiAgICAgIH0gY2F0Y2ggKCBlcnJvciApIHtcbiAgICAgICAgLy8gbG9nIGVycm9yLCBkbyBub3QgaW5pdGlhbGl6ZVxuICAgICAgICBpZiAoIGNvbnNvbGUgKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvciggYEVycm9yIHBhcnNpbmcgJHtkYXRhQXR0cn0gb24gJHtlbGVtLmNsYXNzTmFtZX06ICR7ZXJyb3J9YCApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIC8vIGluaXRpYWxpemVcbiAgICAgIGxldCBpbnN0YW5jZSA9IG5ldyBXaWRnZXRDbGFzcyggZWxlbSwgb3B0aW9ucyApO1xuICAgICAgLy8gbWFrZSBhdmFpbGFibGUgdmlhICQoKS5kYXRhKCduYW1lc3BhY2UnKVxuICAgICAgaWYgKCBqUXVlcnkgKSB7XG4gICAgICAgIGpRdWVyeS5kYXRhKCBlbGVtLCBuYW1lc3BhY2UsIGluc3RhbmNlICk7XG4gICAgICB9XG4gICAgfSApO1xuXG4gIH0gKTtcbn07XG5cbi8vIC0tLS0tICAtLS0tLSAvL1xuXG5yZXR1cm4gdXRpbHM7XG5cbn0gKSApO1xuIiwiLy8gYWRkLCByZW1vdmUgY2VsbFxuKCBmdW5jdGlvbiggd2luZG93LCBmYWN0b3J5ICkge1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cbiAgaWYgKCB0eXBlb2YgbW9kdWxlID09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzICkge1xuICAgIC8vIENvbW1vbkpTXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KFxuICAgICAgICByZXF1aXJlKCcuL2NvcmUnKSxcbiAgICAgICAgcmVxdWlyZSgnZml6enktdWktdXRpbHMnKSxcbiAgICApO1xuICB9IGVsc2Uge1xuICAgIC8vIGJyb3dzZXIgZ2xvYmFsXG4gICAgZmFjdG9yeShcbiAgICAgICAgd2luZG93LkZsaWNraXR5LFxuICAgICAgICB3aW5kb3cuZml6enlVSVV0aWxzLFxuICAgICk7XG4gIH1cblxufSggdHlwZW9mIHdpbmRvdyAhPSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHRoaXMsIGZ1bmN0aW9uIGZhY3RvcnkoIEZsaWNraXR5LCB1dGlscyApIHtcblxuLy8gYXBwZW5kIGNlbGxzIHRvIGEgZG9jdW1lbnQgZnJhZ21lbnRcbmZ1bmN0aW9uIGdldENlbGxzRnJhZ21lbnQoIGNlbGxzICkge1xuICBsZXQgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG4gIGNlbGxzLmZvckVhY2goICggY2VsbCApID0+IGZyYWdtZW50LmFwcGVuZENoaWxkKCBjZWxsLmVsZW1lbnQgKSApO1xuICByZXR1cm4gZnJhZ21lbnQ7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGFkZC9yZW1vdmUgY2VsbCBwcm90b3R5cGUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxubGV0IHByb3RvID0gRmxpY2tpdHkucHJvdG90eXBlO1xuXG4vKipcbiAqIEluc2VydCwgcHJlcGVuZCwgb3IgYXBwZW5kIGNlbGxzXG4gKiBAcGFyYW0ge1tFbGVtZW50LCBBcnJheSwgTm9kZUxpc3RdfSBlbGVtcyAtIEVsZW1lbnRzIHRvIGluc2VydFxuICogQHBhcmFtIHtJbnRlZ2VyfSBpbmRleCAtIFplcm8tYmFzZWQgbnVtYmVyIHRvIGluc2VydFxuICovXG5wcm90by5pbnNlcnQgPSBmdW5jdGlvbiggZWxlbXMsIGluZGV4ICkge1xuICBsZXQgY2VsbHMgPSB0aGlzLl9tYWtlQ2VsbHMoIGVsZW1zICk7XG4gIGlmICggIWNlbGxzIHx8ICFjZWxscy5sZW5ndGggKSByZXR1cm47XG5cbiAgbGV0IGxlbiA9IHRoaXMuY2VsbHMubGVuZ3RoO1xuICAvLyBkZWZhdWx0IHRvIGFwcGVuZFxuICBpbmRleCA9IGluZGV4ID09PSB1bmRlZmluZWQgPyBsZW4gOiBpbmRleDtcbiAgLy8gYWRkIGNlbGxzIHdpdGggZG9jdW1lbnQgZnJhZ21lbnRcbiAgbGV0IGZyYWdtZW50ID0gZ2V0Q2VsbHNGcmFnbWVudCggY2VsbHMgKTtcbiAgLy8gYXBwZW5kIHRvIHNsaWRlclxuICBsZXQgaXNBcHBlbmQgPSBpbmRleCA9PT0gbGVuO1xuICBpZiAoIGlzQXBwZW5kICkge1xuICAgIHRoaXMuc2xpZGVyLmFwcGVuZENoaWxkKCBmcmFnbWVudCApO1xuICB9IGVsc2Uge1xuICAgIGxldCBpbnNlcnRDZWxsRWxlbWVudCA9IHRoaXMuY2VsbHNbIGluZGV4IF0uZWxlbWVudDtcbiAgICB0aGlzLnNsaWRlci5pbnNlcnRCZWZvcmUoIGZyYWdtZW50LCBpbnNlcnRDZWxsRWxlbWVudCApO1xuICB9XG4gIC8vIGFkZCB0byB0aGlzLmNlbGxzXG4gIGlmICggaW5kZXggPT09IDAgKSB7XG4gICAgLy8gcHJlcGVuZCwgYWRkIHRvIHN0YXJ0XG4gICAgdGhpcy5jZWxscyA9IGNlbGxzLmNvbmNhdCggdGhpcy5jZWxscyApO1xuICB9IGVsc2UgaWYgKCBpc0FwcGVuZCApIHtcbiAgICAvLyBhcHBlbmQsIGFkZCB0byBlbmRcbiAgICB0aGlzLmNlbGxzID0gdGhpcy5jZWxscy5jb25jYXQoIGNlbGxzICk7XG4gIH0gZWxzZSB7XG4gICAgLy8gaW5zZXJ0IGluIHRoaXMuY2VsbHNcbiAgICBsZXQgZW5kQ2VsbHMgPSB0aGlzLmNlbGxzLnNwbGljZSggaW5kZXgsIGxlbiAtIGluZGV4ICk7XG4gICAgdGhpcy5jZWxscyA9IHRoaXMuY2VsbHMuY29uY2F0KCBjZWxscyApLmNvbmNhdCggZW5kQ2VsbHMgKTtcbiAgfVxuXG4gIHRoaXMuX3NpemVDZWxscyggY2VsbHMgKTtcbiAgdGhpcy5jZWxsQ2hhbmdlKCBpbmRleCApO1xuICB0aGlzLnBvc2l0aW9uU2xpZGVyQXRTZWxlY3RlZCgpO1xufTtcblxucHJvdG8uYXBwZW5kID0gZnVuY3Rpb24oIGVsZW1zICkge1xuICB0aGlzLmluc2VydCggZWxlbXMsIHRoaXMuY2VsbHMubGVuZ3RoICk7XG59O1xuXG5wcm90by5wcmVwZW5kID0gZnVuY3Rpb24oIGVsZW1zICkge1xuICB0aGlzLmluc2VydCggZWxlbXMsIDAgKTtcbn07XG5cbi8qKlxuICogUmVtb3ZlIGNlbGxzXG4gKiBAcGFyYW0ge1tFbGVtZW50LCBBcnJheSwgTm9kZUxpc3RdfSBlbGVtcyAtIEVMZW1lbnRzIHRvIHJlbW92ZVxuICovXG5wcm90by5yZW1vdmUgPSBmdW5jdGlvbiggZWxlbXMgKSB7XG4gIGxldCBjZWxscyA9IHRoaXMuZ2V0Q2VsbHMoIGVsZW1zICk7XG4gIGlmICggIWNlbGxzIHx8ICFjZWxscy5sZW5ndGggKSByZXR1cm47XG5cbiAgbGV0IG1pbkNlbGxJbmRleCA9IHRoaXMuY2VsbHMubGVuZ3RoIC0gMTtcbiAgLy8gcmVtb3ZlIGNlbGxzIGZyb20gY29sbGVjdGlvbiAmIERPTVxuICBjZWxscy5mb3JFYWNoKCAoIGNlbGwgKSA9PiB7XG4gICAgY2VsbC5yZW1vdmUoKTtcbiAgICBsZXQgaW5kZXggPSB0aGlzLmNlbGxzLmluZGV4T2YoIGNlbGwgKTtcbiAgICBtaW5DZWxsSW5kZXggPSBNYXRoLm1pbiggaW5kZXgsIG1pbkNlbGxJbmRleCApO1xuICAgIHV0aWxzLnJlbW92ZUZyb20oIHRoaXMuY2VsbHMsIGNlbGwgKTtcbiAgfSApO1xuXG4gIHRoaXMuY2VsbENoYW5nZSggbWluQ2VsbEluZGV4ICk7XG4gIHRoaXMucG9zaXRpb25TbGlkZXJBdFNlbGVjdGVkKCk7XG59O1xuXG4vKipcbiAqIGxvZ2ljIHRvIGJlIHJ1biBhZnRlciBhIGNlbGwncyBzaXplIGNoYW5nZXNcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbSAtIGNlbGwncyBlbGVtZW50XG4gKi9cbnByb3RvLmNlbGxTaXplQ2hhbmdlID0gZnVuY3Rpb24oIGVsZW0gKSB7XG4gIGxldCBjZWxsID0gdGhpcy5nZXRDZWxsKCBlbGVtICk7XG4gIGlmICggIWNlbGwgKSByZXR1cm47XG5cbiAgY2VsbC5nZXRTaXplKCk7XG5cbiAgbGV0IGluZGV4ID0gdGhpcy5jZWxscy5pbmRleE9mKCBjZWxsICk7XG4gIHRoaXMuY2VsbENoYW5nZSggaW5kZXggKTtcbiAgLy8gZG8gbm90IHBvc2l0aW9uIHNsaWRlciBhZnRlciBsYXp5IGxvYWRcbn07XG5cbi8qKlxuICogbG9naWMgYW55IHRpbWUgYSBjZWxsIGlzIGNoYW5nZWQ6IGFkZGVkLCByZW1vdmVkLCBvciBzaXplIGNoYW5nZWRcbiAqIEBwYXJhbSB7SW50ZWdlcn0gY2hhbmdlZENlbGxJbmRleCAtIGluZGV4IG9mIHRoZSBjaGFuZ2VkIGNlbGwsIG9wdGlvbmFsXG4gKi9cbnByb3RvLmNlbGxDaGFuZ2UgPSBmdW5jdGlvbiggY2hhbmdlZENlbGxJbmRleCApIHtcbiAgbGV0IHByZXZTZWxlY3RlZEVsZW0gPSB0aGlzLnNlbGVjdGVkRWxlbWVudDtcbiAgdGhpcy5fcG9zaXRpb25DZWxscyggY2hhbmdlZENlbGxJbmRleCApO1xuICB0aGlzLl91cGRhdGVXcmFwU2hpZnRDZWxscygpO1xuICB0aGlzLnNldEdhbGxlcnlTaXplKCk7XG4gIC8vIHVwZGF0ZSBzZWxlY3RlZEluZGV4LCB0cnkgdG8gbWFpbnRhaW4gcG9zaXRpb24gJiBzZWxlY3QgcHJldmlvdXMgc2VsZWN0ZWQgZWxlbWVudFxuICBsZXQgY2VsbCA9IHRoaXMuZ2V0Q2VsbCggcHJldlNlbGVjdGVkRWxlbSApO1xuICBpZiAoIGNlbGwgKSB0aGlzLnNlbGVjdGVkSW5kZXggPSB0aGlzLmdldENlbGxTbGlkZUluZGV4KCBjZWxsICk7XG4gIHRoaXMuc2VsZWN0ZWRJbmRleCA9IE1hdGgubWluKCB0aGlzLnNsaWRlcy5sZW5ndGggLSAxLCB0aGlzLnNlbGVjdGVkSW5kZXggKTtcblxuICB0aGlzLmVtaXRFdmVudCggJ2NlbGxDaGFuZ2UnLCBbIGNoYW5nZWRDZWxsSW5kZXggXSApO1xuICAvLyBwb3NpdGlvbiBzbGlkZXJcbiAgdGhpcy5zZWxlY3QoIHRoaXMuc2VsZWN0ZWRJbmRleCApO1xufTtcblxuLy8gLS0tLS0gIC0tLS0tIC8vXG5cbnJldHVybiBGbGlja2l0eTtcblxufSApICk7XG4iLCIvLyBhbmltYXRlXG4oIGZ1bmN0aW9uKCB3aW5kb3csIGZhY3RvcnkgKSB7XG4gIC8vIHVuaXZlcnNhbCBtb2R1bGUgZGVmaW5pdGlvblxuICBpZiAoIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG4gICAgLy8gQ29tbW9uSlNcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoIHJlcXVpcmUoJ2Zpenp5LXVpLXV0aWxzJykgKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBicm93c2VyIGdsb2JhbFxuICAgIHdpbmRvdy5GbGlja2l0eSA9IHdpbmRvdy5GbGlja2l0eSB8fCB7fTtcbiAgICB3aW5kb3cuRmxpY2tpdHkuYW5pbWF0ZVByb3RvdHlwZSA9IGZhY3RvcnkoIHdpbmRvdy5maXp6eVVJVXRpbHMgKTtcbiAgfVxuXG59KCB0eXBlb2Ygd2luZG93ICE9ICd1bmRlZmluZWQnID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24gZmFjdG9yeSggdXRpbHMgKSB7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGFuaW1hdGUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxubGV0IHByb3RvID0ge307XG5cbnByb3RvLnN0YXJ0QW5pbWF0aW9uID0gZnVuY3Rpb24oKSB7XG4gIGlmICggdGhpcy5pc0FuaW1hdGluZyApIHJldHVybjtcblxuICB0aGlzLmlzQW5pbWF0aW5nID0gdHJ1ZTtcbiAgdGhpcy5yZXN0aW5nRnJhbWVzID0gMDtcbiAgdGhpcy5hbmltYXRlKCk7XG59O1xuXG5wcm90by5hbmltYXRlID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuYXBwbHlEcmFnRm9yY2UoKTtcbiAgdGhpcy5hcHBseVNlbGVjdGVkQXR0cmFjdGlvbigpO1xuXG4gIGxldCBwcmV2aW91c1ggPSB0aGlzLng7XG5cbiAgdGhpcy5pbnRlZ3JhdGVQaHlzaWNzKCk7XG4gIHRoaXMucG9zaXRpb25TbGlkZXIoKTtcbiAgdGhpcy5zZXR0bGUoIHByZXZpb3VzWCApO1xuICAvLyBhbmltYXRlIG5leHQgZnJhbWVcbiAgaWYgKCB0aGlzLmlzQW5pbWF0aW5nICkgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCAoKSA9PiB0aGlzLmFuaW1hdGUoKSApO1xufTtcblxucHJvdG8ucG9zaXRpb25TbGlkZXIgPSBmdW5jdGlvbigpIHtcbiAgbGV0IHggPSB0aGlzLng7XG4gIC8vIHdyYXAgcG9zaXRpb24gYXJvdW5kXG4gIGlmICggdGhpcy5pc1dyYXBwaW5nICkge1xuICAgIHggPSB1dGlscy5tb2R1bG8oIHgsIHRoaXMuc2xpZGVhYmxlV2lkdGggKSAtIHRoaXMuc2xpZGVhYmxlV2lkdGg7XG4gICAgdGhpcy5zaGlmdFdyYXBDZWxscyggeCApO1xuICB9XG5cbiAgdGhpcy5zZXRUcmFuc2xhdGVYKCB4LCB0aGlzLmlzQW5pbWF0aW5nICk7XG4gIHRoaXMuZGlzcGF0Y2hTY3JvbGxFdmVudCgpO1xufTtcblxucHJvdG8uc2V0VHJhbnNsYXRlWCA9IGZ1bmN0aW9uKCB4LCBpczNkICkge1xuICB4ICs9IHRoaXMuY3Vyc29yUG9zaXRpb247XG4gIC8vIHJldmVyc2UgaWYgcmlnaHQtdG8tbGVmdCBhbmQgdXNpbmcgdHJhbnNmb3JtXG4gIGlmICggdGhpcy5vcHRpb25zLnJpZ2h0VG9MZWZ0ICkgeCA9IC14O1xuICBsZXQgdHJhbnNsYXRlWCA9IHRoaXMuZ2V0UG9zaXRpb25WYWx1ZSggeCApO1xuICAvLyB1c2UgM0QgdHJhbnNmb3JtcyBmb3IgaGFyZHdhcmUgYWNjZWxlcmF0aW9uIG9uIGlPU1xuICAvLyBidXQgdXNlIDJEIHdoZW4gc2V0dGxlZCwgZm9yIGJldHRlciBmb250LXJlbmRlcmluZ1xuICB0aGlzLnNsaWRlci5zdHlsZS50cmFuc2Zvcm0gPSBpczNkID9cbiAgICBgdHJhbnNsYXRlM2QoJHt0cmFuc2xhdGVYfSwwLDApYCA6IGB0cmFuc2xhdGVYKCR7dHJhbnNsYXRlWH0pYDtcbn07XG5cbnByb3RvLmRpc3BhdGNoU2Nyb2xsRXZlbnQgPSBmdW5jdGlvbigpIHtcbiAgbGV0IGZpcnN0U2xpZGUgPSB0aGlzLnNsaWRlc1swXTtcbiAgaWYgKCAhZmlyc3RTbGlkZSApIHJldHVybjtcblxuICBsZXQgcG9zaXRpb25YID0gLXRoaXMueCAtIGZpcnN0U2xpZGUudGFyZ2V0O1xuICBsZXQgcHJvZ3Jlc3MgPSBwb3NpdGlvblggLyB0aGlzLnNsaWRlc1dpZHRoO1xuICB0aGlzLmRpc3BhdGNoRXZlbnQoICdzY3JvbGwnLCBudWxsLCBbIHByb2dyZXNzLCBwb3NpdGlvblggXSApO1xufTtcblxucHJvdG8ucG9zaXRpb25TbGlkZXJBdFNlbGVjdGVkID0gZnVuY3Rpb24oKSB7XG4gIGlmICggIXRoaXMuY2VsbHMubGVuZ3RoICkgcmV0dXJuO1xuXG4gIHRoaXMueCA9IC10aGlzLnNlbGVjdGVkU2xpZGUudGFyZ2V0O1xuICB0aGlzLnZlbG9jaXR5ID0gMDsgLy8gc3RvcCB3b2JibGVcbiAgdGhpcy5wb3NpdGlvblNsaWRlcigpO1xufTtcblxucHJvdG8uZ2V0UG9zaXRpb25WYWx1ZSA9IGZ1bmN0aW9uKCBwb3NpdGlvbiApIHtcbiAgaWYgKCB0aGlzLm9wdGlvbnMucGVyY2VudFBvc2l0aW9uICkge1xuICAgIC8vIHBlcmNlbnQgcG9zaXRpb24sIHJvdW5kIHRvIDIgZGlnaXRzLCBsaWtlIDEyLjM0JVxuICAgIHJldHVybiAoIE1hdGgucm91bmQoICggcG9zaXRpb24gLyB0aGlzLnNpemUuaW5uZXJXaWR0aCApICogMTAwMDAgKSAqIDAuMDEgKSArICclJztcbiAgfSBlbHNlIHtcbiAgICAvLyBwaXhlbCBwb3NpdGlvbmluZ1xuICAgIHJldHVybiBNYXRoLnJvdW5kKCBwb3NpdGlvbiApICsgJ3B4JztcbiAgfVxufTtcblxucHJvdG8uc2V0dGxlID0gZnVuY3Rpb24oIHByZXZpb3VzWCApIHtcbiAgLy8ga2VlcCB0cmFjayBvZiBmcmFtZXMgd2hlcmUgeCBoYXNuJ3QgbW92ZWRcbiAgbGV0IGlzUmVzdGluZyA9ICF0aGlzLmlzUG9pbnRlckRvd24gJiZcbiAgICAgIE1hdGgucm91bmQoIHRoaXMueCAqIDEwMCApID09PSBNYXRoLnJvdW5kKCBwcmV2aW91c1ggKiAxMDAgKTtcbiAgaWYgKCBpc1Jlc3RpbmcgKSB0aGlzLnJlc3RpbmdGcmFtZXMrKztcbiAgLy8gc3RvcCBhbmltYXRpbmcgaWYgcmVzdGluZyBmb3IgMyBvciBtb3JlIGZyYW1lc1xuICBpZiAoIHRoaXMucmVzdGluZ0ZyYW1lcyA+IDIgKSB7XG4gICAgdGhpcy5pc0FuaW1hdGluZyA9IGZhbHNlO1xuICAgIGRlbGV0ZSB0aGlzLmlzRnJlZVNjcm9sbGluZztcbiAgICAvLyByZW5kZXIgcG9zaXRpb24gd2l0aCB0cmFuc2xhdGVYIHdoZW4gc2V0dGxlZFxuICAgIHRoaXMucG9zaXRpb25TbGlkZXIoKTtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQoICdzZXR0bGUnLCBudWxsLCBbIHRoaXMuc2VsZWN0ZWRJbmRleCBdICk7XG4gIH1cbn07XG5cbnByb3RvLnNoaWZ0V3JhcENlbGxzID0gZnVuY3Rpb24oIHggKSB7XG4gIC8vIHNoaWZ0IGJlZm9yZSBjZWxsc1xuICBsZXQgYmVmb3JlR2FwID0gdGhpcy5jdXJzb3JQb3NpdGlvbiArIHg7XG4gIHRoaXMuX3NoaWZ0Q2VsbHMoIHRoaXMuYmVmb3JlU2hpZnRDZWxscywgYmVmb3JlR2FwLCAtMSApO1xuICAvLyBzaGlmdCBhZnRlciBjZWxsc1xuICBsZXQgYWZ0ZXJHYXAgPSB0aGlzLnNpemUuaW5uZXJXaWR0aCAtICggeCArIHRoaXMuc2xpZGVhYmxlV2lkdGggKyB0aGlzLmN1cnNvclBvc2l0aW9uICk7XG4gIHRoaXMuX3NoaWZ0Q2VsbHMoIHRoaXMuYWZ0ZXJTaGlmdENlbGxzLCBhZnRlckdhcCwgMSApO1xufTtcblxucHJvdG8uX3NoaWZ0Q2VsbHMgPSBmdW5jdGlvbiggY2VsbHMsIGdhcCwgc2hpZnQgKSB7XG4gIGNlbGxzLmZvckVhY2goICggY2VsbCApID0+IHtcbiAgICBsZXQgY2VsbFNoaWZ0ID0gZ2FwID4gMCA/IHNoaWZ0IDogMDtcbiAgICB0aGlzLl93cmFwU2hpZnRDZWxsKCBjZWxsLCBjZWxsU2hpZnQgKTtcbiAgICBnYXAgLT0gY2VsbC5zaXplLm91dGVyV2lkdGg7XG4gIH0gKTtcbn07XG5cbnByb3RvLl91bnNoaWZ0Q2VsbHMgPSBmdW5jdGlvbiggY2VsbHMgKSB7XG4gIGlmICggIWNlbGxzIHx8ICFjZWxscy5sZW5ndGggKSByZXR1cm47XG5cbiAgY2VsbHMuZm9yRWFjaCggKCBjZWxsICkgPT4gdGhpcy5fd3JhcFNoaWZ0Q2VsbCggY2VsbCwgMCApICk7XG59O1xuXG4vLyBAcGFyYW0ge0ludGVnZXJ9IHNoaWZ0IC0gMCwgMSwgb3IgLTFcbnByb3RvLl93cmFwU2hpZnRDZWxsID0gZnVuY3Rpb24oIGNlbGwsIHNoaWZ0ICkge1xuICB0aGlzLl9yZW5kZXJDZWxsUG9zaXRpb24oIGNlbGwsIGNlbGwueCArIHRoaXMuc2xpZGVhYmxlV2lkdGggKiBzaGlmdCApO1xufTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gcGh5c2ljcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG5wcm90by5pbnRlZ3JhdGVQaHlzaWNzID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMueCArPSB0aGlzLnZlbG9jaXR5O1xuICB0aGlzLnZlbG9jaXR5ICo9IHRoaXMuZ2V0RnJpY3Rpb25GYWN0b3IoKTtcbn07XG5cbnByb3RvLmFwcGx5Rm9yY2UgPSBmdW5jdGlvbiggZm9yY2UgKSB7XG4gIHRoaXMudmVsb2NpdHkgKz0gZm9yY2U7XG59O1xuXG5wcm90by5nZXRGcmljdGlvbkZhY3RvciA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gMSAtIHRoaXMub3B0aW9uc1sgdGhpcy5pc0ZyZWVTY3JvbGxpbmcgPyAnZnJlZVNjcm9sbEZyaWN0aW9uJyA6ICdmcmljdGlvbicgXTtcbn07XG5cbnByb3RvLmdldFJlc3RpbmdQb3NpdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAvLyBteSB0aGFua3MgdG8gU3RldmVuIFdpdHRlbnMsIHdobyBzaW1wbGlmaWVkIHRoaXMgbWF0aCBncmVhdGx5XG4gIHJldHVybiB0aGlzLnggKyB0aGlzLnZlbG9jaXR5IC8gKCAxIC0gdGhpcy5nZXRGcmljdGlvbkZhY3RvcigpICk7XG59O1xuXG5wcm90by5hcHBseURyYWdGb3JjZSA9IGZ1bmN0aW9uKCkge1xuICBpZiAoICF0aGlzLmlzRHJhZ2dhYmxlIHx8ICF0aGlzLmlzUG9pbnRlckRvd24gKSByZXR1cm47XG5cbiAgLy8gY2hhbmdlIHRoZSBwb3NpdGlvbiB0byBkcmFnIHBvc2l0aW9uIGJ5IGFwcGx5aW5nIGZvcmNlXG4gIGxldCBkcmFnVmVsb2NpdHkgPSB0aGlzLmRyYWdYIC0gdGhpcy54O1xuICBsZXQgZHJhZ0ZvcmNlID0gZHJhZ1ZlbG9jaXR5IC0gdGhpcy52ZWxvY2l0eTtcbiAgdGhpcy5hcHBseUZvcmNlKCBkcmFnRm9yY2UgKTtcbn07XG5cbnByb3RvLmFwcGx5U2VsZWN0ZWRBdHRyYWN0aW9uID0gZnVuY3Rpb24oKSB7XG4gIC8vIGRvIG5vdCBhdHRyYWN0IGlmIHBvaW50ZXIgZG93biBvciBubyBzbGlkZXNcbiAgbGV0IGRyYWdEb3duID0gdGhpcy5pc0RyYWdnYWJsZSAmJiB0aGlzLmlzUG9pbnRlckRvd247XG4gIGlmICggZHJhZ0Rvd24gfHwgdGhpcy5pc0ZyZWVTY3JvbGxpbmcgfHwgIXRoaXMuc2xpZGVzLmxlbmd0aCApIHJldHVybjtcblxuICBsZXQgZGlzdGFuY2UgPSB0aGlzLnNlbGVjdGVkU2xpZGUudGFyZ2V0ICogLTEgLSB0aGlzLng7XG4gIGxldCBmb3JjZSA9IGRpc3RhbmNlICogdGhpcy5vcHRpb25zLnNlbGVjdGVkQXR0cmFjdGlvbjtcbiAgdGhpcy5hcHBseUZvcmNlKCBmb3JjZSApO1xufTtcblxucmV0dXJuIHByb3RvO1xuXG59ICkgKTtcbiIsIi8vIEZsaWNraXR5LkNlbGxcbiggZnVuY3Rpb24oIHdpbmRvdywgZmFjdG9yeSApIHtcbiAgLy8gdW5pdmVyc2FsIG1vZHVsZSBkZWZpbml0aW9uXG4gIGlmICggdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyApIHtcbiAgICAvLyBDb21tb25KU1xuICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSggcmVxdWlyZSgnZ2V0LXNpemUnKSApO1xuICB9IGVsc2Uge1xuICAgIC8vIGJyb3dzZXIgZ2xvYmFsXG4gICAgd2luZG93LkZsaWNraXR5ID0gd2luZG93LkZsaWNraXR5IHx8IHt9O1xuICAgIHdpbmRvdy5GbGlja2l0eS5DZWxsID0gZmFjdG9yeSggd2luZG93LmdldFNpemUgKTtcbiAgfVxuXG59KCB0eXBlb2Ygd2luZG93ICE9ICd1bmRlZmluZWQnID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24gZmFjdG9yeSggZ2V0U2l6ZSApIHtcblxuY29uc3QgY2VsbENsYXNzTmFtZSA9ICdmbGlja2l0eS1jZWxsJztcblxuZnVuY3Rpb24gQ2VsbCggZWxlbSApIHtcbiAgdGhpcy5lbGVtZW50ID0gZWxlbTtcbiAgdGhpcy5lbGVtZW50LmNsYXNzTGlzdC5hZGQoIGNlbGxDbGFzc05hbWUgKTtcblxuICB0aGlzLnggPSAwO1xuICB0aGlzLnVuc2VsZWN0KCk7XG59XG5cbmxldCBwcm90byA9IENlbGwucHJvdG90eXBlO1xuXG5wcm90by5kZXN0cm95ID0gZnVuY3Rpb24oKSB7XG4gIC8vIHJlc2V0IHN0eWxlXG4gIHRoaXMudW5zZWxlY3QoKTtcbiAgdGhpcy5lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoIGNlbGxDbGFzc05hbWUgKTtcbiAgdGhpcy5lbGVtZW50LnN0eWxlLnRyYW5zZm9ybSA9ICcnO1xuICB0aGlzLmVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdhcmlhLWhpZGRlbicpO1xufTtcblxucHJvdG8uZ2V0U2l6ZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnNpemUgPSBnZXRTaXplKCB0aGlzLmVsZW1lbnQgKTtcbn07XG5cbnByb3RvLnNlbGVjdCA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnaXMtc2VsZWN0ZWQnKTtcbiAgdGhpcy5lbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nKTtcbn07XG5cbnByb3RvLnVuc2VsZWN0ID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdpcy1zZWxlY3RlZCcpO1xuICB0aGlzLmVsZW1lbnQuc2V0QXR0cmlidXRlKCAnYXJpYS1oaWRkZW4nLCAndHJ1ZScgKTtcbn07XG5cbnByb3RvLnJlbW92ZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmVsZW1lbnQucmVtb3ZlKCk7XG59O1xuXG5yZXR1cm4gQ2VsbDtcblxufSApICk7XG4iLCIvLyBGbGlja2l0eSBtYWluXG4vKiBlc2xpbnQtZGlzYWJsZSBtYXgtcGFyYW1zICovXG4oIGZ1bmN0aW9uKCB3aW5kb3csIGZhY3RvcnkgKSB7XG4gIC8vIHVuaXZlcnNhbCBtb2R1bGUgZGVmaW5pdGlvblxuICBpZiAoIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG4gICAgLy8gQ29tbW9uSlNcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoXG4gICAgICAgIHdpbmRvdyxcbiAgICAgICAgcmVxdWlyZSgnZXYtZW1pdHRlcicpLFxuICAgICAgICByZXF1aXJlKCdnZXQtc2l6ZScpLFxuICAgICAgICByZXF1aXJlKCdmaXp6eS11aS11dGlscycpLFxuICAgICAgICByZXF1aXJlKCcuL2NlbGwnKSxcbiAgICAgICAgcmVxdWlyZSgnLi9zbGlkZScpLFxuICAgICAgICByZXF1aXJlKCcuL2FuaW1hdGUnKSxcbiAgICApO1xuICB9IGVsc2Uge1xuICAgIC8vIGJyb3dzZXIgZ2xvYmFsXG4gICAgbGV0IF9GbGlja2l0eSA9IHdpbmRvdy5GbGlja2l0eTtcblxuICAgIHdpbmRvdy5GbGlja2l0eSA9IGZhY3RvcnkoXG4gICAgICAgIHdpbmRvdyxcbiAgICAgICAgd2luZG93LkV2RW1pdHRlcixcbiAgICAgICAgd2luZG93LmdldFNpemUsXG4gICAgICAgIHdpbmRvdy5maXp6eVVJVXRpbHMsXG4gICAgICAgIF9GbGlja2l0eS5DZWxsLFxuICAgICAgICBfRmxpY2tpdHkuU2xpZGUsXG4gICAgICAgIF9GbGlja2l0eS5hbmltYXRlUHJvdG90eXBlLFxuICAgICk7XG4gIH1cblxufSggdHlwZW9mIHdpbmRvdyAhPSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHRoaXMsXG4gICAgZnVuY3Rpb24gZmFjdG9yeSggd2luZG93LCBFdkVtaXR0ZXIsIGdldFNpemUsIHV0aWxzLCBDZWxsLCBTbGlkZSwgYW5pbWF0ZVByb3RvdHlwZSApIHtcbi8qIGVzbGludC1lbmFibGUgbWF4LXBhcmFtcyAqL1xuXG4vLyB2YXJzXG5jb25zdCB7IGdldENvbXB1dGVkU3R5bGUsIGNvbnNvbGUgfSA9IHdpbmRvdztcbmxldCB7IGpRdWVyeSB9ID0gd2luZG93O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBGbGlja2l0eSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4vLyBnbG9iYWxseSB1bmlxdWUgaWRlbnRpZmllcnNcbmxldCBHVUlEID0gMDtcbi8vIGludGVybmFsIHN0b3JlIG9mIGFsbCBGbGlja2l0eSBpbnRhbmNlc1xubGV0IGluc3RhbmNlcyA9IHt9O1xuXG5mdW5jdGlvbiBGbGlja2l0eSggZWxlbWVudCwgb3B0aW9ucyApIHtcbiAgbGV0IHF1ZXJ5RWxlbWVudCA9IHV0aWxzLmdldFF1ZXJ5RWxlbWVudCggZWxlbWVudCApO1xuICBpZiAoICFxdWVyeUVsZW1lbnQgKSB7XG4gICAgaWYgKCBjb25zb2xlICkgY29uc29sZS5lcnJvcihgQmFkIGVsZW1lbnQgZm9yIEZsaWNraXR5OiAke3F1ZXJ5RWxlbWVudCB8fCBlbGVtZW50fWApO1xuICAgIHJldHVybjtcbiAgfVxuICB0aGlzLmVsZW1lbnQgPSBxdWVyeUVsZW1lbnQ7XG4gIC8vIGRvIG5vdCBpbml0aWFsaXplIHR3aWNlIG9uIHNhbWUgZWxlbWVudFxuICBpZiAoIHRoaXMuZWxlbWVudC5mbGlja2l0eUdVSUQgKSB7XG4gICAgbGV0IGluc3RhbmNlID0gaW5zdGFuY2VzWyB0aGlzLmVsZW1lbnQuZmxpY2tpdHlHVUlEIF07XG4gICAgaWYgKCBpbnN0YW5jZSApIGluc3RhbmNlLm9wdGlvbiggb3B0aW9ucyApO1xuICAgIHJldHVybiBpbnN0YW5jZTtcbiAgfVxuXG4gIC8vIGFkZCBqUXVlcnlcbiAgaWYgKCBqUXVlcnkgKSB7XG4gICAgdGhpcy4kZWxlbWVudCA9IGpRdWVyeSggdGhpcy5lbGVtZW50ICk7XG4gIH1cbiAgLy8gb3B0aW9uc1xuICB0aGlzLm9wdGlvbnMgPSB7IC4uLnRoaXMuY29uc3RydWN0b3IuZGVmYXVsdHMgfTtcbiAgdGhpcy5vcHRpb24oIG9wdGlvbnMgKTtcblxuICAvLyBraWNrIHRoaW5ncyBvZmZcbiAgdGhpcy5fY3JlYXRlKCk7XG59XG5cbkZsaWNraXR5LmRlZmF1bHRzID0ge1xuICBhY2Nlc3NpYmlsaXR5OiB0cnVlLFxuICAvLyBhZGFwdGl2ZUhlaWdodDogZmFsc2UsXG4gIGNlbGxBbGlnbjogJ2NlbnRlcicsXG4gIC8vIGNlbGxTZWxlY3RvcjogdW5kZWZpbmVkLFxuICAvLyBjb250YWluOiBmYWxzZSxcbiAgZnJlZVNjcm9sbEZyaWN0aW9uOiAwLjA3NSwgLy8gZnJpY3Rpb24gd2hlbiBmcmVlLXNjcm9sbGluZ1xuICBmcmljdGlvbjogMC4yOCwgLy8gZnJpY3Rpb24gd2hlbiBzZWxlY3RpbmdcbiAgbmFtZXNwYWNlSlF1ZXJ5RXZlbnRzOiB0cnVlLFxuICAvLyBpbml0aWFsSW5kZXg6IDAsXG4gIHBlcmNlbnRQb3NpdGlvbjogdHJ1ZSxcbiAgcmVzaXplOiB0cnVlLFxuICBzZWxlY3RlZEF0dHJhY3Rpb246IDAuMDI1LFxuICBzZXRHYWxsZXJ5U2l6ZTogdHJ1ZSxcbiAgLy8gd2F0Y2hDU1M6IGZhbHNlLFxuICAvLyB3cmFwQXJvdW5kOiBmYWxzZVxufTtcblxuLy8gaGFzaCBvZiBtZXRob2RzIHRyaWdnZXJlZCBvbiBfY3JlYXRlKClcbkZsaWNraXR5LmNyZWF0ZSA9IHt9O1xuXG5sZXQgcHJvdG8gPSBGbGlja2l0eS5wcm90b3R5cGU7XG4vLyBpbmhlcml0IEV2ZW50RW1pdHRlclxuT2JqZWN0LmFzc2lnbiggcHJvdG8sIEV2RW1pdHRlci5wcm90b3R5cGUgKTtcblxucHJvdG8uX2NyZWF0ZSA9IGZ1bmN0aW9uKCkge1xuICBsZXQgeyByZXNpemUsIHdhdGNoQ1NTLCByaWdodFRvTGVmdCB9ID0gdGhpcy5vcHRpb25zO1xuICAvLyBhZGQgaWQgZm9yIEZsaWNraXR5LmRhdGFcbiAgbGV0IGlkID0gdGhpcy5ndWlkID0gKytHVUlEO1xuICB0aGlzLmVsZW1lbnQuZmxpY2tpdHlHVUlEID0gaWQ7IC8vIGV4cGFuZG9cbiAgaW5zdGFuY2VzWyBpZCBdID0gdGhpczsgLy8gYXNzb2NpYXRlIHZpYSBpZFxuICAvLyBpbml0aWFsIHByb3BlcnRpZXNcbiAgdGhpcy5zZWxlY3RlZEluZGV4ID0gMDtcbiAgLy8gaG93IG1hbnkgZnJhbWVzIHNsaWRlciBoYXMgYmVlbiBpbiBzYW1lIHBvc2l0aW9uXG4gIHRoaXMucmVzdGluZ0ZyYW1lcyA9IDA7XG4gIC8vIGluaXRpYWwgcGh5c2ljcyBwcm9wZXJ0aWVzXG4gIHRoaXMueCA9IDA7XG4gIHRoaXMudmVsb2NpdHkgPSAwO1xuICB0aGlzLmJlZ2luTWFyZ2luID0gcmlnaHRUb0xlZnQgPyAnbWFyZ2luUmlnaHQnIDogJ21hcmdpbkxlZnQnO1xuICB0aGlzLmVuZE1hcmdpbiA9IHJpZ2h0VG9MZWZ0ID8gJ21hcmdpbkxlZnQnIDogJ21hcmdpblJpZ2h0JztcbiAgLy8gY3JlYXRlIHZpZXdwb3J0ICYgc2xpZGVyXG4gIHRoaXMudmlld3BvcnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgdGhpcy52aWV3cG9ydC5jbGFzc05hbWUgPSAnZmxpY2tpdHktdmlld3BvcnQnO1xuICB0aGlzLl9jcmVhdGVTbGlkZXIoKTtcbiAgLy8gdXNlZCBmb3Iga2V5Ym9hcmQgbmF2aWdhdGlvblxuICB0aGlzLmZvY3VzYWJsZUVsZW1zID0gWyB0aGlzLmVsZW1lbnQgXTtcblxuICBpZiAoIHJlc2l6ZSB8fCB3YXRjaENTUyApIHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lciggJ3Jlc2l6ZScsIHRoaXMgKTtcbiAgfVxuXG4gIC8vIGFkZCBsaXN0ZW5lcnMgZnJvbSBvbiBvcHRpb25cbiAgZm9yICggbGV0IGV2ZW50TmFtZSBpbiB0aGlzLm9wdGlvbnMub24gKSB7XG4gICAgbGV0IGxpc3RlbmVyID0gdGhpcy5vcHRpb25zLm9uWyBldmVudE5hbWUgXTtcbiAgICB0aGlzLm9uKCBldmVudE5hbWUsIGxpc3RlbmVyICk7XG4gIH1cblxuICBmb3IgKCBsZXQgbWV0aG9kIGluIEZsaWNraXR5LmNyZWF0ZSApIHtcbiAgICBGbGlja2l0eS5jcmVhdGVbIG1ldGhvZCBdLmNhbGwoIHRoaXMgKTtcbiAgfVxuXG4gIGlmICggd2F0Y2hDU1MgKSB7XG4gICAgdGhpcy53YXRjaENTUygpO1xuICB9IGVsc2Uge1xuICAgIHRoaXMuYWN0aXZhdGUoKTtcbiAgfVxufTtcblxuLyoqXG4gKiBzZXQgb3B0aW9uc1xuICogQHBhcmFtIHtPYmplY3R9IG9wdHMgLSBvcHRpb25zIHRvIGV4dGVuZFxuICovXG5wcm90by5vcHRpb24gPSBmdW5jdGlvbiggb3B0cyApIHtcbiAgT2JqZWN0LmFzc2lnbiggdGhpcy5vcHRpb25zLCBvcHRzICk7XG59O1xuXG5wcm90by5hY3RpdmF0ZSA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIHRoaXMuaXNBY3RpdmUgKSByZXR1cm47XG5cbiAgdGhpcy5pc0FjdGl2ZSA9IHRydWU7XG4gIHRoaXMuZWxlbWVudC5jbGFzc0xpc3QuYWRkKCdmbGlja2l0eS1lbmFibGVkJyk7XG4gIGlmICggdGhpcy5vcHRpb25zLnJpZ2h0VG9MZWZ0ICkge1xuICAgIHRoaXMuZWxlbWVudC5jbGFzc0xpc3QuYWRkKCdmbGlja2l0eS1ydGwnKTtcbiAgfVxuXG4gIHRoaXMuZ2V0U2l6ZSgpO1xuICAvLyBtb3ZlIGluaXRpYWwgY2VsbCBlbGVtZW50cyBzbyB0aGV5IGNhbiBiZSBsb2FkZWQgYXMgY2VsbHNcbiAgbGV0IGNlbGxFbGVtcyA9IHRoaXMuX2ZpbHRlckZpbmRDZWxsRWxlbWVudHMoIHRoaXMuZWxlbWVudC5jaGlsZHJlbiApO1xuICB0aGlzLnNsaWRlci5hcHBlbmQoIC4uLmNlbGxFbGVtcyApO1xuICB0aGlzLnZpZXdwb3J0LmFwcGVuZCggdGhpcy5zbGlkZXIgKTtcbiAgdGhpcy5lbGVtZW50LmFwcGVuZCggdGhpcy52aWV3cG9ydCApO1xuICAvLyBnZXQgY2VsbHMgZnJvbSBjaGlsZHJlblxuICB0aGlzLnJlbG9hZENlbGxzKCk7XG5cbiAgaWYgKCB0aGlzLm9wdGlvbnMuYWNjZXNzaWJpbGl0eSApIHtcbiAgICAvLyBhbGxvdyBlbGVtZW50IHRvIGZvY3VzYWJsZVxuICAgIHRoaXMuZWxlbWVudC50YWJJbmRleCA9IDA7XG4gICAgLy8gbGlzdGVuIGZvciBrZXkgcHJlc3Nlc1xuICAgIHRoaXMuZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCAna2V5ZG93bicsIHRoaXMgKTtcbiAgfVxuXG4gIHRoaXMuZW1pdEV2ZW50KCdhY3RpdmF0ZScpO1xuICB0aGlzLnNlbGVjdEluaXRpYWxJbmRleCgpO1xuICAvLyBmbGFnIGZvciBpbml0aWFsIGFjdGl2YXRpb24sIGZvciB1c2luZyBpbml0aWFsSW5kZXhcbiAgdGhpcy5pc0luaXRBY3RpdmF0ZWQgPSB0cnVlO1xuICAvLyByZWFkeSBldmVudC4gIzQ5M1xuICB0aGlzLmRpc3BhdGNoRXZlbnQoJ3JlYWR5Jyk7XG59O1xuXG4vLyBzbGlkZXIgcG9zaXRpb25zIHRoZSBjZWxsc1xucHJvdG8uX2NyZWF0ZVNsaWRlciA9IGZ1bmN0aW9uKCkge1xuICAvLyBzbGlkZXIgZWxlbWVudCBkb2VzIGFsbCB0aGUgcG9zaXRpb25pbmdcbiAgbGV0IHNsaWRlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICBzbGlkZXIuY2xhc3NOYW1lID0gJ2ZsaWNraXR5LXNsaWRlcic7XG4gIHRoaXMuc2xpZGVyID0gc2xpZGVyO1xufTtcblxucHJvdG8uX2ZpbHRlckZpbmRDZWxsRWxlbWVudHMgPSBmdW5jdGlvbiggZWxlbXMgKSB7XG4gIHJldHVybiB1dGlscy5maWx0ZXJGaW5kRWxlbWVudHMoIGVsZW1zLCB0aGlzLm9wdGlvbnMuY2VsbFNlbGVjdG9yICk7XG59O1xuXG4vLyBnb2VzIHRocm91Z2ggYWxsIGNoaWxkcmVuXG5wcm90by5yZWxvYWRDZWxscyA9IGZ1bmN0aW9uKCkge1xuICAvLyBjb2xsZWN0aW9uIG9mIGl0ZW0gZWxlbWVudHNcbiAgdGhpcy5jZWxscyA9IHRoaXMuX21ha2VDZWxscyggdGhpcy5zbGlkZXIuY2hpbGRyZW4gKTtcbiAgdGhpcy5wb3NpdGlvbkNlbGxzKCk7XG4gIHRoaXMuX3VwZGF0ZVdyYXBTaGlmdENlbGxzKCk7XG4gIHRoaXMuc2V0R2FsbGVyeVNpemUoKTtcbn07XG5cbi8qKlxuICogdHVybiBlbGVtZW50cyBpbnRvIEZsaWNraXR5LkNlbGxzXG4gKiBAcGFyYW0ge1tBcnJheSwgTm9kZUxpc3QsIEhUTUxFbGVtZW50XX0gZWxlbXMgLSBlbGVtZW50cyB0byBtYWtlIGludG8gY2VsbHNcbiAqIEByZXR1cm5zIHtBcnJheX0gaXRlbXMgLSBjb2xsZWN0aW9uIG9mIG5ldyBGbGlja2l0eSBDZWxsc1xuICovXG5wcm90by5fbWFrZUNlbGxzID0gZnVuY3Rpb24oIGVsZW1zICkge1xuICBsZXQgY2VsbEVsZW1zID0gdGhpcy5fZmlsdGVyRmluZENlbGxFbGVtZW50cyggZWxlbXMgKTtcblxuICAvLyBjcmVhdGUgbmV3IENlbGxzIGZvciBjb2xsZWN0aW9uXG4gIHJldHVybiBjZWxsRWxlbXMubWFwKCAoIGNlbGxFbGVtICkgPT4gbmV3IENlbGwoIGNlbGxFbGVtICkgKTtcbn07XG5cbnByb3RvLmdldExhc3RDZWxsID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLmNlbGxzWyB0aGlzLmNlbGxzLmxlbmd0aCAtIDEgXTtcbn07XG5cbnByb3RvLmdldExhc3RTbGlkZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5zbGlkZXNbIHRoaXMuc2xpZGVzLmxlbmd0aCAtIDEgXTtcbn07XG5cbi8vIHBvc2l0aW9ucyBhbGwgY2VsbHNcbnByb3RvLnBvc2l0aW9uQ2VsbHMgPSBmdW5jdGlvbigpIHtcbiAgLy8gc2l6ZSBhbGwgY2VsbHNcbiAgdGhpcy5fc2l6ZUNlbGxzKCB0aGlzLmNlbGxzICk7XG4gIC8vIHBvc2l0aW9uIGFsbCBjZWxsc1xuICB0aGlzLl9wb3NpdGlvbkNlbGxzKCAwICk7XG59O1xuXG4vKipcbiAqIHBvc2l0aW9uIGNlcnRhaW4gY2VsbHNcbiAqIEBwYXJhbSB7SW50ZWdlcn0gaW5kZXggLSB3aGljaCBjZWxsIHRvIHN0YXJ0IHdpdGhcbiAqL1xucHJvdG8uX3Bvc2l0aW9uQ2VsbHMgPSBmdW5jdGlvbiggaW5kZXggKSB7XG4gIGluZGV4ID0gaW5kZXggfHwgMDtcbiAgLy8gYWxzbyBtZWFzdXJlIG1heENlbGxIZWlnaHRcbiAgLy8gc3RhcnQgMCBpZiBwb3NpdGlvbmluZyBhbGwgY2VsbHNcbiAgdGhpcy5tYXhDZWxsSGVpZ2h0ID0gaW5kZXggPyB0aGlzLm1heENlbGxIZWlnaHQgfHwgMCA6IDA7XG4gIGxldCBjZWxsWCA9IDA7XG4gIC8vIGdldCBjZWxsWFxuICBpZiAoIGluZGV4ID4gMCApIHtcbiAgICBsZXQgc3RhcnRDZWxsID0gdGhpcy5jZWxsc1sgaW5kZXggLSAxIF07XG4gICAgY2VsbFggPSBzdGFydENlbGwueCArIHN0YXJ0Q2VsbC5zaXplLm91dGVyV2lkdGg7XG4gIH1cblxuICB0aGlzLmNlbGxzLnNsaWNlKCBpbmRleCApLmZvckVhY2goICggY2VsbCApID0+IHtcbiAgICBjZWxsLnggPSBjZWxsWDtcbiAgICB0aGlzLl9yZW5kZXJDZWxsUG9zaXRpb24oIGNlbGwsIGNlbGxYICk7XG4gICAgY2VsbFggKz0gY2VsbC5zaXplLm91dGVyV2lkdGg7XG4gICAgdGhpcy5tYXhDZWxsSGVpZ2h0ID0gTWF0aC5tYXgoIGNlbGwuc2l6ZS5vdXRlckhlaWdodCwgdGhpcy5tYXhDZWxsSGVpZ2h0ICk7XG4gIH0gKTtcbiAgLy8ga2VlcCB0cmFjayBvZiBjZWxsWCBmb3Igd3JhcC1hcm91bmRcbiAgdGhpcy5zbGlkZWFibGVXaWR0aCA9IGNlbGxYO1xuICAvLyBzbGlkZXNcbiAgdGhpcy51cGRhdGVTbGlkZXMoKTtcbiAgLy8gY29udGFpbiBzbGlkZXMgdGFyZ2V0XG4gIHRoaXMuX2NvbnRhaW5TbGlkZXMoKTtcbiAgLy8gdXBkYXRlIHNsaWRlc1dpZHRoXG4gIHRoaXMuc2xpZGVzV2lkdGggPSB0aGlzLmNlbGxzLmxlbmd0aCA/XG4gICAgdGhpcy5nZXRMYXN0U2xpZGUoKS50YXJnZXQgLSB0aGlzLnNsaWRlc1swXS50YXJnZXQgOiAwO1xufTtcblxucHJvdG8uX3JlbmRlckNlbGxQb3NpdGlvbiA9IGZ1bmN0aW9uKCBjZWxsLCB4ICkge1xuICAvLyByZW5kZXIgcG9zaXRpb24gb2YgY2VsbCB3aXRoIGluIHNsaWRlclxuICBsZXQgc2lkZU9mZnNldCA9IHRoaXMub3B0aW9ucy5yaWdodFRvTGVmdCA/IC0xIDogMTtcbiAgbGV0IHJlbmRlclggPSB4ICogc2lkZU9mZnNldDtcbiAgaWYgKCB0aGlzLm9wdGlvbnMucGVyY2VudFBvc2l0aW9uICkgcmVuZGVyWCAqPSB0aGlzLnNpemUuaW5uZXJXaWR0aCAvIGNlbGwuc2l6ZS53aWR0aDtcbiAgbGV0IHBvc2l0aW9uVmFsdWUgPSB0aGlzLmdldFBvc2l0aW9uVmFsdWUoIHJlbmRlclggKTtcbiAgY2VsbC5lbGVtZW50LnN0eWxlLnRyYW5zZm9ybSA9IGB0cmFuc2xhdGVYKCAke3Bvc2l0aW9uVmFsdWV9IClgO1xufTtcblxuLyoqXG4gKiBjZWxsLmdldFNpemUoKSBvbiBtdWx0aXBsZSBjZWxsc1xuICogQHBhcmFtIHtBcnJheX0gY2VsbHMgLSBjZWxscyB0byBzaXplXG4gKi9cbnByb3RvLl9zaXplQ2VsbHMgPSBmdW5jdGlvbiggY2VsbHMgKSB7XG4gIGNlbGxzLmZvckVhY2goICggY2VsbCApID0+IGNlbGwuZ2V0U2l6ZSgpICk7XG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxucHJvdG8udXBkYXRlU2xpZGVzID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuc2xpZGVzID0gW107XG4gIGlmICggIXRoaXMuY2VsbHMubGVuZ3RoICkgcmV0dXJuO1xuXG4gIGxldCB7IGJlZ2luTWFyZ2luLCBlbmRNYXJnaW4gfSA9IHRoaXM7XG4gIGxldCBzbGlkZSA9IG5ldyBTbGlkZSggYmVnaW5NYXJnaW4sIGVuZE1hcmdpbiwgdGhpcy5jZWxsQWxpZ24gKTtcbiAgdGhpcy5zbGlkZXMucHVzaCggc2xpZGUgKTtcblxuICBsZXQgY2FuQ2VsbEZpdCA9IHRoaXMuX2dldENhbkNlbGxGaXQoKTtcblxuICB0aGlzLmNlbGxzLmZvckVhY2goICggY2VsbCwgaSApID0+IHtcbiAgICAvLyBqdXN0IGFkZCBjZWxsIGlmIGZpcnN0IGNlbGwgaW4gc2xpZGVcbiAgICBpZiAoICFzbGlkZS5jZWxscy5sZW5ndGggKSB7XG4gICAgICBzbGlkZS5hZGRDZWxsKCBjZWxsICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHNsaWRlV2lkdGggPSAoIHNsaWRlLm91dGVyV2lkdGggLSBzbGlkZS5maXJzdE1hcmdpbiApICtcbiAgICAgICggY2VsbC5zaXplLm91dGVyV2lkdGggLSBjZWxsLnNpemVbIGVuZE1hcmdpbiBdICk7XG5cbiAgICBpZiAoIGNhbkNlbGxGaXQoIGksIHNsaWRlV2lkdGggKSApIHtcbiAgICAgIHNsaWRlLmFkZENlbGwoIGNlbGwgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gZG9lc24ndCBmaXQsIG5ldyBzbGlkZVxuICAgICAgc2xpZGUudXBkYXRlVGFyZ2V0KCk7XG5cbiAgICAgIHNsaWRlID0gbmV3IFNsaWRlKCBiZWdpbk1hcmdpbiwgZW5kTWFyZ2luLCB0aGlzLmNlbGxBbGlnbiApO1xuICAgICAgdGhpcy5zbGlkZXMucHVzaCggc2xpZGUgKTtcbiAgICAgIHNsaWRlLmFkZENlbGwoIGNlbGwgKTtcbiAgICB9XG4gIH0gKTtcbiAgLy8gbGFzdCBzbGlkZVxuICBzbGlkZS51cGRhdGVUYXJnZXQoKTtcbiAgLy8gdXBkYXRlIC5zZWxlY3RlZFNsaWRlXG4gIHRoaXMudXBkYXRlU2VsZWN0ZWRTbGlkZSgpO1xufTtcblxucHJvdG8uX2dldENhbkNlbGxGaXQgPSBmdW5jdGlvbigpIHtcbiAgbGV0IHsgZ3JvdXBDZWxscyB9ID0gdGhpcy5vcHRpb25zO1xuICBpZiAoICFncm91cENlbGxzICkgcmV0dXJuICgpID0+IGZhbHNlO1xuXG4gIGlmICggdHlwZW9mIGdyb3VwQ2VsbHMgPT0gJ251bWJlcicgKSB7XG4gICAgLy8gZ3JvdXAgYnkgbnVtYmVyLiAzIC0+IFswLDEsMl0sIFszLDQsNV0sIC4uLlxuICAgIGxldCBudW1iZXIgPSBwYXJzZUludCggZ3JvdXBDZWxscywgMTAgKTtcbiAgICByZXR1cm4gKCBpICkgPT4gKCBpICUgbnVtYmVyICkgIT09IDA7XG4gIH1cbiAgLy8gZGVmYXVsdCwgZ3JvdXAgYnkgd2lkdGggb2Ygc2xpZGVcbiAgbGV0IHBlcmNlbnQgPSAxO1xuICAvLyBwYXJzZSAnNzUlXG4gIGxldCBwZXJjZW50TWF0Y2ggPSB0eXBlb2YgZ3JvdXBDZWxscyA9PSAnc3RyaW5nJyAmJiBncm91cENlbGxzLm1hdGNoKCAvXihcXGQrKSUkLyApO1xuICBpZiAoIHBlcmNlbnRNYXRjaCApIHBlcmNlbnQgPSBwYXJzZUludCggcGVyY2VudE1hdGNoWzFdLCAxMCApIC8gMTAwO1xuICBsZXQgZ3JvdXBXaWR0aCA9ICggdGhpcy5zaXplLmlubmVyV2lkdGggKyAxICkgKiBwZXJjZW50O1xuICByZXR1cm4gKCBpLCBzbGlkZVdpZHRoICkgPT4gc2xpZGVXaWR0aCA8PSBncm91cFdpZHRoO1xufTtcblxuLy8gYWxpYXMgX2luaXQgZm9yIGpRdWVyeSBwbHVnaW4gLmZsaWNraXR5KClcbnByb3RvLl9pbml0ID1cbnByb3RvLnJlcG9zaXRpb24gPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5wb3NpdGlvbkNlbGxzKCk7XG4gIHRoaXMucG9zaXRpb25TbGlkZXJBdFNlbGVjdGVkKCk7XG59O1xuXG5wcm90by5nZXRTaXplID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuc2l6ZSA9IGdldFNpemUoIHRoaXMuZWxlbWVudCApO1xuICB0aGlzLnNldENlbGxBbGlnbigpO1xuICB0aGlzLmN1cnNvclBvc2l0aW9uID0gdGhpcy5zaXplLmlubmVyV2lkdGggKiB0aGlzLmNlbGxBbGlnbjtcbn07XG5cbmxldCBjZWxsQWxpZ25TaG9ydGhhbmRzID0ge1xuICBsZWZ0OiAwLFxuICBjZW50ZXI6IDAuNSxcbiAgcmlnaHQ6IDEsXG59O1xuXG5wcm90by5zZXRDZWxsQWxpZ24gPSBmdW5jdGlvbigpIHtcbiAgbGV0IHsgY2VsbEFsaWduLCByaWdodFRvTGVmdCB9ID0gdGhpcy5vcHRpb25zO1xuICBsZXQgc2hvcnRoYW5kID0gY2VsbEFsaWduU2hvcnRoYW5kc1sgY2VsbEFsaWduIF07XG4gIHRoaXMuY2VsbEFsaWduID0gc2hvcnRoYW5kICE9PSB1bmRlZmluZWQgPyBzaG9ydGhhbmQgOiBjZWxsQWxpZ247XG4gIGlmICggcmlnaHRUb0xlZnQgKSB0aGlzLmNlbGxBbGlnbiA9IDEgLSB0aGlzLmNlbGxBbGlnbjtcbn07XG5cbnByb3RvLnNldEdhbGxlcnlTaXplID0gZnVuY3Rpb24oKSB7XG4gIGlmICggIXRoaXMub3B0aW9ucy5zZXRHYWxsZXJ5U2l6ZSApIHJldHVybjtcblxuICBsZXQgaGVpZ2h0ID0gdGhpcy5vcHRpb25zLmFkYXB0aXZlSGVpZ2h0ICYmIHRoaXMuc2VsZWN0ZWRTbGlkZSA/XG4gICAgdGhpcy5zZWxlY3RlZFNsaWRlLmhlaWdodCA6IHRoaXMubWF4Q2VsbEhlaWdodDtcbiAgdGhpcy52aWV3cG9ydC5zdHlsZS5oZWlnaHQgPSBgJHtoZWlnaHR9cHhgO1xufTtcblxucHJvdG8uX3VwZGF0ZVdyYXBTaGlmdENlbGxzID0gZnVuY3Rpb24oKSB7XG4gIC8vIHVwZGF0ZSBpc1dyYXBwaW5nXG4gIHRoaXMuaXNXcmFwcGluZyA9IHRoaXMuZ2V0SXNXcmFwcGluZygpO1xuICAvLyBvbmx5IGZvciB3cmFwLWFyb3VuZFxuICBpZiAoICF0aGlzLmlzV3JhcHBpbmcgKSByZXR1cm47XG5cbiAgLy8gdW5zaGlmdCBwcmV2aW91cyBjZWxsc1xuICB0aGlzLl91bnNoaWZ0Q2VsbHMoIHRoaXMuYmVmb3JlU2hpZnRDZWxscyApO1xuICB0aGlzLl91bnNoaWZ0Q2VsbHMoIHRoaXMuYWZ0ZXJTaGlmdENlbGxzICk7XG4gIC8vIGdldCBiZWZvcmUgY2VsbHNcbiAgLy8gaW5pdGlhbCBnYXBcbiAgbGV0IGJlZm9yZUdhcFggPSB0aGlzLmN1cnNvclBvc2l0aW9uO1xuICBsZXQgbGFzdEluZGV4ID0gdGhpcy5jZWxscy5sZW5ndGggLSAxO1xuICB0aGlzLmJlZm9yZVNoaWZ0Q2VsbHMgPSB0aGlzLl9nZXRHYXBDZWxscyggYmVmb3JlR2FwWCwgbGFzdEluZGV4LCAtMSApO1xuICAvLyBnZXQgYWZ0ZXIgY2VsbHNcbiAgLy8gZW5kaW5nIGdhcCBiZXR3ZWVuIGxhc3QgY2VsbCBhbmQgZW5kIG9mIGdhbGxlcnkgdmlld3BvcnRcbiAgbGV0IGFmdGVyR2FwWCA9IHRoaXMuc2l6ZS5pbm5lcldpZHRoIC0gdGhpcy5jdXJzb3JQb3NpdGlvbjtcbiAgLy8gc3RhcnQgY2xvbmluZyBhdCBmaXJzdCBjZWxsLCB3b3JraW5nIGZvcndhcmRzXG4gIHRoaXMuYWZ0ZXJTaGlmdENlbGxzID0gdGhpcy5fZ2V0R2FwQ2VsbHMoIGFmdGVyR2FwWCwgMCwgMSApO1xufTtcblxucHJvdG8uZ2V0SXNXcmFwcGluZyA9IGZ1bmN0aW9uKCkge1xuICBsZXQgeyB3cmFwQXJvdW5kIH0gPSB0aGlzLm9wdGlvbnM7XG4gIGlmICggIXdyYXBBcm91bmQgfHwgdGhpcy5zbGlkZXMubGVuZ3RoIDwgMiApIHJldHVybiBmYWxzZTtcblxuICBpZiAoIHdyYXBBcm91bmQgIT09ICdmaWxsJyApIHJldHVybiB0cnVlO1xuICAvLyBjaGVjayB0aGF0IHNsaWRlcyBjYW4gZml0XG5cbiAgbGV0IGdhcFdpZHRoID0gdGhpcy5zbGlkZWFibGVXaWR0aCAtIHRoaXMuc2l6ZS5pbm5lcldpZHRoO1xuICBpZiAoIGdhcFdpZHRoID4gdGhpcy5zaXplLmlubmVyV2lkdGggKSByZXR1cm4gdHJ1ZTsgLy8gZ2FwICogMnggYmlnLCBhbGwgZ29vZFxuICAvLyBjaGVjayB0aGF0IGNvbnRlbnQgd2lkdGggLSBzaGlmdGluZyBjZWxsIGlzIGJpZ2dlciB0aGFuIHZpZXdwb3J0IHdpZHRoXG4gIGZvciAoIGxldCBjZWxsIG9mIHRoaXMuY2VsbHMgKSB7XG4gICAgaWYgKCBjZWxsLnNpemUub3V0ZXJXaWR0aCA+IGdhcFdpZHRoICkgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufTtcblxucHJvdG8uX2dldEdhcENlbGxzID0gZnVuY3Rpb24oIGdhcFgsIGNlbGxJbmRleCwgaW5jcmVtZW50ICkge1xuICAvLyBrZWVwIGFkZGluZyBjZWxscyB1bnRpbCB0aGUgY292ZXIgdGhlIGluaXRpYWwgZ2FwXG4gIGxldCBjZWxscyA9IFtdO1xuICB3aGlsZSAoIGdhcFggPiAwICkge1xuICAgIGxldCBjZWxsID0gdGhpcy5jZWxsc1sgY2VsbEluZGV4IF07XG4gICAgaWYgKCAhY2VsbCApIGJyZWFrO1xuXG4gICAgY2VsbHMucHVzaCggY2VsbCApO1xuICAgIGNlbGxJbmRleCArPSBpbmNyZW1lbnQ7XG4gICAgZ2FwWCAtPSBjZWxsLnNpemUub3V0ZXJXaWR0aDtcbiAgfVxuICByZXR1cm4gY2VsbHM7XG59O1xuXG4vLyAtLS0tLSBjb250YWluICYgd3JhcCAtLS0tLSAvL1xuXG4vLyBjb250YWluIGNlbGwgdGFyZ2V0cyBzbyBubyBleGNlc3Mgc2xpZGluZ1xucHJvdG8uX2NvbnRhaW5TbGlkZXMgPSBmdW5jdGlvbigpIHtcbiAgbGV0IGlzQ29udGFpbmluZyA9IHRoaXMub3B0aW9ucy5jb250YWluICYmICF0aGlzLmlzV3JhcHBpbmcgJiZcbiAgICAgIHRoaXMuY2VsbHMubGVuZ3RoO1xuICBpZiAoICFpc0NvbnRhaW5pbmcgKSByZXR1cm47XG5cbiAgbGV0IGNvbnRlbnRXaWR0aCA9IHRoaXMuc2xpZGVhYmxlV2lkdGggLSB0aGlzLmdldExhc3RDZWxsKCkuc2l6ZVsgdGhpcy5lbmRNYXJnaW4gXTtcbiAgLy8gY29udGVudCBpcyBsZXNzIHRoYW4gZ2FsbGVyeSBzaXplXG4gIGxldCBpc0NvbnRlbnRTbWFsbGVyID0gY29udGVudFdpZHRoIDwgdGhpcy5zaXplLmlubmVyV2lkdGg7XG4gIGlmICggaXNDb250ZW50U21hbGxlciApIHtcbiAgICAvLyBhbGwgY2VsbHMgZml0IGluc2lkZSBnYWxsZXJ5XG4gICAgdGhpcy5zbGlkZXMuZm9yRWFjaCggKCBzbGlkZSApID0+IHtcbiAgICAgIHNsaWRlLnRhcmdldCA9IGNvbnRlbnRXaWR0aCAqIHRoaXMuY2VsbEFsaWduO1xuICAgIH0gKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBjb250YWluIHRvIGJvdW5kc1xuICAgIGxldCBiZWdpbkJvdW5kID0gdGhpcy5jdXJzb3JQb3NpdGlvbiArIHRoaXMuY2VsbHNbMF0uc2l6ZVsgdGhpcy5iZWdpbk1hcmdpbiBdO1xuICAgIGxldCBlbmRCb3VuZCA9IGNvbnRlbnRXaWR0aCAtIHRoaXMuc2l6ZS5pbm5lcldpZHRoICogKCAxIC0gdGhpcy5jZWxsQWxpZ24gKTtcbiAgICB0aGlzLnNsaWRlcy5mb3JFYWNoKCAoIHNsaWRlICkgPT4ge1xuICAgICAgc2xpZGUudGFyZ2V0ID0gTWF0aC5tYXgoIHNsaWRlLnRhcmdldCwgYmVnaW5Cb3VuZCApO1xuICAgICAgc2xpZGUudGFyZ2V0ID0gTWF0aC5taW4oIHNsaWRlLnRhcmdldCwgZW5kQm91bmQgKTtcbiAgICB9ICk7XG4gIH1cbn07XG5cbi8vIC0tLS0tIGV2ZW50cyAtLS0tLSAvL1xuXG4vKipcbiAqIGVtaXRzIGV2ZW50cyB2aWEgZXZlbnRFbWl0dGVyIGFuZCBqUXVlcnkgZXZlbnRzXG4gKiBAcGFyYW0ge1N0cmluZ30gdHlwZSAtIG5hbWUgb2YgZXZlbnRcbiAqIEBwYXJhbSB7RXZlbnR9IGV2ZW50IC0gb3JpZ2luYWwgZXZlbnRcbiAqIEBwYXJhbSB7QXJyYXl9IGFyZ3MgLSBleHRyYSBhcmd1bWVudHNcbiAqL1xucHJvdG8uZGlzcGF0Y2hFdmVudCA9IGZ1bmN0aW9uKCB0eXBlLCBldmVudCwgYXJncyApIHtcbiAgbGV0IGVtaXRBcmdzID0gZXZlbnQgPyBbIGV2ZW50IF0uY29uY2F0KCBhcmdzICkgOiBhcmdzO1xuICB0aGlzLmVtaXRFdmVudCggdHlwZSwgZW1pdEFyZ3MgKTtcblxuICBpZiAoIGpRdWVyeSAmJiB0aGlzLiRlbGVtZW50ICkge1xuICAgIC8vIGRlZmF1bHQgdHJpZ2dlciB3aXRoIHR5cGUgaWYgbm8gZXZlbnRcbiAgICB0eXBlICs9IHRoaXMub3B0aW9ucy5uYW1lc3BhY2VKUXVlcnlFdmVudHMgPyAnLmZsaWNraXR5JyA6ICcnO1xuICAgIGxldCAkZXZlbnQgPSB0eXBlO1xuICAgIGlmICggZXZlbnQgKSB7XG4gICAgICAvLyBjcmVhdGUgalF1ZXJ5IGV2ZW50XG4gICAgICBsZXQgalFFdmVudCA9IG5ldyBqUXVlcnkuRXZlbnQoIGV2ZW50ICk7XG4gICAgICBqUUV2ZW50LnR5cGUgPSB0eXBlO1xuICAgICAgJGV2ZW50ID0galFFdmVudDtcbiAgICB9XG4gICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKCAkZXZlbnQsIGFyZ3MgKTtcbiAgfVxufTtcblxuY29uc3QgdW5pZHJhZ2dlckV2ZW50cyA9IFtcbiAgJ2RyYWdTdGFydCcsXG4gICdkcmFnTW92ZScsXG4gICdkcmFnRW5kJyxcbiAgJ3BvaW50ZXJEb3duJyxcbiAgJ3BvaW50ZXJNb3ZlJyxcbiAgJ3BvaW50ZXJFbmQnLFxuICAnc3RhdGljQ2xpY2snLFxuXTtcblxubGV0IF9lbWl0RXZlbnQgPSBwcm90by5lbWl0RXZlbnQ7XG5wcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiggZXZlbnROYW1lLCBhcmdzICkge1xuICBpZiAoIGV2ZW50TmFtZSA9PT0gJ3N0YXRpY0NsaWNrJyApIHtcbiAgICAvLyBhZGQgY2VsbEVsZW0gYW5kIGNlbGxJbmRleCBhcmdzIHRvIHN0YXRpY0NsaWNrXG4gICAgbGV0IGNsaWNrZWRDZWxsID0gdGhpcy5nZXRQYXJlbnRDZWxsKCBhcmdzWzBdLnRhcmdldCApO1xuICAgIGxldCBjZWxsRWxlbSA9IGNsaWNrZWRDZWxsICYmIGNsaWNrZWRDZWxsLmVsZW1lbnQ7XG4gICAgbGV0IGNlbGxJbmRleCA9IGNsaWNrZWRDZWxsICYmIHRoaXMuY2VsbHMuaW5kZXhPZiggY2xpY2tlZENlbGwgKTtcbiAgICBhcmdzID0gYXJncy5jb25jYXQoIGNlbGxFbGVtLCBjZWxsSW5kZXggKTtcbiAgfVxuICAvLyBkbyByZWd1bGFyIHRoaW5nXG4gIF9lbWl0RXZlbnQuY2FsbCggdGhpcywgZXZlbnROYW1lLCBhcmdzICk7XG4gIC8vIGR1Y2stcHVuY2ggaW4galF1ZXJ5IGV2ZW50cyBmb3IgVW5pZHJhZ2dlciBldmVudHNcbiAgbGV0IGlzVW5pZHJhZ2dlckV2ZW50ID0gdW5pZHJhZ2dlckV2ZW50cy5pbmNsdWRlcyggZXZlbnROYW1lICk7XG4gIGlmICggIWlzVW5pZHJhZ2dlckV2ZW50IHx8ICFqUXVlcnkgfHwgIXRoaXMuJGVsZW1lbnQgKSByZXR1cm47XG5cbiAgZXZlbnROYW1lICs9IHRoaXMub3B0aW9ucy5uYW1lc3BhY2VKUXVlcnlFdmVudHMgPyAnLmZsaWNraXR5JyA6ICcnO1xuICBsZXQgZXZlbnQgPSBhcmdzLnNoaWZ0KCAwICk7XG4gIGxldCBqUUV2ZW50ID0gbmV3IGpRdWVyeS5FdmVudCggZXZlbnQgKTtcbiAgalFFdmVudC50eXBlID0gZXZlbnROYW1lO1xuICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoIGpRRXZlbnQsIGFyZ3MgKTtcbn07XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHNlbGVjdCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4vKipcbiAqIEBwYXJhbSB7SW50ZWdlcn0gaW5kZXggLSBpbmRleCBvZiB0aGUgc2xpZGVcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gaXNXcmFwIC0gd2lsbCB3cmFwLWFyb3VuZCB0byBsYXN0L2ZpcnN0IGlmIGF0IHRoZSBlbmRcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gaXNJbnN0YW50IC0gd2lsbCBpbW1lZGlhdGVseSBzZXQgcG9zaXRpb24gYXQgc2VsZWN0ZWQgY2VsbFxuICovXG5wcm90by5zZWxlY3QgPSBmdW5jdGlvbiggaW5kZXgsIGlzV3JhcCwgaXNJbnN0YW50ICkge1xuICBpZiAoICF0aGlzLmlzQWN0aXZlICkgcmV0dXJuO1xuXG4gIGluZGV4ID0gcGFyc2VJbnQoIGluZGV4LCAxMCApO1xuICB0aGlzLl93cmFwU2VsZWN0KCBpbmRleCApO1xuXG4gIGlmICggdGhpcy5pc1dyYXBwaW5nIHx8IGlzV3JhcCApIHtcbiAgICBpbmRleCA9IHV0aWxzLm1vZHVsbyggaW5kZXgsIHRoaXMuc2xpZGVzLmxlbmd0aCApO1xuICB9XG4gIC8vIGJhaWwgaWYgaW52YWxpZCBpbmRleFxuICBpZiAoICF0aGlzLnNsaWRlc1sgaW5kZXggXSApIHJldHVybjtcblxuICBsZXQgcHJldkluZGV4ID0gdGhpcy5zZWxlY3RlZEluZGV4O1xuICB0aGlzLnNlbGVjdGVkSW5kZXggPSBpbmRleDtcbiAgdGhpcy51cGRhdGVTZWxlY3RlZFNsaWRlKCk7XG4gIGlmICggaXNJbnN0YW50ICkge1xuICAgIHRoaXMucG9zaXRpb25TbGlkZXJBdFNlbGVjdGVkKCk7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5zdGFydEFuaW1hdGlvbigpO1xuICB9XG4gIGlmICggdGhpcy5vcHRpb25zLmFkYXB0aXZlSGVpZ2h0ICkge1xuICAgIHRoaXMuc2V0R2FsbGVyeVNpemUoKTtcbiAgfVxuICAvLyBldmVudHNcbiAgdGhpcy5kaXNwYXRjaEV2ZW50KCAnc2VsZWN0JywgbnVsbCwgWyBpbmRleCBdICk7XG4gIC8vIGNoYW5nZSBldmVudCBpZiBuZXcgaW5kZXhcbiAgaWYgKCBpbmRleCAhPT0gcHJldkluZGV4ICkge1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudCggJ2NoYW5nZScsIG51bGwsIFsgaW5kZXggXSApO1xuICB9XG59O1xuXG4vLyB3cmFwcyBwb3NpdGlvbiBmb3Igd3JhcEFyb3VuZCwgdG8gbW92ZSB0byBjbG9zZXN0IHNsaWRlLiAjMTEzXG5wcm90by5fd3JhcFNlbGVjdCA9IGZ1bmN0aW9uKCBpbmRleCApIHtcbiAgaWYgKCAhdGhpcy5pc1dyYXBwaW5nICkgcmV0dXJuO1xuXG4gIGNvbnN0IHsgc2VsZWN0ZWRJbmRleCwgc2xpZGVhYmxlV2lkdGgsIHNsaWRlczogeyBsZW5ndGggfSB9ID0gdGhpcztcbiAgLy8gc2hpZnQgaW5kZXggZm9yIHdyYXAsIGRvIG5vdCB3cmFwIGRyYWdTZWxlY3RcbiAgaWYgKCAhdGhpcy5pc0RyYWdTZWxlY3QgKSB7XG4gICAgbGV0IHdyYXBJbmRleCA9IHV0aWxzLm1vZHVsbyggaW5kZXgsIGxlbmd0aCApO1xuICAgIC8vIGdvIHRvIHNob3J0ZXN0XG4gICAgbGV0IGRlbHRhID0gTWF0aC5hYnMoIHdyYXBJbmRleCAtIHNlbGVjdGVkSW5kZXggKTtcbiAgICBsZXQgYmFja1dyYXBEZWx0YSA9IE1hdGguYWJzKCAoIHdyYXBJbmRleCArIGxlbmd0aCApIC0gc2VsZWN0ZWRJbmRleCApO1xuICAgIGxldCBmb3Jld2FyZFdyYXBEZWx0YSA9IE1hdGguYWJzKCAoIHdyYXBJbmRleCAtIGxlbmd0aCApIC0gc2VsZWN0ZWRJbmRleCApO1xuICAgIGlmICggYmFja1dyYXBEZWx0YSA8IGRlbHRhICkge1xuICAgICAgaW5kZXggKz0gbGVuZ3RoO1xuICAgIH0gZWxzZSBpZiAoIGZvcmV3YXJkV3JhcERlbHRhIDwgZGVsdGEgKSB7XG4gICAgICBpbmRleCAtPSBsZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgLy8gd3JhcCBwb3NpdGlvbiBzbyBzbGlkZXIgaXMgd2l0aGluIG5vcm1hbCBhcmVhXG4gIGlmICggaW5kZXggPCAwICkge1xuICAgIHRoaXMueCAtPSBzbGlkZWFibGVXaWR0aDtcbiAgfSBlbHNlIGlmICggaW5kZXggPj0gbGVuZ3RoICkge1xuICAgIHRoaXMueCArPSBzbGlkZWFibGVXaWR0aDtcbiAgfVxufTtcblxucHJvdG8ucHJldmlvdXMgPSBmdW5jdGlvbiggaXNXcmFwLCBpc0luc3RhbnQgKSB7XG4gIHRoaXMuc2VsZWN0KCB0aGlzLnNlbGVjdGVkSW5kZXggLSAxLCBpc1dyYXAsIGlzSW5zdGFudCApO1xufTtcblxucHJvdG8ubmV4dCA9IGZ1bmN0aW9uKCBpc1dyYXAsIGlzSW5zdGFudCApIHtcbiAgdGhpcy5zZWxlY3QoIHRoaXMuc2VsZWN0ZWRJbmRleCArIDEsIGlzV3JhcCwgaXNJbnN0YW50ICk7XG59O1xuXG5wcm90by51cGRhdGVTZWxlY3RlZFNsaWRlID0gZnVuY3Rpb24oKSB7XG4gIGxldCBzbGlkZSA9IHRoaXMuc2xpZGVzWyB0aGlzLnNlbGVjdGVkSW5kZXggXTtcbiAgLy8gc2VsZWN0ZWRJbmRleCBjb3VsZCBiZSBvdXRzaWRlIG9mIHNsaWRlcywgaWYgdHJpZ2dlcmVkIGJlZm9yZSByZXNpemUoKVxuICBpZiAoICFzbGlkZSApIHJldHVybjtcblxuICAvLyB1bnNlbGVjdCBwcmV2aW91cyBzZWxlY3RlZCBzbGlkZVxuICB0aGlzLnVuc2VsZWN0U2VsZWN0ZWRTbGlkZSgpO1xuICAvLyB1cGRhdGUgbmV3IHNlbGVjdGVkIHNsaWRlXG4gIHRoaXMuc2VsZWN0ZWRTbGlkZSA9IHNsaWRlO1xuICBzbGlkZS5zZWxlY3QoKTtcbiAgdGhpcy5zZWxlY3RlZENlbGxzID0gc2xpZGUuY2VsbHM7XG4gIHRoaXMuc2VsZWN0ZWRFbGVtZW50cyA9IHNsaWRlLmdldENlbGxFbGVtZW50cygpO1xuICAvLyBIQUNLOiBzZWxlY3RlZENlbGwgJiBzZWxlY3RlZEVsZW1lbnQgaXMgZmlyc3QgY2VsbCBpbiBzbGlkZSwgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbiAgdGhpcy5zZWxlY3RlZENlbGwgPSBzbGlkZS5jZWxsc1swXTtcbiAgdGhpcy5zZWxlY3RlZEVsZW1lbnQgPSB0aGlzLnNlbGVjdGVkRWxlbWVudHNbMF07XG59O1xuXG5wcm90by51bnNlbGVjdFNlbGVjdGVkU2xpZGUgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCB0aGlzLnNlbGVjdGVkU2xpZGUgKSB0aGlzLnNlbGVjdGVkU2xpZGUudW5zZWxlY3QoKTtcbn07XG5cbnByb3RvLnNlbGVjdEluaXRpYWxJbmRleCA9IGZ1bmN0aW9uKCkge1xuICBsZXQgaW5pdGlhbEluZGV4ID0gdGhpcy5vcHRpb25zLmluaXRpYWxJbmRleDtcbiAgLy8gYWxyZWFkeSBhY3RpdmF0ZWQsIHNlbGVjdCBwcmV2aW91cyBzZWxlY3RlZEluZGV4XG4gIGlmICggdGhpcy5pc0luaXRBY3RpdmF0ZWQgKSB7XG4gICAgdGhpcy5zZWxlY3QoIHRoaXMuc2VsZWN0ZWRJbmRleCwgZmFsc2UsIHRydWUgKTtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gc2VsZWN0IHdpdGggc2VsZWN0b3Igc3RyaW5nXG4gIGlmICggaW5pdGlhbEluZGV4ICYmIHR5cGVvZiBpbml0aWFsSW5kZXggPT0gJ3N0cmluZycgKSB7XG4gICAgbGV0IGNlbGwgPSB0aGlzLnF1ZXJ5Q2VsbCggaW5pdGlhbEluZGV4ICk7XG4gICAgaWYgKCBjZWxsICkge1xuICAgICAgdGhpcy5zZWxlY3RDZWxsKCBpbml0aWFsSW5kZXgsIGZhbHNlLCB0cnVlICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG5cbiAgbGV0IGluZGV4ID0gMDtcbiAgLy8gc2VsZWN0IHdpdGggbnVtYmVyXG4gIGlmICggaW5pdGlhbEluZGV4ICYmIHRoaXMuc2xpZGVzWyBpbml0aWFsSW5kZXggXSApIHtcbiAgICBpbmRleCA9IGluaXRpYWxJbmRleDtcbiAgfVxuICAvLyBzZWxlY3QgaW5zdGFudGx5XG4gIHRoaXMuc2VsZWN0KCBpbmRleCwgZmFsc2UsIHRydWUgKTtcbn07XG5cbi8qKlxuICogc2VsZWN0IHNsaWRlIGZyb20gbnVtYmVyIG9yIGNlbGwgZWxlbWVudFxuICogQHBhcmFtIHtbRWxlbWVudCwgTnVtYmVyXX0gdmFsdWUgLSB6ZXJvLWJhc2VkIGluZGV4IG9yIGVsZW1lbnQgdG8gc2VsZWN0XG4gKiBAcGFyYW0ge0Jvb2xlYW59IGlzV3JhcCAtIGVuYWJsZXMgd3JhcHBpbmcgYXJvdW5kIGZvciBleHRyYSBpbmRleFxuICogQHBhcmFtIHtCb29sZWFufSBpc0luc3RhbnQgLSBkaXNhYmxlcyBzbGlkZSBhbmltYXRpb25cbiAqL1xucHJvdG8uc2VsZWN0Q2VsbCA9IGZ1bmN0aW9uKCB2YWx1ZSwgaXNXcmFwLCBpc0luc3RhbnQgKSB7XG4gIC8vIGdldCBjZWxsXG4gIGxldCBjZWxsID0gdGhpcy5xdWVyeUNlbGwoIHZhbHVlICk7XG4gIGlmICggIWNlbGwgKSByZXR1cm47XG5cbiAgbGV0IGluZGV4ID0gdGhpcy5nZXRDZWxsU2xpZGVJbmRleCggY2VsbCApO1xuICB0aGlzLnNlbGVjdCggaW5kZXgsIGlzV3JhcCwgaXNJbnN0YW50ICk7XG59O1xuXG5wcm90by5nZXRDZWxsU2xpZGVJbmRleCA9IGZ1bmN0aW9uKCBjZWxsICkge1xuICAvLyBnZXQgaW5kZXggb2Ygc2xpZGUgdGhhdCBoYXMgY2VsbFxuICBsZXQgY2VsbFNsaWRlID0gdGhpcy5zbGlkZXMuZmluZCggKCBzbGlkZSApID0+IHNsaWRlLmNlbGxzLmluY2x1ZGVzKCBjZWxsICkgKTtcbiAgcmV0dXJuIHRoaXMuc2xpZGVzLmluZGV4T2YoIGNlbGxTbGlkZSApO1xufTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gZ2V0IGNlbGxzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbi8qKlxuICogZ2V0IEZsaWNraXR5LkNlbGwsIGdpdmVuIGFuIEVsZW1lbnRcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbSAtIG1hdGNoaW5nIGNlbGwgZWxlbWVudFxuICogQHJldHVybnMge0ZsaWNraXR5LkNlbGx9IGNlbGwgLSBtYXRjaGluZyBjZWxsXG4gKi9cbnByb3RvLmdldENlbGwgPSBmdW5jdGlvbiggZWxlbSApIHtcbiAgLy8gbG9vcCB0aHJvdWdoIGNlbGxzIHRvIGdldCB0aGUgb25lIHRoYXQgbWF0Y2hlc1xuICBmb3IgKCBsZXQgY2VsbCBvZiB0aGlzLmNlbGxzICkge1xuICAgIGlmICggY2VsbC5lbGVtZW50ID09PSBlbGVtICkgcmV0dXJuIGNlbGw7XG4gIH1cbn07XG5cbi8qKlxuICogZ2V0IGNvbGxlY3Rpb24gb2YgRmxpY2tpdHkuQ2VsbHMsIGdpdmVuIEVsZW1lbnRzXG4gKiBAcGFyYW0ge1tFbGVtZW50LCBBcnJheSwgTm9kZUxpc3RdfSBlbGVtcyAtIG11bHRpcGxlIGVsZW1lbnRzXG4gKiBAcmV0dXJucyB7QXJyYXl9IGNlbGxzIC0gRmxpY2tpdHkuQ2VsbHNcbiAqL1xucHJvdG8uZ2V0Q2VsbHMgPSBmdW5jdGlvbiggZWxlbXMgKSB7XG4gIGVsZW1zID0gdXRpbHMubWFrZUFycmF5KCBlbGVtcyApO1xuICByZXR1cm4gZWxlbXMubWFwKCAoIGVsZW0gKSA9PiB0aGlzLmdldENlbGwoIGVsZW0gKSApLmZpbHRlciggQm9vbGVhbiApO1xufTtcblxuLyoqXG4gKiBnZXQgY2VsbCBlbGVtZW50c1xuICogQHJldHVybnMge0FycmF5fSBjZWxsRWxlbXNcbiAqL1xucHJvdG8uZ2V0Q2VsbEVsZW1lbnRzID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLmNlbGxzLm1hcCggKCBjZWxsICkgPT4gY2VsbC5lbGVtZW50ICk7XG59O1xuXG4vKipcbiAqIGdldCBwYXJlbnQgY2VsbCBmcm9tIGFuIGVsZW1lbnRcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbSAtIGNoaWxkIGVsZW1lbnRcbiAqIEByZXR1cm5zIHtGbGlja2l0LkNlbGx9IGNlbGwgLSBwYXJlbnQgY2VsbFxuICovXG5wcm90by5nZXRQYXJlbnRDZWxsID0gZnVuY3Rpb24oIGVsZW0gKSB7XG4gIC8vIGZpcnN0IGNoZWNrIGlmIGVsZW0gaXMgY2VsbFxuICBsZXQgY2VsbCA9IHRoaXMuZ2V0Q2VsbCggZWxlbSApO1xuICBpZiAoIGNlbGwgKSByZXR1cm4gY2VsbDtcblxuICAvLyB0cnkgdG8gZ2V0IHBhcmVudCBjZWxsIGVsZW1cbiAgbGV0IGNsb3Nlc3QgPSBlbGVtLmNsb3Nlc3QoJy5mbGlja2l0eS1zbGlkZXIgPiAqJyk7XG4gIHJldHVybiB0aGlzLmdldENlbGwoIGNsb3Nlc3QgKTtcbn07XG5cbi8qKlxuICogZ2V0IGNlbGxzIGFkamFjZW50IHRvIGEgc2xpZGVcbiAqIEBwYXJhbSB7SW50ZWdlcn0gYWRqQ291bnQgLSBudW1iZXIgb2YgYWRqYWNlbnQgc2xpZGVzXG4gKiBAcGFyYW0ge0ludGVnZXJ9IGluZGV4IC0gaW5kZXggb2Ygc2xpZGUgdG8gc3RhcnRcbiAqIEByZXR1cm5zIHtBcnJheX0gY2VsbHMgLSBhcnJheSBvZiBGbGlja2l0eS5DZWxsc1xuICovXG5wcm90by5nZXRBZGphY2VudENlbGxFbGVtZW50cyA9IGZ1bmN0aW9uKCBhZGpDb3VudCwgaW5kZXggKSB7XG4gIGlmICggIWFkakNvdW50ICkgcmV0dXJuIHRoaXMuc2VsZWN0ZWRTbGlkZS5nZXRDZWxsRWxlbWVudHMoKTtcblxuICBpbmRleCA9IGluZGV4ID09PSB1bmRlZmluZWQgPyB0aGlzLnNlbGVjdGVkSW5kZXggOiBpbmRleDtcblxuICBsZXQgbGVuID0gdGhpcy5zbGlkZXMubGVuZ3RoO1xuICBpZiAoIDEgKyAoIGFkakNvdW50ICogMiApID49IGxlbiApIHtcbiAgICByZXR1cm4gdGhpcy5nZXRDZWxsRWxlbWVudHMoKTsgLy8gZ2V0IGFsbFxuICB9XG5cbiAgbGV0IGNlbGxFbGVtcyA9IFtdO1xuICBmb3IgKCBsZXQgaSA9IGluZGV4IC0gYWRqQ291bnQ7IGkgPD0gaW5kZXggKyBhZGpDb3VudDsgaSsrICkge1xuICAgIGxldCBzbGlkZUluZGV4ID0gdGhpcy5pc1dyYXBwaW5nID8gdXRpbHMubW9kdWxvKCBpLCBsZW4gKSA6IGk7XG4gICAgbGV0IHNsaWRlID0gdGhpcy5zbGlkZXNbIHNsaWRlSW5kZXggXTtcbiAgICBpZiAoIHNsaWRlICkge1xuICAgICAgY2VsbEVsZW1zID0gY2VsbEVsZW1zLmNvbmNhdCggc2xpZGUuZ2V0Q2VsbEVsZW1lbnRzKCkgKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGNlbGxFbGVtcztcbn07XG5cbi8qKlxuICogc2VsZWN0IHNsaWRlIGZyb20gbnVtYmVyIG9yIGNlbGwgZWxlbWVudFxuICogQHBhcmFtIHtbRWxlbWVudCwgU3RyaW5nLCBOdW1iZXJdfSBzZWxlY3RvciAtIGVsZW1lbnQsIHNlbGVjdG9yIHN0cmluZywgb3IgaW5kZXhcbiAqIEByZXR1cm5zIHtGbGlja2l0eS5DZWxsfSAtIG1hdGNoaW5nIGNlbGxcbiAqL1xucHJvdG8ucXVlcnlDZWxsID0gZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuICBpZiAoIHR5cGVvZiBzZWxlY3RvciA9PSAnbnVtYmVyJyApIHtcbiAgICAvLyB1c2UgbnVtYmVyIGFzIGluZGV4XG4gICAgcmV0dXJuIHRoaXMuY2VsbHNbIHNlbGVjdG9yIF07XG4gIH1cbiAgLy8gZG8gbm90IHNlbGVjdCBpbnZhbGlkIHNlbGVjdG9ycyBmcm9tIGhhc2g6ICMxMjMsICMvLiAjNzkxXG4gIGxldCBpc1NlbGVjdG9yU3RyaW5nID0gdHlwZW9mIHNlbGVjdG9yID09ICdzdHJpbmcnICYmICFzZWxlY3Rvci5tYXRjaCggL15bIy5dP1tcXGQvXS8gKTtcbiAgaWYgKCBpc1NlbGVjdG9yU3RyaW5nICkge1xuICAgIC8vIHVzZSBzdHJpbmcgYXMgc2VsZWN0b3IsIGdldCBlbGVtZW50XG4gICAgc2VsZWN0b3IgPSB0aGlzLmVsZW1lbnQucXVlcnlTZWxlY3Rvciggc2VsZWN0b3IgKTtcbiAgfVxuICAvLyBnZXQgY2VsbCBmcm9tIGVsZW1lbnRcbiAgcmV0dXJuIHRoaXMuZ2V0Q2VsbCggc2VsZWN0b3IgKTtcbn07XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGV2ZW50cyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG5wcm90by51aUNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmVtaXRFdmVudCgndWlDaGFuZ2UnKTtcbn07XG5cbi8vIC0tLS0tIHJlc2l6ZSAtLS0tLSAvL1xuXG5wcm90by5vbnJlc2l6ZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLndhdGNoQ1NTKCk7XG4gIHRoaXMucmVzaXplKCk7XG59O1xuXG51dGlscy5kZWJvdW5jZU1ldGhvZCggRmxpY2tpdHksICdvbnJlc2l6ZScsIDE1MCApO1xuXG5wcm90by5yZXNpemUgPSBmdW5jdGlvbigpIHtcbiAgLy8gIzExNzcgZGlzYWJsZSByZXNpemUgYmVoYXZpb3Igd2hlbiBhbmltYXRpbmcgb3IgZHJhZ2dpbmcgZm9yIGlPUyAxNVxuICBpZiAoICF0aGlzLmlzQWN0aXZlIHx8IHRoaXMuaXNBbmltYXRpbmcgfHwgdGhpcy5pc0RyYWdnaW5nICkgcmV0dXJuO1xuICB0aGlzLmdldFNpemUoKTtcbiAgLy8gd3JhcCB2YWx1ZXNcbiAgaWYgKCB0aGlzLmlzV3JhcHBpbmcgKSB7XG4gICAgdGhpcy54ID0gdXRpbHMubW9kdWxvKCB0aGlzLngsIHRoaXMuc2xpZGVhYmxlV2lkdGggKTtcbiAgfVxuICB0aGlzLnBvc2l0aW9uQ2VsbHMoKTtcbiAgdGhpcy5fdXBkYXRlV3JhcFNoaWZ0Q2VsbHMoKTtcbiAgdGhpcy5zZXRHYWxsZXJ5U2l6ZSgpO1xuICB0aGlzLmVtaXRFdmVudCgncmVzaXplJyk7XG4gIC8vIHVwZGF0ZSBzZWxlY3RlZCBpbmRleCBmb3IgZ3JvdXAgc2xpZGVzLCBpbnN0YW50XG4gIC8vIFRPRE86IHBvc2l0aW9uIGNhbiBiZSBsb3N0IGJldHdlZW4gZ3JvdXBzIG9mIHZhcmlvdXMgbnVtYmVyc1xuICBsZXQgc2VsZWN0ZWRFbGVtZW50ID0gdGhpcy5zZWxlY3RlZEVsZW1lbnRzICYmIHRoaXMuc2VsZWN0ZWRFbGVtZW50c1swXTtcbiAgdGhpcy5zZWxlY3RDZWxsKCBzZWxlY3RlZEVsZW1lbnQsIGZhbHNlLCB0cnVlICk7XG59O1xuXG4vLyB3YXRjaGVzIHRoZSA6YWZ0ZXIgcHJvcGVydHksIGFjdGl2YXRlcy9kZWFjdGl2YXRlc1xucHJvdG8ud2F0Y2hDU1MgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCAhdGhpcy5vcHRpb25zLndhdGNoQ1NTICkgcmV0dXJuO1xuXG4gIGxldCBhZnRlckNvbnRlbnQgPSBnZXRDb21wdXRlZFN0eWxlKCB0aGlzLmVsZW1lbnQsICc6YWZ0ZXInICkuY29udGVudDtcbiAgLy8gYWN0aXZhdGUgaWYgOmFmdGVyIHsgY29udGVudDogJ2ZsaWNraXR5JyB9XG4gIGlmICggYWZ0ZXJDb250ZW50LmluY2x1ZGVzKCdmbGlja2l0eScpICkge1xuICAgIHRoaXMuYWN0aXZhdGUoKTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLmRlYWN0aXZhdGUoKTtcbiAgfVxufTtcblxuLy8gLS0tLS0ga2V5ZG93biAtLS0tLSAvL1xuXG4vLyBnbyBwcmV2aW91cy9uZXh0IGlmIGxlZnQvcmlnaHQga2V5cyBwcmVzc2VkXG5wcm90by5vbmtleWRvd24gPSBmdW5jdGlvbiggZXZlbnQgKSB7XG4gIGxldCB7IGFjdGl2ZUVsZW1lbnQgfSA9IGRvY3VtZW50O1xuICBsZXQgaGFuZGxlciA9IEZsaWNraXR5LmtleWJvYXJkSGFuZGxlcnNbIGV2ZW50LmtleSBdO1xuICAvLyBvbmx5IHdvcmsgaWYgZWxlbWVudCBpcyBpbiBmb2N1c1xuICBpZiAoICF0aGlzLm9wdGlvbnMuYWNjZXNzaWJpbGl0eSB8fCAhYWN0aXZlRWxlbWVudCB8fCAhaGFuZGxlciApIHJldHVybjtcblxuICBsZXQgaXNGb2N1c2VkID0gdGhpcy5mb2N1c2FibGVFbGVtcy5zb21lKCAoIGVsZW0gKSA9PiBhY3RpdmVFbGVtZW50ID09PSBlbGVtICk7XG4gIGlmICggaXNGb2N1c2VkICkgaGFuZGxlci5jYWxsKCB0aGlzICk7XG59O1xuXG5GbGlja2l0eS5rZXlib2FyZEhhbmRsZXJzID0ge1xuICBBcnJvd0xlZnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMudWlDaGFuZ2UoKTtcbiAgICBsZXQgbGVmdE1ldGhvZCA9IHRoaXMub3B0aW9ucy5yaWdodFRvTGVmdCA/ICduZXh0JyA6ICdwcmV2aW91cyc7XG4gICAgdGhpc1sgbGVmdE1ldGhvZCBdKCk7XG4gIH0sXG4gIEFycm93UmlnaHQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMudWlDaGFuZ2UoKTtcbiAgICBsZXQgcmlnaHRNZXRob2QgPSB0aGlzLm9wdGlvbnMucmlnaHRUb0xlZnQgPyAncHJldmlvdXMnIDogJ25leHQnO1xuICAgIHRoaXNbIHJpZ2h0TWV0aG9kIF0oKTtcbiAgfSxcbn07XG5cbi8vIC0tLS0tIGZvY3VzIC0tLS0tIC8vXG5cbnByb3RvLmZvY3VzID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuZWxlbWVudC5mb2N1cyh7IHByZXZlbnRTY3JvbGw6IHRydWUgfSk7XG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBkZXN0cm95IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbi8vIGRlYWN0aXZhdGUgYWxsIEZsaWNraXR5IGZ1bmN0aW9uYWxpdHksIGJ1dCBrZWVwIHN0dWZmIGF2YWlsYWJsZVxucHJvdG8uZGVhY3RpdmF0ZSA9IGZ1bmN0aW9uKCkge1xuICBpZiAoICF0aGlzLmlzQWN0aXZlICkgcmV0dXJuO1xuXG4gIHRoaXMuZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdmbGlja2l0eS1lbmFibGVkJyk7XG4gIHRoaXMuZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdmbGlja2l0eS1ydGwnKTtcbiAgdGhpcy51bnNlbGVjdFNlbGVjdGVkU2xpZGUoKTtcbiAgLy8gZGVzdHJveSBjZWxsc1xuICB0aGlzLmNlbGxzLmZvckVhY2goICggY2VsbCApID0+IGNlbGwuZGVzdHJveSgpICk7XG4gIHRoaXMudmlld3BvcnQucmVtb3ZlKCk7XG4gIC8vIG1vdmUgY2hpbGQgZWxlbWVudHMgYmFjayBpbnRvIGVsZW1lbnRcbiAgdGhpcy5lbGVtZW50LmFwcGVuZCggLi4udGhpcy5zbGlkZXIuY2hpbGRyZW4gKTtcbiAgaWYgKCB0aGlzLm9wdGlvbnMuYWNjZXNzaWJpbGl0eSApIHtcbiAgICB0aGlzLmVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCd0YWJJbmRleCcpO1xuICAgIHRoaXMuZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCAna2V5ZG93bicsIHRoaXMgKTtcbiAgfVxuICAvLyBzZXQgZmxhZ3NcbiAgdGhpcy5pc0FjdGl2ZSA9IGZhbHNlO1xuICB0aGlzLmVtaXRFdmVudCgnZGVhY3RpdmF0ZScpO1xufTtcblxucHJvdG8uZGVzdHJveSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmRlYWN0aXZhdGUoKTtcbiAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoICdyZXNpemUnLCB0aGlzICk7XG4gIHRoaXMuYWxsT2ZmKCk7XG4gIHRoaXMuZW1pdEV2ZW50KCdkZXN0cm95Jyk7XG4gIGlmICggalF1ZXJ5ICYmIHRoaXMuJGVsZW1lbnQgKSB7XG4gICAgalF1ZXJ5LnJlbW92ZURhdGEoIHRoaXMuZWxlbWVudCwgJ2ZsaWNraXR5JyApO1xuICB9XG4gIGRlbGV0ZSB0aGlzLmVsZW1lbnQuZmxpY2tpdHlHVUlEO1xuICBkZWxldGUgaW5zdGFuY2VzWyB0aGlzLmd1aWQgXTtcbn07XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHByb3RvdHlwZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG5PYmplY3QuYXNzaWduKCBwcm90bywgYW5pbWF0ZVByb3RvdHlwZSApO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBleHRyYXMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuLyoqXG4gKiBnZXQgRmxpY2tpdHkgaW5zdGFuY2UgZnJvbSBlbGVtZW50XG4gKiBAcGFyYW0ge1tFbGVtZW50LCBTdHJpbmddfSBlbGVtIC0gZWxlbWVudCBvciBzZWxlY3RvciBzdHJpbmdcbiAqIEByZXR1cm5zIHtGbGlja2l0eX0gLSBGbGlja2l0eSBpbnN0YW5jZVxuICovXG5GbGlja2l0eS5kYXRhID0gZnVuY3Rpb24oIGVsZW0gKSB7XG4gIGVsZW0gPSB1dGlscy5nZXRRdWVyeUVsZW1lbnQoIGVsZW0gKTtcbiAgaWYgKCBlbGVtICkgcmV0dXJuIGluc3RhbmNlc1sgZWxlbS5mbGlja2l0eUdVSUQgXTtcbn07XG5cbnV0aWxzLmh0bWxJbml0KCBGbGlja2l0eSwgJ2ZsaWNraXR5JyApO1xuXG5sZXQgeyBqUXVlcnlCcmlkZ2V0IH0gPSB3aW5kb3c7XG5pZiAoIGpRdWVyeSAmJiBqUXVlcnlCcmlkZ2V0ICkge1xuICBqUXVlcnlCcmlkZ2V0KCAnZmxpY2tpdHknLCBGbGlja2l0eSwgalF1ZXJ5ICk7XG59XG5cbi8vIHNldCBpbnRlcm5hbCBqUXVlcnksIGZvciBXZWJwYWNrICsgalF1ZXJ5IHYzLCAjNDc4XG5GbGlja2l0eS5zZXRKUXVlcnkgPSBmdW5jdGlvbigganEgKSB7XG4gIGpRdWVyeSA9IGpxO1xufTtcblxuRmxpY2tpdHkuQ2VsbCA9IENlbGw7XG5GbGlja2l0eS5TbGlkZSA9IFNsaWRlO1xuXG5yZXR1cm4gRmxpY2tpdHk7XG5cbn0gKSApO1xuIiwiLy8gZHJhZ1xuKCBmdW5jdGlvbiggd2luZG93LCBmYWN0b3J5ICkge1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cbiAgaWYgKCB0eXBlb2YgbW9kdWxlID09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzICkge1xuICAgIC8vIENvbW1vbkpTXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KFxuICAgICAgICB3aW5kb3csXG4gICAgICAgIHJlcXVpcmUoJy4vY29yZScpLFxuICAgICAgICByZXF1aXJlKCd1bmlkcmFnZ2VyJyksXG4gICAgICAgIHJlcXVpcmUoJ2Zpenp5LXVpLXV0aWxzJyksXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBicm93c2VyIGdsb2JhbFxuICAgIHdpbmRvdy5GbGlja2l0eSA9IGZhY3RvcnkoXG4gICAgICAgIHdpbmRvdyxcbiAgICAgICAgd2luZG93LkZsaWNraXR5LFxuICAgICAgICB3aW5kb3cuVW5pZHJhZ2dlcixcbiAgICAgICAgd2luZG93LmZpenp5VUlVdGlscyxcbiAgICApO1xuICB9XG5cbn0oIHR5cGVvZiB3aW5kb3cgIT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzLFxuICAgIGZ1bmN0aW9uIGZhY3RvcnkoIHdpbmRvdywgRmxpY2tpdHksIFVuaWRyYWdnZXIsIHV0aWxzICkge1xuXG4vLyAtLS0tLSBkZWZhdWx0cyAtLS0tLSAvL1xuXG5PYmplY3QuYXNzaWduKCBGbGlja2l0eS5kZWZhdWx0cywge1xuICBkcmFnZ2FibGU6ICc+MScsXG4gIGRyYWdUaHJlc2hvbGQ6IDMsXG59ICk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGRyYWcgcHJvdG90eXBlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbmxldCBwcm90byA9IEZsaWNraXR5LnByb3RvdHlwZTtcbk9iamVjdC5hc3NpZ24oIHByb3RvLCBVbmlkcmFnZ2VyLnByb3RvdHlwZSApOyAvLyBpbmhlcml0IFVuaWRyYWdnZXJcbnByb3RvLnRvdWNoQWN0aW9uVmFsdWUgPSAnJztcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbkZsaWNraXR5LmNyZWF0ZS5kcmFnID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMub24oICdhY3RpdmF0ZScsIHRoaXMub25BY3RpdmF0ZURyYWcgKTtcbiAgdGhpcy5vbiggJ3VpQ2hhbmdlJywgdGhpcy5fdWlDaGFuZ2VEcmFnICk7XG4gIHRoaXMub24oICdkZWFjdGl2YXRlJywgdGhpcy5vbkRlYWN0aXZhdGVEcmFnICk7XG4gIHRoaXMub24oICdjZWxsQ2hhbmdlJywgdGhpcy51cGRhdGVEcmFnZ2FibGUgKTtcbiAgdGhpcy5vbiggJ3BvaW50ZXJEb3duJywgdGhpcy5oYW5kbGVQb2ludGVyRG93biApO1xuICB0aGlzLm9uKCAncG9pbnRlclVwJywgdGhpcy5oYW5kbGVQb2ludGVyVXAgKTtcbiAgdGhpcy5vbiggJ3BvaW50ZXJEb3duJywgdGhpcy5oYW5kbGVQb2ludGVyRG9uZSApO1xuICB0aGlzLm9uKCAnZHJhZ1N0YXJ0JywgdGhpcy5oYW5kbGVEcmFnU3RhcnQgKTtcbiAgdGhpcy5vbiggJ2RyYWdNb3ZlJywgdGhpcy5oYW5kbGVEcmFnTW92ZSApO1xuICB0aGlzLm9uKCAnZHJhZ0VuZCcsIHRoaXMuaGFuZGxlRHJhZ0VuZCApO1xuICB0aGlzLm9uKCAnc3RhdGljQ2xpY2snLCB0aGlzLmhhbmRsZVN0YXRpY0NsaWNrICk7XG4gIC8vIFRPRE8gdXBkYXRlRHJhZ2dhYmxlIG9uIHJlc2l6ZT8gaWYgZ3JvdXBDZWxscyAmIHNsaWRlcyBjaGFuZ2Vcbn07XG5cbnByb3RvLm9uQWN0aXZhdGVEcmFnID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuaGFuZGxlcyA9IFsgdGhpcy52aWV3cG9ydCBdO1xuICB0aGlzLmJpbmRIYW5kbGVzKCk7XG4gIHRoaXMudXBkYXRlRHJhZ2dhYmxlKCk7XG59O1xuXG5wcm90by5vbkRlYWN0aXZhdGVEcmFnID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMudW5iaW5kSGFuZGxlcygpO1xuICB0aGlzLmVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgnaXMtZHJhZ2dhYmxlJyk7XG59O1xuXG5wcm90by51cGRhdGVEcmFnZ2FibGUgPSBmdW5jdGlvbigpIHtcbiAgLy8gZGlzYWJsZSBkcmFnZ2luZyBpZiBsZXNzIHRoYW4gMiBzbGlkZXMuICMyNzhcbiAgaWYgKCB0aGlzLm9wdGlvbnMuZHJhZ2dhYmxlID09PSAnPjEnICkge1xuICAgIHRoaXMuaXNEcmFnZ2FibGUgPSB0aGlzLnNsaWRlcy5sZW5ndGggPiAxO1xuICB9IGVsc2Uge1xuICAgIHRoaXMuaXNEcmFnZ2FibGUgPSB0aGlzLm9wdGlvbnMuZHJhZ2dhYmxlO1xuICB9XG4gIHRoaXMuZWxlbWVudC5jbGFzc0xpc3QudG9nZ2xlKCAnaXMtZHJhZ2dhYmxlJywgdGhpcy5pc0RyYWdnYWJsZSApO1xufTtcblxucHJvdG8uX3VpQ2hhbmdlRHJhZyA9IGZ1bmN0aW9uKCkge1xuICBkZWxldGUgdGhpcy5pc0ZyZWVTY3JvbGxpbmc7XG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBwb2ludGVyIGV2ZW50cyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG5wcm90by5oYW5kbGVQb2ludGVyRG93biA9IGZ1bmN0aW9uKCBldmVudCApIHtcbiAgaWYgKCAhdGhpcy5pc0RyYWdnYWJsZSApIHtcbiAgICAvLyBwcm9jZWVkIGZvciBzdGF0aWNDbGlja1xuICAgIHRoaXMuYmluZEFjdGl2ZVBvaW50ZXJFdmVudHMoIGV2ZW50ICk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgbGV0IGlzVG91Y2hTdGFydCA9IGV2ZW50LnR5cGUgPT09ICd0b3VjaHN0YXJ0JztcbiAgbGV0IGlzVG91Y2hQb2ludGVyID0gZXZlbnQucG9pbnRlclR5cGUgPT09ICd0b3VjaCc7XG4gIGxldCBpc0ZvY3VzTm9kZSA9IGV2ZW50LnRhcmdldC5tYXRjaGVzKCdpbnB1dCwgdGV4dGFyZWEsIHNlbGVjdCcpO1xuICBpZiAoICFpc1RvdWNoU3RhcnQgJiYgIWlzVG91Y2hQb2ludGVyICYmICFpc0ZvY3VzTm9kZSApIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gIGlmICggIWlzRm9jdXNOb2RlICkgdGhpcy5mb2N1cygpO1xuICAvLyBibHVyXG4gIGlmICggZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAhPT0gdGhpcy5lbGVtZW50ICkgZG9jdW1lbnQuYWN0aXZlRWxlbWVudC5ibHVyKCk7XG4gIC8vIHN0b3AgaWYgaXQgd2FzIG1vdmluZ1xuICB0aGlzLmRyYWdYID0gdGhpcy54O1xuICB0aGlzLnZpZXdwb3J0LmNsYXNzTGlzdC5hZGQoJ2lzLXBvaW50ZXItZG93bicpO1xuICAvLyB0cmFjayBzY3JvbGxpbmdcbiAgdGhpcy5wb2ludGVyRG93blNjcm9sbCA9IGdldFNjcm9sbFBvc2l0aW9uKCk7XG4gIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCAnc2Nyb2xsJywgdGhpcyApO1xuICB0aGlzLmJpbmRBY3RpdmVQb2ludGVyRXZlbnRzKCBldmVudCApO1xufTtcblxuLy8gLS0tLS0gbW92ZSAtLS0tLSAvL1xuXG5wcm90by5oYXNEcmFnU3RhcnRlZCA9IGZ1bmN0aW9uKCBtb3ZlVmVjdG9yICkge1xuICByZXR1cm4gTWF0aC5hYnMoIG1vdmVWZWN0b3IueCApID4gdGhpcy5vcHRpb25zLmRyYWdUaHJlc2hvbGQ7XG59O1xuXG4vLyAtLS0tLSB1cCAtLS0tLSAvL1xuXG5wcm90by5oYW5kbGVQb2ludGVyVXAgPSBmdW5jdGlvbigpIHtcbiAgZGVsZXRlIHRoaXMuaXNUb3VjaFNjcm9sbGluZztcbiAgdGhpcy52aWV3cG9ydC5jbGFzc0xpc3QucmVtb3ZlKCdpcy1wb2ludGVyLWRvd24nKTtcbn07XG5cbnByb3RvLmhhbmRsZVBvaW50ZXJEb25lID0gZnVuY3Rpb24oKSB7XG4gIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCAnc2Nyb2xsJywgdGhpcyApO1xuICBkZWxldGUgdGhpcy5wb2ludGVyRG93blNjcm9sbDtcbn07XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGRyYWdnaW5nIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbnByb3RvLmhhbmRsZURyYWdTdGFydCA9IGZ1bmN0aW9uKCkge1xuICBpZiAoICF0aGlzLmlzRHJhZ2dhYmxlICkgcmV0dXJuO1xuXG4gIHRoaXMuZHJhZ1N0YXJ0UG9zaXRpb24gPSB0aGlzLng7XG4gIHRoaXMuc3RhcnRBbmltYXRpb24oKTtcbiAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoICdzY3JvbGwnLCB0aGlzICk7XG59O1xuXG5wcm90by5oYW5kbGVEcmFnTW92ZSA9IGZ1bmN0aW9uKCBldmVudCwgcG9pbnRlciwgbW92ZVZlY3RvciApIHtcbiAgaWYgKCAhdGhpcy5pc0RyYWdnYWJsZSApIHJldHVybjtcblxuICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gIHRoaXMucHJldmlvdXNEcmFnWCA9IHRoaXMuZHJhZ1g7XG4gIC8vIHJldmVyc2UgaWYgcmlnaHQtdG8tbGVmdFxuICBsZXQgZGlyZWN0aW9uID0gdGhpcy5vcHRpb25zLnJpZ2h0VG9MZWZ0ID8gLTEgOiAxO1xuICAvLyB3cmFwIGFyb3VuZCBtb3ZlLiAjNTg5XG4gIGlmICggdGhpcy5pc1dyYXBwaW5nICkgbW92ZVZlY3Rvci54ICU9IHRoaXMuc2xpZGVhYmxlV2lkdGg7XG4gIGxldCBkcmFnWCA9IHRoaXMuZHJhZ1N0YXJ0UG9zaXRpb24gKyBtb3ZlVmVjdG9yLnggKiBkaXJlY3Rpb247XG5cbiAgaWYgKCAhdGhpcy5pc1dyYXBwaW5nICkge1xuICAgIC8vIHNsb3cgZHJhZ1xuICAgIGxldCBvcmlnaW5Cb3VuZCA9IE1hdGgubWF4KCAtdGhpcy5zbGlkZXNbMF0udGFyZ2V0LCB0aGlzLmRyYWdTdGFydFBvc2l0aW9uICk7XG4gICAgZHJhZ1ggPSBkcmFnWCA+IG9yaWdpbkJvdW5kID8gKCBkcmFnWCArIG9yaWdpbkJvdW5kICkgKiAwLjUgOiBkcmFnWDtcbiAgICBsZXQgZW5kQm91bmQgPSBNYXRoLm1pbiggLXRoaXMuZ2V0TGFzdFNsaWRlKCkudGFyZ2V0LCB0aGlzLmRyYWdTdGFydFBvc2l0aW9uICk7XG4gICAgZHJhZ1ggPSBkcmFnWCA8IGVuZEJvdW5kID8gKCBkcmFnWCArIGVuZEJvdW5kICkgKiAwLjUgOiBkcmFnWDtcbiAgfVxuXG4gIHRoaXMuZHJhZ1ggPSBkcmFnWDtcbiAgdGhpcy5kcmFnTW92ZVRpbWUgPSBuZXcgRGF0ZSgpO1xufTtcblxucHJvdG8uaGFuZGxlRHJhZ0VuZCA9IGZ1bmN0aW9uKCkge1xuICBpZiAoICF0aGlzLmlzRHJhZ2dhYmxlICkgcmV0dXJuO1xuXG4gIGxldCB7IGZyZWVTY3JvbGwgfSA9IHRoaXMub3B0aW9ucztcbiAgaWYgKCBmcmVlU2Nyb2xsICkgdGhpcy5pc0ZyZWVTY3JvbGxpbmcgPSB0cnVlO1xuICAvLyBzZXQgc2VsZWN0ZWRJbmRleCBiYXNlZCBvbiB3aGVyZSBmbGljayB3aWxsIGVuZCB1cFxuICBsZXQgaW5kZXggPSB0aGlzLmRyYWdFbmRSZXN0aW5nU2VsZWN0KCk7XG5cbiAgaWYgKCBmcmVlU2Nyb2xsICYmICF0aGlzLmlzV3JhcHBpbmcgKSB7XG4gICAgLy8gaWYgZnJlZS1zY3JvbGwgJiBub3Qgd3JhcCBhcm91bmRcbiAgICAvLyBkbyBub3QgZnJlZS1zY3JvbGwgaWYgZ29pbmcgb3V0c2lkZSBvZiBib3VuZGluZyBzbGlkZXNcbiAgICAvLyBzbyBib3VuZGluZyBzbGlkZXMgY2FuIGF0dHJhY3Qgc2xpZGVyLCBhbmQga2VlcCBpdCBpbiBib3VuZHNcbiAgICBsZXQgcmVzdGluZ1ggPSB0aGlzLmdldFJlc3RpbmdQb3NpdGlvbigpO1xuICAgIHRoaXMuaXNGcmVlU2Nyb2xsaW5nID0gLXJlc3RpbmdYID4gdGhpcy5zbGlkZXNbMF0udGFyZ2V0ICYmXG4gICAgICAtcmVzdGluZ1ggPCB0aGlzLmdldExhc3RTbGlkZSgpLnRhcmdldDtcbiAgfSBlbHNlIGlmICggIWZyZWVTY3JvbGwgJiYgaW5kZXggPT09IHRoaXMuc2VsZWN0ZWRJbmRleCApIHtcbiAgICAvLyBib29zdCBzZWxlY3Rpb24gaWYgc2VsZWN0ZWQgaW5kZXggaGFzIG5vdCBjaGFuZ2VkXG4gICAgaW5kZXggKz0gdGhpcy5kcmFnRW5kQm9vc3RTZWxlY3QoKTtcbiAgfVxuICBkZWxldGUgdGhpcy5wcmV2aW91c0RyYWdYO1xuICAvLyBhcHBseSBzZWxlY3Rpb25cbiAgLy8gSEFDSywgc2V0IGZsYWcgc28gZHJhZ2dpbmcgc3RheXMgaW4gY29ycmVjdCBkaXJlY3Rpb25cbiAgdGhpcy5pc0RyYWdTZWxlY3QgPSB0aGlzLmlzV3JhcHBpbmc7XG4gIHRoaXMuc2VsZWN0KCBpbmRleCApO1xuICBkZWxldGUgdGhpcy5pc0RyYWdTZWxlY3Q7XG59O1xuXG5wcm90by5kcmFnRW5kUmVzdGluZ1NlbGVjdCA9IGZ1bmN0aW9uKCkge1xuICBsZXQgcmVzdGluZ1ggPSB0aGlzLmdldFJlc3RpbmdQb3NpdGlvbigpO1xuICAvLyBob3cgZmFyIGF3YXkgZnJvbSBzZWxlY3RlZCBzbGlkZVxuICBsZXQgZGlzdGFuY2UgPSBNYXRoLmFicyggdGhpcy5nZXRTbGlkZURpc3RhbmNlKCAtcmVzdGluZ1gsIHRoaXMuc2VsZWN0ZWRJbmRleCApICk7XG4gIC8vIGdldCBjbG9zZXQgcmVzdGluZyBnb2luZyB1cCBhbmQgZ29pbmcgZG93blxuICBsZXQgcG9zaXRpdmVSZXN0aW5nID0gdGhpcy5fZ2V0Q2xvc2VzdFJlc3RpbmcoIHJlc3RpbmdYLCBkaXN0YW5jZSwgMSApO1xuICBsZXQgbmVnYXRpdmVSZXN0aW5nID0gdGhpcy5fZ2V0Q2xvc2VzdFJlc3RpbmcoIHJlc3RpbmdYLCBkaXN0YW5jZSwgLTEgKTtcbiAgLy8gdXNlIGNsb3NlciByZXN0aW5nIGZvciB3cmFwLWFyb3VuZFxuICByZXR1cm4gcG9zaXRpdmVSZXN0aW5nLmRpc3RhbmNlIDwgbmVnYXRpdmVSZXN0aW5nLmRpc3RhbmNlID9cbiAgICBwb3NpdGl2ZVJlc3RpbmcuaW5kZXggOiBuZWdhdGl2ZVJlc3RpbmcuaW5kZXg7XG59O1xuXG4vKipcbiAqIGdpdmVuIHJlc3RpbmcgWCBhbmQgZGlzdGFuY2UgdG8gc2VsZWN0ZWQgY2VsbFxuICogZ2V0IHRoZSBkaXN0YW5jZSBhbmQgaW5kZXggb2YgdGhlIGNsb3Nlc3QgY2VsbFxuICogQHBhcmFtIHtOdW1iZXJ9IHJlc3RpbmdYIC0gZXN0aW1hdGVkIHBvc3QtZmxpY2sgcmVzdGluZyBwb3NpdGlvblxuICogQHBhcmFtIHtOdW1iZXJ9IGRpc3RhbmNlIC0gZGlzdGFuY2UgdG8gc2VsZWN0ZWQgY2VsbFxuICogQHBhcmFtIHtJbnRlZ2VyfSBpbmNyZW1lbnQgLSArMSBvciAtMSwgZ29pbmcgdXAgb3IgZG93blxuICogQHJldHVybnMge09iamVjdH0gLSB7IGRpc3RhbmNlOiB7TnVtYmVyfSwgaW5kZXg6IHtJbnRlZ2VyfSB9XG4gKi9cbnByb3RvLl9nZXRDbG9zZXN0UmVzdGluZyA9IGZ1bmN0aW9uKCByZXN0aW5nWCwgZGlzdGFuY2UsIGluY3JlbWVudCApIHtcbiAgbGV0IGluZGV4ID0gdGhpcy5zZWxlY3RlZEluZGV4O1xuICBsZXQgbWluRGlzdGFuY2UgPSBJbmZpbml0eTtcbiAgbGV0IGNvbmRpdGlvbiA9IHRoaXMub3B0aW9ucy5jb250YWluICYmICF0aGlzLmlzV3JhcHBpbmcgP1xuICAgIC8vIGlmIGNvbnRhaW5pbmcsIGtlZXAgZ29pbmcgaWYgZGlzdGFuY2UgaXMgZXF1YWwgdG8gbWluRGlzdGFuY2VcbiAgICAoIGRpc3QsIG1pbkRpc3QgKSA9PiBkaXN0IDw9IG1pbkRpc3QgOlxuICAgICggZGlzdCwgbWluRGlzdCApID0+IGRpc3QgPCBtaW5EaXN0O1xuXG4gIHdoaWxlICggY29uZGl0aW9uKCBkaXN0YW5jZSwgbWluRGlzdGFuY2UgKSApIHtcbiAgICAvLyBtZWFzdXJlIGRpc3RhbmNlIHRvIG5leHQgY2VsbFxuICAgIGluZGV4ICs9IGluY3JlbWVudDtcbiAgICBtaW5EaXN0YW5jZSA9IGRpc3RhbmNlO1xuICAgIGRpc3RhbmNlID0gdGhpcy5nZXRTbGlkZURpc3RhbmNlKCAtcmVzdGluZ1gsIGluZGV4ICk7XG4gICAgaWYgKCBkaXN0YW5jZSA9PT0gbnVsbCApIGJyZWFrO1xuXG4gICAgZGlzdGFuY2UgPSBNYXRoLmFicyggZGlzdGFuY2UgKTtcbiAgfVxuICByZXR1cm4ge1xuICAgIGRpc3RhbmNlOiBtaW5EaXN0YW5jZSxcbiAgICAvLyBzZWxlY3RlZCB3YXMgcHJldmlvdXMgaW5kZXhcbiAgICBpbmRleDogaW5kZXggLSBpbmNyZW1lbnQsXG4gIH07XG59O1xuXG4vKipcbiAqIG1lYXN1cmUgZGlzdGFuY2UgYmV0d2VlbiB4IGFuZCBhIHNsaWRlIHRhcmdldFxuICogQHBhcmFtIHtOdW1iZXJ9IHggLSBob3Jpem9udGFsIHBvc2l0aW9uXG4gKiBAcGFyYW0ge0ludGVnZXJ9IGluZGV4IC0gc2xpZGUgaW5kZXhcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IC0gc2xpZGUgZGlzdGFuY2VcbiAqL1xucHJvdG8uZ2V0U2xpZGVEaXN0YW5jZSA9IGZ1bmN0aW9uKCB4LCBpbmRleCApIHtcbiAgbGV0IGxlbiA9IHRoaXMuc2xpZGVzLmxlbmd0aDtcbiAgLy8gd3JhcCBhcm91bmQgaWYgYXQgbGVhc3QgMiBzbGlkZXNcbiAgbGV0IGlzV3JhcEFyb3VuZCA9IHRoaXMub3B0aW9ucy53cmFwQXJvdW5kICYmIGxlbiA+IDE7XG4gIGxldCBzbGlkZUluZGV4ID0gaXNXcmFwQXJvdW5kID8gdXRpbHMubW9kdWxvKCBpbmRleCwgbGVuICkgOiBpbmRleDtcbiAgbGV0IHNsaWRlID0gdGhpcy5zbGlkZXNbIHNsaWRlSW5kZXggXTtcbiAgaWYgKCAhc2xpZGUgKSByZXR1cm4gbnVsbDtcblxuICAvLyBhZGQgZGlzdGFuY2UgZm9yIHdyYXAtYXJvdW5kIHNsaWRlc1xuICBsZXQgd3JhcCA9IGlzV3JhcEFyb3VuZCA/IHRoaXMuc2xpZGVhYmxlV2lkdGggKiBNYXRoLmZsb29yKCBpbmRleC9sZW4gKSA6IDA7XG4gIHJldHVybiB4IC0gKCBzbGlkZS50YXJnZXQgKyB3cmFwICk7XG59O1xuXG5wcm90by5kcmFnRW5kQm9vc3RTZWxlY3QgPSBmdW5jdGlvbigpIHtcbiAgLy8gZG8gbm90IGJvb3N0IGlmIG5vIHByZXZpb3VzRHJhZ1ggb3IgZHJhZ01vdmVUaW1lXG4gIGlmICggdGhpcy5wcmV2aW91c0RyYWdYID09PSB1bmRlZmluZWQgfHwgIXRoaXMuZHJhZ01vdmVUaW1lIHx8XG4gICAgLy8gb3IgaWYgZHJhZyB3YXMgaGVsZCBmb3IgMTAwIG1zXG4gICAgbmV3IERhdGUoKSAtIHRoaXMuZHJhZ01vdmVUaW1lID4gMTAwICkge1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgbGV0IGRpc3RhbmNlID0gdGhpcy5nZXRTbGlkZURpc3RhbmNlKCAtdGhpcy5kcmFnWCwgdGhpcy5zZWxlY3RlZEluZGV4ICk7XG4gIGxldCBkZWx0YSA9IHRoaXMucHJldmlvdXNEcmFnWCAtIHRoaXMuZHJhZ1g7XG4gIGlmICggZGlzdGFuY2UgPiAwICYmIGRlbHRhID4gMCApIHtcbiAgICAvLyBib29zdCB0byBuZXh0IGlmIG1vdmluZyB0b3dhcmRzIHRoZSByaWdodCwgYW5kIHBvc2l0aXZlIHZlbG9jaXR5XG4gICAgcmV0dXJuIDE7XG4gIH0gZWxzZSBpZiAoIGRpc3RhbmNlIDwgMCAmJiBkZWx0YSA8IDAgKSB7XG4gICAgLy8gYm9vc3QgdG8gcHJldmlvdXMgaWYgbW92aW5nIHRvd2FyZHMgdGhlIGxlZnQsIGFuZCBuZWdhdGl2ZSB2ZWxvY2l0eVxuICAgIHJldHVybiAtMTtcbiAgfVxuICByZXR1cm4gMDtcbn07XG5cbi8vIC0tLS0tIHNjcm9sbCAtLS0tLSAvL1xuXG5wcm90by5vbnNjcm9sbCA9IGZ1bmN0aW9uKCkge1xuICBsZXQgc2Nyb2xsID0gZ2V0U2Nyb2xsUG9zaXRpb24oKTtcbiAgbGV0IHNjcm9sbE1vdmVYID0gdGhpcy5wb2ludGVyRG93blNjcm9sbC54IC0gc2Nyb2xsLng7XG4gIGxldCBzY3JvbGxNb3ZlWSA9IHRoaXMucG9pbnRlckRvd25TY3JvbGwueSAtIHNjcm9sbC55O1xuICAvLyBjYW5jZWwgY2xpY2svdGFwIGlmIHNjcm9sbCBpcyB0b28gbXVjaFxuICBpZiAoIE1hdGguYWJzKCBzY3JvbGxNb3ZlWCApID4gMyB8fCBNYXRoLmFicyggc2Nyb2xsTW92ZVkgKSA+IDMgKSB7XG4gICAgdGhpcy5wb2ludGVyRG9uZSgpO1xuICB9XG59O1xuXG4vLyAtLS0tLSB1dGlscyAtLS0tLSAvL1xuXG5mdW5jdGlvbiBnZXRTY3JvbGxQb3NpdGlvbigpIHtcbiAgcmV0dXJuIHtcbiAgICB4OiB3aW5kb3cucGFnZVhPZmZzZXQsXG4gICAgeTogd2luZG93LnBhZ2VZT2Zmc2V0LFxuICB9O1xufVxuXG4vLyAtLS0tLSAgLS0tLS0gLy9cblxucmV0dXJuIEZsaWNraXR5O1xuXG59ICkgKTtcbiIsIi8vIGltYWdlc2xvYWRlZFxuKCBmdW5jdGlvbiggd2luZG93LCBmYWN0b3J5ICkge1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cbiAgaWYgKCB0eXBlb2YgbW9kdWxlID09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzICkge1xuICAgIC8vIENvbW1vbkpTXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KFxuICAgICAgICByZXF1aXJlKCcuL2NvcmUnKSxcbiAgICAgICAgcmVxdWlyZSgnaW1hZ2VzbG9hZGVkJyksXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBicm93c2VyIGdsb2JhbFxuICAgIGZhY3RvcnkoXG4gICAgICAgIHdpbmRvdy5GbGlja2l0eSxcbiAgICAgICAgd2luZG93LmltYWdlc0xvYWRlZCxcbiAgICApO1xuICB9XG5cbn0oIHR5cGVvZiB3aW5kb3cgIT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzLFxuICAgIGZ1bmN0aW9uIGZhY3RvcnkoIEZsaWNraXR5LCBpbWFnZXNMb2FkZWQgKSB7XG5cbkZsaWNraXR5LmNyZWF0ZS5pbWFnZXNMb2FkZWQgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5vbiggJ2FjdGl2YXRlJywgdGhpcy5pbWFnZXNMb2FkZWQgKTtcbn07XG5cbkZsaWNraXR5LnByb3RvdHlwZS5pbWFnZXNMb2FkZWQgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCAhdGhpcy5vcHRpb25zLmltYWdlc0xvYWRlZCApIHJldHVybjtcblxuICBsZXQgb25JbWFnZXNMb2FkZWRQcm9ncmVzcyA9ICggaW5zdGFuY2UsIGltYWdlICkgPT4ge1xuICAgIGxldCBjZWxsID0gdGhpcy5nZXRQYXJlbnRDZWxsKCBpbWFnZS5pbWcgKTtcbiAgICB0aGlzLmNlbGxTaXplQ2hhbmdlKCBjZWxsICYmIGNlbGwuZWxlbWVudCApO1xuICAgIGlmICggIXRoaXMub3B0aW9ucy5mcmVlU2Nyb2xsICkgdGhpcy5wb3NpdGlvblNsaWRlckF0U2VsZWN0ZWQoKTtcbiAgfTtcbiAgaW1hZ2VzTG9hZGVkKCB0aGlzLnNsaWRlciApLm9uKCAncHJvZ3Jlc3MnLCBvbkltYWdlc0xvYWRlZFByb2dyZXNzICk7XG59O1xuXG5yZXR1cm4gRmxpY2tpdHk7XG5cbn0gKSApO1xuIiwiLyohXG4gKiBGbGlja2l0eSB2My4wLjBcbiAqIFRvdWNoLCByZXNwb25zaXZlLCBmbGlja2FibGUgY2Fyb3VzZWxzXG4gKlxuICogTGljZW5zZWQgR1BMdjMgZm9yIG9wZW4gc291cmNlIHVzZVxuICogb3IgRmxpY2tpdHkgQ29tbWVyY2lhbCBMaWNlbnNlIGZvciBjb21tZXJjaWFsIHVzZVxuICpcbiAqIGh0dHBzOi8vZmxpY2tpdHkubWV0YWZpenp5LmNvXG4gKiBDb3B5cmlnaHQgMjAxNS0yMDIyIE1ldGFmaXp6eVxuICovXG5cbmlmICggdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyApIHtcbiAgY29uc3QgRmxpY2tpdHkgPSByZXF1aXJlKCcuL2NvcmUnKTtcbiAgcmVxdWlyZSgnLi9kcmFnJyk7XG4gIHJlcXVpcmUoJy4vcHJldi1uZXh0LWJ1dHRvbicpO1xuICByZXF1aXJlKCcuL3BhZ2UtZG90cycpO1xuICByZXF1aXJlKCcuL3BsYXllcicpO1xuICByZXF1aXJlKCcuL2FkZC1yZW1vdmUtY2VsbCcpO1xuICByZXF1aXJlKCcuL2xhenlsb2FkJyk7XG4gIHJlcXVpcmUoJy4vaW1hZ2VzbG9hZGVkJyk7XG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBGbGlja2l0eTtcbn1cbiIsIi8vIGxhenlsb2FkXG4oIGZ1bmN0aW9uKCB3aW5kb3csIGZhY3RvcnkgKSB7XG4gIC8vIHVuaXZlcnNhbCBtb2R1bGUgZGVmaW5pdGlvblxuICBpZiAoIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG4gICAgLy8gQ29tbW9uSlNcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoXG4gICAgICAgIHJlcXVpcmUoJy4vY29yZScpLFxuICAgICAgICByZXF1aXJlKCdmaXp6eS11aS11dGlscycpLFxuICAgICk7XG4gIH0gZWxzZSB7XG4gICAgLy8gYnJvd3NlciBnbG9iYWxcbiAgICBmYWN0b3J5KFxuICAgICAgICB3aW5kb3cuRmxpY2tpdHksXG4gICAgICAgIHdpbmRvdy5maXp6eVVJVXRpbHMsXG4gICAgKTtcbiAgfVxuXG59KCB0eXBlb2Ygd2luZG93ICE9ICd1bmRlZmluZWQnID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24gZmFjdG9yeSggRmxpY2tpdHksIHV0aWxzICkge1xuXG5jb25zdCBsYXp5QXR0ciA9ICdkYXRhLWZsaWNraXR5LWxhenlsb2FkJztcbmNvbnN0IGxhenlTcmNBdHRyID0gYCR7bGF6eUF0dHJ9LXNyY2A7XG5jb25zdCBsYXp5U3Jjc2V0QXR0ciA9IGAke2xhenlBdHRyfS1zcmNzZXRgO1xuY29uc3QgaW1nU2VsZWN0b3IgPSBgaW1nWyR7bGF6eUF0dHJ9XSwgaW1nWyR7bGF6eVNyY0F0dHJ9XSwgYCArXG4gIGBpbWdbJHtsYXp5U3Jjc2V0QXR0cn1dLCBzb3VyY2VbJHtsYXp5U3Jjc2V0QXR0cn1dYDtcblxuRmxpY2tpdHkuY3JlYXRlLmxhenlMb2FkID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMub24oICdzZWxlY3QnLCB0aGlzLmxhenlMb2FkICk7XG5cbiAgdGhpcy5oYW5kbGVMYXp5TG9hZENvbXBsZXRlID0gdGhpcy5vbkxhenlMb2FkQ29tcGxldGUuYmluZCggdGhpcyApO1xufTtcblxubGV0IHByb3RvID0gRmxpY2tpdHkucHJvdG90eXBlO1xuXG5wcm90by5sYXp5TG9hZCA9IGZ1bmN0aW9uKCkge1xuICBsZXQgeyBsYXp5TG9hZCB9ID0gdGhpcy5vcHRpb25zO1xuICBpZiAoICFsYXp5TG9hZCApIHJldHVybjtcblxuICAvLyBnZXQgYWRqYWNlbnQgY2VsbHMsIHVzZSBsYXp5TG9hZCBvcHRpb24gZm9yIGFkamFjZW50IGNvdW50XG4gIGxldCBhZGpDb3VudCA9IHR5cGVvZiBsYXp5TG9hZCA9PSAnbnVtYmVyJyA/IGxhenlMb2FkIDogMDtcbiAgLy8gbGF6eSBsb2FkIGltYWdlc1xuICB0aGlzLmdldEFkamFjZW50Q2VsbEVsZW1lbnRzKCBhZGpDb3VudCApXG4gICAgLm1hcCggZ2V0Q2VsbExhenlJbWFnZXMgKVxuICAgIC5mbGF0KClcbiAgICAuZm9yRWFjaCggKCBpbWcgKSA9PiBuZXcgTGF6eUxvYWRlciggaW1nLCB0aGlzLmhhbmRsZUxhenlMb2FkQ29tcGxldGUgKSApO1xufTtcblxuZnVuY3Rpb24gZ2V0Q2VsbExhenlJbWFnZXMoIGNlbGxFbGVtICkge1xuICAvLyBjaGVjayBpZiBjZWxsIGVsZW1lbnQgaXMgbGF6eSBpbWFnZVxuICBpZiAoIGNlbGxFbGVtLm1hdGNoZXMoJ2ltZycpICkge1xuICAgIGxldCBjZWxsQXR0ciA9IGNlbGxFbGVtLmdldEF0dHJpYnV0ZSggbGF6eUF0dHIgKTtcbiAgICBsZXQgY2VsbFNyY0F0dHIgPSBjZWxsRWxlbS5nZXRBdHRyaWJ1dGUoIGxhenlTcmNBdHRyICk7XG4gICAgbGV0IGNlbGxTcmNzZXRBdHRyID0gY2VsbEVsZW0uZ2V0QXR0cmlidXRlKCBsYXp5U3Jjc2V0QXR0ciApO1xuICAgIGlmICggY2VsbEF0dHIgfHwgY2VsbFNyY0F0dHIgfHwgY2VsbFNyY3NldEF0dHIgKSB7XG4gICAgICByZXR1cm4gY2VsbEVsZW07XG4gICAgfVxuICB9XG4gIC8vIHNlbGVjdCBsYXp5IGltYWdlcyBpbiBjZWxsXG4gIHJldHVybiBbIC4uLmNlbGxFbGVtLnF1ZXJ5U2VsZWN0b3JBbGwoIGltZ1NlbGVjdG9yICkgXTtcbn1cblxucHJvdG8ub25MYXp5TG9hZENvbXBsZXRlID0gZnVuY3Rpb24oIGltZywgZXZlbnQgKSB7XG4gIGxldCBjZWxsID0gdGhpcy5nZXRQYXJlbnRDZWxsKCBpbWcgKTtcbiAgbGV0IGNlbGxFbGVtID0gY2VsbCAmJiBjZWxsLmVsZW1lbnQ7XG4gIHRoaXMuY2VsbFNpemVDaGFuZ2UoIGNlbGxFbGVtICk7XG5cbiAgdGhpcy5kaXNwYXRjaEV2ZW50KCAnbGF6eUxvYWQnLCBldmVudCwgY2VsbEVsZW0gKTtcbn07XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIExhenlMb2FkZXIgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuLyoqXG4gKiBjbGFzcyB0byBoYW5kbGUgbG9hZGluZyBpbWFnZXNcbiAqIEBwYXJhbSB7SW1hZ2V9IGltZyAtIEltYWdlIGVsZW1lbnRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG9uQ29tcGxldGUgLSBjYWxsYmFjayBmdW5jdGlvblxuICovXG5mdW5jdGlvbiBMYXp5TG9hZGVyKCBpbWcsIG9uQ29tcGxldGUgKSB7XG4gIHRoaXMuaW1nID0gaW1nO1xuICB0aGlzLm9uQ29tcGxldGUgPSBvbkNvbXBsZXRlO1xuICB0aGlzLmxvYWQoKTtcbn1cblxuTGF6eUxvYWRlci5wcm90b3R5cGUuaGFuZGxlRXZlbnQgPSB1dGlscy5oYW5kbGVFdmVudDtcblxuTGF6eUxvYWRlci5wcm90b3R5cGUubG9hZCA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmltZy5hZGRFdmVudExpc3RlbmVyKCAnbG9hZCcsIHRoaXMgKTtcbiAgdGhpcy5pbWcuYWRkRXZlbnRMaXN0ZW5lciggJ2Vycm9yJywgdGhpcyApO1xuICAvLyBnZXQgc3JjICYgc3Jjc2V0XG4gIGxldCBzcmMgPSB0aGlzLmltZy5nZXRBdHRyaWJ1dGUoIGxhenlBdHRyICkgfHxcbiAgICB0aGlzLmltZy5nZXRBdHRyaWJ1dGUoIGxhenlTcmNBdHRyICk7XG4gIGxldCBzcmNzZXQgPSB0aGlzLmltZy5nZXRBdHRyaWJ1dGUoIGxhenlTcmNzZXRBdHRyICk7XG4gIC8vIHNldCBzcmMgJiBzZXJzZXRcbiAgdGhpcy5pbWcuc3JjID0gc3JjO1xuICBpZiAoIHNyY3NldCApIHRoaXMuaW1nLnNldEF0dHJpYnV0ZSggJ3NyY3NldCcsIHNyY3NldCApO1xuICAvLyByZW1vdmUgYXR0clxuICB0aGlzLmltZy5yZW1vdmVBdHRyaWJ1dGUoIGxhenlBdHRyICk7XG4gIHRoaXMuaW1nLnJlbW92ZUF0dHJpYnV0ZSggbGF6eVNyY0F0dHIgKTtcbiAgdGhpcy5pbWcucmVtb3ZlQXR0cmlidXRlKCBsYXp5U3Jjc2V0QXR0ciApO1xufTtcblxuTGF6eUxvYWRlci5wcm90b3R5cGUub25sb2FkID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuICB0aGlzLmNvbXBsZXRlKCBldmVudCwgJ2ZsaWNraXR5LWxhenlsb2FkZWQnICk7XG59O1xuXG5MYXp5TG9hZGVyLnByb3RvdHlwZS5vbmVycm9yID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuICB0aGlzLmNvbXBsZXRlKCBldmVudCwgJ2ZsaWNraXR5LWxhenllcnJvcicgKTtcbn07XG5cbkxhenlMb2FkZXIucHJvdG90eXBlLmNvbXBsZXRlID0gZnVuY3Rpb24oIGV2ZW50LCBjbGFzc05hbWUgKSB7XG4gIC8vIHVuYmluZCBldmVudHNcbiAgdGhpcy5pbWcucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ2xvYWQnLCB0aGlzICk7XG4gIHRoaXMuaW1nLnJlbW92ZUV2ZW50TGlzdGVuZXIoICdlcnJvcicsIHRoaXMgKTtcbiAgbGV0IG1lZGlhRWxlbSA9IHRoaXMuaW1nLnBhcmVudE5vZGUubWF0Y2hlcygncGljdHVyZScpID8gdGhpcy5pbWcucGFyZW50Tm9kZSA6IHRoaXMuaW1nO1xuICBtZWRpYUVsZW0uY2xhc3NMaXN0LmFkZCggY2xhc3NOYW1lICk7XG5cbiAgdGhpcy5vbkNvbXBsZXRlKCB0aGlzLmltZywgZXZlbnQgKTtcbn07XG5cbi8vIC0tLS0tICAtLS0tLSAvL1xuXG5GbGlja2l0eS5MYXp5TG9hZGVyID0gTGF6eUxvYWRlcjtcblxucmV0dXJuIEZsaWNraXR5O1xuXG59ICkgKTtcbiIsIi8vIHBhZ2UgZG90c1xuKCBmdW5jdGlvbiggd2luZG93LCBmYWN0b3J5ICkge1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cbiAgaWYgKCB0eXBlb2YgbW9kdWxlID09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzICkge1xuICAgIC8vIENvbW1vbkpTXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KFxuICAgICAgICByZXF1aXJlKCcuL2NvcmUnKSxcbiAgICAgICAgcmVxdWlyZSgnZml6enktdWktdXRpbHMnKSxcbiAgICApO1xuICB9IGVsc2Uge1xuICAgIC8vIGJyb3dzZXIgZ2xvYmFsXG4gICAgZmFjdG9yeShcbiAgICAgICAgd2luZG93LkZsaWNraXR5LFxuICAgICAgICB3aW5kb3cuZml6enlVSVV0aWxzLFxuICAgICk7XG4gIH1cblxufSggdHlwZW9mIHdpbmRvdyAhPSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHRoaXMsIGZ1bmN0aW9uIGZhY3RvcnkoIEZsaWNraXR5LCB1dGlscyApIHtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gUGFnZURvdHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuZnVuY3Rpb24gUGFnZURvdHMoKSB7XG4gIC8vIGNyZWF0ZSBob2xkZXIgZWxlbWVudFxuICB0aGlzLmhvbGRlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICB0aGlzLmhvbGRlci5jbGFzc05hbWUgPSAnZmxpY2tpdHktcGFnZS1kb3RzJztcbiAgLy8gY3JlYXRlIGRvdHMsIGFycmF5IG9mIGVsZW1lbnRzXG4gIHRoaXMuZG90cyA9IFtdO1xufVxuXG5QYWdlRG90cy5wcm90b3R5cGUuc2V0RG90cyA9IGZ1bmN0aW9uKCBzbGlkZXNMZW5ndGggKSB7XG4gIC8vIGdldCBkaWZmZXJlbmNlIGJldHdlZW4gbnVtYmVyIG9mIHNsaWRlcyBhbmQgbnVtYmVyIG9mIGRvdHNcbiAgbGV0IGRlbHRhID0gc2xpZGVzTGVuZ3RoIC0gdGhpcy5kb3RzLmxlbmd0aDtcbiAgaWYgKCBkZWx0YSA+IDAgKSB7XG4gICAgdGhpcy5hZGREb3RzKCBkZWx0YSApO1xuICB9IGVsc2UgaWYgKCBkZWx0YSA8IDAgKSB7XG4gICAgdGhpcy5yZW1vdmVEb3RzKCAtZGVsdGEgKTtcbiAgfVxufTtcblxuUGFnZURvdHMucHJvdG90eXBlLmFkZERvdHMgPSBmdW5jdGlvbiggY291bnQgKSB7XG4gIGxldCBuZXdEb3RzID0gbmV3IEFycmF5KCBjb3VudCApLmZpbGwoKVxuICAgIC5tYXAoICggaXRlbSwgaSApID0+IHtcbiAgICAgIGxldCBkb3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdidXR0b24nKTtcbiAgICAgIGRvdC5zZXRBdHRyaWJ1dGUoICd0eXBlJywgJ2J1dHRvbicgKTtcbiAgICAgIGxldCBudW0gPSBpICsgMSArIHRoaXMuZG90cy5sZW5ndGg7XG4gICAgICBkb3QuY2xhc3NOYW1lID0gJ2ZsaWNraXR5LXBhZ2UtZG90JztcbiAgICAgIGRvdC50ZXh0Q29udGVudCA9IGBWaWV3IHNsaWRlICR7bnVtfWA7XG4gICAgICByZXR1cm4gZG90O1xuICAgIH0gKTtcblxuICB0aGlzLmhvbGRlci5hcHBlbmQoIC4uLm5ld0RvdHMgKTtcbiAgdGhpcy5kb3RzID0gdGhpcy5kb3RzLmNvbmNhdCggbmV3RG90cyApO1xufTtcblxuUGFnZURvdHMucHJvdG90eXBlLnJlbW92ZURvdHMgPSBmdW5jdGlvbiggY291bnQgKSB7XG4gIC8vIHJlbW92ZSBmcm9tIHRoaXMuZG90cyBjb2xsZWN0aW9uXG4gIGxldCByZW1vdmVEb3RzID0gdGhpcy5kb3RzLnNwbGljZSggdGhpcy5kb3RzLmxlbmd0aCAtIGNvdW50LCBjb3VudCApO1xuICAvLyByZW1vdmUgZnJvbSBET01cbiAgcmVtb3ZlRG90cy5mb3JFYWNoKCAoIGRvdCApID0+IGRvdC5yZW1vdmUoKSApO1xufTtcblxuUGFnZURvdHMucHJvdG90eXBlLnVwZGF0ZVNlbGVjdGVkID0gZnVuY3Rpb24oIGluZGV4ICkge1xuICAvLyByZW1vdmUgc2VsZWN0ZWQgY2xhc3Mgb24gcHJldmlvdXNcbiAgaWYgKCB0aGlzLnNlbGVjdGVkRG90ICkge1xuICAgIHRoaXMuc2VsZWN0ZWREb3QuY2xhc3NMaXN0LnJlbW92ZSgnaXMtc2VsZWN0ZWQnKTtcbiAgICB0aGlzLnNlbGVjdGVkRG90LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1jdXJyZW50Jyk7XG4gIH1cbiAgLy8gZG9uJ3QgcHJvY2VlZCBpZiBubyBkb3RzXG4gIGlmICggIXRoaXMuZG90cy5sZW5ndGggKSByZXR1cm47XG5cbiAgdGhpcy5zZWxlY3RlZERvdCA9IHRoaXMuZG90c1sgaW5kZXggXTtcbiAgdGhpcy5zZWxlY3RlZERvdC5jbGFzc0xpc3QuYWRkKCdpcy1zZWxlY3RlZCcpO1xuICB0aGlzLnNlbGVjdGVkRG90LnNldEF0dHJpYnV0ZSggJ2FyaWEtY3VycmVudCcsICdzdGVwJyApO1xufTtcblxuRmxpY2tpdHkuUGFnZURvdHMgPSBQYWdlRG90cztcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gRmxpY2tpdHkgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuT2JqZWN0LmFzc2lnbiggRmxpY2tpdHkuZGVmYXVsdHMsIHtcbiAgcGFnZURvdHM6IHRydWUsXG59ICk7XG5cbkZsaWNraXR5LmNyZWF0ZS5wYWdlRG90cyA9IGZ1bmN0aW9uKCkge1xuICBpZiAoICF0aGlzLm9wdGlvbnMucGFnZURvdHMgKSByZXR1cm47XG5cbiAgdGhpcy5wYWdlRG90cyA9IG5ldyBQYWdlRG90cygpO1xuICB0aGlzLmhhbmRsZVBhZ2VEb3RzQ2xpY2sgPSB0aGlzLm9uUGFnZURvdHNDbGljay5iaW5kKCB0aGlzICk7XG4gIC8vIGV2ZW50c1xuICB0aGlzLm9uKCAnYWN0aXZhdGUnLCB0aGlzLmFjdGl2YXRlUGFnZURvdHMgKTtcbiAgdGhpcy5vbiggJ3NlbGVjdCcsIHRoaXMudXBkYXRlU2VsZWN0ZWRQYWdlRG90cyApO1xuICB0aGlzLm9uKCAnY2VsbENoYW5nZScsIHRoaXMudXBkYXRlUGFnZURvdHMgKTtcbiAgdGhpcy5vbiggJ3Jlc2l6ZScsIHRoaXMudXBkYXRlUGFnZURvdHMgKTtcbiAgdGhpcy5vbiggJ2RlYWN0aXZhdGUnLCB0aGlzLmRlYWN0aXZhdGVQYWdlRG90cyApO1xufTtcblxubGV0IHByb3RvID0gRmxpY2tpdHkucHJvdG90eXBlO1xuXG5wcm90by5hY3RpdmF0ZVBhZ2VEb3RzID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMucGFnZURvdHMuc2V0RG90cyggdGhpcy5zbGlkZXMubGVuZ3RoICk7XG4gIHRoaXMuZm9jdXNhYmxlRWxlbXMucHVzaCggLi4udGhpcy5wYWdlRG90cy5kb3RzICk7XG4gIHRoaXMucGFnZURvdHMuaG9sZGVyLmFkZEV2ZW50TGlzdGVuZXIoICdjbGljaycsIHRoaXMuaGFuZGxlUGFnZURvdHNDbGljayApO1xuICB0aGlzLmVsZW1lbnQuYXBwZW5kKCB0aGlzLnBhZ2VEb3RzLmhvbGRlciApO1xufTtcblxucHJvdG8ub25QYWdlRG90c0NsaWNrID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuICBsZXQgaW5kZXggPSB0aGlzLnBhZ2VEb3RzLmRvdHMuaW5kZXhPZiggZXZlbnQudGFyZ2V0ICk7XG4gIGlmICggaW5kZXggPT09IC0xICkgcmV0dXJuOyAvLyBvbmx5IGRvdCBjbGlja3NcblxuICB0aGlzLnVpQ2hhbmdlKCk7XG4gIHRoaXMuc2VsZWN0KCBpbmRleCApO1xufTtcblxucHJvdG8udXBkYXRlU2VsZWN0ZWRQYWdlRG90cyA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnBhZ2VEb3RzLnVwZGF0ZVNlbGVjdGVkKCB0aGlzLnNlbGVjdGVkSW5kZXggKTtcbn07XG5cbnByb3RvLnVwZGF0ZVBhZ2VEb3RzID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMucGFnZURvdHMuZG90cy5mb3JFYWNoKCAoIGRvdCApID0+IHtcbiAgICB1dGlscy5yZW1vdmVGcm9tKCB0aGlzLmZvY3VzYWJsZUVsZW1zLCBkb3QgKTtcbiAgfSApO1xuICB0aGlzLnBhZ2VEb3RzLnNldERvdHMoIHRoaXMuc2xpZGVzLmxlbmd0aCApO1xuICB0aGlzLmZvY3VzYWJsZUVsZW1zLnB1c2goIC4uLnRoaXMucGFnZURvdHMuZG90cyApO1xufTtcblxucHJvdG8uZGVhY3RpdmF0ZVBhZ2VEb3RzID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMucGFnZURvdHMuaG9sZGVyLnJlbW92ZSgpO1xuICB0aGlzLnBhZ2VEb3RzLmhvbGRlci5yZW1vdmVFdmVudExpc3RlbmVyKCAnY2xpY2snLCB0aGlzLmhhbmRsZVBhZ2VEb3RzQ2xpY2sgKTtcbn07XG5cbi8vIC0tLS0tICAtLS0tLSAvL1xuXG5GbGlja2l0eS5QYWdlRG90cyA9IFBhZ2VEb3RzO1xuXG5yZXR1cm4gRmxpY2tpdHk7XG5cbn0gKSApO1xuIiwiLy8gcGxheWVyICYgYXV0b1BsYXlcbiggZnVuY3Rpb24oIHdpbmRvdywgZmFjdG9yeSApIHtcbiAgLy8gdW5pdmVyc2FsIG1vZHVsZSBkZWZpbml0aW9uXG4gIGlmICggdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyApIHtcbiAgICAvLyBDb21tb25KU1xuICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSggcmVxdWlyZSgnLi9jb3JlJykgKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBicm93c2VyIGdsb2JhbFxuICAgIGZhY3RvcnkoIHdpbmRvdy5GbGlja2l0eSApO1xuICB9XG5cbn0oIHR5cGVvZiB3aW5kb3cgIT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzLCBmdW5jdGlvbiBmYWN0b3J5KCBGbGlja2l0eSApIHtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gUGxheWVyIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbmZ1bmN0aW9uIFBsYXllciggYXV0b1BsYXksIG9uVGljayApIHtcbiAgdGhpcy5hdXRvUGxheSA9IGF1dG9QbGF5O1xuICB0aGlzLm9uVGljayA9IG9uVGljaztcbiAgdGhpcy5zdGF0ZSA9ICdzdG9wcGVkJztcbiAgLy8gdmlzaWJpbGl0eSBjaGFuZ2UgZXZlbnQgaGFuZGxlclxuICB0aGlzLm9uVmlzaWJpbGl0eUNoYW5nZSA9IHRoaXMudmlzaWJpbGl0eUNoYW5nZS5iaW5kKCB0aGlzICk7XG4gIHRoaXMub25WaXNpYmlsaXR5UGxheSA9IHRoaXMudmlzaWJpbGl0eVBsYXkuYmluZCggdGhpcyApO1xufVxuXG4vLyBzdGFydCBwbGF5XG5QbGF5ZXIucHJvdG90eXBlLnBsYXkgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCB0aGlzLnN0YXRlID09PSAncGxheWluZycgKSByZXR1cm47XG5cbiAgLy8gZG8gbm90IHBsYXkgaWYgcGFnZSBpcyBoaWRkZW4sIHN0YXJ0IHBsYXlpbmcgd2hlbiBwYWdlIGlzIHZpc2libGVcbiAgbGV0IGlzUGFnZUhpZGRlbiA9IGRvY3VtZW50LmhpZGRlbjtcbiAgaWYgKCBpc1BhZ2VIaWRkZW4gKSB7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lciggJ3Zpc2liaWxpdHljaGFuZ2UnLCB0aGlzLm9uVmlzaWJpbGl0eVBsYXkgKTtcbiAgICByZXR1cm47XG4gIH1cblxuICB0aGlzLnN0YXRlID0gJ3BsYXlpbmcnO1xuICAvLyBsaXN0ZW4gdG8gdmlzaWJpbGl0eSBjaGFuZ2VcbiAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lciggJ3Zpc2liaWxpdHljaGFuZ2UnLCB0aGlzLm9uVmlzaWJpbGl0eUNoYW5nZSApO1xuICAvLyBzdGFydCB0aWNraW5nXG4gIHRoaXMudGljaygpO1xufTtcblxuUGxheWVyLnByb3RvdHlwZS50aWNrID0gZnVuY3Rpb24oKSB7XG4gIC8vIGRvIG5vdCB0aWNrIGlmIG5vdCBwbGF5aW5nXG4gIGlmICggdGhpcy5zdGF0ZSAhPT0gJ3BsYXlpbmcnICkgcmV0dXJuO1xuXG4gIC8vIGRlZmF1bHQgdG8gMyBzZWNvbmRzXG4gIGxldCB0aW1lID0gdHlwZW9mIHRoaXMuYXV0b1BsYXkgPT0gJ251bWJlcicgPyB0aGlzLmF1dG9QbGF5IDogMzAwMDtcbiAgLy8gSEFDSzogcmVzZXQgdGlja3MgaWYgc3RvcHBlZCBhbmQgc3RhcnRlZCB3aXRoaW4gaW50ZXJ2YWxcbiAgdGhpcy5jbGVhcigpO1xuICB0aGlzLnRpbWVvdXQgPSBzZXRUaW1lb3V0KCAoKSA9PiB7XG4gICAgdGhpcy5vblRpY2soKTtcbiAgICB0aGlzLnRpY2soKTtcbiAgfSwgdGltZSApO1xufTtcblxuUGxheWVyLnByb3RvdHlwZS5zdG9wID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuc3RhdGUgPSAnc3RvcHBlZCc7XG4gIHRoaXMuY2xlYXIoKTtcbiAgLy8gcmVtb3ZlIHZpc2liaWxpdHkgY2hhbmdlIGV2ZW50XG4gIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoICd2aXNpYmlsaXR5Y2hhbmdlJywgdGhpcy5vblZpc2liaWxpdHlDaGFuZ2UgKTtcbn07XG5cblBsYXllci5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbigpIHtcbiAgY2xlYXJUaW1lb3V0KCB0aGlzLnRpbWVvdXQgKTtcbn07XG5cblBsYXllci5wcm90b3R5cGUucGF1c2UgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCB0aGlzLnN0YXRlID09PSAncGxheWluZycgKSB7XG4gICAgdGhpcy5zdGF0ZSA9ICdwYXVzZWQnO1xuICAgIHRoaXMuY2xlYXIoKTtcbiAgfVxufTtcblxuUGxheWVyLnByb3RvdHlwZS51bnBhdXNlID0gZnVuY3Rpb24oKSB7XG4gIC8vIHJlLXN0YXJ0IHBsYXkgaWYgcGF1c2VkXG4gIGlmICggdGhpcy5zdGF0ZSA9PT0gJ3BhdXNlZCcgKSB0aGlzLnBsYXkoKTtcbn07XG5cbi8vIHBhdXNlIGlmIHBhZ2UgdmlzaWJpbGl0eSBpcyBoaWRkZW4sIHVucGF1c2UgaWYgdmlzaWJsZVxuUGxheWVyLnByb3RvdHlwZS52aXNpYmlsaXR5Q2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gIGxldCBpc1BhZ2VIaWRkZW4gPSBkb2N1bWVudC5oaWRkZW47XG4gIHRoaXNbIGlzUGFnZUhpZGRlbiA/ICdwYXVzZScgOiAndW5wYXVzZScgXSgpO1xufTtcblxuUGxheWVyLnByb3RvdHlwZS52aXNpYmlsaXR5UGxheSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnBsYXkoKTtcbiAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ3Zpc2liaWxpdHljaGFuZ2UnLCB0aGlzLm9uVmlzaWJpbGl0eVBsYXkgKTtcbn07XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIEZsaWNraXR5IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbk9iamVjdC5hc3NpZ24oIEZsaWNraXR5LmRlZmF1bHRzLCB7XG4gIHBhdXNlQXV0b1BsYXlPbkhvdmVyOiB0cnVlLFxufSApO1xuXG5GbGlja2l0eS5jcmVhdGUucGxheWVyID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMucGxheWVyID0gbmV3IFBsYXllciggdGhpcy5vcHRpb25zLmF1dG9QbGF5LCAoKSA9PiB7XG4gICAgdGhpcy5uZXh0KCB0cnVlICk7XG4gIH0gKTtcblxuICB0aGlzLm9uKCAnYWN0aXZhdGUnLCB0aGlzLmFjdGl2YXRlUGxheWVyICk7XG4gIHRoaXMub24oICd1aUNoYW5nZScsIHRoaXMuc3RvcFBsYXllciApO1xuICB0aGlzLm9uKCAncG9pbnRlckRvd24nLCB0aGlzLnN0b3BQbGF5ZXIgKTtcbiAgdGhpcy5vbiggJ2RlYWN0aXZhdGUnLCB0aGlzLmRlYWN0aXZhdGVQbGF5ZXIgKTtcbn07XG5cbmxldCBwcm90byA9IEZsaWNraXR5LnByb3RvdHlwZTtcblxucHJvdG8uYWN0aXZhdGVQbGF5ZXIgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCAhdGhpcy5vcHRpb25zLmF1dG9QbGF5ICkgcmV0dXJuO1xuXG4gIHRoaXMucGxheWVyLnBsYXkoKTtcbiAgdGhpcy5lbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoICdtb3VzZWVudGVyJywgdGhpcyApO1xufTtcblxuLy8gUGxheWVyIEFQSSwgZG9uJ3QgaGF0ZSB0aGUgLi4uIHRoYW5rcyBJIGtub3cgd2hlcmUgdGhlIGRvb3IgaXNcblxucHJvdG8ucGxheVBsYXllciA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnBsYXllci5wbGF5KCk7XG59O1xuXG5wcm90by5zdG9wUGxheWVyID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMucGxheWVyLnN0b3AoKTtcbn07XG5cbnByb3RvLnBhdXNlUGxheWVyID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMucGxheWVyLnBhdXNlKCk7XG59O1xuXG5wcm90by51bnBhdXNlUGxheWVyID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMucGxheWVyLnVucGF1c2UoKTtcbn07XG5cbnByb3RvLmRlYWN0aXZhdGVQbGF5ZXIgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5wbGF5ZXIuc3RvcCgpO1xuICB0aGlzLmVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ21vdXNlZW50ZXInLCB0aGlzICk7XG59O1xuXG4vLyAtLS0tLSBtb3VzZWVudGVyL2xlYXZlIC0tLS0tIC8vXG5cbi8vIHBhdXNlIGF1dG8tcGxheSBvbiBob3ZlclxucHJvdG8ub25tb3VzZWVudGVyID0gZnVuY3Rpb24oKSB7XG4gIGlmICggIXRoaXMub3B0aW9ucy5wYXVzZUF1dG9QbGF5T25Ib3ZlciApIHJldHVybjtcblxuICB0aGlzLnBsYXllci5wYXVzZSgpO1xuICB0aGlzLmVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lciggJ21vdXNlbGVhdmUnLCB0aGlzICk7XG59O1xuXG4vLyByZXN1bWUgYXV0by1wbGF5IG9uIGhvdmVyIG9mZlxucHJvdG8ub25tb3VzZWxlYXZlID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMucGxheWVyLnVucGF1c2UoKTtcbiAgdGhpcy5lbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoICdtb3VzZWxlYXZlJywgdGhpcyApO1xufTtcblxuLy8gLS0tLS0gIC0tLS0tIC8vXG5cbkZsaWNraXR5LlBsYXllciA9IFBsYXllcjtcblxucmV0dXJuIEZsaWNraXR5O1xuXG59ICkgKTtcbiIsIi8vIHByZXYvbmV4dCBidXR0b25zXG4oIGZ1bmN0aW9uKCB3aW5kb3csIGZhY3RvcnkgKSB7XG4gIC8vIHVuaXZlcnNhbCBtb2R1bGUgZGVmaW5pdGlvblxuICBpZiAoIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG4gICAgLy8gQ29tbW9uSlNcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoIHJlcXVpcmUoJy4vY29yZScpICk7XG4gIH0gZWxzZSB7XG4gICAgLy8gYnJvd3NlciBnbG9iYWxcbiAgICBmYWN0b3J5KCB3aW5kb3cuRmxpY2tpdHkgKTtcbiAgfVxuXG59KCB0eXBlb2Ygd2luZG93ICE9ICd1bmRlZmluZWQnID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24gZmFjdG9yeSggRmxpY2tpdHkgKSB7XG5cbmNvbnN0IHN2Z1VSSSA9ICdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Zyc7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIFByZXZOZXh0QnV0dG9uIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbmZ1bmN0aW9uIFByZXZOZXh0QnV0dG9uKCBpbmNyZW1lbnQsIGRpcmVjdGlvbiwgYXJyb3dTaGFwZSApIHtcbiAgdGhpcy5pbmNyZW1lbnQgPSBpbmNyZW1lbnQ7XG4gIHRoaXMuZGlyZWN0aW9uID0gZGlyZWN0aW9uO1xuICB0aGlzLmlzUHJldmlvdXMgPSBpbmNyZW1lbnQgPT09ICdwcmV2aW91cyc7XG4gIHRoaXMuaXNMZWZ0ID0gZGlyZWN0aW9uID09PSAnbGVmdCc7XG4gIHRoaXMuX2NyZWF0ZSggYXJyb3dTaGFwZSApO1xufVxuXG5QcmV2TmV4dEJ1dHRvbi5wcm90b3R5cGUuX2NyZWF0ZSA9IGZ1bmN0aW9uKCBhcnJvd1NoYXBlICkge1xuICAvLyBwcm9wZXJ0aWVzXG4gIGxldCBlbGVtZW50ID0gdGhpcy5lbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyk7XG4gIGVsZW1lbnQuY2xhc3NOYW1lID0gYGZsaWNraXR5LWJ1dHRvbiBmbGlja2l0eS1wcmV2LW5leHQtYnV0dG9uICR7dGhpcy5pbmNyZW1lbnR9YDtcbiAgbGV0IGxhYmVsID0gdGhpcy5pc1ByZXZpb3VzID8gJ1ByZXZpb3VzJyA6ICdOZXh0JztcbiAgLy8gcHJldmVudCBidXR0b24gZnJvbSBzdWJtaXR0aW5nIGZvcm0gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzEwODM2MDc2LzE4MjE4M1xuICBlbGVtZW50LnNldEF0dHJpYnV0ZSggJ3R5cGUnLCAnYnV0dG9uJyApO1xuICBlbGVtZW50LnNldEF0dHJpYnV0ZSggJ2FyaWEtbGFiZWwnLCBsYWJlbCApO1xuICAvLyBpbml0IGFzIGRpc2FibGVkXG4gIHRoaXMuZGlzYWJsZSgpO1xuICAvLyBjcmVhdGUgYXJyb3dcbiAgbGV0IHN2ZyA9IHRoaXMuY3JlYXRlU1ZHKCBsYWJlbCwgYXJyb3dTaGFwZSApO1xuICBlbGVtZW50LmFwcGVuZCggc3ZnICk7XG59O1xuXG5QcmV2TmV4dEJ1dHRvbi5wcm90b3R5cGUuY3JlYXRlU1ZHID0gZnVuY3Rpb24oIGxhYmVsLCBhcnJvd1NoYXBlICkge1xuICBsZXQgc3ZnID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCBzdmdVUkksICdzdmcnICk7XG4gIHN2Zy5zZXRBdHRyaWJ1dGUoICdjbGFzcycsICdmbGlja2l0eS1idXR0b24taWNvbicgKTtcbiAgc3ZnLnNldEF0dHJpYnV0ZSggJ3ZpZXdCb3gnLCAnMCAwIDEwMCAxMDAnICk7XG4gIC8vIGFkZCB0aXRsZSAjMTE4OVxuICBsZXQgdGl0bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoIHN2Z1VSSSwgJ3RpdGxlJyApO1xuICB0aXRsZS5hcHBlbmQoIGxhYmVsICk7XG4gIC8vIGFkZCBwYXRoXG4gIGxldCBwYXRoID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCBzdmdVUkksICdwYXRoJyApO1xuICBsZXQgcGF0aE1vdmVtZW50cyA9IGdldEFycm93TW92ZW1lbnRzKCBhcnJvd1NoYXBlICk7XG4gIHBhdGguc2V0QXR0cmlidXRlKCAnZCcsIHBhdGhNb3ZlbWVudHMgKTtcbiAgcGF0aC5zZXRBdHRyaWJ1dGUoICdjbGFzcycsICdhcnJvdycgKTtcbiAgLy8gcm90YXRlIGFycm93XG4gIGlmICggIXRoaXMuaXNMZWZ0ICkge1xuICAgIHBhdGguc2V0QXR0cmlidXRlKCAndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgxMDAsIDEwMCkgcm90YXRlKDE4MCknICk7XG4gIH1cbiAgc3ZnLmFwcGVuZCggdGl0bGUsIHBhdGggKTtcbiAgcmV0dXJuIHN2Zztcbn07XG5cbi8vIGdldCBTVkcgcGF0aCBtb3ZtZW1lbnRcbmZ1bmN0aW9uIGdldEFycm93TW92ZW1lbnRzKCBzaGFwZSApIHtcbiAgLy8gdXNlIHNoYXBlIGFzIG1vdmVtZW50IGlmIHN0cmluZ1xuICBpZiAoIHR5cGVvZiBzaGFwZSA9PSAnc3RyaW5nJyApIHJldHVybiBzaGFwZTtcblxuICBsZXQgeyB4MCwgeDEsIHgyLCB4MywgeTEsIHkyIH0gPSBzaGFwZTtcblxuICAvLyBjcmVhdGUgbW92ZW1lbnQgc3RyaW5nXG4gIHJldHVybiBgTSAke3gwfSwgNTBcbiAgICBMICR7eDF9LCAke3kxICsgNTB9XG4gICAgTCAke3gyfSwgJHt5MiArIDUwfVxuICAgIEwgJHt4M30sIDUwXG4gICAgTCAke3gyfSwgJHs1MCAtIHkyfVxuICAgIEwgJHt4MX0sICR7NTAgLSB5MX1cbiAgICBaYDtcbn1cblxuLy8gLS0tLS0gIC0tLS0tIC8vXG5cblByZXZOZXh0QnV0dG9uLnByb3RvdHlwZS5lbmFibGUgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5lbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbn07XG5cblByZXZOZXh0QnV0dG9uLnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuZWxlbWVudC5zZXRBdHRyaWJ1dGUoICdkaXNhYmxlZCcsIHRydWUgKTtcbn07XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIEZsaWNraXR5IHByb3RvdHlwZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG5PYmplY3QuYXNzaWduKCBGbGlja2l0eS5kZWZhdWx0cywge1xuICBwcmV2TmV4dEJ1dHRvbnM6IHRydWUsXG4gIGFycm93U2hhcGU6IHtcbiAgICB4MDogMTAsXG4gICAgeDE6IDYwLCB5MTogNTAsXG4gICAgeDI6IDcwLCB5MjogNDAsXG4gICAgeDM6IDMwLFxuICB9LFxufSApO1xuXG5GbGlja2l0eS5jcmVhdGUucHJldk5leHRCdXR0b25zID0gZnVuY3Rpb24oKSB7XG4gIGlmICggIXRoaXMub3B0aW9ucy5wcmV2TmV4dEJ1dHRvbnMgKSByZXR1cm47XG5cbiAgbGV0IHsgcmlnaHRUb0xlZnQsIGFycm93U2hhcGUgfSA9IHRoaXMub3B0aW9ucztcbiAgbGV0IHByZXZEaXJlY3Rpb24gPSByaWdodFRvTGVmdCA/ICdyaWdodCcgOiAnbGVmdCc7XG4gIGxldCBuZXh0RGlyZWN0aW9uID0gcmlnaHRUb0xlZnQgPyAnbGVmdCcgOiAncmlnaHQnO1xuICB0aGlzLnByZXZCdXR0b24gPSBuZXcgUHJldk5leHRCdXR0b24oICdwcmV2aW91cycsIHByZXZEaXJlY3Rpb24sIGFycm93U2hhcGUgKTtcbiAgdGhpcy5uZXh0QnV0dG9uID0gbmV3IFByZXZOZXh0QnV0dG9uKCAnbmV4dCcsIG5leHREaXJlY3Rpb24sIGFycm93U2hhcGUgKTtcbiAgdGhpcy5mb2N1c2FibGVFbGVtcy5wdXNoKCB0aGlzLnByZXZCdXR0b24uZWxlbWVudCApO1xuICB0aGlzLmZvY3VzYWJsZUVsZW1zLnB1c2goIHRoaXMubmV4dEJ1dHRvbi5lbGVtZW50ICk7XG5cbiAgdGhpcy5oYW5kbGVQcmV2QnV0dG9uQ2xpY2sgPSAoKSA9PiB7XG4gICAgdGhpcy51aUNoYW5nZSgpO1xuICAgIHRoaXMucHJldmlvdXMoKTtcbiAgfTtcblxuICB0aGlzLmhhbmRsZU5leHRCdXR0b25DbGljayA9ICgpID0+IHtcbiAgICB0aGlzLnVpQ2hhbmdlKCk7XG4gICAgdGhpcy5uZXh0KCk7XG4gIH07XG5cbiAgdGhpcy5vbiggJ2FjdGl2YXRlJywgdGhpcy5hY3RpdmF0ZVByZXZOZXh0QnV0dG9ucyApO1xuICB0aGlzLm9uKCAnc2VsZWN0JywgdGhpcy51cGRhdGVQcmV2TmV4dEJ1dHRvbnMgKTtcbn07XG5cbmxldCBwcm90byA9IEZsaWNraXR5LnByb3RvdHlwZTtcblxucHJvdG8udXBkYXRlUHJldk5leHRCdXR0b25zID0gZnVuY3Rpb24oKSB7XG4gIGxldCBsYXN0SW5kZXggPSB0aGlzLnNsaWRlcy5sZW5ndGggPyB0aGlzLnNsaWRlcy5sZW5ndGggLSAxIDogMDtcbiAgdGhpcy51cGRhdGVQcmV2TmV4dEJ1dHRvbiggdGhpcy5wcmV2QnV0dG9uLCAwICk7XG4gIHRoaXMudXBkYXRlUHJldk5leHRCdXR0b24oIHRoaXMubmV4dEJ1dHRvbiwgbGFzdEluZGV4ICk7XG59O1xuXG5wcm90by51cGRhdGVQcmV2TmV4dEJ1dHRvbiA9IGZ1bmN0aW9uKCBidXR0b24sIGRpc2FibGVkSW5kZXggKSB7XG4gIC8vIGVuYWJsZSBpcyB3cmFwQXJvdW5kIGFuZCBhdCBsZWFzdCAyIHNsaWRlc1xuICBpZiAoIHRoaXMuaXNXcmFwcGluZyAmJiB0aGlzLnNsaWRlcy5sZW5ndGggPiAxICkge1xuICAgIGJ1dHRvbi5lbmFibGUoKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBsZXQgaXNFbmFibGVkID0gdGhpcy5zZWxlY3RlZEluZGV4ICE9PSBkaXNhYmxlZEluZGV4O1xuICBidXR0b25bIGlzRW5hYmxlZCA/ICdlbmFibGUnIDogJ2Rpc2FibGUnIF0oKTtcbiAgLy8gaWYgZGlzYWJsaW5nIGJ1dHRvbiB0aGF0IGlzIGZvY3VzZWQsXG4gIC8vIHNoaWZ0IGZvY3VzIHRvIGVsZW1lbnQgdG8gbWFpbnRhaW4ga2V5Ym9hcmQgYWNjZXNzaWJpbGl0eVxuICBsZXQgaXNEaXNhYmxlZEZvY3VzZWQgPSAhaXNFbmFibGVkICYmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGJ1dHRvbi5lbGVtZW50O1xuICBpZiAoIGlzRGlzYWJsZWRGb2N1c2VkICkgdGhpcy5mb2N1cygpO1xufTtcblxucHJvdG8uYWN0aXZhdGVQcmV2TmV4dEJ1dHRvbnMgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5wcmV2QnV0dG9uLmVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lciggJ2NsaWNrJywgdGhpcy5oYW5kbGVQcmV2QnV0dG9uQ2xpY2sgKTtcbiAgdGhpcy5uZXh0QnV0dG9uLmVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lciggJ2NsaWNrJywgdGhpcy5oYW5kbGVOZXh0QnV0dG9uQ2xpY2sgKTtcbiAgdGhpcy5lbGVtZW50LmFwcGVuZCggdGhpcy5wcmV2QnV0dG9uLmVsZW1lbnQsIHRoaXMubmV4dEJ1dHRvbi5lbGVtZW50ICk7XG4gIHRoaXMub24oICdkZWFjdGl2YXRlJywgdGhpcy5kZWFjdGl2YXRlUHJldk5leHRCdXR0b25zICk7XG59O1xuXG5wcm90by5kZWFjdGl2YXRlUHJldk5leHRCdXR0b25zID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMucHJldkJ1dHRvbi5lbGVtZW50LnJlbW92ZSgpO1xuICB0aGlzLm5leHRCdXR0b24uZWxlbWVudC5yZW1vdmUoKTtcbiAgdGhpcy5wcmV2QnV0dG9uLmVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ2NsaWNrJywgdGhpcy5oYW5kbGVQcmV2QnV0dG9uQ2xpY2sgKTtcbiAgdGhpcy5uZXh0QnV0dG9uLmVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ2NsaWNrJywgdGhpcy5oYW5kbGVOZXh0QnV0dG9uQ2xpY2sgKTtcbiAgdGhpcy5vZmYoICdkZWFjdGl2YXRlJywgdGhpcy5kZWFjdGl2YXRlUHJldk5leHRCdXR0b25zICk7XG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuRmxpY2tpdHkuUHJldk5leHRCdXR0b24gPSBQcmV2TmV4dEJ1dHRvbjtcblxucmV0dXJuIEZsaWNraXR5O1xuXG59ICkgKTtcbiIsIi8vIHNsaWRlXG4oIGZ1bmN0aW9uKCB3aW5kb3csIGZhY3RvcnkgKSB7XG4gIC8vIHVuaXZlcnNhbCBtb2R1bGUgZGVmaW5pdGlvblxuICBpZiAoIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG4gICAgLy8gQ29tbW9uSlNcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBicm93c2VyIGdsb2JhbFxuICAgIHdpbmRvdy5GbGlja2l0eSA9IHdpbmRvdy5GbGlja2l0eSB8fCB7fTtcbiAgICB3aW5kb3cuRmxpY2tpdHkuU2xpZGUgPSBmYWN0b3J5KCk7XG4gIH1cblxufSggdHlwZW9mIHdpbmRvdyAhPSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHRoaXMsIGZ1bmN0aW9uIGZhY3RvcnkoKSB7XG5cbmZ1bmN0aW9uIFNsaWRlKCBiZWdpbk1hcmdpbiwgZW5kTWFyZ2luLCBjZWxsQWxpZ24gKSB7XG4gIHRoaXMuYmVnaW5NYXJnaW4gPSBiZWdpbk1hcmdpbjtcbiAgdGhpcy5lbmRNYXJnaW4gPSBlbmRNYXJnaW47XG4gIHRoaXMuY2VsbEFsaWduID0gY2VsbEFsaWduO1xuICB0aGlzLmNlbGxzID0gW107XG4gIHRoaXMub3V0ZXJXaWR0aCA9IDA7XG4gIHRoaXMuaGVpZ2h0ID0gMDtcbn1cblxubGV0IHByb3RvID0gU2xpZGUucHJvdG90eXBlO1xuXG5wcm90by5hZGRDZWxsID0gZnVuY3Rpb24oIGNlbGwgKSB7XG4gIHRoaXMuY2VsbHMucHVzaCggY2VsbCApO1xuICB0aGlzLm91dGVyV2lkdGggKz0gY2VsbC5zaXplLm91dGVyV2lkdGg7XG4gIHRoaXMuaGVpZ2h0ID0gTWF0aC5tYXgoIGNlbGwuc2l6ZS5vdXRlckhlaWdodCwgdGhpcy5oZWlnaHQgKTtcbiAgLy8gZmlyc3QgY2VsbCBzdHVmZlxuICBpZiAoIHRoaXMuY2VsbHMubGVuZ3RoID09PSAxICkge1xuICAgIHRoaXMueCA9IGNlbGwueDsgLy8geCBjb21lcyBmcm9tIGZpcnN0IGNlbGxcbiAgICB0aGlzLmZpcnN0TWFyZ2luID0gY2VsbC5zaXplWyB0aGlzLmJlZ2luTWFyZ2luIF07XG4gIH1cbn07XG5cbnByb3RvLnVwZGF0ZVRhcmdldCA9IGZ1bmN0aW9uKCkge1xuICBsZXQgbGFzdENlbGwgPSB0aGlzLmdldExhc3RDZWxsKCk7XG4gIGxldCBsYXN0TWFyZ2luID0gbGFzdENlbGwgPyBsYXN0Q2VsbC5zaXplWyB0aGlzLmVuZE1hcmdpbiBdIDogMDtcbiAgbGV0IHNsaWRlV2lkdGggPSB0aGlzLm91dGVyV2lkdGggLSAoIHRoaXMuZmlyc3RNYXJnaW4gKyBsYXN0TWFyZ2luICk7XG4gIHRoaXMudGFyZ2V0ID0gdGhpcy54ICsgdGhpcy5maXJzdE1hcmdpbiArIHNsaWRlV2lkdGggKiB0aGlzLmNlbGxBbGlnbjtcbn07XG5cbnByb3RvLmdldExhc3RDZWxsID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLmNlbGxzWyB0aGlzLmNlbGxzLmxlbmd0aCAtIDEgXTtcbn07XG5cbnByb3RvLnNlbGVjdCA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmNlbGxzLmZvckVhY2goICggY2VsbCApID0+IGNlbGwuc2VsZWN0KCkgKTtcbn07XG5cbnByb3RvLnVuc2VsZWN0ID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuY2VsbHMuZm9yRWFjaCggKCBjZWxsICkgPT4gY2VsbC51bnNlbGVjdCgpICk7XG59O1xuXG5wcm90by5nZXRDZWxsRWxlbWVudHMgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuY2VsbHMubWFwKCAoIGNlbGwgKSA9PiBjZWxsLmVsZW1lbnQgKTtcbn07XG5cbnJldHVybiBTbGlkZTtcblxufSApICk7XG4iLCIvKiFcbiAqIEluZmluaXRlIFNjcm9sbCB2Mi4wLjRcbiAqIG1lYXN1cmUgc2l6ZSBvZiBlbGVtZW50c1xuICogTUlUIGxpY2Vuc2VcbiAqL1xuXG4oIGZ1bmN0aW9uKCB3aW5kb3csIGZhY3RvcnkgKSB7XG4gIGlmICggdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyApIHtcbiAgICAvLyBDb21tb25KU1xuICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpO1xuICB9IGVsc2Uge1xuICAgIC8vIGJyb3dzZXIgZ2xvYmFsXG4gICAgd2luZG93LmdldFNpemUgPSBmYWN0b3J5KCk7XG4gIH1cblxufSApKCB3aW5kb3csIGZ1bmN0aW9uIGZhY3RvcnkoKSB7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGhlbHBlcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuLy8gZ2V0IGEgbnVtYmVyIGZyb20gYSBzdHJpbmcsIG5vdCBhIHBlcmNlbnRhZ2VcbmZ1bmN0aW9uIGdldFN0eWxlU2l6ZSggdmFsdWUgKSB7XG4gIGxldCBudW0gPSBwYXJzZUZsb2F0KCB2YWx1ZSApO1xuICAvLyBub3QgYSBwZXJjZW50IGxpa2UgJzEwMCUnLCBhbmQgYSBudW1iZXJcbiAgbGV0IGlzVmFsaWQgPSB2YWx1ZS5pbmRleE9mKCclJykgPT0gLTEgJiYgIWlzTmFOKCBudW0gKTtcbiAgcmV0dXJuIGlzVmFsaWQgJiYgbnVtO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBtZWFzdXJlbWVudHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxubGV0IG1lYXN1cmVtZW50cyA9IFtcbiAgJ3BhZGRpbmdMZWZ0JyxcbiAgJ3BhZGRpbmdSaWdodCcsXG4gICdwYWRkaW5nVG9wJyxcbiAgJ3BhZGRpbmdCb3R0b20nLFxuICAnbWFyZ2luTGVmdCcsXG4gICdtYXJnaW5SaWdodCcsXG4gICdtYXJnaW5Ub3AnLFxuICAnbWFyZ2luQm90dG9tJyxcbiAgJ2JvcmRlckxlZnRXaWR0aCcsXG4gICdib3JkZXJSaWdodFdpZHRoJyxcbiAgJ2JvcmRlclRvcFdpZHRoJyxcbiAgJ2JvcmRlckJvdHRvbVdpZHRoJyxcbl07XG5cbmxldCBtZWFzdXJlbWVudHNMZW5ndGggPSBtZWFzdXJlbWVudHMubGVuZ3RoO1xuXG5mdW5jdGlvbiBnZXRaZXJvU2l6ZSgpIHtcbiAgbGV0IHNpemUgPSB7XG4gICAgd2lkdGg6IDAsXG4gICAgaGVpZ2h0OiAwLFxuICAgIGlubmVyV2lkdGg6IDAsXG4gICAgaW5uZXJIZWlnaHQ6IDAsXG4gICAgb3V0ZXJXaWR0aDogMCxcbiAgICBvdXRlckhlaWdodDogMCxcbiAgfTtcbiAgbWVhc3VyZW1lbnRzLmZvckVhY2goICggbWVhc3VyZW1lbnQgKSA9PiB7XG4gICAgc2l6ZVsgbWVhc3VyZW1lbnQgXSA9IDA7XG4gIH0gKTtcbiAgcmV0dXJuIHNpemU7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGdldFNpemUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuZnVuY3Rpb24gZ2V0U2l6ZSggZWxlbSApIHtcbiAgLy8gdXNlIHF1ZXJ5U2VsZXRvciBpZiBlbGVtIGlzIHN0cmluZ1xuICBpZiAoIHR5cGVvZiBlbGVtID09ICdzdHJpbmcnICkgZWxlbSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIGVsZW0gKTtcblxuICAvLyBkbyBub3QgcHJvY2VlZCBvbiBub24tb2JqZWN0c1xuICBsZXQgaXNFbGVtZW50ID0gZWxlbSAmJiB0eXBlb2YgZWxlbSA9PSAnb2JqZWN0JyAmJiBlbGVtLm5vZGVUeXBlO1xuICBpZiAoICFpc0VsZW1lbnQgKSByZXR1cm47XG5cbiAgbGV0IHN0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZSggZWxlbSApO1xuXG4gIC8vIGlmIGhpZGRlbiwgZXZlcnl0aGluZyBpcyAwXG4gIGlmICggc3R5bGUuZGlzcGxheSA9PSAnbm9uZScgKSByZXR1cm4gZ2V0WmVyb1NpemUoKTtcblxuICBsZXQgc2l6ZSA9IHt9O1xuICBzaXplLndpZHRoID0gZWxlbS5vZmZzZXRXaWR0aDtcbiAgc2l6ZS5oZWlnaHQgPSBlbGVtLm9mZnNldEhlaWdodDtcblxuICBsZXQgaXNCb3JkZXJCb3ggPSBzaXplLmlzQm9yZGVyQm94ID0gc3R5bGUuYm94U2l6aW5nID09ICdib3JkZXItYm94JztcblxuICAvLyBnZXQgYWxsIG1lYXN1cmVtZW50c1xuICBtZWFzdXJlbWVudHMuZm9yRWFjaCggKCBtZWFzdXJlbWVudCApID0+IHtcbiAgICBsZXQgdmFsdWUgPSBzdHlsZVsgbWVhc3VyZW1lbnQgXTtcbiAgICBsZXQgbnVtID0gcGFyc2VGbG9hdCggdmFsdWUgKTtcbiAgICAvLyBhbnkgJ2F1dG8nLCAnbWVkaXVtJyB2YWx1ZSB3aWxsIGJlIDBcbiAgICBzaXplWyBtZWFzdXJlbWVudCBdID0gIWlzTmFOKCBudW0gKSA/IG51bSA6IDA7XG4gIH0gKTtcblxuICBsZXQgcGFkZGluZ1dpZHRoID0gc2l6ZS5wYWRkaW5nTGVmdCArIHNpemUucGFkZGluZ1JpZ2h0O1xuICBsZXQgcGFkZGluZ0hlaWdodCA9IHNpemUucGFkZGluZ1RvcCArIHNpemUucGFkZGluZ0JvdHRvbTtcbiAgbGV0IG1hcmdpbldpZHRoID0gc2l6ZS5tYXJnaW5MZWZ0ICsgc2l6ZS5tYXJnaW5SaWdodDtcbiAgbGV0IG1hcmdpbkhlaWdodCA9IHNpemUubWFyZ2luVG9wICsgc2l6ZS5tYXJnaW5Cb3R0b207XG4gIGxldCBib3JkZXJXaWR0aCA9IHNpemUuYm9yZGVyTGVmdFdpZHRoICsgc2l6ZS5ib3JkZXJSaWdodFdpZHRoO1xuICBsZXQgYm9yZGVySGVpZ2h0ID0gc2l6ZS5ib3JkZXJUb3BXaWR0aCArIHNpemUuYm9yZGVyQm90dG9tV2lkdGg7XG5cbiAgLy8gb3ZlcndyaXRlIHdpZHRoIGFuZCBoZWlnaHQgaWYgd2UgY2FuIGdldCBpdCBmcm9tIHN0eWxlXG4gIGxldCBzdHlsZVdpZHRoID0gZ2V0U3R5bGVTaXplKCBzdHlsZS53aWR0aCApO1xuICBpZiAoIHN0eWxlV2lkdGggIT09IGZhbHNlICkge1xuICAgIHNpemUud2lkdGggPSBzdHlsZVdpZHRoICtcbiAgICAgIC8vIGFkZCBwYWRkaW5nIGFuZCBib3JkZXIgdW5sZXNzIGl0J3MgYWxyZWFkeSBpbmNsdWRpbmcgaXRcbiAgICAgICggaXNCb3JkZXJCb3ggPyAwIDogcGFkZGluZ1dpZHRoICsgYm9yZGVyV2lkdGggKTtcbiAgfVxuXG4gIGxldCBzdHlsZUhlaWdodCA9IGdldFN0eWxlU2l6ZSggc3R5bGUuaGVpZ2h0ICk7XG4gIGlmICggc3R5bGVIZWlnaHQgIT09IGZhbHNlICkge1xuICAgIHNpemUuaGVpZ2h0ID0gc3R5bGVIZWlnaHQgK1xuICAgICAgLy8gYWRkIHBhZGRpbmcgYW5kIGJvcmRlciB1bmxlc3MgaXQncyBhbHJlYWR5IGluY2x1ZGluZyBpdFxuICAgICAgKCBpc0JvcmRlckJveCA/IDAgOiBwYWRkaW5nSGVpZ2h0ICsgYm9yZGVySGVpZ2h0ICk7XG4gIH1cblxuICBzaXplLmlubmVyV2lkdGggPSBzaXplLndpZHRoIC0gKCBwYWRkaW5nV2lkdGggKyBib3JkZXJXaWR0aCApO1xuICBzaXplLmlubmVySGVpZ2h0ID0gc2l6ZS5oZWlnaHQgLSAoIHBhZGRpbmdIZWlnaHQgKyBib3JkZXJIZWlnaHQgKTtcblxuICBzaXplLm91dGVyV2lkdGggPSBzaXplLndpZHRoICsgbWFyZ2luV2lkdGg7XG4gIHNpemUub3V0ZXJIZWlnaHQgPSBzaXplLmhlaWdodCArIG1hcmdpbkhlaWdodDtcblxuICByZXR1cm4gc2l6ZTtcbn1cblxucmV0dXJuIGdldFNpemU7XG5cbn0gKTtcbiIsIi8qIVxuICogaW1hZ2VzTG9hZGVkIHY1LjAuMFxuICogSmF2YVNjcmlwdCBpcyBhbGwgbGlrZSBcIllvdSBpbWFnZXMgYXJlIGRvbmUgeWV0IG9yIHdoYXQ/XCJcbiAqIE1JVCBMaWNlbnNlXG4gKi9cblxuKCBmdW5jdGlvbiggd2luZG93LCBmYWN0b3J5ICkge1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cbiAgaWYgKCB0eXBlb2YgbW9kdWxlID09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzICkge1xuICAgIC8vIENvbW1vbkpTXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCB3aW5kb3csIHJlcXVpcmUoJ2V2LWVtaXR0ZXInKSApO1xuICB9IGVsc2Uge1xuICAgIC8vIGJyb3dzZXIgZ2xvYmFsXG4gICAgd2luZG93LmltYWdlc0xvYWRlZCA9IGZhY3RvcnkoIHdpbmRvdywgd2luZG93LkV2RW1pdHRlciApO1xuICB9XG5cbn0gKSggdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzLFxuICAgIGZ1bmN0aW9uIGZhY3RvcnkoIHdpbmRvdywgRXZFbWl0dGVyICkge1xuXG5sZXQgJCA9IHdpbmRvdy5qUXVlcnk7XG5sZXQgY29uc29sZSA9IHdpbmRvdy5jb25zb2xlO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBoZWxwZXJzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbi8vIHR1cm4gZWxlbWVudCBvciBub2RlTGlzdCBpbnRvIGFuIGFycmF5XG5mdW5jdGlvbiBtYWtlQXJyYXkoIG9iaiApIHtcbiAgLy8gdXNlIG9iamVjdCBpZiBhbHJlYWR5IGFuIGFycmF5XG4gIGlmICggQXJyYXkuaXNBcnJheSggb2JqICkgKSByZXR1cm4gb2JqO1xuXG4gIGxldCBpc0FycmF5TGlrZSA9IHR5cGVvZiBvYmogPT0gJ29iamVjdCcgJiYgdHlwZW9mIG9iai5sZW5ndGggPT0gJ251bWJlcic7XG4gIC8vIGNvbnZlcnQgbm9kZUxpc3QgdG8gYXJyYXlcbiAgaWYgKCBpc0FycmF5TGlrZSApIHJldHVybiBbIC4uLm9iaiBdO1xuXG4gIC8vIGFycmF5IG9mIHNpbmdsZSBpbmRleFxuICByZXR1cm4gWyBvYmogXTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gaW1hZ2VzTG9hZGVkIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbi8qKlxuICogQHBhcmFtIHtbQXJyYXksIEVsZW1lbnQsIE5vZGVMaXN0LCBTdHJpbmddfSBlbGVtXG4gKiBAcGFyYW0ge1tPYmplY3QsIEZ1bmN0aW9uXX0gb3B0aW9ucyAtIGlmIGZ1bmN0aW9uLCB1c2UgYXMgY2FsbGJhY2tcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG9uQWx3YXlzIC0gY2FsbGJhY2sgZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtJbWFnZXNMb2FkZWR9XG4gKi9cbmZ1bmN0aW9uIEltYWdlc0xvYWRlZCggZWxlbSwgb3B0aW9ucywgb25BbHdheXMgKSB7XG4gIC8vIGNvZXJjZSBJbWFnZXNMb2FkZWQoKSB3aXRob3V0IG5ldywgdG8gYmUgbmV3IEltYWdlc0xvYWRlZCgpXG4gIGlmICggISggdGhpcyBpbnN0YW5jZW9mIEltYWdlc0xvYWRlZCApICkge1xuICAgIHJldHVybiBuZXcgSW1hZ2VzTG9hZGVkKCBlbGVtLCBvcHRpb25zLCBvbkFsd2F5cyApO1xuICB9XG4gIC8vIHVzZSBlbGVtIGFzIHNlbGVjdG9yIHN0cmluZ1xuICBsZXQgcXVlcnlFbGVtID0gZWxlbTtcbiAgaWYgKCB0eXBlb2YgZWxlbSA9PSAnc3RyaW5nJyApIHtcbiAgICBxdWVyeUVsZW0gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCBlbGVtICk7XG4gIH1cbiAgLy8gYmFpbCBpZiBiYWQgZWxlbWVudFxuICBpZiAoICFxdWVyeUVsZW0gKSB7XG4gICAgY29uc29sZS5lcnJvcihgQmFkIGVsZW1lbnQgZm9yIGltYWdlc0xvYWRlZCAke3F1ZXJ5RWxlbSB8fCBlbGVtfWApO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRoaXMuZWxlbWVudHMgPSBtYWtlQXJyYXkoIHF1ZXJ5RWxlbSApO1xuICB0aGlzLm9wdGlvbnMgPSB7fTtcbiAgLy8gc2hpZnQgYXJndW1lbnRzIGlmIG5vIG9wdGlvbnMgc2V0XG4gIGlmICggdHlwZW9mIG9wdGlvbnMgPT0gJ2Z1bmN0aW9uJyApIHtcbiAgICBvbkFsd2F5cyA9IG9wdGlvbnM7XG4gIH0gZWxzZSB7XG4gICAgT2JqZWN0LmFzc2lnbiggdGhpcy5vcHRpb25zLCBvcHRpb25zICk7XG4gIH1cblxuICBpZiAoIG9uQWx3YXlzICkgdGhpcy5vbiggJ2Fsd2F5cycsIG9uQWx3YXlzICk7XG5cbiAgdGhpcy5nZXRJbWFnZXMoKTtcbiAgLy8gYWRkIGpRdWVyeSBEZWZlcnJlZCBvYmplY3RcbiAgaWYgKCAkICkgdGhpcy5qcURlZmVycmVkID0gbmV3ICQuRGVmZXJyZWQoKTtcblxuICAvLyBIQUNLIGNoZWNrIGFzeW5jIHRvIGFsbG93IHRpbWUgdG8gYmluZCBsaXN0ZW5lcnNcbiAgc2V0VGltZW91dCggdGhpcy5jaGVjay5iaW5kKCB0aGlzICkgKTtcbn1cblxuSW1hZ2VzTG9hZGVkLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoIEV2RW1pdHRlci5wcm90b3R5cGUgKTtcblxuSW1hZ2VzTG9hZGVkLnByb3RvdHlwZS5nZXRJbWFnZXMgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5pbWFnZXMgPSBbXTtcblxuICAvLyBmaWx0ZXIgJiBmaW5kIGl0ZW1zIGlmIHdlIGhhdmUgYW4gaXRlbSBzZWxlY3RvclxuICB0aGlzLmVsZW1lbnRzLmZvckVhY2goIHRoaXMuYWRkRWxlbWVudEltYWdlcywgdGhpcyApO1xufTtcblxuY29uc3QgZWxlbWVudE5vZGVUeXBlcyA9IFsgMSwgOSwgMTEgXTtcblxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IGVsZW1cbiAqL1xuSW1hZ2VzTG9hZGVkLnByb3RvdHlwZS5hZGRFbGVtZW50SW1hZ2VzID0gZnVuY3Rpb24oIGVsZW0gKSB7XG4gIC8vIGZpbHRlciBzaWJsaW5nc1xuICBpZiAoIGVsZW0ubm9kZU5hbWUgPT09ICdJTUcnICkge1xuICAgIHRoaXMuYWRkSW1hZ2UoIGVsZW0gKTtcbiAgfVxuICAvLyBnZXQgYmFja2dyb3VuZCBpbWFnZSBvbiBlbGVtZW50XG4gIGlmICggdGhpcy5vcHRpb25zLmJhY2tncm91bmQgPT09IHRydWUgKSB7XG4gICAgdGhpcy5hZGRFbGVtZW50QmFja2dyb3VuZEltYWdlcyggZWxlbSApO1xuICB9XG5cbiAgLy8gZmluZCBjaGlsZHJlblxuICAvLyBubyBub24tZWxlbWVudCBub2RlcywgIzE0M1xuICBsZXQgeyBub2RlVHlwZSB9ID0gZWxlbTtcbiAgaWYgKCAhbm9kZVR5cGUgfHwgIWVsZW1lbnROb2RlVHlwZXMuaW5jbHVkZXMoIG5vZGVUeXBlICkgKSByZXR1cm47XG5cbiAgbGV0IGNoaWxkSW1ncyA9IGVsZW0ucXVlcnlTZWxlY3RvckFsbCgnaW1nJyk7XG4gIC8vIGNvbmNhdCBjaGlsZEVsZW1zIHRvIGZpbHRlckZvdW5kIGFycmF5XG4gIGZvciAoIGxldCBpbWcgb2YgY2hpbGRJbWdzICkge1xuICAgIHRoaXMuYWRkSW1hZ2UoIGltZyApO1xuICB9XG5cbiAgLy8gZ2V0IGNoaWxkIGJhY2tncm91bmQgaW1hZ2VzXG4gIGlmICggdHlwZW9mIHRoaXMub3B0aW9ucy5iYWNrZ3JvdW5kID09ICdzdHJpbmcnICkge1xuICAgIGxldCBjaGlsZHJlbiA9IGVsZW0ucXVlcnlTZWxlY3RvckFsbCggdGhpcy5vcHRpb25zLmJhY2tncm91bmQgKTtcbiAgICBmb3IgKCBsZXQgY2hpbGQgb2YgY2hpbGRyZW4gKSB7XG4gICAgICB0aGlzLmFkZEVsZW1lbnRCYWNrZ3JvdW5kSW1hZ2VzKCBjaGlsZCApO1xuICAgIH1cbiAgfVxufTtcblxuY29uc3QgcmVVUkwgPSAvdXJsXFwoKFsnXCJdKT8oLio/KVxcMVxcKS9naTtcblxuSW1hZ2VzTG9hZGVkLnByb3RvdHlwZS5hZGRFbGVtZW50QmFja2dyb3VuZEltYWdlcyA9IGZ1bmN0aW9uKCBlbGVtICkge1xuICBsZXQgc3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKCBlbGVtICk7XG4gIC8vIEZpcmVmb3ggcmV0dXJucyBudWxsIGlmIGluIGEgaGlkZGVuIGlmcmFtZSBodHRwczovL2J1Z3ppbC5sYS81NDgzOTdcbiAgaWYgKCAhc3R5bGUgKSByZXR1cm47XG5cbiAgLy8gZ2V0IHVybCBpbnNpZGUgdXJsKFwiLi4uXCIpXG4gIGxldCBtYXRjaGVzID0gcmVVUkwuZXhlYyggc3R5bGUuYmFja2dyb3VuZEltYWdlICk7XG4gIHdoaWxlICggbWF0Y2hlcyAhPT0gbnVsbCApIHtcbiAgICBsZXQgdXJsID0gbWF0Y2hlcyAmJiBtYXRjaGVzWzJdO1xuICAgIGlmICggdXJsICkge1xuICAgICAgdGhpcy5hZGRCYWNrZ3JvdW5kKCB1cmwsIGVsZW0gKTtcbiAgICB9XG4gICAgbWF0Y2hlcyA9IHJlVVJMLmV4ZWMoIHN0eWxlLmJhY2tncm91bmRJbWFnZSApO1xuICB9XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7SW1hZ2V9IGltZ1xuICovXG5JbWFnZXNMb2FkZWQucHJvdG90eXBlLmFkZEltYWdlID0gZnVuY3Rpb24oIGltZyApIHtcbiAgbGV0IGxvYWRpbmdJbWFnZSA9IG5ldyBMb2FkaW5nSW1hZ2UoIGltZyApO1xuICB0aGlzLmltYWdlcy5wdXNoKCBsb2FkaW5nSW1hZ2UgKTtcbn07XG5cbkltYWdlc0xvYWRlZC5wcm90b3R5cGUuYWRkQmFja2dyb3VuZCA9IGZ1bmN0aW9uKCB1cmwsIGVsZW0gKSB7XG4gIGxldCBiYWNrZ3JvdW5kID0gbmV3IEJhY2tncm91bmQoIHVybCwgZWxlbSApO1xuICB0aGlzLmltYWdlcy5wdXNoKCBiYWNrZ3JvdW5kICk7XG59O1xuXG5JbWFnZXNMb2FkZWQucHJvdG90eXBlLmNoZWNrID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMucHJvZ3Jlc3NlZENvdW50ID0gMDtcbiAgdGhpcy5oYXNBbnlCcm9rZW4gPSBmYWxzZTtcbiAgLy8gY29tcGxldGUgaWYgbm8gaW1hZ2VzXG4gIGlmICggIXRoaXMuaW1hZ2VzLmxlbmd0aCApIHtcbiAgICB0aGlzLmNvbXBsZXRlKCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLyogZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGZ1bmMtc3R5bGUgKi9cbiAgbGV0IG9uUHJvZ3Jlc3MgPSAoIGltYWdlLCBlbGVtLCBtZXNzYWdlICkgPT4ge1xuICAgIC8vIEhBQ0sgLSBDaHJvbWUgdHJpZ2dlcnMgZXZlbnQgYmVmb3JlIG9iamVjdCBwcm9wZXJ0aWVzIGhhdmUgY2hhbmdlZC4gIzgzXG4gICAgc2V0VGltZW91dCggKCkgPT4ge1xuICAgICAgdGhpcy5wcm9ncmVzcyggaW1hZ2UsIGVsZW0sIG1lc3NhZ2UgKTtcbiAgICB9ICk7XG4gIH07XG5cbiAgdGhpcy5pbWFnZXMuZm9yRWFjaCggZnVuY3Rpb24oIGxvYWRpbmdJbWFnZSApIHtcbiAgICBsb2FkaW5nSW1hZ2Uub25jZSggJ3Byb2dyZXNzJywgb25Qcm9ncmVzcyApO1xuICAgIGxvYWRpbmdJbWFnZS5jaGVjaygpO1xuICB9ICk7XG59O1xuXG5JbWFnZXNMb2FkZWQucHJvdG90eXBlLnByb2dyZXNzID0gZnVuY3Rpb24oIGltYWdlLCBlbGVtLCBtZXNzYWdlICkge1xuICB0aGlzLnByb2dyZXNzZWRDb3VudCsrO1xuICB0aGlzLmhhc0FueUJyb2tlbiA9IHRoaXMuaGFzQW55QnJva2VuIHx8ICFpbWFnZS5pc0xvYWRlZDtcbiAgLy8gcHJvZ3Jlc3MgZXZlbnRcbiAgdGhpcy5lbWl0RXZlbnQoICdwcm9ncmVzcycsIFsgdGhpcywgaW1hZ2UsIGVsZW0gXSApO1xuICBpZiAoIHRoaXMuanFEZWZlcnJlZCAmJiB0aGlzLmpxRGVmZXJyZWQubm90aWZ5ICkge1xuICAgIHRoaXMuanFEZWZlcnJlZC5ub3RpZnkoIHRoaXMsIGltYWdlICk7XG4gIH1cbiAgLy8gY2hlY2sgaWYgY29tcGxldGVkXG4gIGlmICggdGhpcy5wcm9ncmVzc2VkQ291bnQgPT09IHRoaXMuaW1hZ2VzLmxlbmd0aCApIHtcbiAgICB0aGlzLmNvbXBsZXRlKCk7XG4gIH1cblxuICBpZiAoIHRoaXMub3B0aW9ucy5kZWJ1ZyAmJiBjb25zb2xlICkge1xuICAgIGNvbnNvbGUubG9nKCBgcHJvZ3Jlc3M6ICR7bWVzc2FnZX1gLCBpbWFnZSwgZWxlbSApO1xuICB9XG59O1xuXG5JbWFnZXNMb2FkZWQucHJvdG90eXBlLmNvbXBsZXRlID0gZnVuY3Rpb24oKSB7XG4gIGxldCBldmVudE5hbWUgPSB0aGlzLmhhc0FueUJyb2tlbiA/ICdmYWlsJyA6ICdkb25lJztcbiAgdGhpcy5pc0NvbXBsZXRlID0gdHJ1ZTtcbiAgdGhpcy5lbWl0RXZlbnQoIGV2ZW50TmFtZSwgWyB0aGlzIF0gKTtcbiAgdGhpcy5lbWl0RXZlbnQoICdhbHdheXMnLCBbIHRoaXMgXSApO1xuICBpZiAoIHRoaXMuanFEZWZlcnJlZCApIHtcbiAgICBsZXQganFNZXRob2QgPSB0aGlzLmhhc0FueUJyb2tlbiA/ICdyZWplY3QnIDogJ3Jlc29sdmUnO1xuICAgIHRoaXMuanFEZWZlcnJlZFsganFNZXRob2QgXSggdGhpcyApO1xuICB9XG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuZnVuY3Rpb24gTG9hZGluZ0ltYWdlKCBpbWcgKSB7XG4gIHRoaXMuaW1nID0gaW1nO1xufVxuXG5Mb2FkaW5nSW1hZ2UucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSggRXZFbWl0dGVyLnByb3RvdHlwZSApO1xuXG5Mb2FkaW5nSW1hZ2UucHJvdG90eXBlLmNoZWNrID0gZnVuY3Rpb24oKSB7XG4gIC8vIElmIGNvbXBsZXRlIGlzIHRydWUgYW5kIGJyb3dzZXIgc3VwcG9ydHMgbmF0dXJhbCBzaXplcyxcbiAgLy8gdHJ5IHRvIGNoZWNrIGZvciBpbWFnZSBzdGF0dXMgbWFudWFsbHkuXG4gIGxldCBpc0NvbXBsZXRlID0gdGhpcy5nZXRJc0ltYWdlQ29tcGxldGUoKTtcbiAgaWYgKCBpc0NvbXBsZXRlICkge1xuICAgIC8vIHJlcG9ydCBiYXNlZCBvbiBuYXR1cmFsV2lkdGhcbiAgICB0aGlzLmNvbmZpcm0oIHRoaXMuaW1nLm5hdHVyYWxXaWR0aCAhPT0gMCwgJ25hdHVyYWxXaWR0aCcgKTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBJZiBub25lIG9mIHRoZSBjaGVja3MgYWJvdmUgbWF0Y2hlZCwgc2ltdWxhdGUgbG9hZGluZyBvbiBkZXRhY2hlZCBlbGVtZW50LlxuICB0aGlzLnByb3h5SW1hZ2UgPSBuZXcgSW1hZ2UoKTtcbiAgLy8gYWRkIGNyb3NzT3JpZ2luIGF0dHJpYnV0ZS4gIzIwNFxuICBpZiAoIHRoaXMuaW1nLmNyb3NzT3JpZ2luICkge1xuICAgIHRoaXMucHJveHlJbWFnZS5jcm9zc09yaWdpbiA9IHRoaXMuaW1nLmNyb3NzT3JpZ2luO1xuICB9XG4gIHRoaXMucHJveHlJbWFnZS5hZGRFdmVudExpc3RlbmVyKCAnbG9hZCcsIHRoaXMgKTtcbiAgdGhpcy5wcm94eUltYWdlLmFkZEV2ZW50TGlzdGVuZXIoICdlcnJvcicsIHRoaXMgKTtcbiAgLy8gYmluZCB0byBpbWFnZSBhcyB3ZWxsIGZvciBGaXJlZm94LiAjMTkxXG4gIHRoaXMuaW1nLmFkZEV2ZW50TGlzdGVuZXIoICdsb2FkJywgdGhpcyApO1xuICB0aGlzLmltZy5hZGRFdmVudExpc3RlbmVyKCAnZXJyb3InLCB0aGlzICk7XG4gIHRoaXMucHJveHlJbWFnZS5zcmMgPSB0aGlzLmltZy5jdXJyZW50U3JjIHx8IHRoaXMuaW1nLnNyYztcbn07XG5cbkxvYWRpbmdJbWFnZS5wcm90b3R5cGUuZ2V0SXNJbWFnZUNvbXBsZXRlID0gZnVuY3Rpb24oKSB7XG4gIC8vIGNoZWNrIGZvciBub24temVybywgbm9uLXVuZGVmaW5lZCBuYXR1cmFsV2lkdGhcbiAgLy8gZml4ZXMgU2FmYXJpK0luZmluaXRlU2Nyb2xsK01hc29ucnkgYnVnIGluZmluaXRlLXNjcm9sbCM2NzFcbiAgcmV0dXJuIHRoaXMuaW1nLmNvbXBsZXRlICYmIHRoaXMuaW1nLm5hdHVyYWxXaWR0aDtcbn07XG5cbkxvYWRpbmdJbWFnZS5wcm90b3R5cGUuY29uZmlybSA9IGZ1bmN0aW9uKCBpc0xvYWRlZCwgbWVzc2FnZSApIHtcbiAgdGhpcy5pc0xvYWRlZCA9IGlzTG9hZGVkO1xuICBsZXQgeyBwYXJlbnROb2RlIH0gPSB0aGlzLmltZztcbiAgLy8gZW1pdCBwcm9ncmVzcyB3aXRoIHBhcmVudCA8cGljdHVyZT4gb3Igc2VsZiA8aW1nPlxuICBsZXQgZWxlbSA9IHBhcmVudE5vZGUubm9kZU5hbWUgPT09ICdQSUNUVVJFJyA/IHBhcmVudE5vZGUgOiB0aGlzLmltZztcbiAgdGhpcy5lbWl0RXZlbnQoICdwcm9ncmVzcycsIFsgdGhpcywgZWxlbSwgbWVzc2FnZSBdICk7XG59O1xuXG4vLyAtLS0tLSBldmVudHMgLS0tLS0gLy9cblxuLy8gdHJpZ2dlciBzcGVjaWZpZWQgaGFuZGxlciBmb3IgZXZlbnQgdHlwZVxuTG9hZGluZ0ltYWdlLnByb3RvdHlwZS5oYW5kbGVFdmVudCA9IGZ1bmN0aW9uKCBldmVudCApIHtcbiAgbGV0IG1ldGhvZCA9ICdvbicgKyBldmVudC50eXBlO1xuICBpZiAoIHRoaXNbIG1ldGhvZCBdICkge1xuICAgIHRoaXNbIG1ldGhvZCBdKCBldmVudCApO1xuICB9XG59O1xuXG5Mb2FkaW5nSW1hZ2UucHJvdG90eXBlLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmNvbmZpcm0oIHRydWUsICdvbmxvYWQnICk7XG4gIHRoaXMudW5iaW5kRXZlbnRzKCk7XG59O1xuXG5Mb2FkaW5nSW1hZ2UucHJvdG90eXBlLm9uZXJyb3IgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5jb25maXJtKCBmYWxzZSwgJ29uZXJyb3InICk7XG4gIHRoaXMudW5iaW5kRXZlbnRzKCk7XG59O1xuXG5Mb2FkaW5nSW1hZ2UucHJvdG90eXBlLnVuYmluZEV2ZW50cyA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnByb3h5SW1hZ2UucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ2xvYWQnLCB0aGlzICk7XG4gIHRoaXMucHJveHlJbWFnZS5yZW1vdmVFdmVudExpc3RlbmVyKCAnZXJyb3InLCB0aGlzICk7XG4gIHRoaXMuaW1nLnJlbW92ZUV2ZW50TGlzdGVuZXIoICdsb2FkJywgdGhpcyApO1xuICB0aGlzLmltZy5yZW1vdmVFdmVudExpc3RlbmVyKCAnZXJyb3InLCB0aGlzICk7XG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBCYWNrZ3JvdW5kIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbmZ1bmN0aW9uIEJhY2tncm91bmQoIHVybCwgZWxlbWVudCApIHtcbiAgdGhpcy51cmwgPSB1cmw7XG4gIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gIHRoaXMuaW1nID0gbmV3IEltYWdlKCk7XG59XG5cbi8vIGluaGVyaXQgTG9hZGluZ0ltYWdlIHByb3RvdHlwZVxuQmFja2dyb3VuZC5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKCBMb2FkaW5nSW1hZ2UucHJvdG90eXBlICk7XG5cbkJhY2tncm91bmQucHJvdG90eXBlLmNoZWNrID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuaW1nLmFkZEV2ZW50TGlzdGVuZXIoICdsb2FkJywgdGhpcyApO1xuICB0aGlzLmltZy5hZGRFdmVudExpc3RlbmVyKCAnZXJyb3InLCB0aGlzICk7XG4gIHRoaXMuaW1nLnNyYyA9IHRoaXMudXJsO1xuICAvLyBjaGVjayBpZiBpbWFnZSBpcyBhbHJlYWR5IGNvbXBsZXRlXG4gIGxldCBpc0NvbXBsZXRlID0gdGhpcy5nZXRJc0ltYWdlQ29tcGxldGUoKTtcbiAgaWYgKCBpc0NvbXBsZXRlICkge1xuICAgIHRoaXMuY29uZmlybSggdGhpcy5pbWcubmF0dXJhbFdpZHRoICE9PSAwLCAnbmF0dXJhbFdpZHRoJyApO1xuICAgIHRoaXMudW5iaW5kRXZlbnRzKCk7XG4gIH1cbn07XG5cbkJhY2tncm91bmQucHJvdG90eXBlLnVuYmluZEV2ZW50cyA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmltZy5yZW1vdmVFdmVudExpc3RlbmVyKCAnbG9hZCcsIHRoaXMgKTtcbiAgdGhpcy5pbWcucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ2Vycm9yJywgdGhpcyApO1xufTtcblxuQmFja2dyb3VuZC5wcm90b3R5cGUuY29uZmlybSA9IGZ1bmN0aW9uKCBpc0xvYWRlZCwgbWVzc2FnZSApIHtcbiAgdGhpcy5pc0xvYWRlZCA9IGlzTG9hZGVkO1xuICB0aGlzLmVtaXRFdmVudCggJ3Byb2dyZXNzJywgWyB0aGlzLCB0aGlzLmVsZW1lbnQsIG1lc3NhZ2UgXSApO1xufTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0galF1ZXJ5IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbkltYWdlc0xvYWRlZC5tYWtlSlF1ZXJ5UGx1Z2luID0gZnVuY3Rpb24oIGpRdWVyeSApIHtcbiAgalF1ZXJ5ID0galF1ZXJ5IHx8IHdpbmRvdy5qUXVlcnk7XG4gIGlmICggIWpRdWVyeSApIHJldHVybjtcblxuICAvLyBzZXQgbG9jYWwgdmFyaWFibGVcbiAgJCA9IGpRdWVyeTtcbiAgLy8gJCgpLmltYWdlc0xvYWRlZCgpXG4gICQuZm4uaW1hZ2VzTG9hZGVkID0gZnVuY3Rpb24oIG9wdGlvbnMsIG9uQWx3YXlzICkge1xuICAgIGxldCBpbnN0YW5jZSA9IG5ldyBJbWFnZXNMb2FkZWQoIHRoaXMsIG9wdGlvbnMsIG9uQWx3YXlzICk7XG4gICAgcmV0dXJuIGluc3RhbmNlLmpxRGVmZXJyZWQucHJvbWlzZSggJCggdGhpcyApICk7XG4gIH07XG59O1xuLy8gdHJ5IG1ha2luZyBwbHVnaW5cbkltYWdlc0xvYWRlZC5tYWtlSlF1ZXJ5UGx1Z2luKCk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG5yZXR1cm4gSW1hZ2VzTG9hZGVkO1xuXG59ICk7XG4iLCIvKiFcbiAqIFVuaWRyYWdnZXIgdjMuMC4xXG4gKiBEcmFnZ2FibGUgYmFzZSBjbGFzc1xuICogTUlUIGxpY2Vuc2VcbiAqL1xuXG4oIGZ1bmN0aW9uKCB3aW5kb3csIGZhY3RvcnkgKSB7XG4gIC8vIHVuaXZlcnNhbCBtb2R1bGUgZGVmaW5pdGlvblxuICBpZiAoIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG4gICAgLy8gQ29tbW9uSlNcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoXG4gICAgICAgIHdpbmRvdyxcbiAgICAgICAgcmVxdWlyZSgnZXYtZW1pdHRlcicpLFxuICAgICk7XG4gIH0gZWxzZSB7XG4gICAgLy8gYnJvd3NlciBnbG9iYWxcbiAgICB3aW5kb3cuVW5pZHJhZ2dlciA9IGZhY3RvcnkoXG4gICAgICAgIHdpbmRvdyxcbiAgICAgICAgd2luZG93LkV2RW1pdHRlcixcbiAgICApO1xuICB9XG5cbn0oIHR5cGVvZiB3aW5kb3cgIT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzLCBmdW5jdGlvbiBmYWN0b3J5KCB3aW5kb3csIEV2RW1pdHRlciApIHtcblxuZnVuY3Rpb24gVW5pZHJhZ2dlcigpIHt9XG5cbi8vIGluaGVyaXQgRXZFbWl0dGVyXG5sZXQgcHJvdG8gPSBVbmlkcmFnZ2VyLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoIEV2RW1pdHRlci5wcm90b3R5cGUgKTtcblxuLy8gLS0tLS0gYmluZCBzdGFydCAtLS0tLSAvL1xuXG4vLyB0cmlnZ2VyIGhhbmRsZXIgbWV0aG9kcyBmb3IgZXZlbnRzXG5wcm90by5oYW5kbGVFdmVudCA9IGZ1bmN0aW9uKCBldmVudCApIHtcbiAgbGV0IG1ldGhvZCA9ICdvbicgKyBldmVudC50eXBlO1xuICBpZiAoIHRoaXNbIG1ldGhvZCBdICkge1xuICAgIHRoaXNbIG1ldGhvZCBdKCBldmVudCApO1xuICB9XG59O1xuXG5sZXQgc3RhcnRFdmVudCwgYWN0aXZlRXZlbnRzO1xuaWYgKCAnb250b3VjaHN0YXJ0JyBpbiB3aW5kb3cgKSB7XG4gIC8vIEhBQ0sgcHJlZmVyIFRvdWNoIEV2ZW50cyBhcyB5b3UgY2FuIHByZXZlbnREZWZhdWx0IG9uIHRvdWNoc3RhcnQgdG9cbiAgLy8gZGlzYWJsZSBzY3JvbGwgaW4gaU9TICYgbW9iaWxlIENocm9tZSBtZXRhZml6enkvZmxpY2tpdHkjMTE3N1xuICBzdGFydEV2ZW50ID0gJ3RvdWNoc3RhcnQnO1xuICBhY3RpdmVFdmVudHMgPSBbICd0b3VjaG1vdmUnLCAndG91Y2hlbmQnLCAndG91Y2hjYW5jZWwnIF07XG59IGVsc2UgaWYgKCB3aW5kb3cuUG9pbnRlckV2ZW50ICkge1xuICAvLyBQb2ludGVyIEV2ZW50c1xuICBzdGFydEV2ZW50ID0gJ3BvaW50ZXJkb3duJztcbiAgYWN0aXZlRXZlbnRzID0gWyAncG9pbnRlcm1vdmUnLCAncG9pbnRlcnVwJywgJ3BvaW50ZXJjYW5jZWwnIF07XG59IGVsc2Uge1xuICAvLyBtb3VzZSBldmVudHNcbiAgc3RhcnRFdmVudCA9ICdtb3VzZWRvd24nO1xuICBhY3RpdmVFdmVudHMgPSBbICdtb3VzZW1vdmUnLCAnbW91c2V1cCcgXTtcbn1cblxuLy8gcHJvdG90eXBlIHNvIGl0IGNhbiBiZSBvdmVyd3JpdGVhYmxlIGJ5IEZsaWNraXR5XG5wcm90by50b3VjaEFjdGlvblZhbHVlID0gJ25vbmUnO1xuXG5wcm90by5iaW5kSGFuZGxlcyA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLl9iaW5kSGFuZGxlcyggJ2FkZEV2ZW50TGlzdGVuZXInLCB0aGlzLnRvdWNoQWN0aW9uVmFsdWUgKTtcbn07XG5cbnByb3RvLnVuYmluZEhhbmRsZXMgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5fYmluZEhhbmRsZXMoICdyZW1vdmVFdmVudExpc3RlbmVyJywgJycgKTtcbn07XG5cbi8qKlxuICogQWRkIG9yIHJlbW92ZSBzdGFydCBldmVudFxuICogQHBhcmFtIHtTdHJpbmd9IGJpbmRNZXRob2QgLSBhZGRFdmVudExpc3RlbmVyIG9yIHJlbW92ZUV2ZW50TGlzdGVuZXJcbiAqIEBwYXJhbSB7U3RyaW5nfSB0b3VjaEFjdGlvbiAtIHZhbHVlIGZvciB0b3VjaC1hY3Rpb24gQ1NTIHByb3BlcnR5XG4gKi9cbnByb3RvLl9iaW5kSGFuZGxlcyA9IGZ1bmN0aW9uKCBiaW5kTWV0aG9kLCB0b3VjaEFjdGlvbiApIHtcbiAgdGhpcy5oYW5kbGVzLmZvckVhY2goICggaGFuZGxlICkgPT4ge1xuICAgIGhhbmRsZVsgYmluZE1ldGhvZCBdKCBzdGFydEV2ZW50LCB0aGlzICk7XG4gICAgaGFuZGxlWyBiaW5kTWV0aG9kIF0oICdjbGljaycsIHRoaXMgKTtcbiAgICAvLyB0b3VjaC1hY3Rpb246IG5vbmUgdG8gb3ZlcnJpZGUgYnJvd3NlciB0b3VjaCBnZXN0dXJlcy4gbWV0YWZpenp5L2ZsaWNraXR5IzU0MFxuICAgIGlmICggd2luZG93LlBvaW50ZXJFdmVudCApIGhhbmRsZS5zdHlsZS50b3VjaEFjdGlvbiA9IHRvdWNoQWN0aW9uO1xuICB9ICk7XG59O1xuXG5wcm90by5iaW5kQWN0aXZlUG9pbnRlckV2ZW50cyA9IGZ1bmN0aW9uKCkge1xuICBhY3RpdmVFdmVudHMuZm9yRWFjaCggKCBldmVudE5hbWUgKSA9PiB7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoIGV2ZW50TmFtZSwgdGhpcyApO1xuICB9ICk7XG59O1xuXG5wcm90by51bmJpbmRBY3RpdmVQb2ludGVyRXZlbnRzID0gZnVuY3Rpb24oKSB7XG4gIGFjdGl2ZUV2ZW50cy5mb3JFYWNoKCAoIGV2ZW50TmFtZSApID0+IHtcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lciggZXZlbnROYW1lLCB0aGlzICk7XG4gIH0gKTtcbn07XG5cbi8vIC0tLS0tIGV2ZW50IGhhbmRsZXIgaGVscGVycyAtLS0tLSAvL1xuXG4vLyB0cmlnZ2VyIG1ldGhvZCB3aXRoIG1hdGNoaW5nIHBvaW50ZXJcbnByb3RvLndpdGhQb2ludGVyID0gZnVuY3Rpb24oIG1ldGhvZE5hbWUsIGV2ZW50ICkge1xuICBpZiAoIGV2ZW50LnBvaW50ZXJJZCA9PT0gdGhpcy5wb2ludGVySWRlbnRpZmllciApIHtcbiAgICB0aGlzWyBtZXRob2ROYW1lIF0oIGV2ZW50LCBldmVudCApO1xuICB9XG59O1xuXG4vLyB0cmlnZ2VyIG1ldGhvZCB3aXRoIG1hdGNoaW5nIHRvdWNoXG5wcm90by53aXRoVG91Y2ggPSBmdW5jdGlvbiggbWV0aG9kTmFtZSwgZXZlbnQgKSB7XG4gIGxldCB0b3VjaDtcbiAgZm9yICggbGV0IGNoYW5nZWRUb3VjaCBvZiBldmVudC5jaGFuZ2VkVG91Y2hlcyApIHtcbiAgICBpZiAoIGNoYW5nZWRUb3VjaC5pZGVudGlmaWVyID09PSB0aGlzLnBvaW50ZXJJZGVudGlmaWVyICkge1xuICAgICAgdG91Y2ggPSBjaGFuZ2VkVG91Y2g7XG4gICAgfVxuICB9XG4gIGlmICggdG91Y2ggKSB0aGlzWyBtZXRob2ROYW1lIF0oIGV2ZW50LCB0b3VjaCApO1xufTtcblxuLy8gLS0tLS0gc3RhcnQgZXZlbnQgLS0tLS0gLy9cblxucHJvdG8ub25tb3VzZWRvd24gPSBmdW5jdGlvbiggZXZlbnQgKSB7XG4gIHRoaXMucG9pbnRlckRvd24oIGV2ZW50LCBldmVudCApO1xufTtcblxucHJvdG8ub250b3VjaHN0YXJ0ID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuICB0aGlzLnBvaW50ZXJEb3duKCBldmVudCwgZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0gKTtcbn07XG5cbnByb3RvLm9ucG9pbnRlcmRvd24gPSBmdW5jdGlvbiggZXZlbnQgKSB7XG4gIHRoaXMucG9pbnRlckRvd24oIGV2ZW50LCBldmVudCApO1xufTtcblxuLy8gbm9kZXMgdGhhdCBoYXZlIHRleHQgZmllbGRzXG5jb25zdCBjdXJzb3JOb2RlcyA9IFsgJ1RFWFRBUkVBJywgJ0lOUFVUJywgJ1NFTEVDVCcsICdPUFRJT04nIF07XG4vLyBpbnB1dCB0eXBlcyB0aGF0IGRvIG5vdCBoYXZlIHRleHQgZmllbGRzXG5jb25zdCBjbGlja1R5cGVzID0gWyAncmFkaW8nLCAnY2hlY2tib3gnLCAnYnV0dG9uJywgJ3N1Ym1pdCcsICdpbWFnZScsICdmaWxlJyBdO1xuXG4vKipcbiAqIGFueSB0aW1lIHlvdSBzZXQgYGV2ZW50LCBwb2ludGVyYCBpdCByZWZlcnMgdG86XG4gKiBAcGFyYW0ge0V2ZW50fSBldmVudFxuICogQHBhcmFtIHtFdmVudCB8IFRvdWNofSBwb2ludGVyXG4gKi9cbnByb3RvLnBvaW50ZXJEb3duID0gZnVuY3Rpb24oIGV2ZW50LCBwb2ludGVyICkge1xuICAvLyBkaXNtaXNzIG11bHRpLXRvdWNoIHRhcHMsIHJpZ2h0IGNsaWNrcywgYW5kIGNsaWNrcyBvbiB0ZXh0IGZpZWxkc1xuICBsZXQgaXNDdXJzb3JOb2RlID0gY3Vyc29yTm9kZXMuaW5jbHVkZXMoIGV2ZW50LnRhcmdldC5ub2RlTmFtZSApO1xuICBsZXQgaXNDbGlja1R5cGUgPSBjbGlja1R5cGVzLmluY2x1ZGVzKCBldmVudC50YXJnZXQudHlwZSApO1xuICBsZXQgaXNPa2F5RWxlbWVudCA9ICFpc0N1cnNvck5vZGUgfHwgaXNDbGlja1R5cGU7XG4gIGxldCBpc09rYXkgPSAhdGhpcy5pc1BvaW50ZXJEb3duICYmICFldmVudC5idXR0b24gJiYgaXNPa2F5RWxlbWVudDtcbiAgaWYgKCAhaXNPa2F5ICkgcmV0dXJuO1xuXG4gIHRoaXMuaXNQb2ludGVyRG93biA9IHRydWU7XG4gIC8vIHNhdmUgcG9pbnRlciBpZGVudGlmaWVyIHRvIG1hdGNoIHVwIHRvdWNoIGV2ZW50c1xuICB0aGlzLnBvaW50ZXJJZGVudGlmaWVyID0gcG9pbnRlci5wb2ludGVySWQgIT09IHVuZGVmaW5lZCA/XG4gICAgLy8gcG9pbnRlcklkIGZvciBwb2ludGVyIGV2ZW50cywgdG91Y2guaW5kZW50aWZpZXIgZm9yIHRvdWNoIGV2ZW50c1xuICAgIHBvaW50ZXIucG9pbnRlcklkIDogcG9pbnRlci5pZGVudGlmaWVyO1xuICAvLyB0cmFjayBwb3NpdGlvbiBmb3IgbW92ZVxuICB0aGlzLnBvaW50ZXJEb3duUG9pbnRlciA9IHtcbiAgICBwYWdlWDogcG9pbnRlci5wYWdlWCxcbiAgICBwYWdlWTogcG9pbnRlci5wYWdlWSxcbiAgfTtcblxuICB0aGlzLmJpbmRBY3RpdmVQb2ludGVyRXZlbnRzKCk7XG4gIHRoaXMuZW1pdEV2ZW50KCAncG9pbnRlckRvd24nLCBbIGV2ZW50LCBwb2ludGVyIF0gKTtcbn07XG5cbi8vIC0tLS0tIG1vdmUgLS0tLS0gLy9cblxucHJvdG8ub25tb3VzZW1vdmUgPSBmdW5jdGlvbiggZXZlbnQgKSB7XG4gIHRoaXMucG9pbnRlck1vdmUoIGV2ZW50LCBldmVudCApO1xufTtcblxucHJvdG8ub25wb2ludGVybW92ZSA9IGZ1bmN0aW9uKCBldmVudCApIHtcbiAgdGhpcy53aXRoUG9pbnRlciggJ3BvaW50ZXJNb3ZlJywgZXZlbnQgKTtcbn07XG5cbnByb3RvLm9udG91Y2htb3ZlID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuICB0aGlzLndpdGhUb3VjaCggJ3BvaW50ZXJNb3ZlJywgZXZlbnQgKTtcbn07XG5cbnByb3RvLnBvaW50ZXJNb3ZlID0gZnVuY3Rpb24oIGV2ZW50LCBwb2ludGVyICkge1xuICBsZXQgbW92ZVZlY3RvciA9IHtcbiAgICB4OiBwb2ludGVyLnBhZ2VYIC0gdGhpcy5wb2ludGVyRG93blBvaW50ZXIucGFnZVgsXG4gICAgeTogcG9pbnRlci5wYWdlWSAtIHRoaXMucG9pbnRlckRvd25Qb2ludGVyLnBhZ2VZLFxuICB9O1xuICB0aGlzLmVtaXRFdmVudCggJ3BvaW50ZXJNb3ZlJywgWyBldmVudCwgcG9pbnRlciwgbW92ZVZlY3RvciBdICk7XG4gIC8vIHN0YXJ0IGRyYWcgaWYgcG9pbnRlciBoYXMgbW92ZWQgZmFyIGVub3VnaCB0byBzdGFydCBkcmFnXG4gIGxldCBpc0RyYWdTdGFydGluZyA9ICF0aGlzLmlzRHJhZ2dpbmcgJiYgdGhpcy5oYXNEcmFnU3RhcnRlZCggbW92ZVZlY3RvciApO1xuICBpZiAoIGlzRHJhZ1N0YXJ0aW5nICkgdGhpcy5kcmFnU3RhcnQoIGV2ZW50LCBwb2ludGVyICk7XG4gIGlmICggdGhpcy5pc0RyYWdnaW5nICkgdGhpcy5kcmFnTW92ZSggZXZlbnQsIHBvaW50ZXIsIG1vdmVWZWN0b3IgKTtcbn07XG5cbi8vIGNvbmRpdGlvbiBpZiBwb2ludGVyIGhhcyBtb3ZlZCBmYXIgZW5vdWdoIHRvIHN0YXJ0IGRyYWdcbnByb3RvLmhhc0RyYWdTdGFydGVkID0gZnVuY3Rpb24oIG1vdmVWZWN0b3IgKSB7XG4gIHJldHVybiBNYXRoLmFicyggbW92ZVZlY3Rvci54ICkgPiAzIHx8IE1hdGguYWJzKCBtb3ZlVmVjdG9yLnkgKSA+IDM7XG59O1xuXG4vLyAtLS0tLSBkcmFnIC0tLS0tIC8vXG5cbnByb3RvLmRyYWdTdGFydCA9IGZ1bmN0aW9uKCBldmVudCwgcG9pbnRlciApIHtcbiAgdGhpcy5pc0RyYWdnaW5nID0gdHJ1ZTtcbiAgdGhpcy5pc1ByZXZlbnRpbmdDbGlja3MgPSB0cnVlOyAvLyBzZXQgZmxhZyB0byBwcmV2ZW50IGNsaWNrc1xuICB0aGlzLmVtaXRFdmVudCggJ2RyYWdTdGFydCcsIFsgZXZlbnQsIHBvaW50ZXIgXSApO1xufTtcblxucHJvdG8uZHJhZ01vdmUgPSBmdW5jdGlvbiggZXZlbnQsIHBvaW50ZXIsIG1vdmVWZWN0b3IgKSB7XG4gIHRoaXMuZW1pdEV2ZW50KCAnZHJhZ01vdmUnLCBbIGV2ZW50LCBwb2ludGVyLCBtb3ZlVmVjdG9yIF0gKTtcbn07XG5cbi8vIC0tLS0tIGVuZCAtLS0tLSAvL1xuXG5wcm90by5vbm1vdXNldXAgPSBmdW5jdGlvbiggZXZlbnQgKSB7XG4gIHRoaXMucG9pbnRlclVwKCBldmVudCwgZXZlbnQgKTtcbn07XG5cbnByb3RvLm9ucG9pbnRlcnVwID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuICB0aGlzLndpdGhQb2ludGVyKCAncG9pbnRlclVwJywgZXZlbnQgKTtcbn07XG5cbnByb3RvLm9udG91Y2hlbmQgPSBmdW5jdGlvbiggZXZlbnQgKSB7XG4gIHRoaXMud2l0aFRvdWNoKCAncG9pbnRlclVwJywgZXZlbnQgKTtcbn07XG5cbnByb3RvLnBvaW50ZXJVcCA9IGZ1bmN0aW9uKCBldmVudCwgcG9pbnRlciApIHtcbiAgdGhpcy5wb2ludGVyRG9uZSgpO1xuICB0aGlzLmVtaXRFdmVudCggJ3BvaW50ZXJVcCcsIFsgZXZlbnQsIHBvaW50ZXIgXSApO1xuXG4gIGlmICggdGhpcy5pc0RyYWdnaW5nICkge1xuICAgIHRoaXMuZHJhZ0VuZCggZXZlbnQsIHBvaW50ZXIgKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBwb2ludGVyIGRpZG4ndCBtb3ZlIGVub3VnaCBmb3IgZHJhZyB0byBzdGFydFxuICAgIHRoaXMuc3RhdGljQ2xpY2soIGV2ZW50LCBwb2ludGVyICk7XG4gIH1cbn07XG5cbnByb3RvLmRyYWdFbmQgPSBmdW5jdGlvbiggZXZlbnQsIHBvaW50ZXIgKSB7XG4gIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlOyAvLyByZXNldCBmbGFnXG4gIC8vIHJlLWVuYWJsZSBjbGlja2luZyBhc3luY1xuICBzZXRUaW1lb3V0KCAoKSA9PiBkZWxldGUgdGhpcy5pc1ByZXZlbnRpbmdDbGlja3MgKTtcblxuICB0aGlzLmVtaXRFdmVudCggJ2RyYWdFbmQnLCBbIGV2ZW50LCBwb2ludGVyIF0gKTtcbn07XG5cbi8vIHRyaWdnZXJlZCBvbiBwb2ludGVyIHVwICYgcG9pbnRlciBjYW5jZWxcbnByb3RvLnBvaW50ZXJEb25lID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuaXNQb2ludGVyRG93biA9IGZhbHNlO1xuICBkZWxldGUgdGhpcy5wb2ludGVySWRlbnRpZmllcjtcbiAgdGhpcy51bmJpbmRBY3RpdmVQb2ludGVyRXZlbnRzKCk7XG4gIHRoaXMuZW1pdEV2ZW50KCdwb2ludGVyRG9uZScpO1xufTtcblxuLy8gLS0tLS0gY2FuY2VsIC0tLS0tIC8vXG5cbnByb3RvLm9ucG9pbnRlcmNhbmNlbCA9IGZ1bmN0aW9uKCBldmVudCApIHtcbiAgdGhpcy53aXRoUG9pbnRlciggJ3BvaW50ZXJDYW5jZWwnLCBldmVudCApO1xufTtcblxucHJvdG8ub250b3VjaGNhbmNlbCA9IGZ1bmN0aW9uKCBldmVudCApIHtcbiAgdGhpcy53aXRoVG91Y2goICdwb2ludGVyQ2FuY2VsJywgZXZlbnQgKTtcbn07XG5cbnByb3RvLnBvaW50ZXJDYW5jZWwgPSBmdW5jdGlvbiggZXZlbnQsIHBvaW50ZXIgKSB7XG4gIHRoaXMucG9pbnRlckRvbmUoKTtcbiAgdGhpcy5lbWl0RXZlbnQoICdwb2ludGVyQ2FuY2VsJywgWyBldmVudCwgcG9pbnRlciBdICk7XG59O1xuXG4vLyAtLS0tLSBjbGljayAtLS0tLSAvL1xuXG4vLyBoYW5kbGUgYWxsIGNsaWNrcyBhbmQgcHJldmVudCBjbGlja3Mgd2hlbiBkcmFnZ2luZ1xucHJvdG8ub25jbGljayA9IGZ1bmN0aW9uKCBldmVudCApIHtcbiAgaWYgKCB0aGlzLmlzUHJldmVudGluZ0NsaWNrcyApIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG59O1xuXG4vLyB0cmlnZ2VyZWQgYWZ0ZXIgcG9pbnRlciBkb3duICYgdXAgd2l0aCBuby90aW55IG1vdmVtZW50XG5wcm90by5zdGF0aWNDbGljayA9IGZ1bmN0aW9uKCBldmVudCwgcG9pbnRlciApIHtcbiAgLy8gaWdub3JlIGVtdWxhdGVkIG1vdXNlIHVwIGNsaWNrc1xuICBsZXQgaXNNb3VzZXVwID0gZXZlbnQudHlwZSA9PT0gJ21vdXNldXAnO1xuICBpZiAoIGlzTW91c2V1cCAmJiB0aGlzLmlzSWdub3JpbmdNb3VzZVVwICkgcmV0dXJuO1xuXG4gIHRoaXMuZW1pdEV2ZW50KCAnc3RhdGljQ2xpY2snLCBbIGV2ZW50LCBwb2ludGVyIF0gKTtcblxuICAvLyBzZXQgZmxhZyBmb3IgZW11bGF0ZWQgY2xpY2tzIDMwMG1zIGFmdGVyIHRvdWNoZW5kXG4gIGlmICggaXNNb3VzZXVwICkge1xuICAgIHRoaXMuaXNJZ25vcmluZ01vdXNlVXAgPSB0cnVlO1xuICAgIC8vIHJlc2V0IGZsYWcgYWZ0ZXIgNDAwbXNcbiAgICBzZXRUaW1lb3V0KCAoKSA9PiB7XG4gICAgICBkZWxldGUgdGhpcy5pc0lnbm9yaW5nTW91c2VVcDtcbiAgICB9LCA0MDAgKTtcbiAgfVxufTtcblxuLy8gLS0tLS0gIC0tLS0tIC8vXG5cbnJldHVybiBVbmlkcmFnZ2VyO1xuXG59ICkgKTtcbiIsIi8vIHZhciB0ZW1wbGF0ZVVybCA9IHNpdGUudGhlbWVfdXJsOyAvLyB0aGlzIGNvbWVzIGZyb20gZnVuY3Rpb25zLnBocFxuXG4vLyBDdXN0b21pemUgQm9vdFN0cmFwIC0gaW1wb3J0IG9ubHkgd2hhdCB3ZSBuZWVkXG4vLyBpbXBvcnQgQWxlcnQgZnJvbSAnYm9vdHN0cmFwL2pzL2Rpc3QvYWxlcnQnO1xuLy8gaW1wb3J0IEJ1dHRvbiBmcm9tICdib290c3RyYXAvanMvZGlzdC9idXR0b24nO1xuLy8gaW1wb3J0IENhcm91c2VsIGZyb20gJ2Jvb3RzdHJhcC9qcy9kaXN0L2Nhcm91c2VsJztcbmltcG9ydCBDb2xsYXBzZSBmcm9tICdib290c3RyYXAvanMvZGlzdC9jb2xsYXBzZSc7XG4vLyBpbXBvcnQgRHJvcGRvd24gZnJvbSAnYm9vdHN0cmFwL2pzL2Rpc3QvZHJvcGRvd24nO1xuLy8gaW1wb3J0IE1vZGFsIGZyb20gJ2Jvb3RzdHJhcC9qcy9kaXN0L21vZGFsJztcbi8vIGltcG9ydCBPZmZjYW52YXMgZnJvbSAnYm9vdHN0cmFwL2pzL2Rpc3Qvb2ZmY2FudmFzJztcbi8vIGltcG9ydCBQb3BvdmVyIGZyb20gJ2Jvb3RzdHJhcC9qcy9kaXN0L3BvcG92ZXInO1xuLy8gaW1wb3J0IFNjcm9sbFNweSBmcm9tICdib290c3RyYXAvanMvZGlzdC9zY3JvbGxzcHknO1xuLy8gaW1wb3J0IFRhYiBmcm9tICdib290c3RyYXAvanMvZGlzdC90YWInO1xuLy8gaW1wb3J0IFRvYXN0IGZyb20gJ2Jvb3RzdHJhcC9qcy9kaXN0L3RvYXN0Jztcbi8vIGltcG9ydCBUb29sdGlwIGZyb20gJ2Jvb3RzdHJhcC9qcy9kaXN0L3Rvb2x0aXAnO1xuXG4vLyBBcHBcbmltcG9ydCB7IEJnRG90cyB9IGZyb20gJy4vY29tcG9uZW50cy9nbG9iYWwvYmdEb3RzJztcbmltcG9ydCB7IENhcm91c2VscyB9IGZyb20gJy4vY29tcG9uZW50cy9nbG9iYWwvY2Fyb3VzZWxzJztcbmltcG9ydCB7IE1haW5NZW51IH0gZnJvbSAnLi9jb21wb25lbnRzL2dsb2JhbC9tYWluTWVudSc7XG5cbmNvbnN0IGluaXRBcHAgPSAoKSA9PiB7XG4gIGNvbnN0IGJvZHlFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdib2R5JylbMF07XG5cbiAgLy8gR0xPQkFMXG4gIGNvbnN0IGJnRG90cyA9IG5ldyBCZ0RvdHMoKTtcbiAgYmdEb3RzLmluaXQoKTtcblxuICBjb25zdCBjYXJvdXNlbHMgPSBuZXcgQ2Fyb3VzZWxzKCk7XG4gIGNhcm91c2Vscy5pbml0KCk7XG5cbiAgY29uc3QgbWFpbk1lbnUgPSBuZXcgTWFpbk1lbnUoQ29sbGFwc2UpO1xuICBtYWluTWVudS5pbml0KCk7XG5cbiAgLy8gUEFHRSBERVRFQ1RJT05cbiAgLy8gaWYgKGJvZHlFbC5jbGFzc0xpc3QuY29udGFpbnMoJ2hvbWUnKSkge1xuICAvLyAgIGNvbnN0IGZyb250UGFnZSA9IG5ldyBGcm9udFBhZ2UoKTtcbiAgLy8gICBmcm9udFBhZ2UuaW5pdCgpO1xuICAvLyB9XG59O1xuXG4oZnVuY3Rpb24gKCkge1xuICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgnbm8tanMnKTtcbiAgaW5pdEFwcCgpO1xufSkoKTtcbiIsImV4cG9ydCBmdW5jdGlvbiBCZ0RvdHMoKSB7XG4gIGxldCBkb3RzQ29udGFpbmVycyA9IGZhbHNlO1xuXG4gIGNvbnN0IGJyZWFrcG9pbnQgPSA5OTI7XG5cbiAgY29uc3QgaW5pdCA9ICgpID0+IHtcbiAgICBkb3RzQ29udGFpbmVycyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5iZy1kb3RzJyk7XG5cbiAgICBpZiAoIWRvdHNDb250YWluZXJzKSByZXR1cm4gZmFsc2U7XG5cbiAgICBfYWRkTGlzdGVuZXJzKCk7XG4gICAgX2luaXREb3RzKCk7XG4gICAgLy8gX2NoZWNrV2luZG93KCk7XG4gIH07XG5cbiAgY29uc3QgX2FkZExpc3RlbmVycyA9ICgpID0+IHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICdyZXNpemUnLFxuICAgICAgX2RlYm91bmNlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX2luaXREb3RzKCk7XG4gICAgICB9KSxcbiAgICAgIGZhbHNlLFxuICAgICk7XG5cbiAgICAvLyB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgKGUpID0+IHtcbiAgICAvLyAgIF9jaGVja1dpbmRvdygpO1xuICAgIC8vIH0pO1xuICB9O1xuXG4gIGNvbnN0IF9pbml0RG90cyA9ICgpID0+IHtcbiAgICBkb3RzQ29udGFpbmVycy5mb3JFYWNoKChlbCwgaSkgPT4ge1xuICAgICAgbGV0IG9mZnNldCA9IDM1O1xuICAgICAgbGV0IG1pblNpemUgPSAxMjtcbiAgICAgIGxldCBtYXhTaXplID0gMTU7XG4gICAgICBsZXQgbWluRHVyYXRpb24gPSA1MDAwO1xuICAgICAgbGV0IG1heER1cmF0aW9uID0gMTUwMDA7XG5cbiAgICAgIGNvbnN0IGNvbnRhaW5lcldpZHRoID0gZWwub2Zmc2V0V2lkdGg7XG4gICAgICBjb25zdCBjb250YWluZXJIZWlnaHQgPSBlbC5vZmZzZXRIZWlnaHQ7XG5cbiAgICAgIGVsLmlubmVySFRNTCA9ICcnO1xuXG4gICAgICBpZiAoZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdiZy1kb3RzLS1kYXJrJykpIHtcbiAgICAgICAgbWluU2l6ZSA9IDIzO1xuICAgICAgICBtYXhTaXplID0gMjM7XG4gICAgICB9XG5cbiAgICAgIGZvciAodmFyIHggPSAxMDsgeCA8IGNvbnRhaW5lcldpZHRoOyB4ICs9IG9mZnNldCkge1xuICAgICAgICBmb3IgKHZhciB5ID0gMTA7IHkgPCBjb250YWluZXJIZWlnaHQ7IHkgKz0gb2Zmc2V0KSB7XG4gICAgICAgICAgY29uc3QgZG90ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cbiAgICAgICAgICBkb3QuY2xhc3NMaXN0LmFkZCgnYmctZG90c19fZG90Jyk7XG4gICAgICAgICAgZG90LnN0eWxlLnNldFByb3BlcnR5KCctLXBvc3gnLCB4ICsgJ3B4Jyk7XG4gICAgICAgICAgZG90LnN0eWxlLnNldFByb3BlcnR5KCctLXBvc3knLCB5ICsgJ3B4Jyk7XG4gICAgICAgICAgZG90LnN0eWxlLnNldFByb3BlcnR5KCctLXJhZCcsIF9yYW5kb21SYW5nZShtaW5TaXplLCBtYXhTaXplKSArICdweCcpO1xuICAgICAgICAgIGRvdC5zdHlsZS5zZXRQcm9wZXJ0eSgnLS1kdXInLCBfcmFuZG9tUmFuZ2UobWluRHVyYXRpb24sIG1heER1cmF0aW9uKSArICdtcycpO1xuXG4gICAgICAgICAgZWwuYXBwZW5kQ2hpbGQoZG90KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIC8vIGNvbnN0IF9jaGVja1dpbmRvdyA9IChlKSA9PiB7XG4gIC8vIHJlbW92ZSBiZyBkb3RzIGFuaW1hdGlvbiBvbiBzbWFsbCBzY3JlZW5zXG4gIC8vIGlmICh3aW5kb3cuaW5uZXJXaWR0aCA8IGJyZWFrcG9pbnQpIHtcbiAgLy8gICBkb3RzQ29udGFpbmVycy5mb3JFYWNoKChlbCwgaSkgPT4ge1xuICAvLyAgICAgZWwuY2xhc3NMaXN0LnJlbW92ZSgnYmctZG90cy0tYW5pbWF0ZScpO1xuICAvLyAgIH0pO1xuICAvLyB9XG4gIC8vIH07XG5cbiAgY29uc3QgX3JhbmRvbVJhbmdlID0gKG1pbiwgbWF4KSA9PiB7XG4gICAgcmV0dXJuIE1hdGgucmFuZG9tKCkgKiAobWF4IC0gbWluKSArIG1pbjtcbiAgfTtcblxuICBjb25zdCBfZGVib3VuY2UgPSAoZnVuYywgdGltZW91dCA9IDI1MCkgPT4ge1xuICAgIGxldCB0aW1lcjtcblxuICAgIHJldHVybiAoLi4uYXJncykgPT4ge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIGZ1bmMuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICB9LCB0aW1lb3V0KTtcbiAgICB9O1xuICB9O1xuXG4gIHJldHVybiB7IGluaXQgfTtcbn1cbiIsImltcG9ydCBGbGlja2l0eSBmcm9tICdmbGlja2l0eSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDYXJvdXNlbHMoKSB7XG4gIGxldCBfY2Fyb3VzZWxzO1xuXG4gIGNvbnN0IGluaXQgPSAoKSA9PiB7XG4gICAgX3NlbGVjdENhcm91c2VscygpO1xuICAgIF9pbml0Q2Fyb3VzZWxzKCk7XG4gIH07XG5cbiAgY29uc3QgX3NlbGVjdENhcm91c2VscyA9ICgpID0+IHtcbiAgICBfY2Fyb3VzZWxzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmNhcm91c2VsJyk7XG4gIH07XG5cbiAgY29uc3QgX2luaXRDYXJvdXNlbHMgPSAoKSA9PiB7XG4gICAgaWYgKF9jYXJvdXNlbHMubGVuZ3RoKSB7XG4gICAgICBfY2Fyb3VzZWxzLmZvckVhY2goKGVsKSA9PiB7XG4gICAgICAgIGxldCBmbGt0eSA9IG5ldyBGbGlja2l0eShlbCwge1xuICAgICAgICAgIGNlbGxTZWxlY3RvcjogJy5jYXJvdXNlbF9fY2VsbCcsXG4gICAgICAgICAgd3JhcEFyb3VuZDogZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdjYXJvdXNlbC0taW1ncycpID8gZmFsc2UgOiB0cnVlLFxuICAgICAgICAgIGNvbnRhaW46IGVsLmNsYXNzTGlzdC5jb250YWlucygnY2Fyb3VzZWwtLWltZ3MnKSA/IHRydWUgOiBmYWxzZSxcbiAgICAgICAgICBpbWFnZXNMb2FkZWQ6IGVsLmNsYXNzTGlzdC5jb250YWlucygnY2Fyb3VzZWwtLWltZ3MnKSA/IHRydWUgOiBmYWxzZSxcbiAgICAgICAgICBhdXRvUGxheTogZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdjYXJvdXNlbC0taW1ncycpID8gZmFsc2UgOiAxMDAwMCxcbiAgICAgICAgICBsYXp5TG9hZDogZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdjYXJvdXNlbC0taW1ncycpID8gdHJ1ZSA6IGZhbHNlLFxuICAgICAgICAgIGFkYXB0aXZlSGVpZ2h0OiBlbC5jbGFzc0xpc3QuY29udGFpbnMoJ2Nhcm91c2VsLS1pbWdzJykgPyBmYWxzZSA6IGZhbHNlLFxuICAgICAgICAgIHBhZ2VEb3RzOiBlbC5jbGFzc0xpc3QuY29udGFpbnMoJ2Nhcm91c2VsLS1pbWdzJykgPyBmYWxzZSA6IHRydWUsXG4gICAgICAgICAgcHJldk5leHRCdXR0b25zOiBmYWxzZSxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHsgaW5pdCB9O1xufVxuIiwiZXhwb3J0IGZ1bmN0aW9uIE1haW5NZW51KENvbGxhcHNlKSB7XG4gIC8vIERPTVxuICBjb25zdCBtYWluTWVudSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtYWluLW1lbnUnKTtcbiAgY29uc3QgbmF2YmFyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLm5hdmJhcicpO1xuICBjb25zdCB0b2dnbGVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLm5hdmJhci10b2dnbGVyJyk7XG4gIGNvbnN0IGhlcm8gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuaGVybycpO1xuXG4gIGNvbnN0IGJyZWFrcG9pbnQgPSA5OTI7XG5cbiAgbGV0IG1lbnU7XG5cbiAgLy8gTWV0aG9kc1xuICBjb25zdCBpbml0ID0gKCkgPT4ge1xuICAgIGlmICghbWFpbk1lbnUpIHJldHVybiBmYWxzZTtcblxuICAgIG1lbnUgPSBuZXcgQ29sbGFwc2UobWFpbk1lbnUsIHtcbiAgICAgIHRvZ2dsZTogZmFsc2UsXG4gICAgfSk7XG5cbiAgICBfYWRkTGlzdGVuZXJzKCk7XG4gICAgX2NoZWNrV2luZG93KCk7XG4gIH07XG5cbiAgY29uc3QgX2FkZExpc3RlbmVycyA9ICgpID0+IHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgKGUpID0+IHtcbiAgICAgIF9jaGVja1dpbmRvdygpO1xuICAgIH0pO1xuICB9O1xuXG4gIGNvbnN0IF9jaGVja1dpbmRvdyA9IChlKSA9PiB7XG4gICAgaWYgKHdpbmRvdy5pbm5lcldpZHRoIDwgYnJlYWtwb2ludCkge1xuICAgICAgX2luaXRNb2JpbGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgX2luaXREZXNrdG9wKCk7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IF9pbml0TW9iaWxlID0gKCkgPT4ge1xuICAgIF9jaGVja01lbnVTY3JvbGwoKTtcblxuICAgIG5hdmJhci5jbGFzc0xpc3QucmVtb3ZlKCduYXZiYXItLXN1Ym1lbnUtb3BlbicpO1xuXG4gICAgbWFpbk1lbnUuYWRkRXZlbnRMaXN0ZW5lcignc2hvdy5icy5jb2xsYXBzZScsIF9oYW5kbGVTaG93Q29sbGFwc2UsIGZhbHNlKTtcbiAgICBtYWluTWVudS5hZGRFdmVudExpc3RlbmVyKCdoaWRlLmJzLmNvbGxhcHNlJywgX2hhbmRsZUhpZGVDb2xsYXBzZSwgZmFsc2UpO1xuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIChlKSA9PiB7XG4gICAgICBfY2hlY2tNZW51U2Nyb2xsKCk7XG4gICAgfSk7XG4gIH07XG5cbiAgY29uc3QgX2luaXREZXNrdG9wID0gKCkgPT4ge1xuICAgIF9jaGVja01lbnVTY3JvbGwoKTtcbiAgICBtZW51LmhpZGUoKTtcblxuICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnJlbW92ZSgnbWVudS1vcGVuJyk7XG5cbiAgICBtYWluTWVudS5yZW1vdmVFdmVudExpc3RlbmVyKCdzaG93LmJzLmNvbGxhcHNlJywgX2hhbmRsZVNob3dDb2xsYXBzZSwgZmFsc2UpO1xuICAgIG1haW5NZW51LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2hpZGUuYnMuY29sbGFwc2UnLCBfaGFuZGxlSGlkZUNvbGxhcHNlLCBmYWxzZSk7XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgKGUpID0+IHtcbiAgICAgIF9jaGVja01lbnVTY3JvbGwoKTtcbiAgICB9KTtcbiAgfTtcblxuICBjb25zdCBfY2hlY2tNZW51U2Nyb2xsID0gKCkgPT4ge1xuICAgIGlmIChoZXJvLm9mZnNldEhlaWdodCA9PT0gMCkge1xuICAgICAgLy8gcGFnZSBoYXMgbm8gaGVyb1xuICAgICAgaWYgKHdpbmRvdy5zY3JvbGxZIDwgMTUwKSB7XG4gICAgICAgIG5hdmJhci5jbGFzc0xpc3QucmVtb3ZlKCduYXZiYXItLXN0aWNreScpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmF2YmFyLmNsYXNzTGlzdC5hZGQoJ25hdmJhci0tc3RpY2t5Jyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBvZmZzZXQgPSBoZXJvLmNsYXNzTGlzdC5jb250YWlucygnaGVyby0tY29tcGFjdCcpID8gMTAwIDogMjAwO1xuXG4gICAgICBpZiAod2luZG93LnNjcm9sbFkgPCBoZXJvLm9mZnNldEhlaWdodCAtIG9mZnNldCkge1xuICAgICAgICBuYXZiYXIuY2xhc3NMaXN0LnJlbW92ZSgnbmF2YmFyLS1zdGlja3knKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5hdmJhci5jbGFzc0xpc3QuYWRkKCduYXZiYXItLXN0aWNreScpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBjb25zdCBfaGFuZGxlU2hvd0NvbGxhcHNlID0gKGUpID0+IHtcbiAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoJ21lbnUtb3BlbicpO1xuICAgIHRvZ2dsZXIuY2xhc3NMaXN0LmFkZCgnaXMtYWN0aXZlJyk7XG4gIH07XG5cbiAgY29uc3QgX2hhbmRsZUhpZGVDb2xsYXBzZSA9IChlKSA9PiB7XG4gICAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QucmVtb3ZlKCdtZW51LW9wZW4nKTtcbiAgICB0b2dnbGVyLmNsYXNzTGlzdC5yZW1vdmUoJ2lzLWFjdGl2ZScpO1xuICB9O1xuXG4gIHJldHVybiB7IGluaXQgfTtcbn1cbiJdfQ=="}