{"version":3,"sources":["node_modules/browser-pack/_prelude.js","node_modules/swiper/swiper-bundle.js","wp-content/themes/jcore2/js/swiper.js"],"names":[],"mappings":"AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACprUA;;;;AACA,IAAI,MAAJ,EAAY,MAAM,CAAC,MAAP,GAAgB,qBAAhB","file":"swiper.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 {\n if (typeof target[key] === 'undefined') target[key] = src[key];else if (isObject$1(src[key]) && isObject$1(target[key]) && Object.keys(src[key]).length > 0) {\n extend$1(target[key], src[key]);\n }\n });\n }\n\n const ssrDocument = {\n body: {},\n\n addEventListener() {},\n\n removeEventListener() {},\n\n activeElement: {\n blur() {},\n\n nodeName: ''\n },\n\n querySelector() {\n return null;\n },\n\n querySelectorAll() {\n return [];\n },\n\n getElementById() {\n return null;\n },\n\n createEvent() {\n return {\n initEvent() {}\n\n };\n },\n\n createElement() {\n return {\n children: [],\n childNodes: [],\n style: {},\n\n setAttribute() {},\n\n getElementsByTagName() {\n return [];\n }\n\n };\n },\n\n createElementNS() {\n return {};\n },\n\n importNode() {\n return null;\n },\n\n location: {\n hash: '',\n host: '',\n hostname: '',\n href: '',\n origin: '',\n pathname: '',\n protocol: '',\n search: ''\n }\n };\n\n function getDocument() {\n const doc = typeof document !== 'undefined' ? document : {};\n extend$1(doc, ssrDocument);\n return doc;\n }\n\n const ssrWindow = {\n document: ssrDocument,\n navigator: {\n userAgent: ''\n },\n location: {\n hash: '',\n host: '',\n hostname: '',\n href: '',\n origin: '',\n pathname: '',\n protocol: '',\n search: ''\n },\n history: {\n replaceState() {},\n\n pushState() {},\n\n go() {},\n\n back() {}\n\n },\n CustomEvent: function CustomEvent() {\n return this;\n },\n\n addEventListener() {},\n\n removeEventListener() {},\n\n getComputedStyle() {\n return {\n getPropertyValue() {\n return '';\n }\n\n };\n },\n\n Image() {},\n\n Date() {},\n\n screen: {},\n\n setTimeout() {},\n\n clearTimeout() {},\n\n matchMedia() {\n return {};\n },\n\n requestAnimationFrame(callback) {\n if (typeof setTimeout === 'undefined') {\n callback();\n return null;\n }\n\n return setTimeout(callback, 0);\n },\n\n cancelAnimationFrame(id) {\n if (typeof setTimeout === 'undefined') {\n return;\n }\n\n clearTimeout(id);\n }\n\n };\n\n function getWindow() {\n const win = typeof window !== 'undefined' ? window : {};\n extend$1(win, ssrWindow);\n return win;\n }\n\n /**\n * Dom7 4.0.4\n * Minimalistic JavaScript library for DOM manipulation, with a jQuery-compatible API\n * https://framework7.io/docs/dom7.html\n *\n * Copyright 2022, Vladimir Kharlampidi\n *\n * Licensed under MIT\n *\n * Released on: January 11, 2022\n */\n /* eslint-disable no-proto */\n\n function makeReactive(obj) {\n const proto = obj.__proto__;\n Object.defineProperty(obj, '__proto__', {\n get() {\n return proto;\n },\n\n set(value) {\n proto.__proto__ = value;\n }\n\n });\n }\n\n class Dom7 extends Array {\n constructor(items) {\n if (typeof items === 'number') {\n super(items);\n } else {\n super(...(items || []));\n makeReactive(this);\n }\n }\n\n }\n\n function arrayFlat(arr) {\n if (arr === void 0) {\n arr = [];\n }\n\n const res = [];\n arr.forEach(el => {\n if (Array.isArray(el)) {\n res.push(...arrayFlat(el));\n } else {\n res.push(el);\n }\n });\n return res;\n }\n\n function arrayFilter(arr, callback) {\n return Array.prototype.filter.call(arr, callback);\n }\n\n function arrayUnique(arr) {\n const uniqueArray = [];\n\n for (let i = 0; i < arr.length; i += 1) {\n if (uniqueArray.indexOf(arr[i]) === -1) uniqueArray.push(arr[i]);\n }\n\n return uniqueArray;\n }\n\n\n function qsa(selector, context) {\n if (typeof selector !== 'string') {\n return [selector];\n }\n\n const a = [];\n const res = context.querySelectorAll(selector);\n\n for (let i = 0; i < res.length; i += 1) {\n a.push(res[i]);\n }\n\n return a;\n }\n\n function $(selector, context) {\n const window = getWindow();\n const document = getDocument();\n let arr = [];\n\n if (!context && selector instanceof Dom7) {\n return selector;\n }\n\n if (!selector) {\n return new Dom7(arr);\n }\n\n if (typeof selector === 'string') {\n const html = selector.trim();\n\n if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) {\n let toCreate = 'div';\n if (html.indexOf(' c.split(' ')));\n this.forEach(el => {\n el.classList.add(...classNames);\n });\n return this;\n }\n\n function removeClass() {\n for (var _len2 = arguments.length, classes = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n classes[_key2] = arguments[_key2];\n }\n\n const classNames = arrayFlat(classes.map(c => c.split(' ')));\n this.forEach(el => {\n el.classList.remove(...classNames);\n });\n return this;\n }\n\n function toggleClass() {\n for (var _len3 = arguments.length, classes = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n classes[_key3] = arguments[_key3];\n }\n\n const classNames = arrayFlat(classes.map(c => c.split(' ')));\n this.forEach(el => {\n classNames.forEach(className => {\n el.classList.toggle(className);\n });\n });\n }\n\n function hasClass() {\n for (var _len4 = arguments.length, classes = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n classes[_key4] = arguments[_key4];\n }\n\n const classNames = arrayFlat(classes.map(c => c.split(' ')));\n return arrayFilter(this, el => {\n return classNames.filter(className => el.classList.contains(className)).length > 0;\n }).length > 0;\n }\n\n function attr(attrs, value) {\n if (arguments.length === 1 && typeof attrs === 'string') {\n // Get attr\n if (this[0]) return this[0].getAttribute(attrs);\n return undefined;\n } // Set attrs\n\n\n for (let i = 0; i < this.length; i += 1) {\n if (arguments.length === 2) {\n // String\n this[i].setAttribute(attrs, value);\n } else {\n // Object\n for (const attrName in attrs) {\n this[i][attrName] = attrs[attrName];\n this[i].setAttribute(attrName, attrs[attrName]);\n }\n }\n }\n\n return this;\n }\n\n function removeAttr(attr) {\n for (let i = 0; i < this.length; i += 1) {\n this[i].removeAttribute(attr);\n }\n\n return this;\n }\n\n function transform(transform) {\n for (let i = 0; i < this.length; i += 1) {\n this[i].style.transform = transform;\n }\n\n return this;\n }\n\n function transition$1(duration) {\n for (let i = 0; i < this.length; i += 1) {\n this[i].style.transitionDuration = typeof duration !== 'string' ? `${duration}ms` : duration;\n }\n\n return this;\n }\n\n function on() {\n for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {\n args[_key5] = arguments[_key5];\n }\n\n let [eventType, targetSelector, listener, capture] = args;\n\n if (typeof args[1] === 'function') {\n [eventType, listener, capture] = args;\n targetSelector = undefined;\n }\n\n if (!capture) capture = false;\n\n function handleLiveEvent(e) {\n const target = e.target;\n if (!target) return;\n const eventData = e.target.dom7EventData || [];\n\n if (eventData.indexOf(e) < 0) {\n eventData.unshift(e);\n }\n\n if ($(target).is(targetSelector)) listener.apply(target, eventData);else {\n const parents = $(target).parents(); // eslint-disable-line\n\n for (let k = 0; k < parents.length; k += 1) {\n if ($(parents[k]).is(targetSelector)) listener.apply(parents[k], eventData);\n }\n }\n }\n\n function handleEvent(e) {\n const eventData = e && e.target ? e.target.dom7EventData || [] : [];\n\n if (eventData.indexOf(e) < 0) {\n eventData.unshift(e);\n }\n\n listener.apply(this, eventData);\n }\n\n const events = eventType.split(' ');\n let j;\n\n for (let i = 0; i < this.length; i += 1) {\n const el = this[i];\n\n if (!targetSelector) {\n for (j = 0; j < events.length; j += 1) {\n const event = events[j];\n if (!el.dom7Listeners) el.dom7Listeners = {};\n if (!el.dom7Listeners[event]) el.dom7Listeners[event] = [];\n el.dom7Listeners[event].push({\n listener,\n proxyListener: handleEvent\n });\n el.addEventListener(event, handleEvent, capture);\n }\n } else {\n // Live events\n for (j = 0; j < events.length; j += 1) {\n const event = events[j];\n if (!el.dom7LiveListeners) el.dom7LiveListeners = {};\n if (!el.dom7LiveListeners[event]) el.dom7LiveListeners[event] = [];\n el.dom7LiveListeners[event].push({\n listener,\n proxyListener: handleLiveEvent\n });\n el.addEventListener(event, handleLiveEvent, capture);\n }\n }\n }\n\n return this;\n }\n\n function off() {\n for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {\n args[_key6] = arguments[_key6];\n }\n\n let [eventType, targetSelector, listener, capture] = args;\n\n if (typeof args[1] === 'function') {\n [eventType, listener, capture] = args;\n targetSelector = undefined;\n }\n\n if (!capture) capture = false;\n const events = eventType.split(' ');\n\n for (let i = 0; i < events.length; i += 1) {\n const event = events[i];\n\n for (let j = 0; j < this.length; j += 1) {\n const el = this[j];\n let handlers;\n\n if (!targetSelector && el.dom7Listeners) {\n handlers = el.dom7Listeners[event];\n } else if (targetSelector && el.dom7LiveListeners) {\n handlers = el.dom7LiveListeners[event];\n }\n\n if (handlers && handlers.length) {\n for (let k = handlers.length - 1; k >= 0; k -= 1) {\n const handler = handlers[k];\n\n if (listener && handler.listener === listener) {\n el.removeEventListener(event, handler.proxyListener, capture);\n handlers.splice(k, 1);\n } else if (listener && handler.listener && handler.listener.dom7proxy && handler.listener.dom7proxy === listener) {\n el.removeEventListener(event, handler.proxyListener, capture);\n handlers.splice(k, 1);\n } else if (!listener) {\n el.removeEventListener(event, handler.proxyListener, capture);\n handlers.splice(k, 1);\n }\n }\n }\n }\n }\n\n return this;\n }\n\n function trigger() {\n const window = getWindow();\n\n for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {\n args[_key9] = arguments[_key9];\n }\n\n const events = args[0].split(' ');\n const eventData = args[1];\n\n for (let i = 0; i < events.length; i += 1) {\n const event = events[i];\n\n for (let j = 0; j < this.length; j += 1) {\n const el = this[j];\n\n if (window.CustomEvent) {\n const evt = new window.CustomEvent(event, {\n detail: eventData,\n bubbles: true,\n cancelable: true\n });\n el.dom7EventData = args.filter((data, dataIndex) => dataIndex > 0);\n el.dispatchEvent(evt);\n el.dom7EventData = [];\n delete el.dom7EventData;\n }\n }\n }\n\n return this;\n }\n\n function transitionEnd$1(callback) {\n const dom = this;\n\n function fireCallBack(e) {\n if (e.target !== this) return;\n callback.call(this, e);\n dom.off('transitionend', fireCallBack);\n }\n\n if (callback) {\n dom.on('transitionend', fireCallBack);\n }\n\n return this;\n }\n\n function outerWidth(includeMargins) {\n if (this.length > 0) {\n if (includeMargins) {\n const styles = this.styles();\n return this[0].offsetWidth + parseFloat(styles.getPropertyValue('margin-right')) + parseFloat(styles.getPropertyValue('margin-left'));\n }\n\n return this[0].offsetWidth;\n }\n\n return null;\n }\n\n function outerHeight(includeMargins) {\n if (this.length > 0) {\n if (includeMargins) {\n const styles = this.styles();\n return this[0].offsetHeight + parseFloat(styles.getPropertyValue('margin-top')) + parseFloat(styles.getPropertyValue('margin-bottom'));\n }\n\n return this[0].offsetHeight;\n }\n\n return null;\n }\n\n function offset() {\n if (this.length > 0) {\n const window = getWindow();\n const document = getDocument();\n const el = this[0];\n const box = el.getBoundingClientRect();\n const body = document.body;\n const clientTop = el.clientTop || body.clientTop || 0;\n const clientLeft = el.clientLeft || body.clientLeft || 0;\n const scrollTop = el === window ? window.scrollY : el.scrollTop;\n const scrollLeft = el === window ? window.scrollX : el.scrollLeft;\n return {\n top: box.top + scrollTop - clientTop,\n left: box.left + scrollLeft - clientLeft\n };\n }\n\n return null;\n }\n\n function styles() {\n const window = getWindow();\n if (this[0]) return window.getComputedStyle(this[0], null);\n return {};\n }\n\n function css(props, value) {\n const window = getWindow();\n let i;\n\n if (arguments.length === 1) {\n if (typeof props === 'string') {\n // .css('width')\n if (this[0]) return window.getComputedStyle(this[0], null).getPropertyValue(props);\n } else {\n // .css({ width: '100px' })\n for (i = 0; i < this.length; i += 1) {\n for (const prop in props) {\n this[i].style[prop] = props[prop];\n }\n }\n\n return this;\n }\n }\n\n if (arguments.length === 2 && typeof props === 'string') {\n // .css('width', '100px')\n for (i = 0; i < this.length; i += 1) {\n this[i].style[props] = value;\n }\n\n return this;\n }\n\n return this;\n }\n\n function each(callback) {\n if (!callback) return this;\n this.forEach((el, index) => {\n callback.apply(el, [el, index]);\n });\n return this;\n }\n\n function filter(callback) {\n const result = arrayFilter(this, callback);\n return $(result);\n }\n\n function html(html) {\n if (typeof html === 'undefined') {\n return this[0] ? this[0].innerHTML : null;\n }\n\n for (let i = 0; i < this.length; i += 1) {\n this[i].innerHTML = html;\n }\n\n return this;\n }\n\n function text(text) {\n if (typeof text === 'undefined') {\n return this[0] ? this[0].textContent.trim() : null;\n }\n\n for (let i = 0; i < this.length; i += 1) {\n this[i].textContent = text;\n }\n\n return this;\n }\n\n function is(selector) {\n const window = getWindow();\n const document = getDocument();\n const el = this[0];\n let compareWith;\n let i;\n if (!el || typeof selector === 'undefined') return false;\n\n if (typeof selector === 'string') {\n if (el.matches) return el.matches(selector);\n if (el.webkitMatchesSelector) return el.webkitMatchesSelector(selector);\n if (el.msMatchesSelector) return el.msMatchesSelector(selector);\n compareWith = $(selector);\n\n for (i = 0; i < compareWith.length; i += 1) {\n if (compareWith[i] === el) return true;\n }\n\n return false;\n }\n\n if (selector === document) {\n return el === document;\n }\n\n if (selector === window) {\n return el === window;\n }\n\n if (selector.nodeType || selector instanceof Dom7) {\n compareWith = selector.nodeType ? [selector] : selector;\n\n for (i = 0; i < compareWith.length; i += 1) {\n if (compareWith[i] === el) return true;\n }\n\n return false;\n }\n\n return false;\n }\n\n function index() {\n let child = this[0];\n let i;\n\n if (child) {\n i = 0; // eslint-disable-next-line\n\n while ((child = child.previousSibling) !== null) {\n if (child.nodeType === 1) i += 1;\n }\n\n return i;\n }\n\n return undefined;\n }\n\n function eq(index) {\n if (typeof index === 'undefined') return this;\n const length = this.length;\n\n if (index > length - 1) {\n return $([]);\n }\n\n if (index < 0) {\n const returnIndex = length + index;\n if (returnIndex < 0) return $([]);\n return $([this[returnIndex]]);\n }\n\n return $([this[index]]);\n }\n\n function append() {\n let newChild;\n const document = getDocument();\n\n for (let k = 0; k < arguments.length; k += 1) {\n newChild = k < 0 || arguments.length <= k ? undefined : arguments[k];\n\n for (let i = 0; i < this.length; i += 1) {\n if (typeof newChild === 'string') {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = newChild;\n\n while (tempDiv.firstChild) {\n this[i].appendChild(tempDiv.firstChild);\n }\n } else if (newChild instanceof Dom7) {\n for (let j = 0; j < newChild.length; j += 1) {\n this[i].appendChild(newChild[j]);\n }\n } else {\n this[i].appendChild(newChild);\n }\n }\n }\n\n return this;\n }\n\n function prepend(newChild) {\n const document = getDocument();\n let i;\n let j;\n\n for (i = 0; i < this.length; i += 1) {\n if (typeof newChild === 'string') {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = newChild;\n\n for (j = tempDiv.childNodes.length - 1; j >= 0; j -= 1) {\n this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]);\n }\n } else if (newChild instanceof Dom7) {\n for (j = 0; j < newChild.length; j += 1) {\n this[i].insertBefore(newChild[j], this[i].childNodes[0]);\n }\n } else {\n this[i].insertBefore(newChild, this[i].childNodes[0]);\n }\n }\n\n return this;\n }\n\n function next(selector) {\n if (this.length > 0) {\n if (selector) {\n if (this[0].nextElementSibling && $(this[0].nextElementSibling).is(selector)) {\n return $([this[0].nextElementSibling]);\n }\n\n return $([]);\n }\n\n if (this[0].nextElementSibling) return $([this[0].nextElementSibling]);\n return $([]);\n }\n\n return $([]);\n }\n\n function nextAll(selector) {\n const nextEls = [];\n let el = this[0];\n if (!el) return $([]);\n\n while (el.nextElementSibling) {\n const next = el.nextElementSibling; // eslint-disable-line\n\n if (selector) {\n if ($(next).is(selector)) nextEls.push(next);\n } else nextEls.push(next);\n\n el = next;\n }\n\n return $(nextEls);\n }\n\n function prev(selector) {\n if (this.length > 0) {\n const el = this[0];\n\n if (selector) {\n if (el.previousElementSibling && $(el.previousElementSibling).is(selector)) {\n return $([el.previousElementSibling]);\n }\n\n return $([]);\n }\n\n if (el.previousElementSibling) return $([el.previousElementSibling]);\n return $([]);\n }\n\n return $([]);\n }\n\n function prevAll(selector) {\n const prevEls = [];\n let el = this[0];\n if (!el) return $([]);\n\n while (el.previousElementSibling) {\n const prev = el.previousElementSibling; // eslint-disable-line\n\n if (selector) {\n if ($(prev).is(selector)) prevEls.push(prev);\n } else prevEls.push(prev);\n\n el = prev;\n }\n\n return $(prevEls);\n }\n\n function parent(selector) {\n const parents = []; // eslint-disable-line\n\n for (let i = 0; i < this.length; i += 1) {\n if (this[i].parentNode !== null) {\n if (selector) {\n if ($(this[i].parentNode).is(selector)) parents.push(this[i].parentNode);\n } else {\n parents.push(this[i].parentNode);\n }\n }\n }\n\n return $(parents);\n }\n\n function parents(selector) {\n const parents = []; // eslint-disable-line\n\n for (let i = 0; i < this.length; i += 1) {\n let parent = this[i].parentNode; // eslint-disable-line\n\n while (parent) {\n if (selector) {\n if ($(parent).is(selector)) parents.push(parent);\n } else {\n parents.push(parent);\n }\n\n parent = parent.parentNode;\n }\n }\n\n return $(parents);\n }\n\n function closest(selector) {\n let closest = this; // eslint-disable-line\n\n if (typeof selector === 'undefined') {\n return $([]);\n }\n\n if (!closest.is(selector)) {\n closest = closest.parents(selector).eq(0);\n }\n\n return closest;\n }\n\n function find(selector) {\n const foundElements = [];\n\n for (let i = 0; i < this.length; i += 1) {\n const found = this[i].querySelectorAll(selector);\n\n for (let j = 0; j < found.length; j += 1) {\n foundElements.push(found[j]);\n }\n }\n\n return $(foundElements);\n }\n\n function children(selector) {\n const children = []; // eslint-disable-line\n\n for (let i = 0; i < this.length; i += 1) {\n const childNodes = this[i].children;\n\n for (let j = 0; j < childNodes.length; j += 1) {\n if (!selector || $(childNodes[j]).is(selector)) {\n children.push(childNodes[j]);\n }\n }\n }\n\n return $(children);\n }\n\n function remove() {\n for (let i = 0; i < this.length; i += 1) {\n if (this[i].parentNode) this[i].parentNode.removeChild(this[i]);\n }\n\n return this;\n }\n\n const Methods = {\n addClass,\n removeClass,\n hasClass,\n toggleClass,\n attr,\n removeAttr,\n transform,\n transition: transition$1,\n on,\n off,\n trigger,\n transitionEnd: transitionEnd$1,\n outerWidth,\n outerHeight,\n styles,\n offset,\n css,\n each,\n html,\n text,\n is,\n index,\n eq,\n append,\n prepend,\n next,\n nextAll,\n prev,\n prevAll,\n parent,\n parents,\n closest,\n find,\n children,\n filter,\n remove\n };\n Object.keys(Methods).forEach(methodName => {\n Object.defineProperty($.fn, methodName, {\n value: Methods[methodName],\n writable: true\n });\n });\n\n function deleteProps(obj) {\n const object = obj;\n Object.keys(object).forEach(key => {\n try {\n object[key] = null;\n } catch (e) {// no getter for object\n }\n\n try {\n delete object[key];\n } catch (e) {// something got wrong\n }\n });\n }\n\n function nextTick(callback, delay) {\n if (delay === void 0) {\n delay = 0;\n }\n\n return setTimeout(callback, delay);\n }\n\n function now() {\n return Date.now();\n }\n\n function getComputedStyle$1(el) {\n const window = getWindow();\n let style;\n\n if (window.getComputedStyle) {\n style = window.getComputedStyle(el, null);\n }\n\n if (!style && el.currentStyle) {\n style = el.currentStyle;\n }\n\n if (!style) {\n style = el.style;\n }\n\n return style;\n }\n\n function getTranslate(el, axis) {\n if (axis === void 0) {\n axis = 'x';\n }\n\n const window = getWindow();\n let matrix;\n let curTransform;\n let transformMatrix;\n const curStyle = getComputedStyle$1(el);\n\n if (window.WebKitCSSMatrix) {\n curTransform = curStyle.transform || curStyle.webkitTransform;\n\n if (curTransform.split(',').length > 6) {\n curTransform = curTransform.split(', ').map(a => a.replace(',', '.')).join(', ');\n } // Some old versions of Webkit choke when 'none' is passed; pass\n // empty string instead in this case\n\n\n transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);\n } else {\n transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');\n matrix = transformMatrix.toString().split(',');\n }\n\n if (axis === 'x') {\n // Latest Chrome and webkits Fix\n if (window.WebKitCSSMatrix) curTransform = transformMatrix.m41; // Crazy IE10 Matrix\n else if (matrix.length === 16) curTransform = parseFloat(matrix[12]); // Normal Browsers\n else curTransform = parseFloat(matrix[4]);\n }\n\n if (axis === 'y') {\n // Latest Chrome and webkits Fix\n if (window.WebKitCSSMatrix) curTransform = transformMatrix.m42; // Crazy IE10 Matrix\n else if (matrix.length === 16) curTransform = parseFloat(matrix[13]); // Normal Browsers\n else curTransform = parseFloat(matrix[5]);\n }\n\n return curTransform || 0;\n }\n\n function isObject(o) {\n return typeof o === 'object' && o !== null && o.constructor && Object.prototype.toString.call(o).slice(8, -1) === 'Object';\n }\n\n function isNode(node) {\n // eslint-disable-next-line\n if (typeof window !== 'undefined' && typeof window.HTMLElement !== 'undefined') {\n return node instanceof HTMLElement;\n }\n\n return node && (node.nodeType === 1 || node.nodeType === 11);\n }\n\n function extend() {\n const to = Object(arguments.length <= 0 ? undefined : arguments[0]);\n const noExtend = ['__proto__', 'constructor', 'prototype'];\n\n for (let i = 1; i < arguments.length; i += 1) {\n const nextSource = i < 0 || arguments.length <= i ? undefined : arguments[i];\n\n if (nextSource !== undefined && nextSource !== null && !isNode(nextSource)) {\n const keysArray = Object.keys(Object(nextSource)).filter(key => noExtend.indexOf(key) < 0);\n\n for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) {\n const nextKey = keysArray[nextIndex];\n const desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);\n\n if (desc !== undefined && desc.enumerable) {\n if (isObject(to[nextKey]) && isObject(nextSource[nextKey])) {\n if (nextSource[nextKey].__swiper__) {\n to[nextKey] = nextSource[nextKey];\n } else {\n extend(to[nextKey], nextSource[nextKey]);\n }\n } else if (!isObject(to[nextKey]) && isObject(nextSource[nextKey])) {\n to[nextKey] = {};\n\n if (nextSource[nextKey].__swiper__) {\n to[nextKey] = nextSource[nextKey];\n } else {\n extend(to[nextKey], nextSource[nextKey]);\n }\n } else {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n }\n\n return to;\n }\n\n function setCSSProperty(el, varName, varValue) {\n el.style.setProperty(varName, varValue);\n }\n\n function animateCSSModeScroll(_ref) {\n let {\n swiper,\n targetPosition,\n side\n } = _ref;\n const window = getWindow();\n const startPosition = -swiper.translate;\n let startTime = null;\n let time;\n const duration = swiper.params.speed;\n swiper.wrapperEl.style.scrollSnapType = 'none';\n window.cancelAnimationFrame(swiper.cssModeFrameID);\n const dir = targetPosition > startPosition ? 'next' : 'prev';\n\n const isOutOfBound = (current, target) => {\n return dir === 'next' && current >= target || dir === 'prev' && current <= target;\n };\n\n const animate = () => {\n time = new Date().getTime();\n\n if (startTime === null) {\n startTime = time;\n }\n\n const progress = Math.max(Math.min((time - startTime) / duration, 1), 0);\n const easeProgress = 0.5 - Math.cos(progress * Math.PI) / 2;\n let currentPosition = startPosition + easeProgress * (targetPosition - startPosition);\n\n if (isOutOfBound(currentPosition, targetPosition)) {\n currentPosition = targetPosition;\n }\n\n swiper.wrapperEl.scrollTo({\n [side]: currentPosition\n });\n\n if (isOutOfBound(currentPosition, targetPosition)) {\n swiper.wrapperEl.style.overflow = 'hidden';\n swiper.wrapperEl.style.scrollSnapType = '';\n setTimeout(() => {\n swiper.wrapperEl.style.overflow = '';\n swiper.wrapperEl.scrollTo({\n [side]: currentPosition\n });\n });\n window.cancelAnimationFrame(swiper.cssModeFrameID);\n return;\n }\n\n swiper.cssModeFrameID = window.requestAnimationFrame(animate);\n };\n\n animate();\n }\n\n let support;\n\n function calcSupport() {\n const window = getWindow();\n const document = getDocument();\n return {\n smoothScroll: document.documentElement && 'scrollBehavior' in document.documentElement.style,\n touch: !!('ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch),\n passiveListener: function checkPassiveListener() {\n let supportsPassive = false;\n\n try {\n const opts = Object.defineProperty({}, 'passive', {\n // eslint-disable-next-line\n get() {\n supportsPassive = true;\n }\n\n });\n window.addEventListener('testPassiveListener', null, opts);\n } catch (e) {// No support\n }\n\n return supportsPassive;\n }(),\n gestures: function checkGestures() {\n return 'ongesturestart' in window;\n }()\n };\n }\n\n function getSupport() {\n if (!support) {\n support = calcSupport();\n }\n\n return support;\n }\n\n let deviceCached;\n\n function calcDevice(_temp) {\n let {\n userAgent\n } = _temp === void 0 ? {} : _temp;\n const support = getSupport();\n const window = getWindow();\n const platform = window.navigator.platform;\n const ua = userAgent || window.navigator.userAgent;\n const device = {\n ios: false,\n android: false\n };\n const screenWidth = window.screen.width;\n const screenHeight = window.screen.height;\n const android = ua.match(/(Android);?[\\s\\/]+([\\d.]+)?/); // eslint-disable-line\n\n let ipad = ua.match(/(iPad).*OS\\s([\\d_]+)/);\n const ipod = ua.match(/(iPod)(.*OS\\s([\\d_]+))?/);\n const iphone = !ipad && ua.match(/(iPhone\\sOS|iOS)\\s([\\d_]+)/);\n const windows = platform === 'Win32';\n let macos = platform === 'MacIntel'; // iPadOs 13 fix\n\n const iPadScreens = ['1024x1366', '1366x1024', '834x1194', '1194x834', '834x1112', '1112x834', '768x1024', '1024x768', '820x1180', '1180x820', '810x1080', '1080x810'];\n\n if (!ipad && macos && support.touch && iPadScreens.indexOf(`${screenWidth}x${screenHeight}`) >= 0) {\n ipad = ua.match(/(Version)\\/([\\d.]+)/);\n if (!ipad) ipad = [0, 1, '13_0_0'];\n macos = false;\n } // Android\n\n\n if (android && !windows) {\n device.os = 'android';\n device.android = true;\n }\n\n if (ipad || iphone || ipod) {\n device.os = 'ios';\n device.ios = true;\n } // Export object\n\n\n return device;\n }\n\n function getDevice(overrides) {\n if (overrides === void 0) {\n overrides = {};\n }\n\n if (!deviceCached) {\n deviceCached = calcDevice(overrides);\n }\n\n return deviceCached;\n }\n\n let browser;\n\n function calcBrowser() {\n const window = getWindow();\n\n function isSafari() {\n const ua = window.navigator.userAgent.toLowerCase();\n return ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0;\n }\n\n return {\n isSafari: isSafari(),\n isWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(window.navigator.userAgent)\n };\n }\n\n function getBrowser() {\n if (!browser) {\n browser = calcBrowser();\n }\n\n return browser;\n }\n\n function Resize(_ref) {\n let {\n swiper,\n on,\n emit\n } = _ref;\n const window = getWindow();\n let observer = null;\n let animationFrame = null;\n\n const resizeHandler = () => {\n if (!swiper || swiper.destroyed || !swiper.initialized) return;\n emit('beforeResize');\n emit('resize');\n };\n\n const createObserver = () => {\n if (!swiper || swiper.destroyed || !swiper.initialized) return;\n observer = new ResizeObserver(entries => {\n animationFrame = window.requestAnimationFrame(() => {\n const {\n width,\n height\n } = swiper;\n let newWidth = width;\n let newHeight = height;\n entries.forEach(_ref2 => {\n let {\n contentBoxSize,\n contentRect,\n target\n } = _ref2;\n if (target && target !== swiper.el) return;\n newWidth = contentRect ? contentRect.width : (contentBoxSize[0] || contentBoxSize).inlineSize;\n newHeight = contentRect ? contentRect.height : (contentBoxSize[0] || contentBoxSize).blockSize;\n });\n\n if (newWidth !== width || newHeight !== height) {\n resizeHandler();\n }\n });\n });\n observer.observe(swiper.el);\n };\n\n const removeObserver = () => {\n if (animationFrame) {\n window.cancelAnimationFrame(animationFrame);\n }\n\n if (observer && observer.unobserve && swiper.el) {\n observer.unobserve(swiper.el);\n observer = null;\n }\n };\n\n const orientationChangeHandler = () => {\n if (!swiper || swiper.destroyed || !swiper.initialized) return;\n emit('orientationchange');\n };\n\n on('init', () => {\n if (swiper.params.resizeObserver && typeof window.ResizeObserver !== 'undefined') {\n createObserver();\n return;\n }\n\n window.addEventListener('resize', resizeHandler);\n window.addEventListener('orientationchange', orientationChangeHandler);\n });\n on('destroy', () => {\n removeObserver();\n window.removeEventListener('resize', resizeHandler);\n window.removeEventListener('orientationchange', orientationChangeHandler);\n });\n }\n\n function Observer(_ref) {\n let {\n swiper,\n extendParams,\n on,\n emit\n } = _ref;\n const observers = [];\n const window = getWindow();\n\n const attach = function (target, options) {\n if (options === void 0) {\n options = {};\n }\n\n const ObserverFunc = window.MutationObserver || window.WebkitMutationObserver;\n const observer = new ObserverFunc(mutations => {\n // The observerUpdate event should only be triggered\n // once despite the number of mutations. Additional\n // triggers are redundant and are very costly\n if (mutations.length === 1) {\n emit('observerUpdate', mutations[0]);\n return;\n }\n\n const observerUpdate = function observerUpdate() {\n emit('observerUpdate', mutations[0]);\n };\n\n if (window.requestAnimationFrame) {\n window.requestAnimationFrame(observerUpdate);\n } else {\n window.setTimeout(observerUpdate, 0);\n }\n });\n observer.observe(target, {\n attributes: typeof options.attributes === 'undefined' ? true : options.attributes,\n childList: typeof options.childList === 'undefined' ? true : options.childList,\n characterData: typeof options.characterData === 'undefined' ? true : options.characterData\n });\n observers.push(observer);\n };\n\n const init = () => {\n if (!swiper.params.observer) return;\n\n if (swiper.params.observeParents) {\n const containerParents = swiper.$el.parents();\n\n for (let i = 0; i < containerParents.length; i += 1) {\n attach(containerParents[i]);\n }\n } // Observe container\n\n\n attach(swiper.$el[0], {\n childList: swiper.params.observeSlideChildren\n }); // Observe wrapper\n\n attach(swiper.$wrapperEl[0], {\n attributes: false\n });\n };\n\n const destroy = () => {\n observers.forEach(observer => {\n observer.disconnect();\n });\n observers.splice(0, observers.length);\n };\n\n extendParams({\n observer: false,\n observeParents: false,\n observeSlideChildren: false\n });\n on('init', init);\n on('destroy', destroy);\n }\n\n /* eslint-disable no-underscore-dangle */\n var eventsEmitter = {\n on(events, handler, priority) {\n const self = this;\n if (typeof handler !== 'function') return self;\n const method = priority ? 'unshift' : 'push';\n events.split(' ').forEach(event => {\n if (!self.eventsListeners[event]) self.eventsListeners[event] = [];\n self.eventsListeners[event][method](handler);\n });\n return self;\n },\n\n once(events, handler, priority) {\n const self = this;\n if (typeof handler !== 'function') return self;\n\n function onceHandler() {\n self.off(events, onceHandler);\n\n if (onceHandler.__emitterProxy) {\n delete onceHandler.__emitterProxy;\n }\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n handler.apply(self, args);\n }\n\n onceHandler.__emitterProxy = handler;\n return self.on(events, onceHandler, priority);\n },\n\n onAny(handler, priority) {\n const self = this;\n if (typeof handler !== 'function') return self;\n const method = priority ? 'unshift' : 'push';\n\n if (self.eventsAnyListeners.indexOf(handler) < 0) {\n self.eventsAnyListeners[method](handler);\n }\n\n return self;\n },\n\n offAny(handler) {\n const self = this;\n if (!self.eventsAnyListeners) return self;\n const index = self.eventsAnyListeners.indexOf(handler);\n\n if (index >= 0) {\n self.eventsAnyListeners.splice(index, 1);\n }\n\n return self;\n },\n\n off(events, handler) {\n const self = this;\n if (!self.eventsListeners) return self;\n events.split(' ').forEach(event => {\n if (typeof handler === 'undefined') {\n self.eventsListeners[event] = [];\n } else if (self.eventsListeners[event]) {\n self.eventsListeners[event].forEach((eventHandler, index) => {\n if (eventHandler === handler || eventHandler.__emitterProxy && eventHandler.__emitterProxy === handler) {\n self.eventsListeners[event].splice(index, 1);\n }\n });\n }\n });\n return self;\n },\n\n emit() {\n const self = this;\n if (!self.eventsListeners) return self;\n let events;\n let data;\n let context;\n\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n\n if (typeof args[0] === 'string' || Array.isArray(args[0])) {\n events = args[0];\n data = args.slice(1, args.length);\n context = self;\n } else {\n events = args[0].events;\n data = args[0].data;\n context = args[0].context || self;\n }\n\n data.unshift(context);\n const eventsArray = Array.isArray(events) ? events : events.split(' ');\n eventsArray.forEach(event => {\n if (self.eventsAnyListeners && self.eventsAnyListeners.length) {\n self.eventsAnyListeners.forEach(eventHandler => {\n eventHandler.apply(context, [event, ...data]);\n });\n }\n\n if (self.eventsListeners && self.eventsListeners[event]) {\n self.eventsListeners[event].forEach(eventHandler => {\n eventHandler.apply(context, data);\n });\n }\n });\n return self;\n }\n\n };\n\n function updateSize() {\n const swiper = this;\n let width;\n let height;\n const $el = swiper.$el;\n\n if (typeof swiper.params.width !== 'undefined' && swiper.params.width !== null) {\n width = swiper.params.width;\n } else {\n width = $el[0].clientWidth;\n }\n\n if (typeof swiper.params.height !== 'undefined' && swiper.params.height !== null) {\n height = swiper.params.height;\n } else {\n height = $el[0].clientHeight;\n }\n\n if (width === 0 && swiper.isHorizontal() || height === 0 && swiper.isVertical()) {\n return;\n } // Subtract paddings\n\n\n width = width - parseInt($el.css('padding-left') || 0, 10) - parseInt($el.css('padding-right') || 0, 10);\n height = height - parseInt($el.css('padding-top') || 0, 10) - parseInt($el.css('padding-bottom') || 0, 10);\n if (Number.isNaN(width)) width = 0;\n if (Number.isNaN(height)) height = 0;\n Object.assign(swiper, {\n width,\n height,\n size: swiper.isHorizontal() ? width : height\n });\n }\n\n function updateSlides() {\n const swiper = this;\n\n function getDirectionLabel(property) {\n if (swiper.isHorizontal()) {\n return property;\n } // prettier-ignore\n\n\n return {\n 'width': 'height',\n 'margin-top': 'margin-left',\n 'margin-bottom ': 'margin-right',\n 'margin-left': 'margin-top',\n 'margin-right': 'margin-bottom',\n 'padding-left': 'padding-top',\n 'padding-right': 'padding-bottom',\n 'marginRight': 'marginBottom'\n }[property];\n }\n\n function getDirectionPropertyValue(node, label) {\n return parseFloat(node.getPropertyValue(getDirectionLabel(label)) || 0);\n }\n\n const params = swiper.params;\n const {\n $wrapperEl,\n size: swiperSize,\n rtlTranslate: rtl,\n wrongRTL\n } = swiper;\n const isVirtual = swiper.virtual && params.virtual.enabled;\n const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length;\n const slides = $wrapperEl.children(`.${swiper.params.slideClass}`);\n const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length;\n let snapGrid = [];\n const slidesGrid = [];\n const slidesSizesGrid = [];\n let offsetBefore = params.slidesOffsetBefore;\n\n if (typeof offsetBefore === 'function') {\n offsetBefore = params.slidesOffsetBefore.call(swiper);\n }\n\n let offsetAfter = params.slidesOffsetAfter;\n\n if (typeof offsetAfter === 'function') {\n offsetAfter = params.slidesOffsetAfter.call(swiper);\n }\n\n const previousSnapGridLength = swiper.snapGrid.length;\n const previousSlidesGridLength = swiper.slidesGrid.length;\n let spaceBetween = params.spaceBetween;\n let slidePosition = -offsetBefore;\n let prevSlideSize = 0;\n let index = 0;\n\n if (typeof swiperSize === 'undefined') {\n return;\n }\n\n if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {\n spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiperSize;\n }\n\n swiper.virtualSize = -spaceBetween; // reset margins\n\n if (rtl) slides.css({\n marginLeft: '',\n marginBottom: '',\n marginTop: ''\n });else slides.css({\n marginRight: '',\n marginBottom: '',\n marginTop: ''\n }); // reset cssMode offsets\n\n if (params.centeredSlides && params.cssMode) {\n setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-before', '');\n setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-after', '');\n }\n\n const gridEnabled = params.grid && params.grid.rows > 1 && swiper.grid;\n\n if (gridEnabled) {\n swiper.grid.initSlides(slidesLength);\n } // Calc slides\n\n\n let slideSize;\n const shouldResetSlideSize = params.slidesPerView === 'auto' && params.breakpoints && Object.keys(params.breakpoints).filter(key => {\n return typeof params.breakpoints[key].slidesPerView !== 'undefined';\n }).length > 0;\n\n for (let i = 0; i < slidesLength; i += 1) {\n slideSize = 0;\n const slide = slides.eq(i);\n\n if (gridEnabled) {\n swiper.grid.updateSlide(i, slide, slidesLength, getDirectionLabel);\n }\n\n if (slide.css('display') === 'none') continue; // eslint-disable-line\n\n if (params.slidesPerView === 'auto') {\n if (shouldResetSlideSize) {\n slides[i].style[getDirectionLabel('width')] = ``;\n }\n\n const slideStyles = getComputedStyle(slide[0]);\n const currentTransform = slide[0].style.transform;\n const currentWebKitTransform = slide[0].style.webkitTransform;\n\n if (currentTransform) {\n slide[0].style.transform = 'none';\n }\n\n if (currentWebKitTransform) {\n slide[0].style.webkitTransform = 'none';\n }\n\n if (params.roundLengths) {\n slideSize = swiper.isHorizontal() ? slide.outerWidth(true) : slide.outerHeight(true);\n } else {\n // eslint-disable-next-line\n const width = getDirectionPropertyValue(slideStyles, 'width');\n const paddingLeft = getDirectionPropertyValue(slideStyles, 'padding-left');\n const paddingRight = getDirectionPropertyValue(slideStyles, 'padding-right');\n const marginLeft = getDirectionPropertyValue(slideStyles, 'margin-left');\n const marginRight = getDirectionPropertyValue(slideStyles, 'margin-right');\n const boxSizing = slideStyles.getPropertyValue('box-sizing');\n\n if (boxSizing && boxSizing === 'border-box') {\n slideSize = width + marginLeft + marginRight;\n } else {\n const {\n clientWidth,\n offsetWidth\n } = slide[0];\n slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight + (offsetWidth - clientWidth);\n }\n }\n\n if (currentTransform) {\n slide[0].style.transform = currentTransform;\n }\n\n if (currentWebKitTransform) {\n slide[0].style.webkitTransform = currentWebKitTransform;\n }\n\n if (params.roundLengths) slideSize = Math.floor(slideSize);\n } else {\n slideSize = (swiperSize - (params.slidesPerView - 1) * spaceBetween) / params.slidesPerView;\n if (params.roundLengths) slideSize = Math.floor(slideSize);\n\n if (slides[i]) {\n slides[i].style[getDirectionLabel('width')] = `${slideSize}px`;\n }\n }\n\n if (slides[i]) {\n slides[i].swiperSlideSize = slideSize;\n }\n\n slidesSizesGrid.push(slideSize);\n\n if (params.centeredSlides) {\n slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween;\n if (prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;\n if (i === 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;\n if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0;\n if (params.roundLengths) slidePosition = Math.floor(slidePosition);\n if (index % params.slidesPerGroup === 0) snapGrid.push(slidePosition);\n slidesGrid.push(slidePosition);\n } else {\n if (params.roundLengths) slidePosition = Math.floor(slidePosition);\n if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) snapGrid.push(slidePosition);\n slidesGrid.push(slidePosition);\n slidePosition = slidePosition + slideSize + spaceBetween;\n }\n\n swiper.virtualSize += slideSize + spaceBetween;\n prevSlideSize = slideSize;\n index += 1;\n }\n\n swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter;\n\n if (rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) {\n $wrapperEl.css({\n width: `${swiper.virtualSize + params.spaceBetween}px`\n });\n }\n\n if (params.setWrapperSize) {\n $wrapperEl.css({\n [getDirectionLabel('width')]: `${swiper.virtualSize + params.spaceBetween}px`\n });\n }\n\n if (gridEnabled) {\n swiper.grid.updateWrapperSize(slideSize, snapGrid, getDirectionLabel);\n } // Remove last grid elements depending on width\n\n\n if (!params.centeredSlides) {\n const newSlidesGrid = [];\n\n for (let i = 0; i < snapGrid.length; i += 1) {\n let slidesGridItem = snapGrid[i];\n if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);\n\n if (snapGrid[i] <= swiper.virtualSize - swiperSize) {\n newSlidesGrid.push(slidesGridItem);\n }\n }\n\n snapGrid = newSlidesGrid;\n\n if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {\n snapGrid.push(swiper.virtualSize - swiperSize);\n }\n }\n\n if (snapGrid.length === 0) snapGrid = [0];\n\n if (params.spaceBetween !== 0) {\n const key = swiper.isHorizontal() && rtl ? 'marginLeft' : getDirectionLabel('marginRight');\n slides.filter((_, slideIndex) => {\n if (!params.cssMode) return true;\n\n if (slideIndex === slides.length - 1) {\n return false;\n }\n\n return true;\n }).css({\n [key]: `${spaceBetween}px`\n });\n }\n\n if (params.centeredSlides && params.centeredSlidesBounds) {\n let allSlidesSize = 0;\n slidesSizesGrid.forEach(slideSizeValue => {\n allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);\n });\n allSlidesSize -= params.spaceBetween;\n const maxSnap = allSlidesSize - swiperSize;\n snapGrid = snapGrid.map(snap => {\n if (snap < 0) return -offsetBefore;\n if (snap > maxSnap) return maxSnap + offsetAfter;\n return snap;\n });\n }\n\n if (params.centerInsufficientSlides) {\n let allSlidesSize = 0;\n slidesSizesGrid.forEach(slideSizeValue => {\n allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);\n });\n allSlidesSize -= params.spaceBetween;\n\n if (allSlidesSize < swiperSize) {\n const allSlidesOffset = (swiperSize - allSlidesSize) / 2;\n snapGrid.forEach((snap, snapIndex) => {\n snapGrid[snapIndex] = snap - allSlidesOffset;\n });\n slidesGrid.forEach((snap, snapIndex) => {\n slidesGrid[snapIndex] = snap + allSlidesOffset;\n });\n }\n }\n\n Object.assign(swiper, {\n slides,\n snapGrid,\n slidesGrid,\n slidesSizesGrid\n });\n\n if (params.centeredSlides && params.cssMode && !params.centeredSlidesBounds) {\n setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-before', `${-snapGrid[0]}px`);\n setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-after', `${swiper.size / 2 - slidesSizesGrid[slidesSizesGrid.length - 1] / 2}px`);\n const addToSnapGrid = -swiper.snapGrid[0];\n const addToSlidesGrid = -swiper.slidesGrid[0];\n swiper.snapGrid = swiper.snapGrid.map(v => v + addToSnapGrid);\n swiper.slidesGrid = swiper.slidesGrid.map(v => v + addToSlidesGrid);\n }\n\n if (slidesLength !== previousSlidesLength) {\n swiper.emit('slidesLengthChange');\n }\n\n if (snapGrid.length !== previousSnapGridLength) {\n if (swiper.params.watchOverflow) swiper.checkOverflow();\n swiper.emit('snapGridLengthChange');\n }\n\n if (slidesGrid.length !== previousSlidesGridLength) {\n swiper.emit('slidesGridLengthChange');\n }\n\n if (params.watchSlidesProgress) {\n swiper.updateSlidesOffset();\n }\n\n if (!isVirtual && !params.cssMode && (params.effect === 'slide' || params.effect === 'fade')) {\n const backFaceHiddenClass = `${params.containerModifierClass}backface-hidden`;\n const hasClassBackfaceClassAdded = swiper.$el.hasClass(backFaceHiddenClass);\n\n if (slidesLength <= params.maxBackfaceHiddenSlides) {\n if (!hasClassBackfaceClassAdded) swiper.$el.addClass(backFaceHiddenClass);\n } else if (hasClassBackfaceClassAdded) {\n swiper.$el.removeClass(backFaceHiddenClass);\n }\n }\n }\n\n function updateAutoHeight(speed) {\n const swiper = this;\n const activeSlides = [];\n const isVirtual = swiper.virtual && swiper.params.virtual.enabled;\n let newHeight = 0;\n let i;\n\n if (typeof speed === 'number') {\n swiper.setTransition(speed);\n } else if (speed === true) {\n swiper.setTransition(swiper.params.speed);\n }\n\n const getSlideByIndex = index => {\n if (isVirtual) {\n return swiper.slides.filter(el => parseInt(el.getAttribute('data-swiper-slide-index'), 10) === index)[0];\n }\n\n return swiper.slides.eq(index)[0];\n }; // Find slides currently in view\n\n\n if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) {\n if (swiper.params.centeredSlides) {\n swiper.visibleSlides.each(slide => {\n activeSlides.push(slide);\n });\n } else {\n for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {\n const index = swiper.activeIndex + i;\n if (index > swiper.slides.length && !isVirtual) break;\n activeSlides.push(getSlideByIndex(index));\n }\n }\n } else {\n activeSlides.push(getSlideByIndex(swiper.activeIndex));\n } // Find new height from highest slide in view\n\n\n for (i = 0; i < activeSlides.length; i += 1) {\n if (typeof activeSlides[i] !== 'undefined') {\n const height = activeSlides[i].offsetHeight;\n newHeight = height > newHeight ? height : newHeight;\n }\n } // Update Height\n\n\n if (newHeight || newHeight === 0) swiper.$wrapperEl.css('height', `${newHeight}px`);\n }\n\n function updateSlidesOffset() {\n const swiper = this;\n const slides = swiper.slides;\n\n for (let i = 0; i < slides.length; i += 1) {\n slides[i].swiperSlideOffset = swiper.isHorizontal() ? slides[i].offsetLeft : slides[i].offsetTop;\n }\n }\n\n function updateSlidesProgress(translate) {\n if (translate === void 0) {\n translate = this && this.translate || 0;\n }\n\n const swiper = this;\n const params = swiper.params;\n const {\n slides,\n rtlTranslate: rtl,\n snapGrid\n } = swiper;\n if (slides.length === 0) return;\n if (typeof slides[0].swiperSlideOffset === 'undefined') swiper.updateSlidesOffset();\n let offsetCenter = -translate;\n if (rtl) offsetCenter = translate; // Visible Slides\n\n slides.removeClass(params.slideVisibleClass);\n swiper.visibleSlidesIndexes = [];\n swiper.visibleSlides = [];\n\n for (let i = 0; i < slides.length; i += 1) {\n const slide = slides[i];\n let slideOffset = slide.swiperSlideOffset;\n\n if (params.cssMode && params.centeredSlides) {\n slideOffset -= slides[0].swiperSlideOffset;\n }\n\n const slideProgress = (offsetCenter + (params.centeredSlides ? swiper.minTranslate() : 0) - slideOffset) / (slide.swiperSlideSize + params.spaceBetween);\n const originalSlideProgress = (offsetCenter - snapGrid[0] + (params.centeredSlides ? swiper.minTranslate() : 0) - slideOffset) / (slide.swiperSlideSize + params.spaceBetween);\n const slideBefore = -(offsetCenter - slideOffset);\n const slideAfter = slideBefore + swiper.slidesSizesGrid[i];\n const isVisible = slideBefore >= 0 && slideBefore < swiper.size - 1 || slideAfter > 1 && slideAfter <= swiper.size || slideBefore <= 0 && slideAfter >= swiper.size;\n\n if (isVisible) {\n swiper.visibleSlides.push(slide);\n swiper.visibleSlidesIndexes.push(i);\n slides.eq(i).addClass(params.slideVisibleClass);\n }\n\n slide.progress = rtl ? -slideProgress : slideProgress;\n slide.originalProgress = rtl ? -originalSlideProgress : originalSlideProgress;\n }\n\n swiper.visibleSlides = $(swiper.visibleSlides);\n }\n\n function updateProgress(translate) {\n const swiper = this;\n\n if (typeof translate === 'undefined') {\n const multiplier = swiper.rtlTranslate ? -1 : 1; // eslint-disable-next-line\n\n translate = swiper && swiper.translate && swiper.translate * multiplier || 0;\n }\n\n const params = swiper.params;\n const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();\n let {\n progress,\n isBeginning,\n isEnd\n } = swiper;\n const wasBeginning = isBeginning;\n const wasEnd = isEnd;\n\n if (translatesDiff === 0) {\n progress = 0;\n isBeginning = true;\n isEnd = true;\n } else {\n progress = (translate - swiper.minTranslate()) / translatesDiff;\n isBeginning = progress <= 0;\n isEnd = progress >= 1;\n }\n\n Object.assign(swiper, {\n progress,\n isBeginning,\n isEnd\n });\n if (params.watchSlidesProgress || params.centeredSlides && params.autoHeight) swiper.updateSlidesProgress(translate);\n\n if (isBeginning && !wasBeginning) {\n swiper.emit('reachBeginning toEdge');\n }\n\n if (isEnd && !wasEnd) {\n swiper.emit('reachEnd toEdge');\n }\n\n if (wasBeginning && !isBeginning || wasEnd && !isEnd) {\n swiper.emit('fromEdge');\n }\n\n swiper.emit('progress', progress);\n }\n\n function updateSlidesClasses() {\n const swiper = this;\n const {\n slides,\n params,\n $wrapperEl,\n activeIndex,\n realIndex\n } = swiper;\n const isVirtual = swiper.virtual && params.virtual.enabled;\n slides.removeClass(`${params.slideActiveClass} ${params.slideNextClass} ${params.slidePrevClass} ${params.slideDuplicateActiveClass} ${params.slideDuplicateNextClass} ${params.slideDuplicatePrevClass}`);\n let activeSlide;\n\n if (isVirtual) {\n activeSlide = swiper.$wrapperEl.find(`.${params.slideClass}[data-swiper-slide-index=\"${activeIndex}\"]`);\n } else {\n activeSlide = slides.eq(activeIndex);\n } // Active classes\n\n\n activeSlide.addClass(params.slideActiveClass);\n\n if (params.loop) {\n // Duplicate to all looped slides\n if (activeSlide.hasClass(params.slideDuplicateClass)) {\n $wrapperEl.children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index=\"${realIndex}\"]`).addClass(params.slideDuplicateActiveClass);\n } else {\n $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index=\"${realIndex}\"]`).addClass(params.slideDuplicateActiveClass);\n }\n } // Next Slide\n\n\n let nextSlide = activeSlide.nextAll(`.${params.slideClass}`).eq(0).addClass(params.slideNextClass);\n\n if (params.loop && nextSlide.length === 0) {\n nextSlide = slides.eq(0);\n nextSlide.addClass(params.slideNextClass);\n } // Prev Slide\n\n\n let prevSlide = activeSlide.prevAll(`.${params.slideClass}`).eq(0).addClass(params.slidePrevClass);\n\n if (params.loop && prevSlide.length === 0) {\n prevSlide = slides.eq(-1);\n prevSlide.addClass(params.slidePrevClass);\n }\n\n if (params.loop) {\n // Duplicate to all looped slides\n if (nextSlide.hasClass(params.slideDuplicateClass)) {\n $wrapperEl.children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index=\"${nextSlide.attr('data-swiper-slide-index')}\"]`).addClass(params.slideDuplicateNextClass);\n } else {\n $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index=\"${nextSlide.attr('data-swiper-slide-index')}\"]`).addClass(params.slideDuplicateNextClass);\n }\n\n if (prevSlide.hasClass(params.slideDuplicateClass)) {\n $wrapperEl.children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index=\"${prevSlide.attr('data-swiper-slide-index')}\"]`).addClass(params.slideDuplicatePrevClass);\n } else {\n $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index=\"${prevSlide.attr('data-swiper-slide-index')}\"]`).addClass(params.slideDuplicatePrevClass);\n }\n }\n\n swiper.emitSlidesClasses();\n }\n\n function updateActiveIndex(newActiveIndex) {\n const swiper = this;\n const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;\n const {\n slidesGrid,\n snapGrid,\n params,\n activeIndex: previousIndex,\n realIndex: previousRealIndex,\n snapIndex: previousSnapIndex\n } = swiper;\n let activeIndex = newActiveIndex;\n let snapIndex;\n\n if (typeof activeIndex === 'undefined') {\n for (let i = 0; i < slidesGrid.length; i += 1) {\n if (typeof slidesGrid[i + 1] !== 'undefined') {\n if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1] - (slidesGrid[i + 1] - slidesGrid[i]) / 2) {\n activeIndex = i;\n } else if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1]) {\n activeIndex = i + 1;\n }\n } else if (translate >= slidesGrid[i]) {\n activeIndex = i;\n }\n } // Normalize slideIndex\n\n\n if (params.normalizeSlideIndex) {\n if (activeIndex < 0 || typeof activeIndex === 'undefined') activeIndex = 0;\n }\n }\n\n if (snapGrid.indexOf(translate) >= 0) {\n snapIndex = snapGrid.indexOf(translate);\n } else {\n const skip = Math.min(params.slidesPerGroupSkip, activeIndex);\n snapIndex = skip + Math.floor((activeIndex - skip) / params.slidesPerGroup);\n }\n\n if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;\n\n if (activeIndex === previousIndex) {\n if (snapIndex !== previousSnapIndex) {\n swiper.snapIndex = snapIndex;\n swiper.emit('snapIndexChange');\n }\n\n return;\n } // Get real index\n\n\n const realIndex = parseInt(swiper.slides.eq(activeIndex).attr('data-swiper-slide-index') || activeIndex, 10);\n Object.assign(swiper, {\n snapIndex,\n realIndex,\n previousIndex,\n activeIndex\n });\n swiper.emit('activeIndexChange');\n swiper.emit('snapIndexChange');\n\n if (previousRealIndex !== realIndex) {\n swiper.emit('realIndexChange');\n }\n\n if (swiper.initialized || swiper.params.runCallbacksOnInit) {\n swiper.emit('slideChange');\n }\n }\n\n function updateClickedSlide(e) {\n const swiper = this;\n const params = swiper.params;\n const slide = $(e).closest(`.${params.slideClass}`)[0];\n let slideFound = false;\n let slideIndex;\n\n if (slide) {\n for (let i = 0; i < swiper.slides.length; i += 1) {\n if (swiper.slides[i] === slide) {\n slideFound = true;\n slideIndex = i;\n break;\n }\n }\n }\n\n if (slide && slideFound) {\n swiper.clickedSlide = slide;\n\n if (swiper.virtual && swiper.params.virtual.enabled) {\n swiper.clickedIndex = parseInt($(slide).attr('data-swiper-slide-index'), 10);\n } else {\n swiper.clickedIndex = slideIndex;\n }\n } else {\n swiper.clickedSlide = undefined;\n swiper.clickedIndex = undefined;\n return;\n }\n\n if (params.slideToClickedSlide && swiper.clickedIndex !== undefined && swiper.clickedIndex !== swiper.activeIndex) {\n swiper.slideToClickedSlide();\n }\n }\n\n var update = {\n updateSize,\n updateSlides,\n updateAutoHeight,\n updateSlidesOffset,\n updateSlidesProgress,\n updateProgress,\n updateSlidesClasses,\n updateActiveIndex,\n updateClickedSlide\n };\n\n function getSwiperTranslate(axis) {\n if (axis === void 0) {\n axis = this.isHorizontal() ? 'x' : 'y';\n }\n\n const swiper = this;\n const {\n params,\n rtlTranslate: rtl,\n translate,\n $wrapperEl\n } = swiper;\n\n if (params.virtualTranslate) {\n return rtl ? -translate : translate;\n }\n\n if (params.cssMode) {\n return translate;\n }\n\n let currentTranslate = getTranslate($wrapperEl[0], axis);\n if (rtl) currentTranslate = -currentTranslate;\n return currentTranslate || 0;\n }\n\n function setTranslate(translate, byController) {\n const swiper = this;\n const {\n rtlTranslate: rtl,\n params,\n $wrapperEl,\n wrapperEl,\n progress\n } = swiper;\n let x = 0;\n let y = 0;\n const z = 0;\n\n if (swiper.isHorizontal()) {\n x = rtl ? -translate : translate;\n } else {\n y = translate;\n }\n\n if (params.roundLengths) {\n x = Math.floor(x);\n y = Math.floor(y);\n }\n\n if (params.cssMode) {\n wrapperEl[swiper.isHorizontal() ? 'scrollLeft' : 'scrollTop'] = swiper.isHorizontal() ? -x : -y;\n } else if (!params.virtualTranslate) {\n $wrapperEl.transform(`translate3d(${x}px, ${y}px, ${z}px)`);\n }\n\n swiper.previousTranslate = swiper.translate;\n swiper.translate = swiper.isHorizontal() ? x : y; // Check if we need to update progress\n\n let newProgress;\n const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();\n\n if (translatesDiff === 0) {\n newProgress = 0;\n } else {\n newProgress = (translate - swiper.minTranslate()) / translatesDiff;\n }\n\n if (newProgress !== progress) {\n swiper.updateProgress(translate);\n }\n\n swiper.emit('setTranslate', swiper.translate, byController);\n }\n\n function minTranslate() {\n return -this.snapGrid[0];\n }\n\n function maxTranslate() {\n return -this.snapGrid[this.snapGrid.length - 1];\n }\n\n function translateTo(translate, speed, runCallbacks, translateBounds, internal) {\n if (translate === void 0) {\n translate = 0;\n }\n\n if (speed === void 0) {\n speed = this.params.speed;\n }\n\n if (runCallbacks === void 0) {\n runCallbacks = true;\n }\n\n if (translateBounds === void 0) {\n translateBounds = true;\n }\n\n const swiper = this;\n const {\n params,\n wrapperEl\n } = swiper;\n\n if (swiper.animating && params.preventInteractionOnTransition) {\n return false;\n }\n\n const minTranslate = swiper.minTranslate();\n const maxTranslate = swiper.maxTranslate();\n let newTranslate;\n if (translateBounds && translate > minTranslate) newTranslate = minTranslate;else if (translateBounds && translate < maxTranslate) newTranslate = maxTranslate;else newTranslate = translate; // Update progress\n\n swiper.updateProgress(newTranslate);\n\n if (params.cssMode) {\n const isH = swiper.isHorizontal();\n\n if (speed === 0) {\n wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -newTranslate;\n } else {\n if (!swiper.support.smoothScroll) {\n animateCSSModeScroll({\n swiper,\n targetPosition: -newTranslate,\n side: isH ? 'left' : 'top'\n });\n return true;\n }\n\n wrapperEl.scrollTo({\n [isH ? 'left' : 'top']: -newTranslate,\n behavior: 'smooth'\n });\n }\n\n return true;\n }\n\n if (speed === 0) {\n swiper.setTransition(0);\n swiper.setTranslate(newTranslate);\n\n if (runCallbacks) {\n swiper.emit('beforeTransitionStart', speed, internal);\n swiper.emit('transitionEnd');\n }\n } else {\n swiper.setTransition(speed);\n swiper.setTranslate(newTranslate);\n\n if (runCallbacks) {\n swiper.emit('beforeTransitionStart', speed, internal);\n swiper.emit('transitionStart');\n }\n\n if (!swiper.animating) {\n swiper.animating = true;\n\n if (!swiper.onTranslateToWrapperTransitionEnd) {\n swiper.onTranslateToWrapperTransitionEnd = function transitionEnd(e) {\n if (!swiper || swiper.destroyed) return;\n if (e.target !== this) return;\n swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);\n swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.onTranslateToWrapperTransitionEnd);\n swiper.onTranslateToWrapperTransitionEnd = null;\n delete swiper.onTranslateToWrapperTransitionEnd;\n\n if (runCallbacks) {\n swiper.emit('transitionEnd');\n }\n };\n }\n\n swiper.$wrapperEl[0].addEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);\n swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.onTranslateToWrapperTransitionEnd);\n }\n }\n\n return true;\n }\n\n var translate = {\n getTranslate: getSwiperTranslate,\n setTranslate,\n minTranslate,\n maxTranslate,\n translateTo\n };\n\n function setTransition(duration, byController) {\n const swiper = this;\n\n if (!swiper.params.cssMode) {\n swiper.$wrapperEl.transition(duration);\n }\n\n swiper.emit('setTransition', duration, byController);\n }\n\n function transitionEmit(_ref) {\n let {\n swiper,\n runCallbacks,\n direction,\n step\n } = _ref;\n const {\n activeIndex,\n previousIndex\n } = swiper;\n let dir = direction;\n\n if (!dir) {\n if (activeIndex > previousIndex) dir = 'next';else if (activeIndex < previousIndex) dir = 'prev';else dir = 'reset';\n }\n\n swiper.emit(`transition${step}`);\n\n if (runCallbacks && activeIndex !== previousIndex) {\n if (dir === 'reset') {\n swiper.emit(`slideResetTransition${step}`);\n return;\n }\n\n swiper.emit(`slideChangeTransition${step}`);\n\n if (dir === 'next') {\n swiper.emit(`slideNextTransition${step}`);\n } else {\n swiper.emit(`slidePrevTransition${step}`);\n }\n }\n }\n\n function transitionStart(runCallbacks, direction) {\n if (runCallbacks === void 0) {\n runCallbacks = true;\n }\n\n const swiper = this;\n const {\n params\n } = swiper;\n if (params.cssMode) return;\n\n if (params.autoHeight) {\n swiper.updateAutoHeight();\n }\n\n transitionEmit({\n swiper,\n runCallbacks,\n direction,\n step: 'Start'\n });\n }\n\n function transitionEnd(runCallbacks, direction) {\n if (runCallbacks === void 0) {\n runCallbacks = true;\n }\n\n const swiper = this;\n const {\n params\n } = swiper;\n swiper.animating = false;\n if (params.cssMode) return;\n swiper.setTransition(0);\n transitionEmit({\n swiper,\n runCallbacks,\n direction,\n step: 'End'\n });\n }\n\n var transition = {\n setTransition,\n transitionStart,\n transitionEnd\n };\n\n function slideTo(index, speed, runCallbacks, internal, initial) {\n if (index === void 0) {\n index = 0;\n }\n\n if (speed === void 0) {\n speed = this.params.speed;\n }\n\n if (runCallbacks === void 0) {\n runCallbacks = true;\n }\n\n if (typeof index !== 'number' && typeof index !== 'string') {\n throw new Error(`The 'index' argument cannot have type other than 'number' or 'string'. [${typeof index}] given.`);\n }\n\n if (typeof index === 'string') {\n /**\n * The `index` argument converted from `string` to `number`.\n * @type {number}\n */\n const indexAsNumber = parseInt(index, 10);\n /**\n * Determines whether the `index` argument is a valid `number`\n * after being converted from the `string` type.\n * @type {boolean}\n */\n\n const isValidNumber = isFinite(indexAsNumber);\n\n if (!isValidNumber) {\n throw new Error(`The passed-in 'index' (string) couldn't be converted to 'number'. [${index}] given.`);\n } // Knowing that the converted `index` is a valid number,\n // we can update the original argument's value.\n\n\n index = indexAsNumber;\n }\n\n const swiper = this;\n let slideIndex = index;\n if (slideIndex < 0) slideIndex = 0;\n const {\n params,\n snapGrid,\n slidesGrid,\n previousIndex,\n activeIndex,\n rtlTranslate: rtl,\n wrapperEl,\n enabled\n } = swiper;\n\n if (swiper.animating && params.preventInteractionOnTransition || !enabled && !internal && !initial) {\n return false;\n }\n\n const skip = Math.min(swiper.params.slidesPerGroupSkip, slideIndex);\n let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup);\n if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;\n\n if ((activeIndex || params.initialSlide || 0) === (previousIndex || 0) && runCallbacks) {\n swiper.emit('beforeSlideChangeStart');\n }\n\n const translate = -snapGrid[snapIndex]; // Update progress\n\n swiper.updateProgress(translate); // Normalize slideIndex\n\n if (params.normalizeSlideIndex) {\n for (let i = 0; i < slidesGrid.length; i += 1) {\n const normalizedTranslate = -Math.floor(translate * 100);\n const normalizedGrid = Math.floor(slidesGrid[i] * 100);\n const normalizedGridNext = Math.floor(slidesGrid[i + 1] * 100);\n\n if (typeof slidesGrid[i + 1] !== 'undefined') {\n if (normalizedTranslate >= normalizedGrid && normalizedTranslate < normalizedGridNext - (normalizedGridNext - normalizedGrid) / 2) {\n slideIndex = i;\n } else if (normalizedTranslate >= normalizedGrid && normalizedTranslate < normalizedGridNext) {\n slideIndex = i + 1;\n }\n } else if (normalizedTranslate >= normalizedGrid) {\n slideIndex = i;\n }\n }\n } // Directions locks\n\n\n if (swiper.initialized && slideIndex !== activeIndex) {\n if (!swiper.allowSlideNext && translate < swiper.translate && translate < swiper.minTranslate()) {\n return false;\n }\n\n if (!swiper.allowSlidePrev && translate > swiper.translate && translate > swiper.maxTranslate()) {\n if ((activeIndex || 0) !== slideIndex) return false;\n }\n }\n\n let direction;\n if (slideIndex > activeIndex) direction = 'next';else if (slideIndex < activeIndex) direction = 'prev';else direction = 'reset'; // Update Index\n\n if (rtl && -translate === swiper.translate || !rtl && translate === swiper.translate) {\n swiper.updateActiveIndex(slideIndex); // Update Height\n\n if (params.autoHeight) {\n swiper.updateAutoHeight();\n }\n\n swiper.updateSlidesClasses();\n\n if (params.effect !== 'slide') {\n swiper.setTranslate(translate);\n }\n\n if (direction !== 'reset') {\n swiper.transitionStart(runCallbacks, direction);\n swiper.transitionEnd(runCallbacks, direction);\n }\n\n return false;\n }\n\n if (params.cssMode) {\n const isH = swiper.isHorizontal();\n const t = rtl ? translate : -translate;\n\n if (speed === 0) {\n const isVirtual = swiper.virtual && swiper.params.virtual.enabled;\n\n if (isVirtual) {\n swiper.wrapperEl.style.scrollSnapType = 'none';\n swiper._immediateVirtual = true;\n }\n\n wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t;\n\n if (isVirtual) {\n requestAnimationFrame(() => {\n swiper.wrapperEl.style.scrollSnapType = '';\n swiper._swiperImmediateVirtual = false;\n });\n }\n } else {\n if (!swiper.support.smoothScroll) {\n animateCSSModeScroll({\n swiper,\n targetPosition: t,\n side: isH ? 'left' : 'top'\n });\n return true;\n }\n\n wrapperEl.scrollTo({\n [isH ? 'left' : 'top']: t,\n behavior: 'smooth'\n });\n }\n\n return true;\n }\n\n swiper.setTransition(speed);\n swiper.setTranslate(translate);\n swiper.updateActiveIndex(slideIndex);\n swiper.updateSlidesClasses();\n swiper.emit('beforeTransitionStart', speed, internal);\n swiper.transitionStart(runCallbacks, direction);\n\n if (speed === 0) {\n swiper.transitionEnd(runCallbacks, direction);\n } else if (!swiper.animating) {\n swiper.animating = true;\n\n if (!swiper.onSlideToWrapperTransitionEnd) {\n swiper.onSlideToWrapperTransitionEnd = function transitionEnd(e) {\n if (!swiper || swiper.destroyed) return;\n if (e.target !== this) return;\n swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);\n swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);\n swiper.onSlideToWrapperTransitionEnd = null;\n delete swiper.onSlideToWrapperTransitionEnd;\n swiper.transitionEnd(runCallbacks, direction);\n };\n }\n\n swiper.$wrapperEl[0].addEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);\n swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);\n }\n\n return true;\n }\n\n function slideToLoop(index, speed, runCallbacks, internal) {\n if (index === void 0) {\n index = 0;\n }\n\n if (speed === void 0) {\n speed = this.params.speed;\n }\n\n if (runCallbacks === void 0) {\n runCallbacks = true;\n }\n\n const swiper = this;\n let newIndex = index;\n\n if (swiper.params.loop) {\n newIndex += swiper.loopedSlides;\n }\n\n return swiper.slideTo(newIndex, speed, runCallbacks, internal);\n }\n\n /* eslint no-unused-vars: \"off\" */\n function slideNext(speed, runCallbacks, internal) {\n if (speed === void 0) {\n speed = this.params.speed;\n }\n\n if (runCallbacks === void 0) {\n runCallbacks = true;\n }\n\n const swiper = this;\n const {\n animating,\n enabled,\n params\n } = swiper;\n if (!enabled) return swiper;\n let perGroup = params.slidesPerGroup;\n\n if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {\n perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1);\n }\n\n const increment = swiper.activeIndex < params.slidesPerGroupSkip ? 1 : perGroup;\n\n if (params.loop) {\n if (animating && params.loopPreventsSlide) return false;\n swiper.loopFix(); // eslint-disable-next-line\n\n swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;\n }\n\n if (params.rewind && swiper.isEnd) {\n return swiper.slideTo(0, speed, runCallbacks, internal);\n }\n\n return swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal);\n }\n\n /* eslint no-unused-vars: \"off\" */\n function slidePrev(speed, runCallbacks, internal) {\n if (speed === void 0) {\n speed = this.params.speed;\n }\n\n if (runCallbacks === void 0) {\n runCallbacks = true;\n }\n\n const swiper = this;\n const {\n params,\n animating,\n snapGrid,\n slidesGrid,\n rtlTranslate,\n enabled\n } = swiper;\n if (!enabled) return swiper;\n\n if (params.loop) {\n if (animating && params.loopPreventsSlide) return false;\n swiper.loopFix(); // eslint-disable-next-line\n\n swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;\n }\n\n const translate = rtlTranslate ? swiper.translate : -swiper.translate;\n\n function normalize(val) {\n if (val < 0) return -Math.floor(Math.abs(val));\n return Math.floor(val);\n }\n\n const normalizedTranslate = normalize(translate);\n const normalizedSnapGrid = snapGrid.map(val => normalize(val));\n let prevSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate) - 1];\n\n if (typeof prevSnap === 'undefined' && params.cssMode) {\n let prevSnapIndex;\n snapGrid.forEach((snap, snapIndex) => {\n if (normalizedTranslate >= snap) {\n // prevSnap = snap;\n prevSnapIndex = snapIndex;\n }\n });\n\n if (typeof prevSnapIndex !== 'undefined') {\n prevSnap = snapGrid[prevSnapIndex > 0 ? prevSnapIndex - 1 : prevSnapIndex];\n }\n }\n\n let prevIndex = 0;\n\n if (typeof prevSnap !== 'undefined') {\n prevIndex = slidesGrid.indexOf(prevSnap);\n if (prevIndex < 0) prevIndex = swiper.activeIndex - 1;\n\n if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {\n prevIndex = prevIndex - swiper.slidesPerViewDynamic('previous', true) + 1;\n prevIndex = Math.max(prevIndex, 0);\n }\n }\n\n if (params.rewind && swiper.isBeginning) {\n const lastIndex = swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1;\n return swiper.slideTo(lastIndex, speed, runCallbacks, internal);\n }\n\n return swiper.slideTo(prevIndex, speed, runCallbacks, internal);\n }\n\n /* eslint no-unused-vars: \"off\" */\n function slideReset(speed, runCallbacks, internal) {\n if (speed === void 0) {\n speed = this.params.speed;\n }\n\n if (runCallbacks === void 0) {\n runCallbacks = true;\n }\n\n const swiper = this;\n return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal);\n }\n\n /* eslint no-unused-vars: \"off\" */\n function slideToClosest(speed, runCallbacks, internal, threshold) {\n if (speed === void 0) {\n speed = this.params.speed;\n }\n\n if (runCallbacks === void 0) {\n runCallbacks = true;\n }\n\n if (threshold === void 0) {\n threshold = 0.5;\n }\n\n const swiper = this;\n let index = swiper.activeIndex;\n const skip = Math.min(swiper.params.slidesPerGroupSkip, index);\n const snapIndex = skip + Math.floor((index - skip) / swiper.params.slidesPerGroup);\n const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;\n\n if (translate >= swiper.snapGrid[snapIndex]) {\n // The current translate is on or after the current snap index, so the choice\n // is between the current index and the one after it.\n const currentSnap = swiper.snapGrid[snapIndex];\n const nextSnap = swiper.snapGrid[snapIndex + 1];\n\n if (translate - currentSnap > (nextSnap - currentSnap) * threshold) {\n index += swiper.params.slidesPerGroup;\n }\n } else {\n // The current translate is before the current snap index, so the choice\n // is between the current index and the one before it.\n const prevSnap = swiper.snapGrid[snapIndex - 1];\n const currentSnap = swiper.snapGrid[snapIndex];\n\n if (translate - prevSnap <= (currentSnap - prevSnap) * threshold) {\n index -= swiper.params.slidesPerGroup;\n }\n }\n\n index = Math.max(index, 0);\n index = Math.min(index, swiper.slidesGrid.length - 1);\n return swiper.slideTo(index, speed, runCallbacks, internal);\n }\n\n function slideToClickedSlide() {\n const swiper = this;\n const {\n params,\n $wrapperEl\n } = swiper;\n const slidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : params.slidesPerView;\n let slideToIndex = swiper.clickedIndex;\n let realIndex;\n\n if (params.loop) {\n if (swiper.animating) return;\n realIndex = parseInt($(swiper.clickedSlide).attr('data-swiper-slide-index'), 10);\n\n if (params.centeredSlides) {\n if (slideToIndex < swiper.loopedSlides - slidesPerView / 2 || slideToIndex > swiper.slides.length - swiper.loopedSlides + slidesPerView / 2) {\n swiper.loopFix();\n slideToIndex = $wrapperEl.children(`.${params.slideClass}[data-swiper-slide-index=\"${realIndex}\"]:not(.${params.slideDuplicateClass})`).eq(0).index();\n nextTick(() => {\n swiper.slideTo(slideToIndex);\n });\n } else {\n swiper.slideTo(slideToIndex);\n }\n } else if (slideToIndex > swiper.slides.length - slidesPerView) {\n swiper.loopFix();\n slideToIndex = $wrapperEl.children(`.${params.slideClass}[data-swiper-slide-index=\"${realIndex}\"]:not(.${params.slideDuplicateClass})`).eq(0).index();\n nextTick(() => {\n swiper.slideTo(slideToIndex);\n });\n } else {\n swiper.slideTo(slideToIndex);\n }\n } else {\n swiper.slideTo(slideToIndex);\n }\n }\n\n var slide = {\n slideTo,\n slideToLoop,\n slideNext,\n slidePrev,\n slideReset,\n slideToClosest,\n slideToClickedSlide\n };\n\n function loopCreate() {\n const swiper = this;\n const document = getDocument();\n const {\n params,\n $wrapperEl\n } = swiper; // Remove duplicated slides\n\n const $selector = $wrapperEl.children().length > 0 ? $($wrapperEl.children()[0].parentNode) : $wrapperEl;\n $selector.children(`.${params.slideClass}.${params.slideDuplicateClass}`).remove();\n let slides = $selector.children(`.${params.slideClass}`);\n\n if (params.loopFillGroupWithBlank) {\n const blankSlidesNum = params.slidesPerGroup - slides.length % params.slidesPerGroup;\n\n if (blankSlidesNum !== params.slidesPerGroup) {\n for (let i = 0; i < blankSlidesNum; i += 1) {\n const blankNode = $(document.createElement('div')).addClass(`${params.slideClass} ${params.slideBlankClass}`);\n $selector.append(blankNode);\n }\n\n slides = $selector.children(`.${params.slideClass}`);\n }\n }\n\n if (params.slidesPerView === 'auto' && !params.loopedSlides) params.loopedSlides = slides.length;\n swiper.loopedSlides = Math.ceil(parseFloat(params.loopedSlides || params.slidesPerView, 10));\n swiper.loopedSlides += params.loopAdditionalSlides;\n\n if (swiper.loopedSlides > slides.length) {\n swiper.loopedSlides = slides.length;\n }\n\n const prependSlides = [];\n const appendSlides = [];\n slides.each((el, index) => {\n const slide = $(el);\n\n if (index < swiper.loopedSlides) {\n appendSlides.push(el);\n }\n\n if (index < slides.length && index >= slides.length - swiper.loopedSlides) {\n prependSlides.push(el);\n }\n\n slide.attr('data-swiper-slide-index', index);\n });\n\n for (let i = 0; i < appendSlides.length; i += 1) {\n $selector.append($(appendSlides[i].cloneNode(true)).addClass(params.slideDuplicateClass));\n }\n\n for (let i = prependSlides.length - 1; i >= 0; i -= 1) {\n $selector.prepend($(prependSlides[i].cloneNode(true)).addClass(params.slideDuplicateClass));\n }\n }\n\n function loopFix() {\n const swiper = this;\n swiper.emit('beforeLoopFix');\n const {\n activeIndex,\n slides,\n loopedSlides,\n allowSlidePrev,\n allowSlideNext,\n snapGrid,\n rtlTranslate: rtl\n } = swiper;\n let newIndex;\n swiper.allowSlidePrev = true;\n swiper.allowSlideNext = true;\n const snapTranslate = -snapGrid[activeIndex];\n const diff = snapTranslate - swiper.getTranslate(); // Fix For Negative Oversliding\n\n if (activeIndex < loopedSlides) {\n newIndex = slides.length - loopedSlides * 3 + activeIndex;\n newIndex += loopedSlides;\n const slideChanged = swiper.slideTo(newIndex, 0, false, true);\n\n if (slideChanged && diff !== 0) {\n swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);\n }\n } else if (activeIndex >= slides.length - loopedSlides) {\n // Fix For Positive Oversliding\n newIndex = -slides.length + activeIndex + loopedSlides;\n newIndex += loopedSlides;\n const slideChanged = swiper.slideTo(newIndex, 0, false, true);\n\n if (slideChanged && diff !== 0) {\n swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);\n }\n }\n\n swiper.allowSlidePrev = allowSlidePrev;\n swiper.allowSlideNext = allowSlideNext;\n swiper.emit('loopFix');\n }\n\n function loopDestroy() {\n const swiper = this;\n const {\n $wrapperEl,\n params,\n slides\n } = swiper;\n $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass},.${params.slideClass}.${params.slideBlankClass}`).remove();\n slides.removeAttr('data-swiper-slide-index');\n }\n\n var loop = {\n loopCreate,\n loopFix,\n loopDestroy\n };\n\n function setGrabCursor(moving) {\n const swiper = this;\n if (swiper.support.touch || !swiper.params.simulateTouch || swiper.params.watchOverflow && swiper.isLocked || swiper.params.cssMode) return;\n const el = swiper.params.touchEventsTarget === 'container' ? swiper.el : swiper.wrapperEl;\n el.style.cursor = 'move';\n el.style.cursor = moving ? '-webkit-grabbing' : '-webkit-grab';\n el.style.cursor = moving ? '-moz-grabbin' : '-moz-grab';\n el.style.cursor = moving ? 'grabbing' : 'grab';\n }\n\n function unsetGrabCursor() {\n const swiper = this;\n\n if (swiper.support.touch || swiper.params.watchOverflow && swiper.isLocked || swiper.params.cssMode) {\n return;\n }\n\n swiper[swiper.params.touchEventsTarget === 'container' ? 'el' : 'wrapperEl'].style.cursor = '';\n }\n\n var grabCursor = {\n setGrabCursor,\n unsetGrabCursor\n };\n\n function closestElement(selector, base) {\n if (base === void 0) {\n base = this;\n }\n\n function __closestFrom(el) {\n if (!el || el === getDocument() || el === getWindow()) return null;\n if (el.assignedSlot) el = el.assignedSlot;\n const found = el.closest(selector);\n return found || __closestFrom(el.getRootNode().host);\n }\n\n return __closestFrom(base);\n }\n\n function onTouchStart(event) {\n const swiper = this;\n const document = getDocument();\n const window = getWindow();\n const data = swiper.touchEventsData;\n const {\n params,\n touches,\n enabled\n } = swiper;\n if (!enabled) return;\n\n if (swiper.animating && params.preventInteractionOnTransition) {\n return;\n }\n\n if (!swiper.animating && params.cssMode && params.loop) {\n swiper.loopFix();\n }\n\n let e = event;\n if (e.originalEvent) e = e.originalEvent;\n let $targetEl = $(e.target);\n\n if (params.touchEventsTarget === 'wrapper') {\n if (!$targetEl.closest(swiper.wrapperEl).length) return;\n }\n\n data.isTouchEvent = e.type === 'touchstart';\n if (!data.isTouchEvent && 'which' in e && e.which === 3) return;\n if (!data.isTouchEvent && 'button' in e && e.button > 0) return;\n if (data.isTouched && data.isMoved) return; // change target el for shadow root component\n\n const swipingClassHasValue = !!params.noSwipingClass && params.noSwipingClass !== '';\n\n if (swipingClassHasValue && e.target && e.target.shadowRoot && event.path && event.path[0]) {\n $targetEl = $(event.path[0]);\n }\n\n const noSwipingSelector = params.noSwipingSelector ? params.noSwipingSelector : `.${params.noSwipingClass}`;\n const isTargetShadow = !!(e.target && e.target.shadowRoot); // use closestElement for shadow root element to get the actual closest for nested shadow root element\n\n if (params.noSwiping && (isTargetShadow ? closestElement(noSwipingSelector, e.target) : $targetEl.closest(noSwipingSelector)[0])) {\n swiper.allowClick = true;\n return;\n }\n\n if (params.swipeHandler) {\n if (!$targetEl.closest(params.swipeHandler)[0]) return;\n }\n\n touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;\n touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;\n const startX = touches.currentX;\n const startY = touches.currentY; // Do NOT start if iOS edge swipe is detected. Otherwise iOS app cannot swipe-to-go-back anymore\n\n const edgeSwipeDetection = params.edgeSwipeDetection || params.iOSEdgeSwipeDetection;\n const edgeSwipeThreshold = params.edgeSwipeThreshold || params.iOSEdgeSwipeThreshold;\n\n if (edgeSwipeDetection && (startX <= edgeSwipeThreshold || startX >= window.innerWidth - edgeSwipeThreshold)) {\n if (edgeSwipeDetection === 'prevent') {\n event.preventDefault();\n } else {\n return;\n }\n }\n\n Object.assign(data, {\n isTouched: true,\n isMoved: false,\n allowTouchCallbacks: true,\n isScrolling: undefined,\n startMoving: undefined\n });\n touches.startX = startX;\n touches.startY = startY;\n data.touchStartTime = now();\n swiper.allowClick = true;\n swiper.updateSize();\n swiper.swipeDirection = undefined;\n if (params.threshold > 0) data.allowThresholdMove = false;\n\n if (e.type !== 'touchstart') {\n let preventDefault = true;\n\n if ($targetEl.is(data.focusableElements)) {\n preventDefault = false;\n\n if ($targetEl[0].nodeName === 'SELECT') {\n data.isTouched = false;\n }\n }\n\n if (document.activeElement && $(document.activeElement).is(data.focusableElements) && document.activeElement !== $targetEl[0]) {\n document.activeElement.blur();\n }\n\n const shouldPreventDefault = preventDefault && swiper.allowTouchMove && params.touchStartPreventDefault;\n\n if ((params.touchStartForcePreventDefault || shouldPreventDefault) && !$targetEl[0].isContentEditable) {\n e.preventDefault();\n }\n }\n\n if (swiper.params.freeMode && swiper.params.freeMode.enabled && swiper.freeMode && swiper.animating && !params.cssMode) {\n swiper.freeMode.onTouchStart();\n }\n\n swiper.emit('touchStart', e);\n }\n\n function onTouchMove(event) {\n const document = getDocument();\n const swiper = this;\n const data = swiper.touchEventsData;\n const {\n params,\n touches,\n rtlTranslate: rtl,\n enabled\n } = swiper;\n if (!enabled) return;\n let e = event;\n if (e.originalEvent) e = e.originalEvent;\n\n if (!data.isTouched) {\n if (data.startMoving && data.isScrolling) {\n swiper.emit('touchMoveOpposite', e);\n }\n\n return;\n }\n\n if (data.isTouchEvent && e.type !== 'touchmove') return;\n const targetTouch = e.type === 'touchmove' && e.targetTouches && (e.targetTouches[0] || e.changedTouches[0]);\n const pageX = e.type === 'touchmove' ? targetTouch.pageX : e.pageX;\n const pageY = e.type === 'touchmove' ? targetTouch.pageY : e.pageY;\n\n if (e.preventedByNestedSwiper) {\n touches.startX = pageX;\n touches.startY = pageY;\n return;\n }\n\n if (!swiper.allowTouchMove) {\n if (!$(e.target).is(data.focusableElements)) {\n swiper.allowClick = false;\n }\n\n if (data.isTouched) {\n Object.assign(touches, {\n startX: pageX,\n startY: pageY,\n currentX: pageX,\n currentY: pageY\n });\n data.touchStartTime = now();\n }\n\n return;\n }\n\n if (data.isTouchEvent && params.touchReleaseOnEdges && !params.loop) {\n if (swiper.isVertical()) {\n // Vertical\n if (pageY < touches.startY && swiper.translate <= swiper.maxTranslate() || pageY > touches.startY && swiper.translate >= swiper.minTranslate()) {\n data.isTouched = false;\n data.isMoved = false;\n return;\n }\n } else if (pageX < touches.startX && swiper.translate <= swiper.maxTranslate() || pageX > touches.startX && swiper.translate >= swiper.minTranslate()) {\n return;\n }\n }\n\n if (data.isTouchEvent && document.activeElement) {\n if (e.target === document.activeElement && $(e.target).is(data.focusableElements)) {\n data.isMoved = true;\n swiper.allowClick = false;\n return;\n }\n }\n\n if (data.allowTouchCallbacks) {\n swiper.emit('touchMove', e);\n }\n\n if (e.targetTouches && e.targetTouches.length > 1) return;\n touches.currentX = pageX;\n touches.currentY = pageY;\n const diffX = touches.currentX - touches.startX;\n const diffY = touches.currentY - touches.startY;\n if (swiper.params.threshold && Math.sqrt(diffX ** 2 + diffY ** 2) < swiper.params.threshold) return;\n\n if (typeof data.isScrolling === 'undefined') {\n let touchAngle;\n\n if (swiper.isHorizontal() && touches.currentY === touches.startY || swiper.isVertical() && touches.currentX === touches.startX) {\n data.isScrolling = false;\n } else {\n // eslint-disable-next-line\n if (diffX * diffX + diffY * diffY >= 25) {\n touchAngle = Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180 / Math.PI;\n data.isScrolling = swiper.isHorizontal() ? touchAngle > params.touchAngle : 90 - touchAngle > params.touchAngle;\n }\n }\n }\n\n if (data.isScrolling) {\n swiper.emit('touchMoveOpposite', e);\n }\n\n if (typeof data.startMoving === 'undefined') {\n if (touches.currentX !== touches.startX || touches.currentY !== touches.startY) {\n data.startMoving = true;\n }\n }\n\n if (data.isScrolling) {\n data.isTouched = false;\n return;\n }\n\n if (!data.startMoving) {\n return;\n }\n\n swiper.allowClick = false;\n\n if (!params.cssMode && e.cancelable) {\n e.preventDefault();\n }\n\n if (params.touchMoveStopPropagation && !params.nested) {\n e.stopPropagation();\n }\n\n if (!data.isMoved) {\n if (params.loop && !params.cssMode) {\n swiper.loopFix();\n }\n\n data.startTranslate = swiper.getTranslate();\n swiper.setTransition(0);\n\n if (swiper.animating) {\n swiper.$wrapperEl.trigger('webkitTransitionEnd transitionend');\n }\n\n data.allowMomentumBounce = false; // Grab Cursor\n\n if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {\n swiper.setGrabCursor(true);\n }\n\n swiper.emit('sliderFirstMove', e);\n }\n\n swiper.emit('sliderMove', e);\n data.isMoved = true;\n let diff = swiper.isHorizontal() ? diffX : diffY;\n touches.diff = diff;\n diff *= params.touchRatio;\n if (rtl) diff = -diff;\n swiper.swipeDirection = diff > 0 ? 'prev' : 'next';\n data.currentTranslate = diff + data.startTranslate;\n let disableParentSwiper = true;\n let resistanceRatio = params.resistanceRatio;\n\n if (params.touchReleaseOnEdges) {\n resistanceRatio = 0;\n }\n\n if (diff > 0 && data.currentTranslate > swiper.minTranslate()) {\n disableParentSwiper = false;\n if (params.resistance) data.currentTranslate = swiper.minTranslate() - 1 + (-swiper.minTranslate() + data.startTranslate + diff) ** resistanceRatio;\n } else if (diff < 0 && data.currentTranslate < swiper.maxTranslate()) {\n disableParentSwiper = false;\n if (params.resistance) data.currentTranslate = swiper.maxTranslate() + 1 - (swiper.maxTranslate() - data.startTranslate - diff) ** resistanceRatio;\n }\n\n if (disableParentSwiper) {\n e.preventedByNestedSwiper = true;\n } // Directions locks\n\n\n if (!swiper.allowSlideNext && swiper.swipeDirection === 'next' && data.currentTranslate < data.startTranslate) {\n data.currentTranslate = data.startTranslate;\n }\n\n if (!swiper.allowSlidePrev && swiper.swipeDirection === 'prev' && data.currentTranslate > data.startTranslate) {\n data.currentTranslate = data.startTranslate;\n }\n\n if (!swiper.allowSlidePrev && !swiper.allowSlideNext) {\n data.currentTranslate = data.startTranslate;\n } // Threshold\n\n\n if (params.threshold > 0) {\n if (Math.abs(diff) > params.threshold || data.allowThresholdMove) {\n if (!data.allowThresholdMove) {\n data.allowThresholdMove = true;\n touches.startX = touches.currentX;\n touches.startY = touches.currentY;\n data.currentTranslate = data.startTranslate;\n touches.diff = swiper.isHorizontal() ? touches.currentX - touches.startX : touches.currentY - touches.startY;\n return;\n }\n } else {\n data.currentTranslate = data.startTranslate;\n return;\n }\n }\n\n if (!params.followFinger || params.cssMode) return; // Update active index in free mode\n\n if (params.freeMode && params.freeMode.enabled && swiper.freeMode || params.watchSlidesProgress) {\n swiper.updateActiveIndex();\n swiper.updateSlidesClasses();\n }\n\n if (swiper.params.freeMode && params.freeMode.enabled && swiper.freeMode) {\n swiper.freeMode.onTouchMove();\n } // Update progress\n\n\n swiper.updateProgress(data.currentTranslate); // Update translate\n\n swiper.setTranslate(data.currentTranslate);\n }\n\n function onTouchEnd(event) {\n const swiper = this;\n const data = swiper.touchEventsData;\n const {\n params,\n touches,\n rtlTranslate: rtl,\n slidesGrid,\n enabled\n } = swiper;\n if (!enabled) return;\n let e = event;\n if (e.originalEvent) e = e.originalEvent;\n\n if (data.allowTouchCallbacks) {\n swiper.emit('touchEnd', e);\n }\n\n data.allowTouchCallbacks = false;\n\n if (!data.isTouched) {\n if (data.isMoved && params.grabCursor) {\n swiper.setGrabCursor(false);\n }\n\n data.isMoved = false;\n data.startMoving = false;\n return;\n } // Return Grab Cursor\n\n\n if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {\n swiper.setGrabCursor(false);\n } // Time diff\n\n\n const touchEndTime = now();\n const timeDiff = touchEndTime - data.touchStartTime; // Tap, doubleTap, Click\n\n if (swiper.allowClick) {\n const pathTree = e.path || e.composedPath && e.composedPath();\n swiper.updateClickedSlide(pathTree && pathTree[0] || e.target);\n swiper.emit('tap click', e);\n\n if (timeDiff < 300 && touchEndTime - data.lastClickTime < 300) {\n swiper.emit('doubleTap doubleClick', e);\n }\n }\n\n data.lastClickTime = now();\n nextTick(() => {\n if (!swiper.destroyed) swiper.allowClick = true;\n });\n\n if (!data.isTouched || !data.isMoved || !swiper.swipeDirection || touches.diff === 0 || data.currentTranslate === data.startTranslate) {\n data.isTouched = false;\n data.isMoved = false;\n data.startMoving = false;\n return;\n }\n\n data.isTouched = false;\n data.isMoved = false;\n data.startMoving = false;\n let currentPos;\n\n if (params.followFinger) {\n currentPos = rtl ? swiper.translate : -swiper.translate;\n } else {\n currentPos = -data.currentTranslate;\n }\n\n if (params.cssMode) {\n return;\n }\n\n if (swiper.params.freeMode && params.freeMode.enabled) {\n swiper.freeMode.onTouchEnd({\n currentPos\n });\n return;\n } // Find current slide\n\n\n let stopIndex = 0;\n let groupSize = swiper.slidesSizesGrid[0];\n\n for (let i = 0; i < slidesGrid.length; i += i < params.slidesPerGroupSkip ? 1 : params.slidesPerGroup) {\n const increment = i < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;\n\n if (typeof slidesGrid[i + increment] !== 'undefined') {\n if (currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + increment]) {\n stopIndex = i;\n groupSize = slidesGrid[i + increment] - slidesGrid[i];\n }\n } else if (currentPos >= slidesGrid[i]) {\n stopIndex = i;\n groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2];\n }\n }\n\n let rewindFirstIndex = null;\n let rewindLastIndex = null;\n\n if (params.rewind) {\n if (swiper.isBeginning) {\n rewindLastIndex = swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1;\n } else if (swiper.isEnd) {\n rewindFirstIndex = 0;\n }\n } // Find current slide size\n\n\n const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;\n const increment = stopIndex < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;\n\n if (timeDiff > params.longSwipesMs) {\n // Long touches\n if (!params.longSwipes) {\n swiper.slideTo(swiper.activeIndex);\n return;\n }\n\n if (swiper.swipeDirection === 'next') {\n if (ratio >= params.longSwipesRatio) swiper.slideTo(params.rewind && swiper.isEnd ? rewindFirstIndex : stopIndex + increment);else swiper.slideTo(stopIndex);\n }\n\n if (swiper.swipeDirection === 'prev') {\n if (ratio > 1 - params.longSwipesRatio) {\n swiper.slideTo(stopIndex + increment);\n } else if (rewindLastIndex !== null && ratio < 0 && Math.abs(ratio) > params.longSwipesRatio) {\n swiper.slideTo(rewindLastIndex);\n } else {\n swiper.slideTo(stopIndex);\n }\n }\n } else {\n // Short swipes\n if (!params.shortSwipes) {\n swiper.slideTo(swiper.activeIndex);\n return;\n }\n\n const isNavButtonTarget = swiper.navigation && (e.target === swiper.navigation.nextEl || e.target === swiper.navigation.prevEl);\n\n if (!isNavButtonTarget) {\n if (swiper.swipeDirection === 'next') {\n swiper.slideTo(rewindFirstIndex !== null ? rewindFirstIndex : stopIndex + increment);\n }\n\n if (swiper.swipeDirection === 'prev') {\n swiper.slideTo(rewindLastIndex !== null ? rewindLastIndex : stopIndex);\n }\n } else if (e.target === swiper.navigation.nextEl) {\n swiper.slideTo(stopIndex + increment);\n } else {\n swiper.slideTo(stopIndex);\n }\n }\n }\n\n function onResize() {\n const swiper = this;\n const {\n params,\n el\n } = swiper;\n if (el && el.offsetWidth === 0) return; // Breakpoints\n\n if (params.breakpoints) {\n swiper.setBreakpoint();\n } // Save locks\n\n\n const {\n allowSlideNext,\n allowSlidePrev,\n snapGrid\n } = swiper; // Disable locks on resize\n\n swiper.allowSlideNext = true;\n swiper.allowSlidePrev = true;\n swiper.updateSize();\n swiper.updateSlides();\n swiper.updateSlidesClasses();\n\n if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.isBeginning && !swiper.params.centeredSlides) {\n swiper.slideTo(swiper.slides.length - 1, 0, false, true);\n } else {\n swiper.slideTo(swiper.activeIndex, 0, false, true);\n }\n\n if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) {\n swiper.autoplay.run();\n } // Return locks after resize\n\n\n swiper.allowSlidePrev = allowSlidePrev;\n swiper.allowSlideNext = allowSlideNext;\n\n if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) {\n swiper.checkOverflow();\n }\n }\n\n function onClick(e) {\n const swiper = this;\n if (!swiper.enabled) return;\n\n if (!swiper.allowClick) {\n if (swiper.params.preventClicks) e.preventDefault();\n\n if (swiper.params.preventClicksPropagation && swiper.animating) {\n e.stopPropagation();\n e.stopImmediatePropagation();\n }\n }\n }\n\n function onScroll() {\n const swiper = this;\n const {\n wrapperEl,\n rtlTranslate,\n enabled\n } = swiper;\n if (!enabled) return;\n swiper.previousTranslate = swiper.translate;\n\n if (swiper.isHorizontal()) {\n swiper.translate = -wrapperEl.scrollLeft;\n } else {\n swiper.translate = -wrapperEl.scrollTop;\n } // eslint-disable-next-line\n\n\n if (swiper.translate === -0) swiper.translate = 0;\n swiper.updateActiveIndex();\n swiper.updateSlidesClasses();\n let newProgress;\n const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();\n\n if (translatesDiff === 0) {\n newProgress = 0;\n } else {\n newProgress = (swiper.translate - swiper.minTranslate()) / translatesDiff;\n }\n\n if (newProgress !== swiper.progress) {\n swiper.updateProgress(rtlTranslate ? -swiper.translate : swiper.translate);\n }\n\n swiper.emit('setTranslate', swiper.translate, false);\n }\n\n let dummyEventAttached = false;\n\n function dummyEventListener() {}\n\n const events = (swiper, method) => {\n const document = getDocument();\n const {\n params,\n touchEvents,\n el,\n wrapperEl,\n device,\n support\n } = swiper;\n const capture = !!params.nested;\n const domMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';\n const swiperMethod = method; // Touch Events\n\n if (!support.touch) {\n el[domMethod](touchEvents.start, swiper.onTouchStart, false);\n document[domMethod](touchEvents.move, swiper.onTouchMove, capture);\n document[domMethod](touchEvents.end, swiper.onTouchEnd, false);\n } else {\n const passiveListener = touchEvents.start === 'touchstart' && support.passiveListener && params.passiveListeners ? {\n passive: true,\n capture: false\n } : false;\n el[domMethod](touchEvents.start, swiper.onTouchStart, passiveListener);\n el[domMethod](touchEvents.move, swiper.onTouchMove, support.passiveListener ? {\n passive: false,\n capture\n } : capture);\n el[domMethod](touchEvents.end, swiper.onTouchEnd, passiveListener);\n\n if (touchEvents.cancel) {\n el[domMethod](touchEvents.cancel, swiper.onTouchEnd, passiveListener);\n }\n } // Prevent Links Clicks\n\n\n if (params.preventClicks || params.preventClicksPropagation) {\n el[domMethod]('click', swiper.onClick, true);\n }\n\n if (params.cssMode) {\n wrapperEl[domMethod]('scroll', swiper.onScroll);\n } // Resize handler\n\n\n if (params.updateOnWindowResize) {\n swiper[swiperMethod](device.ios || device.android ? 'resize orientationchange observerUpdate' : 'resize observerUpdate', onResize, true);\n } else {\n swiper[swiperMethod]('observerUpdate', onResize, true);\n }\n };\n\n function attachEvents() {\n const swiper = this;\n const document = getDocument();\n const {\n params,\n support\n } = swiper;\n swiper.onTouchStart = onTouchStart.bind(swiper);\n swiper.onTouchMove = onTouchMove.bind(swiper);\n swiper.onTouchEnd = onTouchEnd.bind(swiper);\n\n if (params.cssMode) {\n swiper.onScroll = onScroll.bind(swiper);\n }\n\n swiper.onClick = onClick.bind(swiper);\n\n if (support.touch && !dummyEventAttached) {\n document.addEventListener('touchstart', dummyEventListener);\n dummyEventAttached = true;\n }\n\n events(swiper, 'on');\n }\n\n function detachEvents() {\n const swiper = this;\n events(swiper, 'off');\n }\n\n var events$1 = {\n attachEvents,\n detachEvents\n };\n\n const isGridEnabled = (swiper, params) => {\n return swiper.grid && params.grid && params.grid.rows > 1;\n };\n\n function setBreakpoint() {\n const swiper = this;\n const {\n activeIndex,\n initialized,\n loopedSlides = 0,\n params,\n $el\n } = swiper;\n const breakpoints = params.breakpoints;\n if (!breakpoints || breakpoints && Object.keys(breakpoints).length === 0) return; // Get breakpoint for window width and update parameters\n\n const breakpoint = swiper.getBreakpoint(breakpoints, swiper.params.breakpointsBase, swiper.el);\n if (!breakpoint || swiper.currentBreakpoint === breakpoint) return;\n const breakpointOnlyParams = breakpoint in breakpoints ? breakpoints[breakpoint] : undefined;\n const breakpointParams = breakpointOnlyParams || swiper.originalParams;\n const wasMultiRow = isGridEnabled(swiper, params);\n const isMultiRow = isGridEnabled(swiper, breakpointParams);\n const wasEnabled = params.enabled;\n\n if (wasMultiRow && !isMultiRow) {\n $el.removeClass(`${params.containerModifierClass}grid ${params.containerModifierClass}grid-column`);\n swiper.emitContainerClasses();\n } else if (!wasMultiRow && isMultiRow) {\n $el.addClass(`${params.containerModifierClass}grid`);\n\n if (breakpointParams.grid.fill && breakpointParams.grid.fill === 'column' || !breakpointParams.grid.fill && params.grid.fill === 'column') {\n $el.addClass(`${params.containerModifierClass}grid-column`);\n }\n\n swiper.emitContainerClasses();\n }\n\n const directionChanged = breakpointParams.direction && breakpointParams.direction !== params.direction;\n const needsReLoop = params.loop && (breakpointParams.slidesPerView !== params.slidesPerView || directionChanged);\n\n if (directionChanged && initialized) {\n swiper.changeDirection();\n }\n\n extend(swiper.params, breakpointParams);\n const isEnabled = swiper.params.enabled;\n Object.assign(swiper, {\n allowTouchMove: swiper.params.allowTouchMove,\n allowSlideNext: swiper.params.allowSlideNext,\n allowSlidePrev: swiper.params.allowSlidePrev\n });\n\n if (wasEnabled && !isEnabled) {\n swiper.disable();\n } else if (!wasEnabled && isEnabled) {\n swiper.enable();\n }\n\n swiper.currentBreakpoint = breakpoint;\n swiper.emit('_beforeBreakpoint', breakpointParams);\n\n if (needsReLoop && initialized) {\n swiper.loopDestroy();\n swiper.loopCreate();\n swiper.updateSlides();\n swiper.slideTo(activeIndex - loopedSlides + swiper.loopedSlides, 0, false);\n }\n\n swiper.emit('breakpoint', breakpointParams);\n }\n\n function getBreakpoint(breakpoints, base, containerEl) {\n if (base === void 0) {\n base = 'window';\n }\n\n if (!breakpoints || base === 'container' && !containerEl) return undefined;\n let breakpoint = false;\n const window = getWindow();\n const currentHeight = base === 'window' ? window.innerHeight : containerEl.clientHeight;\n const points = Object.keys(breakpoints).map(point => {\n if (typeof point === 'string' && point.indexOf('@') === 0) {\n const minRatio = parseFloat(point.substr(1));\n const value = currentHeight * minRatio;\n return {\n value,\n point\n };\n }\n\n return {\n value: point,\n point\n };\n });\n points.sort((a, b) => parseInt(a.value, 10) - parseInt(b.value, 10));\n\n for (let i = 0; i < points.length; i += 1) {\n const {\n point,\n value\n } = points[i];\n\n if (base === 'window') {\n if (window.matchMedia(`(min-width: ${value}px)`).matches) {\n breakpoint = point;\n }\n } else if (value <= containerEl.clientWidth) {\n breakpoint = point;\n }\n }\n\n return breakpoint || 'max';\n }\n\n var breakpoints = {\n setBreakpoint,\n getBreakpoint\n };\n\n function prepareClasses(entries, prefix) {\n const resultClasses = [];\n entries.forEach(item => {\n if (typeof item === 'object') {\n Object.keys(item).forEach(classNames => {\n if (item[classNames]) {\n resultClasses.push(prefix + classNames);\n }\n });\n } else if (typeof item === 'string') {\n resultClasses.push(prefix + item);\n }\n });\n return resultClasses;\n }\n\n function addClasses() {\n const swiper = this;\n const {\n classNames,\n params,\n rtl,\n $el,\n device,\n support\n } = swiper; // prettier-ignore\n\n const suffixes = prepareClasses(['initialized', params.direction, {\n 'pointer-events': !support.touch\n }, {\n 'free-mode': swiper.params.freeMode && params.freeMode.enabled\n }, {\n 'autoheight': params.autoHeight\n }, {\n 'rtl': rtl\n }, {\n 'grid': params.grid && params.grid.rows > 1\n }, {\n 'grid-column': params.grid && params.grid.rows > 1 && params.grid.fill === 'column'\n }, {\n 'android': device.android\n }, {\n 'ios': device.ios\n }, {\n 'css-mode': params.cssMode\n }, {\n 'centered': params.cssMode && params.centeredSlides\n }], params.containerModifierClass);\n classNames.push(...suffixes);\n $el.addClass([...classNames].join(' '));\n swiper.emitContainerClasses();\n }\n\n function removeClasses() {\n const swiper = this;\n const {\n $el,\n classNames\n } = swiper;\n $el.removeClass(classNames.join(' '));\n swiper.emitContainerClasses();\n }\n\n var classes = {\n addClasses,\n removeClasses\n };\n\n function loadImage(imageEl, src, srcset, sizes, checkForComplete, callback) {\n const window = getWindow();\n let image;\n\n function onReady() {\n if (callback) callback();\n }\n\n const isPicture = $(imageEl).parent('picture')[0];\n\n if (!isPicture && (!imageEl.complete || !checkForComplete)) {\n if (src) {\n image = new window.Image();\n image.onload = onReady;\n image.onerror = onReady;\n\n if (sizes) {\n image.sizes = sizes;\n }\n\n if (srcset) {\n image.srcset = srcset;\n }\n\n if (src) {\n image.src = src;\n }\n } else {\n onReady();\n }\n } else {\n // image already loaded...\n onReady();\n }\n }\n\n function preloadImages() {\n const swiper = this;\n swiper.imagesToLoad = swiper.$el.find('img');\n\n function onReady() {\n if (typeof swiper === 'undefined' || swiper === null || !swiper || swiper.destroyed) return;\n if (swiper.imagesLoaded !== undefined) swiper.imagesLoaded += 1;\n\n if (swiper.imagesLoaded === swiper.imagesToLoad.length) {\n if (swiper.params.updateOnImagesReady) swiper.update();\n swiper.emit('imagesReady');\n }\n }\n\n for (let i = 0; i < swiper.imagesToLoad.length; i += 1) {\n const imageEl = swiper.imagesToLoad[i];\n swiper.loadImage(imageEl, imageEl.currentSrc || imageEl.getAttribute('src'), imageEl.srcset || imageEl.getAttribute('srcset'), imageEl.sizes || imageEl.getAttribute('sizes'), true, onReady);\n }\n }\n\n var images = {\n loadImage,\n preloadImages\n };\n\n function checkOverflow() {\n const swiper = this;\n const {\n isLocked: wasLocked,\n params\n } = swiper;\n const {\n slidesOffsetBefore\n } = params;\n\n if (slidesOffsetBefore) {\n const lastSlideIndex = swiper.slides.length - 1;\n const lastSlideRightEdge = swiper.slidesGrid[lastSlideIndex] + swiper.slidesSizesGrid[lastSlideIndex] + slidesOffsetBefore * 2;\n swiper.isLocked = swiper.size > lastSlideRightEdge;\n } else {\n swiper.isLocked = swiper.snapGrid.length === 1;\n }\n\n if (params.allowSlideNext === true) {\n swiper.allowSlideNext = !swiper.isLocked;\n }\n\n if (params.allowSlidePrev === true) {\n swiper.allowSlidePrev = !swiper.isLocked;\n }\n\n if (wasLocked && wasLocked !== swiper.isLocked) {\n swiper.isEnd = false;\n }\n\n if (wasLocked !== swiper.isLocked) {\n swiper.emit(swiper.isLocked ? 'lock' : 'unlock');\n }\n }\n\n var checkOverflow$1 = {\n checkOverflow\n };\n\n var defaults = {\n init: true,\n direction: 'horizontal',\n touchEventsTarget: 'wrapper',\n initialSlide: 0,\n speed: 300,\n cssMode: false,\n updateOnWindowResize: true,\n resizeObserver: true,\n nested: false,\n createElements: false,\n enabled: true,\n focusableElements: 'input, select, option, textarea, button, video, label',\n // Overrides\n width: null,\n height: null,\n //\n preventInteractionOnTransition: false,\n // ssr\n userAgent: null,\n url: null,\n // To support iOS's swipe-to-go-back gesture (when being used in-app).\n edgeSwipeDetection: false,\n edgeSwipeThreshold: 20,\n // Autoheight\n autoHeight: false,\n // Set wrapper width\n setWrapperSize: false,\n // Virtual Translate\n virtualTranslate: false,\n // Effects\n effect: 'slide',\n // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'\n // Breakpoints\n breakpoints: undefined,\n breakpointsBase: 'window',\n // Slides grid\n spaceBetween: 0,\n slidesPerView: 1,\n slidesPerGroup: 1,\n slidesPerGroupSkip: 0,\n slidesPerGroupAuto: false,\n centeredSlides: false,\n centeredSlidesBounds: false,\n slidesOffsetBefore: 0,\n // in px\n slidesOffsetAfter: 0,\n // in px\n normalizeSlideIndex: true,\n centerInsufficientSlides: false,\n // Disable swiper and hide navigation when container not overflow\n watchOverflow: true,\n // Round length\n roundLengths: false,\n // Touches\n touchRatio: 1,\n touchAngle: 45,\n simulateTouch: true,\n shortSwipes: true,\n longSwipes: true,\n longSwipesRatio: 0.5,\n longSwipesMs: 300,\n followFinger: true,\n allowTouchMove: true,\n threshold: 0,\n touchMoveStopPropagation: false,\n touchStartPreventDefault: true,\n touchStartForcePreventDefault: false,\n touchReleaseOnEdges: false,\n // Unique Navigation Elements\n uniqueNavElements: true,\n // Resistance\n resistance: true,\n resistanceRatio: 0.85,\n // Progress\n watchSlidesProgress: false,\n // Cursor\n grabCursor: false,\n // Clicks\n preventClicks: true,\n preventClicksPropagation: true,\n slideToClickedSlide: false,\n // Images\n preloadImages: true,\n updateOnImagesReady: true,\n // loop\n loop: false,\n loopAdditionalSlides: 0,\n loopedSlides: null,\n loopFillGroupWithBlank: false,\n loopPreventsSlide: true,\n // rewind\n rewind: false,\n // Swiping/no swiping\n allowSlidePrev: true,\n allowSlideNext: true,\n swipeHandler: null,\n // '.swipe-handler',\n noSwiping: true,\n noSwipingClass: 'swiper-no-swiping',\n noSwipingSelector: null,\n // Passive Listeners\n passiveListeners: true,\n maxBackfaceHiddenSlides: 10,\n // NS\n containerModifierClass: 'swiper-',\n // NEW\n slideClass: 'swiper-slide',\n slideBlankClass: 'swiper-slide-invisible-blank',\n slideActiveClass: 'swiper-slide-active',\n slideDuplicateActiveClass: 'swiper-slide-duplicate-active',\n slideVisibleClass: 'swiper-slide-visible',\n slideDuplicateClass: 'swiper-slide-duplicate',\n slideNextClass: 'swiper-slide-next',\n slideDuplicateNextClass: 'swiper-slide-duplicate-next',\n slidePrevClass: 'swiper-slide-prev',\n slideDuplicatePrevClass: 'swiper-slide-duplicate-prev',\n wrapperClass: 'swiper-wrapper',\n // Callbacks\n runCallbacksOnInit: true,\n // Internals\n _emitClasses: false\n };\n\n function moduleExtendParams(params, allModulesParams) {\n return function extendParams(obj) {\n if (obj === void 0) {\n obj = {};\n }\n\n const moduleParamName = Object.keys(obj)[0];\n const moduleParams = obj[moduleParamName];\n\n if (typeof moduleParams !== 'object' || moduleParams === null) {\n extend(allModulesParams, obj);\n return;\n }\n\n if (['navigation', 'pagination', 'scrollbar'].indexOf(moduleParamName) >= 0 && params[moduleParamName] === true) {\n params[moduleParamName] = {\n auto: true\n };\n }\n\n if (!(moduleParamName in params && 'enabled' in moduleParams)) {\n extend(allModulesParams, obj);\n return;\n }\n\n if (params[moduleParamName] === true) {\n params[moduleParamName] = {\n enabled: true\n };\n }\n\n if (typeof params[moduleParamName] === 'object' && !('enabled' in params[moduleParamName])) {\n params[moduleParamName].enabled = true;\n }\n\n if (!params[moduleParamName]) params[moduleParamName] = {\n enabled: false\n };\n extend(allModulesParams, obj);\n };\n }\n\n /* eslint no-param-reassign: \"off\" */\n const prototypes = {\n eventsEmitter,\n update,\n translate,\n transition,\n slide,\n loop,\n grabCursor,\n events: events$1,\n breakpoints,\n checkOverflow: checkOverflow$1,\n classes,\n images\n };\n const extendedDefaults = {};\n\n class Swiper {\n constructor() {\n let el;\n let params;\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n if (args.length === 1 && args[0].constructor && Object.prototype.toString.call(args[0]).slice(8, -1) === 'Object') {\n params = args[0];\n } else {\n [el, params] = args;\n }\n\n if (!params) params = {};\n params = extend({}, params);\n if (el && !params.el) params.el = el;\n\n if (params.el && $(params.el).length > 1) {\n const swipers = [];\n $(params.el).each(containerEl => {\n const newParams = extend({}, params, {\n el: containerEl\n });\n swipers.push(new Swiper(newParams));\n });\n return swipers;\n } // Swiper Instance\n\n\n const swiper = this;\n swiper.__swiper__ = true;\n swiper.support = getSupport();\n swiper.device = getDevice({\n userAgent: params.userAgent\n });\n swiper.browser = getBrowser();\n swiper.eventsListeners = {};\n swiper.eventsAnyListeners = [];\n swiper.modules = [...swiper.__modules__];\n\n if (params.modules && Array.isArray(params.modules)) {\n swiper.modules.push(...params.modules);\n }\n\n const allModulesParams = {};\n swiper.modules.forEach(mod => {\n mod({\n swiper,\n extendParams: moduleExtendParams(params, allModulesParams),\n on: swiper.on.bind(swiper),\n once: swiper.once.bind(swiper),\n off: swiper.off.bind(swiper),\n emit: swiper.emit.bind(swiper)\n });\n }); // Extend defaults with modules params\n\n const swiperParams = extend({}, defaults, allModulesParams); // Extend defaults with passed params\n\n swiper.params = extend({}, swiperParams, extendedDefaults, params);\n swiper.originalParams = extend({}, swiper.params);\n swiper.passedParams = extend({}, params); // add event listeners\n\n if (swiper.params && swiper.params.on) {\n Object.keys(swiper.params.on).forEach(eventName => {\n swiper.on(eventName, swiper.params.on[eventName]);\n });\n }\n\n if (swiper.params && swiper.params.onAny) {\n swiper.onAny(swiper.params.onAny);\n } // Save Dom lib\n\n\n swiper.$ = $; // Extend Swiper\n\n Object.assign(swiper, {\n enabled: swiper.params.enabled,\n el,\n // Classes\n classNames: [],\n // Slides\n slides: $(),\n slidesGrid: [],\n snapGrid: [],\n slidesSizesGrid: [],\n\n // isDirection\n isHorizontal() {\n return swiper.params.direction === 'horizontal';\n },\n\n isVertical() {\n return swiper.params.direction === 'vertical';\n },\n\n // Indexes\n activeIndex: 0,\n realIndex: 0,\n //\n isBeginning: true,\n isEnd: false,\n // Props\n translate: 0,\n previousTranslate: 0,\n progress: 0,\n velocity: 0,\n animating: false,\n // Locks\n allowSlideNext: swiper.params.allowSlideNext,\n allowSlidePrev: swiper.params.allowSlidePrev,\n // Touch Events\n touchEvents: function touchEvents() {\n const touch = ['touchstart', 'touchmove', 'touchend', 'touchcancel'];\n const desktop = ['pointerdown', 'pointermove', 'pointerup'];\n swiper.touchEventsTouch = {\n start: touch[0],\n move: touch[1],\n end: touch[2],\n cancel: touch[3]\n };\n swiper.touchEventsDesktop = {\n start: desktop[0],\n move: desktop[1],\n end: desktop[2]\n };\n return swiper.support.touch || !swiper.params.simulateTouch ? swiper.touchEventsTouch : swiper.touchEventsDesktop;\n }(),\n touchEventsData: {\n isTouched: undefined,\n isMoved: undefined,\n allowTouchCallbacks: undefined,\n touchStartTime: undefined,\n isScrolling: undefined,\n currentTranslate: undefined,\n startTranslate: undefined,\n allowThresholdMove: undefined,\n // Form elements to match\n focusableElements: swiper.params.focusableElements,\n // Last click time\n lastClickTime: now(),\n clickTimeout: undefined,\n // Velocities\n velocities: [],\n allowMomentumBounce: undefined,\n isTouchEvent: undefined,\n startMoving: undefined\n },\n // Clicks\n allowClick: true,\n // Touches\n allowTouchMove: swiper.params.allowTouchMove,\n touches: {\n startX: 0,\n startY: 0,\n currentX: 0,\n currentY: 0,\n diff: 0\n },\n // Images\n imagesToLoad: [],\n imagesLoaded: 0\n });\n swiper.emit('_swiper'); // Init\n\n if (swiper.params.init) {\n swiper.init();\n } // Return app instance\n\n\n return swiper;\n }\n\n enable() {\n const swiper = this;\n if (swiper.enabled) return;\n swiper.enabled = true;\n\n if (swiper.params.grabCursor) {\n swiper.setGrabCursor();\n }\n\n swiper.emit('enable');\n }\n\n disable() {\n const swiper = this;\n if (!swiper.enabled) return;\n swiper.enabled = false;\n\n if (swiper.params.grabCursor) {\n swiper.unsetGrabCursor();\n }\n\n swiper.emit('disable');\n }\n\n setProgress(progress, speed) {\n const swiper = this;\n progress = Math.min(Math.max(progress, 0), 1);\n const min = swiper.minTranslate();\n const max = swiper.maxTranslate();\n const current = (max - min) * progress + min;\n swiper.translateTo(current, typeof speed === 'undefined' ? 0 : speed);\n swiper.updateActiveIndex();\n swiper.updateSlidesClasses();\n }\n\n emitContainerClasses() {\n const swiper = this;\n if (!swiper.params._emitClasses || !swiper.el) return;\n const cls = swiper.el.className.split(' ').filter(className => {\n return className.indexOf('swiper') === 0 || className.indexOf(swiper.params.containerModifierClass) === 0;\n });\n swiper.emit('_containerClasses', cls.join(' '));\n }\n\n getSlideClasses(slideEl) {\n const swiper = this;\n return slideEl.className.split(' ').filter(className => {\n return className.indexOf('swiper-slide') === 0 || className.indexOf(swiper.params.slideClass) === 0;\n }).join(' ');\n }\n\n emitSlidesClasses() {\n const swiper = this;\n if (!swiper.params._emitClasses || !swiper.el) return;\n const updates = [];\n swiper.slides.each(slideEl => {\n const classNames = swiper.getSlideClasses(slideEl);\n updates.push({\n slideEl,\n classNames\n });\n swiper.emit('_slideClass', slideEl, classNames);\n });\n swiper.emit('_slideClasses', updates);\n }\n\n slidesPerViewDynamic(view, exact) {\n if (view === void 0) {\n view = 'current';\n }\n\n if (exact === void 0) {\n exact = false;\n }\n\n const swiper = this;\n const {\n params,\n slides,\n slidesGrid,\n slidesSizesGrid,\n size: swiperSize,\n activeIndex\n } = swiper;\n let spv = 1;\n\n if (params.centeredSlides) {\n let slideSize = slides[activeIndex].swiperSlideSize;\n let breakLoop;\n\n for (let i = activeIndex + 1; i < slides.length; i += 1) {\n if (slides[i] && !breakLoop) {\n slideSize += slides[i].swiperSlideSize;\n spv += 1;\n if (slideSize > swiperSize) breakLoop = true;\n }\n }\n\n for (let i = activeIndex - 1; i >= 0; i -= 1) {\n if (slides[i] && !breakLoop) {\n slideSize += slides[i].swiperSlideSize;\n spv += 1;\n if (slideSize > swiperSize) breakLoop = true;\n }\n }\n } else {\n // eslint-disable-next-line\n if (view === 'current') {\n for (let i = activeIndex + 1; i < slides.length; i += 1) {\n const slideInView = exact ? slidesGrid[i] + slidesSizesGrid[i] - slidesGrid[activeIndex] < swiperSize : slidesGrid[i] - slidesGrid[activeIndex] < swiperSize;\n\n if (slideInView) {\n spv += 1;\n }\n }\n } else {\n // previous\n for (let i = activeIndex - 1; i >= 0; i -= 1) {\n const slideInView = slidesGrid[activeIndex] - slidesGrid[i] < swiperSize;\n\n if (slideInView) {\n spv += 1;\n }\n }\n }\n }\n\n return spv;\n }\n\n update() {\n const swiper = this;\n if (!swiper || swiper.destroyed) return;\n const {\n snapGrid,\n params\n } = swiper; // Breakpoints\n\n if (params.breakpoints) {\n swiper.setBreakpoint();\n }\n\n swiper.updateSize();\n swiper.updateSlides();\n swiper.updateProgress();\n swiper.updateSlidesClasses();\n\n function setTranslate() {\n const translateValue = swiper.rtlTranslate ? swiper.translate * -1 : swiper.translate;\n const newTranslate = Math.min(Math.max(translateValue, swiper.maxTranslate()), swiper.minTranslate());\n swiper.setTranslate(newTranslate);\n swiper.updateActiveIndex();\n swiper.updateSlidesClasses();\n }\n\n let translated;\n\n if (swiper.params.freeMode && swiper.params.freeMode.enabled) {\n setTranslate();\n\n if (swiper.params.autoHeight) {\n swiper.updateAutoHeight();\n }\n } else {\n if ((swiper.params.slidesPerView === 'auto' || swiper.params.slidesPerView > 1) && swiper.isEnd && !swiper.params.centeredSlides) {\n translated = swiper.slideTo(swiper.slides.length - 1, 0, false, true);\n } else {\n translated = swiper.slideTo(swiper.activeIndex, 0, false, true);\n }\n\n if (!translated) {\n setTranslate();\n }\n }\n\n if (params.watchOverflow && snapGrid !== swiper.snapGrid) {\n swiper.checkOverflow();\n }\n\n swiper.emit('update');\n }\n\n changeDirection(newDirection, needUpdate) {\n if (needUpdate === void 0) {\n needUpdate = true;\n }\n\n const swiper = this;\n const currentDirection = swiper.params.direction;\n\n if (!newDirection) {\n // eslint-disable-next-line\n newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal';\n }\n\n if (newDirection === currentDirection || newDirection !== 'horizontal' && newDirection !== 'vertical') {\n return swiper;\n }\n\n swiper.$el.removeClass(`${swiper.params.containerModifierClass}${currentDirection}`).addClass(`${swiper.params.containerModifierClass}${newDirection}`);\n swiper.emitContainerClasses();\n swiper.params.direction = newDirection;\n swiper.slides.each(slideEl => {\n if (newDirection === 'vertical') {\n slideEl.style.width = '';\n } else {\n slideEl.style.height = '';\n }\n });\n swiper.emit('changeDirection');\n if (needUpdate) swiper.update();\n return swiper;\n }\n\n mount(el) {\n const swiper = this;\n if (swiper.mounted) return true; // Find el\n\n const $el = $(el || swiper.params.el);\n el = $el[0];\n\n if (!el) {\n return false;\n }\n\n el.swiper = swiper;\n\n const getWrapperSelector = () => {\n return `.${(swiper.params.wrapperClass || '').trim().split(' ').join('.')}`;\n };\n\n const getWrapper = () => {\n if (el && el.shadowRoot && el.shadowRoot.querySelector) {\n const res = $(el.shadowRoot.querySelector(getWrapperSelector())); // Children needs to return slot items\n\n res.children = options => $el.children(options);\n\n return res;\n }\n\n return $el.children(getWrapperSelector());\n }; // Find Wrapper\n\n\n let $wrapperEl = getWrapper();\n\n if ($wrapperEl.length === 0 && swiper.params.createElements) {\n const document = getDocument();\n const wrapper = document.createElement('div');\n $wrapperEl = $(wrapper);\n wrapper.className = swiper.params.wrapperClass;\n $el.append(wrapper);\n $el.children(`.${swiper.params.slideClass}`).each(slideEl => {\n $wrapperEl.append(slideEl);\n });\n }\n\n Object.assign(swiper, {\n $el,\n el,\n $wrapperEl,\n wrapperEl: $wrapperEl[0],\n mounted: true,\n // RTL\n rtl: el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl',\n rtlTranslate: swiper.params.direction === 'horizontal' && (el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl'),\n wrongRTL: $wrapperEl.css('display') === '-webkit-box'\n });\n return true;\n }\n\n init(el) {\n const swiper = this;\n if (swiper.initialized) return swiper;\n const mounted = swiper.mount(el);\n if (mounted === false) return swiper;\n swiper.emit('beforeInit'); // Set breakpoint\n\n if (swiper.params.breakpoints) {\n swiper.setBreakpoint();\n } // Add Classes\n\n\n swiper.addClasses(); // Create loop\n\n if (swiper.params.loop) {\n swiper.loopCreate();\n } // Update size\n\n\n swiper.updateSize(); // Update slides\n\n swiper.updateSlides();\n\n if (swiper.params.watchOverflow) {\n swiper.checkOverflow();\n } // Set Grab Cursor\n\n\n if (swiper.params.grabCursor && swiper.enabled) {\n swiper.setGrabCursor();\n }\n\n if (swiper.params.preloadImages) {\n swiper.preloadImages();\n } // Slide To Initial Slide\n\n\n if (swiper.params.loop) {\n swiper.slideTo(swiper.params.initialSlide + swiper.loopedSlides, 0, swiper.params.runCallbacksOnInit, false, true);\n } else {\n swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit, false, true);\n } // Attach events\n\n\n swiper.attachEvents(); // Init Flag\n\n swiper.initialized = true; // Emit\n\n swiper.emit('init');\n swiper.emit('afterInit');\n return swiper;\n }\n\n destroy(deleteInstance, cleanStyles) {\n if (deleteInstance === void 0) {\n deleteInstance = true;\n }\n\n if (cleanStyles === void 0) {\n cleanStyles = true;\n }\n\n const swiper = this;\n const {\n params,\n $el,\n $wrapperEl,\n slides\n } = swiper;\n\n if (typeof swiper.params === 'undefined' || swiper.destroyed) {\n return null;\n }\n\n swiper.emit('beforeDestroy'); // Init Flag\n\n swiper.initialized = false; // Detach events\n\n swiper.detachEvents(); // Destroy loop\n\n if (params.loop) {\n swiper.loopDestroy();\n } // Cleanup styles\n\n\n if (cleanStyles) {\n swiper.removeClasses();\n $el.removeAttr('style');\n $wrapperEl.removeAttr('style');\n\n if (slides && slides.length) {\n slides.removeClass([params.slideVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass].join(' ')).removeAttr('style').removeAttr('data-swiper-slide-index');\n }\n }\n\n swiper.emit('destroy'); // Detach emitter events\n\n Object.keys(swiper.eventsListeners).forEach(eventName => {\n swiper.off(eventName);\n });\n\n if (deleteInstance !== false) {\n swiper.$el[0].swiper = null;\n deleteProps(swiper);\n }\n\n swiper.destroyed = true;\n return null;\n }\n\n static extendDefaults(newDefaults) {\n extend(extendedDefaults, newDefaults);\n }\n\n static get extendedDefaults() {\n return extendedDefaults;\n }\n\n static get defaults() {\n return defaults;\n }\n\n static installModule(mod) {\n if (!Swiper.prototype.__modules__) Swiper.prototype.__modules__ = [];\n const modules = Swiper.prototype.__modules__;\n\n if (typeof mod === 'function' && modules.indexOf(mod) < 0) {\n modules.push(mod);\n }\n }\n\n static use(module) {\n if (Array.isArray(module)) {\n module.forEach(m => Swiper.installModule(m));\n return Swiper;\n }\n\n Swiper.installModule(module);\n return Swiper;\n }\n\n }\n\n Object.keys(prototypes).forEach(prototypeGroup => {\n Object.keys(prototypes[prototypeGroup]).forEach(protoMethod => {\n Swiper.prototype[protoMethod] = prototypes[prototypeGroup][protoMethod];\n });\n });\n Swiper.use([Resize, Observer]);\n\n function Virtual(_ref) {\n let {\n swiper,\n extendParams,\n on,\n emit\n } = _ref;\n extendParams({\n virtual: {\n enabled: false,\n slides: [],\n cache: true,\n renderSlide: null,\n renderExternal: null,\n renderExternalUpdate: true,\n addSlidesBefore: 0,\n addSlidesAfter: 0\n }\n });\n let cssModeTimeout;\n swiper.virtual = {\n cache: {},\n from: undefined,\n to: undefined,\n slides: [],\n offset: 0,\n slidesGrid: []\n };\n\n function renderSlide(slide, index) {\n const params = swiper.params.virtual;\n\n if (params.cache && swiper.virtual.cache[index]) {\n return swiper.virtual.cache[index];\n }\n\n const $slideEl = params.renderSlide ? $(params.renderSlide.call(swiper, slide, index)) : $(`
${slide}
`);\n if (!$slideEl.attr('data-swiper-slide-index')) $slideEl.attr('data-swiper-slide-index', index);\n if (params.cache) swiper.virtual.cache[index] = $slideEl;\n return $slideEl;\n }\n\n function update(force) {\n const {\n slidesPerView,\n slidesPerGroup,\n centeredSlides\n } = swiper.params;\n const {\n addSlidesBefore,\n addSlidesAfter\n } = swiper.params.virtual;\n const {\n from: previousFrom,\n to: previousTo,\n slides,\n slidesGrid: previousSlidesGrid,\n offset: previousOffset\n } = swiper.virtual;\n\n if (!swiper.params.cssMode) {\n swiper.updateActiveIndex();\n }\n\n const activeIndex = swiper.activeIndex || 0;\n let offsetProp;\n if (swiper.rtlTranslate) offsetProp = 'right';else offsetProp = swiper.isHorizontal() ? 'left' : 'top';\n let slidesAfter;\n let slidesBefore;\n\n if (centeredSlides) {\n slidesAfter = Math.floor(slidesPerView / 2) + slidesPerGroup + addSlidesAfter;\n slidesBefore = Math.floor(slidesPerView / 2) + slidesPerGroup + addSlidesBefore;\n } else {\n slidesAfter = slidesPerView + (slidesPerGroup - 1) + addSlidesAfter;\n slidesBefore = slidesPerGroup + addSlidesBefore;\n }\n\n const from = Math.max((activeIndex || 0) - slidesBefore, 0);\n const to = Math.min((activeIndex || 0) + slidesAfter, slides.length - 1);\n const offset = (swiper.slidesGrid[from] || 0) - (swiper.slidesGrid[0] || 0);\n Object.assign(swiper.virtual, {\n from,\n to,\n offset,\n slidesGrid: swiper.slidesGrid\n });\n\n function onRendered() {\n swiper.updateSlides();\n swiper.updateProgress();\n swiper.updateSlidesClasses();\n\n if (swiper.lazy && swiper.params.lazy.enabled) {\n swiper.lazy.load();\n }\n\n emit('virtualUpdate');\n }\n\n if (previousFrom === from && previousTo === to && !force) {\n if (swiper.slidesGrid !== previousSlidesGrid && offset !== previousOffset) {\n swiper.slides.css(offsetProp, `${offset}px`);\n }\n\n swiper.updateProgress();\n emit('virtualUpdate');\n return;\n }\n\n if (swiper.params.virtual.renderExternal) {\n swiper.params.virtual.renderExternal.call(swiper, {\n offset,\n from,\n to,\n slides: function getSlides() {\n const slidesToRender = [];\n\n for (let i = from; i <= to; i += 1) {\n slidesToRender.push(slides[i]);\n }\n\n return slidesToRender;\n }()\n });\n\n if (swiper.params.virtual.renderExternalUpdate) {\n onRendered();\n } else {\n emit('virtualUpdate');\n }\n\n return;\n }\n\n const prependIndexes = [];\n const appendIndexes = [];\n\n if (force) {\n swiper.$wrapperEl.find(`.${swiper.params.slideClass}`).remove();\n } else {\n for (let i = previousFrom; i <= previousTo; i += 1) {\n if (i < from || i > to) {\n swiper.$wrapperEl.find(`.${swiper.params.slideClass}[data-swiper-slide-index=\"${i}\"]`).remove();\n }\n }\n }\n\n for (let i = 0; i < slides.length; i += 1) {\n if (i >= from && i <= to) {\n if (typeof previousTo === 'undefined' || force) {\n appendIndexes.push(i);\n } else {\n if (i > previousTo) appendIndexes.push(i);\n if (i < previousFrom) prependIndexes.push(i);\n }\n }\n }\n\n appendIndexes.forEach(index => {\n swiper.$wrapperEl.append(renderSlide(slides[index], index));\n });\n prependIndexes.sort((a, b) => b - a).forEach(index => {\n swiper.$wrapperEl.prepend(renderSlide(slides[index], index));\n });\n swiper.$wrapperEl.children('.swiper-slide').css(offsetProp, `${offset}px`);\n onRendered();\n }\n\n function appendSlide(slides) {\n if (typeof slides === 'object' && 'length' in slides) {\n for (let i = 0; i < slides.length; i += 1) {\n if (slides[i]) swiper.virtual.slides.push(slides[i]);\n }\n } else {\n swiper.virtual.slides.push(slides);\n }\n\n update(true);\n }\n\n function prependSlide(slides) {\n const activeIndex = swiper.activeIndex;\n let newActiveIndex = activeIndex + 1;\n let numberOfNewSlides = 1;\n\n if (Array.isArray(slides)) {\n for (let i = 0; i < slides.length; i += 1) {\n if (slides[i]) swiper.virtual.slides.unshift(slides[i]);\n }\n\n newActiveIndex = activeIndex + slides.length;\n numberOfNewSlides = slides.length;\n } else {\n swiper.virtual.slides.unshift(slides);\n }\n\n if (swiper.params.virtual.cache) {\n const cache = swiper.virtual.cache;\n const newCache = {};\n Object.keys(cache).forEach(cachedIndex => {\n const $cachedEl = cache[cachedIndex];\n const cachedElIndex = $cachedEl.attr('data-swiper-slide-index');\n\n if (cachedElIndex) {\n $cachedEl.attr('data-swiper-slide-index', parseInt(cachedElIndex, 10) + numberOfNewSlides);\n }\n\n newCache[parseInt(cachedIndex, 10) + numberOfNewSlides] = $cachedEl;\n });\n swiper.virtual.cache = newCache;\n }\n\n update(true);\n swiper.slideTo(newActiveIndex, 0);\n }\n\n function removeSlide(slidesIndexes) {\n if (typeof slidesIndexes === 'undefined' || slidesIndexes === null) return;\n let activeIndex = swiper.activeIndex;\n\n if (Array.isArray(slidesIndexes)) {\n for (let i = slidesIndexes.length - 1; i >= 0; i -= 1) {\n swiper.virtual.slides.splice(slidesIndexes[i], 1);\n\n if (swiper.params.virtual.cache) {\n delete swiper.virtual.cache[slidesIndexes[i]];\n }\n\n if (slidesIndexes[i] < activeIndex) activeIndex -= 1;\n activeIndex = Math.max(activeIndex, 0);\n }\n } else {\n swiper.virtual.slides.splice(slidesIndexes, 1);\n\n if (swiper.params.virtual.cache) {\n delete swiper.virtual.cache[slidesIndexes];\n }\n\n if (slidesIndexes < activeIndex) activeIndex -= 1;\n activeIndex = Math.max(activeIndex, 0);\n }\n\n update(true);\n swiper.slideTo(activeIndex, 0);\n }\n\n function removeAllSlides() {\n swiper.virtual.slides = [];\n\n if (swiper.params.virtual.cache) {\n swiper.virtual.cache = {};\n }\n\n update(true);\n swiper.slideTo(0, 0);\n }\n\n on('beforeInit', () => {\n if (!swiper.params.virtual.enabled) return;\n swiper.virtual.slides = swiper.params.virtual.slides;\n swiper.classNames.push(`${swiper.params.containerModifierClass}virtual`);\n swiper.params.watchSlidesProgress = true;\n swiper.originalParams.watchSlidesProgress = true;\n\n if (!swiper.params.initialSlide) {\n update();\n }\n });\n on('setTranslate', () => {\n if (!swiper.params.virtual.enabled) return;\n\n if (swiper.params.cssMode && !swiper._immediateVirtual) {\n clearTimeout(cssModeTimeout);\n cssModeTimeout = setTimeout(() => {\n update();\n }, 100);\n } else {\n update();\n }\n });\n on('init update resize', () => {\n if (!swiper.params.virtual.enabled) return;\n\n if (swiper.params.cssMode) {\n setCSSProperty(swiper.wrapperEl, '--swiper-virtual-size', `${swiper.virtualSize}px`);\n }\n });\n Object.assign(swiper.virtual, {\n appendSlide,\n prependSlide,\n removeSlide,\n removeAllSlides,\n update\n });\n }\n\n /* eslint-disable consistent-return */\n function Keyboard(_ref) {\n let {\n swiper,\n extendParams,\n on,\n emit\n } = _ref;\n const document = getDocument();\n const window = getWindow();\n swiper.keyboard = {\n enabled: false\n };\n extendParams({\n keyboard: {\n enabled: false,\n onlyInViewport: true,\n pageUpDown: true\n }\n });\n\n function handle(event) {\n if (!swiper.enabled) return;\n const {\n rtlTranslate: rtl\n } = swiper;\n let e = event;\n if (e.originalEvent) e = e.originalEvent; // jquery fix\n\n const kc = e.keyCode || e.charCode;\n const pageUpDown = swiper.params.keyboard.pageUpDown;\n const isPageUp = pageUpDown && kc === 33;\n const isPageDown = pageUpDown && kc === 34;\n const isArrowLeft = kc === 37;\n const isArrowRight = kc === 39;\n const isArrowUp = kc === 38;\n const isArrowDown = kc === 40; // Directions locks\n\n if (!swiper.allowSlideNext && (swiper.isHorizontal() && isArrowRight || swiper.isVertical() && isArrowDown || isPageDown)) {\n return false;\n }\n\n if (!swiper.allowSlidePrev && (swiper.isHorizontal() && isArrowLeft || swiper.isVertical() && isArrowUp || isPageUp)) {\n return false;\n }\n\n if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {\n return undefined;\n }\n\n if (document.activeElement && document.activeElement.nodeName && (document.activeElement.nodeName.toLowerCase() === 'input' || document.activeElement.nodeName.toLowerCase() === 'textarea')) {\n return undefined;\n }\n\n if (swiper.params.keyboard.onlyInViewport && (isPageUp || isPageDown || isArrowLeft || isArrowRight || isArrowUp || isArrowDown)) {\n let inView = false; // Check that swiper should be inside of visible area of window\n\n if (swiper.$el.parents(`.${swiper.params.slideClass}`).length > 0 && swiper.$el.parents(`.${swiper.params.slideActiveClass}`).length === 0) {\n return undefined;\n }\n\n const $el = swiper.$el;\n const swiperWidth = $el[0].clientWidth;\n const swiperHeight = $el[0].clientHeight;\n const windowWidth = window.innerWidth;\n const windowHeight = window.innerHeight;\n const swiperOffset = swiper.$el.offset();\n if (rtl) swiperOffset.left -= swiper.$el[0].scrollLeft;\n const swiperCoord = [[swiperOffset.left, swiperOffset.top], [swiperOffset.left + swiperWidth, swiperOffset.top], [swiperOffset.left, swiperOffset.top + swiperHeight], [swiperOffset.left + swiperWidth, swiperOffset.top + swiperHeight]];\n\n for (let i = 0; i < swiperCoord.length; i += 1) {\n const point = swiperCoord[i];\n\n if (point[0] >= 0 && point[0] <= windowWidth && point[1] >= 0 && point[1] <= windowHeight) {\n if (point[0] === 0 && point[1] === 0) continue; // eslint-disable-line\n\n inView = true;\n }\n }\n\n if (!inView) return undefined;\n }\n\n if (swiper.isHorizontal()) {\n if (isPageUp || isPageDown || isArrowLeft || isArrowRight) {\n if (e.preventDefault) e.preventDefault();else e.returnValue = false;\n }\n\n if ((isPageDown || isArrowRight) && !rtl || (isPageUp || isArrowLeft) && rtl) swiper.slideNext();\n if ((isPageUp || isArrowLeft) && !rtl || (isPageDown || isArrowRight) && rtl) swiper.slidePrev();\n } else {\n if (isPageUp || isPageDown || isArrowUp || isArrowDown) {\n if (e.preventDefault) e.preventDefault();else e.returnValue = false;\n }\n\n if (isPageDown || isArrowDown) swiper.slideNext();\n if (isPageUp || isArrowUp) swiper.slidePrev();\n }\n\n emit('keyPress', kc);\n return undefined;\n }\n\n function enable() {\n if (swiper.keyboard.enabled) return;\n $(document).on('keydown', handle);\n swiper.keyboard.enabled = true;\n }\n\n function disable() {\n if (!swiper.keyboard.enabled) return;\n $(document).off('keydown', handle);\n swiper.keyboard.enabled = false;\n }\n\n on('init', () => {\n if (swiper.params.keyboard.enabled) {\n enable();\n }\n });\n on('destroy', () => {\n if (swiper.keyboard.enabled) {\n disable();\n }\n });\n Object.assign(swiper.keyboard, {\n enable,\n disable\n });\n }\n\n /* eslint-disable consistent-return */\n function Mousewheel(_ref) {\n let {\n swiper,\n extendParams,\n on,\n emit\n } = _ref;\n const window = getWindow();\n extendParams({\n mousewheel: {\n enabled: false,\n releaseOnEdges: false,\n invert: false,\n forceToAxis: false,\n sensitivity: 1,\n eventsTarget: 'container',\n thresholdDelta: null,\n thresholdTime: null\n }\n });\n swiper.mousewheel = {\n enabled: false\n };\n let timeout;\n let lastScrollTime = now();\n let lastEventBeforeSnap;\n const recentWheelEvents = [];\n\n function normalize(e) {\n // Reasonable defaults\n const PIXEL_STEP = 10;\n const LINE_HEIGHT = 40;\n const PAGE_HEIGHT = 800;\n let sX = 0;\n let sY = 0; // spinX, spinY\n\n let pX = 0;\n let pY = 0; // pixelX, pixelY\n // Legacy\n\n if ('detail' in e) {\n sY = e.detail;\n }\n\n if ('wheelDelta' in e) {\n sY = -e.wheelDelta / 120;\n }\n\n if ('wheelDeltaY' in e) {\n sY = -e.wheelDeltaY / 120;\n }\n\n if ('wheelDeltaX' in e) {\n sX = -e.wheelDeltaX / 120;\n } // side scrolling on FF with DOMMouseScroll\n\n\n if ('axis' in e && e.axis === e.HORIZONTAL_AXIS) {\n sX = sY;\n sY = 0;\n }\n\n pX = sX * PIXEL_STEP;\n pY = sY * PIXEL_STEP;\n\n if ('deltaY' in e) {\n pY = e.deltaY;\n }\n\n if ('deltaX' in e) {\n pX = e.deltaX;\n }\n\n if (e.shiftKey && !pX) {\n // if user scrolls with shift he wants horizontal scroll\n pX = pY;\n pY = 0;\n }\n\n if ((pX || pY) && e.deltaMode) {\n if (e.deltaMode === 1) {\n // delta in LINE units\n pX *= LINE_HEIGHT;\n pY *= LINE_HEIGHT;\n } else {\n // delta in PAGE units\n pX *= PAGE_HEIGHT;\n pY *= PAGE_HEIGHT;\n }\n } // Fall-back if spin cannot be determined\n\n\n if (pX && !sX) {\n sX = pX < 1 ? -1 : 1;\n }\n\n if (pY && !sY) {\n sY = pY < 1 ? -1 : 1;\n }\n\n return {\n spinX: sX,\n spinY: sY,\n pixelX: pX,\n pixelY: pY\n };\n }\n\n function handleMouseEnter() {\n if (!swiper.enabled) return;\n swiper.mouseEntered = true;\n }\n\n function handleMouseLeave() {\n if (!swiper.enabled) return;\n swiper.mouseEntered = false;\n }\n\n function animateSlider(newEvent) {\n if (swiper.params.mousewheel.thresholdDelta && newEvent.delta < swiper.params.mousewheel.thresholdDelta) {\n // Prevent if delta of wheel scroll delta is below configured threshold\n return false;\n }\n\n if (swiper.params.mousewheel.thresholdTime && now() - lastScrollTime < swiper.params.mousewheel.thresholdTime) {\n // Prevent if time between scrolls is below configured threshold\n return false;\n } // If the movement is NOT big enough and\n // if the last time the user scrolled was too close to the current one (avoid continuously triggering the slider):\n // Don't go any further (avoid insignificant scroll movement).\n\n\n if (newEvent.delta >= 6 && now() - lastScrollTime < 60) {\n // Return false as a default\n return true;\n } // If user is scrolling towards the end:\n // If the slider hasn't hit the latest slide or\n // if the slider is a loop and\n // if the slider isn't moving right now:\n // Go to next slide and\n // emit a scroll event.\n // Else (the user is scrolling towards the beginning) and\n // if the slider hasn't hit the first slide or\n // if the slider is a loop and\n // if the slider isn't moving right now:\n // Go to prev slide and\n // emit a scroll event.\n\n\n if (newEvent.direction < 0) {\n if ((!swiper.isEnd || swiper.params.loop) && !swiper.animating) {\n swiper.slideNext();\n emit('scroll', newEvent.raw);\n }\n } else if ((!swiper.isBeginning || swiper.params.loop) && !swiper.animating) {\n swiper.slidePrev();\n emit('scroll', newEvent.raw);\n } // If you got here is because an animation has been triggered so store the current time\n\n\n lastScrollTime = new window.Date().getTime(); // Return false as a default\n\n return false;\n }\n\n function releaseScroll(newEvent) {\n const params = swiper.params.mousewheel;\n\n if (newEvent.direction < 0) {\n if (swiper.isEnd && !swiper.params.loop && params.releaseOnEdges) {\n // Return true to animate scroll on edges\n return true;\n }\n } else if (swiper.isBeginning && !swiper.params.loop && params.releaseOnEdges) {\n // Return true to animate scroll on edges\n return true;\n }\n\n return false;\n }\n\n function handle(event) {\n let e = event;\n let disableParentSwiper = true;\n if (!swiper.enabled) return;\n const params = swiper.params.mousewheel;\n\n if (swiper.params.cssMode) {\n e.preventDefault();\n }\n\n let target = swiper.$el;\n\n if (swiper.params.mousewheel.eventsTarget !== 'container') {\n target = $(swiper.params.mousewheel.eventsTarget);\n }\n\n if (!swiper.mouseEntered && !target[0].contains(e.target) && !params.releaseOnEdges) return true;\n if (e.originalEvent) e = e.originalEvent; // jquery fix\n\n let delta = 0;\n const rtlFactor = swiper.rtlTranslate ? -1 : 1;\n const data = normalize(e);\n\n if (params.forceToAxis) {\n if (swiper.isHorizontal()) {\n if (Math.abs(data.pixelX) > Math.abs(data.pixelY)) delta = -data.pixelX * rtlFactor;else return true;\n } else if (Math.abs(data.pixelY) > Math.abs(data.pixelX)) delta = -data.pixelY;else return true;\n } else {\n delta = Math.abs(data.pixelX) > Math.abs(data.pixelY) ? -data.pixelX * rtlFactor : -data.pixelY;\n }\n\n if (delta === 0) return true;\n if (params.invert) delta = -delta; // Get the scroll positions\n\n let positions = swiper.getTranslate() + delta * params.sensitivity;\n if (positions >= swiper.minTranslate()) positions = swiper.minTranslate();\n if (positions <= swiper.maxTranslate()) positions = swiper.maxTranslate(); // When loop is true:\n // the disableParentSwiper will be true.\n // When loop is false:\n // if the scroll positions is not on edge,\n // then the disableParentSwiper will be true.\n // if the scroll on edge positions,\n // then the disableParentSwiper will be false.\n\n disableParentSwiper = swiper.params.loop ? true : !(positions === swiper.minTranslate() || positions === swiper.maxTranslate());\n if (disableParentSwiper && swiper.params.nested) e.stopPropagation();\n\n if (!swiper.params.freeMode || !swiper.params.freeMode.enabled) {\n // Register the new event in a variable which stores the relevant data\n const newEvent = {\n time: now(),\n delta: Math.abs(delta),\n direction: Math.sign(delta),\n raw: event\n }; // Keep the most recent events\n\n if (recentWheelEvents.length >= 2) {\n recentWheelEvents.shift(); // only store the last N events\n }\n\n const prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined;\n recentWheelEvents.push(newEvent); // If there is at least one previous recorded event:\n // If direction has changed or\n // if the scroll is quicker than the previous one:\n // Animate the slider.\n // Else (this is the first time the wheel is moved):\n // Animate the slider.\n\n if (prevEvent) {\n if (newEvent.direction !== prevEvent.direction || newEvent.delta > prevEvent.delta || newEvent.time > prevEvent.time + 150) {\n animateSlider(newEvent);\n }\n } else {\n animateSlider(newEvent);\n } // If it's time to release the scroll:\n // Return now so you don't hit the preventDefault.\n\n\n if (releaseScroll(newEvent)) {\n return true;\n }\n } else {\n // Freemode or scrollContainer:\n // If we recently snapped after a momentum scroll, then ignore wheel events\n // to give time for the deceleration to finish. Stop ignoring after 500 msecs\n // or if it's a new scroll (larger delta or inverse sign as last event before\n // an end-of-momentum snap).\n const newEvent = {\n time: now(),\n delta: Math.abs(delta),\n direction: Math.sign(delta)\n };\n const ignoreWheelEvents = lastEventBeforeSnap && newEvent.time < lastEventBeforeSnap.time + 500 && newEvent.delta <= lastEventBeforeSnap.delta && newEvent.direction === lastEventBeforeSnap.direction;\n\n if (!ignoreWheelEvents) {\n lastEventBeforeSnap = undefined;\n\n if (swiper.params.loop) {\n swiper.loopFix();\n }\n\n let position = swiper.getTranslate() + delta * params.sensitivity;\n const wasBeginning = swiper.isBeginning;\n const wasEnd = swiper.isEnd;\n if (position >= swiper.minTranslate()) position = swiper.minTranslate();\n if (position <= swiper.maxTranslate()) position = swiper.maxTranslate();\n swiper.setTransition(0);\n swiper.setTranslate(position);\n swiper.updateProgress();\n swiper.updateActiveIndex();\n swiper.updateSlidesClasses();\n\n if (!wasBeginning && swiper.isBeginning || !wasEnd && swiper.isEnd) {\n swiper.updateSlidesClasses();\n }\n\n if (swiper.params.freeMode.sticky) {\n // When wheel scrolling starts with sticky (aka snap) enabled, then detect\n // the end of a momentum scroll by storing recent (N=15?) wheel events.\n // 1. do all N events have decreasing or same (absolute value) delta?\n // 2. did all N events arrive in the last M (M=500?) msecs?\n // 3. does the earliest event have an (absolute value) delta that's\n // at least P (P=1?) larger than the most recent event's delta?\n // 4. does the latest event have a delta that's smaller than Q (Q=6?) pixels?\n // If 1-4 are \"yes\" then we're near the end of a momentum scroll deceleration.\n // Snap immediately and ignore remaining wheel events in this scroll.\n // See comment above for \"remaining wheel events in this scroll\" determination.\n // If 1-4 aren't satisfied, then wait to snap until 500ms after the last event.\n clearTimeout(timeout);\n timeout = undefined;\n\n if (recentWheelEvents.length >= 15) {\n recentWheelEvents.shift(); // only store the last N events\n }\n\n const prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined;\n const firstEvent = recentWheelEvents[0];\n recentWheelEvents.push(newEvent);\n\n if (prevEvent && (newEvent.delta > prevEvent.delta || newEvent.direction !== prevEvent.direction)) {\n // Increasing or reverse-sign delta means the user started scrolling again. Clear the wheel event log.\n recentWheelEvents.splice(0);\n } else if (recentWheelEvents.length >= 15 && newEvent.time - firstEvent.time < 500 && firstEvent.delta - newEvent.delta >= 1 && newEvent.delta <= 6) {\n // We're at the end of the deceleration of a momentum scroll, so there's no need\n // to wait for more events. Snap ASAP on the next tick.\n // Also, because there's some remaining momentum we'll bias the snap in the\n // direction of the ongoing scroll because it's better UX for the scroll to snap\n // in the same direction as the scroll instead of reversing to snap. Therefore,\n // if it's already scrolled more than 20% in the current direction, keep going.\n const snapToThreshold = delta > 0 ? 0.8 : 0.2;\n lastEventBeforeSnap = newEvent;\n recentWheelEvents.splice(0);\n timeout = nextTick(() => {\n swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);\n }, 0); // no delay; move on next tick\n }\n\n if (!timeout) {\n // if we get here, then we haven't detected the end of a momentum scroll, so\n // we'll consider a scroll \"complete\" when there haven't been any wheel events\n // for 500ms.\n timeout = nextTick(() => {\n const snapToThreshold = 0.5;\n lastEventBeforeSnap = newEvent;\n recentWheelEvents.splice(0);\n swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);\n }, 500);\n }\n } // Emit event\n\n\n if (!ignoreWheelEvents) emit('scroll', e); // Stop autoplay\n\n if (swiper.params.autoplay && swiper.params.autoplayDisableOnInteraction) swiper.autoplay.stop(); // Return page scroll on edge positions\n\n if (position === swiper.minTranslate() || position === swiper.maxTranslate()) return true;\n }\n }\n\n if (e.preventDefault) e.preventDefault();else e.returnValue = false;\n return false;\n }\n\n function events(method) {\n let target = swiper.$el;\n\n if (swiper.params.mousewheel.eventsTarget !== 'container') {\n target = $(swiper.params.mousewheel.eventsTarget);\n }\n\n target[method]('mouseenter', handleMouseEnter);\n target[method]('mouseleave', handleMouseLeave);\n target[method]('wheel', handle);\n }\n\n function enable() {\n if (swiper.params.cssMode) {\n swiper.wrapperEl.removeEventListener('wheel', handle);\n return true;\n }\n\n if (swiper.mousewheel.enabled) return false;\n events('on');\n swiper.mousewheel.enabled = true;\n return true;\n }\n\n function disable() {\n if (swiper.params.cssMode) {\n swiper.wrapperEl.addEventListener(event, handle);\n return true;\n }\n\n if (!swiper.mousewheel.enabled) return false;\n events('off');\n swiper.mousewheel.enabled = false;\n return true;\n }\n\n on('init', () => {\n if (!swiper.params.mousewheel.enabled && swiper.params.cssMode) {\n disable();\n }\n\n if (swiper.params.mousewheel.enabled) enable();\n });\n on('destroy', () => {\n if (swiper.params.cssMode) {\n enable();\n }\n\n if (swiper.mousewheel.enabled) disable();\n });\n Object.assign(swiper.mousewheel, {\n enable,\n disable\n });\n }\n\n function createElementIfNotDefined(swiper, originalParams, params, checkProps) {\n const document = getDocument();\n\n if (swiper.params.createElements) {\n Object.keys(checkProps).forEach(key => {\n if (!params[key] && params.auto === true) {\n let element = swiper.$el.children(`.${checkProps[key]}`)[0];\n\n if (!element) {\n element = document.createElement('div');\n element.className = checkProps[key];\n swiper.$el.append(element);\n }\n\n params[key] = element;\n originalParams[key] = element;\n }\n });\n }\n\n return params;\n }\n\n function Navigation(_ref) {\n let {\n swiper,\n extendParams,\n on,\n emit\n } = _ref;\n extendParams({\n navigation: {\n nextEl: null,\n prevEl: null,\n hideOnClick: false,\n disabledClass: 'swiper-button-disabled',\n hiddenClass: 'swiper-button-hidden',\n lockClass: 'swiper-button-lock'\n }\n });\n swiper.navigation = {\n nextEl: null,\n $nextEl: null,\n prevEl: null,\n $prevEl: null\n };\n\n function getEl(el) {\n let $el;\n\n if (el) {\n $el = $(el);\n\n if (swiper.params.uniqueNavElements && typeof el === 'string' && $el.length > 1 && swiper.$el.find(el).length === 1) {\n $el = swiper.$el.find(el);\n }\n }\n\n return $el;\n }\n\n function toggleEl($el, disabled) {\n const params = swiper.params.navigation;\n\n if ($el && $el.length > 0) {\n $el[disabled ? 'addClass' : 'removeClass'](params.disabledClass);\n if ($el[0] && $el[0].tagName === 'BUTTON') $el[0].disabled = disabled;\n\n if (swiper.params.watchOverflow && swiper.enabled) {\n $el[swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);\n }\n }\n }\n\n function update() {\n // Update Navigation Buttons\n if (swiper.params.loop) return;\n const {\n $nextEl,\n $prevEl\n } = swiper.navigation;\n toggleEl($prevEl, swiper.isBeginning && !swiper.params.rewind);\n toggleEl($nextEl, swiper.isEnd && !swiper.params.rewind);\n }\n\n function onPrevClick(e) {\n e.preventDefault();\n if (swiper.isBeginning && !swiper.params.loop && !swiper.params.rewind) return;\n swiper.slidePrev();\n }\n\n function onNextClick(e) {\n e.preventDefault();\n if (swiper.isEnd && !swiper.params.loop && !swiper.params.rewind) return;\n swiper.slideNext();\n }\n\n function init() {\n const params = swiper.params.navigation;\n swiper.params.navigation = createElementIfNotDefined(swiper, swiper.originalParams.navigation, swiper.params.navigation, {\n nextEl: 'swiper-button-next',\n prevEl: 'swiper-button-prev'\n });\n if (!(params.nextEl || params.prevEl)) return;\n const $nextEl = getEl(params.nextEl);\n const $prevEl = getEl(params.prevEl);\n\n if ($nextEl && $nextEl.length > 0) {\n $nextEl.on('click', onNextClick);\n }\n\n if ($prevEl && $prevEl.length > 0) {\n $prevEl.on('click', onPrevClick);\n }\n\n Object.assign(swiper.navigation, {\n $nextEl,\n nextEl: $nextEl && $nextEl[0],\n $prevEl,\n prevEl: $prevEl && $prevEl[0]\n });\n\n if (!swiper.enabled) {\n if ($nextEl) $nextEl.addClass(params.lockClass);\n if ($prevEl) $prevEl.addClass(params.lockClass);\n }\n }\n\n function destroy() {\n const {\n $nextEl,\n $prevEl\n } = swiper.navigation;\n\n if ($nextEl && $nextEl.length) {\n $nextEl.off('click', onNextClick);\n $nextEl.removeClass(swiper.params.navigation.disabledClass);\n }\n\n if ($prevEl && $prevEl.length) {\n $prevEl.off('click', onPrevClick);\n $prevEl.removeClass(swiper.params.navigation.disabledClass);\n }\n }\n\n on('init', () => {\n init();\n update();\n });\n on('toEdge fromEdge lock unlock', () => {\n update();\n });\n on('destroy', () => {\n destroy();\n });\n on('enable disable', () => {\n const {\n $nextEl,\n $prevEl\n } = swiper.navigation;\n\n if ($nextEl) {\n $nextEl[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.navigation.lockClass);\n }\n\n if ($prevEl) {\n $prevEl[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.navigation.lockClass);\n }\n });\n on('click', (_s, e) => {\n const {\n $nextEl,\n $prevEl\n } = swiper.navigation;\n const targetEl = e.target;\n\n if (swiper.params.navigation.hideOnClick && !$(targetEl).is($prevEl) && !$(targetEl).is($nextEl)) {\n if (swiper.pagination && swiper.params.pagination && swiper.params.pagination.clickable && (swiper.pagination.el === targetEl || swiper.pagination.el.contains(targetEl))) return;\n let isHidden;\n\n if ($nextEl) {\n isHidden = $nextEl.hasClass(swiper.params.navigation.hiddenClass);\n } else if ($prevEl) {\n isHidden = $prevEl.hasClass(swiper.params.navigation.hiddenClass);\n }\n\n if (isHidden === true) {\n emit('navigationShow');\n } else {\n emit('navigationHide');\n }\n\n if ($nextEl) {\n $nextEl.toggleClass(swiper.params.navigation.hiddenClass);\n }\n\n if ($prevEl) {\n $prevEl.toggleClass(swiper.params.navigation.hiddenClass);\n }\n }\n });\n Object.assign(swiper.navigation, {\n update,\n init,\n destroy\n });\n }\n\n function classesToSelector(classes) {\n if (classes === void 0) {\n classes = '';\n }\n\n return `.${classes.trim().replace(/([\\.:!\\/])/g, '\\\\$1') // eslint-disable-line\n .replace(/ /g, '.')}`;\n }\n\n function Pagination(_ref) {\n let {\n swiper,\n extendParams,\n on,\n emit\n } = _ref;\n const pfx = 'swiper-pagination';\n extendParams({\n pagination: {\n el: null,\n bulletElement: 'span',\n clickable: false,\n hideOnClick: false,\n renderBullet: null,\n renderProgressbar: null,\n renderFraction: null,\n renderCustom: null,\n progressbarOpposite: false,\n type: 'bullets',\n // 'bullets' or 'progressbar' or 'fraction' or 'custom'\n dynamicBullets: false,\n dynamicMainBullets: 1,\n formatFractionCurrent: number => number,\n formatFractionTotal: number => number,\n bulletClass: `${pfx}-bullet`,\n bulletActiveClass: `${pfx}-bullet-active`,\n modifierClass: `${pfx}-`,\n currentClass: `${pfx}-current`,\n totalClass: `${pfx}-total`,\n hiddenClass: `${pfx}-hidden`,\n progressbarFillClass: `${pfx}-progressbar-fill`,\n progressbarOppositeClass: `${pfx}-progressbar-opposite`,\n clickableClass: `${pfx}-clickable`,\n lockClass: `${pfx}-lock`,\n horizontalClass: `${pfx}-horizontal`,\n verticalClass: `${pfx}-vertical`\n }\n });\n swiper.pagination = {\n el: null,\n $el: null,\n bullets: []\n };\n let bulletSize;\n let dynamicBulletIndex = 0;\n\n function isPaginationDisabled() {\n return !swiper.params.pagination.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0;\n }\n\n function setSideBullets($bulletEl, position) {\n const {\n bulletActiveClass\n } = swiper.params.pagination;\n $bulletEl[position]().addClass(`${bulletActiveClass}-${position}`)[position]().addClass(`${bulletActiveClass}-${position}-${position}`);\n }\n\n function update() {\n // Render || Update Pagination bullets/items\n const rtl = swiper.rtl;\n const params = swiper.params.pagination;\n if (isPaginationDisabled()) return;\n const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;\n const $el = swiper.pagination.$el; // Current/Total\n\n let current;\n const total = swiper.params.loop ? Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;\n\n if (swiper.params.loop) {\n current = Math.ceil((swiper.activeIndex - swiper.loopedSlides) / swiper.params.slidesPerGroup);\n\n if (current > slidesLength - 1 - swiper.loopedSlides * 2) {\n current -= slidesLength - swiper.loopedSlides * 2;\n }\n\n if (current > total - 1) current -= total;\n if (current < 0 && swiper.params.paginationType !== 'bullets') current = total + current;\n } else if (typeof swiper.snapIndex !== 'undefined') {\n current = swiper.snapIndex;\n } else {\n current = swiper.activeIndex || 0;\n } // Types\n\n\n if (params.type === 'bullets' && swiper.pagination.bullets && swiper.pagination.bullets.length > 0) {\n const bullets = swiper.pagination.bullets;\n let firstIndex;\n let lastIndex;\n let midIndex;\n\n if (params.dynamicBullets) {\n bulletSize = bullets.eq(0)[swiper.isHorizontal() ? 'outerWidth' : 'outerHeight'](true);\n $el.css(swiper.isHorizontal() ? 'width' : 'height', `${bulletSize * (params.dynamicMainBullets + 4)}px`);\n\n if (params.dynamicMainBullets > 1 && swiper.previousIndex !== undefined) {\n dynamicBulletIndex += current - (swiper.previousIndex - swiper.loopedSlides || 0);\n\n if (dynamicBulletIndex > params.dynamicMainBullets - 1) {\n dynamicBulletIndex = params.dynamicMainBullets - 1;\n } else if (dynamicBulletIndex < 0) {\n dynamicBulletIndex = 0;\n }\n }\n\n firstIndex = Math.max(current - dynamicBulletIndex, 0);\n lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);\n midIndex = (lastIndex + firstIndex) / 2;\n }\n\n bullets.removeClass(['', '-next', '-next-next', '-prev', '-prev-prev', '-main'].map(suffix => `${params.bulletActiveClass}${suffix}`).join(' '));\n\n if ($el.length > 1) {\n bullets.each(bullet => {\n const $bullet = $(bullet);\n const bulletIndex = $bullet.index();\n\n if (bulletIndex === current) {\n $bullet.addClass(params.bulletActiveClass);\n }\n\n if (params.dynamicBullets) {\n if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {\n $bullet.addClass(`${params.bulletActiveClass}-main`);\n }\n\n if (bulletIndex === firstIndex) {\n setSideBullets($bullet, 'prev');\n }\n\n if (bulletIndex === lastIndex) {\n setSideBullets($bullet, 'next');\n }\n }\n });\n } else {\n const $bullet = bullets.eq(current);\n const bulletIndex = $bullet.index();\n $bullet.addClass(params.bulletActiveClass);\n\n if (params.dynamicBullets) {\n const $firstDisplayedBullet = bullets.eq(firstIndex);\n const $lastDisplayedBullet = bullets.eq(lastIndex);\n\n for (let i = firstIndex; i <= lastIndex; i += 1) {\n bullets.eq(i).addClass(`${params.bulletActiveClass}-main`);\n }\n\n if (swiper.params.loop) {\n if (bulletIndex >= bullets.length) {\n for (let i = params.dynamicMainBullets; i >= 0; i -= 1) {\n bullets.eq(bullets.length - i).addClass(`${params.bulletActiveClass}-main`);\n }\n\n bullets.eq(bullets.length - params.dynamicMainBullets - 1).addClass(`${params.bulletActiveClass}-prev`);\n } else {\n setSideBullets($firstDisplayedBullet, 'prev');\n setSideBullets($lastDisplayedBullet, 'next');\n }\n } else {\n setSideBullets($firstDisplayedBullet, 'prev');\n setSideBullets($lastDisplayedBullet, 'next');\n }\n }\n }\n\n if (params.dynamicBullets) {\n const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);\n const bulletsOffset = (bulletSize * dynamicBulletsLength - bulletSize) / 2 - midIndex * bulletSize;\n const offsetProp = rtl ? 'right' : 'left';\n bullets.css(swiper.isHorizontal() ? offsetProp : 'top', `${bulletsOffset}px`);\n }\n }\n\n if (params.type === 'fraction') {\n $el.find(classesToSelector(params.currentClass)).text(params.formatFractionCurrent(current + 1));\n $el.find(classesToSelector(params.totalClass)).text(params.formatFractionTotal(total));\n }\n\n if (params.type === 'progressbar') {\n let progressbarDirection;\n\n if (params.progressbarOpposite) {\n progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';\n } else {\n progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';\n }\n\n const scale = (current + 1) / total;\n let scaleX = 1;\n let scaleY = 1;\n\n if (progressbarDirection === 'horizontal') {\n scaleX = scale;\n } else {\n scaleY = scale;\n }\n\n $el.find(classesToSelector(params.progressbarFillClass)).transform(`translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`).transition(swiper.params.speed);\n }\n\n if (params.type === 'custom' && params.renderCustom) {\n $el.html(params.renderCustom(swiper, current + 1, total));\n emit('paginationRender', $el[0]);\n } else {\n emit('paginationUpdate', $el[0]);\n }\n\n if (swiper.params.watchOverflow && swiper.enabled) {\n $el[swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);\n }\n }\n\n function render() {\n // Render Container\n const params = swiper.params.pagination;\n if (isPaginationDisabled()) return;\n const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;\n const $el = swiper.pagination.$el;\n let paginationHTML = '';\n\n if (params.type === 'bullets') {\n let numberOfBullets = swiper.params.loop ? Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;\n\n if (swiper.params.freeMode && swiper.params.freeMode.enabled && !swiper.params.loop && numberOfBullets > slidesLength) {\n numberOfBullets = slidesLength;\n }\n\n for (let i = 0; i < numberOfBullets; i += 1) {\n if (params.renderBullet) {\n paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);\n } else {\n paginationHTML += `<${params.bulletElement} class=\"${params.bulletClass}\">`;\n }\n }\n\n $el.html(paginationHTML);\n swiper.pagination.bullets = $el.find(classesToSelector(params.bulletClass));\n }\n\n if (params.type === 'fraction') {\n if (params.renderFraction) {\n paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);\n } else {\n paginationHTML = `` + ' / ' + ``;\n }\n\n $el.html(paginationHTML);\n }\n\n if (params.type === 'progressbar') {\n if (params.renderProgressbar) {\n paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);\n } else {\n paginationHTML = ``;\n }\n\n $el.html(paginationHTML);\n }\n\n if (params.type !== 'custom') {\n emit('paginationRender', swiper.pagination.$el[0]);\n }\n }\n\n function init() {\n swiper.params.pagination = createElementIfNotDefined(swiper, swiper.originalParams.pagination, swiper.params.pagination, {\n el: 'swiper-pagination'\n });\n const params = swiper.params.pagination;\n if (!params.el) return;\n let $el = $(params.el);\n if ($el.length === 0) return;\n\n if (swiper.params.uniqueNavElements && typeof params.el === 'string' && $el.length > 1) {\n $el = swiper.$el.find(params.el); // check if it belongs to another nested Swiper\n\n if ($el.length > 1) {\n $el = $el.filter(el => {\n if ($(el).parents('.swiper')[0] !== swiper.el) return false;\n return true;\n });\n }\n }\n\n if (params.type === 'bullets' && params.clickable) {\n $el.addClass(params.clickableClass);\n }\n\n $el.addClass(params.modifierClass + params.type);\n $el.addClass(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);\n\n if (params.type === 'bullets' && params.dynamicBullets) {\n $el.addClass(`${params.modifierClass}${params.type}-dynamic`);\n dynamicBulletIndex = 0;\n\n if (params.dynamicMainBullets < 1) {\n params.dynamicMainBullets = 1;\n }\n }\n\n if (params.type === 'progressbar' && params.progressbarOpposite) {\n $el.addClass(params.progressbarOppositeClass);\n }\n\n if (params.clickable) {\n $el.on('click', classesToSelector(params.bulletClass), function onClick(e) {\n e.preventDefault();\n let index = $(this).index() * swiper.params.slidesPerGroup;\n if (swiper.params.loop) index += swiper.loopedSlides;\n swiper.slideTo(index);\n });\n }\n\n Object.assign(swiper.pagination, {\n $el,\n el: $el[0]\n });\n\n if (!swiper.enabled) {\n $el.addClass(params.lockClass);\n }\n }\n\n function destroy() {\n const params = swiper.params.pagination;\n if (isPaginationDisabled()) return;\n const $el = swiper.pagination.$el;\n $el.removeClass(params.hiddenClass);\n $el.removeClass(params.modifierClass + params.type);\n $el.removeClass(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);\n if (swiper.pagination.bullets && swiper.pagination.bullets.removeClass) swiper.pagination.bullets.removeClass(params.bulletActiveClass);\n\n if (params.clickable) {\n $el.off('click', classesToSelector(params.bulletClass));\n }\n }\n\n on('init', () => {\n init();\n render();\n update();\n });\n on('activeIndexChange', () => {\n if (swiper.params.loop) {\n update();\n } else if (typeof swiper.snapIndex === 'undefined') {\n update();\n }\n });\n on('snapIndexChange', () => {\n if (!swiper.params.loop) {\n update();\n }\n });\n on('slidesLengthChange', () => {\n if (swiper.params.loop) {\n render();\n update();\n }\n });\n on('snapGridLengthChange', () => {\n if (!swiper.params.loop) {\n render();\n update();\n }\n });\n on('destroy', () => {\n destroy();\n });\n on('enable disable', () => {\n const {\n $el\n } = swiper.pagination;\n\n if ($el) {\n $el[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.pagination.lockClass);\n }\n });\n on('lock unlock', () => {\n update();\n });\n on('click', (_s, e) => {\n const targetEl = e.target;\n const {\n $el\n } = swiper.pagination;\n\n if (swiper.params.pagination.el && swiper.params.pagination.hideOnClick && $el.length > 0 && !$(targetEl).hasClass(swiper.params.pagination.bulletClass)) {\n if (swiper.navigation && (swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl || swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl)) return;\n const isHidden = $el.hasClass(swiper.params.pagination.hiddenClass);\n\n if (isHidden === true) {\n emit('paginationShow');\n } else {\n emit('paginationHide');\n }\n\n $el.toggleClass(swiper.params.pagination.hiddenClass);\n }\n });\n Object.assign(swiper.pagination, {\n render,\n update,\n init,\n destroy\n });\n }\n\n function Scrollbar(_ref) {\n let {\n swiper,\n extendParams,\n on,\n emit\n } = _ref;\n const document = getDocument();\n let isTouched = false;\n let timeout = null;\n let dragTimeout = null;\n let dragStartPos;\n let dragSize;\n let trackSize;\n let divider;\n extendParams({\n scrollbar: {\n el: null,\n dragSize: 'auto',\n hide: false,\n draggable: false,\n snapOnRelease: true,\n lockClass: 'swiper-scrollbar-lock',\n dragClass: 'swiper-scrollbar-drag'\n }\n });\n swiper.scrollbar = {\n el: null,\n dragEl: null,\n $el: null,\n $dragEl: null\n };\n\n function setTranslate() {\n if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;\n const {\n scrollbar,\n rtlTranslate: rtl,\n progress\n } = swiper;\n const {\n $dragEl,\n $el\n } = scrollbar;\n const params = swiper.params.scrollbar;\n let newSize = dragSize;\n let newPos = (trackSize - dragSize) * progress;\n\n if (rtl) {\n newPos = -newPos;\n\n if (newPos > 0) {\n newSize = dragSize - newPos;\n newPos = 0;\n } else if (-newPos + dragSize > trackSize) {\n newSize = trackSize + newPos;\n }\n } else if (newPos < 0) {\n newSize = dragSize + newPos;\n newPos = 0;\n } else if (newPos + dragSize > trackSize) {\n newSize = trackSize - newPos;\n }\n\n if (swiper.isHorizontal()) {\n $dragEl.transform(`translate3d(${newPos}px, 0, 0)`);\n $dragEl[0].style.width = `${newSize}px`;\n } else {\n $dragEl.transform(`translate3d(0px, ${newPos}px, 0)`);\n $dragEl[0].style.height = `${newSize}px`;\n }\n\n if (params.hide) {\n clearTimeout(timeout);\n $el[0].style.opacity = 1;\n timeout = setTimeout(() => {\n $el[0].style.opacity = 0;\n $el.transition(400);\n }, 1000);\n }\n }\n\n function setTransition(duration) {\n if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;\n swiper.scrollbar.$dragEl.transition(duration);\n }\n\n function updateSize() {\n if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;\n const {\n scrollbar\n } = swiper;\n const {\n $dragEl,\n $el\n } = scrollbar;\n $dragEl[0].style.width = '';\n $dragEl[0].style.height = '';\n trackSize = swiper.isHorizontal() ? $el[0].offsetWidth : $el[0].offsetHeight;\n divider = swiper.size / (swiper.virtualSize + swiper.params.slidesOffsetBefore - (swiper.params.centeredSlides ? swiper.snapGrid[0] : 0));\n\n if (swiper.params.scrollbar.dragSize === 'auto') {\n dragSize = trackSize * divider;\n } else {\n dragSize = parseInt(swiper.params.scrollbar.dragSize, 10);\n }\n\n if (swiper.isHorizontal()) {\n $dragEl[0].style.width = `${dragSize}px`;\n } else {\n $dragEl[0].style.height = `${dragSize}px`;\n }\n\n if (divider >= 1) {\n $el[0].style.display = 'none';\n } else {\n $el[0].style.display = '';\n }\n\n if (swiper.params.scrollbar.hide) {\n $el[0].style.opacity = 0;\n }\n\n if (swiper.params.watchOverflow && swiper.enabled) {\n scrollbar.$el[swiper.isLocked ? 'addClass' : 'removeClass'](swiper.params.scrollbar.lockClass);\n }\n }\n\n function getPointerPosition(e) {\n if (swiper.isHorizontal()) {\n return e.type === 'touchstart' || e.type === 'touchmove' ? e.targetTouches[0].clientX : e.clientX;\n }\n\n return e.type === 'touchstart' || e.type === 'touchmove' ? e.targetTouches[0].clientY : e.clientY;\n }\n\n function setDragPosition(e) {\n const {\n scrollbar,\n rtlTranslate: rtl\n } = swiper;\n const {\n $el\n } = scrollbar;\n let positionRatio;\n positionRatio = (getPointerPosition(e) - $el.offset()[swiper.isHorizontal() ? 'left' : 'top'] - (dragStartPos !== null ? dragStartPos : dragSize / 2)) / (trackSize - dragSize);\n positionRatio = Math.max(Math.min(positionRatio, 1), 0);\n\n if (rtl) {\n positionRatio = 1 - positionRatio;\n }\n\n const position = swiper.minTranslate() + (swiper.maxTranslate() - swiper.minTranslate()) * positionRatio;\n swiper.updateProgress(position);\n swiper.setTranslate(position);\n swiper.updateActiveIndex();\n swiper.updateSlidesClasses();\n }\n\n function onDragStart(e) {\n const params = swiper.params.scrollbar;\n const {\n scrollbar,\n $wrapperEl\n } = swiper;\n const {\n $el,\n $dragEl\n } = scrollbar;\n isTouched = true;\n dragStartPos = e.target === $dragEl[0] || e.target === $dragEl ? getPointerPosition(e) - e.target.getBoundingClientRect()[swiper.isHorizontal() ? 'left' : 'top'] : null;\n e.preventDefault();\n e.stopPropagation();\n $wrapperEl.transition(100);\n $dragEl.transition(100);\n setDragPosition(e);\n clearTimeout(dragTimeout);\n $el.transition(0);\n\n if (params.hide) {\n $el.css('opacity', 1);\n }\n\n if (swiper.params.cssMode) {\n swiper.$wrapperEl.css('scroll-snap-type', 'none');\n }\n\n emit('scrollbarDragStart', e);\n }\n\n function onDragMove(e) {\n const {\n scrollbar,\n $wrapperEl\n } = swiper;\n const {\n $el,\n $dragEl\n } = scrollbar;\n if (!isTouched) return;\n if (e.preventDefault) e.preventDefault();else e.returnValue = false;\n setDragPosition(e);\n $wrapperEl.transition(0);\n $el.transition(0);\n $dragEl.transition(0);\n emit('scrollbarDragMove', e);\n }\n\n function onDragEnd(e) {\n const params = swiper.params.scrollbar;\n const {\n scrollbar,\n $wrapperEl\n } = swiper;\n const {\n $el\n } = scrollbar;\n if (!isTouched) return;\n isTouched = false;\n\n if (swiper.params.cssMode) {\n swiper.$wrapperEl.css('scroll-snap-type', '');\n $wrapperEl.transition('');\n }\n\n if (params.hide) {\n clearTimeout(dragTimeout);\n dragTimeout = nextTick(() => {\n $el.css('opacity', 0);\n $el.transition(400);\n }, 1000);\n }\n\n emit('scrollbarDragEnd', e);\n\n if (params.snapOnRelease) {\n swiper.slideToClosest();\n }\n }\n\n function events(method) {\n const {\n scrollbar,\n touchEventsTouch,\n touchEventsDesktop,\n params,\n support\n } = swiper;\n const $el = scrollbar.$el;\n const target = $el[0];\n const activeListener = support.passiveListener && params.passiveListeners ? {\n passive: false,\n capture: false\n } : false;\n const passiveListener = support.passiveListener && params.passiveListeners ? {\n passive: true,\n capture: false\n } : false;\n if (!target) return;\n const eventMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';\n\n if (!support.touch) {\n target[eventMethod](touchEventsDesktop.start, onDragStart, activeListener);\n document[eventMethod](touchEventsDesktop.move, onDragMove, activeListener);\n document[eventMethod](touchEventsDesktop.end, onDragEnd, passiveListener);\n } else {\n target[eventMethod](touchEventsTouch.start, onDragStart, activeListener);\n target[eventMethod](touchEventsTouch.move, onDragMove, activeListener);\n target[eventMethod](touchEventsTouch.end, onDragEnd, passiveListener);\n }\n }\n\n function enableDraggable() {\n if (!swiper.params.scrollbar.el) return;\n events('on');\n }\n\n function disableDraggable() {\n if (!swiper.params.scrollbar.el) return;\n events('off');\n }\n\n function init() {\n const {\n scrollbar,\n $el: $swiperEl\n } = swiper;\n swiper.params.scrollbar = createElementIfNotDefined(swiper, swiper.originalParams.scrollbar, swiper.params.scrollbar, {\n el: 'swiper-scrollbar'\n });\n const params = swiper.params.scrollbar;\n if (!params.el) return;\n let $el = $(params.el);\n\n if (swiper.params.uniqueNavElements && typeof params.el === 'string' && $el.length > 1 && $swiperEl.find(params.el).length === 1) {\n $el = $swiperEl.find(params.el);\n }\n\n let $dragEl = $el.find(`.${swiper.params.scrollbar.dragClass}`);\n\n if ($dragEl.length === 0) {\n $dragEl = $(`
`);\n $el.append($dragEl);\n }\n\n Object.assign(scrollbar, {\n $el,\n el: $el[0],\n $dragEl,\n dragEl: $dragEl[0]\n });\n\n if (params.draggable) {\n enableDraggable();\n }\n\n if ($el) {\n $el[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.scrollbar.lockClass);\n }\n }\n\n function destroy() {\n disableDraggable();\n }\n\n on('init', () => {\n init();\n updateSize();\n setTranslate();\n });\n on('update resize observerUpdate lock unlock', () => {\n updateSize();\n });\n on('setTranslate', () => {\n setTranslate();\n });\n on('setTransition', (_s, duration) => {\n setTransition(duration);\n });\n on('enable disable', () => {\n const {\n $el\n } = swiper.scrollbar;\n\n if ($el) {\n $el[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.scrollbar.lockClass);\n }\n });\n on('destroy', () => {\n destroy();\n });\n Object.assign(swiper.scrollbar, {\n updateSize,\n setTranslate,\n init,\n destroy\n });\n }\n\n function Parallax(_ref) {\n let {\n swiper,\n extendParams,\n on\n } = _ref;\n extendParams({\n parallax: {\n enabled: false\n }\n });\n\n const setTransform = (el, progress) => {\n const {\n rtl\n } = swiper;\n const $el = $(el);\n const rtlFactor = rtl ? -1 : 1;\n const p = $el.attr('data-swiper-parallax') || '0';\n let x = $el.attr('data-swiper-parallax-x');\n let y = $el.attr('data-swiper-parallax-y');\n const scale = $el.attr('data-swiper-parallax-scale');\n const opacity = $el.attr('data-swiper-parallax-opacity');\n\n if (x || y) {\n x = x || '0';\n y = y || '0';\n } else if (swiper.isHorizontal()) {\n x = p;\n y = '0';\n } else {\n y = p;\n x = '0';\n }\n\n if (x.indexOf('%') >= 0) {\n x = `${parseInt(x, 10) * progress * rtlFactor}%`;\n } else {\n x = `${x * progress * rtlFactor}px`;\n }\n\n if (y.indexOf('%') >= 0) {\n y = `${parseInt(y, 10) * progress}%`;\n } else {\n y = `${y * progress}px`;\n }\n\n if (typeof opacity !== 'undefined' && opacity !== null) {\n const currentOpacity = opacity - (opacity - 1) * (1 - Math.abs(progress));\n $el[0].style.opacity = currentOpacity;\n }\n\n if (typeof scale === 'undefined' || scale === null) {\n $el.transform(`translate3d(${x}, ${y}, 0px)`);\n } else {\n const currentScale = scale - (scale - 1) * (1 - Math.abs(progress));\n $el.transform(`translate3d(${x}, ${y}, 0px) scale(${currentScale})`);\n }\n };\n\n const setTranslate = () => {\n const {\n $el,\n slides,\n progress,\n snapGrid\n } = swiper;\n $el.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]').each(el => {\n setTransform(el, progress);\n });\n slides.each((slideEl, slideIndex) => {\n let slideProgress = slideEl.progress;\n\n if (swiper.params.slidesPerGroup > 1 && swiper.params.slidesPerView !== 'auto') {\n slideProgress += Math.ceil(slideIndex / 2) - progress * (snapGrid.length - 1);\n }\n\n slideProgress = Math.min(Math.max(slideProgress, -1), 1);\n $(slideEl).find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]').each(el => {\n setTransform(el, slideProgress);\n });\n });\n };\n\n const setTransition = function (duration) {\n if (duration === void 0) {\n duration = swiper.params.speed;\n }\n\n const {\n $el\n } = swiper;\n $el.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]').each(parallaxEl => {\n const $parallaxEl = $(parallaxEl);\n let parallaxDuration = parseInt($parallaxEl.attr('data-swiper-parallax-duration'), 10) || duration;\n if (duration === 0) parallaxDuration = 0;\n $parallaxEl.transition(parallaxDuration);\n });\n };\n\n on('beforeInit', () => {\n if (!swiper.params.parallax.enabled) return;\n swiper.params.watchSlidesProgress = true;\n swiper.originalParams.watchSlidesProgress = true;\n });\n on('init', () => {\n if (!swiper.params.parallax.enabled) return;\n setTranslate();\n });\n on('setTranslate', () => {\n if (!swiper.params.parallax.enabled) return;\n setTranslate();\n });\n on('setTransition', (_swiper, duration) => {\n if (!swiper.params.parallax.enabled) return;\n setTransition(duration);\n });\n }\n\n function Zoom(_ref) {\n let {\n swiper,\n extendParams,\n on,\n emit\n } = _ref;\n const window = getWindow();\n extendParams({\n zoom: {\n enabled: false,\n maxRatio: 3,\n minRatio: 1,\n toggle: true,\n containerClass: 'swiper-zoom-container',\n zoomedSlideClass: 'swiper-slide-zoomed'\n }\n });\n swiper.zoom = {\n enabled: false\n };\n let currentScale = 1;\n let isScaling = false;\n let gesturesEnabled;\n let fakeGestureTouched;\n let fakeGestureMoved;\n const gesture = {\n $slideEl: undefined,\n slideWidth: undefined,\n slideHeight: undefined,\n $imageEl: undefined,\n $imageWrapEl: undefined,\n maxRatio: 3\n };\n const image = {\n isTouched: undefined,\n isMoved: undefined,\n currentX: undefined,\n currentY: undefined,\n minX: undefined,\n minY: undefined,\n maxX: undefined,\n maxY: undefined,\n width: undefined,\n height: undefined,\n startX: undefined,\n startY: undefined,\n touchesStart: {},\n touchesCurrent: {}\n };\n const velocity = {\n x: undefined,\n y: undefined,\n prevPositionX: undefined,\n prevPositionY: undefined,\n prevTime: undefined\n };\n let scale = 1;\n Object.defineProperty(swiper.zoom, 'scale', {\n get() {\n return scale;\n },\n\n set(value) {\n if (scale !== value) {\n const imageEl = gesture.$imageEl ? gesture.$imageEl[0] : undefined;\n const slideEl = gesture.$slideEl ? gesture.$slideEl[0] : undefined;\n emit('zoomChange', value, imageEl, slideEl);\n }\n\n scale = value;\n }\n\n });\n\n function getDistanceBetweenTouches(e) {\n if (e.targetTouches.length < 2) return 1;\n const x1 = e.targetTouches[0].pageX;\n const y1 = e.targetTouches[0].pageY;\n const x2 = e.targetTouches[1].pageX;\n const y2 = e.targetTouches[1].pageY;\n const distance = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);\n return distance;\n } // Events\n\n\n function onGestureStart(e) {\n const support = swiper.support;\n const params = swiper.params.zoom;\n fakeGestureTouched = false;\n fakeGestureMoved = false;\n\n if (!support.gestures) {\n if (e.type !== 'touchstart' || e.type === 'touchstart' && e.targetTouches.length < 2) {\n return;\n }\n\n fakeGestureTouched = true;\n gesture.scaleStart = getDistanceBetweenTouches(e);\n }\n\n if (!gesture.$slideEl || !gesture.$slideEl.length) {\n gesture.$slideEl = $(e.target).closest(`.${swiper.params.slideClass}`);\n if (gesture.$slideEl.length === 0) gesture.$slideEl = swiper.slides.eq(swiper.activeIndex);\n gesture.$imageEl = gesture.$slideEl.find(`.${params.containerClass}`).eq(0).find('picture, img, svg, canvas, .swiper-zoom-target').eq(0);\n gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);\n gesture.maxRatio = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;\n\n if (gesture.$imageWrapEl.length === 0) {\n gesture.$imageEl = undefined;\n return;\n }\n }\n\n if (gesture.$imageEl) {\n gesture.$imageEl.transition(0);\n }\n\n isScaling = true;\n }\n\n function onGestureChange(e) {\n const support = swiper.support;\n const params = swiper.params.zoom;\n const zoom = swiper.zoom;\n\n if (!support.gestures) {\n if (e.type !== 'touchmove' || e.type === 'touchmove' && e.targetTouches.length < 2) {\n return;\n }\n\n fakeGestureMoved = true;\n gesture.scaleMove = getDistanceBetweenTouches(e);\n }\n\n if (!gesture.$imageEl || gesture.$imageEl.length === 0) {\n if (e.type === 'gesturechange') onGestureStart(e);\n return;\n }\n\n if (support.gestures) {\n zoom.scale = e.scale * currentScale;\n } else {\n zoom.scale = gesture.scaleMove / gesture.scaleStart * currentScale;\n }\n\n if (zoom.scale > gesture.maxRatio) {\n zoom.scale = gesture.maxRatio - 1 + (zoom.scale - gesture.maxRatio + 1) ** 0.5;\n }\n\n if (zoom.scale < params.minRatio) {\n zoom.scale = params.minRatio + 1 - (params.minRatio - zoom.scale + 1) ** 0.5;\n }\n\n gesture.$imageEl.transform(`translate3d(0,0,0) scale(${zoom.scale})`);\n }\n\n function onGestureEnd(e) {\n const device = swiper.device;\n const support = swiper.support;\n const params = swiper.params.zoom;\n const zoom = swiper.zoom;\n\n if (!support.gestures) {\n if (!fakeGestureTouched || !fakeGestureMoved) {\n return;\n }\n\n if (e.type !== 'touchend' || e.type === 'touchend' && e.changedTouches.length < 2 && !device.android) {\n return;\n }\n\n fakeGestureTouched = false;\n fakeGestureMoved = false;\n }\n\n if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;\n zoom.scale = Math.max(Math.min(zoom.scale, gesture.maxRatio), params.minRatio);\n gesture.$imageEl.transition(swiper.params.speed).transform(`translate3d(0,0,0) scale(${zoom.scale})`);\n currentScale = zoom.scale;\n isScaling = false;\n if (zoom.scale === 1) gesture.$slideEl = undefined;\n }\n\n function onTouchStart(e) {\n const device = swiper.device;\n if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;\n if (image.isTouched) return;\n if (device.android && e.cancelable) e.preventDefault();\n image.isTouched = true;\n image.touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;\n image.touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;\n }\n\n function onTouchMove(e) {\n const zoom = swiper.zoom;\n if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;\n swiper.allowClick = false;\n if (!image.isTouched || !gesture.$slideEl) return;\n\n if (!image.isMoved) {\n image.width = gesture.$imageEl[0].offsetWidth;\n image.height = gesture.$imageEl[0].offsetHeight;\n image.startX = getTranslate(gesture.$imageWrapEl[0], 'x') || 0;\n image.startY = getTranslate(gesture.$imageWrapEl[0], 'y') || 0;\n gesture.slideWidth = gesture.$slideEl[0].offsetWidth;\n gesture.slideHeight = gesture.$slideEl[0].offsetHeight;\n gesture.$imageWrapEl.transition(0);\n } // Define if we need image drag\n\n\n const scaledWidth = image.width * zoom.scale;\n const scaledHeight = image.height * zoom.scale;\n if (scaledWidth < gesture.slideWidth && scaledHeight < gesture.slideHeight) return;\n image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0);\n image.maxX = -image.minX;\n image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0);\n image.maxY = -image.minY;\n image.touchesCurrent.x = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;\n image.touchesCurrent.y = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;\n\n if (!image.isMoved && !isScaling) {\n if (swiper.isHorizontal() && (Math.floor(image.minX) === Math.floor(image.startX) && image.touchesCurrent.x < image.touchesStart.x || Math.floor(image.maxX) === Math.floor(image.startX) && image.touchesCurrent.x > image.touchesStart.x)) {\n image.isTouched = false;\n return;\n }\n\n if (!swiper.isHorizontal() && (Math.floor(image.minY) === Math.floor(image.startY) && image.touchesCurrent.y < image.touchesStart.y || Math.floor(image.maxY) === Math.floor(image.startY) && image.touchesCurrent.y > image.touchesStart.y)) {\n image.isTouched = false;\n return;\n }\n }\n\n if (e.cancelable) {\n e.preventDefault();\n }\n\n e.stopPropagation();\n image.isMoved = true;\n image.currentX = image.touchesCurrent.x - image.touchesStart.x + image.startX;\n image.currentY = image.touchesCurrent.y - image.touchesStart.y + image.startY;\n\n if (image.currentX < image.minX) {\n image.currentX = image.minX + 1 - (image.minX - image.currentX + 1) ** 0.8;\n }\n\n if (image.currentX > image.maxX) {\n image.currentX = image.maxX - 1 + (image.currentX - image.maxX + 1) ** 0.8;\n }\n\n if (image.currentY < image.minY) {\n image.currentY = image.minY + 1 - (image.minY - image.currentY + 1) ** 0.8;\n }\n\n if (image.currentY > image.maxY) {\n image.currentY = image.maxY - 1 + (image.currentY - image.maxY + 1) ** 0.8;\n } // Velocity\n\n\n if (!velocity.prevPositionX) velocity.prevPositionX = image.touchesCurrent.x;\n if (!velocity.prevPositionY) velocity.prevPositionY = image.touchesCurrent.y;\n if (!velocity.prevTime) velocity.prevTime = Date.now();\n velocity.x = (image.touchesCurrent.x - velocity.prevPositionX) / (Date.now() - velocity.prevTime) / 2;\n velocity.y = (image.touchesCurrent.y - velocity.prevPositionY) / (Date.now() - velocity.prevTime) / 2;\n if (Math.abs(image.touchesCurrent.x - velocity.prevPositionX) < 2) velocity.x = 0;\n if (Math.abs(image.touchesCurrent.y - velocity.prevPositionY) < 2) velocity.y = 0;\n velocity.prevPositionX = image.touchesCurrent.x;\n velocity.prevPositionY = image.touchesCurrent.y;\n velocity.prevTime = Date.now();\n gesture.$imageWrapEl.transform(`translate3d(${image.currentX}px, ${image.currentY}px,0)`);\n }\n\n function onTouchEnd() {\n const zoom = swiper.zoom;\n if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;\n\n if (!image.isTouched || !image.isMoved) {\n image.isTouched = false;\n image.isMoved = false;\n return;\n }\n\n image.isTouched = false;\n image.isMoved = false;\n let momentumDurationX = 300;\n let momentumDurationY = 300;\n const momentumDistanceX = velocity.x * momentumDurationX;\n const newPositionX = image.currentX + momentumDistanceX;\n const momentumDistanceY = velocity.y * momentumDurationY;\n const newPositionY = image.currentY + momentumDistanceY; // Fix duration\n\n if (velocity.x !== 0) momentumDurationX = Math.abs((newPositionX - image.currentX) / velocity.x);\n if (velocity.y !== 0) momentumDurationY = Math.abs((newPositionY - image.currentY) / velocity.y);\n const momentumDuration = Math.max(momentumDurationX, momentumDurationY);\n image.currentX = newPositionX;\n image.currentY = newPositionY; // Define if we need image drag\n\n const scaledWidth = image.width * zoom.scale;\n const scaledHeight = image.height * zoom.scale;\n image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0);\n image.maxX = -image.minX;\n image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0);\n image.maxY = -image.minY;\n image.currentX = Math.max(Math.min(image.currentX, image.maxX), image.minX);\n image.currentY = Math.max(Math.min(image.currentY, image.maxY), image.minY);\n gesture.$imageWrapEl.transition(momentumDuration).transform(`translate3d(${image.currentX}px, ${image.currentY}px,0)`);\n }\n\n function onTransitionEnd() {\n const zoom = swiper.zoom;\n\n if (gesture.$slideEl && swiper.previousIndex !== swiper.activeIndex) {\n if (gesture.$imageEl) {\n gesture.$imageEl.transform('translate3d(0,0,0) scale(1)');\n }\n\n if (gesture.$imageWrapEl) {\n gesture.$imageWrapEl.transform('translate3d(0,0,0)');\n }\n\n zoom.scale = 1;\n currentScale = 1;\n gesture.$slideEl = undefined;\n gesture.$imageEl = undefined;\n gesture.$imageWrapEl = undefined;\n }\n }\n\n function zoomIn(e) {\n const zoom = swiper.zoom;\n const params = swiper.params.zoom;\n\n if (!gesture.$slideEl) {\n if (e && e.target) {\n gesture.$slideEl = $(e.target).closest(`.${swiper.params.slideClass}`);\n }\n\n if (!gesture.$slideEl) {\n if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) {\n gesture.$slideEl = swiper.$wrapperEl.children(`.${swiper.params.slideActiveClass}`);\n } else {\n gesture.$slideEl = swiper.slides.eq(swiper.activeIndex);\n }\n }\n\n gesture.$imageEl = gesture.$slideEl.find(`.${params.containerClass}`).eq(0).find('picture, img, svg, canvas, .swiper-zoom-target').eq(0);\n gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);\n }\n\n if (!gesture.$imageEl || gesture.$imageEl.length === 0 || !gesture.$imageWrapEl || gesture.$imageWrapEl.length === 0) return;\n\n if (swiper.params.cssMode) {\n swiper.wrapperEl.style.overflow = 'hidden';\n swiper.wrapperEl.style.touchAction = 'none';\n }\n\n gesture.$slideEl.addClass(`${params.zoomedSlideClass}`);\n let touchX;\n let touchY;\n let offsetX;\n let offsetY;\n let diffX;\n let diffY;\n let translateX;\n let translateY;\n let imageWidth;\n let imageHeight;\n let scaledWidth;\n let scaledHeight;\n let translateMinX;\n let translateMinY;\n let translateMaxX;\n let translateMaxY;\n let slideWidth;\n let slideHeight;\n\n if (typeof image.touchesStart.x === 'undefined' && e) {\n touchX = e.type === 'touchend' ? e.changedTouches[0].pageX : e.pageX;\n touchY = e.type === 'touchend' ? e.changedTouches[0].pageY : e.pageY;\n } else {\n touchX = image.touchesStart.x;\n touchY = image.touchesStart.y;\n }\n\n zoom.scale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;\n currentScale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;\n\n if (e) {\n slideWidth = gesture.$slideEl[0].offsetWidth;\n slideHeight = gesture.$slideEl[0].offsetHeight;\n offsetX = gesture.$slideEl.offset().left + window.scrollX;\n offsetY = gesture.$slideEl.offset().top + window.scrollY;\n diffX = offsetX + slideWidth / 2 - touchX;\n diffY = offsetY + slideHeight / 2 - touchY;\n imageWidth = gesture.$imageEl[0].offsetWidth;\n imageHeight = gesture.$imageEl[0].offsetHeight;\n scaledWidth = imageWidth * zoom.scale;\n scaledHeight = imageHeight * zoom.scale;\n translateMinX = Math.min(slideWidth / 2 - scaledWidth / 2, 0);\n translateMinY = Math.min(slideHeight / 2 - scaledHeight / 2, 0);\n translateMaxX = -translateMinX;\n translateMaxY = -translateMinY;\n translateX = diffX * zoom.scale;\n translateY = diffY * zoom.scale;\n\n if (translateX < translateMinX) {\n translateX = translateMinX;\n }\n\n if (translateX > translateMaxX) {\n translateX = translateMaxX;\n }\n\n if (translateY < translateMinY) {\n translateY = translateMinY;\n }\n\n if (translateY > translateMaxY) {\n translateY = translateMaxY;\n }\n } else {\n translateX = 0;\n translateY = 0;\n }\n\n gesture.$imageWrapEl.transition(300).transform(`translate3d(${translateX}px, ${translateY}px,0)`);\n gesture.$imageEl.transition(300).transform(`translate3d(0,0,0) scale(${zoom.scale})`);\n }\n\n function zoomOut() {\n const zoom = swiper.zoom;\n const params = swiper.params.zoom;\n\n if (!gesture.$slideEl) {\n if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) {\n gesture.$slideEl = swiper.$wrapperEl.children(`.${swiper.params.slideActiveClass}`);\n } else {\n gesture.$slideEl = swiper.slides.eq(swiper.activeIndex);\n }\n\n gesture.$imageEl = gesture.$slideEl.find(`.${params.containerClass}`).eq(0).find('picture, img, svg, canvas, .swiper-zoom-target').eq(0);\n gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);\n }\n\n if (!gesture.$imageEl || gesture.$imageEl.length === 0 || !gesture.$imageWrapEl || gesture.$imageWrapEl.length === 0) return;\n\n if (swiper.params.cssMode) {\n swiper.wrapperEl.style.overflow = '';\n swiper.wrapperEl.style.touchAction = '';\n }\n\n zoom.scale = 1;\n currentScale = 1;\n gesture.$imageWrapEl.transition(300).transform('translate3d(0,0,0)');\n gesture.$imageEl.transition(300).transform('translate3d(0,0,0) scale(1)');\n gesture.$slideEl.removeClass(`${params.zoomedSlideClass}`);\n gesture.$slideEl = undefined;\n } // Toggle Zoom\n\n\n function zoomToggle(e) {\n const zoom = swiper.zoom;\n\n if (zoom.scale && zoom.scale !== 1) {\n // Zoom Out\n zoomOut();\n } else {\n // Zoom In\n zoomIn(e);\n }\n }\n\n function getListeners() {\n const support = swiper.support;\n const passiveListener = swiper.touchEvents.start === 'touchstart' && support.passiveListener && swiper.params.passiveListeners ? {\n passive: true,\n capture: false\n } : false;\n const activeListenerWithCapture = support.passiveListener ? {\n passive: false,\n capture: true\n } : true;\n return {\n passiveListener,\n activeListenerWithCapture\n };\n }\n\n function getSlideSelector() {\n return `.${swiper.params.slideClass}`;\n }\n\n function toggleGestures(method) {\n const {\n passiveListener\n } = getListeners();\n const slideSelector = getSlideSelector();\n swiper.$wrapperEl[method]('gesturestart', slideSelector, onGestureStart, passiveListener);\n swiper.$wrapperEl[method]('gesturechange', slideSelector, onGestureChange, passiveListener);\n swiper.$wrapperEl[method]('gestureend', slideSelector, onGestureEnd, passiveListener);\n }\n\n function enableGestures() {\n if (gesturesEnabled) return;\n gesturesEnabled = true;\n toggleGestures('on');\n }\n\n function disableGestures() {\n if (!gesturesEnabled) return;\n gesturesEnabled = false;\n toggleGestures('off');\n } // Attach/Detach Events\n\n\n function enable() {\n const zoom = swiper.zoom;\n if (zoom.enabled) return;\n zoom.enabled = true;\n const support = swiper.support;\n const {\n passiveListener,\n activeListenerWithCapture\n } = getListeners();\n const slideSelector = getSlideSelector(); // Scale image\n\n if (support.gestures) {\n swiper.$wrapperEl.on(swiper.touchEvents.start, enableGestures, passiveListener);\n swiper.$wrapperEl.on(swiper.touchEvents.end, disableGestures, passiveListener);\n } else if (swiper.touchEvents.start === 'touchstart') {\n swiper.$wrapperEl.on(swiper.touchEvents.start, slideSelector, onGestureStart, passiveListener);\n swiper.$wrapperEl.on(swiper.touchEvents.move, slideSelector, onGestureChange, activeListenerWithCapture);\n swiper.$wrapperEl.on(swiper.touchEvents.end, slideSelector, onGestureEnd, passiveListener);\n\n if (swiper.touchEvents.cancel) {\n swiper.$wrapperEl.on(swiper.touchEvents.cancel, slideSelector, onGestureEnd, passiveListener);\n }\n } // Move image\n\n\n swiper.$wrapperEl.on(swiper.touchEvents.move, `.${swiper.params.zoom.containerClass}`, onTouchMove, activeListenerWithCapture);\n }\n\n function disable() {\n const zoom = swiper.zoom;\n if (!zoom.enabled) return;\n const support = swiper.support;\n zoom.enabled = false;\n const {\n passiveListener,\n activeListenerWithCapture\n } = getListeners();\n const slideSelector = getSlideSelector(); // Scale image\n\n if (support.gestures) {\n swiper.$wrapperEl.off(swiper.touchEvents.start, enableGestures, passiveListener);\n swiper.$wrapperEl.off(swiper.touchEvents.end, disableGestures, passiveListener);\n } else if (swiper.touchEvents.start === 'touchstart') {\n swiper.$wrapperEl.off(swiper.touchEvents.start, slideSelector, onGestureStart, passiveListener);\n swiper.$wrapperEl.off(swiper.touchEvents.move, slideSelector, onGestureChange, activeListenerWithCapture);\n swiper.$wrapperEl.off(swiper.touchEvents.end, slideSelector, onGestureEnd, passiveListener);\n\n if (swiper.touchEvents.cancel) {\n swiper.$wrapperEl.off(swiper.touchEvents.cancel, slideSelector, onGestureEnd, passiveListener);\n }\n } // Move image\n\n\n swiper.$wrapperEl.off(swiper.touchEvents.move, `.${swiper.params.zoom.containerClass}`, onTouchMove, activeListenerWithCapture);\n }\n\n on('init', () => {\n if (swiper.params.zoom.enabled) {\n enable();\n }\n });\n on('destroy', () => {\n disable();\n });\n on('touchStart', (_s, e) => {\n if (!swiper.zoom.enabled) return;\n onTouchStart(e);\n });\n on('touchEnd', (_s, e) => {\n if (!swiper.zoom.enabled) return;\n onTouchEnd();\n });\n on('doubleTap', (_s, e) => {\n if (!swiper.animating && swiper.params.zoom.enabled && swiper.zoom.enabled && swiper.params.zoom.toggle) {\n zoomToggle(e);\n }\n });\n on('transitionEnd', () => {\n if (swiper.zoom.enabled && swiper.params.zoom.enabled) {\n onTransitionEnd();\n }\n });\n on('slideChange', () => {\n if (swiper.zoom.enabled && swiper.params.zoom.enabled && swiper.params.cssMode) {\n onTransitionEnd();\n }\n });\n Object.assign(swiper.zoom, {\n enable,\n disable,\n in: zoomIn,\n out: zoomOut,\n toggle: zoomToggle\n });\n }\n\n function Lazy(_ref) {\n let {\n swiper,\n extendParams,\n on,\n emit\n } = _ref;\n extendParams({\n lazy: {\n checkInView: false,\n enabled: false,\n loadPrevNext: false,\n loadPrevNextAmount: 1,\n loadOnTransitionStart: false,\n scrollingElement: '',\n elementClass: 'swiper-lazy',\n loadingClass: 'swiper-lazy-loading',\n loadedClass: 'swiper-lazy-loaded',\n preloaderClass: 'swiper-lazy-preloader'\n }\n });\n swiper.lazy = {};\n let scrollHandlerAttached = false;\n let initialImageLoaded = false;\n\n function loadInSlide(index, loadInDuplicate) {\n if (loadInDuplicate === void 0) {\n loadInDuplicate = true;\n }\n\n const params = swiper.params.lazy;\n if (typeof index === 'undefined') return;\n if (swiper.slides.length === 0) return;\n const isVirtual = swiper.virtual && swiper.params.virtual.enabled;\n const $slideEl = isVirtual ? swiper.$wrapperEl.children(`.${swiper.params.slideClass}[data-swiper-slide-index=\"${index}\"]`) : swiper.slides.eq(index);\n const $images = $slideEl.find(`.${params.elementClass}:not(.${params.loadedClass}):not(.${params.loadingClass})`);\n\n if ($slideEl.hasClass(params.elementClass) && !$slideEl.hasClass(params.loadedClass) && !$slideEl.hasClass(params.loadingClass)) {\n $images.push($slideEl[0]);\n }\n\n if ($images.length === 0) return;\n $images.each(imageEl => {\n const $imageEl = $(imageEl);\n $imageEl.addClass(params.loadingClass);\n const background = $imageEl.attr('data-background');\n const src = $imageEl.attr('data-src');\n const srcset = $imageEl.attr('data-srcset');\n const sizes = $imageEl.attr('data-sizes');\n const $pictureEl = $imageEl.parent('picture');\n swiper.loadImage($imageEl[0], src || background, srcset, sizes, false, () => {\n if (typeof swiper === 'undefined' || swiper === null || !swiper || swiper && !swiper.params || swiper.destroyed) return;\n\n if (background) {\n $imageEl.css('background-image', `url(\"${background}\")`);\n $imageEl.removeAttr('data-background');\n } else {\n if (srcset) {\n $imageEl.attr('srcset', srcset);\n $imageEl.removeAttr('data-srcset');\n }\n\n if (sizes) {\n $imageEl.attr('sizes', sizes);\n $imageEl.removeAttr('data-sizes');\n }\n\n if ($pictureEl.length) {\n $pictureEl.children('source').each(sourceEl => {\n const $source = $(sourceEl);\n\n if ($source.attr('data-srcset')) {\n $source.attr('srcset', $source.attr('data-srcset'));\n $source.removeAttr('data-srcset');\n }\n });\n }\n\n if (src) {\n $imageEl.attr('src', src);\n $imageEl.removeAttr('data-src');\n }\n }\n\n $imageEl.addClass(params.loadedClass).removeClass(params.loadingClass);\n $slideEl.find(`.${params.preloaderClass}`).remove();\n\n if (swiper.params.loop && loadInDuplicate) {\n const slideOriginalIndex = $slideEl.attr('data-swiper-slide-index');\n\n if ($slideEl.hasClass(swiper.params.slideDuplicateClass)) {\n const originalSlide = swiper.$wrapperEl.children(`[data-swiper-slide-index=\"${slideOriginalIndex}\"]:not(.${swiper.params.slideDuplicateClass})`);\n loadInSlide(originalSlide.index(), false);\n } else {\n const duplicatedSlide = swiper.$wrapperEl.children(`.${swiper.params.slideDuplicateClass}[data-swiper-slide-index=\"${slideOriginalIndex}\"]`);\n loadInSlide(duplicatedSlide.index(), false);\n }\n }\n\n emit('lazyImageReady', $slideEl[0], $imageEl[0]);\n\n if (swiper.params.autoHeight) {\n swiper.updateAutoHeight();\n }\n });\n emit('lazyImageLoad', $slideEl[0], $imageEl[0]);\n });\n }\n\n function load() {\n const {\n $wrapperEl,\n params: swiperParams,\n slides,\n activeIndex\n } = swiper;\n const isVirtual = swiper.virtual && swiperParams.virtual.enabled;\n const params = swiperParams.lazy;\n let slidesPerView = swiperParams.slidesPerView;\n\n if (slidesPerView === 'auto') {\n slidesPerView = 0;\n }\n\n function slideExist(index) {\n if (isVirtual) {\n if ($wrapperEl.children(`.${swiperParams.slideClass}[data-swiper-slide-index=\"${index}\"]`).length) {\n return true;\n }\n } else if (slides[index]) return true;\n\n return false;\n }\n\n function slideIndex(slideEl) {\n if (isVirtual) {\n return $(slideEl).attr('data-swiper-slide-index');\n }\n\n return $(slideEl).index();\n }\n\n if (!initialImageLoaded) initialImageLoaded = true;\n\n if (swiper.params.watchSlidesProgress) {\n $wrapperEl.children(`.${swiperParams.slideVisibleClass}`).each(slideEl => {\n const index = isVirtual ? $(slideEl).attr('data-swiper-slide-index') : $(slideEl).index();\n loadInSlide(index);\n });\n } else if (slidesPerView > 1) {\n for (let i = activeIndex; i < activeIndex + slidesPerView; i += 1) {\n if (slideExist(i)) loadInSlide(i);\n }\n } else {\n loadInSlide(activeIndex);\n }\n\n if (params.loadPrevNext) {\n if (slidesPerView > 1 || params.loadPrevNextAmount && params.loadPrevNextAmount > 1) {\n const amount = params.loadPrevNextAmount;\n const spv = slidesPerView;\n const maxIndex = Math.min(activeIndex + spv + Math.max(amount, spv), slides.length);\n const minIndex = Math.max(activeIndex - Math.max(spv, amount), 0); // Next Slides\n\n for (let i = activeIndex + slidesPerView; i < maxIndex; i += 1) {\n if (slideExist(i)) loadInSlide(i);\n } // Prev Slides\n\n\n for (let i = minIndex; i < activeIndex; i += 1) {\n if (slideExist(i)) loadInSlide(i);\n }\n } else {\n const nextSlide = $wrapperEl.children(`.${swiperParams.slideNextClass}`);\n if (nextSlide.length > 0) loadInSlide(slideIndex(nextSlide));\n const prevSlide = $wrapperEl.children(`.${swiperParams.slidePrevClass}`);\n if (prevSlide.length > 0) loadInSlide(slideIndex(prevSlide));\n }\n }\n }\n\n function checkInViewOnLoad() {\n const window = getWindow();\n if (!swiper || swiper.destroyed) return;\n const $scrollElement = swiper.params.lazy.scrollingElement ? $(swiper.params.lazy.scrollingElement) : $(window);\n const isWindow = $scrollElement[0] === window;\n const scrollElementWidth = isWindow ? window.innerWidth : $scrollElement[0].offsetWidth;\n const scrollElementHeight = isWindow ? window.innerHeight : $scrollElement[0].offsetHeight;\n const swiperOffset = swiper.$el.offset();\n const {\n rtlTranslate: rtl\n } = swiper;\n let inView = false;\n if (rtl) swiperOffset.left -= swiper.$el[0].scrollLeft;\n const swiperCoord = [[swiperOffset.left, swiperOffset.top], [swiperOffset.left + swiper.width, swiperOffset.top], [swiperOffset.left, swiperOffset.top + swiper.height], [swiperOffset.left + swiper.width, swiperOffset.top + swiper.height]];\n\n for (let i = 0; i < swiperCoord.length; i += 1) {\n const point = swiperCoord[i];\n\n if (point[0] >= 0 && point[0] <= scrollElementWidth && point[1] >= 0 && point[1] <= scrollElementHeight) {\n if (point[0] === 0 && point[1] === 0) continue; // eslint-disable-line\n\n inView = true;\n }\n }\n\n const passiveListener = swiper.touchEvents.start === 'touchstart' && swiper.support.passiveListener && swiper.params.passiveListeners ? {\n passive: true,\n capture: false\n } : false;\n\n if (inView) {\n load();\n $scrollElement.off('scroll', checkInViewOnLoad, passiveListener);\n } else if (!scrollHandlerAttached) {\n scrollHandlerAttached = true;\n $scrollElement.on('scroll', checkInViewOnLoad, passiveListener);\n }\n }\n\n on('beforeInit', () => {\n if (swiper.params.lazy.enabled && swiper.params.preloadImages) {\n swiper.params.preloadImages = false;\n }\n });\n on('init', () => {\n if (swiper.params.lazy.enabled) {\n if (swiper.params.lazy.checkInView) {\n checkInViewOnLoad();\n } else {\n load();\n }\n }\n });\n on('scroll', () => {\n if (swiper.params.freeMode && swiper.params.freeMode.enabled && !swiper.params.freeMode.sticky) {\n load();\n }\n });\n on('scrollbarDragMove resize _freeModeNoMomentumRelease', () => {\n if (swiper.params.lazy.enabled) {\n if (swiper.params.lazy.checkInView) {\n checkInViewOnLoad();\n } else {\n load();\n }\n }\n });\n on('transitionStart', () => {\n if (swiper.params.lazy.enabled) {\n if (swiper.params.lazy.loadOnTransitionStart || !swiper.params.lazy.loadOnTransitionStart && !initialImageLoaded) {\n if (swiper.params.lazy.checkInView) {\n checkInViewOnLoad();\n } else {\n load();\n }\n }\n }\n });\n on('transitionEnd', () => {\n if (swiper.params.lazy.enabled && !swiper.params.lazy.loadOnTransitionStart) {\n if (swiper.params.lazy.checkInView) {\n checkInViewOnLoad();\n } else {\n load();\n }\n }\n });\n on('slideChange', () => {\n const {\n lazy,\n cssMode,\n watchSlidesProgress,\n touchReleaseOnEdges,\n resistanceRatio\n } = swiper.params;\n\n if (lazy.enabled && (cssMode || watchSlidesProgress && (touchReleaseOnEdges || resistanceRatio === 0))) {\n load();\n }\n });\n Object.assign(swiper.lazy, {\n load,\n loadInSlide\n });\n }\n\n /* eslint no-bitwise: [\"error\", { \"allow\": [\">>\"] }] */\n function Controller(_ref) {\n let {\n swiper,\n extendParams,\n on\n } = _ref;\n extendParams({\n controller: {\n control: undefined,\n inverse: false,\n by: 'slide' // or 'container'\n\n }\n });\n swiper.controller = {\n control: undefined\n };\n\n function LinearSpline(x, y) {\n const binarySearch = function search() {\n let maxIndex;\n let minIndex;\n let guess;\n return (array, val) => {\n minIndex = -1;\n maxIndex = array.length;\n\n while (maxIndex - minIndex > 1) {\n guess = maxIndex + minIndex >> 1;\n\n if (array[guess] <= val) {\n minIndex = guess;\n } else {\n maxIndex = guess;\n }\n }\n\n return maxIndex;\n };\n }();\n\n this.x = x;\n this.y = y;\n this.lastIndex = x.length - 1; // Given an x value (x2), return the expected y2 value:\n // (x1,y1) is the known point before given value,\n // (x3,y3) is the known point after given value.\n\n let i1;\n let i3;\n\n this.interpolate = function interpolate(x2) {\n if (!x2) return 0; // Get the indexes of x1 and x3 (the array indexes before and after given x2):\n\n i3 = binarySearch(this.x, x2);\n i1 = i3 - 1; // We have our indexes i1 & i3, so we can calculate already:\n // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1\n\n return (x2 - this.x[i1]) * (this.y[i3] - this.y[i1]) / (this.x[i3] - this.x[i1]) + this.y[i1];\n };\n\n return this;\n } // xxx: for now i will just save one spline function to to\n\n\n function getInterpolateFunction(c) {\n if (!swiper.controller.spline) {\n swiper.controller.spline = swiper.params.loop ? new LinearSpline(swiper.slidesGrid, c.slidesGrid) : new LinearSpline(swiper.snapGrid, c.snapGrid);\n }\n }\n\n function setTranslate(_t, byController) {\n const controlled = swiper.controller.control;\n let multiplier;\n let controlledTranslate;\n const Swiper = swiper.constructor;\n\n function setControlledTranslate(c) {\n // this will create an Interpolate function based on the snapGrids\n // x is the Grid of the scrolled scroller and y will be the controlled scroller\n // it makes sense to create this only once and recall it for the interpolation\n // the function does a lot of value caching for performance\n const translate = swiper.rtlTranslate ? -swiper.translate : swiper.translate;\n\n if (swiper.params.controller.by === 'slide') {\n getInterpolateFunction(c); // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid\n // but it did not work out\n\n controlledTranslate = -swiper.controller.spline.interpolate(-translate);\n }\n\n if (!controlledTranslate || swiper.params.controller.by === 'container') {\n multiplier = (c.maxTranslate() - c.minTranslate()) / (swiper.maxTranslate() - swiper.minTranslate());\n controlledTranslate = (translate - swiper.minTranslate()) * multiplier + c.minTranslate();\n }\n\n if (swiper.params.controller.inverse) {\n controlledTranslate = c.maxTranslate() - controlledTranslate;\n }\n\n c.updateProgress(controlledTranslate);\n c.setTranslate(controlledTranslate, swiper);\n c.updateActiveIndex();\n c.updateSlidesClasses();\n }\n\n if (Array.isArray(controlled)) {\n for (let i = 0; i < controlled.length; i += 1) {\n if (controlled[i] !== byController && controlled[i] instanceof Swiper) {\n setControlledTranslate(controlled[i]);\n }\n }\n } else if (controlled instanceof Swiper && byController !== controlled) {\n setControlledTranslate(controlled);\n }\n }\n\n function setTransition(duration, byController) {\n const Swiper = swiper.constructor;\n const controlled = swiper.controller.control;\n let i;\n\n function setControlledTransition(c) {\n c.setTransition(duration, swiper);\n\n if (duration !== 0) {\n c.transitionStart();\n\n if (c.params.autoHeight) {\n nextTick(() => {\n c.updateAutoHeight();\n });\n }\n\n c.$wrapperEl.transitionEnd(() => {\n if (!controlled) return;\n\n if (c.params.loop && swiper.params.controller.by === 'slide') {\n c.loopFix();\n }\n\n c.transitionEnd();\n });\n }\n }\n\n if (Array.isArray(controlled)) {\n for (i = 0; i < controlled.length; i += 1) {\n if (controlled[i] !== byController && controlled[i] instanceof Swiper) {\n setControlledTransition(controlled[i]);\n }\n }\n } else if (controlled instanceof Swiper && byController !== controlled) {\n setControlledTransition(controlled);\n }\n }\n\n function removeSpline() {\n if (!swiper.controller.control) return;\n\n if (swiper.controller.spline) {\n swiper.controller.spline = undefined;\n delete swiper.controller.spline;\n }\n }\n\n on('beforeInit', () => {\n swiper.controller.control = swiper.params.controller.control;\n });\n on('update', () => {\n removeSpline();\n });\n on('resize', () => {\n removeSpline();\n });\n on('observerUpdate', () => {\n removeSpline();\n });\n on('setTranslate', (_s, translate, byController) => {\n if (!swiper.controller.control) return;\n swiper.controller.setTranslate(translate, byController);\n });\n on('setTransition', (_s, duration, byController) => {\n if (!swiper.controller.control) return;\n swiper.controller.setTransition(duration, byController);\n });\n Object.assign(swiper.controller, {\n setTranslate,\n setTransition\n });\n }\n\n function A11y(_ref) {\n let {\n swiper,\n extendParams,\n on\n } = _ref;\n extendParams({\n a11y: {\n enabled: true,\n notificationClass: 'swiper-notification',\n prevSlideMessage: 'Previous slide',\n nextSlideMessage: 'Next slide',\n firstSlideMessage: 'This is the first slide',\n lastSlideMessage: 'This is the last slide',\n paginationBulletMessage: 'Go to slide {{index}}',\n slideLabelMessage: '{{index}} / {{slidesLength}}',\n containerMessage: null,\n containerRoleDescriptionMessage: null,\n itemRoleDescriptionMessage: null,\n slideRole: 'group'\n }\n });\n let liveRegion = null;\n\n function notify(message) {\n const notification = liveRegion;\n if (notification.length === 0) return;\n notification.html('');\n notification.html(message);\n }\n\n function getRandomNumber(size) {\n if (size === void 0) {\n size = 16;\n }\n\n const randomChar = () => Math.round(16 * Math.random()).toString(16);\n\n return 'x'.repeat(size).replace(/x/g, randomChar);\n }\n\n function makeElFocusable($el) {\n $el.attr('tabIndex', '0');\n }\n\n function makeElNotFocusable($el) {\n $el.attr('tabIndex', '-1');\n }\n\n function addElRole($el, role) {\n $el.attr('role', role);\n }\n\n function addElRoleDescription($el, description) {\n $el.attr('aria-roledescription', description);\n }\n\n function addElControls($el, controls) {\n $el.attr('aria-controls', controls);\n }\n\n function addElLabel($el, label) {\n $el.attr('aria-label', label);\n }\n\n function addElId($el, id) {\n $el.attr('id', id);\n }\n\n function addElLive($el, live) {\n $el.attr('aria-live', live);\n }\n\n function disableEl($el) {\n $el.attr('aria-disabled', true);\n }\n\n function enableEl($el) {\n $el.attr('aria-disabled', false);\n }\n\n function onEnterOrSpaceKey(e) {\n if (e.keyCode !== 13 && e.keyCode !== 32) return;\n const params = swiper.params.a11y;\n const $targetEl = $(e.target);\n\n if (swiper.navigation && swiper.navigation.$nextEl && $targetEl.is(swiper.navigation.$nextEl)) {\n if (!(swiper.isEnd && !swiper.params.loop)) {\n swiper.slideNext();\n }\n\n if (swiper.isEnd) {\n notify(params.lastSlideMessage);\n } else {\n notify(params.nextSlideMessage);\n }\n }\n\n if (swiper.navigation && swiper.navigation.$prevEl && $targetEl.is(swiper.navigation.$prevEl)) {\n if (!(swiper.isBeginning && !swiper.params.loop)) {\n swiper.slidePrev();\n }\n\n if (swiper.isBeginning) {\n notify(params.firstSlideMessage);\n } else {\n notify(params.prevSlideMessage);\n }\n }\n\n if (swiper.pagination && $targetEl.is(classesToSelector(swiper.params.pagination.bulletClass))) {\n $targetEl[0].click();\n }\n }\n\n function updateNavigation() {\n if (swiper.params.loop || swiper.params.rewind || !swiper.navigation) return;\n const {\n $nextEl,\n $prevEl\n } = swiper.navigation;\n\n if ($prevEl && $prevEl.length > 0) {\n if (swiper.isBeginning) {\n disableEl($prevEl);\n makeElNotFocusable($prevEl);\n } else {\n enableEl($prevEl);\n makeElFocusable($prevEl);\n }\n }\n\n if ($nextEl && $nextEl.length > 0) {\n if (swiper.isEnd) {\n disableEl($nextEl);\n makeElNotFocusable($nextEl);\n } else {\n enableEl($nextEl);\n makeElFocusable($nextEl);\n }\n }\n }\n\n function hasPagination() {\n return swiper.pagination && swiper.pagination.bullets && swiper.pagination.bullets.length;\n }\n\n function hasClickablePagination() {\n return hasPagination() && swiper.params.pagination.clickable;\n }\n\n function updatePagination() {\n const params = swiper.params.a11y;\n if (!hasPagination()) return;\n swiper.pagination.bullets.each(bulletEl => {\n const $bulletEl = $(bulletEl);\n\n if (swiper.params.pagination.clickable) {\n makeElFocusable($bulletEl);\n\n if (!swiper.params.pagination.renderBullet) {\n addElRole($bulletEl, 'button');\n addElLabel($bulletEl, params.paginationBulletMessage.replace(/\\{\\{index\\}\\}/, $bulletEl.index() + 1));\n }\n }\n\n if ($bulletEl.is(`.${swiper.params.pagination.bulletActiveClass}`)) {\n $bulletEl.attr('aria-current', 'true');\n } else {\n $bulletEl.removeAttr('aria-current');\n }\n });\n }\n\n const initNavEl = ($el, wrapperId, message) => {\n makeElFocusable($el);\n\n if ($el[0].tagName !== 'BUTTON') {\n addElRole($el, 'button');\n $el.on('keydown', onEnterOrSpaceKey);\n }\n\n addElLabel($el, message);\n addElControls($el, wrapperId);\n };\n\n const handleFocus = e => {\n const slideEl = e.target.closest(`.${swiper.params.slideClass}`);\n if (!slideEl || !swiper.slides.includes(slideEl)) return;\n const isActive = swiper.slides.indexOf(slideEl) === swiper.activeIndex;\n const isVisible = swiper.params.watchSlidesProgress && swiper.visibleSlides && swiper.visibleSlides.includes(slideEl);\n if (isActive || isVisible) return;\n swiper.slideTo(swiper.slides.indexOf(slideEl), 0);\n };\n\n function init() {\n const params = swiper.params.a11y;\n swiper.$el.append(liveRegion); // Container\n\n const $containerEl = swiper.$el;\n\n if (params.containerRoleDescriptionMessage) {\n addElRoleDescription($containerEl, params.containerRoleDescriptionMessage);\n }\n\n if (params.containerMessage) {\n addElLabel($containerEl, params.containerMessage);\n } // Wrapper\n\n\n const $wrapperEl = swiper.$wrapperEl;\n const wrapperId = $wrapperEl.attr('id') || `swiper-wrapper-${getRandomNumber(16)}`;\n const live = swiper.params.autoplay && swiper.params.autoplay.enabled ? 'off' : 'polite';\n addElId($wrapperEl, wrapperId);\n addElLive($wrapperEl, live); // Slide\n\n if (params.itemRoleDescriptionMessage) {\n addElRoleDescription($(swiper.slides), params.itemRoleDescriptionMessage);\n }\n\n addElRole($(swiper.slides), params.slideRole);\n const slidesLength = swiper.params.loop ? swiper.slides.filter(el => !el.classList.contains(swiper.params.slideDuplicateClass)).length : swiper.slides.length;\n swiper.slides.each((slideEl, index) => {\n const $slideEl = $(slideEl);\n const slideIndex = swiper.params.loop ? parseInt($slideEl.attr('data-swiper-slide-index'), 10) : index;\n const ariaLabelMessage = params.slideLabelMessage.replace(/\\{\\{index\\}\\}/, slideIndex + 1).replace(/\\{\\{slidesLength\\}\\}/, slidesLength);\n addElLabel($slideEl, ariaLabelMessage);\n }); // Navigation\n\n let $nextEl;\n let $prevEl;\n\n if (swiper.navigation && swiper.navigation.$nextEl) {\n $nextEl = swiper.navigation.$nextEl;\n }\n\n if (swiper.navigation && swiper.navigation.$prevEl) {\n $prevEl = swiper.navigation.$prevEl;\n }\n\n if ($nextEl && $nextEl.length) {\n initNavEl($nextEl, wrapperId, params.nextSlideMessage);\n }\n\n if ($prevEl && $prevEl.length) {\n initNavEl($prevEl, wrapperId, params.prevSlideMessage);\n } // Pagination\n\n\n if (hasClickablePagination()) {\n swiper.pagination.$el.on('keydown', classesToSelector(swiper.params.pagination.bulletClass), onEnterOrSpaceKey);\n } // Tab focus\n\n\n swiper.$el.on('focus', handleFocus, true);\n }\n\n function destroy() {\n if (liveRegion && liveRegion.length > 0) liveRegion.remove();\n let $nextEl;\n let $prevEl;\n\n if (swiper.navigation && swiper.navigation.$nextEl) {\n $nextEl = swiper.navigation.$nextEl;\n }\n\n if (swiper.navigation && swiper.navigation.$prevEl) {\n $prevEl = swiper.navigation.$prevEl;\n }\n\n if ($nextEl) {\n $nextEl.off('keydown', onEnterOrSpaceKey);\n }\n\n if ($prevEl) {\n $prevEl.off('keydown', onEnterOrSpaceKey);\n } // Pagination\n\n\n if (hasClickablePagination()) {\n swiper.pagination.$el.off('keydown', classesToSelector(swiper.params.pagination.bulletClass), onEnterOrSpaceKey);\n } // Tab focus\n\n\n swiper.$el.off('focus', handleFocus, true);\n }\n\n on('beforeInit', () => {\n liveRegion = $(``);\n });\n on('afterInit', () => {\n if (!swiper.params.a11y.enabled) return;\n init();\n });\n on('fromEdge toEdge afterInit lock unlock', () => {\n if (!swiper.params.a11y.enabled) return;\n updateNavigation();\n });\n on('paginationUpdate', () => {\n if (!swiper.params.a11y.enabled) return;\n updatePagination();\n });\n on('destroy', () => {\n if (!swiper.params.a11y.enabled) return;\n destroy();\n });\n }\n\n function History(_ref) {\n let {\n swiper,\n extendParams,\n on\n } = _ref;\n extendParams({\n history: {\n enabled: false,\n root: '',\n replaceState: false,\n key: 'slides'\n }\n });\n let initialized = false;\n let paths = {};\n\n const slugify = text => {\n return text.toString().replace(/\\s+/g, '-').replace(/[^\\w-]+/g, '').replace(/--+/g, '-').replace(/^-+/, '').replace(/-+$/, '');\n };\n\n const getPathValues = urlOverride => {\n const window = getWindow();\n let location;\n\n if (urlOverride) {\n location = new URL(urlOverride);\n } else {\n location = window.location;\n }\n\n const pathArray = location.pathname.slice(1).split('/').filter(part => part !== '');\n const total = pathArray.length;\n const key = pathArray[total - 2];\n const value = pathArray[total - 1];\n return {\n key,\n value\n };\n };\n\n const setHistory = (key, index) => {\n const window = getWindow();\n if (!initialized || !swiper.params.history.enabled) return;\n let location;\n\n if (swiper.params.url) {\n location = new URL(swiper.params.url);\n } else {\n location = window.location;\n }\n\n const slide = swiper.slides.eq(index);\n let value = slugify(slide.attr('data-history'));\n\n if (swiper.params.history.root.length > 0) {\n let root = swiper.params.history.root;\n if (root[root.length - 1] === '/') root = root.slice(0, root.length - 1);\n value = `${root}/${key}/${value}`;\n } else if (!location.pathname.includes(key)) {\n value = `${key}/${value}`;\n }\n\n const currentState = window.history.state;\n\n if (currentState && currentState.value === value) {\n return;\n }\n\n if (swiper.params.history.replaceState) {\n window.history.replaceState({\n value\n }, null, value);\n } else {\n window.history.pushState({\n value\n }, null, value);\n }\n };\n\n const scrollToSlide = (speed, value, runCallbacks) => {\n if (value) {\n for (let i = 0, length = swiper.slides.length; i < length; i += 1) {\n const slide = swiper.slides.eq(i);\n const slideHistory = slugify(slide.attr('data-history'));\n\n if (slideHistory === value && !slide.hasClass(swiper.params.slideDuplicateClass)) {\n const index = slide.index();\n swiper.slideTo(index, speed, runCallbacks);\n }\n }\n } else {\n swiper.slideTo(0, speed, runCallbacks);\n }\n };\n\n const setHistoryPopState = () => {\n paths = getPathValues(swiper.params.url);\n scrollToSlide(swiper.params.speed, swiper.paths.value, false);\n };\n\n const init = () => {\n const window = getWindow();\n if (!swiper.params.history) return;\n\n if (!window.history || !window.history.pushState) {\n swiper.params.history.enabled = false;\n swiper.params.hashNavigation.enabled = true;\n return;\n }\n\n initialized = true;\n paths = getPathValues(swiper.params.url);\n if (!paths.key && !paths.value) return;\n scrollToSlide(0, paths.value, swiper.params.runCallbacksOnInit);\n\n if (!swiper.params.history.replaceState) {\n window.addEventListener('popstate', setHistoryPopState);\n }\n };\n\n const destroy = () => {\n const window = getWindow();\n\n if (!swiper.params.history.replaceState) {\n window.removeEventListener('popstate', setHistoryPopState);\n }\n };\n\n on('init', () => {\n if (swiper.params.history.enabled) {\n init();\n }\n });\n on('destroy', () => {\n if (swiper.params.history.enabled) {\n destroy();\n }\n });\n on('transitionEnd _freeModeNoMomentumRelease', () => {\n if (initialized) {\n setHistory(swiper.params.history.key, swiper.activeIndex);\n }\n });\n on('slideChange', () => {\n if (initialized && swiper.params.cssMode) {\n setHistory(swiper.params.history.key, swiper.activeIndex);\n }\n });\n }\n\n function HashNavigation(_ref) {\n let {\n swiper,\n extendParams,\n emit,\n on\n } = _ref;\n let initialized = false;\n const document = getDocument();\n const window = getWindow();\n extendParams({\n hashNavigation: {\n enabled: false,\n replaceState: false,\n watchState: false\n }\n });\n\n const onHashChange = () => {\n emit('hashChange');\n const newHash = document.location.hash.replace('#', '');\n const activeSlideHash = swiper.slides.eq(swiper.activeIndex).attr('data-hash');\n\n if (newHash !== activeSlideHash) {\n const newIndex = swiper.$wrapperEl.children(`.${swiper.params.slideClass}[data-hash=\"${newHash}\"]`).index();\n if (typeof newIndex === 'undefined') return;\n swiper.slideTo(newIndex);\n }\n };\n\n const setHash = () => {\n if (!initialized || !swiper.params.hashNavigation.enabled) return;\n\n if (swiper.params.hashNavigation.replaceState && window.history && window.history.replaceState) {\n window.history.replaceState(null, null, `#${swiper.slides.eq(swiper.activeIndex).attr('data-hash')}` || '');\n emit('hashSet');\n } else {\n const slide = swiper.slides.eq(swiper.activeIndex);\n const hash = slide.attr('data-hash') || slide.attr('data-history');\n document.location.hash = hash || '';\n emit('hashSet');\n }\n };\n\n const init = () => {\n if (!swiper.params.hashNavigation.enabled || swiper.params.history && swiper.params.history.enabled) return;\n initialized = true;\n const hash = document.location.hash.replace('#', '');\n\n if (hash) {\n const speed = 0;\n\n for (let i = 0, length = swiper.slides.length; i < length; i += 1) {\n const slide = swiper.slides.eq(i);\n const slideHash = slide.attr('data-hash') || slide.attr('data-history');\n\n if (slideHash === hash && !slide.hasClass(swiper.params.slideDuplicateClass)) {\n const index = slide.index();\n swiper.slideTo(index, speed, swiper.params.runCallbacksOnInit, true);\n }\n }\n }\n\n if (swiper.params.hashNavigation.watchState) {\n $(window).on('hashchange', onHashChange);\n }\n };\n\n const destroy = () => {\n if (swiper.params.hashNavigation.watchState) {\n $(window).off('hashchange', onHashChange);\n }\n };\n\n on('init', () => {\n if (swiper.params.hashNavigation.enabled) {\n init();\n }\n });\n on('destroy', () => {\n if (swiper.params.hashNavigation.enabled) {\n destroy();\n }\n });\n on('transitionEnd _freeModeNoMomentumRelease', () => {\n if (initialized) {\n setHash();\n }\n });\n on('slideChange', () => {\n if (initialized && swiper.params.cssMode) {\n setHash();\n }\n });\n }\n\n /* eslint no-underscore-dangle: \"off\" */\n function Autoplay(_ref) {\n let {\n swiper,\n extendParams,\n on,\n emit\n } = _ref;\n let timeout;\n swiper.autoplay = {\n running: false,\n paused: false\n };\n extendParams({\n autoplay: {\n enabled: false,\n delay: 3000,\n waitForTransition: true,\n disableOnInteraction: true,\n stopOnLastSlide: false,\n reverseDirection: false,\n pauseOnMouseEnter: false\n }\n });\n\n function run() {\n const $activeSlideEl = swiper.slides.eq(swiper.activeIndex);\n let delay = swiper.params.autoplay.delay;\n\n if ($activeSlideEl.attr('data-swiper-autoplay')) {\n delay = $activeSlideEl.attr('data-swiper-autoplay') || swiper.params.autoplay.delay;\n }\n\n clearTimeout(timeout);\n timeout = nextTick(() => {\n let autoplayResult;\n\n if (swiper.params.autoplay.reverseDirection) {\n if (swiper.params.loop) {\n swiper.loopFix();\n autoplayResult = swiper.slidePrev(swiper.params.speed, true, true);\n emit('autoplay');\n } else if (!swiper.isBeginning) {\n autoplayResult = swiper.slidePrev(swiper.params.speed, true, true);\n emit('autoplay');\n } else if (!swiper.params.autoplay.stopOnLastSlide) {\n autoplayResult = swiper.slideTo(swiper.slides.length - 1, swiper.params.speed, true, true);\n emit('autoplay');\n } else {\n stop();\n }\n } else if (swiper.params.loop) {\n swiper.loopFix();\n autoplayResult = swiper.slideNext(swiper.params.speed, true, true);\n emit('autoplay');\n } else if (!swiper.isEnd) {\n autoplayResult = swiper.slideNext(swiper.params.speed, true, true);\n emit('autoplay');\n } else if (!swiper.params.autoplay.stopOnLastSlide) {\n autoplayResult = swiper.slideTo(0, swiper.params.speed, true, true);\n emit('autoplay');\n } else {\n stop();\n }\n\n if (swiper.params.cssMode && swiper.autoplay.running) run();else if (autoplayResult === false) {\n run();\n }\n }, delay);\n }\n\n function start() {\n if (typeof timeout !== 'undefined') return false;\n if (swiper.autoplay.running) return false;\n swiper.autoplay.running = true;\n emit('autoplayStart');\n run();\n return true;\n }\n\n function stop() {\n if (!swiper.autoplay.running) return false;\n if (typeof timeout === 'undefined') return false;\n\n if (timeout) {\n clearTimeout(timeout);\n timeout = undefined;\n }\n\n swiper.autoplay.running = false;\n emit('autoplayStop');\n return true;\n }\n\n function pause(speed) {\n if (!swiper.autoplay.running) return;\n if (swiper.autoplay.paused) return;\n if (timeout) clearTimeout(timeout);\n swiper.autoplay.paused = true;\n\n if (speed === 0 || !swiper.params.autoplay.waitForTransition) {\n swiper.autoplay.paused = false;\n run();\n } else {\n ['transitionend', 'webkitTransitionEnd'].forEach(event => {\n swiper.$wrapperEl[0].addEventListener(event, onTransitionEnd);\n });\n }\n }\n\n function onVisibilityChange() {\n const document = getDocument();\n\n if (document.visibilityState === 'hidden' && swiper.autoplay.running) {\n pause();\n }\n\n if (document.visibilityState === 'visible' && swiper.autoplay.paused) {\n run();\n swiper.autoplay.paused = false;\n }\n }\n\n function onTransitionEnd(e) {\n if (!swiper || swiper.destroyed || !swiper.$wrapperEl) return;\n if (e.target !== swiper.$wrapperEl[0]) return;\n ['transitionend', 'webkitTransitionEnd'].forEach(event => {\n swiper.$wrapperEl[0].removeEventListener(event, onTransitionEnd);\n });\n swiper.autoplay.paused = false;\n\n if (!swiper.autoplay.running) {\n stop();\n } else {\n run();\n }\n }\n\n function onMouseEnter() {\n if (swiper.params.autoplay.disableOnInteraction) {\n stop();\n } else {\n emit('autoplayPause');\n pause();\n }\n\n ['transitionend', 'webkitTransitionEnd'].forEach(event => {\n swiper.$wrapperEl[0].removeEventListener(event, onTransitionEnd);\n });\n }\n\n function onMouseLeave() {\n if (swiper.params.autoplay.disableOnInteraction) {\n return;\n }\n\n swiper.autoplay.paused = false;\n emit('autoplayResume');\n run();\n }\n\n function attachMouseEvents() {\n if (swiper.params.autoplay.pauseOnMouseEnter) {\n swiper.$el.on('mouseenter', onMouseEnter);\n swiper.$el.on('mouseleave', onMouseLeave);\n }\n }\n\n function detachMouseEvents() {\n swiper.$el.off('mouseenter', onMouseEnter);\n swiper.$el.off('mouseleave', onMouseLeave);\n }\n\n on('init', () => {\n if (swiper.params.autoplay.enabled) {\n start();\n const document = getDocument();\n document.addEventListener('visibilitychange', onVisibilityChange);\n attachMouseEvents();\n }\n });\n on('beforeTransitionStart', (_s, speed, internal) => {\n if (swiper.autoplay.running) {\n if (internal || !swiper.params.autoplay.disableOnInteraction) {\n swiper.autoplay.pause(speed);\n } else {\n stop();\n }\n }\n });\n on('sliderFirstMove', () => {\n if (swiper.autoplay.running) {\n if (swiper.params.autoplay.disableOnInteraction) {\n stop();\n } else {\n pause();\n }\n }\n });\n on('touchEnd', () => {\n if (swiper.params.cssMode && swiper.autoplay.paused && !swiper.params.autoplay.disableOnInteraction) {\n run();\n }\n });\n on('destroy', () => {\n detachMouseEvents();\n\n if (swiper.autoplay.running) {\n stop();\n }\n\n const document = getDocument();\n document.removeEventListener('visibilitychange', onVisibilityChange);\n });\n Object.assign(swiper.autoplay, {\n pause,\n run,\n start,\n stop\n });\n }\n\n function Thumb(_ref) {\n let {\n swiper,\n extendParams,\n on\n } = _ref;\n extendParams({\n thumbs: {\n swiper: null,\n multipleActiveThumbs: true,\n autoScrollOffset: 0,\n slideThumbActiveClass: 'swiper-slide-thumb-active',\n thumbsContainerClass: 'swiper-thumbs'\n }\n });\n let initialized = false;\n let swiperCreated = false;\n swiper.thumbs = {\n swiper: null\n };\n\n function onThumbClick() {\n const thumbsSwiper = swiper.thumbs.swiper;\n if (!thumbsSwiper) return;\n const clickedIndex = thumbsSwiper.clickedIndex;\n const clickedSlide = thumbsSwiper.clickedSlide;\n if (clickedSlide && $(clickedSlide).hasClass(swiper.params.thumbs.slideThumbActiveClass)) return;\n if (typeof clickedIndex === 'undefined' || clickedIndex === null) return;\n let slideToIndex;\n\n if (thumbsSwiper.params.loop) {\n slideToIndex = parseInt($(thumbsSwiper.clickedSlide).attr('data-swiper-slide-index'), 10);\n } else {\n slideToIndex = clickedIndex;\n }\n\n if (swiper.params.loop) {\n let currentIndex = swiper.activeIndex;\n\n if (swiper.slides.eq(currentIndex).hasClass(swiper.params.slideDuplicateClass)) {\n swiper.loopFix(); // eslint-disable-next-line\n\n swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;\n currentIndex = swiper.activeIndex;\n }\n\n const prevIndex = swiper.slides.eq(currentIndex).prevAll(`[data-swiper-slide-index=\"${slideToIndex}\"]`).eq(0).index();\n const nextIndex = swiper.slides.eq(currentIndex).nextAll(`[data-swiper-slide-index=\"${slideToIndex}\"]`).eq(0).index();\n if (typeof prevIndex === 'undefined') slideToIndex = nextIndex;else if (typeof nextIndex === 'undefined') slideToIndex = prevIndex;else if (nextIndex - currentIndex < currentIndex - prevIndex) slideToIndex = nextIndex;else slideToIndex = prevIndex;\n }\n\n swiper.slideTo(slideToIndex);\n }\n\n function init() {\n const {\n thumbs: thumbsParams\n } = swiper.params;\n if (initialized) return false;\n initialized = true;\n const SwiperClass = swiper.constructor;\n\n if (thumbsParams.swiper instanceof SwiperClass) {\n swiper.thumbs.swiper = thumbsParams.swiper;\n Object.assign(swiper.thumbs.swiper.originalParams, {\n watchSlidesProgress: true,\n slideToClickedSlide: false\n });\n Object.assign(swiper.thumbs.swiper.params, {\n watchSlidesProgress: true,\n slideToClickedSlide: false\n });\n } else if (isObject(thumbsParams.swiper)) {\n const thumbsSwiperParams = Object.assign({}, thumbsParams.swiper);\n Object.assign(thumbsSwiperParams, {\n watchSlidesProgress: true,\n slideToClickedSlide: false\n });\n swiper.thumbs.swiper = new SwiperClass(thumbsSwiperParams);\n swiperCreated = true;\n }\n\n swiper.thumbs.swiper.$el.addClass(swiper.params.thumbs.thumbsContainerClass);\n swiper.thumbs.swiper.on('tap', onThumbClick);\n return true;\n }\n\n function update(initial) {\n const thumbsSwiper = swiper.thumbs.swiper;\n if (!thumbsSwiper) return;\n const slidesPerView = thumbsSwiper.params.slidesPerView === 'auto' ? thumbsSwiper.slidesPerViewDynamic() : thumbsSwiper.params.slidesPerView;\n const autoScrollOffset = swiper.params.thumbs.autoScrollOffset;\n const useOffset = autoScrollOffset && !thumbsSwiper.params.loop;\n\n if (swiper.realIndex !== thumbsSwiper.realIndex || useOffset) {\n let currentThumbsIndex = thumbsSwiper.activeIndex;\n let newThumbsIndex;\n let direction;\n\n if (thumbsSwiper.params.loop) {\n if (thumbsSwiper.slides.eq(currentThumbsIndex).hasClass(thumbsSwiper.params.slideDuplicateClass)) {\n thumbsSwiper.loopFix(); // eslint-disable-next-line\n\n thumbsSwiper._clientLeft = thumbsSwiper.$wrapperEl[0].clientLeft;\n currentThumbsIndex = thumbsSwiper.activeIndex;\n } // Find actual thumbs index to slide to\n\n\n const prevThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).prevAll(`[data-swiper-slide-index=\"${swiper.realIndex}\"]`).eq(0).index();\n const nextThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).nextAll(`[data-swiper-slide-index=\"${swiper.realIndex}\"]`).eq(0).index();\n\n if (typeof prevThumbsIndex === 'undefined') {\n newThumbsIndex = nextThumbsIndex;\n } else if (typeof nextThumbsIndex === 'undefined') {\n newThumbsIndex = prevThumbsIndex;\n } else if (nextThumbsIndex - currentThumbsIndex === currentThumbsIndex - prevThumbsIndex) {\n newThumbsIndex = thumbsSwiper.params.slidesPerGroup > 1 ? nextThumbsIndex : currentThumbsIndex;\n } else if (nextThumbsIndex - currentThumbsIndex < currentThumbsIndex - prevThumbsIndex) {\n newThumbsIndex = nextThumbsIndex;\n } else {\n newThumbsIndex = prevThumbsIndex;\n }\n\n direction = swiper.activeIndex > swiper.previousIndex ? 'next' : 'prev';\n } else {\n newThumbsIndex = swiper.realIndex;\n direction = newThumbsIndex > swiper.previousIndex ? 'next' : 'prev';\n }\n\n if (useOffset) {\n newThumbsIndex += direction === 'next' ? autoScrollOffset : -1 * autoScrollOffset;\n }\n\n if (thumbsSwiper.visibleSlidesIndexes && thumbsSwiper.visibleSlidesIndexes.indexOf(newThumbsIndex) < 0) {\n if (thumbsSwiper.params.centeredSlides) {\n if (newThumbsIndex > currentThumbsIndex) {\n newThumbsIndex = newThumbsIndex - Math.floor(slidesPerView / 2) + 1;\n } else {\n newThumbsIndex = newThumbsIndex + Math.floor(slidesPerView / 2) - 1;\n }\n } else if (newThumbsIndex > currentThumbsIndex && thumbsSwiper.params.slidesPerGroup === 1) ;\n\n thumbsSwiper.slideTo(newThumbsIndex, initial ? 0 : undefined);\n }\n } // Activate thumbs\n\n\n let thumbsToActivate = 1;\n const thumbActiveClass = swiper.params.thumbs.slideThumbActiveClass;\n\n if (swiper.params.slidesPerView > 1 && !swiper.params.centeredSlides) {\n thumbsToActivate = swiper.params.slidesPerView;\n }\n\n if (!swiper.params.thumbs.multipleActiveThumbs) {\n thumbsToActivate = 1;\n }\n\n thumbsToActivate = Math.floor(thumbsToActivate);\n thumbsSwiper.slides.removeClass(thumbActiveClass);\n\n if (thumbsSwiper.params.loop || thumbsSwiper.params.virtual && thumbsSwiper.params.virtual.enabled) {\n for (let i = 0; i < thumbsToActivate; i += 1) {\n thumbsSwiper.$wrapperEl.children(`[data-swiper-slide-index=\"${swiper.realIndex + i}\"]`).addClass(thumbActiveClass);\n }\n } else {\n for (let i = 0; i < thumbsToActivate; i += 1) {\n thumbsSwiper.slides.eq(swiper.realIndex + i).addClass(thumbActiveClass);\n }\n }\n }\n\n on('beforeInit', () => {\n const {\n thumbs\n } = swiper.params;\n if (!thumbs || !thumbs.swiper) return;\n init();\n update(true);\n });\n on('slideChange update resize observerUpdate', () => {\n if (!swiper.thumbs.swiper) return;\n update();\n });\n on('setTransition', (_s, duration) => {\n const thumbsSwiper = swiper.thumbs.swiper;\n if (!thumbsSwiper) return;\n thumbsSwiper.setTransition(duration);\n });\n on('beforeDestroy', () => {\n const thumbsSwiper = swiper.thumbs.swiper;\n if (!thumbsSwiper) return;\n\n if (swiperCreated && thumbsSwiper) {\n thumbsSwiper.destroy();\n }\n });\n Object.assign(swiper.thumbs, {\n init,\n update\n });\n }\n\n function freeMode(_ref) {\n let {\n swiper,\n extendParams,\n emit,\n once\n } = _ref;\n extendParams({\n freeMode: {\n enabled: false,\n momentum: true,\n momentumRatio: 1,\n momentumBounce: true,\n momentumBounceRatio: 1,\n momentumVelocityRatio: 1,\n sticky: false,\n minimumVelocity: 0.02\n }\n });\n\n function onTouchStart() {\n const translate = swiper.getTranslate();\n swiper.setTranslate(translate);\n swiper.setTransition(0);\n swiper.touchEventsData.velocities.length = 0;\n swiper.freeMode.onTouchEnd({\n currentPos: swiper.rtl ? swiper.translate : -swiper.translate\n });\n }\n\n function onTouchMove() {\n const {\n touchEventsData: data,\n touches\n } = swiper; // Velocity\n\n if (data.velocities.length === 0) {\n data.velocities.push({\n position: touches[swiper.isHorizontal() ? 'startX' : 'startY'],\n time: data.touchStartTime\n });\n }\n\n data.velocities.push({\n position: touches[swiper.isHorizontal() ? 'currentX' : 'currentY'],\n time: now()\n });\n }\n\n function onTouchEnd(_ref2) {\n let {\n currentPos\n } = _ref2;\n const {\n params,\n $wrapperEl,\n rtlTranslate: rtl,\n snapGrid,\n touchEventsData: data\n } = swiper; // Time diff\n\n const touchEndTime = now();\n const timeDiff = touchEndTime - data.touchStartTime;\n\n if (currentPos < -swiper.minTranslate()) {\n swiper.slideTo(swiper.activeIndex);\n return;\n }\n\n if (currentPos > -swiper.maxTranslate()) {\n if (swiper.slides.length < snapGrid.length) {\n swiper.slideTo(snapGrid.length - 1);\n } else {\n swiper.slideTo(swiper.slides.length - 1);\n }\n\n return;\n }\n\n if (params.freeMode.momentum) {\n if (data.velocities.length > 1) {\n const lastMoveEvent = data.velocities.pop();\n const velocityEvent = data.velocities.pop();\n const distance = lastMoveEvent.position - velocityEvent.position;\n const time = lastMoveEvent.time - velocityEvent.time;\n swiper.velocity = distance / time;\n swiper.velocity /= 2;\n\n if (Math.abs(swiper.velocity) < params.freeMode.minimumVelocity) {\n swiper.velocity = 0;\n } // this implies that the user stopped moving a finger then released.\n // There would be no events with distance zero, so the last event is stale.\n\n\n if (time > 150 || now() - lastMoveEvent.time > 300) {\n swiper.velocity = 0;\n }\n } else {\n swiper.velocity = 0;\n }\n\n swiper.velocity *= params.freeMode.momentumVelocityRatio;\n data.velocities.length = 0;\n let momentumDuration = 1000 * params.freeMode.momentumRatio;\n const momentumDistance = swiper.velocity * momentumDuration;\n let newPosition = swiper.translate + momentumDistance;\n if (rtl) newPosition = -newPosition;\n let doBounce = false;\n let afterBouncePosition;\n const bounceAmount = Math.abs(swiper.velocity) * 20 * params.freeMode.momentumBounceRatio;\n let needsLoopFix;\n\n if (newPosition < swiper.maxTranslate()) {\n if (params.freeMode.momentumBounce) {\n if (newPosition + swiper.maxTranslate() < -bounceAmount) {\n newPosition = swiper.maxTranslate() - bounceAmount;\n }\n\n afterBouncePosition = swiper.maxTranslate();\n doBounce = true;\n data.allowMomentumBounce = true;\n } else {\n newPosition = swiper.maxTranslate();\n }\n\n if (params.loop && params.centeredSlides) needsLoopFix = true;\n } else if (newPosition > swiper.minTranslate()) {\n if (params.freeMode.momentumBounce) {\n if (newPosition - swiper.minTranslate() > bounceAmount) {\n newPosition = swiper.minTranslate() + bounceAmount;\n }\n\n afterBouncePosition = swiper.minTranslate();\n doBounce = true;\n data.allowMomentumBounce = true;\n } else {\n newPosition = swiper.minTranslate();\n }\n\n if (params.loop && params.centeredSlides) needsLoopFix = true;\n } else if (params.freeMode.sticky) {\n let nextSlide;\n\n for (let j = 0; j < snapGrid.length; j += 1) {\n if (snapGrid[j] > -newPosition) {\n nextSlide = j;\n break;\n }\n }\n\n if (Math.abs(snapGrid[nextSlide] - newPosition) < Math.abs(snapGrid[nextSlide - 1] - newPosition) || swiper.swipeDirection === 'next') {\n newPosition = snapGrid[nextSlide];\n } else {\n newPosition = snapGrid[nextSlide - 1];\n }\n\n newPosition = -newPosition;\n }\n\n if (needsLoopFix) {\n once('transitionEnd', () => {\n swiper.loopFix();\n });\n } // Fix duration\n\n\n if (swiper.velocity !== 0) {\n if (rtl) {\n momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity);\n } else {\n momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity);\n }\n\n if (params.freeMode.sticky) {\n // If freeMode.sticky is active and the user ends a swipe with a slow-velocity\n // event, then durations can be 20+ seconds to slide one (or zero!) slides.\n // It's easy to see this when simulating touch with mouse events. To fix this,\n // limit single-slide swipes to the default slide duration. This also has the\n // nice side effect of matching slide speed if the user stopped moving before\n // lifting finger or mouse vs. moving slowly before lifting the finger/mouse.\n // For faster swipes, also apply limits (albeit higher ones).\n const moveDistance = Math.abs((rtl ? -newPosition : newPosition) - swiper.translate);\n const currentSlideSize = swiper.slidesSizesGrid[swiper.activeIndex];\n\n if (moveDistance < currentSlideSize) {\n momentumDuration = params.speed;\n } else if (moveDistance < 2 * currentSlideSize) {\n momentumDuration = params.speed * 1.5;\n } else {\n momentumDuration = params.speed * 2.5;\n }\n }\n } else if (params.freeMode.sticky) {\n swiper.slideToClosest();\n return;\n }\n\n if (params.freeMode.momentumBounce && doBounce) {\n swiper.updateProgress(afterBouncePosition);\n swiper.setTransition(momentumDuration);\n swiper.setTranslate(newPosition);\n swiper.transitionStart(true, swiper.swipeDirection);\n swiper.animating = true;\n $wrapperEl.transitionEnd(() => {\n if (!swiper || swiper.destroyed || !data.allowMomentumBounce) return;\n emit('momentumBounce');\n swiper.setTransition(params.speed);\n setTimeout(() => {\n swiper.setTranslate(afterBouncePosition);\n $wrapperEl.transitionEnd(() => {\n if (!swiper || swiper.destroyed) return;\n swiper.transitionEnd();\n });\n }, 0);\n });\n } else if (swiper.velocity) {\n emit('_freeModeNoMomentumRelease');\n swiper.updateProgress(newPosition);\n swiper.setTransition(momentumDuration);\n swiper.setTranslate(newPosition);\n swiper.transitionStart(true, swiper.swipeDirection);\n\n if (!swiper.animating) {\n swiper.animating = true;\n $wrapperEl.transitionEnd(() => {\n if (!swiper || swiper.destroyed) return;\n swiper.transitionEnd();\n });\n }\n } else {\n swiper.updateProgress(newPosition);\n }\n\n swiper.updateActiveIndex();\n swiper.updateSlidesClasses();\n } else if (params.freeMode.sticky) {\n swiper.slideToClosest();\n return;\n } else if (params.freeMode) {\n emit('_freeModeNoMomentumRelease');\n }\n\n if (!params.freeMode.momentum || timeDiff >= params.longSwipesMs) {\n swiper.updateProgress();\n swiper.updateActiveIndex();\n swiper.updateSlidesClasses();\n }\n }\n\n Object.assign(swiper, {\n freeMode: {\n onTouchStart,\n onTouchMove,\n onTouchEnd\n }\n });\n }\n\n function Grid(_ref) {\n let {\n swiper,\n extendParams\n } = _ref;\n extendParams({\n grid: {\n rows: 1,\n fill: 'column'\n }\n });\n let slidesNumberEvenToRows;\n let slidesPerRow;\n let numFullColumns;\n\n const initSlides = slidesLength => {\n const {\n slidesPerView\n } = swiper.params;\n const {\n rows,\n fill\n } = swiper.params.grid;\n slidesPerRow = slidesNumberEvenToRows / rows;\n numFullColumns = Math.floor(slidesLength / rows);\n\n if (Math.floor(slidesLength / rows) === slidesLength / rows) {\n slidesNumberEvenToRows = slidesLength;\n } else {\n slidesNumberEvenToRows = Math.ceil(slidesLength / rows) * rows;\n }\n\n if (slidesPerView !== 'auto' && fill === 'row') {\n slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, slidesPerView * rows);\n }\n };\n\n const updateSlide = (i, slide, slidesLength, getDirectionLabel) => {\n const {\n slidesPerGroup,\n spaceBetween\n } = swiper.params;\n const {\n rows,\n fill\n } = swiper.params.grid; // Set slides order\n\n let newSlideOrderIndex;\n let column;\n let row;\n\n if (fill === 'row' && slidesPerGroup > 1) {\n const groupIndex = Math.floor(i / (slidesPerGroup * rows));\n const slideIndexInGroup = i - rows * slidesPerGroup * groupIndex;\n const columnsInGroup = groupIndex === 0 ? slidesPerGroup : Math.min(Math.ceil((slidesLength - groupIndex * rows * slidesPerGroup) / rows), slidesPerGroup);\n row = Math.floor(slideIndexInGroup / columnsInGroup);\n column = slideIndexInGroup - row * columnsInGroup + groupIndex * slidesPerGroup;\n newSlideOrderIndex = column + row * slidesNumberEvenToRows / rows;\n slide.css({\n '-webkit-order': newSlideOrderIndex,\n order: newSlideOrderIndex\n });\n } else if (fill === 'column') {\n column = Math.floor(i / rows);\n row = i - column * rows;\n\n if (column > numFullColumns || column === numFullColumns && row === rows - 1) {\n row += 1;\n\n if (row >= rows) {\n row = 0;\n column += 1;\n }\n }\n } else {\n row = Math.floor(i / slidesPerRow);\n column = i - row * slidesPerRow;\n }\n\n slide.css(getDirectionLabel('margin-top'), row !== 0 ? spaceBetween && `${spaceBetween}px` : '');\n };\n\n const updateWrapperSize = (slideSize, snapGrid, getDirectionLabel) => {\n const {\n spaceBetween,\n centeredSlides,\n roundLengths\n } = swiper.params;\n const {\n rows\n } = swiper.params.grid;\n swiper.virtualSize = (slideSize + spaceBetween) * slidesNumberEvenToRows;\n swiper.virtualSize = Math.ceil(swiper.virtualSize / rows) - spaceBetween;\n swiper.$wrapperEl.css({\n [getDirectionLabel('width')]: `${swiper.virtualSize + spaceBetween}px`\n });\n\n if (centeredSlides) {\n snapGrid.splice(0, snapGrid.length);\n const newSlidesGrid = [];\n\n for (let i = 0; i < snapGrid.length; i += 1) {\n let slidesGridItem = snapGrid[i];\n if (roundLengths) slidesGridItem = Math.floor(slidesGridItem);\n if (snapGrid[i] < swiper.virtualSize + snapGrid[0]) newSlidesGrid.push(slidesGridItem);\n }\n\n snapGrid.push(...newSlidesGrid);\n }\n };\n\n swiper.grid = {\n initSlides,\n updateSlide,\n updateWrapperSize\n };\n }\n\n function appendSlide(slides) {\n const swiper = this;\n const {\n $wrapperEl,\n params\n } = swiper;\n\n if (params.loop) {\n swiper.loopDestroy();\n }\n\n if (typeof slides === 'object' && 'length' in slides) {\n for (let i = 0; i < slides.length; i += 1) {\n if (slides[i]) $wrapperEl.append(slides[i]);\n }\n } else {\n $wrapperEl.append(slides);\n }\n\n if (params.loop) {\n swiper.loopCreate();\n }\n\n if (!params.observer) {\n swiper.update();\n }\n }\n\n function prependSlide(slides) {\n const swiper = this;\n const {\n params,\n $wrapperEl,\n activeIndex\n } = swiper;\n\n if (params.loop) {\n swiper.loopDestroy();\n }\n\n let newActiveIndex = activeIndex + 1;\n\n if (typeof slides === 'object' && 'length' in slides) {\n for (let i = 0; i < slides.length; i += 1) {\n if (slides[i]) $wrapperEl.prepend(slides[i]);\n }\n\n newActiveIndex = activeIndex + slides.length;\n } else {\n $wrapperEl.prepend(slides);\n }\n\n if (params.loop) {\n swiper.loopCreate();\n }\n\n if (!params.observer) {\n swiper.update();\n }\n\n swiper.slideTo(newActiveIndex, 0, false);\n }\n\n function addSlide(index, slides) {\n const swiper = this;\n const {\n $wrapperEl,\n params,\n activeIndex\n } = swiper;\n let activeIndexBuffer = activeIndex;\n\n if (params.loop) {\n activeIndexBuffer -= swiper.loopedSlides;\n swiper.loopDestroy();\n swiper.slides = $wrapperEl.children(`.${params.slideClass}`);\n }\n\n const baseLength = swiper.slides.length;\n\n if (index <= 0) {\n swiper.prependSlide(slides);\n return;\n }\n\n if (index >= baseLength) {\n swiper.appendSlide(slides);\n return;\n }\n\n let newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + 1 : activeIndexBuffer;\n const slidesBuffer = [];\n\n for (let i = baseLength - 1; i >= index; i -= 1) {\n const currentSlide = swiper.slides.eq(i);\n currentSlide.remove();\n slidesBuffer.unshift(currentSlide);\n }\n\n if (typeof slides === 'object' && 'length' in slides) {\n for (let i = 0; i < slides.length; i += 1) {\n if (slides[i]) $wrapperEl.append(slides[i]);\n }\n\n newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + slides.length : activeIndexBuffer;\n } else {\n $wrapperEl.append(slides);\n }\n\n for (let i = 0; i < slidesBuffer.length; i += 1) {\n $wrapperEl.append(slidesBuffer[i]);\n }\n\n if (params.loop) {\n swiper.loopCreate();\n }\n\n if (!params.observer) {\n swiper.update();\n }\n\n if (params.loop) {\n swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);\n } else {\n swiper.slideTo(newActiveIndex, 0, false);\n }\n }\n\n function removeSlide(slidesIndexes) {\n const swiper = this;\n const {\n params,\n $wrapperEl,\n activeIndex\n } = swiper;\n let activeIndexBuffer = activeIndex;\n\n if (params.loop) {\n activeIndexBuffer -= swiper.loopedSlides;\n swiper.loopDestroy();\n swiper.slides = $wrapperEl.children(`.${params.slideClass}`);\n }\n\n let newActiveIndex = activeIndexBuffer;\n let indexToRemove;\n\n if (typeof slidesIndexes === 'object' && 'length' in slidesIndexes) {\n for (let i = 0; i < slidesIndexes.length; i += 1) {\n indexToRemove = slidesIndexes[i];\n if (swiper.slides[indexToRemove]) swiper.slides.eq(indexToRemove).remove();\n if (indexToRemove < newActiveIndex) newActiveIndex -= 1;\n }\n\n newActiveIndex = Math.max(newActiveIndex, 0);\n } else {\n indexToRemove = slidesIndexes;\n if (swiper.slides[indexToRemove]) swiper.slides.eq(indexToRemove).remove();\n if (indexToRemove < newActiveIndex) newActiveIndex -= 1;\n newActiveIndex = Math.max(newActiveIndex, 0);\n }\n\n if (params.loop) {\n swiper.loopCreate();\n }\n\n if (!params.observer) {\n swiper.update();\n }\n\n if (params.loop) {\n swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);\n } else {\n swiper.slideTo(newActiveIndex, 0, false);\n }\n }\n\n function removeAllSlides() {\n const swiper = this;\n const slidesIndexes = [];\n\n for (let i = 0; i < swiper.slides.length; i += 1) {\n slidesIndexes.push(i);\n }\n\n swiper.removeSlide(slidesIndexes);\n }\n\n function Manipulation(_ref) {\n let {\n swiper\n } = _ref;\n Object.assign(swiper, {\n appendSlide: appendSlide.bind(swiper),\n prependSlide: prependSlide.bind(swiper),\n addSlide: addSlide.bind(swiper),\n removeSlide: removeSlide.bind(swiper),\n removeAllSlides: removeAllSlides.bind(swiper)\n });\n }\n\n function effectInit(params) {\n const {\n effect,\n swiper,\n on,\n setTranslate,\n setTransition,\n overwriteParams,\n perspective\n } = params;\n on('beforeInit', () => {\n if (swiper.params.effect !== effect) return;\n swiper.classNames.push(`${swiper.params.containerModifierClass}${effect}`);\n\n if (perspective && perspective()) {\n swiper.classNames.push(`${swiper.params.containerModifierClass}3d`);\n }\n\n const overwriteParamsResult = overwriteParams ? overwriteParams() : {};\n Object.assign(swiper.params, overwriteParamsResult);\n Object.assign(swiper.originalParams, overwriteParamsResult);\n });\n on('setTranslate', () => {\n if (swiper.params.effect !== effect) return;\n setTranslate();\n });\n on('setTransition', (_s, duration) => {\n if (swiper.params.effect !== effect) return;\n setTransition(duration);\n });\n let requireUpdateOnVirtual;\n on('virtualUpdate', () => {\n if (!swiper.slides.length) {\n requireUpdateOnVirtual = true;\n }\n\n requestAnimationFrame(() => {\n if (requireUpdateOnVirtual && swiper.slides.length) {\n setTranslate();\n requireUpdateOnVirtual = false;\n }\n });\n });\n }\n\n function effectTarget(effectParams, $slideEl) {\n if (effectParams.transformEl) {\n return $slideEl.find(effectParams.transformEl).css({\n 'backface-visibility': 'hidden',\n '-webkit-backface-visibility': 'hidden'\n });\n }\n\n return $slideEl;\n }\n\n function effectVirtualTransitionEnd(_ref) {\n let {\n swiper,\n duration,\n transformEl,\n allSlides\n } = _ref;\n const {\n slides,\n activeIndex,\n $wrapperEl\n } = swiper;\n\n if (swiper.params.virtualTranslate && duration !== 0) {\n let eventTriggered = false;\n let $transitionEndTarget;\n\n if (allSlides) {\n $transitionEndTarget = transformEl ? slides.find(transformEl) : slides;\n } else {\n $transitionEndTarget = transformEl ? slides.eq(activeIndex).find(transformEl) : slides.eq(activeIndex);\n }\n\n $transitionEndTarget.transitionEnd(() => {\n if (eventTriggered) return;\n if (!swiper || swiper.destroyed) return;\n eventTriggered = true;\n swiper.animating = false;\n const triggerEvents = ['webkitTransitionEnd', 'transitionend'];\n\n for (let i = 0; i < triggerEvents.length; i += 1) {\n $wrapperEl.trigger(triggerEvents[i]);\n }\n });\n }\n }\n\n function EffectFade(_ref) {\n let {\n swiper,\n extendParams,\n on\n } = _ref;\n extendParams({\n fadeEffect: {\n crossFade: false,\n transformEl: null\n }\n });\n\n const setTranslate = () => {\n const {\n slides\n } = swiper;\n const params = swiper.params.fadeEffect;\n\n for (let i = 0; i < slides.length; i += 1) {\n const $slideEl = swiper.slides.eq(i);\n const offset = $slideEl[0].swiperSlideOffset;\n let tx = -offset;\n if (!swiper.params.virtualTranslate) tx -= swiper.translate;\n let ty = 0;\n\n if (!swiper.isHorizontal()) {\n ty = tx;\n tx = 0;\n }\n\n const slideOpacity = swiper.params.fadeEffect.crossFade ? Math.max(1 - Math.abs($slideEl[0].progress), 0) : 1 + Math.min(Math.max($slideEl[0].progress, -1), 0);\n const $targetEl = effectTarget(params, $slideEl);\n $targetEl.css({\n opacity: slideOpacity\n }).transform(`translate3d(${tx}px, ${ty}px, 0px)`);\n }\n };\n\n const setTransition = duration => {\n const {\n transformEl\n } = swiper.params.fadeEffect;\n const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;\n $transitionElements.transition(duration);\n effectVirtualTransitionEnd({\n swiper,\n duration,\n transformEl,\n allSlides: true\n });\n };\n\n effectInit({\n effect: 'fade',\n swiper,\n on,\n setTranslate,\n setTransition,\n overwriteParams: () => ({\n slidesPerView: 1,\n slidesPerGroup: 1,\n watchSlidesProgress: true,\n spaceBetween: 0,\n virtualTranslate: !swiper.params.cssMode\n })\n });\n }\n\n function EffectCube(_ref) {\n let {\n swiper,\n extendParams,\n on\n } = _ref;\n extendParams({\n cubeEffect: {\n slideShadows: true,\n shadow: true,\n shadowOffset: 20,\n shadowScale: 0.94\n }\n });\n\n const setTranslate = () => {\n const {\n $el,\n $wrapperEl,\n slides,\n width: swiperWidth,\n height: swiperHeight,\n rtlTranslate: rtl,\n size: swiperSize,\n browser\n } = swiper;\n const params = swiper.params.cubeEffect;\n const isHorizontal = swiper.isHorizontal();\n const isVirtual = swiper.virtual && swiper.params.virtual.enabled;\n let wrapperRotate = 0;\n let $cubeShadowEl;\n\n if (params.shadow) {\n if (isHorizontal) {\n $cubeShadowEl = $wrapperEl.find('.swiper-cube-shadow');\n\n if ($cubeShadowEl.length === 0) {\n $cubeShadowEl = $('
');\n $wrapperEl.append($cubeShadowEl);\n }\n\n $cubeShadowEl.css({\n height: `${swiperWidth}px`\n });\n } else {\n $cubeShadowEl = $el.find('.swiper-cube-shadow');\n\n if ($cubeShadowEl.length === 0) {\n $cubeShadowEl = $('
');\n $el.append($cubeShadowEl);\n }\n }\n }\n\n for (let i = 0; i < slides.length; i += 1) {\n const $slideEl = slides.eq(i);\n let slideIndex = i;\n\n if (isVirtual) {\n slideIndex = parseInt($slideEl.attr('data-swiper-slide-index'), 10);\n }\n\n let slideAngle = slideIndex * 90;\n let round = Math.floor(slideAngle / 360);\n\n if (rtl) {\n slideAngle = -slideAngle;\n round = Math.floor(-slideAngle / 360);\n }\n\n const progress = Math.max(Math.min($slideEl[0].progress, 1), -1);\n let tx = 0;\n let ty = 0;\n let tz = 0;\n\n if (slideIndex % 4 === 0) {\n tx = -round * 4 * swiperSize;\n tz = 0;\n } else if ((slideIndex - 1) % 4 === 0) {\n tx = 0;\n tz = -round * 4 * swiperSize;\n } else if ((slideIndex - 2) % 4 === 0) {\n tx = swiperSize + round * 4 * swiperSize;\n tz = swiperSize;\n } else if ((slideIndex - 3) % 4 === 0) {\n tx = -swiperSize;\n tz = 3 * swiperSize + swiperSize * 4 * round;\n }\n\n if (rtl) {\n tx = -tx;\n }\n\n if (!isHorizontal) {\n ty = tx;\n tx = 0;\n }\n\n const transform = `rotateX(${isHorizontal ? 0 : -slideAngle}deg) rotateY(${isHorizontal ? slideAngle : 0}deg) translate3d(${tx}px, ${ty}px, ${tz}px)`;\n\n if (progress <= 1 && progress > -1) {\n wrapperRotate = slideIndex * 90 + progress * 90;\n if (rtl) wrapperRotate = -slideIndex * 90 - progress * 90;\n }\n\n $slideEl.transform(transform);\n\n if (params.slideShadows) {\n // Set shadows\n let shadowBefore = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');\n let shadowAfter = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');\n\n if (shadowBefore.length === 0) {\n shadowBefore = $(`
`);\n $slideEl.append(shadowBefore);\n }\n\n if (shadowAfter.length === 0) {\n shadowAfter = $(`
`);\n $slideEl.append(shadowAfter);\n }\n\n if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);\n if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);\n }\n }\n\n $wrapperEl.css({\n '-webkit-transform-origin': `50% 50% -${swiperSize / 2}px`,\n 'transform-origin': `50% 50% -${swiperSize / 2}px`\n });\n\n if (params.shadow) {\n if (isHorizontal) {\n $cubeShadowEl.transform(`translate3d(0px, ${swiperWidth / 2 + params.shadowOffset}px, ${-swiperWidth / 2}px) rotateX(90deg) rotateZ(0deg) scale(${params.shadowScale})`);\n } else {\n const shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90;\n const multiplier = 1.5 - (Math.sin(shadowAngle * 2 * Math.PI / 360) / 2 + Math.cos(shadowAngle * 2 * Math.PI / 360) / 2);\n const scale1 = params.shadowScale;\n const scale2 = params.shadowScale / multiplier;\n const offset = params.shadowOffset;\n $cubeShadowEl.transform(`scale3d(${scale1}, 1, ${scale2}) translate3d(0px, ${swiperHeight / 2 + offset}px, ${-swiperHeight / 2 / scale2}px) rotateX(-90deg)`);\n }\n }\n\n const zFactor = browser.isSafari || browser.isWebView ? -swiperSize / 2 : 0;\n $wrapperEl.transform(`translate3d(0px,0,${zFactor}px) rotateX(${swiper.isHorizontal() ? 0 : wrapperRotate}deg) rotateY(${swiper.isHorizontal() ? -wrapperRotate : 0}deg)`);\n };\n\n const setTransition = duration => {\n const {\n $el,\n slides\n } = swiper;\n slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);\n\n if (swiper.params.cubeEffect.shadow && !swiper.isHorizontal()) {\n $el.find('.swiper-cube-shadow').transition(duration);\n }\n };\n\n effectInit({\n effect: 'cube',\n swiper,\n on,\n setTranslate,\n setTransition,\n perspective: () => true,\n overwriteParams: () => ({\n slidesPerView: 1,\n slidesPerGroup: 1,\n watchSlidesProgress: true,\n resistanceRatio: 0,\n spaceBetween: 0,\n centeredSlides: false,\n virtualTranslate: true\n })\n });\n }\n\n function createShadow(params, $slideEl, side) {\n const shadowClass = `swiper-slide-shadow${side ? `-${side}` : ''}`;\n const $shadowContainer = params.transformEl ? $slideEl.find(params.transformEl) : $slideEl;\n let $shadowEl = $shadowContainer.children(`.${shadowClass}`);\n\n if (!$shadowEl.length) {\n $shadowEl = $(`
`);\n $shadowContainer.append($shadowEl);\n }\n\n return $shadowEl;\n }\n\n function EffectFlip(_ref) {\n let {\n swiper,\n extendParams,\n on\n } = _ref;\n extendParams({\n flipEffect: {\n slideShadows: true,\n limitRotation: true,\n transformEl: null\n }\n });\n\n const setTranslate = () => {\n const {\n slides,\n rtlTranslate: rtl\n } = swiper;\n const params = swiper.params.flipEffect;\n\n for (let i = 0; i < slides.length; i += 1) {\n const $slideEl = slides.eq(i);\n let progress = $slideEl[0].progress;\n\n if (swiper.params.flipEffect.limitRotation) {\n progress = Math.max(Math.min($slideEl[0].progress, 1), -1);\n }\n\n const offset = $slideEl[0].swiperSlideOffset;\n const rotate = -180 * progress;\n let rotateY = rotate;\n let rotateX = 0;\n let tx = swiper.params.cssMode ? -offset - swiper.translate : -offset;\n let ty = 0;\n\n if (!swiper.isHorizontal()) {\n ty = tx;\n tx = 0;\n rotateX = -rotateY;\n rotateY = 0;\n } else if (rtl) {\n rotateY = -rotateY;\n }\n\n $slideEl[0].style.zIndex = -Math.abs(Math.round(progress)) + slides.length;\n\n if (params.slideShadows) {\n // Set shadows\n let shadowBefore = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');\n let shadowAfter = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');\n\n if (shadowBefore.length === 0) {\n shadowBefore = createShadow(params, $slideEl, swiper.isHorizontal() ? 'left' : 'top');\n }\n\n if (shadowAfter.length === 0) {\n shadowAfter = createShadow(params, $slideEl, swiper.isHorizontal() ? 'right' : 'bottom');\n }\n\n if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);\n if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);\n }\n\n const transform = `translate3d(${tx}px, ${ty}px, 0px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;\n const $targetEl = effectTarget(params, $slideEl);\n $targetEl.transform(transform);\n }\n };\n\n const setTransition = duration => {\n const {\n transformEl\n } = swiper.params.flipEffect;\n const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;\n $transitionElements.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);\n effectVirtualTransitionEnd({\n swiper,\n duration,\n transformEl\n });\n };\n\n effectInit({\n effect: 'flip',\n swiper,\n on,\n setTranslate,\n setTransition,\n perspective: () => true,\n overwriteParams: () => ({\n slidesPerView: 1,\n slidesPerGroup: 1,\n watchSlidesProgress: true,\n spaceBetween: 0,\n virtualTranslate: !swiper.params.cssMode\n })\n });\n }\n\n function EffectCoverflow(_ref) {\n let {\n swiper,\n extendParams,\n on\n } = _ref;\n extendParams({\n coverflowEffect: {\n rotate: 50,\n stretch: 0,\n depth: 100,\n scale: 1,\n modifier: 1,\n slideShadows: true,\n transformEl: null\n }\n });\n\n const setTranslate = () => {\n const {\n width: swiperWidth,\n height: swiperHeight,\n slides,\n slidesSizesGrid\n } = swiper;\n const params = swiper.params.coverflowEffect;\n const isHorizontal = swiper.isHorizontal();\n const transform = swiper.translate;\n const center = isHorizontal ? -transform + swiperWidth / 2 : -transform + swiperHeight / 2;\n const rotate = isHorizontal ? params.rotate : -params.rotate;\n const translate = params.depth; // Each slide offset from center\n\n for (let i = 0, length = slides.length; i < length; i += 1) {\n const $slideEl = slides.eq(i);\n const slideSize = slidesSizesGrid[i];\n const slideOffset = $slideEl[0].swiperSlideOffset;\n const centerOffset = (center - slideOffset - slideSize / 2) / slideSize;\n const offsetMultiplier = typeof params.modifier === 'function' ? params.modifier(centerOffset) : centerOffset * params.modifier;\n let rotateY = isHorizontal ? rotate * offsetMultiplier : 0;\n let rotateX = isHorizontal ? 0 : rotate * offsetMultiplier; // var rotateZ = 0\n\n let translateZ = -translate * Math.abs(offsetMultiplier);\n let stretch = params.stretch; // Allow percentage to make a relative stretch for responsive sliders\n\n if (typeof stretch === 'string' && stretch.indexOf('%') !== -1) {\n stretch = parseFloat(params.stretch) / 100 * slideSize;\n }\n\n let translateY = isHorizontal ? 0 : stretch * offsetMultiplier;\n let translateX = isHorizontal ? stretch * offsetMultiplier : 0;\n let scale = 1 - (1 - params.scale) * Math.abs(offsetMultiplier); // Fix for ultra small values\n\n if (Math.abs(translateX) < 0.001) translateX = 0;\n if (Math.abs(translateY) < 0.001) translateY = 0;\n if (Math.abs(translateZ) < 0.001) translateZ = 0;\n if (Math.abs(rotateY) < 0.001) rotateY = 0;\n if (Math.abs(rotateX) < 0.001) rotateX = 0;\n if (Math.abs(scale) < 0.001) scale = 0;\n const slideTransform = `translate3d(${translateX}px,${translateY}px,${translateZ}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(${scale})`;\n const $targetEl = effectTarget(params, $slideEl);\n $targetEl.transform(slideTransform);\n $slideEl[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1;\n\n if (params.slideShadows) {\n // Set shadows\n let $shadowBeforeEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');\n let $shadowAfterEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');\n\n if ($shadowBeforeEl.length === 0) {\n $shadowBeforeEl = createShadow(params, $slideEl, isHorizontal ? 'left' : 'top');\n }\n\n if ($shadowAfterEl.length === 0) {\n $shadowAfterEl = createShadow(params, $slideEl, isHorizontal ? 'right' : 'bottom');\n }\n\n if ($shadowBeforeEl.length) $shadowBeforeEl[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0;\n if ($shadowAfterEl.length) $shadowAfterEl[0].style.opacity = -offsetMultiplier > 0 ? -offsetMultiplier : 0;\n }\n }\n };\n\n const setTransition = duration => {\n const {\n transformEl\n } = swiper.params.coverflowEffect;\n const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;\n $transitionElements.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);\n };\n\n effectInit({\n effect: 'coverflow',\n swiper,\n on,\n setTranslate,\n setTransition,\n perspective: () => true,\n overwriteParams: () => ({\n watchSlidesProgress: true\n })\n });\n }\n\n function EffectCreative(_ref) {\n let {\n swiper,\n extendParams,\n on\n } = _ref;\n extendParams({\n creativeEffect: {\n transformEl: null,\n limitProgress: 1,\n shadowPerProgress: false,\n progressMultiplier: 1,\n perspective: true,\n prev: {\n translate: [0, 0, 0],\n rotate: [0, 0, 0],\n opacity: 1,\n scale: 1\n },\n next: {\n translate: [0, 0, 0],\n rotate: [0, 0, 0],\n opacity: 1,\n scale: 1\n }\n }\n });\n\n const getTranslateValue = value => {\n if (typeof value === 'string') return value;\n return `${value}px`;\n };\n\n const setTranslate = () => {\n const {\n slides,\n $wrapperEl,\n slidesSizesGrid\n } = swiper;\n const params = swiper.params.creativeEffect;\n const {\n progressMultiplier: multiplier\n } = params;\n const isCenteredSlides = swiper.params.centeredSlides;\n\n if (isCenteredSlides) {\n const margin = slidesSizesGrid[0] / 2 - swiper.params.slidesOffsetBefore || 0;\n $wrapperEl.transform(`translateX(calc(50% - ${margin}px))`);\n }\n\n for (let i = 0; i < slides.length; i += 1) {\n const $slideEl = slides.eq(i);\n const slideProgress = $slideEl[0].progress;\n const progress = Math.min(Math.max($slideEl[0].progress, -params.limitProgress), params.limitProgress);\n let originalProgress = progress;\n\n if (!isCenteredSlides) {\n originalProgress = Math.min(Math.max($slideEl[0].originalProgress, -params.limitProgress), params.limitProgress);\n }\n\n const offset = $slideEl[0].swiperSlideOffset;\n const t = [swiper.params.cssMode ? -offset - swiper.translate : -offset, 0, 0];\n const r = [0, 0, 0];\n let custom = false;\n\n if (!swiper.isHorizontal()) {\n t[1] = t[0];\n t[0] = 0;\n }\n\n let data = {\n translate: [0, 0, 0],\n rotate: [0, 0, 0],\n scale: 1,\n opacity: 1\n };\n\n if (progress < 0) {\n data = params.next;\n custom = true;\n } else if (progress > 0) {\n data = params.prev;\n custom = true;\n } // set translate\n\n\n t.forEach((value, index) => {\n t[index] = `calc(${value}px + (${getTranslateValue(data.translate[index])} * ${Math.abs(progress * multiplier)}))`;\n }); // set rotates\n\n r.forEach((value, index) => {\n r[index] = data.rotate[index] * Math.abs(progress * multiplier);\n });\n $slideEl[0].style.zIndex = -Math.abs(Math.round(slideProgress)) + slides.length;\n const translateString = t.join(', ');\n const rotateString = `rotateX(${r[0]}deg) rotateY(${r[1]}deg) rotateZ(${r[2]}deg)`;\n const scaleString = originalProgress < 0 ? `scale(${1 + (1 - data.scale) * originalProgress * multiplier})` : `scale(${1 - (1 - data.scale) * originalProgress * multiplier})`;\n const opacityString = originalProgress < 0 ? 1 + (1 - data.opacity) * originalProgress * multiplier : 1 - (1 - data.opacity) * originalProgress * multiplier;\n const transform = `translate3d(${translateString}) ${rotateString} ${scaleString}`; // Set shadows\n\n if (custom && data.shadow || !custom) {\n let $shadowEl = $slideEl.children('.swiper-slide-shadow');\n\n if ($shadowEl.length === 0 && data.shadow) {\n $shadowEl = createShadow(params, $slideEl);\n }\n\n if ($shadowEl.length) {\n const shadowOpacity = params.shadowPerProgress ? progress * (1 / params.limitProgress) : progress;\n $shadowEl[0].style.opacity = Math.min(Math.max(Math.abs(shadowOpacity), 0), 1);\n }\n }\n\n const $targetEl = effectTarget(params, $slideEl);\n $targetEl.transform(transform).css({\n opacity: opacityString\n });\n\n if (data.origin) {\n $targetEl.css('transform-origin', data.origin);\n }\n }\n };\n\n const setTransition = duration => {\n const {\n transformEl\n } = swiper.params.creativeEffect;\n const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;\n $transitionElements.transition(duration).find('.swiper-slide-shadow').transition(duration);\n effectVirtualTransitionEnd({\n swiper,\n duration,\n transformEl,\n allSlides: true\n });\n };\n\n effectInit({\n effect: 'creative',\n swiper,\n on,\n setTranslate,\n setTransition,\n perspective: () => swiper.params.creativeEffect.perspective,\n overwriteParams: () => ({\n watchSlidesProgress: true,\n virtualTranslate: !swiper.params.cssMode\n })\n });\n }\n\n function EffectCards(_ref) {\n let {\n swiper,\n extendParams,\n on\n } = _ref;\n extendParams({\n cardsEffect: {\n slideShadows: true,\n transformEl: null\n }\n });\n\n const setTranslate = () => {\n const {\n slides,\n activeIndex\n } = swiper;\n const params = swiper.params.cardsEffect;\n const {\n startTranslate,\n isTouched\n } = swiper.touchEventsData;\n const currentTranslate = swiper.translate;\n\n for (let i = 0; i < slides.length; i += 1) {\n const $slideEl = slides.eq(i);\n const slideProgress = $slideEl[0].progress;\n const progress = Math.min(Math.max(slideProgress, -4), 4);\n let offset = $slideEl[0].swiperSlideOffset;\n\n if (swiper.params.centeredSlides && !swiper.params.cssMode) {\n swiper.$wrapperEl.transform(`translateX(${swiper.minTranslate()}px)`);\n }\n\n if (swiper.params.centeredSlides && swiper.params.cssMode) {\n offset -= slides[0].swiperSlideOffset;\n }\n\n let tX = swiper.params.cssMode ? -offset - swiper.translate : -offset;\n let tY = 0;\n const tZ = -100 * Math.abs(progress);\n let scale = 1;\n let rotate = -2 * progress;\n let tXAdd = 8 - Math.abs(progress) * 0.75;\n const slideIndex = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.from + i : i;\n const isSwipeToNext = (slideIndex === activeIndex || slideIndex === activeIndex - 1) && progress > 0 && progress < 1 && (isTouched || swiper.params.cssMode) && currentTranslate < startTranslate;\n const isSwipeToPrev = (slideIndex === activeIndex || slideIndex === activeIndex + 1) && progress < 0 && progress > -1 && (isTouched || swiper.params.cssMode) && currentTranslate > startTranslate;\n\n if (isSwipeToNext || isSwipeToPrev) {\n const subProgress = (1 - Math.abs((Math.abs(progress) - 0.5) / 0.5)) ** 0.5;\n rotate += -28 * progress * subProgress;\n scale += -0.5 * subProgress;\n tXAdd += 96 * subProgress;\n tY = `${-25 * subProgress * Math.abs(progress)}%`;\n }\n\n if (progress < 0) {\n // next\n tX = `calc(${tX}px + (${tXAdd * Math.abs(progress)}%))`;\n } else if (progress > 0) {\n // prev\n tX = `calc(${tX}px + (-${tXAdd * Math.abs(progress)}%))`;\n } else {\n tX = `${tX}px`;\n }\n\n if (!swiper.isHorizontal()) {\n const prevY = tY;\n tY = tX;\n tX = prevY;\n }\n\n const scaleString = progress < 0 ? `${1 + (1 - scale) * progress}` : `${1 - (1 - scale) * progress}`;\n const transform = `\n translate3d(${tX}, ${tY}, ${tZ}px)\n rotateZ(${rotate}deg)\n scale(${scaleString})\n `;\n\n if (params.slideShadows) {\n // Set shadows\n let $shadowEl = $slideEl.find('.swiper-slide-shadow');\n\n if ($shadowEl.length === 0) {\n $shadowEl = createShadow(params, $slideEl);\n }\n\n if ($shadowEl.length) $shadowEl[0].style.opacity = Math.min(Math.max((Math.abs(progress) - 0.5) / 0.5, 0), 1);\n }\n\n $slideEl[0].style.zIndex = -Math.abs(Math.round(slideProgress)) + slides.length;\n const $targetEl = effectTarget(params, $slideEl);\n $targetEl.transform(transform);\n }\n };\n\n const setTransition = duration => {\n const {\n transformEl\n } = swiper.params.cardsEffect;\n const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;\n $transitionElements.transition(duration).find('.swiper-slide-shadow').transition(duration);\n effectVirtualTransitionEnd({\n swiper,\n duration,\n transformEl\n });\n };\n\n effectInit({\n effect: 'cards',\n swiper,\n on,\n setTranslate,\n setTransition,\n perspective: () => true,\n overwriteParams: () => ({\n watchSlidesProgress: true,\n virtualTranslate: !swiper.params.cssMode\n })\n });\n }\n\n // Swiper Class\n const modules = [Virtual, Keyboard, Mousewheel, Navigation, Pagination, Scrollbar, Parallax, Zoom, Lazy, Controller, A11y, History, HashNavigation, Autoplay, Thumb, freeMode, Grid, Manipulation, EffectFade, EffectCube, EffectFlip, EffectCoverflow, EffectCreative, EffectCards];\n Swiper.use(modules);\n\n return Swiper;\n\n}));\n//# sourceMappingURL=swiper-bundle.js.map\n","import Swiper from 'swiper/swiper-bundle';\nif (global) global.Swiper = Swiper\n"],"preExistingComment":"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvc3dpcGVyL3N3aXBlci1idW5kbGUuanMiLCJ3cC1jb250ZW50L3RoZW1lcy9qY29yZTIvanMvc3dpcGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUNwclVBOzs7O0FBQ0EsSUFBSSxNQUFKLEVBQVksTUFBTSxDQUFDLE1BQVAsR0FBZ0IscUJBQWhCIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24oKXtmdW5jdGlvbiByKGUsbix0KXtmdW5jdGlvbiBvKGksZil7aWYoIW5baV0pe2lmKCFlW2ldKXt2YXIgYz1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlO2lmKCFmJiZjKXJldHVybiBjKGksITApO2lmKHUpcmV0dXJuIHUoaSwhMCk7dmFyIGE9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitpK1wiJ1wiKTt0aHJvdyBhLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsYX12YXIgcD1uW2ldPXtleHBvcnRzOnt9fTtlW2ldWzBdLmNhbGwocC5leHBvcnRzLGZ1bmN0aW9uKHIpe3ZhciBuPWVbaV1bMV1bcl07cmV0dXJuIG8obnx8cil9LHAscC5leHBvcnRzLHIsZSxuLHQpfXJldHVybiBuW2ldLmV4cG9ydHN9Zm9yKHZhciB1PVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmUsaT0wO2k8dC5sZW5ndGg7aSsrKW8odFtpXSk7cmV0dXJuIG99cmV0dXJuIHJ9KSgpIiwiLyoqXG4gKiBTd2lwZXIgOC4wLjdcbiAqIE1vc3QgbW9kZXJuIG1vYmlsZSB0b3VjaCBzbGlkZXIgYW5kIGZyYW1ld29yayB3aXRoIGhhcmR3YXJlIGFjY2VsZXJhdGVkIHRyYW5zaXRpb25zXG4gKiBodHRwczovL3N3aXBlcmpzLmNvbVxuICpcbiAqIENvcHlyaWdodCAyMDE0LTIwMjIgVmxhZGltaXIgS2hhcmxhbXBpZGlcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAqXG4gKiBSZWxlYXNlZCBvbjogTWFyY2ggNCwgMjAyMlxuICovXG5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCkgOlxuICAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShmYWN0b3J5KSA6XG4gICAgKGdsb2JhbCA9IHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbFRoaXMgOiBnbG9iYWwgfHwgc2VsZiwgZ2xvYmFsLlN3aXBlciA9IGZhY3RvcnkoKSk7XG59KSh0aGlzLCAoZnVuY3Rpb24gKCkgeyAndXNlIHN0cmljdCc7XG5cbiAgICAvKipcbiAgICAgKiBTU1IgV2luZG93IDQuMC4yXG4gICAgICogQmV0dGVyIGhhbmRsaW5nIGZvciB3aW5kb3cgb2JqZWN0IGluIFNTUiBlbnZpcm9ubWVudFxuICAgICAqIGh0dHBzOi8vZ2l0aHViLmNvbS9ub2xpbWl0czR3ZWIvc3NyLXdpbmRvd1xuICAgICAqXG4gICAgICogQ29weXJpZ2h0IDIwMjEsIFZsYWRpbWlyIEtoYXJsYW1waWRpXG4gICAgICpcbiAgICAgKiBMaWNlbnNlZCB1bmRlciBNSVRcbiAgICAgKlxuICAgICAqIFJlbGVhc2VkIG9uOiBEZWNlbWJlciAxMywgMjAyMVxuICAgICAqL1xuXG4gICAgLyogZXNsaW50LWRpc2FibGUgbm8tcGFyYW0tcmVhc3NpZ24gKi9cbiAgICBmdW5jdGlvbiBpc09iamVjdCQxKG9iaikge1xuICAgICAgcmV0dXJuIG9iaiAhPT0gbnVsbCAmJiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiAnY29uc3RydWN0b3InIGluIG9iaiAmJiBvYmouY29uc3RydWN0b3IgPT09IE9iamVjdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBleHRlbmQkMSh0YXJnZXQsIHNyYykge1xuICAgICAgaWYgKHRhcmdldCA9PT0gdm9pZCAwKSB7XG4gICAgICAgIHRhcmdldCA9IHt9O1xuICAgICAgfVxuXG4gICAgICBpZiAoc3JjID09PSB2b2lkIDApIHtcbiAgICAgICAgc3JjID0ge307XG4gICAgICB9XG5cbiAgICAgIE9iamVjdC5rZXlzKHNyYykuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIHRhcmdldFtrZXldID09PSAndW5kZWZpbmVkJykgdGFyZ2V0W2tleV0gPSBzcmNba2V5XTtlbHNlIGlmIChpc09iamVjdCQxKHNyY1trZXldKSAmJiBpc09iamVjdCQxKHRhcmdldFtrZXldKSAmJiBPYmplY3Qua2V5cyhzcmNba2V5XSkubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGV4dGVuZCQxKHRhcmdldFtrZXldLCBzcmNba2V5XSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IHNzckRvY3VtZW50ID0ge1xuICAgICAgYm9keToge30sXG5cbiAgICAgIGFkZEV2ZW50TGlzdGVuZXIoKSB7fSxcblxuICAgICAgcmVtb3ZlRXZlbnRMaXN0ZW5lcigpIHt9LFxuXG4gICAgICBhY3RpdmVFbGVtZW50OiB7XG4gICAgICAgIGJsdXIoKSB7fSxcblxuICAgICAgICBub2RlTmFtZTogJydcbiAgICAgIH0sXG5cbiAgICAgIHF1ZXJ5U2VsZWN0b3IoKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfSxcblxuICAgICAgcXVlcnlTZWxlY3RvckFsbCgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfSxcblxuICAgICAgZ2V0RWxlbWVudEJ5SWQoKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfSxcblxuICAgICAgY3JlYXRlRXZlbnQoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgaW5pdEV2ZW50KCkge31cblxuICAgICAgICB9O1xuICAgICAgfSxcblxuICAgICAgY3JlYXRlRWxlbWVudCgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjaGlsZHJlbjogW10sXG4gICAgICAgICAgY2hpbGROb2RlczogW10sXG4gICAgICAgICAgc3R5bGU6IHt9LFxuXG4gICAgICAgICAgc2V0QXR0cmlidXRlKCkge30sXG5cbiAgICAgICAgICBnZXRFbGVtZW50c0J5VGFnTmFtZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgfTtcbiAgICAgIH0sXG5cbiAgICAgIGNyZWF0ZUVsZW1lbnROUygpIHtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgfSxcblxuICAgICAgaW1wb3J0Tm9kZSgpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9LFxuXG4gICAgICBsb2NhdGlvbjoge1xuICAgICAgICBoYXNoOiAnJyxcbiAgICAgICAgaG9zdDogJycsXG4gICAgICAgIGhvc3RuYW1lOiAnJyxcbiAgICAgICAgaHJlZjogJycsXG4gICAgICAgIG9yaWdpbjogJycsXG4gICAgICAgIHBhdGhuYW1lOiAnJyxcbiAgICAgICAgcHJvdG9jb2w6ICcnLFxuICAgICAgICBzZWFyY2g6ICcnXG4gICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGdldERvY3VtZW50KCkge1xuICAgICAgY29uc3QgZG9jID0gdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyA/IGRvY3VtZW50IDoge307XG4gICAgICBleHRlbmQkMShkb2MsIHNzckRvY3VtZW50KTtcbiAgICAgIHJldHVybiBkb2M7XG4gICAgfVxuXG4gICAgY29uc3Qgc3NyV2luZG93ID0ge1xuICAgICAgZG9jdW1lbnQ6IHNzckRvY3VtZW50LFxuICAgICAgbmF2aWdhdG9yOiB7XG4gICAgICAgIHVzZXJBZ2VudDogJydcbiAgICAgIH0sXG4gICAgICBsb2NhdGlvbjoge1xuICAgICAgICBoYXNoOiAnJyxcbiAgICAgICAgaG9zdDogJycsXG4gICAgICAgIGhvc3RuYW1lOiAnJyxcbiAgICAgICAgaHJlZjogJycsXG4gICAgICAgIG9yaWdpbjogJycsXG4gICAgICAgIHBhdGhuYW1lOiAnJyxcbiAgICAgICAgcHJvdG9jb2w6ICcnLFxuICAgICAgICBzZWFyY2g6ICcnXG4gICAgICB9LFxuICAgICAgaGlzdG9yeToge1xuICAgICAgICByZXBsYWNlU3RhdGUoKSB7fSxcblxuICAgICAgICBwdXNoU3RhdGUoKSB7fSxcblxuICAgICAgICBnbygpIHt9LFxuXG4gICAgICAgIGJhY2soKSB7fVxuXG4gICAgICB9LFxuICAgICAgQ3VzdG9tRXZlbnQ6IGZ1bmN0aW9uIEN1c3RvbUV2ZW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH0sXG5cbiAgICAgIGFkZEV2ZW50TGlzdGVuZXIoKSB7fSxcblxuICAgICAgcmVtb3ZlRXZlbnRMaXN0ZW5lcigpIHt9LFxuXG4gICAgICBnZXRDb21wdXRlZFN0eWxlKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGdldFByb3BlcnR5VmFsdWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgICAgfVxuXG4gICAgICAgIH07XG4gICAgICB9LFxuXG4gICAgICBJbWFnZSgpIHt9LFxuXG4gICAgICBEYXRlKCkge30sXG5cbiAgICAgIHNjcmVlbjoge30sXG5cbiAgICAgIHNldFRpbWVvdXQoKSB7fSxcblxuICAgICAgY2xlYXJUaW1lb3V0KCkge30sXG5cbiAgICAgIG1hdGNoTWVkaWEoKSB7XG4gICAgICAgIHJldHVybiB7fTtcbiAgICAgIH0sXG5cbiAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZShjYWxsYmFjaykge1xuICAgICAgICBpZiAodHlwZW9mIHNldFRpbWVvdXQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGNhbGxiYWNrLCAwKTtcbiAgICAgIH0sXG5cbiAgICAgIGNhbmNlbEFuaW1hdGlvbkZyYW1lKGlkKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjbGVhclRpbWVvdXQoaWQpO1xuICAgICAgfVxuXG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGdldFdpbmRvdygpIHtcbiAgICAgIGNvbnN0IHdpbiA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93IDoge307XG4gICAgICBleHRlbmQkMSh3aW4sIHNzcldpbmRvdyk7XG4gICAgICByZXR1cm4gd2luO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERvbTcgNC4wLjRcbiAgICAgKiBNaW5pbWFsaXN0aWMgSmF2YVNjcmlwdCBsaWJyYXJ5IGZvciBET00gbWFuaXB1bGF0aW9uLCB3aXRoIGEgalF1ZXJ5LWNvbXBhdGlibGUgQVBJXG4gICAgICogaHR0cHM6Ly9mcmFtZXdvcms3LmlvL2RvY3MvZG9tNy5odG1sXG4gICAgICpcbiAgICAgKiBDb3B5cmlnaHQgMjAyMiwgVmxhZGltaXIgS2hhcmxhbXBpZGlcbiAgICAgKlxuICAgICAqIExpY2Vuc2VkIHVuZGVyIE1JVFxuICAgICAqXG4gICAgICogUmVsZWFzZWQgb246IEphbnVhcnkgMTEsIDIwMjJcbiAgICAgKi9cbiAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1wcm90byAqL1xuXG4gICAgZnVuY3Rpb24gbWFrZVJlYWN0aXZlKG9iaikge1xuICAgICAgY29uc3QgcHJvdG8gPSBvYmouX19wcm90b19fO1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwgJ19fcHJvdG9fXycsIHtcbiAgICAgICAgZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBwcm90bztcbiAgICAgICAgfSxcblxuICAgICAgICBzZXQodmFsdWUpIHtcbiAgICAgICAgICBwcm90by5fX3Byb3RvX18gPSB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjbGFzcyBEb203IGV4dGVuZHMgQXJyYXkge1xuICAgICAgY29uc3RydWN0b3IoaXRlbXMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBpdGVtcyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBzdXBlcihpdGVtcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3VwZXIoLi4uKGl0ZW1zIHx8IFtdKSk7XG4gICAgICAgICAgbWFrZVJlYWN0aXZlKHRoaXMpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhcnJheUZsYXQoYXJyKSB7XG4gICAgICBpZiAoYXJyID09PSB2b2lkIDApIHtcbiAgICAgICAgYXJyID0gW107XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlcyA9IFtdO1xuICAgICAgYXJyLmZvckVhY2goZWwgPT4ge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShlbCkpIHtcbiAgICAgICAgICByZXMucHVzaCguLi5hcnJheUZsYXQoZWwpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXMucHVzaChlbCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhcnJheUZpbHRlcihhcnIsIGNhbGxiYWNrKSB7XG4gICAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLmZpbHRlci5jYWxsKGFyciwgY2FsbGJhY2spO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFycmF5VW5pcXVlKGFycikge1xuICAgICAgY29uc3QgdW5pcXVlQXJyYXkgPSBbXTtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgaWYgKHVuaXF1ZUFycmF5LmluZGV4T2YoYXJyW2ldKSA9PT0gLTEpIHVuaXF1ZUFycmF5LnB1c2goYXJyW2ldKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHVuaXF1ZUFycmF5O1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gcXNhKHNlbGVjdG9yLCBjb250ZXh0KSB7XG4gICAgICBpZiAodHlwZW9mIHNlbGVjdG9yICE9PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gW3NlbGVjdG9yXTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYSA9IFtdO1xuICAgICAgY29uc3QgcmVzID0gY29udGV4dC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKTtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgYS5wdXNoKHJlc1tpXSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uICQoc2VsZWN0b3IsIGNvbnRleHQpIHtcbiAgICAgIGNvbnN0IHdpbmRvdyA9IGdldFdpbmRvdygpO1xuICAgICAgY29uc3QgZG9jdW1lbnQgPSBnZXREb2N1bWVudCgpO1xuICAgICAgbGV0IGFyciA9IFtdO1xuXG4gICAgICBpZiAoIWNvbnRleHQgJiYgc2VsZWN0b3IgaW5zdGFuY2VvZiBEb203KSB7XG4gICAgICAgIHJldHVybiBzZWxlY3RvcjtcbiAgICAgIH1cblxuICAgICAgaWYgKCFzZWxlY3Rvcikge1xuICAgICAgICByZXR1cm4gbmV3IERvbTcoYXJyKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBzZWxlY3RvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc3QgaHRtbCA9IHNlbGVjdG9yLnRyaW0oKTtcblxuICAgICAgICBpZiAoaHRtbC5pbmRleE9mKCc8JykgPj0gMCAmJiBodG1sLmluZGV4T2YoJz4nKSA+PSAwKSB7XG4gICAgICAgICAgbGV0IHRvQ3JlYXRlID0gJ2Rpdic7XG4gICAgICAgICAgaWYgKGh0bWwuaW5kZXhPZignPGxpJykgPT09IDApIHRvQ3JlYXRlID0gJ3VsJztcbiAgICAgICAgICBpZiAoaHRtbC5pbmRleE9mKCc8dHInKSA9PT0gMCkgdG9DcmVhdGUgPSAndGJvZHknO1xuICAgICAgICAgIGlmIChodG1sLmluZGV4T2YoJzx0ZCcpID09PSAwIHx8IGh0bWwuaW5kZXhPZignPHRoJykgPT09IDApIHRvQ3JlYXRlID0gJ3RyJztcbiAgICAgICAgICBpZiAoaHRtbC5pbmRleE9mKCc8dGJvZHknKSA9PT0gMCkgdG9DcmVhdGUgPSAndGFibGUnO1xuICAgICAgICAgIGlmIChodG1sLmluZGV4T2YoJzxvcHRpb24nKSA9PT0gMCkgdG9DcmVhdGUgPSAnc2VsZWN0JztcbiAgICAgICAgICBjb25zdCB0ZW1wUGFyZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0b0NyZWF0ZSk7XG4gICAgICAgICAgdGVtcFBhcmVudC5pbm5lckhUTUwgPSBodG1sO1xuXG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0ZW1wUGFyZW50LmNoaWxkTm9kZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGFyci5wdXNoKHRlbXBQYXJlbnQuY2hpbGROb2Rlc1tpXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFyciA9IHFzYShzZWxlY3Rvci50cmltKCksIGNvbnRleHQgfHwgZG9jdW1lbnQpO1xuICAgICAgICB9IC8vIGFyciA9IHFzYShzZWxlY3RvciwgZG9jdW1lbnQpO1xuXG4gICAgICB9IGVsc2UgaWYgKHNlbGVjdG9yLm5vZGVUeXBlIHx8IHNlbGVjdG9yID09PSB3aW5kb3cgfHwgc2VsZWN0b3IgPT09IGRvY3VtZW50KSB7XG4gICAgICAgIGFyci5wdXNoKHNlbGVjdG9yKTtcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShzZWxlY3RvcikpIHtcbiAgICAgICAgaWYgKHNlbGVjdG9yIGluc3RhbmNlb2YgRG9tNykgcmV0dXJuIHNlbGVjdG9yO1xuICAgICAgICBhcnIgPSBzZWxlY3RvcjtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5ldyBEb203KGFycmF5VW5pcXVlKGFycikpO1xuICAgIH1cblxuICAgICQuZm4gPSBEb203LnByb3RvdHlwZTsgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5cbiAgICBmdW5jdGlvbiBhZGRDbGFzcygpIHtcbiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBjbGFzc2VzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgICBjbGFzc2VzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjbGFzc05hbWVzID0gYXJyYXlGbGF0KGNsYXNzZXMubWFwKGMgPT4gYy5zcGxpdCgnICcpKSk7XG4gICAgICB0aGlzLmZvckVhY2goZWwgPT4ge1xuICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKC4uLmNsYXNzTmFtZXMpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW1vdmVDbGFzcygpIHtcbiAgICAgIGZvciAodmFyIF9sZW4yID0gYXJndW1lbnRzLmxlbmd0aCwgY2xhc3NlcyA9IG5ldyBBcnJheShfbGVuMiksIF9rZXkyID0gMDsgX2tleTIgPCBfbGVuMjsgX2tleTIrKykge1xuICAgICAgICBjbGFzc2VzW19rZXkyXSA9IGFyZ3VtZW50c1tfa2V5Ml07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNsYXNzTmFtZXMgPSBhcnJheUZsYXQoY2xhc3Nlcy5tYXAoYyA9PiBjLnNwbGl0KCcgJykpKTtcbiAgICAgIHRoaXMuZm9yRWFjaChlbCA9PiB7XG4gICAgICAgIGVsLmNsYXNzTGlzdC5yZW1vdmUoLi4uY2xhc3NOYW1lcyk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRvZ2dsZUNsYXNzKCkge1xuICAgICAgZm9yICh2YXIgX2xlbjMgPSBhcmd1bWVudHMubGVuZ3RoLCBjbGFzc2VzID0gbmV3IEFycmF5KF9sZW4zKSwgX2tleTMgPSAwOyBfa2V5MyA8IF9sZW4zOyBfa2V5MysrKSB7XG4gICAgICAgIGNsYXNzZXNbX2tleTNdID0gYXJndW1lbnRzW19rZXkzXTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2xhc3NOYW1lcyA9IGFycmF5RmxhdChjbGFzc2VzLm1hcChjID0+IGMuc3BsaXQoJyAnKSkpO1xuICAgICAgdGhpcy5mb3JFYWNoKGVsID0+IHtcbiAgICAgICAgY2xhc3NOYW1lcy5mb3JFYWNoKGNsYXNzTmFtZSA9PiB7XG4gICAgICAgICAgZWwuY2xhc3NMaXN0LnRvZ2dsZShjbGFzc05hbWUpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhc0NsYXNzKCkge1xuICAgICAgZm9yICh2YXIgX2xlbjQgPSBhcmd1bWVudHMubGVuZ3RoLCBjbGFzc2VzID0gbmV3IEFycmF5KF9sZW40KSwgX2tleTQgPSAwOyBfa2V5NCA8IF9sZW40OyBfa2V5NCsrKSB7XG4gICAgICAgIGNsYXNzZXNbX2tleTRdID0gYXJndW1lbnRzW19rZXk0XTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2xhc3NOYW1lcyA9IGFycmF5RmxhdChjbGFzc2VzLm1hcChjID0+IGMuc3BsaXQoJyAnKSkpO1xuICAgICAgcmV0dXJuIGFycmF5RmlsdGVyKHRoaXMsIGVsID0+IHtcbiAgICAgICAgcmV0dXJuIGNsYXNzTmFtZXMuZmlsdGVyKGNsYXNzTmFtZSA9PiBlbC5jbGFzc0xpc3QuY29udGFpbnMoY2xhc3NOYW1lKSkubGVuZ3RoID4gMDtcbiAgICAgIH0pLmxlbmd0aCA+IDA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXR0cihhdHRycywgdmFsdWUpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxICYmIHR5cGVvZiBhdHRycyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgLy8gR2V0IGF0dHJcbiAgICAgICAgaWYgKHRoaXNbMF0pIHJldHVybiB0aGlzWzBdLmdldEF0dHJpYnV0ZShhdHRycyk7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9IC8vIFNldCBhdHRyc1xuXG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgIC8vIFN0cmluZ1xuICAgICAgICAgIHRoaXNbaV0uc2V0QXR0cmlidXRlKGF0dHJzLCB2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gT2JqZWN0XG4gICAgICAgICAgZm9yIChjb25zdCBhdHRyTmFtZSBpbiBhdHRycykge1xuICAgICAgICAgICAgdGhpc1tpXVthdHRyTmFtZV0gPSBhdHRyc1thdHRyTmFtZV07XG4gICAgICAgICAgICB0aGlzW2ldLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0cnNbYXR0ck5hbWVdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVtb3ZlQXR0cihhdHRyKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgdGhpc1tpXS5yZW1vdmVBdHRyaWJ1dGUoYXR0cik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybSh0cmFuc2Zvcm0pIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICB0aGlzW2ldLnN0eWxlLnRyYW5zZm9ybSA9IHRyYW5zZm9ybTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdHJhbnNpdGlvbiQxKGR1cmF0aW9uKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgdGhpc1tpXS5zdHlsZS50cmFuc2l0aW9uRHVyYXRpb24gPSB0eXBlb2YgZHVyYXRpb24gIT09ICdzdHJpbmcnID8gYCR7ZHVyYXRpb259bXNgIDogZHVyYXRpb247XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uKCkge1xuICAgICAgZm9yICh2YXIgX2xlbjUgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW41KSwgX2tleTUgPSAwOyBfa2V5NSA8IF9sZW41OyBfa2V5NSsrKSB7XG4gICAgICAgIGFyZ3NbX2tleTVdID0gYXJndW1lbnRzW19rZXk1XTtcbiAgICAgIH1cblxuICAgICAgbGV0IFtldmVudFR5cGUsIHRhcmdldFNlbGVjdG9yLCBsaXN0ZW5lciwgY2FwdHVyZV0gPSBhcmdzO1xuXG4gICAgICBpZiAodHlwZW9mIGFyZ3NbMV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgW2V2ZW50VHlwZSwgbGlzdGVuZXIsIGNhcHR1cmVdID0gYXJncztcbiAgICAgICAgdGFyZ2V0U2VsZWN0b3IgPSB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIGlmICghY2FwdHVyZSkgY2FwdHVyZSA9IGZhbHNlO1xuXG4gICAgICBmdW5jdGlvbiBoYW5kbGVMaXZlRXZlbnQoZSkge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSBlLnRhcmdldDtcbiAgICAgICAgaWYgKCF0YXJnZXQpIHJldHVybjtcbiAgICAgICAgY29uc3QgZXZlbnREYXRhID0gZS50YXJnZXQuZG9tN0V2ZW50RGF0YSB8fCBbXTtcblxuICAgICAgICBpZiAoZXZlbnREYXRhLmluZGV4T2YoZSkgPCAwKSB7XG4gICAgICAgICAgZXZlbnREYXRhLnVuc2hpZnQoZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJCh0YXJnZXQpLmlzKHRhcmdldFNlbGVjdG9yKSkgbGlzdGVuZXIuYXBwbHkodGFyZ2V0LCBldmVudERhdGEpO2Vsc2Uge1xuICAgICAgICAgIGNvbnN0IHBhcmVudHMgPSAkKHRhcmdldCkucGFyZW50cygpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cbiAgICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IHBhcmVudHMubGVuZ3RoOyBrICs9IDEpIHtcbiAgICAgICAgICAgIGlmICgkKHBhcmVudHNba10pLmlzKHRhcmdldFNlbGVjdG9yKSkgbGlzdGVuZXIuYXBwbHkocGFyZW50c1trXSwgZXZlbnREYXRhKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gaGFuZGxlRXZlbnQoZSkge1xuICAgICAgICBjb25zdCBldmVudERhdGEgPSBlICYmIGUudGFyZ2V0ID8gZS50YXJnZXQuZG9tN0V2ZW50RGF0YSB8fCBbXSA6IFtdO1xuXG4gICAgICAgIGlmIChldmVudERhdGEuaW5kZXhPZihlKSA8IDApIHtcbiAgICAgICAgICBldmVudERhdGEudW5zaGlmdChlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxpc3RlbmVyLmFwcGx5KHRoaXMsIGV2ZW50RGF0YSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGV2ZW50cyA9IGV2ZW50VHlwZS5zcGxpdCgnICcpO1xuICAgICAgbGV0IGo7XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBjb25zdCBlbCA9IHRoaXNbaV07XG5cbiAgICAgICAgaWYgKCF0YXJnZXRTZWxlY3Rvcikge1xuICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBldmVudHMubGVuZ3RoOyBqICs9IDEpIHtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0gZXZlbnRzW2pdO1xuICAgICAgICAgICAgaWYgKCFlbC5kb203TGlzdGVuZXJzKSBlbC5kb203TGlzdGVuZXJzID0ge307XG4gICAgICAgICAgICBpZiAoIWVsLmRvbTdMaXN0ZW5lcnNbZXZlbnRdKSBlbC5kb203TGlzdGVuZXJzW2V2ZW50XSA9IFtdO1xuICAgICAgICAgICAgZWwuZG9tN0xpc3RlbmVyc1tldmVudF0ucHVzaCh7XG4gICAgICAgICAgICAgIGxpc3RlbmVyLFxuICAgICAgICAgICAgICBwcm94eUxpc3RlbmVyOiBoYW5kbGVFdmVudFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBlbC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBoYW5kbGVFdmVudCwgY2FwdHVyZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIExpdmUgZXZlbnRzXG4gICAgICAgICAgZm9yIChqID0gMDsgaiA8IGV2ZW50cy5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgICAgICAgY29uc3QgZXZlbnQgPSBldmVudHNbal07XG4gICAgICAgICAgICBpZiAoIWVsLmRvbTdMaXZlTGlzdGVuZXJzKSBlbC5kb203TGl2ZUxpc3RlbmVycyA9IHt9O1xuICAgICAgICAgICAgaWYgKCFlbC5kb203TGl2ZUxpc3RlbmVyc1tldmVudF0pIGVsLmRvbTdMaXZlTGlzdGVuZXJzW2V2ZW50XSA9IFtdO1xuICAgICAgICAgICAgZWwuZG9tN0xpdmVMaXN0ZW5lcnNbZXZlbnRdLnB1c2goe1xuICAgICAgICAgICAgICBsaXN0ZW5lcixcbiAgICAgICAgICAgICAgcHJveHlMaXN0ZW5lcjogaGFuZGxlTGl2ZUV2ZW50XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGhhbmRsZUxpdmVFdmVudCwgY2FwdHVyZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9mZigpIHtcbiAgICAgIGZvciAodmFyIF9sZW42ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuNiksIF9rZXk2ID0gMDsgX2tleTYgPCBfbGVuNjsgX2tleTYrKykge1xuICAgICAgICBhcmdzW19rZXk2XSA9IGFyZ3VtZW50c1tfa2V5Nl07XG4gICAgICB9XG5cbiAgICAgIGxldCBbZXZlbnRUeXBlLCB0YXJnZXRTZWxlY3RvciwgbGlzdGVuZXIsIGNhcHR1cmVdID0gYXJncztcblxuICAgICAgaWYgKHR5cGVvZiBhcmdzWzFdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIFtldmVudFR5cGUsIGxpc3RlbmVyLCBjYXB0dXJlXSA9IGFyZ3M7XG4gICAgICAgIHRhcmdldFNlbGVjdG9yID0gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWNhcHR1cmUpIGNhcHR1cmUgPSBmYWxzZTtcbiAgICAgIGNvbnN0IGV2ZW50cyA9IGV2ZW50VHlwZS5zcGxpdCgnICcpO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGV2ZW50cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBjb25zdCBldmVudCA9IGV2ZW50c1tpXTtcblxuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMubGVuZ3RoOyBqICs9IDEpIHtcbiAgICAgICAgICBjb25zdCBlbCA9IHRoaXNbal07XG4gICAgICAgICAgbGV0IGhhbmRsZXJzO1xuXG4gICAgICAgICAgaWYgKCF0YXJnZXRTZWxlY3RvciAmJiBlbC5kb203TGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBoYW5kbGVycyA9IGVsLmRvbTdMaXN0ZW5lcnNbZXZlbnRdO1xuICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0U2VsZWN0b3IgJiYgZWwuZG9tN0xpdmVMaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGhhbmRsZXJzID0gZWwuZG9tN0xpdmVMaXN0ZW5lcnNbZXZlbnRdO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChoYW5kbGVycyAmJiBoYW5kbGVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGsgPSBoYW5kbGVycy5sZW5ndGggLSAxOyBrID49IDA7IGsgLT0gMSkge1xuICAgICAgICAgICAgICBjb25zdCBoYW5kbGVyID0gaGFuZGxlcnNba107XG5cbiAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyICYmIGhhbmRsZXIubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudCwgaGFuZGxlci5wcm94eUxpc3RlbmVyLCBjYXB0dXJlKTtcbiAgICAgICAgICAgICAgICBoYW5kbGVycy5zcGxpY2UoaywgMSk7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgaGFuZGxlci5saXN0ZW5lciAmJiBoYW5kbGVyLmxpc3RlbmVyLmRvbTdwcm94eSAmJiBoYW5kbGVyLmxpc3RlbmVyLmRvbTdwcm94eSA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICBlbC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBoYW5kbGVyLnByb3h5TGlzdGVuZXIsIGNhcHR1cmUpO1xuICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShrLCAxKTtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmICghbGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICBlbC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBoYW5kbGVyLnByb3h5TGlzdGVuZXIsIGNhcHR1cmUpO1xuICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShrLCAxKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0cmlnZ2VyKCkge1xuICAgICAgY29uc3Qgd2luZG93ID0gZ2V0V2luZG93KCk7XG5cbiAgICAgIGZvciAodmFyIF9sZW45ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuOSksIF9rZXk5ID0gMDsgX2tleTkgPCBfbGVuOTsgX2tleTkrKykge1xuICAgICAgICBhcmdzW19rZXk5XSA9IGFyZ3VtZW50c1tfa2V5OV07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGV2ZW50cyA9IGFyZ3NbMF0uc3BsaXQoJyAnKTtcbiAgICAgIGNvbnN0IGV2ZW50RGF0YSA9IGFyZ3NbMV07XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXZlbnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGNvbnN0IGV2ZW50ID0gZXZlbnRzW2ldO1xuXG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgICAgIGNvbnN0IGVsID0gdGhpc1tqXTtcblxuICAgICAgICAgIGlmICh3aW5kb3cuQ3VzdG9tRXZlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IGV2dCA9IG5ldyB3aW5kb3cuQ3VzdG9tRXZlbnQoZXZlbnQsIHtcbiAgICAgICAgICAgICAgZGV0YWlsOiBldmVudERhdGEsXG4gICAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZWwuZG9tN0V2ZW50RGF0YSA9IGFyZ3MuZmlsdGVyKChkYXRhLCBkYXRhSW5kZXgpID0+IGRhdGFJbmRleCA+IDApO1xuICAgICAgICAgICAgZWwuZGlzcGF0Y2hFdmVudChldnQpO1xuICAgICAgICAgICAgZWwuZG9tN0V2ZW50RGF0YSA9IFtdO1xuICAgICAgICAgICAgZGVsZXRlIGVsLmRvbTdFdmVudERhdGE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRyYW5zaXRpb25FbmQkMShjYWxsYmFjaykge1xuICAgICAgY29uc3QgZG9tID0gdGhpcztcblxuICAgICAgZnVuY3Rpb24gZmlyZUNhbGxCYWNrKGUpIHtcbiAgICAgICAgaWYgKGUudGFyZ2V0ICE9PSB0aGlzKSByZXR1cm47XG4gICAgICAgIGNhbGxiYWNrLmNhbGwodGhpcywgZSk7XG4gICAgICAgIGRvbS5vZmYoJ3RyYW5zaXRpb25lbmQnLCBmaXJlQ2FsbEJhY2spO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgZG9tLm9uKCd0cmFuc2l0aW9uZW5kJywgZmlyZUNhbGxCYWNrKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb3V0ZXJXaWR0aChpbmNsdWRlTWFyZ2lucykge1xuICAgICAgaWYgKHRoaXMubGVuZ3RoID4gMCkge1xuICAgICAgICBpZiAoaW5jbHVkZU1hcmdpbnMpIHtcbiAgICAgICAgICBjb25zdCBzdHlsZXMgPSB0aGlzLnN0eWxlcygpO1xuICAgICAgICAgIHJldHVybiB0aGlzWzBdLm9mZnNldFdpZHRoICsgcGFyc2VGbG9hdChzdHlsZXMuZ2V0UHJvcGVydHlWYWx1ZSgnbWFyZ2luLXJpZ2h0JykpICsgcGFyc2VGbG9hdChzdHlsZXMuZ2V0UHJvcGVydHlWYWx1ZSgnbWFyZ2luLWxlZnQnKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpc1swXS5vZmZzZXRXaWR0aDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb3V0ZXJIZWlnaHQoaW5jbHVkZU1hcmdpbnMpIHtcbiAgICAgIGlmICh0aGlzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgaWYgKGluY2x1ZGVNYXJnaW5zKSB7XG4gICAgICAgICAgY29uc3Qgc3R5bGVzID0gdGhpcy5zdHlsZXMoKTtcbiAgICAgICAgICByZXR1cm4gdGhpc1swXS5vZmZzZXRIZWlnaHQgKyBwYXJzZUZsb2F0KHN0eWxlcy5nZXRQcm9wZXJ0eVZhbHVlKCdtYXJnaW4tdG9wJykpICsgcGFyc2VGbG9hdChzdHlsZXMuZ2V0UHJvcGVydHlWYWx1ZSgnbWFyZ2luLWJvdHRvbScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzWzBdLm9mZnNldEhlaWdodDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb2Zmc2V0KCkge1xuICAgICAgaWYgKHRoaXMubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zdCB3aW5kb3cgPSBnZXRXaW5kb3coKTtcbiAgICAgICAgY29uc3QgZG9jdW1lbnQgPSBnZXREb2N1bWVudCgpO1xuICAgICAgICBjb25zdCBlbCA9IHRoaXNbMF07XG4gICAgICAgIGNvbnN0IGJveCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBjb25zdCBib2R5ID0gZG9jdW1lbnQuYm9keTtcbiAgICAgICAgY29uc3QgY2xpZW50VG9wID0gZWwuY2xpZW50VG9wIHx8IGJvZHkuY2xpZW50VG9wIHx8IDA7XG4gICAgICAgIGNvbnN0IGNsaWVudExlZnQgPSBlbC5jbGllbnRMZWZ0IHx8IGJvZHkuY2xpZW50TGVmdCB8fCAwO1xuICAgICAgICBjb25zdCBzY3JvbGxUb3AgPSBlbCA9PT0gd2luZG93ID8gd2luZG93LnNjcm9sbFkgOiBlbC5zY3JvbGxUb3A7XG4gICAgICAgIGNvbnN0IHNjcm9sbExlZnQgPSBlbCA9PT0gd2luZG93ID8gd2luZG93LnNjcm9sbFggOiBlbC5zY3JvbGxMZWZ0O1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHRvcDogYm94LnRvcCArIHNjcm9sbFRvcCAtIGNsaWVudFRvcCxcbiAgICAgICAgICBsZWZ0OiBib3gubGVmdCArIHNjcm9sbExlZnQgLSBjbGllbnRMZWZ0XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0eWxlcygpIHtcbiAgICAgIGNvbnN0IHdpbmRvdyA9IGdldFdpbmRvdygpO1xuICAgICAgaWYgKHRoaXNbMF0pIHJldHVybiB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzWzBdLCBudWxsKTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjc3MocHJvcHMsIHZhbHVlKSB7XG4gICAgICBjb25zdCB3aW5kb3cgPSBnZXRXaW5kb3coKTtcbiAgICAgIGxldCBpO1xuXG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBpZiAodHlwZW9mIHByb3BzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIC8vIC5jc3MoJ3dpZHRoJylcbiAgICAgICAgICBpZiAodGhpc1swXSkgcmV0dXJuIHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHRoaXNbMF0sIG51bGwpLmdldFByb3BlcnR5VmFsdWUocHJvcHMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIC5jc3MoeyB3aWR0aDogJzEwMHB4JyB9KVxuICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHByb3AgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgdGhpc1tpXS5zdHlsZVtwcm9wXSA9IHByb3BzW3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmIHR5cGVvZiBwcm9wcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgLy8gLmNzcygnd2lkdGgnLCAnMTAwcHgnKVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgIHRoaXNbaV0uc3R5bGVbcHJvcHNdID0gdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZWFjaChjYWxsYmFjaykge1xuICAgICAgaWYgKCFjYWxsYmFjaykgcmV0dXJuIHRoaXM7XG4gICAgICB0aGlzLmZvckVhY2goKGVsLCBpbmRleCkgPT4ge1xuICAgICAgICBjYWxsYmFjay5hcHBseShlbCwgW2VsLCBpbmRleF0pO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmaWx0ZXIoY2FsbGJhY2spIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGFycmF5RmlsdGVyKHRoaXMsIGNhbGxiYWNrKTtcbiAgICAgIHJldHVybiAkKHJlc3VsdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaHRtbChodG1sKSB7XG4gICAgICBpZiAodHlwZW9mIGh0bWwgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybiB0aGlzWzBdID8gdGhpc1swXS5pbm5lckhUTUwgOiBudWxsO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgdGhpc1tpXS5pbm5lckhUTUwgPSBodG1sO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0ZXh0KHRleHQpIHtcbiAgICAgIGlmICh0eXBlb2YgdGV4dCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbMF0gPyB0aGlzWzBdLnRleHRDb250ZW50LnRyaW0oKSA6IG51bGw7XG4gICAgICB9XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICB0aGlzW2ldLnRleHRDb250ZW50ID0gdGV4dDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXMoc2VsZWN0b3IpIHtcbiAgICAgIGNvbnN0IHdpbmRvdyA9IGdldFdpbmRvdygpO1xuICAgICAgY29uc3QgZG9jdW1lbnQgPSBnZXREb2N1bWVudCgpO1xuICAgICAgY29uc3QgZWwgPSB0aGlzWzBdO1xuICAgICAgbGV0IGNvbXBhcmVXaXRoO1xuICAgICAgbGV0IGk7XG4gICAgICBpZiAoIWVsIHx8IHR5cGVvZiBzZWxlY3RvciA9PT0gJ3VuZGVmaW5lZCcpIHJldHVybiBmYWxzZTtcblxuICAgICAgaWYgKHR5cGVvZiBzZWxlY3RvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYgKGVsLm1hdGNoZXMpIHJldHVybiBlbC5tYXRjaGVzKHNlbGVjdG9yKTtcbiAgICAgICAgaWYgKGVsLndlYmtpdE1hdGNoZXNTZWxlY3RvcikgcmV0dXJuIGVsLndlYmtpdE1hdGNoZXNTZWxlY3RvcihzZWxlY3Rvcik7XG4gICAgICAgIGlmIChlbC5tc01hdGNoZXNTZWxlY3RvcikgcmV0dXJuIGVsLm1zTWF0Y2hlc1NlbGVjdG9yKHNlbGVjdG9yKTtcbiAgICAgICAgY29tcGFyZVdpdGggPSAkKHNlbGVjdG9yKTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29tcGFyZVdpdGgubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICBpZiAoY29tcGFyZVdpdGhbaV0gPT09IGVsKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNlbGVjdG9yID09PSBkb2N1bWVudCkge1xuICAgICAgICByZXR1cm4gZWwgPT09IGRvY3VtZW50O1xuICAgICAgfVxuXG4gICAgICBpZiAoc2VsZWN0b3IgPT09IHdpbmRvdykge1xuICAgICAgICByZXR1cm4gZWwgPT09IHdpbmRvdztcbiAgICAgIH1cblxuICAgICAgaWYgKHNlbGVjdG9yLm5vZGVUeXBlIHx8IHNlbGVjdG9yIGluc3RhbmNlb2YgRG9tNykge1xuICAgICAgICBjb21wYXJlV2l0aCA9IHNlbGVjdG9yLm5vZGVUeXBlID8gW3NlbGVjdG9yXSA6IHNlbGVjdG9yO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb21wYXJlV2l0aC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgIGlmIChjb21wYXJlV2l0aFtpXSA9PT0gZWwpIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5kZXgoKSB7XG4gICAgICBsZXQgY2hpbGQgPSB0aGlzWzBdO1xuICAgICAgbGV0IGk7XG5cbiAgICAgIGlmIChjaGlsZCkge1xuICAgICAgICBpID0gMDsgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5cbiAgICAgICAgd2hpbGUgKChjaGlsZCA9IGNoaWxkLnByZXZpb3VzU2libGluZykgIT09IG51bGwpIHtcbiAgICAgICAgICBpZiAoY2hpbGQubm9kZVR5cGUgPT09IDEpIGkgKz0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVxKGluZGV4KSB7XG4gICAgICBpZiAodHlwZW9mIGluZGV4ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIHRoaXM7XG4gICAgICBjb25zdCBsZW5ndGggPSB0aGlzLmxlbmd0aDtcblxuICAgICAgaWYgKGluZGV4ID4gbGVuZ3RoIC0gMSkge1xuICAgICAgICByZXR1cm4gJChbXSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgICAgY29uc3QgcmV0dXJuSW5kZXggPSBsZW5ndGggKyBpbmRleDtcbiAgICAgICAgaWYgKHJldHVybkluZGV4IDwgMCkgcmV0dXJuICQoW10pO1xuICAgICAgICByZXR1cm4gJChbdGhpc1tyZXR1cm5JbmRleF1dKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuICQoW3RoaXNbaW5kZXhdXSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXBwZW5kKCkge1xuICAgICAgbGV0IG5ld0NoaWxkO1xuICAgICAgY29uc3QgZG9jdW1lbnQgPSBnZXREb2N1bWVudCgpO1xuXG4gICAgICBmb3IgKGxldCBrID0gMDsgayA8IGFyZ3VtZW50cy5sZW5ndGg7IGsgKz0gMSkge1xuICAgICAgICBuZXdDaGlsZCA9IGsgPCAwIHx8IGFyZ3VtZW50cy5sZW5ndGggPD0gayA/IHVuZGVmaW5lZCA6IGFyZ3VtZW50c1trXTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIG5ld0NoaWxkID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY29uc3QgdGVtcERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICAgICAgdGVtcERpdi5pbm5lckhUTUwgPSBuZXdDaGlsZDtcblxuICAgICAgICAgICAgd2hpbGUgKHRlbXBEaXYuZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgICB0aGlzW2ldLmFwcGVuZENoaWxkKHRlbXBEaXYuZmlyc3RDaGlsZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChuZXdDaGlsZCBpbnN0YW5jZW9mIERvbTcpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbmV3Q2hpbGQubGVuZ3RoOyBqICs9IDEpIHtcbiAgICAgICAgICAgICAgdGhpc1tpXS5hcHBlbmRDaGlsZChuZXdDaGlsZFtqXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXNbaV0uYXBwZW5kQ2hpbGQobmV3Q2hpbGQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwcmVwZW5kKG5ld0NoaWxkKSB7XG4gICAgICBjb25zdCBkb2N1bWVudCA9IGdldERvY3VtZW50KCk7XG4gICAgICBsZXQgaTtcbiAgICAgIGxldCBqO1xuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBpZiAodHlwZW9mIG5ld0NoaWxkID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGNvbnN0IHRlbXBEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgICB0ZW1wRGl2LmlubmVySFRNTCA9IG5ld0NoaWxkO1xuXG4gICAgICAgICAgZm9yIChqID0gdGVtcERpdi5jaGlsZE5vZGVzLmxlbmd0aCAtIDE7IGogPj0gMDsgaiAtPSAxKSB7XG4gICAgICAgICAgICB0aGlzW2ldLmluc2VydEJlZm9yZSh0ZW1wRGl2LmNoaWxkTm9kZXNbal0sIHRoaXNbaV0uY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKG5ld0NoaWxkIGluc3RhbmNlb2YgRG9tNykge1xuICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBuZXdDaGlsZC5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgICAgICAgdGhpc1tpXS5pbnNlcnRCZWZvcmUobmV3Q2hpbGRbal0sIHRoaXNbaV0uY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXNbaV0uaW5zZXJ0QmVmb3JlKG5ld0NoaWxkLCB0aGlzW2ldLmNoaWxkTm9kZXNbMF0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG5leHQoc2VsZWN0b3IpIHtcbiAgICAgIGlmICh0aGlzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICAgICAgaWYgKHRoaXNbMF0ubmV4dEVsZW1lbnRTaWJsaW5nICYmICQodGhpc1swXS5uZXh0RWxlbWVudFNpYmxpbmcpLmlzKHNlbGVjdG9yKSkge1xuICAgICAgICAgICAgcmV0dXJuICQoW3RoaXNbMF0ubmV4dEVsZW1lbnRTaWJsaW5nXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuICQoW10pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXNbMF0ubmV4dEVsZW1lbnRTaWJsaW5nKSByZXR1cm4gJChbdGhpc1swXS5uZXh0RWxlbWVudFNpYmxpbmddKTtcbiAgICAgICAgcmV0dXJuICQoW10pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gJChbXSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbmV4dEFsbChzZWxlY3Rvcikge1xuICAgICAgY29uc3QgbmV4dEVscyA9IFtdO1xuICAgICAgbGV0IGVsID0gdGhpc1swXTtcbiAgICAgIGlmICghZWwpIHJldHVybiAkKFtdKTtcblxuICAgICAgd2hpbGUgKGVsLm5leHRFbGVtZW50U2libGluZykge1xuICAgICAgICBjb25zdCBuZXh0ID0gZWwubmV4dEVsZW1lbnRTaWJsaW5nOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cbiAgICAgICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICAgICAgaWYgKCQobmV4dCkuaXMoc2VsZWN0b3IpKSBuZXh0RWxzLnB1c2gobmV4dCk7XG4gICAgICAgIH0gZWxzZSBuZXh0RWxzLnB1c2gobmV4dCk7XG5cbiAgICAgICAgZWwgPSBuZXh0O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gJChuZXh0RWxzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwcmV2KHNlbGVjdG9yKSB7XG4gICAgICBpZiAodGhpcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IGVsID0gdGhpc1swXTtcblxuICAgICAgICBpZiAoc2VsZWN0b3IpIHtcbiAgICAgICAgICBpZiAoZWwucHJldmlvdXNFbGVtZW50U2libGluZyAmJiAkKGVsLnByZXZpb3VzRWxlbWVudFNpYmxpbmcpLmlzKHNlbGVjdG9yKSkge1xuICAgICAgICAgICAgcmV0dXJuICQoW2VsLnByZXZpb3VzRWxlbWVudFNpYmxpbmddKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gJChbXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZWwucHJldmlvdXNFbGVtZW50U2libGluZykgcmV0dXJuICQoW2VsLnByZXZpb3VzRWxlbWVudFNpYmxpbmddKTtcbiAgICAgICAgcmV0dXJuICQoW10pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gJChbXSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcHJldkFsbChzZWxlY3Rvcikge1xuICAgICAgY29uc3QgcHJldkVscyA9IFtdO1xuICAgICAgbGV0IGVsID0gdGhpc1swXTtcbiAgICAgIGlmICghZWwpIHJldHVybiAkKFtdKTtcblxuICAgICAgd2hpbGUgKGVsLnByZXZpb3VzRWxlbWVudFNpYmxpbmcpIHtcbiAgICAgICAgY29uc3QgcHJldiA9IGVsLnByZXZpb3VzRWxlbWVudFNpYmxpbmc7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblxuICAgICAgICBpZiAoc2VsZWN0b3IpIHtcbiAgICAgICAgICBpZiAoJChwcmV2KS5pcyhzZWxlY3RvcikpIHByZXZFbHMucHVzaChwcmV2KTtcbiAgICAgICAgfSBlbHNlIHByZXZFbHMucHVzaChwcmV2KTtcblxuICAgICAgICBlbCA9IHByZXY7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAkKHByZXZFbHMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBhcmVudChzZWxlY3Rvcikge1xuICAgICAgY29uc3QgcGFyZW50cyA9IFtdOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBpZiAodGhpc1tpXS5wYXJlbnROb2RlICE9PSBudWxsKSB7XG4gICAgICAgICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICAgICAgICBpZiAoJCh0aGlzW2ldLnBhcmVudE5vZGUpLmlzKHNlbGVjdG9yKSkgcGFyZW50cy5wdXNoKHRoaXNbaV0ucGFyZW50Tm9kZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBhcmVudHMucHVzaCh0aGlzW2ldLnBhcmVudE5vZGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gJChwYXJlbnRzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYXJlbnRzKHNlbGVjdG9yKSB7XG4gICAgICBjb25zdCBwYXJlbnRzID0gW107IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGxldCBwYXJlbnQgPSB0aGlzW2ldLnBhcmVudE5vZGU7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblxuICAgICAgICB3aGlsZSAocGFyZW50KSB7XG4gICAgICAgICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICAgICAgICBpZiAoJChwYXJlbnQpLmlzKHNlbGVjdG9yKSkgcGFyZW50cy5wdXNoKHBhcmVudCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBhcmVudHMucHVzaChwYXJlbnQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHBhcmVudCA9IHBhcmVudC5wYXJlbnROb2RlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAkKHBhcmVudHMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNsb3Nlc3Qoc2VsZWN0b3IpIHtcbiAgICAgIGxldCBjbG9zZXN0ID0gdGhpczsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXG4gICAgICBpZiAodHlwZW9mIHNlbGVjdG9yID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm4gJChbXSk7XG4gICAgICB9XG5cbiAgICAgIGlmICghY2xvc2VzdC5pcyhzZWxlY3RvcikpIHtcbiAgICAgICAgY2xvc2VzdCA9IGNsb3Nlc3QucGFyZW50cyhzZWxlY3RvcikuZXEoMCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjbG9zZXN0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZpbmQoc2VsZWN0b3IpIHtcbiAgICAgIGNvbnN0IGZvdW5kRWxlbWVudHMgPSBbXTtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGNvbnN0IGZvdW5kID0gdGhpc1tpXS5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKTtcblxuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGZvdW5kLmxlbmd0aDsgaiArPSAxKSB7XG4gICAgICAgICAgZm91bmRFbGVtZW50cy5wdXNoKGZvdW5kW2pdKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gJChmb3VuZEVsZW1lbnRzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjaGlsZHJlbihzZWxlY3Rvcikge1xuICAgICAgY29uc3QgY2hpbGRyZW4gPSBbXTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgY29uc3QgY2hpbGROb2RlcyA9IHRoaXNbaV0uY2hpbGRyZW47XG5cbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBjaGlsZE5vZGVzLmxlbmd0aDsgaiArPSAxKSB7XG4gICAgICAgICAgaWYgKCFzZWxlY3RvciB8fCAkKGNoaWxkTm9kZXNbal0pLmlzKHNlbGVjdG9yKSkge1xuICAgICAgICAgICAgY2hpbGRyZW4ucHVzaChjaGlsZE5vZGVzW2pdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuICQoY2hpbGRyZW4pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlbW92ZSgpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBpZiAodGhpc1tpXS5wYXJlbnROb2RlKSB0aGlzW2ldLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpc1tpXSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGNvbnN0IE1ldGhvZHMgPSB7XG4gICAgICBhZGRDbGFzcyxcbiAgICAgIHJlbW92ZUNsYXNzLFxuICAgICAgaGFzQ2xhc3MsXG4gICAgICB0b2dnbGVDbGFzcyxcbiAgICAgIGF0dHIsXG4gICAgICByZW1vdmVBdHRyLFxuICAgICAgdHJhbnNmb3JtLFxuICAgICAgdHJhbnNpdGlvbjogdHJhbnNpdGlvbiQxLFxuICAgICAgb24sXG4gICAgICBvZmYsXG4gICAgICB0cmlnZ2VyLFxuICAgICAgdHJhbnNpdGlvbkVuZDogdHJhbnNpdGlvbkVuZCQxLFxuICAgICAgb3V0ZXJXaWR0aCxcbiAgICAgIG91dGVySGVpZ2h0LFxuICAgICAgc3R5bGVzLFxuICAgICAgb2Zmc2V0LFxuICAgICAgY3NzLFxuICAgICAgZWFjaCxcbiAgICAgIGh0bWwsXG4gICAgICB0ZXh0LFxuICAgICAgaXMsXG4gICAgICBpbmRleCxcbiAgICAgIGVxLFxuICAgICAgYXBwZW5kLFxuICAgICAgcHJlcGVuZCxcbiAgICAgIG5leHQsXG4gICAgICBuZXh0QWxsLFxuICAgICAgcHJldixcbiAgICAgIHByZXZBbGwsXG4gICAgICBwYXJlbnQsXG4gICAgICBwYXJlbnRzLFxuICAgICAgY2xvc2VzdCxcbiAgICAgIGZpbmQsXG4gICAgICBjaGlsZHJlbixcbiAgICAgIGZpbHRlcixcbiAgICAgIHJlbW92ZVxuICAgIH07XG4gICAgT2JqZWN0LmtleXMoTWV0aG9kcykuZm9yRWFjaChtZXRob2ROYW1lID0+IHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSgkLmZuLCBtZXRob2ROYW1lLCB7XG4gICAgICAgIHZhbHVlOiBNZXRob2RzW21ldGhvZE5hbWVdLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZVxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBkZWxldGVQcm9wcyhvYmopIHtcbiAgICAgIGNvbnN0IG9iamVjdCA9IG9iajtcbiAgICAgIE9iamVjdC5rZXlzKG9iamVjdCkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIG9iamVjdFtrZXldID0gbnVsbDtcbiAgICAgICAgfSBjYXRjaCAoZSkgey8vIG5vIGdldHRlciBmb3Igb2JqZWN0XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGRlbGV0ZSBvYmplY3Rba2V5XTtcbiAgICAgICAgfSBjYXRjaCAoZSkgey8vIHNvbWV0aGluZyBnb3Qgd3JvbmdcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbmV4dFRpY2soY2FsbGJhY2ssIGRlbGF5KSB7XG4gICAgICBpZiAoZGVsYXkgPT09IHZvaWQgMCkge1xuICAgICAgICBkZWxheSA9IDA7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzZXRUaW1lb3V0KGNhbGxiYWNrLCBkZWxheSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbm93KCkge1xuICAgICAgcmV0dXJuIERhdGUubm93KCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Q29tcHV0ZWRTdHlsZSQxKGVsKSB7XG4gICAgICBjb25zdCB3aW5kb3cgPSBnZXRXaW5kb3coKTtcbiAgICAgIGxldCBzdHlsZTtcblxuICAgICAgaWYgKHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKSB7XG4gICAgICAgIHN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWwsIG51bGwpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXN0eWxlICYmIGVsLmN1cnJlbnRTdHlsZSkge1xuICAgICAgICBzdHlsZSA9IGVsLmN1cnJlbnRTdHlsZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFzdHlsZSkge1xuICAgICAgICBzdHlsZSA9IGVsLnN0eWxlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc3R5bGU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0VHJhbnNsYXRlKGVsLCBheGlzKSB7XG4gICAgICBpZiAoYXhpcyA9PT0gdm9pZCAwKSB7XG4gICAgICAgIGF4aXMgPSAneCc7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHdpbmRvdyA9IGdldFdpbmRvdygpO1xuICAgICAgbGV0IG1hdHJpeDtcbiAgICAgIGxldCBjdXJUcmFuc2Zvcm07XG4gICAgICBsZXQgdHJhbnNmb3JtTWF0cml4O1xuICAgICAgY29uc3QgY3VyU3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlJDEoZWwpO1xuXG4gICAgICBpZiAod2luZG93LldlYktpdENTU01hdHJpeCkge1xuICAgICAgICBjdXJUcmFuc2Zvcm0gPSBjdXJTdHlsZS50cmFuc2Zvcm0gfHwgY3VyU3R5bGUud2Via2l0VHJhbnNmb3JtO1xuXG4gICAgICAgIGlmIChjdXJUcmFuc2Zvcm0uc3BsaXQoJywnKS5sZW5ndGggPiA2KSB7XG4gICAgICAgICAgY3VyVHJhbnNmb3JtID0gY3VyVHJhbnNmb3JtLnNwbGl0KCcsICcpLm1hcChhID0+IGEucmVwbGFjZSgnLCcsICcuJykpLmpvaW4oJywgJyk7XG4gICAgICAgIH0gLy8gU29tZSBvbGQgdmVyc2lvbnMgb2YgV2Via2l0IGNob2tlIHdoZW4gJ25vbmUnIGlzIHBhc3NlZDsgcGFzc1xuICAgICAgICAvLyBlbXB0eSBzdHJpbmcgaW5zdGVhZCBpbiB0aGlzIGNhc2VcblxuXG4gICAgICAgIHRyYW5zZm9ybU1hdHJpeCA9IG5ldyB3aW5kb3cuV2ViS2l0Q1NTTWF0cml4KGN1clRyYW5zZm9ybSA9PT0gJ25vbmUnID8gJycgOiBjdXJUcmFuc2Zvcm0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJhbnNmb3JtTWF0cml4ID0gY3VyU3R5bGUuTW96VHJhbnNmb3JtIHx8IGN1clN0eWxlLk9UcmFuc2Zvcm0gfHwgY3VyU3R5bGUuTXNUcmFuc2Zvcm0gfHwgY3VyU3R5bGUubXNUcmFuc2Zvcm0gfHwgY3VyU3R5bGUudHJhbnNmb3JtIHx8IGN1clN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ3RyYW5zZm9ybScpLnJlcGxhY2UoJ3RyYW5zbGF0ZSgnLCAnbWF0cml4KDEsIDAsIDAsIDEsJyk7XG4gICAgICAgIG1hdHJpeCA9IHRyYW5zZm9ybU1hdHJpeC50b1N0cmluZygpLnNwbGl0KCcsJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChheGlzID09PSAneCcpIHtcbiAgICAgICAgLy8gTGF0ZXN0IENocm9tZSBhbmQgd2Via2l0cyBGaXhcbiAgICAgICAgaWYgKHdpbmRvdy5XZWJLaXRDU1NNYXRyaXgpIGN1clRyYW5zZm9ybSA9IHRyYW5zZm9ybU1hdHJpeC5tNDE7IC8vIENyYXp5IElFMTAgTWF0cml4XG4gICAgICAgIGVsc2UgaWYgKG1hdHJpeC5sZW5ndGggPT09IDE2KSBjdXJUcmFuc2Zvcm0gPSBwYXJzZUZsb2F0KG1hdHJpeFsxMl0pOyAvLyBOb3JtYWwgQnJvd3NlcnNcbiAgICAgICAgZWxzZSBjdXJUcmFuc2Zvcm0gPSBwYXJzZUZsb2F0KG1hdHJpeFs0XSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChheGlzID09PSAneScpIHtcbiAgICAgICAgLy8gTGF0ZXN0IENocm9tZSBhbmQgd2Via2l0cyBGaXhcbiAgICAgICAgaWYgKHdpbmRvdy5XZWJLaXRDU1NNYXRyaXgpIGN1clRyYW5zZm9ybSA9IHRyYW5zZm9ybU1hdHJpeC5tNDI7IC8vIENyYXp5IElFMTAgTWF0cml4XG4gICAgICAgIGVsc2UgaWYgKG1hdHJpeC5sZW5ndGggPT09IDE2KSBjdXJUcmFuc2Zvcm0gPSBwYXJzZUZsb2F0KG1hdHJpeFsxM10pOyAvLyBOb3JtYWwgQnJvd3NlcnNcbiAgICAgICAgZWxzZSBjdXJUcmFuc2Zvcm0gPSBwYXJzZUZsb2F0KG1hdHJpeFs1XSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjdXJUcmFuc2Zvcm0gfHwgMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc09iamVjdChvKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIG8gPT09ICdvYmplY3QnICYmIG8gIT09IG51bGwgJiYgby5jb25zdHJ1Y3RvciAmJiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobykuc2xpY2UoOCwgLTEpID09PSAnT2JqZWN0JztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc05vZGUobm9kZSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHdpbmRvdy5IVE1MRWxlbWVudCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuIG5vZGUgaW5zdGFuY2VvZiBIVE1MRWxlbWVudDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5vZGUgJiYgKG5vZGUubm9kZVR5cGUgPT09IDEgfHwgbm9kZS5ub2RlVHlwZSA9PT0gMTEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4dGVuZCgpIHtcbiAgICAgIGNvbnN0IHRvID0gT2JqZWN0KGFyZ3VtZW50cy5sZW5ndGggPD0gMCA/IHVuZGVmaW5lZCA6IGFyZ3VtZW50c1swXSk7XG4gICAgICBjb25zdCBub0V4dGVuZCA9IFsnX19wcm90b19fJywgJ2NvbnN0cnVjdG9yJywgJ3Byb3RvdHlwZSddO1xuXG4gICAgICBmb3IgKGxldCBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBjb25zdCBuZXh0U291cmNlID0gaSA8IDAgfHwgYXJndW1lbnRzLmxlbmd0aCA8PSBpID8gdW5kZWZpbmVkIDogYXJndW1lbnRzW2ldO1xuXG4gICAgICAgIGlmIChuZXh0U291cmNlICE9PSB1bmRlZmluZWQgJiYgbmV4dFNvdXJjZSAhPT0gbnVsbCAmJiAhaXNOb2RlKG5leHRTb3VyY2UpKSB7XG4gICAgICAgICAgY29uc3Qga2V5c0FycmF5ID0gT2JqZWN0LmtleXMoT2JqZWN0KG5leHRTb3VyY2UpKS5maWx0ZXIoa2V5ID0+IG5vRXh0ZW5kLmluZGV4T2Yoa2V5KSA8IDApO1xuXG4gICAgICAgICAgZm9yIChsZXQgbmV4dEluZGV4ID0gMCwgbGVuID0ga2V5c0FycmF5Lmxlbmd0aDsgbmV4dEluZGV4IDwgbGVuOyBuZXh0SW5kZXggKz0gMSkge1xuICAgICAgICAgICAgY29uc3QgbmV4dEtleSA9IGtleXNBcnJheVtuZXh0SW5kZXhdO1xuICAgICAgICAgICAgY29uc3QgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobmV4dFNvdXJjZSwgbmV4dEtleSk7XG5cbiAgICAgICAgICAgIGlmIChkZXNjICE9PSB1bmRlZmluZWQgJiYgZGVzYy5lbnVtZXJhYmxlKSB7XG4gICAgICAgICAgICAgIGlmIChpc09iamVjdCh0b1tuZXh0S2V5XSkgJiYgaXNPYmplY3QobmV4dFNvdXJjZVtuZXh0S2V5XSkpIHtcbiAgICAgICAgICAgICAgICBpZiAobmV4dFNvdXJjZVtuZXh0S2V5XS5fX3N3aXBlcl9fKSB7XG4gICAgICAgICAgICAgICAgICB0b1tuZXh0S2V5XSA9IG5leHRTb3VyY2VbbmV4dEtleV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIGV4dGVuZCh0b1tuZXh0S2V5XSwgbmV4dFNvdXJjZVtuZXh0S2V5XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc09iamVjdCh0b1tuZXh0S2V5XSkgJiYgaXNPYmplY3QobmV4dFNvdXJjZVtuZXh0S2V5XSkpIHtcbiAgICAgICAgICAgICAgICB0b1tuZXh0S2V5XSA9IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKG5leHRTb3VyY2VbbmV4dEtleV0uX19zd2lwZXJfXykge1xuICAgICAgICAgICAgICAgICAgdG9bbmV4dEtleV0gPSBuZXh0U291cmNlW25leHRLZXldO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBleHRlbmQodG9bbmV4dEtleV0sIG5leHRTb3VyY2VbbmV4dEtleV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0b1tuZXh0S2V5XSA9IG5leHRTb3VyY2VbbmV4dEtleV07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRvO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldENTU1Byb3BlcnR5KGVsLCB2YXJOYW1lLCB2YXJWYWx1ZSkge1xuICAgICAgZWwuc3R5bGUuc2V0UHJvcGVydHkodmFyTmFtZSwgdmFyVmFsdWUpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFuaW1hdGVDU1NNb2RlU2Nyb2xsKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgdGFyZ2V0UG9zaXRpb24sXG4gICAgICAgIHNpZGVcbiAgICAgIH0gPSBfcmVmO1xuICAgICAgY29uc3Qgd2luZG93ID0gZ2V0V2luZG93KCk7XG4gICAgICBjb25zdCBzdGFydFBvc2l0aW9uID0gLXN3aXBlci50cmFuc2xhdGU7XG4gICAgICBsZXQgc3RhcnRUaW1lID0gbnVsbDtcbiAgICAgIGxldCB0aW1lO1xuICAgICAgY29uc3QgZHVyYXRpb24gPSBzd2lwZXIucGFyYW1zLnNwZWVkO1xuICAgICAgc3dpcGVyLndyYXBwZXJFbC5zdHlsZS5zY3JvbGxTbmFwVHlwZSA9ICdub25lJztcbiAgICAgIHdpbmRvdy5jYW5jZWxBbmltYXRpb25GcmFtZShzd2lwZXIuY3NzTW9kZUZyYW1lSUQpO1xuICAgICAgY29uc3QgZGlyID0gdGFyZ2V0UG9zaXRpb24gPiBzdGFydFBvc2l0aW9uID8gJ25leHQnIDogJ3ByZXYnO1xuXG4gICAgICBjb25zdCBpc091dE9mQm91bmQgPSAoY3VycmVudCwgdGFyZ2V0KSA9PiB7XG4gICAgICAgIHJldHVybiBkaXIgPT09ICduZXh0JyAmJiBjdXJyZW50ID49IHRhcmdldCB8fCBkaXIgPT09ICdwcmV2JyAmJiBjdXJyZW50IDw9IHRhcmdldDtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGFuaW1hdGUgPSAoKSA9PiB7XG4gICAgICAgIHRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgICAgICBpZiAoc3RhcnRUaW1lID09PSBudWxsKSB7XG4gICAgICAgICAgc3RhcnRUaW1lID0gdGltZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHByb2dyZXNzID0gTWF0aC5tYXgoTWF0aC5taW4oKHRpbWUgLSBzdGFydFRpbWUpIC8gZHVyYXRpb24sIDEpLCAwKTtcbiAgICAgICAgY29uc3QgZWFzZVByb2dyZXNzID0gMC41IC0gTWF0aC5jb3MocHJvZ3Jlc3MgKiBNYXRoLlBJKSAvIDI7XG4gICAgICAgIGxldCBjdXJyZW50UG9zaXRpb24gPSBzdGFydFBvc2l0aW9uICsgZWFzZVByb2dyZXNzICogKHRhcmdldFBvc2l0aW9uIC0gc3RhcnRQb3NpdGlvbik7XG5cbiAgICAgICAgaWYgKGlzT3V0T2ZCb3VuZChjdXJyZW50UG9zaXRpb24sIHRhcmdldFBvc2l0aW9uKSkge1xuICAgICAgICAgIGN1cnJlbnRQb3NpdGlvbiA9IHRhcmdldFBvc2l0aW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpcGVyLndyYXBwZXJFbC5zY3JvbGxUbyh7XG4gICAgICAgICAgW3NpZGVdOiBjdXJyZW50UG9zaXRpb25cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKGlzT3V0T2ZCb3VuZChjdXJyZW50UG9zaXRpb24sIHRhcmdldFBvc2l0aW9uKSkge1xuICAgICAgICAgIHN3aXBlci53cmFwcGVyRWwuc3R5bGUub3ZlcmZsb3cgPSAnaGlkZGVuJztcbiAgICAgICAgICBzd2lwZXIud3JhcHBlckVsLnN0eWxlLnNjcm9sbFNuYXBUeXBlID0gJyc7XG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBzd2lwZXIud3JhcHBlckVsLnN0eWxlLm92ZXJmbG93ID0gJyc7XG4gICAgICAgICAgICBzd2lwZXIud3JhcHBlckVsLnNjcm9sbFRvKHtcbiAgICAgICAgICAgICAgW3NpZGVdOiBjdXJyZW50UG9zaXRpb25cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHdpbmRvdy5jYW5jZWxBbmltYXRpb25GcmFtZShzd2lwZXIuY3NzTW9kZUZyYW1lSUQpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci5jc3NNb2RlRnJhbWVJRCA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoYW5pbWF0ZSk7XG4gICAgICB9O1xuXG4gICAgICBhbmltYXRlKCk7XG4gICAgfVxuXG4gICAgbGV0IHN1cHBvcnQ7XG5cbiAgICBmdW5jdGlvbiBjYWxjU3VwcG9ydCgpIHtcbiAgICAgIGNvbnN0IHdpbmRvdyA9IGdldFdpbmRvdygpO1xuICAgICAgY29uc3QgZG9jdW1lbnQgPSBnZXREb2N1bWVudCgpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc21vb3RoU2Nyb2xsOiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgJiYgJ3Njcm9sbEJlaGF2aW9yJyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUsXG4gICAgICAgIHRvdWNoOiAhISgnb250b3VjaHN0YXJ0JyBpbiB3aW5kb3cgfHwgd2luZG93LkRvY3VtZW50VG91Y2ggJiYgZG9jdW1lbnQgaW5zdGFuY2VvZiB3aW5kb3cuRG9jdW1lbnRUb3VjaCksXG4gICAgICAgIHBhc3NpdmVMaXN0ZW5lcjogZnVuY3Rpb24gY2hlY2tQYXNzaXZlTGlzdGVuZXIoKSB7XG4gICAgICAgICAgbGV0IHN1cHBvcnRzUGFzc2l2ZSA9IGZhbHNlO1xuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IG9wdHMgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sICdwYXNzaXZlJywge1xuICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICAgICAgICAgICAgZ2V0KCkge1xuICAgICAgICAgICAgICAgIHN1cHBvcnRzUGFzc2l2ZSA9IHRydWU7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigndGVzdFBhc3NpdmVMaXN0ZW5lcicsIG51bGwsIG9wdHMpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHsvLyBObyBzdXBwb3J0XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIHN1cHBvcnRzUGFzc2l2ZTtcbiAgICAgICAgfSgpLFxuICAgICAgICBnZXN0dXJlczogZnVuY3Rpb24gY2hlY2tHZXN0dXJlcygpIHtcbiAgICAgICAgICByZXR1cm4gJ29uZ2VzdHVyZXN0YXJ0JyBpbiB3aW5kb3c7XG4gICAgICAgIH0oKVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRTdXBwb3J0KCkge1xuICAgICAgaWYgKCFzdXBwb3J0KSB7XG4gICAgICAgIHN1cHBvcnQgPSBjYWxjU3VwcG9ydCgpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc3VwcG9ydDtcbiAgICB9XG5cbiAgICBsZXQgZGV2aWNlQ2FjaGVkO1xuXG4gICAgZnVuY3Rpb24gY2FsY0RldmljZShfdGVtcCkge1xuICAgICAgbGV0IHtcbiAgICAgICAgdXNlckFnZW50XG4gICAgICB9ID0gX3RlbXAgPT09IHZvaWQgMCA/IHt9IDogX3RlbXA7XG4gICAgICBjb25zdCBzdXBwb3J0ID0gZ2V0U3VwcG9ydCgpO1xuICAgICAgY29uc3Qgd2luZG93ID0gZ2V0V2luZG93KCk7XG4gICAgICBjb25zdCBwbGF0Zm9ybSA9IHdpbmRvdy5uYXZpZ2F0b3IucGxhdGZvcm07XG4gICAgICBjb25zdCB1YSA9IHVzZXJBZ2VudCB8fCB3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudDtcbiAgICAgIGNvbnN0IGRldmljZSA9IHtcbiAgICAgICAgaW9zOiBmYWxzZSxcbiAgICAgICAgYW5kcm9pZDogZmFsc2VcbiAgICAgIH07XG4gICAgICBjb25zdCBzY3JlZW5XaWR0aCA9IHdpbmRvdy5zY3JlZW4ud2lkdGg7XG4gICAgICBjb25zdCBzY3JlZW5IZWlnaHQgPSB3aW5kb3cuc2NyZWVuLmhlaWdodDtcbiAgICAgIGNvbnN0IGFuZHJvaWQgPSB1YS5tYXRjaCgvKEFuZHJvaWQpOz9bXFxzXFwvXSsoW1xcZC5dKyk/Lyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblxuICAgICAgbGV0IGlwYWQgPSB1YS5tYXRjaCgvKGlQYWQpLipPU1xccyhbXFxkX10rKS8pO1xuICAgICAgY29uc3QgaXBvZCA9IHVhLm1hdGNoKC8oaVBvZCkoLipPU1xccyhbXFxkX10rKSk/Lyk7XG4gICAgICBjb25zdCBpcGhvbmUgPSAhaXBhZCAmJiB1YS5tYXRjaCgvKGlQaG9uZVxcc09TfGlPUylcXHMoW1xcZF9dKykvKTtcbiAgICAgIGNvbnN0IHdpbmRvd3MgPSBwbGF0Zm9ybSA9PT0gJ1dpbjMyJztcbiAgICAgIGxldCBtYWNvcyA9IHBsYXRmb3JtID09PSAnTWFjSW50ZWwnOyAvLyBpUGFkT3MgMTMgZml4XG5cbiAgICAgIGNvbnN0IGlQYWRTY3JlZW5zID0gWycxMDI0eDEzNjYnLCAnMTM2NngxMDI0JywgJzgzNHgxMTk0JywgJzExOTR4ODM0JywgJzgzNHgxMTEyJywgJzExMTJ4ODM0JywgJzc2OHgxMDI0JywgJzEwMjR4NzY4JywgJzgyMHgxMTgwJywgJzExODB4ODIwJywgJzgxMHgxMDgwJywgJzEwODB4ODEwJ107XG5cbiAgICAgIGlmICghaXBhZCAmJiBtYWNvcyAmJiBzdXBwb3J0LnRvdWNoICYmIGlQYWRTY3JlZW5zLmluZGV4T2YoYCR7c2NyZWVuV2lkdGh9eCR7c2NyZWVuSGVpZ2h0fWApID49IDApIHtcbiAgICAgICAgaXBhZCA9IHVhLm1hdGNoKC8oVmVyc2lvbilcXC8oW1xcZC5dKykvKTtcbiAgICAgICAgaWYgKCFpcGFkKSBpcGFkID0gWzAsIDEsICcxM18wXzAnXTtcbiAgICAgICAgbWFjb3MgPSBmYWxzZTtcbiAgICAgIH0gLy8gQW5kcm9pZFxuXG5cbiAgICAgIGlmIChhbmRyb2lkICYmICF3aW5kb3dzKSB7XG4gICAgICAgIGRldmljZS5vcyA9ICdhbmRyb2lkJztcbiAgICAgICAgZGV2aWNlLmFuZHJvaWQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXBhZCB8fCBpcGhvbmUgfHwgaXBvZCkge1xuICAgICAgICBkZXZpY2Uub3MgPSAnaW9zJztcbiAgICAgICAgZGV2aWNlLmlvcyA9IHRydWU7XG4gICAgICB9IC8vIEV4cG9ydCBvYmplY3RcblxuXG4gICAgICByZXR1cm4gZGV2aWNlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldERldmljZShvdmVycmlkZXMpIHtcbiAgICAgIGlmIChvdmVycmlkZXMgPT09IHZvaWQgMCkge1xuICAgICAgICBvdmVycmlkZXMgPSB7fTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFkZXZpY2VDYWNoZWQpIHtcbiAgICAgICAgZGV2aWNlQ2FjaGVkID0gY2FsY0RldmljZShvdmVycmlkZXMpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZGV2aWNlQ2FjaGVkO1xuICAgIH1cblxuICAgIGxldCBicm93c2VyO1xuXG4gICAgZnVuY3Rpb24gY2FsY0Jyb3dzZXIoKSB7XG4gICAgICBjb25zdCB3aW5kb3cgPSBnZXRXaW5kb3coKTtcblxuICAgICAgZnVuY3Rpb24gaXNTYWZhcmkoKSB7XG4gICAgICAgIGNvbnN0IHVhID0gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgcmV0dXJuIHVhLmluZGV4T2YoJ3NhZmFyaScpID49IDAgJiYgdWEuaW5kZXhPZignY2hyb21lJykgPCAwICYmIHVhLmluZGV4T2YoJ2FuZHJvaWQnKSA8IDA7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGlzU2FmYXJpOiBpc1NhZmFyaSgpLFxuICAgICAgICBpc1dlYlZpZXc6IC8oaVBob25lfGlQb2R8aVBhZCkuKkFwcGxlV2ViS2l0KD8hLipTYWZhcmkpL2kudGVzdCh3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudClcbiAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0QnJvd3NlcigpIHtcbiAgICAgIGlmICghYnJvd3Nlcikge1xuICAgICAgICBicm93c2VyID0gY2FsY0Jyb3dzZXIoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGJyb3dzZXI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gUmVzaXplKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgb24sXG4gICAgICAgIGVtaXRcbiAgICAgIH0gPSBfcmVmO1xuICAgICAgY29uc3Qgd2luZG93ID0gZ2V0V2luZG93KCk7XG4gICAgICBsZXQgb2JzZXJ2ZXIgPSBudWxsO1xuICAgICAgbGV0IGFuaW1hdGlvbkZyYW1lID0gbnVsbDtcblxuICAgICAgY29uc3QgcmVzaXplSGFuZGxlciA9ICgpID0+IHtcbiAgICAgICAgaWYgKCFzd2lwZXIgfHwgc3dpcGVyLmRlc3Ryb3llZCB8fCAhc3dpcGVyLmluaXRpYWxpemVkKSByZXR1cm47XG4gICAgICAgIGVtaXQoJ2JlZm9yZVJlc2l6ZScpO1xuICAgICAgICBlbWl0KCdyZXNpemUnKTtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGNyZWF0ZU9ic2VydmVyID0gKCkgPT4ge1xuICAgICAgICBpZiAoIXN3aXBlciB8fCBzd2lwZXIuZGVzdHJveWVkIHx8ICFzd2lwZXIuaW5pdGlhbGl6ZWQpIHJldHVybjtcbiAgICAgICAgb2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoZW50cmllcyA9PiB7XG4gICAgICAgICAgYW5pbWF0aW9uRnJhbWUgPSB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgICAgIGhlaWdodFxuICAgICAgICAgICAgfSA9IHN3aXBlcjtcbiAgICAgICAgICAgIGxldCBuZXdXaWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgbGV0IG5ld0hlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgIGVudHJpZXMuZm9yRWFjaChfcmVmMiA9PiB7XG4gICAgICAgICAgICAgIGxldCB7XG4gICAgICAgICAgICAgICAgY29udGVudEJveFNpemUsXG4gICAgICAgICAgICAgICAgY29udGVudFJlY3QsXG4gICAgICAgICAgICAgICAgdGFyZ2V0XG4gICAgICAgICAgICAgIH0gPSBfcmVmMjtcbiAgICAgICAgICAgICAgaWYgKHRhcmdldCAmJiB0YXJnZXQgIT09IHN3aXBlci5lbCkgcmV0dXJuO1xuICAgICAgICAgICAgICBuZXdXaWR0aCA9IGNvbnRlbnRSZWN0ID8gY29udGVudFJlY3Qud2lkdGggOiAoY29udGVudEJveFNpemVbMF0gfHwgY29udGVudEJveFNpemUpLmlubGluZVNpemU7XG4gICAgICAgICAgICAgIG5ld0hlaWdodCA9IGNvbnRlbnRSZWN0ID8gY29udGVudFJlY3QuaGVpZ2h0IDogKGNvbnRlbnRCb3hTaXplWzBdIHx8IGNvbnRlbnRCb3hTaXplKS5ibG9ja1NpemU7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKG5ld1dpZHRoICE9PSB3aWR0aCB8fCBuZXdIZWlnaHQgIT09IGhlaWdodCkge1xuICAgICAgICAgICAgICByZXNpemVIYW5kbGVyKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBvYnNlcnZlci5vYnNlcnZlKHN3aXBlci5lbCk7XG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZW1vdmVPYnNlcnZlciA9ICgpID0+IHtcbiAgICAgICAgaWYgKGFuaW1hdGlvbkZyYW1lKSB7XG4gICAgICAgICAgd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lKGFuaW1hdGlvbkZyYW1lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvYnNlcnZlciAmJiBvYnNlcnZlci51bm9ic2VydmUgJiYgc3dpcGVyLmVsKSB7XG4gICAgICAgICAgb2JzZXJ2ZXIudW5vYnNlcnZlKHN3aXBlci5lbCk7XG4gICAgICAgICAgb2JzZXJ2ZXIgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBvcmllbnRhdGlvbkNoYW5nZUhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgIGlmICghc3dpcGVyIHx8IHN3aXBlci5kZXN0cm95ZWQgfHwgIXN3aXBlci5pbml0aWFsaXplZCkgcmV0dXJuO1xuICAgICAgICBlbWl0KCdvcmllbnRhdGlvbmNoYW5nZScpO1xuICAgICAgfTtcblxuICAgICAgb24oJ2luaXQnLCAoKSA9PiB7XG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLnJlc2l6ZU9ic2VydmVyICYmIHR5cGVvZiB3aW5kb3cuUmVzaXplT2JzZXJ2ZXIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgY3JlYXRlT2JzZXJ2ZXIoKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgcmVzaXplSGFuZGxlcik7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdvcmllbnRhdGlvbmNoYW5nZScsIG9yaWVudGF0aW9uQ2hhbmdlSGFuZGxlcik7XG4gICAgICB9KTtcbiAgICAgIG9uKCdkZXN0cm95JywgKCkgPT4ge1xuICAgICAgICByZW1vdmVPYnNlcnZlcigpO1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgcmVzaXplSGFuZGxlcik7XG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdvcmllbnRhdGlvbmNoYW5nZScsIG9yaWVudGF0aW9uQ2hhbmdlSGFuZGxlcik7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBPYnNlcnZlcihfcmVmKSB7XG4gICAgICBsZXQge1xuICAgICAgICBzd2lwZXIsXG4gICAgICAgIGV4dGVuZFBhcmFtcyxcbiAgICAgICAgb24sXG4gICAgICAgIGVtaXRcbiAgICAgIH0gPSBfcmVmO1xuICAgICAgY29uc3Qgb2JzZXJ2ZXJzID0gW107XG4gICAgICBjb25zdCB3aW5kb3cgPSBnZXRXaW5kb3coKTtcblxuICAgICAgY29uc3QgYXR0YWNoID0gZnVuY3Rpb24gKHRhcmdldCwgb3B0aW9ucykge1xuICAgICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7XG4gICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgT2JzZXJ2ZXJGdW5jID0gd2luZG93Lk11dGF0aW9uT2JzZXJ2ZXIgfHwgd2luZG93LldlYmtpdE11dGF0aW9uT2JzZXJ2ZXI7XG4gICAgICAgIGNvbnN0IG9ic2VydmVyID0gbmV3IE9ic2VydmVyRnVuYyhtdXRhdGlvbnMgPT4ge1xuICAgICAgICAgIC8vIFRoZSBvYnNlcnZlclVwZGF0ZSBldmVudCBzaG91bGQgb25seSBiZSB0cmlnZ2VyZWRcbiAgICAgICAgICAvLyBvbmNlIGRlc3BpdGUgdGhlIG51bWJlciBvZiBtdXRhdGlvbnMuICBBZGRpdGlvbmFsXG4gICAgICAgICAgLy8gdHJpZ2dlcnMgYXJlIHJlZHVuZGFudCBhbmQgYXJlIHZlcnkgY29zdGx5XG4gICAgICAgICAgaWYgKG11dGF0aW9ucy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIGVtaXQoJ29ic2VydmVyVXBkYXRlJywgbXV0YXRpb25zWzBdKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBvYnNlcnZlclVwZGF0ZSA9IGZ1bmN0aW9uIG9ic2VydmVyVXBkYXRlKCkge1xuICAgICAgICAgICAgZW1pdCgnb2JzZXJ2ZXJVcGRhdGUnLCBtdXRhdGlvbnNbMF0pO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICBpZiAod2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSkge1xuICAgICAgICAgICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZShvYnNlcnZlclVwZGF0ZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KG9ic2VydmVyVXBkYXRlLCAwKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBvYnNlcnZlci5vYnNlcnZlKHRhcmdldCwge1xuICAgICAgICAgIGF0dHJpYnV0ZXM6IHR5cGVvZiBvcHRpb25zLmF0dHJpYnV0ZXMgPT09ICd1bmRlZmluZWQnID8gdHJ1ZSA6IG9wdGlvbnMuYXR0cmlidXRlcyxcbiAgICAgICAgICBjaGlsZExpc3Q6IHR5cGVvZiBvcHRpb25zLmNoaWxkTGlzdCA9PT0gJ3VuZGVmaW5lZCcgPyB0cnVlIDogb3B0aW9ucy5jaGlsZExpc3QsXG4gICAgICAgICAgY2hhcmFjdGVyRGF0YTogdHlwZW9mIG9wdGlvbnMuY2hhcmFjdGVyRGF0YSA9PT0gJ3VuZGVmaW5lZCcgPyB0cnVlIDogb3B0aW9ucy5jaGFyYWN0ZXJEYXRhXG4gICAgICAgIH0pO1xuICAgICAgICBvYnNlcnZlcnMucHVzaChvYnNlcnZlcik7XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBpbml0ID0gKCkgPT4ge1xuICAgICAgICBpZiAoIXN3aXBlci5wYXJhbXMub2JzZXJ2ZXIpIHJldHVybjtcblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5vYnNlcnZlUGFyZW50cykge1xuICAgICAgICAgIGNvbnN0IGNvbnRhaW5lclBhcmVudHMgPSBzd2lwZXIuJGVsLnBhcmVudHMoKTtcblxuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29udGFpbmVyUGFyZW50cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgYXR0YWNoKGNvbnRhaW5lclBhcmVudHNbaV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSAvLyBPYnNlcnZlIGNvbnRhaW5lclxuXG5cbiAgICAgICAgYXR0YWNoKHN3aXBlci4kZWxbMF0sIHtcbiAgICAgICAgICBjaGlsZExpc3Q6IHN3aXBlci5wYXJhbXMub2JzZXJ2ZVNsaWRlQ2hpbGRyZW5cbiAgICAgICAgfSk7IC8vIE9ic2VydmUgd3JhcHBlclxuXG4gICAgICAgIGF0dGFjaChzd2lwZXIuJHdyYXBwZXJFbFswXSwge1xuICAgICAgICAgIGF0dHJpYnV0ZXM6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgY29uc3QgZGVzdHJveSA9ICgpID0+IHtcbiAgICAgICAgb2JzZXJ2ZXJzLmZvckVhY2gob2JzZXJ2ZXIgPT4ge1xuICAgICAgICAgIG9ic2VydmVyLmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIG9ic2VydmVycy5zcGxpY2UoMCwgb2JzZXJ2ZXJzLmxlbmd0aCk7XG4gICAgICB9O1xuXG4gICAgICBleHRlbmRQYXJhbXMoe1xuICAgICAgICBvYnNlcnZlcjogZmFsc2UsXG4gICAgICAgIG9ic2VydmVQYXJlbnRzOiBmYWxzZSxcbiAgICAgICAgb2JzZXJ2ZVNsaWRlQ2hpbGRyZW46IGZhbHNlXG4gICAgICB9KTtcbiAgICAgIG9uKCdpbml0JywgaW5pdCk7XG4gICAgICBvbignZGVzdHJveScsIGRlc3Ryb3kpO1xuICAgIH1cblxuICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLXVuZGVyc2NvcmUtZGFuZ2xlICovXG4gICAgdmFyIGV2ZW50c0VtaXR0ZXIgPSB7XG4gICAgICBvbihldmVudHMsIGhhbmRsZXIsIHByaW9yaXR5KSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAodHlwZW9mIGhhbmRsZXIgIT09ICdmdW5jdGlvbicpIHJldHVybiBzZWxmO1xuICAgICAgICBjb25zdCBtZXRob2QgPSBwcmlvcml0eSA/ICd1bnNoaWZ0JyA6ICdwdXNoJztcbiAgICAgICAgZXZlbnRzLnNwbGl0KCcgJykuZm9yRWFjaChldmVudCA9PiB7XG4gICAgICAgICAgaWYgKCFzZWxmLmV2ZW50c0xpc3RlbmVyc1tldmVudF0pIHNlbGYuZXZlbnRzTGlzdGVuZXJzW2V2ZW50XSA9IFtdO1xuICAgICAgICAgIHNlbGYuZXZlbnRzTGlzdGVuZXJzW2V2ZW50XVttZXRob2RdKGhhbmRsZXIpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICB9LFxuXG4gICAgICBvbmNlKGV2ZW50cywgaGFuZGxlciwgcHJpb3JpdHkpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGlmICh0eXBlb2YgaGFuZGxlciAhPT0gJ2Z1bmN0aW9uJykgcmV0dXJuIHNlbGY7XG5cbiAgICAgICAgZnVuY3Rpb24gb25jZUhhbmRsZXIoKSB7XG4gICAgICAgICAgc2VsZi5vZmYoZXZlbnRzLCBvbmNlSGFuZGxlcik7XG5cbiAgICAgICAgICBpZiAob25jZUhhbmRsZXIuX19lbWl0dGVyUHJveHkpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBvbmNlSGFuZGxlci5fX2VtaXR0ZXJQcm94eTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICAgICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaGFuZGxlci5hcHBseShzZWxmLCBhcmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG9uY2VIYW5kbGVyLl9fZW1pdHRlclByb3h5ID0gaGFuZGxlcjtcbiAgICAgICAgcmV0dXJuIHNlbGYub24oZXZlbnRzLCBvbmNlSGFuZGxlciwgcHJpb3JpdHkpO1xuICAgICAgfSxcblxuICAgICAgb25BbnkoaGFuZGxlciwgcHJpb3JpdHkpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGlmICh0eXBlb2YgaGFuZGxlciAhPT0gJ2Z1bmN0aW9uJykgcmV0dXJuIHNlbGY7XG4gICAgICAgIGNvbnN0IG1ldGhvZCA9IHByaW9yaXR5ID8gJ3Vuc2hpZnQnIDogJ3B1c2gnO1xuXG4gICAgICAgIGlmIChzZWxmLmV2ZW50c0FueUxpc3RlbmVycy5pbmRleE9mKGhhbmRsZXIpIDwgMCkge1xuICAgICAgICAgIHNlbGYuZXZlbnRzQW55TGlzdGVuZXJzW21ldGhvZF0oaGFuZGxlcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgIH0sXG5cbiAgICAgIG9mZkFueShoYW5kbGVyKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAoIXNlbGYuZXZlbnRzQW55TGlzdGVuZXJzKSByZXR1cm4gc2VsZjtcbiAgICAgICAgY29uc3QgaW5kZXggPSBzZWxmLmV2ZW50c0FueUxpc3RlbmVycy5pbmRleE9mKGhhbmRsZXIpO1xuXG4gICAgICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICAgICAgc2VsZi5ldmVudHNBbnlMaXN0ZW5lcnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgfSxcblxuICAgICAgb2ZmKGV2ZW50cywgaGFuZGxlcikge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKCFzZWxmLmV2ZW50c0xpc3RlbmVycykgcmV0dXJuIHNlbGY7XG4gICAgICAgIGV2ZW50cy5zcGxpdCgnICcpLmZvckVhY2goZXZlbnQgPT4ge1xuICAgICAgICAgIGlmICh0eXBlb2YgaGFuZGxlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHNlbGYuZXZlbnRzTGlzdGVuZXJzW2V2ZW50XSA9IFtdO1xuICAgICAgICAgIH0gZWxzZSBpZiAoc2VsZi5ldmVudHNMaXN0ZW5lcnNbZXZlbnRdKSB7XG4gICAgICAgICAgICBzZWxmLmV2ZW50c0xpc3RlbmVyc1tldmVudF0uZm9yRWFjaCgoZXZlbnRIYW5kbGVyLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoZXZlbnRIYW5kbGVyID09PSBoYW5kbGVyIHx8IGV2ZW50SGFuZGxlci5fX2VtaXR0ZXJQcm94eSAmJiBldmVudEhhbmRsZXIuX19lbWl0dGVyUHJveHkgPT09IGhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgICBzZWxmLmV2ZW50c0xpc3RlbmVyc1tldmVudF0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICB9LFxuXG4gICAgICBlbWl0KCkge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKCFzZWxmLmV2ZW50c0xpc3RlbmVycykgcmV0dXJuIHNlbGY7XG4gICAgICAgIGxldCBldmVudHM7XG4gICAgICAgIGxldCBkYXRhO1xuICAgICAgICBsZXQgY29udGV4dDtcblxuICAgICAgICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjIpLCBfa2V5MiA9IDA7IF9rZXkyIDwgX2xlbjI7IF9rZXkyKyspIHtcbiAgICAgICAgICBhcmdzW19rZXkyXSA9IGFyZ3VtZW50c1tfa2V5Ml07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGFyZ3NbMF0gPT09ICdzdHJpbmcnIHx8IEFycmF5LmlzQXJyYXkoYXJnc1swXSkpIHtcbiAgICAgICAgICBldmVudHMgPSBhcmdzWzBdO1xuICAgICAgICAgIGRhdGEgPSBhcmdzLnNsaWNlKDEsIGFyZ3MubGVuZ3RoKTtcbiAgICAgICAgICBjb250ZXh0ID0gc2VsZjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBldmVudHMgPSBhcmdzWzBdLmV2ZW50cztcbiAgICAgICAgICBkYXRhID0gYXJnc1swXS5kYXRhO1xuICAgICAgICAgIGNvbnRleHQgPSBhcmdzWzBdLmNvbnRleHQgfHwgc2VsZjtcbiAgICAgICAgfVxuXG4gICAgICAgIGRhdGEudW5zaGlmdChjb250ZXh0KTtcbiAgICAgICAgY29uc3QgZXZlbnRzQXJyYXkgPSBBcnJheS5pc0FycmF5KGV2ZW50cykgPyBldmVudHMgOiBldmVudHMuc3BsaXQoJyAnKTtcbiAgICAgICAgZXZlbnRzQXJyYXkuZm9yRWFjaChldmVudCA9PiB7XG4gICAgICAgICAgaWYgKHNlbGYuZXZlbnRzQW55TGlzdGVuZXJzICYmIHNlbGYuZXZlbnRzQW55TGlzdGVuZXJzLmxlbmd0aCkge1xuICAgICAgICAgICAgc2VsZi5ldmVudHNBbnlMaXN0ZW5lcnMuZm9yRWFjaChldmVudEhhbmRsZXIgPT4ge1xuICAgICAgICAgICAgICBldmVudEhhbmRsZXIuYXBwbHkoY29udGV4dCwgW2V2ZW50LCAuLi5kYXRhXSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoc2VsZi5ldmVudHNMaXN0ZW5lcnMgJiYgc2VsZi5ldmVudHNMaXN0ZW5lcnNbZXZlbnRdKSB7XG4gICAgICAgICAgICBzZWxmLmV2ZW50c0xpc3RlbmVyc1tldmVudF0uZm9yRWFjaChldmVudEhhbmRsZXIgPT4ge1xuICAgICAgICAgICAgICBldmVudEhhbmRsZXIuYXBwbHkoY29udGV4dCwgZGF0YSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgIH1cblxuICAgIH07XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVTaXplKCkge1xuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIGxldCB3aWR0aDtcbiAgICAgIGxldCBoZWlnaHQ7XG4gICAgICBjb25zdCAkZWwgPSBzd2lwZXIuJGVsO1xuXG4gICAgICBpZiAodHlwZW9mIHN3aXBlci5wYXJhbXMud2lkdGggIT09ICd1bmRlZmluZWQnICYmIHN3aXBlci5wYXJhbXMud2lkdGggIT09IG51bGwpIHtcbiAgICAgICAgd2lkdGggPSBzd2lwZXIucGFyYW1zLndpZHRoO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2lkdGggPSAkZWxbMF0uY2xpZW50V2lkdGg7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2Ygc3dpcGVyLnBhcmFtcy5oZWlnaHQgIT09ICd1bmRlZmluZWQnICYmIHN3aXBlci5wYXJhbXMuaGVpZ2h0ICE9PSBudWxsKSB7XG4gICAgICAgIGhlaWdodCA9IHN3aXBlci5wYXJhbXMuaGVpZ2h0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaGVpZ2h0ID0gJGVsWzBdLmNsaWVudEhlaWdodDtcbiAgICAgIH1cblxuICAgICAgaWYgKHdpZHRoID09PSAwICYmIHN3aXBlci5pc0hvcml6b250YWwoKSB8fCBoZWlnaHQgPT09IDAgJiYgc3dpcGVyLmlzVmVydGljYWwoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9IC8vIFN1YnRyYWN0IHBhZGRpbmdzXG5cblxuICAgICAgd2lkdGggPSB3aWR0aCAtIHBhcnNlSW50KCRlbC5jc3MoJ3BhZGRpbmctbGVmdCcpIHx8IDAsIDEwKSAtIHBhcnNlSW50KCRlbC5jc3MoJ3BhZGRpbmctcmlnaHQnKSB8fCAwLCAxMCk7XG4gICAgICBoZWlnaHQgPSBoZWlnaHQgLSBwYXJzZUludCgkZWwuY3NzKCdwYWRkaW5nLXRvcCcpIHx8IDAsIDEwKSAtIHBhcnNlSW50KCRlbC5jc3MoJ3BhZGRpbmctYm90dG9tJykgfHwgMCwgMTApO1xuICAgICAgaWYgKE51bWJlci5pc05hTih3aWR0aCkpIHdpZHRoID0gMDtcbiAgICAgIGlmIChOdW1iZXIuaXNOYU4oaGVpZ2h0KSkgaGVpZ2h0ID0gMDtcbiAgICAgIE9iamVjdC5hc3NpZ24oc3dpcGVyLCB7XG4gICAgICAgIHdpZHRoLFxuICAgICAgICBoZWlnaHQsXG4gICAgICAgIHNpemU6IHN3aXBlci5pc0hvcml6b250YWwoKSA/IHdpZHRoIDogaGVpZ2h0XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVTbGlkZXMoKSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuXG4gICAgICBmdW5jdGlvbiBnZXREaXJlY3Rpb25MYWJlbChwcm9wZXJ0eSkge1xuICAgICAgICBpZiAoc3dpcGVyLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgcmV0dXJuIHByb3BlcnR5O1xuICAgICAgICB9IC8vIHByZXR0aWVyLWlnbm9yZVxuXG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAnd2lkdGgnOiAnaGVpZ2h0JyxcbiAgICAgICAgICAnbWFyZ2luLXRvcCc6ICdtYXJnaW4tbGVmdCcsXG4gICAgICAgICAgJ21hcmdpbi1ib3R0b20gJzogJ21hcmdpbi1yaWdodCcsXG4gICAgICAgICAgJ21hcmdpbi1sZWZ0JzogJ21hcmdpbi10b3AnLFxuICAgICAgICAgICdtYXJnaW4tcmlnaHQnOiAnbWFyZ2luLWJvdHRvbScsXG4gICAgICAgICAgJ3BhZGRpbmctbGVmdCc6ICdwYWRkaW5nLXRvcCcsXG4gICAgICAgICAgJ3BhZGRpbmctcmlnaHQnOiAncGFkZGluZy1ib3R0b20nLFxuICAgICAgICAgICdtYXJnaW5SaWdodCc6ICdtYXJnaW5Cb3R0b20nXG4gICAgICAgIH1bcHJvcGVydHldO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBnZXREaXJlY3Rpb25Qcm9wZXJ0eVZhbHVlKG5vZGUsIGxhYmVsKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUZsb2F0KG5vZGUuZ2V0UHJvcGVydHlWYWx1ZShnZXREaXJlY3Rpb25MYWJlbChsYWJlbCkpIHx8IDApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zO1xuICAgICAgY29uc3Qge1xuICAgICAgICAkd3JhcHBlckVsLFxuICAgICAgICBzaXplOiBzd2lwZXJTaXplLFxuICAgICAgICBydGxUcmFuc2xhdGU6IHJ0bCxcbiAgICAgICAgd3JvbmdSVExcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICBjb25zdCBpc1ZpcnR1YWwgPSBzd2lwZXIudmlydHVhbCAmJiBwYXJhbXMudmlydHVhbC5lbmFibGVkO1xuICAgICAgY29uc3QgcHJldmlvdXNTbGlkZXNMZW5ndGggPSBpc1ZpcnR1YWwgPyBzd2lwZXIudmlydHVhbC5zbGlkZXMubGVuZ3RoIDogc3dpcGVyLnNsaWRlcy5sZW5ndGg7XG4gICAgICBjb25zdCBzbGlkZXMgPSAkd3JhcHBlckVsLmNoaWxkcmVuKGAuJHtzd2lwZXIucGFyYW1zLnNsaWRlQ2xhc3N9YCk7XG4gICAgICBjb25zdCBzbGlkZXNMZW5ndGggPSBpc1ZpcnR1YWwgPyBzd2lwZXIudmlydHVhbC5zbGlkZXMubGVuZ3RoIDogc2xpZGVzLmxlbmd0aDtcbiAgICAgIGxldCBzbmFwR3JpZCA9IFtdO1xuICAgICAgY29uc3Qgc2xpZGVzR3JpZCA9IFtdO1xuICAgICAgY29uc3Qgc2xpZGVzU2l6ZXNHcmlkID0gW107XG4gICAgICBsZXQgb2Zmc2V0QmVmb3JlID0gcGFyYW1zLnNsaWRlc09mZnNldEJlZm9yZTtcblxuICAgICAgaWYgKHR5cGVvZiBvZmZzZXRCZWZvcmUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgb2Zmc2V0QmVmb3JlID0gcGFyYW1zLnNsaWRlc09mZnNldEJlZm9yZS5jYWxsKHN3aXBlcik7XG4gICAgICB9XG5cbiAgICAgIGxldCBvZmZzZXRBZnRlciA9IHBhcmFtcy5zbGlkZXNPZmZzZXRBZnRlcjtcblxuICAgICAgaWYgKHR5cGVvZiBvZmZzZXRBZnRlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBvZmZzZXRBZnRlciA9IHBhcmFtcy5zbGlkZXNPZmZzZXRBZnRlci5jYWxsKHN3aXBlcik7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHByZXZpb3VzU25hcEdyaWRMZW5ndGggPSBzd2lwZXIuc25hcEdyaWQubGVuZ3RoO1xuICAgICAgY29uc3QgcHJldmlvdXNTbGlkZXNHcmlkTGVuZ3RoID0gc3dpcGVyLnNsaWRlc0dyaWQubGVuZ3RoO1xuICAgICAgbGV0IHNwYWNlQmV0d2VlbiA9IHBhcmFtcy5zcGFjZUJldHdlZW47XG4gICAgICBsZXQgc2xpZGVQb3NpdGlvbiA9IC1vZmZzZXRCZWZvcmU7XG4gICAgICBsZXQgcHJldlNsaWRlU2l6ZSA9IDA7XG4gICAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgICBpZiAodHlwZW9mIHN3aXBlclNpemUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBzcGFjZUJldHdlZW4gPT09ICdzdHJpbmcnICYmIHNwYWNlQmV0d2Vlbi5pbmRleE9mKCclJykgPj0gMCkge1xuICAgICAgICBzcGFjZUJldHdlZW4gPSBwYXJzZUZsb2F0KHNwYWNlQmV0d2Vlbi5yZXBsYWNlKCclJywgJycpKSAvIDEwMCAqIHN3aXBlclNpemU7XG4gICAgICB9XG5cbiAgICAgIHN3aXBlci52aXJ0dWFsU2l6ZSA9IC1zcGFjZUJldHdlZW47IC8vIHJlc2V0IG1hcmdpbnNcblxuICAgICAgaWYgKHJ0bCkgc2xpZGVzLmNzcyh7XG4gICAgICAgIG1hcmdpbkxlZnQ6ICcnLFxuICAgICAgICBtYXJnaW5Cb3R0b206ICcnLFxuICAgICAgICBtYXJnaW5Ub3A6ICcnXG4gICAgICB9KTtlbHNlIHNsaWRlcy5jc3Moe1xuICAgICAgICBtYXJnaW5SaWdodDogJycsXG4gICAgICAgIG1hcmdpbkJvdHRvbTogJycsXG4gICAgICAgIG1hcmdpblRvcDogJydcbiAgICAgIH0pOyAvLyByZXNldCBjc3NNb2RlIG9mZnNldHNcblxuICAgICAgaWYgKHBhcmFtcy5jZW50ZXJlZFNsaWRlcyAmJiBwYXJhbXMuY3NzTW9kZSkge1xuICAgICAgICBzZXRDU1NQcm9wZXJ0eShzd2lwZXIud3JhcHBlckVsLCAnLS1zd2lwZXItY2VudGVyZWQtb2Zmc2V0LWJlZm9yZScsICcnKTtcbiAgICAgICAgc2V0Q1NTUHJvcGVydHkoc3dpcGVyLndyYXBwZXJFbCwgJy0tc3dpcGVyLWNlbnRlcmVkLW9mZnNldC1hZnRlcicsICcnKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZ3JpZEVuYWJsZWQgPSBwYXJhbXMuZ3JpZCAmJiBwYXJhbXMuZ3JpZC5yb3dzID4gMSAmJiBzd2lwZXIuZ3JpZDtcblxuICAgICAgaWYgKGdyaWRFbmFibGVkKSB7XG4gICAgICAgIHN3aXBlci5ncmlkLmluaXRTbGlkZXMoc2xpZGVzTGVuZ3RoKTtcbiAgICAgIH0gLy8gQ2FsYyBzbGlkZXNcblxuXG4gICAgICBsZXQgc2xpZGVTaXplO1xuICAgICAgY29uc3Qgc2hvdWxkUmVzZXRTbGlkZVNpemUgPSBwYXJhbXMuc2xpZGVzUGVyVmlldyA9PT0gJ2F1dG8nICYmIHBhcmFtcy5icmVha3BvaW50cyAmJiBPYmplY3Qua2V5cyhwYXJhbXMuYnJlYWtwb2ludHMpLmZpbHRlcihrZXkgPT4ge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHBhcmFtcy5icmVha3BvaW50c1trZXldLnNsaWRlc1BlclZpZXcgIT09ICd1bmRlZmluZWQnO1xuICAgICAgfSkubGVuZ3RoID4gMDtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbGlkZXNMZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBzbGlkZVNpemUgPSAwO1xuICAgICAgICBjb25zdCBzbGlkZSA9IHNsaWRlcy5lcShpKTtcblxuICAgICAgICBpZiAoZ3JpZEVuYWJsZWQpIHtcbiAgICAgICAgICBzd2lwZXIuZ3JpZC51cGRhdGVTbGlkZShpLCBzbGlkZSwgc2xpZGVzTGVuZ3RoLCBnZXREaXJlY3Rpb25MYWJlbCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2xpZGUuY3NzKCdkaXNwbGF5JykgPT09ICdub25lJykgY29udGludWU7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblxuICAgICAgICBpZiAocGFyYW1zLnNsaWRlc1BlclZpZXcgPT09ICdhdXRvJykge1xuICAgICAgICAgIGlmIChzaG91bGRSZXNldFNsaWRlU2l6ZSkge1xuICAgICAgICAgICAgc2xpZGVzW2ldLnN0eWxlW2dldERpcmVjdGlvbkxhYmVsKCd3aWR0aCcpXSA9IGBgO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHNsaWRlU3R5bGVzID0gZ2V0Q29tcHV0ZWRTdHlsZShzbGlkZVswXSk7XG4gICAgICAgICAgY29uc3QgY3VycmVudFRyYW5zZm9ybSA9IHNsaWRlWzBdLnN0eWxlLnRyYW5zZm9ybTtcbiAgICAgICAgICBjb25zdCBjdXJyZW50V2ViS2l0VHJhbnNmb3JtID0gc2xpZGVbMF0uc3R5bGUud2Via2l0VHJhbnNmb3JtO1xuXG4gICAgICAgICAgaWYgKGN1cnJlbnRUcmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIHNsaWRlWzBdLnN0eWxlLnRyYW5zZm9ybSA9ICdub25lJztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoY3VycmVudFdlYktpdFRyYW5zZm9ybSkge1xuICAgICAgICAgICAgc2xpZGVbMF0uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ25vbmUnO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChwYXJhbXMucm91bmRMZW5ndGhzKSB7XG4gICAgICAgICAgICBzbGlkZVNpemUgPSBzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyBzbGlkZS5vdXRlcldpZHRoKHRydWUpIDogc2xpZGUub3V0ZXJIZWlnaHQodHJ1ZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBnZXREaXJlY3Rpb25Qcm9wZXJ0eVZhbHVlKHNsaWRlU3R5bGVzLCAnd2lkdGgnKTtcbiAgICAgICAgICAgIGNvbnN0IHBhZGRpbmdMZWZ0ID0gZ2V0RGlyZWN0aW9uUHJvcGVydHlWYWx1ZShzbGlkZVN0eWxlcywgJ3BhZGRpbmctbGVmdCcpO1xuICAgICAgICAgICAgY29uc3QgcGFkZGluZ1JpZ2h0ID0gZ2V0RGlyZWN0aW9uUHJvcGVydHlWYWx1ZShzbGlkZVN0eWxlcywgJ3BhZGRpbmctcmlnaHQnKTtcbiAgICAgICAgICAgIGNvbnN0IG1hcmdpbkxlZnQgPSBnZXREaXJlY3Rpb25Qcm9wZXJ0eVZhbHVlKHNsaWRlU3R5bGVzLCAnbWFyZ2luLWxlZnQnKTtcbiAgICAgICAgICAgIGNvbnN0IG1hcmdpblJpZ2h0ID0gZ2V0RGlyZWN0aW9uUHJvcGVydHlWYWx1ZShzbGlkZVN0eWxlcywgJ21hcmdpbi1yaWdodCcpO1xuICAgICAgICAgICAgY29uc3QgYm94U2l6aW5nID0gc2xpZGVTdHlsZXMuZ2V0UHJvcGVydHlWYWx1ZSgnYm94LXNpemluZycpO1xuXG4gICAgICAgICAgICBpZiAoYm94U2l6aW5nICYmIGJveFNpemluZyA9PT0gJ2JvcmRlci1ib3gnKSB7XG4gICAgICAgICAgICAgIHNsaWRlU2l6ZSA9IHdpZHRoICsgbWFyZ2luTGVmdCArIG1hcmdpblJpZ2h0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY29uc3Qge1xuICAgICAgICAgICAgICAgIGNsaWVudFdpZHRoLFxuICAgICAgICAgICAgICAgIG9mZnNldFdpZHRoXG4gICAgICAgICAgICAgIH0gPSBzbGlkZVswXTtcbiAgICAgICAgICAgICAgc2xpZGVTaXplID0gd2lkdGggKyBwYWRkaW5nTGVmdCArIHBhZGRpbmdSaWdodCArIG1hcmdpbkxlZnQgKyBtYXJnaW5SaWdodCArIChvZmZzZXRXaWR0aCAtIGNsaWVudFdpZHRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoY3VycmVudFRyYW5zZm9ybSkge1xuICAgICAgICAgICAgc2xpZGVbMF0uc3R5bGUudHJhbnNmb3JtID0gY3VycmVudFRyYW5zZm9ybTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoY3VycmVudFdlYktpdFRyYW5zZm9ybSkge1xuICAgICAgICAgICAgc2xpZGVbMF0uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gY3VycmVudFdlYktpdFRyYW5zZm9ybTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocGFyYW1zLnJvdW5kTGVuZ3Rocykgc2xpZGVTaXplID0gTWF0aC5mbG9vcihzbGlkZVNpemUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNsaWRlU2l6ZSA9IChzd2lwZXJTaXplIC0gKHBhcmFtcy5zbGlkZXNQZXJWaWV3IC0gMSkgKiBzcGFjZUJldHdlZW4pIC8gcGFyYW1zLnNsaWRlc1BlclZpZXc7XG4gICAgICAgICAgaWYgKHBhcmFtcy5yb3VuZExlbmd0aHMpIHNsaWRlU2l6ZSA9IE1hdGguZmxvb3Ioc2xpZGVTaXplKTtcblxuICAgICAgICAgIGlmIChzbGlkZXNbaV0pIHtcbiAgICAgICAgICAgIHNsaWRlc1tpXS5zdHlsZVtnZXREaXJlY3Rpb25MYWJlbCgnd2lkdGgnKV0gPSBgJHtzbGlkZVNpemV9cHhgO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzbGlkZXNbaV0pIHtcbiAgICAgICAgICBzbGlkZXNbaV0uc3dpcGVyU2xpZGVTaXplID0gc2xpZGVTaXplO1xuICAgICAgICB9XG5cbiAgICAgICAgc2xpZGVzU2l6ZXNHcmlkLnB1c2goc2xpZGVTaXplKTtcblxuICAgICAgICBpZiAocGFyYW1zLmNlbnRlcmVkU2xpZGVzKSB7XG4gICAgICAgICAgc2xpZGVQb3NpdGlvbiA9IHNsaWRlUG9zaXRpb24gKyBzbGlkZVNpemUgLyAyICsgcHJldlNsaWRlU2l6ZSAvIDIgKyBzcGFjZUJldHdlZW47XG4gICAgICAgICAgaWYgKHByZXZTbGlkZVNpemUgPT09IDAgJiYgaSAhPT0gMCkgc2xpZGVQb3NpdGlvbiA9IHNsaWRlUG9zaXRpb24gLSBzd2lwZXJTaXplIC8gMiAtIHNwYWNlQmV0d2VlbjtcbiAgICAgICAgICBpZiAoaSA9PT0gMCkgc2xpZGVQb3NpdGlvbiA9IHNsaWRlUG9zaXRpb24gLSBzd2lwZXJTaXplIC8gMiAtIHNwYWNlQmV0d2VlbjtcbiAgICAgICAgICBpZiAoTWF0aC5hYnMoc2xpZGVQb3NpdGlvbikgPCAxIC8gMTAwMCkgc2xpZGVQb3NpdGlvbiA9IDA7XG4gICAgICAgICAgaWYgKHBhcmFtcy5yb3VuZExlbmd0aHMpIHNsaWRlUG9zaXRpb24gPSBNYXRoLmZsb29yKHNsaWRlUG9zaXRpb24pO1xuICAgICAgICAgIGlmIChpbmRleCAlIHBhcmFtcy5zbGlkZXNQZXJHcm91cCA9PT0gMCkgc25hcEdyaWQucHVzaChzbGlkZVBvc2l0aW9uKTtcbiAgICAgICAgICBzbGlkZXNHcmlkLnB1c2goc2xpZGVQb3NpdGlvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKHBhcmFtcy5yb3VuZExlbmd0aHMpIHNsaWRlUG9zaXRpb24gPSBNYXRoLmZsb29yKHNsaWRlUG9zaXRpb24pO1xuICAgICAgICAgIGlmICgoaW5kZXggLSBNYXRoLm1pbihzd2lwZXIucGFyYW1zLnNsaWRlc1Blckdyb3VwU2tpcCwgaW5kZXgpKSAlIHN3aXBlci5wYXJhbXMuc2xpZGVzUGVyR3JvdXAgPT09IDApIHNuYXBHcmlkLnB1c2goc2xpZGVQb3NpdGlvbik7XG4gICAgICAgICAgc2xpZGVzR3JpZC5wdXNoKHNsaWRlUG9zaXRpb24pO1xuICAgICAgICAgIHNsaWRlUG9zaXRpb24gPSBzbGlkZVBvc2l0aW9uICsgc2xpZGVTaXplICsgc3BhY2VCZXR3ZWVuO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpcGVyLnZpcnR1YWxTaXplICs9IHNsaWRlU2l6ZSArIHNwYWNlQmV0d2VlbjtcbiAgICAgICAgcHJldlNsaWRlU2l6ZSA9IHNsaWRlU2l6ZTtcbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH1cblxuICAgICAgc3dpcGVyLnZpcnR1YWxTaXplID0gTWF0aC5tYXgoc3dpcGVyLnZpcnR1YWxTaXplLCBzd2lwZXJTaXplKSArIG9mZnNldEFmdGVyO1xuXG4gICAgICBpZiAocnRsICYmIHdyb25nUlRMICYmIChwYXJhbXMuZWZmZWN0ID09PSAnc2xpZGUnIHx8IHBhcmFtcy5lZmZlY3QgPT09ICdjb3ZlcmZsb3cnKSkge1xuICAgICAgICAkd3JhcHBlckVsLmNzcyh7XG4gICAgICAgICAgd2lkdGg6IGAke3N3aXBlci52aXJ0dWFsU2l6ZSArIHBhcmFtcy5zcGFjZUJldHdlZW59cHhgXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAocGFyYW1zLnNldFdyYXBwZXJTaXplKSB7XG4gICAgICAgICR3cmFwcGVyRWwuY3NzKHtcbiAgICAgICAgICBbZ2V0RGlyZWN0aW9uTGFiZWwoJ3dpZHRoJyldOiBgJHtzd2lwZXIudmlydHVhbFNpemUgKyBwYXJhbXMuc3BhY2VCZXR3ZWVufXB4YFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGdyaWRFbmFibGVkKSB7XG4gICAgICAgIHN3aXBlci5ncmlkLnVwZGF0ZVdyYXBwZXJTaXplKHNsaWRlU2l6ZSwgc25hcEdyaWQsIGdldERpcmVjdGlvbkxhYmVsKTtcbiAgICAgIH0gLy8gUmVtb3ZlIGxhc3QgZ3JpZCBlbGVtZW50cyBkZXBlbmRpbmcgb24gd2lkdGhcblxuXG4gICAgICBpZiAoIXBhcmFtcy5jZW50ZXJlZFNsaWRlcykge1xuICAgICAgICBjb25zdCBuZXdTbGlkZXNHcmlkID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbmFwR3JpZC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgIGxldCBzbGlkZXNHcmlkSXRlbSA9IHNuYXBHcmlkW2ldO1xuICAgICAgICAgIGlmIChwYXJhbXMucm91bmRMZW5ndGhzKSBzbGlkZXNHcmlkSXRlbSA9IE1hdGguZmxvb3Ioc2xpZGVzR3JpZEl0ZW0pO1xuXG4gICAgICAgICAgaWYgKHNuYXBHcmlkW2ldIDw9IHN3aXBlci52aXJ0dWFsU2l6ZSAtIHN3aXBlclNpemUpIHtcbiAgICAgICAgICAgIG5ld1NsaWRlc0dyaWQucHVzaChzbGlkZXNHcmlkSXRlbSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc25hcEdyaWQgPSBuZXdTbGlkZXNHcmlkO1xuXG4gICAgICAgIGlmIChNYXRoLmZsb29yKHN3aXBlci52aXJ0dWFsU2l6ZSAtIHN3aXBlclNpemUpIC0gTWF0aC5mbG9vcihzbmFwR3JpZFtzbmFwR3JpZC5sZW5ndGggLSAxXSkgPiAxKSB7XG4gICAgICAgICAgc25hcEdyaWQucHVzaChzd2lwZXIudmlydHVhbFNpemUgLSBzd2lwZXJTaXplKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoc25hcEdyaWQubGVuZ3RoID09PSAwKSBzbmFwR3JpZCA9IFswXTtcblxuICAgICAgaWYgKHBhcmFtcy5zcGFjZUJldHdlZW4gIT09IDApIHtcbiAgICAgICAgY29uc3Qga2V5ID0gc3dpcGVyLmlzSG9yaXpvbnRhbCgpICYmIHJ0bCA/ICdtYXJnaW5MZWZ0JyA6IGdldERpcmVjdGlvbkxhYmVsKCdtYXJnaW5SaWdodCcpO1xuICAgICAgICBzbGlkZXMuZmlsdGVyKChfLCBzbGlkZUluZGV4KSA9PiB7XG4gICAgICAgICAgaWYgKCFwYXJhbXMuY3NzTW9kZSkgcmV0dXJuIHRydWU7XG5cbiAgICAgICAgICBpZiAoc2xpZGVJbmRleCA9PT0gc2xpZGVzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSkuY3NzKHtcbiAgICAgICAgICBba2V5XTogYCR7c3BhY2VCZXR3ZWVufXB4YFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5jZW50ZXJlZFNsaWRlcyAmJiBwYXJhbXMuY2VudGVyZWRTbGlkZXNCb3VuZHMpIHtcbiAgICAgICAgbGV0IGFsbFNsaWRlc1NpemUgPSAwO1xuICAgICAgICBzbGlkZXNTaXplc0dyaWQuZm9yRWFjaChzbGlkZVNpemVWYWx1ZSA9PiB7XG4gICAgICAgICAgYWxsU2xpZGVzU2l6ZSArPSBzbGlkZVNpemVWYWx1ZSArIChwYXJhbXMuc3BhY2VCZXR3ZWVuID8gcGFyYW1zLnNwYWNlQmV0d2VlbiA6IDApO1xuICAgICAgICB9KTtcbiAgICAgICAgYWxsU2xpZGVzU2l6ZSAtPSBwYXJhbXMuc3BhY2VCZXR3ZWVuO1xuICAgICAgICBjb25zdCBtYXhTbmFwID0gYWxsU2xpZGVzU2l6ZSAtIHN3aXBlclNpemU7XG4gICAgICAgIHNuYXBHcmlkID0gc25hcEdyaWQubWFwKHNuYXAgPT4ge1xuICAgICAgICAgIGlmIChzbmFwIDwgMCkgcmV0dXJuIC1vZmZzZXRCZWZvcmU7XG4gICAgICAgICAgaWYgKHNuYXAgPiBtYXhTbmFwKSByZXR1cm4gbWF4U25hcCArIG9mZnNldEFmdGVyO1xuICAgICAgICAgIHJldHVybiBzbmFwO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5jZW50ZXJJbnN1ZmZpY2llbnRTbGlkZXMpIHtcbiAgICAgICAgbGV0IGFsbFNsaWRlc1NpemUgPSAwO1xuICAgICAgICBzbGlkZXNTaXplc0dyaWQuZm9yRWFjaChzbGlkZVNpemVWYWx1ZSA9PiB7XG4gICAgICAgICAgYWxsU2xpZGVzU2l6ZSArPSBzbGlkZVNpemVWYWx1ZSArIChwYXJhbXMuc3BhY2VCZXR3ZWVuID8gcGFyYW1zLnNwYWNlQmV0d2VlbiA6IDApO1xuICAgICAgICB9KTtcbiAgICAgICAgYWxsU2xpZGVzU2l6ZSAtPSBwYXJhbXMuc3BhY2VCZXR3ZWVuO1xuXG4gICAgICAgIGlmIChhbGxTbGlkZXNTaXplIDwgc3dpcGVyU2l6ZSkge1xuICAgICAgICAgIGNvbnN0IGFsbFNsaWRlc09mZnNldCA9IChzd2lwZXJTaXplIC0gYWxsU2xpZGVzU2l6ZSkgLyAyO1xuICAgICAgICAgIHNuYXBHcmlkLmZvckVhY2goKHNuYXAsIHNuYXBJbmRleCkgPT4ge1xuICAgICAgICAgICAgc25hcEdyaWRbc25hcEluZGV4XSA9IHNuYXAgLSBhbGxTbGlkZXNPZmZzZXQ7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgc2xpZGVzR3JpZC5mb3JFYWNoKChzbmFwLCBzbmFwSW5kZXgpID0+IHtcbiAgICAgICAgICAgIHNsaWRlc0dyaWRbc25hcEluZGV4XSA9IHNuYXAgKyBhbGxTbGlkZXNPZmZzZXQ7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgT2JqZWN0LmFzc2lnbihzd2lwZXIsIHtcbiAgICAgICAgc2xpZGVzLFxuICAgICAgICBzbmFwR3JpZCxcbiAgICAgICAgc2xpZGVzR3JpZCxcbiAgICAgICAgc2xpZGVzU2l6ZXNHcmlkXG4gICAgICB9KTtcblxuICAgICAgaWYgKHBhcmFtcy5jZW50ZXJlZFNsaWRlcyAmJiBwYXJhbXMuY3NzTW9kZSAmJiAhcGFyYW1zLmNlbnRlcmVkU2xpZGVzQm91bmRzKSB7XG4gICAgICAgIHNldENTU1Byb3BlcnR5KHN3aXBlci53cmFwcGVyRWwsICctLXN3aXBlci1jZW50ZXJlZC1vZmZzZXQtYmVmb3JlJywgYCR7LXNuYXBHcmlkWzBdfXB4YCk7XG4gICAgICAgIHNldENTU1Byb3BlcnR5KHN3aXBlci53cmFwcGVyRWwsICctLXN3aXBlci1jZW50ZXJlZC1vZmZzZXQtYWZ0ZXInLCBgJHtzd2lwZXIuc2l6ZSAvIDIgLSBzbGlkZXNTaXplc0dyaWRbc2xpZGVzU2l6ZXNHcmlkLmxlbmd0aCAtIDFdIC8gMn1weGApO1xuICAgICAgICBjb25zdCBhZGRUb1NuYXBHcmlkID0gLXN3aXBlci5zbmFwR3JpZFswXTtcbiAgICAgICAgY29uc3QgYWRkVG9TbGlkZXNHcmlkID0gLXN3aXBlci5zbGlkZXNHcmlkWzBdO1xuICAgICAgICBzd2lwZXIuc25hcEdyaWQgPSBzd2lwZXIuc25hcEdyaWQubWFwKHYgPT4gdiArIGFkZFRvU25hcEdyaWQpO1xuICAgICAgICBzd2lwZXIuc2xpZGVzR3JpZCA9IHN3aXBlci5zbGlkZXNHcmlkLm1hcCh2ID0+IHYgKyBhZGRUb1NsaWRlc0dyaWQpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2xpZGVzTGVuZ3RoICE9PSBwcmV2aW91c1NsaWRlc0xlbmd0aCkge1xuICAgICAgICBzd2lwZXIuZW1pdCgnc2xpZGVzTGVuZ3RoQ2hhbmdlJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzbmFwR3JpZC5sZW5ndGggIT09IHByZXZpb3VzU25hcEdyaWRMZW5ndGgpIHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMud2F0Y2hPdmVyZmxvdykgc3dpcGVyLmNoZWNrT3ZlcmZsb3coKTtcbiAgICAgICAgc3dpcGVyLmVtaXQoJ3NuYXBHcmlkTGVuZ3RoQ2hhbmdlJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzbGlkZXNHcmlkLmxlbmd0aCAhPT0gcHJldmlvdXNTbGlkZXNHcmlkTGVuZ3RoKSB7XG4gICAgICAgIHN3aXBlci5lbWl0KCdzbGlkZXNHcmlkTGVuZ3RoQ2hhbmdlJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMud2F0Y2hTbGlkZXNQcm9ncmVzcykge1xuICAgICAgICBzd2lwZXIudXBkYXRlU2xpZGVzT2Zmc2V0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghaXNWaXJ0dWFsICYmICFwYXJhbXMuY3NzTW9kZSAmJiAocGFyYW1zLmVmZmVjdCA9PT0gJ3NsaWRlJyB8fCBwYXJhbXMuZWZmZWN0ID09PSAnZmFkZScpKSB7XG4gICAgICAgIGNvbnN0IGJhY2tGYWNlSGlkZGVuQ2xhc3MgPSBgJHtwYXJhbXMuY29udGFpbmVyTW9kaWZpZXJDbGFzc31iYWNrZmFjZS1oaWRkZW5gO1xuICAgICAgICBjb25zdCBoYXNDbGFzc0JhY2tmYWNlQ2xhc3NBZGRlZCA9IHN3aXBlci4kZWwuaGFzQ2xhc3MoYmFja0ZhY2VIaWRkZW5DbGFzcyk7XG5cbiAgICAgICAgaWYgKHNsaWRlc0xlbmd0aCA8PSBwYXJhbXMubWF4QmFja2ZhY2VIaWRkZW5TbGlkZXMpIHtcbiAgICAgICAgICBpZiAoIWhhc0NsYXNzQmFja2ZhY2VDbGFzc0FkZGVkKSBzd2lwZXIuJGVsLmFkZENsYXNzKGJhY2tGYWNlSGlkZGVuQ2xhc3MpO1xuICAgICAgICB9IGVsc2UgaWYgKGhhc0NsYXNzQmFja2ZhY2VDbGFzc0FkZGVkKSB7XG4gICAgICAgICAgc3dpcGVyLiRlbC5yZW1vdmVDbGFzcyhiYWNrRmFjZUhpZGRlbkNsYXNzKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZUF1dG9IZWlnaHQoc3BlZWQpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCBhY3RpdmVTbGlkZXMgPSBbXTtcbiAgICAgIGNvbnN0IGlzVmlydHVhbCA9IHN3aXBlci52aXJ0dWFsICYmIHN3aXBlci5wYXJhbXMudmlydHVhbC5lbmFibGVkO1xuICAgICAgbGV0IG5ld0hlaWdodCA9IDA7XG4gICAgICBsZXQgaTtcblxuICAgICAgaWYgKHR5cGVvZiBzcGVlZCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgc3dpcGVyLnNldFRyYW5zaXRpb24oc3BlZWQpO1xuICAgICAgfSBlbHNlIGlmIChzcGVlZCA9PT0gdHJ1ZSkge1xuICAgICAgICBzd2lwZXIuc2V0VHJhbnNpdGlvbihzd2lwZXIucGFyYW1zLnNwZWVkKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZ2V0U2xpZGVCeUluZGV4ID0gaW5kZXggPT4ge1xuICAgICAgICBpZiAoaXNWaXJ0dWFsKSB7XG4gICAgICAgICAgcmV0dXJuIHN3aXBlci5zbGlkZXMuZmlsdGVyKGVsID0+IHBhcnNlSW50KGVsLmdldEF0dHJpYnV0ZSgnZGF0YS1zd2lwZXItc2xpZGUtaW5kZXgnKSwgMTApID09PSBpbmRleClbMF07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc3dpcGVyLnNsaWRlcy5lcShpbmRleClbMF07XG4gICAgICB9OyAvLyBGaW5kIHNsaWRlcyBjdXJyZW50bHkgaW4gdmlld1xuXG5cbiAgICAgIGlmIChzd2lwZXIucGFyYW1zLnNsaWRlc1BlclZpZXcgIT09ICdhdXRvJyAmJiBzd2lwZXIucGFyYW1zLnNsaWRlc1BlclZpZXcgPiAxKSB7XG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmNlbnRlcmVkU2xpZGVzKSB7XG4gICAgICAgICAgc3dpcGVyLnZpc2libGVTbGlkZXMuZWFjaChzbGlkZSA9PiB7XG4gICAgICAgICAgICBhY3RpdmVTbGlkZXMucHVzaChzbGlkZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZm9yIChpID0gMDsgaSA8IE1hdGguY2VpbChzd2lwZXIucGFyYW1zLnNsaWRlc1BlclZpZXcpOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gc3dpcGVyLmFjdGl2ZUluZGV4ICsgaTtcbiAgICAgICAgICAgIGlmIChpbmRleCA+IHN3aXBlci5zbGlkZXMubGVuZ3RoICYmICFpc1ZpcnR1YWwpIGJyZWFrO1xuICAgICAgICAgICAgYWN0aXZlU2xpZGVzLnB1c2goZ2V0U2xpZGVCeUluZGV4KGluZGV4KSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhY3RpdmVTbGlkZXMucHVzaChnZXRTbGlkZUJ5SW5kZXgoc3dpcGVyLmFjdGl2ZUluZGV4KSk7XG4gICAgICB9IC8vIEZpbmQgbmV3IGhlaWdodCBmcm9tIGhpZ2hlc3Qgc2xpZGUgaW4gdmlld1xuXG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBhY3RpdmVTbGlkZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBhY3RpdmVTbGlkZXNbaV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgY29uc3QgaGVpZ2h0ID0gYWN0aXZlU2xpZGVzW2ldLm9mZnNldEhlaWdodDtcbiAgICAgICAgICBuZXdIZWlnaHQgPSBoZWlnaHQgPiBuZXdIZWlnaHQgPyBoZWlnaHQgOiBuZXdIZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgIH0gLy8gVXBkYXRlIEhlaWdodFxuXG5cbiAgICAgIGlmIChuZXdIZWlnaHQgfHwgbmV3SGVpZ2h0ID09PSAwKSBzd2lwZXIuJHdyYXBwZXJFbC5jc3MoJ2hlaWdodCcsIGAke25ld0hlaWdodH1weGApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZVNsaWRlc09mZnNldCgpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCBzbGlkZXMgPSBzd2lwZXIuc2xpZGVzO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNsaWRlcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBzbGlkZXNbaV0uc3dpcGVyU2xpZGVPZmZzZXQgPSBzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyBzbGlkZXNbaV0ub2Zmc2V0TGVmdCA6IHNsaWRlc1tpXS5vZmZzZXRUb3A7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlU2xpZGVzUHJvZ3Jlc3ModHJhbnNsYXRlKSB7XG4gICAgICBpZiAodHJhbnNsYXRlID09PSB2b2lkIDApIHtcbiAgICAgICAgdHJhbnNsYXRlID0gdGhpcyAmJiB0aGlzLnRyYW5zbGF0ZSB8fCAwO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcztcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgc2xpZGVzLFxuICAgICAgICBydGxUcmFuc2xhdGU6IHJ0bCxcbiAgICAgICAgc25hcEdyaWRcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICBpZiAoc2xpZGVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICAgICAgaWYgKHR5cGVvZiBzbGlkZXNbMF0uc3dpcGVyU2xpZGVPZmZzZXQgPT09ICd1bmRlZmluZWQnKSBzd2lwZXIudXBkYXRlU2xpZGVzT2Zmc2V0KCk7XG4gICAgICBsZXQgb2Zmc2V0Q2VudGVyID0gLXRyYW5zbGF0ZTtcbiAgICAgIGlmIChydGwpIG9mZnNldENlbnRlciA9IHRyYW5zbGF0ZTsgLy8gVmlzaWJsZSBTbGlkZXNcblxuICAgICAgc2xpZGVzLnJlbW92ZUNsYXNzKHBhcmFtcy5zbGlkZVZpc2libGVDbGFzcyk7XG4gICAgICBzd2lwZXIudmlzaWJsZVNsaWRlc0luZGV4ZXMgPSBbXTtcbiAgICAgIHN3aXBlci52aXNpYmxlU2xpZGVzID0gW107XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2xpZGVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGNvbnN0IHNsaWRlID0gc2xpZGVzW2ldO1xuICAgICAgICBsZXQgc2xpZGVPZmZzZXQgPSBzbGlkZS5zd2lwZXJTbGlkZU9mZnNldDtcblxuICAgICAgICBpZiAocGFyYW1zLmNzc01vZGUgJiYgcGFyYW1zLmNlbnRlcmVkU2xpZGVzKSB7XG4gICAgICAgICAgc2xpZGVPZmZzZXQgLT0gc2xpZGVzWzBdLnN3aXBlclNsaWRlT2Zmc2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc2xpZGVQcm9ncmVzcyA9IChvZmZzZXRDZW50ZXIgKyAocGFyYW1zLmNlbnRlcmVkU2xpZGVzID8gc3dpcGVyLm1pblRyYW5zbGF0ZSgpIDogMCkgLSBzbGlkZU9mZnNldCkgLyAoc2xpZGUuc3dpcGVyU2xpZGVTaXplICsgcGFyYW1zLnNwYWNlQmV0d2Vlbik7XG4gICAgICAgIGNvbnN0IG9yaWdpbmFsU2xpZGVQcm9ncmVzcyA9IChvZmZzZXRDZW50ZXIgLSBzbmFwR3JpZFswXSArIChwYXJhbXMuY2VudGVyZWRTbGlkZXMgPyBzd2lwZXIubWluVHJhbnNsYXRlKCkgOiAwKSAtIHNsaWRlT2Zmc2V0KSAvIChzbGlkZS5zd2lwZXJTbGlkZVNpemUgKyBwYXJhbXMuc3BhY2VCZXR3ZWVuKTtcbiAgICAgICAgY29uc3Qgc2xpZGVCZWZvcmUgPSAtKG9mZnNldENlbnRlciAtIHNsaWRlT2Zmc2V0KTtcbiAgICAgICAgY29uc3Qgc2xpZGVBZnRlciA9IHNsaWRlQmVmb3JlICsgc3dpcGVyLnNsaWRlc1NpemVzR3JpZFtpXTtcbiAgICAgICAgY29uc3QgaXNWaXNpYmxlID0gc2xpZGVCZWZvcmUgPj0gMCAmJiBzbGlkZUJlZm9yZSA8IHN3aXBlci5zaXplIC0gMSB8fCBzbGlkZUFmdGVyID4gMSAmJiBzbGlkZUFmdGVyIDw9IHN3aXBlci5zaXplIHx8IHNsaWRlQmVmb3JlIDw9IDAgJiYgc2xpZGVBZnRlciA+PSBzd2lwZXIuc2l6ZTtcblxuICAgICAgICBpZiAoaXNWaXNpYmxlKSB7XG4gICAgICAgICAgc3dpcGVyLnZpc2libGVTbGlkZXMucHVzaChzbGlkZSk7XG4gICAgICAgICAgc3dpcGVyLnZpc2libGVTbGlkZXNJbmRleGVzLnB1c2goaSk7XG4gICAgICAgICAgc2xpZGVzLmVxKGkpLmFkZENsYXNzKHBhcmFtcy5zbGlkZVZpc2libGVDbGFzcyk7XG4gICAgICAgIH1cblxuICAgICAgICBzbGlkZS5wcm9ncmVzcyA9IHJ0bCA/IC1zbGlkZVByb2dyZXNzIDogc2xpZGVQcm9ncmVzcztcbiAgICAgICAgc2xpZGUub3JpZ2luYWxQcm9ncmVzcyA9IHJ0bCA/IC1vcmlnaW5hbFNsaWRlUHJvZ3Jlc3MgOiBvcmlnaW5hbFNsaWRlUHJvZ3Jlc3M7XG4gICAgICB9XG5cbiAgICAgIHN3aXBlci52aXNpYmxlU2xpZGVzID0gJChzd2lwZXIudmlzaWJsZVNsaWRlcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlUHJvZ3Jlc3ModHJhbnNsYXRlKSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuXG4gICAgICBpZiAodHlwZW9mIHRyYW5zbGF0ZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgY29uc3QgbXVsdGlwbGllciA9IHN3aXBlci5ydGxUcmFuc2xhdGUgPyAtMSA6IDE7IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuXG4gICAgICAgIHRyYW5zbGF0ZSA9IHN3aXBlciAmJiBzd2lwZXIudHJhbnNsYXRlICYmIHN3aXBlci50cmFuc2xhdGUgKiBtdWx0aXBsaWVyIHx8IDA7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBhcmFtcyA9IHN3aXBlci5wYXJhbXM7XG4gICAgICBjb25zdCB0cmFuc2xhdGVzRGlmZiA9IHN3aXBlci5tYXhUcmFuc2xhdGUoKSAtIHN3aXBlci5taW5UcmFuc2xhdGUoKTtcbiAgICAgIGxldCB7XG4gICAgICAgIHByb2dyZXNzLFxuICAgICAgICBpc0JlZ2lubmluZyxcbiAgICAgICAgaXNFbmRcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICBjb25zdCB3YXNCZWdpbm5pbmcgPSBpc0JlZ2lubmluZztcbiAgICAgIGNvbnN0IHdhc0VuZCA9IGlzRW5kO1xuXG4gICAgICBpZiAodHJhbnNsYXRlc0RpZmYgPT09IDApIHtcbiAgICAgICAgcHJvZ3Jlc3MgPSAwO1xuICAgICAgICBpc0JlZ2lubmluZyA9IHRydWU7XG4gICAgICAgIGlzRW5kID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHByb2dyZXNzID0gKHRyYW5zbGF0ZSAtIHN3aXBlci5taW5UcmFuc2xhdGUoKSkgLyB0cmFuc2xhdGVzRGlmZjtcbiAgICAgICAgaXNCZWdpbm5pbmcgPSBwcm9ncmVzcyA8PSAwO1xuICAgICAgICBpc0VuZCA9IHByb2dyZXNzID49IDE7XG4gICAgICB9XG5cbiAgICAgIE9iamVjdC5hc3NpZ24oc3dpcGVyLCB7XG4gICAgICAgIHByb2dyZXNzLFxuICAgICAgICBpc0JlZ2lubmluZyxcbiAgICAgICAgaXNFbmRcbiAgICAgIH0pO1xuICAgICAgaWYgKHBhcmFtcy53YXRjaFNsaWRlc1Byb2dyZXNzIHx8IHBhcmFtcy5jZW50ZXJlZFNsaWRlcyAmJiBwYXJhbXMuYXV0b0hlaWdodCkgc3dpcGVyLnVwZGF0ZVNsaWRlc1Byb2dyZXNzKHRyYW5zbGF0ZSk7XG5cbiAgICAgIGlmIChpc0JlZ2lubmluZyAmJiAhd2FzQmVnaW5uaW5nKSB7XG4gICAgICAgIHN3aXBlci5lbWl0KCdyZWFjaEJlZ2lubmluZyB0b0VkZ2UnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzRW5kICYmICF3YXNFbmQpIHtcbiAgICAgICAgc3dpcGVyLmVtaXQoJ3JlYWNoRW5kIHRvRWRnZScpO1xuICAgICAgfVxuXG4gICAgICBpZiAod2FzQmVnaW5uaW5nICYmICFpc0JlZ2lubmluZyB8fCB3YXNFbmQgJiYgIWlzRW5kKSB7XG4gICAgICAgIHN3aXBlci5lbWl0KCdmcm9tRWRnZScpO1xuICAgICAgfVxuXG4gICAgICBzd2lwZXIuZW1pdCgncHJvZ3Jlc3MnLCBwcm9ncmVzcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlU2xpZGVzQ2xhc3NlcygpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHNsaWRlcyxcbiAgICAgICAgcGFyYW1zLFxuICAgICAgICAkd3JhcHBlckVsLFxuICAgICAgICBhY3RpdmVJbmRleCxcbiAgICAgICAgcmVhbEluZGV4XG4gICAgICB9ID0gc3dpcGVyO1xuICAgICAgY29uc3QgaXNWaXJ0dWFsID0gc3dpcGVyLnZpcnR1YWwgJiYgcGFyYW1zLnZpcnR1YWwuZW5hYmxlZDtcbiAgICAgIHNsaWRlcy5yZW1vdmVDbGFzcyhgJHtwYXJhbXMuc2xpZGVBY3RpdmVDbGFzc30gJHtwYXJhbXMuc2xpZGVOZXh0Q2xhc3N9ICR7cGFyYW1zLnNsaWRlUHJldkNsYXNzfSAke3BhcmFtcy5zbGlkZUR1cGxpY2F0ZUFjdGl2ZUNsYXNzfSAke3BhcmFtcy5zbGlkZUR1cGxpY2F0ZU5leHRDbGFzc30gJHtwYXJhbXMuc2xpZGVEdXBsaWNhdGVQcmV2Q2xhc3N9YCk7XG4gICAgICBsZXQgYWN0aXZlU2xpZGU7XG5cbiAgICAgIGlmIChpc1ZpcnR1YWwpIHtcbiAgICAgICAgYWN0aXZlU2xpZGUgPSBzd2lwZXIuJHdyYXBwZXJFbC5maW5kKGAuJHtwYXJhbXMuc2xpZGVDbGFzc31bZGF0YS1zd2lwZXItc2xpZGUtaW5kZXg9XCIke2FjdGl2ZUluZGV4fVwiXWApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYWN0aXZlU2xpZGUgPSBzbGlkZXMuZXEoYWN0aXZlSW5kZXgpO1xuICAgICAgfSAvLyBBY3RpdmUgY2xhc3Nlc1xuXG5cbiAgICAgIGFjdGl2ZVNsaWRlLmFkZENsYXNzKHBhcmFtcy5zbGlkZUFjdGl2ZUNsYXNzKTtcblxuICAgICAgaWYgKHBhcmFtcy5sb29wKSB7XG4gICAgICAgIC8vIER1cGxpY2F0ZSB0byBhbGwgbG9vcGVkIHNsaWRlc1xuICAgICAgICBpZiAoYWN0aXZlU2xpZGUuaGFzQ2xhc3MocGFyYW1zLnNsaWRlRHVwbGljYXRlQ2xhc3MpKSB7XG4gICAgICAgICAgJHdyYXBwZXJFbC5jaGlsZHJlbihgLiR7cGFyYW1zLnNsaWRlQ2xhc3N9Om5vdCguJHtwYXJhbXMuc2xpZGVEdXBsaWNhdGVDbGFzc30pW2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4PVwiJHtyZWFsSW5kZXh9XCJdYCkuYWRkQ2xhc3MocGFyYW1zLnNsaWRlRHVwbGljYXRlQWN0aXZlQ2xhc3MpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICR3cmFwcGVyRWwuY2hpbGRyZW4oYC4ke3BhcmFtcy5zbGlkZUNsYXNzfS4ke3BhcmFtcy5zbGlkZUR1cGxpY2F0ZUNsYXNzfVtkYXRhLXN3aXBlci1zbGlkZS1pbmRleD1cIiR7cmVhbEluZGV4fVwiXWApLmFkZENsYXNzKHBhcmFtcy5zbGlkZUR1cGxpY2F0ZUFjdGl2ZUNsYXNzKTtcbiAgICAgICAgfVxuICAgICAgfSAvLyBOZXh0IFNsaWRlXG5cblxuICAgICAgbGV0IG5leHRTbGlkZSA9IGFjdGl2ZVNsaWRlLm5leHRBbGwoYC4ke3BhcmFtcy5zbGlkZUNsYXNzfWApLmVxKDApLmFkZENsYXNzKHBhcmFtcy5zbGlkZU5leHRDbGFzcyk7XG5cbiAgICAgIGlmIChwYXJhbXMubG9vcCAmJiBuZXh0U2xpZGUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIG5leHRTbGlkZSA9IHNsaWRlcy5lcSgwKTtcbiAgICAgICAgbmV4dFNsaWRlLmFkZENsYXNzKHBhcmFtcy5zbGlkZU5leHRDbGFzcyk7XG4gICAgICB9IC8vIFByZXYgU2xpZGVcblxuXG4gICAgICBsZXQgcHJldlNsaWRlID0gYWN0aXZlU2xpZGUucHJldkFsbChgLiR7cGFyYW1zLnNsaWRlQ2xhc3N9YCkuZXEoMCkuYWRkQ2xhc3MocGFyYW1zLnNsaWRlUHJldkNsYXNzKTtcblxuICAgICAgaWYgKHBhcmFtcy5sb29wICYmIHByZXZTbGlkZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcHJldlNsaWRlID0gc2xpZGVzLmVxKC0xKTtcbiAgICAgICAgcHJldlNsaWRlLmFkZENsYXNzKHBhcmFtcy5zbGlkZVByZXZDbGFzcyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMubG9vcCkge1xuICAgICAgICAvLyBEdXBsaWNhdGUgdG8gYWxsIGxvb3BlZCBzbGlkZXNcbiAgICAgICAgaWYgKG5leHRTbGlkZS5oYXNDbGFzcyhwYXJhbXMuc2xpZGVEdXBsaWNhdGVDbGFzcykpIHtcbiAgICAgICAgICAkd3JhcHBlckVsLmNoaWxkcmVuKGAuJHtwYXJhbXMuc2xpZGVDbGFzc306bm90KC4ke3BhcmFtcy5zbGlkZUR1cGxpY2F0ZUNsYXNzfSlbZGF0YS1zd2lwZXItc2xpZGUtaW5kZXg9XCIke25leHRTbGlkZS5hdHRyKCdkYXRhLXN3aXBlci1zbGlkZS1pbmRleCcpfVwiXWApLmFkZENsYXNzKHBhcmFtcy5zbGlkZUR1cGxpY2F0ZU5leHRDbGFzcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgJHdyYXBwZXJFbC5jaGlsZHJlbihgLiR7cGFyYW1zLnNsaWRlQ2xhc3N9LiR7cGFyYW1zLnNsaWRlRHVwbGljYXRlQ2xhc3N9W2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4PVwiJHtuZXh0U2xpZGUuYXR0cignZGF0YS1zd2lwZXItc2xpZGUtaW5kZXgnKX1cIl1gKS5hZGRDbGFzcyhwYXJhbXMuc2xpZGVEdXBsaWNhdGVOZXh0Q2xhc3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHByZXZTbGlkZS5oYXNDbGFzcyhwYXJhbXMuc2xpZGVEdXBsaWNhdGVDbGFzcykpIHtcbiAgICAgICAgICAkd3JhcHBlckVsLmNoaWxkcmVuKGAuJHtwYXJhbXMuc2xpZGVDbGFzc306bm90KC4ke3BhcmFtcy5zbGlkZUR1cGxpY2F0ZUNsYXNzfSlbZGF0YS1zd2lwZXItc2xpZGUtaW5kZXg9XCIke3ByZXZTbGlkZS5hdHRyKCdkYXRhLXN3aXBlci1zbGlkZS1pbmRleCcpfVwiXWApLmFkZENsYXNzKHBhcmFtcy5zbGlkZUR1cGxpY2F0ZVByZXZDbGFzcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgJHdyYXBwZXJFbC5jaGlsZHJlbihgLiR7cGFyYW1zLnNsaWRlQ2xhc3N9LiR7cGFyYW1zLnNsaWRlRHVwbGljYXRlQ2xhc3N9W2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4PVwiJHtwcmV2U2xpZGUuYXR0cignZGF0YS1zd2lwZXItc2xpZGUtaW5kZXgnKX1cIl1gKS5hZGRDbGFzcyhwYXJhbXMuc2xpZGVEdXBsaWNhdGVQcmV2Q2xhc3MpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHN3aXBlci5lbWl0U2xpZGVzQ2xhc3NlcygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZUFjdGl2ZUluZGV4KG5ld0FjdGl2ZUluZGV4KSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3QgdHJhbnNsYXRlID0gc3dpcGVyLnJ0bFRyYW5zbGF0ZSA/IHN3aXBlci50cmFuc2xhdGUgOiAtc3dpcGVyLnRyYW5zbGF0ZTtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgc2xpZGVzR3JpZCxcbiAgICAgICAgc25hcEdyaWQsXG4gICAgICAgIHBhcmFtcyxcbiAgICAgICAgYWN0aXZlSW5kZXg6IHByZXZpb3VzSW5kZXgsXG4gICAgICAgIHJlYWxJbmRleDogcHJldmlvdXNSZWFsSW5kZXgsXG4gICAgICAgIHNuYXBJbmRleDogcHJldmlvdXNTbmFwSW5kZXhcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICBsZXQgYWN0aXZlSW5kZXggPSBuZXdBY3RpdmVJbmRleDtcbiAgICAgIGxldCBzbmFwSW5kZXg7XG5cbiAgICAgIGlmICh0eXBlb2YgYWN0aXZlSW5kZXggPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2xpZGVzR3JpZC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgIGlmICh0eXBlb2Ygc2xpZGVzR3JpZFtpICsgMV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBpZiAodHJhbnNsYXRlID49IHNsaWRlc0dyaWRbaV0gJiYgdHJhbnNsYXRlIDwgc2xpZGVzR3JpZFtpICsgMV0gLSAoc2xpZGVzR3JpZFtpICsgMV0gLSBzbGlkZXNHcmlkW2ldKSAvIDIpIHtcbiAgICAgICAgICAgICAgYWN0aXZlSW5kZXggPSBpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0cmFuc2xhdGUgPj0gc2xpZGVzR3JpZFtpXSAmJiB0cmFuc2xhdGUgPCBzbGlkZXNHcmlkW2kgKyAxXSkge1xuICAgICAgICAgICAgICBhY3RpdmVJbmRleCA9IGkgKyAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAodHJhbnNsYXRlID49IHNsaWRlc0dyaWRbaV0pIHtcbiAgICAgICAgICAgIGFjdGl2ZUluZGV4ID0gaTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gLy8gTm9ybWFsaXplIHNsaWRlSW5kZXhcblxuXG4gICAgICAgIGlmIChwYXJhbXMubm9ybWFsaXplU2xpZGVJbmRleCkge1xuICAgICAgICAgIGlmIChhY3RpdmVJbmRleCA8IDAgfHwgdHlwZW9mIGFjdGl2ZUluZGV4ID09PSAndW5kZWZpbmVkJykgYWN0aXZlSW5kZXggPSAwO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChzbmFwR3JpZC5pbmRleE9mKHRyYW5zbGF0ZSkgPj0gMCkge1xuICAgICAgICBzbmFwSW5kZXggPSBzbmFwR3JpZC5pbmRleE9mKHRyYW5zbGF0ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBza2lwID0gTWF0aC5taW4ocGFyYW1zLnNsaWRlc1Blckdyb3VwU2tpcCwgYWN0aXZlSW5kZXgpO1xuICAgICAgICBzbmFwSW5kZXggPSBza2lwICsgTWF0aC5mbG9vcigoYWN0aXZlSW5kZXggLSBza2lwKSAvIHBhcmFtcy5zbGlkZXNQZXJHcm91cCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzbmFwSW5kZXggPj0gc25hcEdyaWQubGVuZ3RoKSBzbmFwSW5kZXggPSBzbmFwR3JpZC5sZW5ndGggLSAxO1xuXG4gICAgICBpZiAoYWN0aXZlSW5kZXggPT09IHByZXZpb3VzSW5kZXgpIHtcbiAgICAgICAgaWYgKHNuYXBJbmRleCAhPT0gcHJldmlvdXNTbmFwSW5kZXgpIHtcbiAgICAgICAgICBzd2lwZXIuc25hcEluZGV4ID0gc25hcEluZGV4O1xuICAgICAgICAgIHN3aXBlci5lbWl0KCdzbmFwSW5kZXhDaGFuZ2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gLy8gR2V0IHJlYWwgaW5kZXhcblxuXG4gICAgICBjb25zdCByZWFsSW5kZXggPSBwYXJzZUludChzd2lwZXIuc2xpZGVzLmVxKGFjdGl2ZUluZGV4KS5hdHRyKCdkYXRhLXN3aXBlci1zbGlkZS1pbmRleCcpIHx8IGFjdGl2ZUluZGV4LCAxMCk7XG4gICAgICBPYmplY3QuYXNzaWduKHN3aXBlciwge1xuICAgICAgICBzbmFwSW5kZXgsXG4gICAgICAgIHJlYWxJbmRleCxcbiAgICAgICAgcHJldmlvdXNJbmRleCxcbiAgICAgICAgYWN0aXZlSW5kZXhcbiAgICAgIH0pO1xuICAgICAgc3dpcGVyLmVtaXQoJ2FjdGl2ZUluZGV4Q2hhbmdlJyk7XG4gICAgICBzd2lwZXIuZW1pdCgnc25hcEluZGV4Q2hhbmdlJyk7XG5cbiAgICAgIGlmIChwcmV2aW91c1JlYWxJbmRleCAhPT0gcmVhbEluZGV4KSB7XG4gICAgICAgIHN3aXBlci5lbWl0KCdyZWFsSW5kZXhDaGFuZ2UnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHN3aXBlci5pbml0aWFsaXplZCB8fCBzd2lwZXIucGFyYW1zLnJ1bkNhbGxiYWNrc09uSW5pdCkge1xuICAgICAgICBzd2lwZXIuZW1pdCgnc2xpZGVDaGFuZ2UnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVDbGlja2VkU2xpZGUoZSkge1xuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHN3aXBlci5wYXJhbXM7XG4gICAgICBjb25zdCBzbGlkZSA9ICQoZSkuY2xvc2VzdChgLiR7cGFyYW1zLnNsaWRlQ2xhc3N9YClbMF07XG4gICAgICBsZXQgc2xpZGVGb3VuZCA9IGZhbHNlO1xuICAgICAgbGV0IHNsaWRlSW5kZXg7XG5cbiAgICAgIGlmIChzbGlkZSkge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHN3aXBlci5zbGlkZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICBpZiAoc3dpcGVyLnNsaWRlc1tpXSA9PT0gc2xpZGUpIHtcbiAgICAgICAgICAgIHNsaWRlRm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgc2xpZGVJbmRleCA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHNsaWRlICYmIHNsaWRlRm91bmQpIHtcbiAgICAgICAgc3dpcGVyLmNsaWNrZWRTbGlkZSA9IHNsaWRlO1xuXG4gICAgICAgIGlmIChzd2lwZXIudmlydHVhbCAmJiBzd2lwZXIucGFyYW1zLnZpcnR1YWwuZW5hYmxlZCkge1xuICAgICAgICAgIHN3aXBlci5jbGlja2VkSW5kZXggPSBwYXJzZUludCgkKHNsaWRlKS5hdHRyKCdkYXRhLXN3aXBlci1zbGlkZS1pbmRleCcpLCAxMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3dpcGVyLmNsaWNrZWRJbmRleCA9IHNsaWRlSW5kZXg7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN3aXBlci5jbGlja2VkU2xpZGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHN3aXBlci5jbGlja2VkSW5kZXggPSB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5zbGlkZVRvQ2xpY2tlZFNsaWRlICYmIHN3aXBlci5jbGlja2VkSW5kZXggIT09IHVuZGVmaW5lZCAmJiBzd2lwZXIuY2xpY2tlZEluZGV4ICE9PSBzd2lwZXIuYWN0aXZlSW5kZXgpIHtcbiAgICAgICAgc3dpcGVyLnNsaWRlVG9DbGlja2VkU2xpZGUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgdXBkYXRlID0ge1xuICAgICAgdXBkYXRlU2l6ZSxcbiAgICAgIHVwZGF0ZVNsaWRlcyxcbiAgICAgIHVwZGF0ZUF1dG9IZWlnaHQsXG4gICAgICB1cGRhdGVTbGlkZXNPZmZzZXQsXG4gICAgICB1cGRhdGVTbGlkZXNQcm9ncmVzcyxcbiAgICAgIHVwZGF0ZVByb2dyZXNzLFxuICAgICAgdXBkYXRlU2xpZGVzQ2xhc3NlcyxcbiAgICAgIHVwZGF0ZUFjdGl2ZUluZGV4LFxuICAgICAgdXBkYXRlQ2xpY2tlZFNsaWRlXG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGdldFN3aXBlclRyYW5zbGF0ZShheGlzKSB7XG4gICAgICBpZiAoYXhpcyA9PT0gdm9pZCAwKSB7XG4gICAgICAgIGF4aXMgPSB0aGlzLmlzSG9yaXpvbnRhbCgpID8gJ3gnIDogJ3knO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3Qge1xuICAgICAgICBwYXJhbXMsXG4gICAgICAgIHJ0bFRyYW5zbGF0ZTogcnRsLFxuICAgICAgICB0cmFuc2xhdGUsXG4gICAgICAgICR3cmFwcGVyRWxcbiAgICAgIH0gPSBzd2lwZXI7XG5cbiAgICAgIGlmIChwYXJhbXMudmlydHVhbFRyYW5zbGF0ZSkge1xuICAgICAgICByZXR1cm4gcnRsID8gLXRyYW5zbGF0ZSA6IHRyYW5zbGF0ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5jc3NNb2RlKSB7XG4gICAgICAgIHJldHVybiB0cmFuc2xhdGU7XG4gICAgICB9XG5cbiAgICAgIGxldCBjdXJyZW50VHJhbnNsYXRlID0gZ2V0VHJhbnNsYXRlKCR3cmFwcGVyRWxbMF0sIGF4aXMpO1xuICAgICAgaWYgKHJ0bCkgY3VycmVudFRyYW5zbGF0ZSA9IC1jdXJyZW50VHJhbnNsYXRlO1xuICAgICAgcmV0dXJuIGN1cnJlbnRUcmFuc2xhdGUgfHwgMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRUcmFuc2xhdGUodHJhbnNsYXRlLCBieUNvbnRyb2xsZXIpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHJ0bFRyYW5zbGF0ZTogcnRsLFxuICAgICAgICBwYXJhbXMsXG4gICAgICAgICR3cmFwcGVyRWwsXG4gICAgICAgIHdyYXBwZXJFbCxcbiAgICAgICAgcHJvZ3Jlc3NcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICBsZXQgeCA9IDA7XG4gICAgICBsZXQgeSA9IDA7XG4gICAgICBjb25zdCB6ID0gMDtcblxuICAgICAgaWYgKHN3aXBlci5pc0hvcml6b250YWwoKSkge1xuICAgICAgICB4ID0gcnRsID8gLXRyYW5zbGF0ZSA6IHRyYW5zbGF0ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHkgPSB0cmFuc2xhdGU7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMucm91bmRMZW5ndGhzKSB7XG4gICAgICAgIHggPSBNYXRoLmZsb29yKHgpO1xuICAgICAgICB5ID0gTWF0aC5mbG9vcih5KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5jc3NNb2RlKSB7XG4gICAgICAgIHdyYXBwZXJFbFtzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyAnc2Nyb2xsTGVmdCcgOiAnc2Nyb2xsVG9wJ10gPSBzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyAteCA6IC15O1xuICAgICAgfSBlbHNlIGlmICghcGFyYW1zLnZpcnR1YWxUcmFuc2xhdGUpIHtcbiAgICAgICAgJHdyYXBwZXJFbC50cmFuc2Zvcm0oYHRyYW5zbGF0ZTNkKCR7eH1weCwgJHt5fXB4LCAke3p9cHgpYCk7XG4gICAgICB9XG5cbiAgICAgIHN3aXBlci5wcmV2aW91c1RyYW5zbGF0ZSA9IHN3aXBlci50cmFuc2xhdGU7XG4gICAgICBzd2lwZXIudHJhbnNsYXRlID0gc3dpcGVyLmlzSG9yaXpvbnRhbCgpID8geCA6IHk7IC8vIENoZWNrIGlmIHdlIG5lZWQgdG8gdXBkYXRlIHByb2dyZXNzXG5cbiAgICAgIGxldCBuZXdQcm9ncmVzcztcbiAgICAgIGNvbnN0IHRyYW5zbGF0ZXNEaWZmID0gc3dpcGVyLm1heFRyYW5zbGF0ZSgpIC0gc3dpcGVyLm1pblRyYW5zbGF0ZSgpO1xuXG4gICAgICBpZiAodHJhbnNsYXRlc0RpZmYgPT09IDApIHtcbiAgICAgICAgbmV3UHJvZ3Jlc3MgPSAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV3UHJvZ3Jlc3MgPSAodHJhbnNsYXRlIC0gc3dpcGVyLm1pblRyYW5zbGF0ZSgpKSAvIHRyYW5zbGF0ZXNEaWZmO1xuICAgICAgfVxuXG4gICAgICBpZiAobmV3UHJvZ3Jlc3MgIT09IHByb2dyZXNzKSB7XG4gICAgICAgIHN3aXBlci51cGRhdGVQcm9ncmVzcyh0cmFuc2xhdGUpO1xuICAgICAgfVxuXG4gICAgICBzd2lwZXIuZW1pdCgnc2V0VHJhbnNsYXRlJywgc3dpcGVyLnRyYW5zbGF0ZSwgYnlDb250cm9sbGVyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtaW5UcmFuc2xhdGUoKSB7XG4gICAgICByZXR1cm4gLXRoaXMuc25hcEdyaWRbMF07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWF4VHJhbnNsYXRlKCkge1xuICAgICAgcmV0dXJuIC10aGlzLnNuYXBHcmlkW3RoaXMuc25hcEdyaWQubGVuZ3RoIC0gMV07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlVG8odHJhbnNsYXRlLCBzcGVlZCwgcnVuQ2FsbGJhY2tzLCB0cmFuc2xhdGVCb3VuZHMsIGludGVybmFsKSB7XG4gICAgICBpZiAodHJhbnNsYXRlID09PSB2b2lkIDApIHtcbiAgICAgICAgdHJhbnNsYXRlID0gMDtcbiAgICAgIH1cblxuICAgICAgaWYgKHNwZWVkID09PSB2b2lkIDApIHtcbiAgICAgICAgc3BlZWQgPSB0aGlzLnBhcmFtcy5zcGVlZDtcbiAgICAgIH1cblxuICAgICAgaWYgKHJ1bkNhbGxiYWNrcyA9PT0gdm9pZCAwKSB7XG4gICAgICAgIHJ1bkNhbGxiYWNrcyA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmICh0cmFuc2xhdGVCb3VuZHMgPT09IHZvaWQgMCkge1xuICAgICAgICB0cmFuc2xhdGVCb3VuZHMgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3Qge1xuICAgICAgICBwYXJhbXMsXG4gICAgICAgIHdyYXBwZXJFbFxuICAgICAgfSA9IHN3aXBlcjtcblxuICAgICAgaWYgKHN3aXBlci5hbmltYXRpbmcgJiYgcGFyYW1zLnByZXZlbnRJbnRlcmFjdGlvbk9uVHJhbnNpdGlvbikge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1pblRyYW5zbGF0ZSA9IHN3aXBlci5taW5UcmFuc2xhdGUoKTtcbiAgICAgIGNvbnN0IG1heFRyYW5zbGF0ZSA9IHN3aXBlci5tYXhUcmFuc2xhdGUoKTtcbiAgICAgIGxldCBuZXdUcmFuc2xhdGU7XG4gICAgICBpZiAodHJhbnNsYXRlQm91bmRzICYmIHRyYW5zbGF0ZSA+IG1pblRyYW5zbGF0ZSkgbmV3VHJhbnNsYXRlID0gbWluVHJhbnNsYXRlO2Vsc2UgaWYgKHRyYW5zbGF0ZUJvdW5kcyAmJiB0cmFuc2xhdGUgPCBtYXhUcmFuc2xhdGUpIG5ld1RyYW5zbGF0ZSA9IG1heFRyYW5zbGF0ZTtlbHNlIG5ld1RyYW5zbGF0ZSA9IHRyYW5zbGF0ZTsgLy8gVXBkYXRlIHByb2dyZXNzXG5cbiAgICAgIHN3aXBlci51cGRhdGVQcm9ncmVzcyhuZXdUcmFuc2xhdGUpO1xuXG4gICAgICBpZiAocGFyYW1zLmNzc01vZGUpIHtcbiAgICAgICAgY29uc3QgaXNIID0gc3dpcGVyLmlzSG9yaXpvbnRhbCgpO1xuXG4gICAgICAgIGlmIChzcGVlZCA9PT0gMCkge1xuICAgICAgICAgIHdyYXBwZXJFbFtpc0ggPyAnc2Nyb2xsTGVmdCcgOiAnc2Nyb2xsVG9wJ10gPSAtbmV3VHJhbnNsYXRlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICghc3dpcGVyLnN1cHBvcnQuc21vb3RoU2Nyb2xsKSB7XG4gICAgICAgICAgICBhbmltYXRlQ1NTTW9kZVNjcm9sbCh7XG4gICAgICAgICAgICAgIHN3aXBlcixcbiAgICAgICAgICAgICAgdGFyZ2V0UG9zaXRpb246IC1uZXdUcmFuc2xhdGUsXG4gICAgICAgICAgICAgIHNpZGU6IGlzSCA/ICdsZWZ0JyA6ICd0b3AnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHdyYXBwZXJFbC5zY3JvbGxUbyh7XG4gICAgICAgICAgICBbaXNIID8gJ2xlZnQnIDogJ3RvcCddOiAtbmV3VHJhbnNsYXRlLFxuICAgICAgICAgICAgYmVoYXZpb3I6ICdzbW9vdGgnXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNwZWVkID09PSAwKSB7XG4gICAgICAgIHN3aXBlci5zZXRUcmFuc2l0aW9uKDApO1xuICAgICAgICBzd2lwZXIuc2V0VHJhbnNsYXRlKG5ld1RyYW5zbGF0ZSk7XG5cbiAgICAgICAgaWYgKHJ1bkNhbGxiYWNrcykge1xuICAgICAgICAgIHN3aXBlci5lbWl0KCdiZWZvcmVUcmFuc2l0aW9uU3RhcnQnLCBzcGVlZCwgaW50ZXJuYWwpO1xuICAgICAgICAgIHN3aXBlci5lbWl0KCd0cmFuc2l0aW9uRW5kJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN3aXBlci5zZXRUcmFuc2l0aW9uKHNwZWVkKTtcbiAgICAgICAgc3dpcGVyLnNldFRyYW5zbGF0ZShuZXdUcmFuc2xhdGUpO1xuXG4gICAgICAgIGlmIChydW5DYWxsYmFja3MpIHtcbiAgICAgICAgICBzd2lwZXIuZW1pdCgnYmVmb3JlVHJhbnNpdGlvblN0YXJ0Jywgc3BlZWQsIGludGVybmFsKTtcbiAgICAgICAgICBzd2lwZXIuZW1pdCgndHJhbnNpdGlvblN0YXJ0Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXN3aXBlci5hbmltYXRpbmcpIHtcbiAgICAgICAgICBzd2lwZXIuYW5pbWF0aW5nID0gdHJ1ZTtcblxuICAgICAgICAgIGlmICghc3dpcGVyLm9uVHJhbnNsYXRlVG9XcmFwcGVyVHJhbnNpdGlvbkVuZCkge1xuICAgICAgICAgICAgc3dpcGVyLm9uVHJhbnNsYXRlVG9XcmFwcGVyVHJhbnNpdGlvbkVuZCA9IGZ1bmN0aW9uIHRyYW5zaXRpb25FbmQoZSkge1xuICAgICAgICAgICAgICBpZiAoIXN3aXBlciB8fCBzd2lwZXIuZGVzdHJveWVkKSByZXR1cm47XG4gICAgICAgICAgICAgIGlmIChlLnRhcmdldCAhPT0gdGhpcykgcmV0dXJuO1xuICAgICAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbFswXS5yZW1vdmVFdmVudExpc3RlbmVyKCd0cmFuc2l0aW9uZW5kJywgc3dpcGVyLm9uVHJhbnNsYXRlVG9XcmFwcGVyVHJhbnNpdGlvbkVuZCk7XG4gICAgICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsWzBdLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3dlYmtpdFRyYW5zaXRpb25FbmQnLCBzd2lwZXIub25UcmFuc2xhdGVUb1dyYXBwZXJUcmFuc2l0aW9uRW5kKTtcbiAgICAgICAgICAgICAgc3dpcGVyLm9uVHJhbnNsYXRlVG9XcmFwcGVyVHJhbnNpdGlvbkVuZCA9IG51bGw7XG4gICAgICAgICAgICAgIGRlbGV0ZSBzd2lwZXIub25UcmFuc2xhdGVUb1dyYXBwZXJUcmFuc2l0aW9uRW5kO1xuXG4gICAgICAgICAgICAgIGlmIChydW5DYWxsYmFja3MpIHtcbiAgICAgICAgICAgICAgICBzd2lwZXIuZW1pdCgndHJhbnNpdGlvbkVuZCcpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsWzBdLmFkZEV2ZW50TGlzdGVuZXIoJ3RyYW5zaXRpb25lbmQnLCBzd2lwZXIub25UcmFuc2xhdGVUb1dyYXBwZXJUcmFuc2l0aW9uRW5kKTtcbiAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbFswXS5hZGRFdmVudExpc3RlbmVyKCd3ZWJraXRUcmFuc2l0aW9uRW5kJywgc3dpcGVyLm9uVHJhbnNsYXRlVG9XcmFwcGVyVHJhbnNpdGlvbkVuZCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgdmFyIHRyYW5zbGF0ZSA9IHtcbiAgICAgIGdldFRyYW5zbGF0ZTogZ2V0U3dpcGVyVHJhbnNsYXRlLFxuICAgICAgc2V0VHJhbnNsYXRlLFxuICAgICAgbWluVHJhbnNsYXRlLFxuICAgICAgbWF4VHJhbnNsYXRlLFxuICAgICAgdHJhbnNsYXRlVG9cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gc2V0VHJhbnNpdGlvbihkdXJhdGlvbiwgYnlDb250cm9sbGVyKSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuXG4gICAgICBpZiAoIXN3aXBlci5wYXJhbXMuY3NzTW9kZSkge1xuICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbC50cmFuc2l0aW9uKGR1cmF0aW9uKTtcbiAgICAgIH1cblxuICAgICAgc3dpcGVyLmVtaXQoJ3NldFRyYW5zaXRpb24nLCBkdXJhdGlvbiwgYnlDb250cm9sbGVyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0cmFuc2l0aW9uRW1pdChfcmVmKSB7XG4gICAgICBsZXQge1xuICAgICAgICBzd2lwZXIsXG4gICAgICAgIHJ1bkNhbGxiYWNrcyxcbiAgICAgICAgZGlyZWN0aW9uLFxuICAgICAgICBzdGVwXG4gICAgICB9ID0gX3JlZjtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgYWN0aXZlSW5kZXgsXG4gICAgICAgIHByZXZpb3VzSW5kZXhcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICBsZXQgZGlyID0gZGlyZWN0aW9uO1xuXG4gICAgICBpZiAoIWRpcikge1xuICAgICAgICBpZiAoYWN0aXZlSW5kZXggPiBwcmV2aW91c0luZGV4KSBkaXIgPSAnbmV4dCc7ZWxzZSBpZiAoYWN0aXZlSW5kZXggPCBwcmV2aW91c0luZGV4KSBkaXIgPSAncHJldic7ZWxzZSBkaXIgPSAncmVzZXQnO1xuICAgICAgfVxuXG4gICAgICBzd2lwZXIuZW1pdChgdHJhbnNpdGlvbiR7c3RlcH1gKTtcblxuICAgICAgaWYgKHJ1bkNhbGxiYWNrcyAmJiBhY3RpdmVJbmRleCAhPT0gcHJldmlvdXNJbmRleCkge1xuICAgICAgICBpZiAoZGlyID09PSAncmVzZXQnKSB7XG4gICAgICAgICAgc3dpcGVyLmVtaXQoYHNsaWRlUmVzZXRUcmFuc2l0aW9uJHtzdGVwfWApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci5lbWl0KGBzbGlkZUNoYW5nZVRyYW5zaXRpb24ke3N0ZXB9YCk7XG5cbiAgICAgICAgaWYgKGRpciA9PT0gJ25leHQnKSB7XG4gICAgICAgICAgc3dpcGVyLmVtaXQoYHNsaWRlTmV4dFRyYW5zaXRpb24ke3N0ZXB9YCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3dpcGVyLmVtaXQoYHNsaWRlUHJldlRyYW5zaXRpb24ke3N0ZXB9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0cmFuc2l0aW9uU3RhcnQocnVuQ2FsbGJhY2tzLCBkaXJlY3Rpb24pIHtcbiAgICAgIGlmIChydW5DYWxsYmFja3MgPT09IHZvaWQgMCkge1xuICAgICAgICBydW5DYWxsYmFja3MgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3Qge1xuICAgICAgICBwYXJhbXNcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICBpZiAocGFyYW1zLmNzc01vZGUpIHJldHVybjtcblxuICAgICAgaWYgKHBhcmFtcy5hdXRvSGVpZ2h0KSB7XG4gICAgICAgIHN3aXBlci51cGRhdGVBdXRvSGVpZ2h0KCk7XG4gICAgICB9XG5cbiAgICAgIHRyYW5zaXRpb25FbWl0KHtcbiAgICAgICAgc3dpcGVyLFxuICAgICAgICBydW5DYWxsYmFja3MsXG4gICAgICAgIGRpcmVjdGlvbixcbiAgICAgICAgc3RlcDogJ1N0YXJ0J1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdHJhbnNpdGlvbkVuZChydW5DYWxsYmFja3MsIGRpcmVjdGlvbikge1xuICAgICAgaWYgKHJ1bkNhbGxiYWNrcyA9PT0gdm9pZCAwKSB7XG4gICAgICAgIHJ1bkNhbGxiYWNrcyA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHBhcmFtc1xuICAgICAgfSA9IHN3aXBlcjtcbiAgICAgIHN3aXBlci5hbmltYXRpbmcgPSBmYWxzZTtcbiAgICAgIGlmIChwYXJhbXMuY3NzTW9kZSkgcmV0dXJuO1xuICAgICAgc3dpcGVyLnNldFRyYW5zaXRpb24oMCk7XG4gICAgICB0cmFuc2l0aW9uRW1pdCh7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgcnVuQ2FsbGJhY2tzLFxuICAgICAgICBkaXJlY3Rpb24sXG4gICAgICAgIHN0ZXA6ICdFbmQnXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgdHJhbnNpdGlvbiA9IHtcbiAgICAgIHNldFRyYW5zaXRpb24sXG4gICAgICB0cmFuc2l0aW9uU3RhcnQsXG4gICAgICB0cmFuc2l0aW9uRW5kXG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIHNsaWRlVG8oaW5kZXgsIHNwZWVkLCBydW5DYWxsYmFja3MsIGludGVybmFsLCBpbml0aWFsKSB7XG4gICAgICBpZiAoaW5kZXggPT09IHZvaWQgMCkge1xuICAgICAgICBpbmRleCA9IDA7XG4gICAgICB9XG5cbiAgICAgIGlmIChzcGVlZCA9PT0gdm9pZCAwKSB7XG4gICAgICAgIHNwZWVkID0gdGhpcy5wYXJhbXMuc3BlZWQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChydW5DYWxsYmFja3MgPT09IHZvaWQgMCkge1xuICAgICAgICBydW5DYWxsYmFja3MgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIGluZGV4ICE9PSAnbnVtYmVyJyAmJiB0eXBlb2YgaW5kZXggIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlICdpbmRleCcgYXJndW1lbnQgY2Fubm90IGhhdmUgdHlwZSBvdGhlciB0aGFuICdudW1iZXInIG9yICdzdHJpbmcnLiBbJHt0eXBlb2YgaW5kZXh9XSBnaXZlbi5gKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBpbmRleCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBgaW5kZXhgIGFyZ3VtZW50IGNvbnZlcnRlZCBmcm9tIGBzdHJpbmdgIHRvIGBudW1iZXJgLlxuICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3QgaW5kZXhBc051bWJlciA9IHBhcnNlSW50KGluZGV4LCAxMCk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlIGBpbmRleGAgYXJndW1lbnQgaXMgYSB2YWxpZCBgbnVtYmVyYFxuICAgICAgICAgKiBhZnRlciBiZWluZyBjb252ZXJ0ZWQgZnJvbSB0aGUgYHN0cmluZ2AgdHlwZS5cbiAgICAgICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICAgICAqL1xuXG4gICAgICAgIGNvbnN0IGlzVmFsaWROdW1iZXIgPSBpc0Zpbml0ZShpbmRleEFzTnVtYmVyKTtcblxuICAgICAgICBpZiAoIWlzVmFsaWROdW1iZXIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBwYXNzZWQtaW4gJ2luZGV4JyAoc3RyaW5nKSBjb3VsZG4ndCBiZSBjb252ZXJ0ZWQgdG8gJ251bWJlcicuIFske2luZGV4fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH0gLy8gS25vd2luZyB0aGF0IHRoZSBjb252ZXJ0ZWQgYGluZGV4YCBpcyBhIHZhbGlkIG51bWJlcixcbiAgICAgICAgLy8gd2UgY2FuIHVwZGF0ZSB0aGUgb3JpZ2luYWwgYXJndW1lbnQncyB2YWx1ZS5cblxuXG4gICAgICAgIGluZGV4ID0gaW5kZXhBc051bWJlcjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIGxldCBzbGlkZUluZGV4ID0gaW5kZXg7XG4gICAgICBpZiAoc2xpZGVJbmRleCA8IDApIHNsaWRlSW5kZXggPSAwO1xuICAgICAgY29uc3Qge1xuICAgICAgICBwYXJhbXMsXG4gICAgICAgIHNuYXBHcmlkLFxuICAgICAgICBzbGlkZXNHcmlkLFxuICAgICAgICBwcmV2aW91c0luZGV4LFxuICAgICAgICBhY3RpdmVJbmRleCxcbiAgICAgICAgcnRsVHJhbnNsYXRlOiBydGwsXG4gICAgICAgIHdyYXBwZXJFbCxcbiAgICAgICAgZW5hYmxlZFxuICAgICAgfSA9IHN3aXBlcjtcblxuICAgICAgaWYgKHN3aXBlci5hbmltYXRpbmcgJiYgcGFyYW1zLnByZXZlbnRJbnRlcmFjdGlvbk9uVHJhbnNpdGlvbiB8fCAhZW5hYmxlZCAmJiAhaW50ZXJuYWwgJiYgIWluaXRpYWwpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBza2lwID0gTWF0aC5taW4oc3dpcGVyLnBhcmFtcy5zbGlkZXNQZXJHcm91cFNraXAsIHNsaWRlSW5kZXgpO1xuICAgICAgbGV0IHNuYXBJbmRleCA9IHNraXAgKyBNYXRoLmZsb29yKChzbGlkZUluZGV4IC0gc2tpcCkgLyBzd2lwZXIucGFyYW1zLnNsaWRlc1Blckdyb3VwKTtcbiAgICAgIGlmIChzbmFwSW5kZXggPj0gc25hcEdyaWQubGVuZ3RoKSBzbmFwSW5kZXggPSBzbmFwR3JpZC5sZW5ndGggLSAxO1xuXG4gICAgICBpZiAoKGFjdGl2ZUluZGV4IHx8IHBhcmFtcy5pbml0aWFsU2xpZGUgfHwgMCkgPT09IChwcmV2aW91c0luZGV4IHx8IDApICYmIHJ1bkNhbGxiYWNrcykge1xuICAgICAgICBzd2lwZXIuZW1pdCgnYmVmb3JlU2xpZGVDaGFuZ2VTdGFydCcpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0cmFuc2xhdGUgPSAtc25hcEdyaWRbc25hcEluZGV4XTsgLy8gVXBkYXRlIHByb2dyZXNzXG5cbiAgICAgIHN3aXBlci51cGRhdGVQcm9ncmVzcyh0cmFuc2xhdGUpOyAvLyBOb3JtYWxpemUgc2xpZGVJbmRleFxuXG4gICAgICBpZiAocGFyYW1zLm5vcm1hbGl6ZVNsaWRlSW5kZXgpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbGlkZXNHcmlkLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgY29uc3Qgbm9ybWFsaXplZFRyYW5zbGF0ZSA9IC1NYXRoLmZsb29yKHRyYW5zbGF0ZSAqIDEwMCk7XG4gICAgICAgICAgY29uc3Qgbm9ybWFsaXplZEdyaWQgPSBNYXRoLmZsb29yKHNsaWRlc0dyaWRbaV0gKiAxMDApO1xuICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRHcmlkTmV4dCA9IE1hdGguZmxvb3Ioc2xpZGVzR3JpZFtpICsgMV0gKiAxMDApO1xuXG4gICAgICAgICAgaWYgKHR5cGVvZiBzbGlkZXNHcmlkW2kgKyAxXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGlmIChub3JtYWxpemVkVHJhbnNsYXRlID49IG5vcm1hbGl6ZWRHcmlkICYmIG5vcm1hbGl6ZWRUcmFuc2xhdGUgPCBub3JtYWxpemVkR3JpZE5leHQgLSAobm9ybWFsaXplZEdyaWROZXh0IC0gbm9ybWFsaXplZEdyaWQpIC8gMikge1xuICAgICAgICAgICAgICBzbGlkZUluZGV4ID0gaTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobm9ybWFsaXplZFRyYW5zbGF0ZSA+PSBub3JtYWxpemVkR3JpZCAmJiBub3JtYWxpemVkVHJhbnNsYXRlIDwgbm9ybWFsaXplZEdyaWROZXh0KSB7XG4gICAgICAgICAgICAgIHNsaWRlSW5kZXggPSBpICsgMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKG5vcm1hbGl6ZWRUcmFuc2xhdGUgPj0gbm9ybWFsaXplZEdyaWQpIHtcbiAgICAgICAgICAgIHNsaWRlSW5kZXggPSBpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSAvLyBEaXJlY3Rpb25zIGxvY2tzXG5cblxuICAgICAgaWYgKHN3aXBlci5pbml0aWFsaXplZCAmJiBzbGlkZUluZGV4ICE9PSBhY3RpdmVJbmRleCkge1xuICAgICAgICBpZiAoIXN3aXBlci5hbGxvd1NsaWRlTmV4dCAmJiB0cmFuc2xhdGUgPCBzd2lwZXIudHJhbnNsYXRlICYmIHRyYW5zbGF0ZSA8IHN3aXBlci5taW5UcmFuc2xhdGUoKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghc3dpcGVyLmFsbG93U2xpZGVQcmV2ICYmIHRyYW5zbGF0ZSA+IHN3aXBlci50cmFuc2xhdGUgJiYgdHJhbnNsYXRlID4gc3dpcGVyLm1heFRyYW5zbGF0ZSgpKSB7XG4gICAgICAgICAgaWYgKChhY3RpdmVJbmRleCB8fCAwKSAhPT0gc2xpZGVJbmRleCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGxldCBkaXJlY3Rpb247XG4gICAgICBpZiAoc2xpZGVJbmRleCA+IGFjdGl2ZUluZGV4KSBkaXJlY3Rpb24gPSAnbmV4dCc7ZWxzZSBpZiAoc2xpZGVJbmRleCA8IGFjdGl2ZUluZGV4KSBkaXJlY3Rpb24gPSAncHJldic7ZWxzZSBkaXJlY3Rpb24gPSAncmVzZXQnOyAvLyBVcGRhdGUgSW5kZXhcblxuICAgICAgaWYgKHJ0bCAmJiAtdHJhbnNsYXRlID09PSBzd2lwZXIudHJhbnNsYXRlIHx8ICFydGwgJiYgdHJhbnNsYXRlID09PSBzd2lwZXIudHJhbnNsYXRlKSB7XG4gICAgICAgIHN3aXBlci51cGRhdGVBY3RpdmVJbmRleChzbGlkZUluZGV4KTsgLy8gVXBkYXRlIEhlaWdodFxuXG4gICAgICAgIGlmIChwYXJhbXMuYXV0b0hlaWdodCkge1xuICAgICAgICAgIHN3aXBlci51cGRhdGVBdXRvSGVpZ2h0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBzd2lwZXIudXBkYXRlU2xpZGVzQ2xhc3NlcygpO1xuXG4gICAgICAgIGlmIChwYXJhbXMuZWZmZWN0ICE9PSAnc2xpZGUnKSB7XG4gICAgICAgICAgc3dpcGVyLnNldFRyYW5zbGF0ZSh0cmFuc2xhdGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRpcmVjdGlvbiAhPT0gJ3Jlc2V0Jykge1xuICAgICAgICAgIHN3aXBlci50cmFuc2l0aW9uU3RhcnQocnVuQ2FsbGJhY2tzLCBkaXJlY3Rpb24pO1xuICAgICAgICAgIHN3aXBlci50cmFuc2l0aW9uRW5kKHJ1bkNhbGxiYWNrcywgZGlyZWN0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5jc3NNb2RlKSB7XG4gICAgICAgIGNvbnN0IGlzSCA9IHN3aXBlci5pc0hvcml6b250YWwoKTtcbiAgICAgICAgY29uc3QgdCA9IHJ0bCA/IHRyYW5zbGF0ZSA6IC10cmFuc2xhdGU7XG5cbiAgICAgICAgaWYgKHNwZWVkID09PSAwKSB7XG4gICAgICAgICAgY29uc3QgaXNWaXJ0dWFsID0gc3dpcGVyLnZpcnR1YWwgJiYgc3dpcGVyLnBhcmFtcy52aXJ0dWFsLmVuYWJsZWQ7XG5cbiAgICAgICAgICBpZiAoaXNWaXJ0dWFsKSB7XG4gICAgICAgICAgICBzd2lwZXIud3JhcHBlckVsLnN0eWxlLnNjcm9sbFNuYXBUeXBlID0gJ25vbmUnO1xuICAgICAgICAgICAgc3dpcGVyLl9pbW1lZGlhdGVWaXJ0dWFsID0gdHJ1ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB3cmFwcGVyRWxbaXNIID8gJ3Njcm9sbExlZnQnIDogJ3Njcm9sbFRvcCddID0gdDtcblxuICAgICAgICAgIGlmIChpc1ZpcnR1YWwpIHtcbiAgICAgICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICAgICAgICAgIHN3aXBlci53cmFwcGVyRWwuc3R5bGUuc2Nyb2xsU25hcFR5cGUgPSAnJztcbiAgICAgICAgICAgICAgc3dpcGVyLl9zd2lwZXJJbW1lZGlhdGVWaXJ0dWFsID0gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKCFzd2lwZXIuc3VwcG9ydC5zbW9vdGhTY3JvbGwpIHtcbiAgICAgICAgICAgIGFuaW1hdGVDU1NNb2RlU2Nyb2xsKHtcbiAgICAgICAgICAgICAgc3dpcGVyLFxuICAgICAgICAgICAgICB0YXJnZXRQb3NpdGlvbjogdCxcbiAgICAgICAgICAgICAgc2lkZTogaXNIID8gJ2xlZnQnIDogJ3RvcCdcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgd3JhcHBlckVsLnNjcm9sbFRvKHtcbiAgICAgICAgICAgIFtpc0ggPyAnbGVmdCcgOiAndG9wJ106IHQsXG4gICAgICAgICAgICBiZWhhdmlvcjogJ3Ntb290aCdcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICBzd2lwZXIuc2V0VHJhbnNpdGlvbihzcGVlZCk7XG4gICAgICBzd2lwZXIuc2V0VHJhbnNsYXRlKHRyYW5zbGF0ZSk7XG4gICAgICBzd2lwZXIudXBkYXRlQWN0aXZlSW5kZXgoc2xpZGVJbmRleCk7XG4gICAgICBzd2lwZXIudXBkYXRlU2xpZGVzQ2xhc3NlcygpO1xuICAgICAgc3dpcGVyLmVtaXQoJ2JlZm9yZVRyYW5zaXRpb25TdGFydCcsIHNwZWVkLCBpbnRlcm5hbCk7XG4gICAgICBzd2lwZXIudHJhbnNpdGlvblN0YXJ0KHJ1bkNhbGxiYWNrcywgZGlyZWN0aW9uKTtcblxuICAgICAgaWYgKHNwZWVkID09PSAwKSB7XG4gICAgICAgIHN3aXBlci50cmFuc2l0aW9uRW5kKHJ1bkNhbGxiYWNrcywgZGlyZWN0aW9uKTtcbiAgICAgIH0gZWxzZSBpZiAoIXN3aXBlci5hbmltYXRpbmcpIHtcbiAgICAgICAgc3dpcGVyLmFuaW1hdGluZyA9IHRydWU7XG5cbiAgICAgICAgaWYgKCFzd2lwZXIub25TbGlkZVRvV3JhcHBlclRyYW5zaXRpb25FbmQpIHtcbiAgICAgICAgICBzd2lwZXIub25TbGlkZVRvV3JhcHBlclRyYW5zaXRpb25FbmQgPSBmdW5jdGlvbiB0cmFuc2l0aW9uRW5kKGUpIHtcbiAgICAgICAgICAgIGlmICghc3dpcGVyIHx8IHN3aXBlci5kZXN0cm95ZWQpIHJldHVybjtcbiAgICAgICAgICAgIGlmIChlLnRhcmdldCAhPT0gdGhpcykgcmV0dXJuO1xuICAgICAgICAgICAgc3dpcGVyLiR3cmFwcGVyRWxbMF0ucmVtb3ZlRXZlbnRMaXN0ZW5lcigndHJhbnNpdGlvbmVuZCcsIHN3aXBlci5vblNsaWRlVG9XcmFwcGVyVHJhbnNpdGlvbkVuZCk7XG4gICAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbFswXS5yZW1vdmVFdmVudExpc3RlbmVyKCd3ZWJraXRUcmFuc2l0aW9uRW5kJywgc3dpcGVyLm9uU2xpZGVUb1dyYXBwZXJUcmFuc2l0aW9uRW5kKTtcbiAgICAgICAgICAgIHN3aXBlci5vblNsaWRlVG9XcmFwcGVyVHJhbnNpdGlvbkVuZCA9IG51bGw7XG4gICAgICAgICAgICBkZWxldGUgc3dpcGVyLm9uU2xpZGVUb1dyYXBwZXJUcmFuc2l0aW9uRW5kO1xuICAgICAgICAgICAgc3dpcGVyLnRyYW5zaXRpb25FbmQocnVuQ2FsbGJhY2tzLCBkaXJlY3Rpb24pO1xuICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbFswXS5hZGRFdmVudExpc3RlbmVyKCd0cmFuc2l0aW9uZW5kJywgc3dpcGVyLm9uU2xpZGVUb1dyYXBwZXJUcmFuc2l0aW9uRW5kKTtcbiAgICAgICAgc3dpcGVyLiR3cmFwcGVyRWxbMF0uYWRkRXZlbnRMaXN0ZW5lcignd2Via2l0VHJhbnNpdGlvbkVuZCcsIHN3aXBlci5vblNsaWRlVG9XcmFwcGVyVHJhbnNpdGlvbkVuZCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNsaWRlVG9Mb29wKGluZGV4LCBzcGVlZCwgcnVuQ2FsbGJhY2tzLCBpbnRlcm5hbCkge1xuICAgICAgaWYgKGluZGV4ID09PSB2b2lkIDApIHtcbiAgICAgICAgaW5kZXggPSAwO1xuICAgICAgfVxuXG4gICAgICBpZiAoc3BlZWQgPT09IHZvaWQgMCkge1xuICAgICAgICBzcGVlZCA9IHRoaXMucGFyYW1zLnNwZWVkO1xuICAgICAgfVxuXG4gICAgICBpZiAocnVuQ2FsbGJhY2tzID09PSB2b2lkIDApIHtcbiAgICAgICAgcnVuQ2FsbGJhY2tzID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIGxldCBuZXdJbmRleCA9IGluZGV4O1xuXG4gICAgICBpZiAoc3dpcGVyLnBhcmFtcy5sb29wKSB7XG4gICAgICAgIG5ld0luZGV4ICs9IHN3aXBlci5sb29wZWRTbGlkZXM7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzd2lwZXIuc2xpZGVUbyhuZXdJbmRleCwgc3BlZWQsIHJ1bkNhbGxiYWNrcywgaW50ZXJuYWwpO1xuICAgIH1cblxuICAgIC8qIGVzbGludCBuby11bnVzZWQtdmFyczogXCJvZmZcIiAqL1xuICAgIGZ1bmN0aW9uIHNsaWRlTmV4dChzcGVlZCwgcnVuQ2FsbGJhY2tzLCBpbnRlcm5hbCkge1xuICAgICAgaWYgKHNwZWVkID09PSB2b2lkIDApIHtcbiAgICAgICAgc3BlZWQgPSB0aGlzLnBhcmFtcy5zcGVlZDtcbiAgICAgIH1cblxuICAgICAgaWYgKHJ1bkNhbGxiYWNrcyA9PT0gdm9pZCAwKSB7XG4gICAgICAgIHJ1bkNhbGxiYWNrcyA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCB7XG4gICAgICAgIGFuaW1hdGluZyxcbiAgICAgICAgZW5hYmxlZCxcbiAgICAgICAgcGFyYW1zXG4gICAgICB9ID0gc3dpcGVyO1xuICAgICAgaWYgKCFlbmFibGVkKSByZXR1cm4gc3dpcGVyO1xuICAgICAgbGV0IHBlckdyb3VwID0gcGFyYW1zLnNsaWRlc1Blckdyb3VwO1xuXG4gICAgICBpZiAocGFyYW1zLnNsaWRlc1BlclZpZXcgPT09ICdhdXRvJyAmJiBwYXJhbXMuc2xpZGVzUGVyR3JvdXAgPT09IDEgJiYgcGFyYW1zLnNsaWRlc1Blckdyb3VwQXV0bykge1xuICAgICAgICBwZXJHcm91cCA9IE1hdGgubWF4KHN3aXBlci5zbGlkZXNQZXJWaWV3RHluYW1pYygnY3VycmVudCcsIHRydWUpLCAxKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaW5jcmVtZW50ID0gc3dpcGVyLmFjdGl2ZUluZGV4IDwgcGFyYW1zLnNsaWRlc1Blckdyb3VwU2tpcCA/IDEgOiBwZXJHcm91cDtcblxuICAgICAgaWYgKHBhcmFtcy5sb29wKSB7XG4gICAgICAgIGlmIChhbmltYXRpbmcgJiYgcGFyYW1zLmxvb3BQcmV2ZW50c1NsaWRlKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHN3aXBlci5sb29wRml4KCk7IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuXG4gICAgICAgIHN3aXBlci5fY2xpZW50TGVmdCA9IHN3aXBlci4kd3JhcHBlckVsWzBdLmNsaWVudExlZnQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMucmV3aW5kICYmIHN3aXBlci5pc0VuZCkge1xuICAgICAgICByZXR1cm4gc3dpcGVyLnNsaWRlVG8oMCwgc3BlZWQsIHJ1bkNhbGxiYWNrcywgaW50ZXJuYWwpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc3dpcGVyLnNsaWRlVG8oc3dpcGVyLmFjdGl2ZUluZGV4ICsgaW5jcmVtZW50LCBzcGVlZCwgcnVuQ2FsbGJhY2tzLCBpbnRlcm5hbCk7XG4gICAgfVxuXG4gICAgLyogZXNsaW50IG5vLXVudXNlZC12YXJzOiBcIm9mZlwiICovXG4gICAgZnVuY3Rpb24gc2xpZGVQcmV2KHNwZWVkLCBydW5DYWxsYmFja3MsIGludGVybmFsKSB7XG4gICAgICBpZiAoc3BlZWQgPT09IHZvaWQgMCkge1xuICAgICAgICBzcGVlZCA9IHRoaXMucGFyYW1zLnNwZWVkO1xuICAgICAgfVxuXG4gICAgICBpZiAocnVuQ2FsbGJhY2tzID09PSB2b2lkIDApIHtcbiAgICAgICAgcnVuQ2FsbGJhY2tzID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgcGFyYW1zLFxuICAgICAgICBhbmltYXRpbmcsXG4gICAgICAgIHNuYXBHcmlkLFxuICAgICAgICBzbGlkZXNHcmlkLFxuICAgICAgICBydGxUcmFuc2xhdGUsXG4gICAgICAgIGVuYWJsZWRcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICBpZiAoIWVuYWJsZWQpIHJldHVybiBzd2lwZXI7XG5cbiAgICAgIGlmIChwYXJhbXMubG9vcCkge1xuICAgICAgICBpZiAoYW5pbWF0aW5nICYmIHBhcmFtcy5sb29wUHJldmVudHNTbGlkZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBzd2lwZXIubG9vcEZpeCgpOyAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcblxuICAgICAgICBzd2lwZXIuX2NsaWVudExlZnQgPSBzd2lwZXIuJHdyYXBwZXJFbFswXS5jbGllbnRMZWZ0O1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0cmFuc2xhdGUgPSBydGxUcmFuc2xhdGUgPyBzd2lwZXIudHJhbnNsYXRlIDogLXN3aXBlci50cmFuc2xhdGU7XG5cbiAgICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZSh2YWwpIHtcbiAgICAgICAgaWYgKHZhbCA8IDApIHJldHVybiAtTWF0aC5mbG9vcihNYXRoLmFicyh2YWwpKTtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IodmFsKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgbm9ybWFsaXplZFRyYW5zbGF0ZSA9IG5vcm1hbGl6ZSh0cmFuc2xhdGUpO1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFNuYXBHcmlkID0gc25hcEdyaWQubWFwKHZhbCA9PiBub3JtYWxpemUodmFsKSk7XG4gICAgICBsZXQgcHJldlNuYXAgPSBzbmFwR3JpZFtub3JtYWxpemVkU25hcEdyaWQuaW5kZXhPZihub3JtYWxpemVkVHJhbnNsYXRlKSAtIDFdO1xuXG4gICAgICBpZiAodHlwZW9mIHByZXZTbmFwID09PSAndW5kZWZpbmVkJyAmJiBwYXJhbXMuY3NzTW9kZSkge1xuICAgICAgICBsZXQgcHJldlNuYXBJbmRleDtcbiAgICAgICAgc25hcEdyaWQuZm9yRWFjaCgoc25hcCwgc25hcEluZGV4KSA9PiB7XG4gICAgICAgICAgaWYgKG5vcm1hbGl6ZWRUcmFuc2xhdGUgPj0gc25hcCkge1xuICAgICAgICAgICAgLy8gcHJldlNuYXAgPSBzbmFwO1xuICAgICAgICAgICAgcHJldlNuYXBJbmRleCA9IHNuYXBJbmRleDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlb2YgcHJldlNuYXBJbmRleCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBwcmV2U25hcCA9IHNuYXBHcmlkW3ByZXZTbmFwSW5kZXggPiAwID8gcHJldlNuYXBJbmRleCAtIDEgOiBwcmV2U25hcEluZGV4XTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBsZXQgcHJldkluZGV4ID0gMDtcblxuICAgICAgaWYgKHR5cGVvZiBwcmV2U25hcCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcHJldkluZGV4ID0gc2xpZGVzR3JpZC5pbmRleE9mKHByZXZTbmFwKTtcbiAgICAgICAgaWYgKHByZXZJbmRleCA8IDApIHByZXZJbmRleCA9IHN3aXBlci5hY3RpdmVJbmRleCAtIDE7XG5cbiAgICAgICAgaWYgKHBhcmFtcy5zbGlkZXNQZXJWaWV3ID09PSAnYXV0bycgJiYgcGFyYW1zLnNsaWRlc1Blckdyb3VwID09PSAxICYmIHBhcmFtcy5zbGlkZXNQZXJHcm91cEF1dG8pIHtcbiAgICAgICAgICBwcmV2SW5kZXggPSBwcmV2SW5kZXggLSBzd2lwZXIuc2xpZGVzUGVyVmlld0R5bmFtaWMoJ3ByZXZpb3VzJywgdHJ1ZSkgKyAxO1xuICAgICAgICAgIHByZXZJbmRleCA9IE1hdGgubWF4KHByZXZJbmRleCwgMCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5yZXdpbmQgJiYgc3dpcGVyLmlzQmVnaW5uaW5nKSB7XG4gICAgICAgIGNvbnN0IGxhc3RJbmRleCA9IHN3aXBlci5wYXJhbXMudmlydHVhbCAmJiBzd2lwZXIucGFyYW1zLnZpcnR1YWwuZW5hYmxlZCAmJiBzd2lwZXIudmlydHVhbCA/IHN3aXBlci52aXJ0dWFsLnNsaWRlcy5sZW5ndGggLSAxIDogc3dpcGVyLnNsaWRlcy5sZW5ndGggLSAxO1xuICAgICAgICByZXR1cm4gc3dpcGVyLnNsaWRlVG8obGFzdEluZGV4LCBzcGVlZCwgcnVuQ2FsbGJhY2tzLCBpbnRlcm5hbCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzd2lwZXIuc2xpZGVUbyhwcmV2SW5kZXgsIHNwZWVkLCBydW5DYWxsYmFja3MsIGludGVybmFsKTtcbiAgICB9XG5cbiAgICAvKiBlc2xpbnQgbm8tdW51c2VkLXZhcnM6IFwib2ZmXCIgKi9cbiAgICBmdW5jdGlvbiBzbGlkZVJlc2V0KHNwZWVkLCBydW5DYWxsYmFja3MsIGludGVybmFsKSB7XG4gICAgICBpZiAoc3BlZWQgPT09IHZvaWQgMCkge1xuICAgICAgICBzcGVlZCA9IHRoaXMucGFyYW1zLnNwZWVkO1xuICAgICAgfVxuXG4gICAgICBpZiAocnVuQ2FsbGJhY2tzID09PSB2b2lkIDApIHtcbiAgICAgICAgcnVuQ2FsbGJhY2tzID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIHJldHVybiBzd2lwZXIuc2xpZGVUbyhzd2lwZXIuYWN0aXZlSW5kZXgsIHNwZWVkLCBydW5DYWxsYmFja3MsIGludGVybmFsKTtcbiAgICB9XG5cbiAgICAvKiBlc2xpbnQgbm8tdW51c2VkLXZhcnM6IFwib2ZmXCIgKi9cbiAgICBmdW5jdGlvbiBzbGlkZVRvQ2xvc2VzdChzcGVlZCwgcnVuQ2FsbGJhY2tzLCBpbnRlcm5hbCwgdGhyZXNob2xkKSB7XG4gICAgICBpZiAoc3BlZWQgPT09IHZvaWQgMCkge1xuICAgICAgICBzcGVlZCA9IHRoaXMucGFyYW1zLnNwZWVkO1xuICAgICAgfVxuXG4gICAgICBpZiAocnVuQ2FsbGJhY2tzID09PSB2b2lkIDApIHtcbiAgICAgICAgcnVuQ2FsbGJhY2tzID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRocmVzaG9sZCA9PT0gdm9pZCAwKSB7XG4gICAgICAgIHRocmVzaG9sZCA9IDAuNTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIGxldCBpbmRleCA9IHN3aXBlci5hY3RpdmVJbmRleDtcbiAgICAgIGNvbnN0IHNraXAgPSBNYXRoLm1pbihzd2lwZXIucGFyYW1zLnNsaWRlc1Blckdyb3VwU2tpcCwgaW5kZXgpO1xuICAgICAgY29uc3Qgc25hcEluZGV4ID0gc2tpcCArIE1hdGguZmxvb3IoKGluZGV4IC0gc2tpcCkgLyBzd2lwZXIucGFyYW1zLnNsaWRlc1Blckdyb3VwKTtcbiAgICAgIGNvbnN0IHRyYW5zbGF0ZSA9IHN3aXBlci5ydGxUcmFuc2xhdGUgPyBzd2lwZXIudHJhbnNsYXRlIDogLXN3aXBlci50cmFuc2xhdGU7XG5cbiAgICAgIGlmICh0cmFuc2xhdGUgPj0gc3dpcGVyLnNuYXBHcmlkW3NuYXBJbmRleF0pIHtcbiAgICAgICAgLy8gVGhlIGN1cnJlbnQgdHJhbnNsYXRlIGlzIG9uIG9yIGFmdGVyIHRoZSBjdXJyZW50IHNuYXAgaW5kZXgsIHNvIHRoZSBjaG9pY2VcbiAgICAgICAgLy8gaXMgYmV0d2VlbiB0aGUgY3VycmVudCBpbmRleCBhbmQgdGhlIG9uZSBhZnRlciBpdC5cbiAgICAgICAgY29uc3QgY3VycmVudFNuYXAgPSBzd2lwZXIuc25hcEdyaWRbc25hcEluZGV4XTtcbiAgICAgICAgY29uc3QgbmV4dFNuYXAgPSBzd2lwZXIuc25hcEdyaWRbc25hcEluZGV4ICsgMV07XG5cbiAgICAgICAgaWYgKHRyYW5zbGF0ZSAtIGN1cnJlbnRTbmFwID4gKG5leHRTbmFwIC0gY3VycmVudFNuYXApICogdGhyZXNob2xkKSB7XG4gICAgICAgICAgaW5kZXggKz0gc3dpcGVyLnBhcmFtcy5zbGlkZXNQZXJHcm91cDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVGhlIGN1cnJlbnQgdHJhbnNsYXRlIGlzIGJlZm9yZSB0aGUgY3VycmVudCBzbmFwIGluZGV4LCBzbyB0aGUgY2hvaWNlXG4gICAgICAgIC8vIGlzIGJldHdlZW4gdGhlIGN1cnJlbnQgaW5kZXggYW5kIHRoZSBvbmUgYmVmb3JlIGl0LlxuICAgICAgICBjb25zdCBwcmV2U25hcCA9IHN3aXBlci5zbmFwR3JpZFtzbmFwSW5kZXggLSAxXTtcbiAgICAgICAgY29uc3QgY3VycmVudFNuYXAgPSBzd2lwZXIuc25hcEdyaWRbc25hcEluZGV4XTtcblxuICAgICAgICBpZiAodHJhbnNsYXRlIC0gcHJldlNuYXAgPD0gKGN1cnJlbnRTbmFwIC0gcHJldlNuYXApICogdGhyZXNob2xkKSB7XG4gICAgICAgICAgaW5kZXggLT0gc3dpcGVyLnBhcmFtcy5zbGlkZXNQZXJHcm91cDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpbmRleCA9IE1hdGgubWF4KGluZGV4LCAwKTtcbiAgICAgIGluZGV4ID0gTWF0aC5taW4oaW5kZXgsIHN3aXBlci5zbGlkZXNHcmlkLmxlbmd0aCAtIDEpO1xuICAgICAgcmV0dXJuIHN3aXBlci5zbGlkZVRvKGluZGV4LCBzcGVlZCwgcnVuQ2FsbGJhY2tzLCBpbnRlcm5hbCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2xpZGVUb0NsaWNrZWRTbGlkZSgpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHBhcmFtcyxcbiAgICAgICAgJHdyYXBwZXJFbFxuICAgICAgfSA9IHN3aXBlcjtcbiAgICAgIGNvbnN0IHNsaWRlc1BlclZpZXcgPSBwYXJhbXMuc2xpZGVzUGVyVmlldyA9PT0gJ2F1dG8nID8gc3dpcGVyLnNsaWRlc1BlclZpZXdEeW5hbWljKCkgOiBwYXJhbXMuc2xpZGVzUGVyVmlldztcbiAgICAgIGxldCBzbGlkZVRvSW5kZXggPSBzd2lwZXIuY2xpY2tlZEluZGV4O1xuICAgICAgbGV0IHJlYWxJbmRleDtcblxuICAgICAgaWYgKHBhcmFtcy5sb29wKSB7XG4gICAgICAgIGlmIChzd2lwZXIuYW5pbWF0aW5nKSByZXR1cm47XG4gICAgICAgIHJlYWxJbmRleCA9IHBhcnNlSW50KCQoc3dpcGVyLmNsaWNrZWRTbGlkZSkuYXR0cignZGF0YS1zd2lwZXItc2xpZGUtaW5kZXgnKSwgMTApO1xuXG4gICAgICAgIGlmIChwYXJhbXMuY2VudGVyZWRTbGlkZXMpIHtcbiAgICAgICAgICBpZiAoc2xpZGVUb0luZGV4IDwgc3dpcGVyLmxvb3BlZFNsaWRlcyAtIHNsaWRlc1BlclZpZXcgLyAyIHx8IHNsaWRlVG9JbmRleCA+IHN3aXBlci5zbGlkZXMubGVuZ3RoIC0gc3dpcGVyLmxvb3BlZFNsaWRlcyArIHNsaWRlc1BlclZpZXcgLyAyKSB7XG4gICAgICAgICAgICBzd2lwZXIubG9vcEZpeCgpO1xuICAgICAgICAgICAgc2xpZGVUb0luZGV4ID0gJHdyYXBwZXJFbC5jaGlsZHJlbihgLiR7cGFyYW1zLnNsaWRlQ2xhc3N9W2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4PVwiJHtyZWFsSW5kZXh9XCJdOm5vdCguJHtwYXJhbXMuc2xpZGVEdXBsaWNhdGVDbGFzc30pYCkuZXEoMCkuaW5kZXgoKTtcbiAgICAgICAgICAgIG5leHRUaWNrKCgpID0+IHtcbiAgICAgICAgICAgICAgc3dpcGVyLnNsaWRlVG8oc2xpZGVUb0luZGV4KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzd2lwZXIuc2xpZGVUbyhzbGlkZVRvSW5kZXgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChzbGlkZVRvSW5kZXggPiBzd2lwZXIuc2xpZGVzLmxlbmd0aCAtIHNsaWRlc1BlclZpZXcpIHtcbiAgICAgICAgICBzd2lwZXIubG9vcEZpeCgpO1xuICAgICAgICAgIHNsaWRlVG9JbmRleCA9ICR3cmFwcGVyRWwuY2hpbGRyZW4oYC4ke3BhcmFtcy5zbGlkZUNsYXNzfVtkYXRhLXN3aXBlci1zbGlkZS1pbmRleD1cIiR7cmVhbEluZGV4fVwiXTpub3QoLiR7cGFyYW1zLnNsaWRlRHVwbGljYXRlQ2xhc3N9KWApLmVxKDApLmluZGV4KCk7XG4gICAgICAgICAgbmV4dFRpY2soKCkgPT4ge1xuICAgICAgICAgICAgc3dpcGVyLnNsaWRlVG8oc2xpZGVUb0luZGV4KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzd2lwZXIuc2xpZGVUbyhzbGlkZVRvSW5kZXgpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzd2lwZXIuc2xpZGVUbyhzbGlkZVRvSW5kZXgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBzbGlkZSA9IHtcbiAgICAgIHNsaWRlVG8sXG4gICAgICBzbGlkZVRvTG9vcCxcbiAgICAgIHNsaWRlTmV4dCxcbiAgICAgIHNsaWRlUHJldixcbiAgICAgIHNsaWRlUmVzZXQsXG4gICAgICBzbGlkZVRvQ2xvc2VzdCxcbiAgICAgIHNsaWRlVG9DbGlja2VkU2xpZGVcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9vcENyZWF0ZSgpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCBkb2N1bWVudCA9IGdldERvY3VtZW50KCk7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHBhcmFtcyxcbiAgICAgICAgJHdyYXBwZXJFbFxuICAgICAgfSA9IHN3aXBlcjsgLy8gUmVtb3ZlIGR1cGxpY2F0ZWQgc2xpZGVzXG5cbiAgICAgIGNvbnN0ICRzZWxlY3RvciA9ICR3cmFwcGVyRWwuY2hpbGRyZW4oKS5sZW5ndGggPiAwID8gJCgkd3JhcHBlckVsLmNoaWxkcmVuKClbMF0ucGFyZW50Tm9kZSkgOiAkd3JhcHBlckVsO1xuICAgICAgJHNlbGVjdG9yLmNoaWxkcmVuKGAuJHtwYXJhbXMuc2xpZGVDbGFzc30uJHtwYXJhbXMuc2xpZGVEdXBsaWNhdGVDbGFzc31gKS5yZW1vdmUoKTtcbiAgICAgIGxldCBzbGlkZXMgPSAkc2VsZWN0b3IuY2hpbGRyZW4oYC4ke3BhcmFtcy5zbGlkZUNsYXNzfWApO1xuXG4gICAgICBpZiAocGFyYW1zLmxvb3BGaWxsR3JvdXBXaXRoQmxhbmspIHtcbiAgICAgICAgY29uc3QgYmxhbmtTbGlkZXNOdW0gPSBwYXJhbXMuc2xpZGVzUGVyR3JvdXAgLSBzbGlkZXMubGVuZ3RoICUgcGFyYW1zLnNsaWRlc1Blckdyb3VwO1xuXG4gICAgICAgIGlmIChibGFua1NsaWRlc051bSAhPT0gcGFyYW1zLnNsaWRlc1Blckdyb3VwKSB7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBibGFua1NsaWRlc051bTsgaSArPSAxKSB7XG4gICAgICAgICAgICBjb25zdCBibGFua05vZGUgPSAkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpKS5hZGRDbGFzcyhgJHtwYXJhbXMuc2xpZGVDbGFzc30gJHtwYXJhbXMuc2xpZGVCbGFua0NsYXNzfWApO1xuICAgICAgICAgICAgJHNlbGVjdG9yLmFwcGVuZChibGFua05vZGUpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHNsaWRlcyA9ICRzZWxlY3Rvci5jaGlsZHJlbihgLiR7cGFyYW1zLnNsaWRlQ2xhc3N9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5zbGlkZXNQZXJWaWV3ID09PSAnYXV0bycgJiYgIXBhcmFtcy5sb29wZWRTbGlkZXMpIHBhcmFtcy5sb29wZWRTbGlkZXMgPSBzbGlkZXMubGVuZ3RoO1xuICAgICAgc3dpcGVyLmxvb3BlZFNsaWRlcyA9IE1hdGguY2VpbChwYXJzZUZsb2F0KHBhcmFtcy5sb29wZWRTbGlkZXMgfHwgcGFyYW1zLnNsaWRlc1BlclZpZXcsIDEwKSk7XG4gICAgICBzd2lwZXIubG9vcGVkU2xpZGVzICs9IHBhcmFtcy5sb29wQWRkaXRpb25hbFNsaWRlcztcblxuICAgICAgaWYgKHN3aXBlci5sb29wZWRTbGlkZXMgPiBzbGlkZXMubGVuZ3RoKSB7XG4gICAgICAgIHN3aXBlci5sb29wZWRTbGlkZXMgPSBzbGlkZXMubGVuZ3RoO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwcmVwZW5kU2xpZGVzID0gW107XG4gICAgICBjb25zdCBhcHBlbmRTbGlkZXMgPSBbXTtcbiAgICAgIHNsaWRlcy5lYWNoKChlbCwgaW5kZXgpID0+IHtcbiAgICAgICAgY29uc3Qgc2xpZGUgPSAkKGVsKTtcblxuICAgICAgICBpZiAoaW5kZXggPCBzd2lwZXIubG9vcGVkU2xpZGVzKSB7XG4gICAgICAgICAgYXBwZW5kU2xpZGVzLnB1c2goZWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGluZGV4IDwgc2xpZGVzLmxlbmd0aCAmJiBpbmRleCA+PSBzbGlkZXMubGVuZ3RoIC0gc3dpcGVyLmxvb3BlZFNsaWRlcykge1xuICAgICAgICAgIHByZXBlbmRTbGlkZXMucHVzaChlbCk7XG4gICAgICAgIH1cblxuICAgICAgICBzbGlkZS5hdHRyKCdkYXRhLXN3aXBlci1zbGlkZS1pbmRleCcsIGluZGV4KTtcbiAgICAgIH0pO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFwcGVuZFNsaWRlcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAkc2VsZWN0b3IuYXBwZW5kKCQoYXBwZW5kU2xpZGVzW2ldLmNsb25lTm9kZSh0cnVlKSkuYWRkQ2xhc3MocGFyYW1zLnNsaWRlRHVwbGljYXRlQ2xhc3MpKTtcbiAgICAgIH1cblxuICAgICAgZm9yIChsZXQgaSA9IHByZXBlbmRTbGlkZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpIC09IDEpIHtcbiAgICAgICAgJHNlbGVjdG9yLnByZXBlbmQoJChwcmVwZW5kU2xpZGVzW2ldLmNsb25lTm9kZSh0cnVlKSkuYWRkQ2xhc3MocGFyYW1zLnNsaWRlRHVwbGljYXRlQ2xhc3MpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb29wRml4KCkge1xuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIHN3aXBlci5lbWl0KCdiZWZvcmVMb29wRml4Jyk7XG4gICAgICBjb25zdCB7XG4gICAgICAgIGFjdGl2ZUluZGV4LFxuICAgICAgICBzbGlkZXMsXG4gICAgICAgIGxvb3BlZFNsaWRlcyxcbiAgICAgICAgYWxsb3dTbGlkZVByZXYsXG4gICAgICAgIGFsbG93U2xpZGVOZXh0LFxuICAgICAgICBzbmFwR3JpZCxcbiAgICAgICAgcnRsVHJhbnNsYXRlOiBydGxcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICBsZXQgbmV3SW5kZXg7XG4gICAgICBzd2lwZXIuYWxsb3dTbGlkZVByZXYgPSB0cnVlO1xuICAgICAgc3dpcGVyLmFsbG93U2xpZGVOZXh0ID0gdHJ1ZTtcbiAgICAgIGNvbnN0IHNuYXBUcmFuc2xhdGUgPSAtc25hcEdyaWRbYWN0aXZlSW5kZXhdO1xuICAgICAgY29uc3QgZGlmZiA9IHNuYXBUcmFuc2xhdGUgLSBzd2lwZXIuZ2V0VHJhbnNsYXRlKCk7IC8vIEZpeCBGb3IgTmVnYXRpdmUgT3ZlcnNsaWRpbmdcblxuICAgICAgaWYgKGFjdGl2ZUluZGV4IDwgbG9vcGVkU2xpZGVzKSB7XG4gICAgICAgIG5ld0luZGV4ID0gc2xpZGVzLmxlbmd0aCAtIGxvb3BlZFNsaWRlcyAqIDMgKyBhY3RpdmVJbmRleDtcbiAgICAgICAgbmV3SW5kZXggKz0gbG9vcGVkU2xpZGVzO1xuICAgICAgICBjb25zdCBzbGlkZUNoYW5nZWQgPSBzd2lwZXIuc2xpZGVUbyhuZXdJbmRleCwgMCwgZmFsc2UsIHRydWUpO1xuXG4gICAgICAgIGlmIChzbGlkZUNoYW5nZWQgJiYgZGlmZiAhPT0gMCkge1xuICAgICAgICAgIHN3aXBlci5zZXRUcmFuc2xhdGUoKHJ0bCA/IC1zd2lwZXIudHJhbnNsYXRlIDogc3dpcGVyLnRyYW5zbGF0ZSkgLSBkaWZmKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChhY3RpdmVJbmRleCA+PSBzbGlkZXMubGVuZ3RoIC0gbG9vcGVkU2xpZGVzKSB7XG4gICAgICAgIC8vIEZpeCBGb3IgUG9zaXRpdmUgT3ZlcnNsaWRpbmdcbiAgICAgICAgbmV3SW5kZXggPSAtc2xpZGVzLmxlbmd0aCArIGFjdGl2ZUluZGV4ICsgbG9vcGVkU2xpZGVzO1xuICAgICAgICBuZXdJbmRleCArPSBsb29wZWRTbGlkZXM7XG4gICAgICAgIGNvbnN0IHNsaWRlQ2hhbmdlZCA9IHN3aXBlci5zbGlkZVRvKG5ld0luZGV4LCAwLCBmYWxzZSwgdHJ1ZSk7XG5cbiAgICAgICAgaWYgKHNsaWRlQ2hhbmdlZCAmJiBkaWZmICE9PSAwKSB7XG4gICAgICAgICAgc3dpcGVyLnNldFRyYW5zbGF0ZSgocnRsID8gLXN3aXBlci50cmFuc2xhdGUgOiBzd2lwZXIudHJhbnNsYXRlKSAtIGRpZmYpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHN3aXBlci5hbGxvd1NsaWRlUHJldiA9IGFsbG93U2xpZGVQcmV2O1xuICAgICAgc3dpcGVyLmFsbG93U2xpZGVOZXh0ID0gYWxsb3dTbGlkZU5leHQ7XG4gICAgICBzd2lwZXIuZW1pdCgnbG9vcEZpeCcpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvb3BEZXN0cm95KCkge1xuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgJHdyYXBwZXJFbCxcbiAgICAgICAgcGFyYW1zLFxuICAgICAgICBzbGlkZXNcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICAkd3JhcHBlckVsLmNoaWxkcmVuKGAuJHtwYXJhbXMuc2xpZGVDbGFzc30uJHtwYXJhbXMuc2xpZGVEdXBsaWNhdGVDbGFzc30sLiR7cGFyYW1zLnNsaWRlQ2xhc3N9LiR7cGFyYW1zLnNsaWRlQmxhbmtDbGFzc31gKS5yZW1vdmUoKTtcbiAgICAgIHNsaWRlcy5yZW1vdmVBdHRyKCdkYXRhLXN3aXBlci1zbGlkZS1pbmRleCcpO1xuICAgIH1cblxuICAgIHZhciBsb29wID0ge1xuICAgICAgbG9vcENyZWF0ZSxcbiAgICAgIGxvb3BGaXgsXG4gICAgICBsb29wRGVzdHJveVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBzZXRHcmFiQ3Vyc29yKG1vdmluZykge1xuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIGlmIChzd2lwZXIuc3VwcG9ydC50b3VjaCB8fCAhc3dpcGVyLnBhcmFtcy5zaW11bGF0ZVRvdWNoIHx8IHN3aXBlci5wYXJhbXMud2F0Y2hPdmVyZmxvdyAmJiBzd2lwZXIuaXNMb2NrZWQgfHwgc3dpcGVyLnBhcmFtcy5jc3NNb2RlKSByZXR1cm47XG4gICAgICBjb25zdCBlbCA9IHN3aXBlci5wYXJhbXMudG91Y2hFdmVudHNUYXJnZXQgPT09ICdjb250YWluZXInID8gc3dpcGVyLmVsIDogc3dpcGVyLndyYXBwZXJFbDtcbiAgICAgIGVsLnN0eWxlLmN1cnNvciA9ICdtb3ZlJztcbiAgICAgIGVsLnN0eWxlLmN1cnNvciA9IG1vdmluZyA/ICctd2Via2l0LWdyYWJiaW5nJyA6ICctd2Via2l0LWdyYWInO1xuICAgICAgZWwuc3R5bGUuY3Vyc29yID0gbW92aW5nID8gJy1tb3otZ3JhYmJpbicgOiAnLW1vei1ncmFiJztcbiAgICAgIGVsLnN0eWxlLmN1cnNvciA9IG1vdmluZyA/ICdncmFiYmluZycgOiAnZ3JhYic7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdW5zZXRHcmFiQ3Vyc29yKCkge1xuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcblxuICAgICAgaWYgKHN3aXBlci5zdXBwb3J0LnRvdWNoIHx8IHN3aXBlci5wYXJhbXMud2F0Y2hPdmVyZmxvdyAmJiBzd2lwZXIuaXNMb2NrZWQgfHwgc3dpcGVyLnBhcmFtcy5jc3NNb2RlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgc3dpcGVyW3N3aXBlci5wYXJhbXMudG91Y2hFdmVudHNUYXJnZXQgPT09ICdjb250YWluZXInID8gJ2VsJyA6ICd3cmFwcGVyRWwnXS5zdHlsZS5jdXJzb3IgPSAnJztcbiAgICB9XG5cbiAgICB2YXIgZ3JhYkN1cnNvciA9IHtcbiAgICAgIHNldEdyYWJDdXJzb3IsXG4gICAgICB1bnNldEdyYWJDdXJzb3JcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gY2xvc2VzdEVsZW1lbnQoc2VsZWN0b3IsIGJhc2UpIHtcbiAgICAgIGlmIChiYXNlID09PSB2b2lkIDApIHtcbiAgICAgICAgYmFzZSA9IHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIF9fY2xvc2VzdEZyb20oZWwpIHtcbiAgICAgICAgaWYgKCFlbCB8fCBlbCA9PT0gZ2V0RG9jdW1lbnQoKSB8fCBlbCA9PT0gZ2V0V2luZG93KCkpIHJldHVybiBudWxsO1xuICAgICAgICBpZiAoZWwuYXNzaWduZWRTbG90KSBlbCA9IGVsLmFzc2lnbmVkU2xvdDtcbiAgICAgICAgY29uc3QgZm91bmQgPSBlbC5jbG9zZXN0KHNlbGVjdG9yKTtcbiAgICAgICAgcmV0dXJuIGZvdW5kIHx8IF9fY2xvc2VzdEZyb20oZWwuZ2V0Um9vdE5vZGUoKS5ob3N0KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9fY2xvc2VzdEZyb20oYmFzZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25Ub3VjaFN0YXJ0KGV2ZW50KSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3QgZG9jdW1lbnQgPSBnZXREb2N1bWVudCgpO1xuICAgICAgY29uc3Qgd2luZG93ID0gZ2V0V2luZG93KCk7XG4gICAgICBjb25zdCBkYXRhID0gc3dpcGVyLnRvdWNoRXZlbnRzRGF0YTtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgcGFyYW1zLFxuICAgICAgICB0b3VjaGVzLFxuICAgICAgICBlbmFibGVkXG4gICAgICB9ID0gc3dpcGVyO1xuICAgICAgaWYgKCFlbmFibGVkKSByZXR1cm47XG5cbiAgICAgIGlmIChzd2lwZXIuYW5pbWF0aW5nICYmIHBhcmFtcy5wcmV2ZW50SW50ZXJhY3Rpb25PblRyYW5zaXRpb24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXN3aXBlci5hbmltYXRpbmcgJiYgcGFyYW1zLmNzc01vZGUgJiYgcGFyYW1zLmxvb3ApIHtcbiAgICAgICAgc3dpcGVyLmxvb3BGaXgoKTtcbiAgICAgIH1cblxuICAgICAgbGV0IGUgPSBldmVudDtcbiAgICAgIGlmIChlLm9yaWdpbmFsRXZlbnQpIGUgPSBlLm9yaWdpbmFsRXZlbnQ7XG4gICAgICBsZXQgJHRhcmdldEVsID0gJChlLnRhcmdldCk7XG5cbiAgICAgIGlmIChwYXJhbXMudG91Y2hFdmVudHNUYXJnZXQgPT09ICd3cmFwcGVyJykge1xuICAgICAgICBpZiAoISR0YXJnZXRFbC5jbG9zZXN0KHN3aXBlci53cmFwcGVyRWwpLmxlbmd0aCkgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBkYXRhLmlzVG91Y2hFdmVudCA9IGUudHlwZSA9PT0gJ3RvdWNoc3RhcnQnO1xuICAgICAgaWYgKCFkYXRhLmlzVG91Y2hFdmVudCAmJiAnd2hpY2gnIGluIGUgJiYgZS53aGljaCA9PT0gMykgcmV0dXJuO1xuICAgICAgaWYgKCFkYXRhLmlzVG91Y2hFdmVudCAmJiAnYnV0dG9uJyBpbiBlICYmIGUuYnV0dG9uID4gMCkgcmV0dXJuO1xuICAgICAgaWYgKGRhdGEuaXNUb3VjaGVkICYmIGRhdGEuaXNNb3ZlZCkgcmV0dXJuOyAvLyBjaGFuZ2UgdGFyZ2V0IGVsIGZvciBzaGFkb3cgcm9vdCBjb21wb25lbnRcblxuICAgICAgY29uc3Qgc3dpcGluZ0NsYXNzSGFzVmFsdWUgPSAhIXBhcmFtcy5ub1N3aXBpbmdDbGFzcyAmJiBwYXJhbXMubm9Td2lwaW5nQ2xhc3MgIT09ICcnO1xuXG4gICAgICBpZiAoc3dpcGluZ0NsYXNzSGFzVmFsdWUgJiYgZS50YXJnZXQgJiYgZS50YXJnZXQuc2hhZG93Um9vdCAmJiBldmVudC5wYXRoICYmIGV2ZW50LnBhdGhbMF0pIHtcbiAgICAgICAgJHRhcmdldEVsID0gJChldmVudC5wYXRoWzBdKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgbm9Td2lwaW5nU2VsZWN0b3IgPSBwYXJhbXMubm9Td2lwaW5nU2VsZWN0b3IgPyBwYXJhbXMubm9Td2lwaW5nU2VsZWN0b3IgOiBgLiR7cGFyYW1zLm5vU3dpcGluZ0NsYXNzfWA7XG4gICAgICBjb25zdCBpc1RhcmdldFNoYWRvdyA9ICEhKGUudGFyZ2V0ICYmIGUudGFyZ2V0LnNoYWRvd1Jvb3QpOyAvLyB1c2UgY2xvc2VzdEVsZW1lbnQgZm9yIHNoYWRvdyByb290IGVsZW1lbnQgdG8gZ2V0IHRoZSBhY3R1YWwgY2xvc2VzdCBmb3IgbmVzdGVkIHNoYWRvdyByb290IGVsZW1lbnRcblxuICAgICAgaWYgKHBhcmFtcy5ub1N3aXBpbmcgJiYgKGlzVGFyZ2V0U2hhZG93ID8gY2xvc2VzdEVsZW1lbnQobm9Td2lwaW5nU2VsZWN0b3IsIGUudGFyZ2V0KSA6ICR0YXJnZXRFbC5jbG9zZXN0KG5vU3dpcGluZ1NlbGVjdG9yKVswXSkpIHtcbiAgICAgICAgc3dpcGVyLmFsbG93Q2xpY2sgPSB0cnVlO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMuc3dpcGVIYW5kbGVyKSB7XG4gICAgICAgIGlmICghJHRhcmdldEVsLmNsb3Nlc3QocGFyYW1zLnN3aXBlSGFuZGxlcilbMF0pIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdG91Y2hlcy5jdXJyZW50WCA9IGUudHlwZSA9PT0gJ3RvdWNoc3RhcnQnID8gZS50YXJnZXRUb3VjaGVzWzBdLnBhZ2VYIDogZS5wYWdlWDtcbiAgICAgIHRvdWNoZXMuY3VycmVudFkgPSBlLnR5cGUgPT09ICd0b3VjaHN0YXJ0JyA/IGUudGFyZ2V0VG91Y2hlc1swXS5wYWdlWSA6IGUucGFnZVk7XG4gICAgICBjb25zdCBzdGFydFggPSB0b3VjaGVzLmN1cnJlbnRYO1xuICAgICAgY29uc3Qgc3RhcnRZID0gdG91Y2hlcy5jdXJyZW50WTsgLy8gRG8gTk9UIHN0YXJ0IGlmIGlPUyBlZGdlIHN3aXBlIGlzIGRldGVjdGVkLiBPdGhlcndpc2UgaU9TIGFwcCBjYW5ub3Qgc3dpcGUtdG8tZ28tYmFjayBhbnltb3JlXG5cbiAgICAgIGNvbnN0IGVkZ2VTd2lwZURldGVjdGlvbiA9IHBhcmFtcy5lZGdlU3dpcGVEZXRlY3Rpb24gfHwgcGFyYW1zLmlPU0VkZ2VTd2lwZURldGVjdGlvbjtcbiAgICAgIGNvbnN0IGVkZ2VTd2lwZVRocmVzaG9sZCA9IHBhcmFtcy5lZGdlU3dpcGVUaHJlc2hvbGQgfHwgcGFyYW1zLmlPU0VkZ2VTd2lwZVRocmVzaG9sZDtcblxuICAgICAgaWYgKGVkZ2VTd2lwZURldGVjdGlvbiAmJiAoc3RhcnRYIDw9IGVkZ2VTd2lwZVRocmVzaG9sZCB8fCBzdGFydFggPj0gd2luZG93LmlubmVyV2lkdGggLSBlZGdlU3dpcGVUaHJlc2hvbGQpKSB7XG4gICAgICAgIGlmIChlZGdlU3dpcGVEZXRlY3Rpb24gPT09ICdwcmV2ZW50Jykge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIE9iamVjdC5hc3NpZ24oZGF0YSwge1xuICAgICAgICBpc1RvdWNoZWQ6IHRydWUsXG4gICAgICAgIGlzTW92ZWQ6IGZhbHNlLFxuICAgICAgICBhbGxvd1RvdWNoQ2FsbGJhY2tzOiB0cnVlLFxuICAgICAgICBpc1Njcm9sbGluZzogdW5kZWZpbmVkLFxuICAgICAgICBzdGFydE1vdmluZzogdW5kZWZpbmVkXG4gICAgICB9KTtcbiAgICAgIHRvdWNoZXMuc3RhcnRYID0gc3RhcnRYO1xuICAgICAgdG91Y2hlcy5zdGFydFkgPSBzdGFydFk7XG4gICAgICBkYXRhLnRvdWNoU3RhcnRUaW1lID0gbm93KCk7XG4gICAgICBzd2lwZXIuYWxsb3dDbGljayA9IHRydWU7XG4gICAgICBzd2lwZXIudXBkYXRlU2l6ZSgpO1xuICAgICAgc3dpcGVyLnN3aXBlRGlyZWN0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgaWYgKHBhcmFtcy50aHJlc2hvbGQgPiAwKSBkYXRhLmFsbG93VGhyZXNob2xkTW92ZSA9IGZhbHNlO1xuXG4gICAgICBpZiAoZS50eXBlICE9PSAndG91Y2hzdGFydCcpIHtcbiAgICAgICAgbGV0IHByZXZlbnREZWZhdWx0ID0gdHJ1ZTtcblxuICAgICAgICBpZiAoJHRhcmdldEVsLmlzKGRhdGEuZm9jdXNhYmxlRWxlbWVudHMpKSB7XG4gICAgICAgICAgcHJldmVudERlZmF1bHQgPSBmYWxzZTtcblxuICAgICAgICAgIGlmICgkdGFyZ2V0RWxbMF0ubm9kZU5hbWUgPT09ICdTRUxFQ1QnKSB7XG4gICAgICAgICAgICBkYXRhLmlzVG91Y2hlZCA9IGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50ICYmICQoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkuaXMoZGF0YS5mb2N1c2FibGVFbGVtZW50cykgJiYgZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAhPT0gJHRhcmdldEVsWzBdKSB7XG4gICAgICAgICAgZG9jdW1lbnQuYWN0aXZlRWxlbWVudC5ibHVyKCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzaG91bGRQcmV2ZW50RGVmYXVsdCA9IHByZXZlbnREZWZhdWx0ICYmIHN3aXBlci5hbGxvd1RvdWNoTW92ZSAmJiBwYXJhbXMudG91Y2hTdGFydFByZXZlbnREZWZhdWx0O1xuXG4gICAgICAgIGlmICgocGFyYW1zLnRvdWNoU3RhcnRGb3JjZVByZXZlbnREZWZhdWx0IHx8IHNob3VsZFByZXZlbnREZWZhdWx0KSAmJiAhJHRhcmdldEVsWzBdLmlzQ29udGVudEVkaXRhYmxlKSB7XG4gICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChzd2lwZXIucGFyYW1zLmZyZWVNb2RlICYmIHN3aXBlci5wYXJhbXMuZnJlZU1vZGUuZW5hYmxlZCAmJiBzd2lwZXIuZnJlZU1vZGUgJiYgc3dpcGVyLmFuaW1hdGluZyAmJiAhcGFyYW1zLmNzc01vZGUpIHtcbiAgICAgICAgc3dpcGVyLmZyZWVNb2RlLm9uVG91Y2hTdGFydCgpO1xuICAgICAgfVxuXG4gICAgICBzd2lwZXIuZW1pdCgndG91Y2hTdGFydCcsIGUpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uVG91Y2hNb3ZlKGV2ZW50KSB7XG4gICAgICBjb25zdCBkb2N1bWVudCA9IGdldERvY3VtZW50KCk7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3QgZGF0YSA9IHN3aXBlci50b3VjaEV2ZW50c0RhdGE7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHBhcmFtcyxcbiAgICAgICAgdG91Y2hlcyxcbiAgICAgICAgcnRsVHJhbnNsYXRlOiBydGwsXG4gICAgICAgIGVuYWJsZWRcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICBpZiAoIWVuYWJsZWQpIHJldHVybjtcbiAgICAgIGxldCBlID0gZXZlbnQ7XG4gICAgICBpZiAoZS5vcmlnaW5hbEV2ZW50KSBlID0gZS5vcmlnaW5hbEV2ZW50O1xuXG4gICAgICBpZiAoIWRhdGEuaXNUb3VjaGVkKSB7XG4gICAgICAgIGlmIChkYXRhLnN0YXJ0TW92aW5nICYmIGRhdGEuaXNTY3JvbGxpbmcpIHtcbiAgICAgICAgICBzd2lwZXIuZW1pdCgndG91Y2hNb3ZlT3Bwb3NpdGUnLCBlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGRhdGEuaXNUb3VjaEV2ZW50ICYmIGUudHlwZSAhPT0gJ3RvdWNobW92ZScpIHJldHVybjtcbiAgICAgIGNvbnN0IHRhcmdldFRvdWNoID0gZS50eXBlID09PSAndG91Y2htb3ZlJyAmJiBlLnRhcmdldFRvdWNoZXMgJiYgKGUudGFyZ2V0VG91Y2hlc1swXSB8fCBlLmNoYW5nZWRUb3VjaGVzWzBdKTtcbiAgICAgIGNvbnN0IHBhZ2VYID0gZS50eXBlID09PSAndG91Y2htb3ZlJyA/IHRhcmdldFRvdWNoLnBhZ2VYIDogZS5wYWdlWDtcbiAgICAgIGNvbnN0IHBhZ2VZID0gZS50eXBlID09PSAndG91Y2htb3ZlJyA/IHRhcmdldFRvdWNoLnBhZ2VZIDogZS5wYWdlWTtcblxuICAgICAgaWYgKGUucHJldmVudGVkQnlOZXN0ZWRTd2lwZXIpIHtcbiAgICAgICAgdG91Y2hlcy5zdGFydFggPSBwYWdlWDtcbiAgICAgICAgdG91Y2hlcy5zdGFydFkgPSBwYWdlWTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXN3aXBlci5hbGxvd1RvdWNoTW92ZSkge1xuICAgICAgICBpZiAoISQoZS50YXJnZXQpLmlzKGRhdGEuZm9jdXNhYmxlRWxlbWVudHMpKSB7XG4gICAgICAgICAgc3dpcGVyLmFsbG93Q2xpY2sgPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkYXRhLmlzVG91Y2hlZCkge1xuICAgICAgICAgIE9iamVjdC5hc3NpZ24odG91Y2hlcywge1xuICAgICAgICAgICAgc3RhcnRYOiBwYWdlWCxcbiAgICAgICAgICAgIHN0YXJ0WTogcGFnZVksXG4gICAgICAgICAgICBjdXJyZW50WDogcGFnZVgsXG4gICAgICAgICAgICBjdXJyZW50WTogcGFnZVlcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBkYXRhLnRvdWNoU3RhcnRUaW1lID0gbm93KCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChkYXRhLmlzVG91Y2hFdmVudCAmJiBwYXJhbXMudG91Y2hSZWxlYXNlT25FZGdlcyAmJiAhcGFyYW1zLmxvb3ApIHtcbiAgICAgICAgaWYgKHN3aXBlci5pc1ZlcnRpY2FsKCkpIHtcbiAgICAgICAgICAvLyBWZXJ0aWNhbFxuICAgICAgICAgIGlmIChwYWdlWSA8IHRvdWNoZXMuc3RhcnRZICYmIHN3aXBlci50cmFuc2xhdGUgPD0gc3dpcGVyLm1heFRyYW5zbGF0ZSgpIHx8IHBhZ2VZID4gdG91Y2hlcy5zdGFydFkgJiYgc3dpcGVyLnRyYW5zbGF0ZSA+PSBzd2lwZXIubWluVHJhbnNsYXRlKCkpIHtcbiAgICAgICAgICAgIGRhdGEuaXNUb3VjaGVkID0gZmFsc2U7XG4gICAgICAgICAgICBkYXRhLmlzTW92ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAocGFnZVggPCB0b3VjaGVzLnN0YXJ0WCAmJiBzd2lwZXIudHJhbnNsYXRlIDw9IHN3aXBlci5tYXhUcmFuc2xhdGUoKSB8fCBwYWdlWCA+IHRvdWNoZXMuc3RhcnRYICYmIHN3aXBlci50cmFuc2xhdGUgPj0gc3dpcGVyLm1pblRyYW5zbGF0ZSgpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChkYXRhLmlzVG91Y2hFdmVudCAmJiBkb2N1bWVudC5hY3RpdmVFbGVtZW50KSB7XG4gICAgICAgIGlmIChlLnRhcmdldCA9PT0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAmJiAkKGUudGFyZ2V0KS5pcyhkYXRhLmZvY3VzYWJsZUVsZW1lbnRzKSkge1xuICAgICAgICAgIGRhdGEuaXNNb3ZlZCA9IHRydWU7XG4gICAgICAgICAgc3dpcGVyLmFsbG93Q2xpY2sgPSBmYWxzZTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGRhdGEuYWxsb3dUb3VjaENhbGxiYWNrcykge1xuICAgICAgICBzd2lwZXIuZW1pdCgndG91Y2hNb3ZlJywgZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChlLnRhcmdldFRvdWNoZXMgJiYgZS50YXJnZXRUb3VjaGVzLmxlbmd0aCA+IDEpIHJldHVybjtcbiAgICAgIHRvdWNoZXMuY3VycmVudFggPSBwYWdlWDtcbiAgICAgIHRvdWNoZXMuY3VycmVudFkgPSBwYWdlWTtcbiAgICAgIGNvbnN0IGRpZmZYID0gdG91Y2hlcy5jdXJyZW50WCAtIHRvdWNoZXMuc3RhcnRYO1xuICAgICAgY29uc3QgZGlmZlkgPSB0b3VjaGVzLmN1cnJlbnRZIC0gdG91Y2hlcy5zdGFydFk7XG4gICAgICBpZiAoc3dpcGVyLnBhcmFtcy50aHJlc2hvbGQgJiYgTWF0aC5zcXJ0KGRpZmZYICoqIDIgKyBkaWZmWSAqKiAyKSA8IHN3aXBlci5wYXJhbXMudGhyZXNob2xkKSByZXR1cm47XG5cbiAgICAgIGlmICh0eXBlb2YgZGF0YS5pc1Njcm9sbGluZyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgbGV0IHRvdWNoQW5nbGU7XG5cbiAgICAgICAgaWYgKHN3aXBlci5pc0hvcml6b250YWwoKSAmJiB0b3VjaGVzLmN1cnJlbnRZID09PSB0b3VjaGVzLnN0YXJ0WSB8fCBzd2lwZXIuaXNWZXJ0aWNhbCgpICYmIHRvdWNoZXMuY3VycmVudFggPT09IHRvdWNoZXMuc3RhcnRYKSB7XG4gICAgICAgICAgZGF0YS5pc1Njcm9sbGluZyA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgICAgICAgIGlmIChkaWZmWCAqIGRpZmZYICsgZGlmZlkgKiBkaWZmWSA+PSAyNSkge1xuICAgICAgICAgICAgdG91Y2hBbmdsZSA9IE1hdGguYXRhbjIoTWF0aC5hYnMoZGlmZlkpLCBNYXRoLmFicyhkaWZmWCkpICogMTgwIC8gTWF0aC5QSTtcbiAgICAgICAgICAgIGRhdGEuaXNTY3JvbGxpbmcgPSBzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyB0b3VjaEFuZ2xlID4gcGFyYW1zLnRvdWNoQW5nbGUgOiA5MCAtIHRvdWNoQW5nbGUgPiBwYXJhbXMudG91Y2hBbmdsZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGRhdGEuaXNTY3JvbGxpbmcpIHtcbiAgICAgICAgc3dpcGVyLmVtaXQoJ3RvdWNoTW92ZU9wcG9zaXRlJywgZSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgZGF0YS5zdGFydE1vdmluZyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgaWYgKHRvdWNoZXMuY3VycmVudFggIT09IHRvdWNoZXMuc3RhcnRYIHx8IHRvdWNoZXMuY3VycmVudFkgIT09IHRvdWNoZXMuc3RhcnRZKSB7XG4gICAgICAgICAgZGF0YS5zdGFydE1vdmluZyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGRhdGEuaXNTY3JvbGxpbmcpIHtcbiAgICAgICAgZGF0YS5pc1RvdWNoZWQgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWRhdGEuc3RhcnRNb3ZpbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzd2lwZXIuYWxsb3dDbGljayA9IGZhbHNlO1xuXG4gICAgICBpZiAoIXBhcmFtcy5jc3NNb2RlICYmIGUuY2FuY2VsYWJsZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMudG91Y2hNb3ZlU3RvcFByb3BhZ2F0aW9uICYmICFwYXJhbXMubmVzdGVkKSB7XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghZGF0YS5pc01vdmVkKSB7XG4gICAgICAgIGlmIChwYXJhbXMubG9vcCAmJiAhcGFyYW1zLmNzc01vZGUpIHtcbiAgICAgICAgICBzd2lwZXIubG9vcEZpeCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZGF0YS5zdGFydFRyYW5zbGF0ZSA9IHN3aXBlci5nZXRUcmFuc2xhdGUoKTtcbiAgICAgICAgc3dpcGVyLnNldFRyYW5zaXRpb24oMCk7XG5cbiAgICAgICAgaWYgKHN3aXBlci5hbmltYXRpbmcpIHtcbiAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbC50cmlnZ2VyKCd3ZWJraXRUcmFuc2l0aW9uRW5kIHRyYW5zaXRpb25lbmQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRhdGEuYWxsb3dNb21lbnR1bUJvdW5jZSA9IGZhbHNlOyAvLyBHcmFiIEN1cnNvclxuXG4gICAgICAgIGlmIChwYXJhbXMuZ3JhYkN1cnNvciAmJiAoc3dpcGVyLmFsbG93U2xpZGVOZXh0ID09PSB0cnVlIHx8IHN3aXBlci5hbGxvd1NsaWRlUHJldiA9PT0gdHJ1ZSkpIHtcbiAgICAgICAgICBzd2lwZXIuc2V0R3JhYkN1cnNvcih0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci5lbWl0KCdzbGlkZXJGaXJzdE1vdmUnLCBlKTtcbiAgICAgIH1cblxuICAgICAgc3dpcGVyLmVtaXQoJ3NsaWRlck1vdmUnLCBlKTtcbiAgICAgIGRhdGEuaXNNb3ZlZCA9IHRydWU7XG4gICAgICBsZXQgZGlmZiA9IHN3aXBlci5pc0hvcml6b250YWwoKSA/IGRpZmZYIDogZGlmZlk7XG4gICAgICB0b3VjaGVzLmRpZmYgPSBkaWZmO1xuICAgICAgZGlmZiAqPSBwYXJhbXMudG91Y2hSYXRpbztcbiAgICAgIGlmIChydGwpIGRpZmYgPSAtZGlmZjtcbiAgICAgIHN3aXBlci5zd2lwZURpcmVjdGlvbiA9IGRpZmYgPiAwID8gJ3ByZXYnIDogJ25leHQnO1xuICAgICAgZGF0YS5jdXJyZW50VHJhbnNsYXRlID0gZGlmZiArIGRhdGEuc3RhcnRUcmFuc2xhdGU7XG4gICAgICBsZXQgZGlzYWJsZVBhcmVudFN3aXBlciA9IHRydWU7XG4gICAgICBsZXQgcmVzaXN0YW5jZVJhdGlvID0gcGFyYW1zLnJlc2lzdGFuY2VSYXRpbztcblxuICAgICAgaWYgKHBhcmFtcy50b3VjaFJlbGVhc2VPbkVkZ2VzKSB7XG4gICAgICAgIHJlc2lzdGFuY2VSYXRpbyA9IDA7XG4gICAgICB9XG5cbiAgICAgIGlmIChkaWZmID4gMCAmJiBkYXRhLmN1cnJlbnRUcmFuc2xhdGUgPiBzd2lwZXIubWluVHJhbnNsYXRlKCkpIHtcbiAgICAgICAgZGlzYWJsZVBhcmVudFN3aXBlciA9IGZhbHNlO1xuICAgICAgICBpZiAocGFyYW1zLnJlc2lzdGFuY2UpIGRhdGEuY3VycmVudFRyYW5zbGF0ZSA9IHN3aXBlci5taW5UcmFuc2xhdGUoKSAtIDEgKyAoLXN3aXBlci5taW5UcmFuc2xhdGUoKSArIGRhdGEuc3RhcnRUcmFuc2xhdGUgKyBkaWZmKSAqKiByZXNpc3RhbmNlUmF0aW87XG4gICAgICB9IGVsc2UgaWYgKGRpZmYgPCAwICYmIGRhdGEuY3VycmVudFRyYW5zbGF0ZSA8IHN3aXBlci5tYXhUcmFuc2xhdGUoKSkge1xuICAgICAgICBkaXNhYmxlUGFyZW50U3dpcGVyID0gZmFsc2U7XG4gICAgICAgIGlmIChwYXJhbXMucmVzaXN0YW5jZSkgZGF0YS5jdXJyZW50VHJhbnNsYXRlID0gc3dpcGVyLm1heFRyYW5zbGF0ZSgpICsgMSAtIChzd2lwZXIubWF4VHJhbnNsYXRlKCkgLSBkYXRhLnN0YXJ0VHJhbnNsYXRlIC0gZGlmZikgKiogcmVzaXN0YW5jZVJhdGlvO1xuICAgICAgfVxuXG4gICAgICBpZiAoZGlzYWJsZVBhcmVudFN3aXBlcikge1xuICAgICAgICBlLnByZXZlbnRlZEJ5TmVzdGVkU3dpcGVyID0gdHJ1ZTtcbiAgICAgIH0gLy8gRGlyZWN0aW9ucyBsb2Nrc1xuXG5cbiAgICAgIGlmICghc3dpcGVyLmFsbG93U2xpZGVOZXh0ICYmIHN3aXBlci5zd2lwZURpcmVjdGlvbiA9PT0gJ25leHQnICYmIGRhdGEuY3VycmVudFRyYW5zbGF0ZSA8IGRhdGEuc3RhcnRUcmFuc2xhdGUpIHtcbiAgICAgICAgZGF0YS5jdXJyZW50VHJhbnNsYXRlID0gZGF0YS5zdGFydFRyYW5zbGF0ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFzd2lwZXIuYWxsb3dTbGlkZVByZXYgJiYgc3dpcGVyLnN3aXBlRGlyZWN0aW9uID09PSAncHJldicgJiYgZGF0YS5jdXJyZW50VHJhbnNsYXRlID4gZGF0YS5zdGFydFRyYW5zbGF0ZSkge1xuICAgICAgICBkYXRhLmN1cnJlbnRUcmFuc2xhdGUgPSBkYXRhLnN0YXJ0VHJhbnNsYXRlO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXN3aXBlci5hbGxvd1NsaWRlUHJldiAmJiAhc3dpcGVyLmFsbG93U2xpZGVOZXh0KSB7XG4gICAgICAgIGRhdGEuY3VycmVudFRyYW5zbGF0ZSA9IGRhdGEuc3RhcnRUcmFuc2xhdGU7XG4gICAgICB9IC8vIFRocmVzaG9sZFxuXG5cbiAgICAgIGlmIChwYXJhbXMudGhyZXNob2xkID4gMCkge1xuICAgICAgICBpZiAoTWF0aC5hYnMoZGlmZikgPiBwYXJhbXMudGhyZXNob2xkIHx8IGRhdGEuYWxsb3dUaHJlc2hvbGRNb3ZlKSB7XG4gICAgICAgICAgaWYgKCFkYXRhLmFsbG93VGhyZXNob2xkTW92ZSkge1xuICAgICAgICAgICAgZGF0YS5hbGxvd1RocmVzaG9sZE1vdmUgPSB0cnVlO1xuICAgICAgICAgICAgdG91Y2hlcy5zdGFydFggPSB0b3VjaGVzLmN1cnJlbnRYO1xuICAgICAgICAgICAgdG91Y2hlcy5zdGFydFkgPSB0b3VjaGVzLmN1cnJlbnRZO1xuICAgICAgICAgICAgZGF0YS5jdXJyZW50VHJhbnNsYXRlID0gZGF0YS5zdGFydFRyYW5zbGF0ZTtcbiAgICAgICAgICAgIHRvdWNoZXMuZGlmZiA9IHN3aXBlci5pc0hvcml6b250YWwoKSA/IHRvdWNoZXMuY3VycmVudFggLSB0b3VjaGVzLnN0YXJ0WCA6IHRvdWNoZXMuY3VycmVudFkgLSB0b3VjaGVzLnN0YXJ0WTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGF0YS5jdXJyZW50VHJhbnNsYXRlID0gZGF0YS5zdGFydFRyYW5zbGF0ZTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKCFwYXJhbXMuZm9sbG93RmluZ2VyIHx8IHBhcmFtcy5jc3NNb2RlKSByZXR1cm47IC8vIFVwZGF0ZSBhY3RpdmUgaW5kZXggaW4gZnJlZSBtb2RlXG5cbiAgICAgIGlmIChwYXJhbXMuZnJlZU1vZGUgJiYgcGFyYW1zLmZyZWVNb2RlLmVuYWJsZWQgJiYgc3dpcGVyLmZyZWVNb2RlIHx8IHBhcmFtcy53YXRjaFNsaWRlc1Byb2dyZXNzKSB7XG4gICAgICAgIHN3aXBlci51cGRhdGVBY3RpdmVJbmRleCgpO1xuICAgICAgICBzd2lwZXIudXBkYXRlU2xpZGVzQ2xhc3NlcygpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc3dpcGVyLnBhcmFtcy5mcmVlTW9kZSAmJiBwYXJhbXMuZnJlZU1vZGUuZW5hYmxlZCAmJiBzd2lwZXIuZnJlZU1vZGUpIHtcbiAgICAgICAgc3dpcGVyLmZyZWVNb2RlLm9uVG91Y2hNb3ZlKCk7XG4gICAgICB9IC8vIFVwZGF0ZSBwcm9ncmVzc1xuXG5cbiAgICAgIHN3aXBlci51cGRhdGVQcm9ncmVzcyhkYXRhLmN1cnJlbnRUcmFuc2xhdGUpOyAvLyBVcGRhdGUgdHJhbnNsYXRlXG5cbiAgICAgIHN3aXBlci5zZXRUcmFuc2xhdGUoZGF0YS5jdXJyZW50VHJhbnNsYXRlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvblRvdWNoRW5kKGV2ZW50KSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3QgZGF0YSA9IHN3aXBlci50b3VjaEV2ZW50c0RhdGE7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHBhcmFtcyxcbiAgICAgICAgdG91Y2hlcyxcbiAgICAgICAgcnRsVHJhbnNsYXRlOiBydGwsXG4gICAgICAgIHNsaWRlc0dyaWQsXG4gICAgICAgIGVuYWJsZWRcbiAgICAgIH0gPSBzd2lwZXI7XG4gICAgICBpZiAoIWVuYWJsZWQpIHJldHVybjtcbiAgICAgIGxldCBlID0gZXZlbnQ7XG4gICAgICBpZiAoZS5vcmlnaW5hbEV2ZW50KSBlID0gZS5vcmlnaW5hbEV2ZW50O1xuXG4gICAgICBpZiAoZGF0YS5hbGxvd1RvdWNoQ2FsbGJhY2tzKSB7XG4gICAgICAgIHN3aXBlci5lbWl0KCd0b3VjaEVuZCcsIGUpO1xuICAgICAgfVxuXG4gICAgICBkYXRhLmFsbG93VG91Y2hDYWxsYmFja3MgPSBmYWxzZTtcblxuICAgICAgaWYgKCFkYXRhLmlzVG91Y2hlZCkge1xuICAgICAgICBpZiAoZGF0YS5pc01vdmVkICYmIHBhcmFtcy5ncmFiQ3Vyc29yKSB7XG4gICAgICAgICAgc3dpcGVyLnNldEdyYWJDdXJzb3IoZmFsc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgZGF0YS5pc01vdmVkID0gZmFsc2U7XG4gICAgICAgIGRhdGEuc3RhcnRNb3ZpbmcgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBSZXR1cm4gR3JhYiBDdXJzb3JcblxuXG4gICAgICBpZiAocGFyYW1zLmdyYWJDdXJzb3IgJiYgZGF0YS5pc01vdmVkICYmIGRhdGEuaXNUb3VjaGVkICYmIChzd2lwZXIuYWxsb3dTbGlkZU5leHQgPT09IHRydWUgfHwgc3dpcGVyLmFsbG93U2xpZGVQcmV2ID09PSB0cnVlKSkge1xuICAgICAgICBzd2lwZXIuc2V0R3JhYkN1cnNvcihmYWxzZSk7XG4gICAgICB9IC8vIFRpbWUgZGlmZlxuXG5cbiAgICAgIGNvbnN0IHRvdWNoRW5kVGltZSA9IG5vdygpO1xuICAgICAgY29uc3QgdGltZURpZmYgPSB0b3VjaEVuZFRpbWUgLSBkYXRhLnRvdWNoU3RhcnRUaW1lOyAvLyBUYXAsIGRvdWJsZVRhcCwgQ2xpY2tcblxuICAgICAgaWYgKHN3aXBlci5hbGxvd0NsaWNrKSB7XG4gICAgICAgIGNvbnN0IHBhdGhUcmVlID0gZS5wYXRoIHx8IGUuY29tcG9zZWRQYXRoICYmIGUuY29tcG9zZWRQYXRoKCk7XG4gICAgICAgIHN3aXBlci51cGRhdGVDbGlja2VkU2xpZGUocGF0aFRyZWUgJiYgcGF0aFRyZWVbMF0gfHwgZS50YXJnZXQpO1xuICAgICAgICBzd2lwZXIuZW1pdCgndGFwIGNsaWNrJywgZSk7XG5cbiAgICAgICAgaWYgKHRpbWVEaWZmIDwgMzAwICYmIHRvdWNoRW5kVGltZSAtIGRhdGEubGFzdENsaWNrVGltZSA8IDMwMCkge1xuICAgICAgICAgIHN3aXBlci5lbWl0KCdkb3VibGVUYXAgZG91YmxlQ2xpY2snLCBlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBkYXRhLmxhc3RDbGlja1RpbWUgPSBub3coKTtcbiAgICAgIG5leHRUaWNrKCgpID0+IHtcbiAgICAgICAgaWYgKCFzd2lwZXIuZGVzdHJveWVkKSBzd2lwZXIuYWxsb3dDbGljayA9IHRydWU7XG4gICAgICB9KTtcblxuICAgICAgaWYgKCFkYXRhLmlzVG91Y2hlZCB8fCAhZGF0YS5pc01vdmVkIHx8ICFzd2lwZXIuc3dpcGVEaXJlY3Rpb24gfHwgdG91Y2hlcy5kaWZmID09PSAwIHx8IGRhdGEuY3VycmVudFRyYW5zbGF0ZSA9PT0gZGF0YS5zdGFydFRyYW5zbGF0ZSkge1xuICAgICAgICBkYXRhLmlzVG91Y2hlZCA9IGZhbHNlO1xuICAgICAgICBkYXRhLmlzTW92ZWQgPSBmYWxzZTtcbiAgICAgICAgZGF0YS5zdGFydE1vdmluZyA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGRhdGEuaXNUb3VjaGVkID0gZmFsc2U7XG4gICAgICBkYXRhLmlzTW92ZWQgPSBmYWxzZTtcbiAgICAgIGRhdGEuc3RhcnRNb3ZpbmcgPSBmYWxzZTtcbiAgICAgIGxldCBjdXJyZW50UG9zO1xuXG4gICAgICBpZiAocGFyYW1zLmZvbGxvd0Zpbmdlcikge1xuICAgICAgICBjdXJyZW50UG9zID0gcnRsID8gc3dpcGVyLnRyYW5zbGF0ZSA6IC1zd2lwZXIudHJhbnNsYXRlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY3VycmVudFBvcyA9IC1kYXRhLmN1cnJlbnRUcmFuc2xhdGU7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMuY3NzTW9kZSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChzd2lwZXIucGFyYW1zLmZyZWVNb2RlICYmIHBhcmFtcy5mcmVlTW9kZS5lbmFibGVkKSB7XG4gICAgICAgIHN3aXBlci5mcmVlTW9kZS5vblRvdWNoRW5kKHtcbiAgICAgICAgICBjdXJyZW50UG9zXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IC8vIEZpbmQgY3VycmVudCBzbGlkZVxuXG5cbiAgICAgIGxldCBzdG9wSW5kZXggPSAwO1xuICAgICAgbGV0IGdyb3VwU2l6ZSA9IHN3aXBlci5zbGlkZXNTaXplc0dyaWRbMF07XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2xpZGVzR3JpZC5sZW5ndGg7IGkgKz0gaSA8IHBhcmFtcy5zbGlkZXNQZXJHcm91cFNraXAgPyAxIDogcGFyYW1zLnNsaWRlc1Blckdyb3VwKSB7XG4gICAgICAgIGNvbnN0IGluY3JlbWVudCA9IGkgPCBwYXJhbXMuc2xpZGVzUGVyR3JvdXBTa2lwIC0gMSA/IDEgOiBwYXJhbXMuc2xpZGVzUGVyR3JvdXA7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBzbGlkZXNHcmlkW2kgKyBpbmNyZW1lbnRdICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIGlmIChjdXJyZW50UG9zID49IHNsaWRlc0dyaWRbaV0gJiYgY3VycmVudFBvcyA8IHNsaWRlc0dyaWRbaSArIGluY3JlbWVudF0pIHtcbiAgICAgICAgICAgIHN0b3BJbmRleCA9IGk7XG4gICAgICAgICAgICBncm91cFNpemUgPSBzbGlkZXNHcmlkW2kgKyBpbmNyZW1lbnRdIC0gc2xpZGVzR3JpZFtpXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudFBvcyA+PSBzbGlkZXNHcmlkW2ldKSB7XG4gICAgICAgICAgc3RvcEluZGV4ID0gaTtcbiAgICAgICAgICBncm91cFNpemUgPSBzbGlkZXNHcmlkW3NsaWRlc0dyaWQubGVuZ3RoIC0gMV0gLSBzbGlkZXNHcmlkW3NsaWRlc0dyaWQubGVuZ3RoIC0gMl07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgbGV0IHJld2luZEZpcnN0SW5kZXggPSBudWxsO1xuICAgICAgbGV0IHJld2luZExhc3RJbmRleCA9IG51bGw7XG5cbiAgICAgIGlmIChwYXJhbXMucmV3aW5kKSB7XG4gICAgICAgIGlmIChzd2lwZXIuaXNCZWdpbm5pbmcpIHtcbiAgICAgICAgICByZXdpbmRMYXN0SW5kZXggPSBzd2lwZXIucGFyYW1zLnZpcnR1YWwgJiYgc3dpcGVyLnBhcmFtcy52aXJ0dWFsLmVuYWJsZWQgJiYgc3dpcGVyLnZpcnR1YWwgPyBzd2lwZXIudmlydHVhbC5zbGlkZXMubGVuZ3RoIC0gMSA6IHN3aXBlci5zbGlkZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgfSBlbHNlIGlmIChzd2lwZXIuaXNFbmQpIHtcbiAgICAgICAgICByZXdpbmRGaXJzdEluZGV4ID0gMDtcbiAgICAgICAgfVxuICAgICAgfSAvLyBGaW5kIGN1cnJlbnQgc2xpZGUgc2l6ZVxuXG5cbiAgICAgIGNvbnN0IHJhdGlvID0gKGN1cnJlbnRQb3MgLSBzbGlkZXNHcmlkW3N0b3BJbmRleF0pIC8gZ3JvdXBTaXplO1xuICAgICAgY29uc3QgaW5jcmVtZW50ID0gc3RvcEluZGV4IDwgcGFyYW1zLnNsaWRlc1Blckdyb3VwU2tpcCAtIDEgPyAxIDogcGFyYW1zLnNsaWRlc1Blckdyb3VwO1xuXG4gICAgICBpZiAodGltZURpZmYgPiBwYXJhbXMubG9uZ1N3aXBlc01zKSB7XG4gICAgICAgIC8vIExvbmcgdG91Y2hlc1xuICAgICAgICBpZiAoIXBhcmFtcy5sb25nU3dpcGVzKSB7XG4gICAgICAgICAgc3dpcGVyLnNsaWRlVG8oc3dpcGVyLmFjdGl2ZUluZGV4KTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3dpcGVyLnN3aXBlRGlyZWN0aW9uID09PSAnbmV4dCcpIHtcbiAgICAgICAgICBpZiAocmF0aW8gPj0gcGFyYW1zLmxvbmdTd2lwZXNSYXRpbykgc3dpcGVyLnNsaWRlVG8ocGFyYW1zLnJld2luZCAmJiBzd2lwZXIuaXNFbmQgPyByZXdpbmRGaXJzdEluZGV4IDogc3RvcEluZGV4ICsgaW5jcmVtZW50KTtlbHNlIHN3aXBlci5zbGlkZVRvKHN0b3BJbmRleCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3dpcGVyLnN3aXBlRGlyZWN0aW9uID09PSAncHJldicpIHtcbiAgICAgICAgICBpZiAocmF0aW8gPiAxIC0gcGFyYW1zLmxvbmdTd2lwZXNSYXRpbykge1xuICAgICAgICAgICAgc3dpcGVyLnNsaWRlVG8oc3RvcEluZGV4ICsgaW5jcmVtZW50KTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHJld2luZExhc3RJbmRleCAhPT0gbnVsbCAmJiByYXRpbyA8IDAgJiYgTWF0aC5hYnMocmF0aW8pID4gcGFyYW1zLmxvbmdTd2lwZXNSYXRpbykge1xuICAgICAgICAgICAgc3dpcGVyLnNsaWRlVG8ocmV3aW5kTGFzdEluZGV4KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3dpcGVyLnNsaWRlVG8oc3RvcEluZGV4KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFNob3J0IHN3aXBlc1xuICAgICAgICBpZiAoIXBhcmFtcy5zaG9ydFN3aXBlcykge1xuICAgICAgICAgIHN3aXBlci5zbGlkZVRvKHN3aXBlci5hY3RpdmVJbmRleCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaXNOYXZCdXR0b25UYXJnZXQgPSBzd2lwZXIubmF2aWdhdGlvbiAmJiAoZS50YXJnZXQgPT09IHN3aXBlci5uYXZpZ2F0aW9uLm5leHRFbCB8fCBlLnRhcmdldCA9PT0gc3dpcGVyLm5hdmlnYXRpb24ucHJldkVsKTtcblxuICAgICAgICBpZiAoIWlzTmF2QnV0dG9uVGFyZ2V0KSB7XG4gICAgICAgICAgaWYgKHN3aXBlci5zd2lwZURpcmVjdGlvbiA9PT0gJ25leHQnKSB7XG4gICAgICAgICAgICBzd2lwZXIuc2xpZGVUbyhyZXdpbmRGaXJzdEluZGV4ICE9PSBudWxsID8gcmV3aW5kRmlyc3RJbmRleCA6IHN0b3BJbmRleCArIGluY3JlbWVudCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHN3aXBlci5zd2lwZURpcmVjdGlvbiA9PT0gJ3ByZXYnKSB7XG4gICAgICAgICAgICBzd2lwZXIuc2xpZGVUbyhyZXdpbmRMYXN0SW5kZXggIT09IG51bGwgPyByZXdpbmRMYXN0SW5kZXggOiBzdG9wSW5kZXgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChlLnRhcmdldCA9PT0gc3dpcGVyLm5hdmlnYXRpb24ubmV4dEVsKSB7XG4gICAgICAgICAgc3dpcGVyLnNsaWRlVG8oc3RvcEluZGV4ICsgaW5jcmVtZW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzd2lwZXIuc2xpZGVUbyhzdG9wSW5kZXgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25SZXNpemUoKSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3Qge1xuICAgICAgICBwYXJhbXMsXG4gICAgICAgIGVsXG4gICAgICB9ID0gc3dpcGVyO1xuICAgICAgaWYgKGVsICYmIGVsLm9mZnNldFdpZHRoID09PSAwKSByZXR1cm47IC8vIEJyZWFrcG9pbnRzXG5cbiAgICAgIGlmIChwYXJhbXMuYnJlYWtwb2ludHMpIHtcbiAgICAgICAgc3dpcGVyLnNldEJyZWFrcG9pbnQoKTtcbiAgICAgIH0gLy8gU2F2ZSBsb2Nrc1xuXG5cbiAgICAgIGNvbnN0IHtcbiAgICAgICAgYWxsb3dTbGlkZU5leHQsXG4gICAgICAgIGFsbG93U2xpZGVQcmV2LFxuICAgICAgICBzbmFwR3JpZFxuICAgICAgfSA9IHN3aXBlcjsgLy8gRGlzYWJsZSBsb2NrcyBvbiByZXNpemVcblxuICAgICAgc3dpcGVyLmFsbG93U2xpZGVOZXh0ID0gdHJ1ZTtcbiAgICAgIHN3aXBlci5hbGxvd1NsaWRlUHJldiA9IHRydWU7XG4gICAgICBzd2lwZXIudXBkYXRlU2l6ZSgpO1xuICAgICAgc3dpcGVyLnVwZGF0ZVNsaWRlcygpO1xuICAgICAgc3dpcGVyLnVwZGF0ZVNsaWRlc0NsYXNzZXMoKTtcblxuICAgICAgaWYgKChwYXJhbXMuc2xpZGVzUGVyVmlldyA9PT0gJ2F1dG8nIHx8IHBhcmFtcy5zbGlkZXNQZXJWaWV3ID4gMSkgJiYgc3dpcGVyLmlzRW5kICYmICFzd2lwZXIuaXNCZWdpbm5pbmcgJiYgIXN3aXBlci5wYXJhbXMuY2VudGVyZWRTbGlkZXMpIHtcbiAgICAgICAgc3dpcGVyLnNsaWRlVG8oc3dpcGVyLnNsaWRlcy5sZW5ndGggLSAxLCAwLCBmYWxzZSwgdHJ1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzd2lwZXIuc2xpZGVUbyhzd2lwZXIuYWN0aXZlSW5kZXgsIDAsIGZhbHNlLCB0cnVlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHN3aXBlci5hdXRvcGxheSAmJiBzd2lwZXIuYXV0b3BsYXkucnVubmluZyAmJiBzd2lwZXIuYXV0b3BsYXkucGF1c2VkKSB7XG4gICAgICAgIHN3aXBlci5hdXRvcGxheS5ydW4oKTtcbiAgICAgIH0gLy8gUmV0dXJuIGxvY2tzIGFmdGVyIHJlc2l6ZVxuXG5cbiAgICAgIHN3aXBlci5hbGxvd1NsaWRlUHJldiA9IGFsbG93U2xpZGVQcmV2O1xuICAgICAgc3dpcGVyLmFsbG93U2xpZGVOZXh0ID0gYWxsb3dTbGlkZU5leHQ7XG5cbiAgICAgIGlmIChzd2lwZXIucGFyYW1zLndhdGNoT3ZlcmZsb3cgJiYgc25hcEdyaWQgIT09IHN3aXBlci5zbmFwR3JpZCkge1xuICAgICAgICBzd2lwZXIuY2hlY2tPdmVyZmxvdygpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9uQ2xpY2soZSkge1xuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIGlmICghc3dpcGVyLmVuYWJsZWQpIHJldHVybjtcblxuICAgICAgaWYgKCFzd2lwZXIuYWxsb3dDbGljaykge1xuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5wcmV2ZW50Q2xpY2tzKSBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMucHJldmVudENsaWNrc1Byb3BhZ2F0aW9uICYmIHN3aXBlci5hbmltYXRpbmcpIHtcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvblNjcm9sbCgpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHdyYXBwZXJFbCxcbiAgICAgICAgcnRsVHJhbnNsYXRlLFxuICAgICAgICBlbmFibGVkXG4gICAgICB9ID0gc3dpcGVyO1xuICAgICAgaWYgKCFlbmFibGVkKSByZXR1cm47XG4gICAgICBzd2lwZXIucHJldmlvdXNUcmFuc2xhdGUgPSBzd2lwZXIudHJhbnNsYXRlO1xuXG4gICAgICBpZiAoc3dpcGVyLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgIHN3aXBlci50cmFuc2xhdGUgPSAtd3JhcHBlckVsLnNjcm9sbExlZnQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzd2lwZXIudHJhbnNsYXRlID0gLXdyYXBwZXJFbC5zY3JvbGxUb3A7XG4gICAgICB9IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuXG5cbiAgICAgIGlmIChzd2lwZXIudHJhbnNsYXRlID09PSAtMCkgc3dpcGVyLnRyYW5zbGF0ZSA9IDA7XG4gICAgICBzd2lwZXIudXBkYXRlQWN0aXZlSW5kZXgoKTtcbiAgICAgIHN3aXBlci51cGRhdGVTbGlkZXNDbGFzc2VzKCk7XG4gICAgICBsZXQgbmV3UHJvZ3Jlc3M7XG4gICAgICBjb25zdCB0cmFuc2xhdGVzRGlmZiA9IHN3aXBlci5tYXhUcmFuc2xhdGUoKSAtIHN3aXBlci5taW5UcmFuc2xhdGUoKTtcblxuICAgICAgaWYgKHRyYW5zbGF0ZXNEaWZmID09PSAwKSB7XG4gICAgICAgIG5ld1Byb2dyZXNzID0gMDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld1Byb2dyZXNzID0gKHN3aXBlci50cmFuc2xhdGUgLSBzd2lwZXIubWluVHJhbnNsYXRlKCkpIC8gdHJhbnNsYXRlc0RpZmY7XG4gICAgICB9XG5cbiAgICAgIGlmIChuZXdQcm9ncmVzcyAhPT0gc3dpcGVyLnByb2dyZXNzKSB7XG4gICAgICAgIHN3aXBlci51cGRhdGVQcm9ncmVzcyhydGxUcmFuc2xhdGUgPyAtc3dpcGVyLnRyYW5zbGF0ZSA6IHN3aXBlci50cmFuc2xhdGUpO1xuICAgICAgfVxuXG4gICAgICBzd2lwZXIuZW1pdCgnc2V0VHJhbnNsYXRlJywgc3dpcGVyLnRyYW5zbGF0ZSwgZmFsc2UpO1xuICAgIH1cblxuICAgIGxldCBkdW1teUV2ZW50QXR0YWNoZWQgPSBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIGR1bW15RXZlbnRMaXN0ZW5lcigpIHt9XG5cbiAgICBjb25zdCBldmVudHMgPSAoc3dpcGVyLCBtZXRob2QpID0+IHtcbiAgICAgIGNvbnN0IGRvY3VtZW50ID0gZ2V0RG9jdW1lbnQoKTtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgcGFyYW1zLFxuICAgICAgICB0b3VjaEV2ZW50cyxcbiAgICAgICAgZWwsXG4gICAgICAgIHdyYXBwZXJFbCxcbiAgICAgICAgZGV2aWNlLFxuICAgICAgICBzdXBwb3J0XG4gICAgICB9ID0gc3dpcGVyO1xuICAgICAgY29uc3QgY2FwdHVyZSA9ICEhcGFyYW1zLm5lc3RlZDtcbiAgICAgIGNvbnN0IGRvbU1ldGhvZCA9IG1ldGhvZCA9PT0gJ29uJyA/ICdhZGRFdmVudExpc3RlbmVyJyA6ICdyZW1vdmVFdmVudExpc3RlbmVyJztcbiAgICAgIGNvbnN0IHN3aXBlck1ldGhvZCA9IG1ldGhvZDsgLy8gVG91Y2ggRXZlbnRzXG5cbiAgICAgIGlmICghc3VwcG9ydC50b3VjaCkge1xuICAgICAgICBlbFtkb21NZXRob2RdKHRvdWNoRXZlbnRzLnN0YXJ0LCBzd2lwZXIub25Ub3VjaFN0YXJ0LCBmYWxzZSk7XG4gICAgICAgIGRvY3VtZW50W2RvbU1ldGhvZF0odG91Y2hFdmVudHMubW92ZSwgc3dpcGVyLm9uVG91Y2hNb3ZlLCBjYXB0dXJlKTtcbiAgICAgICAgZG9jdW1lbnRbZG9tTWV0aG9kXSh0b3VjaEV2ZW50cy5lbmQsIHN3aXBlci5vblRvdWNoRW5kLCBmYWxzZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBwYXNzaXZlTGlzdGVuZXIgPSB0b3VjaEV2ZW50cy5zdGFydCA9PT0gJ3RvdWNoc3RhcnQnICYmIHN1cHBvcnQucGFzc2l2ZUxpc3RlbmVyICYmIHBhcmFtcy5wYXNzaXZlTGlzdGVuZXJzID8ge1xuICAgICAgICAgIHBhc3NpdmU6IHRydWUsXG4gICAgICAgICAgY2FwdHVyZTogZmFsc2VcbiAgICAgICAgfSA6IGZhbHNlO1xuICAgICAgICBlbFtkb21NZXRob2RdKHRvdWNoRXZlbnRzLnN0YXJ0LCBzd2lwZXIub25Ub3VjaFN0YXJ0LCBwYXNzaXZlTGlzdGVuZXIpO1xuICAgICAgICBlbFtkb21NZXRob2RdKHRvdWNoRXZlbnRzLm1vdmUsIHN3aXBlci5vblRvdWNoTW92ZSwgc3VwcG9ydC5wYXNzaXZlTGlzdGVuZXIgPyB7XG4gICAgICAgICAgcGFzc2l2ZTogZmFsc2UsXG4gICAgICAgICAgY2FwdHVyZVxuICAgICAgICB9IDogY2FwdHVyZSk7XG4gICAgICAgIGVsW2RvbU1ldGhvZF0odG91Y2hFdmVudHMuZW5kLCBzd2lwZXIub25Ub3VjaEVuZCwgcGFzc2l2ZUxpc3RlbmVyKTtcblxuICAgICAgICBpZiAodG91Y2hFdmVudHMuY2FuY2VsKSB7XG4gICAgICAgICAgZWxbZG9tTWV0aG9kXSh0b3VjaEV2ZW50cy5jYW5jZWwsIHN3aXBlci5vblRvdWNoRW5kLCBwYXNzaXZlTGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgICB9IC8vIFByZXZlbnQgTGlua3MgQ2xpY2tzXG5cblxuICAgICAgaWYgKHBhcmFtcy5wcmV2ZW50Q2xpY2tzIHx8IHBhcmFtcy5wcmV2ZW50Q2xpY2tzUHJvcGFnYXRpb24pIHtcbiAgICAgICAgZWxbZG9tTWV0aG9kXSgnY2xpY2snLCBzd2lwZXIub25DbGljaywgdHJ1ZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMuY3NzTW9kZSkge1xuICAgICAgICB3cmFwcGVyRWxbZG9tTWV0aG9kXSgnc2Nyb2xsJywgc3dpcGVyLm9uU2Nyb2xsKTtcbiAgICAgIH0gLy8gUmVzaXplIGhhbmRsZXJcblxuXG4gICAgICBpZiAocGFyYW1zLnVwZGF0ZU9uV2luZG93UmVzaXplKSB7XG4gICAgICAgIHN3aXBlcltzd2lwZXJNZXRob2RdKGRldmljZS5pb3MgfHwgZGV2aWNlLmFuZHJvaWQgPyAncmVzaXplIG9yaWVudGF0aW9uY2hhbmdlIG9ic2VydmVyVXBkYXRlJyA6ICdyZXNpemUgb2JzZXJ2ZXJVcGRhdGUnLCBvblJlc2l6ZSwgdHJ1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzd2lwZXJbc3dpcGVyTWV0aG9kXSgnb2JzZXJ2ZXJVcGRhdGUnLCBvblJlc2l6ZSwgdHJ1ZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGF0dGFjaEV2ZW50cygpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCBkb2N1bWVudCA9IGdldERvY3VtZW50KCk7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHBhcmFtcyxcbiAgICAgICAgc3VwcG9ydFxuICAgICAgfSA9IHN3aXBlcjtcbiAgICAgIHN3aXBlci5vblRvdWNoU3RhcnQgPSBvblRvdWNoU3RhcnQuYmluZChzd2lwZXIpO1xuICAgICAgc3dpcGVyLm9uVG91Y2hNb3ZlID0gb25Ub3VjaE1vdmUuYmluZChzd2lwZXIpO1xuICAgICAgc3dpcGVyLm9uVG91Y2hFbmQgPSBvblRvdWNoRW5kLmJpbmQoc3dpcGVyKTtcblxuICAgICAgaWYgKHBhcmFtcy5jc3NNb2RlKSB7XG4gICAgICAgIHN3aXBlci5vblNjcm9sbCA9IG9uU2Nyb2xsLmJpbmQoc3dpcGVyKTtcbiAgICAgIH1cblxuICAgICAgc3dpcGVyLm9uQ2xpY2sgPSBvbkNsaWNrLmJpbmQoc3dpcGVyKTtcblxuICAgICAgaWYgKHN1cHBvcnQudG91Y2ggJiYgIWR1bW15RXZlbnRBdHRhY2hlZCkge1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgZHVtbXlFdmVudExpc3RlbmVyKTtcbiAgICAgICAgZHVtbXlFdmVudEF0dGFjaGVkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgZXZlbnRzKHN3aXBlciwgJ29uJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGV0YWNoRXZlbnRzKCkge1xuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIGV2ZW50cyhzd2lwZXIsICdvZmYnKTtcbiAgICB9XG5cbiAgICB2YXIgZXZlbnRzJDEgPSB7XG4gICAgICBhdHRhY2hFdmVudHMsXG4gICAgICBkZXRhY2hFdmVudHNcbiAgICB9O1xuXG4gICAgY29uc3QgaXNHcmlkRW5hYmxlZCA9IChzd2lwZXIsIHBhcmFtcykgPT4ge1xuICAgICAgcmV0dXJuIHN3aXBlci5ncmlkICYmIHBhcmFtcy5ncmlkICYmIHBhcmFtcy5ncmlkLnJvd3MgPiAxO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBzZXRCcmVha3BvaW50KCkge1xuICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgYWN0aXZlSW5kZXgsXG4gICAgICAgIGluaXRpYWxpemVkLFxuICAgICAgICBsb29wZWRTbGlkZXMgPSAwLFxuICAgICAgICBwYXJhbXMsXG4gICAgICAgICRlbFxuICAgICAgfSA9IHN3aXBlcjtcbiAgICAgIGNvbnN0IGJyZWFrcG9pbnRzID0gcGFyYW1zLmJyZWFrcG9pbnRzO1xuICAgICAgaWYgKCFicmVha3BvaW50cyB8fCBicmVha3BvaW50cyAmJiBPYmplY3Qua2V5cyhicmVha3BvaW50cykubGVuZ3RoID09PSAwKSByZXR1cm47IC8vIEdldCBicmVha3BvaW50IGZvciB3aW5kb3cgd2lkdGggYW5kIHVwZGF0ZSBwYXJhbWV0ZXJzXG5cbiAgICAgIGNvbnN0IGJyZWFrcG9pbnQgPSBzd2lwZXIuZ2V0QnJlYWtwb2ludChicmVha3BvaW50cywgc3dpcGVyLnBhcmFtcy5icmVha3BvaW50c0Jhc2UsIHN3aXBlci5lbCk7XG4gICAgICBpZiAoIWJyZWFrcG9pbnQgfHwgc3dpcGVyLmN1cnJlbnRCcmVha3BvaW50ID09PSBicmVha3BvaW50KSByZXR1cm47XG4gICAgICBjb25zdCBicmVha3BvaW50T25seVBhcmFtcyA9IGJyZWFrcG9pbnQgaW4gYnJlYWtwb2ludHMgPyBicmVha3BvaW50c1ticmVha3BvaW50XSA6IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IGJyZWFrcG9pbnRQYXJhbXMgPSBicmVha3BvaW50T25seVBhcmFtcyB8fCBzd2lwZXIub3JpZ2luYWxQYXJhbXM7XG4gICAgICBjb25zdCB3YXNNdWx0aVJvdyA9IGlzR3JpZEVuYWJsZWQoc3dpcGVyLCBwYXJhbXMpO1xuICAgICAgY29uc3QgaXNNdWx0aVJvdyA9IGlzR3JpZEVuYWJsZWQoc3dpcGVyLCBicmVha3BvaW50UGFyYW1zKTtcbiAgICAgIGNvbnN0IHdhc0VuYWJsZWQgPSBwYXJhbXMuZW5hYmxlZDtcblxuICAgICAgaWYgKHdhc011bHRpUm93ICYmICFpc011bHRpUm93KSB7XG4gICAgICAgICRlbC5yZW1vdmVDbGFzcyhgJHtwYXJhbXMuY29udGFpbmVyTW9kaWZpZXJDbGFzc31ncmlkICR7cGFyYW1zLmNvbnRhaW5lck1vZGlmaWVyQ2xhc3N9Z3JpZC1jb2x1bW5gKTtcbiAgICAgICAgc3dpcGVyLmVtaXRDb250YWluZXJDbGFzc2VzKCk7XG4gICAgICB9IGVsc2UgaWYgKCF3YXNNdWx0aVJvdyAmJiBpc011bHRpUm93KSB7XG4gICAgICAgICRlbC5hZGRDbGFzcyhgJHtwYXJhbXMuY29udGFpbmVyTW9kaWZpZXJDbGFzc31ncmlkYCk7XG5cbiAgICAgICAgaWYgKGJyZWFrcG9pbnRQYXJhbXMuZ3JpZC5maWxsICYmIGJyZWFrcG9pbnRQYXJhbXMuZ3JpZC5maWxsID09PSAnY29sdW1uJyB8fCAhYnJlYWtwb2ludFBhcmFtcy5ncmlkLmZpbGwgJiYgcGFyYW1zLmdyaWQuZmlsbCA9PT0gJ2NvbHVtbicpIHtcbiAgICAgICAgICAkZWwuYWRkQ2xhc3MoYCR7cGFyYW1zLmNvbnRhaW5lck1vZGlmaWVyQ2xhc3N9Z3JpZC1jb2x1bW5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci5lbWl0Q29udGFpbmVyQ2xhc3NlcygpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkaXJlY3Rpb25DaGFuZ2VkID0gYnJlYWtwb2ludFBhcmFtcy5kaXJlY3Rpb24gJiYgYnJlYWtwb2ludFBhcmFtcy5kaXJlY3Rpb24gIT09IHBhcmFtcy5kaXJlY3Rpb247XG4gICAgICBjb25zdCBuZWVkc1JlTG9vcCA9IHBhcmFtcy5sb29wICYmIChicmVha3BvaW50UGFyYW1zLnNsaWRlc1BlclZpZXcgIT09IHBhcmFtcy5zbGlkZXNQZXJWaWV3IHx8IGRpcmVjdGlvbkNoYW5nZWQpO1xuXG4gICAgICBpZiAoZGlyZWN0aW9uQ2hhbmdlZCAmJiBpbml0aWFsaXplZCkge1xuICAgICAgICBzd2lwZXIuY2hhbmdlRGlyZWN0aW9uKCk7XG4gICAgICB9XG5cbiAgICAgIGV4dGVuZChzd2lwZXIucGFyYW1zLCBicmVha3BvaW50UGFyYW1zKTtcbiAgICAgIGNvbnN0IGlzRW5hYmxlZCA9IHN3aXBlci5wYXJhbXMuZW5hYmxlZDtcbiAgICAgIE9iamVjdC5hc3NpZ24oc3dpcGVyLCB7XG4gICAgICAgIGFsbG93VG91Y2hNb3ZlOiBzd2lwZXIucGFyYW1zLmFsbG93VG91Y2hNb3ZlLFxuICAgICAgICBhbGxvd1NsaWRlTmV4dDogc3dpcGVyLnBhcmFtcy5hbGxvd1NsaWRlTmV4dCxcbiAgICAgICAgYWxsb3dTbGlkZVByZXY6IHN3aXBlci5wYXJhbXMuYWxsb3dTbGlkZVByZXZcbiAgICAgIH0pO1xuXG4gICAgICBpZiAod2FzRW5hYmxlZCAmJiAhaXNFbmFibGVkKSB7XG4gICAgICAgIHN3aXBlci5kaXNhYmxlKCk7XG4gICAgICB9IGVsc2UgaWYgKCF3YXNFbmFibGVkICYmIGlzRW5hYmxlZCkge1xuICAgICAgICBzd2lwZXIuZW5hYmxlKCk7XG4gICAgICB9XG5cbiAgICAgIHN3aXBlci5jdXJyZW50QnJlYWtwb2ludCA9IGJyZWFrcG9pbnQ7XG4gICAgICBzd2lwZXIuZW1pdCgnX2JlZm9yZUJyZWFrcG9pbnQnLCBicmVha3BvaW50UGFyYW1zKTtcblxuICAgICAgaWYgKG5lZWRzUmVMb29wICYmIGluaXRpYWxpemVkKSB7XG4gICAgICAgIHN3aXBlci5sb29wRGVzdHJveSgpO1xuICAgICAgICBzd2lwZXIubG9vcENyZWF0ZSgpO1xuICAgICAgICBzd2lwZXIudXBkYXRlU2xpZGVzKCk7XG4gICAgICAgIHN3aXBlci5zbGlkZVRvKGFjdGl2ZUluZGV4IC0gbG9vcGVkU2xpZGVzICsgc3dpcGVyLmxvb3BlZFNsaWRlcywgMCwgZmFsc2UpO1xuICAgICAgfVxuXG4gICAgICBzd2lwZXIuZW1pdCgnYnJlYWtwb2ludCcsIGJyZWFrcG9pbnRQYXJhbXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEJyZWFrcG9pbnQoYnJlYWtwb2ludHMsIGJhc2UsIGNvbnRhaW5lckVsKSB7XG4gICAgICBpZiAoYmFzZSA9PT0gdm9pZCAwKSB7XG4gICAgICAgIGJhc2UgPSAnd2luZG93JztcbiAgICAgIH1cblxuICAgICAgaWYgKCFicmVha3BvaW50cyB8fCBiYXNlID09PSAnY29udGFpbmVyJyAmJiAhY29udGFpbmVyRWwpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBsZXQgYnJlYWtwb2ludCA9IGZhbHNlO1xuICAgICAgY29uc3Qgd2luZG93ID0gZ2V0V2luZG93KCk7XG4gICAgICBjb25zdCBjdXJyZW50SGVpZ2h0ID0gYmFzZSA9PT0gJ3dpbmRvdycgPyB3aW5kb3cuaW5uZXJIZWlnaHQgOiBjb250YWluZXJFbC5jbGllbnRIZWlnaHQ7XG4gICAgICBjb25zdCBwb2ludHMgPSBPYmplY3Qua2V5cyhicmVha3BvaW50cykubWFwKHBvaW50ID0+IHtcbiAgICAgICAgaWYgKHR5cGVvZiBwb2ludCA9PT0gJ3N0cmluZycgJiYgcG9pbnQuaW5kZXhPZignQCcpID09PSAwKSB7XG4gICAgICAgICAgY29uc3QgbWluUmF0aW8gPSBwYXJzZUZsb2F0KHBvaW50LnN1YnN0cigxKSk7XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBjdXJyZW50SGVpZ2h0ICogbWluUmF0aW87XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgICAgcG9pbnRcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB2YWx1ZTogcG9pbnQsXG4gICAgICAgICAgcG9pbnRcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgICAgcG9pbnRzLnNvcnQoKGEsIGIpID0+IHBhcnNlSW50KGEudmFsdWUsIDEwKSAtIHBhcnNlSW50KGIudmFsdWUsIDEwKSk7XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBwb2ludCxcbiAgICAgICAgICB2YWx1ZVxuICAgICAgICB9ID0gcG9pbnRzW2ldO1xuXG4gICAgICAgIGlmIChiYXNlID09PSAnd2luZG93Jykge1xuICAgICAgICAgIGlmICh3aW5kb3cubWF0Y2hNZWRpYShgKG1pbi13aWR0aDogJHt2YWx1ZX1weClgKS5tYXRjaGVzKSB7XG4gICAgICAgICAgICBicmVha3BvaW50ID0gcG9pbnQ7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHZhbHVlIDw9IGNvbnRhaW5lckVsLmNsaWVudFdpZHRoKSB7XG4gICAgICAgICAgYnJlYWtwb2ludCA9IHBvaW50O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBicmVha3BvaW50IHx8ICdtYXgnO1xuICAgIH1cblxuICAgIHZhciBicmVha3BvaW50cyA9IHtcbiAgICAgIHNldEJyZWFrcG9pbnQsXG4gICAgICBnZXRCcmVha3BvaW50XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIHByZXBhcmVDbGFzc2VzKGVudHJpZXMsIHByZWZpeCkge1xuICAgICAgY29uc3QgcmVzdWx0Q2xhc3NlcyA9IFtdO1xuICAgICAgZW50cmllcy5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgICBpZiAodHlwZW9mIGl0ZW0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgT2JqZWN0LmtleXMoaXRlbSkuZm9yRWFjaChjbGFzc05hbWVzID0+IHtcbiAgICAgICAgICAgIGlmIChpdGVtW2NsYXNzTmFtZXNdKSB7XG4gICAgICAgICAgICAgIHJlc3VsdENsYXNzZXMucHVzaChwcmVmaXggKyBjbGFzc05hbWVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgaXRlbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICByZXN1bHRDbGFzc2VzLnB1c2gocHJlZml4ICsgaXRlbSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdENsYXNzZXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRkQ2xhc3NlcygpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCB7XG4gICAgICAgIGNsYXNzTmFtZXMsXG4gICAgICAgIHBhcmFtcyxcbiAgICAgICAgcnRsLFxuICAgICAgICAkZWwsXG4gICAgICAgIGRldmljZSxcbiAgICAgICAgc3VwcG9ydFxuICAgICAgfSA9IHN3aXBlcjsgLy8gcHJldHRpZXItaWdub3JlXG5cbiAgICAgIGNvbnN0IHN1ZmZpeGVzID0gcHJlcGFyZUNsYXNzZXMoWydpbml0aWFsaXplZCcsIHBhcmFtcy5kaXJlY3Rpb24sIHtcbiAgICAgICAgJ3BvaW50ZXItZXZlbnRzJzogIXN1cHBvcnQudG91Y2hcbiAgICAgIH0sIHtcbiAgICAgICAgJ2ZyZWUtbW9kZSc6IHN3aXBlci5wYXJhbXMuZnJlZU1vZGUgJiYgcGFyYW1zLmZyZWVNb2RlLmVuYWJsZWRcbiAgICAgIH0sIHtcbiAgICAgICAgJ2F1dG9oZWlnaHQnOiBwYXJhbXMuYXV0b0hlaWdodFxuICAgICAgfSwge1xuICAgICAgICAncnRsJzogcnRsXG4gICAgICB9LCB7XG4gICAgICAgICdncmlkJzogcGFyYW1zLmdyaWQgJiYgcGFyYW1zLmdyaWQucm93cyA+IDFcbiAgICAgIH0sIHtcbiAgICAgICAgJ2dyaWQtY29sdW1uJzogcGFyYW1zLmdyaWQgJiYgcGFyYW1zLmdyaWQucm93cyA+IDEgJiYgcGFyYW1zLmdyaWQuZmlsbCA9PT0gJ2NvbHVtbidcbiAgICAgIH0sIHtcbiAgICAgICAgJ2FuZHJvaWQnOiBkZXZpY2UuYW5kcm9pZFxuICAgICAgfSwge1xuICAgICAgICAnaW9zJzogZGV2aWNlLmlvc1xuICAgICAgfSwge1xuICAgICAgICAnY3NzLW1vZGUnOiBwYXJhbXMuY3NzTW9kZVxuICAgICAgfSwge1xuICAgICAgICAnY2VudGVyZWQnOiBwYXJhbXMuY3NzTW9kZSAmJiBwYXJhbXMuY2VudGVyZWRTbGlkZXNcbiAgICAgIH1dLCBwYXJhbXMuY29udGFpbmVyTW9kaWZpZXJDbGFzcyk7XG4gICAgICBjbGFzc05hbWVzLnB1c2goLi4uc3VmZml4ZXMpO1xuICAgICAgJGVsLmFkZENsYXNzKFsuLi5jbGFzc05hbWVzXS5qb2luKCcgJykpO1xuICAgICAgc3dpcGVyLmVtaXRDb250YWluZXJDbGFzc2VzKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVtb3ZlQ2xhc3NlcygpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCB7XG4gICAgICAgICRlbCxcbiAgICAgICAgY2xhc3NOYW1lc1xuICAgICAgfSA9IHN3aXBlcjtcbiAgICAgICRlbC5yZW1vdmVDbGFzcyhjbGFzc05hbWVzLmpvaW4oJyAnKSk7XG4gICAgICBzd2lwZXIuZW1pdENvbnRhaW5lckNsYXNzZXMoKTtcbiAgICB9XG5cbiAgICB2YXIgY2xhc3NlcyA9IHtcbiAgICAgIGFkZENsYXNzZXMsXG4gICAgICByZW1vdmVDbGFzc2VzXG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGxvYWRJbWFnZShpbWFnZUVsLCBzcmMsIHNyY3NldCwgc2l6ZXMsIGNoZWNrRm9yQ29tcGxldGUsIGNhbGxiYWNrKSB7XG4gICAgICBjb25zdCB3aW5kb3cgPSBnZXRXaW5kb3coKTtcbiAgICAgIGxldCBpbWFnZTtcblxuICAgICAgZnVuY3Rpb24gb25SZWFkeSgpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSBjYWxsYmFjaygpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBpc1BpY3R1cmUgPSAkKGltYWdlRWwpLnBhcmVudCgncGljdHVyZScpWzBdO1xuXG4gICAgICBpZiAoIWlzUGljdHVyZSAmJiAoIWltYWdlRWwuY29tcGxldGUgfHwgIWNoZWNrRm9yQ29tcGxldGUpKSB7XG4gICAgICAgIGlmIChzcmMpIHtcbiAgICAgICAgICBpbWFnZSA9IG5ldyB3aW5kb3cuSW1hZ2UoKTtcbiAgICAgICAgICBpbWFnZS5vbmxvYWQgPSBvblJlYWR5O1xuICAgICAgICAgIGltYWdlLm9uZXJyb3IgPSBvblJlYWR5O1xuXG4gICAgICAgICAgaWYgKHNpemVzKSB7XG4gICAgICAgICAgICBpbWFnZS5zaXplcyA9IHNpemVzO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChzcmNzZXQpIHtcbiAgICAgICAgICAgIGltYWdlLnNyY3NldCA9IHNyY3NldDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoc3JjKSB7XG4gICAgICAgICAgICBpbWFnZS5zcmMgPSBzcmM7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG9uUmVhZHkoKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gaW1hZ2UgYWxyZWFkeSBsb2FkZWQuLi5cbiAgICAgICAgb25SZWFkeSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHByZWxvYWRJbWFnZXMoKSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgc3dpcGVyLmltYWdlc1RvTG9hZCA9IHN3aXBlci4kZWwuZmluZCgnaW1nJyk7XG5cbiAgICAgIGZ1bmN0aW9uIG9uUmVhZHkoKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc3dpcGVyID09PSAndW5kZWZpbmVkJyB8fCBzd2lwZXIgPT09IG51bGwgfHwgIXN3aXBlciB8fCBzd2lwZXIuZGVzdHJveWVkKSByZXR1cm47XG4gICAgICAgIGlmIChzd2lwZXIuaW1hZ2VzTG9hZGVkICE9PSB1bmRlZmluZWQpIHN3aXBlci5pbWFnZXNMb2FkZWQgKz0gMTtcblxuICAgICAgICBpZiAoc3dpcGVyLmltYWdlc0xvYWRlZCA9PT0gc3dpcGVyLmltYWdlc1RvTG9hZC5sZW5ndGgpIHtcbiAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy51cGRhdGVPbkltYWdlc1JlYWR5KSBzd2lwZXIudXBkYXRlKCk7XG4gICAgICAgICAgc3dpcGVyLmVtaXQoJ2ltYWdlc1JlYWR5Jyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzd2lwZXIuaW1hZ2VzVG9Mb2FkLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGNvbnN0IGltYWdlRWwgPSBzd2lwZXIuaW1hZ2VzVG9Mb2FkW2ldO1xuICAgICAgICBzd2lwZXIubG9hZEltYWdlKGltYWdlRWwsIGltYWdlRWwuY3VycmVudFNyYyB8fCBpbWFnZUVsLmdldEF0dHJpYnV0ZSgnc3JjJyksIGltYWdlRWwuc3Jjc2V0IHx8IGltYWdlRWwuZ2V0QXR0cmlidXRlKCdzcmNzZXQnKSwgaW1hZ2VFbC5zaXplcyB8fCBpbWFnZUVsLmdldEF0dHJpYnV0ZSgnc2l6ZXMnKSwgdHJ1ZSwgb25SZWFkeSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGltYWdlcyA9IHtcbiAgICAgIGxvYWRJbWFnZSxcbiAgICAgIHByZWxvYWRJbWFnZXNcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gY2hlY2tPdmVyZmxvdygpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCB7XG4gICAgICAgIGlzTG9ja2VkOiB3YXNMb2NrZWQsXG4gICAgICAgIHBhcmFtc1xuICAgICAgfSA9IHN3aXBlcjtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgc2xpZGVzT2Zmc2V0QmVmb3JlXG4gICAgICB9ID0gcGFyYW1zO1xuXG4gICAgICBpZiAoc2xpZGVzT2Zmc2V0QmVmb3JlKSB7XG4gICAgICAgIGNvbnN0IGxhc3RTbGlkZUluZGV4ID0gc3dpcGVyLnNsaWRlcy5sZW5ndGggLSAxO1xuICAgICAgICBjb25zdCBsYXN0U2xpZGVSaWdodEVkZ2UgPSBzd2lwZXIuc2xpZGVzR3JpZFtsYXN0U2xpZGVJbmRleF0gKyBzd2lwZXIuc2xpZGVzU2l6ZXNHcmlkW2xhc3RTbGlkZUluZGV4XSArIHNsaWRlc09mZnNldEJlZm9yZSAqIDI7XG4gICAgICAgIHN3aXBlci5pc0xvY2tlZCA9IHN3aXBlci5zaXplID4gbGFzdFNsaWRlUmlnaHRFZGdlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3dpcGVyLmlzTG9ja2VkID0gc3dpcGVyLnNuYXBHcmlkLmxlbmd0aCA9PT0gMTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5hbGxvd1NsaWRlTmV4dCA9PT0gdHJ1ZSkge1xuICAgICAgICBzd2lwZXIuYWxsb3dTbGlkZU5leHQgPSAhc3dpcGVyLmlzTG9ja2VkO1xuICAgICAgfVxuXG4gICAgICBpZiAocGFyYW1zLmFsbG93U2xpZGVQcmV2ID09PSB0cnVlKSB7XG4gICAgICAgIHN3aXBlci5hbGxvd1NsaWRlUHJldiA9ICFzd2lwZXIuaXNMb2NrZWQ7XG4gICAgICB9XG5cbiAgICAgIGlmICh3YXNMb2NrZWQgJiYgd2FzTG9ja2VkICE9PSBzd2lwZXIuaXNMb2NrZWQpIHtcbiAgICAgICAgc3dpcGVyLmlzRW5kID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGlmICh3YXNMb2NrZWQgIT09IHN3aXBlci5pc0xvY2tlZCkge1xuICAgICAgICBzd2lwZXIuZW1pdChzd2lwZXIuaXNMb2NrZWQgPyAnbG9jaycgOiAndW5sb2NrJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGNoZWNrT3ZlcmZsb3ckMSA9IHtcbiAgICAgIGNoZWNrT3ZlcmZsb3dcbiAgICB9O1xuXG4gICAgdmFyIGRlZmF1bHRzID0ge1xuICAgICAgaW5pdDogdHJ1ZSxcbiAgICAgIGRpcmVjdGlvbjogJ2hvcml6b250YWwnLFxuICAgICAgdG91Y2hFdmVudHNUYXJnZXQ6ICd3cmFwcGVyJyxcbiAgICAgIGluaXRpYWxTbGlkZTogMCxcbiAgICAgIHNwZWVkOiAzMDAsXG4gICAgICBjc3NNb2RlOiBmYWxzZSxcbiAgICAgIHVwZGF0ZU9uV2luZG93UmVzaXplOiB0cnVlLFxuICAgICAgcmVzaXplT2JzZXJ2ZXI6IHRydWUsXG4gICAgICBuZXN0ZWQ6IGZhbHNlLFxuICAgICAgY3JlYXRlRWxlbWVudHM6IGZhbHNlLFxuICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgIGZvY3VzYWJsZUVsZW1lbnRzOiAnaW5wdXQsIHNlbGVjdCwgb3B0aW9uLCB0ZXh0YXJlYSwgYnV0dG9uLCB2aWRlbywgbGFiZWwnLFxuICAgICAgLy8gT3ZlcnJpZGVzXG4gICAgICB3aWR0aDogbnVsbCxcbiAgICAgIGhlaWdodDogbnVsbCxcbiAgICAgIC8vXG4gICAgICBwcmV2ZW50SW50ZXJhY3Rpb25PblRyYW5zaXRpb246IGZhbHNlLFxuICAgICAgLy8gc3NyXG4gICAgICB1c2VyQWdlbnQ6IG51bGwsXG4gICAgICB1cmw6IG51bGwsXG4gICAgICAvLyBUbyBzdXBwb3J0IGlPUydzIHN3aXBlLXRvLWdvLWJhY2sgZ2VzdHVyZSAod2hlbiBiZWluZyB1c2VkIGluLWFwcCkuXG4gICAgICBlZGdlU3dpcGVEZXRlY3Rpb246IGZhbHNlLFxuICAgICAgZWRnZVN3aXBlVGhyZXNob2xkOiAyMCxcbiAgICAgIC8vIEF1dG9oZWlnaHRcbiAgICAgIGF1dG9IZWlnaHQ6IGZhbHNlLFxuICAgICAgLy8gU2V0IHdyYXBwZXIgd2lkdGhcbiAgICAgIHNldFdyYXBwZXJTaXplOiBmYWxzZSxcbiAgICAgIC8vIFZpcnR1YWwgVHJhbnNsYXRlXG4gICAgICB2aXJ0dWFsVHJhbnNsYXRlOiBmYWxzZSxcbiAgICAgIC8vIEVmZmVjdHNcbiAgICAgIGVmZmVjdDogJ3NsaWRlJyxcbiAgICAgIC8vICdzbGlkZScgb3IgJ2ZhZGUnIG9yICdjdWJlJyBvciAnY292ZXJmbG93JyBvciAnZmxpcCdcbiAgICAgIC8vIEJyZWFrcG9pbnRzXG4gICAgICBicmVha3BvaW50czogdW5kZWZpbmVkLFxuICAgICAgYnJlYWtwb2ludHNCYXNlOiAnd2luZG93JyxcbiAgICAgIC8vIFNsaWRlcyBncmlkXG4gICAgICBzcGFjZUJldHdlZW46IDAsXG4gICAgICBzbGlkZXNQZXJWaWV3OiAxLFxuICAgICAgc2xpZGVzUGVyR3JvdXA6IDEsXG4gICAgICBzbGlkZXNQZXJHcm91cFNraXA6IDAsXG4gICAgICBzbGlkZXNQZXJHcm91cEF1dG86IGZhbHNlLFxuICAgICAgY2VudGVyZWRTbGlkZXM6IGZhbHNlLFxuICAgICAgY2VudGVyZWRTbGlkZXNCb3VuZHM6IGZhbHNlLFxuICAgICAgc2xpZGVzT2Zmc2V0QmVmb3JlOiAwLFxuICAgICAgLy8gaW4gcHhcbiAgICAgIHNsaWRlc09mZnNldEFmdGVyOiAwLFxuICAgICAgLy8gaW4gcHhcbiAgICAgIG5vcm1hbGl6ZVNsaWRlSW5kZXg6IHRydWUsXG4gICAgICBjZW50ZXJJbnN1ZmZpY2llbnRTbGlkZXM6IGZhbHNlLFxuICAgICAgLy8gRGlzYWJsZSBzd2lwZXIgYW5kIGhpZGUgbmF2aWdhdGlvbiB3aGVuIGNvbnRhaW5lciBub3Qgb3ZlcmZsb3dcbiAgICAgIHdhdGNoT3ZlcmZsb3c6IHRydWUsXG4gICAgICAvLyBSb3VuZCBsZW5ndGhcbiAgICAgIHJvdW5kTGVuZ3RoczogZmFsc2UsXG4gICAgICAvLyBUb3VjaGVzXG4gICAgICB0b3VjaFJhdGlvOiAxLFxuICAgICAgdG91Y2hBbmdsZTogNDUsXG4gICAgICBzaW11bGF0ZVRvdWNoOiB0cnVlLFxuICAgICAgc2hvcnRTd2lwZXM6IHRydWUsXG4gICAgICBsb25nU3dpcGVzOiB0cnVlLFxuICAgICAgbG9uZ1N3aXBlc1JhdGlvOiAwLjUsXG4gICAgICBsb25nU3dpcGVzTXM6IDMwMCxcbiAgICAgIGZvbGxvd0ZpbmdlcjogdHJ1ZSxcbiAgICAgIGFsbG93VG91Y2hNb3ZlOiB0cnVlLFxuICAgICAgdGhyZXNob2xkOiAwLFxuICAgICAgdG91Y2hNb3ZlU3RvcFByb3BhZ2F0aW9uOiBmYWxzZSxcbiAgICAgIHRvdWNoU3RhcnRQcmV2ZW50RGVmYXVsdDogdHJ1ZSxcbiAgICAgIHRvdWNoU3RhcnRGb3JjZVByZXZlbnREZWZhdWx0OiBmYWxzZSxcbiAgICAgIHRvdWNoUmVsZWFzZU9uRWRnZXM6IGZhbHNlLFxuICAgICAgLy8gVW5pcXVlIE5hdmlnYXRpb24gRWxlbWVudHNcbiAgICAgIHVuaXF1ZU5hdkVsZW1lbnRzOiB0cnVlLFxuICAgICAgLy8gUmVzaXN0YW5jZVxuICAgICAgcmVzaXN0YW5jZTogdHJ1ZSxcbiAgICAgIHJlc2lzdGFuY2VSYXRpbzogMC44NSxcbiAgICAgIC8vIFByb2dyZXNzXG4gICAgICB3YXRjaFNsaWRlc1Byb2dyZXNzOiBmYWxzZSxcbiAgICAgIC8vIEN1cnNvclxuICAgICAgZ3JhYkN1cnNvcjogZmFsc2UsXG4gICAgICAvLyBDbGlja3NcbiAgICAgIHByZXZlbnRDbGlja3M6IHRydWUsXG4gICAgICBwcmV2ZW50Q2xpY2tzUHJvcGFnYXRpb246IHRydWUsXG4gICAgICBzbGlkZVRvQ2xpY2tlZFNsaWRlOiBmYWxzZSxcbiAgICAgIC8vIEltYWdlc1xuICAgICAgcHJlbG9hZEltYWdlczogdHJ1ZSxcbiAgICAgIHVwZGF0ZU9uSW1hZ2VzUmVhZHk6IHRydWUsXG4gICAgICAvLyBsb29wXG4gICAgICBsb29wOiBmYWxzZSxcbiAgICAgIGxvb3BBZGRpdGlvbmFsU2xpZGVzOiAwLFxuICAgICAgbG9vcGVkU2xpZGVzOiBudWxsLFxuICAgICAgbG9vcEZpbGxHcm91cFdpdGhCbGFuazogZmFsc2UsXG4gICAgICBsb29wUHJldmVudHNTbGlkZTogdHJ1ZSxcbiAgICAgIC8vIHJld2luZFxuICAgICAgcmV3aW5kOiBmYWxzZSxcbiAgICAgIC8vIFN3aXBpbmcvbm8gc3dpcGluZ1xuICAgICAgYWxsb3dTbGlkZVByZXY6IHRydWUsXG4gICAgICBhbGxvd1NsaWRlTmV4dDogdHJ1ZSxcbiAgICAgIHN3aXBlSGFuZGxlcjogbnVsbCxcbiAgICAgIC8vICcuc3dpcGUtaGFuZGxlcicsXG4gICAgICBub1N3aXBpbmc6IHRydWUsXG4gICAgICBub1N3aXBpbmdDbGFzczogJ3N3aXBlci1uby1zd2lwaW5nJyxcbiAgICAgIG5vU3dpcGluZ1NlbGVjdG9yOiBudWxsLFxuICAgICAgLy8gUGFzc2l2ZSBMaXN0ZW5lcnNcbiAgICAgIHBhc3NpdmVMaXN0ZW5lcnM6IHRydWUsXG4gICAgICBtYXhCYWNrZmFjZUhpZGRlblNsaWRlczogMTAsXG4gICAgICAvLyBOU1xuICAgICAgY29udGFpbmVyTW9kaWZpZXJDbGFzczogJ3N3aXBlci0nLFxuICAgICAgLy8gTkVXXG4gICAgICBzbGlkZUNsYXNzOiAnc3dpcGVyLXNsaWRlJyxcbiAgICAgIHNsaWRlQmxhbmtDbGFzczogJ3N3aXBlci1zbGlkZS1pbnZpc2libGUtYmxhbmsnLFxuICAgICAgc2xpZGVBY3RpdmVDbGFzczogJ3N3aXBlci1zbGlkZS1hY3RpdmUnLFxuICAgICAgc2xpZGVEdXBsaWNhdGVBY3RpdmVDbGFzczogJ3N3aXBlci1zbGlkZS1kdXBsaWNhdGUtYWN0aXZlJyxcbiAgICAgIHNsaWRlVmlzaWJsZUNsYXNzOiAnc3dpcGVyLXNsaWRlLXZpc2libGUnLFxuICAgICAgc2xpZGVEdXBsaWNhdGVDbGFzczogJ3N3aXBlci1zbGlkZS1kdXBsaWNhdGUnLFxuICAgICAgc2xpZGVOZXh0Q2xhc3M6ICdzd2lwZXItc2xpZGUtbmV4dCcsXG4gICAgICBzbGlkZUR1cGxpY2F0ZU5leHRDbGFzczogJ3N3aXBlci1zbGlkZS1kdXBsaWNhdGUtbmV4dCcsXG4gICAgICBzbGlkZVByZXZDbGFzczogJ3N3aXBlci1zbGlkZS1wcmV2JyxcbiAgICAgIHNsaWRlRHVwbGljYXRlUHJldkNsYXNzOiAnc3dpcGVyLXNsaWRlLWR1cGxpY2F0ZS1wcmV2JyxcbiAgICAgIHdyYXBwZXJDbGFzczogJ3N3aXBlci13cmFwcGVyJyxcbiAgICAgIC8vIENhbGxiYWNrc1xuICAgICAgcnVuQ2FsbGJhY2tzT25Jbml0OiB0cnVlLFxuICAgICAgLy8gSW50ZXJuYWxzXG4gICAgICBfZW1pdENsYXNzZXM6IGZhbHNlXG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIG1vZHVsZUV4dGVuZFBhcmFtcyhwYXJhbXMsIGFsbE1vZHVsZXNQYXJhbXMpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbiBleHRlbmRQYXJhbXMob2JqKSB7XG4gICAgICAgIGlmIChvYmogPT09IHZvaWQgMCkge1xuICAgICAgICAgIG9iaiA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbW9kdWxlUGFyYW1OYW1lID0gT2JqZWN0LmtleXMob2JqKVswXTtcbiAgICAgICAgY29uc3QgbW9kdWxlUGFyYW1zID0gb2JqW21vZHVsZVBhcmFtTmFtZV07XG5cbiAgICAgICAgaWYgKHR5cGVvZiBtb2R1bGVQYXJhbXMgIT09ICdvYmplY3QnIHx8IG1vZHVsZVBhcmFtcyA9PT0gbnVsbCkge1xuICAgICAgICAgIGV4dGVuZChhbGxNb2R1bGVzUGFyYW1zLCBvYmopO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChbJ25hdmlnYXRpb24nLCAncGFnaW5hdGlvbicsICdzY3JvbGxiYXInXS5pbmRleE9mKG1vZHVsZVBhcmFtTmFtZSkgPj0gMCAmJiBwYXJhbXNbbW9kdWxlUGFyYW1OYW1lXSA9PT0gdHJ1ZSkge1xuICAgICAgICAgIHBhcmFtc1ttb2R1bGVQYXJhbU5hbWVdID0ge1xuICAgICAgICAgICAgYXV0bzogdHJ1ZVxuICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIShtb2R1bGVQYXJhbU5hbWUgaW4gcGFyYW1zICYmICdlbmFibGVkJyBpbiBtb2R1bGVQYXJhbXMpKSB7XG4gICAgICAgICAgZXh0ZW5kKGFsbE1vZHVsZXNQYXJhbXMsIG9iaik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtc1ttb2R1bGVQYXJhbU5hbWVdID09PSB0cnVlKSB7XG4gICAgICAgICAgcGFyYW1zW21vZHVsZVBhcmFtTmFtZV0gPSB7XG4gICAgICAgICAgICBlbmFibGVkOiB0cnVlXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgcGFyYW1zW21vZHVsZVBhcmFtTmFtZV0gPT09ICdvYmplY3QnICYmICEoJ2VuYWJsZWQnIGluIHBhcmFtc1ttb2R1bGVQYXJhbU5hbWVdKSkge1xuICAgICAgICAgIHBhcmFtc1ttb2R1bGVQYXJhbU5hbWVdLmVuYWJsZWQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFwYXJhbXNbbW9kdWxlUGFyYW1OYW1lXSkgcGFyYW1zW21vZHVsZVBhcmFtTmFtZV0gPSB7XG4gICAgICAgICAgZW5hYmxlZDogZmFsc2VcbiAgICAgICAgfTtcbiAgICAgICAgZXh0ZW5kKGFsbE1vZHVsZXNQYXJhbXMsIG9iaik7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qIGVzbGludCBuby1wYXJhbS1yZWFzc2lnbjogXCJvZmZcIiAqL1xuICAgIGNvbnN0IHByb3RvdHlwZXMgPSB7XG4gICAgICBldmVudHNFbWl0dGVyLFxuICAgICAgdXBkYXRlLFxuICAgICAgdHJhbnNsYXRlLFxuICAgICAgdHJhbnNpdGlvbixcbiAgICAgIHNsaWRlLFxuICAgICAgbG9vcCxcbiAgICAgIGdyYWJDdXJzb3IsXG4gICAgICBldmVudHM6IGV2ZW50cyQxLFxuICAgICAgYnJlYWtwb2ludHMsXG4gICAgICBjaGVja092ZXJmbG93OiBjaGVja092ZXJmbG93JDEsXG4gICAgICBjbGFzc2VzLFxuICAgICAgaW1hZ2VzXG4gICAgfTtcbiAgICBjb25zdCBleHRlbmRlZERlZmF1bHRzID0ge307XG5cbiAgICBjbGFzcyBTd2lwZXIge1xuICAgICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIGxldCBlbDtcbiAgICAgICAgbGV0IHBhcmFtcztcblxuICAgICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICAgICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID09PSAxICYmIGFyZ3NbMF0uY29uc3RydWN0b3IgJiYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGFyZ3NbMF0pLnNsaWNlKDgsIC0xKSA9PT0gJ09iamVjdCcpIHtcbiAgICAgICAgICBwYXJhbXMgPSBhcmdzWzBdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIFtlbCwgcGFyYW1zXSA9IGFyZ3M7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXBhcmFtcykgcGFyYW1zID0ge307XG4gICAgICAgIHBhcmFtcyA9IGV4dGVuZCh7fSwgcGFyYW1zKTtcbiAgICAgICAgaWYgKGVsICYmICFwYXJhbXMuZWwpIHBhcmFtcy5lbCA9IGVsO1xuXG4gICAgICAgIGlmIChwYXJhbXMuZWwgJiYgJChwYXJhbXMuZWwpLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICBjb25zdCBzd2lwZXJzID0gW107XG4gICAgICAgICAgJChwYXJhbXMuZWwpLmVhY2goY29udGFpbmVyRWwgPT4ge1xuICAgICAgICAgICAgY29uc3QgbmV3UGFyYW1zID0gZXh0ZW5kKHt9LCBwYXJhbXMsIHtcbiAgICAgICAgICAgICAgZWw6IGNvbnRhaW5lckVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHN3aXBlcnMucHVzaChuZXcgU3dpcGVyKG5ld1BhcmFtcykpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiBzd2lwZXJzO1xuICAgICAgICB9IC8vIFN3aXBlciBJbnN0YW5jZVxuXG5cbiAgICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgICAgc3dpcGVyLl9fc3dpcGVyX18gPSB0cnVlO1xuICAgICAgICBzd2lwZXIuc3VwcG9ydCA9IGdldFN1cHBvcnQoKTtcbiAgICAgICAgc3dpcGVyLmRldmljZSA9IGdldERldmljZSh7XG4gICAgICAgICAgdXNlckFnZW50OiBwYXJhbXMudXNlckFnZW50XG4gICAgICAgIH0pO1xuICAgICAgICBzd2lwZXIuYnJvd3NlciA9IGdldEJyb3dzZXIoKTtcbiAgICAgICAgc3dpcGVyLmV2ZW50c0xpc3RlbmVycyA9IHt9O1xuICAgICAgICBzd2lwZXIuZXZlbnRzQW55TGlzdGVuZXJzID0gW107XG4gICAgICAgIHN3aXBlci5tb2R1bGVzID0gWy4uLnN3aXBlci5fX21vZHVsZXNfX107XG5cbiAgICAgICAgaWYgKHBhcmFtcy5tb2R1bGVzICYmIEFycmF5LmlzQXJyYXkocGFyYW1zLm1vZHVsZXMpKSB7XG4gICAgICAgICAgc3dpcGVyLm1vZHVsZXMucHVzaCguLi5wYXJhbXMubW9kdWxlcyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBhbGxNb2R1bGVzUGFyYW1zID0ge307XG4gICAgICAgIHN3aXBlci5tb2R1bGVzLmZvckVhY2gobW9kID0+IHtcbiAgICAgICAgICBtb2Qoe1xuICAgICAgICAgICAgc3dpcGVyLFxuICAgICAgICAgICAgZXh0ZW5kUGFyYW1zOiBtb2R1bGVFeHRlbmRQYXJhbXMocGFyYW1zLCBhbGxNb2R1bGVzUGFyYW1zKSxcbiAgICAgICAgICAgIG9uOiBzd2lwZXIub24uYmluZChzd2lwZXIpLFxuICAgICAgICAgICAgb25jZTogc3dpcGVyLm9uY2UuYmluZChzd2lwZXIpLFxuICAgICAgICAgICAgb2ZmOiBzd2lwZXIub2ZmLmJpbmQoc3dpcGVyKSxcbiAgICAgICAgICAgIGVtaXQ6IHN3aXBlci5lbWl0LmJpbmQoc3dpcGVyKVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTsgLy8gRXh0ZW5kIGRlZmF1bHRzIHdpdGggbW9kdWxlcyBwYXJhbXNcblxuICAgICAgICBjb25zdCBzd2lwZXJQYXJhbXMgPSBleHRlbmQoe30sIGRlZmF1bHRzLCBhbGxNb2R1bGVzUGFyYW1zKTsgLy8gRXh0ZW5kIGRlZmF1bHRzIHdpdGggcGFzc2VkIHBhcmFtc1xuXG4gICAgICAgIHN3aXBlci5wYXJhbXMgPSBleHRlbmQoe30sIHN3aXBlclBhcmFtcywgZXh0ZW5kZWREZWZhdWx0cywgcGFyYW1zKTtcbiAgICAgICAgc3dpcGVyLm9yaWdpbmFsUGFyYW1zID0gZXh0ZW5kKHt9LCBzd2lwZXIucGFyYW1zKTtcbiAgICAgICAgc3dpcGVyLnBhc3NlZFBhcmFtcyA9IGV4dGVuZCh7fSwgcGFyYW1zKTsgLy8gYWRkIGV2ZW50IGxpc3RlbmVyc1xuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zICYmIHN3aXBlci5wYXJhbXMub24pIHtcbiAgICAgICAgICBPYmplY3Qua2V5cyhzd2lwZXIucGFyYW1zLm9uKS5mb3JFYWNoKGV2ZW50TmFtZSA9PiB7XG4gICAgICAgICAgICBzd2lwZXIub24oZXZlbnROYW1lLCBzd2lwZXIucGFyYW1zLm9uW2V2ZW50TmFtZV0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMgJiYgc3dpcGVyLnBhcmFtcy5vbkFueSkge1xuICAgICAgICAgIHN3aXBlci5vbkFueShzd2lwZXIucGFyYW1zLm9uQW55KTtcbiAgICAgICAgfSAvLyBTYXZlIERvbSBsaWJcblxuXG4gICAgICAgIHN3aXBlci4kID0gJDsgLy8gRXh0ZW5kIFN3aXBlclxuXG4gICAgICAgIE9iamVjdC5hc3NpZ24oc3dpcGVyLCB7XG4gICAgICAgICAgZW5hYmxlZDogc3dpcGVyLnBhcmFtcy5lbmFibGVkLFxuICAgICAgICAgIGVsLFxuICAgICAgICAgIC8vIENsYXNzZXNcbiAgICAgICAgICBjbGFzc05hbWVzOiBbXSxcbiAgICAgICAgICAvLyBTbGlkZXNcbiAgICAgICAgICBzbGlkZXM6ICQoKSxcbiAgICAgICAgICBzbGlkZXNHcmlkOiBbXSxcbiAgICAgICAgICBzbmFwR3JpZDogW10sXG4gICAgICAgICAgc2xpZGVzU2l6ZXNHcmlkOiBbXSxcblxuICAgICAgICAgIC8vIGlzRGlyZWN0aW9uXG4gICAgICAgICAgaXNIb3Jpem9udGFsKCkge1xuICAgICAgICAgICAgcmV0dXJuIHN3aXBlci5wYXJhbXMuZGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCc7XG4gICAgICAgICAgfSxcblxuICAgICAgICAgIGlzVmVydGljYWwoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3dpcGVyLnBhcmFtcy5kaXJlY3Rpb24gPT09ICd2ZXJ0aWNhbCc7XG4gICAgICAgICAgfSxcblxuICAgICAgICAgIC8vIEluZGV4ZXNcbiAgICAgICAgICBhY3RpdmVJbmRleDogMCxcbiAgICAgICAgICByZWFsSW5kZXg6IDAsXG4gICAgICAgICAgLy9cbiAgICAgICAgICBpc0JlZ2lubmluZzogdHJ1ZSxcbiAgICAgICAgICBpc0VuZDogZmFsc2UsXG4gICAgICAgICAgLy8gUHJvcHNcbiAgICAgICAgICB0cmFuc2xhdGU6IDAsXG4gICAgICAgICAgcHJldmlvdXNUcmFuc2xhdGU6IDAsXG4gICAgICAgICAgcHJvZ3Jlc3M6IDAsXG4gICAgICAgICAgdmVsb2NpdHk6IDAsXG4gICAgICAgICAgYW5pbWF0aW5nOiBmYWxzZSxcbiAgICAgICAgICAvLyBMb2Nrc1xuICAgICAgICAgIGFsbG93U2xpZGVOZXh0OiBzd2lwZXIucGFyYW1zLmFsbG93U2xpZGVOZXh0LFxuICAgICAgICAgIGFsbG93U2xpZGVQcmV2OiBzd2lwZXIucGFyYW1zLmFsbG93U2xpZGVQcmV2LFxuICAgICAgICAgIC8vIFRvdWNoIEV2ZW50c1xuICAgICAgICAgIHRvdWNoRXZlbnRzOiBmdW5jdGlvbiB0b3VjaEV2ZW50cygpIHtcbiAgICAgICAgICAgIGNvbnN0IHRvdWNoID0gWyd0b3VjaHN0YXJ0JywgJ3RvdWNobW92ZScsICd0b3VjaGVuZCcsICd0b3VjaGNhbmNlbCddO1xuICAgICAgICAgICAgY29uc3QgZGVza3RvcCA9IFsncG9pbnRlcmRvd24nLCAncG9pbnRlcm1vdmUnLCAncG9pbnRlcnVwJ107XG4gICAgICAgICAgICBzd2lwZXIudG91Y2hFdmVudHNUb3VjaCA9IHtcbiAgICAgICAgICAgICAgc3RhcnQ6IHRvdWNoWzBdLFxuICAgICAgICAgICAgICBtb3ZlOiB0b3VjaFsxXSxcbiAgICAgICAgICAgICAgZW5kOiB0b3VjaFsyXSxcbiAgICAgICAgICAgICAgY2FuY2VsOiB0b3VjaFszXVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHN3aXBlci50b3VjaEV2ZW50c0Rlc2t0b3AgPSB7XG4gICAgICAgICAgICAgIHN0YXJ0OiBkZXNrdG9wWzBdLFxuICAgICAgICAgICAgICBtb3ZlOiBkZXNrdG9wWzFdLFxuICAgICAgICAgICAgICBlbmQ6IGRlc2t0b3BbMl1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm4gc3dpcGVyLnN1cHBvcnQudG91Y2ggfHwgIXN3aXBlci5wYXJhbXMuc2ltdWxhdGVUb3VjaCA/IHN3aXBlci50b3VjaEV2ZW50c1RvdWNoIDogc3dpcGVyLnRvdWNoRXZlbnRzRGVza3RvcDtcbiAgICAgICAgICB9KCksXG4gICAgICAgICAgdG91Y2hFdmVudHNEYXRhOiB7XG4gICAgICAgICAgICBpc1RvdWNoZWQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGlzTW92ZWQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGFsbG93VG91Y2hDYWxsYmFja3M6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHRvdWNoU3RhcnRUaW1lOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBpc1Njcm9sbGluZzogdW5kZWZpbmVkLFxuICAgICAgICAgICAgY3VycmVudFRyYW5zbGF0ZTogdW5kZWZpbmVkLFxuICAgICAgICAgICAgc3RhcnRUcmFuc2xhdGU6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGFsbG93VGhyZXNob2xkTW92ZTogdW5kZWZpbmVkLFxuICAgICAgICAgICAgLy8gRm9ybSBlbGVtZW50cyB0byBtYXRjaFxuICAgICAgICAgICAgZm9jdXNhYmxlRWxlbWVudHM6IHN3aXBlci5wYXJhbXMuZm9jdXNhYmxlRWxlbWVudHMsXG4gICAgICAgICAgICAvLyBMYXN0IGNsaWNrIHRpbWVcbiAgICAgICAgICAgIGxhc3RDbGlja1RpbWU6IG5vdygpLFxuICAgICAgICAgICAgY2xpY2tUaW1lb3V0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICAvLyBWZWxvY2l0aWVzXG4gICAgICAgICAgICB2ZWxvY2l0aWVzOiBbXSxcbiAgICAgICAgICAgIGFsbG93TW9tZW50dW1Cb3VuY2U6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGlzVG91Y2hFdmVudDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgc3RhcnRNb3Zpbmc6IHVuZGVmaW5lZFxuICAgICAgICAgIH0sXG4gICAgICAgICAgLy8gQ2xpY2tzXG4gICAgICAgICAgYWxsb3dDbGljazogdHJ1ZSxcbiAgICAgICAgICAvLyBUb3VjaGVzXG4gICAgICAgICAgYWxsb3dUb3VjaE1vdmU6IHN3aXBlci5wYXJhbXMuYWxsb3dUb3VjaE1vdmUsXG4gICAgICAgICAgdG91Y2hlczoge1xuICAgICAgICAgICAgc3RhcnRYOiAwLFxuICAgICAgICAgICAgc3RhcnRZOiAwLFxuICAgICAgICAgICAgY3VycmVudFg6IDAsXG4gICAgICAgICAgICBjdXJyZW50WTogMCxcbiAgICAgICAgICAgIGRpZmY6IDBcbiAgICAgICAgICB9LFxuICAgICAgICAgIC8vIEltYWdlc1xuICAgICAgICAgIGltYWdlc1RvTG9hZDogW10sXG4gICAgICAgICAgaW1hZ2VzTG9hZGVkOiAwXG4gICAgICAgIH0pO1xuICAgICAgICBzd2lwZXIuZW1pdCgnX3N3aXBlcicpOyAvLyBJbml0XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuaW5pdCkge1xuICAgICAgICAgIHN3aXBlci5pbml0KCk7XG4gICAgICAgIH0gLy8gUmV0dXJuIGFwcCBpbnN0YW5jZVxuXG5cbiAgICAgICAgcmV0dXJuIHN3aXBlcjtcbiAgICAgIH1cblxuICAgICAgZW5hYmxlKCkge1xuICAgICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgICBpZiAoc3dpcGVyLmVuYWJsZWQpIHJldHVybjtcbiAgICAgICAgc3dpcGVyLmVuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmdyYWJDdXJzb3IpIHtcbiAgICAgICAgICBzd2lwZXIuc2V0R3JhYkN1cnNvcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpcGVyLmVtaXQoJ2VuYWJsZScpO1xuICAgICAgfVxuXG4gICAgICBkaXNhYmxlKCkge1xuICAgICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgICBpZiAoIXN3aXBlci5lbmFibGVkKSByZXR1cm47XG4gICAgICAgIHN3aXBlci5lbmFibGVkID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuZ3JhYkN1cnNvcikge1xuICAgICAgICAgIHN3aXBlci51bnNldEdyYWJDdXJzb3IoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci5lbWl0KCdkaXNhYmxlJyk7XG4gICAgICB9XG5cbiAgICAgIHNldFByb2dyZXNzKHByb2dyZXNzLCBzcGVlZCkge1xuICAgICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgICBwcm9ncmVzcyA9IE1hdGgubWluKE1hdGgubWF4KHByb2dyZXNzLCAwKSwgMSk7XG4gICAgICAgIGNvbnN0IG1pbiA9IHN3aXBlci5taW5UcmFuc2xhdGUoKTtcbiAgICAgICAgY29uc3QgbWF4ID0gc3dpcGVyLm1heFRyYW5zbGF0ZSgpO1xuICAgICAgICBjb25zdCBjdXJyZW50ID0gKG1heCAtIG1pbikgKiBwcm9ncmVzcyArIG1pbjtcbiAgICAgICAgc3dpcGVyLnRyYW5zbGF0ZVRvKGN1cnJlbnQsIHR5cGVvZiBzcGVlZCA9PT0gJ3VuZGVmaW5lZCcgPyAwIDogc3BlZWQpO1xuICAgICAgICBzd2lwZXIudXBkYXRlQWN0aXZlSW5kZXgoKTtcbiAgICAgICAgc3dpcGVyLnVwZGF0ZVNsaWRlc0NsYXNzZXMoKTtcbiAgICAgIH1cblxuICAgICAgZW1pdENvbnRhaW5lckNsYXNzZXMoKSB7XG4gICAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy5fZW1pdENsYXNzZXMgfHwgIXN3aXBlci5lbCkgcmV0dXJuO1xuICAgICAgICBjb25zdCBjbHMgPSBzd2lwZXIuZWwuY2xhc3NOYW1lLnNwbGl0KCcgJykuZmlsdGVyKGNsYXNzTmFtZSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGNsYXNzTmFtZS5pbmRleE9mKCdzd2lwZXInKSA9PT0gMCB8fCBjbGFzc05hbWUuaW5kZXhPZihzd2lwZXIucGFyYW1zLmNvbnRhaW5lck1vZGlmaWVyQ2xhc3MpID09PSAwO1xuICAgICAgICB9KTtcbiAgICAgICAgc3dpcGVyLmVtaXQoJ19jb250YWluZXJDbGFzc2VzJywgY2xzLmpvaW4oJyAnKSk7XG4gICAgICB9XG5cbiAgICAgIGdldFNsaWRlQ2xhc3NlcyhzbGlkZUVsKSB7XG4gICAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICAgIHJldHVybiBzbGlkZUVsLmNsYXNzTmFtZS5zcGxpdCgnICcpLmZpbHRlcihjbGFzc05hbWUgPT4ge1xuICAgICAgICAgIHJldHVybiBjbGFzc05hbWUuaW5kZXhPZignc3dpcGVyLXNsaWRlJykgPT09IDAgfHwgY2xhc3NOYW1lLmluZGV4T2Yoc3dpcGVyLnBhcmFtcy5zbGlkZUNsYXNzKSA9PT0gMDtcbiAgICAgICAgfSkuam9pbignICcpO1xuICAgICAgfVxuXG4gICAgICBlbWl0U2xpZGVzQ2xhc3NlcygpIHtcbiAgICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgICAgaWYgKCFzd2lwZXIucGFyYW1zLl9lbWl0Q2xhc3NlcyB8fCAhc3dpcGVyLmVsKSByZXR1cm47XG4gICAgICAgIGNvbnN0IHVwZGF0ZXMgPSBbXTtcbiAgICAgICAgc3dpcGVyLnNsaWRlcy5lYWNoKHNsaWRlRWwgPT4ge1xuICAgICAgICAgIGNvbnN0IGNsYXNzTmFtZXMgPSBzd2lwZXIuZ2V0U2xpZGVDbGFzc2VzKHNsaWRlRWwpO1xuICAgICAgICAgIHVwZGF0ZXMucHVzaCh7XG4gICAgICAgICAgICBzbGlkZUVsLFxuICAgICAgICAgICAgY2xhc3NOYW1lc1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHN3aXBlci5lbWl0KCdfc2xpZGVDbGFzcycsIHNsaWRlRWwsIGNsYXNzTmFtZXMpO1xuICAgICAgICB9KTtcbiAgICAgICAgc3dpcGVyLmVtaXQoJ19zbGlkZUNsYXNzZXMnLCB1cGRhdGVzKTtcbiAgICAgIH1cblxuICAgICAgc2xpZGVzUGVyVmlld0R5bmFtaWModmlldywgZXhhY3QpIHtcbiAgICAgICAgaWYgKHZpZXcgPT09IHZvaWQgMCkge1xuICAgICAgICAgIHZpZXcgPSAnY3VycmVudCc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXhhY3QgPT09IHZvaWQgMCkge1xuICAgICAgICAgIGV4YWN0ID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgIHNsaWRlcyxcbiAgICAgICAgICBzbGlkZXNHcmlkLFxuICAgICAgICAgIHNsaWRlc1NpemVzR3JpZCxcbiAgICAgICAgICBzaXplOiBzd2lwZXJTaXplLFxuICAgICAgICAgIGFjdGl2ZUluZGV4XG4gICAgICAgIH0gPSBzd2lwZXI7XG4gICAgICAgIGxldCBzcHYgPSAxO1xuXG4gICAgICAgIGlmIChwYXJhbXMuY2VudGVyZWRTbGlkZXMpIHtcbiAgICAgICAgICBsZXQgc2xpZGVTaXplID0gc2xpZGVzW2FjdGl2ZUluZGV4XS5zd2lwZXJTbGlkZVNpemU7XG4gICAgICAgICAgbGV0IGJyZWFrTG9vcDtcblxuICAgICAgICAgIGZvciAobGV0IGkgPSBhY3RpdmVJbmRleCArIDE7IGkgPCBzbGlkZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGlmIChzbGlkZXNbaV0gJiYgIWJyZWFrTG9vcCkge1xuICAgICAgICAgICAgICBzbGlkZVNpemUgKz0gc2xpZGVzW2ldLnN3aXBlclNsaWRlU2l6ZTtcbiAgICAgICAgICAgICAgc3B2ICs9IDE7XG4gICAgICAgICAgICAgIGlmIChzbGlkZVNpemUgPiBzd2lwZXJTaXplKSBicmVha0xvb3AgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGZvciAobGV0IGkgPSBhY3RpdmVJbmRleCAtIDE7IGkgPj0gMDsgaSAtPSAxKSB7XG4gICAgICAgICAgICBpZiAoc2xpZGVzW2ldICYmICFicmVha0xvb3ApIHtcbiAgICAgICAgICAgICAgc2xpZGVTaXplICs9IHNsaWRlc1tpXS5zd2lwZXJTbGlkZVNpemU7XG4gICAgICAgICAgICAgIHNwdiArPSAxO1xuICAgICAgICAgICAgICBpZiAoc2xpZGVTaXplID4gc3dpcGVyU2l6ZSkgYnJlYWtMb29wID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgaWYgKHZpZXcgPT09ICdjdXJyZW50Jykge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGFjdGl2ZUluZGV4ICsgMTsgaSA8IHNsaWRlcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgICBjb25zdCBzbGlkZUluVmlldyA9IGV4YWN0ID8gc2xpZGVzR3JpZFtpXSArIHNsaWRlc1NpemVzR3JpZFtpXSAtIHNsaWRlc0dyaWRbYWN0aXZlSW5kZXhdIDwgc3dpcGVyU2l6ZSA6IHNsaWRlc0dyaWRbaV0gLSBzbGlkZXNHcmlkW2FjdGl2ZUluZGV4XSA8IHN3aXBlclNpemU7XG5cbiAgICAgICAgICAgICAgaWYgKHNsaWRlSW5WaWV3KSB7XG4gICAgICAgICAgICAgICAgc3B2ICs9IDE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gcHJldmlvdXNcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBhY3RpdmVJbmRleCAtIDE7IGkgPj0gMDsgaSAtPSAxKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHNsaWRlSW5WaWV3ID0gc2xpZGVzR3JpZFthY3RpdmVJbmRleF0gLSBzbGlkZXNHcmlkW2ldIDwgc3dpcGVyU2l6ZTtcblxuICAgICAgICAgICAgICBpZiAoc2xpZGVJblZpZXcpIHtcbiAgICAgICAgICAgICAgICBzcHYgKz0gMTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzcHY7XG4gICAgICB9XG5cbiAgICAgIHVwZGF0ZSgpIHtcbiAgICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgICAgaWYgKCFzd2lwZXIgfHwgc3dpcGVyLmRlc3Ryb3llZCkgcmV0dXJuO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgc25hcEdyaWQsXG4gICAgICAgICAgcGFyYW1zXG4gICAgICAgIH0gPSBzd2lwZXI7IC8vIEJyZWFrcG9pbnRzXG5cbiAgICAgICAgaWYgKHBhcmFtcy5icmVha3BvaW50cykge1xuICAgICAgICAgIHN3aXBlci5zZXRCcmVha3BvaW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICBzd2lwZXIudXBkYXRlU2l6ZSgpO1xuICAgICAgICBzd2lwZXIudXBkYXRlU2xpZGVzKCk7XG4gICAgICAgIHN3aXBlci51cGRhdGVQcm9ncmVzcygpO1xuICAgICAgICBzd2lwZXIudXBkYXRlU2xpZGVzQ2xhc3NlcygpO1xuXG4gICAgICAgIGZ1bmN0aW9uIHNldFRyYW5zbGF0ZSgpIHtcbiAgICAgICAgICBjb25zdCB0cmFuc2xhdGVWYWx1ZSA9IHN3aXBlci5ydGxUcmFuc2xhdGUgPyBzd2lwZXIudHJhbnNsYXRlICogLTEgOiBzd2lwZXIudHJhbnNsYXRlO1xuICAgICAgICAgIGNvbnN0IG5ld1RyYW5zbGF0ZSA9IE1hdGgubWluKE1hdGgubWF4KHRyYW5zbGF0ZVZhbHVlLCBzd2lwZXIubWF4VHJhbnNsYXRlKCkpLCBzd2lwZXIubWluVHJhbnNsYXRlKCkpO1xuICAgICAgICAgIHN3aXBlci5zZXRUcmFuc2xhdGUobmV3VHJhbnNsYXRlKTtcbiAgICAgICAgICBzd2lwZXIudXBkYXRlQWN0aXZlSW5kZXgoKTtcbiAgICAgICAgICBzd2lwZXIudXBkYXRlU2xpZGVzQ2xhc3NlcygpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRyYW5zbGF0ZWQ7XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuZnJlZU1vZGUgJiYgc3dpcGVyLnBhcmFtcy5mcmVlTW9kZS5lbmFibGVkKSB7XG4gICAgICAgICAgc2V0VHJhbnNsYXRlKCk7XG5cbiAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5hdXRvSGVpZ2h0KSB7XG4gICAgICAgICAgICBzd2lwZXIudXBkYXRlQXV0b0hlaWdodCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoKHN3aXBlci5wYXJhbXMuc2xpZGVzUGVyVmlldyA9PT0gJ2F1dG8nIHx8IHN3aXBlci5wYXJhbXMuc2xpZGVzUGVyVmlldyA+IDEpICYmIHN3aXBlci5pc0VuZCAmJiAhc3dpcGVyLnBhcmFtcy5jZW50ZXJlZFNsaWRlcykge1xuICAgICAgICAgICAgdHJhbnNsYXRlZCA9IHN3aXBlci5zbGlkZVRvKHN3aXBlci5zbGlkZXMubGVuZ3RoIC0gMSwgMCwgZmFsc2UsIHRydWUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0cmFuc2xhdGVkID0gc3dpcGVyLnNsaWRlVG8oc3dpcGVyLmFjdGl2ZUluZGV4LCAwLCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCF0cmFuc2xhdGVkKSB7XG4gICAgICAgICAgICBzZXRUcmFuc2xhdGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLndhdGNoT3ZlcmZsb3cgJiYgc25hcEdyaWQgIT09IHN3aXBlci5zbmFwR3JpZCkge1xuICAgICAgICAgIHN3aXBlci5jaGVja092ZXJmbG93KCk7XG4gICAgICAgIH1cblxuICAgICAgICBzd2lwZXIuZW1pdCgndXBkYXRlJyk7XG4gICAgICB9XG5cbiAgICAgIGNoYW5nZURpcmVjdGlvbihuZXdEaXJlY3Rpb24sIG5lZWRVcGRhdGUpIHtcbiAgICAgICAgaWYgKG5lZWRVcGRhdGUgPT09IHZvaWQgMCkge1xuICAgICAgICAgIG5lZWRVcGRhdGUgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgICAgY29uc3QgY3VycmVudERpcmVjdGlvbiA9IHN3aXBlci5wYXJhbXMuZGlyZWN0aW9uO1xuXG4gICAgICAgIGlmICghbmV3RGlyZWN0aW9uKSB7XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgbmV3RGlyZWN0aW9uID0gY3VycmVudERpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnID8gJ3ZlcnRpY2FsJyA6ICdob3Jpem9udGFsJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChuZXdEaXJlY3Rpb24gPT09IGN1cnJlbnREaXJlY3Rpb24gfHwgbmV3RGlyZWN0aW9uICE9PSAnaG9yaXpvbnRhbCcgJiYgbmV3RGlyZWN0aW9uICE9PSAndmVydGljYWwnKSB7XG4gICAgICAgICAgcmV0dXJuIHN3aXBlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci4kZWwucmVtb3ZlQ2xhc3MoYCR7c3dpcGVyLnBhcmFtcy5jb250YWluZXJNb2RpZmllckNsYXNzfSR7Y3VycmVudERpcmVjdGlvbn1gKS5hZGRDbGFzcyhgJHtzd2lwZXIucGFyYW1zLmNvbnRhaW5lck1vZGlmaWVyQ2xhc3N9JHtuZXdEaXJlY3Rpb259YCk7XG4gICAgICAgIHN3aXBlci5lbWl0Q29udGFpbmVyQ2xhc3NlcygpO1xuICAgICAgICBzd2lwZXIucGFyYW1zLmRpcmVjdGlvbiA9IG5ld0RpcmVjdGlvbjtcbiAgICAgICAgc3dpcGVyLnNsaWRlcy5lYWNoKHNsaWRlRWwgPT4ge1xuICAgICAgICAgIGlmIChuZXdEaXJlY3Rpb24gPT09ICd2ZXJ0aWNhbCcpIHtcbiAgICAgICAgICAgIHNsaWRlRWwuc3R5bGUud2lkdGggPSAnJztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2xpZGVFbC5zdHlsZS5oZWlnaHQgPSAnJztcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBzd2lwZXIuZW1pdCgnY2hhbmdlRGlyZWN0aW9uJyk7XG4gICAgICAgIGlmIChuZWVkVXBkYXRlKSBzd2lwZXIudXBkYXRlKCk7XG4gICAgICAgIHJldHVybiBzd2lwZXI7XG4gICAgICB9XG5cbiAgICAgIG1vdW50KGVsKSB7XG4gICAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICAgIGlmIChzd2lwZXIubW91bnRlZCkgcmV0dXJuIHRydWU7IC8vIEZpbmQgZWxcblxuICAgICAgICBjb25zdCAkZWwgPSAkKGVsIHx8IHN3aXBlci5wYXJhbXMuZWwpO1xuICAgICAgICBlbCA9ICRlbFswXTtcblxuICAgICAgICBpZiAoIWVsKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgZWwuc3dpcGVyID0gc3dpcGVyO1xuXG4gICAgICAgIGNvbnN0IGdldFdyYXBwZXJTZWxlY3RvciA9ICgpID0+IHtcbiAgICAgICAgICByZXR1cm4gYC4keyhzd2lwZXIucGFyYW1zLndyYXBwZXJDbGFzcyB8fCAnJykudHJpbSgpLnNwbGl0KCcgJykuam9pbignLicpfWA7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZ2V0V3JhcHBlciA9ICgpID0+IHtcbiAgICAgICAgICBpZiAoZWwgJiYgZWwuc2hhZG93Um9vdCAmJiBlbC5zaGFkb3dSb290LnF1ZXJ5U2VsZWN0b3IpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlcyA9ICQoZWwuc2hhZG93Um9vdC5xdWVyeVNlbGVjdG9yKGdldFdyYXBwZXJTZWxlY3RvcigpKSk7IC8vIENoaWxkcmVuIG5lZWRzIHRvIHJldHVybiBzbG90IGl0ZW1zXG5cbiAgICAgICAgICAgIHJlcy5jaGlsZHJlbiA9IG9wdGlvbnMgPT4gJGVsLmNoaWxkcmVuKG9wdGlvbnMpO1xuXG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiAkZWwuY2hpbGRyZW4oZ2V0V3JhcHBlclNlbGVjdG9yKCkpO1xuICAgICAgICB9OyAvLyBGaW5kIFdyYXBwZXJcblxuXG4gICAgICAgIGxldCAkd3JhcHBlckVsID0gZ2V0V3JhcHBlcigpO1xuXG4gICAgICAgIGlmICgkd3JhcHBlckVsLmxlbmd0aCA9PT0gMCAmJiBzd2lwZXIucGFyYW1zLmNyZWF0ZUVsZW1lbnRzKSB7XG4gICAgICAgICAgY29uc3QgZG9jdW1lbnQgPSBnZXREb2N1bWVudCgpO1xuICAgICAgICAgIGNvbnN0IHdyYXBwZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgICAkd3JhcHBlckVsID0gJCh3cmFwcGVyKTtcbiAgICAgICAgICB3cmFwcGVyLmNsYXNzTmFtZSA9IHN3aXBlci5wYXJhbXMud3JhcHBlckNsYXNzO1xuICAgICAgICAgICRlbC5hcHBlbmQod3JhcHBlcik7XG4gICAgICAgICAgJGVsLmNoaWxkcmVuKGAuJHtzd2lwZXIucGFyYW1zLnNsaWRlQ2xhc3N9YCkuZWFjaChzbGlkZUVsID0+IHtcbiAgICAgICAgICAgICR3cmFwcGVyRWwuYXBwZW5kKHNsaWRlRWwpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgT2JqZWN0LmFzc2lnbihzd2lwZXIsIHtcbiAgICAgICAgICAkZWwsXG4gICAgICAgICAgZWwsXG4gICAgICAgICAgJHdyYXBwZXJFbCxcbiAgICAgICAgICB3cmFwcGVyRWw6ICR3cmFwcGVyRWxbMF0sXG4gICAgICAgICAgbW91bnRlZDogdHJ1ZSxcbiAgICAgICAgICAvLyBSVExcbiAgICAgICAgICBydGw6IGVsLmRpci50b0xvd2VyQ2FzZSgpID09PSAncnRsJyB8fCAkZWwuY3NzKCdkaXJlY3Rpb24nKSA9PT0gJ3J0bCcsXG4gICAgICAgICAgcnRsVHJhbnNsYXRlOiBzd2lwZXIucGFyYW1zLmRpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnICYmIChlbC5kaXIudG9Mb3dlckNhc2UoKSA9PT0gJ3J0bCcgfHwgJGVsLmNzcygnZGlyZWN0aW9uJykgPT09ICdydGwnKSxcbiAgICAgICAgICB3cm9uZ1JUTDogJHdyYXBwZXJFbC5jc3MoJ2Rpc3BsYXknKSA9PT0gJy13ZWJraXQtYm94J1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIGluaXQoZWwpIHtcbiAgICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgICAgaWYgKHN3aXBlci5pbml0aWFsaXplZCkgcmV0dXJuIHN3aXBlcjtcbiAgICAgICAgY29uc3QgbW91bnRlZCA9IHN3aXBlci5tb3VudChlbCk7XG4gICAgICAgIGlmIChtb3VudGVkID09PSBmYWxzZSkgcmV0dXJuIHN3aXBlcjtcbiAgICAgICAgc3dpcGVyLmVtaXQoJ2JlZm9yZUluaXQnKTsgLy8gU2V0IGJyZWFrcG9pbnRcblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5icmVha3BvaW50cykge1xuICAgICAgICAgIHN3aXBlci5zZXRCcmVha3BvaW50KCk7XG4gICAgICAgIH0gLy8gQWRkIENsYXNzZXNcblxuXG4gICAgICAgIHN3aXBlci5hZGRDbGFzc2VzKCk7IC8vIENyZWF0ZSBsb29wXG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMubG9vcCkge1xuICAgICAgICAgIHN3aXBlci5sb29wQ3JlYXRlKCk7XG4gICAgICAgIH0gLy8gVXBkYXRlIHNpemVcblxuXG4gICAgICAgIHN3aXBlci51cGRhdGVTaXplKCk7IC8vIFVwZGF0ZSBzbGlkZXNcblxuICAgICAgICBzd2lwZXIudXBkYXRlU2xpZGVzKCk7XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMud2F0Y2hPdmVyZmxvdykge1xuICAgICAgICAgIHN3aXBlci5jaGVja092ZXJmbG93KCk7XG4gICAgICAgIH0gLy8gU2V0IEdyYWIgQ3Vyc29yXG5cblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5ncmFiQ3Vyc29yICYmIHN3aXBlci5lbmFibGVkKSB7XG4gICAgICAgICAgc3dpcGVyLnNldEdyYWJDdXJzb3IoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLnByZWxvYWRJbWFnZXMpIHtcbiAgICAgICAgICBzd2lwZXIucHJlbG9hZEltYWdlcygpO1xuICAgICAgICB9IC8vIFNsaWRlIFRvIEluaXRpYWwgU2xpZGVcblxuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmxvb3ApIHtcbiAgICAgICAgICBzd2lwZXIuc2xpZGVUbyhzd2lwZXIucGFyYW1zLmluaXRpYWxTbGlkZSArIHN3aXBlci5sb29wZWRTbGlkZXMsIDAsIHN3aXBlci5wYXJhbXMucnVuQ2FsbGJhY2tzT25Jbml0LCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3dpcGVyLnNsaWRlVG8oc3dpcGVyLnBhcmFtcy5pbml0aWFsU2xpZGUsIDAsIHN3aXBlci5wYXJhbXMucnVuQ2FsbGJhY2tzT25Jbml0LCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgIH0gLy8gQXR0YWNoIGV2ZW50c1xuXG5cbiAgICAgICAgc3dpcGVyLmF0dGFjaEV2ZW50cygpOyAvLyBJbml0IEZsYWdcblxuICAgICAgICBzd2lwZXIuaW5pdGlhbGl6ZWQgPSB0cnVlOyAvLyBFbWl0XG5cbiAgICAgICAgc3dpcGVyLmVtaXQoJ2luaXQnKTtcbiAgICAgICAgc3dpcGVyLmVtaXQoJ2FmdGVySW5pdCcpO1xuICAgICAgICByZXR1cm4gc3dpcGVyO1xuICAgICAgfVxuXG4gICAgICBkZXN0cm95KGRlbGV0ZUluc3RhbmNlLCBjbGVhblN0eWxlcykge1xuICAgICAgICBpZiAoZGVsZXRlSW5zdGFuY2UgPT09IHZvaWQgMCkge1xuICAgICAgICAgIGRlbGV0ZUluc3RhbmNlID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjbGVhblN0eWxlcyA9PT0gdm9pZCAwKSB7XG4gICAgICAgICAgY2xlYW5TdHlsZXMgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcztcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHBhcmFtcyxcbiAgICAgICAgICAkZWwsXG4gICAgICAgICAgJHdyYXBwZXJFbCxcbiAgICAgICAgICBzbGlkZXNcbiAgICAgICAgfSA9IHN3aXBlcjtcblxuICAgICAgICBpZiAodHlwZW9mIHN3aXBlci5wYXJhbXMgPT09ICd1bmRlZmluZWQnIHx8IHN3aXBlci5kZXN0cm95ZWQpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci5lbWl0KCdiZWZvcmVEZXN0cm95Jyk7IC8vIEluaXQgRmxhZ1xuXG4gICAgICAgIHN3aXBlci5pbml0aWFsaXplZCA9IGZhbHNlOyAvLyBEZXRhY2ggZXZlbnRzXG5cbiAgICAgICAgc3dpcGVyLmRldGFjaEV2ZW50cygpOyAvLyBEZXN0cm95IGxvb3BcblxuICAgICAgICBpZiAocGFyYW1zLmxvb3ApIHtcbiAgICAgICAgICBzd2lwZXIubG9vcERlc3Ryb3koKTtcbiAgICAgICAgfSAvLyBDbGVhbnVwIHN0eWxlc1xuXG5cbiAgICAgICAgaWYgKGNsZWFuU3R5bGVzKSB7XG4gICAgICAgICAgc3dpcGVyLnJlbW92ZUNsYXNzZXMoKTtcbiAgICAgICAgICAkZWwucmVtb3ZlQXR0cignc3R5bGUnKTtcbiAgICAgICAgICAkd3JhcHBlckVsLnJlbW92ZUF0dHIoJ3N0eWxlJyk7XG5cbiAgICAgICAgICBpZiAoc2xpZGVzICYmIHNsaWRlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHNsaWRlcy5yZW1vdmVDbGFzcyhbcGFyYW1zLnNsaWRlVmlzaWJsZUNsYXNzLCBwYXJhbXMuc2xpZGVBY3RpdmVDbGFzcywgcGFyYW1zLnNsaWRlTmV4dENsYXNzLCBwYXJhbXMuc2xpZGVQcmV2Q2xhc3NdLmpvaW4oJyAnKSkucmVtb3ZlQXR0cignc3R5bGUnKS5yZW1vdmVBdHRyKCdkYXRhLXN3aXBlci1zbGlkZS1pbmRleCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci5lbWl0KCdkZXN0cm95Jyk7IC8vIERldGFjaCBlbWl0dGVyIGV2ZW50c1xuXG4gICAgICAgIE9iamVjdC5rZXlzKHN3aXBlci5ldmVudHNMaXN0ZW5lcnMpLmZvckVhY2goZXZlbnROYW1lID0+IHtcbiAgICAgICAgICBzd2lwZXIub2ZmKGV2ZW50TmFtZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChkZWxldGVJbnN0YW5jZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICBzd2lwZXIuJGVsWzBdLnN3aXBlciA9IG51bGw7XG4gICAgICAgICAgZGVsZXRlUHJvcHMoc3dpcGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci5kZXN0cm95ZWQgPSB0cnVlO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgc3RhdGljIGV4dGVuZERlZmF1bHRzKG5ld0RlZmF1bHRzKSB7XG4gICAgICAgIGV4dGVuZChleHRlbmRlZERlZmF1bHRzLCBuZXdEZWZhdWx0cyk7XG4gICAgICB9XG5cbiAgICAgIHN0YXRpYyBnZXQgZXh0ZW5kZWREZWZhdWx0cygpIHtcbiAgICAgICAgcmV0dXJuIGV4dGVuZGVkRGVmYXVsdHM7XG4gICAgICB9XG5cbiAgICAgIHN0YXRpYyBnZXQgZGVmYXVsdHMoKSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0cztcbiAgICAgIH1cblxuICAgICAgc3RhdGljIGluc3RhbGxNb2R1bGUobW9kKSB7XG4gICAgICAgIGlmICghU3dpcGVyLnByb3RvdHlwZS5fX21vZHVsZXNfXykgU3dpcGVyLnByb3RvdHlwZS5fX21vZHVsZXNfXyA9IFtdO1xuICAgICAgICBjb25zdCBtb2R1bGVzID0gU3dpcGVyLnByb3RvdHlwZS5fX21vZHVsZXNfXztcblxuICAgICAgICBpZiAodHlwZW9mIG1vZCA9PT0gJ2Z1bmN0aW9uJyAmJiBtb2R1bGVzLmluZGV4T2YobW9kKSA8IDApIHtcbiAgICAgICAgICBtb2R1bGVzLnB1c2gobW9kKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBzdGF0aWMgdXNlKG1vZHVsZSkge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShtb2R1bGUpKSB7XG4gICAgICAgICAgbW9kdWxlLmZvckVhY2gobSA9PiBTd2lwZXIuaW5zdGFsbE1vZHVsZShtKSk7XG4gICAgICAgICAgcmV0dXJuIFN3aXBlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIFN3aXBlci5pbnN0YWxsTW9kdWxlKG1vZHVsZSk7XG4gICAgICAgIHJldHVybiBTd2lwZXI7XG4gICAgICB9XG5cbiAgICB9XG5cbiAgICBPYmplY3Qua2V5cyhwcm90b3R5cGVzKS5mb3JFYWNoKHByb3RvdHlwZUdyb3VwID0+IHtcbiAgICAgIE9iamVjdC5rZXlzKHByb3RvdHlwZXNbcHJvdG90eXBlR3JvdXBdKS5mb3JFYWNoKHByb3RvTWV0aG9kID0+IHtcbiAgICAgICAgU3dpcGVyLnByb3RvdHlwZVtwcm90b01ldGhvZF0gPSBwcm90b3R5cGVzW3Byb3RvdHlwZUdyb3VwXVtwcm90b01ldGhvZF07XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBTd2lwZXIudXNlKFtSZXNpemUsIE9ic2VydmVyXSk7XG5cbiAgICBmdW5jdGlvbiBWaXJ0dWFsKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZXh0ZW5kUGFyYW1zLFxuICAgICAgICBvbixcbiAgICAgICAgZW1pdFxuICAgICAgfSA9IF9yZWY7XG4gICAgICBleHRlbmRQYXJhbXMoe1xuICAgICAgICB2aXJ0dWFsOiB7XG4gICAgICAgICAgZW5hYmxlZDogZmFsc2UsXG4gICAgICAgICAgc2xpZGVzOiBbXSxcbiAgICAgICAgICBjYWNoZTogdHJ1ZSxcbiAgICAgICAgICByZW5kZXJTbGlkZTogbnVsbCxcbiAgICAgICAgICByZW5kZXJFeHRlcm5hbDogbnVsbCxcbiAgICAgICAgICByZW5kZXJFeHRlcm5hbFVwZGF0ZTogdHJ1ZSxcbiAgICAgICAgICBhZGRTbGlkZXNCZWZvcmU6IDAsXG4gICAgICAgICAgYWRkU2xpZGVzQWZ0ZXI6IDBcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBsZXQgY3NzTW9kZVRpbWVvdXQ7XG4gICAgICBzd2lwZXIudmlydHVhbCA9IHtcbiAgICAgICAgY2FjaGU6IHt9LFxuICAgICAgICBmcm9tOiB1bmRlZmluZWQsXG4gICAgICAgIHRvOiB1bmRlZmluZWQsXG4gICAgICAgIHNsaWRlczogW10sXG4gICAgICAgIG9mZnNldDogMCxcbiAgICAgICAgc2xpZGVzR3JpZDogW11cbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIHJlbmRlclNsaWRlKHNsaWRlLCBpbmRleCkge1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zLnZpcnR1YWw7XG5cbiAgICAgICAgaWYgKHBhcmFtcy5jYWNoZSAmJiBzd2lwZXIudmlydHVhbC5jYWNoZVtpbmRleF0pIHtcbiAgICAgICAgICByZXR1cm4gc3dpcGVyLnZpcnR1YWwuY2FjaGVbaW5kZXhdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgJHNsaWRlRWwgPSBwYXJhbXMucmVuZGVyU2xpZGUgPyAkKHBhcmFtcy5yZW5kZXJTbGlkZS5jYWxsKHN3aXBlciwgc2xpZGUsIGluZGV4KSkgOiAkKGA8ZGl2IGNsYXNzPVwiJHtzd2lwZXIucGFyYW1zLnNsaWRlQ2xhc3N9XCIgZGF0YS1zd2lwZXItc2xpZGUtaW5kZXg9XCIke2luZGV4fVwiPiR7c2xpZGV9PC9kaXY+YCk7XG4gICAgICAgIGlmICghJHNsaWRlRWwuYXR0cignZGF0YS1zd2lwZXItc2xpZGUtaW5kZXgnKSkgJHNsaWRlRWwuYXR0cignZGF0YS1zd2lwZXItc2xpZGUtaW5kZXgnLCBpbmRleCk7XG4gICAgICAgIGlmIChwYXJhbXMuY2FjaGUpIHN3aXBlci52aXJ0dWFsLmNhY2hlW2luZGV4XSA9ICRzbGlkZUVsO1xuICAgICAgICByZXR1cm4gJHNsaWRlRWw7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHVwZGF0ZShmb3JjZSkge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgc2xpZGVzUGVyVmlldyxcbiAgICAgICAgICBzbGlkZXNQZXJHcm91cCxcbiAgICAgICAgICBjZW50ZXJlZFNsaWRlc1xuICAgICAgICB9ID0gc3dpcGVyLnBhcmFtcztcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIGFkZFNsaWRlc0JlZm9yZSxcbiAgICAgICAgICBhZGRTbGlkZXNBZnRlclxuICAgICAgICB9ID0gc3dpcGVyLnBhcmFtcy52aXJ0dWFsO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgZnJvbTogcHJldmlvdXNGcm9tLFxuICAgICAgICAgIHRvOiBwcmV2aW91c1RvLFxuICAgICAgICAgIHNsaWRlcyxcbiAgICAgICAgICBzbGlkZXNHcmlkOiBwcmV2aW91c1NsaWRlc0dyaWQsXG4gICAgICAgICAgb2Zmc2V0OiBwcmV2aW91c09mZnNldFxuICAgICAgICB9ID0gc3dpcGVyLnZpcnR1YWw7XG5cbiAgICAgICAgaWYgKCFzd2lwZXIucGFyYW1zLmNzc01vZGUpIHtcbiAgICAgICAgICBzd2lwZXIudXBkYXRlQWN0aXZlSW5kZXgoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFjdGl2ZUluZGV4ID0gc3dpcGVyLmFjdGl2ZUluZGV4IHx8IDA7XG4gICAgICAgIGxldCBvZmZzZXRQcm9wO1xuICAgICAgICBpZiAoc3dpcGVyLnJ0bFRyYW5zbGF0ZSkgb2Zmc2V0UHJvcCA9ICdyaWdodCc7ZWxzZSBvZmZzZXRQcm9wID0gc3dpcGVyLmlzSG9yaXpvbnRhbCgpID8gJ2xlZnQnIDogJ3RvcCc7XG4gICAgICAgIGxldCBzbGlkZXNBZnRlcjtcbiAgICAgICAgbGV0IHNsaWRlc0JlZm9yZTtcblxuICAgICAgICBpZiAoY2VudGVyZWRTbGlkZXMpIHtcbiAgICAgICAgICBzbGlkZXNBZnRlciA9IE1hdGguZmxvb3Ioc2xpZGVzUGVyVmlldyAvIDIpICsgc2xpZGVzUGVyR3JvdXAgKyBhZGRTbGlkZXNBZnRlcjtcbiAgICAgICAgICBzbGlkZXNCZWZvcmUgPSBNYXRoLmZsb29yKHNsaWRlc1BlclZpZXcgLyAyKSArIHNsaWRlc1Blckdyb3VwICsgYWRkU2xpZGVzQmVmb3JlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNsaWRlc0FmdGVyID0gc2xpZGVzUGVyVmlldyArIChzbGlkZXNQZXJHcm91cCAtIDEpICsgYWRkU2xpZGVzQWZ0ZXI7XG4gICAgICAgICAgc2xpZGVzQmVmb3JlID0gc2xpZGVzUGVyR3JvdXAgKyBhZGRTbGlkZXNCZWZvcmU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmcm9tID0gTWF0aC5tYXgoKGFjdGl2ZUluZGV4IHx8IDApIC0gc2xpZGVzQmVmb3JlLCAwKTtcbiAgICAgICAgY29uc3QgdG8gPSBNYXRoLm1pbigoYWN0aXZlSW5kZXggfHwgMCkgKyBzbGlkZXNBZnRlciwgc2xpZGVzLmxlbmd0aCAtIDEpO1xuICAgICAgICBjb25zdCBvZmZzZXQgPSAoc3dpcGVyLnNsaWRlc0dyaWRbZnJvbV0gfHwgMCkgLSAoc3dpcGVyLnNsaWRlc0dyaWRbMF0gfHwgMCk7XG4gICAgICAgIE9iamVjdC5hc3NpZ24oc3dpcGVyLnZpcnR1YWwsIHtcbiAgICAgICAgICBmcm9tLFxuICAgICAgICAgIHRvLFxuICAgICAgICAgIG9mZnNldCxcbiAgICAgICAgICBzbGlkZXNHcmlkOiBzd2lwZXIuc2xpZGVzR3JpZFxuICAgICAgICB9KTtcblxuICAgICAgICBmdW5jdGlvbiBvblJlbmRlcmVkKCkge1xuICAgICAgICAgIHN3aXBlci51cGRhdGVTbGlkZXMoKTtcbiAgICAgICAgICBzd2lwZXIudXBkYXRlUHJvZ3Jlc3MoKTtcbiAgICAgICAgICBzd2lwZXIudXBkYXRlU2xpZGVzQ2xhc3NlcygpO1xuXG4gICAgICAgICAgaWYgKHN3aXBlci5sYXp5ICYmIHN3aXBlci5wYXJhbXMubGF6eS5lbmFibGVkKSB7XG4gICAgICAgICAgICBzd2lwZXIubGF6eS5sb2FkKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZW1pdCgndmlydHVhbFVwZGF0ZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHByZXZpb3VzRnJvbSA9PT0gZnJvbSAmJiBwcmV2aW91c1RvID09PSB0byAmJiAhZm9yY2UpIHtcbiAgICAgICAgICBpZiAoc3dpcGVyLnNsaWRlc0dyaWQgIT09IHByZXZpb3VzU2xpZGVzR3JpZCAmJiBvZmZzZXQgIT09IHByZXZpb3VzT2Zmc2V0KSB7XG4gICAgICAgICAgICBzd2lwZXIuc2xpZGVzLmNzcyhvZmZzZXRQcm9wLCBgJHtvZmZzZXR9cHhgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzd2lwZXIudXBkYXRlUHJvZ3Jlc3MoKTtcbiAgICAgICAgICBlbWl0KCd2aXJ0dWFsVXBkYXRlJyk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMudmlydHVhbC5yZW5kZXJFeHRlcm5hbCkge1xuICAgICAgICAgIHN3aXBlci5wYXJhbXMudmlydHVhbC5yZW5kZXJFeHRlcm5hbC5jYWxsKHN3aXBlciwge1xuICAgICAgICAgICAgb2Zmc2V0LFxuICAgICAgICAgICAgZnJvbSxcbiAgICAgICAgICAgIHRvLFxuICAgICAgICAgICAgc2xpZGVzOiBmdW5jdGlvbiBnZXRTbGlkZXMoKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHNsaWRlc1RvUmVuZGVyID0gW107XG5cbiAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IGZyb207IGkgPD0gdG87IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgIHNsaWRlc1RvUmVuZGVyLnB1c2goc2xpZGVzW2ldKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHJldHVybiBzbGlkZXNUb1JlbmRlcjtcbiAgICAgICAgICAgIH0oKVxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMudmlydHVhbC5yZW5kZXJFeHRlcm5hbFVwZGF0ZSkge1xuICAgICAgICAgICAgb25SZW5kZXJlZCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbWl0KCd2aXJ0dWFsVXBkYXRlJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcHJlcGVuZEluZGV4ZXMgPSBbXTtcbiAgICAgICAgY29uc3QgYXBwZW5kSW5kZXhlcyA9IFtdO1xuXG4gICAgICAgIGlmIChmb3JjZSkge1xuICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsLmZpbmQoYC4ke3N3aXBlci5wYXJhbXMuc2xpZGVDbGFzc31gKS5yZW1vdmUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmb3IgKGxldCBpID0gcHJldmlvdXNGcm9tOyBpIDw9IHByZXZpb3VzVG87IGkgKz0gMSkge1xuICAgICAgICAgICAgaWYgKGkgPCBmcm9tIHx8IGkgPiB0bykge1xuICAgICAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbC5maW5kKGAuJHtzd2lwZXIucGFyYW1zLnNsaWRlQ2xhc3N9W2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4PVwiJHtpfVwiXWApLnJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2xpZGVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgaWYgKGkgPj0gZnJvbSAmJiBpIDw9IHRvKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHByZXZpb3VzVG8gPT09ICd1bmRlZmluZWQnIHx8IGZvcmNlKSB7XG4gICAgICAgICAgICAgIGFwcGVuZEluZGV4ZXMucHVzaChpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChpID4gcHJldmlvdXNUbykgYXBwZW5kSW5kZXhlcy5wdXNoKGkpO1xuICAgICAgICAgICAgICBpZiAoaSA8IHByZXZpb3VzRnJvbSkgcHJlcGVuZEluZGV4ZXMucHVzaChpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBhcHBlbmRJbmRleGVzLmZvckVhY2goaW5kZXggPT4ge1xuICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsLmFwcGVuZChyZW5kZXJTbGlkZShzbGlkZXNbaW5kZXhdLCBpbmRleCkpO1xuICAgICAgICB9KTtcbiAgICAgICAgcHJlcGVuZEluZGV4ZXMuc29ydCgoYSwgYikgPT4gYiAtIGEpLmZvckVhY2goaW5kZXggPT4ge1xuICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsLnByZXBlbmQocmVuZGVyU2xpZGUoc2xpZGVzW2luZGV4XSwgaW5kZXgpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHN3aXBlci4kd3JhcHBlckVsLmNoaWxkcmVuKCcuc3dpcGVyLXNsaWRlJykuY3NzKG9mZnNldFByb3AsIGAke29mZnNldH1weGApO1xuICAgICAgICBvblJlbmRlcmVkKCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGFwcGVuZFNsaWRlKHNsaWRlcykge1xuICAgICAgICBpZiAodHlwZW9mIHNsaWRlcyA9PT0gJ29iamVjdCcgJiYgJ2xlbmd0aCcgaW4gc2xpZGVzKSB7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbGlkZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGlmIChzbGlkZXNbaV0pIHN3aXBlci52aXJ0dWFsLnNsaWRlcy5wdXNoKHNsaWRlc1tpXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN3aXBlci52aXJ0dWFsLnNsaWRlcy5wdXNoKHNsaWRlcyk7XG4gICAgICAgIH1cblxuICAgICAgICB1cGRhdGUodHJ1ZSk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHByZXBlbmRTbGlkZShzbGlkZXMpIHtcbiAgICAgICAgY29uc3QgYWN0aXZlSW5kZXggPSBzd2lwZXIuYWN0aXZlSW5kZXg7XG4gICAgICAgIGxldCBuZXdBY3RpdmVJbmRleCA9IGFjdGl2ZUluZGV4ICsgMTtcbiAgICAgICAgbGV0IG51bWJlck9mTmV3U2xpZGVzID0gMTtcblxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShzbGlkZXMpKSB7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbGlkZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGlmIChzbGlkZXNbaV0pIHN3aXBlci52aXJ0dWFsLnNsaWRlcy51bnNoaWZ0KHNsaWRlc1tpXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbmV3QWN0aXZlSW5kZXggPSBhY3RpdmVJbmRleCArIHNsaWRlcy5sZW5ndGg7XG4gICAgICAgICAgbnVtYmVyT2ZOZXdTbGlkZXMgPSBzbGlkZXMubGVuZ3RoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN3aXBlci52aXJ0dWFsLnNsaWRlcy51bnNoaWZ0KHNsaWRlcyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy52aXJ0dWFsLmNhY2hlKSB7XG4gICAgICAgICAgY29uc3QgY2FjaGUgPSBzd2lwZXIudmlydHVhbC5jYWNoZTtcbiAgICAgICAgICBjb25zdCBuZXdDYWNoZSA9IHt9O1xuICAgICAgICAgIE9iamVjdC5rZXlzKGNhY2hlKS5mb3JFYWNoKGNhY2hlZEluZGV4ID0+IHtcbiAgICAgICAgICAgIGNvbnN0ICRjYWNoZWRFbCA9IGNhY2hlW2NhY2hlZEluZGV4XTtcbiAgICAgICAgICAgIGNvbnN0IGNhY2hlZEVsSW5kZXggPSAkY2FjaGVkRWwuYXR0cignZGF0YS1zd2lwZXItc2xpZGUtaW5kZXgnKTtcblxuICAgICAgICAgICAgaWYgKGNhY2hlZEVsSW5kZXgpIHtcbiAgICAgICAgICAgICAgJGNhY2hlZEVsLmF0dHIoJ2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4JywgcGFyc2VJbnQoY2FjaGVkRWxJbmRleCwgMTApICsgbnVtYmVyT2ZOZXdTbGlkZXMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXdDYWNoZVtwYXJzZUludChjYWNoZWRJbmRleCwgMTApICsgbnVtYmVyT2ZOZXdTbGlkZXNdID0gJGNhY2hlZEVsO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHN3aXBlci52aXJ0dWFsLmNhY2hlID0gbmV3Q2FjaGU7XG4gICAgICAgIH1cblxuICAgICAgICB1cGRhdGUodHJ1ZSk7XG4gICAgICAgIHN3aXBlci5zbGlkZVRvKG5ld0FjdGl2ZUluZGV4LCAwKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gcmVtb3ZlU2xpZGUoc2xpZGVzSW5kZXhlcykge1xuICAgICAgICBpZiAodHlwZW9mIHNsaWRlc0luZGV4ZXMgPT09ICd1bmRlZmluZWQnIHx8IHNsaWRlc0luZGV4ZXMgPT09IG51bGwpIHJldHVybjtcbiAgICAgICAgbGV0IGFjdGl2ZUluZGV4ID0gc3dpcGVyLmFjdGl2ZUluZGV4O1xuXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHNsaWRlc0luZGV4ZXMpKSB7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IHNsaWRlc0luZGV4ZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpIC09IDEpIHtcbiAgICAgICAgICAgIHN3aXBlci52aXJ0dWFsLnNsaWRlcy5zcGxpY2Uoc2xpZGVzSW5kZXhlc1tpXSwgMSk7XG5cbiAgICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLnZpcnR1YWwuY2FjaGUpIHtcbiAgICAgICAgICAgICAgZGVsZXRlIHN3aXBlci52aXJ0dWFsLmNhY2hlW3NsaWRlc0luZGV4ZXNbaV1dO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoc2xpZGVzSW5kZXhlc1tpXSA8IGFjdGl2ZUluZGV4KSBhY3RpdmVJbmRleCAtPSAxO1xuICAgICAgICAgICAgYWN0aXZlSW5kZXggPSBNYXRoLm1heChhY3RpdmVJbmRleCwgMCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN3aXBlci52aXJ0dWFsLnNsaWRlcy5zcGxpY2Uoc2xpZGVzSW5kZXhlcywgMSk7XG5cbiAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy52aXJ0dWFsLmNhY2hlKSB7XG4gICAgICAgICAgICBkZWxldGUgc3dpcGVyLnZpcnR1YWwuY2FjaGVbc2xpZGVzSW5kZXhlc107XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHNsaWRlc0luZGV4ZXMgPCBhY3RpdmVJbmRleCkgYWN0aXZlSW5kZXggLT0gMTtcbiAgICAgICAgICBhY3RpdmVJbmRleCA9IE1hdGgubWF4KGFjdGl2ZUluZGV4LCAwKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHVwZGF0ZSh0cnVlKTtcbiAgICAgICAgc3dpcGVyLnNsaWRlVG8oYWN0aXZlSW5kZXgsIDApO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiByZW1vdmVBbGxTbGlkZXMoKSB7XG4gICAgICAgIHN3aXBlci52aXJ0dWFsLnNsaWRlcyA9IFtdO1xuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLnZpcnR1YWwuY2FjaGUpIHtcbiAgICAgICAgICBzd2lwZXIudmlydHVhbC5jYWNoZSA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgdXBkYXRlKHRydWUpO1xuICAgICAgICBzd2lwZXIuc2xpZGVUbygwLCAwKTtcbiAgICAgIH1cblxuICAgICAgb24oJ2JlZm9yZUluaXQnLCAoKSA9PiB7XG4gICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy52aXJ0dWFsLmVuYWJsZWQpIHJldHVybjtcbiAgICAgICAgc3dpcGVyLnZpcnR1YWwuc2xpZGVzID0gc3dpcGVyLnBhcmFtcy52aXJ0dWFsLnNsaWRlcztcbiAgICAgICAgc3dpcGVyLmNsYXNzTmFtZXMucHVzaChgJHtzd2lwZXIucGFyYW1zLmNvbnRhaW5lck1vZGlmaWVyQ2xhc3N9dmlydHVhbGApO1xuICAgICAgICBzd2lwZXIucGFyYW1zLndhdGNoU2xpZGVzUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICBzd2lwZXIub3JpZ2luYWxQYXJhbXMud2F0Y2hTbGlkZXNQcm9ncmVzcyA9IHRydWU7XG5cbiAgICAgICAgaWYgKCFzd2lwZXIucGFyYW1zLmluaXRpYWxTbGlkZSkge1xuICAgICAgICAgIHVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIG9uKCdzZXRUcmFuc2xhdGUnLCAoKSA9PiB7XG4gICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy52aXJ0dWFsLmVuYWJsZWQpIHJldHVybjtcblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5jc3NNb2RlICYmICFzd2lwZXIuX2ltbWVkaWF0ZVZpcnR1YWwpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQoY3NzTW9kZVRpbWVvdXQpO1xuICAgICAgICAgIGNzc01vZGVUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB1cGRhdGUoKTtcbiAgICAgICAgICB9LCAxMDApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIG9uKCdpbml0IHVwZGF0ZSByZXNpemUnLCAoKSA9PiB7XG4gICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy52aXJ0dWFsLmVuYWJsZWQpIHJldHVybjtcblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5jc3NNb2RlKSB7XG4gICAgICAgICAgc2V0Q1NTUHJvcGVydHkoc3dpcGVyLndyYXBwZXJFbCwgJy0tc3dpcGVyLXZpcnR1YWwtc2l6ZScsIGAke3N3aXBlci52aXJ0dWFsU2l6ZX1weGApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIE9iamVjdC5hc3NpZ24oc3dpcGVyLnZpcnR1YWwsIHtcbiAgICAgICAgYXBwZW5kU2xpZGUsXG4gICAgICAgIHByZXBlbmRTbGlkZSxcbiAgICAgICAgcmVtb3ZlU2xpZGUsXG4gICAgICAgIHJlbW92ZUFsbFNsaWRlcyxcbiAgICAgICAgdXBkYXRlXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiBlc2xpbnQtZGlzYWJsZSBjb25zaXN0ZW50LXJldHVybiAqL1xuICAgIGZ1bmN0aW9uIEtleWJvYXJkKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZXh0ZW5kUGFyYW1zLFxuICAgICAgICBvbixcbiAgICAgICAgZW1pdFxuICAgICAgfSA9IF9yZWY7XG4gICAgICBjb25zdCBkb2N1bWVudCA9IGdldERvY3VtZW50KCk7XG4gICAgICBjb25zdCB3aW5kb3cgPSBnZXRXaW5kb3coKTtcbiAgICAgIHN3aXBlci5rZXlib2FyZCA9IHtcbiAgICAgICAgZW5hYmxlZDogZmFsc2VcbiAgICAgIH07XG4gICAgICBleHRlbmRQYXJhbXMoe1xuICAgICAgICBrZXlib2FyZDoge1xuICAgICAgICAgIGVuYWJsZWQ6IGZhbHNlLFxuICAgICAgICAgIG9ubHlJblZpZXdwb3J0OiB0cnVlLFxuICAgICAgICAgIHBhZ2VVcERvd246IHRydWVcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGZ1bmN0aW9uIGhhbmRsZShldmVudCkge1xuICAgICAgICBpZiAoIXN3aXBlci5lbmFibGVkKSByZXR1cm47XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBydGxUcmFuc2xhdGU6IHJ0bFxuICAgICAgICB9ID0gc3dpcGVyO1xuICAgICAgICBsZXQgZSA9IGV2ZW50O1xuICAgICAgICBpZiAoZS5vcmlnaW5hbEV2ZW50KSBlID0gZS5vcmlnaW5hbEV2ZW50OyAvLyBqcXVlcnkgZml4XG5cbiAgICAgICAgY29uc3Qga2MgPSBlLmtleUNvZGUgfHwgZS5jaGFyQ29kZTtcbiAgICAgICAgY29uc3QgcGFnZVVwRG93biA9IHN3aXBlci5wYXJhbXMua2V5Ym9hcmQucGFnZVVwRG93bjtcbiAgICAgICAgY29uc3QgaXNQYWdlVXAgPSBwYWdlVXBEb3duICYmIGtjID09PSAzMztcbiAgICAgICAgY29uc3QgaXNQYWdlRG93biA9IHBhZ2VVcERvd24gJiYga2MgPT09IDM0O1xuICAgICAgICBjb25zdCBpc0Fycm93TGVmdCA9IGtjID09PSAzNztcbiAgICAgICAgY29uc3QgaXNBcnJvd1JpZ2h0ID0ga2MgPT09IDM5O1xuICAgICAgICBjb25zdCBpc0Fycm93VXAgPSBrYyA9PT0gMzg7XG4gICAgICAgIGNvbnN0IGlzQXJyb3dEb3duID0ga2MgPT09IDQwOyAvLyBEaXJlY3Rpb25zIGxvY2tzXG5cbiAgICAgICAgaWYgKCFzd2lwZXIuYWxsb3dTbGlkZU5leHQgJiYgKHN3aXBlci5pc0hvcml6b250YWwoKSAmJiBpc0Fycm93UmlnaHQgfHwgc3dpcGVyLmlzVmVydGljYWwoKSAmJiBpc0Fycm93RG93biB8fCBpc1BhZ2VEb3duKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghc3dpcGVyLmFsbG93U2xpZGVQcmV2ICYmIChzd2lwZXIuaXNIb3Jpem9udGFsKCkgJiYgaXNBcnJvd0xlZnQgfHwgc3dpcGVyLmlzVmVydGljYWwoKSAmJiBpc0Fycm93VXAgfHwgaXNQYWdlVXApKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGUuc2hpZnRLZXkgfHwgZS5hbHRLZXkgfHwgZS5jdHJsS2V5IHx8IGUubWV0YUtleSkge1xuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAmJiBkb2N1bWVudC5hY3RpdmVFbGVtZW50Lm5vZGVOYW1lICYmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdpbnB1dCcgfHwgZG9jdW1lbnQuYWN0aXZlRWxlbWVudC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSAndGV4dGFyZWEnKSkge1xuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5rZXlib2FyZC5vbmx5SW5WaWV3cG9ydCAmJiAoaXNQYWdlVXAgfHwgaXNQYWdlRG93biB8fCBpc0Fycm93TGVmdCB8fCBpc0Fycm93UmlnaHQgfHwgaXNBcnJvd1VwIHx8IGlzQXJyb3dEb3duKSkge1xuICAgICAgICAgIGxldCBpblZpZXcgPSBmYWxzZTsgLy8gQ2hlY2sgdGhhdCBzd2lwZXIgc2hvdWxkIGJlIGluc2lkZSBvZiB2aXNpYmxlIGFyZWEgb2Ygd2luZG93XG5cbiAgICAgICAgICBpZiAoc3dpcGVyLiRlbC5wYXJlbnRzKGAuJHtzd2lwZXIucGFyYW1zLnNsaWRlQ2xhc3N9YCkubGVuZ3RoID4gMCAmJiBzd2lwZXIuJGVsLnBhcmVudHMoYC4ke3N3aXBlci5wYXJhbXMuc2xpZGVBY3RpdmVDbGFzc31gKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgJGVsID0gc3dpcGVyLiRlbDtcbiAgICAgICAgICBjb25zdCBzd2lwZXJXaWR0aCA9ICRlbFswXS5jbGllbnRXaWR0aDtcbiAgICAgICAgICBjb25zdCBzd2lwZXJIZWlnaHQgPSAkZWxbMF0uY2xpZW50SGVpZ2h0O1xuICAgICAgICAgIGNvbnN0IHdpbmRvd1dpZHRoID0gd2luZG93LmlubmVyV2lkdGg7XG4gICAgICAgICAgY29uc3Qgd2luZG93SGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0O1xuICAgICAgICAgIGNvbnN0IHN3aXBlck9mZnNldCA9IHN3aXBlci4kZWwub2Zmc2V0KCk7XG4gICAgICAgICAgaWYgKHJ0bCkgc3dpcGVyT2Zmc2V0LmxlZnQgLT0gc3dpcGVyLiRlbFswXS5zY3JvbGxMZWZ0O1xuICAgICAgICAgIGNvbnN0IHN3aXBlckNvb3JkID0gW1tzd2lwZXJPZmZzZXQubGVmdCwgc3dpcGVyT2Zmc2V0LnRvcF0sIFtzd2lwZXJPZmZzZXQubGVmdCArIHN3aXBlcldpZHRoLCBzd2lwZXJPZmZzZXQudG9wXSwgW3N3aXBlck9mZnNldC5sZWZ0LCBzd2lwZXJPZmZzZXQudG9wICsgc3dpcGVySGVpZ2h0XSwgW3N3aXBlck9mZnNldC5sZWZ0ICsgc3dpcGVyV2lkdGgsIHN3aXBlck9mZnNldC50b3AgKyBzd2lwZXJIZWlnaHRdXTtcblxuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3dpcGVyQ29vcmQubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGNvbnN0IHBvaW50ID0gc3dpcGVyQ29vcmRbaV07XG5cbiAgICAgICAgICAgIGlmIChwb2ludFswXSA+PSAwICYmIHBvaW50WzBdIDw9IHdpbmRvd1dpZHRoICYmIHBvaW50WzFdID49IDAgJiYgcG9pbnRbMV0gPD0gd2luZG93SGVpZ2h0KSB7XG4gICAgICAgICAgICAgIGlmIChwb2ludFswXSA9PT0gMCAmJiBwb2ludFsxXSA9PT0gMCkgY29udGludWU7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblxuICAgICAgICAgICAgICBpblZpZXcgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghaW5WaWV3KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN3aXBlci5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgIGlmIChpc1BhZ2VVcCB8fCBpc1BhZ2VEb3duIHx8IGlzQXJyb3dMZWZ0IHx8IGlzQXJyb3dSaWdodCkge1xuICAgICAgICAgICAgaWYgKGUucHJldmVudERlZmF1bHQpIGUucHJldmVudERlZmF1bHQoKTtlbHNlIGUucmV0dXJuVmFsdWUgPSBmYWxzZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoKGlzUGFnZURvd24gfHwgaXNBcnJvd1JpZ2h0KSAmJiAhcnRsIHx8IChpc1BhZ2VVcCB8fCBpc0Fycm93TGVmdCkgJiYgcnRsKSBzd2lwZXIuc2xpZGVOZXh0KCk7XG4gICAgICAgICAgaWYgKChpc1BhZ2VVcCB8fCBpc0Fycm93TGVmdCkgJiYgIXJ0bCB8fCAoaXNQYWdlRG93biB8fCBpc0Fycm93UmlnaHQpICYmIHJ0bCkgc3dpcGVyLnNsaWRlUHJldigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChpc1BhZ2VVcCB8fCBpc1BhZ2VEb3duIHx8IGlzQXJyb3dVcCB8fCBpc0Fycm93RG93bikge1xuICAgICAgICAgICAgaWYgKGUucHJldmVudERlZmF1bHQpIGUucHJldmVudERlZmF1bHQoKTtlbHNlIGUucmV0dXJuVmFsdWUgPSBmYWxzZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaXNQYWdlRG93biB8fCBpc0Fycm93RG93bikgc3dpcGVyLnNsaWRlTmV4dCgpO1xuICAgICAgICAgIGlmIChpc1BhZ2VVcCB8fCBpc0Fycm93VXApIHN3aXBlci5zbGlkZVByZXYoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVtaXQoJ2tleVByZXNzJywga2MpO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBlbmFibGUoKSB7XG4gICAgICAgIGlmIChzd2lwZXIua2V5Ym9hcmQuZW5hYmxlZCkgcmV0dXJuO1xuICAgICAgICAkKGRvY3VtZW50KS5vbigna2V5ZG93bicsIGhhbmRsZSk7XG4gICAgICAgIHN3aXBlci5rZXlib2FyZC5lbmFibGVkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZGlzYWJsZSgpIHtcbiAgICAgICAgaWYgKCFzd2lwZXIua2V5Ym9hcmQuZW5hYmxlZCkgcmV0dXJuO1xuICAgICAgICAkKGRvY3VtZW50KS5vZmYoJ2tleWRvd24nLCBoYW5kbGUpO1xuICAgICAgICBzd2lwZXIua2V5Ym9hcmQuZW5hYmxlZCA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBvbignaW5pdCcsICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMua2V5Ym9hcmQuZW5hYmxlZCkge1xuICAgICAgICAgIGVuYWJsZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIG9uKCdkZXN0cm95JywgKCkgPT4ge1xuICAgICAgICBpZiAoc3dpcGVyLmtleWJvYXJkLmVuYWJsZWQpIHtcbiAgICAgICAgICBkaXNhYmxlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgT2JqZWN0LmFzc2lnbihzd2lwZXIua2V5Ym9hcmQsIHtcbiAgICAgICAgZW5hYmxlLFxuICAgICAgICBkaXNhYmxlXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiBlc2xpbnQtZGlzYWJsZSBjb25zaXN0ZW50LXJldHVybiAqL1xuICAgIGZ1bmN0aW9uIE1vdXNld2hlZWwoX3JlZikge1xuICAgICAgbGV0IHtcbiAgICAgICAgc3dpcGVyLFxuICAgICAgICBleHRlbmRQYXJhbXMsXG4gICAgICAgIG9uLFxuICAgICAgICBlbWl0XG4gICAgICB9ID0gX3JlZjtcbiAgICAgIGNvbnN0IHdpbmRvdyA9IGdldFdpbmRvdygpO1xuICAgICAgZXh0ZW5kUGFyYW1zKHtcbiAgICAgICAgbW91c2V3aGVlbDoge1xuICAgICAgICAgIGVuYWJsZWQ6IGZhbHNlLFxuICAgICAgICAgIHJlbGVhc2VPbkVkZ2VzOiBmYWxzZSxcbiAgICAgICAgICBpbnZlcnQ6IGZhbHNlLFxuICAgICAgICAgIGZvcmNlVG9BeGlzOiBmYWxzZSxcbiAgICAgICAgICBzZW5zaXRpdml0eTogMSxcbiAgICAgICAgICBldmVudHNUYXJnZXQ6ICdjb250YWluZXInLFxuICAgICAgICAgIHRocmVzaG9sZERlbHRhOiBudWxsLFxuICAgICAgICAgIHRocmVzaG9sZFRpbWU6IG51bGxcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzd2lwZXIubW91c2V3aGVlbCA9IHtcbiAgICAgICAgZW5hYmxlZDogZmFsc2VcbiAgICAgIH07XG4gICAgICBsZXQgdGltZW91dDtcbiAgICAgIGxldCBsYXN0U2Nyb2xsVGltZSA9IG5vdygpO1xuICAgICAgbGV0IGxhc3RFdmVudEJlZm9yZVNuYXA7XG4gICAgICBjb25zdCByZWNlbnRXaGVlbEV2ZW50cyA9IFtdO1xuXG4gICAgICBmdW5jdGlvbiBub3JtYWxpemUoZSkge1xuICAgICAgICAvLyBSZWFzb25hYmxlIGRlZmF1bHRzXG4gICAgICAgIGNvbnN0IFBJWEVMX1NURVAgPSAxMDtcbiAgICAgICAgY29uc3QgTElORV9IRUlHSFQgPSA0MDtcbiAgICAgICAgY29uc3QgUEFHRV9IRUlHSFQgPSA4MDA7XG4gICAgICAgIGxldCBzWCA9IDA7XG4gICAgICAgIGxldCBzWSA9IDA7IC8vIHNwaW5YLCBzcGluWVxuXG4gICAgICAgIGxldCBwWCA9IDA7XG4gICAgICAgIGxldCBwWSA9IDA7IC8vIHBpeGVsWCwgcGl4ZWxZXG4gICAgICAgIC8vIExlZ2FjeVxuXG4gICAgICAgIGlmICgnZGV0YWlsJyBpbiBlKSB7XG4gICAgICAgICAgc1kgPSBlLmRldGFpbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgnd2hlZWxEZWx0YScgaW4gZSkge1xuICAgICAgICAgIHNZID0gLWUud2hlZWxEZWx0YSAvIDEyMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgnd2hlZWxEZWx0YVknIGluIGUpIHtcbiAgICAgICAgICBzWSA9IC1lLndoZWVsRGVsdGFZIC8gMTIwO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCd3aGVlbERlbHRhWCcgaW4gZSkge1xuICAgICAgICAgIHNYID0gLWUud2hlZWxEZWx0YVggLyAxMjA7XG4gICAgICAgIH0gLy8gc2lkZSBzY3JvbGxpbmcgb24gRkYgd2l0aCBET01Nb3VzZVNjcm9sbFxuXG5cbiAgICAgICAgaWYgKCdheGlzJyBpbiBlICYmIGUuYXhpcyA9PT0gZS5IT1JJWk9OVEFMX0FYSVMpIHtcbiAgICAgICAgICBzWCA9IHNZO1xuICAgICAgICAgIHNZID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHBYID0gc1ggKiBQSVhFTF9TVEVQO1xuICAgICAgICBwWSA9IHNZICogUElYRUxfU1RFUDtcblxuICAgICAgICBpZiAoJ2RlbHRhWScgaW4gZSkge1xuICAgICAgICAgIHBZID0gZS5kZWx0YVk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ2RlbHRhWCcgaW4gZSkge1xuICAgICAgICAgIHBYID0gZS5kZWx0YVg7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZS5zaGlmdEtleSAmJiAhcFgpIHtcbiAgICAgICAgICAvLyBpZiB1c2VyIHNjcm9sbHMgd2l0aCBzaGlmdCBoZSB3YW50cyBob3Jpem9udGFsIHNjcm9sbFxuICAgICAgICAgIHBYID0gcFk7XG4gICAgICAgICAgcFkgPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKChwWCB8fCBwWSkgJiYgZS5kZWx0YU1vZGUpIHtcbiAgICAgICAgICBpZiAoZS5kZWx0YU1vZGUgPT09IDEpIHtcbiAgICAgICAgICAgIC8vIGRlbHRhIGluIExJTkUgdW5pdHNcbiAgICAgICAgICAgIHBYICo9IExJTkVfSEVJR0hUO1xuICAgICAgICAgICAgcFkgKj0gTElORV9IRUlHSFQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGRlbHRhIGluIFBBR0UgdW5pdHNcbiAgICAgICAgICAgIHBYICo9IFBBR0VfSEVJR0hUO1xuICAgICAgICAgICAgcFkgKj0gUEFHRV9IRUlHSFQ7XG4gICAgICAgICAgfVxuICAgICAgICB9IC8vIEZhbGwtYmFjayBpZiBzcGluIGNhbm5vdCBiZSBkZXRlcm1pbmVkXG5cblxuICAgICAgICBpZiAocFggJiYgIXNYKSB7XG4gICAgICAgICAgc1ggPSBwWCA8IDEgPyAtMSA6IDE7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocFkgJiYgIXNZKSB7XG4gICAgICAgICAgc1kgPSBwWSA8IDEgPyAtMSA6IDE7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHNwaW5YOiBzWCxcbiAgICAgICAgICBzcGluWTogc1ksXG4gICAgICAgICAgcGl4ZWxYOiBwWCxcbiAgICAgICAgICBwaXhlbFk6IHBZXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGhhbmRsZU1vdXNlRW50ZXIoKSB7XG4gICAgICAgIGlmICghc3dpcGVyLmVuYWJsZWQpIHJldHVybjtcbiAgICAgICAgc3dpcGVyLm1vdXNlRW50ZXJlZCA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGhhbmRsZU1vdXNlTGVhdmUoKSB7XG4gICAgICAgIGlmICghc3dpcGVyLmVuYWJsZWQpIHJldHVybjtcbiAgICAgICAgc3dpcGVyLm1vdXNlRW50ZXJlZCA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBhbmltYXRlU2xpZGVyKG5ld0V2ZW50KSB7XG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLm1vdXNld2hlZWwudGhyZXNob2xkRGVsdGEgJiYgbmV3RXZlbnQuZGVsdGEgPCBzd2lwZXIucGFyYW1zLm1vdXNld2hlZWwudGhyZXNob2xkRGVsdGEpIHtcbiAgICAgICAgICAvLyBQcmV2ZW50IGlmIGRlbHRhIG9mIHdoZWVsIHNjcm9sbCBkZWx0YSBpcyBiZWxvdyBjb25maWd1cmVkIHRocmVzaG9sZFxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLm1vdXNld2hlZWwudGhyZXNob2xkVGltZSAmJiBub3coKSAtIGxhc3RTY3JvbGxUaW1lIDwgc3dpcGVyLnBhcmFtcy5tb3VzZXdoZWVsLnRocmVzaG9sZFRpbWUpIHtcbiAgICAgICAgICAvLyBQcmV2ZW50IGlmIHRpbWUgYmV0d2VlbiBzY3JvbGxzIGlzIGJlbG93IGNvbmZpZ3VyZWQgdGhyZXNob2xkXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IC8vIElmIHRoZSBtb3ZlbWVudCBpcyBOT1QgYmlnIGVub3VnaCBhbmRcbiAgICAgICAgLy8gaWYgdGhlIGxhc3QgdGltZSB0aGUgdXNlciBzY3JvbGxlZCB3YXMgdG9vIGNsb3NlIHRvIHRoZSBjdXJyZW50IG9uZSAoYXZvaWQgY29udGludW91c2x5IHRyaWdnZXJpbmcgdGhlIHNsaWRlcik6XG4gICAgICAgIC8vICAgRG9uJ3QgZ28gYW55IGZ1cnRoZXIgKGF2b2lkIGluc2lnbmlmaWNhbnQgc2Nyb2xsIG1vdmVtZW50KS5cblxuXG4gICAgICAgIGlmIChuZXdFdmVudC5kZWx0YSA+PSA2ICYmIG5vdygpIC0gbGFzdFNjcm9sbFRpbWUgPCA2MCkge1xuICAgICAgICAgIC8vIFJldHVybiBmYWxzZSBhcyBhIGRlZmF1bHRcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSAvLyBJZiB1c2VyIGlzIHNjcm9sbGluZyB0b3dhcmRzIHRoZSBlbmQ6XG4gICAgICAgIC8vICAgSWYgdGhlIHNsaWRlciBoYXNuJ3QgaGl0IHRoZSBsYXRlc3Qgc2xpZGUgb3JcbiAgICAgICAgLy8gICBpZiB0aGUgc2xpZGVyIGlzIGEgbG9vcCBhbmRcbiAgICAgICAgLy8gICBpZiB0aGUgc2xpZGVyIGlzbid0IG1vdmluZyByaWdodCBub3c6XG4gICAgICAgIC8vICAgICBHbyB0byBuZXh0IHNsaWRlIGFuZFxuICAgICAgICAvLyAgICAgZW1pdCBhIHNjcm9sbCBldmVudC5cbiAgICAgICAgLy8gRWxzZSAodGhlIHVzZXIgaXMgc2Nyb2xsaW5nIHRvd2FyZHMgdGhlIGJlZ2lubmluZykgYW5kXG4gICAgICAgIC8vIGlmIHRoZSBzbGlkZXIgaGFzbid0IGhpdCB0aGUgZmlyc3Qgc2xpZGUgb3JcbiAgICAgICAgLy8gaWYgdGhlIHNsaWRlciBpcyBhIGxvb3AgYW5kXG4gICAgICAgIC8vIGlmIHRoZSBzbGlkZXIgaXNuJ3QgbW92aW5nIHJpZ2h0IG5vdzpcbiAgICAgICAgLy8gICBHbyB0byBwcmV2IHNsaWRlIGFuZFxuICAgICAgICAvLyAgIGVtaXQgYSBzY3JvbGwgZXZlbnQuXG5cblxuICAgICAgICBpZiAobmV3RXZlbnQuZGlyZWN0aW9uIDwgMCkge1xuICAgICAgICAgIGlmICgoIXN3aXBlci5pc0VuZCB8fCBzd2lwZXIucGFyYW1zLmxvb3ApICYmICFzd2lwZXIuYW5pbWF0aW5nKSB7XG4gICAgICAgICAgICBzd2lwZXIuc2xpZGVOZXh0KCk7XG4gICAgICAgICAgICBlbWl0KCdzY3JvbGwnLCBuZXdFdmVudC5yYXcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICgoIXN3aXBlci5pc0JlZ2lubmluZyB8fCBzd2lwZXIucGFyYW1zLmxvb3ApICYmICFzd2lwZXIuYW5pbWF0aW5nKSB7XG4gICAgICAgICAgc3dpcGVyLnNsaWRlUHJldigpO1xuICAgICAgICAgIGVtaXQoJ3Njcm9sbCcsIG5ld0V2ZW50LnJhdyk7XG4gICAgICAgIH0gLy8gSWYgeW91IGdvdCBoZXJlIGlzIGJlY2F1c2UgYW4gYW5pbWF0aW9uIGhhcyBiZWVuIHRyaWdnZXJlZCBzbyBzdG9yZSB0aGUgY3VycmVudCB0aW1lXG5cblxuICAgICAgICBsYXN0U2Nyb2xsVGltZSA9IG5ldyB3aW5kb3cuRGF0ZSgpLmdldFRpbWUoKTsgLy8gUmV0dXJuIGZhbHNlIGFzIGEgZGVmYXVsdFxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gcmVsZWFzZVNjcm9sbChuZXdFdmVudCkge1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zLm1vdXNld2hlZWw7XG5cbiAgICAgICAgaWYgKG5ld0V2ZW50LmRpcmVjdGlvbiA8IDApIHtcbiAgICAgICAgICBpZiAoc3dpcGVyLmlzRW5kICYmICFzd2lwZXIucGFyYW1zLmxvb3AgJiYgcGFyYW1zLnJlbGVhc2VPbkVkZ2VzKSB7XG4gICAgICAgICAgICAvLyBSZXR1cm4gdHJ1ZSB0byBhbmltYXRlIHNjcm9sbCBvbiBlZGdlc1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHN3aXBlci5pc0JlZ2lubmluZyAmJiAhc3dpcGVyLnBhcmFtcy5sb29wICYmIHBhcmFtcy5yZWxlYXNlT25FZGdlcykge1xuICAgICAgICAgIC8vIFJldHVybiB0cnVlIHRvIGFuaW1hdGUgc2Nyb2xsIG9uIGVkZ2VzXG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGhhbmRsZShldmVudCkge1xuICAgICAgICBsZXQgZSA9IGV2ZW50O1xuICAgICAgICBsZXQgZGlzYWJsZVBhcmVudFN3aXBlciA9IHRydWU7XG4gICAgICAgIGlmICghc3dpcGVyLmVuYWJsZWQpIHJldHVybjtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy5tb3VzZXdoZWVsO1xuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmNzc01vZGUpIHtcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgdGFyZ2V0ID0gc3dpcGVyLiRlbDtcblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5tb3VzZXdoZWVsLmV2ZW50c1RhcmdldCAhPT0gJ2NvbnRhaW5lcicpIHtcbiAgICAgICAgICB0YXJnZXQgPSAkKHN3aXBlci5wYXJhbXMubW91c2V3aGVlbC5ldmVudHNUYXJnZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFzd2lwZXIubW91c2VFbnRlcmVkICYmICF0YXJnZXRbMF0uY29udGFpbnMoZS50YXJnZXQpICYmICFwYXJhbXMucmVsZWFzZU9uRWRnZXMpIHJldHVybiB0cnVlO1xuICAgICAgICBpZiAoZS5vcmlnaW5hbEV2ZW50KSBlID0gZS5vcmlnaW5hbEV2ZW50OyAvLyBqcXVlcnkgZml4XG5cbiAgICAgICAgbGV0IGRlbHRhID0gMDtcbiAgICAgICAgY29uc3QgcnRsRmFjdG9yID0gc3dpcGVyLnJ0bFRyYW5zbGF0ZSA/IC0xIDogMTtcbiAgICAgICAgY29uc3QgZGF0YSA9IG5vcm1hbGl6ZShlKTtcblxuICAgICAgICBpZiAocGFyYW1zLmZvcmNlVG9BeGlzKSB7XG4gICAgICAgICAgaWYgKHN3aXBlci5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgICAgaWYgKE1hdGguYWJzKGRhdGEucGl4ZWxYKSA+IE1hdGguYWJzKGRhdGEucGl4ZWxZKSkgZGVsdGEgPSAtZGF0YS5waXhlbFggKiBydGxGYWN0b3I7ZWxzZSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2UgaWYgKE1hdGguYWJzKGRhdGEucGl4ZWxZKSA+IE1hdGguYWJzKGRhdGEucGl4ZWxYKSkgZGVsdGEgPSAtZGF0YS5waXhlbFk7ZWxzZSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkZWx0YSA9IE1hdGguYWJzKGRhdGEucGl4ZWxYKSA+IE1hdGguYWJzKGRhdGEucGl4ZWxZKSA/IC1kYXRhLnBpeGVsWCAqIHJ0bEZhY3RvciA6IC1kYXRhLnBpeGVsWTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkZWx0YSA9PT0gMCkgcmV0dXJuIHRydWU7XG4gICAgICAgIGlmIChwYXJhbXMuaW52ZXJ0KSBkZWx0YSA9IC1kZWx0YTsgLy8gR2V0IHRoZSBzY3JvbGwgcG9zaXRpb25zXG5cbiAgICAgICAgbGV0IHBvc2l0aW9ucyA9IHN3aXBlci5nZXRUcmFuc2xhdGUoKSArIGRlbHRhICogcGFyYW1zLnNlbnNpdGl2aXR5O1xuICAgICAgICBpZiAocG9zaXRpb25zID49IHN3aXBlci5taW5UcmFuc2xhdGUoKSkgcG9zaXRpb25zID0gc3dpcGVyLm1pblRyYW5zbGF0ZSgpO1xuICAgICAgICBpZiAocG9zaXRpb25zIDw9IHN3aXBlci5tYXhUcmFuc2xhdGUoKSkgcG9zaXRpb25zID0gc3dpcGVyLm1heFRyYW5zbGF0ZSgpOyAvLyBXaGVuIGxvb3AgaXMgdHJ1ZTpcbiAgICAgICAgLy8gICAgIHRoZSBkaXNhYmxlUGFyZW50U3dpcGVyIHdpbGwgYmUgdHJ1ZS5cbiAgICAgICAgLy8gV2hlbiBsb29wIGlzIGZhbHNlOlxuICAgICAgICAvLyAgICAgaWYgdGhlIHNjcm9sbCBwb3NpdGlvbnMgaXMgbm90IG9uIGVkZ2UsXG4gICAgICAgIC8vICAgICB0aGVuIHRoZSBkaXNhYmxlUGFyZW50U3dpcGVyIHdpbGwgYmUgdHJ1ZS5cbiAgICAgICAgLy8gICAgIGlmIHRoZSBzY3JvbGwgb24gZWRnZSBwb3NpdGlvbnMsXG4gICAgICAgIC8vICAgICB0aGVuIHRoZSBkaXNhYmxlUGFyZW50U3dpcGVyIHdpbGwgYmUgZmFsc2UuXG5cbiAgICAgICAgZGlzYWJsZVBhcmVudFN3aXBlciA9IHN3aXBlci5wYXJhbXMubG9vcCA/IHRydWUgOiAhKHBvc2l0aW9ucyA9PT0gc3dpcGVyLm1pblRyYW5zbGF0ZSgpIHx8IHBvc2l0aW9ucyA9PT0gc3dpcGVyLm1heFRyYW5zbGF0ZSgpKTtcbiAgICAgICAgaWYgKGRpc2FibGVQYXJlbnRTd2lwZXIgJiYgc3dpcGVyLnBhcmFtcy5uZXN0ZWQpIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgICAgaWYgKCFzd2lwZXIucGFyYW1zLmZyZWVNb2RlIHx8ICFzd2lwZXIucGFyYW1zLmZyZWVNb2RlLmVuYWJsZWQpIHtcbiAgICAgICAgICAvLyBSZWdpc3RlciB0aGUgbmV3IGV2ZW50IGluIGEgdmFyaWFibGUgd2hpY2ggc3RvcmVzIHRoZSByZWxldmFudCBkYXRhXG4gICAgICAgICAgY29uc3QgbmV3RXZlbnQgPSB7XG4gICAgICAgICAgICB0aW1lOiBub3coKSxcbiAgICAgICAgICAgIGRlbHRhOiBNYXRoLmFicyhkZWx0YSksXG4gICAgICAgICAgICBkaXJlY3Rpb246IE1hdGguc2lnbihkZWx0YSksXG4gICAgICAgICAgICByYXc6IGV2ZW50XG4gICAgICAgICAgfTsgLy8gS2VlcCB0aGUgbW9zdCByZWNlbnQgZXZlbnRzXG5cbiAgICAgICAgICBpZiAocmVjZW50V2hlZWxFdmVudHMubGVuZ3RoID49IDIpIHtcbiAgICAgICAgICAgIHJlY2VudFdoZWVsRXZlbnRzLnNoaWZ0KCk7IC8vIG9ubHkgc3RvcmUgdGhlIGxhc3QgTiBldmVudHNcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBwcmV2RXZlbnQgPSByZWNlbnRXaGVlbEV2ZW50cy5sZW5ndGggPyByZWNlbnRXaGVlbEV2ZW50c1tyZWNlbnRXaGVlbEV2ZW50cy5sZW5ndGggLSAxXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICByZWNlbnRXaGVlbEV2ZW50cy5wdXNoKG5ld0V2ZW50KTsgLy8gSWYgdGhlcmUgaXMgYXQgbGVhc3Qgb25lIHByZXZpb3VzIHJlY29yZGVkIGV2ZW50OlxuICAgICAgICAgIC8vICAgSWYgZGlyZWN0aW9uIGhhcyBjaGFuZ2VkIG9yXG4gICAgICAgICAgLy8gICBpZiB0aGUgc2Nyb2xsIGlzIHF1aWNrZXIgdGhhbiB0aGUgcHJldmlvdXMgb25lOlxuICAgICAgICAgIC8vICAgICBBbmltYXRlIHRoZSBzbGlkZXIuXG4gICAgICAgICAgLy8gRWxzZSAodGhpcyBpcyB0aGUgZmlyc3QgdGltZSB0aGUgd2hlZWwgaXMgbW92ZWQpOlxuICAgICAgICAgIC8vICAgICBBbmltYXRlIHRoZSBzbGlkZXIuXG5cbiAgICAgICAgICBpZiAocHJldkV2ZW50KSB7XG4gICAgICAgICAgICBpZiAobmV3RXZlbnQuZGlyZWN0aW9uICE9PSBwcmV2RXZlbnQuZGlyZWN0aW9uIHx8IG5ld0V2ZW50LmRlbHRhID4gcHJldkV2ZW50LmRlbHRhIHx8IG5ld0V2ZW50LnRpbWUgPiBwcmV2RXZlbnQudGltZSArIDE1MCkge1xuICAgICAgICAgICAgICBhbmltYXRlU2xpZGVyKG5ld0V2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYW5pbWF0ZVNsaWRlcihuZXdFdmVudCk7XG4gICAgICAgICAgfSAvLyBJZiBpdCdzIHRpbWUgdG8gcmVsZWFzZSB0aGUgc2Nyb2xsOlxuICAgICAgICAgIC8vICAgUmV0dXJuIG5vdyBzbyB5b3UgZG9uJ3QgaGl0IHRoZSBwcmV2ZW50RGVmYXVsdC5cblxuXG4gICAgICAgICAgaWYgKHJlbGVhc2VTY3JvbGwobmV3RXZlbnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gRnJlZW1vZGUgb3Igc2Nyb2xsQ29udGFpbmVyOlxuICAgICAgICAgIC8vIElmIHdlIHJlY2VudGx5IHNuYXBwZWQgYWZ0ZXIgYSBtb21lbnR1bSBzY3JvbGwsIHRoZW4gaWdub3JlIHdoZWVsIGV2ZW50c1xuICAgICAgICAgIC8vIHRvIGdpdmUgdGltZSBmb3IgdGhlIGRlY2VsZXJhdGlvbiB0byBmaW5pc2guIFN0b3AgaWdub3JpbmcgYWZ0ZXIgNTAwIG1zZWNzXG4gICAgICAgICAgLy8gb3IgaWYgaXQncyBhIG5ldyBzY3JvbGwgKGxhcmdlciBkZWx0YSBvciBpbnZlcnNlIHNpZ24gYXMgbGFzdCBldmVudCBiZWZvcmVcbiAgICAgICAgICAvLyBhbiBlbmQtb2YtbW9tZW50dW0gc25hcCkuXG4gICAgICAgICAgY29uc3QgbmV3RXZlbnQgPSB7XG4gICAgICAgICAgICB0aW1lOiBub3coKSxcbiAgICAgICAgICAgIGRlbHRhOiBNYXRoLmFicyhkZWx0YSksXG4gICAgICAgICAgICBkaXJlY3Rpb246IE1hdGguc2lnbihkZWx0YSlcbiAgICAgICAgICB9O1xuICAgICAgICAgIGNvbnN0IGlnbm9yZVdoZWVsRXZlbnRzID0gbGFzdEV2ZW50QmVmb3JlU25hcCAmJiBuZXdFdmVudC50aW1lIDwgbGFzdEV2ZW50QmVmb3JlU25hcC50aW1lICsgNTAwICYmIG5ld0V2ZW50LmRlbHRhIDw9IGxhc3RFdmVudEJlZm9yZVNuYXAuZGVsdGEgJiYgbmV3RXZlbnQuZGlyZWN0aW9uID09PSBsYXN0RXZlbnRCZWZvcmVTbmFwLmRpcmVjdGlvbjtcblxuICAgICAgICAgIGlmICghaWdub3JlV2hlZWxFdmVudHMpIHtcbiAgICAgICAgICAgIGxhc3RFdmVudEJlZm9yZVNuYXAgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmxvb3ApIHtcbiAgICAgICAgICAgICAgc3dpcGVyLmxvb3BGaXgoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHBvc2l0aW9uID0gc3dpcGVyLmdldFRyYW5zbGF0ZSgpICsgZGVsdGEgKiBwYXJhbXMuc2Vuc2l0aXZpdHk7XG4gICAgICAgICAgICBjb25zdCB3YXNCZWdpbm5pbmcgPSBzd2lwZXIuaXNCZWdpbm5pbmc7XG4gICAgICAgICAgICBjb25zdCB3YXNFbmQgPSBzd2lwZXIuaXNFbmQ7XG4gICAgICAgICAgICBpZiAocG9zaXRpb24gPj0gc3dpcGVyLm1pblRyYW5zbGF0ZSgpKSBwb3NpdGlvbiA9IHN3aXBlci5taW5UcmFuc2xhdGUoKTtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbiA8PSBzd2lwZXIubWF4VHJhbnNsYXRlKCkpIHBvc2l0aW9uID0gc3dpcGVyLm1heFRyYW5zbGF0ZSgpO1xuICAgICAgICAgICAgc3dpcGVyLnNldFRyYW5zaXRpb24oMCk7XG4gICAgICAgICAgICBzd2lwZXIuc2V0VHJhbnNsYXRlKHBvc2l0aW9uKTtcbiAgICAgICAgICAgIHN3aXBlci51cGRhdGVQcm9ncmVzcygpO1xuICAgICAgICAgICAgc3dpcGVyLnVwZGF0ZUFjdGl2ZUluZGV4KCk7XG4gICAgICAgICAgICBzd2lwZXIudXBkYXRlU2xpZGVzQ2xhc3NlcygpO1xuXG4gICAgICAgICAgICBpZiAoIXdhc0JlZ2lubmluZyAmJiBzd2lwZXIuaXNCZWdpbm5pbmcgfHwgIXdhc0VuZCAmJiBzd2lwZXIuaXNFbmQpIHtcbiAgICAgICAgICAgICAgc3dpcGVyLnVwZGF0ZVNsaWRlc0NsYXNzZXMoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuZnJlZU1vZGUuc3RpY2t5KSB7XG4gICAgICAgICAgICAgIC8vIFdoZW4gd2hlZWwgc2Nyb2xsaW5nIHN0YXJ0cyB3aXRoIHN0aWNreSAoYWthIHNuYXApIGVuYWJsZWQsIHRoZW4gZGV0ZWN0XG4gICAgICAgICAgICAgIC8vIHRoZSBlbmQgb2YgYSBtb21lbnR1bSBzY3JvbGwgYnkgc3RvcmluZyByZWNlbnQgKE49MTU/KSB3aGVlbCBldmVudHMuXG4gICAgICAgICAgICAgIC8vIDEuIGRvIGFsbCBOIGV2ZW50cyBoYXZlIGRlY3JlYXNpbmcgb3Igc2FtZSAoYWJzb2x1dGUgdmFsdWUpIGRlbHRhP1xuICAgICAgICAgICAgICAvLyAyLiBkaWQgYWxsIE4gZXZlbnRzIGFycml2ZSBpbiB0aGUgbGFzdCBNIChNPTUwMD8pIG1zZWNzP1xuICAgICAgICAgICAgICAvLyAzLiBkb2VzIHRoZSBlYXJsaWVzdCBldmVudCBoYXZlIGFuIChhYnNvbHV0ZSB2YWx1ZSkgZGVsdGEgdGhhdCdzXG4gICAgICAgICAgICAgIC8vICAgIGF0IGxlYXN0IFAgKFA9MT8pIGxhcmdlciB0aGFuIHRoZSBtb3N0IHJlY2VudCBldmVudCdzIGRlbHRhP1xuICAgICAgICAgICAgICAvLyA0LiBkb2VzIHRoZSBsYXRlc3QgZXZlbnQgaGF2ZSBhIGRlbHRhIHRoYXQncyBzbWFsbGVyIHRoYW4gUSAoUT02PykgcGl4ZWxzP1xuICAgICAgICAgICAgICAvLyBJZiAxLTQgYXJlIFwieWVzXCIgdGhlbiB3ZSdyZSBuZWFyIHRoZSBlbmQgb2YgYSBtb21lbnR1bSBzY3JvbGwgZGVjZWxlcmF0aW9uLlxuICAgICAgICAgICAgICAvLyBTbmFwIGltbWVkaWF0ZWx5IGFuZCBpZ25vcmUgcmVtYWluaW5nIHdoZWVsIGV2ZW50cyBpbiB0aGlzIHNjcm9sbC5cbiAgICAgICAgICAgICAgLy8gU2VlIGNvbW1lbnQgYWJvdmUgZm9yIFwicmVtYWluaW5nIHdoZWVsIGV2ZW50cyBpbiB0aGlzIHNjcm9sbFwiIGRldGVybWluYXRpb24uXG4gICAgICAgICAgICAgIC8vIElmIDEtNCBhcmVuJ3Qgc2F0aXNmaWVkLCB0aGVuIHdhaXQgdG8gc25hcCB1bnRpbCA1MDBtcyBhZnRlciB0aGUgbGFzdCBldmVudC5cbiAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgICAgICB0aW1lb3V0ID0gdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgIGlmIChyZWNlbnRXaGVlbEV2ZW50cy5sZW5ndGggPj0gMTUpIHtcbiAgICAgICAgICAgICAgICByZWNlbnRXaGVlbEV2ZW50cy5zaGlmdCgpOyAvLyBvbmx5IHN0b3JlIHRoZSBsYXN0IE4gZXZlbnRzXG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBjb25zdCBwcmV2RXZlbnQgPSByZWNlbnRXaGVlbEV2ZW50cy5sZW5ndGggPyByZWNlbnRXaGVlbEV2ZW50c1tyZWNlbnRXaGVlbEV2ZW50cy5sZW5ndGggLSAxXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgY29uc3QgZmlyc3RFdmVudCA9IHJlY2VudFdoZWVsRXZlbnRzWzBdO1xuICAgICAgICAgICAgICByZWNlbnRXaGVlbEV2ZW50cy5wdXNoKG5ld0V2ZW50KTtcblxuICAgICAgICAgICAgICBpZiAocHJldkV2ZW50ICYmIChuZXdFdmVudC5kZWx0YSA+IHByZXZFdmVudC5kZWx0YSB8fCBuZXdFdmVudC5kaXJlY3Rpb24gIT09IHByZXZFdmVudC5kaXJlY3Rpb24pKSB7XG4gICAgICAgICAgICAgICAgLy8gSW5jcmVhc2luZyBvciByZXZlcnNlLXNpZ24gZGVsdGEgbWVhbnMgdGhlIHVzZXIgc3RhcnRlZCBzY3JvbGxpbmcgYWdhaW4uIENsZWFyIHRoZSB3aGVlbCBldmVudCBsb2cuXG4gICAgICAgICAgICAgICAgcmVjZW50V2hlZWxFdmVudHMuc3BsaWNlKDApO1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKHJlY2VudFdoZWVsRXZlbnRzLmxlbmd0aCA+PSAxNSAmJiBuZXdFdmVudC50aW1lIC0gZmlyc3RFdmVudC50aW1lIDwgNTAwICYmIGZpcnN0RXZlbnQuZGVsdGEgLSBuZXdFdmVudC5kZWx0YSA+PSAxICYmIG5ld0V2ZW50LmRlbHRhIDw9IDYpIHtcbiAgICAgICAgICAgICAgICAvLyBXZSdyZSBhdCB0aGUgZW5kIG9mIHRoZSBkZWNlbGVyYXRpb24gb2YgYSBtb21lbnR1bSBzY3JvbGwsIHNvIHRoZXJlJ3Mgbm8gbmVlZFxuICAgICAgICAgICAgICAgIC8vIHRvIHdhaXQgZm9yIG1vcmUgZXZlbnRzLiBTbmFwIEFTQVAgb24gdGhlIG5leHQgdGljay5cbiAgICAgICAgICAgICAgICAvLyBBbHNvLCBiZWNhdXNlIHRoZXJlJ3Mgc29tZSByZW1haW5pbmcgbW9tZW50dW0gd2UnbGwgYmlhcyB0aGUgc25hcCBpbiB0aGVcbiAgICAgICAgICAgICAgICAvLyBkaXJlY3Rpb24gb2YgdGhlIG9uZ29pbmcgc2Nyb2xsIGJlY2F1c2UgaXQncyBiZXR0ZXIgVVggZm9yIHRoZSBzY3JvbGwgdG8gc25hcFxuICAgICAgICAgICAgICAgIC8vIGluIHRoZSBzYW1lIGRpcmVjdGlvbiBhcyB0aGUgc2Nyb2xsIGluc3RlYWQgb2YgcmV2ZXJzaW5nIHRvIHNuYXAuICBUaGVyZWZvcmUsXG4gICAgICAgICAgICAgICAgLy8gaWYgaXQncyBhbHJlYWR5IHNjcm9sbGVkIG1vcmUgdGhhbiAyMCUgaW4gdGhlIGN1cnJlbnQgZGlyZWN0aW9uLCBrZWVwIGdvaW5nLlxuICAgICAgICAgICAgICAgIGNvbnN0IHNuYXBUb1RocmVzaG9sZCA9IGRlbHRhID4gMCA/IDAuOCA6IDAuMjtcbiAgICAgICAgICAgICAgICBsYXN0RXZlbnRCZWZvcmVTbmFwID0gbmV3RXZlbnQ7XG4gICAgICAgICAgICAgICAgcmVjZW50V2hlZWxFdmVudHMuc3BsaWNlKDApO1xuICAgICAgICAgICAgICAgIHRpbWVvdXQgPSBuZXh0VGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgICBzd2lwZXIuc2xpZGVUb0Nsb3Nlc3Qoc3dpcGVyLnBhcmFtcy5zcGVlZCwgdHJ1ZSwgdW5kZWZpbmVkLCBzbmFwVG9UaHJlc2hvbGQpO1xuICAgICAgICAgICAgICAgIH0sIDApOyAvLyBubyBkZWxheTsgbW92ZSBvbiBuZXh0IHRpY2tcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlmICghdGltZW91dCkge1xuICAgICAgICAgICAgICAgIC8vIGlmIHdlIGdldCBoZXJlLCB0aGVuIHdlIGhhdmVuJ3QgZGV0ZWN0ZWQgdGhlIGVuZCBvZiBhIG1vbWVudHVtIHNjcm9sbCwgc29cbiAgICAgICAgICAgICAgICAvLyB3ZSdsbCBjb25zaWRlciBhIHNjcm9sbCBcImNvbXBsZXRlXCIgd2hlbiB0aGVyZSBoYXZlbid0IGJlZW4gYW55IHdoZWVsIGV2ZW50c1xuICAgICAgICAgICAgICAgIC8vIGZvciA1MDBtcy5cbiAgICAgICAgICAgICAgICB0aW1lb3V0ID0gbmV4dFRpY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgY29uc3Qgc25hcFRvVGhyZXNob2xkID0gMC41O1xuICAgICAgICAgICAgICAgICAgbGFzdEV2ZW50QmVmb3JlU25hcCA9IG5ld0V2ZW50O1xuICAgICAgICAgICAgICAgICAgcmVjZW50V2hlZWxFdmVudHMuc3BsaWNlKDApO1xuICAgICAgICAgICAgICAgICAgc3dpcGVyLnNsaWRlVG9DbG9zZXN0KHN3aXBlci5wYXJhbXMuc3BlZWQsIHRydWUsIHVuZGVmaW5lZCwgc25hcFRvVGhyZXNob2xkKTtcbiAgICAgICAgICAgICAgICB9LCA1MDApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IC8vIEVtaXQgZXZlbnRcblxuXG4gICAgICAgICAgICBpZiAoIWlnbm9yZVdoZWVsRXZlbnRzKSBlbWl0KCdzY3JvbGwnLCBlKTsgLy8gU3RvcCBhdXRvcGxheVxuXG4gICAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5hdXRvcGxheSAmJiBzd2lwZXIucGFyYW1zLmF1dG9wbGF5RGlzYWJsZU9uSW50ZXJhY3Rpb24pIHN3aXBlci5hdXRvcGxheS5zdG9wKCk7IC8vIFJldHVybiBwYWdlIHNjcm9sbCBvbiBlZGdlIHBvc2l0aW9uc1xuXG4gICAgICAgICAgICBpZiAocG9zaXRpb24gPT09IHN3aXBlci5taW5UcmFuc2xhdGUoKSB8fCBwb3NpdGlvbiA9PT0gc3dpcGVyLm1heFRyYW5zbGF0ZSgpKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZS5wcmV2ZW50RGVmYXVsdCkgZS5wcmV2ZW50RGVmYXVsdCgpO2Vsc2UgZS5yZXR1cm5WYWx1ZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGV2ZW50cyhtZXRob2QpIHtcbiAgICAgICAgbGV0IHRhcmdldCA9IHN3aXBlci4kZWw7XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMubW91c2V3aGVlbC5ldmVudHNUYXJnZXQgIT09ICdjb250YWluZXInKSB7XG4gICAgICAgICAgdGFyZ2V0ID0gJChzd2lwZXIucGFyYW1zLm1vdXNld2hlZWwuZXZlbnRzVGFyZ2V0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRhcmdldFttZXRob2RdKCdtb3VzZWVudGVyJywgaGFuZGxlTW91c2VFbnRlcik7XG4gICAgICAgIHRhcmdldFttZXRob2RdKCdtb3VzZWxlYXZlJywgaGFuZGxlTW91c2VMZWF2ZSk7XG4gICAgICAgIHRhcmdldFttZXRob2RdKCd3aGVlbCcsIGhhbmRsZSk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGVuYWJsZSgpIHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuY3NzTW9kZSkge1xuICAgICAgICAgIHN3aXBlci53cmFwcGVyRWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignd2hlZWwnLCBoYW5kbGUpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN3aXBlci5tb3VzZXdoZWVsLmVuYWJsZWQpIHJldHVybiBmYWxzZTtcbiAgICAgICAgZXZlbnRzKCdvbicpO1xuICAgICAgICBzd2lwZXIubW91c2V3aGVlbC5lbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGRpc2FibGUoKSB7XG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmNzc01vZGUpIHtcbiAgICAgICAgICBzd2lwZXIud3JhcHBlckVsLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGhhbmRsZSk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXN3aXBlci5tb3VzZXdoZWVsLmVuYWJsZWQpIHJldHVybiBmYWxzZTtcbiAgICAgICAgZXZlbnRzKCdvZmYnKTtcbiAgICAgICAgc3dpcGVyLm1vdXNld2hlZWwuZW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgb24oJ2luaXQnLCAoKSA9PiB7XG4gICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy5tb3VzZXdoZWVsLmVuYWJsZWQgJiYgc3dpcGVyLnBhcmFtcy5jc3NNb2RlKSB7XG4gICAgICAgICAgZGlzYWJsZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMubW91c2V3aGVlbC5lbmFibGVkKSBlbmFibGUoKTtcbiAgICAgIH0pO1xuICAgICAgb24oJ2Rlc3Ryb3knLCAoKSA9PiB7XG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmNzc01vZGUpIHtcbiAgICAgICAgICBlbmFibGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzd2lwZXIubW91c2V3aGVlbC5lbmFibGVkKSBkaXNhYmxlKCk7XG4gICAgICB9KTtcbiAgICAgIE9iamVjdC5hc3NpZ24oc3dpcGVyLm1vdXNld2hlZWwsIHtcbiAgICAgICAgZW5hYmxlLFxuICAgICAgICBkaXNhYmxlXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50SWZOb3REZWZpbmVkKHN3aXBlciwgb3JpZ2luYWxQYXJhbXMsIHBhcmFtcywgY2hlY2tQcm9wcykge1xuICAgICAgY29uc3QgZG9jdW1lbnQgPSBnZXREb2N1bWVudCgpO1xuXG4gICAgICBpZiAoc3dpcGVyLnBhcmFtcy5jcmVhdGVFbGVtZW50cykge1xuICAgICAgICBPYmplY3Qua2V5cyhjaGVja1Byb3BzKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgaWYgKCFwYXJhbXNba2V5XSAmJiBwYXJhbXMuYXV0byA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgbGV0IGVsZW1lbnQgPSBzd2lwZXIuJGVsLmNoaWxkcmVuKGAuJHtjaGVja1Byb3BzW2tleV19YClbMF07XG5cbiAgICAgICAgICAgIGlmICghZWxlbWVudCkge1xuICAgICAgICAgICAgICBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gY2hlY2tQcm9wc1trZXldO1xuICAgICAgICAgICAgICBzd2lwZXIuJGVsLmFwcGVuZChlbGVtZW50KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcGFyYW1zW2tleV0gPSBlbGVtZW50O1xuICAgICAgICAgICAgb3JpZ2luYWxQYXJhbXNba2V5XSA9IGVsZW1lbnQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHBhcmFtcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBOYXZpZ2F0aW9uKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZXh0ZW5kUGFyYW1zLFxuICAgICAgICBvbixcbiAgICAgICAgZW1pdFxuICAgICAgfSA9IF9yZWY7XG4gICAgICBleHRlbmRQYXJhbXMoe1xuICAgICAgICBuYXZpZ2F0aW9uOiB7XG4gICAgICAgICAgbmV4dEVsOiBudWxsLFxuICAgICAgICAgIHByZXZFbDogbnVsbCxcbiAgICAgICAgICBoaWRlT25DbGljazogZmFsc2UsXG4gICAgICAgICAgZGlzYWJsZWRDbGFzczogJ3N3aXBlci1idXR0b24tZGlzYWJsZWQnLFxuICAgICAgICAgIGhpZGRlbkNsYXNzOiAnc3dpcGVyLWJ1dHRvbi1oaWRkZW4nLFxuICAgICAgICAgIGxvY2tDbGFzczogJ3N3aXBlci1idXR0b24tbG9jaydcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzd2lwZXIubmF2aWdhdGlvbiA9IHtcbiAgICAgICAgbmV4dEVsOiBudWxsLFxuICAgICAgICAkbmV4dEVsOiBudWxsLFxuICAgICAgICBwcmV2RWw6IG51bGwsXG4gICAgICAgICRwcmV2RWw6IG51bGxcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIGdldEVsKGVsKSB7XG4gICAgICAgIGxldCAkZWw7XG5cbiAgICAgICAgaWYgKGVsKSB7XG4gICAgICAgICAgJGVsID0gJChlbCk7XG5cbiAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy51bmlxdWVOYXZFbGVtZW50cyAmJiB0eXBlb2YgZWwgPT09ICdzdHJpbmcnICYmICRlbC5sZW5ndGggPiAxICYmIHN3aXBlci4kZWwuZmluZChlbCkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAkZWwgPSBzd2lwZXIuJGVsLmZpbmQoZWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAkZWw7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHRvZ2dsZUVsKCRlbCwgZGlzYWJsZWQpIHtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy5uYXZpZ2F0aW9uO1xuXG4gICAgICAgIGlmICgkZWwgJiYgJGVsLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAkZWxbZGlzYWJsZWQgPyAnYWRkQ2xhc3MnIDogJ3JlbW92ZUNsYXNzJ10ocGFyYW1zLmRpc2FibGVkQ2xhc3MpO1xuICAgICAgICAgIGlmICgkZWxbMF0gJiYgJGVsWzBdLnRhZ05hbWUgPT09ICdCVVRUT04nKSAkZWxbMF0uZGlzYWJsZWQgPSBkaXNhYmxlZDtcblxuICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLndhdGNoT3ZlcmZsb3cgJiYgc3dpcGVyLmVuYWJsZWQpIHtcbiAgICAgICAgICAgICRlbFtzd2lwZXIuaXNMb2NrZWQgPyAnYWRkQ2xhc3MnIDogJ3JlbW92ZUNsYXNzJ10ocGFyYW1zLmxvY2tDbGFzcyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHVwZGF0ZSgpIHtcbiAgICAgICAgLy8gVXBkYXRlIE5hdmlnYXRpb24gQnV0dG9uc1xuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5sb29wKSByZXR1cm47XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAkbmV4dEVsLFxuICAgICAgICAgICRwcmV2RWxcbiAgICAgICAgfSA9IHN3aXBlci5uYXZpZ2F0aW9uO1xuICAgICAgICB0b2dnbGVFbCgkcHJldkVsLCBzd2lwZXIuaXNCZWdpbm5pbmcgJiYgIXN3aXBlci5wYXJhbXMucmV3aW5kKTtcbiAgICAgICAgdG9nZ2xlRWwoJG5leHRFbCwgc3dpcGVyLmlzRW5kICYmICFzd2lwZXIucGFyYW1zLnJld2luZCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIG9uUHJldkNsaWNrKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBpZiAoc3dpcGVyLmlzQmVnaW5uaW5nICYmICFzd2lwZXIucGFyYW1zLmxvb3AgJiYgIXN3aXBlci5wYXJhbXMucmV3aW5kKSByZXR1cm47XG4gICAgICAgIHN3aXBlci5zbGlkZVByZXYoKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gb25OZXh0Q2xpY2soZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGlmIChzd2lwZXIuaXNFbmQgJiYgIXN3aXBlci5wYXJhbXMubG9vcCAmJiAhc3dpcGVyLnBhcmFtcy5yZXdpbmQpIHJldHVybjtcbiAgICAgICAgc3dpcGVyLnNsaWRlTmV4dCgpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBpbml0KCkge1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zLm5hdmlnYXRpb247XG4gICAgICAgIHN3aXBlci5wYXJhbXMubmF2aWdhdGlvbiA9IGNyZWF0ZUVsZW1lbnRJZk5vdERlZmluZWQoc3dpcGVyLCBzd2lwZXIub3JpZ2luYWxQYXJhbXMubmF2aWdhdGlvbiwgc3dpcGVyLnBhcmFtcy5uYXZpZ2F0aW9uLCB7XG4gICAgICAgICAgbmV4dEVsOiAnc3dpcGVyLWJ1dHRvbi1uZXh0JyxcbiAgICAgICAgICBwcmV2RWw6ICdzd2lwZXItYnV0dG9uLXByZXYnXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIShwYXJhbXMubmV4dEVsIHx8IHBhcmFtcy5wcmV2RWwpKSByZXR1cm47XG4gICAgICAgIGNvbnN0ICRuZXh0RWwgPSBnZXRFbChwYXJhbXMubmV4dEVsKTtcbiAgICAgICAgY29uc3QgJHByZXZFbCA9IGdldEVsKHBhcmFtcy5wcmV2RWwpO1xuXG4gICAgICAgIGlmICgkbmV4dEVsICYmICRuZXh0RWwubGVuZ3RoID4gMCkge1xuICAgICAgICAgICRuZXh0RWwub24oJ2NsaWNrJywgb25OZXh0Q2xpY2spO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCRwcmV2RWwgJiYgJHByZXZFbC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgJHByZXZFbC5vbignY2xpY2snLCBvblByZXZDbGljayk7XG4gICAgICAgIH1cblxuICAgICAgICBPYmplY3QuYXNzaWduKHN3aXBlci5uYXZpZ2F0aW9uLCB7XG4gICAgICAgICAgJG5leHRFbCxcbiAgICAgICAgICBuZXh0RWw6ICRuZXh0RWwgJiYgJG5leHRFbFswXSxcbiAgICAgICAgICAkcHJldkVsLFxuICAgICAgICAgIHByZXZFbDogJHByZXZFbCAmJiAkcHJldkVsWzBdXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICghc3dpcGVyLmVuYWJsZWQpIHtcbiAgICAgICAgICBpZiAoJG5leHRFbCkgJG5leHRFbC5hZGRDbGFzcyhwYXJhbXMubG9ja0NsYXNzKTtcbiAgICAgICAgICBpZiAoJHByZXZFbCkgJHByZXZFbC5hZGRDbGFzcyhwYXJhbXMubG9ja0NsYXNzKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgJG5leHRFbCxcbiAgICAgICAgICAkcHJldkVsXG4gICAgICAgIH0gPSBzd2lwZXIubmF2aWdhdGlvbjtcblxuICAgICAgICBpZiAoJG5leHRFbCAmJiAkbmV4dEVsLmxlbmd0aCkge1xuICAgICAgICAgICRuZXh0RWwub2ZmKCdjbGljaycsIG9uTmV4dENsaWNrKTtcbiAgICAgICAgICAkbmV4dEVsLnJlbW92ZUNsYXNzKHN3aXBlci5wYXJhbXMubmF2aWdhdGlvbi5kaXNhYmxlZENsYXNzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgkcHJldkVsICYmICRwcmV2RWwubGVuZ3RoKSB7XG4gICAgICAgICAgJHByZXZFbC5vZmYoJ2NsaWNrJywgb25QcmV2Q2xpY2spO1xuICAgICAgICAgICRwcmV2RWwucmVtb3ZlQ2xhc3Moc3dpcGVyLnBhcmFtcy5uYXZpZ2F0aW9uLmRpc2FibGVkQ2xhc3MpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG9uKCdpbml0JywgKCkgPT4ge1xuICAgICAgICBpbml0KCk7XG4gICAgICAgIHVwZGF0ZSgpO1xuICAgICAgfSk7XG4gICAgICBvbigndG9FZGdlIGZyb21FZGdlIGxvY2sgdW5sb2NrJywgKCkgPT4ge1xuICAgICAgICB1cGRhdGUoKTtcbiAgICAgIH0pO1xuICAgICAgb24oJ2Rlc3Ryb3knLCAoKSA9PiB7XG4gICAgICAgIGRlc3Ryb3koKTtcbiAgICAgIH0pO1xuICAgICAgb24oJ2VuYWJsZSBkaXNhYmxlJywgKCkgPT4ge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgJG5leHRFbCxcbiAgICAgICAgICAkcHJldkVsXG4gICAgICAgIH0gPSBzd2lwZXIubmF2aWdhdGlvbjtcblxuICAgICAgICBpZiAoJG5leHRFbCkge1xuICAgICAgICAgICRuZXh0RWxbc3dpcGVyLmVuYWJsZWQgPyAncmVtb3ZlQ2xhc3MnIDogJ2FkZENsYXNzJ10oc3dpcGVyLnBhcmFtcy5uYXZpZ2F0aW9uLmxvY2tDbGFzcyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJHByZXZFbCkge1xuICAgICAgICAgICRwcmV2RWxbc3dpcGVyLmVuYWJsZWQgPyAncmVtb3ZlQ2xhc3MnIDogJ2FkZENsYXNzJ10oc3dpcGVyLnBhcmFtcy5uYXZpZ2F0aW9uLmxvY2tDbGFzcyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb24oJ2NsaWNrJywgKF9zLCBlKSA9PiB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAkbmV4dEVsLFxuICAgICAgICAgICRwcmV2RWxcbiAgICAgICAgfSA9IHN3aXBlci5uYXZpZ2F0aW9uO1xuICAgICAgICBjb25zdCB0YXJnZXRFbCA9IGUudGFyZ2V0O1xuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLm5hdmlnYXRpb24uaGlkZU9uQ2xpY2sgJiYgISQodGFyZ2V0RWwpLmlzKCRwcmV2RWwpICYmICEkKHRhcmdldEVsKS5pcygkbmV4dEVsKSkge1xuICAgICAgICAgIGlmIChzd2lwZXIucGFnaW5hdGlvbiAmJiBzd2lwZXIucGFyYW1zLnBhZ2luYXRpb24gJiYgc3dpcGVyLnBhcmFtcy5wYWdpbmF0aW9uLmNsaWNrYWJsZSAmJiAoc3dpcGVyLnBhZ2luYXRpb24uZWwgPT09IHRhcmdldEVsIHx8IHN3aXBlci5wYWdpbmF0aW9uLmVsLmNvbnRhaW5zKHRhcmdldEVsKSkpIHJldHVybjtcbiAgICAgICAgICBsZXQgaXNIaWRkZW47XG5cbiAgICAgICAgICBpZiAoJG5leHRFbCkge1xuICAgICAgICAgICAgaXNIaWRkZW4gPSAkbmV4dEVsLmhhc0NsYXNzKHN3aXBlci5wYXJhbXMubmF2aWdhdGlvbi5oaWRkZW5DbGFzcyk7XG4gICAgICAgICAgfSBlbHNlIGlmICgkcHJldkVsKSB7XG4gICAgICAgICAgICBpc0hpZGRlbiA9ICRwcmV2RWwuaGFzQ2xhc3Moc3dpcGVyLnBhcmFtcy5uYXZpZ2F0aW9uLmhpZGRlbkNsYXNzKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaXNIaWRkZW4gPT09IHRydWUpIHtcbiAgICAgICAgICAgIGVtaXQoJ25hdmlnYXRpb25TaG93Jyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVtaXQoJ25hdmlnYXRpb25IaWRlJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCRuZXh0RWwpIHtcbiAgICAgICAgICAgICRuZXh0RWwudG9nZ2xlQ2xhc3Moc3dpcGVyLnBhcmFtcy5uYXZpZ2F0aW9uLmhpZGRlbkNsYXNzKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoJHByZXZFbCkge1xuICAgICAgICAgICAgJHByZXZFbC50b2dnbGVDbGFzcyhzd2lwZXIucGFyYW1zLm5hdmlnYXRpb24uaGlkZGVuQ2xhc3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBPYmplY3QuYXNzaWduKHN3aXBlci5uYXZpZ2F0aW9uLCB7XG4gICAgICAgIHVwZGF0ZSxcbiAgICAgICAgaW5pdCxcbiAgICAgICAgZGVzdHJveVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xhc3Nlc1RvU2VsZWN0b3IoY2xhc3Nlcykge1xuICAgICAgaWYgKGNsYXNzZXMgPT09IHZvaWQgMCkge1xuICAgICAgICBjbGFzc2VzID0gJyc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBgLiR7Y2xhc3Nlcy50cmltKCkucmVwbGFjZSgvKFtcXC46IVxcL10pL2csICdcXFxcJDEnKSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG4gIC5yZXBsYWNlKC8gL2csICcuJyl9YDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBQYWdpbmF0aW9uKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZXh0ZW5kUGFyYW1zLFxuICAgICAgICBvbixcbiAgICAgICAgZW1pdFxuICAgICAgfSA9IF9yZWY7XG4gICAgICBjb25zdCBwZnggPSAnc3dpcGVyLXBhZ2luYXRpb24nO1xuICAgICAgZXh0ZW5kUGFyYW1zKHtcbiAgICAgICAgcGFnaW5hdGlvbjoge1xuICAgICAgICAgIGVsOiBudWxsLFxuICAgICAgICAgIGJ1bGxldEVsZW1lbnQ6ICdzcGFuJyxcbiAgICAgICAgICBjbGlja2FibGU6IGZhbHNlLFxuICAgICAgICAgIGhpZGVPbkNsaWNrOiBmYWxzZSxcbiAgICAgICAgICByZW5kZXJCdWxsZXQ6IG51bGwsXG4gICAgICAgICAgcmVuZGVyUHJvZ3Jlc3NiYXI6IG51bGwsXG4gICAgICAgICAgcmVuZGVyRnJhY3Rpb246IG51bGwsXG4gICAgICAgICAgcmVuZGVyQ3VzdG9tOiBudWxsLFxuICAgICAgICAgIHByb2dyZXNzYmFyT3Bwb3NpdGU6IGZhbHNlLFxuICAgICAgICAgIHR5cGU6ICdidWxsZXRzJyxcbiAgICAgICAgICAvLyAnYnVsbGV0cycgb3IgJ3Byb2dyZXNzYmFyJyBvciAnZnJhY3Rpb24nIG9yICdjdXN0b20nXG4gICAgICAgICAgZHluYW1pY0J1bGxldHM6IGZhbHNlLFxuICAgICAgICAgIGR5bmFtaWNNYWluQnVsbGV0czogMSxcbiAgICAgICAgICBmb3JtYXRGcmFjdGlvbkN1cnJlbnQ6IG51bWJlciA9PiBudW1iZXIsXG4gICAgICAgICAgZm9ybWF0RnJhY3Rpb25Ub3RhbDogbnVtYmVyID0+IG51bWJlcixcbiAgICAgICAgICBidWxsZXRDbGFzczogYCR7cGZ4fS1idWxsZXRgLFxuICAgICAgICAgIGJ1bGxldEFjdGl2ZUNsYXNzOiBgJHtwZnh9LWJ1bGxldC1hY3RpdmVgLFxuICAgICAgICAgIG1vZGlmaWVyQ2xhc3M6IGAke3BmeH0tYCxcbiAgICAgICAgICBjdXJyZW50Q2xhc3M6IGAke3BmeH0tY3VycmVudGAsXG4gICAgICAgICAgdG90YWxDbGFzczogYCR7cGZ4fS10b3RhbGAsXG4gICAgICAgICAgaGlkZGVuQ2xhc3M6IGAke3BmeH0taGlkZGVuYCxcbiAgICAgICAgICBwcm9ncmVzc2JhckZpbGxDbGFzczogYCR7cGZ4fS1wcm9ncmVzc2Jhci1maWxsYCxcbiAgICAgICAgICBwcm9ncmVzc2Jhck9wcG9zaXRlQ2xhc3M6IGAke3BmeH0tcHJvZ3Jlc3NiYXItb3Bwb3NpdGVgLFxuICAgICAgICAgIGNsaWNrYWJsZUNsYXNzOiBgJHtwZnh9LWNsaWNrYWJsZWAsXG4gICAgICAgICAgbG9ja0NsYXNzOiBgJHtwZnh9LWxvY2tgLFxuICAgICAgICAgIGhvcml6b250YWxDbGFzczogYCR7cGZ4fS1ob3Jpem9udGFsYCxcbiAgICAgICAgICB2ZXJ0aWNhbENsYXNzOiBgJHtwZnh9LXZlcnRpY2FsYFxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHN3aXBlci5wYWdpbmF0aW9uID0ge1xuICAgICAgICBlbDogbnVsbCxcbiAgICAgICAgJGVsOiBudWxsLFxuICAgICAgICBidWxsZXRzOiBbXVxuICAgICAgfTtcbiAgICAgIGxldCBidWxsZXRTaXplO1xuICAgICAgbGV0IGR5bmFtaWNCdWxsZXRJbmRleCA9IDA7XG5cbiAgICAgIGZ1bmN0aW9uIGlzUGFnaW5hdGlvbkRpc2FibGVkKCkge1xuICAgICAgICByZXR1cm4gIXN3aXBlci5wYXJhbXMucGFnaW5hdGlvbi5lbCB8fCAhc3dpcGVyLnBhZ2luYXRpb24uZWwgfHwgIXN3aXBlci5wYWdpbmF0aW9uLiRlbCB8fCBzd2lwZXIucGFnaW5hdGlvbi4kZWwubGVuZ3RoID09PSAwO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBzZXRTaWRlQnVsbGV0cygkYnVsbGV0RWwsIHBvc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBidWxsZXRBY3RpdmVDbGFzc1xuICAgICAgICB9ID0gc3dpcGVyLnBhcmFtcy5wYWdpbmF0aW9uO1xuICAgICAgICAkYnVsbGV0RWxbcG9zaXRpb25dKCkuYWRkQ2xhc3MoYCR7YnVsbGV0QWN0aXZlQ2xhc3N9LSR7cG9zaXRpb259YClbcG9zaXRpb25dKCkuYWRkQ2xhc3MoYCR7YnVsbGV0QWN0aXZlQ2xhc3N9LSR7cG9zaXRpb259LSR7cG9zaXRpb259YCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHVwZGF0ZSgpIHtcbiAgICAgICAgLy8gUmVuZGVyIHx8IFVwZGF0ZSBQYWdpbmF0aW9uIGJ1bGxldHMvaXRlbXNcbiAgICAgICAgY29uc3QgcnRsID0gc3dpcGVyLnJ0bDtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy5wYWdpbmF0aW9uO1xuICAgICAgICBpZiAoaXNQYWdpbmF0aW9uRGlzYWJsZWQoKSkgcmV0dXJuO1xuICAgICAgICBjb25zdCBzbGlkZXNMZW5ndGggPSBzd2lwZXIudmlydHVhbCAmJiBzd2lwZXIucGFyYW1zLnZpcnR1YWwuZW5hYmxlZCA/IHN3aXBlci52aXJ0dWFsLnNsaWRlcy5sZW5ndGggOiBzd2lwZXIuc2xpZGVzLmxlbmd0aDtcbiAgICAgICAgY29uc3QgJGVsID0gc3dpcGVyLnBhZ2luYXRpb24uJGVsOyAvLyBDdXJyZW50L1RvdGFsXG5cbiAgICAgICAgbGV0IGN1cnJlbnQ7XG4gICAgICAgIGNvbnN0IHRvdGFsID0gc3dpcGVyLnBhcmFtcy5sb29wID8gTWF0aC5jZWlsKChzbGlkZXNMZW5ndGggLSBzd2lwZXIubG9vcGVkU2xpZGVzICogMikgLyBzd2lwZXIucGFyYW1zLnNsaWRlc1Blckdyb3VwKSA6IHN3aXBlci5zbmFwR3JpZC5sZW5ndGg7XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMubG9vcCkge1xuICAgICAgICAgIGN1cnJlbnQgPSBNYXRoLmNlaWwoKHN3aXBlci5hY3RpdmVJbmRleCAtIHN3aXBlci5sb29wZWRTbGlkZXMpIC8gc3dpcGVyLnBhcmFtcy5zbGlkZXNQZXJHcm91cCk7XG5cbiAgICAgICAgICBpZiAoY3VycmVudCA+IHNsaWRlc0xlbmd0aCAtIDEgLSBzd2lwZXIubG9vcGVkU2xpZGVzICogMikge1xuICAgICAgICAgICAgY3VycmVudCAtPSBzbGlkZXNMZW5ndGggLSBzd2lwZXIubG9vcGVkU2xpZGVzICogMjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoY3VycmVudCA+IHRvdGFsIC0gMSkgY3VycmVudCAtPSB0b3RhbDtcbiAgICAgICAgICBpZiAoY3VycmVudCA8IDAgJiYgc3dpcGVyLnBhcmFtcy5wYWdpbmF0aW9uVHlwZSAhPT0gJ2J1bGxldHMnKSBjdXJyZW50ID0gdG90YWwgKyBjdXJyZW50O1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBzd2lwZXIuc25hcEluZGV4ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIGN1cnJlbnQgPSBzd2lwZXIuc25hcEluZGV4O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGN1cnJlbnQgPSBzd2lwZXIuYWN0aXZlSW5kZXggfHwgMDtcbiAgICAgICAgfSAvLyBUeXBlc1xuXG5cbiAgICAgICAgaWYgKHBhcmFtcy50eXBlID09PSAnYnVsbGV0cycgJiYgc3dpcGVyLnBhZ2luYXRpb24uYnVsbGV0cyAmJiBzd2lwZXIucGFnaW5hdGlvbi5idWxsZXRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjb25zdCBidWxsZXRzID0gc3dpcGVyLnBhZ2luYXRpb24uYnVsbGV0cztcbiAgICAgICAgICBsZXQgZmlyc3RJbmRleDtcbiAgICAgICAgICBsZXQgbGFzdEluZGV4O1xuICAgICAgICAgIGxldCBtaWRJbmRleDtcblxuICAgICAgICAgIGlmIChwYXJhbXMuZHluYW1pY0J1bGxldHMpIHtcbiAgICAgICAgICAgIGJ1bGxldFNpemUgPSBidWxsZXRzLmVxKDApW3N3aXBlci5pc0hvcml6b250YWwoKSA/ICdvdXRlcldpZHRoJyA6ICdvdXRlckhlaWdodCddKHRydWUpO1xuICAgICAgICAgICAgJGVsLmNzcyhzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyAnd2lkdGgnIDogJ2hlaWdodCcsIGAke2J1bGxldFNpemUgKiAocGFyYW1zLmR5bmFtaWNNYWluQnVsbGV0cyArIDQpfXB4YCk7XG5cbiAgICAgICAgICAgIGlmIChwYXJhbXMuZHluYW1pY01haW5CdWxsZXRzID4gMSAmJiBzd2lwZXIucHJldmlvdXNJbmRleCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIGR5bmFtaWNCdWxsZXRJbmRleCArPSBjdXJyZW50IC0gKHN3aXBlci5wcmV2aW91c0luZGV4IC0gc3dpcGVyLmxvb3BlZFNsaWRlcyB8fCAwKTtcblxuICAgICAgICAgICAgICBpZiAoZHluYW1pY0J1bGxldEluZGV4ID4gcGFyYW1zLmR5bmFtaWNNYWluQnVsbGV0cyAtIDEpIHtcbiAgICAgICAgICAgICAgICBkeW5hbWljQnVsbGV0SW5kZXggPSBwYXJhbXMuZHluYW1pY01haW5CdWxsZXRzIC0gMTtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChkeW5hbWljQnVsbGV0SW5kZXggPCAwKSB7XG4gICAgICAgICAgICAgICAgZHluYW1pY0J1bGxldEluZGV4ID0gMDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmaXJzdEluZGV4ID0gTWF0aC5tYXgoY3VycmVudCAtIGR5bmFtaWNCdWxsZXRJbmRleCwgMCk7XG4gICAgICAgICAgICBsYXN0SW5kZXggPSBmaXJzdEluZGV4ICsgKE1hdGgubWluKGJ1bGxldHMubGVuZ3RoLCBwYXJhbXMuZHluYW1pY01haW5CdWxsZXRzKSAtIDEpO1xuICAgICAgICAgICAgbWlkSW5kZXggPSAobGFzdEluZGV4ICsgZmlyc3RJbmRleCkgLyAyO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGJ1bGxldHMucmVtb3ZlQ2xhc3MoWycnLCAnLW5leHQnLCAnLW5leHQtbmV4dCcsICctcHJldicsICctcHJldi1wcmV2JywgJy1tYWluJ10ubWFwKHN1ZmZpeCA9PiBgJHtwYXJhbXMuYnVsbGV0QWN0aXZlQ2xhc3N9JHtzdWZmaXh9YCkuam9pbignICcpKTtcblxuICAgICAgICAgIGlmICgkZWwubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgYnVsbGV0cy5lYWNoKGJ1bGxldCA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0ICRidWxsZXQgPSAkKGJ1bGxldCk7XG4gICAgICAgICAgICAgIGNvbnN0IGJ1bGxldEluZGV4ID0gJGJ1bGxldC5pbmRleCgpO1xuXG4gICAgICAgICAgICAgIGlmIChidWxsZXRJbmRleCA9PT0gY3VycmVudCkge1xuICAgICAgICAgICAgICAgICRidWxsZXQuYWRkQ2xhc3MocGFyYW1zLmJ1bGxldEFjdGl2ZUNsYXNzKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlmIChwYXJhbXMuZHluYW1pY0J1bGxldHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoYnVsbGV0SW5kZXggPj0gZmlyc3RJbmRleCAmJiBidWxsZXRJbmRleCA8PSBsYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICRidWxsZXQuYWRkQ2xhc3MoYCR7cGFyYW1zLmJ1bGxldEFjdGl2ZUNsYXNzfS1tYWluYCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGJ1bGxldEluZGV4ID09PSBmaXJzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICBzZXRTaWRlQnVsbGV0cygkYnVsbGV0LCAncHJldicpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChidWxsZXRJbmRleCA9PT0gbGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICBzZXRTaWRlQnVsbGV0cygkYnVsbGV0LCAnbmV4dCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0ICRidWxsZXQgPSBidWxsZXRzLmVxKGN1cnJlbnQpO1xuICAgICAgICAgICAgY29uc3QgYnVsbGV0SW5kZXggPSAkYnVsbGV0LmluZGV4KCk7XG4gICAgICAgICAgICAkYnVsbGV0LmFkZENsYXNzKHBhcmFtcy5idWxsZXRBY3RpdmVDbGFzcyk7XG5cbiAgICAgICAgICAgIGlmIChwYXJhbXMuZHluYW1pY0J1bGxldHMpIHtcbiAgICAgICAgICAgICAgY29uc3QgJGZpcnN0RGlzcGxheWVkQnVsbGV0ID0gYnVsbGV0cy5lcShmaXJzdEluZGV4KTtcbiAgICAgICAgICAgICAgY29uc3QgJGxhc3REaXNwbGF5ZWRCdWxsZXQgPSBidWxsZXRzLmVxKGxhc3RJbmRleCk7XG5cbiAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IGZpcnN0SW5kZXg7IGkgPD0gbGFzdEluZGV4OyBpICs9IDEpIHtcbiAgICAgICAgICAgICAgICBidWxsZXRzLmVxKGkpLmFkZENsYXNzKGAke3BhcmFtcy5idWxsZXRBY3RpdmVDbGFzc30tbWFpbmApO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMubG9vcCkge1xuICAgICAgICAgICAgICAgIGlmIChidWxsZXRJbmRleCA+PSBidWxsZXRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IHBhcmFtcy5keW5hbWljTWFpbkJ1bGxldHM7IGkgPj0gMDsgaSAtPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGJ1bGxldHMuZXEoYnVsbGV0cy5sZW5ndGggLSBpKS5hZGRDbGFzcyhgJHtwYXJhbXMuYnVsbGV0QWN0aXZlQ2xhc3N9LW1haW5gKTtcbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgYnVsbGV0cy5lcShidWxsZXRzLmxlbmd0aCAtIHBhcmFtcy5keW5hbWljTWFpbkJ1bGxldHMgLSAxKS5hZGRDbGFzcyhgJHtwYXJhbXMuYnVsbGV0QWN0aXZlQ2xhc3N9LXByZXZgKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgc2V0U2lkZUJ1bGxldHMoJGZpcnN0RGlzcGxheWVkQnVsbGV0LCAncHJldicpO1xuICAgICAgICAgICAgICAgICAgc2V0U2lkZUJ1bGxldHMoJGxhc3REaXNwbGF5ZWRCdWxsZXQsICduZXh0Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldFNpZGVCdWxsZXRzKCRmaXJzdERpc3BsYXllZEJ1bGxldCwgJ3ByZXYnKTtcbiAgICAgICAgICAgICAgICBzZXRTaWRlQnVsbGV0cygkbGFzdERpc3BsYXllZEJ1bGxldCwgJ25leHQnKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChwYXJhbXMuZHluYW1pY0J1bGxldHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGR5bmFtaWNCdWxsZXRzTGVuZ3RoID0gTWF0aC5taW4oYnVsbGV0cy5sZW5ndGgsIHBhcmFtcy5keW5hbWljTWFpbkJ1bGxldHMgKyA0KTtcbiAgICAgICAgICAgIGNvbnN0IGJ1bGxldHNPZmZzZXQgPSAoYnVsbGV0U2l6ZSAqIGR5bmFtaWNCdWxsZXRzTGVuZ3RoIC0gYnVsbGV0U2l6ZSkgLyAyIC0gbWlkSW5kZXggKiBidWxsZXRTaXplO1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0UHJvcCA9IHJ0bCA/ICdyaWdodCcgOiAnbGVmdCc7XG4gICAgICAgICAgICBidWxsZXRzLmNzcyhzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyBvZmZzZXRQcm9wIDogJ3RvcCcsIGAke2J1bGxldHNPZmZzZXR9cHhgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLnR5cGUgPT09ICdmcmFjdGlvbicpIHtcbiAgICAgICAgICAkZWwuZmluZChjbGFzc2VzVG9TZWxlY3RvcihwYXJhbXMuY3VycmVudENsYXNzKSkudGV4dChwYXJhbXMuZm9ybWF0RnJhY3Rpb25DdXJyZW50KGN1cnJlbnQgKyAxKSk7XG4gICAgICAgICAgJGVsLmZpbmQoY2xhc3Nlc1RvU2VsZWN0b3IocGFyYW1zLnRvdGFsQ2xhc3MpKS50ZXh0KHBhcmFtcy5mb3JtYXRGcmFjdGlvblRvdGFsKHRvdGFsKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLnR5cGUgPT09ICdwcm9ncmVzc2JhcicpIHtcbiAgICAgICAgICBsZXQgcHJvZ3Jlc3NiYXJEaXJlY3Rpb247XG5cbiAgICAgICAgICBpZiAocGFyYW1zLnByb2dyZXNzYmFyT3Bwb3NpdGUpIHtcbiAgICAgICAgICAgIHByb2dyZXNzYmFyRGlyZWN0aW9uID0gc3dpcGVyLmlzSG9yaXpvbnRhbCgpID8gJ3ZlcnRpY2FsJyA6ICdob3Jpem9udGFsJztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvZ3Jlc3NiYXJEaXJlY3Rpb24gPSBzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyAnaG9yaXpvbnRhbCcgOiAndmVydGljYWwnO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHNjYWxlID0gKGN1cnJlbnQgKyAxKSAvIHRvdGFsO1xuICAgICAgICAgIGxldCBzY2FsZVggPSAxO1xuICAgICAgICAgIGxldCBzY2FsZVkgPSAxO1xuXG4gICAgICAgICAgaWYgKHByb2dyZXNzYmFyRGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHNjYWxlWCA9IHNjYWxlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzY2FsZVkgPSBzY2FsZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAkZWwuZmluZChjbGFzc2VzVG9TZWxlY3RvcihwYXJhbXMucHJvZ3Jlc3NiYXJGaWxsQ2xhc3MpKS50cmFuc2Zvcm0oYHRyYW5zbGF0ZTNkKDAsMCwwKSBzY2FsZVgoJHtzY2FsZVh9KSBzY2FsZVkoJHtzY2FsZVl9KWApLnRyYW5zaXRpb24oc3dpcGVyLnBhcmFtcy5zcGVlZCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLnR5cGUgPT09ICdjdXN0b20nICYmIHBhcmFtcy5yZW5kZXJDdXN0b20pIHtcbiAgICAgICAgICAkZWwuaHRtbChwYXJhbXMucmVuZGVyQ3VzdG9tKHN3aXBlciwgY3VycmVudCArIDEsIHRvdGFsKSk7XG4gICAgICAgICAgZW1pdCgncGFnaW5hdGlvblJlbmRlcicsICRlbFswXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZW1pdCgncGFnaW5hdGlvblVwZGF0ZScsICRlbFswXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy53YXRjaE92ZXJmbG93ICYmIHN3aXBlci5lbmFibGVkKSB7XG4gICAgICAgICAgJGVsW3N3aXBlci5pc0xvY2tlZCA/ICdhZGRDbGFzcycgOiAncmVtb3ZlQ2xhc3MnXShwYXJhbXMubG9ja0NsYXNzKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiByZW5kZXIoKSB7XG4gICAgICAgIC8vIFJlbmRlciBDb250YWluZXJcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy5wYWdpbmF0aW9uO1xuICAgICAgICBpZiAoaXNQYWdpbmF0aW9uRGlzYWJsZWQoKSkgcmV0dXJuO1xuICAgICAgICBjb25zdCBzbGlkZXNMZW5ndGggPSBzd2lwZXIudmlydHVhbCAmJiBzd2lwZXIucGFyYW1zLnZpcnR1YWwuZW5hYmxlZCA/IHN3aXBlci52aXJ0dWFsLnNsaWRlcy5sZW5ndGggOiBzd2lwZXIuc2xpZGVzLmxlbmd0aDtcbiAgICAgICAgY29uc3QgJGVsID0gc3dpcGVyLnBhZ2luYXRpb24uJGVsO1xuICAgICAgICBsZXQgcGFnaW5hdGlvbkhUTUwgPSAnJztcblxuICAgICAgICBpZiAocGFyYW1zLnR5cGUgPT09ICdidWxsZXRzJykge1xuICAgICAgICAgIGxldCBudW1iZXJPZkJ1bGxldHMgPSBzd2lwZXIucGFyYW1zLmxvb3AgPyBNYXRoLmNlaWwoKHNsaWRlc0xlbmd0aCAtIHN3aXBlci5sb29wZWRTbGlkZXMgKiAyKSAvIHN3aXBlci5wYXJhbXMuc2xpZGVzUGVyR3JvdXApIDogc3dpcGVyLnNuYXBHcmlkLmxlbmd0aDtcblxuICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmZyZWVNb2RlICYmIHN3aXBlci5wYXJhbXMuZnJlZU1vZGUuZW5hYmxlZCAmJiAhc3dpcGVyLnBhcmFtcy5sb29wICYmIG51bWJlck9mQnVsbGV0cyA+IHNsaWRlc0xlbmd0aCkge1xuICAgICAgICAgICAgbnVtYmVyT2ZCdWxsZXRzID0gc2xpZGVzTGVuZ3RoO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZCdWxsZXRzOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGlmIChwYXJhbXMucmVuZGVyQnVsbGV0KSB7XG4gICAgICAgICAgICAgIHBhZ2luYXRpb25IVE1MICs9IHBhcmFtcy5yZW5kZXJCdWxsZXQuY2FsbChzd2lwZXIsIGksIHBhcmFtcy5idWxsZXRDbGFzcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwYWdpbmF0aW9uSFRNTCArPSBgPCR7cGFyYW1zLmJ1bGxldEVsZW1lbnR9IGNsYXNzPVwiJHtwYXJhbXMuYnVsbGV0Q2xhc3N9XCI+PC8ke3BhcmFtcy5idWxsZXRFbGVtZW50fT5gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgICRlbC5odG1sKHBhZ2luYXRpb25IVE1MKTtcbiAgICAgICAgICBzd2lwZXIucGFnaW5hdGlvbi5idWxsZXRzID0gJGVsLmZpbmQoY2xhc3Nlc1RvU2VsZWN0b3IocGFyYW1zLmJ1bGxldENsYXNzKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLnR5cGUgPT09ICdmcmFjdGlvbicpIHtcbiAgICAgICAgICBpZiAocGFyYW1zLnJlbmRlckZyYWN0aW9uKSB7XG4gICAgICAgICAgICBwYWdpbmF0aW9uSFRNTCA9IHBhcmFtcy5yZW5kZXJGcmFjdGlvbi5jYWxsKHN3aXBlciwgcGFyYW1zLmN1cnJlbnRDbGFzcywgcGFyYW1zLnRvdGFsQ2xhc3MpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYWdpbmF0aW9uSFRNTCA9IGA8c3BhbiBjbGFzcz1cIiR7cGFyYW1zLmN1cnJlbnRDbGFzc31cIj48L3NwYW4+YCArICcgLyAnICsgYDxzcGFuIGNsYXNzPVwiJHtwYXJhbXMudG90YWxDbGFzc31cIj48L3NwYW4+YDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAkZWwuaHRtbChwYWdpbmF0aW9uSFRNTCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLnR5cGUgPT09ICdwcm9ncmVzc2JhcicpIHtcbiAgICAgICAgICBpZiAocGFyYW1zLnJlbmRlclByb2dyZXNzYmFyKSB7XG4gICAgICAgICAgICBwYWdpbmF0aW9uSFRNTCA9IHBhcmFtcy5yZW5kZXJQcm9ncmVzc2Jhci5jYWxsKHN3aXBlciwgcGFyYW1zLnByb2dyZXNzYmFyRmlsbENsYXNzKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGFnaW5hdGlvbkhUTUwgPSBgPHNwYW4gY2xhc3M9XCIke3BhcmFtcy5wcm9ncmVzc2JhckZpbGxDbGFzc31cIj48L3NwYW4+YDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAkZWwuaHRtbChwYWdpbmF0aW9uSFRNTCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLnR5cGUgIT09ICdjdXN0b20nKSB7XG4gICAgICAgICAgZW1pdCgncGFnaW5hdGlvblJlbmRlcicsIHN3aXBlci5wYWdpbmF0aW9uLiRlbFswXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gaW5pdCgpIHtcbiAgICAgICAgc3dpcGVyLnBhcmFtcy5wYWdpbmF0aW9uID0gY3JlYXRlRWxlbWVudElmTm90RGVmaW5lZChzd2lwZXIsIHN3aXBlci5vcmlnaW5hbFBhcmFtcy5wYWdpbmF0aW9uLCBzd2lwZXIucGFyYW1zLnBhZ2luYXRpb24sIHtcbiAgICAgICAgICBlbDogJ3N3aXBlci1wYWdpbmF0aW9uJ1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy5wYWdpbmF0aW9uO1xuICAgICAgICBpZiAoIXBhcmFtcy5lbCkgcmV0dXJuO1xuICAgICAgICBsZXQgJGVsID0gJChwYXJhbXMuZWwpO1xuICAgICAgICBpZiAoJGVsLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLnVuaXF1ZU5hdkVsZW1lbnRzICYmIHR5cGVvZiBwYXJhbXMuZWwgPT09ICdzdHJpbmcnICYmICRlbC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgJGVsID0gc3dpcGVyLiRlbC5maW5kKHBhcmFtcy5lbCk7IC8vIGNoZWNrIGlmIGl0IGJlbG9uZ3MgdG8gYW5vdGhlciBuZXN0ZWQgU3dpcGVyXG5cbiAgICAgICAgICBpZiAoJGVsLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICRlbCA9ICRlbC5maWx0ZXIoZWwgPT4ge1xuICAgICAgICAgICAgICBpZiAoJChlbCkucGFyZW50cygnLnN3aXBlcicpWzBdICE9PSBzd2lwZXIuZWwpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLnR5cGUgPT09ICdidWxsZXRzJyAmJiBwYXJhbXMuY2xpY2thYmxlKSB7XG4gICAgICAgICAgJGVsLmFkZENsYXNzKHBhcmFtcy5jbGlja2FibGVDbGFzcyk7XG4gICAgICAgIH1cblxuICAgICAgICAkZWwuYWRkQ2xhc3MocGFyYW1zLm1vZGlmaWVyQ2xhc3MgKyBwYXJhbXMudHlwZSk7XG4gICAgICAgICRlbC5hZGRDbGFzcyhzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyBwYXJhbXMuaG9yaXpvbnRhbENsYXNzIDogcGFyYW1zLnZlcnRpY2FsQ2xhc3MpO1xuXG4gICAgICAgIGlmIChwYXJhbXMudHlwZSA9PT0gJ2J1bGxldHMnICYmIHBhcmFtcy5keW5hbWljQnVsbGV0cykge1xuICAgICAgICAgICRlbC5hZGRDbGFzcyhgJHtwYXJhbXMubW9kaWZpZXJDbGFzc30ke3BhcmFtcy50eXBlfS1keW5hbWljYCk7XG4gICAgICAgICAgZHluYW1pY0J1bGxldEluZGV4ID0gMDtcblxuICAgICAgICAgIGlmIChwYXJhbXMuZHluYW1pY01haW5CdWxsZXRzIDwgMSkge1xuICAgICAgICAgICAgcGFyYW1zLmR5bmFtaWNNYWluQnVsbGV0cyA9IDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtcy50eXBlID09PSAncHJvZ3Jlc3NiYXInICYmIHBhcmFtcy5wcm9ncmVzc2Jhck9wcG9zaXRlKSB7XG4gICAgICAgICAgJGVsLmFkZENsYXNzKHBhcmFtcy5wcm9ncmVzc2Jhck9wcG9zaXRlQ2xhc3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmFtcy5jbGlja2FibGUpIHtcbiAgICAgICAgICAkZWwub24oJ2NsaWNrJywgY2xhc3Nlc1RvU2VsZWN0b3IocGFyYW1zLmJ1bGxldENsYXNzKSwgZnVuY3Rpb24gb25DbGljayhlKSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSAkKHRoaXMpLmluZGV4KCkgKiBzd2lwZXIucGFyYW1zLnNsaWRlc1Blckdyb3VwO1xuICAgICAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMubG9vcCkgaW5kZXggKz0gc3dpcGVyLmxvb3BlZFNsaWRlcztcbiAgICAgICAgICAgIHN3aXBlci5zbGlkZVRvKGluZGV4KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIE9iamVjdC5hc3NpZ24oc3dpcGVyLnBhZ2luYXRpb24sIHtcbiAgICAgICAgICAkZWwsXG4gICAgICAgICAgZWw6ICRlbFswXVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoIXN3aXBlci5lbmFibGVkKSB7XG4gICAgICAgICAgJGVsLmFkZENsYXNzKHBhcmFtcy5sb2NrQ2xhc3MpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHN3aXBlci5wYXJhbXMucGFnaW5hdGlvbjtcbiAgICAgICAgaWYgKGlzUGFnaW5hdGlvbkRpc2FibGVkKCkpIHJldHVybjtcbiAgICAgICAgY29uc3QgJGVsID0gc3dpcGVyLnBhZ2luYXRpb24uJGVsO1xuICAgICAgICAkZWwucmVtb3ZlQ2xhc3MocGFyYW1zLmhpZGRlbkNsYXNzKTtcbiAgICAgICAgJGVsLnJlbW92ZUNsYXNzKHBhcmFtcy5tb2RpZmllckNsYXNzICsgcGFyYW1zLnR5cGUpO1xuICAgICAgICAkZWwucmVtb3ZlQ2xhc3Moc3dpcGVyLmlzSG9yaXpvbnRhbCgpID8gcGFyYW1zLmhvcml6b250YWxDbGFzcyA6IHBhcmFtcy52ZXJ0aWNhbENsYXNzKTtcbiAgICAgICAgaWYgKHN3aXBlci5wYWdpbmF0aW9uLmJ1bGxldHMgJiYgc3dpcGVyLnBhZ2luYXRpb24uYnVsbGV0cy5yZW1vdmVDbGFzcykgc3dpcGVyLnBhZ2luYXRpb24uYnVsbGV0cy5yZW1vdmVDbGFzcyhwYXJhbXMuYnVsbGV0QWN0aXZlQ2xhc3MpO1xuXG4gICAgICAgIGlmIChwYXJhbXMuY2xpY2thYmxlKSB7XG4gICAgICAgICAgJGVsLm9mZignY2xpY2snLCBjbGFzc2VzVG9TZWxlY3RvcihwYXJhbXMuYnVsbGV0Q2xhc3MpKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBvbignaW5pdCcsICgpID0+IHtcbiAgICAgICAgaW5pdCgpO1xuICAgICAgICByZW5kZXIoKTtcbiAgICAgICAgdXBkYXRlKCk7XG4gICAgICB9KTtcbiAgICAgIG9uKCdhY3RpdmVJbmRleENoYW5nZScsICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMubG9vcCkge1xuICAgICAgICAgIHVwZGF0ZSgpO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBzd2lwZXIuc25hcEluZGV4ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIG9uKCdzbmFwSW5kZXhDaGFuZ2UnLCAoKSA9PiB7XG4gICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy5sb29wKSB7XG4gICAgICAgICAgdXBkYXRlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb24oJ3NsaWRlc0xlbmd0aENoYW5nZScsICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMubG9vcCkge1xuICAgICAgICAgIHJlbmRlcigpO1xuICAgICAgICAgIHVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIG9uKCdzbmFwR3JpZExlbmd0aENoYW5nZScsICgpID0+IHtcbiAgICAgICAgaWYgKCFzd2lwZXIucGFyYW1zLmxvb3ApIHtcbiAgICAgICAgICByZW5kZXIoKTtcbiAgICAgICAgICB1cGRhdGUoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBvbignZGVzdHJveScsICgpID0+IHtcbiAgICAgICAgZGVzdHJveSgpO1xuICAgICAgfSk7XG4gICAgICBvbignZW5hYmxlIGRpc2FibGUnLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAkZWxcbiAgICAgICAgfSA9IHN3aXBlci5wYWdpbmF0aW9uO1xuXG4gICAgICAgIGlmICgkZWwpIHtcbiAgICAgICAgICAkZWxbc3dpcGVyLmVuYWJsZWQgPyAncmVtb3ZlQ2xhc3MnIDogJ2FkZENsYXNzJ10oc3dpcGVyLnBhcmFtcy5wYWdpbmF0aW9uLmxvY2tDbGFzcyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb24oJ2xvY2sgdW5sb2NrJywgKCkgPT4ge1xuICAgICAgICB1cGRhdGUoKTtcbiAgICAgIH0pO1xuICAgICAgb24oJ2NsaWNrJywgKF9zLCBlKSA9PiB7XG4gICAgICAgIGNvbnN0IHRhcmdldEVsID0gZS50YXJnZXQ7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAkZWxcbiAgICAgICAgfSA9IHN3aXBlci5wYWdpbmF0aW9uO1xuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLnBhZ2luYXRpb24uZWwgJiYgc3dpcGVyLnBhcmFtcy5wYWdpbmF0aW9uLmhpZGVPbkNsaWNrICYmICRlbC5sZW5ndGggPiAwICYmICEkKHRhcmdldEVsKS5oYXNDbGFzcyhzd2lwZXIucGFyYW1zLnBhZ2luYXRpb24uYnVsbGV0Q2xhc3MpKSB7XG4gICAgICAgICAgaWYgKHN3aXBlci5uYXZpZ2F0aW9uICYmIChzd2lwZXIubmF2aWdhdGlvbi5uZXh0RWwgJiYgdGFyZ2V0RWwgPT09IHN3aXBlci5uYXZpZ2F0aW9uLm5leHRFbCB8fCBzd2lwZXIubmF2aWdhdGlvbi5wcmV2RWwgJiYgdGFyZ2V0RWwgPT09IHN3aXBlci5uYXZpZ2F0aW9uLnByZXZFbCkpIHJldHVybjtcbiAgICAgICAgICBjb25zdCBpc0hpZGRlbiA9ICRlbC5oYXNDbGFzcyhzd2lwZXIucGFyYW1zLnBhZ2luYXRpb24uaGlkZGVuQ2xhc3MpO1xuXG4gICAgICAgICAgaWYgKGlzSGlkZGVuID09PSB0cnVlKSB7XG4gICAgICAgICAgICBlbWl0KCdwYWdpbmF0aW9uU2hvdycpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbWl0KCdwYWdpbmF0aW9uSGlkZScpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICRlbC50b2dnbGVDbGFzcyhzd2lwZXIucGFyYW1zLnBhZ2luYXRpb24uaGlkZGVuQ2xhc3MpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIE9iamVjdC5hc3NpZ24oc3dpcGVyLnBhZ2luYXRpb24sIHtcbiAgICAgICAgcmVuZGVyLFxuICAgICAgICB1cGRhdGUsXG4gICAgICAgIGluaXQsXG4gICAgICAgIGRlc3Ryb3lcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIFNjcm9sbGJhcihfcmVmKSB7XG4gICAgICBsZXQge1xuICAgICAgICBzd2lwZXIsXG4gICAgICAgIGV4dGVuZFBhcmFtcyxcbiAgICAgICAgb24sXG4gICAgICAgIGVtaXRcbiAgICAgIH0gPSBfcmVmO1xuICAgICAgY29uc3QgZG9jdW1lbnQgPSBnZXREb2N1bWVudCgpO1xuICAgICAgbGV0IGlzVG91Y2hlZCA9IGZhbHNlO1xuICAgICAgbGV0IHRpbWVvdXQgPSBudWxsO1xuICAgICAgbGV0IGRyYWdUaW1lb3V0ID0gbnVsbDtcbiAgICAgIGxldCBkcmFnU3RhcnRQb3M7XG4gICAgICBsZXQgZHJhZ1NpemU7XG4gICAgICBsZXQgdHJhY2tTaXplO1xuICAgICAgbGV0IGRpdmlkZXI7XG4gICAgICBleHRlbmRQYXJhbXMoe1xuICAgICAgICBzY3JvbGxiYXI6IHtcbiAgICAgICAgICBlbDogbnVsbCxcbiAgICAgICAgICBkcmFnU2l6ZTogJ2F1dG8nLFxuICAgICAgICAgIGhpZGU6IGZhbHNlLFxuICAgICAgICAgIGRyYWdnYWJsZTogZmFsc2UsXG4gICAgICAgICAgc25hcE9uUmVsZWFzZTogdHJ1ZSxcbiAgICAgICAgICBsb2NrQ2xhc3M6ICdzd2lwZXItc2Nyb2xsYmFyLWxvY2snLFxuICAgICAgICAgIGRyYWdDbGFzczogJ3N3aXBlci1zY3JvbGxiYXItZHJhZydcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzd2lwZXIuc2Nyb2xsYmFyID0ge1xuICAgICAgICBlbDogbnVsbCxcbiAgICAgICAgZHJhZ0VsOiBudWxsLFxuICAgICAgICAkZWw6IG51bGwsXG4gICAgICAgICRkcmFnRWw6IG51bGxcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIHNldFRyYW5zbGF0ZSgpIHtcbiAgICAgICAgaWYgKCFzd2lwZXIucGFyYW1zLnNjcm9sbGJhci5lbCB8fCAhc3dpcGVyLnNjcm9sbGJhci5lbCkgcmV0dXJuO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgc2Nyb2xsYmFyLFxuICAgICAgICAgIHJ0bFRyYW5zbGF0ZTogcnRsLFxuICAgICAgICAgIHByb2dyZXNzXG4gICAgICAgIH0gPSBzd2lwZXI7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAkZHJhZ0VsLFxuICAgICAgICAgICRlbFxuICAgICAgICB9ID0gc2Nyb2xsYmFyO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zLnNjcm9sbGJhcjtcbiAgICAgICAgbGV0IG5ld1NpemUgPSBkcmFnU2l6ZTtcbiAgICAgICAgbGV0IG5ld1BvcyA9ICh0cmFja1NpemUgLSBkcmFnU2l6ZSkgKiBwcm9ncmVzcztcblxuICAgICAgICBpZiAocnRsKSB7XG4gICAgICAgICAgbmV3UG9zID0gLW5ld1BvcztcblxuICAgICAgICAgIGlmIChuZXdQb3MgPiAwKSB7XG4gICAgICAgICAgICBuZXdTaXplID0gZHJhZ1NpemUgLSBuZXdQb3M7XG4gICAgICAgICAgICBuZXdQb3MgPSAwO1xuICAgICAgICAgIH0gZWxzZSBpZiAoLW5ld1BvcyArIGRyYWdTaXplID4gdHJhY2tTaXplKSB7XG4gICAgICAgICAgICBuZXdTaXplID0gdHJhY2tTaXplICsgbmV3UG9zO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChuZXdQb3MgPCAwKSB7XG4gICAgICAgICAgbmV3U2l6ZSA9IGRyYWdTaXplICsgbmV3UG9zO1xuICAgICAgICAgIG5ld1BvcyA9IDA7XG4gICAgICAgIH0gZWxzZSBpZiAobmV3UG9zICsgZHJhZ1NpemUgPiB0cmFja1NpemUpIHtcbiAgICAgICAgICBuZXdTaXplID0gdHJhY2tTaXplIC0gbmV3UG9zO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN3aXBlci5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgICRkcmFnRWwudHJhbnNmb3JtKGB0cmFuc2xhdGUzZCgke25ld1Bvc31weCwgMCwgMClgKTtcbiAgICAgICAgICAkZHJhZ0VsWzBdLnN0eWxlLndpZHRoID0gYCR7bmV3U2l6ZX1weGA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgJGRyYWdFbC50cmFuc2Zvcm0oYHRyYW5zbGF0ZTNkKDBweCwgJHtuZXdQb3N9cHgsIDApYCk7XG4gICAgICAgICAgJGRyYWdFbFswXS5zdHlsZS5oZWlnaHQgPSBgJHtuZXdTaXplfXB4YDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJhbXMuaGlkZSkge1xuICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgICAkZWxbMF0uc3R5bGUub3BhY2l0eSA9IDE7XG4gICAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgJGVsWzBdLnN0eWxlLm9wYWNpdHkgPSAwO1xuICAgICAgICAgICAgJGVsLnRyYW5zaXRpb24oNDAwKTtcbiAgICAgICAgICB9LCAxMDAwKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBzZXRUcmFuc2l0aW9uKGR1cmF0aW9uKSB7XG4gICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy5zY3JvbGxiYXIuZWwgfHwgIXN3aXBlci5zY3JvbGxiYXIuZWwpIHJldHVybjtcbiAgICAgICAgc3dpcGVyLnNjcm9sbGJhci4kZHJhZ0VsLnRyYW5zaXRpb24oZHVyYXRpb24pO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiB1cGRhdGVTaXplKCkge1xuICAgICAgICBpZiAoIXN3aXBlci5wYXJhbXMuc2Nyb2xsYmFyLmVsIHx8ICFzd2lwZXIuc2Nyb2xsYmFyLmVsKSByZXR1cm47XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBzY3JvbGxiYXJcbiAgICAgICAgfSA9IHN3aXBlcjtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgICRkcmFnRWwsXG4gICAgICAgICAgJGVsXG4gICAgICAgIH0gPSBzY3JvbGxiYXI7XG4gICAgICAgICRkcmFnRWxbMF0uc3R5bGUud2lkdGggPSAnJztcbiAgICAgICAgJGRyYWdFbFswXS5zdHlsZS5oZWlnaHQgPSAnJztcbiAgICAgICAgdHJhY2tTaXplID0gc3dpcGVyLmlzSG9yaXpvbnRhbCgpID8gJGVsWzBdLm9mZnNldFdpZHRoIDogJGVsWzBdLm9mZnNldEhlaWdodDtcbiAgICAgICAgZGl2aWRlciA9IHN3aXBlci5zaXplIC8gKHN3aXBlci52aXJ0dWFsU2l6ZSArIHN3aXBlci5wYXJhbXMuc2xpZGVzT2Zmc2V0QmVmb3JlIC0gKHN3aXBlci5wYXJhbXMuY2VudGVyZWRTbGlkZXMgPyBzd2lwZXIuc25hcEdyaWRbMF0gOiAwKSk7XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuc2Nyb2xsYmFyLmRyYWdTaXplID09PSAnYXV0bycpIHtcbiAgICAgICAgICBkcmFnU2l6ZSA9IHRyYWNrU2l6ZSAqIGRpdmlkZXI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZHJhZ1NpemUgPSBwYXJzZUludChzd2lwZXIucGFyYW1zLnNjcm9sbGJhci5kcmFnU2l6ZSwgMTApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN3aXBlci5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgICRkcmFnRWxbMF0uc3R5bGUud2lkdGggPSBgJHtkcmFnU2l6ZX1weGA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgJGRyYWdFbFswXS5zdHlsZS5oZWlnaHQgPSBgJHtkcmFnU2l6ZX1weGA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZGl2aWRlciA+PSAxKSB7XG4gICAgICAgICAgJGVsWzBdLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgJGVsWzBdLnN0eWxlLmRpc3BsYXkgPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLnNjcm9sbGJhci5oaWRlKSB7XG4gICAgICAgICAgJGVsWzBdLnN0eWxlLm9wYWNpdHkgPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMud2F0Y2hPdmVyZmxvdyAmJiBzd2lwZXIuZW5hYmxlZCkge1xuICAgICAgICAgIHNjcm9sbGJhci4kZWxbc3dpcGVyLmlzTG9ja2VkID8gJ2FkZENsYXNzJyA6ICdyZW1vdmVDbGFzcyddKHN3aXBlci5wYXJhbXMuc2Nyb2xsYmFyLmxvY2tDbGFzcyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZ2V0UG9pbnRlclBvc2l0aW9uKGUpIHtcbiAgICAgICAgaWYgKHN3aXBlci5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgIHJldHVybiBlLnR5cGUgPT09ICd0b3VjaHN0YXJ0JyB8fCBlLnR5cGUgPT09ICd0b3VjaG1vdmUnID8gZS50YXJnZXRUb3VjaGVzWzBdLmNsaWVudFggOiBlLmNsaWVudFg7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZS50eXBlID09PSAndG91Y2hzdGFydCcgfHwgZS50eXBlID09PSAndG91Y2htb3ZlJyA/IGUudGFyZ2V0VG91Y2hlc1swXS5jbGllbnRZIDogZS5jbGllbnRZO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBzZXREcmFnUG9zaXRpb24oZSkge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgc2Nyb2xsYmFyLFxuICAgICAgICAgIHJ0bFRyYW5zbGF0ZTogcnRsXG4gICAgICAgIH0gPSBzd2lwZXI7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAkZWxcbiAgICAgICAgfSA9IHNjcm9sbGJhcjtcbiAgICAgICAgbGV0IHBvc2l0aW9uUmF0aW87XG4gICAgICAgIHBvc2l0aW9uUmF0aW8gPSAoZ2V0UG9pbnRlclBvc2l0aW9uKGUpIC0gJGVsLm9mZnNldCgpW3N3aXBlci5pc0hvcml6b250YWwoKSA/ICdsZWZ0JyA6ICd0b3AnXSAtIChkcmFnU3RhcnRQb3MgIT09IG51bGwgPyBkcmFnU3RhcnRQb3MgOiBkcmFnU2l6ZSAvIDIpKSAvICh0cmFja1NpemUgLSBkcmFnU2l6ZSk7XG4gICAgICAgIHBvc2l0aW9uUmF0aW8gPSBNYXRoLm1heChNYXRoLm1pbihwb3NpdGlvblJhdGlvLCAxKSwgMCk7XG5cbiAgICAgICAgaWYgKHJ0bCkge1xuICAgICAgICAgIHBvc2l0aW9uUmF0aW8gPSAxIC0gcG9zaXRpb25SYXRpbztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBvc2l0aW9uID0gc3dpcGVyLm1pblRyYW5zbGF0ZSgpICsgKHN3aXBlci5tYXhUcmFuc2xhdGUoKSAtIHN3aXBlci5taW5UcmFuc2xhdGUoKSkgKiBwb3NpdGlvblJhdGlvO1xuICAgICAgICBzd2lwZXIudXBkYXRlUHJvZ3Jlc3MocG9zaXRpb24pO1xuICAgICAgICBzd2lwZXIuc2V0VHJhbnNsYXRlKHBvc2l0aW9uKTtcbiAgICAgICAgc3dpcGVyLnVwZGF0ZUFjdGl2ZUluZGV4KCk7XG4gICAgICAgIHN3aXBlci51cGRhdGVTbGlkZXNDbGFzc2VzKCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIG9uRHJhZ1N0YXJ0KGUpIHtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy5zY3JvbGxiYXI7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBzY3JvbGxiYXIsXG4gICAgICAgICAgJHdyYXBwZXJFbFxuICAgICAgICB9ID0gc3dpcGVyO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgJGVsLFxuICAgICAgICAgICRkcmFnRWxcbiAgICAgICAgfSA9IHNjcm9sbGJhcjtcbiAgICAgICAgaXNUb3VjaGVkID0gdHJ1ZTtcbiAgICAgICAgZHJhZ1N0YXJ0UG9zID0gZS50YXJnZXQgPT09ICRkcmFnRWxbMF0gfHwgZS50YXJnZXQgPT09ICRkcmFnRWwgPyBnZXRQb2ludGVyUG9zaXRpb24oZSkgLSBlLnRhcmdldC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVtzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyAnbGVmdCcgOiAndG9wJ10gOiBudWxsO1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICR3cmFwcGVyRWwudHJhbnNpdGlvbigxMDApO1xuICAgICAgICAkZHJhZ0VsLnRyYW5zaXRpb24oMTAwKTtcbiAgICAgICAgc2V0RHJhZ1Bvc2l0aW9uKGUpO1xuICAgICAgICBjbGVhclRpbWVvdXQoZHJhZ1RpbWVvdXQpO1xuICAgICAgICAkZWwudHJhbnNpdGlvbigwKTtcblxuICAgICAgICBpZiAocGFyYW1zLmhpZGUpIHtcbiAgICAgICAgICAkZWwuY3NzKCdvcGFjaXR5JywgMSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5jc3NNb2RlKSB7XG4gICAgICAgICAgc3dpcGVyLiR3cmFwcGVyRWwuY3NzKCdzY3JvbGwtc25hcC10eXBlJywgJ25vbmUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVtaXQoJ3Njcm9sbGJhckRyYWdTdGFydCcsIGUpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBvbkRyYWdNb3ZlKGUpIHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHNjcm9sbGJhcixcbiAgICAgICAgICAkd3JhcHBlckVsXG4gICAgICAgIH0gPSBzd2lwZXI7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAkZWwsXG4gICAgICAgICAgJGRyYWdFbFxuICAgICAgICB9ID0gc2Nyb2xsYmFyO1xuICAgICAgICBpZiAoIWlzVG91Y2hlZCkgcmV0dXJuO1xuICAgICAgICBpZiAoZS5wcmV2ZW50RGVmYXVsdCkgZS5wcmV2ZW50RGVmYXVsdCgpO2Vsc2UgZS5yZXR1cm5WYWx1ZSA9IGZhbHNlO1xuICAgICAgICBzZXREcmFnUG9zaXRpb24oZSk7XG4gICAgICAgICR3cmFwcGVyRWwudHJhbnNpdGlvbigwKTtcbiAgICAgICAgJGVsLnRyYW5zaXRpb24oMCk7XG4gICAgICAgICRkcmFnRWwudHJhbnNpdGlvbigwKTtcbiAgICAgICAgZW1pdCgnc2Nyb2xsYmFyRHJhZ01vdmUnLCBlKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gb25EcmFnRW5kKGUpIHtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy5zY3JvbGxiYXI7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBzY3JvbGxiYXIsXG4gICAgICAgICAgJHdyYXBwZXJFbFxuICAgICAgICB9ID0gc3dpcGVyO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgJGVsXG4gICAgICAgIH0gPSBzY3JvbGxiYXI7XG4gICAgICAgIGlmICghaXNUb3VjaGVkKSByZXR1cm47XG4gICAgICAgIGlzVG91Y2hlZCA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmNzc01vZGUpIHtcbiAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbC5jc3MoJ3Njcm9sbC1zbmFwLXR5cGUnLCAnJyk7XG4gICAgICAgICAgJHdyYXBwZXJFbC50cmFuc2l0aW9uKCcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJhbXMuaGlkZSkge1xuICAgICAgICAgIGNsZWFyVGltZW91dChkcmFnVGltZW91dCk7XG4gICAgICAgICAgZHJhZ1RpbWVvdXQgPSBuZXh0VGljaygoKSA9PiB7XG4gICAgICAgICAgICAkZWwuY3NzKCdvcGFjaXR5JywgMCk7XG4gICAgICAgICAgICAkZWwudHJhbnNpdGlvbig0MDApO1xuICAgICAgICAgIH0sIDEwMDApO1xuICAgICAgICB9XG5cbiAgICAgICAgZW1pdCgnc2Nyb2xsYmFyRHJhZ0VuZCcsIGUpO1xuXG4gICAgICAgIGlmIChwYXJhbXMuc25hcE9uUmVsZWFzZSkge1xuICAgICAgICAgIHN3aXBlci5zbGlkZVRvQ2xvc2VzdCgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGV2ZW50cyhtZXRob2QpIHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHNjcm9sbGJhcixcbiAgICAgICAgICB0b3VjaEV2ZW50c1RvdWNoLFxuICAgICAgICAgIHRvdWNoRXZlbnRzRGVza3RvcCxcbiAgICAgICAgICBwYXJhbXMsXG4gICAgICAgICAgc3VwcG9ydFxuICAgICAgICB9ID0gc3dpcGVyO1xuICAgICAgICBjb25zdCAkZWwgPSBzY3JvbGxiYXIuJGVsO1xuICAgICAgICBjb25zdCB0YXJnZXQgPSAkZWxbMF07XG4gICAgICAgIGNvbnN0IGFjdGl2ZUxpc3RlbmVyID0gc3VwcG9ydC5wYXNzaXZlTGlzdGVuZXIgJiYgcGFyYW1zLnBhc3NpdmVMaXN0ZW5lcnMgPyB7XG4gICAgICAgICAgcGFzc2l2ZTogZmFsc2UsXG4gICAgICAgICAgY2FwdHVyZTogZmFsc2VcbiAgICAgICAgfSA6IGZhbHNlO1xuICAgICAgICBjb25zdCBwYXNzaXZlTGlzdGVuZXIgPSBzdXBwb3J0LnBhc3NpdmVMaXN0ZW5lciAmJiBwYXJhbXMucGFzc2l2ZUxpc3RlbmVycyA/IHtcbiAgICAgICAgICBwYXNzaXZlOiB0cnVlLFxuICAgICAgICAgIGNhcHR1cmU6IGZhbHNlXG4gICAgICAgIH0gOiBmYWxzZTtcbiAgICAgICAgaWYgKCF0YXJnZXQpIHJldHVybjtcbiAgICAgICAgY29uc3QgZXZlbnRNZXRob2QgPSBtZXRob2QgPT09ICdvbicgPyAnYWRkRXZlbnRMaXN0ZW5lcicgOiAncmVtb3ZlRXZlbnRMaXN0ZW5lcic7XG5cbiAgICAgICAgaWYgKCFzdXBwb3J0LnRvdWNoKSB7XG4gICAgICAgICAgdGFyZ2V0W2V2ZW50TWV0aG9kXSh0b3VjaEV2ZW50c0Rlc2t0b3Auc3RhcnQsIG9uRHJhZ1N0YXJ0LCBhY3RpdmVMaXN0ZW5lcik7XG4gICAgICAgICAgZG9jdW1lbnRbZXZlbnRNZXRob2RdKHRvdWNoRXZlbnRzRGVza3RvcC5tb3ZlLCBvbkRyYWdNb3ZlLCBhY3RpdmVMaXN0ZW5lcik7XG4gICAgICAgICAgZG9jdW1lbnRbZXZlbnRNZXRob2RdKHRvdWNoRXZlbnRzRGVza3RvcC5lbmQsIG9uRHJhZ0VuZCwgcGFzc2l2ZUxpc3RlbmVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0YXJnZXRbZXZlbnRNZXRob2RdKHRvdWNoRXZlbnRzVG91Y2guc3RhcnQsIG9uRHJhZ1N0YXJ0LCBhY3RpdmVMaXN0ZW5lcik7XG4gICAgICAgICAgdGFyZ2V0W2V2ZW50TWV0aG9kXSh0b3VjaEV2ZW50c1RvdWNoLm1vdmUsIG9uRHJhZ01vdmUsIGFjdGl2ZUxpc3RlbmVyKTtcbiAgICAgICAgICB0YXJnZXRbZXZlbnRNZXRob2RdKHRvdWNoRXZlbnRzVG91Y2guZW5kLCBvbkRyYWdFbmQsIHBhc3NpdmVMaXN0ZW5lcik7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZW5hYmxlRHJhZ2dhYmxlKCkge1xuICAgICAgICBpZiAoIXN3aXBlci5wYXJhbXMuc2Nyb2xsYmFyLmVsKSByZXR1cm47XG4gICAgICAgIGV2ZW50cygnb24nKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZGlzYWJsZURyYWdnYWJsZSgpIHtcbiAgICAgICAgaWYgKCFzd2lwZXIucGFyYW1zLnNjcm9sbGJhci5lbCkgcmV0dXJuO1xuICAgICAgICBldmVudHMoJ29mZicpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBpbml0KCkge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgc2Nyb2xsYmFyLFxuICAgICAgICAgICRlbDogJHN3aXBlckVsXG4gICAgICAgIH0gPSBzd2lwZXI7XG4gICAgICAgIHN3aXBlci5wYXJhbXMuc2Nyb2xsYmFyID0gY3JlYXRlRWxlbWVudElmTm90RGVmaW5lZChzd2lwZXIsIHN3aXBlci5vcmlnaW5hbFBhcmFtcy5zY3JvbGxiYXIsIHN3aXBlci5wYXJhbXMuc2Nyb2xsYmFyLCB7XG4gICAgICAgICAgZWw6ICdzd2lwZXItc2Nyb2xsYmFyJ1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy5zY3JvbGxiYXI7XG4gICAgICAgIGlmICghcGFyYW1zLmVsKSByZXR1cm47XG4gICAgICAgIGxldCAkZWwgPSAkKHBhcmFtcy5lbCk7XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMudW5pcXVlTmF2RWxlbWVudHMgJiYgdHlwZW9mIHBhcmFtcy5lbCA9PT0gJ3N0cmluZycgJiYgJGVsLmxlbmd0aCA+IDEgJiYgJHN3aXBlckVsLmZpbmQocGFyYW1zLmVsKS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAkZWwgPSAkc3dpcGVyRWwuZmluZChwYXJhbXMuZWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0ICRkcmFnRWwgPSAkZWwuZmluZChgLiR7c3dpcGVyLnBhcmFtcy5zY3JvbGxiYXIuZHJhZ0NsYXNzfWApO1xuXG4gICAgICAgIGlmICgkZHJhZ0VsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICRkcmFnRWwgPSAkKGA8ZGl2IGNsYXNzPVwiJHtzd2lwZXIucGFyYW1zLnNjcm9sbGJhci5kcmFnQ2xhc3N9XCI+PC9kaXY+YCk7XG4gICAgICAgICAgJGVsLmFwcGVuZCgkZHJhZ0VsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIE9iamVjdC5hc3NpZ24oc2Nyb2xsYmFyLCB7XG4gICAgICAgICAgJGVsLFxuICAgICAgICAgIGVsOiAkZWxbMF0sXG4gICAgICAgICAgJGRyYWdFbCxcbiAgICAgICAgICBkcmFnRWw6ICRkcmFnRWxbMF1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHBhcmFtcy5kcmFnZ2FibGUpIHtcbiAgICAgICAgICBlbmFibGVEcmFnZ2FibGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgkZWwpIHtcbiAgICAgICAgICAkZWxbc3dpcGVyLmVuYWJsZWQgPyAncmVtb3ZlQ2xhc3MnIDogJ2FkZENsYXNzJ10oc3dpcGVyLnBhcmFtcy5zY3JvbGxiYXIubG9ja0NsYXNzKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICBkaXNhYmxlRHJhZ2dhYmxlKCk7XG4gICAgICB9XG5cbiAgICAgIG9uKCdpbml0JywgKCkgPT4ge1xuICAgICAgICBpbml0KCk7XG4gICAgICAgIHVwZGF0ZVNpemUoKTtcbiAgICAgICAgc2V0VHJhbnNsYXRlKCk7XG4gICAgICB9KTtcbiAgICAgIG9uKCd1cGRhdGUgcmVzaXplIG9ic2VydmVyVXBkYXRlIGxvY2sgdW5sb2NrJywgKCkgPT4ge1xuICAgICAgICB1cGRhdGVTaXplKCk7XG4gICAgICB9KTtcbiAgICAgIG9uKCdzZXRUcmFuc2xhdGUnLCAoKSA9PiB7XG4gICAgICAgIHNldFRyYW5zbGF0ZSgpO1xuICAgICAgfSk7XG4gICAgICBvbignc2V0VHJhbnNpdGlvbicsIChfcywgZHVyYXRpb24pID0+IHtcbiAgICAgICAgc2V0VHJhbnNpdGlvbihkdXJhdGlvbik7XG4gICAgICB9KTtcbiAgICAgIG9uKCdlbmFibGUgZGlzYWJsZScsICgpID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgICRlbFxuICAgICAgICB9ID0gc3dpcGVyLnNjcm9sbGJhcjtcblxuICAgICAgICBpZiAoJGVsKSB7XG4gICAgICAgICAgJGVsW3N3aXBlci5lbmFibGVkID8gJ3JlbW92ZUNsYXNzJyA6ICdhZGRDbGFzcyddKHN3aXBlci5wYXJhbXMuc2Nyb2xsYmFyLmxvY2tDbGFzcyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb24oJ2Rlc3Ryb3knLCAoKSA9PiB7XG4gICAgICAgIGRlc3Ryb3koKTtcbiAgICAgIH0pO1xuICAgICAgT2JqZWN0LmFzc2lnbihzd2lwZXIuc2Nyb2xsYmFyLCB7XG4gICAgICAgIHVwZGF0ZVNpemUsXG4gICAgICAgIHNldFRyYW5zbGF0ZSxcbiAgICAgICAgaW5pdCxcbiAgICAgICAgZGVzdHJveVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gUGFyYWxsYXgoX3JlZikge1xuICAgICAgbGV0IHtcbiAgICAgICAgc3dpcGVyLFxuICAgICAgICBleHRlbmRQYXJhbXMsXG4gICAgICAgIG9uXG4gICAgICB9ID0gX3JlZjtcbiAgICAgIGV4dGVuZFBhcmFtcyh7XG4gICAgICAgIHBhcmFsbGF4OiB7XG4gICAgICAgICAgZW5hYmxlZDogZmFsc2VcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHNldFRyYW5zZm9ybSA9IChlbCwgcHJvZ3Jlc3MpID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHJ0bFxuICAgICAgICB9ID0gc3dpcGVyO1xuICAgICAgICBjb25zdCAkZWwgPSAkKGVsKTtcbiAgICAgICAgY29uc3QgcnRsRmFjdG9yID0gcnRsID8gLTEgOiAxO1xuICAgICAgICBjb25zdCBwID0gJGVsLmF0dHIoJ2RhdGEtc3dpcGVyLXBhcmFsbGF4JykgfHwgJzAnO1xuICAgICAgICBsZXQgeCA9ICRlbC5hdHRyKCdkYXRhLXN3aXBlci1wYXJhbGxheC14Jyk7XG4gICAgICAgIGxldCB5ID0gJGVsLmF0dHIoJ2RhdGEtc3dpcGVyLXBhcmFsbGF4LXknKTtcbiAgICAgICAgY29uc3Qgc2NhbGUgPSAkZWwuYXR0cignZGF0YS1zd2lwZXItcGFyYWxsYXgtc2NhbGUnKTtcbiAgICAgICAgY29uc3Qgb3BhY2l0eSA9ICRlbC5hdHRyKCdkYXRhLXN3aXBlci1wYXJhbGxheC1vcGFjaXR5Jyk7XG5cbiAgICAgICAgaWYgKHggfHwgeSkge1xuICAgICAgICAgIHggPSB4IHx8ICcwJztcbiAgICAgICAgICB5ID0geSB8fCAnMCc7XG4gICAgICAgIH0gZWxzZSBpZiAoc3dpcGVyLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgeCA9IHA7XG4gICAgICAgICAgeSA9ICcwJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB5ID0gcDtcbiAgICAgICAgICB4ID0gJzAnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHguaW5kZXhPZignJScpID49IDApIHtcbiAgICAgICAgICB4ID0gYCR7cGFyc2VJbnQoeCwgMTApICogcHJvZ3Jlc3MgKiBydGxGYWN0b3J9JWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgeCA9IGAke3ggKiBwcm9ncmVzcyAqIHJ0bEZhY3Rvcn1weGA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoeS5pbmRleE9mKCclJykgPj0gMCkge1xuICAgICAgICAgIHkgPSBgJHtwYXJzZUludCh5LCAxMCkgKiBwcm9ncmVzc30lYDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB5ID0gYCR7eSAqIHByb2dyZXNzfXB4YDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2Ygb3BhY2l0eSAhPT0gJ3VuZGVmaW5lZCcgJiYgb3BhY2l0eSAhPT0gbnVsbCkge1xuICAgICAgICAgIGNvbnN0IGN1cnJlbnRPcGFjaXR5ID0gb3BhY2l0eSAtIChvcGFjaXR5IC0gMSkgKiAoMSAtIE1hdGguYWJzKHByb2dyZXNzKSk7XG4gICAgICAgICAgJGVsWzBdLnN0eWxlLm9wYWNpdHkgPSBjdXJyZW50T3BhY2l0eTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2Ygc2NhbGUgPT09ICd1bmRlZmluZWQnIHx8IHNjYWxlID09PSBudWxsKSB7XG4gICAgICAgICAgJGVsLnRyYW5zZm9ybShgdHJhbnNsYXRlM2QoJHt4fSwgJHt5fSwgMHB4KWApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IGN1cnJlbnRTY2FsZSA9IHNjYWxlIC0gKHNjYWxlIC0gMSkgKiAoMSAtIE1hdGguYWJzKHByb2dyZXNzKSk7XG4gICAgICAgICAgJGVsLnRyYW5zZm9ybShgdHJhbnNsYXRlM2QoJHt4fSwgJHt5fSwgMHB4KSBzY2FsZSgke2N1cnJlbnRTY2FsZX0pYCk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHNldFRyYW5zbGF0ZSA9ICgpID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgICRlbCxcbiAgICAgICAgICBzbGlkZXMsXG4gICAgICAgICAgcHJvZ3Jlc3MsXG4gICAgICAgICAgc25hcEdyaWRcbiAgICAgICAgfSA9IHN3aXBlcjtcbiAgICAgICAgJGVsLmNoaWxkcmVuKCdbZGF0YS1zd2lwZXItcGFyYWxsYXhdLCBbZGF0YS1zd2lwZXItcGFyYWxsYXgteF0sIFtkYXRhLXN3aXBlci1wYXJhbGxheC15XSwgW2RhdGEtc3dpcGVyLXBhcmFsbGF4LW9wYWNpdHldLCBbZGF0YS1zd2lwZXItcGFyYWxsYXgtc2NhbGVdJykuZWFjaChlbCA9PiB7XG4gICAgICAgICAgc2V0VHJhbnNmb3JtKGVsLCBwcm9ncmVzcyk7XG4gICAgICAgIH0pO1xuICAgICAgICBzbGlkZXMuZWFjaCgoc2xpZGVFbCwgc2xpZGVJbmRleCkgPT4ge1xuICAgICAgICAgIGxldCBzbGlkZVByb2dyZXNzID0gc2xpZGVFbC5wcm9ncmVzcztcblxuICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLnNsaWRlc1Blckdyb3VwID4gMSAmJiBzd2lwZXIucGFyYW1zLnNsaWRlc1BlclZpZXcgIT09ICdhdXRvJykge1xuICAgICAgICAgICAgc2xpZGVQcm9ncmVzcyArPSBNYXRoLmNlaWwoc2xpZGVJbmRleCAvIDIpIC0gcHJvZ3Jlc3MgKiAoc25hcEdyaWQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc2xpZGVQcm9ncmVzcyA9IE1hdGgubWluKE1hdGgubWF4KHNsaWRlUHJvZ3Jlc3MsIC0xKSwgMSk7XG4gICAgICAgICAgJChzbGlkZUVsKS5maW5kKCdbZGF0YS1zd2lwZXItcGFyYWxsYXhdLCBbZGF0YS1zd2lwZXItcGFyYWxsYXgteF0sIFtkYXRhLXN3aXBlci1wYXJhbGxheC15XSwgW2RhdGEtc3dpcGVyLXBhcmFsbGF4LW9wYWNpdHldLCBbZGF0YS1zd2lwZXItcGFyYWxsYXgtc2NhbGVdJykuZWFjaChlbCA9PiB7XG4gICAgICAgICAgICBzZXRUcmFuc2Zvcm0oZWwsIHNsaWRlUHJvZ3Jlc3MpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHNldFRyYW5zaXRpb24gPSBmdW5jdGlvbiAoZHVyYXRpb24pIHtcbiAgICAgICAgaWYgKGR1cmF0aW9uID09PSB2b2lkIDApIHtcbiAgICAgICAgICBkdXJhdGlvbiA9IHN3aXBlci5wYXJhbXMuc3BlZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgJGVsXG4gICAgICAgIH0gPSBzd2lwZXI7XG4gICAgICAgICRlbC5maW5kKCdbZGF0YS1zd2lwZXItcGFyYWxsYXhdLCBbZGF0YS1zd2lwZXItcGFyYWxsYXgteF0sIFtkYXRhLXN3aXBlci1wYXJhbGxheC15XSwgW2RhdGEtc3dpcGVyLXBhcmFsbGF4LW9wYWNpdHldLCBbZGF0YS1zd2lwZXItcGFyYWxsYXgtc2NhbGVdJykuZWFjaChwYXJhbGxheEVsID0+IHtcbiAgICAgICAgICBjb25zdCAkcGFyYWxsYXhFbCA9ICQocGFyYWxsYXhFbCk7XG4gICAgICAgICAgbGV0IHBhcmFsbGF4RHVyYXRpb24gPSBwYXJzZUludCgkcGFyYWxsYXhFbC5hdHRyKCdkYXRhLXN3aXBlci1wYXJhbGxheC1kdXJhdGlvbicpLCAxMCkgfHwgZHVyYXRpb247XG4gICAgICAgICAgaWYgKGR1cmF0aW9uID09PSAwKSBwYXJhbGxheER1cmF0aW9uID0gMDtcbiAgICAgICAgICAkcGFyYWxsYXhFbC50cmFuc2l0aW9uKHBhcmFsbGF4RHVyYXRpb24pO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIG9uKCdiZWZvcmVJbml0JywgKCkgPT4ge1xuICAgICAgICBpZiAoIXN3aXBlci5wYXJhbXMucGFyYWxsYXguZW5hYmxlZCkgcmV0dXJuO1xuICAgICAgICBzd2lwZXIucGFyYW1zLndhdGNoU2xpZGVzUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICBzd2lwZXIub3JpZ2luYWxQYXJhbXMud2F0Y2hTbGlkZXNQcm9ncmVzcyA9IHRydWU7XG4gICAgICB9KTtcbiAgICAgIG9uKCdpbml0JywgKCkgPT4ge1xuICAgICAgICBpZiAoIXN3aXBlci5wYXJhbXMucGFyYWxsYXguZW5hYmxlZCkgcmV0dXJuO1xuICAgICAgICBzZXRUcmFuc2xhdGUoKTtcbiAgICAgIH0pO1xuICAgICAgb24oJ3NldFRyYW5zbGF0ZScsICgpID0+IHtcbiAgICAgICAgaWYgKCFzd2lwZXIucGFyYW1zLnBhcmFsbGF4LmVuYWJsZWQpIHJldHVybjtcbiAgICAgICAgc2V0VHJhbnNsYXRlKCk7XG4gICAgICB9KTtcbiAgICAgIG9uKCdzZXRUcmFuc2l0aW9uJywgKF9zd2lwZXIsIGR1cmF0aW9uKSA9PiB7XG4gICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy5wYXJhbGxheC5lbmFibGVkKSByZXR1cm47XG4gICAgICAgIHNldFRyYW5zaXRpb24oZHVyYXRpb24pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gWm9vbShfcmVmKSB7XG4gICAgICBsZXQge1xuICAgICAgICBzd2lwZXIsXG4gICAgICAgIGV4dGVuZFBhcmFtcyxcbiAgICAgICAgb24sXG4gICAgICAgIGVtaXRcbiAgICAgIH0gPSBfcmVmO1xuICAgICAgY29uc3Qgd2luZG93ID0gZ2V0V2luZG93KCk7XG4gICAgICBleHRlbmRQYXJhbXMoe1xuICAgICAgICB6b29tOiB7XG4gICAgICAgICAgZW5hYmxlZDogZmFsc2UsXG4gICAgICAgICAgbWF4UmF0aW86IDMsXG4gICAgICAgICAgbWluUmF0aW86IDEsXG4gICAgICAgICAgdG9nZ2xlOiB0cnVlLFxuICAgICAgICAgIGNvbnRhaW5lckNsYXNzOiAnc3dpcGVyLXpvb20tY29udGFpbmVyJyxcbiAgICAgICAgICB6b29tZWRTbGlkZUNsYXNzOiAnc3dpcGVyLXNsaWRlLXpvb21lZCdcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzd2lwZXIuem9vbSA9IHtcbiAgICAgICAgZW5hYmxlZDogZmFsc2VcbiAgICAgIH07XG4gICAgICBsZXQgY3VycmVudFNjYWxlID0gMTtcbiAgICAgIGxldCBpc1NjYWxpbmcgPSBmYWxzZTtcbiAgICAgIGxldCBnZXN0dXJlc0VuYWJsZWQ7XG4gICAgICBsZXQgZmFrZUdlc3R1cmVUb3VjaGVkO1xuICAgICAgbGV0IGZha2VHZXN0dXJlTW92ZWQ7XG4gICAgICBjb25zdCBnZXN0dXJlID0ge1xuICAgICAgICAkc2xpZGVFbDogdW5kZWZpbmVkLFxuICAgICAgICBzbGlkZVdpZHRoOiB1bmRlZmluZWQsXG4gICAgICAgIHNsaWRlSGVpZ2h0OiB1bmRlZmluZWQsXG4gICAgICAgICRpbWFnZUVsOiB1bmRlZmluZWQsXG4gICAgICAgICRpbWFnZVdyYXBFbDogdW5kZWZpbmVkLFxuICAgICAgICBtYXhSYXRpbzogM1xuICAgICAgfTtcbiAgICAgIGNvbnN0IGltYWdlID0ge1xuICAgICAgICBpc1RvdWNoZWQ6IHVuZGVmaW5lZCxcbiAgICAgICAgaXNNb3ZlZDogdW5kZWZpbmVkLFxuICAgICAgICBjdXJyZW50WDogdW5kZWZpbmVkLFxuICAgICAgICBjdXJyZW50WTogdW5kZWZpbmVkLFxuICAgICAgICBtaW5YOiB1bmRlZmluZWQsXG4gICAgICAgIG1pblk6IHVuZGVmaW5lZCxcbiAgICAgICAgbWF4WDogdW5kZWZpbmVkLFxuICAgICAgICBtYXhZOiB1bmRlZmluZWQsXG4gICAgICAgIHdpZHRoOiB1bmRlZmluZWQsXG4gICAgICAgIGhlaWdodDogdW5kZWZpbmVkLFxuICAgICAgICBzdGFydFg6IHVuZGVmaW5lZCxcbiAgICAgICAgc3RhcnRZOiB1bmRlZmluZWQsXG4gICAgICAgIHRvdWNoZXNTdGFydDoge30sXG4gICAgICAgIHRvdWNoZXNDdXJyZW50OiB7fVxuICAgICAgfTtcbiAgICAgIGNvbnN0IHZlbG9jaXR5ID0ge1xuICAgICAgICB4OiB1bmRlZmluZWQsXG4gICAgICAgIHk6IHVuZGVmaW5lZCxcbiAgICAgICAgcHJldlBvc2l0aW9uWDogdW5kZWZpbmVkLFxuICAgICAgICBwcmV2UG9zaXRpb25ZOiB1bmRlZmluZWQsXG4gICAgICAgIHByZXZUaW1lOiB1bmRlZmluZWRcbiAgICAgIH07XG4gICAgICBsZXQgc2NhbGUgPSAxO1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHN3aXBlci56b29tLCAnc2NhbGUnLCB7XG4gICAgICAgIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gc2NhbGU7XG4gICAgICAgIH0sXG5cbiAgICAgICAgc2V0KHZhbHVlKSB7XG4gICAgICAgICAgaWYgKHNjYWxlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgY29uc3QgaW1hZ2VFbCA9IGdlc3R1cmUuJGltYWdlRWwgPyBnZXN0dXJlLiRpbWFnZUVsWzBdIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgY29uc3Qgc2xpZGVFbCA9IGdlc3R1cmUuJHNsaWRlRWwgPyBnZXN0dXJlLiRzbGlkZUVsWzBdIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgZW1pdCgnem9vbUNoYW5nZScsIHZhbHVlLCBpbWFnZUVsLCBzbGlkZUVsKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzY2FsZSA9IHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgIH0pO1xuXG4gICAgICBmdW5jdGlvbiBnZXREaXN0YW5jZUJldHdlZW5Ub3VjaGVzKGUpIHtcbiAgICAgICAgaWYgKGUudGFyZ2V0VG91Y2hlcy5sZW5ndGggPCAyKSByZXR1cm4gMTtcbiAgICAgICAgY29uc3QgeDEgPSBlLnRhcmdldFRvdWNoZXNbMF0ucGFnZVg7XG4gICAgICAgIGNvbnN0IHkxID0gZS50YXJnZXRUb3VjaGVzWzBdLnBhZ2VZO1xuICAgICAgICBjb25zdCB4MiA9IGUudGFyZ2V0VG91Y2hlc1sxXS5wYWdlWDtcbiAgICAgICAgY29uc3QgeTIgPSBlLnRhcmdldFRvdWNoZXNbMV0ucGFnZVk7XG4gICAgICAgIGNvbnN0IGRpc3RhbmNlID0gTWF0aC5zcXJ0KCh4MiAtIHgxKSAqKiAyICsgKHkyIC0geTEpICoqIDIpO1xuICAgICAgICByZXR1cm4gZGlzdGFuY2U7XG4gICAgICB9IC8vIEV2ZW50c1xuXG5cbiAgICAgIGZ1bmN0aW9uIG9uR2VzdHVyZVN0YXJ0KGUpIHtcbiAgICAgICAgY29uc3Qgc3VwcG9ydCA9IHN3aXBlci5zdXBwb3J0O1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zLnpvb207XG4gICAgICAgIGZha2VHZXN0dXJlVG91Y2hlZCA9IGZhbHNlO1xuICAgICAgICBmYWtlR2VzdHVyZU1vdmVkID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKCFzdXBwb3J0Lmdlc3R1cmVzKSB7XG4gICAgICAgICAgaWYgKGUudHlwZSAhPT0gJ3RvdWNoc3RhcnQnIHx8IGUudHlwZSA9PT0gJ3RvdWNoc3RhcnQnICYmIGUudGFyZ2V0VG91Y2hlcy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZmFrZUdlc3R1cmVUb3VjaGVkID0gdHJ1ZTtcbiAgICAgICAgICBnZXN0dXJlLnNjYWxlU3RhcnQgPSBnZXREaXN0YW5jZUJldHdlZW5Ub3VjaGVzKGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFnZXN0dXJlLiRzbGlkZUVsIHx8ICFnZXN0dXJlLiRzbGlkZUVsLmxlbmd0aCkge1xuICAgICAgICAgIGdlc3R1cmUuJHNsaWRlRWwgPSAkKGUudGFyZ2V0KS5jbG9zZXN0KGAuJHtzd2lwZXIucGFyYW1zLnNsaWRlQ2xhc3N9YCk7XG4gICAgICAgICAgaWYgKGdlc3R1cmUuJHNsaWRlRWwubGVuZ3RoID09PSAwKSBnZXN0dXJlLiRzbGlkZUVsID0gc3dpcGVyLnNsaWRlcy5lcShzd2lwZXIuYWN0aXZlSW5kZXgpO1xuICAgICAgICAgIGdlc3R1cmUuJGltYWdlRWwgPSBnZXN0dXJlLiRzbGlkZUVsLmZpbmQoYC4ke3BhcmFtcy5jb250YWluZXJDbGFzc31gKS5lcSgwKS5maW5kKCdwaWN0dXJlLCBpbWcsIHN2ZywgY2FudmFzLCAuc3dpcGVyLXpvb20tdGFyZ2V0JykuZXEoMCk7XG4gICAgICAgICAgZ2VzdHVyZS4kaW1hZ2VXcmFwRWwgPSBnZXN0dXJlLiRpbWFnZUVsLnBhcmVudChgLiR7cGFyYW1zLmNvbnRhaW5lckNsYXNzfWApO1xuICAgICAgICAgIGdlc3R1cmUubWF4UmF0aW8gPSBnZXN0dXJlLiRpbWFnZVdyYXBFbC5hdHRyKCdkYXRhLXN3aXBlci16b29tJykgfHwgcGFyYW1zLm1heFJhdGlvO1xuXG4gICAgICAgICAgaWYgKGdlc3R1cmUuJGltYWdlV3JhcEVsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgZ2VzdHVyZS4kaW1hZ2VFbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZ2VzdHVyZS4kaW1hZ2VFbCkge1xuICAgICAgICAgIGdlc3R1cmUuJGltYWdlRWwudHJhbnNpdGlvbigwKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlzU2NhbGluZyA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIG9uR2VzdHVyZUNoYW5nZShlKSB7XG4gICAgICAgIGNvbnN0IHN1cHBvcnQgPSBzd2lwZXIuc3VwcG9ydDtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy56b29tO1xuICAgICAgICBjb25zdCB6b29tID0gc3dpcGVyLnpvb207XG5cbiAgICAgICAgaWYgKCFzdXBwb3J0Lmdlc3R1cmVzKSB7XG4gICAgICAgICAgaWYgKGUudHlwZSAhPT0gJ3RvdWNobW92ZScgfHwgZS50eXBlID09PSAndG91Y2htb3ZlJyAmJiBlLnRhcmdldFRvdWNoZXMubGVuZ3RoIDwgMikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGZha2VHZXN0dXJlTW92ZWQgPSB0cnVlO1xuICAgICAgICAgIGdlc3R1cmUuc2NhbGVNb3ZlID0gZ2V0RGlzdGFuY2VCZXR3ZWVuVG91Y2hlcyhlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghZ2VzdHVyZS4kaW1hZ2VFbCB8fCBnZXN0dXJlLiRpbWFnZUVsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChlLnR5cGUgPT09ICdnZXN0dXJlY2hhbmdlJykgb25HZXN0dXJlU3RhcnQoZSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN1cHBvcnQuZ2VzdHVyZXMpIHtcbiAgICAgICAgICB6b29tLnNjYWxlID0gZS5zY2FsZSAqIGN1cnJlbnRTY2FsZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB6b29tLnNjYWxlID0gZ2VzdHVyZS5zY2FsZU1vdmUgLyBnZXN0dXJlLnNjYWxlU3RhcnQgKiBjdXJyZW50U2NhbGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoem9vbS5zY2FsZSA+IGdlc3R1cmUubWF4UmF0aW8pIHtcbiAgICAgICAgICB6b29tLnNjYWxlID0gZ2VzdHVyZS5tYXhSYXRpbyAtIDEgKyAoem9vbS5zY2FsZSAtIGdlc3R1cmUubWF4UmF0aW8gKyAxKSAqKiAwLjU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoem9vbS5zY2FsZSA8IHBhcmFtcy5taW5SYXRpbykge1xuICAgICAgICAgIHpvb20uc2NhbGUgPSBwYXJhbXMubWluUmF0aW8gKyAxIC0gKHBhcmFtcy5taW5SYXRpbyAtIHpvb20uc2NhbGUgKyAxKSAqKiAwLjU7XG4gICAgICAgIH1cblxuICAgICAgICBnZXN0dXJlLiRpbWFnZUVsLnRyYW5zZm9ybShgdHJhbnNsYXRlM2QoMCwwLDApIHNjYWxlKCR7em9vbS5zY2FsZX0pYCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIG9uR2VzdHVyZUVuZChlKSB7XG4gICAgICAgIGNvbnN0IGRldmljZSA9IHN3aXBlci5kZXZpY2U7XG4gICAgICAgIGNvbnN0IHN1cHBvcnQgPSBzd2lwZXIuc3VwcG9ydDtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy56b29tO1xuICAgICAgICBjb25zdCB6b29tID0gc3dpcGVyLnpvb207XG5cbiAgICAgICAgaWYgKCFzdXBwb3J0Lmdlc3R1cmVzKSB7XG4gICAgICAgICAgaWYgKCFmYWtlR2VzdHVyZVRvdWNoZWQgfHwgIWZha2VHZXN0dXJlTW92ZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZS50eXBlICE9PSAndG91Y2hlbmQnIHx8IGUudHlwZSA9PT0gJ3RvdWNoZW5kJyAmJiBlLmNoYW5nZWRUb3VjaGVzLmxlbmd0aCA8IDIgJiYgIWRldmljZS5hbmRyb2lkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZmFrZUdlc3R1cmVUb3VjaGVkID0gZmFsc2U7XG4gICAgICAgICAgZmFrZUdlc3R1cmVNb3ZlZCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFnZXN0dXJlLiRpbWFnZUVsIHx8IGdlc3R1cmUuJGltYWdlRWwubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgICAgIHpvb20uc2NhbGUgPSBNYXRoLm1heChNYXRoLm1pbih6b29tLnNjYWxlLCBnZXN0dXJlLm1heFJhdGlvKSwgcGFyYW1zLm1pblJhdGlvKTtcbiAgICAgICAgZ2VzdHVyZS4kaW1hZ2VFbC50cmFuc2l0aW9uKHN3aXBlci5wYXJhbXMuc3BlZWQpLnRyYW5zZm9ybShgdHJhbnNsYXRlM2QoMCwwLDApIHNjYWxlKCR7em9vbS5zY2FsZX0pYCk7XG4gICAgICAgIGN1cnJlbnRTY2FsZSA9IHpvb20uc2NhbGU7XG4gICAgICAgIGlzU2NhbGluZyA9IGZhbHNlO1xuICAgICAgICBpZiAoem9vbS5zY2FsZSA9PT0gMSkgZ2VzdHVyZS4kc2xpZGVFbCA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gb25Ub3VjaFN0YXJ0KGUpIHtcbiAgICAgICAgY29uc3QgZGV2aWNlID0gc3dpcGVyLmRldmljZTtcbiAgICAgICAgaWYgKCFnZXN0dXJlLiRpbWFnZUVsIHx8IGdlc3R1cmUuJGltYWdlRWwubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgICAgIGlmIChpbWFnZS5pc1RvdWNoZWQpIHJldHVybjtcbiAgICAgICAgaWYgKGRldmljZS5hbmRyb2lkICYmIGUuY2FuY2VsYWJsZSkgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBpbWFnZS5pc1RvdWNoZWQgPSB0cnVlO1xuICAgICAgICBpbWFnZS50b3VjaGVzU3RhcnQueCA9IGUudHlwZSA9PT0gJ3RvdWNoc3RhcnQnID8gZS50YXJnZXRUb3VjaGVzWzBdLnBhZ2VYIDogZS5wYWdlWDtcbiAgICAgICAgaW1hZ2UudG91Y2hlc1N0YXJ0LnkgPSBlLnR5cGUgPT09ICd0b3VjaHN0YXJ0JyA/IGUudGFyZ2V0VG91Y2hlc1swXS5wYWdlWSA6IGUucGFnZVk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIG9uVG91Y2hNb3ZlKGUpIHtcbiAgICAgICAgY29uc3Qgem9vbSA9IHN3aXBlci56b29tO1xuICAgICAgICBpZiAoIWdlc3R1cmUuJGltYWdlRWwgfHwgZ2VzdHVyZS4kaW1hZ2VFbC5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICAgICAgc3dpcGVyLmFsbG93Q2xpY2sgPSBmYWxzZTtcbiAgICAgICAgaWYgKCFpbWFnZS5pc1RvdWNoZWQgfHwgIWdlc3R1cmUuJHNsaWRlRWwpIHJldHVybjtcblxuICAgICAgICBpZiAoIWltYWdlLmlzTW92ZWQpIHtcbiAgICAgICAgICBpbWFnZS53aWR0aCA9IGdlc3R1cmUuJGltYWdlRWxbMF0ub2Zmc2V0V2lkdGg7XG4gICAgICAgICAgaW1hZ2UuaGVpZ2h0ID0gZ2VzdHVyZS4kaW1hZ2VFbFswXS5vZmZzZXRIZWlnaHQ7XG4gICAgICAgICAgaW1hZ2Uuc3RhcnRYID0gZ2V0VHJhbnNsYXRlKGdlc3R1cmUuJGltYWdlV3JhcEVsWzBdLCAneCcpIHx8IDA7XG4gICAgICAgICAgaW1hZ2Uuc3RhcnRZID0gZ2V0VHJhbnNsYXRlKGdlc3R1cmUuJGltYWdlV3JhcEVsWzBdLCAneScpIHx8IDA7XG4gICAgICAgICAgZ2VzdHVyZS5zbGlkZVdpZHRoID0gZ2VzdHVyZS4kc2xpZGVFbFswXS5vZmZzZXRXaWR0aDtcbiAgICAgICAgICBnZXN0dXJlLnNsaWRlSGVpZ2h0ID0gZ2VzdHVyZS4kc2xpZGVFbFswXS5vZmZzZXRIZWlnaHQ7XG4gICAgICAgICAgZ2VzdHVyZS4kaW1hZ2VXcmFwRWwudHJhbnNpdGlvbigwKTtcbiAgICAgICAgfSAvLyBEZWZpbmUgaWYgd2UgbmVlZCBpbWFnZSBkcmFnXG5cblxuICAgICAgICBjb25zdCBzY2FsZWRXaWR0aCA9IGltYWdlLndpZHRoICogem9vbS5zY2FsZTtcbiAgICAgICAgY29uc3Qgc2NhbGVkSGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0ICogem9vbS5zY2FsZTtcbiAgICAgICAgaWYgKHNjYWxlZFdpZHRoIDwgZ2VzdHVyZS5zbGlkZVdpZHRoICYmIHNjYWxlZEhlaWdodCA8IGdlc3R1cmUuc2xpZGVIZWlnaHQpIHJldHVybjtcbiAgICAgICAgaW1hZ2UubWluWCA9IE1hdGgubWluKGdlc3R1cmUuc2xpZGVXaWR0aCAvIDIgLSBzY2FsZWRXaWR0aCAvIDIsIDApO1xuICAgICAgICBpbWFnZS5tYXhYID0gLWltYWdlLm1pblg7XG4gICAgICAgIGltYWdlLm1pblkgPSBNYXRoLm1pbihnZXN0dXJlLnNsaWRlSGVpZ2h0IC8gMiAtIHNjYWxlZEhlaWdodCAvIDIsIDApO1xuICAgICAgICBpbWFnZS5tYXhZID0gLWltYWdlLm1pblk7XG4gICAgICAgIGltYWdlLnRvdWNoZXNDdXJyZW50LnggPSBlLnR5cGUgPT09ICd0b3VjaG1vdmUnID8gZS50YXJnZXRUb3VjaGVzWzBdLnBhZ2VYIDogZS5wYWdlWDtcbiAgICAgICAgaW1hZ2UudG91Y2hlc0N1cnJlbnQueSA9IGUudHlwZSA9PT0gJ3RvdWNobW92ZScgPyBlLnRhcmdldFRvdWNoZXNbMF0ucGFnZVkgOiBlLnBhZ2VZO1xuXG4gICAgICAgIGlmICghaW1hZ2UuaXNNb3ZlZCAmJiAhaXNTY2FsaW5nKSB7XG4gICAgICAgICAgaWYgKHN3aXBlci5pc0hvcml6b250YWwoKSAmJiAoTWF0aC5mbG9vcihpbWFnZS5taW5YKSA9PT0gTWF0aC5mbG9vcihpbWFnZS5zdGFydFgpICYmIGltYWdlLnRvdWNoZXNDdXJyZW50LnggPCBpbWFnZS50b3VjaGVzU3RhcnQueCB8fCBNYXRoLmZsb29yKGltYWdlLm1heFgpID09PSBNYXRoLmZsb29yKGltYWdlLnN0YXJ0WCkgJiYgaW1hZ2UudG91Y2hlc0N1cnJlbnQueCA+IGltYWdlLnRvdWNoZXNTdGFydC54KSkge1xuICAgICAgICAgICAgaW1hZ2UuaXNUb3VjaGVkID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFzd2lwZXIuaXNIb3Jpem9udGFsKCkgJiYgKE1hdGguZmxvb3IoaW1hZ2UubWluWSkgPT09IE1hdGguZmxvb3IoaW1hZ2Uuc3RhcnRZKSAmJiBpbWFnZS50b3VjaGVzQ3VycmVudC55IDwgaW1hZ2UudG91Y2hlc1N0YXJ0LnkgfHwgTWF0aC5mbG9vcihpbWFnZS5tYXhZKSA9PT0gTWF0aC5mbG9vcihpbWFnZS5zdGFydFkpICYmIGltYWdlLnRvdWNoZXNDdXJyZW50LnkgPiBpbWFnZS50b3VjaGVzU3RhcnQueSkpIHtcbiAgICAgICAgICAgIGltYWdlLmlzVG91Y2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlLmNhbmNlbGFibGUpIHtcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBpbWFnZS5pc01vdmVkID0gdHJ1ZTtcbiAgICAgICAgaW1hZ2UuY3VycmVudFggPSBpbWFnZS50b3VjaGVzQ3VycmVudC54IC0gaW1hZ2UudG91Y2hlc1N0YXJ0LnggKyBpbWFnZS5zdGFydFg7XG4gICAgICAgIGltYWdlLmN1cnJlbnRZID0gaW1hZ2UudG91Y2hlc0N1cnJlbnQueSAtIGltYWdlLnRvdWNoZXNTdGFydC55ICsgaW1hZ2Uuc3RhcnRZO1xuXG4gICAgICAgIGlmIChpbWFnZS5jdXJyZW50WCA8IGltYWdlLm1pblgpIHtcbiAgICAgICAgICBpbWFnZS5jdXJyZW50WCA9IGltYWdlLm1pblggKyAxIC0gKGltYWdlLm1pblggLSBpbWFnZS5jdXJyZW50WCArIDEpICoqIDAuODtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpbWFnZS5jdXJyZW50WCA+IGltYWdlLm1heFgpIHtcbiAgICAgICAgICBpbWFnZS5jdXJyZW50WCA9IGltYWdlLm1heFggLSAxICsgKGltYWdlLmN1cnJlbnRYIC0gaW1hZ2UubWF4WCArIDEpICoqIDAuODtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpbWFnZS5jdXJyZW50WSA8IGltYWdlLm1pblkpIHtcbiAgICAgICAgICBpbWFnZS5jdXJyZW50WSA9IGltYWdlLm1pblkgKyAxIC0gKGltYWdlLm1pblkgLSBpbWFnZS5jdXJyZW50WSArIDEpICoqIDAuODtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpbWFnZS5jdXJyZW50WSA+IGltYWdlLm1heFkpIHtcbiAgICAgICAgICBpbWFnZS5jdXJyZW50WSA9IGltYWdlLm1heFkgLSAxICsgKGltYWdlLmN1cnJlbnRZIC0gaW1hZ2UubWF4WSArIDEpICoqIDAuODtcbiAgICAgICAgfSAvLyBWZWxvY2l0eVxuXG5cbiAgICAgICAgaWYgKCF2ZWxvY2l0eS5wcmV2UG9zaXRpb25YKSB2ZWxvY2l0eS5wcmV2UG9zaXRpb25YID0gaW1hZ2UudG91Y2hlc0N1cnJlbnQueDtcbiAgICAgICAgaWYgKCF2ZWxvY2l0eS5wcmV2UG9zaXRpb25ZKSB2ZWxvY2l0eS5wcmV2UG9zaXRpb25ZID0gaW1hZ2UudG91Y2hlc0N1cnJlbnQueTtcbiAgICAgICAgaWYgKCF2ZWxvY2l0eS5wcmV2VGltZSkgdmVsb2NpdHkucHJldlRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICB2ZWxvY2l0eS54ID0gKGltYWdlLnRvdWNoZXNDdXJyZW50LnggLSB2ZWxvY2l0eS5wcmV2UG9zaXRpb25YKSAvIChEYXRlLm5vdygpIC0gdmVsb2NpdHkucHJldlRpbWUpIC8gMjtcbiAgICAgICAgdmVsb2NpdHkueSA9IChpbWFnZS50b3VjaGVzQ3VycmVudC55IC0gdmVsb2NpdHkucHJldlBvc2l0aW9uWSkgLyAoRGF0ZS5ub3coKSAtIHZlbG9jaXR5LnByZXZUaW1lKSAvIDI7XG4gICAgICAgIGlmIChNYXRoLmFicyhpbWFnZS50b3VjaGVzQ3VycmVudC54IC0gdmVsb2NpdHkucHJldlBvc2l0aW9uWCkgPCAyKSB2ZWxvY2l0eS54ID0gMDtcbiAgICAgICAgaWYgKE1hdGguYWJzKGltYWdlLnRvdWNoZXNDdXJyZW50LnkgLSB2ZWxvY2l0eS5wcmV2UG9zaXRpb25ZKSA8IDIpIHZlbG9jaXR5LnkgPSAwO1xuICAgICAgICB2ZWxvY2l0eS5wcmV2UG9zaXRpb25YID0gaW1hZ2UudG91Y2hlc0N1cnJlbnQueDtcbiAgICAgICAgdmVsb2NpdHkucHJldlBvc2l0aW9uWSA9IGltYWdlLnRvdWNoZXNDdXJyZW50Lnk7XG4gICAgICAgIHZlbG9jaXR5LnByZXZUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgZ2VzdHVyZS4kaW1hZ2VXcmFwRWwudHJhbnNmb3JtKGB0cmFuc2xhdGUzZCgke2ltYWdlLmN1cnJlbnRYfXB4LCAke2ltYWdlLmN1cnJlbnRZfXB4LDApYCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIG9uVG91Y2hFbmQoKSB7XG4gICAgICAgIGNvbnN0IHpvb20gPSBzd2lwZXIuem9vbTtcbiAgICAgICAgaWYgKCFnZXN0dXJlLiRpbWFnZUVsIHx8IGdlc3R1cmUuJGltYWdlRWwubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgICAgICAgaWYgKCFpbWFnZS5pc1RvdWNoZWQgfHwgIWltYWdlLmlzTW92ZWQpIHtcbiAgICAgICAgICBpbWFnZS5pc1RvdWNoZWQgPSBmYWxzZTtcbiAgICAgICAgICBpbWFnZS5pc01vdmVkID0gZmFsc2U7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaW1hZ2UuaXNUb3VjaGVkID0gZmFsc2U7XG4gICAgICAgIGltYWdlLmlzTW92ZWQgPSBmYWxzZTtcbiAgICAgICAgbGV0IG1vbWVudHVtRHVyYXRpb25YID0gMzAwO1xuICAgICAgICBsZXQgbW9tZW50dW1EdXJhdGlvblkgPSAzMDA7XG4gICAgICAgIGNvbnN0IG1vbWVudHVtRGlzdGFuY2VYID0gdmVsb2NpdHkueCAqIG1vbWVudHVtRHVyYXRpb25YO1xuICAgICAgICBjb25zdCBuZXdQb3NpdGlvblggPSBpbWFnZS5jdXJyZW50WCArIG1vbWVudHVtRGlzdGFuY2VYO1xuICAgICAgICBjb25zdCBtb21lbnR1bURpc3RhbmNlWSA9IHZlbG9jaXR5LnkgKiBtb21lbnR1bUR1cmF0aW9uWTtcbiAgICAgICAgY29uc3QgbmV3UG9zaXRpb25ZID0gaW1hZ2UuY3VycmVudFkgKyBtb21lbnR1bURpc3RhbmNlWTsgLy8gRml4IGR1cmF0aW9uXG5cbiAgICAgICAgaWYgKHZlbG9jaXR5LnggIT09IDApIG1vbWVudHVtRHVyYXRpb25YID0gTWF0aC5hYnMoKG5ld1Bvc2l0aW9uWCAtIGltYWdlLmN1cnJlbnRYKSAvIHZlbG9jaXR5LngpO1xuICAgICAgICBpZiAodmVsb2NpdHkueSAhPT0gMCkgbW9tZW50dW1EdXJhdGlvblkgPSBNYXRoLmFicygobmV3UG9zaXRpb25ZIC0gaW1hZ2UuY3VycmVudFkpIC8gdmVsb2NpdHkueSk7XG4gICAgICAgIGNvbnN0IG1vbWVudHVtRHVyYXRpb24gPSBNYXRoLm1heChtb21lbnR1bUR1cmF0aW9uWCwgbW9tZW50dW1EdXJhdGlvblkpO1xuICAgICAgICBpbWFnZS5jdXJyZW50WCA9IG5ld1Bvc2l0aW9uWDtcbiAgICAgICAgaW1hZ2UuY3VycmVudFkgPSBuZXdQb3NpdGlvblk7IC8vIERlZmluZSBpZiB3ZSBuZWVkIGltYWdlIGRyYWdcblxuICAgICAgICBjb25zdCBzY2FsZWRXaWR0aCA9IGltYWdlLndpZHRoICogem9vbS5zY2FsZTtcbiAgICAgICAgY29uc3Qgc2NhbGVkSGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0ICogem9vbS5zY2FsZTtcbiAgICAgICAgaW1hZ2UubWluWCA9IE1hdGgubWluKGdlc3R1cmUuc2xpZGVXaWR0aCAvIDIgLSBzY2FsZWRXaWR0aCAvIDIsIDApO1xuICAgICAgICBpbWFnZS5tYXhYID0gLWltYWdlLm1pblg7XG4gICAgICAgIGltYWdlLm1pblkgPSBNYXRoLm1pbihnZXN0dXJlLnNsaWRlSGVpZ2h0IC8gMiAtIHNjYWxlZEhlaWdodCAvIDIsIDApO1xuICAgICAgICBpbWFnZS5tYXhZID0gLWltYWdlLm1pblk7XG4gICAgICAgIGltYWdlLmN1cnJlbnRYID0gTWF0aC5tYXgoTWF0aC5taW4oaW1hZ2UuY3VycmVudFgsIGltYWdlLm1heFgpLCBpbWFnZS5taW5YKTtcbiAgICAgICAgaW1hZ2UuY3VycmVudFkgPSBNYXRoLm1heChNYXRoLm1pbihpbWFnZS5jdXJyZW50WSwgaW1hZ2UubWF4WSksIGltYWdlLm1pblkpO1xuICAgICAgICBnZXN0dXJlLiRpbWFnZVdyYXBFbC50cmFuc2l0aW9uKG1vbWVudHVtRHVyYXRpb24pLnRyYW5zZm9ybShgdHJhbnNsYXRlM2QoJHtpbWFnZS5jdXJyZW50WH1weCwgJHtpbWFnZS5jdXJyZW50WX1weCwwKWApO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBvblRyYW5zaXRpb25FbmQoKSB7XG4gICAgICAgIGNvbnN0IHpvb20gPSBzd2lwZXIuem9vbTtcblxuICAgICAgICBpZiAoZ2VzdHVyZS4kc2xpZGVFbCAmJiBzd2lwZXIucHJldmlvdXNJbmRleCAhPT0gc3dpcGVyLmFjdGl2ZUluZGV4KSB7XG4gICAgICAgICAgaWYgKGdlc3R1cmUuJGltYWdlRWwpIHtcbiAgICAgICAgICAgIGdlc3R1cmUuJGltYWdlRWwudHJhbnNmb3JtKCd0cmFuc2xhdGUzZCgwLDAsMCkgc2NhbGUoMSknKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZ2VzdHVyZS4kaW1hZ2VXcmFwRWwpIHtcbiAgICAgICAgICAgIGdlc3R1cmUuJGltYWdlV3JhcEVsLnRyYW5zZm9ybSgndHJhbnNsYXRlM2QoMCwwLDApJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgem9vbS5zY2FsZSA9IDE7XG4gICAgICAgICAgY3VycmVudFNjYWxlID0gMTtcbiAgICAgICAgICBnZXN0dXJlLiRzbGlkZUVsID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGdlc3R1cmUuJGltYWdlRWwgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgZ2VzdHVyZS4kaW1hZ2VXcmFwRWwgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gem9vbUluKGUpIHtcbiAgICAgICAgY29uc3Qgem9vbSA9IHN3aXBlci56b29tO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zLnpvb207XG5cbiAgICAgICAgaWYgKCFnZXN0dXJlLiRzbGlkZUVsKSB7XG4gICAgICAgICAgaWYgKGUgJiYgZS50YXJnZXQpIHtcbiAgICAgICAgICAgIGdlc3R1cmUuJHNsaWRlRWwgPSAkKGUudGFyZ2V0KS5jbG9zZXN0KGAuJHtzd2lwZXIucGFyYW1zLnNsaWRlQ2xhc3N9YCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFnZXN0dXJlLiRzbGlkZUVsKSB7XG4gICAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy52aXJ0dWFsICYmIHN3aXBlci5wYXJhbXMudmlydHVhbC5lbmFibGVkICYmIHN3aXBlci52aXJ0dWFsKSB7XG4gICAgICAgICAgICAgIGdlc3R1cmUuJHNsaWRlRWwgPSBzd2lwZXIuJHdyYXBwZXJFbC5jaGlsZHJlbihgLiR7c3dpcGVyLnBhcmFtcy5zbGlkZUFjdGl2ZUNsYXNzfWApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZ2VzdHVyZS4kc2xpZGVFbCA9IHN3aXBlci5zbGlkZXMuZXEoc3dpcGVyLmFjdGl2ZUluZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBnZXN0dXJlLiRpbWFnZUVsID0gZ2VzdHVyZS4kc2xpZGVFbC5maW5kKGAuJHtwYXJhbXMuY29udGFpbmVyQ2xhc3N9YCkuZXEoMCkuZmluZCgncGljdHVyZSwgaW1nLCBzdmcsIGNhbnZhcywgLnN3aXBlci16b29tLXRhcmdldCcpLmVxKDApO1xuICAgICAgICAgIGdlc3R1cmUuJGltYWdlV3JhcEVsID0gZ2VzdHVyZS4kaW1hZ2VFbC5wYXJlbnQoYC4ke3BhcmFtcy5jb250YWluZXJDbGFzc31gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghZ2VzdHVyZS4kaW1hZ2VFbCB8fCBnZXN0dXJlLiRpbWFnZUVsLmxlbmd0aCA9PT0gMCB8fCAhZ2VzdHVyZS4kaW1hZ2VXcmFwRWwgfHwgZ2VzdHVyZS4kaW1hZ2VXcmFwRWwubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuY3NzTW9kZSkge1xuICAgICAgICAgIHN3aXBlci53cmFwcGVyRWwuc3R5bGUub3ZlcmZsb3cgPSAnaGlkZGVuJztcbiAgICAgICAgICBzd2lwZXIud3JhcHBlckVsLnN0eWxlLnRvdWNoQWN0aW9uID0gJ25vbmUnO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2VzdHVyZS4kc2xpZGVFbC5hZGRDbGFzcyhgJHtwYXJhbXMuem9vbWVkU2xpZGVDbGFzc31gKTtcbiAgICAgICAgbGV0IHRvdWNoWDtcbiAgICAgICAgbGV0IHRvdWNoWTtcbiAgICAgICAgbGV0IG9mZnNldFg7XG4gICAgICAgIGxldCBvZmZzZXRZO1xuICAgICAgICBsZXQgZGlmZlg7XG4gICAgICAgIGxldCBkaWZmWTtcbiAgICAgICAgbGV0IHRyYW5zbGF0ZVg7XG4gICAgICAgIGxldCB0cmFuc2xhdGVZO1xuICAgICAgICBsZXQgaW1hZ2VXaWR0aDtcbiAgICAgICAgbGV0IGltYWdlSGVpZ2h0O1xuICAgICAgICBsZXQgc2NhbGVkV2lkdGg7XG4gICAgICAgIGxldCBzY2FsZWRIZWlnaHQ7XG4gICAgICAgIGxldCB0cmFuc2xhdGVNaW5YO1xuICAgICAgICBsZXQgdHJhbnNsYXRlTWluWTtcbiAgICAgICAgbGV0IHRyYW5zbGF0ZU1heFg7XG4gICAgICAgIGxldCB0cmFuc2xhdGVNYXhZO1xuICAgICAgICBsZXQgc2xpZGVXaWR0aDtcbiAgICAgICAgbGV0IHNsaWRlSGVpZ2h0O1xuXG4gICAgICAgIGlmICh0eXBlb2YgaW1hZ2UudG91Y2hlc1N0YXJ0LnggPT09ICd1bmRlZmluZWQnICYmIGUpIHtcbiAgICAgICAgICB0b3VjaFggPSBlLnR5cGUgPT09ICd0b3VjaGVuZCcgPyBlLmNoYW5nZWRUb3VjaGVzWzBdLnBhZ2VYIDogZS5wYWdlWDtcbiAgICAgICAgICB0b3VjaFkgPSBlLnR5cGUgPT09ICd0b3VjaGVuZCcgPyBlLmNoYW5nZWRUb3VjaGVzWzBdLnBhZ2VZIDogZS5wYWdlWTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0b3VjaFggPSBpbWFnZS50b3VjaGVzU3RhcnQueDtcbiAgICAgICAgICB0b3VjaFkgPSBpbWFnZS50b3VjaGVzU3RhcnQueTtcbiAgICAgICAgfVxuXG4gICAgICAgIHpvb20uc2NhbGUgPSBnZXN0dXJlLiRpbWFnZVdyYXBFbC5hdHRyKCdkYXRhLXN3aXBlci16b29tJykgfHwgcGFyYW1zLm1heFJhdGlvO1xuICAgICAgICBjdXJyZW50U2NhbGUgPSBnZXN0dXJlLiRpbWFnZVdyYXBFbC5hdHRyKCdkYXRhLXN3aXBlci16b29tJykgfHwgcGFyYW1zLm1heFJhdGlvO1xuXG4gICAgICAgIGlmIChlKSB7XG4gICAgICAgICAgc2xpZGVXaWR0aCA9IGdlc3R1cmUuJHNsaWRlRWxbMF0ub2Zmc2V0V2lkdGg7XG4gICAgICAgICAgc2xpZGVIZWlnaHQgPSBnZXN0dXJlLiRzbGlkZUVsWzBdLm9mZnNldEhlaWdodDtcbiAgICAgICAgICBvZmZzZXRYID0gZ2VzdHVyZS4kc2xpZGVFbC5vZmZzZXQoKS5sZWZ0ICsgd2luZG93LnNjcm9sbFg7XG4gICAgICAgICAgb2Zmc2V0WSA9IGdlc3R1cmUuJHNsaWRlRWwub2Zmc2V0KCkudG9wICsgd2luZG93LnNjcm9sbFk7XG4gICAgICAgICAgZGlmZlggPSBvZmZzZXRYICsgc2xpZGVXaWR0aCAvIDIgLSB0b3VjaFg7XG4gICAgICAgICAgZGlmZlkgPSBvZmZzZXRZICsgc2xpZGVIZWlnaHQgLyAyIC0gdG91Y2hZO1xuICAgICAgICAgIGltYWdlV2lkdGggPSBnZXN0dXJlLiRpbWFnZUVsWzBdLm9mZnNldFdpZHRoO1xuICAgICAgICAgIGltYWdlSGVpZ2h0ID0gZ2VzdHVyZS4kaW1hZ2VFbFswXS5vZmZzZXRIZWlnaHQ7XG4gICAgICAgICAgc2NhbGVkV2lkdGggPSBpbWFnZVdpZHRoICogem9vbS5zY2FsZTtcbiAgICAgICAgICBzY2FsZWRIZWlnaHQgPSBpbWFnZUhlaWdodCAqIHpvb20uc2NhbGU7XG4gICAgICAgICAgdHJhbnNsYXRlTWluWCA9IE1hdGgubWluKHNsaWRlV2lkdGggLyAyIC0gc2NhbGVkV2lkdGggLyAyLCAwKTtcbiAgICAgICAgICB0cmFuc2xhdGVNaW5ZID0gTWF0aC5taW4oc2xpZGVIZWlnaHQgLyAyIC0gc2NhbGVkSGVpZ2h0IC8gMiwgMCk7XG4gICAgICAgICAgdHJhbnNsYXRlTWF4WCA9IC10cmFuc2xhdGVNaW5YO1xuICAgICAgICAgIHRyYW5zbGF0ZU1heFkgPSAtdHJhbnNsYXRlTWluWTtcbiAgICAgICAgICB0cmFuc2xhdGVYID0gZGlmZlggKiB6b29tLnNjYWxlO1xuICAgICAgICAgIHRyYW5zbGF0ZVkgPSBkaWZmWSAqIHpvb20uc2NhbGU7XG5cbiAgICAgICAgICBpZiAodHJhbnNsYXRlWCA8IHRyYW5zbGF0ZU1pblgpIHtcbiAgICAgICAgICAgIHRyYW5zbGF0ZVggPSB0cmFuc2xhdGVNaW5YO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0cmFuc2xhdGVYID4gdHJhbnNsYXRlTWF4WCkge1xuICAgICAgICAgICAgdHJhbnNsYXRlWCA9IHRyYW5zbGF0ZU1heFg7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRyYW5zbGF0ZVkgPCB0cmFuc2xhdGVNaW5ZKSB7XG4gICAgICAgICAgICB0cmFuc2xhdGVZID0gdHJhbnNsYXRlTWluWTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodHJhbnNsYXRlWSA+IHRyYW5zbGF0ZU1heFkpIHtcbiAgICAgICAgICAgIHRyYW5zbGF0ZVkgPSB0cmFuc2xhdGVNYXhZO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0cmFuc2xhdGVYID0gMDtcbiAgICAgICAgICB0cmFuc2xhdGVZID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGdlc3R1cmUuJGltYWdlV3JhcEVsLnRyYW5zaXRpb24oMzAwKS50cmFuc2Zvcm0oYHRyYW5zbGF0ZTNkKCR7dHJhbnNsYXRlWH1weCwgJHt0cmFuc2xhdGVZfXB4LDApYCk7XG4gICAgICAgIGdlc3R1cmUuJGltYWdlRWwudHJhbnNpdGlvbigzMDApLnRyYW5zZm9ybShgdHJhbnNsYXRlM2QoMCwwLDApIHNjYWxlKCR7em9vbS5zY2FsZX0pYCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHpvb21PdXQoKSB7XG4gICAgICAgIGNvbnN0IHpvb20gPSBzd2lwZXIuem9vbTtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy56b29tO1xuXG4gICAgICAgIGlmICghZ2VzdHVyZS4kc2xpZGVFbCkge1xuICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLnZpcnR1YWwgJiYgc3dpcGVyLnBhcmFtcy52aXJ0dWFsLmVuYWJsZWQgJiYgc3dpcGVyLnZpcnR1YWwpIHtcbiAgICAgICAgICAgIGdlc3R1cmUuJHNsaWRlRWwgPSBzd2lwZXIuJHdyYXBwZXJFbC5jaGlsZHJlbihgLiR7c3dpcGVyLnBhcmFtcy5zbGlkZUFjdGl2ZUNsYXNzfWApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnZXN0dXJlLiRzbGlkZUVsID0gc3dpcGVyLnNsaWRlcy5lcShzd2lwZXIuYWN0aXZlSW5kZXgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGdlc3R1cmUuJGltYWdlRWwgPSBnZXN0dXJlLiRzbGlkZUVsLmZpbmQoYC4ke3BhcmFtcy5jb250YWluZXJDbGFzc31gKS5lcSgwKS5maW5kKCdwaWN0dXJlLCBpbWcsIHN2ZywgY2FudmFzLCAuc3dpcGVyLXpvb20tdGFyZ2V0JykuZXEoMCk7XG4gICAgICAgICAgZ2VzdHVyZS4kaW1hZ2VXcmFwRWwgPSBnZXN0dXJlLiRpbWFnZUVsLnBhcmVudChgLiR7cGFyYW1zLmNvbnRhaW5lckNsYXNzfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFnZXN0dXJlLiRpbWFnZUVsIHx8IGdlc3R1cmUuJGltYWdlRWwubGVuZ3RoID09PSAwIHx8ICFnZXN0dXJlLiRpbWFnZVdyYXBFbCB8fCBnZXN0dXJlLiRpbWFnZVdyYXBFbC5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5jc3NNb2RlKSB7XG4gICAgICAgICAgc3dpcGVyLndyYXBwZXJFbC5zdHlsZS5vdmVyZmxvdyA9ICcnO1xuICAgICAgICAgIHN3aXBlci53cmFwcGVyRWwuc3R5bGUudG91Y2hBY3Rpb24gPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIHpvb20uc2NhbGUgPSAxO1xuICAgICAgICBjdXJyZW50U2NhbGUgPSAxO1xuICAgICAgICBnZXN0dXJlLiRpbWFnZVdyYXBFbC50cmFuc2l0aW9uKDMwMCkudHJhbnNmb3JtKCd0cmFuc2xhdGUzZCgwLDAsMCknKTtcbiAgICAgICAgZ2VzdHVyZS4kaW1hZ2VFbC50cmFuc2l0aW9uKDMwMCkudHJhbnNmb3JtKCd0cmFuc2xhdGUzZCgwLDAsMCkgc2NhbGUoMSknKTtcbiAgICAgICAgZ2VzdHVyZS4kc2xpZGVFbC5yZW1vdmVDbGFzcyhgJHtwYXJhbXMuem9vbWVkU2xpZGVDbGFzc31gKTtcbiAgICAgICAgZ2VzdHVyZS4kc2xpZGVFbCA9IHVuZGVmaW5lZDtcbiAgICAgIH0gLy8gVG9nZ2xlIFpvb21cblxuXG4gICAgICBmdW5jdGlvbiB6b29tVG9nZ2xlKGUpIHtcbiAgICAgICAgY29uc3Qgem9vbSA9IHN3aXBlci56b29tO1xuXG4gICAgICAgIGlmICh6b29tLnNjYWxlICYmIHpvb20uc2NhbGUgIT09IDEpIHtcbiAgICAgICAgICAvLyBab29tIE91dFxuICAgICAgICAgIHpvb21PdXQoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBab29tIEluXG4gICAgICAgICAgem9vbUluKGUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGdldExpc3RlbmVycygpIHtcbiAgICAgICAgY29uc3Qgc3VwcG9ydCA9IHN3aXBlci5zdXBwb3J0O1xuICAgICAgICBjb25zdCBwYXNzaXZlTGlzdGVuZXIgPSBzd2lwZXIudG91Y2hFdmVudHMuc3RhcnQgPT09ICd0b3VjaHN0YXJ0JyAmJiBzdXBwb3J0LnBhc3NpdmVMaXN0ZW5lciAmJiBzd2lwZXIucGFyYW1zLnBhc3NpdmVMaXN0ZW5lcnMgPyB7XG4gICAgICAgICAgcGFzc2l2ZTogdHJ1ZSxcbiAgICAgICAgICBjYXB0dXJlOiBmYWxzZVxuICAgICAgICB9IDogZmFsc2U7XG4gICAgICAgIGNvbnN0IGFjdGl2ZUxpc3RlbmVyV2l0aENhcHR1cmUgPSBzdXBwb3J0LnBhc3NpdmVMaXN0ZW5lciA/IHtcbiAgICAgICAgICBwYXNzaXZlOiBmYWxzZSxcbiAgICAgICAgICBjYXB0dXJlOiB0cnVlXG4gICAgICAgIH0gOiB0cnVlO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHBhc3NpdmVMaXN0ZW5lcixcbiAgICAgICAgICBhY3RpdmVMaXN0ZW5lcldpdGhDYXB0dXJlXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGdldFNsaWRlU2VsZWN0b3IoKSB7XG4gICAgICAgIHJldHVybiBgLiR7c3dpcGVyLnBhcmFtcy5zbGlkZUNsYXNzfWA7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHRvZ2dsZUdlc3R1cmVzKG1ldGhvZCkge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgcGFzc2l2ZUxpc3RlbmVyXG4gICAgICAgIH0gPSBnZXRMaXN0ZW5lcnMoKTtcbiAgICAgICAgY29uc3Qgc2xpZGVTZWxlY3RvciA9IGdldFNsaWRlU2VsZWN0b3IoKTtcbiAgICAgICAgc3dpcGVyLiR3cmFwcGVyRWxbbWV0aG9kXSgnZ2VzdHVyZXN0YXJ0Jywgc2xpZGVTZWxlY3Rvciwgb25HZXN0dXJlU3RhcnQsIHBhc3NpdmVMaXN0ZW5lcik7XG4gICAgICAgIHN3aXBlci4kd3JhcHBlckVsW21ldGhvZF0oJ2dlc3R1cmVjaGFuZ2UnLCBzbGlkZVNlbGVjdG9yLCBvbkdlc3R1cmVDaGFuZ2UsIHBhc3NpdmVMaXN0ZW5lcik7XG4gICAgICAgIHN3aXBlci4kd3JhcHBlckVsW21ldGhvZF0oJ2dlc3R1cmVlbmQnLCBzbGlkZVNlbGVjdG9yLCBvbkdlc3R1cmVFbmQsIHBhc3NpdmVMaXN0ZW5lcik7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGVuYWJsZUdlc3R1cmVzKCkge1xuICAgICAgICBpZiAoZ2VzdHVyZXNFbmFibGVkKSByZXR1cm47XG4gICAgICAgIGdlc3R1cmVzRW5hYmxlZCA9IHRydWU7XG4gICAgICAgIHRvZ2dsZUdlc3R1cmVzKCdvbicpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBkaXNhYmxlR2VzdHVyZXMoKSB7XG4gICAgICAgIGlmICghZ2VzdHVyZXNFbmFibGVkKSByZXR1cm47XG4gICAgICAgIGdlc3R1cmVzRW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICB0b2dnbGVHZXN0dXJlcygnb2ZmJyk7XG4gICAgICB9IC8vIEF0dGFjaC9EZXRhY2ggRXZlbnRzXG5cblxuICAgICAgZnVuY3Rpb24gZW5hYmxlKCkge1xuICAgICAgICBjb25zdCB6b29tID0gc3dpcGVyLnpvb207XG4gICAgICAgIGlmICh6b29tLmVuYWJsZWQpIHJldHVybjtcbiAgICAgICAgem9vbS5lbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgY29uc3Qgc3VwcG9ydCA9IHN3aXBlci5zdXBwb3J0O1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgcGFzc2l2ZUxpc3RlbmVyLFxuICAgICAgICAgIGFjdGl2ZUxpc3RlbmVyV2l0aENhcHR1cmVcbiAgICAgICAgfSA9IGdldExpc3RlbmVycygpO1xuICAgICAgICBjb25zdCBzbGlkZVNlbGVjdG9yID0gZ2V0U2xpZGVTZWxlY3RvcigpOyAvLyBTY2FsZSBpbWFnZVxuXG4gICAgICAgIGlmIChzdXBwb3J0Lmdlc3R1cmVzKSB7XG4gICAgICAgICAgc3dpcGVyLiR3cmFwcGVyRWwub24oc3dpcGVyLnRvdWNoRXZlbnRzLnN0YXJ0LCBlbmFibGVHZXN0dXJlcywgcGFzc2l2ZUxpc3RlbmVyKTtcbiAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbC5vbihzd2lwZXIudG91Y2hFdmVudHMuZW5kLCBkaXNhYmxlR2VzdHVyZXMsIHBhc3NpdmVMaXN0ZW5lcik7XG4gICAgICAgIH0gZWxzZSBpZiAoc3dpcGVyLnRvdWNoRXZlbnRzLnN0YXJ0ID09PSAndG91Y2hzdGFydCcpIHtcbiAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbC5vbihzd2lwZXIudG91Y2hFdmVudHMuc3RhcnQsIHNsaWRlU2VsZWN0b3IsIG9uR2VzdHVyZVN0YXJ0LCBwYXNzaXZlTGlzdGVuZXIpO1xuICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsLm9uKHN3aXBlci50b3VjaEV2ZW50cy5tb3ZlLCBzbGlkZVNlbGVjdG9yLCBvbkdlc3R1cmVDaGFuZ2UsIGFjdGl2ZUxpc3RlbmVyV2l0aENhcHR1cmUpO1xuICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsLm9uKHN3aXBlci50b3VjaEV2ZW50cy5lbmQsIHNsaWRlU2VsZWN0b3IsIG9uR2VzdHVyZUVuZCwgcGFzc2l2ZUxpc3RlbmVyKTtcblxuICAgICAgICAgIGlmIChzd2lwZXIudG91Y2hFdmVudHMuY2FuY2VsKSB7XG4gICAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbC5vbihzd2lwZXIudG91Y2hFdmVudHMuY2FuY2VsLCBzbGlkZVNlbGVjdG9yLCBvbkdlc3R1cmVFbmQsIHBhc3NpdmVMaXN0ZW5lcik7XG4gICAgICAgICAgfVxuICAgICAgICB9IC8vIE1vdmUgaW1hZ2VcblxuXG4gICAgICAgIHN3aXBlci4kd3JhcHBlckVsLm9uKHN3aXBlci50b3VjaEV2ZW50cy5tb3ZlLCBgLiR7c3dpcGVyLnBhcmFtcy56b29tLmNvbnRhaW5lckNsYXNzfWAsIG9uVG91Y2hNb3ZlLCBhY3RpdmVMaXN0ZW5lcldpdGhDYXB0dXJlKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZGlzYWJsZSgpIHtcbiAgICAgICAgY29uc3Qgem9vbSA9IHN3aXBlci56b29tO1xuICAgICAgICBpZiAoIXpvb20uZW5hYmxlZCkgcmV0dXJuO1xuICAgICAgICBjb25zdCBzdXBwb3J0ID0gc3dpcGVyLnN1cHBvcnQ7XG4gICAgICAgIHpvb20uZW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgcGFzc2l2ZUxpc3RlbmVyLFxuICAgICAgICAgIGFjdGl2ZUxpc3RlbmVyV2l0aENhcHR1cmVcbiAgICAgICAgfSA9IGdldExpc3RlbmVycygpO1xuICAgICAgICBjb25zdCBzbGlkZVNlbGVjdG9yID0gZ2V0U2xpZGVTZWxlY3RvcigpOyAvLyBTY2FsZSBpbWFnZVxuXG4gICAgICAgIGlmIChzdXBwb3J0Lmdlc3R1cmVzKSB7XG4gICAgICAgICAgc3dpcGVyLiR3cmFwcGVyRWwub2ZmKHN3aXBlci50b3VjaEV2ZW50cy5zdGFydCwgZW5hYmxlR2VzdHVyZXMsIHBhc3NpdmVMaXN0ZW5lcik7XG4gICAgICAgICAgc3dpcGVyLiR3cmFwcGVyRWwub2ZmKHN3aXBlci50b3VjaEV2ZW50cy5lbmQsIGRpc2FibGVHZXN0dXJlcywgcGFzc2l2ZUxpc3RlbmVyKTtcbiAgICAgICAgfSBlbHNlIGlmIChzd2lwZXIudG91Y2hFdmVudHMuc3RhcnQgPT09ICd0b3VjaHN0YXJ0Jykge1xuICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsLm9mZihzd2lwZXIudG91Y2hFdmVudHMuc3RhcnQsIHNsaWRlU2VsZWN0b3IsIG9uR2VzdHVyZVN0YXJ0LCBwYXNzaXZlTGlzdGVuZXIpO1xuICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsLm9mZihzd2lwZXIudG91Y2hFdmVudHMubW92ZSwgc2xpZGVTZWxlY3Rvciwgb25HZXN0dXJlQ2hhbmdlLCBhY3RpdmVMaXN0ZW5lcldpdGhDYXB0dXJlKTtcbiAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbC5vZmYoc3dpcGVyLnRvdWNoRXZlbnRzLmVuZCwgc2xpZGVTZWxlY3Rvciwgb25HZXN0dXJlRW5kLCBwYXNzaXZlTGlzdGVuZXIpO1xuXG4gICAgICAgICAgaWYgKHN3aXBlci50b3VjaEV2ZW50cy5jYW5jZWwpIHtcbiAgICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsLm9mZihzd2lwZXIudG91Y2hFdmVudHMuY2FuY2VsLCBzbGlkZVNlbGVjdG9yLCBvbkdlc3R1cmVFbmQsIHBhc3NpdmVMaXN0ZW5lcik7XG4gICAgICAgICAgfVxuICAgICAgICB9IC8vIE1vdmUgaW1hZ2VcblxuXG4gICAgICAgIHN3aXBlci4kd3JhcHBlckVsLm9mZihzd2lwZXIudG91Y2hFdmVudHMubW92ZSwgYC4ke3N3aXBlci5wYXJhbXMuem9vbS5jb250YWluZXJDbGFzc31gLCBvblRvdWNoTW92ZSwgYWN0aXZlTGlzdGVuZXJXaXRoQ2FwdHVyZSk7XG4gICAgICB9XG5cbiAgICAgIG9uKCdpbml0JywgKCkgPT4ge1xuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy56b29tLmVuYWJsZWQpIHtcbiAgICAgICAgICBlbmFibGUoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBvbignZGVzdHJveScsICgpID0+IHtcbiAgICAgICAgZGlzYWJsZSgpO1xuICAgICAgfSk7XG4gICAgICBvbigndG91Y2hTdGFydCcsIChfcywgZSkgPT4ge1xuICAgICAgICBpZiAoIXN3aXBlci56b29tLmVuYWJsZWQpIHJldHVybjtcbiAgICAgICAgb25Ub3VjaFN0YXJ0KGUpO1xuICAgICAgfSk7XG4gICAgICBvbigndG91Y2hFbmQnLCAoX3MsIGUpID0+IHtcbiAgICAgICAgaWYgKCFzd2lwZXIuem9vbS5lbmFibGVkKSByZXR1cm47XG4gICAgICAgIG9uVG91Y2hFbmQoKTtcbiAgICAgIH0pO1xuICAgICAgb24oJ2RvdWJsZVRhcCcsIChfcywgZSkgPT4ge1xuICAgICAgICBpZiAoIXN3aXBlci5hbmltYXRpbmcgJiYgc3dpcGVyLnBhcmFtcy56b29tLmVuYWJsZWQgJiYgc3dpcGVyLnpvb20uZW5hYmxlZCAmJiBzd2lwZXIucGFyYW1zLnpvb20udG9nZ2xlKSB7XG4gICAgICAgICAgem9vbVRvZ2dsZShlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBvbigndHJhbnNpdGlvbkVuZCcsICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci56b29tLmVuYWJsZWQgJiYgc3dpcGVyLnBhcmFtcy56b29tLmVuYWJsZWQpIHtcbiAgICAgICAgICBvblRyYW5zaXRpb25FbmQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBvbignc2xpZGVDaGFuZ2UnLCAoKSA9PiB7XG4gICAgICAgIGlmIChzd2lwZXIuem9vbS5lbmFibGVkICYmIHN3aXBlci5wYXJhbXMuem9vbS5lbmFibGVkICYmIHN3aXBlci5wYXJhbXMuY3NzTW9kZSkge1xuICAgICAgICAgIG9uVHJhbnNpdGlvbkVuZCgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIE9iamVjdC5hc3NpZ24oc3dpcGVyLnpvb20sIHtcbiAgICAgICAgZW5hYmxlLFxuICAgICAgICBkaXNhYmxlLFxuICAgICAgICBpbjogem9vbUluLFxuICAgICAgICBvdXQ6IHpvb21PdXQsXG4gICAgICAgIHRvZ2dsZTogem9vbVRvZ2dsZVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gTGF6eShfcmVmKSB7XG4gICAgICBsZXQge1xuICAgICAgICBzd2lwZXIsXG4gICAgICAgIGV4dGVuZFBhcmFtcyxcbiAgICAgICAgb24sXG4gICAgICAgIGVtaXRcbiAgICAgIH0gPSBfcmVmO1xuICAgICAgZXh0ZW5kUGFyYW1zKHtcbiAgICAgICAgbGF6eToge1xuICAgICAgICAgIGNoZWNrSW5WaWV3OiBmYWxzZSxcbiAgICAgICAgICBlbmFibGVkOiBmYWxzZSxcbiAgICAgICAgICBsb2FkUHJldk5leHQ6IGZhbHNlLFxuICAgICAgICAgIGxvYWRQcmV2TmV4dEFtb3VudDogMSxcbiAgICAgICAgICBsb2FkT25UcmFuc2l0aW9uU3RhcnQ6IGZhbHNlLFxuICAgICAgICAgIHNjcm9sbGluZ0VsZW1lbnQ6ICcnLFxuICAgICAgICAgIGVsZW1lbnRDbGFzczogJ3N3aXBlci1sYXp5JyxcbiAgICAgICAgICBsb2FkaW5nQ2xhc3M6ICdzd2lwZXItbGF6eS1sb2FkaW5nJyxcbiAgICAgICAgICBsb2FkZWRDbGFzczogJ3N3aXBlci1sYXp5LWxvYWRlZCcsXG4gICAgICAgICAgcHJlbG9hZGVyQ2xhc3M6ICdzd2lwZXItbGF6eS1wcmVsb2FkZXInXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc3dpcGVyLmxhenkgPSB7fTtcbiAgICAgIGxldCBzY3JvbGxIYW5kbGVyQXR0YWNoZWQgPSBmYWxzZTtcbiAgICAgIGxldCBpbml0aWFsSW1hZ2VMb2FkZWQgPSBmYWxzZTtcblxuICAgICAgZnVuY3Rpb24gbG9hZEluU2xpZGUoaW5kZXgsIGxvYWRJbkR1cGxpY2F0ZSkge1xuICAgICAgICBpZiAobG9hZEluRHVwbGljYXRlID09PSB2b2lkIDApIHtcbiAgICAgICAgICBsb2FkSW5EdXBsaWNhdGUgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy5sYXp5O1xuICAgICAgICBpZiAodHlwZW9mIGluZGV4ID09PSAndW5kZWZpbmVkJykgcmV0dXJuO1xuICAgICAgICBpZiAoc3dpcGVyLnNsaWRlcy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICAgICAgY29uc3QgaXNWaXJ0dWFsID0gc3dpcGVyLnZpcnR1YWwgJiYgc3dpcGVyLnBhcmFtcy52aXJ0dWFsLmVuYWJsZWQ7XG4gICAgICAgIGNvbnN0ICRzbGlkZUVsID0gaXNWaXJ0dWFsID8gc3dpcGVyLiR3cmFwcGVyRWwuY2hpbGRyZW4oYC4ke3N3aXBlci5wYXJhbXMuc2xpZGVDbGFzc31bZGF0YS1zd2lwZXItc2xpZGUtaW5kZXg9XCIke2luZGV4fVwiXWApIDogc3dpcGVyLnNsaWRlcy5lcShpbmRleCk7XG4gICAgICAgIGNvbnN0ICRpbWFnZXMgPSAkc2xpZGVFbC5maW5kKGAuJHtwYXJhbXMuZWxlbWVudENsYXNzfTpub3QoLiR7cGFyYW1zLmxvYWRlZENsYXNzfSk6bm90KC4ke3BhcmFtcy5sb2FkaW5nQ2xhc3N9KWApO1xuXG4gICAgICAgIGlmICgkc2xpZGVFbC5oYXNDbGFzcyhwYXJhbXMuZWxlbWVudENsYXNzKSAmJiAhJHNsaWRlRWwuaGFzQ2xhc3MocGFyYW1zLmxvYWRlZENsYXNzKSAmJiAhJHNsaWRlRWwuaGFzQ2xhc3MocGFyYW1zLmxvYWRpbmdDbGFzcykpIHtcbiAgICAgICAgICAkaW1hZ2VzLnB1c2goJHNsaWRlRWxbMF0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCRpbWFnZXMubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgICAgICRpbWFnZXMuZWFjaChpbWFnZUVsID0+IHtcbiAgICAgICAgICBjb25zdCAkaW1hZ2VFbCA9ICQoaW1hZ2VFbCk7XG4gICAgICAgICAgJGltYWdlRWwuYWRkQ2xhc3MocGFyYW1zLmxvYWRpbmdDbGFzcyk7XG4gICAgICAgICAgY29uc3QgYmFja2dyb3VuZCA9ICRpbWFnZUVsLmF0dHIoJ2RhdGEtYmFja2dyb3VuZCcpO1xuICAgICAgICAgIGNvbnN0IHNyYyA9ICRpbWFnZUVsLmF0dHIoJ2RhdGEtc3JjJyk7XG4gICAgICAgICAgY29uc3Qgc3Jjc2V0ID0gJGltYWdlRWwuYXR0cignZGF0YS1zcmNzZXQnKTtcbiAgICAgICAgICBjb25zdCBzaXplcyA9ICRpbWFnZUVsLmF0dHIoJ2RhdGEtc2l6ZXMnKTtcbiAgICAgICAgICBjb25zdCAkcGljdHVyZUVsID0gJGltYWdlRWwucGFyZW50KCdwaWN0dXJlJyk7XG4gICAgICAgICAgc3dpcGVyLmxvYWRJbWFnZSgkaW1hZ2VFbFswXSwgc3JjIHx8IGJhY2tncm91bmQsIHNyY3NldCwgc2l6ZXMsIGZhbHNlLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHN3aXBlciA9PT0gJ3VuZGVmaW5lZCcgfHwgc3dpcGVyID09PSBudWxsIHx8ICFzd2lwZXIgfHwgc3dpcGVyICYmICFzd2lwZXIucGFyYW1zIHx8IHN3aXBlci5kZXN0cm95ZWQpIHJldHVybjtcblxuICAgICAgICAgICAgaWYgKGJhY2tncm91bmQpIHtcbiAgICAgICAgICAgICAgJGltYWdlRWwuY3NzKCdiYWNrZ3JvdW5kLWltYWdlJywgYHVybChcIiR7YmFja2dyb3VuZH1cIilgKTtcbiAgICAgICAgICAgICAgJGltYWdlRWwucmVtb3ZlQXR0cignZGF0YS1iYWNrZ3JvdW5kJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAoc3Jjc2V0KSB7XG4gICAgICAgICAgICAgICAgJGltYWdlRWwuYXR0cignc3Jjc2V0Jywgc3Jjc2V0KTtcbiAgICAgICAgICAgICAgICAkaW1hZ2VFbC5yZW1vdmVBdHRyKCdkYXRhLXNyY3NldCcpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKHNpemVzKSB7XG4gICAgICAgICAgICAgICAgJGltYWdlRWwuYXR0cignc2l6ZXMnLCBzaXplcyk7XG4gICAgICAgICAgICAgICAgJGltYWdlRWwucmVtb3ZlQXR0cignZGF0YS1zaXplcycpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKCRwaWN0dXJlRWwubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgJHBpY3R1cmVFbC5jaGlsZHJlbignc291cmNlJykuZWFjaChzb3VyY2VFbCA9PiB7XG4gICAgICAgICAgICAgICAgICBjb25zdCAkc291cmNlID0gJChzb3VyY2VFbCk7XG5cbiAgICAgICAgICAgICAgICAgIGlmICgkc291cmNlLmF0dHIoJ2RhdGEtc3Jjc2V0JykpIHtcbiAgICAgICAgICAgICAgICAgICAgJHNvdXJjZS5hdHRyKCdzcmNzZXQnLCAkc291cmNlLmF0dHIoJ2RhdGEtc3Jjc2V0JykpO1xuICAgICAgICAgICAgICAgICAgICAkc291cmNlLnJlbW92ZUF0dHIoJ2RhdGEtc3Jjc2V0Jyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBpZiAoc3JjKSB7XG4gICAgICAgICAgICAgICAgJGltYWdlRWwuYXR0cignc3JjJywgc3JjKTtcbiAgICAgICAgICAgICAgICAkaW1hZ2VFbC5yZW1vdmVBdHRyKCdkYXRhLXNyYycpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICRpbWFnZUVsLmFkZENsYXNzKHBhcmFtcy5sb2FkZWRDbGFzcykucmVtb3ZlQ2xhc3MocGFyYW1zLmxvYWRpbmdDbGFzcyk7XG4gICAgICAgICAgICAkc2xpZGVFbC5maW5kKGAuJHtwYXJhbXMucHJlbG9hZGVyQ2xhc3N9YCkucmVtb3ZlKCk7XG5cbiAgICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmxvb3AgJiYgbG9hZEluRHVwbGljYXRlKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHNsaWRlT3JpZ2luYWxJbmRleCA9ICRzbGlkZUVsLmF0dHIoJ2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4Jyk7XG5cbiAgICAgICAgICAgICAgaWYgKCRzbGlkZUVsLmhhc0NsYXNzKHN3aXBlci5wYXJhbXMuc2xpZGVEdXBsaWNhdGVDbGFzcykpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvcmlnaW5hbFNsaWRlID0gc3dpcGVyLiR3cmFwcGVyRWwuY2hpbGRyZW4oYFtkYXRhLXN3aXBlci1zbGlkZS1pbmRleD1cIiR7c2xpZGVPcmlnaW5hbEluZGV4fVwiXTpub3QoLiR7c3dpcGVyLnBhcmFtcy5zbGlkZUR1cGxpY2F0ZUNsYXNzfSlgKTtcbiAgICAgICAgICAgICAgICBsb2FkSW5TbGlkZShvcmlnaW5hbFNsaWRlLmluZGV4KCksIGZhbHNlKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkdXBsaWNhdGVkU2xpZGUgPSBzd2lwZXIuJHdyYXBwZXJFbC5jaGlsZHJlbihgLiR7c3dpcGVyLnBhcmFtcy5zbGlkZUR1cGxpY2F0ZUNsYXNzfVtkYXRhLXN3aXBlci1zbGlkZS1pbmRleD1cIiR7c2xpZGVPcmlnaW5hbEluZGV4fVwiXWApO1xuICAgICAgICAgICAgICAgIGxvYWRJblNsaWRlKGR1cGxpY2F0ZWRTbGlkZS5pbmRleCgpLCBmYWxzZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZW1pdCgnbGF6eUltYWdlUmVhZHknLCAkc2xpZGVFbFswXSwgJGltYWdlRWxbMF0pO1xuXG4gICAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5hdXRvSGVpZ2h0KSB7XG4gICAgICAgICAgICAgIHN3aXBlci51cGRhdGVBdXRvSGVpZ2h0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgZW1pdCgnbGF6eUltYWdlTG9hZCcsICRzbGlkZUVsWzBdLCAkaW1hZ2VFbFswXSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBsb2FkKCkge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgJHdyYXBwZXJFbCxcbiAgICAgICAgICBwYXJhbXM6IHN3aXBlclBhcmFtcyxcbiAgICAgICAgICBzbGlkZXMsXG4gICAgICAgICAgYWN0aXZlSW5kZXhcbiAgICAgICAgfSA9IHN3aXBlcjtcbiAgICAgICAgY29uc3QgaXNWaXJ0dWFsID0gc3dpcGVyLnZpcnR1YWwgJiYgc3dpcGVyUGFyYW1zLnZpcnR1YWwuZW5hYmxlZDtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyUGFyYW1zLmxhenk7XG4gICAgICAgIGxldCBzbGlkZXNQZXJWaWV3ID0gc3dpcGVyUGFyYW1zLnNsaWRlc1BlclZpZXc7XG5cbiAgICAgICAgaWYgKHNsaWRlc1BlclZpZXcgPT09ICdhdXRvJykge1xuICAgICAgICAgIHNsaWRlc1BlclZpZXcgPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gc2xpZGVFeGlzdChpbmRleCkge1xuICAgICAgICAgIGlmIChpc1ZpcnR1YWwpIHtcbiAgICAgICAgICAgIGlmICgkd3JhcHBlckVsLmNoaWxkcmVuKGAuJHtzd2lwZXJQYXJhbXMuc2xpZGVDbGFzc31bZGF0YS1zd2lwZXItc2xpZGUtaW5kZXg9XCIke2luZGV4fVwiXWApLmxlbmd0aCkge1xuICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKHNsaWRlc1tpbmRleF0pIHJldHVybiB0cnVlO1xuXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gc2xpZGVJbmRleChzbGlkZUVsKSB7XG4gICAgICAgICAgaWYgKGlzVmlydHVhbCkge1xuICAgICAgICAgICAgcmV0dXJuICQoc2xpZGVFbCkuYXR0cignZGF0YS1zd2lwZXItc2xpZGUtaW5kZXgnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gJChzbGlkZUVsKS5pbmRleCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFpbml0aWFsSW1hZ2VMb2FkZWQpIGluaXRpYWxJbWFnZUxvYWRlZCA9IHRydWU7XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMud2F0Y2hTbGlkZXNQcm9ncmVzcykge1xuICAgICAgICAgICR3cmFwcGVyRWwuY2hpbGRyZW4oYC4ke3N3aXBlclBhcmFtcy5zbGlkZVZpc2libGVDbGFzc31gKS5lYWNoKHNsaWRlRWwgPT4ge1xuICAgICAgICAgICAgY29uc3QgaW5kZXggPSBpc1ZpcnR1YWwgPyAkKHNsaWRlRWwpLmF0dHIoJ2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4JykgOiAkKHNsaWRlRWwpLmluZGV4KCk7XG4gICAgICAgICAgICBsb2FkSW5TbGlkZShpbmRleCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoc2xpZGVzUGVyVmlldyA+IDEpIHtcbiAgICAgICAgICBmb3IgKGxldCBpID0gYWN0aXZlSW5kZXg7IGkgPCBhY3RpdmVJbmRleCArIHNsaWRlc1BlclZpZXc7IGkgKz0gMSkge1xuICAgICAgICAgICAgaWYgKHNsaWRlRXhpc3QoaSkpIGxvYWRJblNsaWRlKGkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsb2FkSW5TbGlkZShhY3RpdmVJbmRleCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLmxvYWRQcmV2TmV4dCkge1xuICAgICAgICAgIGlmIChzbGlkZXNQZXJWaWV3ID4gMSB8fCBwYXJhbXMubG9hZFByZXZOZXh0QW1vdW50ICYmIHBhcmFtcy5sb2FkUHJldk5leHRBbW91bnQgPiAxKSB7XG4gICAgICAgICAgICBjb25zdCBhbW91bnQgPSBwYXJhbXMubG9hZFByZXZOZXh0QW1vdW50O1xuICAgICAgICAgICAgY29uc3Qgc3B2ID0gc2xpZGVzUGVyVmlldztcbiAgICAgICAgICAgIGNvbnN0IG1heEluZGV4ID0gTWF0aC5taW4oYWN0aXZlSW5kZXggKyBzcHYgKyBNYXRoLm1heChhbW91bnQsIHNwdiksIHNsaWRlcy5sZW5ndGgpO1xuICAgICAgICAgICAgY29uc3QgbWluSW5kZXggPSBNYXRoLm1heChhY3RpdmVJbmRleCAtIE1hdGgubWF4KHNwdiwgYW1vdW50KSwgMCk7IC8vIE5leHQgU2xpZGVzXG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBhY3RpdmVJbmRleCArIHNsaWRlc1BlclZpZXc7IGkgPCBtYXhJbmRleDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgIGlmIChzbGlkZUV4aXN0KGkpKSBsb2FkSW5TbGlkZShpKTtcbiAgICAgICAgICAgIH0gLy8gUHJldiBTbGlkZXNcblxuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gbWluSW5kZXg7IGkgPCBhY3RpdmVJbmRleDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgIGlmIChzbGlkZUV4aXN0KGkpKSBsb2FkSW5TbGlkZShpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbmV4dFNsaWRlID0gJHdyYXBwZXJFbC5jaGlsZHJlbihgLiR7c3dpcGVyUGFyYW1zLnNsaWRlTmV4dENsYXNzfWApO1xuICAgICAgICAgICAgaWYgKG5leHRTbGlkZS5sZW5ndGggPiAwKSBsb2FkSW5TbGlkZShzbGlkZUluZGV4KG5leHRTbGlkZSkpO1xuICAgICAgICAgICAgY29uc3QgcHJldlNsaWRlID0gJHdyYXBwZXJFbC5jaGlsZHJlbihgLiR7c3dpcGVyUGFyYW1zLnNsaWRlUHJldkNsYXNzfWApO1xuICAgICAgICAgICAgaWYgKHByZXZTbGlkZS5sZW5ndGggPiAwKSBsb2FkSW5TbGlkZShzbGlkZUluZGV4KHByZXZTbGlkZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBjaGVja0luVmlld09uTG9hZCgpIHtcbiAgICAgICAgY29uc3Qgd2luZG93ID0gZ2V0V2luZG93KCk7XG4gICAgICAgIGlmICghc3dpcGVyIHx8IHN3aXBlci5kZXN0cm95ZWQpIHJldHVybjtcbiAgICAgICAgY29uc3QgJHNjcm9sbEVsZW1lbnQgPSBzd2lwZXIucGFyYW1zLmxhenkuc2Nyb2xsaW5nRWxlbWVudCA/ICQoc3dpcGVyLnBhcmFtcy5sYXp5LnNjcm9sbGluZ0VsZW1lbnQpIDogJCh3aW5kb3cpO1xuICAgICAgICBjb25zdCBpc1dpbmRvdyA9ICRzY3JvbGxFbGVtZW50WzBdID09PSB3aW5kb3c7XG4gICAgICAgIGNvbnN0IHNjcm9sbEVsZW1lbnRXaWR0aCA9IGlzV2luZG93ID8gd2luZG93LmlubmVyV2lkdGggOiAkc2Nyb2xsRWxlbWVudFswXS5vZmZzZXRXaWR0aDtcbiAgICAgICAgY29uc3Qgc2Nyb2xsRWxlbWVudEhlaWdodCA9IGlzV2luZG93ID8gd2luZG93LmlubmVySGVpZ2h0IDogJHNjcm9sbEVsZW1lbnRbMF0ub2Zmc2V0SGVpZ2h0O1xuICAgICAgICBjb25zdCBzd2lwZXJPZmZzZXQgPSBzd2lwZXIuJGVsLm9mZnNldCgpO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgcnRsVHJhbnNsYXRlOiBydGxcbiAgICAgICAgfSA9IHN3aXBlcjtcbiAgICAgICAgbGV0IGluVmlldyA9IGZhbHNlO1xuICAgICAgICBpZiAocnRsKSBzd2lwZXJPZmZzZXQubGVmdCAtPSBzd2lwZXIuJGVsWzBdLnNjcm9sbExlZnQ7XG4gICAgICAgIGNvbnN0IHN3aXBlckNvb3JkID0gW1tzd2lwZXJPZmZzZXQubGVmdCwgc3dpcGVyT2Zmc2V0LnRvcF0sIFtzd2lwZXJPZmZzZXQubGVmdCArIHN3aXBlci53aWR0aCwgc3dpcGVyT2Zmc2V0LnRvcF0sIFtzd2lwZXJPZmZzZXQubGVmdCwgc3dpcGVyT2Zmc2V0LnRvcCArIHN3aXBlci5oZWlnaHRdLCBbc3dpcGVyT2Zmc2V0LmxlZnQgKyBzd2lwZXIud2lkdGgsIHN3aXBlck9mZnNldC50b3AgKyBzd2lwZXIuaGVpZ2h0XV07XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzd2lwZXJDb29yZC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgIGNvbnN0IHBvaW50ID0gc3dpcGVyQ29vcmRbaV07XG5cbiAgICAgICAgICBpZiAocG9pbnRbMF0gPj0gMCAmJiBwb2ludFswXSA8PSBzY3JvbGxFbGVtZW50V2lkdGggJiYgcG9pbnRbMV0gPj0gMCAmJiBwb2ludFsxXSA8PSBzY3JvbGxFbGVtZW50SGVpZ2h0KSB7XG4gICAgICAgICAgICBpZiAocG9pbnRbMF0gPT09IDAgJiYgcG9pbnRbMV0gPT09IDApIGNvbnRpbnVlOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cbiAgICAgICAgICAgIGluVmlldyA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcGFzc2l2ZUxpc3RlbmVyID0gc3dpcGVyLnRvdWNoRXZlbnRzLnN0YXJ0ID09PSAndG91Y2hzdGFydCcgJiYgc3dpcGVyLnN1cHBvcnQucGFzc2l2ZUxpc3RlbmVyICYmIHN3aXBlci5wYXJhbXMucGFzc2l2ZUxpc3RlbmVycyA/IHtcbiAgICAgICAgICBwYXNzaXZlOiB0cnVlLFxuICAgICAgICAgIGNhcHR1cmU6IGZhbHNlXG4gICAgICAgIH0gOiBmYWxzZTtcblxuICAgICAgICBpZiAoaW5WaWV3KSB7XG4gICAgICAgICAgbG9hZCgpO1xuICAgICAgICAgICRzY3JvbGxFbGVtZW50Lm9mZignc2Nyb2xsJywgY2hlY2tJblZpZXdPbkxvYWQsIHBhc3NpdmVMaXN0ZW5lcik7XG4gICAgICAgIH0gZWxzZSBpZiAoIXNjcm9sbEhhbmRsZXJBdHRhY2hlZCkge1xuICAgICAgICAgIHNjcm9sbEhhbmRsZXJBdHRhY2hlZCA9IHRydWU7XG4gICAgICAgICAgJHNjcm9sbEVsZW1lbnQub24oJ3Njcm9sbCcsIGNoZWNrSW5WaWV3T25Mb2FkLCBwYXNzaXZlTGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG9uKCdiZWZvcmVJbml0JywgKCkgPT4ge1xuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5sYXp5LmVuYWJsZWQgJiYgc3dpcGVyLnBhcmFtcy5wcmVsb2FkSW1hZ2VzKSB7XG4gICAgICAgICAgc3dpcGVyLnBhcmFtcy5wcmVsb2FkSW1hZ2VzID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb24oJ2luaXQnLCAoKSA9PiB7XG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmxhenkuZW5hYmxlZCkge1xuICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmxhenkuY2hlY2tJblZpZXcpIHtcbiAgICAgICAgICAgIGNoZWNrSW5WaWV3T25Mb2FkKCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvYWQoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb24oJ3Njcm9sbCcsICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuZnJlZU1vZGUgJiYgc3dpcGVyLnBhcmFtcy5mcmVlTW9kZS5lbmFibGVkICYmICFzd2lwZXIucGFyYW1zLmZyZWVNb2RlLnN0aWNreSkge1xuICAgICAgICAgIGxvYWQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBvbignc2Nyb2xsYmFyRHJhZ01vdmUgcmVzaXplIF9mcmVlTW9kZU5vTW9tZW50dW1SZWxlYXNlJywgKCkgPT4ge1xuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5sYXp5LmVuYWJsZWQpIHtcbiAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5sYXp5LmNoZWNrSW5WaWV3KSB7XG4gICAgICAgICAgICBjaGVja0luVmlld09uTG9hZCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2FkKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIG9uKCd0cmFuc2l0aW9uU3RhcnQnLCAoKSA9PiB7XG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmxhenkuZW5hYmxlZCkge1xuICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmxhenkubG9hZE9uVHJhbnNpdGlvblN0YXJ0IHx8ICFzd2lwZXIucGFyYW1zLmxhenkubG9hZE9uVHJhbnNpdGlvblN0YXJ0ICYmICFpbml0aWFsSW1hZ2VMb2FkZWQpIHtcbiAgICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmxhenkuY2hlY2tJblZpZXcpIHtcbiAgICAgICAgICAgICAgY2hlY2tJblZpZXdPbkxvYWQoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGxvYWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb24oJ3RyYW5zaXRpb25FbmQnLCAoKSA9PiB7XG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmxhenkuZW5hYmxlZCAmJiAhc3dpcGVyLnBhcmFtcy5sYXp5LmxvYWRPblRyYW5zaXRpb25TdGFydCkge1xuICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmxhenkuY2hlY2tJblZpZXcpIHtcbiAgICAgICAgICAgIGNoZWNrSW5WaWV3T25Mb2FkKCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvYWQoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb24oJ3NsaWRlQ2hhbmdlJywgKCkgPT4ge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgbGF6eSxcbiAgICAgICAgICBjc3NNb2RlLFxuICAgICAgICAgIHdhdGNoU2xpZGVzUHJvZ3Jlc3MsXG4gICAgICAgICAgdG91Y2hSZWxlYXNlT25FZGdlcyxcbiAgICAgICAgICByZXNpc3RhbmNlUmF0aW9cbiAgICAgICAgfSA9IHN3aXBlci5wYXJhbXM7XG5cbiAgICAgICAgaWYgKGxhenkuZW5hYmxlZCAmJiAoY3NzTW9kZSB8fCB3YXRjaFNsaWRlc1Byb2dyZXNzICYmICh0b3VjaFJlbGVhc2VPbkVkZ2VzIHx8IHJlc2lzdGFuY2VSYXRpbyA9PT0gMCkpKSB7XG4gICAgICAgICAgbG9hZCgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIE9iamVjdC5hc3NpZ24oc3dpcGVyLmxhenksIHtcbiAgICAgICAgbG9hZCxcbiAgICAgICAgbG9hZEluU2xpZGVcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qIGVzbGludCBuby1iaXR3aXNlOiBbXCJlcnJvclwiLCB7IFwiYWxsb3dcIjogW1wiPj5cIl0gfV0gKi9cbiAgICBmdW5jdGlvbiBDb250cm9sbGVyKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZXh0ZW5kUGFyYW1zLFxuICAgICAgICBvblxuICAgICAgfSA9IF9yZWY7XG4gICAgICBleHRlbmRQYXJhbXMoe1xuICAgICAgICBjb250cm9sbGVyOiB7XG4gICAgICAgICAgY29udHJvbDogdW5kZWZpbmVkLFxuICAgICAgICAgIGludmVyc2U6IGZhbHNlLFxuICAgICAgICAgIGJ5OiAnc2xpZGUnIC8vIG9yICdjb250YWluZXInXG5cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzd2lwZXIuY29udHJvbGxlciA9IHtcbiAgICAgICAgY29udHJvbDogdW5kZWZpbmVkXG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiBMaW5lYXJTcGxpbmUoeCwgeSkge1xuICAgICAgICBjb25zdCBiaW5hcnlTZWFyY2ggPSBmdW5jdGlvbiBzZWFyY2goKSB7XG4gICAgICAgICAgbGV0IG1heEluZGV4O1xuICAgICAgICAgIGxldCBtaW5JbmRleDtcbiAgICAgICAgICBsZXQgZ3Vlc3M7XG4gICAgICAgICAgcmV0dXJuIChhcnJheSwgdmFsKSA9PiB7XG4gICAgICAgICAgICBtaW5JbmRleCA9IC0xO1xuICAgICAgICAgICAgbWF4SW5kZXggPSBhcnJheS5sZW5ndGg7XG5cbiAgICAgICAgICAgIHdoaWxlIChtYXhJbmRleCAtIG1pbkluZGV4ID4gMSkge1xuICAgICAgICAgICAgICBndWVzcyA9IG1heEluZGV4ICsgbWluSW5kZXggPj4gMTtcblxuICAgICAgICAgICAgICBpZiAoYXJyYXlbZ3Vlc3NdIDw9IHZhbCkge1xuICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gZ3Vlc3M7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbWF4SW5kZXggPSBndWVzcztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gbWF4SW5kZXg7XG4gICAgICAgICAgfTtcbiAgICAgICAgfSgpO1xuXG4gICAgICAgIHRoaXMueCA9IHg7XG4gICAgICAgIHRoaXMueSA9IHk7XG4gICAgICAgIHRoaXMubGFzdEluZGV4ID0geC5sZW5ndGggLSAxOyAvLyBHaXZlbiBhbiB4IHZhbHVlICh4MiksIHJldHVybiB0aGUgZXhwZWN0ZWQgeTIgdmFsdWU6XG4gICAgICAgIC8vICh4MSx5MSkgaXMgdGhlIGtub3duIHBvaW50IGJlZm9yZSBnaXZlbiB2YWx1ZSxcbiAgICAgICAgLy8gKHgzLHkzKSBpcyB0aGUga25vd24gcG9pbnQgYWZ0ZXIgZ2l2ZW4gdmFsdWUuXG5cbiAgICAgICAgbGV0IGkxO1xuICAgICAgICBsZXQgaTM7XG5cbiAgICAgICAgdGhpcy5pbnRlcnBvbGF0ZSA9IGZ1bmN0aW9uIGludGVycG9sYXRlKHgyKSB7XG4gICAgICAgICAgaWYgKCF4MikgcmV0dXJuIDA7IC8vIEdldCB0aGUgaW5kZXhlcyBvZiB4MSBhbmQgeDMgKHRoZSBhcnJheSBpbmRleGVzIGJlZm9yZSBhbmQgYWZ0ZXIgZ2l2ZW4geDIpOlxuXG4gICAgICAgICAgaTMgPSBiaW5hcnlTZWFyY2godGhpcy54LCB4Mik7XG4gICAgICAgICAgaTEgPSBpMyAtIDE7IC8vIFdlIGhhdmUgb3VyIGluZGV4ZXMgaTEgJiBpMywgc28gd2UgY2FuIGNhbGN1bGF0ZSBhbHJlYWR5OlxuICAgICAgICAgIC8vIHkyIDo9ICgoeDLiiJJ4MSkgw5cgKHkz4oiSeTEpKSDDtyAoeDPiiJJ4MSkgKyB5MVxuXG4gICAgICAgICAgcmV0dXJuICh4MiAtIHRoaXMueFtpMV0pICogKHRoaXMueVtpM10gLSB0aGlzLnlbaTFdKSAvICh0aGlzLnhbaTNdIC0gdGhpcy54W2kxXSkgKyB0aGlzLnlbaTFdO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfSAvLyB4eHg6IGZvciBub3cgaSB3aWxsIGp1c3Qgc2F2ZSBvbmUgc3BsaW5lIGZ1bmN0aW9uIHRvIHRvXG5cblxuICAgICAgZnVuY3Rpb24gZ2V0SW50ZXJwb2xhdGVGdW5jdGlvbihjKSB7XG4gICAgICAgIGlmICghc3dpcGVyLmNvbnRyb2xsZXIuc3BsaW5lKSB7XG4gICAgICAgICAgc3dpcGVyLmNvbnRyb2xsZXIuc3BsaW5lID0gc3dpcGVyLnBhcmFtcy5sb29wID8gbmV3IExpbmVhclNwbGluZShzd2lwZXIuc2xpZGVzR3JpZCwgYy5zbGlkZXNHcmlkKSA6IG5ldyBMaW5lYXJTcGxpbmUoc3dpcGVyLnNuYXBHcmlkLCBjLnNuYXBHcmlkKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBzZXRUcmFuc2xhdGUoX3QsIGJ5Q29udHJvbGxlcikge1xuICAgICAgICBjb25zdCBjb250cm9sbGVkID0gc3dpcGVyLmNvbnRyb2xsZXIuY29udHJvbDtcbiAgICAgICAgbGV0IG11bHRpcGxpZXI7XG4gICAgICAgIGxldCBjb250cm9sbGVkVHJhbnNsYXRlO1xuICAgICAgICBjb25zdCBTd2lwZXIgPSBzd2lwZXIuY29uc3RydWN0b3I7XG5cbiAgICAgICAgZnVuY3Rpb24gc2V0Q29udHJvbGxlZFRyYW5zbGF0ZShjKSB7XG4gICAgICAgICAgLy8gdGhpcyB3aWxsIGNyZWF0ZSBhbiBJbnRlcnBvbGF0ZSBmdW5jdGlvbiBiYXNlZCBvbiB0aGUgc25hcEdyaWRzXG4gICAgICAgICAgLy8geCBpcyB0aGUgR3JpZCBvZiB0aGUgc2Nyb2xsZWQgc2Nyb2xsZXIgYW5kIHkgd2lsbCBiZSB0aGUgY29udHJvbGxlZCBzY3JvbGxlclxuICAgICAgICAgIC8vIGl0IG1ha2VzIHNlbnNlIHRvIGNyZWF0ZSB0aGlzIG9ubHkgb25jZSBhbmQgcmVjYWxsIGl0IGZvciB0aGUgaW50ZXJwb2xhdGlvblxuICAgICAgICAgIC8vIHRoZSBmdW5jdGlvbiBkb2VzIGEgbG90IG9mIHZhbHVlIGNhY2hpbmcgZm9yIHBlcmZvcm1hbmNlXG4gICAgICAgICAgY29uc3QgdHJhbnNsYXRlID0gc3dpcGVyLnJ0bFRyYW5zbGF0ZSA/IC1zd2lwZXIudHJhbnNsYXRlIDogc3dpcGVyLnRyYW5zbGF0ZTtcblxuICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmNvbnRyb2xsZXIuYnkgPT09ICdzbGlkZScpIHtcbiAgICAgICAgICAgIGdldEludGVycG9sYXRlRnVuY3Rpb24oYyk7IC8vIGkgYW0gbm90IHN1cmUgd2h5IHRoZSB2YWx1ZXMgaGF2ZSB0byBiZSBtdWx0aXBsaWNhdGVkIHRoaXMgd2F5LCB0cmllZCB0byBpbnZlcnQgdGhlIHNuYXBHcmlkXG4gICAgICAgICAgICAvLyBidXQgaXQgZGlkIG5vdCB3b3JrIG91dFxuXG4gICAgICAgICAgICBjb250cm9sbGVkVHJhbnNsYXRlID0gLXN3aXBlci5jb250cm9sbGVyLnNwbGluZS5pbnRlcnBvbGF0ZSgtdHJhbnNsYXRlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIWNvbnRyb2xsZWRUcmFuc2xhdGUgfHwgc3dpcGVyLnBhcmFtcy5jb250cm9sbGVyLmJ5ID09PSAnY29udGFpbmVyJykge1xuICAgICAgICAgICAgbXVsdGlwbGllciA9IChjLm1heFRyYW5zbGF0ZSgpIC0gYy5taW5UcmFuc2xhdGUoKSkgLyAoc3dpcGVyLm1heFRyYW5zbGF0ZSgpIC0gc3dpcGVyLm1pblRyYW5zbGF0ZSgpKTtcbiAgICAgICAgICAgIGNvbnRyb2xsZWRUcmFuc2xhdGUgPSAodHJhbnNsYXRlIC0gc3dpcGVyLm1pblRyYW5zbGF0ZSgpKSAqIG11bHRpcGxpZXIgKyBjLm1pblRyYW5zbGF0ZSgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmNvbnRyb2xsZXIuaW52ZXJzZSkge1xuICAgICAgICAgICAgY29udHJvbGxlZFRyYW5zbGF0ZSA9IGMubWF4VHJhbnNsYXRlKCkgLSBjb250cm9sbGVkVHJhbnNsYXRlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGMudXBkYXRlUHJvZ3Jlc3MoY29udHJvbGxlZFRyYW5zbGF0ZSk7XG4gICAgICAgICAgYy5zZXRUcmFuc2xhdGUoY29udHJvbGxlZFRyYW5zbGF0ZSwgc3dpcGVyKTtcbiAgICAgICAgICBjLnVwZGF0ZUFjdGl2ZUluZGV4KCk7XG4gICAgICAgICAgYy51cGRhdGVTbGlkZXNDbGFzc2VzKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjb250cm9sbGVkKSkge1xuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29udHJvbGxlZC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgaWYgKGNvbnRyb2xsZWRbaV0gIT09IGJ5Q29udHJvbGxlciAmJiBjb250cm9sbGVkW2ldIGluc3RhbmNlb2YgU3dpcGVyKSB7XG4gICAgICAgICAgICAgIHNldENvbnRyb2xsZWRUcmFuc2xhdGUoY29udHJvbGxlZFtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGNvbnRyb2xsZWQgaW5zdGFuY2VvZiBTd2lwZXIgJiYgYnlDb250cm9sbGVyICE9PSBjb250cm9sbGVkKSB7XG4gICAgICAgICAgc2V0Q29udHJvbGxlZFRyYW5zbGF0ZShjb250cm9sbGVkKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBzZXRUcmFuc2l0aW9uKGR1cmF0aW9uLCBieUNvbnRyb2xsZXIpIHtcbiAgICAgICAgY29uc3QgU3dpcGVyID0gc3dpcGVyLmNvbnN0cnVjdG9yO1xuICAgICAgICBjb25zdCBjb250cm9sbGVkID0gc3dpcGVyLmNvbnRyb2xsZXIuY29udHJvbDtcbiAgICAgICAgbGV0IGk7XG5cbiAgICAgICAgZnVuY3Rpb24gc2V0Q29udHJvbGxlZFRyYW5zaXRpb24oYykge1xuICAgICAgICAgIGMuc2V0VHJhbnNpdGlvbihkdXJhdGlvbiwgc3dpcGVyKTtcblxuICAgICAgICAgIGlmIChkdXJhdGlvbiAhPT0gMCkge1xuICAgICAgICAgICAgYy50cmFuc2l0aW9uU3RhcnQoKTtcblxuICAgICAgICAgICAgaWYgKGMucGFyYW1zLmF1dG9IZWlnaHQpIHtcbiAgICAgICAgICAgICAgbmV4dFRpY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgIGMudXBkYXRlQXV0b0hlaWdodCgpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYy4kd3JhcHBlckVsLnRyYW5zaXRpb25FbmQoKCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoIWNvbnRyb2xsZWQpIHJldHVybjtcblxuICAgICAgICAgICAgICBpZiAoYy5wYXJhbXMubG9vcCAmJiBzd2lwZXIucGFyYW1zLmNvbnRyb2xsZXIuYnkgPT09ICdzbGlkZScpIHtcbiAgICAgICAgICAgICAgICBjLmxvb3BGaXgoKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGMudHJhbnNpdGlvbkVuZCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29udHJvbGxlZCkpIHtcbiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29udHJvbGxlZC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgaWYgKGNvbnRyb2xsZWRbaV0gIT09IGJ5Q29udHJvbGxlciAmJiBjb250cm9sbGVkW2ldIGluc3RhbmNlb2YgU3dpcGVyKSB7XG4gICAgICAgICAgICAgIHNldENvbnRyb2xsZWRUcmFuc2l0aW9uKGNvbnRyb2xsZWRbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChjb250cm9sbGVkIGluc3RhbmNlb2YgU3dpcGVyICYmIGJ5Q29udHJvbGxlciAhPT0gY29udHJvbGxlZCkge1xuICAgICAgICAgIHNldENvbnRyb2xsZWRUcmFuc2l0aW9uKGNvbnRyb2xsZWQpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHJlbW92ZVNwbGluZSgpIHtcbiAgICAgICAgaWYgKCFzd2lwZXIuY29udHJvbGxlci5jb250cm9sKSByZXR1cm47XG5cbiAgICAgICAgaWYgKHN3aXBlci5jb250cm9sbGVyLnNwbGluZSkge1xuICAgICAgICAgIHN3aXBlci5jb250cm9sbGVyLnNwbGluZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICBkZWxldGUgc3dpcGVyLmNvbnRyb2xsZXIuc3BsaW5lO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG9uKCdiZWZvcmVJbml0JywgKCkgPT4ge1xuICAgICAgICBzd2lwZXIuY29udHJvbGxlci5jb250cm9sID0gc3dpcGVyLnBhcmFtcy5jb250cm9sbGVyLmNvbnRyb2w7XG4gICAgICB9KTtcbiAgICAgIG9uKCd1cGRhdGUnLCAoKSA9PiB7XG4gICAgICAgIHJlbW92ZVNwbGluZSgpO1xuICAgICAgfSk7XG4gICAgICBvbigncmVzaXplJywgKCkgPT4ge1xuICAgICAgICByZW1vdmVTcGxpbmUoKTtcbiAgICAgIH0pO1xuICAgICAgb24oJ29ic2VydmVyVXBkYXRlJywgKCkgPT4ge1xuICAgICAgICByZW1vdmVTcGxpbmUoKTtcbiAgICAgIH0pO1xuICAgICAgb24oJ3NldFRyYW5zbGF0ZScsIChfcywgdHJhbnNsYXRlLCBieUNvbnRyb2xsZXIpID0+IHtcbiAgICAgICAgaWYgKCFzd2lwZXIuY29udHJvbGxlci5jb250cm9sKSByZXR1cm47XG4gICAgICAgIHN3aXBlci5jb250cm9sbGVyLnNldFRyYW5zbGF0ZSh0cmFuc2xhdGUsIGJ5Q29udHJvbGxlcik7XG4gICAgICB9KTtcbiAgICAgIG9uKCdzZXRUcmFuc2l0aW9uJywgKF9zLCBkdXJhdGlvbiwgYnlDb250cm9sbGVyKSA9PiB7XG4gICAgICAgIGlmICghc3dpcGVyLmNvbnRyb2xsZXIuY29udHJvbCkgcmV0dXJuO1xuICAgICAgICBzd2lwZXIuY29udHJvbGxlci5zZXRUcmFuc2l0aW9uKGR1cmF0aW9uLCBieUNvbnRyb2xsZXIpO1xuICAgICAgfSk7XG4gICAgICBPYmplY3QuYXNzaWduKHN3aXBlci5jb250cm9sbGVyLCB7XG4gICAgICAgIHNldFRyYW5zbGF0ZSxcbiAgICAgICAgc2V0VHJhbnNpdGlvblxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gQTExeShfcmVmKSB7XG4gICAgICBsZXQge1xuICAgICAgICBzd2lwZXIsXG4gICAgICAgIGV4dGVuZFBhcmFtcyxcbiAgICAgICAgb25cbiAgICAgIH0gPSBfcmVmO1xuICAgICAgZXh0ZW5kUGFyYW1zKHtcbiAgICAgICAgYTExeToge1xuICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgbm90aWZpY2F0aW9uQ2xhc3M6ICdzd2lwZXItbm90aWZpY2F0aW9uJyxcbiAgICAgICAgICBwcmV2U2xpZGVNZXNzYWdlOiAnUHJldmlvdXMgc2xpZGUnLFxuICAgICAgICAgIG5leHRTbGlkZU1lc3NhZ2U6ICdOZXh0IHNsaWRlJyxcbiAgICAgICAgICBmaXJzdFNsaWRlTWVzc2FnZTogJ1RoaXMgaXMgdGhlIGZpcnN0IHNsaWRlJyxcbiAgICAgICAgICBsYXN0U2xpZGVNZXNzYWdlOiAnVGhpcyBpcyB0aGUgbGFzdCBzbGlkZScsXG4gICAgICAgICAgcGFnaW5hdGlvbkJ1bGxldE1lc3NhZ2U6ICdHbyB0byBzbGlkZSB7e2luZGV4fX0nLFxuICAgICAgICAgIHNsaWRlTGFiZWxNZXNzYWdlOiAne3tpbmRleH19IC8ge3tzbGlkZXNMZW5ndGh9fScsXG4gICAgICAgICAgY29udGFpbmVyTWVzc2FnZTogbnVsbCxcbiAgICAgICAgICBjb250YWluZXJSb2xlRGVzY3JpcHRpb25NZXNzYWdlOiBudWxsLFxuICAgICAgICAgIGl0ZW1Sb2xlRGVzY3JpcHRpb25NZXNzYWdlOiBudWxsLFxuICAgICAgICAgIHNsaWRlUm9sZTogJ2dyb3VwJ1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGxldCBsaXZlUmVnaW9uID0gbnVsbDtcblxuICAgICAgZnVuY3Rpb24gbm90aWZ5KG1lc3NhZ2UpIHtcbiAgICAgICAgY29uc3Qgbm90aWZpY2F0aW9uID0gbGl2ZVJlZ2lvbjtcbiAgICAgICAgaWYgKG5vdGlmaWNhdGlvbi5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICAgICAgbm90aWZpY2F0aW9uLmh0bWwoJycpO1xuICAgICAgICBub3RpZmljYXRpb24uaHRtbChtZXNzYWdlKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZ2V0UmFuZG9tTnVtYmVyKHNpemUpIHtcbiAgICAgICAgaWYgKHNpemUgPT09IHZvaWQgMCkge1xuICAgICAgICAgIHNpemUgPSAxNjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJhbmRvbUNoYXIgPSAoKSA9PiBNYXRoLnJvdW5kKDE2ICogTWF0aC5yYW5kb20oKSkudG9TdHJpbmcoMTYpO1xuXG4gICAgICAgIHJldHVybiAneCcucmVwZWF0KHNpemUpLnJlcGxhY2UoL3gvZywgcmFuZG9tQ2hhcik7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIG1ha2VFbEZvY3VzYWJsZSgkZWwpIHtcbiAgICAgICAgJGVsLmF0dHIoJ3RhYkluZGV4JywgJzAnKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gbWFrZUVsTm90Rm9jdXNhYmxlKCRlbCkge1xuICAgICAgICAkZWwuYXR0cigndGFiSW5kZXgnLCAnLTEnKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gYWRkRWxSb2xlKCRlbCwgcm9sZSkge1xuICAgICAgICAkZWwuYXR0cigncm9sZScsIHJvbGUpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBhZGRFbFJvbGVEZXNjcmlwdGlvbigkZWwsIGRlc2NyaXB0aW9uKSB7XG4gICAgICAgICRlbC5hdHRyKCdhcmlhLXJvbGVkZXNjcmlwdGlvbicsIGRlc2NyaXB0aW9uKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gYWRkRWxDb250cm9scygkZWwsIGNvbnRyb2xzKSB7XG4gICAgICAgICRlbC5hdHRyKCdhcmlhLWNvbnRyb2xzJywgY29udHJvbHMpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBhZGRFbExhYmVsKCRlbCwgbGFiZWwpIHtcbiAgICAgICAgJGVsLmF0dHIoJ2FyaWEtbGFiZWwnLCBsYWJlbCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGFkZEVsSWQoJGVsLCBpZCkge1xuICAgICAgICAkZWwuYXR0cignaWQnLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGFkZEVsTGl2ZSgkZWwsIGxpdmUpIHtcbiAgICAgICAgJGVsLmF0dHIoJ2FyaWEtbGl2ZScsIGxpdmUpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBkaXNhYmxlRWwoJGVsKSB7XG4gICAgICAgICRlbC5hdHRyKCdhcmlhLWRpc2FibGVkJywgdHJ1ZSk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGVuYWJsZUVsKCRlbCkge1xuICAgICAgICAkZWwuYXR0cignYXJpYS1kaXNhYmxlZCcsIGZhbHNlKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gb25FbnRlck9yU3BhY2VLZXkoZSkge1xuICAgICAgICBpZiAoZS5rZXlDb2RlICE9PSAxMyAmJiBlLmtleUNvZGUgIT09IDMyKSByZXR1cm47XG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHN3aXBlci5wYXJhbXMuYTExeTtcbiAgICAgICAgY29uc3QgJHRhcmdldEVsID0gJChlLnRhcmdldCk7XG5cbiAgICAgICAgaWYgKHN3aXBlci5uYXZpZ2F0aW9uICYmIHN3aXBlci5uYXZpZ2F0aW9uLiRuZXh0RWwgJiYgJHRhcmdldEVsLmlzKHN3aXBlci5uYXZpZ2F0aW9uLiRuZXh0RWwpKSB7XG4gICAgICAgICAgaWYgKCEoc3dpcGVyLmlzRW5kICYmICFzd2lwZXIucGFyYW1zLmxvb3ApKSB7XG4gICAgICAgICAgICBzd2lwZXIuc2xpZGVOZXh0KCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHN3aXBlci5pc0VuZCkge1xuICAgICAgICAgICAgbm90aWZ5KHBhcmFtcy5sYXN0U2xpZGVNZXNzYWdlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbm90aWZ5KHBhcmFtcy5uZXh0U2xpZGVNZXNzYWdlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3dpcGVyLm5hdmlnYXRpb24gJiYgc3dpcGVyLm5hdmlnYXRpb24uJHByZXZFbCAmJiAkdGFyZ2V0RWwuaXMoc3dpcGVyLm5hdmlnYXRpb24uJHByZXZFbCkpIHtcbiAgICAgICAgICBpZiAoIShzd2lwZXIuaXNCZWdpbm5pbmcgJiYgIXN3aXBlci5wYXJhbXMubG9vcCkpIHtcbiAgICAgICAgICAgIHN3aXBlci5zbGlkZVByZXYoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoc3dpcGVyLmlzQmVnaW5uaW5nKSB7XG4gICAgICAgICAgICBub3RpZnkocGFyYW1zLmZpcnN0U2xpZGVNZXNzYWdlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbm90aWZ5KHBhcmFtcy5wcmV2U2xpZGVNZXNzYWdlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3dpcGVyLnBhZ2luYXRpb24gJiYgJHRhcmdldEVsLmlzKGNsYXNzZXNUb1NlbGVjdG9yKHN3aXBlci5wYXJhbXMucGFnaW5hdGlvbi5idWxsZXRDbGFzcykpKSB7XG4gICAgICAgICAgJHRhcmdldEVsWzBdLmNsaWNrKCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gdXBkYXRlTmF2aWdhdGlvbigpIHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMubG9vcCB8fCBzd2lwZXIucGFyYW1zLnJld2luZCB8fCAhc3dpcGVyLm5hdmlnYXRpb24pIHJldHVybjtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgICRuZXh0RWwsXG4gICAgICAgICAgJHByZXZFbFxuICAgICAgICB9ID0gc3dpcGVyLm5hdmlnYXRpb247XG5cbiAgICAgICAgaWYgKCRwcmV2RWwgJiYgJHByZXZFbC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgaWYgKHN3aXBlci5pc0JlZ2lubmluZykge1xuICAgICAgICAgICAgZGlzYWJsZUVsKCRwcmV2RWwpO1xuICAgICAgICAgICAgbWFrZUVsTm90Rm9jdXNhYmxlKCRwcmV2RWwpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbmFibGVFbCgkcHJldkVsKTtcbiAgICAgICAgICAgIG1ha2VFbEZvY3VzYWJsZSgkcHJldkVsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJG5leHRFbCAmJiAkbmV4dEVsLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBpZiAoc3dpcGVyLmlzRW5kKSB7XG4gICAgICAgICAgICBkaXNhYmxlRWwoJG5leHRFbCk7XG4gICAgICAgICAgICBtYWtlRWxOb3RGb2N1c2FibGUoJG5leHRFbCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVuYWJsZUVsKCRuZXh0RWwpO1xuICAgICAgICAgICAgbWFrZUVsRm9jdXNhYmxlKCRuZXh0RWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBoYXNQYWdpbmF0aW9uKCkge1xuICAgICAgICByZXR1cm4gc3dpcGVyLnBhZ2luYXRpb24gJiYgc3dpcGVyLnBhZ2luYXRpb24uYnVsbGV0cyAmJiBzd2lwZXIucGFnaW5hdGlvbi5idWxsZXRzLmxlbmd0aDtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gaGFzQ2xpY2thYmxlUGFnaW5hdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGhhc1BhZ2luYXRpb24oKSAmJiBzd2lwZXIucGFyYW1zLnBhZ2luYXRpb24uY2xpY2thYmxlO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiB1cGRhdGVQYWdpbmF0aW9uKCkge1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zLmExMXk7XG4gICAgICAgIGlmICghaGFzUGFnaW5hdGlvbigpKSByZXR1cm47XG4gICAgICAgIHN3aXBlci5wYWdpbmF0aW9uLmJ1bGxldHMuZWFjaChidWxsZXRFbCA9PiB7XG4gICAgICAgICAgY29uc3QgJGJ1bGxldEVsID0gJChidWxsZXRFbCk7XG5cbiAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5wYWdpbmF0aW9uLmNsaWNrYWJsZSkge1xuICAgICAgICAgICAgbWFrZUVsRm9jdXNhYmxlKCRidWxsZXRFbCk7XG5cbiAgICAgICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy5wYWdpbmF0aW9uLnJlbmRlckJ1bGxldCkge1xuICAgICAgICAgICAgICBhZGRFbFJvbGUoJGJ1bGxldEVsLCAnYnV0dG9uJyk7XG4gICAgICAgICAgICAgIGFkZEVsTGFiZWwoJGJ1bGxldEVsLCBwYXJhbXMucGFnaW5hdGlvbkJ1bGxldE1lc3NhZ2UucmVwbGFjZSgvXFx7XFx7aW5kZXhcXH1cXH0vLCAkYnVsbGV0RWwuaW5kZXgoKSArIDEpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoJGJ1bGxldEVsLmlzKGAuJHtzd2lwZXIucGFyYW1zLnBhZ2luYXRpb24uYnVsbGV0QWN0aXZlQ2xhc3N9YCkpIHtcbiAgICAgICAgICAgICRidWxsZXRFbC5hdHRyKCdhcmlhLWN1cnJlbnQnLCAndHJ1ZScpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkYnVsbGV0RWwucmVtb3ZlQXR0cignYXJpYS1jdXJyZW50Jyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaW5pdE5hdkVsID0gKCRlbCwgd3JhcHBlcklkLCBtZXNzYWdlKSA9PiB7XG4gICAgICAgIG1ha2VFbEZvY3VzYWJsZSgkZWwpO1xuXG4gICAgICAgIGlmICgkZWxbMF0udGFnTmFtZSAhPT0gJ0JVVFRPTicpIHtcbiAgICAgICAgICBhZGRFbFJvbGUoJGVsLCAnYnV0dG9uJyk7XG4gICAgICAgICAgJGVsLm9uKCdrZXlkb3duJywgb25FbnRlck9yU3BhY2VLZXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgYWRkRWxMYWJlbCgkZWwsIG1lc3NhZ2UpO1xuICAgICAgICBhZGRFbENvbnRyb2xzKCRlbCwgd3JhcHBlcklkKTtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGhhbmRsZUZvY3VzID0gZSA9PiB7XG4gICAgICAgIGNvbnN0IHNsaWRlRWwgPSBlLnRhcmdldC5jbG9zZXN0KGAuJHtzd2lwZXIucGFyYW1zLnNsaWRlQ2xhc3N9YCk7XG4gICAgICAgIGlmICghc2xpZGVFbCB8fCAhc3dpcGVyLnNsaWRlcy5pbmNsdWRlcyhzbGlkZUVsKSkgcmV0dXJuO1xuICAgICAgICBjb25zdCBpc0FjdGl2ZSA9IHN3aXBlci5zbGlkZXMuaW5kZXhPZihzbGlkZUVsKSA9PT0gc3dpcGVyLmFjdGl2ZUluZGV4O1xuICAgICAgICBjb25zdCBpc1Zpc2libGUgPSBzd2lwZXIucGFyYW1zLndhdGNoU2xpZGVzUHJvZ3Jlc3MgJiYgc3dpcGVyLnZpc2libGVTbGlkZXMgJiYgc3dpcGVyLnZpc2libGVTbGlkZXMuaW5jbHVkZXMoc2xpZGVFbCk7XG4gICAgICAgIGlmIChpc0FjdGl2ZSB8fCBpc1Zpc2libGUpIHJldHVybjtcbiAgICAgICAgc3dpcGVyLnNsaWRlVG8oc3dpcGVyLnNsaWRlcy5pbmRleE9mKHNsaWRlRWwpLCAwKTtcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIGluaXQoKSB7XG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHN3aXBlci5wYXJhbXMuYTExeTtcbiAgICAgICAgc3dpcGVyLiRlbC5hcHBlbmQobGl2ZVJlZ2lvbik7IC8vIENvbnRhaW5lclxuXG4gICAgICAgIGNvbnN0ICRjb250YWluZXJFbCA9IHN3aXBlci4kZWw7XG5cbiAgICAgICAgaWYgKHBhcmFtcy5jb250YWluZXJSb2xlRGVzY3JpcHRpb25NZXNzYWdlKSB7XG4gICAgICAgICAgYWRkRWxSb2xlRGVzY3JpcHRpb24oJGNvbnRhaW5lckVsLCBwYXJhbXMuY29udGFpbmVyUm9sZURlc2NyaXB0aW9uTWVzc2FnZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLmNvbnRhaW5lck1lc3NhZ2UpIHtcbiAgICAgICAgICBhZGRFbExhYmVsKCRjb250YWluZXJFbCwgcGFyYW1zLmNvbnRhaW5lck1lc3NhZ2UpO1xuICAgICAgICB9IC8vIFdyYXBwZXJcblxuXG4gICAgICAgIGNvbnN0ICR3cmFwcGVyRWwgPSBzd2lwZXIuJHdyYXBwZXJFbDtcbiAgICAgICAgY29uc3Qgd3JhcHBlcklkID0gJHdyYXBwZXJFbC5hdHRyKCdpZCcpIHx8IGBzd2lwZXItd3JhcHBlci0ke2dldFJhbmRvbU51bWJlcigxNil9YDtcbiAgICAgICAgY29uc3QgbGl2ZSA9IHN3aXBlci5wYXJhbXMuYXV0b3BsYXkgJiYgc3dpcGVyLnBhcmFtcy5hdXRvcGxheS5lbmFibGVkID8gJ29mZicgOiAncG9saXRlJztcbiAgICAgICAgYWRkRWxJZCgkd3JhcHBlckVsLCB3cmFwcGVySWQpO1xuICAgICAgICBhZGRFbExpdmUoJHdyYXBwZXJFbCwgbGl2ZSk7IC8vIFNsaWRlXG5cbiAgICAgICAgaWYgKHBhcmFtcy5pdGVtUm9sZURlc2NyaXB0aW9uTWVzc2FnZSkge1xuICAgICAgICAgIGFkZEVsUm9sZURlc2NyaXB0aW9uKCQoc3dpcGVyLnNsaWRlcyksIHBhcmFtcy5pdGVtUm9sZURlc2NyaXB0aW9uTWVzc2FnZSk7XG4gICAgICAgIH1cblxuICAgICAgICBhZGRFbFJvbGUoJChzd2lwZXIuc2xpZGVzKSwgcGFyYW1zLnNsaWRlUm9sZSk7XG4gICAgICAgIGNvbnN0IHNsaWRlc0xlbmd0aCA9IHN3aXBlci5wYXJhbXMubG9vcCA/IHN3aXBlci5zbGlkZXMuZmlsdGVyKGVsID0+ICFlbC5jbGFzc0xpc3QuY29udGFpbnMoc3dpcGVyLnBhcmFtcy5zbGlkZUR1cGxpY2F0ZUNsYXNzKSkubGVuZ3RoIDogc3dpcGVyLnNsaWRlcy5sZW5ndGg7XG4gICAgICAgIHN3aXBlci5zbGlkZXMuZWFjaCgoc2xpZGVFbCwgaW5kZXgpID0+IHtcbiAgICAgICAgICBjb25zdCAkc2xpZGVFbCA9ICQoc2xpZGVFbCk7XG4gICAgICAgICAgY29uc3Qgc2xpZGVJbmRleCA9IHN3aXBlci5wYXJhbXMubG9vcCA/IHBhcnNlSW50KCRzbGlkZUVsLmF0dHIoJ2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4JyksIDEwKSA6IGluZGV4O1xuICAgICAgICAgIGNvbnN0IGFyaWFMYWJlbE1lc3NhZ2UgPSBwYXJhbXMuc2xpZGVMYWJlbE1lc3NhZ2UucmVwbGFjZSgvXFx7XFx7aW5kZXhcXH1cXH0vLCBzbGlkZUluZGV4ICsgMSkucmVwbGFjZSgvXFx7XFx7c2xpZGVzTGVuZ3RoXFx9XFx9Lywgc2xpZGVzTGVuZ3RoKTtcbiAgICAgICAgICBhZGRFbExhYmVsKCRzbGlkZUVsLCBhcmlhTGFiZWxNZXNzYWdlKTtcbiAgICAgICAgfSk7IC8vIE5hdmlnYXRpb25cblxuICAgICAgICBsZXQgJG5leHRFbDtcbiAgICAgICAgbGV0ICRwcmV2RWw7XG5cbiAgICAgICAgaWYgKHN3aXBlci5uYXZpZ2F0aW9uICYmIHN3aXBlci5uYXZpZ2F0aW9uLiRuZXh0RWwpIHtcbiAgICAgICAgICAkbmV4dEVsID0gc3dpcGVyLm5hdmlnYXRpb24uJG5leHRFbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzd2lwZXIubmF2aWdhdGlvbiAmJiBzd2lwZXIubmF2aWdhdGlvbi4kcHJldkVsKSB7XG4gICAgICAgICAgJHByZXZFbCA9IHN3aXBlci5uYXZpZ2F0aW9uLiRwcmV2RWw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJG5leHRFbCAmJiAkbmV4dEVsLmxlbmd0aCkge1xuICAgICAgICAgIGluaXROYXZFbCgkbmV4dEVsLCB3cmFwcGVySWQsIHBhcmFtcy5uZXh0U2xpZGVNZXNzYWdlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgkcHJldkVsICYmICRwcmV2RWwubGVuZ3RoKSB7XG4gICAgICAgICAgaW5pdE5hdkVsKCRwcmV2RWwsIHdyYXBwZXJJZCwgcGFyYW1zLnByZXZTbGlkZU1lc3NhZ2UpO1xuICAgICAgICB9IC8vIFBhZ2luYXRpb25cblxuXG4gICAgICAgIGlmIChoYXNDbGlja2FibGVQYWdpbmF0aW9uKCkpIHtcbiAgICAgICAgICBzd2lwZXIucGFnaW5hdGlvbi4kZWwub24oJ2tleWRvd24nLCBjbGFzc2VzVG9TZWxlY3Rvcihzd2lwZXIucGFyYW1zLnBhZ2luYXRpb24uYnVsbGV0Q2xhc3MpLCBvbkVudGVyT3JTcGFjZUtleSk7XG4gICAgICAgIH0gLy8gVGFiIGZvY3VzXG5cblxuICAgICAgICBzd2lwZXIuJGVsLm9uKCdmb2N1cycsIGhhbmRsZUZvY3VzLCB0cnVlKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZGVzdHJveSgpIHtcbiAgICAgICAgaWYgKGxpdmVSZWdpb24gJiYgbGl2ZVJlZ2lvbi5sZW5ndGggPiAwKSBsaXZlUmVnaW9uLnJlbW92ZSgpO1xuICAgICAgICBsZXQgJG5leHRFbDtcbiAgICAgICAgbGV0ICRwcmV2RWw7XG5cbiAgICAgICAgaWYgKHN3aXBlci5uYXZpZ2F0aW9uICYmIHN3aXBlci5uYXZpZ2F0aW9uLiRuZXh0RWwpIHtcbiAgICAgICAgICAkbmV4dEVsID0gc3dpcGVyLm5hdmlnYXRpb24uJG5leHRFbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzd2lwZXIubmF2aWdhdGlvbiAmJiBzd2lwZXIubmF2aWdhdGlvbi4kcHJldkVsKSB7XG4gICAgICAgICAgJHByZXZFbCA9IHN3aXBlci5uYXZpZ2F0aW9uLiRwcmV2RWw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJG5leHRFbCkge1xuICAgICAgICAgICRuZXh0RWwub2ZmKCdrZXlkb3duJywgb25FbnRlck9yU3BhY2VLZXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCRwcmV2RWwpIHtcbiAgICAgICAgICAkcHJldkVsLm9mZigna2V5ZG93bicsIG9uRW50ZXJPclNwYWNlS2V5KTtcbiAgICAgICAgfSAvLyBQYWdpbmF0aW9uXG5cblxuICAgICAgICBpZiAoaGFzQ2xpY2thYmxlUGFnaW5hdGlvbigpKSB7XG4gICAgICAgICAgc3dpcGVyLnBhZ2luYXRpb24uJGVsLm9mZigna2V5ZG93bicsIGNsYXNzZXNUb1NlbGVjdG9yKHN3aXBlci5wYXJhbXMucGFnaW5hdGlvbi5idWxsZXRDbGFzcyksIG9uRW50ZXJPclNwYWNlS2V5KTtcbiAgICAgICAgfSAvLyBUYWIgZm9jdXNcblxuXG4gICAgICAgIHN3aXBlci4kZWwub2ZmKCdmb2N1cycsIGhhbmRsZUZvY3VzLCB0cnVlKTtcbiAgICAgIH1cblxuICAgICAgb24oJ2JlZm9yZUluaXQnLCAoKSA9PiB7XG4gICAgICAgIGxpdmVSZWdpb24gPSAkKGA8c3BhbiBjbGFzcz1cIiR7c3dpcGVyLnBhcmFtcy5hMTF5Lm5vdGlmaWNhdGlvbkNsYXNzfVwiIGFyaWEtbGl2ZT1cImFzc2VydGl2ZVwiIGFyaWEtYXRvbWljPVwidHJ1ZVwiPjwvc3Bhbj5gKTtcbiAgICAgIH0pO1xuICAgICAgb24oJ2FmdGVySW5pdCcsICgpID0+IHtcbiAgICAgICAgaWYgKCFzd2lwZXIucGFyYW1zLmExMXkuZW5hYmxlZCkgcmV0dXJuO1xuICAgICAgICBpbml0KCk7XG4gICAgICB9KTtcbiAgICAgIG9uKCdmcm9tRWRnZSB0b0VkZ2UgYWZ0ZXJJbml0IGxvY2sgdW5sb2NrJywgKCkgPT4ge1xuICAgICAgICBpZiAoIXN3aXBlci5wYXJhbXMuYTExeS5lbmFibGVkKSByZXR1cm47XG4gICAgICAgIHVwZGF0ZU5hdmlnYXRpb24oKTtcbiAgICAgIH0pO1xuICAgICAgb24oJ3BhZ2luYXRpb25VcGRhdGUnLCAoKSA9PiB7XG4gICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy5hMTF5LmVuYWJsZWQpIHJldHVybjtcbiAgICAgICAgdXBkYXRlUGFnaW5hdGlvbigpO1xuICAgICAgfSk7XG4gICAgICBvbignZGVzdHJveScsICgpID0+IHtcbiAgICAgICAgaWYgKCFzd2lwZXIucGFyYW1zLmExMXkuZW5hYmxlZCkgcmV0dXJuO1xuICAgICAgICBkZXN0cm95KCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBIaXN0b3J5KF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZXh0ZW5kUGFyYW1zLFxuICAgICAgICBvblxuICAgICAgfSA9IF9yZWY7XG4gICAgICBleHRlbmRQYXJhbXMoe1xuICAgICAgICBoaXN0b3J5OiB7XG4gICAgICAgICAgZW5hYmxlZDogZmFsc2UsXG4gICAgICAgICAgcm9vdDogJycsXG4gICAgICAgICAgcmVwbGFjZVN0YXRlOiBmYWxzZSxcbiAgICAgICAgICBrZXk6ICdzbGlkZXMnXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgbGV0IGluaXRpYWxpemVkID0gZmFsc2U7XG4gICAgICBsZXQgcGF0aHMgPSB7fTtcblxuICAgICAgY29uc3Qgc2x1Z2lmeSA9IHRleHQgPT4ge1xuICAgICAgICByZXR1cm4gdGV4dC50b1N0cmluZygpLnJlcGxhY2UoL1xccysvZywgJy0nKS5yZXBsYWNlKC9bXlxcdy1dKy9nLCAnJykucmVwbGFjZSgvLS0rL2csICctJykucmVwbGFjZSgvXi0rLywgJycpLnJlcGxhY2UoLy0rJC8sICcnKTtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGdldFBhdGhWYWx1ZXMgPSB1cmxPdmVycmlkZSA9PiB7XG4gICAgICAgIGNvbnN0IHdpbmRvdyA9IGdldFdpbmRvdygpO1xuICAgICAgICBsZXQgbG9jYXRpb247XG5cbiAgICAgICAgaWYgKHVybE92ZXJyaWRlKSB7XG4gICAgICAgICAgbG9jYXRpb24gPSBuZXcgVVJMKHVybE92ZXJyaWRlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsb2NhdGlvbiA9IHdpbmRvdy5sb2NhdGlvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBhdGhBcnJheSA9IGxvY2F0aW9uLnBhdGhuYW1lLnNsaWNlKDEpLnNwbGl0KCcvJykuZmlsdGVyKHBhcnQgPT4gcGFydCAhPT0gJycpO1xuICAgICAgICBjb25zdCB0b3RhbCA9IHBhdGhBcnJheS5sZW5ndGg7XG4gICAgICAgIGNvbnN0IGtleSA9IHBhdGhBcnJheVt0b3RhbCAtIDJdO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHBhdGhBcnJheVt0b3RhbCAtIDFdO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGtleSxcbiAgICAgICAgICB2YWx1ZVxuICAgICAgICB9O1xuICAgICAgfTtcblxuICAgICAgY29uc3Qgc2V0SGlzdG9yeSA9IChrZXksIGluZGV4KSA9PiB7XG4gICAgICAgIGNvbnN0IHdpbmRvdyA9IGdldFdpbmRvdygpO1xuICAgICAgICBpZiAoIWluaXRpYWxpemVkIHx8ICFzd2lwZXIucGFyYW1zLmhpc3RvcnkuZW5hYmxlZCkgcmV0dXJuO1xuICAgICAgICBsZXQgbG9jYXRpb247XG5cbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMudXJsKSB7XG4gICAgICAgICAgbG9jYXRpb24gPSBuZXcgVVJMKHN3aXBlci5wYXJhbXMudXJsKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsb2NhdGlvbiA9IHdpbmRvdy5sb2NhdGlvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNsaWRlID0gc3dpcGVyLnNsaWRlcy5lcShpbmRleCk7XG4gICAgICAgIGxldCB2YWx1ZSA9IHNsdWdpZnkoc2xpZGUuYXR0cignZGF0YS1oaXN0b3J5JykpO1xuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmhpc3Rvcnkucm9vdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgbGV0IHJvb3QgPSBzd2lwZXIucGFyYW1zLmhpc3Rvcnkucm9vdDtcbiAgICAgICAgICBpZiAocm9vdFtyb290Lmxlbmd0aCAtIDFdID09PSAnLycpIHJvb3QgPSByb290LnNsaWNlKDAsIHJvb3QubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgdmFsdWUgPSBgJHtyb290fS8ke2tleX0vJHt2YWx1ZX1gO1xuICAgICAgICB9IGVsc2UgaWYgKCFsb2NhdGlvbi5wYXRobmFtZS5pbmNsdWRlcyhrZXkpKSB7XG4gICAgICAgICAgdmFsdWUgPSBgJHtrZXl9LyR7dmFsdWV9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHdpbmRvdy5oaXN0b3J5LnN0YXRlO1xuXG4gICAgICAgIGlmIChjdXJyZW50U3RhdGUgJiYgY3VycmVudFN0YXRlLnZhbHVlID09PSB2YWx1ZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmhpc3RvcnkucmVwbGFjZVN0YXRlKSB7XG4gICAgICAgICAgd2luZG93Lmhpc3RvcnkucmVwbGFjZVN0YXRlKHtcbiAgICAgICAgICAgIHZhbHVlXG4gICAgICAgICAgfSwgbnVsbCwgdmFsdWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHdpbmRvdy5oaXN0b3J5LnB1c2hTdGF0ZSh7XG4gICAgICAgICAgICB2YWx1ZVxuICAgICAgICAgIH0sIG51bGwsIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgY29uc3Qgc2Nyb2xsVG9TbGlkZSA9IChzcGVlZCwgdmFsdWUsIHJ1bkNhbGxiYWNrcykgPT4ge1xuICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gc3dpcGVyLnNsaWRlcy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgY29uc3Qgc2xpZGUgPSBzd2lwZXIuc2xpZGVzLmVxKGkpO1xuICAgICAgICAgICAgY29uc3Qgc2xpZGVIaXN0b3J5ID0gc2x1Z2lmeShzbGlkZS5hdHRyKCdkYXRhLWhpc3RvcnknKSk7XG5cbiAgICAgICAgICAgIGlmIChzbGlkZUhpc3RvcnkgPT09IHZhbHVlICYmICFzbGlkZS5oYXNDbGFzcyhzd2lwZXIucGFyYW1zLnNsaWRlRHVwbGljYXRlQ2xhc3MpKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gc2xpZGUuaW5kZXgoKTtcbiAgICAgICAgICAgICAgc3dpcGVyLnNsaWRlVG8oaW5kZXgsIHNwZWVkLCBydW5DYWxsYmFja3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzd2lwZXIuc2xpZGVUbygwLCBzcGVlZCwgcnVuQ2FsbGJhY2tzKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgY29uc3Qgc2V0SGlzdG9yeVBvcFN0YXRlID0gKCkgPT4ge1xuICAgICAgICBwYXRocyA9IGdldFBhdGhWYWx1ZXMoc3dpcGVyLnBhcmFtcy51cmwpO1xuICAgICAgICBzY3JvbGxUb1NsaWRlKHN3aXBlci5wYXJhbXMuc3BlZWQsIHN3aXBlci5wYXRocy52YWx1ZSwgZmFsc2UpO1xuICAgICAgfTtcblxuICAgICAgY29uc3QgaW5pdCA9ICgpID0+IHtcbiAgICAgICAgY29uc3Qgd2luZG93ID0gZ2V0V2luZG93KCk7XG4gICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy5oaXN0b3J5KSByZXR1cm47XG5cbiAgICAgICAgaWYgKCF3aW5kb3cuaGlzdG9yeSB8fCAhd2luZG93Lmhpc3RvcnkucHVzaFN0YXRlKSB7XG4gICAgICAgICAgc3dpcGVyLnBhcmFtcy5oaXN0b3J5LmVuYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICBzd2lwZXIucGFyYW1zLmhhc2hOYXZpZ2F0aW9uLmVuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAgICAgcGF0aHMgPSBnZXRQYXRoVmFsdWVzKHN3aXBlci5wYXJhbXMudXJsKTtcbiAgICAgICAgaWYgKCFwYXRocy5rZXkgJiYgIXBhdGhzLnZhbHVlKSByZXR1cm47XG4gICAgICAgIHNjcm9sbFRvU2xpZGUoMCwgcGF0aHMudmFsdWUsIHN3aXBlci5wYXJhbXMucnVuQ2FsbGJhY2tzT25Jbml0KTtcblxuICAgICAgICBpZiAoIXN3aXBlci5wYXJhbXMuaGlzdG9yeS5yZXBsYWNlU3RhdGUpIHtcbiAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncG9wc3RhdGUnLCBzZXRIaXN0b3J5UG9wU3RhdGUpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBkZXN0cm95ID0gKCkgPT4ge1xuICAgICAgICBjb25zdCB3aW5kb3cgPSBnZXRXaW5kb3coKTtcblxuICAgICAgICBpZiAoIXN3aXBlci5wYXJhbXMuaGlzdG9yeS5yZXBsYWNlU3RhdGUpIHtcbiAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncG9wc3RhdGUnLCBzZXRIaXN0b3J5UG9wU3RhdGUpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBvbignaW5pdCcsICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuaGlzdG9yeS5lbmFibGVkKSB7XG4gICAgICAgICAgaW5pdCgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIG9uKCdkZXN0cm95JywgKCkgPT4ge1xuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5oaXN0b3J5LmVuYWJsZWQpIHtcbiAgICAgICAgICBkZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb24oJ3RyYW5zaXRpb25FbmQgX2ZyZWVNb2RlTm9Nb21lbnR1bVJlbGVhc2UnLCAoKSA9PiB7XG4gICAgICAgIGlmIChpbml0aWFsaXplZCkge1xuICAgICAgICAgIHNldEhpc3Rvcnkoc3dpcGVyLnBhcmFtcy5oaXN0b3J5LmtleSwgc3dpcGVyLmFjdGl2ZUluZGV4KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBvbignc2xpZGVDaGFuZ2UnLCAoKSA9PiB7XG4gICAgICAgIGlmIChpbml0aWFsaXplZCAmJiBzd2lwZXIucGFyYW1zLmNzc01vZGUpIHtcbiAgICAgICAgICBzZXRIaXN0b3J5KHN3aXBlci5wYXJhbXMuaGlzdG9yeS5rZXksIHN3aXBlci5hY3RpdmVJbmRleCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIEhhc2hOYXZpZ2F0aW9uKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZXh0ZW5kUGFyYW1zLFxuICAgICAgICBlbWl0LFxuICAgICAgICBvblxuICAgICAgfSA9IF9yZWY7XG4gICAgICBsZXQgaW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICAgIGNvbnN0IGRvY3VtZW50ID0gZ2V0RG9jdW1lbnQoKTtcbiAgICAgIGNvbnN0IHdpbmRvdyA9IGdldFdpbmRvdygpO1xuICAgICAgZXh0ZW5kUGFyYW1zKHtcbiAgICAgICAgaGFzaE5hdmlnYXRpb246IHtcbiAgICAgICAgICBlbmFibGVkOiBmYWxzZSxcbiAgICAgICAgICByZXBsYWNlU3RhdGU6IGZhbHNlLFxuICAgICAgICAgIHdhdGNoU3RhdGU6IGZhbHNlXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBvbkhhc2hDaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgIGVtaXQoJ2hhc2hDaGFuZ2UnKTtcbiAgICAgICAgY29uc3QgbmV3SGFzaCA9IGRvY3VtZW50LmxvY2F0aW9uLmhhc2gucmVwbGFjZSgnIycsICcnKTtcbiAgICAgICAgY29uc3QgYWN0aXZlU2xpZGVIYXNoID0gc3dpcGVyLnNsaWRlcy5lcShzd2lwZXIuYWN0aXZlSW5kZXgpLmF0dHIoJ2RhdGEtaGFzaCcpO1xuXG4gICAgICAgIGlmIChuZXdIYXNoICE9PSBhY3RpdmVTbGlkZUhhc2gpIHtcbiAgICAgICAgICBjb25zdCBuZXdJbmRleCA9IHN3aXBlci4kd3JhcHBlckVsLmNoaWxkcmVuKGAuJHtzd2lwZXIucGFyYW1zLnNsaWRlQ2xhc3N9W2RhdGEtaGFzaD1cIiR7bmV3SGFzaH1cIl1gKS5pbmRleCgpO1xuICAgICAgICAgIGlmICh0eXBlb2YgbmV3SW5kZXggPT09ICd1bmRlZmluZWQnKSByZXR1cm47XG4gICAgICAgICAgc3dpcGVyLnNsaWRlVG8obmV3SW5kZXgpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBzZXRIYXNoID0gKCkgPT4ge1xuICAgICAgICBpZiAoIWluaXRpYWxpemVkIHx8ICFzd2lwZXIucGFyYW1zLmhhc2hOYXZpZ2F0aW9uLmVuYWJsZWQpIHJldHVybjtcblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5oYXNoTmF2aWdhdGlvbi5yZXBsYWNlU3RhdGUgJiYgd2luZG93Lmhpc3RvcnkgJiYgd2luZG93Lmhpc3RvcnkucmVwbGFjZVN0YXRlKSB7XG4gICAgICAgICAgd2luZG93Lmhpc3RvcnkucmVwbGFjZVN0YXRlKG51bGwsIG51bGwsIGAjJHtzd2lwZXIuc2xpZGVzLmVxKHN3aXBlci5hY3RpdmVJbmRleCkuYXR0cignZGF0YS1oYXNoJyl9YCB8fCAnJyk7XG4gICAgICAgICAgZW1pdCgnaGFzaFNldCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IHNsaWRlID0gc3dpcGVyLnNsaWRlcy5lcShzd2lwZXIuYWN0aXZlSW5kZXgpO1xuICAgICAgICAgIGNvbnN0IGhhc2ggPSBzbGlkZS5hdHRyKCdkYXRhLWhhc2gnKSB8fCBzbGlkZS5hdHRyKCdkYXRhLWhpc3RvcnknKTtcbiAgICAgICAgICBkb2N1bWVudC5sb2NhdGlvbi5oYXNoID0gaGFzaCB8fCAnJztcbiAgICAgICAgICBlbWl0KCdoYXNoU2V0Jyk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGluaXQgPSAoKSA9PiB7XG4gICAgICAgIGlmICghc3dpcGVyLnBhcmFtcy5oYXNoTmF2aWdhdGlvbi5lbmFibGVkIHx8IHN3aXBlci5wYXJhbXMuaGlzdG9yeSAmJiBzd2lwZXIucGFyYW1zLmhpc3RvcnkuZW5hYmxlZCkgcmV0dXJuO1xuICAgICAgICBpbml0aWFsaXplZCA9IHRydWU7XG4gICAgICAgIGNvbnN0IGhhc2ggPSBkb2N1bWVudC5sb2NhdGlvbi5oYXNoLnJlcGxhY2UoJyMnLCAnJyk7XG5cbiAgICAgICAgaWYgKGhhc2gpIHtcbiAgICAgICAgICBjb25zdCBzcGVlZCA9IDA7XG5cbiAgICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gc3dpcGVyLnNsaWRlcy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgY29uc3Qgc2xpZGUgPSBzd2lwZXIuc2xpZGVzLmVxKGkpO1xuICAgICAgICAgICAgY29uc3Qgc2xpZGVIYXNoID0gc2xpZGUuYXR0cignZGF0YS1oYXNoJykgfHwgc2xpZGUuYXR0cignZGF0YS1oaXN0b3J5Jyk7XG5cbiAgICAgICAgICAgIGlmIChzbGlkZUhhc2ggPT09IGhhc2ggJiYgIXNsaWRlLmhhc0NsYXNzKHN3aXBlci5wYXJhbXMuc2xpZGVEdXBsaWNhdGVDbGFzcykpIHtcbiAgICAgICAgICAgICAgY29uc3QgaW5kZXggPSBzbGlkZS5pbmRleCgpO1xuICAgICAgICAgICAgICBzd2lwZXIuc2xpZGVUbyhpbmRleCwgc3BlZWQsIHN3aXBlci5wYXJhbXMucnVuQ2FsbGJhY2tzT25Jbml0LCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5oYXNoTmF2aWdhdGlvbi53YXRjaFN0YXRlKSB7XG4gICAgICAgICAgJCh3aW5kb3cpLm9uKCdoYXNoY2hhbmdlJywgb25IYXNoQ2hhbmdlKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgY29uc3QgZGVzdHJveSA9ICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuaGFzaE5hdmlnYXRpb24ud2F0Y2hTdGF0ZSkge1xuICAgICAgICAgICQod2luZG93KS5vZmYoJ2hhc2hjaGFuZ2UnLCBvbkhhc2hDaGFuZ2UpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBvbignaW5pdCcsICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuaGFzaE5hdmlnYXRpb24uZW5hYmxlZCkge1xuICAgICAgICAgIGluaXQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBvbignZGVzdHJveScsICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuaGFzaE5hdmlnYXRpb24uZW5hYmxlZCkge1xuICAgICAgICAgIGRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBvbigndHJhbnNpdGlvbkVuZCBfZnJlZU1vZGVOb01vbWVudHVtUmVsZWFzZScsICgpID0+IHtcbiAgICAgICAgaWYgKGluaXRpYWxpemVkKSB7XG4gICAgICAgICAgc2V0SGFzaCgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIG9uKCdzbGlkZUNoYW5nZScsICgpID0+IHtcbiAgICAgICAgaWYgKGluaXRpYWxpemVkICYmIHN3aXBlci5wYXJhbXMuY3NzTW9kZSkge1xuICAgICAgICAgIHNldEhhc2goKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyogZXNsaW50IG5vLXVuZGVyc2NvcmUtZGFuZ2xlOiBcIm9mZlwiICovXG4gICAgZnVuY3Rpb24gQXV0b3BsYXkoX3JlZikge1xuICAgICAgbGV0IHtcbiAgICAgICAgc3dpcGVyLFxuICAgICAgICBleHRlbmRQYXJhbXMsXG4gICAgICAgIG9uLFxuICAgICAgICBlbWl0XG4gICAgICB9ID0gX3JlZjtcbiAgICAgIGxldCB0aW1lb3V0O1xuICAgICAgc3dpcGVyLmF1dG9wbGF5ID0ge1xuICAgICAgICBydW5uaW5nOiBmYWxzZSxcbiAgICAgICAgcGF1c2VkOiBmYWxzZVxuICAgICAgfTtcbiAgICAgIGV4dGVuZFBhcmFtcyh7XG4gICAgICAgIGF1dG9wbGF5OiB7XG4gICAgICAgICAgZW5hYmxlZDogZmFsc2UsXG4gICAgICAgICAgZGVsYXk6IDMwMDAsXG4gICAgICAgICAgd2FpdEZvclRyYW5zaXRpb246IHRydWUsXG4gICAgICAgICAgZGlzYWJsZU9uSW50ZXJhY3Rpb246IHRydWUsXG4gICAgICAgICAgc3RvcE9uTGFzdFNsaWRlOiBmYWxzZSxcbiAgICAgICAgICByZXZlcnNlRGlyZWN0aW9uOiBmYWxzZSxcbiAgICAgICAgICBwYXVzZU9uTW91c2VFbnRlcjogZmFsc2VcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGZ1bmN0aW9uIHJ1bigpIHtcbiAgICAgICAgY29uc3QgJGFjdGl2ZVNsaWRlRWwgPSBzd2lwZXIuc2xpZGVzLmVxKHN3aXBlci5hY3RpdmVJbmRleCk7XG4gICAgICAgIGxldCBkZWxheSA9IHN3aXBlci5wYXJhbXMuYXV0b3BsYXkuZGVsYXk7XG5cbiAgICAgICAgaWYgKCRhY3RpdmVTbGlkZUVsLmF0dHIoJ2RhdGEtc3dpcGVyLWF1dG9wbGF5JykpIHtcbiAgICAgICAgICBkZWxheSA9ICRhY3RpdmVTbGlkZUVsLmF0dHIoJ2RhdGEtc3dpcGVyLWF1dG9wbGF5JykgfHwgc3dpcGVyLnBhcmFtcy5hdXRvcGxheS5kZWxheTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgdGltZW91dCA9IG5leHRUaWNrKCgpID0+IHtcbiAgICAgICAgICBsZXQgYXV0b3BsYXlSZXN1bHQ7XG5cbiAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5hdXRvcGxheS5yZXZlcnNlRGlyZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5sb29wKSB7XG4gICAgICAgICAgICAgIHN3aXBlci5sb29wRml4KCk7XG4gICAgICAgICAgICAgIGF1dG9wbGF5UmVzdWx0ID0gc3dpcGVyLnNsaWRlUHJldihzd2lwZXIucGFyYW1zLnNwZWVkLCB0cnVlLCB0cnVlKTtcbiAgICAgICAgICAgICAgZW1pdCgnYXV0b3BsYXknKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXN3aXBlci5pc0JlZ2lubmluZykge1xuICAgICAgICAgICAgICBhdXRvcGxheVJlc3VsdCA9IHN3aXBlci5zbGlkZVByZXYoc3dpcGVyLnBhcmFtcy5zcGVlZCwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgIGVtaXQoJ2F1dG9wbGF5Jyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFzd2lwZXIucGFyYW1zLmF1dG9wbGF5LnN0b3BPbkxhc3RTbGlkZSkge1xuICAgICAgICAgICAgICBhdXRvcGxheVJlc3VsdCA9IHN3aXBlci5zbGlkZVRvKHN3aXBlci5zbGlkZXMubGVuZ3RoIC0gMSwgc3dpcGVyLnBhcmFtcy5zcGVlZCwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgIGVtaXQoJ2F1dG9wbGF5Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzdG9wKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChzd2lwZXIucGFyYW1zLmxvb3ApIHtcbiAgICAgICAgICAgIHN3aXBlci5sb29wRml4KCk7XG4gICAgICAgICAgICBhdXRvcGxheVJlc3VsdCA9IHN3aXBlci5zbGlkZU5leHQoc3dpcGVyLnBhcmFtcy5zcGVlZCwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICBlbWl0KCdhdXRvcGxheScpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIXN3aXBlci5pc0VuZCkge1xuICAgICAgICAgICAgYXV0b3BsYXlSZXN1bHQgPSBzd2lwZXIuc2xpZGVOZXh0KHN3aXBlci5wYXJhbXMuc3BlZWQsIHRydWUsIHRydWUpO1xuICAgICAgICAgICAgZW1pdCgnYXV0b3BsYXknKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKCFzd2lwZXIucGFyYW1zLmF1dG9wbGF5LnN0b3BPbkxhc3RTbGlkZSkge1xuICAgICAgICAgICAgYXV0b3BsYXlSZXN1bHQgPSBzd2lwZXIuc2xpZGVUbygwLCBzd2lwZXIucGFyYW1zLnNwZWVkLCB0cnVlLCB0cnVlKTtcbiAgICAgICAgICAgIGVtaXQoJ2F1dG9wbGF5Jyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0b3AoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5jc3NNb2RlICYmIHN3aXBlci5hdXRvcGxheS5ydW5uaW5nKSBydW4oKTtlbHNlIGlmIChhdXRvcGxheVJlc3VsdCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJ1bigpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgZGVsYXkpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBzdGFydCgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB0aW1lb3V0ICE9PSAndW5kZWZpbmVkJykgcmV0dXJuIGZhbHNlO1xuICAgICAgICBpZiAoc3dpcGVyLmF1dG9wbGF5LnJ1bm5pbmcpIHJldHVybiBmYWxzZTtcbiAgICAgICAgc3dpcGVyLmF1dG9wbGF5LnJ1bm5pbmcgPSB0cnVlO1xuICAgICAgICBlbWl0KCdhdXRvcGxheVN0YXJ0Jyk7XG4gICAgICAgIHJ1bigpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gc3RvcCgpIHtcbiAgICAgICAgaWYgKCFzd2lwZXIuYXV0b3BsYXkucnVubmluZykgcmV0dXJuIGZhbHNlO1xuICAgICAgICBpZiAodHlwZW9mIHRpbWVvdXQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgaWYgKHRpbWVvdXQpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgICAgdGltZW91dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci5hdXRvcGxheS5ydW5uaW5nID0gZmFsc2U7XG4gICAgICAgIGVtaXQoJ2F1dG9wbGF5U3RvcCcpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gcGF1c2Uoc3BlZWQpIHtcbiAgICAgICAgaWYgKCFzd2lwZXIuYXV0b3BsYXkucnVubmluZykgcmV0dXJuO1xuICAgICAgICBpZiAoc3dpcGVyLmF1dG9wbGF5LnBhdXNlZCkgcmV0dXJuO1xuICAgICAgICBpZiAodGltZW91dCkgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICBzd2lwZXIuYXV0b3BsYXkucGF1c2VkID0gdHJ1ZTtcblxuICAgICAgICBpZiAoc3BlZWQgPT09IDAgfHwgIXN3aXBlci5wYXJhbXMuYXV0b3BsYXkud2FpdEZvclRyYW5zaXRpb24pIHtcbiAgICAgICAgICBzd2lwZXIuYXV0b3BsYXkucGF1c2VkID0gZmFsc2U7XG4gICAgICAgICAgcnVuKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgWyd0cmFuc2l0aW9uZW5kJywgJ3dlYmtpdFRyYW5zaXRpb25FbmQnXS5mb3JFYWNoKGV2ZW50ID0+IHtcbiAgICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsWzBdLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIG9uVHJhbnNpdGlvbkVuZCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gb25WaXNpYmlsaXR5Q2hhbmdlKCkge1xuICAgICAgICBjb25zdCBkb2N1bWVudCA9IGdldERvY3VtZW50KCk7XG5cbiAgICAgICAgaWYgKGRvY3VtZW50LnZpc2liaWxpdHlTdGF0ZSA9PT0gJ2hpZGRlbicgJiYgc3dpcGVyLmF1dG9wbGF5LnJ1bm5pbmcpIHtcbiAgICAgICAgICBwYXVzZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRvY3VtZW50LnZpc2liaWxpdHlTdGF0ZSA9PT0gJ3Zpc2libGUnICYmIHN3aXBlci5hdXRvcGxheS5wYXVzZWQpIHtcbiAgICAgICAgICBydW4oKTtcbiAgICAgICAgICBzd2lwZXIuYXV0b3BsYXkucGF1c2VkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gb25UcmFuc2l0aW9uRW5kKGUpIHtcbiAgICAgICAgaWYgKCFzd2lwZXIgfHwgc3dpcGVyLmRlc3Ryb3llZCB8fCAhc3dpcGVyLiR3cmFwcGVyRWwpIHJldHVybjtcbiAgICAgICAgaWYgKGUudGFyZ2V0ICE9PSBzd2lwZXIuJHdyYXBwZXJFbFswXSkgcmV0dXJuO1xuICAgICAgICBbJ3RyYW5zaXRpb25lbmQnLCAnd2Via2l0VHJhbnNpdGlvbkVuZCddLmZvckVhY2goZXZlbnQgPT4ge1xuICAgICAgICAgIHN3aXBlci4kd3JhcHBlckVsWzBdLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIG9uVHJhbnNpdGlvbkVuZCk7XG4gICAgICAgIH0pO1xuICAgICAgICBzd2lwZXIuYXV0b3BsYXkucGF1c2VkID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKCFzd2lwZXIuYXV0b3BsYXkucnVubmluZykge1xuICAgICAgICAgIHN0b3AoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBydW4oKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBvbk1vdXNlRW50ZXIoKSB7XG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmF1dG9wbGF5LmRpc2FibGVPbkludGVyYWN0aW9uKSB7XG4gICAgICAgICAgc3RvcCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVtaXQoJ2F1dG9wbGF5UGF1c2UnKTtcbiAgICAgICAgICBwYXVzZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgWyd0cmFuc2l0aW9uZW5kJywgJ3dlYmtpdFRyYW5zaXRpb25FbmQnXS5mb3JFYWNoKGV2ZW50ID0+IHtcbiAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbFswXS5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBvblRyYW5zaXRpb25FbmQpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gb25Nb3VzZUxlYXZlKCkge1xuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5hdXRvcGxheS5kaXNhYmxlT25JbnRlcmFjdGlvbikge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci5hdXRvcGxheS5wYXVzZWQgPSBmYWxzZTtcbiAgICAgICAgZW1pdCgnYXV0b3BsYXlSZXN1bWUnKTtcbiAgICAgICAgcnVuKCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGF0dGFjaE1vdXNlRXZlbnRzKCkge1xuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5hdXRvcGxheS5wYXVzZU9uTW91c2VFbnRlcikge1xuICAgICAgICAgIHN3aXBlci4kZWwub24oJ21vdXNlZW50ZXInLCBvbk1vdXNlRW50ZXIpO1xuICAgICAgICAgIHN3aXBlci4kZWwub24oJ21vdXNlbGVhdmUnLCBvbk1vdXNlTGVhdmUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGRldGFjaE1vdXNlRXZlbnRzKCkge1xuICAgICAgICBzd2lwZXIuJGVsLm9mZignbW91c2VlbnRlcicsIG9uTW91c2VFbnRlcik7XG4gICAgICAgIHN3aXBlci4kZWwub2ZmKCdtb3VzZWxlYXZlJywgb25Nb3VzZUxlYXZlKTtcbiAgICAgIH1cblxuICAgICAgb24oJ2luaXQnLCAoKSA9PiB7XG4gICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmF1dG9wbGF5LmVuYWJsZWQpIHtcbiAgICAgICAgICBzdGFydCgpO1xuICAgICAgICAgIGNvbnN0IGRvY3VtZW50ID0gZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd2aXNpYmlsaXR5Y2hhbmdlJywgb25WaXNpYmlsaXR5Q2hhbmdlKTtcbiAgICAgICAgICBhdHRhY2hNb3VzZUV2ZW50cygpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIG9uKCdiZWZvcmVUcmFuc2l0aW9uU3RhcnQnLCAoX3MsIHNwZWVkLCBpbnRlcm5hbCkgPT4ge1xuICAgICAgICBpZiAoc3dpcGVyLmF1dG9wbGF5LnJ1bm5pbmcpIHtcbiAgICAgICAgICBpZiAoaW50ZXJuYWwgfHwgIXN3aXBlci5wYXJhbXMuYXV0b3BsYXkuZGlzYWJsZU9uSW50ZXJhY3Rpb24pIHtcbiAgICAgICAgICAgIHN3aXBlci5hdXRvcGxheS5wYXVzZShzcGVlZCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0b3AoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb24oJ3NsaWRlckZpcnN0TW92ZScsICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci5hdXRvcGxheS5ydW5uaW5nKSB7XG4gICAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuYXV0b3BsYXkuZGlzYWJsZU9uSW50ZXJhY3Rpb24pIHtcbiAgICAgICAgICAgIHN0b3AoKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGF1c2UoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb24oJ3RvdWNoRW5kJywgKCkgPT4ge1xuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5jc3NNb2RlICYmIHN3aXBlci5hdXRvcGxheS5wYXVzZWQgJiYgIXN3aXBlci5wYXJhbXMuYXV0b3BsYXkuZGlzYWJsZU9uSW50ZXJhY3Rpb24pIHtcbiAgICAgICAgICBydW4oKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBvbignZGVzdHJveScsICgpID0+IHtcbiAgICAgICAgZGV0YWNoTW91c2VFdmVudHMoKTtcblxuICAgICAgICBpZiAoc3dpcGVyLmF1dG9wbGF5LnJ1bm5pbmcpIHtcbiAgICAgICAgICBzdG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkb2N1bWVudCA9IGdldERvY3VtZW50KCk7XG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Zpc2liaWxpdHljaGFuZ2UnLCBvblZpc2liaWxpdHlDaGFuZ2UpO1xuICAgICAgfSk7XG4gICAgICBPYmplY3QuYXNzaWduKHN3aXBlci5hdXRvcGxheSwge1xuICAgICAgICBwYXVzZSxcbiAgICAgICAgcnVuLFxuICAgICAgICBzdGFydCxcbiAgICAgICAgc3RvcFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gVGh1bWIoX3JlZikge1xuICAgICAgbGV0IHtcbiAgICAgICAgc3dpcGVyLFxuICAgICAgICBleHRlbmRQYXJhbXMsXG4gICAgICAgIG9uXG4gICAgICB9ID0gX3JlZjtcbiAgICAgIGV4dGVuZFBhcmFtcyh7XG4gICAgICAgIHRodW1iczoge1xuICAgICAgICAgIHN3aXBlcjogbnVsbCxcbiAgICAgICAgICBtdWx0aXBsZUFjdGl2ZVRodW1iczogdHJ1ZSxcbiAgICAgICAgICBhdXRvU2Nyb2xsT2Zmc2V0OiAwLFxuICAgICAgICAgIHNsaWRlVGh1bWJBY3RpdmVDbGFzczogJ3N3aXBlci1zbGlkZS10aHVtYi1hY3RpdmUnLFxuICAgICAgICAgIHRodW1ic0NvbnRhaW5lckNsYXNzOiAnc3dpcGVyLXRodW1icydcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBsZXQgaW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICAgIGxldCBzd2lwZXJDcmVhdGVkID0gZmFsc2U7XG4gICAgICBzd2lwZXIudGh1bWJzID0ge1xuICAgICAgICBzd2lwZXI6IG51bGxcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIG9uVGh1bWJDbGljaygpIHtcbiAgICAgICAgY29uc3QgdGh1bWJzU3dpcGVyID0gc3dpcGVyLnRodW1icy5zd2lwZXI7XG4gICAgICAgIGlmICghdGh1bWJzU3dpcGVyKSByZXR1cm47XG4gICAgICAgIGNvbnN0IGNsaWNrZWRJbmRleCA9IHRodW1ic1N3aXBlci5jbGlja2VkSW5kZXg7XG4gICAgICAgIGNvbnN0IGNsaWNrZWRTbGlkZSA9IHRodW1ic1N3aXBlci5jbGlja2VkU2xpZGU7XG4gICAgICAgIGlmIChjbGlja2VkU2xpZGUgJiYgJChjbGlja2VkU2xpZGUpLmhhc0NsYXNzKHN3aXBlci5wYXJhbXMudGh1bWJzLnNsaWRlVGh1bWJBY3RpdmVDbGFzcykpIHJldHVybjtcbiAgICAgICAgaWYgKHR5cGVvZiBjbGlja2VkSW5kZXggPT09ICd1bmRlZmluZWQnIHx8IGNsaWNrZWRJbmRleCA9PT0gbnVsbCkgcmV0dXJuO1xuICAgICAgICBsZXQgc2xpZGVUb0luZGV4O1xuXG4gICAgICAgIGlmICh0aHVtYnNTd2lwZXIucGFyYW1zLmxvb3ApIHtcbiAgICAgICAgICBzbGlkZVRvSW5kZXggPSBwYXJzZUludCgkKHRodW1ic1N3aXBlci5jbGlja2VkU2xpZGUpLmF0dHIoJ2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4JyksIDEwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzbGlkZVRvSW5kZXggPSBjbGlja2VkSW5kZXg7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5sb29wKSB7XG4gICAgICAgICAgbGV0IGN1cnJlbnRJbmRleCA9IHN3aXBlci5hY3RpdmVJbmRleDtcblxuICAgICAgICAgIGlmIChzd2lwZXIuc2xpZGVzLmVxKGN1cnJlbnRJbmRleCkuaGFzQ2xhc3Moc3dpcGVyLnBhcmFtcy5zbGlkZUR1cGxpY2F0ZUNsYXNzKSkge1xuICAgICAgICAgICAgc3dpcGVyLmxvb3BGaXgoKTsgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5cbiAgICAgICAgICAgIHN3aXBlci5fY2xpZW50TGVmdCA9IHN3aXBlci4kd3JhcHBlckVsWzBdLmNsaWVudExlZnQ7XG4gICAgICAgICAgICBjdXJyZW50SW5kZXggPSBzd2lwZXIuYWN0aXZlSW5kZXg7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgcHJldkluZGV4ID0gc3dpcGVyLnNsaWRlcy5lcShjdXJyZW50SW5kZXgpLnByZXZBbGwoYFtkYXRhLXN3aXBlci1zbGlkZS1pbmRleD1cIiR7c2xpZGVUb0luZGV4fVwiXWApLmVxKDApLmluZGV4KCk7XG4gICAgICAgICAgY29uc3QgbmV4dEluZGV4ID0gc3dpcGVyLnNsaWRlcy5lcShjdXJyZW50SW5kZXgpLm5leHRBbGwoYFtkYXRhLXN3aXBlci1zbGlkZS1pbmRleD1cIiR7c2xpZGVUb0luZGV4fVwiXWApLmVxKDApLmluZGV4KCk7XG4gICAgICAgICAgaWYgKHR5cGVvZiBwcmV2SW5kZXggPT09ICd1bmRlZmluZWQnKSBzbGlkZVRvSW5kZXggPSBuZXh0SW5kZXg7ZWxzZSBpZiAodHlwZW9mIG5leHRJbmRleCA9PT0gJ3VuZGVmaW5lZCcpIHNsaWRlVG9JbmRleCA9IHByZXZJbmRleDtlbHNlIGlmIChuZXh0SW5kZXggLSBjdXJyZW50SW5kZXggPCBjdXJyZW50SW5kZXggLSBwcmV2SW5kZXgpIHNsaWRlVG9JbmRleCA9IG5leHRJbmRleDtlbHNlIHNsaWRlVG9JbmRleCA9IHByZXZJbmRleDtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci5zbGlkZVRvKHNsaWRlVG9JbmRleCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGluaXQoKSB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICB0aHVtYnM6IHRodW1ic1BhcmFtc1xuICAgICAgICB9ID0gc3dpcGVyLnBhcmFtcztcbiAgICAgICAgaWYgKGluaXRpYWxpemVkKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAgICAgY29uc3QgU3dpcGVyQ2xhc3MgPSBzd2lwZXIuY29uc3RydWN0b3I7XG5cbiAgICAgICAgaWYgKHRodW1ic1BhcmFtcy5zd2lwZXIgaW5zdGFuY2VvZiBTd2lwZXJDbGFzcykge1xuICAgICAgICAgIHN3aXBlci50aHVtYnMuc3dpcGVyID0gdGh1bWJzUGFyYW1zLnN3aXBlcjtcbiAgICAgICAgICBPYmplY3QuYXNzaWduKHN3aXBlci50aHVtYnMuc3dpcGVyLm9yaWdpbmFsUGFyYW1zLCB7XG4gICAgICAgICAgICB3YXRjaFNsaWRlc1Byb2dyZXNzOiB0cnVlLFxuICAgICAgICAgICAgc2xpZGVUb0NsaWNrZWRTbGlkZTogZmFsc2VcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBPYmplY3QuYXNzaWduKHN3aXBlci50aHVtYnMuc3dpcGVyLnBhcmFtcywge1xuICAgICAgICAgICAgd2F0Y2hTbGlkZXNQcm9ncmVzczogdHJ1ZSxcbiAgICAgICAgICAgIHNsaWRlVG9DbGlja2VkU2xpZGU6IGZhbHNlXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QodGh1bWJzUGFyYW1zLnN3aXBlcikpIHtcbiAgICAgICAgICBjb25zdCB0aHVtYnNTd2lwZXJQYXJhbXMgPSBPYmplY3QuYXNzaWduKHt9LCB0aHVtYnNQYXJhbXMuc3dpcGVyKTtcbiAgICAgICAgICBPYmplY3QuYXNzaWduKHRodW1ic1N3aXBlclBhcmFtcywge1xuICAgICAgICAgICAgd2F0Y2hTbGlkZXNQcm9ncmVzczogdHJ1ZSxcbiAgICAgICAgICAgIHNsaWRlVG9DbGlja2VkU2xpZGU6IGZhbHNlXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgc3dpcGVyLnRodW1icy5zd2lwZXIgPSBuZXcgU3dpcGVyQ2xhc3ModGh1bWJzU3dpcGVyUGFyYW1zKTtcbiAgICAgICAgICBzd2lwZXJDcmVhdGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXBlci50aHVtYnMuc3dpcGVyLiRlbC5hZGRDbGFzcyhzd2lwZXIucGFyYW1zLnRodW1icy50aHVtYnNDb250YWluZXJDbGFzcyk7XG4gICAgICAgIHN3aXBlci50aHVtYnMuc3dpcGVyLm9uKCd0YXAnLCBvblRodW1iQ2xpY2spO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gdXBkYXRlKGluaXRpYWwpIHtcbiAgICAgICAgY29uc3QgdGh1bWJzU3dpcGVyID0gc3dpcGVyLnRodW1icy5zd2lwZXI7XG4gICAgICAgIGlmICghdGh1bWJzU3dpcGVyKSByZXR1cm47XG4gICAgICAgIGNvbnN0IHNsaWRlc1BlclZpZXcgPSB0aHVtYnNTd2lwZXIucGFyYW1zLnNsaWRlc1BlclZpZXcgPT09ICdhdXRvJyA/IHRodW1ic1N3aXBlci5zbGlkZXNQZXJWaWV3RHluYW1pYygpIDogdGh1bWJzU3dpcGVyLnBhcmFtcy5zbGlkZXNQZXJWaWV3O1xuICAgICAgICBjb25zdCBhdXRvU2Nyb2xsT2Zmc2V0ID0gc3dpcGVyLnBhcmFtcy50aHVtYnMuYXV0b1Njcm9sbE9mZnNldDtcbiAgICAgICAgY29uc3QgdXNlT2Zmc2V0ID0gYXV0b1Njcm9sbE9mZnNldCAmJiAhdGh1bWJzU3dpcGVyLnBhcmFtcy5sb29wO1xuXG4gICAgICAgIGlmIChzd2lwZXIucmVhbEluZGV4ICE9PSB0aHVtYnNTd2lwZXIucmVhbEluZGV4IHx8IHVzZU9mZnNldCkge1xuICAgICAgICAgIGxldCBjdXJyZW50VGh1bWJzSW5kZXggPSB0aHVtYnNTd2lwZXIuYWN0aXZlSW5kZXg7XG4gICAgICAgICAgbGV0IG5ld1RodW1ic0luZGV4O1xuICAgICAgICAgIGxldCBkaXJlY3Rpb247XG5cbiAgICAgICAgICBpZiAodGh1bWJzU3dpcGVyLnBhcmFtcy5sb29wKSB7XG4gICAgICAgICAgICBpZiAodGh1bWJzU3dpcGVyLnNsaWRlcy5lcShjdXJyZW50VGh1bWJzSW5kZXgpLmhhc0NsYXNzKHRodW1ic1N3aXBlci5wYXJhbXMuc2xpZGVEdXBsaWNhdGVDbGFzcykpIHtcbiAgICAgICAgICAgICAgdGh1bWJzU3dpcGVyLmxvb3BGaXgoKTsgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5cbiAgICAgICAgICAgICAgdGh1bWJzU3dpcGVyLl9jbGllbnRMZWZ0ID0gdGh1bWJzU3dpcGVyLiR3cmFwcGVyRWxbMF0uY2xpZW50TGVmdDtcbiAgICAgICAgICAgICAgY3VycmVudFRodW1ic0luZGV4ID0gdGh1bWJzU3dpcGVyLmFjdGl2ZUluZGV4O1xuICAgICAgICAgICAgfSAvLyBGaW5kIGFjdHVhbCB0aHVtYnMgaW5kZXggdG8gc2xpZGUgdG9cblxuXG4gICAgICAgICAgICBjb25zdCBwcmV2VGh1bWJzSW5kZXggPSB0aHVtYnNTd2lwZXIuc2xpZGVzLmVxKGN1cnJlbnRUaHVtYnNJbmRleCkucHJldkFsbChgW2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4PVwiJHtzd2lwZXIucmVhbEluZGV4fVwiXWApLmVxKDApLmluZGV4KCk7XG4gICAgICAgICAgICBjb25zdCBuZXh0VGh1bWJzSW5kZXggPSB0aHVtYnNTd2lwZXIuc2xpZGVzLmVxKGN1cnJlbnRUaHVtYnNJbmRleCkubmV4dEFsbChgW2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4PVwiJHtzd2lwZXIucmVhbEluZGV4fVwiXWApLmVxKDApLmluZGV4KCk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgcHJldlRodW1ic0luZGV4ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICBuZXdUaHVtYnNJbmRleCA9IG5leHRUaHVtYnNJbmRleDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG5leHRUaHVtYnNJbmRleCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgbmV3VGh1bWJzSW5kZXggPSBwcmV2VGh1bWJzSW5kZXg7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG5leHRUaHVtYnNJbmRleCAtIGN1cnJlbnRUaHVtYnNJbmRleCA9PT0gY3VycmVudFRodW1ic0luZGV4IC0gcHJldlRodW1ic0luZGV4KSB7XG4gICAgICAgICAgICAgIG5ld1RodW1ic0luZGV4ID0gdGh1bWJzU3dpcGVyLnBhcmFtcy5zbGlkZXNQZXJHcm91cCA+IDEgPyBuZXh0VGh1bWJzSW5kZXggOiBjdXJyZW50VGh1bWJzSW5kZXg7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG5leHRUaHVtYnNJbmRleCAtIGN1cnJlbnRUaHVtYnNJbmRleCA8IGN1cnJlbnRUaHVtYnNJbmRleCAtIHByZXZUaHVtYnNJbmRleCkge1xuICAgICAgICAgICAgICBuZXdUaHVtYnNJbmRleCA9IG5leHRUaHVtYnNJbmRleDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIG5ld1RodW1ic0luZGV4ID0gcHJldlRodW1ic0luZGV4O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkaXJlY3Rpb24gPSBzd2lwZXIuYWN0aXZlSW5kZXggPiBzd2lwZXIucHJldmlvdXNJbmRleCA/ICduZXh0JyA6ICdwcmV2JztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3VGh1bWJzSW5kZXggPSBzd2lwZXIucmVhbEluZGV4O1xuICAgICAgICAgICAgZGlyZWN0aW9uID0gbmV3VGh1bWJzSW5kZXggPiBzd2lwZXIucHJldmlvdXNJbmRleCA/ICduZXh0JyA6ICdwcmV2JztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodXNlT2Zmc2V0KSB7XG4gICAgICAgICAgICBuZXdUaHVtYnNJbmRleCArPSBkaXJlY3Rpb24gPT09ICduZXh0JyA/IGF1dG9TY3JvbGxPZmZzZXQgOiAtMSAqIGF1dG9TY3JvbGxPZmZzZXQ7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRodW1ic1N3aXBlci52aXNpYmxlU2xpZGVzSW5kZXhlcyAmJiB0aHVtYnNTd2lwZXIudmlzaWJsZVNsaWRlc0luZGV4ZXMuaW5kZXhPZihuZXdUaHVtYnNJbmRleCkgPCAwKSB7XG4gICAgICAgICAgICBpZiAodGh1bWJzU3dpcGVyLnBhcmFtcy5jZW50ZXJlZFNsaWRlcykge1xuICAgICAgICAgICAgICBpZiAobmV3VGh1bWJzSW5kZXggPiBjdXJyZW50VGh1bWJzSW5kZXgpIHtcbiAgICAgICAgICAgICAgICBuZXdUaHVtYnNJbmRleCA9IG5ld1RodW1ic0luZGV4IC0gTWF0aC5mbG9vcihzbGlkZXNQZXJWaWV3IC8gMikgKyAxO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG5ld1RodW1ic0luZGV4ID0gbmV3VGh1bWJzSW5kZXggKyBNYXRoLmZsb29yKHNsaWRlc1BlclZpZXcgLyAyKSAtIDE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAobmV3VGh1bWJzSW5kZXggPiBjdXJyZW50VGh1bWJzSW5kZXggJiYgdGh1bWJzU3dpcGVyLnBhcmFtcy5zbGlkZXNQZXJHcm91cCA9PT0gMSkgO1xuXG4gICAgICAgICAgICB0aHVtYnNTd2lwZXIuc2xpZGVUbyhuZXdUaHVtYnNJbmRleCwgaW5pdGlhbCA/IDAgOiB1bmRlZmluZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSAvLyBBY3RpdmF0ZSB0aHVtYnNcblxuXG4gICAgICAgIGxldCB0aHVtYnNUb0FjdGl2YXRlID0gMTtcbiAgICAgICAgY29uc3QgdGh1bWJBY3RpdmVDbGFzcyA9IHN3aXBlci5wYXJhbXMudGh1bWJzLnNsaWRlVGh1bWJBY3RpdmVDbGFzcztcblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5zbGlkZXNQZXJWaWV3ID4gMSAmJiAhc3dpcGVyLnBhcmFtcy5jZW50ZXJlZFNsaWRlcykge1xuICAgICAgICAgIHRodW1ic1RvQWN0aXZhdGUgPSBzd2lwZXIucGFyYW1zLnNsaWRlc1BlclZpZXc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXN3aXBlci5wYXJhbXMudGh1bWJzLm11bHRpcGxlQWN0aXZlVGh1bWJzKSB7XG4gICAgICAgICAgdGh1bWJzVG9BY3RpdmF0ZSA9IDE7XG4gICAgICAgIH1cblxuICAgICAgICB0aHVtYnNUb0FjdGl2YXRlID0gTWF0aC5mbG9vcih0aHVtYnNUb0FjdGl2YXRlKTtcbiAgICAgICAgdGh1bWJzU3dpcGVyLnNsaWRlcy5yZW1vdmVDbGFzcyh0aHVtYkFjdGl2ZUNsYXNzKTtcblxuICAgICAgICBpZiAodGh1bWJzU3dpcGVyLnBhcmFtcy5sb29wIHx8IHRodW1ic1N3aXBlci5wYXJhbXMudmlydHVhbCAmJiB0aHVtYnNTd2lwZXIucGFyYW1zLnZpcnR1YWwuZW5hYmxlZCkge1xuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGh1bWJzVG9BY3RpdmF0ZTsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aHVtYnNTd2lwZXIuJHdyYXBwZXJFbC5jaGlsZHJlbihgW2RhdGEtc3dpcGVyLXNsaWRlLWluZGV4PVwiJHtzd2lwZXIucmVhbEluZGV4ICsgaX1cIl1gKS5hZGRDbGFzcyh0aHVtYkFjdGl2ZUNsYXNzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aHVtYnNUb0FjdGl2YXRlOyBpICs9IDEpIHtcbiAgICAgICAgICAgIHRodW1ic1N3aXBlci5zbGlkZXMuZXEoc3dpcGVyLnJlYWxJbmRleCArIGkpLmFkZENsYXNzKHRodW1iQWN0aXZlQ2xhc3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBvbignYmVmb3JlSW5pdCcsICgpID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHRodW1ic1xuICAgICAgICB9ID0gc3dpcGVyLnBhcmFtcztcbiAgICAgICAgaWYgKCF0aHVtYnMgfHwgIXRodW1icy5zd2lwZXIpIHJldHVybjtcbiAgICAgICAgaW5pdCgpO1xuICAgICAgICB1cGRhdGUodHJ1ZSk7XG4gICAgICB9KTtcbiAgICAgIG9uKCdzbGlkZUNoYW5nZSB1cGRhdGUgcmVzaXplIG9ic2VydmVyVXBkYXRlJywgKCkgPT4ge1xuICAgICAgICBpZiAoIXN3aXBlci50aHVtYnMuc3dpcGVyKSByZXR1cm47XG4gICAgICAgIHVwZGF0ZSgpO1xuICAgICAgfSk7XG4gICAgICBvbignc2V0VHJhbnNpdGlvbicsIChfcywgZHVyYXRpb24pID0+IHtcbiAgICAgICAgY29uc3QgdGh1bWJzU3dpcGVyID0gc3dpcGVyLnRodW1icy5zd2lwZXI7XG4gICAgICAgIGlmICghdGh1bWJzU3dpcGVyKSByZXR1cm47XG4gICAgICAgIHRodW1ic1N3aXBlci5zZXRUcmFuc2l0aW9uKGR1cmF0aW9uKTtcbiAgICAgIH0pO1xuICAgICAgb24oJ2JlZm9yZURlc3Ryb3knLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHRodW1ic1N3aXBlciA9IHN3aXBlci50aHVtYnMuc3dpcGVyO1xuICAgICAgICBpZiAoIXRodW1ic1N3aXBlcikgcmV0dXJuO1xuXG4gICAgICAgIGlmIChzd2lwZXJDcmVhdGVkICYmIHRodW1ic1N3aXBlcikge1xuICAgICAgICAgIHRodW1ic1N3aXBlci5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgT2JqZWN0LmFzc2lnbihzd2lwZXIudGh1bWJzLCB7XG4gICAgICAgIGluaXQsXG4gICAgICAgIHVwZGF0ZVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZnJlZU1vZGUoX3JlZikge1xuICAgICAgbGV0IHtcbiAgICAgICAgc3dpcGVyLFxuICAgICAgICBleHRlbmRQYXJhbXMsXG4gICAgICAgIGVtaXQsXG4gICAgICAgIG9uY2VcbiAgICAgIH0gPSBfcmVmO1xuICAgICAgZXh0ZW5kUGFyYW1zKHtcbiAgICAgICAgZnJlZU1vZGU6IHtcbiAgICAgICAgICBlbmFibGVkOiBmYWxzZSxcbiAgICAgICAgICBtb21lbnR1bTogdHJ1ZSxcbiAgICAgICAgICBtb21lbnR1bVJhdGlvOiAxLFxuICAgICAgICAgIG1vbWVudHVtQm91bmNlOiB0cnVlLFxuICAgICAgICAgIG1vbWVudHVtQm91bmNlUmF0aW86IDEsXG4gICAgICAgICAgbW9tZW50dW1WZWxvY2l0eVJhdGlvOiAxLFxuICAgICAgICAgIHN0aWNreTogZmFsc2UsXG4gICAgICAgICAgbWluaW11bVZlbG9jaXR5OiAwLjAyXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBmdW5jdGlvbiBvblRvdWNoU3RhcnQoKSB7XG4gICAgICAgIGNvbnN0IHRyYW5zbGF0ZSA9IHN3aXBlci5nZXRUcmFuc2xhdGUoKTtcbiAgICAgICAgc3dpcGVyLnNldFRyYW5zbGF0ZSh0cmFuc2xhdGUpO1xuICAgICAgICBzd2lwZXIuc2V0VHJhbnNpdGlvbigwKTtcbiAgICAgICAgc3dpcGVyLnRvdWNoRXZlbnRzRGF0YS52ZWxvY2l0aWVzLmxlbmd0aCA9IDA7XG4gICAgICAgIHN3aXBlci5mcmVlTW9kZS5vblRvdWNoRW5kKHtcbiAgICAgICAgICBjdXJyZW50UG9zOiBzd2lwZXIucnRsID8gc3dpcGVyLnRyYW5zbGF0ZSA6IC1zd2lwZXIudHJhbnNsYXRlXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBvblRvdWNoTW92ZSgpIHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHRvdWNoRXZlbnRzRGF0YTogZGF0YSxcbiAgICAgICAgICB0b3VjaGVzXG4gICAgICAgIH0gPSBzd2lwZXI7IC8vIFZlbG9jaXR5XG5cbiAgICAgICAgaWYgKGRhdGEudmVsb2NpdGllcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICBkYXRhLnZlbG9jaXRpZXMucHVzaCh7XG4gICAgICAgICAgICBwb3NpdGlvbjogdG91Y2hlc1tzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyAnc3RhcnRYJyA6ICdzdGFydFknXSxcbiAgICAgICAgICAgIHRpbWU6IGRhdGEudG91Y2hTdGFydFRpbWVcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRhdGEudmVsb2NpdGllcy5wdXNoKHtcbiAgICAgICAgICBwb3NpdGlvbjogdG91Y2hlc1tzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyAnY3VycmVudFgnIDogJ2N1cnJlbnRZJ10sXG4gICAgICAgICAgdGltZTogbm93KClcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIG9uVG91Y2hFbmQoX3JlZjIpIHtcbiAgICAgICAgbGV0IHtcbiAgICAgICAgICBjdXJyZW50UG9zXG4gICAgICAgIH0gPSBfcmVmMjtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHBhcmFtcyxcbiAgICAgICAgICAkd3JhcHBlckVsLFxuICAgICAgICAgIHJ0bFRyYW5zbGF0ZTogcnRsLFxuICAgICAgICAgIHNuYXBHcmlkLFxuICAgICAgICAgIHRvdWNoRXZlbnRzRGF0YTogZGF0YVxuICAgICAgICB9ID0gc3dpcGVyOyAvLyBUaW1lIGRpZmZcblxuICAgICAgICBjb25zdCB0b3VjaEVuZFRpbWUgPSBub3coKTtcbiAgICAgICAgY29uc3QgdGltZURpZmYgPSB0b3VjaEVuZFRpbWUgLSBkYXRhLnRvdWNoU3RhcnRUaW1lO1xuXG4gICAgICAgIGlmIChjdXJyZW50UG9zIDwgLXN3aXBlci5taW5UcmFuc2xhdGUoKSkge1xuICAgICAgICAgIHN3aXBlci5zbGlkZVRvKHN3aXBlci5hY3RpdmVJbmRleCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGN1cnJlbnRQb3MgPiAtc3dpcGVyLm1heFRyYW5zbGF0ZSgpKSB7XG4gICAgICAgICAgaWYgKHN3aXBlci5zbGlkZXMubGVuZ3RoIDwgc25hcEdyaWQubGVuZ3RoKSB7XG4gICAgICAgICAgICBzd2lwZXIuc2xpZGVUbyhzbmFwR3JpZC5sZW5ndGggLSAxKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3dpcGVyLnNsaWRlVG8oc3dpcGVyLnNsaWRlcy5sZW5ndGggLSAxKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyYW1zLmZyZWVNb2RlLm1vbWVudHVtKSB7XG4gICAgICAgICAgaWYgKGRhdGEudmVsb2NpdGllcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBjb25zdCBsYXN0TW92ZUV2ZW50ID0gZGF0YS52ZWxvY2l0aWVzLnBvcCgpO1xuICAgICAgICAgICAgY29uc3QgdmVsb2NpdHlFdmVudCA9IGRhdGEudmVsb2NpdGllcy5wb3AoKTtcbiAgICAgICAgICAgIGNvbnN0IGRpc3RhbmNlID0gbGFzdE1vdmVFdmVudC5wb3NpdGlvbiAtIHZlbG9jaXR5RXZlbnQucG9zaXRpb247XG4gICAgICAgICAgICBjb25zdCB0aW1lID0gbGFzdE1vdmVFdmVudC50aW1lIC0gdmVsb2NpdHlFdmVudC50aW1lO1xuICAgICAgICAgICAgc3dpcGVyLnZlbG9jaXR5ID0gZGlzdGFuY2UgLyB0aW1lO1xuICAgICAgICAgICAgc3dpcGVyLnZlbG9jaXR5IC89IDI7XG5cbiAgICAgICAgICAgIGlmIChNYXRoLmFicyhzd2lwZXIudmVsb2NpdHkpIDwgcGFyYW1zLmZyZWVNb2RlLm1pbmltdW1WZWxvY2l0eSkge1xuICAgICAgICAgICAgICBzd2lwZXIudmVsb2NpdHkgPSAwO1xuICAgICAgICAgICAgfSAvLyB0aGlzIGltcGxpZXMgdGhhdCB0aGUgdXNlciBzdG9wcGVkIG1vdmluZyBhIGZpbmdlciB0aGVuIHJlbGVhc2VkLlxuICAgICAgICAgICAgLy8gVGhlcmUgd291bGQgYmUgbm8gZXZlbnRzIHdpdGggZGlzdGFuY2UgemVybywgc28gdGhlIGxhc3QgZXZlbnQgaXMgc3RhbGUuXG5cblxuICAgICAgICAgICAgaWYgKHRpbWUgPiAxNTAgfHwgbm93KCkgLSBsYXN0TW92ZUV2ZW50LnRpbWUgPiAzMDApIHtcbiAgICAgICAgICAgICAgc3dpcGVyLnZlbG9jaXR5ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3dpcGVyLnZlbG9jaXR5ID0gMDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzd2lwZXIudmVsb2NpdHkgKj0gcGFyYW1zLmZyZWVNb2RlLm1vbWVudHVtVmVsb2NpdHlSYXRpbztcbiAgICAgICAgICBkYXRhLnZlbG9jaXRpZXMubGVuZ3RoID0gMDtcbiAgICAgICAgICBsZXQgbW9tZW50dW1EdXJhdGlvbiA9IDEwMDAgKiBwYXJhbXMuZnJlZU1vZGUubW9tZW50dW1SYXRpbztcbiAgICAgICAgICBjb25zdCBtb21lbnR1bURpc3RhbmNlID0gc3dpcGVyLnZlbG9jaXR5ICogbW9tZW50dW1EdXJhdGlvbjtcbiAgICAgICAgICBsZXQgbmV3UG9zaXRpb24gPSBzd2lwZXIudHJhbnNsYXRlICsgbW9tZW50dW1EaXN0YW5jZTtcbiAgICAgICAgICBpZiAocnRsKSBuZXdQb3NpdGlvbiA9IC1uZXdQb3NpdGlvbjtcbiAgICAgICAgICBsZXQgZG9Cb3VuY2UgPSBmYWxzZTtcbiAgICAgICAgICBsZXQgYWZ0ZXJCb3VuY2VQb3NpdGlvbjtcbiAgICAgICAgICBjb25zdCBib3VuY2VBbW91bnQgPSBNYXRoLmFicyhzd2lwZXIudmVsb2NpdHkpICogMjAgKiBwYXJhbXMuZnJlZU1vZGUubW9tZW50dW1Cb3VuY2VSYXRpbztcbiAgICAgICAgICBsZXQgbmVlZHNMb29wRml4O1xuXG4gICAgICAgICAgaWYgKG5ld1Bvc2l0aW9uIDwgc3dpcGVyLm1heFRyYW5zbGF0ZSgpKSB7XG4gICAgICAgICAgICBpZiAocGFyYW1zLmZyZWVNb2RlLm1vbWVudHVtQm91bmNlKSB7XG4gICAgICAgICAgICAgIGlmIChuZXdQb3NpdGlvbiArIHN3aXBlci5tYXhUcmFuc2xhdGUoKSA8IC1ib3VuY2VBbW91bnQpIHtcbiAgICAgICAgICAgICAgICBuZXdQb3NpdGlvbiA9IHN3aXBlci5tYXhUcmFuc2xhdGUoKSAtIGJvdW5jZUFtb3VudDtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGFmdGVyQm91bmNlUG9zaXRpb24gPSBzd2lwZXIubWF4VHJhbnNsYXRlKCk7XG4gICAgICAgICAgICAgIGRvQm91bmNlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgZGF0YS5hbGxvd01vbWVudHVtQm91bmNlID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIG5ld1Bvc2l0aW9uID0gc3dpcGVyLm1heFRyYW5zbGF0ZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocGFyYW1zLmxvb3AgJiYgcGFyYW1zLmNlbnRlcmVkU2xpZGVzKSBuZWVkc0xvb3BGaXggPSB0cnVlO1xuICAgICAgICAgIH0gZWxzZSBpZiAobmV3UG9zaXRpb24gPiBzd2lwZXIubWluVHJhbnNsYXRlKCkpIHtcbiAgICAgICAgICAgIGlmIChwYXJhbXMuZnJlZU1vZGUubW9tZW50dW1Cb3VuY2UpIHtcbiAgICAgICAgICAgICAgaWYgKG5ld1Bvc2l0aW9uIC0gc3dpcGVyLm1pblRyYW5zbGF0ZSgpID4gYm91bmNlQW1vdW50KSB7XG4gICAgICAgICAgICAgICAgbmV3UG9zaXRpb24gPSBzd2lwZXIubWluVHJhbnNsYXRlKCkgKyBib3VuY2VBbW91bnQ7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBhZnRlckJvdW5jZVBvc2l0aW9uID0gc3dpcGVyLm1pblRyYW5zbGF0ZSgpO1xuICAgICAgICAgICAgICBkb0JvdW5jZSA9IHRydWU7XG4gICAgICAgICAgICAgIGRhdGEuYWxsb3dNb21lbnR1bUJvdW5jZSA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBuZXdQb3NpdGlvbiA9IHN3aXBlci5taW5UcmFuc2xhdGUoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHBhcmFtcy5sb29wICYmIHBhcmFtcy5jZW50ZXJlZFNsaWRlcykgbmVlZHNMb29wRml4ID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHBhcmFtcy5mcmVlTW9kZS5zdGlja3kpIHtcbiAgICAgICAgICAgIGxldCBuZXh0U2xpZGU7XG5cbiAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgc25hcEdyaWQubGVuZ3RoOyBqICs9IDEpIHtcbiAgICAgICAgICAgICAgaWYgKHNuYXBHcmlkW2pdID4gLW5ld1Bvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgbmV4dFNsaWRlID0gajtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMoc25hcEdyaWRbbmV4dFNsaWRlXSAtIG5ld1Bvc2l0aW9uKSA8IE1hdGguYWJzKHNuYXBHcmlkW25leHRTbGlkZSAtIDFdIC0gbmV3UG9zaXRpb24pIHx8IHN3aXBlci5zd2lwZURpcmVjdGlvbiA9PT0gJ25leHQnKSB7XG4gICAgICAgICAgICAgIG5ld1Bvc2l0aW9uID0gc25hcEdyaWRbbmV4dFNsaWRlXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIG5ld1Bvc2l0aW9uID0gc25hcEdyaWRbbmV4dFNsaWRlIC0gMV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG5ld1Bvc2l0aW9uID0gLW5ld1Bvc2l0aW9uO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChuZWVkc0xvb3BGaXgpIHtcbiAgICAgICAgICAgIG9uY2UoJ3RyYW5zaXRpb25FbmQnLCAoKSA9PiB7XG4gICAgICAgICAgICAgIHN3aXBlci5sb29wRml4KCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IC8vIEZpeCBkdXJhdGlvblxuXG5cbiAgICAgICAgICBpZiAoc3dpcGVyLnZlbG9jaXR5ICE9PSAwKSB7XG4gICAgICAgICAgICBpZiAocnRsKSB7XG4gICAgICAgICAgICAgIG1vbWVudHVtRHVyYXRpb24gPSBNYXRoLmFicygoLW5ld1Bvc2l0aW9uIC0gc3dpcGVyLnRyYW5zbGF0ZSkgLyBzd2lwZXIudmVsb2NpdHkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbW9tZW50dW1EdXJhdGlvbiA9IE1hdGguYWJzKChuZXdQb3NpdGlvbiAtIHN3aXBlci50cmFuc2xhdGUpIC8gc3dpcGVyLnZlbG9jaXR5KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHBhcmFtcy5mcmVlTW9kZS5zdGlja3kpIHtcbiAgICAgICAgICAgICAgLy8gSWYgZnJlZU1vZGUuc3RpY2t5IGlzIGFjdGl2ZSBhbmQgdGhlIHVzZXIgZW5kcyBhIHN3aXBlIHdpdGggYSBzbG93LXZlbG9jaXR5XG4gICAgICAgICAgICAgIC8vIGV2ZW50LCB0aGVuIGR1cmF0aW9ucyBjYW4gYmUgMjArIHNlY29uZHMgdG8gc2xpZGUgb25lIChvciB6ZXJvISkgc2xpZGVzLlxuICAgICAgICAgICAgICAvLyBJdCdzIGVhc3kgdG8gc2VlIHRoaXMgd2hlbiBzaW11bGF0aW5nIHRvdWNoIHdpdGggbW91c2UgZXZlbnRzLiBUbyBmaXggdGhpcyxcbiAgICAgICAgICAgICAgLy8gbGltaXQgc2luZ2xlLXNsaWRlIHN3aXBlcyB0byB0aGUgZGVmYXVsdCBzbGlkZSBkdXJhdGlvbi4gVGhpcyBhbHNvIGhhcyB0aGVcbiAgICAgICAgICAgICAgLy8gbmljZSBzaWRlIGVmZmVjdCBvZiBtYXRjaGluZyBzbGlkZSBzcGVlZCBpZiB0aGUgdXNlciBzdG9wcGVkIG1vdmluZyBiZWZvcmVcbiAgICAgICAgICAgICAgLy8gbGlmdGluZyBmaW5nZXIgb3IgbW91c2UgdnMuIG1vdmluZyBzbG93bHkgYmVmb3JlIGxpZnRpbmcgdGhlIGZpbmdlci9tb3VzZS5cbiAgICAgICAgICAgICAgLy8gRm9yIGZhc3RlciBzd2lwZXMsIGFsc28gYXBwbHkgbGltaXRzIChhbGJlaXQgaGlnaGVyIG9uZXMpLlxuICAgICAgICAgICAgICBjb25zdCBtb3ZlRGlzdGFuY2UgPSBNYXRoLmFicygocnRsID8gLW5ld1Bvc2l0aW9uIDogbmV3UG9zaXRpb24pIC0gc3dpcGVyLnRyYW5zbGF0ZSk7XG4gICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRTbGlkZVNpemUgPSBzd2lwZXIuc2xpZGVzU2l6ZXNHcmlkW3N3aXBlci5hY3RpdmVJbmRleF07XG5cbiAgICAgICAgICAgICAgaWYgKG1vdmVEaXN0YW5jZSA8IGN1cnJlbnRTbGlkZVNpemUpIHtcbiAgICAgICAgICAgICAgICBtb21lbnR1bUR1cmF0aW9uID0gcGFyYW1zLnNwZWVkO1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1vdmVEaXN0YW5jZSA8IDIgKiBjdXJyZW50U2xpZGVTaXplKSB7XG4gICAgICAgICAgICAgICAgbW9tZW50dW1EdXJhdGlvbiA9IHBhcmFtcy5zcGVlZCAqIDEuNTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb21lbnR1bUR1cmF0aW9uID0gcGFyYW1zLnNwZWVkICogMi41O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChwYXJhbXMuZnJlZU1vZGUuc3RpY2t5KSB7XG4gICAgICAgICAgICBzd2lwZXIuc2xpZGVUb0Nsb3Nlc3QoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocGFyYW1zLmZyZWVNb2RlLm1vbWVudHVtQm91bmNlICYmIGRvQm91bmNlKSB7XG4gICAgICAgICAgICBzd2lwZXIudXBkYXRlUHJvZ3Jlc3MoYWZ0ZXJCb3VuY2VQb3NpdGlvbik7XG4gICAgICAgICAgICBzd2lwZXIuc2V0VHJhbnNpdGlvbihtb21lbnR1bUR1cmF0aW9uKTtcbiAgICAgICAgICAgIHN3aXBlci5zZXRUcmFuc2xhdGUobmV3UG9zaXRpb24pO1xuICAgICAgICAgICAgc3dpcGVyLnRyYW5zaXRpb25TdGFydCh0cnVlLCBzd2lwZXIuc3dpcGVEaXJlY3Rpb24pO1xuICAgICAgICAgICAgc3dpcGVyLmFuaW1hdGluZyA9IHRydWU7XG4gICAgICAgICAgICAkd3JhcHBlckVsLnRyYW5zaXRpb25FbmQoKCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoIXN3aXBlciB8fCBzd2lwZXIuZGVzdHJveWVkIHx8ICFkYXRhLmFsbG93TW9tZW50dW1Cb3VuY2UpIHJldHVybjtcbiAgICAgICAgICAgICAgZW1pdCgnbW9tZW50dW1Cb3VuY2UnKTtcbiAgICAgICAgICAgICAgc3dpcGVyLnNldFRyYW5zaXRpb24ocGFyYW1zLnNwZWVkKTtcbiAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgc3dpcGVyLnNldFRyYW5zbGF0ZShhZnRlckJvdW5jZVBvc2l0aW9uKTtcbiAgICAgICAgICAgICAgICAkd3JhcHBlckVsLnRyYW5zaXRpb25FbmQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCFzd2lwZXIgfHwgc3dpcGVyLmRlc3Ryb3llZCkgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgc3dpcGVyLnRyYW5zaXRpb25FbmQoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHN3aXBlci52ZWxvY2l0eSkge1xuICAgICAgICAgICAgZW1pdCgnX2ZyZWVNb2RlTm9Nb21lbnR1bVJlbGVhc2UnKTtcbiAgICAgICAgICAgIHN3aXBlci51cGRhdGVQcm9ncmVzcyhuZXdQb3NpdGlvbik7XG4gICAgICAgICAgICBzd2lwZXIuc2V0VHJhbnNpdGlvbihtb21lbnR1bUR1cmF0aW9uKTtcbiAgICAgICAgICAgIHN3aXBlci5zZXRUcmFuc2xhdGUobmV3UG9zaXRpb24pO1xuICAgICAgICAgICAgc3dpcGVyLnRyYW5zaXRpb25TdGFydCh0cnVlLCBzd2lwZXIuc3dpcGVEaXJlY3Rpb24pO1xuXG4gICAgICAgICAgICBpZiAoIXN3aXBlci5hbmltYXRpbmcpIHtcbiAgICAgICAgICAgICAgc3dpcGVyLmFuaW1hdGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICR3cmFwcGVyRWwudHJhbnNpdGlvbkVuZCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFzd2lwZXIgfHwgc3dpcGVyLmRlc3Ryb3llZCkgcmV0dXJuO1xuICAgICAgICAgICAgICAgIHN3aXBlci50cmFuc2l0aW9uRW5kKCk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzd2lwZXIudXBkYXRlUHJvZ3Jlc3MobmV3UG9zaXRpb24pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHN3aXBlci51cGRhdGVBY3RpdmVJbmRleCgpO1xuICAgICAgICAgIHN3aXBlci51cGRhdGVTbGlkZXNDbGFzc2VzKCk7XG4gICAgICAgIH0gZWxzZSBpZiAocGFyYW1zLmZyZWVNb2RlLnN0aWNreSkge1xuICAgICAgICAgIHN3aXBlci5zbGlkZVRvQ2xvc2VzdCgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbXMuZnJlZU1vZGUpIHtcbiAgICAgICAgICBlbWl0KCdfZnJlZU1vZGVOb01vbWVudHVtUmVsZWFzZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFwYXJhbXMuZnJlZU1vZGUubW9tZW50dW0gfHwgdGltZURpZmYgPj0gcGFyYW1zLmxvbmdTd2lwZXNNcykge1xuICAgICAgICAgIHN3aXBlci51cGRhdGVQcm9ncmVzcygpO1xuICAgICAgICAgIHN3aXBlci51cGRhdGVBY3RpdmVJbmRleCgpO1xuICAgICAgICAgIHN3aXBlci51cGRhdGVTbGlkZXNDbGFzc2VzKCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgT2JqZWN0LmFzc2lnbihzd2lwZXIsIHtcbiAgICAgICAgZnJlZU1vZGU6IHtcbiAgICAgICAgICBvblRvdWNoU3RhcnQsXG4gICAgICAgICAgb25Ub3VjaE1vdmUsXG4gICAgICAgICAgb25Ub3VjaEVuZFxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBHcmlkKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZXh0ZW5kUGFyYW1zXG4gICAgICB9ID0gX3JlZjtcbiAgICAgIGV4dGVuZFBhcmFtcyh7XG4gICAgICAgIGdyaWQ6IHtcbiAgICAgICAgICByb3dzOiAxLFxuICAgICAgICAgIGZpbGw6ICdjb2x1bW4nXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgbGV0IHNsaWRlc051bWJlckV2ZW5Ub1Jvd3M7XG4gICAgICBsZXQgc2xpZGVzUGVyUm93O1xuICAgICAgbGV0IG51bUZ1bGxDb2x1bW5zO1xuXG4gICAgICBjb25zdCBpbml0U2xpZGVzID0gc2xpZGVzTGVuZ3RoID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHNsaWRlc1BlclZpZXdcbiAgICAgICAgfSA9IHN3aXBlci5wYXJhbXM7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICByb3dzLFxuICAgICAgICAgIGZpbGxcbiAgICAgICAgfSA9IHN3aXBlci5wYXJhbXMuZ3JpZDtcbiAgICAgICAgc2xpZGVzUGVyUm93ID0gc2xpZGVzTnVtYmVyRXZlblRvUm93cyAvIHJvd3M7XG4gICAgICAgIG51bUZ1bGxDb2x1bW5zID0gTWF0aC5mbG9vcihzbGlkZXNMZW5ndGggLyByb3dzKTtcblxuICAgICAgICBpZiAoTWF0aC5mbG9vcihzbGlkZXNMZW5ndGggLyByb3dzKSA9PT0gc2xpZGVzTGVuZ3RoIC8gcm93cykge1xuICAgICAgICAgIHNsaWRlc051bWJlckV2ZW5Ub1Jvd3MgPSBzbGlkZXNMZW5ndGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2xpZGVzTnVtYmVyRXZlblRvUm93cyA9IE1hdGguY2VpbChzbGlkZXNMZW5ndGggLyByb3dzKSAqIHJvd3M7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2xpZGVzUGVyVmlldyAhPT0gJ2F1dG8nICYmIGZpbGwgPT09ICdyb3cnKSB7XG4gICAgICAgICAgc2xpZGVzTnVtYmVyRXZlblRvUm93cyA9IE1hdGgubWF4KHNsaWRlc051bWJlckV2ZW5Ub1Jvd3MsIHNsaWRlc1BlclZpZXcgKiByb3dzKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgY29uc3QgdXBkYXRlU2xpZGUgPSAoaSwgc2xpZGUsIHNsaWRlc0xlbmd0aCwgZ2V0RGlyZWN0aW9uTGFiZWwpID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHNsaWRlc1Blckdyb3VwLFxuICAgICAgICAgIHNwYWNlQmV0d2VlblxuICAgICAgICB9ID0gc3dpcGVyLnBhcmFtcztcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHJvd3MsXG4gICAgICAgICAgZmlsbFxuICAgICAgICB9ID0gc3dpcGVyLnBhcmFtcy5ncmlkOyAvLyBTZXQgc2xpZGVzIG9yZGVyXG5cbiAgICAgICAgbGV0IG5ld1NsaWRlT3JkZXJJbmRleDtcbiAgICAgICAgbGV0IGNvbHVtbjtcbiAgICAgICAgbGV0IHJvdztcblxuICAgICAgICBpZiAoZmlsbCA9PT0gJ3JvdycgJiYgc2xpZGVzUGVyR3JvdXAgPiAxKSB7XG4gICAgICAgICAgY29uc3QgZ3JvdXBJbmRleCA9IE1hdGguZmxvb3IoaSAvIChzbGlkZXNQZXJHcm91cCAqIHJvd3MpKTtcbiAgICAgICAgICBjb25zdCBzbGlkZUluZGV4SW5Hcm91cCA9IGkgLSByb3dzICogc2xpZGVzUGVyR3JvdXAgKiBncm91cEluZGV4O1xuICAgICAgICAgIGNvbnN0IGNvbHVtbnNJbkdyb3VwID0gZ3JvdXBJbmRleCA9PT0gMCA/IHNsaWRlc1Blckdyb3VwIDogTWF0aC5taW4oTWF0aC5jZWlsKChzbGlkZXNMZW5ndGggLSBncm91cEluZGV4ICogcm93cyAqIHNsaWRlc1Blckdyb3VwKSAvIHJvd3MpLCBzbGlkZXNQZXJHcm91cCk7XG4gICAgICAgICAgcm93ID0gTWF0aC5mbG9vcihzbGlkZUluZGV4SW5Hcm91cCAvIGNvbHVtbnNJbkdyb3VwKTtcbiAgICAgICAgICBjb2x1bW4gPSBzbGlkZUluZGV4SW5Hcm91cCAtIHJvdyAqIGNvbHVtbnNJbkdyb3VwICsgZ3JvdXBJbmRleCAqIHNsaWRlc1Blckdyb3VwO1xuICAgICAgICAgIG5ld1NsaWRlT3JkZXJJbmRleCA9IGNvbHVtbiArIHJvdyAqIHNsaWRlc051bWJlckV2ZW5Ub1Jvd3MgLyByb3dzO1xuICAgICAgICAgIHNsaWRlLmNzcyh7XG4gICAgICAgICAgICAnLXdlYmtpdC1vcmRlcic6IG5ld1NsaWRlT3JkZXJJbmRleCxcbiAgICAgICAgICAgIG9yZGVyOiBuZXdTbGlkZU9yZGVySW5kZXhcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChmaWxsID09PSAnY29sdW1uJykge1xuICAgICAgICAgIGNvbHVtbiA9IE1hdGguZmxvb3IoaSAvIHJvd3MpO1xuICAgICAgICAgIHJvdyA9IGkgLSBjb2x1bW4gKiByb3dzO1xuXG4gICAgICAgICAgaWYgKGNvbHVtbiA+IG51bUZ1bGxDb2x1bW5zIHx8IGNvbHVtbiA9PT0gbnVtRnVsbENvbHVtbnMgJiYgcm93ID09PSByb3dzIC0gMSkge1xuICAgICAgICAgICAgcm93ICs9IDE7XG5cbiAgICAgICAgICAgIGlmIChyb3cgPj0gcm93cykge1xuICAgICAgICAgICAgICByb3cgPSAwO1xuICAgICAgICAgICAgICBjb2x1bW4gKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcm93ID0gTWF0aC5mbG9vcihpIC8gc2xpZGVzUGVyUm93KTtcbiAgICAgICAgICBjb2x1bW4gPSBpIC0gcm93ICogc2xpZGVzUGVyUm93O1xuICAgICAgICB9XG5cbiAgICAgICAgc2xpZGUuY3NzKGdldERpcmVjdGlvbkxhYmVsKCdtYXJnaW4tdG9wJyksIHJvdyAhPT0gMCA/IHNwYWNlQmV0d2VlbiAmJiBgJHtzcGFjZUJldHdlZW59cHhgIDogJycpO1xuICAgICAgfTtcblxuICAgICAgY29uc3QgdXBkYXRlV3JhcHBlclNpemUgPSAoc2xpZGVTaXplLCBzbmFwR3JpZCwgZ2V0RGlyZWN0aW9uTGFiZWwpID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHNwYWNlQmV0d2VlbixcbiAgICAgICAgICBjZW50ZXJlZFNsaWRlcyxcbiAgICAgICAgICByb3VuZExlbmd0aHNcbiAgICAgICAgfSA9IHN3aXBlci5wYXJhbXM7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICByb3dzXG4gICAgICAgIH0gPSBzd2lwZXIucGFyYW1zLmdyaWQ7XG4gICAgICAgIHN3aXBlci52aXJ0dWFsU2l6ZSA9IChzbGlkZVNpemUgKyBzcGFjZUJldHdlZW4pICogc2xpZGVzTnVtYmVyRXZlblRvUm93cztcbiAgICAgICAgc3dpcGVyLnZpcnR1YWxTaXplID0gTWF0aC5jZWlsKHN3aXBlci52aXJ0dWFsU2l6ZSAvIHJvd3MpIC0gc3BhY2VCZXR3ZWVuO1xuICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbC5jc3Moe1xuICAgICAgICAgIFtnZXREaXJlY3Rpb25MYWJlbCgnd2lkdGgnKV06IGAke3N3aXBlci52aXJ0dWFsU2l6ZSArIHNwYWNlQmV0d2Vlbn1weGBcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKGNlbnRlcmVkU2xpZGVzKSB7XG4gICAgICAgICAgc25hcEdyaWQuc3BsaWNlKDAsIHNuYXBHcmlkLmxlbmd0aCk7XG4gICAgICAgICAgY29uc3QgbmV3U2xpZGVzR3JpZCA9IFtdO1xuXG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbmFwR3JpZC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgbGV0IHNsaWRlc0dyaWRJdGVtID0gc25hcEdyaWRbaV07XG4gICAgICAgICAgICBpZiAocm91bmRMZW5ndGhzKSBzbGlkZXNHcmlkSXRlbSA9IE1hdGguZmxvb3Ioc2xpZGVzR3JpZEl0ZW0pO1xuICAgICAgICAgICAgaWYgKHNuYXBHcmlkW2ldIDwgc3dpcGVyLnZpcnR1YWxTaXplICsgc25hcEdyaWRbMF0pIG5ld1NsaWRlc0dyaWQucHVzaChzbGlkZXNHcmlkSXRlbSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc25hcEdyaWQucHVzaCguLi5uZXdTbGlkZXNHcmlkKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgc3dpcGVyLmdyaWQgPSB7XG4gICAgICAgIGluaXRTbGlkZXMsXG4gICAgICAgIHVwZGF0ZVNsaWRlLFxuICAgICAgICB1cGRhdGVXcmFwcGVyU2l6ZVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhcHBlbmRTbGlkZShzbGlkZXMpIHtcbiAgICAgIGNvbnN0IHN3aXBlciA9IHRoaXM7XG4gICAgICBjb25zdCB7XG4gICAgICAgICR3cmFwcGVyRWwsXG4gICAgICAgIHBhcmFtc1xuICAgICAgfSA9IHN3aXBlcjtcblxuICAgICAgaWYgKHBhcmFtcy5sb29wKSB7XG4gICAgICAgIHN3aXBlci5sb29wRGVzdHJveSgpO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIHNsaWRlcyA9PT0gJ29iamVjdCcgJiYgJ2xlbmd0aCcgaW4gc2xpZGVzKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2xpZGVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgaWYgKHNsaWRlc1tpXSkgJHdyYXBwZXJFbC5hcHBlbmQoc2xpZGVzW2ldKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgJHdyYXBwZXJFbC5hcHBlbmQoc2xpZGVzKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5sb29wKSB7XG4gICAgICAgIHN3aXBlci5sb29wQ3JlYXRlKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghcGFyYW1zLm9ic2VydmVyKSB7XG4gICAgICAgIHN3aXBlci51cGRhdGUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwcmVwZW5kU2xpZGUoc2xpZGVzKSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3Qge1xuICAgICAgICBwYXJhbXMsXG4gICAgICAgICR3cmFwcGVyRWwsXG4gICAgICAgIGFjdGl2ZUluZGV4XG4gICAgICB9ID0gc3dpcGVyO1xuXG4gICAgICBpZiAocGFyYW1zLmxvb3ApIHtcbiAgICAgICAgc3dpcGVyLmxvb3BEZXN0cm95KCk7XG4gICAgICB9XG5cbiAgICAgIGxldCBuZXdBY3RpdmVJbmRleCA9IGFjdGl2ZUluZGV4ICsgMTtcblxuICAgICAgaWYgKHR5cGVvZiBzbGlkZXMgPT09ICdvYmplY3QnICYmICdsZW5ndGgnIGluIHNsaWRlcykge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNsaWRlcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgIGlmIChzbGlkZXNbaV0pICR3cmFwcGVyRWwucHJlcGVuZChzbGlkZXNbaV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgbmV3QWN0aXZlSW5kZXggPSBhY3RpdmVJbmRleCArIHNsaWRlcy5sZW5ndGg7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAkd3JhcHBlckVsLnByZXBlbmQoc2xpZGVzKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5sb29wKSB7XG4gICAgICAgIHN3aXBlci5sb29wQ3JlYXRlKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghcGFyYW1zLm9ic2VydmVyKSB7XG4gICAgICAgIHN3aXBlci51cGRhdGUoKTtcbiAgICAgIH1cblxuICAgICAgc3dpcGVyLnNsaWRlVG8obmV3QWN0aXZlSW5kZXgsIDAsIGZhbHNlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhZGRTbGlkZShpbmRleCwgc2xpZGVzKSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3Qge1xuICAgICAgICAkd3JhcHBlckVsLFxuICAgICAgICBwYXJhbXMsXG4gICAgICAgIGFjdGl2ZUluZGV4XG4gICAgICB9ID0gc3dpcGVyO1xuICAgICAgbGV0IGFjdGl2ZUluZGV4QnVmZmVyID0gYWN0aXZlSW5kZXg7XG5cbiAgICAgIGlmIChwYXJhbXMubG9vcCkge1xuICAgICAgICBhY3RpdmVJbmRleEJ1ZmZlciAtPSBzd2lwZXIubG9vcGVkU2xpZGVzO1xuICAgICAgICBzd2lwZXIubG9vcERlc3Ryb3koKTtcbiAgICAgICAgc3dpcGVyLnNsaWRlcyA9ICR3cmFwcGVyRWwuY2hpbGRyZW4oYC4ke3BhcmFtcy5zbGlkZUNsYXNzfWApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBiYXNlTGVuZ3RoID0gc3dpcGVyLnNsaWRlcy5sZW5ndGg7XG5cbiAgICAgIGlmIChpbmRleCA8PSAwKSB7XG4gICAgICAgIHN3aXBlci5wcmVwZW5kU2xpZGUoc2xpZGVzKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW5kZXggPj0gYmFzZUxlbmd0aCkge1xuICAgICAgICBzd2lwZXIuYXBwZW5kU2xpZGUoc2xpZGVzKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBsZXQgbmV3QWN0aXZlSW5kZXggPSBhY3RpdmVJbmRleEJ1ZmZlciA+IGluZGV4ID8gYWN0aXZlSW5kZXhCdWZmZXIgKyAxIDogYWN0aXZlSW5kZXhCdWZmZXI7XG4gICAgICBjb25zdCBzbGlkZXNCdWZmZXIgPSBbXTtcblxuICAgICAgZm9yIChsZXQgaSA9IGJhc2VMZW5ndGggLSAxOyBpID49IGluZGV4OyBpIC09IDEpIHtcbiAgICAgICAgY29uc3QgY3VycmVudFNsaWRlID0gc3dpcGVyLnNsaWRlcy5lcShpKTtcbiAgICAgICAgY3VycmVudFNsaWRlLnJlbW92ZSgpO1xuICAgICAgICBzbGlkZXNCdWZmZXIudW5zaGlmdChjdXJyZW50U2xpZGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIHNsaWRlcyA9PT0gJ29iamVjdCcgJiYgJ2xlbmd0aCcgaW4gc2xpZGVzKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2xpZGVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgaWYgKHNsaWRlc1tpXSkgJHdyYXBwZXJFbC5hcHBlbmQoc2xpZGVzW2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld0FjdGl2ZUluZGV4ID0gYWN0aXZlSW5kZXhCdWZmZXIgPiBpbmRleCA/IGFjdGl2ZUluZGV4QnVmZmVyICsgc2xpZGVzLmxlbmd0aCA6IGFjdGl2ZUluZGV4QnVmZmVyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgJHdyYXBwZXJFbC5hcHBlbmQoc2xpZGVzKTtcbiAgICAgIH1cblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbGlkZXNCdWZmZXIubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgJHdyYXBwZXJFbC5hcHBlbmQoc2xpZGVzQnVmZmVyW2ldKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5sb29wKSB7XG4gICAgICAgIHN3aXBlci5sb29wQ3JlYXRlKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghcGFyYW1zLm9ic2VydmVyKSB7XG4gICAgICAgIHN3aXBlci51cGRhdGUoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5sb29wKSB7XG4gICAgICAgIHN3aXBlci5zbGlkZVRvKG5ld0FjdGl2ZUluZGV4ICsgc3dpcGVyLmxvb3BlZFNsaWRlcywgMCwgZmFsc2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3dpcGVyLnNsaWRlVG8obmV3QWN0aXZlSW5kZXgsIDAsIGZhbHNlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW1vdmVTbGlkZShzbGlkZXNJbmRleGVzKSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3Qge1xuICAgICAgICBwYXJhbXMsXG4gICAgICAgICR3cmFwcGVyRWwsXG4gICAgICAgIGFjdGl2ZUluZGV4XG4gICAgICB9ID0gc3dpcGVyO1xuICAgICAgbGV0IGFjdGl2ZUluZGV4QnVmZmVyID0gYWN0aXZlSW5kZXg7XG5cbiAgICAgIGlmIChwYXJhbXMubG9vcCkge1xuICAgICAgICBhY3RpdmVJbmRleEJ1ZmZlciAtPSBzd2lwZXIubG9vcGVkU2xpZGVzO1xuICAgICAgICBzd2lwZXIubG9vcERlc3Ryb3koKTtcbiAgICAgICAgc3dpcGVyLnNsaWRlcyA9ICR3cmFwcGVyRWwuY2hpbGRyZW4oYC4ke3BhcmFtcy5zbGlkZUNsYXNzfWApO1xuICAgICAgfVxuXG4gICAgICBsZXQgbmV3QWN0aXZlSW5kZXggPSBhY3RpdmVJbmRleEJ1ZmZlcjtcbiAgICAgIGxldCBpbmRleFRvUmVtb3ZlO1xuXG4gICAgICBpZiAodHlwZW9mIHNsaWRlc0luZGV4ZXMgPT09ICdvYmplY3QnICYmICdsZW5ndGgnIGluIHNsaWRlc0luZGV4ZXMpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbGlkZXNJbmRleGVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgaW5kZXhUb1JlbW92ZSA9IHNsaWRlc0luZGV4ZXNbaV07XG4gICAgICAgICAgaWYgKHN3aXBlci5zbGlkZXNbaW5kZXhUb1JlbW92ZV0pIHN3aXBlci5zbGlkZXMuZXEoaW5kZXhUb1JlbW92ZSkucmVtb3ZlKCk7XG4gICAgICAgICAgaWYgKGluZGV4VG9SZW1vdmUgPCBuZXdBY3RpdmVJbmRleCkgbmV3QWN0aXZlSW5kZXggLT0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld0FjdGl2ZUluZGV4ID0gTWF0aC5tYXgobmV3QWN0aXZlSW5kZXgsIDApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5kZXhUb1JlbW92ZSA9IHNsaWRlc0luZGV4ZXM7XG4gICAgICAgIGlmIChzd2lwZXIuc2xpZGVzW2luZGV4VG9SZW1vdmVdKSBzd2lwZXIuc2xpZGVzLmVxKGluZGV4VG9SZW1vdmUpLnJlbW92ZSgpO1xuICAgICAgICBpZiAoaW5kZXhUb1JlbW92ZSA8IG5ld0FjdGl2ZUluZGV4KSBuZXdBY3RpdmVJbmRleCAtPSAxO1xuICAgICAgICBuZXdBY3RpdmVJbmRleCA9IE1hdGgubWF4KG5ld0FjdGl2ZUluZGV4LCAwKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5sb29wKSB7XG4gICAgICAgIHN3aXBlci5sb29wQ3JlYXRlKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghcGFyYW1zLm9ic2VydmVyKSB7XG4gICAgICAgIHN3aXBlci51cGRhdGUoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5sb29wKSB7XG4gICAgICAgIHN3aXBlci5zbGlkZVRvKG5ld0FjdGl2ZUluZGV4ICsgc3dpcGVyLmxvb3BlZFNsaWRlcywgMCwgZmFsc2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3dpcGVyLnNsaWRlVG8obmV3QWN0aXZlSW5kZXgsIDAsIGZhbHNlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW1vdmVBbGxTbGlkZXMoKSB7XG4gICAgICBjb25zdCBzd2lwZXIgPSB0aGlzO1xuICAgICAgY29uc3Qgc2xpZGVzSW5kZXhlcyA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHN3aXBlci5zbGlkZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgc2xpZGVzSW5kZXhlcy5wdXNoKGkpO1xuICAgICAgfVxuXG4gICAgICBzd2lwZXIucmVtb3ZlU2xpZGUoc2xpZGVzSW5kZXhlcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gTWFuaXB1bGF0aW9uKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlclxuICAgICAgfSA9IF9yZWY7XG4gICAgICBPYmplY3QuYXNzaWduKHN3aXBlciwge1xuICAgICAgICBhcHBlbmRTbGlkZTogYXBwZW5kU2xpZGUuYmluZChzd2lwZXIpLFxuICAgICAgICBwcmVwZW5kU2xpZGU6IHByZXBlbmRTbGlkZS5iaW5kKHN3aXBlciksXG4gICAgICAgIGFkZFNsaWRlOiBhZGRTbGlkZS5iaW5kKHN3aXBlciksXG4gICAgICAgIHJlbW92ZVNsaWRlOiByZW1vdmVTbGlkZS5iaW5kKHN3aXBlciksXG4gICAgICAgIHJlbW92ZUFsbFNsaWRlczogcmVtb3ZlQWxsU2xpZGVzLmJpbmQoc3dpcGVyKVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZWZmZWN0SW5pdChwYXJhbXMpIHtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgZWZmZWN0LFxuICAgICAgICBzd2lwZXIsXG4gICAgICAgIG9uLFxuICAgICAgICBzZXRUcmFuc2xhdGUsXG4gICAgICAgIHNldFRyYW5zaXRpb24sXG4gICAgICAgIG92ZXJ3cml0ZVBhcmFtcyxcbiAgICAgICAgcGVyc3BlY3RpdmVcbiAgICAgIH0gPSBwYXJhbXM7XG4gICAgICBvbignYmVmb3JlSW5pdCcsICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuZWZmZWN0ICE9PSBlZmZlY3QpIHJldHVybjtcbiAgICAgICAgc3dpcGVyLmNsYXNzTmFtZXMucHVzaChgJHtzd2lwZXIucGFyYW1zLmNvbnRhaW5lck1vZGlmaWVyQ2xhc3N9JHtlZmZlY3R9YCk7XG5cbiAgICAgICAgaWYgKHBlcnNwZWN0aXZlICYmIHBlcnNwZWN0aXZlKCkpIHtcbiAgICAgICAgICBzd2lwZXIuY2xhc3NOYW1lcy5wdXNoKGAke3N3aXBlci5wYXJhbXMuY29udGFpbmVyTW9kaWZpZXJDbGFzc30zZGApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgb3ZlcndyaXRlUGFyYW1zUmVzdWx0ID0gb3ZlcndyaXRlUGFyYW1zID8gb3ZlcndyaXRlUGFyYW1zKCkgOiB7fTtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihzd2lwZXIucGFyYW1zLCBvdmVyd3JpdGVQYXJhbXNSZXN1bHQpO1xuICAgICAgICBPYmplY3QuYXNzaWduKHN3aXBlci5vcmlnaW5hbFBhcmFtcywgb3ZlcndyaXRlUGFyYW1zUmVzdWx0KTtcbiAgICAgIH0pO1xuICAgICAgb24oJ3NldFRyYW5zbGF0ZScsICgpID0+IHtcbiAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuZWZmZWN0ICE9PSBlZmZlY3QpIHJldHVybjtcbiAgICAgICAgc2V0VHJhbnNsYXRlKCk7XG4gICAgICB9KTtcbiAgICAgIG9uKCdzZXRUcmFuc2l0aW9uJywgKF9zLCBkdXJhdGlvbikgPT4ge1xuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5lZmZlY3QgIT09IGVmZmVjdCkgcmV0dXJuO1xuICAgICAgICBzZXRUcmFuc2l0aW9uKGR1cmF0aW9uKTtcbiAgICAgIH0pO1xuICAgICAgbGV0IHJlcXVpcmVVcGRhdGVPblZpcnR1YWw7XG4gICAgICBvbigndmlydHVhbFVwZGF0ZScsICgpID0+IHtcbiAgICAgICAgaWYgKCFzd2lwZXIuc2xpZGVzLmxlbmd0aCkge1xuICAgICAgICAgIHJlcXVpcmVVcGRhdGVPblZpcnR1YWwgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgICAgICBpZiAocmVxdWlyZVVwZGF0ZU9uVmlydHVhbCAmJiBzd2lwZXIuc2xpZGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgc2V0VHJhbnNsYXRlKCk7XG4gICAgICAgICAgICByZXF1aXJlVXBkYXRlT25WaXJ0dWFsID0gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVmZmVjdFRhcmdldChlZmZlY3RQYXJhbXMsICRzbGlkZUVsKSB7XG4gICAgICBpZiAoZWZmZWN0UGFyYW1zLnRyYW5zZm9ybUVsKSB7XG4gICAgICAgIHJldHVybiAkc2xpZGVFbC5maW5kKGVmZmVjdFBhcmFtcy50cmFuc2Zvcm1FbCkuY3NzKHtcbiAgICAgICAgICAnYmFja2ZhY2UtdmlzaWJpbGl0eSc6ICdoaWRkZW4nLFxuICAgICAgICAgICctd2Via2l0LWJhY2tmYWNlLXZpc2liaWxpdHknOiAnaGlkZGVuJ1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuICRzbGlkZUVsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVmZmVjdFZpcnR1YWxUcmFuc2l0aW9uRW5kKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZHVyYXRpb24sXG4gICAgICAgIHRyYW5zZm9ybUVsLFxuICAgICAgICBhbGxTbGlkZXNcbiAgICAgIH0gPSBfcmVmO1xuICAgICAgY29uc3Qge1xuICAgICAgICBzbGlkZXMsXG4gICAgICAgIGFjdGl2ZUluZGV4LFxuICAgICAgICAkd3JhcHBlckVsXG4gICAgICB9ID0gc3dpcGVyO1xuXG4gICAgICBpZiAoc3dpcGVyLnBhcmFtcy52aXJ0dWFsVHJhbnNsYXRlICYmIGR1cmF0aW9uICE9PSAwKSB7XG4gICAgICAgIGxldCBldmVudFRyaWdnZXJlZCA9IGZhbHNlO1xuICAgICAgICBsZXQgJHRyYW5zaXRpb25FbmRUYXJnZXQ7XG5cbiAgICAgICAgaWYgKGFsbFNsaWRlcykge1xuICAgICAgICAgICR0cmFuc2l0aW9uRW5kVGFyZ2V0ID0gdHJhbnNmb3JtRWwgPyBzbGlkZXMuZmluZCh0cmFuc2Zvcm1FbCkgOiBzbGlkZXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgJHRyYW5zaXRpb25FbmRUYXJnZXQgPSB0cmFuc2Zvcm1FbCA/IHNsaWRlcy5lcShhY3RpdmVJbmRleCkuZmluZCh0cmFuc2Zvcm1FbCkgOiBzbGlkZXMuZXEoYWN0aXZlSW5kZXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgJHRyYW5zaXRpb25FbmRUYXJnZXQudHJhbnNpdGlvbkVuZCgoKSA9PiB7XG4gICAgICAgICAgaWYgKGV2ZW50VHJpZ2dlcmVkKSByZXR1cm47XG4gICAgICAgICAgaWYgKCFzd2lwZXIgfHwgc3dpcGVyLmRlc3Ryb3llZCkgcmV0dXJuO1xuICAgICAgICAgIGV2ZW50VHJpZ2dlcmVkID0gdHJ1ZTtcbiAgICAgICAgICBzd2lwZXIuYW5pbWF0aW5nID0gZmFsc2U7XG4gICAgICAgICAgY29uc3QgdHJpZ2dlckV2ZW50cyA9IFsnd2Via2l0VHJhbnNpdGlvbkVuZCcsICd0cmFuc2l0aW9uZW5kJ107XG5cbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRyaWdnZXJFdmVudHMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgICR3cmFwcGVyRWwudHJpZ2dlcih0cmlnZ2VyRXZlbnRzW2ldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIEVmZmVjdEZhZGUoX3JlZikge1xuICAgICAgbGV0IHtcbiAgICAgICAgc3dpcGVyLFxuICAgICAgICBleHRlbmRQYXJhbXMsXG4gICAgICAgIG9uXG4gICAgICB9ID0gX3JlZjtcbiAgICAgIGV4dGVuZFBhcmFtcyh7XG4gICAgICAgIGZhZGVFZmZlY3Q6IHtcbiAgICAgICAgICBjcm9zc0ZhZGU6IGZhbHNlLFxuICAgICAgICAgIHRyYW5zZm9ybUVsOiBudWxsXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBzZXRUcmFuc2xhdGUgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBzbGlkZXNcbiAgICAgICAgfSA9IHN3aXBlcjtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gc3dpcGVyLnBhcmFtcy5mYWRlRWZmZWN0O1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2xpZGVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgY29uc3QgJHNsaWRlRWwgPSBzd2lwZXIuc2xpZGVzLmVxKGkpO1xuICAgICAgICAgIGNvbnN0IG9mZnNldCA9ICRzbGlkZUVsWzBdLnN3aXBlclNsaWRlT2Zmc2V0O1xuICAgICAgICAgIGxldCB0eCA9IC1vZmZzZXQ7XG4gICAgICAgICAgaWYgKCFzd2lwZXIucGFyYW1zLnZpcnR1YWxUcmFuc2xhdGUpIHR4IC09IHN3aXBlci50cmFuc2xhdGU7XG4gICAgICAgICAgbGV0IHR5ID0gMDtcblxuICAgICAgICAgIGlmICghc3dpcGVyLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgICB0eSA9IHR4O1xuICAgICAgICAgICAgdHggPSAwO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHNsaWRlT3BhY2l0eSA9IHN3aXBlci5wYXJhbXMuZmFkZUVmZmVjdC5jcm9zc0ZhZGUgPyBNYXRoLm1heCgxIC0gTWF0aC5hYnMoJHNsaWRlRWxbMF0ucHJvZ3Jlc3MpLCAwKSA6IDEgKyBNYXRoLm1pbihNYXRoLm1heCgkc2xpZGVFbFswXS5wcm9ncmVzcywgLTEpLCAwKTtcbiAgICAgICAgICBjb25zdCAkdGFyZ2V0RWwgPSBlZmZlY3RUYXJnZXQocGFyYW1zLCAkc2xpZGVFbCk7XG4gICAgICAgICAgJHRhcmdldEVsLmNzcyh7XG4gICAgICAgICAgICBvcGFjaXR5OiBzbGlkZU9wYWNpdHlcbiAgICAgICAgICB9KS50cmFuc2Zvcm0oYHRyYW5zbGF0ZTNkKCR7dHh9cHgsICR7dHl9cHgsIDBweClgKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgY29uc3Qgc2V0VHJhbnNpdGlvbiA9IGR1cmF0aW9uID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHRyYW5zZm9ybUVsXG4gICAgICAgIH0gPSBzd2lwZXIucGFyYW1zLmZhZGVFZmZlY3Q7XG4gICAgICAgIGNvbnN0ICR0cmFuc2l0aW9uRWxlbWVudHMgPSB0cmFuc2Zvcm1FbCA/IHN3aXBlci5zbGlkZXMuZmluZCh0cmFuc2Zvcm1FbCkgOiBzd2lwZXIuc2xpZGVzO1xuICAgICAgICAkdHJhbnNpdGlvbkVsZW1lbnRzLnRyYW5zaXRpb24oZHVyYXRpb24pO1xuICAgICAgICBlZmZlY3RWaXJ0dWFsVHJhbnNpdGlvbkVuZCh7XG4gICAgICAgICAgc3dpcGVyLFxuICAgICAgICAgIGR1cmF0aW9uLFxuICAgICAgICAgIHRyYW5zZm9ybUVsLFxuICAgICAgICAgIGFsbFNsaWRlczogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIGVmZmVjdEluaXQoe1xuICAgICAgICBlZmZlY3Q6ICdmYWRlJyxcbiAgICAgICAgc3dpcGVyLFxuICAgICAgICBvbixcbiAgICAgICAgc2V0VHJhbnNsYXRlLFxuICAgICAgICBzZXRUcmFuc2l0aW9uLFxuICAgICAgICBvdmVyd3JpdGVQYXJhbXM6ICgpID0+ICh7XG4gICAgICAgICAgc2xpZGVzUGVyVmlldzogMSxcbiAgICAgICAgICBzbGlkZXNQZXJHcm91cDogMSxcbiAgICAgICAgICB3YXRjaFNsaWRlc1Byb2dyZXNzOiB0cnVlLFxuICAgICAgICAgIHNwYWNlQmV0d2VlbjogMCxcbiAgICAgICAgICB2aXJ0dWFsVHJhbnNsYXRlOiAhc3dpcGVyLnBhcmFtcy5jc3NNb2RlXG4gICAgICAgIH0pXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBFZmZlY3RDdWJlKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZXh0ZW5kUGFyYW1zLFxuICAgICAgICBvblxuICAgICAgfSA9IF9yZWY7XG4gICAgICBleHRlbmRQYXJhbXMoe1xuICAgICAgICBjdWJlRWZmZWN0OiB7XG4gICAgICAgICAgc2xpZGVTaGFkb3dzOiB0cnVlLFxuICAgICAgICAgIHNoYWRvdzogdHJ1ZSxcbiAgICAgICAgICBzaGFkb3dPZmZzZXQ6IDIwLFxuICAgICAgICAgIHNoYWRvd1NjYWxlOiAwLjk0XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBzZXRUcmFuc2xhdGUgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAkZWwsXG4gICAgICAgICAgJHdyYXBwZXJFbCxcbiAgICAgICAgICBzbGlkZXMsXG4gICAgICAgICAgd2lkdGg6IHN3aXBlcldpZHRoLFxuICAgICAgICAgIGhlaWdodDogc3dpcGVySGVpZ2h0LFxuICAgICAgICAgIHJ0bFRyYW5zbGF0ZTogcnRsLFxuICAgICAgICAgIHNpemU6IHN3aXBlclNpemUsXG4gICAgICAgICAgYnJvd3NlclxuICAgICAgICB9ID0gc3dpcGVyO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zLmN1YmVFZmZlY3Q7XG4gICAgICAgIGNvbnN0IGlzSG9yaXpvbnRhbCA9IHN3aXBlci5pc0hvcml6b250YWwoKTtcbiAgICAgICAgY29uc3QgaXNWaXJ0dWFsID0gc3dpcGVyLnZpcnR1YWwgJiYgc3dpcGVyLnBhcmFtcy52aXJ0dWFsLmVuYWJsZWQ7XG4gICAgICAgIGxldCB3cmFwcGVyUm90YXRlID0gMDtcbiAgICAgICAgbGV0ICRjdWJlU2hhZG93RWw7XG5cbiAgICAgICAgaWYgKHBhcmFtcy5zaGFkb3cpIHtcbiAgICAgICAgICBpZiAoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICAkY3ViZVNoYWRvd0VsID0gJHdyYXBwZXJFbC5maW5kKCcuc3dpcGVyLWN1YmUtc2hhZG93Jyk7XG5cbiAgICAgICAgICAgIGlmICgkY3ViZVNoYWRvd0VsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAkY3ViZVNoYWRvd0VsID0gJCgnPGRpdiBjbGFzcz1cInN3aXBlci1jdWJlLXNoYWRvd1wiPjwvZGl2PicpO1xuICAgICAgICAgICAgICAkd3JhcHBlckVsLmFwcGVuZCgkY3ViZVNoYWRvd0VsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJGN1YmVTaGFkb3dFbC5jc3Moe1xuICAgICAgICAgICAgICBoZWlnaHQ6IGAke3N3aXBlcldpZHRofXB4YFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICRjdWJlU2hhZG93RWwgPSAkZWwuZmluZCgnLnN3aXBlci1jdWJlLXNoYWRvdycpO1xuXG4gICAgICAgICAgICBpZiAoJGN1YmVTaGFkb3dFbC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgJGN1YmVTaGFkb3dFbCA9ICQoJzxkaXYgY2xhc3M9XCJzd2lwZXItY3ViZS1zaGFkb3dcIj48L2Rpdj4nKTtcbiAgICAgICAgICAgICAgJGVsLmFwcGVuZCgkY3ViZVNoYWRvd0VsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNsaWRlcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgIGNvbnN0ICRzbGlkZUVsID0gc2xpZGVzLmVxKGkpO1xuICAgICAgICAgIGxldCBzbGlkZUluZGV4ID0gaTtcblxuICAgICAgICAgIGlmIChpc1ZpcnR1YWwpIHtcbiAgICAgICAgICAgIHNsaWRlSW5kZXggPSBwYXJzZUludCgkc2xpZGVFbC5hdHRyKCdkYXRhLXN3aXBlci1zbGlkZS1pbmRleCcpLCAxMCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbGV0IHNsaWRlQW5nbGUgPSBzbGlkZUluZGV4ICogOTA7XG4gICAgICAgICAgbGV0IHJvdW5kID0gTWF0aC5mbG9vcihzbGlkZUFuZ2xlIC8gMzYwKTtcblxuICAgICAgICAgIGlmIChydGwpIHtcbiAgICAgICAgICAgIHNsaWRlQW5nbGUgPSAtc2xpZGVBbmdsZTtcbiAgICAgICAgICAgIHJvdW5kID0gTWF0aC5mbG9vcigtc2xpZGVBbmdsZSAvIDM2MCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgcHJvZ3Jlc3MgPSBNYXRoLm1heChNYXRoLm1pbigkc2xpZGVFbFswXS5wcm9ncmVzcywgMSksIC0xKTtcbiAgICAgICAgICBsZXQgdHggPSAwO1xuICAgICAgICAgIGxldCB0eSA9IDA7XG4gICAgICAgICAgbGV0IHR6ID0gMDtcblxuICAgICAgICAgIGlmIChzbGlkZUluZGV4ICUgNCA9PT0gMCkge1xuICAgICAgICAgICAgdHggPSAtcm91bmQgKiA0ICogc3dpcGVyU2l6ZTtcbiAgICAgICAgICAgIHR6ID0gMDtcbiAgICAgICAgICB9IGVsc2UgaWYgKChzbGlkZUluZGV4IC0gMSkgJSA0ID09PSAwKSB7XG4gICAgICAgICAgICB0eCA9IDA7XG4gICAgICAgICAgICB0eiA9IC1yb3VuZCAqIDQgKiBzd2lwZXJTaXplO1xuICAgICAgICAgIH0gZWxzZSBpZiAoKHNsaWRlSW5kZXggLSAyKSAlIDQgPT09IDApIHtcbiAgICAgICAgICAgIHR4ID0gc3dpcGVyU2l6ZSArIHJvdW5kICogNCAqIHN3aXBlclNpemU7XG4gICAgICAgICAgICB0eiA9IHN3aXBlclNpemU7XG4gICAgICAgICAgfSBlbHNlIGlmICgoc2xpZGVJbmRleCAtIDMpICUgNCA9PT0gMCkge1xuICAgICAgICAgICAgdHggPSAtc3dpcGVyU2l6ZTtcbiAgICAgICAgICAgIHR6ID0gMyAqIHN3aXBlclNpemUgKyBzd2lwZXJTaXplICogNCAqIHJvdW5kO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChydGwpIHtcbiAgICAgICAgICAgIHR4ID0gLXR4O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICB0eSA9IHR4O1xuICAgICAgICAgICAgdHggPSAwO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybSA9IGByb3RhdGVYKCR7aXNIb3Jpem9udGFsID8gMCA6IC1zbGlkZUFuZ2xlfWRlZykgcm90YXRlWSgke2lzSG9yaXpvbnRhbCA/IHNsaWRlQW5nbGUgOiAwfWRlZykgdHJhbnNsYXRlM2QoJHt0eH1weCwgJHt0eX1weCwgJHt0en1weClgO1xuXG4gICAgICAgICAgaWYgKHByb2dyZXNzIDw9IDEgJiYgcHJvZ3Jlc3MgPiAtMSkge1xuICAgICAgICAgICAgd3JhcHBlclJvdGF0ZSA9IHNsaWRlSW5kZXggKiA5MCArIHByb2dyZXNzICogOTA7XG4gICAgICAgICAgICBpZiAocnRsKSB3cmFwcGVyUm90YXRlID0gLXNsaWRlSW5kZXggKiA5MCAtIHByb2dyZXNzICogOTA7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgJHNsaWRlRWwudHJhbnNmb3JtKHRyYW5zZm9ybSk7XG5cbiAgICAgICAgICBpZiAocGFyYW1zLnNsaWRlU2hhZG93cykge1xuICAgICAgICAgICAgLy8gU2V0IHNoYWRvd3NcbiAgICAgICAgICAgIGxldCBzaGFkb3dCZWZvcmUgPSBpc0hvcml6b250YWwgPyAkc2xpZGVFbC5maW5kKCcuc3dpcGVyLXNsaWRlLXNoYWRvdy1sZWZ0JykgOiAkc2xpZGVFbC5maW5kKCcuc3dpcGVyLXNsaWRlLXNoYWRvdy10b3AnKTtcbiAgICAgICAgICAgIGxldCBzaGFkb3dBZnRlciA9IGlzSG9yaXpvbnRhbCA/ICRzbGlkZUVsLmZpbmQoJy5zd2lwZXItc2xpZGUtc2hhZG93LXJpZ2h0JykgOiAkc2xpZGVFbC5maW5kKCcuc3dpcGVyLXNsaWRlLXNoYWRvdy1ib3R0b20nKTtcblxuICAgICAgICAgICAgaWYgKHNoYWRvd0JlZm9yZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgc2hhZG93QmVmb3JlID0gJChgPGRpdiBjbGFzcz1cInN3aXBlci1zbGlkZS1zaGFkb3ctJHtpc0hvcml6b250YWwgPyAnbGVmdCcgOiAndG9wJ31cIj48L2Rpdj5gKTtcbiAgICAgICAgICAgICAgJHNsaWRlRWwuYXBwZW5kKHNoYWRvd0JlZm9yZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzaGFkb3dBZnRlci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgc2hhZG93QWZ0ZXIgPSAkKGA8ZGl2IGNsYXNzPVwic3dpcGVyLXNsaWRlLXNoYWRvdy0ke2lzSG9yaXpvbnRhbCA/ICdyaWdodCcgOiAnYm90dG9tJ31cIj48L2Rpdj5gKTtcbiAgICAgICAgICAgICAgJHNsaWRlRWwuYXBwZW5kKHNoYWRvd0FmdGVyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHNoYWRvd0JlZm9yZS5sZW5ndGgpIHNoYWRvd0JlZm9yZVswXS5zdHlsZS5vcGFjaXR5ID0gTWF0aC5tYXgoLXByb2dyZXNzLCAwKTtcbiAgICAgICAgICAgIGlmIChzaGFkb3dBZnRlci5sZW5ndGgpIHNoYWRvd0FmdGVyWzBdLnN0eWxlLm9wYWNpdHkgPSBNYXRoLm1heChwcm9ncmVzcywgMCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgJHdyYXBwZXJFbC5jc3Moe1xuICAgICAgICAgICctd2Via2l0LXRyYW5zZm9ybS1vcmlnaW4nOiBgNTAlIDUwJSAtJHtzd2lwZXJTaXplIC8gMn1weGAsXG4gICAgICAgICAgJ3RyYW5zZm9ybS1vcmlnaW4nOiBgNTAlIDUwJSAtJHtzd2lwZXJTaXplIC8gMn1weGBcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHBhcmFtcy5zaGFkb3cpIHtcbiAgICAgICAgICBpZiAoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICAkY3ViZVNoYWRvd0VsLnRyYW5zZm9ybShgdHJhbnNsYXRlM2QoMHB4LCAke3N3aXBlcldpZHRoIC8gMiArIHBhcmFtcy5zaGFkb3dPZmZzZXR9cHgsICR7LXN3aXBlcldpZHRoIC8gMn1weCkgcm90YXRlWCg5MGRlZykgcm90YXRlWigwZGVnKSBzY2FsZSgke3BhcmFtcy5zaGFkb3dTY2FsZX0pYCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHNoYWRvd0FuZ2xlID0gTWF0aC5hYnMod3JhcHBlclJvdGF0ZSkgLSBNYXRoLmZsb29yKE1hdGguYWJzKHdyYXBwZXJSb3RhdGUpIC8gOTApICogOTA7XG4gICAgICAgICAgICBjb25zdCBtdWx0aXBsaWVyID0gMS41IC0gKE1hdGguc2luKHNoYWRvd0FuZ2xlICogMiAqIE1hdGguUEkgLyAzNjApIC8gMiArIE1hdGguY29zKHNoYWRvd0FuZ2xlICogMiAqIE1hdGguUEkgLyAzNjApIC8gMik7XG4gICAgICAgICAgICBjb25zdCBzY2FsZTEgPSBwYXJhbXMuc2hhZG93U2NhbGU7XG4gICAgICAgICAgICBjb25zdCBzY2FsZTIgPSBwYXJhbXMuc2hhZG93U2NhbGUgLyBtdWx0aXBsaWVyO1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gcGFyYW1zLnNoYWRvd09mZnNldDtcbiAgICAgICAgICAgICRjdWJlU2hhZG93RWwudHJhbnNmb3JtKGBzY2FsZTNkKCR7c2NhbGUxfSwgMSwgJHtzY2FsZTJ9KSB0cmFuc2xhdGUzZCgwcHgsICR7c3dpcGVySGVpZ2h0IC8gMiArIG9mZnNldH1weCwgJHstc3dpcGVySGVpZ2h0IC8gMiAvIHNjYWxlMn1weCkgcm90YXRlWCgtOTBkZWcpYCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgekZhY3RvciA9IGJyb3dzZXIuaXNTYWZhcmkgfHwgYnJvd3Nlci5pc1dlYlZpZXcgPyAtc3dpcGVyU2l6ZSAvIDIgOiAwO1xuICAgICAgICAkd3JhcHBlckVsLnRyYW5zZm9ybShgdHJhbnNsYXRlM2QoMHB4LDAsJHt6RmFjdG9yfXB4KSByb3RhdGVYKCR7c3dpcGVyLmlzSG9yaXpvbnRhbCgpID8gMCA6IHdyYXBwZXJSb3RhdGV9ZGVnKSByb3RhdGVZKCR7c3dpcGVyLmlzSG9yaXpvbnRhbCgpID8gLXdyYXBwZXJSb3RhdGUgOiAwfWRlZylgKTtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHNldFRyYW5zaXRpb24gPSBkdXJhdGlvbiA9PiB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAkZWwsXG4gICAgICAgICAgc2xpZGVzXG4gICAgICAgIH0gPSBzd2lwZXI7XG4gICAgICAgIHNsaWRlcy50cmFuc2l0aW9uKGR1cmF0aW9uKS5maW5kKCcuc3dpcGVyLXNsaWRlLXNoYWRvdy10b3AsIC5zd2lwZXItc2xpZGUtc2hhZG93LXJpZ2h0LCAuc3dpcGVyLXNsaWRlLXNoYWRvdy1ib3R0b20sIC5zd2lwZXItc2xpZGUtc2hhZG93LWxlZnQnKS50cmFuc2l0aW9uKGR1cmF0aW9uKTtcblxuICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5jdWJlRWZmZWN0LnNoYWRvdyAmJiAhc3dpcGVyLmlzSG9yaXpvbnRhbCgpKSB7XG4gICAgICAgICAgJGVsLmZpbmQoJy5zd2lwZXItY3ViZS1zaGFkb3cnKS50cmFuc2l0aW9uKGR1cmF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgZWZmZWN0SW5pdCh7XG4gICAgICAgIGVmZmVjdDogJ2N1YmUnLFxuICAgICAgICBzd2lwZXIsXG4gICAgICAgIG9uLFxuICAgICAgICBzZXRUcmFuc2xhdGUsXG4gICAgICAgIHNldFRyYW5zaXRpb24sXG4gICAgICAgIHBlcnNwZWN0aXZlOiAoKSA9PiB0cnVlLFxuICAgICAgICBvdmVyd3JpdGVQYXJhbXM6ICgpID0+ICh7XG4gICAgICAgICAgc2xpZGVzUGVyVmlldzogMSxcbiAgICAgICAgICBzbGlkZXNQZXJHcm91cDogMSxcbiAgICAgICAgICB3YXRjaFNsaWRlc1Byb2dyZXNzOiB0cnVlLFxuICAgICAgICAgIHJlc2lzdGFuY2VSYXRpbzogMCxcbiAgICAgICAgICBzcGFjZUJldHdlZW46IDAsXG4gICAgICAgICAgY2VudGVyZWRTbGlkZXM6IGZhbHNlLFxuICAgICAgICAgIHZpcnR1YWxUcmFuc2xhdGU6IHRydWVcbiAgICAgICAgfSlcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVNoYWRvdyhwYXJhbXMsICRzbGlkZUVsLCBzaWRlKSB7XG4gICAgICBjb25zdCBzaGFkb3dDbGFzcyA9IGBzd2lwZXItc2xpZGUtc2hhZG93JHtzaWRlID8gYC0ke3NpZGV9YCA6ICcnfWA7XG4gICAgICBjb25zdCAkc2hhZG93Q29udGFpbmVyID0gcGFyYW1zLnRyYW5zZm9ybUVsID8gJHNsaWRlRWwuZmluZChwYXJhbXMudHJhbnNmb3JtRWwpIDogJHNsaWRlRWw7XG4gICAgICBsZXQgJHNoYWRvd0VsID0gJHNoYWRvd0NvbnRhaW5lci5jaGlsZHJlbihgLiR7c2hhZG93Q2xhc3N9YCk7XG5cbiAgICAgIGlmICghJHNoYWRvd0VsLmxlbmd0aCkge1xuICAgICAgICAkc2hhZG93RWwgPSAkKGA8ZGl2IGNsYXNzPVwic3dpcGVyLXNsaWRlLXNoYWRvdyR7c2lkZSA/IGAtJHtzaWRlfWAgOiAnJ31cIj48L2Rpdj5gKTtcbiAgICAgICAgJHNoYWRvd0NvbnRhaW5lci5hcHBlbmQoJHNoYWRvd0VsKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuICRzaGFkb3dFbDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBFZmZlY3RGbGlwKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZXh0ZW5kUGFyYW1zLFxuICAgICAgICBvblxuICAgICAgfSA9IF9yZWY7XG4gICAgICBleHRlbmRQYXJhbXMoe1xuICAgICAgICBmbGlwRWZmZWN0OiB7XG4gICAgICAgICAgc2xpZGVTaGFkb3dzOiB0cnVlLFxuICAgICAgICAgIGxpbWl0Um90YXRpb246IHRydWUsXG4gICAgICAgICAgdHJhbnNmb3JtRWw6IG51bGxcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHNldFRyYW5zbGF0ZSA9ICgpID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHNsaWRlcyxcbiAgICAgICAgICBydGxUcmFuc2xhdGU6IHJ0bFxuICAgICAgICB9ID0gc3dpcGVyO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zLmZsaXBFZmZlY3Q7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbGlkZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICBjb25zdCAkc2xpZGVFbCA9IHNsaWRlcy5lcShpKTtcbiAgICAgICAgICBsZXQgcHJvZ3Jlc3MgPSAkc2xpZGVFbFswXS5wcm9ncmVzcztcblxuICAgICAgICAgIGlmIChzd2lwZXIucGFyYW1zLmZsaXBFZmZlY3QubGltaXRSb3RhdGlvbikge1xuICAgICAgICAgICAgcHJvZ3Jlc3MgPSBNYXRoLm1heChNYXRoLm1pbigkc2xpZGVFbFswXS5wcm9ncmVzcywgMSksIC0xKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBvZmZzZXQgPSAkc2xpZGVFbFswXS5zd2lwZXJTbGlkZU9mZnNldDtcbiAgICAgICAgICBjb25zdCByb3RhdGUgPSAtMTgwICogcHJvZ3Jlc3M7XG4gICAgICAgICAgbGV0IHJvdGF0ZVkgPSByb3RhdGU7XG4gICAgICAgICAgbGV0IHJvdGF0ZVggPSAwO1xuICAgICAgICAgIGxldCB0eCA9IHN3aXBlci5wYXJhbXMuY3NzTW9kZSA/IC1vZmZzZXQgLSBzd2lwZXIudHJhbnNsYXRlIDogLW9mZnNldDtcbiAgICAgICAgICBsZXQgdHkgPSAwO1xuXG4gICAgICAgICAgaWYgKCFzd2lwZXIuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgICAgICAgIHR5ID0gdHg7XG4gICAgICAgICAgICB0eCA9IDA7XG4gICAgICAgICAgICByb3RhdGVYID0gLXJvdGF0ZVk7XG4gICAgICAgICAgICByb3RhdGVZID0gMDtcbiAgICAgICAgICB9IGVsc2UgaWYgKHJ0bCkge1xuICAgICAgICAgICAgcm90YXRlWSA9IC1yb3RhdGVZO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICRzbGlkZUVsWzBdLnN0eWxlLnpJbmRleCA9IC1NYXRoLmFicyhNYXRoLnJvdW5kKHByb2dyZXNzKSkgKyBzbGlkZXMubGVuZ3RoO1xuXG4gICAgICAgICAgaWYgKHBhcmFtcy5zbGlkZVNoYWRvd3MpIHtcbiAgICAgICAgICAgIC8vIFNldCBzaGFkb3dzXG4gICAgICAgICAgICBsZXQgc2hhZG93QmVmb3JlID0gc3dpcGVyLmlzSG9yaXpvbnRhbCgpID8gJHNsaWRlRWwuZmluZCgnLnN3aXBlci1zbGlkZS1zaGFkb3ctbGVmdCcpIDogJHNsaWRlRWwuZmluZCgnLnN3aXBlci1zbGlkZS1zaGFkb3ctdG9wJyk7XG4gICAgICAgICAgICBsZXQgc2hhZG93QWZ0ZXIgPSBzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyAkc2xpZGVFbC5maW5kKCcuc3dpcGVyLXNsaWRlLXNoYWRvdy1yaWdodCcpIDogJHNsaWRlRWwuZmluZCgnLnN3aXBlci1zbGlkZS1zaGFkb3ctYm90dG9tJyk7XG5cbiAgICAgICAgICAgIGlmIChzaGFkb3dCZWZvcmUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIHNoYWRvd0JlZm9yZSA9IGNyZWF0ZVNoYWRvdyhwYXJhbXMsICRzbGlkZUVsLCBzd2lwZXIuaXNIb3Jpem9udGFsKCkgPyAnbGVmdCcgOiAndG9wJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzaGFkb3dBZnRlci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgc2hhZG93QWZ0ZXIgPSBjcmVhdGVTaGFkb3cocGFyYW1zLCAkc2xpZGVFbCwgc3dpcGVyLmlzSG9yaXpvbnRhbCgpID8gJ3JpZ2h0JyA6ICdib3R0b20nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHNoYWRvd0JlZm9yZS5sZW5ndGgpIHNoYWRvd0JlZm9yZVswXS5zdHlsZS5vcGFjaXR5ID0gTWF0aC5tYXgoLXByb2dyZXNzLCAwKTtcbiAgICAgICAgICAgIGlmIChzaGFkb3dBZnRlci5sZW5ndGgpIHNoYWRvd0FmdGVyWzBdLnN0eWxlLm9wYWNpdHkgPSBNYXRoLm1heChwcm9ncmVzcywgMCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgdHJhbnNmb3JtID0gYHRyYW5zbGF0ZTNkKCR7dHh9cHgsICR7dHl9cHgsIDBweCkgcm90YXRlWCgke3JvdGF0ZVh9ZGVnKSByb3RhdGVZKCR7cm90YXRlWX1kZWcpYDtcbiAgICAgICAgICBjb25zdCAkdGFyZ2V0RWwgPSBlZmZlY3RUYXJnZXQocGFyYW1zLCAkc2xpZGVFbCk7XG4gICAgICAgICAgJHRhcmdldEVsLnRyYW5zZm9ybSh0cmFuc2Zvcm0pO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBzZXRUcmFuc2l0aW9uID0gZHVyYXRpb24gPT4ge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgdHJhbnNmb3JtRWxcbiAgICAgICAgfSA9IHN3aXBlci5wYXJhbXMuZmxpcEVmZmVjdDtcbiAgICAgICAgY29uc3QgJHRyYW5zaXRpb25FbGVtZW50cyA9IHRyYW5zZm9ybUVsID8gc3dpcGVyLnNsaWRlcy5maW5kKHRyYW5zZm9ybUVsKSA6IHN3aXBlci5zbGlkZXM7XG4gICAgICAgICR0cmFuc2l0aW9uRWxlbWVudHMudHJhbnNpdGlvbihkdXJhdGlvbikuZmluZCgnLnN3aXBlci1zbGlkZS1zaGFkb3ctdG9wLCAuc3dpcGVyLXNsaWRlLXNoYWRvdy1yaWdodCwgLnN3aXBlci1zbGlkZS1zaGFkb3ctYm90dG9tLCAuc3dpcGVyLXNsaWRlLXNoYWRvdy1sZWZ0JykudHJhbnNpdGlvbihkdXJhdGlvbik7XG4gICAgICAgIGVmZmVjdFZpcnR1YWxUcmFuc2l0aW9uRW5kKHtcbiAgICAgICAgICBzd2lwZXIsXG4gICAgICAgICAgZHVyYXRpb24sXG4gICAgICAgICAgdHJhbnNmb3JtRWxcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBlZmZlY3RJbml0KHtcbiAgICAgICAgZWZmZWN0OiAnZmxpcCcsXG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgb24sXG4gICAgICAgIHNldFRyYW5zbGF0ZSxcbiAgICAgICAgc2V0VHJhbnNpdGlvbixcbiAgICAgICAgcGVyc3BlY3RpdmU6ICgpID0+IHRydWUsXG4gICAgICAgIG92ZXJ3cml0ZVBhcmFtczogKCkgPT4gKHtcbiAgICAgICAgICBzbGlkZXNQZXJWaWV3OiAxLFxuICAgICAgICAgIHNsaWRlc1Blckdyb3VwOiAxLFxuICAgICAgICAgIHdhdGNoU2xpZGVzUHJvZ3Jlc3M6IHRydWUsXG4gICAgICAgICAgc3BhY2VCZXR3ZWVuOiAwLFxuICAgICAgICAgIHZpcnR1YWxUcmFuc2xhdGU6ICFzd2lwZXIucGFyYW1zLmNzc01vZGVcbiAgICAgICAgfSlcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIEVmZmVjdENvdmVyZmxvdyhfcmVmKSB7XG4gICAgICBsZXQge1xuICAgICAgICBzd2lwZXIsXG4gICAgICAgIGV4dGVuZFBhcmFtcyxcbiAgICAgICAgb25cbiAgICAgIH0gPSBfcmVmO1xuICAgICAgZXh0ZW5kUGFyYW1zKHtcbiAgICAgICAgY292ZXJmbG93RWZmZWN0OiB7XG4gICAgICAgICAgcm90YXRlOiA1MCxcbiAgICAgICAgICBzdHJldGNoOiAwLFxuICAgICAgICAgIGRlcHRoOiAxMDAsXG4gICAgICAgICAgc2NhbGU6IDEsXG4gICAgICAgICAgbW9kaWZpZXI6IDEsXG4gICAgICAgICAgc2xpZGVTaGFkb3dzOiB0cnVlLFxuICAgICAgICAgIHRyYW5zZm9ybUVsOiBudWxsXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBzZXRUcmFuc2xhdGUgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICB3aWR0aDogc3dpcGVyV2lkdGgsXG4gICAgICAgICAgaGVpZ2h0OiBzd2lwZXJIZWlnaHQsXG4gICAgICAgICAgc2xpZGVzLFxuICAgICAgICAgIHNsaWRlc1NpemVzR3JpZFxuICAgICAgICB9ID0gc3dpcGVyO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zLmNvdmVyZmxvd0VmZmVjdDtcbiAgICAgICAgY29uc3QgaXNIb3Jpem9udGFsID0gc3dpcGVyLmlzSG9yaXpvbnRhbCgpO1xuICAgICAgICBjb25zdCB0cmFuc2Zvcm0gPSBzd2lwZXIudHJhbnNsYXRlO1xuICAgICAgICBjb25zdCBjZW50ZXIgPSBpc0hvcml6b250YWwgPyAtdHJhbnNmb3JtICsgc3dpcGVyV2lkdGggLyAyIDogLXRyYW5zZm9ybSArIHN3aXBlckhlaWdodCAvIDI7XG4gICAgICAgIGNvbnN0IHJvdGF0ZSA9IGlzSG9yaXpvbnRhbCA/IHBhcmFtcy5yb3RhdGUgOiAtcGFyYW1zLnJvdGF0ZTtcbiAgICAgICAgY29uc3QgdHJhbnNsYXRlID0gcGFyYW1zLmRlcHRoOyAvLyBFYWNoIHNsaWRlIG9mZnNldCBmcm9tIGNlbnRlclxuXG4gICAgICAgIGZvciAobGV0IGkgPSAwLCBsZW5ndGggPSBzbGlkZXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICBjb25zdCAkc2xpZGVFbCA9IHNsaWRlcy5lcShpKTtcbiAgICAgICAgICBjb25zdCBzbGlkZVNpemUgPSBzbGlkZXNTaXplc0dyaWRbaV07XG4gICAgICAgICAgY29uc3Qgc2xpZGVPZmZzZXQgPSAkc2xpZGVFbFswXS5zd2lwZXJTbGlkZU9mZnNldDtcbiAgICAgICAgICBjb25zdCBjZW50ZXJPZmZzZXQgPSAoY2VudGVyIC0gc2xpZGVPZmZzZXQgLSBzbGlkZVNpemUgLyAyKSAvIHNsaWRlU2l6ZTtcbiAgICAgICAgICBjb25zdCBvZmZzZXRNdWx0aXBsaWVyID0gdHlwZW9mIHBhcmFtcy5tb2RpZmllciA9PT0gJ2Z1bmN0aW9uJyA/IHBhcmFtcy5tb2RpZmllcihjZW50ZXJPZmZzZXQpIDogY2VudGVyT2Zmc2V0ICogcGFyYW1zLm1vZGlmaWVyO1xuICAgICAgICAgIGxldCByb3RhdGVZID0gaXNIb3Jpem9udGFsID8gcm90YXRlICogb2Zmc2V0TXVsdGlwbGllciA6IDA7XG4gICAgICAgICAgbGV0IHJvdGF0ZVggPSBpc0hvcml6b250YWwgPyAwIDogcm90YXRlICogb2Zmc2V0TXVsdGlwbGllcjsgLy8gdmFyIHJvdGF0ZVogPSAwXG5cbiAgICAgICAgICBsZXQgdHJhbnNsYXRlWiA9IC10cmFuc2xhdGUgKiBNYXRoLmFicyhvZmZzZXRNdWx0aXBsaWVyKTtcbiAgICAgICAgICBsZXQgc3RyZXRjaCA9IHBhcmFtcy5zdHJldGNoOyAvLyBBbGxvdyBwZXJjZW50YWdlIHRvIG1ha2UgYSByZWxhdGl2ZSBzdHJldGNoIGZvciByZXNwb25zaXZlIHNsaWRlcnNcblxuICAgICAgICAgIGlmICh0eXBlb2Ygc3RyZXRjaCA9PT0gJ3N0cmluZycgJiYgc3RyZXRjaC5pbmRleE9mKCclJykgIT09IC0xKSB7XG4gICAgICAgICAgICBzdHJldGNoID0gcGFyc2VGbG9hdChwYXJhbXMuc3RyZXRjaCkgLyAxMDAgKiBzbGlkZVNpemU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbGV0IHRyYW5zbGF0ZVkgPSBpc0hvcml6b250YWwgPyAwIDogc3RyZXRjaCAqIG9mZnNldE11bHRpcGxpZXI7XG4gICAgICAgICAgbGV0IHRyYW5zbGF0ZVggPSBpc0hvcml6b250YWwgPyBzdHJldGNoICogb2Zmc2V0TXVsdGlwbGllciA6IDA7XG4gICAgICAgICAgbGV0IHNjYWxlID0gMSAtICgxIC0gcGFyYW1zLnNjYWxlKSAqIE1hdGguYWJzKG9mZnNldE11bHRpcGxpZXIpOyAvLyBGaXggZm9yIHVsdHJhIHNtYWxsIHZhbHVlc1xuXG4gICAgICAgICAgaWYgKE1hdGguYWJzKHRyYW5zbGF0ZVgpIDwgMC4wMDEpIHRyYW5zbGF0ZVggPSAwO1xuICAgICAgICAgIGlmIChNYXRoLmFicyh0cmFuc2xhdGVZKSA8IDAuMDAxKSB0cmFuc2xhdGVZID0gMDtcbiAgICAgICAgICBpZiAoTWF0aC5hYnModHJhbnNsYXRlWikgPCAwLjAwMSkgdHJhbnNsYXRlWiA9IDA7XG4gICAgICAgICAgaWYgKE1hdGguYWJzKHJvdGF0ZVkpIDwgMC4wMDEpIHJvdGF0ZVkgPSAwO1xuICAgICAgICAgIGlmIChNYXRoLmFicyhyb3RhdGVYKSA8IDAuMDAxKSByb3RhdGVYID0gMDtcbiAgICAgICAgICBpZiAoTWF0aC5hYnMoc2NhbGUpIDwgMC4wMDEpIHNjYWxlID0gMDtcbiAgICAgICAgICBjb25zdCBzbGlkZVRyYW5zZm9ybSA9IGB0cmFuc2xhdGUzZCgke3RyYW5zbGF0ZVh9cHgsJHt0cmFuc2xhdGVZfXB4LCR7dHJhbnNsYXRlWn1weCkgIHJvdGF0ZVgoJHtyb3RhdGVYfWRlZykgcm90YXRlWSgke3JvdGF0ZVl9ZGVnKSBzY2FsZSgke3NjYWxlfSlgO1xuICAgICAgICAgIGNvbnN0ICR0YXJnZXRFbCA9IGVmZmVjdFRhcmdldChwYXJhbXMsICRzbGlkZUVsKTtcbiAgICAgICAgICAkdGFyZ2V0RWwudHJhbnNmb3JtKHNsaWRlVHJhbnNmb3JtKTtcbiAgICAgICAgICAkc2xpZGVFbFswXS5zdHlsZS56SW5kZXggPSAtTWF0aC5hYnMoTWF0aC5yb3VuZChvZmZzZXRNdWx0aXBsaWVyKSkgKyAxO1xuXG4gICAgICAgICAgaWYgKHBhcmFtcy5zbGlkZVNoYWRvd3MpIHtcbiAgICAgICAgICAgIC8vIFNldCBzaGFkb3dzXG4gICAgICAgICAgICBsZXQgJHNoYWRvd0JlZm9yZUVsID0gaXNIb3Jpem9udGFsID8gJHNsaWRlRWwuZmluZCgnLnN3aXBlci1zbGlkZS1zaGFkb3ctbGVmdCcpIDogJHNsaWRlRWwuZmluZCgnLnN3aXBlci1zbGlkZS1zaGFkb3ctdG9wJyk7XG4gICAgICAgICAgICBsZXQgJHNoYWRvd0FmdGVyRWwgPSBpc0hvcml6b250YWwgPyAkc2xpZGVFbC5maW5kKCcuc3dpcGVyLXNsaWRlLXNoYWRvdy1yaWdodCcpIDogJHNsaWRlRWwuZmluZCgnLnN3aXBlci1zbGlkZS1zaGFkb3ctYm90dG9tJyk7XG5cbiAgICAgICAgICAgIGlmICgkc2hhZG93QmVmb3JlRWwubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICRzaGFkb3dCZWZvcmVFbCA9IGNyZWF0ZVNoYWRvdyhwYXJhbXMsICRzbGlkZUVsLCBpc0hvcml6b250YWwgPyAnbGVmdCcgOiAndG9wJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICgkc2hhZG93QWZ0ZXJFbC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgJHNoYWRvd0FmdGVyRWwgPSBjcmVhdGVTaGFkb3cocGFyYW1zLCAkc2xpZGVFbCwgaXNIb3Jpem9udGFsID8gJ3JpZ2h0JyA6ICdib3R0b20nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCRzaGFkb3dCZWZvcmVFbC5sZW5ndGgpICRzaGFkb3dCZWZvcmVFbFswXS5zdHlsZS5vcGFjaXR5ID0gb2Zmc2V0TXVsdGlwbGllciA+IDAgPyBvZmZzZXRNdWx0aXBsaWVyIDogMDtcbiAgICAgICAgICAgIGlmICgkc2hhZG93QWZ0ZXJFbC5sZW5ndGgpICRzaGFkb3dBZnRlckVsWzBdLnN0eWxlLm9wYWNpdHkgPSAtb2Zmc2V0TXVsdGlwbGllciA+IDAgPyAtb2Zmc2V0TXVsdGlwbGllciA6IDA7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBzZXRUcmFuc2l0aW9uID0gZHVyYXRpb24gPT4ge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgdHJhbnNmb3JtRWxcbiAgICAgICAgfSA9IHN3aXBlci5wYXJhbXMuY292ZXJmbG93RWZmZWN0O1xuICAgICAgICBjb25zdCAkdHJhbnNpdGlvbkVsZW1lbnRzID0gdHJhbnNmb3JtRWwgPyBzd2lwZXIuc2xpZGVzLmZpbmQodHJhbnNmb3JtRWwpIDogc3dpcGVyLnNsaWRlcztcbiAgICAgICAgJHRyYW5zaXRpb25FbGVtZW50cy50cmFuc2l0aW9uKGR1cmF0aW9uKS5maW5kKCcuc3dpcGVyLXNsaWRlLXNoYWRvdy10b3AsIC5zd2lwZXItc2xpZGUtc2hhZG93LXJpZ2h0LCAuc3dpcGVyLXNsaWRlLXNoYWRvdy1ib3R0b20sIC5zd2lwZXItc2xpZGUtc2hhZG93LWxlZnQnKS50cmFuc2l0aW9uKGR1cmF0aW9uKTtcbiAgICAgIH07XG5cbiAgICAgIGVmZmVjdEluaXQoe1xuICAgICAgICBlZmZlY3Q6ICdjb3ZlcmZsb3cnLFxuICAgICAgICBzd2lwZXIsXG4gICAgICAgIG9uLFxuICAgICAgICBzZXRUcmFuc2xhdGUsXG4gICAgICAgIHNldFRyYW5zaXRpb24sXG4gICAgICAgIHBlcnNwZWN0aXZlOiAoKSA9PiB0cnVlLFxuICAgICAgICBvdmVyd3JpdGVQYXJhbXM6ICgpID0+ICh7XG4gICAgICAgICAgd2F0Y2hTbGlkZXNQcm9ncmVzczogdHJ1ZVxuICAgICAgICB9KVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gRWZmZWN0Q3JlYXRpdmUoX3JlZikge1xuICAgICAgbGV0IHtcbiAgICAgICAgc3dpcGVyLFxuICAgICAgICBleHRlbmRQYXJhbXMsXG4gICAgICAgIG9uXG4gICAgICB9ID0gX3JlZjtcbiAgICAgIGV4dGVuZFBhcmFtcyh7XG4gICAgICAgIGNyZWF0aXZlRWZmZWN0OiB7XG4gICAgICAgICAgdHJhbnNmb3JtRWw6IG51bGwsXG4gICAgICAgICAgbGltaXRQcm9ncmVzczogMSxcbiAgICAgICAgICBzaGFkb3dQZXJQcm9ncmVzczogZmFsc2UsXG4gICAgICAgICAgcHJvZ3Jlc3NNdWx0aXBsaWVyOiAxLFxuICAgICAgICAgIHBlcnNwZWN0aXZlOiB0cnVlLFxuICAgICAgICAgIHByZXY6IHtcbiAgICAgICAgICAgIHRyYW5zbGF0ZTogWzAsIDAsIDBdLFxuICAgICAgICAgICAgcm90YXRlOiBbMCwgMCwgMF0sXG4gICAgICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICAgICAgc2NhbGU6IDFcbiAgICAgICAgICB9LFxuICAgICAgICAgIG5leHQ6IHtcbiAgICAgICAgICAgIHRyYW5zbGF0ZTogWzAsIDAsIDBdLFxuICAgICAgICAgICAgcm90YXRlOiBbMCwgMCwgMF0sXG4gICAgICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICAgICAgc2NhbGU6IDFcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBnZXRUcmFuc2xhdGVWYWx1ZSA9IHZhbHVlID0+IHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHJldHVybiB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIGAke3ZhbHVlfXB4YDtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHNldFRyYW5zbGF0ZSA9ICgpID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHNsaWRlcyxcbiAgICAgICAgICAkd3JhcHBlckVsLFxuICAgICAgICAgIHNsaWRlc1NpemVzR3JpZFxuICAgICAgICB9ID0gc3dpcGVyO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBzd2lwZXIucGFyYW1zLmNyZWF0aXZlRWZmZWN0O1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgcHJvZ3Jlc3NNdWx0aXBsaWVyOiBtdWx0aXBsaWVyXG4gICAgICAgIH0gPSBwYXJhbXM7XG4gICAgICAgIGNvbnN0IGlzQ2VudGVyZWRTbGlkZXMgPSBzd2lwZXIucGFyYW1zLmNlbnRlcmVkU2xpZGVzO1xuXG4gICAgICAgIGlmIChpc0NlbnRlcmVkU2xpZGVzKSB7XG4gICAgICAgICAgY29uc3QgbWFyZ2luID0gc2xpZGVzU2l6ZXNHcmlkWzBdIC8gMiAtIHN3aXBlci5wYXJhbXMuc2xpZGVzT2Zmc2V0QmVmb3JlIHx8IDA7XG4gICAgICAgICAgJHdyYXBwZXJFbC50cmFuc2Zvcm0oYHRyYW5zbGF0ZVgoY2FsYyg1MCUgLSAke21hcmdpbn1weCkpYCk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNsaWRlcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgIGNvbnN0ICRzbGlkZUVsID0gc2xpZGVzLmVxKGkpO1xuICAgICAgICAgIGNvbnN0IHNsaWRlUHJvZ3Jlc3MgPSAkc2xpZGVFbFswXS5wcm9ncmVzcztcbiAgICAgICAgICBjb25zdCBwcm9ncmVzcyA9IE1hdGgubWluKE1hdGgubWF4KCRzbGlkZUVsWzBdLnByb2dyZXNzLCAtcGFyYW1zLmxpbWl0UHJvZ3Jlc3MpLCBwYXJhbXMubGltaXRQcm9ncmVzcyk7XG4gICAgICAgICAgbGV0IG9yaWdpbmFsUHJvZ3Jlc3MgPSBwcm9ncmVzcztcblxuICAgICAgICAgIGlmICghaXNDZW50ZXJlZFNsaWRlcykge1xuICAgICAgICAgICAgb3JpZ2luYWxQcm9ncmVzcyA9IE1hdGgubWluKE1hdGgubWF4KCRzbGlkZUVsWzBdLm9yaWdpbmFsUHJvZ3Jlc3MsIC1wYXJhbXMubGltaXRQcm9ncmVzcyksIHBhcmFtcy5saW1pdFByb2dyZXNzKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBvZmZzZXQgPSAkc2xpZGVFbFswXS5zd2lwZXJTbGlkZU9mZnNldDtcbiAgICAgICAgICBjb25zdCB0ID0gW3N3aXBlci5wYXJhbXMuY3NzTW9kZSA/IC1vZmZzZXQgLSBzd2lwZXIudHJhbnNsYXRlIDogLW9mZnNldCwgMCwgMF07XG4gICAgICAgICAgY29uc3QgciA9IFswLCAwLCAwXTtcbiAgICAgICAgICBsZXQgY3VzdG9tID0gZmFsc2U7XG5cbiAgICAgICAgICBpZiAoIXN3aXBlci5pc0hvcml6b250YWwoKSkge1xuICAgICAgICAgICAgdFsxXSA9IHRbMF07XG4gICAgICAgICAgICB0WzBdID0gMDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsZXQgZGF0YSA9IHtcbiAgICAgICAgICAgIHRyYW5zbGF0ZTogWzAsIDAsIDBdLFxuICAgICAgICAgICAgcm90YXRlOiBbMCwgMCwgMF0sXG4gICAgICAgICAgICBzY2FsZTogMSxcbiAgICAgICAgICAgIG9wYWNpdHk6IDFcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgaWYgKHByb2dyZXNzIDwgMCkge1xuICAgICAgICAgICAgZGF0YSA9IHBhcmFtcy5uZXh0O1xuICAgICAgICAgICAgY3VzdG9tID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHByb2dyZXNzID4gMCkge1xuICAgICAgICAgICAgZGF0YSA9IHBhcmFtcy5wcmV2O1xuICAgICAgICAgICAgY3VzdG9tID0gdHJ1ZTtcbiAgICAgICAgICB9IC8vIHNldCB0cmFuc2xhdGVcblxuXG4gICAgICAgICAgdC5mb3JFYWNoKCh2YWx1ZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIHRbaW5kZXhdID0gYGNhbGMoJHt2YWx1ZX1weCArICgke2dldFRyYW5zbGF0ZVZhbHVlKGRhdGEudHJhbnNsYXRlW2luZGV4XSl9ICogJHtNYXRoLmFicyhwcm9ncmVzcyAqIG11bHRpcGxpZXIpfSkpYDtcbiAgICAgICAgICB9KTsgLy8gc2V0IHJvdGF0ZXNcblxuICAgICAgICAgIHIuZm9yRWFjaCgodmFsdWUsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICByW2luZGV4XSA9IGRhdGEucm90YXRlW2luZGV4XSAqIE1hdGguYWJzKHByb2dyZXNzICogbXVsdGlwbGllcik7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgJHNsaWRlRWxbMF0uc3R5bGUuekluZGV4ID0gLU1hdGguYWJzKE1hdGgucm91bmQoc2xpZGVQcm9ncmVzcykpICsgc2xpZGVzLmxlbmd0aDtcbiAgICAgICAgICBjb25zdCB0cmFuc2xhdGVTdHJpbmcgPSB0LmpvaW4oJywgJyk7XG4gICAgICAgICAgY29uc3Qgcm90YXRlU3RyaW5nID0gYHJvdGF0ZVgoJHtyWzBdfWRlZykgcm90YXRlWSgke3JbMV19ZGVnKSByb3RhdGVaKCR7clsyXX1kZWcpYDtcbiAgICAgICAgICBjb25zdCBzY2FsZVN0cmluZyA9IG9yaWdpbmFsUHJvZ3Jlc3MgPCAwID8gYHNjYWxlKCR7MSArICgxIC0gZGF0YS5zY2FsZSkgKiBvcmlnaW5hbFByb2dyZXNzICogbXVsdGlwbGllcn0pYCA6IGBzY2FsZSgkezEgLSAoMSAtIGRhdGEuc2NhbGUpICogb3JpZ2luYWxQcm9ncmVzcyAqIG11bHRpcGxpZXJ9KWA7XG4gICAgICAgICAgY29uc3Qgb3BhY2l0eVN0cmluZyA9IG9yaWdpbmFsUHJvZ3Jlc3MgPCAwID8gMSArICgxIC0gZGF0YS5vcGFjaXR5KSAqIG9yaWdpbmFsUHJvZ3Jlc3MgKiBtdWx0aXBsaWVyIDogMSAtICgxIC0gZGF0YS5vcGFjaXR5KSAqIG9yaWdpbmFsUHJvZ3Jlc3MgKiBtdWx0aXBsaWVyO1xuICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybSA9IGB0cmFuc2xhdGUzZCgke3RyYW5zbGF0ZVN0cmluZ30pICR7cm90YXRlU3RyaW5nfSAke3NjYWxlU3RyaW5nfWA7IC8vIFNldCBzaGFkb3dzXG5cbiAgICAgICAgICBpZiAoY3VzdG9tICYmIGRhdGEuc2hhZG93IHx8ICFjdXN0b20pIHtcbiAgICAgICAgICAgIGxldCAkc2hhZG93RWwgPSAkc2xpZGVFbC5jaGlsZHJlbignLnN3aXBlci1zbGlkZS1zaGFkb3cnKTtcblxuICAgICAgICAgICAgaWYgKCRzaGFkb3dFbC5sZW5ndGggPT09IDAgJiYgZGF0YS5zaGFkb3cpIHtcbiAgICAgICAgICAgICAgJHNoYWRvd0VsID0gY3JlYXRlU2hhZG93KHBhcmFtcywgJHNsaWRlRWwpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoJHNoYWRvd0VsLmxlbmd0aCkge1xuICAgICAgICAgICAgICBjb25zdCBzaGFkb3dPcGFjaXR5ID0gcGFyYW1zLnNoYWRvd1BlclByb2dyZXNzID8gcHJvZ3Jlc3MgKiAoMSAvIHBhcmFtcy5saW1pdFByb2dyZXNzKSA6IHByb2dyZXNzO1xuICAgICAgICAgICAgICAkc2hhZG93RWxbMF0uc3R5bGUub3BhY2l0eSA9IE1hdGgubWluKE1hdGgubWF4KE1hdGguYWJzKHNoYWRvd09wYWNpdHkpLCAwKSwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgJHRhcmdldEVsID0gZWZmZWN0VGFyZ2V0KHBhcmFtcywgJHNsaWRlRWwpO1xuICAgICAgICAgICR0YXJnZXRFbC50cmFuc2Zvcm0odHJhbnNmb3JtKS5jc3Moe1xuICAgICAgICAgICAgb3BhY2l0eTogb3BhY2l0eVN0cmluZ1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKGRhdGEub3JpZ2luKSB7XG4gICAgICAgICAgICAkdGFyZ2V0RWwuY3NzKCd0cmFuc2Zvcm0tb3JpZ2luJywgZGF0YS5vcmlnaW4pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgY29uc3Qgc2V0VHJhbnNpdGlvbiA9IGR1cmF0aW9uID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHRyYW5zZm9ybUVsXG4gICAgICAgIH0gPSBzd2lwZXIucGFyYW1zLmNyZWF0aXZlRWZmZWN0O1xuICAgICAgICBjb25zdCAkdHJhbnNpdGlvbkVsZW1lbnRzID0gdHJhbnNmb3JtRWwgPyBzd2lwZXIuc2xpZGVzLmZpbmQodHJhbnNmb3JtRWwpIDogc3dpcGVyLnNsaWRlcztcbiAgICAgICAgJHRyYW5zaXRpb25FbGVtZW50cy50cmFuc2l0aW9uKGR1cmF0aW9uKS5maW5kKCcuc3dpcGVyLXNsaWRlLXNoYWRvdycpLnRyYW5zaXRpb24oZHVyYXRpb24pO1xuICAgICAgICBlZmZlY3RWaXJ0dWFsVHJhbnNpdGlvbkVuZCh7XG4gICAgICAgICAgc3dpcGVyLFxuICAgICAgICAgIGR1cmF0aW9uLFxuICAgICAgICAgIHRyYW5zZm9ybUVsLFxuICAgICAgICAgIGFsbFNsaWRlczogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIGVmZmVjdEluaXQoe1xuICAgICAgICBlZmZlY3Q6ICdjcmVhdGl2ZScsXG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgb24sXG4gICAgICAgIHNldFRyYW5zbGF0ZSxcbiAgICAgICAgc2V0VHJhbnNpdGlvbixcbiAgICAgICAgcGVyc3BlY3RpdmU6ICgpID0+IHN3aXBlci5wYXJhbXMuY3JlYXRpdmVFZmZlY3QucGVyc3BlY3RpdmUsXG4gICAgICAgIG92ZXJ3cml0ZVBhcmFtczogKCkgPT4gKHtcbiAgICAgICAgICB3YXRjaFNsaWRlc1Byb2dyZXNzOiB0cnVlLFxuICAgICAgICAgIHZpcnR1YWxUcmFuc2xhdGU6ICFzd2lwZXIucGFyYW1zLmNzc01vZGVcbiAgICAgICAgfSlcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIEVmZmVjdENhcmRzKF9yZWYpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIHN3aXBlcixcbiAgICAgICAgZXh0ZW5kUGFyYW1zLFxuICAgICAgICBvblxuICAgICAgfSA9IF9yZWY7XG4gICAgICBleHRlbmRQYXJhbXMoe1xuICAgICAgICBjYXJkc0VmZmVjdDoge1xuICAgICAgICAgIHNsaWRlU2hhZG93czogdHJ1ZSxcbiAgICAgICAgICB0cmFuc2Zvcm1FbDogbnVsbFxuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgc2V0VHJhbnNsYXRlID0gKCkgPT4ge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgc2xpZGVzLFxuICAgICAgICAgIGFjdGl2ZUluZGV4XG4gICAgICAgIH0gPSBzd2lwZXI7XG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHN3aXBlci5wYXJhbXMuY2FyZHNFZmZlY3Q7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBzdGFydFRyYW5zbGF0ZSxcbiAgICAgICAgICBpc1RvdWNoZWRcbiAgICAgICAgfSA9IHN3aXBlci50b3VjaEV2ZW50c0RhdGE7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRUcmFuc2xhdGUgPSBzd2lwZXIudHJhbnNsYXRlO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2xpZGVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgY29uc3QgJHNsaWRlRWwgPSBzbGlkZXMuZXEoaSk7XG4gICAgICAgICAgY29uc3Qgc2xpZGVQcm9ncmVzcyA9ICRzbGlkZUVsWzBdLnByb2dyZXNzO1xuICAgICAgICAgIGNvbnN0IHByb2dyZXNzID0gTWF0aC5taW4oTWF0aC5tYXgoc2xpZGVQcm9ncmVzcywgLTQpLCA0KTtcbiAgICAgICAgICBsZXQgb2Zmc2V0ID0gJHNsaWRlRWxbMF0uc3dpcGVyU2xpZGVPZmZzZXQ7XG5cbiAgICAgICAgICBpZiAoc3dpcGVyLnBhcmFtcy5jZW50ZXJlZFNsaWRlcyAmJiAhc3dpcGVyLnBhcmFtcy5jc3NNb2RlKSB7XG4gICAgICAgICAgICBzd2lwZXIuJHdyYXBwZXJFbC50cmFuc2Zvcm0oYHRyYW5zbGF0ZVgoJHtzd2lwZXIubWluVHJhbnNsYXRlKCl9cHgpYCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHN3aXBlci5wYXJhbXMuY2VudGVyZWRTbGlkZXMgJiYgc3dpcGVyLnBhcmFtcy5jc3NNb2RlKSB7XG4gICAgICAgICAgICBvZmZzZXQgLT0gc2xpZGVzWzBdLnN3aXBlclNsaWRlT2Zmc2V0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGxldCB0WCA9IHN3aXBlci5wYXJhbXMuY3NzTW9kZSA/IC1vZmZzZXQgLSBzd2lwZXIudHJhbnNsYXRlIDogLW9mZnNldDtcbiAgICAgICAgICBsZXQgdFkgPSAwO1xuICAgICAgICAgIGNvbnN0IHRaID0gLTEwMCAqIE1hdGguYWJzKHByb2dyZXNzKTtcbiAgICAgICAgICBsZXQgc2NhbGUgPSAxO1xuICAgICAgICAgIGxldCByb3RhdGUgPSAtMiAqIHByb2dyZXNzO1xuICAgICAgICAgIGxldCB0WEFkZCA9IDggLSBNYXRoLmFicyhwcm9ncmVzcykgKiAwLjc1O1xuICAgICAgICAgIGNvbnN0IHNsaWRlSW5kZXggPSBzd2lwZXIudmlydHVhbCAmJiBzd2lwZXIucGFyYW1zLnZpcnR1YWwuZW5hYmxlZCA/IHN3aXBlci52aXJ0dWFsLmZyb20gKyBpIDogaTtcbiAgICAgICAgICBjb25zdCBpc1N3aXBlVG9OZXh0ID0gKHNsaWRlSW5kZXggPT09IGFjdGl2ZUluZGV4IHx8IHNsaWRlSW5kZXggPT09IGFjdGl2ZUluZGV4IC0gMSkgJiYgcHJvZ3Jlc3MgPiAwICYmIHByb2dyZXNzIDwgMSAmJiAoaXNUb3VjaGVkIHx8IHN3aXBlci5wYXJhbXMuY3NzTW9kZSkgJiYgY3VycmVudFRyYW5zbGF0ZSA8IHN0YXJ0VHJhbnNsYXRlO1xuICAgICAgICAgIGNvbnN0IGlzU3dpcGVUb1ByZXYgPSAoc2xpZGVJbmRleCA9PT0gYWN0aXZlSW5kZXggfHwgc2xpZGVJbmRleCA9PT0gYWN0aXZlSW5kZXggKyAxKSAmJiBwcm9ncmVzcyA8IDAgJiYgcHJvZ3Jlc3MgPiAtMSAmJiAoaXNUb3VjaGVkIHx8IHN3aXBlci5wYXJhbXMuY3NzTW9kZSkgJiYgY3VycmVudFRyYW5zbGF0ZSA+IHN0YXJ0VHJhbnNsYXRlO1xuXG4gICAgICAgICAgaWYgKGlzU3dpcGVUb05leHQgfHwgaXNTd2lwZVRvUHJldikge1xuICAgICAgICAgICAgY29uc3Qgc3ViUHJvZ3Jlc3MgPSAoMSAtIE1hdGguYWJzKChNYXRoLmFicyhwcm9ncmVzcykgLSAwLjUpIC8gMC41KSkgKiogMC41O1xuICAgICAgICAgICAgcm90YXRlICs9IC0yOCAqIHByb2dyZXNzICogc3ViUHJvZ3Jlc3M7XG4gICAgICAgICAgICBzY2FsZSArPSAtMC41ICogc3ViUHJvZ3Jlc3M7XG4gICAgICAgICAgICB0WEFkZCArPSA5NiAqIHN1YlByb2dyZXNzO1xuICAgICAgICAgICAgdFkgPSBgJHstMjUgKiBzdWJQcm9ncmVzcyAqIE1hdGguYWJzKHByb2dyZXNzKX0lYDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocHJvZ3Jlc3MgPCAwKSB7XG4gICAgICAgICAgICAvLyBuZXh0XG4gICAgICAgICAgICB0WCA9IGBjYWxjKCR7dFh9cHggKyAoJHt0WEFkZCAqIE1hdGguYWJzKHByb2dyZXNzKX0lKSlgO1xuICAgICAgICAgIH0gZWxzZSBpZiAocHJvZ3Jlc3MgPiAwKSB7XG4gICAgICAgICAgICAvLyBwcmV2XG4gICAgICAgICAgICB0WCA9IGBjYWxjKCR7dFh9cHggKyAoLSR7dFhBZGQgKiBNYXRoLmFicyhwcm9ncmVzcyl9JSkpYDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdFggPSBgJHt0WH1weGA7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFzd2lwZXIuaXNIb3Jpem9udGFsKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IHByZXZZID0gdFk7XG4gICAgICAgICAgICB0WSA9IHRYO1xuICAgICAgICAgICAgdFggPSBwcmV2WTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBzY2FsZVN0cmluZyA9IHByb2dyZXNzIDwgMCA/IGAkezEgKyAoMSAtIHNjYWxlKSAqIHByb2dyZXNzfWAgOiBgJHsxIC0gKDEgLSBzY2FsZSkgKiBwcm9ncmVzc31gO1xuICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybSA9IGBcbiAgICAgICAgdHJhbnNsYXRlM2QoJHt0WH0sICR7dFl9LCAke3RafXB4KVxuICAgICAgICByb3RhdGVaKCR7cm90YXRlfWRlZylcbiAgICAgICAgc2NhbGUoJHtzY2FsZVN0cmluZ30pXG4gICAgICBgO1xuXG4gICAgICAgICAgaWYgKHBhcmFtcy5zbGlkZVNoYWRvd3MpIHtcbiAgICAgICAgICAgIC8vIFNldCBzaGFkb3dzXG4gICAgICAgICAgICBsZXQgJHNoYWRvd0VsID0gJHNsaWRlRWwuZmluZCgnLnN3aXBlci1zbGlkZS1zaGFkb3cnKTtcblxuICAgICAgICAgICAgaWYgKCRzaGFkb3dFbC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgJHNoYWRvd0VsID0gY3JlYXRlU2hhZG93KHBhcmFtcywgJHNsaWRlRWwpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoJHNoYWRvd0VsLmxlbmd0aCkgJHNoYWRvd0VsWzBdLnN0eWxlLm9wYWNpdHkgPSBNYXRoLm1pbihNYXRoLm1heCgoTWF0aC5hYnMocHJvZ3Jlc3MpIC0gMC41KSAvIDAuNSwgMCksIDEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICRzbGlkZUVsWzBdLnN0eWxlLnpJbmRleCA9IC1NYXRoLmFicyhNYXRoLnJvdW5kKHNsaWRlUHJvZ3Jlc3MpKSArIHNsaWRlcy5sZW5ndGg7XG4gICAgICAgICAgY29uc3QgJHRhcmdldEVsID0gZWZmZWN0VGFyZ2V0KHBhcmFtcywgJHNsaWRlRWwpO1xuICAgICAgICAgICR0YXJnZXRFbC50cmFuc2Zvcm0odHJhbnNmb3JtKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgY29uc3Qgc2V0VHJhbnNpdGlvbiA9IGR1cmF0aW9uID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHRyYW5zZm9ybUVsXG4gICAgICAgIH0gPSBzd2lwZXIucGFyYW1zLmNhcmRzRWZmZWN0O1xuICAgICAgICBjb25zdCAkdHJhbnNpdGlvbkVsZW1lbnRzID0gdHJhbnNmb3JtRWwgPyBzd2lwZXIuc2xpZGVzLmZpbmQodHJhbnNmb3JtRWwpIDogc3dpcGVyLnNsaWRlcztcbiAgICAgICAgJHRyYW5zaXRpb25FbGVtZW50cy50cmFuc2l0aW9uKGR1cmF0aW9uKS5maW5kKCcuc3dpcGVyLXNsaWRlLXNoYWRvdycpLnRyYW5zaXRpb24oZHVyYXRpb24pO1xuICAgICAgICBlZmZlY3RWaXJ0dWFsVHJhbnNpdGlvbkVuZCh7XG4gICAgICAgICAgc3dpcGVyLFxuICAgICAgICAgIGR1cmF0aW9uLFxuICAgICAgICAgIHRyYW5zZm9ybUVsXG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgZWZmZWN0SW5pdCh7XG4gICAgICAgIGVmZmVjdDogJ2NhcmRzJyxcbiAgICAgICAgc3dpcGVyLFxuICAgICAgICBvbixcbiAgICAgICAgc2V0VHJhbnNsYXRlLFxuICAgICAgICBzZXRUcmFuc2l0aW9uLFxuICAgICAgICBwZXJzcGVjdGl2ZTogKCkgPT4gdHJ1ZSxcbiAgICAgICAgb3ZlcndyaXRlUGFyYW1zOiAoKSA9PiAoe1xuICAgICAgICAgIHdhdGNoU2xpZGVzUHJvZ3Jlc3M6IHRydWUsXG4gICAgICAgICAgdmlydHVhbFRyYW5zbGF0ZTogIXN3aXBlci5wYXJhbXMuY3NzTW9kZVxuICAgICAgICB9KVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gU3dpcGVyIENsYXNzXG4gICAgY29uc3QgbW9kdWxlcyA9IFtWaXJ0dWFsLCBLZXlib2FyZCwgTW91c2V3aGVlbCwgTmF2aWdhdGlvbiwgUGFnaW5hdGlvbiwgU2Nyb2xsYmFyLCBQYXJhbGxheCwgWm9vbSwgTGF6eSwgQ29udHJvbGxlciwgQTExeSwgSGlzdG9yeSwgSGFzaE5hdmlnYXRpb24sIEF1dG9wbGF5LCBUaHVtYiwgZnJlZU1vZGUsIEdyaWQsIE1hbmlwdWxhdGlvbiwgRWZmZWN0RmFkZSwgRWZmZWN0Q3ViZSwgRWZmZWN0RmxpcCwgRWZmZWN0Q292ZXJmbG93LCBFZmZlY3RDcmVhdGl2ZSwgRWZmZWN0Q2FyZHNdO1xuICAgIFN3aXBlci51c2UobW9kdWxlcyk7XG5cbiAgICByZXR1cm4gU3dpcGVyO1xuXG59KSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1zd2lwZXItYnVuZGxlLmpzLm1hcFxuIiwiaW1wb3J0IFN3aXBlciBmcm9tICdzd2lwZXIvc3dpcGVyLWJ1bmRsZSc7XG5pZiAoZ2xvYmFsKSBnbG9iYWwuU3dpcGVyID0gU3dpcGVyXG4iXX0="}