{"version":3,"file":"base-ui-components.umd.cjs","sources":["../src/composables/useAnnouncer.js","../src/composables/useDebounce.js","../node_modules/@babel/runtime/helpers/esm/typeof.js","../node_modules/@babel/runtime/helpers/esm/toPrimitive.js","../node_modules/@babel/runtime/helpers/esm/toPropertyKey.js","../node_modules/@babel/runtime/helpers/esm/defineProperty.js","../src/composables/useElementObserver.js","../src/composables/useEventListener.js","../src/composables/useElementFadeOut.js","../src/composables/useExtractAttrs.js","../src/composables/useHasSlotContent.js","../node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js","../node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js","../node_modules/@babel/runtime/helpers/esm/iterableToArray.js","../node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js","../node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js","../node_modules/@babel/runtime/helpers/esm/toConsumableArray.js","../src/composables/useHorizontalDragScroll.js","../src/composables/useI18n.js","../node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js","../node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js","../node_modules/@babel/runtime/helpers/esm/nonIterableRest.js","../node_modules/@babel/runtime/helpers/esm/slicedToArray.js","../src/utils/utils.js","../src/composables/useId.js","../src/composables/useListNavigation.js","../node_modules/@kyvg/vue3-notification/dist/index.es.js","../src/composables/useNotifications.js","../node_modules/body-scroll-lock/lib/bodyScrollLock.esm.js","../src/composables/usePopUpLock.js","../src/composables/useTabKeyHandler.js","../src/composables/useWindowResize.js","../src/components/BaseSearch/BaseSearch.vue","../src/components/BaseIcon/BaseIcon.vue","../src/components/BaseButton/BaseButton.vue","../node_modules/@vueuse/shared/index.mjs","../node_modules/@vueuse/core/index.mjs","../src/components/BaseInput/BaseInput.vue","../src/components/BaseChipsInputField/BaseChipsInputField.vue","../src/components/BaseChip/BaseChip.vue","../src/components/BaseDropDownList/BaseDropDownList.vue","../src/components/BaseAdvancedSearch/BaseAdvancedSearchRow.vue","../src/components/BaseAdvancedSearch/BaseAdvancedSearch.vue","../src/components/BaseAutocompleteInput/BaseAutocompleteInput.vue","../src/components/BaseBox/BaseBox.vue","../src/components/BaseBoxButton/BaseBoxButton.vue","../src/components/BaseBoxTooltip/BaseBoxTooltip.vue","../src/directives/cleanDomNodes.js","../src/components/BaseLink/BaseLink.vue","../src/components/BaseBreadCrumbs/BaseBreadCrumbs.vue","../src/components/BaseImageBox/BaseImageBox.vue","../src/components/BaseCarousel/BaseCarousel.vue","../src/components/BaseCheckmark/BaseCheckmark.vue","../src/components/BaseChipsInput/BaseChipsInput.vue","../src/components/BaseChipsBelow/BaseChipsBelow.vue","../node_modules/@vueuse/components/index.mjs","../src/components/BaseDateInput/BaseDateInput.vue","../src/components/BaseDetailBox/BaseDetailBox.vue","../src/components/BaseDropBox/BaseDropBox.vue","../src/components/BaseDropButton/BaseDropButton.vue","../src/components/BaseDropDown/BaseDropDown.vue","../src/components/BaseLoader/BaseLoader.vue","../src/components/BaseEditControl/BaseEditControl.vue","../src/components/BaseEntrySelector/BaseEntrySelector.vue","../src/components/BaseExpandBox/BaseExpandBox.vue","../src/components/BaseExpandList/BaseExpandListRow.vue","../src/components/BaseExpandList/BaseExpandList.vue","../src/components/BaseExpandRow/BaseExpandRow.vue","../src/components/BaseFormFieldCreator/BaseFormFieldCreator.vue","../src/components/BaseForm/BaseForm.vue","../src/components/BaseFormGroups/BaseFormGroups.vue","../src/components/BaseHlsVideo/BaseHlsVideo.vue","../src/components/BaseImage/BaseImage.vue","../src/components/BaseImageGrid/BaseImageGrid.vue","../src/components/BaseInfoPanel/BaseInfoPanel.vue","../src/components/BaseMap/BaseMap.vue","../src/components/BaseTextList/BaseTextList.vue","../src/components/BaseMapLocations/BaseMapLocations.vue","../src/components/BaseMediaCarousel/BaseMediaCarouselItem.vue","../src/components/BaseMediaCarousel/BaseMediaCarousel.vue","../src/components/BaseMenuEntry/BaseMenuEntry.vue","../src/components/BaseMenuList/BaseMenuList.vue","../src/components/BaseMultilineTextInput/BaseMultilineTextInput.vue","../src/components/BaseNavigation/BaseNavigation.vue","../src/components/BaseOptions/BaseOptions.vue","../src/components/BasePagination/BasePagination.vue","../src/components/BasePdfViewer/BasePdfViewer.vue","../src/components/BasePopUp/BasePopUp.vue","../src/components/BaseProgressBar/BaseProgressBar.vue","../src/components/BaseRangeSlider/BaseRangeSlider.vue","../src/components/BaseResultBoxSection/BaseResultBoxSection.vue","../src/components/BaseSelectOptions/BaseSelectOptions.vue","../src/components/BaseSwitchButton/BaseSwitchButton.vue","../src/components/BaseToggle/BaseToggle.vue","../src/components/BaseTooltipBox/BaseTooltipBox.vue","../src/components/BaseUploadPopUp/BaseUploadPopUp.vue","../src/components/BaseNotification/BaseNotification.vue","../src/plugins/base-notifications.js","../node_modules/vue-draggable-plus/dist/vue-draggable-plus.js","../src/components/BaseInsertTextAsHtml/BaseInsertTextAsHtml.vue","../src/components/BaseAdvancedSearch/BaseCollapsedFilterItem.vue","../src/components/BaseAdvancedSearch/BaseCollapsedFilterRow.vue","../node_modules/swiper/shared/ssr-window.esm.mjs","../node_modules/swiper/shared/utils.mjs","../node_modules/swiper/modules/keyboard.mjs","../node_modules/swiper/shared/create-element-if-not-defined.mjs","../node_modules/swiper/modules/navigation.mjs","../node_modules/swiper/shared/classes-to-selector.mjs","../node_modules/swiper/modules/pagination.mjs","../node_modules/swiper/modules/zoom.mjs","../node_modules/swiper/modules/a11y.mjs","../node_modules/swiper/modules/autoplay.mjs","../node_modules/date-format-parse/es/util.js","../node_modules/date-format-parse/es/locale/en.js","../node_modules/date-format-parse/es/format.js","../node_modules/date-format-parse/es/parse.js","../node_modules/vue-datepicker-next/index.es.js","../node_modules/vue-datepicker-next/locale/af.es.js","../node_modules/vue-datepicker-next/locale/ar-dz.es.js","../node_modules/vue-datepicker-next/locale/ar-sa.es.js","../node_modules/vue-datepicker-next/locale/ar.es.js","../node_modules/vue-datepicker-next/locale/az.es.js","../node_modules/vue-datepicker-next/locale/be.es.js","../node_modules/vue-datepicker-next/locale/bg.es.js","../node_modules/vue-datepicker-next/locale/bm.es.js","../node_modules/vue-datepicker-next/locale/bn.es.js","../node_modules/vue-datepicker-next/locale/ca.es.js","../node_modules/vue-datepicker-next/locale/cs.es.js","../node_modules/vue-datepicker-next/locale/cy.es.js","../node_modules/vue-datepicker-next/locale/da.es.js","../node_modules/vue-datepicker-next/locale/de.es.js","../node_modules/vue-datepicker-next/locale/el.es.js","../node_modules/vue-datepicker-next/locale/en.es.js","../node_modules/vue-datepicker-next/locale/eo.es.js","../node_modules/vue-datepicker-next/locale/es.es.js","../node_modules/vue-datepicker-next/locale/et.es.js","../node_modules/vue-datepicker-next/locale/fi.es.js","../node_modules/vue-datepicker-next/locale/fr.es.js","../node_modules/vue-datepicker-next/locale/gl.es.js","../node_modules/vue-datepicker-next/locale/gu.es.js","../node_modules/vue-datepicker-next/locale/he.es.js","../node_modules/vue-datepicker-next/locale/hi.es.js","../node_modules/vue-datepicker-next/locale/hr.es.js","../node_modules/vue-datepicker-next/locale/hu.es.js","../node_modules/vue-datepicker-next/locale/id.es.js","../node_modules/vue-datepicker-next/locale/is.es.js","../node_modules/vue-datepicker-next/locale/it.es.js","../node_modules/vue-datepicker-next/locale/ja.es.js","../node_modules/vue-datepicker-next/locale/ka.es.js","../node_modules/vue-datepicker-next/locale/kk.es.js","../node_modules/vue-datepicker-next/locale/ko.es.js","../node_modules/vue-datepicker-next/locale/lt.es.js","../node_modules/vue-datepicker-next/locale/lv.es.js","../node_modules/vue-datepicker-next/locale/mk.es.js","../node_modules/vue-datepicker-next/locale/ms.es.js","../node_modules/vue-datepicker-next/locale/nb.es.js","../node_modules/vue-datepicker-next/locale/nl-be.es.js","../node_modules/vue-datepicker-next/locale/nl.es.js","../node_modules/vue-datepicker-next/locale/pl.es.js","../node_modules/vue-datepicker-next/locale/pt-br.es.js","../node_modules/vue-datepicker-next/locale/pt.es.js","../node_modules/vue-datepicker-next/locale/ro.es.js","../node_modules/vue-datepicker-next/locale/ru.es.js","../node_modules/vue-datepicker-next/locale/sl.es.js","../node_modules/vue-datepicker-next/locale/sr.es.js","../node_modules/vue-datepicker-next/locale/sv.es.js","../node_modules/vue-datepicker-next/locale/ta.es.js","../node_modules/vue-datepicker-next/locale/te.es.js","../node_modules/vue-datepicker-next/locale/th.es.js","../node_modules/vue-datepicker-next/locale/tr.es.js","../node_modules/vue-datepicker-next/locale/ug-cn.es.js","../node_modules/vue-datepicker-next/locale/uk.es.js","../node_modules/vue-datepicker-next/locale/vi.es.js","../node_modules/vue-datepicker-next/locale/zh-cn.es.js","../node_modules/vue-datepicker-next/locale/zh-tw.es.js","../node_modules/lazysizes/lazysizes.js","../node_modules/pdfjs-dist/build/pdf.worker.mjs?url"],"sourcesContent":["import { ref, watch } from 'vue';\n\n/**\n * composable to add an HTML element to a component that uses aria-live 'assertive'\n *  to announce provided text\n *\n * @param {Ref<UnwrapRef<null|HTMLElement>>} target - a reference to an element where the announcer should\n *  be appended to\n * @param {number} timeout - time (in ms) to wait until announcement text is deleted again\n */\nexport function useAnnouncer(target, timeout = 300) {\n  /**\n   * variable to save the assertive element to be able to update / delete the\n   * innerText from it\n   * @type {Ref<UnwrapRef<null|HTMLElement>>}\n   */\n  const assertiveElement = ref(null);\n  /**\n   * variable to control the text to be read\n   * @type {Ref<UnwrapRef<string>>}\n   */\n  const announcement = ref('');\n\n  // automatically delete the text again after a timeout, so the\n  // same text could be read again at a later point in time\n  function clearText() {\n    setTimeout(() => {\n      // reset HTML element inner text\n      assertiveElement.value.innerText = '';\n      // and announcement string (so changes to it can be detected)\n      announcement.value = '';\n    }, timeout);\n  }\n\n  // watch the provided announcement value for changes and update\n  // the element inner text if necessary\n  watch(announcement, (val) => {\n    // if a string was set assign it to the HTML element created earlier\n    if (val) {\n      // first check if the target element exists, so assertive element could be set\n      if (!target.value) {\n        console.warn('Announcement element could not be set because the target reference is undefined!');\n        return;\n      }\n      assertiveElement.value.innerText = val;\n      // afterward trigger the text clearance\n      clearText();\n    }\n  });\n\n  /**\n   * unfortunately it is currently not possible to use onMounted with the nuxt frontend\n   * (warning: nuxt [Vue warn]: onMounted is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup().)\n   * therefore we use a watcher on the element reference and add the assertive\n   * element once this is there\n   */\n  watch(target, () => {\n    if (target.value) {\n      // create a HTML element\n      assertiveElement.value = document.createElement('div');\n      // use the 'hide' class to hide it from the screen\n      assertiveElement.value.classList.add('hide');\n      // set the aria-live attribute to 'assertive' so it is announced as soon as it\n      // is filled with text\n      assertiveElement.value.setAttribute('aria-live', 'assertive');\n      // append the element to the component\n      target.value.appendChild(assertiveElement.value);\n    }\n  });\n\n  return {\n    // export announcement variable so it can be modified in the component\n    announcement,\n  };\n}\n","import { ref } from 'vue';\n\nexport function useDebounce() {\n  const timeout = ref(null);\n\n  function debounce(callback, time) {\n    // check if there is a timeout already set and clear it if yes\n    if (timeout.value) {\n      clearTimeout(timeout.value);\n      timeout.value = null;\n    }\n    timeout.value = setTimeout(() => {\n      callback();\n    }, time);\n  }\n\n  return {\n    debounce,\n  };\n}\n","function _typeof(o) {\n  \"@babel/helpers - typeof\";\n\n  return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) {\n    return typeof o;\n  } : function (o) {\n    return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o;\n  }, _typeof(o);\n}\nexport { _typeof as default };","import _typeof from \"./typeof.js\";\nfunction toPrimitive(t, r) {\n  if (\"object\" != _typeof(t) || !t) return t;\n  var e = t[Symbol.toPrimitive];\n  if (void 0 !== e) {\n    var i = e.call(t, r || \"default\");\n    if (\"object\" != _typeof(i)) return i;\n    throw new TypeError(\"@@toPrimitive must return a primitive value.\");\n  }\n  return (\"string\" === r ? String : Number)(t);\n}\nexport { toPrimitive as default };","import _typeof from \"./typeof.js\";\nimport toPrimitive from \"./toPrimitive.js\";\nfunction toPropertyKey(t) {\n  var i = toPrimitive(t, \"string\");\n  return \"symbol\" == _typeof(i) ? i : i + \"\";\n}\nexport { toPropertyKey as default };","import toPropertyKey from \"./toPropertyKey.js\";\nfunction _defineProperty(e, r, t) {\n  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {\n    value: t,\n    enumerable: !0,\n    configurable: !0,\n    writable: !0\n  }) : e[r] = t, e;\n}\nexport { _defineProperty as default };","import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';\n\n/**\n * @typedef {Object} IntersectionObserverOptions\n * @property {boolean} triggerCallbackWhenInViewport - fire callback when target is in viewport only\n * @property {boolean} stopObservingWhenInViewport - disconnect the observer when target is in viewport\n */\n\n/**\n * use this composable to add a resize or mutation observer to a component\n * @param {string} type - specify the type of observer\n *  @values 'resize', 'mutation', 'intersection'\n * @param {Ref<UnwrapRef<HTMLElement>>} target - the element to observe changes on\n * @param {function} callback - the function to be executed when the callback\n *  of the observer is triggered\n * @param {object|IntersectionObserverOptions} [options={}] - options specific for that type of observer\n * @returns {{observer: Ref<UnwrapRef<null|MutationObserver|ResizeObserver|IntersectionObserver>>}}\n */\nexport function useElementObserver({ type, target, callback, options = {} }) {\n  // create a reference to the provided target element, also check if value can\n  // be used directly or if it is a vue component (then $el must be used)\n  const targetElement = computed(() => target.value?.$el || target.value);\n  // create an observer variable\n  const observer = ref(null);\n\n  /**\n   * observer initialization function\n   */\n  function initObserver() {\n    // if type is resize create a new resize observer\n    if (type === 'resize') {\n      // create a resize observer with calculation functions\n      observer.value = new ResizeObserver(callback);\n      // or create a new mutation observer\n    } else if (type === 'mutation') {\n      observer.value = new MutationObserver(callback);\n      // or create a new intersection observer\n    } else if (type === 'intersection') {\n      observer.value = new IntersectionObserver((entries) => {\n        entries.forEach((entry) => {\n          // if option `triggerCallBackWhenInViewport` is set and not in viewport return immediately\n          if (options?.triggerCallbackWhenInViewport && !entry.isIntersecting) return;\n          // if the option `stopObservingWhenInViewport` is set, disconnect the observer\n          if (options?.stopObservingWhenInViewport) observer.value.disconnect();\n          // execute the callback function\n          callback();\n        });\n      });\n    } else {\n      console.warn(`type '${type}' can currently not be handled in useElementObserver.`);\n    }\n    observer.value.observe(targetElement.value, options);\n  }\n\n  onMounted(() => {\n    // check if element was already rendered\n    if (targetElement.value) {\n      // initialize the observer\n      initObserver();\n      // if not, put a watcher on it and init the observer as soon as it is rendered\n    } else {\n      watch(targetElement, (val) => {\n        if (val && !observer.value) {\n          // initialize the observer\n          initObserver();\n        }\n      });\n    }\n  });\n\n  onBeforeUnmount(() => {\n    if (observer.value) {\n      observer.value.disconnect();\n    }\n  });\n\n  return {\n    observer,\n  };\n}\n","import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';\nimport { useDebounce } from '@/composables/useDebounce.js';\n\n/**\n * put an even listener on an HTML element\n * @param {HTMLElement|Ref<HTMLElement>|string} target - the html element the listener should be attached to - could be a native\n *  element (e.g. 'body') or a reference to an element (or a vue component) - if window or document should be used just\n *  provide the appropriate string (needed since window or document are not available in setup on server side rendering)\n * @param {string} event - the name of the event that should be listened to\n * @param {function} callback - the function to be executed when the event is triggered\n * @param {boolean|Object} [options={}] - the event listener options\n * @param {boolean|number} [setDebounce=false] - specify a time (in ms) if a timeout should be set before\n *  calling the function\n * @param {boolean} [callOnMounted=false] - specify if function should be called the first time on mounted\n */\nexport function useEventListener({\n  target,\n  event,\n  callback,\n  options = {},\n  setDebounce = false,\n  callOnMounted = false,\n}) {\n  // in order to be able to use all kind of element we create a separate variable here\n  const listenerContainer = computed(() => (target.value === undefined\n    ? target : target.value?.$el || target.value));\n\n  /**\n   * define a variable that can hold the debounce function in case debounce\n   * should be applied\n   * @type {Ref<UnwrapRef<Function>>}\n   */\n  const listenerCallback = ref(callback);\n\n  // check if debounce was set\n  if (typeof setDebounce === 'number' && setDebounce >= 0) {\n    // if yes - add it to the callback function\n    const { debounce } = useDebounce();\n    listenerCallback.value = () => debounce(callback, setDebounce);\n    // if setDebounce evaluates to true but did not hit the condition above\n    // give a warning to the user\n  } else if (setDebounce) {\n    console.warn('Attention: useEventListener: `setDebounce` needs to be a number (in ms).');\n  }\n\n  // on mounted the listener is attached\n  onMounted(() => {\n    // check if a plain string was provided as target which we need to do for SSR, since we can not\n    // pass window or document element in setup\n    if (typeof listenerContainer.value === 'string') {\n      if (callOnMounted) {\n        callback();\n      }\n      if (listenerContainer.value === 'window') {\n        window.addEventListener(event, listenerCallback.value, options);\n      } else if (listenerContainer.value === 'document') {\n        document.addEventListener(event, listenerCallback.value, options);\n      } else {\n        console.warn(`${listenerContainer.value} is not a valid EventListener element`);\n      }\n      return;\n    }\n    // else treat the listenerContainer as ref to an HTML element\n    // check if the element is already present\n    if (listenerContainer.value) {\n      if (callOnMounted) {\n        callback();\n      }\n      listenerContainer.value.addEventListener(event, listenerCallback.value, options);\n      // if not - set up a watcher that will set up the listener as soon as the listenerContainer\n      // has a value\n    } else {\n      watch(listenerContainer, (container) => {\n        if (container) {\n          if (callOnMounted) {\n            callback();\n          }\n          container.addEventListener(event, listenerCallback.value, options);\n        }\n      }, { once: true });\n    }\n  });\n\n  // and on before unmount it is removed again\n  onBeforeUnmount(() => {\n    // check if a plain string was provided as target which we need to do for SSR, since we can not\n    // pass window or document element in setup\n    if (typeof listenerContainer.value === 'string') {\n      if (listenerContainer.value === 'window') {\n        window.removeEventListener(event, listenerCallback.value, options);\n      } else if (listenerContainer.value === 'document') {\n        document.removeEventListener(event, listenerCallback.value, options);\n      }\n      return;\n    }\n    if (listenerContainer.value) {\n      listenerContainer.value.removeEventListener(event, listenerCallback.value, options);\n    }\n  });\n}\n","import {\n  ref, computed,\n} from 'vue';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\nimport { useEventListener } from '@/composables/useEventListener.js';\n\n/**\n *\n * @param {Ref<HTMLElement>} target - this must be a reference(!) to an HTML element\n * @param {Object} options - additional options\n * @property {string} [options.direction='vertical'] - should calculation be horizontal or vertical\n * @property {string} [options.className='fade-out'] - specify the name of the class that should be\n *  appended / removed on fade out (e.g. className 'fade-out' with direction 'horizontal' will\n *  add the classes 'fade-out-left' and 'fade-out-right' respectively (styling for these classes\n *  is already provided in lib.scss)\n *\n * @returns {{boxFadeOut: Ref<{ ['top'|'left']: boolean, ['bottom'|'right']: boolean }>, elementIsScrollable: ComputedRef<boolean>, calcFadeOut: function }}\n */\nexport function useElementFadeOut(target, {\n  // default options when single properties were not provided\n  direction = 'vertical',\n  className = 'fade-out',\n} = {\n  // default object when options were not provided\n  direction: 'vertical',\n  className: 'fade-out',\n}) {\n  /**\n   * get either the element itself or if it is a Vue component the child\n   * (TODO: this probably will face problems if there is more than one root component?)\n   * @type {ComputedRef<HTMLElement>}\n   */\n  const scrollContainer = computed(() => target.value?.$el || target.value);\n\n  /**\n   * store the direction of the fade out (vertical or horizontal)\n   * @type {boolean}\n   */\n  const directionIsVertical = direction === 'vertical';\n\n  /**\n   * and get how the properties should be named\n   * vertical: 'top' and 'bottom'\n   * horizontal: 'left' and 'right'\n   * @type {string}\n   */\n  const preElementName = directionIsVertical ? 'top' : 'left';\n  const postElementName = directionIsVertical ? 'bottom' : 'right';\n\n  /**\n   * variable storing if fadeout top/left bottom/right should be shown\n   * @type {Ref<{ ['top'|'left']: boolean, ['bottom'|'right']: boolean }>}\n   */\n  const boxFadeOut = ref({\n    [preElementName]: false,\n    [postElementName]: false,\n  });\n\n  // use composable here not inside mounted since it has an onMounted itself!\n  useEventListener({\n    target,\n    event: 'scroll',\n    callback: calcFadeOut,\n  });\n  useElementObserver({\n    type: 'resize',\n    target,\n    callback: calcFadeOut,\n  });\n\n  /**\n   * function calculating fade out left and right / top and bottom respectively which\n   *  is returned with variable `boxFadeOut`\n   *  triggered automatically on resize but also exported so fade out can also be\n   *  recalculated manually if necessary\n   */\n  function calcFadeOut() {\n    if (scrollContainer.value) {\n      // get current element scroll position\n      const scrollPosition = direction === 'vertical' ? Math.ceil(scrollContainer.value.scrollTop)\n        : Math.ceil(scrollContainer.value.scrollLeft);\n      // get element max scroll position\n      const scrollMax = direction === 'vertical' ? scrollContainer.value.scrollHeight - scrollContainer.value.clientHeight\n        : scrollContainer.value.scrollWidth - scrollContainer.value.clientWidth;\n      // set filter fade variables\n      boxFadeOut.value = {\n        // show fade out left as soon as scroll position is different from 0\n        // chose > 0 since also negative numbers possible on iOS Safari (at least in Browserstack)\n        [preElementName]: scrollPosition > 0,\n        // show fade out right as soon as scroll position is different from maximum position\n        // but only if element exceeds available space\n        [postElementName]: scrollMax !== 0 && scrollPosition < scrollMax,\n      };\n      // add the necessary classes for the fade out (per default: `fade-out-left'\n      // or 'fade-out-top' and 'fade-out-right' / 'fade-out-botom') if className\n      // parameter is set\n      if (className) {\n        if (boxFadeOut.value[preElementName]) {\n          scrollContainer.value.classList.add(`${className}-${preElementName}`);\n        } else {\n          scrollContainer.value.classList.remove(`${className}-${preElementName}`);\n        }\n        if (boxFadeOut.value[postElementName]) {\n          scrollContainer.value.classList.add(`${className}-${postElementName}`);\n        } else {\n          scrollContainer.value.classList.remove(`${className}-${postElementName}`);\n        }\n      }\n    }\n  }\n\n  /**\n   * determine from fade out calculations if element is scrollable\n   * @type {ComputedRef<boolean>}\n   */\n  const elementIsScrollable = computed(() => !!boxFadeOut.value[preElementName]\n    || !!boxFadeOut.value[postElementName]);\n\n  return { boxFadeOut, elementIsScrollable, calcFadeOut };\n}\n","import { useAttrs, computed } from 'vue';\n\nexport function useExtractAttrs({ filterAttrs } = {\n  filterAttrs: [\n    'class',\n    'style',\n    'data-base-id',\n  ]\n}) {\n\n  // get the $attrs - this is all attributes that are not specified in props\n  const attrs = useAttrs();\n\n  /**\n   * get the attributes that should remain at component root level\n   * @type {ComputedRef<{}>}\n   */\n  const rootAttrs = computed(() => {\n    const newAttrs = {};\n    filterAttrs.forEach((attr) => {\n      if (attrs[attr]) {\n        newAttrs[attr] = attrs[attr];\n      }\n    });\n    return newAttrs;\n  });\n  /**\n   * get all other attributes, to be forwarded to the child component\n   * @type {ComputedRef<{}>}\n   */\n  const forwardAttrs = computed(() => {\n    const newAttrs = { ...attrs };\n    filterAttrs.forEach((attr) => {\n      if (attrs[attr]) {\n        delete newAttrs[attr];\n      }\n    });\n    return newAttrs;\n  })\n\n  return {\n    rootAttrs,\n    forwardAttrs,\n  }\n}\n","import { computed, Comment, Fragment, Text } from 'vue'\n\n/**\n * check if a slot truly has content - either text or native html elements\n *\n * @param {Function|Object} slot - the slot to check\n * @returns {{slotHasContent: ComputedRef<boolean>}}\n */\nexport function useHasSlotContent(slot) {\n\n  /**\n   * variable to provide to user\n   * @type {ComputedRef<boolean>}\n   */\n  const slotHasContent = computed(() => {\n    if (!slot) return false\n    // check if slot was provided as function - this is the case\n    // if slotProps object was not provided (aka slots[slotname])\n    if (typeof slot === 'function') {\n      return vNodeHasContent(slot({}));\n    }\n    // if slot props object had to be provided (aka aka slots[slotname]({})) the\n    // array is passed directly (should only be the case if it is Vue2)\n    return vNodeHasContent(slot);\n  });\n\n  /**\n   * recursive function checking every node for content\n   * @param vnodes\n   * @returns {boolean}\n   */\n  function vNodeHasContent(vnodes) {\n    // check every vnode found in the slot\n    return vnodes.some(node => {\n      // if it is a comment this does not count as content\n      if (node.type === Comment) return false;\n      // if type is any native html element (e.g. 'div' or 'button') then node.type is 'string'\n      // and we assume this as content (in this case we dont care any further if the elements\n      // added by the user have any content - this should then be handled in front end\n      if (typeof node.type !== 'symbol') return true;\n      // if type is just text and its not empty spaces this counts as content\n      if (node.type === Text && node.children.trim()) return true;\n      // if element is a container containing further elements we need to loop further\n      return node.type === Fragment\n        && vNodeHasContent(node.children);\n    })\n  }\n\n  return {\n    slotHasContent,\n  }\n}\n","function _arrayLikeToArray(r, a) {\n  (null == a || a > r.length) && (a = r.length);\n  for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];\n  return n;\n}\nexport { _arrayLikeToArray as default };","import arrayLikeToArray from \"./arrayLikeToArray.js\";\nfunction _arrayWithoutHoles(r) {\n  if (Array.isArray(r)) return arrayLikeToArray(r);\n}\nexport { _arrayWithoutHoles as default };","function _iterableToArray(r) {\n  if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r);\n}\nexport { _iterableToArray as default };","import arrayLikeToArray from \"./arrayLikeToArray.js\";\nfunction _unsupportedIterableToArray(r, a) {\n  if (r) {\n    if (\"string\" == typeof r) return arrayLikeToArray(r, a);\n    var t = {}.toString.call(r).slice(8, -1);\n    return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? arrayLikeToArray(r, a) : void 0;\n  }\n}\nexport { _unsupportedIterableToArray as default };","function _nonIterableSpread() {\n  throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\nexport { _nonIterableSpread as default };","import arrayWithoutHoles from \"./arrayWithoutHoles.js\";\nimport iterableToArray from \"./iterableToArray.js\";\nimport unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nimport nonIterableSpread from \"./nonIterableSpread.js\";\nfunction _toConsumableArray(r) {\n  return arrayWithoutHoles(r) || iterableToArray(r) || unsupportedIterableToArray(r) || nonIterableSpread();\n}\nexport { _toConsumableArray as default };","import { useElementFadeOut } from '@/composables/useElementFadeOut.js';\nimport { ref, watch } from 'vue';\nimport { useEventListener } from '@/composables/useEventListener.js';\n\n/**\n *\n * @param {Ref<HTMLElement>} target - the scroll target\n * @param {string[]} [scrollingClassNames=['scrolling']] - classes that should be added on scrollstart\n *  (the default class 'scrolling' is provided in variables.scss)\n * @param {string[]} scrollableClassNames - classes to be added if element is scrollable\n * @returns {{boxFadeOut: Ref<{}>, calcFadeOut: Function, elementIsScrollable: ComputedRef<boolean>, isScrolling: Ref<UnwrapRef<boolean>, UnwrapRef<boolean>|boolean>, pos: Ref<UnwrapRef<Object>>}}\n */\nexport function useHorizontalDragScroll(\n  target,\n  {\n    // options set when only single properties were not set\n    scrollingClassNames = ['scrolling'],\n    scrollableClassNames = [],\n  } = {\n    // default options if complete object is missing\n    scrollingClassNames: ['scrolling'],\n    scrollableClassNames: [],\n  },\n) {\n  /**\n   * @type {Object} boxFadeOut - variable to steer fade outs\n   * also if element is scrollable is determined here\n   * @property {boolean} boxFadeOut.left - left fade out\n   * @property {boolean} boxFadeOut.right - right fade out\n   * @type {function} calcFadeOut - function to recalculate fade out\n   * @type {boolean} filterListScrollable - just check if fade out is shown since calculations\n   *  are done for fade out anyway\n   */\n  const { boxFadeOut, calcFadeOut, elementIsScrollable } = useElementFadeOut(target, {\n    direction: 'horizontal',\n  });\n\n  /**\n   * set cursor styling according to current scroll state\n   * use variable instead of setting css class directly so child component\n   *  BaseCollapsedFilter item can also be steered easily\n   *  @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n   */\n  const isScrolling = ref(false);\n  /**\n   * store the element scroll and pointer position, needed for drag scrolling\n   * @type {Ref<UnwrapRef<Object>>}\n   * @property {number} pos.top - element scrollTop value\n   * @property {number} pos.left - element scrollLeft value\n   * @property {number} pos.x - cursor x position\n   * @property {number} pos.y - cursor y position\n   */\n  const pos = ref({ top: 0, left: 0, x: 0, y: 0 });\n\n  /**\n   * need to handle click event caused by pointer down after drag\n   * that has unwanted side effects on Safari (MacOS) and also setPointerCapture can\n   * only be added on pointermove to not prevent other click events within the component\n   * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n   */\n  const clickModificationsSet = ref(false);\n\n  // if classes are set, apply the necessary classes as soon as `isScrolling` is set true\n  if (scrollingClassNames.length) {\n    watch(isScrolling, (state) => {\n      if (state) {\n        target.value.classList.add(...scrollingClassNames);\n      } else {\n        target.value.classList.remove(...scrollingClassNames);\n      }\n    });\n  }\n\n  // if classes are set, apply the necessary classes as soon as element is scrollable\n  if (scrollableClassNames.length) {\n    watch(elementIsScrollable, (state) => {\n      if (state) {\n        target.value.classList.add(...scrollableClassNames);\n      } else {\n        target.value.classList.remove(...scrollableClassNames);\n      }\n    });\n  }\n\n  /**\n   * function triggered by pointer down on filter list, triggering scroll functionality\n   * @param {PointerEvent} event - the pointer down event\n   */\n  function pointerDownHandler(event) {\n    // mobile is working natively so we dont need to handle pointer events\n    if (event.pointerType === 'touch') return;\n    // add event listeners for pointermove and pointerup to be able to trigger scroll\n    target.value.addEventListener('pointermove', pointerMoveHandler);\n    target.value.addEventListener('pointerup', pointerUpHandler);\n    // check if filterList is actually scrollable\n    if (elementIsScrollable.value) {\n      // save the current element scroll state and pointer position\n      pos.value = {\n        // The current scroll\n        left: target.value.scrollLeft,\n        top: target.value.scrollTop,\n        // Get the current pointer position\n        x: event.clientX ?? (event.touches ? event.touches[0]?.clientX : 0),\n        y: event.clientY ?? (event.touches ? event.touches[0]?.clientY : 0),\n      };\n      // Change the cursor and prevent user from selecting the text (css classes\n      // are set as soon as isScrolling is true)\n      isScrolling.value = true;\n    }\n  }\n\n  /**\n   * function triggered by document pointer move after event listeners were added\n   * in pointer down filter list element event\n   * @param {PointerEvent} event\n   */\n  function pointerMoveHandler(event) {\n    event.preventDefault();\n    // check for this flag variable so that overlay is on the first move event\n    if (!clickModificationsSet.value) {\n      // setPointerCapture solves the problem of consistent cursor style!\n      // class applied to target element takes priority everywhere)\n      // TODO: this is not working with Safari but no solution found so far\n      // (except applying class as scrolling * { but did not do that because\n      // of performance implications)\n      // this is added here (and not in pointerdown) because otherwise click\n      // event on elements (e.g. remove chips) also prevented\n      target.value.setPointerCapture(event.pointerId);\n      // there is a click event caused by the drag that is executed after pointerup\n      // this does not have any consequences on Chrome but on Safari and Firefox elements\n      // are triggered (button click, drop down open etc) so we create an overlay to\n      // prevent the click event\n      // this is added here and not in pointerdown because pointerdown is triggered\n      // with every click even without drag and clicking would be permanently disabled\n      const overlay = document.createElement('div');\n      overlay.id = 'overlay';\n      overlay.style.position = 'fixed';\n      overlay.style.top = '0';\n      overlay.style.left = '0';\n      overlay.style.height = '100%';\n      overlay.style.width = '100%';\n      // set transparent\n      overlay.style.backgroundColor = 'rgba(0, 0, 0, 0)';\n      // select z-index larger than largest value in variables.scss\n      overlay.style.zIndex = '99999';\n      document.body.appendChild(overlay);\n      clickModificationsSet.value = true;\n    }\n    // get event position - touch event does not have clientX/clientY - fallback\n    // to touches position\n    const eventXPosition = event.clientX ?? (event.touches ? event.touches[0]?.clientX : 0);\n    // How far the pointer has been moved\n    const dx = eventXPosition - pos.value.x;\n    // Scroll the element horizontally\n    // eslint-disable-next-line no-param-reassign\n    target.value.scrollLeft = pos.value.left - dx;\n  }\n  /**\n   * function triggered by document pointer up after event listeners were added\n   * in pointer down filter list element event\n   * @param {PointerEvent} event - the native pointerup event\n   */\n  function pointerUpHandler(event) {\n    // remove all the event listeners again\n    target.value.removeEventListener('pointermove', pointerMoveHandler);\n    target.value.removeEventListener('pointerup', pointerUpHandler);\n    // and release the pointer again\n    target.value.releasePointerCapture(event.pointerId);\n\n    // also remove the overlay again that was put in place to prevent the\n    // pointerup followed click event\n    const overlay = document.getElementById('overlay');\n    if (overlay) {\n      document.body.removeChild(overlay);\n    }\n\n    // change the styling of the element back to normal\n    isScrolling.value = false;\n    // and remove the flag that was indicating that click prevent / pointer capture\n    // where done\n    clickModificationsSet.value = false;\n  }\n\n  // set event listeners on the scroll container\n  useEventListener({\n    target: target,\n    event: 'pointerdown',\n    callback: pointerDownHandler,\n  });\n\n  return {\n    boxFadeOut,\n    calcFadeOut,\n    elementIsScrollable,\n    isScrolling,\n    pos,\n  }\n}\n","import { computed, getCurrentInstance, ref } from 'vue';\n\n/**\n * component internal i18n functionality, will check if plugin exists\n *  and utilize its functions if present\n * @param {Ref<String>} [language] - provide the currently set locale here\n * @returns {{setLangLabels: (function(string, string[]): {}), getLangLabel: ((function((string|Object), boolean=): (Object|string))|*), getI18nTerm: ((function(string, number=, Object=): string)|*)}}\n */\nexport function useI18n(language) {\n  // in order to check for i18n we need to access the app instance app context\n  const { app } = getCurrentInstance().appContext;\n  const i18n = ref(null);\n  const t = ref(null);\n  const te = ref(null);\n  const langInt = ref(language);\n  /**\n   * now we can use it to determine if i18n functionality is available\n   * @type {ComputedRef<any|boolean>}\n   */\n  const hasI18n = computed(() => {\n    const i18nEnabled = Boolean(app?.config?.globalProperties?.$i18n);\n    // if the __VUE_I18N__ variable is set - return the global $i18n variable\n    if (i18nEnabled) {\n      // if i18n is present in the app set all the necessary\n      // functionalities (the i18n instance and the translation\n      // methods that are stored separately in globalProperties\n      i18n.value = app.config.globalProperties.$i18n;\n      t.value = app.config.globalProperties.$t;\n      te.value = app.config.globalProperties.$te;\n    }\n    return i18nEnabled;\n  });\n\n  /**\n   * get the i18n term from json files present in your project - this works exactly like\n   * vue-i18n except that the count variable can not be skipped if you want to use\n   * named formatting\n   *\n   * @param {string} key - your locale file key\n   * @param {number} [count=-1] - your count number for pluralization\n   * @param {object} [variables={}] - your object for named formatting - object property needs\n   *  to be named like the localization file variable\n   *  (https://kazupon.github.io/vue-i18n/guide/formatting.html)\n   * @returns {string}\n   */\n  function getI18nTerm(key, count = -1, variables = {}) {\n    if (!key) return '';\n    if (hasI18n.value && te.value(key)) {\n      if (count >= 0) {\n        return t.value(key, variables, count);\n      }\n      return t.value(key, variables);\n    }\n    const termPath = key.split('.');\n    return termPath.pop() || key;\n  }\n\n  /**\n   * function to provide an object with translations for all available languages\n   * @param {string} key - the locale file key\n   * @param {string[]} locales - an array of available locales\n   * @returns {Object}\n   */\n  function setLangLabels(key, locales) {\n    return locales\n      .reduce((prev, curr) => {\n        return {\n          ...prev,\n          [curr]: hasI18n.value\n            ? t.value(key, curr) : key.split('.').pop()\n        };\n      }, {});\n  }\n\n  /**\n   * function to\n   * a) check if provided value is a language object and if yes\n   * b) get the correct label from an object with language (ISO 639-1) as property\n   *    (e.g. { de: 'yyy', en: 'xxx' })\n   * @param {string|Object} value - the string or object to be processed\n   * @param {boolean} [useAny=false] - specify if a label in a different language should be used\n   *  if the currently set language has no result\n   * @returns {Object|string}\n   */\n  function getLangLabel(value, useAny = false) {\n    const langToUse = hasI18n.value\n      ? langInt.value || i18n.value.locale : langInt.value;\n    if (typeof value === 'string') return value;\n    if (value && langToUse && value[langToUse]) {\n      return value[langToUse];\n    }\n    if (value && langToUse && useAny) {\n      const availableLang = Object.keys(value).find(key => !!value[key]);\n      // return the first one that has content\n      return value[availableLang] || value[langToUse] || '';\n    }\n    return value;\n  }\n\n  return {\n    hasI18n,\n    getI18nTerm,\n    setLangLabels,\n    getLangLabel,\n  };\n}\n","function _arrayWithHoles(r) {\n  if (Array.isArray(r)) return r;\n}\nexport { _arrayWithHoles as default };","function _iterableToArrayLimit(r, l) {\n  var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"];\n  if (null != t) {\n    var e,\n      n,\n      i,\n      u,\n      a = [],\n      f = !0,\n      o = !1;\n    try {\n      if (i = (t = t.call(r)).next, 0 === l) {\n        if (Object(t) !== t) return;\n        f = !1;\n      } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);\n    } catch (r) {\n      o = !0, n = r;\n    } finally {\n      try {\n        if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return;\n      } finally {\n        if (o) throw n;\n      }\n    }\n    return a;\n  }\n}\nexport { _iterableToArrayLimit as default };","function _nonIterableRest() {\n  throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\nexport { _nonIterableRest as default };","import arrayWithHoles from \"./arrayWithHoles.js\";\nimport iterableToArrayLimit from \"./iterableToArrayLimit.js\";\nimport unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nimport nonIterableRest from \"./nonIterableRest.js\";\nfunction _slicedToArray(r, e) {\n  return arrayWithHoles(r) || iterableToArrayLimit(r, e) || unsupportedIterableToArray(r, e) || nonIterableRest();\n}\nexport { _slicedToArray as default };","export const capitalizeString = (string) => {\n  const newString2 = string.split('/')\n    .map(partialString => partialString.slice(0, 1)\n      .toUpperCase() + partialString.slice(1)).join('/');\n  return newString2.split(' ')\n    .map(partialString => partialString.slice(0, 1)\n      .toUpperCase() + partialString.slice(1)).join(' ');\n};\n\nexport const createId = () => Math.random().toString(36).slice(2, 9);\n\n/**\n * function to extract the value from a nested object property\n * e.g. to get 'prop3' value from { prop1: { prop2: { prop3: [value] }}} provide\n * the object and string `prop1.prop2.prop3`\n *\n * @param {string} string - the nested object property path in dot notation\n * @param {Object} object - the object from which the property value should be extracted\n * @returns {*} - the value contained in the nested object\n */\nexport const extractNestedPropertyValue = (string, object) => string\n  .split('.').reduce((a, b) => {\n    if (a) {\n      return a[b];\n    }\n    // if the previous `a[b]` did not exist `a` is now 'undefined' - return this\n    // directly instead of `a` to make code easier to read\n    return undefined;\n  }, object);\n\n/**\n * function taking a string and returning any name format in an array\n * with primary compare value (=last name) first and\n * secondary compare value (=first name) second\n *\n * @param compareString {string}\n * @returns {[string, string]}\n */\nexport const getNameSortValue = (compareString) => {\n  const compareStringSansNumbers = compareString.replace(/,? [0-9-]+/g, '');\n  if (compareStringSansNumbers.includes(',')) {\n    const compareArray = compareStringSansNumbers.split(', ');\n    return [compareArray[0], compareArray.splice(1).join()];\n  }\n  const compArray = compareStringSansNumbers.split(' ');\n  return [compArray.pop(), compareStringSansNumbers];\n};\n\n/**\n * function for sorting also allowing special sorting of objects for specified\n * attribute\n *\n * @param list {Array}: the list to sort\n * @param objectProp {String}: the property to sort an object by\n * @param sortByName {Boolean}: does it require special name sorting\n * @param valueFunction {Function}: possibility to apply a special function to\n * the value before any further handling (e.g. used for getting language specific\n * label\n * @returns {[*]}\n */\nexport const sort = (\n  list,\n  objectProp = '',\n  sortByName = false,\n  valueFunction = null,\n) => list.sort((a, b) => {\n  // assign respective list values to variables\n  let compareValueA = a;\n  let compareValueB = b;\n  // if a property name was passed use its value for comparison\n  if (objectProp) {\n    compareValueA = compareValueA[objectProp];\n    compareValueB = compareValueB[objectProp];\n  }\n  // if a special function was provided apply it to the value\n  if (valueFunction) {\n    compareValueA = valueFunction(compareValueA);\n    compareValueB = valueFunction(compareValueB);\n  }\n  // if sortByName was specified, get the respective compare values\n  if (sortByName) {\n    let secondaryCompareValueA = '';\n    let secondaryCompareValueB = '';\n    [compareValueA, secondaryCompareValueA] = getNameSortValue(compareValueA);\n    [compareValueB, secondaryCompareValueB] = getNameSortValue(compareValueB);\n\n    // if primary compare values are equal - use secondary compare value\n    if (compareValueA.toLowerCase() === compareValueB.toLowerCase()) {\n      compareValueA = secondaryCompareValueA;\n      compareValueB = secondaryCompareValueB;\n    }\n  }\n  // now do the actual value comparison\n  if (compareValueA.toLowerCase() > compareValueB.toLowerCase()) {\n    return 1;\n  }\n  return -1;\n});\n\nexport const hasData = (fieldValues) => {\n  let hasContent = false;\n  if (fieldValues && typeof fieldValues === 'object') {\n    if (fieldValues.length >= 0) {\n      fieldValues.forEach((values) => {\n        hasContent = hasData(values) || hasContent;\n      });\n    } else {\n      const objectKeys = Object.keys(fieldValues);\n      objectKeys\n        .forEach((key) => {\n          hasContent = hasData(fieldValues[key]) || hasContent;\n        });\n    }\n  } else {\n    hasContent = fieldValues === 0 || !!fieldValues || hasContent;\n  }\n  return hasContent;\n};\n\nexport const debounce = (delay, f) => {\n  let timer = 0;\n  return (...args) => {\n    clearTimeout(timer);\n    timer = setTimeout(() => f.apply(this, args), delay);\n  };\n};\n\n/**\n * highlight characters in a word matching a given string with chosen html tags\n * @param {string} word - the word that should be highlighted\n * @param {string} queryString - the query string that should be highlighted in `word`\n * @param {string[]} highlightTags - the names of one or more html tags to apply\n *  (only names without '<' and '>'! e.g. ['u', 'b'])\n * @returns {string} - the string to fill into v-html\n */\nexport const highlightText = ({ word, queryString, highlightTags = ['u', 'strong'] }) => {\n  const check = new RegExp(queryString, 'ig');\n  const highlightTagsStart = `<${highlightTags.join('><')}>`;\n  const highlightTagsEnd = `</${highlightTags.join('></')}>`;\n  return word.toString()\n    .replace(check, matchedText => (`${highlightTagsStart}${matchedText}${highlightTagsEnd}`));\n};\n","import { getCurrentInstance } from 'vue';\nimport { createId } from '@/utils/utils.js';\n\nconst ATTR_KEY = 'data-base-id';\n\nexport function useId() {\n  // get the current component instance\n  const instance = getCurrentInstance();\n  // if root is a comment node and sibling is an element - take that data attribute - otherwise we\n  // can use the root element directly\n  const el = instance.vnode.el?.nodeType === 8 && instance.vnode.el?.nextElementSibling?.getAttribute\n    ? instance.vnode.el?.nextElementSibling\n    : instance.vnode.el;\n  // check if an id was already set on the element\n  let id = el?.getAttribute?.(ATTR_KEY);\n\n  // if yes return that\n  if (id) {\n    return id;\n  }\n  // if not - create a new id\n  id = createId();\n  // and set it on the element attributes\n  instance.attrs[ATTR_KEY] = id;\n  // and return the newly created id\n  return id;\n}\n","export function useListNavigation() {\n  /**\n   * function to check if arrow key navigation was within the array\n   * @param {Array} list - the list that is navigated with arrow keys\n   * @param {boolean} isArrowDown - was arrow up or down used\n   * @param {number} newIndex - the new index that would be navigated to\n   * @returns {boolean}\n   */\n  function isWithinArrayLimit(list, isArrowDown, newIndex) {\n    // set variable for limit to check against\n    // 0 for arrow up and array length for arrow down\n    const listLimit = isArrowDown ? list.length : 0;\n    // define operator functions to be able to use condition generically\n    const operators = {\n      '>=': (a, b) => a >= b,\n      '<': (a, b) => a < b,\n    };\n    // set the actual operator\n    const operator = isArrowDown ? '<' : '>=';\n    // return Boolean if it is within limits of array or not\n    return operators[operator](newIndex, listLimit);\n  }\n  /**\n   * function to navigate a drop-down list or similar via key up/down\n   * @param {Array} list - the list to navigate in\n   * @param {boolean} isArrowDown - was key navigation up or down\n   * @param {number} currentIndex - the index of the current active option in the array\n   * @param {boolean} [loop=false] - should index return to last/first\n   *  item if first/last item was reached\n   * @param {boolean} [allowNegativeIndex=false] - allow index to become -1 (no active option -->\n   *  function will return null)\n   * @returns {?Object|?string} - the new active element\n   */\n  function\n  navigate(\n    list,\n    isArrowDown,\n    currentIndex,\n    loop = false,\n    allowNegativeIndex = false,\n  ) {\n    // depending on if arrow was up or down set +/- one to add or subtract\n    // generically\n    const numberToAdd = isArrowDown ? 1 : -1;\n    if (isWithinArrayLimit(\n      list,\n      isArrowDown,\n      currentIndex + numberToAdd,\n    )) {\n      // set new active entry\n      return list[currentIndex + numberToAdd];\n    }\n    if (currentIndex >= 0 && allowNegativeIndex) {\n      return null;\n    }\n    if (loop) {\n      return list[isArrowDown ? 0 : list.length - 1];\n    }\n    return list[currentIndex];\n  }\n  return {\n    navigate,\n    isWithinArrayLimit,\n  };\n}\n","(function(){\"use strict\";var o;try{if(typeof document<\"u\"){var e=document.createElement(\"style\");e.nonce=(o=document.head.querySelector(\"meta[property=csp-nonce]\"))==null?void 0:o.content,e.appendChild(document.createTextNode(\".vue-notification-group{display:block;position:fixed;z-index:5000}.vue-notification-wrapper{display:block;overflow:hidden;width:100%;margin:0;padding:0}.notification-title{font-weight:600}.vue-notification-template{display:block;box-sizing:border-box;background:#fff;text-align:left}.vue-notification{display:block;box-sizing:border-box;text-align:left;font-size:12px;padding:10px;margin:0 5px 5px;color:#fff;background:#44a4fc;border-left:5px solid #187FE7}.vue-notification.warn{background:#ffb648;border-left-color:#f48a06}.vue-notification.error{background:#e54d42;border-left-color:#b82e24}.vue-notification.success{background:#68cd86;border-left-color:#42a85f}.vn-fade-enter-active,.vn-fade-leave-active,.vn-fade-move{transition:all .5s}.vn-fade-enter-from,.vn-fade-leave-to{opacity:0}\")),document.head.appendChild(e)}}catch(n){console.error(\"vite-plugin-css-injected-by-js\",n)}})();\nimport { defineComponent as Q, ref as X, computed as h, onMounted as Z, onUnmounted as tt, createVNode as l, TransitionGroup as et, mergeProps as nt, Fragment as H, isVNode as ot } from \"vue\";\nconst B = /* @__PURE__ */ new Map();\nfunction it(t) {\n  return { all: t = t || /* @__PURE__ */ new Map(), on: function(o, i) {\n    var a = t.get(o);\n    a ? a.push(i) : t.set(o, [i]);\n  }, off: function(o, i) {\n    var a = t.get(o);\n    a && (i ? a.splice(a.indexOf(i) >>> 0, 1) : t.set(o, []));\n  }, emit: function(o, i) {\n    var a = t.get(o);\n    a && a.slice().map(function(r) {\n      r(i);\n    }), (a = t.get(\"*\")) && a.slice().map(function(r) {\n      r(o, i);\n    });\n  } };\n}\nconst y = it(), T = \"[-+]?[0-9]*.?[0-9]+\", R = [\n  {\n    name: \"px\",\n    regexp: new RegExp(`^${T}px$`)\n  },\n  {\n    name: \"%\",\n    regexp: new RegExp(`^${T}%$`)\n  },\n  /**\n   * Fallback option\n   * If no suffix specified, assigning \"px\"\n   */\n  {\n    name: \"px\",\n    regexp: new RegExp(`^${T}$`)\n  }\n], at = (t) => {\n  if (t === \"auto\")\n    return {\n      type: t,\n      value: 0\n    };\n  for (let o = 0; o < R.length; o++) {\n    const i = R[o];\n    if (i.regexp.test(t))\n      return {\n        type: i.name,\n        value: parseFloat(t)\n      };\n  }\n  return {\n    type: \"\",\n    value: t\n  };\n}, st = (t) => {\n  switch (typeof t) {\n    case \"number\":\n      return { type: \"px\", value: t };\n    case \"string\":\n      return at(t);\n    default:\n      return { type: \"\", value: t };\n  }\n}, j = {\n  x: /* @__PURE__ */ new Set([\"left\", \"center\", \"right\"]),\n  y: /* @__PURE__ */ new Set([\"top\", \"bottom\"])\n}, rt = /* @__PURE__ */ ((t) => () => t++)(0), lt = (t) => typeof t != \"string\" ? [] : t.split(/\\s+/gi).filter(Boolean), ct = (t) => {\n  typeof t == \"string\" && (t = lt(t));\n  let o = null, i = null;\n  return t.forEach((a) => {\n    j.y.has(a) && (i = a), j.x.has(a) && (o = a);\n  }), { x: o, y: i };\n}, b = {\n  position: [\"top\", \"right\"],\n  cssAnimation: \"vn-fade\",\n  velocityAnimation: {\n    enter: (t) => ({\n      height: [t.clientHeight, 0],\n      opacity: [1, 0]\n    }),\n    leave: {\n      height: 0,\n      opacity: [0, 1]\n    }\n  }\n}, ut = (t, o) => {\n  let i, a, r = o;\n  const m = () => {\n    a = Date.now(), i = setTimeout(t, r);\n  }, g = () => {\n    clearTimeout(i), r -= Date.now() - a;\n  };\n  return m(), {\n    start: m,\n    stop: g\n  };\n};\nfunction ft(t) {\n  return typeof t == \"function\" || Object.prototype.toString.call(t) === \"[object Object]\" && !ot(t);\n}\nconst v = {\n  IDLE: 0,\n  DESTROYED: 2\n}, dt = /* @__PURE__ */ Q({\n  // eslint-disable-next-line vue/multi-word-component-names\n  name: \"notifications\",\n  props: {\n    group: {\n      type: String,\n      default: \"\"\n    },\n    /** \n     * Width of notification holder, can be `%`, `px` string or number.\n     * @example '100%', '200px', 200 \n     * */\n    width: {\n      type: [Number, String],\n      default: 300\n    },\n    reverse: {\n      type: Boolean,\n      default: !1\n    },\n    position: {\n      type: [String, Array],\n      default: () => b.position\n    },\n    classes: {\n      type: [String, Array],\n      default: \"vue-notification\"\n    },\n    animationType: {\n      type: String,\n      default: \"css\",\n      validator(t) {\n        return t === \"css\" || t === \"velocity\";\n      }\n    },\n    animation: {\n      type: Object,\n      default() {\n        return b.velocityAnimation;\n      }\n    },\n    animationName: {\n      type: String,\n      default: b.cssAnimation\n    },\n    speed: {\n      type: Number,\n      default: 300\n    },\n    /** Time (in ms) to keep the notification on screen (if **negative** - notification will stay **forever** or until clicked) */\n    duration: {\n      type: Number,\n      default: 3e3\n    },\n    delay: {\n      type: Number,\n      default: 0\n    },\n    max: {\n      type: Number,\n      default: 1 / 0\n    },\n    ignoreDuplicates: {\n      type: Boolean,\n      default: !1\n    },\n    closeOnClick: {\n      type: Boolean,\n      default: !0\n    },\n    pauseOnHover: {\n      type: Boolean,\n      default: !1\n    },\n    /** Use [v-html](https://vuejs.org/api/built-in-directives.html#v-html) to set `title` and `text` */\n    dangerouslySetInnerHtml: {\n      type: Boolean,\n      default: !1\n    }\n  },\n  emits: {\n    /* eslint-disable @typescript-eslint/no-unused-vars */\n    click: (t) => !0,\n    destroy: (t) => !0,\n    start: (t) => !0\n    /* eslint-enable @typescript-eslint/no-unused-vars */\n  },\n  slots: Object,\n  setup: (t, {\n    emit: o,\n    slots: i,\n    expose: a\n  }) => {\n    const r = X([]), m = B.get(\"velocity\"), g = h(() => t.animationType === \"velocity\"), c = h(() => r.value.filter((e) => e.state !== v.DESTROYED)), D = h(() => st(t.width)), S = h(() => {\n      const {\n        x: e,\n        y: n\n      } = ct(t.position), s = D.value.value, u = D.value.type, p = {\n        width: s + u\n      };\n      return n && (p[n] = \"0px\"), e && (e === \"center\" ? p.left = `calc(50% - ${+s / 2}${u})` : p[e] = \"0px\"), p;\n    }), L = h(() => g.value ? {\n      onEnter: G,\n      onLeave: W,\n      onAfterLeave: A\n    } : {}), k = (e) => {\n      o(\"click\", e), t.closeOnClick && d(e);\n    }, C = (e) => {\n      var n;\n      t.pauseOnHover && ((n = e.timer) == null || n.stop());\n    }, P = (e) => {\n      var n;\n      t.pauseOnHover && ((n = e.timer) == null || n.start());\n    }, N = (e = {}) => {\n      if (e.group || (e.group = \"\"), e.data || (e.data = {}), t.group !== e.group)\n        return;\n      if (e.clean || e.clear) {\n        F();\n        return;\n      }\n      const n = typeof e.duration == \"number\" ? e.duration : t.duration, s = typeof e.speed == \"number\" ? e.speed : t.speed, u = typeof e.ignoreDuplicates == \"boolean\" ? e.ignoreDuplicates : t.ignoreDuplicates, {\n        title: p,\n        text: U,\n        type: q,\n        data: z,\n        id: J\n      } = e, f = {\n        id: J || rt(),\n        title: p,\n        text: U,\n        type: q,\n        state: v.IDLE,\n        speed: s,\n        length: n + 2 * s,\n        data: z,\n        duplicates: 0\n      };\n      n >= 0 && (f.timer = ut(() => d(f), f.length));\n      const I = \"bottom\" in S.value, K = t.reverse ? !I : I;\n      let x = -1;\n      const $ = c.value.find((M) => M.title === e.title && M.text === e.text);\n      if (u && $) {\n        $.duplicates++;\n        return;\n      }\n      K ? (r.value.push(f), o(\"start\", f), c.value.length > t.max && (x = 0)) : (r.value.unshift(f), o(\"start\", f), c.value.length > t.max && (x = c.value.length - 1)), x !== -1 && d(c.value[x]);\n    }, O = (e) => {\n      _(e);\n    }, Y = (e) => [\"vue-notification-template\", t.classes, e.type || \"\"], V = (e) => g.value ? void 0 : {\n      transition: `all ${e.speed}ms`\n    }, d = (e) => {\n      var n;\n      (n = e.timer) == null || n.stop(), e.state = v.DESTROYED, A(), o(\"destroy\", e);\n    }, _ = (e) => {\n      const n = r.value.find((s) => s.id === e);\n      n && d(n);\n    }, F = () => {\n      c.value.forEach(d);\n    }, w = (e, n) => {\n      var u;\n      const s = (u = t.animation) == null ? void 0 : u[e];\n      return typeof s == \"function\" ? s(n) : s;\n    }, G = (e, n) => {\n      const s = w(\"enter\", e);\n      m(e, s, {\n        duration: t.speed,\n        complete: n\n      });\n    }, W = (e, n) => {\n      const s = w(\"leave\", e);\n      m(e, s, {\n        duration: t.speed,\n        complete: n\n      });\n    };\n    function A() {\n      r.value = r.value.filter((e) => e.state !== v.DESTROYED);\n    }\n    return Z(() => {\n      y.on(\"add\", N), y.on(\"close\", O);\n    }), tt(() => {\n      y.off(\"add\", N), y.off(\"close\", O);\n    }), () => {\n      let e;\n      return l(\"div\", {\n        class: \"vue-notification-group\",\n        style: S.value\n      }, [l(et, nt(L.value, {\n        tag: \"div\",\n        css: !g.value,\n        name: t.animationName\n      }), ft(e = c.value.map((n) => l(\"div\", {\n        key: n.id,\n        class: \"vue-notification-wrapper\",\n        style: V(n),\n        \"data-id\": n.id,\n        onMouseenter: () => C(n),\n        onMouseleave: () => P(n)\n      }, [i.body ? i.body({\n        item: n,\n        class: [t.classes, n.type],\n        close: () => d(n)\n      }) : l(\"div\", {\n        class: Y(n),\n        onClick: () => k(n)\n      }, [t.dangerouslySetInnerHtml ? l(H, null, [n.title ? l(\"div\", {\n        class: \"notification-title\",\n        innerHTML: n.title\n      }, null) : null, l(\"div\", {\n        class: \"notification-content\",\n        innerHTML: n.text\n      }, null)]) : l(H, null, [n.title ? l(\"div\", {\n        class: \"notification-title\"\n      }, [n.title]) : null, l(\"div\", {\n        class: \"notification-content\"\n      }, [n.text])])])]))) ? e : {\n        default: () => [e]\n      })]);\n    };\n  }\n}), E = (t) => {\n  typeof t == \"string\" && (t = { title: \"\", text: t }), typeof t == \"object\" && y.emit(\"add\", t);\n};\nE.close = (t) => {\n  y.emit(\"close\", t);\n};\nconst gt = () => ({ notify: E }), pt = \"Notifications\";\nfunction yt(t, o = {}) {\n  Object.entries(o).forEach((a) => B.set(...a));\n  const i = o.name || \"notify\";\n  t.config.globalProperties[\"$\" + i] = E, t.component(o.componentName || pt, dt);\n}\nconst ht = {\n  install: yt\n};\nexport {\n  dt as Notifications,\n  ht as default,\n  E as notify,\n  gt as useNotification\n};\n","import { useNotification } from \"@kyvg/vue3-notification\";\n\n/**\n * composable to trigger the BaseNotification component\n * @returns {{notify: {(args: (NotificationsOptions | string)): void, close(id: unknown): void}}}\n */\nexport function useNotifications() {\n  const { notify }  = useNotification();\n\n  return {\n    notify,\n  };\n}\n","function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\n// Older browsers don't support event options, feature detect it.\n\n// Adopted and modified solution from Bohdan Didukh (2017)\n// https://stackoverflow.com/questions/41594997/ios-10-safari-prevent-scrolling-behind-a-fixed-overlay-and-maintain-scroll-posi\n\nvar hasPassiveEvents = false;\nif (typeof window !== 'undefined') {\n  var passiveTestOptions = {\n    get passive() {\n      hasPassiveEvents = true;\n      return undefined;\n    }\n  };\n  window.addEventListener('testPassive', null, passiveTestOptions);\n  window.removeEventListener('testPassive', null, passiveTestOptions);\n}\n\nvar isIosDevice = typeof window !== 'undefined' && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === 'MacIntel' && window.navigator.maxTouchPoints > 1);\n\n\nvar locks = [];\nvar documentListenerAdded = false;\nvar initialClientY = -1;\nvar previousBodyOverflowSetting = void 0;\nvar previousBodyPosition = void 0;\nvar previousBodyPaddingRight = void 0;\n\n// returns true if `el` should be allowed to receive touchmove events.\nvar allowTouchMove = function allowTouchMove(el) {\n  return locks.some(function (lock) {\n    if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {\n      return true;\n    }\n\n    return false;\n  });\n};\n\nvar preventDefault = function preventDefault(rawEvent) {\n  var e = rawEvent || window.event;\n\n  // For the case whereby consumers adds a touchmove event listener to document.\n  // Recall that we do document.addEventListener('touchmove', preventDefault, { passive: false })\n  // in disableBodyScroll - so if we provide this opportunity to allowTouchMove, then\n  // the touchmove event on document will break.\n  if (allowTouchMove(e.target)) {\n    return true;\n  }\n\n  // Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom).\n  if (e.touches.length > 1) return true;\n\n  if (e.preventDefault) e.preventDefault();\n\n  return false;\n};\n\nvar setOverflowHidden = function setOverflowHidden(options) {\n  // If previousBodyPaddingRight is already set, don't set it again.\n  if (previousBodyPaddingRight === undefined) {\n    var _reserveScrollBarGap = !!options && options.reserveScrollBarGap === true;\n    var scrollBarGap = window.innerWidth - document.documentElement.clientWidth;\n\n    if (_reserveScrollBarGap && scrollBarGap > 0) {\n      var computedBodyPaddingRight = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'), 10);\n      previousBodyPaddingRight = document.body.style.paddingRight;\n      document.body.style.paddingRight = computedBodyPaddingRight + scrollBarGap + 'px';\n    }\n  }\n\n  // If previousBodyOverflowSetting is already set, don't set it again.\n  if (previousBodyOverflowSetting === undefined) {\n    previousBodyOverflowSetting = document.body.style.overflow;\n    document.body.style.overflow = 'hidden';\n  }\n};\n\nvar restoreOverflowSetting = function restoreOverflowSetting() {\n  if (previousBodyPaddingRight !== undefined) {\n    document.body.style.paddingRight = previousBodyPaddingRight;\n\n    // Restore previousBodyPaddingRight to undefined so setOverflowHidden knows it\n    // can be set again.\n    previousBodyPaddingRight = undefined;\n  }\n\n  if (previousBodyOverflowSetting !== undefined) {\n    document.body.style.overflow = previousBodyOverflowSetting;\n\n    // Restore previousBodyOverflowSetting to undefined\n    // so setOverflowHidden knows it can be set again.\n    previousBodyOverflowSetting = undefined;\n  }\n};\n\nvar setPositionFixed = function setPositionFixed() {\n  return window.requestAnimationFrame(function () {\n    // If previousBodyPosition is already set, don't set it again.\n    if (previousBodyPosition === undefined) {\n      previousBodyPosition = {\n        position: document.body.style.position,\n        top: document.body.style.top,\n        left: document.body.style.left\n      };\n\n      // Update the dom inside an animation frame \n      var _window = window,\n          scrollY = _window.scrollY,\n          scrollX = _window.scrollX,\n          innerHeight = _window.innerHeight;\n\n      document.body.style.position = 'fixed';\n      document.body.style.top = -scrollY;\n      document.body.style.left = -scrollX;\n\n      setTimeout(function () {\n        return window.requestAnimationFrame(function () {\n          // Attempt to check if the bottom bar appeared due to the position change\n          var bottomBarHeight = innerHeight - window.innerHeight;\n          if (bottomBarHeight && scrollY >= innerHeight) {\n            // Move the content further up so that the bottom bar doesn't hide it\n            document.body.style.top = -(scrollY + bottomBarHeight);\n          }\n        });\n      }, 300);\n    }\n  });\n};\n\nvar restorePositionSetting = function restorePositionSetting() {\n  if (previousBodyPosition !== undefined) {\n    // Convert the position from \"px\" to Int\n    var y = -parseInt(document.body.style.top, 10);\n    var x = -parseInt(document.body.style.left, 10);\n\n    // Restore styles\n    document.body.style.position = previousBodyPosition.position;\n    document.body.style.top = previousBodyPosition.top;\n    document.body.style.left = previousBodyPosition.left;\n\n    // Restore scroll\n    window.scrollTo(x, y);\n\n    previousBodyPosition = undefined;\n  }\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions\nvar isTargetElementTotallyScrolled = function isTargetElementTotallyScrolled(targetElement) {\n  return targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false;\n};\n\nvar handleScroll = function handleScroll(event, targetElement) {\n  var clientY = event.targetTouches[0].clientY - initialClientY;\n\n  if (allowTouchMove(event.target)) {\n    return false;\n  }\n\n  if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {\n    // element is at the top of its scroll.\n    return preventDefault(event);\n  }\n\n  if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) {\n    // element is at the bottom of its scroll.\n    return preventDefault(event);\n  }\n\n  event.stopPropagation();\n  return true;\n};\n\nexport var disableBodyScroll = function disableBodyScroll(targetElement, options) {\n  // targetElement must be provided\n  if (!targetElement) {\n    // eslint-disable-next-line no-console\n    console.error('disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.');\n    return;\n  }\n\n  // disableBodyScroll must not have been called on this targetElement before\n  if (locks.some(function (lock) {\n    return lock.targetElement === targetElement;\n  })) {\n    return;\n  }\n\n  var lock = {\n    targetElement: targetElement,\n    options: options || {}\n  };\n\n  locks = [].concat(_toConsumableArray(locks), [lock]);\n\n  if (isIosDevice) {\n    setPositionFixed();\n  } else {\n    setOverflowHidden(options);\n  }\n\n  if (isIosDevice) {\n    targetElement.ontouchstart = function (event) {\n      if (event.targetTouches.length === 1) {\n        // detect single touch.\n        initialClientY = event.targetTouches[0].clientY;\n      }\n    };\n    targetElement.ontouchmove = function (event) {\n      if (event.targetTouches.length === 1) {\n        // detect single touch.\n        handleScroll(event, targetElement);\n      }\n    };\n\n    if (!documentListenerAdded) {\n      document.addEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n      documentListenerAdded = true;\n    }\n  }\n};\n\nexport var clearAllBodyScrollLocks = function clearAllBodyScrollLocks() {\n  if (isIosDevice) {\n    // Clear all locks ontouchstart/ontouchmove handlers, and the references.\n    locks.forEach(function (lock) {\n      lock.targetElement.ontouchstart = null;\n      lock.targetElement.ontouchmove = null;\n    });\n\n    if (documentListenerAdded) {\n      document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n      documentListenerAdded = false;\n    }\n\n    // Reset initial clientY.\n    initialClientY = -1;\n  }\n\n  if (isIosDevice) {\n    restorePositionSetting();\n  } else {\n    restoreOverflowSetting();\n  }\n\n  locks = [];\n};\n\nexport var enableBodyScroll = function enableBodyScroll(targetElement) {\n  if (!targetElement) {\n    // eslint-disable-next-line no-console\n    console.error('enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.');\n    return;\n  }\n\n  locks = locks.filter(function (lock) {\n    return lock.targetElement !== targetElement;\n  });\n\n  if (isIosDevice) {\n    targetElement.ontouchstart = null;\n    targetElement.ontouchmove = null;\n\n    if (documentListenerAdded && locks.length === 0) {\n      document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n      documentListenerAdded = false;\n    }\n  }\n\n  if (isIosDevice) {\n    restorePositionSetting();\n  } else {\n    restoreOverflowSetting();\n  }\n};\n\n","import {\n  disableBodyScroll,\n  enableBodyScroll,\n  clearAllBodyScrollLocks,\n} from 'body-scroll-lock';\nimport { computed, onBeforeUnmount, onUpdated, ref, watch } from 'vue';\n\n/**\n * function to place a scroll lock on the body when a target element is displayed\n * governed via variable showElement\n *\n * @param {Ref<UnwrapRef<HTMLElement>>|Ref<UnwrapRef<null>>} target - the element that is toggled\n *  and should trigger the scroll lock\n * @returns {{toggleScrollLock: function, showElement: Ref<UnwrapRef<boolean>>}}\n */\nexport function usePopUpLock(target) {\n  const showElement = ref(false);\n  // create a separate variable here so we can use regular HTML elements OR vue components\n  const targetElement = computed(() => {\n    // if target is still undefined just return null for now\n    if (!target) return null;\n    // else check if this is a Ref element - and return the value\n    // or if it is a vue component the coresponding $el\n    // else just return the target itself\n    return target.value ? target.value.$el || target.value : target;\n  });\n\n  function toggleScrollLock(value) {\n    showElement.value = value;\n  }\n\n  watch(showElement, (val) => {\n    if (val && targetElement.value) {\n      disableBodyScroll(targetElement.value, {\n        reserveScrollBarGap: true,\n      });\n    }\n  });\n\n  onUpdated(() => {\n    if (targetElement?.value) {\n      if (showElement.value) {\n        disableBodyScroll(targetElement.value, {\n          allowTouchMove: () => true,\n          reserveScrollBarGap: true,\n        });\n      } else {\n        enableBodyScroll(targetElement.value);\n      }\n    }\n  });\n  onBeforeUnmount(() => {\n    clearAllBodyScrollLocks();\n  });\n\n  return {\n    toggleScrollLock,\n    showElement,\n  };\n}\n","import { computed, ref, watchEffect } from 'vue';\n\n/**\n * Handle tab key events to focus a list of focusable HTML elements\n * Note: Currently the composable makes troubles when imported from the base-ui-components library.\n * TODO: Find another way to initialize the EventListener than within the watchEffect method.\n *\n * @param {Object, String} target - container element where the focusableElements are located\n *                                  * can be either a Vue reference object or\n *                                  * a string representing a CSS selector\n * @param {string} focusableElements - comma separated list of HTML elements to focus\n * @param {boolean} disable - disable method and do nothing\n * @returns {{focusableHTMLTags: *, disableHandler: *}}\n */\nexport function useTabKeyHandler(target, focusableElements, disable = false) {\n  const focusableHTMLTags = ref(focusableElements);\n  const disableHandler = ref(disable);\n\n  /**\n   * determine the target HTML element\n   * @return {HTMLElement, undefined}\n   */\n  const targetElement = computed(() => {\n    if (typeof target === 'object' && target?.value) {\n      return target.value;\n    }\n    // if target is a string representing a CSS selector\n    if (typeof target === 'string' && document?.querySelector(target)) {\n      return document?.querySelector(target);\n    }\n    return undefined;\n  });\n\n  /**\n   * get focusable dom elements within a target container element\n   * @return array - list of focusable DOM elements\n   */\n  function getFocusableElements() {\n    // if targetElement is not defined, return an empty array\n    if (!targetElement.value) return [];\n    // define an empty list\n    const elements = Array.from(targetElement.value.querySelectorAll(focusableHTMLTags.value));\n    // return DOM visible focusable elements\n    return elements.filter(element => element.checkVisibility());\n  }\n\n  /**\n   * set focus to next/prev focusable DOM element\n   * @param {string} direction\n   */\n  function setFocus(direction = 'next') {\n    const elements = getFocusableElements();\n    if (!elements.length) return;\n\n    let currentFocus = null;\n    let nextFocus = null;\n    // find current focus\n    elements.forEach((element, index) => {\n      if (element.matches(':focus')) {\n        currentFocus = index;\n      }\n    });\n    // if the current focus is not one of the focusable items, use the first one\n    if (currentFocus === null) {\n      elements[0].focus();\n      return;\n    }\n    // set the next focus depending on the direction\n    if (direction === 'next') {\n      nextFocus = elements[currentFocus + 1] ? currentFocus + 1 : 0;\n    }\n    if (direction === 'prev') {\n      nextFocus = elements[currentFocus - 1]\n        ? currentFocus - 1 : elements.length - 1;\n    }\n    // finally, set focus\n    elements[nextFocus].focus();\n  }\n\n  /**\n   * intercept tab key event\n   * @param {Object} e - event\n   */\n  function tabKeyHandler(e) {\n    if (disableHandler.value) return;\n\n    if (e.shiftKey && e.key === 'Tab') {\n      e.preventDefault();\n      setFocus('prev');\n      return;\n    }\n\n    if (e.key === 'Tab') {\n      e.preventDefault();\n      setFocus('next');\n    }\n  }\n\n  watchEffect(() => {\n    /**\n     * Currently the composable makes troubles when imported from the base-ui-components library.\n     * Somehow the watchEffect method is called before the DOM is updated.\n     * TODO: find another way to initialize the eventListener\n     */\n    if (targetElement.value) {\n      targetElement.value.addEventListener('keydown', tabKeyHandler);\n    }\n  });\n\n  return {\n    focusableHTMLTags,\n    disableHandler,\n  };\n}\n","import { computed, ref } from 'vue';\nimport { useEventListener } from '@/composables/useEventListener.js';\n\n/**\n * composable that manages an event listener on the window resize event\n *  and returns variables windowInnerWidth the window.innerWidth in px as well\n *  as isMobile and isTablet for device size dependent logic\n *\n * @param {function} callback - the function to be executed on resize\n * @param {number} [mobileMaxSize=639] - specify a max mobile size\n * @param {number} [tabletMaxSize=1023] - specify a max tablet size\n * @param {boolean|number} [setDebounce=false] - specify a time (in ms) if a timeout should be set before\n *  calling the function\n * @param {boolean} [callOnMounted=false] - specify if function should be called the first time on mounted\n * @returns {{windowInnerWidth: number, isTablet: boolean, isMobile: boolean}}\n */\nexport function useWindowResize({\n  callback,\n  mobileMaxSize = 639,\n  tabletMaxSize = 1023,\n  setDebounce = false,\n  callOnMounted = false,\n}) {\n  /**\n   * variable to store window inner width\n   * @type {Ref<UnwrapRef<number>>}\n   */\n  const windowInnerWidth = ref(0);\n  /**\n   * is window width within mobile size\n   * @type {ComputedRef<boolean>}\n   */\n  const isMobile = computed(() => windowInnerWidth.value <= mobileMaxSize);\n  /**\n   * is window width within tablet size\n   * @type {ComputedRef<boolean>}\n   */\n  const isTablet = computed(() => windowInnerWidth.value <= tabletMaxSize);\n\n  /**\n   * on resize update the windowInnerWidth variable and\n   * execute the function provided to the composable\n   */\n  function resize() {\n    // safeguard against window not being defined yet\n    windowInnerWidth.value = window?.innerWidth || 0;\n    callback();\n  }\n\n  useEventListener({\n    target: 'window',\n    event: 'resize',\n    callback: resize,\n    setDebounce,\n    callOnMounted,\n  });\n\n  return {\n    windowInnerWidth,\n    isMobile,\n    isTablet,\n  };\n}\n","<script>\nimport { defineAsyncComponent, computed, useTemplateRef, watch } from 'vue';\nimport { useId } from '@/composables/useId.js';\nimport { useAnnouncer } from '@/composables/useAnnouncer.js';\nimport { useExtractAttrs } from '@/composables/useExtractAttrs.js';\n\n/**\n * A basic text search to filter entries or files\n */\nexport default {\n  name: 'BaseSearch',\n  components: {\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseChipsInputField: defineAsyncComponent(() => import('@/components/BaseChipsInputField/BaseChipsInputField.vue')),\n    BaseInput: defineAsyncComponent(() => import('@/components/BaseInput/BaseInput.vue')),\n    BaseDateInput: defineAsyncComponent(() => import('@/components/BaseDateInput/BaseDateInput.vue')),\n  },\n  inheritAttrs: false,\n  props: {\n    /**\n     * set input value from outside\n     *   for searchType `daterange` this needs to be an object with\n     *   `date_from` and `date_to` properties!\n     */\n    modelValue: {\n      type: [String, Object],\n      default: '',\n    },\n    /**\n     * if input searchType is `chips` this is the prop to\n     * pass selected options (chips).\n     *  you may use the v-model directive on this prop\n     */\n    selectedChips: {\n      type: Array,\n      default: () => ([]),\n    },\n    /**\n     * placeholder to show for input; either just a string or an object with\n     * different text for each search type (`text`, `chips`, `date`)\n     */\n    placeholder: {\n      type: [String, Object],\n      default: 'Search your works and events',\n    },\n    /**\n     * label connected with input (will not be visible but for usability!)\n     */\n    label: {\n      type: String,\n      default: 'Search',\n    },\n    /**\n     * define if the magnifier glass (in front of input field) should be shown\n     */\n    showPreInputIcon: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * specify the id of a linked drop down list\n     */\n    dropDownListId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify a field id for identification of the input field\n     * if none is specified an internal id will be assigned\n     */\n    inputId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify the type of input field\n     * @values text, chips, controlled, date, daterange, chipssingle\n     */\n    searchType: {\n      type: String,\n      default: 'text',\n      validator: val => ['text', 'chips', 'chipssingle', 'controlled', 'date', 'daterange'].includes(val),\n    },\n    /**\n     * specify a linked list option (e.g. drop down)\n     *   (will be used in `aria-activedescendant` attribute)\n     */\n    linkedListOption: {\n      type: [Number, String],\n      default: null,\n    },\n    /**\n     * if `true` space is reserved for a loader that can be activated\n     * with the 'isLoading' prop\n     */\n    loadable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * is loading indicator - showing loader if `true`\n     */\n    isLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set the language (ISO 639-1)\n     */\n    language: {\n      type: String,\n      default: 'en',\n      validator: val => !val || val.length === 2,\n    },\n    /**\n     * specify the object property that should be used as identifier (only needed\n     * for type `chips`\n     */\n    identifierPropertyName: {\n      type: String,\n      default: 'id',\n    },\n    /**\n     * specify the object property that should be used as value to be displayed (only needed\n     * for type `chips`\n     */\n    labelPropertyName: {\n      type: String,\n      default: 'label',\n    },\n    /**\n     * mark the form field as invalid and ideally also provide an error message\n     * to display below the form field.\n     * for an example see [BaseInput](BaseInput)\n     */\n    invalid: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define if error icon should be shown\n     * for an example see [BaseInput](BaseInput)\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * if `true` a remove icon will be shown allowing to remove\n     * all input at once.\n     * for an example see [BaseInput](BaseInput)\n     */\n    clearable: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * set active state from outside\n     */\n    isActive: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * use this prop to deactivate automatic setting of focus as soon as input element\n     * becomes active - this might require external handling of focus setting!\n     */\n    setFocusOnActive: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * for `searchType` 'chips': set this false if you want to add the chip\n     * manually e.g. if option is selected from a dropdown, `true` is mainly\n     * just useful if BaseSearch is a standalone element\n     */\n    addChipsInputDirectly : {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * this prop gives the option to add assistive text for screen readers\n     * properties:\n     *\n     * **selectedOption**: text read when a selected option is focused (currently only\n     *  working for type chips)\n     * **loaderActive**: text that is announced when results are being fetched (prop\n     *  `isLoading` is set `true`)\n     * **clearInput**: text read for remove input icon if prop `clearable` is set `true`\n     * **optionAdded**: text read when an option was added to selected list (for type `chips`)\n     * **optionToRemoveSelected**: text read when a selected option is in\n     *    focus to be removed (for type `chips`)\n     * **optionRemoved**: text read when an option was removed\n     *    from selected list (for type `chips`)\n     * **results**: provide text that should be announced when the search has\n     *  yielded results (or not).\n     *\n     *  Caveat: `results` has a watcher attached to trigger the\n     *    announcement so make sure the property values are reset after filling them\n     *    by using update:assistive-text or resetting it manually (after a timeout)\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        selectedOption: '',\n        loaderActive: 'loading.',\n        clearInput: 'Clear input',\n        optionAdded: 'option {label} added to selected list.',\n        optionToRemoveSelected: 'option {label} from selected list marked for removal. Press delete or backspace to remove.',\n        optionRemoved: 'option {label} removed.',\n        results: '',\n      }),\n    },\n    /**\n     * use this prop to set a delay in ms before date input calendar is displayed\n     */\n    dateFieldDelay: {\n      type: Number,\n      default: 0,\n    },\n  },\n  emits: ['update:model-value', 'update:selected-chips', 'update:is-active', 'update:assistive-text'],\n  setup(props, { emit }) {\n    /** ATTRS HANDLING */\n    const { rootAttrs, forwardAttrs } = useExtractAttrs();\n\n    /** INTERNAL ID */\n      // get an internal id in case prop inputId is not set, but do it\n      // before the compute so its only calculated once and stays the same\n    const internalId = useId();\n    /**\n     * internally used id - eiter provided by props or use internally created one\n     * @returns {string}\n     */\n    const idInt = computed(() => props.inputId || internalId);\n\n    /** INPUT REF HANDLING */\n    /**\n     * we want to keep the reference to the native input HTML element and have it\n     * accessible for the parent\n     * so we create a reference to the Vue component first - this can be a BaseInput,\n     * BaseChipsInputField or BaseDateInput (all of which have the variable `inputElement`\n     * pointing to the native input element)\n     * @type {Readonly<ShallowRef<unknown | HTMLElement>>}\n     */\n    const inputComponent = useTemplateRef('inputComponentEl');\n    /**\n     * and then assign the component `input` variable as soon as the component\n     * is available\n     * this variable is used in BaseAdvancedSearch!!\n     * @type {ComputedRef<HTMLElement|null>}\n     */\n    const inputElement = computed(() => inputComponent.value?.inputElement || null);\n    /**\n     * in case of BaseDateInput there could be more than one input element so also expose\n     * all fields to the parent\n     * @type {ComputedRef<HTMLElement|null[]>}\n     */\n    const inputElements = computed(() => inputComponent.value?.inputElements || null);\n\n    /** TAB KEY HANDLER */\n    /**\n     * set up a reference to the element to be able to attach the announcements element\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const search = useTemplateRef('searchEl');\n    /**\n     * insert an HTML element with aria-live assertive that will announce the\n     * search result\n     * @type {Ref<UnwrapRef<string>>}\n     */\n    const { announcement } = useAnnouncer(search);\n\n    // also add a watcher to the announcement variable so user can easily have assistiveText.results\n    // reset after announcement (the watcher for this variable again is only working in setup!)\n    watch(announcement, (val) => {\n      // check if values are already in sync\n      if (val !== props.assistiveText.results) {\n        // if not - emit update\n        /**\n         * event to keep assistiveText.results in sync after\n         * announcement\n         * @event update:assistive-text\n         * @type {Object}\n         */\n        emit('update:assistive-text', {\n          ...props.assistiveText,\n          results: val,\n        });\n      }\n    });\n\n    return {\n      rootAttrs,\n      forwardAttrs,\n      idInt,\n      inputElement,\n      inputElements,\n      search,\n      // need to just export the announcement text because setting it in setup function\n      // did not work in nuxt (respectively the watcher on assistiveText did not work)\n      announcement,\n    };\n  },\n  data() {\n    return {\n      /**\n       * internal handling of the input active state\n       * @type {boolean}\n       */\n      isActiveInt: false,\n      /**\n       * internal handling of text input --> for 'chips' and 'text'\n       * (separated from dateInputInt to preserve the input when switching type)\n       * @type {string}\n       */\n      textInputInt: '',\n      /**\n       * internal handling of date input (separated from textInputInt to preserve\n       * the input when switching type)\n       * @type {string|Object}\n       */\n      dateInputInt: '',\n      /**\n       * internal handling of selected chips for type 'chips'\n       * @type {Array}\n       */\n      selectedChipsInt: [],\n    };\n  },\n  computed: {\n    /**\n     * compute and import only the component necessary for the respective type selected\n     * @returns {null|(function(): Promise<HTMLElement>)|string}\n     */\n    inputComponent() {\n      if (this.searchType === 'text') {\n        return 'BaseInput';\n      } if (this.isFieldTypeChips) {\n        return 'BaseChipsInputField';\n      } if (this.searchType === 'date' || this.searchType === 'daterange') {\n        return 'BaseDateInput';\n      }\n      return null;\n    },\n    /**\n     * compute the inputInt used for BaseInput v-model\n     * this can either be a string or an object - also this is used to\n     * convert dates between 'daterange' and 'date'\n     */\n    inputInt: {\n      /**\n       * set either textInputInt or dateInputInt depending on the searchType\n       * @param {string|{date_to: string, date_from: string}} val - depending on the searchType\n       * this is a date string, text string or an Object for 'daterange' with the following\n       * properties:\n       * @property {string} val.date_from\n       * @property {string} val.date_to\n       */\n      set(val) {\n        if (this.searchType === 'date') {\n          this.dateInputInt = val;\n          /**\n           * inform parent of changed input values (v-model)\n           *\n           * @event update:model-value\n           * @param {string, Object} - the altered input values\n           */\n          this.$emit('update:model-value', this.dateInputInt);\n        } else if (this.searchType === 'daterange') {\n          this.dateInputInt = { ...val };\n          this.$emit('update:model-value', this.dateInputInt);\n        } else {\n          this.textInputInt = val;\n          this.$emit('update:model-value', this.textInputInt);\n        }\n      },\n      /**\n       * get inputInt according to search type\n       * @returns {string|{date_to: string, date_from: string}}\n       */\n      get() {\n        // for date or daterange use dateInputInt and use correct type\n        // this preserves the date when switching between date and daterange btw\n        if (this.searchType === 'date') {\n          return this.dateInputInt.date_from || this.dateInputInt;\n        }\n        if (this.searchType === 'daterange') {\n          return typeof this.dateInputInt === 'object' ? this.dateInputInt : {\n            date_from: this.dateInputInt,\n            date_to: '',\n          };\n        }\n        // everything else just return the textInputInt string\n        // this preserves the text switching between chips and text\n        return this.textInputInt;\n      },\n    },\n    /**\n     * in order to only attach the prop when it is a chips input we create a\n     * separate computed property\n     */\n    selectedChipsModelValue: {\n      set(val) {\n        this.selectedChipsInt = val;\n      },\n      get() {\n        if (this.isFieldTypeChips) {\n          return this.selectedChipsInt;\n        }\n        return null;\n      },\n    },\n    /**\n     * to easily access the type needed for BaseDateInput in case searchType\n     * is 'date' or 'daterange'\n     * @returns {string|boolean}\n     */\n    dateFieldType() {\n      if (this.searchType === 'date') {\n        return 'single';\n      }\n      if (this.searchType === 'daterange') {\n        return 'daterange';\n      }\n      // if searchType is neither 'date' or 'daterange' set the element attribute to null\n      // so it does not show up in the rendered HTML\n      return null;\n    },\n    /**\n     * compute adaptions necessary for BaseDateInput since this component currently\n     * only has 3 languages to choose from\n     * @returns {string}\n     */\n    languageInt() {\n      // adaptions for date input since only 'de', 'en', 'fr' available atm\n      if (this.searchType === 'date' || this.searchType === 'daterange') {\n        return ['de', 'en', 'fr'].includes(this.language) ? this.language : 'en';\n      }\n      return this.language;\n    },\n    /**\n     * determine if searchType is 'chips'\n     * @returns {boolean}\n     */\n    isFieldTypeChips() {\n      return this.searchType.includes('chips') || this.searchType === 'controlled';\n    },\n    placeholderInt() {\n      if (typeof this.placeholder === 'string') {\n        return this.placeholder;\n      }\n      if (this.searchType.includes('date')) {\n        return this.placeholder.date;\n      }\n      if (this.searchType === 'controlled' || this.searchType === 'chipssingle') {\n        return this.placeholder.chips;\n      }\n      return this.placeholder[this.searchType];\n    },\n  },\n  watch: {\n    /**\n     * watch modelValue prop to sync with inputInt\n     * @param {string|{date_from: string, date_to: string}} val\n     */\n    modelValue: {\n      handler(val) {\n        // if value is empty clear all input (to be able to reset the component completely)\n        if (!val) {\n          this.textInputInt = '';\n          this.dateInputInt = this.searchType === 'daterange' ? {\n            date_from: '',\n            date_to: '',\n          } : '';\n          // else if input is not matching internal input update\n        } else if (val !== this.inputInt) {\n          this.inputInt = val;\n        }\n      },\n      immediate: true,\n    },\n    /**\n     * watch inputInt to sync with parent input\n     * @param {string|{date_from: string, date_to: string}} val\n     */\n    inputInt(val) {\n      if (val !== this.modelValue) {\n        this.$emit('update:model-value', val);\n      }\n    },\n    /**\n     * watch selectedChips prop to sync with selectedChipsInt\n     * @param {Object[]} val\n     */\n    selectedChips: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.selectedChipsInt)) {\n          this.selectedChipsInt = [...val];\n        }\n      },\n      immediate: true,\n      deep: true,\n    },\n    /**\n     * watch selectedChipsInt to sync with selectedChips prop provided by parent\n     * @param {Object[]} val\n     */\n    selectedChipsInt: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.selectedChips)) {\n          /**\n           * inform parent of changes in selected chips\n           *\n           * @event update:selected-chips\n           * @param {Array} - the updated selected options list\n           */\n          this.$emit('update:selected-chips', val);\n        }\n      },\n      deep: true,\n    },\n    /**\n     * sync internal active state with parent\n     */\n    isActive: {\n      handler(val) {\n        if (val !== this.isActiveInt) {\n          this.isActiveInt = val;\n        }\n      },\n      immediate: true,\n    },\n    isActiveInt(val) {\n      if (val !== this.isActive) {\n        /**\n         * inform parent if is active has changed internally\n         * @event update:is-active\n         * @type {boolean}\n         */\n        this.$emit('update:is-active', val);\n      }\n    },\n    /**\n     * inserting this component in Nuxt only options API watcher on prop\n     * is working (in setup this is not working)\n     */\n    assistiveText: {\n      handler(val) {\n        // before updating check if value is different from already set value\n        // or that a value was provided for 'results'\n        if (val.results || (Boolean(val.results) !== Boolean(this.announcement))) {\n          this.announcement = val.results;\n        }\n      },\n      deep: true,\n    },\n  },\n  methods: {\n    onEnter(event) {\n      // if device has a virtual keyboard open we want to close it on search enter\n      // just to be safe also check if the target element (where the keydown came from) is the\n      // search input - compare ids\n      // add a few pixels (20) to account for scrollbar which would also alter visualViewport height\n      if (window.visualViewport.height + 20 < window.innerHeight && event.target.id === this.idInt) {\n        event.target.blur();\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <!-- make this a form so that iOS recognizes it as 'search'\n  (also the action=\".\" is needed for that) -->\n  <!-- ref is used in BaseAdvancedSearchRow! -->\n  <form\n    ref=\"searchEl\"\n    v-bind=\"rootAttrs\"\n    action=\".\"\n    role=\"search\"\n    class=\"base-search\"\n    @submit.prevent\n    @keydown.enter.prevent>\n    <component\n      :is=\"inputComponent\"\n      ref=\"inputComponentEl\"\n      v-model=\"inputInt\"\n      v-model:is-active=\"isActiveInt\"\n      v-model:selected-list=\"selectedChipsModelValue\"\n      v-bind=\"forwardAttrs\"\n      :input-id=\"idInt\"\n      :date-type=\"dateFieldType\"\n      :show-label=\"false\"\n      :use-form-field-styling=\"false\"\n      :show-input-border=\"false\"\n      :label=\"label\"\n      :placeholder=\"placeholderInt\"\n      :linked-list-option=\"linkedListOption\"\n      :drop-down-list-id=\"dropDownListId || undefined\"\n      :is-loading=\"!dateFieldType ? isLoading : undefined\"\n      :clearable=\"clearable\"\n      :invalid=\"invalid\"\n      :show-error-icon=\"showErrorIcon\"\n      :language=\"languageInt\"\n      :allow-unknown-entries=\"isFieldTypeChips ? searchType === 'chips' : undefined\"\n      :loadable=\"!dateFieldType ? loadable : undefined\"\n      :chips-editable=\"isFieldTypeChips ? searchType === 'chips' : undefined\"\n      :label-property-name=\"isFieldTypeChips ? labelPropertyName : undefined\"\n      :identifier-property-name=\"isFieldTypeChips ? identifierPropertyName : undefined\"\n      :set-focus-on-active=\"setFocusOnActive\"\n      :add-selected-entry-directly=\"isFieldTypeChips && addChipsInputDirectly || undefined\"\n      :assistive-text=\"!searchType.includes('date') ? {\n        selectedOption: assistiveText.selectedOption,\n        loaderActive: assistiveText.loaderActive,\n        clearInput: assistiveText.clearInput,\n        optionAdded: assistiveText.optionAdded,\n        optionToRemoveSelected: assistiveText.optionToRemoveSelected,\n        optionRemoved: assistiveText.optionRemoved,\n      } : {\n        clearInput: assistiveText.clearInput,\n      }\"\n      :is-active-delay=\"searchType.includes('date') ? dateFieldDelay : undefined\"\n      :allow-multiple-entries=\"isFieldTypeChips ? searchType !== 'chipssingle' : undefined\"\n      :chips-removable=\"isFieldTypeChips ? searchType !== 'chipssingle' : undefined\"\n      :input-type=\"'search'\"\n      input-class=\"base-search__input-field\"\n      enterkeyhint=\"search\"\n      class=\"base-search__input\"\n      @keydown.enter=\"onEnter\">\n      <template #pre-input-field>\n        <!-- @slot add elements within search but before all other elements. for an example see [BaseInput](BaseInput) -->\n        <slot name=\"pre-input-field\" />\n      </template>\n      <template #input-field-addition-before>\n        <!-- @slot add elements within search but before all other elements. for an example see [BaseInput](BaseInput) -->\n        <slot name=\"input-field-addition-before\" />\n      </template>\n      <template #input-field-inline-before>\n        <div\n          :class=\"[dateFieldType && showPreInputIcon\n            ? 'base-search__spacing-date' : 'base-search__spacing']\" />\n        <!-- @slot a slot to exchange the magnifier icon with other elements -->\n        <slot name=\"input-field-inline-before\">\n          <BaseIcon\n            v-if=\"showPreInputIcon\"\n            name=\"magnifier\"\n            :class=\"['base-search__magnifier-icon',\n                     { 'base-search__magnifier-icon__date': !!dateFieldType },\n                     { 'base-search__magnifier-icon__active': isActiveInt }]\" />\n        </slot>\n      </template>\n      <template #input-field-addition-after>\n        <!-- @slot for adding elements after input. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"input-field-addition-after\" />\n      </template>\n      <template #post-input-field>\n        <!-- @slot elements after the actual input element but within the input field container. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"post-input-field\" />\n        <div :class=\"{ 'base-search__spacing': dateFieldType }\" />\n      </template>\n      <template #error-icon>\n        <!-- @slot use a custom icon instead of standard error/warning icon. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"error-icon\" />\n      </template>\n      <template #remove-icon>\n        <!-- @slot for adding custom input remove icon. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"remove-icon\" />\n      </template>\n      <template #below-input>\n        <!-- @slot below-input slot added to e.g. add drop down -->\n        <slot name=\"below-input\" />\n      </template>\n    </component>\n  </form>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n.base-search {\n  background: white;\n  min-height: $row-height-large;\n  width: 100%;\n\n  .base-search__input {\n    background:white;\n    width: 100%;\n    min-height: $row-height-large;\n\n    .base-search__spacing {\n      margin-left: $spacing-small;\n      content: '';\n    }\n\n    .base-search__spacing-date {\n      margin-left: $spacing;\n    }\n\n    .base-search__magnifier-icon {\n      height: $icon-large;\n      width: $icon-large;\n      margin-right: $spacing;\n      flex-shrink: 0;\n      align-self: center;\n\n      &.base-search__magnifier-icon__date {\n        margin-right: $spacing-small;\n      }\n\n      &.base-search__magnifier-icon__active {\n        color: grey;\n        fill: grey;\n      }\n    }\n  }\n}\n</style>\n\n<style lang=\"scss\">\n@use \"@/styles/variables\" as *;\n.base-search__input-field {\n  min-height: $row-height-large !important;\n}\n</style>\n","<script>\nimport { useId } from '@/composables/useId.js';\n\n/**\n * A wrapper component for base icons\n */\n\nexport default {\n  name: 'BaseIcon',\n  props: {\n    /**\n     * define icon name\n     */\n    name: {\n      type: String,\n      default: null,\n      validator(val) {\n        return ['add-existing-collection', 'add-existing-object', 'add-new-collection', 'add-new-object', 'archive-arrow',\n          'archive-empty', 'archive-sheets', 'arrow-left', 'arrow-right', 'attachment', 'attention', 'audio-object', 'calendar-many',\n          'calendar-number', 'camera', 'check-mark', 'clock', 'collection', 'download', 'drag-lines', 'drag-n-drop',\n          'drop-down', 'duplicate', 'edit', 'eye-hide', 'eye', 'file-object', 'forbidden', 'fullscreen', 'fullscreen-exit',\n          'grid', 'home', 'image-object', 'image-cropped', 'image-resized', 'information', 'institution', 'information-solo',\n          'licence', 'logo', 'magnifier', 'minus', 'next', 'options-menu', 'people', 'people-filled', 'play', 'plus', 'prev', 'print',\n          'refresh', 'remove', 'save-file', 'separator-vertical', 'share', 'sort', 'subscribe', 'success', 'text', 'unsubscribe',\n          'video-object', 'waste-bin'].includes(val);\n      },\n    },\n    /**\n     * define title tag\n     */\n    title: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define description tag\n     */\n    desc: {\n      type: String,\n      default: '',\n    },\n  },\n  setup() {\n    const internalId = useId();\n    return {\n      internalId,\n    };\n  },\n  data() {\n    return {\n      // path to base-ui-icons.svg\n      baseIcons: null,\n    };\n  },\n  computed: {\n    icon() {\n      return `${this.baseIcons}#${this.name}`;\n    },\n    ariaAttribute() {\n      const aria = [];\n      if (this.title) {\n        aria.push(`title_${this.internalId}`);\n      }\n      if (this.desc) {\n        aria.push(`desc_${this.internalId}`);\n      }\n      return aria.join(' ');\n    },\n  },\n  mounted() {\n    // window.base_ui_icons could be adapted in parent frontend project\n    if (window.base_ui_icons) {\n      this.baseIcons = window.base_ui_icons;\n      return;\n    }\n    this.baseIcons = '/base-ui-icons.svg';\n  },\n};\n</script>\n\n<template>\n  <svg\n    :aria-labelledby=\"title || desc ? ariaAttribute : undefined\"\n    class=\"base-icon\">\n    <title\n      v-if=\"title\"\n      :id=\"'title_' + internalId\">{{ title }}</title>\n    <desc\n      v-if=\"desc\"\n      :id=\"'desc_' + internalId\">{{ desc }}</desc>\n    <use\n      v-if=\"baseIcons\"\n      :href=\"icon\" />\n  </svg>\n</template>\n\n<style lang=\"scss\" scoped>\n  .base-icon {\n    display: inline-block;\n    stroke-width: 0;\n    stroke: currentColor;\n    fill: currentColor;\n    max-height: 100%;\n    max-width: 100%;\n  }\n</style>\n","<script>\nimport { computed, defineAsyncComponent, useSlots } from 'vue';\nimport { useId } from '@/composables/useId.js';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\n\n/**\n * Standard buttons\n */\nexport default {\n  name: 'BaseButton',\n  components: {\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseBoxTooltip: defineAsyncComponent(() => import('@/components/BaseBoxTooltip/BaseBoxTooltip.vue')),\n  },\n  props: {\n    /**\n     * Button Text\n     *\n     * if button text is left empty and slot `text` is not used (so this is a button only\n     *  with an icon) please set at least the prop `description` or `iconTitle` for accessibility reasons!\n     */\n    text: {\n      type: String,\n      default: '',\n    },\n    // TODO: need to check if it is possible to use custom icons --> if yes description!\n    /**\n     * icon displayed\n     * see [BaseIcon](BaseIcon) for available icons\n     */\n    icon: {\n      type: String,\n      default: null,\n    },\n    /**\n     * set from outside if icon should be made invisible\n     */\n    hideIcon: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify if icon should be displayed left or right\n     */\n    iconPosition: {\n      type: String,\n      default: 'left',\n      validator(val) {\n        return ['top', 'right', 'left'].includes(val);\n      },\n    },\n    /**\n     * set button active (will display a colored border on botton) (row style)\n     * or keep icon colored (single style)\n     */\n    active: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify a button style\n     */\n    buttonStyle: {\n      type: String,\n      default: 'single',\n      validator(val) {\n        return ['single', 'row', 'secondary', 'circle'].includes(val);\n      },\n    },\n    /**\n     * display icon with app-color\n     */\n    iconColored: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify icon size\n     * **Caveat**: this will have no effect on `buttonStyle`: `secondary` | `circle` - icon will always be small\n     */\n    iconSize: {\n      type: String,\n      default: 'small',\n      validator(val) {\n        return ['small', 'large'].includes(val);\n      },\n    },\n    /**\n     * set a title for the icon that is shown as a tooltip on hover\n     */\n    iconTitle: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set button inactive\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set button type\n     */\n    buttonType: {\n      type: String,\n      default: 'button',\n    },\n    /**\n     * define alignment of button content\n     * Info: has no effect, if iconPosition 'top' is set\n     */\n    alignText: {\n      type: String,\n      default: 'center',\n      validator(val) {\n        return ['center', 'left', 'right'].includes(val);\n      },\n    },\n    /**\n     * background color is fixed however at least possibility to\n     * display transparent instead\n     */\n    hasBackgroundColor: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * show tooltip\n     */\n    showTooltip: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * Add a button description to be used by aria-describedby\n     */\n    description: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set false if button text should not be wrapped\n     */\n    buttonTextWrap: {\n      type: Boolean,\n      default: true,\n    },\n  },\n  emits: ['clicked'],\n  setup(props) {\n    /** INTERNAL ID */\n      // create a unique id\n    const internalId = useId();\n\n    /** SET BUTTON LABEL */\n    // access slots to check if it is filled later\n    const slots = useSlots();\n    // slot is not directly accessible anymore - use composable to determine\n    // if slot has content\n    const { slotHasContent = false } = useHasSlotContent(slots.text);\n\n    // compute if internal id should be set for aria-attribute\n    // (no need if no text or slot is not used)\n    const buttonHasTextElement = computed(() => (!!props.text  || slotHasContent.value) && props.buttonStyle !== 'circle');\n\n    return {\n      internalId,\n      buttonHasTextElement,\n    };\n  },\n  methods: {\n    clicked(event) {\n      /**\n       * triggered on button click\n       * @event clicked\n       * @param {Event} - the native click event\n       */\n      this.$emit('clicked', event);\n    },\n  },\n};\n</script>\n\n<template>\n  <button\n    ref=\"baseButton\"\n    :disabled=\"disabled || undefined\"\n    :aria-disabled=\"disabled || undefined\"\n    :aria-labelledby=\"buttonHasTextElement ? internalId : undefined\"\n    :aria-describedby=\"description ? `${internalId}-description` : undefined\"\n    :type=\"buttonType\"\n    :class=\"['base-button',\n             `base-button--${buttonStyle}`,\n             `base-button--icon-${iconPosition}`,\n             `base-button--align-${alignText}`,\n             { 'base-button--background': hasBackgroundColor },\n             { 'base-button--active': active }]\"\n    @click.prevent=\"clicked\">\n    <BaseIcon\n      v-if=\"icon\"\n      :name=\"icon\"\n      :title=\"iconTitle\"\n      :class=\"['base-button__icon',\n               'base-button__icon--' + iconSize,\n               { 'base-button__icon--colored': iconColored },\n               { 'base-button__icon--hide': hideIcon },\n               { 'base-button__icon--margin': buttonHasTextElement }]\" />\n\n    <!-- @slot create custom content (e.g. icon) left of text -->\n    <slot name=\"left-of-text\" />\n\n    <!-- @slot have your own text element which also allows for easier custom styling.\n      @binding {string|number} label-id If you are using this slot please also set the id of your custom element to `label-id` since this id is used for the <button> `aria-labelledby` attribute -->\n    <slot\n      name=\"text\"\n      :label-id=\"internalId\">\n      <span\n        v-if=\"text && buttonStyle !== 'circle'\"\n        :id=\"internalId\"\n        :class=\"['base-button__text', { 'base-button__text--nowrap': !buttonTextWrap }]\">\n        {{ text }}\n      </span>\n    </slot>\n\n    <!-- @slot create custom content (e.g. icon) right of text -->\n    <slot name=\"right-of-text\" />\n\n    <BaseBoxTooltip\n      v-if=\"showTooltip\"\n      @clicked=\"clicked\">\n      test\n    </BaseBoxTooltip>\n    <span\n      v-if=\"description\"\n      :id=\"`${internalId}-description`\"\n      class=\"hide\">\n      {{ description }}\n    </span>\n  </button>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n  @use \"@/styles/variables\" as *;\n\n  .base-button {\n    position: relative;\n    padding: 0 $spacing;\n    cursor: pointer;\n    display: flex;\n    align-items: center;\n    background-color: transparent;\n    transition: all 0.2s ease-in-out;\n    justify-content: center;\n    color: inherit;\n\n    .base-button__text {\n      text-align: center;\n\n      &.base-button__text--nowrap {\n        white-space: nowrap;\n      }\n    }\n\n    .base-button__icon {\n      height: $icon-small;\n      width: $icon-small;\n      max-width: $icon-small;\n      flex: 0 0 auto;\n      // added for drop icon animation\n      transition: transform 0.5s ease;\n\n      &.base-button__icon--colored {\n        color: $app-color;\n      }\n    }\n\n    /**\n     * button-style: row\n     */\n    &.base-button--row {\n      min-height: $row-height-large;\n\n      &.base-button--background {\n        background-color: white;\n      }\n\n      .base-button__icon--large {\n        height: $icon-large;\n        width: $icon-large;\n        max-width: $icon-large;\n      }\n\n      .base-button__icon--small {\n        height: $icon-medium;\n        width: $icon-medium;\n        max-width: $icon-medium;\n      }\n\n      &.base-button--active {\n        /* TODO: adjust this to style guide if necessary */\n        box-shadow: $box-shadow-reg, inset 0 (-$border-active-width) 0 0 $app-color;\n        z-index: map.get($zindex, button-active);\n      }\n    }\n\n    /**\n     * button-style: single\n     */\n    &.base-button--single {\n      min-height: $row-height-small;\n\n      &.base-button--background {\n        background-color: $button-header-color;\n      }\n\n      .base-button__icon--large {\n        height: $icon-medium;\n        width: $icon-medium;\n        max-width: $icon-medium;\n      }\n\n      .base-button__icon--small {\n        height: $icon-small;\n        width: $icon-small;\n        max-width: $icon-small;\n      }\n\n      &.base-button--active .base-button__icon {\n        color: $app-color;\n      }\n    }\n\n    /**\n     * button-style: secondary\n     */\n    &.base-button--secondary {\n      font-size: $font-size-small;\n      color: $font-color-second;\n\n      &.base-button--background {\n        background-color: $button-header-color;\n      }\n\n      &:disabled {\n        color: $font-color-third;\n\n        &:hover, &:focus, &:active, &:active .base-button__icon, &:focus .base-button__icon {\n          color: $font-color-third;\n        }\n      }\n    }\n\n    .base-button__icon--hide {\n      visibility: hidden;\n    }\n\n    /**\n     * button-style: circle\n     */\n    &.base-button--circle {\n      background-color: #ffffff;\n      border-radius: 50%;\n      color: $font-color-second;\n      border: 1px solid $font-color-second;\n      padding: 0;\n      width: 24px;\n      // to prevent shrinking e.g. if parent is flex container\n      min-width: 24px;\n      height: 24px;\n\n      &:hover {\n        color: $app-color;\n        border-color: $app-color;\n      }\n\n      &:focus {\n        color: $app-color;\n      }\n    }\n\n    /**\n     * modifiers\n     */\n    &.base-button--active {\n      /* TODO: adjust this to style guide if necessary */\n      box-shadow: $box-shadow-reg, inset 0 (-$border-active-width) 0 0 $app-color;\n      z-index: map.get($zindex, button-active);\n    }\n\n    &.base-button--align-left:not(&.base-button--icon-top) {\n      justify-content: flex-start;\n    }\n\n    &.base-button--align-center {\n      justify-content: center;\n    }\n\n    &.base-button--align-right:not(&.base-button--icon-top)  {\n      justify-content: flex-end;\n    }\n\n    &.base-button--icon-top {\n      flex-direction: column;\n      justify-content: center;\n      line-height: $line-height;\n\n      .base-button__icon--margin {\n        margin-top: $spacing-small-half;\n      }\n    }\n\n    &.base-button--icon-left {\n      .base-button__icon--margin {\n        margin-right: $spacing;\n      }\n    }\n\n    &.base-button--icon-right {\n      .base-button__icon {\n        order: 1;\n\n        // this class is used in BaseAdvancedSearchRow\n        &.base-button__icon--margin {\n          margin-left: $spacing;\n        }\n      }\n    }\n\n    /* class is set in following components: baseExpandBox and BaseAdvancedSearch */\n    &.base-button--rotate-icon-180 {\n      .base-button__icon {\n        transform: rotate(180deg);\n      }\n    }\n\n    &:hover {\n      color: $app-color;\n    }\n\n    &:active .base-button__icon, &:focus .base-button__icon {\n      color: $app-color;\n    }\n\n    &:disabled {\n      cursor: default;\n      color: $graytext-color;\n\n      &:hover, &:focus, &:active, &:active .base-button__icon, &:focus .base-button__icon {\n        color: $graytext-color;\n      }\n    }\n  }\n</style>\n","import { shallowRef, watchEffect, readonly, watch, customRef, getCurrentScope, onScopeDispose, effectScope, getCurrentInstance, hasInjectionContext, inject, provide, ref, isRef, unref, toValue as toValue$1, computed, reactive, toRefs as toRefs$1, toRef as toRef$1, shallowReadonly, onBeforeMount, nextTick, onBeforeUnmount, onMounted, onUnmounted, isReactive } from 'vue';\n\nfunction computedEager(fn, options) {\n  var _a;\n  const result = shallowRef();\n  watchEffect(() => {\n    result.value = fn();\n  }, {\n    ...options,\n    flush: (_a = options == null ? void 0 : options.flush) != null ? _a : \"sync\"\n  });\n  return readonly(result);\n}\n\nfunction computedWithControl(source, fn, options = {}) {\n  let v = void 0;\n  let track;\n  let trigger;\n  let dirty = true;\n  const update = () => {\n    dirty = true;\n    trigger();\n  };\n  watch(source, update, { flush: \"sync\", ...options });\n  const get = typeof fn === \"function\" ? fn : fn.get;\n  const set = typeof fn === \"function\" ? void 0 : fn.set;\n  const result = customRef((_track, _trigger) => {\n    track = _track;\n    trigger = _trigger;\n    return {\n      get() {\n        if (dirty) {\n          v = get(v);\n          dirty = false;\n        }\n        track();\n        return v;\n      },\n      set(v2) {\n        set == null ? void 0 : set(v2);\n      }\n    };\n  });\n  result.trigger = update;\n  return result;\n}\n\nfunction tryOnScopeDispose(fn) {\n  if (getCurrentScope()) {\n    onScopeDispose(fn);\n    return true;\n  }\n  return false;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction createEventHook() {\n  const fns = /* @__PURE__ */ new Set();\n  const off = (fn) => {\n    fns.delete(fn);\n  };\n  const clear = () => {\n    fns.clear();\n  };\n  const on = (fn) => {\n    fns.add(fn);\n    const offFn = () => off(fn);\n    tryOnScopeDispose(offFn);\n    return {\n      off: offFn\n    };\n  };\n  const trigger = (...args) => {\n    return Promise.all(Array.from(fns).map((fn) => fn(...args)));\n  };\n  return {\n    on,\n    off,\n    trigger,\n    clear\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction createGlobalState(stateFactory) {\n  let initialized = false;\n  let state;\n  const scope = effectScope(true);\n  return (...args) => {\n    if (!initialized) {\n      state = scope.run(() => stateFactory(...args));\n      initialized = true;\n    }\n    return state;\n  };\n}\n\nconst localProvidedStateMap = /* @__PURE__ */ new WeakMap();\n\nconst injectLocal = /* @__NO_SIDE_EFFECTS__ */ (...args) => {\n  var _a;\n  const key = args[0];\n  const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy;\n  if (instance == null && !hasInjectionContext())\n    throw new Error(\"injectLocal must be called in setup\");\n  if (instance && localProvidedStateMap.has(instance) && key in localProvidedStateMap.get(instance))\n    return localProvidedStateMap.get(instance)[key];\n  return inject(...args);\n};\n\nfunction provideLocal(key, value) {\n  var _a;\n  const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy;\n  if (instance == null)\n    throw new Error(\"provideLocal must be called in setup\");\n  if (!localProvidedStateMap.has(instance))\n    localProvidedStateMap.set(instance, /* @__PURE__ */ Object.create(null));\n  const localProvidedState = localProvidedStateMap.get(instance);\n  localProvidedState[key] = value;\n  return provide(key, value);\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction createInjectionState(composable, options) {\n  const key = (options == null ? void 0 : options.injectionKey) || Symbol(composable.name || \"InjectionState\");\n  const defaultValue = options == null ? void 0 : options.defaultValue;\n  const useProvidingState = (...args) => {\n    const state = composable(...args);\n    provideLocal(key, state);\n    return state;\n  };\n  const useInjectedState = () => injectLocal(key, defaultValue);\n  return [useProvidingState, useInjectedState];\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction createRef(value, deep) {\n  if (deep === true) {\n    return ref(value);\n  } else {\n    return shallowRef(value);\n  }\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction createSharedComposable(composable) {\n  let subscribers = 0;\n  let state;\n  let scope;\n  const dispose = () => {\n    subscribers -= 1;\n    if (scope && subscribers <= 0) {\n      scope.stop();\n      state = void 0;\n      scope = void 0;\n    }\n  };\n  return (...args) => {\n    subscribers += 1;\n    if (!scope) {\n      scope = effectScope(true);\n      state = scope.run(() => composable(...args));\n    }\n    tryOnScopeDispose(dispose);\n    return state;\n  };\n}\n\nfunction extendRef(ref, extend, { enumerable = false, unwrap = true } = {}) {\n  for (const [key, value] of Object.entries(extend)) {\n    if (key === \"value\")\n      continue;\n    if (isRef(value) && unwrap) {\n      Object.defineProperty(ref, key, {\n        get() {\n          return value.value;\n        },\n        set(v) {\n          value.value = v;\n        },\n        enumerable\n      });\n    } else {\n      Object.defineProperty(ref, key, { value, enumerable });\n    }\n  }\n  return ref;\n}\n\nfunction get(obj, key) {\n  if (key == null)\n    return unref(obj);\n  return unref(obj)[key];\n}\n\nfunction isDefined(v) {\n  return unref(v) != null;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction makeDestructurable(obj, arr) {\n  if (typeof Symbol !== \"undefined\") {\n    const clone = { ...obj };\n    Object.defineProperty(clone, Symbol.iterator, {\n      enumerable: false,\n      value() {\n        let index = 0;\n        return {\n          next: () => ({\n            value: arr[index++],\n            done: index > arr.length\n          })\n        };\n      }\n    });\n    return clone;\n  } else {\n    return Object.assign([...arr], obj);\n  }\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction reactify(fn, options) {\n  const unrefFn = (options == null ? void 0 : options.computedGetter) === false ? unref : toValue$1;\n  return function(...args) {\n    return computed(() => fn.apply(this, args.map((i) => unrefFn(i))));\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction reactifyObject(obj, optionsOrKeys = {}) {\n  let keys = [];\n  let options;\n  if (Array.isArray(optionsOrKeys)) {\n    keys = optionsOrKeys;\n  } else {\n    options = optionsOrKeys;\n    const { includeOwnProperties = true } = optionsOrKeys;\n    keys.push(...Object.keys(obj));\n    if (includeOwnProperties)\n      keys.push(...Object.getOwnPropertyNames(obj));\n  }\n  return Object.fromEntries(\n    keys.map((key) => {\n      const value = obj[key];\n      return [\n        key,\n        typeof value === \"function\" ? reactify(value.bind(obj), options) : value\n      ];\n    })\n  );\n}\n\nfunction toReactive(objectRef) {\n  if (!isRef(objectRef))\n    return reactive(objectRef);\n  const proxy = new Proxy({}, {\n    get(_, p, receiver) {\n      return unref(Reflect.get(objectRef.value, p, receiver));\n    },\n    set(_, p, value) {\n      if (isRef(objectRef.value[p]) && !isRef(value))\n        objectRef.value[p].value = value;\n      else\n        objectRef.value[p] = value;\n      return true;\n    },\n    deleteProperty(_, p) {\n      return Reflect.deleteProperty(objectRef.value, p);\n    },\n    has(_, p) {\n      return Reflect.has(objectRef.value, p);\n    },\n    ownKeys() {\n      return Object.keys(objectRef.value);\n    },\n    getOwnPropertyDescriptor() {\n      return {\n        enumerable: true,\n        configurable: true\n      };\n    }\n  });\n  return reactive(proxy);\n}\n\nfunction reactiveComputed(fn) {\n  return toReactive(computed(fn));\n}\n\nfunction reactiveOmit(obj, ...keys) {\n  const flatKeys = keys.flat();\n  const predicate = flatKeys[0];\n  return reactiveComputed(() => typeof predicate === \"function\" ? Object.fromEntries(Object.entries(toRefs$1(obj)).filter(([k, v]) => !predicate(toValue$1(v), k))) : Object.fromEntries(Object.entries(toRefs$1(obj)).filter((e) => !flatKeys.includes(e[0]))));\n}\n\nconst isClient = typeof window !== \"undefined\" && typeof document !== \"undefined\";\nconst isWorker = typeof WorkerGlobalScope !== \"undefined\" && globalThis instanceof WorkerGlobalScope;\nconst isDef = (val) => typeof val !== \"undefined\";\nconst notNullish = (val) => val != null;\nconst assert = (condition, ...infos) => {\n  if (!condition)\n    console.warn(...infos);\n};\nconst toString = Object.prototype.toString;\nconst isObject = (val) => toString.call(val) === \"[object Object]\";\nconst now = () => Date.now();\nconst timestamp = () => +Date.now();\nconst clamp = (n, min, max) => Math.min(max, Math.max(min, n));\nconst noop = () => {\n};\nconst rand = (min, max) => {\n  min = Math.ceil(min);\n  max = Math.floor(max);\n  return Math.floor(Math.random() * (max - min + 1)) + min;\n};\nconst hasOwn = (val, key) => Object.prototype.hasOwnProperty.call(val, key);\nconst isIOS = /* @__PURE__ */ getIsIOS();\nfunction getIsIOS() {\n  var _a, _b;\n  return isClient && ((_a = window == null ? void 0 : window.navigator) == null ? void 0 : _a.userAgent) && (/iP(?:ad|hone|od)/.test(window.navigator.userAgent) || ((_b = window == null ? void 0 : window.navigator) == null ? void 0 : _b.maxTouchPoints) > 2 && /iPad|Macintosh/.test(window == null ? void 0 : window.navigator.userAgent));\n}\n\nfunction toRef(...args) {\n  if (args.length !== 1)\n    return toRef$1(...args);\n  const r = args[0];\n  return typeof r === \"function\" ? readonly(customRef(() => ({ get: r, set: noop }))) : ref(r);\n}\nconst resolveRef = toRef;\n\nfunction reactivePick(obj, ...keys) {\n  const flatKeys = keys.flat();\n  const predicate = flatKeys[0];\n  return reactiveComputed(() => typeof predicate === \"function\" ? Object.fromEntries(Object.entries(toRefs$1(obj)).filter(([k, v]) => predicate(toValue$1(v), k))) : Object.fromEntries(flatKeys.map((k) => [k, toRef(obj, k)])));\n}\n\nfunction refAutoReset(defaultValue, afterMs = 1e4) {\n  return customRef((track, trigger) => {\n    let value = toValue$1(defaultValue);\n    let timer;\n    const resetAfter = () => setTimeout(() => {\n      value = toValue$1(defaultValue);\n      trigger();\n    }, toValue$1(afterMs));\n    tryOnScopeDispose(() => {\n      clearTimeout(timer);\n    });\n    return {\n      get() {\n        track();\n        return value;\n      },\n      set(newValue) {\n        value = newValue;\n        trigger();\n        clearTimeout(timer);\n        timer = resetAfter();\n      }\n    };\n  });\n}\n\nfunction createFilterWrapper(filter, fn) {\n  function wrapper(...args) {\n    return new Promise((resolve, reject) => {\n      Promise.resolve(filter(() => fn.apply(this, args), { fn, thisArg: this, args })).then(resolve).catch(reject);\n    });\n  }\n  return wrapper;\n}\nconst bypassFilter = (invoke) => {\n  return invoke();\n};\nfunction debounceFilter(ms, options = {}) {\n  let timer;\n  let maxTimer;\n  let lastRejector = noop;\n  const _clearTimeout = (timer2) => {\n    clearTimeout(timer2);\n    lastRejector();\n    lastRejector = noop;\n  };\n  let lastInvoker;\n  const filter = (invoke) => {\n    const duration = toValue$1(ms);\n    const maxDuration = toValue$1(options.maxWait);\n    if (timer)\n      _clearTimeout(timer);\n    if (duration <= 0 || maxDuration !== void 0 && maxDuration <= 0) {\n      if (maxTimer) {\n        _clearTimeout(maxTimer);\n        maxTimer = void 0;\n      }\n      return Promise.resolve(invoke());\n    }\n    return new Promise((resolve, reject) => {\n      lastRejector = options.rejectOnCancel ? reject : resolve;\n      lastInvoker = invoke;\n      if (maxDuration && !maxTimer) {\n        maxTimer = setTimeout(() => {\n          if (timer)\n            _clearTimeout(timer);\n          maxTimer = void 0;\n          resolve(lastInvoker());\n        }, maxDuration);\n      }\n      timer = setTimeout(() => {\n        if (maxTimer)\n          _clearTimeout(maxTimer);\n        maxTimer = void 0;\n        resolve(invoke());\n      }, duration);\n    });\n  };\n  return filter;\n}\nfunction throttleFilter(...args) {\n  let lastExec = 0;\n  let timer;\n  let isLeading = true;\n  let lastRejector = noop;\n  let lastValue;\n  let ms;\n  let trailing;\n  let leading;\n  let rejectOnCancel;\n  if (!isRef(args[0]) && typeof args[0] === \"object\")\n    ({ delay: ms, trailing = true, leading = true, rejectOnCancel = false } = args[0]);\n  else\n    [ms, trailing = true, leading = true, rejectOnCancel = false] = args;\n  const clear = () => {\n    if (timer) {\n      clearTimeout(timer);\n      timer = void 0;\n      lastRejector();\n      lastRejector = noop;\n    }\n  };\n  const filter = (_invoke) => {\n    const duration = toValue$1(ms);\n    const elapsed = Date.now() - lastExec;\n    const invoke = () => {\n      return lastValue = _invoke();\n    };\n    clear();\n    if (duration <= 0) {\n      lastExec = Date.now();\n      return invoke();\n    }\n    if (elapsed > duration && (leading || !isLeading)) {\n      lastExec = Date.now();\n      invoke();\n    } else if (trailing) {\n      lastValue = new Promise((resolve, reject) => {\n        lastRejector = rejectOnCancel ? reject : resolve;\n        timer = setTimeout(() => {\n          lastExec = Date.now();\n          isLeading = true;\n          resolve(invoke());\n          clear();\n        }, Math.max(0, duration - elapsed));\n      });\n    }\n    if (!leading && !timer)\n      timer = setTimeout(() => isLeading = true, duration);\n    isLeading = false;\n    return lastValue;\n  };\n  return filter;\n}\nfunction pausableFilter(extendFilter = bypassFilter, options = {}) {\n  const {\n    initialState = \"active\"\n  } = options;\n  const isActive = toRef(initialState === \"active\");\n  function pause() {\n    isActive.value = false;\n  }\n  function resume() {\n    isActive.value = true;\n  }\n  const eventFilter = (...args) => {\n    if (isActive.value)\n      extendFilter(...args);\n  };\n  return { isActive: readonly(isActive), pause, resume, eventFilter };\n}\n\nfunction promiseTimeout(ms, throwOnTimeout = false, reason = \"Timeout\") {\n  return new Promise((resolve, reject) => {\n    if (throwOnTimeout)\n      setTimeout(() => reject(reason), ms);\n    else\n      setTimeout(resolve, ms);\n  });\n}\nfunction identity(arg) {\n  return arg;\n}\nfunction createSingletonPromise(fn) {\n  let _promise;\n  function wrapper() {\n    if (!_promise)\n      _promise = fn();\n    return _promise;\n  }\n  wrapper.reset = async () => {\n    const _prev = _promise;\n    _promise = void 0;\n    if (_prev)\n      await _prev;\n  };\n  return wrapper;\n}\nfunction invoke(fn) {\n  return fn();\n}\nfunction containsProp(obj, ...props) {\n  return props.some((k) => k in obj);\n}\nfunction increaseWithUnit(target, delta) {\n  var _a;\n  if (typeof target === \"number\")\n    return target + delta;\n  const value = ((_a = target.match(/^-?\\d+\\.?\\d*/)) == null ? void 0 : _a[0]) || \"\";\n  const unit = target.slice(value.length);\n  const result = Number.parseFloat(value) + delta;\n  if (Number.isNaN(result))\n    return target;\n  return result + unit;\n}\nfunction pxValue(px) {\n  return px.endsWith(\"rem\") ? Number.parseFloat(px) * 16 : Number.parseFloat(px);\n}\nfunction objectPick(obj, keys, omitUndefined = false) {\n  return keys.reduce((n, k) => {\n    if (k in obj) {\n      if (!omitUndefined || obj[k] !== void 0)\n        n[k] = obj[k];\n    }\n    return n;\n  }, {});\n}\nfunction objectOmit(obj, keys, omitUndefined = false) {\n  return Object.fromEntries(Object.entries(obj).filter(([key, value]) => {\n    return (!omitUndefined || value !== void 0) && !keys.includes(key);\n  }));\n}\nfunction objectEntries(obj) {\n  return Object.entries(obj);\n}\nfunction toArray(value) {\n  return Array.isArray(value) ? value : [value];\n}\n\nfunction cacheStringFunction(fn) {\n  const cache = /* @__PURE__ */ Object.create(null);\n  return (str) => {\n    const hit = cache[str];\n    return hit || (cache[str] = fn(str));\n  };\n}\nconst hyphenateRE = /\\B([A-Z])/g;\nconst hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, \"-$1\").toLowerCase());\nconst camelizeRE = /-(\\w)/g;\nconst camelize = cacheStringFunction((str) => {\n  return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : \"\");\n});\n\nfunction getLifeCycleTarget(target) {\n  return target || getCurrentInstance();\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useDebounceFn(fn, ms = 200, options = {}) {\n  return createFilterWrapper(\n    debounceFilter(ms, options),\n    fn\n  );\n}\n\nfunction refDebounced(value, ms = 200, options = {}) {\n  const debounced = ref(toValue$1(value));\n  const updater = useDebounceFn(() => {\n    debounced.value = value.value;\n  }, ms, options);\n  watch(value, () => updater());\n  return shallowReadonly(debounced);\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction refDefault(source, defaultValue) {\n  return computed({\n    get() {\n      var _a;\n      return (_a = source.value) != null ? _a : defaultValue;\n    },\n    set(value) {\n      source.value = value;\n    }\n  });\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useThrottleFn(fn, ms = 200, trailing = false, leading = true, rejectOnCancel = false) {\n  return createFilterWrapper(\n    throttleFilter(ms, trailing, leading, rejectOnCancel),\n    fn\n  );\n}\n\nfunction refThrottled(value, delay = 200, trailing = true, leading = true) {\n  if (delay <= 0)\n    return value;\n  const throttled = ref(toValue$1(value));\n  const updater = useThrottleFn(() => {\n    throttled.value = value.value;\n  }, delay, trailing, leading);\n  watch(value, () => updater());\n  return throttled;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction refWithControl(initial, options = {}) {\n  let source = initial;\n  let track;\n  let trigger;\n  const ref = customRef((_track, _trigger) => {\n    track = _track;\n    trigger = _trigger;\n    return {\n      get() {\n        return get();\n      },\n      set(v) {\n        set(v);\n      }\n    };\n  });\n  function get(tracking = true) {\n    if (tracking)\n      track();\n    return source;\n  }\n  function set(value, triggering = true) {\n    var _a, _b;\n    if (value === source)\n      return;\n    const old = source;\n    if (((_a = options.onBeforeChange) == null ? void 0 : _a.call(options, value, old)) === false)\n      return;\n    source = value;\n    (_b = options.onChanged) == null ? void 0 : _b.call(options, value, old);\n    if (triggering)\n      trigger();\n  }\n  const untrackedGet = () => get(false);\n  const silentSet = (v) => set(v, false);\n  const peek = () => get(false);\n  const lay = (v) => set(v, false);\n  return extendRef(\n    ref,\n    {\n      get,\n      set,\n      untrackedGet,\n      silentSet,\n      peek,\n      lay\n    },\n    { enumerable: true }\n  );\n}\nconst controlledRef = refWithControl;\n\nfunction set(...args) {\n  if (args.length === 2) {\n    const [ref, value] = args;\n    ref.value = value;\n  }\n  if (args.length === 3) {\n    const [target, key, value] = args;\n    target[key] = value;\n  }\n}\n\nfunction watchWithFilter(source, cb, options = {}) {\n  const {\n    eventFilter = bypassFilter,\n    ...watchOptions\n  } = options;\n  return watch(\n    source,\n    createFilterWrapper(\n      eventFilter,\n      cb\n    ),\n    watchOptions\n  );\n}\n\nfunction watchPausable(source, cb, options = {}) {\n  const {\n    eventFilter: filter,\n    initialState = \"active\",\n    ...watchOptions\n  } = options;\n  const { eventFilter, pause, resume, isActive } = pausableFilter(filter, { initialState });\n  const stop = watchWithFilter(\n    source,\n    cb,\n    {\n      ...watchOptions,\n      eventFilter\n    }\n  );\n  return { stop, pause, resume, isActive };\n}\n\nfunction syncRef(left, right, ...[options]) {\n  const {\n    flush = \"sync\",\n    deep = false,\n    immediate = true,\n    direction = \"both\",\n    transform = {}\n  } = options || {};\n  const watchers = [];\n  const transformLTR = \"ltr\" in transform && transform.ltr || ((v) => v);\n  const transformRTL = \"rtl\" in transform && transform.rtl || ((v) => v);\n  if (direction === \"both\" || direction === \"ltr\") {\n    watchers.push(watchPausable(\n      left,\n      (newValue) => {\n        watchers.forEach((w) => w.pause());\n        right.value = transformLTR(newValue);\n        watchers.forEach((w) => w.resume());\n      },\n      { flush, deep, immediate }\n    ));\n  }\n  if (direction === \"both\" || direction === \"rtl\") {\n    watchers.push(watchPausable(\n      right,\n      (newValue) => {\n        watchers.forEach((w) => w.pause());\n        left.value = transformRTL(newValue);\n        watchers.forEach((w) => w.resume());\n      },\n      { flush, deep, immediate }\n    ));\n  }\n  const stop = () => {\n    watchers.forEach((w) => w.stop());\n  };\n  return stop;\n}\n\nfunction syncRefs(source, targets, options = {}) {\n  const {\n    flush = \"sync\",\n    deep = false,\n    immediate = true\n  } = options;\n  const targetsArray = toArray(targets);\n  return watch(\n    source,\n    (newValue) => targetsArray.forEach((target) => target.value = newValue),\n    { flush, deep, immediate }\n  );\n}\n\nfunction toRefs(objectRef, options = {}) {\n  if (!isRef(objectRef))\n    return toRefs$1(objectRef);\n  const result = Array.isArray(objectRef.value) ? Array.from({ length: objectRef.value.length }) : {};\n  for (const key in objectRef.value) {\n    result[key] = customRef(() => ({\n      get() {\n        return objectRef.value[key];\n      },\n      set(v) {\n        var _a;\n        const replaceRef = (_a = toValue$1(options.replaceRef)) != null ? _a : true;\n        if (replaceRef) {\n          if (Array.isArray(objectRef.value)) {\n            const copy = [...objectRef.value];\n            copy[key] = v;\n            objectRef.value = copy;\n          } else {\n            const newObject = { ...objectRef.value, [key]: v };\n            Object.setPrototypeOf(newObject, Object.getPrototypeOf(objectRef.value));\n            objectRef.value = newObject;\n          }\n        } else {\n          objectRef.value[key] = v;\n        }\n      }\n    }));\n  }\n  return result;\n}\n\nconst toValue = toValue$1;\nconst resolveUnref = toValue$1;\n\nfunction tryOnBeforeMount(fn, sync = true, target) {\n  const instance = getLifeCycleTarget(target);\n  if (instance)\n    onBeforeMount(fn, target);\n  else if (sync)\n    fn();\n  else\n    nextTick(fn);\n}\n\nfunction tryOnBeforeUnmount(fn, target) {\n  const instance = getLifeCycleTarget(target);\n  if (instance)\n    onBeforeUnmount(fn, target);\n}\n\nfunction tryOnMounted(fn, sync = true, target) {\n  const instance = getLifeCycleTarget(target);\n  if (instance)\n    onMounted(fn, target);\n  else if (sync)\n    fn();\n  else\n    nextTick(fn);\n}\n\nfunction tryOnUnmounted(fn, target) {\n  const instance = getLifeCycleTarget(target);\n  if (instance)\n    onUnmounted(fn, target);\n}\n\nfunction createUntil(r, isNot = false) {\n  function toMatch(condition, { flush = \"sync\", deep = false, timeout, throwOnTimeout } = {}) {\n    let stop = null;\n    const watcher = new Promise((resolve) => {\n      stop = watch(\n        r,\n        (v) => {\n          if (condition(v) !== isNot) {\n            if (stop)\n              stop();\n            else\n              nextTick(() => stop == null ? void 0 : stop());\n            resolve(v);\n          }\n        },\n        {\n          flush,\n          deep,\n          immediate: true\n        }\n      );\n    });\n    const promises = [watcher];\n    if (timeout != null) {\n      promises.push(\n        promiseTimeout(timeout, throwOnTimeout).then(() => toValue$1(r)).finally(() => stop == null ? void 0 : stop())\n      );\n    }\n    return Promise.race(promises);\n  }\n  function toBe(value, options) {\n    if (!isRef(value))\n      return toMatch((v) => v === value, options);\n    const { flush = \"sync\", deep = false, timeout, throwOnTimeout } = options != null ? options : {};\n    let stop = null;\n    const watcher = new Promise((resolve) => {\n      stop = watch(\n        [r, value],\n        ([v1, v2]) => {\n          if (isNot !== (v1 === v2)) {\n            if (stop)\n              stop();\n            else\n              nextTick(() => stop == null ? void 0 : stop());\n            resolve(v1);\n          }\n        },\n        {\n          flush,\n          deep,\n          immediate: true\n        }\n      );\n    });\n    const promises = [watcher];\n    if (timeout != null) {\n      promises.push(\n        promiseTimeout(timeout, throwOnTimeout).then(() => toValue$1(r)).finally(() => {\n          stop == null ? void 0 : stop();\n          return toValue$1(r);\n        })\n      );\n    }\n    return Promise.race(promises);\n  }\n  function toBeTruthy(options) {\n    return toMatch((v) => Boolean(v), options);\n  }\n  function toBeNull(options) {\n    return toBe(null, options);\n  }\n  function toBeUndefined(options) {\n    return toBe(void 0, options);\n  }\n  function toBeNaN(options) {\n    return toMatch(Number.isNaN, options);\n  }\n  function toContains(value, options) {\n    return toMatch((v) => {\n      const array = Array.from(v);\n      return array.includes(value) || array.includes(toValue$1(value));\n    }, options);\n  }\n  function changed(options) {\n    return changedTimes(1, options);\n  }\n  function changedTimes(n = 1, options) {\n    let count = -1;\n    return toMatch(() => {\n      count += 1;\n      return count >= n;\n    }, options);\n  }\n  if (Array.isArray(toValue$1(r))) {\n    const instance = {\n      toMatch,\n      toContains,\n      changed,\n      changedTimes,\n      get not() {\n        return createUntil(r, !isNot);\n      }\n    };\n    return instance;\n  } else {\n    const instance = {\n      toMatch,\n      toBe,\n      toBeTruthy,\n      toBeNull,\n      toBeNaN,\n      toBeUndefined,\n      changed,\n      changedTimes,\n      get not() {\n        return createUntil(r, !isNot);\n      }\n    };\n    return instance;\n  }\n}\nfunction until(r) {\n  return createUntil(r);\n}\n\nfunction defaultComparator(value, othVal) {\n  return value === othVal;\n}\n// @__NO_SIDE_EFFECTS__\nfunction useArrayDifference(...args) {\n  var _a, _b;\n  const list = args[0];\n  const values = args[1];\n  let compareFn = (_a = args[2]) != null ? _a : defaultComparator;\n  const {\n    symmetric = false\n  } = (_b = args[3]) != null ? _b : {};\n  if (typeof compareFn === \"string\") {\n    const key = compareFn;\n    compareFn = (value, othVal) => value[key] === othVal[key];\n  }\n  const diff1 = computed(() => toValue$1(list).filter((x) => toValue$1(values).findIndex((y) => compareFn(x, y)) === -1));\n  if (symmetric) {\n    const diff2 = computed(() => toValue$1(values).filter((x) => toValue$1(list).findIndex((y) => compareFn(x, y)) === -1));\n    return computed(() => symmetric ? [...toValue$1(diff1), ...toValue$1(diff2)] : toValue$1(diff1));\n  } else {\n    return diff1;\n  }\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useArrayEvery(list, fn) {\n  return computed(() => toValue$1(list).every((element, index, array) => fn(toValue$1(element), index, array)));\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useArrayFilter(list, fn) {\n  return computed(() => toValue$1(list).map((i) => toValue$1(i)).filter(fn));\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useArrayFind(list, fn) {\n  return computed(() => toValue$1(\n    toValue$1(list).find((element, index, array) => fn(toValue$1(element), index, array))\n  ));\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useArrayFindIndex(list, fn) {\n  return computed(() => toValue$1(list).findIndex((element, index, array) => fn(toValue$1(element), index, array)));\n}\n\nfunction findLast(arr, cb) {\n  let index = arr.length;\n  while (index-- > 0) {\n    if (cb(arr[index], index, arr))\n      return arr[index];\n  }\n  return void 0;\n}\n// @__NO_SIDE_EFFECTS__\nfunction useArrayFindLast(list, fn) {\n  return computed(() => toValue$1(\n    !Array.prototype.findLast ? findLast(toValue$1(list), (element, index, array) => fn(toValue$1(element), index, array)) : toValue$1(list).findLast((element, index, array) => fn(toValue$1(element), index, array))\n  ));\n}\n\nfunction isArrayIncludesOptions(obj) {\n  return isObject(obj) && containsProp(obj, \"formIndex\", \"comparator\");\n}\n// @__NO_SIDE_EFFECTS__\nfunction useArrayIncludes(...args) {\n  var _a;\n  const list = args[0];\n  const value = args[1];\n  let comparator = args[2];\n  let formIndex = 0;\n  if (isArrayIncludesOptions(comparator)) {\n    formIndex = (_a = comparator.fromIndex) != null ? _a : 0;\n    comparator = comparator.comparator;\n  }\n  if (typeof comparator === \"string\") {\n    const key = comparator;\n    comparator = (element, value2) => element[key] === toValue$1(value2);\n  }\n  comparator = comparator != null ? comparator : (element, value2) => element === toValue$1(value2);\n  return computed(() => toValue$1(list).slice(formIndex).some((element, index, array) => comparator(\n    toValue$1(element),\n    toValue$1(value),\n    index,\n    toValue$1(array)\n  )));\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useArrayJoin(list, separator) {\n  return computed(() => toValue$1(list).map((i) => toValue$1(i)).join(toValue$1(separator)));\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useArrayMap(list, fn) {\n  return computed(() => toValue$1(list).map((i) => toValue$1(i)).map(fn));\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useArrayReduce(list, reducer, ...args) {\n  const reduceCallback = (sum, value, index) => reducer(toValue$1(sum), toValue$1(value), index);\n  return computed(() => {\n    const resolved = toValue$1(list);\n    return args.length ? resolved.reduce(reduceCallback, typeof args[0] === \"function\" ? toValue$1(args[0]()) : toValue$1(args[0])) : resolved.reduce(reduceCallback);\n  });\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useArraySome(list, fn) {\n  return computed(() => toValue$1(list).some((element, index, array) => fn(toValue$1(element), index, array)));\n}\n\nfunction uniq(array) {\n  return Array.from(new Set(array));\n}\nfunction uniqueElementsBy(array, fn) {\n  return array.reduce((acc, v) => {\n    if (!acc.some((x) => fn(v, x, array)))\n      acc.push(v);\n    return acc;\n  }, []);\n}\n// @__NO_SIDE_EFFECTS__\nfunction useArrayUnique(list, compareFn) {\n  return computed(() => {\n    const resolvedList = toValue$1(list).map((element) => toValue$1(element));\n    return compareFn ? uniqueElementsBy(resolvedList, compareFn) : uniq(resolvedList);\n  });\n}\n\nfunction useCounter(initialValue = 0, options = {}) {\n  let _initialValue = unref(initialValue);\n  const count = shallowRef(initialValue);\n  const {\n    max = Number.POSITIVE_INFINITY,\n    min = Number.NEGATIVE_INFINITY\n  } = options;\n  const inc = (delta = 1) => count.value = Math.max(Math.min(max, count.value + delta), min);\n  const dec = (delta = 1) => count.value = Math.min(Math.max(min, count.value - delta), max);\n  const get = () => count.value;\n  const set = (val) => count.value = Math.max(min, Math.min(max, val));\n  const reset = (val = _initialValue) => {\n    _initialValue = val;\n    return set(val);\n  };\n  return { count: shallowReadonly(count), inc, dec, get, set, reset };\n}\n\nconst REGEX_PARSE = /^(\\d{4})[-/]?(\\d{1,2})?[-/]?(\\d{0,2})[T\\s]*(\\d{1,2})?:?(\\d{1,2})?:?(\\d{1,2})?[.:]?(\\d+)?$/i;\nconst REGEX_FORMAT = /[YMDHhms]o|\\[([^\\]]+)\\]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a{1,2}|A{1,2}|m{1,2}|s{1,2}|Z{1,2}|z{1,4}|SSS/g;\nfunction defaultMeridiem(hours, minutes, isLowercase, hasPeriod) {\n  let m = hours < 12 ? \"AM\" : \"PM\";\n  if (hasPeriod)\n    m = m.split(\"\").reduce((acc, curr) => acc += `${curr}.`, \"\");\n  return isLowercase ? m.toLowerCase() : m;\n}\nfunction formatOrdinal(num) {\n  const suffixes = [\"th\", \"st\", \"nd\", \"rd\"];\n  const v = num % 100;\n  return num + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]);\n}\nfunction formatDate(date, formatStr, options = {}) {\n  var _a;\n  const years = date.getFullYear();\n  const month = date.getMonth();\n  const days = date.getDate();\n  const hours = date.getHours();\n  const minutes = date.getMinutes();\n  const seconds = date.getSeconds();\n  const milliseconds = date.getMilliseconds();\n  const day = date.getDay();\n  const meridiem = (_a = options.customMeridiem) != null ? _a : defaultMeridiem;\n  const stripTimeZone = (dateString) => {\n    var _a2;\n    return (_a2 = dateString.split(\" \")[1]) != null ? _a2 : \"\";\n  };\n  const matches = {\n    Yo: () => formatOrdinal(years),\n    YY: () => String(years).slice(-2),\n    YYYY: () => years,\n    M: () => month + 1,\n    Mo: () => formatOrdinal(month + 1),\n    MM: () => `${month + 1}`.padStart(2, \"0\"),\n    MMM: () => date.toLocaleDateString(toValue$1(options.locales), { month: \"short\" }),\n    MMMM: () => date.toLocaleDateString(toValue$1(options.locales), { month: \"long\" }),\n    D: () => String(days),\n    Do: () => formatOrdinal(days),\n    DD: () => `${days}`.padStart(2, \"0\"),\n    H: () => String(hours),\n    Ho: () => formatOrdinal(hours),\n    HH: () => `${hours}`.padStart(2, \"0\"),\n    h: () => `${hours % 12 || 12}`.padStart(1, \"0\"),\n    ho: () => formatOrdinal(hours % 12 || 12),\n    hh: () => `${hours % 12 || 12}`.padStart(2, \"0\"),\n    m: () => String(minutes),\n    mo: () => formatOrdinal(minutes),\n    mm: () => `${minutes}`.padStart(2, \"0\"),\n    s: () => String(seconds),\n    so: () => formatOrdinal(seconds),\n    ss: () => `${seconds}`.padStart(2, \"0\"),\n    SSS: () => `${milliseconds}`.padStart(3, \"0\"),\n    d: () => day,\n    dd: () => date.toLocaleDateString(toValue$1(options.locales), { weekday: \"narrow\" }),\n    ddd: () => date.toLocaleDateString(toValue$1(options.locales), { weekday: \"short\" }),\n    dddd: () => date.toLocaleDateString(toValue$1(options.locales), { weekday: \"long\" }),\n    A: () => meridiem(hours, minutes),\n    AA: () => meridiem(hours, minutes, false, true),\n    a: () => meridiem(hours, minutes, true),\n    aa: () => meridiem(hours, minutes, true, true),\n    z: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: \"shortOffset\" })),\n    zz: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: \"shortOffset\" })),\n    zzz: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: \"shortOffset\" })),\n    zzzz: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: \"longOffset\" }))\n  };\n  return formatStr.replace(REGEX_FORMAT, (match, $1) => {\n    var _a2, _b;\n    return (_b = $1 != null ? $1 : (_a2 = matches[match]) == null ? void 0 : _a2.call(matches)) != null ? _b : match;\n  });\n}\nfunction normalizeDate(date) {\n  if (date === null)\n    return new Date(Number.NaN);\n  if (date === void 0)\n    return /* @__PURE__ */ new Date();\n  if (date instanceof Date)\n    return new Date(date);\n  if (typeof date === \"string\" && !/Z$/i.test(date)) {\n    const d = date.match(REGEX_PARSE);\n    if (d) {\n      const m = d[2] - 1 || 0;\n      const ms = (d[7] || \"0\").substring(0, 3);\n      return new Date(d[1], m, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms);\n    }\n  }\n  return new Date(date);\n}\n// @__NO_SIDE_EFFECTS__\nfunction useDateFormat(date, formatStr = \"HH:mm:ss\", options = {}) {\n  return computed(() => formatDate(normalizeDate(toValue$1(date)), toValue$1(formatStr), options));\n}\n\nfunction useIntervalFn(cb, interval = 1e3, options = {}) {\n  const {\n    immediate = true,\n    immediateCallback = false\n  } = options;\n  let timer = null;\n  const isActive = shallowRef(false);\n  function clean() {\n    if (timer) {\n      clearInterval(timer);\n      timer = null;\n    }\n  }\n  function pause() {\n    isActive.value = false;\n    clean();\n  }\n  function resume() {\n    const intervalValue = toValue$1(interval);\n    if (intervalValue <= 0)\n      return;\n    isActive.value = true;\n    if (immediateCallback)\n      cb();\n    clean();\n    if (isActive.value)\n      timer = setInterval(cb, intervalValue);\n  }\n  if (immediate && isClient)\n    resume();\n  if (isRef(interval) || typeof interval === \"function\") {\n    const stopWatch = watch(interval, () => {\n      if (isActive.value && isClient)\n        resume();\n    });\n    tryOnScopeDispose(stopWatch);\n  }\n  tryOnScopeDispose(pause);\n  return {\n    isActive: shallowReadonly(isActive),\n    pause,\n    resume\n  };\n}\n\nfunction useInterval(interval = 1e3, options = {}) {\n  const {\n    controls: exposeControls = false,\n    immediate = true,\n    callback\n  } = options;\n  const counter = shallowRef(0);\n  const update = () => counter.value += 1;\n  const reset = () => {\n    counter.value = 0;\n  };\n  const controls = useIntervalFn(\n    callback ? () => {\n      update();\n      callback(counter.value);\n    } : update,\n    interval,\n    { immediate }\n  );\n  if (exposeControls) {\n    return {\n      counter: shallowReadonly(counter),\n      reset,\n      ...controls\n    };\n  } else {\n    return shallowReadonly(counter);\n  }\n}\n\nfunction useLastChanged(source, options = {}) {\n  var _a;\n  const ms = shallowRef((_a = options.initialValue) != null ? _a : null);\n  watch(\n    source,\n    () => ms.value = timestamp(),\n    options\n  );\n  return shallowReadonly(ms);\n}\n\nfunction useTimeoutFn(cb, interval, options = {}) {\n  const {\n    immediate = true,\n    immediateCallback = false\n  } = options;\n  const isPending = shallowRef(false);\n  let timer;\n  function clear() {\n    if (timer) {\n      clearTimeout(timer);\n      timer = void 0;\n    }\n  }\n  function stop() {\n    isPending.value = false;\n    clear();\n  }\n  function start(...args) {\n    if (immediateCallback)\n      cb();\n    clear();\n    isPending.value = true;\n    timer = setTimeout(() => {\n      isPending.value = false;\n      timer = void 0;\n      cb(...args);\n    }, toValue$1(interval));\n  }\n  if (immediate) {\n    isPending.value = true;\n    if (isClient)\n      start();\n  }\n  tryOnScopeDispose(stop);\n  return {\n    isPending: shallowReadonly(isPending),\n    start,\n    stop\n  };\n}\n\nfunction useTimeout(interval = 1e3, options = {}) {\n  const {\n    controls: exposeControls = false,\n    callback\n  } = options;\n  const controls = useTimeoutFn(\n    callback != null ? callback : noop,\n    interval,\n    options\n  );\n  const ready = computed(() => !controls.isPending.value);\n  if (exposeControls) {\n    return {\n      ready,\n      ...controls\n    };\n  } else {\n    return ready;\n  }\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useToNumber(value, options = {}) {\n  const {\n    method = \"parseFloat\",\n    radix,\n    nanToZero\n  } = options;\n  return computed(() => {\n    let resolved = toValue$1(value);\n    if (typeof method === \"function\")\n      resolved = method(resolved);\n    else if (typeof resolved === \"string\")\n      resolved = Number[method](resolved, radix);\n    if (nanToZero && Number.isNaN(resolved))\n      resolved = 0;\n    return resolved;\n  });\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useToString(value) {\n  return computed(() => `${toValue$1(value)}`);\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useToggle(initialValue = false, options = {}) {\n  const {\n    truthyValue = true,\n    falsyValue = false\n  } = options;\n  const valueIsRef = isRef(initialValue);\n  const _value = shallowRef(initialValue);\n  function toggle(value) {\n    if (arguments.length) {\n      _value.value = value;\n      return _value.value;\n    } else {\n      const truthy = toValue$1(truthyValue);\n      _value.value = _value.value === truthy ? toValue$1(falsyValue) : truthy;\n      return _value.value;\n    }\n  }\n  if (valueIsRef)\n    return toggle;\n  else\n    return [_value, toggle];\n}\n\nfunction watchArray(source, cb, options) {\n  let oldList = (options == null ? void 0 : options.immediate) ? [] : [...typeof source === \"function\" ? source() : Array.isArray(source) ? source : toValue$1(source)];\n  return watch(source, (newList, _, onCleanup) => {\n    const oldListRemains = Array.from({ length: oldList.length });\n    const added = [];\n    for (const obj of newList) {\n      let found = false;\n      for (let i = 0; i < oldList.length; i++) {\n        if (!oldListRemains[i] && obj === oldList[i]) {\n          oldListRemains[i] = true;\n          found = true;\n          break;\n        }\n      }\n      if (!found)\n        added.push(obj);\n    }\n    const removed = oldList.filter((_2, i) => !oldListRemains[i]);\n    cb(newList, oldList, added, removed, onCleanup);\n    oldList = [...newList];\n  }, options);\n}\n\nfunction watchAtMost(source, cb, options) {\n  const {\n    count,\n    ...watchOptions\n  } = options;\n  const current = shallowRef(0);\n  const stop = watchWithFilter(\n    source,\n    (...args) => {\n      current.value += 1;\n      if (current.value >= toValue$1(count))\n        nextTick(() => stop());\n      cb(...args);\n    },\n    watchOptions\n  );\n  return { count: current, stop };\n}\n\nfunction watchDebounced(source, cb, options = {}) {\n  const {\n    debounce = 0,\n    maxWait = void 0,\n    ...watchOptions\n  } = options;\n  return watchWithFilter(\n    source,\n    cb,\n    {\n      ...watchOptions,\n      eventFilter: debounceFilter(debounce, { maxWait })\n    }\n  );\n}\n\nfunction watchDeep(source, cb, options) {\n  return watch(\n    source,\n    cb,\n    {\n      ...options,\n      deep: true\n    }\n  );\n}\n\nfunction watchIgnorable(source, cb, options = {}) {\n  const {\n    eventFilter = bypassFilter,\n    ...watchOptions\n  } = options;\n  const filteredCb = createFilterWrapper(\n    eventFilter,\n    cb\n  );\n  let ignoreUpdates;\n  let ignorePrevAsyncUpdates;\n  let stop;\n  if (watchOptions.flush === \"sync\") {\n    let ignore = false;\n    ignorePrevAsyncUpdates = () => {\n    };\n    ignoreUpdates = (updater) => {\n      ignore = true;\n      updater();\n      ignore = false;\n    };\n    stop = watch(\n      source,\n      (...args) => {\n        if (!ignore)\n          filteredCb(...args);\n      },\n      watchOptions\n    );\n  } else {\n    const disposables = [];\n    let ignoreCounter = 0;\n    let syncCounter = 0;\n    ignorePrevAsyncUpdates = () => {\n      ignoreCounter = syncCounter;\n    };\n    disposables.push(\n      watch(\n        source,\n        () => {\n          syncCounter++;\n        },\n        { ...watchOptions, flush: \"sync\" }\n      )\n    );\n    ignoreUpdates = (updater) => {\n      const syncCounterPrev = syncCounter;\n      updater();\n      ignoreCounter += syncCounter - syncCounterPrev;\n    };\n    disposables.push(\n      watch(\n        source,\n        (...args) => {\n          const ignore = ignoreCounter > 0 && ignoreCounter === syncCounter;\n          ignoreCounter = 0;\n          syncCounter = 0;\n          if (ignore)\n            return;\n          filteredCb(...args);\n        },\n        watchOptions\n      )\n    );\n    stop = () => {\n      disposables.forEach((fn) => fn());\n    };\n  }\n  return { stop, ignoreUpdates, ignorePrevAsyncUpdates };\n}\n\nfunction watchImmediate(source, cb, options) {\n  return watch(\n    source,\n    cb,\n    {\n      ...options,\n      immediate: true\n    }\n  );\n}\n\nfunction watchOnce(source, cb, options) {\n  return watch(\n    source,\n    cb,\n    {\n      ...options,\n      once: true\n    }\n  );\n}\n\nfunction watchThrottled(source, cb, options = {}) {\n  const {\n    throttle = 0,\n    trailing = true,\n    leading = true,\n    ...watchOptions\n  } = options;\n  return watchWithFilter(\n    source,\n    cb,\n    {\n      ...watchOptions,\n      eventFilter: throttleFilter(throttle, trailing, leading)\n    }\n  );\n}\n\nfunction watchTriggerable(source, cb, options = {}) {\n  let cleanupFn;\n  function onEffect() {\n    if (!cleanupFn)\n      return;\n    const fn = cleanupFn;\n    cleanupFn = void 0;\n    fn();\n  }\n  function onCleanup(callback) {\n    cleanupFn = callback;\n  }\n  const _cb = (value, oldValue) => {\n    onEffect();\n    return cb(value, oldValue, onCleanup);\n  };\n  const res = watchIgnorable(source, _cb, options);\n  const { ignoreUpdates } = res;\n  const trigger = () => {\n    let res2;\n    ignoreUpdates(() => {\n      res2 = _cb(getWatchSources(source), getOldValue(source));\n    });\n    return res2;\n  };\n  return {\n    ...res,\n    trigger\n  };\n}\nfunction getWatchSources(sources) {\n  if (isReactive(sources))\n    return sources;\n  if (Array.isArray(sources))\n    return sources.map((item) => toValue$1(item));\n  return toValue$1(sources);\n}\nfunction getOldValue(source) {\n  return Array.isArray(source) ? source.map(() => void 0) : void 0;\n}\n\nfunction whenever(source, cb, options) {\n  const stop = watch(\n    source,\n    (v, ov, onInvalidate) => {\n      if (v) {\n        if (options == null ? void 0 : options.once)\n          nextTick(() => stop());\n        cb(v, ov, onInvalidate);\n      }\n    },\n    {\n      ...options,\n      once: false\n    }\n  );\n  return stop;\n}\n\nexport { assert, refAutoReset as autoResetRef, bypassFilter, camelize, clamp, computedEager, computedWithControl, containsProp, computedWithControl as controlledComputed, controlledRef, createEventHook, createFilterWrapper, createGlobalState, createInjectionState, reactify as createReactiveFn, createRef, createSharedComposable, createSingletonPromise, debounceFilter, refDebounced as debouncedRef, watchDebounced as debouncedWatch, computedEager as eagerComputed, extendRef, formatDate, get, getLifeCycleTarget, hasOwn, hyphenate, identity, watchIgnorable as ignorableWatch, increaseWithUnit, injectLocal, invoke, isClient, isDef, isDefined, isIOS, isObject, isWorker, makeDestructurable, noop, normalizeDate, notNullish, now, objectEntries, objectOmit, objectPick, pausableFilter, watchPausable as pausableWatch, promiseTimeout, provideLocal, pxValue, rand, reactify, reactifyObject, reactiveComputed, reactiveOmit, reactivePick, refAutoReset, refDebounced, refDefault, refThrottled, refWithControl, resolveRef, resolveUnref, set, syncRef, syncRefs, throttleFilter, refThrottled as throttledRef, watchThrottled as throttledWatch, timestamp, toArray, toReactive, toRef, toRefs, toValue, tryOnBeforeMount, tryOnBeforeUnmount, tryOnMounted, tryOnScopeDispose, tryOnUnmounted, until, useArrayDifference, useArrayEvery, useArrayFilter, useArrayFind, useArrayFindIndex, useArrayFindLast, useArrayIncludes, useArrayJoin, useArrayMap, useArrayReduce, useArraySome, useArrayUnique, useCounter, useDateFormat, refDebounced as useDebounce, useDebounceFn, useInterval, useIntervalFn, useLastChanged, refThrottled as useThrottle, useThrottleFn, useTimeout, useTimeoutFn, useToNumber, useToString, useToggle, watchArray, watchAtMost, watchDebounced, watchDeep, watchIgnorable, watchImmediate, watchOnce, watchPausable, watchThrottled, watchTriggerable, watchWithFilter, whenever };\n","import { noop, makeDestructurable, camelize, isClient, toArray, watchImmediate, isObject, tryOnScopeDispose, isIOS, notNullish, tryOnMounted, objectOmit, promiseTimeout, until, injectLocal, provideLocal, pxValue, increaseWithUnit, objectEntries, createRef, createSingletonPromise, useTimeoutFn, pausableWatch, toRef, createEventHook, useIntervalFn, computedWithControl, timestamp, pausableFilter, watchIgnorable, debounceFilter, bypassFilter, createFilterWrapper, toRefs, watchOnce, containsProp, hasOwn, throttleFilter, useDebounceFn, useThrottleFn, tryOnUnmounted, clamp, syncRef, objectPick, watchWithFilter, identity, isDef, whenever, isWorker } from '@vueuse/shared';\nexport * from '@vueuse/shared';\nimport { isRef, shallowRef, ref, watchEffect, computed, inject, defineComponent, h, TransitionGroup, Fragment, shallowReactive, toValue, unref, getCurrentInstance, onMounted, watch, customRef, onUpdated, readonly, reactive, hasInjectionContext, toRaw, shallowReadonly, nextTick, markRaw, getCurrentScope, isReadonly, onBeforeUpdate } from 'vue';\n\nfunction computedAsync(evaluationCallback, initialState, optionsOrRef) {\n  var _a;\n  let options;\n  if (isRef(optionsOrRef)) {\n    options = {\n      evaluating: optionsOrRef\n    };\n  } else {\n    options = optionsOrRef || {};\n  }\n  const {\n    lazy = false,\n    flush = \"pre\",\n    evaluating = void 0,\n    shallow = true,\n    onError = (_a = globalThis.reportError) != null ? _a : noop\n  } = options;\n  const started = shallowRef(!lazy);\n  const current = shallow ? shallowRef(initialState) : ref(initialState);\n  let counter = 0;\n  watchEffect(async (onInvalidate) => {\n    if (!started.value)\n      return;\n    counter++;\n    const counterAtBeginning = counter;\n    let hasFinished = false;\n    if (evaluating) {\n      Promise.resolve().then(() => {\n        evaluating.value = true;\n      });\n    }\n    try {\n      const result = await evaluationCallback((cancelCallback) => {\n        onInvalidate(() => {\n          if (evaluating)\n            evaluating.value = false;\n          if (!hasFinished)\n            cancelCallback();\n        });\n      });\n      if (counterAtBeginning === counter)\n        current.value = result;\n    } catch (e) {\n      onError(e);\n    } finally {\n      if (evaluating && counterAtBeginning === counter)\n        evaluating.value = false;\n      hasFinished = true;\n    }\n  }, { flush });\n  if (lazy) {\n    return computed(() => {\n      started.value = true;\n      return current.value;\n    });\n  } else {\n    return current;\n  }\n}\n\nfunction computedInject(key, options, defaultSource, treatDefaultAsFactory) {\n  let source = inject(key);\n  if (defaultSource)\n    source = inject(key, defaultSource);\n  if (treatDefaultAsFactory)\n    source = inject(key, defaultSource, treatDefaultAsFactory);\n  if (typeof options === \"function\") {\n    return computed((oldValue) => options(source, oldValue));\n  } else {\n    return computed({\n      get: (oldValue) => options.get(source, oldValue),\n      set: options.set\n    });\n  }\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction createReusableTemplate(options = {}) {\n  const {\n    inheritAttrs = true\n  } = options;\n  const render = shallowRef();\n  const define = /*@__PURE__*/ defineComponent({\n    setup(_, { slots }) {\n      return () => {\n        render.value = slots.default;\n      };\n    }\n  });\n  const reuse = /*@__PURE__*/ defineComponent({\n    inheritAttrs,\n    props: options.props,\n    setup(props, { attrs, slots }) {\n      return () => {\n        var _a;\n        if (!render.value && process.env.NODE_ENV !== \"production\")\n          throw new Error(\"[VueUse] Failed to find the definition of reusable template\");\n        const vnode = (_a = render.value) == null ? void 0 : _a.call(render, {\n          ...options.props == null ? keysToCamelKebabCase(attrs) : props,\n          $slots: slots\n        });\n        return inheritAttrs && (vnode == null ? void 0 : vnode.length) === 1 ? vnode[0] : vnode;\n      };\n    }\n  });\n  return makeDestructurable(\n    { define, reuse },\n    [define, reuse]\n  );\n}\nfunction keysToCamelKebabCase(obj) {\n  const newObj = {};\n  for (const key in obj)\n    newObj[camelize(key)] = obj[key];\n  return newObj;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction createTemplatePromise(options = {}) {\n  let index = 0;\n  const instances = ref([]);\n  function create(...args) {\n    const props = shallowReactive({\n      key: index++,\n      args,\n      promise: void 0,\n      resolve: () => {\n      },\n      reject: () => {\n      },\n      isResolving: false,\n      options\n    });\n    instances.value.push(props);\n    props.promise = new Promise((_resolve, _reject) => {\n      props.resolve = (v) => {\n        props.isResolving = true;\n        return _resolve(v);\n      };\n      props.reject = _reject;\n    }).finally(() => {\n      props.promise = void 0;\n      const index2 = instances.value.indexOf(props);\n      if (index2 !== -1)\n        instances.value.splice(index2, 1);\n    });\n    return props.promise;\n  }\n  function start(...args) {\n    if (options.singleton && instances.value.length > 0)\n      return instances.value[0].promise;\n    return create(...args);\n  }\n  const component = /*@__PURE__*/ defineComponent((_, { slots }) => {\n    const renderList = () => instances.value.map((props) => {\n      var _a;\n      return h(Fragment, { key: props.key }, (_a = slots.default) == null ? void 0 : _a.call(slots, props));\n    });\n    if (options.transition)\n      return () => h(TransitionGroup, options.transition, renderList);\n    return renderList;\n  });\n  component.start = start;\n  return component;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction createUnrefFn(fn) {\n  return function(...args) {\n    return fn.apply(this, args.map((i) => toValue(i)));\n  };\n}\n\nconst defaultWindow = isClient ? window : void 0;\nconst defaultDocument = isClient ? window.document : void 0;\nconst defaultNavigator = isClient ? window.navigator : void 0;\nconst defaultLocation = isClient ? window.location : void 0;\n\nfunction unrefElement(elRef) {\n  var _a;\n  const plain = toValue(elRef);\n  return (_a = plain == null ? void 0 : plain.$el) != null ? _a : plain;\n}\n\nfunction useEventListener(...args) {\n  const cleanups = [];\n  const cleanup = () => {\n    cleanups.forEach((fn) => fn());\n    cleanups.length = 0;\n  };\n  const register = (el, event, listener, options) => {\n    el.addEventListener(event, listener, options);\n    return () => el.removeEventListener(event, listener, options);\n  };\n  const firstParamTargets = computed(() => {\n    const test = toArray(toValue(args[0])).filter((e) => e != null);\n    return test.every((e) => typeof e !== \"string\") ? test : void 0;\n  });\n  const stopWatch = watchImmediate(\n    () => {\n      var _a, _b;\n      return [\n        (_b = (_a = firstParamTargets.value) == null ? void 0 : _a.map((e) => unrefElement(e))) != null ? _b : [defaultWindow].filter((e) => e != null),\n        toArray(toValue(firstParamTargets.value ? args[1] : args[0])),\n        toArray(unref(firstParamTargets.value ? args[2] : args[1])),\n        // @ts-expect-error - TypeScript gets the correct types, but somehow still complains\n        toValue(firstParamTargets.value ? args[3] : args[2])\n      ];\n    },\n    ([raw_targets, raw_events, raw_listeners, raw_options]) => {\n      cleanup();\n      if (!(raw_targets == null ? void 0 : raw_targets.length) || !(raw_events == null ? void 0 : raw_events.length) || !(raw_listeners == null ? void 0 : raw_listeners.length))\n        return;\n      const optionsClone = isObject(raw_options) ? { ...raw_options } : raw_options;\n      cleanups.push(\n        ...raw_targets.flatMap(\n          (el) => raw_events.flatMap(\n            (event) => raw_listeners.map((listener) => register(el, event, listener, optionsClone))\n          )\n        )\n      );\n    },\n    { flush: \"post\" }\n  );\n  const stop = () => {\n    stopWatch();\n    cleanup();\n  };\n  tryOnScopeDispose(cleanup);\n  return stop;\n}\n\nlet _iOSWorkaround = false;\nfunction onClickOutside(target, handler, options = {}) {\n  const { window = defaultWindow, ignore = [], capture = true, detectIframe = false, controls = false } = options;\n  if (!window) {\n    return controls ? { stop: noop, cancel: noop, trigger: noop } : noop;\n  }\n  if (isIOS && !_iOSWorkaround) {\n    _iOSWorkaround = true;\n    const listenerOptions = { passive: true };\n    Array.from(window.document.body.children).forEach((el) => el.addEventListener(\"click\", noop, listenerOptions));\n    window.document.documentElement.addEventListener(\"click\", noop, listenerOptions);\n  }\n  let shouldListen = true;\n  const shouldIgnore = (event) => {\n    return toValue(ignore).some((target2) => {\n      if (typeof target2 === \"string\") {\n        return Array.from(window.document.querySelectorAll(target2)).some((el) => el === event.target || event.composedPath().includes(el));\n      } else {\n        const el = unrefElement(target2);\n        return el && (event.target === el || event.composedPath().includes(el));\n      }\n    });\n  };\n  function hasMultipleRoots(target2) {\n    const vm = toValue(target2);\n    return vm && vm.$.subTree.shapeFlag === 16;\n  }\n  function checkMultipleRoots(target2, event) {\n    const vm = toValue(target2);\n    const children = vm.$.subTree && vm.$.subTree.children;\n    if (children == null || !Array.isArray(children))\n      return false;\n    return children.some((child) => child.el === event.target || event.composedPath().includes(child.el));\n  }\n  const listener = (event) => {\n    const el = unrefElement(target);\n    if (event.target == null)\n      return;\n    if (!(el instanceof Element) && hasMultipleRoots(target) && checkMultipleRoots(target, event))\n      return;\n    if (!el || el === event.target || event.composedPath().includes(el))\n      return;\n    if (\"detail\" in event && event.detail === 0)\n      shouldListen = !shouldIgnore(event);\n    if (!shouldListen) {\n      shouldListen = true;\n      return;\n    }\n    handler(event);\n  };\n  let isProcessingClick = false;\n  const cleanup = [\n    useEventListener(window, \"click\", (event) => {\n      if (!isProcessingClick) {\n        isProcessingClick = true;\n        setTimeout(() => {\n          isProcessingClick = false;\n        }, 0);\n        listener(event);\n      }\n    }, { passive: true, capture }),\n    useEventListener(window, \"pointerdown\", (e) => {\n      const el = unrefElement(target);\n      shouldListen = !shouldIgnore(e) && !!(el && !e.composedPath().includes(el));\n    }, { passive: true }),\n    detectIframe && useEventListener(window, \"blur\", (event) => {\n      setTimeout(() => {\n        var _a;\n        const el = unrefElement(target);\n        if (((_a = window.document.activeElement) == null ? void 0 : _a.tagName) === \"IFRAME\" && !(el == null ? void 0 : el.contains(window.document.activeElement))) {\n          handler(event);\n        }\n      }, 0);\n    }, { passive: true })\n  ].filter(Boolean);\n  const stop = () => cleanup.forEach((fn) => fn());\n  if (controls) {\n    return {\n      stop,\n      cancel: () => {\n        shouldListen = false;\n      },\n      trigger: (event) => {\n        shouldListen = true;\n        listener(event);\n        shouldListen = false;\n      }\n    };\n  }\n  return stop;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useMounted() {\n  const isMounted = shallowRef(false);\n  const instance = getCurrentInstance();\n  if (instance) {\n    onMounted(() => {\n      isMounted.value = true;\n    }, instance);\n  }\n  return isMounted;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useSupported(callback) {\n  const isMounted = useMounted();\n  return computed(() => {\n    isMounted.value;\n    return Boolean(callback());\n  });\n}\n\nfunction useMutationObserver(target, callback, options = {}) {\n  const { window = defaultWindow, ...mutationOptions } = options;\n  let observer;\n  const isSupported = useSupported(() => window && \"MutationObserver\" in window);\n  const cleanup = () => {\n    if (observer) {\n      observer.disconnect();\n      observer = void 0;\n    }\n  };\n  const targets = computed(() => {\n    const value = toValue(target);\n    const items = toArray(value).map(unrefElement).filter(notNullish);\n    return new Set(items);\n  });\n  const stopWatch = watch(\n    targets,\n    (newTargets) => {\n      cleanup();\n      if (isSupported.value && newTargets.size) {\n        observer = new MutationObserver(callback);\n        newTargets.forEach((el) => observer.observe(el, mutationOptions));\n      }\n    },\n    { immediate: true, flush: \"post\" }\n  );\n  const takeRecords = () => {\n    return observer == null ? void 0 : observer.takeRecords();\n  };\n  const stop = () => {\n    stopWatch();\n    cleanup();\n  };\n  tryOnScopeDispose(stop);\n  return {\n    isSupported,\n    stop,\n    takeRecords\n  };\n}\n\nfunction onElementRemoval(target, callback, options = {}) {\n  const {\n    window = defaultWindow,\n    document = window == null ? void 0 : window.document,\n    flush = \"sync\"\n  } = options;\n  if (!window || !document)\n    return noop;\n  let stopFn;\n  const cleanupAndUpdate = (fn) => {\n    stopFn == null ? void 0 : stopFn();\n    stopFn = fn;\n  };\n  const stopWatch = watchEffect(() => {\n    const el = unrefElement(target);\n    if (el) {\n      const { stop } = useMutationObserver(\n        document,\n        (mutationsList) => {\n          const targetRemoved = mutationsList.map((mutation) => [...mutation.removedNodes]).flat().some((node) => node === el || node.contains(el));\n          if (targetRemoved) {\n            callback(mutationsList);\n          }\n        },\n        {\n          window,\n          childList: true,\n          subtree: true\n        }\n      );\n      cleanupAndUpdate(stop);\n    }\n  }, { flush });\n  const stopHandle = () => {\n    stopWatch();\n    cleanupAndUpdate();\n  };\n  tryOnScopeDispose(stopHandle);\n  return stopHandle;\n}\n\nfunction createKeyPredicate(keyFilter) {\n  if (typeof keyFilter === \"function\")\n    return keyFilter;\n  else if (typeof keyFilter === \"string\")\n    return (event) => event.key === keyFilter;\n  else if (Array.isArray(keyFilter))\n    return (event) => keyFilter.includes(event.key);\n  return () => true;\n}\nfunction onKeyStroke(...args) {\n  let key;\n  let handler;\n  let options = {};\n  if (args.length === 3) {\n    key = args[0];\n    handler = args[1];\n    options = args[2];\n  } else if (args.length === 2) {\n    if (typeof args[1] === \"object\") {\n      key = true;\n      handler = args[0];\n      options = args[1];\n    } else {\n      key = args[0];\n      handler = args[1];\n    }\n  } else {\n    key = true;\n    handler = args[0];\n  }\n  const {\n    target = defaultWindow,\n    eventName = \"keydown\",\n    passive = false,\n    dedupe = false\n  } = options;\n  const predicate = createKeyPredicate(key);\n  const listener = (e) => {\n    if (e.repeat && toValue(dedupe))\n      return;\n    if (predicate(e))\n      handler(e);\n  };\n  return useEventListener(target, eventName, listener, passive);\n}\nfunction onKeyDown(key, handler, options = {}) {\n  return onKeyStroke(key, handler, { ...options, eventName: \"keydown\" });\n}\nfunction onKeyPressed(key, handler, options = {}) {\n  return onKeyStroke(key, handler, { ...options, eventName: \"keypress\" });\n}\nfunction onKeyUp(key, handler, options = {}) {\n  return onKeyStroke(key, handler, { ...options, eventName: \"keyup\" });\n}\n\nconst DEFAULT_DELAY = 500;\nconst DEFAULT_THRESHOLD = 10;\nfunction onLongPress(target, handler, options) {\n  var _a, _b;\n  const elementRef = computed(() => unrefElement(target));\n  let timeout;\n  let posStart;\n  let startTimestamp;\n  let hasLongPressed = false;\n  function clear() {\n    if (timeout) {\n      clearTimeout(timeout);\n      timeout = void 0;\n    }\n    posStart = void 0;\n    startTimestamp = void 0;\n    hasLongPressed = false;\n  }\n  function getDelay(ev) {\n    const delay = options == null ? void 0 : options.delay;\n    if (typeof delay === \"function\") {\n      return delay(ev);\n    }\n    return delay != null ? delay : DEFAULT_DELAY;\n  }\n  function onRelease(ev) {\n    var _a2, _b2, _c;\n    const [_startTimestamp, _posStart, _hasLongPressed] = [startTimestamp, posStart, hasLongPressed];\n    clear();\n    if (!(options == null ? void 0 : options.onMouseUp) || !_posStart || !_startTimestamp)\n      return;\n    if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)\n      return;\n    if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)\n      ev.preventDefault();\n    if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)\n      ev.stopPropagation();\n    const dx = ev.x - _posStart.x;\n    const dy = ev.y - _posStart.y;\n    const distance = Math.sqrt(dx * dx + dy * dy);\n    options.onMouseUp(ev.timeStamp - _startTimestamp, distance, _hasLongPressed);\n  }\n  function onDown(ev) {\n    var _a2, _b2, _c;\n    if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)\n      return;\n    clear();\n    if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)\n      ev.preventDefault();\n    if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)\n      ev.stopPropagation();\n    posStart = {\n      x: ev.x,\n      y: ev.y\n    };\n    startTimestamp = ev.timeStamp;\n    timeout = setTimeout(\n      () => {\n        hasLongPressed = true;\n        handler(ev);\n      },\n      getDelay(ev)\n    );\n  }\n  function onMove(ev) {\n    var _a2, _b2, _c, _d;\n    if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)\n      return;\n    if (!posStart || (options == null ? void 0 : options.distanceThreshold) === false)\n      return;\n    if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)\n      ev.preventDefault();\n    if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)\n      ev.stopPropagation();\n    const dx = ev.x - posStart.x;\n    const dy = ev.y - posStart.y;\n    const distance = Math.sqrt(dx * dx + dy * dy);\n    if (distance >= ((_d = options == null ? void 0 : options.distanceThreshold) != null ? _d : DEFAULT_THRESHOLD))\n      clear();\n  }\n  const listenerOptions = {\n    capture: (_a = options == null ? void 0 : options.modifiers) == null ? void 0 : _a.capture,\n    once: (_b = options == null ? void 0 : options.modifiers) == null ? void 0 : _b.once\n  };\n  const cleanup = [\n    useEventListener(elementRef, \"pointerdown\", onDown, listenerOptions),\n    useEventListener(elementRef, \"pointermove\", onMove, listenerOptions),\n    useEventListener(elementRef, [\"pointerup\", \"pointerleave\"], onRelease, listenerOptions)\n  ];\n  const stop = () => cleanup.forEach((fn) => fn());\n  return stop;\n}\n\nfunction isFocusedElementEditable() {\n  const { activeElement, body } = document;\n  if (!activeElement)\n    return false;\n  if (activeElement === body)\n    return false;\n  switch (activeElement.tagName) {\n    case \"INPUT\":\n    case \"TEXTAREA\":\n      return true;\n  }\n  return activeElement.hasAttribute(\"contenteditable\");\n}\nfunction isTypedCharValid({\n  keyCode,\n  metaKey,\n  ctrlKey,\n  altKey\n}) {\n  if (metaKey || ctrlKey || altKey)\n    return false;\n  if (keyCode >= 48 && keyCode <= 57 || keyCode >= 96 && keyCode <= 105)\n    return true;\n  if (keyCode >= 65 && keyCode <= 90)\n    return true;\n  return false;\n}\nfunction onStartTyping(callback, options = {}) {\n  const { document: document2 = defaultDocument } = options;\n  const keydown = (event) => {\n    if (!isFocusedElementEditable() && isTypedCharValid(event)) {\n      callback(event);\n    }\n  };\n  if (document2)\n    useEventListener(document2, \"keydown\", keydown, { passive: true });\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction templateRef(key, initialValue = null) {\n  const instance = getCurrentInstance();\n  let _trigger = () => {\n  };\n  const element = customRef((track, trigger) => {\n    _trigger = trigger;\n    return {\n      get() {\n        var _a, _b;\n        track();\n        return (_b = (_a = instance == null ? void 0 : instance.proxy) == null ? void 0 : _a.$refs[key]) != null ? _b : initialValue;\n      },\n      set() {\n      }\n    };\n  });\n  tryOnMounted(_trigger);\n  onUpdated(_trigger);\n  return element;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useActiveElement(options = {}) {\n  var _a;\n  const {\n    window = defaultWindow,\n    deep = true,\n    triggerOnRemoval = false\n  } = options;\n  const document = (_a = options.document) != null ? _a : window == null ? void 0 : window.document;\n  const getDeepActiveElement = () => {\n    var _a2;\n    let element = document == null ? void 0 : document.activeElement;\n    if (deep) {\n      while (element == null ? void 0 : element.shadowRoot)\n        element = (_a2 = element == null ? void 0 : element.shadowRoot) == null ? void 0 : _a2.activeElement;\n    }\n    return element;\n  };\n  const activeElement = shallowRef();\n  const trigger = () => {\n    activeElement.value = getDeepActiveElement();\n  };\n  if (window) {\n    const listenerOptions = {\n      capture: true,\n      passive: true\n    };\n    useEventListener(\n      window,\n      \"blur\",\n      (event) => {\n        if (event.relatedTarget !== null)\n          return;\n        trigger();\n      },\n      listenerOptions\n    );\n    useEventListener(\n      window,\n      \"focus\",\n      trigger,\n      listenerOptions\n    );\n  }\n  if (triggerOnRemoval) {\n    onElementRemoval(activeElement, trigger, { document });\n  }\n  trigger();\n  return activeElement;\n}\n\nfunction useRafFn(fn, options = {}) {\n  const {\n    immediate = true,\n    fpsLimit = void 0,\n    window = defaultWindow,\n    once = false\n  } = options;\n  const isActive = shallowRef(false);\n  const intervalLimit = computed(() => {\n    return fpsLimit ? 1e3 / toValue(fpsLimit) : null;\n  });\n  let previousFrameTimestamp = 0;\n  let rafId = null;\n  function loop(timestamp) {\n    if (!isActive.value || !window)\n      return;\n    if (!previousFrameTimestamp)\n      previousFrameTimestamp = timestamp;\n    const delta = timestamp - previousFrameTimestamp;\n    if (intervalLimit.value && delta < intervalLimit.value) {\n      rafId = window.requestAnimationFrame(loop);\n      return;\n    }\n    previousFrameTimestamp = timestamp;\n    fn({ delta, timestamp });\n    if (once) {\n      isActive.value = false;\n      rafId = null;\n      return;\n    }\n    rafId = window.requestAnimationFrame(loop);\n  }\n  function resume() {\n    if (!isActive.value && window) {\n      isActive.value = true;\n      previousFrameTimestamp = 0;\n      rafId = window.requestAnimationFrame(loop);\n    }\n  }\n  function pause() {\n    isActive.value = false;\n    if (rafId != null && window) {\n      window.cancelAnimationFrame(rafId);\n      rafId = null;\n    }\n  }\n  if (immediate)\n    resume();\n  tryOnScopeDispose(pause);\n  return {\n    isActive: readonly(isActive),\n    pause,\n    resume\n  };\n}\n\nfunction useAnimate(target, keyframes, options) {\n  let config;\n  let animateOptions;\n  if (isObject(options)) {\n    config = options;\n    animateOptions = objectOmit(options, [\"window\", \"immediate\", \"commitStyles\", \"persist\", \"onReady\", \"onError\"]);\n  } else {\n    config = { duration: options };\n    animateOptions = options;\n  }\n  const {\n    window = defaultWindow,\n    immediate = true,\n    commitStyles,\n    persist,\n    playbackRate: _playbackRate = 1,\n    onReady,\n    onError = (e) => {\n      console.error(e);\n    }\n  } = config;\n  const isSupported = useSupported(() => window && HTMLElement && \"animate\" in HTMLElement.prototype);\n  const animate = shallowRef(void 0);\n  const store = shallowReactive({\n    startTime: null,\n    currentTime: null,\n    timeline: null,\n    playbackRate: _playbackRate,\n    pending: false,\n    playState: immediate ? \"idle\" : \"paused\",\n    replaceState: \"active\"\n  });\n  const pending = computed(() => store.pending);\n  const playState = computed(() => store.playState);\n  const replaceState = computed(() => store.replaceState);\n  const startTime = computed({\n    get() {\n      return store.startTime;\n    },\n    set(value) {\n      store.startTime = value;\n      if (animate.value)\n        animate.value.startTime = value;\n    }\n  });\n  const currentTime = computed({\n    get() {\n      return store.currentTime;\n    },\n    set(value) {\n      store.currentTime = value;\n      if (animate.value) {\n        animate.value.currentTime = value;\n        syncResume();\n      }\n    }\n  });\n  const timeline = computed({\n    get() {\n      return store.timeline;\n    },\n    set(value) {\n      store.timeline = value;\n      if (animate.value)\n        animate.value.timeline = value;\n    }\n  });\n  const playbackRate = computed({\n    get() {\n      return store.playbackRate;\n    },\n    set(value) {\n      store.playbackRate = value;\n      if (animate.value)\n        animate.value.playbackRate = value;\n    }\n  });\n  const play = () => {\n    if (animate.value) {\n      try {\n        animate.value.play();\n        syncResume();\n      } catch (e) {\n        syncPause();\n        onError(e);\n      }\n    } else {\n      update();\n    }\n  };\n  const pause = () => {\n    var _a;\n    try {\n      (_a = animate.value) == null ? void 0 : _a.pause();\n      syncPause();\n    } catch (e) {\n      onError(e);\n    }\n  };\n  const reverse = () => {\n    var _a;\n    if (!animate.value)\n      update();\n    try {\n      (_a = animate.value) == null ? void 0 : _a.reverse();\n      syncResume();\n    } catch (e) {\n      syncPause();\n      onError(e);\n    }\n  };\n  const finish = () => {\n    var _a;\n    try {\n      (_a = animate.value) == null ? void 0 : _a.finish();\n      syncPause();\n    } catch (e) {\n      onError(e);\n    }\n  };\n  const cancel = () => {\n    var _a;\n    try {\n      (_a = animate.value) == null ? void 0 : _a.cancel();\n      syncPause();\n    } catch (e) {\n      onError(e);\n    }\n  };\n  watch(() => unrefElement(target), (el) => {\n    if (el) {\n      update(true);\n    } else {\n      animate.value = void 0;\n    }\n  });\n  watch(() => keyframes, (value) => {\n    if (animate.value) {\n      update();\n      const targetEl = unrefElement(target);\n      if (targetEl) {\n        animate.value.effect = new KeyframeEffect(\n          targetEl,\n          toValue(value),\n          animateOptions\n        );\n      }\n    }\n  }, { deep: true });\n  tryOnMounted(() => update(true), false);\n  tryOnScopeDispose(cancel);\n  function update(init) {\n    const el = unrefElement(target);\n    if (!isSupported.value || !el)\n      return;\n    if (!animate.value)\n      animate.value = el.animate(toValue(keyframes), animateOptions);\n    if (persist)\n      animate.value.persist();\n    if (_playbackRate !== 1)\n      animate.value.playbackRate = _playbackRate;\n    if (init && !immediate)\n      animate.value.pause();\n    else\n      syncResume();\n    onReady == null ? void 0 : onReady(animate.value);\n  }\n  const listenerOptions = { passive: true };\n  useEventListener(animate, [\"cancel\", \"finish\", \"remove\"], syncPause, listenerOptions);\n  useEventListener(animate, \"finish\", () => {\n    var _a;\n    if (commitStyles)\n      (_a = animate.value) == null ? void 0 : _a.commitStyles();\n  }, listenerOptions);\n  const { resume: resumeRef, pause: pauseRef } = useRafFn(() => {\n    if (!animate.value)\n      return;\n    store.pending = animate.value.pending;\n    store.playState = animate.value.playState;\n    store.replaceState = animate.value.replaceState;\n    store.startTime = animate.value.startTime;\n    store.currentTime = animate.value.currentTime;\n    store.timeline = animate.value.timeline;\n    store.playbackRate = animate.value.playbackRate;\n  }, { immediate: false });\n  function syncResume() {\n    if (isSupported.value)\n      resumeRef();\n  }\n  function syncPause() {\n    if (isSupported.value && window)\n      window.requestAnimationFrame(pauseRef);\n  }\n  return {\n    isSupported,\n    animate,\n    // actions\n    play,\n    pause,\n    reverse,\n    finish,\n    cancel,\n    // state\n    pending,\n    playState,\n    replaceState,\n    startTime,\n    currentTime,\n    timeline,\n    playbackRate\n  };\n}\n\nfunction useAsyncQueue(tasks, options) {\n  const {\n    interrupt = true,\n    onError = noop,\n    onFinished = noop,\n    signal\n  } = options || {};\n  const promiseState = {\n    aborted: \"aborted\",\n    fulfilled: \"fulfilled\",\n    pending: \"pending\",\n    rejected: \"rejected\"\n  };\n  const initialResult = Array.from(Array.from({ length: tasks.length }), () => ({ state: promiseState.pending, data: null }));\n  const result = reactive(initialResult);\n  const activeIndex = shallowRef(-1);\n  if (!tasks || tasks.length === 0) {\n    onFinished();\n    return {\n      activeIndex,\n      result\n    };\n  }\n  function updateResult(state, res) {\n    activeIndex.value++;\n    result[activeIndex.value].data = res;\n    result[activeIndex.value].state = state;\n  }\n  tasks.reduce((prev, curr) => {\n    return prev.then((prevRes) => {\n      var _a;\n      if (signal == null ? void 0 : signal.aborted) {\n        updateResult(promiseState.aborted, new Error(\"aborted\"));\n        return;\n      }\n      if (((_a = result[activeIndex.value]) == null ? void 0 : _a.state) === promiseState.rejected && interrupt) {\n        onFinished();\n        return;\n      }\n      const done = curr(prevRes).then((currentRes) => {\n        updateResult(promiseState.fulfilled, currentRes);\n        if (activeIndex.value === tasks.length - 1)\n          onFinished();\n        return currentRes;\n      });\n      if (!signal)\n        return done;\n      return Promise.race([done, whenAborted(signal)]);\n    }).catch((e) => {\n      if (signal == null ? void 0 : signal.aborted) {\n        updateResult(promiseState.aborted, e);\n        return e;\n      }\n      updateResult(promiseState.rejected, e);\n      onError();\n      return e;\n    });\n  }, Promise.resolve());\n  return {\n    activeIndex,\n    result\n  };\n}\nfunction whenAborted(signal) {\n  return new Promise((resolve, reject) => {\n    const error = new Error(\"aborted\");\n    if (signal.aborted)\n      reject(error);\n    else\n      signal.addEventListener(\"abort\", () => reject(error), { once: true });\n  });\n}\n\nfunction useAsyncState(promise, initialState, options) {\n  var _a;\n  const {\n    immediate = true,\n    delay = 0,\n    onError = (_a = globalThis.reportError) != null ? _a : noop,\n    onSuccess = noop,\n    resetOnExecute = true,\n    shallow = true,\n    throwError\n  } = options != null ? options : {};\n  const state = shallow ? shallowRef(initialState) : ref(initialState);\n  const isReady = shallowRef(false);\n  const isLoading = shallowRef(false);\n  const error = shallowRef(void 0);\n  async function execute(delay2 = 0, ...args) {\n    if (resetOnExecute)\n      state.value = toValue(initialState);\n    error.value = void 0;\n    isReady.value = false;\n    isLoading.value = true;\n    if (delay2 > 0)\n      await promiseTimeout(delay2);\n    const _promise = typeof promise === \"function\" ? promise(...args) : promise;\n    try {\n      const data = await _promise;\n      state.value = data;\n      isReady.value = true;\n      onSuccess(data);\n    } catch (e) {\n      error.value = e;\n      onError(e);\n      if (throwError)\n        throw e;\n    } finally {\n      isLoading.value = false;\n    }\n    return state.value;\n  }\n  if (immediate) {\n    execute(delay);\n  }\n  const shell = {\n    state,\n    isReady,\n    isLoading,\n    error,\n    execute,\n    executeImmediate: (...args) => execute(0, ...args)\n  };\n  function waitUntilIsLoaded() {\n    return new Promise((resolve, reject) => {\n      until(isLoading).toBe(false).then(() => resolve(shell)).catch(reject);\n    });\n  }\n  return {\n    ...shell,\n    then(onFulfilled, onRejected) {\n      return waitUntilIsLoaded().then(onFulfilled, onRejected);\n    }\n  };\n}\n\nconst defaults = {\n  array: (v) => JSON.stringify(v),\n  object: (v) => JSON.stringify(v),\n  set: (v) => JSON.stringify(Array.from(v)),\n  map: (v) => JSON.stringify(Object.fromEntries(v)),\n  null: () => \"\"\n};\nfunction getDefaultSerialization(target) {\n  if (!target)\n    return defaults.null;\n  if (target instanceof Map)\n    return defaults.map;\n  else if (target instanceof Set)\n    return defaults.set;\n  else if (Array.isArray(target))\n    return defaults.array;\n  else\n    return defaults.object;\n}\n\nfunction useBase64(target, options) {\n  const base64 = shallowRef(\"\");\n  const promise = shallowRef();\n  function execute() {\n    if (!isClient)\n      return;\n    promise.value = new Promise((resolve, reject) => {\n      try {\n        const _target = toValue(target);\n        if (_target == null) {\n          resolve(\"\");\n        } else if (typeof _target === \"string\") {\n          resolve(blobToBase64(new Blob([_target], { type: \"text/plain\" })));\n        } else if (_target instanceof Blob) {\n          resolve(blobToBase64(_target));\n        } else if (_target instanceof ArrayBuffer) {\n          resolve(window.btoa(String.fromCharCode(...new Uint8Array(_target))));\n        } else if (_target instanceof HTMLCanvasElement) {\n          resolve(_target.toDataURL(options == null ? void 0 : options.type, options == null ? void 0 : options.quality));\n        } else if (_target instanceof HTMLImageElement) {\n          const img = _target.cloneNode(false);\n          img.crossOrigin = \"Anonymous\";\n          imgLoaded(img).then(() => {\n            const canvas = document.createElement(\"canvas\");\n            const ctx = canvas.getContext(\"2d\");\n            canvas.width = img.width;\n            canvas.height = img.height;\n            ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\n            resolve(canvas.toDataURL(options == null ? void 0 : options.type, options == null ? void 0 : options.quality));\n          }).catch(reject);\n        } else if (typeof _target === \"object\") {\n          const _serializeFn = (options == null ? void 0 : options.serializer) || getDefaultSerialization(_target);\n          const serialized = _serializeFn(_target);\n          return resolve(blobToBase64(new Blob([serialized], { type: \"application/json\" })));\n        } else {\n          reject(new Error(\"target is unsupported types\"));\n        }\n      } catch (error) {\n        reject(error);\n      }\n    });\n    promise.value.then((res) => {\n      base64.value = (options == null ? void 0 : options.dataUrl) === false ? res.replace(/^data:.*?;base64,/, \"\") : res;\n    });\n    return promise.value;\n  }\n  if (isRef(target) || typeof target === \"function\")\n    watch(target, execute, { immediate: true });\n  else\n    execute();\n  return {\n    base64,\n    promise,\n    execute\n  };\n}\nfunction imgLoaded(img) {\n  return new Promise((resolve, reject) => {\n    if (!img.complete) {\n      img.onload = () => {\n        resolve();\n      };\n      img.onerror = reject;\n    } else {\n      resolve();\n    }\n  });\n}\nfunction blobToBase64(blob) {\n  return new Promise((resolve, reject) => {\n    const fr = new FileReader();\n    fr.onload = (e) => {\n      resolve(e.target.result);\n    };\n    fr.onerror = reject;\n    fr.readAsDataURL(blob);\n  });\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useBattery(options = {}) {\n  const { navigator = defaultNavigator } = options;\n  const events = [\"chargingchange\", \"chargingtimechange\", \"dischargingtimechange\", \"levelchange\"];\n  const isSupported = useSupported(() => navigator && \"getBattery\" in navigator && typeof navigator.getBattery === \"function\");\n  const charging = shallowRef(false);\n  const chargingTime = shallowRef(0);\n  const dischargingTime = shallowRef(0);\n  const level = shallowRef(1);\n  let battery;\n  function updateBatteryInfo() {\n    charging.value = this.charging;\n    chargingTime.value = this.chargingTime || 0;\n    dischargingTime.value = this.dischargingTime || 0;\n    level.value = this.level;\n  }\n  if (isSupported.value) {\n    navigator.getBattery().then((_battery) => {\n      battery = _battery;\n      updateBatteryInfo.call(battery);\n      useEventListener(battery, events, updateBatteryInfo, { passive: true });\n    });\n  }\n  return {\n    isSupported,\n    charging,\n    chargingTime,\n    dischargingTime,\n    level\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useBluetooth(options) {\n  let {\n    acceptAllDevices = false\n  } = options || {};\n  const {\n    filters = void 0,\n    optionalServices = void 0,\n    navigator = defaultNavigator\n  } = options || {};\n  const isSupported = useSupported(() => navigator && \"bluetooth\" in navigator);\n  const device = shallowRef();\n  const error = shallowRef(null);\n  watch(device, () => {\n    connectToBluetoothGATTServer();\n  });\n  async function requestDevice() {\n    if (!isSupported.value)\n      return;\n    error.value = null;\n    if (filters && filters.length > 0)\n      acceptAllDevices = false;\n    try {\n      device.value = await (navigator == null ? void 0 : navigator.bluetooth.requestDevice({\n        acceptAllDevices,\n        filters,\n        optionalServices\n      }));\n    } catch (err) {\n      error.value = err;\n    }\n  }\n  const server = shallowRef();\n  const isConnected = shallowRef(false);\n  function reset() {\n    isConnected.value = false;\n    device.value = void 0;\n    server.value = void 0;\n  }\n  async function connectToBluetoothGATTServer() {\n    error.value = null;\n    if (device.value && device.value.gatt) {\n      useEventListener(device, \"gattserverdisconnected\", reset, { passive: true });\n      try {\n        server.value = await device.value.gatt.connect();\n        isConnected.value = server.value.connected;\n      } catch (err) {\n        error.value = err;\n      }\n    }\n  }\n  tryOnMounted(() => {\n    var _a;\n    if (device.value)\n      (_a = device.value.gatt) == null ? void 0 : _a.connect();\n  });\n  tryOnScopeDispose(() => {\n    var _a;\n    if (device.value)\n      (_a = device.value.gatt) == null ? void 0 : _a.disconnect();\n  });\n  return {\n    isSupported,\n    isConnected: readonly(isConnected),\n    // Device:\n    device,\n    requestDevice,\n    // Server:\n    server,\n    // Errors:\n    error\n  };\n}\n\nconst ssrWidthSymbol = Symbol(\"vueuse-ssr-width\");\n// @__NO_SIDE_EFFECTS__\nfunction useSSRWidth() {\n  const ssrWidth = hasInjectionContext() ? injectLocal(ssrWidthSymbol, null) : null;\n  return typeof ssrWidth === \"number\" ? ssrWidth : void 0;\n}\nfunction provideSSRWidth(width, app) {\n  if (app !== void 0) {\n    app.provide(ssrWidthSymbol, width);\n  } else {\n    provideLocal(ssrWidthSymbol, width);\n  }\n}\n\nfunction useMediaQuery(query, options = {}) {\n  const { window = defaultWindow, ssrWidth = useSSRWidth() } = options;\n  const isSupported = useSupported(() => window && \"matchMedia\" in window && typeof window.matchMedia === \"function\");\n  const ssrSupport = shallowRef(typeof ssrWidth === \"number\");\n  const mediaQuery = shallowRef();\n  const matches = shallowRef(false);\n  const handler = (event) => {\n    matches.value = event.matches;\n  };\n  watchEffect(() => {\n    if (ssrSupport.value) {\n      ssrSupport.value = !isSupported.value;\n      const queryStrings = toValue(query).split(\",\");\n      matches.value = queryStrings.some((queryString) => {\n        const not = queryString.includes(\"not all\");\n        const minWidth = queryString.match(/\\(\\s*min-width:\\s*(-?\\d+(?:\\.\\d*)?[a-z]+\\s*)\\)/);\n        const maxWidth = queryString.match(/\\(\\s*max-width:\\s*(-?\\d+(?:\\.\\d*)?[a-z]+\\s*)\\)/);\n        let res = Boolean(minWidth || maxWidth);\n        if (minWidth && res) {\n          res = ssrWidth >= pxValue(minWidth[1]);\n        }\n        if (maxWidth && res) {\n          res = ssrWidth <= pxValue(maxWidth[1]);\n        }\n        return not ? !res : res;\n      });\n      return;\n    }\n    if (!isSupported.value)\n      return;\n    mediaQuery.value = window.matchMedia(toValue(query));\n    matches.value = mediaQuery.value.matches;\n  });\n  useEventListener(mediaQuery, \"change\", handler, { passive: true });\n  return computed(() => matches.value);\n}\n\nconst breakpointsTailwind = {\n  \"sm\": 640,\n  \"md\": 768,\n  \"lg\": 1024,\n  \"xl\": 1280,\n  \"2xl\": 1536\n};\nconst breakpointsBootstrapV5 = {\n  xs: 0,\n  sm: 576,\n  md: 768,\n  lg: 992,\n  xl: 1200,\n  xxl: 1400\n};\nconst breakpointsVuetifyV2 = {\n  xs: 0,\n  sm: 600,\n  md: 960,\n  lg: 1264,\n  xl: 1904\n};\nconst breakpointsVuetifyV3 = {\n  xs: 0,\n  sm: 600,\n  md: 960,\n  lg: 1280,\n  xl: 1920,\n  xxl: 2560\n};\nconst breakpointsVuetify = breakpointsVuetifyV2;\nconst breakpointsAntDesign = {\n  xs: 480,\n  sm: 576,\n  md: 768,\n  lg: 992,\n  xl: 1200,\n  xxl: 1600\n};\nconst breakpointsQuasar = {\n  xs: 0,\n  sm: 600,\n  md: 1024,\n  lg: 1440,\n  xl: 1920\n};\nconst breakpointsSematic = {\n  mobileS: 320,\n  mobileM: 375,\n  mobileL: 425,\n  tablet: 768,\n  laptop: 1024,\n  laptopL: 1440,\n  desktop4K: 2560\n};\nconst breakpointsMasterCss = {\n  \"3xs\": 360,\n  \"2xs\": 480,\n  \"xs\": 600,\n  \"sm\": 768,\n  \"md\": 1024,\n  \"lg\": 1280,\n  \"xl\": 1440,\n  \"2xl\": 1600,\n  \"3xl\": 1920,\n  \"4xl\": 2560\n};\nconst breakpointsPrimeFlex = {\n  sm: 576,\n  md: 768,\n  lg: 992,\n  xl: 1200\n};\nconst breakpointsElement = {\n  xs: 0,\n  sm: 768,\n  md: 992,\n  lg: 1200,\n  xl: 1920\n};\n\n// @__NO_SIDE_EFFECTS__\nfunction useBreakpoints(breakpoints, options = {}) {\n  function getValue(k, delta) {\n    let v = toValue(breakpoints[toValue(k)]);\n    if (delta != null)\n      v = increaseWithUnit(v, delta);\n    if (typeof v === \"number\")\n      v = `${v}px`;\n    return v;\n  }\n  const { window = defaultWindow, strategy = \"min-width\", ssrWidth = useSSRWidth() } = options;\n  const ssrSupport = typeof ssrWidth === \"number\";\n  const mounted = ssrSupport ? shallowRef(false) : { value: true };\n  if (ssrSupport) {\n    tryOnMounted(() => mounted.value = !!window);\n  }\n  function match(query, size) {\n    if (!mounted.value && ssrSupport) {\n      return query === \"min\" ? ssrWidth >= pxValue(size) : ssrWidth <= pxValue(size);\n    }\n    if (!window)\n      return false;\n    return window.matchMedia(`(${query}-width: ${size})`).matches;\n  }\n  const greaterOrEqual = (k) => {\n    return useMediaQuery(() => `(min-width: ${getValue(k)})`, options);\n  };\n  const smallerOrEqual = (k) => {\n    return useMediaQuery(() => `(max-width: ${getValue(k)})`, options);\n  };\n  const shortcutMethods = Object.keys(breakpoints).reduce((shortcuts, k) => {\n    Object.defineProperty(shortcuts, k, {\n      get: () => strategy === \"min-width\" ? greaterOrEqual(k) : smallerOrEqual(k),\n      enumerable: true,\n      configurable: true\n    });\n    return shortcuts;\n  }, {});\n  function current() {\n    const points = Object.keys(breakpoints).map((k) => [k, shortcutMethods[k], pxValue(getValue(k))]).sort((a, b) => a[2] - b[2]);\n    return computed(() => points.filter(([, v]) => v.value).map(([k]) => k));\n  }\n  return Object.assign(shortcutMethods, {\n    greaterOrEqual,\n    smallerOrEqual,\n    greater(k) {\n      return useMediaQuery(() => `(min-width: ${getValue(k, 0.1)})`, options);\n    },\n    smaller(k) {\n      return useMediaQuery(() => `(max-width: ${getValue(k, -0.1)})`, options);\n    },\n    between(a, b) {\n      return useMediaQuery(() => `(min-width: ${getValue(a)}) and (max-width: ${getValue(b, -0.1)})`, options);\n    },\n    isGreater(k) {\n      return match(\"min\", getValue(k, 0.1));\n    },\n    isGreaterOrEqual(k) {\n      return match(\"min\", getValue(k));\n    },\n    isSmaller(k) {\n      return match(\"max\", getValue(k, -0.1));\n    },\n    isSmallerOrEqual(k) {\n      return match(\"max\", getValue(k));\n    },\n    isInBetween(a, b) {\n      return match(\"min\", getValue(a)) && match(\"max\", getValue(b, -0.1));\n    },\n    current,\n    active() {\n      const bps = current();\n      return computed(() => bps.value.length === 0 ? \"\" : bps.value.at(strategy === \"min-width\" ? -1 : 0));\n    }\n  });\n}\n\nfunction useBroadcastChannel(options) {\n  const {\n    name,\n    window = defaultWindow\n  } = options;\n  const isSupported = useSupported(() => window && \"BroadcastChannel\" in window);\n  const isClosed = shallowRef(false);\n  const channel = ref();\n  const data = ref();\n  const error = shallowRef(null);\n  const post = (data2) => {\n    if (channel.value)\n      channel.value.postMessage(data2);\n  };\n  const close = () => {\n    if (channel.value)\n      channel.value.close();\n    isClosed.value = true;\n  };\n  if (isSupported.value) {\n    tryOnMounted(() => {\n      error.value = null;\n      channel.value = new BroadcastChannel(name);\n      const listenerOptions = {\n        passive: true\n      };\n      useEventListener(channel, \"message\", (e) => {\n        data.value = e.data;\n      }, listenerOptions);\n      useEventListener(channel, \"messageerror\", (e) => {\n        error.value = e;\n      }, listenerOptions);\n      useEventListener(channel, \"close\", () => {\n        isClosed.value = true;\n      }, listenerOptions);\n    });\n  }\n  tryOnScopeDispose(() => {\n    close();\n  });\n  return {\n    isSupported,\n    channel,\n    data,\n    post,\n    close,\n    error,\n    isClosed\n  };\n}\n\nconst WRITABLE_PROPERTIES = [\n  \"hash\",\n  \"host\",\n  \"hostname\",\n  \"href\",\n  \"pathname\",\n  \"port\",\n  \"protocol\",\n  \"search\"\n];\n// @__NO_SIDE_EFFECTS__\nfunction useBrowserLocation(options = {}) {\n  const { window = defaultWindow } = options;\n  const refs = Object.fromEntries(\n    WRITABLE_PROPERTIES.map((key) => [key, ref()])\n  );\n  for (const [key, ref] of objectEntries(refs)) {\n    watch(ref, (value) => {\n      if (!(window == null ? void 0 : window.location) || window.location[key] === value)\n        return;\n      window.location[key] = value;\n    });\n  }\n  const buildState = (trigger) => {\n    var _a;\n    const { state: state2, length } = (window == null ? void 0 : window.history) || {};\n    const { origin } = (window == null ? void 0 : window.location) || {};\n    for (const key of WRITABLE_PROPERTIES)\n      refs[key].value = (_a = window == null ? void 0 : window.location) == null ? void 0 : _a[key];\n    return reactive({\n      trigger,\n      state: state2,\n      length,\n      origin,\n      ...refs\n    });\n  };\n  const state = ref(buildState(\"load\"));\n  if (window) {\n    const listenerOptions = { passive: true };\n    useEventListener(window, \"popstate\", () => state.value = buildState(\"popstate\"), listenerOptions);\n    useEventListener(window, \"hashchange\", () => state.value = buildState(\"hashchange\"), listenerOptions);\n  }\n  return state;\n}\n\nfunction useCached(refValue, comparator = (a, b) => a === b, options) {\n  const { deepRefs = true, ...watchOptions } = options || {};\n  const cachedValue = createRef(refValue.value, deepRefs);\n  watch(() => refValue.value, (value) => {\n    if (!comparator(value, cachedValue.value))\n      cachedValue.value = value;\n  }, watchOptions);\n  return cachedValue;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction usePermission(permissionDesc, options = {}) {\n  const {\n    controls = false,\n    navigator = defaultNavigator\n  } = options;\n  const isSupported = useSupported(() => navigator && \"permissions\" in navigator);\n  const permissionStatus = shallowRef();\n  const desc = typeof permissionDesc === \"string\" ? { name: permissionDesc } : permissionDesc;\n  const state = shallowRef();\n  const update = () => {\n    var _a, _b;\n    state.value = (_b = (_a = permissionStatus.value) == null ? void 0 : _a.state) != null ? _b : \"prompt\";\n  };\n  useEventListener(permissionStatus, \"change\", update, { passive: true });\n  const query = createSingletonPromise(async () => {\n    if (!isSupported.value)\n      return;\n    if (!permissionStatus.value) {\n      try {\n        permissionStatus.value = await navigator.permissions.query(desc);\n      } catch (e) {\n        permissionStatus.value = void 0;\n      } finally {\n        update();\n      }\n    }\n    if (controls)\n      return toRaw(permissionStatus.value);\n  });\n  query();\n  if (controls) {\n    return {\n      state,\n      isSupported,\n      query\n    };\n  } else {\n    return state;\n  }\n}\n\nfunction useClipboard(options = {}) {\n  const {\n    navigator = defaultNavigator,\n    read = false,\n    source,\n    copiedDuring = 1500,\n    legacy = false\n  } = options;\n  const isClipboardApiSupported = useSupported(() => navigator && \"clipboard\" in navigator);\n  const permissionRead = usePermission(\"clipboard-read\");\n  const permissionWrite = usePermission(\"clipboard-write\");\n  const isSupported = computed(() => isClipboardApiSupported.value || legacy);\n  const text = shallowRef(\"\");\n  const copied = shallowRef(false);\n  const timeout = useTimeoutFn(() => copied.value = false, copiedDuring, { immediate: false });\n  async function updateText() {\n    let useLegacy = !(isClipboardApiSupported.value && isAllowed(permissionRead.value));\n    if (!useLegacy) {\n      try {\n        text.value = await navigator.clipboard.readText();\n      } catch (e) {\n        useLegacy = true;\n      }\n    }\n    if (useLegacy) {\n      text.value = legacyRead();\n    }\n  }\n  if (isSupported.value && read)\n    useEventListener([\"copy\", \"cut\"], updateText, { passive: true });\n  async function copy(value = toValue(source)) {\n    if (isSupported.value && value != null) {\n      let useLegacy = !(isClipboardApiSupported.value && isAllowed(permissionWrite.value));\n      if (!useLegacy) {\n        try {\n          await navigator.clipboard.writeText(value);\n        } catch (e) {\n          useLegacy = true;\n        }\n      }\n      if (useLegacy)\n        legacyCopy(value);\n      text.value = value;\n      copied.value = true;\n      timeout.start();\n    }\n  }\n  function legacyCopy(value) {\n    const ta = document.createElement(\"textarea\");\n    ta.value = value != null ? value : \"\";\n    ta.style.position = \"absolute\";\n    ta.style.opacity = \"0\";\n    document.body.appendChild(ta);\n    ta.select();\n    document.execCommand(\"copy\");\n    ta.remove();\n  }\n  function legacyRead() {\n    var _a, _b, _c;\n    return (_c = (_b = (_a = document == null ? void 0 : document.getSelection) == null ? void 0 : _a.call(document)) == null ? void 0 : _b.toString()) != null ? _c : \"\";\n  }\n  function isAllowed(status) {\n    return status === \"granted\" || status === \"prompt\";\n  }\n  return {\n    isSupported,\n    text,\n    copied,\n    copy\n  };\n}\n\nfunction useClipboardItems(options = {}) {\n  const {\n    navigator = defaultNavigator,\n    read = false,\n    source,\n    copiedDuring = 1500\n  } = options;\n  const isSupported = useSupported(() => navigator && \"clipboard\" in navigator);\n  const content = ref([]);\n  const copied = shallowRef(false);\n  const timeout = useTimeoutFn(() => copied.value = false, copiedDuring, { immediate: false });\n  function updateContent() {\n    if (isSupported.value) {\n      navigator.clipboard.read().then((items) => {\n        content.value = items;\n      });\n    }\n  }\n  if (isSupported.value && read) {\n    useEventListener([\"copy\", \"cut\"], updateContent, { passive: true });\n  }\n  async function copy(value = toValue(source)) {\n    if (isSupported.value && value != null) {\n      await navigator.clipboard.write(value);\n      content.value = value;\n      copied.value = true;\n      timeout.start();\n    }\n  }\n  return {\n    isSupported,\n    content: shallowReadonly(content),\n    copied: readonly(copied),\n    copy,\n    read: updateContent\n  };\n}\n\nfunction cloneFnJSON(source) {\n  return JSON.parse(JSON.stringify(source));\n}\nfunction useCloned(source, options = {}) {\n  const cloned = ref({});\n  const isModified = shallowRef(false);\n  let _lastSync = false;\n  const {\n    manual,\n    clone = cloneFnJSON,\n    // watch options\n    deep = true,\n    immediate = true\n  } = options;\n  watch(cloned, () => {\n    if (_lastSync) {\n      _lastSync = false;\n      return;\n    }\n    isModified.value = true;\n  }, {\n    deep: true,\n    flush: \"sync\"\n  });\n  function sync() {\n    _lastSync = true;\n    isModified.value = false;\n    cloned.value = clone(toValue(source));\n  }\n  if (!manual && (isRef(source) || typeof source === \"function\")) {\n    watch(source, sync, {\n      ...options,\n      deep,\n      immediate\n    });\n  } else {\n    sync();\n  }\n  return { cloned, isModified, sync };\n}\n\nconst _global = typeof globalThis !== \"undefined\" ? globalThis : typeof window !== \"undefined\" ? window : typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : {};\nconst globalKey = \"__vueuse_ssr_handlers__\";\nconst handlers = /* @__PURE__ */ getHandlers();\nfunction getHandlers() {\n  if (!(globalKey in _global))\n    _global[globalKey] = _global[globalKey] || {};\n  return _global[globalKey];\n}\nfunction getSSRHandler(key, fallback) {\n  return handlers[key] || fallback;\n}\nfunction setSSRHandler(key, fn) {\n  handlers[key] = fn;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction usePreferredDark(options) {\n  return useMediaQuery(\"(prefers-color-scheme: dark)\", options);\n}\n\nfunction guessSerializerType(rawInit) {\n  return rawInit == null ? \"any\" : rawInit instanceof Set ? \"set\" : rawInit instanceof Map ? \"map\" : rawInit instanceof Date ? \"date\" : typeof rawInit === \"boolean\" ? \"boolean\" : typeof rawInit === \"string\" ? \"string\" : typeof rawInit === \"object\" ? \"object\" : !Number.isNaN(rawInit) ? \"number\" : \"any\";\n}\n\nconst StorageSerializers = {\n  boolean: {\n    read: (v) => v === \"true\",\n    write: (v) => String(v)\n  },\n  object: {\n    read: (v) => JSON.parse(v),\n    write: (v) => JSON.stringify(v)\n  },\n  number: {\n    read: (v) => Number.parseFloat(v),\n    write: (v) => String(v)\n  },\n  any: {\n    read: (v) => v,\n    write: (v) => String(v)\n  },\n  string: {\n    read: (v) => v,\n    write: (v) => String(v)\n  },\n  map: {\n    read: (v) => new Map(JSON.parse(v)),\n    write: (v) => JSON.stringify(Array.from(v.entries()))\n  },\n  set: {\n    read: (v) => new Set(JSON.parse(v)),\n    write: (v) => JSON.stringify(Array.from(v))\n  },\n  date: {\n    read: (v) => new Date(v),\n    write: (v) => v.toISOString()\n  }\n};\nconst customStorageEventName = \"vueuse-storage\";\nfunction useStorage(key, defaults, storage, options = {}) {\n  var _a;\n  const {\n    flush = \"pre\",\n    deep = true,\n    listenToStorageChanges = true,\n    writeDefaults = true,\n    mergeDefaults = false,\n    shallow,\n    window = defaultWindow,\n    eventFilter,\n    onError = (e) => {\n      console.error(e);\n    },\n    initOnMounted\n  } = options;\n  const data = (shallow ? shallowRef : ref)(typeof defaults === \"function\" ? defaults() : defaults);\n  const keyComputed = computed(() => toValue(key));\n  if (!storage) {\n    try {\n      storage = getSSRHandler(\"getDefaultStorage\", () => {\n        var _a2;\n        return (_a2 = defaultWindow) == null ? void 0 : _a2.localStorage;\n      })();\n    } catch (e) {\n      onError(e);\n    }\n  }\n  if (!storage)\n    return data;\n  const rawInit = toValue(defaults);\n  const type = guessSerializerType(rawInit);\n  const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type];\n  const { pause: pauseWatch, resume: resumeWatch } = pausableWatch(\n    data,\n    (newValue) => write(newValue),\n    { flush, deep, eventFilter }\n  );\n  watch(keyComputed, () => update(), { flush });\n  let firstMounted = false;\n  const onStorageEvent = (ev) => {\n    if (initOnMounted && !firstMounted) {\n      return;\n    }\n    update(ev);\n  };\n  const onStorageCustomEvent = (ev) => {\n    if (initOnMounted && !firstMounted) {\n      return;\n    }\n    updateFromCustomEvent(ev);\n  };\n  if (window && listenToStorageChanges) {\n    if (storage instanceof Storage)\n      useEventListener(window, \"storage\", onStorageEvent, { passive: true });\n    else\n      useEventListener(window, customStorageEventName, onStorageCustomEvent);\n  }\n  if (initOnMounted) {\n    tryOnMounted(() => {\n      firstMounted = true;\n      update();\n    });\n  } else {\n    update();\n  }\n  function dispatchWriteEvent(oldValue, newValue) {\n    if (window) {\n      const payload = {\n        key: keyComputed.value,\n        oldValue,\n        newValue,\n        storageArea: storage\n      };\n      window.dispatchEvent(storage instanceof Storage ? new StorageEvent(\"storage\", payload) : new CustomEvent(customStorageEventName, {\n        detail: payload\n      }));\n    }\n  }\n  function write(v) {\n    try {\n      const oldValue = storage.getItem(keyComputed.value);\n      if (v == null) {\n        dispatchWriteEvent(oldValue, null);\n        storage.removeItem(keyComputed.value);\n      } else {\n        const serialized = serializer.write(v);\n        if (oldValue !== serialized) {\n          storage.setItem(keyComputed.value, serialized);\n          dispatchWriteEvent(oldValue, serialized);\n        }\n      }\n    } catch (e) {\n      onError(e);\n    }\n  }\n  function read(event) {\n    const rawValue = event ? event.newValue : storage.getItem(keyComputed.value);\n    if (rawValue == null) {\n      if (writeDefaults && rawInit != null)\n        storage.setItem(keyComputed.value, serializer.write(rawInit));\n      return rawInit;\n    } else if (!event && mergeDefaults) {\n      const value = serializer.read(rawValue);\n      if (typeof mergeDefaults === \"function\")\n        return mergeDefaults(value, rawInit);\n      else if (type === \"object\" && !Array.isArray(value))\n        return { ...rawInit, ...value };\n      return value;\n    } else if (typeof rawValue !== \"string\") {\n      return rawValue;\n    } else {\n      return serializer.read(rawValue);\n    }\n  }\n  function update(event) {\n    if (event && event.storageArea !== storage)\n      return;\n    if (event && event.key == null) {\n      data.value = rawInit;\n      return;\n    }\n    if (event && event.key !== keyComputed.value) {\n      return;\n    }\n    pauseWatch();\n    try {\n      const serializedData = serializer.write(data.value);\n      if (event === void 0 || (event == null ? void 0 : event.newValue) !== serializedData) {\n        data.value = read(event);\n      }\n    } catch (e) {\n      onError(e);\n    } finally {\n      if (event)\n        nextTick(resumeWatch);\n      else\n        resumeWatch();\n    }\n  }\n  function updateFromCustomEvent(event) {\n    update(event.detail);\n  }\n  return data;\n}\n\nconst CSS_DISABLE_TRANS = \"*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}\";\nfunction useColorMode(options = {}) {\n  const {\n    selector = \"html\",\n    attribute = \"class\",\n    initialValue = \"auto\",\n    window = defaultWindow,\n    storage,\n    storageKey = \"vueuse-color-scheme\",\n    listenToStorageChanges = true,\n    storageRef,\n    emitAuto,\n    disableTransition = true\n  } = options;\n  const modes = {\n    auto: \"\",\n    light: \"light\",\n    dark: \"dark\",\n    ...options.modes || {}\n  };\n  const preferredDark = usePreferredDark({ window });\n  const system = computed(() => preferredDark.value ? \"dark\" : \"light\");\n  const store = storageRef || (storageKey == null ? toRef(initialValue) : useStorage(storageKey, initialValue, storage, { window, listenToStorageChanges }));\n  const state = computed(() => store.value === \"auto\" ? system.value : store.value);\n  const updateHTMLAttrs = getSSRHandler(\n    \"updateHTMLAttrs\",\n    (selector2, attribute2, value) => {\n      const el = typeof selector2 === \"string\" ? window == null ? void 0 : window.document.querySelector(selector2) : unrefElement(selector2);\n      if (!el)\n        return;\n      const classesToAdd = /* @__PURE__ */ new Set();\n      const classesToRemove = /* @__PURE__ */ new Set();\n      let attributeToChange = null;\n      if (attribute2 === \"class\") {\n        const current = value.split(/\\s/g);\n        Object.values(modes).flatMap((i) => (i || \"\").split(/\\s/g)).filter(Boolean).forEach((v) => {\n          if (current.includes(v))\n            classesToAdd.add(v);\n          else\n            classesToRemove.add(v);\n        });\n      } else {\n        attributeToChange = { key: attribute2, value };\n      }\n      if (classesToAdd.size === 0 && classesToRemove.size === 0 && attributeToChange === null)\n        return;\n      let style;\n      if (disableTransition) {\n        style = window.document.createElement(\"style\");\n        style.appendChild(document.createTextNode(CSS_DISABLE_TRANS));\n        window.document.head.appendChild(style);\n      }\n      for (const c of classesToAdd) {\n        el.classList.add(c);\n      }\n      for (const c of classesToRemove) {\n        el.classList.remove(c);\n      }\n      if (attributeToChange) {\n        el.setAttribute(attributeToChange.key, attributeToChange.value);\n      }\n      if (disableTransition) {\n        window.getComputedStyle(style).opacity;\n        document.head.removeChild(style);\n      }\n    }\n  );\n  function defaultOnChanged(mode) {\n    var _a;\n    updateHTMLAttrs(selector, attribute, (_a = modes[mode]) != null ? _a : mode);\n  }\n  function onChanged(mode) {\n    if (options.onChanged)\n      options.onChanged(mode, defaultOnChanged);\n    else\n      defaultOnChanged(mode);\n  }\n  watch(state, onChanged, { flush: \"post\", immediate: true });\n  tryOnMounted(() => onChanged(state.value));\n  const auto = computed({\n    get() {\n      return emitAuto ? store.value : state.value;\n    },\n    set(v) {\n      store.value = v;\n    }\n  });\n  return Object.assign(auto, { store, system, state });\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useConfirmDialog(revealed = shallowRef(false)) {\n  const confirmHook = createEventHook();\n  const cancelHook = createEventHook();\n  const revealHook = createEventHook();\n  let _resolve = noop;\n  const reveal = (data) => {\n    revealHook.trigger(data);\n    revealed.value = true;\n    return new Promise((resolve) => {\n      _resolve = resolve;\n    });\n  };\n  const confirm = (data) => {\n    revealed.value = false;\n    confirmHook.trigger(data);\n    _resolve({ data, isCanceled: false });\n  };\n  const cancel = (data) => {\n    revealed.value = false;\n    cancelHook.trigger(data);\n    _resolve({ data, isCanceled: true });\n  };\n  return {\n    isRevealed: computed(() => revealed.value),\n    reveal,\n    confirm,\n    cancel,\n    onReveal: revealHook.on,\n    onConfirm: confirmHook.on,\n    onCancel: cancelHook.on\n  };\n}\n\nfunction useCountdown(initialCountdown, options) {\n  var _a, _b;\n  const remaining = shallowRef(toValue(initialCountdown));\n  const intervalController = useIntervalFn(() => {\n    var _a2, _b2;\n    const value = remaining.value - 1;\n    remaining.value = value < 0 ? 0 : value;\n    (_a2 = options == null ? void 0 : options.onTick) == null ? void 0 : _a2.call(options);\n    if (remaining.value <= 0) {\n      intervalController.pause();\n      (_b2 = options == null ? void 0 : options.onComplete) == null ? void 0 : _b2.call(options);\n    }\n  }, (_a = options == null ? void 0 : options.interval) != null ? _a : 1e3, { immediate: (_b = options == null ? void 0 : options.immediate) != null ? _b : false });\n  const reset = (countdown) => {\n    var _a2;\n    remaining.value = (_a2 = toValue(countdown)) != null ? _a2 : toValue(initialCountdown);\n  };\n  const stop = () => {\n    intervalController.pause();\n    reset();\n  };\n  const resume = () => {\n    if (!intervalController.isActive.value) {\n      if (remaining.value > 0) {\n        intervalController.resume();\n      }\n    }\n  };\n  const start = (countdown) => {\n    reset(countdown);\n    intervalController.resume();\n  };\n  return {\n    remaining,\n    reset,\n    stop,\n    start,\n    pause: intervalController.pause,\n    resume,\n    isActive: intervalController.isActive\n  };\n}\n\nfunction useCssVar(prop, target, options = {}) {\n  const { window = defaultWindow, initialValue, observe = false } = options;\n  const variable = shallowRef(initialValue);\n  const elRef = computed(() => {\n    var _a;\n    return unrefElement(target) || ((_a = window == null ? void 0 : window.document) == null ? void 0 : _a.documentElement);\n  });\n  function updateCssVar() {\n    var _a;\n    const key = toValue(prop);\n    const el = toValue(elRef);\n    if (el && window && key) {\n      const value = (_a = window.getComputedStyle(el).getPropertyValue(key)) == null ? void 0 : _a.trim();\n      variable.value = value || variable.value || initialValue;\n    }\n  }\n  if (observe) {\n    useMutationObserver(elRef, updateCssVar, {\n      attributeFilter: [\"style\", \"class\"],\n      window\n    });\n  }\n  watch(\n    [elRef, () => toValue(prop)],\n    (_, old) => {\n      if (old[0] && old[1])\n        old[0].style.removeProperty(old[1]);\n      updateCssVar();\n    },\n    { immediate: true }\n  );\n  watch(\n    [variable, elRef],\n    ([val, el]) => {\n      const raw_prop = toValue(prop);\n      if ((el == null ? void 0 : el.style) && raw_prop) {\n        if (val == null)\n          el.style.removeProperty(raw_prop);\n        else\n          el.style.setProperty(raw_prop, val);\n      }\n    },\n    { immediate: true }\n  );\n  return variable;\n}\n\nfunction useCurrentElement(rootComponent) {\n  const vm = getCurrentInstance();\n  const currentElement = computedWithControl(\n    () => null,\n    () => rootComponent ? unrefElement(rootComponent) : vm.proxy.$el\n  );\n  onUpdated(currentElement.trigger);\n  onMounted(currentElement.trigger);\n  return currentElement;\n}\n\nfunction useCycleList(list, options) {\n  const state = shallowRef(getInitialValue());\n  const listRef = toRef(list);\n  const index = computed({\n    get() {\n      var _a;\n      const targetList = listRef.value;\n      let index2 = (options == null ? void 0 : options.getIndexOf) ? options.getIndexOf(state.value, targetList) : targetList.indexOf(state.value);\n      if (index2 < 0)\n        index2 = (_a = options == null ? void 0 : options.fallbackIndex) != null ? _a : 0;\n      return index2;\n    },\n    set(v) {\n      set(v);\n    }\n  });\n  function set(i) {\n    const targetList = listRef.value;\n    const length = targetList.length;\n    const index2 = (i % length + length) % length;\n    const value = targetList[index2];\n    state.value = value;\n    return value;\n  }\n  function shift(delta = 1) {\n    return set(index.value + delta);\n  }\n  function next(n = 1) {\n    return shift(n);\n  }\n  function prev(n = 1) {\n    return shift(-n);\n  }\n  function getInitialValue() {\n    var _a, _b;\n    return (_b = toValue((_a = options == null ? void 0 : options.initialValue) != null ? _a : toValue(list)[0])) != null ? _b : void 0;\n  }\n  watch(listRef, () => set(index.value));\n  return {\n    state,\n    index,\n    next,\n    prev,\n    go: set\n  };\n}\n\nfunction useDark(options = {}) {\n  const {\n    valueDark = \"dark\",\n    valueLight = \"\"\n  } = options;\n  const mode = useColorMode({\n    ...options,\n    onChanged: (mode2, defaultHandler) => {\n      var _a;\n      if (options.onChanged)\n        (_a = options.onChanged) == null ? void 0 : _a.call(options, mode2 === \"dark\", defaultHandler, mode2);\n      else\n        defaultHandler(mode2);\n    },\n    modes: {\n      dark: valueDark,\n      light: valueLight\n    }\n  });\n  const system = computed(() => mode.system.value);\n  const isDark = computed({\n    get() {\n      return mode.value === \"dark\";\n    },\n    set(v) {\n      const modeVal = v ? \"dark\" : \"light\";\n      if (system.value === modeVal)\n        mode.value = \"auto\";\n      else\n        mode.value = modeVal;\n    }\n  });\n  return isDark;\n}\n\nfunction fnBypass(v) {\n  return v;\n}\nfunction fnSetSource(source, value) {\n  return source.value = value;\n}\nfunction defaultDump(clone) {\n  return clone ? typeof clone === \"function\" ? clone : cloneFnJSON : fnBypass;\n}\nfunction defaultParse(clone) {\n  return clone ? typeof clone === \"function\" ? clone : cloneFnJSON : fnBypass;\n}\nfunction useManualRefHistory(source, options = {}) {\n  const {\n    clone = false,\n    dump = defaultDump(clone),\n    parse = defaultParse(clone),\n    setSource = fnSetSource\n  } = options;\n  function _createHistoryRecord() {\n    return markRaw({\n      snapshot: dump(source.value),\n      timestamp: timestamp()\n    });\n  }\n  const last = ref(_createHistoryRecord());\n  const undoStack = ref([]);\n  const redoStack = ref([]);\n  const _setSource = (record) => {\n    setSource(source, parse(record.snapshot));\n    last.value = record;\n  };\n  const commit = () => {\n    undoStack.value.unshift(last.value);\n    last.value = _createHistoryRecord();\n    if (options.capacity && undoStack.value.length > options.capacity)\n      undoStack.value.splice(options.capacity, Number.POSITIVE_INFINITY);\n    if (redoStack.value.length)\n      redoStack.value.splice(0, redoStack.value.length);\n  };\n  const clear = () => {\n    undoStack.value.splice(0, undoStack.value.length);\n    redoStack.value.splice(0, redoStack.value.length);\n  };\n  const undo = () => {\n    const state = undoStack.value.shift();\n    if (state) {\n      redoStack.value.unshift(last.value);\n      _setSource(state);\n    }\n  };\n  const redo = () => {\n    const state = redoStack.value.shift();\n    if (state) {\n      undoStack.value.unshift(last.value);\n      _setSource(state);\n    }\n  };\n  const reset = () => {\n    _setSource(last.value);\n  };\n  const history = computed(() => [last.value, ...undoStack.value]);\n  const canUndo = computed(() => undoStack.value.length > 0);\n  const canRedo = computed(() => redoStack.value.length > 0);\n  return {\n    source,\n    undoStack,\n    redoStack,\n    last,\n    history,\n    canUndo,\n    canRedo,\n    clear,\n    commit,\n    reset,\n    undo,\n    redo\n  };\n}\n\nfunction useRefHistory(source, options = {}) {\n  const {\n    deep = false,\n    flush = \"pre\",\n    eventFilter,\n    shouldCommit = () => true\n  } = options;\n  const {\n    eventFilter: composedFilter,\n    pause,\n    resume: resumeTracking,\n    isActive: isTracking\n  } = pausableFilter(eventFilter);\n  let lastRawValue = source.value;\n  const {\n    ignoreUpdates,\n    ignorePrevAsyncUpdates,\n    stop\n  } = watchIgnorable(\n    source,\n    commit,\n    { deep, flush, eventFilter: composedFilter }\n  );\n  function setSource(source2, value) {\n    ignorePrevAsyncUpdates();\n    ignoreUpdates(() => {\n      source2.value = value;\n      lastRawValue = value;\n    });\n  }\n  const manualHistory = useManualRefHistory(source, { ...options, clone: options.clone || deep, setSource });\n  const { clear, commit: manualCommit } = manualHistory;\n  function commit() {\n    ignorePrevAsyncUpdates();\n    if (!shouldCommit(lastRawValue, source.value))\n      return;\n    lastRawValue = source.value;\n    manualCommit();\n  }\n  function resume(commitNow) {\n    resumeTracking();\n    if (commitNow)\n      commit();\n  }\n  function batch(fn) {\n    let canceled = false;\n    const cancel = () => canceled = true;\n    ignoreUpdates(() => {\n      fn(cancel);\n    });\n    if (!canceled)\n      commit();\n  }\n  function dispose() {\n    stop();\n    clear();\n  }\n  return {\n    ...manualHistory,\n    isTracking,\n    pause,\n    resume,\n    commit,\n    batch,\n    dispose\n  };\n}\n\nfunction useDebouncedRefHistory(source, options = {}) {\n  const filter = options.debounce ? debounceFilter(options.debounce) : void 0;\n  const history = useRefHistory(source, { ...options, eventFilter: filter });\n  return {\n    ...history\n  };\n}\n\nfunction useDeviceMotion(options = {}) {\n  const {\n    window = defaultWindow,\n    requestPermissions = false,\n    eventFilter = bypassFilter\n  } = options;\n  const isSupported = useSupported(() => typeof DeviceMotionEvent !== \"undefined\");\n  const requirePermissions = useSupported(() => isSupported.value && \"requestPermission\" in DeviceMotionEvent && typeof DeviceMotionEvent.requestPermission === \"function\");\n  const permissionGranted = shallowRef(false);\n  const acceleration = ref({ x: null, y: null, z: null });\n  const rotationRate = ref({ alpha: null, beta: null, gamma: null });\n  const interval = shallowRef(0);\n  const accelerationIncludingGravity = ref({\n    x: null,\n    y: null,\n    z: null\n  });\n  function init() {\n    if (window) {\n      const onDeviceMotion = createFilterWrapper(\n        eventFilter,\n        (event) => {\n          var _a, _b, _c, _d, _e, _f, _g, _h, _i;\n          acceleration.value = {\n            x: ((_a = event.acceleration) == null ? void 0 : _a.x) || null,\n            y: ((_b = event.acceleration) == null ? void 0 : _b.y) || null,\n            z: ((_c = event.acceleration) == null ? void 0 : _c.z) || null\n          };\n          accelerationIncludingGravity.value = {\n            x: ((_d = event.accelerationIncludingGravity) == null ? void 0 : _d.x) || null,\n            y: ((_e = event.accelerationIncludingGravity) == null ? void 0 : _e.y) || null,\n            z: ((_f = event.accelerationIncludingGravity) == null ? void 0 : _f.z) || null\n          };\n          rotationRate.value = {\n            alpha: ((_g = event.rotationRate) == null ? void 0 : _g.alpha) || null,\n            beta: ((_h = event.rotationRate) == null ? void 0 : _h.beta) || null,\n            gamma: ((_i = event.rotationRate) == null ? void 0 : _i.gamma) || null\n          };\n          interval.value = event.interval;\n        }\n      );\n      useEventListener(window, \"devicemotion\", onDeviceMotion, { passive: true });\n    }\n  }\n  const ensurePermissions = async () => {\n    if (!requirePermissions.value)\n      permissionGranted.value = true;\n    if (permissionGranted.value)\n      return;\n    if (requirePermissions.value) {\n      const requestPermission = DeviceMotionEvent.requestPermission;\n      try {\n        const response = await requestPermission();\n        if (response === \"granted\") {\n          permissionGranted.value = true;\n          init();\n        }\n      } catch (error) {\n        console.error(error);\n      }\n    }\n  };\n  if (isSupported.value) {\n    if (requestPermissions && requirePermissions.value) {\n      ensurePermissions().then(() => init());\n    } else {\n      init();\n    }\n  }\n  return {\n    acceleration,\n    accelerationIncludingGravity,\n    rotationRate,\n    interval,\n    isSupported,\n    requirePermissions,\n    ensurePermissions,\n    permissionGranted\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useDeviceOrientation(options = {}) {\n  const { window = defaultWindow } = options;\n  const isSupported = useSupported(() => window && \"DeviceOrientationEvent\" in window);\n  const isAbsolute = shallowRef(false);\n  const alpha = shallowRef(null);\n  const beta = shallowRef(null);\n  const gamma = shallowRef(null);\n  if (window && isSupported.value) {\n    useEventListener(window, \"deviceorientation\", (event) => {\n      isAbsolute.value = event.absolute;\n      alpha.value = event.alpha;\n      beta.value = event.beta;\n      gamma.value = event.gamma;\n    }, { passive: true });\n  }\n  return {\n    isSupported,\n    isAbsolute,\n    alpha,\n    beta,\n    gamma\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useDevicePixelRatio(options = {}) {\n  const {\n    window = defaultWindow\n  } = options;\n  const pixelRatio = shallowRef(1);\n  const query = useMediaQuery(() => `(resolution: ${pixelRatio.value}dppx)`, options);\n  let stop = noop;\n  if (window) {\n    stop = watchImmediate(query, () => pixelRatio.value = window.devicePixelRatio);\n  }\n  return {\n    pixelRatio: readonly(pixelRatio),\n    stop\n  };\n}\n\nfunction useDevicesList(options = {}) {\n  const {\n    navigator = defaultNavigator,\n    requestPermissions = false,\n    constraints = { audio: true, video: true },\n    onUpdated\n  } = options;\n  const devices = ref([]);\n  const videoInputs = computed(() => devices.value.filter((i) => i.kind === \"videoinput\"));\n  const audioInputs = computed(() => devices.value.filter((i) => i.kind === \"audioinput\"));\n  const audioOutputs = computed(() => devices.value.filter((i) => i.kind === \"audiooutput\"));\n  const isSupported = useSupported(() => navigator && navigator.mediaDevices && navigator.mediaDevices.enumerateDevices);\n  const permissionGranted = shallowRef(false);\n  let stream;\n  async function update() {\n    if (!isSupported.value)\n      return;\n    devices.value = await navigator.mediaDevices.enumerateDevices();\n    onUpdated == null ? void 0 : onUpdated(devices.value);\n    if (stream) {\n      stream.getTracks().forEach((t) => t.stop());\n      stream = null;\n    }\n  }\n  async function ensurePermissions() {\n    const deviceName = constraints.video ? \"camera\" : \"microphone\";\n    if (!isSupported.value)\n      return false;\n    if (permissionGranted.value)\n      return true;\n    const { state, query } = usePermission(deviceName, { controls: true });\n    await query();\n    if (state.value !== \"granted\") {\n      let granted = true;\n      try {\n        const allDevices = await navigator.mediaDevices.enumerateDevices();\n        const hasCamera = allDevices.some((device) => device.kind === \"videoinput\");\n        const hasMicrophone = allDevices.some((device) => device.kind === \"audioinput\" || device.kind === \"audiooutput\");\n        constraints.video = hasCamera ? constraints.video : false;\n        constraints.audio = hasMicrophone ? constraints.audio : false;\n        stream = await navigator.mediaDevices.getUserMedia(constraints);\n      } catch (e) {\n        stream = null;\n        granted = false;\n      }\n      update();\n      permissionGranted.value = granted;\n    } else {\n      permissionGranted.value = true;\n    }\n    return permissionGranted.value;\n  }\n  if (isSupported.value) {\n    if (requestPermissions)\n      ensurePermissions();\n    useEventListener(navigator.mediaDevices, \"devicechange\", update, { passive: true });\n    update();\n  }\n  return {\n    devices,\n    ensurePermissions,\n    permissionGranted,\n    videoInputs,\n    audioInputs,\n    audioOutputs,\n    isSupported\n  };\n}\n\nfunction useDisplayMedia(options = {}) {\n  var _a;\n  const enabled = shallowRef((_a = options.enabled) != null ? _a : false);\n  const video = options.video;\n  const audio = options.audio;\n  const { navigator = defaultNavigator } = options;\n  const isSupported = useSupported(() => {\n    var _a2;\n    return (_a2 = navigator == null ? void 0 : navigator.mediaDevices) == null ? void 0 : _a2.getDisplayMedia;\n  });\n  const constraint = { audio, video };\n  const stream = shallowRef();\n  async function _start() {\n    var _a2;\n    if (!isSupported.value || stream.value)\n      return;\n    stream.value = await navigator.mediaDevices.getDisplayMedia(constraint);\n    (_a2 = stream.value) == null ? void 0 : _a2.getTracks().forEach((t) => useEventListener(t, \"ended\", stop, { passive: true }));\n    return stream.value;\n  }\n  async function _stop() {\n    var _a2;\n    (_a2 = stream.value) == null ? void 0 : _a2.getTracks().forEach((t) => t.stop());\n    stream.value = void 0;\n  }\n  function stop() {\n    _stop();\n    enabled.value = false;\n  }\n  async function start() {\n    await _start();\n    if (stream.value)\n      enabled.value = true;\n    return stream.value;\n  }\n  watch(\n    enabled,\n    (v) => {\n      if (v)\n        _start();\n      else\n        _stop();\n    },\n    { immediate: true }\n  );\n  return {\n    isSupported,\n    stream,\n    start,\n    stop,\n    enabled\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useDocumentVisibility(options = {}) {\n  const { document = defaultDocument } = options;\n  if (!document)\n    return shallowRef(\"visible\");\n  const visibility = shallowRef(document.visibilityState);\n  useEventListener(document, \"visibilitychange\", () => {\n    visibility.value = document.visibilityState;\n  }, { passive: true });\n  return visibility;\n}\n\nfunction useDraggable(target, options = {}) {\n  var _a;\n  const {\n    pointerTypes,\n    preventDefault,\n    stopPropagation,\n    exact,\n    onMove,\n    onEnd,\n    onStart,\n    initialValue,\n    axis = \"both\",\n    draggingElement = defaultWindow,\n    containerElement,\n    handle: draggingHandle = target,\n    buttons = [0]\n  } = options;\n  const position = ref(\n    (_a = toValue(initialValue)) != null ? _a : { x: 0, y: 0 }\n  );\n  const pressedDelta = ref();\n  const filterEvent = (e) => {\n    if (pointerTypes)\n      return pointerTypes.includes(e.pointerType);\n    return true;\n  };\n  const handleEvent = (e) => {\n    if (toValue(preventDefault))\n      e.preventDefault();\n    if (toValue(stopPropagation))\n      e.stopPropagation();\n  };\n  const start = (e) => {\n    var _a2;\n    if (!toValue(buttons).includes(e.button))\n      return;\n    if (toValue(options.disabled) || !filterEvent(e))\n      return;\n    if (toValue(exact) && e.target !== toValue(target))\n      return;\n    const container = toValue(containerElement);\n    const containerRect = (_a2 = container == null ? void 0 : container.getBoundingClientRect) == null ? void 0 : _a2.call(container);\n    const targetRect = toValue(target).getBoundingClientRect();\n    const pos = {\n      x: e.clientX - (container ? targetRect.left - containerRect.left + container.scrollLeft : targetRect.left),\n      y: e.clientY - (container ? targetRect.top - containerRect.top + container.scrollTop : targetRect.top)\n    };\n    if ((onStart == null ? void 0 : onStart(pos, e)) === false)\n      return;\n    pressedDelta.value = pos;\n    handleEvent(e);\n  };\n  const move = (e) => {\n    if (toValue(options.disabled) || !filterEvent(e))\n      return;\n    if (!pressedDelta.value)\n      return;\n    const container = toValue(containerElement);\n    const targetRect = toValue(target).getBoundingClientRect();\n    let { x, y } = position.value;\n    if (axis === \"x\" || axis === \"both\") {\n      x = e.clientX - pressedDelta.value.x;\n      if (container)\n        x = Math.min(Math.max(0, x), container.scrollWidth - targetRect.width);\n    }\n    if (axis === \"y\" || axis === \"both\") {\n      y = e.clientY - pressedDelta.value.y;\n      if (container)\n        y = Math.min(Math.max(0, y), container.scrollHeight - targetRect.height);\n    }\n    position.value = {\n      x,\n      y\n    };\n    onMove == null ? void 0 : onMove(position.value, e);\n    handleEvent(e);\n  };\n  const end = (e) => {\n    if (toValue(options.disabled) || !filterEvent(e))\n      return;\n    if (!pressedDelta.value)\n      return;\n    pressedDelta.value = void 0;\n    onEnd == null ? void 0 : onEnd(position.value, e);\n    handleEvent(e);\n  };\n  if (isClient) {\n    const config = () => {\n      var _a2;\n      return {\n        capture: (_a2 = options.capture) != null ? _a2 : true,\n        passive: !toValue(preventDefault)\n      };\n    };\n    useEventListener(draggingHandle, \"pointerdown\", start, config);\n    useEventListener(draggingElement, \"pointermove\", move, config);\n    useEventListener(draggingElement, \"pointerup\", end, config);\n  }\n  return {\n    ...toRefs(position),\n    position,\n    isDragging: computed(() => !!pressedDelta.value),\n    style: computed(\n      () => `left:${position.value.x}px;top:${position.value.y}px;`\n    )\n  };\n}\n\nfunction useDropZone(target, options = {}) {\n  var _a, _b;\n  const isOverDropZone = shallowRef(false);\n  const files = shallowRef(null);\n  let counter = 0;\n  let isValid = true;\n  if (isClient) {\n    const _options = typeof options === \"function\" ? { onDrop: options } : options;\n    const multiple = (_a = _options.multiple) != null ? _a : true;\n    const preventDefaultForUnhandled = (_b = _options.preventDefaultForUnhandled) != null ? _b : false;\n    const getFiles = (event) => {\n      var _a2, _b2;\n      const list = Array.from((_b2 = (_a2 = event.dataTransfer) == null ? void 0 : _a2.files) != null ? _b2 : []);\n      return list.length === 0 ? null : multiple ? list : [list[0]];\n    };\n    const checkDataTypes = (types) => {\n      const dataTypes = unref(_options.dataTypes);\n      if (typeof dataTypes === \"function\")\n        return dataTypes(types);\n      if (!(dataTypes == null ? void 0 : dataTypes.length))\n        return true;\n      if (types.length === 0)\n        return false;\n      return types.every(\n        (type) => dataTypes.some((allowedType) => type.includes(allowedType))\n      );\n    };\n    const checkValidity = (items) => {\n      const types = Array.from(items != null ? items : []).map((item) => item.type);\n      const dataTypesValid = checkDataTypes(types);\n      const multipleFilesValid = multiple || items.length <= 1;\n      return dataTypesValid && multipleFilesValid;\n    };\n    const isSafari = () => /^(?:(?!chrome|android).)*safari/i.test(navigator.userAgent) && !(\"chrome\" in window);\n    const handleDragEvent = (event, eventType) => {\n      var _a2, _b2, _c, _d, _e, _f;\n      const dataTransferItemList = (_a2 = event.dataTransfer) == null ? void 0 : _a2.items;\n      isValid = (_b2 = dataTransferItemList && checkValidity(dataTransferItemList)) != null ? _b2 : false;\n      if (preventDefaultForUnhandled) {\n        event.preventDefault();\n      }\n      if (!isSafari() && !isValid) {\n        if (event.dataTransfer) {\n          event.dataTransfer.dropEffect = \"none\";\n        }\n        return;\n      }\n      event.preventDefault();\n      if (event.dataTransfer) {\n        event.dataTransfer.dropEffect = \"copy\";\n      }\n      const currentFiles = getFiles(event);\n      switch (eventType) {\n        case \"enter\":\n          counter += 1;\n          isOverDropZone.value = true;\n          (_c = _options.onEnter) == null ? void 0 : _c.call(_options, null, event);\n          break;\n        case \"over\":\n          (_d = _options.onOver) == null ? void 0 : _d.call(_options, null, event);\n          break;\n        case \"leave\":\n          counter -= 1;\n          if (counter === 0)\n            isOverDropZone.value = false;\n          (_e = _options.onLeave) == null ? void 0 : _e.call(_options, null, event);\n          break;\n        case \"drop\":\n          counter = 0;\n          isOverDropZone.value = false;\n          if (isValid) {\n            files.value = currentFiles;\n            (_f = _options.onDrop) == null ? void 0 : _f.call(_options, currentFiles, event);\n          }\n          break;\n      }\n    };\n    useEventListener(target, \"dragenter\", (event) => handleDragEvent(event, \"enter\"));\n    useEventListener(target, \"dragover\", (event) => handleDragEvent(event, \"over\"));\n    useEventListener(target, \"dragleave\", (event) => handleDragEvent(event, \"leave\"));\n    useEventListener(target, \"drop\", (event) => handleDragEvent(event, \"drop\"));\n  }\n  return {\n    files,\n    isOverDropZone\n  };\n}\n\nfunction useResizeObserver(target, callback, options = {}) {\n  const { window = defaultWindow, ...observerOptions } = options;\n  let observer;\n  const isSupported = useSupported(() => window && \"ResizeObserver\" in window);\n  const cleanup = () => {\n    if (observer) {\n      observer.disconnect();\n      observer = void 0;\n    }\n  };\n  const targets = computed(() => {\n    const _targets = toValue(target);\n    return Array.isArray(_targets) ? _targets.map((el) => unrefElement(el)) : [unrefElement(_targets)];\n  });\n  const stopWatch = watch(\n    targets,\n    (els) => {\n      cleanup();\n      if (isSupported.value && window) {\n        observer = new ResizeObserver(callback);\n        for (const _el of els) {\n          if (_el)\n            observer.observe(_el, observerOptions);\n        }\n      }\n    },\n    { immediate: true, flush: \"post\" }\n  );\n  const stop = () => {\n    cleanup();\n    stopWatch();\n  };\n  tryOnScopeDispose(stop);\n  return {\n    isSupported,\n    stop\n  };\n}\n\nfunction useElementBounding(target, options = {}) {\n  const {\n    reset = true,\n    windowResize = true,\n    windowScroll = true,\n    immediate = true,\n    updateTiming = \"sync\"\n  } = options;\n  const height = shallowRef(0);\n  const bottom = shallowRef(0);\n  const left = shallowRef(0);\n  const right = shallowRef(0);\n  const top = shallowRef(0);\n  const width = shallowRef(0);\n  const x = shallowRef(0);\n  const y = shallowRef(0);\n  function recalculate() {\n    const el = unrefElement(target);\n    if (!el) {\n      if (reset) {\n        height.value = 0;\n        bottom.value = 0;\n        left.value = 0;\n        right.value = 0;\n        top.value = 0;\n        width.value = 0;\n        x.value = 0;\n        y.value = 0;\n      }\n      return;\n    }\n    const rect = el.getBoundingClientRect();\n    height.value = rect.height;\n    bottom.value = rect.bottom;\n    left.value = rect.left;\n    right.value = rect.right;\n    top.value = rect.top;\n    width.value = rect.width;\n    x.value = rect.x;\n    y.value = rect.y;\n  }\n  function update() {\n    if (updateTiming === \"sync\")\n      recalculate();\n    else if (updateTiming === \"next-frame\")\n      requestAnimationFrame(() => recalculate());\n  }\n  useResizeObserver(target, update);\n  watch(() => unrefElement(target), (ele) => !ele && update());\n  useMutationObserver(target, update, {\n    attributeFilter: [\"style\", \"class\"]\n  });\n  if (windowScroll)\n    useEventListener(\"scroll\", update, { capture: true, passive: true });\n  if (windowResize)\n    useEventListener(\"resize\", update, { passive: true });\n  tryOnMounted(() => {\n    if (immediate)\n      update();\n  });\n  return {\n    height,\n    bottom,\n    left,\n    right,\n    top,\n    width,\n    x,\n    y,\n    update\n  };\n}\n\nfunction useElementByPoint(options) {\n  const {\n    x,\n    y,\n    document = defaultDocument,\n    multiple,\n    interval = \"requestAnimationFrame\",\n    immediate = true\n  } = options;\n  const isSupported = useSupported(() => {\n    if (toValue(multiple))\n      return document && \"elementsFromPoint\" in document;\n    return document && \"elementFromPoint\" in document;\n  });\n  const element = shallowRef(null);\n  const cb = () => {\n    var _a, _b;\n    element.value = toValue(multiple) ? (_a = document == null ? void 0 : document.elementsFromPoint(toValue(x), toValue(y))) != null ? _a : [] : (_b = document == null ? void 0 : document.elementFromPoint(toValue(x), toValue(y))) != null ? _b : null;\n  };\n  const controls = interval === \"requestAnimationFrame\" ? useRafFn(cb, { immediate }) : useIntervalFn(cb, interval, { immediate });\n  return {\n    isSupported,\n    element,\n    ...controls\n  };\n}\n\nfunction useElementHover(el, options = {}) {\n  const {\n    delayEnter = 0,\n    delayLeave = 0,\n    triggerOnRemoval = false,\n    window = defaultWindow\n  } = options;\n  const isHovered = shallowRef(false);\n  let timer;\n  const toggle = (entering) => {\n    const delay = entering ? delayEnter : delayLeave;\n    if (timer) {\n      clearTimeout(timer);\n      timer = void 0;\n    }\n    if (delay)\n      timer = setTimeout(() => isHovered.value = entering, delay);\n    else\n      isHovered.value = entering;\n  };\n  if (!window)\n    return isHovered;\n  useEventListener(el, \"mouseenter\", () => toggle(true), { passive: true });\n  useEventListener(el, \"mouseleave\", () => toggle(false), { passive: true });\n  if (triggerOnRemoval) {\n    onElementRemoval(\n      computed(() => unrefElement(el)),\n      () => toggle(false)\n    );\n  }\n  return isHovered;\n}\n\nfunction useElementSize(target, initialSize = { width: 0, height: 0 }, options = {}) {\n  const { window = defaultWindow, box = \"content-box\" } = options;\n  const isSVG = computed(() => {\n    var _a, _b;\n    return (_b = (_a = unrefElement(target)) == null ? void 0 : _a.namespaceURI) == null ? void 0 : _b.includes(\"svg\");\n  });\n  const width = shallowRef(initialSize.width);\n  const height = shallowRef(initialSize.height);\n  const { stop: stop1 } = useResizeObserver(\n    target,\n    ([entry]) => {\n      const boxSize = box === \"border-box\" ? entry.borderBoxSize : box === \"content-box\" ? entry.contentBoxSize : entry.devicePixelContentBoxSize;\n      if (window && isSVG.value) {\n        const $elem = unrefElement(target);\n        if ($elem) {\n          const rect = $elem.getBoundingClientRect();\n          width.value = rect.width;\n          height.value = rect.height;\n        }\n      } else {\n        if (boxSize) {\n          const formatBoxSize = toArray(boxSize);\n          width.value = formatBoxSize.reduce((acc, { inlineSize }) => acc + inlineSize, 0);\n          height.value = formatBoxSize.reduce((acc, { blockSize }) => acc + blockSize, 0);\n        } else {\n          width.value = entry.contentRect.width;\n          height.value = entry.contentRect.height;\n        }\n      }\n    },\n    options\n  );\n  tryOnMounted(() => {\n    const ele = unrefElement(target);\n    if (ele) {\n      width.value = \"offsetWidth\" in ele ? ele.offsetWidth : initialSize.width;\n      height.value = \"offsetHeight\" in ele ? ele.offsetHeight : initialSize.height;\n    }\n  });\n  const stop2 = watch(\n    () => unrefElement(target),\n    (ele) => {\n      width.value = ele ? initialSize.width : 0;\n      height.value = ele ? initialSize.height : 0;\n    }\n  );\n  function stop() {\n    stop1();\n    stop2();\n  }\n  return {\n    width,\n    height,\n    stop\n  };\n}\n\nfunction useIntersectionObserver(target, callback, options = {}) {\n  const {\n    root,\n    rootMargin = \"0px\",\n    threshold = 0,\n    window = defaultWindow,\n    immediate = true\n  } = options;\n  const isSupported = useSupported(() => window && \"IntersectionObserver\" in window);\n  const targets = computed(() => {\n    const _target = toValue(target);\n    return toArray(_target).map(unrefElement).filter(notNullish);\n  });\n  let cleanup = noop;\n  const isActive = shallowRef(immediate);\n  const stopWatch = isSupported.value ? watch(\n    () => [targets.value, unrefElement(root), isActive.value],\n    ([targets2, root2]) => {\n      cleanup();\n      if (!isActive.value)\n        return;\n      if (!targets2.length)\n        return;\n      const observer = new IntersectionObserver(\n        callback,\n        {\n          root: unrefElement(root2),\n          rootMargin,\n          threshold\n        }\n      );\n      targets2.forEach((el) => el && observer.observe(el));\n      cleanup = () => {\n        observer.disconnect();\n        cleanup = noop;\n      };\n    },\n    { immediate, flush: \"post\" }\n  ) : noop;\n  const stop = () => {\n    cleanup();\n    stopWatch();\n    isActive.value = false;\n  };\n  tryOnScopeDispose(stop);\n  return {\n    isSupported,\n    isActive,\n    pause() {\n      cleanup();\n      isActive.value = false;\n    },\n    resume() {\n      isActive.value = true;\n    },\n    stop\n  };\n}\n\nfunction useElementVisibility(element, options = {}) {\n  const {\n    window = defaultWindow,\n    scrollTarget,\n    threshold = 0,\n    rootMargin,\n    once = false\n  } = options;\n  const elementIsVisible = shallowRef(false);\n  const { stop } = useIntersectionObserver(\n    element,\n    (intersectionObserverEntries) => {\n      let isIntersecting = elementIsVisible.value;\n      let latestTime = 0;\n      for (const entry of intersectionObserverEntries) {\n        if (entry.time >= latestTime) {\n          latestTime = entry.time;\n          isIntersecting = entry.isIntersecting;\n        }\n      }\n      elementIsVisible.value = isIntersecting;\n      if (once) {\n        watchOnce(elementIsVisible, () => {\n          stop();\n        });\n      }\n    },\n    {\n      root: scrollTarget,\n      window,\n      threshold,\n      rootMargin: toValue(rootMargin)\n    }\n  );\n  return elementIsVisible;\n}\n\nconst events = /* @__PURE__ */ new Map();\n\n// @__NO_SIDE_EFFECTS__\nfunction useEventBus(key) {\n  const scope = getCurrentScope();\n  function on(listener) {\n    var _a;\n    const listeners = events.get(key) || /* @__PURE__ */ new Set();\n    listeners.add(listener);\n    events.set(key, listeners);\n    const _off = () => off(listener);\n    (_a = scope == null ? void 0 : scope.cleanups) == null ? void 0 : _a.push(_off);\n    return _off;\n  }\n  function once(listener) {\n    function _listener(...args) {\n      off(_listener);\n      listener(...args);\n    }\n    return on(_listener);\n  }\n  function off(listener) {\n    const listeners = events.get(key);\n    if (!listeners)\n      return;\n    listeners.delete(listener);\n    if (!listeners.size)\n      reset();\n  }\n  function reset() {\n    events.delete(key);\n  }\n  function emit(event, payload) {\n    var _a;\n    (_a = events.get(key)) == null ? void 0 : _a.forEach((v) => v(event, payload));\n  }\n  return { on, once, off, emit, reset };\n}\n\nfunction resolveNestedOptions$1(options) {\n  if (options === true)\n    return {};\n  return options;\n}\nfunction useEventSource(url, events = [], options = {}) {\n  const event = shallowRef(null);\n  const data = shallowRef(null);\n  const status = shallowRef(\"CONNECTING\");\n  const eventSource = ref(null);\n  const error = shallowRef(null);\n  const urlRef = toRef(url);\n  const lastEventId = shallowRef(null);\n  let explicitlyClosed = false;\n  let retried = 0;\n  const {\n    withCredentials = false,\n    immediate = true,\n    autoConnect = true,\n    autoReconnect,\n    serializer = {\n      read: (v) => v\n    }\n  } = options;\n  const close = () => {\n    if (isClient && eventSource.value) {\n      eventSource.value.close();\n      eventSource.value = null;\n      status.value = \"CLOSED\";\n      explicitlyClosed = true;\n    }\n  };\n  const _init = () => {\n    if (explicitlyClosed || typeof urlRef.value === \"undefined\")\n      return;\n    const es = new EventSource(urlRef.value, { withCredentials });\n    status.value = \"CONNECTING\";\n    eventSource.value = es;\n    es.onopen = () => {\n      status.value = \"OPEN\";\n      error.value = null;\n    };\n    es.onerror = (e) => {\n      status.value = \"CLOSED\";\n      error.value = e;\n      if (es.readyState === 2 && !explicitlyClosed && autoReconnect) {\n        es.close();\n        const {\n          retries = -1,\n          delay = 1e3,\n          onFailed\n        } = resolveNestedOptions$1(autoReconnect);\n        retried += 1;\n        if (typeof retries === \"number\" && (retries < 0 || retried < retries))\n          setTimeout(_init, delay);\n        else if (typeof retries === \"function\" && retries())\n          setTimeout(_init, delay);\n        else\n          onFailed == null ? void 0 : onFailed();\n      }\n    };\n    es.onmessage = (e) => {\n      var _a;\n      event.value = null;\n      data.value = (_a = serializer.read(e.data)) != null ? _a : null;\n      lastEventId.value = e.lastEventId;\n    };\n    for (const event_name of events) {\n      useEventListener(es, event_name, (e) => {\n        var _a, _b;\n        event.value = event_name;\n        data.value = (_a = serializer.read(e.data)) != null ? _a : null;\n        lastEventId.value = (_b = e.lastEventId) != null ? _b : null;\n      }, { passive: true });\n    }\n  };\n  const open = () => {\n    if (!isClient)\n      return;\n    close();\n    explicitlyClosed = false;\n    retried = 0;\n    _init();\n  };\n  if (immediate)\n    open();\n  if (autoConnect)\n    watch(urlRef, open);\n  tryOnScopeDispose(close);\n  return {\n    eventSource,\n    event,\n    data,\n    status,\n    error,\n    open,\n    close,\n    lastEventId\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useEyeDropper(options = {}) {\n  const { initialValue = \"\" } = options;\n  const isSupported = useSupported(() => typeof window !== \"undefined\" && \"EyeDropper\" in window);\n  const sRGBHex = shallowRef(initialValue);\n  async function open(openOptions) {\n    if (!isSupported.value)\n      return;\n    const eyeDropper = new window.EyeDropper();\n    const result = await eyeDropper.open(openOptions);\n    sRGBHex.value = result.sRGBHex;\n    return result;\n  }\n  return { isSupported, sRGBHex, open };\n}\n\nfunction useFavicon(newIcon = null, options = {}) {\n  const {\n    baseUrl = \"\",\n    rel = \"icon\",\n    document = defaultDocument\n  } = options;\n  const favicon = toRef(newIcon);\n  const applyIcon = (icon) => {\n    const elements = document == null ? void 0 : document.head.querySelectorAll(`link[rel*=\"${rel}\"]`);\n    if (!elements || elements.length === 0) {\n      const link = document == null ? void 0 : document.createElement(\"link\");\n      if (link) {\n        link.rel = rel;\n        link.href = `${baseUrl}${icon}`;\n        link.type = `image/${icon.split(\".\").pop()}`;\n        document == null ? void 0 : document.head.append(link);\n      }\n      return;\n    }\n    elements == null ? void 0 : elements.forEach((el) => el.href = `${baseUrl}${icon}`);\n  };\n  watch(\n    favicon,\n    (i, o) => {\n      if (typeof i === \"string\" && i !== o)\n        applyIcon(i);\n    },\n    { immediate: true }\n  );\n  return favicon;\n}\n\nconst payloadMapping = {\n  json: \"application/json\",\n  text: \"text/plain\"\n};\nfunction isFetchOptions(obj) {\n  return obj && containsProp(obj, \"immediate\", \"refetch\", \"initialData\", \"timeout\", \"beforeFetch\", \"afterFetch\", \"onFetchError\", \"fetch\", \"updateDataOnError\");\n}\nconst reAbsolute = /^(?:[a-z][a-z\\d+\\-.]*:)?\\/\\//i;\nfunction isAbsoluteURL(url) {\n  return reAbsolute.test(url);\n}\nfunction headersToObject(headers) {\n  if (typeof Headers !== \"undefined\" && headers instanceof Headers)\n    return Object.fromEntries(headers.entries());\n  return headers;\n}\nfunction combineCallbacks(combination, ...callbacks) {\n  if (combination === \"overwrite\") {\n    return async (ctx) => {\n      let callback;\n      for (let i = callbacks.length - 1; i >= 0; i--) {\n        if (callbacks[i] != null) {\n          callback = callbacks[i];\n          break;\n        }\n      }\n      if (callback)\n        return { ...ctx, ...await callback(ctx) };\n      return ctx;\n    };\n  } else {\n    return async (ctx) => {\n      for (const callback of callbacks) {\n        if (callback)\n          ctx = { ...ctx, ...await callback(ctx) };\n      }\n      return ctx;\n    };\n  }\n}\nfunction createFetch(config = {}) {\n  const _combination = config.combination || \"chain\";\n  const _options = config.options || {};\n  const _fetchOptions = config.fetchOptions || {};\n  function useFactoryFetch(url, ...args) {\n    const computedUrl = computed(() => {\n      const baseUrl = toValue(config.baseUrl);\n      const targetUrl = toValue(url);\n      return baseUrl && !isAbsoluteURL(targetUrl) ? joinPaths(baseUrl, targetUrl) : targetUrl;\n    });\n    let options = _options;\n    let fetchOptions = _fetchOptions;\n    if (args.length > 0) {\n      if (isFetchOptions(args[0])) {\n        options = {\n          ...options,\n          ...args[0],\n          beforeFetch: combineCallbacks(_combination, _options.beforeFetch, args[0].beforeFetch),\n          afterFetch: combineCallbacks(_combination, _options.afterFetch, args[0].afterFetch),\n          onFetchError: combineCallbacks(_combination, _options.onFetchError, args[0].onFetchError)\n        };\n      } else {\n        fetchOptions = {\n          ...fetchOptions,\n          ...args[0],\n          headers: {\n            ...headersToObject(fetchOptions.headers) || {},\n            ...headersToObject(args[0].headers) || {}\n          }\n        };\n      }\n    }\n    if (args.length > 1 && isFetchOptions(args[1])) {\n      options = {\n        ...options,\n        ...args[1],\n        beforeFetch: combineCallbacks(_combination, _options.beforeFetch, args[1].beforeFetch),\n        afterFetch: combineCallbacks(_combination, _options.afterFetch, args[1].afterFetch),\n        onFetchError: combineCallbacks(_combination, _options.onFetchError, args[1].onFetchError)\n      };\n    }\n    return useFetch(computedUrl, fetchOptions, options);\n  }\n  return useFactoryFetch;\n}\nfunction useFetch(url, ...args) {\n  var _a, _b;\n  const supportsAbort = typeof AbortController === \"function\";\n  let fetchOptions = {};\n  let options = {\n    immediate: true,\n    refetch: false,\n    timeout: 0,\n    updateDataOnError: false\n  };\n  const config = {\n    method: \"GET\",\n    type: \"text\",\n    payload: void 0\n  };\n  if (args.length > 0) {\n    if (isFetchOptions(args[0]))\n      options = { ...options, ...args[0] };\n    else\n      fetchOptions = args[0];\n  }\n  if (args.length > 1) {\n    if (isFetchOptions(args[1]))\n      options = { ...options, ...args[1] };\n  }\n  const {\n    fetch = (_b = (_a = defaultWindow) == null ? void 0 : _a.fetch) != null ? _b : globalThis == null ? void 0 : globalThis.fetch,\n    initialData,\n    timeout\n  } = options;\n  const responseEvent = createEventHook();\n  const errorEvent = createEventHook();\n  const finallyEvent = createEventHook();\n  const isFinished = shallowRef(false);\n  const isFetching = shallowRef(false);\n  const aborted = shallowRef(false);\n  const statusCode = shallowRef(null);\n  const response = shallowRef(null);\n  const error = shallowRef(null);\n  const data = shallowRef(initialData || null);\n  const canAbort = computed(() => supportsAbort && isFetching.value);\n  let controller;\n  let timer;\n  const abort = (reason) => {\n    if (supportsAbort) {\n      controller == null ? void 0 : controller.abort(reason);\n      controller = new AbortController();\n      controller.signal.onabort = () => aborted.value = true;\n      fetchOptions = {\n        ...fetchOptions,\n        signal: controller.signal\n      };\n    }\n  };\n  const loading = (isLoading) => {\n    isFetching.value = isLoading;\n    isFinished.value = !isLoading;\n  };\n  if (timeout)\n    timer = useTimeoutFn(abort, timeout, { immediate: false });\n  let executeCounter = 0;\n  const execute = async (throwOnFailed = false) => {\n    var _a2, _b2;\n    abort();\n    loading(true);\n    error.value = null;\n    statusCode.value = null;\n    aborted.value = false;\n    executeCounter += 1;\n    const currentExecuteCounter = executeCounter;\n    const defaultFetchOptions = {\n      method: config.method,\n      headers: {}\n    };\n    const payload = toValue(config.payload);\n    if (payload) {\n      const headers = headersToObject(defaultFetchOptions.headers);\n      const proto = Object.getPrototypeOf(payload);\n      if (!config.payloadType && payload && (proto === Object.prototype || Array.isArray(proto)) && !(payload instanceof FormData))\n        config.payloadType = \"json\";\n      if (config.payloadType)\n        headers[\"Content-Type\"] = (_a2 = payloadMapping[config.payloadType]) != null ? _a2 : config.payloadType;\n      defaultFetchOptions.body = config.payloadType === \"json\" ? JSON.stringify(payload) : payload;\n    }\n    let isCanceled = false;\n    const context = {\n      url: toValue(url),\n      options: {\n        ...defaultFetchOptions,\n        ...fetchOptions\n      },\n      cancel: () => {\n        isCanceled = true;\n      }\n    };\n    if (options.beforeFetch)\n      Object.assign(context, await options.beforeFetch(context));\n    if (isCanceled || !fetch) {\n      loading(false);\n      return Promise.resolve(null);\n    }\n    let responseData = null;\n    if (timer)\n      timer.start();\n    return fetch(\n      context.url,\n      {\n        ...defaultFetchOptions,\n        ...context.options,\n        headers: {\n          ...headersToObject(defaultFetchOptions.headers),\n          ...headersToObject((_b2 = context.options) == null ? void 0 : _b2.headers)\n        }\n      }\n    ).then(async (fetchResponse) => {\n      response.value = fetchResponse;\n      statusCode.value = fetchResponse.status;\n      responseData = await fetchResponse.clone()[config.type]();\n      if (!fetchResponse.ok) {\n        data.value = initialData || null;\n        throw new Error(fetchResponse.statusText);\n      }\n      if (options.afterFetch) {\n        ({ data: responseData } = await options.afterFetch({\n          data: responseData,\n          response: fetchResponse,\n          context,\n          execute\n        }));\n      }\n      data.value = responseData;\n      responseEvent.trigger(fetchResponse);\n      return fetchResponse;\n    }).catch(async (fetchError) => {\n      let errorData = fetchError.message || fetchError.name;\n      if (options.onFetchError) {\n        ({ error: errorData, data: responseData } = await options.onFetchError({\n          data: responseData,\n          error: fetchError,\n          response: response.value,\n          context,\n          execute\n        }));\n      }\n      error.value = errorData;\n      if (options.updateDataOnError)\n        data.value = responseData;\n      errorEvent.trigger(fetchError);\n      if (throwOnFailed)\n        throw fetchError;\n      return null;\n    }).finally(() => {\n      if (currentExecuteCounter === executeCounter)\n        loading(false);\n      if (timer)\n        timer.stop();\n      finallyEvent.trigger(null);\n    });\n  };\n  const refetch = toRef(options.refetch);\n  watch(\n    [\n      refetch,\n      toRef(url)\n    ],\n    ([refetch2]) => refetch2 && execute(),\n    { deep: true }\n  );\n  const shell = {\n    isFinished: readonly(isFinished),\n    isFetching: readonly(isFetching),\n    statusCode,\n    response,\n    error,\n    data,\n    canAbort,\n    aborted,\n    abort,\n    execute,\n    onFetchResponse: responseEvent.on,\n    onFetchError: errorEvent.on,\n    onFetchFinally: finallyEvent.on,\n    // method\n    get: setMethod(\"GET\"),\n    put: setMethod(\"PUT\"),\n    post: setMethod(\"POST\"),\n    delete: setMethod(\"DELETE\"),\n    patch: setMethod(\"PATCH\"),\n    head: setMethod(\"HEAD\"),\n    options: setMethod(\"OPTIONS\"),\n    // type\n    json: setType(\"json\"),\n    text: setType(\"text\"),\n    blob: setType(\"blob\"),\n    arrayBuffer: setType(\"arrayBuffer\"),\n    formData: setType(\"formData\")\n  };\n  function setMethod(method) {\n    return (payload, payloadType) => {\n      if (!isFetching.value) {\n        config.method = method;\n        config.payload = payload;\n        config.payloadType = payloadType;\n        if (isRef(config.payload)) {\n          watch(\n            [\n              refetch,\n              toRef(config.payload)\n            ],\n            ([refetch2]) => refetch2 && execute(),\n            { deep: true }\n          );\n        }\n        return {\n          ...shell,\n          then(onFulfilled, onRejected) {\n            return waitUntilFinished().then(onFulfilled, onRejected);\n          }\n        };\n      }\n      return void 0;\n    };\n  }\n  function waitUntilFinished() {\n    return new Promise((resolve, reject) => {\n      until(isFinished).toBe(true).then(() => resolve(shell)).catch(reject);\n    });\n  }\n  function setType(type) {\n    return () => {\n      if (!isFetching.value) {\n        config.type = type;\n        return {\n          ...shell,\n          then(onFulfilled, onRejected) {\n            return waitUntilFinished().then(onFulfilled, onRejected);\n          }\n        };\n      }\n      return void 0;\n    };\n  }\n  if (options.immediate)\n    Promise.resolve().then(() => execute());\n  return {\n    ...shell,\n    then(onFulfilled, onRejected) {\n      return waitUntilFinished().then(onFulfilled, onRejected);\n    }\n  };\n}\nfunction joinPaths(start, end) {\n  if (!start.endsWith(\"/\") && !end.startsWith(\"/\")) {\n    return `${start}/${end}`;\n  }\n  if (start.endsWith(\"/\") && end.startsWith(\"/\")) {\n    return `${start.slice(0, -1)}${end}`;\n  }\n  return `${start}${end}`;\n}\n\nconst DEFAULT_OPTIONS = {\n  multiple: true,\n  accept: \"*\",\n  reset: false,\n  directory: false\n};\nfunction prepareInitialFiles(files) {\n  if (!files)\n    return null;\n  if (files instanceof FileList)\n    return files;\n  const dt = new DataTransfer();\n  for (const file of files) {\n    dt.items.add(file);\n  }\n  return dt.files;\n}\nfunction useFileDialog(options = {}) {\n  const {\n    document = defaultDocument\n  } = options;\n  const files = ref(prepareInitialFiles(options.initialFiles));\n  const { on: onChange, trigger: changeTrigger } = createEventHook();\n  const { on: onCancel, trigger: cancelTrigger } = createEventHook();\n  const inputRef = computed(() => {\n    var _a;\n    const input = (_a = unrefElement(options.input)) != null ? _a : document ? document.createElement(\"input\") : void 0;\n    if (input) {\n      input.type = \"file\";\n      input.onchange = (event) => {\n        const result = event.target;\n        files.value = result.files;\n        changeTrigger(files.value);\n      };\n      input.oncancel = () => {\n        cancelTrigger();\n      };\n    }\n    return input;\n  });\n  const reset = () => {\n    files.value = null;\n    if (inputRef.value && inputRef.value.value) {\n      inputRef.value.value = \"\";\n      changeTrigger(null);\n    }\n  };\n  const applyOptions = (options2) => {\n    const el = inputRef.value;\n    if (!el)\n      return;\n    el.multiple = toValue(options2.multiple);\n    el.accept = toValue(options2.accept);\n    el.webkitdirectory = toValue(options2.directory);\n    if (hasOwn(options2, \"capture\"))\n      el.capture = toValue(options2.capture);\n  };\n  const open = (localOptions) => {\n    const el = inputRef.value;\n    if (!el)\n      return;\n    const mergedOptions = {\n      ...DEFAULT_OPTIONS,\n      ...options,\n      ...localOptions\n    };\n    applyOptions(mergedOptions);\n    if (toValue(mergedOptions.reset))\n      reset();\n    el.click();\n  };\n  watchEffect(() => {\n    applyOptions(options);\n  });\n  return {\n    files: readonly(files),\n    open,\n    reset,\n    onCancel,\n    onChange\n  };\n}\n\nfunction useFileSystemAccess(options = {}) {\n  const {\n    window: _window = defaultWindow,\n    dataType = \"Text\"\n  } = options;\n  const window = _window;\n  const isSupported = useSupported(() => window && \"showSaveFilePicker\" in window && \"showOpenFilePicker\" in window);\n  const fileHandle = shallowRef();\n  const data = shallowRef();\n  const file = shallowRef();\n  const fileName = computed(() => {\n    var _a, _b;\n    return (_b = (_a = file.value) == null ? void 0 : _a.name) != null ? _b : \"\";\n  });\n  const fileMIME = computed(() => {\n    var _a, _b;\n    return (_b = (_a = file.value) == null ? void 0 : _a.type) != null ? _b : \"\";\n  });\n  const fileSize = computed(() => {\n    var _a, _b;\n    return (_b = (_a = file.value) == null ? void 0 : _a.size) != null ? _b : 0;\n  });\n  const fileLastModified = computed(() => {\n    var _a, _b;\n    return (_b = (_a = file.value) == null ? void 0 : _a.lastModified) != null ? _b : 0;\n  });\n  async function open(_options = {}) {\n    if (!isSupported.value)\n      return;\n    const [handle] = await window.showOpenFilePicker({ ...toValue(options), ..._options });\n    fileHandle.value = handle;\n    await updateData();\n  }\n  async function create(_options = {}) {\n    if (!isSupported.value)\n      return;\n    fileHandle.value = await window.showSaveFilePicker({ ...options, ..._options });\n    data.value = void 0;\n    await updateData();\n  }\n  async function save(_options = {}) {\n    if (!isSupported.value)\n      return;\n    if (!fileHandle.value)\n      return saveAs(_options);\n    if (data.value) {\n      const writableStream = await fileHandle.value.createWritable();\n      await writableStream.write(data.value);\n      await writableStream.close();\n    }\n    await updateFile();\n  }\n  async function saveAs(_options = {}) {\n    if (!isSupported.value)\n      return;\n    fileHandle.value = await window.showSaveFilePicker({ ...options, ..._options });\n    if (data.value) {\n      const writableStream = await fileHandle.value.createWritable();\n      await writableStream.write(data.value);\n      await writableStream.close();\n    }\n    await updateFile();\n  }\n  async function updateFile() {\n    var _a;\n    file.value = await ((_a = fileHandle.value) == null ? void 0 : _a.getFile());\n  }\n  async function updateData() {\n    var _a, _b;\n    await updateFile();\n    const type = toValue(dataType);\n    if (type === \"Text\")\n      data.value = await ((_a = file.value) == null ? void 0 : _a.text());\n    else if (type === \"ArrayBuffer\")\n      data.value = await ((_b = file.value) == null ? void 0 : _b.arrayBuffer());\n    else if (type === \"Blob\")\n      data.value = file.value;\n  }\n  watch(() => toValue(dataType), updateData);\n  return {\n    isSupported,\n    data,\n    file,\n    fileName,\n    fileMIME,\n    fileSize,\n    fileLastModified,\n    open,\n    create,\n    save,\n    saveAs,\n    updateData\n  };\n}\n\nfunction useFocus(target, options = {}) {\n  const { initialValue = false, focusVisible = false, preventScroll = false } = options;\n  const innerFocused = shallowRef(false);\n  const targetElement = computed(() => unrefElement(target));\n  const listenerOptions = { passive: true };\n  useEventListener(targetElement, \"focus\", (event) => {\n    var _a, _b;\n    if (!focusVisible || ((_b = (_a = event.target).matches) == null ? void 0 : _b.call(_a, \":focus-visible\")))\n      innerFocused.value = true;\n  }, listenerOptions);\n  useEventListener(targetElement, \"blur\", () => innerFocused.value = false, listenerOptions);\n  const focused = computed({\n    get: () => innerFocused.value,\n    set(value) {\n      var _a, _b;\n      if (!value && innerFocused.value)\n        (_a = targetElement.value) == null ? void 0 : _a.blur();\n      else if (value && !innerFocused.value)\n        (_b = targetElement.value) == null ? void 0 : _b.focus({ preventScroll });\n    }\n  });\n  watch(\n    targetElement,\n    () => {\n      focused.value = initialValue;\n    },\n    { immediate: true, flush: \"post\" }\n  );\n  return { focused };\n}\n\nconst EVENT_FOCUS_IN = \"focusin\";\nconst EVENT_FOCUS_OUT = \"focusout\";\nconst PSEUDO_CLASS_FOCUS_WITHIN = \":focus-within\";\nfunction useFocusWithin(target, options = {}) {\n  const { window = defaultWindow } = options;\n  const targetElement = computed(() => unrefElement(target));\n  const _focused = shallowRef(false);\n  const focused = computed(() => _focused.value);\n  const activeElement = useActiveElement(options);\n  if (!window || !activeElement.value) {\n    return { focused };\n  }\n  const listenerOptions = { passive: true };\n  useEventListener(targetElement, EVENT_FOCUS_IN, () => _focused.value = true, listenerOptions);\n  useEventListener(targetElement, EVENT_FOCUS_OUT, () => {\n    var _a, _b, _c;\n    return _focused.value = (_c = (_b = (_a = targetElement.value) == null ? void 0 : _a.matches) == null ? void 0 : _b.call(_a, PSEUDO_CLASS_FOCUS_WITHIN)) != null ? _c : false;\n  }, listenerOptions);\n  return { focused };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useFps(options) {\n  var _a;\n  const fps = shallowRef(0);\n  if (typeof performance === \"undefined\")\n    return fps;\n  const every = (_a = options == null ? void 0 : options.every) != null ? _a : 10;\n  let last = performance.now();\n  let ticks = 0;\n  useRafFn(() => {\n    ticks += 1;\n    if (ticks >= every) {\n      const now = performance.now();\n      const diff = now - last;\n      fps.value = Math.round(1e3 / (diff / ticks));\n      last = now;\n      ticks = 0;\n    }\n  });\n  return fps;\n}\n\nconst eventHandlers = [\n  \"fullscreenchange\",\n  \"webkitfullscreenchange\",\n  \"webkitendfullscreen\",\n  \"mozfullscreenchange\",\n  \"MSFullscreenChange\"\n];\nfunction useFullscreen(target, options = {}) {\n  const {\n    document = defaultDocument,\n    autoExit = false\n  } = options;\n  const targetRef = computed(() => {\n    var _a;\n    return (_a = unrefElement(target)) != null ? _a : document == null ? void 0 : document.documentElement;\n  });\n  const isFullscreen = shallowRef(false);\n  const requestMethod = computed(() => {\n    return [\n      \"requestFullscreen\",\n      \"webkitRequestFullscreen\",\n      \"webkitEnterFullscreen\",\n      \"webkitEnterFullScreen\",\n      \"webkitRequestFullScreen\",\n      \"mozRequestFullScreen\",\n      \"msRequestFullscreen\"\n    ].find((m) => document && m in document || targetRef.value && m in targetRef.value);\n  });\n  const exitMethod = computed(() => {\n    return [\n      \"exitFullscreen\",\n      \"webkitExitFullscreen\",\n      \"webkitExitFullScreen\",\n      \"webkitCancelFullScreen\",\n      \"mozCancelFullScreen\",\n      \"msExitFullscreen\"\n    ].find((m) => document && m in document || targetRef.value && m in targetRef.value);\n  });\n  const fullscreenEnabled = computed(() => {\n    return [\n      \"fullScreen\",\n      \"webkitIsFullScreen\",\n      \"webkitDisplayingFullscreen\",\n      \"mozFullScreen\",\n      \"msFullscreenElement\"\n    ].find((m) => document && m in document || targetRef.value && m in targetRef.value);\n  });\n  const fullscreenElementMethod = [\n    \"fullscreenElement\",\n    \"webkitFullscreenElement\",\n    \"mozFullScreenElement\",\n    \"msFullscreenElement\"\n  ].find((m) => document && m in document);\n  const isSupported = useSupported(() => targetRef.value && document && requestMethod.value !== void 0 && exitMethod.value !== void 0 && fullscreenEnabled.value !== void 0);\n  const isCurrentElementFullScreen = () => {\n    if (fullscreenElementMethod)\n      return (document == null ? void 0 : document[fullscreenElementMethod]) === targetRef.value;\n    return false;\n  };\n  const isElementFullScreen = () => {\n    if (fullscreenEnabled.value) {\n      if (document && document[fullscreenEnabled.value] != null) {\n        return document[fullscreenEnabled.value];\n      } else {\n        const target2 = targetRef.value;\n        if ((target2 == null ? void 0 : target2[fullscreenEnabled.value]) != null) {\n          return Boolean(target2[fullscreenEnabled.value]);\n        }\n      }\n    }\n    return false;\n  };\n  async function exit() {\n    if (!isSupported.value || !isFullscreen.value)\n      return;\n    if (exitMethod.value) {\n      if ((document == null ? void 0 : document[exitMethod.value]) != null) {\n        await document[exitMethod.value]();\n      } else {\n        const target2 = targetRef.value;\n        if ((target2 == null ? void 0 : target2[exitMethod.value]) != null)\n          await target2[exitMethod.value]();\n      }\n    }\n    isFullscreen.value = false;\n  }\n  async function enter() {\n    if (!isSupported.value || isFullscreen.value)\n      return;\n    if (isElementFullScreen())\n      await exit();\n    const target2 = targetRef.value;\n    if (requestMethod.value && (target2 == null ? void 0 : target2[requestMethod.value]) != null) {\n      await target2[requestMethod.value]();\n      isFullscreen.value = true;\n    }\n  }\n  async function toggle() {\n    await (isFullscreen.value ? exit() : enter());\n  }\n  const handlerCallback = () => {\n    const isElementFullScreenValue = isElementFullScreen();\n    if (!isElementFullScreenValue || isElementFullScreenValue && isCurrentElementFullScreen())\n      isFullscreen.value = isElementFullScreenValue;\n  };\n  const listenerOptions = { capture: false, passive: true };\n  useEventListener(document, eventHandlers, handlerCallback, listenerOptions);\n  useEventListener(() => unrefElement(targetRef), eventHandlers, handlerCallback, listenerOptions);\n  tryOnMounted(handlerCallback, false);\n  if (autoExit)\n    tryOnScopeDispose(exit);\n  return {\n    isSupported,\n    isFullscreen,\n    enter,\n    exit,\n    toggle\n  };\n}\n\nfunction mapGamepadToXbox360Controller(gamepad) {\n  return computed(() => {\n    if (gamepad.value) {\n      return {\n        buttons: {\n          a: gamepad.value.buttons[0],\n          b: gamepad.value.buttons[1],\n          x: gamepad.value.buttons[2],\n          y: gamepad.value.buttons[3]\n        },\n        bumper: {\n          left: gamepad.value.buttons[4],\n          right: gamepad.value.buttons[5]\n        },\n        triggers: {\n          left: gamepad.value.buttons[6],\n          right: gamepad.value.buttons[7]\n        },\n        stick: {\n          left: {\n            horizontal: gamepad.value.axes[0],\n            vertical: gamepad.value.axes[1],\n            button: gamepad.value.buttons[10]\n          },\n          right: {\n            horizontal: gamepad.value.axes[2],\n            vertical: gamepad.value.axes[3],\n            button: gamepad.value.buttons[11]\n          }\n        },\n        dpad: {\n          up: gamepad.value.buttons[12],\n          down: gamepad.value.buttons[13],\n          left: gamepad.value.buttons[14],\n          right: gamepad.value.buttons[15]\n        },\n        back: gamepad.value.buttons[8],\n        start: gamepad.value.buttons[9]\n      };\n    }\n    return null;\n  });\n}\n// @__NO_SIDE_EFFECTS__\nfunction useGamepad(options = {}) {\n  const {\n    navigator = defaultNavigator\n  } = options;\n  const isSupported = useSupported(() => navigator && \"getGamepads\" in navigator);\n  const gamepads = ref([]);\n  const onConnectedHook = createEventHook();\n  const onDisconnectedHook = createEventHook();\n  const stateFromGamepad = (gamepad) => {\n    const hapticActuators = [];\n    const vibrationActuator = \"vibrationActuator\" in gamepad ? gamepad.vibrationActuator : null;\n    if (vibrationActuator)\n      hapticActuators.push(vibrationActuator);\n    if (gamepad.hapticActuators)\n      hapticActuators.push(...gamepad.hapticActuators);\n    return {\n      id: gamepad.id,\n      index: gamepad.index,\n      connected: gamepad.connected,\n      mapping: gamepad.mapping,\n      timestamp: gamepad.timestamp,\n      vibrationActuator: gamepad.vibrationActuator,\n      hapticActuators,\n      axes: gamepad.axes.map((axes) => axes),\n      buttons: gamepad.buttons.map((button) => ({ pressed: button.pressed, touched: button.touched, value: button.value }))\n    };\n  };\n  const updateGamepadState = () => {\n    const _gamepads = (navigator == null ? void 0 : navigator.getGamepads()) || [];\n    for (const gamepad of _gamepads) {\n      if (gamepad && gamepads.value[gamepad.index])\n        gamepads.value[gamepad.index] = stateFromGamepad(gamepad);\n    }\n  };\n  const { isActive, pause, resume } = useRafFn(updateGamepadState);\n  const onGamepadConnected = (gamepad) => {\n    if (!gamepads.value.some(({ index }) => index === gamepad.index)) {\n      gamepads.value.push(stateFromGamepad(gamepad));\n      onConnectedHook.trigger(gamepad.index);\n    }\n    resume();\n  };\n  const onGamepadDisconnected = (gamepad) => {\n    gamepads.value = gamepads.value.filter((x) => x.index !== gamepad.index);\n    onDisconnectedHook.trigger(gamepad.index);\n  };\n  const listenerOptions = { passive: true };\n  useEventListener(\"gamepadconnected\", (e) => onGamepadConnected(e.gamepad), listenerOptions);\n  useEventListener(\"gamepaddisconnected\", (e) => onGamepadDisconnected(e.gamepad), listenerOptions);\n  tryOnMounted(() => {\n    const _gamepads = (navigator == null ? void 0 : navigator.getGamepads()) || [];\n    for (const gamepad of _gamepads) {\n      if (gamepad && gamepads.value[gamepad.index])\n        onGamepadConnected(gamepad);\n    }\n  });\n  pause();\n  return {\n    isSupported,\n    onConnected: onConnectedHook.on,\n    onDisconnected: onDisconnectedHook.on,\n    gamepads,\n    pause,\n    resume,\n    isActive\n  };\n}\n\nfunction useGeolocation(options = {}) {\n  const {\n    enableHighAccuracy = true,\n    maximumAge = 3e4,\n    timeout = 27e3,\n    navigator = defaultNavigator,\n    immediate = true\n  } = options;\n  const isSupported = useSupported(() => navigator && \"geolocation\" in navigator);\n  const locatedAt = shallowRef(null);\n  const error = shallowRef(null);\n  const coords = ref({\n    accuracy: 0,\n    latitude: Number.POSITIVE_INFINITY,\n    longitude: Number.POSITIVE_INFINITY,\n    altitude: null,\n    altitudeAccuracy: null,\n    heading: null,\n    speed: null\n  });\n  function updatePosition(position) {\n    locatedAt.value = position.timestamp;\n    coords.value = position.coords;\n    error.value = null;\n  }\n  let watcher;\n  function resume() {\n    if (isSupported.value) {\n      watcher = navigator.geolocation.watchPosition(\n        updatePosition,\n        (err) => error.value = err,\n        {\n          enableHighAccuracy,\n          maximumAge,\n          timeout\n        }\n      );\n    }\n  }\n  if (immediate)\n    resume();\n  function pause() {\n    if (watcher && navigator)\n      navigator.geolocation.clearWatch(watcher);\n  }\n  tryOnScopeDispose(() => {\n    pause();\n  });\n  return {\n    isSupported,\n    coords,\n    locatedAt,\n    error,\n    resume,\n    pause\n  };\n}\n\nconst defaultEvents$1 = [\"mousemove\", \"mousedown\", \"resize\", \"keydown\", \"touchstart\", \"wheel\"];\nconst oneMinute = 6e4;\nfunction useIdle(timeout = oneMinute, options = {}) {\n  const {\n    initialState = false,\n    listenForVisibilityChange = true,\n    events = defaultEvents$1,\n    window = defaultWindow,\n    eventFilter = throttleFilter(50)\n  } = options;\n  const idle = shallowRef(initialState);\n  const lastActive = shallowRef(timestamp());\n  let timer;\n  const reset = () => {\n    idle.value = false;\n    clearTimeout(timer);\n    timer = setTimeout(() => idle.value = true, timeout);\n  };\n  const onEvent = createFilterWrapper(\n    eventFilter,\n    () => {\n      lastActive.value = timestamp();\n      reset();\n    }\n  );\n  if (window) {\n    const document = window.document;\n    const listenerOptions = { passive: true };\n    for (const event of events)\n      useEventListener(window, event, onEvent, listenerOptions);\n    if (listenForVisibilityChange) {\n      useEventListener(document, \"visibilitychange\", () => {\n        if (!document.hidden)\n          onEvent();\n      }, listenerOptions);\n    }\n    if (!initialState)\n      reset();\n  }\n  return {\n    idle,\n    lastActive,\n    reset\n  };\n}\n\nasync function loadImage(options) {\n  return new Promise((resolve, reject) => {\n    const img = new Image();\n    const { src, srcset, sizes, class: clazz, loading, crossorigin, referrerPolicy, width, height, decoding, fetchPriority, ismap, usemap } = options;\n    img.src = src;\n    if (srcset != null)\n      img.srcset = srcset;\n    if (sizes != null)\n      img.sizes = sizes;\n    if (clazz != null)\n      img.className = clazz;\n    if (loading != null)\n      img.loading = loading;\n    if (crossorigin != null)\n      img.crossOrigin = crossorigin;\n    if (referrerPolicy != null)\n      img.referrerPolicy = referrerPolicy;\n    if (width != null)\n      img.width = width;\n    if (height != null)\n      img.height = height;\n    if (decoding != null)\n      img.decoding = decoding;\n    if (fetchPriority != null)\n      img.fetchPriority = fetchPriority;\n    if (ismap != null)\n      img.isMap = ismap;\n    if (usemap != null)\n      img.useMap = usemap;\n    img.onload = () => resolve(img);\n    img.onerror = reject;\n  });\n}\nfunction useImage(options, asyncStateOptions = {}) {\n  const state = useAsyncState(\n    () => loadImage(toValue(options)),\n    void 0,\n    {\n      resetOnExecute: true,\n      ...asyncStateOptions\n    }\n  );\n  watch(\n    () => toValue(options),\n    () => state.execute(asyncStateOptions.delay),\n    { deep: true }\n  );\n  return state;\n}\n\nfunction resolveElement(el) {\n  if (typeof Window !== \"undefined\" && el instanceof Window)\n    return el.document.documentElement;\n  if (typeof Document !== \"undefined\" && el instanceof Document)\n    return el.documentElement;\n  return el;\n}\n\nconst ARRIVED_STATE_THRESHOLD_PIXELS = 1;\nfunction useScroll(element, options = {}) {\n  const {\n    throttle = 0,\n    idle = 200,\n    onStop = noop,\n    onScroll = noop,\n    offset = {\n      left: 0,\n      right: 0,\n      top: 0,\n      bottom: 0\n    },\n    observe: _observe = {\n      mutation: false\n    },\n    eventListenerOptions = {\n      capture: false,\n      passive: true\n    },\n    behavior = \"auto\",\n    window = defaultWindow,\n    onError = (e) => {\n      console.error(e);\n    }\n  } = options;\n  const observe = typeof _observe === \"boolean\" ? {\n    mutation: _observe\n  } : _observe;\n  const internalX = shallowRef(0);\n  const internalY = shallowRef(0);\n  const x = computed({\n    get() {\n      return internalX.value;\n    },\n    set(x2) {\n      scrollTo(x2, void 0);\n    }\n  });\n  const y = computed({\n    get() {\n      return internalY.value;\n    },\n    set(y2) {\n      scrollTo(void 0, y2);\n    }\n  });\n  function scrollTo(_x, _y) {\n    var _a, _b, _c, _d;\n    if (!window)\n      return;\n    const _element = toValue(element);\n    if (!_element)\n      return;\n    (_c = _element instanceof Document ? window.document.body : _element) == null ? void 0 : _c.scrollTo({\n      top: (_a = toValue(_y)) != null ? _a : y.value,\n      left: (_b = toValue(_x)) != null ? _b : x.value,\n      behavior: toValue(behavior)\n    });\n    const scrollContainer = ((_d = _element == null ? void 0 : _element.document) == null ? void 0 : _d.documentElement) || (_element == null ? void 0 : _element.documentElement) || _element;\n    if (x != null)\n      internalX.value = scrollContainer.scrollLeft;\n    if (y != null)\n      internalY.value = scrollContainer.scrollTop;\n  }\n  const isScrolling = shallowRef(false);\n  const arrivedState = reactive({\n    left: true,\n    right: false,\n    top: true,\n    bottom: false\n  });\n  const directions = reactive({\n    left: false,\n    right: false,\n    top: false,\n    bottom: false\n  });\n  const onScrollEnd = (e) => {\n    if (!isScrolling.value)\n      return;\n    isScrolling.value = false;\n    directions.left = false;\n    directions.right = false;\n    directions.top = false;\n    directions.bottom = false;\n    onStop(e);\n  };\n  const onScrollEndDebounced = useDebounceFn(onScrollEnd, throttle + idle);\n  const setArrivedState = (target) => {\n    var _a;\n    if (!window)\n      return;\n    const el = ((_a = target == null ? void 0 : target.document) == null ? void 0 : _a.documentElement) || (target == null ? void 0 : target.documentElement) || unrefElement(target);\n    const { display, flexDirection, direction } = getComputedStyle(el);\n    const directionMultipler = direction === \"rtl\" ? -1 : 1;\n    const scrollLeft = el.scrollLeft;\n    directions.left = scrollLeft < internalX.value;\n    directions.right = scrollLeft > internalX.value;\n    const left = Math.abs(scrollLeft * directionMultipler) <= (offset.left || 0);\n    const right = Math.abs(scrollLeft * directionMultipler) + el.clientWidth >= el.scrollWidth - (offset.right || 0) - ARRIVED_STATE_THRESHOLD_PIXELS;\n    if (display === \"flex\" && flexDirection === \"row-reverse\") {\n      arrivedState.left = right;\n      arrivedState.right = left;\n    } else {\n      arrivedState.left = left;\n      arrivedState.right = right;\n    }\n    internalX.value = scrollLeft;\n    let scrollTop = el.scrollTop;\n    if (target === window.document && !scrollTop)\n      scrollTop = window.document.body.scrollTop;\n    directions.top = scrollTop < internalY.value;\n    directions.bottom = scrollTop > internalY.value;\n    const top = Math.abs(scrollTop) <= (offset.top || 0);\n    const bottom = Math.abs(scrollTop) + el.clientHeight >= el.scrollHeight - (offset.bottom || 0) - ARRIVED_STATE_THRESHOLD_PIXELS;\n    if (display === \"flex\" && flexDirection === \"column-reverse\") {\n      arrivedState.top = bottom;\n      arrivedState.bottom = top;\n    } else {\n      arrivedState.top = top;\n      arrivedState.bottom = bottom;\n    }\n    internalY.value = scrollTop;\n  };\n  const onScrollHandler = (e) => {\n    var _a;\n    if (!window)\n      return;\n    const eventTarget = (_a = e.target.documentElement) != null ? _a : e.target;\n    setArrivedState(eventTarget);\n    isScrolling.value = true;\n    onScrollEndDebounced(e);\n    onScroll(e);\n  };\n  useEventListener(\n    element,\n    \"scroll\",\n    throttle ? useThrottleFn(onScrollHandler, throttle, true, false) : onScrollHandler,\n    eventListenerOptions\n  );\n  tryOnMounted(() => {\n    try {\n      const _element = toValue(element);\n      if (!_element)\n        return;\n      setArrivedState(_element);\n    } catch (e) {\n      onError(e);\n    }\n  });\n  if ((observe == null ? void 0 : observe.mutation) && element != null && element !== window && element !== document) {\n    useMutationObserver(\n      element,\n      () => {\n        const _element = toValue(element);\n        if (!_element)\n          return;\n        setArrivedState(_element);\n      },\n      {\n        attributes: true,\n        childList: true,\n        subtree: true\n      }\n    );\n  }\n  useEventListener(\n    element,\n    \"scrollend\",\n    onScrollEnd,\n    eventListenerOptions\n  );\n  return {\n    x,\n    y,\n    isScrolling,\n    arrivedState,\n    directions,\n    measure() {\n      const _element = toValue(element);\n      if (window && _element)\n        setArrivedState(_element);\n    }\n  };\n}\n\nfunction useInfiniteScroll(element, onLoadMore, options = {}) {\n  var _a;\n  const {\n    direction = \"bottom\",\n    interval = 100,\n    canLoadMore = () => true\n  } = options;\n  const state = reactive(useScroll(\n    element,\n    {\n      ...options,\n      offset: {\n        [direction]: (_a = options.distance) != null ? _a : 0,\n        ...options.offset\n      }\n    }\n  ));\n  const promise = ref();\n  const isLoading = computed(() => !!promise.value);\n  const observedElement = computed(() => {\n    return resolveElement(toValue(element));\n  });\n  const isElementVisible = useElementVisibility(observedElement);\n  function checkAndLoad() {\n    state.measure();\n    if (!observedElement.value || !isElementVisible.value || !canLoadMore(observedElement.value))\n      return;\n    const { scrollHeight, clientHeight, scrollWidth, clientWidth } = observedElement.value;\n    const isNarrower = direction === \"bottom\" || direction === \"top\" ? scrollHeight <= clientHeight : scrollWidth <= clientWidth;\n    if (state.arrivedState[direction] || isNarrower) {\n      if (!promise.value) {\n        promise.value = Promise.all([\n          onLoadMore(state),\n          new Promise((resolve) => setTimeout(resolve, interval))\n        ]).finally(() => {\n          promise.value = null;\n          nextTick(() => checkAndLoad());\n        });\n      }\n    }\n  }\n  const stop = watch(\n    () => [state.arrivedState[direction], isElementVisible.value],\n    checkAndLoad,\n    { immediate: true }\n  );\n  tryOnUnmounted(stop);\n  return {\n    isLoading,\n    reset() {\n      nextTick(() => checkAndLoad());\n    }\n  };\n}\n\nconst defaultEvents = [\"mousedown\", \"mouseup\", \"keydown\", \"keyup\"];\n// @__NO_SIDE_EFFECTS__\nfunction useKeyModifier(modifier, options = {}) {\n  const {\n    events = defaultEvents,\n    document = defaultDocument,\n    initial = null\n  } = options;\n  const state = shallowRef(initial);\n  if (document) {\n    events.forEach((listenerEvent) => {\n      useEventListener(document, listenerEvent, (evt) => {\n        if (typeof evt.getModifierState === \"function\")\n          state.value = evt.getModifierState(modifier);\n      }, { passive: true });\n    });\n  }\n  return state;\n}\n\nfunction useLocalStorage(key, initialValue, options = {}) {\n  const { window = defaultWindow } = options;\n  return useStorage(key, initialValue, window == null ? void 0 : window.localStorage, options);\n}\n\nconst DefaultMagicKeysAliasMap = {\n  ctrl: \"control\",\n  command: \"meta\",\n  cmd: \"meta\",\n  option: \"alt\",\n  up: \"arrowup\",\n  down: \"arrowdown\",\n  left: \"arrowleft\",\n  right: \"arrowright\"\n};\n\nfunction useMagicKeys(options = {}) {\n  const {\n    reactive: useReactive = false,\n    target = defaultWindow,\n    aliasMap = DefaultMagicKeysAliasMap,\n    passive = true,\n    onEventFired = noop\n  } = options;\n  const current = reactive(/* @__PURE__ */ new Set());\n  const obj = {\n    toJSON() {\n      return {};\n    },\n    current\n  };\n  const refs = useReactive ? reactive(obj) : obj;\n  const metaDeps = /* @__PURE__ */ new Set();\n  const shiftDeps = /* @__PURE__ */ new Set();\n  const usedKeys = /* @__PURE__ */ new Set();\n  function setRefs(key, value) {\n    if (key in refs) {\n      if (useReactive)\n        refs[key] = value;\n      else\n        refs[key].value = value;\n    }\n  }\n  function reset() {\n    current.clear();\n    for (const key of usedKeys)\n      setRefs(key, false);\n  }\n  function updateRefs(e, value) {\n    var _a, _b;\n    const key = (_a = e.key) == null ? void 0 : _a.toLowerCase();\n    const code = (_b = e.code) == null ? void 0 : _b.toLowerCase();\n    const values = [code, key].filter(Boolean);\n    if (key) {\n      if (value)\n        current.add(key);\n      else\n        current.delete(key);\n    }\n    for (const key2 of values) {\n      usedKeys.add(key2);\n      setRefs(key2, value);\n    }\n    if (key === \"shift\" && !value) {\n      const shiftDepsArray = Array.from(shiftDeps);\n      const shiftIndex = shiftDepsArray.indexOf(\"shift\");\n      shiftDepsArray.forEach((key2, index) => {\n        if (index >= shiftIndex) {\n          current.delete(key2);\n          setRefs(key2, false);\n        }\n      });\n      shiftDeps.clear();\n    } else if (typeof e.getModifierState === \"function\" && e.getModifierState(\"Shift\") && value) {\n      [...current, ...values].forEach((key2) => shiftDeps.add(key2));\n    }\n    if (key === \"meta\" && !value) {\n      metaDeps.forEach((key2) => {\n        current.delete(key2);\n        setRefs(key2, false);\n      });\n      metaDeps.clear();\n    } else if (typeof e.getModifierState === \"function\" && e.getModifierState(\"Meta\") && value) {\n      [...current, ...values].forEach((key2) => metaDeps.add(key2));\n    }\n  }\n  useEventListener(target, \"keydown\", (e) => {\n    updateRefs(e, true);\n    return onEventFired(e);\n  }, { passive });\n  useEventListener(target, \"keyup\", (e) => {\n    updateRefs(e, false);\n    return onEventFired(e);\n  }, { passive });\n  useEventListener(\"blur\", reset, { passive });\n  useEventListener(\"focus\", reset, { passive });\n  const proxy = new Proxy(\n    refs,\n    {\n      get(target2, prop, rec) {\n        if (typeof prop !== \"string\")\n          return Reflect.get(target2, prop, rec);\n        prop = prop.toLowerCase();\n        if (prop in aliasMap)\n          prop = aliasMap[prop];\n        if (!(prop in refs)) {\n          if (/[+_-]/.test(prop)) {\n            const keys = prop.split(/[+_-]/g).map((i) => i.trim());\n            refs[prop] = computed(() => keys.map((key) => toValue(proxy[key])).every(Boolean));\n          } else {\n            refs[prop] = shallowRef(false);\n          }\n        }\n        const r = Reflect.get(target2, prop, rec);\n        return useReactive ? toValue(r) : r;\n      }\n    }\n  );\n  return proxy;\n}\n\nfunction usingElRef(source, cb) {\n  if (toValue(source))\n    cb(toValue(source));\n}\nfunction timeRangeToArray(timeRanges) {\n  let ranges = [];\n  for (let i = 0; i < timeRanges.length; ++i)\n    ranges = [...ranges, [timeRanges.start(i), timeRanges.end(i)]];\n  return ranges;\n}\nfunction tracksToArray(tracks) {\n  return Array.from(tracks).map(({ label, kind, language, mode, activeCues, cues, inBandMetadataTrackDispatchType }, id) => ({ id, label, kind, language, mode, activeCues, cues, inBandMetadataTrackDispatchType }));\n}\nconst defaultOptions = {\n  src: \"\",\n  tracks: []\n};\nfunction useMediaControls(target, options = {}) {\n  target = toRef(target);\n  options = {\n    ...defaultOptions,\n    ...options\n  };\n  const {\n    document = defaultDocument\n  } = options;\n  const listenerOptions = { passive: true };\n  const currentTime = shallowRef(0);\n  const duration = shallowRef(0);\n  const seeking = shallowRef(false);\n  const volume = shallowRef(1);\n  const waiting = shallowRef(false);\n  const ended = shallowRef(false);\n  const playing = shallowRef(false);\n  const rate = shallowRef(1);\n  const stalled = shallowRef(false);\n  const buffered = ref([]);\n  const tracks = ref([]);\n  const selectedTrack = shallowRef(-1);\n  const isPictureInPicture = shallowRef(false);\n  const muted = shallowRef(false);\n  const supportsPictureInPicture = document && \"pictureInPictureEnabled\" in document;\n  const sourceErrorEvent = createEventHook();\n  const playbackErrorEvent = createEventHook();\n  const disableTrack = (track) => {\n    usingElRef(target, (el) => {\n      if (track) {\n        const id = typeof track === \"number\" ? track : track.id;\n        el.textTracks[id].mode = \"disabled\";\n      } else {\n        for (let i = 0; i < el.textTracks.length; ++i)\n          el.textTracks[i].mode = \"disabled\";\n      }\n      selectedTrack.value = -1;\n    });\n  };\n  const enableTrack = (track, disableTracks = true) => {\n    usingElRef(target, (el) => {\n      const id = typeof track === \"number\" ? track : track.id;\n      if (disableTracks)\n        disableTrack();\n      el.textTracks[id].mode = \"showing\";\n      selectedTrack.value = id;\n    });\n  };\n  const togglePictureInPicture = () => {\n    return new Promise((resolve, reject) => {\n      usingElRef(target, async (el) => {\n        if (supportsPictureInPicture) {\n          if (!isPictureInPicture.value) {\n            el.requestPictureInPicture().then(resolve).catch(reject);\n          } else {\n            document.exitPictureInPicture().then(resolve).catch(reject);\n          }\n        }\n      });\n    });\n  };\n  watchEffect(() => {\n    if (!document)\n      return;\n    const el = toValue(target);\n    if (!el)\n      return;\n    const src = toValue(options.src);\n    let sources = [];\n    if (!src)\n      return;\n    if (typeof src === \"string\")\n      sources = [{ src }];\n    else if (Array.isArray(src))\n      sources = src;\n    else if (isObject(src))\n      sources = [src];\n    el.querySelectorAll(\"source\").forEach((e) => {\n      e.remove();\n    });\n    sources.forEach(({ src: src2, type, media }) => {\n      const source = document.createElement(\"source\");\n      source.setAttribute(\"src\", src2);\n      source.setAttribute(\"type\", type || \"\");\n      source.setAttribute(\"media\", media || \"\");\n      useEventListener(source, \"error\", sourceErrorEvent.trigger, listenerOptions);\n      el.appendChild(source);\n    });\n    el.load();\n  });\n  watch([target, volume], () => {\n    const el = toValue(target);\n    if (!el)\n      return;\n    el.volume = volume.value;\n  });\n  watch([target, muted], () => {\n    const el = toValue(target);\n    if (!el)\n      return;\n    el.muted = muted.value;\n  });\n  watch([target, rate], () => {\n    const el = toValue(target);\n    if (!el)\n      return;\n    el.playbackRate = rate.value;\n  });\n  watchEffect(() => {\n    if (!document)\n      return;\n    const textTracks = toValue(options.tracks);\n    const el = toValue(target);\n    if (!textTracks || !textTracks.length || !el)\n      return;\n    el.querySelectorAll(\"track\").forEach((e) => e.remove());\n    textTracks.forEach(({ default: isDefault, kind, label, src, srcLang }, i) => {\n      const track = document.createElement(\"track\");\n      track.default = isDefault || false;\n      track.kind = kind;\n      track.label = label;\n      track.src = src;\n      track.srclang = srcLang;\n      if (track.default)\n        selectedTrack.value = i;\n      el.appendChild(track);\n    });\n  });\n  const { ignoreUpdates: ignoreCurrentTimeUpdates } = watchIgnorable(currentTime, (time) => {\n    const el = toValue(target);\n    if (!el)\n      return;\n    el.currentTime = time;\n  });\n  const { ignoreUpdates: ignorePlayingUpdates } = watchIgnorable(playing, (isPlaying) => {\n    const el = toValue(target);\n    if (!el)\n      return;\n    if (isPlaying) {\n      el.play().catch((e) => {\n        playbackErrorEvent.trigger(e);\n        throw e;\n      });\n    } else {\n      el.pause();\n    }\n  });\n  useEventListener(\n    target,\n    \"timeupdate\",\n    () => ignoreCurrentTimeUpdates(() => currentTime.value = toValue(target).currentTime),\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"durationchange\",\n    () => duration.value = toValue(target).duration,\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"progress\",\n    () => buffered.value = timeRangeToArray(toValue(target).buffered),\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"seeking\",\n    () => seeking.value = true,\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"seeked\",\n    () => seeking.value = false,\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    [\"waiting\", \"loadstart\"],\n    () => {\n      waiting.value = true;\n      ignorePlayingUpdates(() => playing.value = false);\n    },\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"loadeddata\",\n    () => waiting.value = false,\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"playing\",\n    () => {\n      waiting.value = false;\n      ended.value = false;\n      ignorePlayingUpdates(() => playing.value = true);\n    },\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"ratechange\",\n    () => rate.value = toValue(target).playbackRate,\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"stalled\",\n    () => stalled.value = true,\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"ended\",\n    () => ended.value = true,\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"pause\",\n    () => ignorePlayingUpdates(() => playing.value = false),\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"play\",\n    () => ignorePlayingUpdates(() => playing.value = true),\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"enterpictureinpicture\",\n    () => isPictureInPicture.value = true,\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"leavepictureinpicture\",\n    () => isPictureInPicture.value = false,\n    listenerOptions\n  );\n  useEventListener(\n    target,\n    \"volumechange\",\n    () => {\n      const el = toValue(target);\n      if (!el)\n        return;\n      volume.value = el.volume;\n      muted.value = el.muted;\n    },\n    listenerOptions\n  );\n  const listeners = [];\n  const stop = watch([target], () => {\n    const el = toValue(target);\n    if (!el)\n      return;\n    stop();\n    listeners[0] = useEventListener(el.textTracks, \"addtrack\", () => tracks.value = tracksToArray(el.textTracks), listenerOptions);\n    listeners[1] = useEventListener(el.textTracks, \"removetrack\", () => tracks.value = tracksToArray(el.textTracks), listenerOptions);\n    listeners[2] = useEventListener(el.textTracks, \"change\", () => tracks.value = tracksToArray(el.textTracks), listenerOptions);\n  });\n  tryOnScopeDispose(() => listeners.forEach((listener) => listener()));\n  return {\n    currentTime,\n    duration,\n    waiting,\n    seeking,\n    ended,\n    stalled,\n    buffered,\n    playing,\n    rate,\n    // Volume\n    volume,\n    muted,\n    // Tracks\n    tracks,\n    selectedTrack,\n    enableTrack,\n    disableTrack,\n    // Picture in Picture\n    supportsPictureInPicture,\n    togglePictureInPicture,\n    isPictureInPicture,\n    // Events\n    onSourceError: sourceErrorEvent.on,\n    onPlaybackError: playbackErrorEvent.on\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useMemoize(resolver, options) {\n  const initCache = () => {\n    if (options == null ? void 0 : options.cache)\n      return shallowReactive(options.cache);\n    return shallowReactive(/* @__PURE__ */ new Map());\n  };\n  const cache = initCache();\n  const generateKey = (...args) => (options == null ? void 0 : options.getKey) ? options.getKey(...args) : JSON.stringify(args);\n  const _loadData = (key, ...args) => {\n    cache.set(key, resolver(...args));\n    return cache.get(key);\n  };\n  const loadData = (...args) => _loadData(generateKey(...args), ...args);\n  const deleteData = (...args) => {\n    cache.delete(generateKey(...args));\n  };\n  const clearData = () => {\n    cache.clear();\n  };\n  const memoized = (...args) => {\n    const key = generateKey(...args);\n    if (cache.has(key))\n      return cache.get(key);\n    return _loadData(key, ...args);\n  };\n  memoized.load = loadData;\n  memoized.delete = deleteData;\n  memoized.clear = clearData;\n  memoized.generateKey = generateKey;\n  memoized.cache = cache;\n  return memoized;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useMemory(options = {}) {\n  const memory = ref();\n  const isSupported = useSupported(() => typeof performance !== \"undefined\" && \"memory\" in performance);\n  if (isSupported.value) {\n    const { interval = 1e3 } = options;\n    useIntervalFn(() => {\n      memory.value = performance.memory;\n    }, interval, { immediate: options.immediate, immediateCallback: options.immediateCallback });\n  }\n  return { isSupported, memory };\n}\n\nconst UseMouseBuiltinExtractors = {\n  page: (event) => [event.pageX, event.pageY],\n  client: (event) => [event.clientX, event.clientY],\n  screen: (event) => [event.screenX, event.screenY],\n  movement: (event) => event instanceof MouseEvent ? [event.movementX, event.movementY] : null\n};\nfunction useMouse(options = {}) {\n  const {\n    type = \"page\",\n    touch = true,\n    resetOnTouchEnds = false,\n    initialValue = { x: 0, y: 0 },\n    window = defaultWindow,\n    target = window,\n    scroll = true,\n    eventFilter\n  } = options;\n  let _prevMouseEvent = null;\n  let _prevScrollX = 0;\n  let _prevScrollY = 0;\n  const x = shallowRef(initialValue.x);\n  const y = shallowRef(initialValue.y);\n  const sourceType = shallowRef(null);\n  const extractor = typeof type === \"function\" ? type : UseMouseBuiltinExtractors[type];\n  const mouseHandler = (event) => {\n    const result = extractor(event);\n    _prevMouseEvent = event;\n    if (result) {\n      [x.value, y.value] = result;\n      sourceType.value = \"mouse\";\n    }\n    if (window) {\n      _prevScrollX = window.scrollX;\n      _prevScrollY = window.scrollY;\n    }\n  };\n  const touchHandler = (event) => {\n    if (event.touches.length > 0) {\n      const result = extractor(event.touches[0]);\n      if (result) {\n        [x.value, y.value] = result;\n        sourceType.value = \"touch\";\n      }\n    }\n  };\n  const scrollHandler = () => {\n    if (!_prevMouseEvent || !window)\n      return;\n    const pos = extractor(_prevMouseEvent);\n    if (_prevMouseEvent instanceof MouseEvent && pos) {\n      x.value = pos[0] + window.scrollX - _prevScrollX;\n      y.value = pos[1] + window.scrollY - _prevScrollY;\n    }\n  };\n  const reset = () => {\n    x.value = initialValue.x;\n    y.value = initialValue.y;\n  };\n  const mouseHandlerWrapper = eventFilter ? (event) => eventFilter(() => mouseHandler(event), {}) : (event) => mouseHandler(event);\n  const touchHandlerWrapper = eventFilter ? (event) => eventFilter(() => touchHandler(event), {}) : (event) => touchHandler(event);\n  const scrollHandlerWrapper = eventFilter ? () => eventFilter(() => scrollHandler(), {}) : () => scrollHandler();\n  if (target) {\n    const listenerOptions = { passive: true };\n    useEventListener(target, [\"mousemove\", \"dragover\"], mouseHandlerWrapper, listenerOptions);\n    if (touch && type !== \"movement\") {\n      useEventListener(target, [\"touchstart\", \"touchmove\"], touchHandlerWrapper, listenerOptions);\n      if (resetOnTouchEnds)\n        useEventListener(target, \"touchend\", reset, listenerOptions);\n    }\n    if (scroll && type === \"page\")\n      useEventListener(window, \"scroll\", scrollHandlerWrapper, listenerOptions);\n  }\n  return {\n    x,\n    y,\n    sourceType\n  };\n}\n\nfunction useMouseInElement(target, options = {}) {\n  const {\n    windowResize = true,\n    windowScroll = true,\n    handleOutside = true,\n    window = defaultWindow\n  } = options;\n  const type = options.type || \"page\";\n  const { x, y, sourceType } = useMouse(options);\n  const targetRef = shallowRef(target != null ? target : window == null ? void 0 : window.document.body);\n  const elementX = shallowRef(0);\n  const elementY = shallowRef(0);\n  const elementPositionX = shallowRef(0);\n  const elementPositionY = shallowRef(0);\n  const elementHeight = shallowRef(0);\n  const elementWidth = shallowRef(0);\n  const isOutside = shallowRef(true);\n  function update() {\n    if (!window)\n      return;\n    const el = unrefElement(targetRef);\n    if (!el || !(el instanceof Element))\n      return;\n    const {\n      left,\n      top,\n      width,\n      height\n    } = el.getBoundingClientRect();\n    elementPositionX.value = left + (type === \"page\" ? window.pageXOffset : 0);\n    elementPositionY.value = top + (type === \"page\" ? window.pageYOffset : 0);\n    elementHeight.value = height;\n    elementWidth.value = width;\n    const elX = x.value - elementPositionX.value;\n    const elY = y.value - elementPositionY.value;\n    isOutside.value = width === 0 || height === 0 || elX < 0 || elY < 0 || elX > width || elY > height;\n    if (handleOutside || !isOutside.value) {\n      elementX.value = elX;\n      elementY.value = elY;\n    }\n  }\n  const stopFnList = [];\n  function stop() {\n    stopFnList.forEach((fn) => fn());\n    stopFnList.length = 0;\n  }\n  tryOnMounted(() => {\n    update();\n  });\n  if (window) {\n    const {\n      stop: stopResizeObserver\n    } = useResizeObserver(targetRef, update);\n    const {\n      stop: stopMutationObserver\n    } = useMutationObserver(targetRef, update, {\n      attributeFilter: [\"style\", \"class\"]\n    });\n    const stopWatch = watch(\n      [targetRef, x, y],\n      update\n    );\n    stopFnList.push(\n      stopResizeObserver,\n      stopMutationObserver,\n      stopWatch\n    );\n    useEventListener(\n      document,\n      \"mouseleave\",\n      () => isOutside.value = true,\n      { passive: true }\n    );\n    if (windowScroll) {\n      stopFnList.push(\n        useEventListener(\"scroll\", update, { capture: true, passive: true })\n      );\n    }\n    if (windowResize) {\n      stopFnList.push(\n        useEventListener(\"resize\", update, { passive: true })\n      );\n    }\n  }\n  return {\n    x,\n    y,\n    sourceType,\n    elementX,\n    elementY,\n    elementPositionX,\n    elementPositionY,\n    elementHeight,\n    elementWidth,\n    isOutside,\n    stop\n  };\n}\n\nfunction useMousePressed(options = {}) {\n  const {\n    touch = true,\n    drag = true,\n    capture = false,\n    initialValue = false,\n    window = defaultWindow\n  } = options;\n  const pressed = shallowRef(initialValue);\n  const sourceType = shallowRef(null);\n  if (!window) {\n    return {\n      pressed,\n      sourceType\n    };\n  }\n  const onPressed = (srcType) => (event) => {\n    var _a;\n    pressed.value = true;\n    sourceType.value = srcType;\n    (_a = options.onPressed) == null ? void 0 : _a.call(options, event);\n  };\n  const onReleased = (event) => {\n    var _a;\n    pressed.value = false;\n    sourceType.value = null;\n    (_a = options.onReleased) == null ? void 0 : _a.call(options, event);\n  };\n  const target = computed(() => unrefElement(options.target) || window);\n  const listenerOptions = { passive: true, capture };\n  useEventListener(target, \"mousedown\", onPressed(\"mouse\"), listenerOptions);\n  useEventListener(window, \"mouseleave\", onReleased, listenerOptions);\n  useEventListener(window, \"mouseup\", onReleased, listenerOptions);\n  if (drag) {\n    useEventListener(target, \"dragstart\", onPressed(\"mouse\"), listenerOptions);\n    useEventListener(window, \"drop\", onReleased, listenerOptions);\n    useEventListener(window, \"dragend\", onReleased, listenerOptions);\n  }\n  if (touch) {\n    useEventListener(target, \"touchstart\", onPressed(\"touch\"), listenerOptions);\n    useEventListener(window, \"touchend\", onReleased, listenerOptions);\n    useEventListener(window, \"touchcancel\", onReleased, listenerOptions);\n  }\n  return {\n    pressed,\n    sourceType\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useNavigatorLanguage(options = {}) {\n  const { window = defaultWindow } = options;\n  const navigator = window == null ? void 0 : window.navigator;\n  const isSupported = useSupported(() => navigator && \"language\" in navigator);\n  const language = shallowRef(navigator == null ? void 0 : navigator.language);\n  useEventListener(window, \"languagechange\", () => {\n    if (navigator)\n      language.value = navigator.language;\n  }, { passive: true });\n  return {\n    isSupported,\n    language\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useNetwork(options = {}) {\n  const { window = defaultWindow } = options;\n  const navigator = window == null ? void 0 : window.navigator;\n  const isSupported = useSupported(() => navigator && \"connection\" in navigator);\n  const isOnline = shallowRef(true);\n  const saveData = shallowRef(false);\n  const offlineAt = shallowRef(void 0);\n  const onlineAt = shallowRef(void 0);\n  const downlink = shallowRef(void 0);\n  const downlinkMax = shallowRef(void 0);\n  const rtt = shallowRef(void 0);\n  const effectiveType = shallowRef(void 0);\n  const type = shallowRef(\"unknown\");\n  const connection = isSupported.value && navigator.connection;\n  function updateNetworkInformation() {\n    if (!navigator)\n      return;\n    isOnline.value = navigator.onLine;\n    offlineAt.value = isOnline.value ? void 0 : Date.now();\n    onlineAt.value = isOnline.value ? Date.now() : void 0;\n    if (connection) {\n      downlink.value = connection.downlink;\n      downlinkMax.value = connection.downlinkMax;\n      effectiveType.value = connection.effectiveType;\n      rtt.value = connection.rtt;\n      saveData.value = connection.saveData;\n      type.value = connection.type;\n    }\n  }\n  const listenerOptions = { passive: true };\n  if (window) {\n    useEventListener(window, \"offline\", () => {\n      isOnline.value = false;\n      offlineAt.value = Date.now();\n    }, listenerOptions);\n    useEventListener(window, \"online\", () => {\n      isOnline.value = true;\n      onlineAt.value = Date.now();\n    }, listenerOptions);\n  }\n  if (connection)\n    useEventListener(connection, \"change\", updateNetworkInformation, listenerOptions);\n  updateNetworkInformation();\n  return {\n    isSupported,\n    isOnline: readonly(isOnline),\n    saveData: readonly(saveData),\n    offlineAt: readonly(offlineAt),\n    onlineAt: readonly(onlineAt),\n    downlink: readonly(downlink),\n    downlinkMax: readonly(downlinkMax),\n    effectiveType: readonly(effectiveType),\n    rtt: readonly(rtt),\n    type: readonly(type)\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useNow(options = {}) {\n  const {\n    controls: exposeControls = false,\n    interval = \"requestAnimationFrame\",\n    immediate = true\n  } = options;\n  const now = ref(/* @__PURE__ */ new Date());\n  const update = () => now.value = /* @__PURE__ */ new Date();\n  const controls = interval === \"requestAnimationFrame\" ? useRafFn(update, { immediate }) : useIntervalFn(update, interval, { immediate });\n  if (exposeControls) {\n    return {\n      now,\n      ...controls\n    };\n  } else {\n    return now;\n  }\n}\n\nfunction useObjectUrl(object) {\n  const url = shallowRef();\n  const release = () => {\n    if (url.value)\n      URL.revokeObjectURL(url.value);\n    url.value = void 0;\n  };\n  watch(\n    () => toValue(object),\n    (newObject) => {\n      release();\n      if (newObject)\n        url.value = URL.createObjectURL(newObject);\n    },\n    { immediate: true }\n  );\n  tryOnScopeDispose(release);\n  return readonly(url);\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useClamp(value, min, max) {\n  if (typeof value === \"function\" || isReadonly(value))\n    return computed(() => clamp(toValue(value), toValue(min), toValue(max)));\n  const _value = ref(value);\n  return computed({\n    get() {\n      return _value.value = clamp(_value.value, toValue(min), toValue(max));\n    },\n    set(value2) {\n      _value.value = clamp(value2, toValue(min), toValue(max));\n    }\n  });\n}\n\nfunction useOffsetPagination(options) {\n  const {\n    total = Number.POSITIVE_INFINITY,\n    pageSize = 10,\n    page = 1,\n    onPageChange = noop,\n    onPageSizeChange = noop,\n    onPageCountChange = noop\n  } = options;\n  const currentPageSize = useClamp(pageSize, 1, Number.POSITIVE_INFINITY);\n  const pageCount = computed(() => Math.max(\n    1,\n    Math.ceil(toValue(total) / toValue(currentPageSize))\n  ));\n  const currentPage = useClamp(page, 1, pageCount);\n  const isFirstPage = computed(() => currentPage.value === 1);\n  const isLastPage = computed(() => currentPage.value === pageCount.value);\n  if (isRef(page)) {\n    syncRef(page, currentPage, {\n      direction: isReadonly(page) ? \"ltr\" : \"both\"\n    });\n  }\n  if (isRef(pageSize)) {\n    syncRef(pageSize, currentPageSize, {\n      direction: isReadonly(pageSize) ? \"ltr\" : \"both\"\n    });\n  }\n  function prev() {\n    currentPage.value--;\n  }\n  function next() {\n    currentPage.value++;\n  }\n  const returnValue = {\n    currentPage,\n    currentPageSize,\n    pageCount,\n    isFirstPage,\n    isLastPage,\n    prev,\n    next\n  };\n  watch(currentPage, () => {\n    onPageChange(reactive(returnValue));\n  });\n  watch(currentPageSize, () => {\n    onPageSizeChange(reactive(returnValue));\n  });\n  watch(pageCount, () => {\n    onPageCountChange(reactive(returnValue));\n  });\n  return returnValue;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useOnline(options = {}) {\n  const { isOnline } = useNetwork(options);\n  return isOnline;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction usePageLeave(options = {}) {\n  const { window = defaultWindow } = options;\n  const isLeft = shallowRef(false);\n  const handler = (event) => {\n    if (!window)\n      return;\n    event = event || window.event;\n    const from = event.relatedTarget || event.toElement;\n    isLeft.value = !from;\n  };\n  if (window) {\n    const listenerOptions = { passive: true };\n    useEventListener(window, \"mouseout\", handler, listenerOptions);\n    useEventListener(window.document, \"mouseleave\", handler, listenerOptions);\n    useEventListener(window.document, \"mouseenter\", handler, listenerOptions);\n  }\n  return isLeft;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useScreenOrientation(options = {}) {\n  const {\n    window = defaultWindow\n  } = options;\n  const isSupported = useSupported(() => window && \"screen\" in window && \"orientation\" in window.screen);\n  const screenOrientation = isSupported.value ? window.screen.orientation : {};\n  const orientation = ref(screenOrientation.type);\n  const angle = shallowRef(screenOrientation.angle || 0);\n  if (isSupported.value) {\n    useEventListener(window, \"orientationchange\", () => {\n      orientation.value = screenOrientation.type;\n      angle.value = screenOrientation.angle;\n    }, { passive: true });\n  }\n  const lockOrientation = (type) => {\n    if (isSupported.value && typeof screenOrientation.lock === \"function\")\n      return screenOrientation.lock(type);\n    return Promise.reject(new Error(\"Not supported\"));\n  };\n  const unlockOrientation = () => {\n    if (isSupported.value && typeof screenOrientation.unlock === \"function\")\n      screenOrientation.unlock();\n  };\n  return {\n    isSupported,\n    orientation,\n    angle,\n    lockOrientation,\n    unlockOrientation\n  };\n}\n\nfunction useParallax(target, options = {}) {\n  const {\n    deviceOrientationTiltAdjust = (i) => i,\n    deviceOrientationRollAdjust = (i) => i,\n    mouseTiltAdjust = (i) => i,\n    mouseRollAdjust = (i) => i,\n    window = defaultWindow\n  } = options;\n  const orientation = reactive(useDeviceOrientation({ window }));\n  const screenOrientation = reactive(useScreenOrientation({ window }));\n  const {\n    elementX: x,\n    elementY: y,\n    elementWidth: width,\n    elementHeight: height\n  } = useMouseInElement(target, { handleOutside: false, window });\n  const source = computed(() => {\n    if (orientation.isSupported && (orientation.alpha != null && orientation.alpha !== 0 || orientation.gamma != null && orientation.gamma !== 0)) {\n      return \"deviceOrientation\";\n    }\n    return \"mouse\";\n  });\n  const roll = computed(() => {\n    if (source.value === \"deviceOrientation\") {\n      let value;\n      switch (screenOrientation.orientation) {\n        case \"landscape-primary\":\n          value = orientation.gamma / 90;\n          break;\n        case \"landscape-secondary\":\n          value = -orientation.gamma / 90;\n          break;\n        case \"portrait-primary\":\n          value = -orientation.beta / 90;\n          break;\n        case \"portrait-secondary\":\n          value = orientation.beta / 90;\n          break;\n        default:\n          value = -orientation.beta / 90;\n      }\n      return deviceOrientationRollAdjust(value);\n    } else {\n      const value = -(y.value - height.value / 2) / height.value;\n      return mouseRollAdjust(value);\n    }\n  });\n  const tilt = computed(() => {\n    if (source.value === \"deviceOrientation\") {\n      let value;\n      switch (screenOrientation.orientation) {\n        case \"landscape-primary\":\n          value = orientation.beta / 90;\n          break;\n        case \"landscape-secondary\":\n          value = -orientation.beta / 90;\n          break;\n        case \"portrait-primary\":\n          value = orientation.gamma / 90;\n          break;\n        case \"portrait-secondary\":\n          value = -orientation.gamma / 90;\n          break;\n        default:\n          value = orientation.gamma / 90;\n      }\n      return deviceOrientationTiltAdjust(value);\n    } else {\n      const value = (x.value - width.value / 2) / width.value;\n      return mouseTiltAdjust(value);\n    }\n  });\n  return { roll, tilt, source };\n}\n\nfunction useParentElement(element = useCurrentElement()) {\n  const parentElement = shallowRef();\n  const update = () => {\n    const el = unrefElement(element);\n    if (el)\n      parentElement.value = el.parentElement;\n  };\n  tryOnMounted(update);\n  watch(() => toValue(element), update);\n  return parentElement;\n}\n\nfunction usePerformanceObserver(options, callback) {\n  const {\n    window = defaultWindow,\n    immediate = true,\n    ...performanceOptions\n  } = options;\n  const isSupported = useSupported(() => window && \"PerformanceObserver\" in window);\n  let observer;\n  const stop = () => {\n    observer == null ? void 0 : observer.disconnect();\n  };\n  const start = () => {\n    if (isSupported.value) {\n      stop();\n      observer = new PerformanceObserver(callback);\n      observer.observe(performanceOptions);\n    }\n  };\n  tryOnScopeDispose(stop);\n  if (immediate)\n    start();\n  return {\n    isSupported,\n    start,\n    stop\n  };\n}\n\nconst defaultState = {\n  x: 0,\n  y: 0,\n  pointerId: 0,\n  pressure: 0,\n  tiltX: 0,\n  tiltY: 0,\n  width: 0,\n  height: 0,\n  twist: 0,\n  pointerType: null\n};\nconst keys = /* @__PURE__ */ Object.keys(defaultState);\nfunction usePointer(options = {}) {\n  const {\n    target = defaultWindow\n  } = options;\n  const isInside = shallowRef(false);\n  const state = shallowRef(options.initialValue || {});\n  Object.assign(state.value, defaultState, state.value);\n  const handler = (event) => {\n    isInside.value = true;\n    if (options.pointerTypes && !options.pointerTypes.includes(event.pointerType))\n      return;\n    state.value = objectPick(event, keys, false);\n  };\n  if (target) {\n    const listenerOptions = { passive: true };\n    useEventListener(target, [\"pointerdown\", \"pointermove\", \"pointerup\"], handler, listenerOptions);\n    useEventListener(target, \"pointerleave\", () => isInside.value = false, listenerOptions);\n  }\n  return {\n    ...toRefs(state),\n    isInside\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction usePointerLock(target, options = {}) {\n  const { document = defaultDocument } = options;\n  const isSupported = useSupported(() => document && \"pointerLockElement\" in document);\n  const element = shallowRef();\n  const triggerElement = shallowRef();\n  let targetElement;\n  if (isSupported.value) {\n    const listenerOptions = { passive: true };\n    useEventListener(document, \"pointerlockchange\", () => {\n      var _a;\n      const currentElement = (_a = document.pointerLockElement) != null ? _a : element.value;\n      if (targetElement && currentElement === targetElement) {\n        element.value = document.pointerLockElement;\n        if (!element.value)\n          targetElement = triggerElement.value = null;\n      }\n    }, listenerOptions);\n    useEventListener(document, \"pointerlockerror\", () => {\n      var _a;\n      const currentElement = (_a = document.pointerLockElement) != null ? _a : element.value;\n      if (targetElement && currentElement === targetElement) {\n        const action = document.pointerLockElement ? \"release\" : \"acquire\";\n        throw new Error(`Failed to ${action} pointer lock.`);\n      }\n    }, listenerOptions);\n  }\n  async function lock(e) {\n    var _a;\n    if (!isSupported.value)\n      throw new Error(\"Pointer Lock API is not supported by your browser.\");\n    triggerElement.value = e instanceof Event ? e.currentTarget : null;\n    targetElement = e instanceof Event ? (_a = unrefElement(target)) != null ? _a : triggerElement.value : unrefElement(e);\n    if (!targetElement)\n      throw new Error(\"Target element undefined.\");\n    targetElement.requestPointerLock();\n    return await until(element).toBe(targetElement);\n  }\n  async function unlock() {\n    if (!element.value)\n      return false;\n    document.exitPointerLock();\n    await until(element).toBeNull();\n    return true;\n  }\n  return {\n    isSupported,\n    element,\n    triggerElement,\n    lock,\n    unlock\n  };\n}\n\nfunction usePointerSwipe(target, options = {}) {\n  const targetRef = toRef(target);\n  const {\n    threshold = 50,\n    onSwipe,\n    onSwipeEnd,\n    onSwipeStart,\n    disableTextSelect = false\n  } = options;\n  const posStart = reactive({ x: 0, y: 0 });\n  const updatePosStart = (x, y) => {\n    posStart.x = x;\n    posStart.y = y;\n  };\n  const posEnd = reactive({ x: 0, y: 0 });\n  const updatePosEnd = (x, y) => {\n    posEnd.x = x;\n    posEnd.y = y;\n  };\n  const distanceX = computed(() => posStart.x - posEnd.x);\n  const distanceY = computed(() => posStart.y - posEnd.y);\n  const { max, abs } = Math;\n  const isThresholdExceeded = computed(() => max(abs(distanceX.value), abs(distanceY.value)) >= threshold);\n  const isSwiping = shallowRef(false);\n  const isPointerDown = shallowRef(false);\n  const direction = computed(() => {\n    if (!isThresholdExceeded.value)\n      return \"none\";\n    if (abs(distanceX.value) > abs(distanceY.value)) {\n      return distanceX.value > 0 ? \"left\" : \"right\";\n    } else {\n      return distanceY.value > 0 ? \"up\" : \"down\";\n    }\n  });\n  const eventIsAllowed = (e) => {\n    var _a, _b, _c;\n    const isReleasingButton = e.buttons === 0;\n    const isPrimaryButton = e.buttons === 1;\n    return (_c = (_b = (_a = options.pointerTypes) == null ? void 0 : _a.includes(e.pointerType)) != null ? _b : isReleasingButton || isPrimaryButton) != null ? _c : true;\n  };\n  const listenerOptions = { passive: true };\n  const stops = [\n    useEventListener(target, \"pointerdown\", (e) => {\n      if (!eventIsAllowed(e))\n        return;\n      isPointerDown.value = true;\n      const eventTarget = e.target;\n      eventTarget == null ? void 0 : eventTarget.setPointerCapture(e.pointerId);\n      const { clientX: x, clientY: y } = e;\n      updatePosStart(x, y);\n      updatePosEnd(x, y);\n      onSwipeStart == null ? void 0 : onSwipeStart(e);\n    }, listenerOptions),\n    useEventListener(target, \"pointermove\", (e) => {\n      if (!eventIsAllowed(e))\n        return;\n      if (!isPointerDown.value)\n        return;\n      const { clientX: x, clientY: y } = e;\n      updatePosEnd(x, y);\n      if (!isSwiping.value && isThresholdExceeded.value)\n        isSwiping.value = true;\n      if (isSwiping.value)\n        onSwipe == null ? void 0 : onSwipe(e);\n    }, listenerOptions),\n    useEventListener(target, \"pointerup\", (e) => {\n      if (!eventIsAllowed(e))\n        return;\n      if (isSwiping.value)\n        onSwipeEnd == null ? void 0 : onSwipeEnd(e, direction.value);\n      isPointerDown.value = false;\n      isSwiping.value = false;\n    }, listenerOptions)\n  ];\n  tryOnMounted(() => {\n    var _a, _b, _c, _d, _e, _f, _g, _h;\n    (_b = (_a = targetRef.value) == null ? void 0 : _a.style) == null ? void 0 : _b.setProperty(\"touch-action\", \"pan-y\");\n    if (disableTextSelect) {\n      (_d = (_c = targetRef.value) == null ? void 0 : _c.style) == null ? void 0 : _d.setProperty(\"-webkit-user-select\", \"none\");\n      (_f = (_e = targetRef.value) == null ? void 0 : _e.style) == null ? void 0 : _f.setProperty(\"-ms-user-select\", \"none\");\n      (_h = (_g = targetRef.value) == null ? void 0 : _g.style) == null ? void 0 : _h.setProperty(\"user-select\", \"none\");\n    }\n  });\n  const stop = () => stops.forEach((s) => s());\n  return {\n    isSwiping: readonly(isSwiping),\n    direction: readonly(direction),\n    posStart: readonly(posStart),\n    posEnd: readonly(posEnd),\n    distanceX,\n    distanceY,\n    stop\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction usePreferredColorScheme(options) {\n  const isLight = useMediaQuery(\"(prefers-color-scheme: light)\", options);\n  const isDark = useMediaQuery(\"(prefers-color-scheme: dark)\", options);\n  return computed(() => {\n    if (isDark.value)\n      return \"dark\";\n    if (isLight.value)\n      return \"light\";\n    return \"no-preference\";\n  });\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction usePreferredContrast(options) {\n  const isMore = useMediaQuery(\"(prefers-contrast: more)\", options);\n  const isLess = useMediaQuery(\"(prefers-contrast: less)\", options);\n  const isCustom = useMediaQuery(\"(prefers-contrast: custom)\", options);\n  return computed(() => {\n    if (isMore.value)\n      return \"more\";\n    if (isLess.value)\n      return \"less\";\n    if (isCustom.value)\n      return \"custom\";\n    return \"no-preference\";\n  });\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction usePreferredLanguages(options = {}) {\n  const { window = defaultWindow } = options;\n  if (!window)\n    return shallowRef([\"en\"]);\n  const navigator = window.navigator;\n  const value = shallowRef(navigator.languages);\n  useEventListener(window, \"languagechange\", () => {\n    value.value = navigator.languages;\n  }, { passive: true });\n  return value;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction usePreferredReducedMotion(options) {\n  const isReduced = useMediaQuery(\"(prefers-reduced-motion: reduce)\", options);\n  return computed(() => {\n    if (isReduced.value)\n      return \"reduce\";\n    return \"no-preference\";\n  });\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction usePreferredReducedTransparency(options) {\n  const isReduced = useMediaQuery(\"(prefers-reduced-transparency: reduce)\", options);\n  return computed(() => {\n    if (isReduced.value)\n      return \"reduce\";\n    return \"no-preference\";\n  });\n}\n\nfunction usePrevious(value, initialValue) {\n  const previous = shallowRef(initialValue);\n  watch(\n    toRef(value),\n    (_, oldValue) => {\n      previous.value = oldValue;\n    },\n    { flush: \"sync\" }\n  );\n  return readonly(previous);\n}\n\nconst topVarName = \"--vueuse-safe-area-top\";\nconst rightVarName = \"--vueuse-safe-area-right\";\nconst bottomVarName = \"--vueuse-safe-area-bottom\";\nconst leftVarName = \"--vueuse-safe-area-left\";\nfunction useScreenSafeArea() {\n  const top = shallowRef(\"\");\n  const right = shallowRef(\"\");\n  const bottom = shallowRef(\"\");\n  const left = shallowRef(\"\");\n  if (isClient) {\n    const topCssVar = useCssVar(topVarName);\n    const rightCssVar = useCssVar(rightVarName);\n    const bottomCssVar = useCssVar(bottomVarName);\n    const leftCssVar = useCssVar(leftVarName);\n    topCssVar.value = \"env(safe-area-inset-top, 0px)\";\n    rightCssVar.value = \"env(safe-area-inset-right, 0px)\";\n    bottomCssVar.value = \"env(safe-area-inset-bottom, 0px)\";\n    leftCssVar.value = \"env(safe-area-inset-left, 0px)\";\n    tryOnMounted(update);\n    useEventListener(\"resize\", useDebounceFn(update), { passive: true });\n  }\n  function update() {\n    top.value = getValue(topVarName);\n    right.value = getValue(rightVarName);\n    bottom.value = getValue(bottomVarName);\n    left.value = getValue(leftVarName);\n  }\n  return {\n    top,\n    right,\n    bottom,\n    left,\n    update\n  };\n}\nfunction getValue(position) {\n  return getComputedStyle(document.documentElement).getPropertyValue(position);\n}\n\nfunction useScriptTag(src, onLoaded = noop, options = {}) {\n  const {\n    immediate = true,\n    manual = false,\n    type = \"text/javascript\",\n    async = true,\n    crossOrigin,\n    referrerPolicy,\n    noModule,\n    defer,\n    document = defaultDocument,\n    attrs = {},\n    nonce = void 0\n  } = options;\n  const scriptTag = shallowRef(null);\n  let _promise = null;\n  const loadScript = (waitForScriptLoad) => new Promise((resolve, reject) => {\n    const resolveWithElement = (el2) => {\n      scriptTag.value = el2;\n      resolve(el2);\n      return el2;\n    };\n    if (!document) {\n      resolve(false);\n      return;\n    }\n    let shouldAppend = false;\n    let el = document.querySelector(`script[src=\"${toValue(src)}\"]`);\n    if (!el) {\n      el = document.createElement(\"script\");\n      el.type = type;\n      el.async = async;\n      el.src = toValue(src);\n      if (defer)\n        el.defer = defer;\n      if (crossOrigin)\n        el.crossOrigin = crossOrigin;\n      if (noModule)\n        el.noModule = noModule;\n      if (referrerPolicy)\n        el.referrerPolicy = referrerPolicy;\n      if (nonce) {\n        el.nonce = nonce;\n      }\n      Object.entries(attrs).forEach(([name, value]) => el == null ? void 0 : el.setAttribute(name, value));\n      shouldAppend = true;\n    } else if (el.hasAttribute(\"data-loaded\")) {\n      resolveWithElement(el);\n    }\n    const listenerOptions = {\n      passive: true\n    };\n    useEventListener(el, \"error\", (event) => reject(event), listenerOptions);\n    useEventListener(el, \"abort\", (event) => reject(event), listenerOptions);\n    useEventListener(el, \"load\", () => {\n      el.setAttribute(\"data-loaded\", \"true\");\n      onLoaded(el);\n      resolveWithElement(el);\n    }, listenerOptions);\n    if (shouldAppend)\n      el = document.head.appendChild(el);\n    if (!waitForScriptLoad)\n      resolveWithElement(el);\n  });\n  const load = (waitForScriptLoad = true) => {\n    if (!_promise)\n      _promise = loadScript(waitForScriptLoad);\n    return _promise;\n  };\n  const unload = () => {\n    if (!document)\n      return;\n    _promise = null;\n    if (scriptTag.value)\n      scriptTag.value = null;\n    const el = document.querySelector(`script[src=\"${toValue(src)}\"]`);\n    if (el)\n      document.head.removeChild(el);\n  };\n  if (immediate && !manual)\n    tryOnMounted(load);\n  if (!manual)\n    tryOnUnmounted(unload);\n  return { scriptTag, load, unload };\n}\n\nfunction checkOverflowScroll(ele) {\n  const style = window.getComputedStyle(ele);\n  if (style.overflowX === \"scroll\" || style.overflowY === \"scroll\" || style.overflowX === \"auto\" && ele.clientWidth < ele.scrollWidth || style.overflowY === \"auto\" && ele.clientHeight < ele.scrollHeight) {\n    return true;\n  } else {\n    const parent = ele.parentNode;\n    if (!parent || parent.tagName === \"BODY\")\n      return false;\n    return checkOverflowScroll(parent);\n  }\n}\nfunction preventDefault(rawEvent) {\n  const e = rawEvent || window.event;\n  const _target = e.target;\n  if (checkOverflowScroll(_target))\n    return false;\n  if (e.touches.length > 1)\n    return true;\n  if (e.preventDefault)\n    e.preventDefault();\n  return false;\n}\nconst elInitialOverflow = /* @__PURE__ */ new WeakMap();\nfunction useScrollLock(element, initialState = false) {\n  const isLocked = shallowRef(initialState);\n  let stopTouchMoveListener = null;\n  let initialOverflow = \"\";\n  watch(toRef(element), (el) => {\n    const target = resolveElement(toValue(el));\n    if (target) {\n      const ele = target;\n      if (!elInitialOverflow.get(ele))\n        elInitialOverflow.set(ele, ele.style.overflow);\n      if (ele.style.overflow !== \"hidden\")\n        initialOverflow = ele.style.overflow;\n      if (ele.style.overflow === \"hidden\")\n        return isLocked.value = true;\n      if (isLocked.value)\n        return ele.style.overflow = \"hidden\";\n    }\n  }, {\n    immediate: true\n  });\n  const lock = () => {\n    const el = resolveElement(toValue(element));\n    if (!el || isLocked.value)\n      return;\n    if (isIOS) {\n      stopTouchMoveListener = useEventListener(\n        el,\n        \"touchmove\",\n        (e) => {\n          preventDefault(e);\n        },\n        { passive: false }\n      );\n    }\n    el.style.overflow = \"hidden\";\n    isLocked.value = true;\n  };\n  const unlock = () => {\n    const el = resolveElement(toValue(element));\n    if (!el || !isLocked.value)\n      return;\n    if (isIOS)\n      stopTouchMoveListener == null ? void 0 : stopTouchMoveListener();\n    el.style.overflow = initialOverflow;\n    elInitialOverflow.delete(el);\n    isLocked.value = false;\n  };\n  tryOnScopeDispose(unlock);\n  return computed({\n    get() {\n      return isLocked.value;\n    },\n    set(v) {\n      if (v)\n        lock();\n      else unlock();\n    }\n  });\n}\n\nfunction useSessionStorage(key, initialValue, options = {}) {\n  const { window = defaultWindow } = options;\n  return useStorage(key, initialValue, window == null ? void 0 : window.sessionStorage, options);\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useShare(shareOptions = {}, options = {}) {\n  const { navigator = defaultNavigator } = options;\n  const _navigator = navigator;\n  const isSupported = useSupported(() => _navigator && \"canShare\" in _navigator);\n  const share = async (overrideOptions = {}) => {\n    if (isSupported.value) {\n      const data = {\n        ...toValue(shareOptions),\n        ...toValue(overrideOptions)\n      };\n      let granted = true;\n      if (data.files && _navigator.canShare)\n        granted = _navigator.canShare({ files: data.files });\n      if (granted)\n        return _navigator.share(data);\n    }\n  };\n  return {\n    isSupported,\n    share\n  };\n}\n\nconst defaultSortFn = (source, compareFn) => source.sort(compareFn);\nconst defaultCompare = (a, b) => a - b;\nfunction useSorted(...args) {\n  var _a, _b, _c, _d;\n  const [source] = args;\n  let compareFn = defaultCompare;\n  let options = {};\n  if (args.length === 2) {\n    if (typeof args[1] === \"object\") {\n      options = args[1];\n      compareFn = (_a = options.compareFn) != null ? _a : defaultCompare;\n    } else {\n      compareFn = (_b = args[1]) != null ? _b : defaultCompare;\n    }\n  } else if (args.length > 2) {\n    compareFn = (_c = args[1]) != null ? _c : defaultCompare;\n    options = (_d = args[2]) != null ? _d : {};\n  }\n  const {\n    dirty = false,\n    sortFn = defaultSortFn\n  } = options;\n  if (!dirty)\n    return computed(() => sortFn([...toValue(source)], compareFn));\n  watchEffect(() => {\n    const result = sortFn(toValue(source), compareFn);\n    if (isRef(source))\n      source.value = result;\n    else\n      source.splice(0, source.length, ...result);\n  });\n  return source;\n}\n\nfunction useSpeechRecognition(options = {}) {\n  const {\n    interimResults = true,\n    continuous = true,\n    maxAlternatives = 1,\n    window = defaultWindow\n  } = options;\n  const lang = toRef(options.lang || \"en-US\");\n  const isListening = shallowRef(false);\n  const isFinal = shallowRef(false);\n  const result = shallowRef(\"\");\n  const error = shallowRef(void 0);\n  let recognition;\n  const start = () => {\n    isListening.value = true;\n  };\n  const stop = () => {\n    isListening.value = false;\n  };\n  const toggle = (value = !isListening.value) => {\n    if (value) {\n      start();\n    } else {\n      stop();\n    }\n  };\n  const SpeechRecognition = window && (window.SpeechRecognition || window.webkitSpeechRecognition);\n  const isSupported = useSupported(() => SpeechRecognition);\n  if (isSupported.value) {\n    recognition = new SpeechRecognition();\n    recognition.continuous = continuous;\n    recognition.interimResults = interimResults;\n    recognition.lang = toValue(lang);\n    recognition.maxAlternatives = maxAlternatives;\n    recognition.onstart = () => {\n      isListening.value = true;\n      isFinal.value = false;\n    };\n    watch(lang, (lang2) => {\n      if (recognition && !isListening.value)\n        recognition.lang = lang2;\n    });\n    recognition.onresult = (event) => {\n      const currentResult = event.results[event.resultIndex];\n      const { transcript } = currentResult[0];\n      isFinal.value = currentResult.isFinal;\n      result.value = transcript;\n      error.value = void 0;\n    };\n    recognition.onerror = (event) => {\n      error.value = event;\n    };\n    recognition.onend = () => {\n      isListening.value = false;\n      recognition.lang = toValue(lang);\n    };\n    watch(isListening, (newValue, oldValue) => {\n      if (newValue === oldValue)\n        return;\n      if (newValue)\n        recognition.start();\n      else\n        recognition.stop();\n    });\n  }\n  tryOnScopeDispose(() => {\n    stop();\n  });\n  return {\n    isSupported,\n    isListening,\n    isFinal,\n    recognition,\n    result,\n    error,\n    toggle,\n    start,\n    stop\n  };\n}\n\nfunction useSpeechSynthesis(text, options = {}) {\n  const {\n    pitch = 1,\n    rate = 1,\n    volume = 1,\n    window = defaultWindow,\n    onBoundary\n  } = options;\n  const synth = window && window.speechSynthesis;\n  const isSupported = useSupported(() => synth);\n  const isPlaying = shallowRef(false);\n  const status = shallowRef(\"init\");\n  const spokenText = toRef(text || \"\");\n  const lang = toRef(options.lang || \"en-US\");\n  const error = shallowRef(void 0);\n  const toggle = (value = !isPlaying.value) => {\n    isPlaying.value = value;\n  };\n  const bindEventsForUtterance = (utterance2) => {\n    utterance2.lang = toValue(lang);\n    utterance2.voice = toValue(options.voice) || null;\n    utterance2.pitch = toValue(pitch);\n    utterance2.rate = toValue(rate);\n    utterance2.volume = toValue(volume);\n    utterance2.onstart = () => {\n      isPlaying.value = true;\n      status.value = \"play\";\n    };\n    utterance2.onpause = () => {\n      isPlaying.value = false;\n      status.value = \"pause\";\n    };\n    utterance2.onresume = () => {\n      isPlaying.value = true;\n      status.value = \"play\";\n    };\n    utterance2.onend = () => {\n      isPlaying.value = false;\n      status.value = \"end\";\n    };\n    utterance2.onerror = (event) => {\n      error.value = event;\n    };\n    utterance2.onboundary = (event) => {\n      onBoundary == null ? void 0 : onBoundary(event);\n    };\n  };\n  const utterance = computed(() => {\n    isPlaying.value = false;\n    status.value = \"init\";\n    const newUtterance = new SpeechSynthesisUtterance(spokenText.value);\n    bindEventsForUtterance(newUtterance);\n    return newUtterance;\n  });\n  const speak = () => {\n    synth.cancel();\n    if (utterance)\n      synth.speak(utterance.value);\n  };\n  const stop = () => {\n    synth.cancel();\n    isPlaying.value = false;\n  };\n  if (isSupported.value) {\n    bindEventsForUtterance(utterance.value);\n    watch(lang, (lang2) => {\n      if (utterance.value && !isPlaying.value)\n        utterance.value.lang = lang2;\n    });\n    if (options.voice) {\n      watch(options.voice, () => {\n        synth.cancel();\n      });\n    }\n    watch(isPlaying, () => {\n      if (isPlaying.value)\n        synth.resume();\n      else\n        synth.pause();\n    });\n  }\n  tryOnScopeDispose(() => {\n    isPlaying.value = false;\n  });\n  return {\n    isSupported,\n    isPlaying,\n    status,\n    utterance,\n    error,\n    stop,\n    toggle,\n    speak\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useStepper(steps, initialStep) {\n  const stepsRef = ref(steps);\n  const stepNames = computed(() => Array.isArray(stepsRef.value) ? stepsRef.value : Object.keys(stepsRef.value));\n  const index = ref(stepNames.value.indexOf(initialStep != null ? initialStep : stepNames.value[0]));\n  const current = computed(() => at(index.value));\n  const isFirst = computed(() => index.value === 0);\n  const isLast = computed(() => index.value === stepNames.value.length - 1);\n  const next = computed(() => stepNames.value[index.value + 1]);\n  const previous = computed(() => stepNames.value[index.value - 1]);\n  function at(index2) {\n    if (Array.isArray(stepsRef.value))\n      return stepsRef.value[index2];\n    return stepsRef.value[stepNames.value[index2]];\n  }\n  function get(step) {\n    if (!stepNames.value.includes(step))\n      return;\n    return at(stepNames.value.indexOf(step));\n  }\n  function goTo(step) {\n    if (stepNames.value.includes(step))\n      index.value = stepNames.value.indexOf(step);\n  }\n  function goToNext() {\n    if (isLast.value)\n      return;\n    index.value++;\n  }\n  function goToPrevious() {\n    if (isFirst.value)\n      return;\n    index.value--;\n  }\n  function goBackTo(step) {\n    if (isAfter(step))\n      goTo(step);\n  }\n  function isNext(step) {\n    return stepNames.value.indexOf(step) === index.value + 1;\n  }\n  function isPrevious(step) {\n    return stepNames.value.indexOf(step) === index.value - 1;\n  }\n  function isCurrent(step) {\n    return stepNames.value.indexOf(step) === index.value;\n  }\n  function isBefore(step) {\n    return index.value < stepNames.value.indexOf(step);\n  }\n  function isAfter(step) {\n    return index.value > stepNames.value.indexOf(step);\n  }\n  return {\n    steps: stepsRef,\n    stepNames,\n    index,\n    current,\n    next,\n    previous,\n    isFirst,\n    isLast,\n    at,\n    get,\n    goTo,\n    goToNext,\n    goToPrevious,\n    goBackTo,\n    isNext,\n    isPrevious,\n    isCurrent,\n    isBefore,\n    isAfter\n  };\n}\n\nfunction useStorageAsync(key, initialValue, storage, options = {}) {\n  var _a;\n  const {\n    flush = \"pre\",\n    deep = true,\n    listenToStorageChanges = true,\n    writeDefaults = true,\n    mergeDefaults = false,\n    shallow,\n    window = defaultWindow,\n    eventFilter,\n    onError = (e) => {\n      console.error(e);\n    },\n    onReady\n  } = options;\n  const rawInit = toValue(initialValue);\n  const type = guessSerializerType(rawInit);\n  const data = (shallow ? shallowRef : ref)(toValue(initialValue));\n  const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type];\n  if (!storage) {\n    try {\n      storage = getSSRHandler(\"getDefaultStorageAsync\", () => {\n        var _a2;\n        return (_a2 = defaultWindow) == null ? void 0 : _a2.localStorage;\n      })();\n    } catch (e) {\n      onError(e);\n    }\n  }\n  async function read(event) {\n    if (!storage || event && event.key !== key)\n      return;\n    try {\n      const rawValue = event ? event.newValue : await storage.getItem(key);\n      if (rawValue == null) {\n        data.value = rawInit;\n        if (writeDefaults && rawInit !== null)\n          await storage.setItem(key, await serializer.write(rawInit));\n      } else if (mergeDefaults) {\n        const value = await serializer.read(rawValue);\n        if (typeof mergeDefaults === \"function\")\n          data.value = mergeDefaults(value, rawInit);\n        else if (type === \"object\" && !Array.isArray(value))\n          data.value = { ...rawInit, ...value };\n        else data.value = value;\n      } else {\n        data.value = await serializer.read(rawValue);\n      }\n    } catch (e) {\n      onError(e);\n    }\n  }\n  const promise = new Promise((resolve) => {\n    read().then(() => {\n      onReady == null ? void 0 : onReady(data.value);\n      resolve(data);\n    });\n  });\n  if (window && listenToStorageChanges)\n    useEventListener(window, \"storage\", (e) => Promise.resolve().then(() => read(e)), { passive: true });\n  if (storage) {\n    watchWithFilter(\n      data,\n      async () => {\n        try {\n          if (data.value == null)\n            await storage.removeItem(key);\n          else\n            await storage.setItem(key, await serializer.write(data.value));\n        } catch (e) {\n          onError(e);\n        }\n      },\n      {\n        flush,\n        deep,\n        eventFilter\n      }\n    );\n  }\n  Object.assign(data, {\n    then: promise.then.bind(promise),\n    catch: promise.catch.bind(promise)\n  });\n  return data;\n}\n\nlet _id = 0;\nfunction useStyleTag(css, options = {}) {\n  const isLoaded = shallowRef(false);\n  const {\n    document = defaultDocument,\n    immediate = true,\n    manual = false,\n    id = `vueuse_styletag_${++_id}`\n  } = options;\n  const cssRef = shallowRef(css);\n  let stop = () => {\n  };\n  const load = () => {\n    if (!document)\n      return;\n    const el = document.getElementById(id) || document.createElement(\"style\");\n    if (!el.isConnected) {\n      el.id = id;\n      if (options.nonce)\n        el.nonce = options.nonce;\n      if (options.media)\n        el.media = options.media;\n      document.head.appendChild(el);\n    }\n    if (isLoaded.value)\n      return;\n    stop = watch(\n      cssRef,\n      (value) => {\n        el.textContent = value;\n      },\n      { immediate: true }\n    );\n    isLoaded.value = true;\n  };\n  const unload = () => {\n    if (!document || !isLoaded.value)\n      return;\n    stop();\n    document.head.removeChild(document.getElementById(id));\n    isLoaded.value = false;\n  };\n  if (immediate && !manual)\n    tryOnMounted(load);\n  if (!manual)\n    tryOnScopeDispose(unload);\n  return {\n    id,\n    css: cssRef,\n    unload,\n    load,\n    isLoaded: readonly(isLoaded)\n  };\n}\n\nfunction useSwipe(target, options = {}) {\n  const {\n    threshold = 50,\n    onSwipe,\n    onSwipeEnd,\n    onSwipeStart,\n    passive = true\n  } = options;\n  const coordsStart = reactive({ x: 0, y: 0 });\n  const coordsEnd = reactive({ x: 0, y: 0 });\n  const diffX = computed(() => coordsStart.x - coordsEnd.x);\n  const diffY = computed(() => coordsStart.y - coordsEnd.y);\n  const { max, abs } = Math;\n  const isThresholdExceeded = computed(() => max(abs(diffX.value), abs(diffY.value)) >= threshold);\n  const isSwiping = shallowRef(false);\n  const direction = computed(() => {\n    if (!isThresholdExceeded.value)\n      return \"none\";\n    if (abs(diffX.value) > abs(diffY.value)) {\n      return diffX.value > 0 ? \"left\" : \"right\";\n    } else {\n      return diffY.value > 0 ? \"up\" : \"down\";\n    }\n  });\n  const getTouchEventCoords = (e) => [e.touches[0].clientX, e.touches[0].clientY];\n  const updateCoordsStart = (x, y) => {\n    coordsStart.x = x;\n    coordsStart.y = y;\n  };\n  const updateCoordsEnd = (x, y) => {\n    coordsEnd.x = x;\n    coordsEnd.y = y;\n  };\n  const listenerOptions = { passive, capture: !passive };\n  const onTouchEnd = (e) => {\n    if (isSwiping.value)\n      onSwipeEnd == null ? void 0 : onSwipeEnd(e, direction.value);\n    isSwiping.value = false;\n  };\n  const stops = [\n    useEventListener(target, \"touchstart\", (e) => {\n      if (e.touches.length !== 1)\n        return;\n      const [x, y] = getTouchEventCoords(e);\n      updateCoordsStart(x, y);\n      updateCoordsEnd(x, y);\n      onSwipeStart == null ? void 0 : onSwipeStart(e);\n    }, listenerOptions),\n    useEventListener(target, \"touchmove\", (e) => {\n      if (e.touches.length !== 1)\n        return;\n      const [x, y] = getTouchEventCoords(e);\n      updateCoordsEnd(x, y);\n      if (listenerOptions.capture && !listenerOptions.passive && Math.abs(diffX.value) > Math.abs(diffY.value))\n        e.preventDefault();\n      if (!isSwiping.value && isThresholdExceeded.value)\n        isSwiping.value = true;\n      if (isSwiping.value)\n        onSwipe == null ? void 0 : onSwipe(e);\n    }, listenerOptions),\n    useEventListener(target, [\"touchend\", \"touchcancel\"], onTouchEnd, listenerOptions)\n  ];\n  const stop = () => stops.forEach((s) => s());\n  return {\n    isSwiping,\n    direction,\n    coordsStart,\n    coordsEnd,\n    lengthX: diffX,\n    lengthY: diffY,\n    stop,\n    // TODO: Remove in the next major version\n    isPassiveEventSupported: true\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useTemplateRefsList() {\n  const refs = ref([]);\n  refs.value.set = (el) => {\n    if (el)\n      refs.value.push(el);\n  };\n  onBeforeUpdate(() => {\n    refs.value.length = 0;\n  });\n  return refs;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useTextDirection(options = {}) {\n  const {\n    document = defaultDocument,\n    selector = \"html\",\n    observe = false,\n    initialValue = \"ltr\"\n  } = options;\n  function getValue() {\n    var _a, _b;\n    return (_b = (_a = document == null ? void 0 : document.querySelector(selector)) == null ? void 0 : _a.getAttribute(\"dir\")) != null ? _b : initialValue;\n  }\n  const dir = ref(getValue());\n  tryOnMounted(() => dir.value = getValue());\n  if (observe && document) {\n    useMutationObserver(\n      document.querySelector(selector),\n      () => dir.value = getValue(),\n      { attributes: true }\n    );\n  }\n  return computed({\n    get() {\n      return dir.value;\n    },\n    set(v) {\n      var _a, _b;\n      dir.value = v;\n      if (!document)\n        return;\n      if (dir.value)\n        (_a = document.querySelector(selector)) == null ? void 0 : _a.setAttribute(\"dir\", dir.value);\n      else\n        (_b = document.querySelector(selector)) == null ? void 0 : _b.removeAttribute(\"dir\");\n    }\n  });\n}\n\nfunction getRangesFromSelection(selection) {\n  var _a;\n  const rangeCount = (_a = selection.rangeCount) != null ? _a : 0;\n  return Array.from({ length: rangeCount }, (_, i) => selection.getRangeAt(i));\n}\n// @__NO_SIDE_EFFECTS__\nfunction useTextSelection(options = {}) {\n  const {\n    window = defaultWindow\n  } = options;\n  const selection = ref(null);\n  const text = computed(() => {\n    var _a, _b;\n    return (_b = (_a = selection.value) == null ? void 0 : _a.toString()) != null ? _b : \"\";\n  });\n  const ranges = computed(() => selection.value ? getRangesFromSelection(selection.value) : []);\n  const rects = computed(() => ranges.value.map((range) => range.getBoundingClientRect()));\n  function onSelectionChange() {\n    selection.value = null;\n    if (window)\n      selection.value = window.getSelection();\n  }\n  if (window)\n    useEventListener(window.document, \"selectionchange\", onSelectionChange, { passive: true });\n  return {\n    text,\n    rects,\n    ranges,\n    selection\n  };\n}\n\nfunction tryRequestAnimationFrame(window = defaultWindow, fn) {\n  if (window && typeof window.requestAnimationFrame === \"function\") {\n    window.requestAnimationFrame(fn);\n  } else {\n    fn();\n  }\n}\nfunction useTextareaAutosize(options = {}) {\n  var _a, _b;\n  const { window = defaultWindow } = options;\n  const textarea = toRef(options == null ? void 0 : options.element);\n  const input = toRef((_a = options == null ? void 0 : options.input) != null ? _a : \"\");\n  const styleProp = (_b = options == null ? void 0 : options.styleProp) != null ? _b : \"height\";\n  const textareaScrollHeight = shallowRef(1);\n  const textareaOldWidth = shallowRef(0);\n  function triggerResize() {\n    var _a2;\n    if (!textarea.value)\n      return;\n    let height = \"\";\n    textarea.value.style[styleProp] = \"1px\";\n    textareaScrollHeight.value = (_a2 = textarea.value) == null ? void 0 : _a2.scrollHeight;\n    const _styleTarget = toValue(options == null ? void 0 : options.styleTarget);\n    if (_styleTarget)\n      _styleTarget.style[styleProp] = `${textareaScrollHeight.value}px`;\n    else\n      height = `${textareaScrollHeight.value}px`;\n    textarea.value.style[styleProp] = height;\n  }\n  watch([input, textarea], () => nextTick(triggerResize), { immediate: true });\n  watch(textareaScrollHeight, () => {\n    var _a2;\n    return (_a2 = options == null ? void 0 : options.onResize) == null ? void 0 : _a2.call(options);\n  });\n  useResizeObserver(textarea, ([{ contentRect }]) => {\n    if (textareaOldWidth.value === contentRect.width)\n      return;\n    tryRequestAnimationFrame(window, () => {\n      textareaOldWidth.value = contentRect.width;\n      triggerResize();\n    });\n  });\n  if (options == null ? void 0 : options.watch)\n    watch(options.watch, triggerResize, { immediate: true, deep: true });\n  return {\n    textarea,\n    input,\n    triggerResize\n  };\n}\n\nfunction useThrottledRefHistory(source, options = {}) {\n  const { throttle = 200, trailing = true } = options;\n  const filter = throttleFilter(throttle, trailing);\n  const history = useRefHistory(source, { ...options, eventFilter: filter });\n  return {\n    ...history\n  };\n}\n\nconst DEFAULT_UNITS = [\n  { max: 6e4, value: 1e3, name: \"second\" },\n  { max: 276e4, value: 6e4, name: \"minute\" },\n  { max: 72e6, value: 36e5, name: \"hour\" },\n  { max: 5184e5, value: 864e5, name: \"day\" },\n  { max: 24192e5, value: 6048e5, name: \"week\" },\n  { max: 28512e6, value: 2592e6, name: \"month\" },\n  { max: Number.POSITIVE_INFINITY, value: 31536e6, name: \"year\" }\n];\nconst DEFAULT_MESSAGES = {\n  justNow: \"just now\",\n  past: (n) => n.match(/\\d/) ? `${n} ago` : n,\n  future: (n) => n.match(/\\d/) ? `in ${n}` : n,\n  month: (n, past) => n === 1 ? past ? \"last month\" : \"next month\" : `${n} month${n > 1 ? \"s\" : \"\"}`,\n  year: (n, past) => n === 1 ? past ? \"last year\" : \"next year\" : `${n} year${n > 1 ? \"s\" : \"\"}`,\n  day: (n, past) => n === 1 ? past ? \"yesterday\" : \"tomorrow\" : `${n} day${n > 1 ? \"s\" : \"\"}`,\n  week: (n, past) => n === 1 ? past ? \"last week\" : \"next week\" : `${n} week${n > 1 ? \"s\" : \"\"}`,\n  hour: (n) => `${n} hour${n > 1 ? \"s\" : \"\"}`,\n  minute: (n) => `${n} minute${n > 1 ? \"s\" : \"\"}`,\n  second: (n) => `${n} second${n > 1 ? \"s\" : \"\"}`,\n  invalid: \"\"\n};\nfunction DEFAULT_FORMATTER(date) {\n  return date.toISOString().slice(0, 10);\n}\n// @__NO_SIDE_EFFECTS__\nfunction useTimeAgo(time, options = {}) {\n  const {\n    controls: exposeControls = false,\n    updateInterval = 3e4\n  } = options;\n  const { now, ...controls } = useNow({ interval: updateInterval, controls: true });\n  const timeAgo = computed(() => formatTimeAgo(new Date(toValue(time)), options, toValue(now)));\n  if (exposeControls) {\n    return {\n      timeAgo,\n      ...controls\n    };\n  } else {\n    return timeAgo;\n  }\n}\nfunction formatTimeAgo(from, options = {}, now = Date.now()) {\n  var _a;\n  const {\n    max,\n    messages = DEFAULT_MESSAGES,\n    fullDateFormatter = DEFAULT_FORMATTER,\n    units = DEFAULT_UNITS,\n    showSecond = false,\n    rounding = \"round\"\n  } = options;\n  const roundFn = typeof rounding === \"number\" ? (n) => +n.toFixed(rounding) : Math[rounding];\n  const diff = +now - +from;\n  const absDiff = Math.abs(diff);\n  function getValue(diff2, unit) {\n    return roundFn(Math.abs(diff2) / unit.value);\n  }\n  function format(diff2, unit) {\n    const val = getValue(diff2, unit);\n    const past = diff2 > 0;\n    const str = applyFormat(unit.name, val, past);\n    return applyFormat(past ? \"past\" : \"future\", str, past);\n  }\n  function applyFormat(name, val, isPast) {\n    const formatter = messages[name];\n    if (typeof formatter === \"function\")\n      return formatter(val, isPast);\n    return formatter.replace(\"{0}\", val.toString());\n  }\n  if (absDiff < 6e4 && !showSecond)\n    return messages.justNow;\n  if (typeof max === \"number\" && absDiff > max)\n    return fullDateFormatter(new Date(from));\n  if (typeof max === \"string\") {\n    const unitMax = (_a = units.find((i) => i.name === max)) == null ? void 0 : _a.max;\n    if (unitMax && absDiff > unitMax)\n      return fullDateFormatter(new Date(from));\n  }\n  for (const [idx, unit] of units.entries()) {\n    const val = getValue(diff, unit);\n    if (val <= 0 && units[idx - 1])\n      return format(diff, units[idx - 1]);\n    if (absDiff < unit.max)\n      return format(diff, unit);\n  }\n  return messages.invalid;\n}\n\nconst UNITS = [\n  { name: \"year\", ms: 31536e6 },\n  { name: \"month\", ms: 2592e6 },\n  { name: \"week\", ms: 6048e5 },\n  { name: \"day\", ms: 864e5 },\n  { name: \"hour\", ms: 36e5 },\n  { name: \"minute\", ms: 6e4 },\n  { name: \"second\", ms: 1e3 }\n];\nfunction useTimeAgoIntl(time, options = {}) {\n  const {\n    controls: exposeControls = false,\n    updateInterval = 3e4\n  } = options;\n  const { now, ...controls } = useNow({ interval: updateInterval, controls: true });\n  const result = computed(\n    () => getTimeAgoIntlResult(new Date(toValue(time)), options, toValue(now))\n  );\n  const parts = computed(() => result.value.parts);\n  const timeAgoIntl = computed(\n    () => formatTimeAgoIntlParts(parts.value, {\n      ...options,\n      locale: result.value.resolvedLocale\n    })\n  );\n  return exposeControls ? { timeAgoIntl, parts, ...controls } : timeAgoIntl;\n}\nfunction formatTimeAgoIntl(from, options = {}, now = Date.now()) {\n  const { parts, resolvedLocale } = getTimeAgoIntlResult(from, options, now);\n  return formatTimeAgoIntlParts(parts, {\n    ...options,\n    locale: resolvedLocale\n  });\n}\nfunction getTimeAgoIntlResult(from, options = {}, now = Date.now()) {\n  const {\n    locale,\n    relativeTimeFormatOptions = { numeric: \"auto\" }\n  } = options;\n  const rtf = new Intl.RelativeTimeFormat(locale, relativeTimeFormatOptions);\n  const { locale: resolvedLocale } = rtf.resolvedOptions();\n  const diff = +from - +now;\n  const absDiff = Math.abs(diff);\n  for (const { name, ms } of UNITS) {\n    if (absDiff >= ms) {\n      return {\n        resolvedLocale,\n        parts: rtf.formatToParts(Math.round(diff / ms), name)\n      };\n    }\n  }\n  return {\n    resolvedLocale,\n    parts: rtf.formatToParts(0, \"second\")\n  };\n}\nfunction formatTimeAgoIntlParts(parts, options = {}) {\n  const {\n    insertSpace = true,\n    joinParts,\n    locale\n  } = options;\n  if (typeof joinParts === \"function\")\n    return joinParts(parts, locale);\n  if (!insertSpace)\n    return parts.map((part) => part.value).join(\"\");\n  return parts.map((part) => part.value.trim()).join(\" \");\n}\n\nfunction useTimeoutPoll(fn, interval, options = {}) {\n  const {\n    immediate = true,\n    immediateCallback = false\n  } = options;\n  const { start } = useTimeoutFn(loop, interval, { immediate });\n  const isActive = shallowRef(false);\n  async function loop() {\n    if (!isActive.value)\n      return;\n    await fn();\n    start();\n  }\n  function resume() {\n    if (!isActive.value) {\n      isActive.value = true;\n      if (immediateCallback)\n        fn();\n      start();\n    }\n  }\n  function pause() {\n    isActive.value = false;\n  }\n  if (immediate && isClient)\n    resume();\n  tryOnScopeDispose(pause);\n  return {\n    isActive,\n    pause,\n    resume\n  };\n}\n\nfunction useTimestamp(options = {}) {\n  const {\n    controls: exposeControls = false,\n    offset = 0,\n    immediate = true,\n    interval = \"requestAnimationFrame\",\n    callback\n  } = options;\n  const ts = shallowRef(timestamp() + offset);\n  const update = () => ts.value = timestamp() + offset;\n  const cb = callback ? () => {\n    update();\n    callback(ts.value);\n  } : update;\n  const controls = interval === \"requestAnimationFrame\" ? useRafFn(cb, { immediate }) : useIntervalFn(cb, interval, { immediate });\n  if (exposeControls) {\n    return {\n      timestamp: ts,\n      ...controls\n    };\n  } else {\n    return ts;\n  }\n}\n\nfunction useTitle(newTitle = null, options = {}) {\n  var _a, _b, _c;\n  const {\n    document = defaultDocument,\n    restoreOnUnmount = (t) => t\n  } = options;\n  const originalTitle = (_a = document == null ? void 0 : document.title) != null ? _a : \"\";\n  const title = toRef((_b = newTitle != null ? newTitle : document == null ? void 0 : document.title) != null ? _b : null);\n  const isReadonly = !!(newTitle && typeof newTitle === \"function\");\n  function format(t) {\n    if (!(\"titleTemplate\" in options))\n      return t;\n    const template = options.titleTemplate || \"%s\";\n    return typeof template === \"function\" ? template(t) : toValue(template).replace(/%s/g, t);\n  }\n  watch(\n    title,\n    (newValue, oldValue) => {\n      if (newValue !== oldValue && document)\n        document.title = format(newValue != null ? newValue : \"\");\n    },\n    { immediate: true }\n  );\n  if (options.observe && !options.titleTemplate && document && !isReadonly) {\n    useMutationObserver(\n      (_c = document.head) == null ? void 0 : _c.querySelector(\"title\"),\n      () => {\n        if (document && document.title !== title.value)\n          title.value = format(document.title);\n      },\n      { childList: true }\n    );\n  }\n  tryOnScopeDispose(() => {\n    if (restoreOnUnmount) {\n      const restoredTitle = restoreOnUnmount(originalTitle, title.value || \"\");\n      if (restoredTitle != null && document)\n        document.title = restoredTitle;\n    }\n  });\n  return title;\n}\n\nconst _TransitionPresets = {\n  easeInSine: [0.12, 0, 0.39, 0],\n  easeOutSine: [0.61, 1, 0.88, 1],\n  easeInOutSine: [0.37, 0, 0.63, 1],\n  easeInQuad: [0.11, 0, 0.5, 0],\n  easeOutQuad: [0.5, 1, 0.89, 1],\n  easeInOutQuad: [0.45, 0, 0.55, 1],\n  easeInCubic: [0.32, 0, 0.67, 0],\n  easeOutCubic: [0.33, 1, 0.68, 1],\n  easeInOutCubic: [0.65, 0, 0.35, 1],\n  easeInQuart: [0.5, 0, 0.75, 0],\n  easeOutQuart: [0.25, 1, 0.5, 1],\n  easeInOutQuart: [0.76, 0, 0.24, 1],\n  easeInQuint: [0.64, 0, 0.78, 0],\n  easeOutQuint: [0.22, 1, 0.36, 1],\n  easeInOutQuint: [0.83, 0, 0.17, 1],\n  easeInExpo: [0.7, 0, 0.84, 0],\n  easeOutExpo: [0.16, 1, 0.3, 1],\n  easeInOutExpo: [0.87, 0, 0.13, 1],\n  easeInCirc: [0.55, 0, 1, 0.45],\n  easeOutCirc: [0, 0.55, 0.45, 1],\n  easeInOutCirc: [0.85, 0, 0.15, 1],\n  easeInBack: [0.36, 0, 0.66, -0.56],\n  easeOutBack: [0.34, 1.56, 0.64, 1],\n  easeInOutBack: [0.68, -0.6, 0.32, 1.6]\n};\nconst TransitionPresets = /* @__PURE__ */ Object.assign({}, { linear: identity }, _TransitionPresets);\nfunction createEasingFunction([p0, p1, p2, p3]) {\n  const a = (a1, a2) => 1 - 3 * a2 + 3 * a1;\n  const b = (a1, a2) => 3 * a2 - 6 * a1;\n  const c = (a1) => 3 * a1;\n  const calcBezier = (t, a1, a2) => ((a(a1, a2) * t + b(a1, a2)) * t + c(a1)) * t;\n  const getSlope = (t, a1, a2) => 3 * a(a1, a2) * t * t + 2 * b(a1, a2) * t + c(a1);\n  const getTforX = (x) => {\n    let aGuessT = x;\n    for (let i = 0; i < 4; ++i) {\n      const currentSlope = getSlope(aGuessT, p0, p2);\n      if (currentSlope === 0)\n        return aGuessT;\n      const currentX = calcBezier(aGuessT, p0, p2) - x;\n      aGuessT -= currentX / currentSlope;\n    }\n    return aGuessT;\n  };\n  return (x) => p0 === p1 && p2 === p3 ? x : calcBezier(getTforX(x), p1, p3);\n}\nfunction lerp(a, b, alpha) {\n  return a + alpha * (b - a);\n}\nfunction toVec(t) {\n  return (typeof t === \"number\" ? [t] : t) || [];\n}\nfunction executeTransition(source, from, to, options = {}) {\n  var _a, _b;\n  const {\n    window = defaultWindow\n  } = options;\n  const fromVal = toValue(from);\n  const toVal = toValue(to);\n  const v1 = toVec(fromVal);\n  const v2 = toVec(toVal);\n  const duration = (_a = toValue(options.duration)) != null ? _a : 1e3;\n  const startedAt = Date.now();\n  const endAt = Date.now() + duration;\n  const trans = typeof options.transition === \"function\" ? options.transition : (_b = toValue(options.transition)) != null ? _b : identity;\n  const ease = typeof trans === \"function\" ? trans : createEasingFunction(trans);\n  return new Promise((resolve) => {\n    source.value = fromVal;\n    const tick = () => {\n      var _a2;\n      if ((_a2 = options.abort) == null ? void 0 : _a2.call(options)) {\n        resolve();\n        return;\n      }\n      const now = Date.now();\n      const alpha = ease((now - startedAt) / duration);\n      const arr = toVec(source.value).map((n, i) => lerp(v1[i], v2[i], alpha));\n      if (Array.isArray(source.value))\n        source.value = arr.map((n, i) => {\n          var _a3, _b2;\n          return lerp((_a3 = v1[i]) != null ? _a3 : 0, (_b2 = v2[i]) != null ? _b2 : 0, alpha);\n        });\n      else if (typeof source.value === \"number\")\n        source.value = arr[0];\n      if (now < endAt) {\n        window == null ? void 0 : window.requestAnimationFrame(tick);\n      } else {\n        source.value = toVal;\n        resolve();\n      }\n    };\n    tick();\n  });\n}\nfunction useTransition(source, options = {}) {\n  let currentId = 0;\n  const sourceVal = () => {\n    const v = toValue(source);\n    return typeof v === \"number\" ? v : v.map(toValue);\n  };\n  const outputRef = ref(sourceVal());\n  watch(sourceVal, async (to) => {\n    var _a, _b;\n    if (toValue(options.disabled))\n      return;\n    const id = ++currentId;\n    if (options.delay)\n      await promiseTimeout(toValue(options.delay));\n    if (id !== currentId)\n      return;\n    const toVal = Array.isArray(to) ? to.map(toValue) : toValue(to);\n    (_a = options.onStarted) == null ? void 0 : _a.call(options);\n    await executeTransition(outputRef, outputRef.value, toVal, {\n      ...options,\n      abort: () => {\n        var _a2;\n        return id !== currentId || ((_a2 = options.abort) == null ? void 0 : _a2.call(options));\n      }\n    });\n    (_b = options.onFinished) == null ? void 0 : _b.call(options);\n  }, { deep: true });\n  watch(() => toValue(options.disabled), (disabled) => {\n    if (disabled) {\n      currentId++;\n      outputRef.value = sourceVal();\n    }\n  });\n  tryOnScopeDispose(() => {\n    currentId++;\n  });\n  return computed(() => toValue(options.disabled) ? sourceVal() : outputRef.value);\n}\n\nfunction useUrlSearchParams(mode = \"history\", options = {}) {\n  const {\n    initialValue = {},\n    removeNullishValues = true,\n    removeFalsyValues = false,\n    write: enableWrite = true,\n    writeMode = \"replace\",\n    window = defaultWindow,\n    stringify = (params) => params.toString()\n  } = options;\n  if (!window)\n    return reactive(initialValue);\n  const state = reactive({});\n  function getRawParams() {\n    if (mode === \"history\") {\n      return window.location.search || \"\";\n    } else if (mode === \"hash\") {\n      const hash = window.location.hash || \"\";\n      const index = hash.indexOf(\"?\");\n      return index > 0 ? hash.slice(index) : \"\";\n    } else {\n      return (window.location.hash || \"\").replace(/^#/, \"\");\n    }\n  }\n  function constructQuery(params) {\n    const stringified = stringify(params);\n    if (mode === \"history\")\n      return `${stringified ? `?${stringified}` : \"\"}${window.location.hash || \"\"}`;\n    if (mode === \"hash-params\")\n      return `${window.location.search || \"\"}${stringified ? `#${stringified}` : \"\"}`;\n    const hash = window.location.hash || \"#\";\n    const index = hash.indexOf(\"?\");\n    if (index > 0)\n      return `${window.location.search || \"\"}${hash.slice(0, index)}${stringified ? `?${stringified}` : \"\"}`;\n    return `${window.location.search || \"\"}${hash}${stringified ? `?${stringified}` : \"\"}`;\n  }\n  function read() {\n    return new URLSearchParams(getRawParams());\n  }\n  function updateState(params) {\n    const unusedKeys = new Set(Object.keys(state));\n    for (const key of params.keys()) {\n      const paramsForKey = params.getAll(key);\n      state[key] = paramsForKey.length > 1 ? paramsForKey : params.get(key) || \"\";\n      unusedKeys.delete(key);\n    }\n    Array.from(unusedKeys).forEach((key) => delete state[key]);\n  }\n  const { pause, resume } = pausableWatch(\n    state,\n    () => {\n      const params = new URLSearchParams(\"\");\n      Object.keys(state).forEach((key) => {\n        const mapEntry = state[key];\n        if (Array.isArray(mapEntry))\n          mapEntry.forEach((value) => params.append(key, value));\n        else if (removeNullishValues && mapEntry == null)\n          params.delete(key);\n        else if (removeFalsyValues && !mapEntry)\n          params.delete(key);\n        else\n          params.set(key, mapEntry);\n      });\n      write(params, false);\n    },\n    { deep: true }\n  );\n  function write(params, shouldUpdate, shouldWriteHistory = true) {\n    pause();\n    if (shouldUpdate)\n      updateState(params);\n    if (writeMode === \"replace\") {\n      window.history.replaceState(\n        window.history.state,\n        window.document.title,\n        window.location.pathname + constructQuery(params)\n      );\n    } else {\n      if (shouldWriteHistory) {\n        window.history.pushState(\n          window.history.state,\n          window.document.title,\n          window.location.pathname + constructQuery(params)\n        );\n      }\n    }\n    nextTick(() => resume());\n  }\n  function onChanged() {\n    if (!enableWrite)\n      return;\n    write(read(), true, false);\n  }\n  const listenerOptions = { passive: true };\n  useEventListener(window, \"popstate\", onChanged, listenerOptions);\n  if (mode !== \"history\")\n    useEventListener(window, \"hashchange\", onChanged, listenerOptions);\n  const initial = read();\n  if (initial.keys().next().value)\n    updateState(initial);\n  else\n    Object.assign(state, initialValue);\n  return state;\n}\n\nfunction useUserMedia(options = {}) {\n  var _a, _b;\n  const enabled = shallowRef((_a = options.enabled) != null ? _a : false);\n  const autoSwitch = shallowRef((_b = options.autoSwitch) != null ? _b : true);\n  const constraints = ref(options.constraints);\n  const { navigator = defaultNavigator } = options;\n  const isSupported = useSupported(() => {\n    var _a2;\n    return (_a2 = navigator == null ? void 0 : navigator.mediaDevices) == null ? void 0 : _a2.getUserMedia;\n  });\n  const stream = shallowRef();\n  function getDeviceOptions(type) {\n    switch (type) {\n      case \"video\": {\n        if (constraints.value)\n          return constraints.value.video || false;\n        break;\n      }\n      case \"audio\": {\n        if (constraints.value)\n          return constraints.value.audio || false;\n        break;\n      }\n    }\n  }\n  async function _start() {\n    if (!isSupported.value || stream.value)\n      return;\n    stream.value = await navigator.mediaDevices.getUserMedia({\n      video: getDeviceOptions(\"video\"),\n      audio: getDeviceOptions(\"audio\")\n    });\n    return stream.value;\n  }\n  function _stop() {\n    var _a2;\n    (_a2 = stream.value) == null ? void 0 : _a2.getTracks().forEach((t) => t.stop());\n    stream.value = void 0;\n  }\n  function stop() {\n    _stop();\n    enabled.value = false;\n  }\n  async function start() {\n    await _start();\n    if (stream.value)\n      enabled.value = true;\n    return stream.value;\n  }\n  async function restart() {\n    _stop();\n    return await start();\n  }\n  watch(\n    enabled,\n    (v) => {\n      if (v)\n        _start();\n      else _stop();\n    },\n    { immediate: true }\n  );\n  watch(\n    constraints,\n    () => {\n      if (autoSwitch.value && stream.value)\n        restart();\n    },\n    { immediate: true }\n  );\n  tryOnScopeDispose(() => {\n    stop();\n  });\n  return {\n    isSupported,\n    stream,\n    start,\n    stop,\n    restart,\n    constraints,\n    enabled,\n    autoSwitch\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useVModel(props, key, emit, options = {}) {\n  var _a, _b, _c;\n  const {\n    clone = false,\n    passive = false,\n    eventName,\n    deep = false,\n    defaultValue,\n    shouldEmit\n  } = options;\n  const vm = getCurrentInstance();\n  const _emit = emit || (vm == null ? void 0 : vm.emit) || ((_a = vm == null ? void 0 : vm.$emit) == null ? void 0 : _a.bind(vm)) || ((_c = (_b = vm == null ? void 0 : vm.proxy) == null ? void 0 : _b.$emit) == null ? void 0 : _c.bind(vm == null ? void 0 : vm.proxy));\n  let event = eventName;\n  if (!key) {\n    key = \"modelValue\";\n  }\n  event = event || `update:${key.toString()}`;\n  const cloneFn = (val) => !clone ? val : typeof clone === \"function\" ? clone(val) : cloneFnJSON(val);\n  const getValue = () => isDef(props[key]) ? cloneFn(props[key]) : defaultValue;\n  const triggerEmit = (value) => {\n    if (shouldEmit) {\n      if (shouldEmit(value))\n        _emit(event, value);\n    } else {\n      _emit(event, value);\n    }\n  };\n  if (passive) {\n    const initialValue = getValue();\n    const proxy = ref(initialValue);\n    let isUpdating = false;\n    watch(\n      () => props[key],\n      (v) => {\n        if (!isUpdating) {\n          isUpdating = true;\n          proxy.value = cloneFn(v);\n          nextTick(() => isUpdating = false);\n        }\n      }\n    );\n    watch(\n      proxy,\n      (v) => {\n        if (!isUpdating && (v !== props[key] || deep))\n          triggerEmit(v);\n      },\n      { deep }\n    );\n    return proxy;\n  } else {\n    return computed({\n      get() {\n        return getValue();\n      },\n      set(value) {\n        triggerEmit(value);\n      }\n    });\n  }\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useVModels(props, emit, options = {}) {\n  const ret = {};\n  for (const key in props) {\n    ret[key] = useVModel(\n      props,\n      key,\n      emit,\n      options\n    );\n  }\n  return ret;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useVibrate(options) {\n  const {\n    pattern = [],\n    interval = 0,\n    navigator = defaultNavigator\n  } = options || {};\n  const isSupported = useSupported(() => typeof navigator !== \"undefined\" && \"vibrate\" in navigator);\n  const patternRef = toRef(pattern);\n  let intervalControls;\n  const vibrate = (pattern2 = patternRef.value) => {\n    if (isSupported.value)\n      navigator.vibrate(pattern2);\n  };\n  const stop = () => {\n    if (isSupported.value)\n      navigator.vibrate(0);\n    intervalControls == null ? void 0 : intervalControls.pause();\n  };\n  if (interval > 0) {\n    intervalControls = useIntervalFn(\n      vibrate,\n      interval,\n      {\n        immediate: false,\n        immediateCallback: false\n      }\n    );\n  }\n  return {\n    isSupported,\n    pattern,\n    intervalControls,\n    vibrate,\n    stop\n  };\n}\n\nfunction useVirtualList(list, options) {\n  const { containerStyle, wrapperProps, scrollTo, calculateRange, currentList, containerRef } = \"itemHeight\" in options ? useVerticalVirtualList(options, list) : useHorizontalVirtualList(options, list);\n  return {\n    list: currentList,\n    scrollTo,\n    containerProps: {\n      ref: containerRef,\n      onScroll: () => {\n        calculateRange();\n      },\n      style: containerStyle\n    },\n    wrapperProps\n  };\n}\nfunction useVirtualListResources(list) {\n  const containerRef = shallowRef(null);\n  const size = useElementSize(containerRef);\n  const currentList = ref([]);\n  const source = shallowRef(list);\n  const state = ref({ start: 0, end: 10 });\n  return { state, source, currentList, size, containerRef };\n}\nfunction createGetViewCapacity(state, source, itemSize) {\n  return (containerSize) => {\n    if (typeof itemSize === \"number\")\n      return Math.ceil(containerSize / itemSize);\n    const { start = 0 } = state.value;\n    let sum = 0;\n    let capacity = 0;\n    for (let i = start; i < source.value.length; i++) {\n      const size = itemSize(i);\n      sum += size;\n      capacity = i;\n      if (sum > containerSize)\n        break;\n    }\n    return capacity - start;\n  };\n}\nfunction createGetOffset(source, itemSize) {\n  return (scrollDirection) => {\n    if (typeof itemSize === \"number\")\n      return Math.floor(scrollDirection / itemSize) + 1;\n    let sum = 0;\n    let offset = 0;\n    for (let i = 0; i < source.value.length; i++) {\n      const size = itemSize(i);\n      sum += size;\n      if (sum >= scrollDirection) {\n        offset = i;\n        break;\n      }\n    }\n    return offset + 1;\n  };\n}\nfunction createCalculateRange(type, overscan, getOffset, getViewCapacity, { containerRef, state, currentList, source }) {\n  return () => {\n    const element = containerRef.value;\n    if (element) {\n      const offset = getOffset(type === \"vertical\" ? element.scrollTop : element.scrollLeft);\n      const viewCapacity = getViewCapacity(type === \"vertical\" ? element.clientHeight : element.clientWidth);\n      const from = offset - overscan;\n      const to = offset + viewCapacity + overscan;\n      state.value = {\n        start: from < 0 ? 0 : from,\n        end: to > source.value.length ? source.value.length : to\n      };\n      currentList.value = source.value.slice(state.value.start, state.value.end).map((ele, index) => ({\n        data: ele,\n        index: index + state.value.start\n      }));\n    }\n  };\n}\nfunction createGetDistance(itemSize, source) {\n  return (index) => {\n    if (typeof itemSize === \"number\") {\n      const size2 = index * itemSize;\n      return size2;\n    }\n    const size = source.value.slice(0, index).reduce((sum, _, i) => sum + itemSize(i), 0);\n    return size;\n  };\n}\nfunction useWatchForSizes(size, list, containerRef, calculateRange) {\n  watch([size.width, size.height, () => toValue(list), containerRef], () => {\n    calculateRange();\n  });\n}\nfunction createComputedTotalSize(itemSize, source) {\n  return computed(() => {\n    if (typeof itemSize === \"number\")\n      return source.value.length * itemSize;\n    return source.value.reduce((sum, _, index) => sum + itemSize(index), 0);\n  });\n}\nconst scrollToDictionaryForElementScrollKey = {\n  horizontal: \"scrollLeft\",\n  vertical: \"scrollTop\"\n};\nfunction createScrollTo(type, calculateRange, getDistance, containerRef) {\n  return (index) => {\n    if (containerRef.value) {\n      containerRef.value[scrollToDictionaryForElementScrollKey[type]] = getDistance(index);\n      calculateRange();\n    }\n  };\n}\nfunction useHorizontalVirtualList(options, list) {\n  const resources = useVirtualListResources(list);\n  const { state, source, currentList, size, containerRef } = resources;\n  const containerStyle = { overflowX: \"auto\" };\n  const { itemWidth, overscan = 5 } = options;\n  const getViewCapacity = createGetViewCapacity(state, source, itemWidth);\n  const getOffset = createGetOffset(source, itemWidth);\n  const calculateRange = createCalculateRange(\"horizontal\", overscan, getOffset, getViewCapacity, resources);\n  const getDistanceLeft = createGetDistance(itemWidth, source);\n  const offsetLeft = computed(() => getDistanceLeft(state.value.start));\n  const totalWidth = createComputedTotalSize(itemWidth, source);\n  useWatchForSizes(size, list, containerRef, calculateRange);\n  const scrollTo = createScrollTo(\"horizontal\", calculateRange, getDistanceLeft, containerRef);\n  const wrapperProps = computed(() => {\n    return {\n      style: {\n        height: \"100%\",\n        width: `${totalWidth.value - offsetLeft.value}px`,\n        marginLeft: `${offsetLeft.value}px`,\n        display: \"flex\"\n      }\n    };\n  });\n  return {\n    scrollTo,\n    calculateRange,\n    wrapperProps,\n    containerStyle,\n    currentList,\n    containerRef\n  };\n}\nfunction useVerticalVirtualList(options, list) {\n  const resources = useVirtualListResources(list);\n  const { state, source, currentList, size, containerRef } = resources;\n  const containerStyle = { overflowY: \"auto\" };\n  const { itemHeight, overscan = 5 } = options;\n  const getViewCapacity = createGetViewCapacity(state, source, itemHeight);\n  const getOffset = createGetOffset(source, itemHeight);\n  const calculateRange = createCalculateRange(\"vertical\", overscan, getOffset, getViewCapacity, resources);\n  const getDistanceTop = createGetDistance(itemHeight, source);\n  const offsetTop = computed(() => getDistanceTop(state.value.start));\n  const totalHeight = createComputedTotalSize(itemHeight, source);\n  useWatchForSizes(size, list, containerRef, calculateRange);\n  const scrollTo = createScrollTo(\"vertical\", calculateRange, getDistanceTop, containerRef);\n  const wrapperProps = computed(() => {\n    return {\n      style: {\n        width: \"100%\",\n        height: `${totalHeight.value - offsetTop.value}px`,\n        marginTop: `${offsetTop.value}px`\n      }\n    };\n  });\n  return {\n    calculateRange,\n    scrollTo,\n    containerStyle,\n    wrapperProps,\n    currentList,\n    containerRef\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useWakeLock(options = {}) {\n  const {\n    navigator = defaultNavigator,\n    document = defaultDocument\n  } = options;\n  const requestedType = shallowRef(false);\n  const sentinel = shallowRef(null);\n  const documentVisibility = useDocumentVisibility({ document });\n  const isSupported = useSupported(() => navigator && \"wakeLock\" in navigator);\n  const isActive = computed(() => !!sentinel.value && documentVisibility.value === \"visible\");\n  if (isSupported.value) {\n    useEventListener(sentinel, \"release\", () => {\n      var _a, _b;\n      requestedType.value = (_b = (_a = sentinel.value) == null ? void 0 : _a.type) != null ? _b : false;\n    }, { passive: true });\n    whenever(\n      () => documentVisibility.value === \"visible\" && (document == null ? void 0 : document.visibilityState) === \"visible\" && requestedType.value,\n      (type) => {\n        requestedType.value = false;\n        forceRequest(type);\n      }\n    );\n  }\n  async function forceRequest(type) {\n    var _a;\n    await ((_a = sentinel.value) == null ? void 0 : _a.release());\n    sentinel.value = isSupported.value ? await navigator.wakeLock.request(type) : null;\n  }\n  async function request(type) {\n    if (documentVisibility.value === \"visible\")\n      await forceRequest(type);\n    else\n      requestedType.value = type;\n  }\n  async function release() {\n    requestedType.value = false;\n    const s = sentinel.value;\n    sentinel.value = null;\n    await (s == null ? void 0 : s.release());\n  }\n  return {\n    sentinel,\n    isSupported,\n    isActive,\n    request,\n    forceRequest,\n    release\n  };\n}\n\nfunction useWebNotification(options = {}) {\n  const {\n    window = defaultWindow,\n    requestPermissions: _requestForPermissions = true\n  } = options;\n  const defaultWebNotificationOptions = options;\n  const isSupported = useSupported(() => {\n    if (!window || !(\"Notification\" in window))\n      return false;\n    if (Notification.permission === \"granted\")\n      return true;\n    try {\n      const notification2 = new Notification(\"\");\n      notification2.onshow = () => {\n        notification2.close();\n      };\n    } catch (e) {\n      if (e.name === \"TypeError\")\n        return false;\n    }\n    return true;\n  });\n  const permissionGranted = shallowRef(isSupported.value && \"permission\" in Notification && Notification.permission === \"granted\");\n  const notification = ref(null);\n  const ensurePermissions = async () => {\n    if (!isSupported.value)\n      return;\n    if (!permissionGranted.value && Notification.permission !== \"denied\") {\n      const result = await Notification.requestPermission();\n      if (result === \"granted\")\n        permissionGranted.value = true;\n    }\n    return permissionGranted.value;\n  };\n  const { on: onClick, trigger: clickTrigger } = createEventHook();\n  const { on: onShow, trigger: showTrigger } = createEventHook();\n  const { on: onError, trigger: errorTrigger } = createEventHook();\n  const { on: onClose, trigger: closeTrigger } = createEventHook();\n  const show = async (overrides) => {\n    if (!isSupported.value || !permissionGranted.value)\n      return;\n    const options2 = Object.assign({}, defaultWebNotificationOptions, overrides);\n    notification.value = new Notification(options2.title || \"\", options2);\n    notification.value.onclick = clickTrigger;\n    notification.value.onshow = showTrigger;\n    notification.value.onerror = errorTrigger;\n    notification.value.onclose = closeTrigger;\n    return notification.value;\n  };\n  const close = () => {\n    if (notification.value)\n      notification.value.close();\n    notification.value = null;\n  };\n  if (_requestForPermissions)\n    tryOnMounted(ensurePermissions);\n  tryOnScopeDispose(close);\n  if (isSupported.value && window) {\n    const document = window.document;\n    useEventListener(document, \"visibilitychange\", (e) => {\n      e.preventDefault();\n      if (document.visibilityState === \"visible\") {\n        close();\n      }\n    });\n  }\n  return {\n    isSupported,\n    notification,\n    ensurePermissions,\n    permissionGranted,\n    show,\n    close,\n    onClick,\n    onShow,\n    onError,\n    onClose\n  };\n}\n\nconst DEFAULT_PING_MESSAGE = \"ping\";\nfunction resolveNestedOptions(options) {\n  if (options === true)\n    return {};\n  return options;\n}\nfunction useWebSocket(url, options = {}) {\n  const {\n    onConnected,\n    onDisconnected,\n    onError,\n    onMessage,\n    immediate = true,\n    autoConnect = true,\n    autoClose = true,\n    protocols = []\n  } = options;\n  const data = ref(null);\n  const status = shallowRef(\"CLOSED\");\n  const wsRef = ref();\n  const urlRef = toRef(url);\n  let heartbeatPause;\n  let heartbeatResume;\n  let explicitlyClosed = false;\n  let retried = 0;\n  let bufferedData = [];\n  let retryTimeout;\n  let pongTimeoutWait;\n  const _sendBuffer = () => {\n    if (bufferedData.length && wsRef.value && status.value === \"OPEN\") {\n      for (const buffer of bufferedData)\n        wsRef.value.send(buffer);\n      bufferedData = [];\n    }\n  };\n  const resetRetry = () => {\n    if (retryTimeout != null) {\n      clearTimeout(retryTimeout);\n      retryTimeout = void 0;\n    }\n  };\n  const resetHeartbeat = () => {\n    clearTimeout(pongTimeoutWait);\n    pongTimeoutWait = void 0;\n  };\n  const close = (code = 1e3, reason) => {\n    resetRetry();\n    if (!isClient && !isWorker || !wsRef.value)\n      return;\n    explicitlyClosed = true;\n    resetHeartbeat();\n    heartbeatPause == null ? void 0 : heartbeatPause();\n    wsRef.value.close(code, reason);\n    wsRef.value = void 0;\n  };\n  const send = (data2, useBuffer = true) => {\n    if (!wsRef.value || status.value !== \"OPEN\") {\n      if (useBuffer)\n        bufferedData.push(data2);\n      return false;\n    }\n    _sendBuffer();\n    wsRef.value.send(data2);\n    return true;\n  };\n  const _init = () => {\n    if (explicitlyClosed || typeof urlRef.value === \"undefined\")\n      return;\n    const ws = new WebSocket(urlRef.value, protocols);\n    wsRef.value = ws;\n    status.value = \"CONNECTING\";\n    ws.onopen = () => {\n      status.value = \"OPEN\";\n      retried = 0;\n      onConnected == null ? void 0 : onConnected(ws);\n      heartbeatResume == null ? void 0 : heartbeatResume();\n      _sendBuffer();\n    };\n    ws.onclose = (ev) => {\n      status.value = \"CLOSED\";\n      resetHeartbeat();\n      heartbeatPause == null ? void 0 : heartbeatPause();\n      onDisconnected == null ? void 0 : onDisconnected(ws, ev);\n      if (!explicitlyClosed && options.autoReconnect && (wsRef.value == null || ws === wsRef.value)) {\n        const {\n          retries = -1,\n          delay = 1e3,\n          onFailed\n        } = resolveNestedOptions(options.autoReconnect);\n        const checkRetires = typeof retries === \"function\" ? retries : () => typeof retries === \"number\" && (retries < 0 || retried < retries);\n        if (checkRetires(retried)) {\n          retried += 1;\n          retryTimeout = setTimeout(_init, delay);\n        } else {\n          onFailed == null ? void 0 : onFailed();\n        }\n      }\n    };\n    ws.onerror = (e) => {\n      onError == null ? void 0 : onError(ws, e);\n    };\n    ws.onmessage = (e) => {\n      if (options.heartbeat) {\n        resetHeartbeat();\n        const {\n          message = DEFAULT_PING_MESSAGE,\n          responseMessage = message\n        } = resolveNestedOptions(options.heartbeat);\n        if (e.data === toValue(responseMessage))\n          return;\n      }\n      data.value = e.data;\n      onMessage == null ? void 0 : onMessage(ws, e);\n    };\n  };\n  if (options.heartbeat) {\n    const {\n      message = DEFAULT_PING_MESSAGE,\n      interval = 1e3,\n      pongTimeout = 1e3\n    } = resolveNestedOptions(options.heartbeat);\n    const { pause, resume } = useIntervalFn(\n      () => {\n        send(toValue(message), false);\n        if (pongTimeoutWait != null)\n          return;\n        pongTimeoutWait = setTimeout(() => {\n          close();\n          explicitlyClosed = false;\n        }, pongTimeout);\n      },\n      interval,\n      { immediate: false }\n    );\n    heartbeatPause = pause;\n    heartbeatResume = resume;\n  }\n  if (autoClose) {\n    if (isClient)\n      useEventListener(\"beforeunload\", () => close(), { passive: true });\n    tryOnScopeDispose(close);\n  }\n  const open = () => {\n    if (!isClient && !isWorker)\n      return;\n    close();\n    explicitlyClosed = false;\n    retried = 0;\n    _init();\n  };\n  if (immediate)\n    open();\n  if (autoConnect)\n    watch(urlRef, open);\n  return {\n    data,\n    status,\n    close,\n    send,\n    open,\n    ws: wsRef\n  };\n}\n\nfunction useWebWorker(arg0, workerOptions, options) {\n  const {\n    window = defaultWindow\n  } = options != null ? options : {};\n  const data = ref(null);\n  const worker = shallowRef();\n  const post = (...args) => {\n    if (!worker.value)\n      return;\n    worker.value.postMessage(...args);\n  };\n  const terminate = function terminate2() {\n    if (!worker.value)\n      return;\n    worker.value.terminate();\n  };\n  if (window) {\n    if (typeof arg0 === \"string\")\n      worker.value = new Worker(arg0, workerOptions);\n    else if (typeof arg0 === \"function\")\n      worker.value = arg0();\n    else\n      worker.value = arg0;\n    worker.value.onmessage = (e) => {\n      data.value = e.data;\n    };\n    tryOnScopeDispose(() => {\n      if (worker.value)\n        worker.value.terminate();\n    });\n  }\n  return {\n    data,\n    post,\n    terminate,\n    worker\n  };\n}\n\nfunction depsParser(deps, localDeps) {\n  if (deps.length === 0 && localDeps.length === 0)\n    return \"\";\n  const depsString = deps.map((dep) => `'${dep}'`).toString();\n  const depsFunctionString = localDeps.filter((dep) => typeof dep === \"function\").map((fn) => {\n    const str = fn.toString();\n    if (str.trim().startsWith(\"function\")) {\n      return str;\n    } else {\n      const name = fn.name;\n      return `const ${name} = ${str}`;\n    }\n  }).join(\";\");\n  const importString = `importScripts(${depsString});`;\n  return `${depsString.trim() === \"\" ? \"\" : importString} ${depsFunctionString}`;\n}\n\nfunction jobRunner(userFunc) {\n  return (e) => {\n    const userFuncArgs = e.data[0];\n    return Promise.resolve(userFunc.apply(void 0, userFuncArgs)).then((result) => {\n      postMessage([\"SUCCESS\", result]);\n    }).catch((error) => {\n      postMessage([\"ERROR\", error]);\n    });\n  };\n}\n\nfunction createWorkerBlobUrl(fn, deps, localDeps) {\n  const blobCode = `${depsParser(deps, localDeps)}; onmessage=(${jobRunner})(${fn})`;\n  const blob = new Blob([blobCode], { type: \"text/javascript\" });\n  const url = URL.createObjectURL(blob);\n  return url;\n}\n\nfunction useWebWorkerFn(fn, options = {}) {\n  const {\n    dependencies = [],\n    localDependencies = [],\n    timeout,\n    window = defaultWindow\n  } = options;\n  const worker = ref();\n  const workerStatus = shallowRef(\"PENDING\");\n  const promise = ref({});\n  const timeoutId = shallowRef();\n  const workerTerminate = (status = \"PENDING\") => {\n    if (worker.value && worker.value._url && window) {\n      worker.value.terminate();\n      URL.revokeObjectURL(worker.value._url);\n      promise.value = {};\n      worker.value = void 0;\n      window.clearTimeout(timeoutId.value);\n      workerStatus.value = status;\n    }\n  };\n  workerTerminate();\n  tryOnScopeDispose(workerTerminate);\n  const generateWorker = () => {\n    const blobUrl = createWorkerBlobUrl(fn, dependencies, localDependencies);\n    const newWorker = new Worker(blobUrl);\n    newWorker._url = blobUrl;\n    newWorker.onmessage = (e) => {\n      const { resolve = () => {\n      }, reject = () => {\n      } } = promise.value;\n      const [status, result] = e.data;\n      switch (status) {\n        case \"SUCCESS\":\n          resolve(result);\n          workerTerminate(status);\n          break;\n        default:\n          reject(result);\n          workerTerminate(\"ERROR\");\n          break;\n      }\n    };\n    newWorker.onerror = (e) => {\n      const { reject = () => {\n      } } = promise.value;\n      e.preventDefault();\n      reject(e);\n      workerTerminate(\"ERROR\");\n    };\n    if (timeout) {\n      timeoutId.value = setTimeout(\n        () => workerTerminate(\"TIMEOUT_EXPIRED\"),\n        timeout\n      );\n    }\n    return newWorker;\n  };\n  const callWorker = (...fnArgs) => new Promise((resolve, reject) => {\n    var _a;\n    promise.value = {\n      resolve,\n      reject\n    };\n    (_a = worker.value) == null ? void 0 : _a.postMessage([[...fnArgs]]);\n    workerStatus.value = \"RUNNING\";\n  });\n  const workerFn = (...fnArgs) => {\n    if (workerStatus.value === \"RUNNING\") {\n      console.error(\n        \"[useWebWorkerFn] You can only run one instance of the worker at a time.\"\n      );\n      return Promise.reject();\n    }\n    worker.value = generateWorker();\n    return callWorker(...fnArgs);\n  };\n  return {\n    workerFn,\n    workerStatus,\n    workerTerminate\n  };\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useWindowFocus(options = {}) {\n  const { window = defaultWindow } = options;\n  if (!window)\n    return shallowRef(false);\n  const focused = shallowRef(window.document.hasFocus());\n  const listenerOptions = { passive: true };\n  useEventListener(window, \"blur\", () => {\n    focused.value = false;\n  }, listenerOptions);\n  useEventListener(window, \"focus\", () => {\n    focused.value = true;\n  }, listenerOptions);\n  return focused;\n}\n\nfunction useWindowScroll(options = {}) {\n  const { window = defaultWindow, ...rest } = options;\n  return useScroll(window, rest);\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useWindowSize(options = {}) {\n  const {\n    window = defaultWindow,\n    initialWidth = Number.POSITIVE_INFINITY,\n    initialHeight = Number.POSITIVE_INFINITY,\n    listenOrientation = true,\n    includeScrollbar = true,\n    type = \"inner\"\n  } = options;\n  const width = shallowRef(initialWidth);\n  const height = shallowRef(initialHeight);\n  const update = () => {\n    if (window) {\n      if (type === \"outer\") {\n        width.value = window.outerWidth;\n        height.value = window.outerHeight;\n      } else if (type === \"visual\" && window.visualViewport) {\n        const { width: visualViewportWidth, height: visualViewportHeight, scale } = window.visualViewport;\n        width.value = Math.round(visualViewportWidth * scale);\n        height.value = Math.round(visualViewportHeight * scale);\n      } else if (includeScrollbar) {\n        width.value = window.innerWidth;\n        height.value = window.innerHeight;\n      } else {\n        width.value = window.document.documentElement.clientWidth;\n        height.value = window.document.documentElement.clientHeight;\n      }\n    }\n  };\n  update();\n  tryOnMounted(update);\n  const listenerOptions = { passive: true };\n  useEventListener(\"resize\", update, listenerOptions);\n  if (window && type === \"visual\" && window.visualViewport) {\n    useEventListener(window.visualViewport, \"resize\", update, listenerOptions);\n  }\n  if (listenOrientation) {\n    const matches = useMediaQuery(\"(orientation: portrait)\");\n    watch(matches, () => update());\n  }\n  return { width, height };\n}\n\nexport { DefaultMagicKeysAliasMap, StorageSerializers, TransitionPresets, computedAsync as asyncComputed, breakpointsAntDesign, breakpointsBootstrapV5, breakpointsElement, breakpointsMasterCss, breakpointsPrimeFlex, breakpointsQuasar, breakpointsSematic, breakpointsTailwind, breakpointsVuetify, breakpointsVuetifyV2, breakpointsVuetifyV3, cloneFnJSON, computedAsync, computedInject, createFetch, createReusableTemplate, createTemplatePromise, createUnrefFn, customStorageEventName, defaultDocument, defaultLocation, defaultNavigator, defaultWindow, executeTransition, formatTimeAgo, formatTimeAgoIntl, formatTimeAgoIntlParts, getSSRHandler, mapGamepadToXbox360Controller, onClickOutside, onElementRemoval, onKeyDown, onKeyPressed, onKeyStroke, onKeyUp, onLongPress, onStartTyping, provideSSRWidth, setSSRHandler, templateRef, unrefElement, useActiveElement, useAnimate, useAsyncQueue, useAsyncState, useBase64, useBattery, useBluetooth, useBreakpoints, useBroadcastChannel, useBrowserLocation, useCached, useClipboard, useClipboardItems, useCloned, useColorMode, useConfirmDialog, useCountdown, useCssVar, useCurrentElement, useCycleList, useDark, useDebouncedRefHistory, useDeviceMotion, useDeviceOrientation, useDevicePixelRatio, useDevicesList, useDisplayMedia, useDocumentVisibility, useDraggable, useDropZone, useElementBounding, useElementByPoint, useElementHover, useElementSize, useElementVisibility, useEventBus, useEventListener, useEventSource, useEyeDropper, useFavicon, useFetch, useFileDialog, useFileSystemAccess, useFocus, useFocusWithin, useFps, useFullscreen, useGamepad, useGeolocation, useIdle, useImage, useInfiniteScroll, useIntersectionObserver, useKeyModifier, useLocalStorage, useMagicKeys, useManualRefHistory, useMediaControls, useMediaQuery, useMemoize, useMemory, useMounted, useMouse, useMouseInElement, useMousePressed, useMutationObserver, useNavigatorLanguage, useNetwork, useNow, useObjectUrl, useOffsetPagination, useOnline, usePageLeave, useParallax, useParentElement, usePerformanceObserver, usePermission, usePointer, usePointerLock, usePointerSwipe, usePreferredColorScheme, usePreferredContrast, usePreferredDark, usePreferredLanguages, usePreferredReducedMotion, usePreferredReducedTransparency, usePrevious, useRafFn, useRefHistory, useResizeObserver, useSSRWidth, useScreenOrientation, useScreenSafeArea, useScriptTag, useScroll, useScrollLock, useSessionStorage, useShare, useSorted, useSpeechRecognition, useSpeechSynthesis, useStepper, useStorage, useStorageAsync, useStyleTag, useSupported, useSwipe, useTemplateRefsList, useTextDirection, useTextSelection, useTextareaAutosize, useThrottledRefHistory, useTimeAgo, useTimeAgoIntl, useTimeoutPoll, useTimestamp, useTitle, useTransition, useUrlSearchParams, useUserMedia, useVModel, useVModels, useVibrate, useVirtualList, useWakeLock, useWebNotification, useWebSocket, useWebWorker, useWebWorkerFn, useWindowFocus, useWindowScroll, useWindowSize };\n","<script>\nimport { defineAsyncComponent, ref, computed, toRef, useTemplateRef, watch, onMounted } from 'vue';\nimport { onClickOutside } from '@vueuse/core';\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport { useId } from '@/composables/useId.js';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { useExtractAttrs } from '@/composables/useExtractAttrs.js';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\n\n/**\n * Form Input Field Component\n */\n\nexport default {\n  name: 'BaseInput',\n  components: {\n    BaseIcon,\n    BaseLoader: defineAsyncComponent(() => import('@/components/BaseLoader/BaseLoader.vue')),\n  },\n  inheritAttrs: false,\n  props: {\n    /**\n     * input field settable from outside\n     */\n    modelValue: {\n      type: [String, Number],\n      default: '',\n    },\n    /** label for input field, required for usability purposes, handle\n     * showing of label with property `showLabel`\n     */\n    label: {\n      type: String,\n      required: true,\n    },\n    /**\n     * defines if input label should be visible\n     */\n    showLabel: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * if field is occurring more then once - set an `id`\n     * **caveat**: in case a custom input is used with the `input` slot it is important to\n     * assign the same id to the input element\n     */\n    inputId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set a placeholder for the input field\n     */\n    placeholder: {\n      type: String,\n      default: 'Enter Text Here',\n    },\n    /**\n     * mark as required field\n     */\n    required: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * mark the form field as invalid and ideally also provide an error message\n     * to display below the form field\n     * the v-model directive might be used on this prop\n     */\n    invalid: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * add an error message to be displayed below form field if field is invalid\n     */\n    errorMessage: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define if error icon should be shown\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * specify input type\n     * @values text, number, password, email, url, search\n     *\n     */\n    inputType: {\n      type: String,\n      default: 'text',\n      validator: val => ['text', 'number', 'password', 'email', 'url', 'search'].includes(val),\n    },\n    /**\n     * specify the id of a linked drop down list\n     */\n    dropDownListId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify a linked list option (e.g. drop down)\n     *   (will be used in `aria-activedescendant` attribute)\n     */\n    linkedListOption: {\n      type: [Number, String],\n      default: null,\n    },\n    /**\n     * option to hide input field from outside (required for chips input)\n     */\n    hideInputField: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set input field in active state from outside\n     * the v-model directive can be used on this prop\n     */\n    isActive: {\n      type: Boolean,\n      default: null,\n    },\n    /**\n     * option to have the border of the input field not displayed\n     */\n    showInputBorder: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define if standard form field styling should be\n     * used (otherwise no border, no box shadow)\n     */\n    useFormFieldStyling: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * if `true` a remove icon (or custom icon if slot `remove-icon` is used) will be shown allowing to remove\n     * all input at once\n     */\n    clearable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `true` space is reserved for a loader that can be activated\n     * with the `isLoading` prop\n     */\n    loadable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * show spinner to indicate that something is loading\n     * (for dynamically fetched entries that need to do backend requests)\n     */\n    isLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * turn off input fade out if it interferes with other styling (e.g. with custom input)\n     */\n    useFadeOut: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * specify additional input field styling\n     */\n    inputClass: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set a language (ISO 639-1)\n     */\n    language: {\n      type: String,\n      default: '',\n      validator: val => !val || val.length === 2,\n    },\n    /**\n     * use this prop to deactivate automatic setting of focus as soon as input element\n     * becomes active - this might require external handling of focus setting!\n     */\n    setFocusOnActive: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * set `true` if input field should be disabled\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set min length of characters\n     */\n    minLength: {\n      type: Number,\n      default: null,\n    },\n    /**\n     * set max length of characters\n     */\n    maxLength: {\n      type: Number,\n      default: null,\n    },\n    /**\n     * set number of decimals (inputType=number)<br>\n     * Note: -1 is used for endless decimals\n     */\n    decimals: {\n      type: Number,\n      default: null,\n    },\n    /**\n     * set decimal separator character, e.g. ',' for german\n     * note that this only changes the display of decimal values, input\n     * values should always be provided with '.' as separator and will be\n     * returned as such\n     */\n    decimalSeparator: {\n      type: String,\n      default: '.',\n    },\n    /**\n     * set minimum value to accept\n     */\n    min: {\n      type: Number,\n      default: null,\n    },\n    /**\n     * set maximum value to accept\n     */\n    max: {\n      type: Number,\n      default: null,\n    },\n    /**\n     * define validation messages\n     * currently just for type number\n     */\n    validationTexts: {\n      type: Object,\n      default: () => ({\n        min: 'Value must be greater than or equal to {value}.',\n        max: 'Value must be less than or equal to {value}.',\n        minLength: 'Text must be at least {value} character(s) long.',\n        maxLength: 'Text cannot be longer than {value} characters.',\n      }),\n      // checking if all necessary properties are part of the provided object\n      validator: val => !Object.keys(val).length || ['min', 'max', 'minLength', 'maxLength']\n        .every(prop => Object.keys(val).includes(prop)),\n    },\n    /**\n     * provide assistive text for screen readers\n     * **loaderActive**: if `loadable` is set `true` this text is read\n     *  as soon as the loader is appearing (`isLoading` is set true)\n     * **clearInput**: text read for remove input icon if prop `clearable` is set `true`\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        loaderActive: 'loading.',\n        clearInput: 'Clear input',\n      }),\n    },\n    /**\n     * add queryselector strings for elements that should not trigger a\n     * click outside event\n     */\n    ignoreClickOutside: {\n      type: Array,\n      default: () => ([]),\n    },\n  },\n  emits: ['clicked-outside', 'click-input-field', 'update:invalid', 'update:is-active', 'update:model-value'],\n  setup(props, { emit, slots }) {\n    /** LABEL and ERROR MESSAGE LOCALIZATION */\n    const internalValidationMessage = ref('');\n    const { getLangLabel } = useI18n(toRef(props, 'language'));\n    const labelLocalized = computed(() => getLangLabel(props.label));\n    const errorMessageInt = computed(() => getLangLabel(internalValidationMessage.value || props.errorMessage));\n\n    /** INTERNAL ID */\n    /**\n     * create a permanent id (also suitable for ssr)\n     * @type {Ref<UnwrapRef<string|number>>}\n     */\n    const idInt = ref(props.inputId);\n    if (!idInt.value) {\n      // define an internal id, needed for aria and reference purposes\n      idInt.value = useId();\n    }\n\n    /** ATTRS HANDLING */\n    const { rootAttrs, forwardAttrs } = useExtractAttrs();\n\n    /** LABEL ROW DISPLAY */\n\n    const { slotHasContent } = useHasSlotContent(slots['label-addition']);\n    /**\n     * variable to define if label low (with margin) should be displayed or not\n     * @type {ComputedRef<boolean>}\n     */\n    const showLabelRow = computed(() => {\n      return props.showLabel || slotHasContent.value;\n    });\n\n    /** INPUT HANDLING */\n    /**\n     * store the input v-model value\n     * @type {Ref<UnwrapRef<string>>}\n     */\n    const inputInt = ref('');\n    /**\n     * get the appropriate value for <input> attribute `inputmode` in case\n     * input is of type number\n     * @type {ComputedRef<null|string>}\n     */\n    const inputMode = computed(() => {\n      if (props.inputType !== 'number') return null;\n      return props.decimals ? 'decimal' : 'numeric';\n    });\n    /**\n     * determines if remove icon should be shown - added to section input handling\n     * since value is determined by input present\n     * @type {ComputedRef<boolean>}\n     */\n    const showRemoveIcon = computed(() => {\n      return props.clearable && !!inputInt.value;\n    });\n\n    /** FOCUS HANDLING */\n    /**\n     * reference to the native HTML input element (if slot was not used and it exists)\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const input = useTemplateRef('input');\n    /**\n     * find and store the input element associated with this component in a variable\n     * @type {ComputedRef<HTMLElement|null>}\n     */\n    const inputElement = computed(() => {\n      // check if client side\n      if (window) {\n        // if input element exists in ref use this one\n        if (input.value) {\n          return input.value;\n        }\n        // otherwise check for a custom element by id\n        const tempElement = document.getElementById(idInt.value);\n        // check if element exists\n        if (tempElement) {\n          return tempElement;\n        }\n        // otherwise warn that the id was not assigned to the input element\n        console.warn('BaseInput: you did not assign the same id to the BaseInputComponent and the input element!');\n      }\n      return null;\n    });\n\n    /** CLICK OUTSIDE HANDLING */\n    // get the ref element for click outside\n    const inputFrame = useTemplateRef('inputFrameEl');\n    const isActiveInt = ref(false);\n\n    /**\n     * keep externally set active variable and internal active variable in sync\n     * @param {boolean} val\n     */\n    watch(() => props.isActive, (val) => {\n      if (val !== isActiveInt.value) {\n        setFieldState(val);\n      }\n    }, {\n      immediate: true,\n    });\n    /**\n     * keep externally set active variable and internal active variable in sync\n     * @param {boolean} val\n     */\n    watch(isActiveInt, (val) => {\n      // if active was set true focus the input field\n      if (inputElement.value && val && props.setFocusOnActive\n        // however do not take away the focus from the remove button\n        && document.activeElement?.id !== `${idInt.value}-remove-icon`) {\n        inputElement.value.focus();\n      }\n      /**\n       * propagate active state changes of input field to parent\n       * @event update:is-active\n       * @param {boolean} - is input field active\n       */\n      emit('update:is-active', val);\n    });\n\n    /**\n     * set the active input field state (used for visual active indication)\n     * @param {boolean} val - the value to be set\n     */\n    function setFieldState(val) {\n      if (val !== isActiveInt.value) {\n        isActiveInt.value = val;\n      }\n    }\n    /**\n     * intercept click-outside event and close the component\n     * triggered when click happened outside of 'input-frame' element\n     * @param {Event} event\n     */\n    onClickOutside(inputFrame, (event) => {\n      setFieldState(false);\n      /**\n       * Event emitted when click outside input field <div> is registered\n       *\n       * @event clicked-outside\n       * @param {MouseEvent} - the native mouse event\n       *\n       */\n      emit('clicked-outside', event);\n    }, {\n      // define elements that should not trigger a click outside event\n      // here (e.g. drop downs)\n      ignore: props.ignoreClickOutside,\n    });\n\n    /**\n     * function triggered if click event or focus event happened inside the\n     * 'input-frame' element\n     * @param {FocusEvent|MouseEvent} event the native event\n     */\n    function clickedInside(event) {\n      if (!props.disabled) {\n        setFieldState(true);\n        /**\n         * Event emitted on click on input field <div>\n         *\n         * @event click-input-field\n         * @param {FocusEvent, MouseEvent} - event triggered by focusin or click\n         *\n         */\n        emit('click-input-field', event);\n      }\n    }\n    /**\n     * tab key does not always trigger the leaving of the input field but only if\n     * input remove icon is not present\n     * @param event\n     */\n    function handleInputTab(event) {\n      if (!showRemoveIcon.value || event.shiftKey) {\n        setFieldState(false);\n      }\n    }\n\n    onMounted(() => {\n      // on first render set the focus here manually\n      if (isActiveInt.value && inputElement.value) {\n        inputElement.value.focus();\n      }\n    });\n\n    return {\n      idInt,\n      rootAttrs,\n      forwardAttrs,\n      showLabelRow,\n      showRemoveIcon,\n      inputInt,\n      inputMode,\n      input,\n      inputElement,\n      labelLocalized,\n      internalValidationMessage,\n      errorMessageInt,\n      // focus handling\n      inputFrame,\n      isActiveInt,\n      setFieldState,\n      clickedInside,\n      handleInputTab,\n    };\n  },\n  data() {\n    return {\n      /**\n       * store previous input in case invalid input needs to be replaced\n       * @type {string|number}\n       */\n      previousInput: '',\n      /**\n       * variable specifically for internal validation status so\n       * it can not be overwritten by prop `invalid` and `invalidInt`\n       * will always show false if either this variable or `invalid`\n       * are true\n       * @type {boolean}\n       */\n      internalValidationFailed: false,\n    };\n  },\n  computed: {\n    isInputTypeNumber() {\n      return this.inputType === 'number';\n    },\n    /**\n     * compute actual invalid state considering value provided by parent\n     * and internal validation state\n     * @returns {boolean}\n     */\n    invalidInt() {\n      return this.invalid || this.internalValidationFailed;\n    },\n  },\n  watch: {\n    /**\n     * watch modelValue prop to sync with internal inputInt variable\n     */\n    modelValue: {\n      handler(val) {\n        // since internally all values are handled as strings we need to parse input\n        // with inputType 'number' and also place the correct decimal separator\n        // since type float comes with '.'\n        let parsedValue = this.isInputTypeNumber\n          ? this.translateFloat(val) : val;\n\n        // now check if the value provided by parent is actually different from current\n        // internal value\n        if (parsedValue !== this.inputInt) {\n          if (this.isInputTypeNumber) {\n            // in case prop `decimals` is set (to not -1) add the appropriate number\n            // of decimal places to the number\n            // if data is null leave the field empty\n            if (parsedValue && this.decimals !== undefined && this.decimals !== null && this.decimals !== -1) {\n              parsedValue = this.translateFloat(Number(this.stringToFloat(parsedValue)).toFixed(this.decimals));\n            }\n          }\n          // if yes validate the input\n          const validatedValue = this.validate(parsedValue);\n          if (validatedValue !== undefined) {\n            this.inputInt = validatedValue;\n            this.previousInput = this.inputInt;\n          }\n          if (validatedValue !== parsedValue) {\n            // if something went wrong the internal value will not be udpated with the\n            // value provided but a modified value - so to have parent in sync we will\n            // inform them about the current value\n            this.updateModelValue();\n          }\n        }\n      },\n      immediate: true,\n    },\n    /**\n     * keep externally set invalid variable and internal invalid variable in sync\n     * @param {boolean} val\n     */\n    invalidInt(val) {\n      if (val !== this.invalid) {\n        /**\n         * propagate invalid state changes of input field to parent\n         * @event update:invalid\n         * @param {boolean} val\n         */\n        this.$emit('update:invalid', val);\n      }\n    },\n  },\n  methods: {\n    /** INPUT EVENT HANDLING */\n    /**\n     * if input is inputType 'number' we only want to allow certain keys\n     * (yes disallowed characters will be filtered in input validation again as\n     * well but why not stop the entering right here if possible then they don't have to\n     * be removed again later)\n     * @param event\n     */\n    onKeydown(event) {\n      if (this.isInputTypeNumber) {\n        const { key, ctrlKey } = event;\n        // only allow comma keys if decimals are allowed\n        const allowedDecimalKeys = this.decimals !== 0 ? ['\\\\.', ','] : [];\n        // and define and add keys that are always allowed in number fields\n        const allowedKeys = allowedDecimalKeys.concat(['Backspace', 'Delete', 'Tab', 'Enter', 'ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown', 'Shift', 'Control', '[0-9]', 'e', '-', '\\\\+']);\n        const allowedKeysRegex = new RegExp(`(${allowedKeys.join('|')})`);\n        // check if control is true to allow for copy & paste etc. - otherwise stop any\n        // key that is not in allowed keys\n        if (!ctrlKey && !allowedKeysRegex.test(key)) {\n          event.preventDefault();\n          event.stopPropagation();\n        }\n      }\n    },\n\n    /**\n     * method triggered on native HTML input `input` event\n     * @param {InputEvent} event - the native HTML input event\n     */\n    onInput(event) {\n      // validate the provided value\n      const validatedValue = this.validate(event.target.value);\n      // only emit if a value was returned from the validateFunction\n      if (validatedValue !== undefined) {\n        // we need to update the value manually here since it is not updated\n        // through v-model on time for the event emit on some mobile devices\n        this.inputInt = validatedValue;\n        // store input to use/reset if validation fails\n        this.previousInput = validatedValue;\n        // and inform parent of the input update\n        this.updateModelValue();\n      }\n    },\n    /**\n     * function called when input changed and has been validated\n     */\n    updateModelValue() {\n      let parsedValue = this.inputInt;\n      if (this.isInputTypeNumber) {\n        // since internally value is always handled as string we need to transform\n        // it back to a number in case field type is 'number' and also add the correct\n        // decimal separator for type number ('.') again\n        parsedValue = this.stringToFloat(this.inputInt);\n      }\n      /**\n       * Event emitted on input, passing input string\n       *\n       * @event update:model-value\n       * @param {string|number} - the validated input value\n       *\n       */\n      this.$emit('update:model-value', parsedValue);\n    },\n    /**\n     * in general input field active styling is handled via focusin and\n     * clicked-outside, however two cases are handled here:\n     * 1) for special case iOS touch devices have\n     *  up and down arrows that do not trigger any event other than blur and will\n     *  cause the dropdowns of input fields to remain open\n     * 2) field `inputType 'number'` handling\n     * @param {FocusEvent} event - the native blur event\n     */\n    onInputBlur(event) {\n      const { value, id } = event.target;\n\n      // 1) so since these arrows only navigate between input fields we check if there is a\n      // related target and if this related target is an input field and if yes we make sure\n      // the id is different from the input id of this component (the one the event originated from)\n      if (event.relatedTarget && event.relatedTarget.tagName === 'INPUT'\n        && (!event.relatedTarget.id || event.relatedTarget.id !== id)) {\n        // set input active state false\n        this.setFieldState(false);\n      }\n      // 2) check for inputType number\n      if (this.isInputTypeNumber) {\n        // clear value and return if value is NaN\n        if (value === '' || Number.isNaN(Number(this.stringToFloat(value)))) {\n          this.inputInt = '';\n          this.previousInput = '';\n        } else if (this.decimals) {\n          let updatedString;\n          if (this.decimals === -1) {\n            // if an unlimited number of decimals is allowed, parse the value again as\n            // number to remove obsolete chars, e.g. 0.0 > 0\n            updatedString = this.translateFloat(Number(this.stringToFloat(value)));\n          } else {\n            // else add the appropriate number of decimals\n            updatedString = this.translateFloat(Number(this.stringToFloat(value)).toFixed(this.decimals));\n          }\n          this.inputInt = updatedString;\n          // also update previous input so there are no funny effects if a type an\n          // invalid character after blur\n          this.previousInput = this.inputInt;\n        }\n        // and also inform parent of possible changes\n        this.updateModelValue();\n      }\n    },\n    /**\n     * special event triggered when tab was used on clear input button\n     * @param {KeyboardEvent} event\n     */\n    blurInput(event) {\n      // set input active state false\n      this.setFieldState(false);\n      // forward this event as if tab was coming from input to also allow parent to handle\n      // active state if isActive is used\n      // but first check if keydown event was set on parent\n      if (this.$attrs?.onKeyDown) {\n        this.$attrs.onKeyDown(event);\n      }\n    },\n    /**\n     * triggered on clear input button click and removes input and returns focus\n     * to input field\n     */\n    removeInput() {\n      this.inputInt = '';\n      // in input was reset also clear internal error message\n      this.internalValidationMessage = '';\n      this.internalValidationFailed = false;\n      this.updateModelValue();\n      if (this.inputElement) {\n        this.inputElement.focus();\n      }\n    },\n\n    /** INPUT VALIDATION */\n    /**\n     * function validating the input on @input event changes or on values provided by parent\n     * @param {string} input - the value provided by the @input event or `modelValue`\n     * @returns {string|undefined}\n     */\n    validate(input) {\n      // clear errorMessage\n      this.internalValidationMessage = '';\n      this.internalValidationFailed = false;\n      // define a temporary variable that will be modified\n      let value = input;\n\n      // Handle number inputs with input field type text.\n      // Use a regular expression to validate the number format.\n      // Invalid entries are restored with the previous valid value.\n      if (this.isInputTypeNumber) {\n        const decimalSeparator = this.decimals ? `\\\\${this.decimalSeparator}` : '';\n        // if field type is number disallow every character except 0-9, e, +, - and the correct\n        // decimal separator\n        const bannedChars = new RegExp(`[^e0-9${decimalSeparator}\\\\+-]`, 'g');\n        const decimals = this.decimals && this.decimals !== Number('-1') ? `{0,${this.decimals}}` : '*';\n        const eMinus = this.decimals && this.decimals !== Number('-1') ? '-' : '';\n        // pattern to match number: ^((-?[0-9]+(,|\\.)?[0-9]{0,2}(e(-|\\+)?[0-9]*)?)|-)$\n        // allow: optional -, numbers, optional decimal separator, e, optional +|-, numbers\n        const pattern = new RegExp(`^((-?[0-9]*${decimalSeparator}?([0-9]${decimals})(e(${eMinus}|\\\\+)?[0-9]*)?)|-)$`, 'g');\n        // dot or comma are allowed as decimal separators\n        // translate them beforehand\n        value = value.replace(',', this.decimalSeparator);\n        value = value.replace('.', this.decimalSeparator);\n        // remove banned characters\n        value = value.replace(bannedChars, '');\n        // remove multiple special characters\n        value = this.removeMultipleChars(value, this.decimalSeparator);\n        value = this.removeMultipleChars(value, 'e');\n        // update input\n        this.inputInt = value;\n        // round and crop decimals if decimals set\n        if (Number(this.decimals) > -1 && !Number.isNaN(Number(value))) {\n          value = this.roundDecimals(value);\n          this.inputInt = value;\n        }\n        // validate number format\n        if (value !== '' && !value.match(pattern)) {\n          this.inputInt = this.previousInput;\n          return this.inputInt;\n        }\n        // handle min values\n        if (this.min !== null && value && Number(this.stringToFloat(value)) < this.min) {\n          this.internalValidationMessage = this.validationTexts.min.replace('{value}', this.min.toString());\n          this.internalValidationFailed = true;\n        }\n        // handle max values\n        if (this.max !== null && Number(this.stringToFloat(value)) > this.max) {\n          this.internalValidationMessage = this.validationTexts.max.replace('{value}', this.max.toString());\n          this.internalValidationFailed = true;\n        }\n        // reset infinite values\n        if (Number(this.stringToFloat(value)) === Infinity) {\n          value = '0';\n          this.inputInt = value;\n          return;\n        }\n        // do not emit cases which would be NaN\n        if (this.inputIsNaN(value)) {\n          return;\n        }\n      }\n\n      if (this.inputType !== 'number') {\n        // handle min length\n        if (this.minLength && value && value.length < this.minLength) {\n          this.internalValidationMessage = this.validationTexts.minLength.replace('{value}', this.minLength.toString());\n          this.internalValidationFailed = true;\n        }\n        // handle max length\n        if (this.maxLength && value.length > this.maxLength) {\n          this.internalValidationMessage = this.validationTexts.maxLength.replace('{value}', this.maxLength.toString());\n          this.internalValidationFailed = true;\n        }\n      }\n      return value;\n    },\n\n    /** NUMBER HANDLING */\n    /**\n     * create a string out of number values for internal handling (if it is not already)\n     * and replace dot with the display decimalSeparator chosen with prop `decimalSeparator`\n     *\n     * @param {number|string} value\n     * @returns {string}\n     */\n    translateFloat(value) {\n      if (value == null) return '';\n      return value.toString().replace('.', this.decimalSeparator);\n    },\n    /**\n     * replace decimalSeparator with dot\n     *\n     * @param {string} value\n     * @returns {number}\n     */\n    stringToFloat(value) {\n      // number('') would be 0, so we leave it empty if necessary\n      return value ? Number(value.toString().replace(this.decimalSeparator, '.')) : null;\n    },\n    /**\n     * check if input would not be a valid number\n     *\n     * @param {string} value\n     * @returns {boolean}\n     */\n    inputIsNaN(value) {\n      const ds = this.decimalSeparator;\n      // eg: -|-,|-0|-0,0|1,|11,|-1,\n      const pattern = new RegExp(`^(-0|-?(([0-9]*\\\\${ds}([0]*)?)?|(\\\\${ds}([0-9]*)?)?))$`, 'g');\n      return value.length\n        && (value.toString().match(pattern) || Number.isNaN(this.stringToFloat(value)));\n    },\n    /**\n     * crop and round decimals if needed\n     * eg allowed decimals: 2 <br>\n     *   * 12.5e-2 => 0.125 => 0.13\n     *   * 0.01e-1 => 0.001 => 0\n     * @param value\n     * @returns {string}\n     */\n    roundDecimals(value) {\n      const chunks = value.split(this.decimalSeparator);\n      if (chunks[1] && chunks[1].length > this.decimals) {\n        return this.translateFloat(Number(Number(value).toFixed(this.decimals)));\n      }\n      return value;\n    },\n    /**\n     * remove multiple given character except first occurrence\n     * @param {String} value\n     * @param {String} char\n     * @returns {string}\n     */\n    removeMultipleChars(value, char) {\n      const pattern = new RegExp(`\\\\${char}`, 'g');\n      return value.replace(pattern, (c, i, text) => text.indexOf(c) === i ? c : '');\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    v-bind=\"rootAttrs\"\n    class=\"base-input\">\n    <!-- LABEL ROW -->\n    <div\n      :class=\"['base-input__label-row', { hide: !showLabelRow }]\"\n      @click.stop=\"\">\n      <!-- need to disable because label is there (below)? -->\n      <!-- eslint-disable-next-line  vuejs-accessibility/label-has-for -->\n      <label\n        :for=\"idInt\"\n        :class=\"['base-input__label', { hide: !showLabel }]\">\n        {{ labelLocalized }}\n      </label>\n      <div class=\"base-input__label-spacer\" />\n      <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs)) -->\n      <slot name=\"label-addition\" />\n    </div>\n\n    <!-- ACTUAL INPUT FIELD -->\n    <!-- vuejs-accessibility/click-events-have-key-events: keydown event would have unwanted side\n      effects here and is not relevant for accessibility -->\n    <!-- vuejs-accessibility/no-static-element-interactions: click is just for handling focus no\n      interaction/accessibility needed -->\n    <!-- eslint-disable-next-line vuejs-accessibility/click-events-have-key-events vuejs-accessibility/no-static-element-interactions -->\n    <div\n      ref=\"inputFrameEl\"\n      :class=\"['base-input__input-frame',\n               { 'base-input__input-frame__border': showInputBorder },\n               { 'base-input__input-frame__disabled': disabled },\n               { 'base-input__input-frame__invalid': invalidInt }]\"\n      @focusin=\"clickedInside\"\n      @click=\"clickedInside\">\n      <!-- one class __active for pseudo-class :focus-within, one class __is-active\n      for manually setting input active -->\n      <div\n        :class=\"['base-input__input-container',\n                 {\n                   'base-input__input-container__is-active':\n                     isActiveInt && useFormFieldStyling,\n                 }]\">\n        <!-- @slot add elements before the actual input line but within the input field container -->\n        <slot name=\"pre-input-field\" />\n        <div\n          :class=\"['base-input__input-line-container',\n                   { 'base-input__input-line-container__wrap': !hideInputField }]\">\n          <!-- @slot Slot to allow for additional elements in the input field <div> (e.g. chips) (before <input>) -->\n          <slot name=\"input-field-addition-before\" />\n          <div class=\"base-input__input-line\">\n            <!-- @slot to add elements directly inline before the input (contrary to input-field-addition-before this does not wrap -->\n            <slot name=\"input-field-inline-before\" />\n            <div\n              :class=\"['base-input__input-wrapper',\n                       {\n                         'base-input__input-wrapper__fade-out':\n                           useFadeOut && !isActiveInt && !hideInputField,\n                       }]\">\n              <!-- @slot replace native HTML input element with custom input\n                   @binding { string } id - the id of the BaseInput component - if `id` is not provided in props this is an internal id that should also be set as <input> `id`. Also if this slot is used the v-model value should be provided to BaseInput as well for validation. Otherwise validation can be triggered with the `validate()` method. -->\n              <slot\n                :id=\"idInt\"\n                name=\"input\">\n                <!-- instead of v-model we need to use :value because on android chrome value is not updated properly otherwise\n                also see https://stackoverflow.com/questions/75477442/vue-3-v-model-not-properly-updating-on-in-andoids-chrome -->\n                <!-- id attributes needs to be below v-bind in order to prevent an (accidental) overwrite from\n                  outside (and thus id not matching label anymore) -->\n                <!-- eslint-disable vue/attributes-order -->\n                <!-- need to disable because label is there (below)? -->\n                <!-- eslint-disable-next-line  vuejs-accessibility/form-control-has-label -->\n                <input\n                  ref=\"inputField\"\n                  enterkeyhint=\"done\"\n                  autocomplete=\"off\"\n                  v-bind=\"forwardAttrs\"\n                  :id=\"idInt\"\n                  :value=\"inputInt\"\n                  :placeholder=\"placeholder\"\n                  :type=\"isInputTypeNumber ? 'text' : inputType\"\n                  :list=\"dropDownListId || undefined\"\n                  :disabled=\"disabled\"\n                  :aria-disabled=\"disabled\"\n                  :aria-activedescendant=\"linkedListOption\"\n                  :aria-describedby=\"idInt\"\n                  :aria-required=\"required\"\n                  :required=\"required\"\n                  :aria-invalid=\"invalidInt\"\n                  :minlength=\"minLength\"\n                  :maxlength=\"maxLength\"\n                  :inputmode=\"inputMode\"\n                  :class=\"[inputClass, 'base-input__input',\n                           { 'base-input__input__hidden': hideInputField }]\"\n                  @input.stop=\"onInput\"\n                  @keydown=\"onKeydown\"\n                  @keydown.tab=\"handleInputTab\"\n                  @blur=\"onInputBlur\">\n                <!-- eslint-enable vue/attributes-order -->\n              </slot>\n            </div>\n            <div\n              v-if=\"loadable\"\n              class=\"base-input__loader\">\n              <BaseLoader\n                :hide=\"!isLoading\"\n                :text-on-loader-show=\"assistiveText.loaderActive\" />\n            </div>\n            <!-- wrapped in a button for accessibility -->\n            <button\n              v-if=\"showRemoveIcon\"\n              :id=\"`${idInt}-remove-icon`\"\n              class=\"base-input__remove-icon-wrapper\"\n              @keydown.tab=\"blurInput\"\n              @keydown.enter.stop=\"removeInput\"\n              @click.stop=\"removeInput\">\n              <!-- @slot use a custom icon instead of standard remove icon -->\n              <slot name=\"remove-icon\">\n                <BaseIcon\n                  :title=\"assistiveText?.clearInput || 'Clear input'\"\n                  name=\"remove\"\n                  class=\"base-input__remove-icon\" />\n              </slot>\n            </button>\n            <!-- @slot for adding elements after input (e.g. used to add loader) -->\n            <slot name=\"input-field-addition-after\" />\n          </div>\n        </div>\n        <div\n          v-if=\"showErrorIcon && invalidInt\"\n          class=\"base-input__error-icon-wrapper\">\n          <!-- @slot use a custom icon instead of standard error/warning icon -->\n          <slot name=\"error-icon\">\n            <BaseIcon\n              name=\"attention\"\n              class=\"base-input__error-icon\" />\n          </slot>\n        </div>\n        <!-- @slot after the actual input element over whole height of the input field container -->\n        <slot name=\"post-input-field\" />\n      </div>\n    </div>\n\n    <!-- BELOW INPUT FIELD -->\n    <div>\n      <!-- @slot below-input slot added to e.g. add drop down -->\n      <!-- this way it does not interfere with error message -->\n      <slot name=\"below-input\" />\n    </div>\n    <div\n      v-if=\"invalidInt && errorMessageInt\"\n      class=\"base-input__invalid-message\">\n      {{ errorMessageInt }}\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n.base-input {\n  position: relative;\n  background: inherit;\n  width: 100%;\n\n  .base-input__label-row {\n    display: flex;\n    flex-direction: row;\n    margin-bottom: $spacing-small;\n\n    .base-input__label {\n      color: $font-color-second;\n      text-align: left;\n      align-self: flex-end;\n      overflow-wrap: break-word;\n      min-width: 150px;\n      line-height: $line-height;\n    }\n\n    .base-input__label-spacer {\n      flex: 1 1 auto;\n    }\n  }\n\n  .base-input__input-frame {\n    position: relative;\n    width: 100%;\n    background: inherit;\n\n    &::after {\n      content: '';\n      position: absolute;\n      top: 0;\n      right: 0;\n      left: 0;\n      bottom: 0;\n      pointer-events: none;\n      background: transparent;\n    }\n\n    &.base-input__input-frame__border::after {\n      border: $input-field-border;\n    }\n\n    &.base-input__input-frame__invalid::after {\n      border: 1px solid #{$app-color};\n    }\n\n    &.base-input__input-frame__disabled::after {\n      position: absolute;\n      left: 0;\n      top: 0;\n      content: '';\n      height: 100%;\n      width: 100%;\n      background: rgba(245, 245, 245, 0.4);\n    }\n\n    .base-input__input-container {\n      display: flex;\n      position: relative;\n      background: white;\n      min-height: $row-height-small;\n      padding: 0 $spacing-small;\n\n      &.base-input__input-container__active:focus-within,\n      &.base-input__input-container__is-active {\n        box-shadow: $input-shadow;\n      }\n\n      .base-input__input-line-container {\n        display: flex;\n        align-items: center;\n        flex: 1 1 auto;\n\n        &.base-input__input-line-container__wrap {\n          flex-wrap: wrap;\n        }\n\n        .base-input__input-line {\n          display: flex;\n          flex: 1 1 auto;\n          align-items: center;\n\n          .base-input__input-wrapper {\n            flex: 1 1 auto;\n            margin-right: $spacing;\n            position: relative;\n            display: flex;\n\n            &.base-input__input-wrapper__fade-out::after {\n              content: '';\n              width: calc(#{$fade-out-width} + #{$spacing});\n              height: $input-field-line-height;\n              position: absolute;\n              top: 50%;\n              transform: translateY(-50%);\n              right: 0;\n              background: linear-gradient(to right, rgba(255, 255, 255, 0) , white);\n              pointer-events: none;\n            }\n\n            .base-input__input {\n              padding: $spacing-small-half 0;\n              min-height: $row-height-small;\n              width: 100%;\n\n              &.base-input__input__hidden {\n                width: 1px;\n                overflow: hidden;\n                opacity: 0;\n                filter:alpha(opacity=0);\n                animation: all 500ms ease;\n              }\n\n              &[type=search] {\n                appearance: none;\n              }\n            }\n          }\n\n          .base-input__remove-icon-wrapper {\n            color: $font-color-third;\n            cursor: pointer;\n            display: flex;\n            justify-content: center;\n            flex-shrink: 0;\n\n            &:focus, &:active {\n              color: $app-color-secondary;\n            }\n\n            .base-input__remove-icon {\n              height: $icon-medium;\n              width: $icon-medium;\n              min-width: $icon-medium;\n              margin: $spacing-small;\n            }\n          }\n\n          .base-input__loader {\n            margin: 0 $spacing;\n            transform: scale(0.5);\n            pointer-events: none;\n          }\n        }\n      }\n      .base-input__error-icon-wrapper {\n        color: $app-color;\n        display: flex;\n        justify-content: center;\n        align-self: center;\n        flex-shrink: 0;\n\n        .base-input__error-icon {\n          height: $icon-large;\n          width: $icon-large;\n          margin-left: $spacing-small;\n          flex-shrink: 0;\n        }\n      }\n    }\n  }\n\n  .base-input__invalid-message {\n    font-size: $font-size-small;\n    color: $app-color;\n  }\n}\n\n@media screen and (max-width: $tablet) {\n  .base-input {\n    .base-input__label-row {\n      flex-wrap: wrap;\n      justify-content: flex-end;\n\n      .base-input__label-spacer {\n        flex: 1 1 auto;\n      }\n    }\n  }\n}\n</style>\n","<script>\nimport { computed, defineAsyncComponent, toRef, useTemplateRef } from 'vue';\nimport { sort, createId } from '@/utils/utils.js';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { useListNavigation } from '@/composables/useListNavigation.js';\nimport { useAnnouncer } from '@/composables/useAnnouncer.js';\nimport BaseInput from '@/components/BaseInput/BaseInput.vue';\nimport { useId } from '@/composables/useId.js';\nimport { useExtractAttrs } from '@/composables/useExtractAttrs.js';\n\n/** input field with chips functionalities */\n\nexport default {\n  name: 'BaseChipsInputField',\n  components: {\n    BaseInput,\n    BaseChip: defineAsyncComponent(() => import('@/components/BaseChip/BaseChip.vue')),\n    VueDraggable: defineAsyncComponent(() => import('vue-draggable-plus').then(m => m.VueDraggable)),\n  },\n  inheritAttrs: false,\n  props: {\n    /**\n     if field is occurring more than once - set an id\n     */\n    inputId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * list of selected options (strings or objects - set `isStringArray` `true` if it is an array of strings),\n     *  displayed as chips\n     * (you can use the v-model directive on this property)\n     */\n    selectedList: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * input string\n     */\n    modelValue: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify input field type\n     * @values text, search\n     */\n    inputType: {\n      type: String,\n      default: 'text',\n      validator: val => ['text', 'search'].includes(val),\n    },\n    /**\n     * input field label\n     */\n    label: {\n      type: String,\n      required: true,\n    },\n    /**\n     * define if label should be visible\n     */\n    showLabel: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * input field placeholder\n     */\n    placeholder: {\n      type: String,\n      default: null,\n    },\n    /**\n     * define if the user can add an option that is not in the list\n     */\n    // can the user add Entries that are not available in the vocabulary (selectable list)\n    allowUnknownEntries: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define only a single or multiple options can be selected\n     */\n    // define if one or several entries can be selected from drop down menu\n    allowMultipleEntries: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * this means typed input will be added as chip directly\n     */\n    addSelectedEntryDirectly: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `true` a button with that functionality will be visible\n     */\n    sortable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define if chips should be draggable\n     */\n    draggable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define if entries should always appear linked (-> with grey background)\n     */\n    alwaysLinked: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * show spinner to indicate that something is loading\n     * (for dynamically fetched entries that need to do backend requests)\n     */\n    isLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if sorting is enabled this will be the text shown in the button\n     */\n    sortText: {\n      type: String,\n      default: 'Sort A – Z',\n    },\n    /**\n     * if `true` sorting will consider the last string in a label or if a comma is\n     * present the string before the comma\n     */\n    sortName: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set a language (ISO 639-1)\n     */\n    language: {\n      type: String,\n      default: '',\n    },\n    /**\n     * option to have the border of the input field not displayed\n     */\n    showInputBorder: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define if standard form field styling should be\n     * used (otherwise no border, no box shadow)\n     */\n    useFormFieldStyling: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * specify the id of a linked drop-down list\n     */\n    dropDownListId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify a linked list option (e.g. drop down)\n     *   (will be used in `aria-activedescendant` attribute)\n     */\n    linkedListOption: {\n      type: [Number, String],\n      default: null,\n    },\n    /**\n     * specify the object property that should be used as identifier\n     */\n    identifierPropertyName: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify the object property that should be used as value to be displayed\n     */\n    labelPropertyName: {\n      type: String,\n      default: 'label',\n    },\n    /**\n     * specify `true` if `selectedList` array is a array of strings\n     */\n    isStringArray: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * property for special case component [BaseChipsBelow](BaseChipsBelow) - if `false` in this case chips will\n     * not be displayed in the input field\n     */\n    displayChipsInline: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * mark as required field (currently only used for aria-required)\n     */\n    required: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * mark the form field as invalid and ideally also provide an error message\n     * to display below the form field\n     * for an example see [BaseInput](BaseInput)\n     */\n    invalid: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set `true` if input field should be disabled\n     * for an example see [BaseInput](BaseInput)\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * add an error message to be displayed below form field if field is invalid\n     * for an example see [BaseInput](BaseInput)\n     */\n    errorMessage: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define if error icon should be shown\n     * for an example see [BaseInput](BaseInput)\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * if `true` a remove icon will be shown allowing to remove\n     * all input at once\n     * for an example see [BaseInput](BaseInput)\n     */\n    clearable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `true` space is reserved for a loader that can be activated\n     * with the 'isLoading' prop\n     */\n    loadable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * possibility to steer input field active state from outside\n     * it is possible to use the v-model directive here\n     */\n    isActive: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify additional input field styling\n     */\n    inputClass: {\n      type: String,\n      default: '',\n    },\n    /**\n     * use this prop to deactivate automatic setting of focus as soon as input element\n     * becomes active - this might require external handling of focus setting!\n     */\n    setFocusOnActive: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define true if chip should be editable on click\n     * **caveat**: this will only work if prop `allowUnknownEntries` is also set `true`\n     * also setting this prop `true` will disable the dragging functionality (also see prop\n     * `draggable`)\n     */\n    chipsEditable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * this prop gives the option to add assistive text for screen readers\n     * properties:\n     *\n     * **selectedOption**: text read when a selected option is focused (currently only\n     *  working for editable chips)\n     * **loaderActive**: text that is announced when results are being fetched (prop\n     *  `isLoading` is set `true`)\n     * **clearInput**: text read for remove input icon if prop `clearable` is set `true`\n     * **optionAdded**: text read when option was added to the selected list. string {label}\n     *  could be added to be replaced by the actual chip label (value in [`labelPropertyName`])\n     * **optionToRemoveSelected**: text read when option is marked active for removal (by using\n     *  backspace in empty input field). string {label} could be added to be replaced\n     *  by the actual chip label (value in [`labelPropertyName`])\n     * **optionRemoved**: text read when option was removed from the selected list. string {label}\n     *  could be added to be replaced by the actual chip label (value in [`labelPropertyName`])\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        selectedOption: '',\n        loaderActive: 'loading.',\n        clearInput: 'Clear input',\n        optionAdded: 'option {label} added to selected list.',\n        optionToRemoveSelected: 'option {label} from selected list marked for removal. Press delete or backspace to remove.',\n        optionRemoved: 'option {label} removed.',\n      }),\n    },\n    /**\n     * define if selected options chips should come with a remove icon\n     * (usually desired usability wise just an additional option for `allowMultipleEntries`\n     * `false` if there is any other means of removal\n     * (e.g. [BaseAdvancedSearch](#baseadvancedsearch)))\n     */\n    chipsRemovable: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * if necessary chip text can\n     *  be rendered as v-html directive\n     *\n     *  **caveat**: setting this variable `true` can lead to XSS attacks. Only use\n     *    this prop on trusted content and never on user-provided content. This is\n     *    also why this will only take effect on selected chips with identifier (=selected\n     *    from the options not a direct user input)\n     */\n    interpretChipsLabelAsHtml: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['update:selected-list', 'duplicate', 'removed', 'update:model-value', 'update:is-active'],\n  setup(props) {\n    /** INTERNAL ID */\n    const generatedId = useId();\n\n    /** ATTRS HANDLING */\n    const { rootAttrs, forwardAttrs } = useExtractAttrs();\n    /**\n     * use the value provided by the composable\n     * @type {ComputedRef<string>}\n     */\n    const internalId = computed(() => props.inputId || generatedId);\n\n    /** INPUT ELEMENT HANDLING */\n    /**\n     * get a reference to the BaseInput component\n     * @type {Readonly<ShallowRef<HTMLElement| null>>}\n     */\n    const baseInput = useTemplateRef('baseInputEl');\n    /**\n     * from the BaseInput get access to the native HTML input element\n     * this variable is accessed in BaseChipsInput (at least)\n     * @type {ComputedRef<HTMLElement>}\n     */\n    const inputElement = computed(() => baseInput.value?.inputElement || null);\n\n    /** LIST NAVIGATION */\n    const { navigate } = useListNavigation();\n\n    /**\n     * MANIPULATING SELECTED LIST (EDIT OR DRAG)\n     */\n    const isChipsEditable = computed(() => props.chipsEditable && props.allowUnknownEntries);\n\n    /** INTERNATIONALIZATION */\n    const { getLangLabel } = useI18n(toRef(props, 'language'));\n\n    /** ACCESSIBILITY ANNOUNCEMENTS */\n    /**\n     * set up component reference\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const chipsInputField = useTemplateRef('chipsInputFieldEl');\n    // use composable to announce screen reader text on actions taken (e.g.\n    // add chip to selected list or remove chip\n    const { announcement } = useAnnouncer(chipsInputField);\n    return {\n      internalId,\n      baseInput,\n      inputElement,\n      rootAttrs,\n      forwardAttrs,\n      navigate,\n      isChipsEditable,\n      getLangLabel,\n      chipsInputField,\n      announcement,\n    };\n  },\n  data() {\n    return {\n      /**\n       * internal representation of selectedList\n       * @type {(String[]|Object[])}\n       */\n      selectedListInt: [],\n      /**\n       * store active state of the base input field\n       * @type {boolean}\n       */\n      isActiveInt: false,\n      /**\n       * for removing chips via backspace, to get delay after\n       * keydown event\n       * @type {?number}\n       */\n      timeout: null,\n      /**\n       * for removing chips via backspace, to no accidentally delete\n       * chips on multiple backspace keydown events\n       * @type {boolean}\n       */\n      fired: false,\n      /**\n       * for dragging functionality (transition)\n       * @type {boolean}\n       */\n      drag: false,\n      /**\n       * variable for the currently active chip (for arrow key use)\n       * @type {number}\n       */\n      indexActiveForRemove: -1,\n      /**\n       * variable for internal input handling\n       * @type {string}\n       */\n      inputInt: '',\n    };\n  },\n  watch: {\n    /**\n     * selectedList is watched to also change selectedListInt if necessary\n     * was thinking of making this a computed property however if you do\n     * list manipulations (e.g. push, splice) the setter is not triggered\n     * --> more complicated to inform parent (because sometimes setter triggered sometimes not)\n     */\n    selectedList: {\n      handler(val) {\n        // check that new value is not undefined (would throw error with map)\n        if (val) {\n          // create a temporary list object and add an internal id\n          const tempList = val.map(option => ({\n            ...(this.isStringArray ? { [this.labelPropertyName]: option }\n              : option),\n            // adding an internal id - either the one given by identifierProperty or\n            // if not available - assign a previously assigned one or a new id\n            ...{ idInt: option[this.identifierPropertyName] || this.getIdInt(option) },\n          }));\n          // only update if internal list is different from outside list\n          if (JSON.stringify(tempList) !== JSON.stringify(this.selectedListInt)) {\n            this.selectedListInt = tempList;\n          }\n        } else {\n          this.selectedListInt = [];\n        }\n      },\n      deep: true,\n      immediate: true,\n    },\n    /**\n     * to have isActive prop in sync\n     * @param {boolean} val - internal input field active value\n     */\n    isActiveInt(val) {\n      /**\n       * event updating the is-active prop in case of internal changes\n       *\n       * @event update:is-active\n       * @param {boolean} - is input field active\n       */\n      this.$emit('update:is-active', val);\n    },\n    /**\n     * watch for outside changes in the input field active state\n     * @param {boolean} val - the prop value set from outside\n     */\n    isActive: {\n      handler(val) {\n        // check is in sync already\n        if (val !== this.isActiveInt) {\n          this.isActiveInt = val;\n        }\n      },\n      immediate: true,\n    },\n    /**\n     * also input needs to be synchronized between component and parent (if necessary)\n     */\n    modelValue: {\n      handler(val) {\n        // check if sync already\n        if (val !== this.inputInt) {\n          this.inputInt = val;\n        }\n      },\n      immediate: true,\n    },\n    /**\n     * watch if input changes internally and emit event if necessary\n     */\n    inputInt: {\n      handler(val) {\n        if (val !== this.modelValue) {\n          /**\n           * emitting the input string if changed internally\n           * @event update:model-value\n           * @param {string} - the new input string\n           */\n          this.$emit('update:model-value', val);\n        }\n      },\n      immediate: true,\n    },\n  },\n  methods: {\n    /** KEYBOARD HANDLING FOR CHIPS */\n\n    /**\n     * function triggered on any keydown on the input field\n     * @param {KeyboardEvent} event\n     */\n    checkKeyEvent(event) {\n      const { key } = event;\n      // define conditions in which input field should be set inactive (in styling and blurring)\n      if ((key === 'Tab' && !(this.clearable && !!this.inputInt)) || (key === 'Enter' && !this.allowMultipleEntries)) {\n        this.isActiveInt = false;\n      }\n      // if event was Delete check if a chip should be deleted\n      if (this.chipsRemovable && (key === 'Backspace' || key === 'Delete')) {\n        // if backspace (once) is used make last chip active\n        if (key === 'Backspace' && !this.fired\n          && !this.inputInt && this.indexActiveForRemove < 0) {\n          this.indexActiveForRemove = this.selectedListInt.length - 1;\n          // on second backspace set timeout for delete\n        } else if (this.indexActiveForRemove >= 0 && !this.fired && !this.inputInt) {\n          // check if there is actually anything left to remove\n          this.removeEntry(\n            this.selectedListInt[this.indexActiveForRemove],\n            this.indexActiveForRemove,\n          );\n          this.indexActiveForRemove = -1;\n        }\n        // necessary to prevent accidental delete of chips when user keeps backspace pressed\n        this.fired = true;\n        if (this.timeout) {\n          clearTimeout(this.timeout);\n          this.timeout = null;\n        }\n        this.timeout = setTimeout(() => {\n          this.fired = false;\n        }, 200);\n        // if there is no input and arrow right or left was pressed\n        // navigate between the chips\n      } else if (!this.inputInt && (event.key === 'ArrowRight' || event.key === 'ArrowLeft')) {\n        // determine if index should be increased or decreased\n        const isIndexUp = event.key === 'ArrowRight';\n        // do the navigation in the chips list, returns the chip that should be\n        // active after navigation\n        const activeChip = this.navigate(\n          this.selectedListInt,\n          isIndexUp,\n          this.indexActiveForRemove,\n          true,\n        );\n        // set the chip active for removal (currently active one)\n        this.indexActiveForRemove = this.selectedListInt.indexOf(activeChip);\n        // in any other key event reset the chip active for remove\n      } else {\n        this.indexActiveForRemove = -1;\n      }\n      // if an entry was set active for removal by any key action - announce it\n      // to the screen reader user\n      if (this.assistiveText.optionToRemoveSelected && this.indexActiveForRemove >= 0) {\n        // inform screen reader user\n        this.announcement = this.assistiveText.optionToRemoveSelected\n          .replace('{label}', this.selectedListInt[this.indexActiveForRemove][this.labelPropertyName]);\n      }\n    },\n\n    /** LIST MODIFICATIONS */\n\n    /**\n     * remove an entry from the list of selected entries\n     *\n     * @param {Object} option - the option selected from the list of selected\n     * options\n     * @param {number} index - the index of the item in the list\n     */\n    removeEntry(option, index) {\n      // save the label for screen reader information\n      const optionLabel = this.selectedListInt[index][this.labelPropertyName];\n      // remove the item from the internal list\n      this.selectedListInt.splice(index, 1);\n      // emit an event to inform parent of altered list\n      this.updateParentList(this.selectedListInt);\n      // also emit event to inform which item was removed\n      /**\n       * event emitted if option is removed from the list of selected\n       * options (additionally to altered list in case parent needs to know\n       * which item was removed)\n       *\n       * @event removed\n       * @aram {Object} - the removed option\n       */\n      this.$emit('removed', option);\n      // lay the focus on the input field\n      if (this.inputElement) {\n        // trigger an input click here instead of focus so that clicked-outside is triggered for all\n        // other input fields (and potential drop downs / pop ups are closed)\n        this.inputElement.click();\n      }\n      // check if assistive text was set\n      if (this.assistiveText.optionRemoved) {\n        // add a timeout so announcement is not interfered with by default drop down list announcement\n        setTimeout(() => {\n          // inform screen reader user\n          this.announcement = this.assistiveText.optionRemoved\n            .replace('{label}', optionLabel);\n        }, 1000);\n      }\n    },\n    /**\n     * adding an selected option to the array of selected options\n     */\n    addOption() {\n      // if there is input, unknown options are allowed and direct option addition\n      // is enabled - we can add the option to the selected list directly\n      if (this.inputInt && this.allowUnknownEntries && this.addSelectedEntryDirectly) {\n        // check for duplicates\n        const duplicate = this.selectedListInt\n          .find(option => option[this.labelPropertyName] === this.inputInt);\n        // if no duplicate was found add the entry\n        if (!duplicate) {\n          // where should new item be placed (added at the end or replacing old entry\n          // if single select\n          const setIndex = this.allowMultipleEntries ? this.selectedListInt.length : 0;\n          // create object to add\n          const newEntry = {\n            idInt: this.getIdInt(),\n            [this.labelPropertyName]: this.inputInt,\n          };\n          // set entry in selectedList\n          this.selectedListInt[setIndex] = newEntry;\n          // emit an event to inform parent of altered list\n          this.updateParentList(this.selectedListInt);\n          // make sure the assistiveText property was set\n          if (this.assistiveText.optionAdded) {\n            // and inform screen reader user\n            this.announcement = this.assistiveText.optionAdded\n              .replace('{label}', this.inputInt);\n          }\n          // otherwise just emit event to parent (for informing user)\n        } else {\n          /**\n           * emitted when user was trying to add an option but there was already\n           * an option with the same value in the list of selected options\n           *\n           * @event duplicate\n           * @param {Object} - the option with the identical value\n           */\n          this.$emit('duplicate', duplicate);\n        }\n        // reset the input\n        this.inputInt = '';\n      }\n    },\n    modifyListEntry(newString, index) {\n      // since this is also checked when assigning value to chip we should also check\n      // here if label is lang object (e.g. {de: '', en: '' })\n      if (typeof this.selectedListInt[index][this.labelPropertyName] === 'object'\n        && this.selectedListInt[index][this.labelPropertyName][this.language] !== undefined) {\n        // if so then assign the new value to the current language\n        // and also remove the id since the entry was altered and is not identical with the entry\n        // belonging to this id anymore\n        this.selectedListInt[index] = {\n          [this.labelPropertyName]: {\n            [this.language]: newString,\n          },\n        };\n        // else check if label prop is string and assign it directly\n        // (otherwise this case (an object with unknown properties) can not be handled)\n      } else if (typeof this.selectedListInt[index][this.labelPropertyName] === 'string') {\n        // and also remove the id since the entry was altered and is not identical with the entry\n        // belonging to this id anymore\n        this.selectedListInt[index] = {\n          [this.labelPropertyName]: newString,\n        };\n      }\n      // trigger change propagation to parent\n      this.updateParentList(this.selectedListInt);\n    },\n    /**\n     * function called when parent needs to be informed of selected\n     * list changes\n     *\n     * @param {Object[]} newSelectedListInt - the altered list of selected options\n     */\n    updateParentList(newSelectedListInt) {\n      let tempList = JSON.parse(JSON.stringify(newSelectedListInt));\n      // if provided selected list consisted of strings - return this way\n      if (this.isStringArray) {\n        tempList = tempList.map(selected => selected[this.labelPropertyName]);\n      } else if (newSelectedListInt.length) {\n        // remove internal ids again\n        tempList = tempList.map((selected) => {\n          // eslint-disable-next-line no-param-reassign\n          delete selected.idInt;\n          return selected;\n        });\n      }\n      /**\n       * inform parent of changes to selected option list\n       * (you can use the v-model directive on prop selectedList)\n       *\n       * @event update:selected-list\n       * @param {(Object[], String[])} - the modified list - array\n       * of strings is returned if isStringArray was set to true\n       */\n      this.$emit('update:selected-list', tempList);\n    },\n    /**\n     * every selected option needs an internal id to be uniquely identifyable\n     * by draggablejs\n     *\n     * @param {Object} [option=null] - the option the internal id is determined for\n     */\n    getIdInt(option = null) {\n      // check if the selected option already has an internal identifier\n      // not applicable for newly created entries so check if option was provided\n      if (option) {\n        // get matching option by value (this is only for options that dont have an\n        // external id provided anyways (also duplicates are excluded in 'addOption()'\n        const matchingOption = this.selectedListInt\n          .find(opt => opt[this.labelPropertyName] === option[this.labelPropertyName]\n            || opt[this.labelPropertyName] === option);\n        // check if there was exactly one matching result\n        if (matchingOption) {\n          return matchingOption.idInt;\n        }\n      }\n      // else return a new internal id\n      return createId();\n    },\n\n    /** SORTING */\n    /** function called when the 'sort' button is clicked */\n    sortSelectedList() {\n      this.isActiveInt = false;\n      sort(\n        this.selectedListInt,\n        this.labelPropertyName,\n        this.sortName,\n        this.language ? this.getLangLabel : null,\n      );\n      this.updateParentList(this.selectedListInt);\n    },\n\n    /** DRAGGABLE FUNCTIONALITIES */\n\n    /**\n     * need to set custom due to some strange effects not showing correct element in some cases\n     * @param {DataTransfer} dataTransfer\n     * @param {HTMLElement} dragEl - the dragged HTML Element\n     */\n    setDragElement(dataTransfer, dragEl) {\n      this.drag = true;\n      const img = dragEl.cloneNode(true);\n      img.id = 'chip-inline-drag';\n      img.style.position = 'absolute';\n      img.style.top = '-99999px';\n      img.style.left = '-99999px';\n\n      // add the element to the dom\n      document.body.appendChild(img);\n      dataTransfer.setDragImage(img, 0, 0);\n    },\n    /**\n     * set the appropriate cursor on mouse down by adding a class\n     * (if it is set on drag start there is a short period where\n     * cursor does not match action)\n     */\n    onMouseDown() {\n      if (this.draggable) {\n        this.drag = true;\n      }\n    },\n    /**\n     * remove that class again by setting drag false\n     */\n    onMouseUp() {\n      this.drag = false;\n    },\n    onDragEnd() {\n      this.drag = false;\n      const elem = document.getElementById('chip-inline-drag');\n      if (elem) {\n        elem.parentNode.removeChild(elem);\n      }\n      // check if dragging led to differently sorted list\n      // and inform parent if yes\n      if (JSON.stringify(this.selectedList) !== JSON.stringify(this.selectedListInt)) {\n        this.updateParentList(this.selectedListInt);\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    ref=\"chipsInputFieldEl\"\n    v-bind=\"rootAttrs\"\n    class=\"base-chips-input-field\">\n    <!-- INPUT LABEL AND FIELD -->\n    <BaseInput\n      ref=\"baseInputEl\"\n      v-model=\"inputInt\"\n      v-model:is-active=\"isActiveInt\"\n      :input-id=\"internalId\"\n      v-bind=\"forwardAttrs\"\n      :input-type=\"inputType\"\n      :placeholder=\"allowMultipleEntries || !selectedListInt.length ? placeholder : ''\"\n      :label=\"label\"\n      :show-label=\"showLabel\"\n      :show-input-border=\"showInputBorder\"\n      :use-form-field-styling=\"useFormFieldStyling\"\n      :drop-down-list-id=\"dropDownListId\"\n      :linked-list-option=\"linkedListOption\"\n      :hide-input-field=\"!allowMultipleEntries && !!selectedListInt.length\"\n      :invalid=\"invalid\"\n      :required=\"required\"\n      :disabled=\"disabled\"\n      :clearable=\"clearable\"\n      :loadable=\"loadable\"\n      :error-message=\"errorMessage\"\n      :show-error-icon=\"showErrorIcon\"\n      :is-loading=\"isLoading\"\n      :input-class=\"inputClass\"\n      :set-focus-on-active=\"setFocusOnActive\"\n      :validation-texts=\"{}\"\n      :assistive-text=\"{\n        loaderActive: assistiveText.loaderActive,\n        clearInput: assistiveText.clearInput,\n      }\"\n      @keydown.enter.prevent=\"addOption\"\n      @keydown=\"checkKeyEvent\">\n      <template\n        #label-addition>\n        <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs)) -->\n        <slot name=\"label-addition\" />\n        <button\n          v-if=\"sortable\"\n          :aria-label=\"`${label}. ${sortText.replace(/[—–-]/, 'to')}`\"\n          type=\"button\"\n          class=\"base-chips-input-field__sort\"\n          @click=\"sortSelectedList(selectedListInt)\">\n          {{ sortText }}\n        </button>\n      </template>\n      <template #pre-input-field>\n        <!-- @slot slot to add elements within the form field but in a row before the actual input field. for an example see [BaseInput](BaseInput)-->\n        <slot name=\"pre-input-field\" />\n      </template>\n      <template\n        #input-field-addition-before>\n        <!-- @slot Slot to allow for additional elements in the input field <div> (before <input>) -->\n        <slot name=\"input-field-addition-before\" />\n        <div\n          v-if=\"displayChipsInline\"\n          class=\"base-chips-input-field__chips\">\n          <template v-if=\"draggable && !isChipsEditable\">\n            <VueDraggable\n              v-model=\"selectedListInt\"\n              :set-data=\"setDragElement\"\n              :animation=\"200\"\n              handle=\".base-chip__text\"\n              drag-class=\"base-chips-input-field__chip--dragged\"\n              class=\"base-chips-input-field__chips-transition\"\n              @mousedown=\"onMouseDown\"\n              @mouseup=\"onMouseUp\"\n              @end=\"onDragEnd\">\n              <TransitionGroup\n                :name=\"!drag ? 'flip-list' : undefined\"\n                type=\"transition\">\n                <template\n                  v-for=\"(entry, index) in selectedListInt\">\n                  <!-- @slot a slot to provide customized chips\n                    @binding { object } entry - one selected option displayed as chip\n                    @binding { number } index - the index of the entry in the selectedList array\n                    @binding { number } indexActiveForRemove - the index of the chip that is currently active to be removed (for keyboard handling)\n                    @binding { function } removeEntry - function to remove the entry from selectedList, needs `entry` and `index` as arguments\n                  -->\n                  <slot\n                    name=\"chip\"\n                    v-bind=\"{\n                      entry,\n                      index,\n                      indexActiveForRemove,\n                      removeEntry,\n                    }\">\n                    <BaseChip\n                      :id=\"entry.idInt\"\n                      :key=\"allowMultipleEntries ? 'chip-' + entry.idInt : index\"\n                      :model-value=\"getLangLabel(entry[labelPropertyName], true)\"\n                      :is-linked=\"alwaysLinked || entry[identifierPropertyName] === 0\n                        || !!entry[identifierPropertyName]\"\n                      :chip-active=\"indexActiveForRemove === index\"\n                      :is-removable=\"chipsRemovable\"\n                      :interpret-text-as-html=\"interpretChipsLabelAsHtml && !!entry[identifierPropertyName]\"\n                      :class=\"['base-chips-input-field__chip--draggable', { 'base-chips-input-field__chip--dragging': drag }]\"\n                      @remove-entry=\"removeEntry(entry, index)\" />\n                  </slot>\n                </template>\n              </TransitionGroup>\n            </VueDraggable>\n          </template>\n          <template v-else>\n            <template\n              v-for=\"(entry, index) in selectedListInt\">\n              <!-- @slot a slot to provide customized chips\n                @binding { object } entry - one selected option displayed as chip\n                @binding { number } index - the index of the entry in the selectedList array\n                @binding { number } indexActiveForRemove - the index of the chip that is currently active to be removed (for keyboard handling)\n                @binding { function } removeEntry - function to remove the entry from selectedList, needs `entry` and `index` as arguments\n              -->\n              <slot\n                name=\"chip\"\n                v-bind=\"{\n                  entry,\n                  index,\n                  indexActiveForRemove,\n                  removeEntry,\n                }\">\n                <BaseChip\n                  :id=\"entry.idInt\"\n                  :key=\"allowMultipleEntries ? 'chip-' + entry.idInt : index\"\n                  :model-value=\"getLangLabel(entry[labelPropertyName], true)\"\n                  :editable=\"isChipsEditable\"\n                  :is-linked=\"alwaysLinked || entry[identifierPropertyName] === 0\n                    || !!entry[identifierPropertyName]\"\n                  :chip-active=\"indexActiveForRemove === index\"\n                  :assistive-text=\"assistiveText.selectedOption\"\n                  :is-removable=\"chipsRemovable\"\n                  :interpret-text-as-html=\"interpretChipsLabelAsHtml && !!entry[identifierPropertyName]\"\n                  @remove-entry=\"removeEntry(entry, index)\"\n                  @update:model-value=\"modifyListEntry($event, index)\" />\n              </slot>\n            </template>\n          </template>\n        </div>\n      </template>\n      <template #input-field-inline-before>\n        <!-- @slot to add elements directly inline before the input (contrary to `input-field-addition-before` this does not wrap). for an example see [BaseInput](BaseInput)-->\n        <slot name=\"input-field-inline-before\" />\n      </template>\n      <template #input-field-addition-after>\n        <!-- @slot for adding elements after input -->\n        <slot name=\"input-field-addition-after\" />\n      </template>\n      <template #post-input-field>\n        <!-- @slot for adding elements at the end covering the whole height -->\n        <slot name=\"post-input-field\" />\n      </template>\n      <template #error-icon>\n        <!-- @slot use a custom icon instead of standard error/warning icon -->\n        <slot name=\"error-icon\" />\n      </template>\n      <template #remove-icon>\n        <!-- @slot use a custom icon instead of standard remove icon -->\n        <slot name=\"remove-icon\" />\n      </template>\n      <template #below-input>\n        <!-- @slot below-input slot added to e.g. add drop down -->\n        <slot name=\"below-input\" />\n      </template>\n    </BaseInput>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-chips-input-field {\n    width: 100%;\n    text-align: left;\n\n    .base-chips-input-field__chips {\n      max-width: 100%;\n\n      .base-chips-input-field__chips-transition {\n        display: flex;\n        flex-wrap: wrap;\n\n        // needed at least for Firefox\n        .base-chips-input-field__chip--dragged {\n          cursor: grabbing;\n        }\n\n        .base-chips-input-field__chip--draggable {\n          &:hover {\n            cursor: grab;\n          }\n\n          &.base-chips-input-field__chip--dragging {\n            &:deep(.base-chip__text) {\n              &:active, &:focus {\n                cursor: grabbing;\n              }\n            }\n          }\n        }\n      }\n    }\n\n    .base-chips-input-field__sort {\n      cursor: pointer;\n      margin-left: $spacing;\n      white-space: nowrap;\n      transition: all 0.2s ease;\n\n      &:hover, &:active, &:focus {\n        color: $app-color;\n      }\n    }\n\n    .base-chips-input-field__loader {\n      margin: 0 $spacing;\n      transform: scale(0.5);\n      pointer-events: none;\n    }\n  }\n</style>\n","<script>\nimport { defineAsyncComponent } from 'vue';\nimport { useId } from '@/composables/useId.js';\n\n/**\n * Basic Chip component\n */\n\nexport default {\n  name: 'BaseChip',\n  components: {\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseInsertTextAsHtml: defineAsyncComponent(() => import('@/components/BaseInsertTextAsHtml/BaseInsertTextAsHtml.vue')),\n  },\n  props: {\n    /**\n     * pass the text for the chip\n     */\n    modelValue: {\n      type: String,\n      required: true,\n    },\n    /**\n     * set if entry is a linked data entry and displayed with grey background\n     */\n    isLinked: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * set chip active (set color)\n     */\n    chipActive: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * flag to specify if chip can be removed\n     */\n    isRemovable: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * add some custom text styling\n     */\n    textStyling: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * define true if chip should be editable on click\n     */\n    editable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * text read when a chip is focused - currently only available with prop\n     *  `editable` true\n     */\n    assistiveText: {\n      type: String,\n      default: '',\n    },\n    /**\n     * if necessary chip text can be rendered as html\n     *  this feature is currently only available if the chip is not editable\n     *\n     *  **caveat**: setting this variable `true` can lead to XSS attacks. Only use\n     *    this prop on trusted content and never on user-provided content.\n     */\n    interpretTextAsHtml: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['clicked', 'update:model-value', 'remove-entry'],\n  setup() {\n    const internalId = useId();\n    return {\n      internalId,\n    };\n  },\n  data() {\n    return {\n      /**\n       * internal representation of string provided by parent\n       * @type {string}\n       */\n      modelValueInt: '',\n    };\n  },\n  watch: {\n    modelValue: {\n      handler(val) {\n        if (val !== this.modelValueInt) {\n          this.modelValueInt = val;\n        }\n      },\n      immediate: true,\n    },\n  },\n  methods: {\n    /**\n     * update the internal text variable if chip is editable and\n     * inform parent\n     * @param {KeyboardEvent} event\n     */\n    updateText(event) {\n      const textString = event.target.innerText;\n      if (this.editable && textString !== this.modelValueInt) {\n        this.modelValueInt = textString;\n        /**\n         * if chip is editable value is updated with this event\n         *\n         * @event update:model-value\n         * @param {string} - the displayed text string after edit\n         */\n        this.$emit('update:model-value', this.modelValueInt);\n      }\n    },\n    clickAction(e) {\n      if (!this.editable) {\n        e.stopPropagation();\n        /**\n         * event emitted when chip is clicked\n         *\n         * @event clicked\n         *\n         */\n        this.$emit('clicked');\n      }\n    },\n    removeClicked() {\n      /**\n       * triggered when the remove icon is clicked and returns the data behind the chip\n       *\n       * @event remove-entry\n       * @param {string} - the displayed chip string\n       *\n       */\n      this.$emit('remove-entry', this.modelValueInt);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    :class=\"['base-chip',\n             { 'base-chip__removable': isRemovable },\n             { 'base-chip__linked': isLinked },\n             { 'base-chip__active': chipActive }]\">\n    <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n    <BaseInsertTextAsHtml\n      ref=\"chipText\"\n      render-element-as=\"div\"\n      :text=\"modelValueInt\"\n      :interpret-text-as-html=\"interpretTextAsHtml && !editable\"\n      :style=\"textStyling\"\n      :contenteditable=\"editable ? 'true' : undefined\"\n      :aria-labelledby=\"assistiveText ? `${internalId}_aria-label` : undefined\"\n      enterkeyhint=\"search\"\n      class=\"base-chip__text\"\n      @blur=\"updateText\"\n      @keydown.enter.prevent=\"updateText\"\n      @click.stop=\"clickAction\" />\n    <span\n      v-if=\"assistiveText\"\n      :id=\"`${internalId}_aria-label`\"\n      class=\"hide\">\n      {{ assistiveText }}\n    </span>\n    <BaseIcon\n      v-if=\"isRemovable\"\n      name=\"remove\"\n      class=\"base-chip__icon\"\n      @click.stop=\"removeClicked\" />\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n  @use \"@/styles/variables\" as *;\n\n  .base-chip {\n    margin: $chips-spacing*4 $spacing-small $chips-spacing*4 0;\n    padding: $chips-spacing $spacing-small;\n    flex: 0 0 auto;\n    background-color: rgba(255, 255, 255, 0);\n    line-height: $line-height;\n    display: inline-flex;\n    align-items: center;\n    cursor: default;\n    position: relative;\n    overflow: hidden;\n    max-width: 100%;\n\n    &.base-chip__linked {\n      background-color: $background-color;\n    }\n\n    &.base-chip__removable {\n      padding-right: calc(#{$spacing} + #{$icon-min});\n    }\n\n    &.base-chip__active {\n\n      &:after {\n        content: '';\n        width: 100%;\n        height: 100%;\n        position: absolute;\n        top: 0;\n        right: 0;\n        background-color: $app-color;\n        opacity: 0.5;\n      }\n    }\n\n    // this class is also specified as handle in BaseChipsInputField!\n    .base-chip__text {\n      border: none;\n      background-color: rgba(255, 255, 255, 0);\n      color: $font-color;\n      word-break: break-word;\n      z-index: map.get($zindex, boxcontent);\n\n      &:active, &:focus {\n        outline: none;\n        cursor: text;\n      }\n    }\n\n    .base-chip__icon {\n      position: absolute;\n      padding: $spacing-small;\n      right: 0;\n      cursor: pointer;\n      width: calc((#{$spacing-small} * 2) + #{$icon-min});\n      display: flex;\n      justify-content: center;\n      align-items: center;\n    }\n  }\n</style>\n","<script setup>\nimport { highlightText } from '@/utils/utils.js';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { computed, useSlots, toRef, useTemplateRef, watch } from 'vue';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\n\n/** a multipurpose drop-down list */\n\ndefineOptions({\n  name: 'BaseDropDownList',\n});\n\n\nconst props = defineProps({\n  /**\n   * list of options to select from, this needs to be an object with identifier\n   * and label (the actual property names can be adapted with\n   * `identifierPropertyName` and `labelPropertyName` respectively)\n   */\n  dropDownOptions: {\n    type: Array,\n    default: () => [],\n  },\n  /**\n   * specify the name of a property that can be used as identifier\n   */\n  identifierPropertyName: {\n    type: String,\n    default: 'id',\n  },\n  /**\n   * specify the name of the property that should be displayed\n   */\n  labelPropertyName: {\n    type: String,\n    default: 'value',\n  },\n  /**\n   * specify the currently active option (will have gray background\n   * if not disabled by setting `activeStyled` `false`) for example for\n   * combination with input and keyboard use\n   */\n  activeOption: {\n    type: [Object],\n    default: () => ({}),\n  },\n  /**\n   * specify the currently selected option (will appear in app color if not disabled\n   * by setting `selectStyled` `false`, but also used for `aria-selected`).\n   *   the v-model directive can be used here\n   */\n  selectedOption: {\n    type: [Object],\n    default: () => ({}),\n  },\n  /**\n   * in order to link the drop-down body to an <input> element specify a list\n   * id and use the `list` attribute on the input\n   */\n  listId: {\n    type: String,\n    default: '',\n  },\n  /**\n   * add styling to the list body (e.g. max-height) (useful\n   * if slots `before-list` or `after-list` should not be part of scroll container)\n   */\n  listBodyStyle: {\n    type: Object,\n    default: () => ({}),\n  },\n  /**\n   * flag if the currently active element should be styled\n   * (gray background)\n   */\n  activeStyled: {\n    type: Boolean,\n    default: true,\n  },\n  /**\n   * flag if the currently selected entry should be styled\n   * (only makes sense for single select, color: app-color)\n   */\n  selectStyled: {\n    type: Boolean,\n    default: false,\n  },\n  /**\n   * if `true` the element will be styled as a drop-down element with\n   * box-shadow\n   */\n  displayAsDropDown: {\n    type: Boolean,\n    default: true,\n  },\n  /**\n   * message displayed when no selectable options are available\n   */\n  dropDownNoOptionsInfo: {\n    type: String,\n    default: '',\n  },\n  /**\n   * specify a language (ISO 639-1) (used for label if label is language specific object\n   * e.g. `{ de: 'xxx', en: 'yyy' }`\n   */\n  language: {\n    type: String,\n    default: '',\n  },\n  /**\n   * this adds the possibility of nested options (thus a second list nested within the first one),\n   * if an active sub-option is added, this will have consequences for scroll adjustment of list\n   * on keyboard use and how the active option is determined (the identifier property will be used)\n   */\n  activeSubOption: {\n    type: [Object, null],\n    default: () => null,\n  },\n  /**\n   * in case a custom option background should be set to the currently active option\n   *   (this will also apply if `activeStyled` is set `false`).\n   * if you want to use this option please set the css variable `--option-background`\n   * in your app\n   */\n  useCustomOptionActiveBackgroundColor: {\n    type: Boolean,\n    default: false,\n  },\n  /**\n   * set true if option characters matching a string provided in `highlightStringMatch`\n   *  should be highlighted\n   */\n  useHighlightStringMatch: {\n    type: Boolean,\n    default: false,\n  },\n  /**\n   * if `useHighlightStringMatch` is set to `true`, provide a string to match with the\n   *  option label here\n   */\n  highlightStringMatch: {\n    type: String,\n    default: '',\n  },\n  /**\n   * provide tag names to style the matched characters\n   *  (without '<' and '>', e.g. ['b'] for <b>)\n   */\n  highlightStringTags: {\n    type: Array,\n    default: () => ([]),\n  },\n});\n\nconst emits = defineEmits([\n  /**\n   * inform parent if option was selected by mouse click\n   * (v-model on prop selectedOption can be used)\n   *\n   * @event update:selected-option\n   * @param {Object} - the selected option\n   */\n  'update:selected-option',\n]);\n\n/** INTERNATIONALIZATION */\nconst { getLangLabel } = useI18n(toRef(props, 'language'));\n\n/** GENERAL */\n/**\n * a reference to the single list options\n * @type {Readonly<ShallowRef<HTMLElement[] | null>>}\n */\nconst options = useTemplateRef('optionsEl');\n/**\n * a reference to the outermost element container - either this element or\n * dropDownList could be scroll container\n * @type {Readonly<ShallowRef<HTMLElement | null>>}\n */\nconst dropDownContainer = useTemplateRef('dropDownContainerEl');\n/**\n * a reference to the <ul> element - either this element or\n * dropDownContainer could be scroll container\n * @type {Readonly<ShallowRef<HTMLElement | null>>}\n */\nconst dropDownList = useTemplateRef('dropDownListEl');\n\n/**\n * filter out duplicates and options that don't have a value to display\n * @type {ComputedRef<Object[]>}\n */\nconst cleanedOptions = computed(() => {\n  // get array ids to check for uniqueness (done here to limit additional looping to a minimum)\n  const arrayIds = props.dropDownOptions.map(item => item[props.identifierPropertyName]);\n  // check for duplicates\n  const hasDuplicates = new Set(arrayIds).size !== arrayIds.length;\n  return props.dropDownOptions.reduce((prev, option) => {\n    let isDuplicate = false;\n    const langLabel = getLangLabel(option[props.labelPropertyName], true);\n    // if the array does have duplicates we need to check if the option is\n    // already in the reduced array (done so additional filtering is only done if really\n    // necessary\n    if (hasDuplicates) {\n      // check if an option with that id was already pushed to the reduced array\n      isDuplicate = prev\n        .some((reducedArrItem) => reducedArrItem[props.identifierPropertyName] === option[props.identifierPropertyName]);\n      if (isDuplicate) {\n        console.warn(`Option '${langLabel}' (identifier: ${option[props.identifierPropertyName]}) is duplicated in the options list and will be removed!`);\n      }\n    }\n    // check that option is not a duplicate and if a label string was found\n    if (!isDuplicate && langLabel) {\n      // if yes add it to the new list\n      return prev.concat({\n        ...option,\n        [props.labelPropertyName]: langLabel,\n      });\n    }\n    // else just return the new array as is\n    return prev;\n  }, []);\n});\n\n/** SELECT OPTION */\n/**\n * triggered if option was selected by click\n * @param {Object} selectedOption - the selected option\n */\nfunction selected(selectedOption) {\n  // do not emit the modified option but the originally provided one\n  const originalOption = props.dropDownOptions\n    .find((option) => option[props.identifierPropertyName] === selectedOption[props.identifierPropertyName]);\n  emits('update:selected-option', originalOption);\n}\n\n/** ACTIVE OPTION HANDLING */\n/**\n * determine the scroll container dynamically, since usually it would be the container element\n * however with prop `listBodyStyle` overflow could also be set on the <ul> element (useful\n * if slots `before-list` or `after-list` should not be part of scroll container)\n * @type {ComputedRef<null|HTMLElement>}\n */\nconst scrollContainerElement = computed(() => {\n  if (dropDownList.value && dropDownList.value.scrollHeight > dropDownList.value.clientHeight) {\n    return dropDownList.value;\n  }\n  return dropDownContainer.value;\n});\n/**\n * since it should not change often also determine the height dynamically\n * @type {ComputedRef<number>}\n */\nconst scrollContainerHeight = computed(() => {\n  return scrollContainerElement.value ? scrollContainerElement.value.clientHeight : 0;\n});\n/**\n * the index of the currently active option provided by parent\n * @returns {number}\n */\nconst activeOptionIndex = computed(() => {\n  if (!props.activeOption) return -1;\n  return cleanedOptions.value.findIndex((option) => {\n    return option[props.identifierPropertyName] === props.activeOption[props.identifierPropertyName];\n  });\n});\n/**\n * the currently active option provided by parent\n * @returns {number}\n */\nconst activeOptionInt = computed(() => {\n  return cleanedOptions.value[activeOptionIndex.value] || null;\n});\n\n/**\n * get the template element for the currently active option\n * @type {ComputedRef<HTMLElement|null>}\n */\nconst activeOptionElement = computed(() => {\n  if (!options.value) return null;\n  // this can NOT be done via activeOptionIndex since the Vue docs state that the element reference\n  // array DOES NOT necessarily have the same order!\n  // (https://vuejs.org/guide/essentials/template-refs#refs-inside-v-for)\n  return options.value\n    .find((option) => option.id === activeOptionInt.value[props.identifierPropertyName]?.toString())\n    || null;\n});\n\n/**\n * watch prop `activeSubOption` to handle list intoView scrolling of the currently\n * active element\n */\nwatch(() => props.activeSubOption, (val) => {\n  // check if a sub-option is present and active\n  if (val) {\n    // get the relevant HTML element so the position can be determined\n    const subOptionElement = document.getElementById(val.id);\n    // make sure an active option and sub-option was found\n    if (activeOptionElement.value && subOptionElement) {\n      // combine the offsetTop of the active element and the offsetTop of the\n      // sub-option (which is relative to the active element)\n      const totalOffsetTop = activeOptionElement.value.offsetTop + subOptionElement.offsetTop;\n      // check if the sub-option top position is smaller than the scroll container offsetTop or larger\n      // than the top position + container size (= the offsetTop is out of the view window)\n      // if yes - trigger scroll into view (up)\n      if (totalOffsetTop < scrollContainerElement.value.scrollTop\n        || totalOffsetTop > scrollContainerElement.value.scrollTop + scrollContainerHeight.value) {\n        // scrollIntoView is not working properly here so we set the position manually\n        scrollContainerElement.value.scrollTop = totalOffsetTop;\n        // or check if the bottom of the active sub-option is not in view anymore - then adjust the\n        // scroll as well\n        // scrollIntoView is not working properly here so we set the position manually\n      } else if (totalOffsetTop + subOptionElement.clientHeight > scrollContainerHeight.value + scrollContainerElement.value.scrollTop) {\n        scrollContainerElement.value.scrollTop = scrollContainerElement.value.scrollTop + subOptionElement.clientHeight;\n      }\n    }\n  }\n});\n\nwatch(activeOptionIndex, (index) => {\n  // if the component has sub-options the scrolling will be handled by the props.activeSubOption\n  // watcher\n  if (props.activeSubOption) return;\n  // if active option was removed and drop down is still present scroll back to\n  // top\n  if (index === -1 && scrollContainerElement.value) {\n    scrollContainerElement.value.scrollTo({\n      top: 0,\n    });\n    return;\n  }\n  // make sure an active option was found\n  if (activeOptionElement.value) {\n    // store element offsetTop in a variable since used more than once\n    const elementOffsetTop = activeOptionElement.value.offsetTop;\n    // get the necessary container elements and their top and height variables\n    // check if current active option is out of view\n    const optionOutOfView = elementOffsetTop < scrollContainerElement.value.scrollTop\n      || elementOffsetTop + activeOptionElement.value.clientHeight > scrollContainerHeight.value;\n\n    if (optionOutOfView) {\n      activeOptionElement.value.scrollIntoView({\n        behavior: 'auto',\n        block: 'nearest',\n      });\n    }\n  }\n});\n\n/** STRING HIGHLIGHTING */\n/**\n * create an object out of prop `highlightStringTags` so it can be\n *  spread into the options of the `highlightText` function\n * @returns {ComputedRef<{highlightTags: []}|{}>}\n */\nconst highlightTags = computed(() => {\n  return props.highlightStringTags?.length\n    ? { highlightTags: props.highlightStringTags } : {};\n});\n\n/**\n * function to highlight characters of a string\n * @param {string} word - the option that should be matched with query string\n * @returns {string} - the string to fill into v-html\n */\nfunction highlight(word) {\n  return highlightText({\n    word,\n    queryString: props.highlightStringMatch,\n    // this is an empty object if prop `highlightStringTags` was not used\n    ...highlightTags,\n  });\n}\n\n/** NO OPTIONS SLOT */\nconst slots = useSlots();\n// determine if no-options slot has any template or text content\n// (simply using !!slots['no-options'] does not work anymore in Vue 3 since comments etc\n// are evaluating to true as well\nconst { slotHasContent } = useHasSlotContent(slots['no-options']);\n/**\n * determine if no options info element should be shown\n * @returns {ComputedRef<boolean>}\n */\nconst showNoOptions = computed(() => {\n  return !props.dropDownOptions.length && (slotHasContent.value || props.dropDownNoOptionsInfo);\n});\n</script>\n\n<template>\n  <div\n    ref=\"dropDownContainerEl\"\n    :class=\"['base-drop-down-list__container',\n             { 'base-drop-down-list__container-drop-down-style': displayAsDropDown }]\"\n    class=\"base-drop-down-list__container\">\n    <!-- @slot for adding elements before the options list -->\n    <slot name=\"before-list\" />\n    <ul\n      :id=\"listId\"\n      ref=\"dropDownListEl\"\n      :style=\"listBodyStyle\"\n      :aria-activedescendant=\"activeOption ? activeOption[identifierPropertyName] : undefined\"\n      role=\"listbox\"\n      class=\"base-drop-down-list\">\n      <template\n        v-for=\"(dropDownOption, optionIndex) in cleanedOptions\"\n        :key=\"dropDownOption[identifierPropertyName]\">\n        <li\n          :id=\"dropDownOption[identifierPropertyName]\"\n          ref=\"optionsEl\"\n          :value=\"dropDownOption[labelPropertyName]\"\n          :aria-selected=\"(selectStyled\n            && dropDownOption[identifierPropertyName] === selectedOption[identifierPropertyName])\n            || null\"\n          :class=\"[\n            'base-drop-down-list__option',\n            { 'base-drop-down-list__option__hover': activeStyled },\n            {\n              'base-drop-down-list__option__selected': selectStyled\n                && dropDownOption[identifierPropertyName] === selectedOption[identifierPropertyName],\n            },\n            {\n              'base-drop-down-list__option__active': activeStyled\n                && optionIndex === activeOptionIndex,\n            },\n            {\n              'base-drop-down-list__option__active-custom': useCustomOptionActiveBackgroundColor\n                && optionIndex === activeOptionIndex,\n            }]\"\n          role=\"option\"\n          tabindex=\"0\"\n          @keydown.enter=\"selected(dropDownOption)\"\n          @click.stop=\"selected(dropDownOption)\"\n          @touchstart.stop.passive=\"\">\n          <!-- @slot a slot to customize every single option (e.g. display of information other than `[valuePropertyName]`)\n            @binding {Object} option - the current option in the options list-->\n          <slot\n            name=\"option\"\n            :option=\"dropDownOption\">\n            <template v-if=\"useHighlightStringMatch\">\n              <!-- eslint-disable-next-line vue/no-v-html -->\n              <span v-html=\"highlight(dropDownOption[labelPropertyName])\" />\n            </template>\n            <template v-else>\n              {{ dropDownOption[labelPropertyName] }}\n            </template>\n          </slot>\n        </li>\n      </template>\n      <li\n        v-if=\"showNoOptions\"\n        :class=\"[\n          'base-drop-down-list__option',\n          'base-drop-down-list__no-options',\n        ]\">\n        <!--\n          @slot customize what is displayed when no drop down options are available\n        -->\n        <slot\n          v-if=\"!dropDownOptions.length\"\n          name=\"no-options\">\n          {{ dropDownNoOptionsInfo }}\n        </slot>\n      </li>\n    </ul>\n    <!-- @slot to add elements after the options list -->\n    <slot name=\"after-list\" />\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n@use \"@/styles/variables\" as *;\n\n.base-drop-down-list__container {\n  background: inherit;\n\n  &.base-drop-down-list__container-drop-down-style {\n    box-shadow: $drop-shadow;\n    z-index: map.get($zindex, dropdown);\n    max-height: 10 * $row-height-small;\n    overflow-y: auto;\n    position: absolute;\n  }\n\n  .base-drop-down-list {\n    position: relative;\n    overflow-y: auto;\n\n    .base-drop-down-list__option {\n      display: flex;\n      align-items: center;\n      min-height: $row-height-small;\n      padding: $spacing-small-half $spacing;\n      line-height: $line-height;\n      width: 100%;\n      transition: all 0.2s ease;\n      cursor: pointer;\n\n      &.base-drop-down-list__no-options {\n        cursor: default;\n        align-items: center;\n        padding: 0 $spacing;\n      }\n\n      &.base-drop-down-list__option__selected {\n        color: $app-color;\n      }\n\n      &.base-drop-down-list__option__hover:hover {\n        background-color: $button-header-color;\n      }\n\n      &.base-drop-down-list__option__active,\n      &.base-drop-down-list__option__active:hover {\n        background-color: $keyboard-active-color;\n      }\n\n      &.base-drop-down-list__option__active-custom {\n        background-color: var(--option-background);\n      }\n    }\n  }\n}\n</style>\n","<script>\nimport { computed, ref, toRef, useTemplateRef } from 'vue';\nimport { hasData, sort } from '@/utils/utils.js';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { useId } from '@/composables/useId.js';\nimport { useListNavigation } from '@/composables/useListNavigation.js';\nimport { useAnnouncer } from '@/composables/useAnnouncer.js';\nimport BaseSearch from '@/components/BaseSearch/BaseSearch.vue';\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport BaseButton from '@/components/BaseButton/BaseButton.vue';\nimport BaseChipsInputField from '@/components/BaseChipsInputField/BaseChipsInputField.vue';\nimport BaseChip from '@/components/BaseChip/BaseChip.vue';\nimport BaseDropDownList from '@/components/BaseDropDownList/BaseDropDownList.vue';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\nimport { useHorizontalDragScroll } from '@/composables/useHorizontalDragScroll.js';\n\nexport default {\n  name: 'BaseAdvancedSearchRow',\n  components: {\n    BaseButton,\n    BaseDropDownList,\n    BaseChip,\n    BaseChipsInputField,\n    BaseSearch,\n    BaseIcon,\n  },\n  props: {\n    /**\n     * provide an id for each search row\n     */\n    searchRowId: {\n      type: String,\n      default: '',\n    },\n    /**\n     *\n     */\n    mode: {\n      type: String,\n      default: 'list',\n      validator: val => ['list', 'form'].includes(val),\n    },\n    /**\n     * property to distinguish between one of multiple filter rows\n     * and the main search field (where new filters are added) that has\n     * a slightly different design and functionality\n     */\n    isMainSearch: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * list of available filters, needs to be an array of objects with the following properties:<br>\n     *   <br>\n     *    <b>label</b> {string} - the label of the filter (displayed\n     *      if not main search) - this prop can be customized by specifying\n     *      labelPropertyName.filter<br>\n     *    <b>id</b> {string} - the identifier of the filter (displayed\n     *      if not main search) - this prop can be customized by specifying\n     *      identifierPropertyName.filter<br>\n     *    <b>type</b> {('text'|'chips'|'chipssingle'|'date'|'daterange')} - the filter type<br>\n     *    <b>freetext_allowed</b> {boolean} - determines if predetermined options from 'options'\n     *      property are used or autocomplete is used\n     *    <b>options</b> {Object[]} - for filter type 'chips' and 'chipssingle' the controlled\n     *      vocabulary options\n     *    <b>subsets</b> {string[]} - if a filter of `type` 'text' or 'chips' with\n     *      `freetext_allowed` (thus triggering autocomplete) has subordinate filters for which\n     *      the autosuggest results should also be shown - add these filter ids here\n     */\n    filterList: {\n      type: Array,\n      default: () => ([]),\n      validator: val => !val.length\n        || (val.every(v => !!v.type && (!['chips', 'chipssingle'].includes(v.type)\n          || v.freetext_allowed || !!v.options))),\n    },\n    /**\n     * specify a default value for a filter that is set when none of the\n     * available filters is selected, should have the following properties:<br>\n     *   <br>\n     *    <b>label</b> {string} - the label of the filter (displayed\n     *      if not main search) - this prop can be customized by specifying\n     *      labelPropertyName.filter<br>\n     *    <b>id</b> {string} - the identifier of the filter (displayed\n     *      if not main search) - this prop can be customized by specifying\n     *      identifierPropertyName.filter<br>\n     *    <b>type</b> {('text'|'chips'|'chipssingle'|'date'|'daterange')} - the filter type<br>\n     *    <b>freetext_allowed</b> {boolean} - determines if predetermined options from 'options'\n     *      property are used or autocomplete is used\n     *    <b>options</b> {Object[]} - for filter type 'chips' and 'chipssingle' the controlled\n     *      vocabulary options<br>\n     *    <b>filter_values</b> {Object[]|string[]|Object} - the values selected - object for date\n     *      or array of objects or strings for type 'text', type 'chips' and 'chipssingle'\n     *\n     *    defaultFilter does not need the property subsets since results for all filters are\n     *    shown per default\n     */\n    defaultFilter: {\n      type: Object,\n      default: () => ({\n        id: 'default',\n        label: 'Fulltext',\n        type: 'text',\n        options: [],\n      }),\n      validator: val => !val.length\n        || (val.every(v => !!v.type && (!['chips', 'chipssingle'].includes(v.type)\n          || v.freetext_allowed || !!v.options))),\n    },\n    /**\n     * the filter currently applied, needs to be an object with the following properties:<br>\n     *   <br>\n     *    <b>label</b> {string} - the label of the filter (displayed\n     *      if not main search) - this prop can be customized by specifying\n     *      labelPropertyName.filter<br>\n     *    <b>id</b> {string} - the identifier of the filter (displayed\n     *      if not main search) - this prop can be customized by specifying\n     *      identifierPropertyName.filter<br>\n     *    <b>type</b> {('text'|'chips'|'chipssingle'|'date'|'daterange')} - the filter type<br>\n     *    <b>freetext_allowed</b> {boolean} - determines if predetermined options from 'options'\n     *      property are used or autocomplete is used\n     *    <b>filter_values</b> {Object[]|string[]|Object} - the values selected - object for date\n     *      or array of objects or strings for type 'text',  type 'chips' and 'chipssingle'\n     *    <b>subsets</b> {string[]} - if a filter of `type` 'text' or 'chips' with\n     *      `freetext_allowed` (thus triggering autocomplete) has subordinate filters for which\n     *      the autosuggest results should also be shown - add these filter ids here\n     */\n    appliedFilter: {\n      type: [Object, null],\n      default: null,\n      validator: val => val === null || !val.length || ['id', 'type', 'label'].every(prop => Object.keys(val).includes(prop)),\n    },\n    /**\n     * provide the component with the fetched autocomplete results\n     * (drop down options)<br>\n     * this needs to be an object array with the properties specified in\n     * `autocompletePropertyNames`\n     */\n    autocompleteResults: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * flag to set if loader should be shown (for autocomplete requests\n     */\n    isLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify a language (ISO 639-1) (used for label if label is language specific object\n     * e.g. { de: 'xxx', en: 'yyy' })\n     */\n    language: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify the object property that can be used for identification of filters,\n     * autocomplete options and controlled vocabulary options.<br>\n     *   Could be a string (used for all of the mentioned objects) or an object with the following\n     *   properties:<br>\n     *     <b>filter</b>: identifier property name in filter objects<br>\n     *     <b>autocompleteOption</b>: identifier property name in autocomplete option objects<br>\n     *     <b>controlledVocabularyOption</b>: identifier property name in controlled\n     *     vocabulary option objects<br>\n     */\n    identifierPropertyName: {\n      type: [Object, String],\n      default: () => ({\n        filter: 'id',\n        autocompleteOption: 'id',\n        controlledVocabularyOption: 'id',\n      }),\n    },\n    /**\n     * specify the object property that should be used for label display of filters,\n     * autocomplete options and controlled vocabulary options.<br>\n     *   Could be a string (used for all of the mentioned objects) or an object with the following\n     *   properties:<br>\n     *     <b>filter</b>: label property name in filter objects<br>\n     *     <b>autocompleteOption</b>: label property name in autocomplete option objects<br>\n     *     <b>controlledVocabularyOption</b>: label property name in controlled\n     *     vocabulary option objects<br>\n     */\n    labelPropertyName: {\n      type: [Object, String],\n      default: () => ({\n        filter: 'label',\n        autocompleteOption: 'title',\n        controlledVocabularyOption: 'label',\n      }),\n    },\n    /**\n     * autocomplete results need a label, an id and a data property that contains all the actual\n     * autocomplete results for that specific category\n     * TODO: make category optional\n     */\n    autocompletePropertyNames: {\n      type: Object,\n      default: () => ({\n        label: 'label',\n        id: 'id',\n        data: 'data',\n      }),\n      // check if all the necessary attributes are included in the provided object\n      validator: val => ['label', 'id', 'data'].every(key => Object.keys(val).includes(key)),\n    },\n    /**\n     * add a placeholder for the search input; either just a string or an object with\n     * different text for each search type (text, chips, date)\n     */\n    placeholder: {\n      type: [String, Object],\n      default: 'Search and discover',\n    },\n    /**\n     * specify informational texts for the component - this needs to be an object with the following\n     * properties (if you dont want to display any text leave an empty string):  <br>\n     *   <br>\n     *     <b>title</b>: text shown as first line on the drop down in filters area<br>\n     *     <b>subtext</b>: text shown as second line on the drop down in filters area<br>\n     *     <b>availableOptions</b>: text shown with chips options for controlled vocabulary\n     *     search<br>\n     *  <br>\n     *  The values of this object might be plain text or a key for an i18n file<br>\n     * This prop can be ignored when the 'no-options' slot is used.\n     */\n    advancedSearchText: {\n      type: Object,\n      default: () => ({\n        title: 'Advanced Search',\n        subtext: 'Select a filter',\n        availableOptions: 'Available options',\n      }),\n    },\n    /**\n     * specify informational texts for the drop down - this needs to be an object with the following\n     * properties (if you dont want to display any text leave an empty string:  <br>\n     *   <br>\n     *     <b>autocompleteNoOptions</b>: text shown when no autocomplete options are available<br>\n     *     <b>autocompleteOngoing</b>: text shown when an autocomplete search request is ongoing<br>\n     *     <b>autocompleteInitial</b>: initial text shown before user started typing<br>\n     *     <b>chipsNoOptions</b>: text shown when there are no options for controlled vocabulary\n     *        available<br>\n     *     <b>chipsMaxOptions</b>: text displayed if more than max number of options that can be\n     *        displayed are available (configure via prop maxNumberControlledOptions)<br>\n     *     <b>chipsNoMatch</b>: text displayed if string in input does not match any options<br>\n     *     <b>chipsOngoing</b>: text shown for chips fetching request ongoing<br>\n     *  <br>\n     *  The values of this object might be plain text or a key for an i18n file<br>\n     */\n    dropDownInfoTexts: {\n      type: Object,\n      default: () => ({\n        autocompleteNoOptions: 'No matching options found',\n        autocompleteOngoing: 'Autocomplete is being fetched...',\n        autocompleteInitial: 'Please start typing or select a filter to see options',\n        chipsNoOptions: 'No more options available',\n        chipsMaxOptions: 'Please start typing to see options',\n        chipsNoMatch: 'No matching options were found',\n        chipsOngoing: 'Options are being loaded...',\n      }),\n      // checking if all necessary properties are part of the provided object\n      validator: val => ['autocompleteNoOptions', 'autocompleteOngoing', 'autocompleteInitial',\n        'chipsNoOptions', 'chipsOngoing', 'chipsMaxOptions', 'chipsNoMatch']\n        .every(prop => Object.keys(val).includes(prop)),\n    },\n    /**\n     * define a maximum number of controlled vocabulary options to be displayed\n     */\n    maxNumberControlledOptions: {\n      type: Number,\n      default: 100,\n    },\n    /**\n     * this prop gives the option to add assistive text for screen readers<br>\n     * properties:<br>\n     * <b>addFilter</b>: text/label used for add filter icon<br>\n     * <b>removeFilter</b>: text/label used for remove filter icon<br>\n     * <b>selectFilterLabel</b>: label (not visible) used for filter chips input field<br>\n     * <b>searchLabel</b>: label (not visible) used for search input field<br>\n     * <b>selectedOption</b>: text read when a selected option is focused (currently only\n     *  working for type chips with autocomplete (=freetext_allowed))\n     * **optionAdded**: only for mode `list` - text read when an option was added to selected list\n     *    (if BaseSearch type is type `chips`)\n     * **optionToRemoveSelected**: only for mode `list` - text read when a selected option is in\n     *    focus to be removed (if BaseSearch type is type `chips`)\n     * **optionRemoved**: only for mode `list` - text read when an option was removed\n     *    from selected list (if BaseSearch type is type `chips`)\n     * **loaderActive**: text that is announced when results are being fetched (prop\n     *  `isLoading` is set `true`)\n     * **autocompleteResultsRetrieved**: text announced when autocomplete results are returned.\n     *  use {optionsNumber} and {collectionsNumber} in the string to announce the number of\n     *  total options and collections found respectively.\n     * **autocompleteNoResults**: Text announced when no results were found with a given\n     *  search string.\n     * **autocompleteInitial**: Text announced when no search string was provided for\n     *  autocomplete.\n     * **categoryAnnouncement**: Text announced when a new category is entered in the\n     *  autocomplete drop down options list with keyboard navigation. string '{label}' will\n     *  be replaced by the actual specified category label\n     * **optionsAnnouncement**: announced together with category when in category selection\n     *  mode (after using arrowLeft key on autocomplete input) - to give the user a feeling\n     *  how many options were found for the announced category. string '{number}' will be\n     *  replaced by the number of entries in that category.\n     * **results**: provide text that should be announced when the search has\n     *  yielded results (or not).\n     *\n     * Caveat: `results` has a watcher attached to trigger the\n     *    announcement so make sure the property values are reset after filling them\n     *    by using update:assistive-text or resetting it manually (after a timeout)\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        addFilter: 'Add filter',\n        removeFilter: 'Remove filter',\n        selectFilterLabel: 'Select filter',\n        searchLabel: 'Search for Entries',\n        selectedOption: '',\n        optionAdded: 'option {label} added to selected list.',\n        optionToRemoveSelected: 'option {label} from selected list marked for removal. Press delete or backspace to remove.',\n        optionRemoved: 'option {label} removed.',\n        loaderActive: 'loading.',\n        autocompleteResultsRetrieved: '{optionsNumber} options found in {collectionsNumber} categories.',\n        autocompleteNoResults: 'No results found.',\n        autocompleteInitial: 'Please start typing to see suggestions.',\n        categoryAnnouncement: 'category {label}.',\n        optionsAnnouncement: '{number} options.',\n        results: '',\n      }),\n    },\n    /**\n     * if desired the box shadow around the search rows can be deactivated here\n     */\n    applyBoxShadow: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * use this prop to set a delay in ms before date input calender is displayed\n     */\n    dateFieldDelay: {\n      type: Number,\n      default: 0,\n    },\n    /**\n     * set this flag to `true` to highlight autocomplete option characters that match\n     *  the current search input string\n     */\n    highlightAutocompleteMatch: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `highlightAutocompleteMatch` is set `true`\n     *  provide tag names to style the matched characters\n     *  (without '<' and '>', e.g. ['b'] for <b>)\n     */\n    highlightAutocompleteTags: {\n      type: Array,\n      default: () => ([]),\n    },\n  },\n  emits: ['update:applied-filter', 'fetch-autocomplete-results', 'is-active', 'option-selected', 'remove-filter', 'add-filter-row'],\n  setup(props) {\n    /** GENERAL */\n    /**\n     * set up a reference to the root element (e.g. for announcer element)\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const advancedSearchRow = useTemplateRef('advancedSearchRow');\n    /**\n     * reference to the search element, needed for resizing actions\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const baseSearch = useTemplateRef('baseSearch');\n\n    /** FILTER DATA */\n    /**\n     * the currently selected filter\n     * @type {Filter}\n     */\n    const filter = ref({\n      ...props.defaultFilter,\n      filter_values: props.defaultFilter.values || setFilterValues(props.defaultFilter),\n    });\n\n    /**\n     * function to set the correct values for filter.filter_values attribute\n     *\n     * @param {Filter} newFilter - the newly selected filter\n     * @param {Filter} previousFilter - the previously set filter\n\n     * @returns {?string|Array|Object} the correct value type for the filter type\n     */\n    function setFilterValues(newFilter, previousFilter = {}) {\n      const previousFilterValues = previousFilter.filter_values;\n      const { type } = newFilter;\n      const freetextAllowed = newFilter.freetext_allowed;\n      if (type === 'date') {\n        // map the date from daterange to date if necessary\n        return previousFilter?.type?.includes('date')\n        && previousFilterValues ? previousFilterValues.date_from || previousFilterValues.date_to : '';\n      }\n      if (type === 'daterange') {\n        // check if it can be mapped from date to daterange\n        if (previousFilter.type?.includes('date')) {\n          return {\n            date_from: previousFilterValues ? previousFilterValues.date_from || previousFilterValues || '' : '',\n            date_to: previousFilterValues?.to ? previousFilterValues.to : '',\n          };\n        }\n        // else just return empty object\n        return {\n          date_from: '',\n          date_to: '',\n        };\n      }\n      // check if both are autocomplete chips filters\n      if (type === 'chips' && freetextAllowed && previousFilter.type === 'chips' && previousFilter.freetext_allowed) {\n        // check if new filter is a superset filter of the previous filter (=previous\n        // filter id is included in current filter 'subsets' property\n        if (newFilter.subsets?.includes(previousFilter[props.identifierPropertyName.filter])) {\n          return previousFilterValues;\n        }\n        // if both are chips with freetext keep options without id (=not specific entries)\n        return previousFilterValues?.length ? previousFilterValues\n          .filter(value => !value[props.identifierPropertyName.autocompleteOption]) : [];\n      }\n      // check if previous filter was text and new filter is autocomplete chips\n      if (previousFilter.type === 'text' && previousFilterValues?.length\n        && !!previousFilterValues[0] && type === 'chips' && freetextAllowed) {\n        return [{\n          [this.labelPropertyName.autocompleteOption]: previousFilterValues[0],\n        }];\n      }\n      return [];\n    }\n\n    /** INTERNAL ID */\n    const internalId = useId();\n    /**\n     * create a row id either taken from externally specified id or\n     * from internally created id\n     */\n    const internalRowId = computed(() => props.searchRowId || internalId);\n\n    /** LOCALIZATION */\n    const { getLangLabel, getI18nTerm } = useI18n(toRef(props, 'language'));\n\n\n    /** DROP DOWN NAVIGATION */\n    const { navigate, isWithinArrayLimit } = useListNavigation();\n\n    /** COMPONENT RESIZING */\n    /**\n     * depending on element size a different slot of BaseInput is used and needs\n     * to be passed on to v-slot directive of template element\n     * @type {Ref<UnwrapRef<string>, UnwrapRef<string> | string>}\n     */\n    const filterSlotName = ref('pre-input-field');\n\n    /**\n     * Resize Observer to trigger actions (e.g. drop down columns calculations) when\n     * component is resized\n     */\n    useElementObserver({\n      type: 'resize',\n      target: advancedSearchRow,\n      callback: resizeActions,\n    });\n    /**\n     * calculate the number of columns for filters and chips dynamically and\n     * use correct slot for selected filter depending on element size\n     */\n    function resizeActions() {\n      // get the actual search HTML element by reference\n      const searchElement = baseSearch.value?.search;\n      // check if it was found\n      if (searchElement) {\n        // SET COLUMN STYLE\n        // get the width of the element\n        const searchElementWidth = searchElement.clientWidth;\n        // set a css variable that is responsible for the number of items\n        // (subtract 1/4 of elementWidth because of first column): 180px is assumed for each column\n        advancedSearchRow.value.style.setProperty(\n          '--col-number',\n          Math.floor((searchElementWidth - searchElementWidth / 4) / 180) || 1,\n        );\n      }\n      // check if it was found\n      if (advancedSearchRow.value) {\n        // SET CORRECT SLOT FOR SELECTED FILTER DISPLAY\n        // get the width of the element\n        const searchRowElementWidth = advancedSearchRow.value.clientWidth;\n        // need to set time out and put this assignment at the end of all observer callback executions\n        // so it is not interfering with the still unfinished observer callback (making changes to DOM\n        // while observer callback is still ongoing, causing a loop)\n        setTimeout(() => {\n          filterSlotName.value = searchRowElementWidth >= 500 ? 'pre-input-field' : 'input-field-addition-before';\n        }, 0);\n      }\n    }\n\n    /** FOCUS HANDLING */\n    /**\n     * get the native HTML input element which is stored in BaseSearch `inputElement`\n     * variable to enable manual focusing\n     * @type {ComputedRef<HTMLElement|null>}\n     */\n    const searchInputElement = computed(() => baseSearch.value?.inputElement || null);\n    /**\n     * to control if search field is active (and drop down shown)\n     * @type {Ref<UnwrapRef<boolean>>}\n     */\n    const isActive = ref(false);\n    /**\n     * store the current filter type to recognize when it changes and only take\n     * action e.g. on focusing input field, after it was rendered\n     * @type {Ref<UnwrapRef<string>>}\n     */\n    const currentFilterType = ref(props.appliedFilter ? props.appliedFilter.type : props.defaultFilter.type);\n\n    /**\n     * Mutation observer for handling the focusing of input field after changes\n     */\n    useElementObserver({\n      type: 'mutation',\n      target: advancedSearchRow,\n      callback: filterChangeObserverAction,\n      options: {\n        subtree: true,\n        childList: true,\n      },\n    });\n\n    function filterChangeObserverAction() {\n      if (filter.value.type !== currentFilterType.value && isActive.value) {\n        if (searchInputElement.value) {\n          searchInputElement.value.focus();\n          currentFilterType.value = filter.value?.type || props.defaultFilter.type;\n        }\n      }\n    }\n\n    /**\n     * if tab key was used we want to check if drop down should be closed\n     * @param event\n     */\n    function handleDropDownOnTabKey(event) {\n      // get all input elements\n      const inputElements = advancedSearchRow.value.getElementsByTagName('input');\n      // create an array out of input elements found\n      const searchInputArray = Array.from(inputElements)\n        // and filter only for elements that are connected to search (necessary for mode\n        // 'form' which has additional input fields)\n        .filter(element => element.id.includes('search'));\n      // check if some were found\n      if (inputElements) {\n        // get the index of the element the event came from\n        const eventInputIndex = searchInputArray.indexOf(event.target);\n        // check if element is either the last input element and no shift key was used or\n        // it is the first element and shift key was used --> if true --> close drop down\n        if ((!event.shiftKey && eventInputIndex >= searchInputArray.length - 1)\n          || (event.shiftKey && eventInputIndex <= 0)) {\n          isActive.value = false;\n        }\n      }\n    }\n\n    /** FILTER ROW FADE OUT */\n    /**\n     * template reference to the element containing the filter list\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const filterBox = useTemplateRef('filterBoxElement');\n\n    const { boxFadeOut: filterFade } = useHorizontalDragScroll(filterBox, {});\n\n    /** ACCESSIBILITY */\n    /**\n     * insert an HTML element with aria-live assertive that will announce the\n     * search result\n     * @type {Ref<UnwrapRef<string>>}\n     */\n    const { announcement } = useAnnouncer(advancedSearchRow);\n\n    return {\n      // ref elements\n      advancedSearchRow,\n      baseSearch,\n      // filter data\n      filter,\n      setFilterValues,\n      // internal id\n      internalRowId,\n      // drop down navigation\n      navigate,\n      isWithinArrayLimit,\n      // internationalization\n      getLangLabel,\n      getI18nTerm,\n      // resize handling\n      filterSlotName,\n      // focus handling\n      searchInputElement,\n      isActive,\n      handleDropDownOnTabKey,\n      // fadeout\n      filterFade,\n      filterBox,\n      // accessibility\n      announcement,\n    };\n  },\n  data() {\n    return {\n      /**\n       * variable containing search text\n       * @type {?string|?Object}\n       */\n      currentInput: '',\n      /**\n       * the currently active (selected by key navigation) filter\n       * @type {?Filter}\n       */\n      activeFilter: null,\n      /**\n       * for autocomplete drop down navigation - collection level\n       * @type {?string}\n       */\n      activeCollectionId: '',\n      /**\n       * switch between arrow use on collection or entry level\n       * (true for collection level)\n       * @type {boolean}\n       */\n      collectionSelect: false,\n      /**\n       * the currently active controlled vocabulary entry\n       * @type {?Object|?string}\n       */\n      activeControlledVocabularyEntry: null,\n      /**\n       * for autocomplete drop down navigation - single autocomplete option level\n       * @type {?Object}\n       */\n      activeEntry: null,\n      /**\n       * variable for touch devices to stop the click event from opening the drop down\n       *  when click event was coming from elements within the search (e.g. BaseForm)\n       */\n      stopSearchClick: false,\n    };\n  },\n  computed: {\n    /**\n     * v-model of BaseChipsInputField provides an array of selected options - do\n     * conversion to object and array respectively with this computed variable\n     * (this is triggered when deleting the selected filter)\n     */\n    selectedFilter: {\n      /**\n       * triggered on deleting a filter via chip 'x'\n       * @param {Filter[]} val\n       */\n      set(val) {\n        const newFilter = val.length ? val.pop() : this.defaultFilter;\n        // check if filter was selected - else use the default filter\n        this.filter = {\n          ...newFilter,\n          filter_values: this.setFilterValues(newFilter, this.filter),\n        };\n      },\n      get() {\n        // return current filter object as array\n        return [this.filter];\n      },\n    },\n    /**\n     * for main filter do not display the default filter in the drop down list with\n     *  available filters (mode 'list')\n     * @returns {Filter[]}\n     */\n    displayFilterList() {\n      if (!this.isMainSearch) return this.filterList;\n      return this.filterList.filter(filter => filter[this.identifierPropertyName.filter]\n        !== this.defaultFilter[[this.identifierPropertyName.filter]]);\n    },\n    /**\n     * variable to return if autocomplete functionality should be shown (= results fetched\n     * and displayed in drop down, how input is handled, etc.)\n     * this evaluates to true if type is text or chips with freetext allowed\n     * @returns {boolean}\n     */\n    useAutocompleteFunctionality() {\n      const { type } = this.filter;\n      return type === 'text' || (type === 'chips' && this.filter.freetext_allowed);\n    },\n    /**\n     * depending on the filter type get selectedOptions for BaseSearch from filter values\n     */\n    selectedOptions: {\n      /**\n       * this is used when a chip is deleted\n       * @param {Object[]|string[]} val - the new selected options to be set as filter_values in the\n       *  current filter\n       */\n      set(val) {\n        this.filter.filter_values = [...val];\n      },\n      get() {\n        /**\n         * this variable should only contain values for chips\n         * not for date, daterange or text\n         * @returns {Object[]|string[]}\n         */\n        if (this.filter.type.includes('chips')) {\n          return this.filter && this.filter.filter_values ? [...this.filter.filter_values] : [];\n        }\n        return [];\n      },\n    },\n    /**\n     * in case the filter is a controlled vocabulary filter get the options\n     * from the corresponding filter in the filter list\n     * @returns {Object[]}\n     */\n    controlledVocabularyOptions() {\n      // check first if filter is type controlled vocabulary\n      if (this.filter.type === 'chips' && !this.filter.freetext_allowed) {\n        // if yes - get the filter from filterList that has all the options\n        const currentFilter = this.filterList\n          .find(filter => filter[this.identifierPropertyName.filter]\n            === this.filter[this.identifierPropertyName.filter]);\n        // if one was found return the options\n        return currentFilter ? currentFilter.options : [];\n      }\n      return [];\n    },\n    /**\n     * the actually displayed controlled vocabulary options\n     * (filtered for already selected and for the current input string)\n     *\n     * @returns Object[]\n     */\n    displayedOptions() {\n      if (this.controlledVocabularyOptions) {\n        let options = [].concat(this.controlledVocabularyOptions);\n        // remove already selected options if there are any\n        if (this.filter.filter_values && this.filter.filter_values.length) {\n          options = options.filter(option => !this.filter.filter_values\n            .map(value => value[this.identifierPropertyName.controlledVocabularyOption])\n            .includes(option[this.identifierPropertyName.controlledVocabularyOption]));\n        }\n        // only display options matching the current input string\n        if (this.currentInput) {\n          options = options.filter(filter => filter[this.labelPropertyName.filter]\n            .toLowerCase().includes(this.currentInput.toLowerCase()));\n        }\n        return sort(\n          options,\n          this.labelPropertyName.controlledVocabularyOption,\n          false,\n          this.getLangLabel,\n        );\n      }\n      return [];\n    },\n    /**\n     * filtered autocomplete list, e.g. removing collections with no results\n     * and options that were already selected\n     * @type {Object[]} resultListInt\n     * @returns {Object[]}\n     */\n    resultListInt() {\n      if (this.useAutocompleteFunctionality) {\n        let resultsToDisplay = this.autocompleteResults;\n        // if a filter is not default filter then only show autocomplete results that\n        // have same category as selected text filter\n        if (this.filter[this.identifierPropertyName.filter]\n          !== this.defaultFilter[this.identifierPropertyName.filter]) {\n          // filter for identical autocomplete section id OR if a filter has the\n          // prop `subsets` specified also filter for the ids specified in that array\n          resultsToDisplay = resultsToDisplay\n            .filter(section => section[this.autocompletePropertyNames.id]\n              === this.filter[this.identifierPropertyName.filter]\n              || (this.filter.subsets && this.filter.subsets.length\n                && this.filter.subsets.includes(section[this.autocompletePropertyNames.id])));\n        }\n        // filter empty collections\n        resultsToDisplay = resultsToDisplay\n          .filter(section => section[this.autocompletePropertyNames.data]\n            && section[this.autocompletePropertyNames.data].length);\n        // filter options already selected previously\n        if (this.selectedOptions && this.selectedOptions.length) {\n          const selectedOptionIds = this.selectedOptions\n            .map(option => option[this.identifierPropertyName.autocompleteOption]);\n          return resultsToDisplay.map(section => ({\n            data: section[this.autocompletePropertyNames.data].filter(entry => !selectedOptionIds\n              .includes(entry[this.identifierPropertyName.autocompleteOption])),\n            [this.autocompletePropertyNames.id]:\n              section[this.autocompletePropertyNames.id],\n            [this.autocompletePropertyNames.label]:\n              section[this.autocompletePropertyNames.label],\n          }));\n        }\n        return resultsToDisplay;\n      }\n      return [];\n    },\n    /**\n     * list of autocomplete results used for determining currently active\n     * collection // activity\n     * @type {Object} consolidatedResultList\n     * @returns {Object}\n     */\n    consolidatedResultList() {\n      return this.resultListInt.reduce((prev, curr) => ({\n        ...prev,\n        [curr[this.autocompletePropertyNames.id]]: curr[this.autocompletePropertyNames.data],\n      }), {});\n    },\n    /**\n     * function to determine if filter has filter values\n     */\n    filterHasValues() {\n      // check if filter is not default filter\n      return this.filter[this.identifierPropertyName.filter]\n        !== this.defaultFilter[this.identifierPropertyName.filter]\n        // or has filter values\n        || hasData(this.filter.filter_values);\n    },\n    /**\n     * map filter type\n     */\n    searchType() {\n      if (this.filter) {\n        const { type } = this.filter;\n        // chips input filters that don't allow freetext need to have the type 'controlled'\n        // in BaseSearchComponent\n        if (type === 'chips' && !this.filter.freetext_allowed) {\n          return 'controlled';\n        }\n        return type;\n      }\n      return 'text';\n    },\n  },\n  watch: {\n    /**\n     * watch internal filter object for changes\n     */\n    filter: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.appliedFilter)) {\n          /**\n           * event emitted when the applied filter changes\n           * @event update:applied-filter\n           * @property {Filter} val - the new currently applied filter\n           */\n          this.$emit('update:applied-filter', JSON.parse(JSON.stringify(val)));\n        }\n      },\n      deep: true,\n    },\n    /**\n     * watch if applied filter changes from outside\n     */\n    appliedFilter: {\n      /**\n       * @param {Filter} val - the currently applied filter as set from outside\n       */\n      handler(val) {\n        // check if anything actually changed\n        if (JSON.stringify(val) !== JSON.stringify(this.filter)) {\n          let newFilter = JSON.parse(JSON.stringify(val || this.defaultFilter));\n          newFilter = {\n            ...newFilter,\n            // if filter is changed from outside this often means resetting a filter so previous\n            // values should not be taken over (=leave second argument of function empty here)\n            filter_values: newFilter.filter_values || this.setFilterValues(newFilter),\n          };\n          this.filter = newFilter;\n          // check if the new filter has values\n          if (newFilter && newFilter.filter_values) {\n            // distinguish between date and others to assign to correct variable\n            if (newFilter.type.includes('date')) {\n              this.currentInput = newFilter.filter_values;\n            } else if (newFilter.type === 'text') {\n              this.currentInput = newFilter.filter_values[0] || '';\n            } else {\n              this.currentInput = '';\n            }\n          } else {\n            this.currentInput = '';\n          }\n        }\n      },\n      immediate: true,\n      deep: true,\n    },\n    /**\n     * when current input changes emit this to parent component which should\n     * do the fetching of autocomplete results (if filter type 'text') or assign\n     * the values to filter.filter_values if type is 'date' or 'daterange'\n     * @param {string} val - the search string\n     */\n    currentInput: {\n      handler(val) {\n        // if filter type is text - just emit for fetching autocomplete results\n        if (this.useAutocompleteFunctionality) {\n          /**\n           * event emitted when input string for text or chips filter changes\n           *\n           * @event fetch-autocomplete-results\n           * @property {string} input - the input string\n           * @property {Filter} filter - the filter currently applied\n           */\n          this.$emit('fetch-autocomplete-results', { input: val, filter: this.filter });\n        }\n      },\n      immediate: true,\n    },\n    /**\n     * if 'isActive' is set true reset the filterFade (for mobile filter view) to\n     * default values\n     */\n    isActive(val) {\n      if (val) {\n        // if drop down was opened and there is no currently active entry (if there is, the options\n        // are announced anyway) we announce the dropdown content\n        if (!this.activeEntry) {\n          // timeout and secondary isActive check is needed because on click in the form the isActive value\n          // also changes to true for a second before it switches back to false\n          setTimeout(() => {\n            if (this.isActive) {\n              this.assembleAutocompleteResultsAnnouncement();\n            }\n          }, 300);\n        }\n      }\n      // if isActive becomes false and the drop down closes check for remaining input strings\n      // if the filter is chips\n      if (!val && this.filter.type === 'chips' && !!this.currentInput && this.currentInput.trim()) {\n        // check if the string can actually be added (freetext options allowed) and that the option\n        // was not added previously\n        if (this.filter.freetext_allowed && (!this.selectedOptions || !this.selectedOptions\n          .some(option => (!option[this.identifierPropertyName.autocompleteOption]\n            && option[this.labelPropertyName.autocompleteOption] === this.currentInput)))) {\n          // if this holds true - add the option\n          this.addOption({ [this.labelPropertyName.autocompleteOption]: this.currentInput });\n        } else {\n          // else reset all input\n          this.resetAllInput();\n        }\n        // if filter type is text and the value was not added in that form yet also add it\n        // (which will trigger search)\n      } else if (!val && this.filter.type === 'text'\n        && this.filter.filter_values.join() !== this.currentInput) {\n        this.addOption(this.currentInput);\n      }\n      /**\n       * event emitted when input field becomes active / inactive\n       * @event is-active\n       * @type {boolean}\n       */\n      this.$emit('is-active', val);\n    },\n    /**\n     * reset the currently active drop down autocomplete option when the list changes\n     */\n    autocompleteResults() {\n      // reset the active entry / collection set with the previous results\n      this.activeEntry = null;\n      this.activeCollectionId = '';\n      // on results change announce what was found, but only if the dropdown is active\n      if (this.isActive) {\n        this.assembleAutocompleteResultsAnnouncement();\n      }\n    },\n    /**\n     * reset the currently active controlled vocabulary option when the list changes\n     */\n    displayedOptions() {\n      // reset currently active vc entry if list changed\n      this.activeControlledVocabularyEntry = null;\n    },\n  },\n  methods: {\n    /** FILTER ROW RELATED FUNCTIONALITIES */\n\n    // inform parent of click on plus or remove respectively\n    addFilterRow() {\n      /**\n       * event emitted when user took action to add filter\n       *\n       * @event add-filter-row\n       * @property {Filter} filter - the filter object in question\n       * @property {string} input - the current input\n       */\n      this.$emit('add-filter-row', { filter: this.filter, input: this.currentInput });\n    },\n    removeFilter() {\n      if (this.isMainSearch) {\n        this.filter = {\n          ...this.defaultFilter,\n          filter_values: this.setFilterValues(this.defaultFilter),\n        };\n        this.resetAllInput();\n        this.isActive = false;\n      } else {\n        /**\n         * event emitted when user triggered remove icon on filter row\n         *\n         * @event remove-filter\n         * @property {Filter} filter - the filter to be removed\n         */\n        this.$emit('remove-filter', this.filter);\n      }\n    },\n\n    /** FILTER RELATED FUNCTIONALITIES */\n\n    /**\n     * set the via click or navigation selected filter as currently\n     * active filter\n     *\n     * @param {Filter} selectedFilter - the selected filter object\n     * @property {string} selectedFilter.type - the type of the filter needed\n     * to set the default filter values accordingly (array, string, object)\n     */\n    selectFilter(selectedFilter) {\n      // check if filter actually changed\n      if (selectedFilter && this.filter[this.identifierPropertyName.filter]\n        !== selectedFilter[this.identifierPropertyName.filter]) {\n        // store the previous filter in a variable\n        const previousFilter = this.filter;\n        // store previous input value in a variable (to keep it if new filter type is\n        // compatible\n        const previousInput = this.currentInput;\n        // set newly selected filter as current filter\n        this.filter = {\n          ...selectedFilter,\n          // set filter values separately to be able to keep some values\n          filter_values: this.setFilterValues(selectedFilter, previousFilter),\n        };\n        // reset all input variables\n        this.resetAllInput();\n        this.activeFilter = null;\n        // now restore the input value if it makes sense (=filter type is autocomplete filter and\n        // type stays the same or switches to other autocomplete type (chips, text))\n        if (['text', 'chips'].includes(selectedFilter.type)\n          && ['text', 'chips'].includes(previousFilter.type)\n          && !(previousFilter.type === 'text' && previousFilter.filter_values[0] === previousInput)) {\n          // restore the input value\n          this.currentInput = previousInput;\n          // now - if there is an input value and there are no autocomplete results available for\n          // the category of the new filter - trigger the autocomplete fetch again\n          if ((selectedFilter.type === 'text' || (selectedFilter.type === 'chips' && selectedFilter.freetext_allowed))\n            && this.currentInput && !this.autocompleteResults\n              .some(category => category.filter_id === selectedFilter.id)) {\n            this.$emit('fetch-autocomplete-results', { input: this.currentInput, filter: this.filter });\n          }\n        }\n        // if filter type date sync current input\n        if (this.filter.type.includes('date')) {\n          this.currentInput = this.filter.filter_values;\n        }\n        if (this.filter.type === 'chipssingle') {\n          this.addOption(this.filter.options[0]);\n        }\n      }\n      if (this.searchInputElement) {\n        // in either case - focus on input field again after click on filter\n        this.searchInputElement.focus();\n      }\n    },\n    /**\n     * @param {KeyboardEvent} event - keyboard event bubbled from\n     * filter input field\n     */\n    navigateFilters(event) {\n      if (this.filterList.length && this.isActive && this.$refs.dropDown) {\n        const currentIndex = this.filterList.indexOf(this.activeFilter);\n        // determine if arrow was up or down - true if down, false for up\n        const isArrowDown = event.key === 'ArrowDown';\n        this.activeFilter = this.navigate(this.filterList, isArrowDown, currentIndex, true);\n      }\n    },\n\n    /** CONTROLLED VOCABULARY AND AUTOCOMPLETE SELECT RELATED METHODS */\n\n    /**\n     * function to add any entry to the BaseSearch selectedChips list (since basically all\n     * base search input is handled as chips)\n     *\n     * @param {Object} entry - the entry to add to the selected list\n     * @param {string} collectionId - to set filter after adding from autocomplete a collection id\n     *  is needed when option was selected by click\n     */\n    addOption(entry, collectionId = '') {\n      // get the result category of the selected option (on key navigation this.activeCollectionId\n      // should be set, if selected from drop down by click the collectionId is passed to the\n      // function else the default filter category is assumed\n      const selectedOptionCollection = collectionId\n        || this.defaultFilter[this.identifierPropertyName.filter];\n      // check if filters were specified - if not assume the input is handled in parent component\n      if (!this.filterList || !this.filterList.length) {\n        this.$emit('option-selected', ({ entry, collectionId: selectedOptionCollection }));\n        // check if filter is not default filter\n        if (selectedOptionCollection !== this.defaultFilter[this.identifierPropertyName.filter]) {\n          // only then reset all input\n          this.resetAllInput();\n        }\n        // if option is coming from autocomplete drop down list (=has an id)\n        // and currently active filter is not identical\n        // with the category of the selected item (if everything is going right this should\n        // be 'default') then set the category of the selected item as current filter\n      } else if (this.useAutocompleteFunctionality\n        && entry[this.identifierPropertyName.autocompleteOption]\n        // and currently active filter is not identical\n        // with the category of the selected item\n        && this.filter[this.identifierPropertyName.filter]\n        !== selectedOptionCollection\n        // and selected item is not from a subset (so\n        // if everything goes right category should be 'default')\n        && !(this.filter.subsets && this.filter.subsets.length\n          && this.filter.subsets.includes(selectedOptionCollection))) {\n        // then set the category of the selected item as current filter\n        const newFilter = this.filterList.find(filter => filter[this.identifierPropertyName.filter]\n          // the filterList SHOULD have the filter included that is displayed as autocomplete option\n          // category but if everything fails - use default filter again\n          === (this.activeCollectionId || collectionId)) || this.defaultFilter;\n        // since default filter could be other than chips at least safeguard against type 'text'\n        // TODO: this assumes default filter type is 'text'! needs further handling if other filter\n        // types could be default\n        const newValue = newFilter[this.identifierPropertyName.filter]\n        === this.defaultFilter[this.identifierPropertyName.filter]\n          ? [].concat(entry[this.labelPropertyName.autocompleteOption]) : [].concat(entry);\n        const oldFilterValues = this.filter.filter_values && this.filter.filter_values.length === 1\n        && typeof this.filter.filter_values[0] === 'string' ? [{\n          [this.labelPropertyName.autocompleteOption]: this.filter.filter_values[0],\n        }] : [];\n        this.filter = {\n          ...newFilter,\n          // check for filter_values property which does not exist in the filterList filters\n          filter_values: oldFilterValues.concat(newValue),\n        };\n      } else {\n        this.selectedOptions = this.filter.filter_values.concat(entry);\n      }\n      // if filter type is text only use string for search on enter so dont remove the input\n      // new addition: also controlled vocabulary input should stay as long as options available\n      if (this.filter.type !== 'text' && (this.filter.type !== 'chips' || this.filter.freetext_allowed\n        || !this.displayedOptions.length)) {\n        // reset everything\n        this.resetAllInput();\n      } else {\n        // else just empty the previously selected controlled vocabulary entry\n        this.activeControlledVocabularyEntry = null;\n      }\n\n      // if filter row is not controlled vocabulary close the filter to be able to see search\n      // results\n      if (this.filter.type !== 'chips' || this.filter.freetext_allowed) {\n        this.isActive = false;\n      }\n    },\n    /**\n     * function triggered on BaseSearch keyboard enter. Will add the currently active option or\n     * controlled vocabulary option respectively. Or if no option is active the current input text.\n     * If there is no active option and no input text then the keyboard enter will be interpreted\n     * as a signal to add the filter to a filter array (parent is informed)\n     */\n    selectOptionOnKeyEnter() {\n      // else check if filter type is chips and there is an active entry in the options list\n      if (this.filter.type === 'chips' && this.activeControlledVocabularyEntry) {\n        this.addOption(this.activeControlledVocabularyEntry);\n        // if an active entry is present (=selected by key navigation) add the entry\n      } else if (this.useAutocompleteFunctionality && this.activeEntry) {\n        this.addOption(this.activeEntry, this.activeCollectionId);\n        // check if filter type is text\n      } else if (this.filter.type === 'text') {\n        const newTextArray = [].concat(this.currentInput);\n        if (JSON.stringify(this.filter.filter_values) !== JSON.stringify(newTextArray)) {\n          this.filter.filter_values = newTextArray;\n          this.isActive = false;\n        } else {\n          this.isActive = !this.isActive;\n        }\n        // if there is no active entry check if there is input in the search field and\n        // add the text input as chip if available, however check if text was already added\n        // to avoid duplicates\n      } else if (this.filter.type === 'chips' && this.filter.freetext_allowed\n        && this.currentInput && this.currentInput.trim()\n        && (!this.selectedOptions || !this.selectedOptions\n          .some(option => (!option[this.identifierPropertyName.autocompleteOption]\n            && option[this.labelPropertyName.autocompleteOption] === this.currentInput)))) {\n        this.addOption({\n          [this.labelPropertyName.autocompleteOption]: this.currentInput,\n        });\n        // if this is main search and there is no current input and filter values are present\n        // inform parent that filter can be processed\n      } else if (!this.currentInput) {\n        this.isActive = !this.isActive;\n      }\n    },\n    /**\n     * @param {KeyboardEvent} event - the event triggered by keydown\n     */\n    handleKeyDownEvent(event) {\n      const { key } = event;\n      if (!['Tab', 'Enter', ' ', 'Shift'].includes(key)) {\n        this.isActive = true;\n      } else if (key === ' ' && !this.currentInput) {\n        this.isActive = !this.isActive;\n        event.preventDefault();\n      }\n    },\n    /**\n     * create an announcement to inform about the information shown in the autocomplete\n     * dropdown\n     */\n    assembleAutocompleteResultsAnnouncement() {\n      // check if there are results to display and if the needed assistive text was defined in\n      // the prop\n      if (this.resultListInt.length && this.assistiveText.autocompleteResultsRetrieved) {\n        // calculate the complete number of results provided\n        const resultsNumber = this.resultListInt.reduce((prev, curr) => prev + curr.data.length, 0);\n        // set the announcement text with the appropriate number of collections and total results\n        // displayed\n        this.announcement = this.assistiveText.autocompleteResultsRetrieved\n          .replace('{optionsNumber}', resultsNumber.toString())\n          .replace('{collectionsNumber}', this.resultListInt.length.toString());\n        // else handle an empty drop down list if\n        // a) no results were found or\n      } else if (!this.resultListInt.length && this.currentInput\n        && this.assistiveText.autocompleteNoResults) {\n        this.announcement = this.assistiveText.autocompleteNoResults;\n        // b) no search input string is given\n      } else if (!this.resultListInt.length && !this.currentInput\n        && this.assistiveText.autocompleteInitial) {\n        this.announcement = this.assistiveText.autocompleteInitial;\n      }\n    },\n\n    /** DROP DOWN NAVIGATION */\n\n    /**\n     * event triggered on row click to open drop down and focus main input\n     */\n    openDropDown() {\n      // set focus to input field when drop down opens only if\n      // a) drop down is not already open (e.g. otherwise this would always cause the first input field of a date\n      //    range to get focused on element click\n      // b) mode is 'list'\n      // c) search input element exists\n      if (!this.isActive && this.mode === 'list' && this.searchInputElement) {\n        this.searchInputElement.focus();\n      }\n      this.isActive = true;\n    },\n    /**\n     * primary drop down navigation deciding what arrow keys are used for\n     * --> could be used for controlled vocabulary or autocomplete options\n     * @param {KeyboardEvent} event - the keydown event bubbled from search input field\n     */\n    navigateDropDown(event) {\n      event.preventDefault();\n      // determine if arrow was up or down - true if down, false for up\n      const isArrowDown = event.key === 'ArrowDown';\n      // if navigation is used to navigate controlled vocabulary options (= are there\n      // option specified in the filter?) only use arrow up and down\n      if (this.controlledVocabularyOptions && this.controlledVocabularyOptions.length\n        && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {\n        const currentIndex = this.displayedOptions.indexOf(this.activeControlledVocabularyEntry);\n        this.activeControlledVocabularyEntry = this.navigate(\n          this.displayedOptions,\n          isArrowDown,\n          currentIndex,\n          true,\n        );\n        // else navigation is used for autocomplete options\n      } else {\n        this.navigateAutocomplete(event, isArrowDown);\n      }\n    },\n    /**\n     * navigation handling complexe autocomplete navigation with possibilities to\n     * navigate single entries or collections (switch between collections and entries\n     * by using left/right arrow key)\n     *\n     * @param {KeyboardEvent} event - the keydown event bubbled from search input field\n     * @param {boolean} isArrowDown - param passed from navigateDropDown so no need to newly assign\n     */\n    navigateAutocomplete(event, isArrowDown) {\n      // prevent moving of cursor on input line\n      event.preventDefault();\n      if (this.resultListInt.length) {\n        // remember the previous collection so it can be decided if\n        // announcement should be read in the end\n        const previousActiveCollection = this.activeCollectionId;\n        // store key stroked in variable\n        const { key } = event;\n        // actions for arrow up or down\n        if (key === 'ArrowDown' || key === 'ArrowUp') {\n          // if there is no active Collection (could happen due to hover)\n          // set the first item in array\n          if (!this.activeCollectionId) {\n            this.activeCollectionId = this\n              .resultListInt[0][this.autocompletePropertyNames.id];\n          }\n          // get the index of the currently active collection\n          const currentCollectionIndex = this.resultListInt\n            .map(section => section[this.autocompletePropertyNames.id])\n            .indexOf(this.activeCollectionId);\n          let currentCollectionArray = this.consolidatedResultList[this.activeCollectionId];\n          // depending if arrow was up or down set +/- one to add or subtract\n          // generically\n          const numberToAdd = isArrowDown ? 1 : -1;\n          // get the index of the currently active entry within a collection\n          const currentEntryIndex = currentCollectionArray.indexOf(this.activeEntry);\n          // check if the last or first entry of the options list is reached\n          const isWithinListLimit = this.isWithinArrayLimit(\n            this.resultListInt,\n            isArrowDown,\n            currentCollectionIndex + numberToAdd,\n          );\n          // check if collection select is active and if not, if the arrow action is\n          // within the limits of the array\n          if (!this.collectionSelect\n            && this.isWithinArrayLimit(\n              currentCollectionArray,\n              isArrowDown,\n              currentEntryIndex + numberToAdd,\n            )) {\n            // set new active entry\n            this.activeEntry = this.navigate(\n              currentCollectionArray,\n              isArrowDown,\n              currentEntryIndex,\n            );\n            // since it is allowed to add unknown entries it must be possible to\n            // have no active entry when navigating beyond list\n          } else if (!this.collectionSelect\n            && (!isArrowDown && currentCollectionIndex === 0 && currentEntryIndex === 0)) {\n            this.activeEntry = null;\n            this.activeCollectionId = '';\n            // if collection select is active or first/last element of the current collection\n            // is reached - switch to next/previous collection\n          } else if (isWithinListLimit) {\n            // set the new active collection\n            this.activeCollectionId = this.resultListInt[currentCollectionIndex + numberToAdd][this\n              .autocompletePropertyNames.id];\n            currentCollectionArray = this.consolidatedResultList[this.activeCollectionId];\n            // define which element in the newly active collection should appear active\n            // if collection select or arrow up - first one otherwise last\n            const newItemIndex = isArrowDown || this.collectionSelect ? 0\n              : currentCollectionArray.length - 1;\n            // set the active entry of the newly set collection\n            this.activeEntry = currentCollectionArray[newItemIndex];\n            // if it is the last entry of the complete list - start from the top\n          } else if (!isWithinListLimit && currentCollectionIndex === this.resultListInt.length - 1\n            && currentEntryIndex === currentCollectionArray.length - 1) {\n            this.activeCollectionId = this\n              .resultListInt[0][this.autocompletePropertyNames.id];\n            currentCollectionArray = this.consolidatedResultList[this.activeCollectionId];\n            [this.activeEntry] = currentCollectionArray;\n            // else if current index is at -1 go to the last entry in the list\n          } else if (!isWithinListLimit && currentCollectionIndex === 0\n            && currentEntryIndex === -1) {\n            this.activeCollectionId = this.resultListInt[this.resultListInt.length - 1][this\n              .autocompletePropertyNames.id];\n            currentCollectionArray = this.consolidatedResultList[this.activeCollectionId];\n            [this.activeEntry] = currentCollectionArray.slice(-1);\n          }\n        } else if (key === 'ArrowLeft') {\n          this.collectionSelect = true;\n        } else if (key === 'ArrowRight') {\n          this.collectionSelect = false;\n        }\n        // if the assistive text was set, announce if a new category was entered via\n        // key navigation! (not if in collection select mode because then category is announced\n        // anyway)\n        if (this.activeCollectionId && !this.collectionSelect\n          && previousActiveCollection !== this.activeCollectionId\n          && this.assistiveText.categoryAnnouncement) {\n          // since this.activeCollectionId is just the id we need to get the collection label\n          const collectionLabel = this.autocompleteResults\n            .find(({ [this.autocompletePropertyNames.id]: id }) => id === this.activeCollectionId)[this\n            .autocompletePropertyNames.label];\n          // set the announcement and the collection label\n          this.announcement = this.assistiveText.categoryAnnouncement\n            .replace('{label}', collectionLabel);\n        }\n      }\n    },\n    /**\n     * handle the date input after it was validated (necessary to only assign valid date input\n     * to filter_values)\n     *\n     * @param {string|Object} data - the date data in question - either a single string for type\n     * 'date' or an object with date_from and date_to for type 'daterange'\n     */\n    handleDateInput(data) {\n      // check if filter is actually of type date and the validated value differs from the\n      // previously set values\n      if (this.filter.type.includes('date')\n        && JSON.stringify(data) !== JSON.stringify(this.filter.filter_values)) {\n        this.currentInput = data;\n        // set the filter_values with date values - this will trigger search\n        this.filter.filter_values = this.currentInput;\n        this.isActive = false;\n      }\n    },\n\n    /** OTHERS */\n\n    /**\n     * reset all filter row input and navigational variables\n     */\n    resetAllInput() {\n      this.currentInput = '';\n      this.activeEntry = null;\n      this.activeCollectionId = '';\n      this.activeControlledVocabularyEntry = null;\n    },\n    /**\n     * function called on tab keydown on row 'x' or '+' icon\n     * @param {KeyboardEvent} event - the keydown event\n     */\n    onTab(event) {\n      // check if shift key was pressed on tab keydown (only if not the focus leaves the row)\n      if (!event.shiftKey) {\n        // if no - set row active to false\n        this.isActive = false;\n      }\n    },\n    /**\n     * on touch devices click-outside is not only triggered by 'touchstart' instead of 'click'.\n     *  this means the 'click-outside' event gets propagated before the 'click' event on touch devices (on\n     *  desktop browsers it is the other way round). This leads to search drop down getting\n     *  triggered when an element INSIDE search was clicked (in case of desktop when click-outside\n     *  is propagated AFTER this leads to isActive = false again immediately after so no drop\n     *  down showing). Therefore, we need to check for mobile event and set variable stopSearchClick\n     *  to true so in event onSearchClick the click can be stopped from opening the drop-down.\n     *\n     * @param {MouseEvent|TouchEvent} event - the event provided by click-outside plugin\n     */\n    onClickedOutsideSearch(event) {\n      // do the regular action to set is active false (and close drop down)\n      this.isActive = false;\n      // get the event type\n      const { type } = event;\n      // if event type is 'touchstart' we assume mobile that was propagated before click event\n      if (type === 'touchstart') {\n        // therefore we set the click stop variable true\n        this.stopSearchClick = true;\n        // since this should only affect click events triggered directly after set\n        // the variable false again after a time out\n        setTimeout(() => {\n          this.stopSearchClick = false;\n        }, 500);\n      }\n    },\n    /**\n     * need to special handle search click event due to the reasons described above in function\n     *  onClickedOutsideSearch().\n     *\n     * @param {MouseEvent} event - the native click event\n     */\n    onSearchClick(event) {\n      // check if mobile variable to stop click being propagated after click-outside\n      // was set\n      if (!this.stopSearchClick) {\n        // if no - show drop down\n        this.isActive = true;\n      } else {\n        // if click-outside was propagated before click event stop the event here\n        // and don't open drop down\n        event.stopPropagation();\n        this.isActive = false;\n        // set variable false again after\n        this.stopSearchClick = false;\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <!-- vuejs-accessibility/click-events-have-key-events: keydown event is counter productive to workflow here -->\n  <!-- vuejs-accessibility/no-static-element-interactions: click is just for handling focus no\n    interaction/accessibility needed -->\n  <!-- eslint-disable-next-line vuejs-accessibility/click-events-have-key-events vuejs-accessibility/no-static-element-interactions -->\n  <div\n    ref=\"advancedSearchRow\"\n    class=\"base-advanced-search-row\"\n    @click=\"openDropDown\">\n    <!-- SEARCH FIELD -->\n    <!-- note: the id is used in the javascript part as well as the parent component\n      BaseAdvancedSearch.vue - consider that when changing it! -->\n    <BaseSearch\n      ref=\"baseSearch\"\n      v-model=\"currentInput\"\n      v-model:selected-chips=\"selectedOptions\"\n      v-model:is-active=\"isActive\"\n      v-bind=\"$attrs\"\n      :input-id=\"'search-input-' + internalRowId\"\n      :show-pre-input-icon=\"isMainSearch\n        && filter[identifierPropertyName.filter] === defaultFilter[identifierPropertyName.filter]\"\n      :label=\"assistiveText.searchLabel || 'Search for Entries'\"\n      :search-type=\"searchType\"\n      :loadable=\"filter.type === 'text' || filter.type === 'chips'\"\n      :is-loading=\"isLoading\"\n      :placeholder=\"placeholder\"\n      :drop-down-list-id=\"searchType === 'controlled' ? `controlled-options-${internalRowId}`\n        : 'autocomplete-options-' + internalRowId\"\n      :language=\"language\"\n      :identifier-property-name=\"useAutocompleteFunctionality\n        ? identifierPropertyName.autocompleteOption\n        : identifierPropertyName.controlledVocabularyOption\"\n      :label-property-name=\"useAutocompleteFunctionality ? labelPropertyName.autocompleteOption\n        : labelPropertyName.controlledVocabularyOption\"\n      :set-focus-on-active=\"false\"\n      :clearable=\"false\"\n      :add-chips-input-directly=\"false\"\n      :assistive-text=\"{\n        selectedOption: assistiveText.selectedOption,\n        loaderActive: assistiveText.loaderActive,\n        optionAdded: assistiveText.optionAdded,\n        optionToRemoveSelected: assistiveText.optionToRemoveSelected,\n        optionRemoved: assistiveText.optionRemoved,\n        results: assistiveText.results,\n      }\"\n      :date-field-delay=\"dateFieldDelay\"\n      :linked-list-option=\"activeEntry\n        // set option for autocomplete - check if collection select mode is active and set id of that if yes\n        ? (collectionSelect ? activeCollectionId\n          // or set the active entry id\n          : activeEntry[identifierPropertyName.autocompleteOption])\n        // else check if there is an active controlled vocabulary entry and set that if yes\n        : (activeControlledVocabularyEntry\n          ? activeControlledVocabularyEntry[identifierPropertyName.controlledVocabularyOption]\n          // if everything else fails set undefined\n          : undefined)\"\n      :ignore-click-outside=\"['.base-advanced-search-row__drop-down-body']\"\n      :class=\"['base-advanced-search-row__search',\n               { 'base-advanced-search-row__search__shadow': applyBoxShadow }]\"\n      @clicked-outside=\"onClickedOutsideSearch\"\n      @click=\"onSearchClick\"\n      @keydown.stop=\"handleKeyDownEvent\"\n      @keydown.up.down.right.left=\"navigateDropDown\"\n      @keydown.tab=\"handleDropDownOnTabKey\"\n      @keydown.enter.stop.prevent=\"selectOptionOnKeyEnter\"\n      @keydown.esc=\"isActive = false\"\n      @value-validated=\"handleDateInput\">\n      <!-- FIRST COLUMN OF SEARCH FIELD (FILTERS) -->\n      <template #[filterSlotName]>\n        <BaseChipsInputField\n          v-if=\"mode === 'list'\"\n          v-model:selected-list=\"selectedFilter\"\n          :input-id=\"'search-filter-select-' + internalRowId\"\n          :allow-multiple-entries=\"false\"\n          :allow-unknown-entries=\"false\"\n          :allow-dynamic-drop-down-entries=\"false\"\n          :linked-list-option=\"activeFilter\n            ? `filter-option-${activeFilter[identifierPropertyName.filter]}` : null\"\n          :use-form-field-styling=\"false\"\n          :show-input-border=\"false\"\n          :show-label=\"false\"\n          :label=\"assistiveText.selectFilterLabel || 'Select filter'\"\n          :language=\"language\"\n          :drop-down-list-id=\"'filter-options-' + internalRowId\"\n          :identifier-property-name=\"identifierPropertyName.filter\"\n          :label-property-name=\"labelPropertyName.filter\"\n          :input-class=\"filterSlotName === 'input-field-addition-before'\n            ? '' : 'base-advanced-search-row__input-field'\"\n          :class=\"['base-advanced-search-row__first-column',\n                   {\n                     'base-advanced-search-row__first-column__small':\n                       filterSlotName === 'input-field-addition-before',\n                   },\n                   'base-advanced-search-row__filter-input',\n                   {\n                     hide: isMainSearch && filter\n                       [identifierPropertyName.filter] === defaultFilter\n                         [identifierPropertyName.filter],\n                   },\n                   {\n                     'base-advanced-search-row__filter-input__date':\n                       filter.type.includes('date'),\n                   }]\"\n          @click=\"isActive = true\"\n          @keydown.stop=\"handleKeyDownEvent\"\n          @keydown.tab=\"handleDropDownOnTabKey\"\n          @keydown.enter=\"selectFilter(activeFilter)\"\n          @keydown.up.down=\"navigateFilters\">\n          <template #chip=\"{ entry }\">\n            <span\n              :id=\"entry.idInt\"\n              :key=\"'chip-' + entry.idInt\"\n              class=\"base-advanced-search-row__selected-filter-label\">\n              {{ `#${getLangLabel(entry[labelPropertyName.filter], true)}` }}\n            </span>\n          </template>\n        </BaseChipsInputField>\n      </template>\n      <template #post-input-field>\n        <button\n          v-if=\"!isMainSearch\n            || filterHasValues || (filter.type === 'text' && currentInput)\"\n          :class=\"['base-advanced-search-row__icon-button',\n                   { 'base-advanced-search-row__icon-button__date': filter.type.includes('date') }]\"\n          @focusin.stop.prevent\n          @keydown.tab=\"onTab\"\n          @keydown.enter.stop.prevent=\"removeFilter\"\n          @click.stop.prevent=\"removeFilter\">\n          <BaseIcon\n            :title=\"assistiveText.removeFilter || 'Remove filter'\"\n            name=\"remove\"\n            class=\"base-advanced-search-row__search-row-icon\" />\n        </button>\n        <!-- @slot add an element at the end of the search row (e.g. additional button) -->\n        <slot name=\"after\" />\n      </template>\n\n      <!-- DROP DOWN BODY -->\n      <template #below-input>\n        <BaseDropDownList\n          v-if=\"isActive\"\n          ref=\"dropDown\"\n          :drop-down-options=\"resultListInt\"\n          :active-option=\"{ [autocompletePropertyNames.id]: activeCollectionId }\"\n          :list-id=\"'autocomplete-options-' + internalRowId\"\n          :active-styled=\"false\"\n          :active-sub-option=\"activeEntry\"\n          :display-as-drop-down=\"false\"\n          :use-custom-option-active-background-color=\"true\"\n          :language=\"language\"\n          :identifier-property-name=\"autocompletePropertyNames.id\"\n          :label-property-name=\"autocompletePropertyNames.label\"\n          :list-body-style=\"{\n            'max-height': '400px',\n            'overflow-y': 'auto',\n          }\"\n          class=\"base-advanced-search-row__drop-down-body\"\n          @touchstart.stop.passive=\"\"\n          @click.stop=\"\">\n          <!-- FILTER AREA -->\n          <template\n            v-if=\"mode === 'list'\"\n            #before-list>\n            <div\n              :class=\"['base-advanced-search-row__above-list-area',\n                       'base-advanced-search-row__area-padding',\n                       {\n                         'base-advanced-search-row__above-list-area-filters':\n                           filter.type === 'text' || filter.type === 'chips',\n                       }]\">\n              <!-- FILTER SELECT LIST -->\n              <div\n                class=\"base-advanced-search-row__filter-area-wrapper\">\n                <div\n                  class=\"base-advanced-search-row__first-column\n                base-advanced-search-row__filter-area\">\n                  <div\n                    class=\"base-advanced-search-row__filter-area-header\">\n                    <div class=\"base-advanced-search-row__filter-text\">\n                      {{ getI18nTerm(getLangLabel(advancedSearchText.title)) }}\n                    </div>\n                    <div\n                      class=\"base-advanced-search-row__filter-subtext\">\n                      {{ getI18nTerm(getLangLabel(advancedSearchText.subtext)) }}\n                    </div>\n                  </div>\n                  <button\n                    tabindex=\"-1\"\n                    class=\"base-advanced-search-row__filter-area-close\"\n                    @keydown.enter=\"isActive = false\"\n                    @click.stop=\"isActive = false\">\n                    <BaseIcon\n                      class=\"rotate-180 base-advanced-search-row__filter-area-close-icon\"\n                      name=\"drop-down\" />\n                  </button>\n                </div>\n                <div\n                  :class=\"['base-advanced-search-row__columns',\n                           'base-advanced-search-row__filter-list-wrapper',\n                           {\n                             'base-advanced-search-row__filter-list-wrapper__fade-right':\n                               filterFade.right,\n                           },\n                           {\n                             'base-advanced-search-row__filter-list-wrapper__fade-left':\n                               filterFade.left,\n                           }]\">\n                  <ul\n                    :id=\"'filter-options-' + internalRowId\"\n                    ref=\"filterBoxElement\"\n                    role=\"listbox\"\n                    class=\"base-advanced-search-row__filter-list\">\n                    <li\n                      v-for=\"(singleFilter, index) in displayFilterList\"\n                      :id=\"`filter-option-${singleFilter[identifierPropertyName.filter]}`\"\n                      :key=\"index\"\n                      ref=\"filterOption\"\n                      :aria-selected=\"(filter && filter[identifierPropertyName.filter]\n                        === singleFilter[identifierPropertyName.filter]).toString()\"\n                      tabindex=\"-1\"\n                      class=\"base-advanced-search-row__filter base-advanced-search-row__column-item\"\n                      :class=\"[{\n                                 'base-advanced-search-row__filter-active':\n                                   activeFilter === singleFilter,\n                               },\n                               {\n                                 'base-advanced-search-row__filter-selected':\n                                   filter && filter[identifierPropertyName.filter]\n                                     === singleFilter[identifierPropertyName.filter],\n                               }]\"\n                      role=\"option\"\n                      @keydown.enter.stop=\"selectFilter(singleFilter)\"\n                      @click.stop=\"selectFilter(singleFilter)\">\n                      {{ `#${singleFilter[labelPropertyName.filter]}` }}\n                    </li>\n                  </ul>\n                </div>\n              </div>\n            </div>\n          </template>\n\n          <!-- AUTOCOMPLETE OPTIONS LIST -->\n          <template\n            #option=\"{ option }\">\n            <div\n              v-if=\"!filter || useAutocompleteFunctionality\"\n              class=\"base-advanced-search-row__autocomplete-body\">\n              <div\n                v-if=\"option[autocompletePropertyNames.data].length\"\n                :class=\"['base-advanced-search-row__first-column',\n                         'base-advanced-search-row__autocomplete-collection',\n                ]\">\n                <div class=\"base-advanced-search-row__autocomplete-collection-text\">\n                  {{ option[autocompletePropertyNames.label] }}\n                  <span\n                    v-if=\"assistiveText.optionsAnnouncement\"\n                    class=\"hide\">{{ assistiveText.optionsAnnouncement\n                      .replace('{number}', option[autocompletePropertyNames.data].length) }}</span>\n                </div>\n              </div>\n\n              <!-- AUTOCOMPLETE OPTIONS -->\n              <BaseDropDownList\n                :drop-down-options=\"option[autocompletePropertyNames.data]\"\n                :active-option=\"activeCollectionId === option[autocompletePropertyNames.id]\n                  ? activeEntry : {}\"\n                :display-as-drop-down=\"false\"\n                :list-id=\"'autocomplete-options-' + internalRowId\"\n                :language=\"language\"\n                :identifier-property-name=\"identifierPropertyName.autocompleteOption\"\n                :label-property-name=\"labelPropertyName.autocompleteOption\"\n                :use-highlight-string-match=\"highlightAutocompleteMatch\"\n                :highlight-string-tags=\"highlightAutocompleteTags\"\n                :highlight-string-match=\"currentInput\"\n                class=\"base-advanced-search-row__autocomplete-options\"\n                @update:selected-option=\"addOption(\n                  $event,\n                  option[autocompletePropertyNames.id],\n                )\">\n                <template #option=\"{ option: autocompleteOption }\">\n                  <!-- @slot to allow for modification of the autocomplete option\n                    @binding {Object} option - the option object as specified in the [autocompletePropertyNames.data] array\n                    @binding {string} collection-id the currently active collection as provided in [autocompletePropertyNames.id] -->\n                  <slot\n                    name=\"autocomplete-option\"\n                    :option=\"autocompleteOption\"\n                    :collection-id=\"option[autocompletePropertyNames.id]\" />\n                </template>\n              </BaseDropDownList>\n            </div>\n          </template>\n\n          <!-- CHIPS (CONTROLLED VOCABULARY OPTIONS) AREA -->\n          <template\n            v-if=\"filter.type === 'chips' && !filter.freetext_allowed\"\n            #after-list>\n            <div\n              class=\"base-advanced-search-row__above-list-area\n                 base-advanced-search-row__chips-area\n                 base-advanced-search-row__area-padding\">\n              <div\n                :class=\"['base-advanced-search-row__chips-row',\n                         {\n                           'base-advanced-search-row__chips-row__no-options':\n                             filter.type === 'chips' && !displayedOptions.length,\n                         }]\">\n                <div\n                  class=\"base-advanced-search-row__controlled-options-title\n                         base-advanced-search-row__first-column\">\n                  {{ getI18nTerm(getLangLabel(advancedSearchText.availableOptions)) }}\n                </div>\n                <ul\n                  v-if=\"controlledVocabularyOptions && displayedOptions.length\n                    && (displayedOptions.length <= maxNumberControlledOptions\n                      || (currentInput && currentInput.length >= 4))\"\n                  :id=\"`controlled-options-${internalRowId}`\"\n                  role=\"listbox\"\n                  class=\"base-advanced-search-row__chips-list base-advanced-search-row__columns\">\n                  <li\n                    v-for=\"chip in displayedOptions\"\n                    :id=\"chip[identifierPropertyName.controlledVocabularyOption]\"\n                    :key=\"chip[identifierPropertyName.controlledVocabularyOption]\"\n                    :value=\"chip[labelPropertyName.controlledVocabularyOption]\"\n                    :aria-selected=\"(activeControlledVocabularyEntry\n                      && chip[identifierPropertyName.controlledVocabularyOption]\n                        === activeControlledVocabularyEntry[identifierPropertyName\n                          .controlledVocabularyOption] || false).toString()\"\n                    role=\"option\"\n                    tabindex=\"0\"\n                    class=\"base-advanced-search-row__column-item\"\n                    @mouseenter=\"activeControlledVocabularyEntry = chip\"\n                    @focusin=\"activeControlledVocabularyEntry = chip\"\n                    @mouseleave=\"activeControlledVocabularyEntry = null\"\n                    @focusout=\"activeControlledVocabularyEntry = null\">\n                    <BaseChip\n                      :is-removable=\"false\"\n                      :model-value=\"getLangLabel(chip[labelPropertyName.controlledVocabularyOption])\"\n                      :chip-active=\"activeControlledVocabularyEntry\n                        && chip[identifierPropertyName.controlledVocabularyOption]\n                          === activeControlledVocabularyEntry[identifierPropertyName\n                            .controlledVocabularyOption]\"\n                      class=\"base-advanced-search-row__option-chip\"\n                      @clicked=\"addOption(chip)\" />\n                  </li>\n                </ul>\n                <div\n                  v-else-if=\"isLoading\"\n                  class=\"base-advanced-search-row__no-options\n                     base-advanced-search-row__area-padding\">\n                  {{ getI18nTerm(getLangLabel(dropDownInfoTexts.chipsOngoing, true)) }}\n                </div>\n                <!-- INFO if there are too many options to display (however from a certain\n                string length options are still displayed because this would be not very\n                user friendly else... -->\n                <div\n                  v-else-if=\"displayedOptions.length > maxNumberControlledOptions\n                    && (!currentInput || currentInput.length < 4)\"\n                  class=\"base-advanced-search-row__no-options\n                  base-advanced-search-row__area-padding\">\n                  {{ getI18nTerm(getLangLabel(dropDownInfoTexts.chipsMaxOptions, true)) }}\n                </div>\n                <!-- IFNO if string does not match any options -->\n                <div\n                  v-else-if=\"currentInput && currentInput.length && !displayedOptions.length\"\n                  class=\"base-advanced-search-row__no-options\n                     base-advanced-search-row__area-padding\">\n                  {{ getI18nTerm(getLangLabel(dropDownInfoTexts.chipsNoMatch, true)) }}\n                </div>\n                <!-- INFO if no more options are available (all options already added) -->\n                <div\n                  v-else-if=\"!displayedOptions.length\"\n                  class=\"base-advanced-search-row__no-options\n                     base-advanced-search-row__area-padding\">\n                  {{ getI18nTerm(getLangLabel(dropDownInfoTexts.chipsNoOptions, true)) }}\n                </div>\n              </div>\n            </div>\n          </template>\n          <template\n            #no-options>\n            <div\n              v-if=\"useAutocompleteFunctionality\"\n              :class=\"[\n                'base-advanced-search-row__no-options',\n                { 'base-advanced-search-row__no-options-hidden': !useAutocompleteFunctionality },\n              ]\">\n              <div\n                v-if=\"!currentInput\n                  || (typeof currentInput === 'string' && !currentInput.trim())\">\n                {{ getI18nTerm(getLangLabel(dropDownInfoTexts.autocompleteInitial, true)) }}\n              </div>\n              <div\n                v-else-if=\"isLoading\">\n                {{ getI18nTerm(getLangLabel(dropDownInfoTexts.autocompleteOngoing, true)) }}\n              </div>\n              <div v-else>\n                {{ getI18nTerm(getLangLabel(dropDownInfoTexts.autocompleteNoOptions, true)) }}\n              </div>\n            </div>\n          </template>\n        </BaseDropDownList>\n        <!-- @slot add an element below the primary row (same styling (box-shadow) as primary row element) -->\n        <slot name=\"below\" />\n      </template>\n    </BaseSearch>\n    <BaseButton\n      v-if=\"mode === 'list' && isMainSearch\"\n      icon=\"plus\"\n      button-style=\"row\"\n      icon-position=\"right\"\n      :class=\"['base-advanced-search-row__add-filter-button',\n               { 'base-advanced-search-row__add-filter-button__shadow': applyBoxShadow }]\"\n      @clicked=\"addFilterRow\"\n      @click.stop=\"\">\n      <template #text=\"{ labelId }\">\n        <span\n          :id=\"labelId\"\n          class=\"base-advanced-search-row__add-filter-button__text\">\n          {{ assistiveText.addFilter || 'Add filter' }}\n        </span>\n      </template>\n    </BaseButton>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n@use \"@/styles/variables\" as *;\n\n.base-advanced-search-row {\n  position: relative;\n  width: 100%;\n  // css variable to define option background color\n  // THIS IS SETTING THE BACKGROUND COLOR IN BASEDROPDOWNLIST\n  --option-background: rgb(248, 248, 248);\n  // set number of columns for filters and chips\n  --col-number: 4;\n  display: flex;\n  flex-direction: row;\n\n  .base-advanced-search-row__search {\n    width: 100%;\n\n    &__shadow {\n      box-shadow: $box-shadow-reg;\n    }\n\n    .base-advanced-search-row__first-column {\n      // if the 25% is changed the function resizeActions() column calculations\n      // needs to be adapted as well\n      flex: 0 0 25%;\n      min-width: 120px;\n      max-width: 250px;\n      overflow-wrap: break-word;\n      margin-right: $spacing;\n\n      &__small {\n        flex: unset;\n        max-width: 100%;\n      }\n    }\n\n    .base-advanced-search-row__area-padding {\n      padding-right: $spacing;\n      padding-left: $spacing;\n    }\n\n    .base-advanced-search-row__filter-input {\n      align-self: center;\n\n      &.base-advanced-search-row__filter-input__date {\n        padding-left: $spacing-small;\n      }\n\n      .base-advanced-search-row__selected-filter-label {\n        color: $app-color;\n        display: -webkit-box;\n        -webkit-line-clamp: 2;\n        -webkit-box-orient: vertical;\n        overflow: hidden;\n      }\n    }\n\n    .base-advanced-search-row__icon-button {\n      display: flex;\n      flex: 0 0 auto;\n      align-self: center;\n      height: 100%;\n      padding: $spacing;\n      margin-right: -$spacing-small;\n      cursor: pointer;\n\n      &:active, &:focus {\n        color: $app-color;\n        fill: $app-color;\n      }\n\n      &.base-advanced-search-row__icon-button__date {\n        margin-right: -$spacing-small;\n        align-items: center;\n      }\n\n      .base-advanced-search-row__search-row-icon {\n        height: $icon-medium;\n        width: $icon-medium;\n      }\n    }\n\n    .base-advanced-search-row__drop-down-body {\n      background: white;\n      border-top: $separation-line;\n      width: 100%;\n      position: absolute;\n      box-shadow: $drop-shadow;\n      z-index: map.get($zindex, dropdown);\n\n      &.base-advanced-search-row__drop-down-body__date {\n        width: calc(100% + #{$spacing});\n        left: -$spacing-small;\n      }\n\n      .base-advanced-search-row__columns {\n        column-gap: $spacing;\n        column-count: var(--col-number, 4);\n        // this is used in the script part to calculate columns! (~line 1589)\n        column-width: 180px;\n        display: block;\n        width: 100%;\n\n        .base-advanced-search-row__column-item {\n          // for chrome columns not aligned properly and\n          // last item bleeding into next column\n          -webkit-column-break-inside: avoid;\n          backface-visibility: hidden;\n        }\n      }\n\n      .base-advanced-search-row__above-list-area {\n        &.base-advanced-search-row__above-list-area-filters {\n          border-bottom: $separation-line;\n          padding-top: $spacing-small-half;\n          padding-bottom: $spacing-small-half;\n        }\n\n        .base-advanced-search-row__filter-area-wrapper {\n          .base-advanced-search-row__filter-area {\n            display: flex;\n            flex-direction: row;\n            justify-content: space-between;\n            align-items: center;\n            width: 100%;\n\n            .base-advanced-search-row__filter-area-header {\n              align-self: flex-start;\n              max-width: 100%;\n\n              .base-advanced-search-row__filter-text {\n                padding-top: $spacing-small-half;\n                color: $font-color-second;\n              }\n              .base-advanced-search-row__filter-subtext {\n                color: $font-color-second;\n                font-size: $font-size-small;\n              }\n            }\n          }\n        }\n\n        .base-advanced-search-row__filter-list-wrapper {\n          .base-advanced-search-row__filter-list {\n            .base-advanced-search-row__filter {\n              cursor: pointer;\n              color: $app-color;\n              padding: $spacing-small-half $spacing;\n\n              &:focus {\n                outline: none;\n              }\n\n              &.base-advanced-search-row__filter-active, &:hover {\n                box-shadow: inset 0 0 0 1px $app-color;\n              }\n\n              &.base-advanced-search-row__filter-selected {\n\n              }\n            }\n          }\n        }\n\n        .base-advanced-search-row__chips-row, .base-advanced-search-row__filter-area-wrapper {\n          display: flex;\n        }\n\n        .base-advanced-search-row__chips-row {\n          align-items: baseline;\n          min-height: calc(#{$row-height-small} + #{$spacing-small});\n          padding-top: $spacing-small-half;\n          padding-bottom: $spacing-small-half;\n\n          &.base-advanced-search-row__chips-row__no-options {\n            padding-top: 0;\n            padding-bottom: 0;\n          }\n\n          .base-advanced-search-row__controlled-options-title {\n            color: $font-color-second;\n            min-height: $row-height-small;\n            padding-top: calc(#{$spacing-small} / 2);\n          }\n\n          .base-advanced-search-row__chips-list {\n            margin-left: $spacing;\n            line-height: $row-height-small;\n\n            .base-advanced-search-row__option-chip {\n              cursor: pointer;\n\n              &:hover::after {\n                content: '';\n                width: 100%;\n                height: 100%;\n                position: absolute;\n                top: 0;\n                right: 0;\n                background: $app-color;\n                opacity: 0.5;\n              }\n            }\n          }\n        }\n      }\n\n      .base-advanced-search-row__autocomplete-body {\n        display: flex;\n        flex-direction: row;\n        width: 100%;\n\n        .base-advanced-search-row__autocomplete-collection {\n          font-weight: 600;\n\n          .base-advanced-search-row__autocomplete-collection-text {\n            min-height: $row-height-small;\n            padding-top: calc(#{$spacing-small} / 2);\n          }\n        }\n\n        .base-advanced-search-row__autocomplete-options {\n          width: 100%;\n        }\n      }\n\n      .base-advanced-search-row__no-options {\n        min-height: calc(#{$row-height-small} + #{$spacing-small});\n        padding-top: 0;\n        padding-bottom: 0;\n        width: 100%;\n        display: flex;\n        align-items: center;\n\n        &.base-advanced-search-row__no-options-hidden {\n          display: none;\n        }\n      }\n    }\n  }\n}\n\n.base-advanced-search-row__add-filter-button {\n  margin-left: $spacing-small;\n  width: $row-height-large;\n\n  .base-advanced-search-row__add-filter-button__text {\n    position: absolute;\n    top: auto;\n    left: -9999px;\n  }\n\n  &__shadow {\n    box-shadow: $box-shadow-reg;\n  }\n\n  // override the margin set as soon as slot has content - which is the case\n  // here but text is not shown > mobile\n  &.base-button:deep(.base-button__icon.base-button__icon--margin) {\n    @media screen and (min-width: $mobile-min-width) {\n      margin-left: 0;\n    }\n  }\n}\n\n.base-advanced-search-row__filter-area-close {\n  display: none;\n\n  .base-advanced-search-row__filter-area-close-icon {\n    width: $icon-medium;\n    height: $icon-medium;\n  }\n}\n\n@media screen and (max-width: $mobile) {\n  .base-advanced-search-row {\n    flex-direction: column;\n\n    .base-advanced-search-row__add-filter-button {\n      margin-left: 0;\n      margin-top: $spacing-small;\n      height: $row-height-large;\n      width: 100%;\n\n      .base-advanced-search-row__add-filter-button__text {\n        position: relative;\n        top: auto;\n        left: unset;\n        display: inline;\n      }\n    }\n\n    .base-advanced-search-row__first-column {\n      max-width: 100%;\n      margin-right: $spacing-small;\n    }\n\n    .base-advanced-search-row__drop-down-body {\n      .base-advanced-search-row__above-list-area{\n\n        .base-advanced-search-row__filter-area-wrapper, .base-advanced-search-row__chips-row {\n          flex-direction: column;\n        }\n\n        .base-advanced-search-row__filter-area-wrapper {\n          .base-advanced-search-row__filter-area {\n            max-width: unset;\n\n            .base-advanced-search-row__filter-area-close {\n              display: inline;\n              padding: $spacing-small $spacing;\n            }\n          }\n        }\n\n        .base-advanced-search-row__filter-list-wrapper {\n          position: relative;\n          overflow: hidden;\n          display: flex;\n          min-height: $row-height-small;\n\n          &.base-advanced-search-row__filter-list-wrapper__fade-right {\n            &::after {\n              content: '';\n              height: 100%;\n              width: 80px;\n              position: absolute;\n              top: 0;\n              right: 0;\n              background: linear-gradient(to right, rgba(255, 255, 255, 0),\n                rgba(255, 255, 255, 1));\n              pointer-events: none;\n            }\n          }\n\n          &.base-advanced-search-row__filter-list-wrapper__fade-left {\n            &::before {\n              content: '';\n              height: 100%;\n              width: 80px;\n              position: absolute;\n              top: 0;\n              left: 0;\n              background: linear-gradient(to right, rgba(255, 255, 255, 1),\n                rgba(255, 255, 255, 0));\n              pointer-events: none;\n            }\n          }\n\n          .base-advanced-search-row__filter-list {\n            column-count: unset;\n            column-gap: unset;\n            column-width: unset;\n            display: flex;\n            align-items: center;\n            flex-direction: row;\n            overflow: auto;\n            margin: 0 1px;\n            scrollbar-width: none; /* Firefox */\n            -ms-overflow-style: none;  /* Internet Explorer 10+ */\n\n            &::-webkit-scrollbar { /* WebKit */\n              width: 0;\n              height: 0;\n            }\n\n            .base-advanced-search-row__filter {\n              white-space: nowrap;\n\n              &.base-advanced-search-row__filter-selected,\n              &.base-advanced-search-row__filter-active,\n              &.base-advanced-search-row__filter:hover {\n                box-shadow: none;\n              }\n            }\n          }\n        }\n      }\n\n      .base-advanced-search-row__autocomplete-body {\n        flex-wrap: wrap;\n\n        .base-advanced-search-row__autocomplete-collection {\n          flex: 0 0 auto;\n          margin-right: 0;\n        }\n      }\n    }\n  }\n}\n</style>\n\n<style lang=\"scss\">\n@use \"@/styles/variables\" as *;\n\n.base-advanced-search-row__input-field {\n  height: calc(#{$row-height-large} - 4px);\n}\n</style>\n","<script>\nimport { computed, defineAsyncComponent, useTemplateRef } from 'vue';\nimport { createId, debounce, extractNestedPropertyValue, hasData, sort } from '@/utils/utils.js';\nimport { useAnnouncer } from '@/composables/useAnnouncer.js';\nimport { useId } from '@/composables/useId.js';\nimport BaseAdvancedSearchRow from '@/components/BaseAdvancedSearch/BaseAdvancedSearchRow.vue';\n\n/**\n * @typedef Filter\n * @property {string?} label|* - property 'label' indicating the label or an equivalent\n *  custom property defined in prop labelPropertyName.filter\n * @property {string} id|* - property 'id' used as unique identifier or an equivalent\n *  custom property defined in prop identifierPropertyName.filter\n * @property {string} type - a filter type defining the type of search element shown\n *  @values text, chips, chipssingle, date, daterange\n * @property {boolean?} [hidden] - exclude filters that have this attribute true from display\n * @property {boolean?} [freetext_allowed] - property specifc for type: chips determining\n *  if options are autocompleted (true) or used from the options property (false)\n * @property {Object[]?} [options] - the options used for chips filter types with\n *  freetext_allowed false\n * @property {Object[]|string[]|string|Object?} [filter_values] - the values a filter contains - only\n *  relevant for applied filters, not for filters coming from backend presented in the drop down\n * @property {string[]} [subsets] - if a filter of `type` 'text' or 'chips' with `freetext_allowed`\n *      (thus triggering autocomplete) has subordinate filters for which the autosuggest results\n *      should also be shown - add these filter ids here\n */\n\nexport default {\n  name: 'BaseAdvancedSearch',\n  components: {\n    BaseAdvancedSearchRow,\n    BaseCollapsedFilterRow: defineAsyncComponent(() => import('@/components/BaseAdvancedSearch/BaseCollapsedFilterRow.vue').then(m => m.default || m)),\n    BaseForm: defineAsyncComponent(() => import('@/components/BaseForm/BaseForm.vue').then(m => m.default || m)),\n    BaseButton: defineAsyncComponent(() => import('@/components/BaseButton/BaseButton.vue').then(m => m.default || m)),\n    BaseInsertTextAsHtml: defineAsyncComponent(() => import('@/components/BaseInsertTextAsHtml/BaseInsertTextAsHtml.vue')),\n  },\n  props: {\n    /**\n     * define the appearance and functionality of the component here.\n     * **`list`**: search offers advanced search with 'filters' to select from drop down, each filter is added\n     *    as a separate row.\n     * **`form`**: advanced search is displayed as a form below only one single search row. Offers a condensed view\n     *    of the form within a single scrollable row below main row.\n     */\n    mode: {\n      type: String,\n      default: 'list',\n      validator: val => ['list', 'form'].includes(val),\n    },\n    /**\n     * this variable is just used in mode `list`, for mode `form` leave it empty and use variable `formFilterList`\n     *  to provide a list of filters instead.\n     * provide a list of available filters, needs to be an array of objects with the following properties:\n     *\n     *    **label** `string` - the label of the filter (displayed\n     *      if not main search) - this prop can be customized by specifying\n     *      `labelPropertyName.filter`.\n     *    **id** `string` - the identifier of the filter (displayed\n     *      if not main search) - this prop can be customized by specifying\n     *      `identifierPropertyName.filter`.\n     *    **type** `string` - the filter type. Possible values: `text`, `chips`, `chipssingle`, `date`, `daterange`.\n     *    **hidden** `boolean` - filters with this attribute true will be filtered from\n     *      displayed filter list.\n     *    **freetext_allowed** `boolean` - determines if predetermined options from `options`\n     *      property are used or autocomplete is used.\n     *    **options** `Object[]` - for filter type `chips` and `chipssingle` the controlled\n     *      vocabulary options.\n     *     **subsets** `string[]` - if a filter of `type` 'text' or 'chips' with\n     *      `freetext_allowed` (thus triggering autocomplete) has subordinate filters for which\n     *      the autosuggest results should also be shown - add the filter identifiers here\n     */\n    filterList: {\n      type: Array,\n      default: () => ([]),\n      validator: val => !val.length\n        // make sure a filter type is present and type is other than chips or freetext is\n        // allowed - otherwise it needs to have an options property\n        || (val.every(v => !!v.type\n          && (!['chips', 'chipssingle'].includes(v.type) || v.freetext_allowed || !!v.options))),\n    },\n    /**\n     * this variable is just used in mode `list`, for mode `form` leave it empty and use property `formFilterValues`\n     *  to provide values per filter instead.\n     * possibility to set applied filters from outside, for necessary object properties\n     * see `filterList` (except `options` - this property is not necessary for applied filters)\n     */\n    appliedFilters: {\n      type: Array,\n      default: () => ([]),\n      // don't check for options on applied filters - not necessary\n      validator: val => !val.length || val.every(v => v.type),\n    },\n    /**\n     * in mode `list` specify a default value for a filter that is set when none of the\n     * available filters is selected, should have the following properties:\n     *\n     *    **label** `string` - the label of the filter (displayed\n     *      if not main search) - this prop can be customized by specifying\n     *      `labelPropertyName.filter`.\n     *    **id** `string` - the identifier of the filter (displayed\n     *      if not main search) - this prop can be customized by specifying\n     *      `identifierPropertyName.filter`.\n     *    **type** `string` - the filter type. Possible values: `text`, `chips`, `chipssingle`, `date`, `daterange`.\n     *    **options** `Object[]` - for filter type `chips` and `chipssingle` the controlled\n     *      vocabulary options.\n     *    **filter_values** `Object[], string[], Object` - the values selected - object for date\n     *    or array of objects or strings for type `text`, type `chips` and `chipssingle`,\n     *\n     *    defaultFilter does not need the property `subsets` since results for all filters are\n     *    shown per default\n     *\n     *  this property is not relevant in mode `form`\n     */\n    defaultFilter: {\n      type: Object,\n      default: () => ({\n        label: 'Fulltext',\n        id: 'default',\n        type: 'text',\n        options: [],\n        filter_values: [],\n      }),\n      validator: val => val === null || (val.type\n        && (!['chips', 'chipssingle'].includes(val.type) || val.options)),\n    },\n    /**\n     * this variable is just used in mode `form`, for mode `list` leave it empty and use property `filterList`\n     *  to provide a list of filters instead.\n     * for mode 'form' provide a specification for the form fields in the form of [OpenAPi\n     *  schema object](https://swagger.io/specification/#schema-object).\n     *  see also [BaseForm](BaseForm) `form-field-json` prop - currently all field types except\n     *    `multiline` and `chips-below` and for date/time fields only single date, date range and date time fields\n     *    are supported. Also field groups are supported but maximum nesting level is 1.\n     */\n    formFilterList: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * this variable is just used in mode `form`, for mode `list` leave it empty and use property `appliedFilters`\n     *  to provide values per filter instead.\n     * provide values for the fields specified in `formFilterList`. Main filter can be filled by adding a `default` property.\n     */\n    formFilterValues: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * pass props for [BaseForm](BaseForm) directly via this prop, for example `autocompleteResults`,\n     *  `isLoading` or `fieldProps` (except `valueList` and `formFieldJson` which are passed separately\n     *   since they are also utilized (and modified) in this component).\n     */\n    formProps: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * provide the component with the fetched autocomplete results\n     * (drop down options).\n     * this needs to be an object array with the properties specified in\n     * `autocompletePropertyNames`.\n     */\n    autocompleteResults: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * specify a language (ISO 639-1) (used for label if label is language specific object\n     * e.g. `{ de: 'xxx', en: 'yyy' }`) or for date display conversion in mode 'form'.\n     */\n    language: {\n      type: String,\n      default: 'en',\n    },\n    /**\n     * set the row loader from outside per row index\n     */\n    isLoadingIndex: {\n      type: Number,\n      default: -1,\n    },\n    /**\n     * specify informational texts for the component - this needs to be an object with the following\n     * properties (if you don't want to display any text leave an empty string):\n     *\n     *     **title**: text shown as first line on the drop-down in filters area for mode `list`.\n     *     **subtext**: text shown as second line on the drop-down in filters area for mode `list`.\n     *     **availableOptions**: text shown with chips options for controlled vocabulary\n     *     search` for mode `list`.\n     *     **collapsedDateTime**: for mode `form`: set the text for the collapsed filter row which is\n     *      displayed for date or time values of ranges when only one field is filled. (e.g. `until 12.12.2023`)\n     *     **advancedButtonLabel**: button text displayed for Advanced Search Toggle button for mode `form`.\n     *\n     *  The values of this object might be plain text or a key for an i18n file.\n     */\n    advancedSearchText: {\n      type: Object,\n      default: () => ({\n        title: 'Advanced Search',\n        subtext: 'Select a filter',\n        availableOptions: 'Available options',\n        collapsedDateTime: {\n          from: 'from',\n          until: 'until',\n          range: 'to',\n        },\n        advancedButtonLabel: 'Advanced Search',\n      }),\n    },\n    /**\n     * specify informational texts for the drop-down - this needs to be an object with the following\n     * properties:\n     *\n     *     **autocompleteNoOptions**: info text shown when autocomplete search does not yield\n     *        any results.\n     *     **autocompleteOngoing**: info text displayed while autocomplete search is ongoing\n     *        (and no previous results are displayed).\n     *     **autocompleteInitial**: info text shown when user first opens the search\n     *        component.\n     *     **chipsNoOptions**: info text shown when no options for controlled vocabulary search\n     *        are available (anymore).\n     *     **chipsMaxOptions**: text displayed if more than max number of options that can be\n     *        displayed are available (configure via prop `maxNumberControlledOptions`).\n     *     **chipsNoMatch**: text displayed if string in input does not match any options.\n     *     **chipsOngoing**: info text shown when controlled vocabulary chips are being\n     *        fetched.\n     *\n     *  The values of this object might be plain text or a key for an i18n file\n     * This prop can be ignored when the `no-options` slot is used.\n     */\n    dropDownInfoTexts: {\n      type: Object,\n      default: () => ({\n        autocompleteNoOptions: 'No matching options found',\n        autocompleteOngoing: 'Autocomplete is being fetched...',\n        autocompleteInitial: 'Please start typing or select a filter to see options',\n        chipsNoOptions: 'No more options available',\n        chipsMaxOptions: 'Please start typing to see options',\n        chipsNoMatch: 'No matching options were found',\n        chipsOngoing: 'Options are being loaded...',\n      }),\n      // checking if all necessary properties are part of the provided object\n      validator: val => ['autocompleteNoOptions', 'autocompleteOngoing', 'autocompleteInitial',\n        'chipsNoOptions', 'chipsOngoing', 'chipsMaxOptions', 'chipsNoMatch']\n        .every(prop => Object.keys(val).includes(prop)),\n    },\n    /**\n     * add a placeholder for the search input, either a string used for every row or\n     * add separate values for main filter row and already added filters\n     * properties:\n     *     **filterRow**: for already added filter rows.\n     *     **main**: for the primary search input field.\n     *\n     *  each of these specific placeholders can again be a string or an object with different\n     *  placeholders for each search type (`text`, `chips`, `date`)\n     */\n    placeholder: {\n      type: [Object, String],\n      default: () => ({\n        filterRow: 'Add values to your filter',\n        main: 'Search and Discover',\n      }),\n      validator: val => typeof val === 'string' || ['filterRow', 'main']\n        .every(prop => Object.keys(val).includes(prop)),\n    },\n    /**\n     * specify the object property that can be used for identification of filters,\n     * autocomplete options and controlled vocabulary options.\n     *   Could be a string (used for all the mentioned objects) or an object with the following\n     *   properties:\n     *     **filter**: identifier property name in filter objects.\n     *     **autocompleteOption**: identifier property name in autocomplete option objects.\n     *     **controlledVocabularyOption**: identifier property name in controlled\n     *     vocabulary option objects.\n     *     **formInputs**: for mode 'form' in case the form contains chips or autocomplete input fields,\n     *      the object properties for label and identifier need to be set here (in case they are different\n     *      from the input components default (e.g. see [BaseChipsInput](BaseChipsInput) `identifierPropertyName`))\n     *      if `identifierPropertyName` is also set via `fieldProps` the latter is the preferred value.\n     *  Caveat: Please note that the property `idInternal` is used for internal handlings and the property\n     *    might be overwritten\n     */\n    identifierPropertyName: {\n      type: [Object, String],\n      default: () => ({\n        filter: 'id',\n        autocompleteOption: 'id',\n        controlledVocabularyOption: 'id',\n        formInputs: 'source',\n      }),\n    },\n    /**\n     * specify the object property that should be used for label display of filters,\n     * autocomplete options and controlled vocabulary options.\n     *   Could be a string (used for all the mentioned objects) or an object with the following\n     *   properties:\n     *     **filter**: label property name in filter objects.\n     *     **autocompleteOption**: label property name in autocomplete option objects.\n     *     **controlledVocabularyOption**: label property name in controlled\n     *     vocabulary option objects.\n     *     **formInputs**: for mode 'form' in case the form contains chips or autocomplete input fields,\n     *      the object properties for label and identifier need to be set here (in case they are different\n     *      from the input components default (e.g. see [BaseChipsInput](BaseChipsInput) `labelPropertyName`))\n     *      if `labelPropertyName` is also set via `fieldProps` the latter is the preferred value.\n     *    Caveat: Please note that the property `labelInternal` is used for internal handlings and the property\n     *    might be overwritten\n     */\n    labelPropertyName: {\n      type: [Object, String],\n      default: () => ({\n        filter: 'label',\n        autocompleteOption: 'title',\n        controlledVocabularyOption: 'label',\n        formInputs: 'label',\n      }),\n    },\n    /**\n     * autocomplete results need a label, and id and a data property that contains all the actual\n     * autocomplete results for that specific category\n     * TODO: make category optional\n     */\n    autocompletePropertyNames: {\n      type: Object,\n      default: () => ({\n        label: 'label',\n        id: 'id',\n        data: 'data',\n      }),\n      // check if all the necessary attributes are included in the provided object\n      validator: val => ['id', 'label', 'data'].every(key => Object.keys(val).includes(key)),\n    },\n    /**\n     * this prop gives the option to add assistive text for screen readers for\n     *  the BaseSearch component.\n     * properties:\n     * **addFilter**: text/label used for add filter icon for mode `list`.\n     * **removeFilter**: text/label used for remove filter icon for mode `list`.\n     * **selectFilterLabel**: label (not visible) used for filter chips input field for mode `list`.\n     * **searchLabel**: label (not visible) used for search input field.\n     * **selectedOption**: text read when a selected option is focused (currently only\n     *  working for type chips with autocomplete (=freetext_allowed))\n     * **optionAdded**: only for mode `list` - text read when an option was added to selected list\n     *    (if BaseSearch type is type `chips`)\n     * **optionToRemoveSelected**: only for mode `list` - text read when a selected option is in\n     *    focus to be removed (if BaseSearch type is type `chips`)\n     * **optionRemoved**: only for mode `list` - text read when an option was removed\n     *    from selected list (if BaseSearch type is type `chips`)\n     * **loaderActive**: text that is announced when autocomplete results are being fetched (prop\n     *  `isLoading` is set `true`)\n     * **autocompleteResultsRetrieved**: text announced when autocomplete results are returned.\n     *  use {optionsNumber} and {collectionsNumber} in the string to announce the number of\n     *  total options and collections found respectively.\n     * **autocompleteNoResults**: Text announced when no results were found with a given\n     *  search string.\n     * **autocompleteInitial**: Text announced when no search string was provided for\n     *  autocomplete.\n     * **categoryAnnouncement**: Text announced when a new category is entered in the\n     *  autocomplete drop down options list with keyboard navigation. string '{label}' will\n     *  be replaced by the actual specified category label\n     * **optionsAnnouncement**: announced together with category when in category selection\n     *  mode (after using arrowLeft key on autocomplete input) - to give the user a feeling\n     *  how many options were found for the announced category. string '{number}' will be\n     *  replaced by the number of entries in that category.\n     * **autocompleteOptionFilledToForm**: text announced when an option was selected from the autocomplete\n     *  dropdown, and it is filled into the respective form field. (only for mode `form`)\n     * **advancedButtonDescription**: button description for Advanced Search Toggle button for mode `form`.\n     *      For accessibility purposes. You may add the string {state} which will be replaced with the respective\n     *      'open' and 'close' value specified in `formState` (see below). Only relevant for mode `form`.\n     * **formState**: an object with properties `open` (text that is read when form is closed and button\n     *      functionality is to open the form) and `close` (text that is read when form is open and button\n     *      functionality is to close the form). Only relevant for mode `form`.\n     * **removeAllFiltersLabel**: label for the remove icon in the collapsed filter row.\n     *     Only relevant for mode `form`. For accessibility purposes\n     * **removeFilterValueNotification**: notification that is read by screen readers when a filter\n     *      value was removed. Add the string {value} to read the filter value that was removed and\n     *      {label} to read the label of the filter from which the value was removed. Only relevant for mode `form`.\n     * **collapsedFilterRowRemovedNotification**: notification read when the last filter was removed from\n     *      the collapsed filter row. Or remove row was clicked. Only relevant for mode `form`.\n     * **collapsedAppliedFiltersLabel**: description for the filters in the collapsed filter row.\n     *      Only relevant for mode `form`. For accessibility purposes.\n     * **collapsedBooleanFilterValue**: Set text that should be read for a boolean filter value. You may add\n     *      the string {label} which will be replaced by the filter label.\n     *      Only relevant for mode `form`. For accessibility purposes.\n     * **collapsedOptionToRemoveSelected**: text read when an option is focused (and thus selected), should\n     *  announce to the screen reader user that option can now be removed via Backspace or Delete.\n     * **results**: provide text that should be announced when the search has\n     *  yielded results (or not).\n     *\n     * Caveat: `results` has a watcher attached to trigger the\n     *    announcement so make sure the property values are reset after filling them\n     *    by using update:assistive-text or resetting it manually (after a timeout)\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        addFilter: 'Add filter',\n        removeFilter: 'Remove filter',\n        selectFilterLabel: 'Select filter',\n        searchLabel: 'Search for Entries',\n        selectedOption: '',\n        optionAdded: 'option {label} added to selected list.',\n        optionToRemoveSelected: 'option {label} from selected list marked for removal. Press delete or backspace to remove.',\n        optionRemoved: 'option {label} removed.',\n        autocompleteLoaderActive: 'loading options.',\n        autocompleteResultsRetrieved: '{optionsNumber} options found in {collectionsNumber} categories.',\n        autocompleteNoResults: 'No results found.',\n        autocompleteInitial: 'Please start typing to see suggestions.',\n        categoryAnnouncement: 'category {label}.',\n        optionsAnnouncement: '{number} options.',\n        autocompleteOptionFilledToForm: 'option {optionLabel} filled to field {fieldLabel}.',\n        advancedButtonDescription: 'Click to {state} advanced search form.',\n        formState: {\n          open: 'open',\n          close: 'close',\n        },\n        removeAllFiltersLabel: 'Remove all filters.',\n        removeFilterValueNotification: 'Filter value {value} was removed from filter {label}.',\n        collapsedFilterRowRemovedNotification: 'All search filters were reset.',\n        collapsedAppliedFiltersLabel: 'Currently applied Filters',\n        collapsedBooleanFilterValue: 'Filter {label} was set',\n        collapsedOptionToRemoveSelected: 'Press delete or backspace to remove.',\n        results: '',\n      }),\n    },\n    /**\n     * if desired the box shadow around the search rows can be deactivated here\n     */\n    applyBoxShadow: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * use this prop to set a delay in ms before date input calendar is displayed\n     */\n    dateFieldDelay: {\n      type: Number,\n      default: 0,\n    },\n    /**\n     * prop only relevant for mode `form`\n     * set advanced search (form) visibility from outside\n     * this can also be used to not show the advanced search after initial loading\n     */\n    advancedFormOpen: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * set this flag to `true` to highlight autocomplete option characters that match\n     *  the current search input string\n     */\n    highlightAutocompleteMatch: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `highlightAutocompleteMatch` is set `true`\n     *  provide tag names to style the matched characters\n     *  (without '<' and '>', e.g. ['b'] for <b>)\n     */\n    highlightAutocompleteTags: {\n      type: Array,\n      default: () => ([]),\n    },\n    /**\n     * mode `form`: if necessary selected chip text can  be rendered as v-html directive\n     *  either set this prop `true` or `false`\n     *\n     * this will only be applied to chips with an identifier property and of course\n     *   can only apply to form field field_type `chips`\n     *\n     * if only chips of certain form fields should be rendered as html use prop\n     *  `formProps.fieldProps.interpretChipsLabelAsHtml` or if certain fields should\n     *  be excluded set this prop to `true` and set `formProps.fieldProps.interpretChipsLabelAsHtml`\n     *  for that field `false`\n     */\n    interpretFormChipsLabelAsHtml: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['search', 'fetch-autocomplete', 'fetch-form-autocomplete', 'update:applied-filters', 'update:form-filter-values', 'update:advanced-form-open'],\n  setup() {\n    /** ADD FILTER ROW */\n    /**\n     * set up a reference to the main search field, which we need to be able\n     * to focus the input field after adding a filter row\n     * @type {Readonly<ShallowRef<null|HTMLElement>>}\n     */\n    const mainSearch = useTemplateRef('mainSearch');\n\n    /**\n     * get the native HTML input element stored in the `inputElement` variable in BaseSearch\n     * @type {ComputedRef<HTMLElement|null>}\n     */\n    const inputElement = computed(() => mainSearch.value?.baseSearch?.inputElement || null);\n\n    /** INTERNAL ID */\n    const internalId = useId();\n\n    /** ACCESSIBILITY ANNOUNCEMENTS */\n    /**\n     * set up a reference to the element to be able to attach the announcements element\n     * @type {Readonly<ShallowRef<null|HTMLElement>>}\n     */\n    const searchContainer = useTemplateRef('searchContainer');\n    /**\n     * insert an HTML element with aria-live assertive that will announce the\n     * search result\n     * @type {Ref<UnwrapRef<string>>}\n     */\n    const { announcement } = useAnnouncer(searchContainer);\n    return {\n      internalId,\n      mainSearch,\n      inputElement,\n      searchContainer,\n      announcement,\n    };\n  },\n  data() {\n    return {\n      /**\n       * internal variable to handle applied filters also when set from outside\n       * @type {Filter[]}\n       */\n      appliedFiltersInt: [],\n      /**\n       * the filter used in the main search field - not added to applied filters yet\n       * @type {Filter}\n       */\n      mainFilter: null,\n      /**\n       * store the autocomplete results for each filter in this variable to have\n       * it available even when other filter was used in the meantime\n       * @type {Object[]}\n       */\n      filtersAutocompleteResults: [],\n      /**\n       * a variable storing the info for which filter autocomplete results were\n       * requested\n       * @type {number}\n       */\n      autocompleteIndex: -1,\n      originalMainFilter: null,\n      /**\n       * variable to control showing of advanced search form in mode 'form'\n       * @type {boolean}\n       */\n      formOpen: true,\n      /**\n       * internal representation of formFilterValues in order to be able to modify\n       * @type {Object}\n       */\n      formFilterValuesInt: {},\n      /**\n       * store filter values to see if filter values changed before triggering search\n       * @type {Object}\n       */\n      originalFilterValues: null,\n      /**\n       * render BaseForm with delay to reduce flickering and flinching\n       * @type {boolean}\n       */\n      formMounted: false,\n      /**\n       * resize observer for specific element (instead of window)\n       * (only mode `form`)\n       */\n      resizeObserver: null,\n      /**\n       * button text should only be shown if enough space is available\n       * (only mode `form`)\n       */\n      showAdvancedSearchButtonText: true,\n      /**\n       * variable to contain assistive text to inform user of actions\n       * @type {string}\n       */\n      assistiveTextNotification: '',\n    };\n  },\n  computed: {\n    amendedFormProps() {\n      // if the prop is false - don't bother any further and just return\n      // the formProps as is\n      if (!this.interpretFormChipsLabelAsHtml) {\n        return this.formProps;\n      }\n      // else get the fieldProps out of formProps\n      const fieldProps = this.formProps.fieldProps || {};\n      // now iterate over the fields and add (or overwrite) the `interpretChipsLabelAsHtml`\n      // prop\n      const updatedFormFieldProps = this.renderFormChipsLabelAsHtml.reduce((prev, renderProp) => ({\n        ...prev,\n        ...this.addNewPropertyValueToNestedObject(\n          renderProp,\n          fieldProps || {},\n          'interpretChipsLabelAsHtml',\n          true,\n          // individually set fields should always have priority\n          // over `interpretFormChipsLabelAsHtml`\n          false,\n        ),\n      }), {});\n\n      return {\n        // add all other specified form props\n        ...this.formProps,\n        // and the modified fieldprops\n        fieldProps: {\n          // also don't lose the field props of non-chips fields or not\n          // modified ones\n          ...fieldProps,\n          // and add the modified ones\n          ...updatedFormFieldProps,\n        },\n      };\n    },\n    /**\n     * store the loading state of every filter\n     *\n     * @returns {boolean[]}\n     */\n    filtersLoadingState() {\n      return [\n        ...this.appliedFiltersInt\n          // also checking for mainSearch template reference here because if it is not\n          // rendered yet we will get a hydration mismatch in nuxt\n          .map((filter, index) => (this.mainSearch && this.autocompleteIndex === index)),\n        // add one at the end for main search field (not added to applied filters array yet)\n        this.mainSearch && this.autocompleteIndex === this.appliedFiltersInt.length,\n      ];\n    },\n    /**\n     * the actually displayed filter categories (visible in the filter drop down for mode 'list')\n     * @returns {Filter[]}\n     */\n    displayedFilters() {\n      // filter filters with property hidden true\n      const displayed = [...this.filterList].filter(f => !f.hidden);\n      // sort them\n      return sort(displayed, this.labelPropertyName.filter);\n    },\n    /**\n     * main filter is always added to the emitted filter array last to maintain same order\n     *  to what is rendered (main filter lowest) so we need to get the last filter index\n     * @returns {number}\n     */\n    mainFilterIndex() {\n      const lastFilterIndex = this.appliedFilters.length - 1;\n      return lastFilterIndex > 0 ? lastFilterIndex : 0;\n    },\n    /**\n     * transform values to collapsed form and back\n     */\n    collapsedFiltersArray: {\n      /**\n       * use formFieldValuesInt to create the correct structure for BaseCollapsedFilterRow\n       * @returns {{\n       *  filter_values: { values: Object[], fieldType: string, fieldId: string },\n       *  label: string,\n       *  id: string,\n       *  }[]}\n       */\n      get() {\n        return Object.entries(this.formFilterValuesInt)\n          // only use filters that have values\n          .filter(([, value]) => hasData(value))\n          // sort the values in the order of the form so the collapsed display has the same order\n          .sort(([key1], [key2]) => {\n            if (this.formFilterList[key1] && this.formFilterList[key2]\n              && this.formFilterList[key1]['x-attrs'].order > this.formFilterList[key2]['x-attrs'].order) {\n              return 1;\n            }\n            return -1;\n          })\n          // map data to collapsed filter array structure\n          .map(([key, value]) => {\n            // get the OpenAPI json field information for the field in question\n            const formFilterData = this.formFilterList[key];\n            // check here if field is repeatable\n            const isRepeatableField = formFilterData.type === 'array' && !formFilterData['x-attrs'].field_type.includes('chips');\n            // if value list is not already an array (because it is a repeatable field) make it an array\n            const valueList = isRepeatableField ? value : [value];\n            return valueList.map((repeatableEntry, index) => ({\n              // label that will be displayed on top of each collapsed filter\n              labelInternal: formFilterData.title,\n              // add a special id that allows to identify repeatable fields (applied in reverse mapping\n              // ~line 555)\n              idInternal: `${key}${isRepeatableField ? `-group-${index}` : ''}`,\n              // the actual filter values and filter information for each field (important for field groups)\n              filter_values: this.getCollapsedFilterValue(repeatableEntry, formFilterData, key),\n            }));\n          })\n          .flat();\n      },\n      /**\n       * maps changes that were made to collapsed filters back to formFilterValuesInt\n       * @param {{ filter_values: Object[]|Object[[]], label: string, id: string, type: string|string[] }[]} val - changed collapsed filter values\n       */\n      set(val) {\n        // loop through every collapsed filter array value and create a form filter values compatible\n        // object structure out of it again\n        this.formFilterValuesInt = val.reduce((prev, filter) => {\n          // necessary because of field groups to remove index (added in line 538) from id\n          // get actual field id and indicator if field was repeatable field\n          const [, filterId, groupMatch] = filter.idInternal.match(/(.*?)(-group-\\d*)?$/);\n          // get the form field data for the id\n          const filterData = this.formFilterList[filterId];\n          // get the correctly mapped filter values\n          const filterValues = this.setFormFilterValues(filter.filter_values, filterData);\n          // if field is repeatable - check if there are already values field into the object property\n          // if yes store them in a value to be able to concat or use an empty array\n          const previousValues = groupMatch && prev && prev[filterId] ? prev[filterId] : [];\n          return {\n            ...prev,\n            // if field is repeatable join the previous values with the new values otherwise just\n            // set currently retrieved values\n            [filterId]: groupMatch ? previousValues.concat(filterValues) : filterValues,\n          };\n        }, {});\n        // trigger search after filters changed\n        this.search();\n      },\n    },\n    renderFormChipsLabelAsHtml() {\n      // first get all form field props\n      const { fieldProps } = this.formProps;\n      // if no fieldProps were specified just use the prop value\n      if (!fieldProps) return this.interpretFormChipsLabelAsHtml;\n      // else we need to check if prop `renderChipsLabelAsHtml` was specified for\n      // a chips input field - done via recursive (because of subforms) function\n      const fieldsToSetTrue = this.filterHtmlRenderFields(this.formFilterList);\n\n      // check if values were set for individual fields, otherwise fall back\n      // to the prop value\n      return fieldsToSetTrue.length ? fieldsToSetTrue : this.interpretFormChipsLabelAsHtml;\n    },\n    /**\n     * advanced button description for mode `form`\n     * @returns {string}\n     */\n    advancedButtonDescription() {\n      // if value was not set for any reason just return an empty string\n      if (!this.assistiveText.advancedButtonDescription) return '';\n      return this.assistiveText.advancedButtonDescription\n        .replace('{state}', this.assistiveText.formState[this.formOpen ? 'close' : 'open']);\n    },\n    /**\n     * create a list of the filters with a unique id for RENDERING and HTML UPDATING\n     * purposes (v-for key needs to be permanent)\n     * created separate variable so appliedFiltersInt can be kept in\n     * sync with appliedFilters prop without extra prop causing problems in comparison\n     * @returns {(Filter&{uid: string})[]}\n     */\n    appliedFilterKeys() {\n      // if an internal id already exists use that one - if filters were set from outside\n      // add an internal id (for keying purposes)\n      // it is made sure the index is always correct by also handling appliedFilterKeys\n      // in the removeFilter function (add for addFilterRow it is ok because a new\n      // row can only be appended at the end of the list\n      return this.appliedFiltersInt.map((filter, index) => this.appliedFilterKeys?.[index] || createId());\n    },\n  },\n  watch: {\n    /**\n     * watch prop autocompleteResults to assign it to the correct filter row\n     */\n    autocompleteResults(val) {\n      // check if autocomplete is active for any field ( > -1 )\n      if (this.autocompleteIndex >= 0) {\n        // if yes set the results on the filter row active\n        this.filtersAutocompleteResults[this.autocompleteIndex] = [...val];\n        this.autocompleteIndex = -1;\n      }\n    },\n    /**\n     * have appliedFilters in sync with parent to be able to set them from outside\n     */\n    appliedFiltersInt: {\n      handler(val) {\n        // check if val is actually different from prop value\n        if (JSON.stringify(val) !== JSON.stringify(this.appliedFilters.slice(1))) {\n          // if yes - inform parent\n          this.$emit('update:applied-filters', JSON.parse(JSON.stringify([...val, this.mainFilter])));\n        }\n      },\n      deep: true,\n    },\n    /**\n     * have appliedFilters in sync with parent to be able to set them from outside\n     */\n    appliedFilters: {\n      handler(val) {\n        // check if value is different from internal value\n        if (val\n          && JSON.stringify(val.slice(0, -1)) !== JSON.stringify(this.appliedFiltersInt)) {\n          // if yes - update internal value\n          [, ...this.appliedFiltersInt] = JSON.parse(JSON\n            .stringify([val, ...val.slice(0, -1)]));\n        }\n        // also check if main filter is different separately!\n        if (val && val.length >= 1\n          && JSON.stringify(this.mainFilter) !== JSON.stringify(val[this.mainFilterIndex])) {\n          [this.mainFilter] = JSON.parse(JSON.stringify(val.slice(-1)));\n        } else if (!val || val < 1) {\n          this.mainFilter = JSON.parse(JSON.stringify(this.defaultFilter));\n        }\n      },\n      immediate: true,\n    },\n    /**\n     * watch main filter since changes are not directly handled via update:applied-filters\n     * event and trigger search if anything changed\n     * @param {Filter} val - the updated main filter\n     */\n    mainFilter(val) {\n      // make sure mainFilter exists and has property filter_values\n      if (val && val.filter_values) {\n        // store values to compare in variables\n        const mainFilterHasData = hasData(val.filter_values);\n        // for original filter also check right here if property filter_values actually\n        // exists\n        const originalMainFilterHasData = !!this.originalMainFilter\n          && !!this.originalMainFilter.filter_values\n          && hasData(this.originalMainFilter.filter_values);\n        // now check a) if originalMainFilter exists already and\n        // b) filter itself has switched (and there are actually data to search for)\n        // c) original data and current data diverge (only one of them does not have data)\n        // d) or both have data but data are different from each other\n        if (this.originalMainFilter\n          && ((mainFilterHasData && this.originalMainFilter[this.identifierPropertyName.filter]\n              !== val[this.identifierPropertyName.filter])\n            || mainFilterHasData !== originalMainFilterHasData\n            || (mainFilterHasData && originalMainFilterHasData\n              && (JSON.stringify(this.originalMainFilter.filter_values\n                !== JSON.stringify(val.filter_values)))))) {\n          // if so - update original data\n          this.originalMainFilter = JSON.parse(JSON.stringify(this.mainFilter));\n          // and trigger search\n          this.search(true);\n        }\n      }\n      /**\n       * inform parent of changes in applied filters - event emitted for mode `list`\n       *\n       * @event update:applied-filters\n       * @param {Filter[]} - the list of updated applied filters\n       */\n      this.$emit('update:applied-filters', JSON.parse(JSON.stringify([...this.appliedFiltersInt, val])));\n      // also emit updated form filter values at this point\n      this.$emit('update:form-filter-values', JSON.parse(JSON.stringify({ ...this.formFilterValuesInt, default: this.mainFilter.filter_values })));\n    },\n    /**\n     * have formFilterValues in sync with parent to be able to set them from outside\n     */\n    formFilterValuesInt: {\n      handler(val) {\n        // get filters without default first to ensure comparability\n        const filtersWithoutDefault = JSON.parse(JSON.stringify(this.formFilterValues));\n        delete filtersWithoutDefault.default;\n        // check if val is actually different from prop value\n        if (JSON.stringify(val) !== JSON.stringify(filtersWithoutDefault)) {\n          // if yes - inform parent\n          /**\n           * inform parent of form filter value changes - event emitted for mode `form`\n           * @event update:form-filter-values\n           * @param {Object} - a form filter values object with a property for each filter field - main filter values\n           *  are available under the default property\n           *\n           */\n          this.$emit('update:form-filter-values', JSON.parse(JSON.stringify({ ...val, default: this.mainFilter.filter_values })));\n        }\n      },\n      deep: true,\n    },\n    /**\n     * have formFilterValues in sync with parent to be able to set them from outside\n     */\n    formFilterValues: {\n      handler(val) {\n        if (this.mode === 'form') {\n          // check if value is different from internal value\n          if (val\n            && JSON.stringify(val) !== JSON.stringify({\n              ...this.formFilterValuesInt,\n              default: this.mainFilter.filter_values,\n            })) {\n            // remove the default key from the form filter values that should fill form\n            // eslint-disable-next-line no-unused-vars\n            const { default: _, ...filterValuesNoMain } = val;\n            // update internal values\n            this.formFilterValuesInt = JSON.parse(JSON.stringify(filterValuesNoMain));\n            // set default property to mainFilter.filter_values\n            this.mainFilter.filter_values = val.default || [''];\n            // trigger search with updated values\n            this.search();\n          }\n        }\n      },\n      immediate: true,\n    },\n    advancedFormOpen: {\n      handler(val) {\n        this.formOpen = val;\n      },\n      immediate: true,\n    },\n    formOpen(val) {\n      /**\n       * in mode `form` when 'advanced search' button was clicked\n       * @event update:advanced-form-open\n       * @type {boolean}\n       */\n      this.$emit('update:advanced-form-open', val);\n    },\n    /**\n     * function to automatically reset the assistiveTextNotification\n     * after using it\n     * @param {string} val\n     */\n    assistiveTextNotification(val) {\n      // setting the value will trigger the screenreader\n      if (val) {\n        setTimeout(() => {\n          // after that text can be removed again\n          this.assistiveTextNotification = '';\n        }, 300);\n      }\n    },\n  },\n  created() {\n    // check if mainFilter was already set (e.g. from outside)\n    if (!this.mainFilter) {\n      // if not set default filter\n      this.mainFilter = JSON.parse(JSON.stringify(this.defaultFilter));\n    }\n    // copy these filter values to later be able to determine if filters changed before\n    // triggering search\n    this.originalMainFilter = JSON.parse(JSON.stringify(this.mainFilter));\n  },\n  mounted() {\n    // only add observer for mode `form`\n    if (this.mode === 'form') {\n      // to listen to element with instead of window width create an observer!\n      this.initObserver();\n    }\n  },\n  beforeUnmount() {\n    if (this.resizeObserver) this.resizeObserver.unobserve(this.$refs.searchContainer);\n  },\n  methods: {\n    extractNestedPropertyValue,\n    /**\n     * GENERAL FUNCTIONALITIES\n     */\n\n    /**\n     * initialize resize observer to steer advanced search button appearance\n     */\n    initObserver() {\n      const resizeObserver = new ResizeObserver(debounce(50, ([container]) => {\n        this.showAdvancedSearchButtonText = container.contentRect.width >= 460;\n      }));\n      resizeObserver.observe(this.$refs.searchContainer);\n      this.resizeObserver = resizeObserver;\n    },\n    /**\n     * @param {string} input - the search string to autocomplete\n     * @param {Filter} filter - the filter the autocomplete was triggered for\n     * @param {number} index - the index of the filter\n     */\n    fetchAutocomplete({ input, filter }, index) {\n      if (input) {\n        // if input string present set autocomplete variable to correct filter row\n        this.autocompleteIndex = index;\n      } else {\n        // else reset the autocomplete results\n        this.filtersAutocompleteResults[index] = [];\n      }\n      // stil emit fetch-autocomplete no matter if input string present or not to give\n      // parent opportunity to also update\n      /**\n       * inform parent to fetch autocomplete data for the provided filter\n       *\n       * @event fetch-autocomplete\n       * @type {Object} - object with the following properties:\n       * @property {string} searchString - the string to autocomplete\n       * @property {Filter} filter - the filter object\n       * @property {number} index - the filter index of all filters (main and applied)\n       */\n      this.$emit('fetch-autocomplete', { searchString: input, filter, index });\n    },\n    /**\n     * search function\n     * @param {boolean} alwaysTrigger - set true if search should be triggered irrespective of\n     *  appliedFiltersInt changes (needed for changes in mainFilter which is checked in the\n     *  mainFilter watcher already)\n     */\n    search(alwaysTrigger = false) {\n      // get the correct filter values list according to component mode\n      const modeFilterList = this.mode === 'form' ? this.formFilterList : this.filterList;\n      // define variable to store modified filters list to be emitted\n      let searchFilterList = [];\n      if (this.mode === 'form') {\n        searchFilterList = Object.entries(this.formFilterValuesInt)\n          // also only keep the filters that have filter values\n          .filter(([, filterValues]) => hasData(filterValues))\n          .map(([filterKey, filterValues]) => ({\n            [this.identifierPropertyName.filter]: filterKey,\n            type: modeFilterList[filterKey]?.['x-attrs']?.field_type ?? 'text',\n            // only keep filter values that actually have values (relevant for groups!)\n            filter_values: typeof filterValues === 'object' && filterValues.length\n            && !modeFilterList[filterKey]?.type.includes('chips')\n              ? filterValues.filter(filterValue => hasData(filterValue)) : filterValues,\n          }));\n      } else {\n        searchFilterList = this.appliedFiltersInt\n          // and only keep the properties relevant for search\n          .map(filter => ({\n            [this.identifierPropertyName.filter]: filter[this.identifierPropertyName.filter],\n            type: filter.type,\n            filter_values: filter.filter_values,\n          }));\n      }\n      // if there are changes in filters or main filter trigger search (=if alwaysTrigger was\n      // set true in mainFilter watcher)\n      if (alwaysTrigger || JSON.stringify(this.originalFilterValues) !== JSON\n        .stringify(searchFilterList)) {\n        // update the original value\n        this.originalFilterValues = JSON.parse(JSON.stringify(searchFilterList));\n        // also minimize main filter\n        const minMainFilter = {\n          [this.identifierPropertyName.filter]: this.mainFilter[this.identifierPropertyName.filter],\n          type: this.mainFilter.type,\n          filter_values: this.mainFilter.filter_values,\n        };\n        /**\n         * inform parent that search should be triggered\n         *\n         * @event search\n         * @param {Filter[]} - the updated list of applied filters - last filter in the list is always the main\n         *  filter (relevant especially for mode `form`)\n         */\n        this.$emit('search', [...searchFilterList, minMainFilter]);\n      }\n    },\n    /**\n     * MODE 'LIST' FUNCTIONALITIES\n     */\n\n    /**\n     * function to add a filter row after '+' icon was triggered\n     */\n    addFilterRow({ filter, input }) {\n      // first handle remaining input and add it to filter values if necessary\n      // therefore have separate variable and assign the original values first (in case no\n      // modifications are necessary)\n      let newFilterValues = filter.type.includes('date') ? filter.filter_values\n        : [...filter.filter_values];\n      // have variable for search trigger in case additional values are added and should trigger\n      // search\n      let triggerSearch = false;\n      // now check if type is text and the current value saved in filter does not equal text input\n      if (filter.type === 'text' && input.trim() && (!filter.filter_values || !filter.filter_values.length\n        || this.mainFilter.filter_values[0] !== input.trim())) {\n        // in that case assign new value and set search trigger true\n        newFilterValues = [input];\n        triggerSearch = true;\n        // else if type is freetext chips add the value at the end of the array\n      } else if (filter.type === 'chips' && filter.freetext_allowed && input.trim()) {\n        newFilterValues = [\n          ...filter.filter_values,\n          {\n            [this.labelPropertyName.autocompleteOption]: input,\n          },\n        ];\n        // also here triger search after\n        triggerSearch = true;\n      }\n      // now finally add filter to internal filter list\n      this.appliedFiltersInt.push({\n        ...filter,\n        filter_values: newFilterValues,\n      });\n      // and reset the main filter\n      this.mainFilter = {\n        ...this.defaultFilter,\n      };\n      // and store the main filter to compare to later\n      this.originalMainFilter = JSON.parse(JSON.stringify(this.mainFilter));\n      // now check if search should be triggered\n      if (triggerSearch) {\n        this.search();\n      }\n      // make sure the main search input element was found\n      if (this.inputElement) {\n        // and if yes focus the 'new' last row\n        this.inputElement.focus();\n      }\n    },\n    /**\n     * remove filter after 'x' was triggered\n     * @param {Filter} filter - the filter to remove\n     * @param {number} index - the index of the filter\n     */\n    removeFilter(filter, index) {\n      // when removing a filter row also update the keyed list (responsible for the correct\n      // rendering (html updating) and do it FIRST because appliedFilterKeys RELIES on\n      // appliedFiltersInt and if appliedFiltersInt is updated first the internal id (idInt)\n      // will be calculated incorrectly for appliedFilterKeys\n      this.appliedFilterKeys.splice(index, 1);\n      // now also update the applied filters list (handling the values displayed for a row)\n      this.appliedFiltersInt.splice(index, 1);\n      // trigger search to update search results\n      this.search();\n    },\n    /**\n     * for mode 'list'\n     * function called when a filter object within a filter row changes\n     * @param {Filter} filter - the filter that was altered\n     * @param {number} index - the index of the filter\n     */\n    updateFilter(filter, index) {\n      this.appliedFiltersInt[index] = JSON.parse(JSON.stringify(filter));\n      // trigger search to update search results\n      this.search();\n    },\n\n    /**\n     * MODE 'FORM' FUNCTIONALITIES\n     */\n\n    /**\n     * function called when an option was selected from main search autocomplete OR on\n     *  search input TAB keydown\n     *\n     * @param {Object} entry - the selected option\n     * @param {string} collectionId - the option category selected - this needs to match a\n     *  formFilter id\n     */\n    fillOptionToForm({ entry, collectionId }) {\n      // check if mode is form and if collection id is present\n      // (otherwise value is default filter string input)\n      if (this.mode === 'form' && collectionId\n        // and if option is already included in the selected options to prevent double key problems\n        && !this.formFilterValuesInt[collectionId]\n          ?.map(selectedOption => selectedOption[this.identifierPropertyName.formInputs])\n          .includes(entry[this.identifierPropertyName.autocompleteOption])) {\n        // get the filter field information if there is any\n        const fieldInformation = this.formFilterList[collectionId];\n        // check if there is actual field information --> default filter is not part of\n        // swagger list! so all but default filter will go here!\n        if (fieldInformation) {\n          const fieldXAttrs = fieldInformation['x-attrs'];\n          // check the type of field that the value should be added to (we assume the only possibilities\n          // are chips or text - other types are currently NOT implemented and would need to be added here!)\n          if (fieldXAttrs.field_type === 'chips') {\n            // in order to be able to set the correct properties for the chip display in the input field\n            // we might need to map the label and id properties of the autocomplete option to the label and\n            // id properties of the input field - since an individual option for a field might have been\n            // set via fieldProps - we need to check for that first\n            const fieldProps = this.formProps.fieldProps?.[collectionId] || {};\n            // check if label prop was set otherwise use the default form input one\n            const labelProp = fieldProps.labelPropertyName\n              || this.labelPropertyName.formInputs;\n            // check if id prop was set otherwise use the default form input one\n            const idProp = fieldProps.identifierPropertyName\n              || this.identifierPropertyName.formInputs;\n            // map the information from the search autocomplete to the chips form field\n            // required values\n            const chipsFormFieldValue = {\n              // map search autocomplete result to chips form field required values\n              [labelProp]: entry[this.labelPropertyName.autocompleteOption],\n              [idProp]: entry[this.identifierPropertyName.autocompleteOption],\n              // HOWEVER - in order to enable customization of the properties used in the front\n              // end - e.g. to add discriminatory terms html we also leave the rest of the\n              // object properties and actually give them PRIORITY over the newly created ones!\n              // (so e.g. if the property `displayLabel` was already added to the autocomplete option\n              // with the appropriate tags and styling then this will not be overwritten by\n              // entry[this.labelPropertyName.autocompleteOption] but be retained\n              ...entry,\n            };\n            // for multi chips - add value to array\n            if (fieldInformation.type === 'array') {\n              // check if property exists already in formFilterValuesInt\n              if (this.formFilterValuesInt[collectionId]) {\n                this.formFilterValuesInt[collectionId].push(chipsFormFieldValue);\n              } else {\n                this.formFilterValuesInt[collectionId] = [chipsFormFieldValue];\n              }\n              // for single chips - replace value\n            } else if (fieldInformation.type === 'object') {\n              this.formFilterValuesInt[collectionId] = chipsFormFieldValue;\n            }\n          } else if (!fieldXAttrs || fieldXAttrs.field_type === 'text') {\n            this.formFilterValuesInt[collectionId] = entry[this.labelPropertyName.autocompleteOption]\n              ?? entry;\n          }\n          // main filter filter values should remain empty\n          this.mainFilter.filter_values = [];\n          // announce to screen reader user that field was added to advanced search form\n          // if the appropriate text was set\n          if (this.assistiveText.autocompleteOptionFilledToForm) {\n            // get option label from entry param\n            const optionLabel = entry[this.labelPropertyName.autocompleteOption];\n            // and field label from fieldInformation\n            const fieldLabel = fieldInformation.title;\n            // assemble announcement\n            this.announcement = this.assistiveText.autocompleteOptionFilledToForm\n              .replace('{optionLabel}', optionLabel)\n              .replace('{fieldLabel}', fieldLabel);\n          }\n\n          // this does not trigger an update event from BaseForm so search needs to be triggered manually here\n          this.search();\n        } else {\n          // if it is main filter set the value to main filter instead\n          this.mainFilter.filter_values = [entry];\n          // and also update original filter with newly set data\n          this.originalMainFilter = JSON.parse(JSON.stringify(this.mainFilter));\n          // this does not trigger an update event from BaseForm so search needs to be triggered manually here\n          // since main filter is not evaluated in filter comparison set alwaysTrigger true\n          this.search(true);\n        }\n      }\n    },\n    /**\n     * function called from form if one of the form fields needs autocomplete\n     *\n     * @param {Object} params - see event for object properties sent to parent\n     */\n    fetchFormAutocomplete(params) {\n      /**\n       * event emitted when a form drop down (e.g. chips input field) needs autocomplete\n       *\n       * @event fetch-form-autocomplete\n       *\n       * @property {string} value - the string to autocomplete\n       * @property {string} name - the name of the field\n       * @property {string} source - the url to request the data from\n       * @property {?string} equivalent - string specified for related fields. e.g. for contributor roles equivalent is `contributor`\n       * @property {?string[]} parentFields - in case the autocomplete event originates from a subform the subform id's (field property names) are specified in this array (most nested property last)\n       */\n      this.$emit('fetch-form-autocomplete', params);\n    },\n    /**\n     * for mode 'form'\n     * update the form filters when an event is received from form that values have changed\n     * @param {Object} newFilterValueList - the new filter values object\n     */\n    updateFormFilters(newFilterValueList) {\n      this.formFilterValuesInt = JSON.parse(JSON.stringify(newFilterValueList));\n      this.search();\n    },\n    /**\n     * function called by BaseCollapsedFilter row if 'x' was clicked to remove all filters\n     */\n    removeAllFilters() {\n      // reset form filter values\n      this.formFilterValuesInt = {};\n      this.assistiveTextNotification = this.assistiveText.collapsedFilterRowRemovedNotification || '';\n      // trigger search without filters\n      this.search();\n    },\n    /**\n     * reduce the flickering and flinching from base form fields rendering by\n     *  only making the element visible after component mount and additionally\n     *  apply a timeout\n     */\n    formIsMounted() {\n      setTimeout(() => {\n        this.formMounted = true;\n      }, 200);\n    },\n    /**\n     * function triggered when 'advanced search' button is clicked in 'form' mode\n     */\n    openAdvancedSearch() {\n      // close the main search autocomplete drop down since this is not in user focus\n      // anymore\n      this.$refs.mainSearch.isActive = false;\n      // toggle form\n      this.formOpen = !this.formOpen;\n    },\n    /**\n     * function to retrieve the filter values in reduced form the way CollapsedFilterRow needs them\n     * @param {any} values - the form field values\n     * @param {Object} fieldData - the OpenAPI json field information\n     * @param {string} fieldId - the id of the field to transform\n     * @param {string[]} parentFields - if field is a field group we also need the parent field name(s)\n     *  (in theory there could be many but BaseAdvancedSearch is currently only supporting one nesting level)\n     * @returns {[string, unknown]|[{label: string}]|string|{label: *}[]|boolean[]|[{label: (string|string)}]|*}\n     */\n    getCollapsedFilterValue(values, fieldData, fieldId, parentFields = []) {\n      const fieldType = fieldData['x-attrs'].field_type;\n      if (fieldType === 'integer' || fieldType === 'float' || typeof values === 'number') {\n        return {\n          values: [{\n            labelInternal: values.toString(),\n          }],\n          fieldId,\n          fieldType,\n        };\n      }\n      if (fieldType === 'boolean' || typeof values === 'boolean') {\n        return {\n          values: [{\n            labelInternal: values,\n          }],\n          fieldId,\n          fieldType,\n        };\n      }\n      if (fieldType === 'text' || fieldType === 'autocomplete' || typeof values === 'string') {\n        let formattedLabel = values;\n        if (fieldType === 'date' && values) {\n          // if type is date we need to parse the storage date to display values also considering\n          // possible minus\n          formattedLabel = this.formatToDisplayDate(values);\n        }\n        return {\n          values: [{\n            // if fieldType is date convert to de date locale for display\n            labelInternal: formattedLabel,\n          }],\n          fieldId,\n          fieldType,\n        };\n      }\n      if (fieldType === 'chips') {\n        // check if general property names were overwritten for the specific field\n        const fieldProps = extractNestedPropertyValue(\n          parentFields.length ? [fieldId].concat(parentFields).join('.') : fieldId,\n          this.formProps.fieldProps,\n        );\n        const labelProp = fieldProps?.labelPropertyName\n          || this.labelPropertyName.formInputs;\n        const idProp = fieldProps?.identifierPropertyName\n          || this.identifierPropertyName.formInputs;\n        return {\n          values: values.map((chipValue) => {\n            // do not delete additional properties the chip might have\n            const additionalProperties = typeof chipValue === 'object' ? chipValue : {};\n            return ({\n              labelInternal: chipValue[labelProp] ?? chipValue,\n              idInternal: chipValue[idProp] || '',\n              ...additionalProperties,\n            });\n          }),\n          fieldId,\n          fieldType,\n        };\n      }\n      if (fieldType === 'group') {\n        return {\n          values: Object.entries(values)\n            .reduce((prev, [fieldKey, fieldValue]) => {\n              // add an array for each field in the group\n              prev.push(this.getCollapsedFilterValue(\n                fieldValue,\n                // depending if group is repeatable or not get to properties attribute\n                fieldData.items ? fieldData.items.properties[fieldKey] : fieldData.properties[fieldKey],\n                fieldKey,\n                [fieldKey].concat(parentFields),\n              ));\n              return prev;\n            }, []),\n          fieldType,\n          fieldId,\n        };\n      }\n      // any date or time range field\n      if (fieldType === 'date' && typeof values !== 'string') {\n        return {\n          values: Object.values(values)\n            .map(chipValue => ({\n              // convert to de date locale for display\n              labelInternal: chipValue ? this.formatToDisplayDate(chipValue) : '',\n            })),\n          fieldId,\n          // BaseCollapsedRow needs information if date is type daterange, timerange or datetime\n          // so alter to 'date' and 'time' for daterange and timerange respectively and 'datetime'\n          // for datetime.\n          fieldType: Object.keys(values).reduce((prev, key) => {\n            const currentType = key.split('_')[0];\n            return currentType !== prev ? prev + currentType : prev;\n          }, ''),\n        };\n      }\n      // NOT COVERED: multiline and chips below\n      return values;\n    },\n    formatToDisplayDate(storageDate) {\n      const { groups: { minus, year, month, day } = {} } = storageDate\n        .match(/((?<minus>-)?(?<year>\\d{4})-?(?<month>\\d{2})?-?(?<day>\\d{2})?)/) || {};\n      return year ? `${day ? `${day}.` : ''}${month ? `${month}.` : ''}${minus || ''}${year}` : '';\n    },\n    formatToStorageDate(storageDate) {\n      const { groups: { minus, year, month, day } = {} } = storageDate\n        .match(/(?<day>\\d{2})?\\.?(?<month>\\d{2})?\\.?(?<minus>-)?(?<year>\\d{4})/) || {};\n      return year ? `${minus || ''}${year}${month ? `-${month}` : ''}${day ? `-${day}` : ''}` : '';\n    },\n    /**\n     * function to transform collapsed values to form field values (necessary if something changed\n     * in collapsed values, e.g. a filter value was removed)\n     * @param {{ values: Object[], fieldId: string, fieldType: string }} collapsedValues - the updated collapsed\n     *  values coming from collapsed filter row\n     * @param {Object} filterData - the relevant OpenAPI form field information\n     * @param {string[]} parentFields - if field is a field group we also need the parent field name(s)\n     *  (in theory there could be many but BaseAdvancedSearch is currently only supporting one nesting level)\n     * @returns {any} - value returned depending on the filter type\n     */\n    setFormFilterValues(collapsedValues, filterData, parentFields = []) {\n      // get the relevant information out of collapsed values\n      const { values, fieldType, fieldId } = collapsedValues;\n      // case string\n      if (filterData.type === 'string') {\n        // special case date that needs to transform display to storage date format again\n        if (fieldType === 'date') {\n          return this.formatToStorageDate(values[0].labelInternal);\n        }\n        return values[0].labelInternal;\n      }\n      // case boolean value\n      if (filterData.type === 'boolean') {\n        return values[0].labelInternal;\n      }\n      // case number value\n      if (filterData.type === 'integer' || filterData.type === 'float') {\n        return Number(values[0].labelInternal);\n        // date could be string if it is just a single date or an object in all other cases\n      }\n      // case date field (not string)\n      if ((fieldType.includes('date') || fieldType.includes('time')) && filterData.type === 'object') {\n        const objectProperties = Object.keys(filterData.properties);\n        return values.reduce((valueObject, value, index) => ({\n          ...valueObject,\n          [objectProperties[index]]: this.formatToStorageDate(value.labelInternal),\n        }), {});\n      }\n      // case chips input field\n      if (fieldType.includes('chips')) {\n        // we need to take into consideration that custom label and identifier property names\n        // might have been set for a specific form field - so we need to check `formProps.fieldProps`\n        // (or the corresponding nested field for type 'group') for that field first and use these\n        // values if present\n        const fieldProps = extractNestedPropertyValue(\n          parentFields.length ? [fieldId].concat(parentFields).join('.') : fieldId,\n          this.formProps.fieldProps,\n        );\n        const labelProp = fieldProps?.labelPropertyName\n          || this.labelPropertyName.formInputs;\n        const idProp = fieldProps?.identifierPropertyName\n          || this.identifierPropertyName.formInputs;\n        return values.filter(filterValue => !!filterValue.labelInternal)\n          .map((filterValue) => {\n            // in order to keep any additional properties the chips entry might have, clone\n            // the object and remove internally added variables again\n            const additionalProperties = JSON.parse(JSON.stringify(filterValue));\n            delete additionalProperties.labelInternal;\n            delete additionalProperties.idInternal;\n            return ({\n              // and add it to the values that are returned\n              ...additionalProperties,\n              // apart from the labelProperty and the identifierProperty\n              [labelProp]: filterValue.labelInternal,\n              [idProp]: filterValue.idInternal,\n            });\n          });\n      }\n      // case repeatable fields where every repeated field or field group is a separate filter entry\n      if (!fieldType.includes('chips') && filterData.type === 'array') {\n        return this.setFormFilterValues(\n          collapsedValues,\n          filterData.items,\n        );\n      }\n      // case field groups\n      if (fieldType === 'group'\n        && filterData.type === 'object') {\n        return values\n          .filter(value => hasData(value.values))\n          .reduce((o, k) => ({\n            ...o,\n            [k.fieldId]: this.setFormFilterValues(\n              k,\n              filterData.properties[k.fieldId],\n              [k.fieldId].concat(parentFields),\n            ),\n          }), {});\n      }\n      return null;\n    },\n    filterHtmlRenderFields(formFieldInfo, parentFields = []) {\n      // get the field props needed later\n      const { fieldProps } = this.formProps;\n      // iterate over all form fields given in formFieldInfo\n      return Object.entries(formFieldInfo)\n        .reduce((prev, [key, values]) => {\n          // get the field type from the x attributes\n          const { field_type: fieldType } = values['x-attrs'] ? values['x-attrs'] : {};\n          // check if form fields are nested (subform)\n          if (fieldType === 'group') {\n            // and recursively iterate over these fields as well\n            const subFields = this.filterHtmlRenderFields(\n              values.properties || values.items.properties,\n              [key].concat(parentFields),\n            );\n            // if fields with `interpretChipsLabelAsHtml` `true` are found\n            // add them in the form { [key]: ['subField1', 'SubField2'] }\n            return subFields.length ? prev.concat({\n              [key]: subFields,\n            }) : prev;\n          }\n          // only add fields that are type chips\n          if (fieldType === 'chips') {\n            // get the fieldProps set for that specific field - if it is a nested field we\n            // need to extract them with the function below - else we can use fieldProps directly\n            const keyProps = ((parentFields.length\n              ? extractNestedPropertyValue(parentFields.join('.'), fieldProps) : fieldProps) || {})[key];\n            // now check if field key should be added to the list - 2 possibilities to add:\n            // a) prop `interpretFormChipsLabelAsHtml` is `false` - and the fieldProp for that specific\n            //  field is set\n            // b) prop `interpretFormChipsLabelAsHtml` was set `true` to cover all fields and\n            //  specifically exclude this one\n            if ((!this.interpretFormChipsLabelAsHtml && keyProps?.interpretChipsLabelAsHtml)\n              || (this.interpretFormChipsLabelAsHtml && (!keyProps\n                || !Object.keys(keyProps).includes('interpretChipsLabelAsHtml') || keyProps.interpretChipsLabelAsHtml))) {\n              return prev.concat(key);\n            }\n          }\n          // if any of the conditions fail just return the list unaltered\n          return prev;\n        }, []);\n    },\n    /**\n     * a function to add a new property to a nested object\n     *\n     * @param {string|Object} renderProp - this is either a string - then an object\n     *  with `previousFieldProps` and this property will be created, or an object in\n     *  the style of { [parentProperty]: ['childProp1', 'childProp2'] } - this object\n     *  can also be nested deeper - 'childProp2' could instead also be an object in the\n     *  style above again\n     * @param {Object} fieldProps - an object for all fields including `renderProp` that contains\n     *  other properties `renderProp` or [renderProp.key] should receive\n     *  so: { [renderProp]: { renderPropProperties } }\n     * @param {string} propertyName - the name of the property to be added or overwritten\n     * @param {*} propertyValue - the value of the property to be added or overwritten\n     * @param {boolean} [overwritePreviousValues=true] - define if a preexisting value for\n     *  `propertyName` should be overwritten\n     * @returns {{[p: string]: *}|{}} - returns an object in the style\n     *  { [renderProp|renderProp.key]: { ...previousFieldProps, [propertyName]: propertyValue }}\n     *  or a deeper nested version thereof\n     */\n    addNewPropertyValueToNestedObject(\n      renderProp,\n      fieldProps,\n      propertyName,\n      propertyValue,\n      overwritePreviousValues = false,\n    ) {\n      // check if renderProp is a string\n      if (typeof renderProp === 'string') {\n        const previousFieldProps = fieldProps[renderProp] || {};\n        return {\n          [renderProp]: {\n            // if previous values should be overwritten - place the add the previous\n            // object properties first\n            ...(overwritePreviousValues ? previousFieldProps : {}),\n            [propertyName]: propertyValue,\n            // otherwise add them after the new property\n            ...(!overwritePreviousValues ? previousFieldProps : {}),\n          },\n        };\n      }\n      if (typeof renderProp === 'object') {\n        return Object.entries(renderProp).reduce((prev, [renderPropKey, renderPropValues]) => ({\n          ...prev,\n          // add an object in the form of [formGroupPropertyName]: {},\n          [renderPropKey]: {\n            // add all the field props that have been defined for that form group fields\n            // previously\n            ...fieldProps[renderPropKey],\n            // then overwrite form group fields that are defined in the renderProp array\n            ...renderPropValues.reduce((prevObject, field) => ({\n              ...prevObject,\n              // add property to fieldProps of this field\n              ...this.addNewPropertyValueToNestedObject(\n                field,\n                fieldProps[renderPropKey] || {},\n                propertyName,\n                propertyValue,\n              ),\n            }), {}),\n          },\n        }), {});\n      }\n      return {};\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    ref=\"searchContainer\"\n    class=\"base-advanced-search\">\n    <!-- FILTER ROW LIST (MODE 'LIST') -->\n    <template v-if=\"mode === 'list' && appliedFiltersInt && appliedFiltersInt.length\">\n      <BaseAdvancedSearchRow\n        v-for=\"(filter, index) in appliedFiltersInt\"\n        :key=\"appliedFilterKeys[index]\"\n        :mode=\"mode\"\n        :search-row-id=\"`${internalId}-${filter[identifierPropertyName.filter]}-${index}`\"\n        :is-main-search=\"false\"\n        :autocomplete-results=\"filtersAutocompleteResults[index]\"\n        :filter-list=\"displayedFilters\"\n        :applied-filter=\"filter\"\n        :is-loading=\"filtersLoadingState[index]\"\n        :default-filter=\"defaultFilter\"\n        :placeholder=\"placeholder.filterRow || placeholder\"\n        :autocomplete-property-names=\"autocompletePropertyNames\"\n        :label-property-name=\"labelPropertyName\"\n        :identifier-property-name=\"identifierPropertyName\"\n        :drop-down-info-texts=\"dropDownInfoTexts\"\n        :advanced-search-text=\"advancedSearchText\"\n        :assistive-text=\"{\n          addFilter: assistiveText.addFilter,\n          removeFilter: assistiveText.removeFilter,\n          selectFilterLabel: assistiveText.selectFilterLabel,\n          searchLabel: assistiveText.searchLabel,\n          selectedOption: assistiveText.selectedOption,\n          optionAdded: assistiveText.optionAdded,\n          optionToRemoveSelected: assistiveText.optionToRemoveSelected,\n          optionRemoved: assistiveText.optionRemoved,\n          loaderActive: assistiveText.autocompleteLoaderActive,\n          autocompleteResultsRetrieved: assistiveText.autocompleteResultsRetrieved,\n          autocompleteNoResults: assistiveText.autocompleteNoResults,\n          autocompleteInitial: assistiveText.autocompleteInitial,\n          categoryAnnouncement: assistiveText.categoryAnnouncement,\n          optionsAnnouncement: assistiveText.optionsAnnouncement,\n        }\"\n        :date-field-delay=\"dateFieldDelay\"\n        :language=\"language\"\n        :highlight-autocomplete-match=\"highlightAutocompleteMatch\"\n        :highlight-autocomplete-tags=\"highlightAutocompleteTags\"\n        class=\"base-advanced-search__filter-row\"\n        @remove-filter=\"removeFilter($event, index)\"\n        @update:applied-filter=\"updateFilter($event, index)\"\n        @fetch-autocomplete-results=\"fetchAutocomplete($event, index)\">\n        <template #autocomplete-option=\"{ option: autocompleteOption, collectionId }\">\n          <!-- @slot to allow for modification of the autocomplete option\n            @binding {Object} option - the option object as specified in the [autocompletePropertyNames.data] array\n            @binding {string} collection-id the currently active collection as provided in [autocompletePropertyNames.id] -->\n          <slot\n            name=\"autocomplete-option\"\n            :option=\"autocompleteOption\"\n            :collection-id=\"collectionId\" />\n        </template>\n      </BaseAdvancedSearchRow>\n    </template>\n\n    <!-- MAIN FILTER -->\n    <BaseAdvancedSearchRow\n      ref=\"mainSearch\"\n      v-model:applied-filter=\"mainFilter\"\n      v-bind=\"$attrs\"\n      :search-row-id=\"`main-${internalId}`\"\n      :mode=\"mode\"\n      :filter-list=\"displayedFilters\"\n      :form-filter-list=\"formFilterList\"\n      :default-filter=\"defaultFilter\"\n      :autocomplete-results=\"filtersAutocompleteResults[mainFilterIndex]\"\n      :is-loading=\"filtersLoadingState[mainFilterIndex]\"\n      :placeholder=\"placeholder.main || placeholder\"\n      :autocomplete-property-names=\"autocompletePropertyNames\"\n      :label-property-name=\"labelPropertyName\"\n      :identifier-property-name=\"identifierPropertyName\"\n      :drop-down-info-texts=\"dropDownInfoTexts\"\n      :advanced-search-text=\"advancedSearchText\"\n      :assistive-text=\"{\n        addFilter: assistiveText.addFilter,\n        removeFilter: assistiveText.removeFilter,\n        selectFilterLabel: assistiveText.selectFilterLabel,\n        searchLabel: assistiveText.searchLabel,\n        selectedOption: assistiveText.selectedOption,\n        loaderActive: assistiveText.autocompleteLoaderActive,\n        autocompleteResultsRetrieved: assistiveText.autocompleteResultsRetrieved,\n        autocompleteNoResults: assistiveText.autocompleteNoResults,\n        autocompleteInitial: assistiveText.autocompleteInitial,\n        categoryAnnouncement: assistiveText.categoryAnnouncement,\n        optionsAnnouncement: assistiveText.optionsAnnouncement,\n        results: assistiveText.results,\n      }\"\n      :date-field-delay=\"dateFieldDelay\"\n      :language=\"language\"\n      :highlight-autocomplete-match=\"highlightAutocompleteMatch\"\n      :highlight-autocomplete-tags=\"highlightAutocompleteTags\"\n      @add-filter-row=\"addFilterRow\"\n      @fetch-autocomplete-results=\"fetchAutocomplete($event, mainFilterIndex)\"\n      @option-selected=\"fillOptionToForm\">\n      <!-- SHOW ADVANCED SEARCH FORM BUTTON (MODE 'FORM') -->\n      <template #after>\n        <BaseButton\n          v-if=\"mode === 'form'\"\n          :text=\"showAdvancedSearchButtonText ? advancedSearchText.advancedButtonLabel : ''\"\n          :aria-expanded=\"`${formOpen}`\"\n          :aria-controls=\"`${internalId}-form`\"\n          :description=\"advancedButtonDescription\"\n          button-style=\"row\"\n          icon=\"drop-down\"\n          icon-size=\"small\"\n          icon-position=\"right\"\n          :class=\"['base-advanced-search__expand-button',\n                   { 'base-button--rotate-icon-180': formOpen }]\"\n          @click.prevent.stop=\"openAdvancedSearch\"\n          @keydown.enter.space.prevent.stop=\"openAdvancedSearch\"\n          @focusin.stop />\n      </template>\n      <!-- ADVANCED SEARCH FORM (MODE 'FORM') -->\n      <template #below>\n        <BaseForm\n          v-if=\"mainSearch && mode === 'form' && formOpen/** check for mainSearch template ref to avoid hydration mismatches */\"\n          v-bind=\"amendedFormProps\"\n          :model-value=\"formFilterValuesInt\"\n          :form-id=\"`${internalId}-form`\"\n          :form-field-json=\"formFilterList\"\n          :label-property-name=\"labelPropertyName.formInputs\"\n          :identifier-property-name=\"identifierPropertyName.formInputs\"\n          :class=\"['base-advanced-search__search-form',\n                   { 'base-advanced-search__search-form--hidden': !formMounted}]\"\n          @input-complete=\"updateFormFilters\"\n          @fetch-autocomplete=\"fetchFormAutocomplete\"\n          @form-mounted=\"formIsMounted\"\n          @keydown.stop\n          @click.stop>\n          <template #label-addition=\"{ fieldName, groupNames }\">\n            <!-- @slot all [BaseForm](BaseForm.html#slots) slots are available with the prefix 'form-'. For a more detailed description and demonstration refer to [BaseForm](BaseForm.html#slots).\n            @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n            @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n            <slot\n              name=\"form-label-addition\"\n              :field-name=\"fieldName\"\n              :group-names=\"groupNames\" />\n          </template>\n          <template #pre-input-field=\"{ fieldName, groupNames }\">\n            <!-- @slot all [BaseForm](BaseForm.html#slots) slots are available with the prefix 'form-'. For a more detailed description and demonstration refer to [BaseForm](BaseForm.html#slots).\n            @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n            @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n            <slot\n              name=\"form-pre-input-field\"\n              :field-name=\"fieldName\"\n              :group-names=\"groupNames\" />\n          </template>\n          <template\n            #input-field-addition-before=\"{ fieldName, groupNames }\">\n            <!-- @slot all [BaseForm](BaseForm.html#slots) slots are available with the prefix 'form-'. For a more detailed description and demonstration refer to [BaseForm](BaseForm.html#slots).\n            @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n            @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n            <slot\n              name=\"form-input-field-addition-before\"\n              :field-name=\"fieldName\"\n              :group-names=\"groupNames\" />\n          </template>\n          <template #input-field-inline-before=\"{ fieldName, groupNames }\">\n            <!-- @slot all [BaseForm](BaseForm.html#slots) slots are available with the prefix 'form-'. For a more detailed description and demonstration refer to [BaseForm](BaseForm.html#slots).\n            @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n            @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n            <slot\n              name=\"form-input-field-inline-before\"\n              :field-name=\"fieldName\"\n              :group-names=\"groupNames\" />\n          </template>\n          <template #input-field-addition-after=\"{ fieldName, groupNames }\">\n            <!-- @slot all [BaseForm](BaseForm.html#slots) slots are available with the prefix 'form-'. For a more detailed description and demonstration refer to [BaseForm](BaseForm.html#slots).\n            @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n            @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n            <slot\n              name=\"form-input-field-addition-after\"\n              :field-name=\"fieldName\"\n              :group-names=\"groupNames\" />\n          </template>\n          <template #post-input-field=\"{ fieldName, groupNames }\">\n            <!-- @slot all [BaseForm](BaseForm.html#slots) slots are available with the prefix 'form-'. For a more detailed description and demonstration refer to [BaseForm](BaseForm.html#slots).\n            @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n            @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n            <slot\n              name=\"form-post-input-field\"\n              :field-name=\"fieldName\"\n              :group-names=\"groupNames\" />\n          </template>\n          <template #error-icon>\n            <!-- @slot all [BaseForm](BaseForm.html#slots) slots are available with the prefix 'form-'. For a more detailed description and demonstration refer to [BaseForm](BaseForm.html#slots). -->\n            <slot name=\"form-error-icon\" />\n          </template>\n          <template #remove-icon>\n            <!-- @slot all [BaseForm](BaseForm.html#slots) slots are available with the prefix 'form-'. For a more detailed description and demonstration refer to [BaseForm](BaseForm.html#slots). -->\n            <slot name=\"form-remove-icon\" />\n          </template>\n          <template #below-input=\"{ fieldName, groupNames }\">\n            <!-- @slot all [BaseForm](BaseForm.html#slots) slots are available with the prefix 'form-'. For a more detailed description and demonstration refer to [BaseForm](BaseForm.html#slots).\n            @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n            @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n            <slot\n              name=\"form-below-input\"\n              :field-name=\"fieldName\"\n              :group-names=\"groupNames\" />\n          </template>\n          <template #drop-down-entry=\"{ option, fieldName, groupNames }\">\n            <!-- @slot all [BaseForm](BaseForm.html#slots) slots are available with the prefix 'form-'. For a more detailed description and demonstration refer to [BaseForm](BaseForm.html#slots).\n              @binding {object} option - the option object\n              @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n              @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n            <slot\n              :field-name=\"fieldName\"\n              :group-names=\"groupNames\"\n              :option=\"option\"\n              name=\"form-drop-down-entry\">\n              <template\n                v-if=\"mode === 'form'\n                  // check if value is boolean and was set true\n                  && ((typeof renderFormChipsLabelAsHtml === 'boolean' && renderFormChipsLabelAsHtml)\n                    // or if it is an array and\n                    || (typeof renderFormChipsLabelAsHtml === 'object'\n                      // a) includes the field name\n                      && (renderFormChipsLabelAsHtml.includes(fieldName)\n                        // or b) this is nested field in a form group and the array\n                        // contains a (nested) object with the group names and an array with the field name\n                        || (groupNames?.length && renderFormChipsLabelAsHtml\n                          .some((arrayEntry) => typeof arrayEntry === 'object'\n                            && extractNestedPropertyValue(groupNames.join('.'), arrayEntry)\n                              .includes(fieldName))))))\">\n                <BaseInsertTextAsHtml\n                  :render-element-as=\"'span'\"\n                  :text=\"option[labelPropertyName.formInputs]\"\n                  :interpret-text-as-html=\"true\" />\n              </template>\n            </slot>\n          </template>\n        </BaseForm>\n        <div\n          v-else-if=\"mode === 'form' && !formOpen && collapsedFiltersArray.length\">\n          <BaseCollapsedFilterRow\n            v-model:filters=\"collapsedFiltersArray\"\n            :date-time-text=\"advancedSearchText.collapsedDateTime\"\n            :interpret-label-as-html=\"renderFormChipsLabelAsHtml\"\n            :assistive-text=\"{\n              removeFiltersLabel: assistiveText.removeAllFiltersLabel,\n              filterRemovedNotification: assistiveText.removeFilterValueNotification,\n              appliedFiltersLabel: assistiveText.collapsedAppliedFiltersLabel,\n              booleanFilterLabel: assistiveText.collapsedBooleanFilterValue,\n              optionToRemoveSelected: assistiveText.collapsedOptionToRemoveSelected,\n            }\"\n            @click.stop\n            @keydown.stop\n            @remove-all=\"removeAllFilters\" />\n        </div>\n      </template>\n      <template #autocomplete-option=\"{ option: autocompleteOption, collectionId }\">\n        <!-- @slot to allow for modification of the autocomplete option\n          @binding {Object} option - the option object as specified in the [autocompletePropertyNames.data] array\n          @binding {string} collection-id the currently active collection as provided in [autocompletePropertyNames.id] -->\n        <slot\n          name=\"autocomplete-option\"\n          :option=\"autocompleteOption\"\n          :collection-id=\"collectionId\">\n          <!-- also automate the display of html for all fields specified directly in the component -->\n          <template\n            v-if=\"mode === 'form'\n              && ((typeof renderFormChipsLabelAsHtml === 'boolean' && renderFormChipsLabelAsHtml)\n                || (typeof renderFormChipsLabelAsHtml === 'object'\n                  && renderFormChipsLabelAsHtml.includes(collectionId)))\">\n            <BaseInsertTextAsHtml\n              :render-element-as=\"'span'\"\n              :text=\"autocompleteOption[labelPropertyName.autocompleteOption]\"\n              :interpret-text-as-html=\"true\" />\n          </template>\n        </slot>\n      </template>\n    </BaseAdvancedSearchRow>\n    <span\n      v-if=\"assistiveTextNotification\"\n      aria-live=\"assertive\"\n      class=\"assistive-text\">\n      {{ assistiveTextNotification }}\n    </span>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n.base-advanced-search {\n  .base-advanced-search__filter-row {\n    margin-bottom: $spacing;\n  }\n\n  .base-advanced-search__expand-button {\n    border-left: $separation-line;\n    margin-left: $spacing-small;\n    padding-right: $spacing-small;\n  }\n\n  .base-advanced-search__search-form {\n    border-top: $separation-line;\n\n    &.base-advanced-search__search-form--hidden {\n      display: none;\n    }\n  }\n}\n\n</style>\n","<script setup>\nimport { computed, ref, useTemplateRef, watch } from 'vue';\nimport { createId } from '@/utils/utils.js';\nimport { useListNavigation } from '@/composables/useListNavigation.js';\nimport { useAnnouncer } from '@/composables/useAnnouncer.js';\nimport BaseInput from '@/components/BaseInput/BaseInput.vue';\nimport BaseDropDownList from '@/components/BaseDropDownList/BaseDropDownList.vue';\nimport { useExtractAttrs } from '@/composables/useExtractAttrs.js';\n\n/**\n * Input component allowing to select single values from a drop-down that are filled into\n * the input field as string\n */\n\ndefineOptions({\n  name: 'BaseAutocompleteInput',\n  inheritAttrs: false,\n});\n\nconst props = defineProps({\n    /**\n     * input field settable from outside\n     */\n    modelValue: {\n      type: [String, Number],\n      default: '',\n    },\n    /**\n     * provide a list of options for the drop-down.\n     * could be a list of strings or objects - if it is objects if necessary please adapt\n     * the props `labelPropertyName` (value to be displayed) and `identifierPropertyName` (used for\n     * identification) for correct handling\n     */\n    list: {\n      type: Array,\n      default: () => [],\n      validator: (val) => {\n        // if the value is undefined return false\n        if (!val) return false;\n        // if it is an empty array always return true\n        if (!val.length) return true;\n        // else make sure the options are unique\n        let isUniqueList;\n        // if options are strings compare newly created set with original\n        if (val[0] === 'string') {\n          isUniqueList = val.length === Array.from(new Set(val)).length;\n        } else {\n          // if it is an object we need to stringify the object first before comparison\n          isUniqueList = val.length === Array.from(new Set(val.map(JSON.stringify))).length;\n        }\n        // also issue a warning to the user if options are not unique\n        if (!isUniqueList) {\n          console.warn('An option is appearing in the options list more than once!');\n        }\n        return isUniqueList;\n      }\n    },\n    /** label for input field, required for usability purposes, handle\n     * showing of label with property `showLabel`\n     */\n    label: {\n      type: String,\n      required: true,\n    },\n    /**\n     * defines if input label should be visible\n     */\n    showLabel: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * if field is occurring more then once - set an id\n     * in case a custom input is used with the input slot it is important to\n     * assign the same id to the input element\n     */\n    inputId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set a placeholder for the input field\n     */\n    placeholder: {\n      type: String,\n      default: 'Enter Text Here',\n    },\n    /**\n     * mark as required field (currently only used for `aria-required`)\n     */\n    required: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * mark the form field as invalid and ideally also provide an error message\n     * to display below the form field\n     */\n    invalid: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * add an error message to be displayed below form field if field is invalid\n     */\n    errorMessage: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define if error icon should be shown\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * set input field in active state from outside.\n     * the v-model directive can be used on this prop\n     */\n    isActive: {\n      type: Boolean,\n      default: null,\n    },\n    /**\n     * option to have the border of the input field not displayed\n     */\n    showInputBorder: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define if standard form field styling should be\n     * used (otherwise no box shadow)\n     */\n    useFormFieldStyling: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * if `true` a remove icon (or a custom icon if slot `remove-icon` is used) will be shown allowing to remove\n     * all input at once\n     */\n    clearable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `true` space is reserved for a loader that can be activated\n     * with the 'isLoading' prop\n     */\n    loadable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * show spinner to indicate that something is loading\n     * (for dynamically fetched entries that need to do backend requests)\n     */\n    isLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set a language (ISO 639-1)\n     */\n    language: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set `true` if input field should be disabled\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify the object property that should be used as identifier\n     */\n    identifierPropertyName: {\n      type: String,\n      default: 'id',\n    },\n    /**\n     * specify the object property that should be used as value to be displayed\n     */\n    labelPropertyName: {\n      type: String,\n      default: 'label',\n    },\n    /**\n     * message displayed when no selectable options are available\n     */\n    dropDownNoOptionsInfo: {\n      type: String,\n      default: 'No options available',\n    },\n    /**\n     * if this is `true` parent needs to take care of filling the options list on string\n     * input etc. - useful for fetching autocomplete options from a backend\n     */\n    dynamicFetch: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * set this flag to `true` to highlight autocomplete option characters that match\n     *  the current search input string\n     */\n    highlightStringMatch: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `highlightAutocompleteMatch` is set `true`\n     *  provide tag names to style the matched characters\n     *  (without '<' and '>', e.g. ['b'] for <b>)\n     */\n    highlightStringTags: {\n      type: Array,\n      default: () => ([]),\n    },\n    /**\n     * **loaderActive**: add text that is announced when results are being fetched (prop\n     *  `isLoading` is set `true`)\n     * **clearInput**: text read for remove input icon if prop `clearable` is set `true`\n     * **resultsRetrieved**: text that is announced when results were retrieved (drop-down\n     *  list changed)\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        loaderActive: 'drop-down options are loading.',\n        clearInput: 'Clear input',\n        resultsRetrieved: '{number} options found with your input.',\n      }),\n    },\n  });\nconst emits = defineEmits([\n  /**\n   * event triggered when input changes - part of v-model\n   * @event update:model-value\n   * @param {string} - the altered input string\n   */\n  'update:model-value',\n  /**\n   * an event specifically triggered when drop-down should be fetched anew\n   * when `dynamicFetch` is set `true`\n   * @event fetch-dropdown-entries\n   * @property {string} value\n   */\n  'fetch-dropdown-entries',\n  /**\n   * update when active state of input field changes\n   * the v-model directive can be used on this event\n   * @event update:is-active\n   * @param {boolean} - is input field active\n   */\n  'update:is-active',\n  /**\n   * inform parent when an option was selected with all information provided in options list\n   * (mainly useful when options list was array of objects - if strings this information\n   * is provided with input event anyways)\n   * @event selected\n   * @param {string, Object} - selected option (if list of objects was provided the whole object)\n   */\n  'selected',\n]);\n\n/** ATTRS HANDLING */\nconst { rootAttrs, forwardAttrs } = useExtractAttrs();\n\n/** INPUT ELEMENT */\n/**\n * get the reference to the BaseInput component\n * @type {Readonly<ShallowRef<HTMLElement | null>>}\n */\nconst baseInput = useTemplateRef('baseInputEl');\n/**\n * get the native input element from BaseInput\n * @type {ComputedRef<HTMLElement>}\n */\nconst inputElement = computed(() => baseInput.value?.inputElement || null);\n\n/** INPUT HANDLING */\n/**\n * internal input representation passed on to BaseInput\n * @type {Ref<UnwrapRef<string|Object|null>>}\n */\nconst inputInt = ref(null);\n\n/**\n * watch modelValue prop to update internal representation\n */\nwatch(() => props.modelValue, (val) => {\n  if (val !== inputInt.value) {\n    inputInt.value = val;\n  }\n}, {\n  immediate: true,\n});\n\n/**\n * watch internal input variable to inform parent of changes if necessary\n * @param {Object|string} val\n */\nwatch(inputInt, (val) => {\n  if (val !== props.modelValue) {\n    emits('update:model-value', val);\n  }\n  // if options should be fetched dynamically trigger event when inputInt changes\n  if (props.dynamicFetch) {\n    emits('fetch-dropdown-entries', { value: val });\n  }\n});\n\n\n/** LIST HANDLING */\n\n/**\n * determine if list prop is array of strings or objects\n * @returns {ComputedRef<boolean>}\n */\nconst optionsIsListOfStrings = computed(() => {\n  return !!props.list && !!props.list.length && typeof props.list[0] === 'string';\n});\n/**\n * compute an internal representation for the list to always have an\n * object with identifier provided to BaseDropDownList\n * @returns {ComputedRef<Object[]>}\n */\nconst listInt = computed((val) => {\n  // if list is array of objects - simply return the original prop value\n  return !optionsIsListOfStrings.value\n    // else map the array of strings with internal properties and an internal id\n    ? props.list : props.list.map((option) => {\n      // to not create a new id everytime the list changes but reuse already created id's by finding the\n      // option in `listInt`\n      const previousOptionValue = val ? val.find(({ [props.labelPropertyName]: label }) => option === label)\n        : undefined;\n      // if an option with the identical label string was found in listInt use the id of that one\n      const optionId = previousOptionValue ? previousOptionValue[props.identifierPropertyName]\n        // otherwise create a new id\n        : `${option}-${createId()}`\n      return ({\n        [props.labelPropertyName]: option,\n        [props.identifierPropertyName]: optionId,\n      });\n    });\n});\n\n/**\n * additionally if the list is not fetched dynamically filter already selected\n * options from the  list\n * (since inputInt is always only string now this can only be done by comparing\n * the label!)\n * @returns {ComputedRef<Object[]>}\n */\nconst filteredListInt = computed(() => {\n  // check if list content is fetched dynamically\n  if (!props.dynamicFetch) {\n    // if not filter input string by label property\n    return listInt.value\n      .filter(option => option[props.labelPropertyName].toLowerCase()\n        .includes(inputInt.value.toLowerCase()));\n  }\n  // else just return the unmodified list\n  return listInt.value;\n});\n\n/**\n * drop-down NAVIGATION // ACTIVE OPTION HANDLING\n */\nconst { navigate } = useListNavigation();\n/**\n * needed for navigation via keyboard in drop-down list\n * the index of the current active option in the list array\n * @type {Ref<UnwrapRef<number>>}\n */\nconst activeOptionIndex = ref(-1);\n/**\n * the currently active option object\n */\nconst activeOption = computed({\n  /**\n   * setter function of activeOption - will set active option index\n   * @param {?Object} val - the active option (by hover or arrow key use)\n   */\n  set(val) {\n    activeOptionIndex.value = filteredListInt.value.indexOf(val);\n  },\n  /**\n   * getter function for activeOption - determined by active option index\n   * @returns {ComputedRef<Object>}\n   */\n  get() {\n    return filteredListInt.value[activeOptionIndex.value];\n  },\n});\n\n/**\n * event for keydown arrow (up, down) key use\n *\n * @param {KeyboardEvent} event - the keydown event\n */\nfunction onArrowKey(event) {\n  // check if the list has any options\n  if (filteredListInt.value.length) {\n    // if yes trigger the navigate function\n    activeOption.value = navigate(\n      filteredListInt.value,\n      event.key === 'ArrowDown',\n      activeOptionIndex.value,\n      false,\n      true,\n    );\n  }\n}\n\n/** INPUT/DROP-DOWN ACTIVE HANDLING */\n\n/**\n * internal representation for active state of input and drop-down\n * @type {Ref<UnwrapRef<boolean>>}\n */\nconst isActiveInt = ref(false);\n\n/**\n * watch prop isActive to sync with internal variable\n */\nwatch(() => props.isActive, (val) => {\n  // check first if internal and external variable differ\n  if (val !== isActiveInt.value) {\n    isActiveInt.value = val;\n  }\n}, {\n  immediate: true,\n});\n\n/**\n * watch internal is active variable to be able to inform parent about\n * changes\n */\nwatch(isActiveInt, (val) => {\n  // if input is not active anymore reset the active option index\n  if (!val) {\n    activeOptionIndex.value = -1;\n  }\n  emits('update:is-active', val);\n});\n\n/**\n * if user continues typing after 'enter' (which closes the drop-down)\n * the dropdown should open again\n */\nfunction onKeydown(event) {\n  const { key } = event;\n  if (!['Tab', 'Enter'].includes(key)) {\n    isActiveInt.value = true;\n  }\n}\n\n/** SELECT OPTION */\n\n/**\n * triggered on keydown enter event and will add\n * a selected option\n */\nfunction onEnter() {\n  // check if there is a currently active option\n  if (activeOption.value) {\n    selectOption(activeOption.value);\n    // if enter was not pressed to add an option from the drop-down\n    // still close the drop-down\n  } else {\n    isActiveInt.value = false;\n  }\n}\n\n/**\n * @param {Object} selectedOption - the option selected from drop-down or by keyboard\n * enter - always an object due to internal identifier prop added in case it was a string\n */\nfunction selectOption(selectedOption) {\n  // assign the newly selected value to the input field (only the string from label prop!)\n  inputInt.value = selectedOption[props.labelPropertyName];\n  // if options list was objects also inform parent which option was selected separately\n  if (!optionsIsListOfStrings.value) {\n    // therefore identify the selected option from the list\n    const originalOption = props.list\n      .find(option => option[props.identifierPropertyName]\n        === selectedOption[props.identifierPropertyName]);\n    emits('selected', originalOption);\n  } else {\n    emits('selected', inputInt.value);\n  }\n  // close the drop-down and blur input\n  isActiveInt.value = false;\n}\n\n/** ACCESSIBILITY ANNOUNCEMENTS */\n/**\n * set up component reference\n * @type {Readonly<ShallowRef<HTMLElement | null>>}\n */\nconst autocompleteInput = useTemplateRef('autocompleteInputEl');\n// use composable to announce screen reader text on actions taken (e.g.\n// add chip to selected list or remove chip\nconst { announcement } = useAnnouncer(autocompleteInput);\n/**\n * timeout for drop-down options found announcer because otherwise\n * text not read if more than one character entered into input\n * @type {Ref<UnwrapRef<null|number>>}\n */\nconst timeout = ref(null);\n\nwatch(filteredListInt, (val) => {\n  if (timeout.value) {\n    clearTimeout(timeout.value);\n    timeout.value = null;\n  }\n  // adding this timeout because with dynamicFetch false the list\n  // changes immediately and announcement text is not always read\n  timeout.value = setTimeout(() => {\n    // only read announcement if drop-down is open\n    if (isActiveInt.value) {\n      if (val.length) {\n        announcement.value = props.assistiveText.resultsRetrieved ? props.assistiveText.resultsRetrieved\n          .replace('{number}', val.length) : '';\n      } else {\n        announcement.value = props.dropDownNoOptionsInfo;\n      }\n    }\n  }, 1000);\n});\n\n// with composition API we need to specifically expose variables and functions that\n// should be available from outside\ndefineExpose({\n  /**\n   * the native HTML input element\n   */\n  inputElement,\n})\n</script>\n\n<template>\n  <div\n    ref=\"autocompleteInputEl\"\n    v-bind=\"rootAttrs\"\n    class=\"base-autocomplete-input\">\n    <BaseInput\n      ref=\"baseInputEl\"\n      v-model=\"inputInt\"\n      v-model:is-active=\"isActiveInt\"\n      v-bind=\"forwardAttrs\"\n      :aria-autocomplete=\"'list'\"\n      :aria-controls=\"`${inputId}-list-identifier`\"\n      :aria-expanded=\"isActiveInt\"\n      :aria-haspopup=\"'listbox'\"\n      :input-id=\"inputId\"\n      :label=\"label\"\n      :show-label=\"showLabel\"\n      :placeholder=\"placeholder\"\n      :required=\"required\"\n      :invalid=\"invalid\"\n      :error-message=\"errorMessage\"\n      :show-error-icon=\"showErrorIcon\"\n      :use-form-field-styling=\"useFormFieldStyling\"\n      :show-input-border=\"showInputBorder\"\n      :clearable=\"clearable\"\n      :loadable=\"loadable\"\n      :is-loading=\"isLoading\"\n      :language=\"language\"\n      :disabled=\"disabled\"\n      :drop-down-list-id=\"`${inputId}-list-identifier`\"\n      :linked-list-option=\"activeOption ? activeOption[identifierPropertyName] : undefined\"\n      :assistive-text=\"{\n        loaderActive: assistiveText.loaderActive,\n        clearInput: assistiveText.clearInput,\n      }\"\n      :ignore-click-outside=\"['.base-autocomplete-input__drop-down']\"\n      role=\"combobox\"\n      class=\"base-autocomplete-input__input-field\"\n      @keydown.enter.prevent=\"onEnter\"\n      @keydown.up.down.prevent=\"onArrowKey\"\n      @keydown=\"onKeydown\">\n      <template #below-input>\n        <BaseDropDownList\n          v-if=\"isActiveInt\"\n          :active-option=\"activeOption\"\n          :drop-down-options=\"filteredListInt\"\n          :identifier-property-name=\"identifierPropertyName\"\n          :label-property-name=\"labelPropertyName\"\n          :list-id=\"`${inputId}-list-identifier`\"\n          :language=\"language\"\n          :drop-down-no-options-info=\"dropDownNoOptionsInfo\"\n          :use-highlight-string-match=\"highlightStringMatch\"\n          :highlight-string-tags=\"highlightStringTags\"\n          :highlight-string-match=\"inputInt\"\n          class=\"base-autocomplete-input__drop-down\"\n          @click.stop\n          @touchstart.stop\n          @update:selected-option=\"selectOption\">\n          <template #option=\"{ option }\">\n            <!-- @slot provide custom drop-down options\n              @binding {string, Object} item - the option from provided options list -->\n            <slot\n              :item=\"option\"\n              name=\"drop-down-entry\" />\n          </template>\n        </BaseDropDownList>\n      </template>\n      <template\n        #label-addition>\n        <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs)). for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"label-addition\" />\n      </template>\n      <template #pre-input-field>\n        <!-- @slot slot to add elements within the form field but in a row before the actual input field. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"pre-input-field\" />\n      </template>\n      <template\n        #input-field-addition-before>\n        <!-- @slot Slot to allow for additional elements in the input field <div> (before <input>). for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"input-field-addition-before\" />\n      </template>\n      <template #input-field-inline-before>\n        <!-- @slot to add elements directly inline before the input (contrary to `input-field-addition-before` this does not wrap. for an example see [BaseInput](BaseInput)-->\n        <slot name=\"input-field-inline-before\" />\n      </template>\n      <template #input-field-addition-after>\n        <!-- @slot for adding elements after input -->\n        <slot name=\"input-field-addition-after\" />\n      </template>\n      <template #post-input-field>\n        <!-- @slot for adding elements at the end covering the whole height. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"post-input-field\" />\n      </template>\n      <template #error-icon>\n        <!-- @slot use a custom icon instead of standard error/warning icon. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"error-icon\" />\n      </template>\n      <template #remove-icon>\n        <!-- @slot use a custom icon instead of standard remove icon. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"remove-icon\" />\n      </template>\n    </BaseInput>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n.base-autocomplete-input {\n  .base-autocomplete-input__input-field {\n    .base-autocomplete-input__drop-down {\n      background: white;\n      min-width: 100%;\n    }\n  }\n}\n</style>\n","<script setup>\ndefineOptions({\n  name: 'BaseBox',\n});\n\n/**\n * Wrapper component for everything Box shaped\n */\ndefineProps({\n  /**\n   * specify the tag type of the box\n   *\n   * **note**: rendering a link element\n   * this needs to be a valid vue link component string (e.g. `'RouterLink'`) or a component directly\n   * and vue-router is necessary\n   * **caveat**: if you are using Nuxt the string `'NuxtLink'` is not enough,\n   *  but you need to import the component as `import { NuxtLink } from '#components';`\n   *  and pass the component to the prop!\n   */\n  renderElementAs: {\n    type: [String, Object],\n    default: 'div',\n  },\n  /**\n   * define the size of the box\n   * should be an object with width and / or height\n   */\n  boxSize: {\n    type: Object,\n    default: () => ({ width: '200px' }),\n  },\n  /**\n   * define the ratio of width and height of the box\n   * (in percent string, e.g. 1:1 --> '100', 1:2 --> '50')\n   */\n  boxRatio: {\n    type: String,\n    default: '100',\n  },\n  /**\n   *  enable or disable hover\n   */\n  boxHover: {\n    type: Boolean,\n    default: true,\n  },\n  /**\n   *  set boxShadow size\n   *  @values large, small, none\n   */\n  boxShadowSize: {\n    type: String,\n    default: 'small',\n    validator: val => ['none', 'small', 'large'].includes(val),\n  },\n  /**\n   * set disabled attribute (e.g. for button elements)\n   */\n  disabled: {\n    type: Boolean,\n    default: false,\n  },\n  /**\n   * specify any additional attributes the native box element should have\n   * style and class attributes can not be overwritten though\n   */\n  additionalAttributes: {\n    type: Object,\n    default: () => ({}),\n  },\n});\nconst emits = defineEmits([\n  /**\n   * event emitted upon box click\n   * @event clicked\n   * @param {MouseEvent} - the native mouse event\n   */\n  'clicked',\n]);\n\nfunction clicked(event) {\n  emits('clicked', event);\n}\n</script>\n\n<template>\n  <component\n    :is=\"renderElementAs\"\n    :disabled=\"disabled || undefined\"\n    :type=\"(renderElementAs === 'button') ? 'button' : ''\"\n    v-bind=\"additionalAttributes\"\n    :style=\"boxSize\"\n    :class=\"['base-box',\n             'base-box--' + boxRatio,\n             'base-box--shadow-' + boxShadowSize,\n             { 'base-box--hover': boxHover && !disabled }]\"\n    @click=\"clicked\">\n    <!-- @slot slot for box contents -->\n    <slot />\n  </component>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n  .base-box {\n    background: white;\n    position: relative;\n    overflow: hidden;\n    display: flex;\n\n    &:after {\n      content:  '';\n      display: block;\n      background: white;\n    }\n\n    &.base-box--100::after {\n      padding-bottom: 100%;\n    }\n\n    &.base-box--50::after {\n      padding-bottom: calc(50% - #{$spacing-small});\n    }\n\n    &.base-box--hover:hover,\n    &:focus {\n      box-shadow: $box-shadow-hov;\n    }\n\n    &:disabled {\n      box-shadow: none;\n    }\n\n    &--shadow-small {\n      box-shadow: $box-shadow-reg;\n      transition: $box-transition;\n    }\n\n    &--shadow-large {\n      box-shadow: $box-shadow-edit;\n    }\n  }\n</style>\n","<script>\nimport BaseBox from '@/components/BaseBox/BaseBox.vue';\nimport { ref, defineAsyncComponent, useTemplateRef } from 'vue';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\n\n/**\n * A Base Box Shaped Button\n */\n\nexport default {\n  name: 'BaseBoxButton',\n  components: {\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseBox,\n    BaseBoxTooltip: defineAsyncComponent(() => import('@/components/BaseBoxTooltip/BaseBoxTooltip.vue')),\n\n  },\n  props: {\n    /**\n     * specify the tag of the button\n     */\n    renderElementAs: {\n      type: String,\n      default: 'button',\n    },\n    /**\n     * Define type of button box style: 'large' | 'small'\n     */\n    boxStyle: {\n      type: String,\n      default: 'large',\n      validator(val) {\n        return ['large', 'small'].includes(val);\n      },\n    },\n    /**\n     * specify icon name if desired, this uses the `BaseIcon` component;\n     * see [BaseIcon](BaseIcon) for available icons\n     */\n    icon: {\n      type: String,\n      default: null,\n    },\n    /**\n     * show a plus sign next to the icon if `true`\n     * only available for large button style\n     */\n    showPlus: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify the text for the button\n     */\n    text: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify subtext for the button\n     * only available for large button style\n     */\n    subtext: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define box size\n     */\n    boxSize: {\n      type: Object,\n      default: () => ({ width: '25%' }),\n    },\n    /**\n     * define the ratio of width and height of the box\n     * (in percent string, e.g. 1:1 --> '100', 1:2 --> '50')\n     */\n    boxRatio: {\n      type: String,\n      default: '100',\n    },\n    /**\n     * set button inactive\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * show tooltip\n     */\n    showTooltip: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['clicked', 'on-tooltip'],\n  setup() {\n    /** SUBTEXT DISPLAY FUNCTIONALITY */\n    /**\n     * template reference to the box to determine box size\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const baseBox = useTemplateRef('baseBoxEl');\n    /**\n     * template reference to the subtext to determine subtext position\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const baseBoxSubtext = useTemplateRef('baseBoxSubtextEl');\n    /**\n     * variable to store subtext visiblity, to hide subtext if box is too small\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const showSubtext = ref(false);\n\n    function calcShowSubtext() {\n      if (baseBoxSubtext.value && baseBox.value) {\n        const subtextBottomPosition = baseBoxSubtext.value.offsetTop\n          + baseBoxSubtext.value.offsetHeight;\n        const boxHeight = baseBox.value.$el.offsetHeight;\n        showSubtext.value = boxHeight >= subtextBottomPosition;\n      }\n    }\n\n    useElementObserver({\n      type: 'resize',\n      target: baseBox,\n      callback: calcShowSubtext,\n    });\n\n    return {\n      baseBox,\n      baseBoxSubtext,\n      showSubtext,\n    };\n  },\n  methods: {\n    clicked(event) {\n      // prevent click event if disabled\n      if (this.disabled) return;\n      /**\n       * event emitted on box click\n       *\n       * @event clicked\n       * @param {Event} - the native event\n       */\n      this.$emit('clicked', event);\n    },\n    onTooltip(event) {\n      /**\n       * event emitted on tooltip click\n       *\n       * @event on-tooltip\n       * @param {Event} - the native event from tooltip triggered\n       */\n      this.$emit('on-tooltip', event);\n    },\n  },\n};\n</script>\n\n<template>\n  <BaseBox\n    ref=\"baseBoxEl\"\n    :render-element-as=\"renderElementAs\"\n    :box-size=\"boxSize\"\n    :box-ratio=\"boxRatio\"\n    :disabled=\"disabled\"\n    :class=\"['base-box-button', { 'base-box-button--disabled': disabled }]\"\n    @clicked=\"clicked\">\n    <div\n      v-if=\"boxStyle === 'large'\"\n      class=\"base-box-button__content\">\n      <div class=\"base-box-button__center\">\n        <div\n          class=\"base-box-button__image-row\">\n          <div class=\"base-box-button__plus-container\">\n            <BaseIcon\n              v-if=\"showPlus\"\n              name=\"plus\"\n              alt=\"add\"\n              class=\"base-box-button__icon base-box-button__plus\" />\n          </div>\n          <div class=\"base-box-button__icon-container\">\n            <BaseIcon\n              v-if=\"icon\"\n              :name=\"icon\"\n              class=\"base-box-button__icon\" />\n          </div>\n        </div>\n        <div class=\"base-box-button__text\">\n          {{ text }}\n        </div>\n      </div>\n\n      <div\n        ref=\"baseBoxSubtextEl\"\n        :class=\"['base-box-button__subtext', { 'base-button-box__subtext--hidden': !showSubtext }]\">\n        {{ subtext }}\n      </div>\n      <BaseBoxTooltip\n        v-if=\"showTooltip\"\n        @click.capture=\"onTooltip\"\n        @keydown.enter.capture=\"onTooltip\" />\n    </div>\n    <div\n      v-else\n      class=\"base-box-button__content--small\">\n      <BaseIcon\n        v-if=\"icon\"\n        :name=\"icon\"\n        class=\"base-box-button__icon base-box-button__icon--small\" />\n      <div class=\"base-box-button__text-small\">\n        {{ text }}\n      </div>\n    </div>\n    <!-- undocumented slot? TODO: why is this here, whats the purpose? -->\n    <slot />\n  </BaseBox>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-box-button {\n    display: flex;\n    transition: all 0.2s ease;\n    text-align: left;\n    align-items: center;\n\n    &:focus,\n    &:active,\n    &:hover:not([disabled]) {\n      color: $app-color;\n      fill: $app-color;\n      cursor: pointer;\n    }\n\n    &.base-box-button--disabled {\n      cursor: default;\n      color: $graytext-color;\n\n      &:hover {\n        color: $graytext-color !important;\n        box-shadow: none !important;\n      }\n    }\n\n    .base-box-button__content {\n      padding: $spacing;\n      position: absolute;\n      height: 100%;\n      width: 100%;\n\n      .base-box-button__center {\n        position: absolute;\n        top: 50%;\n        transform: translate(0, -50%);\n        width: calc(100% - (2 * #{$spacing}));\n\n        .base-box-button__image-row {\n          line-height: $icon-max;\n          margin-bottom: $spacing;\n          height: $icon-max;\n          width: $icon-max;\n\n          .base-box-button__plus-container {\n            position: absolute;\n            display: flex;\n            align-items: center;\n            transform: translate(0, 50%);\n            width: 100%;\n            left: calc(50% - 54px);\n\n            .base-box-button__plus {\n              height: $icon-large;\n              width: $icon-large;\n              max-width: $icon-large;\n            }\n          }\n\n          .base-box-button__icon-container {\n            width: calc(100% - (2 * #{$icon-large}));\n            position: absolute;\n            left: calc(50% - #{$icon-large});\n\n            .base-box-button__icon {\n              height: $icon-max;\n              width: $icon-max;\n              max-width: $icon-max;\n            }\n          }\n        }\n        .base-box-button__text {\n          height: calc(2 * #{$line-height})\n        }\n      }\n\n      .base-box-button__text, .base-box-button__subtext {\n        text-align: center;\n      }\n\n      .base-box-button__subtext {\n        margin-top: $spacing-small;\n        padding-bottom: $spacing;\n        font-size: $font-size-small;\n        position: absolute;\n        width: calc(100% - (2 * #{$spacing}));\n        top: calc(50% + 52px);\n\n        &.base-button-box__subtext--hidden {\n          visibility: hidden;\n        }\n      }\n    }\n\n    .base-box-button__icon {\n      pointer-events: none;\n      touch-action: none;\n    }\n  }\n\n  .base-box-button__content--small {\n    padding: $spacing;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    width: 100%;\n\n    .base-box-button__icon--small {\n      flex-shrink: 0;\n      margin-right: $spacing;\n      height: $icon-large;\n      width: $icon-large;\n      max-width: $icon-large;\n    }\n  }\n</style>\n","<script>\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\n\nexport default {\n  name: 'BaseBoxTooltip',\n  components: {\n    BaseIcon,\n  },\n  emits: ['clicked'],\n  methods: {\n    clicked(event) {\n      /**\n       * event emitted on tooltip click\n       * @event clicked\n       * @param {MouseEvent} - the native mouse event on click\n       */\n      this.$emit('clicked', event);\n    },\n  },\n};\n</script>\n\n<template>\n  <span\n    role=\"button\"\n    class=\"base-box-tooltip\"\n    tabindex=\"0\"\n    @keydown.enter=\"clicked\"\n    @click=\"clicked\">\n    <BaseIcon\n      name=\"information\"\n      alt=\"information\"\n      class=\"base-box-tooltip-icon\" />\n  </span>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n  @use \"@/styles/variables\" as *;\n\n  .base-box-tooltip {\n    position: relative;\n    z-index: map.get($zindex, boxcontent);\n    margin-left: auto;\n    color: $font-color;\n    transition: color 250ms ease-in-out;\n\n    @media screen and (min-width: $mobile) {\n      position: absolute;\n      margin-left: 0;\n      top: $spacing-small;\n      right: $spacing-small;\n    }\n\n    &:hover, &:focus, &:active {\n      color: $app-color;\n    }\n\n    &:hover {\n      cursor: pointer;\n    }\n\n    .base-box-tooltip-icon {\n      height: 20px;\n      width: 20px;\n      max-width: 20px;\n      vertical-align: middle;\n    }\n  }\n</style>\n","/**\n * cleans the provided DOM element by removing empty nodes and\n * removes excess spaces and line breaks within a text node\n *\n * @param {ChildNode} element - root element to clean\n * @param {boolean} [binding] - specify in the directive whether to clean\n *  child elements recursively like so: v-clean-dom-nodes={ recursive: [true|false] }\n *  if not specified this defaults to true - if single nodes should be skipped a\n *  'no-clean' css class can be added to that element\n */\nexport default function cleanDomNodes(element, binding) {\n  element.childNodes.forEach((node) => {\n    if (node.nodeType === Node.TEXT_NODE) {\n      // remove white-spaces and new-lines\n      const textContent = node.textContent.trim();\n      // remove empty nodes\n      if (textContent === '') {\n        element.removeChild(node);\n        return;\n      }\n      // update node\n      // eslint-disable-next-line no-param-reassign\n      node.textContent = textContent;\n      return;\n    }\n\n    // clean nodes recursively if binding is not specified or binding value property\n    // recursive is set 'true'\n    if (node.nodeType === Node.ELEMENT_NODE && (!binding || binding?.value?.recursive)) {\n      cleanDomNodes(node);\n    }\n  });\n}\n","<script>\nimport { defineAsyncComponent, ref, getCurrentInstance, computed, useSlots } from 'vue';\nimport { useWindowResize } from '@/composables/useWindowResize.js';\nimport { useEventListener } from '@/composables/useEventListener.js';\nimport { useId } from '@/composables/useId.js';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\nimport cleanDomNodes from '@/directives/cleanDomNodes.js';\n\n/**\n * component to display different types of links\n * e.g.: chip, internal, external, text, tooltip, tooltip (async content)\n */\n\nexport default {\n  name: 'BaseLink',\n  components: {\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseTooltipBox: defineAsyncComponent(() => import('@/components/BaseTooltipBox/BaseTooltipBox.vue')),\n    BaseLoader: defineAsyncComponent(() => import('@/components/BaseLoader/BaseLoader.vue')),\n    BaseInsertTextAsHtml: defineAsyncComponent(() => import('@/components/BaseInsertTextAsHtml/BaseInsertTextAsHtml.vue')),\n  },\n  directives: {\n    cleanDomNodes,\n  },\n  props: {\n    /**\n     * specify a query parameter name for type `chip` links\n     */\n    chipQueryName: {\n      type: String,\n      default: 'chip-link',\n    },\n    /**\n     * specify external link target\n     * @values _blank, _self\n     */\n    externalLinkTarget: {\n      type: String,\n      default: '_blank',\n      validator: val => (val === '_blank' || val === '_self'),\n    },\n    /**\n     * specify the object property that should be used as identifier\n     */\n    identifierPropertyName: {\n      type: String,\n      default: 'source',\n    },\n    /**\n     * specify the internal identifier to route to\n     */\n    identifierPropertyValue: {\n      type: [Number, String],\n      default: '',\n    },\n    /**\n     * specify an internal path to link, only for type chip links\n     */\n    path: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify how a link element should be rendered\n     * this needs to be a valid vue link component string (e.g. `RouterLink`) or a component directly\n     * and vue-router is necessary\n     *\n     * **caveat**: if you are using Nuxt the string `'NuxtLink'` is not enough,\n     *  but you need to import the component as `import { NuxtLink } from '#components';`\n     *  and pass the component to the prop!\n     */\n    renderLinkAs: {\n      type: [String, Object],\n      default: 'RouterLink',\n    },\n    /**\n     * add a space \" \" after an element\n     * useful for link-type tooltip in lists\n     */\n    spaceAfter: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify texts for the title tag depending on a link type (especially helpful to provide language-specific text)\n     * this needs to be an object with the following properties\n     * (if you don't want to display any specific text, leave an empty string):\n     *\n     *     **chip**: Text is shown on hover of a chip link and gets merged with the type and value attributes.\n     *     **tooltip**: Text is shown on hover of a tooltip link.\n     *     **type**: Text for a single chip type.\n     *       This needs to be an object containing properties matching the different chip types.\n     */\n    titleText: {\n      type: Object,\n      default: () => ({\n        chip: 'Open {type} {value} in search',\n        tooltip: 'Show more information',\n        type: {\n          artists: 'artist',\n          keywords: 'keyword',\n        },\n      }),\n      // checking if all necessary properties are part of the provided object\n      validator: val => ['chip', 'tooltip', 'type'].every(prop => Object.keys(val).includes(prop)),\n    },\n    /**\n     * specify tooltip content\n     * Prop must be either set true or an Object[] to render a type tooltip link.\n     * **Object[]**:\n     *   - `[{ label: 'label', value: 'value', altTitle?: 'altTitle',  url: '#' }]` to render a content list\n     *   - any other structure in combination with the slot `#tooltip`\n     * **Boolean**: use the slot `#tooltip` to customize the content\n     */\n    tooltip: {\n      type: [Boolean, Array],\n      default: false,\n    },\n    /**\n     * async tooltip content, e.g. source, id where to fetch data from\n     * if set, event `@tooltip-clicked` with this object will be emitted\n     */\n    tooltipAsync: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * additional tooltip styles\n     * **caveat**: properties `top`, `left`, `right` will be overwritten due position calculation\n     */\n    tooltipStyles: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * specify how the tooltipBox component is rendered on mobile resolutions\n     *\n     * *box*: component is rendered directly at the info icon\n     * *modal*: component is rendered as a modal popup\n     * *fullscreen*: component is rendered as ap popup with max height and width\n     */\n    tooltipTypeOnMobile: {\n      type: String,\n      default: 'box',\n      validator: val => ['box', 'fullscreen', 'modal'].includes(val),\n    },\n    /**\n     * specify a threshold value in px for the [BaseTooltipBox](BaseTooltipBox) top position calculation\n     *\n     * Note: The value can also be set globally with the CSS variable `--base-tooltip-box-threshold-top`.\n     *       The property will be overwritten by the CSS variable.\n     */\n    tooltipThresholdTop: {\n      type: Number,\n      default: 0,\n    },\n    /**\n     * used in combination with property `identifierPropertyValue` to render a type `chip` element.\n     * `type` identifies a source type for chip click-event e.g.: keyword | skill | object\n     */\n    type: {\n      type: String,\n      default: '',\n    },\n    /**\n     * external url to link to\n     * supported protocols: `http://`, `https://`, `mailto:`, `tel:`\n     */\n    url: {\n      type: String,\n      default: '',\n    },\n    /**\n     * value of the entry\n     */\n    value: {\n      type: String,\n      default: '',\n    },\n    /**\n     *  use this property to set the title attribute\n     *  also for link types other than `chip` and `tooltip`\n     *\n     * if `interpretTextAsHtml` is set `true` for type `chip` and `tootlip`\n     *  add a html-free version of `value` here to be used for the `title`\n     *  attribute and with assistive technologies\n     */\n    altTitle: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set additional attributes directly on the link element,\n     *  this can be HTML link element native attributes or framework\n     *  specific props (e.g. `aria-current-value` to set the aria-current\n     *  attribute, for more possibilities check out the\n     *  [Vue-Router documentation](https://v3.router.vuejs.org/api/)\n     */\n    additionalAttributes: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * set true to render link `value` as html\n     *\n     *  **caveat**: setting this variable `true` can lead to XSS attacks. Only use\n     *    this prop on trusted content and never on user-provided content.\n     */\n    interpretTextAsHtml: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['tooltip-clicked', 'chip-clicked'],\n  setup() {\n    /** INTERNAL ID */\n    const internalId = useId();\n\n    /** TOOLTIP VISIBILITY HANDLING */\n    /**\n     * variable to store if tooltip should be shown\n     * @type {Ref<UnwrapRef<boolean>>}\n     */\n    const showTooltip = ref(false);\n\n    /**\n     * close an open tooltip\n     */\n    function closeTooltip() {\n      if (!showTooltip.value) return;\n      showTooltip.value = false;\n    }\n    /**\n     * intercept scroll/resize event and close the tooltip\n     */\n    function scrollResizeHandler() {\n      if (showTooltip.value) {\n        closeTooltip();\n      }\n    }\n\n    // use the window resize event listener\n    useWindowResize({\n      callback: scrollResizeHandler,\n      setDebounce: 100,\n    });\n    // and additionally create a scroll event listener to also\n    // close the tooltip when scrolling is happening on the page\n    useEventListener({\n      // need to pass a string since window not defined in setup for SSR\n      target: 'window',\n      event: 'scroll',\n      callback: scrollResizeHandler,\n      setDebounce: 100,\n    });\n\n    // access slots to check if it is filled later\n    const slots = useSlots();\n    // slot is not directly accessible anymore - use composable to determine\n    // if slot has content\n    const { slotHasContent } = useHasSlotContent(slots.tooltip);\n\n    /** DETERMINE ELEMENT TYPE */\n    // we need to access the current component instance\n    // to check for router\n    const { app } = getCurrentInstance().appContext;\n\n    /**\n     * check if vue router is available\n     * @type {ComputedRef<boolean>}\n     */\n    const isRouterAvailable = computed(() => !!app.config.globalProperties?.$router);\n\n    return {\n      internalId,\n      slotHasContent,\n      showTooltip,\n      isRouterAvailable,\n    };\n  },\n  data() {\n    return {\n      isLoading: false,\n    };\n  },\n  computed: {\n    altTitleInt() {\n      return this.altTitle || this.value;\n    },\n    /**\n     * object added as value to `[chipQueryName]` query param when a chip is clicked\n     * @returns {Object}\n     */\n    chipObj() {\n      const obj = {};\n      obj[this.identifierPropertyName] = this.identifierPropertyValue;\n      obj.type = this.type;\n      // this should not have html in it so we use altTitle if provided\n      obj.value = this.altTitleInt;\n      return obj;\n    },\n    /**\n     * check if an url is set and includes a protocol\n     * e.g. 'http://', 'https://', 'mailto:' or 'tel:'\n     *\n     * @returns {boolean}\n     */\n    hasValidUrl() {\n      //\n      return !!(this.url\n        && (this.url.match(/^([a-z][a-z0-9+\\-.]*:\\/\\/)/)\n            || this.url.match(/^mailto:/)\n            || this.url.match(/^tel:/)));\n    },\n    /**\n     * check if the link is type `chip`\n     * @returns {boolean}\n     */\n    isChip() {\n      return !!(this.identifierPropertyValue && this.type);\n    },\n    /**\n     * check if the link is type `external`\n     * @returns {boolean}\n     */\n    isExternal() {\n      return this.hasValidUrl;\n    },\n    /**\n     * check if the link is type `internal`\n     * @returns {boolean}\n     */\n    isInternal() {\n      return !!(this.identifierPropertyValue && !this.type);\n    },\n    /**\n     * check if the link is type `tooltip`\n     * @returns {boolean}\n     */\n    isTooltip() {\n      return !!(this.tooltip || this.tooltip.length || this.tooltipAsync.length);\n    },\n    /**\n     * render component with a specific tag\n     * @returns {'a' | 'router-link' | 'span'}\n     */\n    renderAs() {\n      // external\n      if (this.isExternal) {\n        return 'a';\n      }\n      // internal, chip\n      if (this.isInternal || this.isChip) {\n        return this.isRouterAvailable ? this.renderLinkAs : 'a';\n      }\n      // default, e.g. tooltip\n      return 'span';\n    },\n    /**\n     * link attributes (href, target, to) to bind to the component\n     * depending on link type and router availability\n     * @returns {Object}\n     */\n    linkAttributes() {\n      const router = this.isRouterAvailable ? 'to' : 'href';\n      const obj = {};\n\n      if (this.isExternal) {\n        obj.href = this.url;\n        obj.target = this.externalLinkTarget;\n      }\n\n      if (this.isInternal) {\n        obj[router] = this.identifierPropertyValue;\n      }\n\n      if (this.isChip) {\n        obj[router] = `${this.path}?${this.chipQueryName}=${JSON.stringify(this.chipObj)}`;\n      }\n\n      return {\n        // add attributes set from outside\n        ...this.additionalAttributes,\n        ...obj,\n      };\n    },\n    /**\n     * build the title attribute depending on the current link type\n     * @returns {null|string}\n     */\n    title() {\n      if (this.isTooltip) {\n        return this.altTitle || this.titleText.tooltip;\n      }\n      if (this.isChip) {\n        return this.titleText.chip\n          // replace the placeholder with a matching translated type, otherwise with an empty string\n          .replace('{type}', this.titleText.type[this.type] ? this.titleText.type[this.type] : '')\n          // replace the placeholder with the value (no translation needed)\n          .replace('{value}', this.altTitleInt)\n          // remove multiple spaces with a single space\n          .replace(/\\s+/g, ' ');\n      }\n      // for all other types set the altTitle as title attribute if it was defined\n      if (this.altTitle) {\n        return this.altTitle;\n      }\n      // default\n      return null;\n    },\n  },\n  watch: {\n    tooltip(val) {\n      if (val) {\n        this.isLoading = false;\n        this.showTooltip = true;\n      }\n    },\n  },\n  methods: {\n    /**\n     * handle click events for different link types\n     */\n    clickHandler() {\n      if (this.isTooltip) {\n        this.tooltipClicked();\n      }\n    },\n    /**\n     * handle tooltip click event\n     */\n    async tooltipClicked() {\n      // check if there is content to display\n      if ((this.tooltip && this.slotHasContent) || this.tooltip.length) {\n        this.showTooltip = !this.showTooltip;\n        return;\n      }\n      // check if there is a data definition to load async from\n      if (this.tooltipAsync.length) {\n        this.isLoading = true;\n        /**\n         * @event tooltip-clicked\n         * @param {Array} - async tooltip content\n         *\n         */\n        this.$emit('tooltip-clicked', this.tooltipAsync);\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <!-- v-clean-dom-nodes is here because space was added before and after the link which\n    was not the desired effect when link was followed by a comma in BaseTextList - also\n    see ticket #2283#note-11 -->\n  <component\n    :is=\"renderAs\"\n    v-bind=\"linkAttributes\"\n    v-clean-dom-nodes\n    :aria-controls=\"isTooltip ? `tooltipBox-${internalId}`: undefined\"\n    :aria-expanded=\"isTooltip ? showTooltip : undefined\"\n    :aria-label=\"isChip || isTooltip ? title : undefined\"\n    :tabindex=\"isTooltip ? 0 : undefined\"\n    :title=\"title\"\n    :class=\"[\n      'base-link',\n      {\n        'base-link--chip': isChip,\n        'base-link--internal': isInternal,\n        'base-link--external': isExternal,\n        'base-link--tooltip': isTooltip,\n        'base-link--active': showTooltip,\n        'base-link--space-after': spaceAfter,\n      },\n    ]\"\n    @keyup.enter=\"clickHandler\"\n    @click=\"clickHandler\">\n    <!-- chip, internal, external, text -->\n    <template\n      v-if=\"!isTooltip\">\n      <slot\n        name=\"label\"\n        :label=\"value\">\n        <BaseInsertTextAsHtml\n          :render-element-as=\"'span'\"\n          :text=\"value\"\n          :interpret-text-as-html=\"interpretTextAsHtml\"\n          :class=\"{ 'no-clean': interpretTextAsHtml }\" />\n      </slot>\n    </template>\n\n    <!-- (i) tooltip -->\n    <template\n      v-if=\"isTooltip\">\n      <span\n        class=\"base-link__label\">\n        <slot\n          name=\"label\"\n          :label=\"value\">\n          <BaseInsertTextAsHtml\n            :render-element-as=\"'span'\"\n            :text=\"value\"\n            :interpret-text-as-html=\"interpretTextAsHtml\"\n            :class=\"{ 'no-clean': interpretTextAsHtml }\" />\n        </slot>\n      </span>\n\n      <span\n        ref=\"icon\"\n        class=\"base-link__icon\">\n        <BaseIcon\n          v-show=\"!isLoading\"\n          name=\"information\" />\n      </span>\n\n      <span\n        v-if=\"isLoading\"\n        class=\"base-link__loader\">\n        <BaseLoader\n          v-if=\"isLoading\" />\n      </span>\n\n      <BaseTooltipBox\n        v-if=\"showTooltip\"\n        :id=\"`tooltipBox-${internalId}`\"\n        :attach-to=\"$refs.icon\"\n        :modal-on-mobile=\"false\"\n        :role=\"'tooltip'\"\n        :styles=\"tooltipStyles\"\n        :threshold-top=\"tooltipThresholdTop\"\n        :type-on-mobile=\"tooltipTypeOnMobile\"\n        @close=\"showTooltip = !showTooltip\">\n        <!-- @slot slot to inject content\n          @binding {Object} item - a tooltip object -->\n        <slot\n          name=\"tooltip\"\n          :item=\"tooltip\">\n          <span\n            v-if=\"tooltip.label\"\n            class=\"base-tooltip__label\">\n            {{ tooltip.label }}\n          </span>\n\n          <div\n            v-for=\"(item, index) in tooltip\"\n            :key=\"index\"\n            class=\"base-tooltip__row\">\n            {{ item.label }}:\n            <template v-if=\"item.url\">\n              <BaseInsertTextAsHtml\n                :render-element-as=\"'a'\"\n                :interpret-text-as-html=\"interpretTextAsHtml\"\n                :text=\"item.value\"\n                :href=\"item.url\"\n                :title=\"item.altTitle || undefined\"\n                class=\"base-link--external\" />\n            </template>\n            <!-- eslint-disable-next-line vue/singleline-html-element-content-newline max-len vue/max-attributes-per-line -->\n            <template v-else><BaseInsertTextAsHtml :render-element-as=\"'span'\" :interpret-text-as-html=\"interpretTextAsHtml\" :text=\"item.value\" /></template>\n          </div>\n        </slot>\n      </BaseTooltipBox>\n    </template>\n  </component>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-link {\n    transition-property: color, text-decoration-color, background-color;\n    transition-duration: 150ms;\n    transition-timing-function: ease-in-out;\n\n    &__label {\n      display: inline-block;\n      overflow: hidden;\n      text-overflow: ellipsis;\n      white-space: nowrap;\n    }\n\n    &__icon {\n      flex-shrink: 0;\n      position: relative;\n      display: inline-block;\n      height: $icon-small;\n      width: $icon-small;\n      margin-left: $spacing-small-half;\n\n      &:deep(svg){\n        vertical-align: top;\n        height: 100%;\n        width: 100%;\n      }\n\n      @media screen and (min-width: $mobile-min-width) {\n        height: $icon-medium;\n        width: $icon-medium;\n      }\n    }\n\n    &__loader {\n      position: relative;\n      right: $spacing-small;\n      display: inline-block;\n      transform: scale(0.35);\n    }\n\n    &--external {\n      position: relative;\n      text-decoration: underline;\n      text-decoration-color: $app-color;\n\n      &:focus,\n      &:hover {\n        color: $app-color-secondary;\n        text-decoration-color: $app-color-secondary;\n      }\n    }\n\n    &--internal {\n      color: $app-color;\n      cursor: pointer;\n\n      &:focus,\n      &:hover {\n        color: $app-color-secondary;\n      }\n    }\n\n    &--chip {\n      padding: 0 $spacing-small;\n      margin-right: $spacing-small;\n      background-color: $background-color;\n      text-decoration: none;\n\n      &:focus,\n      &:hover {\n        background-color: $app-color-secondary;\n        color: white;\n        text-decoration: none;\n      }\n    }\n\n    &--tooltip {\n      position: relative;\n      align-items: center;\n      display: inline-flex;\n      max-width: 100%;\n\n      svg {\n        display: inline-block;\n        transition: fill 150ms ease-in;\n      }\n\n      &:focus,\n      &:hover {\n        cursor: pointer;\n        color: $app-color-secondary;\n\n        svg {\n          fill: $app-color-secondary;\n        }\n      }\n    }\n\n    &--active {\n      svg {\n        fill: $app-color-secondary\n      }\n    }\n\n    &--space-after {\n      .base-link__label {\n        &:after {\n          content: \" \";\n          white-space: pre;\n        }\n      }\n    }\n  }\n</style>\n","<script>\nimport { defineAsyncComponent } from 'vue';\nimport BaseLink from '@/components/BaseLink/BaseLink.vue';\n\n/**\n * component to display breadcrumb-style navigation\n */\n\nexport default {\n  name: 'BaseBreadCrumbs',\n  components: {\n    BaseLink,\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue').then(m => m.default || m)),\n  },\n  props: {\n    /**\n     * specify an array with the properties `route`, `label` and (optional) `icon` and `showLabel` that\n     *  should be used for navigation - these have to be internal\n     *  links, i.e. without a protocol like `http:` or `mailto:` in the url\n     * `showLabel` set to false is only considered if the `icon` property is set!\n     */\n    routes: {\n      type: Array,\n      default: () => [{ route: '', label: '' }],\n      validator: arr => !arr.some(\n        val => (val.route\n            // check that link is specified without protocol\n            && !!(val.route.match(/^([a-z][a-z0-9+\\-.]*:\\/\\/)/)\n              || val.route.match(/^mailto:/)\n              || val.route.match(/^tel:/)))\n          // and check that icon is specified when `showLabel` is\n          || (val.showLabel === false && !val.icon),\n      ),\n    },\n    /**\n     * specify how a link element should be rendered\n     * this needs to be a valid vue link component string (e.g. `'RouterLink'`) or a component directly\n     * and vue-router is necessary\n     *\n     * **caveat**: if you are using Nuxt the string `'NuxtLink'` is not enough,\n     *  but you need to import the component as `import { NuxtLink } from '#components';`\n     *  and pass the component to the prop!\n     */\n    renderLinkAs: {\n      type: [String, Object],\n      default: 'RouterLink',\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    class=\"base-bread-crumbs\">\n    <template\n      v-for=\"({ route, label, showLabel, icon }, index) in routes\"\n      :key=\"route\">\n      <BaseLink\n        external-link-target=\"_self\"\n        :identifier-property-value=\"route\"\n        :value=\"label\"\n        :render-link-as=\"renderLinkAs\"\n        :additional-attributes=\"{ ariaCurrentValue: 'page' }\"\n        :class=\"['base-bread-crumbs__link', { 'base-bread-crumbs__link--icon-only': showLabel === false }]\">\n        <template\n          #label>\n          <span class=\"base-bread-crumbs__label\">\n            <BaseIcon\n              v-if=\"icon\"\n              :key=\"label\"\n              :name=\"icon\"\n              :title=\"showLabel === false ? label : undefined\"\n              :class=\"['base-bread-crumbs__icon',\n                       { 'base-bread-crumbs__icon--with-label': showLabel !== false }]\" />\n            <span\n              v-if=\"showLabel !== false\"\n              class=\"base-bread-crumbs__label-text\">\n              {{ label }}\n            </span>\n          </span>\n        </template>\n      </BaseLink>\n      <BaseIcon\n        v-if=\"index < routes.length - 1\"\n        :key=\"`${route}-separator`\"\n        name=\"next\"\n        class=\"base-bread-crumbs__separator\" />\n    </template>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n.base-bread-crumbs {\n  position: relative;\n  color: $font-color-second;\n  font-size: $font-size-small;\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  flex-wrap: wrap;\n\n  .base-bread-crumbs__link {\n    padding-right: $spacing-small-half;\n    display: flex;\n    align-items: center;\n    color: $font-color-second;\n    // get child to respect parent width\n    // (needed because of white-space: nowrap; further down the line)\n    min-width: 100px;\n\n    &.base-bread-crumbs__link--icon-only {\n      flex-shrink: 0;\n      min-width: $icon-medium;\n    }\n\n    &:hover {\n      text-decoration: none;\n    }\n\n    &:focus, &:hover {\n      color: $app-color;\n    }\n\n    &:nth-child(n+2) {\n      padding-left: $spacing-small-half;\n    }\n\n    &:last-child {\n      text-decoration: underline;\n    }\n\n    .base-bread-crumbs__label {\n      display: flex;\n      justify-content: center;\n      align-items: center;\n      overflow: hidden;\n\n      .base-bread-crumbs__icon {\n        width: $icon-medium;\n        height: $icon-medium;\n        margin: $spacing-small-half 0;\n        flex-shrink: 0;\n\n        &.base-bread-crumbs__icon--with-label {\n          margin: $spacing-small-half $spacing-small-half $spacing-small-half 0;\n        }\n      }\n\n      .base-bread-crumbs__label-text {\n        display: inline;\n        justify-content: flex-start;\n        align-items: center;\n        text-overflow: ellipsis;\n        overflow: hidden;\n      }\n    }\n  }\n\n  .base-bread-crumbs__separator {\n    height: $icon-min;\n    width: $icon-min;\n    flex-shrink: 0;\n    color: $font-color-second;\n  }\n}\n</style>\n","<script>\nimport { defineAsyncComponent, ref, useSlots, useTemplateRef } from 'vue';\nimport BaseBox from '@/components/BaseBox/BaseBox.vue';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\nimport { useWindowResize } from '@/composables/useWindowResize.js';\n\n/**\n * A component with the primary purpose to display\n * images in responsive boxes but also allowing for text only\n */\n\nexport default {\n  name: 'BaseImageBox',\n  components: {\n    BaseBox,\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseCheckmark: defineAsyncComponent(() => import('@/components/BaseCheckmark/BaseCheckmark.vue')),\n    BaseImage: defineAsyncComponent(() => import('@/components/BaseImage/BaseImage.vue')),\n    BaseImageGrid: defineAsyncComponent(() => import('@/components/BaseImageGrid/BaseImageGrid.vue')),\n    BaseInsertTextAsHtml: defineAsyncComponent(() => import('@/components/BaseInsertTextAsHtml/BaseInsertTextAsHtml.vue')),\n  },\n  props: {\n    /**\n     * The title of the item in question (max 2 lines), also used as img alt text\n     */\n    title: {\n      type: String,\n      default: 'No title',\n    },\n    /**\n     * specify a separate title to display on title hover and for the\n     *  image alt text. Useful for example if `interpretTextAsHtml` is\n     *  set `true` and the `title` contains HTML\n     */\n    altTitle: {\n      type: String,\n      default: '',\n    },\n    /**\n     * Text displayed directly below title (max two lines; max 3 lines with title)\n     */\n    subtext: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify a separate subtext to display on subtext hover. Useful for example\n     *  if `interpretTextAsHtml` is set `true` and the `subtext` contains HTML\n     */\n    altSubtext: {\n      type: String,\n      default: '',\n    },\n    /**\n     * should the title be displayed or box only display the image\n     */\n    showTitle: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * should the title be displayed on box hover\n     */\n    showTitleOnHover: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define the number of rows before the title is truncated with ...\n     *\n     * **auto**: If subtext is defined, the title is displayed in one row, otherwise in two rows.\n     * **1**: Title is displayed in one row.\n     */\n    titleRows: {\n      type: [String, Number],\n      default: 'auto',\n      validator: val => ['auto', 1].includes(val),\n    },\n    /**\n     * define a url to a single image\n     *\n     * data variants to render a single image using `src` or `srcset` for a responsive image:\n     * **src**: `'path'`\n     * **srcset**: `{ '640w': 'path' }`\n     */\n    imageUrl: {\n      type: [String, Object],\n      default: null,\n    },\n    /**\n     * define up to 4 image url to be displayed in a grid\n     *\n     * array variants to render a single image using `src` or `srcset` for a responsive image:\n     * **src**: `['path']`\n     * **srcset**: `[{ '640w': 'path' }]`\n     */\n    images: {\n      type: Array,\n      default: () => ([]),\n    },\n    /**\n     * display shadow overlays at the top and bottom of the image\n     * to make text easier to read\n     */\n    imageShadow: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define the margin (left, bottom, right) between the image footer and the image\n     * @values large, small\n     */\n    imageFooterMargin: {\n      type: String,\n      default: 'large',\n      validator: val => ['large', 'small'].includes(val),\n    },\n    /**\n     * descriptive element displayed at bottom of box (e.g. item type like \"Bilderserie\")\n     */\n    description: {\n      type: String,\n      default: null,\n    },\n    /**\n     * descriptive element displayed at bottom of box (e.g. item type like \"Bilderserie\")\n     */\n    additional: {\n      type: String,\n      default: null,\n    },\n    /**\n     * set optional icon\n     * e.g. for items without image\n     */\n    icon: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set optional icon size\n     */\n    iconSize: {\n      type: String,\n      default: 'xxlarge',\n      validator: val => ['small', 'medium', 'large', 'xlarge', 'xxlarge'].includes(val),\n    },\n    /**\n     * display play icon\n     * e.g. for Video, Audio files\n     */\n    playIcon: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * determines if the box should be selectable and the checkbox is displayed\n     */\n    selectable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set prop true if box can be dragged - used solely for styling purposes\n     */\n    draggable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set select status (checkbox checked) from outside\n     */\n    selected: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify the size of the box\n     */\n    boxSize: {\n      type: Object,\n      default: () => ({ width: 'auto', height: 'auto' }),\n    },\n    /**\n     * specify any text that should be displayed instead of an image;\n     * each array element on new line\n     */\n    boxText: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * specify lazy image loading\n     */\n    lazyload: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify position of image\n     */\n    imageFirst: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify if header should be centered horizontally\n     * (aligned left otherwise)\n     */\n    centerHeader: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define html element that should be rendered\n     * this could either be a native HTML element or a framework specific component\n     * name (e.g. `'RouterLink'`) or a component passed directly\n     *\n     * **caveat**: if you are using Nuxt the string `'NuxtLink'` is not enough,\n     *  but you need to import the component as `import { NuxtLink } from '#components';`\n     *  and pass the component to the prop!\n     */\n    renderElementAs: {\n      type: [String, Object],\n      default: 'div',\n    },\n    /**\n     * if element is rendered as vue link component, specify a value for the `to` attribute\n     * can either be a string or a `vue-router` Location object (= object with `path` property\n     * and optional `params` or `query` object)\n     * (this needs vue-router)\n     */\n    linkTo: {\n      type: [String, Object],\n      default: '',\n      validator: val => typeof val === 'string'\n        || (val instanceof Object && Object.keys(val).includes('path')),\n    },\n    /**\n     * if necessary box text (`title`, `subtext`, `boxText`) can\n     *  be rendered as html\n     *\n     *  *tip*: do not forget to set prop `altTitle` and/or `altSubtext` if the\n     *    title text or subtext contains html - otherwise the complete html will\n     *    be displayed on text hover and for image alt text\n     *\n     *  **caveat**: setting this variable `true` can lead to XSS attacks. Only use\n     *    this prop on trusted content and never on user-provided content.\n     */\n    interpretTextAsHtml: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['clicked', 'select-triggered'],\n  setup(props) {\n    /** SLOT DISPLAY */\n      // import slots with vue\n    const slots = useSlots();\n    /**\n     * check if slot `icon` has content\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const { slotHasContent: iconSlotHasContent } = useHasSlotContent(slots.icon);\n    /**\n     * check if slot `footer-right` has content\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const { slotHasContent: footerRightSlotHasContent } = useHasSlotContent(slots['footer-right']);\n    /**\n     * check if slot `footer-left` has content\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const { slotHasContent: footerLeftSlotHasContent } = useHasSlotContent(slots['footer-left']);\n    /**\n     * check if slot `title-right` has content\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const { slotHasContent: titleRightSlotHasContent } = useHasSlotContent(slots['title-right']);\n\n    /** BOX TEXT DISPLAY */\n    /**\n     * template reference to the root element\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const baseBox = useTemplateRef('baseBoxElement');\n    /**\n     * template reference to the root element\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const headerBox = useTemplateRef('headerBoxElement');\n    /**\n     * template reference to the box text wrapper element\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const boxText = useTemplateRef('boxTextElement');\n    /**\n     * template reference to the box text body element\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const boxTextInner = useTemplateRef('boxTextInnerElement');\n\n    /**\n     * needed to set text height and line-clamp correctly after resize\n     * @type {[{}] extends [Ref] ? IfAny<{}, Ref<{}>, {}> : Ref<UnwrapRef<{}>, UnwrapRef<{}> | {}>}\n     */\n    const boxTextStyle = ref({});\n\n    // add an 'resize' event listener so boxText display can be re-calculated\n    useWindowResize({\n      callback: calcTextHeight,\n      setDebounce: 500,\n      callOnMounted: true,\n    });\n\n    /**\n     * function to calculate the text box height and and line-clamp\n     * based on actually box height (-description if necessary)\n     */\n    function calcTextHeight() {\n      // only do this if no image is present and the boxText variable has items\n      // and all the ui elements are there\n      if (!props.imageUrl && props.boxText.length\n        && baseBox.value && boxText.value) {\n        let headerHeight = 0;\n        if (headerBox.value) {\n          const elemInnerHeight = headerBox.value.clientHeight;\n          const boxMargin = headerBox.value.offsetTop;\n          headerHeight = elemInnerHeight + (2 * boxMargin);\n        }\n        // get single text line in the text element (for line height only)\n        const lineElement = boxTextInner.value[0] || boxTextInner.value;\n        // get the height of the complete box\n        const boxHeight = baseBox.value.$el.clientHeight;\n        // get the line height property\n        const lineHeight = window.getComputedStyle(lineElement, null)\n          .getPropertyValue('line-height').replace('px', '');\n        // get the box margin\n        const boxMargin = window.getComputedStyle(boxText.value, null)\n          .getPropertyValue('margin-bottom').replace('px', '');\n        // calculate the actual text box height from\n        // complete box height - header height - box margin (bottom)\n        let textBoxHeight = boxHeight - headerHeight - boxMargin;\n        // if there is a description also leave space for that so its not overlapping\n        // TODO: check if this is wanted\n        if (props.description) {\n          textBoxHeight -= lineHeight;\n        }\n        // calculate how many lines can be displayed\n        const lines = Math.floor(textBoxHeight / lineHeight);\n        // set the style of the text box\n        boxTextStyle.value = {\n          height: `${lineHeight * lines}px`,\n          '-webkit-line-clamp': lines,\n        };\n      }\n    }\n\n    return {\n      // slot display\n      iconSlotHasContent,\n      footerRightSlotHasContent,\n      footerLeftSlotHasContent,\n      titleRightSlotHasContent,\n      // text display\n      boxTextStyle,\n      calcTextHeight,\n    };\n  },\n  data() {\n    return {\n      /**\n       * internal variable for selection status\n       */\n      selectedInt: false,\n      /**\n       * steer displaying of image in case of display error\n       */\n      displayImage: true,\n    };\n  },\n  computed: {\n    /**\n     * compute the alt title used for title hover and image alt description\n     *  from specific prop `altTitle` or use the regular title\n     * @returns {string}\n     */\n    altTitleInt() {\n      return this.altTitle || this.title;\n    },\n    /**\n     * compute the alt subtext used for subtext hover\n     *  from specific prop `altSubtext` or use the regular subtext\n     * @returns {string}\n     */\n    altSubtextInt() {\n      return this.altSubtext || this.subtext;\n    },\n    // determine if a shadow at the top of the image should be visible\n    imageShadowTop() {\n      return (this.selectable && this.hasImages && !this.showTitle)\n        || (this.selectable && this.hasImages && this.imageFirst);\n    },\n    // determine if a shadow at the bottom of the image should be visible\n    imageShadowBottom() {\n      return this.imageShadow && !this.icon\n        && (!this.showTitleOnHover || (this.showTitleOnHover && this.additional));\n    },\n    // determine if there is one or more images to display\n    hasImages() {\n      return !!(this.imageUrl || (this.images && this.images.length));\n    },\n  },\n  watch: {\n    // TODO: could probably just be added to boxSelect method?\n    selectedInt(val) {\n      if (val !== this.selected) {\n        /**\n         * event triggered when box is selectable and clicked upon\n         *\n         * @event select-triggered\n         * @param { Boolean } - was box selected\n         */\n        this.$emit('select-triggered', val);\n      }\n    },\n    selected(val) {\n      if (this.selectedInt !== val) {\n        this.selectedInt = val;\n      }\n    },\n    boxText() {\n      this.calcTextHeight();\n    },\n  },\n  mounted() {\n    this.selectedInt = this.selected;\n  },\n  methods: {\n    boxSelect() {\n      if (this.selectable) {\n        this.selectedInt = !this.selectedInt;\n      } else {\n        /**\n         * event triggered when selectable is false and box is clicked\n         *\n         * @event clicked\n         */\n        this.$emit('clicked');\n      }\n    },\n    /**\n     * get single src\n     *\n     * @param {string|object} data\n     * @returns {string}\n     */\n    src(data) {\n      return typeof data === 'string'\n        ? data\n        // get last array elements path\n        : Object.entries(data).slice(-1)[0][1];\n    },\n    /**\n     * get srcset\n     *\n     * @param {array} data\n     * @returns {array}\n     */\n    srcset(data) {\n      return typeof data === 'object' ? [data] : [];\n    },\n  },\n};\n</script>\n\n<template>\n  <BaseBox\n    ref=\"baseBoxElement\"\n    :box-size=\"boxSize\"\n    :render-element-as=\"renderElementAs\"\n    :additional-attributes=\"linkTo ? { to: linkTo } : {}\"\n    box-ratio=\"100\"\n    @clicked=\"boxSelect\">\n    <div\n      :class=\"['base-image-box',\n               { 'base-image-box--hover': (playIcon || showTitleOnHover) && !selectable },\n               { 'base-image-box--hover-show-title': showTitleOnHover && !selectable },\n               { 'base-image-box--selectable': selectable },\n               { 'base-image-box--draggable': draggable }, // needs to be after selectable\n               { 'base-image-box--selected': selectable && selectedInt }]\">\n      <!-- HEADER -->\n      <div\n        v-if=\"showTitle\"\n        ref=\"headerBoxElement\"\n        :class=\"['base-image-box__header',\n                 { 'base-image-box__header--bottom': imageFirst },\n                 { 'base-image-box__header--center-text': centerHeader },\n                 { 'base-image-box__header--separator-top': !hasImages && !imageShadow && imageFirst },\n                 { 'base-image-box__header--separator-bottom': !hasImages && !imageShadow && !imageFirst }]\">\n        <div\n          class=\"base-image-box__header__row\">\n          <BaseInsertTextAsHtml\n            :render-element-as=\"'div'\"\n            :text=\"title\"\n            :interpret-text-as-html=\"interpretTextAsHtml\"\n            :title=\"altTitleInt\"\n            :class=\"['base-image-box__header__text',\n                     'base-image-box__header__text--bold',\n                     { 'base-image-box__header__text--2-lines': !subtext && titleRows === 'auto' }]\" />\n          <div\n            v-if=\"titleRightSlotHasContent\"\n            class=\"base-image-box__header__row__additional\">\n            <!-- @slot create custom content (e.g. additional text or icon) right of the title -->\n            <slot name=\"title-right\" />\n          </div>\n        </div>\n        <div\n          v-if=\"subtext\"\n          class=\"base-image-box__header__row\">\n          <BaseInsertTextAsHtml\n            :render-element-as=\"'div'\"\n            :text=\"subtext\"\n            :interpret-text-as-html=\"interpretTextAsHtml\"\n            :title=\"altSubtextInt\"\n            class=\"base-image-box__header__text\" />\n        </div>\n      </div>\n\n      <!-- BODY -->\n      <div\n        :class=\"['base-image-box__body',\n                 { 'base-image-box__body__shadow--top': imageShadowTop },\n                 { 'base-image-box__body__shadow--bottom': imageShadowBottom },\n                 { 'base-image-box__body__shadow--height-1-3': imageShadow && imageFirst },\n                 { 'base-image-box__body__shadow--height-1-2': imageShadow && !imageFirst }]\">\n        <!-- IMAGE / IMAGE-GRID -->\n        <template\n          v-if=\"(imageUrl || images.length) && displayImage\">\n          <!-- single image (handle errors, e.g. for uploads) -->\n          <BaseImage\n            v-if=\"imageUrl || (images && images.length === 1)\"\n            ref=\"image\"\n            :alt=\"altTitleInt\"\n            :lazyload=\"lazyload\"\n            :src=\"images && images.length === 1 ? src(images[0]) : src(imageUrl)\"\n            :srcset=\"images && images.length === 1 ? srcset(images[0]) : srcset(imageUrl)\"\n            :class=\"['base-image-box__body__image']\"\n            @error=\"displayImage = false\" />\n\n          <!-- image grid -->\n          <BaseImageGrid\n            v-if=\"images && images.length > 1\"\n            :alt=\"altTitleInt\"\n            :images=\"images\"\n            :lazyload=\"lazyload\" />\n        </template>\n\n        <!-- ICONS -->\n        <div\n          v-if=\"icon || iconSlotHasContent\"\n          :class=\"['base-image-box__body__icon',\n                   'base-image-box__icon',\n                   'base-image-box__icon--' + iconSize]\">\n          <!-- @slot create custom content (e.g. folder icon) -->\n          <slot\n            :icon=\"icon\"\n            name=\"icon\">\n            <!-- display optional icon for entries without an image -->\n            <BaseIcon\n              :name=\"icon\"\n              :class=\"['base-image-box__icon',\n                       'base-image-box__icon--' + iconSize]\" />\n          </slot>\n        </div>\n\n        <!-- display optional play icon e.g. for video, audio -->\n        <BaseIcon\n          v-if=\"playIcon\"\n          name=\"play\"\n          :class=\"['base-image-box__body__icon',\n                   'base-image-box__icon',\n                   'base-image-box__icon--play',\n                   'base-image-box__icon--' + iconSize]\" />\n\n        <!-- BODY TEXT -->\n        <!-- alternative text, when no images are set -->\n        <div\n          v-if=\"!hasImages || !displayImage\"\n          ref=\"boxTextElement\"\n          class=\"base-image-box__body__text\">\n          <!-- @slot to display more advanced text - if you use this please specify the `ref` attribute with `boxTextInnerElement` that has the line-height css attribute set - so the text display height can be calculated correctly! -->\n          <slot\n            :text=\"boxText\"\n            name=\"text\">\n            <!-- default -->\n            <div\n              ref=\"boxTextInnerElement\"\n              :style=\"boxTextStyle\"\n              class=\"base-image-box__body__text__inner\">\n              <BaseInsertTextAsHtml\n                v-for=\"(entry, index) in boxText\"\n                :key=\"index\"\n                :render-element-as=\"'div'\"\n                :text=\"entry\"\n                :interpret-text-as-html=\"interpretTextAsHtml\" />\n            </div>\n          </slot>\n        </div>\n\n        <!-- FOOTER -->\n        <div\n          :class=\"['base-image-box__body__footer',\n                   'base-image-box__body__footer--position-margin-' + imageFooterMargin,\n                   { 'base-image-box__body__footer--invert': icon }]\">\n          <div\n            v-if=\"footerLeftSlotHasContent\"\n            class=\"base-image-box__body__footer__left\">\n            <!-- @slot create custom content (e.g. featured icon for files) left of text -->\n            <slot name=\"footer-left\" />\n          </div>\n\n          <div class=\"base-image-box__body__footer__center\">\n            <BaseInsertTextAsHtml\n              v-if=\"showTitleOnHover\"\n              :render-element-as=\"'div'\"\n              :text=\"title\"\n              :interpret-text-as-html=\"interpretTextAsHtml\"\n              :title=\"altTitleInt\"\n              class=\"base-image-box__body__footer__title base-image-box__body__footer__title--bold\" />\n            <div\n              v-if=\"description\"\n              :title=\"description\"\n              :class=\"['base-image-box__body__footer__text',\n                       { 'base-image-box__body__footer__text--bold': !additional }]\">\n              {{ description }}\n            </div>\n            <div\n              v-if=\"additional\"\n              :title=\"additional\"\n              :class=\"['base-image-box__body__footer__text',\n                       'base-image-box__body__footer__text--bold']\">\n              {{ additional }}\n            </div>\n          </div>\n\n          <div\n            v-if=\"footerRightSlotHasContent || playIcon\"\n            class=\"base-image-box__body__footer__right\">\n            <!-- display optional play icon e.g. for video, audio -->\n            <BaseIcon\n              v-if=\"playIcon\"\n              name=\"play\"\n              :class=\"['base-image-box__icon',\n                       'base-image-box__icon--small',\n                       'base-image-box__icon--play']\" />\n            <!-- @slot create custom content (e.g. published icon for files) left of text -->\n            <slot name=\"footer-right\" />\n          </div>\n        </div>\n      </div>\n\n      <!-- FEATURES -->\n      <div\n        class=\"base-image-box__features\">\n        <transition\n          name=\"slide-fade\">\n          <BaseCheckmark\n            v-if=\"selectable\"\n            :model-value=\"selectedInt\"\n            :label=\"altTitleInt\"\n            mark-style=\"checkbox\"\n            check-box-size=\"large\"\n            class=\"base-image-box__checkbox\"\n            @update:model-value=\"boxSelect\" />\n        </transition>\n      </div>\n    </div>\n  </BaseBox>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n  .base-image-box {\n    display: flex;\n    flex-direction: column;\n    background-color: #ffffff;\n\n    // set absolute to keep baseBox ratio\n    position: absolute;\n    width: 100%;\n    height: 100%;\n\n    /* HEADER */\n    &__header {\n      display: flex;\n      flex-wrap: wrap;\n      flex-shrink: 0;\n      align-items: center;\n      padding: $spacing;\n      line-height: $line-height; /* fallback */\n      height: $line-height * 2 + $spacing * 2;\n      width: 100%;\n\n      &__row {\n        width: 100%;\n        display: flex;\n        align-items: center;\n\n        &__additional {\n          color: #666;\n          font-size: $font-size-small;\n          margin-left: $spacing-small;\n        }\n      }\n\n      &__text {\n        overflow: hidden;\n        white-space: nowrap;\n        text-overflow: ellipsis;\n\n        &--2-lines {\n          white-space: normal;\n          text-overflow: initial;\n\n          display: -webkit-box;\n          -webkit-line-clamp: 2;\n          -webkit-box-orient: vertical;\n          max-height: 100%;\n        }\n\n        &--bold {\n          font-weight: bold;\n        }\n      }\n\n      &--center-text {\n        .base-image-box__header__row {\n          justify-content: center;\n          text-align: center;\n        }\n      }\n\n      &--bottom {\n        order: 1;\n      }\n\n      &--separator-top  {\n        border-top: 3px solid $background-color;\n      }\n\n      &--separator-bottom  {\n        border-bottom: 3px solid $background-color;\n      }\n    }\n\n    /* ICONS */\n    &__icon {\n\n      &--xxlarge {\n        height: $icon-xxlarge;\n        max-width: $icon-xxlarge;\n        width: $icon-xxlarge;\n      }\n\n      &--xlarge {\n        height: $icon-xlarge;\n        max-width: $icon-xlarge;\n        width: $icon-xlarge;\n      }\n\n      &--large {\n        height: $icon-large;\n        max-width: $icon-large;\n        width: $icon-large;\n      }\n\n      &--medium {\n        height: $icon-medium;\n        max-width: $icon-medium;\n        width: $icon-medium;\n      }\n\n      &--small {\n        height: $icon-small;\n        max-width: $icon-small;\n        width: $icon-small;\n      }\n\n      &--play {\n        opacity: 0;\n        z-index: 1;\n        fill: $app-color;\n      }\n    }\n\n    /* BODY */\n    &__body {\n      flex: 1;\n      position: relative;\n      overflow: hidden;\n\n      &__image {\n        object-fit: cover;\n        height: 100% !important; // TODO: add to baseImage\n        width: 100%;\n      }\n\n      &__icon {\n        position: absolute;\n        top: 50%;\n        left: 50%;\n        transform: translate(-50%, -50%);\n        pointer-events: none;\n        fill: $font-color-second;\n      }\n\n      &__text {\n        display: flex;\n        margin: 0 $spacing $spacing;\n        width: calc(100% - 2 * #{$spacing});\n\n        &__inner {\n          overflow-wrap: break-word;\n          overflow: hidden;\n          display: -webkit-box;\n          text-overflow: ellipsis;\n          -webkit-box-orient: vertical;\n          -webkit-line-clamp: 1;\n          height: 100%;\n          line-height: $line-height; /* fallback */\n        }\n      }\n\n      &__footer {\n        position: absolute;\n        color: #ffffff;\n        z-index: 1;\n\n        display: flex;\n        justify-content: flex-start;\n        align-items: center;\n\n        &__left {\n          display: flex;\n          margin-right: $spacing-small;\n        }\n\n        &__center {\n          flex-grow: 1;\n          overflow: hidden;\n        }\n\n        &__right {\n          display: flex;\n          align-items: center;\n          margin-left: $spacing;\n\n          .base-image-box__icon--play {\n            opacity: 1;\n            fill: white;\n            height: $icon-medium;\n            width: $icon-medium;\n            min-width: $icon-medium;\n            margin-right: $spacing-small-half;\n          }\n        }\n\n        &__title,\n        &__text {\n          flex: 1;\n          text-overflow: ellipsis;\n          overflow: hidden;\n          white-space: nowrap;\n\n          &--bold {\n            font-weight: bold;\n          }\n        }\n\n        &__title {\n          display: none;\n        }\n\n        &--position-margin-large {\n          bottom: $spacing;\n          left: $spacing;\n          right: $spacing;\n        }\n\n        &--position-margin-small {\n          bottom: $spacing-small;\n          left: $spacing-small;\n          right: $spacing-small;\n        }\n\n        &--invert {\n          color: $font-color;\n\n          .base-image-box__body__footer__right {\n\n            .base-image-box__icon--play {\n              fill: $font-color;\n            }\n          }\n        }\n      }\n\n      &__shadow {\n        &--top {\n          &:before {\n            content: \"\";\n            width: 100%;\n            min-height: $row-height-large;\n            position: absolute;\n            top: 0;\n            right: 0;\n            z-index: 1;\n            background: linear-gradient(\n                to top, hsla(0, 0%, 0%, 0) 0%,\n                hsla(0, 0%, 0%, 0.017) 11.9%,\n                hsla(0, 0%, 0%, 0.062) 22.5%,\n                hsla(0, 0%, 0%, 0.13) 32.2%,\n                hsla(0, 0%, 0%, 0.211) 41.2%,\n                hsla(0, 0%, 0%, 0.3) 50%,\n                hsla(0, 0%, 0%, 0.389) 58.8%,\n                hsla(0, 0%, 0%, 0.47) 67.8%,\n                hsla(0, 0%, 0%, 0.538) 77.5%,\n                hsla(0, 0%, 0%, 0.583) 88.1%,\n                hsla(0, 0%, 0%, 0.6) 100%);\n          }\n        }\n\n        &--bottom {\n          &:after {\n            content: \"\";\n            width: 100%;\n            min-height: $row-height-large;\n            position: absolute;\n            bottom: 0;\n            right: 0;\n            background: linear-gradient(\n                to bottom, hsla(0, 0%, 0%, 0) 0%,\n                hsla(0, 0%, 0%, 0.017) 11.9%,\n                hsla(0, 0%, 0%, 0.062) 22.5%,\n                hsla(0, 0%, 0%, 0.13) 32.2%,\n                hsla(0, 0%, 0%, 0.211) 41.2%,\n                hsla(0, 0%, 0%, 0.3) 50%,\n                hsla(0, 0%, 0%, 0.389) 58.8%,\n                hsla(0, 0%, 0%, 0.47) 67.8%,\n                hsla(0, 0%, 0%, 0.538) 77.5%,\n                hsla(0, 0%, 0%, 0.583) 88.1%,\n                hsla(0, 0%, 0%, 0.6) 100%);\n          }\n        }\n\n        &--height-1-3:after {\n          height: 33%;\n        }\n\n        &--height-1-2:after {\n          height: 50%;\n        }\n      }\n    }\n\n    /* FEATURES */\n    &__features {\n      position: absolute;\n      top: 0;\n      right: 0;\n      z-index: 10;\n      display: flex;\n      justify-content: flex-end;\n\n      .base-image-box__checkbox {\n        margin-top: $spacing-small;\n        margin-right: $spacing-small;\n      }\n    }\n\n    &:not(.base-image-box--selected) {\n      &:deep(.base-image-box__features) .base-checkmark-container {\n        border-color: $app-color;\n      }\n    }\n\n    /* Modifiers */\n    &.base-image-box--draggable {\n      cursor: move;\n    }\n\n    &--selectable {\n      cursor: pointer;\n\n      // if header is aligned to bottom (image first),\n      // we dont need to shorten the header container\n      .base-image-box__header:not(.base-image-box__header--bottom) {\n        .base-image-box__header__row {\n          width: 80%;\n        }\n      }\n    }\n\n    &--selected {\n      &:after {\n        content: '';\n        width: 100%;\n        height: 100%;\n        position: absolute;\n        top: 0;\n        right: 0;\n        background-color: $app-color;\n        opacity: 0.75;\n        padding-bottom: 100%;\n        z-index: 1;\n      }\n    }\n  }\n\n  // check if device is capable to handle hover state\n  // prevents double clicks on touch devices\n  @media (hover: hover) {\n    .base-image-box {\n      &--hover {\n        cursor: pointer;\n\n        &:after {\n          opacity: 0;\n          position: absolute;\n          top: 0;\n          height: 100%;\n          width: 100%;\n          content: '';\n          background-color: rgba(255, 255, 255, .8);\n          transition: opacity 250ms ease;\n        }\n\n        &:hover {\n          &:after {\n            opacity: 1;\n          }\n\n          .base-image-box__body {\n            .base-image-box__icon--play {\n              opacity: 1;\n              transition: opacity 500ms ease;\n              fill: $app-color;\n            }\n\n            &__footer {\n              .base-image-box__icon {\n                opacity: 0;\n              }\n            }\n          }\n\n          .base-image-box__body__footer__center,\n          .base-image-box__body__footer__right {\n            color: $font-color;\n          }\n        }\n      }\n\n      &--hover-show-title {\n        &:hover {\n          .base-image-box__body__footer__text {\n            display: none;\n          }\n\n          .base-image-box__body__footer__title {\n            display: inherit;\n          }\n        }\n      }\n    }\n  }\n\n  /* TRANSITIONS */\n  .slide-fade-enter-active, .slide-fade-move, .slide-fade-leave-active {\n    transition: all 0.5s ease;\n  }\n\n  .slide-fade-enter-from, .slide-fade-leave-to {\n    opacity: 0;\n    transform: translateX(#{$spacing});\n    margin-left: calc(-2 * #{$spacing});\n  }\n</style>\n","<script>\nimport BaseImageBox from '@/components/BaseImageBox/BaseImageBox.vue';\nimport { computed, defineAsyncComponent, getCurrentInstance } from 'vue';\nimport { useI18n } from '@/composables/useI18n.js';\n\n// import swiper styles\nimport 'swiper/css';\nimport 'swiper/css/navigation';\nimport 'swiper/css/pagination';\nimport 'swiper/css/keyboard';\nimport 'swiper/css/autoplay';\n\n/**\n * Component to render a image slider, based on the JS Library <a href=\"https://swiperjs.com/\">Swiper</a>\n */\n\nexport default {\n  name: 'BaseCarousel',\n  components: {\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseImageBox,\n  },\n  props: {\n    /**\n     * items to display\n     *\n     * array of objects with the following **required** properties:\n     *     **title** `?string` - the title to display.\n     *     **subtext** `?string` - the text below the title.\n     *     **description** `?string` - the type of item.\n     *     **additional** `?string` - additional information (e.g. dates).\n     *     **href** `string` - a url to follow upon item click - this is required if item should be rendered\n     *      as a link element.\n     *     **previews** `Object[]`- an array of image urls in different sizes in the following form:\n     *     e.g. `[{ '460w': 'image-url' }, { '640w': 'image url' },...]`\n     */\n    items: {\n      type: Array,\n      default: () => ([]),\n    },\n    /**\n     * By default, slides are grouped with a maximum of three elements per view, depending on screen resolution.\n     * If there are fewer than three elements, the single element takes up 50% of the space; otherwise, it takes up 33%.\n     * The default configuration with all settings can be found in the sample file code [BaseCarousel](BaseCarousel#demo).\n     *\n     * Otherwise, you can freely set all [swiper API options](https://swiperjs.com/swiper-api).\n     */\n    swiperOptions: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * specify how a link element should be rendered\n     * this needs to be a valid vue link component string (e.g. `'RouterLink'`) or a component directly\n     * and vue-router is necessary\n     *\n     * **caveat**: if you are using Nuxt the string `'NuxtLink'` is not enough,\n     *  but you need to import the component as `import { NuxtLink } from '#components';`\n     *  and pass the component to the prop!\n     */\n    renderLinkElementAs: {\n      type: [String, Object],\n      default: 'RouterLink',\n    },\n    /**\n     * this prop gives the option to add assistive text for screen readers.\n     *\n     * properties:\n     * **gotoSlide**: describing a single pagination bullet\n     * **nextSlide**: describing the next button\n     * **prevSlide**: describing the previous button\n     * **roleDescription**: describing the role of outer swiper container\n     * **slide**: describing a single slide\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        gotoSlide: 'Go to slide',\n        nextSlide: 'Next slide',\n        prevSlide: 'Previous slide',\n        roleDescription: 'Carousel element with {total} items',\n        slide: 'Slide',\n      }),\n      validator: val => Object.keys(val).every(key => ['gotoSlide', 'nextSlide', 'prevSlide', 'roleDescription', 'slide'].includes(key)),\n    },\n  },\n  emits: ['initialized', 'clicked'],\n  setup() {\n    /** INTERNATIONALIZATION */\n    const { getI18nTerm } = useI18n();\n\n    /** CHECK ROUTER AVAILABILITY */\n      // we need to access the current component instance\n      // to check for router\n    const { app } = getCurrentInstance().appContext;\n\n    /**\n     * check if vue router is available\n     * @type {ComputedRef<boolean>}\n     */\n    const isRouterAvailable = computed(() => !!app.config.globalProperties?.$router);\n    return {\n      getI18nTerm,\n      isRouterAvailable,\n    };\n  },\n  data() {\n    return {\n      swiper: undefined,\n      swiperIsActive: false,\n      swiperOptionsInt: {},\n    };\n  },\n  computed: {\n    boxSize() {\n      return this.swiperIsActive ? { height: '400px' } : { 'min-height': '250px', 'max-height': '350px' };\n    },\n  },\n  watch: {\n    items: {\n      handler() {\n        if (!this.swiperIsActive) return;\n        // the pagination and a11y doesn't update correctly, when items change,\n        // so destroy swiper but keep instance\n        this.swiper.destroy(false);\n        // reinit swiper\n        this.initSwiper();\n      },\n      deep: true,\n    },\n    swiperOptions: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.swiperOptionsInt)) {\n          this.swiperOptionsInt = {\n            ...this.swiperOptionsInt,\n            ...JSON.parse(JSON.stringify(val)),\n          };\n        }\n      },\n      immediate: true,\n    },\n  },\n  mounted() {\n    this.initSwiper();\n  },\n  methods: {\n    getImageSrc(object, value) {\n      let imageSrc = '';\n      if (object && object.length) {\n        // filter by value\n        imageSrc = object.map(obj => ((Object.keys(obj)[0] === value) ? Object.values(obj)[0] : ''))\n          .filter(obj => obj !== '').toString();\n\n        // otherwise take first one\n        if (!imageSrc.length) {\n          imageSrc = Object.values(object[0])[0];\n        }\n      }\n      return imageSrc;\n    },\n    async initSwiper() {\n      // import swiper and plugins\n      // to avoid import/require issues in an SSR setup\n      // we import swiper when the component is already mounted\n      const { Swiper } = await import('swiper');\n      const { A11y } = await import('swiper/modules');\n      const { Autoplay } = await import('swiper/modules');\n      const { Keyboard } = await import('swiper/modules');\n      const { Navigation } = await import('swiper/modules');\n      const { Pagination } = await import('swiper/modules');\n\n      this.swiperIsActive = true;\n      this.swiperOptionsInt.init = false;\n\n      // default swiper options\n      const defaultSwiperOptions = {\n        keyboard: true,\n        rewind: true,\n        spaceBetween: 16,\n        speed: 750,\n        slidesPerView: 1,\n        slidesPerGroup: 1,\n        breakpoints: {\n          640: {\n            slidesPerView: 2,\n            slidesPerGroup: 2,\n          },\n          1024: {\n            slidesPerView: this.items.length < 3 ? 2 : 3,\n            slidesPerGroup: this.items.length < 3 ? 2 : 3,\n          },\n        },\n      };\n\n      // if no swiper options are set externally, use the default ones\n      if (!Object.keys(this.swiperOptions).length) this.swiperOptionsInt = defaultSwiperOptions;\n\n      // add autoplay settings if needed\n      if (this.swiperOptionsInt.autoplay) {\n        this.swiperOptionsInt.autoplay = {};\n        this.swiperOptionsInt.autoplay.delay = this.swiperOptionsInt.autoplayDelay || 3000;\n        this.swiperOptionsInt.autoplay.disableOnInteraction = true;\n      }\n\n      // enable accessibility settings\n      this.swiperOptionsInt.a11y = {\n        enabled: true,\n        containerMessage: '',\n        containerRole: 'region',\n        containerRoleDescriptionMessage: this.getI18nTerm(this.assistiveText.roleDescription).replace('{total}', this.items.length),\n        itemRoleDescriptionMessage: this.getI18nTerm(this.assistiveText.slide),\n        nextSlideMessage: this.getI18nTerm(this.assistiveText.nextSlide),\n        paginationBulletMessage: `${this.getI18nTerm(this.assistiveText.gotoSlide)} {{index}}`,\n        prevSlideMessage: this.getI18nTerm(this.assistiveText.prevSlide),\n        slideLabelMessage: '{{index}} / {{slidesLength}}',\n        // override with values from outside if defined\n        ...this.swiperOptions?.a11y,\n      }\n\n      // add classes for custom navigation elements\n      this.swiperOptionsInt.navigation = {\n        nextEl: '.swiper-button-next',\n        prevEl: '.swiper-button-prev',\n        addIcons: false,\n        // override with values from outside if defined\n        ...this.swiperOptions?.navigation,\n      };\n\n      // define pagination elements\n      this.swiperOptionsInt.pagination = {\n        el: '.swiper-pagination',\n        clickable: true,\n        bulletElement: 'button',\n        // override with values from outside if defined\n        ...this.swiperOptions?.pagination,\n      };\n\n      // init swiper modules\n      this.swiperOptionsInt.modules = [A11y, Autoplay, Keyboard, Navigation, Pagination];\n\n      // init swiper\n      setTimeout(() => {\n        this.swiper = new Swiper('.swiper', this.swiperOptionsInt);\n        this.swiper.init();\n        /**\n         * event triggered when slider is initialized\n         *\n         * @event initialized\n         * @param { boolean } - was carousel initialized\n         */\n        this.$emit('initialized', true);\n      }, 0);\n    },\n    subtext(value) {\n      return typeof value === 'object' && typeof value[0] === 'string' ? value.join(', ') : value;\n    },\n    boxClicked(item) {\n      /**\n       * event triggered by a ClickEvent on one of the carousel boxes\n       *\n       * @event clicked\n       * @param {Object} - the carousel item that was clicked\n       */\n      this.$emit('clicked', item);\n    },\n  },\n};\n</script>\n\n<template>\n  <div>\n    <div\n      class=\"base-carousel swiper\">\n      <div\n        class=\"swiper-wrapper\">\n        <div\n          v-for=\"(item, index) in items\"\n          v-show=\"swiperIsActive\"\n          :key=\"index\"\n          :class=\"['base-carousel-slide', { 'swiper-slide': swiperIsActive }]\">\n          <BaseImageBox\n            :title=\"item.title\"\n            :subtext=\"subtext(item.subtext)\"\n            :description=\"item.description\"\n            :additional=\"item.additional\"\n            :image-url=\"getImageSrc(item.previews, items.length < 3 ? '768w' : '640w')\"\n            :box-size=\"boxSize\"\n            :lazyload=\"true\"\n            :image-first=\"true\"\n            :center-header=\"true\"\n            :render-element-as=\"isRouterAvailable && item.href ? renderLinkElementAs : 'div'\"\n            :link-to=\"isRouterAvailable && item.href ? item.href : ''\"\n            style=\"margin-right: 0\"\n            @clicked=\"boxClicked(item)\" />\n        </div>\n      </div>\n\n      <div\n        v-if=\"items.length > 2\"\n        class=\"swiper-pagination\" />\n\n      <template\n        v-if=\"items.length > 1\">\n        <BaseIcon\n          name=\"prev\"\n          class=\"swiper-button swiper-button-prev\" />\n\n        <BaseIcon\n          name=\"next\"\n          class=\"swiper-button swiper-button-next\" />\n      </template>\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-carousel {\n    max-width: 1400px;\n    margin: 0 auto;\n    position: relative;\n\n    .base-carousel-slide {\n      margin-bottom: 0;\n\n      @media screen and (max-width: $mobile) {\n        margin-bottom: $spacing;\n      }\n    }\n\n    .swiper-wrapper {\n      display: flex;\n    }\n\n    .swiper-button {\n      display: none;\n      position: absolute;\n      top: calc(50% - #{$line-height} - #{$spacing});\n      z-index: 1;\n      width: $icon-large;\n      height: $icon-large;\n      fill: white;\n      transform: translateY(-50%);\n      transition: fill 250ms ease-in-out;\n\n      &:focus,\n      &:hover {\n        fill: $app-color;\n        cursor: pointer;\n      }\n\n      &-prev {\n        left: $spacing;\n      }\n\n      &-next {\n        right: $spacing;\n      }\n\n      @media screen and (max-width: $mobile) {\n        display: block;\n      }\n    }\n  }\n</style>\n\n<style lang=\"scss\">\n  @use \"@/styles/variables\" as *;\n\n  .base-carousel {\n    .base-image-box-image {\n      max-width: inherit !important;\n      left: 50%;\n      transform: translate(-50%, -50%) !important;\n    }\n\n    &.swiper {\n      opacity: 0;\n\n      &.swiper-initialized {\n        opacity: 1;\n      }\n    }\n\n    .swiper-pagination {\n      display: none;\n\n      @media screen and (min-width: $mobile-min-width) {\n        display: flex;\n        justify-content: center;\n        position: relative;\n      }\n    }\n\n    .swiper-pagination-bullet {\n      width: 10px;\n      height: 10px;\n      border-radius: 50%;\n      background: $pagination-bullet-color;\n      margin: $spacing-large $spacing-small $spacing !important;\n      cursor: pointer;\n\n      &:focus {\n        outline: none;\n      }\n\n      &:only-child {\n        display: none;\n      }\n    }\n\n    .swiper-pagination-bullet-active {\n      opacity: 1;\n      background: $app-color;\n\n      &:hover,\n      &:focus {\n        box-shadow: $box-shadow-hov;\n      }\n    }\n  }\n</style>\n","<script>\nimport { useId } from '@/composables/useId.js';\nimport { defineAsyncComponent } from 'vue';\n\n/**\n * Checkbox and Radio Button Component\n */\n\nexport default {\n  name: 'BaseCheckmark',\n  components: {\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n  },\n  props: {\n    /**\n     * choose the style\n     * @values radio, checkbox\n     */\n    markStyle: {\n      type: String,\n      default: 'radio',\n      validator(val) {\n        return (val === 'radio' || val === 'checkbox');\n      },\n    },\n    /**\n     * specify a descriptive label\n     * this will not be displayed but is only there for usability purposes\n     * TODO: for radio button label should actually be visible!\n     */\n    label: {\n      type: String,\n      default: 'select',\n    },\n    /**\n     * specify a value for the radio button - if none is specified the label will be used to\n     * determine if radio button should be active!\n     */\n    radioValue: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define if label should be visible - default set false because\n     * currently not needed in base project\n     */\n    showLabel: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * checkbox checked or radio button checked can be set from outside, default\n     * value depending on type of selector\n     */\n    modelValue: {\n      type: [Boolean, String],\n      default: false,\n    },\n    /**\n     * set the size of the checkBox\n     * @values large, small\n     */\n    checkBoxSize: {\n      type: String,\n      default: 'small',\n      validator(val) {\n        return val === 'small' || val === 'large';\n      },\n    },\n  },\n  emits: ['update:model-value'],\n  setup() {\n    /** INTERNAL ID */\n    const internalId = useId();\n    return {\n      internalId,\n    };\n  },\n  data() {\n    return {\n      checkedInt: false,\n    };\n  },\n  computed: {\n    radioValueInt() {\n      return this.radioValue || this.label;\n    },\n  },\n  watch: {\n    modelValue: {\n      handler(val) {\n        this.checkedInt = val;\n      },\n      immediate: true,\n    },\n  },\n  methods: {\n    clicked() {\n      if (this.markStyle === 'checkbox') {\n        this.checkedInt = !this.checkedInt;\n      }\n      /**\n       * event emitted on radio button / checkmark click,\n       * emitting input label\n       *\n       * @event update:model-value\n       * @param {string, boolean} - emitting boolean value for checkmark or radio value\n       */\n      this.$emit('update:model-value', this.markStyle === 'checkbox' ? this.checkedInt : this.radioValueInt);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    :class=\"['base-checkbox-container', 'base-checkbox-container-' + checkBoxSize]\">\n    <input\n      :id=\"internalId\"\n      v-model=\"checkedInt\"\n      :name=\"label\"\n      :value=\"radioValueInt\"\n      :type=\"markStyle === 'checkbox' ? 'checkbox' : 'radio'\"\n      :class=\"['base-checkbox-input', { 'base-checkbox-checked': !!checkedInt }]\"\n      @keydown.enter.prevent.stop=\"clicked\"\n      @click.stop=\"clicked\">\n    <div\n      :class=\"[\n        'base-checkmark-container',\n        'base-checkmark-container-' + checkBoxSize,\n        { 'base-radiomark': markStyle === 'radio' && checkedInt === radioValueInt }]\">\n      <BaseIcon\n        v-if=\"markStyle === 'checkbox' && checkedInt\"\n        :class=\"['base-checkmark', 'base-checkmark-' + checkBoxSize]\"\n        name=\"check-mark\" />\n    </div>\n    <!-- need to disable because label is there - it is just in BaseInput component -->\n    <!-- eslint-disable-next-line  vuejs-accessibility/label-has-for -->\n    <label\n      :for=\"internalId\"\n      :class=\"['base-checkbox-labeltext', { hide: !showLabel }]\">{{ label }}</label>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n  @use \"@/styles/variables\" as *;\n\n  .base-checkbox-container {\n    position: relative;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n    user-select: none;\n    display: flex;\n    align-items: center;\n    transition: all 0.2s ease;\n\n    .base-checkbox-container-small {\n      width: $spacing-small*2;\n    }\n\n    .base-checkbox-container-large {\n      width: $spacing*2;\n    }\n\n    &:hover input ~ .base-checkmark-container-small {\n      border: 1.5px solid $app-color;\n    }\n\n    & input:checked ~ .base-checkmark-container-small {\n      border: 1.5px solid $app-color;\n    }\n\n    & input:focus ~ .base-checkmark-container-small {\n      border: 1.5px solid $app-color;\n    }\n\n    & .base-checkbox-checked:focus ~ .base-checkmark-container-small svg {\n     fill: $app-color;\n    }\n\n    .base-checkbox-input {\n      position: absolute;\n      opacity: 0;\n      cursor: pointer;\n      width: 100%;\n      height: 100%;\n      z-index: map.get($zindex, boxcontent);\n\n      &:focus ~ .base-checkmark-container {\n        border-color: $app-color;\n      }\n    }\n\n    .base-checkmark-container {\n      border-radius: 50%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n\n      .base-checkmark {\n        opacity: 1;\n      }\n    }\n\n    .base-checkmark-container-small {\n      border: 1px solid black;\n      height: $spacing-small*2;\n      width: $spacing-small*2;\n\n      .base-checkmark-small {\n        height: $spacing-small;\n        width: $spacing-small;\n        top: $spacing-small-half;\n        left: $spacing-small-half;\n      }\n    }\n\n    .base-checkmark-container-large {\n      border: 2px solid white;\n      height: $spacing*2;\n      width: $spacing*2;\n\n      .base-checkmark-large {\n        height: $spacing;\n        width: $spacing;\n        top: $spacing-small;\n        left: $spacing-small;\n        color: white;\n      }\n    }\n\n    .base-radiomark {\n      &:after {\n        position: absolute;\n        content: \"\";\n        left: $spacing-small;\n        top: 50%;\n        width: $spacing-small;\n        height: $spacing-small;\n        background-color: black;\n        border-radius: $spacing-small;\n        transform: translate(-50%, -50%);\n      }\n    }\n\n    .base-checkbox-labeltext {\n      padding-left: $spacing;\n    }\n  }\n</style>\n","<script>\nimport { computed, defineAsyncComponent, toRef, useTemplateRef } from 'vue';\nimport { highlightText } from '@/utils/utils.js';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { useListNavigation } from '@/composables/useListNavigation.js';\nimport { useId } from '@/composables/useId.js';\nimport { useAnnouncer } from '@/composables/useAnnouncer.js';\nimport { useExtractAttrs } from '@/composables/useExtractAttrs.js';\nimport BaseChipsInputField from '@/components/BaseChipsInputField/BaseChipsInputField.vue';\n\n/**\n * Base Chips Input component with drop down and autocomplete functionality\n *\n */\n\nexport default {\n  name: 'BaseChipsInput',\n  components: {\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseDropDownList: defineAsyncComponent(() => import('@/components/BaseDropDownList/BaseDropDownList.vue')),\n    BaseInsertTextAsHtml: defineAsyncComponent(() => import('@/components/BaseInsertTextAsHtml/BaseInsertTextAsHtml.vue')),\n    BaseChipsInputField,\n  },\n  inheritAttrs: false,\n  props: {\n    /**\n     * list of selectable options. needs to be a list with at least an identifier and a label\n     *  (properties can be set via `identifierPropertyName` and `labelPropertyName`)\n     */\n    list: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * list of already selected options, displayed as chips\n     *  needs to be a list with at least an identifier and a label\n     *  (properties can be set via `identifierPropertyName` and `labelPropertyName`)\n     */\n    modelValue: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * specify input field type\n     * @values text, search\n     */\n    inputType: {\n      type: String,\n      default: 'text',\n      validator: val => ['text', 'search'].includes(val),\n    },\n    /**\n     * input field label\n     */\n    label: {\n      type: String,\n      required: true,\n    },\n    /**\n     * define if label should be visible\n     */\n    showLabel: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * input field placeholder\n     */\n    placeholder: {\n      type: String,\n      default: null,\n    },\n    /**\n     * message displayed when no selectable options are available\n     */\n    dropDownNoOptionsInfo: {\n      type: String,\n      default: 'No options available',\n    },\n    /**\n     * define if the user can add an option that is not in the list\n     */\n    // can the user add Entries that are not available in the vocabulary (selectable list)\n    allowUnknownEntries: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define only a single or multiple options can be selected\n     */\n    // define if one or several entries can be selected from drop down menu\n    allowMultipleEntries: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define if selectable list options should be fetched every time or if the\n     * list passed in the beginning is used\n     */\n    allowDynamicDropDownEntries: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * option to have the border of the input field not displayed\n     */\n    showInputBorder: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * if `true` a button with that functionality will be visible\n     */\n    sortable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define if chips should be draggable (currently only available for inline)\n     */\n    draggable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define if entries should always appear linked (-> with grey background)\n     */\n    alwaysLinked: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * show spinner to indicate that something is loading\n     * (for dynamically fetched entries that need to do backend requests)\n     */\n    isLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if sorting is enabled this will be the text shown in the button\n     */\n    sortText: {\n      type: String,\n      default: 'Sort A – Z',\n    },\n    /**\n     * if `true` sorting will consider the last string in a label or if a comma is\n     * present the string before the comma\n     */\n    sortName: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set a language (ISO 639-1)\n     */\n    language: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set a chips text for adding a new chip.\n     * (alternatively add a `form.Add` value to your localization files)\n     * if allowUnknownEntries is true please add this in one form or another!\n     */\n    addNewChipText: {\n      type: String,\n      default: '',\n    },\n    /**\n     if field is occuring more then once - set an id\n     */\n    inputId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify the object property that should be used as identifier\n     */\n    identifierPropertyName: {\n      type: String,\n      default: 'id',\n    },\n    /**\n     * specify the object property that should be used as value to be displayed\n     */\n    labelPropertyName: {\n      type: String,\n      default: 'label',\n    },\n    /**\n     * property for special case in component [BaseChipsBelow](BaseChipsBelow) - if `false` in this case chips will\n     * not be displayed in the input field\n     */\n    displayChipsInline: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * mark as required field (currently only used for `aria-required` attribute)\n     */\n    required: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * mark the form field as invalid and ideally also provide an error message\n     * to display below the form field.\n     * for an example see [BaseInput](BaseInput)\n     */\n    invalid: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set `true` if input field should be disabled.\n     * for an example see [BaseInput](BaseInput)\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * add an error message to be displayed below form field if field is invalid.\n     * for an example see [BaseInput](BaseInput)\n     */\n    errorMessage: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define if error icon should be shown.\n     * for an example see [BaseInput](BaseInput)\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `true` a remove icon (or a custom icon if slot `remove-icon` is used) will be shown allowing to remove\n     * all input at once\n     * for an example see [BaseInput](BaseInput)\n     */\n    clearable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify additional input field styling\n     */\n    inputClass: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set `true` if chip should be editable on click\n     * **caveat**: this will only work if prop `allowUnknownEntries` is also set `true`\n     * also setting this prop `true` will disable the dragging functionality (also see prop\n     * `draggable`)\n     */\n    chipsEditable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set `true` if dropdown should be closed after selecting an option\n     */\n    closeDropdownOnOptionSelect: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * this prop gives the option to add assistive text for screen readers\n     * properties:\n     * **selectedOption**: text read when a selected option is focused (currently only\n     *  working for editable chips)\n     * **loaderActive**: text that is announced when results are being fetched (prop\n     *  `isLoading` is set `true`)\n     * **clearInput**: text read for remove input icon if prop `clearable` is set `true`\n     * **resultsRetrieved**: text that is announced when results were retrieved (drop down\n     *  list changed)\n     * **optionAdded**: text read when option was added to the selected list. string {label}\n     *  could be added to be replaced by the actual chip label (value in [`labelPropertyName`])\n     * **optionToRemoveSelected**: text read when option is marked active for removal (by using\n     *  backspace in empty input field). string {label} could be added to be replaced\n     *  by the actual chip label (value in [`labelPropertyName`])\n     * **optionRemoved**: text read when option was removed from the selected list. string {label}\n     *  could be added to be replaced by the actual chip label (value in [`labelPropertyName`])\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        selectedOption: '',\n        loaderActive: 'loading.',\n        clearInput: 'Clear input',\n        resultsRetrieved: '{number} options in drop down.',\n        optionAdded: 'option {label} added to selected list.',\n        optionToRemoveSelected: 'option {label} from selected list marked for removal. Press delete or backspace to remove.',\n        optionRemoved: 'option {label} removed.',\n      }),\n    },\n    /**\n     * define if selected options chips should come with a remove icon\n     */\n    chipsRemovable: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define a default entry\n     * will be added when component is mounted and selected list is initially empty\n     * properties:\n     * **label|*** `string`: the label of the default option - use the property name set via prop `labelPropertyName`\n     * **id|*** `string?`: (optional) identifier of the default option - use the property name set via prop `identifierPropertyName`\n     */\n    defaultEntry: {\n      type: [Object, null],\n      default: null,\n    },\n    /**\n     * set this flag to `true` to highlight autocomplete option characters that match\n     *  the current search input string\n     *\n     *  **caveat**: setting this variable `true` can lead to XSS attacks. Only use\n     *    this prop on trusted content and never on user-provided content.\n     */\n    highlightStringMatch: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `highlightAutocompleteMatch` is set `true`\n     *  provide tag names to style the matched characters\n     *  (without '<' and '>', e.g. ['b'] for <b>)\n     */\n    highlightStringTags: {\n      type: Array,\n      default: () => ([]),\n    },\n    /**\n     * if necessary selected chip text can\n     *  be rendered as v-html directive\n     *\n     *  **caveat**: setting this variable `true` can lead to XSS attacks. Only use\n     *    this prop on trusted content and never on user-provided content.\n     */\n    interpretChipsLabelAsHtml: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['update:model-value', 'fetch-dropdown-entries'],\n  setup(props) {\n    /** DROP DOWN NAVIGATION */\n    const { navigate } = useListNavigation();\n    /** LOCALIZATION */\n    const { getLangLabel, getI18nTerm, hasI18n } = useI18n(toRef(props, 'language'));\n    /** COMPONENT ID */\n    // create an internal id in case there is none provided via props\n    const createdId = useId();\n    /**\n     * provide an internal id\n     * @type {ComputedRef<string|number>}\n     */\n    const internalId = computed(() => props.inputId || createdId);\n    /** ATTRS HANDLING */\n    const { rootAttrs, forwardAttrs } = useExtractAttrs();\n\n    /** INPUT ELEMENT HANDLING */\n    /**\n     * the BaseChipsInputField component\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const chipsInputField = useTemplateRef('chipsInputFieldEl');\n    /**\n     * get the HTML input element (in BaseInput)\n     * @type {ComputedRef<null|HTMLElement>}\n     */\n    const inputElement = computed(() => chipsInputField.value?.inputElement || null);\n\n    /**\n     * ACCESSIBILITY ANNOUNCEMENT\n     */\n    /**\n     * set up component reference\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const chipsInput = useTemplateRef('chipsInputEl');\n    // use composable to announce screen reader text on actions taken (e.g.\n    // add chip to selected list or remove chip\n    const { announcement } = useAnnouncer(chipsInput);\n    return {\n      chipsInput,\n      announcement,\n      navigate,\n      internalId,\n      rootAttrs,\n      forwardAttrs,\n      hasI18n,\n      getLangLabel,\n      getI18nTerm,\n      chipsInputField,\n      inputElement,\n    };\n  },\n  data() {\n    return {\n      /**\n       * the current input field string\n       * @type {string}\n       */\n      input: '',\n      /**\n       * internal representation of selected options list\n       * @type {Object[]}\n       */\n      selectedListInt: [],\n      /**\n       * the currently active option, styled with grey background\n       * (only if selected by keyboard)\n       *\n       * @type {number}\n       */\n      activeOptionIndex: 0,\n      /**\n       * the currently selected option after mouse click or keyboard enter\n       *\n       * @type {?Object}\n       */\n      selectedOption: null,\n      /**\n       * variable to store state of input field (for drop down handling)\n       * @type {boolean}\n       */\n      chipsInputActive: false,\n      /**\n       * timeout for drop down options found announcer because otherwise\n       * text not read if more than one character entered into input\n       * @type {?number}\n       */\n      timeout: null,\n    };\n  },\n  computed: {\n    /**\n     * clean props from props not available in ChipsInputField component\n     * (e.g. because they are only needed for drop down component)\n     */\n    chipsFieldInputProps() {\n      const newProps = {\n        // all attributes not in props except for (class, style and data-base-id) and events will\n        // be forwarded to the native HTML input element\n        ...this.forwardAttrs,\n        ...this.$props,\n        // make sure the input id is always set\n        inputId: this.$props.inputId || this.internalId,\n      };\n      // delete the chipsInput `modelValue` prop because for component\n      // ChipsInputField the input string is `modelValue`\n      delete newProps.modelValue;\n      delete newProps.defaultEntry;\n      // and delete all drop down related props\n      delete newProps.dropDownNoOptionsInfo;\n      delete newProps.allowDynamicDropDownEntries;\n      delete newProps.addNewChipText;\n      delete newProps.closeDropdownOnOptionSelect;\n      delete newProps.highlightStringMatch;\n      delete newProps.highlightStringTags;\n      // drop down options\n      delete newProps.list;\n      return newProps;\n    },\n    /**\n     * internal representation of options list, filtered for already selected entries\n     * and also handling input string matching with options list in case of\n     * no dynamic autocomplete fetching\n     * @returns {Object[]}\n     */\n    listInt() {\n      let tempList = [...this.list];\n      // if unknown entries are allowed add an \"Add InputString ...\" as first option\n      if (this.allowUnknownEntries && this.input) {\n        tempList.unshift({\n          [this.labelPropertyName]: this.language ? { [this.language]: this.input } : this.input,\n          // add an identifier here as well so this option can be recognized by the inputs\n          // `aria-activedescendant` attribute\n          [this.identifierPropertyName]: 'createNew',\n        });\n      }\n      // filter entries that were already selected, if no identifier\n      // compare by object property\n      if (this.selectedListInt && this.selectedListInt.length) {\n        tempList = tempList.filter(option => !this.selectedListInt\n          .map(selected => (selected[this.identifierPropertyName]\n            || selected[this.labelPropertyName]))\n          .includes(option[this.identifierPropertyName] || option[this.labelPropertyName]));\n      }\n      // in case of no dynamic autocomplete fetching match the input string\n      // with the options list and only show matching options\n      if (this.input && !this.allowDynamicDropDownEntries) {\n        // also only return entries matching the input string\n        return tempList.filter(option => this.getLangLabel(option[this.labelPropertyName])\n          .toLowerCase().includes(this.input.toLowerCase()));\n      }\n      return tempList;\n    },\n    /**\n     * the currently active option object\n     */\n    activeOption: {\n      /**\n       * setter function of activeOption - will set active option index\n       * @param {?Object} val - the active option (by hover or arrow key use)\n       */\n      set(val) {\n        this.activeOptionIndex = this.listInt.indexOf(val);\n      },\n      /**\n       * getter function for activeOption - determined by active option index\n       * @returns {?Object}\n       */\n      get() {\n        return this.listInt[this.activeOptionIndex];\n      },\n    },\n    /**\n     * create an object out of prop `highlightStringTags` so it can be\n     *  spread into the options of the `highlightText` function\n     * @returns {{highlightTags: []}|{}}\n     */\n    highlightTags() {\n      return this.highlightStringTags?.length\n        ? { highlightTags: this.highlightStringTags } : {};\n    },\n  },\n  watch: {\n    /**\n     * if the selected option changed (by click or keybord enter) add\n     * it to the list of selected options\n     * @param {?Object} val\n     */\n    selectedOption(val) {\n      if (val) {\n        this.addSelectedOption(val);\n        // if input element was found - focus after chips select\n        if (this.inputElement && this.allowMultipleEntries) {\n          this.inputElement.focus();\n        }\n      }\n    },\n    listInt: {\n      /**\n       * watch listInt for changes to set the currently active option index\n       * accordingly\n       * @param {Object[]} val\n       */\n      handler(val) {\n        if (val.length && !this.activeOption) {\n          // set first option in list as active option\n          this.activeOptionIndex = 0;\n        } else if (!val.length && (!this.allowUnknownEntries || !this.input)) {\n          this.activeOptionIndex = -1;\n        }\n        // only set the text when the drop down is actually visible\n        // and do not announce the \"create {custom entry}...\" because it overwrites\n        // the loader message and is announced again with the rest of the search results\n        // later anyway\n        if (this.chipsInputActive\n          && !this.isLoading && !this.announcement) {\n          if (this.timeout) {\n            clearTimeout(this.timeout);\n            this.timeout = null;\n          }\n          // adding this timeout because with dynamicFetch false the list\n          // changes immediately and announcement text is not always read\n          this.timeout = setTimeout(() => {\n            // check if drop down is still open agin to prevent announcement\n            // after option was added (if drop down was closed)\n            if (this.chipsInputActive && this.assistiveText.resultsRetrieved) {\n              if (val.length) {\n                this.announcement = this.assistiveText.resultsRetrieved\n                  .replace('{number}', val.length);\n              } else {\n                this.announcement = this.dropDownNoOptionsInfo;\n              }\n            }\n          }, 300);\n        }\n      },\n      immediate: true,\n    },\n    list: {\n      /**\n       * watch list to reset active option index\n       * @param {Object[]} val\n       */\n      handler(val) {\n        // if list changed externally - reset index to 0\n        this.activeOptionIndex = val.length || (this.allowUnknownEntries && this.input) ? 0 : -1;\n      },\n      immediate: true,\n    },\n    modelValue: {\n      /**\n       * get changes to selectedListInt as soon as modelValue changes\n       * @param {Object[]} val\n       */\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.selectedListInt)) {\n          this.selectedListInt = JSON.parse(JSON.stringify(val));\n        }\n      },\n      immediate: true,\n      deep: true,\n    },\n    /**\n     * watch for changes to selectedListInt and propagate to parent if necessary\n     * @param {Object[]} val\n     */\n    selectedListInt: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.modelValue)) {\n          /**\n           * inform parent of changes to selected list\n           * @event update:model-value\n           * @property {Object[]} - the altered selectedList\n           */\n          this.$emit('update:model-value', JSON.parse(JSON.stringify(val)));\n        }\n      },\n      immediate: true,\n      deep: true,\n    },\n    /**\n     * input is watched for follow up actions needed after input\n     * --> fetch autocomplete entries\n     * @param {string} val\n     */\n    input(val) {\n      // if dropdown content is dynamic alert parent to fetch new relevant entries (if desired)\n      if (this.allowDynamicDropDownEntries) {\n        /**\n         * if input changed this event is emitted to fetch matching autocomplete options\n         * (if allowDynamicDropDownEntries is set true)\n         *\n         * @event fetch-dropdown-entries\n         * @property {string} value - the input string\n         * @property {string} type - the `labelPropertyName` that was specified\n         */\n        this.$emit('fetch-dropdown-entries', { value: val, type: this.labelPropertyName });\n      }\n    },\n    /**\n     * watching drop down active to do necessary actions once drop down opens\n     * a) to fetch drop down entries for static drop downs on first show only\n     * b) to calculate actual drop down width (TODO: do i need this?)\n     * c) to inform parent of drop down state changes\n     * @param {boolean} val\n     */\n    chipsInputActive(val) {\n      // allow also for static drop down entries to be loaded on first drop down show only\n      if (val && !this.allowDynamicDropDownEntries && !this.listInt.length) {\n        /**\n         * event to fetch drop down entries with changing input\n         *\n         * @event fetch-dropdown-entries\n         * @type { object }\n         *\n         */\n        this.$emit('fetch-dropdown-entries', { value: this.input, type: this.labelPropertyName });\n      }\n      if (val) {\n        // reset the active option index to first item\n        this.activeOptionIndex = 0;\n      }\n    },\n  },\n  created() {\n    // add optional default entry to empty modelValue selected list only\n    if (this.defaultEntry && !this.modelValue.length) {\n      // create a copy of the default entry to remove the property `default`\n      const defaultValue = { ...this.defaultEntry };\n      delete defaultValue.default;\n      // and add the entry to selectedList\n      this.selectedListInt.push(defaultValue);\n    }\n  },\n  methods: {\n    /** CHIPS (ADDING) FUNCTIONALITIES */\n\n    /**\n     * method for adding a selected option to selected option list\n     * (remove works via setter - does not need a separate method)\n     *\n     * @param {Object} selected\n     */\n    addSelectedOption(selected) {\n      // if unknown entries are allowed we need to remove the added\n      // id again before pushing it to selectedListInt\n      const newSelected = { ...selected };\n      // remove the default property if it is present\n      delete newSelected.default;\n      if (this.allowUnknownEntries && newSelected[this.identifierPropertyName] === 'createNew') {\n        delete newSelected[this.identifierPropertyName];\n      }\n      if (this.allowMultipleEntries) {\n        this.selectedListInt.push(newSelected);\n      } else {\n        // set the option on first array index (either setting new if empty\n        // array or replacing old option)\n        this.selectedListInt[0] = newSelected;\n        // for single select the drop down should close again automatically\n        // after choosing the option\n        this.chipsInputActive = false;\n      }\n      // make sure the assistive text exists\n      if (this.assistiveText.optionAdded) {\n        // announce the added option to the screen reader\n        this.announcement = this.assistiveText.optionAdded\n          .replace('{label}', newSelected[this.labelPropertyName]);\n      }\n      // clear input\n      this.input = '';\n      // reset selected option\n      this.selectedOption = null;\n      // remove focus from input if element is single select\n      if (!this.allowMultipleEntries) {\n        this.chipsInputActive = false;\n        this.inputElement.blur();\n      }\n      // make sure drop down is closed at the end of all variable updates\n      setTimeout(() => {\n        // optional close dropdown after selection\n        this.closeDropDown();\n      }, 0);\n    },\n\n    /** INPUT FIELD ACTIVE/INACTIVE HANDLING */\n\n    /**\n     * function triggered when input field was clicked\n     */\n    onInputFocus() {\n      this.chipsInputActive = true;\n    },\n    /**\n     * function triggered when click-outside happened\n     */\n    onInputBlur() {\n      this.chipsInputActive = false;\n      // if the focus goes to somewhere else on the page - remove input string\n      if (this.input && document.activeElement.id !== this.internalId) {\n        this.input = '';\n      }\n    },\n\n    /** KEYBOARD FUNCTIONALITIES */\n\n    /**\n     * general function for checking key events like semicolon or tab\n     * @param {KeyboardEvent} event - the keydown event\n     */\n    checkKeyEvent(event) {\n      const { key } = event;\n      // this should (currently) never be the case (but it was in the past - on closeDropDownOnOptionSelect\n      // focus remained but drop down was closed) but just to be safe - set the input active as soon\n      // as user enters input\n      // TODO: what would happen if user selects an option, focus stays and user copy pastes? (but\n      // again - this is currently just hypothetical)\n      if (!['Tab', 'Enter', 'Shift'].includes(key)) {\n        this.chipsInputActive = true;\n      }\n      // if user pressed tab and thus input field leaves focus we would want to remove the input string\n      // so no confusion is created as to wether this string is part of a search or saved in form\n      // so we check for type of key and if input is present\n      if (key === 'Tab' && this.input\n        // and remove input if\n        // there is no other focusable element in the input (like the clear input button)\n        && (!this.clearable\n          // user is moving focus backwards from input to outside of input field (not from any\n          // other element in the input field)\n          || (event.shiftKey && event.target.tagName === 'INPUT')\n          // user is moving focus from clear input button to outside of the input\n          || (this.clearable && !event.shiftKey && event.target.tagName !== 'INPUT'))) {\n        // this.chipsInputActive = false;\n        this.input = '';\n      }\n    },\n    /**\n     * triggered on keydown enter event and will add\n     * a selected option\n     */\n    onEnter() {\n      // do nothing if dropdown should be closed on option select, and dropdown is not active\n      if (this.closeDropdownOnOptionSelect && !this.chipsInputActive) return;\n\n      // check if there is a currently active option\n      if (this.activeOption) {\n        this.addSelectedOption(this.activeOption);\n      }\n    },\n    /**\n     * event for keydown arrow (up, down) key use\n     *\n     * @param {KeyboardEvent} event - the keydown event\n     */\n    onArrowKey(event) {\n      // check if the list has any options\n      if (this.listInt.length) {\n        // if yes trigger the navigate function\n        this.activeOption = this.navigate(\n          this.listInt,\n          event.key === 'ArrowDown',\n          this.activeOptionIndex,\n          true,\n        );\n        // added the .toString() method here since ids could also be numbers and IN THEORY also 0\n        if (this.activeOption && !this.activeOption[this.identifierPropertyName]?.toString()) {\n          console.warn(`Selected option '${this.activeOption[this.labelPropertyName]}' will not be shown active due to missing identifier property!`);\n        }\n      }\n    },\n\n    /** OTHER FUNCTIONALITIES */\n\n    /**\n     * close dropdown\n     */\n    closeDropDown() {\n      // optional close dropdown after selection\n      if (this.closeDropdownOnOptionSelect && this.chipsInputActive) {\n        this.chipsInputActive = false;\n        if (this.inputElement) {\n          this.inputElement.blur();\n        }\n      }\n    },\n    /**\n     * function to highlight characters of a string\n     * @param {string} word - the option that should be matched with query string\n     * @returns {string} - the string to fill into v-html\n     */\n    highlight(word) {\n      return highlightText({\n        word,\n        queryString: this.input,\n        // this is an empty object if prop `highlightStringTags` was not used\n        ...this.highlightTags,\n      });\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    ref=\"chipsInputEl\"\n    v-bind=\"rootAttrs\"\n    class=\"base-chips-input\">\n    <BaseChipsInputField\n      ref=\"chipsInputFieldEl\"\n      v-model=\"input\"\n      v-model:selected-list=\"selectedListInt\"\n      v-model:is-active=\"chipsInputActive\"\n      v-bind=\"chipsFieldInputProps\"\n      :aria-autocomplete=\"'list'\"\n      :aria-controls=\"`${internalId}-list-identifier`\"\n      :aria-expanded=\"chipsInputActive\"\n      :aria-haspopup=\"'listbox'\"\n      :input-type=\"inputType\"\n      :add-selected-entry-directly=\"false\"\n      :drop-down-list-id=\"internalId\"\n      :linked-list-option=\"activeOption ? activeOption[identifierPropertyName] : undefined\"\n      :loadable=\"allowDynamicDropDownEntries\"\n      :ignore-click-outside=\"['.base-chips-input__drop-down']\"\n      role=\"combobox\"\n      @keydown.enter.prevent=\"onEnter\"\n      @keydown.up.down.prevent=\"onArrowKey\"\n      @keydown=\"checkKeyEvent\"\n      @click-input-field=\"onInputFocus\"\n      @clicked-outside=\"onInputBlur\">\n      <template #below-input>\n        <BaseDropDownList\n          v-if=\"chipsInputActive\"\n          ref=\"dropDownList\"\n          v-model:active-option=\"activeOption\"\n          v-model:selected-option=\"selectedOption\"\n          :drop-down-options=\"listInt\"\n          :identifier-property-name=\"identifierPropertyName\"\n          :label-property-name=\"labelPropertyName\"\n          :list-id=\"internalId\"\n          :language=\"language\"\n          :drop-down-no-options-info=\"dropDownNoOptionsInfo\"\n          class=\"base-chips-input__drop-down\"\n          @click.stop=\"closeDropDown\"\n          @touchstart.stop.passive=\"closeDropDown\">\n          <template #option=\"{ option }\">\n            <span\n              v-if=\"allowUnknownEntries && option[identifierPropertyName] === 'createNew'\"\n              ref=\"option\"\n              :key=\"option[labelPropertyName]\">\n              {{ addNewChipText\n                ? `${addNewChipText} ${getLangLabel(option[labelPropertyName], true)} ...`\n                : `${getI18nTerm('form.Add', -1, {\n                  value: getLangLabel(option[labelPropertyName], true),\n                  // if there is no i18n getI18nTerm will not return the value - so add it here manually\n                })} ${hasI18n ? '' : getLangLabel(option[labelPropertyName], true) }...` }}\n            </span>\n            <template\n              v-else-if=\"option\">\n              <!-- @slot a slot to provide more advanced drop down entries per default only the `Object[labelPropertyName][?lang]` will be displayed\n                @binding {Object} item - the option passed to options list -->\n              <slot\n                :item=\"option\"\n                name=\"drop-down-entry\">\n                <!-- SLOT DEFAULT -->\n                <BaseInsertTextAsHtml\n                  v-if=\"option[identifierPropertyName]\"\n                  :key=\"option[identifierPropertyName]\"\n                  :render-element-as=\"'span'\"\n                  :text=\"highlightStringMatch\n                    ? highlight(getLangLabel(option[labelPropertyName], true))\n                    : getLangLabel(option[labelPropertyName], true)\"\n                  :interpret-text-as-html=\"interpretChipsLabelAsHtml\" />\n              </slot>\n            </template>\n          </template>\n          <template\n            #no-options>\n            <!-- @slot a slot to customize messages in case of no options present in drop down -->\n            <slot\n              name=\"no-options\" />\n          </template>\n        </BaseDropDownList>\n        <!-- @slot to add elements below input fields e.g. add drop down -->\n        <slot name=\"below-input\" />\n      </template>\n      <template\n        #label-addition>\n        <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs)). for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"label-addition\" />\n      </template>\n      <template #pre-input-field>\n        <!-- @slot slot to add elements within the form field but in a row before the actual input field. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"pre-input-field\" />\n      </template>\n      <template\n        #input-field-addition-before>\n        <!-- @slot Slot to allow for additional elements in the input field \\<div\\> (before <input>). for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"input-field-addition-before\" />\n      </template>\n      <template #input-field-inline-before>\n        <!-- @slot to add elements directly inline before the input (contrary to `input-field-addition-before` this does not wrap. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"input-field-inline-before\" />\n      </template>\n      <template #input-field-addition-after>\n        <!-- @slot for adding elements after input -->\n        <slot name=\"input-field-addition-after\" />\n      </template>\n      <template #post-input-field>\n        <!-- @slot for adding elements at the end covering the whole height. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"post-input-field\" />\n        <!-- this element is not needed for keyboard users or accessibility -->\n        <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n        <div\n          v-if=\"!allowMultipleEntries\"\n          class=\"base-chips-input__single-dropdown\"\n          @keydown.enter.stop=\"chipsInputActive = !chipsInputActive\"\n          @click.stop=\"chipsInputActive = !chipsInputActive\">\n          <BaseIcon\n            :class=\"[\n              'base-chips-input__single-dropdown-icon',\n              {\n                'base-chips-input__single-dropdown-icon-rotated':\n                  chipsInputActive,\n              },\n            ]\"\n            name=\"drop-down\" />\n        </div>\n      </template>\n      <template #error-icon>\n        <!-- @slot use a custom icon instead of standard error/warning icon. for an example see [BaseChipsInputField](BaseChipsInputField).-->\n        <slot name=\"error-icon\" />\n      </template>\n      <template #remove-icon>\n        <!-- @slot use a custom icon instead of standard remove icon. for an example see [BaseChipsInputField](BaseChipsInputField). -->\n        <slot name=\"remove-icon\" />\n      </template>\n    </BaseChipsInputField>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n  .base-chips-input {\n    position: relative;\n\n    .base-chips-input__drop-down {\n      background: white;\n      min-width: 100%;\n    }\n\n    .base-chips-input__single-dropdown {\n      display: flex;\n      align-items: center;\n      padding: 0 $spacing-small;\n\n      .base-chips-input__single-dropdown-icon {\n        transition:  $drop-down-arrow-animation;\n        height: $icon-small;\n        width: $icon-small;\n        flex-shrink: 0;\n\n        &.base-chips-input__single-dropdown-icon-rotated {\n          transform: rotate(180deg);\n        }\n      }\n    }\n  }\n</style>\n","<script>\nimport { computed, defineAsyncComponent, useTemplateRef } from 'vue';\nimport { useAnnouncer } from '@/composables/useAnnouncer.js';\nimport BaseChipsInput from '@/components/BaseChipsInput/BaseChipsInput.vue';\nimport { useExtractAttrs } from '@/composables/useExtractAttrs.js';\nimport { createId } from '@/utils/utils.js';\nimport { useId } from '@/composables/useId.js';\n/**\n * A very specialized component based on [BaseChipsInput](BaseChipsInput)\n * in order to assign additional values (e.g. roles) to selected entries)]\n *\n */\n\nexport default {\n  name: 'BaseChipsBelow',\n  components: {\n    BaseChipsInput,\n    BaseChip: defineAsyncComponent(() => import('@/components/BaseChip/BaseChip.vue')),\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n  },\n  inheritAttrs: false,\n  props: {\n    /**\n     * list of selectable options objects with at least an identifier and a label property.\n     * property names can be set with props `identifierPropertyName` and `labelPropertyName`\n     */\n    list: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * list of already selected options objects with at least an identifier and a label property\n     * and a property to use for the secondary drop down ('additional property'), displayed as\n     * chips.\n     * property names can be set with props `identifierPropertyName`, `labelPropertyName` and\n     * `additionalPropertyName`\n     */\n    modelValue: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     if field is occurring more than once - set an id\n     */\n    inputId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * input field label\n     */\n    label: {\n      type: String,\n      required: true,\n    },\n    /**\n     * define if label should be visible\n     */\n    showLabel: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * input field placeholder\n     */\n    placeholder: {\n      type: String,\n      default: null,\n    },\n    /**\n     * message displayed when no selectable options are available\n     */\n    dropDownNoOptionsInfo: {\n      type: String,\n      default: 'No options available',\n    },\n    /**\n     * define if the user can add an option that is not in the list\n     */\n    // can the user add Entries that are not available in the vocabulary (selectable list)\n    allowUnknownEntries: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define whether one or more entries can be selected from the drop-down menu\n     */\n    allowMultipleEntries: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define if selectable list options should be fetched every time of if the\n     * list passed in the beginning is used\n     */\n    allowDynamicDropDownEntries: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define whether one or more options can be selected from the drop-down menu\n     */\n    additionalPropAllowMultipleEntries: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * Additional property options will set the drop down available for the selected entries\n     * needs to be an object with following attributes:\n     * **label|*** `string`: the label of the default option - use the property name set via prop `labelPropertyName`\n     * **id|*** `string?`: (optional) identifier of the default option - use the property name set via prop `identifierPropertyName`\n     */\n    additionalPropOptions: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * define a default option for additional props\n     * see `defaultEntry` at [BaseChipsInput props](BaseChipsInput) for more details\n     */\n    additionalPropDefaultOption: {\n      type: [Object, null],\n      default: null,\n    },\n    /**\n     * specify additional options as required\n     */\n    additionalPropRequired: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify a placeholder of the additional property input field\n     */\n    additionalPropPlaceholder: {\n      type: String,\n      default: 'Select role(s)',\n    },\n    /**\n     * define validation messages\n     */\n    validationTexts: {\n      type: Object,\n      default: () => ({\n        required: 'Select an option.',\n      }),\n      // checking if all necessary properties are part of the provided object\n      validator: val => ['required'].every(prop => Object.keys(val).includes(prop)),\n    },\n    /**\n     * show spinner to indicate that something is loading.\n     *  This is meant for dynamically fetching entries from a backend and will only\n     *  have an effect if prop `allowDynamicDropDownEntries` is set true!\n     */\n    isLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if sorting is enabled this will be the text shown in the button\n     */\n    sortText: {\n      type: String,\n      default: 'Sort A – Z',\n    },\n    /**\n     * if `true` sorting will consider the last string in a label or if a comma is\n     * present the string before the comma\n     */\n    sortName: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set a language (ISO 639-1)\n     */\n    language: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set a chips text for adding a new chip\n     * (alternatively add a 'form.Add' value to your localization files).\n     * if `allowUnknownEntries` is `true` please add this in one form or another!\n     */\n    addNewChipText: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify the object property that should be used as identifier\n     */\n    identifierPropertyName: {\n      type: String,\n      default: 'id',\n    },\n    /**\n     * specify the object property that should be used as value to be displayed\n     */\n    labelPropertyName: {\n      type: String,\n      default: 'label',\n    },\n    /**\n     * define the name of the property that is relevant for the additional drop down\n     * once a value was selected from the primary drop down\n     */\n    additionalPropertyName: {\n      type: String,\n      default: 'roles',\n    },\n    /**\n     * mark as required field\n     */\n    required: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * mark the form field as invalid and ideally also provide an error message\n     * to display below the form field.\n     * for an example see [BaseInput](BaseInput)\n     */\n    invalid: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set `true` if input field should be disabled.\n     * for an example see [BaseInput](BaseInput)\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * add an error message to be displayed below form field if field is invalid\n     * for an example see [BaseInput](BaseInput)\n     */\n    errorMessage: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define if error icon should be shown.\n     * for an example see [BaseInput](BaseInput)\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if true a remove icon will be shown allowing to remove\n     * all input at once.\n     * for an example see [BaseInput](BaseInput)\n     */\n    clearable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set `false` if dropdown should be still open after selecting an option\n     */\n    closeDropdownOnOptionSelect: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * specify additional input field styling\n     */\n    inputClass: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define if a button for sorting the entries is visible\n     */\n    sortable: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define if chips should be draggable\n     */\n    draggable: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * set this flag to `true` to highlight autocomplete option characters that match\n     *  the current search input string\n     *  this will only have effect when the slot `drop-down-entry` is not used\n     */\n    highlightStringMatch: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `highlightAutocompleteMatch` is set `true`\n     *  provide tag names to style the matched characters\n     *  (without '<' and '>', e.g. ['b'] for <b>)\n     *  this will only have effect when the slot `drop-down-entry` is not used\n     */\n    highlightStringTags: {\n      type: Array,\n      default: () => ([]),\n    },\n    /**\n     * this prop gives the option to add assistive text for screen readers\n     * properties:\n     * **loaderActive**: text that is announced when results are being fetched (prop\n     *  `isLoading` is set `true`)\n     * **clearInput**: text read for remove input icon if prop `clearable` is set `true`\n     * **resultsRetrieved**: text that is announced when results were retrieved (drop down\n     *  list changed)\n     * **optionAdded**: text read when option was added to the selected list. string {label}\n     *  could be added to be replaced by the actual chip label (value in [`labelPropertyName`])\n     * **optionRemoved**: text read when option was removed from the selected list. string {label}\n     *  could be added to be replaced by the actual chip label (value in [`labelPropertyName`])\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        loaderActive: 'loading.',\n        clearInput: 'Clear input',\n        resultsRetrieved: '{number} options in drop down.',\n        optionAdded: 'option {label} added to selected list.',\n        optionRemoved: 'option {label} removed.',\n      }),\n    },\n    /**\n     * set `true` if chips (only [labelPropertyName] not additional attribute) should be editable on click\n     * **caveat**: this will only have an effect if `allowUnknownEntries` is true as well\n     */\n    chipsEditable: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['additional-property-changed', 'fetch-dropdown-entries', 'update:model-value', 'duplicate'],\n  setup(props) {\n    /** ATTRS HANDLING */\n    const { rootAttrs, forwardAttrs } = useExtractAttrs();\n\n    /** COMPONENT ID */\n      // create an internal id in case there is none provided via props\n    const createdId = useId();\n    /**\n     * provide an internal id\n     * @type {ComputedRef<string|number>}\n     */\n    const internalId = computed(() => props.inputId || createdId);\n\n    /** INPUT ELEMENT HANDLING */\n    /**\n     * get a reference to the ChipsInput component\n     * @type {Readonly<ShallowRef<HTMLElement| null>>}\n     */\n    const chipsInput = useTemplateRef('chipsInputEl');\n    /**\n     * from the ChipsInput get access to the native HTML input element (it is chained\n     * through from BaseInput)\n     * @type {ComputedRef<HTMLElement>}\n     */\n    const inputElement = computed(() => chipsInput.value?.inputElement || null);\n\n    /** ACCESSIBILITY HANDLING */\n    /**\n     * set up component reference\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const chipsBelow = useTemplateRef('chipsBelowEl');\n    // use composable to announce screen reader text on actions taken (e.g.\n    // add chip to selected list or remove chip\n    const { announcement } = useAnnouncer(chipsBelow);\n    return {\n      rootAttrs,\n      forwardAttrs,\n      internalId,\n      inputElement,\n      chipsBelow,\n      announcement,\n    };\n  },\n  data() {\n    return {\n      /**\n       * internal representation of modelValue to manipulate\n       * @type {Object[]}\n       */\n      selectedBelowListInt: [],\n      // error handling\n      /**\n       * internal validity state - combining `invalid` prop\n       * and internal validation()\n       * @type {boolean}\n       */\n      invalidInt: false,\n      /**\n       * internal error message - combining error message set by `errorMessage` prop\n       * and internal validation()\n       * @type {string}\n       */\n      errorMessageInt: '',\n      /**\n       * flag to handle if additional props error should be displayed or not\n       *  -> only after manual validation (not immediately when field is added)\n       * @type {boolean}\n       */\n      hasAdditionalPropErrors: false,\n    };\n  },\n  computed: {\n    draggableComponent() {\n      if (this.draggable) {\n        return defineAsyncComponent(() => import('vue-draggable-plus').then(m => m.VueDraggable));\n      }\n      return 'div';\n    },\n    // need to filter language from $props for chips input component since only needed for\n    // additional property (roles)!\n    // leads to unwanted behaviour else (creating multilang object)\n    chipsInputProps() {\n      const newProps = {\n        ...this.$props,\n        ...this.forwardAttrs,\n      };\n      delete newProps.language;\n      // also remove additional property related props since unknown to chips input component\n      delete newProps.additionalPropOptions;\n      delete newProps.additionalPropPlaceholder;\n      delete newProps.additionalPropertyName;\n      delete newProps.additionalPropAllowMultipleEntries;\n      delete newProps.additionalPropRequired;\n      // since BaseInput also has a prop `validationTexts` (and also\n      // BaseChipsInput does not have that prop) we dont want that passed down\n      delete newProps.validationTexts;\n      return newProps;\n    },\n    /**\n     * selectedBelowListInt with an internal id added if necessary\n     * @returns {(*&{idInt: *})[]}\n     */\n    renderList: {\n      set(val) {\n        // create a copy of render list so the idInt is not deleted from\n        // renderList as well\n        const renderListCopy = JSON.parse(JSON.stringify(val));\n        // update renderList but remove the internal id needed\n        // for dragging and list generation\n        this.selectedBelowListInt = renderListCopy.map((entry) => {\n          // eslint-disable-next-line no-param-reassign\n          delete entry.idInt;\n          return entry;\n        });\n      },\n      get() {\n        return this.selectedBelowListInt.map((entry) => {\n          // handled with ?? operator to prevent id 0 being ignored\n          let providedId = entry[this.identifierPropertyName] ?? undefined;\n          if (providedId === undefined) {\n            // try to check if the entry already received an id and the id is not it the list yet\n            // check if an id was already assigned to an item with that label which does not appear\n            // in the array more than once (this is just a safeguard - in addOption double adding\n            // of the same freetext should actually be prevented anyway)\n            const matchingLabelsList = this.renderList ? this.renderList.filter((selectedOption) => {\n              return selectedOption[this.labelPropertyName] === entry[this.labelPropertyName];\n            }) : undefined;\n            providedId = matchingLabelsList && matchingLabelsList.length === 1\n              ? matchingLabelsList[0].idInt : entry[this.labelPropertyName] + createId();\n          }\n          return {\n            ...{\n              // and create an internal id if none was provided\n              idInt: this.identifierPropertyName && entry[this.identifierPropertyName] !== undefined\n                ? entry[this.identifierPropertyName] : providedId,\n            },\n            ...entry,\n          };\n        });\n      },\n    },\n    /**\n     * in order to be able to dynamically import VueDraggable and only set v-model\n     * if it is used, use this variable\n     * we are using renderList here so the internalId is also available for\n     * vue draggable\n     */\n    draggableList: {\n      set(val) {\n        this.renderList = val;\n      },\n      get() {\n        // do not set v-model if draggable is false\n        if (!this.draggable) return null;\n        return this.renderList;\n      },\n    },\n    /**\n     * since not all entries have an identifier when `allowUnknownEntries` is set true\n     * we have an index based list that will save the error state per entry\n     * @returns {boolean[]|boolean}\n     */\n    additionalPropErrorsList() {\n      if (!this.additionalPropRequired) return false;\n      return this.selectedBelowListInt.map((selectedOption) => !selectedOption[this.additionalPropertyName]?.length);\n    },\n    chipsRemovable() {\n      if (!this.additionalPropRequired) return true;\n      return this.selectedBelowListInt.map((selectedOption) => this.additionalPropAllowMultipleEntries\n        && selectedOption[this.additionalPropertyName]?.length > 1);\n    },\n  },\n  watch: {\n    /**\n     * create internal list and reset errors\n     * @param {Object[]} val\n     */\n    modelValue: {\n      handler(val) {\n        // reset error if a new item was added\n        if (val.length && val.length > this.selectedBelowListInt.length) {\n          // reset the invalid state but still respect any invalid state set from outside\n          this.invalidInt = this.invalid;\n          this.errorMessageInt = this.errorMessage;\n          // newly added items should not immediately appear with error message so reset\n          // the error flag here\n          this.hasAdditionalPropErrors = false;\n        }\n        // now update the list but also add the additional prop already here if it does not\n        // exist yet\n        this.selectedBelowListInt = val.map((selectedOption) => ({\n          ...selectedOption,\n          [this.additionalPropertyName]: selectedOption[this.additionalPropertyName] || [],\n        }));\n      },\n      immediate: true,\n      deep: true,\n    },\n    /**\n     * keep externally set invalid variable and internal invalid variable in sync\n     * @param {boolean} val\n     */\n    invalid: {\n      handler(val) {\n        this.invalidInt = val;\n      },\n      immediate: true,\n    },\n    /**\n     * keep externally set error message variable and internal error message variable in sync\n     * @param {string} val\n     */\n    errorMessage: {\n      handler(val) {\n        this.errorMessageInt = val;\n      },\n      immediate: true,\n    },\n    /**\n     * reset the invalid status when the required property is externally set to false.\n     * @param {boolean} val\n     */\n    required: {\n      handler(val) {\n        if (!val) {\n          // reset but still consider state set from outside\n          this.invalidInt = this.invalid;\n          this.errorMessageInt = this.errorMessage;\n        }\n      },\n    },\n    /**\n     * reset the additional prop errors when property is externally set to false.\n     * @param {boolean} val\n     */\n    additionalPropRequired: {\n      handler(val) {\n        if (!val) {\n          this.hasAdditionalPropErrors = false;\n        }\n      },\n    },\n  },\n  methods: {\n    /** LIST HANDLING AND MANIPULATIONS */\n    /**\n     * function called when an entry is added to the selected list\n     * @param list\n     */\n    updateSelectedList(list) {\n      // first we need to make sure there are no duplicates if freetext is allowed\n      if (this.allowUnknownEntries && Array.from(new Set(list\n        // either create list of strings from identifier or if not present (=freetext entry)\n        // the label\n        .map((selectedOption) => selectedOption[this.identifierPropertyName]\n          || selectedOption[this.labelPropertyName]))).length !== list.length) {\n        /**\n         * event emitted when user is trying to add duplicate freetext which will be\n         * prevented (so that user can be informed)\n         * @event duplicate\n         * @param {Object[]} - the altered selected list (modelValue)\n         */\n        this.$emit('duplicate', list);\n        // then do not follow up with any further actions (=entry will not be added)\n        return;\n      }\n      // since we don't want a new entry to show an error message immediately we need\n      // to set the invalid variable false\n      this.hasAdditionalPropErrors = false;\n      // update internal selected list - also here add the additional prop immediately\n      this.selectedBelowListInt = list.map((selectedOption) => ({\n        ...selectedOption,\n        [this.additionalPropertyName]: selectedOption[this.additionalPropertyName] || [],\n      }));\n      // and check if input is now valid in case it was invalid before\n      // use isValidChipsInput() not validate() because we really only want to\n      // check main input field\n      if (this.invalidInt && this.isValidChipsInput()) {\n        // still honor invalid state and error message set from outside if any\n        this.invalidInt = this.invalid;\n        this.errorMessageInt = this.errorMessage;\n      }\n      this.emitSelected(list);\n    },\n    /**\n     * function called when an entry should be removed from the selected list\n     * @param {number} index\n     */\n    removeEntry(index) {\n      // remove the entry from the internal list\n      const item = this.selectedBelowListInt.splice(index, 1);\n      // inform parent about the change\n      this.emitSelected(this.selectedBelowListInt);\n      // inform screen reader user\n      this.announcement = this.assistiveText.optionRemoved\n        .replace('{label}', item[0][this.labelPropertyName]);\n    },\n    /**\n     * function called when an option was selected or removed from the additional property\n     * input\n     * @param {Array} updatedSelectedList\n     * @param {number} index\n     */\n    updateAdditionalProperty(updatedSelectedList, index) {\n      // update the additional property of the correct selected entry with the new list\n      this.selectedBelowListInt[index][this.additionalPropertyName] = updatedSelectedList;\n      // inform parent that the selected list changed\n      this.emitSelected(this.selectedBelowListInt);\n      /**\n       * propagate additional-property-changed change event to parent\n       * Note: useful when validation is done from the parent\n       *\n       * @event additional-property-changed\n       * @param {Object} obj - changed object\n       */\n      this.$emit('additional-property-changed', this.modelValue[index]);\n    },\n    /**\n     * function called when `allowUnknownEntries` and `chipsEditable` are set true\n     * and a chip was modified\n     * @param {string} newChipText\n     * @param {number} index\n     */\n    modifyChipValue(newChipText, index) {\n      if (!newChipText) {\n        this.selectedBelowListInt.splice(index, 1);\n      } else {\n        const modifiedEntry = { ...this.selectedBelowListInt[index] };\n        if (this.identifierPropertyName) {\n          modifiedEntry[this.identifierPropertyName] = '';\n        }\n        modifiedEntry[this.labelPropertyName] = newChipText;\n        this.selectedBelowListInt[index] = modifiedEntry;\n      }\n      this.emitSelected(this.selectedBelowListInt);\n    },\n    /**\n     * function to inform parent of updated selected list, sending list\n     * without internal modifications\n     * @param {Object[]} val\n     */\n    emitSelected() {\n      const updatedList = JSON.parse(JSON.stringify(this.selectedBelowListInt));\n      /**\n       * propagate list change from dragging event to parent\n       *\n       * @event update:model-value\n       * @param {Object} - the altered list\n       *\n       */\n      this.$emit('update:model-value', updatedList);\n    },\n\n    /** DROP-DOWN / AUTOCOMPLETE */\n    /**\n     * function triggered on user input to autocomplete options\n     * @param params\n     */\n    fetchDropDownEntries(params) {\n      /**\n       * if drop down entries dynamically set - fetch new entries on input\n       *\n       * @event fetch-dropdown-entries\n       * @property {string} value - the input string\n       * @property {string} type - the `labelPropertyName` that was specified\n       *\n       */\n      this.$emit('fetch-dropdown-entries', params);\n    },\n\n    /** DRAG & DROP HANDING */\n    /**\n     * need to set custom due to some strange effects not showing correct element in some cases\n     * (this function is only triggered on non-touch devices)\n     * @param {DataTransfer} dataTransfer\n     */\n    setDragElement(dataTransfer) {\n      const img = document.createElement('div');\n      img.id = 'drag-element';\n      img.style.position = 'absolute';\n      img.style.top = '-99999px';\n      img.style.left = '-99999px';\n      // setting height and width is important for macOS it wont work\n      // otherwise with an empty element\n      img.style.width = '100%';\n      img.style.height = '100%';\n      // setting like this makes it work in all three major browsers\n      // the 0.01 opacity is needed for firefox not to display some default\n      // document icon\n      img.style.backgroundColor = 'rgb(255, 255, 255, 0.01)';\n      // add the element to the dom\n      document.body.appendChild(img);\n      dataTransfer.setDragImage(img, 0, 0);\n    },\n    /**\n     * cursor is not set per default on macOS so we need to handle it here\n     * this does not influence cursor display on Windows\n     * and Ubuntu is fine anyway\n     * @param {MouseEvent} event - native event\n     */\n    onDragStart(event) {\n      // created separate method because we need to differentiate between\n      // iOS Firefox and all other browsers\n      // also tried to add the class already on mousedown however this will interfere\n      // with the dragstart / dragend cursor setting (at least on all macOS\n      // browsers, maybe others too)\n      this.toggleGrabbingCursor(true, event);\n    },\n    /**\n     * actions to handle when element is dropped again\n     * @param {Object[]} list - the re-sorted item list\n     * @param {MouseEvent} event - the native event\n     */\n    onDragEnd(list, event) {\n      // remove the drag cursor class again - for extensive comment see above\n      this.toggleGrabbingCursor(false, event);\n      // get and remove the drag element created in setDragImage() again\n      const elem = document.getElementById('drag-element');\n      if (elem) {\n        elem.parentNode.removeChild(elem);\n      }\n      // and emit the altered list\n      this.emitSelected(list);\n    },\n    /**\n     * added separate method to distinguish between browsers specifically because\n     * macOS did not display correct cursor and a common solution for Firefox AND Chrome\n     * could not be found\n     * this still might not be the perfect solution - more inspiration to improve can be found\n     * here https://github.com/SortableJS/Vue.Draggable/issues/815\n     * @param {boolean} state - the state that should be applied\n     * @param {MouseEvent} event - the native mouse event\n     */\n    toggleGrabbingCursor(state, event) {\n      // check if client is Firefox - because this is the only way working in Firefox!\n      // we also need to check for event, since it is needed for iOS Firefox\n      if (event && navigator.userAgent.includes('Mac') && typeof InstallTrigger !== 'undefined') {\n        if (state) {\n          event.target.classList.add('grabbing');\n        } else {\n          event.target.classList.remove('grabbing');\n        }\n        // this seems fine for every other OS (and browser therein)\n      } else {\n        const html = document.getElementsByTagName('html').item(0)\n        html.classList.toggle('grabbing', state)\n      }\n    },\n\n\n    /** VALIDATION */\n\n    /**\n     * validate chips input field\n     * @returns {boolean} - error state\n     */\n    isValidChipsInput() {\n      // if not set do anything\n      if (!this.required) return true;\n\n      // if no chips set, throw error\n      if (!this.selectedBelowListInt.length) {\n        this.invalidInt = true;\n        // consider also optional errorMessage\n        this.errorMessageInt = `${this.errorMessage} ${this.validationTexts.required}`.trim();\n        return false;\n      }\n      // otherwise everything is fine\n      return true;\n    },\n    /**\n     * Validation can be triggered by executing e.g. `this.$refs.baseChipsBelowEl.validate();` from parent.<br>\n     * Therefore, the component must have a reference set.\n     * @public\n     * @returns {boolean} - components error state\n     */\n    validate() {\n      // clear errors but still consider if invalid state and error message were set from\n      // outside - in this case use these values instead of a complete reset\n      this.invalidInt = this.invalid;\n      this.errorMessageInt = this.errorMessage;\n      // validate main property field\n      const isValidChipsInput = this.isValidChipsInput();\n      // and check if there are additional prop errors\n      this.hasAdditionalPropErrors = this.additionalPropErrorsList\n        && !!this.additionalPropErrorsList.some((error) => error);\n      // return error state\n      // nice to have would be to return an object or array with more information\n      // e.g. { label: this.label, error: this.errorMessageInt },\n      // but how to deal with the additionalOptions\n      // for now a boolean is enough\n      return !(isValidChipsInput && !this.hasAdditionalPropErrors);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    ref=\"chipsBelowEl\"\n    v-bind=\"rootAttrs\"\n    class=\"base-chips-below\">\n    <BaseChipsInput\n      ref=\"chipsInputEl\"\n      v-bind=\"chipsInputProps\"\n      :model-value=\"selectedBelowListInt\"\n      :close-dropdown-on-option-select=\"closeDropdownOnOptionSelect\"\n      :is-loading=\"isLoading\"\n      :display-chips-inline=\"false\"\n      :sort-text=\"sortText\"\n      :sort-name=\"sortName\"\n      :invalid=\"invalidInt\"\n      :error-message=\"errorMessageInt\"\n      @update:model-value=\"updateSelectedList\"\n      @fetch-dropdown-entries=\"fetchDropDownEntries\">\n      <template\n        #drop-down-entry=\"props\">\n        <!-- @slot a slot to provide customized drop down options\n          @binding {Object} item - an option in the options list  -->\n        <slot\n          :item=\"props.item\"\n          name=\"drop-down-entry\" />\n      </template>\n      <template\n        #label-addition>\n        <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs)). for an example see [BaseChipsInputField](BaseChipsInputField) -->\n        <slot name=\"label-addition\" />\n      </template>\n      <template\n        #input-field-addition-before>\n        <!-- @slot Slot to allow for additional elements in the input field <div> (before <input>). for an example see [BaseChipsInputField](BaseChipsInputField) -->\n        <slot name=\"input-field-addition-before\" />\n      </template>\n      <template #input-field-addition-after>\n        <!-- @slot for adding elements after input -->\n        <slot name=\"input-field-addition-after\" />\n      </template>\n      <template #post-input-field>\n        <!-- @slot for adding elements at the end covering the whole height. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"post-input-field\" />\n      </template>\n      <template #error-icon>\n        <!-- @slot use a custom icon instead of standard error/warning icon. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"error-icon\" />\n      </template>\n      <template #remove-icon>\n        <!-- @slot use a custom icon instead of standard remove icon. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n        <slot name=\"remove-icon\" />\n      </template>\n      <template\n        #no-options>\n        <!-- @slot a slot to customize messages in case of no options present in drop down -->\n        <slot\n          name=\"no-options\" />\n      </template>\n      <!-- @slot to add elements below input fields e.g. add drop down; will appear before the\n        chosen chips list -->\n      <template #below-input>\n        <slot name=\"below-input\" />\n      </template>\n    </BaseChipsInput>\n    <Component\n      :is=\"draggableComponent\"\n      v-model=\"draggableList\"\n      :group=\"draggable ? { name: `chips-below-draggable-${internalId}` }: undefined\"\n      :animation=\"draggable ? 200 : undefined\"\n      :set-data=\"draggable ? setDragElement : undefined\"\n      :handle=\"draggable ? '.base-chips-below__icon-handle' : undefined\"\n      @start=\"onDragStart\"\n      @end=\"onDragEnd(selectedBelowListInt, $event)\">\n      <TransitionGroup\n        :name=\"'flip-list'\"\n        type=\"transition\">\n        <div\n          v-for=\"(entry, index) in renderList\"\n          :key=\"'item' + entry.idInt\"\n          :class=\"['base-chips-below__list-item',\n                   { 'base-chips-below__list-item--draggable': draggable }]\">\n          <div\n            :key=\"'line' + entry.idInt\"\n            class=\"base-chips-below__list-item-line\">\n            <div\n              v-if=\"draggable\"\n              :key=\"'iconwrapper' + entry.idInt\"\n              class=\"base-chips-below__list-icon-wrapper\">\n              <div\n                class=\"base-chips-below__icon-handle\">\n                <BaseIcon\n                  :key=\"'icon' + entry.idInt\"\n                  name=\"drag-lines\"\n                  class=\"base-chips-below__list-icon\" />\n              </div>\n            </div>\n            <div\n              :key=\"'chip-wrapper' + entry.idInt\"\n              class=\"base-chips-below__list-item-chip-wrapper\">\n              <BaseChip\n                :id=\"'chips-below' + entry.idInt\"\n                ref=\"selectedChip\"\n                :key=\"'chip' + entry.idInt\"\n                v-model=\"entry[labelPropertyName]\"\n                :editable=\"allowUnknownEntries && chipsEditable\"\n                :is-linked=\"!entry.edited && (entry[identifierPropertyName] === 0\n                  || !!entry[identifierPropertyName])\"\n                @update:model-value=\"modifyChipValue($event, index)\"\n                @remove-entry=\"removeEntry(index)\" />\n            </div>\n            <BaseChipsInput\n              :key=\"'input_' + entry.idInt\"\n              v-model=\"entry[additionalPropertyName]\"\n              :input-id=\"`${inputId || entry.idInt}_${additionalPropertyName}_${entry[identifierPropertyName]}`\"\n              :show-label=\"false\"\n              :label=\"label + '-' + additionalPropertyName\"\n              :list=\"additionalPropOptions\"\n              :show-input-border=\"false\"\n              :allow-dynamic-drop-down-entries=\"false\"\n              :placeholder=\"additionalPropPlaceholder\"\n              :always-linked=\"true\"\n              :language=\"language\"\n              :draggable=\"true\"\n              :drop-down-no-options-info=\"dropDownNoOptionsInfo\"\n              :identifier-property-name=\"identifierPropertyName\"\n              :label-property-name=\"labelPropertyName\"\n              :invalid=\"hasAdditionalPropErrors && additionalPropErrorsList && additionalPropErrorsList[index]\"\n              :error-message=\"validationTexts.required\"\n              :allow-multiple-entries=\"additionalPropAllowMultipleEntries\"\n              :chips-removable=\"chipsRemovable && chipsRemovable[index]\"\n              :show-error-icon=\"showErrorIcon\"\n              :required=\"additionalPropRequired\"\n              :default-entry=\"additionalPropDefaultOption\"\n              class=\"base-chips-below__chips-input\"\n              @update:model-value=\"updateAdditionalProperty($event, index)\" />\n          </div>\n        </div>\n      </TransitionGroup>\n    </Component>\n  </div>\n</template>\n\n<style lang=\"scss\">\n  @use \"@/styles/variables\" as *;\n\n  .base-chips-below {\n    .base-chips-below__list-item {\n      padding: $spacing-small-half 0 0 0;\n\n      &:not(:last-of-type) {\n        margin-bottom: -2px;\n        border-bottom: $separation-line;\n        padding: $spacing-small-half 0;\n      }\n\n      .base-chips-below__list-item-line {\n        display: flex;\n        align-items: center;\n\n        .base-chips-below__list-icon-wrapper {\n          width: $icon-medium;\n          height: $icon-medium;\n          display: flex;\n          flex: 0 0 auto;\n          cursor: grab;\n          position: relative;\n\n          .base-chips-below__icon-handle {\n            display: flex;\n            justify-content: center;\n\n            /* for mobile create a padding around the icon so its easier to grab */\n            @media screen and (max-width: $mobile) {\n              position: absolute;\n              width: calc(#{$icon-medium} + 2 * #{$spacing-small});\n              height: calc(#{$icon-medium} + 2 * #{$spacing-small});\n              padding: $spacing-small;\n              top: 50%;\n              right: -$spacing-small;\n              transform: translateY(-50%);\n            }\n            .base-chips-below__list-icon {\n              max-height: 100%;\n              width: $icon-medium;\n              height: $icon-medium;\n              color: $input-field-color;\n              margin: auto;\n              pointer-events: none;\n            }\n          }\n        }\n\n        .base-chips-below__list-item-chip-wrapper {\n          width: 100%;\n          margin-right: $spacing;\n          max-width: calc(50% - #{$spacing});\n          flex: 1 0 calc(50% - #{$spacing});\n          text-align: left;\n        }\n\n        .base-chips-below__chips-input {\n          max-width: calc(50%);\n          flex: 1 0 calc(50%);\n        }\n      }\n\n      &.base-chips-below__list-item--draggable {\n        .base-chips-below__list-item-chip-wrapper {\n          margin-left: $spacing-small;\n          max-width: calc(50% - (2 * #{$spacing}));\n          flex: 1 0 calc(50% - (2 * #{$spacing}));\n        }\n\n        .base-chips-below__chips-input {\n          max-width: calc(50% - #{$spacing-small} - #{$spacing-small-half});\n          flex: 1 0 calc(50% - #{$spacing-small} - #{$spacing-small-half});\n        }\n      }\n    }\n  }\n</style>\n","import { onClickOutside as onClickOutside$1, useActiveElement, useBattery, useBrowserLocation, useClipboard, useDark, useDeviceMotion, useDeviceOrientation, useDevicePixelRatio, useDevicesList, useDocumentVisibility, useStorage as useStorage$1, isClient as isClient$1, useDraggable, useElementBounding as useElementBounding$1, useElementSize as useElementSize$1, useElementVisibility as useElementVisibility$1, useEyeDropper, useFullscreen, useGeolocation, useIdle, useMouse as useMouse$1, useMouseInElement as useMouseInElement$1, useMousePressed, useNetwork, useNow, useObjectUrl, useOffsetPagination, useOnline, usePageLeave, usePointer, usePointerLock, usePreferredColorScheme, usePreferredContrast, usePreferredDark as usePreferredDark$1, usePreferredLanguages, usePreferredReducedMotion, usePreferredReducedTransparency, useTimeAgo, useTimestamp, useVirtualList, useWindowFocus, useWindowSize } from '@vueuse/core';\nimport { defineComponent, shallowRef, h, toValue, computed, unref, reactive, hasInjectionContext, getCurrentInstance, onMounted, watchEffect, ref, watch, nextTick, toRefs } from 'vue';\nimport { isClient, toArray, watchImmediate, isObject, tryOnScopeDispose, noop, isIOS, injectLocal, pxValue, pausableWatch, tryOnMounted, toRef, useToggle, notNullish, watchOnce, promiseTimeout, until, useDebounceFn, useThrottleFn, tryOnUnmounted, reactiveOmit } from '@vueuse/shared';\n\nconst OnClickOutside = /* @__PURE__ */ defineComponent({\n  name: \"OnClickOutside\",\n  props: [\"as\", \"options\"],\n  emits: [\"trigger\"],\n  setup(props, { slots, emit }) {\n    const target = shallowRef();\n    onClickOutside$1(target, (e) => {\n      emit(\"trigger\", e);\n    }, props.options);\n    return () => {\n      if (slots.default)\n        return h(props.as || \"div\", { ref: target }, slots.default());\n    };\n  }\n});\n\nconst defaultWindow = isClient ? window : void 0;\n\nfunction unrefElement(elRef) {\n  var _a;\n  const plain = toValue(elRef);\n  return (_a = plain == null ? void 0 : plain.$el) != null ? _a : plain;\n}\n\nfunction useEventListener(...args) {\n  const cleanups = [];\n  const cleanup = () => {\n    cleanups.forEach((fn) => fn());\n    cleanups.length = 0;\n  };\n  const register = (el, event, listener, options) => {\n    el.addEventListener(event, listener, options);\n    return () => el.removeEventListener(event, listener, options);\n  };\n  const firstParamTargets = computed(() => {\n    const test = toArray(toValue(args[0])).filter((e) => e != null);\n    return test.every((e) => typeof e !== \"string\") ? test : void 0;\n  });\n  const stopWatch = watchImmediate(\n    () => {\n      var _a, _b;\n      return [\n        (_b = (_a = firstParamTargets.value) == null ? void 0 : _a.map((e) => unrefElement(e))) != null ? _b : [defaultWindow].filter((e) => e != null),\n        toArray(toValue(firstParamTargets.value ? args[1] : args[0])),\n        toArray(unref(firstParamTargets.value ? args[2] : args[1])),\n        // @ts-expect-error - TypeScript gets the correct types, but somehow still complains\n        toValue(firstParamTargets.value ? args[3] : args[2])\n      ];\n    },\n    ([raw_targets, raw_events, raw_listeners, raw_options]) => {\n      cleanup();\n      if (!(raw_targets == null ? void 0 : raw_targets.length) || !(raw_events == null ? void 0 : raw_events.length) || !(raw_listeners == null ? void 0 : raw_listeners.length))\n        return;\n      const optionsClone = isObject(raw_options) ? { ...raw_options } : raw_options;\n      cleanups.push(\n        ...raw_targets.flatMap(\n          (el) => raw_events.flatMap(\n            (event) => raw_listeners.map((listener) => register(el, event, listener, optionsClone))\n          )\n        )\n      );\n    },\n    { flush: \"post\" }\n  );\n  const stop = () => {\n    stopWatch();\n    cleanup();\n  };\n  tryOnScopeDispose(cleanup);\n  return stop;\n}\n\nlet _iOSWorkaround = false;\nfunction onClickOutside(target, handler, options = {}) {\n  const { window = defaultWindow, ignore = [], capture = true, detectIframe = false, controls = false } = options;\n  if (!window) {\n    return controls ? { stop: noop, cancel: noop, trigger: noop } : noop;\n  }\n  if (isIOS && !_iOSWorkaround) {\n    _iOSWorkaround = true;\n    const listenerOptions = { passive: true };\n    Array.from(window.document.body.children).forEach((el) => el.addEventListener(\"click\", noop, listenerOptions));\n    window.document.documentElement.addEventListener(\"click\", noop, listenerOptions);\n  }\n  let shouldListen = true;\n  const shouldIgnore = (event) => {\n    return toValue(ignore).some((target2) => {\n      if (typeof target2 === \"string\") {\n        return Array.from(window.document.querySelectorAll(target2)).some((el) => el === event.target || event.composedPath().includes(el));\n      } else {\n        const el = unrefElement(target2);\n        return el && (event.target === el || event.composedPath().includes(el));\n      }\n    });\n  };\n  function hasMultipleRoots(target2) {\n    const vm = toValue(target2);\n    return vm && vm.$.subTree.shapeFlag === 16;\n  }\n  function checkMultipleRoots(target2, event) {\n    const vm = toValue(target2);\n    const children = vm.$.subTree && vm.$.subTree.children;\n    if (children == null || !Array.isArray(children))\n      return false;\n    return children.some((child) => child.el === event.target || event.composedPath().includes(child.el));\n  }\n  const listener = (event) => {\n    const el = unrefElement(target);\n    if (event.target == null)\n      return;\n    if (!(el instanceof Element) && hasMultipleRoots(target) && checkMultipleRoots(target, event))\n      return;\n    if (!el || el === event.target || event.composedPath().includes(el))\n      return;\n    if (\"detail\" in event && event.detail === 0)\n      shouldListen = !shouldIgnore(event);\n    if (!shouldListen) {\n      shouldListen = true;\n      return;\n    }\n    handler(event);\n  };\n  let isProcessingClick = false;\n  const cleanup = [\n    useEventListener(window, \"click\", (event) => {\n      if (!isProcessingClick) {\n        isProcessingClick = true;\n        setTimeout(() => {\n          isProcessingClick = false;\n        }, 0);\n        listener(event);\n      }\n    }, { passive: true, capture }),\n    useEventListener(window, \"pointerdown\", (e) => {\n      const el = unrefElement(target);\n      shouldListen = !shouldIgnore(e) && !!(el && !e.composedPath().includes(el));\n    }, { passive: true }),\n    detectIframe && useEventListener(window, \"blur\", (event) => {\n      setTimeout(() => {\n        var _a;\n        const el = unrefElement(target);\n        if (((_a = window.document.activeElement) == null ? void 0 : _a.tagName) === \"IFRAME\" && !(el == null ? void 0 : el.contains(window.document.activeElement))) {\n          handler(event);\n        }\n      }, 0);\n    }, { passive: true })\n  ].filter(Boolean);\n  const stop = () => cleanup.forEach((fn) => fn());\n  if (controls) {\n    return {\n      stop,\n      cancel: () => {\n        shouldListen = false;\n      },\n      trigger: (event) => {\n        shouldListen = true;\n        listener(event);\n        shouldListen = false;\n      }\n    };\n  }\n  return stop;\n}\n\nconst stopClickOutsideMap = /* @__PURE__ */ new WeakMap();\nconst vOnClickOutside = {\n  mounted(el, binding) {\n    const capture = !binding.modifiers.bubble;\n    let stop;\n    if (typeof binding.value === \"function\") {\n      stop = onClickOutside(el, binding.value, { capture });\n    } else {\n      const [handler, options] = binding.value;\n      stop = onClickOutside(el, handler, Object.assign({ capture }, options));\n    }\n    stopClickOutsideMap.set(el, stop);\n  },\n  unmounted(el) {\n    const stop = stopClickOutsideMap.get(el);\n    if (stop && typeof stop === \"function\") {\n      stop();\n    } else {\n      stop == null ? void 0 : stop.stop();\n    }\n    stopClickOutsideMap.delete(el);\n  }\n};\n\nfunction createKeyPredicate(keyFilter) {\n  if (typeof keyFilter === \"function\")\n    return keyFilter;\n  else if (typeof keyFilter === \"string\")\n    return (event) => event.key === keyFilter;\n  else if (Array.isArray(keyFilter))\n    return (event) => keyFilter.includes(event.key);\n  return () => true;\n}\nfunction onKeyStroke(...args) {\n  let key;\n  let handler;\n  let options = {};\n  if (args.length === 3) {\n    key = args[0];\n    handler = args[1];\n    options = args[2];\n  } else if (args.length === 2) {\n    if (typeof args[1] === \"object\") {\n      key = true;\n      handler = args[0];\n      options = args[1];\n    } else {\n      key = args[0];\n      handler = args[1];\n    }\n  } else {\n    key = true;\n    handler = args[0];\n  }\n  const {\n    target = defaultWindow,\n    eventName = \"keydown\",\n    passive = false,\n    dedupe = false\n  } = options;\n  const predicate = createKeyPredicate(key);\n  const listener = (e) => {\n    if (e.repeat && toValue(dedupe))\n      return;\n    if (predicate(e))\n      handler(e);\n  };\n  return useEventListener(target, eventName, listener, passive);\n}\n\nconst vOnKeyStroke = {\n  mounted(el, binding) {\n    var _a, _b;\n    const keys = (_b = (_a = binding.arg) == null ? void 0 : _a.split(\",\")) != null ? _b : true;\n    if (typeof binding.value === \"function\") {\n      onKeyStroke(keys, binding.value, {\n        target: el\n      });\n    } else {\n      const [handler, options] = binding.value;\n      onKeyStroke(keys, handler, {\n        target: el,\n        ...options\n      });\n    }\n  }\n};\n\nconst DEFAULT_DELAY = 500;\nconst DEFAULT_THRESHOLD = 10;\nfunction onLongPress(target, handler, options) {\n  var _a, _b;\n  const elementRef = computed(() => unrefElement(target));\n  let timeout;\n  let posStart;\n  let startTimestamp;\n  let hasLongPressed = false;\n  function clear() {\n    if (timeout) {\n      clearTimeout(timeout);\n      timeout = void 0;\n    }\n    posStart = void 0;\n    startTimestamp = void 0;\n    hasLongPressed = false;\n  }\n  function getDelay(ev) {\n    const delay = options == null ? void 0 : options.delay;\n    if (typeof delay === \"function\") {\n      return delay(ev);\n    }\n    return delay != null ? delay : DEFAULT_DELAY;\n  }\n  function onRelease(ev) {\n    var _a2, _b2, _c;\n    const [_startTimestamp, _posStart, _hasLongPressed] = [startTimestamp, posStart, hasLongPressed];\n    clear();\n    if (!(options == null ? void 0 : options.onMouseUp) || !_posStart || !_startTimestamp)\n      return;\n    if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)\n      return;\n    if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)\n      ev.preventDefault();\n    if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)\n      ev.stopPropagation();\n    const dx = ev.x - _posStart.x;\n    const dy = ev.y - _posStart.y;\n    const distance = Math.sqrt(dx * dx + dy * dy);\n    options.onMouseUp(ev.timeStamp - _startTimestamp, distance, _hasLongPressed);\n  }\n  function onDown(ev) {\n    var _a2, _b2, _c;\n    if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)\n      return;\n    clear();\n    if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)\n      ev.preventDefault();\n    if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)\n      ev.stopPropagation();\n    posStart = {\n      x: ev.x,\n      y: ev.y\n    };\n    startTimestamp = ev.timeStamp;\n    timeout = setTimeout(\n      () => {\n        hasLongPressed = true;\n        handler(ev);\n      },\n      getDelay(ev)\n    );\n  }\n  function onMove(ev) {\n    var _a2, _b2, _c, _d;\n    if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)\n      return;\n    if (!posStart || (options == null ? void 0 : options.distanceThreshold) === false)\n      return;\n    if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)\n      ev.preventDefault();\n    if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)\n      ev.stopPropagation();\n    const dx = ev.x - posStart.x;\n    const dy = ev.y - posStart.y;\n    const distance = Math.sqrt(dx * dx + dy * dy);\n    if (distance >= ((_d = options == null ? void 0 : options.distanceThreshold) != null ? _d : DEFAULT_THRESHOLD))\n      clear();\n  }\n  const listenerOptions = {\n    capture: (_a = options == null ? void 0 : options.modifiers) == null ? void 0 : _a.capture,\n    once: (_b = options == null ? void 0 : options.modifiers) == null ? void 0 : _b.once\n  };\n  const cleanup = [\n    useEventListener(elementRef, \"pointerdown\", onDown, listenerOptions),\n    useEventListener(elementRef, \"pointermove\", onMove, listenerOptions),\n    useEventListener(elementRef, [\"pointerup\", \"pointerleave\"], onRelease, listenerOptions)\n  ];\n  const stop = () => cleanup.forEach((fn) => fn());\n  return stop;\n}\n\nconst OnLongPress = /* @__PURE__ */ defineComponent({\n  name: \"OnLongPress\",\n  props: [\"as\", \"options\"],\n  emits: [\"trigger\"],\n  setup(props, { slots, emit }) {\n    const target = shallowRef();\n    onLongPress(\n      target,\n      (e) => {\n        emit(\"trigger\", e);\n      },\n      props.options\n    );\n    return () => {\n      if (slots.default)\n        return h(props.as || \"div\", { ref: target }, slots.default());\n    };\n  }\n});\n\nconst vOnLongPress = {\n  mounted(el, binding) {\n    if (typeof binding.value === \"function\")\n      onLongPress(el, binding.value, { modifiers: binding.modifiers });\n    else\n      onLongPress(el, ...binding.value);\n  }\n};\n\nconst UseActiveElement = /* @__PURE__ */ defineComponent({\n  name: \"UseActiveElement\",\n  setup(props, { slots }) {\n    const data = reactive({\n      element: useActiveElement()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseBattery = /* @__PURE__ */ defineComponent({\n  name: \"UseBattery\",\n  setup(props, { slots }) {\n    const data = reactive(useBattery(props));\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseBrowserLocation = /* @__PURE__ */ defineComponent({\n  name: \"UseBrowserLocation\",\n  setup(props, { slots }) {\n    const data = reactive(useBrowserLocation());\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseClipboard = /* @__PURE__ */ defineComponent({\n  name: \"UseClipboard\",\n  props: [\n    \"source\",\n    \"read\",\n    \"navigator\",\n    \"copiedDuring\",\n    \"legacy\"\n  ],\n  setup(props, { slots }) {\n    const data = reactive(useClipboard(props));\n    return () => {\n      var _a;\n      return (_a = slots.default) == null ? void 0 : _a.call(slots, data);\n    };\n  }\n});\n\nconst _global = typeof globalThis !== \"undefined\" ? globalThis : typeof window !== \"undefined\" ? window : typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : {};\nconst globalKey = \"__vueuse_ssr_handlers__\";\nconst handlers = /* @__PURE__ */ getHandlers();\nfunction getHandlers() {\n  if (!(globalKey in _global))\n    _global[globalKey] = _global[globalKey] || {};\n  return _global[globalKey];\n}\nfunction getSSRHandler(key, fallback) {\n  return handlers[key] || fallback;\n}\n\nconst ssrWidthSymbol = Symbol(\"vueuse-ssr-width\");\n// @__NO_SIDE_EFFECTS__\nfunction useSSRWidth() {\n  const ssrWidth = hasInjectionContext() ? injectLocal(ssrWidthSymbol, null) : null;\n  return typeof ssrWidth === \"number\" ? ssrWidth : void 0;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useMounted() {\n  const isMounted = shallowRef(false);\n  const instance = getCurrentInstance();\n  if (instance) {\n    onMounted(() => {\n      isMounted.value = true;\n    }, instance);\n  }\n  return isMounted;\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction useSupported(callback) {\n  const isMounted = useMounted();\n  return computed(() => {\n    isMounted.value;\n    return Boolean(callback());\n  });\n}\n\nfunction useMediaQuery(query, options = {}) {\n  const { window = defaultWindow, ssrWidth = useSSRWidth() } = options;\n  const isSupported = useSupported(() => window && \"matchMedia\" in window && typeof window.matchMedia === \"function\");\n  const ssrSupport = shallowRef(typeof ssrWidth === \"number\");\n  const mediaQuery = shallowRef();\n  const matches = shallowRef(false);\n  const handler = (event) => {\n    matches.value = event.matches;\n  };\n  watchEffect(() => {\n    if (ssrSupport.value) {\n      ssrSupport.value = !isSupported.value;\n      const queryStrings = toValue(query).split(\",\");\n      matches.value = queryStrings.some((queryString) => {\n        const not = queryString.includes(\"not all\");\n        const minWidth = queryString.match(/\\(\\s*min-width:\\s*(-?\\d+(?:\\.\\d*)?[a-z]+\\s*)\\)/);\n        const maxWidth = queryString.match(/\\(\\s*max-width:\\s*(-?\\d+(?:\\.\\d*)?[a-z]+\\s*)\\)/);\n        let res = Boolean(minWidth || maxWidth);\n        if (minWidth && res) {\n          res = ssrWidth >= pxValue(minWidth[1]);\n        }\n        if (maxWidth && res) {\n          res = ssrWidth <= pxValue(maxWidth[1]);\n        }\n        return not ? !res : res;\n      });\n      return;\n    }\n    if (!isSupported.value)\n      return;\n    mediaQuery.value = window.matchMedia(toValue(query));\n    matches.value = mediaQuery.value.matches;\n  });\n  useEventListener(mediaQuery, \"change\", handler, { passive: true });\n  return computed(() => matches.value);\n}\n\n// @__NO_SIDE_EFFECTS__\nfunction usePreferredDark(options) {\n  return useMediaQuery(\"(prefers-color-scheme: dark)\", options);\n}\n\nfunction guessSerializerType(rawInit) {\n  return rawInit == null ? \"any\" : rawInit instanceof Set ? \"set\" : rawInit instanceof Map ? \"map\" : rawInit instanceof Date ? \"date\" : typeof rawInit === \"boolean\" ? \"boolean\" : typeof rawInit === \"string\" ? \"string\" : typeof rawInit === \"object\" ? \"object\" : !Number.isNaN(rawInit) ? \"number\" : \"any\";\n}\n\nconst StorageSerializers = {\n  boolean: {\n    read: (v) => v === \"true\",\n    write: (v) => String(v)\n  },\n  object: {\n    read: (v) => JSON.parse(v),\n    write: (v) => JSON.stringify(v)\n  },\n  number: {\n    read: (v) => Number.parseFloat(v),\n    write: (v) => String(v)\n  },\n  any: {\n    read: (v) => v,\n    write: (v) => String(v)\n  },\n  string: {\n    read: (v) => v,\n    write: (v) => String(v)\n  },\n  map: {\n    read: (v) => new Map(JSON.parse(v)),\n    write: (v) => JSON.stringify(Array.from(v.entries()))\n  },\n  set: {\n    read: (v) => new Set(JSON.parse(v)),\n    write: (v) => JSON.stringify(Array.from(v))\n  },\n  date: {\n    read: (v) => new Date(v),\n    write: (v) => v.toISOString()\n  }\n};\nconst customStorageEventName = \"vueuse-storage\";\nfunction useStorage(key, defaults, storage, options = {}) {\n  var _a;\n  const {\n    flush = \"pre\",\n    deep = true,\n    listenToStorageChanges = true,\n    writeDefaults = true,\n    mergeDefaults = false,\n    shallow,\n    window = defaultWindow,\n    eventFilter,\n    onError = (e) => {\n      console.error(e);\n    },\n    initOnMounted\n  } = options;\n  const data = (shallow ? shallowRef : ref)(typeof defaults === \"function\" ? defaults() : defaults);\n  const keyComputed = computed(() => toValue(key));\n  if (!storage) {\n    try {\n      storage = getSSRHandler(\"getDefaultStorage\", () => {\n        var _a2;\n        return (_a2 = defaultWindow) == null ? void 0 : _a2.localStorage;\n      })();\n    } catch (e) {\n      onError(e);\n    }\n  }\n  if (!storage)\n    return data;\n  const rawInit = toValue(defaults);\n  const type = guessSerializerType(rawInit);\n  const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type];\n  const { pause: pauseWatch, resume: resumeWatch } = pausableWatch(\n    data,\n    (newValue) => write(newValue),\n    { flush, deep, eventFilter }\n  );\n  watch(keyComputed, () => update(), { flush });\n  let firstMounted = false;\n  const onStorageEvent = (ev) => {\n    if (initOnMounted && !firstMounted) {\n      return;\n    }\n    update(ev);\n  };\n  const onStorageCustomEvent = (ev) => {\n    if (initOnMounted && !firstMounted) {\n      return;\n    }\n    updateFromCustomEvent(ev);\n  };\n  if (window && listenToStorageChanges) {\n    if (storage instanceof Storage)\n      useEventListener(window, \"storage\", onStorageEvent, { passive: true });\n    else\n      useEventListener(window, customStorageEventName, onStorageCustomEvent);\n  }\n  if (initOnMounted) {\n    tryOnMounted(() => {\n      firstMounted = true;\n      update();\n    });\n  } else {\n    update();\n  }\n  function dispatchWriteEvent(oldValue, newValue) {\n    if (window) {\n      const payload = {\n        key: keyComputed.value,\n        oldValue,\n        newValue,\n        storageArea: storage\n      };\n      window.dispatchEvent(storage instanceof Storage ? new StorageEvent(\"storage\", payload) : new CustomEvent(customStorageEventName, {\n        detail: payload\n      }));\n    }\n  }\n  function write(v) {\n    try {\n      const oldValue = storage.getItem(keyComputed.value);\n      if (v == null) {\n        dispatchWriteEvent(oldValue, null);\n        storage.removeItem(keyComputed.value);\n      } else {\n        const serialized = serializer.write(v);\n        if (oldValue !== serialized) {\n          storage.setItem(keyComputed.value, serialized);\n          dispatchWriteEvent(oldValue, serialized);\n        }\n      }\n    } catch (e) {\n      onError(e);\n    }\n  }\n  function read(event) {\n    const rawValue = event ? event.newValue : storage.getItem(keyComputed.value);\n    if (rawValue == null) {\n      if (writeDefaults && rawInit != null)\n        storage.setItem(keyComputed.value, serializer.write(rawInit));\n      return rawInit;\n    } else if (!event && mergeDefaults) {\n      const value = serializer.read(rawValue);\n      if (typeof mergeDefaults === \"function\")\n        return mergeDefaults(value, rawInit);\n      else if (type === \"object\" && !Array.isArray(value))\n        return { ...rawInit, ...value };\n      return value;\n    } else if (typeof rawValue !== \"string\") {\n      return rawValue;\n    } else {\n      return serializer.read(rawValue);\n    }\n  }\n  function update(event) {\n    if (event && event.storageArea !== storage)\n      return;\n    if (event && event.key == null) {\n      data.value = rawInit;\n      return;\n    }\n    if (event && event.key !== keyComputed.value) {\n      return;\n    }\n    pauseWatch();\n    try {\n      const serializedData = serializer.write(data.value);\n      if (event === void 0 || (event == null ? void 0 : event.newValue) !== serializedData) {\n        data.value = read(event);\n      }\n    } catch (e) {\n      onError(e);\n    } finally {\n      if (event)\n        nextTick(resumeWatch);\n      else\n        resumeWatch();\n    }\n  }\n  function updateFromCustomEvent(event) {\n    update(event.detail);\n  }\n  return data;\n}\n\nconst CSS_DISABLE_TRANS = \"*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}\";\nfunction useColorMode(options = {}) {\n  const {\n    selector = \"html\",\n    attribute = \"class\",\n    initialValue = \"auto\",\n    window = defaultWindow,\n    storage,\n    storageKey = \"vueuse-color-scheme\",\n    listenToStorageChanges = true,\n    storageRef,\n    emitAuto,\n    disableTransition = true\n  } = options;\n  const modes = {\n    auto: \"\",\n    light: \"light\",\n    dark: \"dark\",\n    ...options.modes || {}\n  };\n  const preferredDark = usePreferredDark({ window });\n  const system = computed(() => preferredDark.value ? \"dark\" : \"light\");\n  const store = storageRef || (storageKey == null ? toRef(initialValue) : useStorage(storageKey, initialValue, storage, { window, listenToStorageChanges }));\n  const state = computed(() => store.value === \"auto\" ? system.value : store.value);\n  const updateHTMLAttrs = getSSRHandler(\n    \"updateHTMLAttrs\",\n    (selector2, attribute2, value) => {\n      const el = typeof selector2 === \"string\" ? window == null ? void 0 : window.document.querySelector(selector2) : unrefElement(selector2);\n      if (!el)\n        return;\n      const classesToAdd = /* @__PURE__ */ new Set();\n      const classesToRemove = /* @__PURE__ */ new Set();\n      let attributeToChange = null;\n      if (attribute2 === \"class\") {\n        const current = value.split(/\\s/g);\n        Object.values(modes).flatMap((i) => (i || \"\").split(/\\s/g)).filter(Boolean).forEach((v) => {\n          if (current.includes(v))\n            classesToAdd.add(v);\n          else\n            classesToRemove.add(v);\n        });\n      } else {\n        attributeToChange = { key: attribute2, value };\n      }\n      if (classesToAdd.size === 0 && classesToRemove.size === 0 && attributeToChange === null)\n        return;\n      let style;\n      if (disableTransition) {\n        style = window.document.createElement(\"style\");\n        style.appendChild(document.createTextNode(CSS_DISABLE_TRANS));\n        window.document.head.appendChild(style);\n      }\n      for (const c of classesToAdd) {\n        el.classList.add(c);\n      }\n      for (const c of classesToRemove) {\n        el.classList.remove(c);\n      }\n      if (attributeToChange) {\n        el.setAttribute(attributeToChange.key, attributeToChange.value);\n      }\n      if (disableTransition) {\n        window.getComputedStyle(style).opacity;\n        document.head.removeChild(style);\n      }\n    }\n  );\n  function defaultOnChanged(mode) {\n    var _a;\n    updateHTMLAttrs(selector, attribute, (_a = modes[mode]) != null ? _a : mode);\n  }\n  function onChanged(mode) {\n    if (options.onChanged)\n      options.onChanged(mode, defaultOnChanged);\n    else\n      defaultOnChanged(mode);\n  }\n  watch(state, onChanged, { flush: \"post\", immediate: true });\n  tryOnMounted(() => onChanged(state.value));\n  const auto = computed({\n    get() {\n      return emitAuto ? store.value : state.value;\n    },\n    set(v) {\n      store.value = v;\n    }\n  });\n  return Object.assign(auto, { store, system, state });\n}\n\nconst UseColorMode = /* @__PURE__ */ defineComponent({\n  name: \"UseColorMode\",\n  props: [\"selector\", \"attribute\", \"modes\", \"onChanged\", \"storageKey\", \"storage\", \"emitAuto\"],\n  setup(props, { slots }) {\n    const mode = useColorMode(props);\n    const data = reactive({\n      mode,\n      system: mode.system,\n      store: mode.store\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseDark = /* @__PURE__ */ defineComponent({\n  name: \"UseDark\",\n  props: [\"selector\", \"attribute\", \"valueDark\", \"valueLight\", \"onChanged\", \"storageKey\", \"storage\"],\n  setup(props, { slots }) {\n    const isDark = useDark(props);\n    const data = reactive({\n      isDark,\n      toggleDark: useToggle(isDark)\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseDeviceMotion = /* @__PURE__ */ defineComponent({\n  name: \"UseDeviceMotion\",\n  setup(props, { slots }) {\n    const data = useDeviceMotion();\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseDeviceOrientation = /* @__PURE__ */ defineComponent({\n  name: \"UseDeviceOrientation\",\n  setup(props, { slots }) {\n    const data = reactive(useDeviceOrientation());\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseDevicePixelRatio = /* @__PURE__ */ defineComponent({\n  name: \"UseDevicePixelRatio\",\n  setup(props, { slots }) {\n    const data = reactive({\n      pixelRatio: useDevicePixelRatio()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseDevicesList = /* @__PURE__ */ defineComponent({\n  name: \"UseDevicesList\",\n  props: [\"onUpdated\", \"requestPermissions\", \"constraints\"],\n  setup(props, { slots }) {\n    const data = reactive(useDevicesList(props));\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseDocumentVisibility = /* @__PURE__ */ defineComponent({\n  name: \"UseDocumentVisibility\",\n  setup(props, { slots }) {\n    const data = reactive({\n      visibility: useDocumentVisibility()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseDraggable = /* @__PURE__ */ defineComponent({\n  name: \"UseDraggable\",\n  props: [\n    \"storageKey\",\n    \"storageType\",\n    \"initialValue\",\n    \"exact\",\n    \"preventDefault\",\n    \"stopPropagation\",\n    \"pointerTypes\",\n    \"as\",\n    \"handle\",\n    \"axis\",\n    \"onStart\",\n    \"onMove\",\n    \"onEnd\",\n    \"disabled\",\n    \"buttons\",\n    \"containerElement\",\n    \"capture\"\n  ],\n  setup(props, { slots }) {\n    const target = shallowRef();\n    const handle = computed(() => {\n      var _a;\n      return (_a = toValue(props.handle)) != null ? _a : target.value;\n    });\n    const containerElement = computed(() => {\n      var _a;\n      return (_a = props.containerElement) != null ? _a : void 0;\n    });\n    const disabled = computed(() => !!props.disabled);\n    const storageValue = props.storageKey && useStorage$1(\n      props.storageKey,\n      toValue(props.initialValue) || { x: 0, y: 0 },\n      isClient$1 ? props.storageType === \"session\" ? sessionStorage : localStorage : void 0\n    );\n    const initialValue = storageValue || props.initialValue || { x: 0, y: 0 };\n    const onEnd = (position, event) => {\n      var _a;\n      (_a = props.onEnd) == null ? void 0 : _a.call(props, position, event);\n      if (!storageValue)\n        return;\n      storageValue.value.x = position.x;\n      storageValue.value.y = position.y;\n    };\n    const data = reactive(useDraggable(target, {\n      ...props,\n      handle,\n      initialValue,\n      onEnd,\n      disabled,\n      containerElement\n    }));\n    return () => {\n      if (slots.default)\n        return h(props.as || \"div\", { ref: target, style: `touch-action:none;${data.style}` }, slots.default(data));\n    };\n  }\n});\n\nconst UseElementBounding = /* @__PURE__ */ defineComponent({\n  name: \"UseElementBounding\",\n  props: [\"box\", \"as\"],\n  setup(props, { slots }) {\n    const target = shallowRef();\n    const data = reactive(useElementBounding$1(target));\n    return () => {\n      if (slots.default)\n        return h(props.as || \"div\", { ref: target }, slots.default(data));\n    };\n  }\n});\n\nfunction useMutationObserver(target, callback, options = {}) {\n  const { window = defaultWindow, ...mutationOptions } = options;\n  let observer;\n  const isSupported = useSupported(() => window && \"MutationObserver\" in window);\n  const cleanup = () => {\n    if (observer) {\n      observer.disconnect();\n      observer = void 0;\n    }\n  };\n  const targets = computed(() => {\n    const value = toValue(target);\n    const items = toArray(value).map(unrefElement).filter(notNullish);\n    return new Set(items);\n  });\n  const stopWatch = watch(\n    targets,\n    (newTargets) => {\n      cleanup();\n      if (isSupported.value && newTargets.size) {\n        observer = new MutationObserver(callback);\n        newTargets.forEach((el) => observer.observe(el, mutationOptions));\n      }\n    },\n    { immediate: true, flush: \"post\" }\n  );\n  const takeRecords = () => {\n    return observer == null ? void 0 : observer.takeRecords();\n  };\n  const stop = () => {\n    stopWatch();\n    cleanup();\n  };\n  tryOnScopeDispose(stop);\n  return {\n    isSupported,\n    stop,\n    takeRecords\n  };\n}\n\nfunction useResizeObserver(target, callback, options = {}) {\n  const { window = defaultWindow, ...observerOptions } = options;\n  let observer;\n  const isSupported = useSupported(() => window && \"ResizeObserver\" in window);\n  const cleanup = () => {\n    if (observer) {\n      observer.disconnect();\n      observer = void 0;\n    }\n  };\n  const targets = computed(() => {\n    const _targets = toValue(target);\n    return Array.isArray(_targets) ? _targets.map((el) => unrefElement(el)) : [unrefElement(_targets)];\n  });\n  const stopWatch = watch(\n    targets,\n    (els) => {\n      cleanup();\n      if (isSupported.value && window) {\n        observer = new ResizeObserver(callback);\n        for (const _el of els) {\n          if (_el)\n            observer.observe(_el, observerOptions);\n        }\n      }\n    },\n    { immediate: true, flush: \"post\" }\n  );\n  const stop = () => {\n    cleanup();\n    stopWatch();\n  };\n  tryOnScopeDispose(stop);\n  return {\n    isSupported,\n    stop\n  };\n}\n\nfunction useElementBounding(target, options = {}) {\n  const {\n    reset = true,\n    windowResize = true,\n    windowScroll = true,\n    immediate = true,\n    updateTiming = \"sync\"\n  } = options;\n  const height = shallowRef(0);\n  const bottom = shallowRef(0);\n  const left = shallowRef(0);\n  const right = shallowRef(0);\n  const top = shallowRef(0);\n  const width = shallowRef(0);\n  const x = shallowRef(0);\n  const y = shallowRef(0);\n  function recalculate() {\n    const el = unrefElement(target);\n    if (!el) {\n      if (reset) {\n        height.value = 0;\n        bottom.value = 0;\n        left.value = 0;\n        right.value = 0;\n        top.value = 0;\n        width.value = 0;\n        x.value = 0;\n        y.value = 0;\n      }\n      return;\n    }\n    const rect = el.getBoundingClientRect();\n    height.value = rect.height;\n    bottom.value = rect.bottom;\n    left.value = rect.left;\n    right.value = rect.right;\n    top.value = rect.top;\n    width.value = rect.width;\n    x.value = rect.x;\n    y.value = rect.y;\n  }\n  function update() {\n    if (updateTiming === \"sync\")\n      recalculate();\n    else if (updateTiming === \"next-frame\")\n      requestAnimationFrame(() => recalculate());\n  }\n  useResizeObserver(target, update);\n  watch(() => unrefElement(target), (ele) => !ele && update());\n  useMutationObserver(target, update, {\n    attributeFilter: [\"style\", \"class\"]\n  });\n  if (windowScroll)\n    useEventListener(\"scroll\", update, { capture: true, passive: true });\n  if (windowResize)\n    useEventListener(\"resize\", update, { passive: true });\n  tryOnMounted(() => {\n    if (immediate)\n      update();\n  });\n  return {\n    height,\n    bottom,\n    left,\n    right,\n    top,\n    width,\n    x,\n    y,\n    update\n  };\n}\n\nconst vElementBounding = {\n  mounted(el, binding) {\n    const [handler, options] = typeof binding.value === \"function\" ? [binding.value, {}] : binding.value;\n    const {\n      height,\n      bottom,\n      left,\n      right,\n      top,\n      width,\n      x,\n      y\n    } = useElementBounding(el, options);\n    watch([height, bottom, left, right, top, width, x, y], () => handler({ height, bottom, left, right, top, width, x, y }));\n  }\n};\n\nfunction onElementRemoval(target, callback, options = {}) {\n  const {\n    window = defaultWindow,\n    document = window == null ? void 0 : window.document,\n    flush = \"sync\"\n  } = options;\n  if (!window || !document)\n    return noop;\n  let stopFn;\n  const cleanupAndUpdate = (fn) => {\n    stopFn == null ? void 0 : stopFn();\n    stopFn = fn;\n  };\n  const stopWatch = watchEffect(() => {\n    const el = unrefElement(target);\n    if (el) {\n      const { stop } = useMutationObserver(\n        document,\n        (mutationsList) => {\n          const targetRemoved = mutationsList.map((mutation) => [...mutation.removedNodes]).flat().some((node) => node === el || node.contains(el));\n          if (targetRemoved) {\n            callback(mutationsList);\n          }\n        },\n        {\n          window,\n          childList: true,\n          subtree: true\n        }\n      );\n      cleanupAndUpdate(stop);\n    }\n  }, { flush });\n  const stopHandle = () => {\n    stopWatch();\n    cleanupAndUpdate();\n  };\n  tryOnScopeDispose(stopHandle);\n  return stopHandle;\n}\n\nfunction useElementHover(el, options = {}) {\n  const {\n    delayEnter = 0,\n    delayLeave = 0,\n    triggerOnRemoval = false,\n    window = defaultWindow\n  } = options;\n  const isHovered = shallowRef(false);\n  let timer;\n  const toggle = (entering) => {\n    const delay = entering ? delayEnter : delayLeave;\n    if (timer) {\n      clearTimeout(timer);\n      timer = void 0;\n    }\n    if (delay)\n      timer = setTimeout(() => isHovered.value = entering, delay);\n    else\n      isHovered.value = entering;\n  };\n  if (!window)\n    return isHovered;\n  useEventListener(el, \"mouseenter\", () => toggle(true), { passive: true });\n  useEventListener(el, \"mouseleave\", () => toggle(false), { passive: true });\n  if (triggerOnRemoval) {\n    onElementRemoval(\n      computed(() => unrefElement(el)),\n      () => toggle(false)\n    );\n  }\n  return isHovered;\n}\n\nconst vElementHover = {\n  mounted(el, binding) {\n    const value = binding.value;\n    if (typeof value === \"function\") {\n      const isHovered = useElementHover(el);\n      watch(isHovered, (v) => value(v));\n    } else {\n      const [handler, options] = value;\n      const isHovered = useElementHover(el, options);\n      watch(isHovered, (v) => handler(v));\n    }\n  }\n};\n\nconst UseElementSize = /* @__PURE__ */ defineComponent({\n  name: \"UseElementSize\",\n  props: [\"width\", \"height\", \"box\", \"as\"],\n  setup(props, { slots }) {\n    var _a, _b;\n    const target = shallowRef();\n    const data = reactive(useElementSize$1(target, { width: (_a = props.width) != null ? _a : 0, height: (_b = props.height) != null ? _b : 0 }, { box: props.box }));\n    return () => {\n      if (slots.default)\n        return h(props.as || \"div\", { ref: target }, slots.default(data));\n    };\n  }\n});\n\nfunction useElementSize(target, initialSize = { width: 0, height: 0 }, options = {}) {\n  const { window = defaultWindow, box = \"content-box\" } = options;\n  const isSVG = computed(() => {\n    var _a, _b;\n    return (_b = (_a = unrefElement(target)) == null ? void 0 : _a.namespaceURI) == null ? void 0 : _b.includes(\"svg\");\n  });\n  const width = shallowRef(initialSize.width);\n  const height = shallowRef(initialSize.height);\n  const { stop: stop1 } = useResizeObserver(\n    target,\n    ([entry]) => {\n      const boxSize = box === \"border-box\" ? entry.borderBoxSize : box === \"content-box\" ? entry.contentBoxSize : entry.devicePixelContentBoxSize;\n      if (window && isSVG.value) {\n        const $elem = unrefElement(target);\n        if ($elem) {\n          const rect = $elem.getBoundingClientRect();\n          width.value = rect.width;\n          height.value = rect.height;\n        }\n      } else {\n        if (boxSize) {\n          const formatBoxSize = toArray(boxSize);\n          width.value = formatBoxSize.reduce((acc, { inlineSize }) => acc + inlineSize, 0);\n          height.value = formatBoxSize.reduce((acc, { blockSize }) => acc + blockSize, 0);\n        } else {\n          width.value = entry.contentRect.width;\n          height.value = entry.contentRect.height;\n        }\n      }\n    },\n    options\n  );\n  tryOnMounted(() => {\n    const ele = unrefElement(target);\n    if (ele) {\n      width.value = \"offsetWidth\" in ele ? ele.offsetWidth : initialSize.width;\n      height.value = \"offsetHeight\" in ele ? ele.offsetHeight : initialSize.height;\n    }\n  });\n  const stop2 = watch(\n    () => unrefElement(target),\n    (ele) => {\n      width.value = ele ? initialSize.width : 0;\n      height.value = ele ? initialSize.height : 0;\n    }\n  );\n  function stop() {\n    stop1();\n    stop2();\n  }\n  return {\n    width,\n    height,\n    stop\n  };\n}\n\nconst vElementSize = {\n  mounted(el, binding) {\n    var _a;\n    const handler = typeof binding.value === \"function\" ? binding.value : (_a = binding.value) == null ? void 0 : _a[0];\n    const options = typeof binding.value === \"function\" ? [] : binding.value.slice(1);\n    const { width, height } = useElementSize(el, ...options);\n    watch([width, height], ([width2, height2]) => handler({ width: width2, height: height2 }));\n  }\n};\n\nconst UseElementVisibility = /* @__PURE__ */ defineComponent({\n  name: \"UseElementVisibility\",\n  props: [\"as\"],\n  setup(props, { slots }) {\n    const target = shallowRef();\n    const data = reactive({\n      isVisible: useElementVisibility$1(target)\n    });\n    return () => {\n      if (slots.default)\n        return h(props.as || \"div\", { ref: target }, slots.default(data));\n    };\n  }\n});\n\nfunction useIntersectionObserver(target, callback, options = {}) {\n  const {\n    root,\n    rootMargin = \"0px\",\n    threshold = 0,\n    window = defaultWindow,\n    immediate = true\n  } = options;\n  const isSupported = useSupported(() => window && \"IntersectionObserver\" in window);\n  const targets = computed(() => {\n    const _target = toValue(target);\n    return toArray(_target).map(unrefElement).filter(notNullish);\n  });\n  let cleanup = noop;\n  const isActive = shallowRef(immediate);\n  const stopWatch = isSupported.value ? watch(\n    () => [targets.value, unrefElement(root), isActive.value],\n    ([targets2, root2]) => {\n      cleanup();\n      if (!isActive.value)\n        return;\n      if (!targets2.length)\n        return;\n      const observer = new IntersectionObserver(\n        callback,\n        {\n          root: unrefElement(root2),\n          rootMargin,\n          threshold\n        }\n      );\n      targets2.forEach((el) => el && observer.observe(el));\n      cleanup = () => {\n        observer.disconnect();\n        cleanup = noop;\n      };\n    },\n    { immediate, flush: \"post\" }\n  ) : noop;\n  const stop = () => {\n    cleanup();\n    stopWatch();\n    isActive.value = false;\n  };\n  tryOnScopeDispose(stop);\n  return {\n    isSupported,\n    isActive,\n    pause() {\n      cleanup();\n      isActive.value = false;\n    },\n    resume() {\n      isActive.value = true;\n    },\n    stop\n  };\n}\n\nfunction useElementVisibility(element, options = {}) {\n  const {\n    window = defaultWindow,\n    scrollTarget,\n    threshold = 0,\n    rootMargin,\n    once = false\n  } = options;\n  const elementIsVisible = shallowRef(false);\n  const { stop } = useIntersectionObserver(\n    element,\n    (intersectionObserverEntries) => {\n      let isIntersecting = elementIsVisible.value;\n      let latestTime = 0;\n      for (const entry of intersectionObserverEntries) {\n        if (entry.time >= latestTime) {\n          latestTime = entry.time;\n          isIntersecting = entry.isIntersecting;\n        }\n      }\n      elementIsVisible.value = isIntersecting;\n      if (once) {\n        watchOnce(elementIsVisible, () => {\n          stop();\n        });\n      }\n    },\n    {\n      root: scrollTarget,\n      window,\n      threshold,\n      rootMargin: toValue(rootMargin)\n    }\n  );\n  return elementIsVisible;\n}\n\nconst vElementVisibility = {\n  mounted(el, binding) {\n    if (typeof binding.value === \"function\") {\n      const handler = binding.value;\n      const isVisible = useElementVisibility(el);\n      watch(isVisible, (v) => handler(v), { immediate: true });\n    } else {\n      const [handler, options] = binding.value;\n      const isVisible = useElementVisibility(el, options);\n      watch(isVisible, (v) => handler(v), { immediate: true });\n    }\n  }\n};\n\nconst UseEyeDropper = /* @__PURE__ */ defineComponent({\n  name: \"UseEyeDropper\",\n  props: {\n    sRGBHex: String\n  },\n  setup(props, { slots }) {\n    const data = reactive(useEyeDropper());\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseFullscreen = /* @__PURE__ */ defineComponent({\n  name: \"UseFullscreen\",\n  props: [\"as\"],\n  setup(props, { slots }) {\n    const target = shallowRef();\n    const data = reactive(useFullscreen(target));\n    return () => {\n      if (slots.default)\n        return h(props.as || \"div\", { ref: target }, slots.default(data));\n    };\n  }\n});\n\nconst UseGeolocation = /* @__PURE__ */ defineComponent({\n  name: \"UseGeolocation\",\n  props: [\"enableHighAccuracy\", \"maximumAge\", \"timeout\", \"navigator\"],\n  setup(props, { slots }) {\n    const data = reactive(useGeolocation(props));\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseIdle = /* @__PURE__ */ defineComponent({\n  name: \"UseIdle\",\n  props: [\"timeout\", \"events\", \"listenForVisibilityChange\", \"initialState\"],\n  setup(props, { slots }) {\n    const data = reactive(useIdle(props.timeout, props));\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nfunction useAsyncState(promise, initialState, options) {\n  var _a;\n  const {\n    immediate = true,\n    delay = 0,\n    onError = (_a = globalThis.reportError) != null ? _a : noop,\n    onSuccess = noop,\n    resetOnExecute = true,\n    shallow = true,\n    throwError\n  } = options != null ? options : {};\n  const state = shallow ? shallowRef(initialState) : ref(initialState);\n  const isReady = shallowRef(false);\n  const isLoading = shallowRef(false);\n  const error = shallowRef(void 0);\n  async function execute(delay2 = 0, ...args) {\n    if (resetOnExecute)\n      state.value = toValue(initialState);\n    error.value = void 0;\n    isReady.value = false;\n    isLoading.value = true;\n    if (delay2 > 0)\n      await promiseTimeout(delay2);\n    const _promise = typeof promise === \"function\" ? promise(...args) : promise;\n    try {\n      const data = await _promise;\n      state.value = data;\n      isReady.value = true;\n      onSuccess(data);\n    } catch (e) {\n      error.value = e;\n      onError(e);\n      if (throwError)\n        throw e;\n    } finally {\n      isLoading.value = false;\n    }\n    return state.value;\n  }\n  if (immediate) {\n    execute(delay);\n  }\n  const shell = {\n    state,\n    isReady,\n    isLoading,\n    error,\n    execute,\n    executeImmediate: (...args) => execute(0, ...args)\n  };\n  function waitUntilIsLoaded() {\n    return new Promise((resolve, reject) => {\n      until(isLoading).toBe(false).then(() => resolve(shell)).catch(reject);\n    });\n  }\n  return {\n    ...shell,\n    then(onFulfilled, onRejected) {\n      return waitUntilIsLoaded().then(onFulfilled, onRejected);\n    }\n  };\n}\n\nasync function loadImage(options) {\n  return new Promise((resolve, reject) => {\n    const img = new Image();\n    const { src, srcset, sizes, class: clazz, loading, crossorigin, referrerPolicy, width, height, decoding, fetchPriority, ismap, usemap } = options;\n    img.src = src;\n    if (srcset != null)\n      img.srcset = srcset;\n    if (sizes != null)\n      img.sizes = sizes;\n    if (clazz != null)\n      img.className = clazz;\n    if (loading != null)\n      img.loading = loading;\n    if (crossorigin != null)\n      img.crossOrigin = crossorigin;\n    if (referrerPolicy != null)\n      img.referrerPolicy = referrerPolicy;\n    if (width != null)\n      img.width = width;\n    if (height != null)\n      img.height = height;\n    if (decoding != null)\n      img.decoding = decoding;\n    if (fetchPriority != null)\n      img.fetchPriority = fetchPriority;\n    if (ismap != null)\n      img.isMap = ismap;\n    if (usemap != null)\n      img.useMap = usemap;\n    img.onload = () => resolve(img);\n    img.onerror = reject;\n  });\n}\nfunction useImage(options, asyncStateOptions = {}) {\n  const state = useAsyncState(\n    () => loadImage(toValue(options)),\n    void 0,\n    {\n      resetOnExecute: true,\n      ...asyncStateOptions\n    }\n  );\n  watch(\n    () => toValue(options),\n    () => state.execute(asyncStateOptions.delay),\n    { deep: true }\n  );\n  return state;\n}\n\nconst UseImage = /* @__PURE__ */ defineComponent({\n  name: \"UseImage\",\n  props: [\n    \"src\",\n    \"srcset\",\n    \"sizes\",\n    \"as\",\n    \"alt\",\n    \"class\",\n    \"loading\",\n    \"crossorigin\",\n    \"referrerPolicy\",\n    \"width\",\n    \"height\",\n    \"decoding\",\n    \"fetchPriority\",\n    \"ismap\",\n    \"usemap\"\n  ],\n  setup(props, { slots }) {\n    const data = reactive(useImage(props));\n    return () => {\n      if (data.isLoading && slots.loading)\n        return slots.loading(data);\n      else if (data.error && slots.error)\n        return slots.error(data.error);\n      if (slots.default)\n        return slots.default(data);\n      return h(props.as || \"img\", props);\n    };\n  }\n});\n\nfunction resolveElement(el) {\n  if (typeof Window !== \"undefined\" && el instanceof Window)\n    return el.document.documentElement;\n  if (typeof Document !== \"undefined\" && el instanceof Document)\n    return el.documentElement;\n  return el;\n}\n\nconst ARRIVED_STATE_THRESHOLD_PIXELS = 1;\nfunction useScroll(element, options = {}) {\n  const {\n    throttle = 0,\n    idle = 200,\n    onStop = noop,\n    onScroll = noop,\n    offset = {\n      left: 0,\n      right: 0,\n      top: 0,\n      bottom: 0\n    },\n    observe: _observe = {\n      mutation: false\n    },\n    eventListenerOptions = {\n      capture: false,\n      passive: true\n    },\n    behavior = \"auto\",\n    window = defaultWindow,\n    onError = (e) => {\n      console.error(e);\n    }\n  } = options;\n  const observe = typeof _observe === \"boolean\" ? {\n    mutation: _observe\n  } : _observe;\n  const internalX = shallowRef(0);\n  const internalY = shallowRef(0);\n  const x = computed({\n    get() {\n      return internalX.value;\n    },\n    set(x2) {\n      scrollTo(x2, void 0);\n    }\n  });\n  const y = computed({\n    get() {\n      return internalY.value;\n    },\n    set(y2) {\n      scrollTo(void 0, y2);\n    }\n  });\n  function scrollTo(_x, _y) {\n    var _a, _b, _c, _d;\n    if (!window)\n      return;\n    const _element = toValue(element);\n    if (!_element)\n      return;\n    (_c = _element instanceof Document ? window.document.body : _element) == null ? void 0 : _c.scrollTo({\n      top: (_a = toValue(_y)) != null ? _a : y.value,\n      left: (_b = toValue(_x)) != null ? _b : x.value,\n      behavior: toValue(behavior)\n    });\n    const scrollContainer = ((_d = _element == null ? void 0 : _element.document) == null ? void 0 : _d.documentElement) || (_element == null ? void 0 : _element.documentElement) || _element;\n    if (x != null)\n      internalX.value = scrollContainer.scrollLeft;\n    if (y != null)\n      internalY.value = scrollContainer.scrollTop;\n  }\n  const isScrolling = shallowRef(false);\n  const arrivedState = reactive({\n    left: true,\n    right: false,\n    top: true,\n    bottom: false\n  });\n  const directions = reactive({\n    left: false,\n    right: false,\n    top: false,\n    bottom: false\n  });\n  const onScrollEnd = (e) => {\n    if (!isScrolling.value)\n      return;\n    isScrolling.value = false;\n    directions.left = false;\n    directions.right = false;\n    directions.top = false;\n    directions.bottom = false;\n    onStop(e);\n  };\n  const onScrollEndDebounced = useDebounceFn(onScrollEnd, throttle + idle);\n  const setArrivedState = (target) => {\n    var _a;\n    if (!window)\n      return;\n    const el = ((_a = target == null ? void 0 : target.document) == null ? void 0 : _a.documentElement) || (target == null ? void 0 : target.documentElement) || unrefElement(target);\n    const { display, flexDirection, direction } = getComputedStyle(el);\n    const directionMultipler = direction === \"rtl\" ? -1 : 1;\n    const scrollLeft = el.scrollLeft;\n    directions.left = scrollLeft < internalX.value;\n    directions.right = scrollLeft > internalX.value;\n    const left = Math.abs(scrollLeft * directionMultipler) <= (offset.left || 0);\n    const right = Math.abs(scrollLeft * directionMultipler) + el.clientWidth >= el.scrollWidth - (offset.right || 0) - ARRIVED_STATE_THRESHOLD_PIXELS;\n    if (display === \"flex\" && flexDirection === \"row-reverse\") {\n      arrivedState.left = right;\n      arrivedState.right = left;\n    } else {\n      arrivedState.left = left;\n      arrivedState.right = right;\n    }\n    internalX.value = scrollLeft;\n    let scrollTop = el.scrollTop;\n    if (target === window.document && !scrollTop)\n      scrollTop = window.document.body.scrollTop;\n    directions.top = scrollTop < internalY.value;\n    directions.bottom = scrollTop > internalY.value;\n    const top = Math.abs(scrollTop) <= (offset.top || 0);\n    const bottom = Math.abs(scrollTop) + el.clientHeight >= el.scrollHeight - (offset.bottom || 0) - ARRIVED_STATE_THRESHOLD_PIXELS;\n    if (display === \"flex\" && flexDirection === \"column-reverse\") {\n      arrivedState.top = bottom;\n      arrivedState.bottom = top;\n    } else {\n      arrivedState.top = top;\n      arrivedState.bottom = bottom;\n    }\n    internalY.value = scrollTop;\n  };\n  const onScrollHandler = (e) => {\n    var _a;\n    if (!window)\n      return;\n    const eventTarget = (_a = e.target.documentElement) != null ? _a : e.target;\n    setArrivedState(eventTarget);\n    isScrolling.value = true;\n    onScrollEndDebounced(e);\n    onScroll(e);\n  };\n  useEventListener(\n    element,\n    \"scroll\",\n    throttle ? useThrottleFn(onScrollHandler, throttle, true, false) : onScrollHandler,\n    eventListenerOptions\n  );\n  tryOnMounted(() => {\n    try {\n      const _element = toValue(element);\n      if (!_element)\n        return;\n      setArrivedState(_element);\n    } catch (e) {\n      onError(e);\n    }\n  });\n  if ((observe == null ? void 0 : observe.mutation) && element != null && element !== window && element !== document) {\n    useMutationObserver(\n      element,\n      () => {\n        const _element = toValue(element);\n        if (!_element)\n          return;\n        setArrivedState(_element);\n      },\n      {\n        attributes: true,\n        childList: true,\n        subtree: true\n      }\n    );\n  }\n  useEventListener(\n    element,\n    \"scrollend\",\n    onScrollEnd,\n    eventListenerOptions\n  );\n  return {\n    x,\n    y,\n    isScrolling,\n    arrivedState,\n    directions,\n    measure() {\n      const _element = toValue(element);\n      if (window && _element)\n        setArrivedState(_element);\n    }\n  };\n}\n\nfunction useInfiniteScroll(element, onLoadMore, options = {}) {\n  var _a;\n  const {\n    direction = \"bottom\",\n    interval = 100,\n    canLoadMore = () => true\n  } = options;\n  const state = reactive(useScroll(\n    element,\n    {\n      ...options,\n      offset: {\n        [direction]: (_a = options.distance) != null ? _a : 0,\n        ...options.offset\n      }\n    }\n  ));\n  const promise = ref();\n  const isLoading = computed(() => !!promise.value);\n  const observedElement = computed(() => {\n    return resolveElement(toValue(element));\n  });\n  const isElementVisible = useElementVisibility(observedElement);\n  function checkAndLoad() {\n    state.measure();\n    if (!observedElement.value || !isElementVisible.value || !canLoadMore(observedElement.value))\n      return;\n    const { scrollHeight, clientHeight, scrollWidth, clientWidth } = observedElement.value;\n    const isNarrower = direction === \"bottom\" || direction === \"top\" ? scrollHeight <= clientHeight : scrollWidth <= clientWidth;\n    if (state.arrivedState[direction] || isNarrower) {\n      if (!promise.value) {\n        promise.value = Promise.all([\n          onLoadMore(state),\n          new Promise((resolve) => setTimeout(resolve, interval))\n        ]).finally(() => {\n          promise.value = null;\n          nextTick(() => checkAndLoad());\n        });\n      }\n    }\n  }\n  const stop = watch(\n    () => [state.arrivedState[direction], isElementVisible.value],\n    checkAndLoad,\n    { immediate: true }\n  );\n  tryOnUnmounted(stop);\n  return {\n    isLoading,\n    reset() {\n      nextTick(() => checkAndLoad());\n    }\n  };\n}\n\nconst vInfiniteScroll = {\n  mounted(el, binding) {\n    if (typeof binding.value === \"function\")\n      useInfiniteScroll(el, binding.value);\n    else\n      useInfiniteScroll(el, ...binding.value);\n  }\n};\n\nconst vIntersectionObserver = {\n  mounted(el, binding) {\n    if (typeof binding.value === \"function\")\n      useIntersectionObserver(el, binding.value);\n    else\n      useIntersectionObserver(el, ...binding.value);\n  }\n};\n\nconst UseMouse = /* @__PURE__ */ defineComponent({\n  name: \"UseMouse\",\n  props: [\"touch\", \"resetOnTouchEnds\", \"initialValue\"],\n  setup(props, { slots }) {\n    const data = reactive(useMouse$1(props));\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseMouseInElement = /* @__PURE__ */ defineComponent({\n  name: \"UseMouseElement\",\n  props: [\"handleOutside\", \"as\"],\n  setup(props, { slots }) {\n    const target = shallowRef();\n    const data = reactive(useMouseInElement$1(target, props));\n    return () => {\n      if (slots.default)\n        return h(props.as || \"div\", { ref: target }, slots.default(data));\n    };\n  }\n});\n\nconst UseMouseBuiltinExtractors = {\n  page: (event) => [event.pageX, event.pageY],\n  client: (event) => [event.clientX, event.clientY],\n  screen: (event) => [event.screenX, event.screenY],\n  movement: (event) => event instanceof MouseEvent ? [event.movementX, event.movementY] : null\n};\nfunction useMouse(options = {}) {\n  const {\n    type = \"page\",\n    touch = true,\n    resetOnTouchEnds = false,\n    initialValue = { x: 0, y: 0 },\n    window = defaultWindow,\n    target = window,\n    scroll = true,\n    eventFilter\n  } = options;\n  let _prevMouseEvent = null;\n  let _prevScrollX = 0;\n  let _prevScrollY = 0;\n  const x = shallowRef(initialValue.x);\n  const y = shallowRef(initialValue.y);\n  const sourceType = shallowRef(null);\n  const extractor = typeof type === \"function\" ? type : UseMouseBuiltinExtractors[type];\n  const mouseHandler = (event) => {\n    const result = extractor(event);\n    _prevMouseEvent = event;\n    if (result) {\n      [x.value, y.value] = result;\n      sourceType.value = \"mouse\";\n    }\n    if (window) {\n      _prevScrollX = window.scrollX;\n      _prevScrollY = window.scrollY;\n    }\n  };\n  const touchHandler = (event) => {\n    if (event.touches.length > 0) {\n      const result = extractor(event.touches[0]);\n      if (result) {\n        [x.value, y.value] = result;\n        sourceType.value = \"touch\";\n      }\n    }\n  };\n  const scrollHandler = () => {\n    if (!_prevMouseEvent || !window)\n      return;\n    const pos = extractor(_prevMouseEvent);\n    if (_prevMouseEvent instanceof MouseEvent && pos) {\n      x.value = pos[0] + window.scrollX - _prevScrollX;\n      y.value = pos[1] + window.scrollY - _prevScrollY;\n    }\n  };\n  const reset = () => {\n    x.value = initialValue.x;\n    y.value = initialValue.y;\n  };\n  const mouseHandlerWrapper = eventFilter ? (event) => eventFilter(() => mouseHandler(event), {}) : (event) => mouseHandler(event);\n  const touchHandlerWrapper = eventFilter ? (event) => eventFilter(() => touchHandler(event), {}) : (event) => touchHandler(event);\n  const scrollHandlerWrapper = eventFilter ? () => eventFilter(() => scrollHandler(), {}) : () => scrollHandler();\n  if (target) {\n    const listenerOptions = { passive: true };\n    useEventListener(target, [\"mousemove\", \"dragover\"], mouseHandlerWrapper, listenerOptions);\n    if (touch && type !== \"movement\") {\n      useEventListener(target, [\"touchstart\", \"touchmove\"], touchHandlerWrapper, listenerOptions);\n      if (resetOnTouchEnds)\n        useEventListener(target, \"touchend\", reset, listenerOptions);\n    }\n    if (scroll && type === \"page\")\n      useEventListener(window, \"scroll\", scrollHandlerWrapper, listenerOptions);\n  }\n  return {\n    x,\n    y,\n    sourceType\n  };\n}\n\nfunction useMouseInElement(target, options = {}) {\n  const {\n    windowResize = true,\n    windowScroll = true,\n    handleOutside = true,\n    window = defaultWindow\n  } = options;\n  const type = options.type || \"page\";\n  const { x, y, sourceType } = useMouse(options);\n  const targetRef = shallowRef(target != null ? target : window == null ? void 0 : window.document.body);\n  const elementX = shallowRef(0);\n  const elementY = shallowRef(0);\n  const elementPositionX = shallowRef(0);\n  const elementPositionY = shallowRef(0);\n  const elementHeight = shallowRef(0);\n  const elementWidth = shallowRef(0);\n  const isOutside = shallowRef(true);\n  function update() {\n    if (!window)\n      return;\n    const el = unrefElement(targetRef);\n    if (!el || !(el instanceof Element))\n      return;\n    const {\n      left,\n      top,\n      width,\n      height\n    } = el.getBoundingClientRect();\n    elementPositionX.value = left + (type === \"page\" ? window.pageXOffset : 0);\n    elementPositionY.value = top + (type === \"page\" ? window.pageYOffset : 0);\n    elementHeight.value = height;\n    elementWidth.value = width;\n    const elX = x.value - elementPositionX.value;\n    const elY = y.value - elementPositionY.value;\n    isOutside.value = width === 0 || height === 0 || elX < 0 || elY < 0 || elX > width || elY > height;\n    if (handleOutside || !isOutside.value) {\n      elementX.value = elX;\n      elementY.value = elY;\n    }\n  }\n  const stopFnList = [];\n  function stop() {\n    stopFnList.forEach((fn) => fn());\n    stopFnList.length = 0;\n  }\n  tryOnMounted(() => {\n    update();\n  });\n  if (window) {\n    const {\n      stop: stopResizeObserver\n    } = useResizeObserver(targetRef, update);\n    const {\n      stop: stopMutationObserver\n    } = useMutationObserver(targetRef, update, {\n      attributeFilter: [\"style\", \"class\"]\n    });\n    const stopWatch = watch(\n      [targetRef, x, y],\n      update\n    );\n    stopFnList.push(\n      stopResizeObserver,\n      stopMutationObserver,\n      stopWatch\n    );\n    useEventListener(\n      document,\n      \"mouseleave\",\n      () => isOutside.value = true,\n      { passive: true }\n    );\n    if (windowScroll) {\n      stopFnList.push(\n        useEventListener(\"scroll\", update, { capture: true, passive: true })\n      );\n    }\n    if (windowResize) {\n      stopFnList.push(\n        useEventListener(\"resize\", update, { passive: true })\n      );\n    }\n  }\n  return {\n    x,\n    y,\n    sourceType,\n    elementX,\n    elementY,\n    elementPositionX,\n    elementPositionY,\n    elementHeight,\n    elementWidth,\n    isOutside,\n    stop\n  };\n}\n\nconst vMouseInElement = {\n  mounted(el, binding) {\n    const [handler, options] = typeof binding.value === \"function\" ? [binding.value, {}] : binding.value;\n    const state = reactiveOmit(reactive(useMouseInElement(el, options)), \"stop\");\n    watch(state, (val) => handler(val));\n  }\n};\n\nconst UseMousePressed = /* @__PURE__ */ defineComponent({\n  name: \"UseMousePressed\",\n  props: [\"touch\", \"initialValue\", \"as\"],\n  setup(props, { slots }) {\n    const target = shallowRef();\n    const data = reactive(useMousePressed({ ...props, target }));\n    return () => {\n      if (slots.default)\n        return h(props.as || \"div\", { ref: target }, slots.default(data));\n    };\n  }\n});\n\nconst UseNetwork = /* @__PURE__ */ defineComponent({\n  name: \"UseNetwork\",\n  setup(props, { slots }) {\n    const data = reactive(useNetwork());\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseNow = /* @__PURE__ */ defineComponent({\n  name: \"UseNow\",\n  props: [\"interval\"],\n  setup(props, { slots }) {\n    const data = reactive(useNow({ ...props, controls: true }));\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseObjectUrl = /* @__PURE__ */ defineComponent({\n  name: \"UseObjectUrl\",\n  props: [\n    \"object\"\n  ],\n  setup(props, { slots }) {\n    const object = toRef(props, \"object\");\n    const url = useObjectUrl(object);\n    return () => {\n      if (slots.default && url.value)\n        return slots.default(url);\n    };\n  }\n});\n\nconst UseOffsetPagination = /* @__PURE__ */ defineComponent({\n  name: \"UseOffsetPagination\",\n  props: [\n    \"total\",\n    \"page\",\n    \"pageSize\",\n    \"onPageChange\",\n    \"onPageSizeChange\",\n    \"onPageCountChange\"\n  ],\n  emits: [\n    \"page-change\",\n    \"page-size-change\",\n    \"page-count-change\"\n  ],\n  setup(props, { slots, emit }) {\n    const data = reactive(useOffsetPagination({\n      ...props,\n      onPageChange(...args) {\n        var _a;\n        (_a = props.onPageChange) == null ? void 0 : _a.call(props, ...args);\n        emit(\"page-change\", ...args);\n      },\n      onPageSizeChange(...args) {\n        var _a;\n        (_a = props.onPageSizeChange) == null ? void 0 : _a.call(props, ...args);\n        emit(\"page-size-change\", ...args);\n      },\n      onPageCountChange(...args) {\n        var _a;\n        (_a = props.onPageCountChange) == null ? void 0 : _a.call(props, ...args);\n        emit(\"page-count-change\", ...args);\n      }\n    }));\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseOnline = /* @__PURE__ */ defineComponent({\n  name: \"UseOnline\",\n  setup(props, { slots }) {\n    const data = reactive({\n      isOnline: useOnline()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UsePageLeave = /* @__PURE__ */ defineComponent({\n  name: \"UsePageLeave\",\n  setup(props, { slots }) {\n    const data = reactive({\n      isLeft: usePageLeave()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UsePointer = /* @__PURE__ */ defineComponent({\n  name: \"UsePointer\",\n  props: [\n    \"pointerTypes\",\n    \"initialValue\",\n    \"target\"\n  ],\n  setup(props, { slots }) {\n    const el = shallowRef(null);\n    const data = reactive(usePointer({\n      ...props,\n      target: props.target === \"self\" ? el : defaultWindow\n    }));\n    return () => {\n      if (slots.default)\n        return slots.default(data, { ref: el });\n    };\n  }\n});\n\nconst UsePointerLock = /*@__PURE__*/ defineComponent({\n  name: \"UsePointerLock\",\n  props: [\"as\"],\n  setup(props, { slots }) {\n    const target = shallowRef();\n    const data = reactive(usePointerLock(target));\n    return () => {\n      if (slots.default)\n        return h(props.as || \"div\", { ref: target }, slots.default(data));\n    };\n  }\n});\n\nconst UsePreferredColorScheme = /* @__PURE__ */ defineComponent({\n  name: \"UsePreferredColorScheme\",\n  setup(props, { slots }) {\n    const data = reactive({\n      colorScheme: usePreferredColorScheme()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UsePreferredContrast = /* @__PURE__ */ defineComponent({\n  name: \"UsePreferredContrast\",\n  setup(props, { slots }) {\n    const data = reactive({\n      contrast: usePreferredContrast()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UsePreferredDark = /* @__PURE__ */ defineComponent({\n  name: \"UsePreferredDark\",\n  setup(props, { slots }) {\n    const data = reactive({\n      prefersDark: usePreferredDark$1()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UsePreferredLanguages = /* @__PURE__ */ defineComponent({\n  name: \"UsePreferredLanguages\",\n  setup(props, { slots }) {\n    const data = reactive({\n      languages: usePreferredLanguages()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UsePreferredReducedMotion = /* @__PURE__ */ defineComponent({\n  name: \"UsePreferredReducedMotion\",\n  setup(props, { slots }) {\n    const data = reactive({\n      motion: usePreferredReducedMotion()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UsePreferredReducedTransparency = /* @__PURE__ */ defineComponent({\n  name: \"UsePreferredReducedTransparency\",\n  setup(props, { slots }) {\n    const data = reactive({\n      transparency: usePreferredReducedTransparency()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst vResizeObserver = {\n  mounted(el, binding) {\n    if (typeof binding.value === \"function\")\n      useResizeObserver(el, binding.value);\n    else\n      useResizeObserver(el, ...binding.value);\n  }\n};\n\nfunction useCssVar(prop, target, options = {}) {\n  const { window = defaultWindow, initialValue, observe = false } = options;\n  const variable = shallowRef(initialValue);\n  const elRef = computed(() => {\n    var _a;\n    return unrefElement(target) || ((_a = window == null ? void 0 : window.document) == null ? void 0 : _a.documentElement);\n  });\n  function updateCssVar() {\n    var _a;\n    const key = toValue(prop);\n    const el = toValue(elRef);\n    if (el && window && key) {\n      const value = (_a = window.getComputedStyle(el).getPropertyValue(key)) == null ? void 0 : _a.trim();\n      variable.value = value || variable.value || initialValue;\n    }\n  }\n  if (observe) {\n    useMutationObserver(elRef, updateCssVar, {\n      attributeFilter: [\"style\", \"class\"],\n      window\n    });\n  }\n  watch(\n    [elRef, () => toValue(prop)],\n    (_, old) => {\n      if (old[0] && old[1])\n        old[0].style.removeProperty(old[1]);\n      updateCssVar();\n    },\n    { immediate: true }\n  );\n  watch(\n    [variable, elRef],\n    ([val, el]) => {\n      const raw_prop = toValue(prop);\n      if ((el == null ? void 0 : el.style) && raw_prop) {\n        if (val == null)\n          el.style.removeProperty(raw_prop);\n        else\n          el.style.setProperty(raw_prop, val);\n      }\n    },\n    { immediate: true }\n  );\n  return variable;\n}\n\nconst topVarName = \"--vueuse-safe-area-top\";\nconst rightVarName = \"--vueuse-safe-area-right\";\nconst bottomVarName = \"--vueuse-safe-area-bottom\";\nconst leftVarName = \"--vueuse-safe-area-left\";\nfunction useScreenSafeArea() {\n  const top = shallowRef(\"\");\n  const right = shallowRef(\"\");\n  const bottom = shallowRef(\"\");\n  const left = shallowRef(\"\");\n  if (isClient) {\n    const topCssVar = useCssVar(topVarName);\n    const rightCssVar = useCssVar(rightVarName);\n    const bottomCssVar = useCssVar(bottomVarName);\n    const leftCssVar = useCssVar(leftVarName);\n    topCssVar.value = \"env(safe-area-inset-top, 0px)\";\n    rightCssVar.value = \"env(safe-area-inset-right, 0px)\";\n    bottomCssVar.value = \"env(safe-area-inset-bottom, 0px)\";\n    leftCssVar.value = \"env(safe-area-inset-left, 0px)\";\n    tryOnMounted(update);\n    useEventListener(\"resize\", useDebounceFn(update), { passive: true });\n  }\n  function update() {\n    top.value = getValue(topVarName);\n    right.value = getValue(rightVarName);\n    bottom.value = getValue(bottomVarName);\n    left.value = getValue(leftVarName);\n  }\n  return {\n    top,\n    right,\n    bottom,\n    left,\n    update\n  };\n}\nfunction getValue(position) {\n  return getComputedStyle(document.documentElement).getPropertyValue(position);\n}\n\nconst UseScreenSafeArea = /* @__PURE__ */ defineComponent({\n  name: \"UseScreenSafeArea\",\n  props: {\n    top: Boolean,\n    right: Boolean,\n    bottom: Boolean,\n    left: Boolean\n  },\n  setup(props, { slots }) {\n    const {\n      top,\n      right,\n      bottom,\n      left\n    } = useScreenSafeArea();\n    return () => {\n      if (slots.default) {\n        return h(\"div\", {\n          style: {\n            paddingTop: props.top ? top.value : \"\",\n            paddingRight: props.right ? right.value : \"\",\n            paddingBottom: props.bottom ? bottom.value : \"\",\n            paddingLeft: props.left ? left.value : \"\",\n            boxSizing: \"border-box\",\n            maxHeight: \"100vh\",\n            maxWidth: \"100vw\",\n            overflow: \"auto\"\n          }\n        }, slots.default());\n      }\n    };\n  }\n});\n\nconst vScroll = {\n  mounted(el, binding) {\n    if (typeof binding.value === \"function\") {\n      const handler = binding.value;\n      const state = useScroll(el, {\n        onScroll() {\n          handler(state);\n        },\n        onStop() {\n          handler(state);\n        }\n      });\n    } else {\n      const [handler, options] = binding.value;\n      const state = useScroll(el, {\n        ...options,\n        onScroll(e) {\n          var _a;\n          (_a = options.onScroll) == null ? void 0 : _a.call(options, e);\n          handler(state);\n        },\n        onStop(e) {\n          var _a;\n          (_a = options.onStop) == null ? void 0 : _a.call(options, e);\n          handler(state);\n        }\n      });\n    }\n  }\n};\n\nfunction checkOverflowScroll(ele) {\n  const style = window.getComputedStyle(ele);\n  if (style.overflowX === \"scroll\" || style.overflowY === \"scroll\" || style.overflowX === \"auto\" && ele.clientWidth < ele.scrollWidth || style.overflowY === \"auto\" && ele.clientHeight < ele.scrollHeight) {\n    return true;\n  } else {\n    const parent = ele.parentNode;\n    if (!parent || parent.tagName === \"BODY\")\n      return false;\n    return checkOverflowScroll(parent);\n  }\n}\nfunction preventDefault(rawEvent) {\n  const e = rawEvent || window.event;\n  const _target = e.target;\n  if (checkOverflowScroll(_target))\n    return false;\n  if (e.touches.length > 1)\n    return true;\n  if (e.preventDefault)\n    e.preventDefault();\n  return false;\n}\nconst elInitialOverflow = /* @__PURE__ */ new WeakMap();\nfunction useScrollLock(element, initialState = false) {\n  const isLocked = shallowRef(initialState);\n  let stopTouchMoveListener = null;\n  let initialOverflow = \"\";\n  watch(toRef(element), (el) => {\n    const target = resolveElement(toValue(el));\n    if (target) {\n      const ele = target;\n      if (!elInitialOverflow.get(ele))\n        elInitialOverflow.set(ele, ele.style.overflow);\n      if (ele.style.overflow !== \"hidden\")\n        initialOverflow = ele.style.overflow;\n      if (ele.style.overflow === \"hidden\")\n        return isLocked.value = true;\n      if (isLocked.value)\n        return ele.style.overflow = \"hidden\";\n    }\n  }, {\n    immediate: true\n  });\n  const lock = () => {\n    const el = resolveElement(toValue(element));\n    if (!el || isLocked.value)\n      return;\n    if (isIOS) {\n      stopTouchMoveListener = useEventListener(\n        el,\n        \"touchmove\",\n        (e) => {\n          preventDefault(e);\n        },\n        { passive: false }\n      );\n    }\n    el.style.overflow = \"hidden\";\n    isLocked.value = true;\n  };\n  const unlock = () => {\n    const el = resolveElement(toValue(element));\n    if (!el || !isLocked.value)\n      return;\n    if (isIOS)\n      stopTouchMoveListener == null ? void 0 : stopTouchMoveListener();\n    el.style.overflow = initialOverflow;\n    elInitialOverflow.delete(el);\n    isLocked.value = false;\n  };\n  tryOnScopeDispose(unlock);\n  return computed({\n    get() {\n      return isLocked.value;\n    },\n    set(v) {\n      if (v)\n        lock();\n      else unlock();\n    }\n  });\n}\n\nfunction onScrollLock() {\n  let isMounted = false;\n  const state = shallowRef(false);\n  return (el, binding) => {\n    state.value = binding.value;\n    if (isMounted)\n      return;\n    isMounted = true;\n    const isLocked = useScrollLock(el, binding.value);\n    watch(state, (v) => isLocked.value = v);\n  };\n}\nconst vScrollLock = onScrollLock();\n\nconst UseTimeAgo = /* @__PURE__ */ defineComponent({\n  name: \"UseTimeAgo\",\n  props: [\"time\", \"updateInterval\", \"max\", \"fullDateFormatter\", \"messages\", \"showSecond\"],\n  setup(props, { slots }) {\n    const data = reactive(useTimeAgo(() => props.time, { ...props, controls: true }));\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseTimestamp = /* @__PURE__ */ defineComponent({\n  name: \"UseTimestamp\",\n  props: [\"immediate\", \"interval\", \"offset\"],\n  setup(props, { slots }) {\n    const data = reactive(useTimestamp({ ...props, controls: true }));\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseVirtualList = /* @__PURE__ */ defineComponent({\n  name: \"UseVirtualList\",\n  props: [\n    \"list\",\n    \"options\",\n    \"height\"\n  ],\n  setup(props, { slots, expose }) {\n    const { list: listRef } = toRefs(props);\n    const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(listRef, props.options);\n    expose({ scrollTo });\n    if (containerProps.style && typeof containerProps.style === \"object\" && !Array.isArray(containerProps.style))\n      containerProps.style.height = props.height || \"300px\";\n    return () => h(\"div\", { ...containerProps }, [\n      h(\"div\", { ...wrapperProps.value }, list.value.map((item) => h(\"div\", { style: { overflow: \"hidden\", height: item.height } }, slots.default ? slots.default(item) : \"Please set content!\")))\n    ]);\n  }\n});\n\nconst UseWindowFocus = /* @__PURE__ */ defineComponent({\n  name: \"UseWindowFocus\",\n  setup(props, { slots }) {\n    const data = reactive({\n      focused: useWindowFocus()\n    });\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nconst UseWindowSize = /* @__PURE__ */ defineComponent({\n  name: \"UseWindowSize\",\n  props: [\"initialWidth\", \"initialHeight\"],\n  setup(props, { slots }) {\n    const data = reactive(useWindowSize(props));\n    return () => {\n      if (slots.default)\n        return slots.default(data);\n    };\n  }\n});\n\nexport { OnClickOutside, OnLongPress, UseActiveElement, UseBattery, UseBrowserLocation, UseClipboard, UseColorMode, UseDark, UseDeviceMotion, UseDeviceOrientation, UseDevicePixelRatio, UseDevicesList, UseDocumentVisibility, UseDraggable, UseElementBounding, UseElementSize, UseElementVisibility, UseEyeDropper, UseFullscreen, UseGeolocation, UseIdle, UseImage, UseMouse, UseMouseInElement, UseMousePressed, UseNetwork, UseNow, UseObjectUrl, UseOffsetPagination, UseOnline, UsePageLeave, UsePointer, UsePointerLock, UsePreferredColorScheme, UsePreferredContrast, UsePreferredDark, UsePreferredLanguages, UsePreferredReducedMotion, UsePreferredReducedTransparency, UseScreenSafeArea, UseTimeAgo, UseTimestamp, UseVirtualList, UseWindowFocus, UseWindowSize, vOnClickOutside as VOnClickOutside, vOnLongPress as VOnLongPress, vElementBounding, vElementHover, vElementSize, vElementVisibility, vInfiniteScroll, vIntersectionObserver, vMouseInElement, vOnClickOutside, vOnKeyStroke, vOnLongPress, vResizeObserver, vScroll, vScrollLock };\n","<script>\nimport { computed, defineAsyncComponent, nextTick, ref, useTemplateRef, watch } from 'vue';\nimport { vOnClickOutside } from '@vueuse/components';\nimport { capitalizeString, debounce } from '@/utils/utils.js';\n\nimport BaseInput from '@/components/BaseInput/BaseInput.vue';\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport { useId } from '@/composables/useId.js';\nimport { useExtractAttrs } from '@/composables/useExtractAttrs.js';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\n\n/**\n * Form Input Field Component for Date, Date - Date, Date - Time, or Time - Time\n *\n * for date also a format switch between date | year is available\n */\n\nexport default {\n  name: 'BaseDateInput',\n  components: {\n    BaseInput,\n    BaseIcon,\n    BaseSwitchButton: defineAsyncComponent(() => import('@/components/BaseSwitchButton/BaseSwitchButton.vue')),\n    // we need to import date picker async to avoid SSR problems\n    DatePicker: defineAsyncComponent(() => import('vue-datepicker-next')),\n  },\n  directives: {\n    ClickOutside: vOnClickOutside,\n  },\n  inheritAttrs: false,\n  props: {\n    /**\n     * select date or datetime or a range\n     */\n    dateType: {\n      type: String,\n      default: 'single',\n      validator(val) {\n        return ['daterange', 'datetime', 'single', 'timerange'].includes(val);\n      },\n    },\n    /**\n     * input field settable from outside.\n     *   attention: if this is an object it needs to contain all the\n     *   properties (e.g. date_from, time_to) already otherwise only\n     *   a string will be returned\n     */\n    modelValue: {\n      type: [Object, String, Date],\n      required: true,\n    },\n    /** label for input field, required for usability purposes, handle\n     * showing of label with property showLabel\n     */\n    label: {\n      type: String,\n      required: true,\n    },\n    /**\n     * defines if input label should be visible\n     */\n    showLabel: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * set a placeholder for the input field (object with date and time attribute respectively)\n     */\n    placeholder: {\n      type: [Object, String],\n      default: () => ({ date: 'Select Date', time: 'Select Time' }),\n    },\n    /**\n     * define the range separator\n     */\n    rangeSeparator: {\n      type: String,\n      default: '–',\n    },\n    /**\n     * specify date format.\n     *\n     *  **date_year**: display tabs that allow for toggle between only choosing year\n     *   or complete date\n     *  **date_month_year**: display tabs that allow for toggle between choosing only year,\n     *   year and month or complete date\n     */\n    format: {\n      type: String,\n      default: 'day',\n      validator(val) {\n        return ['day', 'month', 'year', 'date_year', 'date_month_year'].includes(val);\n      },\n    },\n    /**\n     * specify labels displayed instead of 'DD.MM.YYYY' and 'YYYY'\n     *   should have the form `{ date: 'xxx', month: 'zzz', year: 'yyy' }`\n     */\n    dateFormatLabels: {\n      type: Object,\n      default: () => ({ date: 'DD.MM.YYYY', month: 'MM.YYYY', year: 'YYYY' }),\n      validator(val) {\n        const labelKeys = Object.keys(val);\n        return labelKeys.includes('date') && labelKeys.includes('year');\n      },\n    },\n    /**\n     * a legend for the date format switch buttons\n     */\n    formatTabsLegend: {\n      type: String,\n      default: 'Switch between date formats',\n    },\n    /**\n     * set calendar language (ISO 639-1).\n     * **caveat**: currently only `en`, `de` and `fr` are supported\n     *  @values de, en, fr\n     */\n    language: {\n      type: String,\n      default: 'en',\n      validator: val => ['de', 'en', 'fr'].includes(val),\n    },\n    /**\n     * set id\n     */\n    inputId: {\n      type: [Number, String],\n      default: '',\n    },\n    /**\n     * define if standard form field styling should be\n     * used (otherwise no border, no box shadow)\n     */\n    useFormFieldStyling: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * option to have the border of the input field not displayed\n     */\n    showInputBorder: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * mark as required field (currently only used for aria-required)\n     * this can be a string displayed in all fields or specific for one field\n     * (key same as for modelValue object)\n     */\n    required: {\n      type: [Boolean, Object],\n      default: false,\n    },\n    /**\n     * mark the form field as invalid and ideally also provide an error message\n     * to display below the form field\n     * for an example see [BaseInput](BaseInput)\n     * this can be a string displayed in all fields or specific for one field\n     * (key same as for modelValue object)\n     */\n    invalid: {\n      type: [Boolean, Object],\n      default: false,\n    },\n    /**\n     * set `true` if input field should be disabled\n     * for an example see [BaseInput](BaseInput)\n     * this can be a string displayed in all fields or specific for one field\n     * (key same as for modelValue object)\n     */\n    disabled: {\n      type: [Boolean, Object],\n      default: false,\n    },\n    /**\n     * add an error message to be displayed below form field if field is invalid\n     * for an example see [BaseInput](BaseInput)\n     * this can be a string displayed in all fields or specific for one field\n     * (key same as for modelValue object)\n     */\n    errorMessage: {\n      type: [String, Object],\n      default: '',\n    },\n    /**\n     * define if error icon should be shown\n     * for an example see [BaseInput](BaseInput)\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * if `true` a remove icon will be shown allowing to remove\n     * all input at once\n     * for an example see [BaseInput](BaseInput)\n     */\n    clearable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify additional input field styling\n     */\n    inputClass: {\n      type: String,\n      default: '',\n    },\n    /**\n     * use this prop to deactivate automatic setting of focus as soon as input element\n     * becomes active - this might require external handling of focus setting!\n     */\n    setFocusOnActive: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * in order to be able to set input field active state from outside\n     */\n    isActive: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * use this prop to set a delay in ms before calender is displayed\n     */\n    isActiveDelay: {\n      type: Number,\n      default: 0,\n    },\n    /**\n     * specify input field type for the native HTML <input> element\n     * @values text, search\n     */\n    inputType: {\n      type: String,\n      default: 'text',\n      validator: val => ['text', 'search'].includes(val),\n    },\n    /**\n     * provide assistive text for screen readers\n     * **clearInput**: text read for remove input icon if prop `clearable` is set `true`\n     *  this could either be just one string that is used for all fields or an object with\n     *  field specific text\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        clearInput: {\n          date_from: 'Clear input from',\n          date_to: 'Clear input to',\n          time_from: 'Clear input from',\n          time_to: 'Clear input to',\n          date: 'clear date',\n          time: 'clear time',\n        },\n      }),\n    },\n  },\n  emits: ['click-input-field', 'update:model-value', 'clicked-outside', 'value-validated', 'input', 'update:is-active'],\n  setup(props, { emit, slots }) {\n    /** INTERNAL ID */\n    const generatedId = useId();\n    const internalId = computed(() => props.inputId || generatedId);\n\n    /** LOCALIZATION */\n    /**\n     * determine lang object needed for datepicker dynamically, will be filled in mounted\n     * (computed prop does not work reliably)\n     * @type {[null] extends [Ref] ? IfAny<null, Ref<null>, null> : Ref<UnwrapRef<null>, UnwrapRef<null> | null>}\n     */\n    const lang = ref(null);\n    /**\n     * watch the language prop for changes so vue-datepicker can be updated with the relevant\n     * language package\n     */\n    watch(() => props.language, async (newLang) => {\n      // first import the relevant language package\n      await import(`./../../../node_modules/vue-datepicker-next/locale/${newLang}.es.js`);\n      // then update the vue-datepicker lang variable\n      lang.value = newLang;\n    });\n\n    /** ATTRS HANDLING */\n    const { rootAttrs, forwardAttrs } = useExtractAttrs();\n\n    /** INPUT ELEMENT HANDLING */\n    /**\n     * get a reference to the BaseInput component\n     * @type {{ from: Readonly<ShallowRef<null|HTMLElement>>, to: Readonly<ShallowRef<null|HTMLElement>> }}\n     */\n    const baseInput = {\n      from: useTemplateRef('baseInputFromEl'),\n      to: useTemplateRef('baseInputToEl'),\n    }\n    /**\n     * return the native input element found via BaseInput, in case there are two input fields\n     * this variable will always return the first one ('from' field)\n     * @type {ComputedRef<HTMLElement|null>}\n     */\n    const inputElement = computed(() => baseInput.from.value?.inputElement || null);\n\n    /**\n     * return the native input elements found via BaseInput, this variable returns both `from` and\n     * `to` input field in an array\n     * @type {ComputedRef<HTMLElement[]|null[]>}\n     */\n    const inputElements = computed(() => [baseInput.from.value?.inputElement || null, baseInput.to.value?.inputElement || null]);\n\n\n    /** DATE FORMAT */\n    /**\n     * variable for toggling format between date and year for date_year format\n     * @type {string}\n     */\n    const dateFormatInt = ref('');\n\n    /** INPUT HANDLING */\n    /**\n     * internal input representation with all possible values for\n     * date and time\n     * date format YYYY(-MM(-DD)) (storage format)\n     * @typedef {Object} inputInt\n     * @property {string} inputInt.date - attribute a single date or datetime date is stored in\n     * @property {string} inputInt.date_from - storing daterange from\n     * @property {string} inputInt.date_to - storing daterange to\n     * @property {string} inputInt.time - storing the time for datetime type\n     * @property {string} inputInt.time_from - storing timerange from\n     * @property {string} inputInt.time_to - storing timerange to\n     */\n    const inputInt = ref({\n      date: '',\n      date_from: '',\n      date_to: '',\n      time: '',\n      time_from: '',\n      time_to: '',\n    });\n\n    /**\n     * determine if the from field is a time field\n     * @returns {boolean}\n     */\n    const isFromTimeField = computed(() => {\n      return props.dateType === 'timerange';\n    });\n    /**\n     * determine if the to field is a time field\n     * @returns {boolean}\n     */\n    const isToTimeField = computed(() => {\n      return props.dateType === 'datetime' || props.dateType === 'timerange';\n    });\n    /**\n     * check if input is just a single date or an object\n     * @returns {boolean}\n     */\n    const isInputTypeString = computed(() => {\n      return typeof props.modelValue === 'string' || !inputProperties.value.length;\n    });\n    /**\n     * compute the properties of the object provided in input prop\n     * @returns {string[]}\n     */\n    const inputProperties = computed(() => {\n      // if input is object return those keys // else for a single date it\n      // could also be a string - then just return an empty array\n      return typeof props.modelValue === 'object' ? Object.keys(props.modelValue) : [];\n    });\n\n\n    /**\n     * handle input for the 'from' input field\n     */\n    const inputFrom = computed({\n      /**\n       * get back the appropriate inputInt attribute value\n       * @returns {string} - a date in the format DD.MM.YYYY\n       */\n      get() {\n        // if it is a time field just return the time_from value\n        if (isFromTimeField.value) {\n          return inputInt.value.time_from || '';\n        }\n        // else it is a date (either single or date_from) --> convert it into the\n        // correct format for display (DD.MM.YYYY instead of the saved DD-MM-YYY)\n        return parseToDateDisplay(inputInt.value.date || inputInt.value.date_from);\n      },\n      /**\n       * also assign them again accordingly\n       * @param {string} val - the value provided by the input element\n       * @param {string} oldValue - the previous value of inputFrom\n       */\n      set(val, oldValue) {\n        let newDate = val;\n        if (isFromTimeField.value) {\n          inputInt.value.time_from = newDate;\n        } else {\n          newDate = parseToDateStorage(val);\n          if (inputProperties.value.includes('date_from')) {\n            inputInt.value.date_from = newDate;\n          } else {\n            inputInt.value.date = newDate;\n          }\n        }\n        // watching of computed values does not work so emit event for altered inputInt right here\n        // the actual value is not needed here since data were transformed and\n        // original object structure with correct data is retrieved with function getInputData\n        if (newDate !== oldValue) {\n          emitData();\n        }\n      },\n    });\n\n    /**\n     * as above - if there is only a single time field get value from 'time' variable\n     * if it is a range use 'time_to''\n     */\n    const inputTo = computed({\n      /**\n       * get back the appropriate inputInt attribute value\n       * @returns {string}\n       */\n      get() {\n        // check if a to time field exists\n        if (isToTimeField.value) {\n          // return the appropriate attribute value\n          return inputInt.value.time || inputInt.value.time_to || '';\n        }\n        // else return the date_to attribute value\n        return parseToDateDisplay(inputInt.value.date_to);\n      },\n      /**\n       * also assign them again accordingly\n       * @param {string} val - the value provided by the input element\n       * @param {string} oldValue - the previous value of inputTo\n       */\n      set(val, oldValue) {\n        let newValue = val;\n        // check if field is date field\n        if (!isToTimeField.value) {\n          newValue = parseToDateStorage(newValue);\n          // if so, set date_to attribute value and transform value appropriately\n          // TODO: this could be insufficient since currently no validity checks on input string\n          inputInt.value.date_to = newValue;\n          // else check if type is timerange\n        } else if (inputProperties.value.includes('time_from')) {\n          inputInt.value.time_to = newValue;\n          // else assume the type is datetime\n        } else {\n          inputInt.value.time = newValue;\n        }\n        // watching of computed values does not work so emit event for altered inputInt right here\n        // the actual value is not needed here since data were transformed and\n        // original object structure with correct data is retrieved with function getInputData\n        if (newValue !== oldValue) {\n          emitData();\n        }\n      },\n    });\n    /**\n     * data emit function, transforming data before emit event\n     */\n    function emitData() {\n      // get a data object that only contains fields that were also present\n      // in external input\n      const data = getInputData();\n      /**\n       * emit an event when focus leaves the input\n       *\n       * @event selected\n       * @param {string, Object} - the input string or object\n       */\n      emit('update:model-value', data);\n    }\n    /**\n     * if input was just a single string return that otherwise\n     * only return the properties provided by external input\n     * if input is empty set value to empty string instead of null (default vue2-datepicker)\n     * @returns {string | Object}\n     */\n    function getInputData() {\n      if (isInputTypeString.value) {\n        return inputInt.value.date !== null ? inputInt.value.date : '';\n      }\n      const data = {};\n      inputProperties.value.forEach((key) => {\n        data[key] = inputInt.value[key] !== null ? inputInt.value[key] : '';\n      });\n      return data;\n    }\n    // HELPER METHODS\n    /**\n     * transform the date to the correct display format\n     * @param {string} dateString - the date string in YYYY-MM-DD format\n     */\n    function parseToDateDisplay(dateString) {\n      // if no date string was provided just return an empty string\n      if (!dateString) return '';\n      // now check if year is negative\n      const isNegativeYear = isNegativeStorageDate(dateString);\n      // if so, create a positive date string\n      const positiveDateString = isNegativeYear\n        ? removeYearMinusFromStorageDate(dateString) : dateString;\n      // now do the transformation and add the minus to the year again if necessary\n      return addYearMinusToDateDisplay(\n        positiveDateString.split('-').reverse().join('.'),\n        isNegativeYear,\n      );\n    }\n    /**\n     * transform the date to the correct storage format\n     * @param {string} dateString - the date string in DD.MM.YYYY format\n     */\n    function parseToDateStorage(dateString) {\n      return dateString ? dateString.split('.').reverse().join('-') : '';\n    }\n    /**\n     * check for a negative year in the date that is displayed\n     * @param {string} date - date string in the format DD.MM.YYYY\n     * @returns {boolean}\n     */\n    function isNegativeDisplayDate(date) {\n      if (!date) return false;\n      if (dateFormatInt.value === 'MM.YYYY') {\n        return /^\\d{0,2}\\.-\\d{0,4}$/.test(date);\n      }\n      if (dateFormatInt.value === 'YYYY') {\n        return /^-\\d{0,4}$/.test(date);\n      }\n      return /^\\d{0,2}\\.\\d{0,2}\\.-\\d{0,4}$/.test(date);\n    }\n    /**\n     * check if year is negative in the stored date\n     * @param {string} date - a date string in the format YYYY-MM-DD\n     * @param {string} [format=undefined] - in case not the current format (this.dateFormatInt) should\n     *  be used for evaluation provide it with this param\n     * @returns {boolean}\n     */\n    function isNegativeStorageDate(date, format = undefined) {\n      // if there is no date to evaluate just return false\n      if (!date) return false;\n      // either use the format provided as param or the currently set format in dateFormatInt\n      const formatToCheck = format || dateFormatInt.value;\n      if (formatToCheck === 'MM.YYYY') {\n        return /^-\\d{0,4}-\\d{0,2}$/.test(date);\n      }\n      if (formatToCheck === 'YYYY') {\n        return /^-\\d{0,4}$/.test(date);\n      }\n      return /^-\\d{0,4}-\\d{0,2}-\\d{0,2}$/.test(date);\n    }\n    /**\n     * since minus has to be temporarily removed for some actions add it again\n     *  after with this function (for displayed date)\n     * @param {string} date - date in the format DD.MM.YYYY\n     * @param {boolean} [isNegative=true] - optionally do not add minus when calling this\n     *  function\n     * @returns {string}\n     */\n    function addYearMinusToDateDisplay(date, isNegative = true) {\n      if (isNegative) {\n        const [year, month, day] = date.split('.').reverse();\n        return `${day !== undefined ? `${day}.` : ''}${month !== undefined ? `${month}.` : ''}-${year}`;\n      }\n      return date;\n    }\n    /**\n     * since minus has to be temporarily removed for some actions add it again\n     *  after with this function (for stored date)\n     * @param {string} date - date in the format YYYY-MM-DD\n     * @param {boolean} [isNegative=true] - optionally do not add minus when calling this\n     *  function\n     * @returns {string}\n     */\n    function addYearMinusToDateStorage(date, isNegative = true) {\n      if (isNegative) {\n        return `-${date}`;\n      }\n      return date;\n    }\n    /**\n     * remove the minus from the date since some functions (especially Date() ) can\n     *  not cope with negative dates (for displayed date)\n     * @param {string} date - the date string in format DD.MM.YYYY\n     * @returns {string}\n     */\n    function removeYearMinusFromDisplayDate(date) {\n      return isNegativeDisplayDate(date)\n        ? date.replace('-', '') : date;\n    }\n    /**\n     * remove the minus from the date since some functions (especially Date()) can\n     *  not cope with negative dates (for stored date)\n     * @param {string} date - the date string in format YYYY-MM-DD\n     * @param {string} [format=undefined] - in case not the currently selected format should be used\n     *  for date evaluation provide the format with this param\n     * @returns {string}\n     */\n    function removeYearMinusFromStorageDate(date, format = undefined) {\n      return isNegativeStorageDate(date, format)\n        ? date.replace('-', '') : date;\n    }\n\n    /** DATE FORMAT SWITCH */\n    /**\n     * check if format switch tabs should be shown\n     * @returns {boolean}\n     */\n    const isSwitchableFormat = computed(() => {\n      return props.format === 'date_month_year' || props.format === 'date_year';\n    });\n\n    /** LABEL ROW DISPLAY */\n    /**\n     * check if label-addition slot exists is filled\n     */\n    const { slotHasContent: labelRowSlotsHaveData } = useHasSlotContent(slots['label-addition']);\n    /**\n     * determines if label row should be shown\n     * @returns {Boolean|boolean}\n     */\n    const showLabelRow = computed(() => {\n      // show label when prop is set true or a label addition was added via slot\n      return props.showLabel || isSwitchableFormat.value || labelRowSlotsHaveData.value;\n    });\n\n    /** INPUT ACTIVE / PICKER OPEN / CLICK OUTSIDE HANDLING */\n    /**\n     * to steer closing of date/timepicker from and to input field once date/time is selected\n     * (packed into an object to still be able to address it dynamically like so: pickerState[`${origin}Open`]\n     * @type {{fromOpen: Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>, toOpen: Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}}\n     */\n    const pickerState = {\n      fromOpen: ref(false),\n      toOpen: ref(false),\n    }\n    /**\n     * variable to steer if input fade out of from field should be shown\n     * @type {boolean}\n     */\n    /**\n     * variable to keep active state in sync with potential parent prop\n     * (this is needed as independent variable from toOpen and fromOpen for example in\n     * BaseAdvancedSearchRow to keep dropdown open even if datepicker is closed)\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const isActiveInt = ref(false);\n\n    /**\n     * watch for changes in input field active variable to keep in sync with parent\n     * @param {boolean} val - the changed internal is active variable\n     */\n    watch(isActiveInt, (val) => {\n      /**\n       * replace BaseInput state with BaseDateInput field active state and\n       * propagate this one\n       *\n       * @event update:is-active\n       * @param {boolean} - is input field active\n       */\n      emit('update:is-active', val);\n    });\n\n    /**\n     * also adjust internal variable when active state changes from outside\n     * @param {boolean} val - the changed isActive prop\n     */\n    watch(() => props.isActive, (val) => {\n      if (val !== isActiveInt.value) {\n        isActiveInt.value = val;\n        // if is active is set from outside also open the first date field\n        pickerState.fromOpen.value = val;\n      }\n      // if isActive is set false from outside also close date picker\n      if (!val) {\n        pickerState.fromOpen.value = false;\n        pickerState.toOpen.value = false;\n      }\n    }, {\n      immediate: true,\n    });\n\n    const onClickOutsideHandler = [\n      /**\n       * handle click outside event and adjust input active variable accordingly\n       * @param {MouseEvent} event - the event provided by the click outside directive\n       */\n        (event) => {\n        isActiveInt.value = false;\n        /**\n         * emit a custom clicked-outside event instead of BaseInput event (propagation stopped)\n         *\n         * @event clicked-outside\n         * @param {MouseEvent} - the native Event\n         */\n        emit('clicked-outside', event);\n      },\n    ]\n\n    /**\n     * handle click inside the component and adjust input active variable accordingly\n     * @param {MouseEvent} event - event triggered by mouse click\n     */\n    function clickedInside(event) {\n      isActiveInt.value = true;\n      /**\n       * event additionally triggered to BaseInput default click-input-field to also\n       * set field active if component sourroundings are clicked\n       *\n       * @event click-input-field\n       * @param {MouseEvent} - the native Event\n       */\n      emit('click-input-field', event);\n    }\n\n    /**\n     * in general input field active styling is handled via focusin and\n     * clicked-outside, however for special case iOS touch  devices have\n     * up and down arrows that do not trigger any event other than blur and will\n     * cause the dropdowns of input fields to remain open\n     * @param {FocusEvent} event - the native blur event\n     * @param {string} origin - did event emit from 'from' or 'to' date field\n     */\n    function onInputBlur(event, origin) {\n      const relatedTargetInput = event.relatedTarget?.parentElement ? event.relatedTarget.parentElement\n        .getElementsByTagName('input') : null;\n      // so since these arrows only navigate between input fields we check if there is a\n      // related target and if this related target is an input field and if yes we make sure\n      // the id is different from the input id of this component (the one the event originated from)\n      if (event.relatedTarget\n        && ((event.relatedTarget.tagName === 'INPUT'\n            && (!event.relatedTarget?.id || event.relatedTarget.id !== event.target.id))\n          // additionally also set input active false when the BaseInput 'remove' button\n          // (displayed if `clearable` is true) is triggered in the other date field of the range\n          || (event.relatedTarget?.className === 'base-input__remove-icon-wrapper'\n            && relatedTargetInput && relatedTargetInput[0]?.id !== event.target.id))) {\n        // set input active state false\n        pickerState[`${origin}Open`].value = false;\n      }\n    }\n\n    /** STYLE AND FADE OUT CALC ON RESIZE */\n    /**\n     * reference to the root element\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const baseDateInput = useTemplateRef('baseDateInputEl');\n    /**\n     * reference to the label element\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const labelElement = useTemplateRef('labelEl');\n    /**\n     * reference to the possible additions to the label row - switch buttons and `label-addition` slot\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const labelAdditions = useTemplateRef('labelAdditionsEl');\n    /**\n     * reference to the native input elements\n     * @type {{ inputElementFrom: Readonly<ShallowRef<null|HTMLElement>>, inputElementTo: Readonly<ShallowRef<null|HTMLElement>> }}\n     */\n    const nativeInputElements = {\n      inputFromElement: useTemplateRef('inputFromEl'),\n      inputToElement: useTemplateRef('inputToEl'),\n    };\n    /**\n     * reference to the BaseIcon component\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const baseIcon = useTemplateRef('baseIconEl');\n    /**\n     * store icon width in a variable\n     * @type {ComputedRef<number>}\n     */\n    const iconWidth = ref(0);\n    /**\n     * variable to set css class according to label elements wrapping or not\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const wrapLabelRow = ref(false);\n    /**\n     * variable to steer if icons should be shown (becoming false if not enough\n     * space)\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const showIcons = ref(false);\n    /**\n     * variable to steer if input fade out of to field should be shown\n     * @type {boolean}\n     */\n    const fadeOut = {\n      fadeOutFrom: ref(false),\n      fadeOutTo: ref(false),\n    };\n\n    // create an observer with the fade out calc function\n    useElementObserver({\n      type: 'resize',\n      target: baseDateInput,\n      callback: debounce(50, onElementResize),\n    });\n\n    if (props.showLabel && (isSwitchableFormat.value || labelRowSlotsHaveData.value)) {\n      // second observer to trigger label additions width calc as soon as element is rendered\n      useElementObserver({\n        type: 'resize',\n        target: labelAdditions,\n        callback: debounce(50, onLabelAdditionsResize),\n      });\n    }\n    /**\n     * callback function for the resize observer calculating fade out and label\n     * additions width\n     */\n    function onElementResize() {\n      if (props.showLabel && (isSwitchableFormat.value || labelRowSlotsHaveData.value)) {\n        calcLabelAdditionsWidth();\n      }\n      calcFadeOut(['From', 'To']);\n    }\n    /**\n     * callback function for the resize observer calculating label\n     * additions width on label additions render\n     */\n    function onLabelAdditionsResize(entries, observer) {\n      // only do calc when element is filled\n      if (entries[0].contentRect.width > 0) {\n        calcLabelAdditionsWidth();\n        // only do this once as soon as elements are rendered - then disconnect!\n        observer.disconnect();\n      }\n    }\n\n    /**\n     * function to correctly style the date format switch buttons and prevent\n     * overlay with label\n     */\n    function calcLabelAdditionsWidth() {\n      if (baseDateInput.value) {\n        // get the complete element width\n        const observableWidth = baseDateInput.value.clientWidth;\n        // get the label margin\n        const labelMargin = props.showLabel\n          ? Number(getComputedStyle(labelElement.value)['margin-right'].replace('px', '')) : 0;\n        const labelWidth = props.showLabel ? labelElement.value.clientWidth : 0;\n        // calculate the remaining container space after label, label margin and date switch width\n        const spacingLeft = observableWidth\n          - labelWidth\n          - labelMargin\n          - labelAdditions.value.clientWidth;\n        // if no space is left set a class that sets label additions width to 100% so element has to wrap\n        wrapLabelRow.value = spacingLeft < 0;\n      }\n    }\n\n    /**\n     * function to calculate if fade out in the input fields should be shown, needs to be\n     * recalculated after resize or if input changes\n     */\n    async function calcFadeOut(inputFields) {\n      // first we need to determine the iconWidth IF it is shown\n      // only get once since the icon width should not change later on, but wait\n      // until icon is rendered (has a clientWidth)\n      if (!iconWidth.value && baseIcon.value?.$el?.clientWidth) {// get the icon HTML element\n        const iconElement = baseIcon.value.$el;\n        // get the margin that is also part of the icon width in the input field\n        const iconMargin = Number(getComputedStyle(iconElement)['margin-left'].replace('px', ''));\n        // set the icon width as width + margin\n        iconWidth.value = iconElement.clientWidth + iconMargin;\n      }\n      // ICONS\n      // since we want a uniform appearance\n      // across all fields we only do this once with the longest text\n      // for input width etc. we use the 'from' field since it should always be\n      // present\n      // get the 'from' input element\n      const inputElement = nativeInputElements.inputFromElement.value;\n      // make sure the element was found and since icon removal is only considered if there\n      // is input - check if there is actually input (or if this is the initial\n      // state were icons are still hidden per default to avoid a short flash if they dont fit)\n      if (inputElement && (!showIcons.value || inputFrom.value || inputTo.value)) {\n        // but relevant for icon calc is the longest text\n        let maxTextWidth = 0;\n        // check which element has the longer text\n        // create a span\n        const span = document.createElement('span');\n        // hide the span\n        span.setAttribute('class', 'hide');\n        // add the from value to the span\n        span.innerHTML = inputFrom.value;\n        // add the element to the document body\n        baseDateInput.value.appendChild(span);\n        maxTextWidth = span.offsetWidth;\n        // add the to value to the span\n        span.innerHTML = inputTo.value;\n        const toWidth = span.offsetWidth;\n        // update the value if 'to' field text is longer than first determined\n        // 'from'\n        if (toWidth > maxTextWidth) {\n          maxTextWidth = toWidth;\n        }\n        // remove the element again\n        baseDateInput.value.removeChild(span);\n\n        // get inputWidth\n        const inputWidth = inputElement.offsetWidth;\n        // now make the actual comparisons to set the correct showIcons value\n        // if icons are present just check the text against the remaining input width\n        if (showIcons.value && maxTextWidth > inputWidth) {\n          // if not - remove the icons\n          showIcons.value = false;\n          // wait for the DOM to update so the input width is correct in fade out calculations\n          await nextTick();\n          // if icons are not present we need to consider if text would still fit if icons\n          // WERE present - only if yes show icons again\n        } else if (!showIcons.value && maxTextWidth + iconWidth.value <= inputWidth) {\n          showIcons.value = true;\n          // wait for the DOM to update so the input width is correct in fade out calculations\n          await nextTick();\n        }\n      }\n\n\n      // FADE OUT\n      // since fade out is determined for each field individually iterate through the relevant fields\n      inputFields.forEach((field) => {\n        const inputElement = nativeInputElements[`input${field}Element`].value;\n        // check if element exists\n        if (inputElement) {\n          // now get the input field value or the placeholder text\n          // we need to take inputFrom/inputTo here because DOM value is not updated yet\n          // sometimes after validity check\n          const text = (field === 'From' ? inputFrom.value : inputTo.value)\n            || inputElement.getAttribute('placeholder');\n          // now check if any of the two exists\n          if (text) {\n            // create a span\n            const span = document.createElement('span');\n            // hide the span\n            span.setAttribute('class', 'hide');\n            // add the input extracted text to this span\n            span.innerHTML = text;\n            // add the element to the document body\n            baseDateInput.value.appendChild(span);\n            // get the width of that element\n            const textWidth = span.offsetWidth;\n            // remove the element again\n            baseDateInput.value.removeChild(span);\n            // now also get the input width\n            const inputWidth = inputElement.offsetWidth;\n            // and check if the text width fits the input width\n            fadeOut[`fadeOut${field}`].value = textWidth > inputWidth;\n          }\n        }\n      });\n    }\n\n    /** INPUT FIELDS STATE HANDLING */\n    /** INVALID */\n    /** consider if `invalid` prop is string or object and set the value for the 'from' field accordingly\n     * @type {ComputedRef<boolean>}\n     */\n    const invalidFrom = computed(() => typeof props.invalid === 'boolean'\n      ? props.invalid : props.invalid.date_from || props.invalid.time_from || props.invalid.date || false);\n    /** consider if `invalid` prop is string or object and set the value for the 'to' field accordingly\n     * @type {ComputedRef<boolean>}\n     */\n    const invalidTo = computed(() => typeof props.invalid === 'boolean'\n      ? props.invalid : props.invalid.date_to || props.invalid.time_to || props.invalid.time || false);\n\n    /** ERROR MESSAGES */\n    /** consider if `errorMessage` prop is string or object and set the value for the 'from' field accordingly\n     * @type {ComputedRef<string>}\n     */\n    const errorMessageFrom = computed(() => typeof props.errorMessage === 'string'\n      ? props.errorMessage : props.errorMessage.date_from || props.errorMessage.time_from || props.errorMessage.date || '');\n    /** consider if `errorMessage` prop is string or object and set the value for the 'to' field accordingly\n     * @type {ComputedRef<string>}\n     */\n    const errorMessageTo = computed(() => typeof props.errorMessage === 'string'\n      ? props.errorMessage : props.errorMessage.date_to || props.errorMessage.time_to || props.errorMessage.time || '');\n\n    /** REQUIRED */\n    /** consider if `required` prop is string or object and set the value for the 'from' field accordingly\n     * @type {ComputedRef<boolean>}\n     */\n    const requiredFrom = computed(() => typeof props.required === 'boolean'\n      ? props.required : props.required.date_from || props.required.time_from || props.required.date || false);\n    /** consider if `required` prop is string or object and set the value for the 'to' field accordingly\n     * @type {ComputedRef<boolean>}\n     */\n    const requiredTo = computed(() => typeof props.props === 'boolean'\n      ? props.required : props.required.date_to || props.required.time_to || props.required.time || false);\n\n    /** DISABLED */\n    /** consider if `disabled` prop is string or object and set the value for the 'from' field accordingly\n     * @type {ComputedRef<boolean>}\n     */\n    const disabledFrom = computed(() => typeof props.disabled === 'boolean'\n      ? props.disabled : props.disabled.date_from || props.disabled.time_from || props.disabled.date || false);\n    /** consider if `disabled` prop is string or object and set the value for the 'to' field accordingly\n     * @type {ComputedRef<boolean>}\n     */\n    const disabledTo = computed(() => typeof props.props === 'boolean'\n      ? props.disabled : props.disabled.date_to || props.disabled.time_to || props.disabled.time || false);\n\n    return {\n      internalId,\n      lang,\n      rootAttrs,\n      forwardAttrs,\n      inputElement,\n      inputElements,\n      dateFormatInt,\n      inputInt,\n      isFromTimeField,\n      isToTimeField,\n      isInputTypeString,\n      inputProperties,\n      inputFrom,\n      inputTo,\n      emitData,\n      getInputData,\n      parseToDateStorage,\n      parseToDateDisplay,\n      isNegativeDisplayDate,\n      isNegativeStorageDate,\n      addYearMinusToDateDisplay,\n      addYearMinusToDateStorage,\n      removeYearMinusFromDisplayDate,\n      removeYearMinusFromStorageDate,\n      labelRowSlotsHaveData,\n      isSwitchableFormat,\n      showLabelRow,\n      isActiveInt,\n      onClickOutsideHandler,\n      clickedInside,\n      onInputBlur,\n      fromOpen: pickerState.fromOpen,\n      toOpen: pickerState.toOpen,\n      baseDateInput,\n      labelElement,\n      labelAdditions,\n      baseIcon,\n      inputFromElement: nativeInputElements.inputFromElement,\n      inputToElement: nativeInputElements.inputToElement,\n      wrapLabelRow,\n      showIcons,\n      useFadeOutFrom: fadeOut.fadeOutFrom,\n      useFadeOutTo: fadeOut.fadeOutTo,\n      calcFadeOut,\n      // input field state\n      invalidFrom,\n      invalidTo,\n      errorMessageFrom,\n      errorMessageTo,\n      requiredFrom,\n      requiredTo,\n      disabledFrom,\n      disabledTo,\n    };\n  },\n  data() {\n    return {\n      /**\n       * variable to store the date when switching from date to year in order to be\n       * able to restore exact date when switching back\n       * @type {inputInt}\n       */\n      tempDateStore: {},\n      /**\n       * flag set true on mounted to indicate that its ok to render the datepicker\n       * (otherwise SSR or hydration mismatch errors)\n       * @type {boolean}\n       */\n      mounted: false,\n    };\n  },\n  computed: {\n    /**\n     * this is the format we want to store computed based on what\n     * was specified in format and what date toggle tabs (via dateFormatInt) might say\n     * TODO: check if this is still needed with custom input\n     * @returns {string}\n     */\n    datePickerValueFormat() {\n      if (this.format === 'year' || this.dateFormatInt === 'YYYY') {\n        // use single letter for year here to allow negative dates\n        return 'Y';\n      }\n      if (this.format === 'month' || this.dateFormatInt === 'MM.YYYY') {\n        // use single letter for year here to allow negative dates\n        return 'MM.Y';\n      }\n      // use single letter for year here to allow negative dates\n      return 'DD.MM.Y';\n    },\n    /**\n     * if the format is settable this.format is date_year and can not be\n     * used directly for the date picker component\n     * @returns {string}\n     */\n    minDateView() {\n      if (this.isSwitchableFormat && this.dateFormatInt === 'YYYY') {\n        return 'year';\n      }\n      if (this.isSwitchableFormat && this.dateFormatInt === 'MM.YYYY') {\n        return 'month';\n      }\n      if (this.isSwitchableFormat && this.dateFormatInt === 'DD.MM.YYYY') {\n        return 'day';\n      }\n      return this.format;\n    },\n    /**\n     * determine if the initially provided date is a year or a full date\n     * (used to set the correct date display format and date/year switch button)\n     * @returns {boolean}\n     */\n    isDateFormatYear() {\n      return (this.isInputTypeString && this.inputInt.date\n          && /^(-?[0-9]{1,4}|-[0-9]{0,4})$/.test(this.inputInt.date))\n        || (this.inputProperties.some(key => !!key.includes('date')\n          && this.inputInt[key] && /^(-?[0-9]{1,4}|-[0-9]{0,4})$/.test(this.inputInt[key])));\n    },\n    isDateFormatMonth() {\n      return ((this.isInputTypeString && this.inputInt.date\n          && /^(-?[0-9]{1,4}|-[0-9]{0,4})-[0-1]?[0-9]$/.test(this.inputInt.date))\n        || this.inputProperties.some(key => !!key.includes('date')\n          && this.inputInt[key]\n          && /^(-?[0-9]{1,4}|-[0-9]{0,4})-[0-1]?[0-9]$/.test(this.inputInt[key])));\n    },\n    /**\n     * return the format options for date, month, year switches\n     * @returns {[{label: string, value: string}]}\n     */\n    tabSwitchOptions() {\n      // minimal options\n      const options = [\n        { label: this.dateFormatLabels.date, value: 'DD.MM.YYYY' },\n        { label: this.dateFormatLabels.year, value: 'YYYY' },\n      ];\n      // if format can be month as well, add month option\n      if (this.format === 'date_month_year') {\n        options.splice(1, 0, {\n          label: this.dateFormatLabels.month,\n          value: 'MM.YYYY',\n        });\n      }\n      return options;\n    },\n  },\n  watch: {\n    /**\n     * watch if dateInt (in storage format YYYY(MM-(DD)))\n     * changes and inform parent\n     */\n    inputInt: {\n      /**\n       * watch if dateInt (in storage format YYYY(MM-(DD)))\n       * changes and inform parent\n       */\n      handler() {\n        /**\n         * Event emitted on input, passing input string\n         *\n         * @event input\n         * @param {string} - the input event value however\n         * passing only the event.target.value\n         *\n         */\n        this.$emit('input', this.getInputData());\n      },\n      deep: true,\n    },\n    /**\n     * watch format and set correct dateFormat\n     */\n    format: {\n      handler(val) {\n        if (val === 'year') {\n          this.dateFormatInt = 'YYYY';\n          return;\n        }\n        if (val === 'month') {\n          this.dateFormatInt = 'MM.YYYY';\n          return;\n        }\n        this.dateFormatInt = 'DD.MM.YYYY';\n      },\n      immediate: true,\n    },\n    /**\n     * watch input set from outside and set internal inputInt accordingly as well as\n     * set the correct display format\n     */\n    modelValue: {\n      handler(val) {\n        // check if input string is different from inputInt\n        if (JSON.stringify(val) !== JSON.stringify(this.getInputData())) {\n          if (typeof this.modelValue === 'string') {\n            this.inputInt.date = val;\n          } else {\n            this.inputInt = {\n              // keep all inputInt props\n              ...this.inputInt,\n              // and add the ones set by parent\n              ...JSON.parse(JSON.stringify(val)),\n            };\n          }\n          // check if external input was year format and set internal format accordingly\n          if (this.isSwitchableFormat) {\n            if (this.isDateFormatYear) {\n              this.dateFormatInt = 'YYYY';\n            } else if (this.isDateFormatMonth) {\n              this.dateFormatInt = 'MM.YYYY';\n            } else {\n              this.dateFormatInt = 'DD.MM.YYYY';\n            }\n          }\n        }\n      },\n      // to not need to do extra assignment in created()\n      immediate: true,\n    },\n    /**\n     * in order to allow user to restore previous date after switching\n     * from date to year and back store in temp variable (but only if previous date was full date\n     * (check necessary for starting with year where format is switched to 'YYYY'\n     * but no previous full date avaliable))\n     * @param {string} val - the changed dateFormatInt value\n     * @param {string} old - the previous value\n     */\n    dateFormatInt(val, old) {\n      // in order to allow user to restore previous date after switching\n      // from date to year and back store in temp variable if\n      // a) date is not just format 'YYYY' & switch was made from full date\n      if (!this.isDateFormatYear && old === 'DD.MM.YYYY') {\n        this.tempDateStore = { ...this.inputInt };\n        // b) tab switch was made from month to year\n      } else if (!this.isDateFormatYear\n        && (val === 'YYYY' && old === 'MM.YYYY')) {\n        // if there is no previous stored date just store everything\n        if (!this.tempDateStore) {\n          this.tempDateStore = { ...this.inputInt };\n          // if there was a previous stored date check for every date prop in inputInt\n          // if stored date should be overwritten\n        } else {\n          Object.keys(this.inputInt).filter(key => !!key.includes('date'))\n            .forEach((dateKey) => {\n              // date should be overwritten if month or year are different from\n              // the already stored date\n              if (!this.monthAndYearIdent(\n                  // check if the positive dates are identical\n                  this.removeYearMinusFromStorageDate(this.inputInt[dateKey], old),\n                  (/^-/.test(this.tempDateStore[dateKey]) ? this.tempDateStore[dateKey].replace('-', '') : this.tempDateStore[dateKey]),\n                  // and also check if the operator in front of year is identical\n                ) && this.isNegativeStorageDate(this.inputInt[dateKey], old)\n                === /^-/.test(this.tempDateStore[dateKey])) {\n                this.tempDateStore[dateKey] = this.inputInt[dateKey];\n              }\n            });\n        }\n      }\n      this.convertDate(old);\n      // since inputInt is manipulated directly in this case (easier with Date conversions)\n      // inputFrom and inputTo setters are not triggered and we need to emit the new data manually\n      this.emitData();\n    },\n  },\n  async mounted() {\n    // in order to avoid SSR and hydration problems only render the datepicker when component is mounted\n    // first import the relevant language package\n    await import(`./../../../node_modules/vue-datepicker-next/locale/${this.language}.es.js`);\n    // then set mounted flag which will serve as the notification to render\n    this.mounted = true;\n  },\n  updated() {\n    // this hack is necessary because otherwise keyboard navigation was impaired by the datepicker\n    // pop up elements\n    // check if datepicker element is actually open\n    if (this.fromOpen || this.toOpen) {\n      // wait until elements are rendered\n      this.$nextTick(() => {\n        // get all focusable elements that have the 'mx-' in the class name\n        // had to add 'div's as well because of some strange effect in Firefox\n        const keyboardfocusableElements = [...this.$el.querySelectorAll(\n          'div, a, button, input, textarea, select, details, [tabindex]:not([tabindex=\"-1\"])',\n        )]\n          .filter(el => !el.hasAttribute('disabled'))\n          .filter(el => el.className.includes('mx-'));\n        // iterate through the elements and add tabindex -1\n        keyboardfocusableElements.forEach((element) => {\n          element.setAttribute('tabindex', -1);\n        });\n      });\n    }\n  },\n  methods: {\n    /**\n     * since the complete datepicker lies within the BaseInput, the BaseInput click event\n     *  is triggered also when a date is picked from the date picker - this leads to the undesired\n     *  side effect that the date picker pop up is reopened when a date was selected there\n     *  therefore we only allow the click event to pass on when the user clicks on the input field\n     *  DIRECTLY\n     * @param {PointerEvent} event - the native click event\n     */\n    onInputClick(event) {\n      if (event.target.tagName !== 'INPUT') {\n        event.stopPropagation();\n      }\n    },\n    /**\n     * checks done on keydown events\n     * a) tab key needs separate handling and only needs to set input field close when\n     * there is no clearable button (or shift key was used for going to previous field)\n     * b) prevent user from entering chars other than number or period (date) or colon (time)\n     * and not more characters than the date format requires\n     * @param {KeyboardEvent} event - the keydown event\n     * @param {string} origin - is event coming from 'from' or 'to' field in title case\n     */\n    handleInputKeydown(event, origin) {\n      let currentInputString = event.target.value;\n      // get the key triggering the event\n      const { key } = event;\n      // now check for the specific input key to preventDefault and prevent unwanted\n      // characters\n      // create boolean to determine if it is a time field (otherwise date is assumed)\n      const isTimeField = this.isTimeInputField(origin);\n      // if time ':' is allowed in input regex - otherwise '.'\n      const allowedFieldKey = isTimeField ? ':' : '\\\\.';\n      // check if '-' should be an allowed key\n      let allowMinus = false;\n      if ((this.dateFormatInt === 'DD.MM.YYYY' && /^\\d{2}\\.\\d{2}\\.\\d{0,4}$/.test(currentInputString))\n        || (this.dateFormatInt === 'MM.YYYY' && /^\\d{2}\\.\\d{0,4}$/.test(currentInputString))\n        || (this.dateFormatInt === 'YYYY' && /^\\d{0,4}$/.test(currentInputString))) {\n        allowMinus = true;\n      }\n      // create regex for allowed keys\n      const allowedKeysRegex = new RegExp(`([0-9${allowMinus ? '-' : ''}]|${allowedFieldKey}|Backspace|Delete|Tab|Enter|ArrowRight|ArrowLeft)`);\n      // create regex that should not be allowed if max length is reached\n      const disallowedKeysOnLengthRegex = new RegExp(`([0-9]|${allowedFieldKey})`);\n      // get the max length for the respective format (for time: 'HH:mm' = 5)\n      // also check for a minus\n      let formatLength = isTimeField ? 5 : this.dateFormatInt.length;\n      if (!isTimeField && this.isNegativeDisplayDate(currentInputString)) {\n        // add one extra to formatLength for the '-' if date is negative\n        formatLength += 1;\n      }\n      // check if\n      // * key was not any of the allowed keys\n      // * or was an allowed key but the length is to long for the format in\n      //    question (and no text was selected = will be replaced)\n      // * if type is date and key was period and date format is year or last char in string was\n      //    already a period\n      // * if type is time and key was colon and last char was already a colon\n      // * and also make sure copy & paste is allowed!\n      if ((!allowedKeysRegex.test(key)\n          || (disallowedKeysOnLengthRegex.test(key) && currentInputString.length >= formatLength\n            && document.activeElement.selectionEnd - document.activeElement.selectionStart === 0)\n          || (!isTimeField && key === '.' && (this.dateFormatInt === 'YYYY'\n            || currentInputString.charAt(currentInputString.length - 1) === '.'))\n          || (isTimeField && key === ':' && currentInputString.charAt(currentInputString.length - 1) === ':'))\n        && !(['c', 'v', 'x'].includes(key) && event.ctrlKey)) {\n        event.preventDefault();\n      }\n      // when the user tries to leave the field check if input string is valid\n      if (key === 'Enter') {\n        this.checkDateValidity(origin);\n        currentInputString = this[`input${origin}`];\n      }\n      // check if key was tab because of reasons specified above and close picker if necessary\n      if (key === 'Enter' || (key === 'Tab' && (event.shiftKey || !this.clearable\n        || !currentInputString))) {\n        // if yes set the relevant input field open status to false\n        this[`${origin.charAt(0).toLowerCase()}${origin.slice(1)}Open`] = false;\n      }\n    },\n    /**\n     * this function is triggered with the input event - it checks the length of the value and\n     * adds the '.' (date) or (':') or '0' in the correct places or removes '-' that was added at\n     * a wrong position if necessary\n     * @param {InputEvent} event - the input event\n     * @param {string} origin - is event coming from 'from' or 'to' field in title case\n     */\n    checkDate(event, origin) {\n      // get the value in question\n      let modifiedValue = event.target.value;\n      // this is a workaround necessary because of the manual input event triggered in BaseInput\n      // (~line 610) but since input has not changed with this event we can easily filter it out\n      // by only applying the operations if input has changed\n      if (modifiedValue === this[`input${origin}`]) return;\n      // otherwise continue to check the input\n      // determine if input is coming from a time or date field\n      const isTimeField = this.isTimeInputField(origin);\n      // depending on that different characters need to be added\n      const charToAdd = isTimeField ? ':' : '.';\n      // check if value is present and if input type is other than 'deleteContentBackward' because\n      // otherwise the dots can not be deleted anymore\n      if (modifiedValue && event.inputType !== 'deleteContentBackward') {\n        // remove a non-matching '-' character\n        if (modifiedValue !== '-' && !this.isNegativeDisplayDate(modifiedValue)) {\n          modifiedValue = modifiedValue.replace('-', '');\n        }\n        // now check the date format and if input so far matches the appropriate regex\n        if ((!isTimeField && this.dateFormatInt === 'DD.MM.YYYY' && /^(\\d{2}$|\\d{2}\\.\\d{2})$/.test(modifiedValue))\n          || ((this.dateFormatInt === 'MM.YYYY' || isTimeField) && /^\\d{2}$/.test(modifiedValue))) {\n          // if so - add a period character\n          modifiedValue = `${modifiedValue}${charToAdd}`;\n        }\n        const firstTwoDigitsRegex = new RegExp(`^[1-9]${isTimeField ? ':' : '\\\\.'}$`);\n        // check if input was a period - if yes - check date validity and add zeros if necessary\n        if (firstTwoDigitsRegex.test(modifiedValue)) {\n          modifiedValue = `0${modifiedValue}`;\n        } else if (/^\\d{2}\\.\\d\\.$/.test(modifiedValue)) {\n          const [day, month, year] = modifiedValue.split('.');\n          modifiedValue = `${day}.0${month}.${year}`;\n        }\n      }\n      this[`input${origin}`] = modifiedValue;\n    },\n    /**\n     * this function is triggered with the blur event on the input and does a last check on the\n     * validity of the value\n     * @param {string} origin - is event coming from 'from' or 'to' field in title case\n     */\n    checkDateValidity(origin) {\n      // important and mostly different checks to make depending if value is date or time\n      // so save that in variable\n      const isTimeField = this.isTimeInputField(origin);\n      // since Date() has problems with negative dates just remove the '-' and add it again after!\n      let positiveDate = this.removeYearMinusFromDisplayDate(this[`input${origin}`]);\n      // check if there is a value present\n      if (positiveDate) {\n        // also save the current format length\n        const formatLength = isTimeField ? 5 : this.dateFormatInt.length;\n        // get the separator depending on time or date field\n        const separator = isTimeField ? ':' : '.';\n        // get the array length of array with string split up by separator (should be same for\n        // format and value string)\n        const numberFormatParts = isTimeField ? 2 : this.dateFormatInt.split('.').length;\n        // first check if periods (date) or colons (time) are too many\n        if (positiveDate.split(separator).length > numberFormatParts) {\n          // just remove all the periods or colons - there the next check will add some again\n          positiveDate = positiveDate.replaceAll('.', '');\n        }\n        // check if there are too little separators\n        if (numberFormatParts > positiveDate.split(separator).length) {\n          // check if day and month (for DDMMYYYY) or month and year (for MMYYYY) or time\n          // are without period or colon respectively\n          if (formatLength !== 4 && /^\\d{3}/.test(positiveDate)) {\n            // this assumes the first two digits are for day or month respectively!\n            // TODO: not ideal that 2 digits are assumed - see if this can be improved\n            positiveDate = `${positiveDate.slice(0, 2)}${separator}${positiveDate.slice(2, positiveDate.length)}`;\n          }\n          // check if there is a second period between month and year (for DDMMYYYY)\n          if (this.dateFormatInt === 'DD.MM.YYYY' && formatLength !== 4 && /^\\d{2}\\.\\d{3}/.test(positiveDate)) {\n            // this assumes there are two digits for day and month respectively!\n            // TODO: not ideal that 2 digits are assumed - see if this can be improved\n            positiveDate = `${positiveDate.slice(0, 5)}.${positiveDate.slice(5, positiveDate.length)}`;\n          }\n        }\n        // second check if the length of the value is correct\n        if (positiveDate.length !== formatLength) {\n          // distinguish between date and time string\n          if (isTimeField) {\n            // check if minutes are missing\n            if (/^\\d{1,2}:?$/.test(positiveDate)) {\n              const [hours] = positiveDate.split(':');\n              positiveDate = `${hours}:00`;\n            }\n            // check if zeros out front are missing from hour\n            if (/^\\d:\\d{1,2}$/.test(positiveDate)) {\n              const [hours, minutes] = positiveDate.split(':');\n              positiveDate = `0${hours}:${minutes}`;\n            }\n            // check if zeros out front are missing from minute\n            if (/^\\d{2}:\\d$/.test(positiveDate)) {\n              const [hours, minutes] = positiveDate.split(':');\n              positiveDate = `${hours}:0${minutes}`;\n            }\n          } else {\n            // first check reason for length mismatch is year is\n            // completely missing for date format\n            if (this.dateFormatInt === 'DD.MM.YYYY' && /^\\d{1,2}\\.\\d{1,2}\\.?(\\d{0,3})$/.test(positiveDate)) {\n              // determine current year\n              const currentYear = new Date().getFullYear();\n              const [day, month, year] = positiveDate.split('.');\n              if (!year) {\n                // repair date and add the year if it is missing\n                positiveDate = `${day}.${month}.${currentYear}`;\n                // else assume there are digits missing from the year and add 0\n              } else {\n                positiveDate = `${day}.${month}.${year.padStart(4, '0')}`;\n              }\n            }\n            // for month format\n            if (this.dateFormatInt === 'MM.YYYY' && /^\\d{1,2}\\.?(\\d{0}|\\d{2})$/.test(positiveDate)) {\n              // determine current year\n              const currentYear = new Date().getFullYear();\n              const [month, year] = positiveDate.split('.');\n              // repair date and add first two year digits - if date more than 10 years to the\n              // future - make it current century - otherwise last century\n              const century = (currentYear).toString().slice(0, 2);\n              positiveDate = `${month}.${year > (currentYear + 10).toString().slice(2, 4)\n                ? Number(century - 1) : century}${year || currentYear.toString().slice(2, 4)}`;\n            }\n            // second check if the reason for the length not matching is that the day is\n            // missing a zero\n            if (this.dateFormatInt === 'DD.MM.YYYY' && /^[1-9]\\.\\d{1,2}\\.\\d{4}$/.test(positiveDate)) {\n              // get the values\n              const [day, month, year] = positiveDate.split('.');\n              // repair date and add a zero to day\n              positiveDate = `0${day}.${month}.${year}`;\n            }\n            // second check if the reason for mismatching length is that the zero in month\n            // is missing\n            if (['DD.MM.YYYY', 'MM.YYYY'].includes(this.dateFormatInt) && /^\\d{2}?\\.?[1-9]\\.\\d{4}$/.test(positiveDate)) {\n              // get values, reverse in order to be able to get also correct values for format\n              // 'month'\n              const [year, month, day] = positiveDate.split('.').reverse();\n              // repair date and add missing zero to month\n              positiveDate = `${day}.0${month}.${year}`;\n            }\n            // if format is year assume there are zeros in the year missing\n            if (this.dateFormatInt === 'YYYY') {\n              positiveDate = `${positiveDate.padStart(4, '0')}`;\n            }\n          }\n          // now check if time/date has now the correct length - if not still remove the value\n          if (positiveDate.length !== formatLength) {\n            positiveDate = '';\n          }\n        }\n        // now check for general validity\n        if (isTimeField) {\n          // just add random date to see if time is valid\n          if (Number.isNaN(Date.parse(`1212-12-12T${positiveDate}`))) {\n            let [hours, minutes] = positiveDate.split(':');\n            // check if valid hours\n            if (!/^([0-1][0-9]|2[0-4])$/.test(hours)) {\n              hours = '00';\n            }\n            // check if valid minutes\n            if (!/^[0-5][0-9]$/.test(minutes)) {\n              minutes = '00';\n            }\n            // construct a new time\n            const newTime = `${hours}:${minutes}`;\n            // now check again if time is valid now if yes assign, if no delete the string\n            positiveDate = Number.isNaN(Date.parse(`1212-12-12T${newTime}`)) ? '' : newTime;\n          }\n        } else {\n          // now truly check if date is a valid date\n          if (Number.isNaN(Date.parse(this.parseToDateStorage(positiveDate)))) {\n            // TODO: check if date has appropriate number of periods\n            const [year, month, day] = positiveDate.split('.').reverse();\n            if (this.dateFormatInt === 'DD.MM.YYYY') {\n              // TODO: could this check already be done on input???\n              // check if something is wrong with the day\n              if (!/^(0[1-9]|[1-2][0-9]|3[0-1])/.test(day)) {\n                // replace day with appropriate value\n                positiveDate = `01.${month}.${year}`;\n              }\n            } if (this.dateFormatInt !== 'YYYY') {\n              // check if something is wrong with the month\n              if (!/^(0[1-9]|1[0-2])/.test(month)) {\n                // replace month with appropriate value\n                positiveDate = `${day ? `${day}.` : ''}01.${year}`;\n              }\n            }\n          }\n          // since technically invalid dates (like 30.02.2000) will also be considered a\n          // valid date by Date.parse() just convert to Date and back one more time\n          // new Date(input) will always convert to the actual day in the next month\n          // e.g. 31.06. --> 01.07. ; 30.02. --> 02.03.\n          const tempDate = this.getDateString(this.convertToDate(this.parseToDateStorage(positiveDate)));\n          // now check if date in the format YYYY-(MM-(DD)) is valid\n          if (!Number.isNaN(Date.parse(this.parseToDateStorage(tempDate)))) {\n            // if it is a valid date after conversion and if yes store it so it can\n            // be assigned back to inputFrom/inputTo\n            positiveDate = this.parseToDateDisplay(tempDate);\n          } else {\n            positiveDate = '';\n          }\n        }\n        // now add the minus again if necessary\n        this[`input${origin}`] = this.addYearMinusToDateDisplay(\n          positiveDate,\n          this.isNegativeDisplayDate(this[`input${origin}`]),\n        );\n      }\n      // after everything also still check if the new date/time string needs a fade out\n      this.calcFadeOut([origin]);\n      const data = this.getInputData();\n      /**\n       * this event is emitted when the value was validated in case input should just be considered\n       * after date validation\n       *\n       * @event value-validated\n       * @param {string, Object} - the validated string or input object\n       */\n      this.$emit('value-validated', data);\n    },\n    /**\n     * a function to have the time picker close automatically as soon as minutes\n     * are selected\n     * @param {string} origin - is it from the 'from' or 'to' part of the picker\n     * @param {string} type - was 'hour' or 'minute' selected\n     */\n    closeTimePicker({ origin, type }) {\n      // else check if value selected was type 'minute' - this will automatically also\n      // exclude date fields from any action\n      if (type === 'minute') {\n        // get capitalized origin here since needed 2x\n        const uppercaseOrigin = capitalizeString(origin);\n        // check date validity\n        this.checkDateValidity(uppercaseOrigin);\n        // close the drop down\n        this[`${origin}Open`] = false;\n      }\n    },\n    /**\n     * function triggered on datepicker 'pick' event, handling date picker closing\n     *  caveat: this event is just triggered for DATE picker - not time!\n     * @param origin\n     */\n    datePicked(origin) {\n      this[`${origin}Open`] = false;\n    },\n    /**\n     * convert function triggered on format tab switch\n     */\n    convertDate(oldFormat) {\n      // go over each property of inputInt (that includes date - since not applicable to time\n      // values)\n      Object.entries(this.inputInt).filter(([key]) => !!key.includes('date'))\n        .forEach(([dateKey, dateValue]) => {\n          // get the date to convert and remove the minus if there is one\n          const dateToConvert = this.removeYearMinusFromStorageDate(dateValue, oldFormat);\n          if (dateToConvert) {\n            if (this.minDateView === 'year') {\n              // convert date string to real date in order to get year and convert back to string\n              this.inputInt[dateKey] = this.addYearMinusToDateStorage(\n                this.convertToDate(dateToConvert).getFullYear().toString(),\n                this.isNegativeStorageDate(dateValue, oldFormat),\n              );\n              return;\n            }\n            let useStorageDate;\n            const storageDate = this.tempDateStore ? this.tempDateStore[dateKey] : null;\n            const isNegativeTempStorageDate = !!storageDate && /^-/.test(storageDate);\n            const isNegativeNewDateValue = this.isNegativeStorageDate(dateValue, oldFormat);\n            const positiveTempStorageDate = isNegativeTempStorageDate ? storageDate.replace('-', '') : storageDate;\n            if (this.minDateView === 'month') {\n              useStorageDate = !!positiveTempStorageDate\n                // get stored date if\n                // a) previous date was full date and month and year\n                // are identical with stored year and month\n                && ((!this.isDateFormatYear\n                    && this.monthAndYearIdent(positiveTempStorageDate, dateToConvert))\n                  // b) previous date was year and it is identical with stored year\n                  || (new Date(positiveTempStorageDate)\n                    .getFullYear().toString() === dateToConvert))\n                // also check that they have the identical sign\n                && (isNegativeTempStorageDate === isNegativeNewDateValue);\n              // assume the format is 'date'\n            } else {\n              // check if a previous date was stored and year (coming from year)\n              useStorageDate = !!positiveTempStorageDate && ((this.isDateFormatYear\n                  && new Date(positiveTempStorageDate).getFullYear().toString() === dateToConvert\n                  && isNegativeTempStorageDate === this.isNegativeStorageDate(dateValue, oldFormat))\n                // or month and year (coming from month) was changed or is still the same\n                || (this.isDateFormatMonth\n                  && this.monthAndYearIdent(positiveTempStorageDate, dateToConvert)\n                  && (isNegativeTempStorageDate === isNegativeNewDateValue)));\n              // if a previous date was stored use this one else use the input date\n            }\n            const newDate = useStorageDate ? positiveTempStorageDate : dateToConvert;\n            // now assign the new date to the input variable\n            this.inputInt[dateKey] = this.addYearMinusToDateStorage(\n              this.getDateString(this.convertToDate(newDate)),\n              // use the original dates here before minus was removed, depending on which date was used\n              (useStorageDate ? isNegativeTempStorageDate : isNegativeNewDateValue),\n            );\n          }\n        });\n    },\n    /**\n     * convert a value to a date in local time at zero hours\n     *\n     * @param {string} value - the date string stored in db (format YYYY-MM-DD) - this needs to\n     *  be a positive date value!! (remove minus from negative years before applying this function)\n     * @returns {Date} - (e.g. Fri Jul 30 2021 00:00:00 GMT+0200 (Central European Summer Time))\n     */\n    convertToDate(value) {\n      return new Date(`${value}T00:00:00.000`);\n    },\n    /**\n     * a function to convert a date to a string in the format YYYY-MM-DD\n     *\n     * @param {Date} date in format\n     * @returns {string} - returns a string in format YYYY-MM-DD\n     */\n    getDateString(date) {\n      // there is always a year // add padStart to always have 4 digits\n      let dateString = `${date.getFullYear().toString().padStart(4, '0')}`;\n      // if date format is not 'year' only - add month\n      if (this.dateFormatInt !== 'YYYY') {\n        const month = (date.getMonth() + 1).toString();\n        dateString = `${dateString}-${month.length < 2 ? '0' : ''}${month}`;\n      }\n      // if date format is 'date' - add day\n      if (this.dateFormatInt === 'DD.MM.YYYY') {\n        const day = date.getDate().toString();\n        dateString = `${dateString}-${day.length < 2 ? '0' : ''}${day}`;\n      }\n      return dateString;\n    },\n    /**\n     * compare 2 dates for identical month and year values respectively\n     *  these dates need to be positive values (remove the minus from the date\n     *  before applying this function)\n     * @param {string} date1 - a string in YYYY-MM-DD format\n     * @param {string} date2 - a string in YYYY-MM-DD format\n     * @returns {boolean}\n     */\n    monthAndYearIdent(date1, date2) {\n      const convertedDate1 = this.convertToDate(date1);\n      const convertedDate2 = this.convertToDate(date2);\n      const monthDate1 = convertedDate1.getMonth();\n      const monthDate2 = convertedDate2.getMonth();\n      const yearDate1 = convertedDate1.getFullYear();\n      const yearDate2 = convertedDate2.getFullYear();\n      return monthDate1 === monthDate2 && yearDate1 === yearDate2;\n    },\n    isTimeInputField(origin) {\n      return this.dateType === 'timerange' || (this.dateType === 'datetime' && origin.toLowerCase() === 'to');\n    },\n    /**\n     * add delay before value is set\n     *\n     * @param {String} origin - is event originating from 'from' or 'to' field\n     * @param {boolean} value\n     */\n    isActiveHandler(origin, value) {\n      // if false set value immediately\n      if (!value) {\n        this[`${origin}Open`] = value;\n        this.isActiveInt = this.fromOpen || this.toOpen;\n        // check for date validity here instead of blur event (necessary for time input\n        // which is not triggered otherwise)\n        this.checkDateValidity(capitalizeString(origin));\n        return;\n      }\n\n      // otherwise add a delay\n      setTimeout(() => {\n        this[`${origin}Open`] = value;\n        this.isActiveInt = this.fromOpen || this.toOpen;\n      }, this.isActiveDelay);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    ref=\"baseDateInputEl\"\n    v-bind=\"rootAttrs\"\n    class=\"base-date-input\">\n    <div\n      v-if=\"showLabelRow\"\n      :class=\"['base-date-input__label-row',\n               { 'base-date-input__label-row--visible': showLabel }]\">\n      <legend\n        v-if=\"showLabel\"\n        ref=\"labelEl\"\n        class=\"base-date-input__label\"\n        @click.prevent=\"\">\n        {{ label }}\n      </legend>\n      <div\n        :class=\"['base-date-input__label-additions',\n                 {'base-date-input__label-additions--switch-height': isSwitchableFormat },\n                 {'base-date-input__label-additions--wrap': wrapLabelRow }]\">\n        <div\n          ref=\"labelAdditionsEl\"\n          :class=\"['base-date-input__label-additions-inner',\n                   {'base-date-input__label-additions-inner--switch': isSwitchableFormat },\n                   {'base-date-input__label-additions-inner--no-label-switch': isSwitchableFormat\n                     && !showLabel }]\">\n          <!-- @slot to add additional elements to the label row -->\n          <slot name=\"label-addition\" />\n          <BaseSwitchButton\n            v-if=\"isSwitchableFormat\"\n            v-model=\"dateFormatInt\"\n            :options=\"tabSwitchOptions\"\n            :label=\"formatTabsLegend\"\n            :active-tab=\"dateFormatInt\"\n            class=\"base-date-input__switch-buttons\" />\n        </div>\n      </div>\n    </div>\n\n    <!-- FORM FIELDS -->\n    <!-- vuejs-accessibility/click-events-have-key-events: keydown event is counter productive to workflow here -->\n    <!-- vuejs-accessibility/no-static-element-interactions: click is just for handling focus no\n      interaction/accessibility needed -->\n    <!-- eslint-disable-next-line vuejs-accessibility/click-events-have-key-events vuejs-accessibility/no-static-element-interactions -->\n    <div\n      v-click-outside=\"onClickOutsideHandler\"\n      class=\"base-date-input__field-wrapper\"\n      @click=\"clickedInside\">\n      <!-- @slot to add elements within form field but before the input element line for an example see [BaseInput](BaseInput)-->\n      <slot name=\"pre-input-field\" />\n      <div class=\"base-date-input__input-fields\">\n        <!-- @slot add elements within input form field but before all other elements - this field wraps if necessary for an example see [BaseInput](BaseInput) -->\n        <slot name=\"input-field-addition-before\" />\n        <div class=\"base-date-input__input-line\">\n          <!-- @slot add elements directly in the input line (no wrapping) for an example see [BaseInput](BaseInput)-->\n          <slot name=\"input-field-inline-before\" />\n          <!-- INPUT FROM -->\n          <BaseInput\n            ref=\"baseInputFromEl\"\n            v-model=\"inputFrom\"\n            :input-id=\"`input-${internalId}-from`\"\n            :label=\"label\"\n            :show-label=\"false\"\n            :is-active=\"fromOpen\"\n            :use-form-field-styling=\"useFormFieldStyling\"\n            :show-input-border=\"showInputBorder\"\n            :clearable=\"clearable\"\n            :assistive-text=\"{\n              clearInput: typeof assistiveText.clearInput === 'string'\n                ? assistiveText.clearInput\n                : assistiveText.clearInput?.date_from ?? assistiveText.clearInput?.time_from\n                  ?? assistiveText.clearInput?.date ?? 'clear input',\n            }\"\n            :required=\"requiredFrom\"\n            :invalid=\"invalidFrom\"\n            :disabled=\"disabledFrom\"\n            :show-error-icon=\"showErrorIcon\"\n            :error-message=\"errorMessageFrom\"\n            :input-class=\"inputClass\"\n            :set-focus-on-active=\"setFocusOnActive\"\n            :use-fade-out=\"useFadeOutFrom\"\n            class=\"base-date-input__input-wrapper\"\n            @update:is-active=\"isActiveHandler('from', $event)\">\n            <template #input>\n              <div\n                class=\"base-date-input__datepicker\">\n                <!-- date picker needs to be added on mounted because otherwise SSR errors or hydration missmatches -->\n                <DatePicker\n                  v-if=\"mounted\"\n                  v-model:value=\"inputFrom\"\n                  :placeholder=\"isFromTimeField ? placeholder.time : placeholder.date\"\n                  :clearable=\"false\"\n                  :append-to-body=\"false\"\n                  :lang=\"lang\"\n                  :open=\"fromOpen\"\n                  :type=\"isFromTimeField ? 'time' : minDateView\"\n                  :format=\"isFromTimeField ? 'HH:mm' : datePickerValueFormat\"\n                  :value-type=\"isFromTimeField ? 'format' : datePickerValueFormat\"\n                  input-class=\"base-date-input__datepicker-input\"\n                  @pick=\"datePicked('from')\"\n                  @click.prevent=\"onInputClick\"\n                  @change=\"(time, timeType) => closeTimePicker({ origin: 'from', type: timeType })\">\n                  <template #input>\n                    <!-- need to disable because label is there - it is just in BaseInput\n                    component -->\n                    <!-- eslint-disable-next-line  vuejs-accessibility/form-control-has-label -->\n                    <input\n                      :id=\"`input-${internalId}-from`\"\n                      ref=\"inputFromEl\"\n                      enterkeyhint=\"done\"\n                      autocomplete=\"off\"\n                      v-bind=\"forwardAttrs\"\n                      :value=\"inputFrom\"\n                      :placeholder=\"isFromTimeField ? placeholder.time ?? placeholder\n                        : placeholder.date ?? placeholder\"\n                      :type=\"inputType\"\n                      :aria-describedby=\"label + '-' + internalId\"\n                      :aria-required=\"required\"\n                      :aria-invalid=\"invalid\"\n                      :required=\"required\"\n                      :disabled=\"disabled\"\n                      :aria-disabled=\"disabled\"\n                      :class=\"['base-date-input__input', inputClass]\"\n                      @input=\"checkDate($event, 'From')\"\n                      @keydown=\"handleInputKeydown($event, 'From')\"\n                      @blur=\"onInputBlur($event, 'from')\"\n                      @vue:mounted=\"calcFadeOut(['From'])\">\n                  </template>\n                  <!-- this empty element is here so that the default icon of datepicker\n                  is not used -->\n                  <template #icon-calendar>\n                    <div class=\"base-date-input__icon-wrapper\" />\n                  </template>\n                </DatePicker>\n              </div>\n            </template>\n            <template #post-input-field>\n              <BaseIcon\n                ref=\"baseIconEl\"\n                :name=\"isFromTimeField ? 'clock' : 'calendar-many'\"\n                :class=\"['base-date-input__date-icon', { hide: !showIcons }]\"\n                @click.stop=\"fromOpen = !fromOpen\" />\n            </template>\n          </BaseInput>\n\n          <span\n            v-if=\"dateType === 'daterange' || dateType === 'timerange'\"\n            class=\"base-date-input__separator\">{{ rangeSeparator }}</span>\n\n          <!-- INPUT TO -->\n          <BaseInput\n            v-if=\"dateType !== 'single'\"\n            ref=\"baseInputToEl\"\n            v-model=\"inputTo\"\n            :input-id=\"`input-${internalId}-to`\"\n            :label=\"label\"\n            :show-label=\"false\"\n            :is-active=\"toOpen\"\n            :use-form-field-styling=\"useFormFieldStyling\"\n            :show-input-border=\"showInputBorder\"\n            :clearable=\"clearable\"\n            :assistive-text=\"{\n              clearInput: typeof assistiveText.clearInput === 'string'\n                ? assistiveText.clearInput\n                : assistiveText.clearInput?.date_to ?? assistiveText.clearInput?.time_to\n                  ?? assistiveText.clearInput?.time ?? 'clear input',\n            }\"\n            :required=\"requiredTo\"\n            :invalid=\"invalidTo\"\n            :disabled=\"disabledTo\"\n            :show-error-icon=\"showErrorIcon\"\n            :error-message=\"errorMessageTo\"\n            :set-focus-on-active=\"setFocusOnActive\"\n            :use-fade-out=\"useFadeOutTo\"\n            class=\"base-date-input__input-wrapper\"\n            @update:is-active=\"isActiveHandler('to', $event)\">\n            <template #input>\n              <div\n                class=\"base-date-input__datepicker\">\n                <!-- date picker needs to be added on mounted because otherwise SSR errors or hydration missmatches -->\n                <DatePicker\n                  v-if=\"mounted\"\n                  v-model:value=\"inputTo\"\n                  :placeholder=\"isToTimeField ? placeholder.time : placeholder.date\"\n                  :clearable=\"false\"\n                  :append-to-body=\"false\"\n                  :lang=\"lang\"\n                  :open=\"toOpen\"\n                  :type=\"isToTimeField ? 'time' : minDateView\"\n                  :format=\"isToTimeField ? 'HH:mm' : datePickerValueFormat\"\n                  :value-type=\"isToTimeField ? 'format' : datePickerValueFormat\"\n                  input-class=\"base-date-input__datepicker-input\"\n                  @pick=\"datePicked('to')\"\n                  @click.prevent=\"onInputClick\"\n                  @change=\"(time, timeType) => closeTimePicker({ origin: 'to', type: timeType })\">\n                  <template #input>\n                    <!-- need to disable because label is there - it is just in BaseInput\n                      component -->\n                    <!-- eslint-disable-next-line  vuejs-accessibility/form-control-has-label -->\n                    <input\n                      :id=\"`input-${internalId}-to`\"\n                      ref=\"inputToEl\"\n                      enterkeyhint=\"done\"\n                      autocomplete=\"off\"\n                      v-bind=\"forwardAttrs\"\n                      :value=\"inputTo\"\n                      :placeholder=\"isToTimeField ? placeholder.time ?? placeholder\n                        : placeholder.date ?? placeholder\"\n                      :type=\"inputType\"\n                      :aria-describedby=\"label + '-to-' + internalId\"\n                      :aria-required=\"required\"\n                      :aria-invalid=\"invalid\"\n                      :required=\"required\"\n                      :disabled=\"disabled\"\n                      :aria-disabled=\"disabled\"\n                      :class=\"['base-date-input__input', inputClass]\"\n                      @input=\"checkDate($event, 'To')\"\n                      @keydown=\"handleInputKeydown($event, 'To')\"\n                      @blur=\"onInputBlur($event, 'to')\"\n                      @vue:mounted=\"calcFadeOut(['To'])\">\n                  </template>\n                  <!-- this empty element is here so that the default icon of\n                  datepicker is not used -->\n                  <template #icon-calendar>\n                    <div class=\"base-date-input__icon-wrapper\" />\n                  </template>\n                </DatePicker>\n              </div>\n            </template>\n            <template #post-input-field>\n              <BaseIcon\n                v-if=\"showIcons\"\n                :name=\"isToTimeField ? 'clock' : 'calendar-many'\"\n                class=\"base-date-input__date-icon\"\n                @click.stop=\"toOpen = !toOpen\" />\n            </template>\n          </BaseInput>\n        </div>\n      </div>\n      <!-- @slot for adding elements after input -->\n      <slot name=\"post-input-field\" />\n    </div>\n\n    <div class=\"base-date-input__below\">\n      <!-- @slot to add elements below input fields e.g. add drop down -->\n      <slot name=\"below-input\" />\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-date-input {\n    display: flex;\n    flex-direction: column;\n    width: 100%;\n    position: relative;\n\n    .base-date-input__label-row {\n      display: flex;\n      flex-wrap: wrap;\n      width: 100%;\n      height: 100%;\n      justify-content: space-between;\n      align-items: center;\n\n      &.base-date-input__label-row--visible {\n        margin-bottom: $spacing-small-half;\n      }\n\n      .base-date-input__label {\n        color: $font-color-second;\n        margin-bottom: $spacing-small-half;\n        text-align: left;\n        align-self: flex-end;\n        margin-right: 50px;\n      }\n\n      .base-date-input__label-additions {\n        position: relative;\n        display: flex;\n        flex-wrap: wrap;\n        align-items: center;\n        justify-content: flex-end;\n        flex: 1 1 auto;\n        height: $line-height;\n\n        &.base-date-input__label-additions--switch-height {\n          height: calc(#{$line-height} + #{$spacing-small-half});\n\n          @media screen and (max-width: $mobile) {\n            height: calc(#{$line-height} + #{$spacing-small});\n          }\n\n          &.base-date-input__label-additions--wrap {\n            margin-top: 2px;\n          }\n        }\n\n        &.base-date-input__label-additions--wrap {\n          width: 100%;\n        }\n      }\n\n      .base-date-input__label-additions-inner {\n        position: absolute;\n        right: 0;\n        display: flex;\n        align-items: center;\n        margin-bottom: $spacing-small-half;\n\n        &.base-date-input__label-additions-inner--switch {\n          bottom: 0;\n          margin-bottom: calc(-#{$spacing-small-half} / 2);\n\n          @media screen and (max-width: $mobile) {\n            margin-bottom: calc(-#{$spacing-small} - 2px);\n          }\n        }\n        &.base-date-input__label-additions-inner--no-label-switch {\n          margin-bottom:  2px;\n\n          @media screen and (max-width: $mobile) {\n            margin-bottom: calc(-#{$spacing-small} + 1px);\n          }\n        }\n\n        .base-date-input__switch-buttons {\n          bottom: 0;\n          display: flex;\n        }\n      }\n    }\n\n    .base-date-input__field-wrapper {\n      display: flex;\n      align-items: baseline;\n      width: 100%;\n\n      .base-date-input__input-fields {\n        display: flex;\n        align-items: center;\n        flex: 1 1 auto;\n        flex-wrap: wrap;\n\n        .base-date-input__input-line {\n          display: flex;\n          flex: 1 1 auto;\n          align-items: baseline;\n\n          .base-date-input__input-wrapper {\n\n            & + .base-date-input__input-wrapper {\n              margin-left: $spacing;\n            }\n\n            .base-date-input__datepicker {\n              flex-grow: 1;\n              width: auto;\n              font-family: inherit;\n              font-size: inherit;\n\n              .base-date-input__input {\n                min-height: $row-height-small;\n                line-height: $row-height-small;\n                width: 100%;\n                height: 100%;\n              }\n            }\n\n            .base-date-input__icon-wrapper::before {\n              content: '';\n            }\n\n            .base-date-input__date-icon {\n              position: relative;\n              width: $icon-large;\n              height: $icon-large;\n              color: $font-color-second;\n              cursor: pointer;\n              flex-shrink: 0;\n              align-self: center;\n              margin-left: $spacing-small;\n            }\n          }\n\n          .base-date-input__separator {\n            padding: 0 $spacing;\n          }\n        }\n      }\n    }\n\n    .base-date-input__below {\n      position: relative;\n    }\n  }\n\n  @media screen and (max-width: $mobile) {\n    .base-date-input .base-date-input__label-row .base-date-input__label-additions {\n      align-items: center;\n    }\n  }\n</style>\n\n<style lang=\"scss\">\n  @use '@/styles/datepicker';\n</style>\n","<script>\nimport BaseBox from '@/components/BaseBox/BaseBox.vue';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { toRef } from 'vue';\n\n/**\n * conveniently display key value pairs in a list\n */\nexport default {\n  name: 'BaseDetailBox',\n  components: {\n    BaseBox,\n  },\n  props: {\n    /**\n     * an array with objects to pass the data to be displayed, expecting an object with\n     * `label` and `value` properties - if different please use `valuePropertyName`\n     * and `labelPropertyName` respectively!\n     */\n    data: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * customize the value property displayed\n     */\n    valuePropertyName: {\n      type: String,\n      default: 'value',\n    },\n    /**\n     * customize the label property displayed\n     */\n    labelPropertyName: {\n      type: String,\n      default: 'label',\n    },\n    /**\n     * specify a language (ISO 639-1) (used for label if label is language specific object\n     * e.g. `{ de: 'xxx', en: 'yyy' }`)\n     */\n    language: {\n      type: String,\n      default: 'en',\n    },\n  },\n  setup(props) {\n    /** INTERNATIONALIZATION */\n    const { getLangLabel } = useI18n(toRef(props, 'language'));\n    return {\n      getLangLabel,\n    };\n  },\n};\n</script>\n\n<template>\n  <BaseBox\n    :box-size=\"{ width: '100%' }\"\n    :box-hover=\"false\"\n    box-ratio=\"0\"\n    class=\"base-detail-box\">\n    <dl class=\"base-detail-box-dl\">\n      <template\n        v-for=\"(item, index) in data\"\n        :key=\"'dt' + index\">\n        <dt>\n          {{ getLangLabel(item[labelPropertyName], true) }}\n        </dt>\n        <dd>\n          <!-- TODO: if necessary also add language specific function here! -->\n          {{ item[valuePropertyName] }}\n        </dd>\n      </template>\n    </dl>\n  </BaseBox>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  $width-dl: 20%;\n  $width-dd: 80%;\n\n  .base-detail-box {\n    padding: $spacing;\n  }\n\n  .base-detail-box-dl {\n    display: block;\n\n    dt {\n      color: $font-color-second;\n      margin-top: $spacing;\n    }\n\n    dt:first-of-type {\n      margin-top: 0;\n    }\n\n    dd {\n      margin-top: $spacing-small;\n    }\n\n    @media screen and (min-width: 640px) {\n      display: flex;\n      flex-wrap: wrap;\n\n      dt,\n      dd {\n        margin-top: $spacing;\n      }\n\n      dt {\n        position: relative;\n        margin-right: $spacing;\n        overflow: hidden;\n\n        &:after {\n          content: '';\n          height: 100%;\n          width: $fade-out-width;\n          position: absolute;\n          top: 0;\n          right: -1px;\n          background: linear-gradient(to right, rgba(255, 255, 255, 0) , rgba(255, 255, 255, 1));\n        }\n      }\n\n      dd {\n        margin-left: $spacing;\n      }\n\n      dt:first-of-type,\n      dd:first-of-type {\n        margin-top: 0;\n      }\n\n      dt {\n        width: calc(#{$width-dl} - #{$spacing});\n      }\n\n      dt + dd {\n        width: calc(#{$width-dd} - #{$spacing-large});\n      }\n\n      dd + dd {\n        width: calc(#{$width-dd} - #{$spacing-large});\n        margin-top: $spacing-small;\n        margin-left: calc(#{$width-dl} + #{$spacing});\n      }\n    }\n  }\n</style>\n","<script>\nimport BaseBoxButton from '@/components/BaseBoxButton/BaseBoxButton.vue';\nimport { defineAsyncComponent } from 'vue';\n\n/**\n * An Element to drop files or other UI Elements into\n */\n\nexport default {\n  name: 'BaseDropBox',\n  components: {\n    BaseBoxButton,\n    VueDraggable: defineAsyncComponent(() => import('vue-draggable-plus').then(m => m.VueDraggable)),\n  },\n  props: {\n    /**\n     * specify an icon to be displayed centered in the box\n     */\n    icon: {\n      type: String,\n      default: null,\n    },\n    /**\n     * if `true` a plus sign is displayed in front of the icon\n     */\n    showPlus: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * the text displayed below the icon\n     */\n    text: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify a potential subtext\n     */\n    subtext: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define the box size\n     */\n    boxSize: {\n      type: Object,\n      default: () => ({ width: '250px' }),\n    },\n    /**\n     * define the ratio of width and height of the box\n     * (in percent string, e.g. 1:1 --> `'100'`, 1:2 --> `'50'`)\n     */\n    boxRatio: {\n      type: String,\n      default: '100',\n    },\n    /**\n     * specify the tag of the button\n     */\n    renderElementAs: {\n      type: String,\n      default: 'div',\n    },\n    /**\n     * specify the type of drops\n     *     @values files, elements\n     */\n    dropType: {\n      type: String,\n      default: 'files',\n      validate(val) {\n        return ['files', 'elements'].includes(val);\n      },\n    },\n    /**\n     * if the `dropType` is `elements`, specify the element group name\n     * this needs to match the group name of the draggable element that should\n     * be dragged into this element\n     */\n    dropElementName: {\n      type: String,\n      default: '',\n    },\n    /**\n     * if the `dropType` is `elements` specify a class name to limit interactions to a certain element\n     */\n    dragItemClass: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set button inactive\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * show tooltip\n     */\n    showTooltip: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['clicked', 'dropped-element', 'dropped-file'],\n  data() {\n    return {\n      dragAndDropCapable: false,\n      isDragOver: false,\n      dragList: [],\n    };\n  },\n  mounted() {\n    this.dragAndDropCapable = this.determineDragAndDropCapable();\n    if (this.dragAndDropCapable) {\n      ['drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop'].forEach(((evt) => {\n        this.$refs.baseDropBoxElement.$el.addEventListener(evt, ((e) => {\n          e.preventDefault();\n        }), true);\n      }));\n      if (this.dropType === 'files') {\n        this.$refs.fileform.addEventListener('drop', (e) => {\n          this.isDragOver = false;\n          // if the element is disabled or drop event does not contain any files - do not emit\n          // the event and return\n          if (this.disabled || !e.dataTransfer?.files?.length) return;\n          /**\n           * event emitted when a file or an element is dropped on the box, emitting the type of event\n           *\n           * @event dropped-file\n           * @param { DragEvent } - propagating the triggered event\n           */\n          this.$emit('dropped-file', e);\n        });\n        ['dragenter', 'dragleave'].forEach(((evt) => {\n          this.$refs.fileform.addEventListener(evt, ((originalEvent) => {\n            if (this.disabled) return;\n            // kind of hacky solution to prevent target element to change color\n            // only works when draggable prop is set on every draggable element on site\n            // otherwise it will light up on file drop boxes!\n            if (!originalEvent.dataTransfer.types.includes('draggable')) {\n              this.isDragOver = !this.isDragOver;\n            }\n          }));\n        }));\n      }\n    }\n  },\n  methods: {\n    onDragChange(evt) {\n      if (!this.isDragOver) {\n        // check if a drag item class was specified otherwise always\n        // set dragging true\n        if (!this.dragItemClass) {\n          this.isDragOver = true;\n          // else check if cloned element contains class name\n        } else if (evt.clone.className.includes(this.dragItemClass)) {\n          this.isDragOver = true;\n        }\n      }\n      return evt.newIndex;\n    },\n    determineDragAndDropCapable() {\n      const div = document.createElement('div');\n      return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div))\n        && 'FormData' in window && 'FileReader' in window;\n    },\n    /**\n     * method to get the dropped element id and emit it to parent\n     */\n    addEntry(event) {\n      // check if box is for receiving elements (not files)\n      if (this.dropType === 'elements') {\n        // and check if item is currently still dragged over box (draggable event will also\n        // fire if item was dragged outside again)\n        if (this.isDragOver) {\n          const draggedElementId = this.dragList[0].id;\n          /**\n           * event emitted when an element is dropped on the box, emitting the element data id\n           *\n           * @event dropped-element\n           * @param { string } - the id of the dropped element\n           */\n          this.$emit('dropped-element', draggedElementId);\n        }\n        this.dragList = [];\n        // otherwise box stays highlighted on touch\n        if (event.originalEvent.type === 'touchend') {\n          this.isDragOver = false;\n        }\n      }\n    },\n    dragEnter(event) {\n      // trigger click event on touch devices\n      if (event.pointerType === 'touch' && !this.disabled && !this.isDragOver) {\n        this.$emit('clicked', event);\n      }\n    },\n    dragLeave(event) {\n      // to prevent trigger when it is touch device and element was just dropped into box\n      if (!(event.pointerType === 'touch' && !event.relatedTarget)) {\n        this.isDragOver = false;\n      }\n    },\n    onClicked(event) {\n      // on touch devices the click event is handled with dragEnter() due problems on iOS Safari\n      if (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0)) {\n        return;\n      }\n\n      /**\n       * Triggered when the box or tooltip is clicked\n       *\n       * @event clicked\n       * @param {Event} - propagating the triggered click event\n       */\n      if (!this.disabled) {\n        this.$emit('clicked', event);\n      }\n    },\n    onTooltip(event) {\n      /**\n       * Triggered when the box or tooltip is clicked\n       *\n       * @event clicked\n       * @param {Event} - propagating the triggered click event\n       */\n      this.$emit('clicked', event);\n    },\n  },\n};\n\n</script>\n\n<template>\n  <BaseBoxButton\n    ref=\"baseDropBoxElement\"\n    v-bind=\"$props\"\n    :box-ratio=\"boxRatio\"\n    :render-element-as=\"renderElementAs\"\n    :disabled=\"disabled\"\n    :class=\"[\n      'base-drop-box',\n      { 'base-box-button--disabled': disabled },\n      { 'is-drag-over': isDragOver }]\"\n    @clicked=\"onClicked\"\n    @on-tooltip=\"onTooltip\">\n    <div\n      class=\"base-drop-box-inner\">\n      <VueDraggable\n        v-if=\"dropType === 'elements'\"\n        v-model=\"dragList\"\n        :sort=\"false\"\n        :group=\"dropElementName\"\n        :on-change=\"onDragChange\"\n        :disabled=\"disabled\"\n        ghost-class=\"base-drop-box-ghost\"\n        class=\"base-drop-box-drag-area\"\n        @add=\"addEntry\">\n        <!-- these events are not relevant for accessibility -->\n        <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n        <div\n          class=\"base-drop-box-drag-area\"\n          @dragleave=\"dragLeave\"\n          @pointerenter=\"dragEnter\"\n          @pointerleave=\"dragLeave\">\n          <div\n            v-for=\"item in dragList\"\n            :key=\"item.id\"\n            class=\"base-drop-box-cloned-items\">\n            {{ item }}\n          </div>\n        </div>\n      </VueDraggable>\n      <form\n        v-else\n        ref=\"fileform\" />\n    </div>\n  </BaseBoxButton>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-drop-box {\n    background-color: $background-color !important;\n    display: flex;\n    cursor: text;\n\n    &:hover {\n      color: $app-color !important;\n    }\n\n    .base-drop-box-inner {\n      position: absolute;\n      height: 100%;\n      width: 100%;\n      border: $upload-border;\n      transition: all 0.2s ease;\n\n      &:hover {\n        border: $upload-border-hover;\n        cursor: pointer;\n      }\n\n      .base-drop-box-drag-area {\n        height: 100%;\n      }\n\n      form{\n        text-align: center;\n        height: 100%;\n        width: 100%;\n      }\n    }\n\n    &.base-box-button--disabled {\n\n      .base-drop-box-inner {\n        border-color: $graytext-color;\n\n        &:hover {\n          border-color: $graytext-color;\n          cursor: default;\n          box-shadow: none;\n        }\n      }\n    }\n  }\n\n  .is-drag-over {\n    color: $app-color;\n    cursor: move;\n\n    &:hover {\n      cursor: pointer;\n    }\n\n    .base-drop-box-inner {\n      border: $upload-border-hover;\n    }\n  }\n\n  .base-drop-box-drag-area :deep(.base-drop-box-ghost) {\n    visibility: hidden !important;\n    position: absolute;\n    top: auto;\n  }\n</style>\n","<script>\nimport { vOnClickOutside } from '@vueuse/components';\nimport BaseButton from '@/components/BaseButton/BaseButton.vue';\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport { useListNavigation } from '@/composables/useListNavigation.js';\nimport { defineAsyncComponent, ref, useTemplateRef, watch } from 'vue';\nimport { useWindowResize } from '@/composables/useWindowResize.js';\nimport { useDebounce } from '@/composables/useDebounce.js';\n\n/**\n * An Element to have the functionality of several buttons in one element\n */\nexport default {\n  name: 'BaseDropButton',\n  components: {\n    BaseDropDownList: defineAsyncComponent(() => import('@/components/BaseDropDownList/BaseDropDownList.vue')),\n    BaseButton,\n    BaseIcon,\n  },\n  directives: {\n    ClickOutside: vOnClickOutside,\n  },\n  props: {\n    /**\n     * array of button options\n     * specify an array of strings naming the action (in case label and icon are handled via slot)\n     * or objects with `action`, `label` and `icon` (`action` and `label` may be customized\n     * via `identifierPropertyName` and `labelPropertyName` respectively)\n     */\n    buttons: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * specify either a button object or the identifier value of one of the items in\n     * the buttons array that should be shown as primary button - always visible.\n     * in case a string is provided an object with that identifier should be present in the buttons\n     * array!\n     */\n    primaryButton: {\n      type: [Object, String],\n      default: null,\n    },\n    /**\n     * add a description for the expand button - purely for accessibility\n     * functionalities\n     */\n    expandButtonLabel: {\n      type: String,\n      default: 'Show more Options',\n    },\n    /**\n     * specify a custom buttons array object property that should be used as\n     * identifier\n     */\n    identifierPropertyName: {\n      type: String,\n      default: 'action',\n    },\n    /**\n     * specify a custom buttons array object property that should be used as\n     * label\n     */\n    labelPropertyName: {\n      type: String,\n      default: 'label',\n    },\n  },\n  emits: ['clicked'],\n  setup() {\n    /** DROP DOWN NAVIGATION */\n    const { navigate } = useListNavigation();\n\n    /** RESIZE HANDLING */\n      // create reference to drop down element\n    const dropDown = useTemplateRef('dropDownEl');\n    // and the drop down parent element\n    const dropArea = useTemplateRef('dropAreaEl');\n    /**\n     * a variable to steer the css classes for drop down positioning (this way\n     * scss variables can still be used)\n     * @type {Object}\n     * @property {string} dropDownPosition.horizontal - to position drop down 'left' or 'right'\n     * @property {string} dropDownPosition.vertical - to position drop down 'top' or 'bottom'\n     */\n    const dropDownPosition = ref({\n      horizontal: 'right',\n      vertical: 'bottom',\n    });\n    /**\n     * a variable to add additional styling to the drop-down in case there is not enough space\n     * to handle positioning with css classes - since used for HTML attribute 'style' either an\n     * object with 'transform' property or 'false' so that attribute is not shown\n     * @type {boolean|Object}\n     */\n    const dropDownTransformation = ref(false);\n    /**\n     * function to calculate correct drop down position within window limits\n     */\n    function calculateDropDownPosition() {\n      // check if elements are rendered\n      if (dropDown.value) {\n        // use viewport width instead of window width so element is always in view\n        // even if window is wider than visible frame\n        const windowWidth = window.visualViewport.width;\n        // get drop down position\n        const dropElement = dropDown.value.$el.getBoundingClientRect();\n        // get parent element position\n        const dropAreaPosition = dropArea.value.getBoundingClientRect();\n        // get top, bottom, left, and right position for parent element\n        const dropAreaStart = dropAreaPosition.x;\n        const dropAreaEnd = dropAreaStart + dropAreaPosition.width;\n        const dropAreaTop = dropAreaPosition.y;\n        const dropAreaBottom = dropAreaTop + dropAreaPosition.height;\n\n        // check for left/right position\n        // check if element has space on the right side\n        if (dropAreaStart + dropElement.width >= windowWidth) {\n          // if not check if there is enough space on the left side\n          if (dropAreaEnd - dropElement.width >= 0) {\n            // if yes - position it on the left side\n            dropDownTransformation.value = false;\n            dropDownPosition.value.horizontal = 'left';\n            // if not - try to shift gradually until space used up\n          } else {\n            const moveToLeft = windowWidth - dropAreaStart - dropElement.width;\n            // check if move would put box above window threshold\n            if (dropAreaStart + moveToLeft >= 0) {\n              // if not move the calculated px\n              dropDownTransformation.value = {\n                transform: `translate(${moveToLeft}px, 0px)`,\n              };\n              dropDownPosition.value.horizontal = 'right';\n              // if yes - only move to window border\n            } else {\n              dropDownTransformation.value = {\n                transform: `translate(-${dropAreaStart}px, 0px)`,\n              };\n              dropDownPosition.value.horizontal = 'right';\n            }\n          }\n        } else {\n          // just set element in standard position\n          dropDownTransformation.value = false;\n          dropDownPosition.value.horizontal = 'right';\n        }\n\n        // check for top/bottom position\n        // check if element has enough space on the bottom\n        if (dropAreaBottom + dropElement.height >= window.visualViewport.height) {\n          // if not check if there is enough space on the top\n          if (dropAreaTop - dropElement.height >= 0) {\n            // if yes - position it on the top\n            dropDownPosition.value.vertical = 'top';\n          }\n        } else {\n          // just set element in standard position\n          dropDownPosition.value.vertical = 'bottom';\n        }\n      }\n    }\n\n    /**\n     * adding a debounce function to the recalculation on\n     * resize\n     */\n    const { debounce } = useDebounce();\n    function debounceCalc() {\n      debounce(calculateDropDownPosition, 100);\n    }\n\n    /** listen to window resize so the drop down position can be recalculated */\n    useWindowResize({\n      callback: debounceCalc,\n    });\n    /**\n     * we also need to watch when drop down area is shown so we can calculate\n     * the correct position\n     */\n    watch(dropDown, (val) => {\n      if (val) {\n        calculateDropDownPosition();\n      }\n    });\n    return {\n      dropDown,\n      dropArea,\n      calculateDropDownPosition,\n      dropDownPosition,\n      dropDownTransformation,\n      navigate,\n    };\n  },\n  data() {\n    return {\n      /**\n       * handle hiding and showing of drop down options\n       * @type {boolean}\n       */\n      showOptions: false,\n      /**\n       * the currently active option when navigating via keys\n       * @type {?Object}\n       */\n      activeOption: null,\n    };\n  },\n  computed: {\n    /**\n     * get the primary button - since prop 'primaryButton' can be either a string with the\n     * identifier or the complete object - it is handled here to have the complete object\n     * available for primary button\n     * @returns {Object}\n     */\n    primaryButtonInt() {\n      // check if a primary button was specififed\n      if (this.primaryButton) {\n        // if yes - check if it is an object that can be returned readily or\n        // alternatively search the buttons array for an object with the specified identifier\n        // TODO: what happens if no button with that identifier is found\n        return typeof this.primaryButton === 'object'\n          ? this.primaryButton : this.buttons\n            .find(button => this.primaryButton === button[this.identifierPropertyName]);\n      }\n      // if none was specififed just return the first object of the buttons array\n      return this.buttons[0];\n    },\n    /**\n     * filter the buttons for the primary button to not have it shown double\n     * @returns {Object[]}\n     */\n    buttonsInt() {\n      return this.buttons.filter(button => button[this.identifierPropertyName]\n        !== this.primaryButtonInt[this.identifierPropertyName]);\n    },\n  },\n  watch: {\n    buttonsInt: {\n      handler() {\n        // if buttons changed the drop-down size might have as well - recalculate\n        // the position of the drop-down\n        // this might be obsolete now due to the v-click-outside but still leaving it here in case\n        // there might be any other scenario where drop-down size changes\n        this.calculateDropDownPosition();\n      },\n      deep: true,\n    },\n    showOptions(val) {\n      if (!val) {\n        // reset activeOption on drop down close\n        this.activeOption = null;\n      }\n    },\n  },\n  methods: {\n    /**\n     * function triggered on enter key event\n     */\n    dropDownEnterAction() {\n      // in case there is an active option - inform parent that action\n      // should be triggered\n      if (this.activeOption) {\n        this.fireAction(this.activeOption[this.identifierPropertyName]);\n      } else {\n        // else close drop down\n        this.showOptions = !this.showOptions;\n      }\n    },\n    /**\n     * function triggered on key up or down and tab key\n     * @param {KeyboardEvent} event\n     */\n    navigateOptions(event) {\n      // check if key was up or down or tab back or forth\n      const isArrowDown = event.key === 'ArrowDown'\n        || (event.key === 'Tab' && !event.shiftKey);\n      // get the current index needed for navigate function\n      const currentIndex = this.buttonsInt.indexOf(this.activeOption);\n      // call composable navigate function that returns the new active option\n      this.activeOption = this.navigate(\n        this.buttonsInt,\n        isArrowDown,\n        currentIndex,\n        true,\n      );\n    },\n    /**\n     * function to inform parent that action was triggered (by click or enter)\n     * @param {string} actionType\n     */\n    fireAction(actionType) {\n      // close drop down and reset everything\n      this.showOptions = false;\n      /**\n       * fired upon any button click\n       *\n       * @event clicked\n       * @param {string} - the action (string) that was provided for that button\n       */\n      this.$emit('clicked', actionType);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    v-click-outside=\"() => showOptions = false\"\n    class=\"base-drop-button\">\n    <BaseButton\n      :text=\"primaryButtonInt[labelPropertyName]\"\n      :icon=\"primaryButtonInt.icon || undefined\"\n      icon-size=\"large\"\n      :class=\"{ 'base-drop-button__button__multi': buttonsInt && buttonsInt.length }\"\n      @clicked=\"fireAction(primaryButtonInt[identifierPropertyName])\">\n      <template #left-of-text>\n        <!-- @slot create custom content (e.g. icon) left of text -->\n        <slot name=\"left-of-text\" />\n      </template>\n      <template #right-of-text>\n        <!-- @slot create custom content (e.g. icon) right of text -->\n        <slot name=\"right-of-text\" />\n      </template>\n    </BaseButton>\n    <div\n      v-if=\"buttonsInt && buttonsInt.length\"\n      ref=\"dropAreaEl\"\n      class=\"base-drop-button__options-area\">\n      <button\n        :aria-expanded=\"showOptions\"\n        :aria-label=\"expandButtonLabel\"\n        :class=\"['base-drop-button__toggle-button',\n                 { 'base-drop-button__toggle-button__active': showOptions }]\"\n        type=\"button\"\n        aria-haspopup=\"listbox\"\n        @click.prevent=\"showOptions = !showOptions\"\n        @keydown.enter.prevent=\"dropDownEnterAction\"\n        @keydown.tab=\"activeOption = null\"\n        @keydown.up.down.prevent=\"navigateOptions\">\n        <BaseIcon\n          name=\"drop-down\"\n          :class=\"['base-drop-button__drop-icon',\n                   { 'base-drop-button__drop-icon__rotated': showOptions }]\" />\n      </button>\n      <BaseDropDownList\n        v-if=\"showOptions\"\n        ref=\"dropDownEl\"\n        :drop-down-options=\"buttonsInt\"\n        :active-option=\"activeOption\"\n        :active-styled=\"false\"\n        :style=\"dropDownTransformation\"\n        :aria-activedescendant=\"activeOption ? `button-${activeOption.action}` : undefined\"\n        :identifier-property-name=\"identifierPropertyName\"\n        :label-property-name=\"labelPropertyName\"\n        :class=\"[\n          'base-drop-button__drop-down',\n          `base-drop-button__drop-down__${dropDownPosition.horizontal}`,\n          `base-drop-button__drop-down__${dropDownPosition.vertical}`,\n        ]\">\n        <template #option=\"{ option }\">\n          <button\n            :id=\"`button-${option[identifierPropertyName]}`\"\n            :class=\"[\n              'base-drop-button__action',\n              {\n                'base-drop-button__action__active': activeOption\n                  && option[identifierPropertyName] === activeOption[identifierPropertyName],\n              }]\"\n            type=\"button\"\n            @keydown.up.down.prevent=\"\"\n            @click.prevent=\"fireAction(option[identifierPropertyName])\">\n            <BaseIcon\n              v-if=\"option.icon\"\n              :name=\"option.icon\"\n              class=\"base-drop-button__action-icon\" />\n            <span>{{ option[labelPropertyName] }}</span>\n          </button>\n        </template>\n      </BaseDropDownList>\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n.base-drop-button {\n  position: relative;\n  display: flex;\n  flex-direction: row;\n\n  .base-drop-button__button__multi {\n    box-shadow: inset -1.5px 0 0 0 #{$font-color-second};\n\n    &:hover {\n      --button-header-color: white;\n    }\n  }\n\n  .base-drop-button__options-area {\n    position: relative;\n\n    .base-drop-button__toggle-button {\n      height: 100%;\n      padding: $spacing-small $spacing;\n      background: $background-color;\n      color: inherit;\n      cursor: pointer;\n\n      &.base-drop-button__toggle-button__active,\n      &:hover {\n        background: white;\n      }\n\n      &:hover .base-drop-button__drop-icon,\n      &:focus .base-drop-button__drop-icon,\n      &:active .base-drop-button__drop-icon {\n        color: $app-color;\n        fill: $app-color;\n      }\n\n      .base-drop-button__drop-icon {\n        height: $icon-small;\n        width: $icon-small;\n        transition: $drop-down-arrow-animation;\n\n        &.base-drop-button__drop-icon__rotated {\n          transform: rotate(180deg);\n        }\n      }\n    }\n\n    .base-drop-button__drop-down {\n      background: white;\n\n      .base-drop-button__action {\n        display: flex;\n        align-items: center;\n        min-height: $row-height-small - $spacing-small-half;\n        width: 100%;\n        color: inherit;\n        white-space: nowrap;\n\n        &.base-drop-button__action__active, &:hover, &:focus, &:active {\n          color: $app-color;\n        }\n\n        .base-drop-button__action-icon {\n          height: $icon-medium;\n          width: $icon-medium;\n          max-width: $icon-medium;\n          flex: 0 0 auto;\n          margin-right: $spacing;\n        }\n      }\n\n      &.base-drop-button__drop-down__top {\n        bottom: $row-height-small;\n        box-shadow: 0 -10px 10px 0 rgba(0, 0, 0, 25%);\n      }\n\n      &.base-drop-button__drop-down__bottom {\n        bottom: auto;\n        box-shadow: $drop-shadow;\n      }\n\n      &.base-drop-button__drop-down__left {\n        right: 0;\n      }\n\n      &.base-drop-button__drop-down__right {\n        right: auto;\n      }\n    }\n  }\n}\n</style>\n","<script>\nimport { vOnClickOutside } from '@vueuse/components';\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { computed, ref, toRef, useTemplateRef, watch } from 'vue';\nimport { useId } from '@/composables/useId.js';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\nimport { useDebounce } from '@/composables/useDebounce.js';\n\n/**\n * Accessible drop down component\n */\nexport default {\n  name: 'BaseDropDown',\n  components: {\n    BaseIcon,\n  },\n  directives: {\n    ClickOutside: vOnClickOutside,\n  },\n  props: {\n    /**\n     * specify options to choose from\n     *   needs to be an array with label and value properties\n     */\n    options: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * label for the drop down, recommended to define for accessibility\n     */\n    label: {\n      type: String,\n      default: 'Drop Down',\n    },\n    /**\n     * placeholder appearing in select when no option was\n     * selected\n     */\n    placeholder: {\n      type: String,\n      default: 'Select',\n    },\n    /**\n     * the selected value\n     */\n    modelValue: {\n      type: Object,\n      default: () => ({ value: '', label: '' }),\n    },\n    /**\n     * define if label should be shown\n     */\n    showLabel: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set the background color of drop down head\n     */\n    headerBackgroundColor: {\n      type: String,\n      default: 'inherit',\n    },\n    /**\n     * set a language (ISO 639-1)\n     */\n    language: {\n      type: String,\n      default: '',\n      validator: val => !val || val.length === 2,\n    },\n    /**\n     * set the name of the property that holds the value\n     */\n    valueProp: {\n      type: String,\n      default: 'value',\n    },\n    /**\n     * flag to set drop down inactive\n     */\n    isDisabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * flag to disable spacing left and right\n     * (needed for sidebar drop downs)\n     */\n    withSpacing: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * align drop down with left or right border\n     */\n    alignDropDown: {\n      type: String,\n      default: 'left',\n      validator(val) {\n        return ['left', 'right'].includes(val);\n      },\n    },\n    /**\n     * set id if drop down with this label appears more than once\n     */\n    id: {\n      type: [String, Number],\n      default: '',\n    },\n  },\n  emits: ['update:model-value'],\n  setup(props) {\n    /**\n     * generally get a reference to the root template element\n     * (used for resize observer (fade out calc) and drop down height calc)\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const baseDropDown = useTemplateRef('baseDropDownElement')\n    /** ID HANDLING */\n      // create a persistent id via composable\n    const internalId = useId();\n    // use either the prop provided one or the internally created one\n    const idInt = computed(() => props.id || internalId);\n    /** INTERNATIONALIZATION */\n    const { getLangLabel } = useI18n(toRef(props, 'language'));\n\n    /** RESIZE / FADE OUT HANDLING */\n    /**\n     * template reference to the area available for selected option text display\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const dropDownButton = useTemplateRef('dropDownButtonElement');\n    /**\n     * template reference to the actual selected option text\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const headText = useTemplateRef('headTextElement');\n\n    /**\n     * handle fade out for selected option text showing (if text does not fit)\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const showFadeOut = ref(false);\n\n    /**\n     * calc if the selected option text fits the area available for displaying the text\n     */\n    function setOverflow() {\n      const headerWidth = dropDownButton.value ? dropDownButton.value.getBoundingClientRect().width : 0;\n      const textWidth = headText.value ? headText.value.getBoundingClientRect().width : 0;\n      showFadeOut.value = textWidth > headerWidth;\n    }\n    const { debounce } = useDebounce();\n    useElementObserver({\n      type: 'resize',\n      target: baseDropDown,\n      callback: () => debounce(setOverflow, 50),\n    });\n\n    /** DROP DOWN VISIBILITY & HEIGHT */\n    /**\n     *\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const showDropDown = ref(false);\n    /**\n     *\n     * @type {Ref<UnwrapRef<number>, UnwrapRef<number> | number>}\n     */\n    const maxDropDownHeight = ref(0);\n\n    watch(showDropDown, (val) => {\n      if (val) {\n        // option container element is not rendered yet so we need to calc the\n        // top position from the selected option container\n        const { y, height } = baseDropDown.value.getBoundingClientRect() || {};\n        // make sure the container will not go above space by ceiling the value\n        let dropDownTopPosition = Math.ceil(y + height);\n        // don't let drop-down size be larger than window (also taking into account\n        // virtual keyboard with visualViewport (which should not be present at this\n        // point but just in case)\n        // and also leave a little space to the window bottom\n        let maxHeight = window.visualViewport.height - dropDownTopPosition;\n        // TODO make min and max values configurable?\n        // if remaining space is more than 120px use the remaining space or\n        // max 300px\n        if (maxHeight > 120) {\n          // set the css property `max-height`\n          maxDropDownHeight.value = `${maxHeight > 300 ? 300 : maxHeight - 16}px`;\n          // if there is less than 120px remaining scroll the component into view\n        } else {\n          window.scrollTo(0, baseDropDown.value.offsetTop);\n          // and recalc the remaining space\n          const { y: newY, height: newHeight } = baseDropDown.value.getBoundingClientRect() || {};\n          dropDownTopPosition = Math.ceil(newY + newHeight);\n          maxHeight = window.visualViewport.height - dropDownTopPosition;\n          maxDropDownHeight.value = `${maxHeight > 300 ? 300 : maxHeight - 16}px`;\n          // also consider here that there could STILL be less than 120px remaining and\n          // make this the min\n          maxDropDownHeight.value = `${maxHeight > 300 ? 300 : (maxHeight < 120 ? 120 : maxHeight - 16)}px`;\n        }\n      }\n      // reset index on close\n      if (!val) {\n        keySelectedIndex.value = -1;\n      }\n    });\n\n    /** DROP DOWN NAVIGATION */\n    /**\n     * template reference to the options container\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const dropDownContainer = useTemplateRef('dropDownContainerElement');\n    /**\n     * index of currently active option in keyboard drop down navigation\n     * @type {Ref<UnwrapRef<number>, UnwrapRef<number> | number>}\n     */\n    const keySelectedIndex = ref(-1);\n    return {\n      // root element reference\n      baseDropDown,\n      // id handling\n      idInt,\n      // internationalization\n      getLangLabel,\n      // fade out handling\n      showFadeOut,\n      // drop down handling\n      showDropDown,\n      maxDropDownHeight,\n      dropDownContainer,\n      keySelectedIndex,\n    };\n  },\n  computed: {\n    selectedOptionInt() {\n      return this.getLangLabel(this.modelValue.label, true) || this.placeholder || '';\n    },\n  },\n  methods: {\n    // event triggered by clicking on option or Enter after\n    // selecting via keys\n    selectValue(option) {\n      this.showDropDown = false;\n      /**\n       * Event emitted when an option is selected\n       *\n       * @event update:model-value\n       * @param { Object } - the selected option\n       */\n      this.$emit('update:model-value', option);\n    },\n    // adding key navigation for accessibility\n    selectByKey(event) {\n      const { key } = event;\n      if (key === 'Space') {\n        this.showDropDown = !this.showDropDown;\n      } else if (this.showDropDown && (key === 'ArrowUp' || (event.shiftKey && key === 'Tab'))) {\n        if (this.keySelectedIndex > 0) {\n          this.keySelectedIndex -= 1;\n        }\n      } else if (this.showDropDown && (key === 'ArrowDown' || key === 'Tab')) {\n        if (this.keySelectedIndex < this.options.length - 1) {\n          this.keySelectedIndex += 1;\n        }\n      } else if (key === 'Enter') {\n        if (this.showDropDown && this.keySelectedIndex >= 0) {\n          this.selectValue(this.options[this.keySelectedIndex]);\n        } else {\n          this.showDropDown = !this.showDropDown;\n        }\n      } else if (key === 'Escape') {\n        this.showDropDown = false;\n      }\n      if (this.$refs.option && this.$refs.option[this.keySelectedIndex]\n        && this.dropDownContainer.scrollHeight\n        !== this.dropDownContainer.clientHeight) {\n        this.$refs.option[this.keySelectedIndex].scrollIntoView({ block: 'nearest', inline: 'nearest' });\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    ref=\"baseDropDownElement\"\n    v-click-outside=\"() => showDropDown = false\"\n    class=\"base-drop-down\">\n    <div\n      :class=\"['base-drop-down-label-wrapper',\n               { hide: !getLangLabel(label, true) || !showLabel }]\">\n      <!-- TODO: check if this is correct HTML - label associated with button? -->\n      <!-- eslint-disable-next-line  vuejs-accessibility/label-has-for -->\n      <label\n        :for=\"getLangLabel(label) + '-' + idInt\"\n        class=\"base-drop-down-label\">\n        {{ getLangLabel(label, true) }}\n      </label>\n    </div>\n    <button\n      :id=\"getLangLabel(label) + '-' + idInt\"\n      :aria-expanded=\"String(showDropDown)\"\n      :style=\"{ 'background-color': headerBackgroundColor }\"\n      :disabled=\"isDisabled\"\n      :class=\"['base-drop-down-head', { 'base-drop-down-head-spacing': withSpacing }]\"\n      aria-haspopup=\"listbox\"\n      type=\"button\"\n      @click.prevent=\"showDropDown = !showDropDown\"\n      @keydown.enter.esc.down.up.prevent=\"selectByKey\"\n      @keydown.tab=\"selectByKey\">\n      <div\n        ref=\"dropDownButtonElement\"\n        :class=\"['base-drop-down-head-text-wrapper',\n                 { 'base-drop-down-head-text-fade-out': showFadeOut }]\">\n        <span\n          ref=\"headTextElement\"\n          class=\"base-drop-down-head-text\">\n          {{ selectedOptionInt }}\n        </span>\n      </div>\n      <!-- @slot place elements right of header -->\n      <slot name=\"header-right\">\n        <BaseIcon\n          :class=\"['base-drop-down-icon', { 'base-drop-down-icon-rotated': showDropDown }]\"\n          name=\"drop-down\" />\n      </slot>\n    </button>\n    <div\n      v-if=\"showDropDown\"\n      ref=\"dropDownContainerElement\"\n      :style=\"{ [alignDropDown]: 0, 'max-height': maxDropDownHeight }\"\n      class=\"base-drop-down-body\">\n      <!-- @slot create custom drop down body -->\n      <slot>\n        <ul\n          :aria-labelledby=\"getLangLabel(label) + '-' + idInt\"\n          role=\"listbox\"\n          class=\"base-drop-down-body-list\">\n          <li\n            v-for=\"(option, index) in options\"\n            ref=\"option\"\n            :key=\"option[valueProp]\"\n            :class=\"[\n              'base-drop-down-option',\n              {\n                'base-drop-down-option-selected': modelValue\n                  && option[valueProp] === modelValue[valueProp],\n              },\n              { 'base-drop-down-option-key-selected': keySelectedIndex === index }]\"\n            role=\"option\"\n            :aria-selected=\"(modelValue\n              && option[valueProp] === modelValue[valueProp]).toString()\"\n            tabindex=\"0\"\n            @keydown.enter=\"selectValue(option)\"\n            @keydown.tab=\"selectByKey\"\n            @click=\"selectValue(option)\">\n            {{ getLangLabel(option.label, true) }}\n          </li>\n        </ul>\n      </slot>\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n  @use \"@/styles/variables\" as *;\n\n  .base-drop-down {\n    display: inline-block;\n    position: relative;\n\n    .base-drop-down-label-wrapper {\n      margin-bottom: $spacing-small;\n\n      .base-drop-down-label {\n        color: $font-color-second;\n        margin-bottom: $spacing-small;\n      }\n    }\n\n    .base-drop-down-head {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      height: $row-height-small;\n      width: 100%;\n      line-height: $row-height-small;\n      cursor: pointer;\n      color: $font-color-second;\n      fill: $font-color-second;\n      background-color: $background-color;\n      padding: 0;\n\n      &.base-drop-down-head-spacing {\n        padding: 0 $spacing;\n      }\n\n      .base-drop-down-head-text-wrapper {\n        overflow: hidden;\n        position: relative;\n        margin-right: $spacing;\n        transition: all 0.2s ease;\n        width: 100%;\n        text-align: left;\n\n        .base-drop-down-head-text {\n          white-space: nowrap;\n          text-align: left;\n        }\n\n        &.base-drop-down-head-text-fade-out::after {\n          content: '';\n          height: 100%;\n          width: $fade-out-width;\n          position: absolute;\n          top: 0;\n          right: -1px;\n          background: linear-gradient(to right, rgba(240, 240, 240, 0) , rgba(240, 240, 240, 1));\n        }\n      }\n\n      &:hover {\n        color: $app-color;\n        fill: $app-color;\n      }\n\n      &:active .base-drop-down-icon, &:focus .base-drop-down-icon {\n        fill: $app-color;\n      }\n\n      &:disabled {\n        cursor: default;\n        color: $graytext-color;\n        fill: $graytext-color;\n\n        .base-drop-down-icon {\n          fill: $graytext-color;\n        }\n      }\n\n      .base-drop-down-icon {\n        transition: $drop-down-arrow-animation;\n        height: $icon-small;\n        width: $icon-small;\n        flex-shrink: 0;\n\n        &.base-drop-down-icon-rotated {\n          transform: rotate(180deg);\n        }\n      }\n    }\n\n    .base-drop-down-body {\n      position: absolute;\n      background-color: white;\n      z-index: map.get($zindex, dropdown);\n      box-shadow: $drop-shadow;\n      max-height: 300px;\n      max-width: calc(100vw - 3 * #{$spacing});\n      min-width: 100%;\n      min-height: 0;\n      overflow-y: auto;\n      overflow-x: hidden;\n      cursor: pointer;\n\n      .base-drop-down-body-list {\n\n        .base-drop-down-option {\n          min-height: $row-height-small;\n          padding: $spacing-small-half $spacing;\n          line-height: $line-height;\n          width: 100%;\n          transition: all 0.2s ease;\n\n          &.base-drop-down-option-selected {\n            color: $app-color;\n          }\n\n          &:hover, &.base-drop-down-option-key-selected {\n            background-color: $button-header-color;\n          }\n        }\n      }\n    }\n  }\n</style>\n","<script setup>\nimport { ref, useTemplateRef, watch } from 'vue';\nimport { useAnnouncer } from '@/composables/useAnnouncer.js';\n\n/**\n * Minimal loader component to be reused in other components\n */\n\ndefineOptions({\n  name: 'BaseLoader',\n});\n\nconst props = defineProps({\n  /**\n   * define a color for the loader\n   */\n  loaderColor: {\n    type: String,\n    default: '',\n  },\n  /**\n   * add positional properties like for a style object\n   */\n  position: {\n    type: Object,\n    default: () => ({}),\n  },\n  /**\n   * set this to `true` if you want to keep element (with height and width) but dont\n   * want the loader to show\n   */\n  hide: {\n    type: Boolean,\n    default: false,\n  },\n  /**\n   * define a text that should be read as soon as loader appears\n   */\n  textOnLoaderShow: {\n    type: String,\n    default: 'loading',\n  },\n});\n\n/**\n * set up a reference to the element to be able to attach the announcements element\n * @type {Readonly<ShallowRef<HTMLElement | null>>}\n */\nconst loader = useTemplateRef('loaderElement');\n/**\n * timeout variable to only set announcement after a certain time passed\n * @type {Ref<null|number>}\n */\nconst timeout = ref(null);\n/**\n * insert an HTML element with aria-live assertive that will announce the\n * loading process\n */\nconst { announcement } = useAnnouncer(loader);\n\n/**\n * function called on changes to the loader element or prop `hide`\n * announcing the text set in prop `textOnLoaderShow`\n */\nfunction setLoaderAnnouncement() {\n  // first check if loader is now present and not hidden\n  if (loader.value && !props.hide) {\n    // if so need to be working with a timeout here so the announcement\n    // is not overwritten by later actions\n    if (timeout.value) {\n      clearTimeout(timeout.value);\n      timeout.value = null;\n    }\n    timeout.value = setTimeout(() => {\n      // now check again if element is still visible\n      if (loader.value && !props.hide) {\n        // if yes - make loading announcement\n        announcement.value = props.textOnLoaderShow;\n      }\n    }, 1000);\n  }\n}\n\n// watch the element to add the text as soon as it is rendered either from\n// component rendering or prop `hide` becoming `false`\nwatch([loader, () => props.hide], () => {\n  setLoaderAnnouncement();\n});\n</script>\n\n<template>\n  <div\n    ref=\"loaderElement\"\n    :style=\"{ ...position, ...{ '--loader-color': loaderColor || 'unset' } }\"\n    class=\"base-loader\">\n    <svg\n      v-if=\"!hide\"\n      class=\"base-loader-circular\">\n      <circle\n        class=\"base-loader-path\"\n        cx=\"50\"\n        cy=\"50\"\n        r=\"20\"\n        fill=\"none\"\n        stroke-width=\"4\"\n        stroke-miterlimit=\"10\" />\n    </svg>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n  .base-loader{\n    position: absolute;\n    width: 100px;\n    height: 100px;\n    top: 20%;\n    left: 50%;\n    transform: translate(-50%,-50%);\n    overflow: hidden;\n\n    .base-loader-circular{\n      animation: rotate 2s linear infinite;\n      height: 100px;\n      position: relative;\n      width: 100px;\n\n      .base-loader-path {\n        stroke-dasharray: 1,200;\n        stroke-dashoffset: 0;\n        animation:\n          dash 1.5s ease-in-out infinite;\n        stroke: var(--loader-color, $app-color);\n        color: var(--loader-color, $app-color);\n      }\n    }\n  }\n\n  @keyframes rotate{\n    100%{\n      transform: rotate(360deg);\n    }\n  }\n\n  @keyframes dash{\n    0%{\n      stroke-dasharray: 1,200;\n      stroke-dashoffset: 0;\n    }\n    50%{\n      stroke-dasharray: 89,200;\n      stroke-dashoffset: -35;\n    }\n    100%{\n      stroke-dasharray: 89,200;\n      stroke-dashoffset: -124;\n    }\n  }\n</style>\n","<script>\nimport BaseButton from '@/components/BaseButton/BaseButton.vue';\nimport BaseLoader from '@/components/BaseLoader/BaseLoader.vue';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { useElementFadeOut } from '@/composables/useElementFadeOut.js';\nimport { useTemplateRef } from 'vue';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\n\nexport default {\n  name: 'BaseEditControl',\n  components: {\n    BaseButton,\n    BaseLoader,\n  },\n  props: {\n    /**\n     * toggle control buttons\n     */\n    controls: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * disable edit button\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set edit mode\n     */\n    edit: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * flag to set if loader should be shown (for autocomplete requests\n     */\n    isLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define title\n     */\n    title: {\n      type: String,\n      default: 'Title',\n    },\n    /**\n     * define subtitle\n     */\n    subtitle: {\n      type: String,\n      default: '',\n    },\n    /**\n     * render title as e.g.: 'h2' | 'h3'\n     */\n    renderTitleAs: {\n      type: String,\n      default: 'h2',\n    },\n    /**\n     * define button text.\n     * could be string or path to i18n json as well\n     */\n    editButtonText: {\n      type: String,\n      default: 'Edit',\n    },\n    /**\n     * define button text.\n     * could be string or path to i18n json as well\n     */\n    cancelButtonText: {\n      type: String,\n      default: 'Cancel',\n    },\n    /**\n     * define button text.\n     * could be string or path to i18n json as well\n     */\n    saveButtonText: {\n      type: String,\n      default: '',\n    },\n    /**\n     * decide on buttons presented in edit mode.\n     *  **save**: element has a 'save' and 'cancel' button\n     *  **done**: element solely has a 'done' button. this button is also emitting\n     *    a `saved` event when clicked and uses the `saveButtonText`\n     */\n    editMode: {\n      type: String,\n      default: 'save',\n      validator: val => ['save', 'done'].includes(val),\n    },\n  },\n  emits: ['saved', 'canceled', 'activated'],\n  setup() {\n    /** INTERNATIONALIZATION */\n    const { getI18nTerm } = useI18n();\n\n    /** TITLE LINE FADE OUT */\n    const titleLine = useTemplateRef('titleLineElement');\n    const { boxFadeOut, calcFadeOut } = useElementFadeOut(titleLine, {\n      direction: 'horizontal',\n      // TODO: refactor to use build in classes and pseudo elements\n      className: '',\n    });\n\n    // also consider the title text (or subtext changing) in fade out calc\n    useElementObserver({\n      type: 'mutation',\n      target: titleLine,\n      callback: calcFadeOut,\n      options: {\n        characterData: true,\n        subtree: true,\n      },\n      callOnMount: true,\n    });\n\n    return {\n      getI18nTerm,\n      boxFadeOut,\n    };\n  },\n  computed: {\n    /**\n     * set icon depending on editMode\n     * @returns {string}\n     */\n    saveButtonIcon() {\n      if (this.isLoading) {\n        return '';\n      }\n      return this.editMode === 'done' ? 'check-mark' : 'save-file';\n    },\n    /**\n     * set default save button text depending on editMode\n     * @returns {string}\n     */\n    saveButtonTextInt() {\n      return this.saveButtonText || (this.editMode === 'done' ? 'Done' : 'Save');\n    },\n  },\n  watch: {\n    edit: {\n      handler(val) {\n        if (val) {\n          window.addEventListener('keyup', this.escEventHandler);\n        } else {\n          window.removeEventListener('keyup', this.escEventHandler);\n        }\n      },\n    },\n  },\n  methods: {\n    activate(event) {\n      /**\n       * event emitted by click on edit button\n       *\n       * @event activated\n       * @param {PointerEvent} - the native pointer event\n       */\n      this.$emit('activated', event);\n    },\n    cancel(event) {\n      /**\n       * event emitted by click on cancel button\n       * @event canceled\n       * @param {PointerEvent} - the native pointer event\n       */\n      this.$emit('canceled', event);\n    },\n    save(event) {\n      /**\n       * event emitted by click on save button\n       * @event saved\n       * @param {PointerEvent} - the native pointer event\n       */\n      this.$emit('saved', event);\n    },\n    /**\n     * intercept escape key event and reset edit mode\n     */\n    escEventHandler(e) {\n      if (e.key === 'Escape') {\n        this.cancel();\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    class=\"base-edit-control\">\n    <component\n      :is=\"renderTitleAs\"\n      v-if=\"title\"\n      ref=\"titleLineElement\"\n      :class=\"['base-edit-control__title',\n               { 'base-text-fade-out-background': boxFadeOut.right }]\">\n      <!-- @slot title slot -->\n      <slot>\n        {{ title }}\n        <span\n          v-if=\"subtitle\"\n          class=\"base-edit-control__title__additional\">\n          {{ subtitle }}\n        </span>\n      </slot>\n    </component>\n\n    <div\n      v-if=\"controls\"\n      class=\"base-edit-control__buttons\">\n      <BaseButton\n        v-if=\"!edit\"\n        :disabled=\"disabled\"\n        :has-background-color=\"false\"\n        :icon=\"!isLoading ? 'edit' : ''\"\n        :text=\"getI18nTerm(editButtonText)\"\n        class=\"base-edit-control__button\"\n        @clicked=\"activate\">\n        <template\n          v-if=\"isLoading\"\n          #left-of-text>\n          <span class=\"base-edit-control__loader\">\n            <BaseLoader />\n          </span>\n        </template>\n      </BaseButton>\n\n      <BaseButton\n        v-if=\"edit\"\n        :disabled=\"disabled\"\n        :has-background-color=\"false\"\n        :icon=\"saveButtonIcon\"\n        :text=\"getI18nTerm(saveButtonTextInt)\"\n        class=\"base-edit-control__button\"\n        @clicked=\"save\">\n        <template\n          v-if=\"isLoading\"\n          #left-of-text>\n          <span class=\"base-edit-control__loader\">\n            <BaseLoader />\n          </span>\n        </template>\n      </BaseButton>\n\n      <BaseButton\n        v-if=\"editMode === 'save' && edit\"\n        :has-background-color=\"false\"\n        icon=\"remove\"\n        :text=\"getI18nTerm(cancelButtonText)\"\n        class=\"base-edit-control__button\"\n        @clicked=\"cancel\" />\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-edit-control {\n    display: flex;\n    align-items: center;\n    justify-content: flex-end;\n    min-height: $row-height-small;\n\n    &__title {\n      flex-grow: 1;\n      justify-self: flex-start;\n      margin-bottom: 0;\n      white-space: nowrap;\n      overflow: hidden;\n      position: relative;\n      z-index: 0;\n\n      &__additional {\n        font-weight: normal;\n        font-size: $font-size-small;\n        color: $font-color-second;\n      }\n    }\n\n    &__buttons {\n      display: flex;\n      align-items: center;\n    }\n\n    &__button {\n      &:last-of-type {\n        padding-right: 0;\n        transition-property: color;\n      }\n    }\n\n    &__loader {\n      position: relative;\n      margin-right: $spacing;\n      transform: scale(0.45);\n      /* adjusted for 'save-file' icon */\n      top: 2px;\n      height: 12px;\n      width: 12px;\n    }\n  }\n</style>\n","<script>\nimport { defineAsyncComponent, ref, toRef, useTemplateRef, watch } from 'vue';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { useElementObserver, useEventListener } from '@/composables';\n\n/**\n * Component to select elements from a list, including search, options and pagination elements.\n */\n\nexport default {\n  name: 'BaseEntrySelector',\n  components: {\n    BaseDropDown: defineAsyncComponent(() => import('@/components/BaseDropDown/BaseDropDown.vue')),\n    BaseLoader: defineAsyncComponent(() => import('@/components/BaseLoader/BaseLoader.vue')),\n    BaseMenuList: defineAsyncComponent(() => import('@/components/BaseMenuList/BaseMenuList.vue')),\n    BaseOptions: defineAsyncComponent(() => import('@/components/BaseOptions/BaseOptions.vue')),\n    BasePagination: defineAsyncComponent(() => import('@/components/BasePagination/BasePagination.vue')),\n    BaseSearch: defineAsyncComponent(() => import('@/components/BaseSearch/BaseSearch.vue')),\n    BaseSelectOptions: defineAsyncComponent(() => import('@/components/BaseSelectOptions/BaseSelectOptions.vue')),\n  },\n  props: {\n    /**\n     * list of entries to display. Unless the slot `entries` is used this should be an object with\n     * properties compatible with [BaseMenuList](BaseMenuList) `list` object array\n     */\n    entries: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * provide the total number of entries for pagination calculations\n     */\n    entriesTotal: {\n      type: Number,\n      default: null,\n    },\n    /**\n     * number of entries per page (this does not steer the number of entries displayed.\n     * (the correct number needs to be provided by `entries`) but is solely\n     * needed for correct pagination calculations)\n     */\n    entriesPerPage: {\n      type: Number,\n      default: 10,\n    },\n    /**\n     * define if entries are selectable - thus if checkboxes are available\n     */\n    entriesSelectable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify a maximum number of entries that can be selected.\n     * specify `0` if there should be no limit\n     */\n    maxSelectedEntries: {\n      type: Number,\n      default: 0,\n    },\n    /**\n     * specify a custom height - mainly useful if component is within a pop-up.\n     * Use a valid CSS height property value.\n     */\n    height: {\n      type: String,\n      default: '',\n    },\n    /**\n     * flag to set if loader should be shown (for fetch requests)\n     */\n    isLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify the index of an entry to be marked active (color border on left side).\n     */\n    activeEntry: {\n      type: Number,\n      default: -1,\n    },\n    /**\n     * specify a language (ISO 639-1) (used for label if label is language specific object\n     * e.g. `{ de: 'xxx', en: 'yyy' }`)\n     */\n    language: {\n      type: String,\n      default: 'en',\n    },\n    /**\n     * hide options completely (necessary if only before or after slot elements should remain)\n     * if the complete options row should be hidden set `showOptionsRow` to `false` instead!\n     */\n    optionsHidden: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define options to filter entries\n     * structure e.g.: `[{ label: { de: \"Alle Typen\", en: \"All Types\" }, source: \"\" }]`\n     */\n    entryTypes: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * specify config options for your sorting drop down element (if `sortOptions` are\n     * provided).\n     * Needs to be an object with the following properties:\n     *  **label** `string` - specify a label for the sort options drop down (purely for accessibility purposes)\n     *  **default** `?Object` - specify a default option that the dropdown is initialized with.\n     *    this needs to have the same object structure as the objects in `entryTypes`.\n     *    if no default is provided the first option in the list will be selected.\n     *  **valuePropertyName** `string` - specify the name of the property that contains a unique value\n     */\n    entryTypesConfig: {\n      type: Object,\n      default: () => ({\n        label: 'filter by type',\n        default: null,\n        valuePropertyName: 'value',\n      }),\n      validator: value => !value || ['label', 'default', 'valuePropertyName']\n        .every(key => Object.keys(value).includes(key)),\n    },\n    /**\n     * define options for sorting entries.\n     * structure e.g: `[{ label: 'By Type', value: 'type_en' }]`\n     */\n    sortOptions: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * specify config options for your sorting drop down element (if `sortOptions` are\n     * provided).\n     * Needs to be an object with the following properties:\n     *  **label** `string` - specify a label for the sort options drop down (purely for accessibility purposes)\n     *  **default** `?Object` - specify a default option that the dropdown is initialized with.\n     *    this needs to have the same object structure as the objects in `entryTypes`.\n     *    if no default is provided the first option in the list will be selected.\n     *  **valuePropertyName** `string` - specify the name of the property that contains a unique value\n     */\n    sortConfig: {\n      type: Object,\n      default: () => ({\n        label: 'sort entries',\n        default: null,\n        valuePropertyName: 'value',\n      }),\n      validator: value => !value || Object.keys(value).every(key => [\n        'label', 'default', 'valuePropertyName'].includes(key)),\n    },\n    /**\n     * specify informational texts for the component (especially helpful to provide language\n     * specific text) - this needs to be an object with the following\n     * properties (if you don't want to display any text leave an empty string):\n     *\n     *     **noEntriesTitle**: Header text shown if search for string returned no results.\n     *     **noEntriesSubtext**: subtext shown if search for string returned no result.\n     *     **options**: Text for title button.\n     *        This needs to be an object containing a `show` and `hide` property that are shown when\n     *        `entriesSelectable` is `true` or `false` respectively.\n     *     **search**: placeholder in search input field.\n     *     **selectAll**: Text for 'Select All' button.\n     *     **selectNone**: Text for 'Select None' button.\n     *     **entriesSelected**: Text for number of entries (x) selected. information displayed as\n     *      `x {provided text}`.\n     *\n     *  The values of this object might be plain string or a key for an i18n file (in case it is not\n     *  an object that is required! - in that case the above applies to the values within that\n     *  object)\n     */\n    entrySelectorText: {\n      type: Object,\n      default: () => ({\n        noEntriesTitle: 'No matching entries found',\n        noEntriesSubtext: 'Please adjust your search criteria.',\n        options: {\n          show: 'options',\n          hide: 'options',\n        },\n        search: 'Search',\n        selectAll: 'Select All',\n        selectNone: 'Select None',\n        entriesSelected: 'entries selected',\n        maxEntriesReached: 'Maximum Number Exceeded!',\n      }),\n      // checking if all necessary properties are part of the provided object\n      validator: val => [\n          'noEntriesTitle',\n          'noEntriesSubtext',\n          'options',\n          'search',\n          'selectAll',\n          'selectNone',\n          'entriesSelected',\n          'maxEntriesReached',\n        ]\n          .every(prop => Object.keys(val).includes(prop))\n        && ['show', 'hide'].every(requiredProp => Object.keys(val.options).includes(requiredProp)),\n    },\n    /**\n     * define if search field should be shown.\n     * this will have no effect if `head` slot is used.\n     */\n    useSearch: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * this will remove the complete row between search and entries list.\n     * This means also the slots `options` and `afterOptions` are not available anymore!\n     * (if only the options menu should be hidden use `optionsHidden` instead)\n     */\n    showOptionsRow: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * make the single menu list items draggable\n     */\n    useDraggable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * this prop gives the option to add assistive text for screen readers.\n     * properties:\n     * **loaderActive**: text that is announced when results are being fetched (prop\n     *  `isLoading` is set `true`)\n     * **clearInput**: text read for remove input icon if prop `clearable` is set `true`\n     * **resultsFound**: provide text that should be announced when the search has\n     *  yielded results. Adding the string '{number}' will announce the total number\n     *  of results found\n     * **noResultsFound**: provide text that should be announced when no search results\n     *  were round\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        resultsFound: '{number} Results found.',\n        noResultsFound: 'No results found.',\n        loaderActive: 'Loading.',\n        clearInput: 'Clear input',\n      }),\n    },\n    /**\n     * this prop gives the option to add assistive text for the pagination:\n     *\n     *   **currentPage**: aria-label for the current page\n     *   **nextPage**: aria-label for the next page\n     *   **pagination**: aria-label for the pagination element description\n     *   **previousPage**: aria-label for the previous page\n     *   **toPage**: aria-label for all page buttons except the current one\n     *\n     * The values of this object might be plain text or a key for an i18n file\n     */\n    paginationAssistiveText: {\n      type: Object,\n      default: () => ({\n        currentPage: 'Current Page, Page',\n        nextPage: 'Go to next page',\n        pagination: 'Pagination',\n        previousPage: 'Go to previous page',\n        toPage: 'Go to page',\n      }),\n      // checking if all necessary properties are part of the provided object\n      validator: val => ['currentPage', 'nextPage', 'pagination', 'previousPage', 'toPage']\n        .every(prop => Object.keys(val).includes(prop)),\n    }\n  },\n  emits: ['entry-clicked', 'fetch-entries', 'selected-changed', 'update:entries-selectable'],\n  setup(props) {\n    /** INTERNATIONALIZATION */\n    const { getI18nTerm } = useI18n(toRef(props, 'language'));\n\n    /** LIST FADE OUT */\n    const bodyEl = useTemplateRef('body');\n    const headHasShadow = ref(false);\n    const bottomHasShadow = ref(false);\n    function scroll() {\n      headHasShadow.value = bodyEl.value.scrollTop !== 0;\n      bottomHasShadow.value = bodyEl.value.clientHeight + bodyEl.value.scrollTop < bodyEl.value.scrollHeight;\n    }\n\n    useEventListener({\n      target: bodyEl,\n      event: 'scroll',\n      callback: scroll,\n      callOnMounted: true,\n    });\n\n    useElementObserver({\n      type: 'resize',\n      target: bodyEl,\n      callback: scroll,\n    });\n\n    /**\n     * on firefox resize observer is not always triggered when entries change\n     * so we need an additional watcher on entries\n     */\n    watch(() => props.entries, () => {\n      // wait until all calc / rendering is done\n      setTimeout(() => scroll('Timeout'), 0);\n    });\n\n    return {\n      getI18nTerm,\n      bodyEl,\n      headHasShadow,\n      bottomHasShadow,\n    };\n  },\n  data() {\n    return {\n      /**\n       * variable to store filter text entered into search\n       * @type {string}\n       */\n      filterString: '',\n      /**\n       * variable to store selected filter type\n       * @type {Object}\n       */\n      filterType: {},\n      /**\n       * variable to store selected sort option\n       * @type {Object}\n       */\n      sortParam: {},\n      pageNumber: 1,\n      showOptions: false,\n      // TODO: eventually it would make sense to have selected entries settable from outside\n      selectedEntries: [],\n      /**\n       * timeout to prevent triggering of search after every key stroke\n       * @type {?number}\n       * TODO: eventually this should be kept in front end to give more individual control to\n       * component users\n       */\n      timeout: null,\n      /**\n       * variable to remember if page changed when entries are updated (to set the focus\n       * to first entry after page change)\n       */\n      pageChanged: false,\n      /**\n       * manage the announcement of found results\n       * @type {string}\n       */\n      resultsAnnouncement: '',\n    };\n  },\n  computed: {\n    /**\n     * create object for the element style attribute\n     * @returns {Object}\n     */\n    calcStyle() {\n      return this.height ? { height: this.height } : {};\n    },\n    /**\n     * calculate page total for pagination from available numbers\n     * @returns {number}\n     */\n    pageTotal() {\n      return this.entriesPerPage ? Math.ceil(this.entriesTotal / this.entriesPerPage) : 0;\n    },\n    /**\n     * BaseMenuList components needs a list of unique IDs for selected entries\n     * @returns {string[]}\n     */\n    selectedListIds() {\n      // deduplicate by creating set and convert back to array\n      return [...new Set(this.selectedEntries.map(entry => entry.id))];\n    },\n    /**\n     * to calc the correct max-with for the sort and type drop downs we need to know how\n     * many there are\n     * @type {number}\n     */\n    dropDownElementsCount() {\n      if (this.sortOptions && this.sortOptions.length\n        && this.entryTypes && this.entryTypes.length) {\n        return 2;\n      }\n      return 1;\n    },\n    /**\n     * filter entries which are not disabled\n     *\n     * @returns {Object[]}\n     */\n    selectableEntries() {\n      return this.entries.filter(entry => !entry.disabled);\n    },\n  },\n  watch: {\n    /**\n     * watch if entries are updated to set the focus on the first list\n     * element\n     */\n    entries: {\n      handler() {\n        // check if the menu list exist already (which it should on page\n        // change) and if change was triggered by changing the page\n        if (this.$refs.menuList && this.pageChanged) {\n          // wait until the elements are rendered\n          this.$nextTick(() => {\n            // then depending on if select input is shown or not\n            const firstFocusableListElement = this.showOptions\n              // get the first select input element\n              ? this.$refs.menuList.$el.querySelector('input:enabled')\n              // or the first menu entry element (that has tabindex 0 set)\n              : this.$refs.menuList.$el.querySelector('*[tabindex]:not([tabindex=\"-1\"])');\n            // check if an element was found\n            if (firstFocusableListElement) {\n              // if yes - focus\n              firstFocusableListElement.focus();\n            }\n          });\n        }\n        // reset pageChanged flag\n        this.pageChanged = false;\n        // announce that entries have changed\n        const announcementTextKey = this.entriesTotal ? 'resultsFound' : 'noResultsFound';\n        // safeguard against text not existing\n        if (this.assistiveText[announcementTextKey]) {\n          this.resultsAnnouncement = this.assistiveText[announcementTextKey]\n            .replace('{number}', this.entriesTotal);\n        }\n        // and reset afterward so the same text would trigger the watcher again\n        setTimeout(() => {\n          this.resultsAnnouncement = '';\n        }, 300);\n      },\n      deep: true,\n    },\n    /**\n     * watch outside variable to have it in sync with internal 'showOptions'\n     */\n    entriesSelectable: {\n      handler(val) {\n        if (val !== this.showOptions) {\n          this.showOptions = val;\n        }\n      },\n      immediate: true,\n    },\n    showOptions(val) {\n      // delete selected when options menu is closed and reset select all\n      if (!val) {\n        this.selectedEntries = [];\n      }\n      if (val !== this.entriesSelectable) {\n        /**\n         * emit event to inform parent about toggle triggered and keep prop variable\n         * `entriesSelectable` in sync\n         * @event update:entries-selectable\n         * @param {boolean} - are entries selectable\n         */\n        this.$emit('update:entries-selectable', this.showOptions);\n      }\n    },\n    /**\n     * watch selectedEntries to inform parent of changes in selection\n     */\n    selectedEntries: {\n      handler() {\n        /**\n         * event emitted every time the selected entries change\n         * @event selected-changed\n         * @param {Object[]} - array of updated selected entries\n         */\n        this.$emit('selected-changed', this.selectedEntries);\n      },\n      deep: true,\n    },\n  },\n  created() {\n    // set the default option for the drop down menus\n    this.sortParam = this.sortConfig.default\n      || (this.sortOptions.length ? this.sortOptions[0] : {});\n    this.filterType = this.entryTypesConfig.default\n      || (this.entryTypes.length ? this.entryTypes[0] : {});\n  },\n  mounted() {\n    // fetch initial entries\n    this.fetchEntries();\n  },\n  methods: {\n    /**\n     * select all or none entries\n     *\n     * @param {Boolean} selected\n     */\n    changeAllSelectState(selected) {\n      if (selected) {\n        // add all visible entries to selected list\n        this.selectedEntries = this.selectedEntries.concat(this.selectableEntries);\n        // deduplicate by creating set and convert back to array\n        this.selectedEntries = [...new Set(this.selectedEntries)];\n      } else {\n        const entriesIds = this.entries.map(entry => entry.id);\n        this.selectedEntries = this.selectedEntries\n          .filter(entry => !entriesIds.includes(entry.id));\n      }\n    },\n    fetchEntries() {\n      if (this.timeout) {\n        clearTimeout(this.timeout);\n        this.timeout = null;\n      }\n      this.timeout = setTimeout(() => {\n        /**\n         * Event emitted to fetch entries\n         *\n         * @event fetch-entries\n         * @property {string} page - current pagination page\n         * @property {string} query - the search string\n         * @property {object} sort - the sort filter\n         * @property {object} type - the type filter\n         */\n        this.$emit('fetch-entries', {\n          page: this.pageNumber,\n          query: this.filterString,\n          sort: this.sortParam,\n          type: this.filterType,\n        });\n      }, 600);\n    },\n    filterEntries(value, type) {\n      if (type === 'type') {\n        this.fetchEntries();\n      } else if (type === 'title') {\n        if (this.timeout) {\n          clearTimeout(this.timeout);\n          this.timeout = null;\n        }\n        this.timeout = setTimeout(() => {\n          if (value.length === 0 || value.length > 2) {\n            this.fetchEntries();\n          }\n        }, 600);\n      }\n      this.pageNumber = 1;\n    },\n    /**\n     * function to trigger from slot `entries` when an entry was selected\n     * @param {Object} obj - selected entry\n     * @property {boolean} obj.selected - variable indicating if entry was selected or deselected\n     * @property {string} obj.index - the index of the selected or deselected entry in 'entries'\n     * @public\n     */\n    selectEntry(obj) {\n      if (obj.selected) {\n        this.selectedEntries.push(this.entries[obj.index]);\n      } else {\n        this.selectedEntries = this.selectedEntries\n          .filter(entry => entry.id !== this.entries[obj.index].id);\n      }\n    },\n    setPage(number) {\n      this.pageChanged = true;\n      this.pageNumber = number;\n      this.fetchEntries();\n    },\n    entryClicked(index) {\n      /**\n       * Triggered when the entry is clicked\n       *\n       * @event entry-clicked\n       * @param {string} - the id of the clicked entry\n       */\n      this.$emit('entry-clicked', this.entries[index].id);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    :style=\"calcStyle\"\n    class=\"base-entry-selector\">\n    <!-- HEAD -->\n    <div\n      ref=\"head\"\n      :class=\"['base-entry-selector__head',\n               { 'base-entry-selector__head--padding': useSearch }]\">\n      <!-- @slot per default this element contains the search element of the component. Use this slot to replace it with your own elements -->\n      <slot name=\"head\">\n        <!-- default -->\n        <BaseSearch\n          v-if=\"useSearch\"\n          v-model=\"filterString\"\n          :show-image=\"true\"\n          :placeholder=\"getI18nTerm(entrySelectorText.search)\"\n          :assistive-text=\"{\n            loaderActive: assistiveText.loaderActive,\n            clearInput: assistiveText.clearInput,\n            results: resultsAnnouncement,\n          }\"\n          :class=\"['base-entry-selector__head__search-bar',\n                   { 'base-entry-selector__head__search-bar--margin-large': !showOptionsRow && !showOptions }]\"\n          @update:model-value=\"filterEntries($event, 'title')\" />\n      </slot>\n\n      <!-- BASE OPTIONS ROW -->\n      <div\n        v-if=\"showOptionsRow\"\n        class=\"base-entry-selector__options\">\n        <BaseOptions\n          ref=\"baseOptions\"\n          v-model:show-options=\"showOptions\"\n          :options-hidden=\"optionsHidden\"\n          :use-options-button-on=\"'always'\"\n          :show-after-options-below=\"true\"\n          :options-button-icon=\"{\n            show: 'options-menu',\n            hide: 'options-menu',\n          }\"\n          :options-button-text=\"entrySelectorText.options\"\n          align-options=\"left\">\n          <template\n            #afterOptions>\n            <div\n              class=\"base-entry-selector__dropdowns\">\n              <!-- @slot to add custom elements at the end of the options row, e.g. custom drop downs -->\n              <slot name=\"after-options\">\n                <!-- default -->\n                <BaseDropDown\n                  v-if=\"sortOptions.length\"\n                  :id=\"`${sortConfig.label}-sort-drop-down`\"\n                  ref=\"baseDropDown\"\n                  v-model=\"sortParam\"\n                  :label=\"sortConfig.label\"\n                  :options=\"sortOptions\"\n                  :with-spacing=\"false\"\n                  :align-drop-down=\"entryTypes.length ? 'left' : 'right'\"\n                  :style=\"{ maxWidth: `${100 / dropDownElementsCount}%` }\"\n                  :value-prop=\"sortConfig.valuePropertyName\"\n                  class=\"base-entry-selector__dropdowns__dropdown\"\n                  @update:model-value=\"fetchEntries\" />\n                <BaseDropDown\n                  v-if=\"entryTypes.length\"\n                  :id=\"`${entryTypesConfig.label}-types-drop-down`\"\n                  ref=\"baseDropDown\"\n                  v-model=\"filterType\"\n                  :label=\"entryTypesConfig.label\"\n                  :options=\"entryTypes\"\n                  :language=\"language\"\n                  :with-spacing=\"false\"\n                  :style=\"{ maxWidth: `${100 / dropDownElementsCount}%` }\"\n                  :value-prop=\"entryTypesConfig.valuePropertyName\"\n                  align-drop-down=\"right\"\n                  class=\"base-entry-selector__dropdowns__dropdown\"\n                  @update:model-value=\"filterEntries($event, 'type')\" />\n              </slot>\n            </div>\n          </template>\n          <template\n            #options>\n            <!-- @slot add custom action (buttons) -->\n            <slot name=\"option-actions\" />\n          </template>\n        </BaseOptions>\n      </div>\n      <!-- SELECTOR OPTIONS -->\n      <BaseSelectOptions\n        v-if=\"showOptions\"\n        ref=\"selectOptions\"\n        :select-text=\"getI18nTerm(entrySelectorText.selectAll)\"\n        :selected-number-text=\"getI18nTerm(entrySelectorText.entriesSelected)\"\n        :deselect-text=\"getI18nTerm(entrySelectorText.selectNone)\"\n        :list=\"selectableEntries\"\n        :selected-list=\"selectedEntries\"\n        :select-all-disabled=\"!!maxSelectedEntries\n          && (!(selectableEntries.length < (maxSelectedEntries - selectedListIds.length)\n            || !selectableEntries.some((entry) => !selectedListIds.includes(entry.id))))\"\n        @selected=\"changeAllSelectState\">\n        <template #selectedText>\n          {{ `${selectedListIds.length}${(maxSelectedEntries ? `/${maxSelectedEntries}` : '')}\n          ${getI18nTerm(entrySelectorText.entriesSelected)}` }}\n          <span\n            v-if=\"!!maxSelectedEntries && selectedListIds.length >= maxSelectedEntries\">\n            {{ `(${getI18nTerm(entrySelectorText.maxEntriesReached)})` }}\n          </span>\n        </template>\n      </BaseSelectOptions>\n    </div>\n\n    <!-- BODY -->\n    <div\n      class=\"base-entry-selector__body-wrapper\">\n      <div\n        :class=\"['base-entry-selector__body-shadow', { 'base-entry-selector__body-shadow--top': headHasShadow }]\" />\n      <div\n        :class=\"['base-entry-selector__body-shadow', { 'base-entry-selector__body-shadow--bottom': bottomHasShadow }]\" />\n      <div\n        ref=\"body\"\n        class=\"base-entry-selector__body\">\n        <div\n          v-if=\"isLoading\"\n          class=\"loading-area\">\n          <BaseLoader\n            :text-on-loader-show=\"assistiveText.loaderActive\"\n            :class=\"{ 'base-entry-selector__loader__center': entries.length < 4 }\" />\n        </div>\n        <!-- @slot the component [BaseMenuList](BaseMenuList) is used per default to display the list of entries - if something different is required use this slot.\n            @binding {Object[]} entries - list of entries to display\n            @binding {Function} select-entry - function to trigger when entry was selected - takes two arguments: @property **index** `number`: the index of the element in the entries list. **selected** `boolean`: if element was selected or deselected\n            -->\n        <slot\n          name=\"entries\"\n          :entries=\"entries\"\n          :select-entry=\"selectEntry\">\n          <!-- default -->\n          <BaseMenuList\n            v-if=\"entries.length\"\n            key=\"menu-list\"\n            ref=\"menuList\"\n            :select-active=\"showOptions\"\n            :list=\"entries\"\n            :active-entry=\"activeEntry\"\n            :selected-list=\"selectedListIds\"\n            :use-draggable=\"useDraggable\"\n            class=\"base-entry-selector__body__entries\"\n            @clicked=\"entryClicked\"\n            @selected=\"selectEntry\">\n            <template #entry-text-content=\"{ item }\">\n              <!-- @slot text-content - use this slot to individualize the displayed text per selector entry.\n              @binding {Object} item - the data of one single selector entry provided with `entries` -->\n              <slot\n                name=\"entry-text-content\"\n                :item=\"item\" />\n            </template>\n            <template #entry-right-side-elements=\"{ isSelected, item }\">\n              <!-- @slot use this slot to add elements to the right side of an entry. This slot content will be rendered in place of thumbnails and select checkbox so it will effectively disable the display of selection elements and if select mode is desired, custom elements should be provided\n                 @binding { Object } item - the complete entry provided by list\n                 @binding { boolean } is-selected - was item selected\n                 @binding { boolean } select-active - is select mode of entry selector active -->\n              <slot\n                name=\"entry-right-side-elements\"\n                :is-selected=\"isSelected\"\n                :select-active=\"showOptions\"\n                :item=\"item\" />\n            </template>\n            <template\n              #thumbnails=\"{ item }\">\n              <!-- @slot add custom elements at the end of the item row (see also [BaseMenuList](BaseMenuList)). this slot can only be be used if the `entries` slot is not used\n                @binding { Object } item - the data of one entry provided by `entries` prop -->\n              <slot\n                :item=\"item\"\n                name=\"thumbnails\" />\n            </template>\n          </BaseMenuList>\n          <div\n            v-else-if=\"!isLoading\"\n            class=\"base-entry-selector__no-entries\">\n            <p class=\"base-entry-selector__no-entries__title\">\n              {{ getI18nTerm(entrySelectorText.noEntriesTitle) }}\n            </p>\n            <p class=\"base-entry-selector__no-entries__subtext\">\n              {{ getI18nTerm(entrySelectorText.noEntriesSubtext) }}\n            </p>\n          </div>\n        </slot>\n      </div>\n    </div>\n\n    <BasePagination\n      v-if=\"pageTotal > 1\"\n      ref=\"pagination\"\n      :total=\"pageTotal\"\n      :model-value=\"pageNumber\"\n      :assistive-text=\"paginationAssistiveText\"\n      @update:model-value=\"setPage\" />\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n  @use \"@/styles/variables\" as *;\n\n  .base-entry-selector {\n    display: flex;\n    flex-direction: column;\n    background: $background-color;\n\n    &__head {\n      position: sticky;\n      z-index: map.get($zindex, entry-selector-head);\n      background-color: $background-color;\n      flex: 0 0 auto;\n\n      &--padding {\n        padding-top: $spacing;\n      }\n\n      &--shadow {\n        box-shadow: 0 $spacing-small $spacing-small (-$spacing-small) rgba(0, 0, 0, 0.25);\n      }\n\n      &__search-bar {\n        margin-bottom: $spacing-small;\n      }\n\n      &__search-bar--margin-large {\n        margin-bottom: $spacing;\n      }\n    }\n\n    &__options {\n      padding-bottom: $spacing-small;\n    }\n\n    // wrapper introduced for shadow effects\n    .base-entry-selector__body-wrapper {\n      height: 100%;\n      min-height: $row-height-large;\n      position: relative;\n      overflow: hidden;\n\n      .base-entry-selector__body {\n        height: 100%;\n        position: relative;\n        overflow-y: auto;\n        flex: 1 1 auto;\n        min-height: $row-height-large;\n\n        .base-entry-selector__body__entries {\n          height: 100%;\n        }\n\n        .loading-area {\n          position: absolute;\n          height: 100%;\n          width: 100%;\n          z-index: map.get($zindex, loader);\n          background-color: $loading-background;\n          overflow: hidden;\n\n          .base-entry-selector__loader__center {\n            top: 50%;\n          }\n        }\n      }\n      .base-entry-selector__body-shadow {\n        position: absolute;\n        left: 0;\n        // z-index needs to lie above BaseMenuEntry text-fade-out\n        z-index: calc(map.get($zindex, fadeout) + 2);\n        height: 8px;\n        width: 100%;\n        pointer-events: none;\n      }\n\n      .base-entry-selector__body-shadow--top {\n        top: 0;\n        box-shadow: inset 0 $spacing-small $spacing-small (-$spacing-small) rgba(0, 0, 0, 0.25);\n      }\n\n      .base-entry-selector__body-shadow--bottom {\n        bottom: 0;\n        box-shadow: inset 0 (-$spacing-small) $spacing-small (-$spacing-small) rgba(0, 0, 0, 0.25);\n      }\n    }\n\n    &__no-entries {\n      height: 100%;\n      width: 100%;\n      padding-top: 50px;\n\n      &__title,\n      &__subtext {\n        text-align: center;\n        color: $font-color-second;\n        margin-bottom: $spacing;\n        padding: 0 $spacing-large;\n      }\n\n      &__title {\n        font-size: $font-size-large;\n      }\n    }\n\n    &__dropdowns {\n      display: flex;\n      justify-content: flex-end;\n      width: 100%;\n\n      &__dropdown {\n        &:not(:first-of-type) {\n          margin-left: $spacing;\n        }\n      }\n\n      @media screen and (max-width: $tablet) {\n        flex-wrap: wrap;\n      }\n    }\n  }\n</style>\n","<script>\nimport { debounce } from '@/utils/utils.js';\nimport { useId } from '@/composables/useId.js';\nimport { useSlots, useTemplateRef } from 'vue';\nimport BaseBox from '@/components/BaseBox/BaseBox.vue';\nimport BaseButton from '@/components/BaseButton/BaseButton.vue';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\n\n/**\n * Component to render content in expandable container\n */\n\nexport default {\n  name: 'BaseExpandBox',\n  components: {\n    BaseBox,\n    BaseButton,\n  },\n  props: {\n    /**\n     * expand box from the outside\n     */\n    expand: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define padding of the box\n     */\n    padding: {\n      type: String,\n      default: 'small',\n      validator(val) {\n        return ['none', 'large', 'small'].includes(val);\n      },\n    },\n    /**\n     * button text to show more content\n     */\n    showMoreText: {\n      type: String,\n      default: 'Show more',\n    },\n    /**\n     * button text to show less content\n     */\n    showLessText: {\n      type: String,\n      default: 'Show less',\n    },\n    /**\n     * define whether box height depends on content\n     */\n    autoHeight: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define the max height of the collapsed box in px\n     */\n    maxCollapsedHeight: {\n      type: Number,\n      default: 300,\n    },\n    /**\n     * define the height including margin of the show-more button in px\n     */\n    showButtonHeight: {\n      type: Number,\n      default: 54,\n    },\n    /**\n     * option to disable the box shadow if element is nested into a box\n     */\n    boxShadow: {\n      type: Boolean,\n      default: true,\n    },\n  },\n  emits: ['update:expand', 'box-height'],\n  setup() {\n    /** INTERNAL ID */\n    const internalId = useId();\n\n    /** SLOT VISIBILITY */\n    const slots = useSlots();\n    /**\n     * determine if header slot has content\n     * @type {boolean}\n     */\n    const { slotHasContent: headerSlotHasContent } = useHasSlotContent(slots.header);\n    /**\n     * determine if header slot has content\n     */\n    const { slotHasContent: footerSlotHasContent } = useHasSlotContent(slots.footer);\n\n\n    /** EXPAND BUTTON AND FADE OUT VISIBILITY */\n    /**\n     * template reference to the expand box content\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const content = useTemplateRef('contentElement');\n    /**\n     *\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const contentInner = useTemplateRef('contentInnerElement');\n\n    return {\n      // internal id\n      internalId,\n      // slot handling\n      headerSlotHasContent,\n      footerSlotHasContent,\n      // expand button and fade out\n      content,\n      contentInner,\n    };\n  },\n  data() {\n    return {\n      expandInt: false,\n      initialized: false,\n      showButton: false,\n      mutationObserver: null,\n      resizeObserver: null,\n    };\n  },\n  computed: {\n    maxCollapsedHeightInt() {\n      return this.showButton\n        ? this.maxCollapsedHeight - this.showButtonHeight\n        : this.maxCollapsedHeight;\n    },\n    style() {\n      return { '--max-collapsed-height': `${this.maxCollapsedHeightInt}px` };\n    },\n  },\n  mounted() {\n    this.init();\n  },\n  beforeUnmount() {\n    if (this.mutationObserver) this.mutationObserver.disconnect();\n    if (this.resizeObserver) this.resizeObserver.disconnect();\n  },\n  methods: {\n    /**\n     * init\n     */\n    init() {\n      // set internal expand variable\n      if (this.expand) this.expandInt = true;\n      // calculate the show-more button visibility\n      this.calcButtonVisibility();\n      // init observers (currently for resize and mutation)\n      this.initObserver();\n      // set initialization state\n      this.initialized = true;\n    },\n    /**\n     * create resize/mutation observer for the content container\n     * to trigger the calculation for the visibility of the show more button\n     */\n    initObserver() {\n      // create a resize observer with calculation functions\n      const resizeObserver = new ResizeObserver(debounce(50, this.calcButtonVisibility));\n\n      // create a mutation observer with calculation functions\n      const mutationObserver = new MutationObserver(this.calcButtonVisibility);\n\n      // attach the observers to the component\n      resizeObserver.observe(this.content);\n      mutationObserver.observe(this.content, { childList: true, subtree: true });\n\n      // store them in variables\n      this.resizeObserver = resizeObserver;\n      this.mutationObserver = mutationObserver;\n    },\n    /**\n     * calculate visibility of 'show more' button\n     */\n    calcButtonVisibility() {\n      if (this.contentInner) {\n        // clone inner content\n        const contentInnerTemp = this.contentInner.cloneNode(true);\n        // add unique id for later use\n        contentInnerTemp.setAttribute('id', `contentInnerTemp-${this.internalId}`);\n        // append the temporary element to the component\n        this.$el.appendChild(contentInnerTemp);\n        // get the height of the temporary element\n        const contentInnerTempHeight = contentInnerTemp.scrollHeight;\n        // remove  element\n        this.$el.removeChild(document.getElementById(`contentInnerTemp-${this.internalId}`));\n        // set button visibility\n        this.showButton = contentInnerTempHeight > this.maxCollapsedHeight;\n\n        // emit box-size\n        if (!this.expandInt) {\n          /**\n           * emitting box-height on resize\n           * @param {number} - the element offset height\n           */\n          this.$emit('box-height', this.$el.offsetHeight);\n        }\n      }\n    },\n    /**\n     * click event for the show-more button\n     */\n    toggle() {\n      this.expandInt = !this.expandInt;\n\n      /**\n       * event emitted on button click\n       * @param {boolean} - is box expanded\n       */\n      this.$emit('update:expand', this.expandInt);\n    },\n  },\n};\n</script>\n\n<template>\n  <BaseBox\n    :box-ratio=\"'0'\"\n    :box-hover=\"false\"\n    :box-size=\"{}\"\n    :box-shadow-size=\"boxShadow ? 'small' : 'none'\"\n    :style=\"style\"\n    :class=\"[\n      'base-expand-box',\n      'base-expand-box-padding-' + padding,\n      { 'base-expand-box-auto-height': autoHeight },\n      { 'base-expand-box-open': expandInt }]\">\n    <div\n      v-if=\"headerSlotHasContent\"\n      class=\"base-expand-box-header\">\n      <!-- @slot slot to add additional information before expandable content -->\n      <slot name=\"header\" />\n    </div>\n    <div\n      ref=\"contentElement\"\n      :class=\"[\n        'base-expand-box-content',\n        { 'base-expand-box-content-fade-out': (!initialized || !expandInt && showButton) }]\">\n      <div\n        class=\"base-expand-box-content-inner\">\n        <!-- div is needed for calculation of content height -->\n        <div\n          ref=\"contentInnerElement\">\n          <!--\n            @slot add expand box content here\n          -->\n          <slot />\n        </div>\n      </div>\n    </div>\n\n    <BaseButton\n      v-if=\"showButton\"\n      :text=\"expandInt ? showLessText : showMoreText\"\n      :has-background-color=\"false\"\n      align-text=\"left\"\n      icon=\"drop-down\"\n      icon-position=\"right\"\n      :class=\"[\n        'base-expand-box-button',\n        { 'base-button--rotate-icon-180': expandInt }]\"\n      @clicked=\"toggle\" />\n\n    <div\n      v-if=\"footerSlotHasContent\"\n      class=\"base-expand-box-footer\">\n      <div class=\"base-expand-box-footer-inner\">\n        <!-- @slot slot to add additional information after expandable content -->\n        <slot name=\"footer\" />\n      </div>\n    </div>\n  </BaseBox>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-expand-box {\n    flex-direction: column;\n\n    &.base-expand-box-padding-none {\n      padding: 0;\n    }\n\n    &.base-expand-box-padding-small {\n      padding: $spacing;\n    }\n\n    &.base-expand-box-padding-large {\n      padding: $spacing-large;\n    }\n\n    &.base-expand-box-auto-height:not(.base-expand-box-open) .base-expand-box-content {\n      max-height: var(--max-collapsed-height);\n    }\n\n    &:not(.base-expand-box-auto-height) .base-expand-box-content {\n      height: var(--max-collapsed-height);\n    }\n\n    .base-expand-box-content {\n      position: relative;\n      overflow: hidden;\n      line-height: $line-height;\n\n      &.base-expand-box-content-fade-out::after {\n        content: '';\n        width: 100%;\n        height: $line-height * 2;\n        position: absolute;\n        bottom: 0;\n        left: 0;\n        z-index: 1;\n        pointer-events: none;\n        background: linear-gradient(to bottom, rgba(255, 255, 255, 0) , white);\n      }\n    }\n\n    .base-expand-box-content-inner {\n      position: relative;\n      height: 100%;\n      visibility: visible;\n    }\n\n    .base-expand-box-button {\n      margin-top: $spacing;\n      padding-left: 0;\n      justify-content: flex-start; // IE 11\n    }\n\n    &.base-expand-box-open {\n      .base-expand-box-content {\n        height: auto;\n      }\n    }\n\n    .base-expand-box-footer {\n      margin-top: auto;\n\n      .base-expand-box-footer-inner {\n        border-top: $border-width solid $background-color;\n        margin: $spacing 0 0;\n        padding-top: $spacing;\n      }\n    }\n  }\n</style>\n","<script>\nimport { defineAsyncComponent } from 'vue';\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport { useId } from '@/composables/useId.js';\n\nexport default {\n  name: 'BaseExpandListRow',\n  components: {\n    BaseToggle: defineAsyncComponent(() => import('@/components/BaseToggle/BaseToggle.vue')),\n    BaseButton: defineAsyncComponent(() => import('@/components/BaseButton/BaseButton.vue')),\n    BaseExpandListRow: defineAsyncComponent(() => import('@/components/BaseExpandList/BaseExpandListRow.vue')),\n    BaseIcon,\n  },\n  props: {\n    /**\n     * data object: { label: 'String', data: [{ value: 'String', }],\n     *  [hidden]: boolean, [count]: number }\n     * optional properties:\n     *  count: used for the number shown in brackets\n     *    (else the array length will be used)\n     *  hidden: used to set visibility and is set in edit mode to toggle item\n     * rendered variants:\n     *  expandable row: data object contains property 'label'\n     *  entry row: data object contains property 'value'\n     */\n    data: {\n      type: Object,\n      default: () => {\n      },\n    },\n    /**\n     * set edit mode\n     */\n    edit: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * expand multiple items\n     */\n    multiple: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * render component as e.g.: 'div' | 'li'\n     */\n    renderAs: {\n      type: String,\n      default: 'div',\n    },\n    /**\n     * button text to hide item\n     */\n    editHideText: {\n      type: String,\n      default: 'Hide',\n    },\n    /**\n     * button text to show item\n     */\n    editShowText: {\n      type: String,\n      default: 'Show',\n    },\n    /**\n     * specify the type of visibility switch in edit mode\n     *  **button**: a [BaseButton](BaseButton) without text\n     *  **button**: a [BaseToggle](BaseToggle) element without text\n     */\n    controlType: {\n      type: String,\n      default: 'button',\n      validator: val => ['button', 'toggle'].includes(val),\n    },\n    /**\n     * index of parent element\n     * used to expand item from outside\n     */\n    parentIndex: {\n      type: [Number, String],\n      default: 0,\n    },\n    /**\n     * option to disable the edit functionalities of the element (toggle and draggable)\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['expanded-state', 'update:data', 'sorted', 'assistive'],\n  setup() {\n    /** INTERNAL ID */\n    const internalId = useId();\n    return {\n      internalId,\n    };\n  },\n  data() {\n    return {\n      // toggle item\n      expanded: false,\n      // referenced in BaseExpandList\n      movable: false,\n      // referenced in BaseExpandList\n      useAssistiveText: true,\n      // internal representation of data\n      dataInt: null,\n      // fade out overlays\n      fadeOutLeft: false,\n      fadeOutRight: true,\n    };\n  },\n  computed: {\n    itemVisible: {\n      set(val) {\n        this.dataInt.hidden = !val;\n      },\n      get() {\n        return !this.dataInt.hidden;\n      },\n    },\n  },\n  watch: {\n    /**\n     * Set focus to active movable item\n     *\n     * @params {string}\n     */\n    movable(val) {\n      const dragHandle = this.$el.querySelector('.base-expand-item__handle');\n\n      if (val) {\n        dragHandle.focus();\n      }\n\n      // check if dragHandle has focus\n      if (document.activeElement === dragHandle) {\n        // emit assistive text for aria-live\n        this.assistiveText(this.movable ? 'activated' : 'activate');\n      }\n\n      // enable assistive text (disabled by moveItem())\n      this.useAssistiveText = true;\n    },\n    dataInt: {\n      handler(val) {\n        // check if data has values (and is not initial null) and if it differs\n        // from parent data\n        if (!!val && JSON.stringify(val) !== JSON.stringify(this.data)) {\n          // if yes update parent data\n          this.$emit('update:data', val);\n        }\n      },\n      deep: true,\n      immediate: true,\n    },\n    data: {\n      handler(val) {\n        // check if parent data differ from internal data - if yes update\n        if (JSON.stringify(val) !== JSON.stringify(this.dataInt)) {\n          this.dataInt = JSON.parse(JSON.stringify(val));\n        }\n      },\n      deep: true,\n      immediate: true,\n    },\n  },\n  mounted() {\n    if (this.$refs.listItemScrollable) {\n      const scrollable = this.$refs.listItemScrollable;\n      scrollable.addEventListener('scroll', () => this.scrollHandler(scrollable));\n    }\n  },\n  unmounted() {\n    if (this.$refs.listItemScrollable) {\n      const scrollable = this.$refs.listItemScrollable;\n      scrollable.removeEventListener('scroll', () => this.scrollHandler(scrollable));\n    }\n  },\n  methods: {\n    /**\n     * cancel movable state, stop propagation if needed\n     *   e.g. further esc key event\n     * @param {KeyboardEvent} e - event\n     */\n    cancelMovable(e) {\n      if (this.movable) {\n        e.stopPropagation();\n        e.stopImmediatePropagation();\n        e.preventDefault();\n        this.movable = false;\n      }\n    },\n    /**\n     * set visibility if button was clicked\n     */\n    setVisibility(val) {\n      this.itemVisible = val;\n    },\n    /**\n     * move item\n     *\n     * @param {string} direction values: 'up' | 'down'\n     */\n    moveItem(direction = 'up ') {\n      if (this.movable) {\n        // disable assistive text to avoid message cue\n        this.useAssistiveText = false;\n        this.movable = false;\n        this.$emit('sorted', {\n          direction,\n        });\n      }\n    },\n    /**\n     * expand item\n     */\n    expand() {\n      // which element(s) are currently expanded\n      // eg: level1, first item = 0; level2, second item: 0-1\n      const currentState = this.$.vnode.key.toString().split('-');\n\n      if (this.expanded) {\n        this.expanded = false;\n        // remove current level and emit expanded state\n        this.emitExpandedState(currentState.length > 1 ? currentState.slice(-1) : '');\n        return;\n      }\n\n      // close expanded rows\n      if (!this.multiple) {\n        const rows = this.$parent.$refs.baseExpandListRow;\n\n        if (rows) {\n          rows.forEach((row) => {\n            // eslint-disable-next-line\n            row.expanded = false;\n          });\n        }\n      }\n\n      this.expanded = true;\n      this.emitExpandedState(currentState);\n    },\n    /**\n     * emit expanded state of items\n     * each array element represents the index of the expanded item per level\n     * eg: [0,1]: level1 first item, level2 second item is expanded\n     *\n     * @param {Array} value - value to emit\n     */\n    emitExpandedState(value) {\n      /**\n       * event triggered when expanded state changes\n       *\n       * @event expanded-state\n       * @param {Array} - array with indices of the expanded item per level; eg: [0, 1]: level1 first item, level2 second item is expanded\n       */\n      this.$emit('expanded-state', value);\n    },\n    /**\n     * calc max height for transition\n     *\n     * @params {object} el\n     */\n    maxHeight(el) {\n      const elementHeight = this.$el.querySelector('.base-expand-item').offsetHeight;\n      const maxHeight = elementHeight + elementHeight * this.dataInt.data.length;\n\n      el.setAttribute('style', `max-height: ${maxHeight}px`);\n    },\n    /**\n     * close expanded rows\n     *\n     * @params {array} rows\n     */\n    closeRows(rows) {\n      if (rows) {\n        rows.forEach((row) => {\n          // eslint-disable-next-line\n          row.expanded = false;\n        });\n      }\n    },\n    /**\n     * event triggered on enter transition\n     *\n     * @params {object} el\n     */\n    enter(el) {\n      this.maxHeight(el);\n    },\n    /**\n     * event triggered on finished enter transition\n     *\n     * @params {object} el\n     */\n    afterEnter(el) {\n      el.style.removeProperty('max-height');\n    },\n    /**\n     * event triggered on leave transition\n     *\n     * @params {object} el\n     */\n    leave(el) {\n      const elementHeight = this.$el.offsetHeight;\n      el.setAttribute('style', `max-height: ${elementHeight}px`);\n    },\n    /**\n     * event triggered on before leave transition\n     */\n    beforeLeave() {\n      // close expanded rows of current level\n      if (!this.multiple) {\n        this.closeRows(this.$refs.baseExpandListRow);\n      }\n    },\n    /**\n     * assistive text for screen readers\n     */\n    assistiveText(type = 'activate') {\n      if (!this.useAssistiveText) {\n        return;\n      }\n      /**\n       * event emitted on dragHandle toggle\n       *\n       * @event assistive\n       * @property {string} type\n       */\n      this.$emit('assistive', type);\n    },\n    /**\n     * set fadeOut elements depending on scroll position\n     *\n     * @param {object} row\n     */\n    scrollHandler(row) {\n      this.fadeOutLeft = !!row.scrollLeft;\n      this.fadeOutRight = row.scrollWidth - row.scrollLeft !== row.offsetWidth;\n    },\n  },\n};\n</script>\n\n<template>\n  <component\n    :is=\"renderAs\"\n    :class=\"[{\n      'base-expand': !edit,\n      expanded: expanded,\n    }]\">\n    <template\n      v-if=\"!edit && dataInt.label\">\n      <button\n        :id=\"'base-expand-control-' + internalId\"\n        :aria-expanded=\"expanded\"\n        :aria-controls=\"'base-expand-region-' + internalId\"\n        type=\"button\"\n        class=\"base-expand__head base-expand-item\"\n        @click=\"expand\">\n        <span class=\"base-expand-item__col base-expand-item__label base-text-fade-out\">\n          <span\n            class=\"base-expand__head__label\">{{ dataInt.label }}</span>\n          <span\n            class=\"base-expand__head__additional\">\n            ({{ dataInt.count !== undefined ? dataInt.count : dataInt.data.length }})\n          </span>\n        </span>\n        <BaseIcon\n          name=\"drop-down\"\n          class=\"base-expand-item__col base-expand__head__icon\" />\n      </button>\n\n      <transition\n        name=\"expand\"\n        @enter=\"enter\"\n        @after-enter=\"afterEnter\"\n        @leave=\"leave\"\n        @before-leave=\"beforeLeave\">\n        <ul\n          v-show=\"expanded\"\n          :id=\"'base-expand-region-' + internalId\"\n          :aria-labelledby=\"'base-expand-control-' + internalId\"\n          :aria-hidden=\"!expanded\"\n          class=\"base-expand__body\">\n          <!-- Todo: limit levels (counter) -->\n          <BaseExpandListRow\n            v-for=\"(items, index) in dataInt.data\"\n            ref=\"baseExpandListRow\"\n            :key=\"`${parentIndex}-${index}`\"\n            :data=\"items\"\n            :multiple=\"multiple\"\n            render-as=\"li\"\n            @expanded-state=\"emitExpandedState\">\n            <template\n              #content=\"dataNextLevel\">\n              <!-- @slot a slot to provide customized entry row in next level -->\n              <slot\n                name=\"content\"\n                :data=\"dataNextLevel.data\" />\n            </template>\n          </BaseExpandListRow>\n        </ul>\n      </transition>\n    </template>\n\n    <template\n      v-if=\"!edit && dataInt.value\">\n      <div\n        :class=\"['base-expand-item',\n                 'base-expand-item--intend',\n                 {\n                   'base-text-fade-out-left': fadeOutLeft,\n                   'base-text-fade-out': fadeOutRight,\n                 }]\">\n        <span\n          ref=\"listItemScrollable\"\n          class=\"base-expand-item__col base-expand-item__label\">\n          <!-- @slot a slot to provide customized entry row -->\n          <slot\n            name=\"content\"\n            :data=\"dataInt\">\n            {{ dataInt.value }}\n          </slot>\n        </span>\n      </div>\n    </template>\n\n    <template\n      v-if=\"edit\">\n      <div\n        :class=\"['base-expand-item', { 'base-expand-item--movable': movable }]\">\n        <span\n          ref=\"baseExpandItemHandle\"\n          :title=\"dataInt.label\"\n          role=\"button\"\n          tabindex=\"0\"\n          class=\"base-expand-item__col base-expand-item__handle\"\n          @keydown.down.prevent.stop=\"moveItem('down')\"\n          @keydown.up.prevent.stop=\"moveItem('up')\"\n          @keydown.enter.prevent.stop=\"movable = !movable\"\n          @focus=\"assistiveText('activate')\"\n          @keyup.esc=\"cancelMovable\"\n          @blur=\"cancelMovable\">\n          <BaseIcon\n            name=\"drag-lines\" />\n        </span>\n        <div class=\"base-expand-item__col base-expand-item__label base-text-fade-out\">\n          <div\n            v-if=\"!itemVisible\"\n            class=\"base-expand-item__overlay\" />\n          <span\n            :class=\"[\n              'base-expand__head__label',\n              { 'base-expand__head__label--disabled': !itemVisible }]\">\n            {{ dataInt.label }}\n          </span>\n          <span\n            class=\"base-expand__head__additional\">\n            ({{ dataInt.count !== undefined ? dataInt.count : dataInt.data.length }})\n          </span>\n        </div>\n        <div class=\"base-expand-item__col base-expand-item__controls\">\n          <BaseButton\n            v-if=\"controlType === 'button'\"\n            :icon=\"itemVisible ? 'eye' : 'eye-hide'\"\n            :text=\"''\"\n            :has-background-color=\"false\"\n            :disabled=\"disabled\"\n            :aria-label=\"`${itemVisible ? editHideText : editShowText } ${dataInt.label}`\"\n            icon-size=\"large\"\n            icon-position=\"left\"\n            @clicked=\"setVisibility(!itemVisible)\" />\n          <BaseToggle\n            v-else-if=\"controlType === 'toggle'\"\n            v-model=\"itemVisible\"\n            :disabled=\"disabled\"\n            :hide-label=\"true\"\n            :label=\"`${editShowText} ${dataInt.label}`\"\n            class=\"base-expand-item__toggle\" />\n        </div>\n      </div>\n    </template>\n  </component>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n.base-expand-item {\n  display: flex;\n  align-items: center;\n  background-color: #fff;\n  margin-bottom: $border-width;\n  padding-left: calc(#{$spacing} - #{$border-active-width});\n  padding-right: $spacing;\n  outline: 1px solid $background-color;\n  border-left: $border-active-width solid transparent;\n  transition: border-left-color 500ms ease-in-out;\n  overflow: hidden;\n\n  a {\n    color: $app-color;\n    transition: $link-transition;\n    margin-right: 5px; // Todo: find better solution for spacing\n\n    &:hover,\n    &:focus {\n      color: $app-color-secondary;\n    }\n  }\n\n  &__col {\n    display: flex;\n    align-items: center;\n    min-height: $row-height-large;\n    overflow: hidden;\n  }\n\n  &__handle {\n    margin-right: $spacing-small;\n    color: $font-color-second;\n\n    svg {\n      transition: $drop-down-arrow-animation;\n      height: $icon-medium;\n      width: $icon-medium;\n      min-width: $icon-small;\n    }\n\n    &:hover,\n    &:focus {\n      cursor: grab;\n      color: $app-color;\n      outline: none;\n    }\n  }\n\n  &__label {\n    flex-grow: 1;\n    white-space: nowrap;\n    // enable scroll and hide scrollBars\n    overflow-x: auto;\n    scrollbar-width: none; /* Firefox */\n    -ms-overflow-style: none;  /* Internet Explorer 10+ */\n\n    &::-webkit-scrollbar { /* WebKit */\n      width: 0;\n      height: 0;\n    }\n\n    & .base-expand-item__overlay {\n      position: absolute;\n      content: '';\n      height: 100%;\n      width: 100%;\n      background: rgba(255, 255, 255, 40%);\n    }\n  }\n\n  &__controls {\n    justify-self: flex-end;\n    border-left: $border-width solid $background-color;\n    margin-right: -$spacing;\n\n    .base-expand-item__toggle {\n      margin: 0 $spacing;\n    }\n  }\n\n  &.base-text-fade-out::after {\n    right: $spacing-small;\n  }\n\n  &.base-text-fade-out-left::before {\n    left: calc(#{$spacing-large} - #{$border-active-width});\n\n    @media screen and (max-width: $mobile) {\n      left: calc(#{$spacing} - #{$border-active-width});\n    }\n  }\n\n  &--intend {\n    padding-left: calc(#{$spacing-large} - #{$border-active-width});\n\n    @media screen and (max-width: $mobile) {\n      padding-left: calc(#{$spacing} - #{$border-active-width});\n    }\n  }\n\n  &--movable {\n    position: relative;\n    z-index: 1;\n    outline: 1px solid $app-color;\n  }\n\n  &:focus {\n    .base-expand-item__handle {\n      color: $app-color;\n    }\n  }\n}\n</style>\n\n<style lang=\"scss\">\n@use \"@/styles/variables\" as *;\n\n.expand-enter-active,\n.expand-leave-active {\n  transition-duration: $base-expand-list-transition-duration;\n  transition-timing-function: ease-in-out;\n}\n\n.expand-enter-to,\n.expand-leave-from {\n  overflow: hidden;\n}\n\n.expand-enter-from,\n.expand-leave-to {\n  overflow: hidden;\n  max-height: 0 !important;\n}\n\n.expand-enter-from {\n  .base-expand-item {\n    border-color: transparent !important;\n  }\n}\n\n.expand-enter-to {\n  .base-expand-item {\n    border-color: $app-color-secondary !important;\n  }\n}\n</style>\n\n<style lang=\"scss\">\n@use \"@/styles/baseExpand\";\n</style>\n","<script>\nimport BaseButton from '@/components/BaseButton/BaseButton.vue';\nimport BaseExpandListRow from '@/components/BaseExpandList/BaseExpandListRow.vue';\nimport { useId } from '@/composables/useId.js';\nimport { defineAsyncComponent, ref } from 'vue';\n\nexport default {\n  name: 'BaseExpandList',\n  components: {\n    BaseButton,\n    BaseExpandListRow,\n  },\n  props: {\n    /**\n     * should be an object array with the following properties:\n     *  **label** `string` - the displayed label\n     *  **id** `string` - an identifier\n     *  **data** `Object[]` - an object array with the property:\n     *    \\* **label** `string` (renders component as\n     *    expandable row) or\n     *    * **value** `string` (renders component as entry row)\n     *\n     * optional properties:\n     *  **count** `number` - used for the number shown in brackets\n     *    (else the array length will be used)\n     *  **hidden** `boolean` - used to set visibility and is set in edit mode to toggle item\n     *\n     *  the v-model directive might be used on this prop\n     */\n    data: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * set edit mode from outside\n     */\n    edit: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify number of minimal displayed items\n     */\n    minItems: {\n      type: Number,\n      default: 3,\n    },\n    /**\n     * expand multiple items\n     */\n    multiple: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * button text to show more content\n     */\n    showMoreText: {\n      type: String,\n      default: 'Show all',\n    },\n    /**\n     * button text to show less content\n     */\n    showLessText: {\n      type: String,\n      default: 'Show less',\n    },\n    /**\n     * button text to hide item\n     */\n    editHideText: {\n      type: String,\n      default: 'Hide',\n    },\n    /**\n     * button text to show item\n     */\n    editShowText: {\n      type: String,\n      default: 'Show',\n    },\n    /**\n     * additional texts for screen-reader users to order items.\n     *   object that needs to have the following properties:\n     *   **activate**: Text read when item is focused, use variable {state} to\n     *    announce item visibility - specify text used in properties 'hidden' and 'visible'\n     *   **activated**: Text read after item was activated (selected by enter key)\n     *   **description**: Text read on initial list focus\n     *   **moved**: Text read after item was moved; can contain variables {pos} (for new position) and {total}\n     *   **visible**: string substituted to 'activate' text for state variable if item is visible\n     *   **hidden**: string substituted to 'activate' text for state variable if item is hidden\n     *\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        activate: 'Use the Enter key to select item. Item is currently {state}',\n        activated: 'Item selected. Use arrow keys to order item.',\n        description: 'Use Tab key to navigate to item an order item.',\n        moved: 'Item moved: {pos} of {total}',\n        visible: 'visible',\n        hidden: 'hidden',\n      }),\n      validator: val => Object.keys(val)\n        .every(key => ['activate', 'activated', 'description', 'moved', 'visible', 'hidden'].includes(key)),\n    },\n    /**\n     * specify the type of visibility switch in edit mode\n     *  **button**: a [BaseButton](BaseButton) without text\n     *  **toggle**: a [BaseToggle](BaseToggle) element without text\n     */\n    controlType: {\n      type: String,\n      default: 'button',\n      validator: val => ['button', 'toggle'].includes(val),\n    },\n    /**\n     * define which items are expanded\n     * v-model might be used on this property\n     */\n    expanded: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * option to disable the edit functionalities of the element (toggle and draggable)\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: [\n    'saved',\n    'update:expanded',\n    'update:data',\n    /**\n     * triggered when async component is initialized\n     *\n     * @event update:edit-mode-is-ready\n     * @param {boolean} - the current loading state\n     */\n    'update:edit-mode-is-ready'],\n  setup(props, { emit }) {\n    /** HANDLE ASYNC COMPONENT */\n    // store state if component is loaded\n    const draggableIsLoaded = ref(false);\n    // load draggable component asynchronously, emit state when ready\n    const Draggable = defineAsyncComponent({\n      loader: async () => {\n        emit('update:edit-mode-is-ready', false);\n        const component = await import('vue-draggable-plus').then(m => m.VueDraggable);\n        emit('update:edit-mode-is-ready', true);\n        draggableIsLoaded.value = true;\n        return component;\n      },\n    });\n\n    /** INTERNAL ID */\n    const internalId = useId();\n\n    return {\n      Draggable,\n      draggableIsLoaded,\n      internalId,\n    };\n  },\n  data() {\n    return {\n      assertiveText: '',\n      showAll: false,\n      dataSorted: null,\n      originalData: null,\n      dragHandle: '',\n    };\n  },\n  computed: {\n    // the data array computed for draggable\n    dataInt: {\n      get() {\n        return this.dataSorted || this.data;\n      },\n      set(val) {\n        this.dataSorted = val;\n      },\n    },\n    /**\n     * evaluate if editable list is displayed\n     * @returns {boolean}\n     */\n    showEditableList() {\n      return this.edit && this.draggableIsLoaded;\n    },\n    /**\n     * evaluate if expandable list is displayed\n     * @returns {boolean}\n     */\n    showList() {\n      return (!this.draggableIsLoaded) || (!this.edit && this.draggableIsLoaded);\n    },\n    /**\n     * evaluate if a ghost component to load the draggable component asynchronously is displayed\n     * @returns {boolean}\n     */\n    showDraggableLoader() {\n      return this.edit && !this.draggableIsLoaded;\n    }\n  },\n  watch: {\n    dataSorted: {\n      handler(val) {\n        // check if update is actually done by user during edit mode\n        // (this is the only time internal data should change!)\n        if (this.edit && JSON.stringify(val) !== JSON.stringify(this.data)) {\n          /**\n           * event emitted when data change internally (e.g. sorting, toggling hidden, etc.).\n           *  the v-model directive may be used on the corresponding prop\n           *\n           * @event update:data\n           * @param {Object[]} - the modified data (e.g. from sorting)\n           */\n          this.$emit('update:data', val);\n        }\n      },\n      deep: true,\n    },\n    data: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.dataSorted)) {\n          this.dataInt = JSON.parse(JSON.stringify(val));\n        }\n      },\n      deep: true,\n      immediate: true,\n    },\n    /**\n     * watch edit to create a copy of the data for the reset function\n     */\n    edit(val) {\n      this.assertiveText = '';\n      if (val) {\n        // save a copy of original data in variable on edit activation\n        this.originalData = JSON.parse(JSON.stringify(this.data));\n\n        if (this.draggableIsLoaded) {\n          this.$emit('update:edit-mode-is-ready', true);\n          this.$nextTick(() => {\n            // set focus draggable area on edit start\n            this.$refs.baseExpandListDraggable.focus({ preventScroll: true });\n          });\n        }\n      }\n    },\n    /**\n     * watch expanded state and expand items\n     */\n    expanded(val) {\n      this.expandItems(val);\n    },\n  },\n  mounted() {\n    // set draggable area depending on device touch capabilities\n    // ssr: check when component is mounted because isTouchCapable() uses window object\n    this.dragHandle = this.isTouchCapable()\n      ? ['.base-expand-item__handle']\n      : ['.base-expand-item__handle', '.base-expand-item__label'];\n  },\n  methods: {\n    /**\n     * expand items\n     *\n     * @param {Array} state - expanded state, eg: [0, 1]: level1 first item,\n     *  level2 second item is expanded\n     */\n    expandItems(state) {\n      if (!state.length) {\n        return;\n      }\n\n      // show all list items\n      if (state[0] >= this.minItems\n        && this.$refs.baseExpandListRow[state[0]]) {\n        this.showAll = true;\n      }\n\n      // first level\n      if (state[0] !== undefined\n        && this.$refs.baseExpandListRow[state[0]]) {\n        this.$refs.baseExpandListRow[state[0]].expanded = true;\n      }\n\n      // second level\n      if (state[1] !== undefined\n        && this.$refs.baseExpandListRow[state[0]].$refs.baseExpandListRow[state[1]]) {\n        this.$refs.baseExpandListRow[state[0]].$refs.baseExpandListRow[state[1]].expanded = true;\n      }\n    },\n    /**\n     * emit expanded state of items\n     * each array element represents the index of the expanded item per level\n     * eg: [0, 1]: level1 first item, level2 second item is expanded\n     *\n     * @param {Array} value - value to emit\n     */\n    emitExpandedState(value) {\n      /**\n       * event triggered when expanded state changes\n       *\n       * @event update:expanded\n       * @param {Array} - array with indices of the expanded item per level; eg: [0, 1]: level1 first item, level2 second item is expanded\n       */\n      this.$emit('update:expanded', value);\n    },\n    /**\n     * function called from BaseExpandListRow in case a prop of the data variable\n     * changes (e.g. hidden)\n     * @param {Object} rowData - the updated data of the BaseExpandListRow\n     * @param {number} index - the index in the dataInt array\n     */\n    updateData(rowData, index) {\n      this.dataSorted[index] = rowData;\n    },\n    /**\n     * sort list\n     *\n     * @param {object} obj\n     * @property {string} obj.direction - 'up' or 'down'\n     * @param {number} index - the previous index of the item in the array\n     */\n    sort({ direction }, index) {\n      // check list boundary\n      if ((direction === 'up' && index - 1 < 0)\n        || (direction === 'down' && index + 1 >= this.dataInt.length)) {\n        // current movable item (focus) needs to stay the same\n        this.$refs.baseExpandListRow[index].useAssistiveText = false;\n        this.$refs.baseExpandListRow[index].movable = true;\n        return;\n      }\n\n      // set object to new position\n      const to = direction === 'up' ? index - 1 : index + 1;\n      const from = index;\n      const data = this.dataInt;\n      data.splice(to, 0, data.splice(from, 1)[0]);\n      this.dataInt = data;\n\n      // set assertive text\n      this.assertiveText = this.assistiveText.moved\n        .replace('{pos}', to + 1)\n        .replace('{total}', this.dataInt.length);\n\n      // set current item movable (focus)\n      this.$refs.baseExpandListRow[to].useAssistiveText = false;\n      this.$refs.baseExpandListRow[to].movable = true;\n    },\n    /**\n     * reset list data - this always restores the state of the data on\n     * last save() triggered (=was triggered in parent)\n     * @public\n     */\n    reset() {\n      this.dataInt = JSON.parse(JSON.stringify(this.originalData));\n      // watcher on sortedData is not triggered here (because edit is already false)\n      // - need to propagate event to parent manually\n      this.$emit('update:data', this.dataInt);\n    },\n    /**\n     * save changed data\n     * @public\n     */\n    save() {\n      /**\n       * triggered on button click\n       * @event saved\n       * @param {object} - the data altered and ready for saving\n       */\n      this.$emit('saved', this.dataInt);\n      // update reset data copy\n      this.originalData = JSON.parse(JSON.stringify(this.dataInt));\n    },\n    /**\n     * set assistiveText for screen readers\n     *\n     * @param {string} type\n     * @param {number} index\n     */\n    assistive(type, index) {\n      const visibilityText = this.dataInt[index].hidden\n        ? this.assistiveText.hidden : this.assistiveText.visible;\n      const currentSupportString = this.assistiveText[type].replace('{state}', visibilityText);\n      if (this.assertiveText === currentSupportString) {\n        // clear temporary to trigger screen reader\n        this.assertiveText = '';\n        // screen reader needs delay to trigger aria-live message\n        setTimeout(() => {\n          this.assertiveText = currentSupportString;\n        }, 1);\n        return;\n      }\n      this.assertiveText = currentSupportString;\n    },\n    /**\n     * check touch capabilities of current device\n     *\n     * @returns {boolean|*}\n     */\n    isTouchCapable() {\n      return 'ontouchstart' in window\n        || (window.DocumentTouch && document instanceof window.DocumentTouch)\n        || navigator.maxTouchPoints > 0\n        || window.navigator.msMaxTouchPoints > 0;\n    },\n  },\n};\n</script>\n\n<template>\n  <div class=\"base-expand-list\">\n    <!-- List items with clickable head to expand body -->\n    <div\n      :class=\"['base-box-shadow', { 'base-box-shadow--edit': edit }]\">\n      <ul\n        v-if=\"showList\">\n        <BaseExpandListRow\n          v-for=\"(items, index) in data\"\n          v-show=\"index < (showAll ? data.length : minItems)\"\n          ref=\"baseExpandListRow\"\n          :key=\"index\"\n          :parent-index=\"index\"\n          :data=\"items\"\n          :multiple=\"multiple\"\n          render-as=\"li\"\n          @expanded-state=\"emitExpandedState\">\n          <template\n            #content=\"props\">\n            <!-- @slot a slot to provide customized entry row\n              @binding {Object} data - an object in `data` array -->\n            <slot\n              name=\"content\"\n              :data=\"props.data\" />\n          </template>\n        </BaseExpandListRow>\n      </ul>\n\n      <!-- Helper to load the draggable component asynchronously\n           <suspense> needed to avoid an DOMException error in nuxt context -->\n      <suspense v-if=\"showDraggableLoader\">\n        <component :is=\"Draggable\" />\n      </suspense>\n\n      <!-- List items in draggable area -->\n      <template\n        v-if=\"showEditableList\">\n        <div\n          aria-live=\"assertive\"\n          class=\"assistive-text\">\n          {{ assertiveText }}\n        </div>\n\n        <p\n          :id=\"`draggable-${internalId}`\"\n          class=\"assistive-text\">\n          {{ assistiveText['description'] }}\n        </p>\n\n        <div\n          ref=\"baseExpandListDraggable\"\n          tabindex=\"0\"\n          :aria-labelledby=\"`draggable-${internalId}`\"\n          class=\"base-expand-list__draggable\">\n          <component\n            :is=\"Draggable\"\n            v-model=\"dataInt\"\n            :draggable=\"'.base-expand-list__draggable__item'\"\n            :handle=\"dragHandle\"\n            :disabled=\"disabled\"\n            animation=\"150\"\n            class=\"base-expand-list__draggable\">\n            <BaseExpandListRow\n              v-for=\"(item, index) in dataInt\"\n              ref=\"baseExpandListRow\"\n              :key=\"index\"\n              :data=\"item\"\n              :edit=\"true\"\n              :edit-hide-text=\"editHideText\"\n              :edit-show-text=\"editShowText\"\n              :control-type=\"controlType\"\n              :disabled=\"disabled\"\n              class=\"base-expand-list__draggable__item\"\n              @assistive=\"assistive($event, index)\"\n              @sorted=\"sort($event, index)\"\n              @update:data=\"updateData($event, index)\" />\n          </component>\n        </div>\n      </template>\n    </div>\n\n    <BaseButton\n      v-if=\"showList && data.length > minItems\"\n      :id=\"`base-expand-list-${internalId}`\"\n      :aria-expanded=\"showAll ? 'true' : 'false'\"\n      :has-background-color=\"false\"\n      icon=\"drop-down\"\n      icon-position=\"right\"\n      :text=\"showAll ? showLessText : showMoreText\"\n      :class=\"{ 'base-button--rotate-icon-180': showAll }\"\n      @clicked=\"showAll = !showAll\" />\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n  .base-expand-list {\n    &__draggable {\n      outline: none;\n    }\n  }\n</style>\n","<script>\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport BaseCheckmark from '@/components/BaseCheckmark/BaseCheckmark.vue';\nimport { computed, ref, useSlots } from 'vue';\nimport { useId } from '@/composables/useId.js';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\n\nexport default {\n  name: 'BaseExpandRow',\n  components: {\n    BaseCheckmark,\n    BaseIcon,\n  },\n  props: {\n    /**\n     * specify if box is expandable\n     */\n    expandable: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * Title of the row.\n     */\n    title: {\n      type: String,\n      default: '',\n    },\n    /**\n     * Optional subtitle of the row.\n     */\n    subtitle: {\n      type: String,\n      default: '',\n    },\n    /**\n     * Lets you optionally specify an icon that is displayed before the title.\n     * For valid values, see [BaseIcon](BaseIcon).\n     */\n    icon: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set the background of collapsed expand-row-body\n     */\n    bodyHasBackground: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * Set this to `true` if the row should be in expanded state.\n     */\n    isExpanded: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * Lets you specify if the row is selectable. If `true`, a check box appears\n     * on the left side. The `isSelected` prop determines whether the check box is\n     * actually selected or not.\n     */\n    isSelectable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * Lets you specify if the row is currently selected.\n     */\n    isSelected: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * provide assistive text for screen readers\n     * **label**: if `title` or `subtitle` is empty this text is read\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        label: 'Expandable element',\n      }),\n      validator: val => Object.keys(val).every(key => ['label'].includes(key)),\n    },\n  },\n  emits: ['selected', 'expanded'],\n  setup(props) {\n    /** INTERNAL ID */\n    const internalId = useId();\n    /** INTERNATIONALIZATION */\n    const { getI18nTerm } = useI18n();\n    /** SLOTS */\n    // access slots to check if it is filled later\n    const slots = useSlots();\n    /**\n     * check if slot `default` has content\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const { slotHasContent: hasDefaultSlot } = useHasSlotContent(slots.default);\n    /**\n     * check if slot `icon` has content\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const { slotHasContent: hasIconSlot } = useHasSlotContent(slots.icon);\n    /** INTERNALS */\n    /**\n     * check if component is marked as selected\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const isSelectedInternal = ref(props.isSelected);\n    /**\n     * check if component is expanded\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const isExpandedInternal = ref(props.isExpanded && hasDefaultSlot.value);\n    /**\n     * check if component is expandable\n     * @type {ComputedRef<boolean>}\n     */\n    const isExpandable = computed(() => props.expandable && hasDefaultSlot.value);\n\n    return {\n      internalId,\n      isExpandable,\n      isExpandedInternal,\n      isSelectedInternal,\n      getI18nTerm,\n      hasDefaultSlot,\n      hasIconSlot,\n    }\n  },\n  watch: {\n    /**\n     * watch for expandable state changes from outside\n     * @param {boolean} val - the prop value set from outside\n     */\n    expandable(val) {\n      // when component is not expandable, collapse the content area\n      if (!val) this.isExpandedInternal = false;\n    },\n    /**\n     * watch for expanded/collapsed state changes from outside\n     * @param {boolean} val - the prop value set from outside\n     */\n    isExpanded(val) {\n      this.isExpandedInternal = val;\n    },\n    /**\n     * watch for select state changes from outside\n     * @param {boolean} val - the prop value set from outside\n     */\n    isSelected(val) {\n      this.isSelectedInternal = val;\n    },\n  },\n  methods: {\n    clicked() {\n      this.isExpandedInternal = !this.isExpandedInternal;\n      /**\n       * Event triggered when the row is expanded or collapsed.\n       * The payload value `true` indicates expanded state, `false` indicates collapsed state.\n       *\n       * @event expanded\n       * @param {Boolean} - is row expanded\n       */\n      this.$emit('expanded', this.isExpandedInternal);\n    },\n    checkboxClicked() {\n      this.isSelectedInternal = !this.isSelectedInternal;\n      /**\n       * Event triggered when the *check box* is clicked; this is applicable\n       * only if the row is selectable and thus has a check box.\n       * The payload indicates the selected state (true or false).\n       *\n       * @event selected\n       * @param {Boolean} - was row selected\n       */\n      this.$emit('selected', this.isSelectedInternal);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    :class=\"['base-expand-row',\n             { 'base-expand-row--expandable': isExpandable },\n             { 'base-expand-row--expanded': isExpandedInternal }]\">\n    <div class=\"base-expand-row__header\">\n      <BaseCheckmark\n        v-if=\"isSelectable\"\n        :key=\"internalId + 'checkmark'\"\n        mark-style=\"checkbox\"\n        :model-value=\"isSelected\"\n        class=\"base-expand-row__header__checkbox\"\n        @update:model-value=\"checkboxClicked\" />\n      <component\n        :is=\"isExpandable ? 'button' : 'div'\"\n        :id=\"'base-expand-row-' + internalId\"\n        :aria-controls=\"isExpandable ? 'base-expand-row-panel-' + internalId : undefined\"\n        :aria-expanded=\"isExpandable ? isExpandedInternal : undefined\"\n        :type=\"isExpandable ? 'button' : undefined\"\n        :class=\"['base-expand-row__header__button', { selectable: isSelectable }]\"\n        @click=\"isExpandable ? clicked() : null\">\n        <div\n          v-if=\"icon || hasIconSlot\"\n          class=\"base-expand-row__header__icon\">\n          <!-- @slot slot to inject icon/image left side before label -->\n          <slot name=\"icon\">\n            <BaseIcon\n              :name=\"icon\" />\n          </slot>\n        </div>\n\n        <div\n          class=\"base-expand-row__header__wrapper\">\n          <div\n            v-if=\"!title && !subtitle\"\n            class=\"hide\">\n            {{ getI18nTerm(assistiveText.label) }}\n          </div>\n          <div\n            v-if=\"title\"\n            class=\"base-expand-row__header__title base-text-fade-out\">\n            {{ title }}\n          </div>\n          <div\n            v-if=\"subtitle\"\n            class=\"base-expand-row__header__subtitle base-text-fade-out\">\n            {{ subtitle }}\n          </div>\n        </div>\n        <BaseIcon\n          v-if=\"isExpandable\"\n          name=\"drop-down\"\n          class=\"base-expand-row__header__collapse-icon\" />\n      </component>\n    </div>\n    <div\n      :id=\"'base-expand-row-panel-' + internalId\"\n      :aria-labelledby=\"'base-expand-row-' + internalId\"\n      :aria-hidden=\"!isExpandedInternal ? 'true' : 'false'\"\n      :role=\"'region'\"\n      :class=\"['base-expand-row__body', { 'base-expand-row__body--bg': bodyHasBackground }]\">\n      <!-- @slot slot for expanded content -->\n      <slot />\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-expand-row {\n    margin-bottom: $border-width;\n    background-color: $background-color;\n\n    .base-expand-row__header {\n      display: flex;\n      justify-content: flex-start;\n      align-items: center;\n      background: $box-color;\n      box-shadow: $box-shadow-reg;\n      transition: $box-transition;\n\n      .base-expand-row__header__checkbox {\n        padding: 0 $spacing;\n        width: $spacing * 3;\n      }\n\n      .base-expand-row__header__button {\n        height: $row-height-large;\n        padding: 0 $spacing;\n        width: 100%;\n        display: flex;\n        justify-content: flex-start;\n        align-items: center;\n\n        .base-expand-row__header__wrapper {\n          flex: auto;\n          margin-right: $spacing;\n          overflow: hidden;\n        }\n\n        .base-expand-row__header__title {\n          color: $font-color;\n          text-align: left;\n          white-space: nowrap;\n        }\n\n        .base-expand-row__header__subtitle {\n          font-size: $font-size-small;\n          color: $font-color-second;\n          text-align: left;\n          white-space: nowrap;\n        }\n\n        .base-expand-row__header__icon {\n          height: $icon-large;\n          width: $icon-large;\n          margin-right: $spacing;\n          color: currentColor;\n          flex-shrink: 0;\n\n          svg,\n          img {\n            width: 100%;\n          }\n        }\n\n        .base-expand-row__header__collapse-icon {\n          transition: $drop-down-arrow-animation;\n          height: $icon-small;\n          width: $icon-small;\n          min-width: $icon-small;\n          color: $font-color;\n        }\n\n        &.selectable {\n          // if row is selectable, we must account for the width of the check box.\n          // therefore, decrease 100% width by the width of .base-expand-row__header__checkbox\n          width: calc(100% - #{$spacing} * 3);\n          padding: 0 $spacing 0 0;\n        }\n      }\n\n      &:focus {\n        outline: none;\n      }\n    }\n\n    .base-expand-row__body {\n      padding: $spacing;\n\n      &.base-expand-row__body--bg {\n        margin-top: $border-width;\n        background-color: $box-color;\n      }\n    }\n\n    &.base-expand-row--expandable {\n      .base-expand-row__header__button {\n\n        &:focus,\n        &:hover {\n          cursor: pointer;\n\n          .base-expand-row__header__collapse-icon {\n            color: $app-color;\n          }\n        }\n      }\n    }\n\n    &.base-expand-row--expanded {\n      .base-expand-row__header {\n        .base-expand-row__header__button {\n          .base-expand-row__header__wrapper {\n            .base-expand-row__header__title {\n              color: $font-color;\n              font-weight: bold;\n            }\n          }\n        }\n      }\n\n      .base-expand-row__body {\n        display: block;\n      }\n\n      .base-expand-row__header__collapse-icon {\n        transform: rotate(180deg);\n      }\n    }\n\n    .base-expand-row__body {\n      display: none;\n    }\n  }\n</style>\n","<script>\nimport { defineAsyncComponent, toRef } from 'vue';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { useExtractAttrs } from '@/composables/useExtractAttrs.js';\n\n/**\n * A component for form field creation via [openAPI](https://spec.openapis.org/oas/v3.1.0/) standard\n */\n\nexport default {\n  name: 'BaseFormFieldCreator',\n  components: {\n    BaseDropDown: defineAsyncComponent(() => import('@/components/BaseDropDown/BaseDropDown.vue')),\n    BaseDateInput: defineAsyncComponent(() => import('@/components/BaseDateInput/BaseDateInput.vue')),\n    BaseToggle: defineAsyncComponent(() => import('@/components/BaseToggle/BaseToggle.vue')),\n    BaseLink: defineAsyncComponent(() => import('@/components/BaseLink/BaseLink.vue')),\n    BaseInsertTextAsHtml: defineAsyncComponent(() => import('@/components/BaseInsertTextAsHtml/BaseInsertTextAsHtml.vue')),\n  },\n  inheritAttrs: false,\n  props: {\n    /**\n     * a key to uniquely identify the field\n     */\n    fieldKey: {\n      type: [Number, String],\n      required: true,\n    },\n    /**\n     * field information as provided in [openAPI](https://spec.openapis.org/oas/v3.1.0#schema-object) standard\n     */\n    field: {\n      type: Object,\n      required: true,\n    },\n    /**\n     * the field value\n     */\n    modelValue: {\n      type: [Object, String, Array, Date, Number, Boolean, null],\n      required: true,\n    },\n    /**\n     * add properties any input field can take and set values - find the possible variables at the\n     * respective input components:\n     * [BaseInput](BaseInput)\n     * [BaseAutocompleteInput](BaseAutocompleteInput)\n     * [BaseMultilineTextInput](BaseMultilineTextInput)\n     * [BaseChipsInput](BaseChipsInput)\n     * [BaseChipsBelow](BaseChipsBelow)\n     * [BaseDateInput](BaseDateInput)\n     * [BaseToggle](BaseToggle)\n     *\n     * **Caveat**: this means several input field properties are settable via separate props as well\n     * as via `fieldProps` (e.g. `language`, `required`, `sortText`) the logic here is the following:\n     *  separate props will have priority over `fieldProps` values **unless** the separate\n     *  prop has a default value other than ones evaluating to `false` (boolean false,\n     *  empty string).\n     *  Field props that are set via `x-attrs` (e.g. `allowUnknownEntries`) in the OpenAPI definition\n     *  have priority over `fieldProps` set values.\n     *  Fields for which a unified appearance makes sense (e.g. `clearable`, `showErrorIcon`) or that\n     *  are modified internally (e.g. `input`, `selectedList`) might not be settable\n     *  via `fieldProps`.\n     */\n    fieldProps: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * a label for the field\n     */\n    label: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define if field label should be shown\n     */\n    showLabel: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * a placeholder for the field\n     * per default the placeholder attribute in OpenAPI `x-attrs` field will be used\n     * (no need to specify that)\n     */\n    placeholder: {\n      type: [String, Object],\n      default: '',\n    },\n    /**\n     * provide an options list for `autocomplete`, `chips` or `chips-below` fields\n     * for field type `group` provide a nested object with field names\n     * as properties and an array for each field to ensure the correct options are assigned\n     * even if field names within different groups are identical\n     */\n    dropDownList: {\n      type: [Array, Object],\n      default: () => [],\n    },\n    /**\n     * provide a second options list (needed e.g. for texts field (text type) or\n     * contributors field (roles)\n     */\n    secondaryDropdown: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * possibility to steer field loading (`chips`, `autocomplete`) from outside\n     */\n    autocompleteLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set the current language\n     */\n    language: {\n      type: String,\n      default: 'en',\n    },\n    /**\n     * provide available locales\n     */\n    availableLocales: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * set a sorting text\n     */\n    sortText: {\n      type: String,\n      default: 'Sort A - Z',\n    },\n    /**\n     * pass down all necessary options for potential subform.\n     *   see [BaseForm props](BaseForm)\n     */\n    fieldGroupParams: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * mark as required field\n     *\n     * **Caveat**: currently the required prop is only used to trigger [BaseChipsBelow](BaseChipsBelow) validation -\n     *             for all other form fields it is only used for the `aria-required` attributes\n     * **Note**: if required is also set via OpenAPI definition x-attrs (provided by prop `field`) this will overwrite the prop!\n     * value can be an object if `field_type` date has several values\n     */\n    required: {\n      type: [Boolean, Object],\n      default: false,\n    },\n    /**\n     * set `true` if input field should be disabled\n     * for an example see [BaseInput](BaseInput)\n     * value can be an object if `field_type` date has several values\n     */\n    disabled: {\n      type: [Boolean, Object],\n      default: false,\n    },\n    /**\n     * mark the form field as invalid and ideally also provide an error message\n     * to display below the form field.\n     * for an example see [BaseInput](BaseInput)\n     * value can be an object if `field_type` date has several values\n     */\n    invalid: {\n      type: [Boolean, Object],\n      default: false,\n    },\n    /**\n     * add an error message to be displayed below form field if field is invalid.\n     * for an example see [BaseInput](BaseInput)\n     * for `field_type` 'group' an Object with the fields can be passed on or\n     * value can be an object if `field_type` date has several values\n     */\n    errorMessage: {\n      type: [String, Object],\n      default: '',\n    },\n    /**\n     * define validation texts to be displayed below form field if input is invalid.\n     * for an example see [BaseInput](BaseInput)\n     */\n    validationTexts: {\n      type: Object,\n      default: () => ({\n        text: {\n          min: 'Value must be greater than or equal to {value}.',\n          max: 'Value must be less than or equal to {value}.',\n          minLength: 'Text must be at least {value} character(s) long.',\n          maxLength: 'Text cannot be longer than {value} characters.',\n        },\n        chips: {\n          required: 'Select an option.',\n        },\n      }),\n      // checking if all necessary properties are part of the provided object\n      validator: val => !Object.keys(val).length || (['text'].every(prop => Object.keys(val).includes(prop))\n        && ['min', 'max', 'minLength', 'maxLength']\n          .every(prop => Object.keys(val.text).includes(prop))),\n    },\n    /**\n     * define if error icon should be shown.\n     * for an example see [BaseInput](BaseInput)\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * if `true` a remove icon will be shown allowing to remove\n     * all input at once.\n     * for an example see [BaseInput](BaseInput)\n     */\n    clearable: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * specify the object property that should be used as identifier\n     */\n    identifierPropertyName: {\n      type: String,\n      default: 'source',\n    },\n    /**\n     * specify the object property that should be used as value to be displayed\n     */\n    labelPropertyName: {\n      type: String,\n      default: 'label',\n    },\n    /**\n     * this prop gives the option to add assistive text for screen readers\n     * properties:\n     *\n     * Options for all input types (except `boolean`):\n     * **clearInput**: text read for remove input icon if prop `clearable` is set `true`\n     *\n     * Options for inputs type `autocomplete`, `chips`, `chips-below`:\n     * **loaderActive**: text that is announced when options are being fetched (prop\n     *  `isLoading` is set `true`)\n     *\n     * Options for inputs type `chips`:\n     * **optionToRemoveSelected**: text read when option is marked active for removal (by using\n     *  backspace in empty input field). string {label} could be added to be replaced\n     *  by the actual chip label (value in [`labelPropertyName`])\n     *\n     * Options for inputs type `chips`, `chips-below`:\n     * **resultsRetrieved**: text that is announced when results were retrieved (drop down\n     *  list changed)\n     * **optionAdded**: text read when option was added to the selected list. string {label}\n     *  could be added to be replaced by the actual chip label (value in [`labelPropertyName`])\n     * **optionRemoved**: text read when option was removed from the selected list. string {label}\n     *  could be added to be replaced by the actual chip label (value in [`labelPropertyName`])\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        loaderActive: 'loading.',\n        clearInput: 'Clear input',\n        resultsRetrieved: '{number} options in drop down.',\n        optionAdded: 'option {label} added to selected list.',\n        optionToRemoveSelected: 'option {label} from selected list marked for removal. Press delete or backspace to remove.',\n        optionRemoved: 'option {label} removed.',\n      }),\n    },\n  },\n  emits: ['input-complete', 'fetch-autocomplete', 'update:model-value'],\n  setup(props) {\n    /** INTERNATIONALIZATION */\n    const { getLangLabel, hasI18n, getI18nTerm, setLangLabels } = useI18n(toRef(props, 'language'));\n\n    /** ATTRS HANDLING */\n    const { rootAttrs, forwardAttrs } = useExtractAttrs();\n\n    return {\n      getLangLabel,\n      hasI18n,\n      getI18nTerm,\n      setLangLabels,\n      rootAttrs,\n      forwardAttrs,\n    };\n  },\n  data() {\n    return {\n      /**\n       * internal representation of field value\n       * @type {any}\n       */\n      fieldValueInt: null,\n      /**\n       * variable for current text input in chips fields\n       * @type {string}\n       */\n      textInput: '',\n      /**\n       * internal loading indicator\n       * @type {boolean}\n       */\n      fetchingData: false,\n      /**\n       * internal active tab for multiline text field\n       * @type {string}\n       */\n      activeTab: '',\n      /**\n       * store a copy of fieldValueInt to only trigger event when value\n       *  has changed\n       *  @type {any}\n       */\n      originalFieldValueInt: null,\n    };\n  },\n  computed: {\n    /**\n     * need internal variable to be able to add event listeners\n     * @returns {Object}\n     */\n    fieldPropsInt() {\n      return {\n        ...this.forwardAttrs,\n        ...this.fieldProps,\n      };\n    },\n    /**\n     * need internal variable to be able to add event listeners\n     * @returns {Object}\n     */\n    fieldGroupParamsInt() {\n      return {\n        ...this.forwardAttrs,\n        ...this.fieldGroupParams,\n        formFieldJson: this.groupFormFields,\n        modelValue: this.fieldValueInt,\n        formId: `${this.fieldKey}_${this.field.name}`,\n        fieldProps: this.fieldProps,\n        dropDownLists: this.fieldGroupDropDownLists,\n        // if type is 'group' error messages need to be passed on - otherwise leave empty object\n        errorMessagesObject: typeof this.errorMessage === 'string' ? {} : this.errorMessage,\n      };\n    },\n    /**\n     * import the relevant component\n     * @returns {{readonly default?: {name: string, components: {BaseIcon: {name: string, props: {name: {type: String | StringConstructor, default: null, validator(*): *}, title: {type: String | StringConstructor, default: string}, desc: {type: String | StringConstructor, default: string}}, setup(): {internalId: *}, data(): {baseIcons: null}, computed: {icon(): string, ariaAttribute(): *}, mounted(): void}, BaseLoader: {new(): {$: ComponentInternalInstance, $data: {}, $props: {readonly textOnLoaderShow: string, readonly hide: boolean, readonly position: Object, readonly loaderColor: string}, $attrs: Data, $refs: {readonly loader: RefObject<HTMLElement|null> | RefCallback<HTMLElement|null>, [p: string]: unknown}, $slots: (UnwrapSlotsType<any>&{}), $root: ComponentPublicInstance | null, $parent: ComponentPublicInstance | null, $host: Element | null, $emit: (event: string, ...args: any[]) => void, $el: any, $options: any, $forceUpdate: () => void, $nextTick: typeof nextTick, $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends ((...args: any) => infer R) ? ((...args: [R, R, OnCleanup]) => any) : ((...args: [any, any, OnCleanup]) => any), options?: WatchOptions): WatchStopHandle, readonly textOnLoaderShow: string, readonly hide: boolean, readonly position: Object, readonly loaderColor: string}, readonly default?}}, inheritAttrs: boolean, props: {modelValue: {type: [String | StringConstructor,Number | NumberConstructor], default: string}, label: {type: String | StringConstructor, required: boolean}, showLabel: {type: Boolean | BooleanConstructor, default: boolean}, inputId: {type: String | StringConstructor, default: string}, placeholder: {type: String | StringConstructor, default: string}, required: {type: Boolean | BooleanConstructor, default: boolean}, invalid: {type: Boolean | BooleanConstructor, default: boolean}, errorMessage: {type: String | StringConstructor, default: string}, showErrorIcon: {type: Boolean | BooleanConstructor, default: boolean}, fieldType: {type: String | StringConstructor, default: string, validator: function(*): *}, dropDownListId: {type: String | StringConstructor, default: string}, linkedListOption: {type: [Number | NumberConstructor,String | StringConstructor], default: null}, hideInputField: {type: Boolean | BooleanConstructor, default: boolean}, isActive: {type: Boolean | BooleanConstructor, default: null}, showInputBorder: {type: Boolean | BooleanConstructor, default: boolean}, useFormFieldStyling: {type: Boolean | BooleanConstructor, default: boolean}, clearable: {type: Boolean | BooleanConstructor, default: boolean}, loadable: {type: Boolean | BooleanConstructor, default: boolean}, isLoading: {type: Boolean | BooleanConstructor, default: boolean}, useFadeOut: {type: Boolean | BooleanConstructor, default: boolean}, inputClass: {type: String | StringConstructor, default: string}, language: {type: String | StringConstructor, default: string, validator: function(*): *}, setFocusOnActive: {type: Boolean | BooleanConstructor, default: boolean}, disabled: {type: Boolean | BooleanConstructor, default: boolean}, minLength: {type: Number | NumberConstructor, default: null}, maxLength: {type: Number | NumberConstructor, default: null}, decimals: {type: Number | NumberConstructor, default: null}, decimalSeparator: {type: String | StringConstructor, default: string}, min: {type: Number | NumberConstructor, default: null}, max: {type: Number | NumberConstructor, default: null}, validationTexts: {type: Object | ObjectConstructor, default: function(): {min: string, max: string, minLength: string, maxLength: string}, validator: function(*): *}, assistiveText: {type: Object | ObjectConstructor, default: function(): {loaderActive: string}}, ignoreClickOutside: {type: Array | ArrayConstructor, default: function(): []}}, emits: string[], setup(*, {emit: *, slots: *}): {idInt: RefObject<string extends (Builtin | Ref | RefUnwrapBailTypes[keyof RefUnwrapBailTypes] | {[RawSymbol]?: true}) ? string : (string extends Map<infer K, infer V> ? (Map<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof Map<any, any>>>) : (string extends WeakMap<infer K, infer V> ? (WeakMap<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof WeakMap<any, any>>>) : (string extends Set<infer V> ? (Set<UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof Set<any>>>) : (string extends WeakSet<infer V> ? (WeakSet<UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof WeakSet<any>>>) : (string extends ReadonlyArray<any> ? {[K in keyof string]: UnwrapRefSimple<string[K]>} : (string extends (object & {[ShallowReactiveMarker]?: never}) ? {[P in keyof string]: P extends symbol ? string[P] : UnwrapRef<string[P]>} : string)))))) | number extends (Builtin | Ref | RefUnwrapBailTypes[keyof RefUnwrapBailTypes] | {[RawSymbol]?: true}) ? number : (number extends Map<infer K, infer V> ? (Map<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<number, keyof Map<any, any>>>) : (number extends WeakMap<infer K, infer V> ? (WeakMap<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<number, keyof WeakMap<any, any>>>) : (number extends Set<infer V> ? (Set<UnwrapRefSimple<V>> & UnwrapRef<Omit<number, keyof Set<any>>>) : (number extends WeakSet<infer V> ? (WeakSet<UnwrapRefSimple<V>> & UnwrapRef<Omit<number, keyof WeakSet<any>>>) : (number extends ReadonlyArray<any> ? {[K in keyof number]: UnwrapRefSimple<number[K]>} : (number extends (object & {[ShallowReactiveMarker]?: never}) ? {[P in keyof number]: P extends symbol ? number[P] : UnwrapRef<number[P]>} : number))))))> | RefCallback<string extends (Builtin | Ref | RefUnwrapBailTypes[keyof RefUnwrapBailTypes] | {[RawSymbol]?: true}) ? string : (string extends Map<infer K, infer V> ? (Map<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof Map<any, any>>>) : (string extends WeakMap<infer K, infer V> ? (WeakMap<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof WeakMap<any, any>>>) : (string extends Set<infer V> ? (Set<UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof Set<any>>>) : (string extends WeakSet<infer V> ? (WeakSet<UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof WeakSet<any>>>) : (string extends ReadonlyArray<any> ? {[K in keyof string]: UnwrapRefSimple<string[K]>} : (string extends (object & {[ShallowReactiveMarker]?: never}) ? {[P in keyof string]: P extends symbol ? string[P] : UnwrapRef<string[P]>} : string)))))) | number extends (Builtin | Ref | RefUnwrapBailTypes[keyof RefUnwrapBailTypes] | {[RawSymbol]?: true}) ? number : (number extends Map<infer K, infer V> ? (Map<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<number, keyof Map<any, any>>>) : (number extends WeakMap<infer K, infer V> ? (WeakMap<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<number, keyof WeakMap<any, any>>>) : (number extends Set<infer V> ? (Set<UnwrapRefSimple<V>> & UnwrapRef<Omit<number, keyof Set<any>>>) : (number extends WeakSet<infer V> ? (WeakSet<UnwrapRefSimple<V>> & UnwrapRef<Omit<number, keyof WeakSet<any>>>) : (number extends ReadonlyArray<any> ? {[K in keyof number]: UnwrapRefSimple<number[K]>} : (number extends (object & {[ShallowReactiveMarker]?: never}) ? {[P in keyof number]: P extends symbol ? number[P] : UnwrapRef<number[P]>} : number))))))>, rootAttrs: ComputedRef<{}>, forwardAttrs: ComputedRef<{}>, showLabelRow: ComputedRef<boolean>, showRemoveIcon: ComputedRef<boolean>, inputInt: RefObject<string extends (Builtin | Ref | RefUnwrapBailTypes[keyof RefUnwrapBailTypes] | {[RawSymbol]?: true}) ? string : (string extends Map<infer K, infer V> ? (Map<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof Map<any, any>>>) : (string extends WeakMap<infer K, infer V> ? (WeakMap<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof WeakMap<any, any>>>) : (string extends Set<infer V> ? (Set<UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof Set<any>>>) : (string extends WeakSet<infer V> ? (WeakSet<UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof WeakSet<any>>>) : (string extends ReadonlyArray<any> ? {[K in keyof string]: UnwrapRefSimple<string[K]>} : (string extends (object & {[ShallowReactiveMarker]?: never}) ? {[P in keyof string]: P extends symbol ? string[P] : UnwrapRef<string[P]>} : string))))))> | RefCallback<string extends (Builtin | Ref | RefUnwrapBailTypes[keyof RefUnwrapBailTypes] | {[RawSymbol]?: true}) ? string : (string extends Map<infer K, infer V> ? (Map<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof Map<any, any>>>) : (string extends WeakMap<infer K, infer V> ? (WeakMap<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof WeakMap<any, any>>>) : (string extends Set<infer V> ? (Set<UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof Set<any>>>) : (string extends WeakSet<infer V> ? (WeakSet<UnwrapRefSimple<V>> & UnwrapRef<Omit<string, keyof WeakSet<any>>>) : (string extends ReadonlyArray<any> ? {[K in keyof string]: UnwrapRefSimple<string[K]>} : (string extends (object & {[ShallowReactiveMarker]?: never}) ? {[P in keyof string]: P extends symbol ? string[P] : UnwrapRef<string[P]>} : string))))))>, inputMode: ComputedRef<string|null>, input: RefObject<HTMLElement extends ShallowRef<infer V, unknown> ? V : (HTMLElement extends Ref<infer V, unknown> ? UnwrapRefSimple<V> : UnwrapRefSimple<HTMLElement>) | null extends ShallowRef<infer V, unknown> ? V : (null extends Ref<infer V, unknown> ? UnwrapRefSimple<V> : UnwrapRefSimple<null>)> | RefCallback<HTMLElement extends ShallowRef<infer V, unknown> ? V : (HTMLElement extends Ref<infer V, unknown> ? UnwrapRefSimple<V> : UnwrapRefSimple<HTMLElement>) | null extends ShallowRef<infer V, unknown> ? V : (null extends Ref<infer V, unknown> ? UnwrapRefSimple<V> : UnwrapRefSimple<null>)>, inputElement: ComputedRef<HTMLElement|null>, inputFrame: [null] extends [Ref] ? IfAny<null, Ref<null>, null> : Ref<UnwrapRef<null>, UnwrapRef<null> | null>, isActiveInt: Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>, labelLocalized: ComputedRef<Object|string>, internalValidationMessage: Ref<UnwrapRef<string>, UnwrapRef<string> | string>, errorMessageInt: ComputedRef<Object|string>, setFieldState: function(boolean): void}, data(): {previousInput: (string|number), internalValidationFailed: boolean}, computed: {isFieldTypeNumber(): boolean, invalidInt(): boolean}, watch: {modelValue: {handler(*): void, immediate: boolean}, isActive: {handler(*): void, immediate: boolean}, isActiveInt(boolean): void, invalidInt(boolean): void}, mounted(): void, methods: {onKeydown(*): void, onInput(InputEvent): void, updateModelValue(): void, onInputBlur(FocusEvent): void, blurInput(KeyboardEvent): void, clickedInside((FocusEvent|MouseEvent)): void, removeInput(): void, handleInputTab(*): void, validate(string): (string|undefined), translateFloat((number|string)): string, stringToFloat(string): number, inputIsNaN(string): boolean, roundDecimals(*): string, removeMultipleChars(String, String): string}}}|null|{new(): {$: ComponentInternalInstance, $data: {}, $props: {readonly assistiveText: Object, readonly highlightStringTags: *[], readonly highlightStringMatch: boolean, readonly dynamicFetch: boolean, readonly dropDownNoOptionsInfo: string, readonly labelPropertyName: string, readonly identifierPropertyName: string, readonly disabled: boolean, readonly language: string, readonly isLoading: boolean, readonly loadable: boolean, readonly clearable: boolean, readonly useFormFieldStyling: boolean, readonly showInputBorder: boolean, readonly isActive: boolean, readonly showErrorIcon: boolean, readonly errorMessage: string, readonly invalid: boolean, readonly required: boolean, readonly placeholder: string, readonly inputId: string, readonly showLabel: boolean, readonly label: string, readonly list: *[], readonly modelValue: string|number}, $attrs: Data, $refs: {readonly autocompleteInput: RefObject<HTMLElement extends ShallowRef<infer V, unknown> ? V : (HTMLElement extends Ref<infer V, unknown> ? UnwrapRefSimple<V> : UnwrapRefSimple<HTMLElement>) | null extends ShallowRef<infer V, unknown> ? V : (null extends Ref<infer V, unknown> ? UnwrapRefSimple<V> : UnwrapRefSimple<null>)> | RefCallback<HTMLElement extends ShallowRef<infer V, unknown> ? V : (HTMLElement extends Ref<infer V, unknown> ? UnwrapRefSimple<V> : UnwrapRefSimple<HTMLElement>) | null extends ShallowRef<infer V, unknown> ? V : (null extends Ref<infer V, unknown> ? UnwrapRefSimple<V> : UnwrapRefSimple<null>)>, [p: string]: unknown}, $slots: (UnwrapSlotsType<any>&{readonly 'drop-down-entry'?: Slot, readonly 'label-addition'?: Slot, readonly 'pre-input-field'?: Slot, readonly 'input-field-addition-before'?: Slot, readonly 'input-field-inline-before'?: Slot, readonly 'input-field-addition-after'?: Slot, readonly 'post-input-field'?: Slot, readonly 'error-icon'?: Slot, readonly 'remove-icon'?: Slot}), $root: ComponentPublicInstance | null, $parent: ComponentPublicInstance | null, $host: Element | null, $emit: (event: (\"update:model-value\" | \"fetch-dropdown-entries\" | \"update:is-active\" | \"selected\"), ...args: any[]) => any, $el: any, $options: any, $forceUpdate: () => void, $nextTick: typeof nextTick, $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends ((...args: any) => infer R) ? ((...args: [R, R, OnCleanup]) => any) : ((...args: [any, any, OnCleanup]) => any), options?: WatchOptions): WatchStopHandle, readonly assistiveText: Object, readonly highlightStringTags: *[], readonly highlightStringMatch: boolean, readonly dynamicFetch: boolean, readonly dropDownNoOptionsInfo: string, readonly labelPropertyName: string, readonly identifierPropertyName: string, readonly disabled: boolean, readonly language: string, readonly isLoading: boolean, readonly loadable: boolean, readonly clearable: boolean, readonly useFormFieldStyling: boolean, readonly showInputBorder: boolean, readonly isActive: boolean, readonly showErrorIcon: boolean, readonly errorMessage: string, readonly invalid: boolean, readonly required: boolean, readonly placeholder: string, readonly inputId: string, readonly showLabel: boolean, readonly label: string, readonly list: *[], readonly modelValue: string|number}, readonly default?}}\n     */\n    fieldElement() {\n      if (this.fieldType === 'text' || this.fieldType === 'integer' || this.fieldType === 'float') {\n        return defineAsyncComponent(() => import('@/components/BaseInput/BaseInput.vue'));\n      } if (this.fieldType === 'multiline') {\n        return defineAsyncComponent(() => import('@/components/BaseMultilineTextInput/BaseMultilineTextInput.vue'));\n      } if (this.fieldType === 'autocomplete') {\n        return defineAsyncComponent(() => import('@/components/BaseAutocompleteInput/BaseAutocompleteInput.vue'));\n      } if (this.fieldType === 'chips') {\n        return defineAsyncComponent(() => import('@/components/BaseChipsInput/BaseChipsInput.vue'));\n      } if (this.fieldType === 'chips-below') {\n        return defineAsyncComponent(() => import('@/components/BaseChipsBelow/BaseChipsBelow.vue'));\n      } if (this.fieldType === 'group') {\n        return defineAsyncComponent(() => import('@/components/BaseForm/BaseForm.vue'));\n      }\n      return null;\n    },\n\n    /**\n     * determine if BaseMultilineTextInput has drop down options\n     * TODO: currently hardcoded as 'type'\n     * @returns {boolean}\n     */\n    multilineHasDropdownOptions() {\n      return !!this.field.items?.properties?.type;\n    },\n    /**\n     * determine if BaseMultilineTextInput has tabs\n     * @returns {boolean}\n     */\n    multilineHasTabs() {\n      return !!this.tabs?.length;\n    },\n    /**\n     * check which date field type was provided and set type accordingly\n     * @returns {string}\n     */\n    dateType() {\n      // check if date is an Object with properties or just string (= single date)\n      // also need to check items in case date field is repeatable\n      const props = this.field.properties || (this.field.items && this.field.items.properties)\n        ? Object.keys(this.field.properties || this.field.items.properties) : [];\n      if (!this.field.properties && (!this.field.items || !this.field.items.properties)) {\n        return 'single';\n      }\n      if (props.includes('date_to') && props.includes('time_to')) {\n        return 'daterangetimerange';\n      }\n      if (props.includes('date') && props.includes('time_to')) {\n        return 'datetimerange';\n      }\n      if (props.includes('time')) {\n        return 'datetime';\n      }\n      if (props.includes('date_to')) {\n        return 'daterange';\n      }\n      if (props.includes('time_from') && props.includes('time_to')) {\n        return 'timerange';\n      }\n      return 'single';\n    },\n    dateErrorMessage() {\n      if (this.fieldType !== 'date') return '';\n      if (typeof this.errorMessage === 'object') {\n        return Object.fromEntries(Object.entries(this.errorMessage).map(([key, value]) => {\n          return [key, typeof value === 'object' && value.length ? value.join(' ') : value];\n        }));\n      }\n      return this.errorMessage;\n    },\n    dateInvalid() {\n      if (this.fieldType !== 'date') return false;\n      if (this.invalid) return this.invalid;\n      if (typeof this.dateErrorMessage === 'object' && Object.keys(this.dateErrorMessage).length) {\n        return Object.fromEntries(Object.entries(this.dateErrorMessage).map(([key, value]) => [key, !!value]));\n      }\n      return this.fieldProps.invalid || false;\n    },\n    /**\n     * get field properties from swagger info - necessary for subforms\n     * @returns {Object}\n     */\n    groupFormFields() {\n      // check if field group is a list (=repeatable) or not\n      if (this.field.type === 'array') {\n        return this.field.items.properties;\n      }\n      return this.field.properties;\n    },\n    /**\n     * function to check if dropdowns for field groups are nested. Nesting was necessary\n     * to ensure every field group gets their own dropdown even if field names are identical.\n     * For backwards compatibility keep using direct base level fieldName array as fallback.\n     * @returns {{ [fieldName]: Object[] }}\n     */\n    fieldGroupDropDownLists() {\n      // get field name\n      const fieldName = this.field.name;\n      // get parent BaseForm $props.dropDownLists that were passed to BaseFormFieldCreator\n      // as fieldGroupParams\n      const { dropDownLists } = this.fieldGroupParams;\n      // check if the nested object with the fieldName exists, if not fall back to use\n      // field name directly\n      return dropDownLists && dropDownLists[fieldName]\n        ? dropDownLists[fieldName] : dropDownLists;\n    },\n    formFieldXAttrs() {\n      // x-attrs should exist however just in case if not return an empty object\n      // so that ['x-attrs'][xAttrProperty] does not throw errors\n      return this.field['x-attrs'] || {};\n    },\n    // the type default for texts field\n    textTypeDefault() {\n      return {\n        // map the language specific labels for no value selected to the default\n        [this.labelPropertyName]: this.setLangLabels('form.noTextType', this.availableLocales),\n        [this.identifierPropertyName]: '',\n      };\n    },\n    // compute the texts type drop down list specific for texts\n    textTypeOptions() {\n      return [this.textTypeDefault].concat(this.secondaryDropdown);\n    },\n    // for chips input fields - check if it is a contributors field\n    isContributorOrEquivalent() {\n      return this.field.name === 'contributors'\n        || this.formFieldXAttrs.equivalent === 'contributors';\n    },\n    // to determine text display for chips input\n    fieldInput() {\n      return this.textInput && this.textInput.length > 2;\n    },\n    // check if chips input is a single select field\n    isChipsSingleSelect() {\n      return (this.fieldType\n        && this.fieldType.includes('chips')\n        && this.field.type === 'object');\n    },\n    // check if label was specified - if not defer from title or check if there is a localized term\n    labelInt() {\n      if (this.label || this.fieldProps.label) {\n        return this.label || this.fieldProps.label;\n      }\n      return this.field.title || this.getI18nTerm(this.field.name ? `form.${this.field.name}` : this.field.name);\n    },\n    // check if placeholder was specified - if not defer from\n    // title or check if there is a localized term\n    placeholderInt() {\n      if (this.placeholder || this.fieldProps.placeholder) {\n        return this.placeholder || this.fieldProps.placeholder;\n      }\n      const internalPlaceholder = this.formFieldXAttrs.placeholder || '';\n      return internalPlaceholder || `${this.hasI18n ? this.getI18nTerm('form.select') : 'Select'} ${this.labelInt}`;\n    },\n    // compute field type\n    fieldType() {\n      return this.formFieldXAttrs.field_type || 'text';\n    },\n    tabs() {\n      if (this.field.items && this.field.items.properties && this.field.items.properties.data\n        && this.field.items.properties.data.items\n        && this.field.items.properties.data.items.properties\n        && this.field.items.properties.data.items.properties.language) {\n        return Object.keys(this.field.items.properties\n          .data.items.properties\n          .language.properties\n          .label.properties).filter(lang => this.availableLocales.includes(lang));\n      }\n      // if tabs are not set via language in the openAPI JSON check the fieldProps\n      // or just set an empty array\n      return this.fieldProps.tabs || [];\n    },\n    /**\n     * check if field is either type integer of float\n     * @returns {boolean}\n     */\n    isNumberField() {\n      // get OpenAPI json field type and check if its a repeatable field (array)\n      const openAPIFieldType = this.field.items ? this.field.items.type : this.field.type;\n      // valid OpenAPI number field types are 'integer' and 'number'\n      return ['integer', 'number'].includes(openAPIFieldType)\n        // include 'text' here for backwards compatibility\n        && ['integer', 'float', 'text'].includes(this.fieldType);\n    },\n    /**\n     * check allowed number of decimals\n     * @returns {number|null}\n     */\n    allowedDecimals() {\n      // check if decimals were configured with priority for x-attrs\n      const decimals = this.formFieldXAttrs.decimals || this.fieldProps.decimals;\n      // get OpenAPI definition field type and also consider repeatable fields\n      const numberFieldType = this.field.type === 'array' ? this.field.items.type : this.field.type;\n      // get the OpenAPI definition field format\n      const numberFieldFormat = this.field.type === 'array' ? this.field.items.format : this.field.format;\n      // for OpenAPI data type 'number', that have format specified allow endless decimals\n      // only 'float' and 'double' are defined in OpenAPI but it is an \"open string-valued property\"\n      // so adding 'decimal' since backend model has data type Decimal\n      if ((numberFieldType === 'number' && ['float', 'double', 'decimal'].includes(numberFieldFormat))\n        && !(decimals || decimals === 0)) {\n        return -1;\n      }\n      // for type float and decimals set limit to decimals\n      if ((numberFieldType === 'number' || this.fieldProps.fieldType === 'number')\n        && ['float', 'double', 'decimal'].includes(numberFieldFormat) && (decimals || decimals === 0)) {\n        return decimals;\n      }\n      // for type integer prevent decimals\n      if (numberFieldType === 'integer' || this.fieldProps.fieldType === 'number' || decimals === 0) {\n        return 0;\n      }\n      return null;\n    },\n    /**\n     * create the assistiveText object as required by the input component\n     * depending on field type\n     * @returns {{loaderActive: (string|*)}|Object|undefined|{}}\n     */\n    assistiveTextInt() {\n      if (this.fieldType === 'chips') {\n        return this.assistiveText;\n      }\n      if (this.fieldType === 'autocomplete') {\n        return {\n          loaderActive: this.assistiveText.loaderActive || '',\n          clearInput: this.assistiveText.clearInput || '',\n        };\n      }\n      if (this.fieldType === 'chips-below') {\n        const textObject = { ...this.assistiveText };\n        delete textObject.optionToRemoveSelected;\n        return textObject;\n      }\n      return {\n        clearInput: this.assistiveText.clearInput || '',\n      };\n    },\n  },\n  watch: {\n    modelValue: {\n      handler(val) {\n        if (JSON.stringify(this.fieldValueInt) !== JSON.stringify(val)) {\n          this.setFieldValue(val);\n          if (this.multilineHasTabs) {\n            this.activeTab = this.setActiveTab();\n          }\n        }\n      },\n      deep: true,\n    },\n    fieldValueInt: {\n      handler(val) {\n        // prevent event being fired when change comes from outside\n        if (val !== undefined && JSON.stringify(this.modelValue) !== JSON.stringify(val)) {\n          /**\n           * Event emitted when field value changed internally\n           *\n           * @event update:model-value\n           * @property {Object, Array, String, Number} - the changed field value\n           */\n          this.$emit('update:model-value', JSON.parse(JSON.stringify(val)));\n        }\n      },\n      deep: true,\n    },\n    dropDownList: {\n      handler() {\n        this.fetchingData = false;\n      },\n    },\n  },\n  created() {\n    // set the fieldValueInt immediately on creation so the initial value 'null'\n    // never reaches the input components\n    // the first time the field is mounted set the initial field value\n    // and tabs (if applicable)\n    this.setFieldValue(this.modelValue);\n    if (this.multilineHasTabs) {\n      this.activeTab = this.setActiveTab();\n    }\n  },\n  methods: {\n    // function for setting internal field value breaking all potential links to\n    // value passed from parent\n    setFieldValue(val) {\n      if (val && typeof val === 'object') {\n        // check if it is array\n        if (val.length >= 0) {\n          this.fieldValueInt = [].concat(JSON.parse(JSON.stringify(val)));\n          // else assume it is object\n        } else {\n          this.fieldValueInt = { ...JSON.parse(JSON.stringify(val)) };\n        }\n        // or simply assign directly if string\n      } else {\n        this.fieldValueInt = val;\n      }\n    },\n    /**\n     * assign input to BaseInput, BaseAutocompleteInput or BaseMultilineTextInput\n     * since the BaseMultilineTextInput model value is just returning the input (if tabs are set\n     *  in the form { [tab1]: 'string', [tab2]: 'string' } or otherwise a plain string)\n     *  we also need to consider the type available here in BaseFormFieldCreator and\n     *  make sure it is not overwritten\n     * @param {Object|string} multilineText\n     */\n    setInputValue(multilineText) {\n      // check if input is type 'multiline' and if the multiline text input\n      // has drop down options or tabs - in this case the multilineText has to be\n      // an object!\n      if (this.fieldType === 'multiline' && (this.multilineHasDropdownOptions\n        || this.multilineHasTabs)) {\n        // assign this object so that potential 'type' does not get overwritten\n        this.fieldValueInt = { ...this.fieldValueInt, ...JSON.parse(JSON.stringify(multilineText)) };\n      } else {\n        // else we assume the returned input value is just a string or number and can be assigned\n        // directly\n        this.fieldValueInt = multilineText;\n      }\n    },\n    /**\n     * called by chips input autocomplete\n     * @param {Object} event - the spread object emitted\n     * @property {string} event.value - the string in the input field\n     */\n    fetchAutocomplete({ value }) {\n      this.fetchingData = true;\n      this.textInput = value;\n      /**\n       * Event emitted for text input on autocomplete fields (field types `autocomplete`,\n       * `chips`, `chips-below`)\n       *\n       * @event fetch-autocomplete\n       * @property {string} value - the string to autocomplete\n       * @property {string} name - the name of the field\n       * @property {string} fieldKey - a unique identifier for the field, that was specified as prop and is assigned to the native <input> field\n       * @property {string} source - the url to request the data from\n       * @property {?string} equivalent - string specified for related fields e.g. for contributor roles equivalent is 'contributor'\n       * @property {?string[]} parentFields - in case the autocomplete event originates from a subform the subform id's (field property names) are specified in this array (most nested property last)\n       */\n      this.$emit('fetch-autocomplete', {\n        value,\n        name: this.field.name,\n        fieldKey: this.fieldKey,\n        source: this.formFieldXAttrs.source,\n        equivalent: this.formFieldXAttrs.equivalent,\n      });\n    },\n    /**\n     * called from subform - already contains all the information to pass\n     * to parent (see above for details)\n     * @param {Object} autocompleteInformation\n     */\n    subFormFetchAutocomplete(autocompleteInformation) {\n      const parentFieldsArary = autocompleteInformation.parentFields || [];\n      parentFieldsArary.unshift(this.field.name);\n      this.$emit('fetch-autocomplete', {\n        ...autocompleteInformation,\n        parentFields: parentFieldsArary,\n      });\n    },\n    /**\n     * function getting label from all possible label structures (lang object (--> get\n     // correct lang) or simple string)\n     * @param {string|Object} value - the language string or object - if object it contains\n     * all the languages e.g. { de: '', en: '' }\n     * @returns {string}\n     */\n    getLabel(value) {\n      return this.getLangLabel(value, this.language, true);\n    },\n    // functionality for multiline text input with language tabs\n    setActiveTab() {\n      // check which locales have content\n      const localesWithContent = this.availableLocales.filter(lang => !!this.fieldValueInt[lang]);\n      // if none of the locales has content or the current locale has content\n      // - return current locale - else first alternative\n      return !localesWithContent.length || this.fieldValueInt[this.language]\n        ? this.language : localesWithContent[0];\n    },\n    // function for mulitline text input to set drop down field correctly\n    setMultilineDropDown(val) {\n      // set texts type value if present - otherwise set empty\n      // TODO: source is still hardcoded here??\n      this.fieldValueInt.type = val.source ? val : null;\n      this.emitCompletedInputValues();\n    },\n    // prevent default action for everything except multiline\n    onEnter(event) {\n      if (this.fieldType !== 'multiline') {\n        event.preventDefault();\n        // also emit event that input was completed (e.g. for triggering search)\n        this.emitCompletedInputValues();\n      }\n    },\n    /**\n     * function to trigger event informing parent that input on that specific input field was completed\n     */\n    emitCompletedInputValues() {\n      // check if the value actually changed\n      if (JSON.stringify(this.fieldValueInt) !== JSON.stringify(this.originalFieldValueInt)) {\n        // store the new reference value in the original variable\n        this.originalFieldValueInt = JSON.parse(JSON.stringify(this.fieldValueInt));\n        /**\n         * event emitted once an input was completed (e.g. an option selected in chips input or\n         *  an enter key triggered in BaseInput or after a date was validated)\n         *  @event input-complete\n         *  @property {string, number, Object, Array} - the updated value\n         */\n        this.$emit('input-complete', JSON.parse(JSON.stringify(this.fieldValueInt)));\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    v-bind=\"rootAttrs\">\n    <!-- TEXT FIELD -->\n    <!-- AUTOCOMPLETE -->\n    <!-- MULTILINE -->\n    <component\n      :is=\"fieldElement\"\n      v-if=\"fieldType !== 'date' && fieldType !== 'chips'\n        && fieldType !== 'chips-below' && fieldType !== 'group'\n        && fieldType !== 'boolean'\"\n      :key=\"`${fieldKey}-text`\"\n      :input-id=\"fieldKey\"\n      v-bind=\"fieldPropsInt\"\n      :label=\"labelInt\"\n      :show-label=\"fieldProps.showLabel !== undefined ? fieldProps.showLabel : showLabel\"\n      :placeholder=\"placeholderInt\"\n      :tabs=\"fieldType === 'multiline' ? tabs : undefined\"\n      :tab-labels=\"fieldType === 'multiline'\n        ? fieldProps.tabLabels || tabs.map(tab => getI18nTerm(tab)) : null\"\n      :tabs-legend=\"fieldType === 'multiline'\n        ? fieldProps.tabsLegend || getI18nTerm('form.textTabsLegend') : null\"\n      :active-tab=\"fieldType === 'multiline' ? activeTab : undefined\"\n      :list=\"fieldType === 'autocomplete'\n        ? dropDownList?.length ? dropDownList : fieldProps.list || [] : null\"\n      :is-loading=\"autocompleteLoading\"\n      :loadable=\"fieldType === 'autocomplete' && fieldProps.loadable !== false\"\n      :model-value=\"fieldValueInt\"\n      :input-type=\"isNumberField ? 'number' : fieldProps.fieldType || 'text'\"\n      :invalid=\"invalid || fieldProps.invalid\"\n      :required=\"required || fieldProps.required\"\n      :error-message=\"errorMessage || fieldProps.errorMessage\"\n      :validation-texts=\"fieldProps.validationTexts\n        ? (fieldProps.validationTexts[!isNumberField ? fieldType : 'text']\n          || fieldProps.validationTexts)\n        : validationTexts[!isNumberField ? fieldType : 'text']\"\n      :show-error-icon=\"showErrorIcon\"\n      :clearable=\"clearable\"\n      :min-length=\"field.minLength || fieldProps.minLength\"\n      :max-length=\"field.maxLength || fieldProps.maxLength\"\n      :min=\"typeof formFieldXAttrs.min !== 'undefined' ? formFieldXAttrs.min : fieldProps.min\"\n      :max=\"typeof formFieldXAttrs.max !== 'undefined' ? formFieldXAttrs.max : fieldProps.max\"\n      :decimals=\"allowedDecimals\"\n      :decimal-separator=\"fieldProps.decimalSeparator || language === 'de' ? ',' : '.'\"\n      :assistive-text=\"assistiveTextInt\"\n      @keydown.enter=\"onEnter\"\n      @blur=\"emitCompletedInputValues\"\n      @update:model-value=\"setInputValue($event)\"\n      @fetch-dropdown-entries=\"$emit('fetch-autocomplete', {\n        value: $event,\n        name: field.name,\n        fieldKey: fieldKey,\n        source: formFieldXAttrs.source,\n      })\">\n      <template\n        #label-addition>\n        <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs))\n          @binding {string} field-name -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"label-addition\" />\n        <BaseDropDown\n          v-if=\"fieldType === 'multiline' && multilineHasDropdownOptions\"\n          :id=\"fieldKey\"\n          :model-value=\"fieldValueInt && fieldValueInt.type && fieldValueInt.type.source\n            ? fieldValueInt.type : textTypeDefault\"\n          :options=\"textTypeOptions\"\n          :label=\"getI18nTerm('form.texttype')\"\n          :language=\"language\"\n          value-prop=\"source\"\n          class=\"base-form-field-creator__multiline-dropdown\"\n          @update:model-value=\"setMultilineDropDown\" />\n      </template>\n      <template #pre-input-field>\n        <!-- @slot slot to add elements within the form field but in a row before the actual input field. for an example see [BaseInput](BaseInput)\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"pre-input-field\" />\n      </template>\n      <template\n        #input-field-addition-before>\n        <!-- @slot Slot to allow for additional elements in the input field <div> (before <input>)\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"input-field-addition-before\" />\n      </template>\n      <template #input-field-inline-before>\n        <!-- @slot to add elements directly inline before the input (contrary to input-field-addition-before this does not wrap). for an example see [BaseInput](BaseInput)\n          @binding {string} field-name - the name of the current field for identification purposes-->\n        <slot\n          :field-name=\"field.name\"\n          name=\"input-field-inline-before\" />\n      </template>\n      <template #input-field-addition-after>\n        <!-- @slot for adding elements after input\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"input-field-addition-after\" />\n      </template>\n      <template #post-input-field>\n        <!-- @slot for adding elements at the end covering the whole height\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"post-input-field\" />\n      </template>\n      <template #error-icon>\n        <!-- @slot use a custom icon instead of standard error/warning icon -->\n        <slot\n          name=\"error-icon\" />\n      </template>\n      <template #remove-icon>\n        <!-- @slot use a custom icon instead of standard remove icon -->\n        <slot\n          name=\"remove-icon\" />\n      </template>\n      <template #below-input>\n        <!-- @slot below-input slot added to e.g. add drop down\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"below-input\" />\n      </template>\n      <template #drop-down-entry=\"{ item }\">\n        <template v-if=\"fieldType === 'autocomplete'\">\n          <!-- @slot customize the form field drop down options\n            @binding {object} option - the option object -->\n          <slot\n            :field-name=\"field.name\"\n            :option=\"item\"\n            name=\"drop-down-entry\" />\n        </template>\n      </template>\n    </component>\n\n    <!-- DATE FIELD -->\n    <fieldset\n      v-else-if=\"fieldType === 'date'\"\n      class=\"base-form-field-creator__date-fieldset\">\n      <div class=\"base-form-field-creator__date-field-wrapper\">\n        <!-- if any date is included in the object (`date`, `date_from` `date_to`) this component is\n          rendered -->\n        <BaseDateInput\n          v-if=\"dateType === 'single' || dateType.includes('date')\"\n          :key=\"fieldKey + '_date'\"\n          v-model=\"fieldValueInt\"\n          :input-id=\"fieldKey\"\n          v-bind=\"fieldPropsInt\"\n          :label=\"labelInt\"\n          :show-label=\"fieldProps.showLabel !== undefined ? fieldProps.showLabel : showLabel\"\n          :placeholder=\"placeholderInt\"\n          :range-separator=\"fieldProps.rangeSeparator || getI18nTerm('form.until')\"\n          :format=\"formFieldXAttrs.date_format || fieldProps.format\"\n          :date-type=\"dateType.includes('timerange') ? dateType.includes('daterange')\n            ? 'daterange' : 'single' : dateType\"\n          :date-format-labels=\"fieldProps.dateFormatLabels\n            || {\n              date: getI18nTerm('form.date'),\n              month: getI18nTerm('form.month'),\n              year: getI18nTerm('form.year'),\n            }\"\n          :format-tabs-legend=\"fieldProps.formatTabsLegend || getI18nTerm('form.dateTabsLegend')\"\n          :language=\"language\"\n          :invalid=\"dateInvalid\"\n          :required=\"required || fieldProps.required\"\n          :error-message=\"dateErrorMessage || fieldProps.errorMessage\"\n          :clearable=\"clearable\"\n          :assistive-text=\"assistiveTextInt\"\n          class=\"base-form-field-creator__date-field\"\n          @value-validated=\"emitCompletedInputValues\">\n          <template\n            #label-addition>\n            <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs))\n              @binding {string} field-name -->\n            <slot\n              :field-name=\"field.name\"\n              name=\"label-addition\" />\n          </template>\n          <template #pre-input-field>\n            <!-- @slot slot to add elements within the form field but in a row before the actual input field. for an example see [BaseInput](BaseInput)\n              @binding {string} field-name - the name of the current field for identification purposes -->\n            <slot\n              :field-name=\"field.name\"\n              name=\"pre-input-field\" />\n          </template>\n          <template\n            #input-field-addition-before>\n            <!-- @slot Slot to allow for additional elements in the input field <div> (before <input>)\n              @binding {string} field-name - the name of the current field for identification purposes -->\n            <slot\n              :field-name=\"field.name\"\n              name=\"input-field-addition-before\" />\n          </template>\n          <template #input-field-inline-before>\n            <!-- @slot to add elements directly inline before the input (contrary to input-field-addition-before this does not wrap). for an example see [BaseInput](BaseInput)\n              @binding {string} field-name - the name of the current field for identification purposes -->\n            <slot\n              :field-name=\"field.name\"\n              name=\"input-field-inline-before\" />\n          </template>\n          <template #input-field-addition-after>\n            <!-- @slot for adding elements after input\n              @binding {string} field-name - the name of the current field for identification purposes -->\n            <slot\n              :field-name=\"field.name\"\n              name=\"input-field-addition-after\" />\n          </template>\n          <template #post-input-field>\n            <!-- @slot for adding elements at the end covering the whole height\n              @binding {string} field-name - the name of the current field for identification purposes -->\n            <slot\n              :field-name=\"field.name\"\n              name=\"post-input-field\" />\n          </template>\n          <template #error-icon>\n            <!-- @slot use a custom icon instead of standard error/warning icon -->\n            <slot\n              name=\"error-icon\" />\n          </template>\n          <template #remove-icon>\n            <!-- @slot use a custom icon instead of standard remove icon -->\n            <slot\n              name=\"remove-icon\" />\n          </template>\n          <template #below-input>\n            <!-- @slot below-input slot added to e.g. add drop down\n              @binding {string} field-name - the name of the current field for identification purposes -->\n            <slot\n              :field-name=\"field.name\"\n              name=\"below-input\" />\n          </template>\n        </BaseDateInput>\n        <!-- if any time range is included in the object this component is\n          rendered -->\n        <BaseDateInput\n          v-if=\"dateType.includes('timerange')\"\n          :key=\"fieldKey + '_time'\"\n          v-model=\"fieldValueInt\"\n          :input-id=\"fieldKey + '_time'\"\n          v-bind=\"fieldPropsInt\"\n          :label=\"dateType !== 'timerange' && field.properties.time_from.title\n            ? field.properties.time_from.title : labelInt\"\n          :show-label=\"!dateType.includes('date')\"\n          :placeholder=\"placeholderInt.time || placeholderInt\"\n          :range-separator=\"fieldProps.rangeSeparator || getI18nTerm('form.until')\"\n          :invalid=\"dateInvalid\"\n          :required=\"required || fieldProps.required\"\n          :error-message=\"dateErrorMessage || fieldProps.errorMessage\"\n          :clearable=\"clearable\"\n          :assistive-text=\"assistiveTextInt\"\n          date-type=\"timerange\"\n          :class=\"['base-form-field-creator__date-field',\n                   { 'base-form-field-creator__date-field--spacing': dateType.includes('date') }]\"\n          @value-validated=\"emitCompletedInputValues\">\n          <!-- only add slot here if it there is no first (date) field row -->\n          <template\n            #label-addition>\n            <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs))\n              @binding {string} field-name - the name of the current field for identification purposes (for time range fields there is a '-time' suffix added) -->\n            <slot\n              :field-name=\"`${field.name}-time`\"\n              name=\"label-addition\" />\n          </template>\n          <template #pre-input-field>\n            <!-- @slot slot to add elements within the form field but in a row before the actual input field. for an example see [BaseInput](BaseInput)\n              @binding {string} field-name - the name of the current field for identification purposes (for time range fields there is a '-time' suffix added) -->\n            <slot\n              :field-name=\"`${field.name}-time`\"\n              name=\"pre-input-field\" />\n          </template>\n          <template\n            #input-field-addition-before>\n            <!-- @slot Slot to allow for additional elements in the input field <div> (before <input>)\n              @binding {string} field-name - the name of the current field for identification purposes (for time range fields there is a '-time' suffix added)-->\n            <slot\n              :field-name=\"`${field.name}-time`\"\n              name=\"input-field-addition-before\" />\n          </template>\n          <template #input-field-inline-before>\n            <!-- @slot to add elements directly inline before the input (contrary to input-field-addition-before this does not wrap). for an example see [BaseInput](BaseInput)\n              @binding {string} field-name - the name of the current field for identification purposes (for time range fields there is a '-time' suffix added) -->\n            <slot\n              :field-name=\"`${field.name}-time`\"\n              name=\"input-field-inline-before\" />\n          </template>\n          <template #input-field-addition-after>\n            <!-- @slot for adding elements after input\n              @binding {string} field-name - the name of the current field for identification purposes (for time range fields there is a '-time' suffix added) -->\n            <slot\n              :field-name=\"`${field.name}-time`\"\n              name=\"input-field-addition-after\" />\n          </template>\n          <template #post-input-field>\n            <!-- @slot for adding elements at the end covering the whole height\n              @binding {string} field-name - the name of the current field for identification purposes (for time range fields there is a '-time' suffix added) -->\n            <slot\n              :field-name=\"`${field.name}-time`\"\n              name=\"post-input-field\" />\n          </template>\n          <template #error-icon>\n            <!-- @slot use a custom icon instead of standard error/warning icon -->\n            <slot\n              name=\"error-icon\" />\n          </template>\n          <template #remove-icon>\n            <!-- @slot use a custom icon instead of standard remove icon -->\n            <slot\n              name=\"remove-icon\" />\n          </template>\n          <template #below-input>\n            <!-- @slot below-input slot added to e.g. add drop down\n              @binding {string} field-name - the name of the current field for identification purposes (for time range fields there is a '-time' suffix added) -->\n            <slot\n              :field-name=\"`${field.name}-time`\"\n              name=\"below-input\" />\n          </template>\n        </BaseDateInput>\n      </div>\n    </fieldset>\n\n    <!-- CHIPS INPUT -->\n    <component\n      :is=\"fieldElement\"\n      v-else-if=\"fieldType === 'chips' || fieldType === 'chips-below'\"\n      :ref=\"fieldType + fieldKey\"\n      :key=\"`${fieldKey}-chips`\"\n      v-model=\"fieldValueInt\"\n      :input-id=\"fieldKey\"\n      v-bind=\"fieldPropsInt\"\n      :placeholder=\"placeholderInt\"\n      :label=\"labelInt\"\n      :show-label=\"fieldProps.showLabel !== undefined ? fieldProps.showLabel : showLabel\"\n      :list=\"dropDownList.length ? dropDownList : fieldProps.list || []\"\n      :allow-dynamic-drop-down-entries=\"formFieldXAttrs.dynamic_autosuggest\n        || !!fieldProps.allowDynamicDropDownEntries\"\n      :allow-multiple-entries=\"!isChipsSingleSelect\"\n      :allow-unknown-entries=\"formFieldXAttrs.allow_unknown_entries\n        || !!fieldProps.allowUnknownEntries\"\n      :draggable=\"!!fieldProps.draggable || !isChipsSingleSelect\"\n      :sortable=\"formFieldXAttrs.sortable\n        || !!fieldProps.sortable\"\n      :is-loading=\"autocompleteLoading\"\n      :sort-text=\"fieldProps.sortText || sortText\"\n      :sort-name=\"fieldProps.sortName || isContributorOrEquivalent\"\n      :language=\"formFieldXAttrs.set_label_language\n        || fieldType === 'chips-below' ? language : ''\"\n      :drop-down-no-options-info=\"fieldProps.dropDownNoOptionsInfo || getI18nTerm('form.noMatch')\"\n      :additional-prop-options=\"fieldType === 'chips-below' ? secondaryDropdown : undefined\"\n      :additional-prop-placeholder=\"fieldType === 'chips-below'\n        ? fieldProps.additionalPropPlaceholder || getI18nTerm('form.selectRoles') : null\"\n      :additional-property-name=\"fieldType === 'chips-below'\n        ? fieldProps.additionalPropertyName || 'roles' : null\"\n      :additional-prop-required=\"fieldType === 'chips-below'\n        ? formFieldXAttrs.additional_prop_required : null\"\n      :invalid=\"invalid || fieldProps.invalid\"\n      :required=\"field.required || required || fieldProps.required\"\n      :error-message=\"errorMessage || fieldProps.errorMessage\"\n      :clearable=\"clearable\"\n      :validation-texts=\"validationTexts.chips || fieldProps.validationTexts.chips\"\n      :show-error-icon=\"showErrorIcon\"\n      :identifier-property-name=\"fieldProps.identifierPropertyName || identifierPropertyName\"\n      :label-property-name=\"fieldProps.labelPropertyName || labelPropertyName\"\n      :assistive-text=\"assistiveTextInt\"\n      @update:model-value=\"emitCompletedInputValues\"\n      @fetch-dropdown-entries=\"fetchAutocomplete\"\n      @input=\"textInput = $event\">\n      <template\n        #drop-down-entry=\"{ item }\">\n        <!-- @slot customize the form field drop down options\n          @binding {object} option - the option object -->\n        <slot\n          :field-name=\"field.name\"\n          :option=\"item\"\n          name=\"drop-down-entry\">\n          <BaseInsertTextAsHtml\n            :render-element-as=\"'span'\"\n            :text=\"getLabel(item[labelPropertyName])\"\n            :interpret-text-as-html=\"fieldProps.interpretChipsLabelAsHtml\" />\n          <span class=\"base-form-field-creator__chips-dropdown-second\">\n            {{ item.additional }}\n          </span>\n          <span class=\"base-form-field-creator__chips-dropdown-third\">\n            {{ item.source_name }}\n          </span>\n        </slot>\n      </template>\n      <template #no-options>\n        <span v-if=\"formFieldXAttrs.dynamic_autosuggest && !fieldInput\">\n          {{ getI18nTerm('form.startTyping') }}\n        </span>\n        <span v-else-if=\"!formFieldXAttrs.dynamic_autosuggest && textInput\">\n          {{ getI18nTerm('form.noMatch') }}\n        </span>\n        <span v-else-if=\"fieldInput && !fetchingData && !autocompleteLoading\">\n          {{ getI18nTerm('form.noResult') }}\n        </span>\n        <span v-else>\n          {{ getI18nTerm('form.fetchingResults') }}\n        </span>\n      </template>\n      <template\n        #label-addition>\n        <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs))\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"label-addition\" />\n      </template>\n      <template #pre-input-field>\n        <!-- @slot slot to add elements within the form field but in a row before the actual input field. for an example see [BaseInput](BaseInput)\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"pre-input-field\" />\n      </template>\n      <template\n        #input-field-addition-before>\n        <!-- @slot Slot to allow for additional elements in the input field <div> (before <input>)\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"input-field-addition-before\" />\n      </template>\n      <template #input-field-inline-before>\n        <!-- @slot to add elements directly inline before the input (contrary to input-field-addition-before this does not wrap). for an example see [BaseInput](BaseInput)\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"input-field-inline-before\" />\n      </template>\n      <template #input-field-addition-after>\n        <!-- @slot for adding elements after input\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"input-field-addition-after\" />\n      </template>\n      <template #post-input-field>\n        <!-- @slot for adding elements at the end covering the whole height\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"post-input-field\" />\n      </template>\n      <template #error-icon>\n        <!-- @slot use a custom icon instead of standard error/warning icon -->\n        <slot\n          name=\"error-icon\" />\n      </template>\n      <template #remove-icon>\n        <!-- @slot use a custom icon instead of standard remove icon -->\n        <slot\n          :field-name=\"field.name\" />\n      </template>\n      <template #below-input>\n        <!-- @slot below-input slot added to e.g. add drop down\n          @binding {string} field-name - the name of the current field for identification purposes -->\n        <slot\n          :field-name=\"field.name\"\n          name=\"below-input\" />\n      </template>\n    </component>\n\n    <!-- FIELD GROUPS -->\n    <div\n      v-else-if=\"fieldType === 'group'\"\n      :key=\"`${fieldKey}-group`\"\n      class=\"base-form-field-creator__field-array\">\n      <div\n        v-if=\"formFieldXAttrs.show_label\"\n        class=\"base-form-field-creator__field-array-label\">\n        {{ `${labelInt}:` }}\n      </div>\n      <div\n        :key=\"fieldKey\"\n        class=\"base-form-field-creator__subform-wrapper\">\n        <component\n          :is=\"fieldElement\"\n          v-bind=\"fieldGroupParamsInt\"\n          class=\"base-form-field-creator__subform\"\n          @update:model-value=\"setFieldValue\"\n          @input-complete=\"emitCompletedInputValues\"\n          @fetch-autocomplete=\"subFormFetchAutocomplete\">\n          <template\n            #label-addition=\"{ fieldName, groupNames, index }\">\n            <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs))\n              @binding {string} field-name - the name of the current field for identification purposes\n              @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n              @binding {number} index - in case field is repeatable the index of the field -->\n            <slot\n              :field-name=\"fieldName\"\n              :group-names=\"(groupNames ? groupNames : []).concat(field.name)\"\n              :index=\"index\"\n              name=\"label-addition\" />\n          </template>\n          <template #pre-input-field=\"{ fieldName, groupNames, index }\">\n            <!-- @slot slot to add elements within the form field but in a row before the actual input field. for an example see [BaseInput](BaseInput)\n              @binding {string} field-name - the name of the current field for identification purposes\n              @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n              @binding {number} index - in case field is repeatable the index of the field -->\n            <slot\n              :field-name=\"fieldName\"\n              :group-names=\"(groupNames ? groupNames : []).concat(field.name)\"\n              :index=\"index\"\n              name=\"pre-input-field\" />\n          </template>\n          <template\n            #input-field-addition-before=\"{ fieldName, groupNames, index }\">\n            <!-- @slot Slot to allow for additional elements in the input field <div> (before <input>)\n              @binding {string} field-name - the name of the current field for identification purposes\n              @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n              @binding {number} index - in case field is repeatable the index of the field -->\n            <slot\n              :field-name=\"fieldName\"\n              :group-names=\"(groupNames ? groupNames : []).concat(field.name)\"\n              :index=\"index\"\n              name=\"input-field-addition-before\" />\n          </template>\n          <template #input-field-inline-before=\"{ fieldName, groupNames, index }\">\n            <!-- @slot to add elements directly inline before the input (contrary to input-field-addition-before this does not wrap). for an example see [BaseInput](BaseInput)\n              @binding {string} field-name - the name of the current field for identification purposes\n              @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n              @binding {number} index - in case field is repeatable the index of the field -->\n            <slot\n              :field-name=\"fieldName\"\n              :group-names=\"(groupNames ? groupNames : []).concat(field.name)\"\n              :index=\"index\"\n              name=\"input-field-inline-before\" />\n          </template>\n          <template #input-field-addition-after=\"{ fieldName, groupNames, index }\">\n            <!-- @slot for adding elements after input\n              @binding {string} field-name - the name of the current field for identification purposes\n              @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n              @binding {number} index - in case field is repeatable the index of the field -->\n            <slot\n              :field-name=\"fieldName\"\n              :group-names=\"(groupNames ? groupNames : []).concat(field.name)\"\n              :index=\"index\"\n              name=\"input-field-addition-after\" />\n          </template>\n          <template #post-input-field=\"{ fieldName, groupNames, index }\">\n            <!-- @slot for adding elements at the end covering the whole height\n              @binding {string} field-name - the name of the current field for identification purposes\n              @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n              @binding {number} index - in case field is repeatable the index of the field -->\n            <slot\n              :field-name=\"fieldName\"\n              :group-names=\"(groupNames ? groupNames : []).concat(field.name)\"\n              :index=\"index\"\n              name=\"post-input-field\" />\n          </template>\n          <template #error-icon>\n            <!-- @slot use a custom icon instead of standard error/warning icon -->\n            <slot\n              name=\"error-icon\" />\n          </template>\n          <template #remove-icon>\n            <!-- @slot use a custom icon instead of standard remove icon -->\n            <slot\n              name=\"remove-icon\" />\n          </template>\n          <template #below-input=\"{ fieldName, groupNames, index }\">\n            <!-- @slot below-input slot added to e.g. add drop down\n              @binding {string} field-name - the name of the current field for identification purposes\n              @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n              @binding {number} index - in case field is repeatable the index of the field -->\n            <slot\n              :field-name=\"fieldName\"\n              :group-names=\"(groupNames ? groupNames : []).concat(field.name)\"\n              :index=\"index\"\n              name=\"below-input\" />\n          </template>\n          <template #drop-down-entry=\"{ option, fieldName, groupNames }\">\n            <!-- @slot customize the form field drop down options\n              @binding {object} option - the option object\n              @binding {string} field-name - the name of the current field for identification purposes\n              @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n            <slot\n              :field-name=\"fieldName\"\n              :group-names=\"(groupNames ? groupNames : []).concat(field.name)\"\n              :option=\"option\"\n              name=\"drop-down-entry\" />\n          </template>\n        </component>\n      </div>\n    </div>\n\n    <!-- FIELD BOOLEAN -->\n    <BaseToggle\n      v-else-if=\"fieldType === 'boolean'\"\n      :key=\"`${fieldKey}-toggle`\"\n      v-model=\"fieldValueInt\"\n      v-bind=\"fieldPropsInt\"\n      :input-id=\"fieldKey\"\n      :name=\"fieldKey\"\n      :label=\"labelInt\"\n      :bind-slot-to-state=\"fieldProps.bindSlotToState || true\"\n      :input-type=\"isNumberField ? 'number' : fieldProps.fieldType || 'text'\"\n      :invalid=\"invalid || fieldProps.invalid\"\n      :required=\"required || fieldProps.required\"\n      :error-message=\"errorMessage || fieldProps.errorMessage\"\n      :show-error-icon=\"showErrorIcon\"\n      class=\"base-form-field-creator__toggle\"\n      @update:model-value=\"emitCompletedInputValues\">\n      <BaseLink\n        v-if=\"formFieldXAttrs.subtext && formFieldXAttrs.subtext.value\"\n        :identifier-property-value=\"formFieldXAttrs.subtext.source || ''\"\n        :url=\"formFieldXAttrs.subtext.url || ''\"\n        :value=\"formFieldXAttrs.subtext.value\" />\n    </BaseToggle>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n  @use \"@/styles/variables\" as *;\n\n  .base-form-field-creator__field-array {\n    margin-top: $spacing-small;\n    display: flex;\n    flex-direction: column;\n\n    .base-form-field-creator__field-array-label {\n      color: $font-color-second;\n      margin-bottom: $spacing-small;\n      z-index: map.get($zindex, boxcontent);\n    }\n\n    .base-form-field-creator__subform-wrapper {\n      border-right: 3px solid rgb(240, 240, 240);\n      border-left: 3px solid rgb(240, 240, 240);\n\n      .base-form-field-creator__subform {\n        position: relative;\n        margin: -$spacing auto;\n        width: calc(100% - 6px);\n\n        @media screen and (max-width: $mobile) {\n          margin: -$spacing auto;\n        }\n      }\n    }\n  }\n\n  // this class is used in BaseForm.vue!\n  .base-form-field-creator__date-field-wrapper {\n    display: flex;\n    flex-direction: row;\n    gap: $spacing;\n\n    @media screen and (max-width: 1260px) {\n      flex-direction: column;\n    }\n\n    @media screen and (max-width: $mobile) {\n      gap: $spacing-small;\n    }\n\n    .base-form-field-creator__date-field--spacing {\n      @media screen and (min-width: 1261px) {\n        margin-top: calc(#{$line-height} + #{$spacing-small});\n      }\n    }\n  }\n\n  .base-form-field-creator__multiline-dropdown {\n    text-transform: capitalize;\n  }\n\n  .base-form-field-creator__chips-dropdown-second {\n    margin-left: $spacing;\n    color: $font-color-second;\n    font-size: $font-size-small;\n    margin-top: 1px;\n    flex-grow: 2;\n  }\n\n  .base-form-field-creator__chips-dropdown-third {\n    color: $font-color-third;\n    font-size: $font-size-small;\n    margin-top: auto;\n    white-space: nowrap;\n  }\n\n  .base-form-field-creator__date-fieldset {\n    display: contents;\n  }\n\n  .base-form-field-creator__toggle {\n    &:deep(.base-toggle__container) {\n      min-height: $row-height-small;\n    }\n  }\n</style>\n","<script>\nimport { defineAsyncComponent, toRef } from 'vue';\nimport BaseFormFieldCreator from '@/components/BaseFormFieldCreator/BaseFormFieldCreator.vue';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { createId } from '@/utils/utils.js';\n\n/**\n * Component creating a form according to a provided [openAPI](https://www.openapis.org/) standard\n */\n\n// list all the fieldProps here that can be set individually for each repeatable field\nconst INDIVIDUAL_REPEATABLE_FIELDPROPS = [\n  'errorMessage',\n  'invalid',\n  'isActive',\n  'isLoading',\n  'linkedListOption',\n  'activeTab',\n  'validationTexts',\n];\n\nexport default {\n  name: 'BaseForm',\n  components: {\n    BaseButton: defineAsyncComponent(() => import('@/components/BaseButton/BaseButton.vue').then(m => m.default || m)),\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue').then(m => m.default || m)),\n    BaseFormFieldCreator,\n  },\n  props: {\n    /**\n     * the json object containing all the field information incl. `x-attrs` custom field\n     * for placeholder, field type, etc. (for further documentation and configuration options see\n     * further down below [slots](BaseForm.html#slots))\n     */\n    formFieldJson: {\n      type: Object,\n      required: true,\n    },\n    /**\n     * the values for each field if any already present\n     */\n    modelValue: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * set current language\n     */\n    language: {\n      type: String,\n      default: 'en',\n    },\n    /**\n     * provide information about all available languages\n     */\n    availableLocales: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * an id for field groups to still have unique field ids\n     */\n    formId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define additional style for the form\n     * should be an object e.g. `{ 'padding-top': 0 }`\n     */\n    formStyle: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * define fields (specify field name!) for which tabs should be shown\n     */\n    fieldsWithTabs: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * enter the field name of a field that is currently fetching autocomplete\n     * results\n     * WARNING: this prop is deprecated and will be removed in the next major version!\n     *  Please use fieldLoadingId instead!\n     */\n    fieldIsLoading: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set a field id of a field that is currently fetching autocomplete\n     *  results to display a loader\n     */\n    fieldLoadingId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * provide an object that contains the options list for all\n     *  fields with autocomplete / chips input\n     * object should be provided with field names and field key as nested properties\n     * or just field names as properties if field key is not available\n     * e.g. {\n     *   [fieldName]: {\n     *     // an options list fetched via autocomplete\n     *     [fieldKey]: [[options]]\n     *   },\n     *   // a prefetched dropdown options list\n     *   [fieldName2]: [[options]]\n     * }\n     * providing options with field key should be preferred whenever possible, otherwise\n     *  problems might arise for repeatable fields\n     * for field type `group` provide a nested object with field names\n     *  as properties and an array for each field to ensure the correct options are assigned\n     *  even if field names within different groups are identical\n     */\n    dropDownLists: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * define if error icon should be shown.\n     * for an example on how it looks on an individual form field see [BaseInput](BaseInput)\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * provide all error messages for fields in a separate object\n     * same structure as modelValue, final value should be an array\n     * of messages\n     *\n     * example - error in repeatable field group, only the second group has an error:\n     * { [fieldGroupName]: [{}, { amount: ['This field is required.'] }]}\n     *\n     * caveat: if error messages are provided via errorMessagesObject, they take\n     *  priority over `fieldProps` set values\n     */\n    errorMessagesObject: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * if `true` a remove icon will be shown allowing to remove\n     * all input at once.\n     * for an example on how it looks on an individual form field see [BaseInput](BaseInput)\n     */\n    clearable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * provide an object with settings and properties for each field. This takes an object\n     * with the field name as properties with the props nested.\n     * `{ [fieldName1]: { required: false, ... }, [fieldName2]: { ... } }`\n     *\n     * find the possible variables at the respective input components:\n     * [BaseInput](BaseInput)\n     * [BaseAutocompleteInput](BaseAutocompleteInput)\n     * [BaseMultilineTextInput](BaseMultilineTextInput)\n     * [BaseChipsInput](BaseChipsInput)\n     * [BaseChipsBelow](BaseChipsBelow)\n     * [BaseDateInput](BaseDateInput)\n     * [BaseToggle](BaseToggle)\n     *\n     * **special case repeatable fields**: the following field props can be set individually\n     * per repeated field:\n     *  `errorMessage`, `invalid`, `isActive`, `isLoading`,\n     *  `linkedListOption`, `activeTab`\n     *  the field property value should be set as object specifying the field index as key:\n     *  `{ [fieldIndex]: [value to be set] }` (e.g. `{ required: { 0: false }}`)\n     */\n    fieldProps: {\n      type: Object,\n      default: () => ({}),\n      validator: val => Object.keys(val).length === 0 || Object.values(val)\n        .every(fieldProps => Object.keys(fieldProps)),\n    },\n    /**\n     * in case the field `form_group_title` was added to the `x-attrs` field, this is\n     * is rendered as a header above the form and here the HTML tag may be defined.\n     */\n    renderHeaderAs: {\n      type: String,\n      default: 'div',\n    },\n    /**\n     * define validation texts to be displayed below form field if input is invalid.\n     * for an example see [BaseInput](BaseInput)\n     */\n    validationTexts: {\n      type: Object,\n      default: () => ({\n        text: {\n          min: 'Value must be greater than or equal to {value}.',\n          max: 'Value must be less than or equal to {value}.',\n          minLength: 'Text must be at least {value} character(s) long.',\n          maxLength: 'Text cannot be longer than {value} characters.',\n        },\n        chips: {\n          required: 'Select an option.',\n        },\n      }),\n      // checking if all necessary properties are part of the provided object\n      validator: val => ['text'].every(prop => Object.keys(val).includes(prop))\n        && ['min', 'max', 'minLength', 'maxLength']\n          .every(prop => Object.keys(val.text).includes(prop)),\n    },\n    /**\n     * specify the object property that should be used as identifier.\n     * used for chips input as well as dropdowns.\n     */\n    identifierPropertyName: {\n      type: String,\n      default: 'source',\n    },\n    /**\n     * specify the object property that should be used as value to be displayed.\n     * used for chips input as well as dropdowns.\n     */\n    labelPropertyName: {\n      type: String,\n      default: 'label',\n    },\n    /**\n     * this prop gives the option to add assistive text for screen readers\n     * properties:\n     *\n     * Options for all input types (except `boolean`):\n     * **clearInput**: text read for remove input icon if prop `clearable` is set `true`\n     *\n     * Options for inputs type `autocomplete`, `chips`, `chips-below`:\n     * **loaderActive**: text that is announced when options are being fetched (prop\n     *  `isLoading` is set `true`)\n     *\n     * Options for inputs type `chips`:\n     * **optionToRemoveSelected**: text read when option is marked active for removal (by using\n     *  backspace in empty input field). string {label} could be added to be replaced\n     *  by the actual chip label (value in [`labelPropertyName`])\n     *\n     * Options for inputs type `chips`, `chips-below`:\n     * **resultsRetrieved**: text that is announced when results were retrieved (drop down\n     *  list changed)\n     * **optionAdded**: text read when option was added to the selected list. string {label}\n     *  could be added to be replaced by the actual chip label (value in [`labelPropertyName`])\n     * **optionRemoved**: text read when option was removed from the selected list. string {label}\n     *  could be added to be replaced by the actual chip label (value in [`labelPropertyName`])\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        loaderActive: 'loading.',\n        clearInput: 'Clear input',\n        resultsRetrieved: '{number} options in drop down.',\n        optionAdded: 'option {label} added to selected list.',\n        optionToRemoveSelected: 'option {label} from selected list marked for removal. Press delete or backspace to remove.',\n        optionRemoved: 'option {label} removed.',\n      }),\n    },\n  },\n  emits: ['update:model-value', 'input-complete', 'fetch-autocomplete', 'form-mounted'],\n  setup(props) {\n    /** INTERNATIONALIZATION */\n    const { getLangLabel, getI18nTerm } = useI18n(toRef(props, 'language'));\n\n    return {\n      getLangLabel,\n      getI18nTerm,\n    };\n  },\n  data() {\n    return {\n      /**\n       * variable to be able to focus to the field after multiply\n       * @type {?Object}\n       * @property {number} index - the index of the new field in the array\n       * @property {string} name - the name of the field\n       */\n      multiplyParams: null,\n      /**\n       * internal representation of modelValue (containing values for all input fields)\n       * @type {Object}\n       * @property {?string|?Array|?Object} [the name of the input field]\n       */\n      valueListInt: {},\n    };\n  },\n  computed: {\n    /**\n     * the form fields provided in the prop `formFieldJson` as filtered (remove unneeded and hidden fields)\n     * and sorted list with the field key added to the object as `name` property.\n     * @returns {(*&{name: *})[]}\n     */\n    cleanedAndSortedFormFieldList() {\n      return Object.entries(this.formFieldJson)\n        // filter out $ref property from JSON\n        // do not filter out hidden fields here since they still need to be present\n        // in valueList (for which this variable is used)\n        .filter(([, value]) => !value.$ref)\n        // map all fields to include the field key as property `name`\n        // and an id for the v-for key\n        .map(([key, value]) => ({\n          fieldId: createId(),\n          name: key,\n          ...value,\n        }))\n        // sort the fields according to their x-attribute (order)\n        .sort((a, b) => (a['x-attrs']?.order > b['x-attrs']?.order ? 1 : -1));\n    },\n    /**\n     * internal form field list, sorted and with additional name property to save\n     * the name of the input field in a variable, also filtered from fields that\n     * should not be shown\n     *\n     * @property {string} name - the name of the input field\n     * @returns {Object}\n     * @property {*} [*] all other properties contained in the swagger\n     */\n    formFieldListInt() {\n      // now get the list in the desired structure of grouping fields with identical field_format\n      // together in the way: [{ type: [field_format], data: [fieldList] }]\n      // where fieldList is an array with all fields that consecutively have the same field format\n      return this.cleanedAndSortedFormFieldList.reduce((prev, curr) => {\n        // save the field_format in a variable\n        const { field_format: fieldFormat, order, field_type: fieldType, hidden } = curr['x-attrs'] || {};\n        // hidden fields still need to be initialized (otherwise they are missing from valueList and cause\n        // discrepancies when checking for unsaved changes) so just remove them here (not in\n        // cleanedAndSortedFormFieldLists which is used for initialization)\n        if (hidden) return prev;\n        const lastArrayElementIndex = prev.length - 1;\n        // check if fields should be grouped (only for 'half' and 'third')\n        if (fieldFormat && fieldType !== 'group'\n          && ['half', 'third'].includes(fieldFormat)\n          && prev[lastArrayElementIndex]\n          // and if the last element of the list already has the same format as the current one\n          // and thus an entry for that field format already exists\n          && prev[lastArrayElementIndex]?.type === fieldFormat\n          // also make sure that there are not more than 2 or 3 elements in a row array respectively\n          && ((fieldFormat === 'half' && prev[lastArrayElementIndex].data.length < 2)\n            || (fieldFormat === 'third' && prev[lastArrayElementIndex].data.length < 3))\n          // lastly check if order of elements is sequential so in it is possible to leave a field empty by\n          // skipping a number\n          && prev[lastArrayElementIndex].data.at(-1)['x-attrs'].order + 1 >= order) {\n          // if yes - push the current element to the already existing array\n          prev[lastArrayElementIndex].data.push(curr);\n          // else create a new array entry with the new format for that group (or single field)\n        } else {\n          prev.push({\n            rowId: createId(),\n            // field type group should always be full\n            type: fieldFormat && curr['x-attrs']?.field_type !== 'group'\n              ? fieldFormat : 'full',\n            data: [curr],\n          });\n        }\n        // return the updated array\n        return prev;\n      }, []);\n    },\n    /**\n     * get the title string for the form header if one was set in the OpenAPI definition\n     * @returns {string}\n     */\n    formHeader() {\n      // find a field with the x-attr form_group_title (formFieldListInt is already sorted\n      // by order x-attr so the title of the field with the lowest order will automatically\n      // be chosen\n      const groupTitleField = this.cleanedAndSortedFormFieldList\n        .find(field => field['x-attrs'] && field['x-attrs'].form_group_title);\n      // return the title string for the header to set if one was found\n      return groupTitleField ? groupTitleField['x-attrs'].form_group_title : '';\n    },\n  },\n  watch: {\n    /**\n     * watch the prop to see if it has changed from outside\n     */\n    modelValue: {\n      handler(val) {\n        const changedValues = Object.keys(this.valueListInt)\n          .some(key => JSON.stringify(this.valueListInt[key]) !== JSON.stringify(val[key]));\n        if (changedValues) {\n          this.initializeValueObject();\n        }\n      },\n      deep: true,\n      immediate: true,\n    },\n    valueListInt: {\n      handler(val) {\n        // make sure there are any changes not updated yet\n        if (Object.keys(this.formFieldJson)\n          .some((key) => JSON.stringify(this.modelValue[key]) !== JSON.stringify(val[key]))) {\n          /**\n           * event triggered when the values of a field were altered or a form\n           * field was added or removed\n           *\n           * @event update:model-value\n           * @param {Object[]} - the changed value list\n           * @param {Object} - the field information of the changed field\n           */\n          this.$emit('update:model-value', JSON.parse(JSON.stringify(val)));\n        }\n\n      },\n      deep: true,\n    },\n    /**\n     * if the form fields definition was changed from outside - reinitialize the internal value list\n     */\n    formFieldJson: {\n      handler() {\n        // initialize value object with new properties\n        this.initializeValueObject();\n      },\n      immediate: true,\n    },\n    /**\n     * temporary watcher to inform user that the prop is deprecated\n     * @param val\n     */\n    fieldIsLoading(val) {\n      if (val) {\n        console.warn('Prop \\'fieldIsLoading\\' is deprecated and will be removed in the next major version - please use \\'fieldLoadingId\\' instead!');\n      }\n    },\n  },\n  updated() {\n    if (this.multiplyParams && this.multiplyParams.name) {\n      const elements = this.$refs[this.multiplyParams.name];\n      if (elements.length) {\n        // this seems like a stupid hack however had to do this because if 'getElementsByTagName'\n        // was evaluated immediately it came back empty for 'textarea' since for some reason\n        // this was not in the DOM tree yet... (no problems for input fields / subforms tho)\n        setTimeout((params) => {\n          const inputs = elements[params.index].getElementsByTagName('textarea').length\n            ? elements[params.index].getElementsByTagName('textarea')\n            : elements[params.index].getElementsByTagName('input');\n          if (inputs.length) {\n            inputs[0].focus();\n          }\n        }, 50, this.multiplyParams);\n      }\n      this.multiplyParams = null;\n    }\n  },\n  mounted() {\n    // inform parent that form was mounted\n    this.$nextTick(() => {\n      this.$emit('form-mounted');\n    });\n  },\n  methods: {\n    /** FORM INPUT HANDLING */\n\n    fetchAutocomplete(params) {\n      /**\n       * triggered if field has an autocomplete functionality\n       * (chips-input, autocomplete-input, chips-below-input)\n       *\n       * @event fetch-autocomplete\n       *\n       * @property {string} value - the string to autocomplete\n       * @property {string} name - the name of the field\n       * @property {string} fieldKey - a unique identifier for the field, generated here in BaseForm and assigned to the native <input> field\n       * @property {string} source - the url to request the data from\n       * @property {?string} equivalent - string specified for related fields. e.g. for contributor roles equivalent is `contributor`\n       * @property {?string[]} parentFields - in case the autocomplete event originates from a subform the subform id's (field property names) are specififed in this array (most nested property last)\n       */\n      this.$emit('fetch-autocomplete', params);\n    },\n    /**\n     * function triggered when an input field input was completed (e.g. an option selected in chips input or\n     *  an enter key triggered in BaseInput or after a date was validated)\n     * @param {string|number|Object|Array} value - the updated value\n     * @param {string} fieldName - the name of the field in question\n     * @param {number} index - if field is repeatable - the index in the valueList array\n     */\n    onInputComplete(value, fieldName, index = -1) {\n      // update the valueListInt\n      this.setFieldValue(value, fieldName, index);\n\n      /**\n       * event emitted once an input was completed (e.g. an option selected in chips input or\n       *  an enter key triggered in BaseInput or after a date was validated)\n       *  @event input-complete\n       *  @property {string, number, Object, Array} - the updated value\n       */\n      this.$emit('input-complete', this.valueListInt);\n    },\n    /**\n     * triggered if value in form field changed\n     * @param {*} value - the altered field value\n     * @param {string} fieldName - the property name of the altered field\n     * @param {number} index - the field index if field is repeatable\n     */\n    setFieldValue(value, fieldName, index = -1) {\n      if (index >= 0) {\n        this.valueListInt[fieldName][index] = JSON.parse(JSON.stringify(value));\n      } else {\n        this.valueListInt[fieldName] = value ? JSON.parse(JSON.stringify(value)) : value;\n      }\n    },\n\n    /** FIELD VALUE INITIALIZATION */\n\n    /**\n     * go through all fields relevant for display and assign an appropriate value\n     */\n    initializeValueObject() {\n      const newValueList = {};\n      this.cleanedAndSortedFormFieldList.forEach((field) => {\n        newValueList[field.name] = this.getInitialFieldValue(field);\n      });\n      this.valueListInt = newValueList;\n    },\n    /**\n     * function to determine the appropriate value for a field\n     * @param {Object} field - the openAPI definition of the field\n     * @returns {{[p: string]: *}|*|boolean|string|string|*[]}\n     */\n    getInitialFieldValue({ name, 'x-attrs': xAttrs, type, items, properties }) {\n      // get the current field value\n      const value = this.modelValue[name];\n      // if the field is hidden no need to initialize\n      if (xAttrs?.hidden) return value;\n      // get the OpenAPI x-attrs (that we use for form config) field type\n      const xAttrsFieldType = xAttrs?.field_type;\n      // valid types in OpenAPI definition are 'number' and 'integer'\n      if (['number', 'integer'].includes(type)) {\n        return value >=0 ? value : null;\n      }\n      // check special case single-choice chips (is chips but is saved as\n      // (multilang) object on backend)\n      if (xAttrsFieldType && xAttrsFieldType.includes('chips')\n        && type === 'object') {\n        if (value && Object.keys(value).length) {\n          return [].concat(value);\n        }\n        return [];\n      }\n      // check if field is array\n      if (type === 'array') {\n        // check if values are already present and set those if yes\n        if (typeof value === 'object' && value && value.length) {\n          return [].concat(value);\n        }\n        if (!xAttrs || !xAttrsFieldType\n          || (xAttrsFieldType && !xAttrsFieldType.includes('chips'))) {\n          return [].concat(this.getInitialFieldValue(items));\n        }\n        // else return empty array\n        return [];\n        // check if field is object\n      } if (type === 'object') {\n        const initObj = {};\n        // for each property in the object also get initial values\n        Object.keys(properties).forEach((key) => {\n          initObj[key] = this.getInitialFieldValue(properties[key]);\n        });\n        return ({ ...initObj, ...value });\n      }\n\n      // check if field is boolean\n      if (type === 'boolean') {\n        return value || false;\n      }\n      // if it is not an array or object simply return value from list or empty string\n      return (typeof value === 'string' ? value : '');\n    },\n\n    /** REPEATABLE FIELDS */\n\n    /**\n     * triggered on user clicking multiply button\n     * @param {Object} field - the openAPI information of the form field\n     * @param {number} index - the index of the field where the multiply button was pressed\n     */\n    multiplyField(field, index) {\n      // get the initialized new field values\n      const newFieldValues = this.getInitialFieldValue(field.items);\n      // check if function call is coming from an input field where field can only be\n      // inserted at last position\n      if (!index && index !== 0) {\n        // add field at the end of array\n        this.valueListInt[field.name].push(newFieldValues);\n        // else its coming from an inline repeatable field\n      } else {\n        // insert at the correct level\n        this.valueListInt[field.name].splice(index + 1, 0, newFieldValues);\n      }\n\n      // set multiply params - this is needed to focus the new input element\n      // on updated() (can not do it here because elements not rendered yet)\n      this.multiplyParams = {\n        index: !index && index !== 0\n          ? this.valueListInt[field.name].length - 1 : index + 1,\n        name: field.name,\n      };\n    },\n    /**\n     * remove multiplied field again\n     * @param {Object} field - the openAPI information of the form field\n     * @param {number} index - the index of the field where the remove button was pressed\n     */\n    removeField(field, index) {\n      const fieldGroupValues = this.valueListInt[field.name];\n      // only splice off group if more than one field visible\n      if (fieldGroupValues && fieldGroupValues.length > 1) {\n        fieldGroupValues.splice(index, 1);\n        // else just clear the fields\n      } else {\n        fieldGroupValues[index] = this.getInitialFieldValue(field.items);\n      }\n      // inform parent of changes\n      this.$emit('input-complete', this.valueListInt);\n    },\n\n    /** VALIDATION */\n\n    /**\n     * Trigger public validate function for each form component\n     * Note: Currently a validation function is only implemented for baseChipsBelow\n     *\n     * @public\n     * @returns {boolean} - forms error state\n     */\n    validate() {\n      const errors = [];\n      // get form elements to iterate through\n      const formFields = this.$refs.baseFormField;\n      // iterate through all form fields, trigger components validation function and\n      // set error state if needed\n      formFields.forEach((field) => {\n        if (Object.keys(field.$refs).length) {\n          // get first ref name\n          const refName = Object.keys(field.$refs)[0];\n          // check if component has a validate function\n          if (field.$refs[refName].validate !== undefined) {\n            // validate component\n            const hasErrors = field.$refs[refName].validate();\n            // set error state if needed\n            if (hasErrors) { errors.push(hasErrors); }\n          }\n        }\n      });\n      // return error state\n      return !!errors.length;\n    },\n\n    /** HELPER FUNCTIONS FOR INDIVIDUAL FIELDS */\n\n    /**\n     * get all the component properties per field that are necessary for the BaseFormFieldCreator\n     *  component\n     * @param {Object} element - the openAPI field definition information\n     * @param {number} index - element row index\n     * @param {number} groupIndex - index of element within a row\n     * @param {number?} [valueIndex=1] - index of element if field is repeatable\n     * @returns {{fieldGroupParams: ({readonly labelPropertyName: string, readonly identifierPropertyName: string, readonly validationTexts: Object, readonly renderHeaderAs: string, readonly fieldProps: Object, readonly clearable: boolean, readonly showErrorIcon: boolean, readonly dropDownLists: Object, readonly fieldIsLoading: string, readonly fieldsWithTabs: *[], readonly formStyle: Object, readonly formId: string, readonly availableLocales: *[], readonly language: string, readonly valueList: Object, readonly formFieldJson: Object}|null), showErrorIcon: boolean, labelPropertyName: string, clearable: boolean, validationTexts: (*|Object), dropDownList: *, fieldKey: string, autocompleteLoading: boolean, sortText: (string|string), language: string, label: (*|string), fieldValue: *, showLabel: boolean, identifierPropertyName: string, availableLocales: *[], field, secondaryDropdown: *, fieldProps: (any|{})}}\n     */\n    formFieldComponentProps(element, index, groupIndex, valueIndex = -1) {\n      // get the element.name for easier access\n      const { name } = element;\n      // get all fieldProps of that field if set, otherwise set empty array\n      // important to create an independent copy because properties eventually get deleted\n      // later on\n      let singleFieldProps = this.fieldProps[name]\n        ? JSON.parse(JSON.stringify(this.fieldProps[name])) : {};\n      // store in variable if field is repeatable\n      const fieldRepeatable = valueIndex >= 0;\n      // check if field is repeatable\n      if (fieldRepeatable) {\n        let repeatableFieldProps;\n        if (element['x-attrs']?.field_type === 'group') {\n          repeatableFieldProps = singleFieldProps[valueIndex];\n        } else {\n          // if yes get the field Props that are actually settable for each field individually\n          // and present in the fieldProps object\n          const existingIndividualFieldProps = Object.entries(singleFieldProps)\n            .filter(([key]) => INDIVIDUAL_REPEATABLE_FIELDPROPS.includes(key));\n          // now check if any individually settable field props were found for the field\n          if (existingIndividualFieldProps.length) {\n            // now get an object that only contains the fieldProps of repeatable fields where the\n            // index is present in the value object\n            // otherwise delete the value object from the fieldProps completely (since usually not\n            // compatible with actual fieldProp type and values not usable\n            repeatableFieldProps = existingIndividualFieldProps.reduce((prev, [key, value]) => {\n              // check if the input field index exists as a key in the value object\n              if (Object.keys(value).includes(valueIndex.toString())) {\n                // if yes - add it to the object with the appropriate value\n                return {\n                  ...prev,\n                  [key]: value[valueIndex.toString()],\n                };\n              }\n              // else delete the fieldProp from the fieldProps object completely\n              delete singleFieldProps[key];\n              // and just return the unmodified object\n              return prev;\n            }, {});\n          }\n        }\n        // finally actually combine the original fieldProps object with the properties settable\n        // per repeated field\n        singleFieldProps = {\n          ...singleFieldProps,\n          ...repeatableFieldProps,\n\n        };\n      }\n      // create a unique string for identifier(key) purposes out of field index\n      // and (if field is repeatable) value index\n      const comboIndex = fieldRepeatable ? `${index}_${groupIndex}_${valueIndex}` : `${index}_${groupIndex}`;\n      // define a unique field key needed for identification and in autocomplete functionality\n      // (loader display and correct dropdown options assignment)\n      const fieldKey = `${name}_${comboIndex}_${this.formId}`;\n      // get the relevant error message(s) from `errorMessagesObject` already here since we need it\n      // several times\n      const errorMessagesObjectExtract = this.getErrorMessage(name, valueIndex);\n\n      return {\n        field: element,\n        label: singleFieldProps && singleFieldProps.label\n          ? singleFieldProps.label : this.getFieldName(element),\n        fieldProps: singleFieldProps,\n        showLabel: !this.allowMultiply({ type: element.type, xAttrs: element['x-attrs'] })\n          || !this.multiplyButtonsInline(element) || valueIndex === 0,\n        dropDownList: this.getDropDown(name, fieldKey),\n        secondaryDropdown: this.getDropDown([`${name}_secondary`], fieldKey),\n        language: this.language,\n        availableLocales: this.availableLocales,\n        sortText: this.getI18nTerm('form.sort') || 'Sort',\n        fieldKey: fieldKey,\n        autocompleteLoading: this.fieldIsLoading === name || this.fieldLoadingId === fieldKey ||  singleFieldProps.isLoading,\n        // add component props to form fields creator props if list contains a field_type 'group'\n        fieldGroupParams: this.cleanedAndSortedFormFieldList\n          .some(field => field['x-attrs'] && field['x-attrs'].field_type === 'group')\n          ? this.$props : null,\n        clearable: this.clearable,\n        showErrorIcon: this.showErrorIcon,\n        validationTexts: singleFieldProps.validationTexts || this.validationTexts,\n        identifierPropertyName: this.identifierPropertyName,\n        labelPropertyName: this.labelPropertyName,\n        assistiveText: singleFieldProps.assistiveText || this.assistiveText,\n        // get string from `errorMessagesObject` and if not present use `fieldProps`\n        errorMessage: errorMessagesObjectExtract || singleFieldProps.errorMessage,\n        invalid: !!(errorMessagesObjectExtract && errorMessagesObjectExtract.length) || singleFieldProps.invalid,\n      };\n    },\n    /**\n     * function to extract error messages string from errorMessageObject\n     * @param {string} name - the field name\n     * @param {number} valueIndex - the index of the field in case it is a repeatable field\n     * @returns {?string|Object} - single field returns the error message, for field groups an object\n     *  is returned (either array for repeatable groups or object for single group), if no error message\n     *  was found undefined is returned\n     */\n    getErrorMessage(name, valueIndex) {\n      // extract error messages for a field, depending on if repeatable or not\n      const errors = valueIndex >= 0 ? this.errorMessagesObject?.[name]?.[valueIndex] : this.errorMessagesObject?.[name];\n      // if messages were found and the retrieved array value is a string we are at the lowest level\n      if (errors && typeof errors === 'object' && typeof errors[0] === 'string') {\n        // return all array strings\n        return errors.join(' ');\n      }\n      // else either the field has no errors or it is an object meant for\n      // a field group - either way - return that\n      return errors;\n    },\n    /**\n     * check if field can be multiplied\n     * @param {string} type - the openAPI field definition field type\n     * @param {Object} xAttrs - the openAPI field definition x-attrs with custom\n     *  information filled to configure form\n     * @returns {boolean}\n     */\n    allowMultiply({ type, xAttrs }) {\n      // field can be multiplied if it is an array and not a chips or chips-below\n      // field\n      return type === 'array' && (!xAttrs || !xAttrs.field_type || (xAttrs\n        && !['chips', 'chips-below'].includes(xAttrs.field_type)));\n    },\n    /**\n     * check if field should display multiply buttons inline (all but 'group' and 'multiline')\n     * @param {Object} el - the openAPI field definition information\n     * @returns {boolean}\n     */\n    multiplyButtonsInline(el) {\n      return !['group', 'multiline'].includes(el['x-attrs'].field_type);\n    },\n    /**\n     * check if field is a date field with switch buttons above - this means it needs\n     *  more margin on top\n     * @param {Object} fieldXAttrs - the openAPI field information 'x-attrs'\n     * @returns {boolean}\n     */\n    fieldIsDateSwitch(fieldXAttrs) {\n      // check if field is date and is switchable (= date_format is date_year or date_month_year)\n      return fieldXAttrs?.field_type?.includes('date') && fieldXAttrs?.date_format?.includes('_');\n    },\n    /**\n     * get a field name to display\n     * @param {Object} el - the openAPI field definition information\n     * @returns {string}\n     */\n    getFieldName(el) {\n      // use the openAPI definition title or see if there is a i18n translation key with the field key\n      return el.title || this.getI18nTerm(el.name ? `form.${el.name}` : el.name);\n    },\n    /**\n     * determine if field has content to see if multiply buttons should be shown\n     * @param {string} fieldName - the field key / property name\n     * @param {number} index - index in the repeated field\n     * @returns {boolean}\n     */\n    checkFieldContent(fieldName, index = -1) {\n      return this.hasValues(\n        index < 0 ? this.valueListInt[fieldName][index] : this.valueListInt[fieldName],\n        index < 0 ? this.formFieldJson[fieldName] : this.formFieldJson[fieldName].items);\n    },\n    /**\n     * loop through all field values depending on the type of value\n     * @param {*} fieldValues - the values assigned to a form field\n     * @param {Object} [schema={}] - the openAPI field definition\n     * @returns {boolean}\n     */\n    hasValues(fieldValues, schema = {}) {\n      let hasContent = false;\n      if (fieldValues && typeof fieldValues === 'object') {\n        if (fieldValues.length >= 0) {\n          // since evaluation is not based on form field json but on the values data type\n          // we don't know if items or properties need to be passed (because e.g. of\n          // single chips - is object in json schema but values are array)\n          const subSchema = schema.items || schema.properties || {};\n          fieldValues.forEach((values) => {\n            hasContent = this.hasValues(values, subSchema) || hasContent;\n          });\n        } else {\n          const objectKeys = Object.keys(fieldValues);\n          objectKeys\n            .forEach((key) => {\n              hasContent = this.hasValues(fieldValues[key], schema[key]) || hasContent;\n            });\n        }\n      } else {\n        // do not consider hidden fields in the evaluation\n        hasContent = !schema?.['x-attrs']?.hidden && (fieldValues === 0 || !!fieldValues || hasContent);\n      }\n      return hasContent;\n    },\n    /**\n     * function to get the correct dropdown since fieldKey is utilized now to set\n     * drop down more targeted (but remains the same for prefetched options since\n     * we do not have the fieldKey available at the point of data fetching)\n     * @param {string} name - the field name (property) to set the dropdown list for\n     * @param {string} key - the fieldKey of the specific field that should be autocompleted\n     * @returns {[]}\n     */\n    getDropDown(name, key) {\n      const fieldLists = this.dropDownLists[name];\n      // check if field dropdown list is an object with keys\n      // this is checked first since it is the more specific option!\n      if (key && typeof fieldLists === 'object' && !fieldLists.length) {\n        return fieldLists[key] || [];\n      }\n      // check if dropdown list is array\n      if (typeof fieldLists === 'object' && fieldLists.length) {\n        return fieldLists;\n      }\n      return [];\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    class=\"base-form\"\n    :style=\"formStyle\">\n    <!-- OPTIONAL HEADER -->\n    <component\n      :is=\"renderHeaderAs\"\n      v-if=\"formHeader\"\n      class=\"base-form__header\">\n      {{ formHeader }}\n    </component>\n    <!-- FORM -->\n    <div\n      class=\"base-form__body\">\n      <!-- A FORM ROW -->\n      <div\n        v-for=\"({ rowId, type: rowType, data }, rowIndex) in formFieldListInt\"\n        :key=\"`form-row-${formId}-${rowId}`\"\n        :class=\"['base-form__form-row', `base-form__form-row--${rowType}`]\">\n        <!-- A SINGLE PROPERTY IN THE FORM FIELDS DEFINITION -->\n        <template v-for=\"(field, index) in data\">\n          <!-- FOR A SINGLE FORM FIELD - RENDER BASEFORMFIELDCREATOR COMPONENT -->\n          <BaseFormFieldCreator\n            v-if=\"!allowMultiply({ type: field.type, xAttrs: field['x-attrs'] })\"\n            ref=\"baseFormField\"\n            :key=\"`${field.name}_${rowId}_${field.fieldId}_${formId}`\"\n            v-bind=\"formFieldComponentProps(field, index, rowIndex)\"\n            v-model=\"valueListInt[field.name]\"\n            :class=\"[\n              'base-form__input-field',\n              `base-form__input-field--${rowType}`,\n              // for BaseToogle add a top margin in height of label if it is in a row with other elements\n              { 'base-form__input-field--top-margin': field.type === 'boolean'\n                && data.some((rowField) => rowField.type !== 'boolean') },\n              { 'base-form__input-field--date-switch-spacing': fieldIsDateSwitch(field['x-attrs'])},\n            ]\"\n            @fetch-autocomplete=\"fetchAutocomplete\"\n            @input-complete=\"onInputComplete($event, field.name)\">\n            <template #label-addition=\"{ fieldName, groupNames }\">\n              <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs))\n              @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n              @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n              <slot\n                name=\"label-addition\"\n                :field-name=\"fieldName\"\n                :group-names=\"groupNames\" />\n            </template>\n            <template #pre-input-field=\"{ fieldName, groupNames }\">\n              <!-- @slot slot to add elements within the form field but in a row before the actual input field. for an example see [BaseInput](BaseInput)\n              @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n              @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n              <slot\n                name=\"pre-input-field\"\n                :field-name=\"fieldName\"\n                :group-names=\"groupNames\" />\n            </template>\n            <template\n              #input-field-addition-before=\"{ fieldName, groupNames }\">\n              <!-- @slot Slot to allow for additional elements in the input field <div> (before <input>)\n              @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n              @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n              <slot\n                name=\"input-field-addition-before\"\n                :field-name=\"fieldName\"\n                :group-names=\"groupNames\" />\n            </template>\n            <template #input-field-inline-before=\"{ fieldName, groupNames }\">\n              <!-- @slot to add elements directly inline before the input (contrary to `input-field-addition-before` this does not wrap. for an example see [BaseInput](BaseInput)\n              @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n              @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n              <slot\n                name=\"input-field-inline-before\"\n                :field-name=\"fieldName\"\n                :group-names=\"groupNames\" />\n              <span\n                v-if=\"field['x-attrs'] && field['x-attrs'].text_before\"\n                class=\"base-form__input-field__text-before\">\n                {{ field['x-attrs'].text_before }}\n              </span>\n            </template>\n            <template #input-field-addition-after=\"{ fieldName, groupNames }\">\n              <span\n                v-if=\"field['x-attrs'] && field['x-attrs'].text_after\"\n                class=\"base-form__input-field__text-after\">\n                {{ field['x-attrs'].text_after }}\n              </span>\n              <!-- @slot for adding elements after input\n              @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n              @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n              <slot\n                name=\"input-field-addition-after\"\n                :field-name=\"fieldName\"\n                :group-names=\"groupNames\" />\n            </template>\n            <template #post-input-field=\"{ fieldName, groupNames }\">\n              <!-- @slot for adding elements at the end covering the whole height\n              @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n              @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n              <slot\n                name=\"post-input-field\"\n                :field-name=\"fieldName\"\n                :group-names=\"groupNames\" />\n            </template>\n            <template #error-icon>\n              <!-- @slot use a custom icon instead of standard error/warning icon -->\n              <slot name=\"error-icon\" />\n            </template>\n            <template #remove-icon>\n              <!-- @slot use a custom icon instead of standard remove icon -->\n              <slot name=\"remove-icon\" />\n            </template>\n            <template #below-input=\"{ fieldName, groupNames }\">\n              <!-- @slot below-input slot added to e.g. add drop down\n              @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n              @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n              <slot\n                name=\"below-input\"\n                :field-name=\"fieldName\"\n                :group-names=\"groupNames\" />\n            </template>\n            <template #drop-down-entry=\"{ option, fieldName, groupNames }\">\n              <!-- @slot customize the form field drop down options\n                @binding {object} option - the option object\n                @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n                @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n              <slot\n                :field-name=\"fieldName\"\n                :group-names=\"groupNames\"\n                :option=\"option\"\n                name=\"drop-down-entry\" />\n            </template>\n          </BaseFormFieldCreator>\n\n          <!-- FOR REPEATABLE FIELDS - ALLOW FOR MULTIPLE VALUES PER FIELD -->\n          <div\n            v-else-if=\"allowMultiply({ type: field.type, xAttrs: field['x-attrs'] })\"\n            :key=\"`${field.name}_${field.fieldId}_${formId}_wrapper`\"\n            :class=\"['base-form__input-field',\n                     `base-form__input-field--${rowType}`,\n                     { 'base-form__input-field--date-switch-spacing': fieldIsDateSwitch(field['x-attrs'])}]\">\n            <!-- wrapper around form field group and remove button -->\n            <div\n              v-for=\"(value, valueIndex) in valueListInt[field.name]\"\n              :ref=\"field.name\"\n              :key=\"`${field.name}_${index}_${valueIndex}_${formId}_wrapper`\"\n              :class=\"[{ 'base-form__repeatable-field': multiplyButtonsInline(field) }]\">\n              <BaseFormFieldCreator\n                :key=\"`${field.name}_${index}_${valueIndex}_${formId}`\"\n                ref=\"baseFormField\"\n                v-bind=\"formFieldComponentProps(field, index, rowIndex, valueIndex)\"\n                v-model=\"valueListInt[field.name][valueIndex]\"\n                :class=\"['base-form__input-component',\n                         { 'base-form__input-component--margin-bottom': !multiplyButtonsInline(field) }]\"\n                @fetch-autocomplete=\"fetchAutocomplete\"\n                @input-complete=\"onInputComplete(\n                  $event,\n                  field.name,\n                  valueIndex)\">\n                <template #label-addition=\"{ fieldName, groupNames }\">\n                  <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs))\n                    @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n                    @binding {number} index - the array index of field values\n                    @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n                  <slot\n                    name=\"label-addition\"\n                    :field-name=\"fieldName\"\n                    :group-names=\"groupNames\"\n                    :index=\"valueIndex\" />\n                </template>\n                <template #pre-input-field=\"{ fieldName, groupNames }\">\n                  <!-- @slot slot to add elements within the form field but in a row before the actual input field. for an example see [BaseInput](BaseInput)\n                  @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n                  @binding {number} index - the array index of field values\n                  @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n                  <slot\n                    name=\"pre-input-field\"\n                    :field-name=\"fieldName\"\n                    :group-names=\"groupNames\"\n                    :index=\"valueIndex\" />\n                </template>\n                <template\n                  #input-field-addition-before=\"{ fieldName, groupNames }\">\n                  <!-- @slot Slot to allow for additional elements in the input field \\<div\\>\n                    (before \\<input\\>)\n                  @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n                  @binding {number} index - the array index of field values\n                  @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n                  <slot\n                    name=\"input-field-addition-before\"\n                    :field-name=\"fieldName\"\n                    :group-names=\"groupNames\"\n                    :index=\"valueIndex\" />\n                </template>\n                <template #input-field-inline-before=\"{ fieldName, groupNames }\">\n                  <span\n                    v-if=\"field['x-attrs'] && field['x-attrs'].text_before\"\n                    class=\"base-form__input-field__text-before\">\n                    {{ field['x-attrs'].text_before }}\n                  </span>\n                  <!-- @slot to add elements directly inline before the input (contrary to input-field-addition-before this does not wrap. for an example see [BaseInput](BaseInput)\n                  @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n                  @binding {number} index - the array index of field values\n                  @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n                  <slot\n                    name=\"input-field-inline-before\"\n                    :field-name=\"fieldName\"\n                    :group-names=\"groupNames\"\n                    :index=\"valueIndex\" />\n                </template>\n                <template #input-field-addition-after=\"{ fieldName, groupNames }\">\n                  <span\n                    v-if=\"field['x-attrs'] && field['x-attrs'].text_after\"\n                    class=\"base-form__input-field__text-after\">\n                    {{ field['x-attrs'].text_after }}\n                  </span>\n                  <!-- @slot for adding elements after input\n                  @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n                  @binding {number} index - the array index of field values\n                  @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n                  <slot\n                    name=\"input-field-addition-after\"\n                    :field-name=\"fieldName\"\n                    :group-names=\"groupNames\"\n                    :index=\"valueIndex\" />\n                </template>\n                <template #post-input-field=\"{ fieldName, groupNames }\">\n                  <!-- @slot for adding elements at the end covering the whole height\n                  @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n                  @binding {number} index - the array index of field values\n                  @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n                  <slot\n                    name=\"post-input-field\"\n                    :field-name=\"fieldName\"\n                    :group-names=\"groupNames\"\n                    :index=\"valueIndex\" />\n                </template>\n                <template #error-icon>\n                  <!-- @slot use a custom icon instead of standard error/warning icon -->\n                  <slot name=\"error-icon\" />\n                </template>\n                <template #remove-icon>\n                  <!-- @slot use a custom icon instead of standard remove icon -->\n                  <slot name=\"remove-icon\" />\n                </template>\n                <template #below-input=\"{ fieldName, groupNames }\">\n                  <!-- @slot below-input slot added to e.g. add drop down\n                  @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n                  @binding {number} index - the array index of field values\n                  @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n                  <slot\n                    name=\"below-input\"\n                    :field-name=\"fieldName\"\n                    :group-names=\"groupNames\"\n                    :index=\"valueIndex\" />\n                </template>\n                <template #drop-down-entry=\"{ option, fieldName, groupNames }\">\n                  <!-- @slot customize the form field drop down options\n                    @binding {object} option - the option object\n                    @binding {string} field-name - the name of the displayed field (for time range fields there is a '-time' suffix added)\n                    @binding {string[]} group-names - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names -->\n                  <slot\n                    :field-name=\"fieldName\"\n                    :group-names=\"groupNames\"\n                    :option=\"option\"\n                    name=\"drop-down-entry\" />\n                </template>\n              </BaseFormFieldCreator>\n\n              <!-- INLINE MULTIPLY FOR TEXT AND DATE FIELDS -->\n              <template\n                v-if=\"multiplyButtonsInline(field)\">\n                <div\n                  ref=\"multiplyButtons\"\n                  class=\"base-form__inline-buttons\">\n                  <BaseButton\n                    v-if=\"valueListInt[field.name].length > 1\n                      || checkFieldContent(field.name, 0)\"\n                    :icon-title=\"valueListInt[field.name].length === 1\n                      ? getI18nTerm('form.clearField') || 'Clear'\n                      : getI18nTerm('form.removeField', -1, { fieldType: getFieldName(field) })\"\n                    :has-background-color=\"false\"\n                    text=\"\"\n                    button-style=\"single\"\n                    icon=\"remove\"\n                    icon-size=\"large\"\n                    class=\"base-form__inline-button\"\n                    @clicked=\"removeField(field, valueIndex)\" />\n                  <BaseButton\n                    :icon-title=\"valueIndex !== (valueListInt[field.name].length - 1)\n                      ? getI18nTerm('form.addGroupBelow', -1, {\n                        fieldType: getFieldName(field),\n                      }) : getI18nTerm('form.addGroup', -1, {\n                        fieldType: getFieldName(field),\n                      })\"\n                    :has-background-color=\"false\"\n                    text=\"\"\n                    button-style=\"single\"\n                    icon=\"plus\"\n                    icon-size=\"large\"\n                    class=\"base-form__inline-button\"\n                    @clicked=\"multiplyField(field, valueIndex)\" />\n                </div>\n              </template>\n\n              <!-- MULTIPLY FOR MULTILINE FIELDS AND FIELD GROUPS -->\n              <div class=\"base-form__multiply-buttons\">\n                <!-- if there is field content show a 'remove all content' button -->\n                <BaseButton\n                  v-if=\"!multiplyButtonsInline(field) && (valueListInt[field.name].length > 1\n                    || checkFieldContent(field.name, 0))\"\n                  :text=\"valueListInt[field.name].length === 1\n                    ? getI18nTerm('form.clearField') || 'Clear'\n                    : getI18nTerm('form.removeField', -1, { fieldType: getFieldName(field) })\"\n                  :has-background-color=\"false\"\n                  icon-position=\"right\"\n                  icon=\"remove\"\n                  :class=\"['base-form__multiply-button', 'base-form__multiply-button--remove']\"\n                  @clicked=\"removeField(field, valueIndex)\" />\n                <!-- multiply button -->\n                <BaseButton\n                  v-if=\"!multiplyButtonsInline(field)\"\n                  :text=\"getI18nTerm('form.addGroup', -1, {\n                    fieldType: getFieldName(field),\n                  })\"\n                  :has-background-color=\"false\"\n                  icon-position=\"right\"\n                  icon=\"plus\"\n                  class=\"base-form__multiply-button\"\n                  @clicked=\"multiplyField(field, valueIndex)\" />\n              </div>\n            </div>\n          </div>\n        </template>\n      </div>\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-form {\n    position: relative;\n\n    .base-form__header {\n      position: relative;\n      margin: $spacing-small $spacing;\n      color: $font-color-second;\n    }\n\n    .base-form__body {\n      background-color: white;\n      display: flex;\n      flex-direction: column;\n      gap: $spacing;\n      padding: $spacing;\n\n      @media screen and (max-width: $mobile) {\n        padding: $spacing $spacing-small $spacing;\n        gap: $spacing-small;\n      }\n\n      .base-form__form-row {\n        display: flex;\n        flex-direction: row;\n        gap: $spacing;\n        width: 100%;\n        // this is flex-start to keep nice alignment if error message is shown!\n        align-items: flex-start;\n\n        &.base-form__form-row--full {\n          flex-direction: column;\n        }\n\n        // from 870px switch all fields to full width\n        @media screen and (max-width: 870px) {\n          &.base-form__form-row--half, &.base-form__form-row--third {\n            flex-direction: column;\n          }\n        }\n\n        // on mobile reduce the gap between single fields\n        @media screen and (max-width: $mobile) {\n          gap: $spacing-small;\n        }\n\n        .base-form__input-field {\n          flex: 0 1 100%;\n          width: 100%;\n          display: flex;\n          flex-direction: column;\n          gap: $spacing;\n\n          &.base-form__input-field--date-switch-spacing {\n            gap: 0;\n          }\n\n          @media screen and (max-width: 870px) {\n            &.base-form__input-field--date-switch-spacing {\n              margin-top: $spacing-small-half;\n            }\n          }\n\n          @media screen and (max-width: $mobile) {\n            gap: $spacing-small;\n            &.base-form__input-field--date-switch-spacing {\n              margin-top: calc(#{$spacing-small} + #{$spacing-small-half});\n              gap: $spacing-small;\n            }\n          }\n\n          &.base-form__input-field--half {\n            // needed to add the 0.01rem for edge...\n            flex: 0 1 calc(50% - #{$spacing-small} - 0.01rem);\n            max-width: calc(50% - #{$spacing-small} - 0.01rem);\n\n            @media screen and (max-width: 870px) {\n              flex: 0 0 100%;\n              max-width: 100%;\n            }\n          }\n\n          &.base-form__input-field--third {\n            // needed to add the 0.01rem for edge...\n            flex: 0 1 calc(33% - #{$spacing-small} - 0.01rem);\n            max-width: calc(33% - #{$spacing-small} - 0.01rem);\n\n            @media screen and (max-width: 870px) {\n              flex: 0 0 100%;\n              max-width: 100%;\n            }\n          }\n\n          &.base-form__input-field--top-margin {\n            margin-top: $line-height + $spacing-small;\n\n            // since field switches to only one field per row - remove top margin\n            @media screen and (max-width: 870px) {\n              margin-top: 0;\n            }\n          }\n\n          .base-form__repeatable-field {\n            display: flex;\n            align-items: flex-end;\n            transform: none;\n            // this gap needs to be here for the flex box to not go beyond boarder\n            gap: $spacing;\n\n            .base-form__inline-buttons {\n              flex: 0 0 auto;\n              display: flex;\n              align-items: center;\n              color: $font-color-second;\n              // align buttons with the form\n              margin: 0 0 0 (-#{$spacing-small});\n\n              .base-form__inline-button {\n                flex: 0 0 auto;\n                // reduce the button spacing\n                padding: 0 $spacing-small;\n              }\n            }\n          }\n\n          &.base-form__input-field--date-switch-spacing {\n            .base-form__repeatable-field:not(:first-child) {\n              margin-top: calc(#{$spacing-small} + #{$spacing-small-half});\n            }\n          }\n\n          .base-form__input-component {\n            flex: 1 1 auto;\n            /** make input fit the parent container */\n            min-width: 0;\n\n            &.base-form__input-component--margin-bottom {\n              margin-bottom: $spacing-small;\n\n              @media screen and (max-width: $mobile) {\n                margin-bottom: calc(#{$spacing-small} + #{$spacing-small-half});\n              }\n            }\n          }\n\n          .base-form__multiply-buttons {\n            display: flex;\n            flex-direction: column;\n            align-items: flex-start;\n            margin-left: -($spacing);\n\n            @media screen and (max-width: $mobile) {\n              flex-direction: row;\n              flex-wrap: wrap;\n              margin-top: -($spacing-small);\n            }\n\n            .base-form__multiply-button {\n              color: $font-color-second;\n            }\n          }\n\n          .base-form__input-field__text-before {\n            margin-right: $spacing-small;\n          }\n\n          .base-form__input-field__text-after {\n            margin-left: $spacing-small;\n          }\n        }\n      }\n    }\n  }\n</style>\n\n<style lang=\"scss\">\n  @use \"@/styles/variables\" as *;\n\n  .base-form__input-field--third {\n    .base-form-field-creator__date-field-wrapper {\n      flex-direction: column;\n    }\n  }\n\n  @media screen and (min-width: $mobile) {\n    .base-form__input-field {\n      .base-drop-down-list__container {\n        max-width: calc(100% - #{$spacing} * 2);\n      }\n    }\n  }\n</style>\n","<script>\nimport { useId } from '@/composables/useId.js';\nimport BaseForm from '@/components/BaseForm/BaseForm.vue';\nimport { useExtractAttrs } from '@/composables/useExtractAttrs.js';\nimport { computed, ref } from 'vue';\n\nexport default {\n  name: 'BaseFormGroups',\n  components: {\n    BaseForm,\n  },\n  inheritAttrs: false,\n  props: {\n    /**\n     * the json object containing all the field information incl. `x-attrs` custom field\n     * for placeholder, field type, etc. For more information on the attributes see\n     * [BaseForm](BaseForm).\n     * Most importantly the `x-attrs` needs to include the field `form_group` assigning\n     *  a number (1-based index!) to each form field by which fields are grouped.\n     * Optional: add an attribute `form_group_title` to any group field (the field with the\n     *  lowest order takes precedent) to add a form group header.\n     */\n    formFieldJson: {\n      type: Object,\n      required: true,\n    },\n    /**\n     * the values for each field if any already present\n     */\n    modelValue: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * set current language\n     */\n    language: {\n      type: String,\n      default: 'en',\n    },\n    /**\n     * provide information about all available languages\n     */\n    availableLocales: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * an id for field groups to still have unique field ids\n     */\n    formId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define additional style for the form\n     * should be an object eg. `{ 'padding-top': 0 }`.\n     *  note: this applies to [BaseForm](BaseForm) not the wrapper\n     *  component\n     */\n    formStyle: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * define fields (specify field name!) for which tabs should be shown\n     */\n    fieldsWithTabs: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * enter the field name of a field that is currently fetching autocomplete\n     * results\n     */\n    fieldIsLoading: {\n      type: String,\n      default: '',\n    },\n    /**\n     * provide an object that contains the options list for all\n     * fields with autocomplete / chips input\n     */\n    dropDownLists: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * define if error icon should be shown.\n     * for an example on how it looks on an individual form field see [BaseInput](BaseInput)\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * provide all error messages for fields in a separate object\n     * same structure as modelValue, final value should be an array\n     * of messages\n     *\n     * example - error in repeatable field group, only the second group has an error:\n     * { [fieldGroupName]: [{}, { amount: ['This field is required.'] }]}\n     *\n     * caveat: if error messages are provided via errorMessagesObject, they take\n     *  priority over `fieldProps` set values\n     */\n    errorMessagesObject: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * if `true` a remove icon will be shown allowing to remove\n     * all input at once.\n     * for an example on how it looks on an individual form field see [BaseInput](BaseInput)\n     */\n    clearable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * provide an object with settings and properties for each field. This takes an object\n     * with the field name as properties with the props nested.\n     * `{ fieldName1: { required: false, ... }, fieldName2: { ... } }`.\n     *\n     * find the possible variables at the respective input components:\n     * [BaseInput](BaseInput)\n     * [BaseAutocompleteInput](BaseAutocompleteInput)\n     * [BaseMultilineTextInput](BaseMultilineTextInput)\n     * [BaseChipsInput](BaseChipsInput)\n     * [BaseChipsBelow](BaseChipsBelow)\n     * [BaseDateInput](BaseDateInput)\n     * [BaseToggle](BaseToggle)\n     */\n    fieldProps: {\n      type: Object,\n      default: () => ({}),\n      validator: val => Object.keys(val).length === 0 || Object.values(val)\n        .every(fieldProps => Object.keys(fieldProps)),\n    },\n  },\n  emits: ['update:model-value', 'input-complete', 'fetch-autocomplete', 'form-mounted'],\n  setup(props, { emit }) {\n    /** INTERNAL ID */\n    /**\n     * create an internal id for looping purposes\n     * @returns {string}\n     */\n    const groupsId = useId();\n\n    /** ATTRS HANDLING */\n    const { rootAttrs, forwardAttrs } = useExtractAttrs();\n\n    /**\n     * the formFieldJSON needs to be separated in to the specific groups according\n     * to `form_group` `x-attrs` field.\n     *  Fields that do not have the attribute set will be added at the end.\n     * @returns {Object[]}\n     */\n    const formFieldsGrouped = computed(() => {\n      const groupedFormFields = [];\n      const noGroupFields = {};\n      Object.entries(props.formFieldJson).forEach(([key, value]) => {\n        // check if the array index position exists already\n        if (value['x-attrs'] && value['x-attrs'].form_group) {\n          // if yes add the field information object to it (-1 because it is a 1-based\n          // index number and we need to set position in groups array)\n          const groupIndex = value['x-attrs'].form_group - 1;\n          // check if that array position already has content\n          if (groupedFormFields[groupIndex]) {\n            // if yes - add the object property\n            groupedFormFields[groupIndex][key] = value;\n          } else {\n            // if not set an object with first property\n            groupedFormFields[groupIndex] = {\n              [key]: value,\n            };\n          }\n        } else {\n          // if not - save the field to a separate object that will be added last\n          noGroupFields[key] = value;\n        }\n      });\n      if (Object.keys(noGroupFields).length) {\n        groupedFormFields.push(noGroupFields);\n      }\n      return groupedFormFields;\n    });\n\n    /**\n     * provide the necessary values to each form specifically by mapping\n     * from the grouped form fields json\n     * @returns {{[fieldName: string]: *}[]}\n     */\n    const formValuesGrouped = computed(() => {\n      return formFieldsGrouped.value.map((group) => {\n        return Object.fromEntries(Object.keys(group).map((key) => [key, props.modelValue[key]]));\n      });\n    });\n\n    /**\n     * to only emit value when all forms are mounted - keep state with this variable\n     * @type {Ref<UnwrapRef<boolean[]>, UnwrapRef<boolean[]> | boolean[]>}\n     */\n    const formsMounted = ref(Array.from({length: formFieldsGrouped.value.length}, () => false));\n\n    /**\n     * call when a form was mounted\n     * @param {number} index - index of the form in the forms array\n     */\n    function formMounted(index) {\n      // set the state variable true\n      formsMounted.value[index] = true;\n      // and check if all forms were mounted already\n      if (allFormsMounted.value) {\n        // if yes - emit value\n        emit('form-mounted');\n      }\n    }\n\n    function updateFormValues(val) {\n      emit('update:model-value', {\n        ...props.modelValue,\n        ...JSON.parse(JSON.stringify(val)),\n      });\n    }\n\n    const allFormsMounted = computed(() => !formsMounted.value.some(mountedVal => !mountedVal));\n\n    return {\n      groupsId,\n      rootAttrs,\n      forwardAttrs,\n      formFieldsGrouped,\n      formValuesGrouped,\n      formMounted,\n      updateFormValues,\n      allFormsMounted,\n    };\n  },\n  computed: {\n    /**\n     * modify the component $props, so they can be forwarded to BaseForm directly via\n     * v-bind\n     * @returns {{}}\n     */\n    formProps() {\n      const newProps = JSON.parse(JSON.stringify(this.$props));\n      delete newProps.formFieldJson;\n      delete newProps.formId;\n      delete newProps.modelValue;\n      return {\n        ...this.forwardAttrs,\n        ...newProps,\n      };\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    v-bind=\"rootAttrs\"\n    class=\"base-form-groups\">\n    <!-- form-field-json and model-value are below v-bind because we want to overwrite\n      the values provided in props -->\n    <BaseForm\n      v-for=\"(formGroup, index) of formFieldsGrouped\"\n      :key=\"`${groupsId}-${index}`\"\n      v-bind=\"formProps\"\n      :form-field-json=\"formGroup\"\n      :model-value=\"formValuesGrouped[index]\"\n      :form-id=\"`${formId}-${index}`\"\n      class=\"base-form-groups__group\"\n      @fetch-autocomplete=\"$emit('fetch-autocomplete', $event)\"\n      @input-complete=\"$emit('input-complete', $event)\"\n      @form-mounted=\"formMounted(index)\"\n      @update:model-value=\"updateFormValues\">\n      <template #label-addition=\"{ fieldName, groupNames, index: fieldIndex }\">\n        <!-- @slot Slot to allow for additional elements on the right side of the label row <div> (e.g. language tabs))\n        @binding {string} field-name - in order to use slot for only one field use a if condition with the form field name (the object property)\n        @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n        @binding {number} index - in case field is repeatable the index of the field -->\n        <slot\n          name=\"label-addition\"\n          :field-name=\"fieldName\"\n          :group-names=\"groupNames\"\n          :index=\"fieldIndex\" />\n      </template>\n      <template #pre-input-field=\"{ fieldName, groupNames, index: fieldIndex }\">\n        <!-- @slot slot to add elements within the form field but in a row before the actual input field. For an example see [BaseInput](BaseInput).\n        @binding {string} field-name in order to use slot for only one field use a if condition with the form field name (the object property)\n        @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n        @binding {number} index - in case field is repeatable the index of the field -->\n        <slot\n          name=\"pre-input-field\"\n          :field-name=\"fieldName\"\n          :group-names=\"groupNames\"\n          :index=\"fieldIndex\" />\n      </template>\n      <template\n        #input-field-addition-before=\"{ fieldName, groupNames, index: fieldIndex }\">\n        <!-- @slot Slot to allow for additional elements in the input field <div> (before <input>).\n        @binding {string} field-name in order to use slot for only one field use a if condition with the form field name (the object property)\n        @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n        @binding {number} index - in case field is repeatable the index of the field -->\n        <slot\n          name=\"input-field-addition-before\"\n          :field-name=\"fieldName\"\n          :group-names=\"groupNames\"\n          :index=\"fieldIndex\" />\n      </template>\n      <template #input-field-inline-before=\"{ fieldName, groupNames, index: fieldIndex }\">\n        <!-- @slot to add elements directly inline before the input (contrary to input-field-addition-before this does not wrap. For an example see [BaseInput](BaseInput).\n        @binding {string} field-name in order to use slot for only one field use a if condition with the form field name (the object property)\n        @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n        @binding {number} index - in case field is repeatable the index of the field -->\n        <slot\n          name=\"input-field-inline-before\"\n          :field-name=\"fieldName\"\n          :group-names=\"groupNames\"\n          :index=\"fieldIndex\" />\n      </template>\n      <template #input-field-addition-after=\"{ fieldName, groupNames, index: fieldIndex }\">\n        <!-- @slot for adding elements after input\n        @binding {string} field-name in order to use slot for only one field use a if condition with the form field name (the object property)\n        @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n        @binding {number} index - in case field is repeatable the index of the field -->\n        <slot\n          name=\"input-field-addition-after\"\n          :field-name=\"fieldName\"\n          :group-names=\"groupNames\"\n          :index=\"fieldIndex\" />\n      </template>\n      <template #post-input-field=\"{ fieldName, groupNames, index: fieldIndex }\">\n        <!-- @slot for adding elements at the end covering the whole height\n        @binding {string} field-name in order to use slot for only one field use a if condition with the form field name (the object property)\n        @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n        @binding {number} index - in case field is repeatable the index of the field -->\n        <slot\n          name=\"post-input-field\"\n          :field-name=\"fieldName\"\n          :group-names=\"groupNames\"\n          :index=\"fieldIndex\" />\n      </template>\n      <template #error-icon>\n        <!-- @slot use a custom icon instead of standard error/warning icon -->\n        <slot name=\"error-icon\" />\n      </template>\n      <template #remove-icon>\n        <!-- @slot use a custom icon instead of standard remove icon\n        @binding {string} field-name in order to use slot for only one field use a if condition with the form field name (the object property) -->\n        <slot name=\"remove-icon\" />\n      </template>\n      <template #below-input=\"{ fieldName, groupNames, index: fieldIndex }\">\n        <!-- @slot below-input slot added to e.g. add drop down\n        @binding {string} field-name in order to use slot for only one field use a if condition with the form field name (the object property)\n        @binding {string[]} groupNames - in case the slot is for a subform (form group) field, `groupNames` contains the parent field groups names\n        @binding {number} index - in case field is repeatable the index of the field -->\n        <slot\n          name=\"below-input\"\n          :field-name=\"fieldName\"\n          :group-names=\"groupNames\"\n          :index=\"fieldIndex\" />\n      </template>\n    </BaseForm>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n.base-form-groups {\n  .base-form-groups__group:nth-of-type(n+2) {\n    margin-top: $spacing;\n  }\n}\n</style>\n","<script>\nimport { ref, defineAsyncComponent, useTemplateRef } from 'vue';\nimport { useI18n } from '@/composables/useI18n.js';\n\n/**\n * Component to implement the <a href=\"https://github.com/video-dev/hls.js\">HLS.js</a> JavaScript library which adds an HTTP Live Streaming client.\n * It relies on HTML5 video and MediaSource Extensions for playback.\n */\n\nexport default {\n  name: 'BaseHlsVideo',\n  components: {\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseLoader: defineAsyncComponent(() => import('@/components/BaseLoader/BaseLoader.vue')),\n  },\n  props: {\n    /**\n     * url of the media to be displayed\n     */\n    mediaUrl: {\n      type: String,\n      default: '',\n    },\n    /**\n     * url of image for poster property in html5 video tag\n     */\n    mediaPosterUrl: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set height and with from outside\n     */\n    displaySize: {\n      type: Object,\n      default: () => ({ height: '720px', width: '1280px' }),\n    },\n    /**\n     * start video on load\n     */\n    autoplay: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define play button text\n     * could be string or path to i18n json as well\n     */\n    buttonTitle: {\n      type: String,\n      default: 'Play',\n    },\n    /**\n     * define startLevel (size) of hls-video\n     * Note: The default value of -1 indicates automatic start level selection.\n     */\n    hlsStartLevel: {\n      type: Number,\n      default: -1,\n    },\n  },\n  setup() {\n    const { getI18nTerm } = useI18n();\n    const isLoading = ref(false);\n    const hls = ref(() => {});\n    const playButton = ref(true);\n    const video = useTemplateRef('videoEl');\n\n    return {\n      getI18nTerm,\n      isLoading,\n      hls,\n      playButton,\n      video,\n    };\n  },\n  mounted() {\n    // play video if autoplay is enabled\n    if (this.autoplay) this.play();\n  },\n  unmounted() {\n    // destroy hls object to stop buffering and save bandwidth\n    if (this.hls.value) this.hls.value.destroy();\n  },\n  methods: {\n    /**\n     * init video\n     */\n    async init() {\n      // check if the video element exists, otherwise do nothing\n      if (!this.video) return;\n      // set loading state\n      this.isLoading = true;\n      // import hls.js library\n      const HlsLight = await import('hls.js/dist/hls.light.js');\n      // set loading state\n      this.isLoading = false;\n      // map hls.js library for internal use\n      const Hls = HlsLight.default;\n      // check if hls is supported by the browser\n      if (Hls.isSupported()) {\n        // if hls is not initialised yet\n        if (!this.hls.value) {\n          // initialise the hls.js library\n          this.hls.value = new Hls({\n            startLevel: this.hlsStartLevel,\n          });\n          // add the video source\n          this.hls.value.loadSource(this.mediaUrl);\n          // attach media to the video element\n          this.hls.value.attachMedia(this.video);\n          // handle event when the video has finished loading\n          this.hls.value.on(Hls.Events.MANIFEST_PARSED, () => {\n            this.play();\n            this.playButton = false;\n            this.video.controls = true;\n            this.video.focus();\n          });\n        }\n      // else try to use the native video element\n      } else if (this.video.canPlayType('application/vnd.apple.mpegurl')\n          || this.video.canPlayType('application/vnd.apple.mpegurl') === 'maybe') {\n        // set hls state\n        this.hls.value = false;\n        // add media to the video element\n        this.video.src = this.mediaUrl;\n        // handle event when the video has finished loading\n        this.video.addEventListener('loadedmetadata', () => {\n          this.video.play();\n          this.video.focus();\n          this.video.controls = true;\n        });\n      } else {\n        console.warn('Your browser does not support the video tag.');\n        return;\n      }\n      // handle event to pause the video\n      this.video.addEventListener('pause', () => {\n        this.playButton = true;\n      });\n      // handle event to play the video\n      this.video.addEventListener('play', () => {\n        this.playButton = false;\n      });\n    },\n    /**\n     * initialize hls player and start video\n     * @public\n     */\n    play() {\n      if (!this.video) return;\n      // check if the video player is already initialised and play the video\n      if (this.hls.value || this.video.src) {\n        this.video.play();\n        return;\n      }\n      // otherwise initialise the video player\n      this.init();\n    },\n    /**\n     * pause video\n     * @public\n     */\n    pause() {\n      if (!this.video) return;\n      this.video.pause();\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    class=\"base-media-video\">\n    <div\n      v-if=\"isLoading\"\n      class=\"base-media-video__loader\">\n      <BaseLoader\n        class=\"base-media-video__loader__inner\" />\n    </div>\n\n    <button\n      v-if=\"playButton && !isLoading\"\n      :title=\"`${getI18nTerm(buttonTitle)} Video`\"\n      class=\"base-media-video__control\"\n      @keydown.enter.space=\"play\"\n      @click=\"play\">\n      <BaseIcon\n        name=\"play\"\n        class=\"base-media-video__icon\" />\n    </button>\n\n    <!-- tabindex is needed for swiper to handle focus after using tab key -->\n    <video\n      ref=\"videoEl\"\n      :style=\"displaySize\"\n      :poster=\"mediaPosterUrl\"\n      :tabindex=\"playButton ? '-1' : '0'\"\n      class=\"base-media-video__video\">\n      Your browser does not support the video tag.\n    </video>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-media-video {\n    position: relative;\n    min-height: 50px;\n\n    &__control {\n      position: absolute;\n      z-index: 1;\n      top: 50%;\n      left: 50%;\n      width: 50px;\n      height: 50px;\n      border-radius: 50%;\n      transform: translate(-50%, -50%);\n      cursor: pointer;\n      color: $app-color;\n      background-color: white;\n      box-shadow: 0 0 5px 5px rgba(0, 0, 0, 0.15);\n      opacity: 0.5;\n      transition: opacity 250ms ease-in-out;\n\n      &:focus,\n      &:hover {\n        opacity: 1;\n      }\n    }\n\n    &__video {\n      max-height: 100%;\n      max-width: 100%;\n      vertical-align: middle;\n    }\n\n    &__icon {\n      height: 100%;\n      width: 100%;\n    }\n\n    &__loader {\n      position: absolute;\n      width: 100%;\n      height: 100%;\n      display: flex;\n      justify-content: center;\n      align-items: center;\n\n      &__inner {\n        top: 50%;\n        transform: translate(-50%, -50%);\n      }\n    }\n  }\n</style>\n","<script>\n/**\n * Component to render an image and optional lazy-loading\n */\n\nexport default {\n  name: 'BaseImage',\n  props: {\n    /**\n     * set `alt` attribute\n     */\n    alt: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify lazy image loading\n     */\n    lazyload: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set `src` attribute\n     */\n    src: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set `srcSet` attribute\n     * structure: `[{ '640w': 'path' }]`\n     */\n    srcset: {\n      type: Array,\n      default: () => [],\n    },\n  },\n  emits: ['error'],\n  computed: {\n    clearPng() {\n      return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8//t3PQAJbAN2AyakNQAAAABJRU5ErkJggg==';\n    },\n    source() {\n      const last = this.srcset.length - 1;\n      return this.srcset[last]\n        ? Object.values(this.srcset[last])[0] : this.src;\n    },\n    sourceSet() {\n      return this.srcset.length ? this.srcset.map(size => Object.keys(size)\n        .map(width => `${size[width]} ${width}`)).join(', ') : null;\n    },\n  },\n  async mounted() {\n    // to avoid hydration problems with lazysizes in SSR mode\n    // check if component runs on client-side and import lazysizes if needed\n    if (window && this.lazyload) {\n      await import('lazysizes');\n    }\n  },\n  methods: {\n    emitError(event) {\n      /**\n       * @event error\n       * @param {ErrorEvent} - the native <img> error event\n       */\n      this.$emit('error', event);\n    },\n  },\n};\n</script>\n\n<template>\n  <img\n    :alt=\"alt\"\n    :data-src=\"lazyload ? source : undefined\"\n    :data-srcset=\"lazyload ? sourceSet : undefined\"\n    :src=\"lazyload ? clearPng : source\"\n    :srcset=\"lazyload ? null : sourceSet\"\n    :class=\"['base-image', { lazyload: lazyload }]\"\n    @error=\"emitError\">\n</template>\n\n<style lang=\"scss\" scoped>\n  .base-image {\n    max-width: 100%;\n    height: auto;\n    vertical-align: top;\n    transition: opacity 250ms ease-in-out;\n\n    &.lazyload,\n    &.lazyloading {\n      opacity: 0;\n    }\n\n    &.lazyloaded {\n      opacity: 1;\n    }\n  }\n</style>\n","<script>\nimport BaseImage from '@/components/BaseImage/BaseImage.vue';\n\n/**\n * Base Component to render 1 to 4 images in a static grid\n */\nexport default {\n  name: 'BaseImageGrid',\n  components: {\n    BaseImage,\n  },\n  props: {\n    /**\n     * specify alt text (used for each image)\n     */\n    alt: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify lazy image loading\n     */\n    lazyload: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * specify images to display in a grid\n     *\n     * array variants to render a single image using `src` or `srcset` for a responsive image:\n     * **src**: `['path']`\n     * **srcset**: `[{ '640w': 'path' }]`\n     */\n    images: {\n      type: Array,\n      default: () => ([]),\n    },\n  },\n  computed: {\n    /**\n     * Reduce images array to the first 4 images\n     * @returns {*[]}\n     */\n    imagesInt() {\n      return this.images.slice(0, 4);\n    },\n  },\n  methods: {\n    /**\n     * get single src\n     *\n     * @param {string|object} data\n     * @returns {string}\n     */\n    src(data) {\n      return typeof data === 'string'\n        ? data\n        // get last array elements path\n        : Object.entries(data).slice(-1)[0][1];\n    },\n    /**\n     * get srcset\n     *\n     * @param {object} data\n     * @returns {array}\n     */\n    srcset(data) {\n      return typeof data === 'object' ? [data] : [];\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    :class=\"['base-image-grid',\n             'base-image-grid--' + imagesInt.length]\">\n    <div\n      v-for=\"(image, index) in imagesInt\"\n      :key=\"'image' + index\"\n      class=\"base-image-grid__item\">\n      <BaseImage\n        :lazyload=\"true\"\n        :src=\"src(image)\"\n        :srcset=\"srcset(image)\" />\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n$baseImageGrid: base-image-grid;\n.#{$baseImageGrid} {\n  display: grid;\n  grid-gap: 3px;\n  height: 100%;\n  width: 100%;\n\n  &__item {\n    overflow: hidden;\n    background-color: $background-color;\n\n    img {\n      object-fit: cover;\n      width: 100%;\n      height: 100%;\n    }\n  }\n\n  // 1 image\n  &--1 {\n    grid-template-rows: 1fr;\n  }\n\n  // 2 images\n  &--2 {\n    grid-template-rows: 1fr 1fr;\n  }\n\n  // 3 images\n  &--3 {\n    grid-template-rows: 1fr 1fr;\n    grid-template-columns: 1fr 1fr;\n\n    .#{$baseImageGrid}__item {\n      &:nth-of-type(3) {\n        grid-column: 1 / span 2;\n      }\n    }\n  }\n\n  // 4 images\n  &--4 {\n    grid-template-rows: 1fr 1fr;\n    grid-template-columns: 1fr 1fr;\n  }\n}\n</style>\n","<script>\nimport { computed, defineAsyncComponent, useSlots } from 'vue';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\n\nexport default {\n  name: 'BaseInfoPanel',\n  components: {\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseButton: defineAsyncComponent(() => import('@/components/BaseButton/BaseButton.vue')),\n  },\n  props: {\n    /**\n     * specify the name of the icon rendered on the left side or use slot `icon`.\n     *  (see [BaseIcon](BaseIcon) for available icons).\n     *  if no icon should be displayed leave the section empty.\n     */\n    iconName: {\n      type: String,\n      default: 'attention',\n    },\n    /**\n     * define if icon should be aligned `top` or `center`.\n     *  if prop `expandable` is true the default is `top` otherwise the default is `center`.\n     *  @values top, center\n     */\n    alignIcon: {\n      type: String,\n      default: '',\n      validator: val => !val || ['top', 'center'].includes(val),\n    },\n    /**\n     * define the styling of the panel (influences e.g. icon size or padding).\n     */\n    panelStyle: {\n      type: String,\n      default: 'large',\n      validator: val => ['large', 'medium'].includes(val),\n    },\n    /**\n     * should box shadow be visible (useful to turn of if component should\n     *  be rendered inside another box e.g.).\n     */\n    boxShadow: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * the panel header text or use slot `header` instead.\n     */\n    panelHeaderText: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define the HTML element as which the header should be rendered or\n     * use slot `header` instead.\n     */\n    renderPanelHeaderAs: {\n      type: String,\n      default: 'h2',\n    },\n    /**\n     * define panel body text or use slot `text` instead.\n     */\n    text: {\n      type: [String, Array],\n      default: '',\n    },\n    /**\n     * add buttons at the end of the text element via this config and it will\n     *  render [BaseButton](BaseButton) elements - this should be an array of objects with the following\n     *  properties:\n     *\n     *  **`id`**: identifier that will also be emitted via `action` event on button click\n     *  **`label?`**: button label\n     *  **`icon?`**: button icon to be displayed - for available options see [BaseIcon](BaseIcon)\n     *  **`iconPosition?`**: should icon be displayed `left` or `right` of button label, default\n     *    is `right`\n     *  **`disabled?`**: set button disabled\n     *\n     *  **caveat**: `label` and `icon` property are optional but at least one of them needs to be\n     *    specified!\n     */\n    buttonsConfig: {\n      type: Array,\n      default: () => ([]),\n      // see that every button at least has an id and text OR icon\n      validator: val => val.every(({ id, label, icon }) => id && (label || icon)),\n    },\n    /**\n     * if set true an [BaseExpandBox](BaseExpandBox) is rendered inside the text body\n     *  config for this BaseExpandBox can be set via `expandBoxConfig` prop.\n     */\n    expandable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if prop `expandable` is set true use this prop to configure the BaseExpandBox element.\n     *  See [BaseExpandBox](BaseExpandBox#props) for available options.\n     */\n    expandBoxConfig: {\n      type: Object,\n      default: () => ({}),\n    },\n  },\n  emits: ['action'],\n  setup(props) {\n    /** ELEMENT DISPLAY / CONTENT CHECK */\n    const slots = useSlots();\n\n    // for icon element\n    const { slotHasContent: iconSlotHasContent } = useHasSlotContent(slots.icon);\n    /**\n     * should icon HTML element be rendered\n     * @returns {boolean}\n     */\n    const useIconElement = computed(() => {\n      return !!props.iconName || iconSlotHasContent.value;\n    });\n\n    // for element\n    const { slotHasContent: headerSlotHasContent } = useHasSlotContent(slots.header);\n    /**\n     * should header HTML element be rendered\n     * @returns {boolean}\n     */\n    const useHeaderElement = computed(() => !!props.panelHeaderText || headerSlotHasContent.value);\n\n    // for bottom element\n    const { slotHasContent: bottomSlotHasContent } = useHasSlotContent(slots.bottom);\n    /**\n     * should text body HTML element be rendered\n     * @returns {boolean}\n     */\n    const useBottomElement = computed(() => !!props.buttonsConfig.length || bottomSlotHasContent.value);\n\n    return {\n      useIconElement,\n      useHeaderElement,\n      useBottomElement,\n    }\n  },\n  computed: {\n    /**\n     * since prop `text` can be string or array unify for internal rendering\n     *  to always return an array\n     * @returns {string[]}\n     */\n    displayedText() {\n      if (this.text.length && typeof this.text === 'string') {\n        return [this.text];\n      }\n      return this.text;\n    },\n    /**\n     * if user has not set prop `alignIcon` choose value based on prop `expandable`\n     * @returns {string}\n     */\n    alignIconInt() {\n      return this.alignIcon || (this.expandable ? 'top' : 'center');\n    },\n    /**\n     * return the body HTML element - either a native `<div>` or if component\n     *  is `expandable` then the BaseExpandBox component\n     * @returns {Object|string}\n     */\n    textBodyWrapper() {\n      if (this.expandable) {\n        return defineAsyncComponent(() => import('@/components/BaseExpandBox/BaseExpandBox.vue'));\n      }\n      return 'div';\n    },\n    /**\n     * assemble BaseExpandBox props from internal default settings and user specified\n     *  config\n     * @returns {Object}\n     */\n    expandBoxProps() {\n      return {\n        maxCollapsedHeight: 150,\n        boxShadow: !this.expandable,\n        padding: this.expandable ? 'none' : false,\n        ...this.expandBoxConfig,\n      };\n    },\n  },\n  methods: {\n    /**\n     * emit button click event\n     * @param {string} action - the id of the button clicked\n     */\n    emitAction(action) {\n      /**\n       * inform parent of button click\n       * @event action\n       * @param {string} - the id of the button clicked\n       */\n      this.$emit('action', action);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    :class=\"['base-info-panel', { 'base-info-panel--box-shadow': boxShadow },\n             `base-info-panel--${panelStyle}`]\">\n    <!-- LEFT SIDE - ICON -->\n    <div\n      v-if=\"useIconElement\"\n      :class=\"['base-info-panel__icon-wrapper', `base-info-panel__icon-wrapper--${alignIconInt}`]\">\n      <!-- @slot replace the left side icon element -->\n      <slot\n        name=\"icon\">\n        <BaseIcon\n          :name=\"iconName\"\n          :class=\"['base-info-panel__icon', `base-info-panel__icon--${panelStyle}`]\" />\n      </slot>\n    </div>\n\n    <!-- RIGHT SIDE - TEXT -->\n    <div\n      class=\"base-info-panel__text-wrapper\">\n      <!-- HEADER -->\n      <!-- @slot replace the header instead of using `panelHeaderText` -->\n      <slot\n        name=\"header\">\n        <component\n          :is=\"renderPanelHeaderAs\"\n          v-if=\"useHeaderElement\">\n          {{ panelHeaderText }}\n        </component>\n      </slot>\n\n      <!-- BODY -->\n      <component\n        :is=\"textBodyWrapper\"\n        v-bind=\"expandable ? expandBoxProps : false\"\n        class=\"base-info-panel__text-body\">\n        <!-- @slot replace the text body with something custom e.g. BaseTextList -->\n        <slot\n          name=\"text\">\n          <p\n            v-for=\"paragraph in displayedText\"\n            :key=\"paragraph\">\n            {{ paragraph }}\n          </p>\n        </slot>\n        <!-- BOTTOM AREA -->\n        <div\n          v-if=\"useBottomElement\"\n          class=\"base-info-panel__text-body-bottom\">\n          <div\n            class=\"base-info-panel__button-row\">\n            <template\n              v-if=\"!!buttonsConfig.length\">\n              <BaseButton\n                v-for=\"{ id, label, icon, iconPosition, disabled } in buttonsConfig\"\n                :key=\"id\"\n                :text=\"label\"\n                :icon=\"icon\"\n                :disabled=\"disabled ?? false\"\n                :icon-position=\"iconPosition || 'right'\"\n                button-style=\"single\"\n                icon-size=\"large\"\n                @clicked=\"emitAction(id)\" />\n            </template>\n            <!-- @slot replace buttons with custom elements or add some other custom element. If body is expandable these elements are rendered within the expand box.  -->\n            <slot name=\"bottom\" />\n          </div>\n        </div>\n      </component>\n    </div>\n  </div>\n</template>\n\n<style scoped lang=\"scss\">\n@use \"@/styles/variables\" as *;\n\n.base-info-panel {\n  position: relative;\n  display: flex;\n  flex-direction: row;\n  width: 100%;\n  background: #ffffff;\n  gap: $spacing;\n  padding: $spacing-large;\n\n  @media screen and (max-width: $mobile) {\n    padding: $spacing;\n  }\n\n  &.base-info-panel--box-shadow {\n    box-shadow: $box-shadow-reg;\n  }\n\n  .base-info-panel__icon-wrapper {\n    flex: 0 0 auto;\n\n    &.base-info-panel__icon-wrapper--center {\n      margin: auto 0;\n    }\n\n    .base-info-panel__icon {\n      height: $icon-max;\n      width: $icon-max;\n      color: $app-color;\n\n      @media screen and (max-width: $mobile) {\n        height: 32px;\n        width: 32px;\n      }\n    }\n  }\n\n  .base-info-panel__text-wrapper {\n    flex: 1 1 auto;\n\n    .base-info-panel__text-body-bottom {\n      margin-top: $spacing-large;\n\n      @media screen and (max-width: $mobile) {\n        margin-top: $spacing;\n      }\n\n      .base-info-panel__button-row {\n        display: flex;\n        flex-direction: row;\n        gap: $spacing;\n        flex-wrap: wrap;\n\n        @media screen and (max-width: $mobile) {\n          flex-direction: column;\n          gap: $spacing-small;\n          align-items: flex-start;\n        }\n      }\n    }\n  }\n\n  &.base-info-panel--large {\n    padding: $spacing-large;\n\n    @media screen and (max-width: $mobile) {\n      padding: $spacing;\n    }\n\n    .base-info-panel__icon {\n      height: $icon-max;\n      width: $icon-max;\n\n      @media screen and (max-width: $mobile) {\n        height: 32px;\n        width: 32px;\n      }\n    }\n  }\n  &.base-info-panel--medium {\n    padding: $spacing;\n\n    @media screen and (max-width: $mobile) {\n      padding: $spacing-small;\n    }\n\n    .base-info-panel__icon {\n      height: 32px;\n      width: 32px;\n\n      @media screen and (max-width: $mobile) {\n        height: $icon-large;\n        width: $icon-large;\n      }\n    }\n  }\n}\n</style>\n","<script setup>\nimport { computed, ref, shallowRef, useTemplateRef, watch } from 'vue';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\n\n/**\n * A component to display a Leaflet-map with multiple locations\n */\n\ndefineOptions({\n  name: 'BaseMap',\n});\n\nconst props = defineProps({\n  /**\n   * define map attribution\n   */\n  attribution: {\n    type: String,\n    default: 'Source: <a href=\"https://openstreetmap.org/\">OpenStreetMap contributors</a>',\n  },\n  /**\n   * define position of map attribution\n   *   @values topright, bottomleft, bottomright\n   */\n  attributionPosition: {\n    type: String,\n    default: 'bottomright',\n    validator: val => ['topright', 'bottomleft', 'bottomright'].includes(val),\n  },\n  /**\n   * set array index of marker to center map from outside\n   */\n  centerMarker: {\n    type: Number,\n    default: null,\n  },\n  /**\n   * define number of items for cluster sizes\n   *   structure: `{ medium: 5, large: 20, xlarge: 100 }`\n   *   Note: properties `medium`, `large`, `xlarge` are mandatory\n   */\n  clusterSizes: {\n    type: Object,\n    default: () => ({ medium: 5, large: 20, xlarge: 100 }),\n    validator: data => data.medium && data.large && data.xlarge,\n  },\n  /**\n   * define map copyright\n   */\n  copyright: {\n    type: String,\n    default: '<a href=http://creativecommons.org/licenses/by-sa/3.0/>CC BY-SA 3.0</a>',\n  },\n  /**\n   * set array index of marker to highlight it from outside\n   */\n  highlightMarker: {\n    type: Number,\n    default: null,\n  },\n  /**\n   * define html code for a custom icon\n   */\n  icon: {\n    type: String,\n    default: '<svg viewBox=\"0 0 70.866 70.866\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m35.433 0a22.731 22.731 0 0 0-22.731 22.82 24.125 24.125 0 0 0 1.872 9.1814l19.611 38.063a1.3718 1.3718 0 0 0 2.496 0l19.611-38.063a22.249 22.249 0 0 0 1.872-9.1814 22.731 22.731 0 0 0-22.731-22.82zm0 32.858a10.216 10.216 0 1 1 10.216-10.216 10.241 10.241 0 0 1-10.216 10.216z\" fill=\"#010101\"/></svg>',\n  },\n  /**\n   * define icon size\n   */\n  iconSize: {\n    type: Number,\n    default: 32,\n  },\n  /**\n   * define custom options for map data\n   *   e.g. {\n   *          style: 'normal',\n   *          subdomains: ['mapsneu'],\n   *          tileMatrixSet: 'google3857',\n   *          type: 'geolandbasemap'\n   *   }\n   *\n   *   usage custom keys in `url` property:\n   *   https://{s}.wien.gv.at/basemap/{type}/{style}/{tileMatrixSet}/{z}/{y}/{x}.png\n   *\n   *   for more information refer to the [Leaflet TileLayer documentation](https://leafletjs.com/reference.html#tilelayer)\n   */\n  options: {\n    type: Object,\n    default: () => ({}),\n  },\n  /**\n   * define marker\n   *   structure: [{\n   *     coordinates: [16.382782, 48.208309],\n   *     latLng: [48.208309, 16.382782],\n   *     data: [ 'University of Applied Arts', 'Oskar Kokoschka-Platz 2',\n   *     '1010 Vienna', 'Austria']\n   *   }]\n   *   Note: either GeoJSON coordinates or latLng is mandatory\n   */\n  marker: {\n    type: Array,\n    default: () => [],\n    validator: data => data.every(item => (item.latLng || item.coordinates)),\n  },\n  /**\n   * show popups for marker\n   */\n  markerPopups: {\n    type: Boolean,\n    default: true,\n  },\n  /**\n   * define max zoom factor\n   */\n  maxZoom: {\n    type: Number,\n    default: 18,\n  },\n  /**\n   * define url to tileLayer service\n   */\n  url: {\n    type: String,\n    default: '',\n  },\n  /**\n   * specify service for the [tileLayer](https://leafletjs.com/examples/wms/wms.html)\n   * @values WMTS, TMS, WMS'\n   */\n  tileLayerService: {\n    type: String,\n    default: 'WMTS',\n    validator(val) {\n      return ['WMTS', 'TMS', 'WMS'].includes(val);\n    },\n  },\n  /**\n   * define initial zoom factor\n   */\n  zoom: {\n    type: Number,\n    default: 16,\n  },\n});\n\n/**\n * define emits\n */\nconst emits = defineEmits([\n  /**\n   * Event emitted on mouseenter, mouseleave of a map marker\n   * mouseenter: index of the marker object in component property 'marker' array\n   * mouseleave: null\n   *\n   * @event highlighted\n   * @property {number} - array index or null\n   */\n  'highlighted',\n]);\n\n/**\n * set reference to map element\n */\nconst mapElement = useTemplateRef('mapEl');\n/**\n * define leaflet object  reference\n */\nconst L = shallowRef( null);\n/**\n * define leaflet map reference\n */\nconst map = shallowRef(null);\n/**\n * set active popup\n */\nconst activePopUp = ref(null);\n/**\n * define map bounds\n */\nconst boundsPadding = [0, 20];\n/**\n * set highlighted marker\n */\nconst highlightedMarker = ref(null);\n/**\n * define marker CSS class\n * @type {string}\n */\nconst markerClass = 'base-map-marker-icon';\n/**\n * define marker cluster reference\n */\nconst markerCluster = shallowRef(null);\n/**\n * define marker cluster CSS class\n * @type {string}\n */\nconst markerClusterClass = 'base-map-marker-cluster';\n/**\n * define popup options object reference\n */\nconst popupOptions = ref({\n  offset: [10, -25],\n  closeButton: false,\n  keepInView: true,\n});\n/**\n * define scroll wheel zoom reference\n */\nconst scrollWheelZoom = ref(false);\n/**\n * calc popup CSS inline properties\n */\nconst cssProps = computed(() => ({ '--leaflet-popup-offset-bottom': `${popupOptions.value.offset[1]}px` }));\n/**\n * compare marker objects and remove duplicates\n */\nconst markerFiltered = computed(() => {\n  return Array.from(new Set(props.marker.map(JSON.stringify))).map(JSON.parse);\n});\n\n/**\n * define watcher to centre the map to the given marker\n */\nwatch(() => props.centerMarker, (index) => {\n  if (map.value && index !== null) {\n    map.value.setView(\n      getLatLng(markerFiltered.value[index]),\n      props.zoom,\n    );\n  }\n});\n\n/**\n * define watcher to close all markers and highlight the current marker\n */\nwatch(() => props.highlightMarker, (value, before) => {\n  if (value !== null) {\n    // close all open popups\n    map.value.closePopup();\n    // reset all marker\n    resetAllMarker();\n    // get all marker and filter by id\n    map.value.eachLayer((layer) => {\n      // highlight markerCluster\n      if (layer._bounds && layer._icon) {\n        const marker = getLatLng(markerFiltered.value[value]);\n        const bounds = L.value.latLngBounds(layer._bounds);\n        if (bounds.contains(marker)) {\n          layer._icon.classList.add(`${markerClusterClass}--active`);\n          return;\n        }\n      }\n      // highlight marker\n      if (layer.options.id != null && layer.options.id === value) {\n        highlightedMarker.value = layer._icon;\n        highlightedMarker.value.classList.add(`${markerClass}--active`);\n      }\n    });\n    return;\n  }\n  // reset active marker\n  if (highlightedMarker.value != null && activePopUp.value !== before) {\n    highlightedMarker.value.classList.remove(`${markerClass}--active`);\n    highlightedMarker.value = null;\n  }\n  // reset active markerCluster\n  const markerClusterActive = mapElement.value.querySelector(`.${markerClusterClass}--active`);\n  if (markerClusterActive) {\n    markerClusterActive.classList.remove(`${markerClusterClass}--active`);\n  }\n});\n\n/**\n * method to activate a specific marker due toggling a CSS class\n * @param {Object} e - event object\n */\nfunction activateMarker(e) {\n  const { id } = e.target.options;\n  const marker = e.target._icon;\n  // reset all marker\n  resetAllMarker();\n  // set active and populate markerState\n  if (!e.target.options.active) {\n    activePopUp.value = id;\n    emitMarkerState(id);\n    marker.classList.add(`${markerClass}--active`);\n    e.target.options.active = true;\n  }\n}\n\n/**\n * method to reset the active state by removing a CSS class\n * @param {Object} e - event object\n */\nfunction resetMarker(e) {\n  const marker = e.target._icon;\n\n  marker.classList.remove(`${markerClass}--active`);\n  activePopUp.value = null;\n  emitMarkerState(null);\n\n  delete e.target.options.active;\n}\n\n/**\n * method to reset all markers\n */\nfunction resetAllMarker() {\n  map.value.eachLayer((layer) => {\n    const marker = layer._icon;\n\n    if (marker) {\n      marker.classList.remove(`${markerClass}--active`);\n      marker.classList.remove(`${markerClusterClass}--active`);\n      activePopUp.value = null;\n      emitMarkerState(null);\n      // eslint-disable-next-line no-param-reassign\n      delete layer.options.active;\n    }\n  });\n}\n\n/**\n * method to emit the `highlighted` state\n * @param value\n */\nfunction emitMarkerState(value) {\n  emits('highlighted', value);\n}\n\n/**\n * method to get the latLng pair of a given marker object\n * @param item\n * @returns {number[]|*|null|*[]}\n */\nfunction getLatLng(item) {\n  if (item.coordinates) return [item.coordinates[1], item.coordinates[0]];\n  if (item.latLng) return item.latLng;\n  return null;\n}\n\n/**\n * method to initialize and draw the leaflet map, set markers,\n * group markers to clusters, handle marker popups\n * @returns {Promise<void>}\n */\nasync function init() {\n  // Check if leaflet map is already initialized\n  if (L.value) return;\n\n  // Import Leaflet and related plugins\n  L.value = await import('leaflet').then((m) => m.default || m);\n  const { ResponsivePopup } = await import('leaflet-responsive-popup').then((m) => m.default || m);\n  const { MarkerClusterGroup } = await import('leaflet.markercluster').then((m) => m.default || m);\n\n  // Initialize Leaflet map\n  const mapTmp = L.value.map(mapElement.value, {\n    scrollWheelZoom: scrollWheelZoom.value,\n    tap: false, // fix clickEvent for macOS Safari\n  });\n\n  // Set position of attribution\n  mapTmp.attributionControl.setPosition(props.attributionPosition);\n\n  // Draw Leaflet map\n  const mapConfig = {\n    maxZoom: props.maxZoom,\n    attribution: [props.attribution, props.copyright].join(', '),\n    tms: props.tileLayerService === 'TMS',\n    ...props.options,\n  };\n\n  if (props.tileLayerService === 'WMS') {\n    L.value.tileLayer.wms(props.url, mapConfig).addTo(mapTmp);\n  } else {\n    L.value.tileLayer(props.url, mapConfig).addTo(mapTmp);\n  }\n\n  // Add marker to map\n  if (!markerFiltered.value.length) {\n    return;\n  }\n\n  // Custom icon\n  const iconOptions = {\n    className: markerClass,\n    html: props.icon,\n    iconSize: [props.iconSize, props.iconSize],\n    iconAnchor: [props.iconSize / 2, props.iconSize],\n  };\n  const markerIcon = L.value.divIcon(iconOptions);\n\n  // Define Leaflet clusterGroup\n  markerCluster.value = new MarkerClusterGroup({\n    maxClusterRadius: 50,\n    showCoverageOnHover: false,\n    iconCreateFunction: (cluster) => {\n      const items = cluster.getAllChildMarkers().length;\n      let classSize = 'small';\n      let size = 48;\n\n      if (items > props.clusterSizes.medium) {\n        classSize = 'medium';\n        size = 64;\n      }\n\n      if (items > props.clusterSizes.large) {\n        classSize = 'large';\n        size = 80;\n      }\n\n      if (items > props.clusterSizes.xlarge) {\n        classSize = 'xlarge';\n        size = 128;\n      }\n\n      return L.value.divIcon({\n        html: `<div class=\"${markerClusterClass}__inner\">${items}</div>`,\n        className: `${markerClusterClass} ${markerClusterClass}--${classSize}`,\n        iconSize: L.value.point(size, size),\n      });\n    },\n  });\n\n  markerFiltered.value.forEach((item, index) => {\n    const popup = new ResponsivePopup(popupOptions.value);\n    const markerOptions = {\n      id: index,\n      icon: markerIcon,\n    };\n\n    // check if geo reference is present before setting marker on map\n    if (!getLatLng(item)) return;\n\n    // Define marker to map\n    const marker = L.value.marker(L.value.latLng(getLatLng(item)), markerOptions)\n      .on('mouseover', activateMarker)\n      .on('mouseout', resetMarker);\n\n    // Set popup content\n    if (props.markerPopups && Array.isArray(item.data)) {\n      popup.setContent(item.data.join('<br>'));\n      marker.bindPopup(popup);\n    }\n\n    // Add marker to cluster\n    markerCluster.value.addLayer(marker);\n  });\n\n  // Add clusterGroup to map\n  mapTmp.addLayer(markerCluster.value);\n\n  // Check if marker has property latLng or coordinates again, otherwise do not render to map\n  const marker = markerFiltered.value.filter(item => (item.latLng || item.coordinates));\n  if (!marker.length) {\n    return;\n  }\n\n  // Center map based on Marker(s)\n  // has to be called after marker have been set to map\n  const bounds = new L.value.LatLngBounds(\n    markerFiltered.value.map(item => getLatLng(item)),\n  );\n\n  mapTmp.fitBounds(bounds, {\n    padding: boundsPadding,\n    maxZoom: props.zoom,\n  });\n\n  // store map to vue context\n  map.value = mapTmp;\n}\n\n/**\n * init intersection observer to initialise the map only, when in viewport\n */\nuseElementObserver({\n  type: 'intersection',\n  target: mapElement,\n  callback: init,\n  options: {\n    triggerCallbackWhenInViewport: true,\n    stopObservingWhenInViewport: true,\n  },\n});\n</script>\n\n<template>\n  <div\n    ref=\"mapEl\"\n    :style=\"cssProps\"\n    class=\"base-map\" />\n</template>\n\n<style lang=\"scss\" scoped>\n.base-map {\n  min-height: 200px;\n}\n</style>\n\n<style lang=\"scss\">\n@use \"@/styles/variables\" as *;\n\n@import 'leaflet/dist/leaflet.css';\n@import 'leaflet.markercluster/dist/MarkerCluster.css';\n@import 'leaflet-responsive-popup/leaflet.responsive.popup.css';\n\n/* Cluster */\n$clusterClass: '.base-map-marker-cluster';\n#{$clusterClass} {\n  &__inner {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 100%;\n    height: 100%;\n    color: white;\n    font-weight: bold;\n    font-size: $font-size-regular;\n    background-clip: padding-box;\n    border-radius: 50%;\n    border-style: solid;\n    border-color: $map-cluster-bg;\n    background-color: $map-cluster-bg-inner;\n    transition: all 250ms ease-in-out;\n  }\n\n  &.base-map-marker-cluster--small #{$clusterClass}__inner {\n    border-width: 4px;\n  }\n\n  &.base-map-marker-cluster--medium #{$clusterClass}__inner {\n    border-width: 8px;\n  }\n\n  &.base-map-marker-cluster--large #{$clusterClass}__inner {\n    border-width: 8px;\n  }\n\n  &.base-map-marker-cluster--xlarge #{$clusterClass}__inner {\n    border-width: 16px;\n  }\n\n  &--active,\n  &:hover {\n    #{$clusterClass}__inner {\n      background-color: $map-cluster-bg-inner-hover;\n      border-color:  $map-cluster-bg-hover;\n    }\n  }\n}\n\n// cluster spider lines\n.leaflet-pane > svg path.leaflet-interactive {\n  stroke: $app-color;\n}\n\n/* marker */\n.base-map-marker-icon {\n  > svg path {\n    fill: $app-color;\n    transition: fill 250ms ease-in-out;\n  }\n\n  &--active,\n  &:hover {\n    > svg path {\n      fill: $app-color-secondary;\n    }\n  }\n}\n\n/* popup */\n.leaflet-popup {\n\n  &.leaflet-resp-popup-north-west .leaflet-popup-content-wrapper,\n  &.leaflet-resp-popup-west-south .leaflet-popup-content-wrapper,\n  &.leaflet-resp-popup-south-east .leaflet-popup-content-wrapper {\n    border-radius: 0;\n  }\n\n  &.leaflet-resp-popup-south,\n  &.leaflet-resp-popup-south-east {\n    margin-top: var(--leaflet-popup-offset-bottom);\n  }\n}\n\n.leaflet-popup-tip-container {\n  display: none;\n}\n\n.leaflet-popup-content-wrapper {\n  width: 225px;\n  border-radius: 0;\n}\n\n.leaflet-popup-content {\n  margin: $spacing-small $spacing-large $spacing $spacing-small;\n  font-size: $font-size-small;\n  line-height: $line-height-small;\n  color: $font-color;\n}\n\n.leaflet-container {\n  font-family: inherit;\n}\n\n.leaflet-container a.leaflet-popup-close-button {\n  padding: $spacing-small $spacing-small 0 0;\n}\n\n.leaflet-control a {\n  color: $app-color;\n\n  &:hover {\n    color: $app-color-secondary;\n  }\n}\n</style>\n","<script>\nimport { defineAsyncComponent } from 'vue';\nimport cleanDomNodes from '@/directives/cleanDomNodes.js';\nimport { useI18n } from '@/composables/useI18n.js';\n\n/**\n * Component to render different types of text content depending on the data type of prop `data`\n */\n\nexport default {\n  name: 'BaseTextList',\n  components: {\n    BaseTextList: defineAsyncComponent(() => import('./BaseTextList.vue')),\n    BaseLink: defineAsyncComponent(() => import('@/components/BaseLink/BaseLink.vue')),\n    BaseInsertTextAsHtml: defineAsyncComponent(() => import('@/components/BaseInsertTextAsHtml/BaseInsertTextAsHtml.vue')),\n  },\n  directives: {\n    cleanDomNodes,\n  },\n  props: {\n    /**\n     * specify a list of array objects to render different types of text content\n     *\n     * single object structure: `{ label: {string, Object}, data: {string, Object, string[], Object[]} }`\n     *  **label** - a heading for the list section\n     * **data** property variants and their output (see readme.md for examples):\n     * - `{string}` - renders as simple text\n     * - `{Object}` - depending on object properties (see below) renders as chip | external ink | internal link | text | text with tooltip\n     * - `{string[]}` - renders as unordered list\n     * - `{Object[]}` - renders multiple objects (see above)\n     *\n     *  Possible object properties for `{ data : {Object, Object[]} }`:\n     *  - **value** `string` - the displayed text for all types\n     *  - **label** `string?` - an optional pretext in style of 'label:'\n     *  - **altTitle** `string?` - if `interpretTextAsHtml` is set `true`, add a html-free version of the label\n     *    here that can be used for hover title and assistive technologies (needed for type 'chip')\n     * - **[identifierPropertyName]** `string?` - specify the id of a chip or the path for internal link - specify the object property name with prop `identifierPropertyName`\n     * - **id** `string?` - for type chip - an identifier for the chip type (used in link generation)\n     * - **path** `string?` - for type chip (used in link generation)\n     * - **url** `string?` - for external link - the url to link to\n     * - **additional** `Object?` - used for tooltip content generation - an array of objects with properties:\n     *    `label`, `value` optionally `altTitle` (if `interpretTextAsHtml` is set true) and `url` (in case the item should render as link)\n     *    **caveat**: even if tooltip content is created via slot this property (`tooltip`) needs to be present and filled in order for the tooltip to show\n     *\n     * Note: objects wrapped in an extra array are rendered as columns respecting the `cols` property.\n     */\n    data: {\n      type: Array,\n      default: () => ([]),\n    },\n    /**\n     * specify the object property that should be used as identifier\n     *\n     * Note: only applies for chips and internal links:\n     * - chip: to build the link query data\n     *         e.g.: query: `path?chip-link={[identifierPropertyName]:'keywordId',type:'dataObject.id',value:'keywordValue'}`\n     * - internal: to set the link path\n     */\n    identifierPropertyName: {\n      type: String,\n      default: 'source',\n    },\n    /**\n     * specify a query parameter name for type chip links\n     */\n    chipQueryName: {\n      type: String,\n      default: 'chip-link',\n    },\n    /**\n     * render component as e.g.: 'h2' | 'h3'\n     */\n    renderLabelAs: {\n      type: String,\n      default: 'div',\n    },\n    /**\n     * set margin-bottom for the label\n     */\n    labelMarginBottom: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify the number of columns to render array nested objects\n     */\n    cols: {\n      type: Number,\n      default: 2,\n      validator: val => val > 0,\n    },\n    /**\n     * specify the number of columns to render a single object typeof string\n     */\n    colsSingleTextObject: {\n      type: Number,\n      default: 1,\n      validator: val => val > 0,\n    },\n    /**\n     * specify how a link element should be rendered\n     * this needs to be a valid vue link component string (e.g. `'RouterLink'`) or a component directly\n     * and vue-router is necessary\n     * if no routing plugin is found the element will be rendered as <a> tag\n     *\n     * **caveat**: if you are using Nuxt the string `'NuxtLink'` is not enough,\n     *  but you need to import the component as `import { NuxtLink } from '#components';`\n     *  and pass the component to the prop!\n     */\n    renderLinkAs: {\n      type: [String, Object],\n      default: 'RouterLink',\n    },\n    /**\n     * specify how data-list (label, value) should be rendered\n     * Note: Only applies to `{ data: {Object[]} }`.\n     * @values horizontal, vertical\n     */\n    listType: {\n      type: String,\n      default: 'horizontal',\n      validator: val => ['horizontal', 'vertical'].includes(val),\n    },\n    /**\n     * specify the gap between content rows\n     * @values large, small\n     */\n    rowGap: {\n      type: String,\n      default: 'large',\n      validator: val => ['large', 'small'].includes(val),\n    },\n    /**\n     * specify a threshold value in px for the [BaseTooltipBox](BaseTooltipBox) top position calculation\n     *\n     * Note: The value can also be set globally with the CSS variable `--base-tooltip-box-threshold-top`.\n     *       The property will be overwritten by the CSS variable.\n     */\n    tooltipThresholdTop: {\n      type: Number,\n      default: 0,\n    },\n    /**\n     * set true to render `data` or `value` content as html\n     *\n     *  **caveat**: setting this variable `true` can lead to XSS attacks. Only use\n     *    this prop on trusted content and never on user-provided content.\n     */\n    interpretTextAsHtml: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  setup() {\n    /** INTERNATIONALIZATION */\n    const { getLangLabel } = useI18n();\n\n    return {\n      getLangLabel,\n    };\n  },\n  data() {\n    return {\n      /**\n       * variable for handling columns class\n       * Note: is finally evaluated in created lifecycle hook\n       * @type {boolean}\n       */\n      hasColumns: false,\n    };\n  },\n  computed: {\n    /**\n     * evaluate if data is a single object and typeof string\n     * @returns {boolean}\n     */\n    isSingleTextObject() {\n      return this.data.length === 1\n          && this.data[0].data\n          && typeof this.data[0].data === 'string';\n    },\n  },\n  created() {\n    // Check if the parent component is type `BaseTextList`,\n    // and assume it is recursive, and the current `BaseTextList` has columns.\n    // With this workaround, we avoid problems with the CSS var `--columns` in the parent scope.\n    this.hasColumns = this.$parent.$options.name === 'BaseTextList';\n  },\n  methods: {\n    /**\n     * check if all array objects have a key label\n     *\n     * @param {array} data\n     * @param {string} key\n     * @returns {boolean}\n     */\n    containKeys(data, key) {\n      return data.every(obj => Object.keys(obj).includes(key));\n    },\n    /**\n     * check if the link is type `tooltip`\n     * @param {Object} item\n     * @returns {boolean}\n     */\n    isTooltip(item) {\n      return !!item.additional;\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    :style=\"isSingleTextObject ? { '--columns': colsSingleTextObject } : undefined\"\n    :class=\"[\n      'base-text-list',\n      'base-text-list--row-gap-' + rowGap,\n      {\n        'base-text-list--cols': hasColumns || isSingleTextObject && colsSingleTextObject > 1,\n        'base-text-list--cols-single-content': isSingleTextObject && colsSingleTextObject > 1,\n      }]\">\n    <div\n      v-for=\"(item, index) in data\"\n      :key=\"index\"\n      class=\"base-text-list__group\">\n      <component\n        :is=\"renderLabelAs\"\n        v-if=\"item.label\"\n        :class=\"['base-text-list__label', { 'base-text-list__label--mb': labelMarginBottom }]\">\n        {{ getLangLabel(item.label) }}\n      </component>\n\n      <!-- Array as multiple columns -->\n      <template v-if=\"typeof item === 'object' && typeof item[0] === 'object'\">\n        <BaseTextList\n          ref=\"baseTextList\"\n          :cols=\"cols\"\n          :data=\"item\"\n          :identifier-property-name=\"identifierPropertyName\"\n          :label-margin-bottom=\"labelMarginBottom\"\n          :list-type=\"listType\"\n          :render-label-as=\"renderLabelAs\"\n          :style=\"{ '--columns': cols }\"\n          :interpret-text-as-html=\"interpretTextAsHtml\" />\n      </template>\n\n      <!-- String as text -->\n      <!-- get rid of prepending white-space -->\n      <BaseInsertTextAsHtml\n        v-else-if=\"item.data && typeof item.data === 'string'\"\n        :render-element-as=\"'p'\"\n        :text=\"item.data\"\n        :interpret-text-as-html=\"interpretTextAsHtml\"\n        :class=\"[\n          'base-text-list__content',\n          { 'base-text-list__content--pre-line': !interpretTextAsHtml },\n          { 'base-text-list--cols': data.length === 1 }]\" />\n\n      <!-- Array as unordered list -->\n      <ul\n        v-else-if=\"item.data && typeof item.data === 'object' && typeof item.data[0] === 'string'\"\n        class=\"base-text-list__content\">\n        <BaseInsertTextAsHtml\n          v-for=\"(arrayItem, listIndex) in item.data\"\n          :key=\"listIndex\"\n          :render-element-as=\"'li'\"\n          :text=\"arrayItem\"\n          :interpret-text-as-html=\"interpretTextAsHtml\" />\n      </ul>\n\n      <!-- Array/Objects -->\n      <template\n        v-else-if=\"item.data && typeof item.data === 'object'\">\n        <!-- render as comma separated list -->\n        <template\n          v-if=\"!containKeys([].concat(item.data), 'label')\">\n          <div class=\"base-text-list__content base-text-list__content--list\">\n            <span\n              v-for=\"(objectItem, objectIndex) in [].concat(item.data)\"\n              :key=\"objectItem.value\"\n              v-clean-dom-nodes=\"{ recursive: false }\"\n              :class=\"['base-link__wrapper', { 'base-link__wrapper--tooltip': isTooltip(objectItem)}]\">\n              <!-- BaseLink: text, external, internal, text and tooltip -->\n              <BaseLink\n                :identifier-property-name=\"identifierPropertyName\"\n                :identifier-property-value=\"objectItem[identifierPropertyName]\"\n                :chip-query-name=\"chipQueryName\"\n                :path=\"item.path\"\n                :tooltip=\"objectItem.additional\"\n                :type=\"item.id\"\n                :url=\"objectItem.url\"\n                :value=\"objectItem.value\"\n                :alt-title=\"objectItem.altTitle\"\n                :interpret-text-as-html=\"interpretTextAsHtml\"\n                :class=\"['base-text-list__link', { 'base-link--chip-text-list': item.id }]\">\n                <template #tooltip>\n                  <template v-if=\"isTooltip(objectItem)\">\n                    <!-- @slot slot for tooltip content\n                         @binding {array} data - the tooltip data that were provided with the `data` object property `additional` -->\n                    <slot\n                      :data=\"objectItem.additional\"\n                      name=\"tooltip\" />\n                  </template>\n                </template>\n                <!-- add directly after to avoid additional spaces - if this\n                  is separated there will be a space between link and comma -->\n                <!-- eslint-disable-next-line max-len -->\n              </BaseLink><span :key=\"`${objectIndex}-space`\">{{ item.data.length && objectIndex !== item.data.length - 1 && !item.id ? ',&nbsp;' : '' }}</span>\n            </span>\n          </div>\n        </template>\n\n        <!-- render as data list -->\n        <template\n          v-if=\"containKeys([].concat(item.data), 'label')\">\n          <dl\n            v-if=\"typeof item.data === 'object'\"\n            :class=\"['base-text-list__content',\n                     'base-text-list__content--' + listType]\">\n            <template\n              v-for=\"(objectItem) in [].concat(item.data)\"\n              :key=\"objectItem.value\">\n              <dt\n                class=\"base-text-list__content__label\">\n                <template\n                  v-if=\"objectItem.label\">\n                  {{ getLangLabel(objectItem.label) }}:&nbsp;\n                </template>\n              </dt>\n              <dd\n                class=\"base-text-list__content__label base-text-list__content__value\">\n                <BaseLink\n                  :render-link-as=\"renderLinkAs\"\n                  :identifier-property-name=\"identifierPropertyName\"\n                  :identifier-property-value=\"objectItem[identifierPropertyName]\"\n                  :chip-query-name=\"chipQueryName\"\n                  :path=\"item.path\"\n                  :tooltip=\"objectItem.additional\"\n                  :tooltip-threshold-top=\"tooltipThresholdTop\"\n                  :type=\"item.id\"\n                  :url=\"objectItem.url\"\n                  :value=\"objectItem.value\"\n                  :alt-title=\"objectItem.altTitle\"\n                  :interpret-text-as-html=\"interpretTextAsHtml\">\n                  <!-- @slot slot for tooltip content\n                       @binding {array} data - the tooltip data that were provided with the `data` object property `additional` -->\n                  <slot\n                    name=\"tooltip\"\n                    :data=\"objectItem.additional\" />\n                </BaseLink>\n              </dd>\n            </template>\n          </dl>\n        </template>\n      </template>\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-text-list {\n\n    .base-text-list__group {\n      page-break-inside: avoid;\n      break-inside: avoid;\n\n      .base-text-list__label {\n        margin-top: 0;\n        margin-bottom: 0;\n        overflow-wrap: break-word;\n\n        &.base-text-list__label--mb {\n          margin-bottom: $spacing;\n        }\n      }\n\n      // class gets modified in component baseMapLocations\n      .base-text-list__content {\n        position: relative;\n        color: $font-color-second;\n        height: 100%;\n        overflow-wrap: break-word;\n\n        &.base-text-list__content--list {\n          display: flex;\n          flex-direction: row;\n          flex-wrap: wrap;\n\n          .base-link__wrapper {\n            max-width: 100%;\n            min-width: 0;\n\n            &.base-link__wrapper--tooltip {\n              display: inline-flex;\n            }\n          }\n\n          .base-text-list__link {\n            min-width: 0;\n            max-width: 100%;\n\n            &.base-link--chip-text-list {\n              display: inline-block;\n              margin-right: $spacing-small;\n              margin-bottom: $spacing-small-half;\n            }\n          }\n        }\n      }\n\n      .base-text-list__content--pre-line {\n        white-space: pre-line;\n        break-inside: avoid;\n      }\n\n      .base-text-list__content--horizontal {\n\n        .base-text-list__content__label {\n          display: inline;\n        }\n\n        .base-text-list__content__value {\n          display: inline;\n\n          &:after {\n            display: block;\n            content: '';\n            width: 100%;\n          }\n        }\n      }\n\n      .base-text-list__content--vertical {\n        line-height: $line-height;\n\n        .base-text-list__content__label {\n          display: block;\n        }\n\n        .base-text-list__content__value {\n          display: block;\n          color: $font-color;\n          margin-bottom: $spacing-small;\n          word-break: break-word;\n        }\n      }\n    }\n\n    // spacing below elements\n    // Note: Use a negative margin to get an exact bottom boundary\n    //       without extra spacing from paddings of the inner elements.\n    //       Could possibly be done with CSS Masonry layout once it's stable.\n    &.base-text-list--row-gap-small {\n      margin-bottom: -$spacing;\n\n      .base-text-list__group {\n        padding-bottom: $spacing;\n      }\n    }\n\n    &.base-text-list--row-gap-large {\n      margin-bottom: -$line-height;\n\n      .base-text-list__group {\n        padding-bottom: $line-height;\n      }\n    }\n  }\n\n  // columns\n  .base-text-list--cols {\n    columns: var(--columns);\n    column-gap: $spacing-large;\n\n    @media screen and (max-width: $mobile) {\n      columns: inherit;\n    }\n  }\n\n  .base-text-list--cols-single-content {\n    display: flex;\n  }\n</style>\n","<script>\nimport { defineAsyncComponent } from 'vue';\nimport BaseTextList from '@/components/BaseTextList/BaseTextList.vue';\n\n/**\n * A component to display Basemap, locations-list and interact with each other\n */\n\nexport default {\n  name: 'BaseMapLocations',\n  components: {\n    BaseMap: defineAsyncComponent(() => import('@/components/BaseMap/BaseMap.vue')),\n    BaseTextList,\n  },\n  props: {\n    /**\n     * set additional styles for map e.g. height\n     */\n    additionalMapStyles: {\n      type: Object,\n      default: () => ({ height: '368px' }),\n    },\n    /**\n     * define map attribution\n     */\n    attribution: {\n      type: String,\n      default: 'Source: <a href=https://openstreetmap.org/>OpenStreetMap contributors</a>',\n    },\n    /**\n     * define position of map attribution\n     *   @values topright, bottomleft, bottomright\n     */\n    attributionPosition: {\n      type: String,\n      default: 'bottomright',\n      validate(val) {\n        return ['topright', 'bottomleft', 'bottomright'].includes(val);\n      },\n    },\n    /**\n     * define number of items for cluster sizes\n     *   structure: `{ medium: 5, large: 20, xlarge: 100 }`\n     *   Note: properties `medium`, `large`, `xlarge` are mandatory\n     */\n    clusterSizes: {\n      type: Object,\n      default: () => ({ medium: 5, large: 20, xlarge: 100 }),\n      validator: data => data.medium && data.large && data.xlarge,\n    },\n    /**\n     * define map copyright\n     */\n    copyright: {\n      type: String,\n      default: '<a href=http://creativecommons.org/licenses/by-sa/3.0/>CC BY-SA 3.0</a>',\n    },\n    /**\n     * define html code for a custom icon\n     */\n    icon: {\n      type: String,\n      default: '<svg viewBox=\"0 0 70.866 70.866\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m35.433 0a22.731 22.731 0 0 0-22.731 22.82 24.125 24.125 0 0 0 1.872 9.1814l19.611 38.063a1.3718 1.3718 0 0 0 2.496 0l19.611-38.063a22.249 22.249 0 0 0 1.872-9.1814 22.731 22.731 0 0 0-22.731-22.82zm0 32.858a10.216 10.216 0 1 1 10.216-10.216 10.241 10.241 0 0 1-10.216 10.216z\" fill=\"#010101\"/></svg>',\n    },\n    /**\n     * define icon size\n     */\n    iconSize: {\n      type: Number,\n      default: 32,\n    },\n    /**\n     * define label for the locations-list\n     */\n    label: {\n      type: String,\n      default: 'Addresses',\n    },\n    /**\n     * define locations\n     *   structure: [{\n     *     coordinates: [16.382782, 48.208309],\n     *     latLng: [48.208309, 16.382782],\n     *     data: [ 'University of Applied Arts', 'Oskar Kokoschka-Platz 2',\n     *     '1010 Vienna', 'Austria']\n     *   }]\n     *   Note: either coordinates or latLng is mandatory\n     */\n    locations: {\n      type: Array,\n      default: () => [],\n      validator: data => data.filter(item => (item.latLng || item.coordinates)).length\n        === data.length,\n    },\n    /**\n     * deactivate popups for marker\n     */\n    markerPopups: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define max zoom factor\n     */\n    maxZoom: {\n      type: Number,\n      default: 18,\n    },\n    /**\n     * define custom options for map data\n     *   e.g. {\n     *          style: 'normal',\n     *          subdomains: ['mapsneu'],\n     *          tileMatrixSet: 'google3857',\n     *          type: 'geolandbasemap'\n     *   }\n     *\n     *   usage custom keys in `url` property:\n     *   https://{s}.wien.gv.at/basemap/{type}/{style}/{tileMatrixSet}/{z}/{y}/{x}.png\n     *\n     *   for more information refer to the [Leaflet TileLayer documentation](https://leafletjs.com/reference.html#tilelayer)\n     */\n    options: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * define url to tileLayer service\n     */\n    url: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify service for the [tileLayer](https://leafletjs.com/examples/wms/wms.html)\n     * @values WMTS, TMS, WMS'\n     */\n    tileLayerService: {\n      type: String,\n      default: 'WMTS',\n      validator(val) {\n        return ['WMTS', 'TMS', 'WMS'].includes(val);\n      },\n    },\n    /**\n     * define initial zoom factor\n     */\n    zoom: {\n      type: Number,\n      default: 16,\n    },\n  },\n  data() {\n    return {\n      highlightedMarker: null,\n      highlightedLocation: null,\n      centeredMarker: null,\n    };\n  },\n  computed: {\n    // compare marker objects and remove duplicates\n    locationsFiltered() {\n      return Array.from(new Set(this.locations.map(JSON.stringify))).map(JSON.parse);\n    },\n  },\n  methods: {\n    highlightLocation(value) {\n      this.highlightedLocation = value;\n    },\n    resetMarker() {\n      this.highlightedMarker = null;\n      this.centeredMarker = null;\n    },\n  },\n};\n</script>\n\n<template>\n  <div class=\"base-map-locations\">\n    <div\n      class=\"base-map-locations__map\"\n      :style=\"additionalMapStyles\">\n      <BaseMap\n        :attribution=\"attribution\"\n        :attribution-position=\"attributionPosition\"\n        :cluster-sizes=\"clusterSizes\"\n        :copyright=\"copyright\"\n        :center-marker=\"centeredMarker\"\n        :icon=\"icon\"\n        :icon-size=\"iconSize\"\n        :highlight-marker=\"highlightedMarker\"\n        :marker=\"locationsFiltered\"\n        :marker-popups=\"markerPopups\"\n        :max-zoom=\"maxZoom\"\n        :options=\"options\"\n        :style=\"additionalMapStyles\"\n        :tile-layer-service=\"tileLayerService\"\n        :url=\"url\"\n        :zoom=\"zoom\"\n        @highlighted=\"highlightLocation\" />\n    </div>\n\n    <h2\n      v-if=\"label\"\n      class=\"base-map-locations__label\">\n      {{ label }}\n    </h2>\n\n    <div class=\"base-map-locations__list\">\n      <template\n        v-for=\"(location, index) in locationsFiltered\">\n        <!-- TODO: leaving focusin and focusout events for now even though they have no effect\n          because component is not accessible at all in general -->\n        <BaseTextList\n          v-if=\"location.latLng || location.coordinates\"\n          :key=\"index\"\n          :data=\"[location]\"\n          :class=\"['base-map-locations__list__group',\n                   { 'base-map-locations__list__group--highlight': index === highlightedLocation }]\"\n          @click=\"centeredMarker = index\"\n          @focusin=\"highlightedMarker = index\"\n          @mouseenter=\"highlightedMarker = index\"\n          @focusout=\"resetMarker\"\n          @mouseleave=\"resetMarker\" />\n      </template>\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-map-locations {\n\n    &__map {\n      margin-bottom: $spacing;\n    }\n\n    &__list {\n      display: flex;\n      flex-wrap: wrap;\n\n      &__group {\n        width: calc(33% - #{$spacing-large});\n        margin-right: $spacing-large;\n        margin-bottom: $spacing;\n\n        @media screen and (max-width: $tablet) {\n          width: calc(50% - #{$spacing});\n          margin-right: $spacing;\n          margin-bottom: $spacing;\n        }\n\n        @media screen and (max-width: $mobile) {\n          width: 100%;\n          margin-bottom: $spacing-small;\n        }\n\n        &:deep(.base-text-list__content) {\n          margin-bottom: $spacing-small;\n          transition: color 250ms ease-in-out;\n        }\n\n        &--highlight :deep(.base-text-list__content) {\n          color: $app-color !important;\n        }\n      }\n\n      :deep(.base-map-locations__list__group) {\n        &:hover {\n          cursor: pointer;\n\n          .base-text-list__content {\n            color: $app-color !important;\n          }\n        }\n      }\n    }\n  }\n</style>\n","<script>\nimport { defineAsyncComponent, ref } from 'vue';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { useWindowResize } from '@/composables/useWindowResize.js';\nimport { useId } from '@/composables/useId.js';\nimport BaseLoader from '@/components/BaseLoader/BaseLoader.vue';\n\n/**\n * Component allowing for the display of images or streaming of\n * audio and video (currently only hls format) and by using browser pdf viewer also pdfs\n */\n\nexport default {\n  name: 'BaseMediaItem',\n  components: {\n    BaseLoader,\n    BaseButton: defineAsyncComponent(() => import('@/components/BaseButton/BaseButton.vue')),\n    BaseImage: defineAsyncComponent(() => import('@/components/BaseImage/BaseImage.vue')),\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseHlsVideo: defineAsyncComponent(() => import('@/components/BaseHlsVideo/BaseHlsVideo.vue')),\n    BasePdfViewer: defineAsyncComponent(() => import('@/components/BasePdfViewer/BasePdfViewer.vue')),\n    BaseRangeSlider: defineAsyncComponent(() => import('@/components/BaseRangeSlider/BaseRangeSlider.vue')),\n  },\n  props: {\n    /**\n     * url of the medium to be displayed\n     */\n    mediaUrl: {\n      type: String,\n      default: '',\n    },\n    /**\n     * url of image for poster property in html5 video tag\n     */\n    mediaPosterUrl: {\n      type: String,\n      default: '',\n    },\n    /**\n     * filename that will be displayed for the medium\n     */\n    displayName: {\n      type: String,\n      default: '',\n    },\n    /**\n     * url for downloading the file\n     */\n    downloadUrl: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define the media type\n     *     options: 'image'|'video'|'audio'|'pdf'\n     */\n    mediaType: {\n      type: String,\n      default: '',\n      validator(val) {\n        return ['image', 'video', 'audio', 'pdf', ''].includes(val);\n      },\n    },\n    /**\n     * set height and with from outside\n     * e.g. { width: 1280px, height: 720px }\n     */\n    displaySize: {\n      type: Object,\n      default: () => ({}),\n    },\n    /**\n     * define if download button should be shown and download be enabled\n     */\n    allowDownload: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define information texts\n     * e.g. for download and view (for pdfs) buttons or error messages\n     */\n    infoTexts: {\n      type: Object,\n      default: () => ({\n        download: 'Download',\n        view: 'View',\n        error: {\n          pdf: 'The PDF couldn’t be opened in the PDF-Viewer.',\n        }\n      }),\n      validator: val => ['download', 'view', 'error'].every(prop => Object.keys(val).includes(prop))\n        && val?.error?.pdf,\n    },\n    /**\n     * define how the image should be rotated (EXIF orientation values)\n     */\n    orientation: {\n      type: Number,\n      default: 0,\n    },\n    /**\n     * specify an image srcset as an array of objects in the form\n     *     `{ [mediawidth]: 'url' }`\n     */\n    previews: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * additional info text below file name\n     */\n    additionalInfo: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * set autoplay for video\n     */\n    autoplay: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * info text to display current slide e.g. '1 / 6'\n     */\n    currentSlideInfo: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define startLevel (size) of hls-video\n     */\n    hlsStartLevel: {\n      type: Number,\n      default: undefined,\n    },\n    /**\n     * url of a preview image for the medium\n     * e.g. used for files for which no special viewer is available\n     */\n    thumbnail: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define current zoom object\n     * <b>id</b> {string} - the identifier of the current slide<br>\n     * <b>value</b> {number} - the zoom factor of the current slide in %\n     */\n    currentZoom: {\n      type: Object,\n      default: () => ({\n        id: null,\n        value: 100,\n      }),\n      // checking if all necessary properties are part of the provided object\n      validator: val => ['id', 'value'].every(prop => Object.keys(val).includes(prop)),\n    },\n    /**\n     * define the initial width (in pixels) for pdf pages\n     */\n    pdfInitialWidth: {\n      type: Number,\n      default: 1000,\n    },\n    /**\n     * defines the width (in pixels) of PDF pages in zoom mode\n     */\n    pdfZoomWidth: {\n      type: Number,\n      default: 2500,\n    },\n    /**\n     * define the max zoom factor in %\n     */\n    zoomMax: {\n      type: Number,\n      default: 250,\n    },\n  },\n  emits: ['download', 'update:swiper-zoom'],\n  setup() {\n    /** INTERNAL ID */\n    const internalId = useId();\n\n    /** INTERNATIONALIZATION */\n    const { getI18nTerm } = useI18n();\n\n    /** RESIZE / FOOTER HEIGHT CALCULATIONS */\n    /**\n     * element reference\n     * @type {Ref<UnwrapRef<HTMLElement|null>>}\n     */\n    const footer = ref(null);\n    /**\n     * variable to store calculated footer height\n     * @type {Ref<UnwrapRef<number|null>>}\n     */\n    const footerHeight = ref(null);\n\n    /**\n     * function calculating the footer height\n     */\n    function setFooterHeight() {\n      if (!footer.value) return;\n      footerHeight.value = footer.value.offsetHeight;\n    }\n\n    /**\n     * set up a resize event listener calling the footer height function\n     */\n    const { isMobile } = useWindowResize({\n      callback: setFooterHeight,\n      setDebounce: 500,\n      callOnMounted: true,\n    });\n\n    return {\n      getI18nTerm,\n      isMobile,\n      footer,\n      footerHeight,\n      internalId,\n    };\n  },\n  data() {\n    return {\n      /**\n       * variable for display image error handling\n       * @type {boolean}\n       */\n      displayImage: true,\n      /**\n       * variable to indicate the current zoom state\n       * @type {boolean}\n       */\n      isZoomActive: false,\n      /**\n       * variable to toggle zoom (BaseRangeSlider) for PDF viewer\n       * @type {boolean}\n       */\n      enableZoom: false,\n      /**\n       * define the max zoom factor in %\n       * @type {Number}\n       */\n      zoomMin: 100,\n      /**\n       * variable to store current zoom value\n       * @type {Number}\n       */\n      currentZoomInt: 100,\n      /**\n       * variable to display pdf using BasePdfViewer.\n       * if false, display the document fallback\n       * @type {boolean}\n       */\n      displayPdf: true,\n    };\n  },\n  computed: {\n    fileType() {\n      if (this.mediaType) return this.mediaType;\n      const docType = this.fileEnding;\n      // check if image\n      if (['png', 'gif', 'jpeg', 'jpg'].includes(docType.toLowerCase())) {\n        return 'image';\n      }\n      // check if video\n      if (['mp4', 'm3u8', 'ogg'].includes(docType.toLowerCase())) {\n        return 'video';\n      }\n      // check if audio\n      if (['mp3', 'wav', 'mpeg'].includes(docType.toLowerCase())) {\n        return 'audio';\n      }\n      // check if pdf\n      if (['pdf'].includes(docType.toLowerCase())) {\n        return 'pdf';\n      }\n      return '';\n    },\n    fileName() {\n      const match = this.sourceUrl.match(/([^/]+)$/);\n      return match ? decodeURI(match[1]) : '';\n    },\n    fileEnding() {\n      const match = this.sourceUrl.match(/\\w+\\.(\\w{2,4})$/);\n      return match ? match[1] : '';\n    },\n    // TODO: this property is not used?\n    formatNotSupported() {\n      return !this.fileType;\n    },\n    imageSourceSet() {\n      return this.previews.length ? this.previews.map(size => Object.keys(size)\n        .map(width => `${size[width]} ${width}`)).join(', ') : '';\n    },\n    sourceUrl() {\n      const last = this.previews.length - 1;\n      return this.previews && this.previews[last]\n        ? Object.values(this.previews[last])[0] : this.mediaUrl;\n    },\n  },\n  watch: {\n    currentZoom: {\n      handler(obj) {\n        if (obj.id !== this.internalId) return;\n        this.currentZoomInt = obj.value;\n      },\n      immediate: true,\n      deep: true,\n    },\n  },\n  methods: {\n    /**\n     * function to toggle zoom mode for BasePdfViewer\n     * @param {number} value - current zoom value\n     */\n    zoomPdf(value) {\n      this.currentZoomInt = value;\n      this.isZoomActive = this.currentZoomInt !== this.zoomMin;\n      this.$emit('update:swiper-zoom', { id: this.internalId, value: value });\n    },\n    /**\n     * function to trigger download action\n     */\n    download() {\n      // check again if user is allowed to download\n      if (this.allowDownload\n        || (!this.allowDownload && this.fileType === '')\n        || (!this.allowDownload && this.fileType === 'pdf')) {\n        /**\n         * download button clicked\n         *\n         * @event download\n         * @property {string} url - the download url\n         * @property {string} name - the file name\n         *\n         */\n        this.$emit('download', { url: this.downloadUrl || this.mediaUrl, name: this.fileName });\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    :style=\"{ '--footer-height': footerHeight + 'px' }\"\n    class=\"base-media-preview-image-stage\">\n    <!-- container 'base-media-preview-preloader' is removed by swiper after image is loaded -->\n    <!-- class is also defined in swiper setup -->\n    <div\n      v-if=\"displayImage && fileType === 'image'\"\n      class=\"base-media-preview-preloader\">\n      <BaseLoader\n        class=\"base-media-preview-preloader-loader\" />\n    </div>\n    <img\n      v-if=\"displayImage && fileType === 'image'\"\n      :src=\"sourceUrl\"\n      :srcset=\"imageSourceSet\"\n      :style=\"displaySize\"\n      :alt=\"fileName\"\n      :class=\"[\n        'base-media-preview-image',\n        'base-media-preview-rotation-' + orientation.toString(),\n      ]\"\n      loading=\"lazy\"\n      @error=\"displayImage = false\">\n    <div\n      v-else-if=\"fileType === 'image' && !displayImage\"\n      class=\"base-media-preview-not-supported base-media-preview-error\">\n      <p class=\"base-media-preview-not-supported-file-name\">\n        An error occurred displaying this image.\n      </p>\n    </div>\n    <BaseHlsVideo\n      v-else-if=\"fileType === 'video'\"\n      ref=\"baseMediaVideo\"\n      :display-size=\"displaySize\"\n      :media-url=\"mediaUrl\"\n      :media-poster-url=\"mediaPosterUrl\"\n      :autoplay=\"autoplay\"\n      :hls-start-level=\"hlsStartLevel\"\n      class=\"base-media-preview-image base-media-preview-video\" />\n    <audio\n      v-else-if=\"fileType === 'audio'\"\n      ref=\"baseMediaAudio\"\n      controls\n      class=\"base-media-preview__audio\">\n      Your browser does not support the audio tag.\n      <source\n        :src=\"mediaUrl\"\n        type=\"audio/mpeg\">\n    </audio>\n    <template\n      v-else-if=\"fileType === 'pdf' && displayPdf\">\n      <div class=\"base-media-preview__pdf__toolbar\">\n        <transition\n          name=\"fade\"\n          mode=\"out-in\">\n          <div v-if=\"enableZoom\">\n            <BaseRangeSlider\n              v-model=\"currentZoomInt\"\n              :min=\"zoomMin\"\n              :max=\"zoomMax\"\n              class=\"base-media-preview__pdf__range-slider\"\n              @update:model-value=\"zoomPdf\" />\n          </div>\n        </transition>\n      </div>\n      <div class=\"swiper-zoom-container base-media-preview__pdf__container\">\n        <BasePdfViewer\n          ref=\"pdfViewer\"\n          :src=\"mediaUrl\"\n          :initial-width=\"pdfInitialWidth\"\n          :zoom-width=\"pdfZoomWidth\"\n          :zoom=\"isZoomActive\"\n          class=\"base-media-preview__pdf swiper-zoom-target\"\n          @initialized=\"enableZoom = true\"\n          @error=\"displayPdf = false\" />\n      </div>\n    </template>\n    <div\n      v-else\n      class=\"base-media-preview-not-supported base-media-preview-error\">\n      <div class=\"base-media-preview-not-supported__container\">\n        <BaseImage\n          v-if=\"thumbnail\"\n          :src=\"thumbnail\"\n          :lazyload=\"true\"\n          class=\"base-media-preview-not-supported__thumbnail\" />\n        <div class=\"base-media-preview-not-supported__content\">\n          <p class=\"base-media-preview-not-supported-file-name\">\n            {{ fileName }}\n          </p>\n          <p\n            v-for=\"textline in additionalInfo\"\n            :key=\"textline\"\n            class=\"base-media-preview__not-supported-additional\">\n            {{ textline }}\n          </p>\n        </div>\n      </div>\n      <div\n        v-if=\"!displayPdf && infoTexts?.error?.pdf\"\n        class=\"base-media-preview-not-supported__error\">\n        <BaseIcon\n          name=\"attention\"\n          class=\"base-media-preview-not-supported__error__icon\" />\n        <div class=\"base-media-preview-not-supported__error__text\">\n          {{ infoTexts.error.pdf }}\n        </div>\n      </div>\n    </div>\n    <div\n      ref=\"footer\"\n      class=\"base-media-preview-info\">\n      <div\n        class=\"base-media-preview__info__col\n               base-media-preview__info__col1\n               base-media-preview__info-text-wrapper\">\n        <p class=\"base-media-preview-info-text\">\n          {{ displayName }}\n        </p>\n        <template v-if=\"additionalInfo.length\">\n          <p\n            v-for=\"textline in additionalInfo\"\n            :key=\"textline\"\n            class=\"base-media-preview__info-text-additional\">\n            {{ textline }}\n          </p>\n        </template>\n      </div>\n      <div\n        v-if=\"currentSlideInfo\"\n        aria-hidden=\"true\"\n        class=\"base-media-preview__info__col base-media-preview__info__col2\">\n        <p>\n          {{ currentSlideInfo }}\n        </p>\n      </div>\n      <!-- enable the file download button for PDFs and unknown filetypes -->\n      <div\n        v-if=\"(allowDownload || fileType === 'pdf' || (!allowDownload && fileType === ''))\"\n        class=\"base-media-preview__info__col base-media-preview__info__col3\">\n        <BaseButton\n          :text=\"infoTexts.download\"\n          icon=\"download\"\n          icon-position=\"right\"\n          icon-size=\"large\"\n          class=\"base-media-preview__button\"\n          @clicked=\"download\" />\n      </div>\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n  .base-media-preview-image-stage {\n    margin: auto;\n    height: 100%;\n    width: 100%;\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n    align-items: center;\n    outline: none;\n    padding: 0 $spacing-small;\n\n    .base-media-preview-image {\n      width: 100%;\n      max-height: calc(100vh - var(--footer-height) - #{$spacing});\n      max-width: 100%;\n      margin-top: auto;\n      object-fit: scale-down;\n\n      &.base-media-preview-rotation-2 {\n        transform: scaleX(-1);\n      }\n\n      &.base-media-preview-rotation-3 {\n        transform: scale(-1);\n      }\n\n      &.base-media-preview-rotation-4 {\n        transform: scaleY(-1);\n      }\n\n      &.base-media-preview-rotation-5 {\n        transform: scaleX(-1) rotate(90deg);\n      }\n\n      &.base-media-preview-rotation-6 {\n        transform: scale(-1) rotate(-90deg);\n      }\n\n      &.base-media-preview-rotation-7 {\n        transform: scaleY(-1) rotate(90deg);\n      }\n\n      &.base-media-preview-rotation-8 {\n        transform: scale(-1) rotate(90deg);\n      }\n    }\n\n    .base-media-preview-error {\n      color: whitesmoke;\n    }\n\n    .base-media-preview__audio {\n      margin-top: auto;\n    }\n\n    .base-media-preview__pdf {\n      max-height: calc(100vh - var(--footer-height) - #{$spacing-large});\n      margin-top: auto;\n\n      @media screen and (max-width: $mobile) {\n        max-height: calc(100vh - var(--footer-height) - #{$spacing});\n\n        @supports (max-height: 100dvh) {\n          max-height: calc(100dvh - var(--footer-height) - #{$spacing});\n        }\n\n      }\n    }\n\n    .base-media-preview__pdf__container {\n      display: flex;\n      flex-wrap: wrap;\n      align-content: center;\n      justify-content: center;\n      height: 100%;\n    }\n\n    .base-media-preview__pdf__toolbar {\n      position: absolute;\n      top: $spacing;\n      left: $spacing;\n      z-index: 1000;\n      align-self: flex-start;\n      min-height: $row-height-large;\n\n      @media screen and (max-width: $mobile) {\n        top: $spacing-small;\n        left: $spacing-small;\n      }\n    }\n\n    .base-media-preview__pdf__range-slider {\n      box-shadow: $box-shadow-hov;\n\n      &:hover {\n        box-shadow: $box-shadow-edit;\n      }\n    }\n\n    .base-media-preview-not-supported {\n      text-align: center;\n      min-height: 200px;\n      min-width: 500px;\n      max-width: 600px;\n      width: 40%;\n\n      color: whitesmoke;\n      margin-top: auto;\n\n      &__container {\n        display: flex;\n        flex-wrap: wrap;\n        padding: $spacing;\n        background-color: rgba(0, 0, 0, 0.3);\n      }\n\n      @media screen and (max-width: $mobile) {\n        width: 75%;\n      }\n\n      @media screen and (max-width: $tablet) {\n        width: 60%;\n        min-width: 200px;\n      }\n\n      .base-media-preview-not-supported__thumbnail {\n        display: block;\n        width: auto;\n        height: 200px;\n        margin-right: $spacing;\n\n        @media screen and (max-width: $mobile) {\n          display: none;\n        }\n      }\n\n      &__content {\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        flex: 1;\n      }\n\n      &__error {\n        flex: 1 1 100%;\n        display: flex;\n        justify-content: center;\n        align-items: center;\n        padding: $spacing-small;\n        margin-top: $spacing-small;\n        background-color: rgba(0, 0, 0, 0.3);\n\n        @media screen and (max-width: $mobile) {\n          align-items: normal;\n        }\n\n        &__icon {\n          margin-right: $spacing-small;\n          width: $icon-small;\n          height: $icon-small;\n          min-width: $icon-small;\n          min-height: $icon-small;\n\n          @media screen and (max-width: $mobile) {\n            margin-top: $spacing-small;\n          }\n        }\n\n        &__text {\n          text-align: left;\n          font-size: $font-size-small;\n          word-break: normal;\n        }\n      }\n\n      .base-media-preview-not-supported-file-name {\n        margin-bottom: $spacing;\n        padding: 0 $spacing;\n        font-weight: 600;\n        word-break: break-all;\n      }\n\n      .base-media-preview-not-supported-buttons {\n        display: flex;\n        justify-content: center;\n\n        .base-media-preview-not-supported-button {\n          margin: 0 $spacing-small $spacing;\n          min-width: 150px;\n        }\n      }\n\n      .base-media-preview__not-supported-additional {\n        font-size: $font-size-small;\n        word-break: break-all;\n      }\n    }\n\n    .base-media-preview-video {\n      width: auto;\n      max-height: calc(100vh - var(--footer-height) - #{$spacing});\n      max-width: 100%;\n      margin-top: auto;\n    }\n\n    .base-media-preview-document-wrapper {\n      height: 90%;\n      width: 90%;\n\n      .base-media-preview-document {\n        height: 100%;\n        width: 100%;\n      }\n    }\n\n    .base-media-preview-info {\n      width: calc(100% + #{$spacing});\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      background-color: rgba(0, 0, 0, 0.3);\n      color: whitesmoke;\n      padding: $spacing-small;\n      margin-top: auto;\n      margin-left: -$spacing-small;\n      margin-right: -$spacing-small;\n      line-height: normal;\n\n      .base-media-preview__info__col1,\n      .base-media-preview__info__col3 {\n        flex: 1;\n      }\n\n      .base-media-preview__info__col1 {\n        word-break: break-word;\n      }\n\n      .base-media-preview__info__col2 {\n        text-align: center;\n        font-size: $font-size-small;\n        align-self: flex-end;\n      }\n\n      .base-media-preview__info__col3 {\n        display: flex;\n        justify-content: flex-end;\n      }\n\n      .base-media-preview__info-text-wrapper {\n        margin-right: $spacing;\n\n        .base-media-preview-info-text {\n          padding-bottom: $spacing-small-half;\n          margin: 0;\n        }\n\n        .base-media-preview__info-text-additional {\n          font-size: $font-size-small;\n          margin: 0;\n        }\n      }\n    }\n\n    .base-media-preview__button {\n      color: $font-color;\n\n      &:hover {\n        color: $app-color;\n      }\n\n      &:active, &:focus {\n        fill: $app-color;\n      }\n    }\n  }\n\n  @media screen and (max-width: $mobile) {\n    .base-media-preview-not-supported,\n    .base-media-preview-not-supported-buttons {\n      flex-wrap: wrap;\n    }\n\n    .base-media-preview-image-stage,\n    .base-media-preview-not-supported,\n    .base-media-preview-not-supported-buttons {\n      .base-media-preview-not-supported-button {\n        margin: $spacing-small;\n        min-width: 125px;\n      }\n    }\n  }\n\n  .base-media-preview-preloader {\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n\n    .base-media-preview-preloader-loader {\n      top: 50%;\n      transform: translate(-50%, -75%);\n    }\n  }\n\n  .fade-enter-active,\n  .fade-leave-active {\n    transition: opacity 500ms ease;\n  }\n\n  .fade-enter-from,\n  .fade-leave-to {\n    opacity: 0;\n  }\n</style>\n","<script>\nimport BaseMediaCarouselItem from '@/components/BaseMediaCarousel/BaseMediaCarouselItem.vue';\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport { useTemplateRef } from 'vue';\nimport { usePopUpLock } from '@/composables/usePopUpLock.js';\nimport { useId } from '@/composables/useId.js';\n\n// import swiper styles\nimport 'swiper/css';\nimport 'swiper/css/navigation';\nimport 'swiper/css/pagination';\nimport 'swiper/css/keyboard';\nimport 'swiper/css/autoplay';\nimport 'swiper/css/zoom';\n\n/**\n * Component for browsing various file formats.\n * Supports images, audio, video (currently HLS only), and PDF through dedicated viewers.\n * For unknown formats, a preview image is shown when available, with an option to download the file.\n */\n\nexport default {\n  name: 'BaseMediaCarousel',\n  components: {\n    BaseMediaCarouselItem,\n    BaseIcon,\n  },\n  props: {\n    /**\n     * items to display in a swiper carousel\n     *\n     * array of objects with the following **required** properties:\n     *  **title** `string` - the asset title\n     *  **mediaUrl** `string` - url of the medium to be displayed\n     *\n     *  additionally, type `video` also requires the following properties:\n     *  **mediaPosterUrl** `string` - url of image for poster property in html5 video tag\n     *  **displaySize** `Object` - set height and with from outside, needs to be an object with properties `height` and/or `width`.\n     *\n     *  **optional** properties:\n     *  **additionalInfo** `string[]` - additional info text below file name, an array of strings.\n     *  **downloadUrl** `string` - url for downloading the file\n     *  **mediaType** `string` - specify the media type - needs to be one of: `image`, `video`, `audio`, `pdf`. **Caveat**: if media type is not specified it is automatically determined from file ending!\n     *  **orientation** `number` - define how the image should be rotated (EXIF orientation values) (only for type `image`)\n     *  **previews** `Object[]` - specify an image `srcset` as an array of objects in the form `{ [mediawidth]: 'url' }` (only for type `image`)\n     *  **hlsStartLevel** `number` - define startLevel (size) of hls-video\n     *  **thumbnail** `string` - url of a preview image, used for files for which no special viewer is available\n     *\n     */\n    items: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * index of initial slide\n     *   this NEEDS to be provided if carousel should start with any other\n     *   than first image in items array\n     */\n    initialSlide: {\n      type: [Number, String],\n      default: 0,\n    },\n    /**\n     * define if download button should be shown and download be enabled\n     */\n    allowDownload: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define information texts\n     * e.g. for download and view (for pdfs) buttons or error messages\n     */\n    infoTexts: {\n      type: Object,\n      default: () => ({\n        download: 'Download',\n        view: 'View',\n        error: {\n          pdf: 'The PDF couldn’t be opened in the PDF-Viewer.',\n        }\n      }),\n      validator: val => ['download', 'view', 'error'].every(prop => Object.keys(val).includes(prop))\n        && val?.error?.pdf,\n    },\n    /**\n     * steer the display of the lightbox\n     */\n    showPreview: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify [swiper API options](https://swiperjs.com/swiper-api)\n     */\n    swiperOptions: {\n      type: Object,\n      default: () => ({\n        speed: 500,\n        keyboard: {\n          enabled: true,\n        },\n      }),\n    },\n    /**\n     * define the initial width (in pixels) for pdf pages\n     */\n    pdfInitialWidth: {\n      type: Number,\n      default: 1000,\n    },\n    /**\n     * defines the width (in pixels) of PDF pages in zoom mode\n     */\n    pdfZoomWidth: {\n      type: Number,\n      default: 2500,\n    },\n    /**\n     * define the max zoom factor in %\n     */\n    zoomMax: {\n      type: Number,\n      default: 250,\n    },\n  },\n  emits: ['download', 'hide'],\n  setup() {\n    /** POP UP LOCK */\n    const mediaCarousel = useTemplateRef('mediaCarouselEl');\n    const { toggleScrollLock, showElement: showInt } = usePopUpLock(mediaCarousel);\n\n    /** PROVIDE A SWIPER ID */\n    const swiperId = `base-media-carousel__swiper-${useId()}`;\n\n    return {\n      toggleScrollLock,\n      showInt,\n      mediaCarousel,\n      swiperId,\n    };\n  },\n  data() {\n    return {\n      /**\n       * store the swiper instance\n       */\n      swiper: undefined,\n      /**\n       * store the current zoom factor for baseRangeSlider\n       * Note: the id is needed to address the right slide.\n       *       the id is added, when zoom is triggered\n       */\n      currentZoom: {\n        id: null,\n        value: 100,\n      },\n      /**\n       * flag if component is mounted\n       */\n      isMounted: false,\n    };\n  },\n  watch: {\n    showPreview(val) {\n      this.toggleScrollLock(val);\n    },\n  },\n  mounted() {\n    this.isMounted = true;\n  },\n  updated() {\n    this.$nextTick(() => {\n      if (this.isMounted && this.showInt && !this.swiper) {\n        this.initSwiper();\n        this.$el.addEventListener('keyup', this.escapeEvent);\n        this.$el.addEventListener('keydown', this.tabEvents);\n      }\n\n      if (!this.showInt) {\n        this.swiper = null;\n        this.$el.removeEventListener('keyup', this.escapeEvent);\n        this.$el.removeEventListener('keydown', this.tabEvents);\n      }\n    });\n  },\n  methods: {\n    /**\n     * hide preview\n     */\n    hide() {\n      /**\n       * triggered by clicking on close button\n       * @event hide\n       */\n      this.$emit('hide');\n    },\n    /**\n     * init Swiper\n     * control media after swipe\n     */\n    async initSwiper() {\n      // import swiper and plugins\n      // to avoid import/require issues in an SSR setup\n      // we import swiper when the component is already mounted\n      const { Swiper } = await import('swiper');\n      const { Keyboard } = await import('swiper/modules');\n      const { Navigation } = await import('swiper/modules');\n      const { Zoom } = await import('swiper/modules');\n\n      const additionalOptions = {\n        init: false,\n        initialSlide: this.initialSlide,\n        navigation: {\n          nextEl: '.swiper-button-next',\n          prevEl: '.swiper-button-prev',\n          addIcons: false,\n        },\n        lazyPreloaderClass: 'base-media-preview-preloader',\n        // Threshold value in px.\n        // If \"touch distance\" will be lower than this value then swiper will not move\n        threshold: 10,\n        zoom: {\n          // maximum image zoom multiplier\n          maxRatio: this.zoomMax / 100,\n          // disable zoom-in by slide's double tap\n          // Todo: find solution to prevent double click event when it happens 'on' baseRangeSlider\n          toggle: false,\n        },\n        modules: [Navigation, Keyboard, Zoom],\n      };\n\n      this.swiper = new Swiper(`#${this.swiperId}`, {\n        ...this.swiperOptions,\n        ...additionalOptions,\n      });\n\n      /**\n       * On slide change, reset the PDF zoom factor to 100% and control rendering\n       * (pause on inactive slides, resume on the active slide).\n       *\n       * A `setTimeout` is used to defer execution:\n       * without it, the pdfViewer's zoom watcher may run\n       * after `stopRendering`, unintentionally resuming rendering.\n       */\n      this.swiper.on('transitionStart', () => {\n        // reset zoom before slide changes\n        if (this.currentZoom.value !== 100) this.currentZoom.value = 100;\n\n        // pause/resume PDF rendering\n        setTimeout(() => {\n          const slides = this.$refs.baseMedia;\n          slides.forEach((slide, i) => {\n            const pdfViewer = slide.$refs.pdfViewer;\n            if (pdfViewer) {\n              if (i === this.swiper.activeIndex) {\n                pdfViewer.resumeRendering();\n              } else {\n                pdfViewer.stopRendering();\n              }\n            }\n          });\n        }, 0);\n      });\n\n      this.swiper.on('slideChange', () => {\n        this.mediaPause();\n      });\n\n      this.swiper.on('transitionEnd', () => {\n        // check if swiper is still there since this event is also called on swiper hide\n        if (this.swiper) {\n          // select active slide and set focus\n          const media = this.$refs.baseMedia[this.swiper.activeIndex];\n          media.$el.focus();\n        }\n      });\n\n      // update currentZoom\n      this.swiper.on('zoomChange', (swiper, scale) => {\n        // get the value needed here\n        this.currentZoom.value = scale * 100;\n      });\n\n      // calc of slide width is wrong on first initialization using component in ssr\n      // quickfix is to trigger resize after swiper init\n      // TODO: clarify and find better solution\n      this.swiper.on('init', () => {\n        // edge needs somehow setTimeout to trigger resize\n        setTimeout(() => {\n          window.dispatchEvent(new Event('resize'));\n        }, 0);\n      });\n\n      this.swiper.init();\n\n      // set focus to opened slide/media - otherwise esc key won't work on first slide\n      this.$refs.baseMedia[this.swiper.activeIndex].$el.focus();\n    },\n    /**\n     * pause media on previous slide\n     */\n    mediaPause() {\n      const media = this.$refs.baseMedia[this.swiper.previousIndex];\n\n      // video\n      if (media && media.$refs.baseMediaVideo) {\n        media.$refs.baseMediaVideo.pause();\n      }\n\n      // audio\n      if (media && media.$refs.baseMediaAudio) {\n        media.$refs.baseMediaAudio.pause();\n      }\n    },\n    /**\n     * intercept escape key event, hide modal\n     */\n    escapeEvent(e) {\n      if (e.key === 'Escape') {\n        this.hide();\n      }\n    },\n    /**\n     * intercept tab key event\n     * due swiper breaks using tab keys\n     */\n    tabEvents(e) {\n      if (e.shiftKey && e.key === 'Tab') {\n        e.preventDefault();\n\n        this.setFocus('prev');\n        return;\n      }\n\n      if (e.key === 'Tab') {\n        e.preventDefault();\n        this.setFocus('next');\n      }\n    },\n    /**\n     * get focusable dom elements per slide\n     *\n     * @return array\n     */\n    getFocusableItems() {\n      const focusable = 'button, audio, video[tabindex=\"0\"], input[type=\"range\"]';\n      const focusableBySlide = [];\n\n      this.$refs.baseMedia.forEach((slide) => {\n        // focusable dom elements\n        const items = Array.from(slide.$el.querySelectorAll(focusable));\n        // add current slide (is focused after slide change)\n        items.unshift(slide.$el);\n\n        focusableBySlide.push(items);\n      });\n\n      return focusableBySlide;\n    },\n    /**\n     * set focus to prev/next focusable dom element\n     * trigger slideEvent if needed\n     *\n     * @param {string} direction 'prev', 'next'\n     */\n    setFocus(direction = 'next') {\n      const items = this.getFocusableItems();\n      let currentSlide;\n      let currentFocus;\n\n      items.forEach((item, itemIndex) => {\n        item.forEach((element, elemIndex) => {\n          if (element.matches(':focus')) {\n            currentSlide = itemIndex;\n            currentFocus = elemIndex;\n          }\n        });\n      });\n\n      if (direction === 'next') {\n        if (items[currentSlide] && items[currentSlide][currentFocus + 1]) {\n          items[currentSlide][currentFocus + 1].focus();\n          return;\n        }\n        this.swiper.slideNext();\n      }\n\n      if (direction === 'prev') {\n        if (items[currentSlide] && items[currentSlide][currentFocus - 1]) {\n          items[currentSlide][currentFocus - 1].focus();\n          return;\n        }\n        this.swiper.slidePrev();\n      }\n    },\n    download(value) {\n      /**\n       * download button clicked\n       *\n       * @event download\n       * @property {string} url - the download url\n       * @property {string} name - the file name\n       *\n       */\n      this.$emit('download', value);\n    },\n    /**\n     * set a zoom factor for swiper\n     * @param {Object} obj - current zoom factor in %\n     */\n    zoomSlide(obj) {\n      this.currentZoom = obj;\n      this.swiper.zoom.in(obj.value / 100);\n    },\n  },\n};\n</script>\n\n<template>\n  <div id=\"mediaCarousel\">\n    <transition name=\"grow\">\n      <div\n        v-if=\"showInt\"\n        ref=\"mediaCarouselEl\"\n        class=\"base-media-carousel\">\n        <div class=\"base-media-carousel__background\" />\n\n        <button\n          class=\"base-media-carousel__close\"\n          @click=\"hide\">\n          <BaseIcon\n            name=\"remove\" />\n        </button>\n\n        <div\n          :id=\"swiperId\"\n          class=\"swiper-container\">\n          <template\n            v-if=\"items.length > 1\">\n            <BaseIcon\n              name=\"prev\"\n              class=\"swiper-button swiper-button-prev\" />\n\n            <BaseIcon\n              name=\"next\"\n              class=\"swiper-button swiper-button-next\" />\n          </template>\n\n          <div class=\"swiper-wrapper\">\n            <div\n              v-for=\"(media, index) in items\"\n              :key=\"index\"\n              class=\"swiper-slide\">\n              <BaseMediaCarouselItem\n                ref=\"baseMedia\"\n                :autoplay=\"index === initialSlide\"\n                :additional-info=\"media.additionalInfo\"\n                :allow-download=\"allowDownload\"\n                :current-slide-info=\"items.length > 1 ? `${index + 1} / ${items.length}` : ''\"\n                :display-name=\"media.title\"\n                :display-size=\"media.displaySize\"\n                :download-url=\"media.downloadUrl\"\n                :info-texts=\"infoTexts\"\n                :media-url=\"media.mediaUrl\"\n                :media-poster-url=\"media.mediaPosterUrl\"\n                :media-type=\"media.mediaType\"\n                :orientation=\"media.orientation\"\n                :previews=\"media.previews\"\n                :hls-start-level=\"media.hlsStartLevel\"\n                :thumbnail=\"media.thumbnail\"\n                :current-zoom=\"currentZoom\"\n                :zoom-active-width=\"pdfZoomWidth\"\n                :zoom-initial-width=\"pdfInitialWidth\"\n                :zoom-max=\"zoomMax\"\n                tabindex=\"0\"\n                @update:swiper-zoom=\"zoomSlide\"\n                @download=\"download\" />\n            </div>\n          </div>\n        </div>\n      </div>\n    </transition>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n  @use \"@/styles/variables\" as *;\n\n  .base-media-carousel {\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    z-index: map.get($zindex, modal_bg);\n    display: flex;\n    overflow: hidden;\n\n    @supports (height: 100dvh) {\n      height: 100dvh;\n    }\n\n    &__background {\n      position: absolute;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      background: $overlay-background-dark;\n    }\n\n    &__close {\n      position: absolute;\n      top: $spacing;\n      right: $spacing-large;\n      width: $icon-large;\n      height: 3rem;\n      color: white;\n      z-index: 5;\n      transition: color 250ms ease-in-out;\n      mix-blend-mode: difference;\n\n      @media screen and (max-width: $mobile) {\n        top: $spacing-small;\n        right: $spacing;\n      }\n\n      &:focus,\n      &:hover {\n        cursor: pointer;\n        color: $app-color;\n      }\n\n      svg {\n        width: 100%;\n        height: 100%;\n      }\n    }\n\n    &__slide {\n      display: flex;\n      justify-content: center;\n      align-items: center;\n    }\n\n    &:deep(.swiper-container) {\n      width: 100%;\n    }\n\n    &:deep(.swiper-button) {\n      display: block;\n      width: calc(#{$icon-large} + (2 * #{$spacing-small}));\n      padding: 0 $spacing-small;\n      fill: white;\n      transform: translateY(-50%);\n      transition: fill 250ms ease-in-out;\n    }\n  }\n\n  .grow-enter-active,\n  .grow-leave-active {\n    transition: all 300ms ease-in-out;\n  }\n\n  .grow-enter-from,\n  .grow-leave-to {\n    transform: scale(0.33);\n    opacity: 0;\n  }\n\n  .swiper-button-prev,\n  .swiper-button-next {\n    mix-blend-mode: difference;\n  }\n</style>\n","<script>\nimport { computed, defineAsyncComponent, useSlots } from 'vue';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\n// loading component synchronously due a transition is missing on the first pass\n// when select-active is set to true\nimport BaseCheckmark from '@/components/BaseCheckmark/BaseCheckmark.vue';\n\n/**\n * Component to be used in Menu Entry List or as a sort of header element\n * with possibility to specify title description and more\n */\n\nexport default {\n  name: 'BaseMenuEntry',\n  components: {\n    BaseCheckmark,\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n  },\n  props: {\n    /**\n     * An id to allow identification needs to be specified\n     */\n    entryId: {\n      type: [Number, String],\n      required: true,\n    },\n    /**\n     * item main title\n     * if prop `isSelectable` is true please always set this so\n     * the checkbox has a label\n     */\n    title: {\n      type: String,\n      default: '',\n    },\n    /**\n     * additional text displayed directly after title\n     */\n    subtext: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify if item is active - which will display a border on right side\n     * and title in bold\n     */\n    isActive: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify if item is selected - this will cause the included checkbox\n     * to be checked\n     */\n    isSelected: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify an icon that is displayed before the title.\n     * see [BaseIcon](BaseIcon) for available icons\n     */\n    icon: {\n      type: String,\n      default: '',\n    },\n    /**\n     * Text displayed at the end of the item\n     */\n    description: {\n      type: String,\n      default: '',\n    },\n    /** control if the checkboxes are visible\n     *\n     */\n    selectActive: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define if entry is selectable - thus if checkboxes are available\n     */\n    isSelectable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define if entry is disabled - thus if checkboxes are available\n     *   will overrule prop isSelectable\n     */\n    isDisabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define if entry will be active upon click\n     */\n    isActivatable: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define if title should be displayed in bold constantly\n     */\n    titleBold: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define if thumbnail overlay should be shown\n     */\n    showThumbnails: {\n      type: Boolean,\n      default: true,\n    },\n  },\n  emits: ['clicked', 'selected'],\n  setup(props) {\n    /** GENERAL */\n    const slots = useSlots();\n\n    /** ELEMENT TYPE RENDER */\n      // element should be rendered with role link and appropriate attributes unless\n      // select is active\n    const isSelectActive = computed(() => props.isSelectable && props.selectActive);\n\n    /** THUMBNAILS */\n      // check if thumbnails slot was populated\n    const { slotHasContent: thumbnailsSlotHasContent } = useHasSlotContent(slots.thumbnails);\n\n    /** TITLE FADE OUT */\n      // right-side-element slot allows for replacing all the menu entry content with custom\n      // content - so we also don't need the fade out if the slot is filled\n    const { slotHasContent: rightSideSlotHasContent } = useHasSlotContent(slots['right-side-elements']);\n\n    return {\n      isSelectActive,\n      thumbnailsSlotHasContent,\n      rightSideSlotHasContent,\n    };\n  },\n  data() {\n    return {\n      isSelectedInt: false,\n      // how many columns the thumbnail container takes\n      columns: 0,\n      // toggle transition-group transition\n      transition: false,\n    };\n  },\n  watch: {\n    isSelected(val) {\n      this.isSelectedInt = val;\n    },\n    /**\n     * watch if selectActive changes and enable the transition\n     * and disable after a certain time\n     */\n    isSelectActive() {\n      this.transition = true;\n      this.disableTransition(500);\n    },\n    /**\n     * watch if thumbnails slot content changes and enable the transition\n     * and disable after a certain time\n     */\n    thumbnailsSlotHasContent() {\n      this.transition = true;\n      this.disableTransition(500);\n    }\n  },\n  mounted() {\n    this.setThumbnailColumns();\n    this.isSelectedInt = this.isSelected;\n  },\n  updated() {\n    this.setThumbnailColumns();\n  },\n  methods: {\n    clicked() {\n      if (this.isDisabled) {\n        return;\n      }\n\n      if (this.selectActive) {\n        this.isSelectedInt = !this.isSelectedInt;\n        /**\n         * Event emitted when selectActive is true and the entry is clicked\n         *\n         * @event selected\n         * @param { Boolean } - was entry selected\n         */\n        this.$emit('selected', this.isSelectedInt);\n      } else {\n        /**\n         * Event emitted when entry is clicked and selectActive is false (=checkbox not shown)\n         *\n         * @event clicked\n         */\n        this.$emit('clicked');\n      }\n    },\n    /**\n     * disable transition after defined delay\n     * @param {Number} delay - time, in milliseconds, until method is executed\n     */\n    disableTransition(delay) {\n      // the delay should be the same as the slide-fade-move transition duration\n      setTimeout(() => this.transition = false, delay || 0);\n    },\n    slideFadeLeave() {\n      // safari fix: somehow transition needs to be triggered manually\n      this.$refs.slideFade.style.right = '1px';\n    },\n    slideFadeAfterLeave() {\n      // sometimes newly duplicated element has no html element yet so\n      // check if element exists first\n      if (this.$refs.slideFade) {\n        // safari fix: reset transition\n        this.$refs.slideFade.style.removeProperty('right');\n      }\n    },\n    /**\n     * Returns the count of columns that the thumbnail icons take.\n     */\n    setThumbnailColumns() {\n      if (this.showThumbnails && this.$refs.thumbnailContainer) {\n        // get the current count of thumbnails\n        const thumbnailCount = this.$refs.thumbnailContainer.childElementCount;\n        // find the count of columns (each column holds 2 thumbnails)\n        this.columns = Math.ceil(thumbnailCount / 2);\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <!-- since role is set conditional eslint does not recognized this -->\n  <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n  <div\n    :tabindex=\"isSelectActive ? -1 : 0\"\n    :class=\"['base-menu-entry',\n             {\n               'base-menu-entry--activatable': isActivatable && !isDisabled,\n               'base-menu-entry--active': isActive,\n               'base-menu-entry--no-icon': !icon,\n               'base-menu-entry--disabled': isDisabled,\n               'base-menu-entry--text-fade-out': !showThumbnails && !rightSideSlotHasContent,\n             }]\"\n    :role=\"!isSelectActive ? 'option' : undefined\"\n    :aria-selected=\"isActive\"\n    :aria-disabled=\"isDisabled\"\n    @keydown.enter.prevent=\"clicked\"\n    @click=\"clicked\">\n    <BaseIcon\n      v-if=\"icon\"\n      ref=\"entryIcon\"\n      :name=\"icon\"\n      class=\"base-menu-entry__icon\" />\n\n    <div\n      :class=\"[\n        'base-menu-entry__text-wrapper',\n        { 'base-menu-entry__text-slide-overlay': showThumbnails && thumbnailsSlotHasContent\n          && isSelectable },\n      ]\">\n      <!-- @slot text-content - use this slot to individualize the displayed text in the base\n        menu entry. if this slot is used, prop title, subtext and description will not have any\n        effect. -->\n      <slot\n        name=\"text-content\">\n        <div class=\"base-menu-entry__title-description-wrapper\">\n          <div class=\"base-menu-entry__title-subtext-wrapper\">\n            <div\n              v-if=\"title\"\n              :class=\"['base-menu-entry__title',\n                       { 'base-menu-entry__title--bold': isActive || titleBold }]\">\n              {{ title }}\n            </div>\n            <div\n              v-if=\"subtext\"\n              class=\"base-menu-entry__subtext\">\n              {{ subtext }}\n            </div>\n          </div>\n          <div class=\"base-menu-entry__description\">\n            {{ description }}\n          </div>\n        </div>\n      </slot>\n    </div>\n    <!-- @slot add custom elements on the right side of the entry row. This slot content will be rendered in place of thumbnails and select checkbox so it will effectively disable the display of selection elements and if select mode is desired, custom elements should be provided\n      @binding { boolean } is-selected - true if value is selected -->\n    <slot\n      name=\"right-side-elements\"\n      :is-selected=\"isSelectedInt\">\n      <TransitionGroup\n        v-if=\"isSelectable || showThumbnails\"\n        :name=\"transition ? 'slide-fade' : 'none'\"\n        tag=\"div\"\n        class=\"base-menu-entry__transition-container\"\n        @leave=\"slideFadeLeave\"\n        @after-leave=\"slideFadeAfterLeave\">\n        <div\n          v-if=\"showThumbnails\"\n          :key=\"entryId + 'thumbnail'\"\n          ref=\"slideFade\"\n          class=\"slide-fade-group base-menu-entry--text-fade-out\">\n          <div\n            ref=\"thumbnailContainer\"\n            class=\"base-menu-entry__thumbnail-container\"\n            :style=\"{ '--cols': columns }\">\n            <!-- @slot Use this slot to supply a list of [BaseIcon](BaseIcon) components that are to be shown in the right area of the menu entry as thumbnails. If using the slot make sure that `showThumbnails` is true.-->\n            <slot name=\"thumbnails\" />\n          </div>\n        </div>\n        <BaseCheckmark\n          v-if=\"isSelectable && selectActive && !isDisabled\"\n          :key=\"entryId + 'checkmark'\"\n          :model-value=\"isSelected\"\n          :label=\"title\"\n          title=\"checkbox\"\n          mark-style=\"checkbox\"\n          class=\"base-menu-entry__checkbox\"\n          @update:model-value=\"clicked\" />\n      </TransitionGroup>\n    </slot>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n  @use \"@/styles/variables\" as *;\n\n  .base-menu-entry {\n    display: flex;\n    align-items: center;\n    height: $row-height-large;\n    width: 100%;\n    position: relative;\n    background: white;\n    overflow: hidden;\n\n    &:focus {\n      .base-menu-entry__icon,\n      .base-menu-entry__title,\n      .base-menu-entry__subtext,\n      .base-menu-entry__text-wrapper .base-menu-entry__title-description-wrapper .base-menu-entry__description {\n        fill: $app-color;\n        color: $app-color;\n      }\n    }\n\n    &.base-menu-entry--no-icon {\n      padding-left: $spacing;\n    }\n\n    &.base-menu-entry--text-fade-out {\n      &::before {\n        left: inherit;\n        right: $spacing;\n      }\n    }\n\n    &.base-menu-entry--disabled {\n      .base-menu-entry__icon {\n        color: $graytext-color;\n      }\n      .base-menu-entry__text-wrapper {\n        .base-menu-entry__title,\n        .base-menu-entry__subtext,\n        .base-menu-entry__title-description-wrapper .base-menu-entry__description {\n          color: $graytext-color;\n        }\n      }\n\n      .base-menu-entry__thumbnail-container {\n        color: $graytext-color;\n      }\n    }\n\n    &.base-menu-entry--activatable {\n      cursor: pointer;\n      transition: box-shadow 0.2s ease;\n\n      &.base-menu-entry--active {\n        box-shadow: inset $border-active-width 0 0 0 $app-color;\n      }\n\n      &:hover {\n        .base-menu-entry__icon,\n        .base-menu-entry__title,\n        .base-menu-entry__subtext,\n        .base-menu-entry__text-wrapper .base-menu-entry__title-description-wrapper .base-menu-entry__description {\n          fill: $app-color;\n          color: $app-color;\n        }\n      }\n    }\n\n    // this class name is used in BaseMenuList for setting the drag image!!\n    .base-menu-entry__icon {\n      height: $icon-large;\n      max-height: $icon-large;\n      width: $icon-large;\n      margin: 0 $spacing;\n      flex: 0 0 #{$icon-large};\n      transition: fill 0.1s ease;\n    }\n\n    .base-menu-entry__text-wrapper {\n      flex-grow: 1;\n      flex-shrink: 1;\n      display: flex;\n      align-items: baseline;\n      max-width: calc(100% - #{$icon-large} - (2 * #{$spacing}) - #{$border-width}\n      - 2 * #{$spacing-small} + 2 * #{$spacing});\n      position: relative;\n      overflow: hidden;\n      margin-right: $spacing;\n\n      &.base-menu-entry__text-slide-overlay::after {\n        content: '';\n        width: calc(#{$icon-medium} +  (2 * #{$spacing}));\n        height: 100%;\n        position: absolute;\n        top: 0;\n        right: -$spacing;\n        background-color: white;\n      }\n\n      .base-menu-entry__title-description-wrapper {\n        flex-shrink: 1;\n        flex-grow: 1;\n\n        .base-menu-entry__title-subtext-wrapper {\n          display: flex;\n          align-items: baseline;\n\n          .base-menu-entry__title {\n            margin-right: $spacing;\n\n            &.base-menu-entry__title--bold {\n              font-weight: bold;\n            }\n          }\n        }\n\n        .base-menu-entry__description {\n          color: $font-color-second;\n          font-size: $font-size-small;\n          white-space: nowrap;\n          transition: color 0.1s ease;\n        }\n      }\n    }\n\n    .base-menu-entry__title + .base-menu-entry__subtext {\n      margin-left: 0;\n    }\n\n    .base-menu-entry__subtext, .base-menu-entry__title {\n      position: relative;\n      white-space: nowrap;\n      overflow: hidden;\n      transition: color 0.1s ease;\n    }\n\n    .base-menu-entry__subtext {\n      color: $font-color-second;\n      font-size: $font-size-small;\n      margin-right: $spacing;\n      flex-grow: 99;\n      flex-shrink: 0;\n      padding-right: $spacing;\n    }\n\n    .base-menu-entry__transition-container {\n      position: absolute;\n      right: 0;\n      margin-right: $spacing;\n      height: 100%;\n      display: flex;\n      align-items: center;\n    }\n\n    .base-menu-entry__thumbnail-container {\n      position: relative;\n      z-index: 2;\n      display: flex;\n      flex-direction: column;\n      flex-wrap: wrap-reverse;\n      height: $row-height-large;\n      justify-content: center;\n      align-items: flex-start;\n      padding-left: $spacing;\n      gap: $spacing;\n      background-color: $box-color;\n      // calculate container width as sum of thumbnail columns and column gaps,\n      // plus an extra $spacing to account for the padding-left applied above.\n      // the count of columns is calculated in the setThumbnailColumns() method.\n      width: calc(var(--cols) * #{$icon-small} + (var(--cols) - 1) * #{$spacing} + #{$spacing});\n    }\n\n    .base-menu-entry__checkbox {\n      background: $box-color;\n      height: 100%;\n      padding-left: $spacing;\n      z-index: 1;\n      -webkit-backface-visibility: hidden;\n      -webkit-transform: translateZ(0) scale(1, 1);\n    }\n\n    .slide-fade-group {\n      display: flex;\n      align-items: center;\n      height: 100%;\n      position: relative;\n      z-index: 101;\n      -webkit-backface-visibility: hidden;\n      -webkit-transform: translateZ(0) scale(1, 1);\n    }\n\n    .slide-fade-enter-active,\n    .slide-fade-move,\n    .slide-fade-leave-active {\n      transition: opacity 0.5s ease, transform 0.5s ease-in-out;\n    }\n\n    .slide-fade-enter-from,\n    .slide-fade-leave-to {\n      opacity: 0;\n    }\n\n    .slide-fade-enter-from {\n      // transition looks more natural with larger value\n      // when entering from the right side\n      transform: translateX($spacing + $spacing-small);\n    }\n\n    .slide-fade-leave-to {\n      transform: translateX(#{$spacing});\n    }\n\n    .slide-fade-leave-active {\n      position: absolute;\n      right: -$spacing;\n    }\n  }\n\n.base-menu-entry--text-fade-out {\n  &::before {\n    content: '';\n    width: calc(#{$fade-out-width} + #{$spacing});\n    height: $row-height-large;\n    position: absolute;\n    top: 0;\n    left: calc(-#{$fade-out-width} - #{$spacing});\n    background: linear-gradient(to right, rgba(255, 255, 255, 0) , white);\n    z-index: map.get($zindex, fadeout);\n  }\n}\n</style>\n","<script>\nimport BaseMenuEntry from '@/components/BaseMenuEntry/BaseMenuEntry.vue';\nimport { defineAsyncComponent, ref } from 'vue';\nimport { useWindowResize } from '@/composables/useWindowResize.js';\n\n/**\n * Base Component for SideBar Menu Entries\n *   (this component is currently not ssr-capable)\n */\n\nexport default {\n  name: 'BaseMenuList',\n  components: {\n    BaseMenuEntry,\n  },\n  props: {\n    /**\n     * define if entries are selectable -> d.h. the selectboxes are showing\n     */\n    selectActive: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * list of menu entries - array of objects\n     *  v-model:list may be used on this prop\n     *   Entry properties that can be displayed:\n     *\n     *     *required*:\n     *      **id** `string` - give every item an unique id\n     *\n     *     *optional*:\n     *      **title** `string` - main text line in the list item\n     *      **description** `string` - second text line in the list item\n     *      **active** `boolean` - steer from outside if item should be displayed active (with left\n     *        side color border)\n     *      **selected** `boolean` - steer from outside if entry select box should be checked\n     *      **disabled** `boolean` - steer from outside if entry select box should be disabled\n     *      **icon** `string` - a valid [BaseIcon](BaseIcon) icon name\n     *\n     *      Also see [BaseMenuEntry](BaseMenuEntry) component for more information on\n     *        the mentioned properties.\n     */\n    list: {\n      type: Array,\n      default: () => [],\n      validator: val => val.every(item => Object.keys(item).includes('id')),\n    },\n    /**\n     * index of the entry that should currently be active\n     * TODO: check if it would be better to use id here!\n     */\n    activeEntry: {\n      type: Number,\n      default: -1,\n    },\n    /**\n     * provide a list of entries that should appear selected\n     */\n    selectedList: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * make the single menu list items draggable\n     */\n    useDraggable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify the group name for the drag receiver\n     * **important**: if you intend to use the drag functionality set `useDraggable`\n     * to `true`\n     */\n    dragName: {\n      type: String,\n      default: 'menuEntry',\n    },\n  },\n  emits: ['selected', 'clicked', 'update:list'],\n  setup() {\n    /**\n     * defines if menu list entries are draggable\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const isDraggable = ref(false);\n    /** listen to window resize and set draggable state depending on window width */\n    useWindowResize({\n      callback: () => isDraggable.value = !(window.innerWidth < 640),\n      setDebounce: 250,\n      callOnMounted: true,\n    });\n\n    return {\n      isDraggable,\n    };\n  },\n  data() {\n    return {\n      // have internally necessary props in separate array to prevent issues with\n      // outside store mutations\n      entryProps: [],\n      /**\n       * variable to determine which properties should be stored in variable\n       * `entryProps`\n       * @type {string[]}\n       */\n      entryPropsKeys: ['selected', 'active', 'error'],\n      dragging: false,\n      dragAndDropCapable: false,\n      /**\n       * chrome can not deal with delay if drag image is cloned from dom on setData directly\n       * so image needs to be set previously and stored in variable\n       * @type {?SVGElement}\n       */\n      dragImg: null,\n      /**\n       * internal list representation needed for drag manipulations\n       * @type {Object[]}\n       */\n      listInt: [],\n    };\n  },\n  computed: {\n    /**\n     * make the vue-draggable import optional and either return\n     * the component or use the native `<ul>` element\n     * @returns {Object|string}\n     */\n    draggableComponent() {\n      if (this.useDraggable) {\n        return defineAsyncComponent(() => import('vue-draggable-plus').then(m => m.VueDraggable));\n      }\n      return 'ul';\n    },\n    /**\n     * to only set model-value attribute if it is a vue-draggable\n     * component\n     * @returns {undefined|Object[]}\n     */\n    draggableList() {\n      if (this.useDraggable) return this.listInt;\n      return undefined;\n    }\n  },\n  watch: {\n    /**\n     * watch prop `list` for changes from outside\n     */\n    list: {\n      handler(val) {\n        // check if the provided list differs from the internal copy\n        if (JSON.stringify(val) !== JSON.stringify(this.listInt)) {\n          // if yes - update the internal copy\n          this.listInt = JSON.parse(JSON.stringify(val));\n          // and set `entryProps` variable accordingly managing\n          // state for every single entry\n          this.setInternalVar();\n        }\n      },\n      deep: true,\n      immediate: true,\n    },\n    /**\n     * watch internal representation of `list` to be able to\n     * update parent accordingly\n     */\n    listInt: {\n      handler(val) {\n        // check if internal list and external list differ\n        if (JSON.stringify(val) !== JSON.stringify(this.list)) {\n          // if yes - inform the parent\n          this.$emit('update:list', JSON.parse(JSON.stringify(this.listInt)));\n        }\n      },\n      deep: true,\n      immediate: true,\n    },\n    activeEntry(val) {\n      this.entryProps.forEach((item) => {\n        // eslint-disable-next-line no-param-reassign\n        item.active = false;\n      });\n      if (val >= 0 && this.entryProps[val]) {\n        this.entryProps[val].active = true;\n      }\n    },\n    selectActive(val) {\n      if (!val) {\n        this.entryProps.forEach((entry) => {\n          // eslint-disable-next-line no-param-reassign\n          entry.selected = false;\n        });\n      } else {\n        this.setInternalVar();\n      }\n    },\n    selectedList: {\n      handler() {\n        this.setInternalVar();\n      },\n      deep: true,\n    },\n    /**\n     * watch variable `entryProps` - managing the state for every entry - to\n     * update the internal list IF the state prop is also present\n     * in the entry list provided by parent\n     */\n    entryProps: {\n      handler() {\n        // if entryProps changed update the internal list\n        this.listInt = this.listInt.map((entry, index) => {\n          // get all the object properties of the entry\n          const entryKeys = Object.keys(entry);\n          // now loop through internal state keys\n          return this.entryPropsKeys.reduce((prev, entryPropsKey) => {\n            // if key is also present in list - update the list property\n            if (entryKeys.includes(entryPropsKey)) {\n              return {\n                ...prev,\n                [entryPropsKey]: this.entryProps[index][entryPropsKey]\n              }\n            }\n            // otherwise just return the unaltered object\n            return prev;\n          }, {\n            // as a start use the entry as it currently is in listInt\n            ...entry,\n          });\n        });\n      },\n      deep: true,\n      immediate: true,\n    }\n  },\n  mounted() {\n    this.dragAndDropCapable = ('DragEvent' in window);\n  },\n  methods: {\n    // this function is called when a menu entry is clicked (when checkboxes not active)\n    activateItem(index) {\n      /**\n       * event emitted when a menu entry is clicked\n       *\n       * @event clicked\n       * @param { String } - the index of the respective entry\n       */\n      this.$emit('clicked', index);\n    },\n    selectItem(index, selected) {\n      this.entryProps[index].selected = selected;\n      /**\n       * event emitted when entry is clicked and select is active\n       *\n       * @event selected\n       * @type { Object }\n       * @property {string} index - the index of the selected item\n       * @property {boolean} selected - was items selected\n       */\n      this.$emit('selected', { index, selected });\n    },\n    setInternalVar() {\n      this.entryProps = this.listInt.map(entry => {\n        return ({\n          selected: entry.selected || this.selectedList.includes(entry.id),\n          active: entry.active || false,\n          error: entry.error || false,\n        });\n      });\n      if (this.entryProps.length && this.activeEntry >= 0) {\n        this.entryProps[this.activeEntry].active = true;\n      }\n    },\n    /**\n     * get the relevant icon image from the dom and save it in a variable\n     * (Chrome could not deal with setting it in modifyDragItem directly)\n     * @param {CustomEvent} event\n     */\n    getDragImage(event) {\n      // get the relevant svg element from the base menu entry by class name\n      // (necessary to use class name so thumbnail sgvs are not used if no icon is provided in list)\n      const entryIcon = event.item.getElementsByClassName('base-menu-entry__icon')[0];\n      // check if icon was set\n      if (entryIcon) {\n        // get the size to be able to set it to the drag image as well\n        const size = `${(entryIcon.clientHeight * 2)}px`;\n\n        // clone the svg used in this entry\n        const pic = entryIcon.cloneNode(true);\n        pic.id = 'drag-icon';\n        pic.style.height = size;\n        pic.style.maxHeight = size;\n        pic.style.width = size;\n        pic.style.backgroundColor = 'white';\n        pic.style.position = 'absolute';\n        pic.style.top = '-99999px';\n        pic.style.left = '-99999px';\n        // store it in the variable\n        this.dragImg = pic;\n      } else {\n        this.dragImg = null;\n      }\n    },\n    dragStart() {\n      this.dragging = true;\n    },\n    dragEnd() {\n      this.dragging = false;\n      // remove drag item from the body again if necessary after drag ended\n      const elem = document.getElementById('drag-icon');\n      if (elem) {\n        elem.parentNode.removeChild(elem);\n      }\n    },\n    modifyDragItem(dataTransfer) {\n      // check if drag image was set (not the case if no icon was provided in list items)\n      if (this.dragImg) {\n        // add the element retrieved in choose event (getDragImage()) to the dom\n        document.body.appendChild(this.dragImg);\n        // Edge does not support setDragImage\n        if (typeof DataTransfer.prototype.setDragImage === 'function') {\n          dataTransfer.setDragImage(this.dragImg, 0, 0);\n        }\n      }\n      dataTransfer.setData('draggable', '');\n    },\n  },\n};\n</script>\n\n<template>\n  <component\n    :is=\"draggableComponent\"\n    ref=\"draggable\"\n    :model-value=\"draggableList\"\n    :sort=\"useDraggable ? false : undefined\"\n    :disabled=\"useDraggable ? !isDraggable || selectActive : undefined\"\n    :group=\"useDraggable ? { name: dragName, pull: 'clone', put: false } : undefined\"\n    :set-data=\"modifyDragItem\"\n    :tag=\"useDraggable ? 'ul' : undefined\"\n    class=\"base-menu-list\"\n    @choose=\"getDragImage\"\n    @start=\"dragStart\"\n    @end=\"dragEnd\">\n    <li\n      v-for=\"(item, index) in listInt\"\n      :key=\"item.id || item.title\"\n      class=\"base-menu-list__list-entry\">\n      <BaseMenuEntry\n        ref=\"menuEntry\"\n        :entry-id=\"item.id\"\n        :title=\"item.title\"\n        :is-active=\"entryProps[index].active\"\n        :is-selected=\"entryProps[index].selected\"\n        :is-disabled=\"item.disabled\"\n        :icon=\"item.icon\"\n        :description=\"item.description\"\n        :is-selectable=\"true\"\n        :select-active=\"selectActive\"\n        @clicked=\"activateItem(index)\"\n        @selected=\"selectItem(index, $event)\">\n        <template #text-content>\n          <!-- @slot use this slot to individualize the displayed text per\n            menu entry.\n            @binding { Object } item - the complete entry provided by list -->\n          <slot\n            name=\"entry-text-content\"\n            :item=\"item\" />\n        </template>\n        <template #right-side-elements=\"{ isSelected }\">\n          <!-- @slot use this slot to add elements to the right side of an entry. This slot content\n            will be rendered in place of thumbnails and select checkbox so it will effectively\n            disable the display of selection elements and if select mode is desired, custom elements\n            should be provided\n             @binding { Object } item - the complete entry provided by list\n             @binding { boolean } is-selected - was item selected -->\n          <slot\n            name=\"entry-right-side-elements\"\n            :is-selected=\"isSelected\"\n            :item=\"item\" />\n        </template>\n        <template\n          #thumbnails>\n          <!-- @slot Use this scoped slot to supply a list of thumbnails (i.e. [BaseIcon](BaseIcon)) for `item`, where `item` is one list element. See also the example below.-->\n          <slot\n            name=\"thumbnails\"\n            :item=\"item\" />\n        </template>\n      </BaseMenuEntry>\n    </li>\n  </component>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-menu-list {\n    position: relative;\n\n    .base-menu-list__list-entry {\n      &:not(:last-of-type) {\n        border-bottom: $separation-line;\n      }\n    }\n  }\n</style>\n","<script>\nimport { defineAsyncComponent, toRef, useTemplateRef, computed } from 'vue';\nimport BaseInput from '@/components/BaseInput/BaseInput.vue';\nimport { useId } from '@/composables/useId.js';\nimport { useExtractAttrs } from '@/composables/useExtractAttrs.js';\nimport { useElementFadeOut } from '@/composables/useElementFadeOut.js';\n\n/**\n * A multiline textfield base component\n */\n\nexport default {\n  name: 'BaseMultilineTextInput',\n  components: {\n    BaseInput,\n    BaseIcon: defineAsyncComponent(() => import('@/components/BaseIcon/BaseIcon.vue')),\n    BaseSwitchButton: defineAsyncComponent(() => import('@/components/BaseSwitchButton/BaseSwitchButton.vue')),\n  },\n  inheritAttrs: false,\n  props: {\n    /**\n     * input displayed in the textarea.\n     *   if `tabs` prop is set, this needs to be an object with properties corresponding to\n     *   tab names.\n     */\n    modelValue: {\n      type: [Object, String],\n      default: '',\n    },\n    /**\n     * set the label for the input component\n     */\n    label: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set `true` if label should be visible\n     */\n    showLabel: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * set input field placeholder\n     */\n    placeholder: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set tabs for the input field\n     */\n    tabs: {\n      type: Array,\n      default: () => ['default'],\n    },\n    /**\n     * give the possibility to specify what should be displayed in the tabs\n     */\n    tabLabels: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * set the currently active tab (specify the property of the object not the label)\n     */\n    activeTab: {\n      type: String,\n      default: '',\n    },\n    /**\n     * set a legend for the tabs to be read (for accessibility only, hidden)\n     */\n    tabsLegend: {\n      type: String,\n      default: 'Radiogroup',\n    },\n    /**\n     * set id which is used for label + id\n     */\n    inputId: {\n      type: [String, Number],\n      default: '',\n    },\n    /**\n     * set a language (ISO 639-1)\n     */\n    language: {\n      type: String,\n      default: '',\n    },\n    /**\n     * mark as required field (currently only used for `aria-required`)\n     */\n    required: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * mark the form field as invalid and ideally also provide an error message\n     * to display below the form field.\n     * for an example see [BaseInput](BaseInput)\n     */\n    invalid: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set true if input field should be disabled.\n     * for an example see [BaseInput](BaseInput)\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * add an error message to be displayed below form field if field is invalid.\n     * for an example see [BaseInput](BaseInput)\n     */\n    errorMessage: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define if error icon should be shown.\n     * for an example see [BaseInput](BaseInput)\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * if true a remove icon will be shown allowing to remove\n     * all input at once.\n     * for an example see [BaseInput](BaseInput)\n     */\n    clearable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * provide assistive text for screen readers\n     * **clearInput**: text read for remove input icon if prop `clearable` is set `true`\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        clearInput: 'Clear input',\n      }),\n    },\n  },\n  emits: ['update:model-value'],\n  setup(props) {\n    /** INTERNAL ID */\n    /**\n     * create a permanent id (also suitable for ssr)\n     * @type {Ref<UnwrapRef<string>> | Ref<UnwrapRef<number>>}\n     */\n    const idInt = toRef(props.inputId);\n    // check if one was provided by prop or create one\n    if (!idInt.value) {\n      idInt.value = useId();\n    }\n\n    /** ATTRS HANDLING */\n    // split up the $attrs to leave class style and data-base-id at root level\n    const { rootAttrs, forwardAttrs } = useExtractAttrs();\n\n    /** INPUT ELEMENT */\n    /**\n     * get the reference to the BaseInput component\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const baseInput = useTemplateRef('baseInputEl');\n    /**\n     * get the native input element from BaseInput\n     * @type {ComputedRef<HTMLElement>}\n     */\n    const inputElement = computed(() => baseInput.value?.inputElement || null);\n\n    /** FADE OUT HANDLING */\n    /**\n     * variable to store a reference the textarea element\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const textarea = useTemplateRef('textareaEl');\n    const { boxFadeOut } = useElementFadeOut(textarea, {\n      // TODO: refactor to use build in classes and pseudo elements\n      className: '',\n    });\n\n    return {\n      idInt,\n      rootAttrs,\n      forwardAttrs,\n      textarea,\n      inputElement,\n      boxFadeOut,\n    };\n  },\n  data() {\n    return {\n      activeTabInt: this.tabs[0],\n      fieldContent: {},\n      isActive: false,\n    };\n  },\n  computed: {\n    /**\n     * map the switch options to the format required by BaseSwitchButton (an object with label\n     * value and (optionally) icon)\n     * @returns {{value: string, label: string}[]}\n     */\n    switchTabs() {\n      return this.tabs.map((tab, index) => ({ value: tab, label: this.tabLabels[index] || tab }));\n    },\n    /**\n     * calc if fade out should be visible which is if textarea height is overflown (calculated in\n     * composable) AND only if the input is not active\n     * @returns {boolean}\n     */\n    showFadeOut() {\n      return !this.isActive && (this.boxFadeOut.top || this.boxFadeOut.bottom);\n    },\n  },\n  watch: {\n    // watch for input changes from outside\n    modelValue: {\n      handler(val) {\n        if ((typeof val === 'object' && JSON.stringify(val) !== JSON.stringify(this.fieldContent))\n          || (typeof val === 'string' && val !== this.fieldContent[this.activeTabInt])) {\n          // if input changes set internal fieldContent variable\n          this.setFieldContent(val);\n        }\n      },\n      immediate: true,\n      deep: true,\n    },\n    // get updates for active tab from outside\n    activeTab: {\n      handler(val) {\n        this.activeTabInt = val || this.tabs[0] || 'default';\n      },\n      immediate: true,\n    },\n  },\n  methods: {\n    /**\n     * forward the input\n     */\n    onInput() {\n      /**\n       * Event emitted on input, passing input string or input object\n       *\n       * @event update:model-value\n       * @param {string, Object} - the altered field input\n       */\n      this.$emit('update:model-value', this.emitFieldContent());\n    },\n    setFieldContent(val) {\n      if (this.tabs.length < 2) {\n        const propName = this.activeTabInt || 'default';\n        this.fieldContent[propName] = typeof val === 'string' ? val : val[propName];\n      } else {\n        this.tabs.forEach((tab) => {\n          this.fieldContent[tab] = val[tab];\n        });\n      }\n    },\n    emitFieldContent() {\n      if (typeof this.modelValue === 'object') {\n        return this.fieldContent;\n      }\n      return this.fieldContent[this.activeTabInt];\n    },\n    hasText(val) {\n      return !!this.fieldContent[val];\n    },\n  },\n};\n</script>\n\n<template>\n  <BaseInput\n    ref=\"baseInputEl\"\n    v-model=\"fieldContent[activeTabInt]\"\n    v-model:is-active=\"isActive\"\n    v-bind=\"rootAttrs\"\n    :input-id=\"idInt\"\n    :label=\"label\"\n    :show-label=\"showLabel\"\n    :placeholder=\"placeholder\"\n    :required=\"required\"\n    :invalid=\"invalid\"\n    :disabled=\"disabled\"\n    :show-error-icon=\"showErrorIcon\"\n    :error-message=\"errorMessage\"\n    :clearable=\"clearable\"\n    :assistive-text=\"assistiveText\"\n    :use-fade-out=\"false\"\n    class=\"base-multiline-text-input\">\n    <template #label-addition>\n      <div class=\"base-multiline-text-input__additions\">\n        <!-- @slot to add drop down needed for text input field (base specific) or any other element deemed necessary -->\n        <slot name=\"label-addition\" />\n        <BaseSwitchButton\n          v-if=\"tabs && tabs[0] !== 'default'\"\n          v-model=\"activeTabInt\"\n          :options=\"switchTabs\"\n          :label=\"tabsLegend\"\n          class=\"base-multiline-text-input__tabs\">\n          <template\n            #right-of-content=\"tab\">\n            <BaseIcon\n              v-if=\"hasText(tab.value)\"\n              class=\"base-multiline-text-input__text-icon\"\n              name=\"text\" />\n          </template>\n        </BaseSwitchButton>\n      </div>\n    </template>\n    <template #input>\n      <div\n        :class=\"['base-multiline-text-input__textarea-wrapper',\n                 { 'base-multiline-text-input__textarea-wrapper__fade-out': showFadeOut },\n                 { 'base-multiline-text-input__textarea-wrapper__fade-out--top': boxFadeOut.top },\n                 { 'base-multiline-text-input__textarea-wrapper__fade-out--bottom': boxFadeOut.bottom }]\">\n        <!-- need to disable because label is there - it is just in BaseInput component -->\n        <!-- eslint-disable-next-line  vuejs-accessibility/form-control-has-label -->\n        <textarea\n          :id=\"idInt\"\n          ref=\"textareaEl\"\n          v-model=\"fieldContent[activeTabInt]\"\n          v-bind=\"forwardAttrs\"\n          :required=\"required\"\n          :aria-required=\"required\"\n          :aria-describedby=\"idInt\"\n          :aria-invalid=\"invalid\"\n          :disabled=\"disabled\"\n          :aria-disabled=\"disabled\"\n          :placeholder=\"placeholder\"\n          class=\"base-multiline-text-input__textarea\"\n          @keydown.tab=\"isActive = false\"\n          @input=\"onInput\" />\n      </div>\n    </template>\n    <template\n      #input-field-addition-before>\n      <!-- @slot Slot to allow for additional elements in the input field <div> (before <input>) -->\n      <slot name=\"input-field-addition-before\" />\n    </template>\n    <template #input-field-addition-after>\n      <!-- @slot for adding elements after input -->\n      <slot name=\"input-field-addition-after\" />\n    </template>\n    <template #post-input-field>\n      <!-- @slot elements after the actual input element but within the input field container. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n      <slot name=\"post-input-field\" />\n    </template>\n    <template #error-icon>\n      <!-- @slot use a custom icon instead of standard error/warning icon. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n      <slot name=\"error-icon\" />\n    </template>\n    <template #remove-icon>\n      <!-- @slot use a custom icon instead of standard remove icon. for an example see [BaseChipsInputField](BaseChipsInputField)-->\n      <slot name=\"remove-icon\" />\n    </template>\n  </BaseInput>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n@use \"@/styles/variables\" as *;\n\n.base-multiline-text-input {\n  font-family: inherit;\n  font-size: inherit;\n\n  .base-multiline-text-input__additions {\n    display: flex;\n    flex-wrap: wrap;\n    align-items: center;\n    justify-content: flex-end;\n    margin-bottom: -$spacing-small-half;\n\n    .base-multiline-text-input__tabs {\n      align-self: center;\n      flex-shrink: 0;\n\n      .base-multiline-text-input__text-icon {\n        height: 10px;\n        width: 10px;\n        color: $font-color-second;\n        fill: $font-color-second;\n      }\n    }\n  }\n\n  .base-multiline-text-input__textarea-wrapper {\n    width: 100%;\n\n    &.base-multiline-text-input__textarea-wrapper__fade-out::after,\n    &.base-multiline-text-input__textarea-wrapper__fade-out::before {\n      content: '';\n      width: 100%;\n      height: $fade-out-width;\n      position: absolute;\n      pointer-events: none;\n      z-index: map.get($zindex, fadeout);\n    }\n\n    &.base-multiline-text-input__textarea-wrapper__fade-out--bottom::after {\n      bottom: 1px;\n      left: 0;\n      background: linear-gradient(to bottom, rgba(255, 255, 255, 0) , white);\n    }\n\n    &.base-multiline-text-input__textarea-wrapper__fade-out--top::before {\n      top: 1px;\n      left: 0;\n      background: linear-gradient(to top, rgba(255, 255, 255, 0) , white);\n    }\n\n    .base-multiline-text-input__textarea {\n      width: 100%;\n      line-height: $line-height;\n      padding: $spacing-small-half 0;\n      margin: 0;\n      height: 240px;\n      appearance: none;\n      resize: none;\n      -ms-overflow-style: none;  /* Internet Explorer 10+ */\n      scrollbar-width: none;  /* Firefox */\n\n      &::-webkit-scrollbar {\n        display: none;  /* Safari and Chrome */\n      }\n    }\n  }\n}\n\n@media screen and (max-width: $tablet) {\n  .base-multiline-text-input {\n    .base-multiline-text-input__additions {\n      justify-content: flex-end;\n    }\n  }\n}\n\n@media screen and (max-width: $mobile) {\n  .base-multiline-text-input\n  .base-multiline-text-input__additions {\n    margin-bottom: -$spacing-small;\n  }\n}\n\n</style>\n","<script setup>\nimport BaseLink from '@/components/BaseLink/BaseLink.vue';\nimport { computed, defineAsyncComponent, nextTick, ref, getCurrentInstance, onMounted, useTemplateRef, watch } from 'vue';\nimport { useWindowResize } from '@/composables/useWindowResize.js';\n\n/**\n * navigation bar component tabs (internal or external links)\n */\n\ndefineOptions({\n  name: 'BaseNavigation',\n});\n\nconst BaseButton = defineAsyncComponent(() => import('@/components/BaseButton/BaseButton.vue'));\n\nconst props = defineProps({\n  /**\n   * list of primary navigation items, with the following properties:\n   *\n   *    **id** `string` - a unique id\n   *    **label** `string` - a label for the route to be displayed\n   *    **shortLabel** `string?` - a shorter version of the label to be shown if the regular label does not\n   *      fit the element anymore\n   *    **route** `string?` - the route of the element should navigate to\n   *    **url** `string?` - the external url to navigate to on element click\n   *    **routeMatch** `RegEx?` - provide a regular expression that will be used to determine\n   *      the currently active element\n   *\n   *  caveat: the object requires either the `route` or the `url` property!\n   *\n   * on a desktop screen, these elements will be rendered on the left-hand side of the navigation\n   * on a mobile screen, these elements will be rendered in the upper half of the dropdown list\n   */\n  primaryItems: {\n    type: Array,\n    default: () => [\n      {\n        id: '1',\n        label: 'Label',\n        shortLabel: '',\n        route: '/',\n      },\n    ],\n    validator: arr => arr.every(entry => !['id', 'label']\n      .some(property => !Object.keys(entry).includes(property)) && (entry.route || entry.url)),\n  },\n  /**\n   * list of secondary navigation items, with the following properties:\n   *\n   *    **id** `string` - a unique id\n   *    **label** `string` - a label for the route to be displayed\n   *    **shortLabel** `?string` - a shorter version of the label to be shown if the regular label does not\n   *      fit the element anymore\n   *   **route** `string?` - the route of the element should navigate to\n   *    **url** `string?` - the external url to navigate to on element click\n   *    **routeMatch** `RegEx?` - provide a regular expression that will be used to determine\n   *      the currently active element\n   *\n   *  caveat: the object requires either the `route` or the `url` property!\n   *\n   * on a desktop screen, these elements will be rendered on the right-hand side of the navigation\n   * on a mobile screen, these elements will be rendered in the lower half of the dropdown list\n   */\n  secondaryItems: {\n    type: Array,\n    default: () => [\n      {\n        id: '1',\n        label: 'Label',\n        shortLabel: '',\n        route: '/',\n      },\n    ],\n    validator: arr => arr.every(entry => !['id', 'label']\n      .some(property => !Object.keys(entry).includes(property)) && (entry.route || entry.url)),\n  },\n  /**\n   * specify how link element should be rendered - this needs to be a\n   * valid vue link component string (e.g. `'RouterLink'`) a component directly and\n   * vue-router is necessary or `'a'` for a native HTML link element\n   *\n   * **caveat**: if you are using Nuxt the string `'NuxtLink'` is not enough,\n   *  but you need to import the component as `import { NuxtLink } from '#components';`\n   *  and pass the component to the prop!\n   */\n  renderAs: {\n    type: [String, Object],\n    default: 'a',\n    validate: (val) => {\n      if (typeof val === 'string') {\n        return ['RouterLink', 'NuxtLink', 'a'].includes(val)\n      }\n      return typeof val === 'object'\n        && val.name && ['RouterLink', 'NuxtLink'].includes(val);\n    },\n  },\n  /**\n   * specify a label for the navigation bar - for accessibility reasons\n   */\n  navigationLabel: {\n    type: String,\n    default: 'App Navigation',\n  },\n  /**\n   * provide a accessible label for the mobile menu icon\n   */\n  menuButtonLabel: {\n    type: String,\n    default: 'Toggle Navigation',\n  },\n  /**\n   * active Element can be set two ways:\n   * 1) provide a regex in property `routeMatch` for each element in\n   *  `primaryItems` and `secondaryItems`\n   * 2) handle the active element in the front end and set the active\n   *  element id with this property - this property will have priority over\n   *  `routeMatch`\n   */\n  activeElementId: {\n    type: [String, Number],\n    default: null,\n  },\n  /**\n   * define a custom size (in px) when the component should switch to mobile view\n   *  (with hamburger menu icon)\n   */\n  mobileSize: {\n    type: Number,\n    default: 640,\n  },\n});\n\n/** MOBILE NAV OPEN HANDLING */\n/**\n * variable to control navigation drop down on mobile\n * @type {Ref<UnwrapRef<boolean>>}\n */\nconst navOpen = ref(false);\n\n/** ACTIVE ELEMENT HANDLING */\n// we need to access the current component instance\n// to check for router\nconst { app } = getCurrentInstance().appContext;\n\nconst currentRoute = computed(() => app.config.globalProperties.$route?.path);\n\n/**\n * provide a list of all nav elements on the page (=primary and secondary items\n *  combined)\n * @returns {Object[]}\n */\nconst navElements = computed(() => [].concat(props.primaryItems, props.secondaryItems));\n\n/**\n * return the active list element or an empty object if $route not initialized yet\n * (empty object to avoid undefined errors)\n * @returns {{}|Object}\n */\nconst activeElement = computed(() => {\n  // if no other match is found the first list item will be used.\n  let element = null;\n  // prioritize active element set via props\n  if (props.activeElementId) {\n    element = navElements.value.find(e => e.id === props.activeElementId);\n    // if prop is not set check for the current active element via route match\n  } else if (currentRoute.value) {\n    element = navElements.value.find(e => e.routeMatch && currentRoute.value\n      .search(e.routeMatch) >= 0);\n    // if no element was found with routeMatch property take a last attempt to\n    // match the route\n    if (!element) {\n      element = navElements.value.find(e => currentRoute.value === e.route);\n    }\n  }\n  // restrict warning to when element was searched for but no element was found and no option was set\n  // to define one\n  if (!element && !navElements.value.some(e => e.routeMatch) && !props.activeElementId) {\n    // provide a warning to the user\n    console.warn('Attention - no active element could be identified and the first list item will be used!'\n      + 'Please set an active element via prop `activeElementId` or `routeMatch` property.');\n  }\n\n  // use the found element or if nothing was found use the first element in\n  // list\n  return element || navElements.value[0];\n});\n/**\n * the id of the currently active element\n * @returns {?string}\n */\nconst activeElementIdInt = computed(() => activeElement.value?.id ?? '');\n\n/** MOBILE OR DESKTOP DISPLAY */\n// set up all the html elements that are needed for resize calculations\n// (mobile or desktop view)\nconst mobileViewNavigation = useTemplateRef('mobileViewNavigationElement');\nconst desktopNavigation = useTemplateRef('desktopNavigationElement');\nconst menuButton = useTemplateRef('menuButtonElement');\n\n// get isMobile variable from window resize event listener\nconst { isMobile } = useWindowResize({\n  callback: resizeTriggered,\n  mobileMaxSize: props.mobileSize,\n  setDebounce: 0,\n  callOnMounted: true,\n});\n\n/**\n * only render desktop view when dom was mounted (to avoid hydration issues with SSR)\n * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n */\nconst isMounted = ref(false);\n\n/**\n * after calculating all the element widths - should short label be shown?\n * @type {Ref<UnwrapRef<boolean>>}\n */\nconst showShortLabel = ref(false);\n\n/**\n * list of navigation elements minus the currently active element\n * @returns {Object[]}\n */\nconst mobileDropDownElements = computed(() => navElements.value\n  .filter(e => e.id !== activeElementIdInt.value));\n/**\n * return all elements that should appear in the mobile drop down below the separation line\n * (filtering out the active item)\n * @returns {Object[]}\n */\nconst mobileRightElements = computed(() => props.secondaryItems\n  .filter(e => e.id !== activeElementIdInt.value));\n/**\n * return all elements that should appear in the mobile drop down above the separation line\n * (filtering out the active item)\n * @returns {Object[]}\n */\nconst mobileLeftElements = computed(() => props.primaryItems\n  .filter(e => e.id !== activeElementIdInt.value));\n/**\n * drop down primary and secondary separator should only be shown if in total min 3 items\n * @returns {boolean}\n */\nconst showSeparator = computed(() => {\n  const rightElementsLength = mobileRightElements.value.length;\n  const leftElementsLength = mobileLeftElements.value.length;\n  return !!leftElementsLength && !!rightElementsLength\n    && (leftElementsLength + rightElementsLength) > 2;\n});\n\n/**\n * determine if labels fit the navigation element or if short labels should be used\n */\nfunction calcTextWidth() {\n  // clone the navigation element in question\n  const cloneRef = mobileViewNavigation.value || desktopNavigation.value;\n  // safeguard against element not existing\n  if (cloneRef) {\n    // clone the element\n    const clonedNavigation = cloneRef.cloneNode(true);\n    // get the element width (needed to set clone width and for mobile calculations)\n    const navigationWidth = cloneRef.clientWidth;\n    // set the cloned element width\n    clonedNavigation.style.maxWidth = `${navigationWidth}px`;\n    // add the cloned element to the DOM\n    cloneRef.parentElement.append(clonedNavigation);\n    // different elements need to be checked if it is mobile (<640px or custom mobileSize) or desktop\n    // also include MenuButton in check here since it is sometimes not rendered yet\n    if (isMobile.value && menuButton.value) {\n      // get the menu button width\n      const menuButtonWidth = menuButton.value.$el.clientWidth;\n      // get the link (<a>) element\n      const activeLinkElement = clonedNavigation.getElementsByTagName('a')[0];\n      // get the text (<span>) element\n      const activeTextElement = clonedNavigation.getElementsByTagName('span')[0];\n      // get the link element (<a>) of the active element\n      // const activeLinkElement = clonedNavigation.firstChild.firstChild;\n      // get the text element (<span>) of the active element\n      // const activeTextElement = activeLinkElement.firstChild;\n      // get the padding of the link element\n      const activeLinkPadding = Number(window.getComputedStyle(activeLinkElement).paddingLeft\n        .replace('px', ''));\n      // now set the regular label of the currently active element as innerText\n      activeTextElement.innerText = activeElement.value.label;\n      // check if short label should be shown by\n      // a) checking if active element label does not fit in the navigation width (- the menu button width)\n      showShortLabel.value = (navigationWidth - menuButtonWidth - (2 * activeLinkPadding)\n          < activeTextElement.scrollWidth)\n        // b) if any of the dropdown entries does not fit into the navigation width\n        || mobileDropDownElements.value.some((item) => {\n          // assign the relevant label\n          activeTextElement.innerText = item.label;\n          // see if it fits\n          return (Math.ceil(navigationWidth - (2 * activeLinkPadding))\n            < activeTextElement.scrollWidth);\n        });\n    } else {\n      // get grandchildren of navigation element -> <li> elements\n      showShortLabel.value = [...clonedNavigation.childNodes].flat()\n        // filter out separation lines and other potential items that do not contain a link element\n        .filter(li => li instanceof HTMLElement && li.getElementsByClassName('base-navigation__nav-item-link')[0])\n        // check if one of the elements has text that does not fit the link element\n        .some((li, index) => {\n          // get the link (<a>) element\n          const linkElement = li.getElementsByTagName('a')[0] || li.firstChild;\n          // get the text (<span>) element\n          const textElement = li.getElementsByTagName('span')[0];\n          // set the innerText of the span to the full label of the element with the same index in the navElements array\n          textElement.innerText = navElements.value[index]?.label;\n          // get the link element padding to subtract from available width\n          const linkPadding = Number(window.getComputedStyle(linkElement).paddingLeft.replace('px', ''));\n          // check if text fits link element width of if scrollWidth exceeds it\n          return (Math.ceil(linkElement.clientWidth - (2 * linkPadding)) < textElement.scrollWidth);\n        });\n    }\n    // remove the cloned elements\n    clonedNavigation.remove();\n  }\n}\n/**\n * resize function with timeout to minimize number of label display recalculations\n */\nfunction resizeTriggered() {\n  // give mobile elements time to render\n  nextTick(() => {\n    calcTextWidth();\n  });\n}\n\n// on mobile the menuButton is not rendered in time on mounted so\n// we add a watcher that calculates again as soon as button is rendered\nwatch(menuButton, () => {\n  if (menuButton.value) {\n    calcTextWidth();\n  }\n});\n\nonMounted(() => {\n  isMounted.value = true;\n});\n</script>\n\n<template>\n  <nav\n    :aria-label=\"navigationLabel\"\n    class=\"base-navigation\">\n    <!-- VIEW FOR DESKTOP APPLICATIONS -->\n    <!-- render desktop view if a) elements were mounted and window size is not mobile (-> default\n      rendered is mobile view) -->\n    <template\n      v-if=\"isMounted && !isMobile\">\n      <ul\n        ref=\"desktopNavigationElement\"\n        class=\"base-navigation__nav-items\">\n        <!-- PRIMARY ELEMENTS -->\n        <li\n          v-for=\"element in primaryItems\"\n          :key=\"`p-${element.id}`\"\n          class=\"base-navigation__nav-item\">\n          <BaseLink\n            :render-link-as=\"renderAs\"\n            :value=\"showShortLabel && element.shortLabel ? element.shortLabel : element.label\"\n            :aria-current=\"element.id === activeElementIdInt ? 'page' : undefined\"\n            :identifier-property-value=\"element.route || undefined\"\n            :url=\"element.url || undefined\"\n            :class=\"['base-navigation__nav-item-link',\n                     { 'base-navigation__nav-item-link--active': activeElementIdInt === element.id }]\">\n            <template #label=\"{ label }\">\n              <span :class=\"{ 'base-navigation__nav-item-link__text--truncation': showShortLabel }\">\n                {{ label }}\n              </span>\n            </template>\n          </BaseLink>\n        </li>\n        <!-- SECONDARY ELEMENTS -->\n        <li\n          v-for=\"element in secondaryItems\"\n          :key=\"`s-${element.id}`\"\n          class=\"base-navigation__nav-item base-navigation__nav-item--secondary\">\n          <BaseLink\n            :render-link-as=\"renderAs\"\n            :value=\"showShortLabel && element.shortLabel ? element.shortLabel : element.label\"\n            :aria-current=\"element.id === activeElementIdInt ? 'page' : undefined\"\n            :identifier-property-value=\"element.route || undefined\"\n            :url=\"element.url || undefined\"\n            :class=\"['base-navigation__nav-item-link',\n                     { 'base-navigation__nav-item-link--active': activeElementIdInt === element.id }]\">\n            <template #label=\"{ label }\">\n              <span :class=\"{ 'base-navigation__nav-item-link__text--truncation': showShortLabel }\">\n                {{ label }}\n              </span>\n            </template>\n          </BaseLink>\n        </li>\n      </ul>\n    </template>\n\n    <!-- MOBILE VIEW -->\n    <template v-else>\n      <!-- THE VISIBLE NAV BAR WITH THE ACTIVE ELEMENT AND HAMBURGER MENU -->\n      <div\n        ref=\"mobileViewNavigationElement\"\n        class=\"base-navigation__mobile-nav-bar\">\n        <!-- ACTIVE NAV ITEM -->\n        <div\n          class=\"base-navigation__nav-item\">\n          <BaseLink\n            :render-link-as=\"renderAs\"\n            :value=\"showShortLabel && activeElement.shortLabel ?\n              activeElement.shortLabel : activeElement.label\"\n            :additional-attributes=\"{ ariaCurrentValue: 'page', exactPath: true }\"\n            :identifier-property-value=\"activeElement.route\"\n            class=\"base-navigation__nav-item-link\n                   base-navigation__nav-item-link--active\">\n            <template #label=\"{ label }\">\n              <span :class=\"{ 'base-navigation__nav-item-link__text--truncation': showShortLabel }\">\n                {{ label }}\n              </span>\n            </template>\n          </BaseLink>\n        </div>\n        <!-- HAMBURGER MENU -->\n        <BaseButton\n          v-if=\"isMounted && isMobile && mobileDropDownElements.length\"\n          ref=\"menuButtonElement\"\n          button-style=\"row\"\n          text=\"\"\n          :icon-title=\"menuButtonLabel\"\n          :icon=\"navOpen ? 'remove' : 'drag-lines'\"\n          :aria-expanded=\"navOpen\"\n          class=\"base-navigation__mobile-menu-button\"\n          @clicked=\"navOpen = !navOpen\" />\n      </div>\n      <!-- DROP DOWN MENU -->\n      <transition name=\"translateY\">\n        <ul\n          v-if=\"navOpen\"\n          class=\"base-navigation__drop-down\">\n          <!-- PRIMARY ELEMENTS -->\n          <li\n            v-for=\"element in mobileLeftElements\"\n            :key=\"`pm-${element.id}`\"\n            class=\"base-navigation__nav-item\">\n            <BaseLink\n              :render-link-as=\"renderAs\"\n              :value=\"showShortLabel && element.shortLabel ? element.shortLabel : element.label\"\n              :identifier-property-value=\"element.route || undefined\"\n              :url=\"element.url || undefined\"\n              :class=\"['base-navigation__nav-item-link',\n                       { 'base-navigation__nav-item-link--separator': mobileLeftElements.length\n                         + mobileRightElements.length > 2 },\n                       { 'base-navigation__nav-item-link--active': activeElementIdInt === element.id }]\"\n              @click=\"navOpen = false\"\n              @keydown.enter=\"navOpen = false\">\n              <template #label=\"{ label }\">\n                <span :class=\"{ 'base-navigation__nav-item-link__text--truncation': showShortLabel }\">\n                  {{ label }}\n                </span>\n              </template>\n            </BaseLink>\n          </li>\n          <!-- SECONDARY ELEMENTS -->\n          <li\n            v-for=\"element in mobileRightElements\"\n            :key=\"`sm-${element.id}`\"\n            :class=\"['base-navigation__nav-item', 'base-navigation__nav-item--secondary',\n                     { 'base-navigation__nav-item--separator': showSeparator }]\">\n            <BaseLink\n              :render-link-as=\"renderAs\"\n              :value=\"showShortLabel && element.shortLabel ? element.shortLabel : element.label\"\n              :identifier-property-value=\"element.route || undefined\"\n              :url=\"element.url || undefined\"\n              :class=\"['base-navigation__nav-item-link',\n                       { 'base-navigation__nav-item-link--active': activeElementIdInt === element.id }]\"\n              @click=\"navOpen = false\"\n              @keydown.enter=\"navOpen = false\">\n              <template #label=\"{ label }\">\n                <span :class=\"{ 'base-navigation__nav-item-link__text--truncation': showShortLabel }\">\n                  {{ label }}\n                </span>\n              </template>\n            </BaseLink>\n          </li>\n        </ul>\n      </transition>\n    </template>\n  </nav>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n@use \"@/styles/variables\" as *;\n\n.base-navigation {\n  box-shadow: $box-shadow-reg;\n  position: relative;\n  display: flex;\n  width: 100%;\n  height: $row-height-large;\n  background: $box-color;\n\n  // for all elements\n  .base-navigation__nav-item {\n    white-space: nowrap;\n    overflow: hidden;\n    height: $row-height-large;\n\n    .base-navigation__nav-item-link {\n      display: flex;\n      height: 100%;\n      box-sizing: border-box;\n      position: relative;\n      padding: 0 $spacing;\n      cursor: pointer;\n      align-items: center;\n      transition: all 0.2s ease-in-out;\n      color: inherit;\n      background-color: white;\n      text-align: center;\n      white-space: nowrap;\n      text-decoration: none;\n\n      &:hover, &:focus, &:active, &:focus-within {\n        text-decoration: none;\n        color: $app-color;\n      }\n\n      &.base-navigation__nav-item-link--active {\n        // add one pixel to active border and make smaller again by reducing the spread-radius\n        // otherwise there is an artefact line left or right of the element sometimes\n        box-shadow: $box-shadow-reg, inset 0 (-#{$border-active-width + 1}) 0 -1px $app-color;\n      }\n\n      .base-navigation__nav-item-link__text--truncation {\n        overflow: hidden;\n        text-overflow: ellipsis;\n      }\n    }\n  }\n\n  // desktop element styling\n  .base-navigation__nav-items {\n    display: flex;\n    width: 100%;\n    align-items: center;\n\n    .base-navigation__nav-item {\n      &:nth-child(1 of .base-navigation__nav-item--secondary) {\n        margin-left: auto;\n      }\n    }\n  }\n\n  // mobile element styling\n  .base-navigation__mobile-nav-bar {\n    display: flex;\n    flex-direction: row;\n    width: 100%;\n    background: $box-color;\n    // add z-index here so drop down is behind nav bar\n    z-index: calc(#{map.get($zindex, dropdown)} + 1);\n\n    .base-navigation__mobile-menu-button {\n      margin-left: auto;\n\n      &.base-navigation__mobile-menu-button--hidden {\n        visibility: hidden;\n      }\n    }\n  }\n\n  // mobile drop down styling\n  .base-navigation__drop-down {\n    position: absolute;\n    display: inline-block;\n    width: 100%;\n    background: $box-color;\n    box-shadow: $drop-shadow;\n    border-top: $separation-line;\n    margin-top: $row-height-large;\n    z-index: map.get($zindex, dropdown);\n\n    .base-navigation__nav-item {\n      &:nth-child(1 of .base-navigation__nav-item--secondary) {\n        border-top: $separation-line;\n      }\n    }\n  }\n}\n\n// drop down animations\n.translateY-enter-active,.translateY-leave-active {\n  transform-origin: top left 0;\n  transition:.2s ease;\n}\n\n.translateY-enter-from,\n.translateY-leave-to {\n  transform: translateY(-10px);\n  opacity: 0;\n}\n</style>\n","<script>\nimport BaseButton from '@/components/BaseButton/BaseButton.vue';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { computed, ref, useSlots, useTemplateRef, watch } from 'vue';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\nimport { useWindowResize } from '@/composables/useWindowResize.js';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\n\n/**\n * a row that can display options responsively either hidden behind an options button\n * or directly\n */\n\nexport default {\n  name: 'BaseOptions',\n  components: {\n    BaseButton,\n  },\n  props: {\n    /**\n     * set showing of option buttons from outside.\n     *   the v-model directive may be used on this prop\n     */\n    showOptions: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * hide options completely (necessary if only before or after slot elements should remain)\n     */\n    optionsHidden: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define alignment of options button and options\n     */\n    alignOptions: {\n      type: String,\n      default: 'right',\n      validator: val => ['left', 'right'].includes(val),\n    },\n    /**\n     * define in which scenario an options button should be shown:\n     *\n     *   **always**: always show the options button\n     *   **mobile**: only show options button when window size < 640px\n     *   **never**: never show the options button - just show the available options directly\n     *   **fitted**: use options button whenever the options (incl. before and after slot) do\n     *    not fit the row anymore\n     */\n    useOptionsButtonOn: {\n      type: String,\n      default: 'always',\n      validator: val => ['always', 'mobile', 'never', 'fitted'].includes(val),\n    },\n    /**\n     * define the options button text as an object with `show` (=text that should be\n     * shown with options hidden) and `hide` (=text that should be shown with options visible)\n     *   values can be either plain strings or a string leading to a localization file.\n     *   (only relevant if `useOptionsButtonOn` is different from 'never')\n     */\n    optionsButtonText: {\n      type: Object,\n      default: () => ({\n        show: 'options',\n        hide: 'return',\n      }),\n      validator: val => 'show' in val && 'hide' in val,\n    },\n    /**\n     * define the icon for the options button as an object with `show` (=icon that should be\n     * shown with options hidden) and `hide` (=icon that should be shown with options visible)\n     *   see [BaseIcon](BaseIcon) for available icons.\n     *   (only relevant if `useOptionsButtonOn` is different from 'never')\n     */\n    optionsButtonIcon: {\n      type: Object,\n      default: () => ({\n        show: 'options-menu',\n        hide: 'remove',\n      }),\n      validator: val => 'show' in val && 'hide' in val,\n    },\n    /**\n     * define if slot after-options should be shown before or after options.\n     * if row wraps because of space issues\n     *   (only relevant with use of options button)\n     */\n    showAfterOptionsBelow: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * in order to display options one can either use the slot `options` or specify a\n     * config via `optionsConfig` prop. If the latter option is used the following properties\n     * need to be provided:\n     *\n     *   **text** `string` - the text displayed in the button\n     *   **icon** `string` - the icon name to display\n     *    (for available icons see [BaseIcon](BaseIcon) )\n     *   **value** `string` - the value emitted on button click\n     *   **disabled** `boolean?` - should button be shown as disabled\n     */\n    optionsConfig: {\n      type: Array,\n      default: () => [{\n        text: 'delete',\n        icon: 'waste-bin',\n        value: 'delete',\n        disabled: false,\n      }],\n      validator: val => val.every((option) => {\n        const requiredProps = ['text', 'icon', 'value'];\n        const optionProps = Object.keys(option);\n        return requiredProps.every(prop => optionProps.includes(prop));\n      }),\n    },\n    /**\n     * specify an array of values set in `optionsConfig` property `value`\n     *  for options that should appear disabled.\n     *  This is equivalent to and just a more convenient way than to\n     *  set the `optionsConfig` property `disabled`\n     */\n    disableOptions: {\n      type: Array,\n      default: () => ([]),\n    },\n    /**\n     * set true if options button should be disabled\n     *  not relevant for `useOptionsButtonOn` with value `never`\n     */\n    optionsButtonDisabled: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['option-triggered', 'update:show-options'],\n  setup(props, { emit }) {\n    /** ROW ELEMENTS RENDERING */\n    /**\n     * get a reference to the root component\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const optionsRow = useTemplateRef('optionsRowElement');\n    /**\n     * total row width needed to calc if options and after options\n     * should be shown inline\n     * @type {Ref<UnwrapRef<number>, UnwrapRef<number> | number>}\n     */\n    const rowWidth = ref(4000);\n\n    /**\n     * component isMobile variable defined here to always have it\n     * available\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const isMobile = ref(false);\n\n    /** SLOTS */\n    const slots = useSlots();\n    /**\n     * determine if before slot has data\n     * @returns {Boolean}\n     */\n    const { slotHasContent: beforeSlotHasData } = useHasSlotContent(slots.beforeOptions);\n    /**\n     * determine if after slot has data\n     * @returns {Boolean}\n     */\n    const { slotHasContent: afterSlotHasData } = useHasSlotContent(slots.afterOptions);\n    /**\n     * get a reference to the before slot element\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const beforeOptions = useTemplateRef('beforeOptionsElement');\n    /**\n     * get a reference to the after slot element\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const afterOptions = useTemplateRef('afterOptionsElement');\n    /**\n     * get a reference to the after slot element\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const afterOptionsBelow = useTemplateRef('afterOptionsBelowElement');\n\n    /** ROW WIDTH CALCULATIONS */\n    /**\n     * a reference to the element containing all option buttons\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const options = useTemplateRef('optionsElement');\n    /**\n     * reference to the options button (Vue) element\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const optionsButton = useTemplateRef('optionsButtonElement');\n    /**\n     * width remaining inline for the actual option buttons to be rendered\n     * @type {Ref<UnwrapRef<number>, UnwrapRef<number> | number>}\n     */\n    const remainingOptionsWidth = ref(4000);\n    /**\n     * beforeOptions element width needed to calc if options\n     * should be shown inline\n     * @type {Ref<UnwrapRef<number>, UnwrapRef<number> | number>}\n     */\n    const beforeOptionsWidth = ref(0);\n    /**\n     * afterOptions element width needed to calc if options\n     * should be shown inline\n     * @type {Ref<UnwrapRef<number>, UnwrapRef<number> | number>}\n     */\n    const afterOptionsWidth = ref(0);\n    /**\n     * options button element width needed to calc if options\n     * should be shown inline\n     * @type {Ref<UnwrapRef<number>, UnwrapRef<number> | number>}\n     */\n    const optionsButtonWidth = ref(0);\n    /**\n     * beforeOptions element width needed to calc if options\n     * should be shown inline\n     * @type {Ref<UnwrapRef<number>, UnwrapRef<number> | number>}\n     */\n    const optionsWidth = ref(0);\n    /**\n     * to detect changes in font size we need to add this element\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const fontSizeChangeDetector = useTemplateRef('fontSizeChangeDetectorElement');\n    /**\n     * store the line height in a variable to detect font size changes\n     * (which requires fixed element with to be recalculated)\n     * @type {Ref<UnwrapRef<number>, UnwrapRef<number> | number>}\n     */\n    const lineHeight = ref(0);\n    /**\n     * only display options after initial width calculations have been done to\n     * avoid unnecessary flashing (especially on SSR)\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const optionsInitialized = ref(false);\n\n    /**\n     * function for elements width that only has to be calculated once\n     */\n    function calcFixedElementWidth() {\n      // check if the slot beforeOptions has elements\n      if (beforeSlotHasData.value && beforeOptions.value) {\n        // if yes set the variable with the width of the element\n        beforeOptionsWidth.value = beforeOptions.value.clientWidth;\n      }\n      // since afterOptions element can be inline or below we need to get\n      // the correct one that is currently rendered\n      const afterOptionsElement = afterOptions.value || afterOptionsBelow.value;\n      // check if the slot afterOptions has data\n      if (afterSlotHasData.value && afterOptionsElement) {\n        // determine the current element width\n        afterOptionsWidth.value = getElementWidth(afterOptionsElement);\n      }\n      // check if it is used and rendered\n      if (useOptionsButton.value && optionsButton.value) {\n        // clone the element (the direct values are not always 100% correct - so\n        // we clone the element to be free from side effects and take that value\n        optionsButtonWidth.value = getElementWidth(optionsButton.value.$el);\n      }\n    }\n\n    /**\n     * get the unobstructed element width by appending an absolute clone\n     * to the root element\n     * @param {HTMLElement} elementToClone - the element we want to know the width of\n     * @returns {number} - the width as provided by clientWidth\n     */\n    function getElementWidth(elementToClone) {\n      const node = elementToClone.cloneNode(true);\n      // make it absolute so all the row space is available\n      node.style.position = 'absolute';\n      // hide it from the user\n      node.style.top = '-99999px';\n      node.style.left = '-99999px';\n      // append it to the options row to have it take up the correct amount of\n      // space\n      optionsRow.value.appendChild(node);\n      // if yes - set the variable to store the button width\n      const elementWidth = node.clientWidth;\n      // and remove the clone again\n      optionsRow.value.removeChild(node);\n      return elementWidth;\n    }\n\n    /**\n     * calculate the variable width elements width after initial render, options toggle\n     * or window resize events\n     */\n    function calcOptionsWidth() {\n      if (optionsRow.value) {\n        rowWidth.value = optionsRow.value.clientWidth;\n      }\n      // check if it is defined - if yes - calculate the width remaining for the option buttons\n      remainingOptionsWidth.value = optionsRow.value ? rowWidth.value\n        - beforeOptionsWidth.value - afterOptionsWidth.value\n        // only subtract options button if it is shown (and showing options button is\n        // not depending on remaining width)\n        - (useOptionsButton.value && props.useOptionsButtonOn !== 'fitted'\n          ? optionsButtonWidth.value : 0)\n        : 0;\n      // check if it is defined\n      if (options.value) {\n        // if yes - get the width they all together actually take up\n        optionsWidth.value = getElementWidth(options.value);\n        // after value was calculated initialized can be set true to\n        // make options visible\n        optionsInitialized.value = true;\n      }\n    }\n\n    // if options button should be shown on mobile only add a window resize\n    // listener\n    if (props.useOptionsButtonOn === 'mobile') {\n      const { isMobile: isMobileInt } = useWindowResize({\n        callback: () => {\n          // on resize update the component variable\n          isMobile.value = isMobileInt.value;\n        },\n        callOnMounted: true,\n        setDebounce: 50,\n      });\n    }\n    // on resize check if all elements still fit the row or need to\n    // be wrapped\n    useElementObserver({\n      type: 'resize',\n      target: optionsRow,\n      callback: () => {\n        // we need to check if the font size changed after the resize\n        // so an empty element (with one space) was added that is checked for height\n        const newHeight = fontSizeChangeDetector.value?.offsetHeight || 0;\n        // if height changed - re-calculate!\n        if (newHeight !== lineHeight.value) {\n          calcFixedElementWidth();\n          // and update the height value\n          lineHeight.value = newHeight;\n        }\n        // now calc all other elements\n        calcOptionsWidth();\n      },\n    });\n\n    /**\n     * initially observe the options button to get the correct size\n     * only when mutation is triggered the since is calculated correctly!\n     * (it seems the svg might still be missing before)\n     */\n    useElementObserver({\n      target: optionsButton,\n      type: 'mutation',\n      callback: (value, observer) => {\n        if (optionsButton.value) {\n          optionsButtonWidth.value = getElementWidth(optionsButton.value.$el);\n          calcOptionsWidth();\n          observer.disconnect();\n        }\n      },\n      options: {\n        childList: true,\n        subtree: true,\n      },\n    });\n\n    /**\n     * observe mutations to actions to calc the initial width correctly - this is\n     * needed when the options button is NOT shown initially (otherwise calculation\n     * is correctly done by optionsButton MutationObserver anyway)\n     */\n    useElementObserver({\n      target: options,\n      type: 'mutation',\n      callback: (value, observer) => {\n        // check if element exists\n        if (options.value) {\n          // if yes calculated the width\n          optionsWidth.value = getElementWidth(options.value);\n          // and make element visible\n          optionsInitialized.value = true;\n          // after that observer can be disconnected\n          observer.disconnect();\n        }\n      },\n      options: {\n        childList: true,\n        subtree: true,\n      },\n    });\n\n    /** OPTIONS AND OPTIONS BUTTON DISPLAY */\n    /**\n     * internal variable for options toggle\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const showOptionsInt = ref(false);\n\n    /**\n     * watch external showOptions prop to keep internal variable in sync\n     */\n    watch(() => props.showOptions, (val) => {\n      if (val !== showOptionsInt.value) {\n        showOptionsInt.value = val;\n      }\n    }, { immediate: true });\n\n    // watch options toggle to recalculate the remaining size\n    // for options (= should they be shown inline or below)\n    watch(showOptionsInt, (val) => {\n      if (val !== props.showOptions) {\n        /**\n         * emitted when options button is toggled (not relevant if `useOptionsButtonOn` prop\n         * is set to 'never')\n         *   the v-model directive can be used on `showOptions` prop here\n         * @event update:show-options\n         * @param {boolean} - was show value set true or false\n         */\n        emit('update:show-options', val);\n      }\n    });\n\n    /**\n     * determine if options are fitting the row taking into account all option buttons and before and after elements\n     * (needed for type 'fitted')\n     * @type {ComputedRef<boolean>}\n     */\n    const optionsFittingRowWidth = computed(() => {\n      return rowWidth.value - optionsWidth.value - beforeOptionsWidth.value - afterOptionsWidth.value > 0;\n    });\n\n    /**\n     * translate prop into boolean value to see if options\n     * button should be shown\n     * @returns {ComputedRef<boolean>}\n     */\n    const useOptionsButton = computed(() => {\n      return props.useOptionsButtonOn === 'always'\n        || (props.useOptionsButtonOn === 'mobile' && isMobile.value)\n        || (props.useOptionsButtonOn === 'fitted' && !optionsFittingRowWidth.value);\n    });\n\n    /**\n     * showOptionsInt really only governs options display in connection\n     * with options button toggle, but actual options rendering also needs\n     * to consider if options button is used at all\n     * @type {ComputedRef<boolean>}\n     */\n    const displayOptions = computed(() => {\n      return showOptionsInt.value || !useOptionsButton.value;\n    });\n\n    /**\n     * determine if options should be shown inline or below options row\n     * @returns {ComputedRef<boolean>}\n     */\n    const showOptionsInline = computed(() => {\n      // show options inline if either options button is not used or there is enough space left\n      return !useOptionsButton.value || remainingOptionsWidth.value - optionsWidth.value > 0;\n    });\n\n    /**\n     * when options are rendered do an initial calculation for the options\n     * fitting the row\n     */\n    watch(options, (val) => {\n      if (val) {\n        calcOptionsWidth();\n      }\n    });\n\n    // if options button becomes disabled, hide displayed options\n    watch(() => props.optionsButtonDisabled, (val) => {\n      if (val) {\n        showOptionsInt.value = false;\n      }\n    });\n\n    /** INTERNATIONALIZATION */\n    const { getI18nTerm } = useI18n();\n\n    return {\n      rowWidth,\n      // slots\n      beforeSlotHasData,\n      afterSlotHasData,\n      beforeOptions,\n      afterOptions,\n      // options fit calculations\n      remainingOptionsWidth,\n      optionsWidth,\n      optionsInitialized,\n      calcFixedElementWidth,\n      calcOptionsWidth,\n      // options and options button display\n      showOptionsInt,\n      useOptionsButton,\n      displayOptions,\n      showOptionsInline,\n      // internationalization\n      getI18nTerm,\n    };\n  },\n  data() {\n    return {\n      /**\n       * mutation observer for specific element\n       */\n      mutationObserver: null,\n    };\n  },\n  computed: {\n    /**\n     * determine if afterOptions slot should be shown above or below options in a\n     * wrapping situation\n     */\n    showAfterOptionsInline() {\n      // show options inline if\n      // a) the slot was actually used and\n      return this.afterSlotHasData\n        // b) options button is not used and there is enough space for them or\n        && ((!this.useOptionsButton && this.remainingOptionsWidth > this.optionsWidth)\n          // c) options button is used and there is enough space left inline or\n          // showAfterOptionsBelow is false\n          || (this.useOptionsButton && (!this.showAfterOptionsBelow\n            || this.remainingOptionsWidth > 0)));\n    },\n    /**\n     * determine if option buttons need to be flex-wrapped\n     */\n    wrapOptions() {\n      return this.rowWidth <= this.optionsWidth;\n    },\n  },\n  updated() {\n    // calc the width of all fixed width elements (beforeOptions,\n    // options button, after Options)\n    this.calcFixedElementWidth();\n    this.calcOptionsWidth();\n  },\n  methods: {\n    optionTriggered(value) {\n      /**\n       * emitted if prop `optionsConfig` is used when an options button is clicked\n       *\n       * @event option-triggered\n       * @param {string} - the value provided in `optionsConfig` object\n       */\n      this.$emit('option-triggered', value);\n    },\n  },\n};\n</script>\n\n<template>\n  <div class=\"base-options\">\n    <div\n      ref=\"optionsRowElement\"\n      :class=\"[\n        'base-options__row',\n        `base-options__row-${alignOptions}`,\n        {\n          'base-options__row-wrap': !showOptionsInline\n            || (!useOptionsButton && remainingOptionsWidth < optionsWidth),\n        },\n      ]\">\n      <div\n        v-if=\"beforeSlotHasData\"\n        ref=\"beforeOptionsElement\"\n        class=\"base-options__before\">\n        <!-- @slot add an element before the options e.g. a header -->\n        <slot\n          name=\"beforeOptions\" />\n      </div>\n      <div\n        v-if=\"alignOptions === 'right'\"\n        class=\"base-options__spacer\" />\n      <div\n        v-if=\"!optionsHidden && showOptionsInline && displayOptions\"\n        ref=\"optionsElement\"\n        :class=\"['base-options__options-inline',\n                 { 'base-options__options-inline-wrap': wrapOptions },\n                 { 'base-options__options-inline-left': alignOptions === 'left' },\n                 { 'base-options__options-inline-hidden': !optionsInitialized }]\">\n        <!-- @slot add the actual options -->\n        <slot name=\"options\">\n          <template v-if=\"optionsConfig.length\">\n            <BaseButton\n              v-for=\"({ text, icon, disabled, value }, index) of optionsConfig\"\n              :key=\"text + '_' + index\"\n              :text=\"text\"\n              :icon=\"icon\"\n              :disabled=\"disabled || disableOptions.includes(value)\"\n              :has-background-color=\"false\"\n              icon-size=\"large\"\n              button-style=\"single\"\n              @clicked=\"optionTriggered(value)\" />\n          </template>\n        </slot>\n      </div>\n      <BaseButton\n        v-if=\"!optionsHidden && useOptionsButton\"\n        ref=\"optionsButtonElement\"\n        :text=\"showOptionsInt ? getI18nTerm(optionsButtonText.hide)\n          : getI18nTerm(optionsButtonText.show)\"\n        :icon=\"showOptionsInt ? optionsButtonIcon.hide : optionsButtonIcon.show\"\n        :disabled=\"optionsButtonDisabled\"\n        :class=\"[{ 'base-options__options-button-left': alignOptions === 'left' }]\"\n        @clicked=\"showOptionsInt = !showOptionsInt\" />\n      <div\n        v-if=\"alignOptions === 'left'\"\n        class=\"base-options__spacer base-options__spacer-left\" />\n      <div\n        v-if=\"showAfterOptionsInline && afterSlotHasData\"\n        ref=\"afterOptionsElement\"\n        class=\"base-options__after-inline\">\n        <!-- @slot add elements after the options element -->\n        <slot name=\"afterOptions\" />\n      </div>\n      <span\n        ref=\"fontSizeChangeDetectorElement\"\n        class=\"hide base-options__font-size-detector\">\n        &#10240;\n      </span>\n    </div>\n    <transition name=\"slide-fade-options\">\n      <div\n        v-if=\"!optionsHidden && displayOptions && !showOptionsInline\"\n        class=\"base-options__below\">\n        <!-- @slot add the actual options -->\n        <slot name=\"options\">\n          <template v-if=\"optionsConfig.length\">\n            <BaseButton\n              v-for=\"(config, index) of optionsConfig\"\n              :key=\"config.text + '_' + index\"\n              :text=\"config.text\"\n              :icon=\"config.icon\"\n              :has-background-color=\"false\"\n              icon-size=\"large\"\n              button-style=\"single\"\n              @clicked=\"optionTriggered(config.value)\" />\n          </template>\n        </slot>\n      </div>\n    </transition>\n    <div\n      v-if=\"!showAfterOptionsInline && afterSlotHasData\"\n      ref=\"afterOptionsBelowElement\"\n      class=\"base-options__after\">\n      <!-- @slot add elements after the options element -->\n      <slot name=\"afterOptions\" />\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n@use \"sass:map\";\n\n.base-options {\n  width: 100%;\n\n  .base-options__row {\n    position: relative;\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    min-height: $row-height-small;\n    width: 100%;\n    background-color: inherit;\n    z-index: map.get($zindex, slidein);\n\n    &-left {\n      justify-content: flex-start;\n    }\n\n    &-right {\n      justify-content: flex-end;\n    }\n\n    &-wrap {\n      flex-wrap: wrap;\n    }\n\n    .base-options__options-button-left {\n      order: 0;\n    }\n\n    .base-options__before {\n      flex: 0 1 auto;\n    }\n\n    .base-options__spacer {\n      flex: 1 1 auto;\n\n      &-left {\n        order: 2;\n      }\n    }\n\n    .base-options__options-inline {\n      flex: 0 0 auto;\n      display: flex;\n      justify-content: flex-end;\n\n      &-left {\n        order: 1;\n        justify-content: flex-start;\n      }\n\n      &-wrap {\n        flex: 0 1 auto;\n        flex-wrap: wrap;\n        justify-content: center;\n      }\n\n      &-hidden {\n        visibility: hidden;\n      }\n    }\n\n    .base-options__after-inline {\n      flex: 0 1 auto;\n      order: 5;\n      display: flex;\n      justify-content: flex-end;\n      background-color: inherit;\n    }\n  }\n\n  .base-options__below {\n    display: flex;\n    flex-wrap: wrap;\n    height: auto;\n    justify-content: center;\n  }\n\n  .base-options__after {\n    display: flex;\n    justify-content: flex-end;\n  }\n\n  .base-options__font-size-detector {\n    // needed so the span adapts the height with\n    // changing font-size\n    line-height: $line-height;\n  }\n}\n\n.slide-fade-options-enter-active, .slide-fade-options-move {\n  transition: all 0.5s ease;\n}\n\n.slide-fade-options-enter-from {\n  opacity: 0;\n  transform: translateY(-#{2*$spacing});\n}\n</style>\n","<script>\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport { ref, useTemplateRef } from 'vue';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { useDebounce } from '@/composables/useDebounce.js';\n\n/**\n * Pagination component\n */\n\nexport default {\n  name: 'BasePagination',\n  components: {\n    BaseIcon,\n  },\n  props: {\n    /**\n     * specify the total number of pages\n     */\n    total: {\n      type: Number,\n      default: null,\n    },\n    /**\n     * currently active page number\n     */\n    modelValue: {\n      type: Number,\n      default: 1,\n    },\n    /**\n     * specify if pagination elements should be links - specify a vue link element (as\n     * string e.g. `'RouterLink` or pass the component directly) or set the variable `false`\n     * if element should not be a link (this needs vue-router)\n     * currently only vue components (like 'RouterLink' or 'NuxtLink') are supported!\n     *\n     * **caveat**: if you are using Nuxt the string `'NuxtLink'` is not enough,\n     *  but you need to import the component as `import { NuxtLink } from '#components';`\n     *  and pass the component to the prop!\n     */\n    useLinkElement: {\n      type: [String, Boolean, Object],\n      default: false,\n      validator: val => (typeof val === 'boolean' && !val)\n        || (typeof val === 'string' && val)\n        || (typeof val === 'object' && val.name && ['NuxtLink', 'RouterLink'].includes(val.name)),\n    },\n    /**\n     * this prop gives the option to add assistive text for screen readers\n     * properties:\n     *\n     *   **currentPage**: aria-label for the current page\n     *   **nextPage**: aria-label for the next page\n     *   **pagination**: aria-label for the pagination element description\n     *   **previousPage**: aria-label for the previous page\n     *   **toPage**: aria-label for all page buttons except the current one\n     *\n     * The values of this object might be plain text or a key for an i18n file\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        currentPage: 'Current Page, Page',\n        nextPage: 'Go to next page',\n        pagination: 'Pagination',\n        previousPage: 'Go to previous page',\n        toPage: 'Go to page',\n      }),\n      // checking if all necessary properties are part of the provided object\n      validator: val => ['currentPage', 'nextPage', 'pagination', 'previousPage', 'toPage']\n        .every(prop => Object.keys(val).includes(prop)),\n    },\n  },\n  emits: ['update:model-value'],\n  setup(props) {\n    /** ACTIVE PAGE NUMBER */\n    /**\n     * currently active page number\n     * @type {Ref<UnwrapRef<number>>}\n     */\n    const active = ref(props.modelValue);\n\n    /** PAGE NUMBER DISPLAY CALCULATIONS */\n    const pagination = useTemplateRef('paginationEl');\n    /**\n     * total numbers to be displayed before the '...' depending on the width of the\n     * pagination element (only relevant if not all numbers can be displayed)\n     * @type {Ref<UnwrapRef<number>>}\n     */\n    const subsetNumber = ref(7);\n    /**\n     * max numbers to be displayed\n     * @type {Ref<UnwrapRef<number>>}\n     */\n    const maxNumbers = ref(10);\n    /**\n     * number the displayed pages between '...' should start with\n     * (only relevant if not all numbers can be displayed)\n     * @type {Ref<UnwrapRef<?number>>}\n     */\n    const start = ref(null);\n    /**\n     * number the displayed pages between the '...' should end with\n     * (only relevant if not all numbers can be displayed)\n     * @type {Ref<UnwrapRef<?number>>}\n     */\n    const end = ref(null);\n\n    /**\n     * depending on with of the parent element of the pagination calculate\n     * how many page numbers can be displayed\n     */\n    function setStartEnd() {\n      // safeguard against pagination element not rendered yet\n      if (!pagination.value) return;\n      // get parent width\n      const elementWidth = pagination.value.clientWidth;\n      // set the subset and the max number accordingly\n      if (elementWidth < 400) {\n        subsetNumber.value = 1;\n        maxNumbers.value = 5;\n      } else if (elementWidth < 550) {\n        subsetNumber.value = 3;\n        maxNumbers.value = 8;\n      } else if (elementWidth < 700) {\n        subsetNumber.value = 5;\n        maxNumbers.value = 8;\n      } else {\n        subsetNumber.value = 7;\n        maxNumbers.value = 10;\n      }\n      // calc start and end number from the subset number\n      start.value = active.value - subsetNumber.value / 2 > 0\n        ? active.value - Math.floor(subsetNumber.value / 2) : 1;\n      end.value = active.value + subsetNumber.value / 2 < props.total\n        ? active.value + Math.floor(subsetNumber.value / 2) : props.total;\n    }\n\n    // add a delay to start / end calculations\n    const { debounce } = useDebounce();\n    function debounceCalculations() {\n      debounce(setStartEnd, 50);\n    }\n\n    /**\n     * add an observer to adjust displayed numbers according to component\n     * width\n     */\n    useElementObserver({\n      type: 'resize',\n      target: pagination,\n      callback: debounceCalculations,\n    });\n\n    /**\n     * called on @vue:mounted of paginationEl element\n     * (to make sure pagination is actually present)\n     */\n    function elementMounted()  {\n      // calc the correct numbers for the first time as soon as component\n      // is mounted\n      setStartEnd();\n    }\n\n    /** LOCALIZATION */\n    const { getLangLabel, getI18nTerm } = useI18n();\n\n    return {\n      pagination,\n      subsetNumber,\n      maxNumbers,\n      start,\n      end,\n      active,\n      setStartEnd,\n      getLangLabel,\n      getI18nTerm,\n      elementMounted,\n    };\n  },\n  computed: {\n    /**\n     * calculate the actual subset page numbers to be displayed\n     * @returns {number[]}\n     */\n    subset() {\n      // check if subset number would exceed total number of items and start\n      // array from total - subsetNumber\n      const subsetStart = this.start + this.subsetNumber > this.total\n        ? this.total - this.subsetNumber + 1 : this.start;\n      return Array.from(\n        { length: this.subsetNumber },\n        (v, k) => k + subsetStart,\n      );\n    },\n    /**\n     * check if element should be displayed as a link element, otherwise make it a <span>\n     * @returns {String|Boolean|string}\n     */\n    numberElement() {\n      return this.useLinkElement ? this.useLinkElement : 'div';\n    },\n  },\n  watch: {\n    /**\n     * in case pagination is set via route - add a watcher here (however this only works\n     * with a query param 'page'!\n     */\n    $route: {\n      handler(to) {\n        if (!!this.useLinkElement && to?.query?.page && Number(to.query.page) !== Number(this.active)) {\n          this.active = Number(to.query.page);\n        }\n      },\n      immediate: true,\n    },\n    /**\n     * if active number changes inform parent\n     * @param {number} val - the new page number active\n     */\n    active: {\n      handler(val) {\n        // check if new number is different from prop value\n        if (this.modelValue !== val) {\n          /**\n           * triggered on page select\n           *\n           * @event update:model-value\n           * @param {number} - the new page number\n           */\n          this.$emit('update:model-value', val);\n        }\n        // adjust the start and end value accordingly (if not all numbers can be displayed)\n        this.setStartEnd();\n      },\n      // since $route watcher is immediate this needs to be immediate too in\n      // case the 'page' query param was set in the url\n      immediate: true,\n    },\n    /**\n     * check if parent prop changes\n     * @param {number} val - the page number provided by the parent component\n     */\n    modelValue(val) {\n      this.active = val;\n    },\n  },\n  methods: {\n    /**\n     * function to set a new page number active\n     * @param {number} page - the new page number\n     */\n    setActivePage(page) {\n      // if new page is not set via url set it here manually\n      if (!this.useLinkElement) {\n        // set internal variable to new page number\n        this.active = page;\n      }\n    },\n    /**\n     * get the correct link in case element is a link element\n     * @param {number} page - the page number of the element in question\n     * @returns {{path: string, query: Object}|string}\n     */\n    getLinkPath(page) {\n      // check if router in project and link element is used and set link path accordingly if yes\n      if (!!this.useLinkElement && this.$route) {\n        return ({ path: this.$route.fullPath, query: {\n          ...this.$route.query,\n          page,\n        }});\n      }\n      return '';\n    },\n  },\n};\n</script>\n\n<template>\n  <nav\n    ref=\"paginationEl\"\n    :aria-label=\"getI18nTerm(assistiveText.pagination)\"\n    class=\"base-pagination\"\n    @vue:mounted=\"elementMounted\">\n    <component\n      :is=\"numberElement\"\n      :to=\"!!useLinkElement ? getLinkPath(active - 1 > 0 ? active - 1 : 1) : undefined\"\n      :aria-disabled=\"active <= 1\"\n      :tabindex=\"active <= 1 ? -1 : 0\"\n      :class=\"[\n        'base-pagination__arrow',\n        { 'base-pagination__arrow-icon-inactive': active <= 1 },\n      ]\"\n      :aria-label=\"getI18nTerm(assistiveText.previousPage)\"\n      @click.prevent=\"active - 1 > 0 && !useLinkElement ? setActivePage(active - 1) : null\"\n      @keydown.enter=\"active - 1 > 0 && !useLinkElement ? setActivePage(active - 1) : null\">\n      <BaseIcon\n        class=\"base-pagination__arrow-icon base-pagination__arrow-icon-left\"\n        name=\"arrow-left\" />\n    </component>\n    <div class=\"base-pagination__row\">\n      <!-- ELEMENT TO DISPLAY WHEN TOTAL NUMBER OF ELEMENTS FITS INTO PARENT -->\n      <template v-if=\"total <= maxNumbers\">\n        <component\n          :is=\"numberElement\"\n          v-for=\"n in total\"\n          :key=\"n\"\n          :to=\"useLinkElement ? getLinkPath(n) : undefined\"\n          :tabindex=\"!useLinkElement ? 0 : undefined\"\n          :aria-current=\"active === n ? 'true' : undefined\"\n          :aria-label=\"`${active === n ? getI18nTerm(assistiveText.currentPage) : getI18nTerm(assistiveText.toPage)} ${n}`\"\n          :class=\"['base-pagination__number', { 'base-pagination__number-active': active === n }]\"\n          @keydown.enter=\"setActivePage(n)\"\n          @click.prevent=\"setActivePage(n)\">\n          {{ n }}\n        </component>\n      </template>\n      <template v-else>\n        <component\n          :is=\"numberElement\"\n          v-if=\"start !== 1\"\n          :to=\"useLinkElement ? getLinkPath(1) : undefined\"\n          :tabindex=\"!useLinkElement ? 0 : undefined\"\n          :aria-current=\"active === 1 ? 'true' : undefined\"\n          :aria-label=\"`${active === 1 ? getI18nTerm(assistiveText.currentPage) : getI18nTerm(assistiveText.toPage)} ${1}`\"\n          :class=\"['base-pagination__number', { 'base-pagination__number-active': active === 1 }]\"\n          @keydown.enter=\"setActivePage(1)\"\n          @click.prevent=\"setActivePage(1)\">\n          {{ 1 }}\n        </component>\n        <span\n          v-if=\"start > 2\"\n          class=\"base-pagination__more\">&#8943;</span>\n        <component\n          :is=\"numberElement\"\n          v-for=\"n in subset\"\n          :key=\"n\"\n          :to=\"useLinkElement ? getLinkPath(n) : undefined\"\n          :tabindex=\"!useLinkElement ? 0 : undefined\"\n          :aria-current=\"active === n ? 'true' : undefined\"\n          :aria-label=\"`${active === n ? getI18nTerm(assistiveText.currentPage) : getI18nTerm(assistiveText.toPage)} ${n}`\"\n          :class=\"['base-pagination__number', { 'base-pagination__number-active': active === n }]\"\n          @keydown.enter=\"setActivePage(n)\"\n          @click.prevent=\"setActivePage(n)\">\n          {{ n }}\n        </component>\n        <span\n          v-if=\"(end) < (total - 1) && (end) !== (total - 1)\"\n          class=\"base-pagination__more\">&#8943;</span>\n        <component\n          :is=\"numberElement\"\n          v-if=\"(end - 1) < (total - 1) && (end - 1) !== (total - 1)\"\n          :to=\"useLinkElement ? getLinkPath(total) : undefined\"\n          :tabindex=\"!useLinkElement ? 0 : undefined\"\n          :aria-current=\"active === total ? 'true' : undefined\"\n          :aria-label=\"`${active === total ? getI18nTerm(assistiveText.currentPage) : getI18nTerm(assistiveText.toPage)} ${total}`\"\n          :class=\"['base-pagination__number',\n                   { 'base-pagination__number-active': active === total }]\"\n          @keydown.enter=\"setActivePage(total)\"\n          @click.prevent=\"setActivePage(total)\">\n          {{ total }}\n        </component>\n      </template>\n    </div>\n    <component\n      :is=\"numberElement\"\n      :to=\"!!useLinkElement ? getLinkPath(active + 1 <= total ? active + 1 : total) : undefined\"\n      :aria-disabled=\"active >= total\"\n      :tabindex=\"active >= total ? -1 : 0\"\n      :class=\"[\n        'base-pagination__arrow',\n        { 'base-pagination__arrow-icon-inactive': active >= total },\n      ]\"\n      :aria-label=\"getI18nTerm(assistiveText.nextPage)\"\n      @click.prevent=\"active + 1 <= total && !useLinkElement\n        ? setActivePage(active + 1) : false\"\n      @keydown.enter=\"active + 1 <= total && !useLinkElement ? setActivePage(active + 1) : null\">\n      <BaseIcon\n        class=\"base-pagination__arrow-icon base-pagination__arrow-icon-right\"\n        name=\"arrow-left\" />\n    </component>\n  </nav>\n</template>\n\n<style lang=\"scss\">\n  @use \"@/styles/variables\" as *;\n\n  .base-pagination {\n    text-align: center;\n    margin-top: $spacing;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n\n    .base-pagination__arrow, .base-pagination__number {\n      cursor: pointer;\n    }\n\n    .base-pagination__row {\n      display: flex;\n      align-items: center;\n      justify-content: center;\n\n      .base-pagination__number {\n        position: relative;\n        font-weight: bold;\n        background-color: $box-color;\n        padding: 0 $spacing-small;\n        height: 2 * $spacing;\n        min-width: 2 * $spacing;\n        margin-right: $spacing-small;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        transition: all 0.2s ease;\n\n        &:last-child {\n          margin-right: 0;\n        }\n\n        &:hover, &:focus, &:active, &:focus-within {\n          color: $app-color;\n        }\n\n        &.base-pagination__number-active {\n          color: white;\n          background-color: $app-color;\n          cursor: default;\n\n          &:hover {\n            color: white;\n          }\n        }\n        .base-pagination__link {\n          position: absolute;\n          height: 100%;\n          width: 100%;\n        }\n      }\n\n      .base-pagination__more {\n        margin-right: $spacing-small;\n      }\n    }\n\n    .base-pagination__arrow {\n      &:hover .base-pagination__arrow-icon,\n      &:active .base-pagination__arrow-icon,\n      &:focus .base-pagination__arrow-icon {\n        fill: $app-color;\n      }\n\n      .base-pagination__arrow-icon {\n        height: $icon-medium;\n        width: $icon-medium;\n        margin: 0 $spacing;\n\n        &.base-pagination__arrow-icon-right {\n          transform: rotate(180deg);\n        }\n      }\n\n      &.base-pagination__arrow-icon-inactive {\n        cursor: default;\n\n        .base-pagination__arrow-icon,\n        &:hover .base-pagination__arrow-icon {\n          fill: $graytext-color;\n        }\n      }\n    }\n\n    .base-pagination__row, .base-pagination__arrow-icon {\n      flex: 0 0 auto;\n    }\n\n    .base-pagination__arrow, .base-pagination__number {\n      outline: none;\n    }\n  }\n\n  @media screen and (max-width: $mobile) {\n    .base-pagination__arrow-icon {\n      margin: 0 $spacing-small;\n    }\n  }\n</style>\n","<script setup>\nimport { ref, watch, onUnmounted, useTemplateRef } from 'vue';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\nimport BaseLoader from '@/components/BaseLoader/BaseLoader.vue';\n\n/**\n * Viewer to render a PDF with multiple pages.\n * Optional render with a higher resolution for zooming, e.g. in [BaseMediaCarousel](BaseMediaCarousel).\n *\n * Lifecycle and integration notes:\n * - Uses lazy-loading (via `useElementObserver`) to load only when entering the viewport.\n * - Supports pausing and resuming rendering via the exposed `stopRendering` and `resumeRendering` methods,\n *   enabling integration with parent components.\n */\n\ndefineOptions({\n  name: 'BasePdfViewer',\n});\n\nconst props = defineProps({\n  /**\n   * path or URL to the PDF file to display\n   */\n  src: {\n    type: String,\n    required: true,\n  },\n  /**\n   * default target width (in pixels) used when zoom is disabled\n   */\n  initialWidth: {\n    type: Number,\n    default: 1000,\n  },\n  /**\n   * whether to render pages at a higher \"zoomWidth\" for better detail\n   */\n  zoom: {\n    type: Boolean,\n    default: true,\n  },\n  /**\n   * target width (in pixels) used when zoom is enabled\n   */\n  zoomWidth: {\n    type: Number,\n    default: 2500,\n  },\n});\n\nconst emits = defineEmits([\n  /**\n   * event triggered when pdfjs fails to render the PDF\n   * @event error\n   * @param {boolean}\n   */\n  'error',\n  /**\n   * event triggered when pdfjs lib is loaded and PDF is loaded\n   * Note: needed to toggle the BaseRangeSlider in BaseMediaCarousel\n   * @event initialized\n   * @param {boolean}\n   */\n  'initialized',\n]);\n\n/**\n * reference to the container where canvas elements (PDF pages) will be inserted.\n * bound via <div ref=\"canvasContainer\" /> in the template.\n */\nconst canvasContainer = useTemplateRef('canvasContainerEl');\n\n/**\n * state of component\n * used to cancel current render tasks\n */\nconst mounted = ref(true);\n\n/**\n * controls visibility of the loading spinner while fetching or rendering pages\n */\nconst isLoading = ref(false);\n\n/**\n * the loaded PDF document object from pdf.js\n * null until successfully loaded\n */\nlet pdfDoc = null;\n\n/**\n * tracks the current rendering version,\n * incremented to cancel obsolete rendering tasks during re-rendering\n */\nconst renderVersion = ref(0);\n\n/**\n * tracks the last successfully rendered page number,\n * allowing rendering to resume from where it left off\n */\nconst lastRenderedPage = ref(0);\n\n/**\n * controls page rendering\n */\nconst renderPagesAllowed = ref(true);\n\n/**\n * indicates whether all PDF pages have finished rendering\n */\nconst allPagesRendered = ref(false);\n\n/**\n * Dynamically imports pdf.js (and its worker) and loads the specified PDF file.\n * @param {string} src - path or URL to the PDF file\n * @returns {Promise<PDFDocumentProxy>}\n */\nasync function loadPdf(src) {\n  const pdfjsLib = await import('pdfjs-dist/build/pdf.mjs');\n  const pdfjsWorker = await import('pdfjs-dist/build/pdf.worker.mjs?url');\n  pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker.default;\n  return pdfjsLib.getDocument(src).promise;\n}\n\n/**\n * Computes the scaling factor for a PDF page based on its natural width\n * and the current zoom settings.\n * @param {number} naturalWidth - Original page width from PDF metadata.\n * @returns {number} - The scale to apply when rendering.\n */\nfunction getScaleForPage(naturalWidth) {\n  return (props.zoom ? props.zoomWidth : props.initialWidth) / naturalWidth;\n}\n\n/**\n * Renders all pages of the loaded PDF into canvas elements.\n * Cancels previously executed renderings.\n * @param {number} startPage page number to start rendering\n */\nasync function renderPages(startPage = 1) {\n  if (!canvasContainer.value || !pdfDoc) return;\n\n  renderVersion.value++;\n  const newVersion = renderVersion.value;\n  isLoading.value = true;\n  allPagesRendered.value = false;\n\n  // create empty canvases for all pages up front\n  if (startPage === 1) {\n    const fragment = document.createDocumentFragment();\n    const canvases = Array.from({ length: pdfDoc.numPages }, () => {\n      const c = document.createElement('canvas');\n      c.style.marginBottom = '16px';\n      return c;\n    });\n    canvases.forEach((canvas) => fragment.appendChild(canvas));\n    canvasContainer.value.innerHTML = '';\n    canvasContainer.value.appendChild(fragment);\n\n    lastRenderedPage.value = 0;\n  }\n\n  // render each page\n  for (let pageNum = startPage, n = pdfDoc.numPages; pageNum <= n; pageNum++) {\n    // stop the current page rendering when a new render version is requested\n    // or the component is unmounted\n    // or render pages is not allowed (due external event)\n    if (newVersion !== renderVersion.value || !mounted.value || !renderPagesAllowed.value) break;\n\n    // define page properties\n    const page = await pdfDoc.getPage(pageNum);\n    const naturalViewport = page.getViewport({ scale: 1 });\n    const scale = getScaleForPage(naturalViewport.width);\n    const viewport = page.getViewport({ scale });\n    const canvas = canvasContainer.value.children[pageNum - 1];\n    const context = canvas.getContext('2d');\n    canvas.width = Math.floor(viewport.width);\n    canvas.height = Math.floor(viewport.height);\n    // prepare page to render\n    const task = page.render({ canvasContext: context, viewport });\n\n    try {\n      await task.promise;\n      // check the renderVersion to ensure that outdated rendering loops cannot\n      // overwrite the current lastRenderedPage state\n      if (newVersion === renderVersion.value) lastRenderedPage.value = pageNum;\n    } catch (e) {\n      if (e?.name !== 'RenderingCancelledException') {\n        console.error('PDF render error:', e);\n        emits('error', true);\n      }\n    }\n  }\n\n  if (newVersion === renderVersion.value) {\n    isLoading.value = false;\n    renderPagesAllowed.value = false;\n    allPagesRendered.value = lastRenderedPage.value >= pdfDoc.numPages;\n  }\n}\n\n/**\n * Loads the PDF document and triggers rendering\n * @param {string} src - path or URL to the PDF file\n */\nasync function renderPdf(src) {\n  if (typeof window === 'undefined' || !canvasContainer.value) return;\n\n  isLoading.value = true;\n  pdfDoc = null;\n\n  try {\n    pdfDoc = await loadPdf(src);\n    emits('initialized');\n    await renderPages();\n  } catch (err) {\n    console.error('PDF load error:', err);\n    emits('error', true);\n    isLoading.value = false;\n  }\n}\n\n/**\n * Stops any further rendering of PDF pages\n * - Sets the `renderPagesAllowed` flag to `false` so the current render loop will exit.\n * - Any pages already rendered remain visible.\n * - The `lastRenderedPage` state is preserved so rendering can resume later.\n * - Intended for cases where the component is hidden (e.g. when the slide becomes inactive in a carousel).\n */\nfunction stopRendering() {\n  renderPagesAllowed.value = false;\n}\n\n/**\n * Resumes rendering of the remaining PDF pages.\n * - Sets the `renderPagesAllowed` flag to `true`.\n * - Skips execution if all pages have already been rendered.\n * - Calls `renderPages` starting at `lastRenderedPage + 1`, so previously rendered pages are reused.\n * - Useful when the component becomes visible again (e.g. when the slide becomes active in a carousel).\n */\nfunction resumeRendering() {\n  renderPagesAllowed.value = true;\n  if (!pdfDoc || allPagesRendered.value) return;\n  renderPages(lastRenderedPage.value + 1);\n}\n\n/**\n * lazy-load PDF only when it enters the viewport\n * Note: needed for usage in BaseMediaCarousel\n */\nuseElementObserver({\n  type: 'intersection',\n  target: canvasContainer,\n  callback: () => {\n    if (props.src) renderPdf(props.src);\n  },\n  options: {\n    triggerCallbackWhenInViewport: true,\n    stopObservingWhenInViewport: true,\n  },\n});\n\n/**\n * Cancel all renders if the component unmounts\n */\nonUnmounted(() => mounted.value = false);\n\n/**\n * Reload PDF when the `src` changes (only if one is already loaded)\n */\nwatch(() => props.src, (newSrc) => {\n  if (newSrc && pdfDoc) renderPdf(newSrc);\n});\n\n/**\n * watch for zoom changes and trigger re-render\n */\nwatch(() => [props.zoom, props.zoomWidth], () => {\n  renderPagesAllowed.value = true;\n  lastRenderedPage.value = 0;\n  renderPages();\n});\n\n// With composition API we need to specifically expose variables and functions that\n// should be available from outside.\ndefineExpose({\n  /**\n   * Function to stop any further rendering of PDF pages. <br>\n   * The `lastRenderedPage` state is preserved so rendering can resume later.\n   */\n  stopRendering,\n  /**\n   * Function to render the remaining PDF pages.\n   */\n  resumeRendering,\n});\n</script>\n\n<template>\n  <div\n    class=\"base-pdf-viewer\"\n    :style=\"{ '--maxWidth': `${initialWidth}px` }\">\n    <!-- Loader shown while PDF is loading or rendering -->\n    <BaseLoader\n      v-if=\"isLoading\"\n      class=\"base-pdf-viewer__loader\" />\n    <!-- Container for rendered PDF pages -->\n    <div\n      ref=\"canvasContainerEl\"\n      class=\"base-pdf-viewer__container\" />\n  </div>\n</template>\n\n<style lang=\"scss\">\n@use \"@/styles/variables\" as *;\n\n.base-pdf-viewer {\n  canvas {\n    width: 100%;\n    max-width: 100%;\n  }\n}\n</style>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n.base-pdf-viewer {\n  height: 100%;\n  min-height: 1px;\n\n  &__container {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    overflow-y: auto;\n    height: 100%;\n    max-width: var(--maxWidth);\n  }\n}\n</style>\n","<script>\nimport { defineAsyncComponent, useTemplateRef, watchEffect } from 'vue';\nimport { useTabKeyHandler } from '@/composables/useTabKeyHandler.js';\nimport { usePopUpLock } from '@/composables/usePopUpLock.js';\nimport BaseButton from '@/components/BaseButton/BaseButton.vue';\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\n\n/**\n * A component as overlay to display messages\n *\n */\n\nexport default {\n  name: 'BasePopUp',\n  components: {\n    BaseIcon,\n    BaseButton,\n    BaseLoader: defineAsyncComponent(() => import('@/components/BaseLoader/BaseLoader.vue')),\n  },\n  props: {\n    /**\n     * pop up header text\n     */\n    title: {\n      type: String,\n      default: 'Pop Up',\n    },\n    /**\n     * customize the popup header id.\n     *  if you are using the `header-title` slot this should also be set as id on your custom title element\n     */\n    headerId: {\n      type: [String, Number],\n      default: 'popup-title',\n    },\n    /**\n     * specify the id of the element containing a description - for accessibility only\n     */\n    descriptionElementId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * text shown in left button\n     */\n    buttonLeftText: {\n      type: String,\n      default: 'Cancel',\n    },\n    /**\n     * text shown in right button\n     */\n    buttonRightText: {\n      type: String,\n      default: 'Submit',\n    },\n    /**\n     * icon shown in left button\n     */\n    buttonLeftIcon: {\n      type: String,\n      default: 'remove',\n    },\n    /**\n     * icon shown in right button\n     */\n    buttonRightIcon: {\n      type: String,\n      default: 'check-mark',\n    },\n    /**\n     * disable right button\n     */\n    buttonRightDisabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * disable close button\n     */\n    closeButtonDisabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if true button loader will be shown\n     */\n    isLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * HTMLElement to focus after opening the popup\n     * **Note:** If empty, the header title will be focused by default.\n     *           If using the slot for a custom header, be sure to\n     *           define an id attribute with the value `popup-title`\n     *           The value should be a valid CSS selector.\n     * **useful IDs:**\n     * - left-button: `popup-left-button`\n     * - right-button: `popup-right-button`\n     */\n    initialFocusElement: {\n      type: String,\n      default: '',\n    },\n    /**\n     * specify to render component with max height and width\n     */\n    fullscreenOnMobile: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * list of focusable HTML elements using tab key navigation\n     */\n    focusableElements: {\n      type: Array,\n      // also add all elements in general that have a tabindex, except the ones with value -1\n      default: () => ['a[href]', 'button:enabled', 'input:enabled', '*[tabindex]:not([tabindex=\"-1\"])'],\n    },\n    /**\n     * specify to disable the tab key handler within the component\n     */\n    disableTabKeyHandler: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * button row visibility\n     */\n    showButtonRow: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * define if the overlay background should be visible\n     * (semitransparent black)\n     */\n    overlayBackgroundVisible: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['button-left', 'button-right', 'close'],\n  setup(props) {\n    // get the pop up body ref for scroll lock\n    const popUpBody = useTemplateRef('popUpBodyEl');\n\n    /** SCROLL LOCK HANDLING */\n      // set scroll lock\n    const { toggleScrollLock } = usePopUpLock(popUpBody);\n\n    /** TAB KEY HANDLING */\n      // init tab key handler\n    const { focusableHTMLTags, disableHandler } = useTabKeyHandler(popUpBody, props.focusableElements.join(', '), props.disableTabKeyHandler);\n    // watcher to set specific properties\n    watchEffect(() => {\n      focusableHTMLTags.value = props.focusableElements;\n      disableHandler.value = props.disableTabKeyHandler;\n    });\n\n    return {\n      popUpBody,\n      toggleScrollLock,\n    };\n  },\n  data() {\n    return {\n      // HTML element that should be focused when the component is closed\n      prevActiveElement: undefined,\n    };\n  },\n  mounted() {\n    this.toggleScrollLock(true);\n    document.onkeyup = (e) => {\n      const { key } = e;\n      if (document.querySelector('.popup-box')) {\n        if (!this.closeButtonDisabled && key === 'Escape') {\n          const btn = document.querySelector('.popup-box .base-popup__close-button');\n          btn.dispatchEvent(new Event('click'));\n        }\n      }\n    };\n    // also set the previously active element so it can be used to return to\n    // if pop up is closed\n    this.prevActiveElement = document.activeElement;\n    this.$nextTick(() => {\n      this.determineFocus();\n    });\n  },\n  beforeUnmount() {\n    // when the popup is closed, try to focus the previous triggering element\n    if (this.prevActiveElement) {\n      this.prevActiveElement.focus();\n      this.prevActiveElement = false;\n    }\n  },\n  methods: {\n    close() {\n      /**\n       * Event triggered on right top corner close action\n       *\n       * @event close\n       */\n      this.$emit('close');\n    },\n    buttonRight() {\n      /**\n       * Event triggered with right button\n       *\n       * @event button-right\n       */\n      this.$emit('button-right');\n    },\n    buttonLeft() {\n      /**\n       * Event triggered with left button\n       *\n       * @event button-left\n       */\n      this.$emit('button-left');\n    },\n\n    /** INITIAL FOCUS */\n    determineFocus() {\n      // try to focus the element defined with the initialFocusElement property\n      if (!!this.initialFocusElement && this.$el?.querySelector(this.initialFocusElement)) {\n        this.$el.querySelector(this.initialFocusElement).focus();\n        // or the popup title\n      } else if (this.$el?.querySelector(`#${this.headerId}`)) {\n        this.$el.querySelector(`#${this.headerId}`).focus();\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    :class=\"['base-pop-up',\n             { 'base-pop-up--fullscreen-on-mobile': fullscreenOnMobile }]\">\n    <div\n      :class=\"[\n        'base-pop-up__background',\n        { 'base-pop-up__background--visible': overlayBackgroundVisible },\n      ]\" />\n    <div\n      ref=\"popUpBodyEl\"\n      :aria-labelledby=\"headerId\"\n      :aria-describedby=\"descriptionElementId\"\n      role=\"alertdialog\"\n      aria-modal=\"true\"\n      class=\"popup-box\">\n      <!-- POP UP HEADER -->\n      <div class=\"popup-header\">\n        <!-- @slot add a custom header title instead of the text defined with the prop `title`.\n          @binding header-id {string, number} - set this id on your custom element as it is used by the aria-labelledby attribute of the pop up container -->\n        <slot\n          name=\"header-title\"\n          :header-id=\"headerId\">\n          <div\n            :id=\"headerId\"\n            tabindex=\"-1\"\n            class=\"popup-title\">\n            {{ title }}\n          </div>\n        </slot>\n        <!-- @event close -->\n        <button\n          v-if=\"!closeButtonDisabled\"\n          type=\"button\"\n          aria-label=\"close pop up\"\n          class=\"base-popup__close-button\"\n          @click=\"close\">\n          <BaseIcon\n            class=\"popup-remove\"\n            name=\"remove\" />\n        </button>\n      </div>\n\n      <!-- POP UP CONTENT -->\n      <div class=\"popup-content\">\n        <!-- @slot slot to fill the body of the box with custom content -->\n        <slot />\n        <div\n          v-if=\"showButtonRow\"\n          class=\"popup-button-row\">\n          <!-- @slot custom button row -->\n          <slot name=\"button-row\">\n            <BaseButton\n              id=\"popup-left-button\"\n              :text=\"buttonLeftText\"\n              :icon=\"buttonLeftIcon\"\n              :icon-position=\"'right'\"\n              :icon-size=\"'small'\"\n              class=\"base-popup-button\"\n              @clicked=\"buttonLeft\" />\n            <BaseButton\n              id=\"popup-right-button\"\n              :text=\"buttonRightText\"\n              :icon=\"!isLoading ? buttonRightIcon : ''\"\n              :icon-position=\"'right'\"\n              :icon-size=\"'small'\"\n              :disabled=\"buttonRightDisabled\"\n              class=\"base-popup-button\"\n              @clicked=\"buttonRight\">\n              <template\n                #right-of-text>\n                <span\n                  v-show=\"isLoading\"\n                  class=\"base-popup-button-loader\">\n                  <BaseLoader />\n                </span>\n              </template>\n            </BaseButton>\n          </slot>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n  @use \"@/styles/variables\" as *;\n\n  .base-pop-up {\n    .base-pop-up__background {\n      position: fixed;\n      top: 0;\n      left: 0;\n      height: 100%;\n      width: 100%;\n      /* specific to be higher than base header */\n      z-index: map.get($zindex, modal_bg);\n      overflow: hidden;\n\n      &.base-pop-up__background--visible {\n        background: $overlay-background-light;\n      }\n    }\n\n    .popup-box {\n      box-shadow: $pop-up-shadow;\n      position: fixed;\n      top: 20vh;\n      left: 50%;\n      z-index: map.get($zindex, modal);\n      min-width: 288px;\n      width: 50%;\n      max-width: 700px;\n      display: flex;\n      flex-direction: column;\n      transform: translateX(-50%);\n\n      .popup-header {\n        background-color: $button-header-color;\n        height: $row-height-large;\n        padding: 0 #{$spacing};\n        display: flex;\n        flex-direction: row;\n        justify-content: space-between;\n        align-items: center;\n        flex-shrink: 0;\n\n        .popup-title {\n          margin-right: $spacing-small;\n          display: -webkit-box;\n          -webkit-line-clamp: 2;\n          -webkit-box-orient: vertical;\n          overflow: hidden;\n        }\n\n        .base-popup__close-button {\n          &:active, &:focus {\n            color: $app-color;\n            fill: $app-color;\n          }\n\n          .popup-remove {\n            width: $icon-medium;\n            min-width: $icon-medium;\n            cursor: pointer;\n          }\n        }\n      }\n\n      .popup-content {\n        padding: $spacing;\n        background-color: white;\n\n        .popup-button-row {\n          margin-top: $spacing;\n          display: flex;\n          flex-direction: row;\n\n          /* TODO: check if button size should just be adjustable via props in general\" */\n          .base-popup-button {\n            margin-right: $spacing;\n            // width: calc(50% - 8px);\n            flex-basis: 50%;\n          }\n\n          & .base-popup-button:last-child {\n            margin-right: 0;\n          }\n\n          .base-popup-button-loader {\n            position: relative;\n            transform: scale(0.5);\n            margin-left: $spacing;\n            padding-left: $spacing;\n          }\n        }\n      }\n    }\n  }\n\n  @media screen and (max-width: $tablet) {\n    .base-pop-up {\n      .popup-box {\n        max-width: 100%;\n        width: 70%;\n      }\n    }\n  }\n\n  @media screen and (max-width: $mobile) {\n    .base-pop-up {\n      .popup-box {\n        max-width: 100%;\n        width: 90%;\n        top: 10vh;\n\n        .popup-content {\n          padding: $spacing $spacing-small;\n\n          .popup-button-row {\n            flex-wrap: wrap;\n\n            & .base-popup-button {\n              margin-right: 0;\n              flex-basis: 100%;\n            }\n\n            & .base-popup-button:last-child {\n              margin-top: $spacing-small;\n            }\n          }\n        }\n      }\n\n      &.base-pop-up--fullscreen-on-mobile {\n        .popup-box {\n          top: 0;\n          width: 100%;\n          min-height: 100%;\n          height: 100%;\n\n          .popup-content {\n            display: flex;\n            flex: auto;\n            flex-direction: column;\n\n            .body {\n              flex: auto;\n              align-content: flex-start;\n            }\n          }\n        }\n      }\n    }\n  }\n\n  @media screen and (max-height: 1042px) {\n    .base-pop-up {\n      .popup-box {\n        top: 10vh;\n      }\n    }\n  }\n\n  @media screen and (max-height: 500px) {\n    .base-pop-up {\n      .popup-box {\n        top: 2vh;\n      }\n    }\n  }\n</style>\n","<script>\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport { ref, useTemplateRef } from 'vue';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\n\n/**\n * Progress bar including file upload features (display filename or file size)\n * and remove functionality\n */\n\nexport default {\n  name: 'BaseProgressBar',\n  components: {\n    BaseIcon,\n  },\n  props: {\n    /**\n     * additional error message\n     */\n    errorMessage: {\n      type: String,\n      default: '',\n    },\n    /**\n     * filename that will be displayed in the bar\n     */\n    fileName: {\n      type: String,\n      default: '',\n    },\n    /**\n     * filesize that will be displayed in the bar\n     */\n    fileSize: {\n      type: String,\n      default: '',\n    },\n    /**\n     * progress of the upload (percentage)\n     * @values 0-100\n     */\n    progress: {\n      type: [Number, String],\n      default: 0,\n      validator(val) {\n        return val >= 0 && val <= 100;\n      },\n    },\n    /**\n     * indicate the success or fail of an upload\n     *   @values success, fail, ''\n     */\n    status: {\n      type: String,\n      default: '',\n      validator(val) {\n        return ['success', 'fail', ''].includes(val);\n      },\n    },\n    /**\n     * show a remove icon\n     */\n    showRemove: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['remove-item'],\n  setup() {\n    /** FADE OUT HANDLING */\n    const progressBar = useTemplateRef('progressBarElement');\n    /**\n     * control the fade out showing\n     * @type {Ref<UnwrapRef<boolean>, UnwrapRef<boolean> | boolean>}\n     */\n    const showFadeOut = ref(true);\n    /**\n     * template reference to the file name that might need fade out\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const fileName = useTemplateRef('fileNameElement');\n\n    function calcFadeOut() {\n      showFadeOut.value = fileName.value.scrollWidth > fileName.value.clientWidth;\n    }\n\n    useElementObserver({\n      type: 'resize',\n      target: progressBar,\n      callback: calcFadeOut,\n    });\n\n    return {\n      showFadeOut,\n      calcFadeOut,\n    }\n  },\n  mounted() {\n    this.calcFadeOut();\n  },\n  methods: {\n    remove() {\n      /**\n       * event triggered on remove icon click\n       *\n       * @event remove-item\n       */\n      this.$emit('remove-item');\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    ref=\"progressBarElement\"\n    :aria-valuenow=\"progress\"\n    role=\"progressbar\"\n    aria-valuemin=\"0\"\n    aria-valuemax=\"100\"\n    class=\"base-progress-bar\">\n    <div class=\"base-progress-bar__container\">\n      <div\n        :style=\"{ width: `${progress}%` }\"\n        class=\"base-progress-bar__progress\">\n        <div\n          class=\"base-progress-bar__content\">\n          <div\n            ref=\"fileNameElement\"\n            :class=\"['base-progress-bar__file-name',\n                     { 'base-progress-bar__file-name--fade-out': showFadeOut }]\">\n            {{ fileName }}\n          </div>\n          <span\n            v-if=\"fileSize\"\n            class=\"base-progress-bar__file-size\">\n            {{ fileSize }}\n          </span>\n          <BaseIcon\n            v-if=\"status === 'success'\"\n            class=\"base-progress-bar__status-icon base-progress-bar__status-icon-success\"\n            name=\"success\" />\n          <BaseIcon\n            v-if=\"status === 'fail'\"\n            :title=\"errorMessage\"\n            class=\"base-progress-bar__status-icon base-progress-bar__status-icon-fail\"\n            name=\"attention\" />\n          <BaseIcon\n            v-if=\"showRemove\"\n            class=\"base-progress-bar__status-icon base-progress-bar__status-icon-remove\"\n            name=\"remove\"\n            @click=\"remove\" />\n        </div>\n      </div>\n    </div>\n    <div\n      v-if=\"status === 'fail' && errorMessage\"\n      class=\"base-progress-bar__error-message\">\n      {{ errorMessage }}\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n@use \"@/styles/variables\" as *;\n\n.base-progress-bar {\n  .base-progress-bar__container {\n    font-family: inherit;\n    font-size: inherit;\n    position: relative;\n    width: 100%;\n    height: $row-height-small;\n    background-color: $button-header-color;\n    line-height: $row-height-small;\n  }\n\n  .base-progress-bar__progress {\n    transition: width 0.5s;\n    height: 100%;\n    background-color: $uploadbar-color;\n  }\n\n  .base-progress-bar__content {\n    position: absolute;\n    display: flex;\n    align-items: center;\n    top: 0;\n    left: 0;\n    padding: 0 $spacing;\n    overflow: hidden;\n    white-space: nowrap;\n    width: 100%;\n    height: 100%;\n\n    .base-progress-bar__file-name {\n      overflow: hidden;\n      flex: 1 1 auto;\n      position: relative;\n\n      &.base-progress-bar__file-name--fade-out {\n        background-image: linear-gradient(90deg,#000000 calc(100% - 30px),rgba(0,0,0,0));\n        -webkit-background-clip: text;\n        -webkit-text-fill-color: transparent;\n      }\n    }\n\n    .base-progress-bar__file-size {\n      position: relative;\n      margin-left: auto;\n      flex-shrink: 0;\n      left: $spacing;\n      margin-right: $spacing;\n    }\n\n    .base-progress-bar__status-icon {\n      height: $icon-medium;\n      width: $icon-medium;\n      flex-shrink: 0;\n      margin-left: $spacing;\n\n      &.base-progress-bar__status-icon-success {\n        fill: white;\n      }\n\n      &.base-progress-bar__status-icon-fail {\n        fill: $warning-color;\n      }\n\n      &.base-progress-bar__status-icon-remove {\n        cursor: pointer;\n        fill: $font-color-third;\n      }\n    }\n  }\n\n  .base-progress-bar__error-message {\n    font-size: $font-size-small;\n    color: $warning-color;\n  }\n}\n</style>\n","<script setup>\nimport {ref, watch } from 'vue';\nimport { useId } from '@/composables/useId.js';\nimport BaseButton from '@/components/BaseButton/BaseButton.vue';\n\n/**\n * Input range slider with additional buttons to increase/decrease the current value\n */\n\ndefineOptions({\n  name: 'BaseRangeSlider',\n});\n\nconst props = defineProps({\n  /**\n   * specify the current range value\n   */\n  modelValue: {\n    type: Number,\n    default: 0,\n  },\n  /** label for the input range field\n   */\n  label: {\n    type: String,\n    default: 'Range slider',\n  },\n  /**\n   * specify the min range value\n   */\n  min: {\n    type: Number,\n    default: 0,\n    validator(val) {\n      return val >= 0;\n    },\n  },\n  /**\n   * specify the max range value\n   */\n  max: {\n    type: Number,\n    default: 100,\n  },\n  /**\n   * specify the step size to increase/decrease the value\n   */\n  step: {\n    type: Number,\n    default: 10,\n  },\n  /**\n   * set `true` if input field should be disabled\n   */\n  disabled: {\n    type: Boolean,\n    default: false,\n  },\n  /**\n   * this prop gives the option to add assistive text for screen readers\n   * properties:\n   * **increase**: text for the increase button\n   * **decrease**: text for the decrease button\n   */\n  assistiveText: {\n    type: Object,\n    default: () => ({\n      increase: 'increase value',\n      decrease: 'decrease value',\n    }),\n  },\n});\n\n/**\n * event triggered when range value changes\n * @event update:model-value\n * @param {number} - the current range value\n */\nconst emits = defineEmits([\n  'update:model-value',\n]);\n\n/** INTERNAL ID */\nconst internalId = useId();\n\n/** current value - model */\nconst currentValue = ref();\n\n/**\n * count decimals of a number\n * @param number - number to analyse\n * @returns {number} number of decimals\n */\nfunction countDecimals(number) {\n  const str = number.toString();\n  return str.includes('.') ? str.split('.')[1].length : 0;\n}\n\n/**\n * increase/decrease value, respect min and max values\n * @param {number} stepSize\n */\nfunction stepper(stepSize) {\n  let newValue = +currentValue.value + stepSize;\n  if (newValue < props.min) newValue = 0;\n  if (newValue > props.max) newValue = props.max;\n  currentValue.value = newValue.toFixed(countDecimals(props.step));\n}\n\n/**\n * keep externally set modelValue variable and internal currentValue variable in sync\n * @param {number} newValue\n */\nwatch(() => props.modelValue, (newValue) => {\n  currentValue.value = newValue;\n}, {\n  immediate: true,\n});\n\n/**\n * watch internal input variable to inform parent of changes if necessary\n * @param {number} newValue\n */\nwatch(() => currentValue.value, (newValue) => {\n  emits('update:model-value', Number(newValue));\n}, {});\n</script>\n\n<template>\n  <div\n    class=\"base-range-slider\">\n    <!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->\n    <label\n      :for=\"`base-range-slider-${internalId}`\"\n      class=\"base-range-slider__label\">\n      Slider\n    </label>\n    <input\n      :id=\"`base-range-slider-${internalId}`\"\n      v-model=\"currentValue\"\n      type=\"range\"\n      :min=\"min\"\n      :max=\"max\"\n      :step=\"step\"\n      :disabled=\"disabled\"\n      :name=\"`base-range-slider-${internalId}`\">\n    <BaseButton\n      icon=\"minus\"\n      icon-position=\"left\"\n      icon-size=\"small\"\n      button-style=\"row\"\n      :disabled=\"disabled || modelValue === min\"\n      :description=\"assistiveText.decrease\"\n      class=\"base-range-slider__button\"\n      @clicked=\"stepper(-step)\" />\n    <BaseButton\n      icon=\"plus\"\n      icon-position=\"left\"\n      icon-size=\"small\"\n      button-style=\"row\"\n      :disabled=\"disabled || modelValue === max\"\n      :description=\"assistiveText.increase\"\n      :step=\"step\"\n      class=\"base-range-slider__button\"\n      @clicked=\"stepper(step)\" />\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n\n\n.base-range-slider {\n  display: flex;\n  box-shadow: $box-shadow-reg;\n  transition: $box-transition;\n  background-color: $background-color;\n  min-height: $row-height-large;\n\n  &__label {\n    display: none;\n  }\n\n  &__button {\n    margin-left: $border-width;\n  }\n\n  input[type=\"range\"] {\n    display: none;\n\n    @media screen and (min-width: $mobile) {\n      display: block;\n    }\n  }\n\n  input[type=\"range\"] {\n    background-color: #fff;\n    width: 100%;\n    -webkit-appearance: none;\n    appearance: none;\n    cursor: pointer;\n    padding: $spacing;\n  }\n\n  /***** Chrome, Safari, Opera, and Edge Chromium *****/\n  input[type=\"range\"]::-webkit-slider-runnable-track {\n    -webkit-appearance: unset; /* Override default look */\n    appearance: unset;\n    background: $background-color;\n    height: 2px;\n  }\n\n  /******** Firefox ********/\n  input[type=\"range\"]::-moz-range-track {\n    background: $background-color;\n    height: 2px;\n  }\n\n  /***** Chrome, Safari, Opera, and Edge Chromium *****/\n  input[type=\"range\"]::-webkit-slider-thumb {\n    -webkit-appearance: none; /* Override default look */\n    /* appearance: unset; */\n    border: none;\n    background-color: black;\n    height: 20px;\n    width: 20px;\n    border-radius: 50%;\n    margin-top: -10px;\n    transition: background-color 0.2s ease-in-out;\n  }\n\n  input[type=\"range\"]:focus::-webkit-slider-thumb {\n    background-color: $app-color-secondary;\n  }\n\n  input[type=\"range\"]:disabled::-webkit-slider-thumb {\n    background-color: $font-color-third;\n  }\n\n  /***** Firefox *****/\n  input[type=\"range\"]::-moz-range-thumb {\n    border: none;\n    background-color: black;\n    transition: background-color 0.2s ease-in-out;\n  }\n\n  input[type=\"range\"]:focus::-moz-range-thumb {\n    background-color: $app-color-secondary;\n  }\n\n  input[type=\"range\"]:disabled::-moz-range-thumb {\n    background-color: $font-color-third;\n  }\n\n  input[type=\"range\"]:disabled {\n    cursor: default;\n  }\n}\n</style>\n","<script>\nimport { defineAsyncComponent, ref, useTemplateRef, watch } from 'vue';\nimport { useI18n } from '@/composables/useI18n.js';\nimport { extractNestedPropertyValue } from '@/utils/utils.js';\nimport { useId } from '@/composables/useId.js';\nimport { useWindowResize } from '@/composables/useWindowResize.js';\nimport BaseImageBox from '@/components/BaseImageBox/BaseImageBox.vue';\n\n/**\n * A component to display rows of boxes with or without pagination\n */\nexport default {\n  name: 'BaseResultBoxSection',\n  components: {\n    BaseImageBox,\n    BaseLoader: defineAsyncComponent(() => import('@/components/BaseLoader/BaseLoader.vue')),\n    BaseOptions: defineAsyncComponent(() => import('@/components/BaseOptions/BaseOptions.vue')),\n    BaseButton: defineAsyncComponent(() => import('@/components/BaseButton/BaseButton.vue')),\n    BasePagination: defineAsyncComponent(() => import('@/components/BasePagination/BasePagination.vue')),\n    BaseBoxButton: defineAsyncComponent(() => import('@/components/BaseBoxButton/BaseBoxButton.vue')),\n    BaseSelectOptions: defineAsyncComponent(() => import('@/components/BaseSelectOptions/BaseSelectOptions.vue')),\n  },\n  props: {\n    /**\n     * actual entries list - if slot `result-box` is not used to use custom elements this\n     * object array should have the following properties to be displayed\n     * in a [BaseImageBox](BaseImageBox):\n     *\n     *    **id** `string` - a unique identifier\n     *    **title** `?string` - the title of the box\n     *    **subtext** `?string` - a subtitle\n     *    **description** `?string` - text displayed at the bottom of the box\n     *    **imageUrl** `?string` - url to display an image\n     *    **text** `?string[]` - an array with strings that will be\n     *    displayed if no image is provided\n     *\n     *    if a different schema is used please use the slot 'result-box' to create your own\n     *    elements - only id and title should still be provided but can also\n     *    be customized via `identifierPropertyName` and `titlePropertyName`\n     */\n    modelValue: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * if `false` the header row (title and options) will not be available\n     *   **Caveat**: for draggable functionality this needs to be true\n     */\n    showHeader: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * title of section\n     * it is recommended to also set the `headerText` even if slot `header` is used for header\n     * for accessibility reasons\n     */\n    headerText: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define if options should be shown\n     */\n    showOptions: {\n      type: Boolean,\n      default: true,\n    },\n    /**\n     * set text for the options button if `showOptions` is `true`\n     *   this needs to be an object with `show` (displayed when options are hidden)\n     *   and `hide` (displayed when options are visible) attributes\n     */\n    optionsButtonText: {\n      type: Object,\n      default: () => ({\n        show: 'edit',\n        hide: 'editReturn',\n      }),\n      validator: val => ['show', 'hide'].every(requiredProp => Object.keys(val).includes(requiredProp)),\n    },\n    /**\n     * set the icon for the options button.\n     * if `showOptions` is `true` this needs to be an object with `show`\n     *  (displayed when options are hidden) and `hide` (displayed when\n     *  options are visible) attributes\n     */\n    optionsButtonIcon: {\n      type: Object,\n      default: () => ({\n        show: 'edit',\n        hide: 'remove',\n      }),\n      validator: val => ['show', 'hide'].every(requiredProp => Object.keys(val).includes(requiredProp)),\n    },\n    /**\n     * specify how many boxes should be displayed in a row in an array\n     * with \"tupples\" (array with min-size and number of boxes).\n     * depending on the size of the container (not screen width - unless\n     * `calcBoxNumberRelativeToWindow` is set to `true`)\n     * like the following:\n     *   `[[0, [number of boxes]], [[min px size for this number of boxes], [number of boxes]], ...]`\n     */\n    boxBreakpoints: {\n      type: Array,\n      default: () => ([\n        [0, 2],\n        [640, 4],\n        [1024, 6],\n      ]),\n      validator: val => val\n        .every(point => typeof point === 'object' && point.length === 2\n          && point.every(pointValue => typeof pointValue === 'number')),\n    },\n    /**\n     * set component loader active\n     */\n    isLoading: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * flag if component should be in edit mode (dragging, deleting,\n     * other custom options visible)\n     *   the v-model directive may be used on this prop\n     */\n    editMode: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set this variable `true` if `background-color` should be white in edit mode\n     */\n    editModeWhiteBackground: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * provide a list of selected entries for select options (can\n     * be entry objects or entry ids).\n     *  the v-model directive may be used on this prop\n\n     */\n    selectedList: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * set a text for '[x] entries selected' and 'select all / none'\n     */\n    selectOptionsText: {\n      type: Object,\n      default: () => ({\n        selectAll: 'select all',\n        selectNone: 'select none',\n        entriesSelected: 'entries selected',\n      }),\n    },\n    /**\n     * if slot `options-message-area` is not used this variable\n     * can be used to customize message text.\n     *   this should be a string or an object with the actions needed (default: `delete`,\n     *   if `draggable` is `true` than also a `drag` property with suiting text is needed).\n     *     in case of a string the same text is used for all actions\n     */\n    messageText: {\n      type: String,\n      default: 'Drag or Select',\n    },\n    /**\n     * if slot `options-message-area` is not used this variable\n     * can be used to customize message subtext.\n     *   this should be a string or an object with the actions needed (default: `delete`,\n     *   if `draggable` is `true` than also a `drag` property with suiting text is needed).\n     *     in case of a string the same text is used for all actions\n     */\n    messageSubtext: {\n      type: String,\n      default: 'Drag\\'n Drop to reorder or select the relevant items and choose an action',\n    },\n    /**\n     * determine if boxes can be dragged\n     *   (only applicable if `showHeader` and `showOptions` is set to `true`)\n     */\n    draggable: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set `true` if pagination should be used\n     */\n    usePagination: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `usePagination` is set `true` this will determine the number of\n     * rows shown on one page\n     *   (only applicable if `usePagination` is set `true`)\n     */\n    maxRows: {\n      type: Number,\n      default: 5,\n    },\n    /**\n     * set this `true` if only a limited number of boxes should be shown\n     * and rest can be displayed by clicking a \"show more\" button\n     */\n    useExpandMode: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if `useExpandMode` is `true` set the state of 'show more' from outside\n     *   the v-model directive may be used on this prop\n     */\n    expanded: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * Provide text that should be shown within the button with the\n     * expand / collapse functionality.\n     *   should be an object with props `expand` for text to expand\n     *   and `collapse` for text to collapse\n     */\n    expandText: {\n      type: Object,\n      default: () => ({\n        expand: 'more objects',\n        collapse: 'collapse',\n      }),\n    },\n    /**\n     * add a number of total elements (needed for `useExpandMode` and\n     * `usePagination`)\n     */\n    total: {\n      type: Number,\n      default: null,\n    },\n    /**\n     * set the current page number from outside if `usePagination` is `true`.\n     *   the v-model directive may be used on this prop\n     */\n    currentPageNumber: {\n      type: Number,\n      default: 1,\n    },\n    /**\n     * how many rows should be shown with show more button (expandMode)\n     *   (only applicable with `useExpandMode true`)\n     */\n    maxShowMoreRows: {\n      type: Number,\n      default: 1,\n    },\n    /**\n     * define if the section should scroll to top on page change\n     *   (only applicable with `usePagination true`)\n     */\n    jumpToTop: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * define if the big button box at the end of all attached items should be shown\n     */\n    showActionButtonBoxes: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set some config for each action used - needs to be an array of objects with the\n     *  following properties:\n     *\n     *   **text** `string` - the text displayed in the button\n     *   **icon** `string` - the icon name to display\n     *    (for available icons see [BaseIcon](BaseIcon) )\n     *   **value** `string` - the value emitted on button click\n     *   **[display='all']** `?string` - define where the action should be displayed:\n     *     *top*: only in top row\n     *     *bottom*: only in action button box at bottom of list\n     *     *all*: on top as well as bottom\n     *   **disabled** `?boolean` - disable button\n     */\n    actionButtonsConfig: {\n      type: Array,\n      default: () => [{\n        text: 'delete',\n        icon: 'waste-bin',\n        value: 'delete',\n        display: 'all',\n        disabled: false,\n      }],\n      validator: val => val.every((action) => {\n        const requiredProps = ['text', 'icon', 'value'];\n        const actionProps = Object.keys(action);\n        return requiredProps.every(prop => actionProps.includes(prop))\n          && (['all', 'top', 'bottom'].includes(action.display) || !action.display);\n      }),\n    },\n    /**\n     * define a custom identifier property name for objects in your\n     * `modelValue` array.\n     *   if relevant property is contained in a nested object the string can\n     *   be in dot notation. e.g. `nestedObject.id`\n     */\n    identifierPropertyName: {\n      type: String,\n      default: 'id',\n    },\n    /**\n     * define a custom title property name for objects in your\n     * `modelValue` array.\n     *   if relevant property is contained in a nested object the string can\n     *   be in dot notation. e.g. `nestedObject.title`\n     */\n    titlePropertyName: {\n      type: String,\n      default: 'title',\n    },\n    /**\n     * specify if pagination elements should be a link element - if pagination element should\n     * be a link element - please specify the kind of element either as a string (e.g. `'RouterLink'`\n     * or pass the component directly (currently only Vue components (e.g.\n     * [`RouterLink`](https://router.vuejs.org/guide/#router-link),\n     * [`NuxtLink`](https://nuxtjs.org/docs/features/nuxt-components/#the-nuxtlink-component)) are supported)\n     *\n     * **caveat**: if you are using Nuxt the string `'NuxtLink'` is not enough,\n     *  but you need to import the component as `import { NuxtLink } from '#components';`\n     *  and pass the component to the prop!\n     */\n    usePaginationLinkElement: {\n      type: [String, Boolean, Object],\n      default: false,\n      validator: val => (typeof val === 'boolean' && !val)\n        || (typeof val === 'string' && val)\n        || (typeof val === 'object' && val.name && ['NuxtLink', 'RouterLink'].includes(val.name)),\n    },\n    /**\n     * set this variable `true` if pagination is used and data fetching is done per page\n     */\n    fetchDataExternally: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify an additional number of px for the position the page\n     * should jump to on page change\n     */\n    scrollToOffset: {\n      type: Number,\n      default: 0,\n    },\n    /**\n     * specify an initial number of items per row that should be assumed before\n     * rendering the page\n     */\n    // this is necessary because otherwise in SSR serverside and client side DOM tree\n    // might not match\n    initialItemsPerRow: {\n      type: Number,\n      default: 6,\n    },\n    /**\n     * add text for screen reader users that helps them navigate list and use edit mode\n     * functionalities.\n     * object should have the following properties:\n     *\n     *   **description**: Text read on edit mode activation\n     *   **activated**: Text read after item was activated for reordering\n     *    (selected by enter key)\n     *    property moved can contain variable `{pos}` which will be filled with current\n     *    position\n     *   **moved**: Text read after item was moved\n     *    property moved can contain variables `{pos}` (new position) and `{total}` (total number\n     *    of list items)\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        description: 'Select items via space bar to carry out actions or use enter '\n          + 'key to select an item for reordering. Use Tab key to navigate between items.',\n        activated: 'Item at position {pos} selected for reordering. Use arrow keys to order item.',\n        moved: 'Item moved to position {pos} of {total}',\n        loaderActive: 'loading.',\n      }),\n    },\n    /**\n     * this prop gives the option to add assistive text for the pagination:\n     *\n     *   **currentPage**: aria-label for the current page\n     *   **nextPage**: aria-label for the next page\n     *   **pagination**: aria-label for the pagination element description\n     *   **previousPage**: aria-label for the previous page\n     *   **toPage**: aria-label for all page buttons except the current one\n     *\n     * The values of this object might be plain text or a key for an i18n file\n     */\n    paginationAssistiveText: {\n      type: Object,\n      default: () => ({\n        currentPage: 'Current Page, Page',\n        nextPage: 'Go to next page',\n        pagination: 'Pagination',\n        previousPage: 'Go to previous page',\n        toPage: 'Go to page',\n      }),\n    },\n    /**\n     * `BaseResultBoxSection` is for example used to display search results - which contain a link\n     * to the entry - in this case the focus should be on the link element so that navigation to\n     * route link triggers on enter and focus on the list element itself is disabled (if not edit\n     * mode!)\n     */\n    disableListElementFocus: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['entry-clicked', 'items-per-row-changed', 'submit-action', 'update:edit-mode', 'update:expanded', 'update:current-page-number', 'update:selected-list', 'update:model-value'],\n  setup(props, { emit }) {\n    /** INTERNAL ID HANDLING */\n      // unique persistent id to assign javascript calculated styles to\n    const elementId = useId();\n\n    /** BOX DISPLAY FUNCTIONALITIES */\n    /**\n     * a template reference to the root element to be able to add the css variable\n     * for items per row\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const resultBoxSection = useTemplateRef('resultBoxSectionElement');\n    /**\n     * template reference to the boxes container (needed for calculating avaiable space\n     * for boxes)\n     * @type {Readonly<ShallowRef<unknown | null>>}\n     */\n    const resultBoxesArea = useTemplateRef('resultBoxesAreaElement');\n    // how many items do fit in one row\n    const itemsPerRow = ref(props.initialItemsPerRow);\n    // try to only do initial box size calculation once\n    const initialBoxCalcDone = ref(false);\n\n    // recalc box number on window resize\n    useWindowResize({\n      target: 'resultboxsection',\n      callback: calcBoxNumber,\n      setDebounce: 300,\n    })\n\n    /**\n     * calculate the box number according to available space and breaking points set\n     */\n    function calcBoxNumber() {\n      // get the result boxes parent - in case of draggable active this is a vue component\n      // and $el needs to be addressed - otherwise native HTML element can be used directly\n      const resultBoxesElement = resultBoxesArea.value && resultBoxesArea.value.$el\n        ? resultBoxesArea.value.$el : resultBoxesArea.value;\n      // if such an element was found and element has children (= boxes are rendered)\n      if (resultBoxesElement) {\n        // get the element width\n        const totalWidth = resultBoxesElement.clientWidth;\n        // create a copy of the prop to avoid direct prop mutation\n        const boxBreakpointsCopy = [...props.boxBreakpoints];\n        // calculate how many items should be displayed according to\n        // breakpoints set\n        itemsPerRow.value = boxBreakpointsCopy\n          // then also sorting should not be necessary anymore (maybe keep to\n          // be on the save side?\n          .sort((a, b) => a[0] > b[0])\n          // get the correct box number\n          .reduce((prev, [size, number]) => {\n            if (totalWidth > size) {\n              return number;\n            }\n            return prev;\n          }, 0);\n        // set the correct margins for the boxes\n        const nodeId = `base-result-box-section__box-style-${elementId}`;\n        let style = document.getElementById(nodeId);\n        // check if element already exists to only create it once\n        if (!style) {\n          // if not - create the style element\n          style = document.createElement('style');\n          // set an id\n          style.id = nodeId;\n          // append the style element\n          resultBoxSection.value.appendChild(style);\n        }\n        // set the actually css in the style element\n        style.innerHTML = `\n          .base-result-box-section__box-item-${elementId}:nth-child(n + ${itemsPerRow.value + 1}) {\n            margin-top: var(--spacing-regular);\n          }\n          .base-result-box-section__box-item-${elementId}:not(:nth-child(${itemsPerRow.value}n)) {\n            margin-right: var(--spacing-regular);\n          }`;\n        initialBoxCalcDone.value = true;\n      }\n    }\n\n    /**\n     * calc the number of boxes that fits the space as soon as the container\n     * has been rendered\n     * (we can not use the useWindowResize callOnMounted since this is just considering\n     * window not the component)\n     */\n    watch(resultBoxesArea, (value) => {\n      // as soon as area is rendered and variable received a value calc\n      // how much space per box is available\n      if (value) {\n        calcBoxNumber();\n      }\n    }, { once: true });\n\n    // in order to only trigger event when value has really changed create a watcher\n    watch(itemsPerRow, (val, oldVal) => {\n      if (val !== oldVal) {\n        /**\n         * communicate to parent when items per row changed, either after initial\n         * render space calculations or when window was resized\n         * @event items-per-row-changed\n         * @param {number} - the new number of items that fit in a row\n         */\n        emit('items-per-row-changed', itemsPerRow.value);\n      }\n    });\n\n    /** INTERNATIONALIZATION */\n    const { getI18nTerm } = useI18n();\n\n    return {\n      // internal id\n      elementId,\n      // box rendering\n      resultBoxesArea,\n      resultBoxSection,\n      itemsPerRow,\n      initialBoxCalcDone,\n      // i18n\n      getI18nTerm,\n      calcBoxNumber,\n    };\n  },\n  data() {\n    return {\n      // internal representation of entry list to be able to\n      // modify list via draggable\n      entryListInt: [],\n      // flag for edit mode activated\n      editModeActive: false,\n      // current page number\n      currentPageNumberInt: 1,\n      // store the expand state internally\n      expandedInt: false,\n      // store collapsed state on action start\n      wasExpanded: false,\n      // to manipulate selectedList internally\n      selectedListInt: [],\n      imageBoxesSelectable: false,\n      // store state if component is mounted and window is present\n      initialized: false,\n      /**\n       * variable for keyboard sorting - is element currently selected for moving\n       * @type {?string}\n       */\n      movableElementId: null,\n      /**\n       * add assistive text especially to ease use of drag mode accessibly\n       * @type {string}\n       */\n      currentAssistiveText: '',\n      /**\n       * control pagination display with this variable and only render after\n       *  entryListInt was initialized from outside\n       *  @type {boolean}\n       */\n      showPagination: false,\n    };\n  },\n  computed: {\n    /**\n     * to lazy load vuedraggable only if draggable mode is set true\n     *\n     * @returns {string|ComponentPublicInstanceConstructor}\n     */\n    draggableComponent() {\n      if (this.draggable) {\n        return defineAsyncComponent(() => import('vue-draggable-plus').then(m => m.VueDraggable));\n      }\n      return 'ul';\n    },\n    /**\n     * get the entries that should be displayed in the section -\n     * taking into consideration pagination and 'show more' functionality\n     * @returns {Object[]}\n     */\n    visibleBoxes() {\n      if (this.editModeActive && (this.draggable || !this.usePagination)) {\n        return [...this.entryListInt];\n      }\n      // if expand mode is used and status is collapsed and there\n      // are more items than can be displayed in the rows specified by 'show more'\n      // slice first few\n      if (!this.editModeActive && this.useExpandMode && !this.expandedInt && this.expandNeeded) {\n        // slice from 0 to number of rows * items per row - 1 so that the button\n        // take the last box\n        return this.entryListInt.slice(0, (this.itemsPerRow * this.maxShowMoreRows) - 1);\n      }\n      // else if pagination is active and items are not fetched from outside\n      // slice items fitting one page\n      if (this.usePagination && !this.fetchDataExternally) {\n        // slice taking into account current pagination and the total number of\n        // visible items\n        return this.entryListInt\n          .slice(\n            (this.currentPageNumberInt - 1) * this.visibleNumberOfItems,\n            this.currentPageNumberInt * this.visibleNumberOfItems,\n          );\n      }\n      if (this.fetchDataExternally) {\n        return this.modelValue.slice(0, this.visibleNumberOfItems);\n      }\n      // else return complete list\n      return this.entryListInt;\n    },\n    /**\n     * in order to only set model-value when the VueDraggable component\n     * is rendered (and not for the <li> element) add a separate computed\n     * variable\n     */\n    draggableBoxes: {\n      get() {\n        // if boxes are not draggable do not set the attribute\n        if (!this.draggable) return undefined;\n        // else return the boxes computed in visibleBoxes\n        return this.visibleBoxes;\n      },\n      // since boxes are only changed by draggable have set here now instead\n      // of in visibleBoxes\n      set(val) {\n        this.entryListInt = [...val];\n      }\n    },\n    /** PAGINATION AND EXPAND MODE */\n    /**\n     * the number of items that should be visible on one page\n     * (if pagination is active)\n     * @returns {number}\n     */\n    visibleNumberOfItems() {\n      const availableSpaces = this.itemsPerRow * this.maxRows;\n      if (this.editModeActive && this.showActionButtonBoxes) {\n        return availableSpaces - this.actionButtonsConfig.length;\n      }\n      if (!this.editModeActive && this.useExpandMode) {\n        // subtract 1 for the Expand Box Button or Action Button\n        return availableSpaces - 1;\n      }\n      return availableSpaces;\n    },\n    /**\n     * number of pages (if pagination is active)\n     * @returns {?number}\n     */\n    pages() {\n      if (!this.initialBoxCalcDone) return null;\n      return (this.total || this.entryListInt.length) && this.visibleNumberOfItems >= 0\n        ? Math.ceil((this.total || this.entryListInt.length) / this.visibleNumberOfItems) : 1;\n    },\n    /**\n     * determines if the total number of entries exceeds the number of entries that\n     * can be displayed and thus if an expand button is needed\n     */\n    expandNeeded() {\n      return (this.itemsPerRow * this.maxShowMoreRows) < this.modelValue.length;\n    },\n  },\n  watch: {\n    modelValue: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.entryListInt)) {\n          this.entryListInt = [...val];\n          // check if showPagination was already set true otherwise do it after\n          // entryListInt was set for the first time\n          if (!this.showPagination) {\n            // make sure this is one last (and boxes are already rendered)\n            setTimeout(() => {\n              this.showPagination = true;\n            }, 0);\n          }\n        }\n      },\n      immediate: true,\n      deep: true,\n    },\n    entryListInt: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.modelValue)) {\n          /**\n           * event emitted when the list of entries changed internally\n           * (relevant if `draggable` is set `true`)\n           *\n           * @event update:model-value\n           * @param {Object[]} - the updated list of entries\n           */\n          this.$emit('update:model-value', val);\n        }\n      },\n      deep: true,\n    },\n    // watch selectedList prop and assign to internal value if changes occur\n    selectedList: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.selectedListInt)) {\n          this.selectedListInt = JSON.parse(JSON.stringify(val));\n        }\n      },\n      immediate: true,\n    },\n    // watch selectedList prop and assign to internal value if changes occur\n    selectedListInt: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.selectedList)) {\n          /**\n           * inform the parent of the changes in `selectedList` and provide\n           * the ids of all selected.\n           *   the v-model directive may be used on the corresponding prop\n           *\n           * @event update:selected-list\n           * @param {Array} - the list of selected entry ids\n           */\n          this.$emit('update:selected-list', val);\n        }\n      },\n      deep: true,\n    },\n    // watch pages in case of deletion of items and take care\n    // current page is not higher than total page number\n    pages: {\n      handler(val) {\n        if (this.currentPageNumberInt > val) {\n          // if the current page number exceeds the total number of pages\n          // set the value to the last existing page\n          this.currentPageNumberInt = val;\n        }\n      },\n      immediate: true,\n    },\n    // update internal page number if changed from outside\n    currentPageNumber: {\n      handler(val) {\n        if (val && val !== this.currentPageNumberInt) {\n          // check if number is larger than max number of pages currently available and\n          // set to max possible value if yes instead\n          // TODO: changed this to internal handling for now because it makes problems with\n          // externally provided data but maybe it would make sense to get rid of it all together\n          this.currentPageNumberInt = this.pages && val > this.pages && !this.fetchDataExternally\n            ? this.pages : val;\n        }\n      },\n      immediate: true,\n    },\n    /**\n     * watch internal page number to inform parent about changes\n     * @param {number} val\n     */\n    currentPageNumberInt: {\n      handler(val) {\n        if (val !== this.currentPageNumber) {\n          /** emitted when pagination is used and page number was changed\n           *\n           * @event update:current-page-number\n           * @param {number} - the new page number\n           */\n          this.$emit('update:current-page-number', this.currentPageNumberInt);\n        }\n      },\n      immediate: true,\n    },\n    // if expanded variable is set from outside change\n    // internal variable accordingly\n    expanded: {\n      handler(val) {\n        if (val !== this.expandedInt) {\n          this.expandedInt = val;\n        }\n      },\n      immediate: true,\n    },\n    // if internal value changes, reset page number and inform parent\n    expandedInt(val) {\n      // reset current page number on collapse\n      if (!val) {\n        this.currentPageNumberInt = 1;\n      }\n      // inform parent of internal change\n      if (val !== this.expanded) {\n        /**\n         * event emitted on expand toggle.\n         *   the v-model directive may be used on the corresponding prop\n         * @event update:expanded\n         * @param { Boolean } - true if list is expanded\n         */\n        this.$emit('update:expanded', val);\n      }\n    },\n    editModeActive(val) {\n      // have setting true of selectable delayed for animation\n      setTimeout(() => {\n        this.imageBoxesSelectable = val;\n      }, 50);\n      setTimeout(() => {\n        if (val) {\n          this.$nextTick(() => {\n            if (this.$refs.resultBoxItemElement && this.$refs.resultBoxItemElement.length) {\n              this.$refs.resultBoxItemElement.forEach((element) => {\n                const inputElement = element.getElementsByTagName('input');\n                if (inputElement?.length) {\n                  inputElement[0].setAttribute('tabindex', '-1');\n                }\n              });\n              // it appears refs are not reactive and do not reflect reordering so we need\n              // to look for the actual current first element in the visibleBoxes array\n              const firstElement = this.$refs.resultBoxItemElement\n                .find(element => element.id.includes(this.visibleBoxes[0].id));\n              firstElement.focus({ preventScroll: true });\n            }\n          });\n        }\n      }, 500);\n      if (val) {\n        this.currentAssistiveText = this.assistiveText.description;\n      } else {\n        this.movableElementId = null;\n        this.currentAssistiveText = '';\n      }\n      if (val !== this.editMode) {\n        /**\n         * emitted on edit mode toggle (options toggle).\n         *   the v-model directive may be used on the corresponding prop\n         *\n         * @event update:edit-mode\n         * @param {Boolean} - flag for edit mode active\n         */\n        this.$emit('update:edit-mode', val);\n      }\n\n      // add listener to esc key event (toggle edit mode)\n      if (!this.initialized) return;\n      if (val) {\n        window.addEventListener('keyup', this.escEventHandler);\n      } else {\n        window.removeEventListener('keyup', this.escEventHandler);\n      }\n    },\n    editMode: {\n      handler(val) {\n        if (val !== this.editModeActive) {\n          this.editModeActive = val && this.showOptions && this.showHeader;\n        }\n      },\n      immediate: true,\n    },\n    showOptions(val) {\n      if (!val) {\n        this.editModeActive = false;\n      }\n    },\n    showHeader(val) {\n      if (!val) {\n        this.editModeActive = false;\n      }\n    },\n  },\n  created() {\n    if (!this.useExpandMode) {\n      this.expandedInt = true;\n    }\n    // since prop `editMode` watcher does not have immediate flag set the\n    // internal variables in sync here and also already set `imageBoxesSelectable`\n    // since this is giving a hydration error with nuxt otherwise\n    this.editModeActive = this.editMode;\n    if (this.editModeActive) {\n      this.imageBoxesSelectable = true;\n    }\n  },\n  mounted() {\n    /**\n     * Calculate the number of boxes that fit in the space.\n     * Do this during mounting to ensure that page transitions work correctly in Nuxt.\n     * Note: a watcher in setup() is currently triggered before the component is mounted\n     */\n    this.calcBoxNumber();\n    /**\n     * component is initialized and ready\n     */\n    this.initialized = true;\n  },\n  methods: {\n    dragStart(event) {\n      this.movableElementId = event.data?.id;\n      const className = 'grabbing';\n      const html = document.getElementsByTagName('html').item(0);\n      if (html && new RegExp(className).test(html.className) === false) {\n        html.className += ' ' + className; // use a space in case there are other classNames\n      }\n    },\n    dragEnd() {\n      // due to an click event being fired on Firefox on dragend (mouseup) we need\n      // to move the resetting of the movableElementId to the very end of the queue\n      // so when the click event comes i can check for an ongoing drag event (see below)\n      setTimeout(() => {\n        this.movableElementId = null;\n      }, 0)\n      const className = 'grabbing';\n      const html = document.getElementsByTagName('html').item(0);\n      if (html && new RegExp(className).test(html.className) === true) {\n        // Remove className with the added space (from setClassToHTMLElement)\n        html.className = html.className.replace(\n          new RegExp(' ' + className),\n          ''\n        );\n        // Remove className without added space (just in case)\n        html.className = html.className.replace(new RegExp(className), '');\n      }\n    },\n    /**\n     * in Firefox a click event is triggered on dragend (mouseup) with vue-draggable\n     * which causes the box to get selected/unselected after dragging - to stop this\n     * we need to check here if drag is ongoing (=movableElementId is still set) and\n     * stop event propagation if yes\n     * @param {MouseEvent} event\n     */\n    onBoxClick(event) {\n      if (this.movableElementId) {\n        event.stopPropagation();\n      }\n    },\n    /** EDIT MODE FUNCTIONALITIES */\n    /**\n     * toggling of options when options are behind a 'options' button\n     *\n     * @param {Boolean} actionsVisible true for open, false for close\n     */\n    optionsToggle(actionsVisible) {\n      this.editModeActive = actionsVisible;\n      if (!actionsVisible) {\n        // on close return to original collapsed state\n        this.expandedInt = this.wasExpanded;\n        // clear selected boxes\n        this.selectedListInt = [];\n        // on open - store the original collapsed state\n      } else {\n        this.wasExpanded = this.expandedInt;\n      }\n    },\n    /**\n     * function triggered when selecteAll was clicked in select mode\n     *\n     * @param {boolean} selectAll - true if everything was selected,\n     * false if everything was deselected\n     */\n    selectAllTriggered(selectAll) {\n      if (selectAll) {\n        // select all entries that are currently visible\n        // deduplicate by creating Set and converting back to array\n        this.selectedListInt = [...new Set([...this.selectedListInt,\n          ...this.visibleBoxes.map(entry => this\n            .getPropValue(this.identifierPropertyName, entry))])];\n      } else {\n        const visibleEntryIds = this.visibleBoxes\n          .map(visibleEntry => this.getPropValue(this.identifierPropertyName, visibleEntry));\n        this.selectedListInt = this.selectedListInt\n          .filter(entry => !visibleEntryIds\n            .includes(this.getPropValue(this.identifierPropertyName, entry) || entry));\n      }\n    },\n    /**\n     * triggered when an entry is selected or is clicked upon\n     *\n     * @param {string} entryId - the entry id of the selected entry\n     * @param {boolean} [selected=undefined] - not provided and thus undefined\n     * if entry was clicked\n     */\n    entrySelected(entryId, selected) {\n      // if entry was selected in edit mode and list does not contain entry\n      // already - add it to the list\n      if (selected && !this.selectedListInt.includes(entryId)) {\n        this.selectedListInt.push(entryId);\n      } else if (!selected) {\n        this.selectedListInt = this.selectedListInt.filter(boxId => boxId !== entryId);\n      }\n    },\n    /**\n     * function to calc if image box is currently selected\n     *\n     * @param {Object} entry - the entry in question\n     * @returns {Boolean}\n     */\n    isEntrySelected(entry) {\n      return this.selectedListInt\n        .map(selectedEntry => this.getPropValue(this.identifierPropertyName, selectedEntry)\n          || selectedEntry).includes(this.getPropValue(this.identifierPropertyName, entry));\n    },\n    /**\n     * function triggered when user has\n     * clicked action button to go through with the action\n     */\n    submitAction(action) {\n      /**\n       * event triggered when an action is triggered (after selecting boxes)\n       *\n       * @event submit-action\n       * @param {string} - the action type\n       */\n      this.$emit('submit-action', action);\n    },\n    /**\n     * intercept escape key event and reset edit mode\n     */\n    escEventHandler(e) {\n      if (e.key === 'Escape') {\n        // first use escape key to leave drag mode\n        if (this.movableElementId) {\n          this.cancelDragMode();\n          // else use it to leave edit mode\n        } else {\n          this.editModeActive = false;\n          this.currentAssistiveText = '';\n        }\n      }\n    },\n    /**\n     * event handler on keydown 'Enter'\n     * @param {KeyboardEvent} event - the keydown event\n     * @param {Object} entry - the entry the event was triggered on\n     * @param {number} index - the index of the entry in the visibleBoxes array\n     */\n    onEnterKey(event, entry, index) {\n      if (this.editModeActive && this.draggable) {\n        event.preventDefault();\n        // check if movableElementId is null\n        if (!this.movableElementId) {\n          // if yes activate drag mode by assigning the entry id as movableElementId\n          this.movableElementId = entry.id;\n          // add assistive text for the screen reader\n          this.currentAssistiveText = this.assistiveText.activated\n            .replace('{pos}', (index + 1).toString());\n        } else {\n          // if drag mode was active before - cancel it\n          this.cancelDragMode();\n        }\n      } else {\n        this.entryClicked(this.getPropValue(this.identifierPropertyName, entry));\n      }\n    },\n    /**\n     * event handler on keydown with arrow keys\n     * @param {KeyboardEvent} event - the keydown event\n     * @param {number} index - the index of the entry on which the event was triggered\n     *  in the draggableBoxes array\n     */\n    moveEntry(event, index) {\n      // reset assistive text\n      this.currentAssistiveText = '';\n      // get key that was pressed\n      const { key } = event;\n      // determine if element should be moved up or down in the list\n      const shiftDown = ['ArrowRight', 'ArrowDown'].includes(key);\n      // get the corresponding number to add to the array index\n      const shiftIndex = shiftDown ? 1 : -1;\n      // get new Index\n      const newIndex = index + shiftIndex;\n      // check if move is possible or if item is first or last respectively already\n      if (this.isWithinArrayLimit(this.draggableBoxes, shiftDown, newIndex)) {\n        // assign box list to variable so the set() of draggableBoxes is actually triggered\n        // when it is assigned again later on (doing it directly on draggableBoxes or entryListInt\n        // has no effect)\n        const newArray = this.draggableBoxes;\n        // do swapping with array destructuring\n        [newArray[index], newArray[newIndex]] = [newArray[newIndex], newArray[index]];\n        // assign it again to draggableBoxes variable\n        this.draggableBoxes = newArray;\n        // next tick so there is time to repaint and get new order\n        this.$nextTick(() => {\n          // get all box elements\n          const movedElement = document.getElementById(`li-${this.movableElementId}`);\n          // element is loosing focus in the process of swapping so refocus here\n          movedElement.focus();\n        });\n        // add matching assistive text informing the user of the move and the new position\n        this.currentAssistiveText = this.assistiveText.moved\n          .replace('{pos}', newIndex + 1)\n          .replace('{total}', this.draggableBoxes.length);\n      }\n    },\n    /**\n     * reset drag related variable and assistive text\n     */\n    cancelDragMode() {\n      this.movableElementId = null;\n      this.currentAssistiveText = '';\n    },\n\n    /** PAGINATION */\n    /**\n     * function triggered when page in pagination component is selected\n     *\n     * @param {number} number - the selected page number\n     */\n    setPage(number) {\n      // set internal page number - this will also trigger an event to parent\n      this.currentPageNumberInt = number;\n      // if variable is set true jump to top of element\n      if (this.jumpToTop) {\n        window.scrollTo(0, this.$el.offsetTop - this.scrollToOffset);\n      }\n    },\n\n    /** GENERAL FUNCTIONALITIES */\n    /**\n     * triggered when an entry is clicked upon (edit mode not acive)\n     *\n     * @param {string} entryId - the entry id of the selected entry\n     */\n    entryClicked(entryId) {\n      /**\n       * event emitted from default image box when clicked\n       * @event entry-clicked\n       * @property {string} entryId - the id of the clicked entry\n       * the select mode was not active but the box was clicked\n       */\n      this.$emit('entry-clicked', { entryId });\n    },\n    /**\n     * get an internationalized string\n     *\n     * @param {string|Object} localizationArguments - string or object to look\n     * up in localization files\n     *   if it is an object it should have the following properties:\n     * @property {string} string - string to look up in a Locale messages file\n     * @property {number} count - for pluralization\n     * @property {Object} variables - locale string variables object\n     * @returns {string}\n     */\n    getI18nString(localizationArguments) {\n      // check if a string was provided\n      if (typeof localizationArguments === 'string') {\n        return this.getI18nTerm(localizationArguments);\n      }\n      // if not - assume an object with the relevant properties\n      const { string, count, variables } = { ...localizationArguments };\n      return this.getI18nTerm(string, count, variables);\n    },\n    /**\n     * to get a nested object property value from a string in dot notation\n     *\n     * @param {string} string - the nested object property path in dot notation\n     * @param {Object} object - the object from which the property value should be extracted\n     * @returns {*}\n     */\n    getPropValue(string, object) {\n      return extractNestedPropertyValue(string, object);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    ref=\"resultBoxSectionElement\"\n    class=\"base-result-box-section\">\n    <!-- LOADER -->\n    <div\n      v-if=\"isLoading\"\n      class=\"base-result-box-section__loading\">\n      <BaseLoader\n        :text-on-loader-show=\"assistiveText.loaderActive\"\n        class=\"base-result-box-section__loader\" />\n    </div>\n\n    <!-- RESULT BOX SECTION AREA -->\n    <div\n      class=\"base-result-box-section__container\">\n      <!-- HEADER ROW -->\n      <div\n        v-if=\"showHeader\"\n        class=\"base-result-box-section__header-row\">\n        <!-- HEADER WITH OPTIONS -->\n        <BaseOptions\n          v-if=\"showOptions\"\n          :show-options=\"editModeActive\"\n          :options-button-icon=\"optionsButtonIcon\"\n          :options-button-text=\"optionsButtonText\"\n          use-options-button-on=\"always\"\n          @update:show-options=\"optionsToggle\">\n          <template #beforeOptions>\n            <!-- @slot add a custom header instead of headerText -->\n            <slot name=\"header\">\n              <h3\n                v-if=\"headerText\"\n                class=\"base-result-box-section__header\">\n                {{ headerText }}\n              </h3>\n            </slot>\n          </template>\n\n          <!-- ACTIONS FOR BOXES -->\n          <template\n            #options>\n            <!-- @slot add custom option/action elements in the header row\n              @binding {Function} submit-action - the method that should be called after the action button was clicked\n            -->\n            <slot\n              name=\"optionButtons\"\n              :submit-action=\"submitAction\">\n              <!-- default iterate through optionsConfig array -->\n              <template v-for=\"action of actionButtonsConfig\">\n                <BaseButton\n                  v-if=\"action.display === 'top' || action.display === 'all' || !action.display\"\n                  :key=\"action.text\"\n                  :text=\"getI18nString(action.text)\"\n                  :icon=\"action.icon\"\n                  :has-background-color=\"false\"\n                  :disabled=\"action.disabled\"\n                  icon-size=\"large\"\n                  button-style=\"single\"\n                  @clicked=\"submitAction(action.value)\" />\n              </template>\n            </slot>\n          </template>\n        </BaseOptions>\n\n        <!-- HEADER ONLY -->\n        <template v-else>\n          <slot name=\"header\">\n            <h3\n              v-if=\"headerText\"\n              class=\"base-result-box-section__header\">\n              {{ headerText }}\n            </h3>\n          </slot>\n        </template>\n      </div>\n\n      <div\n        :class=\"['base-result-box-section__background',\n                 {\n                   'base-result-box-section__background--white':\n                     editModeWhiteBackground && editModeActive,\n                 }]\">\n        <!-- MESSAGE AND FOLLOW UP ACTION AREA FOR EDIT MODE -->\n        <!-- MESSAGE AREA -->\n        <div\n          v-if=\"editModeActive\"\n          :key=\"headerText + '_messageArea'\"\n          class=\"base-result-box-section__message-area\">\n          <div class=\"base-result-box-section__message-area-text\">\n            {{ messageText }}\n          </div>\n          <span class=\"base-result-box-section__message-area-subtext\">{{ messageSubtext }}</span>\n          <!-- @slot add a custom element after the message area -->\n          <slot name=\"optionsMessageAreaAfter\" />\n        </div>\n\n        <!-- SELECT OPTIONS (NUMBER OF SELECTED AND SELECT ALL) -->\n\n        <!-- adding a indicator of how many items are selected and 'select all' button\n        only shown in select mode -->\n        <BaseSelectOptions\n          v-if=\"editModeActive\"\n          :key=\"headerText + '_selectOptions'\"\n          :selected-number-text=\"getI18nString(selectOptionsText.entriesSelected)\"\n          :select-text=\"getI18nString(selectOptionsText.selectAll)\"\n          :deselect-text=\"getI18nString(selectOptionsText.selectNone)\"\n          :list=\"visibleBoxes\"\n          :selected-list=\"selectedListInt\"\n          @selected=\"selectAllTriggered\" />\n        <span\n          aria-live=\"assertive\"\n          class=\"assistive-text\">\n          {{ currentAssistiveText }}\n        </span>\n        <!-- BOXES AREA -->\n        <template v-if=\"entryListInt.length\">\n          <component\n            :is=\"draggableComponent\"\n            ref=\"resultBoxesAreaElement\"\n            :model-value=\"draggableBoxes\"\n            :animation=\"draggable ? 150 : undefined\"\n            :tag=\"draggable ? 'ul' : undefined\"\n            :disabled=\"draggable ? !editModeActive : undefined\"\n            :draggable=\"editModeActive ? '.base-result-box-section__result-box-item' : undefined\"\n            :aria-label=\"headerText\"\n            :handle=\"draggable ? '.base-result-box-section__result-box-item__draggable .base-image-box' : undefined\"\n            :force-fallback=\"draggable ? true : undefined\"\n            :role=\"draggable ? 'list' : undefined\"\n            class=\"base-result-box-section__boxes-container\"\n            @start=\"dragStart\"\n            @end=\"dragEnd\"\n            @click.capture=\"onBoxClick\"\n            @update:model-value=\"draggableBoxes = $event\">\n            <!-- element NEEDS to be a listitem element since parent is <ul> -->\n            <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n            <li\n              v-for=\"(entry, index) of visibleBoxes\"\n              :id=\"`li-${entry.id}`\"\n              :key=\"getPropValue(identifierPropertyName, entry)\"\n              ref=\"resultBoxItemElement\"\n              :tabindex=\"editModeActive || !disableListElementFocus ? 0 : -1\"\n              :aria-label=\"getPropValue(titlePropertyName, entry)\"\n              :aria-grabbed=\"movableElementId === entry.id\"\n              :aria-selected=\"editModeActive ? isEntrySelected(entry) : undefined\"\n              :class=\"['base-result-box-section__box-item',\n                       'base-result-box-section__result-box-item',\n                       { 'base-result-box-section__box-item__hidden': !initialBoxCalcDone },\n                       `base-result-box-section__box-item-${elementId}`,\n                       {\n                         'base-result-box-section__result-box-item__draggable':\n                           draggable && editModeActive,\n                       },\n                       {\n                         'base-result-box-section__result-box-item__dragging':\n                           movableElementId === entry[identifierPropertyName],\n                       }]\"\n              @keydown.enter=\"onEnterKey($event, entry, index)\"\n              @keydown.up.down.left.right.prevent=\"editModeActive && draggable && movableElementId\n                ? moveEntry($event, index) : false\"\n              @keydown.space.prevent=\"editModeActive ? entrySelected(\n                getPropValue(identifierPropertyName, entry), !isEntrySelected(entry)) : false\"\n              @keydown.tab=\"cancelDragMode\">\n              <!-- @slot result-box - for custom result boxes\n                @binding {Object} item - one list item of boxes to be displayed\n                @binding {number} index - the index of the item\n                @binding {boolean} select-active - are items in select mode\n                @binding {boolean} is-entry-selected - is the particular item currently selected\n                @binding {Function} entry-selected - method that should be called when an entry was selected\n              -->\n              <slot\n                :item=\"entry\"\n                :index=\"index\"\n                :select-active=\"editModeActive\"\n                :is-entry-selected=\"isEntrySelected\"\n                :entry-selected=\"entrySelected\"\n                name=\"resultBox\">\n                <BaseImageBox\n                  :key=\"getPropValue(identifierPropertyName, entry)\"\n                  :selectable=\"imageBoxesSelectable\"\n                  :draggable=\"editModeActive && draggable\"\n                  :selected=\"isEntrySelected(entry)\"\n                  :box-size=\"{ width: 'auto' }\"\n                  :box-ratio=\"'100'\"\n                  :title=\"getPropValue(titlePropertyName, entry)\"\n                  :subtext=\"entry.subtext\"\n                  :description=\"entry.description\"\n                  :image-url=\"entry.imageUrl\"\n                  :box-text=\"entry.text\"\n                  :lazyload=\"true\"\n                  @select-triggered=\"entrySelected(\n                    getPropValue(identifierPropertyName, entry), $event)\"\n                  @clicked=\"entryClicked(getPropValue(identifierPropertyName, entry))\" />\n              </slot>\n            </li>\n\n            <!-- ACTION BUTTONS -->\n            <!-- @slot add custom elements after result elements list use scoped slot prop `itemsPerRow` or dynamically adjusted css variable `--items-per-row` to adjust element width in accordance with other boxes\n              @binding {number} items-per-row - items per row calculated from container or page width\n              @binding {string} element-id - add a class `base-result-box-section__box-item-${elementId}` to action button element to include it in box size and styling calculations\n            -->\n            <slot\n              v-if=\"showActionButtonBoxes && editModeActive\"\n              :items-per-row=\"itemsPerRow\"\n              :element-id=\"elementId\"\n              name=\"actionButtons\">\n              <!-- default button -->\n              <template\n                v-for=\"action of actionButtonsConfig\">\n                <BaseBoxButton\n                  v-if=\"action.display === 'bottom' || action.display === 'all' || !action.display\"\n                  :key=\"action.value\"\n                  :text=\"getI18nString(action.text)\"\n                  :box-size=\"{ width: 'calc(25% - 8rem/19 - (8rem/19/2))', height: '100%' }\"\n                  :icon=\"action.icon\"\n                  box-style=\"small\"\n                  render-element-as=\"button\"\n                  :class=\"['base-result-box-section__box-item',\n                           `base-result-box-section__box-item-${elementId}`]\"\n                  @clicked=\"submitAction(action.value)\" />\n              </template>\n            </slot>\n            <!-- EXPAND BUTTON -->\n            <BaseBoxButton\n              v-else-if=\"useExpandMode && !editModeActive && expandNeeded && initialBoxCalcDone\"\n              :box-size=\"{ width: 'calc(25% - 8rem/19 - (8rem/19/2))', height: '100%' }\"\n              icon=\"\"\n              text=\"\"\n              render-element-as=\"button\"\n              :class=\"['base-result-box-section__box-item',\n                       `base-result-box-section__box-item-${elementId}`]\"\n              @clicked=\"expandedInt = !expandedInt\">\n              <template #default>\n                <!-- needed to add v-if here again - otherwise strange side effects -->\n                <div\n                  v-if=\"!editModeActive\"\n                  class=\"base-result-box-section__expand-button__content\">\n                  <span\n                    v-if=\"!expandedInt\"\n                    class=\"base-result-box-section__expand-button__content-number\">\n                    {{ `+${(total || modelValue.length) - visibleBoxes.length}` }}\n                  </span>\n                  <span\n                    :class=\"[expandedInt\n                      ? 'base-result-box-section__expand-button__content-text-expanded'\n                      : 'base-result-box-section__expand-button__content-text-collapsed']\">\n                    {{ expandedInt ? expandText.collapse : expandText.expand }}\n                  </span>\n                </div>\n              </template>\n            </BaseBoxButton>\n          </component>\n          <!-- PAGINATION -->\n          <!-- only shown if\n          * usePagination is true\n          * it is actually needed because there is more than one page\n          * edit mode is active and draggable functionality is not used\n          * edit mode is not active and rows are expanded (always true if\n            useExpandMode is set false) -->\n          <BasePagination\n            v-if=\"usePagination && showPagination && pages > 1\n              && ((editModeActive && !draggable)\n                || (!editModeActive && expandedInt))\"\n            :key=\"'pagination-' + elementId\"\n            :total=\"pages\"\n            :model-value=\"currentPageNumberInt\"\n            :use-link-element=\"usePaginationLinkElement\"\n            :assistive-text=\"paginationAssistiveText\"\n            @update:model-value=\"setPage\" />\n        </template>\n        <template v-else>\n          <!-- @slot slot to display user information when `modelValue` array is empty -->\n          <slot name=\"no-results\" />\n        </template>\n      </div>\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n@use \"@/styles/variables\" as *;\n\n.base-result-box-section {\n  position: relative;\n  display: flex;\n  width: 100%;\n  --items-per-row: v-bind(itemsPerRow);\n  --spacing-regular: #{$spacing};\n\n  .base-result-box-section__loading {\n    position: absolute;\n    height: 100%;\n    width: 100%;\n    z-index: map.get($zindex, loader);\n    background-color: $loading-background;\n\n    .base-result-box-section__loader {\n      top: var(--loader-position-top, 150px);\n    }\n  }\n\n  .base-result-box-section__container {\n    width: 100%;\n    .base-result-box-section__header-row {\n      display: flex;\n      flex-direction: row;\n      justify-content: space-between;\n      align-items: center;\n      margin: $spacing-small 0;\n\n      .base-result-box-section__header {\n        font-size: $font-size-regular;\n        color: $font-color-second;\n        font-weight: normal;\n        margin: 0 0 0 $spacing;\n      }\n    }\n\n    .base-result-box-section__boxes-container {\n      display: flex;\n      flex-direction: row;\n      flex-wrap: wrap;\n\n      .base-result-box-section__box-item {\n        position: relative;\n        // subtracted 0.01rem for edge\n        flex: 0 0 calc(((100% - ((var(--items-per-row) - 1) * #{$spacing}))\n        / var(--items-per-row)) - 0.01rem);\n        height: 100%;\n\n        &__hidden {\n          visibility: hidden;\n        }\n\n        &:before {\n          content: '';\n          height: 100%;\n          top: 0;\n          right: 0;\n          pointer-events: none;\n          background-color: transparent;\n          padding-bottom: 100%;\n        }\n\n        &:focus-within:after {\n          content: '';\n          width: 100%;\n          height: 100%;\n          position: absolute;\n          top: 0;\n          right: 0;\n          box-shadow: inset 0 0 0 1px var(--app-color-secondary, #b085f5);\n          pointer-events: none;\n          background-color: transparent;\n        }\n\n        &:focus:not(:focus-visible) {\n          outline: none;\n        }\n      }\n\n      .base-result-box-section__result-box-item {\n        box-shadow: $box-shadow-reg;\n        cursor: pointer;\n\n        &__draggable {\n          box-shadow: 0 0 12px 2px rgba(0, 0, 0, 0.25);\n          cursor: move;\n        }\n      }\n\n      .base-result-box-section__expand-button__content {\n        display: flex;\n        width: 100%;\n        height: 100%;\n        flex-direction: column;\n        align-items: center;\n        justify-content: center;\n        cursor: pointer;\n\n        .base-result-box-section__expand-button__content-number {\n          color: $app-color;\n          font-size: $font-size-large;\n          font-weight: bold;\n        }\n\n        .base-result-box-section__expand-button__content-text-collapsed,\n        .base-result-box-section__expand-button__content-text-expanded:hover{\n          color: $app-color;\n        }\n      }\n    }\n\n    .base-result-box-section__message-area {\n      margin-bottom: $spacing-large;\n      text-align: center;\n      color: $font-color-second;\n      backface-visibility: hidden;\n      z-index: map.get($zindex, boxcontent);\n      position: relative;\n\n      .base-result-box-section__message-area-text {\n        font-size: $font-size-large;\n        margin-bottom: $spacing-small;\n      }\n\n      .base-result-box-section__message-area-subtext {\n        font-size: $font-size-small;\n        white-space: pre-line;\n      }\n    }\n\n    .base-result-box-section__background {\n\n      &--white {\n        position: relative;\n        z-index: 1;\n        padding: $spacing;\n        background-color: #fff;\n        box-shadow: $box-shadow-edit;\n\n        .base-result-box-section__message-area {\n          margin-bottom: $spacing-small;\n        }\n\n        .base-result-box-section__result-box-item__draggable {\n          box-shadow: $box-shadow-reg;\n        }\n      }\n\n      &:deep(.base-button.base-button--secondary.base-button--background){\n        background-color: transparent;\n      }\n    }\n  }\n}\n\n.sortable-chosen {\n  user-select: none;\n}\n</style>\n","<script>\nimport BaseButton from '@/components/BaseButton/BaseButton.vue';\n\n/**\n * component to enable display of selected items and a select all\n */\nexport default {\n  name: 'BaseSelectOptions',\n  components: {\n    BaseButton,\n  },\n  props: {\n    /**\n     * specify the text displayed for number of selected entries:\n     * `x {selectedNumberText}`\n     */\n    selectedNumberText: {\n      type: String,\n      default: 'entries selected',\n    },\n    /**\n     * the text displayed for select / deselect all\n     */\n    selectText: {\n      type: String,\n      default: 'All',\n    },\n    /**\n     * the text displayed for select / deselect all\n     */\n    deselectText: {\n      type: String,\n      default: 'None',\n    },\n    /**\n     * provide a list of currently visible entries\n     */\n    list: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * provide a list of selected entries\n     */\n    selectedList: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * disable the button by setting this prop to true\n     */\n    selectAllDisabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * By default, the \"All/None\" button appears on the right, and the counter of\n     * selected items appears on the left. Set this to `true` to reverse the order.\n     */\n    reverse: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  emits: ['selected'],\n  data() {\n    return {\n      selectedInt: false,\n      // used to change the flex direction of select options from 'row' to 'row-reverse' (#1692)\n      flexDirection: 'row',\n    };\n  },\n  computed: {\n    numberSelected() {\n      return this.selectedList.length;\n    },\n    allSelected() {\n      // not just calc comparing selectedList with list because with pagination\n      // selectedList can contain entries that are currently not incluced in list\n      const idList = this.selectedList.length && this.selectedList[0].id\n        ? this.selectedList.map(entry => entry.id) : this.selectedList;\n      const unselectedLength = this.list\n        .filter(entry => !idList.includes(entry.id)).length;\n      return unselectedLength === 0;\n    },\n  },\n  watch: {\n    allSelected: {\n      handler(val) {\n        if (val !== this.selectedInt) {\n          this.selectedInt = val;\n        }\n      },\n      immediate: true,\n    },\n  },\n  created() {\n    // swap position of select options based on the 'reverse' prop (#1692)\n    this.flexDirection = this.reverse ? 'row-reverse' : 'row';\n  },\n  methods: {\n    select() {\n      this.selectedInt = !this.selectedInt;\n      /**\n       * emitted on select all button click\n       *\n       * @event selected\n       * @param {boolean} - were all entries selected\n       */\n      this.$emit('selected', this.selectedInt);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    class=\"base-select-options\"\n    :style=\"{ '--direction': flexDirection }\">\n    <div class=\"base-select-options__number-selected\">\n      <!-- @slot here number of selected entries is indicated - replace with this slot for customization. -->\n      <slot name=\"selectedText\">\n        {{ `${numberSelected} ${selectedNumberText}` }}\n      </slot>\n    </div>\n    <BaseButton\n      :text=\"allSelected ? deselectText : selectText\"\n      :disabled=\"selectAllDisabled\"\n      button-style=\"secondary\"\n      :class=\"['base-select-options__select-button',\n               `base-select-options__select-button--margin-${reverse ? 'right' : 'left'}`]\"\n      @clicked=\"select\" />\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-select-options {\n    display: flex;\n    // flex direction can be 'row' or 'row-reverse' and depends on the 'reverse' prop (#1692)\n    flex-direction: var(--direction);\n    justify-content: space-between;\n    align-items: center;\n    flex-wrap: wrap;\n    margin-bottom: $spacing-small;\n\n    .base-select-options__number-selected {\n      font-size: $font-size-small;\n      color: $font-color-second;\n      margin: $spacing-small-half $spacing-small;\n    }\n\n    .base-select-options__select-button {\n      &.base-select-options__select-button--left {\n        // to keep button aligned right when parent wraps\n        margin-left: auto;\n      }\n      &.base-select-options__select-button--margin-right {\n        // to keep button aligned left when parent wraps\n        margin-right: auto;\n      }\n\n      &:hover,\n      &:focus {\n        color: $app-color;\n      }\n    }\n  }\n</style>\n","<script>\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport { useId } from '@/composables/useId.js';\n\n/**\n * accessible tab switch buttons\n */\nexport default {\n  name: 'BaseSwitchButton',\n  components: { BaseIcon },\n  props: {\n    /**\n     * set true if the buttons should be visible but disabled, so they\n     * will appear greyed out and not be clickable\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify where the icon should be rendered\n     */\n    iconPosition: {\n      type: String,\n      default: 'right',\n      validator: val => ['right', 'left'].includes(val),\n    },\n    /**\n     * specify icon size\n     * this prop currently only applies to `type` 'prominent'\n     */\n    iconSize: {\n      type: String,\n      default: 'medium',\n      validator(val) {\n        return ['small', 'medium', 'large'].includes(val);\n      },\n    },\n    /**\n     * set a label for the switches, not visible per default (set `showLabel` to `true` if label should be shown) but required for accessibility\n     */\n    label: {\n      type: String,\n      required: true,\n    },\n    /**\n     * set the currently active tab (specify the value of the object not the label)\n     */\n    modelValue: {\n      type: String,\n      required: true,\n    },\n    /**\n     * specify the tabs as array of object with `value`, `label` and (optional) `icon` properties\n     */\n    options: {\n      type: Array,\n      default: () => [{ label: 'tab', value: 'tab', icon: '' }],\n      validator: arr => arr.every(val => ['label', 'value'].every(prop => Object.keys(val).includes(prop))),\n    },\n    /**\n     * define if the label of the single buttons should be shown (or just icons). This\n     * property is default undefined and is determined internally individually for each type:\n     *  **normal**: default is `true`\n     *  **prominent**: default is `false`\n     */\n    showButtonsLabel: {\n      type: Boolean,\n      default: undefined,\n    },\n    /**\n     * set if the switch label is shown\n     */\n    showLabel: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * set a type for the button's active state rendering style\n     *  **normal**: gives the switch a more subtle, more condensed look with active item only indicated by grey border,\n     *    buttons have a label per default (`showButtonsLabel` is `true`).\n     *  **prominent**: larger buttons with more spacing and permanent border around each item, active item is\n     *    indicated by a 2px (app-)colored bottom border, button labels are not shown per default (`showButtonsLabel` is `false`)\n     *    so the property `icon` should be set for each switch item in `options`.\n     */\n    type: {\n      type: String,\n      default: 'normal',\n      validator: val => ['normal', 'prominent'].includes(val),\n    },\n  },\n  emits: ['update:model-value'],\n  setup() {\n    const internalId = useId();\n    return {\n      internalId,\n    };\n  },\n  data() {\n    return {\n      selectedOption: this.modelValue,\n    };\n  },\n  computed: {\n    // to ensure a unique id (made problems on field duplication)\n    optionIds() {\n      return this.options.map(option => `${this.internalId}-${option.value}`);\n    },\n    defaultShowButtonsLabel() {\n      return this.type === 'normal';\n    },\n    showButtonsLabelInt() {\n      return this.showButtonsLabel ?? this.defaultShowButtonsLabel;\n    },\n  },\n  watch: {\n    selectedOption(val) {\n      /**\n       * Event emitted on options switch, value of options object is emitted\n       *\n       * @event update:model-value\n       * @param { string } - the `value` of the selected option object\n       */\n      this.$emit('update:model-value', val);\n    },\n    modelValue(val) {\n      if (val !== this.selectedOption) {\n        this.selectedOption = val;\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <fieldset\n    :class=\"['base-switch-buttons', { 'base-switch-buttons--gap': type === 'prominent' }]\">\n    <!-- we need to separate legend here from the actually displayed label because\n      legend is not accessible if wrapped in a span but i can not style the legend the way\n      i want without the span -->\n    <legend\n      class=\"hide\">\n      {{ label }}\n    </legend>\n    <span\n      :class=\"['base-switch-buttons__legend', { 'hide': !showLabel },\n               { 'base-switch-buttons__legend--disabled': disabled },\n               { 'base-switch-buttons__legend--gap': type === 'normal' }]\">\n      {{ label }}\n    </span>\n\n    <template\n      v-for=\"(option, index) in options\"\n      :key=\"option.value\">\n      <label\n        :for=\"optionIds[index]\"\n        :title=\"!showButtonsLabelInt ? option.label : undefined\"\n        :class=\"['base-switch-buttons__button',\n                 `base-switch-buttons__button--${type}`,\n                 { [`base-switch-buttons__button--${type}-active`]: option.value === selectedOption },\n                 { 'base-switch-buttons__button--icon-only': !showButtonsLabel },\n                 { 'base-switch-buttons__button--disabled': disabled }]\">\n        <input\n          :id=\"optionIds[index]\"\n          :key=\"option.value + 'input'\"\n          v-model=\"selectedOption\"\n          :tabindex=\"option.value === selectedOption ? 0 : -1\"\n          :checked=\"option.value === selectedOption\"\n          :aria-checked=\"option.value === selectedOption\"\n          :value=\"option.value\"\n          :name=\"label\"\n          :disabled=\"disabled\"\n          class=\"hide\"\n          type=\"radio\"\n          @keydown.enter.prevent=\"\">\n        <BaseIcon\n          v-if=\"option?.icon?.length > 0 && iconPosition === 'left'\"\n          :name=\"option.icon\"\n          :class=\"['base-switch-buttons__icon',\n                   `base-switch-buttons__icon--${iconSize}`]\" />\n        <span\n          v-if=\"showButtonsLabelInt\">\n          {{ option.label }}\n        </span>\n        <BaseIcon\n          v-if=\"option?.icon?.length > 0 && iconPosition === 'right'\"\n          :name=\"option.icon\"\n          :class=\"['base-switch-buttons__icon',\n                   `base-switch-buttons__icon--${iconSize}`]\" />\n        <!-- @slot slot to display something right of text (e.g. icon), or if `showButtonsLabel` false - generally right of the button content\n        @binding {string} value - the value of the option object\n        --->\n        <slot\n          :value=\"option.value\"\n          name=\"right-of-content\" />\n      </label>\n    </template>\n  </fieldset>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-switch-buttons {\n    clear: both;\n    display: flex;\n    position: relative;\n    align-items: center;\n    background-color: inherit;\n    line-height: $line-height;\n\n    &.base-switch-buttons--gap {\n      gap: $spacing;\n    }\n\n    .base-switch-buttons__legend {\n      display: flex;\n\n      &.base-switch-buttons__legend--disabled {\n        color: $font-color-second;\n      }\n\n      &.base-switch-buttons__legend--gap {\n        padding-right: $spacing-small;\n      }\n    }\n\n    .base-switch-buttons__button {\n      position: relative;\n      display: inline-flex;\n      align-items: center;\n      gap: $spacing-small;\n      padding: $spacing-small-half $spacing;\n      cursor: pointer;\n      background-color: inherit;\n      flex: 0 0 auto;\n      transition: border 0.2s ease;\n\n      &.base-switch-buttons__button--normal {\n        // white border to prevent twitching when adding colored border\n        border: 1px solid rgba(255, 255, 255, 0);\n\n        &.base-switch-buttons__button--normal-active {\n          border: $input-field-border;\n        }\n\n        &:focus-within {\n          border-bottom-color: $app-color;\n        }\n      }\n\n      &.base-switch-buttons__button--prominent {\n        justify-content: center;\n        border: $input-field-border;\n        height: $row-height-small;\n\n        &.base-switch-buttons__button--prominent-active {\n          box-shadow: inset 0 -#{$border-width} 0 0 #{$app-color};\n\n          &.base-switch-buttons__button--disabled {\n            box-shadow: inset 0 -#{$border-width} 0 0 #{$graytext-color};\n          }\n        }\n\n        &.base-switch-buttons__button--icon-only {\n          width: 50px;\n          padding: 0;\n        }\n\n        &:focus-within {\n          border-color: $app-color;\n        }\n      }\n\n      .base-switch-buttons__icon {\n        flex: 0 0 auto;\n\n        &.base-switch-buttons__icon--small {\n          height: $icon-small;\n          width: $icon-small;\n        }\n\n        &.base-switch-buttons__icon--medium {\n          height: $icon-medium;\n          width: $icon-medium;\n        }\n\n        &.base-switch-buttons__icon--large {\n          height: $icon-large;\n          width: $icon-large;\n        }\n      }\n\n      &:hover .base-switch-buttons__icon,\n      &:active .base-switch-buttons__icon {\n        color: $app-color;\n      }\n\n      &.base-switch-buttons__button--disabled {\n        cursor: default;\n        color: $graytext-color;\n\n        &:hover .base-switch-buttons__icon,\n        &:active .base-switch-buttons__icon {\n          color: $graytext-color;\n        }\n      }\n    }\n  }\n\n  @media screen and (max-width: $mobile) {\n    .base-switch-buttons {\n      margin: $spacing-small 0;\n\n      .base-switch-buttons__button {\n        padding: $spacing-small $spacing;\n\n        &.base-switch-buttons__button--prominent {\n          height: calc(#{$row-height-small} + #{$spacing-small});\n        }\n      }\n    }\n  }\n</style>\n","<script>\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport { useId } from '@/composables/useId.js';\nimport { useHasSlotContent } from '@/composables/useHasSlotContent.js';\nimport { computed, useSlots } from 'vue';\n\n/**\n * Toggle Component\n */\nexport default {\n  name: 'BaseToggle',\n  components: {\n    BaseIcon,\n  },\n  props: {\n    /**\n     * specify a descriptive name\n     * this will not be displayed but is only there for usability purposes\n     */\n    name: {\n      type: String,\n      default: 'baseToggle',\n    },\n    /**\n     * specify label\n     */\n    label: {\n      type: String,\n      default: 'baseToggle',\n    },\n    /**\n     * disable the toggle button\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * is toggle checked\n     */\n    modelValue: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * specify visibility of the label\n     */\n    hideLabel: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * bind visibility of slot content to components checked state\n     */\n    bindSlotToState: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * if field is occurring more than once - set an id\n     */\n    inputId: {\n      type: String,\n      default: '',\n    },\n    /**\n     * mark as required field\n     */\n    required: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * mark the form field as invalid and ideally also provide an error message\n     * to display below the form field\n     * the v-model directive might be used on this prop\n     */\n    invalid: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * add an error message to be displayed below form field if field is invalid\n     */\n    errorMessage: {\n      type: String,\n      default: '',\n    },\n    /**\n     * define if error icon should be shown\n     */\n    showErrorIcon: {\n      type: Boolean,\n      default: true,\n    },\n  },\n  emits: ['update:model-value'],\n  setup(props) {\n    // create id outside of computed to make sure we just have one fixed id\n    const internalId = useId();\n    // access slots to check if it is filled later\n    const slots = useSlots();\n    // slot is not directly accessible anymore - use composable to determine\n    // if slot has content\n    const { slotHasContent } = useHasSlotContent(slots.default);\n    /**\n     * check if an id was provided (to handle label input connection), if not\n     *  use the created one\n     * @returns {String|string}\n     */\n    const idInt = computed(() => props.inputId || internalId);\n    return {\n      idInt,\n      slotHasContent,\n    };\n  },\n  data() {\n    return {\n      checkedInt: false,\n      animate: false,\n    };\n  },\n  watch: {\n    modelValue: {\n      handler(val) {\n        if (val !== this.checkedInt) {\n          this.checkedInt = val;\n        }\n      },\n      immediate: true,\n    },\n    checkedInt(val) {\n      /**\n       * event emitted on radio button / checkmark click\n       * @event update:model-value\n       * @param {string, boolean} - emitted input value (string for Radio Button, boolean value for Checkmark)\n       */\n      this.$emit('update:model-value', val);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    class=\"base-toggle\">\n    <!-- events are just here to handle animation - no accessibility needed -->\n    <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n    <div\n      :class=\"['base-toggle__container',\n               { 'base-toggle__container--checked': checkedInt },\n               { 'base-toggle__container--disabled': disabled }]\"\n      @focusin=\"animate = true\"\n      @mouseover=\"animate = true\"\n      @focusout=\"animate = false\"\n      @mouseleave=\"animate = false\">\n      <label\n        :for=\"`toggle-input-${idInt}`\"\n        class=\"base-toggle__input-container\">\n        <input\n          :id=\"`toggle-input-${idInt}`\"\n          v-model=\"checkedInt\"\n          :name=\"name\"\n          :checked=\"checkedInt\"\n          :disabled=\"disabled\"\n          :aria-checked=\"checkedInt\"\n          :aria-disabled=\"disabled\"\n          :aria-required=\"required\"\n          :required=\"required\"\n          :type=\"'checkbox'\"\n          value=\"\"\n          class=\"base-toggle__input\"\n          @click.stop=\"\">\n        <span class=\"base-switch\">\n          <span\n            :class=\"['base-switch__control', { 'base-switch__control--animate': animate }]\">\n            <BaseIcon\n              v-if=\"checkedInt\"\n              :title=\"hideLabel ? label : ''\"\n              name=\"check-mark\" />\n            <BaseIcon\n              v-if=\"!checkedInt\"\n              :title=\"hideLabel ? label : ''\"\n              name=\"remove\" />\n          </span>\n        </span>\n        <span\n          v-if=\"!hideLabel\"\n          class=\"base-toggle__label\">\n          {{ label }}\n        </span>\n        <template\n          v-if=\"invalid && showErrorIcon\">\n          <!-- @slot use a custom icon instead of standard error/warning icon -->\n          <slot name=\"error-icon\">\n            <BaseIcon\n              name=\"attention\"\n              class=\"base-input__error-icon\" />\n          </slot>\n        </template>\n      </label>\n      <span\n        v-if=\"(slotHasContent && checkedInt && bindSlotToState)\n          || (slotHasContent && !bindSlotToState)\"\n        class=\"base-toggle__subtext\">\n        <!-- @slot slot after the label -->\n        <slot />\n      </span>\n    </div>\n    <div\n      v-if=\"invalid && errorMessage\"\n      class=\"base-input__invalid-message\">\n      {{ errorMessage }}\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n@use \"@/styles/variables\" as *;\n\n  .base-toggle {\n    position: relative;\n    --margin-left: calc(30px + #{$spacing-small});\n\n    // class used in BaseFormFieldCreator\n    .base-toggle__container {\n      display: flex;\n      flex-direction: column;\n      justify-content: center;\n\n      &--disabled {\n        color: $font-color-second;\n        cursor: not-allowed;\n      }\n\n      &--checked {\n        .base-switch {\n          .base-switch__control {\n            left: calc(100% - #{$spacing});\n            background-color: $switch-checked-color;\n\n            svg {\n              fill: $switch-svg-checked-color;\n            }\n          }\n        }\n      }\n\n      &:not(.base-toggle__container--disabled) {\n        .base-switch {\n          cursor: pointer;\n        }\n      }\n    }\n\n    .base-toggle__input-container {\n      position: relative;\n      user-select: none;\n      display: flex;\n      align-items: center;\n    }\n\n    .base-toggle__input {\n      position: absolute;\n      left: -1000px;\n      opacity: 0;\n      z-index: map.get($zindex, boxcontent);\n\n      &:focus-visible ~ .base-switch {\n        border: 1px solid $app-color;\n      }\n    }\n\n    .base-toggle__label {\n      padding-left: $spacing-small;\n    }\n\n    .base-input__error-icon {\n      height: $icon-large;\n      width: $icon-large;\n      margin-left: $spacing-small;\n      flex-shrink: 0;\n      color: $app-color;\n    }\n\n    .base-switch {\n      position: relative;\n      display: flex;\n      align-items: center;\n      justify-content: flex-start;\n      height: calc(#{$spacing} + 2px);\n      width: 30px;\n      background-color: $switch-container-color;\n      border-radius: calc((#{$spacing} + 2px) / 2);\n      border: 1px solid $switch-container-color;\n      transition: border-color 250ms ease-in-out;\n      flex: 0 0 auto;\n\n      .base-switch__control {\n        position: absolute;\n        left: 0;\n        display: flex;\n        justify-content: center;\n        width: $spacing;\n        height: $spacing;\n        border-radius: 50%;\n        background-color: $switch-color;\n        pointer-events: none;\n\n        &--animate {\n          transition: all 250ms ease-in-out;\n        }\n\n        svg {\n          width: $spacing-small;\n          fill: $switch-svg-color;\n          pointer-events: none;\n        }\n      }\n    }\n\n    .base-input__invalid-message {\n      font-size: $font-size-small;\n      color: $app-color;\n      line-height: $line-height-small;\n    }\n  }\n\n  .base-toggle__subtext {\n    display: block;\n    margin-left: var(--margin-left);\n    font-size: $font-size-small;\n    line-height: $line-height-small;\n  }\n</style>\n","<script setup>\nimport { onClickOutside } from '@vueuse/core';\nimport { usePopUpLock } from '@/composables/usePopUpLock.js';\nimport {\n  computed,\n  nextTick,\n  onBeforeUnmount,\n  onMounted,\n  onUnmounted,\n  ref, useTemplateRef,\n  watch,\n  watchEffect,\n} from 'vue';\nimport { useId } from '@/composables/useId.js';\nimport { useWindowResize } from '@/composables/useWindowResize.js';\nimport { useElementObserver } from '@/composables/useElementObserver.js';\nimport { useElementFadeOut } from '@/composables/useElementFadeOut.js';\nimport { useEventListener } from '@/composables/useEventListener.js';\nimport { useTabKeyHandler } from '@/composables/useTabKeyHandler.js';\n\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\n\n/**\n * Component to display a tooltip\n *   for additional content e.g.: quick actions\n */\n\ndefineOptions({\n  name: 'BaseTooltipBox',\n});\n\nconst props = defineProps({\n  /**\n     * HTMLElement to attach the tooltip\n     * e.g.: vue ref element\n     */\n  attachTo: {\n    type: null, // HTMLElement makes troubles with nuxt/nuxt-bridge\n    required: true,\n  },\n  /**\n     * define the default direction order\n     */\n  directionOrder: {\n    type: Array,\n    default: () => ['top', 'bottom', 'right', 'left'],\n    validator: val => [...val].sort().toString() === ['top', 'bottom', 'right', 'left'].sort().toString(),\n  },\n  /**\n     * add additional styling\n     * **caveat**: properties `top`, `left` and `right` will be overwritten due position calculation\n     */\n  styles: {\n    type: Object,\n    default: () => ({}),\n  },\n  /**\n     * title of the modal popup on mobile\n     * if more customisation is needed, use the slot `header-title` instead\n     */\n  modalTitle: {\n    type: String,\n    default: '',\n  },\n  /**\n     * specify how the component is rendered on mobile resolutions\n     *\n     * **box**: component is rendered at the `attachTo` HTMLElement\n     * **modal**: component is rendered as a modal popup\n     * **fullscreen**: component is rendered as ap popup with max height and width\n     */\n  typeOnMobile: {\n    type: String,\n    default: 'modal',\n    validator: val => ['box', 'fullscreen', 'modal'].includes(val),\n  },\n  /**\n     * specify a threshold value in px for the box top position calculation\n     * Useful to prevent top alignment of the TooltipBox, for example, when there is a fixed-positioned header (BaseHeader).\n     *\n     * Note: The value can also be set globally with the CSS variable `--base-tooltip-box-threshold-top`.\n     *       The property will be overwritten by the CSS variable.\n     */\n  thresholdTop: {\n    type: Number,\n    default: 0,\n  },\n  /**\n   * customise the tooltipBox id\n   *  if you are using the `header-title` slot this should also be set as id on your custom title element\n   *  (it is also available via slot binding)\n   */\n  headerId: {\n    type: [String, Number],\n    default: 'popup-title',\n  },\n  /**\n   * specify the id of the element containing a description - for accessibility only\n   */\n  descriptionElementId: {\n    type: String,\n    default: 'popup-body',\n  },\n  /**\n   * define if the overlay background should be visible\n   *   (semitransparent black) - this only applies to `typeOnMobile` 'modal'\n   */\n  overlayBackgroundVisible: {\n    type: Boolean,\n    default: false,\n  },\n  /**\n   * define a custom size (in px) when the component should switch to mobile view\n   */\n  mobileSize: {\n    type: Number,\n    default: 640,\n  },\n  /**\n   * HTMLElement to focus after opening the tooltip\n   * Note: If empty, the header title will be focused by default.\n   *       If using the slot for a custom header, be sure to\n   *       define an id attribute with the value `headerId`\n   *       The value should be a valid CSS selector.\n   */\n  initialFocusElement: {\n    type: String,\n    default: '',\n  },\n  /**\n   * list of focusable HTML elements using tab key navigation\n   */\n  focusableElements: {\n    type: Array,\n    // also add all elements in general that have a tabindex, except the ones with value -1\n    default: () => ['a[href]', 'button:enabled', 'input:enabled', '*[tabindex]:not([tabindex=\"-1\"])'],\n  },\n  /**\n   * specify to disable the tab key handler within the component\n   */\n  disableTabKeyHandler: {\n    type: Boolean,\n    default: false,\n  },\n  /**\n   * specify options for the click-outside handler\n   * https://vueuse.org/core/onClickOutside/#type-declarations\n   */\n  clickOutsideOptions: {\n    type: Object,\n    default: () => ({\n      capture: false,\n    }),\n  },\n});\n\nconst emits = defineEmits([\n  /**\n   * Event emitted when close button is clicked or clicked-outside is triggered\n   * @event close\n   * @param {boolean} - the updated state\n   */\n  'close',\n]);\n\n/** GENERAL VARIABLES */\n// define an internal id, needed for aria purposes\nconst internalId = useId();\n// get reference to element\nconst tooltipBox = useTemplateRef('tooltipBoxEl');\n// the HTML element reference for the actual tooltip container\nconst tooltipInner = ref(null);\n// ref variable for the container body (handling fade-out)\nconst body = ref(null);\n// ref variable for the tooltip body inner element (within fade out)\nconst bodyInner = ref(null);\n\n// variable to steer visibility of tooltip box when active\nconst isActive = ref(false);\n\nconst { isMobile } = useWindowResize({\n  callback: calcPosition,\n  mobileMaxSize: props.mobileSize,\n  callOnMounted: true,\n});\n\n/** CLICK OUTSIDE HANDLING */\n// guard for click-outside-event\nconst isClickOutsideActive = ref(false);\n\n/**\n * trigger event to remove/close the component\n */\nfunction close() {\n  emits('close');\n}\n\n/**\n * intercept escape key event and reset edit mode\n */\nfunction escEventHandler(e) {\n  if (e.key === 'Escape') {\n    close();\n  }\n}\n\nuseEventListener({\n  // need to pass a string since window not defined in setup for SSR\n  target: 'window',\n  event: 'keydown',\n  callback: escEventHandler,\n});\n\n/**\n * intercept click-outside event and close the component\n */\nonClickOutside(\n  tooltipInner,\n  () => {\n    if (isClickOutsideActive.value) {\n      close();\n    }\n  },\n  props.clickOutsideOptions,\n);\n\n/** FADE OUT RELATED FUNCTIONALITY */\n// use the whole boxFadeOut object instead of destructuring it because otherwise\n// reactivity is destroyed\nconst { boxFadeOut, calcFadeOut } = useElementFadeOut(body, {\n  // TODO: refactor to use build in classes and pseudo elements\n  className: '',\n});\n\n/** TOOLTIP POSITION HANDLING */\nconst direction = ref(null);\nconst css = ref({\n  top: '0',\n  left: '-10000px',\n});\nconst thresholdX = ref(2); // px, distance between tooltip and attachTo element\nconst thresholdY = ref(2); // px, distance between tooltip and attachTo element\nconst spacing = ref(8); // px, distance from window's left or right boundary\n\n/**\n * get the thresholdTop value from the CSS variables if defined,\n * create a temporary ghost element and evaluate the computed style value,\n * otherwise use the component prop\n * @returns {number}\n */\nconst thresholdTopInt = computed(() => {\n  // get optional global css variable\n  const style = getComputedStyle(document.body);\n  const thresholdTopCssVar = style.getPropertyValue('--base-tooltip-box-threshold-top');\n\n  // do nothing if the css variable is not defined\n  if (!thresholdTopCssVar) return props.thresholdTop;\n\n  // check if the css variable contains only digits and return it\n  if (/^\\d+$/.test(thresholdTopCssVar)) return Number(thresholdTopCssVar);\n\n  // create a ghost node element to evaluate top value in px\n  const elem = document.createElement('div');\n  elem.style.position = 'absolute';\n  elem.style.top = thresholdTopCssVar;\n  elem.style.visibility = 'hidden';\n  // append the ghost element to body\n  document.body.appendChild(elem);\n  // get computed style value\n  const computedTop = window.getComputedStyle(elem).top;\n  // remove non digits (px unit)\n  const thresholdTopAsNumber = Number(computedTop.replace(/\\D/g, ''));\n  // remove ghost element\n  elem.remove();\n\n  // return value\n  return thresholdTopAsNumber;\n});\n\n/**\n * calc absolute tooltip and inner triangle position\n */\nfunction calcPosition() {\n  if (!tooltipBox.value) return;\n  css.value = {};\n  // anchor elements current position\n  const attachToRect = props.attachTo.getBoundingClientRect();\n\n  // sizes\n  const boxWidth = tooltipBox.value.offsetWidth;\n  const boxHeight = tooltipBox.value.offsetHeight;\n  const triangleHeight = parseFloat(window.getComputedStyle(tooltipBox.value, ':after').height) / 2;\n  const triangleWidth = parseFloat(window.getComputedStyle(tooltipBox.value, ':after').width) / 2;\n\n  // current scroll position\n  const { scrollY } = window;\n\n  // loop through the preferred direction order\n  // and choose the first direction which fits and leave the loop\n  props.directionOrder.every((directionOption) => {\n    if (directionOption === 'left'\n        // check if fits to the left\n        && attachToRect.left > boxWidth + triangleWidth\n        // check if box overlaps the window top\n        && !(attachToRect.top + (attachToRect.height / 2) - thresholdTopInt.value < boxHeight / 2)\n        // check if box overlaps the window bottom\n        && !(window.innerHeight - (attachToRect.top + (attachToRect.height / 2)) < boxHeight / 2)) {\n      direction.value = 'left';\n      css.value.top = `${attachToRect.top + attachToRect.height / 2 - boxHeight / 2 + scrollY}px`;\n      css.value.left = `${attachToRect.left - boxWidth - triangleWidth - thresholdX.value}px`;\n      return false;\n    }\n\n    if (directionOption === 'right'\n        // check if fits to the right\n        && window.innerWidth - attachToRect.right > boxWidth + triangleWidth\n        // check if box overlaps the window top\n        && !((attachToRect.top + attachToRect.height / 2) - thresholdTopInt.value < boxHeight / 2)\n        // check if box overlaps the window bottom\n        && !(window.innerHeight - (attachToRect.top + (attachToRect.height / 2)) < boxHeight / 2)) {\n      direction.value = 'right';\n      css.value.top = `${attachToRect.top + attachToRect.height / 2 - boxHeight / 2 + scrollY}px`;\n      css.value.left = `${attachToRect.right + triangleWidth + thresholdX.value}px`;\n      return false;\n    }\n\n    if (directionOption === 'top'\n        // check if fits to the top\n        && attachToRect.top - thresholdTopInt.value > boxHeight + triangleHeight + thresholdY.value) {\n      direction.value = 'top';\n      css.value.top = `${attachToRect.top - boxHeight - triangleHeight - thresholdY.value + scrollY}px`;\n      css.value.left = `${attachToRect.left + (attachToRect.width / 2) - (boxWidth / 2)}px`;\n      return false;\n    }\n\n    if (directionOption === 'bottom'\n        // check if fits to the bottom\n        && window.innerHeight - attachToRect.bottom\n        > boxHeight + triangleHeight + thresholdY.value + spacing.value) {\n      direction.value = 'bottom';\n      css.value.top = `${attachToRect.bottom + triangleHeight + thresholdY.value + scrollY}px`;\n      css.value.left = `${attachToRect.left + (attachToRect.width / 2) - (boxWidth / 2)}px`;\n      return false;\n    }\n    return true;\n  });\n\n  // center the triangle by default\n  css.value['--triangle-left'] = '50%';\n\n  // Direction 'top' or 'bottom':\n  // Check again if the box overlaps the window on the left or right side.\n  // If so, reposition the box and adjust the triangle's position relative to the anchor point.\n  if (!['top', 'bottom'].includes(direction.value)) {\n    return;\n  }\n\n  // the box overlaps the window left side\n  if (attachToRect.x < boxWidth / 2) {\n    css.value.left = `${spacing.value}px`;\n    css.value.right = `${spacing.value}px`; // clear right position\n    css.value['--triangle-left'] = `${attachToRect.left + attachToRect.width / 2 - spacing.value}px`;\n    return;\n  }\n\n  // the box overlaps the window right side\n  if (attachToRect.left + attachToRect.width / 2 + boxWidth / 2 > window.innerWidth) {\n    css.value.left = ''; // clear left position\n    css.value.right = `${spacing.value}px`;\n    css.value['--triangle-left'] = `${boxWidth + spacing.value\n    - (document.body.clientWidth - (attachToRect.right - attachToRect.width / 2))}px`;\n  }\n}\n\n/** BODY SCROLL LOCK HANDLING */\nconst { toggleScrollLock } = usePopUpLock(tooltipBox);\n\nconst isPopUpLockEnabled = computed(() => (props.typeOnMobile === 'modal' || props.typeOnMobile === 'fullscreen')\n      && isMobile.value);\n\n/** ADDING OBSERVERS FOR FADEOUT AND TOOLTIP POSITIONING */\n/**\n * watch if attachTo has changed and calculate the component position again\n */\nwatch(() => props.attachTo, () => {\n  nextTick(() => {\n    calcFadeOut();\n    calcPosition();\n  });\n});\n\nfunction onMutation() {\n  calcPosition();\n}\n\nuseElementObserver({\n  type: 'mutation',\n  target: bodyInner,\n  callback: onMutation,\n  options: { childList: true, subtree: true },\n});\n\n/**\n * FOCUS / TABKEY HANDLING HANDLING\n */\n/**\n * variable to store the element active before the tooltip box was opened\n * @type {[null] extends [Ref] ? IfAny<null, Ref<null>, null> : Ref<UnwrapRef<null>, UnwrapRef<null> | null>}\n */\nconst prevActiveElement = ref(null);\n// init tab key handler\nconst { focusableHTMLTags, disableHandler } = useTabKeyHandler(tooltipBox, props.focusableElements.join(', '), props.disableTabKeyHandler);\n// watcher to set specific properties\nwatchEffect(() => {\n  focusableHTMLTags.value = props.focusableElements;\n  disableHandler.value = props.disableTabKeyHandler;\n});\n/**\n * determine which element should be focused when opening the component\n */\nfunction focusInitialElement() {\n  setTimeout(() => {\n    // by default for box mode, focus the component container\n    let focusElement = tooltipBox.value;\n    // if the component is in popup mode and within mobile resolution, focus the popup title\n    if (props.typeOnMobile !== 'box' && isMobile.value) {\n      focusElement = props.headerId ? document.querySelector(`#${props.headerId}`) : undefined;\n    }\n    // if a specific element within the component is defined, try that one\n    if (props.initialFocusElement && document.querySelector(props.initialFocusElement)) {\n      focusElement = document.querySelector(props.initialFocusElement);\n    }\n    // finally, focus the element\n    if (focusElement) focusElement.focus();\n  }, 0);\n}\n\nonMounted(() => {\n  // save the previously active element\n  prevActiveElement.value = document?.activeElement;\n  // focus a specific element when the component is opened\n  focusInitialElement();\n  // move the component to the body node to position it absolutely in the document\n  document.querySelector('body')\n    .appendChild(tooltipBox.value);\n\n  // Note: the click-outside event is executed immediately when the component is initialized.\n  //       To prevent this timing problem, the guard variable is set with a delay.\n  setTimeout(() => {\n    isClickOutsideActive.value = true;\n  }, 0);\n  // In SSR environment, the first position calculation is wrong.\n  // To prevent this timing problem, the calc and further functions are executed with a delay.\n  // Using nextTick() has no effect for whatever reason.\n  setTimeout(() => {\n    // calc components position and activate it\n    calcPosition();\n    isActive.value = true;\n    // block body scrolling\n    toggleScrollLock(isPopUpLockEnabled.value);\n  }, 0);\n});\n\nonBeforeUnmount(() => {\n  // when the tooltipBox is closed, try to focus the previous active element\n  if (prevActiveElement.value\n    // but not if an element of the same class is now focused (case where tooltip box\n    // is closed and another one is immediately opened)\n    // this is good enough for our current use case, but we might need to think of a more\n    // thoroughly solution in future (prop for exempt classes?)\n    && JSON.stringify(prevActiveElement.value.classList) !== JSON\n      .stringify(document.activeElement.classList)) {\n    prevActiveElement.value.focus();\n  }\n});\n\nonUnmounted(() => {\n  isActive.value = false;\n});\n</script>\n\n<template>\n  <div\n    :id=\"internalId\"\n    ref=\"tooltipBoxEl\"\n    role=\"dialog\"\n    tabindex=\"-1\"\n    :aria-labelledby=\"headerId\"\n    :aria-describedby=\"descriptionElementId\"\n    :style=\"{ ...styles, ...css }\"\n    :class=\"['base-tooltip-box',\n             { 'base-tooltip-box--background-visible': overlayBackgroundVisible },\n             'base-tooltip-box--' + direction,\n             { 'base-tooltip-box--modal-on-mobile': typeOnMobile === 'modal'\n               || typeOnMobile === 'fullscreen' },\n             { 'base-tooltip-box--fullscreen-on-mobile': typeOnMobile === 'fullscreen' },\n             { 'base-tooltip-box--active': isActive }]\">\n    <div\n      :id=\"descriptionElementId\"\n      ref=\"tooltipInner\"\n      class=\"base-tooltip-box__inner\">\n      <div class=\"base-tooltip-box__header\">\n        <!-- @slot customize the header displayed on mobile for `typeOnMobile` `modal` and `fullscreen`\n        @binding header-id {string, number} bind this id to your slot element containing the title text for assistive technology to work properly -->\n        <slot\n          name=\"header-title\"\n          :header-id=\"headerId\">\n          <div\n            :id=\"headerId\"\n            tabindex=\"-1\"\n            class=\"base-tooltip-box__header__title\">\n            {{ modalTitle }}\n          </div>\n        </slot>\n        <button\n          title=\"close\"\n          class=\"base-tooltip-box__button\"\n          @click=\"close\">\n          <BaseIcon\n            name=\"remove\"\n            class=\"base-tooltip-box__button__icon\" />\n        </button>\n      </div>\n      <div\n        ref=\"body\"\n        :class=\"['base-tooltip-box__body',\n                 {'base-tooltip-box__body--fade-out': boxFadeOut.top || boxFadeOut.bottom},\n                 { 'base-tooltip-box__body--fade-out--top': boxFadeOut.top },\n                 { 'base-tooltip-box__body--fade-out--bottom': boxFadeOut.bottom }]\">\n        <div\n          ref=\"bodyInner\"\n          class=\"base-tooltip-box__body__inner\">\n          <!-- @slot slot to inject box content -->\n          <slot>\n            <i>use default slot</i>\n          </slot>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n@use \"@/styles/variables\" as *;\n\n  .base-tooltip-box {\n    position: absolute;\n    z-index: map.get($zindex, modal);\n    min-width: 200px;\n    max-height: 50vh;\n    max-width: calc(100% - $spacing);\n    color: $font-color;\n    background-color: #fff;\n    visibility: hidden;\n    opacity: 0;\n    transition: opacity 150ms ease-in;\n    filter: drop-shadow($tooltip-drop-shadow);\n    // Use the GPU to render the element. Otherwise, the drop-shadow\n    // will disappear after the opacity transition finishes on MacOS Safari\n    transform: translateZ(0);\n\n    &__inner {\n      position: relative;\n      display: flex;\n      flex-direction: column;\n      height: 100%;\n    }\n\n    &__header {\n      display: none;\n\n      &__title {\n        margin-right: $spacing-small;\n        white-space: normal;\n        text-overflow: initial;\n        display: -webkit-box;\n        -webkit-line-clamp: 2;\n        -webkit-box-orient: vertical;\n        max-height: 100%;\n        overflow: hidden;\n      }\n    }\n\n    &__body {\n      margin: $spacing;\n      flex: 1;\n      overflow: auto;\n      max-height: calc(50vh - #{$spacing-large});\n\n      &--fade-out {\n        &::before,\n        &::after {\n          pointer-events: none;\n          content: '';\n          height: $line-height;\n          position: absolute;\n          left: $spacing;\n          right: $spacing;\n          z-index: map.get($zindex, fadeout);\n        }\n\n        &--top {\n          &::before {\n            top: $spacing;\n            background: linear-gradient(to top, rgba(255, 255, 255, 0), white);\n          }\n        }\n\n        &--bottom {\n          &::after {\n            bottom: $spacing;\n            background: linear-gradient(to bottom, rgba(255, 255, 255, 0), white);\n          }\n        }\n      }\n\n      .base-tooltip-box__body__inner {\n        overflow: hidden;\n      }\n    }\n\n    &__label {\n      display: inline-block;\n      font-weight: bold;\n      margin-bottom: $spacing-small;\n    }\n\n    &__button {\n      display: flex;\n      flex-shrink: 0;\n      transition: $link-transition;\n\n      &__icon {\n        width: $icon-medium;\n        height: $icon-medium;\n        cursor: pointer;\n      }\n\n      &:hover,\n      &:active,\n      &:focus {\n        color: $app-color;\n        fill: $app-color;\n      }\n    }\n\n    &--active {\n      visibility: visible;\n      opacity: 1;\n      cursor: default;\n    }\n\n    // on mobile\n    &.base-tooltip-box--modal-on-mobile {\n      @media screen and (max-width: $mobile) {\n        position: fixed;\n        top: 0 !important;\n        left: 0 !important;\n        right: 0 !important;\n        width: 100vw;\n        height: 100vh;\n        max-height: 100vh;\n        max-width: inherit;\n        background-color: transparent;\n        z-index: map.get($zindex, modal);\n\n        &.base-tooltip-box--background-visible {\n          background-color: $overlay-background-light;\n        }\n\n        .base-tooltip-box__inner {\n          position: relative;\n          margin: 10vh auto 0;\n          width: 90%;\n          max-height: 80vh;\n          height: initial;\n          background-color: #fff;\n        }\n\n        .base-tooltip-box__header {\n          background-color: $button-header-color;\n          height: $row-height-large;\n          padding: 0 #{$spacing};\n          display: flex;\n          flex-direction: row;\n          justify-content: space-between;\n          align-items: center;\n          flex-shrink: 0;\n        }\n\n        &:after {\n          display: none;\n        }\n\n        .base-tooltip-box__body--fade-out--top {\n          &::before {\n            top: $row-height-large + $spacing;\n          }\n        }\n      }\n    }\n\n    &.base-tooltip-box--fullscreen-on-mobile {\n      @media screen and (max-width: $mobile) {\n        max-width: inherit;\n\n        .base-tooltip-box__body {\n          max-height: calc(100% - #{$spacing-large});\n        }\n\n        .base-tooltip-box__inner {\n          margin: 0;\n          width: 100%;\n          height: 100vh;\n          max-height: inherit;\n        }\n      }\n    }\n\n    // add triangle for non mobile sizes\n    &:after {\n      content: '';\n      position: absolute;\n      display: inline-block;\n      border-width: 8px;\n      border-style: solid;\n      pointer-events: none;\n    }\n\n    &--top {\n      &:after {\n        left: var(--triangle-left);\n        bottom: 0;\n        transform: translate(-50%, 100%);\n        border-color: #fff transparent transparent transparent;\n      }\n    }\n\n    &--bottom {\n      &:after {\n        top: 0;\n        left: var(--triangle-left);\n        transform: translate(-50%, -100%);\n        border-color: transparent transparent #fff transparent;\n      }\n    }\n\n    &--left {\n      &:after {\n        top: 50%;\n        right: 0;\n        transform: translate(100%, -50%);\n        border-color: transparent transparent transparent #fff;\n      }\n    }\n\n    &--right {\n      &:after {\n        top: 50%;\n        left: 0;\n        transform: translate(-100%, -50%);\n        border-color: transparent #fff transparent transparent;\n      }\n    }\n  }\n</style>\n","<script>\nimport BaseButton from '@/components/BaseButton/BaseButton.vue';\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport BaseLoader from '@/components/BaseLoader/BaseLoader.vue';\nimport BasePopUp from '@/components/BasePopUp/BasePopUp.vue';\nimport BaseProgressBar from '@/components/BaseProgressBar/BaseProgressBar.vue';\nimport { useI18n } from '@/composables/useI18n.js';\n\n/**\n * A component taking care of uploads within a pop up\n */\n\nexport default {\n  name: 'BaseUploadPopUp',\n  components: {\n    BaseButton,\n    BaseIcon,\n    BaseLoader,\n    BasePopUp,\n    BaseProgressBar,\n  },\n  props: {\n    /**\n     * register files to upload\n     * array with file-object(s) from file-input field\n     */\n    fileList: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * define current status\n     * @values initial, saving, success, failed\n     */\n    currentStatus: {\n      type: String,\n      default: 'initial',\n      validate(val) {\n        return ['initial', 'saving', 'success', 'failed'].includes(val);\n      },\n    },\n    /**\n     * define button text\n     * could be string or path to i18n json as well\n     */\n    cancelButtonText: {\n      type: String,\n      default: 'cancel',\n    },\n    /**\n     * specify informational texts for the component -\n     * this needs to be an object with the following properties:\n     *\n     *   **title** `string` - text used in the popup header\n     *   **upload** `string` - default button text\n     *   **done** `string` - button text when upload finished\n     *   **retry** `string` - button text when an upload error occurs\n     *   **quotaExceeded** `- string` text used when user quota is exceeded\n     *\n     * The values of this object might be plain text or a key for an i18n file\n     */\n    uploadText: {\n      type: Object,\n      default: () => ({\n        title: 'File Upload',\n        upload: 'Upload',\n        done: 'Done',\n        retry: 'Try Again',\n        quotaExceeded: 'Unfortunately you exceeded your quota, because you have '\n          + 'only {space} of space left. Please remove some files to enable uploading.',\n      }),\n    },\n    /**\n     * current upload progress in percent per file\n     * array with current upload progress per file\n     * e.g. [11, 55, 100]\n     */\n    uploadPercentage: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * define current free storage space (bytes)\n     */\n    userSpace: {\n      type: Number,\n      default: 10000000,\n    },\n    /**\n     * define rejected files\n     * array with filename(s)\n     */\n    rejectedFiles: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * define uploaded files\n     * array with filename(s)\n     */\n    uploadedFiles: {\n      type: Array,\n      default: () => [],\n    },\n    /**\n     * define errors for rejected files\n     * array with objects\n     * eg: `[{ name: 'foo.txt', message: 'The file may include a virus' }]`\n     * Note: each object must contain the properties: `name`, `message`\n     */\n    fileErrors: {\n      type: Array,\n      default: () => [],\n      // checking if all necessary properties are part of the provided object\n      validator: (val) => {\n        if (val.length) {\n          return !['name', 'message']\n            .every(prop => Object.keys(val).includes(prop));\n        }\n        return true;\n      },\n    },\n  },\n  emits: ['remove-file', 'start-upload', 'cancel-upload'],\n  setup() {\n    const { getI18nTerm, getLangLabel } = useI18n();\n    return {\n      getLangLabel,\n      getI18nTerm,\n    };\n  },\n  computed: {\n    buttonText() {\n      if (this.currentStatus === 'initial' || this.currentStatus === 'saving') {\n        return this.getI18nTerm(this.getLangLabel(this.uploadText.upload));\n      }\n      if (this.rejectedFiles.length) {\n        return this.getI18nTerm(this.getLangLabel(this.uploadText.retry));\n      }\n      return this.getI18nTerm(this.getLangLabel(this.uploadText.done));\n    },\n    userQuotaExceeded() {\n      return this.userSpace < this.fileList\n        .reduce((prev, curr) => prev + curr.size, 0);\n    },\n  },\n  methods: {\n    convertSpace(bytes, si) {\n      let newBytes = bytes;\n      const thresh = si ? 1000 : 1024;\n      if (Math.abs(bytes) < thresh) {\n        return `${bytes} B`;\n      }\n      const units = si\n        ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n        : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];\n      let u = -1;\n      do {\n        newBytes /= thresh;\n        u += 1;\n      } while (Math.abs(newBytes) >= thresh && u < units.length - 1);\n      return `${newBytes.toFixed(1)} ${units[u]}`;\n    },\n    getStatus(fileName) {\n      if (this.uploadedFiles.includes(fileName)) {\n        return 'success';\n      }\n      if (this.rejectedFiles.includes(fileName)) {\n        return 'fail';\n      }\n      return '';\n    },\n    getErrorMessage(fileName) {\n      if (this.fileErrors.find(file => file.name === fileName)) {\n        const { message } = this.fileErrors.find(file => file.name === fileName);\n        return message;\n      }\n      return '';\n    },\n    cancelUpload() {\n      /**\n       * Event emitted when cancel button is clicked\n       *\n       * @event cancel-upload\n       */\n      this.$emit('cancel-upload');\n    },\n    startUpload() {\n      /**\n       * Event emitted when upload button is clicked\n       *\n       * @event start-upload\n       */\n      this.$emit('start-upload');\n    },\n    removeFile(index) {\n      /**\n       * Event emitted when remove button on file entry is clicked\n       *\n       * @event remove-file\n       * @property {number} - index of the file entry\n       */\n      this.$emit('remove-file', index);\n    },\n  },\n};\n</script>\n\n<template>\n  <BasePopUp\n    v-if=\"!!fileList.length\"\n    :title=\"getI18nTerm(getLangLabel(uploadText.title))\"\n    @close=\"cancelUpload\">\n    <TransitionGroup name=\"list-complete\">\n      <div\n        v-if=\"userQuotaExceeded\"\n        key=\"user-warning\"\n        class=\"base-uploader-user-warning\">\n        <BaseIcon\n          name=\"attention\"\n          class=\"icon base-uploader-user-warning-icon\" />\n        {{ getI18nTerm(\n          getLangLabel(uploadText.quotaExceeded),\n          1,\n          { space: convertSpace(userSpace) }\n        ) }}\n      </div>\n\n      <div\n        key=\"upload-area\"\n        class=\"popup-upload-area\">\n        <TransitionGroup\n          name=\"bar-move\">\n          <BaseProgressBar\n            v-for=\"(file, index) of fileList\"\n            :key=\"file.name\"\n            :progress=\"uploadPercentage[index]\"\n            :file-name=\"file.name\"\n            :file-size=\"userQuotaExceeded ? convertSpace(file.size) : ''\"\n            :status=\"getStatus(file.name)\"\n            :error-message=\"getErrorMessage(file.name)\"\n            :show-remove=\"currentStatus === 'initial' && fileList.length > 1\"\n            class=\"upload-bar\"\n            @remove-item=\"removeFile(index)\" />\n        </TransitionGroup>\n      </div>\n    </TransitionGroup>\n\n    <!-- @slot slot for additional content after upload bars but before buttons -->\n    <slot />\n\n    <template #button-row>\n      <BaseButton\n        v-if=\"currentStatus === 'initial' || currentStatus === 'failed'\"\n        :text=\"getI18nTerm(cancelButtonText)\"\n        :icon=\"'remove'\"\n        :icon-position=\"'right'\"\n        :icon-size=\"'small'\"\n        class=\"base-upload-bar-button\"\n        @clicked=\"cancelUpload\" />\n\n      <BaseButton\n        ref=\"uploadButton\"\n        :text=\"buttonText\"\n        :icon=\"currentStatus !== 'saving' && currentStatus !== 'failed' ? 'check-mark' : ''\"\n        :icon-position=\"'right'\"\n        :icon-size=\"'small'\"\n        :disabled=\"currentStatus === 'saving' || userQuotaExceeded\"\n        class=\"base-upload-bar-button\"\n        @clicked=\"startUpload\">\n        <template\n          v-if=\"currentStatus === 'saving'\"\n          #right-of-text>\n          <span class=\"base-upload-bar-loader\">\n            <BaseLoader />\n          </span>\n        </template>\n      </BaseButton>\n    </template>\n  </BasePopUp>\n</template>\n\n<style lang=\"scss\" scoped>\n  @use \"@/styles/variables\" as *;\n\n  .base-uploader-user-warning {\n    color: $warning-color;\n    fill: $warning-color;\n    margin-bottom: $spacing;\n    display: flex;\n    align-items: center;\n\n    .icon {\n      height: $icon-large;\n      width: $icon-large;\n      max-width: $icon-large;\n\n      &.base-uploader-user-warning-icon {\n        margin-right: $spacing-small;\n        flex: 0 0 auto;\n      }\n    }\n  }\n\n  .popup-text {\n    display: flex;\n    align-items: flex-end;\n    margin-top: $spacing;\n\n    .upload-dropdown {\n      width: calc(50% - #{$spacing-small});\n      flex: 0 0 auto;\n    }\n  }\n\n  .popup-text > div:first-of-type {\n    margin-right: $spacing;\n  }\n\n  .files-popup-input-field {\n    margin-bottom: $spacing;\n  }\n\n  .popup-upload-area {\n    max-height: 50vh;\n    overflow-y: auto;\n\n    .upload-bar:not(:last-child) {\n      margin-bottom: $spacing;\n    }\n  }\n\n  .base-upload-bar-button {\n    flex-basis: 100%;\n    transition: color 250ms ease-in-out;\n  }\n\n  .base-upload-bar-button + .base-upload-bar-button {\n    margin-left: $spacing;\n  }\n\n  .list-complete-enter-from,\n  .list-complete-leave-to {\n    opacity: 0;\n    transform: translateY(-15px);\n  }\n\n  .list-complete-leave-active {\n    position: absolute;\n  }\n\n  .list-complete-move {\n    transition: all 200ms;\n  }\n\n  .bar-move-leave-active {\n    opacity: 0;\n    transition: all 250ms;\n  }\n\n  @media screen and (max-width: $mobile) {\n    .popup-upload-area {\n      max-height: ($row-height-small + $spacing) * 5;\n    }\n\n    .base-upload-bar-button + .base-upload-bar-button {\n      margin-left: 0;\n      margin-top: $spacing;\n    }\n  }\n\n  @media screen and (max-height: 600px) {\n    .popup-upload-area {\n      max-height: 40vh;\n    }\n  }\n  @media screen and (max-height: 500px) {\n    .popup-upload-area {\n      max-height: 40vh;\n    }\n  }\n  @media screen and (max-height: 400px) {\n    .popup-upload-area {\n      max-height: 30vh;\n    }\n  }\n  @media screen and (max-height: 300px) {\n    .popup-upload-area {\n      max-height: 20vh;\n    }\n  }\n</style>\n\n<style lang=\"scss\">\n@use \"@/styles/variables\" as *;\n\n.base-upload-bar-loader {\n  position: relative;\n  transform: scale(0.5);\n  margin-left: $spacing;\n  padding-left: $spacing;\n}\n</style>\n","<script setup>\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\n\ndefineOptions({\n  name: 'BaseNotification',\n});\n\nconst props = defineProps({\n  /**\n   * time the notification is shown\n   */\n  duration: {\n    type: Number,\n    default: 4000,\n  },\n  /**\n   * set a notification group name to handle groups independently\n   *\n   * **deprecation warning**: currently default is set to 'request-notifications' to not break backwards\n   *  compatibility however this will be removed in future major versions! Add group=\"request-notifications\"\n   *  to your component in front-end if you want to keep the group!\n   */\n  group: {\n    type: String,\n    default: 'request-notifications',\n  },\n  /**\n   * define if a header is present to display notification below that header\n   *\n   * if a header is present make sure the css variable `--header-height` is\n   * set correctly!\n   */\n  hasHeader: {\n    type: Boolean,\n    default: true,\n  },\n});\n\n// capitalize first letter of title\nfunction notificationTitle(val) {\n  return val.slice(0, 1).toUpperCase() + val.slice(1);\n}\n</script>\n\n<template>\n  <div\n    :class=\"[\n      'base-notification',\n      { 'base-notification--no-base-header': !props.hasHeader }]\">\n    <div class=\"base-notification__wrapper\">\n      <Notifications\n        :duration=\"props.duration\"\n        :width=\"'100%'\"\n        :group=\"group\"\n        position=\"top right\"\n        animation-name=\"v-slide\">\n        <template\n          #body=\"{ item, close }\">\n          <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions vuejs-accessibility/click-events-have-key-events -->\n          <div\n            role=\"alert\"\n            :class=\"[`base-notification__notification--${item.type}`, 'base-notification__notification']\"\n            @click=\"close\">\n            <BaseIcon\n              v-if=\"item.type === 'error'\"\n              name=\"attention\"\n              class=\"icon base-notification__status-icon\" />\n            <BaseIcon\n              v-else-if=\"item.type === 'success'\"\n              name=\"success\"\n              class=\"base-notification__status-icon\" />\n            <div class=\"base-notification__text\">\n              <h5\n                class=\"base-notification__title\">\n                {{ notificationTitle(item.title) }}\n              </h5>\n              <!-- eslint-disable vue/no-v-html -->\n              <div\n                class=\"base-notification__message\"\n                v-html=\"item.text\" />\n              <!-- eslint-enable -->\n            </div>\n\n            <button\n              class=\"base-notification__close\"\n              @click=\"close\">\n              <BaseIcon\n                name=\"remove\"\n                aria-labelledby=\"title\"\n                class=\"base-notification__icon\" />\n            </button>\n          </div>\n        </template>\n      </Notifications>\n    </div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"@/styles/variables\" as *;\n@use \"sass:map\";\n\n.base-notification {\n  position: sticky;\n  top: $header-height;\n  z-index: map.get($zindex, notification);\n  max-width: 100%;\n  margin-top: $header-height;\n\n  @media screen and (min-width: $tablet) {\n    max-width: 450px;\n  }\n\n  &--no-base-header {\n    margin-top: 0;\n    top: 0;\n  }\n\n  &.fixed {\n    position: fixed;\n    top: $header-height;\n  }\n\n  .base-notification__wrapper {\n    position: relative;\n\n    :deep(.vue-notification-wrapper) {\n      box-shadow: 0 3px 3px rgba(0, 0, 0, .05);\n    }\n\n    :deep(.vue-notification-group) {\n      position: absolute;\n    }\n  }\n\n  @media screen and (max-width: $mobile) {\n    z-index: map.get($zindex, notification_mobile);\n  }\n}\n\n.base-notification__notification {\n  position: relative;\n  padding: $spacing;\n  background-color: white;\n  font-size: $font-size-small;\n  display: flex;\n  align-items: center;\n  border-left: 5px solid $app-color;\n  border-top: 1px solid $button-header-color;\n\n  .base-notification__text {\n    flex-grow: 1;\n\n    .base-notification__title {\n      font-size: inherit;\n      font-weight: 600;\n    }\n\n    .base-notification__message {\n      word-break: break-word;\n    }\n  }\n\n  .base-notification__close {\n    margin: auto;\n    cursor: pointer;\n    flex-shrink: 0;\n\n    .base-notification__icon {\n      width: $icon-medium;\n      max-height: $icon-medium;\n      vertical-align: middle;\n      margin-left: $spacing;\n    }\n  }\n\n  .base-notification__status-icon {\n    width: $icon-large;\n    max-height: $icon-large;\n    margin-right: $spacing;\n    fill: $font-color-second;\n    stroke: $font-color-second;\n    flex-shrink: 0;\n  }\n}\n\n.v-slide-enter-active,\n.v-slide-leave-active,\n.v-slide-move {\n  transition: all 1s ease;\n}\n\n.slide-fade-enter, .v-slide-leave-to {\n  background-color: transparent;\n  opacity: 0;\n}\n\n.v-slide-leave-active {\n  z-index: 0;\n  position: absolute;\n}\n</style>\n","import Notifications from '@kyvg/vue3-notification';\nimport BaseNotification from '@/components/BaseNotification/BaseNotification.vue';\n\nconst BaseNotificationsPlugin = {\n  install(app) {\n    app.use(Notifications);\n    app.component('BaseNotification', BaseNotification);\n  },\n};\n\nexport default BaseNotificationsPlugin;\n","var an = Object.defineProperty;\nvar Pe = Object.getOwnPropertySymbols;\nvar yt = Object.prototype.hasOwnProperty, wt = Object.prototype.propertyIsEnumerable;\nvar bt = (t, e, n) => e in t ? an(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n, fe = (t, e) => {\n  for (var n in e || (e = {}))\n    yt.call(e, n) && bt(t, n, e[n]);\n  if (Pe)\n    for (var n of Pe(e))\n      wt.call(e, n) && bt(t, n, e[n]);\n  return t;\n};\nvar $e = (t, e) => {\n  var n = {};\n  for (var o in t)\n    yt.call(t, o) && e.indexOf(o) < 0 && (n[o] = t[o]);\n  if (t != null && Pe)\n    for (var o of Pe(t))\n      e.indexOf(o) < 0 && wt.call(t, o) && (n[o] = t[o]);\n  return n;\n};\nimport { getCurrentInstance as dt, unref as U, watch as ln, onUnmounted as sn, onMounted as un, nextTick as kt, isRef as qe, defineComponent as cn, computed as Et, toRefs as fn, ref as dn, reactive as hn, h as pn, isProxy as gn } from \"vue\";\nconst Ht = \"[vue-draggable-plus]: \";\nfunction mn(t) {\n  console.warn(Ht + t);\n}\nfunction vn(t) {\n  console.error(Ht + t);\n}\nfunction St(t, e, n) {\n  return n >= 0 && n < t.length && t.splice(n, 0, t.splice(e, 1)[0]), t;\n}\nfunction bn(t) {\n  return t.replace(/-(\\w)/g, (e, n) => n ? n.toUpperCase() : \"\");\n}\nfunction yn(t) {\n  return Object.keys(t).reduce((e, n) => (typeof t[n] != \"undefined\" && (e[bn(n)] = t[n]), e), {});\n}\nfunction Dt(t, e) {\n  return Array.isArray(t) && t.splice(e, 1), t;\n}\nfunction _t(t, e, n) {\n  return Array.isArray(t) && t.splice(e, 0, n), t;\n}\nfunction wn(t) {\n  return typeof t == \"undefined\";\n}\nfunction En(t) {\n  return typeof t == \"string\";\n}\nfunction Tt(t, e, n) {\n  const o = t.children[n];\n  t.insertBefore(e, o);\n}\nfunction Ke(t) {\n  t.parentNode && t.parentNode.removeChild(t);\n}\nfunction Sn(t, e = document) {\n  var o;\n  let n = null;\n  return typeof (e == null ? void 0 : e.querySelector) == \"function\" ? n = (o = e == null ? void 0 : e.querySelector) == null ? void 0 : o.call(e, t) : n = document.querySelector(t), n || mn(`Element not found: ${t}`), n;\n}\nfunction Dn(t, e, n = null) {\n  return function(...o) {\n    return t.apply(n, o), e.apply(n, o);\n  };\n}\nfunction _n(t, e) {\n  const n = fe({}, t);\n  return Object.keys(e).forEach((o) => {\n    n[o] ? n[o] = Dn(t[o], e[o]) : n[o] = e[o];\n  }), n;\n}\nfunction Tn(t) {\n  return t instanceof HTMLElement;\n}\nfunction Ct(t, e) {\n  Object.keys(t).forEach((n) => {\n    e(n, t[n]);\n  });\n}\nfunction Cn(t) {\n  return t.charCodeAt(0) === 111 && t.charCodeAt(1) === 110 && (t.charCodeAt(2) > 122 || t.charCodeAt(2) < 97);\n}\nconst On = Object.assign;\n/**!\n * Sortable 1.15.2\n * @author\tRubaXa   <trash@rubaxa.org>\n * @author\towenm    <owen23355@gmail.com>\n * @license MIT\n */\nfunction Ot(t, e) {\n  var n = Object.keys(t);\n  if (Object.getOwnPropertySymbols) {\n    var o = Object.getOwnPropertySymbols(t);\n    e && (o = o.filter(function(r) {\n      return Object.getOwnPropertyDescriptor(t, r).enumerable;\n    })), n.push.apply(n, o);\n  }\n  return n;\n}\nfunction ne(t) {\n  for (var e = 1; e < arguments.length; e++) {\n    var n = arguments[e] != null ? arguments[e] : {};\n    e % 2 ? Ot(Object(n), !0).forEach(function(o) {\n      In(t, o, n[o]);\n    }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(t, Object.getOwnPropertyDescriptors(n)) : Ot(Object(n)).forEach(function(o) {\n      Object.defineProperty(t, o, Object.getOwnPropertyDescriptor(n, o));\n    });\n  }\n  return t;\n}\nfunction Ye(t) {\n  \"@babel/helpers - typeof\";\n  return typeof Symbol == \"function\" && typeof Symbol.iterator == \"symbol\" ? Ye = function(e) {\n    return typeof e;\n  } : Ye = function(e) {\n    return e && typeof Symbol == \"function\" && e.constructor === Symbol && e !== Symbol.prototype ? \"symbol\" : typeof e;\n  }, Ye(t);\n}\nfunction In(t, e, n) {\n  return e in t ? Object.defineProperty(t, e, {\n    value: n,\n    enumerable: !0,\n    configurable: !0,\n    writable: !0\n  }) : t[e] = n, t;\n}\nfunction ie() {\n  return ie = Object.assign || function(t) {\n    for (var e = 1; e < arguments.length; e++) {\n      var n = arguments[e];\n      for (var o in n)\n        Object.prototype.hasOwnProperty.call(n, o) && (t[o] = n[o]);\n    }\n    return t;\n  }, ie.apply(this, arguments);\n}\nfunction An(t, e) {\n  if (t == null)\n    return {};\n  var n = {}, o = Object.keys(t), r, i;\n  for (i = 0; i < o.length; i++)\n    r = o[i], !(e.indexOf(r) >= 0) && (n[r] = t[r]);\n  return n;\n}\nfunction xn(t, e) {\n  if (t == null)\n    return {};\n  var n = An(t, e), o, r;\n  if (Object.getOwnPropertySymbols) {\n    var i = Object.getOwnPropertySymbols(t);\n    for (r = 0; r < i.length; r++)\n      o = i[r], !(e.indexOf(o) >= 0) && Object.prototype.propertyIsEnumerable.call(t, o) && (n[o] = t[o]);\n  }\n  return n;\n}\nvar Nn = \"1.15.2\";\nfunction re(t) {\n  if (typeof window != \"undefined\" && window.navigator)\n    return !!/* @__PURE__ */ navigator.userAgent.match(t);\n}\nvar ae = re(/(?:Trident.*rv[ :]?11\\.|msie|iemobile|Windows Phone)/i), xe = re(/Edge/i), It = re(/firefox/i), Te = re(/safari/i) && !re(/chrome/i) && !re(/android/i), Lt = re(/iP(ad|od|hone)/i), Wt = re(/chrome/i) && re(/android/i), Gt = {\n  capture: !1,\n  passive: !1\n};\nfunction S(t, e, n) {\n  t.addEventListener(e, n, !ae && Gt);\n}\nfunction E(t, e, n) {\n  t.removeEventListener(e, n, !ae && Gt);\n}\nfunction We(t, e) {\n  if (e) {\n    if (e[0] === \">\" && (e = e.substring(1)), t)\n      try {\n        if (t.matches)\n          return t.matches(e);\n        if (t.msMatchesSelector)\n          return t.msMatchesSelector(e);\n        if (t.webkitMatchesSelector)\n          return t.webkitMatchesSelector(e);\n      } catch (n) {\n        return !1;\n      }\n    return !1;\n  }\n}\nfunction Pn(t) {\n  return t.host && t !== document && t.host.nodeType ? t.host : t.parentNode;\n}\nfunction Q(t, e, n, o) {\n  if (t) {\n    n = n || document;\n    do {\n      if (e != null && (e[0] === \">\" ? t.parentNode === n && We(t, e) : We(t, e)) || o && t === n)\n        return t;\n      if (t === n)\n        break;\n    } while (t = Pn(t));\n  }\n  return null;\n}\nvar At = /\\s+/g;\nfunction V(t, e, n) {\n  if (t && e)\n    if (t.classList)\n      t.classList[n ? \"add\" : \"remove\"](e);\n    else {\n      var o = (\" \" + t.className + \" \").replace(At, \" \").replace(\" \" + e + \" \", \" \");\n      t.className = (o + (n ? \" \" + e : \"\")).replace(At, \" \");\n    }\n}\nfunction h(t, e, n) {\n  var o = t && t.style;\n  if (o) {\n    if (n === void 0)\n      return document.defaultView && document.defaultView.getComputedStyle ? n = document.defaultView.getComputedStyle(t, \"\") : t.currentStyle && (n = t.currentStyle), e === void 0 ? n : n[e];\n    !(e in o) && e.indexOf(\"webkit\") === -1 && (e = \"-webkit-\" + e), o[e] = n + (typeof n == \"string\" ? \"\" : \"px\");\n  }\n}\nfunction ye(t, e) {\n  var n = \"\";\n  if (typeof t == \"string\")\n    n = t;\n  else\n    do {\n      var o = h(t, \"transform\");\n      o && o !== \"none\" && (n = o + \" \" + n);\n    } while (!e && (t = t.parentNode));\n  var r = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix;\n  return r && new r(n);\n}\nfunction jt(t, e, n) {\n  if (t) {\n    var o = t.getElementsByTagName(e), r = 0, i = o.length;\n    if (n)\n      for (; r < i; r++)\n        n(o[r], r);\n    return o;\n  }\n  return [];\n}\nfunction te() {\n  var t = document.scrollingElement;\n  return t || document.documentElement;\n}\nfunction P(t, e, n, o, r) {\n  if (!(!t.getBoundingClientRect && t !== window)) {\n    var i, a, l, s, u, d, f;\n    if (t !== window && t.parentNode && t !== te() ? (i = t.getBoundingClientRect(), a = i.top, l = i.left, s = i.bottom, u = i.right, d = i.height, f = i.width) : (a = 0, l = 0, s = window.innerHeight, u = window.innerWidth, d = window.innerHeight, f = window.innerWidth), (e || n) && t !== window && (r = r || t.parentNode, !ae))\n      do\n        if (r && r.getBoundingClientRect && (h(r, \"transform\") !== \"none\" || n && h(r, \"position\") !== \"static\")) {\n          var m = r.getBoundingClientRect();\n          a -= m.top + parseInt(h(r, \"border-top-width\")), l -= m.left + parseInt(h(r, \"border-left-width\")), s = a + i.height, u = l + i.width;\n          break;\n        }\n      while (r = r.parentNode);\n    if (o && t !== window) {\n      var y = ye(r || t), b = y && y.a, w = y && y.d;\n      y && (a /= w, l /= b, f /= b, d /= w, s = a + d, u = l + f);\n    }\n    return {\n      top: a,\n      left: l,\n      bottom: s,\n      right: u,\n      width: f,\n      height: d\n    };\n  }\n}\nfunction xt(t, e, n) {\n  for (var o = ce(t, !0), r = P(t)[e]; o; ) {\n    var i = P(o)[n], a = void 0;\n    if (a = r >= i, !a)\n      return o;\n    if (o === te())\n      break;\n    o = ce(o, !1);\n  }\n  return !1;\n}\nfunction we(t, e, n, o) {\n  for (var r = 0, i = 0, a = t.children; i < a.length; ) {\n    if (a[i].style.display !== \"none\" && a[i] !== p.ghost && (o || a[i] !== p.dragged) && Q(a[i], n.draggable, t, !1)) {\n      if (r === e)\n        return a[i];\n      r++;\n    }\n    i++;\n  }\n  return null;\n}\nfunction ht(t, e) {\n  for (var n = t.lastElementChild; n && (n === p.ghost || h(n, \"display\") === \"none\" || e && !We(n, e)); )\n    n = n.previousElementSibling;\n  return n || null;\n}\nfunction J(t, e) {\n  var n = 0;\n  if (!t || !t.parentNode)\n    return -1;\n  for (; t = t.previousElementSibling; )\n    t.nodeName.toUpperCase() !== \"TEMPLATE\" && t !== p.clone && (!e || We(t, e)) && n++;\n  return n;\n}\nfunction Nt(t) {\n  var e = 0, n = 0, o = te();\n  if (t)\n    do {\n      var r = ye(t), i = r.a, a = r.d;\n      e += t.scrollLeft * i, n += t.scrollTop * a;\n    } while (t !== o && (t = t.parentNode));\n  return [e, n];\n}\nfunction Mn(t, e) {\n  for (var n in t)\n    if (t.hasOwnProperty(n)) {\n      for (var o in e)\n        if (e.hasOwnProperty(o) && e[o] === t[n][o])\n          return Number(n);\n    }\n  return -1;\n}\nfunction ce(t, e) {\n  if (!t || !t.getBoundingClientRect)\n    return te();\n  var n = t, o = !1;\n  do\n    if (n.clientWidth < n.scrollWidth || n.clientHeight < n.scrollHeight) {\n      var r = h(n);\n      if (n.clientWidth < n.scrollWidth && (r.overflowX == \"auto\" || r.overflowX == \"scroll\") || n.clientHeight < n.scrollHeight && (r.overflowY == \"auto\" || r.overflowY == \"scroll\")) {\n        if (!n.getBoundingClientRect || n === document.body)\n          return te();\n        if (o || e)\n          return n;\n        o = !0;\n      }\n    }\n  while (n = n.parentNode);\n  return te();\n}\nfunction Fn(t, e) {\n  if (t && e)\n    for (var n in e)\n      e.hasOwnProperty(n) && (t[n] = e[n]);\n  return t;\n}\nfunction Je(t, e) {\n  return Math.round(t.top) === Math.round(e.top) && Math.round(t.left) === Math.round(e.left) && Math.round(t.height) === Math.round(e.height) && Math.round(t.width) === Math.round(e.width);\n}\nvar Ce;\nfunction zt(t, e) {\n  return function() {\n    if (!Ce) {\n      var n = arguments, o = this;\n      n.length === 1 ? t.call(o, n[0]) : t.apply(o, n), Ce = setTimeout(function() {\n        Ce = void 0;\n      }, e);\n    }\n  };\n}\nfunction Rn() {\n  clearTimeout(Ce), Ce = void 0;\n}\nfunction Ut(t, e, n) {\n  t.scrollLeft += e, t.scrollTop += n;\n}\nfunction Vt(t) {\n  var e = window.Polymer, n = window.jQuery || window.Zepto;\n  return e && e.dom ? e.dom(t).cloneNode(!0) : n ? n(t).clone(!0)[0] : t.cloneNode(!0);\n}\nfunction $t(t, e, n) {\n  var o = {};\n  return Array.from(t.children).forEach(function(r) {\n    var i, a, l, s;\n    if (!(!Q(r, e.draggable, t, !1) || r.animated || r === n)) {\n      var u = P(r);\n      o.left = Math.min((i = o.left) !== null && i !== void 0 ? i : 1 / 0, u.left), o.top = Math.min((a = o.top) !== null && a !== void 0 ? a : 1 / 0, u.top), o.right = Math.max((l = o.right) !== null && l !== void 0 ? l : -1 / 0, u.right), o.bottom = Math.max((s = o.bottom) !== null && s !== void 0 ? s : -1 / 0, u.bottom);\n    }\n  }), o.width = o.right - o.left, o.height = o.bottom - o.top, o.x = o.left, o.y = o.top, o;\n}\nvar q = \"Sortable\" + (/* @__PURE__ */ new Date()).getTime();\nfunction Xn() {\n  var t = [], e;\n  return {\n    captureAnimationState: function() {\n      if (t = [], !!this.options.animation) {\n        var o = [].slice.call(this.el.children);\n        o.forEach(function(r) {\n          if (!(h(r, \"display\") === \"none\" || r === p.ghost)) {\n            t.push({\n              target: r,\n              rect: P(r)\n            });\n            var i = ne({}, t[t.length - 1].rect);\n            if (r.thisAnimationDuration) {\n              var a = ye(r, !0);\n              a && (i.top -= a.f, i.left -= a.e);\n            }\n            r.fromRect = i;\n          }\n        });\n      }\n    },\n    addAnimationState: function(o) {\n      t.push(o);\n    },\n    removeAnimationState: function(o) {\n      t.splice(Mn(t, {\n        target: o\n      }), 1);\n    },\n    animateAll: function(o) {\n      var r = this;\n      if (!this.options.animation) {\n        clearTimeout(e), typeof o == \"function\" && o();\n        return;\n      }\n      var i = !1, a = 0;\n      t.forEach(function(l) {\n        var s = 0, u = l.target, d = u.fromRect, f = P(u), m = u.prevFromRect, y = u.prevToRect, b = l.rect, w = ye(u, !0);\n        w && (f.top -= w.f, f.left -= w.e), u.toRect = f, u.thisAnimationDuration && Je(m, f) && !Je(d, f) && // Make sure animatingRect is on line between toRect & fromRect\n        (b.top - f.top) / (b.left - f.left) === (d.top - f.top) / (d.left - f.left) && (s = Bn(b, m, y, r.options)), Je(f, d) || (u.prevFromRect = d, u.prevToRect = f, s || (s = r.options.animation), r.animate(u, b, f, s)), s && (i = !0, a = Math.max(a, s), clearTimeout(u.animationResetTimer), u.animationResetTimer = setTimeout(function() {\n          u.animationTime = 0, u.prevFromRect = null, u.fromRect = null, u.prevToRect = null, u.thisAnimationDuration = null;\n        }, s), u.thisAnimationDuration = s);\n      }), clearTimeout(e), i ? e = setTimeout(function() {\n        typeof o == \"function\" && o();\n      }, a) : typeof o == \"function\" && o(), t = [];\n    },\n    animate: function(o, r, i, a) {\n      if (a) {\n        h(o, \"transition\", \"\"), h(o, \"transform\", \"\");\n        var l = ye(this.el), s = l && l.a, u = l && l.d, d = (r.left - i.left) / (s || 1), f = (r.top - i.top) / (u || 1);\n        o.animatingX = !!d, o.animatingY = !!f, h(o, \"transform\", \"translate3d(\" + d + \"px,\" + f + \"px,0)\"), this.forRepaintDummy = Yn(o), h(o, \"transition\", \"transform \" + a + \"ms\" + (this.options.easing ? \" \" + this.options.easing : \"\")), h(o, \"transform\", \"translate3d(0,0,0)\"), typeof o.animated == \"number\" && clearTimeout(o.animated), o.animated = setTimeout(function() {\n          h(o, \"transition\", \"\"), h(o, \"transform\", \"\"), o.animated = !1, o.animatingX = !1, o.animatingY = !1;\n        }, a);\n      }\n    }\n  };\n}\nfunction Yn(t) {\n  return t.offsetWidth;\n}\nfunction Bn(t, e, n, o) {\n  return Math.sqrt(Math.pow(e.top - t.top, 2) + Math.pow(e.left - t.left, 2)) / Math.sqrt(Math.pow(e.top - n.top, 2) + Math.pow(e.left - n.left, 2)) * o.animation;\n}\nvar ge = [], Ze = {\n  initializeByDefault: !0\n}, Ne = {\n  mount: function(e) {\n    for (var n in Ze)\n      Ze.hasOwnProperty(n) && !(n in e) && (e[n] = Ze[n]);\n    ge.forEach(function(o) {\n      if (o.pluginName === e.pluginName)\n        throw \"Sortable: Cannot mount plugin \".concat(e.pluginName, \" more than once\");\n    }), ge.push(e);\n  },\n  pluginEvent: function(e, n, o) {\n    var r = this;\n    this.eventCanceled = !1, o.cancel = function() {\n      r.eventCanceled = !0;\n    };\n    var i = e + \"Global\";\n    ge.forEach(function(a) {\n      n[a.pluginName] && (n[a.pluginName][i] && n[a.pluginName][i](ne({\n        sortable: n\n      }, o)), n.options[a.pluginName] && n[a.pluginName][e] && n[a.pluginName][e](ne({\n        sortable: n\n      }, o)));\n    });\n  },\n  initializePlugins: function(e, n, o, r) {\n    ge.forEach(function(l) {\n      var s = l.pluginName;\n      if (!(!e.options[s] && !l.initializeByDefault)) {\n        var u = new l(e, n, e.options);\n        u.sortable = e, u.options = e.options, e[s] = u, ie(o, u.defaults);\n      }\n    });\n    for (var i in e.options)\n      if (e.options.hasOwnProperty(i)) {\n        var a = this.modifyOption(e, i, e.options[i]);\n        typeof a != \"undefined\" && (e.options[i] = a);\n      }\n  },\n  getEventProperties: function(e, n) {\n    var o = {};\n    return ge.forEach(function(r) {\n      typeof r.eventProperties == \"function\" && ie(o, r.eventProperties.call(n[r.pluginName], e));\n    }), o;\n  },\n  modifyOption: function(e, n, o) {\n    var r;\n    return ge.forEach(function(i) {\n      e[i.pluginName] && i.optionListeners && typeof i.optionListeners[n] == \"function\" && (r = i.optionListeners[n].call(e[i.pluginName], o));\n    }), r;\n  }\n};\nfunction kn(t) {\n  var e = t.sortable, n = t.rootEl, o = t.name, r = t.targetEl, i = t.cloneEl, a = t.toEl, l = t.fromEl, s = t.oldIndex, u = t.newIndex, d = t.oldDraggableIndex, f = t.newDraggableIndex, m = t.originalEvent, y = t.putSortable, b = t.extraEventProperties;\n  if (e = e || n && n[q], !!e) {\n    var w, L = e.options, G = \"on\" + o.charAt(0).toUpperCase() + o.substr(1);\n    window.CustomEvent && !ae && !xe ? w = new CustomEvent(o, {\n      bubbles: !0,\n      cancelable: !0\n    }) : (w = document.createEvent(\"Event\"), w.initEvent(o, !0, !0)), w.to = a || n, w.from = l || n, w.item = r || n, w.clone = i, w.oldIndex = s, w.newIndex = u, w.oldDraggableIndex = d, w.newDraggableIndex = f, w.originalEvent = m, w.pullMode = y ? y.lastPutMode : void 0;\n    var R = ne(ne({}, b), Ne.getEventProperties(o, e));\n    for (var j in R)\n      w[j] = R[j];\n    n && n.dispatchEvent(w), L[G] && L[G].call(e, w);\n  }\n}\nvar Hn = [\"evt\"], z = function(e, n) {\n  var o = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}, r = o.evt, i = xn(o, Hn);\n  Ne.pluginEvent.bind(p)(e, n, ne({\n    dragEl: c,\n    parentEl: O,\n    ghostEl: g,\n    rootEl: T,\n    nextEl: pe,\n    lastDownEl: Be,\n    cloneEl: C,\n    cloneHidden: ue,\n    dragStarted: Se,\n    putSortable: Y,\n    activeSortable: p.active,\n    originalEvent: r,\n    oldIndex: be,\n    oldDraggableIndex: Oe,\n    newIndex: $,\n    newDraggableIndex: se,\n    hideGhostForTarget: Zt,\n    unhideGhostForTarget: Qt,\n    cloneNowHidden: function() {\n      ue = !0;\n    },\n    cloneNowShown: function() {\n      ue = !1;\n    },\n    dispatchSortableEvent: function(l) {\n      W({\n        sortable: n,\n        name: l,\n        originalEvent: r\n      });\n    }\n  }, i));\n};\nfunction W(t) {\n  kn(ne({\n    putSortable: Y,\n    cloneEl: C,\n    targetEl: c,\n    rootEl: T,\n    oldIndex: be,\n    oldDraggableIndex: Oe,\n    newIndex: $,\n    newDraggableIndex: se\n  }, t));\n}\nvar c, O, g, T, pe, Be, C, ue, be, $, Oe, se, Me, Y, ve = !1, Ge = !1, je = [], de, Z, Qe, et, Pt, Mt, Se, me, Ie, Ae = !1, Fe = !1, ke, H, tt = [], lt = !1, ze = [], Ve = typeof document != \"undefined\", Re = Lt, Ft = xe || ae ? \"cssFloat\" : \"float\", Ln = Ve && !Wt && !Lt && \"draggable\" in document.createElement(\"div\"), qt = function() {\n  if (Ve) {\n    if (ae)\n      return !1;\n    var t = document.createElement(\"x\");\n    return t.style.cssText = \"pointer-events:auto\", t.style.pointerEvents === \"auto\";\n  }\n}(), Kt = function(e, n) {\n  var o = h(e), r = parseInt(o.width) - parseInt(o.paddingLeft) - parseInt(o.paddingRight) - parseInt(o.borderLeftWidth) - parseInt(o.borderRightWidth), i = we(e, 0, n), a = we(e, 1, n), l = i && h(i), s = a && h(a), u = l && parseInt(l.marginLeft) + parseInt(l.marginRight) + P(i).width, d = s && parseInt(s.marginLeft) + parseInt(s.marginRight) + P(a).width;\n  if (o.display === \"flex\")\n    return o.flexDirection === \"column\" || o.flexDirection === \"column-reverse\" ? \"vertical\" : \"horizontal\";\n  if (o.display === \"grid\")\n    return o.gridTemplateColumns.split(\" \").length <= 1 ? \"vertical\" : \"horizontal\";\n  if (i && l.float && l.float !== \"none\") {\n    var f = l.float === \"left\" ? \"left\" : \"right\";\n    return a && (s.clear === \"both\" || s.clear === f) ? \"vertical\" : \"horizontal\";\n  }\n  return i && (l.display === \"block\" || l.display === \"flex\" || l.display === \"table\" || l.display === \"grid\" || u >= r && o[Ft] === \"none\" || a && o[Ft] === \"none\" && u + d > r) ? \"vertical\" : \"horizontal\";\n}, Wn = function(e, n, o) {\n  var r = o ? e.left : e.top, i = o ? e.right : e.bottom, a = o ? e.width : e.height, l = o ? n.left : n.top, s = o ? n.right : n.bottom, u = o ? n.width : n.height;\n  return r === l || i === s || r + a / 2 === l + u / 2;\n}, Gn = function(e, n) {\n  var o;\n  return je.some(function(r) {\n    var i = r[q].options.emptyInsertThreshold;\n    if (!(!i || ht(r))) {\n      var a = P(r), l = e >= a.left - i && e <= a.right + i, s = n >= a.top - i && n <= a.bottom + i;\n      if (l && s)\n        return o = r;\n    }\n  }), o;\n}, Jt = function(e) {\n  function n(i, a) {\n    return function(l, s, u, d) {\n      var f = l.options.group.name && s.options.group.name && l.options.group.name === s.options.group.name;\n      if (i == null && (a || f))\n        return !0;\n      if (i == null || i === !1)\n        return !1;\n      if (a && i === \"clone\")\n        return i;\n      if (typeof i == \"function\")\n        return n(i(l, s, u, d), a)(l, s, u, d);\n      var m = (a ? l : s).options.group.name;\n      return i === !0 || typeof i == \"string\" && i === m || i.join && i.indexOf(m) > -1;\n    };\n  }\n  var o = {}, r = e.group;\n  (!r || Ye(r) != \"object\") && (r = {\n    name: r\n  }), o.name = r.name, o.checkPull = n(r.pull, !0), o.checkPut = n(r.put), o.revertClone = r.revertClone, e.group = o;\n}, Zt = function() {\n  !qt && g && h(g, \"display\", \"none\");\n}, Qt = function() {\n  !qt && g && h(g, \"display\", \"\");\n};\nVe && !Wt && document.addEventListener(\"click\", function(t) {\n  if (Ge)\n    return t.preventDefault(), t.stopPropagation && t.stopPropagation(), t.stopImmediatePropagation && t.stopImmediatePropagation(), Ge = !1, !1;\n}, !0);\nvar he = function(e) {\n  if (c) {\n    e = e.touches ? e.touches[0] : e;\n    var n = Gn(e.clientX, e.clientY);\n    if (n) {\n      var o = {};\n      for (var r in e)\n        e.hasOwnProperty(r) && (o[r] = e[r]);\n      o.target = o.rootEl = n, o.preventDefault = void 0, o.stopPropagation = void 0, n[q]._onDragOver(o);\n    }\n  }\n}, jn = function(e) {\n  c && c.parentNode[q]._isOutsideThisEl(e.target);\n};\nfunction p(t, e) {\n  if (!(t && t.nodeType && t.nodeType === 1))\n    throw \"Sortable: `el` must be an HTMLElement, not \".concat({}.toString.call(t));\n  this.el = t, this.options = e = ie({}, e), t[q] = this;\n  var n = {\n    group: null,\n    sort: !0,\n    disabled: !1,\n    store: null,\n    handle: null,\n    draggable: /^[uo]l$/i.test(t.nodeName) ? \">li\" : \">*\",\n    swapThreshold: 1,\n    // percentage; 0 <= x <= 1\n    invertSwap: !1,\n    // invert always\n    invertedSwapThreshold: null,\n    // will be set to same as swapThreshold if default\n    removeCloneOnHide: !0,\n    direction: function() {\n      return Kt(t, this.options);\n    },\n    ghostClass: \"sortable-ghost\",\n    chosenClass: \"sortable-chosen\",\n    dragClass: \"sortable-drag\",\n    ignore: \"a, img\",\n    filter: null,\n    preventOnFilter: !0,\n    animation: 0,\n    easing: null,\n    setData: function(a, l) {\n      a.setData(\"Text\", l.textContent);\n    },\n    dropBubble: !1,\n    dragoverBubble: !1,\n    dataIdAttr: \"data-id\",\n    delay: 0,\n    delayOnTouchOnly: !1,\n    touchStartThreshold: (Number.parseInt ? Number : window).parseInt(window.devicePixelRatio, 10) || 1,\n    forceFallback: !1,\n    fallbackClass: \"sortable-fallback\",\n    fallbackOnBody: !1,\n    fallbackTolerance: 0,\n    fallbackOffset: {\n      x: 0,\n      y: 0\n    },\n    supportPointer: p.supportPointer !== !1 && \"PointerEvent\" in window && !Te,\n    emptyInsertThreshold: 5\n  };\n  Ne.initializePlugins(this, t, n);\n  for (var o in n)\n    !(o in e) && (e[o] = n[o]);\n  Jt(e);\n  for (var r in this)\n    r.charAt(0) === \"_\" && typeof this[r] == \"function\" && (this[r] = this[r].bind(this));\n  this.nativeDraggable = e.forceFallback ? !1 : Ln, this.nativeDraggable && (this.options.touchStartThreshold = 1), e.supportPointer ? S(t, \"pointerdown\", this._onTapStart) : (S(t, \"mousedown\", this._onTapStart), S(t, \"touchstart\", this._onTapStart)), this.nativeDraggable && (S(t, \"dragover\", this), S(t, \"dragenter\", this)), je.push(this.el), e.store && e.store.get && this.sort(e.store.get(this) || []), ie(this, Xn());\n}\np.prototype = /** @lends Sortable.prototype */\n{\n  constructor: p,\n  _isOutsideThisEl: function(e) {\n    !this.el.contains(e) && e !== this.el && (me = null);\n  },\n  _getDirection: function(e, n) {\n    return typeof this.options.direction == \"function\" ? this.options.direction.call(this, e, n, c) : this.options.direction;\n  },\n  _onTapStart: function(e) {\n    if (e.cancelable) {\n      var n = this, o = this.el, r = this.options, i = r.preventOnFilter, a = e.type, l = e.touches && e.touches[0] || e.pointerType && e.pointerType === \"touch\" && e, s = (l || e).target, u = e.target.shadowRoot && (e.path && e.path[0] || e.composedPath && e.composedPath()[0]) || s, d = r.filter;\n      if (Zn(o), !c && !(/mousedown|pointerdown/.test(a) && e.button !== 0 || r.disabled) && !u.isContentEditable && !(!this.nativeDraggable && Te && s && s.tagName.toUpperCase() === \"SELECT\") && (s = Q(s, r.draggable, o, !1), !(s && s.animated) && Be !== s)) {\n        if (be = J(s), Oe = J(s, r.draggable), typeof d == \"function\") {\n          if (d.call(this, e, s, this)) {\n            W({\n              sortable: n,\n              rootEl: u,\n              name: \"filter\",\n              targetEl: s,\n              toEl: o,\n              fromEl: o\n            }), z(\"filter\", n, {\n              evt: e\n            }), i && e.cancelable && e.preventDefault();\n            return;\n          }\n        } else if (d && (d = d.split(\",\").some(function(f) {\n          if (f = Q(u, f.trim(), o, !1), f)\n            return W({\n              sortable: n,\n              rootEl: f,\n              name: \"filter\",\n              targetEl: s,\n              fromEl: o,\n              toEl: o\n            }), z(\"filter\", n, {\n              evt: e\n            }), !0;\n        }), d)) {\n          i && e.cancelable && e.preventDefault();\n          return;\n        }\n        r.handle && !Q(u, r.handle, o, !1) || this._prepareDragStart(e, l, s);\n      }\n    }\n  },\n  _prepareDragStart: function(e, n, o) {\n    var r = this, i = r.el, a = r.options, l = i.ownerDocument, s;\n    if (o && !c && o.parentNode === i) {\n      var u = P(o);\n      if (T = i, c = o, O = c.parentNode, pe = c.nextSibling, Be = o, Me = a.group, p.dragged = c, de = {\n        target: c,\n        clientX: (n || e).clientX,\n        clientY: (n || e).clientY\n      }, Pt = de.clientX - u.left, Mt = de.clientY - u.top, this._lastX = (n || e).clientX, this._lastY = (n || e).clientY, c.style[\"will-change\"] = \"all\", s = function() {\n        if (z(\"delayEnded\", r, {\n          evt: e\n        }), p.eventCanceled) {\n          r._onDrop();\n          return;\n        }\n        r._disableDelayedDragEvents(), !It && r.nativeDraggable && (c.draggable = !0), r._triggerDragStart(e, n), W({\n          sortable: r,\n          name: \"choose\",\n          originalEvent: e\n        }), V(c, a.chosenClass, !0);\n      }, a.ignore.split(\",\").forEach(function(d) {\n        jt(c, d.trim(), nt);\n      }), S(l, \"dragover\", he), S(l, \"mousemove\", he), S(l, \"touchmove\", he), S(l, \"mouseup\", r._onDrop), S(l, \"touchend\", r._onDrop), S(l, \"touchcancel\", r._onDrop), It && this.nativeDraggable && (this.options.touchStartThreshold = 4, c.draggable = !0), z(\"delayStart\", this, {\n        evt: e\n      }), a.delay && (!a.delayOnTouchOnly || n) && (!this.nativeDraggable || !(xe || ae))) {\n        if (p.eventCanceled) {\n          this._onDrop();\n          return;\n        }\n        S(l, \"mouseup\", r._disableDelayedDrag), S(l, \"touchend\", r._disableDelayedDrag), S(l, \"touchcancel\", r._disableDelayedDrag), S(l, \"mousemove\", r._delayedDragTouchMoveHandler), S(l, \"touchmove\", r._delayedDragTouchMoveHandler), a.supportPointer && S(l, \"pointermove\", r._delayedDragTouchMoveHandler), r._dragStartTimer = setTimeout(s, a.delay);\n      } else\n        s();\n    }\n  },\n  _delayedDragTouchMoveHandler: function(e) {\n    var n = e.touches ? e.touches[0] : e;\n    Math.max(Math.abs(n.clientX - this._lastX), Math.abs(n.clientY - this._lastY)) >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1)) && this._disableDelayedDrag();\n  },\n  _disableDelayedDrag: function() {\n    c && nt(c), clearTimeout(this._dragStartTimer), this._disableDelayedDragEvents();\n  },\n  _disableDelayedDragEvents: function() {\n    var e = this.el.ownerDocument;\n    E(e, \"mouseup\", this._disableDelayedDrag), E(e, \"touchend\", this._disableDelayedDrag), E(e, \"touchcancel\", this._disableDelayedDrag), E(e, \"mousemove\", this._delayedDragTouchMoveHandler), E(e, \"touchmove\", this._delayedDragTouchMoveHandler), E(e, \"pointermove\", this._delayedDragTouchMoveHandler);\n  },\n  _triggerDragStart: function(e, n) {\n    n = n || e.pointerType == \"touch\" && e, !this.nativeDraggable || n ? this.options.supportPointer ? S(document, \"pointermove\", this._onTouchMove) : n ? S(document, \"touchmove\", this._onTouchMove) : S(document, \"mousemove\", this._onTouchMove) : (S(c, \"dragend\", this), S(T, \"dragstart\", this._onDragStart));\n    try {\n      document.selection ? He(function() {\n        document.selection.empty();\n      }) : window.getSelection().removeAllRanges();\n    } catch (o) {\n    }\n  },\n  _dragStarted: function(e, n) {\n    if (ve = !1, T && c) {\n      z(\"dragStarted\", this, {\n        evt: n\n      }), this.nativeDraggable && S(document, \"dragover\", jn);\n      var o = this.options;\n      !e && V(c, o.dragClass, !1), V(c, o.ghostClass, !0), p.active = this, e && this._appendGhost(), W({\n        sortable: this,\n        name: \"start\",\n        originalEvent: n\n      });\n    } else\n      this._nulling();\n  },\n  _emulateDragOver: function() {\n    if (Z) {\n      this._lastX = Z.clientX, this._lastY = Z.clientY, Zt();\n      for (var e = document.elementFromPoint(Z.clientX, Z.clientY), n = e; e && e.shadowRoot && (e = e.shadowRoot.elementFromPoint(Z.clientX, Z.clientY), e !== n); )\n        n = e;\n      if (c.parentNode[q]._isOutsideThisEl(e), n)\n        do {\n          if (n[q]) {\n            var o = void 0;\n            if (o = n[q]._onDragOver({\n              clientX: Z.clientX,\n              clientY: Z.clientY,\n              target: e,\n              rootEl: n\n            }), o && !this.options.dragoverBubble)\n              break;\n          }\n          e = n;\n        } while (n = n.parentNode);\n      Qt();\n    }\n  },\n  _onTouchMove: function(e) {\n    if (de) {\n      var n = this.options, o = n.fallbackTolerance, r = n.fallbackOffset, i = e.touches ? e.touches[0] : e, a = g && ye(g, !0), l = g && a && a.a, s = g && a && a.d, u = Re && H && Nt(H), d = (i.clientX - de.clientX + r.x) / (l || 1) + (u ? u[0] - tt[0] : 0) / (l || 1), f = (i.clientY - de.clientY + r.y) / (s || 1) + (u ? u[1] - tt[1] : 0) / (s || 1);\n      if (!p.active && !ve) {\n        if (o && Math.max(Math.abs(i.clientX - this._lastX), Math.abs(i.clientY - this._lastY)) < o)\n          return;\n        this._onDragStart(e, !0);\n      }\n      if (g) {\n        a ? (a.e += d - (Qe || 0), a.f += f - (et || 0)) : a = {\n          a: 1,\n          b: 0,\n          c: 0,\n          d: 1,\n          e: d,\n          f\n        };\n        var m = \"matrix(\".concat(a.a, \",\").concat(a.b, \",\").concat(a.c, \",\").concat(a.d, \",\").concat(a.e, \",\").concat(a.f, \")\");\n        h(g, \"webkitTransform\", m), h(g, \"mozTransform\", m), h(g, \"msTransform\", m), h(g, \"transform\", m), Qe = d, et = f, Z = i;\n      }\n      e.cancelable && e.preventDefault();\n    }\n  },\n  _appendGhost: function() {\n    if (!g) {\n      var e = this.options.fallbackOnBody ? document.body : T, n = P(c, !0, Re, !0, e), o = this.options;\n      if (Re) {\n        for (H = e; h(H, \"position\") === \"static\" && h(H, \"transform\") === \"none\" && H !== document; )\n          H = H.parentNode;\n        H !== document.body && H !== document.documentElement ? (H === document && (H = te()), n.top += H.scrollTop, n.left += H.scrollLeft) : H = te(), tt = Nt(H);\n      }\n      g = c.cloneNode(!0), V(g, o.ghostClass, !1), V(g, o.fallbackClass, !0), V(g, o.dragClass, !0), h(g, \"transition\", \"\"), h(g, \"transform\", \"\"), h(g, \"box-sizing\", \"border-box\"), h(g, \"margin\", 0), h(g, \"top\", n.top), h(g, \"left\", n.left), h(g, \"width\", n.width), h(g, \"height\", n.height), h(g, \"opacity\", \"0.8\"), h(g, \"position\", Re ? \"absolute\" : \"fixed\"), h(g, \"zIndex\", \"100000\"), h(g, \"pointerEvents\", \"none\"), p.ghost = g, e.appendChild(g), h(g, \"transform-origin\", Pt / parseInt(g.style.width) * 100 + \"% \" + Mt / parseInt(g.style.height) * 100 + \"%\");\n    }\n  },\n  _onDragStart: function(e, n) {\n    var o = this, r = e.dataTransfer, i = o.options;\n    if (z(\"dragStart\", this, {\n      evt: e\n    }), p.eventCanceled) {\n      this._onDrop();\n      return;\n    }\n    z(\"setupClone\", this), p.eventCanceled || (C = Vt(c), C.removeAttribute(\"id\"), C.draggable = !1, C.style[\"will-change\"] = \"\", this._hideClone(), V(C, this.options.chosenClass, !1), p.clone = C), o.cloneId = He(function() {\n      z(\"clone\", o), !p.eventCanceled && (o.options.removeCloneOnHide || T.insertBefore(C, c), o._hideClone(), W({\n        sortable: o,\n        name: \"clone\"\n      }));\n    }), !n && V(c, i.dragClass, !0), n ? (Ge = !0, o._loopId = setInterval(o._emulateDragOver, 50)) : (E(document, \"mouseup\", o._onDrop), E(document, \"touchend\", o._onDrop), E(document, \"touchcancel\", o._onDrop), r && (r.effectAllowed = \"move\", i.setData && i.setData.call(o, r, c)), S(document, \"drop\", o), h(c, \"transform\", \"translateZ(0)\")), ve = !0, o._dragStartId = He(o._dragStarted.bind(o, n, e)), S(document, \"selectstart\", o), Se = !0, Te && h(document.body, \"user-select\", \"none\");\n  },\n  // Returns true - if no further action is needed (either inserted or another condition)\n  _onDragOver: function(e) {\n    var n = this.el, o = e.target, r, i, a, l = this.options, s = l.group, u = p.active, d = Me === s, f = l.sort, m = Y || u, y, b = this, w = !1;\n    if (lt)\n      return;\n    function L(ee, Ee) {\n      z(ee, b, ne({\n        evt: e,\n        isOwner: d,\n        axis: y ? \"vertical\" : \"horizontal\",\n        revert: a,\n        dragRect: r,\n        targetRect: i,\n        canSort: f,\n        fromSortable: m,\n        target: o,\n        completed: R,\n        onMove: function(vt, rn) {\n          return Xe(T, n, c, r, vt, P(vt), e, rn);\n        },\n        changed: j\n      }, Ee));\n    }\n    function G() {\n      L(\"dragOverAnimationCapture\"), b.captureAnimationState(), b !== m && m.captureAnimationState();\n    }\n    function R(ee) {\n      return L(\"dragOverCompleted\", {\n        insertion: ee\n      }), ee && (d ? u._hideClone() : u._showClone(b), b !== m && (V(c, Y ? Y.options.ghostClass : u.options.ghostClass, !1), V(c, l.ghostClass, !0)), Y !== b && b !== p.active ? Y = b : b === p.active && Y && (Y = null), m === b && (b._ignoreWhileAnimating = o), b.animateAll(function() {\n        L(\"dragOverAnimationComplete\"), b._ignoreWhileAnimating = null;\n      }), b !== m && (m.animateAll(), m._ignoreWhileAnimating = null)), (o === c && !c.animated || o === n && !o.animated) && (me = null), !l.dragoverBubble && !e.rootEl && o !== document && (c.parentNode[q]._isOutsideThisEl(e.target), !ee && he(e)), !l.dragoverBubble && e.stopPropagation && e.stopPropagation(), w = !0;\n    }\n    function j() {\n      $ = J(c), se = J(c, l.draggable), W({\n        sortable: b,\n        name: \"change\",\n        toEl: n,\n        newIndex: $,\n        newDraggableIndex: se,\n        originalEvent: e\n      });\n    }\n    if (e.preventDefault !== void 0 && e.cancelable && e.preventDefault(), o = Q(o, l.draggable, n, !0), L(\"dragOver\"), p.eventCanceled)\n      return w;\n    if (c.contains(e.target) || o.animated && o.animatingX && o.animatingY || b._ignoreWhileAnimating === o)\n      return R(!1);\n    if (Ge = !1, u && !l.disabled && (d ? f || (a = O !== T) : Y === this || (this.lastPutMode = Me.checkPull(this, u, c, e)) && s.checkPut(this, u, c, e))) {\n      if (y = this._getDirection(e, o) === \"vertical\", r = P(c), L(\"dragOverValid\"), p.eventCanceled)\n        return w;\n      if (a)\n        return O = T, G(), this._hideClone(), L(\"revert\"), p.eventCanceled || (pe ? T.insertBefore(c, pe) : T.appendChild(c)), R(!0);\n      var B = ht(n, l.draggable);\n      if (!B || $n(e, y, this) && !B.animated) {\n        if (B === c)\n          return R(!1);\n        if (B && n === e.target && (o = B), o && (i = P(o)), Xe(T, n, c, r, o, i, e, !!o) !== !1)\n          return G(), B && B.nextSibling ? n.insertBefore(c, B.nextSibling) : n.appendChild(c), O = n, j(), R(!0);\n      } else if (B && Vn(e, y, this)) {\n        var X = we(n, 0, l, !0);\n        if (X === c)\n          return R(!1);\n        if (o = X, i = P(o), Xe(T, n, c, r, o, i, e, !1) !== !1)\n          return G(), n.insertBefore(c, X), O = n, j(), R(!0);\n      } else if (o.parentNode === n) {\n        i = P(o);\n        var K = 0, oe, le = c.parentNode !== n, k = !Wn(c.animated && c.toRect || r, o.animated && o.toRect || i, y), v = y ? \"top\" : \"left\", D = xt(o, \"top\", \"top\") || xt(c, \"top\", \"top\"), A = D ? D.scrollTop : void 0;\n        me !== o && (oe = i[v], Ae = !1, Fe = !k && l.invertSwap || le), K = qn(e, o, i, y, k ? 1 : l.swapThreshold, l.invertedSwapThreshold == null ? l.swapThreshold : l.invertedSwapThreshold, Fe, me === o);\n        var I;\n        if (K !== 0) {\n          var _ = J(c);\n          do\n            _ -= K, I = O.children[_];\n          while (I && (h(I, \"display\") === \"none\" || I === g));\n        }\n        if (K === 0 || I === o)\n          return R(!1);\n        me = o, Ie = K;\n        var x = o.nextElementSibling, M = !1;\n        M = K === 1;\n        var F = Xe(T, n, c, r, o, i, e, M);\n        if (F !== !1)\n          return (F === 1 || F === -1) && (M = F === 1), lt = !0, setTimeout(Un, 30), G(), M && !x ? n.appendChild(c) : o.parentNode.insertBefore(c, M ? x : o), D && Ut(D, 0, A - D.scrollTop), O = c.parentNode, oe !== void 0 && !Fe && (ke = Math.abs(oe - P(o)[v])), j(), R(!0);\n      }\n      if (n.contains(c))\n        return R(!1);\n    }\n    return !1;\n  },\n  _ignoreWhileAnimating: null,\n  _offMoveEvents: function() {\n    E(document, \"mousemove\", this._onTouchMove), E(document, \"touchmove\", this._onTouchMove), E(document, \"pointermove\", this._onTouchMove), E(document, \"dragover\", he), E(document, \"mousemove\", he), E(document, \"touchmove\", he);\n  },\n  _offUpEvents: function() {\n    var e = this.el.ownerDocument;\n    E(e, \"mouseup\", this._onDrop), E(e, \"touchend\", this._onDrop), E(e, \"pointerup\", this._onDrop), E(e, \"touchcancel\", this._onDrop), E(document, \"selectstart\", this);\n  },\n  _onDrop: function(e) {\n    var n = this.el, o = this.options;\n    if ($ = J(c), se = J(c, o.draggable), z(\"drop\", this, {\n      evt: e\n    }), O = c && c.parentNode, $ = J(c), se = J(c, o.draggable), p.eventCanceled) {\n      this._nulling();\n      return;\n    }\n    ve = !1, Fe = !1, Ae = !1, clearInterval(this._loopId), clearTimeout(this._dragStartTimer), st(this.cloneId), st(this._dragStartId), this.nativeDraggable && (E(document, \"drop\", this), E(n, \"dragstart\", this._onDragStart)), this._offMoveEvents(), this._offUpEvents(), Te && h(document.body, \"user-select\", \"\"), h(c, \"transform\", \"\"), e && (Se && (e.cancelable && e.preventDefault(), !o.dropBubble && e.stopPropagation()), g && g.parentNode && g.parentNode.removeChild(g), (T === O || Y && Y.lastPutMode !== \"clone\") && C && C.parentNode && C.parentNode.removeChild(C), c && (this.nativeDraggable && E(c, \"dragend\", this), nt(c), c.style[\"will-change\"] = \"\", Se && !ve && V(c, Y ? Y.options.ghostClass : this.options.ghostClass, !1), V(c, this.options.chosenClass, !1), W({\n      sortable: this,\n      name: \"unchoose\",\n      toEl: O,\n      newIndex: null,\n      newDraggableIndex: null,\n      originalEvent: e\n    }), T !== O ? ($ >= 0 && (W({\n      rootEl: O,\n      name: \"add\",\n      toEl: O,\n      fromEl: T,\n      originalEvent: e\n    }), W({\n      sortable: this,\n      name: \"remove\",\n      toEl: O,\n      originalEvent: e\n    }), W({\n      rootEl: O,\n      name: \"sort\",\n      toEl: O,\n      fromEl: T,\n      originalEvent: e\n    }), W({\n      sortable: this,\n      name: \"sort\",\n      toEl: O,\n      originalEvent: e\n    })), Y && Y.save()) : $ !== be && $ >= 0 && (W({\n      sortable: this,\n      name: \"update\",\n      toEl: O,\n      originalEvent: e\n    }), W({\n      sortable: this,\n      name: \"sort\",\n      toEl: O,\n      originalEvent: e\n    })), p.active && (($ == null || $ === -1) && ($ = be, se = Oe), W({\n      sortable: this,\n      name: \"end\",\n      toEl: O,\n      originalEvent: e\n    }), this.save()))), this._nulling();\n  },\n  _nulling: function() {\n    z(\"nulling\", this), T = c = O = g = pe = C = Be = ue = de = Z = Se = $ = se = be = Oe = me = Ie = Y = Me = p.dragged = p.ghost = p.clone = p.active = null, ze.forEach(function(e) {\n      e.checked = !0;\n    }), ze.length = Qe = et = 0;\n  },\n  handleEvent: function(e) {\n    switch (e.type) {\n      case \"drop\":\n      case \"dragend\":\n        this._onDrop(e);\n        break;\n      case \"dragenter\":\n      case \"dragover\":\n        c && (this._onDragOver(e), zn(e));\n        break;\n      case \"selectstart\":\n        e.preventDefault();\n        break;\n    }\n  },\n  /**\n   * Serializes the item into an array of string.\n   * @returns {String[]}\n   */\n  toArray: function() {\n    for (var e = [], n, o = this.el.children, r = 0, i = o.length, a = this.options; r < i; r++)\n      n = o[r], Q(n, a.draggable, this.el, !1) && e.push(n.getAttribute(a.dataIdAttr) || Jn(n));\n    return e;\n  },\n  /**\n   * Sorts the elements according to the array.\n   * @param  {String[]}  order  order of the items\n   */\n  sort: function(e, n) {\n    var o = {}, r = this.el;\n    this.toArray().forEach(function(i, a) {\n      var l = r.children[a];\n      Q(l, this.options.draggable, r, !1) && (o[i] = l);\n    }, this), n && this.captureAnimationState(), e.forEach(function(i) {\n      o[i] && (r.removeChild(o[i]), r.appendChild(o[i]));\n    }), n && this.animateAll();\n  },\n  /**\n   * Save the current sorting\n   */\n  save: function() {\n    var e = this.options.store;\n    e && e.set && e.set(this);\n  },\n  /**\n   * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.\n   * @param   {HTMLElement}  el\n   * @param   {String}       [selector]  default: `options.draggable`\n   * @returns {HTMLElement|null}\n   */\n  closest: function(e, n) {\n    return Q(e, n || this.options.draggable, this.el, !1);\n  },\n  /**\n   * Set/get option\n   * @param   {string} name\n   * @param   {*}      [value]\n   * @returns {*}\n   */\n  option: function(e, n) {\n    var o = this.options;\n    if (n === void 0)\n      return o[e];\n    var r = Ne.modifyOption(this, e, n);\n    typeof r != \"undefined\" ? o[e] = r : o[e] = n, e === \"group\" && Jt(o);\n  },\n  /**\n   * Destroy\n   */\n  destroy: function() {\n    z(\"destroy\", this);\n    var e = this.el;\n    e[q] = null, E(e, \"mousedown\", this._onTapStart), E(e, \"touchstart\", this._onTapStart), E(e, \"pointerdown\", this._onTapStart), this.nativeDraggable && (E(e, \"dragover\", this), E(e, \"dragenter\", this)), Array.prototype.forEach.call(e.querySelectorAll(\"[draggable]\"), function(n) {\n      n.removeAttribute(\"draggable\");\n    }), this._onDrop(), this._disableDelayedDragEvents(), je.splice(je.indexOf(this.el), 1), this.el = e = null;\n  },\n  _hideClone: function() {\n    if (!ue) {\n      if (z(\"hideClone\", this), p.eventCanceled)\n        return;\n      h(C, \"display\", \"none\"), this.options.removeCloneOnHide && C.parentNode && C.parentNode.removeChild(C), ue = !0;\n    }\n  },\n  _showClone: function(e) {\n    if (e.lastPutMode !== \"clone\") {\n      this._hideClone();\n      return;\n    }\n    if (ue) {\n      if (z(\"showClone\", this), p.eventCanceled)\n        return;\n      c.parentNode == T && !this.options.group.revertClone ? T.insertBefore(C, c) : pe ? T.insertBefore(C, pe) : T.appendChild(C), this.options.group.revertClone && this.animate(c, C), h(C, \"display\", \"\"), ue = !1;\n    }\n  }\n};\nfunction zn(t) {\n  t.dataTransfer && (t.dataTransfer.dropEffect = \"move\"), t.cancelable && t.preventDefault();\n}\nfunction Xe(t, e, n, o, r, i, a, l) {\n  var s, u = t[q], d = u.options.onMove, f;\n  return window.CustomEvent && !ae && !xe ? s = new CustomEvent(\"move\", {\n    bubbles: !0,\n    cancelable: !0\n  }) : (s = document.createEvent(\"Event\"), s.initEvent(\"move\", !0, !0)), s.to = e, s.from = t, s.dragged = n, s.draggedRect = o, s.related = r || e, s.relatedRect = i || P(e), s.willInsertAfter = l, s.originalEvent = a, t.dispatchEvent(s), d && (f = d.call(u, s, a)), f;\n}\nfunction nt(t) {\n  t.draggable = !1;\n}\nfunction Un() {\n  lt = !1;\n}\nfunction Vn(t, e, n) {\n  var o = P(we(n.el, 0, n.options, !0)), r = $t(n.el, n.options, g), i = 10;\n  return e ? t.clientX < r.left - i || t.clientY < o.top && t.clientX < o.right : t.clientY < r.top - i || t.clientY < o.bottom && t.clientX < o.left;\n}\nfunction $n(t, e, n) {\n  var o = P(ht(n.el, n.options.draggable)), r = $t(n.el, n.options, g), i = 10;\n  return e ? t.clientX > r.right + i || t.clientY > o.bottom && t.clientX > o.left : t.clientY > r.bottom + i || t.clientX > o.right && t.clientY > o.top;\n}\nfunction qn(t, e, n, o, r, i, a, l) {\n  var s = o ? t.clientY : t.clientX, u = o ? n.height : n.width, d = o ? n.top : n.left, f = o ? n.bottom : n.right, m = !1;\n  if (!a) {\n    if (l && ke < u * r) {\n      if (!Ae && (Ie === 1 ? s > d + u * i / 2 : s < f - u * i / 2) && (Ae = !0), Ae)\n        m = !0;\n      else if (Ie === 1 ? s < d + ke : s > f - ke)\n        return -Ie;\n    } else if (s > d + u * (1 - r) / 2 && s < f - u * (1 - r) / 2)\n      return Kn(e);\n  }\n  return m = m || a, m && (s < d + u * i / 2 || s > f - u * i / 2) ? s > d + u / 2 ? 1 : -1 : 0;\n}\nfunction Kn(t) {\n  return J(c) < J(t) ? 1 : -1;\n}\nfunction Jn(t) {\n  for (var e = t.tagName + t.className + t.src + t.href + t.textContent, n = e.length, o = 0; n--; )\n    o += e.charCodeAt(n);\n  return o.toString(36);\n}\nfunction Zn(t) {\n  ze.length = 0;\n  for (var e = t.getElementsByTagName(\"input\"), n = e.length; n--; ) {\n    var o = e[n];\n    o.checked && ze.push(o);\n  }\n}\nfunction He(t) {\n  return setTimeout(t, 0);\n}\nfunction st(t) {\n  return clearTimeout(t);\n}\nVe && S(document, \"touchmove\", function(t) {\n  (p.active || ve) && t.cancelable && t.preventDefault();\n});\np.utils = {\n  on: S,\n  off: E,\n  css: h,\n  find: jt,\n  is: function(e, n) {\n    return !!Q(e, n, e, !1);\n  },\n  extend: Fn,\n  throttle: zt,\n  closest: Q,\n  toggleClass: V,\n  clone: Vt,\n  index: J,\n  nextTick: He,\n  cancelNextTick: st,\n  detectDirection: Kt,\n  getChild: we\n};\np.get = function(t) {\n  return t[q];\n};\np.mount = function() {\n  for (var t = arguments.length, e = new Array(t), n = 0; n < t; n++)\n    e[n] = arguments[n];\n  e[0].constructor === Array && (e = e[0]), e.forEach(function(o) {\n    if (!o.prototype || !o.prototype.constructor)\n      throw \"Sortable: Mounted plugin must be a constructor function, not \".concat({}.toString.call(o));\n    o.utils && (p.utils = ne(ne({}, p.utils), o.utils)), Ne.mount(o);\n  });\n};\np.create = function(t, e) {\n  return new p(t, e);\n};\np.version = Nn;\nvar N = [], De, ut, ct = !1, ot, rt, Ue, _e;\nfunction Qn() {\n  function t() {\n    this.defaults = {\n      scroll: !0,\n      forceAutoScrollFallback: !1,\n      scrollSensitivity: 30,\n      scrollSpeed: 10,\n      bubbleScroll: !0\n    };\n    for (var e in this)\n      e.charAt(0) === \"_\" && typeof this[e] == \"function\" && (this[e] = this[e].bind(this));\n  }\n  return t.prototype = {\n    dragStarted: function(n) {\n      var o = n.originalEvent;\n      this.sortable.nativeDraggable ? S(document, \"dragover\", this._handleAutoScroll) : this.options.supportPointer ? S(document, \"pointermove\", this._handleFallbackAutoScroll) : o.touches ? S(document, \"touchmove\", this._handleFallbackAutoScroll) : S(document, \"mousemove\", this._handleFallbackAutoScroll);\n    },\n    dragOverCompleted: function(n) {\n      var o = n.originalEvent;\n      !this.options.dragOverBubble && !o.rootEl && this._handleAutoScroll(o);\n    },\n    drop: function() {\n      this.sortable.nativeDraggable ? E(document, \"dragover\", this._handleAutoScroll) : (E(document, \"pointermove\", this._handleFallbackAutoScroll), E(document, \"touchmove\", this._handleFallbackAutoScroll), E(document, \"mousemove\", this._handleFallbackAutoScroll)), Rt(), Le(), Rn();\n    },\n    nulling: function() {\n      Ue = ut = De = ct = _e = ot = rt = null, N.length = 0;\n    },\n    _handleFallbackAutoScroll: function(n) {\n      this._handleAutoScroll(n, !0);\n    },\n    _handleAutoScroll: function(n, o) {\n      var r = this, i = (n.touches ? n.touches[0] : n).clientX, a = (n.touches ? n.touches[0] : n).clientY, l = document.elementFromPoint(i, a);\n      if (Ue = n, o || this.options.forceAutoScrollFallback || xe || ae || Te) {\n        it(n, this.options, l, o);\n        var s = ce(l, !0);\n        ct && (!_e || i !== ot || a !== rt) && (_e && Rt(), _e = setInterval(function() {\n          var u = ce(document.elementFromPoint(i, a), !0);\n          u !== s && (s = u, Le()), it(n, r.options, u, o);\n        }, 10), ot = i, rt = a);\n      } else {\n        if (!this.options.bubbleScroll || ce(l, !0) === te()) {\n          Le();\n          return;\n        }\n        it(n, this.options, ce(l, !1), !1);\n      }\n    }\n  }, ie(t, {\n    pluginName: \"scroll\",\n    initializeByDefault: !0\n  });\n}\nfunction Le() {\n  N.forEach(function(t) {\n    clearInterval(t.pid);\n  }), N = [];\n}\nfunction Rt() {\n  clearInterval(_e);\n}\nvar it = zt(function(t, e, n, o) {\n  if (e.scroll) {\n    var r = (t.touches ? t.touches[0] : t).clientX, i = (t.touches ? t.touches[0] : t).clientY, a = e.scrollSensitivity, l = e.scrollSpeed, s = te(), u = !1, d;\n    ut !== n && (ut = n, Le(), De = e.scroll, d = e.scrollFn, De === !0 && (De = ce(n, !0)));\n    var f = 0, m = De;\n    do {\n      var y = m, b = P(y), w = b.top, L = b.bottom, G = b.left, R = b.right, j = b.width, B = b.height, X = void 0, K = void 0, oe = y.scrollWidth, le = y.scrollHeight, k = h(y), v = y.scrollLeft, D = y.scrollTop;\n      y === s ? (X = j < oe && (k.overflowX === \"auto\" || k.overflowX === \"scroll\" || k.overflowX === \"visible\"), K = B < le && (k.overflowY === \"auto\" || k.overflowY === \"scroll\" || k.overflowY === \"visible\")) : (X = j < oe && (k.overflowX === \"auto\" || k.overflowX === \"scroll\"), K = B < le && (k.overflowY === \"auto\" || k.overflowY === \"scroll\"));\n      var A = X && (Math.abs(R - r) <= a && v + j < oe) - (Math.abs(G - r) <= a && !!v), I = K && (Math.abs(L - i) <= a && D + B < le) - (Math.abs(w - i) <= a && !!D);\n      if (!N[f])\n        for (var _ = 0; _ <= f; _++)\n          N[_] || (N[_] = {});\n      (N[f].vx != A || N[f].vy != I || N[f].el !== y) && (N[f].el = y, N[f].vx = A, N[f].vy = I, clearInterval(N[f].pid), (A != 0 || I != 0) && (u = !0, N[f].pid = setInterval(function() {\n        o && this.layer === 0 && p.active._onTouchMove(Ue);\n        var x = N[this.layer].vy ? N[this.layer].vy * l : 0, M = N[this.layer].vx ? N[this.layer].vx * l : 0;\n        typeof d == \"function\" && d.call(p.dragged.parentNode[q], M, x, t, Ue, N[this.layer].el) !== \"continue\" || Ut(N[this.layer].el, M, x);\n      }.bind({\n        layer: f\n      }), 24))), f++;\n    } while (e.bubbleScroll && m !== s && (m = ce(m, !1)));\n    ct = u;\n  }\n}, 30), en = function(e) {\n  var n = e.originalEvent, o = e.putSortable, r = e.dragEl, i = e.activeSortable, a = e.dispatchSortableEvent, l = e.hideGhostForTarget, s = e.unhideGhostForTarget;\n  if (n) {\n    var u = o || i;\n    l();\n    var d = n.changedTouches && n.changedTouches.length ? n.changedTouches[0] : n, f = document.elementFromPoint(d.clientX, d.clientY);\n    s(), u && !u.el.contains(f) && (a(\"spill\"), this.onSpill({\n      dragEl: r,\n      putSortable: o\n    }));\n  }\n};\nfunction pt() {\n}\npt.prototype = {\n  startIndex: null,\n  dragStart: function(e) {\n    var n = e.oldDraggableIndex;\n    this.startIndex = n;\n  },\n  onSpill: function(e) {\n    var n = e.dragEl, o = e.putSortable;\n    this.sortable.captureAnimationState(), o && o.captureAnimationState();\n    var r = we(this.sortable.el, this.startIndex, this.options);\n    r ? this.sortable.el.insertBefore(n, r) : this.sortable.el.appendChild(n), this.sortable.animateAll(), o && o.animateAll();\n  },\n  drop: en\n};\nie(pt, {\n  pluginName: \"revertOnSpill\"\n});\nfunction gt() {\n}\ngt.prototype = {\n  onSpill: function(e) {\n    var n = e.dragEl, o = e.putSortable, r = o || this.sortable;\n    r.captureAnimationState(), n.parentNode && n.parentNode.removeChild(n), r.animateAll();\n  },\n  drop: en\n};\nie(gt, {\n  pluginName: \"removeOnSpill\"\n});\np.mount(new Qn());\np.mount(gt, pt);\nfunction eo(t) {\n  return t == null ? t : JSON.parse(JSON.stringify(t));\n}\nfunction to(t) {\n  dt() && sn(t);\n}\nfunction no(t) {\n  dt() ? un(t) : kt(t);\n}\nlet tn = null, nn = null;\nfunction Xt(t = null, e = null) {\n  tn = t, nn = e;\n}\nfunction oo() {\n  return {\n    data: tn,\n    clonedData: nn\n  };\n}\nconst Yt = Symbol(\"cloneElement\");\nfunction on(...t) {\n  var le, k;\n  const e = (le = dt()) == null ? void 0 : le.proxy;\n  let n = null;\n  const o = t[0];\n  let [, r, i] = t;\n  Array.isArray(U(r)) || (i = r, r = null);\n  let a = null;\n  const {\n    immediate: l = !0,\n    clone: s = eo,\n    forceFallback: u,\n    fallbackOnBody: d,\n    customUpdate: f\n  } = (k = U(i)) != null ? k : {};\n  function m(v) {\n    var F;\n    const { from: D, oldIndex: A, item: I } = v, _ = Array.from(D.childNodes);\n    n = u && !d ? _.slice(0, -1) : _;\n    const x = U((F = U(r)) == null ? void 0 : F[A]), M = s(x);\n    Xt(x, M), I[Yt] = M;\n  }\n  function y(v) {\n    const D = v.item[Yt];\n    if (!wn(D)) {\n      if (Ke(v.item), qe(r)) {\n        const A = [...U(r)];\n        r.value = _t(A, v.newDraggableIndex, D);\n        return;\n      }\n      _t(U(r), v.newDraggableIndex, D);\n    }\n  }\n  function b(v) {\n    const { from: D, item: A, oldIndex: I, oldDraggableIndex: _, pullMode: x, clone: M } = v;\n    if (Tt(D, A, I), x === \"clone\") {\n      Ke(M);\n      return;\n    }\n    if (qe(r)) {\n      const F = [...U(r)];\n      r.value = Dt(F, _);\n      return;\n    }\n    Dt(U(r), _);\n  }\n  function w(v) {\n    if (f) {\n      f(v);\n      return;\n    }\n    const { from: D, item: A, oldIndex: I, oldDraggableIndex: _, newDraggableIndex: x } = v;\n    if (Ke(A), Tt(D, A, I), qe(r)) {\n      const M = [...U(r)];\n      r.value = St(\n        M,\n        _,\n        x\n      );\n      return;\n    }\n    St(U(r), _, x);\n  }\n  function L(v) {\n    const { newIndex: D, oldIndex: A, from: I, to: _ } = v;\n    let x = null;\n    const M = D === A && I === _;\n    try {\n      if (M) {\n        let F = null;\n        n == null || n.some((ee, Ee) => {\n          if (F && (n == null ? void 0 : n.length) !== _.childNodes.length)\n            return I.insertBefore(F, ee.nextSibling), !0;\n          const mt = _.childNodes[Ee];\n          F = _ == null ? void 0 : _.replaceChild(ee, mt);\n        });\n      }\n    } catch (F) {\n      x = F;\n    } finally {\n      n = null;\n    }\n    kt(() => {\n      if (Xt(), x)\n        throw x;\n    });\n  }\n  const G = {\n    onUpdate: w,\n    onStart: m,\n    onAdd: y,\n    onRemove: b,\n    onEnd: L\n  };\n  function R(v) {\n    const D = U(o);\n    return v || (v = En(D) ? Sn(D, e == null ? void 0 : e.$el) : D), v && !Tn(v) && (v = v.$el), v || vn(\"Root element not found\"), v;\n  }\n  function j() {\n    var I;\n    const _ = (I = U(i)) != null ? I : {}, { immediate: v, clone: D } = _, A = $e(_, [\"immediate\", \"clone\"]);\n    return Ct(A, (x, M) => {\n      Cn(x) && (A[x] = (F, ...ee) => {\n        const Ee = oo();\n        return On(F, Ee), M(F, ...ee);\n      });\n    }), _n(\n      r === null ? {} : G,\n      A\n    );\n  }\n  const B = (v) => {\n    v = R(v), a && X.destroy(), a = new p(v, j());\n  };\n  ln(\n    () => i,\n    () => {\n      a && Ct(j(), (v, D) => {\n        a == null || a.option(v, D);\n      });\n    },\n    { deep: !0 }\n  );\n  const X = {\n    option: (v, D) => a == null ? void 0 : a.option(v, D),\n    destroy: () => {\n      a == null || a.destroy(), a = null;\n    },\n    save: () => a == null ? void 0 : a.save(),\n    toArray: () => a == null ? void 0 : a.toArray(),\n    closest: (...v) => a == null ? void 0 : a.closest(...v)\n  }, K = () => X == null ? void 0 : X.option(\"disabled\", !0), oe = () => X == null ? void 0 : X.option(\"disabled\", !1);\n  return no(() => {\n    l && B();\n  }), to(X.destroy), fe({ start: B, pause: K, resume: oe }, X);\n}\nconst ft = [\n  \"update\",\n  \"start\",\n  \"add\",\n  \"remove\",\n  \"choose\",\n  \"unchoose\",\n  \"end\",\n  \"sort\",\n  \"filter\",\n  \"clone\",\n  \"move\",\n  \"change\"\n], ro = [\n  \"clone\",\n  \"animation\",\n  \"ghostClass\",\n  \"group\",\n  \"sort\",\n  \"disabled\",\n  \"store\",\n  \"handle\",\n  \"draggable\",\n  \"swapThreshold\",\n  \"invertSwap\",\n  \"invertedSwapThreshold\",\n  \"removeCloneOnHide\",\n  \"direction\",\n  \"chosenClass\",\n  \"dragClass\",\n  \"ignore\",\n  \"filter\",\n  \"preventOnFilter\",\n  \"easing\",\n  \"setData\",\n  \"dropBubble\",\n  \"dragoverBubble\",\n  \"dataIdAttr\",\n  \"delay\",\n  \"delayOnTouchOnly\",\n  \"touchStartThreshold\",\n  \"forceFallback\",\n  \"fallbackClass\",\n  \"fallbackOnBody\",\n  \"fallbackTolerance\",\n  \"fallbackOffset\",\n  \"supportPointer\",\n  \"emptyInsertThreshold\",\n  \"scroll\",\n  \"forceAutoScrollFallback\",\n  \"scrollSensitivity\",\n  \"scrollSpeed\",\n  \"bubbleScroll\",\n  \"modelValue\",\n  \"tag\",\n  \"target\",\n  \"customUpdate\",\n  ...ft.map((t) => `on${t.replace(/^\\S/, (e) => e.toUpperCase())}`)\n], lo = cn({\n  name: \"VueDraggable\",\n  model: {\n    prop: \"modelValue\",\n    event: \"update:modelValue\"\n  },\n  props: ro,\n  emits: [\"update:modelValue\", ...ft],\n  setup(t, { slots: e, emit: n, expose: o, attrs: r }) {\n    const i = ft.reduce((d, f) => {\n      const m = `on${f.replace(/^\\S/, (y) => y.toUpperCase())}`;\n      return d[m] = (...y) => n(f, ...y), d;\n    }, {}), a = Et(() => {\n      const y = fn(t), { modelValue: d } = y, f = $e(y, [\"modelValue\"]), m = Object.entries(f).reduce((b, [w, L]) => {\n        const G = U(L);\n        return G !== void 0 && (b[w] = G), b;\n      }, {});\n      return fe(fe({}, i), yn(fe(fe({}, r), m)));\n    }), l = Et({\n      get: () => t.modelValue,\n      set: (d) => n(\"update:modelValue\", d)\n    }), s = dn(), u = hn(\n      on(t.target || s, l, a)\n    );\n    return o(u), () => {\n      var d;\n      return pn(t.tag || \"div\", { ref: s }, (d = e == null ? void 0 : e.default) == null ? void 0 : d.call(e, u));\n    };\n  }\n}), Bt = {\n  mounted: \"mounted\",\n  unmounted: \"unmounted\"\n}, at = /* @__PURE__ */ new WeakMap(), so = {\n  [Bt.mounted](t, e) {\n    const n = gn(e.value) ? [e.value] : e.value, [o, r] = n, i = on(t, o, r);\n    at.set(t, i.destroy);\n  },\n  [Bt.unmounted](t) {\n    var e;\n    (e = at.get(t)) == null || e(), at.delete(t);\n  }\n};\nexport {\n  lo as VueDraggable,\n  on as useDraggable,\n  so as vDraggable\n};\n","<script setup>\n/**\n * Component to render a text string as HTML conditionally (this is not possible with v-html)\n */\n\ndefineOptions({\n  name: 'BaseInsertTextAsHtml',\n});\n\nconst props = defineProps({\n  /**\n   * specify the tag of the element (e.g. `span`, `li`)\n   */\n  renderElementAs: {\n    type: String,\n    default: 'span',\n  },\n  /**\n   * specify the text to render\n   */\n  text: {\n    type: [String, Number],\n    default: '',\n  },\n  /**\n   * specify if the text should be rendered as HTML text or plain text\n   */\n  interpretTextAsHtml: {\n    type: Boolean,\n    default: false,\n  },\n});\n</script>\n\n<template>\n  <!-- eslint-disable vue/no-v-html vue/no-v-text-v-html-on-component -->\n  <component\n    :is=\"renderElementAs\"\n    v-text=\"!interpretTextAsHtml ? props.text : null\"\n    v-html=\"interpretTextAsHtml ? props.text : null\" />\n  <!-- eslint-enable vue/no-v-html vue/no-v-text-v-html-on-component -->\n</template>\n","<script>\n\nimport BaseChip from '@/components/BaseChip/BaseChip.vue';\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\n\nexport default {\n  name: 'BaseCollapsedFilterItem',\n  components: {\n    BaseIcon,\n    BaseChip,\n  },\n  props: {\n    /**\n     * the chip object to be displayed. Needs to be an object with idInternal (optional) and labelInternal\n     */\n    value: {\n      type: [Object],\n      required: true,\n      validator: val => Object.keys(val)\n        .includes('labelInternal'),\n    },\n    /**\n     * the `field_type` of the form field for which the chip should be displayed\n     */\n    type: {\n      type: String,\n      default: 'text',\n    },\n    /**\n     * for date and time ranges it needs to be determined if a 'until' character should\n     *  be displayed\n     */\n    rangeIndicator: {\n      type: String,\n      default: 'from',\n    },\n    /**\n     * if necessary selected chip text can be rendered as v-html directive\n     * will only be applied to values with `idInternal`\n     */\n    interpretLabelAsHtml: {\n      type: Boolean,\n      default: false,\n    },\n    /**\n     * provide assistive text for boolean values and to inform user of chip\n     * removal options\n     *\n     * **booleanFilterLabel**: Set text that should be read for a boolean filter value. You may add\n     *  the string {label} which will be replaced by the filter label.\n     * **optionToRemoveSelected**: text read when an option is focused (and thus selected), should\n     *  announce to the screen reader user that option can now be removed via Backspace or Delete.\n     *  You may add the string {label} which will be replaced by the filter label.\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        booleanFilterLabel: 'Filter was set.',\n        optionToRemoveSelected: 'Press delete or backspace to remove.',\n      }),\n    },\n  },\n  emits: ['remove-chip'],\n  computed: {\n    /**\n     * is the type of the value to be displayed boolean\n     * @returns {boolean}\n     */\n    isBoolean() {\n      return this.type === 'boolean';\n    },\n    isDateOrTimeRange() {\n      return ['date', 'time'].includes(this.type) && this.rangeIndicator;\n    },\n    /**\n     * does the provided value exist and have a labelInternal\n     * @returns {boolean}\n     */\n    hasValue() {\n      return !!this.value && !!this.value.labelInternal;\n    },\n    filterItemLabel() {\n      if (this.isBoolean && this.assistiveText.booleanFilterLabel\n        && this.assistiveText.optionToRemoveSelected) {\n        return `${this.assistiveText.booleanFilterLabel}. ${this.assistiveText.optionToRemoveSelected}`;\n      }\n      if (this.isBoolean && this.assistiveText.booleanFilterLabel) {\n        return this.assistiveText.booleanFilterLabel;\n      }\n      if (!this.isBoolean && this.assistiveText.optionToRemoveSelected) {\n        return `${this.value.labelInternal}. ${this.assistiveText.optionToRemoveSelected}`;\n      }\n      return this.value.labelInternal.toString();\n    },\n  },\n  methods: {\n    /**\n     * propagate to parent when the remove icon was clicked\n     */\n    removeChip(event) {\n      const { type, key } = event;\n      // if event is not coming from 'keydown' it should go through - if it is\n      // a keydown event we need to check if correct keys were triggered\n      if (type !== 'keydown' || (type === 'keydown' && ['Backspace', 'Delete'].includes(key))) {\n        /**\n         * inform parent about chip removal\n         * @event remove-chip\n         */\n        this.$emit('remove-chip');\n      }\n    },\n  },\n};\n</script>\n\n<template>\n  <!-- this element NEEDS to be a listitem element because parent is <ul> and moving the keydown\n    event elsewhere had undesired side effects so disabling eslint rule -->\n  <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n  <li\n    ref=\"filterChip\"\n    tabindex=\"0\"\n    class=\"base-collapsed-filter-item\"\n    @keydown=\"removeChip\">\n    <!-- if value is single value of date or time range add an 'from' or 'until' character -->\n    <span\n      v-if=\"isDateOrTimeRange\"\n      class=\"base-collapsed-filter-item__until\">\n      {{ rangeIndicator }}\n    </span>\n    <!-- per default use BaseChip component except for type `boolean`\n      enable interpret-text-as-html for chips input fields and chips WITH ids -->\n    <BaseChip\n      v-if=\"!isBoolean && hasValue\"\n      :model-value=\"value.labelInternal\"\n      :is-linked=\"true\"\n      :interpret-text-as-html=\"interpretLabelAsHtml && !!value.idInternal\"\n      :assistive-text=\"filterItemLabel\"\n      class=\"base-collapsed-filter-item__chip\"\n      @remove-entry=\"removeChip\" />\n    <!-- for boolean we use a checkmark icon instead of text -->\n    <div\n      v-else-if=\"isBoolean && hasValue\"\n      class=\"base-collapsed-filter-item__chip base-collapsed-filter-item__boolean-value\">\n      <BaseIcon\n        :title=\"filterItemLabel\"\n        name=\"check-mark\"\n        class=\"base-collapsed-filter-item__icon\" />\n      <BaseIcon\n        name=\"remove\"\n        class=\"base-collapsed-filter-item__icon-remove\"\n        @click.stop=\"removeChip\" />\n    </div>\n  </li>\n</template>\n\n<style scoped lang=\"scss\">\n@use \"@/styles/variables\" as *;\n\n.base-collapsed-filter-item {\n  flex-shrink: 0;\n\n  &:focus-visible {\n    /* Draw the focus when :focus-visible is supported */\n    .base-collapsed-filter-item__chip {\n      background-color: $app-color-secondary;\n    }\n  }\n\n  @supports not selector(:focus-visible) {\n    /* Fallback for browsers without :focus-visible support */\n    .base-collapsed-filter-item__chip {\n      background-color: $app-color-secondary;\n    }\n  }\n\n  .base-collapsed-filter-item__boolean-value {\n    display: flex;\n    align-items: center;\n    background: $background-color;\n    padding: $chips-spacing 0 $chips-spacing $spacing-small;\n    margin: $chips-spacing*4 $spacing-small $chips-spacing*4 0;\n\n    .base-collapsed-filter-item__icon {\n      height: $icon-medium;\n      width: $icon-medium;\n    }\n    .base-collapsed-filter-item__icon-remove {\n      padding: $spacing-small;\n      height: calc(#{$icon-min} + (2 * #{$spacing-small}));\n      width: calc(#{$icon-min} + (2 * #{$spacing-small}));\n      cursor: pointer;\n    }\n  }\n\n  .base-collapsed-filter-item__until {\n    margin: 0 #{$spacing-small-half} 0 0;\n  }\n}\n</style>\n","<script>\nimport BaseIcon from '@/components/BaseIcon/BaseIcon.vue';\nimport BaseCollapsedFilterItem from '@/components/BaseAdvancedSearch/BaseCollapsedFilterItem.vue';\nimport { hasData } from '@/utils/utils.js';\nimport { useTemplateRef } from 'vue';\nimport { useHorizontalDragScroll } from '@/composables/useHorizontalDragScroll.js';\n\n/**\n * component for BaseAdvancedSearch 'form' mode to display form filter values efficiently\n */\nexport default {\n  name: 'BaseCollapsedFilterRow',\n  components: {\n    BaseCollapsedFilterItem,\n    BaseIcon,\n  },\n  props: {\n    /**\n     * provide a list of filters in array form, every array object that needs the following properties:\n     *  **idInternal** `string` - a filter identifier\n     *  **labelInternal** `string` - a label shown for the filter\n     *  **filter_values** `{\n     *    values: { labelInternal: string|boolean, idInternal: string? }[]|{ values: {}, fieldId: string, fieldType: string }[]\n     *    fieldId: string,\n     *    fieldType: string,\n     *   }[]` - the values that were selected for the filter (set by BaseAdvancedSearch internally), this is again\n     *    an array of objects with the properties\n     *      `values` - either containing the actual values to display (with `labelInternal` and `idInternal` (optional) properties)\n     *      OR in case of field groups to have nested another object array with `fieldType`, `fieldId` and `values` properties\n     *      again (see below for description)\n     *    `fieldId`: the property of the form field in question\n     *    `fieldType`: the type of the field in question\n     */\n    filters: {\n      type: Array,\n      default: () => ([]),\n      validator: (val) => {\n        // define all required props here\n        const requiredProps = ['idInternal', 'labelInternal', 'filter_values'];\n        const requiredFilterValueProps = ['values', 'fieldType', 'fieldId'];\n        // iterate through the filter array - return true if NO prop is missing\n        return !val.some((filter) => {\n          // get the properties the filter has\n          const filterProps = Object.keys(filter);\n          const filterValueProps = Object.keys(filter.filter_values);\n          // check if any of those is missing\n          let propMissing = requiredProps.some(prop => !filterProps.includes(prop));\n          // only continue checking if all props were found so far\n          if (!propMissing) {\n            propMissing = requiredFilterValueProps.some(prop => !filterValueProps.includes(prop));\n            // only continue checking if all props were found so far\n            if (!propMissing) {\n              // now also check if all filter.filter_values have a label to display\n              propMissing = filter.filter_values.values.some((filterValue) => {\n                // check for special case field groups where filter_values has nested arrays - so\n                // if filterValue has a length it is a nested array\n                if (filterValue?.values?.length >= 0) {\n                  const groupFilterValueProps = Object.keys(filterValue);\n                  // if yes check for each array if it has content and if yes, if it has the labelInternal property\n                  return filterValue.values.length !== 0\n                    && requiredFilterValueProps.some(prop => !groupFilterValueProps.includes(prop))\n                    && filterValue.values\n                      // also account here for special case boolean which does not need a labelInternal\n                      .some(nestedFilterValue => !Object.keys(nestedFilterValue).includes('labelInternal'));\n                }\n                // else check for each filterValue if labelInternal property is there\n                return !Object.keys(filterValue).includes('labelInternal');\n              });\n            }\n          }\n          // return boolean value if prop is missing\n          return propMissing;\n        });\n      },\n    },\n    /**\n     * set the text displayed for date or time values of ranges where only one field is\n     * filled.\n     */\n    dateTimeText: {\n      type: Object,\n      default: () => ({\n        from: 'from',\n        until: 'until',\n        range: 'to',\n      }),\n      validator: val => !['from', 'until', 'range'].some(property => !Object.keys(val).includes(property)),\n    },\n    /**\n     * if necessary selected chip text can be rendered as v-html directive\n     * can be `true` (all fields will have html rendering enabled) `false` or a list\n     *  of field names for which rendering should be enabled, for nested fields\n     *  specify an object with a list of child field names.\n     *  e.g. :interpretLabelAsHtml=\"['field1', { [field2]: ['childField1'] }]\"\n     */\n    interpretLabelAsHtml: {\n      type: [Boolean, Array],\n      default: false,\n    },\n    /**\n     * **removeFiltersLabel**: add a descriptive label used for the remove all\n     *  filters icon in collapsed row\n     * **filterRemovedNotification**: notification that is read by screenreaders when a filter\n     *  value was removed. Add the string {value} to read the filter value that was removed and\n     *  {label} to read the label of the filter from which the value was removed.\n     * **appliedFiltersLabel**: description for the filters in the collapsed filter row.\n     * **booleanFilterLabel**: Set text that should be read for a boolan filter value. You may add\n     *      the string {label} which will be replaced by the filter label.\n     * **optionToRemoveSelected**: text read when an option is focused (and thus selected), should\n     *  announce to the screen reader user that option can now be removed via Backspace or Delete.\n     */\n    assistiveText: {\n      type: Object,\n      default: () => ({\n        removeFiltersLabel: 'Remove all filters.',\n        filterRemovedNotification: 'Filter value {value} was removed from filter {label}.',\n        appliedFiltersLabel: 'Currently applied Filters',\n        booleanFilterLabel: 'Filter {label} was set',\n        optionToRemoveSelected: 'Press delete or backspace to remove.',\n      }),\n    },\n  },\n  emits: ['update:filters', 'remove-all'],\n  setup() {\n    /**\n     * store the scroll drag element\n     * @type {Readonly<ShallowRef<HTMLElement | null>>}\n     */\n    const scrollContainer = useTemplateRef('filterList');\n\n    const {\n      boxFadeOut,\n      calcFadeOut,\n    } = useHorizontalDragScroll(scrollContainer, {\n      scrollableClassNames: ['base-collapsed-filter-row__filter-list__scrollable'],\n    });\n\n    return {\n      scrollContainer,\n      // fade out\n      boxFadeOut,\n      calcFadeOut,\n    }\n  },\n  data() {\n    return {\n      /**\n       * internal representation of filters list, for a list of object properties see\n       *  prop `filters`\n       * @type Object[]\n       */\n      filtersInt: [],\n      /**\n       * assistive text set when a chip was removed to be read\n       * by screenreader\n       * @type {string}\n       */\n      chipRemovedAssistiveText: '',\n    };\n  },\n  watch: {\n    /**\n     * keep filters in sync with parent component and vice versa\n     */\n    filters: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.filtersInt)) {\n          this.filtersInt = JSON.parse(JSON.stringify(val));\n        }\n      },\n      immediate: true,\n    },\n    /**\n     * keep filters in sync with parent component and vice versa\n     */\n    filtersInt: {\n      handler(val) {\n        if (JSON.stringify(val) !== JSON.stringify(this.filters)) {\n          this.$emit('update:filters', [...val]);\n        }\n        this.$nextTick(() => this.calcFadeOut());\n      },\n      deep: true,\n    },\n  },\n  methods: {\n    /**\n     * if 'remove all' icon was triggered just emit event to parent to take care of this\n     */\n    removeFilters() {\n      /**\n       * event emitted on remove icon click to remove all filters\n       * @event remove-all\n       */\n      this.$emit('remove-all');\n    },\n    /**\n     * function to remove one specific value from a filter in the filters list\n     * @param {number} filterIndex - the index of the filter\n     * @param {number} valueIndex - the index of the specific value\n     * @param {number?} groupIndex - in case filter is from form group, this is the index of the field\n     *  within the group\n     */\n    removeChip(filterIndex, valueIndex, groupIndex) {\n      const { fieldType, values } = this.filtersInt[filterIndex].filter_values;\n      const filterLabel = this.filtersInt[filterIndex].labelInternal;\n      // get the filter value label and assume it is not a group\n      const filterValue = fieldType === 'group' ? values[valueIndex].values[groupIndex].labelInternal\n        : values[valueIndex].labelInternal;\n      // first check special case group\n      if (fieldType === 'group') {\n        // get all the concatenated values within the group\n        const concatValuesArray = values.reduce((prev, { values: groupFilterValues }) => prev\n          .concat(groupFilterValues.filter(val => hasData(val))), []);\n        // check if more than 1 value is left in the whole row\n        if (concatValuesArray.length < 2 && this.filtersInt.length < 2) {\n          this.removeFilters();\n          // now check if more than one value is left for the group\n        } else if (concatValuesArray.length > 1) {\n          // check for special case date and time fields\n          if (values[valueIndex].fieldType.includes('date') || values[valueIndex].fieldType.includes('time')) {\n            // for date arrays just remove the labelInternal so the order of the date_from and date_to does not\n            // get mixed up by removing the complete value\n            this.filtersInt[filterIndex].filter_values.values[valueIndex].values[groupIndex].labelInternal = '';\n          } else {\n            // if its not a date just splice the value out of the array\n            this.filtersInt[filterIndex].filter_values.values[valueIndex].values.splice(groupIndex, 1);\n          }\n          // else this means there is only 1 value in the group left and the whole filter group can be\n          // spliced away\n        } else {\n          // if no - just splice the complete filter group away\n          this.filtersInt.splice(filterIndex, 1);\n        }\n        // check if this is the last (or only) filter value currently selected\n      } else if (this.filtersInt.length === 1 && values.length === 1) {\n        // if yes - remove the complete row\n        this.removeFilters();\n        // else check if this is the only value for a specific filter\n      } else if (values.length === 1) {\n        // if yes - remove the complete filter\n        this.filtersInt.splice(filterIndex, 1);\n        // special case date object\n      } else if (fieldType.includes('date') || fieldType.includes('time')) {\n        if (values.filter(value => hasData(value)).length < 2) {\n          // if yes - remove the complete filter\n          this.filtersInt.splice(filterIndex, 1);\n        } else {\n          this.filtersInt[filterIndex].filter_values.values[valueIndex].labelInternal = '';\n        }\n      } else {\n        this.filtersInt[filterIndex].filter_values.values.splice(valueIndex, 1);\n      }\n      // set the assistive text so it is read by screenreader\n      this.chipRemovedAssistiveText = this.assistiveText.filterRemovedNotification\n        .replace('{label}', filterLabel)\n        .replace('{value}', filterValue);\n      // and remove it again afterward\n      setTimeout(() => {\n        this.chipRemovedAssistiveText = '';\n      }, 300);\n      // on iOS Safari the container remains the previous size so we scroll back to the max\n      // position manually\n      this.$nextTick(() => {\n        // if the scroll container is not present anymore, do nothing\n        if (!this.scrollContainer) return;\n        // otherwise calculate and scroll back to max position\n        if (this.scrollContainer.scrollLeft + this.scrollContainer.clientWidth >= this.scrollContainer.scrollWidth) {\n          this.scrollContainer.scrollLeft = this.scrollContainer.scrollWidth - this.scrollContainer.clientWidth;\n        }\n      });\n    },\n\n    /** OTHER METHODS */\n\n    /**\n     * determine if the provided filter values array has any label data in it\n     * (could be kept in the filter values list even if empty in order to be able\n     * to map again to the original formFieldValues)\n     * @param {Object[]} filterValues\n     * @returns {boolean}\n     */\n    filterValuesHaveData(filterValues) {\n      return hasData(filterValues);\n    },\n    getRangeIndicator(filterValues, index) {\n      // check if it is a filter with an array of exactly two values\n      if (filterValues.values.length === 2\n        && ['date', 'time'].includes(filterValues.fieldType)) {\n        if (!!filterValues.values[0].labelInternal\n          && !!filterValues.values[1].labelInternal && index === 1) {\n          return this.dateTimeText.range;\n        }\n        if (!filterValues.values[1].labelInternal && filterValues.values[0].labelInternal) {\n          return this.dateTimeText.from;\n        }\n        if (!filterValues.values[0].labelInternal && filterValues.values[1].labelInternal) {\n          return this.dateTimeText.until;\n        }\n      }\n      return '';\n    },\n    /**\n     * we need to check if `interpretLabelAsHtml` was set true for a subform field when\n     *  the prop was provided as [{ [parentField]: ['subfield1'] }]\n     * @param {string} filterId - the filter id as provided to this component (in the form\n     *  [fieldname]-group-[index])\n     * @param {string} valueId - the property name of the actual subformfield\n     * @returns {boolean}\n     */\n    calcSubFormChipHtmlRender(filterId, valueId) {\n      // get the correct filter property name from the id\n      // e.g. 'weekday-date-group-0' -> 'weekday-date'\n      const filterPropertyName = filterId.split('-').slice(0, 1).join('-');\n      // find the correct object in the `interpretLabelAsHtml` array\n      const subFormList = this.interpretLabelAsHtml\n        .find(id => typeof id === 'object' && Object.keys(id).includes(filterPropertyName));\n      // check if a value was found and if the field name is included in the list of that value\n      return !!subFormList && subFormList[filterPropertyName].includes(valueId);\n    },\n  },\n};\n</script>\n\n<template>\n  <div\n    class=\"base-collapsed-filter-row\">\n    <!-- Container to add fade out effect -->\n    <div\n      ref=\"filterListContainer\"\n      :class=\"['base-collapsed-filter-row__filter-list-container']\">\n      <!-- the actual list of filters -->\n      <ul\n        ref=\"filterList\"\n        :aria-description=\"assistiveText.appliedFiltersLabel\"\n        :class=\"[\n          'base-collapsed-filter-row__filter-list',\n        ]\">\n        <li\n          v-for=\"(filter, filterIndex) in filtersInt\"\n          :key=\"filter.idInternal\"\n          :aria-describedby=\"`${filter.idInternal}-label`\"\n          tabindex=\"0\"\n          :class=\"['base-collapsed-filter-row__filter',\n                   { 'base-collapsed-filter-row__filter__boolean': filter.filter_values\n                     .fieldType === 'boolean' }]\">\n          <template v-if=\"filter.filter_values && filterValuesHaveData(filter.filter_values.values)\">\n            <div\n              :id=\"`${filter.idInternal}-label`\"\n              class=\"base-collapsed-filter-row__filter-label\">\n              {{ filter.labelInternal }}\n            </div>\n            <!-- the chips for each filter -->\n            <ul\n              class=\"base-collapsed-filter-row__chips-list\">\n              <!-- iterate through the filter values list -->\n              <template\n                v-for=\"(value, valueIndex) in filter.filter_values?.values\">\n                <!-- check if filter.fieldType is an array to determine if it belongs to a field group -->\n                <template v-if=\"filter.filter_values.fieldType === 'group'\">\n                  <!-- if yes - also iterate through those values -->\n                  <template\n                    v-for=\"(groupValue, groupIndex) in value.values\"\n                    :key=\"groupValue.idInternal\n                      || `${groupValue.labelInternal}-${valueIndex}-${groupIndex}`\">\n                    <BaseCollapsedFilterItem\n                      v-if=\"groupValue.labelInternal\"\n                      :value=\"groupValue\"\n                      :type=\"value.fieldType\"\n                      :range-indicator=\"getRangeIndicator(value, groupIndex)\"\n                      :date-time-text=\"dateTimeText\"\n                      :interpret-label-as-html=\"(typeof interpretLabelAsHtml === 'boolean'\n                        && interpretLabelAsHtml) || (typeof interpretLabelAsHtml === 'object'\n                        && calcSubFormChipHtmlRender(filter.idInternal, value.fieldId))\"\n                      :assistive-text=\"{\n                        booleanFilterLabel: assistiveText.booleanFilterLabel\n                          ? assistiveText.booleanFilterLabel\n                            .replace('{label}', filter.labelInternal) : groupValue.labelInternal.toString(),\n                        optionToRemoveSelected: assistiveText.optionToRemoveSelected,\n                      }\"\n                      @remove-chip=\"removeChip(filterIndex, valueIndex, groupIndex)\" />\n                  </template>\n                </template>\n                <template v-else>\n                  <BaseCollapsedFilterItem\n                    v-if=\"value.labelInternal\"\n                    :key=\"value.idInternal || `${value.labelInternal}-${valueIndex}`\"\n                    :value=\"value\"\n                    :type=\"filter.filter_values.fieldType\"\n                    :range-indicator=\"getRangeIndicator(filter.filter_values, valueIndex)\"\n                    :date-time-text=\"dateTimeText\"\n                    :interpret-label-as-html=\"(typeof interpretLabelAsHtml === 'boolean'\n                      && interpretLabelAsHtml) || (typeof interpretLabelAsHtml === 'object'\n                      && interpretLabelAsHtml.includes(filter.idInternal))\"\n                    :assistive-text=\"{\n                      booleanFilterLabel: assistiveText.booleanFilterLabel\n                        ? assistiveText.booleanFilterLabel\n                          .replace('{label}', filter.labelInternal) : value.labelInternal.toString(),\n                      optionToRemoveSelected: assistiveText.optionToRemoveSelected,\n                    }\"\n                    @remove-chip=\"removeChip(filterIndex, valueIndex)\" />\n                </template>\n              </template>\n            </ul>\n          </template>\n        </li>\n      </ul>\n    </div>\n    <span\n      v-if=\"chipRemovedAssistiveText\"\n      aria-live=\"assertive\"\n      class=\"assistive-text\">\n      {{ chipRemovedAssistiveText }}\n    </span>\n\n    <!-- remove all filters button -->\n    <button\n      :title=\"assistiveText.removeFiltersLabel\"\n      class=\"base-collapsed-filter-row__remove\"\n      @keydown.enter.stop=\"removeFilters\"\n      @click.stop=\"removeFilters\">\n      <BaseIcon\n        name=\"remove\"\n        class=\"base-collapsed-filter-row__remove-icon\" />\n    </button>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n@use \"sass:map\";\n@use \"@/styles/variables\" as *;\n\n.base-collapsed-filter-row {\n  position: relative;\n  align-items: center;\n  padding-left: $spacing;\n  border-top: $separation-line;\n  display: flex;\n  flex-direction: row;\n  overflow: hidden;\n\n  .base-collapsed-filter-row__filter-list-container {\n    position: relative;\n    flex: 1 1 auto;\n    overflow: hidden;\n\n    .base-collapsed-filter-row__filter-list {\n      display: flex;\n      overflow-x: auto;\n      scrollbar-width: none; /* Firefox */\n      -ms-overflow-style: none;  /* Internet Explorer 10+ */\n      // need to add 1px because fade out not positioned perfectly else\n      margin-left: 1px;\n\n      &::-webkit-scrollbar { /* WebKit */\n        width: 0;\n        height: 0;\n      }\n\n      &.base-collapsed-filter-row__filter-list__scrollable,\n      &.base-collapsed-filter-row__filter-list__scrollable *:not(.base-chip__icon, .base-chip__icon use) {\n        cursor: grab;\n      }\n\n      .base-collapsed-filter-row__filter {\n        display: flex;\n        flex-direction: column;\n        justify-content: flex-start;\n        flex: 0 0 auto;\n        overflow-y: hidden;\n\n        + .base-collapsed-filter-row__filter {\n          margin-left: $spacing;\n        }\n\n        &.base-collapsed-filter-row__filter__boolean {\n          flex: 0 1 auto;\n          min-width: 150px;\n          overflow: hidden;\n        }\n\n        .base-collapsed-filter-row__filter-label {\n          font-size: $font-size-small;\n          line-height: normal;\n          color: $font-color-second;\n          white-space: nowrap;\n          width: 100%;\n          overflow: hidden;\n          text-overflow: ellipsis;\n        }\n\n        .base-collapsed-filter-row__chips-list {\n          display: flex;\n          flex-direction: row;\n          white-space: nowrap;\n          flex: 1 0 auto;\n          align-items: center;\n\n          .base-collapsed-filter-row__group-chip--spacing-right {\n            margin-right: $spacing-small;\n          }\n        }\n      }\n    }\n  }\n\n  .base-collapsed-filter-row__remove {\n    background: white;\n    display: flex;\n    flex: 0 0 auto;\n    padding: 0 $spacing;\n    height: 100%;\n    align-items: center;\n\n    &:hover, &:active, &:focus {\n      color: $app-color;\n    }\n\n    .base-collapsed-filter-row__remove-icon {\n      height: $icon-medium;\n      width: $icon-medium;\n      cursor: pointer;\n    }\n  }\n}\n</style>\n","/**\n * SSR Window 5.0.1\n * Better handling for window object in SSR environment\n * https://github.com/nolimits4web/ssr-window\n *\n * Copyright 2025, Vladimir Kharlampidi\n *\n * Licensed under MIT\n *\n * Released on: June 27, 2025\n */\n/* eslint-disable no-param-reassign */\nfunction isObject(obj) {\n  return obj !== null && typeof obj === 'object' && 'constructor' in obj && obj.constructor === Object;\n}\nfunction extend(target = {}, src = {}) {\n  const noExtend = ['__proto__', 'constructor', 'prototype'];\n  Object.keys(src).filter(key => noExtend.indexOf(key) < 0).forEach(key => {\n    if (typeof target[key] === 'undefined') target[key] = src[key];else if (isObject(src[key]) && isObject(target[key]) && Object.keys(src[key]).length > 0) {\n      extend(target[key], src[key]);\n    }\n  });\n}\nconst ssrDocument = {\n  body: {},\n  addEventListener() {},\n  removeEventListener() {},\n  activeElement: {\n    blur() {},\n    nodeName: ''\n  },\n  querySelector() {\n    return null;\n  },\n  querySelectorAll() {\n    return [];\n  },\n  getElementById() {\n    return null;\n  },\n  createEvent() {\n    return {\n      initEvent() {}\n    };\n  },\n  createElement() {\n    return {\n      children: [],\n      childNodes: [],\n      style: {},\n      setAttribute() {},\n      getElementsByTagName() {\n        return [];\n      }\n    };\n  },\n  createElementNS() {\n    return {};\n  },\n  importNode() {\n    return null;\n  },\n  location: {\n    hash: '',\n    host: '',\n    hostname: '',\n    href: '',\n    origin: '',\n    pathname: '',\n    protocol: '',\n    search: ''\n  }\n};\nfunction getDocument() {\n  const doc = typeof document !== 'undefined' ? document : {};\n  extend(doc, ssrDocument);\n  return doc;\n}\nconst 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    pushState() {},\n    go() {},\n    back() {}\n  },\n  CustomEvent: function CustomEvent() {\n    return this;\n  },\n  addEventListener() {},\n  removeEventListener() {},\n  getComputedStyle() {\n    return {\n      getPropertyValue() {\n        return '';\n      }\n    };\n  },\n  Image() {},\n  Date() {},\n  screen: {},\n  setTimeout() {},\n  clearTimeout() {},\n  matchMedia() {\n    return {};\n  },\n  requestAnimationFrame(callback) {\n    if (typeof setTimeout === 'undefined') {\n      callback();\n      return null;\n    }\n    return setTimeout(callback, 0);\n  },\n  cancelAnimationFrame(id) {\n    if (typeof setTimeout === 'undefined') {\n      return;\n    }\n    clearTimeout(id);\n  }\n};\nfunction getWindow() {\n  const win = typeof window !== 'undefined' ? window : {};\n  extend(win, ssrWindow);\n  return win;\n}\n\nexport { getWindow as a, getDocument as g };\n","import { a as getWindow, g as getDocument } from './ssr-window.esm.mjs';\n\nfunction classesToTokens(classes = '') {\n  return classes.trim().split(' ').filter(c => !!c.trim());\n}\n\nfunction deleteProps(obj) {\n  const object = obj;\n  Object.keys(object).forEach(key => {\n    try {\n      object[key] = null;\n    } catch (e) {\n      // no getter for object\n    }\n    try {\n      delete object[key];\n    } catch (e) {\n      // something got wrong\n    }\n  });\n}\nfunction nextTick(callback, delay = 0) {\n  return setTimeout(callback, delay);\n}\nfunction now() {\n  return Date.now();\n}\nfunction getComputedStyle(el) {\n  const window = getWindow();\n  let style;\n  if (window.getComputedStyle) {\n    style = window.getComputedStyle(el, null);\n  }\n  if (!style && el.currentStyle) {\n    style = el.currentStyle;\n  }\n  if (!style) {\n    style = el.style;\n  }\n  return style;\n}\nfunction getTranslate(el, axis = 'x') {\n  const window = getWindow();\n  let matrix;\n  let curTransform;\n  let transformMatrix;\n  const curStyle = getComputedStyle(el);\n  if (window.WebKitCSSMatrix) {\n    curTransform = curStyle.transform || curStyle.webkitTransform;\n    if (curTransform.split(',').length > 6) {\n      curTransform = curTransform.split(', ').map(a => a.replace(',', '.')).join(', ');\n    }\n    // Some old versions of Webkit choke when 'none' is passed; pass\n    // empty string instead in this case\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  if (axis === 'x') {\n    // Latest Chrome and webkits Fix\n    if (window.WebKitCSSMatrix) curTransform = transformMatrix.m41;\n    // Crazy IE10 Matrix\n    else if (matrix.length === 16) curTransform = parseFloat(matrix[12]);\n    // Normal Browsers\n    else curTransform = parseFloat(matrix[4]);\n  }\n  if (axis === 'y') {\n    // Latest Chrome and webkits Fix\n    if (window.WebKitCSSMatrix) curTransform = transformMatrix.m42;\n    // Crazy IE10 Matrix\n    else if (matrix.length === 16) curTransform = parseFloat(matrix[13]);\n    // Normal Browsers\n    else curTransform = parseFloat(matrix[5]);\n  }\n  return curTransform || 0;\n}\nfunction isObject(o) {\n  return typeof o === 'object' && o !== null && o.constructor && Object.prototype.toString.call(o).slice(8, -1) === 'Object';\n}\nfunction isNode(node) {\n  // eslint-disable-next-line\n  if (typeof window !== 'undefined' && typeof window.HTMLElement !== 'undefined') {\n    return node instanceof HTMLElement;\n  }\n  return node && (node.nodeType === 1 || node.nodeType === 11);\n}\nfunction extend(...args) {\n  const to = Object(args[0]);\n  for (let i = 1; i < args.length; i += 1) {\n    const nextSource = args[i];\n    if (nextSource !== undefined && nextSource !== null && !isNode(nextSource)) {\n      const keysArray = Object.keys(Object(nextSource)).filter(key => key !== '__proto__' && key !== 'constructor' && key !== 'prototype');\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        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            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  return to;\n}\nfunction setCSSProperty(el, varName, varValue) {\n  el.style.setProperty(varName, varValue);\n}\nfunction animateCSSModeScroll({\n  swiper,\n  targetPosition,\n  side\n}) {\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  const isOutOfBound = (current, target) => {\n    return dir === 'next' && current >= target || dir === 'prev' && current <= target;\n  };\n  const animate = () => {\n    time = new Date().getTime();\n    if (startTime === null) {\n      startTime = time;\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    if (isOutOfBound(currentPosition, targetPosition)) {\n      currentPosition = targetPosition;\n    }\n    swiper.wrapperEl.scrollTo({\n      [side]: currentPosition\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    swiper.cssModeFrameID = window.requestAnimationFrame(animate);\n  };\n  animate();\n}\nfunction getSlideTransformEl(slideEl) {\n  return slideEl.querySelector('.swiper-slide-transform') || slideEl.shadowRoot && slideEl.shadowRoot.querySelector('.swiper-slide-transform') || slideEl;\n}\nfunction elementChildren(element, selector = '') {\n  const window = getWindow();\n  const children = [...element.children];\n  if (window.HTMLSlotElement && element instanceof HTMLSlotElement) {\n    children.push(...element.assignedElements());\n  }\n  if (!selector) {\n    return children;\n  }\n  return children.filter(el => el.matches(selector));\n}\nfunction elementIsChildOfSlot(el, slot) {\n  // Breadth-first search through all parent's children and assigned elements\n  const elementsQueue = [slot];\n  while (elementsQueue.length > 0) {\n    const elementToCheck = elementsQueue.shift();\n    if (el === elementToCheck) {\n      return true;\n    }\n    elementsQueue.push(...elementToCheck.children, ...(elementToCheck.shadowRoot ? elementToCheck.shadowRoot.children : []), ...(elementToCheck.assignedElements ? elementToCheck.assignedElements() : []));\n  }\n}\nfunction elementIsChildOf(el, parent) {\n  const window = getWindow();\n  let isChild = parent.contains(el);\n  if (!isChild && window.HTMLSlotElement && parent instanceof HTMLSlotElement) {\n    const children = [...parent.assignedElements()];\n    isChild = children.includes(el);\n    if (!isChild) {\n      isChild = elementIsChildOfSlot(el, parent);\n    }\n  }\n  return isChild;\n}\nfunction showWarning(text) {\n  try {\n    console.warn(text);\n    return;\n  } catch (err) {\n    // err\n  }\n}\nfunction createElement(tag, classes = []) {\n  const el = document.createElement(tag);\n  el.classList.add(...(Array.isArray(classes) ? classes : classesToTokens(classes)));\n  return el;\n}\nfunction elementOffset(el) {\n  const window = getWindow();\n  const document = getDocument();\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}\nfunction elementPrevAll(el, selector) {\n  const prevEls = [];\n  while (el.previousElementSibling) {\n    const prev = el.previousElementSibling; // eslint-disable-line\n    if (selector) {\n      if (prev.matches(selector)) prevEls.push(prev);\n    } else prevEls.push(prev);\n    el = prev;\n  }\n  return prevEls;\n}\nfunction elementNextAll(el, selector) {\n  const nextEls = [];\n  while (el.nextElementSibling) {\n    const next = el.nextElementSibling; // eslint-disable-line\n    if (selector) {\n      if (next.matches(selector)) nextEls.push(next);\n    } else nextEls.push(next);\n    el = next;\n  }\n  return nextEls;\n}\nfunction elementStyle(el, prop) {\n  const window = getWindow();\n  return window.getComputedStyle(el, null).getPropertyValue(prop);\n}\nfunction elementIndex(el) {\n  let child = el;\n  let i;\n  if (child) {\n    i = 0;\n    // eslint-disable-next-line\n    while ((child = child.previousSibling) !== null) {\n      if (child.nodeType === 1) i += 1;\n    }\n    return i;\n  }\n  return undefined;\n}\nfunction elementParents(el, selector) {\n  const parents = []; // eslint-disable-line\n  let parent = el.parentElement; // eslint-disable-line\n  while (parent) {\n    if (selector) {\n      if (parent.matches(selector)) parents.push(parent);\n    } else {\n      parents.push(parent);\n    }\n    parent = parent.parentElement;\n  }\n  return parents;\n}\nfunction elementTransitionEnd(el, callback) {\n  function fireCallBack(e) {\n    if (e.target !== el) return;\n    callback.call(el, e);\n    el.removeEventListener('transitionend', fireCallBack);\n  }\n  if (callback) {\n    el.addEventListener('transitionend', fireCallBack);\n  }\n}\nfunction elementOuterSize(el, size, includeMargins) {\n  const window = getWindow();\n  if (includeMargins) {\n    return el[size === 'width' ? 'offsetWidth' : 'offsetHeight'] + parseFloat(window.getComputedStyle(el, null).getPropertyValue(size === 'width' ? 'margin-right' : 'margin-top')) + parseFloat(window.getComputedStyle(el, null).getPropertyValue(size === 'width' ? 'margin-left' : 'margin-bottom'));\n  }\n  return el.offsetWidth;\n}\nfunction makeElementsArray(el) {\n  return (Array.isArray(el) ? el : [el]).filter(e => !!e);\n}\nfunction getRotateFix(swiper) {\n  return v => {\n    if (Math.abs(v) > 0 && swiper.browser && swiper.browser.need3dFix && Math.abs(v) % 90 === 0) {\n      return v + 0.001;\n    }\n    return v;\n  };\n}\nfunction setInnerHTML(el, html = '') {\n  if (typeof trustedTypes !== 'undefined') {\n    el.innerHTML = trustedTypes.createPolicy('html', {\n      createHTML: s => s\n    }).createHTML(html);\n  } else {\n    el.innerHTML = html;\n  }\n}\n\nexport { getRotateFix as a, setCSSProperty as b, createElement as c, elementParents as d, elementChildren as e, elementOffset as f, getSlideTransformEl as g, now as h, elementOuterSize as i, elementIndex as j, classesToTokens as k, getTranslate as l, makeElementsArray as m, nextTick as n, elementTransitionEnd as o, isObject as p, elementStyle as q, elementNextAll as r, setInnerHTML as s, elementPrevAll as t, animateCSSModeScroll as u, showWarning as v, elementIsChildOf as w, extend as x, deleteProps as y };\n","import { g as getDocument, a as getWindow } from '../shared/ssr-window.esm.mjs';\nimport { d as elementParents, f as elementOffset } from '../shared/utils.mjs';\n\n/* eslint-disable consistent-return */\nfunction Keyboard({\n  swiper,\n  extendParams,\n  on,\n  emit\n}) {\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      speed: undefined\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    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;\n    // Directions locks\n    if (!swiper.allowSlideNext && (swiper.isHorizontal() && isArrowRight || swiper.isVertical() && isArrowDown || isPageDown)) {\n      return false;\n    }\n    if (!swiper.allowSlidePrev && (swiper.isHorizontal() && isArrowLeft || swiper.isVertical() && isArrowUp || isPageUp)) {\n      return false;\n    }\n    if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {\n      return undefined;\n    }\n    if (document.activeElement && (document.activeElement.isContentEditable || document.activeElement.nodeName && (document.activeElement.nodeName.toLowerCase() === 'input' || document.activeElement.nodeName.toLowerCase() === 'textarea'))) {\n      return undefined;\n    }\n    if (swiper.params.keyboard.onlyInViewport && (isPageUp || isPageDown || isArrowLeft || isArrowRight || isArrowUp || isArrowDown)) {\n      let inView = false;\n      // Check that swiper should be inside of visible area of window\n      if (elementParents(swiper.el, `.${swiper.params.slideClass}, swiper-slide`).length > 0 && elementParents(swiper.el, `.${swiper.params.slideActiveClass}`).length === 0) {\n        return undefined;\n      }\n      const el = swiper.el;\n      const swiperWidth = el.clientWidth;\n      const swiperHeight = el.clientHeight;\n      const windowWidth = window.innerWidth;\n      const windowHeight = window.innerHeight;\n      const swiperOffset = elementOffset(el);\n      if (rtl) swiperOffset.left -= el.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      for (let i = 0; i < swiperCoord.length; i += 1) {\n        const point = swiperCoord[i];\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          inView = true;\n        }\n      }\n      if (!inView) return undefined;\n    }\n    const speed = swiper.params.keyboard.speed;\n    if (swiper.isHorizontal()) {\n      if (isPageUp || isPageDown || isArrowLeft || isArrowRight) {\n        if (e.preventDefault) e.preventDefault();else e.returnValue = false;\n      }\n      if ((isPageDown || isArrowRight) && !rtl || (isPageUp || isArrowLeft) && rtl) swiper.slideNext(speed);\n      if ((isPageUp || isArrowLeft) && !rtl || (isPageDown || isArrowRight) && rtl) swiper.slidePrev(speed);\n    } else {\n      if (isPageUp || isPageDown || isArrowUp || isArrowDown) {\n        if (e.preventDefault) e.preventDefault();else e.returnValue = false;\n      }\n      if (isPageDown || isArrowDown) swiper.slideNext(speed);\n      if (isPageUp || isArrowUp) swiper.slidePrev(speed);\n    }\n    emit('keyPress', kc);\n    return undefined;\n  }\n  function enable() {\n    if (swiper.keyboard.enabled) return;\n    document.addEventListener('keydown', handle);\n    swiper.keyboard.enabled = true;\n  }\n  function disable() {\n    if (!swiper.keyboard.enabled) return;\n    document.removeEventListener('keydown', handle);\n    swiper.keyboard.enabled = false;\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\nexport { Keyboard as default };\n","import { e as elementChildren, c as createElement } from './utils.mjs';\n\nfunction createElementIfNotDefined(swiper, originalParams, params, checkProps) {\n  if (swiper.params.createElements) {\n    Object.keys(checkProps).forEach(key => {\n      if (!params[key] && params.auto === true) {\n        let element = elementChildren(swiper.el, `.${checkProps[key]}`)[0];\n        if (!element) {\n          element = createElement('div', checkProps[key]);\n          element.className = checkProps[key];\n          swiper.el.append(element);\n        }\n        params[key] = element;\n        originalParams[key] = element;\n      }\n    });\n  }\n  return params;\n}\n\nexport { createElementIfNotDefined as c };\n","import { c as createElementIfNotDefined } from '../shared/create-element-if-not-defined.mjs';\nimport { m as makeElementsArray, s as setInnerHTML } from '../shared/utils.mjs';\n\nconst arrowSvg = `<svg class=\"swiper-navigation-icon\" width=\"11\" height=\"20\" viewBox=\"0 0 11 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M0.38296 20.0762C0.111788 19.805 0.111788 19.3654 0.38296 19.0942L9.19758 10.2796L0.38296 1.46497C0.111788 1.19379 0.111788 0.754138 0.38296 0.482966C0.654131 0.211794 1.09379 0.211794 1.36496 0.482966L10.4341 9.55214C10.8359 9.9539 10.8359 10.6053 10.4341 11.007L1.36496 20.0762C1.09379 20.3474 0.654131 20.3474 0.38296 20.0762Z\" fill=\"currentColor\"/></svg>`;\nfunction Navigation({\n  swiper,\n  extendParams,\n  on,\n  emit\n}) {\n  extendParams({\n    navigation: {\n      nextEl: null,\n      prevEl: null,\n      addIcons: true,\n      hideOnClick: false,\n      disabledClass: 'swiper-button-disabled',\n      hiddenClass: 'swiper-button-hidden',\n      lockClass: 'swiper-button-lock',\n      navigationDisabledClass: 'swiper-navigation-disabled'\n    }\n  });\n  swiper.navigation = {\n    nextEl: null,\n    prevEl: null,\n    arrowSvg\n  };\n  function getEl(el) {\n    let res;\n    if (el && typeof el === 'string' && swiper.isElement) {\n      res = swiper.el.querySelector(el) || swiper.hostEl.querySelector(el);\n      if (res) return res;\n    }\n    if (el) {\n      if (typeof el === 'string') res = [...document.querySelectorAll(el)];\n      if (swiper.params.uniqueNavElements && typeof el === 'string' && res && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) {\n        res = swiper.el.querySelector(el);\n      } else if (res && res.length === 1) {\n        res = res[0];\n      }\n    }\n    if (el && !res) return el;\n    // if (Array.isArray(res) && res.length === 1) res = res[0];\n    return res;\n  }\n  function toggleEl(el, disabled) {\n    const params = swiper.params.navigation;\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      if (subEl) {\n        subEl.classList[disabled ? 'add' : 'remove'](...params.disabledClass.split(' '));\n        if (subEl.tagName === 'BUTTON') subEl.disabled = disabled;\n        if (swiper.params.watchOverflow && swiper.enabled) {\n          subEl.classList[swiper.isLocked ? 'add' : 'remove'](params.lockClass);\n        }\n      }\n    });\n  }\n  function update() {\n    // Update Navigation Buttons\n    const {\n      nextEl,\n      prevEl\n    } = swiper.navigation;\n    if (swiper.params.loop) {\n      toggleEl(prevEl, false);\n      toggleEl(nextEl, false);\n      return;\n    }\n    toggleEl(prevEl, swiper.isBeginning && !swiper.params.rewind);\n    toggleEl(nextEl, swiper.isEnd && !swiper.params.rewind);\n  }\n  function onPrevClick(e) {\n    e.preventDefault();\n    if (swiper.isBeginning && !swiper.params.loop && !swiper.params.rewind) return;\n    swiper.slidePrev();\n    emit('navigationPrev');\n  }\n  function onNextClick(e) {\n    e.preventDefault();\n    if (swiper.isEnd && !swiper.params.loop && !swiper.params.rewind) return;\n    swiper.slideNext();\n    emit('navigationNext');\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    let nextEl = getEl(params.nextEl);\n    let prevEl = getEl(params.prevEl);\n    Object.assign(swiper.navigation, {\n      nextEl,\n      prevEl\n    });\n    nextEl = makeElementsArray(nextEl);\n    prevEl = makeElementsArray(prevEl);\n    const initButton = (el, dir) => {\n      if (el) {\n        if (params.addIcons && el.matches('.swiper-button-next,.swiper-button-prev') && !el.querySelector('svg')) {\n          const tempEl = document.createElement('div');\n          setInnerHTML(tempEl, arrowSvg);\n          el.appendChild(tempEl.querySelector('svg'));\n          tempEl.remove();\n        }\n        el.addEventListener('click', dir === 'next' ? onNextClick : onPrevClick);\n      }\n      if (!swiper.enabled && el) {\n        el.classList.add(...params.lockClass.split(' '));\n      }\n    };\n    nextEl.forEach(el => initButton(el, 'next'));\n    prevEl.forEach(el => initButton(el, 'prev'));\n  }\n  function destroy() {\n    let {\n      nextEl,\n      prevEl\n    } = swiper.navigation;\n    nextEl = makeElementsArray(nextEl);\n    prevEl = makeElementsArray(prevEl);\n    const destroyButton = (el, dir) => {\n      el.removeEventListener('click', dir === 'next' ? onNextClick : onPrevClick);\n      el.classList.remove(...swiper.params.navigation.disabledClass.split(' '));\n    };\n    nextEl.forEach(el => destroyButton(el, 'next'));\n    prevEl.forEach(el => destroyButton(el, 'prev'));\n  }\n  on('init', () => {\n    if (swiper.params.navigation.enabled === false) {\n      // eslint-disable-next-line\n      disable();\n    } else {\n      init();\n      update();\n    }\n  });\n  on('toEdge fromEdge lock unlock', () => {\n    update();\n  });\n  on('destroy', () => {\n    destroy();\n  });\n  on('enable disable', () => {\n    let {\n      nextEl,\n      prevEl\n    } = swiper.navigation;\n    nextEl = makeElementsArray(nextEl);\n    prevEl = makeElementsArray(prevEl);\n    if (swiper.enabled) {\n      update();\n      return;\n    }\n    [...nextEl, ...prevEl].filter(el => !!el).forEach(el => el.classList.add(swiper.params.navigation.lockClass));\n  });\n  on('click', (_s, e) => {\n    let {\n      nextEl,\n      prevEl\n    } = swiper.navigation;\n    nextEl = makeElementsArray(nextEl);\n    prevEl = makeElementsArray(prevEl);\n    const targetEl = e.target;\n    let targetIsButton = prevEl.includes(targetEl) || nextEl.includes(targetEl);\n    if (swiper.isElement && !targetIsButton) {\n      const path = e.path || e.composedPath && e.composedPath();\n      if (path) {\n        targetIsButton = path.find(pathEl => nextEl.includes(pathEl) || prevEl.includes(pathEl));\n      }\n    }\n    if (swiper.params.navigation.hideOnClick && !targetIsButton) {\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      if (nextEl.length) {\n        isHidden = nextEl[0].classList.contains(swiper.params.navigation.hiddenClass);\n      } else if (prevEl.length) {\n        isHidden = prevEl[0].classList.contains(swiper.params.navigation.hiddenClass);\n      }\n      if (isHidden === true) {\n        emit('navigationShow');\n      } else {\n        emit('navigationHide');\n      }\n      [...nextEl, ...prevEl].filter(el => !!el).forEach(el => el.classList.toggle(swiper.params.navigation.hiddenClass));\n    }\n  });\n  const enable = () => {\n    swiper.el.classList.remove(...swiper.params.navigation.navigationDisabledClass.split(' '));\n    init();\n    update();\n  };\n  const disable = () => {\n    swiper.el.classList.add(...swiper.params.navigation.navigationDisabledClass.split(' '));\n    destroy();\n  };\n  Object.assign(swiper.navigation, {\n    enable,\n    disable,\n    update,\n    init,\n    destroy\n  });\n}\n\nexport { Navigation as default };\n","function classesToSelector(classes = '') {\n  // Escape all CSS selector special characters\n  return `.${classes.trim().replace(/([\\.:!+\\/()[\\]#>~*^$|=,'\"@{}\\\\])/g, '\\\\$1') // eslint-disable-line\n  .replace(/ /g, '.')}`;\n}\n\nexport { classesToSelector as c };\n","import { c as classesToSelector } from '../shared/classes-to-selector.mjs';\nimport { c as createElementIfNotDefined } from '../shared/create-element-if-not-defined.mjs';\nimport { m as makeElementsArray, i as elementOuterSize, j as elementIndex, s as setInnerHTML, d as elementParents } from '../shared/utils.mjs';\n\nfunction Pagination({\n  swiper,\n  extendParams,\n  on,\n  emit\n}) {\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      paginationDisabledClass: `${pfx}-disabled`\n    }\n  });\n  swiper.pagination = {\n    el: null,\n    bullets: []\n  };\n  let bulletSize;\n  let dynamicBulletIndex = 0;\n  function isPaginationDisabled() {\n    return !swiper.params.pagination.el || !swiper.pagination.el || Array.isArray(swiper.pagination.el) && swiper.pagination.el.length === 0;\n  }\n  function setSideBullets(bulletEl, position) {\n    const {\n      bulletActiveClass\n    } = swiper.params.pagination;\n    if (!bulletEl) return;\n    bulletEl = bulletEl[`${position === 'prev' ? 'previous' : 'next'}ElementSibling`];\n    if (bulletEl) {\n      bulletEl.classList.add(`${bulletActiveClass}-${position}`);\n      bulletEl = bulletEl[`${position === 'prev' ? 'previous' : 'next'}ElementSibling`];\n      if (bulletEl) {\n        bulletEl.classList.add(`${bulletActiveClass}-${position}-${position}`);\n      }\n    }\n  }\n  function getMoveDirection(prevIndex, nextIndex, length) {\n    prevIndex = prevIndex % length;\n    nextIndex = nextIndex % length;\n    if (nextIndex === prevIndex + 1) {\n      return 'next';\n    } else if (nextIndex === prevIndex - 1) {\n      return 'previous';\n    }\n    return;\n  }\n  function onBulletClick(e) {\n    const bulletEl = e.target.closest(classesToSelector(swiper.params.pagination.bulletClass));\n    if (!bulletEl) {\n      return;\n    }\n    e.preventDefault();\n    const index = elementIndex(bulletEl) * swiper.params.slidesPerGroup;\n    if (swiper.params.loop) {\n      if (swiper.realIndex === index) return;\n      const moveDirection = getMoveDirection(swiper.realIndex, index, swiper.slides.length);\n      if (moveDirection === 'next') {\n        swiper.slideNext();\n      } else if (moveDirection === 'previous') {\n        swiper.slidePrev();\n      } else {\n        swiper.slideToLoop(index);\n      }\n    } else {\n      swiper.slideTo(index);\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    let el = swiper.pagination.el;\n    el = makeElementsArray(el);\n    // Current/Total\n    let current;\n    let previousIndex;\n    const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;\n    const total = swiper.params.loop ? Math.ceil(slidesLength / swiper.params.slidesPerGroup) : swiper.snapGrid.length;\n    if (swiper.params.loop) {\n      previousIndex = swiper.previousRealIndex || 0;\n      current = swiper.params.slidesPerGroup > 1 ? Math.floor(swiper.realIndex / swiper.params.slidesPerGroup) : swiper.realIndex;\n    } else if (typeof swiper.snapIndex !== 'undefined') {\n      current = swiper.snapIndex;\n      previousIndex = swiper.previousSnapIndex;\n    } else {\n      previousIndex = swiper.previousIndex || 0;\n      current = swiper.activeIndex || 0;\n    }\n    // Types\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      if (params.dynamicBullets) {\n        bulletSize = elementOuterSize(bullets[0], swiper.isHorizontal() ? 'width' : 'height', true);\n        el.forEach(subEl => {\n          subEl.style[swiper.isHorizontal() ? 'width' : 'height'] = `${bulletSize * (params.dynamicMainBullets + 4)}px`;\n        });\n        if (params.dynamicMainBullets > 1 && previousIndex !== undefined) {\n          dynamicBulletIndex += current - (previousIndex || 0);\n          if (dynamicBulletIndex > params.dynamicMainBullets - 1) {\n            dynamicBulletIndex = params.dynamicMainBullets - 1;\n          } else if (dynamicBulletIndex < 0) {\n            dynamicBulletIndex = 0;\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      bullets.forEach(bulletEl => {\n        const classesToRemove = [...['', '-next', '-next-next', '-prev', '-prev-prev', '-main'].map(suffix => `${params.bulletActiveClass}${suffix}`)].map(s => typeof s === 'string' && s.includes(' ') ? s.split(' ') : s).flat();\n        bulletEl.classList.remove(...classesToRemove);\n      });\n      if (el.length > 1) {\n        bullets.forEach(bullet => {\n          const bulletIndex = elementIndex(bullet);\n          if (bulletIndex === current) {\n            bullet.classList.add(...params.bulletActiveClass.split(' '));\n          } else if (swiper.isElement) {\n            bullet.setAttribute('part', 'bullet');\n          }\n          if (params.dynamicBullets) {\n            if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {\n              bullet.classList.add(...`${params.bulletActiveClass}-main`.split(' '));\n            }\n            if (bulletIndex === firstIndex) {\n              setSideBullets(bullet, 'prev');\n            }\n            if (bulletIndex === lastIndex) {\n              setSideBullets(bullet, 'next');\n            }\n          }\n        });\n      } else {\n        const bullet = bullets[current];\n        if (bullet) {\n          bullet.classList.add(...params.bulletActiveClass.split(' '));\n        }\n        if (swiper.isElement) {\n          bullets.forEach((bulletEl, bulletIndex) => {\n            bulletEl.setAttribute('part', bulletIndex === current ? 'bullet-active' : 'bullet');\n          });\n        }\n        if (params.dynamicBullets) {\n          const firstDisplayedBullet = bullets[firstIndex];\n          const lastDisplayedBullet = bullets[lastIndex];\n          for (let i = firstIndex; i <= lastIndex; i += 1) {\n            if (bullets[i]) {\n              bullets[i].classList.add(...`${params.bulletActiveClass}-main`.split(' '));\n            }\n          }\n          setSideBullets(firstDisplayedBullet, 'prev');\n          setSideBullets(lastDisplayedBullet, 'next');\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.forEach(bullet => {\n          bullet.style[swiper.isHorizontal() ? offsetProp : 'top'] = `${bulletsOffset}px`;\n        });\n      }\n    }\n    el.forEach((subEl, subElIndex) => {\n      if (params.type === 'fraction') {\n        subEl.querySelectorAll(classesToSelector(params.currentClass)).forEach(fractionEl => {\n          fractionEl.textContent = params.formatFractionCurrent(current + 1);\n        });\n        subEl.querySelectorAll(classesToSelector(params.totalClass)).forEach(totalEl => {\n          totalEl.textContent = params.formatFractionTotal(total);\n        });\n      }\n      if (params.type === 'progressbar') {\n        let progressbarDirection;\n        if (params.progressbarOpposite) {\n          progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';\n        } else {\n          progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';\n        }\n        const scale = (current + 1) / total;\n        let scaleX = 1;\n        let scaleY = 1;\n        if (progressbarDirection === 'horizontal') {\n          scaleX = scale;\n        } else {\n          scaleY = scale;\n        }\n        subEl.querySelectorAll(classesToSelector(params.progressbarFillClass)).forEach(progressEl => {\n          progressEl.style.transform = `translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`;\n          progressEl.style.transitionDuration = `${swiper.params.speed}ms`;\n        });\n      }\n      if (params.type === 'custom' && params.renderCustom) {\n        setInnerHTML(subEl, params.renderCustom(swiper, current + 1, total));\n        if (subElIndex === 0) emit('paginationRender', subEl);\n      } else {\n        if (subElIndex === 0) emit('paginationRender', subEl);\n        emit('paginationUpdate', subEl);\n      }\n      if (swiper.params.watchOverflow && swiper.enabled) {\n        subEl.classList[swiper.isLocked ? 'add' : 'remove'](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.grid && swiper.params.grid.rows > 1 ? swiper.slides.length / Math.ceil(swiper.params.grid.rows) : swiper.slides.length;\n    let el = swiper.pagination.el;\n    el = makeElementsArray(el);\n    let paginationHTML = '';\n    if (params.type === 'bullets') {\n      let numberOfBullets = swiper.params.loop ? Math.ceil(slidesLength / swiper.params.slidesPerGroup) : swiper.snapGrid.length;\n      if (swiper.params.freeMode && swiper.params.freeMode.enabled && numberOfBullets > slidesLength) {\n        numberOfBullets = slidesLength;\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          // prettier-ignore\n          paginationHTML += `<${params.bulletElement} ${swiper.isElement ? 'part=\"bullet\"' : ''} class=\"${params.bulletClass}\"></${params.bulletElement}>`;\n        }\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 = `<span class=\"${params.currentClass}\"></span>` + ' / ' + `<span class=\"${params.totalClass}\"></span>`;\n      }\n    }\n    if (params.type === 'progressbar') {\n      if (params.renderProgressbar) {\n        paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);\n      } else {\n        paginationHTML = `<span class=\"${params.progressbarFillClass}\"></span>`;\n      }\n    }\n    swiper.pagination.bullets = [];\n    el.forEach(subEl => {\n      if (params.type !== 'custom') {\n        setInnerHTML(subEl, paginationHTML || '');\n      }\n      if (params.type === 'bullets') {\n        swiper.pagination.bullets.push(...subEl.querySelectorAll(classesToSelector(params.bulletClass)));\n      }\n    });\n    if (params.type !== 'custom') {\n      emit('paginationRender', el[0]);\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;\n    if (typeof params.el === 'string' && swiper.isElement) {\n      el = swiper.el.querySelector(params.el);\n    }\n    if (!el && typeof params.el === 'string') {\n      el = [...document.querySelectorAll(params.el)];\n    }\n    if (!el) {\n      el = params.el;\n    }\n    if (!el || el.length === 0) return;\n    if (swiper.params.uniqueNavElements && typeof params.el === 'string' && Array.isArray(el) && el.length > 1) {\n      el = [...swiper.el.querySelectorAll(params.el)];\n      // check if it belongs to another nested Swiper\n      if (el.length > 1) {\n        el = el.find(subEl => {\n          if (elementParents(subEl, '.swiper')[0] !== swiper.el) return false;\n          return true;\n        });\n      }\n    }\n    if (Array.isArray(el) && el.length === 1) el = el[0];\n    Object.assign(swiper.pagination, {\n      el\n    });\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      if (params.type === 'bullets' && params.clickable) {\n        subEl.classList.add(...(params.clickableClass || '').split(' '));\n      }\n      subEl.classList.add(params.modifierClass + params.type);\n      subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);\n      if (params.type === 'bullets' && params.dynamicBullets) {\n        subEl.classList.add(`${params.modifierClass}${params.type}-dynamic`);\n        dynamicBulletIndex = 0;\n        if (params.dynamicMainBullets < 1) {\n          params.dynamicMainBullets = 1;\n        }\n      }\n      if (params.type === 'progressbar' && params.progressbarOpposite) {\n        subEl.classList.add(params.progressbarOppositeClass);\n      }\n      if (params.clickable) {\n        subEl.addEventListener('click', onBulletClick);\n      }\n      if (!swiper.enabled) {\n        subEl.classList.add(params.lockClass);\n      }\n    });\n  }\n  function destroy() {\n    const params = swiper.params.pagination;\n    if (isPaginationDisabled()) return;\n    let el = swiper.pagination.el;\n    if (el) {\n      el = makeElementsArray(el);\n      el.forEach(subEl => {\n        subEl.classList.remove(params.hiddenClass);\n        subEl.classList.remove(params.modifierClass + params.type);\n        subEl.classList.remove(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);\n        if (params.clickable) {\n          subEl.classList.remove(...(params.clickableClass || '').split(' '));\n          subEl.removeEventListener('click', onBulletClick);\n        }\n      });\n    }\n    if (swiper.pagination.bullets) swiper.pagination.bullets.forEach(subEl => subEl.classList.remove(...params.bulletActiveClass.split(' ')));\n  }\n  on('changeDirection', () => {\n    if (!swiper.pagination || !swiper.pagination.el) return;\n    const params = swiper.params.pagination;\n    let {\n      el\n    } = swiper.pagination;\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      subEl.classList.remove(params.horizontalClass, params.verticalClass);\n      subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);\n    });\n  });\n  on('init', () => {\n    if (swiper.params.pagination.enabled === false) {\n      // eslint-disable-next-line\n      disable();\n    } else {\n      init();\n      render();\n      update();\n    }\n  });\n  on('activeIndexChange', () => {\n    if (typeof swiper.snapIndex === 'undefined') {\n      update();\n    }\n  });\n  on('snapIndexChange', () => {\n    update();\n  });\n  on('snapGridLengthChange', () => {\n    render();\n    update();\n  });\n  on('destroy', () => {\n    destroy();\n  });\n  on('enable disable', () => {\n    let {\n      el\n    } = swiper.pagination;\n    if (el) {\n      el = makeElementsArray(el);\n      el.forEach(subEl => subEl.classList[swiper.enabled ? 'remove' : 'add'](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 el = makeElementsArray(swiper.pagination.el);\n    if (swiper.params.pagination.el && swiper.params.pagination.hideOnClick && el && el.length > 0 && !targetEl.classList.contains(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[0].classList.contains(swiper.params.pagination.hiddenClass);\n      if (isHidden === true) {\n        emit('paginationShow');\n      } else {\n        emit('paginationHide');\n      }\n      el.forEach(subEl => subEl.classList.toggle(swiper.params.pagination.hiddenClass));\n    }\n  });\n  const enable = () => {\n    swiper.el.classList.remove(swiper.params.pagination.paginationDisabledClass);\n    let {\n      el\n    } = swiper.pagination;\n    if (el) {\n      el = makeElementsArray(el);\n      el.forEach(subEl => subEl.classList.remove(swiper.params.pagination.paginationDisabledClass));\n    }\n    init();\n    render();\n    update();\n  };\n  const disable = () => {\n    swiper.el.classList.add(swiper.params.pagination.paginationDisabledClass);\n    let {\n      el\n    } = swiper.pagination;\n    if (el) {\n      el = makeElementsArray(el);\n      el.forEach(subEl => subEl.classList.add(swiper.params.pagination.paginationDisabledClass));\n    }\n    destroy();\n  };\n  Object.assign(swiper.pagination, {\n    enable,\n    disable,\n    render,\n    update,\n    init,\n    destroy\n  });\n}\n\nexport { Pagination as default };\n","import { a as getWindow } from '../shared/ssr-window.esm.mjs';\nimport { e as elementChildren, d as elementParents, f as elementOffset, l as getTranslate } from '../shared/utils.mjs';\n\nfunction Zoom({\n  swiper,\n  extendParams,\n  on,\n  emit\n}) {\n  const window = getWindow();\n  extendParams({\n    zoom: {\n      enabled: false,\n      limitToOriginalSize: false,\n      maxRatio: 3,\n      minRatio: 1,\n      panOnMouseMove: false,\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 isPanningWithMouse = false;\n  let mousePanStart = {\n    x: 0,\n    y: 0\n  };\n  const mousePanSensitivity = -3; // Negative to invert pan direction\n  let fakeGestureTouched;\n  let fakeGestureMoved;\n  const evCache = [];\n  const gesture = {\n    originX: 0,\n    originY: 0,\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    set(value) {\n      if (scale !== value) {\n        const imageEl = gesture.imageEl;\n        const slideEl = gesture.slideEl;\n        emit('zoomChange', value, imageEl, slideEl);\n      }\n      scale = value;\n    }\n  });\n  function getDistanceBetweenTouches() {\n    if (evCache.length < 2) return 1;\n    const x1 = evCache[0].pageX;\n    const y1 = evCache[0].pageY;\n    const x2 = evCache[1].pageX;\n    const y2 = evCache[1].pageY;\n    const distance = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);\n    return distance;\n  }\n  function getMaxRatio() {\n    const params = swiper.params.zoom;\n    const maxRatio = gesture.imageWrapEl.getAttribute('data-swiper-zoom') || params.maxRatio;\n    if (params.limitToOriginalSize && gesture.imageEl && gesture.imageEl.naturalWidth) {\n      const imageMaxRatio = gesture.imageEl.naturalWidth / gesture.imageEl.offsetWidth;\n      return Math.min(imageMaxRatio, maxRatio);\n    }\n    return maxRatio;\n  }\n  function getScaleOrigin() {\n    if (evCache.length < 2) return {\n      x: null,\n      y: null\n    };\n    const box = gesture.imageEl.getBoundingClientRect();\n    return [(evCache[0].pageX + (evCache[1].pageX - evCache[0].pageX) / 2 - box.x - window.scrollX) / currentScale, (evCache[0].pageY + (evCache[1].pageY - evCache[0].pageY) / 2 - box.y - window.scrollY) / currentScale];\n  }\n  function getSlideSelector() {\n    return swiper.isElement ? `swiper-slide` : `.${swiper.params.slideClass}`;\n  }\n  function eventWithinSlide(e) {\n    const slideSelector = getSlideSelector();\n    if (e.target.matches(slideSelector)) return true;\n    if (swiper.slides.filter(slideEl => slideEl.contains(e.target)).length > 0) return true;\n    return false;\n  }\n  function eventWithinZoomContainer(e) {\n    const selector = `.${swiper.params.zoom.containerClass}`;\n    if (e.target.matches(selector)) return true;\n    if ([...swiper.hostEl.querySelectorAll(selector)].filter(containerEl => containerEl.contains(e.target)).length > 0) return true;\n    return false;\n  }\n\n  // Events\n  function onGestureStart(e) {\n    if (e.pointerType === 'mouse') {\n      evCache.splice(0, evCache.length);\n    }\n    if (!eventWithinSlide(e)) return;\n    const params = swiper.params.zoom;\n    fakeGestureTouched = false;\n    fakeGestureMoved = false;\n    evCache.push(e);\n    if (evCache.length < 2) {\n      return;\n    }\n    fakeGestureTouched = true;\n    gesture.scaleStart = getDistanceBetweenTouches();\n    if (!gesture.slideEl) {\n      gesture.slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`);\n      if (!gesture.slideEl) gesture.slideEl = swiper.slides[swiper.activeIndex];\n      let imageEl = gesture.slideEl.querySelector(`.${params.containerClass}`);\n      if (imageEl) {\n        imageEl = imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0];\n      }\n      gesture.imageEl = imageEl;\n      if (imageEl) {\n        gesture.imageWrapEl = elementParents(gesture.imageEl, `.${params.containerClass}`)[0];\n      } else {\n        gesture.imageWrapEl = undefined;\n      }\n      if (!gesture.imageWrapEl) {\n        gesture.imageEl = undefined;\n        return;\n      }\n      gesture.maxRatio = getMaxRatio();\n    }\n    if (gesture.imageEl) {\n      const [originX, originY] = getScaleOrigin();\n      gesture.originX = originX;\n      gesture.originY = originY;\n      gesture.imageEl.style.transitionDuration = '0ms';\n    }\n    isScaling = true;\n  }\n  function onGestureChange(e) {\n    if (!eventWithinSlide(e)) return;\n    const params = swiper.params.zoom;\n    const zoom = swiper.zoom;\n    const pointerIndex = evCache.findIndex(cachedEv => cachedEv.pointerId === e.pointerId);\n    if (pointerIndex >= 0) evCache[pointerIndex] = e;\n    if (evCache.length < 2) {\n      return;\n    }\n    fakeGestureMoved = true;\n    gesture.scaleMove = getDistanceBetweenTouches();\n    if (!gesture.imageEl) {\n      return;\n    }\n    zoom.scale = gesture.scaleMove / gesture.scaleStart * currentScale;\n    if (zoom.scale > gesture.maxRatio) {\n      zoom.scale = gesture.maxRatio - 1 + (zoom.scale - gesture.maxRatio + 1) ** 0.5;\n    }\n    if (zoom.scale < params.minRatio) {\n      zoom.scale = params.minRatio + 1 - (params.minRatio - zoom.scale + 1) ** 0.5;\n    }\n    gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`;\n  }\n  function onGestureEnd(e) {\n    if (!eventWithinSlide(e)) return;\n    if (e.pointerType === 'mouse' && e.type === 'pointerout') return;\n    const params = swiper.params.zoom;\n    const zoom = swiper.zoom;\n    const pointerIndex = evCache.findIndex(cachedEv => cachedEv.pointerId === e.pointerId);\n    if (pointerIndex >= 0) evCache.splice(pointerIndex, 1);\n    if (!fakeGestureTouched || !fakeGestureMoved) {\n      return;\n    }\n    fakeGestureTouched = false;\n    fakeGestureMoved = false;\n    if (!gesture.imageEl) return;\n    zoom.scale = Math.max(Math.min(zoom.scale, gesture.maxRatio), params.minRatio);\n    gesture.imageEl.style.transitionDuration = `${swiper.params.speed}ms`;\n    gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`;\n    currentScale = zoom.scale;\n    isScaling = false;\n    if (zoom.scale > 1 && gesture.slideEl) {\n      gesture.slideEl.classList.add(`${params.zoomedSlideClass}`);\n    } else if (zoom.scale <= 1 && gesture.slideEl) {\n      gesture.slideEl.classList.remove(`${params.zoomedSlideClass}`);\n    }\n    if (zoom.scale === 1) {\n      gesture.originX = 0;\n      gesture.originY = 0;\n      gesture.slideEl = undefined;\n    }\n  }\n  let allowTouchMoveTimeout;\n  function allowTouchMove() {\n    swiper.touchEventsData.preventTouchMoveFromPointerMove = false;\n  }\n  function preventTouchMove() {\n    clearTimeout(allowTouchMoveTimeout);\n    swiper.touchEventsData.preventTouchMoveFromPointerMove = true;\n    allowTouchMoveTimeout = setTimeout(() => {\n      if (swiper.destroyed) return;\n      allowTouchMove();\n    });\n  }\n  function onTouchStart(e) {\n    const device = swiper.device;\n    if (!gesture.imageEl) return;\n    if (image.isTouched) return;\n    if (device.android && e.cancelable) e.preventDefault();\n    image.isTouched = true;\n    const event = evCache.length > 0 ? evCache[0] : e;\n    image.touchesStart.x = event.pageX;\n    image.touchesStart.y = event.pageY;\n  }\n  function onTouchMove(e) {\n    const isMouseEvent = e.pointerType === 'mouse';\n    const isMousePan = isMouseEvent && swiper.params.zoom.panOnMouseMove;\n    if (!eventWithinSlide(e) || !eventWithinZoomContainer(e)) {\n      return;\n    }\n    const zoom = swiper.zoom;\n    if (!gesture.imageEl) {\n      return;\n    }\n    if (!image.isTouched || !gesture.slideEl) {\n      if (isMousePan) onMouseMove(e);\n      return;\n    }\n    if (isMousePan) {\n      onMouseMove(e);\n      return;\n    }\n    if (!image.isMoved) {\n      image.width = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth;\n      image.height = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight;\n      image.startX = getTranslate(gesture.imageWrapEl, 'x') || 0;\n      image.startY = getTranslate(gesture.imageWrapEl, 'y') || 0;\n      gesture.slideWidth = gesture.slideEl.offsetWidth;\n      gesture.slideHeight = gesture.slideEl.offsetHeight;\n      gesture.imageWrapEl.style.transitionDuration = '0ms';\n    }\n    // Define if we need image drag\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.touchesCurrent.x = evCache.length > 0 ? evCache[0].pageX : e.pageX;\n    image.touchesCurrent.y = evCache.length > 0 ? evCache[0].pageY : e.pageY;\n    const touchesDiff = Math.max(Math.abs(image.touchesCurrent.x - image.touchesStart.x), Math.abs(image.touchesCurrent.y - image.touchesStart.y));\n    if (touchesDiff > 5) {\n      swiper.allowClick = false;\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        allowTouchMove();\n        return;\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        allowTouchMove();\n        return;\n      }\n    }\n    if (e.cancelable) {\n      e.preventDefault();\n    }\n    e.stopPropagation();\n    preventTouchMove();\n    image.isMoved = true;\n    const scaleRatio = (zoom.scale - currentScale) / (gesture.maxRatio - swiper.params.zoom.minRatio);\n    const {\n      originX,\n      originY\n    } = gesture;\n    image.currentX = image.touchesCurrent.x - image.touchesStart.x + image.startX + scaleRatio * (image.width - originX * 2);\n    image.currentY = image.touchesCurrent.y - image.touchesStart.y + image.startY + scaleRatio * (image.height - originY * 2);\n    if (image.currentX < image.minX) {\n      image.currentX = image.minX + 1 - (image.minX - image.currentX + 1) ** 0.8;\n    }\n    if (image.currentX > image.maxX) {\n      image.currentX = image.maxX - 1 + (image.currentX - image.maxX + 1) ** 0.8;\n    }\n    if (image.currentY < image.minY) {\n      image.currentY = image.minY + 1 - (image.minY - image.currentY + 1) ** 0.8;\n    }\n    if (image.currentY > image.maxY) {\n      image.currentY = image.maxY - 1 + (image.currentY - image.maxY + 1) ** 0.8;\n    }\n\n    // Velocity\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.style.transform = `translate3d(${image.currentX}px, ${image.currentY}px,0)`;\n  }\n  function onTouchEnd() {\n    const zoom = swiper.zoom;\n    evCache.length = 0;\n    if (!gesture.imageEl) return;\n    if (!image.isTouched || !image.isMoved) {\n      image.isTouched = false;\n      image.isMoved = false;\n      return;\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;\n\n    // Fix duration\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;\n    // Define if we need image drag\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.style.transitionDuration = `${momentumDuration}ms`;\n    gesture.imageWrapEl.style.transform = `translate3d(${image.currentX}px, ${image.currentY}px,0)`;\n  }\n  function onTransitionEnd() {\n    const zoom = swiper.zoom;\n    if (gesture.slideEl && swiper.activeIndex !== swiper.slides.indexOf(gesture.slideEl)) {\n      if (gesture.imageEl) {\n        gesture.imageEl.style.transform = 'translate3d(0,0,0) scale(1)';\n      }\n      if (gesture.imageWrapEl) {\n        gesture.imageWrapEl.style.transform = 'translate3d(0,0,0)';\n      }\n      gesture.slideEl.classList.remove(`${swiper.params.zoom.zoomedSlideClass}`);\n      zoom.scale = 1;\n      currentScale = 1;\n      gesture.slideEl = undefined;\n      gesture.imageEl = undefined;\n      gesture.imageWrapEl = undefined;\n      gesture.originX = 0;\n      gesture.originY = 0;\n    }\n  }\n  function onMouseMove(e) {\n    // Only pan if zoomed in and mouse panning is enabled\n    if (currentScale <= 1 || !gesture.imageWrapEl) return;\n    if (!eventWithinSlide(e) || !eventWithinZoomContainer(e)) return;\n    const currentTransform = window.getComputedStyle(gesture.imageWrapEl).transform;\n    const matrix = new window.DOMMatrix(currentTransform);\n    if (!isPanningWithMouse) {\n      isPanningWithMouse = true;\n      mousePanStart.x = e.clientX;\n      mousePanStart.y = e.clientY;\n      image.startX = matrix.e;\n      image.startY = matrix.f;\n      image.width = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth;\n      image.height = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight;\n      gesture.slideWidth = gesture.slideEl.offsetWidth;\n      gesture.slideHeight = gesture.slideEl.offsetHeight;\n      return;\n    }\n    const deltaX = (e.clientX - mousePanStart.x) * mousePanSensitivity;\n    const deltaY = (e.clientY - mousePanStart.y) * mousePanSensitivity;\n    const scaledWidth = image.width * currentScale;\n    const scaledHeight = image.height * currentScale;\n    const slideWidth = gesture.slideWidth;\n    const slideHeight = gesture.slideHeight;\n    const minX = Math.min(slideWidth / 2 - scaledWidth / 2, 0);\n    const maxX = -minX;\n    const minY = Math.min(slideHeight / 2 - scaledHeight / 2, 0);\n    const maxY = -minY;\n    const newX = Math.max(Math.min(image.startX + deltaX, maxX), minX);\n    const newY = Math.max(Math.min(image.startY + deltaY, maxY), minY);\n    gesture.imageWrapEl.style.transitionDuration = '0ms';\n    gesture.imageWrapEl.style.transform = `translate3d(${newX}px, ${newY}px, 0)`;\n    mousePanStart.x = e.clientX;\n    mousePanStart.y = e.clientY;\n    image.startX = newX;\n    image.startY = newY;\n    image.currentX = newX;\n    image.currentY = newY;\n  }\n  function zoomIn(e) {\n    const zoom = swiper.zoom;\n    const params = swiper.params.zoom;\n    if (!gesture.slideEl) {\n      if (e && e.target) {\n        gesture.slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`);\n      }\n      if (!gesture.slideEl) {\n        if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) {\n          gesture.slideEl = elementChildren(swiper.slidesEl, `.${swiper.params.slideActiveClass}`)[0];\n        } else {\n          gesture.slideEl = swiper.slides[swiper.activeIndex];\n        }\n      }\n      let imageEl = gesture.slideEl.querySelector(`.${params.containerClass}`);\n      if (imageEl) {\n        imageEl = imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0];\n      }\n      gesture.imageEl = imageEl;\n      if (imageEl) {\n        gesture.imageWrapEl = elementParents(gesture.imageEl, `.${params.containerClass}`)[0];\n      } else {\n        gesture.imageWrapEl = undefined;\n      }\n    }\n    if (!gesture.imageEl || !gesture.imageWrapEl) return;\n    gesture.maxRatio = getMaxRatio();\n    if (swiper.params.cssMode) {\n      swiper.wrapperEl.style.overflow = 'hidden';\n      swiper.wrapperEl.style.touchAction = 'none';\n    }\n    gesture.slideEl.classList.add(`${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    if (typeof image.touchesStart.x === 'undefined' && e) {\n      touchX = e.pageX;\n      touchY = e.pageY;\n    } else {\n      touchX = image.touchesStart.x;\n      touchY = image.touchesStart.y;\n    }\n    const prevScale = currentScale;\n    const forceZoomRatio = typeof e === 'number' ? e : null;\n    if (currentScale === 1 && forceZoomRatio) {\n      touchX = undefined;\n      touchY = undefined;\n      image.touchesStart.x = undefined;\n      image.touchesStart.y = undefined;\n    }\n    const maxRatio = getMaxRatio();\n    zoom.scale = forceZoomRatio || maxRatio;\n    currentScale = forceZoomRatio || maxRatio;\n    if (e && !(currentScale === 1 && forceZoomRatio)) {\n      slideWidth = gesture.slideEl.offsetWidth;\n      slideHeight = gesture.slideEl.offsetHeight;\n      offsetX = elementOffset(gesture.slideEl).left + window.scrollX;\n      offsetY = elementOffset(gesture.slideEl).top + window.scrollY;\n      diffX = offsetX + slideWidth / 2 - touchX;\n      diffY = offsetY + slideHeight / 2 - touchY;\n      imageWidth = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth;\n      imageHeight = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight;\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      if (prevScale > 0 && forceZoomRatio && typeof image.currentX === 'number' && typeof image.currentY === 'number') {\n        translateX = image.currentX * zoom.scale / prevScale;\n        translateY = image.currentY * zoom.scale / prevScale;\n      } else {\n        translateX = diffX * zoom.scale;\n        translateY = diffY * zoom.scale;\n      }\n      if (translateX < translateMinX) {\n        translateX = translateMinX;\n      }\n      if (translateX > translateMaxX) {\n        translateX = translateMaxX;\n      }\n      if (translateY < translateMinY) {\n        translateY = translateMinY;\n      }\n      if (translateY > translateMaxY) {\n        translateY = translateMaxY;\n      }\n    } else {\n      translateX = 0;\n      translateY = 0;\n    }\n    if (forceZoomRatio && zoom.scale === 1) {\n      gesture.originX = 0;\n      gesture.originY = 0;\n    }\n    image.currentX = translateX;\n    image.currentY = translateY;\n    gesture.imageWrapEl.style.transitionDuration = '300ms';\n    gesture.imageWrapEl.style.transform = `translate3d(${translateX}px, ${translateY}px,0)`;\n    gesture.imageEl.style.transitionDuration = '300ms';\n    gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`;\n  }\n  function zoomOut() {\n    const zoom = swiper.zoom;\n    const params = swiper.params.zoom;\n    if (!gesture.slideEl) {\n      if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) {\n        gesture.slideEl = elementChildren(swiper.slidesEl, `.${swiper.params.slideActiveClass}`)[0];\n      } else {\n        gesture.slideEl = swiper.slides[swiper.activeIndex];\n      }\n      let imageEl = gesture.slideEl.querySelector(`.${params.containerClass}`);\n      if (imageEl) {\n        imageEl = imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0];\n      }\n      gesture.imageEl = imageEl;\n      if (imageEl) {\n        gesture.imageWrapEl = elementParents(gesture.imageEl, `.${params.containerClass}`)[0];\n      } else {\n        gesture.imageWrapEl = undefined;\n      }\n    }\n    if (!gesture.imageEl || !gesture.imageWrapEl) return;\n    gesture.maxRatio = getMaxRatio();\n    if (swiper.params.cssMode) {\n      swiper.wrapperEl.style.overflow = '';\n      swiper.wrapperEl.style.touchAction = '';\n    }\n    zoom.scale = 1;\n    currentScale = 1;\n    image.currentX = undefined;\n    image.currentY = undefined;\n    image.touchesStart.x = undefined;\n    image.touchesStart.y = undefined;\n    gesture.imageWrapEl.style.transitionDuration = '300ms';\n    gesture.imageWrapEl.style.transform = 'translate3d(0,0,0)';\n    gesture.imageEl.style.transitionDuration = '300ms';\n    gesture.imageEl.style.transform = 'translate3d(0,0,0) scale(1)';\n    gesture.slideEl.classList.remove(`${params.zoomedSlideClass}`);\n    gesture.slideEl = undefined;\n    gesture.originX = 0;\n    gesture.originY = 0;\n    if (swiper.params.zoom.panOnMouseMove) {\n      mousePanStart = {\n        x: 0,\n        y: 0\n      };\n      if (isPanningWithMouse) {\n        isPanningWithMouse = false;\n        image.startX = 0;\n        image.startY = 0;\n      }\n    }\n  }\n\n  // Toggle Zoom\n  function zoomToggle(e) {\n    const zoom = swiper.zoom;\n    if (zoom.scale && zoom.scale !== 1) {\n      // Zoom Out\n      zoomOut();\n    } else {\n      // Zoom In\n      zoomIn(e);\n    }\n  }\n  function getListeners() {\n    const passiveListener = swiper.params.passiveListeners ? {\n      passive: true,\n      capture: false\n    } : false;\n    const activeListenerWithCapture = swiper.params.passiveListeners ? {\n      passive: false,\n      capture: true\n    } : true;\n    return {\n      passiveListener,\n      activeListenerWithCapture\n    };\n  }\n\n  // Attach/Detach Events\n  function enable() {\n    const zoom = swiper.zoom;\n    if (zoom.enabled) return;\n    zoom.enabled = true;\n    const {\n      passiveListener,\n      activeListenerWithCapture\n    } = getListeners();\n\n    // Scale image\n    swiper.wrapperEl.addEventListener('pointerdown', onGestureStart, passiveListener);\n    swiper.wrapperEl.addEventListener('pointermove', onGestureChange, activeListenerWithCapture);\n    ['pointerup', 'pointercancel', 'pointerout'].forEach(eventName => {\n      swiper.wrapperEl.addEventListener(eventName, onGestureEnd, passiveListener);\n    });\n\n    // Move image\n    swiper.wrapperEl.addEventListener('pointermove', onTouchMove, activeListenerWithCapture);\n  }\n  function disable() {\n    const zoom = swiper.zoom;\n    if (!zoom.enabled) return;\n    zoom.enabled = false;\n    const {\n      passiveListener,\n      activeListenerWithCapture\n    } = getListeners();\n\n    // Scale image\n    swiper.wrapperEl.removeEventListener('pointerdown', onGestureStart, passiveListener);\n    swiper.wrapperEl.removeEventListener('pointermove', onGestureChange, activeListenerWithCapture);\n    ['pointerup', 'pointercancel', 'pointerout'].forEach(eventName => {\n      swiper.wrapperEl.removeEventListener(eventName, onGestureEnd, passiveListener);\n    });\n\n    // Move image\n    swiper.wrapperEl.removeEventListener('pointermove', onTouchMove, activeListenerWithCapture);\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\nexport { Zoom as default };\n","import { g as getDocument } from '../shared/ssr-window.esm.mjs';\nimport { c as classesToSelector } from '../shared/classes-to-selector.mjs';\nimport { c as createElement, j as elementIndex, m as makeElementsArray, s as setInnerHTML } from '../shared/utils.mjs';\n\nfunction A11y({\n  swiper,\n  extendParams,\n  on\n}) {\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      containerRole: null,\n      itemRoleDescriptionMessage: null,\n      slideRole: 'group',\n      id: null,\n      scrollOnFocus: true,\n      wrapperLiveRegion: true\n    }\n  });\n  swiper.a11y = {\n    clicked: false\n  };\n  let liveRegion = null;\n  let preventFocusHandler;\n  let focusTargetSlideEl;\n  let visibilityChangedTimestamp = new Date().getTime();\n  function notify(message) {\n    const notification = liveRegion;\n    if (notification.length === 0) return;\n    setInnerHTML(notification, message);\n  }\n  function getRandomNumber(size = 16) {\n    const randomChar = () => Math.round(16 * Math.random()).toString(16);\n    return 'x'.repeat(size).replace(/x/g, randomChar);\n  }\n  function makeElFocusable(el) {\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      subEl.setAttribute('tabIndex', '0');\n    });\n  }\n  function makeElNotFocusable(el) {\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      subEl.setAttribute('tabIndex', '-1');\n    });\n  }\n  function addElRole(el, role) {\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      subEl.setAttribute('role', role);\n    });\n  }\n  function addElRoleDescription(el, description) {\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      subEl.setAttribute('aria-roledescription', description);\n    });\n  }\n  function addElLabel(el, label) {\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      subEl.setAttribute('aria-label', label);\n    });\n  }\n  function addElId(el, id) {\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      subEl.setAttribute('id', id);\n    });\n  }\n  function addElLive(el, live) {\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      subEl.setAttribute('aria-live', live);\n    });\n  }\n  function disableEl(el) {\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      subEl.setAttribute('aria-disabled', true);\n    });\n  }\n  function enableEl(el) {\n    el = makeElementsArray(el);\n    el.forEach(subEl => {\n      subEl.removeAttribute('aria-disabled');\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    if (swiper.pagination && swiper.pagination.el && (targetEl === swiper.pagination.el || swiper.pagination.el.contains(e.target))) {\n      if (!e.target.matches(classesToSelector(swiper.params.pagination.bulletClass))) return;\n    }\n    if (swiper.navigation && swiper.navigation.prevEl && swiper.navigation.nextEl) {\n      const prevEls = makeElementsArray(swiper.navigation.prevEl);\n      const nextEls = makeElementsArray(swiper.navigation.nextEl);\n      if (nextEls.includes(targetEl)) {\n        if (!(swiper.isEnd && !swiper.params.loop)) {\n          swiper.slideNext();\n        }\n        if (swiper.isEnd) {\n          notify(params.lastSlideMessage);\n        } else {\n          notify(params.nextSlideMessage);\n        }\n      }\n      if (prevEls.includes(targetEl)) {\n        if (!(swiper.isBeginning && !swiper.params.loop)) {\n          swiper.slidePrev();\n        }\n        if (swiper.isBeginning) {\n          notify(params.firstSlideMessage);\n        } else {\n          notify(params.prevSlideMessage);\n        }\n      }\n    }\n    if (swiper.pagination && targetEl.matches(classesToSelector(swiper.params.pagination.bulletClass))) {\n      targetEl.click();\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    if (prevEl) {\n      if (swiper.isBeginning) {\n        disableEl(prevEl);\n        makeElNotFocusable(prevEl);\n      } else {\n        enableEl(prevEl);\n        makeElFocusable(prevEl);\n      }\n    }\n    if (nextEl) {\n      if (swiper.isEnd) {\n        disableEl(nextEl);\n        makeElNotFocusable(nextEl);\n      } else {\n        enableEl(nextEl);\n        makeElFocusable(nextEl);\n      }\n    }\n  }\n  function hasPagination() {\n    return swiper.pagination && swiper.pagination.bullets && swiper.pagination.bullets.length;\n  }\n  function hasClickablePagination() {\n    return hasPagination() && swiper.params.pagination.clickable;\n  }\n  function updatePagination() {\n    const params = swiper.params.a11y;\n    if (!hasPagination()) return;\n    swiper.pagination.bullets.forEach(bulletEl => {\n      if (swiper.params.pagination.clickable) {\n        makeElFocusable(bulletEl);\n        if (!swiper.params.pagination.renderBullet) {\n          addElRole(bulletEl, 'button');\n          addElLabel(bulletEl, params.paginationBulletMessage.replace(/\\{\\{index\\}\\}/, elementIndex(bulletEl) + 1));\n        }\n      }\n      if (bulletEl.matches(classesToSelector(swiper.params.pagination.bulletActiveClass))) {\n        bulletEl.setAttribute('aria-current', 'true');\n      } else {\n        bulletEl.removeAttribute('aria-current');\n      }\n    });\n  }\n  const initNavEl = (el, wrapperId, message) => {\n    makeElFocusable(el);\n    if (el.tagName !== 'BUTTON') {\n      addElRole(el, 'button');\n      el.addEventListener('keydown', onEnterOrSpaceKey);\n    }\n    addElLabel(el, message);\n  };\n  const handlePointerDown = e => {\n    if (focusTargetSlideEl && focusTargetSlideEl !== e.target && !focusTargetSlideEl.contains(e.target)) {\n      preventFocusHandler = true;\n    }\n    swiper.a11y.clicked = true;\n  };\n  const handlePointerUp = () => {\n    preventFocusHandler = false;\n    requestAnimationFrame(() => {\n      requestAnimationFrame(() => {\n        if (!swiper.destroyed) {\n          swiper.a11y.clicked = false;\n        }\n      });\n    });\n  };\n  const onVisibilityChange = e => {\n    visibilityChangedTimestamp = new Date().getTime();\n  };\n  const handleFocus = e => {\n    if (swiper.a11y.clicked || !swiper.params.a11y.scrollOnFocus) return;\n    if (new Date().getTime() - visibilityChangedTimestamp < 100) return;\n    const slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`);\n    if (!slideEl || !swiper.slides.includes(slideEl)) return;\n    focusTargetSlideEl = slideEl;\n    const isVirtual = swiper.virtual && swiper.params.virtual.enabled;\n    const isActive = (isVirtual ? parseInt(slideEl.getAttribute('data-swiper-slide-index'), 10) : swiper.slides.indexOf(slideEl)) === swiper.activeIndex;\n    const isVisible = swiper.params.watchSlidesProgress && swiper.visibleSlides && swiper.visibleSlides.includes(slideEl);\n    if (isActive || isVisible) return;\n    if (e.sourceCapabilities && e.sourceCapabilities.firesTouchEvents) return;\n    if (swiper.isHorizontal()) {\n      swiper.el.scrollLeft = 0;\n    } else {\n      swiper.el.scrollTop = 0;\n    }\n    requestAnimationFrame(() => {\n      if (preventFocusHandler) return;\n      if (swiper.params.loop) {\n        swiper.slideToLoop(swiper.getSlideIndexWhenGrid(parseInt(slideEl.getAttribute('data-swiper-slide-index'))), 0);\n      } else if (isVirtual) {\n        swiper.slideTo(swiper.getSlideIndexWhenGrid(parseInt(slideEl.getAttribute('data-swiper-slide-index'), 10)), 0);\n      } else {\n        swiper.slideTo(swiper.getSlideIndexWhenGrid(swiper.slides.indexOf(slideEl)), 0);\n      }\n      preventFocusHandler = false;\n    });\n  };\n  const initSlides = () => {\n    const params = swiper.params.a11y;\n    if (params.itemRoleDescriptionMessage) {\n      addElRoleDescription(swiper.slides, params.itemRoleDescriptionMessage);\n    }\n    if (params.slideRole) {\n      addElRole(swiper.slides, params.slideRole);\n    }\n    const slidesLength = swiper.slides.length;\n    if (params.slideLabelMessage) {\n      swiper.slides.forEach((slideEl, index) => {\n        const slideIndex = swiper.params.loop ? parseInt(slideEl.getAttribute('data-swiper-slide-index'), 10) : index;\n        const ariaLabelMessage = params.slideLabelMessage.replace(/\\{\\{index\\}\\}/, slideIndex + 1).replace(/\\{\\{slidesLength\\}\\}/, slidesLength);\n        addElLabel(slideEl, ariaLabelMessage);\n      });\n    }\n  };\n  const init = () => {\n    const params = swiper.params.a11y;\n    swiper.el.append(liveRegion);\n\n    // Container\n    const containerEl = swiper.el;\n    if (params.containerRoleDescriptionMessage) {\n      addElRoleDescription(containerEl, params.containerRoleDescriptionMessage);\n    }\n    if (params.containerMessage) {\n      addElLabel(containerEl, params.containerMessage);\n    }\n    if (params.containerRole) {\n      addElRole(containerEl, params.containerRole);\n    }\n\n    // Wrapper\n    const wrapperEl = swiper.wrapperEl;\n    const wrapperId = params.id || wrapperEl.getAttribute('id') || `swiper-wrapper-${getRandomNumber(16)}`;\n    addElId(wrapperEl, wrapperId);\n    if (params.wrapperLiveRegion) {\n      const live = swiper.params.autoplay && swiper.params.autoplay.enabled ? 'off' : 'polite';\n      addElLive(wrapperEl, live);\n    }\n\n    // Slide\n    initSlides();\n\n    // Navigation\n    let {\n      nextEl,\n      prevEl\n    } = swiper.navigation ? swiper.navigation : {};\n    nextEl = makeElementsArray(nextEl);\n    prevEl = makeElementsArray(prevEl);\n    if (nextEl) {\n      nextEl.forEach(el => initNavEl(el, wrapperId, params.nextSlideMessage));\n    }\n    if (prevEl) {\n      prevEl.forEach(el => initNavEl(el, wrapperId, params.prevSlideMessage));\n    }\n\n    // Pagination\n    if (hasClickablePagination()) {\n      const paginationEl = makeElementsArray(swiper.pagination.el);\n      paginationEl.forEach(el => {\n        el.addEventListener('keydown', onEnterOrSpaceKey);\n      });\n    }\n\n    // Tab focus\n    const document = getDocument();\n    document.addEventListener('visibilitychange', onVisibilityChange);\n    swiper.el.addEventListener('focus', handleFocus, true);\n    swiper.el.addEventListener('pointerdown', handlePointerDown, true);\n    swiper.el.addEventListener('pointerup', handlePointerUp, true);\n  };\n  function destroy() {\n    if (liveRegion) liveRegion.remove();\n    let {\n      nextEl,\n      prevEl\n    } = swiper.navigation ? swiper.navigation : {};\n    nextEl = makeElementsArray(nextEl);\n    prevEl = makeElementsArray(prevEl);\n    if (nextEl) {\n      nextEl.forEach(el => el.removeEventListener('keydown', onEnterOrSpaceKey));\n    }\n    if (prevEl) {\n      prevEl.forEach(el => el.removeEventListener('keydown', onEnterOrSpaceKey));\n    }\n\n    // Pagination\n    if (hasClickablePagination()) {\n      const paginationEl = makeElementsArray(swiper.pagination.el);\n      paginationEl.forEach(el => {\n        el.removeEventListener('keydown', onEnterOrSpaceKey);\n      });\n    }\n    const document = getDocument();\n    document.removeEventListener('visibilitychange', onVisibilityChange);\n    // Tab focus\n    if (swiper.el && typeof swiper.el !== 'string') {\n      swiper.el.removeEventListener('focus', handleFocus, true);\n      swiper.el.removeEventListener('pointerdown', handlePointerDown, true);\n      swiper.el.removeEventListener('pointerup', handlePointerUp, true);\n    }\n  }\n  on('beforeInit', () => {\n    liveRegion = createElement('span', swiper.params.a11y.notificationClass);\n    liveRegion.setAttribute('aria-live', 'assertive');\n    liveRegion.setAttribute('aria-atomic', 'true');\n  });\n  on('afterInit', () => {\n    if (!swiper.params.a11y.enabled) return;\n    init();\n  });\n  on('slidesLengthChange snapGridLengthChange slidesGridLengthChange', () => {\n    if (!swiper.params.a11y.enabled) return;\n    initSlides();\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\nexport { A11y as default };\n","import { g as getDocument } from '../shared/ssr-window.esm.mjs';\n\n/* eslint no-underscore-dangle: \"off\" */\n/* eslint no-use-before-define: \"off\" */\nfunction Autoplay({\n  swiper,\n  extendParams,\n  on,\n  emit,\n  params\n}) {\n  swiper.autoplay = {\n    running: false,\n    paused: false,\n    timeLeft: 0\n  };\n  extendParams({\n    autoplay: {\n      enabled: false,\n      delay: 3000,\n      waitForTransition: true,\n      disableOnInteraction: false,\n      stopOnLastSlide: false,\n      reverseDirection: false,\n      pauseOnMouseEnter: false\n    }\n  });\n  let timeout;\n  let raf;\n  let autoplayDelayTotal = params && params.autoplay ? params.autoplay.delay : 3000;\n  let autoplayDelayCurrent = params && params.autoplay ? params.autoplay.delay : 3000;\n  let autoplayTimeLeft;\n  let autoplayStartTime = new Date().getTime();\n  let wasPaused;\n  let isTouched;\n  let pausedByTouch;\n  let touchStartTimeout;\n  let pausedByInteraction;\n  let pausedByPointerEnter;\n  function onTransitionEnd(e) {\n    if (!swiper || swiper.destroyed || !swiper.wrapperEl) return;\n    if (e.target !== swiper.wrapperEl) return;\n    swiper.wrapperEl.removeEventListener('transitionend', onTransitionEnd);\n    if (pausedByPointerEnter || e.detail && e.detail.bySwiperTouchMove) {\n      return;\n    }\n    resume();\n  }\n  const calcTimeLeft = () => {\n    if (swiper.destroyed || !swiper.autoplay.running) return;\n    if (swiper.autoplay.paused) {\n      wasPaused = true;\n    } else if (wasPaused) {\n      autoplayDelayCurrent = autoplayTimeLeft;\n      wasPaused = false;\n    }\n    const timeLeft = swiper.autoplay.paused ? autoplayTimeLeft : autoplayStartTime + autoplayDelayCurrent - new Date().getTime();\n    swiper.autoplay.timeLeft = timeLeft;\n    emit('autoplayTimeLeft', timeLeft, timeLeft / autoplayDelayTotal);\n    raf = requestAnimationFrame(() => {\n      calcTimeLeft();\n    });\n  };\n  const getSlideDelay = () => {\n    let activeSlideEl;\n    if (swiper.virtual && swiper.params.virtual.enabled) {\n      activeSlideEl = swiper.slides.find(slideEl => slideEl.classList.contains('swiper-slide-active'));\n    } else {\n      activeSlideEl = swiper.slides[swiper.activeIndex];\n    }\n    if (!activeSlideEl) return undefined;\n    const currentSlideDelay = parseInt(activeSlideEl.getAttribute('data-swiper-autoplay'), 10);\n    return currentSlideDelay;\n  };\n  const getTotalDelay = () => {\n    let totalDelay = swiper.params.autoplay.delay;\n    const currentSlideDelay = getSlideDelay();\n    if (!Number.isNaN(currentSlideDelay) && currentSlideDelay > 0) {\n      totalDelay = currentSlideDelay;\n    }\n    return totalDelay;\n  };\n  const run = delayForce => {\n    if (swiper.destroyed || !swiper.autoplay.running) return;\n    cancelAnimationFrame(raf);\n    calcTimeLeft();\n    let delay = delayForce;\n    if (typeof delay === 'undefined') {\n      delay = getTotalDelay();\n      autoplayDelayTotal = delay;\n      autoplayDelayCurrent = delay;\n    }\n    autoplayTimeLeft = delay;\n    const speed = swiper.params.speed;\n    const proceed = () => {\n      if (!swiper || swiper.destroyed) return;\n      if (swiper.params.autoplay.reverseDirection) {\n        if (!swiper.isBeginning || swiper.params.loop || swiper.params.rewind) {\n          swiper.slidePrev(speed, true, true);\n          emit('autoplay');\n        } else if (!swiper.params.autoplay.stopOnLastSlide) {\n          swiper.slideTo(swiper.slides.length - 1, speed, true, true);\n          emit('autoplay');\n        }\n      } else {\n        if (!swiper.isEnd || swiper.params.loop || swiper.params.rewind) {\n          swiper.slideNext(speed, true, true);\n          emit('autoplay');\n        } else if (!swiper.params.autoplay.stopOnLastSlide) {\n          swiper.slideTo(0, speed, true, true);\n          emit('autoplay');\n        }\n      }\n      if (swiper.params.cssMode) {\n        autoplayStartTime = new Date().getTime();\n        requestAnimationFrame(() => {\n          run();\n        });\n      }\n    };\n    if (delay > 0) {\n      clearTimeout(timeout);\n      timeout = setTimeout(() => {\n        proceed();\n      }, delay);\n    } else {\n      requestAnimationFrame(() => {\n        proceed();\n      });\n    }\n\n    // eslint-disable-next-line\n    return delay;\n  };\n  const start = () => {\n    autoplayStartTime = new Date().getTime();\n    swiper.autoplay.running = true;\n    run();\n    emit('autoplayStart');\n  };\n  const stop = () => {\n    swiper.autoplay.running = false;\n    clearTimeout(timeout);\n    cancelAnimationFrame(raf);\n    emit('autoplayStop');\n  };\n  const pause = (internal, reset) => {\n    if (swiper.destroyed || !swiper.autoplay.running) return;\n    clearTimeout(timeout);\n    if (!internal) {\n      pausedByInteraction = true;\n    }\n    const proceed = () => {\n      emit('autoplayPause');\n      if (swiper.params.autoplay.waitForTransition) {\n        swiper.wrapperEl.addEventListener('transitionend', onTransitionEnd);\n      } else {\n        resume();\n      }\n    };\n    swiper.autoplay.paused = true;\n    if (reset) {\n      proceed();\n      return;\n    }\n    const delay = autoplayTimeLeft || swiper.params.autoplay.delay;\n    autoplayTimeLeft = delay - (new Date().getTime() - autoplayStartTime);\n    if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop) return;\n    if (autoplayTimeLeft < 0) autoplayTimeLeft = 0;\n    proceed();\n  };\n  const resume = () => {\n    if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop || swiper.destroyed || !swiper.autoplay.running) return;\n    autoplayStartTime = new Date().getTime();\n    if (pausedByInteraction) {\n      pausedByInteraction = false;\n      run(autoplayTimeLeft);\n    } else {\n      run();\n    }\n    swiper.autoplay.paused = false;\n    emit('autoplayResume');\n  };\n  const onVisibilityChange = () => {\n    if (swiper.destroyed || !swiper.autoplay.running) return;\n    const document = getDocument();\n    if (document.visibilityState === 'hidden') {\n      pausedByInteraction = true;\n      pause(true);\n    }\n    if (document.visibilityState === 'visible') {\n      resume();\n    }\n  };\n  const onPointerEnter = e => {\n    if (e.pointerType !== 'mouse') return;\n    pausedByInteraction = true;\n    pausedByPointerEnter = true;\n    if (swiper.animating || swiper.autoplay.paused) return;\n    pause(true);\n  };\n  const onPointerLeave = e => {\n    if (e.pointerType !== 'mouse') return;\n    pausedByPointerEnter = false;\n    if (swiper.autoplay.paused) {\n      resume();\n    }\n  };\n  const attachMouseEvents = () => {\n    if (swiper.params.autoplay.pauseOnMouseEnter) {\n      swiper.el.addEventListener('pointerenter', onPointerEnter);\n      swiper.el.addEventListener('pointerleave', onPointerLeave);\n    }\n  };\n  const detachMouseEvents = () => {\n    if (swiper.el && typeof swiper.el !== 'string') {\n      swiper.el.removeEventListener('pointerenter', onPointerEnter);\n      swiper.el.removeEventListener('pointerleave', onPointerLeave);\n    }\n  };\n  const attachDocumentEvents = () => {\n    const document = getDocument();\n    document.addEventListener('visibilitychange', onVisibilityChange);\n  };\n  const detachDocumentEvents = () => {\n    const document = getDocument();\n    document.removeEventListener('visibilitychange', onVisibilityChange);\n  };\n  on('init', () => {\n    if (swiper.params.autoplay.enabled) {\n      attachMouseEvents();\n      attachDocumentEvents();\n      start();\n    }\n  });\n  on('destroy', () => {\n    detachMouseEvents();\n    detachDocumentEvents();\n    if (swiper.autoplay.running) {\n      stop();\n    }\n  });\n  on('_freeModeStaticRelease', () => {\n    if (pausedByTouch || pausedByInteraction) {\n      resume();\n    }\n  });\n  on('_freeModeNoMomentumRelease', () => {\n    if (!swiper.params.autoplay.disableOnInteraction) {\n      pause(true, true);\n    } else {\n      stop();\n    }\n  });\n  on('beforeTransitionStart', (_s, speed, internal) => {\n    if (swiper.destroyed || !swiper.autoplay.running) return;\n    if (internal || !swiper.params.autoplay.disableOnInteraction) {\n      pause(true, true);\n    } else {\n      stop();\n    }\n  });\n  on('sliderFirstMove', () => {\n    if (swiper.destroyed || !swiper.autoplay.running) return;\n    if (swiper.params.autoplay.disableOnInteraction) {\n      stop();\n      return;\n    }\n    isTouched = true;\n    pausedByTouch = false;\n    pausedByInteraction = false;\n    touchStartTimeout = setTimeout(() => {\n      pausedByInteraction = true;\n      pausedByTouch = true;\n      pause(true);\n    }, 200);\n  });\n  on('touchEnd', () => {\n    if (swiper.destroyed || !swiper.autoplay.running || !isTouched) return;\n    clearTimeout(touchStartTimeout);\n    clearTimeout(timeout);\n    if (swiper.params.autoplay.disableOnInteraction) {\n      pausedByTouch = false;\n      isTouched = false;\n      return;\n    }\n    if (pausedByTouch && swiper.params.cssMode) resume();\n    pausedByTouch = false;\n    isTouched = false;\n  });\n  on('slideChange', () => {\n    if (swiper.destroyed || !swiper.autoplay.running) return;\n    if (swiper.autoplay.paused) {\n      autoplayTimeLeft = getTotalDelay();\n      autoplayDelayTotal = getTotalDelay();\n    }\n  });\n  Object.assign(swiper.autoplay, {\n    start,\n    stop,\n    pause,\n    resume\n  });\n}\n\nexport { Autoplay as default };\n","export function isDate(value) {\n  return value instanceof Date || Object.prototype.toString.call(value) === '[object Date]';\n}\nexport function toDate(value) {\n  if (isDate(value)) {\n    return new Date(value.getTime());\n  }\n\n  if (value == null) {\n    return new Date(NaN);\n  }\n\n  return new Date(value);\n}\nexport function isValidDate(value) {\n  return isDate(value) && !isNaN(value.getTime());\n}\nexport function startOfWeek(value) {\n  var firstDayOfWeek = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n\n  if (!(firstDayOfWeek >= 0 && firstDayOfWeek <= 6)) {\n    throw new RangeError('weekStartsOn must be between 0 and 6');\n  }\n\n  var date = toDate(value);\n  var day = date.getDay();\n  var diff = (day + 7 - firstDayOfWeek) % 7;\n  date.setDate(date.getDate() - diff);\n  date.setHours(0, 0, 0, 0);\n  return date;\n}\nexport function startOfWeekYear(value) {\n  var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n      _ref$firstDayOfWeek = _ref.firstDayOfWeek,\n      firstDayOfWeek = _ref$firstDayOfWeek === void 0 ? 0 : _ref$firstDayOfWeek,\n      _ref$firstWeekContain = _ref.firstWeekContainsDate,\n      firstWeekContainsDate = _ref$firstWeekContain === void 0 ? 1 : _ref$firstWeekContain;\n\n  if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {\n    throw new RangeError('firstWeekContainsDate must be between 1 and 7');\n  }\n\n  var date = toDate(value);\n  var year = date.getFullYear();\n  var firstDateOfFirstWeek = new Date(0);\n\n  for (var i = year + 1; i >= year - 1; i--) {\n    firstDateOfFirstWeek.setFullYear(i, 0, firstWeekContainsDate);\n    firstDateOfFirstWeek.setHours(0, 0, 0, 0);\n    firstDateOfFirstWeek = startOfWeek(firstDateOfFirstWeek, firstDayOfWeek);\n\n    if (date.getTime() >= firstDateOfFirstWeek.getTime()) {\n      break;\n    }\n  }\n\n  return firstDateOfFirstWeek;\n}\nexport function getWeek(value) {\n  var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n      _ref2$firstDayOfWeek = _ref2.firstDayOfWeek,\n      firstDayOfWeek = _ref2$firstDayOfWeek === void 0 ? 0 : _ref2$firstDayOfWeek,\n      _ref2$firstWeekContai = _ref2.firstWeekContainsDate,\n      firstWeekContainsDate = _ref2$firstWeekContai === void 0 ? 1 : _ref2$firstWeekContai;\n\n  var date = toDate(value);\n  var firstDateOfThisWeek = startOfWeek(date, firstDayOfWeek);\n  var firstDateOfFirstWeek = startOfWeekYear(date, {\n    firstDayOfWeek: firstDayOfWeek,\n    firstWeekContainsDate: firstWeekContainsDate\n  });\n  var diff = firstDateOfThisWeek.getTime() - firstDateOfFirstWeek.getTime();\n  return Math.round(diff / (7 * 24 * 3600 * 1000)) + 1;\n}","var locale = {\n  months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],\n  monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n  weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],\n  weekdaysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n  weekdaysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 1\n};\nexport default locale;","import { toDate, isValidDate, getWeek } from './util';\nimport defaultLocale from './locale/en';\nvar REGEX_FORMAT = /\\[([^\\]]+)]|YYYY|YY?|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|m{1,2}|s{1,2}|Z{1,2}|S{1,3}|w{1,2}|x|X|a|A/g;\n\nfunction pad(val) {\n  var len = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;\n  var output = \"\".concat(Math.abs(val));\n  var sign = val < 0 ? '-' : '';\n\n  while (output.length < len) {\n    output = \"0\".concat(output);\n  }\n\n  return sign + output;\n}\n\nfunction getOffset(date) {\n  return Math.round(date.getTimezoneOffset() / 15) * 15;\n}\n\nfunction formatTimezone(offset) {\n  var delimeter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';\n  var sign = offset > 0 ? '-' : '+';\n  var absOffset = Math.abs(offset);\n  var hours = Math.floor(absOffset / 60);\n  var minutes = absOffset % 60;\n  return sign + pad(hours, 2) + delimeter + pad(minutes, 2);\n}\n\nvar meridiem = function meridiem(h, _, isLowercase) {\n  var word = h < 12 ? 'AM' : 'PM';\n  return isLowercase ? word.toLocaleLowerCase() : word;\n};\n\nvar formatFlags = {\n  Y: function Y(date) {\n    var y = date.getFullYear();\n    return y <= 9999 ? \"\".concat(y) : \"+\".concat(y);\n  },\n  // Year: 00, 01, ..., 99\n  YY: function YY(date) {\n    return pad(date.getFullYear(), 4).substr(2);\n  },\n  // Year: 1900, 1901, ..., 2099\n  YYYY: function YYYY(date) {\n    return pad(date.getFullYear(), 4);\n  },\n  // Month: 1, 2, ..., 12\n  M: function M(date) {\n    return date.getMonth() + 1;\n  },\n  // Month: 01, 02, ..., 12\n  MM: function MM(date) {\n    return pad(date.getMonth() + 1, 2);\n  },\n  MMM: function MMM(date, locale) {\n    return locale.monthsShort[date.getMonth()];\n  },\n  MMMM: function MMMM(date, locale) {\n    return locale.months[date.getMonth()];\n  },\n  // Day of month: 1, 2, ..., 31\n  D: function D(date) {\n    return date.getDate();\n  },\n  // Day of month: 01, 02, ..., 31\n  DD: function DD(date) {\n    return pad(date.getDate(), 2);\n  },\n  // Hour: 0, 1, ... 23\n  H: function H(date) {\n    return date.getHours();\n  },\n  // Hour: 00, 01, ..., 23\n  HH: function HH(date) {\n    return pad(date.getHours(), 2);\n  },\n  // Hour: 1, 2, ..., 12\n  h: function h(date) {\n    var hours = date.getHours();\n\n    if (hours === 0) {\n      return 12;\n    }\n\n    if (hours > 12) {\n      return hours % 12;\n    }\n\n    return hours;\n  },\n  // Hour: 01, 02, ..., 12\n  hh: function hh() {\n    var hours = formatFlags.h.apply(formatFlags, arguments);\n    return pad(hours, 2);\n  },\n  // Minute: 0, 1, ..., 59\n  m: function m(date) {\n    return date.getMinutes();\n  },\n  // Minute: 00, 01, ..., 59\n  mm: function mm(date) {\n    return pad(date.getMinutes(), 2);\n  },\n  // Second: 0, 1, ..., 59\n  s: function s(date) {\n    return date.getSeconds();\n  },\n  // Second: 00, 01, ..., 59\n  ss: function ss(date) {\n    return pad(date.getSeconds(), 2);\n  },\n  // 1/10 of second: 0, 1, ..., 9\n  S: function S(date) {\n    return Math.floor(date.getMilliseconds() / 100);\n  },\n  // 1/100 of second: 00, 01, ..., 99\n  SS: function SS(date) {\n    return pad(Math.floor(date.getMilliseconds() / 10), 2);\n  },\n  // Millisecond: 000, 001, ..., 999\n  SSS: function SSS(date) {\n    return pad(date.getMilliseconds(), 3);\n  },\n  // Day of week: 0, 1, ..., 6\n  d: function d(date) {\n    return date.getDay();\n  },\n  // Day of week: 'Su', 'Mo', ..., 'Sa'\n  dd: function dd(date, locale) {\n    return locale.weekdaysMin[date.getDay()];\n  },\n  // Day of week: 'Sun', 'Mon',..., 'Sat'\n  ddd: function ddd(date, locale) {\n    return locale.weekdaysShort[date.getDay()];\n  },\n  // Day of week: 'Sunday', 'Monday', ...,'Saturday'\n  dddd: function dddd(date, locale) {\n    return locale.weekdays[date.getDay()];\n  },\n  // AM, PM\n  A: function A(date, locale) {\n    var meridiemFunc = locale.meridiem || meridiem;\n    return meridiemFunc(date.getHours(), date.getMinutes(), false);\n  },\n  // am, pm\n  a: function a(date, locale) {\n    var meridiemFunc = locale.meridiem || meridiem;\n    return meridiemFunc(date.getHours(), date.getMinutes(), true);\n  },\n  // Timezone: -01:00, +00:00, ... +12:00\n  Z: function Z(date) {\n    return formatTimezone(getOffset(date), ':');\n  },\n  // Timezone: -0100, +0000, ... +1200\n  ZZ: function ZZ(date) {\n    return formatTimezone(getOffset(date));\n  },\n  // Seconds timestamp: 512969520\n  X: function X(date) {\n    return Math.floor(date.getTime() / 1000);\n  },\n  // Milliseconds timestamp: 512969520900\n  x: function x(date) {\n    return date.getTime();\n  },\n  w: function w(date, locale) {\n    return getWeek(date, {\n      firstDayOfWeek: locale.firstDayOfWeek,\n      firstWeekContainsDate: locale.firstWeekContainsDate\n    });\n  },\n  ww: function ww(date, locale) {\n    return pad(formatFlags.w(date, locale), 2);\n  }\n};\nexport function format(val, str) {\n  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n  var formatStr = str ? String(str) : 'YYYY-MM-DDTHH:mm:ss.SSSZ';\n  var date = toDate(val);\n\n  if (!isValidDate(date)) {\n    return 'Invalid Date';\n  }\n\n  var locale = options.locale || defaultLocale;\n  return formatStr.replace(REGEX_FORMAT, function (match, p1) {\n    if (p1) {\n      return p1;\n    }\n\n    if (typeof formatFlags[match] === 'function') {\n      return \"\".concat(formatFlags[match](date, locale));\n    }\n\n    return match;\n  });\n}","function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\nfunction _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }\n\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === \"[object Arguments]\")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport defaultLocale from './locale/en';\nimport { startOfWeekYear } from './util';\nvar formattingTokens = /(\\[[^\\[]*\\])|(MM?M?M?|Do|DD?|ddd?d?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|S{1,3}|x|X|ZZ?|.)/g;\nvar match1 = /\\d/; // 0 - 9\n\nvar match2 = /\\d\\d/; // 00 - 99\n\nvar match3 = /\\d{3}/; // 000 - 999\n\nvar match4 = /\\d{4}/; // 0000 - 9999\n\nvar match1to2 = /\\d\\d?/; // 0 - 99\n\nvar matchShortOffset = /[+-]\\d\\d:?\\d\\d/; // +00:00 -00:00 +0000 or -0000\n\nvar matchSigned = /[+-]?\\d+/; // -inf - inf\n\nvar matchTimestamp = /[+-]?\\d+(\\.\\d{1,3})?/; // 123456789 123456789.123\n// const matchWord = /[0-9]{0,256}['a-z\\u00A0-\\u05FF\\u0700-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFF07\\uFF10-\\uFFEF]{1,256}|[\\u0600-\\u06FF\\/]{1,256}(\\s*?[\\u0600-\\u06FF]{1,256}){1,2}/i; // Word\n\nvar YEAR = 'year';\nvar MONTH = 'month';\nvar DAY = 'day';\nvar HOUR = 'hour';\nvar MINUTE = 'minute';\nvar SECOND = 'second';\nvar MILLISECOND = 'millisecond';\nvar parseFlags = {};\n\nvar addParseFlag = function addParseFlag(token, regex, callback) {\n  var tokens = Array.isArray(token) ? token : [token];\n  var func;\n\n  if (typeof callback === 'string') {\n    func = function func(input) {\n      var value = parseInt(input, 10);\n      return _defineProperty({}, callback, value);\n    };\n  } else {\n    func = callback;\n  }\n\n  tokens.forEach(function (key) {\n    parseFlags[key] = [regex, func];\n  });\n};\n\nvar escapeStringRegExp = function escapeStringRegExp(str) {\n  return str.replace(/[|\\\\{}()[\\]^$+*?.]/g, '\\\\$&');\n};\n\nvar matchWordRegExp = function matchWordRegExp(localeKey) {\n  return function (locale) {\n    var array = locale[localeKey];\n\n    if (!Array.isArray(array)) {\n      throw new Error(\"Locale[\".concat(localeKey, \"] need an array\"));\n    }\n\n    return new RegExp(array.map(escapeStringRegExp).join('|'));\n  };\n};\n\nvar matchWordCallback = function matchWordCallback(localeKey, key) {\n  return function (input, locale) {\n    var array = locale[localeKey];\n\n    if (!Array.isArray(array)) {\n      throw new Error(\"Locale[\".concat(localeKey, \"] need an array\"));\n    }\n\n    var index = array.indexOf(input);\n\n    if (index < 0) {\n      throw new Error('Invalid Word');\n    }\n\n    return _defineProperty({}, key, index);\n  };\n};\n\naddParseFlag('Y', matchSigned, YEAR);\naddParseFlag('YY', match2, function (input) {\n  var year = new Date().getFullYear();\n  var cent = Math.floor(year / 100);\n  var value = parseInt(input, 10);\n  value = (value > 68 ? cent - 1 : cent) * 100 + value;\n  return _defineProperty({}, YEAR, value);\n});\naddParseFlag('YYYY', match4, YEAR);\naddParseFlag('M', match1to2, function (input) {\n  return _defineProperty({}, MONTH, parseInt(input, 10) - 1);\n});\naddParseFlag('MM', match2, function (input) {\n  return _defineProperty({}, MONTH, parseInt(input, 10) - 1);\n});\naddParseFlag('MMM', matchWordRegExp('monthsShort'), matchWordCallback('monthsShort', MONTH));\naddParseFlag('MMMM', matchWordRegExp('months'), matchWordCallback('months', MONTH));\naddParseFlag('D', match1to2, DAY);\naddParseFlag('DD', match2, DAY);\naddParseFlag(['H', 'h'], match1to2, HOUR);\naddParseFlag(['HH', 'hh'], match2, HOUR);\naddParseFlag('m', match1to2, MINUTE);\naddParseFlag('mm', match2, MINUTE);\naddParseFlag('s', match1to2, SECOND);\naddParseFlag('ss', match2, SECOND);\naddParseFlag('S', match1, function (input) {\n  return _defineProperty({}, MILLISECOND, parseInt(input, 10) * 100);\n});\naddParseFlag('SS', match2, function (input) {\n  return _defineProperty({}, MILLISECOND, parseInt(input, 10) * 10);\n});\naddParseFlag('SSS', match3, MILLISECOND);\n\nfunction matchMeridiem(locale) {\n  return locale.meridiemParse || /[ap]\\.?m?\\.?/i;\n}\n\nfunction defaultIsPM(input) {\n  return \"\".concat(input).toLowerCase().charAt(0) === 'p';\n}\n\naddParseFlag(['A', 'a'], matchMeridiem, function (input, locale) {\n  var isPM = typeof locale.isPM === 'function' ? locale.isPM(input) : defaultIsPM(input);\n  return {\n    isPM: isPM\n  };\n});\n\nfunction offsetFromString(str) {\n  var _ref8 = str.match(/([+-]|\\d\\d)/g) || ['-', '0', '0'],\n      _ref9 = _slicedToArray(_ref8, 3),\n      symbol = _ref9[0],\n      hour = _ref9[1],\n      minute = _ref9[2];\n\n  var minutes = parseInt(hour, 10) * 60 + parseInt(minute, 10);\n\n  if (minutes === 0) {\n    return 0;\n  }\n\n  return symbol === '+' ? -minutes : +minutes;\n}\n\naddParseFlag(['Z', 'ZZ'], matchShortOffset, function (input) {\n  return {\n    offset: offsetFromString(input)\n  };\n});\naddParseFlag('x', matchSigned, function (input) {\n  return {\n    date: new Date(parseInt(input, 10))\n  };\n});\naddParseFlag('X', matchTimestamp, function (input) {\n  return {\n    date: new Date(parseFloat(input) * 1000)\n  };\n});\naddParseFlag('d', match1, 'weekday');\naddParseFlag('dd', matchWordRegExp('weekdaysMin'), matchWordCallback('weekdaysMin', 'weekday'));\naddParseFlag('ddd', matchWordRegExp('weekdaysShort'), matchWordCallback('weekdaysShort', 'weekday'));\naddParseFlag('dddd', matchWordRegExp('weekdays'), matchWordCallback('weekdays', 'weekday'));\naddParseFlag('w', match1to2, 'week');\naddParseFlag('ww', match2, 'week');\n\nfunction to24hour(hour, isPM) {\n  if (hour !== undefined && isPM !== undefined) {\n    if (isPM) {\n      if (hour < 12) {\n        return hour + 12;\n      }\n    } else if (hour === 12) {\n      return 0;\n    }\n  }\n\n  return hour;\n}\n\nfunction getFullInputArray(input) {\n  var backupDate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Date();\n  var result = [0, 0, 1, 0, 0, 0, 0];\n  var backupArr = [backupDate.getFullYear(), backupDate.getMonth(), backupDate.getDate(), backupDate.getHours(), backupDate.getMinutes(), backupDate.getSeconds(), backupDate.getMilliseconds()];\n  var useBackup = true;\n\n  for (var i = 0; i < 7; i++) {\n    if (input[i] === undefined) {\n      result[i] = useBackup ? backupArr[i] : result[i];\n    } else {\n      result[i] = input[i];\n      useBackup = false;\n    }\n  }\n\n  return result;\n}\n\nfunction createDate(y, m, d, h, M, s, ms) {\n  var date;\n\n  if (y < 100 && y >= 0) {\n    date = new Date(y + 400, m, d, h, M, s, ms);\n\n    if (isFinite(date.getFullYear())) {\n      date.setFullYear(y);\n    }\n  } else {\n    date = new Date(y, m, d, h, M, s, ms);\n  }\n\n  return date;\n}\n\nfunction createUTCDate() {\n  var date;\n\n  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n    args[_key] = arguments[_key];\n  }\n\n  var y = args[0];\n\n  if (y < 100 && y >= 0) {\n    args[0] += 400;\n    date = new Date(Date.UTC.apply(Date, args)); // eslint-disable-next-line no-restricted-globals\n\n    if (isFinite(date.getUTCFullYear())) {\n      date.setUTCFullYear(y);\n    }\n  } else {\n    date = new Date(Date.UTC.apply(Date, args));\n  }\n\n  return date;\n}\n\nfunction makeParser(dateString, format, locale) {\n  var tokens = format.match(formattingTokens);\n\n  if (!tokens) {\n    throw new Error();\n  }\n\n  var length = tokens.length;\n  var mark = {};\n\n  for (var i = 0; i < length; i += 1) {\n    var token = tokens[i];\n    var parseTo = parseFlags[token];\n\n    if (!parseTo) {\n      var word = token.replace(/^\\[|\\]$/g, '');\n\n      if (dateString.indexOf(word) === 0) {\n        dateString = dateString.substr(word.length);\n      } else {\n        throw new Error('not match');\n      }\n    } else {\n      var regex = typeof parseTo[0] === 'function' ? parseTo[0](locale) : parseTo[0];\n      var parser = parseTo[1];\n      var value = (regex.exec(dateString) || [])[0];\n      var obj = parser(value, locale);\n      mark = _objectSpread({}, mark, {}, obj);\n      dateString = dateString.replace(value, '');\n    }\n  }\n\n  return mark;\n}\n\nexport function parse(str, format) {\n  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n\n  try {\n    var _options$locale = options.locale,\n        _locale = _options$locale === void 0 ? defaultLocale : _options$locale,\n        _options$backupDate = options.backupDate,\n        backupDate = _options$backupDate === void 0 ? new Date() : _options$backupDate;\n\n    var parseResult = makeParser(str, format, _locale);\n    var year = parseResult.year,\n        month = parseResult.month,\n        day = parseResult.day,\n        hour = parseResult.hour,\n        minute = parseResult.minute,\n        second = parseResult.second,\n        millisecond = parseResult.millisecond,\n        isPM = parseResult.isPM,\n        date = parseResult.date,\n        offset = parseResult.offset,\n        weekday = parseResult.weekday,\n        week = parseResult.week;\n\n    if (date) {\n      return date;\n    }\n\n    var inputArray = [year, month, day, hour, minute, second, millisecond];\n    inputArray[3] = to24hour(inputArray[3], isPM); // check week\n\n    if (week !== undefined && month === undefined && day === undefined) {\n      // new Date(year, 3) make sure in current year\n      var firstDate = startOfWeekYear(year === undefined ? backupDate : new Date(year, 3), {\n        firstDayOfWeek: _locale.firstDayOfWeek,\n        firstWeekContainsDate: _locale.firstWeekContainsDate\n      });\n      return new Date(firstDate.getTime() + (week - 1) * 7 * 24 * 3600 * 1000);\n    }\n\n    var parsedDate;\n    var result = getFullInputArray(inputArray, backupDate);\n\n    if (offset !== undefined) {\n      result[6] += offset * 60 * 1000;\n      parsedDate = createUTCDate.apply(void 0, _toConsumableArray(result));\n    } else {\n      parsedDate = createDate.apply(void 0, _toConsumableArray(result));\n    } // check weekday\n\n\n    if (weekday !== undefined && parsedDate.getDay() !== weekday) {\n      return new Date(NaN);\n    }\n\n    return parsedDate;\n  } catch (e) {\n    return new Date(NaN);\n  }\n}","var __defProp = Object.defineProperty;\nvar __defProps = Object.defineProperties;\nvar __getOwnPropDescs = Object.getOwnPropertyDescriptors;\nvar __getOwnPropSymbols = Object.getOwnPropertySymbols;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __propIsEnum = Object.prototype.propertyIsEnumerable;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __spreadValues = (a, b) => {\n  for (var prop in b || (b = {}))\n    if (__hasOwnProp.call(b, prop))\n      __defNormalProp(a, prop, b[prop]);\n  if (__getOwnPropSymbols)\n    for (var prop of __getOwnPropSymbols(b)) {\n      if (__propIsEnum.call(b, prop))\n        __defNormalProp(a, prop, b[prop]);\n    }\n  return a;\n};\nvar __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));\nvar __objRest = (source, exclude) => {\n  var target = {};\n  for (var prop in source)\n    if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)\n      target[prop] = source[prop];\n  if (source != null && __getOwnPropSymbols)\n    for (var prop of __getOwnPropSymbols(source)) {\n      if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))\n        target[prop] = source[prop];\n    }\n  return target;\n};\nimport { inject, shallowRef, computed, provide, ref, watchEffect, createVNode, Teleport, Transition, openBlock, createElementBlock, createElementVNode, toRef, defineComponent, onMounted, onUnmounted, isVNode, watch, h } from \"vue\";\nimport { getWeek, format, parse } from \"date-format-parse\";\nimport en from \"date-format-parse/es/locale/en\";\nconst lang = {\n  formatLocale: en,\n  yearFormat: \"YYYY\",\n  monthFormat: \"MMM\",\n  monthBeforeYear: true\n};\nlet defaultLocale = \"en\";\nconst locales = {};\nlocales[defaultLocale] = lang;\nfunction locale(name, object, isLocal = false) {\n  if (typeof name !== \"string\")\n    return locales[defaultLocale];\n  let l = defaultLocale;\n  if (locales[name]) {\n    l = name;\n  }\n  if (object) {\n    locales[name] = object;\n    l = name;\n  }\n  if (!isLocal) {\n    defaultLocale = l;\n  }\n  return locales[name] || locales[defaultLocale];\n}\nfunction getLocale(name) {\n  return locale(name, void 0, true);\n}\nfunction chunk(arr, size) {\n  if (!Array.isArray(arr)) {\n    return [];\n  }\n  const result = [];\n  const len = arr.length;\n  let i = 0;\n  size = size || len;\n  while (i < len) {\n    result.push(arr.slice(i, i += size));\n  }\n  return result;\n}\nfunction last(array) {\n  return Array.isArray(array) ? array[array.length - 1] : void 0;\n}\nfunction isPlainObject(obj) {\n  return Object.prototype.toString.call(obj) === \"[object Object]\";\n}\nfunction pick(obj, props) {\n  const res = {};\n  if (!isPlainObject(obj))\n    return res;\n  if (!Array.isArray(props)) {\n    props = [props];\n  }\n  props.forEach((prop) => {\n    if (Object.prototype.hasOwnProperty.call(obj, prop)) {\n      res[prop] = obj[prop];\n    }\n  });\n  return res;\n}\nfunction mergeDeep(target, source) {\n  if (!isPlainObject(target)) {\n    return {};\n  }\n  let result = target;\n  if (isPlainObject(source)) {\n    Object.keys(source).forEach((key) => {\n      let value = source[key];\n      const targetValue = target[key];\n      if (isPlainObject(value) && isPlainObject(targetValue)) {\n        value = mergeDeep(targetValue, value);\n      }\n      result = __spreadProps(__spreadValues({}, result), { [key]: value });\n    });\n  }\n  return result;\n}\nfunction padNumber(value) {\n  const num = parseInt(String(value), 10);\n  return num < 10 ? `0${num}` : `${num}`;\n}\nfunction camelcase(str) {\n  const camelizeRE = /-(\\w)/g;\n  return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : \"\");\n}\nconst localeContextKey = \"datepicker_locale\";\nconst prefixClassKey = \"datepicker_prefixClass\";\nconst getWeekKey = \"datepicker_getWeek\";\nfunction useLocale() {\n  return inject(localeContextKey, shallowRef(getLocale()));\n}\nfunction provideLocale(lang2) {\n  const locale2 = computed(() => {\n    if (isPlainObject(lang2.value)) {\n      return mergeDeep(getLocale(), lang2.value);\n    }\n    return getLocale(lang2.value);\n  });\n  provide(localeContextKey, locale2);\n  return locale2;\n}\nfunction providePrefixClass(value) {\n  provide(prefixClassKey, value);\n}\nfunction usePrefixClass() {\n  return inject(prefixClassKey, \"mx\");\n}\nfunction provideGetWeek(value) {\n  provide(getWeekKey, value);\n}\nfunction useGetWeek() {\n  return inject(getWeekKey, getWeek);\n}\nfunction getPopupElementSize(element) {\n  const originalDisplay = element.style.display;\n  const originalVisibility = element.style.visibility;\n  element.style.display = \"block\";\n  element.style.visibility = \"hidden\";\n  const styles = window.getComputedStyle(element);\n  const width = element.offsetWidth + parseInt(styles.marginLeft, 10) + parseInt(styles.marginRight, 10);\n  const height = element.offsetHeight + parseInt(styles.marginTop, 10) + parseInt(styles.marginBottom, 10);\n  element.style.display = originalDisplay;\n  element.style.visibility = originalVisibility;\n  return { width, height };\n}\nfunction getRelativePosition(el, targetWidth, targetHeight, fixed) {\n  let left = 0;\n  let top = 0;\n  let offsetX = 0;\n  let offsetY = 0;\n  const relativeRect = el.getBoundingClientRect();\n  const dw = document.documentElement.clientWidth;\n  const dh = document.documentElement.clientHeight;\n  if (fixed) {\n    offsetX = window.pageXOffset + relativeRect.left;\n    offsetY = window.pageYOffset + relativeRect.top;\n  }\n  if (dw - relativeRect.left < targetWidth && relativeRect.right < targetWidth) {\n    left = offsetX - relativeRect.left + 1;\n  } else if (relativeRect.left + relativeRect.width / 2 <= dw / 2) {\n    left = offsetX;\n  } else {\n    left = offsetX + relativeRect.width - targetWidth;\n  }\n  if (relativeRect.top <= targetHeight && dh - relativeRect.bottom <= targetHeight) {\n    top = offsetY + dh - relativeRect.top - targetHeight;\n  } else if (relativeRect.top + relativeRect.height / 2 <= dh / 2) {\n    top = offsetY + relativeRect.height;\n  } else {\n    top = offsetY - targetHeight;\n  }\n  return { left: `${left}px`, top: `${top}px` };\n}\nfunction getScrollParent(node, until = document.body) {\n  if (!node || node === until) {\n    return null;\n  }\n  const style = (value, prop) => getComputedStyle(value, null).getPropertyValue(prop);\n  const regex = /(auto|scroll)/;\n  const scroll = regex.test(style(node, \"overflow\") + style(node, \"overflow-y\") + style(node, \"overflow-x\"));\n  return scroll ? node : getScrollParent(node.parentElement, until);\n}\nlet scrollBarWidth;\nfunction getScrollbarWidth() {\n  if (typeof window === \"undefined\")\n    return 0;\n  if (scrollBarWidth !== void 0)\n    return scrollBarWidth;\n  const outer = document.createElement(\"div\");\n  outer.style.visibility = \"hidden\";\n  outer.style.overflow = \"scroll\";\n  outer.style.width = \"100px\";\n  outer.style.position = \"absolute\";\n  outer.style.top = \"-9999px\";\n  document.body.appendChild(outer);\n  const inner = document.createElement(\"div\");\n  inner.style.width = \"100%\";\n  outer.appendChild(inner);\n  scrollBarWidth = outer.offsetWidth - inner.offsetWidth;\n  outer.parentNode.removeChild(outer);\n  return scrollBarWidth;\n}\nconst mousedownEvent = \"ontouchend\" in document ? \"touchstart\" : \"mousedown\";\nfunction rafThrottle(fn) {\n  let isRunning = false;\n  return function fnBinfRaf(...args) {\n    if (isRunning)\n      return;\n    isRunning = true;\n    requestAnimationFrame(() => {\n      isRunning = false;\n      fn.apply(this, args);\n    });\n  };\n}\nfunction defineVueComponent(setup, props) {\n  return { setup, name: setup.name, props };\n}\nfunction withDefault(props, defaultProps) {\n  const result = new Proxy(props, {\n    get(target, key) {\n      const value = target[key];\n      if (value !== void 0) {\n        return value;\n      }\n      return defaultProps[key];\n    }\n  });\n  return result;\n}\nconst keys = () => (props) => props;\nconst resolveProps = (obj, booleanKeys2) => {\n  const props = {};\n  for (const key in obj) {\n    if (Object.prototype.hasOwnProperty.call(obj, key)) {\n      const camelizeKey = camelcase(key);\n      let value = obj[key];\n      if (booleanKeys2.indexOf(camelizeKey) !== -1 && value === \"\") {\n        value = true;\n      }\n      props[camelizeKey] = value;\n    }\n  }\n  return props;\n};\nfunction Popup(originalProps, {\n  slots\n}) {\n  const props = withDefault(originalProps, {\n    appendToBody: true\n  });\n  const prefixClass = usePrefixClass();\n  const popup = ref(null);\n  const position = ref({\n    left: \"\",\n    top: \"\"\n  });\n  const displayPopup = () => {\n    if (!props.visible || !popup.value)\n      return;\n    const relativeElement = props.getRelativeElement();\n    if (!relativeElement)\n      return;\n    const {\n      width,\n      height\n    } = getPopupElementSize(popup.value);\n    position.value = getRelativePosition(relativeElement, width, height, props.appendToBody);\n  };\n  watchEffect(displayPopup, {\n    flush: \"post\"\n  });\n  watchEffect((onInvalidate) => {\n    const relativeElement = props.getRelativeElement();\n    if (!relativeElement)\n      return;\n    const scrollElement = getScrollParent(relativeElement) || window;\n    const handleMove = rafThrottle(displayPopup);\n    scrollElement.addEventListener(\"scroll\", handleMove);\n    window.addEventListener(\"resize\", handleMove);\n    onInvalidate(() => {\n      scrollElement.removeEventListener(\"scroll\", handleMove);\n      window.removeEventListener(\"resize\", handleMove);\n    });\n  }, {\n    flush: \"post\"\n  });\n  const handleClickOutside = (evt) => {\n    if (!props.visible)\n      return;\n    const target = evt.target;\n    const el = popup.value;\n    const relativeElement = props.getRelativeElement();\n    if (el && !el.contains(target) && relativeElement && !relativeElement.contains(target)) {\n      props.onClickOutside(evt);\n    }\n  };\n  watchEffect((onInvalidate) => {\n    document.addEventListener(mousedownEvent, handleClickOutside);\n    onInvalidate(() => {\n      document.removeEventListener(mousedownEvent, handleClickOutside);\n    });\n  });\n  return () => {\n    return createVNode(Teleport, {\n      \"to\": \"body\",\n      \"disabled\": !props.appendToBody\n    }, {\n      default: () => [createVNode(Transition, {\n        \"name\": `${prefixClass}-zoom-in-down`\n      }, {\n        default: () => {\n          var _a;\n          return [props.visible && createVNode(\"div\", {\n            \"ref\": popup,\n            \"class\": `${prefixClass}-datepicker-main ${prefixClass}-datepicker-popup ${props.className}`,\n            \"style\": [__spreadValues({\n              position: \"absolute\"\n            }, position.value), props.style || {}]\n          }, [(_a = slots.default) == null ? void 0 : _a.call(slots)])];\n        }\n      })]\n    });\n  };\n}\nconst popupProps = keys()([\"style\", \"className\", \"visible\", \"appendToBody\", \"onClickOutside\", \"getRelativeElement\"]);\nvar Popup$1 = defineVueComponent(Popup, popupProps);\nconst _hoisted_1$2 = {\n  xmlns: \"http://www.w3.org/2000/svg\",\n  viewBox: \"0 0 1024 1024\",\n  width: \"1em\",\n  height: \"1em\"\n};\nconst _hoisted_2$2 = /* @__PURE__ */ createElementVNode(\"path\", { d: \"M940.218 107.055H730.764v-60.51H665.6v60.51H363.055v-60.51H297.89v60.51H83.78c-18.617 0-32.581 13.963-32.581 32.581v805.237c0 18.618 13.964 32.582 32.582 32.582h861.09c18.619 0 32.583-13.964 32.583-32.582V139.636c-4.655-18.618-18.619-32.581-37.237-32.581zm-642.327 65.163v60.51h65.164v-60.51h307.2v60.51h65.163v-60.51h176.873v204.8H116.364v-204.8H297.89zM116.364 912.291V442.18H912.29v470.11H116.364z\" }, null, -1);\nconst _hoisted_3$2 = [\n  _hoisted_2$2\n];\nfunction render$2(_ctx, _cache) {\n  return openBlock(), createElementBlock(\"svg\", _hoisted_1$2, _hoisted_3$2);\n}\nconst _hoisted_1$1 = {\n  xmlns: \"http://www.w3.org/2000/svg\",\n  viewBox: \"0 0 1024 1024\",\n  width: \"1em\",\n  height: \"1em\"\n};\nconst _hoisted_2$1 = /* @__PURE__ */ createElementVNode(\"path\", { d: \"M810.005 274.005 572.011 512l237.994 237.995-60.01 60.01L512 572.011 274.005 810.005l-60.01-60.01L451.989 512 213.995 274.005l60.01-60.01L512 451.989l237.995-237.994z\" }, null, -1);\nconst _hoisted_3$1 = [\n  _hoisted_2$1\n];\nfunction render$1(_ctx, _cache) {\n  return openBlock(), createElementBlock(\"svg\", _hoisted_1$1, _hoisted_3$1);\n}\nconst _hoisted_1 = {\n  xmlns: \"http://www.w3.org/2000/svg\",\n  viewBox: \"0 0 24 24\",\n  width: \"1em\",\n  height: \"1em\"\n};\nconst _hoisted_2 = /* @__PURE__ */ createElementVNode(\"path\", {\n  d: \"M0 0h24v24H0z\",\n  fill: \"none\"\n}, null, -1);\nconst _hoisted_3 = /* @__PURE__ */ createElementVNode(\"path\", { d: \"M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z\" }, null, -1);\nconst _hoisted_4 = /* @__PURE__ */ createElementVNode(\"path\", { d: \"M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z\" }, null, -1);\nconst _hoisted_5 = [\n  _hoisted_2,\n  _hoisted_3,\n  _hoisted_4\n];\nfunction render(_ctx, _cache) {\n  return openBlock(), createElementBlock(\"svg\", _hoisted_1, _hoisted_5);\n}\nfunction createDate(y, M = 0, d = 1, h2 = 0, m = 0, s = 0, ms = 0) {\n  const date = new Date(y, M, d, h2, m, s, ms);\n  if (y < 100 && y >= 0) {\n    date.setFullYear(y);\n  }\n  return date;\n}\nfunction isValidDate(date) {\n  return date instanceof Date && !isNaN(date.getTime());\n}\nfunction isValidRangeDate(dates) {\n  return Array.isArray(dates) && dates.length === 2 && dates.every(isValidDate) && dates[0] <= dates[1];\n}\nfunction isValidDates(dates) {\n  return Array.isArray(dates) && dates.every(isValidDate);\n}\nfunction getValidDate(...values) {\n  if (values[0] !== void 0 && values[0] !== null) {\n    const date = new Date(values[0]);\n    if (isValidDate(date)) {\n      return date;\n    }\n  }\n  const rest = values.slice(1);\n  if (rest.length) {\n    return getValidDate(...rest);\n  }\n  return new Date();\n}\nfunction startOfYear(value) {\n  const date = new Date(value);\n  date.setMonth(0, 1);\n  date.setHours(0, 0, 0, 0);\n  return date;\n}\nfunction startOfMonth(value) {\n  const date = new Date(value);\n  date.setDate(1);\n  date.setHours(0, 0, 0, 0);\n  return date;\n}\nfunction startOfDay(value) {\n  const date = new Date(value);\n  date.setHours(0, 0, 0, 0);\n  return date;\n}\nfunction getCalendar({\n  firstDayOfWeek,\n  year,\n  month\n}) {\n  const arr = [];\n  const calendar = createDate(year, month, 0);\n  const lastDayInLastMonth = calendar.getDate();\n  const firstDayInLastMonth = lastDayInLastMonth - (calendar.getDay() + 7 - firstDayOfWeek) % 7;\n  for (let i = firstDayInLastMonth; i <= lastDayInLastMonth; i++) {\n    arr.push(createDate(year, month, i - lastDayInLastMonth));\n  }\n  calendar.setMonth(month + 1, 0);\n  const lastDayInCurrentMonth = calendar.getDate();\n  for (let i = 1; i <= lastDayInCurrentMonth; i++) {\n    arr.push(createDate(year, month, i));\n  }\n  const lastMonthLength = lastDayInLastMonth - firstDayInLastMonth + 1;\n  const nextMonthLength = 6 * 7 - lastMonthLength - lastDayInCurrentMonth;\n  for (let i = 1; i <= nextMonthLength; i++) {\n    arr.push(createDate(year, month, lastDayInCurrentMonth + i));\n  }\n  return arr;\n}\nfunction setMonth(dirtyDate, dirtyMonth) {\n  const date = new Date(dirtyDate);\n  const month = typeof dirtyMonth === \"function\" ? dirtyMonth(date.getMonth()) : Number(dirtyMonth);\n  const year = date.getFullYear();\n  const daysInMonth = createDate(year, month + 1, 0).getDate();\n  const day = date.getDate();\n  date.setMonth(month, Math.min(day, daysInMonth));\n  return date;\n}\nfunction setYear(dirtyDate, dirtyYear) {\n  const date = new Date(dirtyDate);\n  const year = typeof dirtyYear === \"function\" ? dirtyYear(date.getFullYear()) : dirtyYear;\n  date.setFullYear(year);\n  return date;\n}\nfunction diffCalendarMonths(dirtyDateLeft, dirtyDateRight) {\n  const dateRight = new Date(dirtyDateRight);\n  const dateLeft = new Date(dirtyDateLeft);\n  const yearDiff = dateRight.getFullYear() - dateLeft.getFullYear();\n  const monthDiff = dateRight.getMonth() - dateLeft.getMonth();\n  return yearDiff * 12 + monthDiff;\n}\nfunction assignTime(target, source) {\n  const date = new Date(target);\n  const time = new Date(source);\n  date.setHours(time.getHours(), time.getMinutes(), time.getSeconds());\n  return date;\n}\nfunction PickerInput(originalProps, {\n  slots\n}) {\n  const props = withDefault(originalProps, {\n    editable: true,\n    disabled: false,\n    clearable: true,\n    range: false,\n    multiple: false\n  });\n  const prefixClass = usePrefixClass();\n  const userInput = ref(null);\n  const innerSeparator = computed(() => {\n    return props.separator || (props.range ? \" ~ \" : \",\");\n  });\n  const isValidValue = (value) => {\n    if (props.range) {\n      return isValidRangeDate(value);\n    }\n    if (props.multiple) {\n      return isValidDates(value);\n    }\n    return isValidDate(value);\n  };\n  const isDisabledValue = (value) => {\n    if (Array.isArray(value)) {\n      return value.some((v) => props.disabledDate(v));\n    }\n    return props.disabledDate(value);\n  };\n  const text = computed(() => {\n    if (userInput.value !== null) {\n      return userInput.value;\n    }\n    if (typeof props.renderInputText === \"function\") {\n      return props.renderInputText(props.value);\n    }\n    if (!isValidValue(props.value)) {\n      return \"\";\n    }\n    if (Array.isArray(props.value)) {\n      return props.value.map((v) => props.formatDate(v)).join(innerSeparator.value);\n    }\n    return props.formatDate(props.value);\n  });\n  const handleClear = (evt) => {\n    var _a;\n    if (evt) {\n      evt.stopPropagation();\n    }\n    props.onChange(props.range ? [null, null] : null);\n    (_a = props.onClear) == null ? void 0 : _a.call(props);\n  };\n  const handleChange = () => {\n    var _a;\n    if (!props.editable || userInput.value === null)\n      return;\n    const text2 = userInput.value.trim();\n    userInput.value = null;\n    if (text2 === \"\") {\n      handleClear();\n      return;\n    }\n    let date;\n    if (props.range) {\n      let arr = text2.split(innerSeparator.value);\n      if (arr.length !== 2) {\n        arr = text2.split(innerSeparator.value.trim());\n      }\n      date = arr.map((v) => props.parseDate(v.trim()));\n    } else if (props.multiple) {\n      date = text2.split(innerSeparator.value).map((v) => props.parseDate(v.trim()));\n    } else {\n      date = props.parseDate(text2);\n    }\n    if (isValidValue(date) && !isDisabledValue(date)) {\n      props.onChange(date);\n    } else {\n      (_a = props.onInputError) == null ? void 0 : _a.call(props, text2);\n    }\n  };\n  const handleInput = (evt) => {\n    userInput.value = typeof evt === \"string\" ? evt : evt.target.value;\n  };\n  const handleKeydown = (evt) => {\n    const {\n      keyCode\n    } = evt;\n    if (keyCode === 9) {\n      props.onBlur();\n    } else if (keyCode === 13) {\n      handleChange();\n    }\n  };\n  return () => {\n    var _a, _b, _c;\n    const showClearIcon = !props.disabled && props.clearable && text.value;\n    const inputProps = __spreadProps(__spreadValues({\n      name: \"date\",\n      type: \"text\",\n      autocomplete: \"off\",\n      value: text.value,\n      class: props.inputClass || `${prefixClass}-input`,\n      readonly: !props.editable,\n      disabled: props.disabled,\n      placeholder: props.placeholder\n    }, props.inputAttr), {\n      onFocus: props.onFocus,\n      onKeydown: handleKeydown,\n      onInput: handleInput,\n      onChange: handleChange\n    });\n    return createVNode(\"div\", {\n      \"class\": `${prefixClass}-input-wrapper`,\n      \"onClick\": props.onClick\n    }, [((_a = slots.input) == null ? void 0 : _a.call(slots, inputProps)) || createVNode(\"input\", inputProps, null), showClearIcon ? createVNode(\"i\", {\n      \"class\": `${prefixClass}-icon-clear`,\n      \"onClick\": handleClear\n    }, [((_b = slots[\"icon-clear\"]) == null ? void 0 : _b.call(slots)) || createVNode(render$1, null, null)]) : null, createVNode(\"i\", {\n      \"class\": `${prefixClass}-icon-calendar`\n    }, [((_c = slots[\"icon-calendar\"]) == null ? void 0 : _c.call(slots)) || createVNode(render$2, null, null)])]);\n  };\n}\nconst pickerInputBaseProps = keys()([\"placeholder\", \"editable\", \"disabled\", \"clearable\", \"inputClass\", \"inputAttr\", \"range\", \"multiple\", \"separator\", \"renderInputText\", \"onInputError\", \"onClear\"]);\nconst pickerInputProps = keys()([\"value\", \"formatDate\", \"parseDate\", \"disabledDate\", \"onChange\", \"onFocus\", \"onBlur\", \"onClick\", ...pickerInputBaseProps]);\nvar PickerInput$1 = defineVueComponent(PickerInput, pickerInputProps);\nfunction Picker(originalProps, {\n  slots\n}) {\n  var _a;\n  const props = withDefault(originalProps, {\n    prefixClass: \"mx\",\n    valueType: \"date\",\n    format: \"YYYY-MM-DD\",\n    type: \"date\",\n    disabledDate: () => false,\n    disabledTime: () => false,\n    confirmText: \"OK\"\n  });\n  providePrefixClass(props.prefixClass);\n  provideGetWeek(((_a = props.formatter) == null ? void 0 : _a.getWeek) || getWeek);\n  const locale2 = provideLocale(toRef(originalProps, \"lang\"));\n  const container = ref();\n  const getContainer = () => container.value;\n  const defaultOpen = ref(false);\n  const popupVisible = computed(() => {\n    return !props.disabled && (typeof props.open === \"boolean\" ? props.open : defaultOpen.value);\n  });\n  const openPopup = () => {\n    var _a2, _b;\n    if (props.disabled || popupVisible.value)\n      return;\n    defaultOpen.value = true;\n    (_a2 = props[\"onUpdate:open\"]) == null ? void 0 : _a2.call(props, true);\n    (_b = props.onOpen) == null ? void 0 : _b.call(props);\n  };\n  const closePopup = () => {\n    var _a2, _b;\n    if (!popupVisible.value)\n      return;\n    defaultOpen.value = false;\n    (_a2 = props[\"onUpdate:open\"]) == null ? void 0 : _a2.call(props, false);\n    (_b = props.onClose) == null ? void 0 : _b.call(props);\n  };\n  const formatDate = (date, fmt) => {\n    fmt = fmt || props.format;\n    if (isPlainObject(props.formatter) && typeof props.formatter.stringify === \"function\") {\n      return props.formatter.stringify(date, fmt);\n    }\n    return format(date, fmt, {\n      locale: locale2.value.formatLocale\n    });\n  };\n  const parseDate = (value, fmt) => {\n    fmt = fmt || props.format;\n    if (isPlainObject(props.formatter) && typeof props.formatter.parse === \"function\") {\n      return props.formatter.parse(value, fmt);\n    }\n    const backupDate = new Date();\n    return parse(value, fmt, {\n      locale: locale2.value.formatLocale,\n      backupDate\n    });\n  };\n  const value2date = (value) => {\n    switch (props.valueType) {\n      case \"date\":\n        return value instanceof Date ? new Date(value.getTime()) : new Date(NaN);\n      case \"timestamp\":\n        return typeof value === \"number\" ? new Date(value) : new Date(NaN);\n      case \"format\":\n        return typeof value === \"string\" ? parseDate(value) : new Date(NaN);\n      default:\n        return typeof value === \"string\" ? parseDate(value, props.valueType) : new Date(NaN);\n    }\n  };\n  const date2value = (date) => {\n    if (!isValidDate(date))\n      return null;\n    switch (props.valueType) {\n      case \"date\":\n        return date;\n      case \"timestamp\":\n        return date.getTime();\n      case \"format\":\n        return formatDate(date);\n      default:\n        return formatDate(date, props.valueType);\n    }\n  };\n  const innerValue = computed(() => {\n    const value = props.value;\n    if (props.range) {\n      return (Array.isArray(value) ? value.slice(0, 2) : [null, null]).map(value2date);\n    }\n    if (props.multiple) {\n      return (Array.isArray(value) ? value : []).map(value2date);\n    }\n    return value2date(value);\n  });\n  const emitValue = (date, type, close = true) => {\n    var _a2, _b;\n    const value = Array.isArray(date) ? date.map(date2value) : date2value(date);\n    (_a2 = props[\"onUpdate:value\"]) == null ? void 0 : _a2.call(props, value);\n    (_b = props.onChange) == null ? void 0 : _b.call(props, value, type);\n    if (close) {\n      closePopup();\n    }\n    return value;\n  };\n  const currentValue = ref(new Date());\n  watchEffect(() => {\n    if (popupVisible.value) {\n      currentValue.value = innerValue.value;\n    }\n  });\n  const handleSelect = (val, type) => {\n    if (props.confirm) {\n      currentValue.value = val;\n    } else {\n      emitValue(val, type, !props.multiple && (type === props.type || type === \"time\"));\n    }\n  };\n  const handleConfirm = () => {\n    var _a2;\n    const value = emitValue(currentValue.value);\n    (_a2 = props.onConfirm) == null ? void 0 : _a2.call(props, value);\n  };\n  const disabledDateTime = (v) => {\n    return props.disabledDate(v) || props.disabledTime(v);\n  };\n  const renderSidebar = (slotProps) => {\n    var _a2;\n    const {\n      prefixClass\n    } = props;\n    return createVNode(\"div\", {\n      \"class\": `${prefixClass}-datepicker-sidebar`\n    }, [(_a2 = slots.sidebar) == null ? void 0 : _a2.call(slots, slotProps), (props.shortcuts || []).map((v, i) => createVNode(\"button\", {\n      \"key\": i,\n      \"data-index\": i,\n      \"type\": \"button\",\n      \"class\": `${prefixClass}-btn ${prefixClass}-btn-text ${prefixClass}-btn-shortcut`,\n      \"onClick\": () => {\n        var _a3;\n        const date = (_a3 = v.onClick) == null ? void 0 : _a3.call(v);\n        if (date) {\n          emitValue(date);\n        }\n      }\n    }, [v.text]))]);\n  };\n  return () => {\n    var _a2, _b;\n    const {\n      prefixClass,\n      disabled,\n      confirm,\n      range,\n      popupClass,\n      popupStyle,\n      appendToBody\n    } = props;\n    const slotProps = {\n      value: currentValue.value,\n      [\"onUpdate:value\"]: handleSelect,\n      emit: emitValue\n    };\n    const header = slots.header && createVNode(\"div\", {\n      \"class\": `${prefixClass}-datepicker-header`\n    }, [slots.header(slotProps)]);\n    const footer = (slots.footer || confirm) && createVNode(\"div\", {\n      \"class\": `${prefixClass}-datepicker-footer`\n    }, [(_a2 = slots.footer) == null ? void 0 : _a2.call(slots, slotProps), confirm && createVNode(\"button\", {\n      \"type\": \"button\",\n      \"class\": `${prefixClass}-btn ${prefixClass}-datepicker-btn-confirm`,\n      \"onClick\": handleConfirm\n    }, [props.confirmText])]);\n    const content = (_b = slots.content) == null ? void 0 : _b.call(slots, slotProps);\n    const sidedar = (slots.sidebar || props.shortcuts) && renderSidebar(slotProps);\n    return createVNode(\"div\", {\n      \"ref\": container,\n      \"class\": {\n        [`${prefixClass}-datepicker`]: true,\n        [`${prefixClass}-datepicker-range`]: range,\n        disabled\n      }\n    }, [createVNode(PickerInput$1, __spreadProps(__spreadValues({}, pick(props, pickerInputBaseProps)), {\n      \"value\": innerValue.value,\n      \"formatDate\": formatDate,\n      \"parseDate\": parseDate,\n      \"disabledDate\": disabledDateTime,\n      \"onChange\": emitValue,\n      \"onClick\": openPopup,\n      \"onFocus\": openPopup,\n      \"onBlur\": closePopup\n    }), pick(slots, [\"icon-calendar\", \"icon-clear\", \"input\"])), createVNode(Popup$1, {\n      \"className\": popupClass,\n      \"style\": popupStyle,\n      \"visible\": popupVisible.value,\n      \"appendToBody\": appendToBody,\n      \"getRelativeElement\": getContainer,\n      \"onClickOutside\": closePopup\n    }, {\n      default: () => [sidedar, createVNode(\"div\", {\n        \"class\": `${prefixClass}-datepicker-content`\n      }, [header, content, footer])]\n    })]);\n  };\n}\nconst pickerbaseProps = keys()([\"value\", \"valueType\", \"type\", \"format\", \"formatter\", \"lang\", \"prefixClass\", \"appendToBody\", \"open\", \"popupClass\", \"popupStyle\", \"confirm\", \"confirmText\", \"shortcuts\", \"disabledDate\", \"disabledTime\", \"onOpen\", \"onClose\", \"onConfirm\", \"onChange\", \"onUpdate:open\", \"onUpdate:value\"]);\nconst pickerProps = [...pickerbaseProps, ...pickerInputBaseProps];\nvar Picker$1 = defineVueComponent(Picker, pickerProps);\nfunction ButtonIcon(_a) {\n  var _b = _a, {\n    value\n  } = _b, rest = __objRest(_b, [\n    \"value\"\n  ]);\n  const prefixClass = usePrefixClass();\n  return createVNode(\"button\", __spreadProps(__spreadValues({}, rest), {\n    \"type\": \"button\",\n    \"class\": `${prefixClass}-btn ${prefixClass}-btn-text ${prefixClass}-btn-icon-${value}`\n  }), [createVNode(\"i\", {\n    \"class\": `${prefixClass}-icon-${value}`\n  }, null)]);\n}\nfunction TableHeader({\n  type,\n  calendar,\n  onUpdateCalendar\n}, {\n  slots\n}) {\n  var _a;\n  const prefixClass = usePrefixClass();\n  const lastMonth = () => {\n    onUpdateCalendar(setMonth(calendar, (v) => v - 1));\n  };\n  const nextMonth = () => {\n    onUpdateCalendar(setMonth(calendar, (v) => v + 1));\n  };\n  const lastYear = () => {\n    onUpdateCalendar(setYear(calendar, (v) => v - 1));\n  };\n  const nextYear = () => {\n    onUpdateCalendar(setYear(calendar, (v) => v + 1));\n  };\n  const lastDecade = () => {\n    onUpdateCalendar(setYear(calendar, (v) => v - 10));\n  };\n  const nextDecade = () => {\n    onUpdateCalendar(setYear(calendar, (v) => v + 10));\n  };\n  return createVNode(\"div\", {\n    \"class\": `${prefixClass}-calendar-header`\n  }, [createVNode(ButtonIcon, {\n    \"value\": \"double-left\",\n    \"onClick\": type === \"year\" ? lastDecade : lastYear\n  }, null), type === \"date\" && createVNode(ButtonIcon, {\n    \"value\": \"left\",\n    \"onClick\": lastMonth\n  }, null), createVNode(ButtonIcon, {\n    \"value\": \"double-right\",\n    \"onClick\": type === \"year\" ? nextDecade : nextYear\n  }, null), type === \"date\" && createVNode(ButtonIcon, {\n    \"value\": \"right\",\n    \"onClick\": nextMonth\n  }, null), createVNode(\"span\", {\n    \"class\": `${prefixClass}-calendar-header-label`\n  }, [(_a = slots.default) == null ? void 0 : _a.call(slots)])]);\n}\nfunction TableDate({\n  calendar,\n  isWeekMode,\n  showWeekNumber,\n  titleFormat,\n  getWeekActive,\n  getCellClasses,\n  onSelect,\n  onUpdatePanel,\n  onUpdateCalendar,\n  onDateMouseEnter,\n  onDateMouseLeave\n}) {\n  const prefixClass = usePrefixClass();\n  const getWeekNumber = useGetWeek();\n  const locale2 = useLocale().value;\n  const {\n    yearFormat,\n    monthBeforeYear,\n    monthFormat = \"MMM\",\n    formatLocale\n  } = locale2;\n  const firstDayOfWeek = formatLocale.firstDayOfWeek || 0;\n  let days = locale2.days || formatLocale.weekdaysMin;\n  days = days.concat(days).slice(firstDayOfWeek, firstDayOfWeek + 7);\n  const year = calendar.getFullYear();\n  const month = calendar.getMonth();\n  const dates = chunk(getCalendar({\n    firstDayOfWeek,\n    year,\n    month\n  }), 7);\n  const formatDate = (date, fmt) => {\n    return format(date, fmt, {\n      locale: locale2.formatLocale\n    });\n  };\n  const handlePanelChange = (panel) => {\n    onUpdatePanel(panel);\n  };\n  const getCellDate = (el) => {\n    const index2 = el.getAttribute(\"data-index\");\n    const [row, col] = index2.split(\",\").map((v) => parseInt(v, 10));\n    const value = dates[row][col];\n    return new Date(value);\n  };\n  const handleCellClick = (evt) => {\n    onSelect(getCellDate(evt.currentTarget));\n  };\n  const handleMouseEnter = (evt) => {\n    if (onDateMouseEnter) {\n      onDateMouseEnter(getCellDate(evt.currentTarget));\n    }\n  };\n  const handleMouseLeave = (evt) => {\n    if (onDateMouseLeave) {\n      onDateMouseLeave(getCellDate(evt.currentTarget));\n    }\n  };\n  const yearLabel = createVNode(\"button\", {\n    \"type\": \"button\",\n    \"class\": `${prefixClass}-btn ${prefixClass}-btn-text ${prefixClass}-btn-current-year`,\n    \"onClick\": () => handlePanelChange(\"year\")\n  }, [formatDate(calendar, yearFormat)]);\n  const monthLabel = createVNode(\"button\", {\n    \"type\": \"button\",\n    \"class\": `${prefixClass}-btn ${prefixClass}-btn-text ${prefixClass}-btn-current-month`,\n    \"onClick\": () => handlePanelChange(\"month\")\n  }, [formatDate(calendar, monthFormat)]);\n  showWeekNumber = typeof showWeekNumber === \"boolean\" ? showWeekNumber : isWeekMode;\n  return createVNode(\"div\", {\n    \"class\": [`${prefixClass}-calendar ${prefixClass}-calendar-panel-date`, {\n      [`${prefixClass}-calendar-week-mode`]: isWeekMode\n    }]\n  }, [createVNode(TableHeader, {\n    \"type\": \"date\",\n    \"calendar\": calendar,\n    \"onUpdateCalendar\": onUpdateCalendar\n  }, {\n    default: () => [monthBeforeYear ? [monthLabel, yearLabel] : [yearLabel, monthLabel]]\n  }), createVNode(\"div\", {\n    \"class\": `${prefixClass}-calendar-content`\n  }, [createVNode(\"table\", {\n    \"class\": `${prefixClass}-table ${prefixClass}-table-date`\n  }, [createVNode(\"thead\", null, [createVNode(\"tr\", null, [showWeekNumber && createVNode(\"th\", {\n    \"class\": `${prefixClass}-week-number-header`\n  }, null), days.map((day) => createVNode(\"th\", {\n    \"key\": day\n  }, [day]))])]), createVNode(\"tbody\", null, [dates.map((row, i) => createVNode(\"tr\", {\n    \"key\": i,\n    \"class\": [`${prefixClass}-date-row`, {\n      [`${prefixClass}-active-week`]: getWeekActive(row)\n    }]\n  }, [showWeekNumber && createVNode(\"td\", {\n    \"class\": `${prefixClass}-week-number`,\n    \"data-index\": `${i},0`,\n    \"onClick\": handleCellClick\n  }, [createVNode(\"div\", null, [getWeekNumber(row[0])])]), row.map((cell, j) => createVNode(\"td\", {\n    \"key\": j,\n    \"class\": [\"cell\", getCellClasses(cell)],\n    \"title\": formatDate(cell, titleFormat),\n    \"data-index\": `${i},${j}`,\n    \"onClick\": handleCellClick,\n    \"onMouseenter\": handleMouseEnter,\n    \"onMouseleave\": handleMouseLeave\n  }, [createVNode(\"div\", null, [cell.getDate()])]))]))])])])]);\n}\nfunction TableMonth({\n  calendar,\n  getCellClasses,\n  onSelect,\n  onUpdateCalendar,\n  onUpdatePanel\n}) {\n  const prefixClass = usePrefixClass();\n  const locale2 = useLocale().value;\n  const months = locale2.months || locale2.formatLocale.monthsShort;\n  const getDate = (month) => {\n    return createDate(calendar.getFullYear(), month);\n  };\n  const handleClick = (evt) => {\n    const target = evt.currentTarget;\n    const month = target.getAttribute(\"data-month\");\n    onSelect(getDate(parseInt(month, 10)));\n  };\n  return createVNode(\"div\", {\n    \"class\": `${prefixClass}-calendar ${prefixClass}-calendar-panel-month`\n  }, [createVNode(TableHeader, {\n    \"type\": \"month\",\n    \"calendar\": calendar,\n    \"onUpdateCalendar\": onUpdateCalendar\n  }, {\n    default: () => [createVNode(\"button\", {\n      \"type\": \"button\",\n      \"class\": `${prefixClass}-btn ${prefixClass}-btn-text ${prefixClass}-btn-current-year`,\n      \"onClick\": () => onUpdatePanel(\"year\")\n    }, [calendar.getFullYear()])]\n  }), createVNode(\"div\", {\n    \"class\": `${prefixClass}-calendar-content`\n  }, [createVNode(\"table\", {\n    \"class\": `${prefixClass}-table ${prefixClass}-table-month`\n  }, [chunk(months, 3).map((row, i) => createVNode(\"tr\", {\n    \"key\": i\n  }, [row.map((cell, j) => {\n    const month = i * 3 + j;\n    return createVNode(\"td\", {\n      \"key\": j,\n      \"class\": [\"cell\", getCellClasses(getDate(month))],\n      \"data-month\": month,\n      \"onClick\": handleClick\n    }, [createVNode(\"div\", null, [cell])]);\n  })]))])])]);\n}\nconst getDefaultYears = (calendar) => {\n  const firstYear = Math.floor(calendar.getFullYear() / 10) * 10;\n  const years = [];\n  for (let i = 0; i < 10; i++) {\n    years.push(firstYear + i);\n  }\n  return chunk(years, 2);\n};\nfunction TableYear({\n  calendar,\n  getCellClasses = () => [],\n  getYearPanel = getDefaultYears,\n  onSelect,\n  onUpdateCalendar\n}) {\n  const prefixClass = usePrefixClass();\n  const getDate = (year) => {\n    return createDate(year, 0);\n  };\n  const handleClick = (evt) => {\n    const target = evt.currentTarget;\n    const year = target.getAttribute(\"data-year\");\n    onSelect(getDate(parseInt(year, 10)));\n  };\n  const years = getYearPanel(new Date(calendar));\n  const firstYear = years[0][0];\n  const lastYear = last(last(years));\n  return createVNode(\"div\", {\n    \"class\": `${prefixClass}-calendar ${prefixClass}-calendar-panel-year`\n  }, [createVNode(TableHeader, {\n    \"type\": \"year\",\n    \"calendar\": calendar,\n    \"onUpdateCalendar\": onUpdateCalendar\n  }, {\n    default: () => [createVNode(\"span\", null, [firstYear]), createVNode(\"span\", {\n      \"class\": `${prefixClass}-calendar-decade-separator`\n    }, null), createVNode(\"span\", null, [lastYear])]\n  }), createVNode(\"div\", {\n    \"class\": `${prefixClass}-calendar-content`\n  }, [createVNode(\"table\", {\n    \"class\": `${prefixClass}-table ${prefixClass}-table-year`\n  }, [years.map((row, i) => createVNode(\"tr\", {\n    \"key\": i\n  }, [row.map((cell, j) => createVNode(\"td\", {\n    \"key\": j,\n    \"class\": [\"cell\", getCellClasses(getDate(cell))],\n    \"data-year\": cell,\n    \"onClick\": handleClick\n  }, [createVNode(\"div\", null, [cell])]))]))])])]);\n}\nfunction Calendar(originalProps) {\n  const props = withDefault(originalProps, {\n    defaultValue: startOfDay(new Date()),\n    type: \"date\",\n    disabledDate: () => false,\n    getClasses: () => [],\n    titleFormat: \"YYYY-MM-DD\"\n  });\n  const innerValue = computed(() => {\n    const value = Array.isArray(props.value) ? props.value : [props.value];\n    return value.filter(isValidDate).map((v) => {\n      if (props.type === \"year\")\n        return startOfYear(v);\n      if (props.type === \"month\")\n        return startOfMonth(v);\n      return startOfDay(v);\n    });\n  });\n  const innerCalendar = ref(new Date());\n  watchEffect(() => {\n    let calendarDate = props.calendar;\n    if (!isValidDate(calendarDate)) {\n      const {\n        length\n      } = innerValue.value;\n      calendarDate = getValidDate(length > 0 ? innerValue.value[length - 1] : props.defaultValue);\n    }\n    innerCalendar.value = startOfMonth(calendarDate);\n  });\n  const handleCalendarChange = (calendar) => {\n    var _a;\n    innerCalendar.value = calendar;\n    (_a = props.onCalendarChange) == null ? void 0 : _a.call(props, calendar);\n  };\n  const panel = ref(\"date\");\n  watchEffect(() => {\n    const panels = [\"date\", \"month\", \"year\"];\n    const index2 = Math.max(panels.indexOf(props.type), panels.indexOf(props.defaultPanel));\n    panel.value = index2 !== -1 ? panels[index2] : \"date\";\n  });\n  const handelPanelChange = (value) => {\n    var _a;\n    const oldPanel = panel.value;\n    panel.value = value;\n    (_a = props.onPanelChange) == null ? void 0 : _a.call(props, value, oldPanel);\n  };\n  const isDisabled = (date) => {\n    return props.disabledDate(new Date(date), innerValue.value);\n  };\n  const emitDate = (date, type) => {\n    var _a, _b, _c;\n    if (!isDisabled(date)) {\n      (_a = props.onPick) == null ? void 0 : _a.call(props, date);\n      if (props.multiple === true) {\n        const nextDates = innerValue.value.filter((v) => v.getTime() !== date.getTime());\n        if (nextDates.length === innerValue.value.length) {\n          nextDates.push(date);\n        }\n        (_b = props[\"onUpdate:value\"]) == null ? void 0 : _b.call(props, nextDates, type);\n      } else {\n        (_c = props[\"onUpdate:value\"]) == null ? void 0 : _c.call(props, date, type);\n      }\n    }\n  };\n  const handleSelectDate = (date) => {\n    emitDate(date, props.type === \"week\" ? \"week\" : \"date\");\n  };\n  const handleSelectYear = (date) => {\n    if (props.type === \"year\") {\n      emitDate(date, \"year\");\n    } else {\n      handleCalendarChange(date);\n      handelPanelChange(\"month\");\n      if (props.partialUpdate && innerValue.value.length === 1) {\n        const value = setYear(innerValue.value[0], date.getFullYear());\n        emitDate(value, \"year\");\n      }\n    }\n  };\n  const handleSelectMonth = (date) => {\n    if (props.type === \"month\") {\n      emitDate(date, \"month\");\n    } else {\n      handleCalendarChange(date);\n      handelPanelChange(\"date\");\n      if (props.partialUpdate && innerValue.value.length === 1) {\n        const value = setMonth(setYear(innerValue.value[0], date.getFullYear()), date.getMonth());\n        emitDate(value, \"month\");\n      }\n    }\n  };\n  const getCellClasses = (cellDate, classes = []) => {\n    if (isDisabled(cellDate)) {\n      classes.push(\"disabled\");\n    } else if (innerValue.value.some((v) => v.getTime() === cellDate.getTime())) {\n      classes.push(\"active\");\n    }\n    return classes.concat(props.getClasses(cellDate, innerValue.value, classes.join(\" \")));\n  };\n  const getDateClasses = (cellDate) => {\n    const notCurrentMonth = cellDate.getMonth() !== innerCalendar.value.getMonth();\n    const classes = [];\n    if (cellDate.getTime() === new Date().setHours(0, 0, 0, 0)) {\n      classes.push(\"today\");\n    }\n    if (notCurrentMonth) {\n      classes.push(\"not-current-month\");\n    }\n    return getCellClasses(cellDate, classes);\n  };\n  const getMonthClasses = (cellDate) => {\n    if (props.type !== \"month\") {\n      return innerCalendar.value.getMonth() === cellDate.getMonth() ? \"active\" : \"\";\n    }\n    return getCellClasses(cellDate);\n  };\n  const getYearClasses = (cellDate) => {\n    if (props.type !== \"year\") {\n      return innerCalendar.value.getFullYear() === cellDate.getFullYear() ? \"active\" : \"\";\n    }\n    return getCellClasses(cellDate);\n  };\n  const getWeekActive = (row) => {\n    if (props.type !== \"week\")\n      return false;\n    const start = row[0].getTime();\n    const end = row[6].getTime();\n    return innerValue.value.some((v) => {\n      const time = v.getTime();\n      return time >= start && time <= end;\n    });\n  };\n  return () => {\n    if (panel.value === \"year\") {\n      return createVNode(TableYear, {\n        \"calendar\": innerCalendar.value,\n        \"getCellClasses\": getYearClasses,\n        \"getYearPanel\": props.getYearPanel,\n        \"onSelect\": handleSelectYear,\n        \"onUpdateCalendar\": handleCalendarChange\n      }, null);\n    }\n    if (panel.value === \"month\") {\n      return createVNode(TableMonth, {\n        \"calendar\": innerCalendar.value,\n        \"getCellClasses\": getMonthClasses,\n        \"onSelect\": handleSelectMonth,\n        \"onUpdatePanel\": handelPanelChange,\n        \"onUpdateCalendar\": handleCalendarChange\n      }, null);\n    }\n    return createVNode(TableDate, {\n      \"isWeekMode\": props.type === \"week\",\n      \"showWeekNumber\": props.showWeekNumber,\n      \"titleFormat\": props.titleFormat,\n      \"calendar\": innerCalendar.value,\n      \"getCellClasses\": getDateClasses,\n      \"getWeekActive\": getWeekActive,\n      \"onSelect\": handleSelectDate,\n      \"onUpdatePanel\": handelPanelChange,\n      \"onUpdateCalendar\": handleCalendarChange,\n      \"onDateMouseEnter\": props.onDateMouseEnter,\n      \"onDateMouseLeave\": props.onDateMouseLeave\n    }, null);\n  };\n}\nconst calendarProps = keys()([\"type\", \"value\", \"defaultValue\", \"defaultPanel\", \"disabledDate\", \"getClasses\", \"calendar\", \"multiple\", \"partialUpdate\", \"showWeekNumber\", \"titleFormat\", \"getYearPanel\", \"onDateMouseEnter\", \"onDateMouseLeave\", \"onCalendarChange\", \"onPanelChange\", \"onUpdate:value\", \"onPick\"]);\nvar Calendar$1 = defineVueComponent(Calendar, calendarProps);\nconst inRange = (date, range) => {\n  const value = date.getTime();\n  let [min, max] = range.map((v) => v.getTime());\n  if (min > max) {\n    [min, max] = [max, min];\n  }\n  return value > min && value < max;\n};\nfunction CalendarRange(originalProps) {\n  const props = withDefault(originalProps, {\n    defaultValue: new Date(),\n    type: \"date\"\n  });\n  const prefixClass = usePrefixClass();\n  const defaultValues = computed(() => {\n    let values = Array.isArray(props.defaultValue) ? props.defaultValue : [props.defaultValue, props.defaultValue];\n    values = values.map((v) => startOfDay(v));\n    if (isValidRangeDate(values)) {\n      return values;\n    }\n    return [new Date(), new Date()].map((v) => startOfDay(v));\n  });\n  const innerValue = ref([new Date(NaN), new Date(NaN)]);\n  watchEffect(() => {\n    if (isValidRangeDate(props.value)) {\n      innerValue.value = props.value;\n    }\n  });\n  const handlePick = (date, type) => {\n    var _a;\n    const [startValue, endValue] = innerValue.value;\n    if (isValidDate(startValue) && !isValidDate(endValue)) {\n      if (startValue.getTime() > date.getTime()) {\n        innerValue.value = [date, startValue];\n      } else {\n        innerValue.value = [startValue, date];\n      }\n      (_a = props[\"onUpdate:value\"]) == null ? void 0 : _a.call(props, innerValue.value, type);\n    } else {\n      innerValue.value = [date, new Date(NaN)];\n    }\n  };\n  const defaultCalendars = ref([new Date(), new Date()]);\n  const calendars = computed(() => {\n    return isValidRangeDate(props.calendar) ? props.calendar : defaultCalendars.value;\n  });\n  const calendarMinDiff = computed(() => {\n    if (props.type === \"year\")\n      return 10 * 12;\n    if (props.type === \"month\")\n      return 1 * 12;\n    return 1;\n  });\n  const updateCalendars = (dates, index2) => {\n    var _a;\n    const diff = diffCalendarMonths(dates[0], dates[1]);\n    const gap = calendarMinDiff.value - diff;\n    if (gap > 0) {\n      const anotherIndex = index2 === 1 ? 0 : 1;\n      dates[anotherIndex] = setMonth(dates[anotherIndex], (v) => v + (anotherIndex === 0 ? -gap : gap));\n    }\n    defaultCalendars.value = dates;\n    (_a = props.onCalendarChange) == null ? void 0 : _a.call(props, dates, index2);\n  };\n  const updateCalendarStart = (date) => {\n    updateCalendars([date, calendars.value[1]], 0);\n  };\n  const updateCalendarEnd = (date) => {\n    updateCalendars([calendars.value[0], date], 1);\n  };\n  watchEffect(() => {\n    const dates = isValidRangeDate(props.value) ? props.value : defaultValues.value;\n    updateCalendars(dates.slice(0, 2));\n  });\n  const hoveredValue = ref(null);\n  const handleMouseEnter = (v) => hoveredValue.value = v;\n  const handleMouseLeave = () => hoveredValue.value = null;\n  const getRangeClasses = (cellDate, currentDates, classnames) => {\n    const outerClasses = props.getClasses ? props.getClasses(cellDate, currentDates, classnames) : [];\n    const classes = Array.isArray(outerClasses) ? outerClasses : [outerClasses];\n    if (/disabled|active/.test(classnames))\n      return classes;\n    if (currentDates.length === 2 && inRange(cellDate, currentDates)) {\n      classes.push(\"in-range\");\n    }\n    if (currentDates.length === 1 && hoveredValue.value && inRange(cellDate, [currentDates[0], hoveredValue.value])) {\n      return classes.concat(\"hover-in-range\");\n    }\n    return classes;\n  };\n  return () => {\n    const calendarRange = calendars.value.map((calendar, index2) => {\n      const calendarProps2 = __spreadProps(__spreadValues({}, props), {\n        calendar,\n        value: innerValue.value,\n        defaultValue: defaultValues.value[index2],\n        getClasses: getRangeClasses,\n        partialUpdate: false,\n        multiple: false,\n        [\"onUpdate:value\"]: handlePick,\n        onCalendarChange: index2 === 0 ? updateCalendarStart : updateCalendarEnd,\n        onDateMouseLeave: handleMouseLeave,\n        onDateMouseEnter: handleMouseEnter\n      });\n      return createVNode(Calendar$1, calendarProps2, null);\n    });\n    return createVNode(\"div\", {\n      \"class\": `${prefixClass}-calendar-range`\n    }, [calendarRange]);\n  };\n}\nconst calendarRangeProps = calendarProps;\nvar CalendarRange$1 = defineVueComponent(CalendarRange, calendarRangeProps);\nconst ScrollbarVertical = defineComponent({\n  setup(props, {\n    slots\n  }) {\n    const prefixClass = usePrefixClass();\n    const wrapper = ref();\n    const thumbHeight = ref(\"\");\n    const thumbTop = ref(\"\");\n    const getThumbHeight = () => {\n      if (!wrapper.value)\n        return;\n      const el = wrapper.value;\n      const heightPercentage = el.clientHeight * 100 / el.scrollHeight;\n      thumbHeight.value = heightPercentage < 100 ? `${heightPercentage}%` : \"\";\n    };\n    onMounted(getThumbHeight);\n    const scrollbarWidth = getScrollbarWidth();\n    const handleScroll = (evt) => {\n      const el = evt.currentTarget;\n      const {\n        scrollHeight,\n        scrollTop\n      } = el;\n      thumbTop.value = `${scrollTop * 100 / scrollHeight}%`;\n    };\n    let draggable = false;\n    let prevY = 0;\n    const handleDragstart = (evt) => {\n      evt.stopImmediatePropagation();\n      const el = evt.currentTarget;\n      const {\n        offsetTop\n      } = el;\n      draggable = true;\n      prevY = evt.clientY - offsetTop;\n    };\n    const handleDraging = (evt) => {\n      if (!draggable || !wrapper.value)\n        return;\n      const {\n        clientY\n      } = evt;\n      const {\n        scrollHeight,\n        clientHeight\n      } = wrapper.value;\n      const offsetY = clientY - prevY;\n      const top = offsetY * scrollHeight / clientHeight;\n      wrapper.value.scrollTop = top;\n    };\n    const handleDragend = () => {\n      draggable = false;\n    };\n    onMounted(() => {\n      document.addEventListener(\"mousemove\", handleDraging);\n      document.addEventListener(\"mouseup\", handleDragend);\n    });\n    onUnmounted(() => {\n      document.addEventListener(\"mousemove\", handleDraging);\n      document.addEventListener(\"mouseup\", handleDragend);\n    });\n    return () => {\n      var _a;\n      return createVNode(\"div\", {\n        \"class\": `${prefixClass}-scrollbar`,\n        \"style\": {\n          position: \"relative\",\n          overflow: \"hidden\"\n        }\n      }, [createVNode(\"div\", {\n        \"ref\": wrapper,\n        \"class\": `${prefixClass}-scrollbar-wrap`,\n        \"style\": {\n          marginRight: `-${scrollbarWidth}px`\n        },\n        \"onScroll\": handleScroll\n      }, [(_a = slots.default) == null ? void 0 : _a.call(slots)]), createVNode(\"div\", {\n        \"class\": `${prefixClass}-scrollbar-track`\n      }, [createVNode(\"div\", {\n        \"class\": `${prefixClass}-scrollbar-thumb`,\n        \"style\": {\n          height: thumbHeight.value,\n          top: thumbTop.value\n        },\n        \"onMousedown\": handleDragstart\n      }, null)])]);\n    };\n  }\n});\nfunction Columns({\n  options,\n  getClasses,\n  onSelect\n}) {\n  const prefixClass = usePrefixClass();\n  const handleSelect = (evt) => {\n    const target = evt.target;\n    const currentTarget = evt.currentTarget;\n    if (target.tagName.toUpperCase() !== \"LI\")\n      return;\n    const type = currentTarget.getAttribute(\"data-type\");\n    const col = parseInt(currentTarget.getAttribute(\"data-index\"), 10);\n    const index2 = parseInt(target.getAttribute(\"data-index\"), 10);\n    const value = options[col].list[index2].value;\n    onSelect(value, type);\n  };\n  return createVNode(\"div\", {\n    \"class\": `${prefixClass}-time-columns`\n  }, [options.map((col, i) => createVNode(ScrollbarVertical, {\n    \"key\": col.type,\n    \"class\": `${prefixClass}-time-column`\n  }, {\n    default: () => [createVNode(\"ul\", {\n      \"class\": `${prefixClass}-time-list`,\n      \"data-index\": i,\n      \"data-type\": col.type,\n      \"onClick\": handleSelect\n    }, [col.list.map((item, j) => createVNode(\"li\", {\n      \"key\": item.text,\n      \"data-index\": j,\n      \"class\": [`${prefixClass}-time-item`, getClasses(item.value, col.type)]\n    }, [item.text]))])]\n  }))]);\n}\nfunction _isSlot(s) {\n  return typeof s === \"function\" || Object.prototype.toString.call(s) === \"[object Object]\" && !isVNode(s);\n}\nfunction FixedList(props) {\n  let _slot;\n  const prefixClass = usePrefixClass();\n  return createVNode(ScrollbarVertical, null, _isSlot(_slot = props.options.map((item) => createVNode(\"div\", {\n    \"key\": item.text,\n    \"class\": [`${prefixClass}-time-option`, props.getClasses(item.value, \"time\")],\n    \"onClick\": () => props.onSelect(item.value, \"time\")\n  }, [item.text]))) ? _slot : {\n    default: () => [_slot]\n  });\n}\nfunction generateList({\n  length,\n  step = 1,\n  options\n}) {\n  if (Array.isArray(options)) {\n    return options.filter((v) => v >= 0 && v < length);\n  }\n  if (step <= 0) {\n    step = 1;\n  }\n  const arr = [];\n  for (let i = 0; i < length; i += step) {\n    arr.push(i);\n  }\n  return arr;\n}\nfunction getColumnOptions(date, options) {\n  let { showHour, showMinute, showSecond, use12h } = options;\n  const format2 = options.format || \"HH:mm:ss\";\n  showHour = typeof showHour === \"boolean\" ? showHour : /[HhKk]/.test(format2);\n  showMinute = typeof showMinute === \"boolean\" ? showMinute : /m/.test(format2);\n  showSecond = typeof showSecond === \"boolean\" ? showSecond : /s/.test(format2);\n  use12h = typeof use12h === \"boolean\" ? use12h : /a/i.test(format2);\n  const columns = [];\n  const isPM = use12h && date.getHours() >= 12;\n  if (showHour) {\n    columns.push({\n      type: \"hour\",\n      list: generateList({\n        length: use12h ? 12 : 24,\n        step: options.hourStep,\n        options: options.hourOptions\n      }).map((num) => {\n        const text = num === 0 && use12h ? \"12\" : padNumber(num);\n        const value = new Date(date);\n        value.setHours(isPM ? num + 12 : num);\n        return { value, text };\n      })\n    });\n  }\n  if (showMinute) {\n    columns.push({\n      type: \"minute\",\n      list: generateList({\n        length: 60,\n        step: options.minuteStep,\n        options: options.minuteOptions\n      }).map((num) => {\n        const value = new Date(date);\n        value.setMinutes(num);\n        return { value, text: padNumber(num) };\n      })\n    });\n  }\n  if (showSecond) {\n    columns.push({\n      type: \"second\",\n      list: generateList({\n        length: 60,\n        step: options.secondStep,\n        options: options.secondOptions\n      }).map((num) => {\n        const value = new Date(date);\n        value.setSeconds(num);\n        return { value, text: padNumber(num) };\n      })\n    });\n  }\n  if (use12h) {\n    columns.push({\n      type: \"ampm\",\n      list: [\"AM\", \"PM\"].map((text, i) => {\n        const value = new Date(date);\n        value.setHours(value.getHours() % 12 + i * 12);\n        return { text, value };\n      })\n    });\n  }\n  return columns;\n}\nfunction parseOption(time = \"\") {\n  const values = time.split(\":\");\n  if (values.length >= 2) {\n    const hours = parseInt(values[0], 10);\n    const minutes = parseInt(values[1], 10);\n    return {\n      hours,\n      minutes\n    };\n  }\n  return null;\n}\nfunction getFixedOptions({\n  date,\n  option,\n  format: format2,\n  formatDate\n}) {\n  const result = [];\n  if (typeof option === \"function\") {\n    return option() || [];\n  }\n  const start = parseOption(option.start);\n  const end = parseOption(option.end);\n  const step = parseOption(option.step);\n  const fmt = option.format || format2;\n  if (start && end && step) {\n    const startMinutes = start.minutes + start.hours * 60;\n    const endMinutes = end.minutes + end.hours * 60;\n    const stepMinutes = step.minutes + step.hours * 60;\n    const len = Math.floor((endMinutes - startMinutes) / stepMinutes);\n    for (let i = 0; i <= len; i++) {\n      const timeMinutes = startMinutes + i * stepMinutes;\n      const hours = Math.floor(timeMinutes / 60);\n      const minutes = timeMinutes % 60;\n      const value = new Date(date);\n      value.setHours(hours, minutes, 0);\n      result.push({\n        value,\n        text: formatDate(value, fmt)\n      });\n    }\n  }\n  return result;\n}\nconst scrollTo = (element, to, duration = 0) => {\n  if (duration <= 0) {\n    requestAnimationFrame(() => {\n      element.scrollTop = to;\n    });\n    return;\n  }\n  const difference = to - element.scrollTop;\n  const tick = difference / duration * 10;\n  requestAnimationFrame(() => {\n    const scrollTop = element.scrollTop + tick;\n    if (scrollTop >= to) {\n      element.scrollTop = to;\n      return;\n    }\n    element.scrollTop = scrollTop;\n    scrollTo(element, to, duration - 10);\n  });\n};\nfunction TimePanel(originalProps) {\n  const props = withDefault(originalProps, {\n    defaultValue: startOfDay(new Date()),\n    format: \"HH:mm:ss\",\n    timeTitleFormat: \"YYYY-MM-DD\",\n    disabledTime: () => false,\n    scrollDuration: 100\n  });\n  const prefixClass = usePrefixClass();\n  const locale2 = useLocale();\n  const formatDate = (date, fmt) => {\n    return format(date, fmt, {\n      locale: locale2.value.formatLocale\n    });\n  };\n  const innerValue = ref(new Date());\n  watchEffect(() => {\n    innerValue.value = getValidDate(props.value, props.defaultValue);\n  });\n  const isDisabledTimes = (value) => {\n    if (Array.isArray(value)) {\n      return value.every((v) => props.disabledTime(new Date(v)));\n    }\n    return props.disabledTime(new Date(value));\n  };\n  const isDisabledHour = (date) => {\n    const value = new Date(date);\n    return isDisabledTimes([value.getTime(), value.setMinutes(0, 0, 0), value.setMinutes(59, 59, 999)]);\n  };\n  const isDisabledMinute = (date) => {\n    const value = new Date(date);\n    return isDisabledTimes([value.getTime(), value.setSeconds(0, 0), value.setSeconds(59, 999)]);\n  };\n  const isDisabledAMPM = (date) => {\n    const value = new Date(date);\n    const minHour = value.getHours() < 12 ? 0 : 12;\n    const maxHour = minHour + 11;\n    return isDisabledTimes([value.getTime(), value.setHours(minHour, 0, 0, 0), value.setHours(maxHour, 59, 59, 999)]);\n  };\n  const isDisabled = (date, type) => {\n    if (type === \"hour\") {\n      return isDisabledHour(date);\n    }\n    if (type === \"minute\") {\n      return isDisabledMinute(date);\n    }\n    if (type === \"ampm\") {\n      return isDisabledAMPM(date);\n    }\n    return isDisabledTimes(date);\n  };\n  const handleSelect = (value, type) => {\n    var _a;\n    if (!isDisabled(value, type)) {\n      const date = new Date(value);\n      innerValue.value = date;\n      if (!isDisabledTimes(date)) {\n        (_a = props[\"onUpdate:value\"]) == null ? void 0 : _a.call(props, date, type);\n      }\n    }\n  };\n  const getClasses = (cellDate, type) => {\n    if (isDisabled(cellDate, type)) {\n      return \"disabled\";\n    }\n    if (cellDate.getTime() === innerValue.value.getTime()) {\n      return \"active\";\n    }\n    return \"\";\n  };\n  const container = ref();\n  const scrollToSelected = (duration) => {\n    if (!container.value)\n      return;\n    const elements = container.value.querySelectorAll(\".active\");\n    for (let i = 0; i < elements.length; i++) {\n      const element = elements[i];\n      const scrollElement = getScrollParent(element, container.value);\n      if (scrollElement) {\n        const to = element.offsetTop;\n        scrollTo(scrollElement, to, duration);\n      }\n    }\n  };\n  onMounted(() => scrollToSelected(0));\n  watch(innerValue, () => scrollToSelected(props.scrollDuration), {\n    flush: \"post\"\n  });\n  return () => {\n    let content;\n    if (props.timePickerOptions) {\n      content = createVNode(FixedList, {\n        \"onSelect\": handleSelect,\n        \"getClasses\": getClasses,\n        \"options\": getFixedOptions({\n          date: innerValue.value,\n          format: props.format,\n          option: props.timePickerOptions,\n          formatDate\n        })\n      }, null);\n    } else {\n      content = createVNode(Columns, {\n        \"options\": getColumnOptions(innerValue.value, props),\n        \"onSelect\": handleSelect,\n        \"getClasses\": getClasses\n      }, null);\n    }\n    return createVNode(\"div\", {\n      \"class\": `${prefixClass}-time`,\n      \"ref\": container\n    }, [props.showTimeHeader && createVNode(\"div\", {\n      \"class\": `${prefixClass}-time-header`\n    }, [createVNode(\"button\", {\n      \"type\": \"button\",\n      \"class\": `${prefixClass}-btn ${prefixClass}-btn-text ${prefixClass}-time-header-title`,\n      \"onClick\": props.onClickTitle\n    }, [formatDate(innerValue.value, props.timeTitleFormat)])]), createVNode(\"div\", {\n      \"class\": `${prefixClass}-time-content`\n    }, [content])]);\n  };\n}\nconst timePanelProps = keys()([\"value\", \"defaultValue\", \"format\", \"timeTitleFormat\", \"showTimeHeader\", \"disabledTime\", \"timePickerOptions\", \"hourOptions\", \"minuteOptions\", \"secondOptions\", \"hourStep\", \"minuteStep\", \"secondStep\", \"showHour\", \"showMinute\", \"showSecond\", \"use12h\", \"scrollDuration\", \"onClickTitle\", \"onUpdate:value\"]);\nvar TimePanel$1 = defineVueComponent(TimePanel, timePanelProps);\nfunction TimeRange(originalProps) {\n  const props = withDefault(originalProps, {\n    defaultValue: startOfDay(new Date()),\n    disabledTime: () => false\n  });\n  const prefixClass = usePrefixClass();\n  const innerValue = ref([new Date(NaN), new Date(NaN)]);\n  watchEffect(() => {\n    if (isValidRangeDate(props.value)) {\n      innerValue.value = props.value;\n    } else {\n      innerValue.value = [new Date(NaN), new Date(NaN)];\n    }\n  });\n  const emitChange = (type, index2) => {\n    var _a;\n    (_a = props[\"onUpdate:value\"]) == null ? void 0 : _a.call(props, innerValue.value, type === \"time\" ? \"time-range\" : type, index2);\n  };\n  const handleSelectStart = (date, type) => {\n    innerValue.value[0] = date;\n    if (!(innerValue.value[1].getTime() >= date.getTime())) {\n      innerValue.value[1] = date;\n    }\n    emitChange(type, 0);\n  };\n  const handleSelectEnd = (date, type) => {\n    innerValue.value[1] = date;\n    if (!(innerValue.value[0].getTime() <= date.getTime())) {\n      innerValue.value[0] = date;\n    }\n    emitChange(type, 1);\n  };\n  const disabledStartTime = (date) => {\n    return props.disabledTime(date, 0);\n  };\n  const disabledEndTime = (date) => {\n    return date.getTime() < innerValue.value[0].getTime() || props.disabledTime(date, 1);\n  };\n  return () => {\n    const defaultValues = Array.isArray(props.defaultValue) ? props.defaultValue : [props.defaultValue, props.defaultValue];\n    return createVNode(\"div\", {\n      \"class\": `${prefixClass}-time-range`\n    }, [createVNode(TimePanel$1, __spreadProps(__spreadValues({}, props), {\n      [\"onUpdate:value\"]: handleSelectStart,\n      \"value\": innerValue.value[0],\n      \"defaultValue\": defaultValues[0],\n      \"disabledTime\": disabledStartTime\n    }), null), createVNode(TimePanel$1, __spreadProps(__spreadValues({}, props), {\n      [\"onUpdate:value\"]: handleSelectEnd,\n      \"value\": innerValue.value[1],\n      \"defaultValue\": defaultValues[1],\n      \"disabledTime\": disabledEndTime\n    }), null)]);\n  };\n}\nconst timeRangeProps = timePanelProps;\nvar TimeRange$1 = defineVueComponent(TimeRange, timeRangeProps);\nfunction useTimePanelVisible(props) {\n  const defaultTimeVisible = ref(false);\n  const closeTimePanel = () => {\n    var _a;\n    defaultTimeVisible.value = false;\n    (_a = props.onShowTimePanelChange) == null ? void 0 : _a.call(props, false);\n  };\n  const openTimePanel = () => {\n    var _a;\n    defaultTimeVisible.value = true;\n    (_a = props.onShowTimePanelChange) == null ? void 0 : _a.call(props, true);\n  };\n  const timeVisible = computed(() => {\n    return typeof props.showTimePanel === \"boolean\" ? props.showTimePanel : defaultTimeVisible.value;\n  });\n  return { timeVisible, openTimePanel, closeTimePanel };\n}\nfunction DateTime(originalProps) {\n  const props = withDefault(originalProps, {\n    disabledTime: () => false,\n    defaultValue: startOfDay(new Date())\n  });\n  const currentValue = ref(props.value);\n  watchEffect(() => {\n    currentValue.value = props.value;\n  });\n  const {\n    openTimePanel,\n    closeTimePanel,\n    timeVisible\n  } = useTimePanelVisible(props);\n  const handleSelect = (date, type) => {\n    var _a;\n    if (type === \"date\") {\n      openTimePanel();\n    }\n    let datetime = assignTime(date, getValidDate(props.value, props.defaultValue));\n    if (props.disabledTime(new Date(datetime))) {\n      datetime = assignTime(date, props.defaultValue);\n      if (props.disabledTime(new Date(datetime))) {\n        currentValue.value = datetime;\n        return;\n      }\n    }\n    (_a = props[\"onUpdate:value\"]) == null ? void 0 : _a.call(props, datetime, type);\n  };\n  return () => {\n    const prefixClass = usePrefixClass();\n    const calendarProp = __spreadProps(__spreadValues({}, pick(props, calendarProps)), {\n      multiple: false,\n      type: \"date\",\n      value: currentValue.value,\n      [\"onUpdate:value\"]: handleSelect\n    });\n    const timeProps = __spreadProps(__spreadValues({}, pick(props, timePanelProps)), {\n      showTimeHeader: true,\n      value: currentValue.value,\n      [\"onUpdate:value\"]: props[\"onUpdate:value\"],\n      onClickTitle: closeTimePanel\n    });\n    return createVNode(\"div\", {\n      \"class\": `${prefixClass}-date-time`\n    }, [createVNode(Calendar$1, calendarProp, null), timeVisible.value && createVNode(TimePanel$1, timeProps, null)]);\n  };\n}\nconst datetimeBaseProps = keys()([\"showTimePanel\", \"onShowTimePanelChange\"]);\nconst datetimeProps = [...datetimeBaseProps, ...calendarProps, ...timePanelProps];\nvar DateTime$1 = defineVueComponent(DateTime, datetimeProps);\nfunction DateTimeRange(originalProps) {\n  const props = withDefault(originalProps, {\n    defaultValue: startOfDay(new Date()),\n    disabledTime: () => false\n  });\n  const currentValue = ref(props.value);\n  watchEffect(() => {\n    currentValue.value = props.value;\n  });\n  const {\n    openTimePanel,\n    closeTimePanel,\n    timeVisible\n  } = useTimePanelVisible(props);\n  const handleSelect = (dates, type) => {\n    var _a;\n    if (type === \"date\") {\n      openTimePanel();\n    }\n    const defaultValues = Array.isArray(props.defaultValue) ? props.defaultValue : [props.defaultValue, props.defaultValue];\n    let datetimes = dates.map((date, i) => {\n      const time = isValidRangeDate(props.value) ? props.value[i] : defaultValues[i];\n      return assignTime(date, time);\n    });\n    if (datetimes[1].getTime() < datetimes[0].getTime()) {\n      datetimes = [datetimes[0], datetimes[0]];\n    }\n    if (datetimes.some(props.disabledTime)) {\n      datetimes = dates.map((date, i) => assignTime(date, defaultValues[i]));\n      if (datetimes.some(props.disabledTime)) {\n        currentValue.value = datetimes;\n        return;\n      }\n    }\n    (_a = props[\"onUpdate:value\"]) == null ? void 0 : _a.call(props, datetimes, type);\n  };\n  return () => {\n    const prefixClass = usePrefixClass();\n    const calendarProp = __spreadProps(__spreadValues({}, pick(props, calendarRangeProps)), {\n      type: \"date\",\n      value: currentValue.value,\n      [\"onUpdate:value\"]: handleSelect\n    });\n    const timeProps = __spreadProps(__spreadValues({}, pick(props, timeRangeProps)), {\n      showTimeHeader: true,\n      value: currentValue.value,\n      [\"onUpdate:value\"]: props[\"onUpdate:value\"],\n      onClickTitle: closeTimePanel\n    });\n    return createVNode(\"div\", {\n      \"class\": `${prefixClass}-date-time-range`\n    }, [createVNode(CalendarRange$1, calendarProp, null), timeVisible.value && createVNode(TimeRange$1, timeProps, null)]);\n  };\n}\nconst datetimeRangeProps = [...datetimeBaseProps, ...timeRangeProps, ...calendarRangeProps];\nvar DateTimeRange$1 = defineVueComponent(DateTimeRange, datetimeRangeProps);\nconst booleanKeys = keys()([\"range\", \"open\", \"appendToBody\", \"clearable\", \"confirm\", \"disabled\", \"editable\", \"multiple\", \"partialUpdate\", \"showHour\", \"showMinute\", \"showSecond\", \"showTimeHeader\", \"showTimePanel\", \"showWeekNumber\", \"use12h\"]);\nconst formatMap = {\n  date: \"YYYY-MM-DD\",\n  datetime: \"YYYY-MM-DD HH:mm:ss\",\n  year: \"YYYY\",\n  month: \"YYYY-MM\",\n  time: \"HH:mm:ss\",\n  week: \"w\"\n};\nfunction DatePicker(originalProps, {\n  slots\n}) {\n  const type = originalProps.type || \"date\";\n  const format2 = originalProps.format || formatMap[type] || formatMap.date;\n  const props = __spreadProps(__spreadValues({}, resolveProps(originalProps, booleanKeys)), {\n    type,\n    format: format2\n  });\n  return createVNode(Picker$1, pick(props, Picker$1.props), __spreadValues({\n    content: (slotProps) => {\n      if (props.range) {\n        const Content = type === \"time\" ? TimeRange$1 : type === \"datetime\" ? DateTimeRange$1 : CalendarRange$1;\n        return h(Content, pick(__spreadValues(__spreadValues({}, props), slotProps), Content.props));\n      } else {\n        const Content = type === \"time\" ? TimePanel$1 : type === \"datetime\" ? DateTime$1 : Calendar$1;\n        return h(Content, pick(__spreadValues(__spreadValues({}, props), slotProps), Content.props));\n      }\n    },\n    [\"icon-calendar\"]: () => type === \"time\" ? createVNode(render, null, null) : createVNode(render$2, null, null)\n  }, slots));\n}\nconst api = {\n  locale,\n  install: (app) => {\n    app.component(\"DatePicker\", DatePicker);\n  }\n};\nvar index = Object.assign(DatePicker, api, {\n  Calendar: Calendar$1,\n  CalendarRange: CalendarRange$1,\n  TimePanel: TimePanel$1,\n  TimeRange: TimeRange$1,\n  DateTime: DateTime$1,\n  DateTimeRange: DateTimeRange$1\n});\nexport { index as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'],\n  monthsShort: ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],\n  weekdays: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],\n  weekdaysShort: ['Son', 'Maa', 'Din', 'Woe', 'Don', 'Vry', 'Sat'],\n  weekdaysMin: ['So', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Sa'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 1\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('af', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],\n  monthsShort: ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],\n  weekdays: ['الأحد', 'الإثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],\n  weekdaysShort: ['احد', 'اثنين', 'ثلاثاء', 'اربعاء', 'خميس', 'جمعة', 'سبت'],\n  weekdaysMin: ['أح', 'إث', 'ثلا', 'أر', 'خم', 'جم', 'سب'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('ar-dz', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],\n  monthsShort: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],\n  weekdays: ['الأحد', 'الإثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],\n  weekdaysShort: ['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],\n  weekdaysMin: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 6\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('ar-sa', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],\n  monthsShort: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],\n  weekdays: ['الأحد', 'الإثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],\n  weekdaysShort: ['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],\n  weekdaysMin: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],\n  firstDayOfWeek: 6,\n  firstWeekContainsDate: 12\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('ar', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],\n  monthsShort: ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl', 'avq', 'sen', 'okt', 'noy', 'dek'],\n  weekdays: ['Bazar', 'Bazar ertəsi', 'Çərşənbə axşamı', 'Çərşənbə', 'Cümə axşamı', 'Cümə', 'Şənbə'],\n  weekdaysShort: ['Baz', 'BzE', 'ÇAx', 'Çər', 'CAx', 'Cüm', 'Şən'],\n  weekdaysMin: ['Bz', 'BE', 'ÇA', 'Çə', 'CA', 'Cü', 'Şə'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('az', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['студзень', 'люты', 'сакавік', 'красавік', 'травень', 'чэрвень', 'ліпень', 'жнівень', 'верасень', 'кастрычнік', 'лістапад', 'снежань'],\n  monthsShort: ['студ', 'лют', 'сак', 'крас', 'трав', 'чэрв', 'ліп', 'жнів', 'вер', 'каст', 'ліст', 'снеж'],\n  weekdays: ['нядзеля', 'панядзелак', 'аўторак', 'серада', 'чацвер', 'пятніца', 'субота'],\n  weekdaysShort: ['нд', 'пн', 'ат', 'ср', 'чц', 'пт', 'сб'],\n  weekdaysMin: ['нд', 'пн', 'ат', 'ср', 'чц', 'пт', 'сб'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('be', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['януари', 'февруари', 'март', 'април', 'май', 'юни', 'юли', 'август', 'септември', 'октомври', 'ноември', 'декември'],\n  monthsShort: ['янр', 'фев', 'мар', 'апр', 'май', 'юни', 'юли', 'авг', 'сеп', 'окт', 'ное', 'дек'],\n  weekdays: ['неделя', 'понеделник', 'вторник', 'сряда', 'четвъртък', 'петък', 'събота'],\n  weekdaysShort: ['нед', 'пон', 'вто', 'сря', 'чет', 'пет', 'съб'],\n  weekdaysMin: ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('bg', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['Zanwuyekalo', 'Fewuruyekalo', 'Marisikalo', 'Awirilikalo', 'Mɛkalo', 'Zuwɛnkalo', 'Zuluyekalo', 'Utikalo', 'Sɛtanburukalo', 'ɔkutɔburukalo', 'Nowanburukalo', 'Desanburukalo'],\n  monthsShort: ['Zan', 'Few', 'Mar', 'Awi', 'Mɛ', 'Zuw', 'Zul', 'Uti', 'Sɛt', 'ɔku', 'Now', 'Des'],\n  weekdays: ['Kari', 'Ntɛnɛn', 'Tarata', 'Araba', 'Alamisa', 'Juma', 'Sibiri'],\n  weekdaysShort: ['Kar', 'Ntɛ', 'Tar', 'Ara', 'Ala', 'Jum', 'Sib'],\n  weekdaysMin: ['Ka', 'Nt', 'Ta', 'Ar', 'Al', 'Ju', 'Si'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('bm', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['জানুয়ারী', 'ফেব্রুয়ারি', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],\n  monthsShort: ['জানু', 'ফেব', 'মার্চ', 'এপ্র', 'মে', 'জুন', 'জুল', 'আগ', 'সেপ্ট', 'অক্টো', 'নভে', 'ডিসে'],\n  weekdays: ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'],\n  weekdaysShort: ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],\n  weekdaysMin: ['রবি', 'সোম', 'মঙ্গ', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 6\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('bn', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'],\n  monthsShort: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.', 'set.', 'oct.', 'nov.', 'des.'],\n  weekdays: ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous', 'divendres', 'dissabte'],\n  weekdaysShort: ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],\n  weekdaysMin: ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('ca', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['leden', 'únor', 'březen', 'duben', 'květen', 'červen', 'červenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec'],\n  monthsShort: ['led', 'úno', 'bře', 'dub', 'kvě', 'čvn', 'čvc', 'srp', 'zář', 'říj', 'lis', 'pro'],\n  weekdays: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'],\n  weekdaysShort: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],\n  weekdaysMin: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('cs', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['Ionawr', 'Chwefror', 'Mawrth', 'Ebrill', 'Mai', 'Mehefin', 'Gorffennaf', 'Awst', 'Medi', 'Hydref', 'Tachwedd', 'Rhagfyr'],\n  monthsShort: ['Ion', 'Chwe', 'Maw', 'Ebr', 'Mai', 'Meh', 'Gor', 'Aws', 'Med', 'Hyd', 'Tach', 'Rhag'],\n  weekdays: ['Dydd Sul', 'Dydd Llun', 'Dydd Mawrth', 'Dydd Mercher', 'Dydd Iau', 'Dydd Gwener', 'Dydd Sadwrn'],\n  weekdaysShort: ['Sul', 'Llun', 'Maw', 'Mer', 'Iau', 'Gwe', 'Sad'],\n  weekdaysMin: ['Su', 'Ll', 'Ma', 'Me', 'Ia', 'Gw', 'Sa'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 1\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('cy', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['januar', 'februar', 'marts', 'april', 'maj', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'december'],\n  monthsShort: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],\n  weekdays: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'],\n  weekdaysShort: ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'],\n  weekdaysMin: ['sø', 'ma', 'ti', 'on', 'to', 'fr', 'lø'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('da', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],\n  monthsShort: ['Jan', 'Feb', 'März', 'Apr', 'Mai', 'Juni', 'Juli', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],\n  weekdays: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],\n  weekdaysShort: ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],\n  weekdaysMin: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('de', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['Ιανουάριος', 'Φεβρουάριος', 'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος', 'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος', 'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος'],\n  monthsShort: ['Ιαν', 'Φεβ', 'Μαρ', 'Απρ', 'Μαϊ', 'Ιουν', 'Ιουλ', 'Αυγ', 'Σεπ', 'Οκτ', 'Νοε', 'Δεκ'],\n  weekdays: ['Κυριακή', 'Δευτέρα', 'Τρίτη', 'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σάββατο'],\n  weekdaysShort: ['Κυρ', 'Δευ', 'Τρι', 'Τετ', 'Πεμ', 'Παρ', 'Σαβ'],\n  weekdaysMin: ['Κυ', 'Δε', 'Τρ', 'Τε', 'Πε', 'Πα', 'Σα'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('el', lang);\n\nexport { lang as default };\n","var locale = {\n  months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],\n  monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n  weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],\n  weekdaysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n  weekdaysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 1\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['januaro', 'februaro', 'marto', 'aprilo', 'majo', 'junio', 'julio', 'aŭgusto', 'septembro', 'oktobro', 'novembro', 'decembro'],\n  monthsShort: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aŭg', 'sep', 'okt', 'nov', 'dec'],\n  weekdays: ['dimanĉo', 'lundo', 'mardo', 'merkredo', 'ĵaŭdo', 'vendredo', 'sabato'],\n  weekdaysShort: ['dim', 'lun', 'mard', 'merk', 'ĵaŭ', 'ven', 'sab'],\n  weekdaysMin: ['di', 'lu', 'ma', 'me', 'ĵa', 've', 'sa'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('eo', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],\n  monthsShort: ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],\n  weekdays: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'],\n  weekdaysShort: ['dom', 'lun', 'mar', 'mié', 'jue', 'vie', 'sáb'],\n  weekdaysMin: ['do', 'lu', 'ma', 'mi', 'ju', 'vi', 'sá'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 1\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('es', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni', 'juuli', 'august', 'september', 'oktoober', 'november', 'detsember'],\n  monthsShort: ['jaan', 'veebr', 'märts', 'apr', 'mai', 'juuni', 'juuli', 'aug', 'sept', 'okt', 'nov', 'dets'],\n  weekdays: ['pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev', 'neljapäev', 'reede', 'laupäev'],\n  weekdaysShort: ['P', 'E', 'T', 'K', 'N', 'R', 'L'],\n  weekdaysMin: ['P', 'E', 'T', 'K', 'N', 'R', 'L'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('et', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'],\n  monthsShort: ['tammi', 'helmi', 'maalis', 'huhti', 'touko', 'kesä', 'heinä', 'elo', 'syys', 'loka', 'marras', 'joulu'],\n  weekdays: ['sunnuntai', 'maanantai', 'tiistai', 'keskiviikko', 'torstai', 'perjantai', 'lauantai'],\n  weekdaysShort: ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],\n  weekdaysMin: ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('fi', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],\n  monthsShort: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'],\n  weekdays: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],\n  weekdaysShort: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],\n  weekdaysMin: ['di', 'lu', 'ma', 'me', 'je', 've', 'sa'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 1\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('fr', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['xaneiro', 'febreiro', 'marzo', 'abril', 'maio', 'xuño', 'xullo', 'agosto', 'setembro', 'outubro', 'novembro', 'decembro'],\n  monthsShort: ['xan.', 'feb.', 'mar.', 'abr.', 'mai.', 'xuñ.', 'xul.', 'ago.', 'set.', 'out.', 'nov.', 'dec.'],\n  weekdays: ['domingo', 'luns', 'martes', 'mércores', 'xoves', 'venres', 'sábado'],\n  weekdaysShort: ['dom.', 'lun.', 'mar.', 'mér.', 'xov.', 'ven.', 'sáb.'],\n  weekdaysMin: ['do', 'lu', 'ma', 'mé', 'xo', 've', 'sá'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('gl', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['જાન્યુઆરી', 'ફેબ્રુઆરી', 'માર્ચ', 'એપ્રિલ', 'મે', 'જૂન', 'જુલાઈ', 'ઑગસ્ટ', 'સપ્ટેમ્બર', 'ઑક્ટ્બર', 'નવેમ્બર', 'ડિસેમ્બર'],\n  monthsShort: ['જાન્યુ.', 'ફેબ્રુ.', 'માર્ચ', 'એપ્રિ.', 'મે', 'જૂન', 'જુલા.', 'ઑગ.', 'સપ્ટે.', 'ઑક્ટ્.', 'નવે.', 'ડિસે.'],\n  weekdays: ['રવિવાર', 'સોમવાર', 'મંગળવાર', 'બુધ્વાર', 'ગુરુવાર', 'શુક્રવાર', 'શનિવાર'],\n  weekdaysShort: ['રવિ', 'સોમ', 'મંગળ', 'બુધ્', 'ગુરુ', 'શુક્ર', 'શનિ'],\n  weekdaysMin: ['ર', 'સો', 'મં', 'બુ', 'ગુ', 'શુ', 'શ'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 6\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('gu', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'],\n  monthsShort: ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳', 'דצמ׳'],\n  weekdays: ['ראשון', 'שני', 'שלישי', 'רביעי', 'חמישי', 'שישי', 'שבת'],\n  weekdaysShort: ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'],\n  weekdaysMin: ['א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ש'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 6\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('he', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],\n  monthsShort: ['जन.', 'फ़र.', 'मार्च', 'अप्रै.', 'मई', 'जून', 'जुल.', 'अग.', 'सित.', 'अक्टू.', 'नव.', 'दिस.'],\n  weekdays: ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरूवार', 'शुक्रवार', 'शनिवार'],\n  weekdaysShort: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरू', 'शुक्र', 'शनि'],\n  weekdaysMin: ['र', 'सो', 'मं', 'बु', 'गु', 'शु', 'श'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 6\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('hi', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj', 'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'],\n  monthsShort: ['sij.', 'velj.', 'ožu.', 'tra.', 'svi.', 'lip.', 'srp.', 'kol.', 'ruj.', 'lis.', 'stu.', 'pro.'],\n  weekdays: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],\n  weekdaysShort: ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'],\n  weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('hr', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['január', 'február', 'március', 'április', 'május', 'június', 'július', 'augusztus', 'szeptember', 'október', 'november', 'december'],\n  monthsShort: ['jan', 'feb', 'márc', 'ápr', 'máj', 'jún', 'júl', 'aug', 'szept', 'okt', 'nov', 'dec'],\n  weekdays: ['vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök', 'péntek', 'szombat'],\n  weekdaysShort: ['vas', 'hét', 'kedd', 'sze', 'csüt', 'pén', 'szo'],\n  weekdaysMin: ['v', 'h', 'k', 'sze', 'cs', 'p', 'szo'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: false,\r\n};\r\nDatePicker.locale('hu', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'],\n  monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agt', 'Sep', 'Okt', 'Nov', 'Des'],\n  weekdays: ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'],\n  weekdaysShort: ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],\n  weekdaysMin: ['Mg', 'Sn', 'Sl', 'Rb', 'Km', 'Jm', 'Sb'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('id', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['janúar', 'febrúar', 'mars', 'apríl', 'maí', 'júní', 'júlí', 'ágúst', 'september', 'október', 'nóvember', 'desember'],\n  monthsShort: ['jan', 'feb', 'mar', 'apr', 'maí', 'jún', 'júl', 'ágú', 'sep', 'okt', 'nóv', 'des'],\n  weekdays: ['sunnudagur', 'mánudagur', 'þriðjudagur', 'miðvikudagur', 'fimmtudagur', 'föstudagur', 'laugardagur'],\n  weekdaysShort: ['sun', 'mán', 'þri', 'mið', 'fim', 'fös', 'lau'],\n  weekdaysMin: ['Su', 'Má', 'Þr', 'Mi', 'Fi', 'Fö', 'La'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('is', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno', 'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'],\n  monthsShort: ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set', 'ott', 'nov', 'dic'],\n  weekdays: ['domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato'],\n  weekdaysShort: ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],\n  weekdaysMin: ['do', 'lu', 'ma', 'me', 'gi', 've', 'sa'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('it', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],\n  monthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],\n  weekdays: ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'],\n  weekdaysShort: ['日', '月', '火', '水', '木', '金', '土'],\n  weekdaysMin: ['日', '月', '火', '水', '木', '金', '土'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 6\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: false,\r\n};\r\nDatePicker.locale('ja', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი', 'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი'],\n  monthsShort: ['იან', 'თებ', 'მარ', 'აპრ', 'მაი', 'ივნ', 'ივლ', 'აგვ', 'სექ', 'ოქტ', 'ნოე', 'დეკ'],\n  weekdays: ['კვირა', 'ორშაბათი', 'სამშაბათი', 'ოთხშაბათი', 'ხუთშაბათი', 'პარასკევი', 'შაბათი'],\n  weekdaysShort: ['კვი', 'ორშ', 'სამ', 'ოთხ', 'ხუთ', 'პარ', 'შაბ'],\n  weekdaysMin: ['კვ', 'ორ', 'სა', 'ოთ', 'ხუ', 'პა', 'შა'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('ka', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['қаңтар', 'ақпан', 'наурыз', 'сәуір', 'мамыр', 'маусым', 'шілде', 'тамыз', 'қыркүйек', 'қазан', 'қараша', 'желтоқсан'],\n  monthsShort: ['қаң', 'ақп', 'нау', 'сәу', 'мам', 'мау', 'шіл', 'там', 'қыр', 'қаз', 'қар', 'жел'],\n  weekdays: ['жексенбі', 'дүйсенбі', 'сейсенбі', 'сәрсенбі', 'бейсенбі', 'жұма', 'сенбі'],\n  weekdaysShort: ['жек', 'дүй', 'сей', 'сәр', 'бей', 'жұм', 'сен'],\n  weekdaysMin: ['жк', 'дй', 'сй', 'ср', 'бй', 'жм', 'сн'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('kk', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],\n  monthsShort: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],\n  weekdays: ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'],\n  weekdaysShort: ['일', '월', '화', '수', '목', '금', '토'],\n  weekdaysMin: ['일', '월', '화', '수', '목', '금', '토'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 6\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: false,\r\n};\r\nDatePicker.locale('ko', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['sausis', 'vasaris', 'kovas', 'balandis', 'gegužė', 'birželis', 'liepa', 'rugpjūtis', 'rugsėjis', 'spalis', 'lapkritis', 'gruodis'],\n  monthsShort: ['sau', 'vas', 'kov', 'bal', 'geg', 'bir', 'lie', 'rgp', 'rgs', 'spa', 'lap', 'grd'],\n  weekdays: ['sekmadienis', 'pirmadienis', 'antradienis', 'trečiadienis', 'ketvirtadienis', 'penktadienis', 'šeštadienis'],\n  weekdaysShort: ['Sek', 'Pir', 'Ant', 'Tre', 'Ket', 'Pen', 'Šeš'],\n  weekdaysMin: ['S', 'P', 'A', 'T', 'K', 'Pn', 'Š'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('lt', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['janvāris', 'februāris', 'marts', 'aprīlis', 'maijs', 'jūnijs', 'jūlijs', 'augusts', 'septembris', 'oktobris', 'novembris', 'decembris'],\n  monthsShort: ['jan', 'feb', 'mar', 'apr', 'mai', 'jūn', 'jūl', 'aug', 'sep', 'okt', 'nov', 'dec'],\n  weekdays: ['svētdiena', 'pirmdiena', 'otrdiena', 'trešdiena', 'ceturtdiena', 'piektdiena', 'sestdiena'],\n  weekdaysShort: ['Sv', 'P', 'O', 'T', 'C', 'Pk', 'S'],\n  weekdaysMin: ['Sv', 'P', 'O', 'T', 'C', 'Pk', 'S'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: false,\r\n};\r\nDatePicker.locale('lv', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['јануари', 'февруари', 'март', 'април', 'мај', 'јуни', 'јули', 'август', 'септември', 'октомври', 'ноември', 'декември'],\n  monthsShort: ['јан', 'фев', 'мар', 'апр', 'мај', 'јун', 'јул', 'авг', 'сеп', 'окт', 'ное', 'дек'],\n  weekdays: ['недела', 'понеделник', 'вторник', 'среда', 'четврток', 'петок', 'сабота'],\n  weekdaysShort: ['нед', 'пон', 'вто', 'сре', 'чет', 'пет', 'саб'],\n  weekdaysMin: ['нe', 'пo', 'вт', 'ср', 'че', 'пе', 'сa'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('mk', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun', 'Julai', 'Ogos', 'September', 'Oktober', 'November', 'Disember'],\n  monthsShort: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ogs', 'Sep', 'Okt', 'Nov', 'Dis'],\n  weekdays: ['Ahad', 'Isnin', 'Selasa', 'Rabu', 'Khamis', 'Jumaat', 'Sabtu'],\n  weekdaysShort: ['Ahd', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'],\n  weekdaysMin: ['Ah', 'Is', 'Sl', 'Rb', 'Km', 'Jm', 'Sb'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('ms', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],\n  monthsShort: ['jan.', 'feb.', 'mars', 'april', 'mai', 'juni', 'juli', 'aug.', 'sep.', 'okt.', 'nov.', 'des.'],\n  weekdays: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'],\n  weekdaysShort: ['sø.', 'ma.', 'ti.', 'on.', 'to.', 'fr.', 'lø.'],\n  weekdaysMin: ['sø', 'ma', 'ti', 'on', 'to', 'fr', 'lø'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('nb', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],\n  monthsShort: ['jan.', 'feb.', 'mrt.', 'apr.', 'mei', 'jun.', 'jul.', 'aug.', 'sep.', 'okt.', 'nov.', 'dec.'],\n  weekdays: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],\n  weekdaysShort: ['zo.', 'ma.', 'di.', 'wo.', 'do.', 'vr.', 'za.'],\n  weekdaysMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('nl-be', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],\n  monthsShort: ['jan.', 'feb.', 'mrt.', 'apr.', 'mei', 'jun.', 'jul.', 'aug.', 'sep.', 'okt.', 'nov.', 'dec.'],\n  weekdays: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],\n  weekdaysShort: ['zo.', 'ma.', 'di.', 'wo.', 'do.', 'vr.', 'za.'],\n  weekdaysMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('nl', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['styczeń', 'luty', 'marzec', 'kwiecień', 'maj', 'czerwiec', 'lipiec', 'sierpień', 'wrzesień', 'październik', 'listopad', 'grudzień'],\n  monthsShort: ['sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip', 'sie', 'wrz', 'paź', 'lis', 'gru'],\n  weekdays: ['niedziela', 'poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota'],\n  weekdaysShort: ['ndz', 'pon', 'wt', 'śr', 'czw', 'pt', 'sob'],\n  weekdaysMin: ['Nd', 'Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'So'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('pl', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],\n  monthsShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],\n  weekdays: ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'],\n  weekdaysShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],\n  weekdaysMin: ['Do', '2ª', '3ª', '4ª', '5ª', '6ª', 'Sá'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 6\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('pt-br', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],\n  monthsShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],\n  weekdays: ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'],\n  weekdaysShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],\n  weekdaysMin: ['Do', '2ª', '3ª', '4ª', '5ª', '6ª', 'Sá'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('pt', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['ianuarie', 'februarie', 'martie', 'aprilie', 'mai', 'iunie', 'iulie', 'august', 'septembrie', 'octombrie', 'noiembrie', 'decembrie'],\n  monthsShort: ['ian', 'feb', 'mar', 'apr', 'mai', 'iun', 'iul', 'aug', 'sep', 'oct', 'noi', 'dec'],\n  weekdays: ['duminică', 'luni', 'marți', 'miercuri', 'joi', 'vineri', 'sâmbătă'],\n  weekdaysShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],\n  weekdaysMin: ['Du', 'Lu', 'Ma', 'Mi', 'Jo', 'Vi', 'Sâ'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('ro', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],\n  monthsShort: ['янв.', 'февр.', 'март', 'апр.', 'май', 'июнь', 'июль', 'авг.', 'сент.', 'окт.', 'нояб.', 'дек.'],\n  weekdays: ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'],\n  weekdaysShort: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],\n  weekdaysMin: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 1\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('ru', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['januar', 'februar', 'marec', 'april', 'maj', 'junij', 'julij', 'avgust', 'september', 'oktober', 'november', 'december'],\n  monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj.', 'jun.', 'jul.', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'],\n  weekdays: ['nedelja', 'ponedeljek', 'torek', 'sreda', 'četrtek', 'petek', 'sobota'],\n  weekdaysShort: ['ned.', 'pon.', 'tor.', 'sre.', 'čet.', 'pet.', 'sob.'],\n  weekdaysMin: ['ne', 'po', 'to', 'sr', 'če', 'pe', 'so'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('sl', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],\n  monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'],\n  weekdays: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'],\n  weekdaysShort: ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'],\n  weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('sr', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli', 'augusti', 'september', 'oktober', 'november', 'december'],\n  monthsShort: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],\n  weekdays: ['söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag', 'lördag'],\n  weekdaysShort: ['sön', 'mån', 'tis', 'ons', 'tor', 'fre', 'lör'],\n  weekdaysMin: ['sö', 'må', 'ti', 'on', 'to', 'fr', 'lö'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('sv', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டெம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],\n  monthsShort: ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டெம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],\n  weekdays: ['ஞாயிற்றுக்கிழமை', 'திங்கட்கிழமை', 'செவ்வாய்கிழமை', 'புதன்கிழமை', 'வியாழக்கிழமை', 'வெள்ளிக்கிழமை', 'சனிக்கிழமை'],\n  weekdaysShort: ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],\n  weekdaysMin: ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 6\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('ta', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['జనవరి', 'ఫిబ్రవరి', 'మార్చి', 'ఏప్రిల్', 'మే', 'జూన్', 'జులై', 'ఆగస్టు', 'సెప్టెంబర్', 'అక్టోబర్', 'నవంబర్', 'డిసెంబర్'],\n  monthsShort: ['జన.', 'ఫిబ్ర.', 'మార్చి', 'ఏప్రి.', 'మే', 'జూన్', 'జులై', 'ఆగ.', 'సెప్.', 'అక్టో.', 'నవ.', 'డిసె.'],\n  weekdays: ['ఆదివారం', 'సోమవారం', 'మంగళవారం', 'బుధవారం', 'గురువారం', 'శుక్రవారం', 'శనివారం'],\n  weekdaysShort: ['ఆది', 'సోమ', 'మంగళ', 'బుధ', 'గురు', 'శుక్ర', 'శని'],\n  weekdaysMin: ['ఆ', 'సో', 'మం', 'బు', 'గు', 'శు', 'శ'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 6\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('te', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน', 'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม'],\n  monthsShort: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.', 'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.', 'พ.ย.', 'ธ.ค.'],\n  weekdays: ['อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัสบดี', 'ศุกร์', 'เสาร์'],\n  weekdaysShort: ['อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัส', 'ศุกร์', 'เสาร์'],\n  weekdaysMin: ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'],\n  firstDayOfWeek: 0,\n  firstWeekContainsDate: 6\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('th', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],\n  monthsShort: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem', 'Ağu', 'Eyl', 'Eki', 'Kas', 'Ara'],\n  weekdays: ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi'],\n  weekdaysShort: ['Paz', 'Pts', 'Sal', 'Çar', 'Per', 'Cum', 'Cts'],\n  weekdaysMin: ['Pz', 'Pt', 'Sa', 'Ça', 'Pe', 'Cu', 'Ct'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('tr', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل', 'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر', 'ئۆكتەبىر', 'نويابىر', 'دېكابىر'],\n  monthsShort: ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل', 'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر', 'ئۆكتەبىر', 'نويابىر', 'دېكابىر'],\n  weekdays: ['يەكشەنبە', 'دۈشەنبە', 'سەيشەنبە', 'چارشەنبە', 'پەيشەنبە', 'جۈمە', 'شەنبە'],\n  weekdaysShort: ['يە', 'دۈ', 'سە', 'چا', 'پە', 'جۈ', 'شە'],\n  weekdaysMin: ['يە', 'دۈ', 'سە', 'چا', 'پە', 'جۈ', 'شە'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('ug-cn', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['січень', 'лютий', 'березень', 'квітень', 'травень', 'червень', 'липень', 'серпень', 'вересень', 'жовтень', 'листопад', 'грудень'],\n  monthsShort: ['січ', 'лют', 'бер', 'квіт', 'трав', 'черв', 'лип', 'серп', 'вер', 'жовт', 'лист', 'груд'],\n  weekdays: ['неділя', 'понеділок', 'вівторок', 'середа', 'четвер', 'п’ятниця', 'субота'],\n  weekdaysShort: ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],\n  weekdaysMin: ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 7\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: true,\r\n};\r\nDatePicker.locale('uk', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['tháng 1', 'tháng 2', 'tháng 3', 'tháng 4', 'tháng 5', 'tháng 6', 'tháng 7', 'tháng 8', 'tháng 9', 'tháng 10', 'tháng 11', 'tháng 12'],\n  monthsShort: ['Th01', 'Th02', 'Th03', 'Th04', 'Th05', 'Th06', 'Th07', 'Th08', 'Th09', 'Th10', 'Th11', 'Th12'],\n  weekdays: ['chủ nhật', 'thứ hai', 'thứ ba', 'thứ tư', 'thứ năm', 'thứ sáu', 'thứ bảy'],\n  weekdaysShort: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],\n  weekdaysMin: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: false,\r\n};\r\nDatePicker.locale('vi', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],\n  monthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],\n  weekdays: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],\n  weekdaysShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],\n  weekdaysMin: ['日', '一', '二', '三', '四', '五', '六'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4,\n  meridiemParse: /上午|下午/,\n  meridiem: function meridiem(hour) {\n    if (hour < 12) {\n      return '上午';\n    }\n\n    return '下午';\n  },\n  isPM: function isPM(input) {\n    return input === '下午';\n  }\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY年',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: false,\r\n};\r\nDatePicker.locale('zh-cn', lang);\n\nexport { lang as default };\n","import DatePicker from 'vue-datepicker-next';\n\nvar locale = {\n  months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],\n  monthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],\n  weekdays: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],\n  weekdaysShort: ['週日', '週一', '週二', '週三', '週四', '週五', '週六'],\n  weekdaysMin: ['日', '一', '二', '三', '四', '五', '六'],\n  firstDayOfWeek: 1,\n  firstWeekContainsDate: 4,\n  meridiemParse: /上午|下午/,\n  meridiem: function meridiem(hour) {\n    if (hour < 12) {\n      return '上午';\n    }\n\n    return '下午';\n  },\n  isPM: function isPM(input) {\n    return input === '下午';\n  }\n};\n\nconst lang = {\r\n    formatLocale: locale,\r\n    yearFormat: 'YYYY年',\r\n    monthFormat: 'MMM',\r\n    monthBeforeYear: false,\r\n};\r\nDatePicker.locale('zh-tw', lang);\n\nexport { lang as default };\n","(function(window, factory) {\n\tvar lazySizes = factory(window, window.document, Date);\n\twindow.lazySizes = lazySizes;\n\tif(typeof module == 'object' && module.exports){\n\t\tmodule.exports = lazySizes;\n\t}\n}(typeof window != 'undefined' ?\n      window : {}, \n/**\n * import(\"./types/global\")\n * @typedef { import(\"./types/lazysizes-config\").LazySizesConfigPartial } LazySizesConfigPartial\n */\nfunction l(window, document, Date) { // Pass in the window Date function also for SSR because the Date class can be lost\n\t'use strict';\n\t/*jshint eqnull:true */\n\n\tvar lazysizes,\n\t\t/**\n\t\t * @type { LazySizesConfigPartial }\n\t\t */\n\t\tlazySizesCfg;\n\n\t(function(){\n\t\tvar prop;\n\n\t\tvar lazySizesDefaults = {\n\t\t\tlazyClass: 'lazyload',\n\t\t\tloadedClass: 'lazyloaded',\n\t\t\tloadingClass: 'lazyloading',\n\t\t\tpreloadClass: 'lazypreload',\n\t\t\terrorClass: 'lazyerror',\n\t\t\t//strictClass: 'lazystrict',\n\t\t\tautosizesClass: 'lazyautosizes',\n\t\t\tfastLoadedClass: 'ls-is-cached',\n\t\t\tiframeLoadMode: 0,\n\t\t\tsrcAttr: 'data-src',\n\t\t\tsrcsetAttr: 'data-srcset',\n\t\t\tsizesAttr: 'data-sizes',\n\t\t\t//preloadAfterLoad: false,\n\t\t\tminSize: 40,\n\t\t\tcustomMedia: {},\n\t\t\tinit: true,\n\t\t\texpFactor: 1.5,\n\t\t\thFac: 0.8,\n\t\t\tloadMode: 2,\n\t\t\tloadHidden: true,\n\t\t\tricTimeout: 0,\n\t\t\tthrottleDelay: 125,\n\t\t};\n\n\t\tlazySizesCfg = window.lazySizesConfig || window.lazysizesConfig || {};\n\n\t\tfor(prop in lazySizesDefaults){\n\t\t\tif(!(prop in lazySizesCfg)){\n\t\t\t\tlazySizesCfg[prop] = lazySizesDefaults[prop];\n\t\t\t}\n\t\t}\n\t})();\n\n\tif (!document || !document.getElementsByClassName) {\n\t\treturn {\n\t\t\tinit: function () {},\n\t\t\t/**\n\t\t\t * @type { LazySizesConfigPartial }\n\t\t\t */\n\t\t\tcfg: lazySizesCfg,\n\t\t\t/**\n\t\t\t * @type { true }\n\t\t\t */\n\t\t\tnoSupport: true,\n\t\t};\n\t}\n\n\tvar docElem = document.documentElement;\n\n\tvar supportPicture = window.HTMLPictureElement;\n\n\tvar _addEventListener = 'addEventListener';\n\n\tvar _getAttribute = 'getAttribute';\n\n\t/**\n\t * Update to bind to window because 'this' becomes null during SSR\n\t * builds.\n\t */\n\tvar addEventListener = window[_addEventListener].bind(window);\n\n\tvar setTimeout = window.setTimeout;\n\n\tvar requestAnimationFrame = window.requestAnimationFrame || setTimeout;\n\n\tvar requestIdleCallback = window.requestIdleCallback;\n\n\tvar regPicture = /^picture$/i;\n\n\tvar loadEvents = ['load', 'error', 'lazyincluded', '_lazyloaded'];\n\n\tvar regClassCache = {};\n\n\tvar forEach = Array.prototype.forEach;\n\n\t/**\n\t * @param ele {Element}\n\t * @param cls {string}\n\t */\n\tvar hasClass = function(ele, cls) {\n\t\tif(!regClassCache[cls]){\n\t\t\tregClassCache[cls] = new RegExp('(\\\\s|^)'+cls+'(\\\\s|$)');\n\t\t}\n\t\treturn regClassCache[cls].test(ele[_getAttribute]('class') || '') && regClassCache[cls];\n\t};\n\n\t/**\n\t * @param ele {Element}\n\t * @param cls {string}\n\t */\n\tvar addClass = function(ele, cls) {\n\t\tif (!hasClass(ele, cls)){\n\t\t\tele.setAttribute('class', (ele[_getAttribute]('class') || '').trim() + ' ' + cls);\n\t\t}\n\t};\n\n\t/**\n\t * @param ele {Element}\n\t * @param cls {string}\n\t */\n\tvar removeClass = function(ele, cls) {\n\t\tvar reg;\n\t\tif ((reg = hasClass(ele,cls))) {\n\t\t\tele.setAttribute('class', (ele[_getAttribute]('class') || '').replace(reg, ' '));\n\t\t}\n\t};\n\n\tvar addRemoveLoadEvents = function(dom, fn, add){\n\t\tvar action = add ? _addEventListener : 'removeEventListener';\n\t\tif(add){\n\t\t\taddRemoveLoadEvents(dom, fn);\n\t\t}\n\t\tloadEvents.forEach(function(evt){\n\t\t\tdom[action](evt, fn);\n\t\t});\n\t};\n\n\t/**\n\t * @param elem { Element }\n\t * @param name { string }\n\t * @param detail { any }\n\t * @param noBubbles { boolean }\n\t * @param noCancelable { boolean }\n\t * @returns { CustomEvent }\n\t */\n\tvar triggerEvent = function(elem, name, detail, noBubbles, noCancelable){\n\t\tvar event = document.createEvent('Event');\n\n\t\tif(!detail){\n\t\t\tdetail = {};\n\t\t}\n\n\t\tdetail.instance = lazysizes;\n\n\t\tevent.initEvent(name, !noBubbles, !noCancelable);\n\n\t\tevent.detail = detail;\n\n\t\telem.dispatchEvent(event);\n\t\treturn event;\n\t};\n\n\tvar updatePolyfill = function (el, full){\n\t\tvar polyfill;\n\t\tif( !supportPicture && ( polyfill = (window.picturefill || lazySizesCfg.pf) ) ){\n\t\t\tif(full && full.src && !el[_getAttribute]('srcset')){\n\t\t\t\tel.setAttribute('srcset', full.src);\n\t\t\t}\n\t\t\tpolyfill({reevaluate: true, elements: [el]});\n\t\t} else if(full && full.src){\n\t\t\tel.src = full.src;\n\t\t}\n\t};\n\n\tvar getCSS = function (elem, style){\n\t\treturn (getComputedStyle(elem, null) || {})[style];\n\t};\n\n\t/**\n\t *\n\t * @param elem { Element }\n\t * @param parent { Element }\n\t * @param [width] {number}\n\t * @returns {number}\n\t */\n\tvar getWidth = function(elem, parent, width){\n\t\twidth = width || elem.offsetWidth;\n\n\t\twhile(width < lazySizesCfg.minSize && parent && !elem._lazysizesWidth){\n\t\t\twidth =  parent.offsetWidth;\n\t\t\tparent = parent.parentNode;\n\t\t}\n\n\t\treturn width;\n\t};\n\n\tvar rAF = (function(){\n\t\tvar running, waiting;\n\t\tvar firstFns = [];\n\t\tvar secondFns = [];\n\t\tvar fns = firstFns;\n\n\t\tvar run = function(){\n\t\t\tvar runFns = fns;\n\n\t\t\tfns = firstFns.length ? secondFns : firstFns;\n\n\t\t\trunning = true;\n\t\t\twaiting = false;\n\n\t\t\twhile(runFns.length){\n\t\t\t\trunFns.shift()();\n\t\t\t}\n\n\t\t\trunning = false;\n\t\t};\n\n\t\tvar rafBatch = function(fn, queue){\n\t\t\tif(running && !queue){\n\t\t\t\tfn.apply(this, arguments);\n\t\t\t} else {\n\t\t\t\tfns.push(fn);\n\n\t\t\t\tif(!waiting){\n\t\t\t\t\twaiting = true;\n\t\t\t\t\t(document.hidden ? setTimeout : requestAnimationFrame)(run);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\trafBatch._lsFlush = run;\n\n\t\treturn rafBatch;\n\t})();\n\n\tvar rAFIt = function(fn, simple){\n\t\treturn simple ?\n\t\t\tfunction() {\n\t\t\t\trAF(fn);\n\t\t\t} :\n\t\t\tfunction(){\n\t\t\t\tvar that = this;\n\t\t\t\tvar args = arguments;\n\t\t\t\trAF(function(){\n\t\t\t\t\tfn.apply(that, args);\n\t\t\t\t});\n\t\t\t}\n\t\t;\n\t};\n\n\tvar throttle = function(fn){\n\t\tvar running;\n\t\tvar lastTime = 0;\n\t\tvar gDelay = lazySizesCfg.throttleDelay;\n\t\tvar rICTimeout = lazySizesCfg.ricTimeout;\n\t\tvar run = function(){\n\t\t\trunning = false;\n\t\t\tlastTime = Date.now();\n\t\t\tfn();\n\t\t};\n\t\tvar idleCallback = requestIdleCallback && rICTimeout > 49 ?\n\t\t\tfunction(){\n\t\t\t\trequestIdleCallback(run, {timeout: rICTimeout});\n\n\t\t\t\tif(rICTimeout !== lazySizesCfg.ricTimeout){\n\t\t\t\t\trICTimeout = lazySizesCfg.ricTimeout;\n\t\t\t\t}\n\t\t\t} :\n\t\t\trAFIt(function(){\n\t\t\t\tsetTimeout(run);\n\t\t\t}, true)\n\t\t;\n\n\t\treturn function(isPriority){\n\t\t\tvar delay;\n\n\t\t\tif((isPriority = isPriority === true)){\n\t\t\t\trICTimeout = 33;\n\t\t\t}\n\n\t\t\tif(running){\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\trunning =  true;\n\n\t\t\tdelay = gDelay - (Date.now() - lastTime);\n\n\t\t\tif(delay < 0){\n\t\t\t\tdelay = 0;\n\t\t\t}\n\n\t\t\tif(isPriority || delay < 9){\n\t\t\t\tidleCallback();\n\t\t\t} else {\n\t\t\t\tsetTimeout(idleCallback, delay);\n\t\t\t}\n\t\t};\n\t};\n\n\t//based on http://modernjavascript.blogspot.de/2013/08/building-better-debounce.html\n\tvar debounce = function(func) {\n\t\tvar timeout, timestamp;\n\t\tvar wait = 99;\n\t\tvar run = function(){\n\t\t\ttimeout = null;\n\t\t\tfunc();\n\t\t};\n\t\tvar later = function() {\n\t\t\tvar last = Date.now() - timestamp;\n\n\t\t\tif (last < wait) {\n\t\t\t\tsetTimeout(later, wait - last);\n\t\t\t} else {\n\t\t\t\t(requestIdleCallback || run)(run);\n\t\t\t}\n\t\t};\n\n\t\treturn function() {\n\t\t\ttimestamp = Date.now();\n\n\t\t\tif (!timeout) {\n\t\t\t\ttimeout = setTimeout(later, wait);\n\t\t\t}\n\t\t};\n\t};\n\n\tvar loader = (function(){\n\t\tvar preloadElems, isCompleted, resetPreloadingTimer, loadMode, started;\n\n\t\tvar eLvW, elvH, eLtop, eLleft, eLright, eLbottom, isBodyHidden;\n\n\t\tvar regImg = /^img$/i;\n\t\tvar regIframe = /^iframe$/i;\n\n\t\tvar supportScroll = ('onscroll' in window) && !(/(gle|ing)bot/.test(navigator.userAgent));\n\n\t\tvar shrinkExpand = 0;\n\t\tvar currentExpand = 0;\n\n\t\tvar isLoading = 0;\n\t\tvar lowRuns = -1;\n\n\t\tvar resetPreloading = function(e){\n\t\t\tisLoading--;\n\t\t\tif(!e || isLoading < 0 || !e.target){\n\t\t\t\tisLoading = 0;\n\t\t\t}\n\t\t};\n\n\t\tvar isVisible = function (elem) {\n\t\t\tif (isBodyHidden == null) {\n\t\t\t\tisBodyHidden = getCSS(document.body, 'visibility') == 'hidden';\n\t\t\t}\n\n\t\t\treturn isBodyHidden || !(getCSS(elem.parentNode, 'visibility') == 'hidden' && getCSS(elem, 'visibility') == 'hidden');\n\t\t};\n\n\t\tvar isNestedVisible = function(elem, elemExpand){\n\t\t\tvar outerRect;\n\t\t\tvar parent = elem;\n\t\t\tvar visible = isVisible(elem);\n\n\t\t\teLtop -= elemExpand;\n\t\t\teLbottom += elemExpand;\n\t\t\teLleft -= elemExpand;\n\t\t\teLright += elemExpand;\n\n\t\t\twhile(visible && (parent = parent.offsetParent) && parent != document.body && parent != docElem){\n\t\t\t\tvisible = ((getCSS(parent, 'opacity') || 1) > 0);\n\n\t\t\t\tif(visible && getCSS(parent, 'overflow') != 'visible'){\n\t\t\t\t\touterRect = parent.getBoundingClientRect();\n\t\t\t\t\tvisible = eLright > outerRect.left &&\n\t\t\t\t\t\teLleft < outerRect.right &&\n\t\t\t\t\t\teLbottom > outerRect.top - 1 &&\n\t\t\t\t\t\teLtop < outerRect.bottom + 1\n\t\t\t\t\t;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn visible;\n\t\t};\n\n\t\tvar checkElements = function() {\n\t\t\tvar eLlen, i, rect, autoLoadElem, loadedSomething, elemExpand, elemNegativeExpand, elemExpandVal,\n\t\t\t\tbeforeExpandVal, defaultExpand, preloadExpand, hFac;\n\t\t\tvar lazyloadElems = lazysizes.elements;\n\n\t\t\tif((loadMode = lazySizesCfg.loadMode) && isLoading < 8 && (eLlen = lazyloadElems.length)){\n\n\t\t\t\ti = 0;\n\n\t\t\t\tlowRuns++;\n\n\t\t\t\tfor(; i < eLlen; i++){\n\n\t\t\t\t\tif(!lazyloadElems[i] || lazyloadElems[i]._lazyRace){continue;}\n\n\t\t\t\t\tif(!supportScroll || (lazysizes.prematureUnveil && lazysizes.prematureUnveil(lazyloadElems[i]))){unveilElement(lazyloadElems[i]);continue;}\n\n\t\t\t\t\tif(!(elemExpandVal = lazyloadElems[i][_getAttribute]('data-expand')) || !(elemExpand = elemExpandVal * 1)){\n\t\t\t\t\t\telemExpand = currentExpand;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!defaultExpand) {\n\t\t\t\t\t\tdefaultExpand = (!lazySizesCfg.expand || lazySizesCfg.expand < 1) ?\n\t\t\t\t\t\t\tdocElem.clientHeight > 500 && docElem.clientWidth > 500 ? 500 : 370 :\n\t\t\t\t\t\t\tlazySizesCfg.expand;\n\n\t\t\t\t\t\tlazysizes._defEx = defaultExpand;\n\n\t\t\t\t\t\tpreloadExpand = defaultExpand * lazySizesCfg.expFactor;\n\t\t\t\t\t\thFac = lazySizesCfg.hFac;\n\t\t\t\t\t\tisBodyHidden = null;\n\n\t\t\t\t\t\tif(currentExpand < preloadExpand && isLoading < 1 && lowRuns > 2 && loadMode > 2 && !document.hidden){\n\t\t\t\t\t\t\tcurrentExpand = preloadExpand;\n\t\t\t\t\t\t\tlowRuns = 0;\n\t\t\t\t\t\t} else if(loadMode > 1 && lowRuns > 1 && isLoading < 6){\n\t\t\t\t\t\t\tcurrentExpand = defaultExpand;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcurrentExpand = shrinkExpand;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(beforeExpandVal !== elemExpand){\n\t\t\t\t\t\teLvW = innerWidth + (elemExpand * hFac);\n\t\t\t\t\t\telvH = innerHeight + elemExpand;\n\t\t\t\t\t\telemNegativeExpand = elemExpand * -1;\n\t\t\t\t\t\tbeforeExpandVal = elemExpand;\n\t\t\t\t\t}\n\n\t\t\t\t\trect = lazyloadElems[i].getBoundingClientRect();\n\n\t\t\t\t\tif ((eLbottom = rect.bottom) >= elemNegativeExpand &&\n\t\t\t\t\t\t(eLtop = rect.top) <= elvH &&\n\t\t\t\t\t\t(eLright = rect.right) >= elemNegativeExpand * hFac &&\n\t\t\t\t\t\t(eLleft = rect.left) <= eLvW &&\n\t\t\t\t\t\t(eLbottom || eLright || eLleft || eLtop) &&\n\t\t\t\t\t\t(lazySizesCfg.loadHidden || isVisible(lazyloadElems[i])) &&\n\t\t\t\t\t\t((isCompleted && isLoading < 3 && !elemExpandVal && (loadMode < 3 || lowRuns < 4)) || isNestedVisible(lazyloadElems[i], elemExpand))){\n\t\t\t\t\t\tunveilElement(lazyloadElems[i]);\n\t\t\t\t\t\tloadedSomething = true;\n\t\t\t\t\t\tif(isLoading > 9){break;}\n\t\t\t\t\t} else if(!loadedSomething && isCompleted && !autoLoadElem &&\n\t\t\t\t\t\tisLoading < 4 && lowRuns < 4 && loadMode > 2 &&\n\t\t\t\t\t\t(preloadElems[0] || lazySizesCfg.preloadAfterLoad) &&\n\t\t\t\t\t\t(preloadElems[0] || (!elemExpandVal && ((eLbottom || eLright || eLleft || eLtop) || lazyloadElems[i][_getAttribute](lazySizesCfg.sizesAttr) != 'auto')))){\n\t\t\t\t\t\tautoLoadElem = preloadElems[0] || lazyloadElems[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(autoLoadElem && !loadedSomething){\n\t\t\t\t\tunveilElement(autoLoadElem);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tvar throttledCheckElements = throttle(checkElements);\n\n\t\tvar switchLoadingClass = function(e){\n\t\t\tvar elem = e.target;\n\n\t\t\tif (elem._lazyCache) {\n\t\t\t\tdelete elem._lazyCache;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tresetPreloading(e);\n\t\t\taddClass(elem, lazySizesCfg.loadedClass);\n\t\t\tremoveClass(elem, lazySizesCfg.loadingClass);\n\t\t\taddRemoveLoadEvents(elem, rafSwitchLoadingClass);\n\t\t\ttriggerEvent(elem, 'lazyloaded');\n\t\t};\n\t\tvar rafedSwitchLoadingClass = rAFIt(switchLoadingClass);\n\t\tvar rafSwitchLoadingClass = function(e){\n\t\t\trafedSwitchLoadingClass({target: e.target});\n\t\t};\n\n\t\tvar changeIframeSrc = function(elem, src){\n\t\t\tvar loadMode = elem.getAttribute('data-load-mode') || lazySizesCfg.iframeLoadMode;\n\n\t\t\t// loadMode can be also a string!\n\t\t\tif (loadMode == 0) {\n\t\t\t\telem.contentWindow.location.replace(src);\n\t\t\t} else if (loadMode == 1) {\n\t\t\t\telem.src = src;\n\t\t\t}\n\t\t};\n\n\t\tvar handleSources = function(source){\n\t\t\tvar customMedia;\n\n\t\t\tvar sourceSrcset = source[_getAttribute](lazySizesCfg.srcsetAttr);\n\n\t\t\tif( (customMedia = lazySizesCfg.customMedia[source[_getAttribute]('data-media') || source[_getAttribute]('media')]) ){\n\t\t\t\tsource.setAttribute('media', customMedia);\n\t\t\t}\n\n\t\t\tif(sourceSrcset){\n\t\t\t\tsource.setAttribute('srcset', sourceSrcset);\n\t\t\t}\n\t\t};\n\n\t\tvar lazyUnveil = rAFIt(function (elem, detail, isAuto, sizes, isImg){\n\t\t\tvar src, srcset, parent, isPicture, event, firesLoad;\n\n\t\t\tif(!(event = triggerEvent(elem, 'lazybeforeunveil', detail)).defaultPrevented){\n\n\t\t\t\tif(sizes){\n\t\t\t\t\tif(isAuto){\n\t\t\t\t\t\taddClass(elem, lazySizesCfg.autosizesClass);\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.setAttribute('sizes', sizes);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsrcset = elem[_getAttribute](lazySizesCfg.srcsetAttr);\n\t\t\t\tsrc = elem[_getAttribute](lazySizesCfg.srcAttr);\n\n\t\t\t\tif(isImg) {\n\t\t\t\t\tparent = elem.parentNode;\n\t\t\t\t\tisPicture = parent && regPicture.test(parent.nodeName || '');\n\t\t\t\t}\n\n\t\t\t\tfiresLoad = detail.firesLoad || (('src' in elem) && (srcset || src || isPicture));\n\n\t\t\t\tevent = {target: elem};\n\n\t\t\t\taddClass(elem, lazySizesCfg.loadingClass);\n\n\t\t\t\tif(firesLoad){\n\t\t\t\t\tclearTimeout(resetPreloadingTimer);\n\t\t\t\t\tresetPreloadingTimer = setTimeout(resetPreloading, 2500);\n\t\t\t\t\taddRemoveLoadEvents(elem, rafSwitchLoadingClass, true);\n\t\t\t\t}\n\n\t\t\t\tif(isPicture){\n\t\t\t\t\tforEach.call(parent.getElementsByTagName('source'), handleSources);\n\t\t\t\t}\n\n\t\t\t\tif(srcset){\n\t\t\t\t\telem.setAttribute('srcset', srcset);\n\t\t\t\t} else if(src && !isPicture){\n\t\t\t\t\tif(regIframe.test(elem.nodeName)){\n\t\t\t\t\t\tchangeIframeSrc(elem, src);\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem.src = src;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(isImg && (srcset || isPicture)){\n\t\t\t\t\tupdatePolyfill(elem, {src: src});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(elem._lazyRace){\n\t\t\t\tdelete elem._lazyRace;\n\t\t\t}\n\t\t\tremoveClass(elem, lazySizesCfg.lazyClass);\n\n\t\t\trAF(function(){\n\t\t\t\t// Part of this can be removed as soon as this fix is older: https://bugs.chromium.org/p/chromium/issues/detail?id=7731 (2015)\n\t\t\t\tvar isLoaded = elem.complete && elem.naturalWidth > 1;\n\n\t\t\t\tif( !firesLoad || isLoaded){\n\t\t\t\t\tif (isLoaded) {\n\t\t\t\t\t\taddClass(elem, lazySizesCfg.fastLoadedClass);\n\t\t\t\t\t}\n\t\t\t\t\tswitchLoadingClass(event);\n\t\t\t\t\telem._lazyCache = true;\n\t\t\t\t\tsetTimeout(function(){\n\t\t\t\t\t\tif ('_lazyCache' in elem) {\n\t\t\t\t\t\t\tdelete elem._lazyCache;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 9);\n\t\t\t\t}\n\t\t\t\tif (elem.loading == 'lazy') {\n\t\t\t\t\tisLoading--;\n\t\t\t\t}\n\t\t\t}, true);\n\t\t});\n\n\t\t/**\n\t\t *\n\t\t * @param elem { Element }\n\t\t */\n\t\tvar unveilElement = function (elem){\n\t\t\tif (elem._lazyRace) {return;}\n\t\t\tvar detail;\n\n\t\t\tvar isImg = regImg.test(elem.nodeName);\n\n\t\t\t//allow using sizes=\"auto\", but don't use. it's invalid. Use data-sizes=\"auto\" or a valid value for sizes instead (i.e.: sizes=\"80vw\")\n\t\t\tvar sizes = isImg && (elem[_getAttribute](lazySizesCfg.sizesAttr) || elem[_getAttribute]('sizes'));\n\t\t\tvar isAuto = sizes == 'auto';\n\n\t\t\tif( (isAuto || !isCompleted) && isImg && (elem[_getAttribute]('src') || elem.srcset) && !elem.complete && !hasClass(elem, lazySizesCfg.errorClass) && hasClass(elem, lazySizesCfg.lazyClass)){return;}\n\n\t\t\tdetail = triggerEvent(elem, 'lazyunveilread').detail;\n\n\t\t\tif(isAuto){\n\t\t\t\t autoSizer.updateElem(elem, true, elem.offsetWidth);\n\t\t\t}\n\n\t\t\telem._lazyRace = true;\n\t\t\tisLoading++;\n\n\t\t\tlazyUnveil(elem, detail, isAuto, sizes, isImg);\n\t\t};\n\n\t\tvar afterScroll = debounce(function(){\n\t\t\tlazySizesCfg.loadMode = 3;\n\t\t\tthrottledCheckElements();\n\t\t});\n\n\t\tvar altLoadmodeScrollListner = function(){\n\t\t\tif(lazySizesCfg.loadMode == 3){\n\t\t\t\tlazySizesCfg.loadMode = 2;\n\t\t\t}\n\t\t\tafterScroll();\n\t\t};\n\n\t\tvar onload = function(){\n\t\t\tif(isCompleted){return;}\n\t\t\tif(Date.now() - started < 999){\n\t\t\t\tsetTimeout(onload, 999);\n\t\t\t\treturn;\n\t\t\t}\n\n\n\t\t\tisCompleted = true;\n\n\t\t\tlazySizesCfg.loadMode = 3;\n\n\t\t\tthrottledCheckElements();\n\n\t\t\taddEventListener('scroll', altLoadmodeScrollListner, true);\n\t\t};\n\n\t\treturn {\n\t\t\t_: function(){\n\t\t\t\tstarted = Date.now();\n\n\t\t\t\tlazysizes.elements = document.getElementsByClassName(lazySizesCfg.lazyClass);\n\t\t\t\tpreloadElems = document.getElementsByClassName(lazySizesCfg.lazyClass + ' ' + lazySizesCfg.preloadClass);\n\n\t\t\t\taddEventListener('scroll', throttledCheckElements, true);\n\n\t\t\t\taddEventListener('resize', throttledCheckElements, true);\n\n\t\t\t\taddEventListener('pageshow', function (e) {\n\t\t\t\t\tif (e.persisted) {\n\t\t\t\t\t\tvar loadingElements = document.querySelectorAll('.' + lazySizesCfg.loadingClass);\n\n\t\t\t\t\t\tif (loadingElements.length && loadingElements.forEach) {\n\t\t\t\t\t\t\trequestAnimationFrame(function () {\n\t\t\t\t\t\t\t\tloadingElements.forEach( function (img) {\n\t\t\t\t\t\t\t\t\tif (img.complete) {\n\t\t\t\t\t\t\t\t\t\tunveilElement(img);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif(window.MutationObserver){\n\t\t\t\t\tnew MutationObserver( throttledCheckElements ).observe( docElem, {childList: true, subtree: true, attributes: true} );\n\t\t\t\t} else {\n\t\t\t\t\tdocElem[_addEventListener]('DOMNodeInserted', throttledCheckElements, true);\n\t\t\t\t\tdocElem[_addEventListener]('DOMAttrModified', throttledCheckElements, true);\n\t\t\t\t\tsetInterval(throttledCheckElements, 999);\n\t\t\t\t}\n\n\t\t\t\taddEventListener('hashchange', throttledCheckElements, true);\n\n\t\t\t\t//, 'fullscreenchange'\n\t\t\t\t['focus', 'mouseover', 'click', 'load', 'transitionend', 'animationend'].forEach(function(name){\n\t\t\t\t\tdocument[_addEventListener](name, throttledCheckElements, true);\n\t\t\t\t});\n\n\t\t\t\tif((/d$|^c/.test(document.readyState))){\n\t\t\t\t\tonload();\n\t\t\t\t} else {\n\t\t\t\t\taddEventListener('load', onload);\n\t\t\t\t\tdocument[_addEventListener]('DOMContentLoaded', throttledCheckElements);\n\t\t\t\t\tsetTimeout(onload, 20000);\n\t\t\t\t}\n\n\t\t\t\tif(lazysizes.elements.length){\n\t\t\t\t\tcheckElements();\n\t\t\t\t\trAF._lsFlush();\n\t\t\t\t} else {\n\t\t\t\t\tthrottledCheckElements();\n\t\t\t\t}\n\t\t\t},\n\t\t\tcheckElems: throttledCheckElements,\n\t\t\tunveil: unveilElement,\n\t\t\t_aLSL: altLoadmodeScrollListner,\n\t\t};\n\t})();\n\n\n\tvar autoSizer = (function(){\n\t\tvar autosizesElems;\n\n\t\tvar sizeElement = rAFIt(function(elem, parent, event, width){\n\t\t\tvar sources, i, len;\n\t\t\telem._lazysizesWidth = width;\n\t\t\twidth += 'px';\n\n\t\t\telem.setAttribute('sizes', width);\n\n\t\t\tif(regPicture.test(parent.nodeName || '')){\n\t\t\t\tsources = parent.getElementsByTagName('source');\n\t\t\t\tfor(i = 0, len = sources.length; i < len; i++){\n\t\t\t\t\tsources[i].setAttribute('sizes', width);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(!event.detail.dataAttr){\n\t\t\t\tupdatePolyfill(elem, event.detail);\n\t\t\t}\n\t\t});\n\t\t/**\n\t\t *\n\t\t * @param elem {Element}\n\t\t * @param dataAttr\n\t\t * @param [width] { number }\n\t\t */\n\t\tvar getSizeElement = function (elem, dataAttr, width){\n\t\t\tvar event;\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif(parent){\n\t\t\t\twidth = getWidth(elem, parent, width);\n\t\t\t\tevent = triggerEvent(elem, 'lazybeforesizes', {width: width, dataAttr: !!dataAttr});\n\n\t\t\t\tif(!event.defaultPrevented){\n\t\t\t\t\twidth = event.detail.width;\n\n\t\t\t\t\tif(width && width !== elem._lazysizesWidth){\n\t\t\t\t\t\tsizeElement(elem, parent, event, width);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tvar updateElementsSizes = function(){\n\t\t\tvar i;\n\t\t\tvar len = autosizesElems.length;\n\t\t\tif(len){\n\t\t\t\ti = 0;\n\n\t\t\t\tfor(; i < len; i++){\n\t\t\t\t\tgetSizeElement(autosizesElems[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tvar debouncedUpdateElementsSizes = debounce(updateElementsSizes);\n\n\t\treturn {\n\t\t\t_: function(){\n\t\t\t\tautosizesElems = document.getElementsByClassName(lazySizesCfg.autosizesClass);\n\t\t\t\taddEventListener('resize', debouncedUpdateElementsSizes);\n\t\t\t},\n\t\t\tcheckElems: debouncedUpdateElementsSizes,\n\t\t\tupdateElem: getSizeElement\n\t\t};\n\t})();\n\n\tvar init = function(){\n\t\tif(!init.i && document.getElementsByClassName){\n\t\t\tinit.i = true;\n\t\t\tautoSizer._();\n\t\t\tloader._();\n\t\t}\n\t};\n\n\tsetTimeout(function(){\n\t\tif(lazySizesCfg.init){\n\t\t\tinit();\n\t\t}\n\t});\n\n\tlazysizes = {\n\t\t/**\n\t\t * @type { LazySizesConfigPartial }\n\t\t */\n\t\tcfg: lazySizesCfg,\n\t\tautoSizer: autoSizer,\n\t\tloader: loader,\n\t\tinit: init,\n\t\tuP: updatePolyfill,\n\t\taC: addClass,\n\t\trC: removeClass,\n\t\thC: hasClass,\n\t\tfire: triggerEvent,\n\t\tgW: getWidth,\n\t\trAF: rAF,\n\t};\n\n\treturn lazysizes;\n}\n));\n","export default \"data:text/javascript;base64,LyoqCiAqIEBsaWNzdGFydCBUaGUgZm9sbG93aW5nIGlzIHRoZSBlbnRpcmUgbGljZW5zZSBub3RpY2UgZm9yIHRoZQogKiBKYXZhU2NyaXB0IGNvZGUgaW4gdGhpcyBwYWdlCiAqCiAqIENvcHlyaWdodCAyMDI0IE1vemlsbGEgRm91bmRhdGlvbgogKgogKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgogKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKICoKICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKgogKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJUyIgQkFTSVMsCiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgogKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgogKgogKiBAbGljZW5kIFRoZSBhYm92ZSBpcyB0aGUgZW50aXJlIGxpY2Vuc2Ugbm90aWNlIGZvciB0aGUKICogSmF2YVNjcmlwdCBjb2RlIGluIHRoaXMgcGFnZQogKi8KCi8qKgogKiBwZGZqc1ZlcnNpb24gPSA1LjQuNjI0CiAqIHBkZmpzQnVpbGQgPSAzODRjNjIwOGIKICovCi8qKioqKiovIC8vIFRoZSByZXF1aXJlIHNjb3BlCi8qKioqKiovIHZhciBfX3dlYnBhY2tfcmVxdWlyZV9fID0ge307Ci8qKioqKiovIAovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwovKioqKioqLyAvKiB3ZWJwYWNrL3J1bnRpbWUvZGVmaW5lIHByb3BlcnR5IGdldHRlcnMgKi8KLyoqKioqKi8gKCgpID0+IHsKLyoqKioqKi8gCS8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb25zIGZvciBoYXJtb255IGV4cG9ydHMKLyoqKioqKi8gCV9fd2VicGFja19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7Ci8qKioqKiovIAkJZm9yKHZhciBrZXkgaW4gZGVmaW5pdGlvbikgewovKioqKioqLyAJCQlpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHsKLyoqKioqKi8gCQkJCU9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7Ci8qKioqKiovIAkJCX0KLyoqKioqKi8gCQl9Ci8qKioqKiovIAl9OwovKioqKioqLyB9KSgpOwovKioqKioqLyAKLyoqKioqKi8gLyogd2VicGFjay9ydW50aW1lL2hhc093blByb3BlcnR5IHNob3J0aGFuZCAqLwovKioqKioqLyAoKCkgPT4gewovKioqKioqLyAJX193ZWJwYWNrX3JlcXVpcmVfXy5vID0gKG9iaiwgcHJvcCkgPT4gKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKQovKioqKioqLyB9KSgpOwovKioqKioqLyAKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KdmFyIF9fd2VicGFja19leHBvcnRzX18gPSB7fTsKCjsvLyAuL3NyYy9zaGFyZWQvdXRpbC5qcwpjb25zdCBpc05vZGVKUyA9IHR5cGVvZiBwcm9jZXNzID09PSAib2JqZWN0IiAmJiBwcm9jZXNzICsgIiIgPT09ICJbb2JqZWN0IHByb2Nlc3NdIiAmJiAhcHJvY2Vzcy52ZXJzaW9ucy5udyAmJiAhKHByb2Nlc3MudmVyc2lvbnMuZWxlY3Ryb24gJiYgcHJvY2Vzcy50eXBlICYmIHByb2Nlc3MudHlwZSAhPT0gImJyb3dzZXIiKTsKY29uc3QgRk9OVF9JREVOVElUWV9NQVRSSVggPSBbMC4wMDEsIDAsIDAsIDAuMDAxLCAwLCAwXTsKY29uc3QgTElORV9GQUNUT1IgPSAxLjM1Owpjb25zdCBMSU5FX0RFU0NFTlRfRkFDVE9SID0gMC4zNTsKY29uc3QgQkFTRUxJTkVfRkFDVE9SID0gTElORV9ERVNDRU5UX0ZBQ1RPUiAvIExJTkVfRkFDVE9SOwpjb25zdCBSZW5kZXJpbmdJbnRlbnRGbGFnID0gewogIEFOWTogMHgwMSwKICBESVNQTEFZOiAweDAyLAogIFBSSU5UOiAweDA0LAogIFNBVkU6IDB4MDgsCiAgQU5OT1RBVElPTlNfRk9STVM6IDB4MTAsCiAgQU5OT1RBVElPTlNfU1RPUkFHRTogMHgyMCwKICBBTk5PVEFUSU9OU19ESVNBQkxFOiAweDQwLAogIElTX0VESVRJTkc6IDB4ODAsCiAgT1BMSVNUOiAweDEwMAp9Owpjb25zdCBBbm5vdGF0aW9uTW9kZSA9IHsKICBESVNBQkxFOiAwLAogIEVOQUJMRTogMSwKICBFTkFCTEVfRk9STVM6IDIsCiAgRU5BQkxFX1NUT1JBR0U6IDMKfTsKY29uc3QgQW5ub3RhdGlvbkVkaXRvclByZWZpeCA9ICJwZGZqc19pbnRlcm5hbF9lZGl0b3JfIjsKY29uc3QgQW5ub3RhdGlvbkVkaXRvclR5cGUgPSB7CiAgRElTQUJMRTogLTEsCiAgTk9ORTogMCwKICBGUkVFVEVYVDogMywKICBISUdITElHSFQ6IDksCiAgU1RBTVA6IDEzLAogIElOSzogMTUsCiAgUE9QVVA6IDE2LAogIFNJR05BVFVSRTogMTAxLAogIENPTU1FTlQ6IDEwMgp9Owpjb25zdCBBbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZSA9IHsKICBSRVNJWkU6IDEsCiAgQ1JFQVRFOiAyLAogIEZSRUVURVhUX1NJWkU6IDExLAogIEZSRUVURVhUX0NPTE9SOiAxMiwKICBGUkVFVEVYVF9PUEFDSVRZOiAxMywKICBJTktfQ09MT1I6IDIxLAogIElOS19USElDS05FU1M6IDIyLAogIElOS19PUEFDSVRZOiAyMywKICBISUdITElHSFRfQ09MT1I6IDMxLAogIEhJR0hMSUdIVF9USElDS05FU1M6IDMyLAogIEhJR0hMSUdIVF9GUkVFOiAzMywKICBISUdITElHSFRfU0hPV19BTEw6IDM0LAogIERSQVdfU1RFUDogNDEKfTsKY29uc3QgUGVybWlzc2lvbkZsYWcgPSB7CiAgUFJJTlQ6IDB4MDQsCiAgTU9ESUZZX0NPTlRFTlRTOiAweDA4LAogIENPUFk6IDB4MTAsCiAgTU9ESUZZX0FOTk9UQVRJT05TOiAweDIwLAogIEZJTExfSU5URVJBQ1RJVkVfRk9STVM6IDB4MTAwLAogIENPUFlfRk9SX0FDQ0VTU0lCSUxJVFk6IDB4MjAwLAogIEFTU0VNQkxFOiAweDQwMCwKICBQUklOVF9ISUdIX1FVQUxJVFk6IDB4ODAwCn07CmNvbnN0IE1lc2hGaWd1cmVUeXBlID0gewogIFRSSUFOR0xFUzogMSwKICBMQVRUSUNFOiAyLAogIFBBVENIOiAzCn07CmNvbnN0IFRleHRSZW5kZXJpbmdNb2RlID0gewogIEZJTEw6IDAsCiAgU1RST0tFOiAxLAogIEZJTExfU1RST0tFOiAyLAogIElOVklTSUJMRTogMywKICBGSUxMX0FERF9UT19QQVRIOiA0LAogIFNUUk9LRV9BRERfVE9fUEFUSDogNSwKICBGSUxMX1NUUk9LRV9BRERfVE9fUEFUSDogNiwKICBBRERfVE9fUEFUSDogNywKICBGSUxMX1NUUk9LRV9NQVNLOiAzLAogIEFERF9UT19QQVRIX0ZMQUc6IDQKfTsKY29uc3QgSW1hZ2VLaW5kID0gewogIEdSQVlTQ0FMRV8xQlBQOiAxLAogIFJHQl8yNEJQUDogMiwKICBSR0JBXzMyQlBQOiAzCn07CmNvbnN0IEFubm90YXRpb25UeXBlID0gewogIFRFWFQ6IDEsCiAgTElOSzogMiwKICBGUkVFVEVYVDogMywKICBMSU5FOiA0LAogIFNRVUFSRTogNSwKICBDSVJDTEU6IDYsCiAgUE9MWUdPTjogNywKICBQT0xZTElORTogOCwKICBISUdITElHSFQ6IDksCiAgVU5ERVJMSU5FOiAxMCwKICBTUVVJR0dMWTogMTEsCiAgU1RSSUtFT1VUOiAxMiwKICBTVEFNUDogMTMsCiAgQ0FSRVQ6IDE0LAogIElOSzogMTUsCiAgUE9QVVA6IDE2LAogIEZJTEVBVFRBQ0hNRU5UOiAxNywKICBTT1VORDogMTgsCiAgTU9WSUU6IDE5LAogIFdJREdFVDogMjAsCiAgU0NSRUVOOiAyMSwKICBQUklOVEVSTUFSSzogMjIsCiAgVFJBUE5FVDogMjMsCiAgV0FURVJNQVJLOiAyNCwKICBUSFJFRUQ6IDI1LAogIFJFREFDVDogMjYKfTsKY29uc3QgQW5ub3RhdGlvblJlcGx5VHlwZSA9IHsKICBHUk9VUDogIkdyb3VwIiwKICBSRVBMWTogIlIiCn07CmNvbnN0IEFubm90YXRpb25GbGFnID0gewogIElOVklTSUJMRTogMHgwMSwKICBISURERU46IDB4MDIsCiAgUFJJTlQ6IDB4MDQsCiAgTk9aT09NOiAweDA4LAogIE5PUk9UQVRFOiAweDEwLAogIE5PVklFVzogMHgyMCwKICBSRUFET05MWTogMHg0MCwKICBMT0NLRUQ6IDB4ODAsCiAgVE9HR0xFTk9WSUVXOiAweDEwMCwKICBMT0NLRURDT05URU5UUzogMHgyMDAKfTsKY29uc3QgQW5ub3RhdGlvbkZpZWxkRmxhZyA9IHsKICBSRUFET05MWTogMHgwMDAwMDAxLAogIFJFUVVJUkVEOiAweDAwMDAwMDIsCiAgTk9FWFBPUlQ6IDB4MDAwMDAwNCwKICBNVUxUSUxJTkU6IDB4MDAwMTAwMCwKICBQQVNTV09SRDogMHgwMDAyMDAwLAogIE5PVE9HR0xFVE9PRkY6IDB4MDAwNDAwMCwKICBSQURJTzogMHgwMDA4MDAwLAogIFBVU0hCVVRUT046IDB4MDAxMDAwMCwKICBDT01CTzogMHgwMDIwMDAwLAogIEVESVQ6IDB4MDA0MDAwMCwKICBTT1JUOiAweDAwODAwMDAsCiAgRklMRVNFTEVDVDogMHgwMTAwMDAwLAogIE1VTFRJU0VMRUNUOiAweDAyMDAwMDAsCiAgRE9OT1RTUEVMTENIRUNLOiAweDA0MDAwMDAsCiAgRE9OT1RTQ1JPTEw6IDB4MDgwMDAwMCwKICBDT01COiAweDEwMDAwMDAsCiAgUklDSFRFWFQ6IDB4MjAwMDAwMCwKICBSQURJT1NJTlVOSVNPTjogMHgyMDAwMDAwLAogIENPTU1JVE9OU0VMQ0hBTkdFOiAweDQwMDAwMDAKfTsKY29uc3QgQW5ub3RhdGlvbkJvcmRlclN0eWxlVHlwZSA9IHsKICBTT0xJRDogMSwKICBEQVNIRUQ6IDIsCiAgQkVWRUxFRDogMywKICBJTlNFVDogNCwKICBVTkRFUkxJTkU6IDUKfTsKY29uc3QgQW5ub3RhdGlvbkFjdGlvbkV2ZW50VHlwZSA9IHsKICBFOiAiTW91c2UgRW50ZXIiLAogIFg6ICJNb3VzZSBFeGl0IiwKICBEOiAiTW91c2UgRG93biIsCiAgVTogIk1vdXNlIFVwIiwKICBGbzogIkZvY3VzIiwKICBCbDogIkJsdXIiLAogIFBPOiAiUGFnZU9wZW4iLAogIFBDOiAiUGFnZUNsb3NlIiwKICBQVjogIlBhZ2VWaXNpYmxlIiwKICBQSTogIlBhZ2VJbnZpc2libGUiLAogIEs6ICJLZXlzdHJva2UiLAogIEY6ICJGb3JtYXQiLAogIFY6ICJWYWxpZGF0ZSIsCiAgQzogIkNhbGN1bGF0ZSIKfTsKY29uc3QgRG9jdW1lbnRBY3Rpb25FdmVudFR5cGUgPSB7CiAgV0M6ICJXaWxsQ2xvc2UiLAogIFdTOiAiV2lsbFNhdmUiLAogIERTOiAiRGlkU2F2ZSIsCiAgV1A6ICJXaWxsUHJpbnQiLAogIERQOiAiRGlkUHJpbnQiCn07CmNvbnN0IFBhZ2VBY3Rpb25FdmVudFR5cGUgPSB7CiAgTzogIlBhZ2VPcGVuIiwKICBDOiAiUGFnZUNsb3NlIgp9Owpjb25zdCBWZXJib3NpdHlMZXZlbCA9IHsKICBFUlJPUlM6IDAsCiAgV0FSTklOR1M6IDEsCiAgSU5GT1M6IDUKfTsKY29uc3QgT1BTID0gewogIGRlcGVuZGVuY3k6IDEsCiAgc2V0TGluZVdpZHRoOiAyLAogIHNldExpbmVDYXA6IDMsCiAgc2V0TGluZUpvaW46IDQsCiAgc2V0TWl0ZXJMaW1pdDogNSwKICBzZXREYXNoOiA2LAogIHNldFJlbmRlcmluZ0ludGVudDogNywKICBzZXRGbGF0bmVzczogOCwKICBzZXRHU3RhdGU6IDksCiAgc2F2ZTogMTAsCiAgcmVzdG9yZTogMTEsCiAgdHJhbnNmb3JtOiAxMiwKICBtb3ZlVG86IDEzLAogIGxpbmVUbzogMTQsCiAgY3VydmVUbzogMTUsCiAgY3VydmVUbzI6IDE2LAogIGN1cnZlVG8zOiAxNywKICBjbG9zZVBhdGg6IDE4LAogIHJlY3RhbmdsZTogMTksCiAgc3Ryb2tlOiAyMCwKICBjbG9zZVN0cm9rZTogMjEsCiAgZmlsbDogMjIsCiAgZW9GaWxsOiAyMywKICBmaWxsU3Ryb2tlOiAyNCwKICBlb0ZpbGxTdHJva2U6IDI1LAogIGNsb3NlRmlsbFN0cm9rZTogMjYsCiAgY2xvc2VFT0ZpbGxTdHJva2U6IDI3LAogIGVuZFBhdGg6IDI4LAogIGNsaXA6IDI5LAogIGVvQ2xpcDogMzAsCiAgYmVnaW5UZXh0OiAzMSwKICBlbmRUZXh0OiAzMiwKICBzZXRDaGFyU3BhY2luZzogMzMsCiAgc2V0V29yZFNwYWNpbmc6IDM0LAogIHNldEhTY2FsZTogMzUsCiAgc2V0TGVhZGluZzogMzYsCiAgc2V0Rm9udDogMzcsCiAgc2V0VGV4dFJlbmRlcmluZ01vZGU6IDM4LAogIHNldFRleHRSaXNlOiAzOSwKICBtb3ZlVGV4dDogNDAsCiAgc2V0TGVhZGluZ01vdmVUZXh0OiA0MSwKICBzZXRUZXh0TWF0cml4OiA0MiwKICBuZXh0TGluZTogNDMsCiAgc2hvd1RleHQ6IDQ0LAogIHNob3dTcGFjZWRUZXh0OiA0NSwKICBuZXh0TGluZVNob3dUZXh0OiA0NiwKICBuZXh0TGluZVNldFNwYWNpbmdTaG93VGV4dDogNDcsCiAgc2V0Q2hhcldpZHRoOiA0OCwKICBzZXRDaGFyV2lkdGhBbmRCb3VuZHM6IDQ5LAogIHNldFN0cm9rZUNvbG9yU3BhY2U6IDUwLAogIHNldEZpbGxDb2xvclNwYWNlOiA1MSwKICBzZXRTdHJva2VDb2xvcjogNTIsCiAgc2V0U3Ryb2tlQ29sb3JOOiA1MywKICBzZXRGaWxsQ29sb3I6IDU0LAogIHNldEZpbGxDb2xvck46IDU1LAogIHNldFN0cm9rZUdyYXk6IDU2LAogIHNldEZpbGxHcmF5OiA1NywKICBzZXRTdHJva2VSR0JDb2xvcjogNTgsCiAgc2V0RmlsbFJHQkNvbG9yOiA1OSwKICBzZXRTdHJva2VDTVlLQ29sb3I6IDYwLAogIHNldEZpbGxDTVlLQ29sb3I6IDYxLAogIHNoYWRpbmdGaWxsOiA2MiwKICBiZWdpbklubGluZUltYWdlOiA2MywKICBiZWdpbkltYWdlRGF0YTogNjQsCiAgZW5kSW5saW5lSW1hZ2U6IDY1LAogIHBhaW50WE9iamVjdDogNjYsCiAgbWFya1BvaW50OiA2NywKICBtYXJrUG9pbnRQcm9wczogNjgsCiAgYmVnaW5NYXJrZWRDb250ZW50OiA2OSwKICBiZWdpbk1hcmtlZENvbnRlbnRQcm9wczogNzAsCiAgZW5kTWFya2VkQ29udGVudDogNzEsCiAgYmVnaW5Db21wYXQ6IDcyLAogIGVuZENvbXBhdDogNzMsCiAgcGFpbnRGb3JtWE9iamVjdEJlZ2luOiA3NCwKICBwYWludEZvcm1YT2JqZWN0RW5kOiA3NSwKICBiZWdpbkdyb3VwOiA3NiwKICBlbmRHcm91cDogNzcsCiAgYmVnaW5Bbm5vdGF0aW9uOiA4MCwKICBlbmRBbm5vdGF0aW9uOiA4MSwKICBwYWludEltYWdlTWFza1hPYmplY3Q6IDgzLAogIHBhaW50SW1hZ2VNYXNrWE9iamVjdEdyb3VwOiA4NCwKICBwYWludEltYWdlWE9iamVjdDogODUsCiAgcGFpbnRJbmxpbmVJbWFnZVhPYmplY3Q6IDg2LAogIHBhaW50SW5saW5lSW1hZ2VYT2JqZWN0R3JvdXA6IDg3LAogIHBhaW50SW1hZ2VYT2JqZWN0UmVwZWF0OiA4OCwKICBwYWludEltYWdlTWFza1hPYmplY3RSZXBlYXQ6IDg5LAogIHBhaW50U29saWRDb2xvckltYWdlTWFzazogOTAsCiAgY29uc3RydWN0UGF0aDogOTEsCiAgc2V0U3Ryb2tlVHJhbnNwYXJlbnQ6IDkyLAogIHNldEZpbGxUcmFuc3BhcmVudDogOTMsCiAgcmF3RmlsbFBhdGg6IDk0Cn07CmNvbnN0IERyYXdPUFMgPSB7CiAgbW92ZVRvOiAwLAogIGxpbmVUbzogMSwKICBjdXJ2ZVRvOiAyLAogIHF1YWRyYXRpY0N1cnZlVG86IDMsCiAgY2xvc2VQYXRoOiA0Cn07CmNvbnN0IFBhc3N3b3JkUmVzcG9uc2VzID0gewogIE5FRURfUEFTU1dPUkQ6IDEsCiAgSU5DT1JSRUNUX1BBU1NXT1JEOiAyCn07CmxldCB2ZXJib3NpdHkgPSBWZXJib3NpdHlMZXZlbC5XQVJOSU5HUzsKZnVuY3Rpb24gc2V0VmVyYm9zaXR5TGV2ZWwobGV2ZWwpIHsKICBpZiAoTnVtYmVyLmlzSW50ZWdlcihsZXZlbCkpIHsKICAgIHZlcmJvc2l0eSA9IGxldmVsOwogIH0KfQpmdW5jdGlvbiBnZXRWZXJib3NpdHlMZXZlbCgpIHsKICByZXR1cm4gdmVyYm9zaXR5Owp9CmZ1bmN0aW9uIGluZm8obXNnKSB7CiAgaWYgKHZlcmJvc2l0eSA+PSBWZXJib3NpdHlMZXZlbC5JTkZPUykgewogICAgY29uc29sZS5pbmZvKGBJbmZvOiAke21zZ31gKTsKICB9Cn0KZnVuY3Rpb24gd2Fybihtc2cpIHsKICBpZiAodmVyYm9zaXR5ID49IFZlcmJvc2l0eUxldmVsLldBUk5JTkdTKSB7CiAgICBjb25zb2xlLndhcm4oYFdhcm5pbmc6ICR7bXNnfWApOwogIH0KfQpmdW5jdGlvbiB1bnJlYWNoYWJsZShtc2cpIHsKICB0aHJvdyBuZXcgRXJyb3IobXNnKTsKfQpmdW5jdGlvbiBhc3NlcnQoY29uZCwgbXNnKSB7CiAgaWYgKCFjb25kKSB7CiAgICB1bnJlYWNoYWJsZShtc2cpOwogIH0KfQpmdW5jdGlvbiBfaXNWYWxpZFByb3RvY29sKHVybCkgewogIHN3aXRjaCAodXJsPy5wcm90b2NvbCkgewogICAgY2FzZSAiaHR0cDoiOgogICAgY2FzZSAiaHR0cHM6IjoKICAgIGNhc2UgImZ0cDoiOgogICAgY2FzZSAibWFpbHRvOiI6CiAgICBjYXNlICJ0ZWw6IjoKICAgICAgcmV0dXJuIHRydWU7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gZmFsc2U7CiAgfQp9CmZ1bmN0aW9uIGNyZWF0ZVZhbGlkQWJzb2x1dGVVcmwodXJsLCBiYXNlVXJsID0gbnVsbCwgb3B0aW9ucyA9IG51bGwpIHsKICBpZiAoIXVybCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGlmIChvcHRpb25zICYmIHR5cGVvZiB1cmwgPT09ICJzdHJpbmciKSB7CiAgICBpZiAob3B0aW9ucy5hZGREZWZhdWx0UHJvdG9jb2wgJiYgdXJsLnN0YXJ0c1dpdGgoInd3dy4iKSkgewogICAgICBjb25zdCBkb3RzID0gdXJsLm1hdGNoKC9cLi9nKTsKICAgICAgaWYgKGRvdHM/Lmxlbmd0aCA+PSAyKSB7CiAgICAgICAgdXJsID0gYGh0dHA6Ly8ke3VybH1gOwogICAgICB9CiAgICB9CiAgICBpZiAob3B0aW9ucy50cnlDb252ZXJ0RW5jb2RpbmcpIHsKICAgICAgdHJ5IHsKICAgICAgICB1cmwgPSBzdHJpbmdUb1VURjhTdHJpbmcodXJsKTsKICAgICAgfSBjYXRjaCB7fQogICAgfQogIH0KICBjb25zdCBhYnNvbHV0ZVVybCA9IGJhc2VVcmwgPyBVUkwucGFyc2UodXJsLCBiYXNlVXJsKSA6IFVSTC5wYXJzZSh1cmwpOwogIHJldHVybiBfaXNWYWxpZFByb3RvY29sKGFic29sdXRlVXJsKSA/IGFic29sdXRlVXJsIDogbnVsbDsKfQpmdW5jdGlvbiB1cGRhdGVVcmxIYXNoKHVybCwgaGFzaCwgYWxsb3dSZWwgPSBmYWxzZSkgewogIGNvbnN0IHJlcyA9IFVSTC5wYXJzZSh1cmwpOwogIGlmIChyZXMpIHsKICAgIHJlcy5oYXNoID0gaGFzaDsKICAgIHJldHVybiByZXMuaHJlZjsKICB9CiAgaWYgKGFsbG93UmVsICYmIGNyZWF0ZVZhbGlkQWJzb2x1dGVVcmwodXJsLCAiaHR0cDovL2V4YW1wbGUuY29tIikpIHsKICAgIHJldHVybiB1cmwuc3BsaXQoIiMiLCAxKVswXSArIGAke2hhc2ggPyBgIyR7aGFzaH1gIDogIiJ9YDsKICB9CiAgcmV0dXJuICIiOwp9CmZ1bmN0aW9uIHNoYWRvdyhvYmosIHByb3AsIHZhbHVlLCBub25TZXJpYWxpemFibGUgPSBmYWxzZSkgewogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIHByb3AsIHsKICAgIHZhbHVlLAogICAgZW51bWVyYWJsZTogIW5vblNlcmlhbGl6YWJsZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgIHdyaXRhYmxlOiBmYWxzZQogIH0pOwogIHJldHVybiB2YWx1ZTsKfQpjb25zdCBCYXNlRXhjZXB0aW9uID0gZnVuY3Rpb24gQmFzZUV4Y2VwdGlvbkNsb3N1cmUoKSB7CiAgZnVuY3Rpb24gQmFzZUV4Y2VwdGlvbihtZXNzYWdlLCBuYW1lKSB7CiAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlOwogICAgdGhpcy5uYW1lID0gbmFtZTsKICB9CiAgQmFzZUV4Y2VwdGlvbi5wcm90b3R5cGUgPSBuZXcgRXJyb3IoKTsKICBCYXNlRXhjZXB0aW9uLmNvbnN0cnVjdG9yID0gQmFzZUV4Y2VwdGlvbjsKICByZXR1cm4gQmFzZUV4Y2VwdGlvbjsKfSgpOwpjbGFzcyBQYXNzd29yZEV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZywgY29kZSkgewogICAgc3VwZXIobXNnLCAiUGFzc3dvcmRFeGNlcHRpb24iKTsKICAgIHRoaXMuY29kZSA9IGNvZGU7CiAgfQp9CmNsYXNzIFVua25vd25FcnJvckV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZywgZGV0YWlscykgewogICAgc3VwZXIobXNnLCAiVW5rbm93bkVycm9yRXhjZXB0aW9uIik7CiAgICB0aGlzLmRldGFpbHMgPSBkZXRhaWxzOwogIH0KfQpjbGFzcyBJbnZhbGlkUERGRXhjZXB0aW9uIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJJbnZhbGlkUERGRXhjZXB0aW9uIik7CiAgfQp9CmNsYXNzIFJlc3BvbnNlRXhjZXB0aW9uIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnLCBzdGF0dXMsIG1pc3NpbmcpIHsKICAgIHN1cGVyKG1zZywgIlJlc3BvbnNlRXhjZXB0aW9uIik7CiAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgIHRoaXMubWlzc2luZyA9IG1pc3Npbmc7CiAgfQp9CmNsYXNzIEZvcm1hdEVycm9yIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJGb3JtYXRFcnJvciIpOwogIH0KfQpjbGFzcyBBYm9ydEV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIobXNnLCAiQWJvcnRFeGNlcHRpb24iKTsKICB9Cn0KZnVuY3Rpb24gYnl0ZXNUb1N0cmluZyhieXRlcykgewogIGlmICh0eXBlb2YgYnl0ZXMgIT09ICJvYmplY3QiIHx8IGJ5dGVzPy5sZW5ndGggPT09IHVuZGVmaW5lZCkgewogICAgdW5yZWFjaGFibGUoIkludmFsaWQgYXJndW1lbnQgZm9yIGJ5dGVzVG9TdHJpbmciKTsKICB9CiAgY29uc3QgbGVuZ3RoID0gYnl0ZXMubGVuZ3RoOwogIGNvbnN0IE1BWF9BUkdVTUVOVF9DT1VOVCA9IDgxOTI7CiAgaWYgKGxlbmd0aCA8IE1BWF9BUkdVTUVOVF9DT1VOVCkgewogICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgYnl0ZXMpOwogIH0KICBjb25zdCBzdHJCdWYgPSBbXTsKICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSBNQVhfQVJHVU1FTlRfQ09VTlQpIHsKICAgIGNvbnN0IGNodW5rRW5kID0gTWF0aC5taW4oaSArIE1BWF9BUkdVTUVOVF9DT1VOVCwgbGVuZ3RoKTsKICAgIGNvbnN0IGNodW5rID0gYnl0ZXMuc3ViYXJyYXkoaSwgY2h1bmtFbmQpOwogICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBjaHVuaykpOwogIH0KICByZXR1cm4gc3RyQnVmLmpvaW4oIiIpOwp9CmZ1bmN0aW9uIHN0cmluZ1RvQnl0ZXMoc3RyKSB7CiAgaWYgKHR5cGVvZiBzdHIgIT09ICJzdHJpbmciKSB7CiAgICB1bnJlYWNoYWJsZSgiSW52YWxpZCBhcmd1bWVudCBmb3Igc3RyaW5nVG9CeXRlcyIpOwogIH0KICBjb25zdCBsZW5ndGggPSBzdHIubGVuZ3RoOwogIGNvbnN0IGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoKTsKICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICBieXRlc1tpXSA9IHN0ci5jaGFyQ29kZUF0KGkpICYgMHhmZjsKICB9CiAgcmV0dXJuIGJ5dGVzOwp9CmZ1bmN0aW9uIHN0cmluZzMyKHZhbHVlKSB7CiAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUodmFsdWUgPj4gMjQgJiAweGZmLCB2YWx1ZSA+PiAxNiAmIDB4ZmYsIHZhbHVlID4+IDggJiAweGZmLCB2YWx1ZSAmIDB4ZmYpOwp9CmZ1bmN0aW9uIG9iamVjdFNpemUob2JqKSB7CiAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikubGVuZ3RoOwp9CmZ1bmN0aW9uIGlzTGl0dGxlRW5kaWFuKCkgewogIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheSg0KTsKICBidWZmZXI4WzBdID0gMTsKICBjb25zdCB2aWV3MzIgPSBuZXcgVWludDMyQXJyYXkoYnVmZmVyOC5idWZmZXIsIDAsIDEpOwogIHJldHVybiB2aWV3MzJbMF0gPT09IDE7Cn0KZnVuY3Rpb24gaXNFdmFsU3VwcG9ydGVkKCkgewogIHRyeSB7CiAgICBuZXcgRnVuY3Rpb24oIiIpOwogICAgcmV0dXJuIHRydWU7CiAgfSBjYXRjaCB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9CmNsYXNzIEZlYXR1cmVUZXN0IHsKICBzdGF0aWMgZ2V0IGlzTGl0dGxlRW5kaWFuKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiaXNMaXR0bGVFbmRpYW4iLCBpc0xpdHRsZUVuZGlhbigpKTsKICB9CiAgc3RhdGljIGdldCBpc0V2YWxTdXBwb3J0ZWQoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJpc0V2YWxTdXBwb3J0ZWQiLCBpc0V2YWxTdXBwb3J0ZWQoKSk7CiAgfQogIHN0YXRpYyBnZXQgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCIsIHR5cGVvZiBPZmZzY3JlZW5DYW52YXMgIT09ICJ1bmRlZmluZWQiKTsKICB9CiAgc3RhdGljIGdldCBpc0ltYWdlRGVjb2RlclN1cHBvcnRlZCgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgImlzSW1hZ2VEZWNvZGVyU3VwcG9ydGVkIiwgdHlwZW9mIEltYWdlRGVjb2RlciAhPT0gInVuZGVmaW5lZCIpOwogIH0KICBzdGF0aWMgZ2V0IGlzRmxvYXQxNkFycmF5U3VwcG9ydGVkKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiaXNGbG9hdDE2QXJyYXlTdXBwb3J0ZWQiLCB0eXBlb2YgRmxvYXQxNkFycmF5ICE9PSAidW5kZWZpbmVkIik7CiAgfQogIHN0YXRpYyBnZXQgaXNTYW5pdGl6ZXJTdXBwb3J0ZWQoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJpc1Nhbml0aXplclN1cHBvcnRlZCIsIHR5cGVvZiBTYW5pdGl6ZXIgIT09ICJ1bmRlZmluZWQiKTsKICB9CiAgc3RhdGljIGdldCBwbGF0Zm9ybSgpIHsKICAgIGNvbnN0IHsKICAgICAgcGxhdGZvcm0sCiAgICAgIHVzZXJBZ2VudAogICAgfSA9IG5hdmlnYXRvcjsKICAgIHJldHVybiBzaGFkb3codGhpcywgInBsYXRmb3JtIiwgewogICAgICBpc0FuZHJvaWQ6IHVzZXJBZ2VudC5pbmNsdWRlcygiQW5kcm9pZCIpLAogICAgICBpc0xpbnV4OiBwbGF0Zm9ybS5pbmNsdWRlcygiTGludXgiKSwKICAgICAgaXNNYWM6IHBsYXRmb3JtLmluY2x1ZGVzKCJNYWMiKSwKICAgICAgaXNXaW5kb3dzOiBwbGF0Zm9ybS5pbmNsdWRlcygiV2luIiksCiAgICAgIGlzRmlyZWZveDogdXNlckFnZW50LmluY2x1ZGVzKCJGaXJlZm94IikKICAgIH0pOwogIH0KICBzdGF0aWMgZ2V0IGlzQ1NTUm91bmRTdXBwb3J0ZWQoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJpc0NTU1JvdW5kU3VwcG9ydGVkIiwgZ2xvYmFsVGhpcy5DU1M/LnN1cHBvcnRzPy4oIndpZHRoOiByb3VuZCgxLjVweCwgMXB4KSIpKTsKICB9Cn0KY29uc3QgaGV4TnVtYmVycyA9IEFycmF5LmZyb20oQXJyYXkoMjU2KS5rZXlzKCksIG4gPT4gbi50b1N0cmluZygxNikucGFkU3RhcnQoMiwgIjAiKSk7CmNsYXNzIFV0aWwgewogIHN0YXRpYyBtYWtlSGV4Q29sb3IociwgZywgYikgewogICAgcmV0dXJuIGAjJHtoZXhOdW1iZXJzW3JdfSR7aGV4TnVtYmVyc1tnXX0ke2hleE51bWJlcnNbYl19YDsKICB9CiAgc3RhdGljIGRvbU1hdHJpeFRvVHJhbnNmb3JtKGRtKSB7CiAgICByZXR1cm4gW2RtLmEsIGRtLmIsIGRtLmMsIGRtLmQsIGRtLmUsIGRtLmZdOwogIH0KICBzdGF0aWMgc2NhbGVNaW5NYXgodHJhbnNmb3JtLCBtaW5NYXgpIHsKICAgIGxldCB0ZW1wOwogICAgaWYgKHRyYW5zZm9ybVswXSkgewogICAgICBpZiAodHJhbnNmb3JtWzBdIDwgMCkgewogICAgICAgIHRlbXAgPSBtaW5NYXhbMF07CiAgICAgICAgbWluTWF4WzBdID0gbWluTWF4WzJdOwogICAgICAgIG1pbk1heFsyXSA9IHRlbXA7CiAgICAgIH0KICAgICAgbWluTWF4WzBdICo9IHRyYW5zZm9ybVswXTsKICAgICAgbWluTWF4WzJdICo9IHRyYW5zZm9ybVswXTsKICAgICAgaWYgKHRyYW5zZm9ybVszXSA8IDApIHsKICAgICAgICB0ZW1wID0gbWluTWF4WzFdOwogICAgICAgIG1pbk1heFsxXSA9IG1pbk1heFszXTsKICAgICAgICBtaW5NYXhbM10gPSB0ZW1wOwogICAgICB9CiAgICAgIG1pbk1heFsxXSAqPSB0cmFuc2Zvcm1bM107CiAgICAgIG1pbk1heFszXSAqPSB0cmFuc2Zvcm1bM107CiAgICB9IGVsc2UgewogICAgICB0ZW1wID0gbWluTWF4WzBdOwogICAgICBtaW5NYXhbMF0gPSBtaW5NYXhbMV07CiAgICAgIG1pbk1heFsxXSA9IHRlbXA7CiAgICAgIHRlbXAgPSBtaW5NYXhbMl07CiAgICAgIG1pbk1heFsyXSA9IG1pbk1heFszXTsKICAgICAgbWluTWF4WzNdID0gdGVtcDsKICAgICAgaWYgKHRyYW5zZm9ybVsxXSA8IDApIHsKICAgICAgICB0ZW1wID0gbWluTWF4WzFdOwogICAgICAgIG1pbk1heFsxXSA9IG1pbk1heFszXTsKICAgICAgICBtaW5NYXhbM10gPSB0ZW1wOwogICAgICB9CiAgICAgIG1pbk1heFsxXSAqPSB0cmFuc2Zvcm1bMV07CiAgICAgIG1pbk1heFszXSAqPSB0cmFuc2Zvcm1bMV07CiAgICAgIGlmICh0cmFuc2Zvcm1bMl0gPCAwKSB7CiAgICAgICAgdGVtcCA9IG1pbk1heFswXTsKICAgICAgICBtaW5NYXhbMF0gPSBtaW5NYXhbMl07CiAgICAgICAgbWluTWF4WzJdID0gdGVtcDsKICAgICAgfQogICAgICBtaW5NYXhbMF0gKj0gdHJhbnNmb3JtWzJdOwogICAgICBtaW5NYXhbMl0gKj0gdHJhbnNmb3JtWzJdOwogICAgfQogICAgbWluTWF4WzBdICs9IHRyYW5zZm9ybVs0XTsKICAgIG1pbk1heFsxXSArPSB0cmFuc2Zvcm1bNV07CiAgICBtaW5NYXhbMl0gKz0gdHJhbnNmb3JtWzRdOwogICAgbWluTWF4WzNdICs9IHRyYW5zZm9ybVs1XTsKICB9CiAgc3RhdGljIHRyYW5zZm9ybShtMSwgbTIpIHsKICAgIHJldHVybiBbbTFbMF0gKiBtMlswXSArIG0xWzJdICogbTJbMV0sIG0xWzFdICogbTJbMF0gKyBtMVszXSAqIG0yWzFdLCBtMVswXSAqIG0yWzJdICsgbTFbMl0gKiBtMlszXSwgbTFbMV0gKiBtMlsyXSArIG0xWzNdICogbTJbM10sIG0xWzBdICogbTJbNF0gKyBtMVsyXSAqIG0yWzVdICsgbTFbNF0sIG0xWzFdICogbTJbNF0gKyBtMVszXSAqIG0yWzVdICsgbTFbNV1dOwogIH0KICBzdGF0aWMgbXVsdGlwbHlCeURPTU1hdHJpeChtLCBtZCkgewogICAgcmV0dXJuIFttWzBdICogbWQuYSArIG1bMl0gKiBtZC5iLCBtWzFdICogbWQuYSArIG1bM10gKiBtZC5iLCBtWzBdICogbWQuYyArIG1bMl0gKiBtZC5kLCBtWzFdICogbWQuYyArIG1bM10gKiBtZC5kLCBtWzBdICogbWQuZSArIG1bMl0gKiBtZC5mICsgbVs0XSwgbVsxXSAqIG1kLmUgKyBtWzNdICogbWQuZiArIG1bNV1dOwogIH0KICBzdGF0aWMgYXBwbHlUcmFuc2Zvcm0ocCwgbSwgcG9zID0gMCkgewogICAgY29uc3QgcDAgPSBwW3Bvc107CiAgICBjb25zdCBwMSA9IHBbcG9zICsgMV07CiAgICBwW3Bvc10gPSBwMCAqIG1bMF0gKyBwMSAqIG1bMl0gKyBtWzRdOwogICAgcFtwb3MgKyAxXSA9IHAwICogbVsxXSArIHAxICogbVszXSArIG1bNV07CiAgfQogIHN0YXRpYyBhcHBseVRyYW5zZm9ybVRvQmV6aWVyKHAsIHRyYW5zZm9ybSwgcG9zID0gMCkgewogICAgY29uc3QgbTAgPSB0cmFuc2Zvcm1bMF07CiAgICBjb25zdCBtMSA9IHRyYW5zZm9ybVsxXTsKICAgIGNvbnN0IG0yID0gdHJhbnNmb3JtWzJdOwogICAgY29uc3QgbTMgPSB0cmFuc2Zvcm1bM107CiAgICBjb25zdCBtNCA9IHRyYW5zZm9ybVs0XTsKICAgIGNvbnN0IG01ID0gdHJhbnNmb3JtWzVdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCA2OyBpICs9IDIpIHsKICAgICAgY29uc3QgcEkgPSBwW3BvcyArIGldOwogICAgICBjb25zdCBwSTEgPSBwW3BvcyArIGkgKyAxXTsKICAgICAgcFtwb3MgKyBpXSA9IHBJICogbTAgKyBwSTEgKiBtMiArIG00OwogICAgICBwW3BvcyArIGkgKyAxXSA9IHBJICogbTEgKyBwSTEgKiBtMyArIG01OwogICAgfQogIH0KICBzdGF0aWMgYXBwbHlJbnZlcnNlVHJhbnNmb3JtKHAsIG0pIHsKICAgIGNvbnN0IHAwID0gcFswXTsKICAgIGNvbnN0IHAxID0gcFsxXTsKICAgIGNvbnN0IGQgPSBtWzBdICogbVszXSAtIG1bMV0gKiBtWzJdOwogICAgcFswXSA9IChwMCAqIG1bM10gLSBwMSAqIG1bMl0gKyBtWzJdICogbVs1XSAtIG1bNF0gKiBtWzNdKSAvIGQ7CiAgICBwWzFdID0gKC1wMCAqIG1bMV0gKyBwMSAqIG1bMF0gKyBtWzRdICogbVsxXSAtIG1bNV0gKiBtWzBdKSAvIGQ7CiAgfQogIHN0YXRpYyBheGlhbEFsaWduZWRCb3VuZGluZ0JveChyZWN0LCB0cmFuc2Zvcm0sIG91dHB1dCkgewogICAgY29uc3QgbTAgPSB0cmFuc2Zvcm1bMF07CiAgICBjb25zdCBtMSA9IHRyYW5zZm9ybVsxXTsKICAgIGNvbnN0IG0yID0gdHJhbnNmb3JtWzJdOwogICAgY29uc3QgbTMgPSB0cmFuc2Zvcm1bM107CiAgICBjb25zdCBtNCA9IHRyYW5zZm9ybVs0XTsKICAgIGNvbnN0IG01ID0gdHJhbnNmb3JtWzVdOwogICAgY29uc3QgcjAgPSByZWN0WzBdOwogICAgY29uc3QgcjEgPSByZWN0WzFdOwogICAgY29uc3QgcjIgPSByZWN0WzJdOwogICAgY29uc3QgcjMgPSByZWN0WzNdOwogICAgbGV0IGEwID0gbTAgKiByMCArIG00OwogICAgbGV0IGEyID0gYTA7CiAgICBsZXQgYTEgPSBtMCAqIHIyICsgbTQ7CiAgICBsZXQgYTMgPSBhMTsKICAgIGxldCBiMCA9IG0zICogcjEgKyBtNTsKICAgIGxldCBiMiA9IGIwOwogICAgbGV0IGIxID0gbTMgKiByMyArIG01OwogICAgbGV0IGIzID0gYjE7CiAgICBpZiAobTEgIT09IDAgfHwgbTIgIT09IDApIHsKICAgICAgY29uc3QgbTFyMCA9IG0xICogcjA7CiAgICAgIGNvbnN0IG0xcjIgPSBtMSAqIHIyOwogICAgICBjb25zdCBtMnIxID0gbTIgKiByMTsKICAgICAgY29uc3QgbTJyMyA9IG0yICogcjM7CiAgICAgIGEwICs9IG0ycjE7CiAgICAgIGEzICs9IG0ycjE7CiAgICAgIGExICs9IG0ycjM7CiAgICAgIGEyICs9IG0ycjM7CiAgICAgIGIwICs9IG0xcjA7CiAgICAgIGIzICs9IG0xcjA7CiAgICAgIGIxICs9IG0xcjI7CiAgICAgIGIyICs9IG0xcjI7CiAgICB9CiAgICBvdXRwdXRbMF0gPSBNYXRoLm1pbihvdXRwdXRbMF0sIGEwLCBhMSwgYTIsIGEzKTsKICAgIG91dHB1dFsxXSA9IE1hdGgubWluKG91dHB1dFsxXSwgYjAsIGIxLCBiMiwgYjMpOwogICAgb3V0cHV0WzJdID0gTWF0aC5tYXgob3V0cHV0WzJdLCBhMCwgYTEsIGEyLCBhMyk7CiAgICBvdXRwdXRbM10gPSBNYXRoLm1heChvdXRwdXRbM10sIGIwLCBiMSwgYjIsIGIzKTsKICB9CiAgc3RhdGljIGludmVyc2VUcmFuc2Zvcm0obSkgewogICAgY29uc3QgZCA9IG1bMF0gKiBtWzNdIC0gbVsxXSAqIG1bMl07CiAgICByZXR1cm4gW21bM10gLyBkLCAtbVsxXSAvIGQsIC1tWzJdIC8gZCwgbVswXSAvIGQsIChtWzJdICogbVs1XSAtIG1bNF0gKiBtWzNdKSAvIGQsIChtWzRdICogbVsxXSAtIG1bNV0gKiBtWzBdKSAvIGRdOwogIH0KICBzdGF0aWMgc2luZ3VsYXJWYWx1ZURlY29tcG9zZTJkU2NhbGUobWF0cml4LCBvdXRwdXQpIHsKICAgIGNvbnN0IG0wID0gbWF0cml4WzBdOwogICAgY29uc3QgbTEgPSBtYXRyaXhbMV07CiAgICBjb25zdCBtMiA9IG1hdHJpeFsyXTsKICAgIGNvbnN0IG0zID0gbWF0cml4WzNdOwogICAgY29uc3QgYSA9IG0wICoqIDIgKyBtMSAqKiAyOwogICAgY29uc3QgYiA9IG0wICogbTIgKyBtMSAqIG0zOwogICAgY29uc3QgYyA9IG0yICoqIDIgKyBtMyAqKiAyOwogICAgY29uc3QgZmlyc3QgPSAoYSArIGMpIC8gMjsKICAgIGNvbnN0IHNlY29uZCA9IE1hdGguc3FydChmaXJzdCAqKiAyIC0gKGEgKiBjIC0gYiAqKiAyKSk7CiAgICBvdXRwdXRbMF0gPSBNYXRoLnNxcnQoZmlyc3QgKyBzZWNvbmQgfHwgMSk7CiAgICBvdXRwdXRbMV0gPSBNYXRoLnNxcnQoZmlyc3QgLSBzZWNvbmQgfHwgMSk7CiAgfQogIHN0YXRpYyBub3JtYWxpemVSZWN0KHJlY3QpIHsKICAgIGNvbnN0IHIgPSByZWN0LnNsaWNlKDApOwogICAgaWYgKHJlY3RbMF0gPiByZWN0WzJdKSB7CiAgICAgIHJbMF0gPSByZWN0WzJdOwogICAgICByWzJdID0gcmVjdFswXTsKICAgIH0KICAgIGlmIChyZWN0WzFdID4gcmVjdFszXSkgewogICAgICByWzFdID0gcmVjdFszXTsKICAgICAgclszXSA9IHJlY3RbMV07CiAgICB9CiAgICByZXR1cm4gcjsKICB9CiAgc3RhdGljIGludGVyc2VjdChyZWN0MSwgcmVjdDIpIHsKICAgIGNvbnN0IHhMb3cgPSBNYXRoLm1heChNYXRoLm1pbihyZWN0MVswXSwgcmVjdDFbMl0pLCBNYXRoLm1pbihyZWN0MlswXSwgcmVjdDJbMl0pKTsKICAgIGNvbnN0IHhIaWdoID0gTWF0aC5taW4oTWF0aC5tYXgocmVjdDFbMF0sIHJlY3QxWzJdKSwgTWF0aC5tYXgocmVjdDJbMF0sIHJlY3QyWzJdKSk7CiAgICBpZiAoeExvdyA+IHhIaWdoKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgeUxvdyA9IE1hdGgubWF4KE1hdGgubWluKHJlY3QxWzFdLCByZWN0MVszXSksIE1hdGgubWluKHJlY3QyWzFdLCByZWN0MlszXSkpOwogICAgY29uc3QgeUhpZ2ggPSBNYXRoLm1pbihNYXRoLm1heChyZWN0MVsxXSwgcmVjdDFbM10pLCBNYXRoLm1heChyZWN0MlsxXSwgcmVjdDJbM10pKTsKICAgIGlmICh5TG93ID4geUhpZ2gpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gW3hMb3csIHlMb3csIHhIaWdoLCB5SGlnaF07CiAgfQogIHN0YXRpYyBwb2ludEJvdW5kaW5nQm94KHgsIHksIG1pbk1heCkgewogICAgbWluTWF4WzBdID0gTWF0aC5taW4obWluTWF4WzBdLCB4KTsKICAgIG1pbk1heFsxXSA9IE1hdGgubWluKG1pbk1heFsxXSwgeSk7CiAgICBtaW5NYXhbMl0gPSBNYXRoLm1heChtaW5NYXhbMl0sIHgpOwogICAgbWluTWF4WzNdID0gTWF0aC5tYXgobWluTWF4WzNdLCB5KTsKICB9CiAgc3RhdGljIHJlY3RCb3VuZGluZ0JveCh4MCwgeTAsIHgxLCB5MSwgbWluTWF4KSB7CiAgICBtaW5NYXhbMF0gPSBNYXRoLm1pbihtaW5NYXhbMF0sIHgwLCB4MSk7CiAgICBtaW5NYXhbMV0gPSBNYXRoLm1pbihtaW5NYXhbMV0sIHkwLCB5MSk7CiAgICBtaW5NYXhbMl0gPSBNYXRoLm1heChtaW5NYXhbMl0sIHgwLCB4MSk7CiAgICBtaW5NYXhbM10gPSBNYXRoLm1heChtaW5NYXhbM10sIHkwLCB5MSk7CiAgfQogIHN0YXRpYyAjZ2V0RXh0cmVtdW1PbkN1cnZlKHgwLCB4MSwgeDIsIHgzLCB5MCwgeTEsIHkyLCB5MywgdCwgbWluTWF4KSB7CiAgICBpZiAodCA8PSAwIHx8IHQgPj0gMSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBtdCA9IDEgLSB0OwogICAgY29uc3QgdHQgPSB0ICogdDsKICAgIGNvbnN0IHR0dCA9IHR0ICogdDsKICAgIGNvbnN0IHggPSBtdCAqIChtdCAqIChtdCAqIHgwICsgMyAqIHQgKiB4MSkgKyAzICogdHQgKiB4MikgKyB0dHQgKiB4MzsKICAgIGNvbnN0IHkgPSBtdCAqIChtdCAqIChtdCAqIHkwICsgMyAqIHQgKiB5MSkgKyAzICogdHQgKiB5MikgKyB0dHQgKiB5MzsKICAgIG1pbk1heFswXSA9IE1hdGgubWluKG1pbk1heFswXSwgeCk7CiAgICBtaW5NYXhbMV0gPSBNYXRoLm1pbihtaW5NYXhbMV0sIHkpOwogICAgbWluTWF4WzJdID0gTWF0aC5tYXgobWluTWF4WzJdLCB4KTsKICAgIG1pbk1heFszXSA9IE1hdGgubWF4KG1pbk1heFszXSwgeSk7CiAgfQogIHN0YXRpYyAjZ2V0RXh0cmVtdW0oeDAsIHgxLCB4MiwgeDMsIHkwLCB5MSwgeTIsIHkzLCBhLCBiLCBjLCBtaW5NYXgpIHsKICAgIGlmIChNYXRoLmFicyhhKSA8IDFlLTEyKSB7CiAgICAgIGlmIChNYXRoLmFicyhiKSA+PSAxZS0xMikgewogICAgICAgIHRoaXMuI2dldEV4dHJlbXVtT25DdXJ2ZSh4MCwgeDEsIHgyLCB4MywgeTAsIHkxLCB5MiwgeTMsIC1jIC8gYiwgbWluTWF4KTsKICAgICAgfQogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBkZWx0YSA9IGIgKiogMiAtIDQgKiBjICogYTsKICAgIGlmIChkZWx0YSA8IDApIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgc3FydERlbHRhID0gTWF0aC5zcXJ0KGRlbHRhKTsKICAgIGNvbnN0IGEyID0gMiAqIGE7CiAgICB0aGlzLiNnZXRFeHRyZW11bU9uQ3VydmUoeDAsIHgxLCB4MiwgeDMsIHkwLCB5MSwgeTIsIHkzLCAoLWIgKyBzcXJ0RGVsdGEpIC8gYTIsIG1pbk1heCk7CiAgICB0aGlzLiNnZXRFeHRyZW11bU9uQ3VydmUoeDAsIHgxLCB4MiwgeDMsIHkwLCB5MSwgeTIsIHkzLCAoLWIgLSBzcXJ0RGVsdGEpIC8gYTIsIG1pbk1heCk7CiAgfQogIHN0YXRpYyBiZXppZXJCb3VuZGluZ0JveCh4MCwgeTAsIHgxLCB5MSwgeDIsIHkyLCB4MywgeTMsIG1pbk1heCkgewogICAgbWluTWF4WzBdID0gTWF0aC5taW4obWluTWF4WzBdLCB4MCwgeDMpOwogICAgbWluTWF4WzFdID0gTWF0aC5taW4obWluTWF4WzFdLCB5MCwgeTMpOwogICAgbWluTWF4WzJdID0gTWF0aC5tYXgobWluTWF4WzJdLCB4MCwgeDMpOwogICAgbWluTWF4WzNdID0gTWF0aC5tYXgobWluTWF4WzNdLCB5MCwgeTMpOwogICAgdGhpcy4jZ2V0RXh0cmVtdW0oeDAsIHgxLCB4MiwgeDMsIHkwLCB5MSwgeTIsIHkzLCAzICogKC14MCArIDMgKiAoeDEgLSB4MikgKyB4MyksIDYgKiAoeDAgLSAyICogeDEgKyB4MiksIDMgKiAoeDEgLSB4MCksIG1pbk1heCk7CiAgICB0aGlzLiNnZXRFeHRyZW11bSh4MCwgeDEsIHgyLCB4MywgeTAsIHkxLCB5MiwgeTMsIDMgKiAoLXkwICsgMyAqICh5MSAtIHkyKSArIHkzKSwgNiAqICh5MCAtIDIgKiB5MSArIHkyKSwgMyAqICh5MSAtIHkwKSwgbWluTWF4KTsKICB9Cn0KY29uc3QgUERGU3RyaW5nVHJhbnNsYXRlVGFibGUgPSBbMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMHgyZDgsIDB4MmM3LCAweDJjNiwgMHgyZDksIDB4MmRkLCAweDJkYiwgMHgyZGEsIDB4MmRjLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAweDIwMjIsIDB4MjAyMCwgMHgyMDIxLCAweDIwMjYsIDB4MjAxNCwgMHgyMDEzLCAweDE5MiwgMHgyMDQ0LCAweDIwMzksIDB4MjAzYSwgMHgyMjEyLCAweDIwMzAsIDB4MjAxZSwgMHgyMDFjLCAweDIwMWQsIDB4MjAxOCwgMHgyMDE5LCAweDIwMWEsIDB4MjEyMiwgMHhmYjAxLCAweGZiMDIsIDB4MTQxLCAweDE1MiwgMHgxNjAsIDB4MTc4LCAweDE3ZCwgMHgxMzEsIDB4MTQyLCAweDE1MywgMHgxNjEsIDB4MTdlLCAwLCAweDIwYWNdOwpmdW5jdGlvbiBzdHJpbmdUb1BERlN0cmluZyhzdHIsIGtlZXBFc2NhcGVTZXF1ZW5jZSA9IGZhbHNlKSB7CiAgaWYgKHN0clswXSA+PSAiXHhFRiIpIHsKICAgIGxldCBlbmNvZGluZzsKICAgIGlmIChzdHJbMF0gPT09ICJceEZFIiAmJiBzdHJbMV0gPT09ICJceEZGIikgewogICAgICBlbmNvZGluZyA9ICJ1dGYtMTZiZSI7CiAgICAgIGlmIChzdHIubGVuZ3RoICUgMiA9PT0gMSkgewogICAgICAgIHN0ciA9IHN0ci5zbGljZSgwLCAtMSk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoc3RyWzBdID09PSAiXHhGRiIgJiYgc3RyWzFdID09PSAiXHhGRSIpIHsKICAgICAgZW5jb2RpbmcgPSAidXRmLTE2bGUiOwogICAgICBpZiAoc3RyLmxlbmd0aCAlIDIgPT09IDEpIHsKICAgICAgICBzdHIgPSBzdHIuc2xpY2UoMCwgLTEpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKHN0clswXSA9PT0gIlx4RUYiICYmIHN0clsxXSA9PT0gIlx4QkIiICYmIHN0clsyXSA9PT0gIlx4QkYiKSB7CiAgICAgIGVuY29kaW5nID0gInV0Zi04IjsKICAgIH0KICAgIGlmIChlbmNvZGluZykgewogICAgICB0cnkgewogICAgICAgIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoZW5jb2RpbmcsIHsKICAgICAgICAgIGZhdGFsOiB0cnVlCiAgICAgICAgfSk7CiAgICAgICAgY29uc3QgYnVmZmVyID0gc3RyaW5nVG9CeXRlcyhzdHIpOwogICAgICAgIGNvbnN0IGRlY29kZWQgPSBkZWNvZGVyLmRlY29kZShidWZmZXIpOwogICAgICAgIGlmIChrZWVwRXNjYXBlU2VxdWVuY2UgfHwgIWRlY29kZWQuaW5jbHVkZXMoIlx4MWIiKSkgewogICAgICAgICAgcmV0dXJuIGRlY29kZWQ7CiAgICAgICAgfQogICAgICAgIHJldHVybiBkZWNvZGVkLnJlcGxhY2VBbGwoL1x4MWJbXlx4MWJdKig/Olx4MWJ8JCkvZywgIiIpOwogICAgICB9IGNhdGNoIChleCkgewogICAgICAgIHdhcm4oYHN0cmluZ1RvUERGU3RyaW5nOiAiJHtleH0iLmApOwogICAgICB9CiAgICB9CiAgfQogIGNvbnN0IHN0ckJ1ZiA9IFtdOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHN0ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCBjaGFyQ29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpOwogICAgaWYgKCFrZWVwRXNjYXBlU2VxdWVuY2UgJiYgY2hhckNvZGUgPT09IDB4MWIpIHsKICAgICAgd2hpbGUgKCsraSA8IGlpICYmIHN0ci5jaGFyQ29kZUF0KGkpICE9PSAweDFiKSB7fQogICAgICBjb250aW51ZTsKICAgIH0KICAgIGNvbnN0IGNvZGUgPSBQREZTdHJpbmdUcmFuc2xhdGVUYWJsZVtjaGFyQ29kZV07CiAgICBzdHJCdWYucHVzaChjb2RlID8gU3RyaW5nLmZyb21DaGFyQ29kZShjb2RlKSA6IHN0ci5jaGFyQXQoaSkpOwogIH0KICByZXR1cm4gc3RyQnVmLmpvaW4oIiIpOwp9CmZ1bmN0aW9uIHN0cmluZ1RvVVRGOFN0cmluZyhzdHIpIHsKICByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KGVzY2FwZShzdHIpKTsKfQpmdW5jdGlvbiB1dGY4U3RyaW5nVG9TdHJpbmcoc3RyKSB7CiAgcmV0dXJuIHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChzdHIpKTsKfQpmdW5jdGlvbiBpc0FycmF5RXF1YWwoYXJyMSwgYXJyMikgewogIGlmIChhcnIxLmxlbmd0aCAhPT0gYXJyMi5sZW5ndGgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gYXJyMS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBpZiAoYXJyMVtpXSAhPT0gYXJyMltpXSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgfQogIHJldHVybiB0cnVlOwp9CmZ1bmN0aW9uIGdldE1vZGlmaWNhdGlvbkRhdGUoZGF0ZSA9IG5ldyBEYXRlKCkpIHsKICBpZiAoIShkYXRlIGluc3RhbmNlb2YgRGF0ZSkpIHsKICAgIGRhdGUgPSBuZXcgRGF0ZShkYXRlKTsKICB9CiAgY29uc3QgYnVmZmVyID0gW2RhdGUuZ2V0VVRDRnVsbFllYXIoKS50b1N0cmluZygpLCAoZGF0ZS5nZXRVVENNb250aCgpICsgMSkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAiMCIpLCBkYXRlLmdldFVUQ0RhdGUoKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIiksIGRhdGUuZ2V0VVRDSG91cnMoKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIiksIGRhdGUuZ2V0VVRDTWludXRlcygpLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKSwgZGF0ZS5nZXRVVENTZWNvbmRzKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAiMCIpXTsKICByZXR1cm4gYnVmZmVyLmpvaW4oIiIpOwp9CmxldCBOb3JtYWxpemVSZWdleCA9IG51bGw7CmxldCBOb3JtYWxpemF0aW9uTWFwID0gbnVsbDsKZnVuY3Rpb24gbm9ybWFsaXplVW5pY29kZShzdHIpIHsKICBpZiAoIU5vcm1hbGl6ZVJlZ2V4KSB7CiAgICBOb3JtYWxpemVSZWdleCA9IC8oW1x1MDBhMFx1MDBiNVx1MDM3ZVx1MGViM1x1MjAwMC1cdTIwMGFcdTIwMmZcdTIxMjZcdWZiMDAtXHVmYjA0XHVmYjA2XHVmYjIwLVx1ZmIzNlx1ZmIzOC1cdWZiM2NcdWZiM2VcdWZiNDAtXHVmYjQxXHVmYjQzLVx1ZmI0NFx1ZmI0Ni1cdWZiYTFcdWZiYTQtXHVmYmE5XHVmYmFlLVx1ZmJiMVx1ZmJkMy1cdWZiZGNcdWZiZGUtXHVmYmU3XHVmYmVhLVx1ZmJmOFx1ZmJmYy1cdWZiZmRcdWZjMDAtXHVmYzVkXHVmYzY0LVx1ZmNmMVx1ZmNmNS1cdWZkM2RcdWZkODhcdWZkZjRcdWZkZmEtXHVmZGZiXHVmZTcxXHVmZTc3XHVmZTc5XHVmZTdiXHVmZTdkXSspfChcdWZiMDUrKS9ndTsKICAgIE5vcm1hbGl6YXRpb25NYXAgPSBuZXcgTWFwKFtbIu+shSIsICLFv3QiXV0pOwogIH0KICByZXR1cm4gc3RyLnJlcGxhY2VBbGwoTm9ybWFsaXplUmVnZXgsIChfLCBwMSwgcDIpID0+IHAxID8gcDEubm9ybWFsaXplKCJORktDIikgOiBOb3JtYWxpemF0aW9uTWFwLmdldChwMikpOwp9CmZ1bmN0aW9uIGdldFV1aWQoKSB7CiAgaWYgKHR5cGVvZiBjcnlwdG8ucmFuZG9tVVVJRCA9PT0gImZ1bmN0aW9uIikgewogICAgcmV0dXJuIGNyeXB0by5yYW5kb21VVUlEKCk7CiAgfQogIGNvbnN0IGJ1ZiA9IG5ldyBVaW50OEFycmF5KDMyKTsKICBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGJ1Zik7CiAgcmV0dXJuIGJ5dGVzVG9TdHJpbmcoYnVmKTsKfQpjb25zdCBBbm5vdGF0aW9uUHJlZml4ID0gInBkZmpzX2ludGVybmFsX2lkXyI7CmZ1bmN0aW9uIF9pc1ZhbGlkRXhwbGljaXREZXN0KHZhbGlkUmVmLCB2YWxpZE5hbWUsIGRlc3QpIHsKICBpZiAoIUFycmF5LmlzQXJyYXkoZGVzdCkgfHwgZGVzdC5sZW5ndGggPCAyKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGNvbnN0IFtwYWdlLCB6b29tLCAuLi5hcmdzXSA9IGRlc3Q7CiAgaWYgKCF2YWxpZFJlZihwYWdlKSAmJiAhTnVtYmVyLmlzSW50ZWdlcihwYWdlKSkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBpZiAoIXZhbGlkTmFtZSh6b29tKSkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBjb25zdCBhcmdzTGVuID0gYXJncy5sZW5ndGg7CiAgbGV0IGFsbG93TnVsbCA9IHRydWU7CiAgc3dpdGNoICh6b29tLm5hbWUpIHsKICAgIGNhc2UgIlhZWiI6CiAgICAgIGlmIChhcmdzTGVuIDwgMiB8fCBhcmdzTGVuID4gMykgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBicmVhazsKICAgIGNhc2UgIkZpdCI6CiAgICBjYXNlICJGaXRCIjoKICAgICAgcmV0dXJuIGFyZ3NMZW4gPT09IDA7CiAgICBjYXNlICJGaXRIIjoKICAgIGNhc2UgIkZpdEJIIjoKICAgIGNhc2UgIkZpdFYiOgogICAgY2FzZSAiRml0QlYiOgogICAgICBpZiAoYXJnc0xlbiA+IDEpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgYnJlYWs7CiAgICBjYXNlICJGaXRSIjoKICAgICAgaWYgKGFyZ3NMZW4gIT09IDQpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgYWxsb3dOdWxsID0gZmFsc2U7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgcmV0dXJuIGZhbHNlOwogIH0KICBmb3IgKGNvbnN0IGFyZyBvZiBhcmdzKSB7CiAgICBpZiAodHlwZW9mIGFyZyA9PT0gIm51bWJlciIgfHwgYWxsb3dOdWxsICYmIGFyZyA9PT0gbnVsbCkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9CiAgcmV0dXJuIHRydWU7Cn0KZnVuY3Rpb24gTWF0aENsYW1wKHYsIG1pbiwgbWF4KSB7CiAgcmV0dXJuIE1hdGgubWluKE1hdGgubWF4KHYsIG1pbiksIG1heCk7Cn0KaWYgKHR5cGVvZiBNYXRoLnN1bVByZWNpc2UgIT09ICJmdW5jdGlvbiIpIHsKICBNYXRoLnN1bVByZWNpc2UgPSBmdW5jdGlvbiAobnVtYmVycykgewogICAgcmV0dXJuIG51bWJlcnMucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCk7CiAgfTsKfQoKOy8vIC4vc3JjL2NvcmUvcHJpbWl0aXZlcy5qcwoKY29uc3QgQ0lSQ1VMQVJfUkVGID0gU3ltYm9sKCJDSVJDVUxBUl9SRUYiKTsKY29uc3QgRU9GID0gU3ltYm9sKCJFT0YiKTsKbGV0IENtZENhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKbGV0IE5hbWVDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CmxldCBSZWZDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CmZ1bmN0aW9uIGNsZWFyUHJpbWl0aXZlQ2FjaGVzKCkgewogIENtZENhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBOYW1lQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIFJlZkNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKfQpjbGFzcyBOYW1lIHsKICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICB0aGlzLm5hbWUgPSBuYW1lOwogIH0KICBzdGF0aWMgZ2V0KG5hbWUpIHsKICAgIHJldHVybiBOYW1lQ2FjaGVbbmFtZV0gfHw9IG5ldyBOYW1lKG5hbWUpOwogIH0KfQpjbGFzcyBDbWQgewogIGNvbnN0cnVjdG9yKGNtZCkgewogICAgdGhpcy5jbWQgPSBjbWQ7CiAgfQogIHN0YXRpYyBnZXQoY21kKSB7CiAgICByZXR1cm4gQ21kQ2FjaGVbY21kXSB8fD0gbmV3IENtZChjbWQpOwogIH0KfQpjb25zdCBub25TZXJpYWxpemFibGUgPSBmdW5jdGlvbiBub25TZXJpYWxpemFibGVDbG9zdXJlKCkgewogIHJldHVybiBub25TZXJpYWxpemFibGU7Cn07CmNsYXNzIERpY3QgewogIGNvbnN0cnVjdG9yKHhyZWYgPSBudWxsKSB7CiAgICB0aGlzLl9tYXAgPSBuZXcgTWFwKCk7CiAgICB0aGlzLnhyZWYgPSB4cmVmOwogICAgdGhpcy5vYmpJZCA9IG51bGw7CiAgICB0aGlzLnN1cHByZXNzRW5jcnlwdGlvbiA9IGZhbHNlOwogICAgdGhpcy5fX25vblNlcmlhbGl6YWJsZV9fID0gbm9uU2VyaWFsaXphYmxlOwogIH0KICBhc3NpZ25YcmVmKG5ld1hyZWYpIHsKICAgIHRoaXMueHJlZiA9IG5ld1hyZWY7CiAgfQogIGdldCBzaXplKCkgewogICAgcmV0dXJuIHRoaXMuX21hcC5zaXplOwogIH0KICBnZXQoa2V5MSwga2V5Miwga2V5MykgewogICAgbGV0IHZhbHVlID0gdGhpcy5fbWFwLmdldChrZXkxKTsKICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIGtleTIgIT09IHVuZGVmaW5lZCkgewogICAgICB2YWx1ZSA9IHRoaXMuX21hcC5nZXQoa2V5Mik7CiAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIGtleTMgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhbHVlID0gdGhpcy5fbWFwLmdldChrZXkzKTsKICAgICAgfQogICAgfQogICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgUmVmICYmIHRoaXMueHJlZikgewogICAgICByZXR1cm4gdGhpcy54cmVmLmZldGNoKHZhbHVlLCB0aGlzLnN1cHByZXNzRW5jcnlwdGlvbik7CiAgICB9CiAgICByZXR1cm4gdmFsdWU7CiAgfQogIGFzeW5jIGdldEFzeW5jKGtleTEsIGtleTIsIGtleTMpIHsKICAgIGxldCB2YWx1ZSA9IHRoaXMuX21hcC5nZXQoa2V5MSk7CiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiBrZXkyICE9PSB1bmRlZmluZWQpIHsKICAgICAgdmFsdWUgPSB0aGlzLl9tYXAuZ2V0KGtleTIpOwogICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiBrZXkzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB2YWx1ZSA9IHRoaXMuX21hcC5nZXQoa2V5Myk7CiAgICAgIH0KICAgIH0KICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFJlZiAmJiB0aGlzLnhyZWYpIHsKICAgICAgcmV0dXJuIHRoaXMueHJlZi5mZXRjaEFzeW5jKHZhbHVlLCB0aGlzLnN1cHByZXNzRW5jcnlwdGlvbik7CiAgICB9CiAgICByZXR1cm4gdmFsdWU7CiAgfQogIGdldEFycmF5KGtleTEsIGtleTIsIGtleTMpIHsKICAgIGxldCB2YWx1ZSA9IHRoaXMuX21hcC5nZXQoa2V5MSk7CiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiBrZXkyICE9PSB1bmRlZmluZWQpIHsKICAgICAgdmFsdWUgPSB0aGlzLl9tYXAuZ2V0KGtleTIpOwogICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiBrZXkzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB2YWx1ZSA9IHRoaXMuX21hcC5nZXQoa2V5Myk7CiAgICAgIH0KICAgIH0KICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFJlZiAmJiB0aGlzLnhyZWYpIHsKICAgICAgdmFsdWUgPSB0aGlzLnhyZWYuZmV0Y2godmFsdWUsIHRoaXMuc3VwcHJlc3NFbmNyeXB0aW9uKTsKICAgIH0KICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkgewogICAgICB2YWx1ZSA9IHZhbHVlLnNsaWNlKCk7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHZhbHVlLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBpZiAodmFsdWVbaV0gaW5zdGFuY2VvZiBSZWYgJiYgdGhpcy54cmVmKSB7CiAgICAgICAgICB2YWx1ZVtpXSA9IHRoaXMueHJlZi5mZXRjaCh2YWx1ZVtpXSwgdGhpcy5zdXBwcmVzc0VuY3J5cHRpb24pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHZhbHVlOwogIH0KICBnZXRSYXcoa2V5KSB7CiAgICByZXR1cm4gdGhpcy5fbWFwLmdldChrZXkpOwogIH0KICBnZXRLZXlzKCkgewogICAgcmV0dXJuIFsuLi50aGlzLl9tYXAua2V5cygpXTsKICB9CiAgZ2V0UmF3VmFsdWVzKCkgewogICAgcmV0dXJuIFsuLi50aGlzLl9tYXAudmFsdWVzKCldOwogIH0KICBnZXRSYXdFbnRyaWVzKCkgewogICAgcmV0dXJuIHRoaXMuX21hcC5lbnRyaWVzKCk7CiAgfQogIHNldChrZXksIHZhbHVlKSB7CiAgICB0aGlzLl9tYXAuc2V0KGtleSwgdmFsdWUpOwogIH0KICBzZXRJZk5vdEV4aXN0cyhrZXksIHZhbHVlKSB7CiAgICBpZiAoIXRoaXMuaGFzKGtleSkpIHsKICAgICAgdGhpcy5zZXQoa2V5LCB2YWx1ZSk7CiAgICB9CiAgfQogIHNldElmTnVtYmVyKGtleSwgdmFsdWUpIHsKICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJudW1iZXIiKSB7CiAgICAgIHRoaXMuc2V0KGtleSwgdmFsdWUpOwogICAgfQogIH0KICBzZXRJZkFycmF5KGtleSwgdmFsdWUpIHsKICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSB8fCBBcnJheUJ1ZmZlci5pc1ZpZXcodmFsdWUpKSB7CiAgICAgIHRoaXMuc2V0KGtleSwgdmFsdWUpOwogICAgfQogIH0KICBzZXRJZkRlZmluZWQoa2V5LCB2YWx1ZSkgewogICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwpIHsKICAgICAgdGhpcy5zZXQoa2V5LCB2YWx1ZSk7CiAgICB9CiAgfQogIHNldElmTmFtZShrZXksIHZhbHVlKSB7CiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAic3RyaW5nIikgewogICAgICB0aGlzLnNldChrZXksIE5hbWUuZ2V0KHZhbHVlKSk7CiAgICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgTmFtZSkgewogICAgICB0aGlzLnNldChrZXksIHZhbHVlKTsKICAgIH0KICB9CiAgc2V0SWZEaWN0KGtleSwgdmFsdWUpIHsKICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgdGhpcy5zZXQoa2V5LCB2YWx1ZSk7CiAgICB9CiAgfQogIGhhcyhrZXkpIHsKICAgIHJldHVybiB0aGlzLl9tYXAuaGFzKGtleSk7CiAgfQogICpbU3ltYm9sLml0ZXJhdG9yXSgpIHsKICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIHRoaXMuX21hcCkgewogICAgICB5aWVsZCBba2V5LCB2YWx1ZSBpbnN0YW5jZW9mIFJlZiAmJiB0aGlzLnhyZWYgPyB0aGlzLnhyZWYuZmV0Y2godmFsdWUsIHRoaXMuc3VwcHJlc3NFbmNyeXB0aW9uKSA6IHZhbHVlXTsKICAgIH0KICB9CiAgc3RhdGljIGdldCBlbXB0eSgpIHsKICAgIGNvbnN0IGVtcHR5RGljdCA9IG5ldyBEaWN0KG51bGwpOwogICAgZW1wdHlEaWN0LnNldCA9IChrZXksIHZhbHVlKSA9PiB7CiAgICAgIHVucmVhY2hhYmxlKCJTaG91bGQgbm90IGNhbGwgYHNldGAgb24gdGhlIGVtcHR5IGRpY3Rpb25hcnkuIik7CiAgICB9OwogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiZW1wdHkiLCBlbXB0eURpY3QpOwogIH0KICBzdGF0aWMgbWVyZ2UoewogICAgeHJlZiwKICAgIGRpY3RBcnJheSwKICAgIG1lcmdlU3ViRGljdHMgPSBmYWxzZQogIH0pIHsKICAgIGNvbnN0IG1lcmdlZERpY3QgPSBuZXcgRGljdCh4cmVmKSwKICAgICAgcHJvcGVydGllcyA9IG5ldyBNYXAoKTsKICAgIGZvciAoY29uc3QgZGljdCBvZiBkaWN0QXJyYXkpIHsKICAgICAgaWYgKCEoZGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgZGljdC5fbWFwKSB7CiAgICAgICAgbGV0IHByb3BlcnR5ID0gcHJvcGVydGllcy5nZXQoa2V5KTsKICAgICAgICBpZiAocHJvcGVydHkgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcHJvcGVydHkgPSBbXTsKICAgICAgICAgIHByb3BlcnRpZXMuc2V0KGtleSwgcHJvcGVydHkpOwogICAgICAgIH0gZWxzZSBpZiAoIW1lcmdlU3ViRGljdHMgfHwgISh2YWx1ZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgcHJvcGVydHkucHVzaCh2YWx1ZSk7CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgW25hbWUsIHZhbHVlc10gb2YgcHJvcGVydGllcykgewogICAgICBpZiAodmFsdWVzLmxlbmd0aCA9PT0gMSB8fCAhKHZhbHVlc1swXSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgbWVyZ2VkRGljdC5fbWFwLnNldChuYW1lLCB2YWx1ZXNbMF0pOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IHN1YkRpY3QgPSBuZXcgRGljdCh4cmVmKTsKICAgICAgZm9yIChjb25zdCBkaWN0IG9mIHZhbHVlcykgewogICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIGRpY3QuX21hcCkgewogICAgICAgICAgaWYgKCFzdWJEaWN0Ll9tYXAuaGFzKGtleSkpIHsKICAgICAgICAgICAgc3ViRGljdC5fbWFwLnNldChrZXksIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHN1YkRpY3Quc2l6ZSA+IDApIHsKICAgICAgICBtZXJnZWREaWN0Ll9tYXAuc2V0KG5hbWUsIHN1YkRpY3QpOwogICAgICB9CiAgICB9CiAgICBwcm9wZXJ0aWVzLmNsZWFyKCk7CiAgICByZXR1cm4gbWVyZ2VkRGljdC5zaXplID4gMCA/IG1lcmdlZERpY3QgOiBEaWN0LmVtcHR5OwogIH0KICBjbG9uZSgpIHsKICAgIGNvbnN0IGRpY3QgPSBuZXcgRGljdCh0aGlzLnhyZWYpOwogICAgZm9yIChjb25zdCBrZXkgb2YgdGhpcy5nZXRLZXlzKCkpIHsKICAgICAgZGljdC5zZXQoa2V5LCB0aGlzLmdldFJhdyhrZXkpKTsKICAgIH0KICAgIHJldHVybiBkaWN0OwogIH0KICBkZWxldGUoa2V5KSB7CiAgICB0aGlzLl9tYXAuZGVsZXRlKGtleSk7CiAgfQp9CmNsYXNzIFJlZiB7CiAgY29uc3RydWN0b3IobnVtLCBnZW4pIHsKICAgIHRoaXMubnVtID0gbnVtOwogICAgdGhpcy5nZW4gPSBnZW47CiAgfQogIHRvU3RyaW5nKCkgewogICAgaWYgKHRoaXMuZ2VuID09PSAwKSB7CiAgICAgIHJldHVybiBgJHt0aGlzLm51bX1SYDsKICAgIH0KICAgIHJldHVybiBgJHt0aGlzLm51bX1SJHt0aGlzLmdlbn1gOwogIH0KICBzdGF0aWMgZnJvbVN0cmluZyhzdHIpIHsKICAgIGNvbnN0IHJlZiA9IFJlZkNhY2hlW3N0cl07CiAgICBpZiAocmVmKSB7CiAgICAgIHJldHVybiByZWY7CiAgICB9CiAgICBjb25zdCBtID0gL14oXGQrKVIoXGQqKSQvLmV4ZWMoc3RyKTsKICAgIGlmICghbSB8fCBtWzFdID09PSAiMCIpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gUmVmQ2FjaGVbc3RyXSA9IG5ldyBSZWYocGFyc2VJbnQobVsxXSksICFtWzJdID8gMCA6IHBhcnNlSW50KG1bMl0pKTsKICB9CiAgc3RhdGljIGdldChudW0sIGdlbikgewogICAgY29uc3Qga2V5ID0gZ2VuID09PSAwID8gYCR7bnVtfVJgIDogYCR7bnVtfVIke2dlbn1gOwogICAgcmV0dXJuIFJlZkNhY2hlW2tleV0gfHw9IG5ldyBSZWYobnVtLCBnZW4pOwogIH0KfQpjbGFzcyBSZWZTZXQgewogIGNvbnN0cnVjdG9yKHBhcmVudCA9IG51bGwpIHsKICAgIHRoaXMuX3NldCA9IG5ldyBTZXQocGFyZW50Py5fc2V0KTsKICB9CiAgaGFzKHJlZikgewogICAgcmV0dXJuIHRoaXMuX3NldC5oYXMocmVmLnRvU3RyaW5nKCkpOwogIH0KICBwdXQocmVmKSB7CiAgICB0aGlzLl9zZXQuYWRkKHJlZi50b1N0cmluZygpKTsKICB9CiAgcmVtb3ZlKHJlZikgewogICAgdGhpcy5fc2V0LmRlbGV0ZShyZWYudG9TdHJpbmcoKSk7CiAgfQogIFtTeW1ib2wuaXRlcmF0b3JdKCkgewogICAgcmV0dXJuIHRoaXMuX3NldC52YWx1ZXMoKTsKICB9CiAgY2xlYXIoKSB7CiAgICB0aGlzLl9zZXQuY2xlYXIoKTsKICB9Cn0KY2xhc3MgUmVmU2V0Q2FjaGUgewogIGNvbnN0cnVjdG9yKCkgewogICAgdGhpcy5fbWFwID0gbmV3IE1hcCgpOwogIH0KICBnZXQgc2l6ZSgpIHsKICAgIHJldHVybiB0aGlzLl9tYXAuc2l6ZTsKICB9CiAgZ2V0KHJlZikgewogICAgcmV0dXJuIHRoaXMuX21hcC5nZXQocmVmLnRvU3RyaW5nKCkpOwogIH0KICBoYXMocmVmKSB7CiAgICByZXR1cm4gdGhpcy5fbWFwLmhhcyhyZWYudG9TdHJpbmcoKSk7CiAgfQogIHB1dChyZWYsIG9iaikgewogICAgdGhpcy5fbWFwLnNldChyZWYudG9TdHJpbmcoKSwgb2JqKTsKICB9CiAgcHV0QWxpYXMocmVmLCBhbGlhc1JlZikgewogICAgdGhpcy5fbWFwLnNldChyZWYudG9TdHJpbmcoKSwgdGhpcy5nZXQoYWxpYXNSZWYpKTsKICB9CiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7CiAgICByZXR1cm4gdGhpcy5fbWFwLnZhbHVlcygpOwogIH0KICBjbGVhcigpIHsKICAgIHRoaXMuX21hcC5jbGVhcigpOwogIH0KICAqdmFsdWVzKCkgewogICAgeWllbGQqIHRoaXMuX21hcC52YWx1ZXMoKTsKICB9CiAgKml0ZW1zKCkgewogICAgZm9yIChjb25zdCBbcmVmLCB2YWx1ZV0gb2YgdGhpcy5fbWFwKSB7CiAgICAgIHlpZWxkIFtSZWYuZnJvbVN0cmluZyhyZWYpLCB2YWx1ZV07CiAgICB9CiAgfQogICprZXlzKCkgewogICAgZm9yIChjb25zdCByZWYgb2YgdGhpcy5fbWFwLmtleXMoKSkgewogICAgICB5aWVsZCBSZWYuZnJvbVN0cmluZyhyZWYpOwogICAgfQogIH0KfQpmdW5jdGlvbiBpc05hbWUodiwgbmFtZSkgewogIHJldHVybiB2IGluc3RhbmNlb2YgTmFtZSAmJiAobmFtZSA9PT0gdW5kZWZpbmVkIHx8IHYubmFtZSA9PT0gbmFtZSk7Cn0KZnVuY3Rpb24gaXNDbWQodiwgY21kKSB7CiAgcmV0dXJuIHYgaW5zdGFuY2VvZiBDbWQgJiYgKGNtZCA9PT0gdW5kZWZpbmVkIHx8IHYuY21kID09PSBjbWQpOwp9CmZ1bmN0aW9uIGlzRGljdCh2LCB0eXBlKSB7CiAgcmV0dXJuIHYgaW5zdGFuY2VvZiBEaWN0ICYmICh0eXBlID09PSB1bmRlZmluZWQgfHwgaXNOYW1lKHYuZ2V0KCJUeXBlIiksIHR5cGUpKTsKfQpmdW5jdGlvbiBpc1JlZnNFcXVhbCh2MSwgdjIpIHsKICByZXR1cm4gdjEubnVtID09PSB2Mi5udW0gJiYgdjEuZ2VuID09PSB2Mi5nZW47Cn0KCjsvLyAuL3NyYy9jb3JlL2Jhc2Vfc3RyZWFtLmpzCgpjbGFzcyBCYXNlU3RyZWFtIHsKICBnZXQgbGVuZ3RoKCkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IGdldHRlciBgbGVuZ3RoYCBhY2Nlc3NlZCIpOwogIH0KICBnZXQgaXNFbXB0eSgpIHsKICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBnZXR0ZXIgYGlzRW1wdHlgIGFjY2Vzc2VkIik7CiAgfQogIGdldCBpc0RhdGFMb2FkZWQoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJpc0RhdGFMb2FkZWQiLCB0cnVlKTsKICB9CiAgZ2V0Qnl0ZSgpIHsKICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYGdldEJ5dGVgIGNhbGxlZCIpOwogIH0KICBnZXRCeXRlcyhsZW5ndGgpIHsKICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYGdldEJ5dGVzYCBjYWxsZWQiKTsKICB9CiAgYXN5bmMgZ2V0SW1hZ2VEYXRhKGxlbmd0aCwgZGVjb2Rlck9wdGlvbnMpIHsKICAgIHJldHVybiB0aGlzLmdldEJ5dGVzKGxlbmd0aCwgZGVjb2Rlck9wdGlvbnMpOwogIH0KICBhc3luYyBhc3luY0dldEJ5dGVzKCkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgYXN5bmNHZXRCeXRlc2AgY2FsbGVkIik7CiAgfQogIGdldCBpc0FzeW5jKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBnZXQgaXNBc3luY0RlY29kZXIoKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGdldCBpc0ltYWdlU3RyZWFtKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBnZXQgY2FuQXN5bmNEZWNvZGVJbWFnZUZyb21CdWZmZXIoKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGFzeW5jIGdldFRyYW5zZmVyYWJsZUltYWdlKCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIHBlZWtCeXRlKCkgewogICAgY29uc3QgcGVla2VkQnl0ZSA9IHRoaXMuZ2V0Qnl0ZSgpOwogICAgaWYgKHBlZWtlZEJ5dGUgIT09IC0xKSB7CiAgICAgIHRoaXMucG9zLS07CiAgICB9CiAgICByZXR1cm4gcGVla2VkQnl0ZTsKICB9CiAgcGVla0J5dGVzKGxlbmd0aCkgewogICAgY29uc3QgYnl0ZXMgPSB0aGlzLmdldEJ5dGVzKGxlbmd0aCk7CiAgICB0aGlzLnBvcyAtPSBieXRlcy5sZW5ndGg7CiAgICByZXR1cm4gYnl0ZXM7CiAgfQogIGdldFVpbnQxNigpIHsKICAgIGNvbnN0IGIwID0gdGhpcy5nZXRCeXRlKCk7CiAgICBjb25zdCBiMSA9IHRoaXMuZ2V0Qnl0ZSgpOwogICAgaWYgKGIwID09PSAtMSB8fCBiMSA9PT0gLTEpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgcmV0dXJuIChiMCA8PCA4KSArIGIxOwogIH0KICBnZXRJbnQzMigpIHsKICAgIGNvbnN0IGIwID0gdGhpcy5nZXRCeXRlKCk7CiAgICBjb25zdCBiMSA9IHRoaXMuZ2V0Qnl0ZSgpOwogICAgY29uc3QgYjIgPSB0aGlzLmdldEJ5dGUoKTsKICAgIGNvbnN0IGIzID0gdGhpcy5nZXRCeXRlKCk7CiAgICByZXR1cm4gKGIwIDw8IDI0KSArIChiMSA8PCAxNikgKyAoYjIgPDwgOCkgKyBiMzsKICB9CiAgZ2V0Qnl0ZVJhbmdlKGJlZ2luLCBlbmQpIHsKICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYGdldEJ5dGVSYW5nZWAgY2FsbGVkIik7CiAgfQogIGdldFN0cmluZyhsZW5ndGgpIHsKICAgIHJldHVybiBieXRlc1RvU3RyaW5nKHRoaXMuZ2V0Qnl0ZXMobGVuZ3RoKSk7CiAgfQogIHNraXAobikgewogICAgdGhpcy5wb3MgKz0gbiB8fCAxOwogIH0KICByZXNldCgpIHsKICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYHJlc2V0YCBjYWxsZWQiKTsKICB9CiAgbW92ZVN0YXJ0KCkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgbW92ZVN0YXJ0YCBjYWxsZWQiKTsKICB9CiAgbWFrZVN1YlN0cmVhbShzdGFydCwgbGVuZ3RoLCBkaWN0ID0gbnVsbCkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgbWFrZVN1YlN0cmVhbWAgY2FsbGVkIik7CiAgfQogIGdldEJhc2VTdHJlYW1zKCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGdldE9yaWdpbmFsU3RyZWFtKCkgewogICAgcmV0dXJuIHRoaXMuc3RyZWFtPy5nZXRPcmlnaW5hbFN0cmVhbSgpIHx8IHRoaXM7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9jb3JlX3V0aWxzLmpzCgoKCmNvbnN0IFBERl9WRVJTSU9OX1JFR0VYUCA9IC9eWzEtOV1cLlxkJC87CmNvbnN0IE1BWF9JTlRfMzIgPSAyICoqIDMxIC0gMTsKY29uc3QgTUlOX0lOVF8zMiA9IC0oMiAqKiAzMSk7CmNvbnN0IElERU5USVRZX01BVFJJWCA9IFsxLCAwLCAwLCAxLCAwLCAwXTsKY29uc3QgUkVTT1VSQ0VTX0tFWVNfT1BFUkFUT1JfTElTVCA9IFsiQ29sb3JTcGFjZSIsICJFeHRHU3RhdGUiLCAiRm9udCIsICJQYXR0ZXJuIiwgIlByb3BlcnRpZXMiLCAiU2hhZGluZyIsICJYT2JqZWN0Il07CmNvbnN0IFJFU09VUkNFU19LRVlTX1RFWFRfQ09OVEVOVCA9IFsiRXh0R1N0YXRlIiwgIkZvbnQiLCAiUHJvcGVydGllcyIsICJYT2JqZWN0Il07CmZ1bmN0aW9uIGdldExvb2t1cFRhYmxlRmFjdG9yeShpbml0aWFsaXplcikgewogIGxldCBsb29rdXA7CiAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgIGlmIChpbml0aWFsaXplcikgewogICAgICBsb29rdXAgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBpbml0aWFsaXplcihsb29rdXApOwogICAgICBpbml0aWFsaXplciA9IG51bGw7CiAgICB9CiAgICByZXR1cm4gbG9va3VwOwogIH07Cn0KY2xhc3MgTWlzc2luZ0RhdGFFeGNlcHRpb24gZXh0ZW5kcyBCYXNlRXhjZXB0aW9uIHsKICBjb25zdHJ1Y3RvcihiZWdpbiwgZW5kKSB7CiAgICBzdXBlcihgTWlzc2luZyBkYXRhIFske2JlZ2lufSwgJHtlbmR9KWAsICJNaXNzaW5nRGF0YUV4Y2VwdGlvbiIpOwogICAgdGhpcy5iZWdpbiA9IGJlZ2luOwogICAgdGhpcy5lbmQgPSBlbmQ7CiAgfQp9CmNsYXNzIFBhcnNlckVPRkV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIobXNnLCAiUGFyc2VyRU9GRXhjZXB0aW9uIik7CiAgfQp9CmNsYXNzIFhSZWZFbnRyeUV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIobXNnLCAiWFJlZkVudHJ5RXhjZXB0aW9uIik7CiAgfQp9CmNsYXNzIFhSZWZQYXJzZUV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIobXNnLCAiWFJlZlBhcnNlRXhjZXB0aW9uIik7CiAgfQp9CmZ1bmN0aW9uIGFycmF5QnVmZmVyc1RvQnl0ZXMoYXJyKSB7CiAgY29uc3QgbGVuZ3RoID0gYXJyLmxlbmd0aDsKICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCk7CiAgfQogIGlmIChsZW5ndGggPT09IDEpIHsKICAgIHJldHVybiBuZXcgVWludDhBcnJheShhcnJbMF0pOwogIH0KICBsZXQgZGF0YUxlbmd0aCA9IDA7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgZGF0YUxlbmd0aCArPSBhcnJbaV0uYnl0ZUxlbmd0aDsKICB9CiAgY29uc3QgZGF0YSA9IG5ldyBVaW50OEFycmF5KGRhdGFMZW5ndGgpOwogIGxldCBwb3MgPSAwOwogIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgIGNvbnN0IGl0ZW0gPSBuZXcgVWludDhBcnJheShhcnJbaV0pOwogICAgZGF0YS5zZXQoaXRlbSwgcG9zKTsKICAgIHBvcyArPSBpdGVtLmJ5dGVMZW5ndGg7CiAgfQogIHJldHVybiBkYXRhOwp9CmFzeW5jIGZ1bmN0aW9uIGZldGNoQmluYXJ5RGF0YSh1cmwpIHsKICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVybCk7CiAgaWYgKCFyZXNwb25zZS5vaykgewogICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gZmV0Y2ggZmlsZSAiJHt1cmx9IiB3aXRoICIke3Jlc3BvbnNlLnN0YXR1c1RleHR9Ii5gKTsKICB9CiAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGF3YWl0IHJlc3BvbnNlLmFycmF5QnVmZmVyKCkpOwp9CmZ1bmN0aW9uIGdldEluaGVyaXRhYmxlUHJvcGVydHkoewogIGRpY3QsCiAga2V5LAogIGdldEFycmF5ID0gZmFsc2UsCiAgc3RvcFdoZW5Gb3VuZCA9IHRydWUKfSkgewogIGxldCB2YWx1ZXM7CiAgY29uc3QgdmlzaXRlZCA9IG5ldyBSZWZTZXQoKTsKICB3aGlsZSAoZGljdCBpbnN0YW5jZW9mIERpY3QgJiYgIShkaWN0Lm9iaklkICYmIHZpc2l0ZWQuaGFzKGRpY3Qub2JqSWQpKSkgewogICAgaWYgKGRpY3Qub2JqSWQpIHsKICAgICAgdmlzaXRlZC5wdXQoZGljdC5vYmpJZCk7CiAgICB9CiAgICBjb25zdCB2YWx1ZSA9IGdldEFycmF5ID8gZGljdC5nZXRBcnJheShrZXkpIDogZGljdC5nZXQoa2V5KTsKICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmIChzdG9wV2hlbkZvdW5kKSB7CiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICB9CiAgICAgICh2YWx1ZXMgfHw9IFtdKS5wdXNoKHZhbHVlKTsKICAgIH0KICAgIGRpY3QgPSBkaWN0LmdldCgiUGFyZW50Iik7CiAgfQogIHJldHVybiB2YWx1ZXM7Cn0KZnVuY3Rpb24gZ2V0UGFyZW50VG9VcGRhdGUoZGljdCwgcmVmLCB4cmVmKSB7CiAgY29uc3QgdmlzaXRlZCA9IG5ldyBSZWZTZXQoKTsKICBjb25zdCBmaXJzdERpY3QgPSBkaWN0OwogIGNvbnN0IHJlc3VsdCA9IHsKICAgIGRpY3Q6IG51bGwsCiAgICByZWY6IG51bGwKICB9OwogIHdoaWxlIChkaWN0IGluc3RhbmNlb2YgRGljdCAmJiAhdmlzaXRlZC5oYXMocmVmKSkgewogICAgdmlzaXRlZC5wdXQocmVmKTsKICAgIGlmIChkaWN0LmhhcygiVCIpKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgcmVmID0gZGljdC5nZXRSYXcoIlBhcmVudCIpOwogICAgaWYgKCEocmVmIGluc3RhbmNlb2YgUmVmKSkgewogICAgICByZXR1cm4gcmVzdWx0OwogICAgfQogICAgZGljdCA9IHhyZWYuZmV0Y2gocmVmKTsKICB9CiAgaWYgKGRpY3QgaW5zdGFuY2VvZiBEaWN0ICYmIGRpY3QgIT09IGZpcnN0RGljdCkgewogICAgcmVzdWx0LmRpY3QgPSBkaWN0OwogICAgcmVzdWx0LnJlZiA9IHJlZjsKICB9CiAgcmV0dXJuIHJlc3VsdDsKfQpjb25zdCBST01BTl9OVU1CRVJfTUFQID0gWyIiLCAiQyIsICJDQyIsICJDQ0MiLCAiQ0QiLCAiRCIsICJEQyIsICJEQ0MiLCAiRENDQyIsICJDTSIsICIiLCAiWCIsICJYWCIsICJYWFgiLCAiWEwiLCAiTCIsICJMWCIsICJMWFgiLCAiTFhYWCIsICJYQyIsICIiLCAiSSIsICJJSSIsICJJSUkiLCAiSVYiLCAiViIsICJWSSIsICJWSUkiLCAiVklJSSIsICJJWCJdOwpmdW5jdGlvbiB0b1JvbWFuTnVtZXJhbHMobnVtYmVyLCBsb3dlckNhc2UgPSBmYWxzZSkgewogIGFzc2VydChOdW1iZXIuaXNJbnRlZ2VyKG51bWJlcikgJiYgbnVtYmVyID4gMCwgIlRoZSBudW1iZXIgc2hvdWxkIGJlIGEgcG9zaXRpdmUgaW50ZWdlci4iKTsKICBjb25zdCByb21hbiA9ICJNIi5yZXBlYXQobnVtYmVyIC8gMTAwMCB8IDApICsgUk9NQU5fTlVNQkVSX01BUFtudW1iZXIgJSAxMDAwIC8gMTAwIHwgMF0gKyBST01BTl9OVU1CRVJfTUFQWzEwICsgKG51bWJlciAlIDEwMCAvIDEwIHwgMCldICsgUk9NQU5fTlVNQkVSX01BUFsyMCArIG51bWJlciAlIDEwXTsKICByZXR1cm4gbG93ZXJDYXNlID8gcm9tYW4udG9Mb3dlckNhc2UoKSA6IHJvbWFuOwp9CmZ1bmN0aW9uIGxvZzIoeCkgewogIHJldHVybiB4ID4gMCA/IE1hdGguY2VpbChNYXRoLmxvZzIoeCkpIDogMDsKfQpmdW5jdGlvbiByZWFkSW50OChkYXRhLCBvZmZzZXQpIHsKICByZXR1cm4gZGF0YVtvZmZzZXRdIDw8IDI0ID4+IDI0Owp9CmZ1bmN0aW9uIHJlYWRJbnQxNihkYXRhLCBvZmZzZXQpIHsKICByZXR1cm4gKGRhdGFbb2Zmc2V0XSA8PCAyNCB8IGRhdGFbb2Zmc2V0ICsgMV0gPDwgMTYpID4+IDE2Owp9CmZ1bmN0aW9uIHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KSB7CiAgcmV0dXJuIGRhdGFbb2Zmc2V0XSA8PCA4IHwgZGF0YVtvZmZzZXQgKyAxXTsKfQpmdW5jdGlvbiByZWFkVWludDMyKGRhdGEsIG9mZnNldCkgewogIHJldHVybiAoZGF0YVtvZmZzZXRdIDw8IDI0IHwgZGF0YVtvZmZzZXQgKyAxXSA8PCAxNiB8IGRhdGFbb2Zmc2V0ICsgMl0gPDwgOCB8IGRhdGFbb2Zmc2V0ICsgM10pID4+PiAwOwp9CmZ1bmN0aW9uIGlzV2hpdGVTcGFjZShjaCkgewogIHJldHVybiBjaCA9PT0gMHgyMCB8fCBjaCA9PT0gMHgwOSB8fCBjaCA9PT0gMHgwZCB8fCBjaCA9PT0gMHgwYTsKfQpmdW5jdGlvbiBpc0Jvb2xlYW5BcnJheShhcnIsIGxlbikgewogIHJldHVybiBBcnJheS5pc0FycmF5KGFycikgJiYgKGxlbiA9PT0gbnVsbCB8fCBhcnIubGVuZ3RoID09PSBsZW4pICYmIGFyci5ldmVyeSh4ID0+IHR5cGVvZiB4ID09PSAiYm9vbGVhbiIpOwp9CmZ1bmN0aW9uIGlzTnVtYmVyQXJyYXkoYXJyLCBsZW4pIHsKICBpZiAoQXJyYXkuaXNBcnJheShhcnIpKSB7CiAgICByZXR1cm4gKGxlbiA9PT0gbnVsbCB8fCBhcnIubGVuZ3RoID09PSBsZW4pICYmIGFyci5ldmVyeSh4ID0+IHR5cGVvZiB4ID09PSAibnVtYmVyIik7CiAgfQogIHJldHVybiBBcnJheUJ1ZmZlci5pc1ZpZXcoYXJyKSAmJiAhKGFyciBpbnN0YW5jZW9mIEJpZ0ludDY0QXJyYXkgfHwgYXJyIGluc3RhbmNlb2YgQmlnVWludDY0QXJyYXkpICYmIChsZW4gPT09IG51bGwgfHwgYXJyLmxlbmd0aCA9PT0gbGVuKTsKfQpmdW5jdGlvbiBsb29rdXBNYXRyaXgoYXJyLCBmYWxsYmFjaykgewogIHJldHVybiBpc051bWJlckFycmF5KGFyciwgNikgPyBhcnIgOiBmYWxsYmFjazsKfQpmdW5jdGlvbiBsb29rdXBSZWN0KGFyciwgZmFsbGJhY2spIHsKICByZXR1cm4gaXNOdW1iZXJBcnJheShhcnIsIDQpID8gYXJyIDogZmFsbGJhY2s7Cn0KZnVuY3Rpb24gbG9va3VwTm9ybWFsUmVjdChhcnIsIGZhbGxiYWNrKSB7CiAgcmV0dXJuIGlzTnVtYmVyQXJyYXkoYXJyLCA0KSA/IFV0aWwubm9ybWFsaXplUmVjdChhcnIpIDogZmFsbGJhY2s7Cn0KZnVuY3Rpb24gcGFyc2VYRkFQYXRoKHBhdGgpIHsKICBjb25zdCBwb3NpdGlvblBhdHRlcm4gPSAvKC4rKVxbKFxkKylcXSQvOwogIHJldHVybiBwYXRoLnNwbGl0KCIuIikubWFwKGNvbXBvbmVudCA9PiB7CiAgICBjb25zdCBtID0gY29tcG9uZW50Lm1hdGNoKHBvc2l0aW9uUGF0dGVybik7CiAgICBpZiAobSkgewogICAgICByZXR1cm4gewogICAgICAgIG5hbWU6IG1bMV0sCiAgICAgICAgcG9zOiBwYXJzZUludChtWzJdLCAxMCkKICAgICAgfTsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIG5hbWU6IGNvbXBvbmVudCwKICAgICAgcG9zOiAwCiAgICB9OwogIH0pOwp9CmZ1bmN0aW9uIGVzY2FwZVBERk5hbWUoc3RyKSB7CiAgY29uc3QgYnVmZmVyID0gW107CiAgbGV0IHN0YXJ0ID0gMDsKICBmb3IgKGxldCBpID0gMCwgaWkgPSBzdHIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgY29uc3QgY2hhciA9IHN0ci5jaGFyQ29kZUF0KGkpOwogICAgaWYgKGNoYXIgPCAweDIxIHx8IGNoYXIgPiAweDdlIHx8IGNoYXIgPT09IDB4MjMgfHwgY2hhciA9PT0gMHgyOCB8fCBjaGFyID09PSAweDI5IHx8IGNoYXIgPT09IDB4M2MgfHwgY2hhciA9PT0gMHgzZSB8fCBjaGFyID09PSAweDViIHx8IGNoYXIgPT09IDB4NWQgfHwgY2hhciA9PT0gMHg3YiB8fCBjaGFyID09PSAweDdkIHx8IGNoYXIgPT09IDB4MmYgfHwgY2hhciA9PT0gMHgyNSkgewogICAgICBpZiAoc3RhcnQgPCBpKSB7CiAgICAgICAgYnVmZmVyLnB1c2goc3RyLnN1YnN0cmluZyhzdGFydCwgaSkpOwogICAgICB9CiAgICAgIGJ1ZmZlci5wdXNoKGAjJHtjaGFyLnRvU3RyaW5nKDE2KX1gKTsKICAgICAgc3RhcnQgPSBpICsgMTsKICAgIH0KICB9CiAgaWYgKGJ1ZmZlci5sZW5ndGggPT09IDApIHsKICAgIHJldHVybiBzdHI7CiAgfQogIGlmIChzdGFydCA8IHN0ci5sZW5ndGgpIHsKICAgIGJ1ZmZlci5wdXNoKHN0ci5zdWJzdHJpbmcoc3RhcnQsIHN0ci5sZW5ndGgpKTsKICB9CiAgcmV0dXJuIGJ1ZmZlci5qb2luKCIiKTsKfQpmdW5jdGlvbiBlc2NhcGVTdHJpbmcoc3RyKSB7CiAgcmV0dXJuIHN0ci5yZXBsYWNlQWxsKC8oWygpXFxcblxyXSkvZywgbWF0Y2ggPT4gewogICAgaWYgKG1hdGNoID09PSAiXG4iKSB7CiAgICAgIHJldHVybiAiXFxuIjsKICAgIH0gZWxzZSBpZiAobWF0Y2ggPT09ICJcciIpIHsKICAgICAgcmV0dXJuICJcXHIiOwogICAgfQogICAgcmV0dXJuIGBcXCR7bWF0Y2h9YDsKICB9KTsKfQpmdW5jdGlvbiBfY29sbGVjdEpTKGVudHJ5LCB4cmVmLCBsaXN0LCBwYXJlbnRzKSB7CiAgaWYgKCFlbnRyeSkgewogICAgcmV0dXJuOwogIH0KICBsZXQgcGFyZW50ID0gbnVsbDsKICBpZiAoZW50cnkgaW5zdGFuY2VvZiBSZWYpIHsKICAgIGlmIChwYXJlbnRzLmhhcyhlbnRyeSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgcGFyZW50ID0gZW50cnk7CiAgICBwYXJlbnRzLnB1dChwYXJlbnQpOwogICAgZW50cnkgPSB4cmVmLmZldGNoKGVudHJ5KTsKICB9CiAgaWYgKEFycmF5LmlzQXJyYXkoZW50cnkpKSB7CiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZW50cnkpIHsKICAgICAgX2NvbGxlY3RKUyhlbGVtZW50LCB4cmVmLCBsaXN0LCBwYXJlbnRzKTsKICAgIH0KICB9IGVsc2UgaWYgKGVudHJ5IGluc3RhbmNlb2YgRGljdCkgewogICAgaWYgKGlzTmFtZShlbnRyeS5nZXQoIlMiKSwgIkphdmFTY3JpcHQiKSkgewogICAgICBjb25zdCBqcyA9IGVudHJ5LmdldCgiSlMiKTsKICAgICAgbGV0IGNvZGU7CiAgICAgIGlmIChqcyBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgICBjb2RlID0ganMuZ2V0U3RyaW5nKCk7CiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGpzID09PSAic3RyaW5nIikgewogICAgICAgIGNvZGUgPSBqczsKICAgICAgfQogICAgICBjb2RlICYmPSBzdHJpbmdUb1BERlN0cmluZyhjb2RlLCB0cnVlKS5yZXBsYWNlQWxsKCJceDAwIiwgIiIpOwogICAgICBpZiAoY29kZSkgewogICAgICAgIGxpc3QucHVzaChjb2RlLnRyaW0oKSk7CiAgICAgIH0KICAgIH0KICAgIF9jb2xsZWN0SlMoZW50cnkuZ2V0UmF3KCJOZXh0IiksIHhyZWYsIGxpc3QsIHBhcmVudHMpOwogIH0KICBpZiAocGFyZW50KSB7CiAgICBwYXJlbnRzLnJlbW92ZShwYXJlbnQpOwogIH0KfQpmdW5jdGlvbiBjb2xsZWN0QWN0aW9ucyh4cmVmLCBkaWN0LCBldmVudFR5cGUpIHsKICBjb25zdCBhY3Rpb25zID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBjb25zdCBhZGRpdGlvbmFsQWN0aW9uc0RpY3RzID0gZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7CiAgICBkaWN0LAogICAga2V5OiAiQUEiLAogICAgc3RvcFdoZW5Gb3VuZDogZmFsc2UKICB9KTsKICBpZiAoYWRkaXRpb25hbEFjdGlvbnNEaWN0cykgewogICAgZm9yIChsZXQgaSA9IGFkZGl0aW9uYWxBY3Rpb25zRGljdHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgY29uc3QgYWRkaXRpb25hbEFjdGlvbnMgPSBhZGRpdGlvbmFsQWN0aW9uc0RpY3RzW2ldOwogICAgICBpZiAoIShhZGRpdGlvbmFsQWN0aW9ucyBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBrZXkgb2YgYWRkaXRpb25hbEFjdGlvbnMuZ2V0S2V5cygpKSB7CiAgICAgICAgY29uc3QgYWN0aW9uID0gZXZlbnRUeXBlW2tleV07CiAgICAgICAgaWYgKCFhY3Rpb24pIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBhY3Rpb25EaWN0ID0gYWRkaXRpb25hbEFjdGlvbnMuZ2V0UmF3KGtleSk7CiAgICAgICAgY29uc3QgcGFyZW50cyA9IG5ldyBSZWZTZXQoKTsKICAgICAgICBjb25zdCBsaXN0ID0gW107CiAgICAgICAgX2NvbGxlY3RKUyhhY3Rpb25EaWN0LCB4cmVmLCBsaXN0LCBwYXJlbnRzKTsKICAgICAgICBpZiAobGlzdC5sZW5ndGggPiAwKSB7CiAgICAgICAgICBhY3Rpb25zW2FjdGlvbl0gPSBsaXN0OwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICBpZiAoZGljdC5oYXMoIkEiKSkgewogICAgY29uc3QgYWN0aW9uRGljdCA9IGRpY3QuZ2V0KCJBIik7CiAgICBjb25zdCBwYXJlbnRzID0gbmV3IFJlZlNldCgpOwogICAgY29uc3QgbGlzdCA9IFtdOwogICAgX2NvbGxlY3RKUyhhY3Rpb25EaWN0LCB4cmVmLCBsaXN0LCBwYXJlbnRzKTsKICAgIGlmIChsaXN0Lmxlbmd0aCA+IDApIHsKICAgICAgYWN0aW9ucy5BY3Rpb24gPSBsaXN0OwogICAgfQogIH0KICByZXR1cm4gb2JqZWN0U2l6ZShhY3Rpb25zKSA+IDAgPyBhY3Rpb25zIDogbnVsbDsKfQpjb25zdCBYTUxFbnRpdGllcyA9IHsKICAweDNjOiAiJmx0OyIsCiAgMHgzZTogIiZndDsiLAogIDB4MjY6ICImYW1wOyIsCiAgMHgyMjogIiZxdW90OyIsCiAgMHgyNzogIiZhcG9zOyIKfTsKZnVuY3Rpb24qIGNvZGVQb2ludEl0ZXIoc3RyKSB7CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gc3RyLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IGNoYXIgPSBzdHIuY29kZVBvaW50QXQoaSk7CiAgICBpZiAoY2hhciA+IDB4ZDdmZiAmJiAoY2hhciA8IDB4ZTAwMCB8fCBjaGFyID4gMHhmZmZkKSkgewogICAgICBpKys7CiAgICB9CiAgICB5aWVsZCBjaGFyOwogIH0KfQpmdW5jdGlvbiBlbmNvZGVUb1htbFN0cmluZyhzdHIpIHsKICBjb25zdCBidWZmZXIgPSBbXTsKICBsZXQgc3RhcnQgPSAwOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHN0ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCBjaGFyID0gc3RyLmNvZGVQb2ludEF0KGkpOwogICAgaWYgKDB4MjAgPD0gY2hhciAmJiBjaGFyIDw9IDB4N2UpIHsKICAgICAgY29uc3QgZW50aXR5ID0gWE1MRW50aXRpZXNbY2hhcl07CiAgICAgIGlmIChlbnRpdHkpIHsKICAgICAgICBpZiAoc3RhcnQgPCBpKSB7CiAgICAgICAgICBidWZmZXIucHVzaChzdHIuc3Vic3RyaW5nKHN0YXJ0LCBpKSk7CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5wdXNoKGVudGl0eSk7CiAgICAgICAgc3RhcnQgPSBpICsgMTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgaWYgKHN0YXJ0IDwgaSkgewogICAgICAgIGJ1ZmZlci5wdXNoKHN0ci5zdWJzdHJpbmcoc3RhcnQsIGkpKTsKICAgICAgfQogICAgICBidWZmZXIucHVzaChgJiN4JHtjaGFyLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpfTtgKTsKICAgICAgaWYgKGNoYXIgPiAweGQ3ZmYgJiYgKGNoYXIgPCAweGUwMDAgfHwgY2hhciA+IDB4ZmZmZCkpIHsKICAgICAgICBpKys7CiAgICAgIH0KICAgICAgc3RhcnQgPSBpICsgMTsKICAgIH0KICB9CiAgaWYgKGJ1ZmZlci5sZW5ndGggPT09IDApIHsKICAgIHJldHVybiBzdHI7CiAgfQogIGlmIChzdGFydCA8IHN0ci5sZW5ndGgpIHsKICAgIGJ1ZmZlci5wdXNoKHN0ci5zdWJzdHJpbmcoc3RhcnQsIHN0ci5sZW5ndGgpKTsKICB9CiAgcmV0dXJuIGJ1ZmZlci5qb2luKCIiKTsKfQpmdW5jdGlvbiB2YWxpZGF0ZUZvbnROYW1lKGZvbnRGYW1pbHksIG11c3RXYXJuID0gZmFsc2UpIHsKICBjb25zdCBtID0gL14oInwnKS4qKCJ8JykkLy5leGVjKGZvbnRGYW1pbHkpOwogIGlmIChtICYmIG1bMV0gPT09IG1bMl0pIHsKICAgIGNvbnN0IHJlID0gbmV3IFJlZ0V4cChgW15cXFxcXSR7bVsxXX1gKTsKICAgIGlmIChyZS50ZXN0KGZvbnRGYW1pbHkuc2xpY2UoMSwgLTEpKSkgewogICAgICBpZiAobXVzdFdhcm4pIHsKICAgICAgICB3YXJuKGBGb250RmFtaWx5IGNvbnRhaW5zIHVuZXNjYXBlZCAke21bMV19OiAke2ZvbnRGYW1pbHl9LmApOwogICAgICB9CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9IGVsc2UgewogICAgZm9yIChjb25zdCBpZGVudCBvZiBmb250RmFtaWx5LnNwbGl0KC9bIFx0XSsvKSkgewogICAgICBpZiAoL14oXGR8KC0oXGR8LSkpKS8udGVzdChpZGVudCkgfHwgIS9eW1x3LVxcXSskLy50ZXN0KGlkZW50KSkgewogICAgICAgIGlmIChtdXN0V2FybikgewogICAgICAgICAgd2FybihgRm9udEZhbWlseSBjb250YWlucyBpbnZhbGlkIDxjdXN0b20taWRlbnQ+OiAke2ZvbnRGYW1pbHl9LmApOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIHRydWU7Cn0KZnVuY3Rpb24gdmFsaWRhdGVDU1NGb250KGNzc0ZvbnRJbmZvKSB7CiAgY29uc3QgREVGQVVMVF9DU1NfRk9OVF9PQkxJUVVFID0gIjE0IjsKICBjb25zdCBERUZBVUxUX0NTU19GT05UX1dFSUdIVCA9ICI0MDAiOwogIGNvbnN0IENTU19GT05UX1dFSUdIVF9WQUxVRVMgPSBuZXcgU2V0KFsiMTAwIiwgIjIwMCIsICIzMDAiLCAiNDAwIiwgIjUwMCIsICI2MDAiLCAiNzAwIiwgIjgwMCIsICI5MDAiLCAiMTAwMCIsICJub3JtYWwiLCAiYm9sZCIsICJib2xkZXIiLCAibGlnaHRlciJdKTsKICBjb25zdCB7CiAgICBmb250RmFtaWx5LAogICAgZm9udFdlaWdodCwKICAgIGl0YWxpY0FuZ2xlCiAgfSA9IGNzc0ZvbnRJbmZvOwogIGlmICghdmFsaWRhdGVGb250TmFtZShmb250RmFtaWx5LCB0cnVlKSkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBjb25zdCB3ZWlnaHQgPSBmb250V2VpZ2h0ID8gZm9udFdlaWdodC50b1N0cmluZygpIDogIiI7CiAgY3NzRm9udEluZm8uZm9udFdlaWdodCA9IENTU19GT05UX1dFSUdIVF9WQUxVRVMuaGFzKHdlaWdodCkgPyB3ZWlnaHQgOiBERUZBVUxUX0NTU19GT05UX1dFSUdIVDsKICBjb25zdCBhbmdsZSA9IHBhcnNlRmxvYXQoaXRhbGljQW5nbGUpOwogIGNzc0ZvbnRJbmZvLml0YWxpY0FuZ2xlID0gaXNOYU4oYW5nbGUpIHx8IGFuZ2xlIDwgLTkwIHx8IGFuZ2xlID4gOTAgPyBERUZBVUxUX0NTU19GT05UX09CTElRVUUgOiBpdGFsaWNBbmdsZS50b1N0cmluZygpOwogIHJldHVybiB0cnVlOwp9CmZ1bmN0aW9uIHJlY292ZXJKc1VSTChzdHIpIHsKICBjb25zdCBVUkxfT1BFTl9NRVRIT0RTID0gWyJhcHAubGF1bmNoVVJMIiwgIndpbmRvdy5vcGVuIiwgInhmYS5ob3N0LmdvdG9VUkwiXTsKICBjb25zdCByZWdleCA9IG5ldyBSZWdFeHAoIl5cXHMqKCIgKyBVUkxfT1BFTl9NRVRIT0RTLmpvaW4oInwiKS5yZXBsYWNlQWxsKCIuIiwgIlxcLiIpICsgIilcXCgoPzonfFwiKShbXidcIl0qKSg/Oid8XCIpKD86LFxccyooXFx3KylcXCl8XFwpKSIsICJpIik7CiAgY29uc3QganNVcmwgPSByZWdleC5leGVjKHN0cik7CiAgaWYgKGpzVXJsPy5bMl0pIHsKICAgIHJldHVybiB7CiAgICAgIHVybDoganNVcmxbMl0sCiAgICAgIG5ld1dpbmRvdzoganNVcmxbMV0gPT09ICJhcHAubGF1bmNoVVJMIiAmJiBqc1VybFszXSA9PT0gInRydWUiCiAgICB9OwogIH0KICByZXR1cm4gbnVsbDsKfQpmdW5jdGlvbiBudW1iZXJUb1N0cmluZyh2YWx1ZSkgewogIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSkgewogICAgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCk7CiAgfQogIGNvbnN0IHJvdW5kZWRWYWx1ZSA9IE1hdGgucm91bmQodmFsdWUgKiAxMDApOwogIGlmIChyb3VuZGVkVmFsdWUgJSAxMDAgPT09IDApIHsKICAgIHJldHVybiAocm91bmRlZFZhbHVlIC8gMTAwKS50b1N0cmluZygpOwogIH0KICBpZiAocm91bmRlZFZhbHVlICUgMTAgPT09IDApIHsKICAgIHJldHVybiB2YWx1ZS50b0ZpeGVkKDEpOwogIH0KICByZXR1cm4gdmFsdWUudG9GaXhlZCgyKTsKfQpmdW5jdGlvbiBnZXROZXdBbm5vdGF0aW9uc01hcChhbm5vdGF0aW9uU3RvcmFnZSkgewogIGlmICghYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCBuZXdBbm5vdGF0aW9uc0J5UGFnZSA9IG5ldyBNYXAoKTsKICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgaWYgKCFrZXkuc3RhcnRzV2l0aChBbm5vdGF0aW9uRWRpdG9yUHJlZml4KSkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGxldCBhbm5vdGF0aW9ucyA9IG5ld0Fubm90YXRpb25zQnlQYWdlLmdldCh2YWx1ZS5wYWdlSW5kZXgpOwogICAgaWYgKCFhbm5vdGF0aW9ucykgewogICAgICBhbm5vdGF0aW9ucyA9IFtdOwogICAgICBuZXdBbm5vdGF0aW9uc0J5UGFnZS5zZXQodmFsdWUucGFnZUluZGV4LCBhbm5vdGF0aW9ucyk7CiAgICB9CiAgICBhbm5vdGF0aW9ucy5wdXNoKHZhbHVlKTsKICB9CiAgcmV0dXJuIG5ld0Fubm90YXRpb25zQnlQYWdlLnNpemUgPiAwID8gbmV3QW5ub3RhdGlvbnNCeVBhZ2UgOiBudWxsOwp9CmZ1bmN0aW9uIHN0cmluZ1RvQXNjaWlPclVURjE2QkUoc3RyKSB7CiAgaWYgKHN0ciA9PT0gbnVsbCB8fCBzdHIgPT09IHVuZGVmaW5lZCkgewogICAgcmV0dXJuIHN0cjsKICB9CiAgcmV0dXJuIGlzQXNjaWkoc3RyKSA/IHN0ciA6IHN0cmluZ1RvVVRGMTZTdHJpbmcoc3RyLCB0cnVlKTsKfQpmdW5jdGlvbiBpc0FzY2lpKHN0cikgewogIGlmICh0eXBlb2Ygc3RyICE9PSAic3RyaW5nIikgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICByZXR1cm4gIXN0ciB8fCAvXltceDAwLVx4N0ZdKiQvLnRlc3Qoc3RyKTsKfQpmdW5jdGlvbiBzdHJpbmdUb1VURjE2SGV4U3RyaW5nKHN0cikgewogIGNvbnN0IGJ1ZiA9IFtdOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHN0ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCBjaGFyID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICBidWYucHVzaChoZXhOdW1iZXJzW2NoYXIgPj4gOCAmIDB4ZmZdLCBoZXhOdW1iZXJzW2NoYXIgJiAweGZmXSk7CiAgfQogIHJldHVybiBidWYuam9pbigiIik7Cn0KZnVuY3Rpb24gc3RyaW5nVG9VVEYxNlN0cmluZyhzdHIsIGJpZ0VuZGlhbiA9IGZhbHNlKSB7CiAgY29uc3QgYnVmID0gW107CiAgaWYgKGJpZ0VuZGlhbikgewogICAgYnVmLnB1c2goIlx4RkVceEZGIik7CiAgfQogIGZvciAobGV0IGkgPSAwLCBpaSA9IHN0ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCBjaGFyID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICBidWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNoYXIgPj4gOCAmIDB4ZmYpLCBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoYXIgJiAweGZmKSk7CiAgfQogIHJldHVybiBidWYuam9pbigiIik7Cn0KZnVuY3Rpb24gZ2V0Um90YXRpb25NYXRyaXgocm90YXRpb24sIHdpZHRoLCBoZWlnaHQpIHsKICBzd2l0Y2ggKHJvdGF0aW9uKSB7CiAgICBjYXNlIDkwOgogICAgICByZXR1cm4gWzAsIDEsIC0xLCAwLCB3aWR0aCwgMF07CiAgICBjYXNlIDE4MDoKICAgICAgcmV0dXJuIFstMSwgMCwgMCwgLTEsIHdpZHRoLCBoZWlnaHRdOwogICAgY2FzZSAyNzA6CiAgICAgIHJldHVybiBbMCwgLTEsIDEsIDAsIDAsIGhlaWdodF07CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgcm90YXRpb24iKTsKICB9Cn0KZnVuY3Rpb24gZ2V0U2l6ZUluQnl0ZXMoeCkgewogIHJldHVybiBNYXRoLmNlaWwoTWF0aC5jZWlsKE1hdGgubG9nMigxICsgeCkpIC8gOCk7Cn0KCjsvLyAuL2V4dGVybmFsL3FjbXMvcWNtc191dGlscy5qcwpjbGFzcyBRQ01TIHsKICBzdGF0aWMgI21lbW9yeUFycmF5ID0gbnVsbDsKICBzdGF0aWMgX21lbW9yeSA9IG51bGw7CiAgc3RhdGljIF9tdXN0QWRkQWxwaGEgPSBmYWxzZTsKICBzdGF0aWMgX2Rlc3RCdWZmZXIgPSBudWxsOwogIHN0YXRpYyBfZGVzdE9mZnNldCA9IDA7CiAgc3RhdGljIF9kZXN0TGVuZ3RoID0gMDsKICBzdGF0aWMgX2Nzc0NvbG9yID0gIiI7CiAgc3RhdGljIF9tYWtlSGV4Q29sb3IgPSBudWxsOwogIHN0YXRpYyBnZXQgX21lbW9yeUFycmF5KCkgewogICAgY29uc3QgYXJyYXkgPSB0aGlzLiNtZW1vcnlBcnJheTsKICAgIGlmIChhcnJheT8uYnl0ZUxlbmd0aCkgewogICAgICByZXR1cm4gYXJyYXk7CiAgICB9CiAgICByZXR1cm4gdGhpcy4jbWVtb3J5QXJyYXkgPSBuZXcgVWludDhBcnJheSh0aGlzLl9tZW1vcnkuYnVmZmVyKTsKICB9Cn0KZnVuY3Rpb24gY29weV9yZXN1bHQocHRyLCBsZW4pIHsKICBjb25zdCB7CiAgICBfbXVzdEFkZEFscGhhLAogICAgX2Rlc3RCdWZmZXIsCiAgICBfZGVzdE9mZnNldCwKICAgIF9kZXN0TGVuZ3RoLAogICAgX21lbW9yeUFycmF5CiAgfSA9IFFDTVM7CiAgaWYgKGxlbiA9PT0gX2Rlc3RMZW5ndGgpIHsKICAgIF9kZXN0QnVmZmVyLnNldChfbWVtb3J5QXJyYXkuc3ViYXJyYXkocHRyLCBwdHIgKyBsZW4pLCBfZGVzdE9mZnNldCk7CiAgICByZXR1cm47CiAgfQogIGlmIChfbXVzdEFkZEFscGhhKSB7CiAgICBmb3IgKGxldCBpID0gcHRyLCBpaSA9IHB0ciArIGxlbiwgaiA9IF9kZXN0T2Zmc2V0OyBpIDwgaWk7IGkgKz0gMywgaiArPSA0KSB7CiAgICAgIF9kZXN0QnVmZmVyW2pdID0gX21lbW9yeUFycmF5W2ldOwogICAgICBfZGVzdEJ1ZmZlcltqICsgMV0gPSBfbWVtb3J5QXJyYXlbaSArIDFdOwogICAgICBfZGVzdEJ1ZmZlcltqICsgMl0gPSBfbWVtb3J5QXJyYXlbaSArIDJdOwogICAgICBfZGVzdEJ1ZmZlcltqICsgM10gPSAyNTU7CiAgICB9CiAgfSBlbHNlIHsKICAgIGZvciAobGV0IGkgPSBwdHIsIGlpID0gcHRyICsgbGVuLCBqID0gX2Rlc3RPZmZzZXQ7IGkgPCBpaTsgaSArPSAzLCBqICs9IDQpIHsKICAgICAgX2Rlc3RCdWZmZXJbal0gPSBfbWVtb3J5QXJyYXlbaV07CiAgICAgIF9kZXN0QnVmZmVyW2ogKyAxXSA9IF9tZW1vcnlBcnJheVtpICsgMV07CiAgICAgIF9kZXN0QnVmZmVyW2ogKyAyXSA9IF9tZW1vcnlBcnJheVtpICsgMl07CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGNvcHlfcmdiKHB0cikgewogIGNvbnN0IHsKICAgIF9kZXN0QnVmZmVyLAogICAgX2Rlc3RPZmZzZXQsCiAgICBfbWVtb3J5QXJyYXkKICB9ID0gUUNNUzsKICBfZGVzdEJ1ZmZlcltfZGVzdE9mZnNldF0gPSBfbWVtb3J5QXJyYXlbcHRyXTsKICBfZGVzdEJ1ZmZlcltfZGVzdE9mZnNldCArIDFdID0gX21lbW9yeUFycmF5W3B0ciArIDFdOwogIF9kZXN0QnVmZmVyW19kZXN0T2Zmc2V0ICsgMl0gPSBfbWVtb3J5QXJyYXlbcHRyICsgMl07Cn0KZnVuY3Rpb24gbWFrZV9jc3NSR0IocHRyKSB7CiAgY29uc3QgewogICAgX21lbW9yeUFycmF5CiAgfSA9IFFDTVM7CiAgUUNNUy5fY3NzQ29sb3IgPSBRQ01TLl9tYWtlSGV4Q29sb3IoX21lbW9yeUFycmF5W3B0cl0sIF9tZW1vcnlBcnJheVtwdHIgKyAxXSwgX21lbW9yeUFycmF5W3B0ciArIDJdKTsKfQoKOy8vIC4vZXh0ZXJuYWwvcWNtcy9xY21zLmpzCgpsZXQgd2FzbTsKY29uc3QgY2FjaGVkVGV4dERlY29kZXIgPSB0eXBlb2YgVGV4dERlY29kZXIgIT09ICd1bmRlZmluZWQnID8gbmV3IFRleHREZWNvZGVyKCd1dGYtOCcsIHsKICBpZ25vcmVCT006IHRydWUsCiAgZmF0YWw6IHRydWUKfSkgOiB7CiAgZGVjb2RlOiAoKSA9PiB7CiAgICB0aHJvdyBFcnJvcignVGV4dERlY29kZXIgbm90IGF2YWlsYWJsZScpOwogIH0KfTsKaWYgKHR5cGVvZiBUZXh0RGVjb2RlciAhPT0gJ3VuZGVmaW5lZCcpIHsKICBjYWNoZWRUZXh0RGVjb2Rlci5kZWNvZGUoKTsKfQo7CmxldCBjYWNoZWRVaW50OEFycmF5TWVtb3J5MCA9IG51bGw7CmZ1bmN0aW9uIGdldFVpbnQ4QXJyYXlNZW1vcnkwKCkgewogIGlmIChjYWNoZWRVaW50OEFycmF5TWVtb3J5MCA9PT0gbnVsbCB8fCBjYWNoZWRVaW50OEFycmF5TWVtb3J5MC5ieXRlTGVuZ3RoID09PSAwKSB7CiAgICBjYWNoZWRVaW50OEFycmF5TWVtb3J5MCA9IG5ldyBVaW50OEFycmF5KHdhc20ubWVtb3J5LmJ1ZmZlcik7CiAgfQogIHJldHVybiBjYWNoZWRVaW50OEFycmF5TWVtb3J5MDsKfQpmdW5jdGlvbiBnZXRTdHJpbmdGcm9tV2FzbTAocHRyLCBsZW4pIHsKICBwdHIgPSBwdHIgPj4+IDA7CiAgcmV0dXJuIGNhY2hlZFRleHREZWNvZGVyLmRlY29kZShnZXRVaW50OEFycmF5TWVtb3J5MCgpLnN1YmFycmF5KHB0ciwgcHRyICsgbGVuKSk7Cn0KbGV0IFdBU01fVkVDVE9SX0xFTiA9IDA7CmZ1bmN0aW9uIHBhc3NBcnJheThUb1dhc20wKGFyZywgbWFsbG9jKSB7CiAgY29uc3QgcHRyID0gbWFsbG9jKGFyZy5sZW5ndGggKiAxLCAxKSA+Pj4gMDsKICBnZXRVaW50OEFycmF5TWVtb3J5MCgpLnNldChhcmcsIHB0ciAvIDEpOwogIFdBU01fVkVDVE9SX0xFTiA9IGFyZy5sZW5ndGg7CiAgcmV0dXJuIHB0cjsKfQpmdW5jdGlvbiBxY21zX2NvbnZlcnRfYXJyYXkodHJhbnNmb3JtZXIsIHNyYykgewogIGNvbnN0IHB0cjAgPSBwYXNzQXJyYXk4VG9XYXNtMChzcmMsIHdhc20uX193YmluZGdlbl9tYWxsb2MpOwogIGNvbnN0IGxlbjAgPSBXQVNNX1ZFQ1RPUl9MRU47CiAgd2FzbS5xY21zX2NvbnZlcnRfYXJyYXkodHJhbnNmb3JtZXIsIHB0cjAsIGxlbjApOwp9CmZ1bmN0aW9uIHFjbXNfY29udmVydF9vbmUodHJhbnNmb3JtZXIsIHNyYywgY3NzKSB7CiAgd2FzbS5xY21zX2NvbnZlcnRfb25lKHRyYW5zZm9ybWVyLCBzcmMsIGNzcyk7Cn0KZnVuY3Rpb24gcWNtc19jb252ZXJ0X3RocmVlKHRyYW5zZm9ybWVyLCBzcmMxLCBzcmMyLCBzcmMzLCBjc3MpIHsKICB3YXNtLnFjbXNfY29udmVydF90aHJlZSh0cmFuc2Zvcm1lciwgc3JjMSwgc3JjMiwgc3JjMywgY3NzKTsKfQpmdW5jdGlvbiBxY21zX2NvbnZlcnRfZm91cih0cmFuc2Zvcm1lciwgc3JjMSwgc3JjMiwgc3JjMywgc3JjNCwgY3NzKSB7CiAgd2FzbS5xY21zX2NvbnZlcnRfZm91cih0cmFuc2Zvcm1lciwgc3JjMSwgc3JjMiwgc3JjMywgc3JjNCwgY3NzKTsKfQpmdW5jdGlvbiBxY21zX3RyYW5zZm9ybWVyX2Zyb21fbWVtb3J5KG1lbSwgaW5fdHlwZSwgaW50ZW50KSB7CiAgY29uc3QgcHRyMCA9IHBhc3NBcnJheThUb1dhc20wKG1lbSwgd2FzbS5fX3diaW5kZ2VuX21hbGxvYyk7CiAgY29uc3QgbGVuMCA9IFdBU01fVkVDVE9SX0xFTjsKICBjb25zdCByZXQgPSB3YXNtLnFjbXNfdHJhbnNmb3JtZXJfZnJvbV9tZW1vcnkocHRyMCwgbGVuMCwgaW5fdHlwZSwgaW50ZW50KTsKICByZXR1cm4gcmV0ID4+PiAwOwp9CmZ1bmN0aW9uIHFjbXNfZHJvcF90cmFuc2Zvcm1lcih0cmFuc2Zvcm1lcikgewogIHdhc20ucWNtc19kcm9wX3RyYW5zZm9ybWVyKHRyYW5zZm9ybWVyKTsKfQpjb25zdCBEYXRhVHlwZSA9IE9iamVjdC5mcmVlemUoewogIFJHQjg6IDAsCiAgIjAiOiAiUkdCOCIsCiAgUkdCQTg6IDEsCiAgIjEiOiAiUkdCQTgiLAogIEJHUkE4OiAyLAogICIyIjogIkJHUkE4IiwKICBHcmF5ODogMywKICAiMyI6ICJHcmF5OCIsCiAgR3JheUE4OiA0LAogICI0IjogIkdyYXlBOCIsCiAgQ01ZSzogNSwKICAiNSI6ICJDTVlLIgp9KTsKY29uc3QgSW50ZW50ID0gT2JqZWN0LmZyZWV6ZSh7CiAgUGVyY2VwdHVhbDogMCwKICAiMCI6ICJQZXJjZXB0dWFsIiwKICBSZWxhdGl2ZUNvbG9yaW1ldHJpYzogMSwKICAiMSI6ICJSZWxhdGl2ZUNvbG9yaW1ldHJpYyIsCiAgU2F0dXJhdGlvbjogMiwKICAiMiI6ICJTYXR1cmF0aW9uIiwKICBBYnNvbHV0ZUNvbG9yaW1ldHJpYzogMywKICAiMyI6ICJBYnNvbHV0ZUNvbG9yaW1ldHJpYyIKfSk7CmFzeW5jIGZ1bmN0aW9uIF9fd2JnX2xvYWQobW9kdWxlLCBpbXBvcnRzKSB7CiAgaWYgKHR5cGVvZiBSZXNwb25zZSA9PT0gJ2Z1bmN0aW9uJyAmJiBtb2R1bGUgaW5zdGFuY2VvZiBSZXNwb25zZSkgewogICAgaWYgKHR5cGVvZiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZyA9PT0gJ2Z1bmN0aW9uJykgewogICAgICB0cnkgewogICAgICAgIHJldHVybiBhd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZyhtb2R1bGUsIGltcG9ydHMpOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgaWYgKG1vZHVsZS5oZWFkZXJzLmdldCgnQ29udGVudC1UeXBlJykgIT0gJ2FwcGxpY2F0aW9uL3dhc20nKSB7CiAgICAgICAgICBjb25zb2xlLndhcm4oImBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZ2AgZmFpbGVkIGJlY2F1c2UgeW91ciBzZXJ2ZXIgZG9lcyBub3Qgc2VydmUgV2FzbSB3aXRoIGBhcHBsaWNhdGlvbi93YXNtYCBNSU1FIHR5cGUuIEZhbGxpbmcgYmFjayB0byBgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGVgIHdoaWNoIGlzIHNsb3dlci4gT3JpZ2luYWwgZXJyb3I6XG4iLCBlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhyb3cgZTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGJ5dGVzID0gYXdhaXQgbW9kdWxlLmFycmF5QnVmZmVyKCk7CiAgICByZXR1cm4gYXdhaXQgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGUoYnl0ZXMsIGltcG9ydHMpOwogIH0gZWxzZSB7CiAgICBjb25zdCBpbnN0YW5jZSA9IGF3YWl0IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKG1vZHVsZSwgaW1wb3J0cyk7CiAgICBpZiAoaW5zdGFuY2UgaW5zdGFuY2VvZiBXZWJBc3NlbWJseS5JbnN0YW5jZSkgewogICAgICByZXR1cm4gewogICAgICAgIGluc3RhbmNlLAogICAgICAgIG1vZHVsZQogICAgICB9OwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIGluc3RhbmNlOwogICAgfQogIH0KfQpmdW5jdGlvbiBfX3diZ19nZXRfaW1wb3J0cygpIHsKICBjb25zdCBpbXBvcnRzID0ge307CiAgaW1wb3J0cy53YmcgPSB7fTsKICBpbXBvcnRzLndiZy5fX3diZ19jb3B5cmVzdWx0X2IwOGVlN2QyNzNmMjk1ZGQgPSBmdW5jdGlvbiAoYXJnMCwgYXJnMSkgewogICAgY29weV9yZXN1bHQoYXJnMCA+Pj4gMCwgYXJnMSA+Pj4gMCk7CiAgfTsKICBpbXBvcnRzLndiZy5fX3diZ19jb3B5cmdiX2Q2MGNlMTdiYjA1ZDliNjcgPSBmdW5jdGlvbiAoYXJnMCkgewogICAgY29weV9yZ2IoYXJnMCA+Pj4gMCk7CiAgfTsKICBpbXBvcnRzLndiZy5fX3diZ19tYWtlY3NzUkdCXzg5M2JmMGNkOWZkYjMwMmQgPSBmdW5jdGlvbiAoYXJnMCkgewogICAgbWFrZV9jc3NSR0IoYXJnMCA+Pj4gMCk7CiAgfTsKICBpbXBvcnRzLndiZy5fX3diaW5kZ2VuX2luaXRfZXh0ZXJucmVmX3RhYmxlID0gZnVuY3Rpb24gKCkgewogICAgY29uc3QgdGFibGUgPSB3YXNtLl9fd2JpbmRnZW5fZXhwb3J0XzA7CiAgICBjb25zdCBvZmZzZXQgPSB0YWJsZS5ncm93KDQpOwogICAgdGFibGUuc2V0KDAsIHVuZGVmaW5lZCk7CiAgICB0YWJsZS5zZXQob2Zmc2V0ICsgMCwgdW5kZWZpbmVkKTsKICAgIHRhYmxlLnNldChvZmZzZXQgKyAxLCBudWxsKTsKICAgIHRhYmxlLnNldChvZmZzZXQgKyAyLCB0cnVlKTsKICAgIHRhYmxlLnNldChvZmZzZXQgKyAzLCBmYWxzZSk7CiAgfTsKICBpbXBvcnRzLndiZy5fX3diaW5kZ2VuX3Rocm93ID0gZnVuY3Rpb24gKGFyZzAsIGFyZzEpIHsKICAgIHRocm93IG5ldyBFcnJvcihnZXRTdHJpbmdGcm9tV2FzbTAoYXJnMCwgYXJnMSkpOwogIH07CiAgcmV0dXJuIGltcG9ydHM7Cn0KZnVuY3Rpb24gX193YmdfaW5pdF9tZW1vcnkoaW1wb3J0cywgbWVtb3J5KSB7fQpmdW5jdGlvbiBfX3diZ19maW5hbGl6ZV9pbml0KGluc3RhbmNlLCBtb2R1bGUpIHsKICB3YXNtID0gaW5zdGFuY2UuZXhwb3J0czsKICBfX3diZ19pbml0Ll9fd2JpbmRnZW5fd2FzbV9tb2R1bGUgPSBtb2R1bGU7CiAgY2FjaGVkVWludDhBcnJheU1lbW9yeTAgPSBudWxsOwogIHdhc20uX193YmluZGdlbl9zdGFydCgpOwogIHJldHVybiB3YXNtOwp9CmZ1bmN0aW9uIGluaXRTeW5jKG1vZHVsZSkgewogIGlmICh3YXNtICE9PSB1bmRlZmluZWQpIHJldHVybiB3YXNtOwogIGlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJykgewogICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZihtb2R1bGUpID09PSBPYmplY3QucHJvdG90eXBlKSB7CiAgICAgICh7CiAgICAgICAgbW9kdWxlCiAgICAgIH0gPSBtb2R1bGUpOwogICAgfSBlbHNlIHsKICAgICAgY29uc29sZS53YXJuKCd1c2luZyBkZXByZWNhdGVkIHBhcmFtZXRlcnMgZm9yIGBpbml0U3luYygpYDsgcGFzcyBhIHNpbmdsZSBvYmplY3QgaW5zdGVhZCcpOwogICAgfQogIH0KICBjb25zdCBpbXBvcnRzID0gX193YmdfZ2V0X2ltcG9ydHMoKTsKICBfX3diZ19pbml0X21lbW9yeShpbXBvcnRzKTsKICBpZiAoIShtb2R1bGUgaW5zdGFuY2VvZiBXZWJBc3NlbWJseS5Nb2R1bGUpKSB7CiAgICBtb2R1bGUgPSBuZXcgV2ViQXNzZW1ibHkuTW9kdWxlKG1vZHVsZSk7CiAgfQogIGNvbnN0IGluc3RhbmNlID0gbmV3IFdlYkFzc2VtYmx5Lkluc3RhbmNlKG1vZHVsZSwgaW1wb3J0cyk7CiAgcmV0dXJuIF9fd2JnX2ZpbmFsaXplX2luaXQoaW5zdGFuY2UsIG1vZHVsZSk7Cn0KYXN5bmMgZnVuY3Rpb24gX193YmdfaW5pdChtb2R1bGVfb3JfcGF0aCkgewogIGlmICh3YXNtICE9PSB1bmRlZmluZWQpIHJldHVybiB3YXNtOwogIGlmICh0eXBlb2YgbW9kdWxlX29yX3BhdGggIT09ICd1bmRlZmluZWQnKSB7CiAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKG1vZHVsZV9vcl9wYXRoKSA9PT0gT2JqZWN0LnByb3RvdHlwZSkgewogICAgICAoewogICAgICAgIG1vZHVsZV9vcl9wYXRoCiAgICAgIH0gPSBtb2R1bGVfb3JfcGF0aCk7CiAgICB9IGVsc2UgewogICAgICBjb25zb2xlLndhcm4oJ3VzaW5nIGRlcHJlY2F0ZWQgcGFyYW1ldGVycyBmb3IgdGhlIGluaXRpYWxpemF0aW9uIGZ1bmN0aW9uOyBwYXNzIGEgc2luZ2xlIG9iamVjdCBpbnN0ZWFkJyk7CiAgICB9CiAgfQogIGNvbnN0IGltcG9ydHMgPSBfX3diZ19nZXRfaW1wb3J0cygpOwogIGlmICh0eXBlb2YgbW9kdWxlX29yX3BhdGggPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBSZXF1ZXN0ID09PSAnZnVuY3Rpb24nICYmIG1vZHVsZV9vcl9wYXRoIGluc3RhbmNlb2YgUmVxdWVzdCB8fCB0eXBlb2YgVVJMID09PSAnZnVuY3Rpb24nICYmIG1vZHVsZV9vcl9wYXRoIGluc3RhbmNlb2YgVVJMKSB7CiAgICBtb2R1bGVfb3JfcGF0aCA9IGZldGNoKG1vZHVsZV9vcl9wYXRoKTsKICB9CiAgX193YmdfaW5pdF9tZW1vcnkoaW1wb3J0cyk7CiAgY29uc3QgewogICAgaW5zdGFuY2UsCiAgICBtb2R1bGUKICB9ID0gYXdhaXQgX193YmdfbG9hZChhd2FpdCBtb2R1bGVfb3JfcGF0aCwgaW1wb3J0cyk7CiAgcmV0dXJuIF9fd2JnX2ZpbmFsaXplX2luaXQoaW5zdGFuY2UsIG1vZHVsZSk7Cn0KCi8qIGhhcm1vbnkgZGVmYXVsdCBleHBvcnQgKi8gY29uc3QgcWNtcyA9ICgoLyogdW51c2VkIHB1cmUgZXhwcmVzc2lvbiBvciBzdXBlciAqLyBudWxsICYmIChfX3diZ19pbml0KSkpOwo7Ly8gLi9zcmMvY29yZS9jb2xvcnNwYWNlLmpzCgoKZnVuY3Rpb24gcmVzaXplUmdiSW1hZ2Uoc3JjLCBkZXN0LCB3MSwgaDEsIHcyLCBoMiwgYWxwaGEwMSkgewogIGNvbnN0IENPTVBPTkVOVFMgPSAzOwogIGFscGhhMDEgPSBhbHBoYTAxICE9PSAxID8gMCA6IGFscGhhMDE7CiAgY29uc3QgeFJhdGlvID0gdzEgLyB3MjsKICBjb25zdCB5UmF0aW8gPSBoMSAvIGgyOwogIGxldCBuZXdJbmRleCA9IDAsCiAgICBvbGRJbmRleDsKICBjb25zdCB4U2NhbGVkID0gbmV3IFVpbnQxNkFycmF5KHcyKTsKICBjb25zdCB3MVNjYW5saW5lID0gdzEgKiBDT01QT05FTlRTOwogIGZvciAobGV0IGkgPSAwOyBpIDwgdzI7IGkrKykgewogICAgeFNjYWxlZFtpXSA9IE1hdGguZmxvb3IoaSAqIHhSYXRpbykgKiBDT01QT05FTlRTOwogIH0KICBmb3IgKGxldCBpID0gMDsgaSA8IGgyOyBpKyspIHsKICAgIGNvbnN0IHB5ID0gTWF0aC5mbG9vcihpICogeVJhdGlvKSAqIHcxU2NhbmxpbmU7CiAgICBmb3IgKGxldCBqID0gMDsgaiA8IHcyOyBqKyspIHsKICAgICAgb2xkSW5kZXggPSBweSArIHhTY2FsZWRbal07CiAgICAgIGRlc3RbbmV3SW5kZXgrK10gPSBzcmNbb2xkSW5kZXgrK107CiAgICAgIGRlc3RbbmV3SW5kZXgrK10gPSBzcmNbb2xkSW5kZXgrK107CiAgICAgIGRlc3RbbmV3SW5kZXgrK10gPSBzcmNbb2xkSW5kZXgrK107CiAgICAgIG5ld0luZGV4ICs9IGFscGhhMDE7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIHJlc2l6ZVJnYmFJbWFnZShzcmMsIGRlc3QsIHcxLCBoMSwgdzIsIGgyLCBhbHBoYTAxKSB7CiAgY29uc3QgeFJhdGlvID0gdzEgLyB3MjsKICBjb25zdCB5UmF0aW8gPSBoMSAvIGgyOwogIGxldCBuZXdJbmRleCA9IDA7CiAgY29uc3QgeFNjYWxlZCA9IG5ldyBVaW50MTZBcnJheSh3Mik7CiAgaWYgKGFscGhhMDEgPT09IDEpIHsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdzI7IGkrKykgewogICAgICB4U2NhbGVkW2ldID0gTWF0aC5mbG9vcihpICogeFJhdGlvKTsKICAgIH0KICAgIGNvbnN0IHNyYzMyID0gbmV3IFVpbnQzMkFycmF5KHNyYy5idWZmZXIpOwogICAgY29uc3QgZGVzdDMyID0gbmV3IFVpbnQzMkFycmF5KGRlc3QuYnVmZmVyKTsKICAgIGNvbnN0IHJnYk1hc2sgPSBGZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbiA/IDB4MDBmZmZmZmYgOiAweGZmZmZmZjAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoMjsgaSsrKSB7CiAgICAgIGNvbnN0IGJ1ZiA9IHNyYzMyLnN1YmFycmF5KE1hdGguZmxvb3IoaSAqIHlSYXRpbykgKiB3MSk7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdzI7IGorKykgewogICAgICAgIGRlc3QzMltuZXdJbmRleCsrXSB8PSBidWZbeFNjYWxlZFtqXV0gJiByZ2JNYXNrOwogICAgICB9CiAgICB9CiAgfSBlbHNlIHsKICAgIGNvbnN0IENPTVBPTkVOVFMgPSA0OwogICAgY29uc3QgdzFTY2FubGluZSA9IHcxICogQ09NUE9ORU5UUzsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdzI7IGkrKykgewogICAgICB4U2NhbGVkW2ldID0gTWF0aC5mbG9vcihpICogeFJhdGlvKSAqIENPTVBPTkVOVFM7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGgyOyBpKyspIHsKICAgICAgY29uc3QgYnVmID0gc3JjLnN1YmFycmF5KE1hdGguZmxvb3IoaSAqIHlSYXRpbykgKiB3MVNjYW5saW5lKTsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB3MjsgaisrKSB7CiAgICAgICAgY29uc3Qgb2xkSW5kZXggPSB4U2NhbGVkW2pdOwogICAgICAgIGRlc3RbbmV3SW5kZXgrK10gPSBidWZbb2xkSW5kZXhdOwogICAgICAgIGRlc3RbbmV3SW5kZXgrK10gPSBidWZbb2xkSW5kZXggKyAxXTsKICAgICAgICBkZXN0W25ld0luZGV4KytdID0gYnVmW29sZEluZGV4ICsgMl07CiAgICAgIH0KICAgIH0KICB9Cn0KZnVuY3Rpb24gY29weVJnYmFJbWFnZShzcmMsIGRlc3QsIGFscGhhMDEpIHsKICBpZiAoYWxwaGEwMSA9PT0gMSkgewogICAgY29uc3Qgc3JjMzIgPSBuZXcgVWludDMyQXJyYXkoc3JjLmJ1ZmZlcik7CiAgICBjb25zdCBkZXN0MzIgPSBuZXcgVWludDMyQXJyYXkoZGVzdC5idWZmZXIpOwogICAgY29uc3QgcmdiTWFzayA9IEZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuID8gMHgwMGZmZmZmZiA6IDB4ZmZmZmZmMDA7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzcmMzMi5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGRlc3QzMltpXSB8PSBzcmMzMltpXSAmIHJnYk1hc2s7CiAgICB9CiAgfSBlbHNlIHsKICAgIGxldCBqID0gMDsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHNyYy5sZW5ndGg7IGkgPCBpaTsgaSArPSA0KSB7CiAgICAgIGRlc3RbaisrXSA9IHNyY1tpXTsKICAgICAgZGVzdFtqKytdID0gc3JjW2kgKyAxXTsKICAgICAgZGVzdFtqKytdID0gc3JjW2kgKyAyXTsKICAgIH0KICB9Cn0KY2xhc3MgQ29sb3JTcGFjZSB7CiAgc3RhdGljICNyZ2JCdWYgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoMyk7CiAgY29uc3RydWN0b3IobmFtZSwgbnVtQ29tcHMpIHsKICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICB0aGlzLm51bUNvbXBzID0gbnVtQ29tcHM7CiAgfQogIGdldFJnYihzcmMsIHNyY09mZnNldCwgb3V0cHV0ID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDMpKSB7CiAgICB0aGlzLmdldFJnYkl0ZW0oc3JjLCBzcmNPZmZzZXQsIG91dHB1dCwgMCk7CiAgICByZXR1cm4gb3V0cHV0OwogIH0KICBnZXRSZ2JIZXgoc3JjLCBzcmNPZmZzZXQpIHsKICAgIGNvbnN0IGJ1ZmZlciA9IHRoaXMuZ2V0UmdiKHNyYywgc3JjT2Zmc2V0LCBDb2xvclNwYWNlLiNyZ2JCdWYpOwogICAgcmV0dXJuIFV0aWwubWFrZUhleENvbG9yKGJ1ZmZlclswXSwgYnVmZmVyWzFdLCBidWZmZXJbMl0pOwogIH0KICBnZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICB1bnJlYWNoYWJsZSgiU2hvdWxkIG5vdCBjYWxsIENvbG9yU3BhY2UuZ2V0UmdiSXRlbSIpOwogIH0KICBnZXRSZ2JCdWZmZXIoc3JjLCBzcmNPZmZzZXQsIGNvdW50LCBkZXN0LCBkZXN0T2Zmc2V0LCBiaXRzLCBhbHBoYTAxKSB7CiAgICB1bnJlYWNoYWJsZSgiU2hvdWxkIG5vdCBjYWxsIENvbG9yU3BhY2UuZ2V0UmdiQnVmZmVyIik7CiAgfQogIGdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCwgYWxwaGEwMSkgewogICAgdW5yZWFjaGFibGUoIlNob3VsZCBub3QgY2FsbCBDb2xvclNwYWNlLmdldE91dHB1dExlbmd0aCIpOwogIH0KICBpc1Bhc3N0aHJvdWdoKGJpdHMpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgaXNEZWZhdWx0RGVjb2RlKGRlY29kZU1hcCwgYnBjKSB7CiAgICByZXR1cm4gQ29sb3JTcGFjZS5pc0RlZmF1bHREZWNvZGUoZGVjb2RlTWFwLCB0aGlzLm51bUNvbXBzKTsKICB9CiAgZmlsbFJnYihkZXN0LCBvcmlnaW5hbFdpZHRoLCBvcmlnaW5hbEhlaWdodCwgd2lkdGgsIGhlaWdodCwgYWN0dWFsSGVpZ2h0LCBicGMsIGNvbXBzLCBhbHBoYTAxKSB7CiAgICBjb25zdCBjb3VudCA9IG9yaWdpbmFsV2lkdGggKiBvcmlnaW5hbEhlaWdodDsKICAgIGxldCByZ2JCdWYgPSBudWxsOwogICAgY29uc3QgbnVtQ29tcG9uZW50Q29sb3JzID0gMSA8PCBicGM7CiAgICBjb25zdCBuZWVkc1Jlc2l6aW5nID0gb3JpZ2luYWxIZWlnaHQgIT09IGhlaWdodCB8fCBvcmlnaW5hbFdpZHRoICE9PSB3aWR0aDsKICAgIGlmICh0aGlzLmlzUGFzc3Rocm91Z2goYnBjKSkgewogICAgICByZ2JCdWYgPSBjb21wczsKICAgIH0gZWxzZSBpZiAodGhpcy5udW1Db21wcyA9PT0gMSAmJiBjb3VudCA+IG51bUNvbXBvbmVudENvbG9ycyAmJiB0aGlzLm5hbWUgIT09ICJEZXZpY2VHcmF5IiAmJiB0aGlzLm5hbWUgIT09ICJEZXZpY2VSR0IiKSB7CiAgICAgIGNvbnN0IGFsbENvbG9ycyA9IGJwYyA8PSA4ID8gbmV3IFVpbnQ4QXJyYXkobnVtQ29tcG9uZW50Q29sb3JzKSA6IG5ldyBVaW50MTZBcnJheShudW1Db21wb25lbnRDb2xvcnMpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUNvbXBvbmVudENvbG9yczsgaSsrKSB7CiAgICAgICAgYWxsQ29sb3JzW2ldID0gaTsKICAgICAgfQogICAgICBjb25zdCBjb2xvck1hcCA9IG5ldyBVaW50OENsYW1wZWRBcnJheShudW1Db21wb25lbnRDb2xvcnMgKiAzKTsKICAgICAgdGhpcy5nZXRSZ2JCdWZmZXIoYWxsQ29sb3JzLCAwLCBudW1Db21wb25lbnRDb2xvcnMsIGNvbG9yTWFwLCAwLCBicGMsIDApOwogICAgICBpZiAoIW5lZWRzUmVzaXppbmcpIHsKICAgICAgICBsZXQgZGVzdFBvcyA9IDA7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgKytpKSB7CiAgICAgICAgICBjb25zdCBrZXkgPSBjb21wc1tpXSAqIDM7CiAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBjb2xvck1hcFtrZXldOwogICAgICAgICAgZGVzdFtkZXN0UG9zKytdID0gY29sb3JNYXBba2V5ICsgMV07CiAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBjb2xvck1hcFtrZXkgKyAyXTsKICAgICAgICAgIGRlc3RQb3MgKz0gYWxwaGEwMTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmdiQnVmID0gbmV3IFVpbnQ4QXJyYXkoY291bnQgKiAzKTsKICAgICAgICBsZXQgcmdiUG9zID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyArK2kpIHsKICAgICAgICAgIGNvbnN0IGtleSA9IGNvbXBzW2ldICogMzsKICAgICAgICAgIHJnYkJ1ZltyZ2JQb3MrK10gPSBjb2xvck1hcFtrZXldOwogICAgICAgICAgcmdiQnVmW3JnYlBvcysrXSA9IGNvbG9yTWFwW2tleSArIDFdOwogICAgICAgICAgcmdiQnVmW3JnYlBvcysrXSA9IGNvbG9yTWFwW2tleSArIDJdOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIGlmICghbmVlZHNSZXNpemluZykgewogICAgICB0aGlzLmdldFJnYkJ1ZmZlcihjb21wcywgMCwgd2lkdGggKiBhY3R1YWxIZWlnaHQsIGRlc3QsIDAsIGJwYywgYWxwaGEwMSk7CiAgICB9IGVsc2UgewogICAgICByZ2JCdWYgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoY291bnQgKiAzKTsKICAgICAgdGhpcy5nZXRSZ2JCdWZmZXIoY29tcHMsIDAsIGNvdW50LCByZ2JCdWYsIDAsIGJwYywgMCk7CiAgICB9CiAgICBpZiAocmdiQnVmKSB7CiAgICAgIGlmIChuZWVkc1Jlc2l6aW5nKSB7CiAgICAgICAgcmVzaXplUmdiSW1hZ2UocmdiQnVmLCBkZXN0LCBvcmlnaW5hbFdpZHRoLCBvcmlnaW5hbEhlaWdodCwgd2lkdGgsIGhlaWdodCwgYWxwaGEwMSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbGV0IGRlc3RQb3MgPSAwLAogICAgICAgICAgcmdiUG9zID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB3aWR0aCAqIGFjdHVhbEhlaWdodDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgIGRlc3RbZGVzdFBvcysrXSA9IHJnYkJ1ZltyZ2JQb3MrK107CiAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSByZ2JCdWZbcmdiUG9zKytdOwogICAgICAgICAgZGVzdFtkZXN0UG9zKytdID0gcmdiQnVmW3JnYlBvcysrXTsKICAgICAgICAgIGRlc3RQb3MgKz0gYWxwaGEwMTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgZ2V0IHVzZXNaZXJvVG9PbmVSYW5nZSgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgInVzZXNaZXJvVG9PbmVSYW5nZSIsIHRydWUpOwogIH0KICBzdGF0aWMgaXNEZWZhdWx0RGVjb2RlKGRlY29kZSwgbnVtQ29tcHMpIHsKICAgIGlmICghQXJyYXkuaXNBcnJheShkZWNvZGUpKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgaWYgKG51bUNvbXBzICogMiAhPT0gZGVjb2RlLmxlbmd0aCkgewogICAgICB3YXJuKCJUaGUgZGVjb2RlIG1hcCBpcyBub3QgdGhlIGNvcnJlY3QgbGVuZ3RoIik7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZGVjb2RlLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgaWYgKGRlY29kZVtpXSAhPT0gMCB8fCBkZWNvZGVbaSArIDFdICE9PSAxKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KY2xhc3MgQWx0ZXJuYXRlQ1MgZXh0ZW5kcyBDb2xvclNwYWNlIHsKICBjb25zdHJ1Y3RvcihudW1Db21wcywgYmFzZSwgdGludEZuKSB7CiAgICBzdXBlcigiQWx0ZXJuYXRlIiwgbnVtQ29tcHMpOwogICAgdGhpcy5iYXNlID0gYmFzZTsKICAgIHRoaXMudGludEZuID0gdGludEZuOwogICAgdGhpcy50bXBCdWYgPSBuZXcgRmxvYXQzMkFycmF5KGJhc2UubnVtQ29tcHMpOwogIH0KICBnZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICBjb25zdCB0bXBCdWYgPSB0aGlzLnRtcEJ1ZjsKICAgIHRoaXMudGludEZuKHNyYywgc3JjT2Zmc2V0LCB0bXBCdWYsIDApOwogICAgdGhpcy5iYXNlLmdldFJnYkl0ZW0odG1wQnVmLCAwLCBkZXN0LCBkZXN0T2Zmc2V0KTsKICB9CiAgZ2V0UmdiQnVmZmVyKHNyYywgc3JjT2Zmc2V0LCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgYml0cywgYWxwaGEwMSkgewogICAgY29uc3QgdGludEZuID0gdGhpcy50aW50Rm47CiAgICBjb25zdCBiYXNlID0gdGhpcy5iYXNlOwogICAgY29uc3Qgc2NhbGUgPSAxIC8gKCgxIDw8IGJpdHMpIC0gMSk7CiAgICBjb25zdCBiYXNlTnVtQ29tcHMgPSBiYXNlLm51bUNvbXBzOwogICAgY29uc3QgdXNlc1plcm9Ub09uZVJhbmdlID0gYmFzZS51c2VzWmVyb1RvT25lUmFuZ2U7CiAgICBjb25zdCBpc1Bhc3N0aHJvdWdoID0gKGJhc2UuaXNQYXNzdGhyb3VnaCg4KSB8fCAhdXNlc1plcm9Ub09uZVJhbmdlKSAmJiBhbHBoYTAxID09PSAwOwogICAgbGV0IHBvcyA9IGlzUGFzc3Rocm91Z2ggPyBkZXN0T2Zmc2V0IDogMDsKICAgIGNvbnN0IGJhc2VCdWYgPSBpc1Bhc3N0aHJvdWdoID8gZGVzdCA6IG5ldyBVaW50OENsYW1wZWRBcnJheShiYXNlTnVtQ29tcHMgKiBjb3VudCk7CiAgICBjb25zdCBudW1Db21wcyA9IHRoaXMubnVtQ29tcHM7CiAgICBjb25zdCBzY2FsZWQgPSBuZXcgRmxvYXQzMkFycmF5KG51bUNvbXBzKTsKICAgIGNvbnN0IHRpbnRlZCA9IG5ldyBGbG9hdDMyQXJyYXkoYmFzZU51bUNvbXBzKTsKICAgIGxldCBpLCBqOwogICAgZm9yIChpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgZm9yIChqID0gMDsgaiA8IG51bUNvbXBzOyBqKyspIHsKICAgICAgICBzY2FsZWRbal0gPSBzcmNbc3JjT2Zmc2V0KytdICogc2NhbGU7CiAgICAgIH0KICAgICAgdGludEZuKHNjYWxlZCwgMCwgdGludGVkLCAwKTsKICAgICAgaWYgKHVzZXNaZXJvVG9PbmVSYW5nZSkgewogICAgICAgIGZvciAoaiA9IDA7IGogPCBiYXNlTnVtQ29tcHM7IGorKykgewogICAgICAgICAgYmFzZUJ1Zltwb3MrK10gPSB0aW50ZWRbal0gKiAyNTU7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGJhc2UuZ2V0UmdiSXRlbSh0aW50ZWQsIDAsIGJhc2VCdWYsIHBvcyk7CiAgICAgICAgcG9zICs9IGJhc2VOdW1Db21wczsKICAgICAgfQogICAgfQogICAgaWYgKCFpc1Bhc3N0aHJvdWdoKSB7CiAgICAgIGJhc2UuZ2V0UmdiQnVmZmVyKGJhc2VCdWYsIDAsIGNvdW50LCBkZXN0LCBkZXN0T2Zmc2V0LCA4LCBhbHBoYTAxKTsKICAgIH0KICB9CiAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICByZXR1cm4gdGhpcy5iYXNlLmdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCAqIHRoaXMuYmFzZS5udW1Db21wcyAvIHRoaXMubnVtQ29tcHMsIGFscGhhMDEpOwogIH0KfQpjbGFzcyBQYXR0ZXJuQ1MgZXh0ZW5kcyBDb2xvclNwYWNlIHsKICBjb25zdHJ1Y3RvcihiYXNlQ1MpIHsKICAgIHN1cGVyKCJQYXR0ZXJuIiwgbnVsbCk7CiAgICB0aGlzLmJhc2UgPSBiYXNlQ1M7CiAgfQogIGlzRGVmYXVsdERlY29kZShkZWNvZGVNYXAsIGJwYykgewogICAgdW5yZWFjaGFibGUoIlNob3VsZCBub3QgY2FsbCBQYXR0ZXJuQ1MuaXNEZWZhdWx0RGVjb2RlIik7CiAgfQp9CmNsYXNzIEluZGV4ZWRDUyBleHRlbmRzIENvbG9yU3BhY2UgewogIGNvbnN0cnVjdG9yKGJhc2UsIGhpZ2hWYWwsIGxvb2t1cCkgewogICAgc3VwZXIoIkluZGV4ZWQiLCAxKTsKICAgIHRoaXMuYmFzZSA9IGJhc2U7CiAgICB0aGlzLmhpZ2hWYWwgPSBoaWdoVmFsOwogICAgY29uc3QgbGVuZ3RoID0gYmFzZS5udW1Db21wcyAqIChoaWdoVmFsICsgMSk7CiAgICB0aGlzLmxvb2t1cCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCk7CiAgICBpZiAobG9va3VwIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICBjb25zdCBieXRlcyA9IGxvb2t1cC5nZXRCeXRlcyhsZW5ndGgpOwogICAgICB0aGlzLmxvb2t1cC5zZXQoYnl0ZXMpOwogICAgfSBlbHNlIGlmICh0eXBlb2YgbG9va3VwID09PSAic3RyaW5nIikgewogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgdGhpcy5sb29rdXBbaV0gPSBsb29rdXAuY2hhckNvZGVBdChpKSAmIDB4ZmY7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW5kZXhlZENTIC0gdW5yZWNvZ25pemVkIGxvb2t1cCB0YWJsZTogJHtsb29rdXB9YCk7CiAgICB9CiAgfQogIGdldFJnYkl0ZW0oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgIGNvbnN0IHsKICAgICAgYmFzZSwKICAgICAgaGlnaFZhbCwKICAgICAgbG9va3VwCiAgICB9ID0gdGhpczsKICAgIGNvbnN0IHN0YXJ0ID0gTWF0aENsYW1wKE1hdGgucm91bmQoc3JjW3NyY09mZnNldF0pLCAwLCBoaWdoVmFsKSAqIGJhc2UubnVtQ29tcHM7CiAgICBiYXNlLmdldFJnYkJ1ZmZlcihsb29rdXAsIHN0YXJ0LCAxLCBkZXN0LCBkZXN0T2Zmc2V0LCA4LCAwKTsKICB9CiAgZ2V0UmdiQnVmZmVyKHNyYywgc3JjT2Zmc2V0LCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgYml0cywgYWxwaGEwMSkgewogICAgY29uc3QgewogICAgICBiYXNlLAogICAgICBoaWdoVmFsLAogICAgICBsb29rdXAKICAgIH0gPSB0aGlzOwogICAgY29uc3QgewogICAgICBudW1Db21wcwogICAgfSA9IGJhc2U7CiAgICBjb25zdCBvdXRwdXREZWx0YSA9IGJhc2UuZ2V0T3V0cHV0TGVuZ3RoKG51bUNvbXBzLCBhbHBoYTAxKTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7ICsraSkgewogICAgICBjb25zdCBsb29rdXBQb3MgPSBNYXRoQ2xhbXAoTWF0aC5yb3VuZChzcmNbc3JjT2Zmc2V0KytdKSwgMCwgaGlnaFZhbCkgKiBudW1Db21wczsKICAgICAgYmFzZS5nZXRSZ2JCdWZmZXIobG9va3VwLCBsb29rdXBQb3MsIDEsIGRlc3QsIGRlc3RPZmZzZXQsIDgsIGFscGhhMDEpOwogICAgICBkZXN0T2Zmc2V0ICs9IG91dHB1dERlbHRhOwogICAgfQogIH0KICBnZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGgsIGFscGhhMDEpIHsKICAgIHJldHVybiB0aGlzLmJhc2UuZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoICogdGhpcy5iYXNlLm51bUNvbXBzLCBhbHBoYTAxKTsKICB9CiAgaXNEZWZhdWx0RGVjb2RlKGRlY29kZU1hcCwgYnBjKSB7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGVjb2RlTWFwKSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmIChkZWNvZGVNYXAubGVuZ3RoICE9PSAyKSB7CiAgICAgIHdhcm4oIkRlY29kZSBtYXAgbGVuZ3RoIGlzIG5vdCBjb3JyZWN0Iik7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGJwYykgfHwgYnBjIDwgMSkgewogICAgICB3YXJuKCJCaXRzIHBlciBjb21wb25lbnQgaXMgbm90IGNvcnJlY3QiKTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICByZXR1cm4gZGVjb2RlTWFwWzBdID09PSAwICYmIGRlY29kZU1hcFsxXSA9PT0gKDEgPDwgYnBjKSAtIDE7CiAgfQp9CmNsYXNzIERldmljZUdyYXlDUyBleHRlbmRzIENvbG9yU3BhY2UgewogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIoIkRldmljZUdyYXkiLCAxKTsKICB9CiAgZ2V0UmdiSXRlbShzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgY29uc3QgYyA9IHNyY1tzcmNPZmZzZXRdICogMjU1OwogICAgZGVzdFtkZXN0T2Zmc2V0XSA9IGRlc3RbZGVzdE9mZnNldCArIDFdID0gZGVzdFtkZXN0T2Zmc2V0ICsgMl0gPSBjOwogIH0KICBnZXRSZ2JCdWZmZXIoc3JjLCBzcmNPZmZzZXQsIGNvdW50LCBkZXN0LCBkZXN0T2Zmc2V0LCBiaXRzLCBhbHBoYTAxKSB7CiAgICBjb25zdCBzY2FsZSA9IDI1NSAvICgoMSA8PCBiaXRzKSAtIDEpOwogICAgbGV0IGogPSBzcmNPZmZzZXQsCiAgICAgIHEgPSBkZXN0T2Zmc2V0OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgKytpKSB7CiAgICAgIGNvbnN0IGMgPSBzY2FsZSAqIHNyY1tqKytdOwogICAgICBkZXN0W3ErK10gPSBjOwogICAgICBkZXN0W3ErK10gPSBjOwogICAgICBkZXN0W3ErK10gPSBjOwogICAgICBxICs9IGFscGhhMDE7CiAgICB9CiAgfQogIGdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCwgYWxwaGEwMSkgewogICAgcmV0dXJuIGlucHV0TGVuZ3RoICogKDMgKyBhbHBoYTAxKTsKICB9Cn0KY2xhc3MgRGV2aWNlUmdiQ1MgZXh0ZW5kcyBDb2xvclNwYWNlIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHN1cGVyKCJEZXZpY2VSR0IiLCAzKTsKICB9CiAgZ2V0UmdiSXRlbShzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgZGVzdFtkZXN0T2Zmc2V0XSA9IHNyY1tzcmNPZmZzZXRdICogMjU1OwogICAgZGVzdFtkZXN0T2Zmc2V0ICsgMV0gPSBzcmNbc3JjT2Zmc2V0ICsgMV0gKiAyNTU7CiAgICBkZXN0W2Rlc3RPZmZzZXQgKyAyXSA9IHNyY1tzcmNPZmZzZXQgKyAyXSAqIDI1NTsKICB9CiAgZ2V0UmdiQnVmZmVyKHNyYywgc3JjT2Zmc2V0LCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgYml0cywgYWxwaGEwMSkgewogICAgaWYgKGJpdHMgPT09IDggJiYgYWxwaGEwMSA9PT0gMCkgewogICAgICBkZXN0LnNldChzcmMuc3ViYXJyYXkoc3JjT2Zmc2V0LCBzcmNPZmZzZXQgKyBjb3VudCAqIDMpLCBkZXN0T2Zmc2V0KTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgc2NhbGUgPSAyNTUgLyAoKDEgPDwgYml0cykgLSAxKTsKICAgIGxldCBqID0gc3JjT2Zmc2V0LAogICAgICBxID0gZGVzdE9mZnNldDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7ICsraSkgewogICAgICBkZXN0W3ErK10gPSBzY2FsZSAqIHNyY1tqKytdOwogICAgICBkZXN0W3ErK10gPSBzY2FsZSAqIHNyY1tqKytdOwogICAgICBkZXN0W3ErK10gPSBzY2FsZSAqIHNyY1tqKytdOwogICAgICBxICs9IGFscGhhMDE7CiAgICB9CiAgfQogIGdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCwgYWxwaGEwMSkgewogICAgcmV0dXJuIGlucHV0TGVuZ3RoICogKDMgKyBhbHBoYTAxKSAvIDMgfCAwOwogIH0KICBpc1Bhc3N0aHJvdWdoKGJpdHMpIHsKICAgIHJldHVybiBiaXRzID09PSA4OwogIH0KfQpjbGFzcyBEZXZpY2VSZ2JhQ1MgZXh0ZW5kcyBDb2xvclNwYWNlIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHN1cGVyKCJEZXZpY2VSR0JBIiwgNCk7CiAgfQogIGdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCwgX2FscGhhMDEpIHsKICAgIHJldHVybiBpbnB1dExlbmd0aCAqIDQ7CiAgfQogIGlzUGFzc3Rocm91Z2goYml0cykgewogICAgcmV0dXJuIGJpdHMgPT09IDg7CiAgfQogIGZpbGxSZ2IoZGVzdCwgb3JpZ2luYWxXaWR0aCwgb3JpZ2luYWxIZWlnaHQsIHdpZHRoLCBoZWlnaHQsIGFjdHVhbEhlaWdodCwgYnBjLCBjb21wcywgYWxwaGEwMSkgewogICAgaWYgKG9yaWdpbmFsSGVpZ2h0ICE9PSBoZWlnaHQgfHwgb3JpZ2luYWxXaWR0aCAhPT0gd2lkdGgpIHsKICAgICAgcmVzaXplUmdiYUltYWdlKGNvbXBzLCBkZXN0LCBvcmlnaW5hbFdpZHRoLCBvcmlnaW5hbEhlaWdodCwgd2lkdGgsIGhlaWdodCwgYWxwaGEwMSk7CiAgICB9IGVsc2UgewogICAgICBjb3B5UmdiYUltYWdlKGNvbXBzLCBkZXN0LCBhbHBoYTAxKTsKICAgIH0KICB9Cn0KY2xhc3MgRGV2aWNlQ215a0NTIGV4dGVuZHMgQ29sb3JTcGFjZSB7CiAgY29uc3RydWN0b3IoKSB7CiAgICBzdXBlcigiRGV2aWNlQ01ZSyIsIDQpOwogIH0KICAjdG9SZ2Ioc3JjLCBzcmNPZmZzZXQsIHNyY1NjYWxlLCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICBjb25zdCBjID0gc3JjW3NyY09mZnNldF0gKiBzcmNTY2FsZTsKICAgIGNvbnN0IG0gPSBzcmNbc3JjT2Zmc2V0ICsgMV0gKiBzcmNTY2FsZTsKICAgIGNvbnN0IHkgPSBzcmNbc3JjT2Zmc2V0ICsgMl0gKiBzcmNTY2FsZTsKICAgIGNvbnN0IGsgPSBzcmNbc3JjT2Zmc2V0ICsgM10gKiBzcmNTY2FsZTsKICAgIGRlc3RbZGVzdE9mZnNldF0gPSAyNTUgKyBjICogKC00LjM4NzMzMjM4NDYwOTk4OCAqIGMgKyA1NC40ODYxNTE5NDE4OTE3NiAqIG0gKyAxOC44MjI5MDUwMjE2NTMwMiAqIHkgKyAyMTIuMjU2NjI0NTE2Mzk1ODUgKiBrICsgLTI4NS4yMzMxMDI2MTM3MDA0KSArIG0gKiAoMS43MTQ5NzYzNDc3MzYyMTM0ICogbSAtIDUuNjA5NjczNjkwNDA0NzMxNSAqIHkgKyAtMTcuODczODcwODYxNDE1NDQ0ICogayAtIDUuNDk3MDA2NDI3MTk2MzY2KSArIHkgKiAoLTIuNTIxNzM0MDEzMTY4MzAzMyAqIHkgLSAyMS4yNDg5MjMzMzczNTMwNzMgKiBrICsgMTcuNTExOTI3MDg0MTgxMykgKyBrICogKC0yMS44NjEyMjE0NzQ2MzYwNSAqIGsgLSAxODkuNDgxODA4MzU5MjI3NDcpOwogICAgZGVzdFtkZXN0T2Zmc2V0ICsgMV0gPSAyNTUgKyBjICogKDguODQxMDQxNDIyMDM2MTQ5ICogYyArIDYwLjExODAyNzA0NTU5NzM2NiAqIG0gKyA2Ljg3MTQyNTU5MjA0OTAwNyAqIHkgKyAzMS4xNTkxMDAxMzAwNTU5MjIgKiBrICsgLTc5LjI5NzA4NDQ4MTY1NDgpICsgbSAqICgtMTUuMzEwMzYxMzA2OTY3ODE3ICogbSArIDE3LjU3NTI1MTI2MTEwOTQ4MiAqIHkgKyAxMzEuMzUyNTA5MTI0OTM5NzYgKiBrIC0gMTkwLjk0NTMzMDI1ODg5NTEpICsgeSAqICg0LjQ0NDMzOTEwMjg1MjczOSAqIHkgKyA5Ljg2MzI4NjE0OTM0MDUgKiBrIC0gMjQuODY3NDE1ODI1NTU4NzgpICsgayAqICgtMjAuNzM3MzI1NDcxMTgxMDM0ICogayAtIDE4Ny44MDQ1MzcwOTcxOTU3OCk7CiAgICBkZXN0W2Rlc3RPZmZzZXQgKyAyXSA9IDI1NSArIGMgKiAoMC44ODQyNTIyNDMwMDAzMjk2ICogYyArIDguMDc4Njc3NTAzMTEyOTI4ICogbSArIDMwLjg5OTc4MzA5NzAzNzI5ICogeSAtIDAuMjM4ODMyMzg2ODkxNzg5MzQgKiBrICsgLTE0LjE4MzU3Njc5OTY3MzI4NikgKyBtICogKDEwLjQ5NTkzMjczNDMyMDcyICogbSArIDYzLjAyMzc4NDk0NzU0MDUyICogeSArIDUwLjYwNjk1NzY1NjM2MDczNCAqIGsgLSAxMTIuMjM4ODQyNTM3MTkyNDgpICsgeSAqICgwLjAzMjk2MDQxMTE0ODczMjE3ICogeSArIDExNS42MDM4NDQ0OTY0NjY0MSAqIGsgKyAtMTkzLjU4MjA5MzU2ODYxNTA1KSArIGsgKiAoLTIyLjMzODE2ODA3MzA5ODg2ICogayAtIDE4MC4xMjYxMzk3NDcwODM2Nyk7CiAgfQogIGdldFJnYkl0ZW0oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgIHRoaXMuI3RvUmdiKHNyYywgc3JjT2Zmc2V0LCAxLCBkZXN0LCBkZXN0T2Zmc2V0KTsKICB9CiAgZ2V0UmdiQnVmZmVyKHNyYywgc3JjT2Zmc2V0LCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgYml0cywgYWxwaGEwMSkgewogICAgY29uc3Qgc2NhbGUgPSAxIC8gKCgxIDw8IGJpdHMpIC0gMSk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgdGhpcy4jdG9SZ2Ioc3JjLCBzcmNPZmZzZXQsIHNjYWxlLCBkZXN0LCBkZXN0T2Zmc2V0KTsKICAgICAgc3JjT2Zmc2V0ICs9IDQ7CiAgICAgIGRlc3RPZmZzZXQgKz0gMyArIGFscGhhMDE7CiAgICB9CiAgfQogIGdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCwgYWxwaGEwMSkgewogICAgcmV0dXJuIGlucHV0TGVuZ3RoIC8gNCAqICgzICsgYWxwaGEwMSkgfCAwOwogIH0KfQpjbGFzcyBDYWxHcmF5Q1MgZXh0ZW5kcyBDb2xvclNwYWNlIHsKICBjb25zdHJ1Y3Rvcih3aGl0ZVBvaW50LCBibGFja1BvaW50LCBnYW1tYSkgewogICAgc3VwZXIoIkNhbEdyYXkiLCAxKTsKICAgIGlmICghd2hpdGVQb2ludCkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIldoaXRlUG9pbnQgbWlzc2luZyAtIHJlcXVpcmVkIGZvciBjb2xvciBzcGFjZSBDYWxHcmF5Iik7CiAgICB9CiAgICBbdGhpcy5YVywgdGhpcy5ZVywgdGhpcy5aV10gPSB3aGl0ZVBvaW50OwogICAgW3RoaXMuWEIsIHRoaXMuWUIsIHRoaXMuWkJdID0gYmxhY2tQb2ludCB8fCBbMCwgMCwgMF07CiAgICB0aGlzLkcgPSBnYW1tYSB8fCAxOwogICAgaWYgKHRoaXMuWFcgPCAwIHx8IHRoaXMuWlcgPCAwIHx8IHRoaXMuWVcgIT09IDEpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIFdoaXRlUG9pbnQgY29tcG9uZW50cyBmb3IgJHt0aGlzLm5hbWV9LCBubyBmYWxsYmFjayBhdmFpbGFibGVgKTsKICAgIH0KICAgIGlmICh0aGlzLlhCIDwgMCB8fCB0aGlzLllCIDwgMCB8fCB0aGlzLlpCIDwgMCkgewogICAgICBpbmZvKGBJbnZhbGlkIEJsYWNrUG9pbnQgZm9yICR7dGhpcy5uYW1lfSwgZmFsbGluZyBiYWNrIHRvIGRlZmF1bHQuYCk7CiAgICAgIHRoaXMuWEIgPSB0aGlzLllCID0gdGhpcy5aQiA9IDA7CiAgICB9CiAgICBpZiAodGhpcy5YQiAhPT0gMCB8fCB0aGlzLllCICE9PSAwIHx8IHRoaXMuWkIgIT09IDApIHsKICAgICAgd2FybihgJHt0aGlzLm5hbWV9LCBCbGFja1BvaW50OiBYQjogJHt0aGlzLlhCfSwgWUI6ICR7dGhpcy5ZQn0sIGAgKyBgWkI6ICR7dGhpcy5aQn0sIG9ubHkgZGVmYXVsdCB2YWx1ZXMgYXJlIHN1cHBvcnRlZC5gKTsKICAgIH0KICAgIGlmICh0aGlzLkcgPCAxKSB7CiAgICAgIGluZm8oYEludmFsaWQgR2FtbWE6ICR7dGhpcy5HfSBmb3IgJHt0aGlzLm5hbWV9LCBmYWxsaW5nIGJhY2sgdG8gZGVmYXVsdC5gKTsKICAgICAgdGhpcy5HID0gMTsKICAgIH0KICB9CiAgI3RvUmdiKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0LCBzY2FsZSkgewogICAgY29uc3QgQSA9IHNyY1tzcmNPZmZzZXRdICogc2NhbGU7CiAgICBjb25zdCBBRyA9IEEgKiogdGhpcy5HOwogICAgY29uc3QgTCA9IHRoaXMuWVcgKiBBRzsKICAgIGNvbnN0IHZhbCA9IE1hdGgubWF4KDI5NS44ICogTCAqKiAwLjMzMzMzMzMzMzMzMzMzMzMgLSA0MC44LCAwKTsKICAgIGRlc3RbZGVzdE9mZnNldF0gPSB2YWw7CiAgICBkZXN0W2Rlc3RPZmZzZXQgKyAxXSA9IHZhbDsKICAgIGRlc3RbZGVzdE9mZnNldCArIDJdID0gdmFsOwogIH0KICBnZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICB0aGlzLiN0b1JnYihzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCwgMSk7CiAgfQogIGdldFJnYkJ1ZmZlcihzcmMsIHNyY09mZnNldCwgY291bnQsIGRlc3QsIGRlc3RPZmZzZXQsIGJpdHMsIGFscGhhMDEpIHsKICAgIGNvbnN0IHNjYWxlID0gMSAvICgoMSA8PCBiaXRzKSAtIDEpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgKytpKSB7CiAgICAgIHRoaXMuI3RvUmdiKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0LCBzY2FsZSk7CiAgICAgIHNyY09mZnNldCArPSAxOwogICAgICBkZXN0T2Zmc2V0ICs9IDMgKyBhbHBoYTAxOwogICAgfQogIH0KICBnZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGgsIGFscGhhMDEpIHsKICAgIHJldHVybiBpbnB1dExlbmd0aCAqICgzICsgYWxwaGEwMSk7CiAgfQp9CmNsYXNzIENhbFJHQkNTIGV4dGVuZHMgQ29sb3JTcGFjZSB7CiAgc3RhdGljICNCUkFERk9SRF9TQ0FMRV9NQVRSSVggPSBuZXcgRmxvYXQzMkFycmF5KFswLjg5NTEsIDAuMjY2NCwgLTAuMTYxNCwgLTAuNzUwMiwgMS43MTM1LCAwLjAzNjcsIDAuMDM4OSwgLTAuMDY4NSwgMS4wMjk2XSk7CiAgc3RhdGljICNCUkFERk9SRF9TQ0FMRV9JTlZFUlNFX01BVFJJWCA9IG5ldyBGbG9hdDMyQXJyYXkoWzAuOTg2OTkyOSwgLTAuMTQ3MDU0MywgMC4xNTk5NjI3LCAwLjQzMjMwNTMsIDAuNTE4MzYwMywgMC4wNDkyOTEyLCAtMC4wMDg1Mjg3LCAwLjA0MDA0MjgsIDAuOTY4NDg2N10pOwogIHN0YXRpYyAjU1JHQl9ENjVfWFlaX1RPX1JHQl9NQVRSSVggPSBuZXcgRmxvYXQzMkFycmF5KFszLjI0MDQ1NDIsIC0xLjUzNzEzODUsIC0wLjQ5ODUzMTQsIC0wLjk2OTI2NjAsIDEuODc2MDEwOCwgMC4wNDE1NTYwLCAwLjA1NTY0MzQsIC0wLjIwNDAyNTksIDEuMDU3MjI1Ml0pOwogIHN0YXRpYyAjRkxBVF9XSElURVBPSU5UX01BVFJJWCA9IG5ldyBGbG9hdDMyQXJyYXkoWzEsIDEsIDFdKTsKICBzdGF0aWMgI3RlbXBOb3JtYWxpemVNYXRyaXggPSBuZXcgRmxvYXQzMkFycmF5KDMpOwogIHN0YXRpYyAjdGVtcENvbnZlcnRNYXRyaXgxID0gbmV3IEZsb2F0MzJBcnJheSgzKTsKICBzdGF0aWMgI3RlbXBDb252ZXJ0TWF0cml4MiA9IG5ldyBGbG9hdDMyQXJyYXkoMyk7CiAgc3RhdGljICNERUNPREVfTF9DT05TVEFOVCA9ICgoOCArIDE2KSAvIDExNikgKiogMyAvIDguMDsKICBjb25zdHJ1Y3Rvcih3aGl0ZVBvaW50LCBibGFja1BvaW50LCBnYW1tYSwgbWF0cml4KSB7CiAgICBzdXBlcigiQ2FsUkdCIiwgMyk7CiAgICBpZiAoIXdoaXRlUG9pbnQpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJXaGl0ZVBvaW50IG1pc3NpbmcgLSByZXF1aXJlZCBmb3IgY29sb3Igc3BhY2UgQ2FsUkdCIik7CiAgICB9CiAgICBjb25zdCBbWFcsIFlXLCBaV10gPSB0aGlzLndoaXRlUG9pbnQgPSB3aGl0ZVBvaW50OwogICAgY29uc3QgW1hCLCBZQiwgWkJdID0gdGhpcy5ibGFja1BvaW50ID0gYmxhY2tQb2ludCB8fCBuZXcgRmxvYXQzMkFycmF5KDMpOwogICAgW3RoaXMuR1IsIHRoaXMuR0csIHRoaXMuR0JdID0gZ2FtbWEgfHwgbmV3IEZsb2F0MzJBcnJheShbMSwgMSwgMV0pOwogICAgW3RoaXMuTVhBLCB0aGlzLk1ZQSwgdGhpcy5NWkEsIHRoaXMuTVhCLCB0aGlzLk1ZQiwgdGhpcy5NWkIsIHRoaXMuTVhDLCB0aGlzLk1ZQywgdGhpcy5NWkNdID0gbWF0cml4IHx8IG5ldyBGbG9hdDMyQXJyYXkoWzEsIDAsIDAsIDAsIDEsIDAsIDAsIDAsIDFdKTsKICAgIGlmIChYVyA8IDAgfHwgWlcgPCAwIHx8IFlXICE9PSAxKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBXaGl0ZVBvaW50IGNvbXBvbmVudHMgZm9yICR7dGhpcy5uYW1lfSwgbm8gZmFsbGJhY2sgYXZhaWxhYmxlYCk7CiAgICB9CiAgICBpZiAoWEIgPCAwIHx8IFlCIDwgMCB8fCBaQiA8IDApIHsKICAgICAgaW5mbyhgSW52YWxpZCBCbGFja1BvaW50IGZvciAke3RoaXMubmFtZX0gWyR7WEJ9LCAke1lCfSwgJHtaQn1dLCBgICsgImZhbGxpbmcgYmFjayB0byBkZWZhdWx0LiIpOwogICAgICB0aGlzLmJsYWNrUG9pbnQgPSBuZXcgRmxvYXQzMkFycmF5KDMpOwogICAgfQogICAgaWYgKHRoaXMuR1IgPCAwIHx8IHRoaXMuR0cgPCAwIHx8IHRoaXMuR0IgPCAwKSB7CiAgICAgIGluZm8oYEludmFsaWQgR2FtbWEgWyR7dGhpcy5HUn0sICR7dGhpcy5HR30sICR7dGhpcy5HQn1dIGZvciBgICsgYCR7dGhpcy5uYW1lfSwgZmFsbGluZyBiYWNrIHRvIGRlZmF1bHQuYCk7CiAgICAgIHRoaXMuR1IgPSB0aGlzLkdHID0gdGhpcy5HQiA9IDE7CiAgICB9CiAgfQogICNtYXRyaXhQcm9kdWN0KGEsIGIsIHJlc3VsdCkgewogICAgcmVzdWx0WzBdID0gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXSArIGFbMl0gKiBiWzJdOwogICAgcmVzdWx0WzFdID0gYVszXSAqIGJbMF0gKyBhWzRdICogYlsxXSArIGFbNV0gKiBiWzJdOwogICAgcmVzdWx0WzJdID0gYVs2XSAqIGJbMF0gKyBhWzddICogYlsxXSArIGFbOF0gKiBiWzJdOwogIH0KICAjdG9GbGF0KHNvdXJjZVdoaXRlUG9pbnQsIExNUywgcmVzdWx0KSB7CiAgICByZXN1bHRbMF0gPSBMTVNbMF0gKiAxIC8gc291cmNlV2hpdGVQb2ludFswXTsKICAgIHJlc3VsdFsxXSA9IExNU1sxXSAqIDEgLyBzb3VyY2VXaGl0ZVBvaW50WzFdOwogICAgcmVzdWx0WzJdID0gTE1TWzJdICogMSAvIHNvdXJjZVdoaXRlUG9pbnRbMl07CiAgfQogICN0b0Q2NShzb3VyY2VXaGl0ZVBvaW50LCBMTVMsIHJlc3VsdCkgewogICAgY29uc3QgRDY1WCA9IDAuOTUwNDc7CiAgICBjb25zdCBENjVZID0gMTsKICAgIGNvbnN0IEQ2NVogPSAxLjA4ODgzOwogICAgcmVzdWx0WzBdID0gTE1TWzBdICogRDY1WCAvIHNvdXJjZVdoaXRlUG9pbnRbMF07CiAgICByZXN1bHRbMV0gPSBMTVNbMV0gKiBENjVZIC8gc291cmNlV2hpdGVQb2ludFsxXTsKICAgIHJlc3VsdFsyXSA9IExNU1syXSAqIEQ2NVogLyBzb3VyY2VXaGl0ZVBvaW50WzJdOwogIH0KICAjc1JHQlRyYW5zZmVyRnVuY3Rpb24oY29sb3IpIHsKICAgIGlmIChjb2xvciA8PSAwLjAwMzEzMDgpIHsKICAgICAgcmV0dXJuIE1hdGhDbGFtcCgxMi45MiAqIGNvbG9yLCAwLCAxKTsKICAgIH0KICAgIGlmIChjb2xvciA+PSAwLjk5NTU0NTI1KSB7CiAgICAgIHJldHVybiAxOwogICAgfQogICAgcmV0dXJuIE1hdGhDbGFtcCgoMSArIDAuMDU1KSAqIGNvbG9yICoqICgxIC8gMi40KSAtIDAuMDU1LCAwLCAxKTsKICB9CiAgI2RlY29kZUwoTCkgewogICAgaWYgKEwgPCAwKSB7CiAgICAgIHJldHVybiAtdGhpcy4jZGVjb2RlTCgtTCk7CiAgICB9CiAgICBpZiAoTCA+IDguMCkgewogICAgICByZXR1cm4gKChMICsgMTYpIC8gMTE2KSAqKiAzOwogICAgfQogICAgcmV0dXJuIEwgKiBDYWxSR0JDUy4jREVDT0RFX0xfQ09OU1RBTlQ7CiAgfQogICNjb21wZW5zYXRlQmxhY2tQb2ludChzb3VyY2VCbGFja1BvaW50LCBYWVpfRmxhdCwgcmVzdWx0KSB7CiAgICBpZiAoc291cmNlQmxhY2tQb2ludFswXSA9PT0gMCAmJiBzb3VyY2VCbGFja1BvaW50WzFdID09PSAwICYmIHNvdXJjZUJsYWNrUG9pbnRbMl0gPT09IDApIHsKICAgICAgcmVzdWx0WzBdID0gWFlaX0ZsYXRbMF07CiAgICAgIHJlc3VsdFsxXSA9IFhZWl9GbGF0WzFdOwogICAgICByZXN1bHRbMl0gPSBYWVpfRmxhdFsyXTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgemVyb0RlY29kZUwgPSB0aGlzLiNkZWNvZGVMKDApOwogICAgY29uc3QgWF9EU1QgPSB6ZXJvRGVjb2RlTDsKICAgIGNvbnN0IFhfU1JDID0gdGhpcy4jZGVjb2RlTChzb3VyY2VCbGFja1BvaW50WzBdKTsKICAgIGNvbnN0IFlfRFNUID0gemVyb0RlY29kZUw7CiAgICBjb25zdCBZX1NSQyA9IHRoaXMuI2RlY29kZUwoc291cmNlQmxhY2tQb2ludFsxXSk7CiAgICBjb25zdCBaX0RTVCA9IHplcm9EZWNvZGVMOwogICAgY29uc3QgWl9TUkMgPSB0aGlzLiNkZWNvZGVMKHNvdXJjZUJsYWNrUG9pbnRbMl0pOwogICAgY29uc3QgWF9TY2FsZSA9ICgxIC0gWF9EU1QpIC8gKDEgLSBYX1NSQyk7CiAgICBjb25zdCBYX09mZnNldCA9IDEgLSBYX1NjYWxlOwogICAgY29uc3QgWV9TY2FsZSA9ICgxIC0gWV9EU1QpIC8gKDEgLSBZX1NSQyk7CiAgICBjb25zdCBZX09mZnNldCA9IDEgLSBZX1NjYWxlOwogICAgY29uc3QgWl9TY2FsZSA9ICgxIC0gWl9EU1QpIC8gKDEgLSBaX1NSQyk7CiAgICBjb25zdCBaX09mZnNldCA9IDEgLSBaX1NjYWxlOwogICAgcmVzdWx0WzBdID0gWFlaX0ZsYXRbMF0gKiBYX1NjYWxlICsgWF9PZmZzZXQ7CiAgICByZXN1bHRbMV0gPSBYWVpfRmxhdFsxXSAqIFlfU2NhbGUgKyBZX09mZnNldDsKICAgIHJlc3VsdFsyXSA9IFhZWl9GbGF0WzJdICogWl9TY2FsZSArIFpfT2Zmc2V0OwogIH0KICAjbm9ybWFsaXplV2hpdGVQb2ludFRvRmxhdChzb3VyY2VXaGl0ZVBvaW50LCBYWVpfSW4sIHJlc3VsdCkgewogICAgaWYgKHNvdXJjZVdoaXRlUG9pbnRbMF0gPT09IDEgJiYgc291cmNlV2hpdGVQb2ludFsyXSA9PT0gMSkgewogICAgICByZXN1bHRbMF0gPSBYWVpfSW5bMF07CiAgICAgIHJlc3VsdFsxXSA9IFhZWl9JblsxXTsKICAgICAgcmVzdWx0WzJdID0gWFlaX0luWzJdOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBMTVMgPSByZXN1bHQ7CiAgICB0aGlzLiNtYXRyaXhQcm9kdWN0KENhbFJHQkNTLiNCUkFERk9SRF9TQ0FMRV9NQVRSSVgsIFhZWl9JbiwgTE1TKTsKICAgIGNvbnN0IExNU19GbGF0ID0gQ2FsUkdCQ1MuI3RlbXBOb3JtYWxpemVNYXRyaXg7CiAgICB0aGlzLiN0b0ZsYXQoc291cmNlV2hpdGVQb2ludCwgTE1TLCBMTVNfRmxhdCk7CiAgICB0aGlzLiNtYXRyaXhQcm9kdWN0KENhbFJHQkNTLiNCUkFERk9SRF9TQ0FMRV9JTlZFUlNFX01BVFJJWCwgTE1TX0ZsYXQsIHJlc3VsdCk7CiAgfQogICNub3JtYWxpemVXaGl0ZVBvaW50VG9ENjUoc291cmNlV2hpdGVQb2ludCwgWFlaX0luLCByZXN1bHQpIHsKICAgIGNvbnN0IExNUyA9IHJlc3VsdDsKICAgIHRoaXMuI21hdHJpeFByb2R1Y3QoQ2FsUkdCQ1MuI0JSQURGT1JEX1NDQUxFX01BVFJJWCwgWFlaX0luLCBMTVMpOwogICAgY29uc3QgTE1TX0Q2NSA9IENhbFJHQkNTLiN0ZW1wTm9ybWFsaXplTWF0cml4OwogICAgdGhpcy4jdG9ENjUoc291cmNlV2hpdGVQb2ludCwgTE1TLCBMTVNfRDY1KTsKICAgIHRoaXMuI21hdHJpeFByb2R1Y3QoQ2FsUkdCQ1MuI0JSQURGT1JEX1NDQUxFX0lOVkVSU0VfTUFUUklYLCBMTVNfRDY1LCByZXN1bHQpOwogIH0KICAjdG9SZ2Ioc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQsIHNjYWxlKSB7CiAgICBjb25zdCBBID0gTWF0aENsYW1wKHNyY1tzcmNPZmZzZXRdICogc2NhbGUsIDAsIDEpOwogICAgY29uc3QgQiA9IE1hdGhDbGFtcChzcmNbc3JjT2Zmc2V0ICsgMV0gKiBzY2FsZSwgMCwgMSk7CiAgICBjb25zdCBDID0gTWF0aENsYW1wKHNyY1tzcmNPZmZzZXQgKyAyXSAqIHNjYWxlLCAwLCAxKTsKICAgIGNvbnN0IEFHUiA9IEEgPT09IDEgPyAxIDogQSAqKiB0aGlzLkdSOwogICAgY29uc3QgQkdHID0gQiA9PT0gMSA/IDEgOiBCICoqIHRoaXMuR0c7CiAgICBjb25zdCBDR0IgPSBDID09PSAxID8gMSA6IEMgKiogdGhpcy5HQjsKICAgIGNvbnN0IFggPSB0aGlzLk1YQSAqIEFHUiArIHRoaXMuTVhCICogQkdHICsgdGhpcy5NWEMgKiBDR0I7CiAgICBjb25zdCBZID0gdGhpcy5NWUEgKiBBR1IgKyB0aGlzLk1ZQiAqIEJHRyArIHRoaXMuTVlDICogQ0dCOwogICAgY29uc3QgWiA9IHRoaXMuTVpBICogQUdSICsgdGhpcy5NWkIgKiBCR0cgKyB0aGlzLk1aQyAqIENHQjsKICAgIGNvbnN0IFhZWiA9IENhbFJHQkNTLiN0ZW1wQ29udmVydE1hdHJpeDE7CiAgICBYWVpbMF0gPSBYOwogICAgWFlaWzFdID0gWTsKICAgIFhZWlsyXSA9IFo7CiAgICBjb25zdCBYWVpfRmxhdCA9IENhbFJHQkNTLiN0ZW1wQ29udmVydE1hdHJpeDI7CiAgICB0aGlzLiNub3JtYWxpemVXaGl0ZVBvaW50VG9GbGF0KHRoaXMud2hpdGVQb2ludCwgWFlaLCBYWVpfRmxhdCk7CiAgICBjb25zdCBYWVpfQmxhY2sgPSBDYWxSR0JDUy4jdGVtcENvbnZlcnRNYXRyaXgxOwogICAgdGhpcy4jY29tcGVuc2F0ZUJsYWNrUG9pbnQodGhpcy5ibGFja1BvaW50LCBYWVpfRmxhdCwgWFlaX0JsYWNrKTsKICAgIGNvbnN0IFhZWl9ENjUgPSBDYWxSR0JDUy4jdGVtcENvbnZlcnRNYXRyaXgyOwogICAgdGhpcy4jbm9ybWFsaXplV2hpdGVQb2ludFRvRDY1KENhbFJHQkNTLiNGTEFUX1dISVRFUE9JTlRfTUFUUklYLCBYWVpfQmxhY2ssIFhZWl9ENjUpOwogICAgY29uc3QgU1JHQiA9IENhbFJHQkNTLiN0ZW1wQ29udmVydE1hdHJpeDE7CiAgICB0aGlzLiNtYXRyaXhQcm9kdWN0KENhbFJHQkNTLiNTUkdCX0Q2NV9YWVpfVE9fUkdCX01BVFJJWCwgWFlaX0Q2NSwgU1JHQik7CiAgICBkZXN0W2Rlc3RPZmZzZXRdID0gdGhpcy4jc1JHQlRyYW5zZmVyRnVuY3Rpb24oU1JHQlswXSkgKiAyNTU7CiAgICBkZXN0W2Rlc3RPZmZzZXQgKyAxXSA9IHRoaXMuI3NSR0JUcmFuc2ZlckZ1bmN0aW9uKFNSR0JbMV0pICogMjU1OwogICAgZGVzdFtkZXN0T2Zmc2V0ICsgMl0gPSB0aGlzLiNzUkdCVHJhbnNmZXJGdW5jdGlvbihTUkdCWzJdKSAqIDI1NTsKICB9CiAgZ2V0UmdiSXRlbShzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgdGhpcy4jdG9SZ2Ioc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQsIDEpOwogIH0KICBnZXRSZ2JCdWZmZXIoc3JjLCBzcmNPZmZzZXQsIGNvdW50LCBkZXN0LCBkZXN0T2Zmc2V0LCBiaXRzLCBhbHBoYTAxKSB7CiAgICBjb25zdCBzY2FsZSA9IDEgLyAoKDEgPDwgYml0cykgLSAxKTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7ICsraSkgewogICAgICB0aGlzLiN0b1JnYihzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCwgc2NhbGUpOwogICAgICBzcmNPZmZzZXQgKz0gMzsKICAgICAgZGVzdE9mZnNldCArPSAzICsgYWxwaGEwMTsKICAgIH0KICB9CiAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICByZXR1cm4gaW5wdXRMZW5ndGggKiAoMyArIGFscGhhMDEpIC8gMyB8IDA7CiAgfQp9CmNsYXNzIExhYkNTIGV4dGVuZHMgQ29sb3JTcGFjZSB7CiAgY29uc3RydWN0b3Iod2hpdGVQb2ludCwgYmxhY2tQb2ludCwgcmFuZ2UpIHsKICAgIHN1cGVyKCJMYWIiLCAzKTsKICAgIGlmICghd2hpdGVQb2ludCkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIldoaXRlUG9pbnQgbWlzc2luZyAtIHJlcXVpcmVkIGZvciBjb2xvciBzcGFjZSBMYWIiKTsKICAgIH0KICAgIFt0aGlzLlhXLCB0aGlzLllXLCB0aGlzLlpXXSA9IHdoaXRlUG9pbnQ7CiAgICBbdGhpcy5hbWluLCB0aGlzLmFtYXgsIHRoaXMuYm1pbiwgdGhpcy5ibWF4XSA9IHJhbmdlIHx8IFstMTAwLCAxMDAsIC0xMDAsIDEwMF07CiAgICBbdGhpcy5YQiwgdGhpcy5ZQiwgdGhpcy5aQl0gPSBibGFja1BvaW50IHx8IFswLCAwLCAwXTsKICAgIGlmICh0aGlzLlhXIDwgMCB8fCB0aGlzLlpXIDwgMCB8fCB0aGlzLllXICE9PSAxKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBXaGl0ZVBvaW50IGNvbXBvbmVudHMsIG5vIGZhbGxiYWNrIGF2YWlsYWJsZSIpOwogICAgfQogICAgaWYgKHRoaXMuWEIgPCAwIHx8IHRoaXMuWUIgPCAwIHx8IHRoaXMuWkIgPCAwKSB7CiAgICAgIGluZm8oIkludmFsaWQgQmxhY2tQb2ludCwgZmFsbGluZyBiYWNrIHRvIGRlZmF1bHQiKTsKICAgICAgdGhpcy5YQiA9IHRoaXMuWUIgPSB0aGlzLlpCID0gMDsKICAgIH0KICAgIGlmICh0aGlzLmFtaW4gPiB0aGlzLmFtYXggfHwgdGhpcy5ibWluID4gdGhpcy5ibWF4KSB7CiAgICAgIGluZm8oIkludmFsaWQgUmFuZ2UsIGZhbGxpbmcgYmFjayB0byBkZWZhdWx0cyIpOwogICAgICB0aGlzLmFtaW4gPSAtMTAwOwogICAgICB0aGlzLmFtYXggPSAxMDA7CiAgICAgIHRoaXMuYm1pbiA9IC0xMDA7CiAgICAgIHRoaXMuYm1heCA9IDEwMDsKICAgIH0KICB9CiAgI2ZuX2coeCkgewogICAgcmV0dXJuIHggPj0gNiAvIDI5ID8geCAqKiAzIDogMTA4IC8gODQxICogKHggLSA0IC8gMjkpOwogIH0KICAjZGVjb2RlKHZhbHVlLCBoaWdoMSwgbG93MiwgaGlnaDIpIHsKICAgIHJldHVybiBsb3cyICsgdmFsdWUgKiAoaGlnaDIgLSBsb3cyKSAvIGhpZ2gxOwogIH0KICAjdG9SZ2Ioc3JjLCBzcmNPZmZzZXQsIG1heFZhbCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgbGV0IExzID0gc3JjW3NyY09mZnNldF07CiAgICBsZXQgYXMgPSBzcmNbc3JjT2Zmc2V0ICsgMV07CiAgICBsZXQgYnMgPSBzcmNbc3JjT2Zmc2V0ICsgMl07CiAgICBpZiAobWF4VmFsICE9PSBmYWxzZSkgewogICAgICBMcyA9IHRoaXMuI2RlY29kZShMcywgbWF4VmFsLCAwLCAxMDApOwogICAgICBhcyA9IHRoaXMuI2RlY29kZShhcywgbWF4VmFsLCB0aGlzLmFtaW4sIHRoaXMuYW1heCk7CiAgICAgIGJzID0gdGhpcy4jZGVjb2RlKGJzLCBtYXhWYWwsIHRoaXMuYm1pbiwgdGhpcy5ibWF4KTsKICAgIH0KICAgIGlmIChhcyA+IHRoaXMuYW1heCkgewogICAgICBhcyA9IHRoaXMuYW1heDsKICAgIH0gZWxzZSBpZiAoYXMgPCB0aGlzLmFtaW4pIHsKICAgICAgYXMgPSB0aGlzLmFtaW47CiAgICB9CiAgICBpZiAoYnMgPiB0aGlzLmJtYXgpIHsKICAgICAgYnMgPSB0aGlzLmJtYXg7CiAgICB9IGVsc2UgaWYgKGJzIDwgdGhpcy5ibWluKSB7CiAgICAgIGJzID0gdGhpcy5ibWluOwogICAgfQogICAgY29uc3QgTSA9IChMcyArIDE2KSAvIDExNjsKICAgIGNvbnN0IEwgPSBNICsgYXMgLyA1MDA7CiAgICBjb25zdCBOID0gTSAtIGJzIC8gMjAwOwogICAgY29uc3QgWCA9IHRoaXMuWFcgKiB0aGlzLiNmbl9nKEwpOwogICAgY29uc3QgWSA9IHRoaXMuWVcgKiB0aGlzLiNmbl9nKE0pOwogICAgY29uc3QgWiA9IHRoaXMuWlcgKiB0aGlzLiNmbl9nKE4pOwogICAgbGV0IHIsIGcsIGI7CiAgICBpZiAodGhpcy5aVyA8IDEpIHsKICAgICAgciA9IFggKiAzLjEzMzkgKyBZICogLTEuNjE3ICsgWiAqIC0wLjQ5MDY7CiAgICAgIGcgPSBYICogLTAuOTc4NSArIFkgKiAxLjkxNiArIFogKiAwLjAzMzM7CiAgICAgIGIgPSBYICogMC4wNzIgKyBZICogLTAuMjI5ICsgWiAqIDEuNDA1NzsKICAgIH0gZWxzZSB7CiAgICAgIHIgPSBYICogMy4yNDA2ICsgWSAqIC0xLjUzNzIgKyBaICogLTAuNDk4NjsKICAgICAgZyA9IFggKiAtMC45Njg5ICsgWSAqIDEuODc1OCArIFogKiAwLjA0MTU7CiAgICAgIGIgPSBYICogMC4wNTU3ICsgWSAqIC0wLjIwNCArIFogKiAxLjA1NzsKICAgIH0KICAgIGRlc3RbZGVzdE9mZnNldF0gPSBNYXRoLnNxcnQocikgKiAyNTU7CiAgICBkZXN0W2Rlc3RPZmZzZXQgKyAxXSA9IE1hdGguc3FydChnKSAqIDI1NTsKICAgIGRlc3RbZGVzdE9mZnNldCArIDJdID0gTWF0aC5zcXJ0KGIpICogMjU1OwogIH0KICBnZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICB0aGlzLiN0b1JnYihzcmMsIHNyY09mZnNldCwgZmFsc2UsIGRlc3QsIGRlc3RPZmZzZXQpOwogIH0KICBnZXRSZ2JCdWZmZXIoc3JjLCBzcmNPZmZzZXQsIGNvdW50LCBkZXN0LCBkZXN0T2Zmc2V0LCBiaXRzLCBhbHBoYTAxKSB7CiAgICBjb25zdCBtYXhWYWwgPSAoMSA8PCBiaXRzKSAtIDE7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgdGhpcy4jdG9SZ2Ioc3JjLCBzcmNPZmZzZXQsIG1heFZhbCwgZGVzdCwgZGVzdE9mZnNldCk7CiAgICAgIHNyY09mZnNldCArPSAzOwogICAgICBkZXN0T2Zmc2V0ICs9IDMgKyBhbHBoYTAxOwogICAgfQogIH0KICBnZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGgsIGFscGhhMDEpIHsKICAgIHJldHVybiBpbnB1dExlbmd0aCAqICgzICsgYWxwaGEwMSkgLyAzIHwgMDsKICB9CiAgaXNEZWZhdWx0RGVjb2RlKGRlY29kZU1hcCwgYnBjKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgZ2V0IHVzZXNaZXJvVG9PbmVSYW5nZSgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgInVzZXNaZXJvVG9PbmVSYW5nZSIsIGZhbHNlKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2ljY19jb2xvcnNwYWNlLmpzCgoKCgpmdW5jdGlvbiBmZXRjaFN5bmModXJsKSB7CiAgY29uc3QgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7CiAgeGhyLm9wZW4oIkdFVCIsIHVybCwgZmFsc2UpOwogIHhoci5yZXNwb25zZVR5cGUgPSAiYXJyYXlidWZmZXIiOwogIHhoci5zZW5kKG51bGwpOwogIHJldHVybiB4aHIucmVzcG9uc2U7Cn0KY2xhc3MgSWNjQ29sb3JTcGFjZSBleHRlbmRzIENvbG9yU3BhY2UgewogICN0cmFuc2Zvcm1lcjsKICAjY29udmVydFBpeGVsOwogIHN0YXRpYyAjdXNlV2FzbSA9IHRydWU7CiAgc3RhdGljICN3YXNtVXJsID0gbnVsbDsKICBzdGF0aWMgI2ZpbmFsaXplciA9IG51bGw7CiAgY29uc3RydWN0b3IoaWNjUHJvZmlsZSwgbmFtZSwgbnVtQ29tcHMpIHsKICAgIGlmICghSWNjQ29sb3JTcGFjZS5pc1VzYWJsZSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIk5vIElDQyBjb2xvciBzcGFjZSBzdXBwb3J0Iik7CiAgICB9CiAgICBzdXBlcihuYW1lLCBudW1Db21wcyk7CiAgICBsZXQgaW5UeXBlOwogICAgc3dpdGNoIChudW1Db21wcykgewogICAgICBjYXNlIDE6CiAgICAgICAgaW5UeXBlID0gRGF0YVR5cGUuR3JheTg7CiAgICAgICAgdGhpcy4jY29udmVydFBpeGVsID0gKHNyYywgc3JjT2Zmc2V0LCBjc3MpID0+IHFjbXNfY29udmVydF9vbmUodGhpcy4jdHJhbnNmb3JtZXIsIHNyY1tzcmNPZmZzZXRdICogMjU1LCBjc3MpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDM6CiAgICAgICAgaW5UeXBlID0gRGF0YVR5cGUuUkdCODsKICAgICAgICB0aGlzLiNjb252ZXJ0UGl4ZWwgPSAoc3JjLCBzcmNPZmZzZXQsIGNzcykgPT4gcWNtc19jb252ZXJ0X3RocmVlKHRoaXMuI3RyYW5zZm9ybWVyLCBzcmNbc3JjT2Zmc2V0XSAqIDI1NSwgc3JjW3NyY09mZnNldCArIDFdICogMjU1LCBzcmNbc3JjT2Zmc2V0ICsgMl0gKiAyNTUsIGNzcyk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgNDoKICAgICAgICBpblR5cGUgPSBEYXRhVHlwZS5DTVlLOwogICAgICAgIHRoaXMuI2NvbnZlcnRQaXhlbCA9IChzcmMsIHNyY09mZnNldCwgY3NzKSA9PiBxY21zX2NvbnZlcnRfZm91cih0aGlzLiN0cmFuc2Zvcm1lciwgc3JjW3NyY09mZnNldF0gKiAyNTUsIHNyY1tzcmNPZmZzZXQgKyAxXSAqIDI1NSwgc3JjW3NyY09mZnNldCArIDJdICogMjU1LCBzcmNbc3JjT2Zmc2V0ICsgM10gKiAyNTUsIGNzcyk7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBudW1iZXIgb2YgY29tcG9uZW50czogJHtudW1Db21wc31gKTsKICAgIH0KICAgIHRoaXMuI3RyYW5zZm9ybWVyID0gcWNtc190cmFuc2Zvcm1lcl9mcm9tX21lbW9yeShpY2NQcm9maWxlLCBpblR5cGUsIEludGVudC5QZXJjZXB0dWFsKTsKICAgIGlmICghdGhpcy4jdHJhbnNmb3JtZXIpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJGYWlsZWQgdG8gY3JlYXRlIElDQyBjb2xvciBzcGFjZSIpOwogICAgfQogICAgSWNjQ29sb3JTcGFjZS4jZmluYWxpemVyIHx8PSBuZXcgRmluYWxpemF0aW9uUmVnaXN0cnkodHJhbnNmb3JtZXIgPT4gewogICAgICBxY21zX2Ryb3BfdHJhbnNmb3JtZXIodHJhbnNmb3JtZXIpOwogICAgfSk7CiAgICBJY2NDb2xvclNwYWNlLiNmaW5hbGl6ZXIucmVnaXN0ZXIodGhpcywgdGhpcy4jdHJhbnNmb3JtZXIpOwogIH0KICBnZXRSZ2JIZXgoc3JjLCBzcmNPZmZzZXQpIHsKICAgIHRoaXMuI2NvbnZlcnRQaXhlbChzcmMsIHNyY09mZnNldCwgdHJ1ZSk7CiAgICByZXR1cm4gUUNNUy5fY3NzQ29sb3I7CiAgfQogIGdldFJnYkl0ZW0oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgIFFDTVMuX2Rlc3RCdWZmZXIgPSBkZXN0OwogICAgUUNNUy5fZGVzdE9mZnNldCA9IGRlc3RPZmZzZXQ7CiAgICBRQ01TLl9kZXN0TGVuZ3RoID0gMzsKICAgIHRoaXMuI2NvbnZlcnRQaXhlbChzcmMsIHNyY09mZnNldCwgZmFsc2UpOwogICAgUUNNUy5fZGVzdEJ1ZmZlciA9IG51bGw7CiAgfQogIGdldFJnYkJ1ZmZlcihzcmMsIHNyY09mZnNldCwgY291bnQsIGRlc3QsIGRlc3RPZmZzZXQsIGJpdHMsIGFscGhhMDEpIHsKICAgIHNyYyA9IHNyYy5zdWJhcnJheShzcmNPZmZzZXQsIHNyY09mZnNldCArIGNvdW50ICogdGhpcy5udW1Db21wcyk7CiAgICBpZiAoYml0cyAhPT0gOCkgewogICAgICBjb25zdCBzY2FsZSA9IDI1NSAvICgoMSA8PCBiaXRzKSAtIDEpOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzcmMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIHNyY1tpXSAqPSBzY2FsZTsKICAgICAgfQogICAgfQogICAgUUNNUy5fbXVzdEFkZEFscGhhID0gYWxwaGEwMSAmJiBkZXN0LmJ1ZmZlciA9PT0gc3JjLmJ1ZmZlcjsKICAgIFFDTVMuX2Rlc3RCdWZmZXIgPSBkZXN0OwogICAgUUNNUy5fZGVzdE9mZnNldCA9IGRlc3RPZmZzZXQ7CiAgICBRQ01TLl9kZXN0TGVuZ3RoID0gY291bnQgKiAoMyArIGFscGhhMDEpOwogICAgcWNtc19jb252ZXJ0X2FycmF5KHRoaXMuI3RyYW5zZm9ybWVyLCBzcmMpOwogICAgUUNNUy5fbXVzdEFkZEFscGhhID0gZmFsc2U7CiAgICBRQ01TLl9kZXN0QnVmZmVyID0gbnVsbDsKICB9CiAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICByZXR1cm4gaW5wdXRMZW5ndGggLyB0aGlzLm51bUNvbXBzICogKDMgKyBhbHBoYTAxKSB8IDA7CiAgfQogIHN0YXRpYyBzZXRPcHRpb25zKHsKICAgIHVzZVdhc20sCiAgICB1c2VXb3JrZXJGZXRjaCwKICAgIHdhc21VcmwKICB9KSB7CiAgICBpZiAoIXVzZVdvcmtlckZldGNoKSB7CiAgICAgIHRoaXMuI3VzZVdhc20gPSBmYWxzZTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy4jdXNlV2FzbSA9IHVzZVdhc207CiAgICB0aGlzLiN3YXNtVXJsID0gd2FzbVVybDsKICB9CiAgc3RhdGljIGdldCBpc1VzYWJsZSgpIHsKICAgIGxldCBpc1VzYWJsZSA9IGZhbHNlOwogICAgaWYgKHRoaXMuI3VzZVdhc20pIHsKICAgICAgaWYgKHRoaXMuI3dhc21VcmwpIHsKICAgICAgICB0cnkgewogICAgICAgICAgdGhpcy5fbW9kdWxlID0gaW5pdFN5bmMoewogICAgICAgICAgICBtb2R1bGU6IGZldGNoU3luYyhgJHt0aGlzLiN3YXNtVXJsfXFjbXNfYmcud2FzbWApCiAgICAgICAgICB9KTsKICAgICAgICAgIGlzVXNhYmxlID0gISF0aGlzLl9tb2R1bGU7CiAgICAgICAgICBRQ01TLl9tZW1vcnkgPSB0aGlzLl9tb2R1bGUubWVtb3J5OwogICAgICAgICAgUUNNUy5fbWFrZUhleENvbG9yID0gVXRpbC5tYWtlSGV4Q29sb3I7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgd2FybihgSUNDQmFzZWQgY29sb3Igc3BhY2U6ICIke2V9Ii5gKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgd2FybigiTm8gSUNDIGNvbG9yIHNwYWNlIHN1cHBvcnQgZHVlIHRvIG1pc3NpbmcgYHdhc21VcmxgIEFQSSBvcHRpb24iKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiaXNVc2FibGUiLCBpc1VzYWJsZSk7CiAgfQp9CmNsYXNzIENteWtJQ0NCYXNlZENTIGV4dGVuZHMgSWNjQ29sb3JTcGFjZSB7CiAgc3RhdGljICNpY2NVcmw7CiAgY29uc3RydWN0b3IoKSB7CiAgICBjb25zdCBpY2NQcm9maWxlID0gbmV3IFVpbnQ4QXJyYXkoZmV0Y2hTeW5jKGAke0NteWtJQ0NCYXNlZENTLiNpY2NVcmx9Q0dBVFMwMDFDb21wYXQtdjItbWljcm8uaWNjYCkpOwogICAgc3VwZXIoaWNjUHJvZmlsZSwgIkRldmljZUNNWUsiLCA0KTsKICB9CiAgc3RhdGljIHNldE9wdGlvbnMoewogICAgaWNjVXJsCiAgfSkgewogICAgdGhpcy4jaWNjVXJsID0gaWNjVXJsOwogIH0KICBzdGF0aWMgZ2V0IGlzVXNhYmxlKCkgewogICAgbGV0IGlzVXNhYmxlID0gZmFsc2U7CiAgICBpZiAoSWNjQ29sb3JTcGFjZS5pc1VzYWJsZSkgewogICAgICBpZiAodGhpcy4jaWNjVXJsKSB7CiAgICAgICAgaXNVc2FibGUgPSB0cnVlOwogICAgICB9IGVsc2UgewogICAgICAgIHdhcm4oIk5vIENNWUsgSUNDIHByb2ZpbGUgc3VwcG9ydCBkdWUgdG8gbWlzc2luZyBgaWNjVXJsYCBBUEkgb3B0aW9uIik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImlzVXNhYmxlIiwgaXNVc2FibGUpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvc3RyZWFtLmpzCgoKY2xhc3MgU3RyZWFtIGV4dGVuZHMgQmFzZVN0cmVhbSB7CiAgY29uc3RydWN0b3IoYXJyYXlCdWZmZXIsIHN0YXJ0LCBsZW5ndGgsIGRpY3QpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLmJ5dGVzID0gYXJyYXlCdWZmZXIgaW5zdGFuY2VvZiBVaW50OEFycmF5ID8gYXJyYXlCdWZmZXIgOiBuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcik7CiAgICB0aGlzLnN0YXJ0ID0gc3RhcnQgfHwgMDsKICAgIHRoaXMucG9zID0gdGhpcy5zdGFydDsKICAgIHRoaXMuZW5kID0gc3RhcnQgKyBsZW5ndGggfHwgdGhpcy5ieXRlcy5sZW5ndGg7CiAgICB0aGlzLmRpY3QgPSBkaWN0OwogIH0KICBnZXQgbGVuZ3RoKCkgewogICAgcmV0dXJuIHRoaXMuZW5kIC0gdGhpcy5zdGFydDsKICB9CiAgZ2V0IGlzRW1wdHkoKSB7CiAgICByZXR1cm4gdGhpcy5sZW5ndGggPT09IDA7CiAgfQogIGdldEJ5dGUoKSB7CiAgICBpZiAodGhpcy5wb3MgPj0gdGhpcy5lbmQpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgcmV0dXJuIHRoaXMuYnl0ZXNbdGhpcy5wb3MrK107CiAgfQogIGdldEJ5dGVzKGxlbmd0aCkgewogICAgY29uc3QgYnl0ZXMgPSB0aGlzLmJ5dGVzOwogICAgY29uc3QgcG9zID0gdGhpcy5wb3M7CiAgICBjb25zdCBzdHJFbmQgPSB0aGlzLmVuZDsKICAgIGlmICghbGVuZ3RoKSB7CiAgICAgIHRoaXMucG9zID0gc3RyRW5kOwogICAgICByZXR1cm4gYnl0ZXMuc3ViYXJyYXkocG9zLCBzdHJFbmQpOwogICAgfQogICAgbGV0IGVuZCA9IHBvcyArIGxlbmd0aDsKICAgIGlmIChlbmQgPiBzdHJFbmQpIHsKICAgICAgZW5kID0gc3RyRW5kOwogICAgfQogICAgdGhpcy5wb3MgPSBlbmQ7CiAgICByZXR1cm4gYnl0ZXMuc3ViYXJyYXkocG9zLCBlbmQpOwogIH0KICBnZXRCeXRlUmFuZ2UoYmVnaW4sIGVuZCkgewogICAgaWYgKGJlZ2luIDwgMCkgewogICAgICBiZWdpbiA9IDA7CiAgICB9CiAgICBpZiAoZW5kID4gdGhpcy5lbmQpIHsKICAgICAgZW5kID0gdGhpcy5lbmQ7CiAgICB9CiAgICByZXR1cm4gdGhpcy5ieXRlcy5zdWJhcnJheShiZWdpbiwgZW5kKTsKICB9CiAgcmVzZXQoKSB7CiAgICB0aGlzLnBvcyA9IHRoaXMuc3RhcnQ7CiAgfQogIG1vdmVTdGFydCgpIHsKICAgIHRoaXMuc3RhcnQgPSB0aGlzLnBvczsKICB9CiAgbWFrZVN1YlN0cmVhbShzdGFydCwgbGVuZ3RoLCBkaWN0ID0gbnVsbCkgewogICAgcmV0dXJuIG5ldyBTdHJlYW0odGhpcy5ieXRlcy5idWZmZXIsIHN0YXJ0LCBsZW5ndGgsIGRpY3QpOwogIH0KICBjbG9uZSgpIHsKICAgIHJldHVybiBuZXcgU3RyZWFtKHRoaXMuYnl0ZXMuYnVmZmVyLCB0aGlzLnN0YXJ0LCB0aGlzLmVuZCAtIHRoaXMuc3RhcnQsIHRoaXMuZGljdC5jbG9uZSgpKTsKICB9Cn0KY2xhc3MgU3RyaW5nU3RyZWFtIGV4dGVuZHMgU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHIpIHsKICAgIHN1cGVyKHN0cmluZ1RvQnl0ZXMoc3RyKSk7CiAgfQp9CmNsYXNzIE51bGxTdHJlYW0gZXh0ZW5kcyBTdHJlYW0gewogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIobmV3IFVpbnQ4QXJyYXkoMCkpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvY2h1bmtlZF9zdHJlYW0uanMKCgoKY2xhc3MgQ2h1bmtlZFN0cmVhbSBleHRlbmRzIFN0cmVhbSB7CiAgcHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoID0gMDsKICBfbGFzdFN1Y2Nlc3NmdWxFbnN1cmVCeXRlQ2h1bmsgPSAtMTsKICBfbG9hZGVkQ2h1bmtzID0gbmV3IFNldCgpOwogIGNvbnN0cnVjdG9yKGxlbmd0aCwgY2h1bmtTaXplLCBtYW5hZ2VyKSB7CiAgICBzdXBlcihuZXcgVWludDhBcnJheShsZW5ndGgpLCAwLCBsZW5ndGgsIG51bGwpOwogICAgdGhpcy5jaHVua1NpemUgPSBjaHVua1NpemU7CiAgICB0aGlzLm51bUNodW5rcyA9IE1hdGguY2VpbChsZW5ndGggLyBjaHVua1NpemUpOwogICAgdGhpcy5tYW5hZ2VyID0gbWFuYWdlcjsKICB9CiAgZ2V0TWlzc2luZ0NodW5rcygpIHsKICAgIGNvbnN0IGNodW5rcyA9IFtdOwogICAgZm9yIChsZXQgY2h1bmsgPSAwLCBuID0gdGhpcy5udW1DaHVua3M7IGNodW5rIDwgbjsgKytjaHVuaykgewogICAgICBpZiAoIXRoaXMuX2xvYWRlZENodW5rcy5oYXMoY2h1bmspKSB7CiAgICAgICAgY2h1bmtzLnB1c2goY2h1bmspOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gY2h1bmtzOwogIH0KICBnZXQgbnVtQ2h1bmtzTG9hZGVkKCkgewogICAgcmV0dXJuIHRoaXMuX2xvYWRlZENodW5rcy5zaXplOwogIH0KICBnZXQgaXNEYXRhTG9hZGVkKCkgewogICAgcmV0dXJuIHRoaXMubnVtQ2h1bmtzTG9hZGVkID09PSB0aGlzLm51bUNodW5rczsKICB9CiAgb25SZWNlaXZlRGF0YShiZWdpbiwgY2h1bmspIHsKICAgIGNvbnN0IGNodW5rU2l6ZSA9IHRoaXMuY2h1bmtTaXplOwogICAgaWYgKGJlZ2luICUgY2h1bmtTaXplICE9PSAwKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcihgQmFkIGJlZ2luIG9mZnNldDogJHtiZWdpbn1gKTsKICAgIH0KICAgIGNvbnN0IGVuZCA9IGJlZ2luICsgY2h1bmsuYnl0ZUxlbmd0aDsKICAgIGlmIChlbmQgJSBjaHVua1NpemUgIT09IDAgJiYgZW5kICE9PSB0aGlzLmJ5dGVzLmxlbmd0aCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYEJhZCBlbmQgb2Zmc2V0OiAke2VuZH1gKTsKICAgIH0KICAgIHRoaXMuYnl0ZXMuc2V0KG5ldyBVaW50OEFycmF5KGNodW5rKSwgYmVnaW4pOwogICAgY29uc3QgYmVnaW5DaHVuayA9IE1hdGguZmxvb3IoYmVnaW4gLyBjaHVua1NpemUpOwogICAgY29uc3QgZW5kQ2h1bmsgPSBNYXRoLmZsb29yKChlbmQgLSAxKSAvIGNodW5rU2l6ZSkgKyAxOwogICAgZm9yIChsZXQgY3VyQ2h1bmsgPSBiZWdpbkNodW5rOyBjdXJDaHVuayA8IGVuZENodW5rOyArK2N1ckNodW5rKSB7CiAgICAgIHRoaXMuX2xvYWRlZENodW5rcy5hZGQoY3VyQ2h1bmspOwogICAgfQogIH0KICBvblJlY2VpdmVQcm9ncmVzc2l2ZURhdGEoZGF0YSkgewogICAgbGV0IHBvc2l0aW9uID0gdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGg7CiAgICBjb25zdCBiZWdpbkNodW5rID0gTWF0aC5mbG9vcihwb3NpdGlvbiAvIHRoaXMuY2h1bmtTaXplKTsKICAgIHRoaXMuYnl0ZXMuc2V0KG5ldyBVaW50OEFycmF5KGRhdGEpLCBwb3NpdGlvbik7CiAgICBwb3NpdGlvbiArPSBkYXRhLmJ5dGVMZW5ndGg7CiAgICB0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aCA9IHBvc2l0aW9uOwogICAgY29uc3QgZW5kQ2h1bmsgPSBwb3NpdGlvbiA+PSB0aGlzLmVuZCA/IHRoaXMubnVtQ2h1bmtzIDogTWF0aC5mbG9vcihwb3NpdGlvbiAvIHRoaXMuY2h1bmtTaXplKTsKICAgIGZvciAobGV0IGN1ckNodW5rID0gYmVnaW5DaHVuazsgY3VyQ2h1bmsgPCBlbmRDaHVuazsgKytjdXJDaHVuaykgewogICAgICB0aGlzLl9sb2FkZWRDaHVua3MuYWRkKGN1ckNodW5rKTsKICAgIH0KICB9CiAgZW5zdXJlQnl0ZShwb3MpIHsKICAgIGlmIChwb3MgPCB0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBjaHVuayA9IE1hdGguZmxvb3IocG9zIC8gdGhpcy5jaHVua1NpemUpOwogICAgaWYgKGNodW5rID4gdGhpcy5udW1DaHVua3MpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKGNodW5rID09PSB0aGlzLl9sYXN0U3VjY2Vzc2Z1bEVuc3VyZUJ5dGVDaHVuaykgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoIXRoaXMuX2xvYWRlZENodW5rcy5oYXMoY2h1bmspKSB7CiAgICAgIHRocm93IG5ldyBNaXNzaW5nRGF0YUV4Y2VwdGlvbihwb3MsIHBvcyArIDEpOwogICAgfQogICAgdGhpcy5fbGFzdFN1Y2Nlc3NmdWxFbnN1cmVCeXRlQ2h1bmsgPSBjaHVuazsKICB9CiAgZW5zdXJlUmFuZ2UoYmVnaW4sIGVuZCkgewogICAgaWYgKGJlZ2luID49IGVuZCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoZW5kIDw9IHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGJlZ2luQ2h1bmsgPSBNYXRoLmZsb29yKGJlZ2luIC8gdGhpcy5jaHVua1NpemUpOwogICAgaWYgKGJlZ2luQ2h1bmsgPiB0aGlzLm51bUNodW5rcykgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBlbmRDaHVuayA9IE1hdGgubWluKE1hdGguZmxvb3IoKGVuZCAtIDEpIC8gdGhpcy5jaHVua1NpemUpICsgMSwgdGhpcy5udW1DaHVua3MpOwogICAgZm9yIChsZXQgY2h1bmsgPSBiZWdpbkNodW5rOyBjaHVuayA8IGVuZENodW5rOyArK2NodW5rKSB7CiAgICAgIGlmICghdGhpcy5fbG9hZGVkQ2h1bmtzLmhhcyhjaHVuaykpIHsKICAgICAgICB0aHJvdyBuZXcgTWlzc2luZ0RhdGFFeGNlcHRpb24oYmVnaW4sIGVuZCk7CiAgICAgIH0KICAgIH0KICB9CiAgbmV4dEVtcHR5Q2h1bmsoYmVnaW5DaHVuaykgewogICAgY29uc3QgbnVtQ2h1bmtzID0gdGhpcy5udW1DaHVua3M7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUNodW5rczsgKytpKSB7CiAgICAgIGNvbnN0IGNodW5rID0gKGJlZ2luQ2h1bmsgKyBpKSAlIG51bUNodW5rczsKICAgICAgaWYgKCF0aGlzLl9sb2FkZWRDaHVua3MuaGFzKGNodW5rKSkgewogICAgICAgIHJldHVybiBjaHVuazsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogIGhhc0NodW5rKGNodW5rKSB7CiAgICByZXR1cm4gdGhpcy5fbG9hZGVkQ2h1bmtzLmhhcyhjaHVuayk7CiAgfQogIGdldEJ5dGUoKSB7CiAgICBjb25zdCBwb3MgPSB0aGlzLnBvczsKICAgIGlmIChwb3MgPj0gdGhpcy5lbmQpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgaWYgKHBvcyA+PSB0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aCkgewogICAgICB0aGlzLmVuc3VyZUJ5dGUocG9zKTsKICAgIH0KICAgIHJldHVybiB0aGlzLmJ5dGVzW3RoaXMucG9zKytdOwogIH0KICBnZXRCeXRlcyhsZW5ndGgpIHsKICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5ieXRlczsKICAgIGNvbnN0IHBvcyA9IHRoaXMucG9zOwogICAgY29uc3Qgc3RyRW5kID0gdGhpcy5lbmQ7CiAgICBpZiAoIWxlbmd0aCkgewogICAgICBpZiAoc3RyRW5kID4gdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgpIHsKICAgICAgICB0aGlzLmVuc3VyZVJhbmdlKHBvcywgc3RyRW5kKTsKICAgICAgfQogICAgICByZXR1cm4gYnl0ZXMuc3ViYXJyYXkocG9zLCBzdHJFbmQpOwogICAgfQogICAgbGV0IGVuZCA9IHBvcyArIGxlbmd0aDsKICAgIGlmIChlbmQgPiBzdHJFbmQpIHsKICAgICAgZW5kID0gc3RyRW5kOwogICAgfQogICAgaWYgKGVuZCA+IHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoKSB7CiAgICAgIHRoaXMuZW5zdXJlUmFuZ2UocG9zLCBlbmQpOwogICAgfQogICAgdGhpcy5wb3MgPSBlbmQ7CiAgICByZXR1cm4gYnl0ZXMuc3ViYXJyYXkocG9zLCBlbmQpOwogIH0KICBnZXRCeXRlUmFuZ2UoYmVnaW4sIGVuZCkgewogICAgaWYgKGJlZ2luIDwgMCkgewogICAgICBiZWdpbiA9IDA7CiAgICB9CiAgICBpZiAoZW5kID4gdGhpcy5lbmQpIHsKICAgICAgZW5kID0gdGhpcy5lbmQ7CiAgICB9CiAgICBpZiAoZW5kID4gdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgpIHsKICAgICAgdGhpcy5lbnN1cmVSYW5nZShiZWdpbiwgZW5kKTsKICAgIH0KICAgIHJldHVybiB0aGlzLmJ5dGVzLnN1YmFycmF5KGJlZ2luLCBlbmQpOwogIH0KICBtYWtlU3ViU3RyZWFtKHN0YXJ0LCBsZW5ndGgsIGRpY3QgPSBudWxsKSB7CiAgICBpZiAobGVuZ3RoKSB7CiAgICAgIGlmIChzdGFydCArIGxlbmd0aCA+IHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoKSB7CiAgICAgICAgdGhpcy5lbnN1cmVSYW5nZShzdGFydCwgc3RhcnQgKyBsZW5ndGgpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKHN0YXJ0ID49IHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoKSB7CiAgICAgIHRoaXMuZW5zdXJlQnl0ZShzdGFydCk7CiAgICB9CiAgICBmdW5jdGlvbiBDaHVua2VkU3RyZWFtU3Vic3RyZWFtKCkge30KICAgIENodW5rZWRTdHJlYW1TdWJzdHJlYW0ucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSh0aGlzKTsKICAgIENodW5rZWRTdHJlYW1TdWJzdHJlYW0ucHJvdG90eXBlLmdldE1pc3NpbmdDaHVua3MgPSBmdW5jdGlvbiAoKSB7CiAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IHRoaXMuY2h1bmtTaXplOwogICAgICBjb25zdCBiZWdpbkNodW5rID0gTWF0aC5mbG9vcih0aGlzLnN0YXJ0IC8gY2h1bmtTaXplKTsKICAgICAgY29uc3QgZW5kQ2h1bmsgPSBNYXRoLmZsb29yKCh0aGlzLmVuZCAtIDEpIC8gY2h1bmtTaXplKSArIDE7CiAgICAgIGNvbnN0IG1pc3NpbmdDaHVua3MgPSBbXTsKICAgICAgZm9yIChsZXQgY2h1bmsgPSBiZWdpbkNodW5rOyBjaHVuayA8IGVuZENodW5rOyArK2NodW5rKSB7CiAgICAgICAgaWYgKCF0aGlzLl9sb2FkZWRDaHVua3MuaGFzKGNodW5rKSkgewogICAgICAgICAgbWlzc2luZ0NodW5rcy5wdXNoKGNodW5rKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG1pc3NpbmdDaHVua3M7CiAgICB9OwogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KENodW5rZWRTdHJlYW1TdWJzdHJlYW0ucHJvdG90eXBlLCAiaXNEYXRhTG9hZGVkIiwgewogICAgICBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMubnVtQ2h1bmtzTG9hZGVkID09PSB0aGlzLm51bUNodW5rcykgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzLmdldE1pc3NpbmdDaHVua3MoKS5sZW5ndGggPT09IDA7CiAgICAgIH0sCiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogICAgfSk7CiAgICBjb25zdCBzdWJTdHJlYW0gPSBuZXcgQ2h1bmtlZFN0cmVhbVN1YnN0cmVhbSgpOwogICAgc3ViU3RyZWFtLnBvcyA9IHN1YlN0cmVhbS5zdGFydCA9IHN0YXJ0OwogICAgc3ViU3RyZWFtLmVuZCA9IHN0YXJ0ICsgbGVuZ3RoIHx8IHRoaXMuZW5kOwogICAgc3ViU3RyZWFtLmRpY3QgPSBkaWN0OwogICAgcmV0dXJuIHN1YlN0cmVhbTsKICB9CiAgZ2V0QmFzZVN0cmVhbXMoKSB7CiAgICByZXR1cm4gW3RoaXNdOwogIH0KfQpjbGFzcyBDaHVua2VkU3RyZWFtTWFuYWdlciB7CiAgYWJvcnRlZCA9IGZhbHNlOwogIGN1cnJSZXF1ZXN0SWQgPSAwOwogIF9jaHVua3NOZWVkZWRCeVJlcXVlc3QgPSBuZXcgTWFwKCk7CiAgX2xvYWRlZFN0cmVhbUNhcGFiaWxpdHkgPSBQcm9taXNlLndpdGhSZXNvbHZlcnMoKTsKICBfcHJvbWlzZXNCeVJlcXVlc3QgPSBuZXcgTWFwKCk7CiAgX3JlcXVlc3RzQnlDaHVuayA9IG5ldyBNYXAoKTsKICBjb25zdHJ1Y3RvcihwZGZTdHJlYW0sIGFyZ3MpIHsKICAgIHRoaXMubGVuZ3RoID0gYXJncy5sZW5ndGg7CiAgICB0aGlzLmNodW5rU2l6ZSA9IGFyZ3MucmFuZ2VDaHVua1NpemU7CiAgICB0aGlzLnN0cmVhbSA9IG5ldyBDaHVua2VkU3RyZWFtKHRoaXMubGVuZ3RoLCB0aGlzLmNodW5rU2l6ZSwgdGhpcyk7CiAgICB0aGlzLnBkZlN0cmVhbSA9IHBkZlN0cmVhbTsKICAgIHRoaXMuZGlzYWJsZUF1dG9GZXRjaCA9IGFyZ3MuZGlzYWJsZUF1dG9GZXRjaDsKICAgIHRoaXMubXNnSGFuZGxlciA9IGFyZ3MubXNnSGFuZGxlcjsKICB9CiAgc2VuZFJlcXVlc3QoYmVnaW4sIGVuZCkgewogICAgY29uc3QgcmFuZ2VSZWFkZXIgPSB0aGlzLnBkZlN0cmVhbS5nZXRSYW5nZVJlYWRlcihiZWdpbiwgZW5kKTsKICAgIGxldCBjaHVua3MgPSBbXTsKICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAgIGNvbnN0IHJlYWRDaHVuayA9ICh7CiAgICAgICAgdmFsdWUsCiAgICAgICAgZG9uZQogICAgICB9KSA9PiB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGlmIChkb25lKSB7CiAgICAgICAgICAgIHJlc29sdmUoYXJyYXlCdWZmZXJzVG9CeXRlcyhjaHVua3MpKTsKICAgICAgICAgICAgY2h1bmtzID0gbnVsbDsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgfQogICAgICAgICAgY2h1bmtzLnB1c2godmFsdWUpOwogICAgICAgICAgcmFuZ2VSZWFkZXIucmVhZCgpLnRoZW4ocmVhZENodW5rLCByZWplY3QpOwogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIHJlamVjdChlKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIHJhbmdlUmVhZGVyLnJlYWQoKS50aGVuKHJlYWRDaHVuaywgcmVqZWN0KTsKICAgIH0pLnRoZW4oZGF0YSA9PiB7CiAgICAgIGlmICh0aGlzLmFib3J0ZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhpcy5vblJlY2VpdmVEYXRhKHsKICAgICAgICBjaHVuazogZGF0YSwKICAgICAgICBiZWdpbgogICAgICB9KTsKICAgIH0pOwogIH0KICByZXF1ZXN0QWxsQ2h1bmtzKG5vRmV0Y2ggPSBmYWxzZSkgewogICAgaWYgKCFub0ZldGNoKSB7CiAgICAgIGNvbnN0IG1pc3NpbmdDaHVua3MgPSB0aGlzLnN0cmVhbS5nZXRNaXNzaW5nQ2h1bmtzKCk7CiAgICAgIHRoaXMuX3JlcXVlc3RDaHVua3MobWlzc2luZ0NodW5rcyk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5fbG9hZGVkU3RyZWFtQ2FwYWJpbGl0eS5wcm9taXNlOwogIH0KICBfcmVxdWVzdENodW5rcyhjaHVua3MpIHsKICAgIGNvbnN0IHJlcXVlc3RJZCA9IHRoaXMuY3VyclJlcXVlc3RJZCsrOwogICAgY29uc3QgY2h1bmtzTmVlZGVkID0gbmV3IFNldCgpOwogICAgdGhpcy5fY2h1bmtzTmVlZGVkQnlSZXF1ZXN0LnNldChyZXF1ZXN0SWQsIGNodW5rc05lZWRlZCk7CiAgICBmb3IgKGNvbnN0IGNodW5rIG9mIGNodW5rcykgewogICAgICBpZiAoIXRoaXMuc3RyZWFtLmhhc0NodW5rKGNodW5rKSkgewogICAgICAgIGNodW5rc05lZWRlZC5hZGQoY2h1bmspOwogICAgICB9CiAgICB9CiAgICBpZiAoY2h1bmtzTmVlZGVkLnNpemUgPT09IDApIHsKICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpOwogICAgfQogICAgY29uc3QgY2FwYWJpbGl0eSA9IFByb21pc2Uud2l0aFJlc29sdmVycygpOwogICAgdGhpcy5fcHJvbWlzZXNCeVJlcXVlc3Quc2V0KHJlcXVlc3RJZCwgY2FwYWJpbGl0eSk7CiAgICBjb25zdCBjaHVua3NUb1JlcXVlc3QgPSBbXTsKICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzTmVlZGVkKSB7CiAgICAgIGxldCByZXF1ZXN0SWRzID0gdGhpcy5fcmVxdWVzdHNCeUNodW5rLmdldChjaHVuayk7CiAgICAgIGlmICghcmVxdWVzdElkcykgewogICAgICAgIHJlcXVlc3RJZHMgPSBbXTsKICAgICAgICB0aGlzLl9yZXF1ZXN0c0J5Q2h1bmsuc2V0KGNodW5rLCByZXF1ZXN0SWRzKTsKICAgICAgICBjaHVua3NUb1JlcXVlc3QucHVzaChjaHVuayk7CiAgICAgIH0KICAgICAgcmVxdWVzdElkcy5wdXNoKHJlcXVlc3RJZCk7CiAgICB9CiAgICBpZiAoY2h1bmtzVG9SZXF1ZXN0Lmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgZ3JvdXBlZENodW5rc1RvUmVxdWVzdCA9IHRoaXMuZ3JvdXBDaHVua3MoY2h1bmtzVG9SZXF1ZXN0KTsKICAgICAgZm9yIChjb25zdCBncm91cGVkQ2h1bmsgb2YgZ3JvdXBlZENodW5rc1RvUmVxdWVzdCkgewogICAgICAgIGNvbnN0IGJlZ2luID0gZ3JvdXBlZENodW5rLmJlZ2luQ2h1bmsgKiB0aGlzLmNodW5rU2l6ZTsKICAgICAgICBjb25zdCBlbmQgPSBNYXRoLm1pbihncm91cGVkQ2h1bmsuZW5kQ2h1bmsgKiB0aGlzLmNodW5rU2l6ZSwgdGhpcy5sZW5ndGgpOwogICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoYmVnaW4sIGVuZCkuY2F0Y2goY2FwYWJpbGl0eS5yZWplY3QpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgIGlmICh0aGlzLmFib3J0ZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhyb3cgcmVhc29uOwogICAgfSk7CiAgfQogIGdldFN0cmVhbSgpIHsKICAgIHJldHVybiB0aGlzLnN0cmVhbTsKICB9CiAgcmVxdWVzdFJhbmdlKGJlZ2luLCBlbmQpIHsKICAgIGVuZCA9IE1hdGgubWluKGVuZCwgdGhpcy5sZW5ndGgpOwogICAgY29uc3QgYmVnaW5DaHVuayA9IHRoaXMuZ2V0QmVnaW5DaHVuayhiZWdpbik7CiAgICBjb25zdCBlbmRDaHVuayA9IHRoaXMuZ2V0RW5kQ2h1bmsoZW5kKTsKICAgIGNvbnN0IGNodW5rcyA9IFtdOwogICAgZm9yIChsZXQgY2h1bmsgPSBiZWdpbkNodW5rOyBjaHVuayA8IGVuZENodW5rOyArK2NodW5rKSB7CiAgICAgIGNodW5rcy5wdXNoKGNodW5rKTsKICAgIH0KICAgIHJldHVybiB0aGlzLl9yZXF1ZXN0Q2h1bmtzKGNodW5rcyk7CiAgfQogIHJlcXVlc3RSYW5nZXMocmFuZ2VzID0gW10pIHsKICAgIGNvbnN0IGNodW5rc1RvUmVxdWVzdCA9IFtdOwogICAgZm9yIChjb25zdCByYW5nZSBvZiByYW5nZXMpIHsKICAgICAgY29uc3QgYmVnaW5DaHVuayA9IHRoaXMuZ2V0QmVnaW5DaHVuayhyYW5nZS5iZWdpbik7CiAgICAgIGNvbnN0IGVuZENodW5rID0gdGhpcy5nZXRFbmRDaHVuayhyYW5nZS5lbmQpOwogICAgICBmb3IgKGxldCBjaHVuayA9IGJlZ2luQ2h1bms7IGNodW5rIDwgZW5kQ2h1bms7ICsrY2h1bmspIHsKICAgICAgICBpZiAoIWNodW5rc1RvUmVxdWVzdC5pbmNsdWRlcyhjaHVuaykpIHsKICAgICAgICAgIGNodW5rc1RvUmVxdWVzdC5wdXNoKGNodW5rKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGNodW5rc1RvUmVxdWVzdC5zb3J0KChhLCBiKSA9PiBhIC0gYik7CiAgICByZXR1cm4gdGhpcy5fcmVxdWVzdENodW5rcyhjaHVua3NUb1JlcXVlc3QpOwogIH0KICBncm91cENodW5rcyhjaHVua3MpIHsKICAgIGNvbnN0IGdyb3VwZWRDaHVua3MgPSBbXTsKICAgIGxldCBiZWdpbkNodW5rID0gLTE7CiAgICBsZXQgcHJldkNodW5rID0gLTE7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBjaHVua3MubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICBjb25zdCBjaHVuayA9IGNodW5rc1tpXTsKICAgICAgaWYgKGJlZ2luQ2h1bmsgPCAwKSB7CiAgICAgICAgYmVnaW5DaHVuayA9IGNodW5rOwogICAgICB9CiAgICAgIGlmIChwcmV2Q2h1bmsgPj0gMCAmJiBwcmV2Q2h1bmsgKyAxICE9PSBjaHVuaykgewogICAgICAgIGdyb3VwZWRDaHVua3MucHVzaCh7CiAgICAgICAgICBiZWdpbkNodW5rLAogICAgICAgICAgZW5kQ2h1bms6IHByZXZDaHVuayArIDEKICAgICAgICB9KTsKICAgICAgICBiZWdpbkNodW5rID0gY2h1bms7CiAgICAgIH0KICAgICAgaWYgKGkgKyAxID09PSBjaHVua3MubGVuZ3RoKSB7CiAgICAgICAgZ3JvdXBlZENodW5rcy5wdXNoKHsKICAgICAgICAgIGJlZ2luQ2h1bmssCiAgICAgICAgICBlbmRDaHVuazogY2h1bmsgKyAxCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgcHJldkNodW5rID0gY2h1bms7CiAgICB9CiAgICByZXR1cm4gZ3JvdXBlZENodW5rczsKICB9CiAgb25SZWNlaXZlRGF0YShhcmdzKSB7CiAgICBjb25zdCB7CiAgICAgIGNodW5rU2l6ZSwKICAgICAgbGVuZ3RoLAogICAgICBzdHJlYW0KICAgIH0gPSB0aGlzOwogICAgY29uc3QgY2h1bmsgPSBhcmdzLmNodW5rOwogICAgY29uc3QgaXNQcm9ncmVzc2l2ZSA9IGFyZ3MuYmVnaW4gPT09IHVuZGVmaW5lZDsKICAgIGNvbnN0IGJlZ2luID0gaXNQcm9ncmVzc2l2ZSA/IHN0cmVhbS5wcm9ncmVzc2l2ZURhdGFMZW5ndGggOiBhcmdzLmJlZ2luOwogICAgY29uc3QgZW5kID0gYmVnaW4gKyBjaHVuay5ieXRlTGVuZ3RoOwogICAgY29uc3QgYmVnaW5DaHVuayA9IE1hdGguZmxvb3IoYmVnaW4gLyBjaHVua1NpemUpOwogICAgY29uc3QgZW5kQ2h1bmsgPSBlbmQgPCBsZW5ndGggPyBNYXRoLmZsb29yKGVuZCAvIGNodW5rU2l6ZSkgOiBNYXRoLmNlaWwoZW5kIC8gY2h1bmtTaXplKTsKICAgIGlmIChpc1Byb2dyZXNzaXZlKSB7CiAgICAgIHN0cmVhbS5vblJlY2VpdmVQcm9ncmVzc2l2ZURhdGEoY2h1bmspOwogICAgfSBlbHNlIHsKICAgICAgc3RyZWFtLm9uUmVjZWl2ZURhdGEoYmVnaW4sIGNodW5rKTsKICAgIH0KICAgIGlmIChzdHJlYW0uaXNEYXRhTG9hZGVkKSB7CiAgICAgIHRoaXMuX2xvYWRlZFN0cmVhbUNhcGFiaWxpdHkucmVzb2x2ZShzdHJlYW0pOwogICAgfQogICAgY29uc3QgbG9hZGVkUmVxdWVzdHMgPSBbXTsKICAgIGZvciAobGV0IGN1ckNodW5rID0gYmVnaW5DaHVuazsgY3VyQ2h1bmsgPCBlbmRDaHVuazsgKytjdXJDaHVuaykgewogICAgICBjb25zdCByZXF1ZXN0SWRzID0gdGhpcy5fcmVxdWVzdHNCeUNodW5rLmdldChjdXJDaHVuayk7CiAgICAgIGlmICghcmVxdWVzdElkcykgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHRoaXMuX3JlcXVlc3RzQnlDaHVuay5kZWxldGUoY3VyQ2h1bmspOwogICAgICBmb3IgKGNvbnN0IHJlcXVlc3RJZCBvZiByZXF1ZXN0SWRzKSB7CiAgICAgICAgY29uc3QgY2h1bmtzTmVlZGVkID0gdGhpcy5fY2h1bmtzTmVlZGVkQnlSZXF1ZXN0LmdldChyZXF1ZXN0SWQpOwogICAgICAgIGlmIChjaHVua3NOZWVkZWQuaGFzKGN1ckNodW5rKSkgewogICAgICAgICAgY2h1bmtzTmVlZGVkLmRlbGV0ZShjdXJDaHVuayk7CiAgICAgICAgfQogICAgICAgIGlmIChjaHVua3NOZWVkZWQuc2l6ZSA+IDApIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBsb2FkZWRSZXF1ZXN0cy5wdXNoKHJlcXVlc3RJZCk7CiAgICAgIH0KICAgIH0KICAgIGlmICghdGhpcy5kaXNhYmxlQXV0b0ZldGNoICYmIHRoaXMuX3JlcXVlc3RzQnlDaHVuay5zaXplID09PSAwKSB7CiAgICAgIGxldCBuZXh0RW1wdHlDaHVuazsKICAgICAgaWYgKHN0cmVhbS5udW1DaHVua3NMb2FkZWQgPT09IDEpIHsKICAgICAgICBjb25zdCBsYXN0Q2h1bmsgPSBzdHJlYW0ubnVtQ2h1bmtzIC0gMTsKICAgICAgICBpZiAoIXN0cmVhbS5oYXNDaHVuayhsYXN0Q2h1bmspKSB7CiAgICAgICAgICBuZXh0RW1wdHlDaHVuayA9IGxhc3RDaHVuazsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmV4dEVtcHR5Q2h1bmsgPSBzdHJlYW0ubmV4dEVtcHR5Q2h1bmsoZW5kQ2h1bmspOwogICAgICB9CiAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKG5leHRFbXB0eUNodW5rKSkgewogICAgICAgIHRoaXMuX3JlcXVlc3RDaHVua3MoW25leHRFbXB0eUNodW5rXSk7CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgcmVxdWVzdElkIG9mIGxvYWRlZFJlcXVlc3RzKSB7CiAgICAgIGNvbnN0IGNhcGFiaWxpdHkgPSB0aGlzLl9wcm9taXNlc0J5UmVxdWVzdC5nZXQocmVxdWVzdElkKTsKICAgICAgdGhpcy5fcHJvbWlzZXNCeVJlcXVlc3QuZGVsZXRlKHJlcXVlc3RJZCk7CiAgICAgIGNhcGFiaWxpdHkucmVzb2x2ZSgpOwogICAgfQogICAgdGhpcy5tc2dIYW5kbGVyLnNlbmQoIkRvY1Byb2dyZXNzIiwgewogICAgICBsb2FkZWQ6IHN0cmVhbS5udW1DaHVua3NMb2FkZWQgKiBjaHVua1NpemUsCiAgICAgIHRvdGFsOiBsZW5ndGgKICAgIH0pOwogIH0KICBvbkVycm9yKGVycikgewogICAgdGhpcy5fbG9hZGVkU3RyZWFtQ2FwYWJpbGl0eS5yZWplY3QoZXJyKTsKICB9CiAgZ2V0QmVnaW5DaHVuayhiZWdpbikgewogICAgcmV0dXJuIE1hdGguZmxvb3IoYmVnaW4gLyB0aGlzLmNodW5rU2l6ZSk7CiAgfQogIGdldEVuZENodW5rKGVuZCkgewogICAgcmV0dXJuIE1hdGguZmxvb3IoKGVuZCAtIDEpIC8gdGhpcy5jaHVua1NpemUpICsgMTsKICB9CiAgYWJvcnQocmVhc29uKSB7CiAgICB0aGlzLmFib3J0ZWQgPSB0cnVlOwogICAgdGhpcy5wZGZTdHJlYW0/LmNhbmNlbEFsbFJlcXVlc3RzKHJlYXNvbik7CiAgICBmb3IgKGNvbnN0IGNhcGFiaWxpdHkgb2YgdGhpcy5fcHJvbWlzZXNCeVJlcXVlc3QudmFsdWVzKCkpIHsKICAgICAgY2FwYWJpbGl0eS5yZWplY3QocmVhc29uKTsKICAgIH0KICB9Cn0KCjsvLyAuL3NyYy9zaGFyZWQvaW1hZ2VfdXRpbHMuanMKCmZ1bmN0aW9uIGNvbnZlcnRUb1JHQkEocGFyYW1zKSB7CiAgc3dpdGNoIChwYXJhbXMua2luZCkgewogICAgY2FzZSBJbWFnZUtpbmQuR1JBWVNDQUxFXzFCUFA6CiAgICAgIHJldHVybiBjb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQShwYXJhbXMpOwogICAgY2FzZSBJbWFnZUtpbmQuUkdCXzI0QlBQOgogICAgICByZXR1cm4gY29udmVydFJHQlRvUkdCQShwYXJhbXMpOwogIH0KICByZXR1cm4gbnVsbDsKfQpmdW5jdGlvbiBjb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQSh7CiAgc3JjLAogIHNyY1BvcyA9IDAsCiAgZGVzdCwKICB3aWR0aCwKICBoZWlnaHQsCiAgbm9uQmxhY2tDb2xvciA9IDB4ZmZmZmZmZmYsCiAgaW52ZXJzZURlY29kZSA9IGZhbHNlCn0pIHsKICBjb25zdCBibGFjayA9IEZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuID8gMHhmZjAwMDAwMCA6IDB4MDAwMDAwZmY7CiAgY29uc3QgW3plcm9NYXBwaW5nLCBvbmVNYXBwaW5nXSA9IGludmVyc2VEZWNvZGUgPyBbbm9uQmxhY2tDb2xvciwgYmxhY2tdIDogW2JsYWNrLCBub25CbGFja0NvbG9yXTsKICBjb25zdCB3aWR0aEluU291cmNlID0gd2lkdGggPj4gMzsKICBjb25zdCB3aWR0aFJlbWFpbmRlciA9IHdpZHRoICYgNzsKICBjb25zdCBzcmNMZW5ndGggPSBzcmMubGVuZ3RoOwogIGRlc3QgPSBuZXcgVWludDMyQXJyYXkoZGVzdC5idWZmZXIpOwogIGxldCBkZXN0UG9zID0gMDsKICBmb3IgKGxldCBpID0gMDsgaSA8IGhlaWdodDsgaSsrKSB7CiAgICBmb3IgKGNvbnN0IG1heCA9IHNyY1BvcyArIHdpZHRoSW5Tb3VyY2U7IHNyY1BvcyA8IG1heDsgc3JjUG9zKyspIHsKICAgICAgY29uc3QgZWxlbSA9IHNyY1BvcyA8IHNyY0xlbmd0aCA/IHNyY1tzcmNQb3NdIDogMjU1OwogICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMDAwMDAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwMDAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwMDAwID8gb25lTWFwcGluZyA6IHplcm9NYXBwaW5nOwogICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMDAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwID8gb25lTWFwcGluZyA6IHplcm9NYXBwaW5nOwogICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMSA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgIH0KICAgIGlmICh3aWR0aFJlbWFpbmRlciA9PT0gMCkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGNvbnN0IGVsZW0gPSBzcmNQb3MgPCBzcmNMZW5ndGggPyBzcmNbc3JjUG9zKytdIDogMjU1OwogICAgZm9yIChsZXQgaiA9IDA7IGogPCB3aWR0aFJlbWFpbmRlcjsgaisrKSB7CiAgICAgIGRlc3RbZGVzdFBvcysrXSA9IGVsZW0gJiAxIDw8IDcgLSBqID8gb25lTWFwcGluZyA6IHplcm9NYXBwaW5nOwogICAgfQogIH0KICByZXR1cm4gewogICAgc3JjUG9zLAogICAgZGVzdFBvcwogIH07Cn0KZnVuY3Rpb24gY29udmVydFJHQlRvUkdCQSh7CiAgc3JjLAogIHNyY1BvcyA9IDAsCiAgZGVzdCwKICBkZXN0UG9zID0gMCwKICB3aWR0aCwKICBoZWlnaHQKfSkgewogIGxldCBpID0gMDsKICBjb25zdCBsZW4gPSB3aWR0aCAqIGhlaWdodCAqIDM7CiAgY29uc3QgbGVuMzIgPSBsZW4gPj4gMjsKICBjb25zdCBzcmMzMiA9IG5ldyBVaW50MzJBcnJheShzcmMuYnVmZmVyLCBzcmNQb3MsIGxlbjMyKTsKICBpZiAoRmVhdHVyZVRlc3QuaXNMaXR0bGVFbmRpYW4pIHsKICAgIGZvciAoOyBpIDwgbGVuMzIgLSAyOyBpICs9IDMsIGRlc3RQb3MgKz0gNCkgewogICAgICBjb25zdCBzMSA9IHNyYzMyW2ldOwogICAgICBjb25zdCBzMiA9IHNyYzMyW2kgKyAxXTsKICAgICAgY29uc3QgczMgPSBzcmMzMltpICsgMl07CiAgICAgIGRlc3RbZGVzdFBvc10gPSBzMSB8IDB4ZmYwMDAwMDA7CiAgICAgIGRlc3RbZGVzdFBvcyArIDFdID0gczEgPj4+IDI0IHwgczIgPDwgOCB8IDB4ZmYwMDAwMDA7CiAgICAgIGRlc3RbZGVzdFBvcyArIDJdID0gczIgPj4+IDE2IHwgczMgPDwgMTYgfCAweGZmMDAwMDAwOwogICAgICBkZXN0W2Rlc3RQb3MgKyAzXSA9IHMzID4+PiA4IHwgMHhmZjAwMDAwMDsKICAgIH0KICAgIGZvciAobGV0IGogPSBpICogNCwgamogPSBzcmNQb3MgKyBsZW47IGogPCBqajsgaiArPSAzKSB7CiAgICAgIGRlc3RbZGVzdFBvcysrXSA9IHNyY1tqXSB8IHNyY1tqICsgMV0gPDwgOCB8IHNyY1tqICsgMl0gPDwgMTYgfCAweGZmMDAwMDAwOwogICAgfQogIH0gZWxzZSB7CiAgICBmb3IgKDsgaSA8IGxlbjMyIC0gMjsgaSArPSAzLCBkZXN0UG9zICs9IDQpIHsKICAgICAgY29uc3QgczEgPSBzcmMzMltpXTsKICAgICAgY29uc3QgczIgPSBzcmMzMltpICsgMV07CiAgICAgIGNvbnN0IHMzID0gc3JjMzJbaSArIDJdOwogICAgICBkZXN0W2Rlc3RQb3NdID0gczEgfCAweGZmOwogICAgICBkZXN0W2Rlc3RQb3MgKyAxXSA9IHMxIDw8IDI0IHwgczIgPj4+IDggfCAweGZmOwogICAgICBkZXN0W2Rlc3RQb3MgKyAyXSA9IHMyIDw8IDE2IHwgczMgPj4+IDE2IHwgMHhmZjsKICAgICAgZGVzdFtkZXN0UG9zICsgM10gPSBzMyA8PCA4IHwgMHhmZjsKICAgIH0KICAgIGZvciAobGV0IGogPSBpICogNCwgamogPSBzcmNQb3MgKyBsZW47IGogPCBqajsgaiArPSAzKSB7CiAgICAgIGRlc3RbZGVzdFBvcysrXSA9IHNyY1tqXSA8PCAyNCB8IHNyY1tqICsgMV0gPDwgMTYgfCBzcmNbaiArIDJdIDw8IDggfCAweGZmOwogICAgfQogIH0KICByZXR1cm4gewogICAgc3JjUG9zOiBzcmNQb3MgKyBsZW4sCiAgICBkZXN0UG9zCiAgfTsKfQpmdW5jdGlvbiBncmF5VG9SR0JBKHNyYywgZGVzdCkgewogIGlmIChGZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbikgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gc3JjLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgZGVzdFtpXSA9IHNyY1tpXSAqIDB4MTAxMDEgfCAweGZmMDAwMDAwOwogICAgfQogIH0gZWxzZSB7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzcmMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBkZXN0W2ldID0gc3JjW2ldICogMHgxMDEwMTAwIHwgMHgwMDAwMDBmZjsKICAgIH0KICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2ltYWdlX3Jlc2l6ZXIuanMKCgoKY29uc3QgTUlOX0lNQUdFX0RJTSA9IDIwNDg7CmNvbnN0IE1BWF9JTUFHRV9ESU0gPSA2NTUzNzsKY29uc3QgTUFYX0VSUk9SID0gMTI4OwpjbGFzcyBJbWFnZVJlc2l6ZXIgewogIHN0YXRpYyAjZ29vZFNxdWFyZUxlbmd0aCA9IE1JTl9JTUFHRV9ESU07CiAgc3RhdGljICNpc0ltYWdlRGVjb2RlclN1cHBvcnRlZCA9IEZlYXR1cmVUZXN0LmlzSW1hZ2VEZWNvZGVyU3VwcG9ydGVkOwogIGNvbnN0cnVjdG9yKGltZ0RhdGEsIGlzTWFzaykgewogICAgdGhpcy5faW1nRGF0YSA9IGltZ0RhdGE7CiAgICB0aGlzLl9pc01hc2sgPSBpc01hc2s7CiAgfQogIHN0YXRpYyBnZXQgY2FuVXNlSW1hZ2VEZWNvZGVyKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiY2FuVXNlSW1hZ2VEZWNvZGVyIiwgdGhpcy4jaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQgPyBJbWFnZURlY29kZXIuaXNUeXBlU3VwcG9ydGVkKCJpbWFnZS9ibXAiKSA6IFByb21pc2UucmVzb2x2ZShmYWxzZSkpOwogIH0KICBzdGF0aWMgbmVlZHNUb0JlUmVzaXplZCh3aWR0aCwgaGVpZ2h0KSB7CiAgICBpZiAod2lkdGggPD0gdGhpcy4jZ29vZFNxdWFyZUxlbmd0aCAmJiBoZWlnaHQgPD0gdGhpcy4jZ29vZFNxdWFyZUxlbmd0aCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIE1BWF9ESU0KICAgIH0gPSB0aGlzOwogICAgaWYgKHdpZHRoID4gTUFYX0RJTSB8fCBoZWlnaHQgPiBNQVhfRElNKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgY29uc3QgYXJlYSA9IHdpZHRoICogaGVpZ2h0OwogICAgaWYgKHRoaXMuX2hhc01heEFyZWEpIHsKICAgICAgcmV0dXJuIGFyZWEgPiB0aGlzLk1BWF9BUkVBOwogICAgfQogICAgaWYgKGFyZWEgPCB0aGlzLiNnb29kU3F1YXJlTGVuZ3RoICoqIDIpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKHRoaXMuX2FyZUdvb2REaW1zKHdpZHRoLCBoZWlnaHQpKSB7CiAgICAgIHRoaXMuI2dvb2RTcXVhcmVMZW5ndGggPSBNYXRoLm1heCh0aGlzLiNnb29kU3F1YXJlTGVuZ3RoLCBNYXRoLmZsb29yKE1hdGguc3FydCh3aWR0aCAqIGhlaWdodCkpKTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgdGhpcy4jZ29vZFNxdWFyZUxlbmd0aCA9IHRoaXMuX2d1ZXNzTWF4KHRoaXMuI2dvb2RTcXVhcmVMZW5ndGgsIE1BWF9ESU0sIE1BWF9FUlJPUiwgMCk7CiAgICBjb25zdCBtYXhBcmVhID0gdGhpcy5NQVhfQVJFQSA9IHRoaXMuI2dvb2RTcXVhcmVMZW5ndGggKiogMjsKICAgIHJldHVybiBhcmVhID4gbWF4QXJlYTsKICB9CiAgc3RhdGljIGdldFJlZHVjZVBvd2VyRm9ySlBYKHdpZHRoLCBoZWlnaHQsIGNvbXBvbmVudHNDb3VudCkgewogICAgY29uc3QgYXJlYSA9IHdpZHRoICogaGVpZ2h0OwogICAgY29uc3QgbWF4SlBYQXJlYSA9IDIgKiogMzAgLyAoY29tcG9uZW50c0NvdW50ICogNCk7CiAgICBpZiAoIXRoaXMubmVlZHNUb0JlUmVzaXplZCh3aWR0aCwgaGVpZ2h0KSkgewogICAgICBpZiAoYXJlYSA+IG1heEpQWEFyZWEpIHsKICAgICAgICByZXR1cm4gTWF0aC5jZWlsKE1hdGgubG9nMihhcmVhIC8gbWF4SlBYQXJlYSkpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfQogICAgY29uc3QgewogICAgICBNQVhfRElNLAogICAgICBNQVhfQVJFQQogICAgfSA9IHRoaXM7CiAgICBjb25zdCBtaW5GYWN0b3IgPSBNYXRoLm1heCh3aWR0aCAvIE1BWF9ESU0sIGhlaWdodCAvIE1BWF9ESU0sIE1hdGguc3FydChhcmVhIC8gTWF0aC5taW4obWF4SlBYQXJlYSwgTUFYX0FSRUEpKSk7CiAgICByZXR1cm4gTWF0aC5jZWlsKE1hdGgubG9nMihtaW5GYWN0b3IpKTsKICB9CiAgc3RhdGljIGdldCBNQVhfRElNKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiTUFYX0RJTSIsIHRoaXMuX2d1ZXNzTWF4KE1JTl9JTUFHRV9ESU0sIE1BWF9JTUFHRV9ESU0sIDAsIDEpKTsKICB9CiAgc3RhdGljIGdldCBNQVhfQVJFQSgpIHsKICAgIHRoaXMuX2hhc01heEFyZWEgPSB0cnVlOwogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiTUFYX0FSRUEiLCB0aGlzLl9ndWVzc01heCh0aGlzLiNnb29kU3F1YXJlTGVuZ3RoLCB0aGlzLk1BWF9ESU0sIE1BWF9FUlJPUiwgMCkgKiogMik7CiAgfQogIHN0YXRpYyBzZXQgTUFYX0FSRUEoYXJlYSkgewogICAgaWYgKGFyZWEgPj0gMCkgewogICAgICB0aGlzLl9oYXNNYXhBcmVhID0gdHJ1ZTsKICAgICAgc2hhZG93KHRoaXMsICJNQVhfQVJFQSIsIGFyZWEpOwogICAgfQogIH0KICBzdGF0aWMgc2V0T3B0aW9ucyh7CiAgICBjYW52YXNNYXhBcmVhSW5CeXRlcyA9IC0xLAogICAgaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQgPSBmYWxzZQogIH0pIHsKICAgIGlmICghdGhpcy5faGFzTWF4QXJlYSkgewogICAgICB0aGlzLk1BWF9BUkVBID0gY2FudmFzTWF4QXJlYUluQnl0ZXMgPj4gMjsKICAgIH0KICAgIHRoaXMuI2lzSW1hZ2VEZWNvZGVyU3VwcG9ydGVkID0gaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQ7CiAgfQogIHN0YXRpYyBfYXJlR29vZERpbXMod2lkdGgsIGhlaWdodCkgewogICAgdHJ5IHsKICAgICAgY29uc3QgY2FudmFzID0gbmV3IE9mZnNjcmVlbkNhbnZhcyh3aWR0aCwgaGVpZ2h0KTsKICAgICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgICAgIGN0eC5maWxsUmVjdCgwLCAwLCAxLCAxKTsKICAgICAgY29uc3Qgb3BhY2l0eSA9IGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgMSwgMSkuZGF0YVszXTsKICAgICAgY2FudmFzLndpZHRoID0gY2FudmFzLmhlaWdodCA9IDE7CiAgICAgIHJldHVybiBvcGFjaXR5ICE9PSAwOwogICAgfSBjYXRjaCB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9CiAgc3RhdGljIF9ndWVzc01heChzdGFydCwgZW5kLCB0b2xlcmFuY2UsIGRlZmF1bHRIZWlnaHQpIHsKICAgIHdoaWxlIChzdGFydCArIHRvbGVyYW5jZSArIDEgPCBlbmQpIHsKICAgICAgY29uc3QgbWlkZGxlID0gTWF0aC5mbG9vcigoc3RhcnQgKyBlbmQpIC8gMik7CiAgICAgIGNvbnN0IGhlaWdodCA9IGRlZmF1bHRIZWlnaHQgfHwgbWlkZGxlOwogICAgICBpZiAodGhpcy5fYXJlR29vZERpbXMobWlkZGxlLCBoZWlnaHQpKSB7CiAgICAgICAgc3RhcnQgPSBtaWRkbGU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZW5kID0gbWlkZGxlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc3RhcnQ7CiAgfQogIHN0YXRpYyBhc3luYyBjcmVhdGVJbWFnZShpbWdEYXRhLCBpc01hc2sgPSBmYWxzZSkgewogICAgcmV0dXJuIG5ldyBJbWFnZVJlc2l6ZXIoaW1nRGF0YSwgaXNNYXNrKS5fY3JlYXRlSW1hZ2UoKTsKICB9CiAgYXN5bmMgX2NyZWF0ZUltYWdlKCkgewogICAgY29uc3QgewogICAgICBfaW1nRGF0YTogaW1nRGF0YQogICAgfSA9IHRoaXM7CiAgICBjb25zdCB7CiAgICAgIHdpZHRoLAogICAgICBoZWlnaHQKICAgIH0gPSBpbWdEYXRhOwogICAgaWYgKHdpZHRoICogaGVpZ2h0ICogNCA+IE1BWF9JTlRfMzIpIHsKICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy4jcmVzY2FsZUltYWdlRGF0YSgpOwogICAgICBpZiAocmVzdWx0KSB7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQogICAgfQogICAgY29uc3QgZGF0YSA9IHRoaXMuX2VuY29kZUJNUCgpOwogICAgbGV0IGRlY29kZXIsIGltYWdlUHJvbWlzZTsKICAgIGlmIChhd2FpdCBJbWFnZVJlc2l6ZXIuY2FuVXNlSW1hZ2VEZWNvZGVyKSB7CiAgICAgIGRlY29kZXIgPSBuZXcgSW1hZ2VEZWNvZGVyKHsKICAgICAgICBkYXRhLAogICAgICAgIHR5cGU6ICJpbWFnZS9ibXAiLAogICAgICAgIHByZWZlckFuaW1hdGlvbjogZmFsc2UsCiAgICAgICAgdHJhbnNmZXI6IFtkYXRhLmJ1ZmZlcl0KICAgICAgfSk7CiAgICAgIGltYWdlUHJvbWlzZSA9IGRlY29kZXIuZGVjb2RlKCkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgICB3YXJuKGBCTVAgaW1hZ2UgZGVjb2RpbmcgZmFpbGVkOiAke3JlYXNvbn1gKTsKICAgICAgICByZXR1cm4gY3JlYXRlSW1hZ2VCaXRtYXAobmV3IEJsb2IoW3RoaXMuX2VuY29kZUJNUCgpLmJ1ZmZlcl0sIHsKICAgICAgICAgIHR5cGU6ICJpbWFnZS9ibXAiCiAgICAgICAgfSkpOwogICAgICB9KS5maW5hbGx5KCgpID0+IHsKICAgICAgICBkZWNvZGVyLmNsb3NlKCk7CiAgICAgIH0pOwogICAgfSBlbHNlIHsKICAgICAgaW1hZ2VQcm9taXNlID0gY3JlYXRlSW1hZ2VCaXRtYXAobmV3IEJsb2IoW2RhdGEuYnVmZmVyXSwgewogICAgICAgIHR5cGU6ICJpbWFnZS9ibXAiCiAgICAgIH0pKTsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgTUFYX0FSRUEsCiAgICAgIE1BWF9ESU0KICAgIH0gPSBJbWFnZVJlc2l6ZXI7CiAgICBjb25zdCBtaW5GYWN0b3IgPSBNYXRoLm1heCh3aWR0aCAvIE1BWF9ESU0sIGhlaWdodCAvIE1BWF9ESU0sIE1hdGguc3FydCh3aWR0aCAqIGhlaWdodCAvIE1BWF9BUkVBKSk7CiAgICBjb25zdCBmaXJzdEZhY3RvciA9IE1hdGgubWF4KG1pbkZhY3RvciwgMik7CiAgICBjb25zdCBmYWN0b3IgPSBNYXRoLnJvdW5kKDEwICogKG1pbkZhY3RvciArIDEuMjUpKSAvIDEwIC8gZmlyc3RGYWN0b3I7CiAgICBjb25zdCBOID0gTWF0aC5mbG9vcihNYXRoLmxvZzIoZmFjdG9yKSk7CiAgICBjb25zdCBzdGVwcyA9IG5ldyBBcnJheShOICsgMikuZmlsbCgyKTsKICAgIHN0ZXBzWzBdID0gZmlyc3RGYWN0b3I7CiAgICBzdGVwcy5zcGxpY2UoLTEsIDEsIGZhY3RvciAvICgxIDw8IE4pKTsKICAgIGxldCBuZXdXaWR0aCA9IHdpZHRoOwogICAgbGV0IG5ld0hlaWdodCA9IGhlaWdodDsKICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGltYWdlUHJvbWlzZTsKICAgIGxldCBiaXRtYXAgPSByZXN1bHQuaW1hZ2UgfHwgcmVzdWx0OwogICAgZm9yIChjb25zdCBzdGVwIG9mIHN0ZXBzKSB7CiAgICAgIGNvbnN0IHByZXZXaWR0aCA9IG5ld1dpZHRoOwogICAgICBjb25zdCBwcmV2SGVpZ2h0ID0gbmV3SGVpZ2h0OwogICAgICBuZXdXaWR0aCA9IE1hdGguZmxvb3IobmV3V2lkdGggLyBzdGVwKSAtIDE7CiAgICAgIG5ld0hlaWdodCA9IE1hdGguZmxvb3IobmV3SGVpZ2h0IC8gc3RlcCkgLSAxOwogICAgICBjb25zdCBjYW52YXMgPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKG5ld1dpZHRoLCBuZXdIZWlnaHQpOwogICAgICBjb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgiMmQiKTsKICAgICAgY3R4LmRyYXdJbWFnZShiaXRtYXAsIDAsIDAsIHByZXZXaWR0aCwgcHJldkhlaWdodCwgMCwgMCwgbmV3V2lkdGgsIG5ld0hlaWdodCk7CiAgICAgIGJpdG1hcC5jbG9zZSgpOwogICAgICBiaXRtYXAgPSBjYW52YXMudHJhbnNmZXJUb0ltYWdlQml0bWFwKCk7CiAgICB9CiAgICBpbWdEYXRhLmRhdGEgPSBudWxsOwogICAgaW1nRGF0YS5iaXRtYXAgPSBiaXRtYXA7CiAgICBpbWdEYXRhLndpZHRoID0gbmV3V2lkdGg7CiAgICBpbWdEYXRhLmhlaWdodCA9IG5ld0hlaWdodDsKICAgIHJldHVybiBpbWdEYXRhOwogIH0KICAjcmVzY2FsZUltYWdlRGF0YSgpIHsKICAgIGNvbnN0IHsKICAgICAgX2ltZ0RhdGE6IGltZ0RhdGEKICAgIH0gPSB0aGlzOwogICAgY29uc3QgewogICAgICBkYXRhLAogICAgICB3aWR0aCwKICAgICAgaGVpZ2h0LAogICAgICBraW5kCiAgICB9ID0gaW1nRGF0YTsKICAgIGNvbnN0IHJnYmFTaXplID0gd2lkdGggKiBoZWlnaHQgKiA0OwogICAgY29uc3QgSyA9IE1hdGguY2VpbChNYXRoLmxvZzIocmdiYVNpemUgLyBNQVhfSU5UXzMyKSk7CiAgICBjb25zdCBuZXdXaWR0aCA9IHdpZHRoID4+IEs7CiAgICBjb25zdCBuZXdIZWlnaHQgPSBoZWlnaHQgPj4gSzsKICAgIGxldCByZ2JhRGF0YTsKICAgIGxldCBtYXhIZWlnaHQgPSBoZWlnaHQ7CiAgICB0cnkgewogICAgICByZ2JhRGF0YSA9IG5ldyBVaW50OEFycmF5KHJnYmFTaXplKTsKICAgIH0gY2F0Y2ggewogICAgICBsZXQgbiA9IE1hdGguZmxvb3IoTWF0aC5sb2cyKHJnYmFTaXplICsgMSkpOwogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgIHRyeSB7CiAgICAgICAgICByZ2JhRGF0YSA9IG5ldyBVaW50OEFycmF5KDIgKiogbiAtIDEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSBjYXRjaCB7CiAgICAgICAgICBuIC09IDE7CiAgICAgICAgfQogICAgICB9CiAgICAgIG1heEhlaWdodCA9IE1hdGguZmxvb3IoKDIgKiogbiAtIDEpIC8gKHdpZHRoICogNCkpOwogICAgICBjb25zdCBuZXdTaXplID0gd2lkdGggKiBtYXhIZWlnaHQgKiA0OwogICAgICBpZiAobmV3U2l6ZSA8IHJnYmFEYXRhLmxlbmd0aCkgewogICAgICAgIHJnYmFEYXRhID0gbmV3IFVpbnQ4QXJyYXkobmV3U2l6ZSk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHNyYzMyID0gbmV3IFVpbnQzMkFycmF5KHJnYmFEYXRhLmJ1ZmZlcik7CiAgICBjb25zdCBkZXN0MzIgPSBuZXcgVWludDMyQXJyYXkobmV3V2lkdGggKiBuZXdIZWlnaHQpOwogICAgbGV0IHNyY1BvcyA9IDA7CiAgICBsZXQgbmV3SW5kZXggPSAwOwogICAgY29uc3Qgc3RlcCA9IE1hdGguY2VpbChoZWlnaHQgLyBtYXhIZWlnaHQpOwogICAgY29uc3QgcmVtYWluZGVyID0gaGVpZ2h0ICUgbWF4SGVpZ2h0ID09PSAwID8gaGVpZ2h0IDogaGVpZ2h0ICUgbWF4SGVpZ2h0OwogICAgZm9yIChsZXQgayA9IDA7IGsgPCBzdGVwOyBrKyspIHsKICAgICAgY29uc3QgaCA9IGsgPCBzdGVwIC0gMSA/IG1heEhlaWdodCA6IHJlbWFpbmRlcjsKICAgICAgKHsKICAgICAgICBzcmNQb3MKICAgICAgfSA9IGNvbnZlcnRUb1JHQkEoewogICAgICAgIGtpbmQsCiAgICAgICAgc3JjOiBkYXRhLAogICAgICAgIGRlc3Q6IHNyYzMyLAogICAgICAgIHdpZHRoLAogICAgICAgIGhlaWdodDogaCwKICAgICAgICBpbnZlcnNlRGVjb2RlOiB0aGlzLl9pc01hc2ssCiAgICAgICAgc3JjUG9zCiAgICAgIH0pKTsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gaCA+PiBLOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IGJ1ZiA9IHNyYzMyLnN1YmFycmF5KChpIDw8IEspICogd2lkdGgpOwogICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbmV3V2lkdGg7IGorKykgewogICAgICAgICAgZGVzdDMyW25ld0luZGV4KytdID0gYnVmW2ogPDwgS107CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAoSW1hZ2VSZXNpemVyLm5lZWRzVG9CZVJlc2l6ZWQobmV3V2lkdGgsIG5ld0hlaWdodCkpIHsKICAgICAgaW1nRGF0YS5kYXRhID0gZGVzdDMyOwogICAgICBpbWdEYXRhLndpZHRoID0gbmV3V2lkdGg7CiAgICAgIGltZ0RhdGEuaGVpZ2h0ID0gbmV3SGVpZ2h0OwogICAgICBpbWdEYXRhLmtpbmQgPSBJbWFnZUtpbmQuUkdCQV8zMkJQUDsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBjYW52YXMgPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKG5ld1dpZHRoLCBuZXdIZWlnaHQpOwogICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIiwgewogICAgICB3aWxsUmVhZEZyZXF1ZW50bHk6IHRydWUKICAgIH0pOwogICAgY3R4LnB1dEltYWdlRGF0YShuZXcgSW1hZ2VEYXRhKG5ldyBVaW50OENsYW1wZWRBcnJheShkZXN0MzIuYnVmZmVyKSwgbmV3V2lkdGgsIG5ld0hlaWdodCksIDAsIDApOwogICAgaW1nRGF0YS5kYXRhID0gbnVsbDsKICAgIGltZ0RhdGEuYml0bWFwID0gY2FudmFzLnRyYW5zZmVyVG9JbWFnZUJpdG1hcCgpOwogICAgaW1nRGF0YS53aWR0aCA9IG5ld1dpZHRoOwogICAgaW1nRGF0YS5oZWlnaHQgPSBuZXdIZWlnaHQ7CiAgICByZXR1cm4gaW1nRGF0YTsKICB9CiAgX2VuY29kZUJNUCgpIHsKICAgIGNvbnN0IHsKICAgICAgd2lkdGgsCiAgICAgIGhlaWdodCwKICAgICAga2luZAogICAgfSA9IHRoaXMuX2ltZ0RhdGE7CiAgICBsZXQgZGF0YSA9IHRoaXMuX2ltZ0RhdGEuZGF0YTsKICAgIGxldCBiaXRQZXJQaXhlbDsKICAgIGxldCBjb2xvclRhYmxlID0gbmV3IFVpbnQ4QXJyYXkoMCk7CiAgICBsZXQgbWFza1RhYmxlID0gY29sb3JUYWJsZTsKICAgIGxldCBjb21wcmVzc2lvbiA9IDA7CiAgICBzd2l0Y2ggKGtpbmQpIHsKICAgICAgY2FzZSBJbWFnZUtpbmQuR1JBWVNDQUxFXzFCUFA6CiAgICAgICAgewogICAgICAgICAgYml0UGVyUGl4ZWwgPSAxOwogICAgICAgICAgY29sb3JUYWJsZSA9IG5ldyBVaW50OEFycmF5KHRoaXMuX2lzTWFzayA/IFsyNTUsIDI1NSwgMjU1LCAyNTUsIDAsIDAsIDAsIDBdIDogWzAsIDAsIDAsIDAsIDI1NSwgMjU1LCAyNTUsIDI1NV0pOwogICAgICAgICAgY29uc3Qgcm93TGVuID0gd2lkdGggKyA3ID4+IDM7CiAgICAgICAgICBjb25zdCByb3dTaXplID0gcm93TGVuICsgMyAmIC00OwogICAgICAgICAgaWYgKHJvd0xlbiAhPT0gcm93U2l6ZSkgewogICAgICAgICAgICBjb25zdCBuZXdEYXRhID0gbmV3IFVpbnQ4QXJyYXkocm93U2l6ZSAqIGhlaWdodCk7CiAgICAgICAgICAgIGxldCBrID0gMDsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gaGVpZ2h0ICogcm93TGVuOyBpIDwgaWk7IGkgKz0gcm93TGVuLCBrICs9IHJvd1NpemUpIHsKICAgICAgICAgICAgICBuZXdEYXRhLnNldChkYXRhLnN1YmFycmF5KGksIGkgKyByb3dMZW4pLCBrKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBkYXRhID0gbmV3RGF0YTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgY2FzZSBJbWFnZUtpbmQuUkdCXzI0QlBQOgogICAgICAgIHsKICAgICAgICAgIGJpdFBlclBpeGVsID0gMjQ7CiAgICAgICAgICBpZiAod2lkdGggJiAzKSB7CiAgICAgICAgICAgIGNvbnN0IHJvd0xlbiA9IDMgKiB3aWR0aDsKICAgICAgICAgICAgY29uc3Qgcm93U2l6ZSA9IHJvd0xlbiArIDMgJiAtNDsKICAgICAgICAgICAgY29uc3QgZXh0cmFMZW4gPSByb3dTaXplIC0gcm93TGVuOwogICAgICAgICAgICBjb25zdCBuZXdEYXRhID0gbmV3IFVpbnQ4QXJyYXkocm93U2l6ZSAqIGhlaWdodCk7CiAgICAgICAgICAgIGxldCBrID0gMDsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gaGVpZ2h0ICogcm93TGVuOyBpIDwgaWk7IGkgKz0gcm93TGVuKSB7CiAgICAgICAgICAgICAgY29uc3Qgcm93ID0gZGF0YS5zdWJhcnJheShpLCBpICsgcm93TGVuKTsKICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHJvd0xlbjsgaiArPSAzKSB7CiAgICAgICAgICAgICAgICBuZXdEYXRhW2srK10gPSByb3dbaiArIDJdOwogICAgICAgICAgICAgICAgbmV3RGF0YVtrKytdID0gcm93W2ogKyAxXTsKICAgICAgICAgICAgICAgIG5ld0RhdGFbaysrXSA9IHJvd1tqXTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgayArPSBleHRyYUxlbjsKICAgICAgICAgICAgfQogICAgICAgICAgICBkYXRhID0gbmV3RGF0YTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGRhdGEubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMykgewogICAgICAgICAgICAgIGNvbnN0IHRtcCA9IGRhdGFbaV07CiAgICAgICAgICAgICAgZGF0YVtpXSA9IGRhdGFbaSArIDJdOwogICAgICAgICAgICAgIGRhdGFbaSArIDJdID0gdG1wOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIGNhc2UgSW1hZ2VLaW5kLlJHQkFfMzJCUFA6CiAgICAgICAgYml0UGVyUGl4ZWwgPSAzMjsKICAgICAgICBjb21wcmVzc2lvbiA9IDM7CiAgICAgICAgbWFza1RhYmxlID0gbmV3IFVpbnQ4QXJyYXkoNCArIDQgKyA0ICsgNCArIDUyKTsKICAgICAgICBjb25zdCB2aWV3ID0gbmV3IERhdGFWaWV3KG1hc2tUYWJsZS5idWZmZXIpOwogICAgICAgIGlmIChGZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbikgewogICAgICAgICAgdmlldy5zZXRVaW50MzIoMCwgMHgwMDAwMDBmZiwgdHJ1ZSk7CiAgICAgICAgICB2aWV3LnNldFVpbnQzMig0LCAweDAwMDBmZjAwLCB0cnVlKTsKICAgICAgICAgIHZpZXcuc2V0VWludDMyKDgsIDB4MDBmZjAwMDAsIHRydWUpOwogICAgICAgICAgdmlldy5zZXRVaW50MzIoMTIsIDB4ZmYwMDAwMDAsIHRydWUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB2aWV3LnNldFVpbnQzMigwLCAweGZmMDAwMDAwLCB0cnVlKTsKICAgICAgICAgIHZpZXcuc2V0VWludDMyKDQsIDB4MDBmZjAwMDAsIHRydWUpOwogICAgICAgICAgdmlldy5zZXRVaW50MzIoOCwgMHgwMDAwZmYwMCwgdHJ1ZSk7CiAgICAgICAgICB2aWV3LnNldFVpbnQzMigxMiwgMHgwMDAwMDBmZiwgdHJ1ZSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93IG5ldyBFcnJvcigiaW52YWxpZCBmb3JtYXQiKTsKICAgIH0KICAgIGxldCBpID0gMDsKICAgIGNvbnN0IGhlYWRlckxlbmd0aCA9IDQwICsgbWFza1RhYmxlLmxlbmd0aDsKICAgIGNvbnN0IGZpbGVMZW5ndGggPSAxNCArIGhlYWRlckxlbmd0aCArIGNvbG9yVGFibGUubGVuZ3RoICsgZGF0YS5sZW5ndGg7CiAgICBjb25zdCBibXBEYXRhID0gbmV3IFVpbnQ4QXJyYXkoZmlsZUxlbmd0aCk7CiAgICBjb25zdCB2aWV3ID0gbmV3IERhdGFWaWV3KGJtcERhdGEuYnVmZmVyKTsKICAgIHZpZXcuc2V0VWludDE2KGksIDB4NGQ0MiwgdHJ1ZSk7CiAgICBpICs9IDI7CiAgICB2aWV3LnNldFVpbnQzMihpLCBmaWxlTGVuZ3RoLCB0cnVlKTsKICAgIGkgKz0gNDsKICAgIHZpZXcuc2V0VWludDMyKGksIDAsIHRydWUpOwogICAgaSArPSA0OwogICAgdmlldy5zZXRVaW50MzIoaSwgMTQgKyBoZWFkZXJMZW5ndGggKyBjb2xvclRhYmxlLmxlbmd0aCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldFVpbnQzMihpLCBoZWFkZXJMZW5ndGgsIHRydWUpOwogICAgaSArPSA0OwogICAgdmlldy5zZXRJbnQzMihpLCB3aWR0aCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldEludDMyKGksIC1oZWlnaHQsIHRydWUpOwogICAgaSArPSA0OwogICAgdmlldy5zZXRVaW50MTYoaSwgMSwgdHJ1ZSk7CiAgICBpICs9IDI7CiAgICB2aWV3LnNldFVpbnQxNihpLCBiaXRQZXJQaXhlbCwgdHJ1ZSk7CiAgICBpICs9IDI7CiAgICB2aWV3LnNldFVpbnQzMihpLCBjb21wcmVzc2lvbiwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldFVpbnQzMihpLCAwLCB0cnVlKTsKICAgIGkgKz0gNDsKICAgIHZpZXcuc2V0SW50MzIoaSwgMCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldEludDMyKGksIDAsIHRydWUpOwogICAgaSArPSA0OwogICAgdmlldy5zZXRVaW50MzIoaSwgY29sb3JUYWJsZS5sZW5ndGggLyA0LCB0cnVlKTsKICAgIGkgKz0gNDsKICAgIHZpZXcuc2V0VWludDMyKGksIDAsIHRydWUpOwogICAgaSArPSA0OwogICAgYm1wRGF0YS5zZXQobWFza1RhYmxlLCBpKTsKICAgIGkgKz0gbWFza1RhYmxlLmxlbmd0aDsKICAgIGJtcERhdGEuc2V0KGNvbG9yVGFibGUsIGkpOwogICAgaSArPSBjb2xvclRhYmxlLmxlbmd0aDsKICAgIGJtcERhdGEuc2V0KGRhdGEsIGkpOwogICAgcmV0dXJuIGJtcERhdGE7CiAgfQp9Cgo7Ly8gLi9leHRlcm5hbC9qYmlnMi9qYmlnMi5qcwphc3luYyBmdW5jdGlvbiBKQmlnMihtb2R1bGVBcmcgPSB7fSkgewogIHZhciBtb2R1bGVSdG47CiAgdmFyIE1vZHVsZSA9IG1vZHVsZUFyZzsKICB2YXIgRU5WSVJPTk1FTlRfSVNfV0VCID0gdHJ1ZTsKICB2YXIgRU5WSVJPTk1FTlRfSVNfV09SS0VSID0gZmFsc2U7CiAgdmFyIGFyZ3VtZW50c18gPSBbXTsKICB2YXIgdGhpc1Byb2dyYW0gPSAiLi90aGlzLnByb2dyYW0iOwogIHZhciBxdWl0XyA9IChzdGF0dXMsIHRvVGhyb3cpID0+IHsKICAgIHRocm93IHRvVGhyb3c7CiAgfTsKICB2YXIgX3NjcmlwdE5hbWUgPSBpbXBvcnQubWV0YS51cmw7CiAgdmFyIHNjcmlwdERpcmVjdG9yeSA9ICIiOwogIHZhciByZWFkQXN5bmMsIHJlYWRCaW5hcnk7CiAgaWYgKEVOVklST05NRU5UX0lTX1dFQiB8fCBFTlZJUk9OTUVOVF9JU19XT1JLRVIpIHsKICAgIHRyeSB7CiAgICAgIHNjcmlwdERpcmVjdG9yeSA9IG5ldyBVUkwoIi4iLCBfc2NyaXB0TmFtZSkuaHJlZjsKICAgIH0gY2F0Y2gge30KICAgIHJlYWRBc3luYyA9IGFzeW5jIHVybCA9PiB7CiAgICAgIHZhciByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVybCwgewogICAgICAgIGNyZWRlbnRpYWxzOiAic2FtZS1vcmlnaW4iCiAgICAgIH0pOwogICAgICBpZiAocmVzcG9uc2Uub2spIHsKICAgICAgICByZXR1cm4gcmVzcG9uc2UuYXJyYXlCdWZmZXIoKTsKICAgICAgfQogICAgICB0aHJvdyBuZXcgRXJyb3IocmVzcG9uc2Uuc3RhdHVzICsgIiA6ICIgKyByZXNwb25zZS51cmwpOwogICAgfTsKICB9IGVsc2Uge30KICB2YXIgb3V0ID0gY29uc29sZS5sb2cuYmluZChjb25zb2xlKTsKICB2YXIgZXJyID0gY29uc29sZS5lcnJvci5iaW5kKGNvbnNvbGUpOwogIHZhciB3YXNtQmluYXJ5OwogIHZhciBBQk9SVCA9IGZhbHNlOwogIHZhciBFWElUU1RBVFVTOwogIHZhciByZWFkeVByb21pc2VSZXNvbHZlLCByZWFkeVByb21pc2VSZWplY3Q7CiAgdmFyIEhFQVA4LCBIRUFQVTgsIEhFQVAxNiwgSEVBUFUxNiwgSEVBUDMyLCBIRUFQVTMyLCBIRUFQRjMyLCBIRUFQRjY0OwogIHZhciBIRUFQNjQsIEhFQVBVNjQ7CiAgdmFyIHJ1bnRpbWVJbml0aWFsaXplZCA9IGZhbHNlOwogIGZ1bmN0aW9uIHVwZGF0ZU1lbW9yeVZpZXdzKCkgewogICAgdmFyIGIgPSB3YXNtTWVtb3J5LmJ1ZmZlcjsKICAgIEhFQVA4ID0gbmV3IEludDhBcnJheShiKTsKICAgIEhFQVAxNiA9IG5ldyBJbnQxNkFycmF5KGIpOwogICAgSEVBUFU4ID0gbmV3IFVpbnQ4QXJyYXkoYik7CiAgICBIRUFQVTE2ID0gbmV3IFVpbnQxNkFycmF5KGIpOwogICAgSEVBUDMyID0gbmV3IEludDMyQXJyYXkoYik7CiAgICBIRUFQVTMyID0gbmV3IFVpbnQzMkFycmF5KGIpOwogICAgSEVBUEYzMiA9IG5ldyBGbG9hdDMyQXJyYXkoYik7CiAgICBIRUFQRjY0ID0gbmV3IEZsb2F0NjRBcnJheShiKTsKICAgIEhFQVA2NCA9IG5ldyBCaWdJbnQ2NEFycmF5KGIpOwogICAgSEVBUFU2NCA9IG5ldyBCaWdVaW50NjRBcnJheShiKTsKICB9CiAgZnVuY3Rpb24gcHJlUnVuKCkgewogICAgaWYgKE1vZHVsZVsicHJlUnVuIl0pIHsKICAgICAgaWYgKHR5cGVvZiBNb2R1bGVbInByZVJ1biJdID09ICJmdW5jdGlvbiIpIE1vZHVsZVsicHJlUnVuIl0gPSBbTW9kdWxlWyJwcmVSdW4iXV07CiAgICAgIHdoaWxlIChNb2R1bGVbInByZVJ1biJdLmxlbmd0aCkgewogICAgICAgIGFkZE9uUHJlUnVuKE1vZHVsZVsicHJlUnVuIl0uc2hpZnQoKSk7CiAgICAgIH0KICAgIH0KICAgIGNhbGxSdW50aW1lQ2FsbGJhY2tzKG9uUHJlUnVucyk7CiAgfQogIGZ1bmN0aW9uIGluaXRSdW50aW1lKCkgewogICAgcnVudGltZUluaXRpYWxpemVkID0gdHJ1ZTsKICAgIHdhc21FeHBvcnRzWyJoIl0oKTsKICB9CiAgZnVuY3Rpb24gcG9zdFJ1bigpIHsKICAgIGlmIChNb2R1bGVbInBvc3RSdW4iXSkgewogICAgICBpZiAodHlwZW9mIE1vZHVsZVsicG9zdFJ1biJdID09ICJmdW5jdGlvbiIpIE1vZHVsZVsicG9zdFJ1biJdID0gW01vZHVsZVsicG9zdFJ1biJdXTsKICAgICAgd2hpbGUgKE1vZHVsZVsicG9zdFJ1biJdLmxlbmd0aCkgewogICAgICAgIGFkZE9uUG9zdFJ1bihNb2R1bGVbInBvc3RSdW4iXS5zaGlmdCgpKTsKICAgICAgfQogICAgfQogICAgY2FsbFJ1bnRpbWVDYWxsYmFja3Mob25Qb3N0UnVucyk7CiAgfQogIGZ1bmN0aW9uIGFib3J0KHdoYXQpIHsKICAgIE1vZHVsZVsib25BYm9ydCJdPy4od2hhdCk7CiAgICB3aGF0ID0gIkFib3J0ZWQoIiArIHdoYXQgKyAiKSI7CiAgICBlcnIod2hhdCk7CiAgICBBQk9SVCA9IHRydWU7CiAgICB3aGF0ICs9ICIuIEJ1aWxkIHdpdGggLXNBU1NFUlRJT05TIGZvciBtb3JlIGluZm8uIjsKICAgIHZhciBlID0gbmV3IFdlYkFzc2VtYmx5LlJ1bnRpbWVFcnJvcih3aGF0KTsKICAgIHJlYWR5UHJvbWlzZVJlamVjdD8uKGUpOwogICAgdGhyb3cgZTsKICB9CiAgdmFyIHdhc21CaW5hcnlGaWxlOwogIGZ1bmN0aW9uIGdldFdhc21JbXBvcnRzKCkgewogICAgdmFyIGltcG9ydHMgPSB7CiAgICAgIGE6IHdhc21JbXBvcnRzCiAgICB9OwogICAgcmV0dXJuIGltcG9ydHM7CiAgfQogIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdhc20oKSB7CiAgICBmdW5jdGlvbiByZWNlaXZlSW5zdGFuY2UoaW5zdGFuY2UsIG1vZHVsZSkgewogICAgICB3YXNtRXhwb3J0cyA9IGluc3RhbmNlLmV4cG9ydHM7CiAgICAgIGFzc2lnbldhc21FeHBvcnRzKHdhc21FeHBvcnRzKTsKICAgICAgdXBkYXRlTWVtb3J5Vmlld3MoKTsKICAgICAgcmV0dXJuIHdhc21FeHBvcnRzOwogICAgfQogICAgdmFyIGluZm8gPSBnZXRXYXNtSW1wb3J0cygpOwogICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsKICAgICAgTW9kdWxlWyJpbnN0YW50aWF0ZVdhc20iXShpbmZvLCAoaW5zdCwgbW9kKSA9PiB7CiAgICAgICAgcmVzb2x2ZShyZWNlaXZlSW5zdGFuY2UoaW5zdCwgbW9kKSk7CiAgICAgIH0pOwogICAgfSk7CiAgfQogIGNsYXNzIEV4aXRTdGF0dXMgewogICAgbmFtZSA9ICJFeGl0U3RhdHVzIjsKICAgIGNvbnN0cnVjdG9yKHN0YXR1cykgewogICAgICB0aGlzLm1lc3NhZ2UgPSBgUHJvZ3JhbSB0ZXJtaW5hdGVkIHdpdGggZXhpdCgke3N0YXR1c30pYDsKICAgICAgdGhpcy5zdGF0dXMgPSBzdGF0dXM7CiAgICB9CiAgfQogIHZhciBjYWxsUnVudGltZUNhbGxiYWNrcyA9IGNhbGxiYWNrcyA9PiB7CiAgICB3aGlsZSAoY2FsbGJhY2tzLmxlbmd0aCA+IDApIHsKICAgICAgY2FsbGJhY2tzLnNoaWZ0KCkoTW9kdWxlKTsKICAgIH0KICB9OwogIHZhciBvblBvc3RSdW5zID0gW107CiAgdmFyIGFkZE9uUG9zdFJ1biA9IGNiID0+IG9uUG9zdFJ1bnMucHVzaChjYik7CiAgdmFyIG9uUHJlUnVucyA9IFtdOwogIHZhciBhZGRPblByZVJ1biA9IGNiID0+IG9uUHJlUnVucy5wdXNoKGNiKTsKICB2YXIgbm9FeGl0UnVudGltZSA9IHRydWU7CiAgdmFyIF9fYWJvcnRfanMgPSAoKSA9PiBhYm9ydCgiIik7CiAgdmFyIHJ1bnRpbWVLZWVwYWxpdmVDb3VudGVyID0gMDsKICB2YXIgX19lbXNjcmlwdGVuX3J1bnRpbWVfa2VlcGFsaXZlX2NsZWFyID0gKCkgPT4gewogICAgbm9FeGl0UnVudGltZSA9IGZhbHNlOwogICAgcnVudGltZUtlZXBhbGl2ZUNvdW50ZXIgPSAwOwogIH07CiAgdmFyIHRpbWVycyA9IHt9OwogIHZhciBoYW5kbGVFeGNlcHRpb24gPSBlID0+IHsKICAgIGlmIChlIGluc3RhbmNlb2YgRXhpdFN0YXR1cyB8fCBlID09ICJ1bndpbmQiKSB7CiAgICAgIHJldHVybiBFWElUU1RBVFVTOwogICAgfQogICAgcXVpdF8oMSwgZSk7CiAgfTsKICB2YXIga2VlcFJ1bnRpbWVBbGl2ZSA9ICgpID0+IG5vRXhpdFJ1bnRpbWUgfHwgcnVudGltZUtlZXBhbGl2ZUNvdW50ZXIgPiAwOwogIHZhciBfcHJvY19leGl0ID0gY29kZSA9PiB7CiAgICBFWElUU1RBVFVTID0gY29kZTsKICAgIGlmICgha2VlcFJ1bnRpbWVBbGl2ZSgpKSB7CiAgICAgIE1vZHVsZVsib25FeGl0Il0/Lihjb2RlKTsKICAgICAgQUJPUlQgPSB0cnVlOwogICAgfQogICAgcXVpdF8oY29kZSwgbmV3IEV4aXRTdGF0dXMoY29kZSkpOwogIH07CiAgdmFyIGV4aXRKUyA9IChzdGF0dXMsIGltcGxpY2l0KSA9PiB7CiAgICBFWElUU1RBVFVTID0gc3RhdHVzOwogICAgX3Byb2NfZXhpdChzdGF0dXMpOwogIH07CiAgdmFyIF9leGl0ID0gZXhpdEpTOwogIHZhciBtYXliZUV4aXQgPSAoKSA9PiB7CiAgICBpZiAoIWtlZXBSdW50aW1lQWxpdmUoKSkgewogICAgICB0cnkgewogICAgICAgIF9leGl0KEVYSVRTVEFUVVMpOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgaGFuZGxlRXhjZXB0aW9uKGUpOwogICAgICB9CiAgICB9CiAgfTsKICB2YXIgY2FsbFVzZXJDYWxsYmFjayA9IGZ1bmMgPT4gewogICAgaWYgKEFCT1JUKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRyeSB7CiAgICAgIGZ1bmMoKTsKICAgICAgbWF5YmVFeGl0KCk7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIGhhbmRsZUV4Y2VwdGlvbihlKTsKICAgIH0KICB9OwogIHZhciBfZW1zY3JpcHRlbl9nZXRfbm93ID0gKCkgPT4gcGVyZm9ybWFuY2Uubm93KCk7CiAgdmFyIF9fc2V0aXRpbWVyX2pzID0gKHdoaWNoLCB0aW1lb3V0X21zKSA9PiB7CiAgICBpZiAodGltZXJzW3doaWNoXSkgewogICAgICBjbGVhclRpbWVvdXQodGltZXJzW3doaWNoXS5pZCk7CiAgICAgIGRlbGV0ZSB0aW1lcnNbd2hpY2hdOwogICAgfQogICAgaWYgKCF0aW1lb3V0X21zKSByZXR1cm4gMDsKICAgIHZhciBpZCA9IHNldFRpbWVvdXQoKCkgPT4gewogICAgICBkZWxldGUgdGltZXJzW3doaWNoXTsKICAgICAgY2FsbFVzZXJDYWxsYmFjaygoKSA9PiBfX2Vtc2NyaXB0ZW5fdGltZW91dCh3aGljaCwgX2Vtc2NyaXB0ZW5fZ2V0X25vdygpKSk7CiAgICB9LCB0aW1lb3V0X21zKTsKICAgIHRpbWVyc1t3aGljaF0gPSB7CiAgICAgIGlkLAogICAgICB0aW1lb3V0X21zCiAgICB9OwogICAgcmV0dXJuIDA7CiAgfTsKICB2YXIgZ2V0SGVhcE1heCA9ICgpID0+IDIxNDc0ODM2NDg7CiAgdmFyIGFsaWduTWVtb3J5ID0gKHNpemUsIGFsaWdubWVudCkgPT4gTWF0aC5jZWlsKHNpemUgLyBhbGlnbm1lbnQpICogYWxpZ25tZW50OwogIHZhciBncm93TWVtb3J5ID0gc2l6ZSA9PiB7CiAgICB2YXIgb2xkSGVhcFNpemUgPSB3YXNtTWVtb3J5LmJ1ZmZlci5ieXRlTGVuZ3RoOwogICAgdmFyIHBhZ2VzID0gKHNpemUgLSBvbGRIZWFwU2l6ZSArIDY1NTM1KSAvIDY1NTM2IHwgMDsKICAgIHRyeSB7CiAgICAgIHdhc21NZW1vcnkuZ3JvdyhwYWdlcyk7CiAgICAgIHVwZGF0ZU1lbW9yeVZpZXdzKCk7CiAgICAgIHJldHVybiAxOwogICAgfSBjYXRjaCAoZSkge30KICB9OwogIHZhciBfZW1zY3JpcHRlbl9yZXNpemVfaGVhcCA9IHJlcXVlc3RlZFNpemUgPT4gewogICAgdmFyIG9sZFNpemUgPSBIRUFQVTgubGVuZ3RoOwogICAgcmVxdWVzdGVkU2l6ZSA+Pj49IDA7CiAgICB2YXIgbWF4SGVhcFNpemUgPSBnZXRIZWFwTWF4KCk7CiAgICBpZiAocmVxdWVzdGVkU2l6ZSA+IG1heEhlYXBTaXplKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGZvciAodmFyIGN1dERvd24gPSAxOyBjdXREb3duIDw9IDQ7IGN1dERvd24gKj0gMikgewogICAgICB2YXIgb3Zlckdyb3duSGVhcFNpemUgPSBvbGRTaXplICogKDEgKyAuMiAvIGN1dERvd24pOwogICAgICBvdmVyR3Jvd25IZWFwU2l6ZSA9IE1hdGgubWluKG92ZXJHcm93bkhlYXBTaXplLCByZXF1ZXN0ZWRTaXplICsgMTAwNjYzMjk2KTsKICAgICAgdmFyIG5ld1NpemUgPSBNYXRoLm1pbihtYXhIZWFwU2l6ZSwgYWxpZ25NZW1vcnkoTWF0aC5tYXgocmVxdWVzdGVkU2l6ZSwgb3Zlckdyb3duSGVhcFNpemUpLCA2NTUzNikpOwogICAgICB2YXIgcmVwbGFjZW1lbnQgPSBncm93TWVtb3J5KG5ld1NpemUpOwogICAgICBpZiAocmVwbGFjZW1lbnQpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH07CiAgZnVuY3Rpb24gX3NldEltYWdlRGF0YShhcnJheV9wdHIsIHBpdGNoOCwgcGl0Y2gzMiwgaGVpZ2h0KSB7CiAgICBpZiAocGl0Y2gzMiA9PT0gcGl0Y2g4KSB7CiAgICAgIE1vZHVsZS5pbWFnZURhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoSEVBUFU4LnN1YmFycmF5KGFycmF5X3B0ciwgYXJyYXlfcHRyICsgcGl0Y2gzMiAqIGhlaWdodCkpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBkZXN0U2l6ZSA9IHBpdGNoOCAqIGhlaWdodDsKICAgIGNvbnN0IGltYWdlRGF0YSA9IE1vZHVsZS5pbWFnZURhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoZGVzdFNpemUpOwogICAgZm9yIChsZXQgc3JjU3RhcnQgPSBhcnJheV9wdHIsIGRlc3RTdGFydCA9IDA7IGRlc3RTdGFydCA8IGRlc3RTaXplOyBzcmNTdGFydCArPSBwaXRjaDMyLCBkZXN0U3RhcnQgKz0gcGl0Y2g4KSB7CiAgICAgIGltYWdlRGF0YS5zZXQoSEVBUFU4LnN1YmFycmF5KHNyY1N0YXJ0LCBzcmNTdGFydCArIHBpdGNoOCksIGRlc3RTdGFydCk7CiAgICB9CiAgfQogIHZhciB3cml0ZUFycmF5VG9NZW1vcnkgPSAoYXJyYXksIGJ1ZmZlcikgPT4gewogICAgSEVBUDguc2V0KGFycmF5LCBidWZmZXIpOwogIH07CiAgaWYgKE1vZHVsZVsibm9FeGl0UnVudGltZSJdKSBub0V4aXRSdW50aW1lID0gTW9kdWxlWyJub0V4aXRSdW50aW1lIl07CiAgaWYgKE1vZHVsZVsicHJpbnQiXSkgb3V0ID0gTW9kdWxlWyJwcmludCJdOwogIGlmIChNb2R1bGVbInByaW50RXJyIl0pIGVyciA9IE1vZHVsZVsicHJpbnRFcnIiXTsKICBpZiAoTW9kdWxlWyJ3YXNtQmluYXJ5Il0pIHdhc21CaW5hcnkgPSBNb2R1bGVbIndhc21CaW5hcnkiXTsKICBpZiAoTW9kdWxlWyJhcmd1bWVudHMiXSkgYXJndW1lbnRzXyA9IE1vZHVsZVsiYXJndW1lbnRzIl07CiAgaWYgKE1vZHVsZVsidGhpc1Byb2dyYW0iXSkgdGhpc1Byb2dyYW0gPSBNb2R1bGVbInRoaXNQcm9ncmFtIl07CiAgaWYgKE1vZHVsZVsicHJlSW5pdCJdKSB7CiAgICBpZiAodHlwZW9mIE1vZHVsZVsicHJlSW5pdCJdID09ICJmdW5jdGlvbiIpIE1vZHVsZVsicHJlSW5pdCJdID0gW01vZHVsZVsicHJlSW5pdCJdXTsKICAgIHdoaWxlIChNb2R1bGVbInByZUluaXQiXS5sZW5ndGggPiAwKSB7CiAgICAgIE1vZHVsZVsicHJlSW5pdCJdLnNoaWZ0KCkoKTsKICAgIH0KICB9CiAgTW9kdWxlWyJ3cml0ZUFycmF5VG9NZW1vcnkiXSA9IHdyaXRlQXJyYXlUb01lbW9yeTsKICB2YXIgX21hbGxvYywgX2ZyZWUsIF9qYmlnMl9kZWNvZGUsIF9fZW1zY3JpcHRlbl90aW1lb3V0LCBtZW1vcnksIF9faW5kaXJlY3RfZnVuY3Rpb25fdGFibGUsIHdhc21NZW1vcnk7CiAgZnVuY3Rpb24gYXNzaWduV2FzbUV4cG9ydHMod2FzbUV4cG9ydHMpIHsKICAgIF9tYWxsb2MgPSBNb2R1bGVbIl9tYWxsb2MiXSA9IHdhc21FeHBvcnRzWyJpIl07CiAgICBfZnJlZSA9IE1vZHVsZVsiX2ZyZWUiXSA9IHdhc21FeHBvcnRzWyJqIl07CiAgICBfamJpZzJfZGVjb2RlID0gTW9kdWxlWyJfamJpZzJfZGVjb2RlIl0gPSB3YXNtRXhwb3J0c1siayJdOwogICAgX19lbXNjcmlwdGVuX3RpbWVvdXQgPSB3YXNtRXhwb3J0c1sibCJdOwogICAgbWVtb3J5ID0gd2FzbU1lbW9yeSA9IHdhc21FeHBvcnRzWyJnIl07CiAgICBfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlID0gd2FzbUV4cG9ydHNbIl9faW5kaXJlY3RfZnVuY3Rpb25fdGFibGUiXTsKICB9CiAgdmFyIHdhc21JbXBvcnRzID0gewogICAgZTogX19hYm9ydF9qcywKICAgIGI6IF9fZW1zY3JpcHRlbl9ydW50aW1lX2tlZXBhbGl2ZV9jbGVhciwKICAgIGM6IF9fc2V0aXRpbWVyX2pzLAogICAgZDogX2Vtc2NyaXB0ZW5fcmVzaXplX2hlYXAsCiAgICBhOiBfcHJvY19leGl0LAogICAgZjogX3NldEltYWdlRGF0YQogIH07CiAgZnVuY3Rpb24gcnVuKCkgewogICAgcHJlUnVuKCk7CiAgICBmdW5jdGlvbiBkb1J1bigpIHsKICAgICAgTW9kdWxlWyJjYWxsZWRSdW4iXSA9IHRydWU7CiAgICAgIGlmIChBQk9SVCkgcmV0dXJuOwogICAgICBpbml0UnVudGltZSgpOwogICAgICByZWFkeVByb21pc2VSZXNvbHZlPy4oTW9kdWxlKTsKICAgICAgTW9kdWxlWyJvblJ1bnRpbWVJbml0aWFsaXplZCJdPy4oKTsKICAgICAgcG9zdFJ1bigpOwogICAgfQogICAgaWYgKE1vZHVsZVsic2V0U3RhdHVzIl0pIHsKICAgICAgTW9kdWxlWyJzZXRTdGF0dXMiXSgiUnVubmluZy4uLiIpOwogICAgICBzZXRUaW1lb3V0KCgpID0+IHsKICAgICAgICBzZXRUaW1lb3V0KCgpID0+IE1vZHVsZVsic2V0U3RhdHVzIl0oIiIpLCAxKTsKICAgICAgICBkb1J1bigpOwogICAgICB9LCAxKTsKICAgIH0gZWxzZSB7CiAgICAgIGRvUnVuKCk7CiAgICB9CiAgfQogIHZhciB3YXNtRXhwb3J0czsKICB3YXNtRXhwb3J0cyA9IGF3YWl0IGNyZWF0ZVdhc20oKTsKICBydW4oKTsKICBpZiAocnVudGltZUluaXRpYWxpemVkKSB7CiAgICBtb2R1bGVSdG4gPSBNb2R1bGU7CiAgfSBlbHNlIHsKICAgIG1vZHVsZVJ0biA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsKICAgICAgcmVhZHlQcm9taXNlUmVzb2x2ZSA9IHJlc29sdmU7CiAgICAgIHJlYWR5UHJvbWlzZVJlamVjdCA9IHJlamVjdDsKICAgIH0pOwogIH0KICByZXR1cm4gbW9kdWxlUnRuOwp9Ci8qIGhhcm1vbnkgZGVmYXVsdCBleHBvcnQgKi8gY29uc3QgamJpZzIgPSAoSkJpZzIpOwo7Ly8gLi9zcmMvY29yZS9qYmlnMl93YXNtLmpzCgoKCmNsYXNzIEpCaWcyRXJyb3IgZXh0ZW5kcyBCYXNlRXhjZXB0aW9uIHsKICBjb25zdHJ1Y3Rvcihtc2cpIHsKICAgIHN1cGVyKG1zZywgIkpiaWcyRXJyb3IiKTsKICB9Cn0KY2xhc3MgSkJpZzJXYXNtSW1hZ2UgewogIHN0YXRpYyAjYnVmZmVyID0gbnVsbDsKICBzdGF0aWMgI2hhbmRsZXIgPSBudWxsOwogIHN0YXRpYyAjbW9kdWxlUHJvbWlzZSA9IG51bGw7CiAgc3RhdGljICN1c2VXYXNtID0gdHJ1ZTsKICBzdGF0aWMgI3VzZVdvcmtlckZldGNoID0gdHJ1ZTsKICBzdGF0aWMgI3dhc21VcmwgPSBudWxsOwogIHN0YXRpYyBzZXRPcHRpb25zKHsKICAgIGhhbmRsZXIsCiAgICB1c2VXYXNtLAogICAgdXNlV29ya2VyRmV0Y2gsCiAgICB3YXNtVXJsCiAgfSkgewogICAgdGhpcy4jdXNlV2FzbSA9IHVzZVdhc207CiAgICB0aGlzLiN1c2VXb3JrZXJGZXRjaCA9IHVzZVdvcmtlckZldGNoOwogICAgdGhpcy4jd2FzbVVybCA9IHdhc21Vcmw7CiAgICBpZiAoIXVzZVdvcmtlckZldGNoKSB7CiAgICAgIHRoaXMuI2hhbmRsZXIgPSBoYW5kbGVyOwogICAgfQogIH0KICBzdGF0aWMgYXN5bmMgI2luc3RhbnRpYXRlV2FzbShmYWxsYmFja0NhbGxiYWNrLCBpbXBvcnRzLCBzdWNjZXNzQ2FsbGJhY2spIHsKICAgIGNvbnN0IGZpbGVuYW1lID0gImpiaWcyLndhc20iOwogICAgdHJ5IHsKICAgICAgaWYgKCF0aGlzLiNidWZmZXIpIHsKICAgICAgICBpZiAodGhpcy4jdXNlV29ya2VyRmV0Y2gpIHsKICAgICAgICAgIHRoaXMuI2J1ZmZlciA9IGF3YWl0IGZldGNoQmluYXJ5RGF0YShgJHt0aGlzLiN3YXNtVXJsfSR7ZmlsZW5hbWV9YCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuI2J1ZmZlciA9IGF3YWl0IHRoaXMuI2hhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJGZXRjaEJpbmFyeURhdGEiLCB7CiAgICAgICAgICAgIHR5cGU6ICJ3YXNtRmFjdG9yeSIsCiAgICAgICAgICAgIGZpbGVuYW1lCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKHRoaXMuI2J1ZmZlciwgaW1wb3J0cyk7CiAgICAgIHJldHVybiBzdWNjZXNzQ2FsbGJhY2socmVzdWx0cy5pbnN0YW5jZSk7CiAgICB9IGNhdGNoIChyZWFzb24pIHsKICAgICAgd2FybihgSkJpZzJJbWFnZSNpbnN0YW50aWF0ZVdhc206ICR7cmVhc29ufWApOwogICAgICByZXR1cm4gZmFsbGJhY2tDYWxsYmFjayhudWxsKTsKICAgIH0gZmluYWxseSB7CiAgICAgIHRoaXMuI2hhbmRsZXIgPSBudWxsOwogICAgfQogIH0KICBzdGF0aWMgYXN5bmMgZGVjb2RlKGJ5dGVzLCB3aWR0aCwgaGVpZ2h0LCBnbG9iYWxzKSB7CiAgICBpZiAoIXRoaXMuI21vZHVsZVByb21pc2UpIHsKICAgICAgY29uc3QgewogICAgICAgIHByb21pc2UsCiAgICAgICAgcmVzb2x2ZQogICAgICB9ID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7CiAgICAgIGNvbnN0IHByb21pc2VzID0gW3Byb21pc2VdOwogICAgICBpZiAodGhpcy4jdXNlV2FzbSkgewogICAgICAgIHByb21pc2VzLnB1c2goamJpZzIoewogICAgICAgICAgd2Fybjogd2FybiwKICAgICAgICAgIGluc3RhbnRpYXRlV2FzbTogdGhpcy4jaW5zdGFudGlhdGVXYXNtLmJpbmQodGhpcywgcmVzb2x2ZSkKICAgICAgICB9KSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmVzb2x2ZShudWxsKTsKICAgICAgfQogICAgICB0aGlzLiNtb2R1bGVQcm9taXNlID0gUHJvbWlzZS5yYWNlKHByb21pc2VzKTsKICAgIH0KICAgIGNvbnN0IG1vZHVsZSA9IGF3YWl0IHRoaXMuI21vZHVsZVByb21pc2U7CiAgICBpZiAoIW1vZHVsZSkgewogICAgICB0aHJvdyBuZXcgSkJpZzJFcnJvcigiSkJpZzIgZmFpbGVkIHRvIGluaXRpYWxpemUiKTsKICAgIH0KICAgIGxldCBwdHIsIGdsb2JhbHNQdHI7CiAgICB0cnkgewogICAgICBjb25zdCBzaXplID0gYnl0ZXMubGVuZ3RoOwogICAgICBwdHIgPSBtb2R1bGUuX21hbGxvYyhzaXplKTsKICAgICAgbW9kdWxlLndyaXRlQXJyYXlUb01lbW9yeShieXRlcywgcHRyKTsKICAgICAgY29uc3QgZ2xvYmFsc1NpemUgPSBnbG9iYWxzID8gZ2xvYmFscy5sZW5ndGggOiAwOwogICAgICBpZiAoZ2xvYmFsc1NpemUgPiAwKSB7CiAgICAgICAgZ2xvYmFsc1B0ciA9IG1vZHVsZS5fbWFsbG9jKGdsb2JhbHNTaXplKTsKICAgICAgICBtb2R1bGUud3JpdGVBcnJheVRvTWVtb3J5KGdsb2JhbHMsIGdsb2JhbHNQdHIpOwogICAgICB9CiAgICAgIG1vZHVsZS5famJpZzJfZGVjb2RlKHB0ciwgc2l6ZSwgd2lkdGgsIGhlaWdodCwgZ2xvYmFsc1B0ciwgZ2xvYmFsc1NpemUpOwogICAgICBpZiAoIW1vZHVsZS5pbWFnZURhdGEpIHsKICAgICAgICB0aHJvdyBuZXcgSkJpZzJFcnJvcigiVW5rbm93biBlcnJvciIpOwogICAgICB9CiAgICAgIGNvbnN0IHsKICAgICAgICBpbWFnZURhdGEKICAgICAgfSA9IG1vZHVsZTsKICAgICAgbW9kdWxlLmltYWdlRGF0YSA9IG51bGw7CiAgICAgIHJldHVybiBpbWFnZURhdGE7CiAgICB9IGZpbmFsbHkgewogICAgICBpZiAocHRyKSB7CiAgICAgICAgbW9kdWxlLl9mcmVlKHB0cik7CiAgICAgIH0KICAgICAgaWYgKGdsb2JhbHNQdHIpIHsKICAgICAgICBtb2R1bGUuX2ZyZWUoZ2xvYmFsc1B0cik7CiAgICAgIH0KICAgIH0KICB9CiAgc3RhdGljIGNsZWFudXAoKSB7CiAgICB0aGlzLiNtb2R1bGVQcm9taXNlID0gbnVsbDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2RlY29kZV9zdHJlYW0uanMKCgpjb25zdCBlbXB0eUJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KDApOwpjbGFzcyBEZWNvZGVTdHJlYW0gZXh0ZW5kcyBCYXNlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihtYXliZU1pbkJ1ZmZlckxlbmd0aCkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuX3Jhd01pbkJ1ZmZlckxlbmd0aCA9IG1heWJlTWluQnVmZmVyTGVuZ3RoIHx8IDA7CiAgICB0aGlzLnBvcyA9IDA7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IDA7CiAgICB0aGlzLmVvZiA9IGZhbHNlOwogICAgdGhpcy5idWZmZXIgPSBlbXB0eUJ1ZmZlcjsKICAgIHRoaXMubWluQnVmZmVyTGVuZ3RoID0gNTEyOwogICAgaWYgKG1heWJlTWluQnVmZmVyTGVuZ3RoKSB7CiAgICAgIHdoaWxlICh0aGlzLm1pbkJ1ZmZlckxlbmd0aCA8IG1heWJlTWluQnVmZmVyTGVuZ3RoKSB7CiAgICAgICAgdGhpcy5taW5CdWZmZXJMZW5ndGggKj0gMjsKICAgICAgfQogICAgfQogIH0KICBnZXQgaXNFbXB0eSgpIHsKICAgIHdoaWxlICghdGhpcy5lb2YgJiYgdGhpcy5idWZmZXJMZW5ndGggPT09IDApIHsKICAgICAgdGhpcy5yZWFkQmxvY2soKTsKICAgIH0KICAgIHJldHVybiB0aGlzLmJ1ZmZlckxlbmd0aCA9PT0gMDsKICB9CiAgZW5zdXJlQnVmZmVyKHJlcXVlc3RlZCkgewogICAgY29uc3QgYnVmZmVyID0gdGhpcy5idWZmZXI7CiAgICBpZiAocmVxdWVzdGVkIDw9IGJ1ZmZlci5ieXRlTGVuZ3RoKSB7CiAgICAgIHJldHVybiBidWZmZXI7CiAgICB9CiAgICBsZXQgc2l6ZSA9IHRoaXMubWluQnVmZmVyTGVuZ3RoOwogICAgd2hpbGUgKHNpemUgPCByZXF1ZXN0ZWQpIHsKICAgICAgc2l6ZSAqPSAyOwogICAgfQogICAgY29uc3QgYnVmZmVyMiA9IG5ldyBVaW50OEFycmF5KHNpemUpOwogICAgYnVmZmVyMi5zZXQoYnVmZmVyKTsKICAgIHJldHVybiB0aGlzLmJ1ZmZlciA9IGJ1ZmZlcjI7CiAgfQogIGdldEJ5dGUoKSB7CiAgICBjb25zdCBwb3MgPSB0aGlzLnBvczsKICAgIHdoaWxlICh0aGlzLmJ1ZmZlckxlbmd0aCA8PSBwb3MpIHsKICAgICAgaWYgKHRoaXMuZW9mKSB7CiAgICAgICAgcmV0dXJuIC0xOwogICAgICB9CiAgICAgIHRoaXMucmVhZEJsb2NrKCk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5idWZmZXJbdGhpcy5wb3MrK107CiAgfQogIGdldEJ5dGVzKGxlbmd0aCwgZGVjb2Rlck9wdGlvbnMgPSBudWxsKSB7CiAgICBjb25zdCBwb3MgPSB0aGlzLnBvczsKICAgIGxldCBlbmQ7CiAgICBpZiAobGVuZ3RoKSB7CiAgICAgIHRoaXMuZW5zdXJlQnVmZmVyKHBvcyArIGxlbmd0aCk7CiAgICAgIGVuZCA9IHBvcyArIGxlbmd0aDsKICAgICAgd2hpbGUgKCF0aGlzLmVvZiAmJiB0aGlzLmJ1ZmZlckxlbmd0aCA8IGVuZCkgewogICAgICAgIHRoaXMucmVhZEJsb2NrKGRlY29kZXJPcHRpb25zKTsKICAgICAgfQogICAgICBjb25zdCBidWZFbmQgPSB0aGlzLmJ1ZmZlckxlbmd0aDsKICAgICAgaWYgKGVuZCA+IGJ1ZkVuZCkgewogICAgICAgIGVuZCA9IGJ1ZkVuZDsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgd2hpbGUgKCF0aGlzLmVvZikgewogICAgICAgIHRoaXMucmVhZEJsb2NrKGRlY29kZXJPcHRpb25zKTsKICAgICAgfQogICAgICBlbmQgPSB0aGlzLmJ1ZmZlckxlbmd0aDsKICAgIH0KICAgIHRoaXMucG9zID0gZW5kOwogICAgcmV0dXJuIHRoaXMuYnVmZmVyLnN1YmFycmF5KHBvcywgZW5kKTsKICB9CiAgYXN5bmMgZ2V0SW1hZ2VEYXRhKGxlbmd0aCwgZGVjb2Rlck9wdGlvbnMpIHsKICAgIGlmICghdGhpcy5jYW5Bc3luY0RlY29kZUltYWdlRnJvbUJ1ZmZlcikgewogICAgICBpZiAodGhpcy5pc0FzeW5jRGVjb2RlcikgewogICAgICAgIHJldHVybiB0aGlzLmRlY29kZUltYWdlKG51bGwsIGRlY29kZXJPcHRpb25zKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5nZXRCeXRlcyhsZW5ndGgsIGRlY29kZXJPcHRpb25zKTsKICAgIH0KICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLnN0cmVhbS5hc3luY0dldEJ5dGVzKCk7CiAgICByZXR1cm4gdGhpcy5kZWNvZGVJbWFnZShkYXRhLCBkZWNvZGVyT3B0aW9ucyk7CiAgfQogIHJlc2V0KCkgewogICAgdGhpcy5wb3MgPSAwOwogIH0KICBtYWtlU3ViU3RyZWFtKHN0YXJ0LCBsZW5ndGgsIGRpY3QgPSBudWxsKSB7CiAgICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQpIHsKICAgICAgd2hpbGUgKCF0aGlzLmVvZikgewogICAgICAgIHRoaXMucmVhZEJsb2NrKCk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGVuZCA9IHN0YXJ0ICsgbGVuZ3RoOwogICAgICB3aGlsZSAodGhpcy5idWZmZXJMZW5ndGggPD0gZW5kICYmICF0aGlzLmVvZikgewogICAgICAgIHRoaXMucmVhZEJsb2NrKCk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBuZXcgU3RyZWFtKHRoaXMuYnVmZmVyLCBzdGFydCwgbGVuZ3RoLCBkaWN0KTsKICB9CiAgZ2V0QmFzZVN0cmVhbXMoKSB7CiAgICByZXR1cm4gdGhpcy5zdHJlYW0gPyB0aGlzLnN0cmVhbS5nZXRCYXNlU3RyZWFtcygpIDogbnVsbDsKICB9CiAgY2xvbmUoKSB7CiAgICB3aGlsZSAoIXRoaXMuZW9mKSB7CiAgICAgIHRoaXMucmVhZEJsb2NrKCk7CiAgICB9CiAgICByZXR1cm4gbmV3IFN0cmVhbSh0aGlzLmJ1ZmZlciwgdGhpcy5zdGFydCwgdGhpcy5lbmQgLSB0aGlzLnN0YXJ0LCB0aGlzLmRpY3QuY2xvbmUoKSk7CiAgfQp9CmNsYXNzIFN0cmVhbXNTZXF1ZW5jZVN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyZWFtcywgb25FcnJvciA9IG51bGwpIHsKICAgIHN0cmVhbXMgPSBzdHJlYW1zLmZpbHRlcihzID0+IHMgaW5zdGFuY2VvZiBCYXNlU3RyZWFtICYmICFzLmlzSW1hZ2VTdHJlYW0pOwogICAgbGV0IG1heWJlTGVuZ3RoID0gMDsKICAgIGZvciAoY29uc3Qgc3RyZWFtIG9mIHN0cmVhbXMpIHsKICAgICAgbWF5YmVMZW5ndGggKz0gc3RyZWFtIGluc3RhbmNlb2YgRGVjb2RlU3RyZWFtID8gc3RyZWFtLl9yYXdNaW5CdWZmZXJMZW5ndGggOiBzdHJlYW0ubGVuZ3RoOwogICAgfQogICAgc3VwZXIobWF5YmVMZW5ndGgpOwogICAgdGhpcy5zdHJlYW1zID0gc3RyZWFtczsKICAgIHRoaXMuX29uRXJyb3IgPSBvbkVycm9yOwogIH0KICByZWFkQmxvY2soKSB7CiAgICBjb25zdCBzdHJlYW1zID0gdGhpcy5zdHJlYW1zOwogICAgaWYgKHN0cmVhbXMubGVuZ3RoID09PSAwKSB7CiAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgc3RyZWFtID0gc3RyZWFtcy5zaGlmdCgpOwogICAgbGV0IGNodW5rOwogICAgdHJ5IHsKICAgICAgY2h1bmsgPSBzdHJlYW0uZ2V0Qnl0ZXMoKTsKICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICBpZiAodGhpcy5fb25FcnJvcikgewogICAgICAgIHRoaXMuX29uRXJyb3IocmVhc29uLCBzdHJlYW0uZGljdD8ub2JqSWQpOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICB0aHJvdyByZWFzb247CiAgICB9CiAgICBjb25zdCBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlckxlbmd0aDsKICAgIGNvbnN0IG5ld0xlbmd0aCA9IGJ1ZmZlckxlbmd0aCArIGNodW5rLmxlbmd0aDsKICAgIGNvbnN0IGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKG5ld0xlbmd0aCk7CiAgICBidWZmZXIuc2V0KGNodW5rLCBidWZmZXJMZW5ndGgpOwogICAgdGhpcy5idWZmZXJMZW5ndGggPSBuZXdMZW5ndGg7CiAgfQogIGdldEJhc2VTdHJlYW1zKCkgewogICAgY29uc3QgYmFzZVN0cmVhbXNCdWYgPSBbXTsKICAgIGZvciAoY29uc3Qgc3RyZWFtIG9mIHRoaXMuc3RyZWFtcykgewogICAgICBjb25zdCBiYXNlU3RyZWFtcyA9IHN0cmVhbS5nZXRCYXNlU3RyZWFtcygpOwogICAgICBpZiAoYmFzZVN0cmVhbXMpIHsKICAgICAgICBiYXNlU3RyZWFtc0J1Zi5wdXNoKC4uLmJhc2VTdHJlYW1zKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGJhc2VTdHJlYW1zQnVmLmxlbmd0aCA+IDAgPyBiYXNlU3RyZWFtc0J1ZiA6IG51bGw7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9jb2xvcnNwYWNlX3V0aWxzLmpzCgoKCgoKY2xhc3MgQ29sb3JTcGFjZVV0aWxzIHsKICBzdGF0aWMgcGFyc2UoewogICAgY3MsCiAgICB4cmVmLAogICAgcmVzb3VyY2VzID0gbnVsbCwKICAgIHBkZkZ1bmN0aW9uRmFjdG9yeSwKICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlLAogICAgYXN5bmNJZk5vdENhY2hlZCA9IGZhbHNlCiAgfSkgewogICAgY29uc3Qgb3B0aW9ucyA9IHsKICAgICAgeHJlZiwKICAgICAgcmVzb3VyY2VzLAogICAgICBwZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgIH07CiAgICBsZXQgY3NOYW1lLCBjc1JlZiwgcGFyc2VkQ1M7CiAgICBpZiAoY3MgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgY3NSZWYgPSBjczsKICAgICAgY29uc3QgY2FjaGVkQ1MgPSBnbG9iYWxDb2xvclNwYWNlQ2FjaGUuZ2V0QnlSZWYoY3NSZWYpIHx8IGxvY2FsQ29sb3JTcGFjZUNhY2hlLmdldEJ5UmVmKGNzUmVmKTsKICAgICAgaWYgKGNhY2hlZENTKSB7CiAgICAgICAgcmV0dXJuIGNhY2hlZENTOwogICAgICB9CiAgICAgIGNzID0geHJlZi5mZXRjaChjcyk7CiAgICB9CiAgICBpZiAoY3MgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgIGNzTmFtZSA9IGNzLm5hbWU7CiAgICAgIGNvbnN0IGNhY2hlZENTID0gbG9jYWxDb2xvclNwYWNlQ2FjaGUuZ2V0QnlOYW1lKGNzTmFtZSk7CiAgICAgIGlmIChjYWNoZWRDUykgewogICAgICAgIHJldHVybiBjYWNoZWRDUzsKICAgICAgfQogICAgfQogICAgdHJ5IHsKICAgICAgcGFyc2VkQ1MgPSB0aGlzLiNwYXJzZShjcywgb3B0aW9ucyk7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoYXN5bmNJZk5vdENhY2hlZCAmJiAhKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGV4KTsKICAgICAgfQogICAgICB0aHJvdyBleDsKICAgIH0KICAgIGlmIChjc05hbWUgfHwgY3NSZWYpIHsKICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUuc2V0KGNzTmFtZSwgY3NSZWYsIHBhcnNlZENTKTsKICAgICAgaWYgKGNzUmVmKSB7CiAgICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLnNldChudWxsLCBjc1JlZiwgcGFyc2VkQ1MpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gYXN5bmNJZk5vdENhY2hlZCA/IFByb21pc2UucmVzb2x2ZShwYXJzZWRDUykgOiBwYXJzZWRDUzsKICB9CiAgc3RhdGljICNzdWJQYXJzZShjcywgb3B0aW9ucykgewogICAgY29uc3QgewogICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGUKICAgIH0gPSBvcHRpb25zOwogICAgbGV0IGNzUmVmOwogICAgaWYgKGNzIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgIGNzUmVmID0gY3M7CiAgICAgIGNvbnN0IGNhY2hlZENTID0gZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLmdldEJ5UmVmKGNzUmVmKTsKICAgICAgaWYgKGNhY2hlZENTKSB7CiAgICAgICAgcmV0dXJuIGNhY2hlZENTOwogICAgICB9CiAgICB9CiAgICBjb25zdCBwYXJzZWRDUyA9IHRoaXMuI3BhcnNlKGNzLCBvcHRpb25zKTsKICAgIGlmIChjc1JlZikgewogICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGUuc2V0KG51bGwsIGNzUmVmLCBwYXJzZWRDUyk7CiAgICB9CiAgICByZXR1cm4gcGFyc2VkQ1M7CiAgfQogIHN0YXRpYyAjcGFyc2UoY3MsIG9wdGlvbnMpIHsKICAgIGNvbnN0IHsKICAgICAgeHJlZiwKICAgICAgcmVzb3VyY2VzLAogICAgICBwZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZQogICAgfSA9IG9wdGlvbnM7CiAgICBjcyA9IHhyZWYuZmV0Y2hJZlJlZihjcyk7CiAgICBpZiAoY3MgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgIHN3aXRjaCAoY3MubmFtZSkgewogICAgICAgIGNhc2UgIkciOgogICAgICAgIGNhc2UgIkRldmljZUdyYXkiOgogICAgICAgICAgcmV0dXJuIHRoaXMuZ3JheTsKICAgICAgICBjYXNlICJSR0IiOgogICAgICAgIGNhc2UgIkRldmljZVJHQiI6CiAgICAgICAgICByZXR1cm4gdGhpcy5yZ2I7CiAgICAgICAgY2FzZSAiRGV2aWNlUkdCQSI6CiAgICAgICAgICByZXR1cm4gdGhpcy5yZ2JhOwogICAgICAgIGNhc2UgIkNNWUsiOgogICAgICAgIGNhc2UgIkRldmljZUNNWUsiOgogICAgICAgICAgcmV0dXJuIHRoaXMuY215azsKICAgICAgICBjYXNlICJQYXR0ZXJuIjoKICAgICAgICAgIHJldHVybiBuZXcgUGF0dGVybkNTKG51bGwpOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBpZiAocmVzb3VyY2VzIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgICAgICBjb25zdCBjb2xvclNwYWNlcyA9IHJlc291cmNlcy5nZXQoIkNvbG9yU3BhY2UiKTsKICAgICAgICAgICAgaWYgKGNvbG9yU3BhY2VzIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgICAgICAgIGNvbnN0IHJlc291cmNlc0NTID0gY29sb3JTcGFjZXMuZ2V0KGNzLm5hbWUpOwogICAgICAgICAgICAgIGlmIChyZXNvdXJjZXNDUykgewogICAgICAgICAgICAgICAgaWYgKHJlc291cmNlc0NTIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy4jcGFyc2UocmVzb3VyY2VzQ1MsIG9wdGlvbnMpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY3MgPSByZXNvdXJjZXNDUzsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgd2FybihgVW5yZWNvZ25pemVkIENvbG9yU3BhY2U6ICR7Y3MubmFtZX1gKTsKICAgICAgICAgIHJldHVybiB0aGlzLmdyYXk7CiAgICAgIH0KICAgIH0KICAgIGlmIChBcnJheS5pc0FycmF5KGNzKSkgewogICAgICBjb25zdCBtb2RlID0geHJlZi5mZXRjaElmUmVmKGNzWzBdKS5uYW1lOwogICAgICBsZXQgcGFyYW1zLCBudW1Db21wcywgYmFzZUNTLCB3aGl0ZVBvaW50LCBibGFja1BvaW50LCBnYW1tYTsKICAgICAgc3dpdGNoIChtb2RlKSB7CiAgICAgICAgY2FzZSAiRyI6CiAgICAgICAgY2FzZSAiRGV2aWNlR3JheSI6CiAgICAgICAgICByZXR1cm4gdGhpcy5ncmF5OwogICAgICAgIGNhc2UgIlJHQiI6CiAgICAgICAgY2FzZSAiRGV2aWNlUkdCIjoKICAgICAgICAgIHJldHVybiB0aGlzLnJnYjsKICAgICAgICBjYXNlICJDTVlLIjoKICAgICAgICBjYXNlICJEZXZpY2VDTVlLIjoKICAgICAgICAgIHJldHVybiB0aGlzLmNteWs7CiAgICAgICAgY2FzZSAiQ2FsR3JheSI6CiAgICAgICAgICBwYXJhbXMgPSB4cmVmLmZldGNoSWZSZWYoY3NbMV0pOwogICAgICAgICAgd2hpdGVQb2ludCA9IHBhcmFtcy5nZXRBcnJheSgiV2hpdGVQb2ludCIpOwogICAgICAgICAgYmxhY2tQb2ludCA9IHBhcmFtcy5nZXRBcnJheSgiQmxhY2tQb2ludCIpOwogICAgICAgICAgZ2FtbWEgPSBwYXJhbXMuZ2V0KCJHYW1tYSIpOwogICAgICAgICAgcmV0dXJuIG5ldyBDYWxHcmF5Q1Mod2hpdGVQb2ludCwgYmxhY2tQb2ludCwgZ2FtbWEpOwogICAgICAgIGNhc2UgIkNhbFJHQiI6CiAgICAgICAgICBwYXJhbXMgPSB4cmVmLmZldGNoSWZSZWYoY3NbMV0pOwogICAgICAgICAgd2hpdGVQb2ludCA9IHBhcmFtcy5nZXRBcnJheSgiV2hpdGVQb2ludCIpOwogICAgICAgICAgYmxhY2tQb2ludCA9IHBhcmFtcy5nZXRBcnJheSgiQmxhY2tQb2ludCIpOwogICAgICAgICAgZ2FtbWEgPSBwYXJhbXMuZ2V0QXJyYXkoIkdhbW1hIik7CiAgICAgICAgICBjb25zdCBtYXRyaXggPSBwYXJhbXMuZ2V0QXJyYXkoIk1hdHJpeCIpOwogICAgICAgICAgcmV0dXJuIG5ldyBDYWxSR0JDUyh3aGl0ZVBvaW50LCBibGFja1BvaW50LCBnYW1tYSwgbWF0cml4KTsKICAgICAgICBjYXNlICJJQ0NCYXNlZCI6CiAgICAgICAgICBjb25zdCBpc1JlZiA9IGNzWzFdIGluc3RhbmNlb2YgUmVmOwogICAgICAgICAgaWYgKGlzUmVmKSB7CiAgICAgICAgICAgIGNvbnN0IGNhY2hlZENTID0gZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLmdldEJ5UmVmKGNzWzFdKTsKICAgICAgICAgICAgaWYgKGNhY2hlZENTKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENTOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBzdHJlYW0gPSB4cmVmLmZldGNoSWZSZWYoY3NbMV0pOwogICAgICAgICAgY29uc3QgZGljdCA9IHN0cmVhbS5kaWN0OwogICAgICAgICAgbnVtQ29tcHMgPSBkaWN0LmdldCgiTiIpOwogICAgICAgICAgaWYgKEljY0NvbG9yU3BhY2UuaXNVc2FibGUpIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBjb25zdCBpY2NDUyA9IG5ldyBJY2NDb2xvclNwYWNlKHN0cmVhbS5nZXRCeXRlcygpLCAiSUNDQmFzZWQiLCBudW1Db21wcyk7CiAgICAgICAgICAgICAgaWYgKGlzUmVmKSB7CiAgICAgICAgICAgICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGUuc2V0KG51bGwsIGNzWzFdLCBpY2NDUyk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiBpY2NDUzsKICAgICAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgICAgICAgICAgdGhyb3cgZXg7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHdhcm4oYElDQ0Jhc2VkIGNvbG9yIHNwYWNlICgke2NzWzFdfSk6ICIke2V4fSIuYCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGFsdFJhdyA9IGRpY3QuZ2V0UmF3KCJBbHRlcm5hdGUiKTsKICAgICAgICAgIGlmIChhbHRSYXcpIHsKICAgICAgICAgICAgY29uc3QgYWx0Q1MgPSB0aGlzLiNzdWJQYXJzZShhbHRSYXcsIG9wdGlvbnMpOwogICAgICAgICAgICBpZiAoYWx0Q1MubnVtQ29tcHMgPT09IG51bUNvbXBzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGFsdENTOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHdhcm4oIklDQ0Jhc2VkIGNvbG9yIHNwYWNlOiBJZ25vcmluZyBpbmNvcnJlY3QgL0FsdGVybmF0ZSBlbnRyeS4iKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChudW1Db21wcyA9PT0gMSkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5ncmF5OwogICAgICAgICAgfSBlbHNlIGlmIChudW1Db21wcyA9PT0gMykgewogICAgICAgICAgICByZXR1cm4gdGhpcy5yZ2I7CiAgICAgICAgICB9IGVsc2UgaWYgKG51bUNvbXBzID09PSA0KSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmNteWs7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJQYXR0ZXJuIjoKICAgICAgICAgIGJhc2VDUyA9IGNzWzFdIHx8IG51bGw7CiAgICAgICAgICBpZiAoYmFzZUNTKSB7CiAgICAgICAgICAgIGJhc2VDUyA9IHRoaXMuI3N1YlBhcnNlKGJhc2VDUywgb3B0aW9ucyk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gbmV3IFBhdHRlcm5DUyhiYXNlQ1MpOwogICAgICAgIGNhc2UgIkkiOgogICAgICAgIGNhc2UgIkluZGV4ZWQiOgogICAgICAgICAgYmFzZUNTID0gdGhpcy4jc3ViUGFyc2UoY3NbMV0sIG9wdGlvbnMpOwogICAgICAgICAgY29uc3QgaGlWYWwgPSBNYXRoQ2xhbXAoeHJlZi5mZXRjaElmUmVmKGNzWzJdKSwgMCwgMjU1KTsKICAgICAgICAgIGNvbnN0IGxvb2t1cCA9IHhyZWYuZmV0Y2hJZlJlZihjc1szXSk7CiAgICAgICAgICByZXR1cm4gbmV3IEluZGV4ZWRDUyhiYXNlQ1MsIGhpVmFsLCBsb29rdXApOwogICAgICAgIGNhc2UgIlNlcGFyYXRpb24iOgogICAgICAgIGNhc2UgIkRldmljZU4iOgogICAgICAgICAgY29uc3QgbmFtZSA9IHhyZWYuZmV0Y2hJZlJlZihjc1sxXSk7CiAgICAgICAgICBudW1Db21wcyA9IEFycmF5LmlzQXJyYXkobmFtZSkgPyBuYW1lLmxlbmd0aCA6IDE7CiAgICAgICAgICBiYXNlQ1MgPSB0aGlzLiNzdWJQYXJzZShjc1syXSwgb3B0aW9ucyk7CiAgICAgICAgICBjb25zdCB0aW50Rm4gPSBwZGZGdW5jdGlvbkZhY3RvcnkuY3JlYXRlKGNzWzNdKTsKICAgICAgICAgIHJldHVybiBuZXcgQWx0ZXJuYXRlQ1MobnVtQ29tcHMsIGJhc2VDUywgdGludEZuKTsKICAgICAgICBjYXNlICJMYWIiOgogICAgICAgICAgcGFyYW1zID0geHJlZi5mZXRjaElmUmVmKGNzWzFdKTsKICAgICAgICAgIHdoaXRlUG9pbnQgPSBwYXJhbXMuZ2V0QXJyYXkoIldoaXRlUG9pbnQiKTsKICAgICAgICAgIGJsYWNrUG9pbnQgPSBwYXJhbXMuZ2V0QXJyYXkoIkJsYWNrUG9pbnQiKTsKICAgICAgICAgIGNvbnN0IHJhbmdlID0gcGFyYW1zLmdldEFycmF5KCJSYW5nZSIpOwogICAgICAgICAgcmV0dXJuIG5ldyBMYWJDUyh3aGl0ZVBvaW50LCBibGFja1BvaW50LCByYW5nZSk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHdhcm4oYFVuaW1wbGVtZW50ZWQgQ29sb3JTcGFjZSBvYmplY3Q6ICR7bW9kZX1gKTsKICAgICAgICAgIHJldHVybiB0aGlzLmdyYXk7CiAgICAgIH0KICAgIH0KICAgIHdhcm4oYFVucmVjb2duaXplZCBDb2xvclNwYWNlIG9iamVjdDogJHtjc31gKTsKICAgIHJldHVybiB0aGlzLmdyYXk7CiAgfQogIHN0YXRpYyBnZXQgZ3JheSgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgImdyYXkiLCBuZXcgRGV2aWNlR3JheUNTKCkpOwogIH0KICBzdGF0aWMgZ2V0IHJnYigpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgInJnYiIsIG5ldyBEZXZpY2VSZ2JDUygpKTsKICB9CiAgc3RhdGljIGdldCByZ2JhKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAicmdiYSIsIG5ldyBEZXZpY2VSZ2JhQ1MoKSk7CiAgfQogIHN0YXRpYyBnZXQgY215aygpIHsKICAgIGlmIChDbXlrSUNDQmFzZWRDUy5pc1VzYWJsZSkgewogICAgICB0cnkgewogICAgICAgIHJldHVybiBzaGFkb3codGhpcywgImNteWsiLCBuZXcgQ215a0lDQ0Jhc2VkQ1MoKSk7CiAgICAgIH0gY2F0Y2ggewogICAgICAgIHdhcm4oIkNNWUsgZmFsbGJhY2s6IERldmljZUNNWUsiKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiY215ayIsIG5ldyBEZXZpY2VDbXlrQ1MoKSk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9qcGcuanMKCgoKCgpjbGFzcyBKcGVnRXJyb3IgZXh0ZW5kcyBCYXNlRXhjZXB0aW9uIHsKICBjb25zdHJ1Y3Rvcihtc2cpIHsKICAgIHN1cGVyKG1zZywgIkpwZWdFcnJvciIpOwogIH0KfQpjbGFzcyBETkxNYXJrZXJFcnJvciBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1lc3NhZ2UsIHNjYW5MaW5lcykgewogICAgc3VwZXIobWVzc2FnZSwgIkROTE1hcmtlckVycm9yIik7CiAgICB0aGlzLnNjYW5MaW5lcyA9IHNjYW5MaW5lczsKICB9Cn0KY2xhc3MgRU9JTWFya2VyRXJyb3IgZXh0ZW5kcyBCYXNlRXhjZXB0aW9uIHsKICBjb25zdHJ1Y3Rvcihtc2cpIHsKICAgIHN1cGVyKG1zZywgIkVPSU1hcmtlckVycm9yIik7CiAgfQp9CmNvbnN0IGRjdFppZ1phZyA9IG5ldyBVaW50OEFycmF5KFswLCAxLCA4LCAxNiwgOSwgMiwgMywgMTAsIDE3LCAyNCwgMzIsIDI1LCAxOCwgMTEsIDQsIDUsIDEyLCAxOSwgMjYsIDMzLCA0MCwgNDgsIDQxLCAzNCwgMjcsIDIwLCAxMywgNiwgNywgMTQsIDIxLCAyOCwgMzUsIDQyLCA0OSwgNTYsIDU3LCA1MCwgNDMsIDM2LCAyOSwgMjIsIDE1LCAyMywgMzAsIDM3LCA0NCwgNTEsIDU4LCA1OSwgNTIsIDQ1LCAzOCwgMzEsIDM5LCA0NiwgNTMsIDYwLCA2MSwgNTQsIDQ3LCA1NSwgNjIsIDYzXSk7CmNvbnN0IGRjdENvczEgPSA0MDE3Owpjb25zdCBkY3RTaW4xID0gNzk5Owpjb25zdCBkY3RDb3MzID0gMzQwNjsKY29uc3QgZGN0U2luMyA9IDIyNzY7CmNvbnN0IGRjdENvczYgPSAxNTY3Owpjb25zdCBkY3RTaW42ID0gMzc4NDsKY29uc3QgZGN0U3FydDIgPSA1NzkzOwpjb25zdCBkY3RTcXJ0MWQyID0gMjg5NjsKZnVuY3Rpb24gYnVpbGRIdWZmbWFuVGFibGUoY29kZUxlbmd0aHMsIHZhbHVlcykgewogIGxldCBrID0gMCwKICAgIGksCiAgICBqLAogICAgbGVuZ3RoID0gMTY7CiAgd2hpbGUgKGxlbmd0aCA+IDAgJiYgIWNvZGVMZW5ndGhzW2xlbmd0aCAtIDFdKSB7CiAgICBsZW5ndGgtLTsKICB9CiAgY29uc3QgY29kZSA9IFt7CiAgICBjaGlsZHJlbjogW10sCiAgICBpbmRleDogMAogIH1dOwogIGxldCBwID0gY29kZVswXSwKICAgIHE7CiAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICBmb3IgKGogPSAwOyBqIDwgY29kZUxlbmd0aHNbaV07IGorKykgewogICAgICBwID0gY29kZS5wb3AoKTsKICAgICAgcC5jaGlsZHJlbltwLmluZGV4XSA9IHZhbHVlc1trXTsKICAgICAgd2hpbGUgKHAuaW5kZXggPiAwKSB7CiAgICAgICAgcCA9IGNvZGUucG9wKCk7CiAgICAgIH0KICAgICAgcC5pbmRleCsrOwogICAgICBjb2RlLnB1c2gocCk7CiAgICAgIHdoaWxlIChjb2RlLmxlbmd0aCA8PSBpKSB7CiAgICAgICAgY29kZS5wdXNoKHEgPSB7CiAgICAgICAgICBjaGlsZHJlbjogW10sCiAgICAgICAgICBpbmRleDogMAogICAgICAgIH0pOwogICAgICAgIHAuY2hpbGRyZW5bcC5pbmRleF0gPSBxLmNoaWxkcmVuOwogICAgICAgIHAgPSBxOwogICAgICB9CiAgICAgIGsrKzsKICAgIH0KICAgIGlmIChpICsgMSA8IGxlbmd0aCkgewogICAgICBjb2RlLnB1c2gocSA9IHsKICAgICAgICBjaGlsZHJlbjogW10sCiAgICAgICAgaW5kZXg6IDAKICAgICAgfSk7CiAgICAgIHAuY2hpbGRyZW5bcC5pbmRleF0gPSBxLmNoaWxkcmVuOwogICAgICBwID0gcTsKICAgIH0KICB9CiAgcmV0dXJuIGNvZGVbMF0uY2hpbGRyZW47Cn0KZnVuY3Rpb24gZ2V0QmxvY2tCdWZmZXJPZmZzZXQoY29tcG9uZW50LCByb3csIGNvbCkgewogIHJldHVybiA2NCAqICgoY29tcG9uZW50LmJsb2Nrc1BlckxpbmUgKyAxKSAqIHJvdyArIGNvbCk7Cn0KZnVuY3Rpb24gZGVjb2RlU2NhbihkYXRhLCBvZmZzZXQsIGZyYW1lLCBjb21wb25lbnRzLCByZXNldEludGVydmFsLCBzcGVjdHJhbFN0YXJ0LCBzcGVjdHJhbEVuZCwgc3VjY2Vzc2l2ZVByZXYsIHN1Y2Nlc3NpdmUsIHBhcnNlRE5MTWFya2VyID0gZmFsc2UpIHsKICBjb25zdCBtY3VzUGVyTGluZSA9IGZyYW1lLm1jdXNQZXJMaW5lOwogIGNvbnN0IHByb2dyZXNzaXZlID0gZnJhbWUucHJvZ3Jlc3NpdmU7CiAgY29uc3Qgc3RhcnRPZmZzZXQgPSBvZmZzZXQ7CiAgbGV0IGJpdHNEYXRhID0gMCwKICAgIGJpdHNDb3VudCA9IDA7CiAgZnVuY3Rpb24gcmVhZEJpdCgpIHsKICAgIGlmIChiaXRzQ291bnQgPiAwKSB7CiAgICAgIGJpdHNDb3VudC0tOwogICAgICByZXR1cm4gYml0c0RhdGEgPj4gYml0c0NvdW50ICYgMTsKICAgIH0KICAgIGJpdHNEYXRhID0gZGF0YVtvZmZzZXQrK107CiAgICBpZiAoYml0c0RhdGEgPT09IDB4ZmYpIHsKICAgICAgY29uc3QgbmV4dEJ5dGUgPSBkYXRhW29mZnNldCsrXTsKICAgICAgaWYgKG5leHRCeXRlKSB7CiAgICAgICAgaWYgKG5leHRCeXRlID09PSAweGRjICYmIHBhcnNlRE5MTWFya2VyKSB7CiAgICAgICAgICBvZmZzZXQgKz0gMjsKICAgICAgICAgIGNvbnN0IHNjYW5MaW5lcyA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgaWYgKHNjYW5MaW5lcyA+IDAgJiYgc2NhbkxpbmVzICE9PSBmcmFtZS5zY2FuTGluZXMpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEROTE1hcmtlckVycm9yKCJGb3VuZCBETkwgbWFya2VyICgweEZGREMpIHdoaWxlIHBhcnNpbmcgc2NhbiBkYXRhIiwgc2NhbkxpbmVzKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKG5leHRCeXRlID09PSAweGQ5KSB7CiAgICAgICAgICBpZiAocGFyc2VETkxNYXJrZXIpIHsKICAgICAgICAgICAgY29uc3QgbWF5YmVTY2FuTGluZXMgPSBibG9ja1JvdyAqIChmcmFtZS5wcmVjaXNpb24gPT09IDggPyA4IDogMCk7CiAgICAgICAgICAgIGlmIChtYXliZVNjYW5MaW5lcyA+IDAgJiYgTWF0aC5yb3VuZChmcmFtZS5zY2FuTGluZXMgLyBtYXliZVNjYW5MaW5lcykgPj0gNSkgewogICAgICAgICAgICAgIHRocm93IG5ldyBETkxNYXJrZXJFcnJvcigiRm91bmQgRU9JIG1hcmtlciAoMHhGRkQ5KSB3aGlsZSBwYXJzaW5nIHNjYW4gZGF0YSwgIiArICJwb3NzaWJseSBjYXVzZWQgYnkgaW5jb3JyZWN0IGBzY2FuTGluZXNgIHBhcmFtZXRlciIsIG1heWJlU2NhbkxpbmVzKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgdGhyb3cgbmV3IEVPSU1hcmtlckVycm9yKCJGb3VuZCBFT0kgbWFya2VyICgweEZGRDkpIHdoaWxlIHBhcnNpbmcgc2NhbiBkYXRhIik7CiAgICAgICAgfQogICAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoYHVuZXhwZWN0ZWQgbWFya2VyICR7KGJpdHNEYXRhIDw8IDggfCBuZXh0Qnl0ZSkudG9TdHJpbmcoMTYpfWApOwogICAgICB9CiAgICB9CiAgICBiaXRzQ291bnQgPSA3OwogICAgcmV0dXJuIGJpdHNEYXRhID4+PiA3OwogIH0KICBmdW5jdGlvbiBkZWNvZGVIdWZmbWFuKHRyZWUpIHsKICAgIGxldCBub2RlID0gdHJlZTsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIG5vZGUgPSBub2RlW3JlYWRCaXQoKV07CiAgICAgIHN3aXRjaCAodHlwZW9mIG5vZGUpIHsKICAgICAgICBjYXNlICJudW1iZXIiOgogICAgICAgICAgcmV0dXJuIG5vZGU7CiAgICAgICAgY2FzZSAib2JqZWN0IjoKICAgICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoImludmFsaWQgaHVmZm1hbiBzZXF1ZW5jZSIpOwogICAgfQogIH0KICBmdW5jdGlvbiByZWNlaXZlKGxlbmd0aCkgewogICAgbGV0IG4gPSAwOwogICAgd2hpbGUgKGxlbmd0aCA+IDApIHsKICAgICAgbiA9IG4gPDwgMSB8IHJlYWRCaXQoKTsKICAgICAgbGVuZ3RoLS07CiAgICB9CiAgICByZXR1cm4gbjsKICB9CiAgZnVuY3Rpb24gcmVjZWl2ZUFuZEV4dGVuZChsZW5ndGgpIHsKICAgIGlmIChsZW5ndGggPT09IDEpIHsKICAgICAgcmV0dXJuIHJlYWRCaXQoKSA9PT0gMSA/IDEgOiAtMTsKICAgIH0KICAgIGNvbnN0IG4gPSByZWNlaXZlKGxlbmd0aCk7CiAgICBpZiAobiA+PSAxIDw8IGxlbmd0aCAtIDEpIHsKICAgICAgcmV0dXJuIG47CiAgICB9CiAgICByZXR1cm4gbiArICgtMSA8PCBsZW5ndGgpICsgMTsKICB9CiAgZnVuY3Rpb24gZGVjb2RlQmFzZWxpbmUoY29tcG9uZW50LCBibG9ja09mZnNldCkgewogICAgY29uc3QgdCA9IGRlY29kZUh1ZmZtYW4oY29tcG9uZW50Lmh1ZmZtYW5UYWJsZURDKTsKICAgIGNvbnN0IGRpZmYgPSB0ID09PSAwID8gMCA6IHJlY2VpdmVBbmRFeHRlbmQodCk7CiAgICBjb21wb25lbnQuYmxvY2tEYXRhW2Jsb2NrT2Zmc2V0XSA9IGNvbXBvbmVudC5wcmVkICs9IGRpZmY7CiAgICBsZXQgayA9IDE7CiAgICB3aGlsZSAoayA8IDY0KSB7CiAgICAgIGNvbnN0IHJzID0gZGVjb2RlSHVmZm1hbihjb21wb25lbnQuaHVmZm1hblRhYmxlQUMpOwogICAgICBjb25zdCBzID0gcnMgJiAxNSwKICAgICAgICByID0gcnMgPj4gNDsKICAgICAgaWYgKHMgPT09IDApIHsKICAgICAgICBpZiAociA8IDE1KSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgayArPSAxNjsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBrICs9IHI7CiAgICAgIGNvbnN0IHogPSBkY3RaaWdaYWdba107CiAgICAgIGNvbXBvbmVudC5ibG9ja0RhdGFbYmxvY2tPZmZzZXQgKyB6XSA9IHJlY2VpdmVBbmRFeHRlbmQocyk7CiAgICAgIGsrKzsKICAgIH0KICB9CiAgZnVuY3Rpb24gZGVjb2RlRENGaXJzdChjb21wb25lbnQsIGJsb2NrT2Zmc2V0KSB7CiAgICBjb25zdCB0ID0gZGVjb2RlSHVmZm1hbihjb21wb25lbnQuaHVmZm1hblRhYmxlREMpOwogICAgY29uc3QgZGlmZiA9IHQgPT09IDAgPyAwIDogcmVjZWl2ZUFuZEV4dGVuZCh0KSA8PCBzdWNjZXNzaXZlOwogICAgY29tcG9uZW50LmJsb2NrRGF0YVtibG9ja09mZnNldF0gPSBjb21wb25lbnQucHJlZCArPSBkaWZmOwogIH0KICBmdW5jdGlvbiBkZWNvZGVEQ1N1Y2Nlc3NpdmUoY29tcG9uZW50LCBibG9ja09mZnNldCkgewogICAgY29tcG9uZW50LmJsb2NrRGF0YVtibG9ja09mZnNldF0gfD0gcmVhZEJpdCgpIDw8IHN1Y2Nlc3NpdmU7CiAgfQogIGxldCBlb2JydW4gPSAwOwogIGZ1bmN0aW9uIGRlY29kZUFDRmlyc3QoY29tcG9uZW50LCBibG9ja09mZnNldCkgewogICAgaWYgKGVvYnJ1biA+IDApIHsKICAgICAgZW9icnVuLS07CiAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCBrID0gc3BlY3RyYWxTdGFydDsKICAgIGNvbnN0IGUgPSBzcGVjdHJhbEVuZDsKICAgIHdoaWxlIChrIDw9IGUpIHsKICAgICAgY29uc3QgcnMgPSBkZWNvZGVIdWZmbWFuKGNvbXBvbmVudC5odWZmbWFuVGFibGVBQyk7CiAgICAgIGNvbnN0IHMgPSBycyAmIDE1LAogICAgICAgIHIgPSBycyA+PiA0OwogICAgICBpZiAocyA9PT0gMCkgewogICAgICAgIGlmIChyIDwgMTUpIHsKICAgICAgICAgIGVvYnJ1biA9IHJlY2VpdmUocikgKyAoMSA8PCByKSAtIDE7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgayArPSAxNjsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBrICs9IHI7CiAgICAgIGNvbnN0IHogPSBkY3RaaWdaYWdba107CiAgICAgIGNvbXBvbmVudC5ibG9ja0RhdGFbYmxvY2tPZmZzZXQgKyB6XSA9IHJlY2VpdmVBbmRFeHRlbmQocykgKiAoMSA8PCBzdWNjZXNzaXZlKTsKICAgICAgaysrOwogICAgfQogIH0KICBsZXQgc3VjY2Vzc2l2ZUFDU3RhdGUgPSAwLAogICAgc3VjY2Vzc2l2ZUFDTmV4dFZhbHVlOwogIGZ1bmN0aW9uIGRlY29kZUFDU3VjY2Vzc2l2ZShjb21wb25lbnQsIGJsb2NrT2Zmc2V0KSB7CiAgICBsZXQgayA9IHNwZWN0cmFsU3RhcnQ7CiAgICBjb25zdCBlID0gc3BlY3RyYWxFbmQ7CiAgICBsZXQgciA9IDA7CiAgICBsZXQgczsKICAgIGxldCByczsKICAgIHdoaWxlIChrIDw9IGUpIHsKICAgICAgY29uc3Qgb2Zmc2V0WiA9IGJsb2NrT2Zmc2V0ICsgZGN0WmlnWmFnW2tdOwogICAgICBjb25zdCBzaWduID0gY29tcG9uZW50LmJsb2NrRGF0YVtvZmZzZXRaXSA8IDAgPyAtMSA6IDE7CiAgICAgIHN3aXRjaCAoc3VjY2Vzc2l2ZUFDU3RhdGUpIHsKICAgICAgICBjYXNlIDA6CiAgICAgICAgICBycyA9IGRlY29kZUh1ZmZtYW4oY29tcG9uZW50Lmh1ZmZtYW5UYWJsZUFDKTsKICAgICAgICAgIHMgPSBycyAmIDE1OwogICAgICAgICAgciA9IHJzID4+IDQ7CiAgICAgICAgICBpZiAocyA9PT0gMCkgewogICAgICAgICAgICBpZiAociA8IDE1KSB7CiAgICAgICAgICAgICAgZW9icnVuID0gcmVjZWl2ZShyKSArICgxIDw8IHIpOwogICAgICAgICAgICAgIHN1Y2Nlc3NpdmVBQ1N0YXRlID0gNDsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByID0gMTY7CiAgICAgICAgICAgICAgc3VjY2Vzc2l2ZUFDU3RhdGUgPSAxOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpZiAocyAhPT0gMSkgewogICAgICAgICAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoImludmFsaWQgQUNuIGVuY29kaW5nIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3VjY2Vzc2l2ZUFDTmV4dFZhbHVlID0gcmVjZWl2ZUFuZEV4dGVuZChzKTsKICAgICAgICAgICAgc3VjY2Vzc2l2ZUFDU3RhdGUgPSByID8gMiA6IDM7CiAgICAgICAgICB9CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICBjYXNlIDE6CiAgICAgICAgY2FzZSAyOgogICAgICAgICAgaWYgKGNvbXBvbmVudC5ibG9ja0RhdGFbb2Zmc2V0Wl0pIHsKICAgICAgICAgICAgY29tcG9uZW50LmJsb2NrRGF0YVtvZmZzZXRaXSArPSBzaWduICogKHJlYWRCaXQoKSA8PCBzdWNjZXNzaXZlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHItLTsKICAgICAgICAgICAgaWYgKHIgPT09IDApIHsKICAgICAgICAgICAgICBzdWNjZXNzaXZlQUNTdGF0ZSA9IHN1Y2Nlc3NpdmVBQ1N0YXRlID09PSAyID8gMyA6IDA7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzoKICAgICAgICAgIGlmIChjb21wb25lbnQuYmxvY2tEYXRhW29mZnNldFpdKSB7CiAgICAgICAgICAgIGNvbXBvbmVudC5ibG9ja0RhdGFbb2Zmc2V0Wl0gKz0gc2lnbiAqIChyZWFkQml0KCkgPDwgc3VjY2Vzc2l2ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBjb21wb25lbnQuYmxvY2tEYXRhW29mZnNldFpdID0gc3VjY2Vzc2l2ZUFDTmV4dFZhbHVlIDw8IHN1Y2Nlc3NpdmU7CiAgICAgICAgICAgIHN1Y2Nlc3NpdmVBQ1N0YXRlID0gMDsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNDoKICAgICAgICAgIGlmIChjb21wb25lbnQuYmxvY2tEYXRhW29mZnNldFpdKSB7CiAgICAgICAgICAgIGNvbXBvbmVudC5ibG9ja0RhdGFbb2Zmc2V0Wl0gKz0gc2lnbiAqIChyZWFkQml0KCkgPDwgc3VjY2Vzc2l2ZSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBrKys7CiAgICB9CiAgICBpZiAoc3VjY2Vzc2l2ZUFDU3RhdGUgPT09IDQpIHsKICAgICAgZW9icnVuLS07CiAgICAgIGlmIChlb2JydW4gPT09IDApIHsKICAgICAgICBzdWNjZXNzaXZlQUNTdGF0ZSA9IDA7CiAgICAgIH0KICAgIH0KICB9CiAgbGV0IGJsb2NrUm93ID0gMDsKICBmdW5jdGlvbiBkZWNvZGVNY3UoY29tcG9uZW50LCBkZWNvZGUsIG1jdSwgcm93LCBjb2wpIHsKICAgIGNvbnN0IG1jdVJvdyA9IG1jdSAvIG1jdXNQZXJMaW5lIHwgMDsKICAgIGNvbnN0IG1jdUNvbCA9IG1jdSAlIG1jdXNQZXJMaW5lOwogICAgYmxvY2tSb3cgPSBtY3VSb3cgKiBjb21wb25lbnQudiArIHJvdzsKICAgIGNvbnN0IGJsb2NrQ29sID0gbWN1Q29sICogY29tcG9uZW50LmggKyBjb2w7CiAgICBjb25zdCBibG9ja09mZnNldCA9IGdldEJsb2NrQnVmZmVyT2Zmc2V0KGNvbXBvbmVudCwgYmxvY2tSb3csIGJsb2NrQ29sKTsKICAgIGRlY29kZShjb21wb25lbnQsIGJsb2NrT2Zmc2V0KTsKICB9CiAgZnVuY3Rpb24gZGVjb2RlQmxvY2soY29tcG9uZW50LCBkZWNvZGUsIG1jdSkgewogICAgYmxvY2tSb3cgPSBtY3UgLyBjb21wb25lbnQuYmxvY2tzUGVyTGluZSB8IDA7CiAgICBjb25zdCBibG9ja0NvbCA9IG1jdSAlIGNvbXBvbmVudC5ibG9ja3NQZXJMaW5lOwogICAgY29uc3QgYmxvY2tPZmZzZXQgPSBnZXRCbG9ja0J1ZmZlck9mZnNldChjb21wb25lbnQsIGJsb2NrUm93LCBibG9ja0NvbCk7CiAgICBkZWNvZGUoY29tcG9uZW50LCBibG9ja09mZnNldCk7CiAgfQogIGNvbnN0IGNvbXBvbmVudHNMZW5ndGggPSBjb21wb25lbnRzLmxlbmd0aDsKICBsZXQgY29tcG9uZW50LCBpLCBqLCBrLCBuOwogIGxldCBkZWNvZGVGbjsKICBpZiAocHJvZ3Jlc3NpdmUpIHsKICAgIGlmIChzcGVjdHJhbFN0YXJ0ID09PSAwKSB7CiAgICAgIGRlY29kZUZuID0gc3VjY2Vzc2l2ZVByZXYgPT09IDAgPyBkZWNvZGVEQ0ZpcnN0IDogZGVjb2RlRENTdWNjZXNzaXZlOwogICAgfSBlbHNlIHsKICAgICAgZGVjb2RlRm4gPSBzdWNjZXNzaXZlUHJldiA9PT0gMCA/IGRlY29kZUFDRmlyc3QgOiBkZWNvZGVBQ1N1Y2Nlc3NpdmU7CiAgICB9CiAgfSBlbHNlIHsKICAgIGRlY29kZUZuID0gZGVjb2RlQmFzZWxpbmU7CiAgfQogIGxldCBtY3UgPSAwLAogICAgZmlsZU1hcmtlcjsKICBjb25zdCBtY3VFeHBlY3RlZCA9IGNvbXBvbmVudHNMZW5ndGggPT09IDEgPyBjb21wb25lbnRzWzBdLmJsb2Nrc1BlckxpbmUgKiBjb21wb25lbnRzWzBdLmJsb2Nrc1BlckNvbHVtbiA6IG1jdXNQZXJMaW5lICogZnJhbWUubWN1c1BlckNvbHVtbjsKICBsZXQgaCwgdjsKICB3aGlsZSAobWN1IDw9IG1jdUV4cGVjdGVkKSB7CiAgICBjb25zdCBtY3VUb1JlYWQgPSByZXNldEludGVydmFsID8gTWF0aC5taW4obWN1RXhwZWN0ZWQgLSBtY3UsIHJlc2V0SW50ZXJ2YWwpIDogbWN1RXhwZWN0ZWQ7CiAgICBpZiAobWN1VG9SZWFkID4gMCkgewogICAgICBmb3IgKGkgPSAwOyBpIDwgY29tcG9uZW50c0xlbmd0aDsgaSsrKSB7CiAgICAgICAgY29tcG9uZW50c1tpXS5wcmVkID0gMDsKICAgICAgfQogICAgICBlb2JydW4gPSAwOwogICAgICBpZiAoY29tcG9uZW50c0xlbmd0aCA9PT0gMSkgewogICAgICAgIGNvbXBvbmVudCA9IGNvbXBvbmVudHNbMF07CiAgICAgICAgZm9yIChuID0gMDsgbiA8IG1jdVRvUmVhZDsgbisrKSB7CiAgICAgICAgICBkZWNvZGVCbG9jayhjb21wb25lbnQsIGRlY29kZUZuLCBtY3UpOwogICAgICAgICAgbWN1Kys7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGZvciAobiA9IDA7IG4gPCBtY3VUb1JlYWQ7IG4rKykgewogICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbXBvbmVudHNMZW5ndGg7IGkrKykgewogICAgICAgICAgICBjb21wb25lbnQgPSBjb21wb25lbnRzW2ldOwogICAgICAgICAgICBoID0gY29tcG9uZW50Lmg7CiAgICAgICAgICAgIHYgPSBjb21wb25lbnQudjsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHY7IGorKykgewogICAgICAgICAgICAgIGZvciAoayA9IDA7IGsgPCBoOyBrKyspIHsKICAgICAgICAgICAgICAgIGRlY29kZU1jdShjb21wb25lbnQsIGRlY29kZUZuLCBtY3UsIGosIGspOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgbWN1Kys7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBiaXRzQ291bnQgPSAwOwogICAgZmlsZU1hcmtlciA9IGZpbmROZXh0RmlsZU1hcmtlcihkYXRhLCBvZmZzZXQpOwogICAgaWYgKCFmaWxlTWFya2VyKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgaWYgKGZpbGVNYXJrZXIuaW52YWxpZCkgewogICAgICBjb25zdCBwYXJ0aWFsTXNnID0gbWN1VG9SZWFkID4gMCA/ICJ1bmV4cGVjdGVkIiA6ICJleGNlc3NpdmUiOwogICAgICB3YXJuKGBkZWNvZGVTY2FuIC0gJHtwYXJ0aWFsTXNnfSBNQ1UgZGF0YSwgY3VycmVudCBtYXJrZXIgaXM6ICR7ZmlsZU1hcmtlci5pbnZhbGlkfWApOwogICAgICBvZmZzZXQgPSBmaWxlTWFya2VyLm9mZnNldDsKICAgIH0KICAgIGlmIChmaWxlTWFya2VyLm1hcmtlciA+PSAweGZmZDAgJiYgZmlsZU1hcmtlci5tYXJrZXIgPD0gMHhmZmQ3KSB7CiAgICAgIG9mZnNldCArPSAyOwogICAgfSBlbHNlIHsKICAgICAgYnJlYWs7CiAgICB9CiAgfQogIHJldHVybiBvZmZzZXQgLSBzdGFydE9mZnNldDsKfQpmdW5jdGlvbiBxdWFudGl6ZUFuZEludmVyc2UoY29tcG9uZW50LCBibG9ja0J1ZmZlck9mZnNldCwgcCkgewogIGNvbnN0IHF0ID0gY29tcG9uZW50LnF1YW50aXphdGlvblRhYmxlLAogICAgYmxvY2tEYXRhID0gY29tcG9uZW50LmJsb2NrRGF0YTsKICBsZXQgdjAsIHYxLCB2MiwgdjMsIHY0LCB2NSwgdjYsIHY3OwogIGxldCBwMCwgcDEsIHAyLCBwMywgcDQsIHA1LCBwNiwgcDc7CiAgbGV0IHQ7CiAgaWYgKCFxdCkgewogICAgdGhyb3cgbmV3IEpwZWdFcnJvcigibWlzc2luZyByZXF1aXJlZCBRdWFudGl6YXRpb24gVGFibGUuIik7CiAgfQogIGZvciAobGV0IHJvdyA9IDA7IHJvdyA8IDY0OyByb3cgKz0gOCkgewogICAgcDAgPSBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyByb3ddOwogICAgcDEgPSBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyByb3cgKyAxXTsKICAgIHAyID0gYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgcm93ICsgMl07CiAgICBwMyA9IGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIHJvdyArIDNdOwogICAgcDQgPSBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyByb3cgKyA0XTsKICAgIHA1ID0gYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgcm93ICsgNV07CiAgICBwNiA9IGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIHJvdyArIDZdOwogICAgcDcgPSBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyByb3cgKyA3XTsKICAgIHAwICo9IHF0W3Jvd107CiAgICBpZiAoKHAxIHwgcDIgfCBwMyB8IHA0IHwgcDUgfCBwNiB8IHA3KSA9PT0gMCkgewogICAgICB0ID0gZGN0U3FydDIgKiBwMCArIDUxMiA+PiAxMDsKICAgICAgcFtyb3ddID0gdDsKICAgICAgcFtyb3cgKyAxXSA9IHQ7CiAgICAgIHBbcm93ICsgMl0gPSB0OwogICAgICBwW3JvdyArIDNdID0gdDsKICAgICAgcFtyb3cgKyA0XSA9IHQ7CiAgICAgIHBbcm93ICsgNV0gPSB0OwogICAgICBwW3JvdyArIDZdID0gdDsKICAgICAgcFtyb3cgKyA3XSA9IHQ7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgcDEgKj0gcXRbcm93ICsgMV07CiAgICBwMiAqPSBxdFtyb3cgKyAyXTsKICAgIHAzICo9IHF0W3JvdyArIDNdOwogICAgcDQgKj0gcXRbcm93ICsgNF07CiAgICBwNSAqPSBxdFtyb3cgKyA1XTsKICAgIHA2ICo9IHF0W3JvdyArIDZdOwogICAgcDcgKj0gcXRbcm93ICsgN107CiAgICB2MCA9IGRjdFNxcnQyICogcDAgKyAxMjggPj4gODsKICAgIHYxID0gZGN0U3FydDIgKiBwNCArIDEyOCA+PiA4OwogICAgdjIgPSBwMjsKICAgIHYzID0gcDY7CiAgICB2NCA9IGRjdFNxcnQxZDIgKiAocDEgLSBwNykgKyAxMjggPj4gODsKICAgIHY3ID0gZGN0U3FydDFkMiAqIChwMSArIHA3KSArIDEyOCA+PiA4OwogICAgdjUgPSBwMyA8PCA0OwogICAgdjYgPSBwNSA8PCA0OwogICAgdjAgPSB2MCArIHYxICsgMSA+PiAxOwogICAgdjEgPSB2MCAtIHYxOwogICAgdCA9IHYyICogZGN0U2luNiArIHYzICogZGN0Q29zNiArIDEyOCA+PiA4OwogICAgdjIgPSB2MiAqIGRjdENvczYgLSB2MyAqIGRjdFNpbjYgKyAxMjggPj4gODsKICAgIHYzID0gdDsKICAgIHY0ID0gdjQgKyB2NiArIDEgPj4gMTsKICAgIHY2ID0gdjQgLSB2NjsKICAgIHY3ID0gdjcgKyB2NSArIDEgPj4gMTsKICAgIHY1ID0gdjcgLSB2NTsKICAgIHYwID0gdjAgKyB2MyArIDEgPj4gMTsKICAgIHYzID0gdjAgLSB2MzsKICAgIHYxID0gdjEgKyB2MiArIDEgPj4gMTsKICAgIHYyID0gdjEgLSB2MjsKICAgIHQgPSB2NCAqIGRjdFNpbjMgKyB2NyAqIGRjdENvczMgKyAyMDQ4ID4+IDEyOwogICAgdjQgPSB2NCAqIGRjdENvczMgLSB2NyAqIGRjdFNpbjMgKyAyMDQ4ID4+IDEyOwogICAgdjcgPSB0OwogICAgdCA9IHY1ICogZGN0U2luMSArIHY2ICogZGN0Q29zMSArIDIwNDggPj4gMTI7CiAgICB2NSA9IHY1ICogZGN0Q29zMSAtIHY2ICogZGN0U2luMSArIDIwNDggPj4gMTI7CiAgICB2NiA9IHQ7CiAgICBwW3Jvd10gPSB2MCArIHY3OwogICAgcFtyb3cgKyA3XSA9IHYwIC0gdjc7CiAgICBwW3JvdyArIDFdID0gdjEgKyB2NjsKICAgIHBbcm93ICsgNl0gPSB2MSAtIHY2OwogICAgcFtyb3cgKyAyXSA9IHYyICsgdjU7CiAgICBwW3JvdyArIDVdID0gdjIgLSB2NTsKICAgIHBbcm93ICsgM10gPSB2MyArIHY0OwogICAgcFtyb3cgKyA0XSA9IHYzIC0gdjQ7CiAgfQogIGZvciAobGV0IGNvbCA9IDA7IGNvbCA8IDg7ICsrY29sKSB7CiAgICBwMCA9IHBbY29sXTsKICAgIHAxID0gcFtjb2wgKyA4XTsKICAgIHAyID0gcFtjb2wgKyAxNl07CiAgICBwMyA9IHBbY29sICsgMjRdOwogICAgcDQgPSBwW2NvbCArIDMyXTsKICAgIHA1ID0gcFtjb2wgKyA0MF07CiAgICBwNiA9IHBbY29sICsgNDhdOwogICAgcDcgPSBwW2NvbCArIDU2XTsKICAgIGlmICgocDEgfCBwMiB8IHAzIHwgcDQgfCBwNSB8IHA2IHwgcDcpID09PSAwKSB7CiAgICAgIHQgPSBkY3RTcXJ0MiAqIHAwICsgODE5MiA+PiAxNDsKICAgICAgaWYgKHQgPCAtMjA0MCkgewogICAgICAgIHQgPSAwOwogICAgICB9IGVsc2UgaWYgKHQgPj0gMjAyNCkgewogICAgICAgIHQgPSAyNTU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdCA9IHQgKyAyMDU2ID4+IDQ7CiAgICAgIH0KICAgICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sXSA9IHQ7CiAgICAgIGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIGNvbCArIDhdID0gdDsKICAgICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgMTZdID0gdDsKICAgICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgMjRdID0gdDsKICAgICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgMzJdID0gdDsKICAgICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgNDBdID0gdDsKICAgICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgNDhdID0gdDsKICAgICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgNTZdID0gdDsKICAgICAgY29udGludWU7CiAgICB9CiAgICB2MCA9IGRjdFNxcnQyICogcDAgKyAyMDQ4ID4+IDEyOwogICAgdjEgPSBkY3RTcXJ0MiAqIHA0ICsgMjA0OCA+PiAxMjsKICAgIHYyID0gcDI7CiAgICB2MyA9IHA2OwogICAgdjQgPSBkY3RTcXJ0MWQyICogKHAxIC0gcDcpICsgMjA0OCA+PiAxMjsKICAgIHY3ID0gZGN0U3FydDFkMiAqIChwMSArIHA3KSArIDIwNDggPj4gMTI7CiAgICB2NSA9IHAzOwogICAgdjYgPSBwNTsKICAgIHYwID0gKHYwICsgdjEgKyAxID4+IDEpICsgNDExMjsKICAgIHYxID0gdjAgLSB2MTsKICAgIHQgPSB2MiAqIGRjdFNpbjYgKyB2MyAqIGRjdENvczYgKyAyMDQ4ID4+IDEyOwogICAgdjIgPSB2MiAqIGRjdENvczYgLSB2MyAqIGRjdFNpbjYgKyAyMDQ4ID4+IDEyOwogICAgdjMgPSB0OwogICAgdjQgPSB2NCArIHY2ICsgMSA+PiAxOwogICAgdjYgPSB2NCAtIHY2OwogICAgdjcgPSB2NyArIHY1ICsgMSA+PiAxOwogICAgdjUgPSB2NyAtIHY1OwogICAgdjAgPSB2MCArIHYzICsgMSA+PiAxOwogICAgdjMgPSB2MCAtIHYzOwogICAgdjEgPSB2MSArIHYyICsgMSA+PiAxOwogICAgdjIgPSB2MSAtIHYyOwogICAgdCA9IHY0ICogZGN0U2luMyArIHY3ICogZGN0Q29zMyArIDIwNDggPj4gMTI7CiAgICB2NCA9IHY0ICogZGN0Q29zMyAtIHY3ICogZGN0U2luMyArIDIwNDggPj4gMTI7CiAgICB2NyA9IHQ7CiAgICB0ID0gdjUgKiBkY3RTaW4xICsgdjYgKiBkY3RDb3MxICsgMjA0OCA+PiAxMjsKICAgIHY1ID0gdjUgKiBkY3RDb3MxIC0gdjYgKiBkY3RTaW4xICsgMjA0OCA+PiAxMjsKICAgIHY2ID0gdDsKICAgIHAwID0gdjAgKyB2NzsKICAgIHA3ID0gdjAgLSB2NzsKICAgIHAxID0gdjEgKyB2NjsKICAgIHA2ID0gdjEgLSB2NjsKICAgIHAyID0gdjIgKyB2NTsKICAgIHA1ID0gdjIgLSB2NTsKICAgIHAzID0gdjMgKyB2NDsKICAgIHA0ID0gdjMgLSB2NDsKICAgIGlmIChwMCA8IDE2KSB7CiAgICAgIHAwID0gMDsKICAgIH0gZWxzZSBpZiAocDAgPj0gNDA4MCkgewogICAgICBwMCA9IDI1NTsKICAgIH0gZWxzZSB7CiAgICAgIHAwID4+PSA0OwogICAgfQogICAgaWYgKHAxIDwgMTYpIHsKICAgICAgcDEgPSAwOwogICAgfSBlbHNlIGlmIChwMSA+PSA0MDgwKSB7CiAgICAgIHAxID0gMjU1OwogICAgfSBlbHNlIHsKICAgICAgcDEgPj49IDQ7CiAgICB9CiAgICBpZiAocDIgPCAxNikgewogICAgICBwMiA9IDA7CiAgICB9IGVsc2UgaWYgKHAyID49IDQwODApIHsKICAgICAgcDIgPSAyNTU7CiAgICB9IGVsc2UgewogICAgICBwMiA+Pj0gNDsKICAgIH0KICAgIGlmIChwMyA8IDE2KSB7CiAgICAgIHAzID0gMDsKICAgIH0gZWxzZSBpZiAocDMgPj0gNDA4MCkgewogICAgICBwMyA9IDI1NTsKICAgIH0gZWxzZSB7CiAgICAgIHAzID4+PSA0OwogICAgfQogICAgaWYgKHA0IDwgMTYpIHsKICAgICAgcDQgPSAwOwogICAgfSBlbHNlIGlmIChwNCA+PSA0MDgwKSB7CiAgICAgIHA0ID0gMjU1OwogICAgfSBlbHNlIHsKICAgICAgcDQgPj49IDQ7CiAgICB9CiAgICBpZiAocDUgPCAxNikgewogICAgICBwNSA9IDA7CiAgICB9IGVsc2UgaWYgKHA1ID49IDQwODApIHsKICAgICAgcDUgPSAyNTU7CiAgICB9IGVsc2UgewogICAgICBwNSA+Pj0gNDsKICAgIH0KICAgIGlmIChwNiA8IDE2KSB7CiAgICAgIHA2ID0gMDsKICAgIH0gZWxzZSBpZiAocDYgPj0gNDA4MCkgewogICAgICBwNiA9IDI1NTsKICAgIH0gZWxzZSB7CiAgICAgIHA2ID4+PSA0OwogICAgfQogICAgaWYgKHA3IDwgMTYpIHsKICAgICAgcDcgPSAwOwogICAgfSBlbHNlIGlmIChwNyA+PSA0MDgwKSB7CiAgICAgIHA3ID0gMjU1OwogICAgfSBlbHNlIHsKICAgICAgcDcgPj49IDQ7CiAgICB9CiAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2xdID0gcDA7CiAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyA4XSA9IHAxOwogICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgMTZdID0gcDI7CiAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyAyNF0gPSBwMzsKICAgIGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIGNvbCArIDMyXSA9IHA0OwogICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgNDBdID0gcDU7CiAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyA0OF0gPSBwNjsKICAgIGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIGNvbCArIDU2XSA9IHA3OwogIH0KfQpmdW5jdGlvbiBidWlsZENvbXBvbmVudERhdGEoZnJhbWUsIGNvbXBvbmVudCkgewogIGNvbnN0IGJsb2Nrc1BlckxpbmUgPSBjb21wb25lbnQuYmxvY2tzUGVyTGluZTsKICBjb25zdCBibG9ja3NQZXJDb2x1bW4gPSBjb21wb25lbnQuYmxvY2tzUGVyQ29sdW1uOwogIGNvbnN0IGNvbXB1dGF0aW9uQnVmZmVyID0gbmV3IEludDE2QXJyYXkoNjQpOwogIGZvciAobGV0IGJsb2NrUm93ID0gMDsgYmxvY2tSb3cgPCBibG9ja3NQZXJDb2x1bW47IGJsb2NrUm93KyspIHsKICAgIGZvciAobGV0IGJsb2NrQ29sID0gMDsgYmxvY2tDb2wgPCBibG9ja3NQZXJMaW5lOyBibG9ja0NvbCsrKSB7CiAgICAgIGNvbnN0IG9mZnNldCA9IGdldEJsb2NrQnVmZmVyT2Zmc2V0KGNvbXBvbmVudCwgYmxvY2tSb3csIGJsb2NrQ29sKTsKICAgICAgcXVhbnRpemVBbmRJbnZlcnNlKGNvbXBvbmVudCwgb2Zmc2V0LCBjb21wdXRhdGlvbkJ1ZmZlcik7CiAgICB9CiAgfQogIHJldHVybiBjb21wb25lbnQuYmxvY2tEYXRhOwp9CmZ1bmN0aW9uIGZpbmROZXh0RmlsZU1hcmtlcihkYXRhLCBjdXJyZW50UG9zLCBzdGFydFBvcyA9IGN1cnJlbnRQb3MpIHsKICBjb25zdCBtYXhQb3MgPSBkYXRhLmxlbmd0aCAtIDE7CiAgbGV0IG5ld1BvcyA9IHN0YXJ0UG9zIDwgY3VycmVudFBvcyA/IHN0YXJ0UG9zIDogY3VycmVudFBvczsKICBpZiAoY3VycmVudFBvcyA+PSBtYXhQb3MpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCBjdXJyZW50TWFya2VyID0gcmVhZFVpbnQxNihkYXRhLCBjdXJyZW50UG9zKTsKICBpZiAoY3VycmVudE1hcmtlciA+PSAweGZmYzAgJiYgY3VycmVudE1hcmtlciA8PSAweGZmZmUpIHsKICAgIHJldHVybiB7CiAgICAgIGludmFsaWQ6IG51bGwsCiAgICAgIG1hcmtlcjogY3VycmVudE1hcmtlciwKICAgICAgb2Zmc2V0OiBjdXJyZW50UG9zCiAgICB9OwogIH0KICBsZXQgbmV3TWFya2VyID0gcmVhZFVpbnQxNihkYXRhLCBuZXdQb3MpOwogIHdoaWxlICghKG5ld01hcmtlciA+PSAweGZmYzAgJiYgbmV3TWFya2VyIDw9IDB4ZmZmZSkpIHsKICAgIGlmICgrK25ld1BvcyA+PSBtYXhQb3MpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBuZXdNYXJrZXIgPSByZWFkVWludDE2KGRhdGEsIG5ld1Bvcyk7CiAgfQogIHJldHVybiB7CiAgICBpbnZhbGlkOiBjdXJyZW50TWFya2VyLnRvU3RyaW5nKDE2KSwKICAgIG1hcmtlcjogbmV3TWFya2VyLAogICAgb2Zmc2V0OiBuZXdQb3MKICB9Owp9CmZ1bmN0aW9uIHByZXBhcmVDb21wb25lbnRzKGZyYW1lKSB7CiAgY29uc3QgbWN1c1BlckxpbmUgPSBNYXRoLmNlaWwoZnJhbWUuc2FtcGxlc1BlckxpbmUgLyA4IC8gZnJhbWUubWF4SCk7CiAgY29uc3QgbWN1c1BlckNvbHVtbiA9IE1hdGguY2VpbChmcmFtZS5zY2FuTGluZXMgLyA4IC8gZnJhbWUubWF4Vik7CiAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgZnJhbWUuY29tcG9uZW50cykgewogICAgY29uc3QgYmxvY2tzUGVyTGluZSA9IE1hdGguY2VpbChNYXRoLmNlaWwoZnJhbWUuc2FtcGxlc1BlckxpbmUgLyA4KSAqIGNvbXBvbmVudC5oIC8gZnJhbWUubWF4SCk7CiAgICBjb25zdCBibG9ja3NQZXJDb2x1bW4gPSBNYXRoLmNlaWwoTWF0aC5jZWlsKGZyYW1lLnNjYW5MaW5lcyAvIDgpICogY29tcG9uZW50LnYgLyBmcmFtZS5tYXhWKTsKICAgIGNvbnN0IGJsb2Nrc1BlckxpbmVGb3JNY3UgPSBtY3VzUGVyTGluZSAqIGNvbXBvbmVudC5oOwogICAgY29uc3QgYmxvY2tzUGVyQ29sdW1uRm9yTWN1ID0gbWN1c1BlckNvbHVtbiAqIGNvbXBvbmVudC52OwogICAgY29uc3QgYmxvY2tzQnVmZmVyU2l6ZSA9IDY0ICogYmxvY2tzUGVyQ29sdW1uRm9yTWN1ICogKGJsb2Nrc1BlckxpbmVGb3JNY3UgKyAxKTsKICAgIGNvbXBvbmVudC5ibG9ja0RhdGEgPSBuZXcgSW50MTZBcnJheShibG9ja3NCdWZmZXJTaXplKTsKICAgIGNvbXBvbmVudC5ibG9ja3NQZXJMaW5lID0gYmxvY2tzUGVyTGluZTsKICAgIGNvbXBvbmVudC5ibG9ja3NQZXJDb2x1bW4gPSBibG9ja3NQZXJDb2x1bW47CiAgfQogIGZyYW1lLm1jdXNQZXJMaW5lID0gbWN1c1BlckxpbmU7CiAgZnJhbWUubWN1c1BlckNvbHVtbiA9IG1jdXNQZXJDb2x1bW47Cn0KZnVuY3Rpb24gcmVhZERhdGFCbG9jayhkYXRhLCBvZmZzZXQpIHsKICBjb25zdCBsZW5ndGggPSByZWFkVWludDE2KGRhdGEsIG9mZnNldCk7CiAgb2Zmc2V0ICs9IDI7CiAgbGV0IGVuZE9mZnNldCA9IG9mZnNldCArIGxlbmd0aCAtIDI7CiAgY29uc3QgZmlsZU1hcmtlciA9IGZpbmROZXh0RmlsZU1hcmtlcihkYXRhLCBlbmRPZmZzZXQsIG9mZnNldCk7CiAgaWYgKGZpbGVNYXJrZXI/LmludmFsaWQpIHsKICAgIHdhcm4oInJlYWREYXRhQmxvY2sgLSBpbmNvcnJlY3QgbGVuZ3RoLCBjdXJyZW50IG1hcmtlciBpczogIiArIGZpbGVNYXJrZXIuaW52YWxpZCk7CiAgICBlbmRPZmZzZXQgPSBmaWxlTWFya2VyLm9mZnNldDsKICB9CiAgY29uc3QgYXJyYXkgPSBkYXRhLnN1YmFycmF5KG9mZnNldCwgZW5kT2Zmc2V0KTsKICByZXR1cm4gewogICAgYXBwRGF0YTogYXJyYXksCiAgICBvbGRPZmZzZXQ6IG9mZnNldCwKICAgIG5ld09mZnNldDogb2Zmc2V0ICsgYXJyYXkubGVuZ3RoCiAgfTsKfQpmdW5jdGlvbiBza2lwRGF0YShkYXRhLCBvZmZzZXQpIHsKICBjb25zdCBsZW5ndGggPSByZWFkVWludDE2KGRhdGEsIG9mZnNldCk7CiAgb2Zmc2V0ICs9IDI7CiAgY29uc3QgZW5kT2Zmc2V0ID0gb2Zmc2V0ICsgbGVuZ3RoIC0gMjsKICBjb25zdCBmaWxlTWFya2VyID0gZmluZE5leHRGaWxlTWFya2VyKGRhdGEsIGVuZE9mZnNldCwgb2Zmc2V0KTsKICBpZiAoZmlsZU1hcmtlcj8uaW52YWxpZCkgewogICAgcmV0dXJuIGZpbGVNYXJrZXIub2Zmc2V0OwogIH0KICByZXR1cm4gZW5kT2Zmc2V0Owp9CmNsYXNzIEpwZWdJbWFnZSB7CiAgY29uc3RydWN0b3IoewogICAgZGVjb2RlVHJhbnNmb3JtID0gbnVsbCwKICAgIGNvbG9yVHJhbnNmb3JtID0gLTEKICB9ID0ge30pIHsKICAgIHRoaXMuX2RlY29kZVRyYW5zZm9ybSA9IGRlY29kZVRyYW5zZm9ybTsKICAgIHRoaXMuX2NvbG9yVHJhbnNmb3JtID0gY29sb3JUcmFuc2Zvcm07CiAgfQogIHN0YXRpYyBjYW5Vc2VJbWFnZURlY29kZXIoZGF0YSwgY29sb3JUcmFuc2Zvcm0gPSAtMSkgewogICAgbGV0IGV4aWZPZmZzZXRzID0gbnVsbDsKICAgIGxldCBvZmZzZXQgPSAwOwogICAgbGV0IG51bUNvbXBvbmVudHMgPSBudWxsOwogICAgbGV0IGZpbGVNYXJrZXIgPSByZWFkVWludDE2KGRhdGEsIG9mZnNldCk7CiAgICBvZmZzZXQgKz0gMjsKICAgIGlmIChmaWxlTWFya2VyICE9PSAweGZmZDgpIHsKICAgICAgdGhyb3cgbmV3IEpwZWdFcnJvcigiU09JIG5vdCBmb3VuZCIpOwogICAgfQogICAgZmlsZU1hcmtlciA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgIG9mZnNldCArPSAyOwogICAgbWFya2VyTG9vcDogd2hpbGUgKGZpbGVNYXJrZXIgIT09IDB4ZmZkOSkgewogICAgICBzd2l0Y2ggKGZpbGVNYXJrZXIpIHsKICAgICAgICBjYXNlIDB4ZmZlMToKICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgYXBwRGF0YSwKICAgICAgICAgICAgb2xkT2Zmc2V0LAogICAgICAgICAgICBuZXdPZmZzZXQKICAgICAgICAgIH0gPSByZWFkRGF0YUJsb2NrKGRhdGEsIG9mZnNldCk7CiAgICAgICAgICBvZmZzZXQgPSBuZXdPZmZzZXQ7CiAgICAgICAgICBpZiAoYXBwRGF0YVswXSA9PT0gMHg0NSAmJiBhcHBEYXRhWzFdID09PSAweDc4ICYmIGFwcERhdGFbMl0gPT09IDB4NjkgJiYgYXBwRGF0YVszXSA9PT0gMHg2NiAmJiBhcHBEYXRhWzRdID09PSAwICYmIGFwcERhdGFbNV0gPT09IDApIHsKICAgICAgICAgICAgaWYgKGV4aWZPZmZzZXRzKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEpwZWdFcnJvcigiRHVwbGljYXRlIEVYSUYtYmxvY2tzIGZvdW5kLiIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGV4aWZPZmZzZXRzID0gewogICAgICAgICAgICAgIGV4aWZTdGFydDogb2xkT2Zmc2V0ICsgNiwKICAgICAgICAgICAgICBleGlmRW5kOiBuZXdPZmZzZXQKICAgICAgICAgICAgfTsKICAgICAgICAgIH0KICAgICAgICAgIGZpbGVNYXJrZXIgPSByZWFkVWludDE2KGRhdGEsIG9mZnNldCk7CiAgICAgICAgICBvZmZzZXQgKz0gMjsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIGNhc2UgMHhmZmMwOgogICAgICAgIGNhc2UgMHhmZmMxOgogICAgICAgIGNhc2UgMHhmZmMyOgogICAgICAgICAgbnVtQ29tcG9uZW50cyA9IGRhdGFbb2Zmc2V0ICsgKDIgKyAxICsgMiArIDIpXTsKICAgICAgICAgIGJyZWFrIG1hcmtlckxvb3A7CiAgICAgICAgY2FzZSAweGZmZmY6CiAgICAgICAgICBpZiAoZGF0YVtvZmZzZXRdICE9PSAweGZmKSB7CiAgICAgICAgICAgIG9mZnNldC0tOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgb2Zmc2V0ID0gc2tpcERhdGEoZGF0YSwgb2Zmc2V0KTsKICAgICAgZmlsZU1hcmtlciA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgICAgb2Zmc2V0ICs9IDI7CiAgICB9CiAgICBpZiAobnVtQ29tcG9uZW50cyA9PT0gNCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGlmIChudW1Db21wb25lbnRzID09PSAzICYmIGNvbG9yVHJhbnNmb3JtID09PSAwKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcmV0dXJuIGV4aWZPZmZzZXRzIHx8IHt9OwogIH0KICBwYXJzZShkYXRhLCB7CiAgICBkbmxTY2FuTGluZXMgPSBudWxsCiAgfSA9IHt9KSB7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIGxldCBqZmlmID0gbnVsbDsKICAgIGxldCBhZG9iZSA9IG51bGw7CiAgICBsZXQgZnJhbWUsIHJlc2V0SW50ZXJ2YWw7CiAgICBsZXQgbnVtU09TTWFya2VycyA9IDA7CiAgICBjb25zdCBxdWFudGl6YXRpb25UYWJsZXMgPSBbXTsKICAgIGNvbnN0IGh1ZmZtYW5UYWJsZXNBQyA9IFtdLAogICAgICBodWZmbWFuVGFibGVzREMgPSBbXTsKICAgIGxldCBmaWxlTWFya2VyID0gcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDI7CiAgICBpZiAoZmlsZU1hcmtlciAhPT0gMHhmZmQ4KSB7CiAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoIlNPSSBub3QgZm91bmQiKTsKICAgIH0KICAgIGZpbGVNYXJrZXIgPSByZWFkVWludDE2KGRhdGEsIG9mZnNldCk7CiAgICBvZmZzZXQgKz0gMjsKICAgIG1hcmtlckxvb3A6IHdoaWxlIChmaWxlTWFya2VyICE9PSAweGZmZDkpIHsKICAgICAgbGV0IGksIGosIGw7CiAgICAgIHN3aXRjaCAoZmlsZU1hcmtlcikgewogICAgICAgIGNhc2UgMHhmZmUwOgogICAgICAgIGNhc2UgMHhmZmUxOgogICAgICAgIGNhc2UgMHhmZmUyOgogICAgICAgIGNhc2UgMHhmZmUzOgogICAgICAgIGNhc2UgMHhmZmU0OgogICAgICAgIGNhc2UgMHhmZmU1OgogICAgICAgIGNhc2UgMHhmZmU2OgogICAgICAgIGNhc2UgMHhmZmU3OgogICAgICAgIGNhc2UgMHhmZmU4OgogICAgICAgIGNhc2UgMHhmZmU5OgogICAgICAgIGNhc2UgMHhmZmVhOgogICAgICAgIGNhc2UgMHhmZmViOgogICAgICAgIGNhc2UgMHhmZmVjOgogICAgICAgIGNhc2UgMHhmZmVkOgogICAgICAgIGNhc2UgMHhmZmVlOgogICAgICAgIGNhc2UgMHhmZmVmOgogICAgICAgIGNhc2UgMHhmZmZlOgogICAgICAgICAgY29uc3QgewogICAgICAgICAgICBhcHBEYXRhLAogICAgICAgICAgICBuZXdPZmZzZXQKICAgICAgICAgIH0gPSByZWFkRGF0YUJsb2NrKGRhdGEsIG9mZnNldCk7CiAgICAgICAgICBvZmZzZXQgPSBuZXdPZmZzZXQ7CiAgICAgICAgICBpZiAoZmlsZU1hcmtlciA9PT0gMHhmZmUwKSB7CiAgICAgICAgICAgIGlmIChhcHBEYXRhWzBdID09PSAweDRhICYmIGFwcERhdGFbMV0gPT09IDB4NDYgJiYgYXBwRGF0YVsyXSA9PT0gMHg0OSAmJiBhcHBEYXRhWzNdID09PSAweDQ2ICYmIGFwcERhdGFbNF0gPT09IDApIHsKICAgICAgICAgICAgICBqZmlmID0gewogICAgICAgICAgICAgICAgdmVyc2lvbjogewogICAgICAgICAgICAgICAgICBtYWpvcjogYXBwRGF0YVs1XSwKICAgICAgICAgICAgICAgICAgbWlub3I6IGFwcERhdGFbNl0KICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICBkZW5zaXR5VW5pdHM6IGFwcERhdGFbN10sCiAgICAgICAgICAgICAgICB4RGVuc2l0eTogYXBwRGF0YVs4XSA8PCA4IHwgYXBwRGF0YVs5XSwKICAgICAgICAgICAgICAgIHlEZW5zaXR5OiBhcHBEYXRhWzEwXSA8PCA4IHwgYXBwRGF0YVsxMV0sCiAgICAgICAgICAgICAgICB0aHVtYldpZHRoOiBhcHBEYXRhWzEyXSwKICAgICAgICAgICAgICAgIHRodW1iSGVpZ2h0OiBhcHBEYXRhWzEzXSwKICAgICAgICAgICAgICAgIHRodW1iRGF0YTogYXBwRGF0YS5zdWJhcnJheSgxNCwgMTQgKyAzICogYXBwRGF0YVsxMl0gKiBhcHBEYXRhWzEzXSkKICAgICAgICAgICAgICB9OwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZmlsZU1hcmtlciA9PT0gMHhmZmVlKSB7CiAgICAgICAgICAgIGlmIChhcHBEYXRhWzBdID09PSAweDQxICYmIGFwcERhdGFbMV0gPT09IDB4NjQgJiYgYXBwRGF0YVsyXSA9PT0gMHg2ZiAmJiBhcHBEYXRhWzNdID09PSAweDYyICYmIGFwcERhdGFbNF0gPT09IDB4NjUpIHsKICAgICAgICAgICAgICBhZG9iZSA9IHsKICAgICAgICAgICAgICAgIHZlcnNpb246IGFwcERhdGFbNV0gPDwgOCB8IGFwcERhdGFbNl0sCiAgICAgICAgICAgICAgICBmbGFnczA6IGFwcERhdGFbN10gPDwgOCB8IGFwcERhdGFbOF0sCiAgICAgICAgICAgICAgICBmbGFnczE6IGFwcERhdGFbOV0gPDwgOCB8IGFwcERhdGFbMTBdLAogICAgICAgICAgICAgICAgdHJhbnNmb3JtQ29kZTogYXBwRGF0YVsxMV0KICAgICAgICAgICAgICB9OwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4ZmZkYjoKICAgICAgICAgIGNvbnN0IHF1YW50aXphdGlvblRhYmxlc0xlbmd0aCA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgY29uc3QgcXVhbnRpemF0aW9uVGFibGVzRW5kID0gcXVhbnRpemF0aW9uVGFibGVzTGVuZ3RoICsgb2Zmc2V0IC0gMjsKICAgICAgICAgIGxldCB6OwogICAgICAgICAgd2hpbGUgKG9mZnNldCA8IHF1YW50aXphdGlvblRhYmxlc0VuZCkgewogICAgICAgICAgICBjb25zdCBxdWFudGl6YXRpb25UYWJsZVNwZWMgPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgICAgY29uc3QgdGFibGVEYXRhID0gbmV3IFVpbnQxNkFycmF5KDY0KTsKICAgICAgICAgICAgaWYgKHF1YW50aXphdGlvblRhYmxlU3BlYyA+PiA0ID09PSAwKSB7CiAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IDY0OyBqKyspIHsKICAgICAgICAgICAgICAgIHogPSBkY3RaaWdaYWdbal07CiAgICAgICAgICAgICAgICB0YWJsZURhdGFbel0gPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSBpZiAocXVhbnRpemF0aW9uVGFibGVTcGVjID4+IDQgPT09IDEpIHsKICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgNjQ7IGorKykgewogICAgICAgICAgICAgICAgeiA9IGRjdFppZ1phZ1tqXTsKICAgICAgICAgICAgICAgIHRhYmxlRGF0YVt6XSA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgSnBlZ0Vycm9yKCJEUVQgLSBpbnZhbGlkIHRhYmxlIHNwZWMiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBxdWFudGl6YXRpb25UYWJsZXNbcXVhbnRpemF0aW9uVGFibGVTcGVjICYgMTVdID0gdGFibGVEYXRhOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGZmYzA6CiAgICAgICAgY2FzZSAweGZmYzE6CiAgICAgICAgY2FzZSAweGZmYzI6CiAgICAgICAgICBpZiAoZnJhbWUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEpwZWdFcnJvcigiT25seSBzaW5nbGUgZnJhbWUgSlBFR3Mgc3VwcG9ydGVkIik7CiAgICAgICAgICB9CiAgICAgICAgICBvZmZzZXQgKz0gMjsKICAgICAgICAgIGZyYW1lID0ge307CiAgICAgICAgICBmcmFtZS5leHRlbmRlZCA9IGZpbGVNYXJrZXIgPT09IDB4ZmZjMTsKICAgICAgICAgIGZyYW1lLnByb2dyZXNzaXZlID0gZmlsZU1hcmtlciA9PT0gMHhmZmMyOwogICAgICAgICAgZnJhbWUucHJlY2lzaW9uID0gZGF0YVtvZmZzZXQrK107CiAgICAgICAgICBjb25zdCBzb2ZTY2FuTGluZXMgPSByZWFkVWludDE2KGRhdGEsIG9mZnNldCk7CiAgICAgICAgICBvZmZzZXQgKz0gMjsKICAgICAgICAgIGZyYW1lLnNjYW5MaW5lcyA9IGRubFNjYW5MaW5lcyB8fCBzb2ZTY2FuTGluZXM7CiAgICAgICAgICBmcmFtZS5zYW1wbGVzUGVyTGluZSA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgZnJhbWUuY29tcG9uZW50cyA9IFtdOwogICAgICAgICAgZnJhbWUuY29tcG9uZW50SWRzID0ge307CiAgICAgICAgICBjb25zdCBjb21wb25lbnRzQ291bnQgPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgIGxldCBtYXhIID0gMCwKICAgICAgICAgICAgbWF4ViA9IDA7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29tcG9uZW50c0NvdW50OyBpKyspIHsKICAgICAgICAgICAgY29uc3QgY29tcG9uZW50SWQgPSBkYXRhW29mZnNldF07CiAgICAgICAgICAgIGNvbnN0IGggPSBkYXRhW29mZnNldCArIDFdID4+IDQ7CiAgICAgICAgICAgIGNvbnN0IHYgPSBkYXRhW29mZnNldCArIDFdICYgMTU7CiAgICAgICAgICAgIGlmIChtYXhIIDwgaCkgewogICAgICAgICAgICAgIG1heEggPSBoOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChtYXhWIDwgdikgewogICAgICAgICAgICAgIG1heFYgPSB2OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IHFJZCA9IGRhdGFbb2Zmc2V0ICsgMl07CiAgICAgICAgICAgIGwgPSBmcmFtZS5jb21wb25lbnRzLnB1c2goewogICAgICAgICAgICAgIGgsCiAgICAgICAgICAgICAgdiwKICAgICAgICAgICAgICBxdWFudGl6YXRpb25JZDogcUlkLAogICAgICAgICAgICAgIHF1YW50aXphdGlvblRhYmxlOiBudWxsCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBmcmFtZS5jb21wb25lbnRJZHNbY29tcG9uZW50SWRdID0gbCAtIDE7CiAgICAgICAgICAgIG9mZnNldCArPSAzOwogICAgICAgICAgfQogICAgICAgICAgZnJhbWUubWF4SCA9IG1heEg7CiAgICAgICAgICBmcmFtZS5tYXhWID0gbWF4VjsKICAgICAgICAgIHByZXBhcmVDb21wb25lbnRzKGZyYW1lKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHhmZmM0OgogICAgICAgICAgY29uc3QgaHVmZm1hbkxlbmd0aCA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgZm9yIChpID0gMjsgaSA8IGh1ZmZtYW5MZW5ndGg7KSB7CiAgICAgICAgICAgIGNvbnN0IGh1ZmZtYW5UYWJsZVNwZWMgPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgICAgY29uc3QgY29kZUxlbmd0aHMgPSBuZXcgVWludDhBcnJheSgxNik7CiAgICAgICAgICAgIGxldCBjb2RlTGVuZ3RoU3VtID0gMDsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IDE2OyBqKyssIG9mZnNldCsrKSB7CiAgICAgICAgICAgICAgY29kZUxlbmd0aFN1bSArPSBjb2RlTGVuZ3Roc1tqXSA9IGRhdGFbb2Zmc2V0XTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBodWZmbWFuVmFsdWVzID0gbmV3IFVpbnQ4QXJyYXkoY29kZUxlbmd0aFN1bSk7CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBjb2RlTGVuZ3RoU3VtOyBqKyssIG9mZnNldCsrKSB7CiAgICAgICAgICAgICAgaHVmZm1hblZhbHVlc1tqXSA9IGRhdGFbb2Zmc2V0XTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpICs9IDE3ICsgY29kZUxlbmd0aFN1bTsKICAgICAgICAgICAgKGh1ZmZtYW5UYWJsZVNwZWMgPj4gNCA9PT0gMCA/IGh1ZmZtYW5UYWJsZXNEQyA6IGh1ZmZtYW5UYWJsZXNBQylbaHVmZm1hblRhYmxlU3BlYyAmIDE1XSA9IGJ1aWxkSHVmZm1hblRhYmxlKGNvZGVMZW5ndGhzLCBodWZmbWFuVmFsdWVzKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHhmZmRkOgogICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICByZXNldEludGVydmFsID0gcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpOwogICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4ZmZkYToKICAgICAgICAgIGNvbnN0IHBhcnNlRE5MTWFya2VyID0gKytudW1TT1NNYXJrZXJzID09PSAxICYmICFkbmxTY2FuTGluZXM7CiAgICAgICAgICBvZmZzZXQgKz0gMjsKICAgICAgICAgIGNvbnN0IHNlbGVjdG9yc0NvdW50ID0gZGF0YVtvZmZzZXQrK10sCiAgICAgICAgICAgIGNvbXBvbmVudHMgPSBbXTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzZWxlY3RvcnNDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gZGF0YVtvZmZzZXQrK107CiAgICAgICAgICAgIGNvbnN0IGNvbXBvbmVudEluZGV4ID0gZnJhbWUuY29tcG9uZW50SWRzW2luZGV4XTsKICAgICAgICAgICAgY29uc3QgY29tcG9uZW50ID0gZnJhbWUuY29tcG9uZW50c1tjb21wb25lbnRJbmRleF07CiAgICAgICAgICAgIGNvbXBvbmVudC5pbmRleCA9IGluZGV4OwogICAgICAgICAgICBjb25zdCB0YWJsZVNwZWMgPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgICAgY29tcG9uZW50Lmh1ZmZtYW5UYWJsZURDID0gaHVmZm1hblRhYmxlc0RDW3RhYmxlU3BlYyA+PiA0XTsKICAgICAgICAgICAgY29tcG9uZW50Lmh1ZmZtYW5UYWJsZUFDID0gaHVmZm1hblRhYmxlc0FDW3RhYmxlU3BlYyAmIDE1XTsKICAgICAgICAgICAgY29tcG9uZW50cy5wdXNoKGNvbXBvbmVudCk7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBzcGVjdHJhbFN0YXJ0ID0gZGF0YVtvZmZzZXQrK10sCiAgICAgICAgICAgIHNwZWN0cmFsRW5kID0gZGF0YVtvZmZzZXQrK10sCiAgICAgICAgICAgIHN1Y2Nlc3NpdmVBcHByb3hpbWF0aW9uID0gZGF0YVtvZmZzZXQrK107CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBjb25zdCBwcm9jZXNzZWQgPSBkZWNvZGVTY2FuKGRhdGEsIG9mZnNldCwgZnJhbWUsIGNvbXBvbmVudHMsIHJlc2V0SW50ZXJ2YWwsIHNwZWN0cmFsU3RhcnQsIHNwZWN0cmFsRW5kLCBzdWNjZXNzaXZlQXBwcm94aW1hdGlvbiA+PiA0LCBzdWNjZXNzaXZlQXBwcm94aW1hdGlvbiAmIDE1LCBwYXJzZUROTE1hcmtlcik7CiAgICAgICAgICAgIG9mZnNldCArPSBwcm9jZXNzZWQ7CiAgICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBETkxNYXJrZXJFcnJvcikgewogICAgICAgICAgICAgIHdhcm4oYCR7ZXgubWVzc2FnZX0gLS0gYXR0ZW1wdGluZyB0byByZS1wYXJzZSB0aGUgSlBFRyBpbWFnZS5gKTsKICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJzZShkYXRhLCB7CiAgICAgICAgICAgICAgICBkbmxTY2FuTGluZXM6IGV4LnNjYW5MaW5lcwogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9IGVsc2UgaWYgKGV4IGluc3RhbmNlb2YgRU9JTWFya2VyRXJyb3IpIHsKICAgICAgICAgICAgICB3YXJuKGAke2V4Lm1lc3NhZ2V9IC0tIGlnbm9yaW5nIHRoZSByZXN0IG9mIHRoZSBpbWFnZSBkYXRhLmApOwogICAgICAgICAgICAgIGJyZWFrIG1hcmtlckxvb3A7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhyb3cgZXg7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4ZmZkYzoKICAgICAgICAgIG9mZnNldCArPSA0OwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGZmZmY6CiAgICAgICAgICBpZiAoZGF0YVtvZmZzZXRdICE9PSAweGZmKSB7CiAgICAgICAgICAgIG9mZnNldC0tOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIGNvbnN0IG5leHRGaWxlTWFya2VyID0gZmluZE5leHRGaWxlTWFya2VyKGRhdGEsIG9mZnNldCAtIDIsIG9mZnNldCAtIDMpOwogICAgICAgICAgaWYgKG5leHRGaWxlTWFya2VyPy5pbnZhbGlkKSB7CiAgICAgICAgICAgIHdhcm4oIkpwZWdJbWFnZS5wYXJzZSAtIHVuZXhwZWN0ZWQgZGF0YSwgY3VycmVudCBtYXJrZXIgaXM6ICIgKyBuZXh0RmlsZU1hcmtlci5pbnZhbGlkKTsKICAgICAgICAgICAgb2Zmc2V0ID0gbmV4dEZpbGVNYXJrZXIub2Zmc2V0OwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghbmV4dEZpbGVNYXJrZXIgfHwgb2Zmc2V0ID49IGRhdGEubGVuZ3RoIC0gMSkgewogICAgICAgICAgICB3YXJuKCJKcGVnSW1hZ2UucGFyc2UgLSByZWFjaGVkIHRoZSBlbmQgb2YgdGhlIGltYWdlIGRhdGEgIiArICJ3aXRob3V0IGZpbmRpbmcgYW4gRU9JIG1hcmtlciAoMHhGRkQ5KS4iKTsKICAgICAgICAgICAgYnJlYWsgbWFya2VyTG9vcDsKICAgICAgICAgIH0KICAgICAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoIkpwZWdJbWFnZS5wYXJzZSAtIHVua25vd24gbWFya2VyOiAiICsgZmlsZU1hcmtlci50b1N0cmluZygxNikpOwogICAgICB9CiAgICAgIGZpbGVNYXJrZXIgPSByZWFkVWludDE2KGRhdGEsIG9mZnNldCk7CiAgICAgIG9mZnNldCArPSAyOwogICAgfQogICAgaWYgKCFmcmFtZSkgewogICAgICB0aHJvdyBuZXcgSnBlZ0Vycm9yKCJKcGVnSW1hZ2UucGFyc2UgLSBubyBmcmFtZSBkYXRhIGZvdW5kLiIpOwogICAgfQogICAgdGhpcy53aWR0aCA9IGZyYW1lLnNhbXBsZXNQZXJMaW5lOwogICAgdGhpcy5oZWlnaHQgPSBmcmFtZS5zY2FuTGluZXM7CiAgICB0aGlzLmpmaWYgPSBqZmlmOwogICAgdGhpcy5hZG9iZSA9IGFkb2JlOwogICAgdGhpcy5jb21wb25lbnRzID0gW107CiAgICBmb3IgKGNvbnN0IGNvbXBvbmVudCBvZiBmcmFtZS5jb21wb25lbnRzKSB7CiAgICAgIGNvbnN0IHF1YW50aXphdGlvblRhYmxlID0gcXVhbnRpemF0aW9uVGFibGVzW2NvbXBvbmVudC5xdWFudGl6YXRpb25JZF07CiAgICAgIGlmIChxdWFudGl6YXRpb25UYWJsZSkgewogICAgICAgIGNvbXBvbmVudC5xdWFudGl6YXRpb25UYWJsZSA9IHF1YW50aXphdGlvblRhYmxlOwogICAgICB9CiAgICAgIHRoaXMuY29tcG9uZW50cy5wdXNoKHsKICAgICAgICBpbmRleDogY29tcG9uZW50LmluZGV4LAogICAgICAgIG91dHB1dDogYnVpbGRDb21wb25lbnREYXRhKGZyYW1lLCBjb21wb25lbnQpLAogICAgICAgIHNjYWxlWDogY29tcG9uZW50LmggLyBmcmFtZS5tYXhILAogICAgICAgIHNjYWxlWTogY29tcG9uZW50LnYgLyBmcmFtZS5tYXhWLAogICAgICAgIGJsb2Nrc1BlckxpbmU6IGNvbXBvbmVudC5ibG9ja3NQZXJMaW5lLAogICAgICAgIGJsb2Nrc1BlckNvbHVtbjogY29tcG9uZW50LmJsb2Nrc1BlckNvbHVtbgogICAgICB9KTsKICAgIH0KICAgIHRoaXMubnVtQ29tcG9uZW50cyA9IHRoaXMuY29tcG9uZW50cy5sZW5ndGg7CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBfZ2V0TGluZWFyaXplZEJsb2NrRGF0YSh3aWR0aCwgaGVpZ2h0LCBpc1NvdXJjZVBERiA9IGZhbHNlKSB7CiAgICBjb25zdCBzY2FsZVggPSB0aGlzLndpZHRoIC8gd2lkdGgsCiAgICAgIHNjYWxlWSA9IHRoaXMuaGVpZ2h0IC8gaGVpZ2h0OwogICAgbGV0IGNvbXBvbmVudCwgY29tcG9uZW50U2NhbGVYLCBjb21wb25lbnRTY2FsZVksIGJsb2Nrc1BlclNjYW5saW5lOwogICAgbGV0IHgsIHksIGksIGosIGs7CiAgICBsZXQgaW5kZXg7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIGxldCBvdXRwdXQ7CiAgICBjb25zdCBudW1Db21wb25lbnRzID0gdGhpcy5jb21wb25lbnRzLmxlbmd0aDsKICAgIGNvbnN0IGRhdGFMZW5ndGggPSB3aWR0aCAqIGhlaWdodCAqIG51bUNvbXBvbmVudHM7CiAgICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGRhdGFMZW5ndGgpOwogICAgY29uc3QgeFNjYWxlQmxvY2tPZmZzZXQgPSBuZXcgVWludDMyQXJyYXkod2lkdGgpOwogICAgY29uc3QgbWFzazNMU0IgPSAweGZmZmZmZmY4OwogICAgbGV0IGxhc3RDb21wb25lbnRTY2FsZVg7CiAgICBmb3IgKGkgPSAwOyBpIDwgbnVtQ29tcG9uZW50czsgaSsrKSB7CiAgICAgIGNvbXBvbmVudCA9IHRoaXMuY29tcG9uZW50c1tpXTsKICAgICAgY29tcG9uZW50U2NhbGVYID0gY29tcG9uZW50LnNjYWxlWCAqIHNjYWxlWDsKICAgICAgY29tcG9uZW50U2NhbGVZID0gY29tcG9uZW50LnNjYWxlWSAqIHNjYWxlWTsKICAgICAgb2Zmc2V0ID0gaTsKICAgICAgb3V0cHV0ID0gY29tcG9uZW50Lm91dHB1dDsKICAgICAgYmxvY2tzUGVyU2NhbmxpbmUgPSBjb21wb25lbnQuYmxvY2tzUGVyTGluZSArIDEgPDwgMzsKICAgICAgaWYgKGNvbXBvbmVudFNjYWxlWCAhPT0gbGFzdENvbXBvbmVudFNjYWxlWCkgewogICAgICAgIGZvciAoeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7CiAgICAgICAgICBqID0gMCB8IHggKiBjb21wb25lbnRTY2FsZVg7CiAgICAgICAgICB4U2NhbGVCbG9ja09mZnNldFt4XSA9IChqICYgbWFzazNMU0IpIDw8IDMgfCBqICYgNzsKICAgICAgICB9CiAgICAgICAgbGFzdENvbXBvbmVudFNjYWxlWCA9IGNvbXBvbmVudFNjYWxlWDsKICAgICAgfQogICAgICBmb3IgKHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHsKICAgICAgICBqID0gMCB8IHkgKiBjb21wb25lbnRTY2FsZVk7CiAgICAgICAgaW5kZXggPSBibG9ja3NQZXJTY2FubGluZSAqIChqICYgbWFzazNMU0IpIHwgKGogJiA3KSA8PCAzOwogICAgICAgIGZvciAoeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7CiAgICAgICAgICBkYXRhW29mZnNldF0gPSBvdXRwdXRbaW5kZXggKyB4U2NhbGVCbG9ja09mZnNldFt4XV07CiAgICAgICAgICBvZmZzZXQgKz0gbnVtQ29tcG9uZW50czsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGxldCB0cmFuc2Zvcm0gPSB0aGlzLl9kZWNvZGVUcmFuc2Zvcm07CiAgICBpZiAoIWlzU291cmNlUERGICYmIG51bUNvbXBvbmVudHMgPT09IDQgJiYgIXRyYW5zZm9ybSkgewogICAgICB0cmFuc2Zvcm0gPSBuZXcgSW50MzJBcnJheShbLTI1NiwgMjU1LCAtMjU2LCAyNTUsIC0yNTYsIDI1NSwgLTI1NiwgMjU1XSk7CiAgICB9CiAgICBpZiAodHJhbnNmb3JtKSB7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBkYXRhTGVuZ3RoOykgewogICAgICAgIGZvciAoaiA9IDAsIGsgPSAwOyBqIDwgbnVtQ29tcG9uZW50czsgaisrLCBpKyssIGsgKz0gMikgewogICAgICAgICAgZGF0YVtpXSA9IChkYXRhW2ldICogdHJhbnNmb3JtW2tdID4+IDgpICsgdHJhbnNmb3JtW2sgKyAxXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBkYXRhOwogIH0KICBnZXQgX2lzQ29sb3JDb252ZXJzaW9uTmVlZGVkKCkgewogICAgaWYgKHRoaXMuYWRvYmUpIHsKICAgICAgcmV0dXJuICEhdGhpcy5hZG9iZS50cmFuc2Zvcm1Db2RlOwogICAgfQogICAgaWYgKHRoaXMubnVtQ29tcG9uZW50cyA9PT0gMykgewogICAgICBpZiAodGhpcy5fY29sb3JUcmFuc2Zvcm0gPT09IDApIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5jb21wb25lbnRzWzBdLmluZGV4ID09PSAweDUyICYmIHRoaXMuY29tcG9uZW50c1sxXS5pbmRleCA9PT0gMHg0NyAmJiB0aGlzLmNvbXBvbmVudHNbMl0uaW5kZXggPT09IDB4NDIpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBpZiAodGhpcy5fY29sb3JUcmFuc2Zvcm0gPT09IDEpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIF9jb252ZXJ0WWNjVG9SZ2IoZGF0YSkgewogICAgbGV0IFksIENiLCBDcjsKICAgIGZvciAobGV0IGkgPSAwLCBsZW5ndGggPSBkYXRhLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSArPSAzKSB7CiAgICAgIFkgPSBkYXRhW2ldOwogICAgICBDYiA9IGRhdGFbaSArIDFdOwogICAgICBDciA9IGRhdGFbaSArIDJdOwogICAgICBkYXRhW2ldID0gWSAtIDE3OS40NTYgKyAxLjQwMiAqIENyOwogICAgICBkYXRhW2kgKyAxXSA9IFkgKyAxMzUuNDU5IC0gMC4zNDQgKiBDYiAtIDAuNzE0ICogQ3I7CiAgICAgIGRhdGFbaSArIDJdID0gWSAtIDIyNi44MTYgKyAxLjc3MiAqIENiOwogICAgfQogICAgcmV0dXJuIGRhdGE7CiAgfQogIF9jb252ZXJ0WWNjVG9SZ2JhKGRhdGEsIG91dCkgewogICAgZm9yIChsZXQgaSA9IDAsIGogPSAwLCBsZW5ndGggPSBkYXRhLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSArPSAzLCBqICs9IDQpIHsKICAgICAgY29uc3QgWSA9IGRhdGFbaV07CiAgICAgIGNvbnN0IENiID0gZGF0YVtpICsgMV07CiAgICAgIGNvbnN0IENyID0gZGF0YVtpICsgMl07CiAgICAgIG91dFtqXSA9IFkgLSAxNzkuNDU2ICsgMS40MDIgKiBDcjsKICAgICAgb3V0W2ogKyAxXSA9IFkgKyAxMzUuNDU5IC0gMC4zNDQgKiBDYiAtIDAuNzE0ICogQ3I7CiAgICAgIG91dFtqICsgMl0gPSBZIC0gMjI2LjgxNiArIDEuNzcyICogQ2I7CiAgICAgIG91dFtqICsgM10gPSAyNTU7CiAgICB9CiAgICByZXR1cm4gb3V0OwogIH0KICBfY29udmVydFljY2tUb1JnYihkYXRhKSB7CiAgICB0aGlzLl9jb252ZXJ0WWNja1RvQ215ayhkYXRhKTsKICAgIHJldHVybiB0aGlzLl9jb252ZXJ0Q215a1RvUmdiKGRhdGEpOwogIH0KICBfY29udmVydFljY2tUb1JnYmEoZGF0YSkgewogICAgdGhpcy5fY29udmVydFljY2tUb0NteWsoZGF0YSk7CiAgICByZXR1cm4gdGhpcy5fY29udmVydENteWtUb1JnYmEoZGF0YSk7CiAgfQogIF9jb252ZXJ0WWNja1RvQ215ayhkYXRhKSB7CiAgICBsZXQgWSwgQ2IsIENyOwogICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpICs9IDQpIHsKICAgICAgWSA9IGRhdGFbaV07CiAgICAgIENiID0gZGF0YVtpICsgMV07CiAgICAgIENyID0gZGF0YVtpICsgMl07CiAgICAgIGRhdGFbaV0gPSA0MzQuNDU2IC0gWSAtIDEuNDAyICogQ3I7CiAgICAgIGRhdGFbaSArIDFdID0gMTE5LjU0MSAtIFkgKyAwLjM0NCAqIENiICsgMC43MTQgKiBDcjsKICAgICAgZGF0YVtpICsgMl0gPSA0ODEuODE2IC0gWSAtIDEuNzcyICogQ2I7CiAgICB9CiAgICByZXR1cm4gZGF0YTsKICB9CiAgX2NvbnZlcnRDbXlrVG9SZ2IoZGF0YSkgewogICAgY29uc3QgY291bnQgPSBkYXRhLmxlbmd0aCAvIDQ7CiAgICBDb2xvclNwYWNlVXRpbHMuY215ay5nZXRSZ2JCdWZmZXIoZGF0YSwgMCwgY291bnQsIGRhdGEsIDAsIDgsIDApOwogICAgcmV0dXJuIGRhdGEuc3ViYXJyYXkoMCwgY291bnQgKiAzKTsKICB9CiAgX2NvbnZlcnRDbXlrVG9SZ2JhKGRhdGEpIHsKICAgIENvbG9yU3BhY2VVdGlscy5jbXlrLmdldFJnYkJ1ZmZlcihkYXRhLCAwLCBkYXRhLmxlbmd0aCAvIDQsIGRhdGEsIDAsIDgsIDEpOwogICAgaWYgKENvbG9yU3BhY2VVdGlscy5jbXlrIGluc3RhbmNlb2YgRGV2aWNlQ215a0NTKSB7CiAgICAgIGZvciAobGV0IGkgPSAzLCBpaSA9IGRhdGEubGVuZ3RoOyBpIDwgaWk7IGkgKz0gNCkgewogICAgICAgIGRhdGFbaV0gPSAyNTU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBkYXRhOwogIH0KICBnZXREYXRhKHsKICAgIHdpZHRoLAogICAgaGVpZ2h0LAogICAgZm9yY2VSR0JBID0gZmFsc2UsCiAgICBmb3JjZVJHQiA9IGZhbHNlLAogICAgaXNTb3VyY2VQREYgPSBmYWxzZQogIH0pIHsKICAgIGlmICh0aGlzLm51bUNvbXBvbmVudHMgPiA0KSB7CiAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoIlVuc3VwcG9ydGVkIGNvbG9yIG1vZGUiKTsKICAgIH0KICAgIGNvbnN0IGRhdGEgPSB0aGlzLl9nZXRMaW5lYXJpemVkQmxvY2tEYXRhKHdpZHRoLCBoZWlnaHQsIGlzU291cmNlUERGKTsKICAgIGlmICh0aGlzLm51bUNvbXBvbmVudHMgPT09IDEgJiYgKGZvcmNlUkdCQSB8fCBmb3JjZVJHQikpIHsKICAgICAgY29uc3QgbGVuID0gZGF0YS5sZW5ndGggKiAoZm9yY2VSR0JBID8gNCA6IDMpOwogICAgICBjb25zdCByZ2JhRGF0YSA9IG5ldyBVaW50OENsYW1wZWRBcnJheShsZW4pOwogICAgICBsZXQgb2Zmc2V0ID0gMDsKICAgICAgaWYgKGZvcmNlUkdCQSkgewogICAgICAgIGdyYXlUb1JHQkEoZGF0YSwgbmV3IFVpbnQzMkFycmF5KHJnYmFEYXRhLmJ1ZmZlcikpOwogICAgICB9IGVsc2UgewogICAgICAgIGZvciAoY29uc3QgZ3JheUNvbG9yIG9mIGRhdGEpIHsKICAgICAgICAgIHJnYmFEYXRhW29mZnNldCsrXSA9IGdyYXlDb2xvcjsKICAgICAgICAgIHJnYmFEYXRhW29mZnNldCsrXSA9IGdyYXlDb2xvcjsKICAgICAgICAgIHJnYmFEYXRhW29mZnNldCsrXSA9IGdyYXlDb2xvcjsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHJnYmFEYXRhOwogICAgfSBlbHNlIGlmICh0aGlzLm51bUNvbXBvbmVudHMgPT09IDMgJiYgdGhpcy5faXNDb2xvckNvbnZlcnNpb25OZWVkZWQpIHsKICAgICAgaWYgKGZvcmNlUkdCQSkgewogICAgICAgIGNvbnN0IHJnYmFEYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGRhdGEubGVuZ3RoIC8gMyAqIDQpOwogICAgICAgIHJldHVybiB0aGlzLl9jb252ZXJ0WWNjVG9SZ2JhKGRhdGEsIHJnYmFEYXRhKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5fY29udmVydFljY1RvUmdiKGRhdGEpOwogICAgfSBlbHNlIGlmICh0aGlzLm51bUNvbXBvbmVudHMgPT09IDQpIHsKICAgICAgaWYgKHRoaXMuX2lzQ29sb3JDb252ZXJzaW9uTmVlZGVkKSB7CiAgICAgICAgaWYgKGZvcmNlUkdCQSkgewogICAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnZlcnRZY2NrVG9SZ2JhKGRhdGEpOwogICAgICAgIH0KICAgICAgICBpZiAoZm9yY2VSR0IpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9jb252ZXJ0WWNja1RvUmdiKGRhdGEpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpcy5fY29udmVydFljY2tUb0NteWsoZGF0YSk7CiAgICAgIH0gZWxzZSBpZiAoZm9yY2VSR0JBKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnZlcnRDbXlrVG9SZ2JhKGRhdGEpOwogICAgICB9IGVsc2UgaWYgKGZvcmNlUkdCKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnZlcnRDbXlrVG9SZ2IoZGF0YSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBkYXRhOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvanBlZ19zdHJlYW0uanMKCgoKCmNsYXNzIEpwZWdTdHJlYW0gZXh0ZW5kcyBEZWNvZGVTdHJlYW0gewogIHN0YXRpYyAjaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQgPSBGZWF0dXJlVGVzdC5pc0ltYWdlRGVjb2RlclN1cHBvcnRlZDsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIG1heWJlTGVuZ3RoLCBwYXJhbXMpIHsKICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy5kaWN0ID0gc3RyZWFtLmRpY3Q7CiAgICB0aGlzLm1heWJlTGVuZ3RoID0gbWF5YmVMZW5ndGg7CiAgICB0aGlzLnBhcmFtcyA9IHBhcmFtczsKICB9CiAgc3RhdGljIGdldCBjYW5Vc2VJbWFnZURlY29kZXIoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJjYW5Vc2VJbWFnZURlY29kZXIiLCB0aGlzLiNpc0ltYWdlRGVjb2RlclN1cHBvcnRlZCA/IEltYWdlRGVjb2Rlci5pc1R5cGVTdXBwb3J0ZWQoImltYWdlL2pwZWciKSA6IFByb21pc2UucmVzb2x2ZShmYWxzZSkpOwogIH0KICBzdGF0aWMgc2V0T3B0aW9ucyh7CiAgICBpc0ltYWdlRGVjb2RlclN1cHBvcnRlZCA9IGZhbHNlCiAgfSkgewogICAgdGhpcy4jaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQgPSBpc0ltYWdlRGVjb2RlclN1cHBvcnRlZDsKICB9CiAgZ2V0IGJ5dGVzKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiYnl0ZXMiLCB0aGlzLnN0cmVhbS5nZXRCeXRlcyh0aGlzLm1heWJlTGVuZ3RoKSk7CiAgfQogIGVuc3VyZUJ1ZmZlcihyZXF1ZXN0ZWQpIHt9CiAgcmVhZEJsb2NrKCkgewogICAgdGhpcy5kZWNvZGVJbWFnZSgpOwogIH0KICBnZXQganBlZ09wdGlvbnMoKSB7CiAgICBjb25zdCBqcGVnT3B0aW9ucyA9IHsKICAgICAgZGVjb2RlVHJhbnNmb3JtOiB1bmRlZmluZWQsCiAgICAgIGNvbG9yVHJhbnNmb3JtOiB1bmRlZmluZWQKICAgIH07CiAgICBjb25zdCBkZWNvZGVBcnIgPSB0aGlzLmRpY3QuZ2V0QXJyYXkoIkQiLCAiRGVjb2RlIik7CiAgICBpZiAoKHRoaXMuZm9yY2VSR0JBIHx8IHRoaXMuZm9yY2VSR0IpICYmIEFycmF5LmlzQXJyYXkoZGVjb2RlQXJyKSkgewogICAgICBjb25zdCBiaXRzUGVyQ29tcG9uZW50ID0gdGhpcy5kaWN0LmdldCgiQlBDIiwgIkJpdHNQZXJDb21wb25lbnQiKSB8fCA4OwogICAgICBjb25zdCBkZWNvZGVBcnJMZW5ndGggPSBkZWNvZGVBcnIubGVuZ3RoOwogICAgICBjb25zdCB0cmFuc2Zvcm0gPSBuZXcgSW50MzJBcnJheShkZWNvZGVBcnJMZW5ndGgpOwogICAgICBsZXQgdHJhbnNmb3JtTmVlZGVkID0gZmFsc2U7CiAgICAgIGNvbnN0IG1heFZhbHVlID0gKDEgPDwgYml0c1BlckNvbXBvbmVudCkgLSAxOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRlY29kZUFyckxlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgdHJhbnNmb3JtW2ldID0gKGRlY29kZUFycltpICsgMV0gLSBkZWNvZGVBcnJbaV0pICogMjU2IHwgMDsKICAgICAgICB0cmFuc2Zvcm1baSArIDFdID0gZGVjb2RlQXJyW2ldICogbWF4VmFsdWUgfCAwOwogICAgICAgIGlmICh0cmFuc2Zvcm1baV0gIT09IDI1NiB8fCB0cmFuc2Zvcm1baSArIDFdICE9PSAwKSB7CiAgICAgICAgICB0cmFuc2Zvcm1OZWVkZWQgPSB0cnVlOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAodHJhbnNmb3JtTmVlZGVkKSB7CiAgICAgICAganBlZ09wdGlvbnMuZGVjb2RlVHJhbnNmb3JtID0gdHJhbnNmb3JtOwogICAgICB9CiAgICB9CiAgICBpZiAodGhpcy5wYXJhbXMgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGNvbnN0IGNvbG9yVHJhbnNmb3JtID0gdGhpcy5wYXJhbXMuZ2V0KCJDb2xvclRyYW5zZm9ybSIpOwogICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihjb2xvclRyYW5zZm9ybSkpIHsKICAgICAgICBqcGVnT3B0aW9ucy5jb2xvclRyYW5zZm9ybSA9IGNvbG9yVHJhbnNmb3JtOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJqcGVnT3B0aW9ucyIsIGpwZWdPcHRpb25zKTsKICB9CiAgI3NraXBVc2VsZXNzQnl0ZXMoZGF0YSkgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZGF0YS5sZW5ndGggLSAxOyBpIDwgaWk7IGkrKykgewogICAgICBpZiAoZGF0YVtpXSA9PT0gMHhmZiAmJiBkYXRhW2kgKyAxXSA9PT0gMHhkOCkgewogICAgICAgIGlmIChpID4gMCkgewogICAgICAgICAgZGF0YSA9IGRhdGEuc3ViYXJyYXkoaSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZGF0YTsKICB9CiAgZGVjb2RlSW1hZ2UoYnl0ZXMpIHsKICAgIGlmICh0aGlzLmVvZikgewogICAgICByZXR1cm4gdGhpcy5idWZmZXI7CiAgICB9CiAgICBieXRlcyA9IHRoaXMuI3NraXBVc2VsZXNzQnl0ZXMoYnl0ZXMgfHwgdGhpcy5ieXRlcyk7CiAgICBjb25zdCBqcGVnSW1hZ2UgPSBuZXcgSnBlZ0ltYWdlKHRoaXMuanBlZ09wdGlvbnMpOwogICAganBlZ0ltYWdlLnBhcnNlKGJ5dGVzKTsKICAgIGNvbnN0IGRhdGEgPSBqcGVnSW1hZ2UuZ2V0RGF0YSh7CiAgICAgIHdpZHRoOiB0aGlzLmRyYXdXaWR0aCwKICAgICAgaGVpZ2h0OiB0aGlzLmRyYXdIZWlnaHQsCiAgICAgIGZvcmNlUkdCQTogdGhpcy5mb3JjZVJHQkEsCiAgICAgIGZvcmNlUkdCOiB0aGlzLmZvcmNlUkdCLAogICAgICBpc1NvdXJjZVBERjogdHJ1ZQogICAgfSk7CiAgICB0aGlzLmJ1ZmZlciA9IGRhdGE7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGRhdGEubGVuZ3RoOwogICAgdGhpcy5lb2YgPSB0cnVlOwogICAgcmV0dXJuIHRoaXMuYnVmZmVyOwogIH0KICBnZXQgY2FuQXN5bmNEZWNvZGVJbWFnZUZyb21CdWZmZXIoKSB7CiAgICByZXR1cm4gdGhpcy5zdHJlYW0uaXNBc3luYzsKICB9CiAgYXN5bmMgZ2V0VHJhbnNmZXJhYmxlSW1hZ2UoKSB7CiAgICBpZiAoIShhd2FpdCBKcGVnU3RyZWFtLmNhblVzZUltYWdlRGVjb2RlcikpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBqcGVnT3B0aW9ucyA9IHRoaXMuanBlZ09wdGlvbnM7CiAgICBpZiAoanBlZ09wdGlvbnMuZGVjb2RlVHJhbnNmb3JtKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgbGV0IGRlY29kZXI7CiAgICB0cnkgewogICAgICBjb25zdCBieXRlcyA9IHRoaXMuY2FuQXN5bmNEZWNvZGVJbWFnZUZyb21CdWZmZXIgJiYgKGF3YWl0IHRoaXMuc3RyZWFtLmFzeW5jR2V0Qnl0ZXMoKSkgfHwgdGhpcy5ieXRlczsKICAgICAgaWYgKCFieXRlcykgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGxldCBkYXRhID0gdGhpcy4jc2tpcFVzZWxlc3NCeXRlcyhieXRlcyk7CiAgICAgIGNvbnN0IHVzZUltYWdlRGVjb2RlciA9IEpwZWdJbWFnZS5jYW5Vc2VJbWFnZURlY29kZXIoZGF0YSwganBlZ09wdGlvbnMuY29sb3JUcmFuc2Zvcm0pOwogICAgICBpZiAoIXVzZUltYWdlRGVjb2RlcikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGlmICh1c2VJbWFnZURlY29kZXIuZXhpZlN0YXJ0KSB7CiAgICAgICAgZGF0YSA9IGRhdGEuc2xpY2UoKTsKICAgICAgICBkYXRhLmZpbGwoMHgwMCwgdXNlSW1hZ2VEZWNvZGVyLmV4aWZTdGFydCwgdXNlSW1hZ2VEZWNvZGVyLmV4aWZFbmQpOwogICAgICB9CiAgICAgIGRlY29kZXIgPSBuZXcgSW1hZ2VEZWNvZGVyKHsKICAgICAgICBkYXRhLAogICAgICAgIHR5cGU6ICJpbWFnZS9qcGVnIiwKICAgICAgICBwcmVmZXJBbmltYXRpb246IGZhbHNlCiAgICAgIH0pOwogICAgICByZXR1cm4gKGF3YWl0IGRlY29kZXIuZGVjb2RlKCkpLmltYWdlOwogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIHdhcm4oYGdldFRyYW5zZmVyYWJsZUltYWdlIC0gZmFpbGVkOiAiJHtyZWFzb259Ii5gKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9IGZpbmFsbHkgewogICAgICBkZWNvZGVyPy5jbG9zZSgpOwogICAgfQogIH0KICBnZXQgaXNJbWFnZVN0cmVhbSgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KfQoKOy8vIC4vZXh0ZXJuYWwvb3BlbmpwZWcvb3BlbmpwZWcuanMKYXN5bmMgZnVuY3Rpb24gT3BlbkpQRUcobW9kdWxlQXJnID0ge30pIHsKICB2YXIgbW9kdWxlUnRuOwogIHZhciBNb2R1bGUgPSBtb2R1bGVBcmc7CiAgdmFyIEVOVklST05NRU5UX0lTX1dFQiA9IHRydWU7CiAgdmFyIEVOVklST05NRU5UX0lTX1dPUktFUiA9IGZhbHNlOwogIHZhciBhcmd1bWVudHNfID0gW107CiAgdmFyIHRoaXNQcm9ncmFtID0gIi4vdGhpcy5wcm9ncmFtIjsKICB2YXIgcXVpdF8gPSAoc3RhdHVzLCB0b1Rocm93KSA9PiB7CiAgICB0aHJvdyB0b1Rocm93OwogIH07CiAgdmFyIF9zY3JpcHROYW1lID0gaW1wb3J0Lm1ldGEudXJsOwogIHZhciBzY3JpcHREaXJlY3RvcnkgPSAiIjsKICB2YXIgcmVhZEFzeW5jLCByZWFkQmluYXJ5OwogIGlmIChFTlZJUk9OTUVOVF9JU19XRUIgfHwgRU5WSVJPTk1FTlRfSVNfV09SS0VSKSB7CiAgICB0cnkgewogICAgICBzY3JpcHREaXJlY3RvcnkgPSBuZXcgVVJMKCIuIiwgX3NjcmlwdE5hbWUpLmhyZWY7CiAgICB9IGNhdGNoIHt9CiAgICByZWFkQXN5bmMgPSBhc3luYyB1cmwgPT4gewogICAgICB2YXIgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh1cmwsIHsKICAgICAgICBjcmVkZW50aWFsczogInNhbWUtb3JpZ2luIgogICAgICB9KTsKICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7CiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmFycmF5QnVmZmVyKCk7CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IEVycm9yKHJlc3BvbnNlLnN0YXR1cyArICIgOiAiICsgcmVzcG9uc2UudXJsKTsKICAgIH07CiAgfSBlbHNlIHt9CiAgdmFyIG91dCA9IGNvbnNvbGUubG9nLmJpbmQoY29uc29sZSk7CiAgdmFyIGVyciA9IGNvbnNvbGUuZXJyb3IuYmluZChjb25zb2xlKTsKICB2YXIgd2FzbUJpbmFyeTsKICB2YXIgQUJPUlQgPSBmYWxzZTsKICB2YXIgRVhJVFNUQVRVUzsKICB2YXIgcmVhZHlQcm9taXNlUmVzb2x2ZSwgcmVhZHlQcm9taXNlUmVqZWN0OwogIHZhciB3YXNtTWVtb3J5OwogIHZhciBIRUFQOCwgSEVBUFU4LCBIRUFQMTYsIEhFQVBVMTYsIEhFQVAzMiwgSEVBUFUzMiwgSEVBUEYzMiwgSEVBUEY2NDsKICB2YXIgSEVBUDY0LCBIRUFQVTY0OwogIHZhciBydW50aW1lSW5pdGlhbGl6ZWQgPSBmYWxzZTsKICBmdW5jdGlvbiB1cGRhdGVNZW1vcnlWaWV3cygpIHsKICAgIHZhciBiID0gd2FzbU1lbW9yeS5idWZmZXI7CiAgICBIRUFQOCA9IG5ldyBJbnQ4QXJyYXkoYik7CiAgICBIRUFQMTYgPSBuZXcgSW50MTZBcnJheShiKTsKICAgIEhFQVBVOCA9IG5ldyBVaW50OEFycmF5KGIpOwogICAgSEVBUFUxNiA9IG5ldyBVaW50MTZBcnJheShiKTsKICAgIEhFQVAzMiA9IG5ldyBJbnQzMkFycmF5KGIpOwogICAgSEVBUFUzMiA9IG5ldyBVaW50MzJBcnJheShiKTsKICAgIEhFQVBGMzIgPSBuZXcgRmxvYXQzMkFycmF5KGIpOwogICAgSEVBUEY2NCA9IG5ldyBGbG9hdDY0QXJyYXkoYik7CiAgICBIRUFQNjQgPSBuZXcgQmlnSW50NjRBcnJheShiKTsKICAgIEhFQVBVNjQgPSBuZXcgQmlnVWludDY0QXJyYXkoYik7CiAgfQogIGZ1bmN0aW9uIHByZVJ1bigpIHsKICAgIGlmIChNb2R1bGVbInByZVJ1biJdKSB7CiAgICAgIGlmICh0eXBlb2YgTW9kdWxlWyJwcmVSdW4iXSA9PSAiZnVuY3Rpb24iKSBNb2R1bGVbInByZVJ1biJdID0gW01vZHVsZVsicHJlUnVuIl1dOwogICAgICB3aGlsZSAoTW9kdWxlWyJwcmVSdW4iXS5sZW5ndGgpIHsKICAgICAgICBhZGRPblByZVJ1bihNb2R1bGVbInByZVJ1biJdLnNoaWZ0KCkpOwogICAgICB9CiAgICB9CiAgICBjYWxsUnVudGltZUNhbGxiYWNrcyhvblByZVJ1bnMpOwogIH0KICBmdW5jdGlvbiBpbml0UnVudGltZSgpIHsKICAgIHJ1bnRpbWVJbml0aWFsaXplZCA9IHRydWU7CiAgICB3YXNtRXhwb3J0c1sicyJdKCk7CiAgfQogIGZ1bmN0aW9uIHBvc3RSdW4oKSB7CiAgICBpZiAoTW9kdWxlWyJwb3N0UnVuIl0pIHsKICAgICAgaWYgKHR5cGVvZiBNb2R1bGVbInBvc3RSdW4iXSA9PSAiZnVuY3Rpb24iKSBNb2R1bGVbInBvc3RSdW4iXSA9IFtNb2R1bGVbInBvc3RSdW4iXV07CiAgICAgIHdoaWxlIChNb2R1bGVbInBvc3RSdW4iXS5sZW5ndGgpIHsKICAgICAgICBhZGRPblBvc3RSdW4oTW9kdWxlWyJwb3N0UnVuIl0uc2hpZnQoKSk7CiAgICAgIH0KICAgIH0KICAgIGNhbGxSdW50aW1lQ2FsbGJhY2tzKG9uUG9zdFJ1bnMpOwogIH0KICBmdW5jdGlvbiBhYm9ydCh3aGF0KSB7CiAgICBNb2R1bGVbIm9uQWJvcnQiXT8uKHdoYXQpOwogICAgd2hhdCA9ICJBYm9ydGVkKCIgKyB3aGF0ICsgIikiOwogICAgZXJyKHdoYXQpOwogICAgQUJPUlQgPSB0cnVlOwogICAgd2hhdCArPSAiLiBCdWlsZCB3aXRoIC1zQVNTRVJUSU9OUyBmb3IgbW9yZSBpbmZvLiI7CiAgICB2YXIgZSA9IG5ldyBXZWJBc3NlbWJseS5SdW50aW1lRXJyb3Iod2hhdCk7CiAgICByZWFkeVByb21pc2VSZWplY3Q/LihlKTsKICAgIHRocm93IGU7CiAgfQogIHZhciB3YXNtQmluYXJ5RmlsZTsKICBmdW5jdGlvbiBnZXRXYXNtSW1wb3J0cygpIHsKICAgIHJldHVybiB7CiAgICAgIGE6IHdhc21JbXBvcnRzCiAgICB9OwogIH0KICBhc3luYyBmdW5jdGlvbiBjcmVhdGVXYXNtKCkgewogICAgZnVuY3Rpb24gcmVjZWl2ZUluc3RhbmNlKGluc3RhbmNlLCBtb2R1bGUpIHsKICAgICAgd2FzbUV4cG9ydHMgPSBpbnN0YW5jZS5leHBvcnRzOwogICAgICB3YXNtTWVtb3J5ID0gd2FzbUV4cG9ydHNbInIiXTsKICAgICAgdXBkYXRlTWVtb3J5Vmlld3MoKTsKICAgICAgYXNzaWduV2FzbUV4cG9ydHMod2FzbUV4cG9ydHMpOwogICAgICByZXR1cm4gd2FzbUV4cG9ydHM7CiAgICB9CiAgICB2YXIgaW5mbyA9IGdldFdhc21JbXBvcnRzKCk7CiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gewogICAgICBNb2R1bGVbImluc3RhbnRpYXRlV2FzbSJdKGluZm8sIChtb2QsIGluc3QpID0+IHsKICAgICAgICByZXNvbHZlKHJlY2VpdmVJbnN0YW5jZShtb2QsIGluc3QpKTsKICAgICAgfSk7CiAgICB9KTsKICB9CiAgY2xhc3MgRXhpdFN0YXR1cyB7CiAgICBuYW1lID0gIkV4aXRTdGF0dXMiOwogICAgY29uc3RydWN0b3Ioc3RhdHVzKSB7CiAgICAgIHRoaXMubWVzc2FnZSA9IGBQcm9ncmFtIHRlcm1pbmF0ZWQgd2l0aCBleGl0KCR7c3RhdHVzfSlgOwogICAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgIH0KICB9CiAgdmFyIGNhbGxSdW50aW1lQ2FsbGJhY2tzID0gY2FsbGJhY2tzID0+IHsKICAgIHdoaWxlIChjYWxsYmFja3MubGVuZ3RoID4gMCkgewogICAgICBjYWxsYmFja3Muc2hpZnQoKShNb2R1bGUpOwogICAgfQogIH07CiAgdmFyIG9uUG9zdFJ1bnMgPSBbXTsKICB2YXIgYWRkT25Qb3N0UnVuID0gY2IgPT4gb25Qb3N0UnVucy5wdXNoKGNiKTsKICB2YXIgb25QcmVSdW5zID0gW107CiAgdmFyIGFkZE9uUHJlUnVuID0gY2IgPT4gb25QcmVSdW5zLnB1c2goY2IpOwogIHZhciBub0V4aXRSdW50aW1lID0gdHJ1ZTsKICB2YXIgX19hYm9ydF9qcyA9ICgpID0+IGFib3J0KCIiKTsKICB2YXIgcnVudGltZUtlZXBhbGl2ZUNvdW50ZXIgPSAwOwogIHZhciBfX2Vtc2NyaXB0ZW5fcnVudGltZV9rZWVwYWxpdmVfY2xlYXIgPSAoKSA9PiB7CiAgICBub0V4aXRSdW50aW1lID0gZmFsc2U7CiAgICBydW50aW1lS2VlcGFsaXZlQ291bnRlciA9IDA7CiAgfTsKICB2YXIgdGltZXJzID0ge307CiAgdmFyIGhhbmRsZUV4Y2VwdGlvbiA9IGUgPT4gewogICAgaWYgKGUgaW5zdGFuY2VvZiBFeGl0U3RhdHVzIHx8IGUgPT0gInVud2luZCIpIHsKICAgICAgcmV0dXJuIEVYSVRTVEFUVVM7CiAgICB9CiAgICBxdWl0XygxLCBlKTsKICB9OwogIHZhciBrZWVwUnVudGltZUFsaXZlID0gKCkgPT4gbm9FeGl0UnVudGltZSB8fCBydW50aW1lS2VlcGFsaXZlQ291bnRlciA+IDA7CiAgdmFyIF9wcm9jX2V4aXQgPSBjb2RlID0+IHsKICAgIEVYSVRTVEFUVVMgPSBjb2RlOwogICAgaWYgKCFrZWVwUnVudGltZUFsaXZlKCkpIHsKICAgICAgTW9kdWxlWyJvbkV4aXQiXT8uKGNvZGUpOwogICAgICBBQk9SVCA9IHRydWU7CiAgICB9CiAgICBxdWl0Xyhjb2RlLCBuZXcgRXhpdFN0YXR1cyhjb2RlKSk7CiAgfTsKICB2YXIgZXhpdEpTID0gKHN0YXR1cywgaW1wbGljaXQpID0+IHsKICAgIEVYSVRTVEFUVVMgPSBzdGF0dXM7CiAgICBfcHJvY19leGl0KHN0YXR1cyk7CiAgfTsKICB2YXIgX2V4aXQgPSBleGl0SlM7CiAgdmFyIG1heWJlRXhpdCA9ICgpID0+IHsKICAgIGlmICgha2VlcFJ1bnRpbWVBbGl2ZSgpKSB7CiAgICAgIHRyeSB7CiAgICAgICAgX2V4aXQoRVhJVFNUQVRVUyk7CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBoYW5kbGVFeGNlcHRpb24oZSk7CiAgICAgIH0KICAgIH0KICB9OwogIHZhciBjYWxsVXNlckNhbGxiYWNrID0gZnVuYyA9PiB7CiAgICBpZiAoQUJPUlQpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdHJ5IHsKICAgICAgZnVuYygpOwogICAgICBtYXliZUV4aXQoKTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgaGFuZGxlRXhjZXB0aW9uKGUpOwogICAgfQogIH07CiAgdmFyIF9lbXNjcmlwdGVuX2dldF9ub3cgPSAoKSA9PiBwZXJmb3JtYW5jZS5ub3coKTsKICB2YXIgX19zZXRpdGltZXJfanMgPSAod2hpY2gsIHRpbWVvdXRfbXMpID0+IHsKICAgIGlmICh0aW1lcnNbd2hpY2hdKSB7CiAgICAgIGNsZWFyVGltZW91dCh0aW1lcnNbd2hpY2hdLmlkKTsKICAgICAgZGVsZXRlIHRpbWVyc1t3aGljaF07CiAgICB9CiAgICBpZiAoIXRpbWVvdXRfbXMpIHJldHVybiAwOwogICAgdmFyIGlkID0gc2V0VGltZW91dCgoKSA9PiB7CiAgICAgIGRlbGV0ZSB0aW1lcnNbd2hpY2hdOwogICAgICBjYWxsVXNlckNhbGxiYWNrKCgpID0+IF9fZW1zY3JpcHRlbl90aW1lb3V0KHdoaWNoLCBfZW1zY3JpcHRlbl9nZXRfbm93KCkpKTsKICAgIH0sIHRpbWVvdXRfbXMpOwogICAgdGltZXJzW3doaWNoXSA9IHsKICAgICAgaWQsCiAgICAgIHRpbWVvdXRfbXMKICAgIH07CiAgICByZXR1cm4gMDsKICB9OwogIGZ1bmN0aW9uIF9jb3B5X3BpeGVsc18xKGNvbXBHX3B0ciwgbmJfcGl4ZWxzKSB7CiAgICBjb21wR19wdHIgPj49IDI7CiAgICBjb25zdCBpbWFnZURhdGEgPSBNb2R1bGUuaW1hZ2VEYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KG5iX3BpeGVscyk7CiAgICBjb25zdCBjb21wRyA9IEhFQVAzMi5zdWJhcnJheShjb21wR19wdHIsIGNvbXBHX3B0ciArIG5iX3BpeGVscyk7CiAgICBpbWFnZURhdGEuc2V0KGNvbXBHKTsKICB9CiAgZnVuY3Rpb24gX2NvcHlfcGl4ZWxzXzMoY29tcFJfcHRyLCBjb21wR19wdHIsIGNvbXBCX3B0ciwgbmJfcGl4ZWxzKSB7CiAgICBjb21wUl9wdHIgPj49IDI7CiAgICBjb21wR19wdHIgPj49IDI7CiAgICBjb21wQl9wdHIgPj49IDI7CiAgICBjb25zdCBpbWFnZURhdGEgPSBNb2R1bGUuaW1hZ2VEYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KG5iX3BpeGVscyAqIDMpOwogICAgY29uc3QgY29tcFIgPSBIRUFQMzIuc3ViYXJyYXkoY29tcFJfcHRyLCBjb21wUl9wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEcgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEdfcHRyLCBjb21wR19wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEIgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEJfcHRyLCBjb21wQl9wdHIgKyBuYl9waXhlbHMpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuYl9waXhlbHM7IGkrKykgewogICAgICBpbWFnZURhdGFbMyAqIGldID0gY29tcFJbaV07CiAgICAgIGltYWdlRGF0YVszICogaSArIDFdID0gY29tcEdbaV07CiAgICAgIGltYWdlRGF0YVszICogaSArIDJdID0gY29tcEJbaV07CiAgICB9CiAgfQogIGZ1bmN0aW9uIF9jb3B5X3BpeGVsc180KGNvbXBSX3B0ciwgY29tcEdfcHRyLCBjb21wQl9wdHIsIGNvbXBBX3B0ciwgbmJfcGl4ZWxzKSB7CiAgICBjb21wUl9wdHIgPj49IDI7CiAgICBjb21wR19wdHIgPj49IDI7CiAgICBjb21wQl9wdHIgPj49IDI7CiAgICBjb21wQV9wdHIgPj49IDI7CiAgICBjb25zdCBpbWFnZURhdGEgPSBNb2R1bGUuaW1hZ2VEYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KG5iX3BpeGVscyAqIDQpOwogICAgY29uc3QgY29tcFIgPSBIRUFQMzIuc3ViYXJyYXkoY29tcFJfcHRyLCBjb21wUl9wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEcgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEdfcHRyLCBjb21wR19wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEIgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEJfcHRyLCBjb21wQl9wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEEgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEFfcHRyLCBjb21wQV9wdHIgKyBuYl9waXhlbHMpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuYl9waXhlbHM7IGkrKykgewogICAgICBpbWFnZURhdGFbNCAqIGldID0gY29tcFJbaV07CiAgICAgIGltYWdlRGF0YVs0ICogaSArIDFdID0gY29tcEdbaV07CiAgICAgIGltYWdlRGF0YVs0ICogaSArIDJdID0gY29tcEJbaV07CiAgICAgIGltYWdlRGF0YVs0ICogaSArIDNdID0gY29tcEFbaV07CiAgICB9CiAgfQogIHZhciBnZXRIZWFwTWF4ID0gKCkgPT4gMjE0NzQ4MzY0ODsKICB2YXIgYWxpZ25NZW1vcnkgPSAoc2l6ZSwgYWxpZ25tZW50KSA9PiBNYXRoLmNlaWwoc2l6ZSAvIGFsaWdubWVudCkgKiBhbGlnbm1lbnQ7CiAgdmFyIGdyb3dNZW1vcnkgPSBzaXplID0+IHsKICAgIHZhciBvbGRIZWFwU2l6ZSA9IHdhc21NZW1vcnkuYnVmZmVyLmJ5dGVMZW5ndGg7CiAgICB2YXIgcGFnZXMgPSAoc2l6ZSAtIG9sZEhlYXBTaXplICsgNjU1MzUpIC8gNjU1MzYgfCAwOwogICAgdHJ5IHsKICAgICAgd2FzbU1lbW9yeS5ncm93KHBhZ2VzKTsKICAgICAgdXBkYXRlTWVtb3J5Vmlld3MoKTsKICAgICAgcmV0dXJuIDE7CiAgICB9IGNhdGNoIChlKSB7fQogIH07CiAgdmFyIF9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwID0gcmVxdWVzdGVkU2l6ZSA9PiB7CiAgICB2YXIgb2xkU2l6ZSA9IEhFQVBVOC5sZW5ndGg7CiAgICByZXF1ZXN0ZWRTaXplID4+Pj0gMDsKICAgIHZhciBtYXhIZWFwU2l6ZSA9IGdldEhlYXBNYXgoKTsKICAgIGlmIChyZXF1ZXN0ZWRTaXplID4gbWF4SGVhcFNpemUpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgZm9yICh2YXIgY3V0RG93biA9IDE7IGN1dERvd24gPD0gNDsgY3V0RG93biAqPSAyKSB7CiAgICAgIHZhciBvdmVyR3Jvd25IZWFwU2l6ZSA9IG9sZFNpemUgKiAoMSArIC4yIC8gY3V0RG93bik7CiAgICAgIG92ZXJHcm93bkhlYXBTaXplID0gTWF0aC5taW4ob3Zlckdyb3duSGVhcFNpemUsIHJlcXVlc3RlZFNpemUgKyAxMDA2NjMyOTYpOwogICAgICB2YXIgbmV3U2l6ZSA9IE1hdGgubWluKG1heEhlYXBTaXplLCBhbGlnbk1lbW9yeShNYXRoLm1heChyZXF1ZXN0ZWRTaXplLCBvdmVyR3Jvd25IZWFwU2l6ZSksIDY1NTM2KSk7CiAgICAgIHZhciByZXBsYWNlbWVudCA9IGdyb3dNZW1vcnkobmV3U2l6ZSk7CiAgICAgIGlmIChyZXBsYWNlbWVudCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfTsKICB2YXIgRU5WID0ge307CiAgdmFyIGdldEV4ZWN1dGFibGVOYW1lID0gKCkgPT4gdGhpc1Byb2dyYW0gfHwgIi4vdGhpcy5wcm9ncmFtIjsKICB2YXIgZ2V0RW52U3RyaW5ncyA9ICgpID0+IHsKICAgIGlmICghZ2V0RW52U3RyaW5ncy5zdHJpbmdzKSB7CiAgICAgIHZhciBsYW5nID0gKHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9iamVjdCIgJiYgbmF2aWdhdG9yLmxhbmd1YWdlIHx8ICJDIikucmVwbGFjZSgiLSIsICJfIikgKyAiLlVURi04IjsKICAgICAgdmFyIGVudiA9IHsKICAgICAgICBVU0VSOiAid2ViX3VzZXIiLAogICAgICAgIExPR05BTUU6ICJ3ZWJfdXNlciIsCiAgICAgICAgUEFUSDogIi8iLAogICAgICAgIFBXRDogIi8iLAogICAgICAgIEhPTUU6ICIvaG9tZS93ZWJfdXNlciIsCiAgICAgICAgTEFORzogbGFuZywKICAgICAgICBfOiBnZXRFeGVjdXRhYmxlTmFtZSgpCiAgICAgIH07CiAgICAgIGZvciAodmFyIHggaW4gRU5WKSB7CiAgICAgICAgaWYgKEVOVlt4XSA9PT0gdW5kZWZpbmVkKSBkZWxldGUgZW52W3hdO2Vsc2UgZW52W3hdID0gRU5WW3hdOwogICAgICB9CiAgICAgIHZhciBzdHJpbmdzID0gW107CiAgICAgIGZvciAodmFyIHggaW4gZW52KSB7CiAgICAgICAgc3RyaW5ncy5wdXNoKGAke3h9PSR7ZW52W3hdfWApOwogICAgICB9CiAgICAgIGdldEVudlN0cmluZ3Muc3RyaW5ncyA9IHN0cmluZ3M7CiAgICB9CiAgICByZXR1cm4gZ2V0RW52U3RyaW5ncy5zdHJpbmdzOwogIH07CiAgdmFyIHN0cmluZ1RvVVRGOEFycmF5ID0gKHN0ciwgaGVhcCwgb3V0SWR4LCBtYXhCeXRlc1RvV3JpdGUpID0+IHsKICAgIGlmICghKG1heEJ5dGVzVG9Xcml0ZSA+IDApKSByZXR1cm4gMDsKICAgIHZhciBzdGFydElkeCA9IG91dElkeDsKICAgIHZhciBlbmRJZHggPSBvdXRJZHggKyBtYXhCeXRlc1RvV3JpdGUgLSAxOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyArK2kpIHsKICAgICAgdmFyIHUgPSBzdHIuY29kZVBvaW50QXQoaSk7CiAgICAgIGlmICh1IDw9IDEyNykgewogICAgICAgIGlmIChvdXRJZHggPj0gZW5kSWR4KSBicmVhazsKICAgICAgICBoZWFwW291dElkeCsrXSA9IHU7CiAgICAgIH0gZWxzZSBpZiAodSA8PSAyMDQ3KSB7CiAgICAgICAgaWYgKG91dElkeCArIDEgPj0gZW5kSWR4KSBicmVhazsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDE5MiB8IHUgPj4gNjsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUgJiA2MzsKICAgICAgfSBlbHNlIGlmICh1IDw9IDY1NTM1KSB7CiAgICAgICAgaWYgKG91dElkeCArIDIgPj0gZW5kSWR4KSBicmVhazsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDIyNCB8IHUgPj4gMTI7CiAgICAgICAgaGVhcFtvdXRJZHgrK10gPSAxMjggfCB1ID4+IDYgJiA2MzsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUgJiA2MzsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAob3V0SWR4ICsgMyA+PSBlbmRJZHgpIGJyZWFrOwogICAgICAgIGhlYXBbb3V0SWR4KytdID0gMjQwIHwgdSA+PiAxODsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUgPj4gMTIgJiA2MzsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUgPj4gNiAmIDYzOwogICAgICAgIGhlYXBbb3V0SWR4KytdID0gMTI4IHwgdSAmIDYzOwogICAgICAgIGkrKzsKICAgICAgfQogICAgfQogICAgaGVhcFtvdXRJZHhdID0gMDsKICAgIHJldHVybiBvdXRJZHggLSBzdGFydElkeDsKICB9OwogIHZhciBzdHJpbmdUb1VURjggPSAoc3RyLCBvdXRQdHIsIG1heEJ5dGVzVG9Xcml0ZSkgPT4gc3RyaW5nVG9VVEY4QXJyYXkoc3RyLCBIRUFQVTgsIG91dFB0ciwgbWF4Qnl0ZXNUb1dyaXRlKTsKICB2YXIgX2Vudmlyb25fZ2V0ID0gKF9fZW52aXJvbiwgZW52aXJvbl9idWYpID0+IHsKICAgIHZhciBidWZTaXplID0gMDsKICAgIHZhciBlbnZwID0gMDsKICAgIGZvciAodmFyIHN0cmluZyBvZiBnZXRFbnZTdHJpbmdzKCkpIHsKICAgICAgdmFyIHB0ciA9IGVudmlyb25fYnVmICsgYnVmU2l6ZTsKICAgICAgSEVBUFUzMltfX2Vudmlyb24gKyBlbnZwID4+IDJdID0gcHRyOwogICAgICBidWZTaXplICs9IHN0cmluZ1RvVVRGOChzdHJpbmcsIHB0ciwgSW5maW5pdHkpICsgMTsKICAgICAgZW52cCArPSA0OwogICAgfQogICAgcmV0dXJuIDA7CiAgfTsKICB2YXIgbGVuZ3RoQnl0ZXNVVEY4ID0gc3RyID0+IHsKICAgIHZhciBsZW4gPSAwOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyArK2kpIHsKICAgICAgdmFyIGMgPSBzdHIuY2hhckNvZGVBdChpKTsKICAgICAgaWYgKGMgPD0gMTI3KSB7CiAgICAgICAgbGVuKys7CiAgICAgIH0gZWxzZSBpZiAoYyA8PSAyMDQ3KSB7CiAgICAgICAgbGVuICs9IDI7CiAgICAgIH0gZWxzZSBpZiAoYyA+PSA1NTI5NiAmJiBjIDw9IDU3MzQzKSB7CiAgICAgICAgbGVuICs9IDQ7CiAgICAgICAgKytpOwogICAgICB9IGVsc2UgewogICAgICAgIGxlbiArPSAzOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbGVuOwogIH07CiAgdmFyIF9lbnZpcm9uX3NpemVzX2dldCA9IChwZW52aXJvbl9jb3VudCwgcGVudmlyb25fYnVmX3NpemUpID0+IHsKICAgIHZhciBzdHJpbmdzID0gZ2V0RW52U3RyaW5ncygpOwogICAgSEVBUFUzMltwZW52aXJvbl9jb3VudCA+PiAyXSA9IHN0cmluZ3MubGVuZ3RoOwogICAgdmFyIGJ1ZlNpemUgPSAwOwogICAgZm9yICh2YXIgc3RyaW5nIG9mIHN0cmluZ3MpIHsKICAgICAgYnVmU2l6ZSArPSBsZW5ndGhCeXRlc1VURjgoc3RyaW5nKSArIDE7CiAgICB9CiAgICBIRUFQVTMyW3BlbnZpcm9uX2J1Zl9zaXplID4+IDJdID0gYnVmU2l6ZTsKICAgIHJldHVybiAwOwogIH07CiAgdmFyIElOVDUzX01BWCA9IDkwMDcxOTkyNTQ3NDA5OTI7CiAgdmFyIElOVDUzX01JTiA9IC05MDA3MTk5MjU0NzQwOTkyOwogIHZhciBiaWdpbnRUb0k1M0NoZWNrZWQgPSBudW0gPT4gbnVtIDwgSU5UNTNfTUlOIHx8IG51bSA+IElOVDUzX01BWCA/IE5hTiA6IE51bWJlcihudW0pOwogIGZ1bmN0aW9uIF9mZF9zZWVrKGZkLCBvZmZzZXQsIHdoZW5jZSwgbmV3T2Zmc2V0KSB7CiAgICBvZmZzZXQgPSBiaWdpbnRUb0k1M0NoZWNrZWQob2Zmc2V0KTsKICAgIHJldHVybiA3MDsKICB9CiAgdmFyIHByaW50Q2hhckJ1ZmZlcnMgPSBbbnVsbCwgW10sIFtdXTsKICB2YXIgVVRGOERlY29kZXIgPSB0eXBlb2YgVGV4dERlY29kZXIgIT0gInVuZGVmaW5lZCIgPyBuZXcgVGV4dERlY29kZXIoKSA6IHVuZGVmaW5lZDsKICB2YXIgZmluZFN0cmluZ0VuZCA9IChoZWFwT3JBcnJheSwgaWR4LCBtYXhCeXRlc1RvUmVhZCwgaWdub3JlTnVsKSA9PiB7CiAgICB2YXIgbWF4SWR4ID0gaWR4ICsgbWF4Qnl0ZXNUb1JlYWQ7CiAgICBpZiAoaWdub3JlTnVsKSByZXR1cm4gbWF4SWR4OwogICAgd2hpbGUgKGhlYXBPckFycmF5W2lkeF0gJiYgIShpZHggPj0gbWF4SWR4KSkgKytpZHg7CiAgICByZXR1cm4gaWR4OwogIH07CiAgdmFyIFVURjhBcnJheVRvU3RyaW5nID0gKGhlYXBPckFycmF5LCBpZHggPSAwLCBtYXhCeXRlc1RvUmVhZCwgaWdub3JlTnVsKSA9PiB7CiAgICB2YXIgZW5kUHRyID0gZmluZFN0cmluZ0VuZChoZWFwT3JBcnJheSwgaWR4LCBtYXhCeXRlc1RvUmVhZCwgaWdub3JlTnVsKTsKICAgIGlmIChlbmRQdHIgLSBpZHggPiAxNiAmJiBoZWFwT3JBcnJheS5idWZmZXIgJiYgVVRGOERlY29kZXIpIHsKICAgICAgcmV0dXJuIFVURjhEZWNvZGVyLmRlY29kZShoZWFwT3JBcnJheS5zdWJhcnJheShpZHgsIGVuZFB0cikpOwogICAgfQogICAgdmFyIHN0ciA9ICIiOwogICAgd2hpbGUgKGlkeCA8IGVuZFB0cikgewogICAgICB2YXIgdTAgPSBoZWFwT3JBcnJheVtpZHgrK107CiAgICAgIGlmICghKHUwICYgMTI4KSkgewogICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHUwKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICB2YXIgdTEgPSBoZWFwT3JBcnJheVtpZHgrK10gJiA2MzsKICAgICAgaWYgKCh1MCAmIDIyNCkgPT0gMTkyKSB7CiAgICAgICAgc3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKHUwICYgMzEpIDw8IDYgfCB1MSk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgdmFyIHUyID0gaGVhcE9yQXJyYXlbaWR4KytdICYgNjM7CiAgICAgIGlmICgodTAgJiAyNDApID09IDIyNCkgewogICAgICAgIHUwID0gKHUwICYgMTUpIDw8IDEyIHwgdTEgPDwgNiB8IHUyOwogICAgICB9IGVsc2UgewogICAgICAgIHUwID0gKHUwICYgNykgPDwgMTggfCB1MSA8PCAxMiB8IHUyIDw8IDYgfCBoZWFwT3JBcnJheVtpZHgrK10gJiA2MzsKICAgICAgfQogICAgICBpZiAodTAgPCA2NTUzNikgewogICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHUwKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgY2ggPSB1MCAtIDY1NTM2OwogICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2IHwgY2ggPj4gMTAsIDU2MzIwIHwgY2ggJiAxMDIzKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHN0cjsKICB9OwogIHZhciBwcmludENoYXIgPSAoc3RyZWFtLCBjdXJyKSA9PiB7CiAgICB2YXIgYnVmZmVyID0gcHJpbnRDaGFyQnVmZmVyc1tzdHJlYW1dOwogICAgaWYgKGN1cnIgPT09IDAgfHwgY3VyciA9PT0gMTApIHsKICAgICAgKHN0cmVhbSA9PT0gMSA/IG91dCA6IGVycikoVVRGOEFycmF5VG9TdHJpbmcoYnVmZmVyKSk7CiAgICAgIGJ1ZmZlci5sZW5ndGggPSAwOwogICAgfSBlbHNlIHsKICAgICAgYnVmZmVyLnB1c2goY3Vycik7CiAgICB9CiAgfTsKICB2YXIgVVRGOFRvU3RyaW5nID0gKHB0ciwgbWF4Qnl0ZXNUb1JlYWQsIGlnbm9yZU51bCkgPT4gcHRyID8gVVRGOEFycmF5VG9TdHJpbmcoSEVBUFU4LCBwdHIsIG1heEJ5dGVzVG9SZWFkLCBpZ25vcmVOdWwpIDogIiI7CiAgdmFyIF9mZF93cml0ZSA9IChmZCwgaW92LCBpb3ZjbnQsIHBudW0pID0+IHsKICAgIHZhciBudW0gPSAwOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpb3ZjbnQ7IGkrKykgewogICAgICB2YXIgcHRyID0gSEVBUFUzMltpb3YgPj4gMl07CiAgICAgIHZhciBsZW4gPSBIRUFQVTMyW2lvdiArIDQgPj4gMl07CiAgICAgIGlvdiArPSA4OwogICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGxlbjsgaisrKSB7CiAgICAgICAgcHJpbnRDaGFyKGZkLCBIRUFQVThbcHRyICsgal0pOwogICAgICB9CiAgICAgIG51bSArPSBsZW47CiAgICB9CiAgICBIRUFQVTMyW3BudW0gPj4gMl0gPSBudW07CiAgICByZXR1cm4gMDsKICB9OwogIGZ1bmN0aW9uIF9ncmF5X3RvX3JnYmEoY29tcEdfcHRyLCBuYl9waXhlbHMpIHsKICAgIGNvbXBHX3B0ciA+Pj0gMjsKICAgIGNvbnN0IGltYWdlRGF0YSA9IE1vZHVsZS5pbWFnZURhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkobmJfcGl4ZWxzICogNCk7CiAgICBjb25zdCBjb21wRyA9IEhFQVAzMi5zdWJhcnJheShjb21wR19wdHIsIGNvbXBHX3B0ciArIG5iX3BpeGVscyk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iX3BpeGVsczsgaSsrKSB7CiAgICAgIGltYWdlRGF0YVs0ICogaV0gPSBpbWFnZURhdGFbNCAqIGkgKyAxXSA9IGltYWdlRGF0YVs0ICogaSArIDJdID0gY29tcEdbaV07CiAgICAgIGltYWdlRGF0YVs0ICogaSArIDNdID0gMjU1OwogICAgfQogIH0KICBmdW5jdGlvbiBfZ3JheWFfdG9fcmdiYShjb21wR19wdHIsIGNvbXBBX3B0ciwgbmJfcGl4ZWxzKSB7CiAgICBjb21wR19wdHIgPj49IDI7CiAgICBjb21wQV9wdHIgPj49IDI7CiAgICBjb25zdCBpbWFnZURhdGEgPSBNb2R1bGUuaW1hZ2VEYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KG5iX3BpeGVscyAqIDQpOwogICAgY29uc3QgY29tcEcgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEdfcHRyLCBjb21wR19wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEEgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEFfcHRyLCBjb21wQV9wdHIgKyBuYl9waXhlbHMpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuYl9waXhlbHM7IGkrKykgewogICAgICBpbWFnZURhdGFbNCAqIGldID0gaW1hZ2VEYXRhWzQgKiBpICsgMV0gPSBpbWFnZURhdGFbNCAqIGkgKyAyXSA9IGNvbXBHW2ldOwogICAgICBpbWFnZURhdGFbNCAqIGkgKyAzXSA9IGNvbXBBW2ldOwogICAgfQogIH0KICBmdW5jdGlvbiBfanNQcmludFdhcm5pbmcobWVzc2FnZV9wdHIpIHsKICAgIGNvbnN0IG1lc3NhZ2UgPSBVVEY4VG9TdHJpbmcobWVzc2FnZV9wdHIpOwogICAgKE1vZHVsZS53YXJuIHx8IGNvbnNvbGUud2FybikoYE9wZW5KUEVHOiAke21lc3NhZ2V9YCk7CiAgfQogIGZ1bmN0aW9uIF9yZ2JfdG9fcmdiYShjb21wUl9wdHIsIGNvbXBHX3B0ciwgY29tcEJfcHRyLCBuYl9waXhlbHMpIHsKICAgIGNvbXBSX3B0ciA+Pj0gMjsKICAgIGNvbXBHX3B0ciA+Pj0gMjsKICAgIGNvbXBCX3B0ciA+Pj0gMjsKICAgIGNvbnN0IGltYWdlRGF0YSA9IE1vZHVsZS5pbWFnZURhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkobmJfcGl4ZWxzICogNCk7CiAgICBjb25zdCBjb21wUiA9IEhFQVAzMi5zdWJhcnJheShjb21wUl9wdHIsIGNvbXBSX3B0ciArIG5iX3BpeGVscyk7CiAgICBjb25zdCBjb21wRyA9IEhFQVAzMi5zdWJhcnJheShjb21wR19wdHIsIGNvbXBHX3B0ciArIG5iX3BpeGVscyk7CiAgICBjb25zdCBjb21wQiA9IEhFQVAzMi5zdWJhcnJheShjb21wQl9wdHIsIGNvbXBCX3B0ciArIG5iX3BpeGVscyk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iX3BpeGVsczsgaSsrKSB7CiAgICAgIGltYWdlRGF0YVs0ICogaV0gPSBjb21wUltpXTsKICAgICAgaW1hZ2VEYXRhWzQgKiBpICsgMV0gPSBjb21wR1tpXTsKICAgICAgaW1hZ2VEYXRhWzQgKiBpICsgMl0gPSBjb21wQltpXTsKICAgICAgaW1hZ2VEYXRhWzQgKiBpICsgM10gPSAyNTU7CiAgICB9CiAgfQogIGZ1bmN0aW9uIF9zdG9yZUVycm9yTWVzc2FnZShtZXNzYWdlX3B0cikgewogICAgY29uc3QgbWVzc2FnZSA9IFVURjhUb1N0cmluZyhtZXNzYWdlX3B0cik7CiAgICBpZiAoIU1vZHVsZS5lcnJvck1lc3NhZ2VzKSB7CiAgICAgIE1vZHVsZS5lcnJvck1lc3NhZ2VzID0gbWVzc2FnZTsKICAgIH0gZWxzZSB7CiAgICAgIE1vZHVsZS5lcnJvck1lc3NhZ2VzICs9ICJcbiIgKyBtZXNzYWdlOwogICAgfQogIH0KICB2YXIgd3JpdGVBcnJheVRvTWVtb3J5ID0gKGFycmF5LCBidWZmZXIpID0+IHsKICAgIEhFQVA4LnNldChhcnJheSwgYnVmZmVyKTsKICB9OwogIGlmIChNb2R1bGVbIm5vRXhpdFJ1bnRpbWUiXSkgbm9FeGl0UnVudGltZSA9IE1vZHVsZVsibm9FeGl0UnVudGltZSJdOwogIGlmIChNb2R1bGVbInByaW50Il0pIG91dCA9IE1vZHVsZVsicHJpbnQiXTsKICBpZiAoTW9kdWxlWyJwcmludEVyciJdKSBlcnIgPSBNb2R1bGVbInByaW50RXJyIl07CiAgaWYgKE1vZHVsZVsid2FzbUJpbmFyeSJdKSB3YXNtQmluYXJ5ID0gTW9kdWxlWyJ3YXNtQmluYXJ5Il07CiAgaWYgKE1vZHVsZVsiYXJndW1lbnRzIl0pIGFyZ3VtZW50c18gPSBNb2R1bGVbImFyZ3VtZW50cyJdOwogIGlmIChNb2R1bGVbInRoaXNQcm9ncmFtIl0pIHRoaXNQcm9ncmFtID0gTW9kdWxlWyJ0aGlzUHJvZ3JhbSJdOwogIGlmIChNb2R1bGVbInByZUluaXQiXSkgewogICAgaWYgKHR5cGVvZiBNb2R1bGVbInByZUluaXQiXSA9PSAiZnVuY3Rpb24iKSBNb2R1bGVbInByZUluaXQiXSA9IFtNb2R1bGVbInByZUluaXQiXV07CiAgICB3aGlsZSAoTW9kdWxlWyJwcmVJbml0Il0ubGVuZ3RoID4gMCkgewogICAgICBNb2R1bGVbInByZUluaXQiXS5zaGlmdCgpKCk7CiAgICB9CiAgfQogIE1vZHVsZVsid3JpdGVBcnJheVRvTWVtb3J5Il0gPSB3cml0ZUFycmF5VG9NZW1vcnk7CiAgdmFyIF9tYWxsb2MsIF9mcmVlLCBfanAyX2RlY29kZSwgX19lbXNjcmlwdGVuX3RpbWVvdXQ7CiAgZnVuY3Rpb24gYXNzaWduV2FzbUV4cG9ydHMod2FzbUV4cG9ydHMpIHsKICAgIE1vZHVsZVsiX21hbGxvYyJdID0gX21hbGxvYyA9IHdhc21FeHBvcnRzWyJ0Il07CiAgICBNb2R1bGVbIl9mcmVlIl0gPSBfZnJlZSA9IHdhc21FeHBvcnRzWyJ1Il07CiAgICBNb2R1bGVbIl9qcDJfZGVjb2RlIl0gPSBfanAyX2RlY29kZSA9IHdhc21FeHBvcnRzWyJ2Il07CiAgICBfX2Vtc2NyaXB0ZW5fdGltZW91dCA9IHdhc21FeHBvcnRzWyJ3Il07CiAgfQogIHZhciB3YXNtSW1wb3J0cyA9IHsKICAgIGs6IF9fYWJvcnRfanMsCiAgICBqOiBfX2Vtc2NyaXB0ZW5fcnVudGltZV9rZWVwYWxpdmVfY2xlYXIsCiAgICBsOiBfX3NldGl0aW1lcl9qcywKICAgIGY6IF9jb3B5X3BpeGVsc18xLAogICAgZTogX2NvcHlfcGl4ZWxzXzMsCiAgICBkOiBfY29weV9waXhlbHNfNCwKICAgIG06IF9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwLAogICAgbzogX2Vudmlyb25fZ2V0LAogICAgcDogX2Vudmlyb25fc2l6ZXNfZ2V0LAogICAgbjogX2ZkX3NlZWssCiAgICBiOiBfZmRfd3JpdGUsCiAgICBxOiBfZ3JheV90b19yZ2JhLAogICAgaDogX2dyYXlhX3RvX3JnYmEsCiAgICBjOiBfanNQcmludFdhcm5pbmcsCiAgICBpOiBfcHJvY19leGl0LAogICAgZzogX3JnYl90b19yZ2JhLAogICAgYTogX3N0b3JlRXJyb3JNZXNzYWdlCiAgfTsKICBmdW5jdGlvbiBydW4oKSB7CiAgICBwcmVSdW4oKTsKICAgIGZ1bmN0aW9uIGRvUnVuKCkgewogICAgICBNb2R1bGVbImNhbGxlZFJ1biJdID0gdHJ1ZTsKICAgICAgaWYgKEFCT1JUKSByZXR1cm47CiAgICAgIGluaXRSdW50aW1lKCk7CiAgICAgIHJlYWR5UHJvbWlzZVJlc29sdmU/LihNb2R1bGUpOwogICAgICBNb2R1bGVbIm9uUnVudGltZUluaXRpYWxpemVkIl0/LigpOwogICAgICBwb3N0UnVuKCk7CiAgICB9CiAgICBpZiAoTW9kdWxlWyJzZXRTdGF0dXMiXSkgewogICAgICBNb2R1bGVbInNldFN0YXR1cyJdKCJSdW5uaW5nLi4uIik7CiAgICAgIHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgIHNldFRpbWVvdXQoKCkgPT4gTW9kdWxlWyJzZXRTdGF0dXMiXSgiIiksIDEpOwogICAgICAgIGRvUnVuKCk7CiAgICAgIH0sIDEpOwogICAgfSBlbHNlIHsKICAgICAgZG9SdW4oKTsKICAgIH0KICB9CiAgdmFyIHdhc21FeHBvcnRzOwogIHdhc21FeHBvcnRzID0gYXdhaXQgY3JlYXRlV2FzbSgpOwogIHJ1bigpOwogIGlmIChydW50aW1lSW5pdGlhbGl6ZWQpIHsKICAgIG1vZHVsZVJ0biA9IE1vZHVsZTsKICB9IGVsc2UgewogICAgbW9kdWxlUnRuID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gewogICAgICByZWFkeVByb21pc2VSZXNvbHZlID0gcmVzb2x2ZTsKICAgICAgcmVhZHlQcm9taXNlUmVqZWN0ID0gcmVqZWN0OwogICAgfSk7CiAgfQogIHJldHVybiBtb2R1bGVSdG47Cn0KLyogaGFybW9ueSBkZWZhdWx0IGV4cG9ydCAqLyBjb25zdCBvcGVuanBlZyA9IChPcGVuSlBFRyk7CjsvLyAuL3NyYy9jb3JlL2pweC5qcwoKCgoKY2xhc3MgSnB4RXJyb3IgZXh0ZW5kcyBCYXNlRXhjZXB0aW9uIHsKICBjb25zdHJ1Y3Rvcihtc2cpIHsKICAgIHN1cGVyKG1zZywgIkpweEVycm9yIik7CiAgfQp9CmNsYXNzIEpweEltYWdlIHsKICBzdGF0aWMgI2J1ZmZlciA9IG51bGw7CiAgc3RhdGljICNoYW5kbGVyID0gbnVsbDsKICBzdGF0aWMgI21vZHVsZVByb21pc2UgPSBudWxsOwogIHN0YXRpYyAjdXNlV2FzbSA9IHRydWU7CiAgc3RhdGljICN1c2VXb3JrZXJGZXRjaCA9IHRydWU7CiAgc3RhdGljICN3YXNtVXJsID0gbnVsbDsKICBzdGF0aWMgc2V0T3B0aW9ucyh7CiAgICBoYW5kbGVyLAogICAgdXNlV2FzbSwKICAgIHVzZVdvcmtlckZldGNoLAogICAgd2FzbVVybAogIH0pIHsKICAgIHRoaXMuI3VzZVdhc20gPSB1c2VXYXNtOwogICAgdGhpcy4jdXNlV29ya2VyRmV0Y2ggPSB1c2VXb3JrZXJGZXRjaDsKICAgIHRoaXMuI3dhc21VcmwgPSB3YXNtVXJsOwogICAgaWYgKCF1c2VXb3JrZXJGZXRjaCkgewogICAgICB0aGlzLiNoYW5kbGVyID0gaGFuZGxlcjsKICAgIH0KICB9CiAgc3RhdGljIGFzeW5jICNnZXRKc01vZHVsZShmYWxsYmFja0NhbGxiYWNrKSB7CiAgICBjb25zdCBwYXRoID0gYCR7dGhpcy4jd2FzbVVybH1vcGVuanBlZ19ub3dhc21fZmFsbGJhY2suanNgOwogICAgbGV0IGluc3RhbmNlID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIGNvbnN0IG1vZCA9IGF3YWl0IGltcG9ydCgKICAgICAgLyp3ZWJwYWNrSWdub3JlOiB0cnVlKi8KICAgICAgLypAdml0ZS1pZ25vcmUqLwogICAgICBwYXRoKTsKICAgICAgaW5zdGFuY2UgPSBtb2QuZGVmYXVsdCgpOwogICAgfSBjYXRjaCAoZSkgewogICAgICB3YXJuKGBKcHhJbWFnZSNnZXRKc01vZHVsZTogJHtlfWApOwogICAgfQogICAgZmFsbGJhY2tDYWxsYmFjayhpbnN0YW5jZSk7CiAgfQogIHN0YXRpYyBhc3luYyAjaW5zdGFudGlhdGVXYXNtKGZhbGxiYWNrQ2FsbGJhY2ssIGltcG9ydHMsIHN1Y2Nlc3NDYWxsYmFjaykgewogICAgY29uc3QgZmlsZW5hbWUgPSAib3BlbmpwZWcud2FzbSI7CiAgICB0cnkgewogICAgICBpZiAoIXRoaXMuI2J1ZmZlcikgewogICAgICAgIGlmICh0aGlzLiN1c2VXb3JrZXJGZXRjaCkgewogICAgICAgICAgdGhpcy4jYnVmZmVyID0gYXdhaXQgZmV0Y2hCaW5hcnlEYXRhKGAke3RoaXMuI3dhc21Vcmx9JHtmaWxlbmFtZX1gKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhpcy4jYnVmZmVyID0gYXdhaXQgdGhpcy4jaGFuZGxlci5zZW5kV2l0aFByb21pc2UoIkZldGNoQmluYXJ5RGF0YSIsIHsKICAgICAgICAgICAgdHlwZTogIndhc21GYWN0b3J5IiwKICAgICAgICAgICAgZmlsZW5hbWUKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGUodGhpcy4jYnVmZmVyLCBpbXBvcnRzKTsKICAgICAgcmV0dXJuIHN1Y2Nlc3NDYWxsYmFjayhyZXN1bHRzLmluc3RhbmNlKTsKICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICB3YXJuKGBKcHhJbWFnZSNpbnN0YW50aWF0ZVdhc206ICR7cmVhc29ufWApOwogICAgICB0aGlzLiNnZXRKc01vZHVsZShmYWxsYmFja0NhbGxiYWNrKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9IGZpbmFsbHkgewogICAgICB0aGlzLiNoYW5kbGVyID0gbnVsbDsKICAgIH0KICB9CiAgc3RhdGljIGFzeW5jIGRlY29kZShieXRlcywgewogICAgbnVtQ29tcG9uZW50cyA9IDQsCiAgICBpc0luZGV4ZWRDb2xvcm1hcCA9IGZhbHNlLAogICAgc21hc2tJbkRhdGEgPSBmYWxzZSwKICAgIHJlZHVjZVBvd2VyID0gMAogIH0gPSB7fSkgewogICAgaWYgKCF0aGlzLiNtb2R1bGVQcm9taXNlKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBwcm9taXNlLAogICAgICAgIHJlc29sdmUKICAgICAgfSA9IFByb21pc2Uud2l0aFJlc29sdmVycygpOwogICAgICBjb25zdCBwcm9taXNlcyA9IFtwcm9taXNlXTsKICAgICAgaWYgKCF0aGlzLiN1c2VXYXNtKSB7CiAgICAgICAgdGhpcy4jZ2V0SnNNb2R1bGUocmVzb2x2ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcHJvbWlzZXMucHVzaChvcGVuanBlZyh7CiAgICAgICAgICB3YXJuOiB3YXJuLAogICAgICAgICAgaW5zdGFudGlhdGVXYXNtOiB0aGlzLiNpbnN0YW50aWF0ZVdhc20uYmluZCh0aGlzLCByZXNvbHZlKQogICAgICAgIH0pKTsKICAgICAgfQogICAgICB0aGlzLiNtb2R1bGVQcm9taXNlID0gUHJvbWlzZS5yYWNlKHByb21pc2VzKTsKICAgIH0KICAgIGNvbnN0IG1vZHVsZSA9IGF3YWl0IHRoaXMuI21vZHVsZVByb21pc2U7CiAgICBpZiAoIW1vZHVsZSkgewogICAgICB0aHJvdyBuZXcgSnB4RXJyb3IoIk9wZW5KUEVHIGZhaWxlZCB0byBpbml0aWFsaXplIik7CiAgICB9CiAgICBsZXQgcHRyOwogICAgdHJ5IHsKICAgICAgY29uc3Qgc2l6ZSA9IGJ5dGVzLmxlbmd0aDsKICAgICAgcHRyID0gbW9kdWxlLl9tYWxsb2Moc2l6ZSk7CiAgICAgIG1vZHVsZS53cml0ZUFycmF5VG9NZW1vcnkoYnl0ZXMsIHB0cik7CiAgICAgIGNvbnN0IHJldCA9IG1vZHVsZS5fanAyX2RlY29kZShwdHIsIHNpemUsIG51bUNvbXBvbmVudHMgPiAwID8gbnVtQ29tcG9uZW50cyA6IDAsICEhaXNJbmRleGVkQ29sb3JtYXAsICEhc21hc2tJbkRhdGEsIHJlZHVjZVBvd2VyKTsKICAgICAgaWYgKHJldCkgewogICAgICAgIGNvbnN0IHsKICAgICAgICAgIGVycm9yTWVzc2FnZXMKICAgICAgICB9ID0gbW9kdWxlOwogICAgICAgIGlmIChlcnJvck1lc3NhZ2VzKSB7CiAgICAgICAgICBkZWxldGUgbW9kdWxlLmVycm9yTWVzc2FnZXM7CiAgICAgICAgICB0aHJvdyBuZXcgSnB4RXJyb3IoZXJyb3JNZXNzYWdlcyk7CiAgICAgICAgfQogICAgICAgIHRocm93IG5ldyBKcHhFcnJvcigiVW5rbm93biBlcnJvciIpOwogICAgICB9CiAgICAgIGNvbnN0IHsKICAgICAgICBpbWFnZURhdGEKICAgICAgfSA9IG1vZHVsZTsKICAgICAgbW9kdWxlLmltYWdlRGF0YSA9IG51bGw7CiAgICAgIHJldHVybiBpbWFnZURhdGE7CiAgICB9IGZpbmFsbHkgewogICAgICBpZiAocHRyKSB7CiAgICAgICAgbW9kdWxlLl9mcmVlKHB0cik7CiAgICAgIH0KICAgIH0KICB9CiAgc3RhdGljIGNsZWFudXAoKSB7CiAgICB0aGlzLiNtb2R1bGVQcm9taXNlID0gbnVsbDsKICB9CiAgc3RhdGljIHBhcnNlSW1hZ2VQcm9wZXJ0aWVzKHN0cmVhbSkgewogICAgbGV0IG5ld0J5dGUgPSBzdHJlYW0uZ2V0Qnl0ZSgpOwogICAgd2hpbGUgKG5ld0J5dGUgPj0gMCkgewogICAgICBjb25zdCBvbGRCeXRlID0gbmV3Qnl0ZTsKICAgICAgbmV3Qnl0ZSA9IHN0cmVhbS5nZXRCeXRlKCk7CiAgICAgIGNvbnN0IGNvZGUgPSBvbGRCeXRlIDw8IDggfCBuZXdCeXRlOwogICAgICBpZiAoY29kZSA9PT0gMHhmZjUxKSB7CiAgICAgICAgc3RyZWFtLnNraXAoNCk7CiAgICAgICAgY29uc3QgWHNpeiA9IHN0cmVhbS5nZXRJbnQzMigpID4+PiAwOwogICAgICAgIGNvbnN0IFlzaXogPSBzdHJlYW0uZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICBjb25zdCBYT3NpeiA9IHN0cmVhbS5nZXRJbnQzMigpID4+PiAwOwogICAgICAgIGNvbnN0IFlPc2l6ID0gc3RyZWFtLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgc3RyZWFtLnNraXAoMTYpOwogICAgICAgIGNvbnN0IENzaXogPSBzdHJlYW0uZ2V0VWludDE2KCk7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHdpZHRoOiBYc2l6IC0gWE9zaXosCiAgICAgICAgICBoZWlnaHQ6IFlzaXogLSBZT3NpeiwKICAgICAgICAgIGJpdHNQZXJDb21wb25lbnQ6IDgsCiAgICAgICAgICBjb21wb25lbnRzQ291bnQ6IENzaXoKICAgICAgICB9OwogICAgICB9CiAgICB9CiAgICB0aHJvdyBuZXcgSnB4RXJyb3IoIk5vIHNpemUgbWFya2VyIGZvdW5kIGluIEpQWCBzdHJlYW0iKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL29wZXJhdG9yX2xpc3QuanMKCmZ1bmN0aW9uIGFkZFN0YXRlKHBhcmVudFN0YXRlLCBwYXR0ZXJuLCBjaGVja0ZuLCBpdGVyYXRlRm4sIHByb2Nlc3NGbikgewogIGxldCBzdGF0ZSA9IHBhcmVudFN0YXRlOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHBhdHRlcm4ubGVuZ3RoIC0gMTsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IGl0ZW0gPSBwYXR0ZXJuW2ldOwogICAgc3RhdGUgPSBzdGF0ZVtpdGVtXSB8fD0gW107CiAgfQogIHN0YXRlW3BhdHRlcm4uYXQoLTEpXSA9IHsKICAgIGNoZWNrRm4sCiAgICBpdGVyYXRlRm4sCiAgICBwcm9jZXNzRm4KICB9Owp9CmNvbnN0IEluaXRpYWxTdGF0ZSA9IFtdOwphZGRTdGF0ZShJbml0aWFsU3RhdGUsIFtPUFMuc2F2ZSwgT1BTLnRyYW5zZm9ybSwgT1BTLnBhaW50SW5saW5lSW1hZ2VYT2JqZWN0LCBPUFMucmVzdG9yZV0sIG51bGwsIGZ1bmN0aW9uIGl0ZXJhdGVJbmxpbmVJbWFnZUdyb3VwKGNvbnRleHQsIGkpIHsKICBjb25zdCBmbkFycmF5ID0gY29udGV4dC5mbkFycmF5OwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjb250ZXh0LmlDdXJyIC0gMzsKICBjb25zdCBwb3MgPSAoaSAtIGlGaXJzdFNhdmUpICUgNDsKICBzd2l0Y2ggKHBvcykgewogICAgY2FzZSAwOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnNhdmU7CiAgICBjYXNlIDE6CiAgICAgIHJldHVybiBmbkFycmF5W2ldID09PSBPUFMudHJhbnNmb3JtOwogICAgY2FzZSAyOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnBhaW50SW5saW5lSW1hZ2VYT2JqZWN0OwogICAgY2FzZSAzOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnJlc3RvcmU7CiAgfQogIHRocm93IG5ldyBFcnJvcihgaXRlcmF0ZUlubGluZUltYWdlR3JvdXAgLSBpbnZhbGlkIHBvczogJHtwb3N9YCk7Cn0sIGZ1bmN0aW9uIGZvdW5kSW5saW5lSW1hZ2VHcm91cChjb250ZXh0LCBpKSB7CiAgY29uc3QgTUlOX0lNQUdFU19JTl9JTkxJTkVfSU1BR0VTX0JMT0NLID0gMTA7CiAgY29uc3QgTUFYX0lNQUdFU19JTl9JTkxJTkVfSU1BR0VTX0JMT0NLID0gMjAwOwogIGNvbnN0IE1BWF9XSURUSCA9IDEwMDA7CiAgY29uc3QgSU1BR0VfUEFERElORyA9IDE7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGN1cnIgPSBjb250ZXh0LmlDdXJyOwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjdXJyIC0gMzsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RQSUlYTyA9IGN1cnIgLSAxOwogIGNvbnN0IGNvdW50ID0gTWF0aC5taW4oTWF0aC5mbG9vcigoaSAtIGlGaXJzdFNhdmUpIC8gNCksIE1BWF9JTUFHRVNfSU5fSU5MSU5FX0lNQUdFU19CTE9DSyk7CiAgaWYgKGNvdW50IDwgTUlOX0lNQUdFU19JTl9JTkxJTkVfSU1BR0VTX0JMT0NLKSB7CiAgICByZXR1cm4gaSAtIChpIC0gaUZpcnN0U2F2ZSkgJSA0OwogIH0KICBsZXQgbWF4WCA9IDA7CiAgY29uc3QgbWFwID0gW107CiAgbGV0IG1heExpbmVIZWlnaHQgPSAwOwogIGxldCBjdXJyZW50WCA9IElNQUdFX1BBRERJTkcsCiAgICBjdXJyZW50WSA9IElNQUdFX1BBRERJTkc7CiAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrKSB7CiAgICBjb25zdCB0cmFuc2Zvcm0gPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtICsgKHEgPDwgMildOwogICAgY29uc3QgaW1nID0gYXJnc0FycmF5W2lGaXJzdFBJSVhPICsgKHEgPDwgMildWzBdOwogICAgaWYgKGN1cnJlbnRYICsgaW1nLndpZHRoID4gTUFYX1dJRFRIKSB7CiAgICAgIG1heFggPSBNYXRoLm1heChtYXhYLCBjdXJyZW50WCk7CiAgICAgIGN1cnJlbnRZICs9IG1heExpbmVIZWlnaHQgKyAyICogSU1BR0VfUEFERElORzsKICAgICAgY3VycmVudFggPSAwOwogICAgICBtYXhMaW5lSGVpZ2h0ID0gMDsKICAgIH0KICAgIG1hcC5wdXNoKHsKICAgICAgdHJhbnNmb3JtLAogICAgICB4OiBjdXJyZW50WCwKICAgICAgeTogY3VycmVudFksCiAgICAgIHc6IGltZy53aWR0aCwKICAgICAgaDogaW1nLmhlaWdodAogICAgfSk7CiAgICBjdXJyZW50WCArPSBpbWcud2lkdGggKyAyICogSU1BR0VfUEFERElORzsKICAgIG1heExpbmVIZWlnaHQgPSBNYXRoLm1heChtYXhMaW5lSGVpZ2h0LCBpbWcuaGVpZ2h0KTsKICB9CiAgY29uc3QgaW1nV2lkdGggPSBNYXRoLm1heChtYXhYLCBjdXJyZW50WCkgKyBJTUFHRV9QQURESU5HOwogIGNvbnN0IGltZ0hlaWdodCA9IGN1cnJlbnRZICsgbWF4TGluZUhlaWdodCArIElNQUdFX1BBRERJTkc7CiAgY29uc3QgaW1nRGF0YSA9IG5ldyBVaW50OEFycmF5KGltZ1dpZHRoICogaW1nSGVpZ2h0ICogNCk7CiAgY29uc3QgaW1nUm93U2l6ZSA9IGltZ1dpZHRoIDw8IDI7CiAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrKSB7CiAgICBjb25zdCBkYXRhID0gYXJnc0FycmF5W2lGaXJzdFBJSVhPICsgKHEgPDwgMildWzBdLmRhdGE7CiAgICBjb25zdCByb3dTaXplID0gbWFwW3FdLncgPDwgMjsKICAgIGxldCBkYXRhT2Zmc2V0ID0gMDsKICAgIGxldCBvZmZzZXQgPSBtYXBbcV0ueCArIG1hcFtxXS55ICogaW1nV2lkdGggPDwgMjsKICAgIGltZ0RhdGEuc2V0KGRhdGEuc3ViYXJyYXkoMCwgcm93U2l6ZSksIG9mZnNldCAtIGltZ1Jvd1NpemUpOwogICAgZm9yIChsZXQgayA9IDAsIGtrID0gbWFwW3FdLmg7IGsgPCBrazsgaysrKSB7CiAgICAgIGltZ0RhdGEuc2V0KGRhdGEuc3ViYXJyYXkoZGF0YU9mZnNldCwgZGF0YU9mZnNldCArIHJvd1NpemUpLCBvZmZzZXQpOwogICAgICBkYXRhT2Zmc2V0ICs9IHJvd1NpemU7CiAgICAgIG9mZnNldCArPSBpbWdSb3dTaXplOwogICAgfQogICAgaW1nRGF0YS5zZXQoZGF0YS5zdWJhcnJheShkYXRhT2Zmc2V0IC0gcm93U2l6ZSwgZGF0YU9mZnNldCksIG9mZnNldCk7CiAgICB3aGlsZSAob2Zmc2V0ID49IDApIHsKICAgICAgZGF0YVtvZmZzZXQgLSA0XSA9IGRhdGFbb2Zmc2V0XTsKICAgICAgZGF0YVtvZmZzZXQgLSAzXSA9IGRhdGFbb2Zmc2V0ICsgMV07CiAgICAgIGRhdGFbb2Zmc2V0IC0gMl0gPSBkYXRhW29mZnNldCArIDJdOwogICAgICBkYXRhW29mZnNldCAtIDFdID0gZGF0YVtvZmZzZXQgKyAzXTsKICAgICAgZGF0YVtvZmZzZXQgKyByb3dTaXplXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDRdOwogICAgICBkYXRhW29mZnNldCArIHJvd1NpemUgKyAxXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDNdOwogICAgICBkYXRhW29mZnNldCArIHJvd1NpemUgKyAyXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDJdOwogICAgICBkYXRhW29mZnNldCArIHJvd1NpemUgKyAzXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDFdOwogICAgICBvZmZzZXQgLT0gaW1nUm93U2l6ZTsKICAgIH0KICB9CiAgY29uc3QgaW1nID0gewogICAgd2lkdGg6IGltZ1dpZHRoLAogICAgaGVpZ2h0OiBpbWdIZWlnaHQKICB9OwogIGlmIChjb250ZXh0LmlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICBjb25zdCBjYW52YXMgPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKGltZ1dpZHRoLCBpbWdIZWlnaHQpOwogICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgICBjdHgucHV0SW1hZ2VEYXRhKG5ldyBJbWFnZURhdGEobmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGltZ0RhdGEuYnVmZmVyKSwgaW1nV2lkdGgsIGltZ0hlaWdodCksIDAsIDApOwogICAgaW1nLmJpdG1hcCA9IGNhbnZhcy50cmFuc2ZlclRvSW1hZ2VCaXRtYXAoKTsKICAgIGltZy5kYXRhID0gbnVsbDsKICB9IGVsc2UgewogICAgaW1nLmtpbmQgPSBJbWFnZUtpbmQuUkdCQV8zMkJQUDsKICAgIGltZy5kYXRhID0gaW1nRGF0YTsKICB9CiAgZm5BcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBPUFMucGFpbnRJbmxpbmVJbWFnZVhPYmplY3RHcm91cCk7CiAgYXJnc0FycmF5LnNwbGljZShpRmlyc3RTYXZlLCBjb3VudCAqIDQsIFtpbWcsIG1hcF0pOwogIHJldHVybiBpRmlyc3RTYXZlICsgMTsKfSk7CmFkZFN0YXRlKEluaXRpYWxTdGF0ZSwgW09QUy5zYXZlLCBPUFMudHJhbnNmb3JtLCBPUFMucGFpbnRJbWFnZU1hc2tYT2JqZWN0LCBPUFMucmVzdG9yZV0sIG51bGwsIGZ1bmN0aW9uIGl0ZXJhdGVJbWFnZU1hc2tHcm91cChjb250ZXh0LCBpKSB7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheTsKICBjb25zdCBpRmlyc3RTYXZlID0gY29udGV4dC5pQ3VyciAtIDM7CiAgY29uc3QgcG9zID0gKGkgLSBpRmlyc3RTYXZlKSAlIDQ7CiAgc3dpdGNoIChwb3MpIHsKICAgIGNhc2UgMDoKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IE9QUy5zYXZlOwogICAgY2FzZSAxOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnRyYW5zZm9ybTsKICAgIGNhc2UgMjoKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IE9QUy5wYWludEltYWdlTWFza1hPYmplY3Q7CiAgICBjYXNlIDM6CiAgICAgIHJldHVybiBmbkFycmF5W2ldID09PSBPUFMucmVzdG9yZTsKICB9CiAgdGhyb3cgbmV3IEVycm9yKGBpdGVyYXRlSW1hZ2VNYXNrR3JvdXAgLSBpbnZhbGlkIHBvczogJHtwb3N9YCk7Cn0sIGZ1bmN0aW9uIGZvdW5kSW1hZ2VNYXNrR3JvdXAoY29udGV4dCwgaSkgewogIGNvbnN0IE1JTl9JTUFHRVNfSU5fTUFTS1NfQkxPQ0sgPSAxMDsKICBjb25zdCBNQVhfSU1BR0VTX0lOX01BU0tTX0JMT0NLID0gMTAwOwogIGNvbnN0IE1BWF9TQU1FX0lNQUdFU19JTl9NQVNLU19CTE9DSyA9IDEwMDA7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGN1cnIgPSBjb250ZXh0LmlDdXJyOwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjdXJyIC0gMzsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RQSU1YTyA9IGN1cnIgLSAxOwogIGxldCBjb3VudCA9IE1hdGguZmxvb3IoKGkgLSBpRmlyc3RTYXZlKSAvIDQpOwogIGlmIChjb3VudCA8IE1JTl9JTUFHRVNfSU5fTUFTS1NfQkxPQ0spIHsKICAgIHJldHVybiBpIC0gKGkgLSBpRmlyc3RTYXZlKSAlIDQ7CiAgfQogIGxldCBpc1NhbWVJbWFnZSA9IGZhbHNlOwogIGxldCBpVHJhbnNmb3JtLCB0cmFuc2Zvcm1BcmdzOwogIGNvbnN0IGZpcnN0UElNWE9BcmcwID0gYXJnc0FycmF5W2lGaXJzdFBJTVhPXVswXTsKICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzAgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVswXSwKICAgIGZpcnN0VHJhbnNmb3JtQXJnMSA9IGFyZ3NBcnJheVtpRmlyc3RUcmFuc2Zvcm1dWzFdLAogICAgZmlyc3RUcmFuc2Zvcm1BcmcyID0gYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybV1bMl0sCiAgICBmaXJzdFRyYW5zZm9ybUFyZzMgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVszXTsKICBpZiAoZmlyc3RUcmFuc2Zvcm1BcmcxID09PSBmaXJzdFRyYW5zZm9ybUFyZzIpIHsKICAgIGlzU2FtZUltYWdlID0gdHJ1ZTsKICAgIGlUcmFuc2Zvcm0gPSBpRmlyc3RUcmFuc2Zvcm0gKyA0OwogICAgbGV0IGlQSU1YTyA9IGlGaXJzdFBJTVhPICsgNDsKICAgIGZvciAobGV0IHEgPSAxOyBxIDwgY291bnQ7IHErKywgaVRyYW5zZm9ybSArPSA0LCBpUElNWE8gKz0gNCkgewogICAgICB0cmFuc2Zvcm1BcmdzID0gYXJnc0FycmF5W2lUcmFuc2Zvcm1dOwogICAgICBpZiAoYXJnc0FycmF5W2lQSU1YT11bMF0gIT09IGZpcnN0UElNWE9BcmcwIHx8IHRyYW5zZm9ybUFyZ3NbMF0gIT09IGZpcnN0VHJhbnNmb3JtQXJnMCB8fCB0cmFuc2Zvcm1BcmdzWzFdICE9PSBmaXJzdFRyYW5zZm9ybUFyZzEgfHwgdHJhbnNmb3JtQXJnc1syXSAhPT0gZmlyc3RUcmFuc2Zvcm1BcmcyIHx8IHRyYW5zZm9ybUFyZ3NbM10gIT09IGZpcnN0VHJhbnNmb3JtQXJnMykgewogICAgICAgIGlmIChxIDwgTUlOX0lNQUdFU19JTl9NQVNLU19CTE9DSykgewogICAgICAgICAgaXNTYW1lSW1hZ2UgPSBmYWxzZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY291bnQgPSBxOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogIH0KICBpZiAoaXNTYW1lSW1hZ2UpIHsKICAgIGNvdW50ID0gTWF0aC5taW4oY291bnQsIE1BWF9TQU1FX0lNQUdFU19JTl9NQVNLU19CTE9DSyk7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KGNvdW50ICogMik7CiAgICBpVHJhbnNmb3JtID0gaUZpcnN0VHJhbnNmb3JtOwogICAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrLCBpVHJhbnNmb3JtICs9IDQpIHsKICAgICAgdHJhbnNmb3JtQXJncyA9IGFyZ3NBcnJheVtpVHJhbnNmb3JtXTsKICAgICAgcG9zaXRpb25zW3EgPDwgMV0gPSB0cmFuc2Zvcm1BcmdzWzRdOwogICAgICBwb3NpdGlvbnNbKHEgPDwgMSkgKyAxXSA9IHRyYW5zZm9ybUFyZ3NbNV07CiAgICB9CiAgICBmbkFycmF5LnNwbGljZShpRmlyc3RTYXZlLCBjb3VudCAqIDQsIE9QUy5wYWludEltYWdlTWFza1hPYmplY3RSZXBlYXQpOwogICAgYXJnc0FycmF5LnNwbGljZShpRmlyc3RTYXZlLCBjb3VudCAqIDQsIFtmaXJzdFBJTVhPQXJnMCwgZmlyc3RUcmFuc2Zvcm1BcmcwLCBmaXJzdFRyYW5zZm9ybUFyZzEsIGZpcnN0VHJhbnNmb3JtQXJnMiwgZmlyc3RUcmFuc2Zvcm1BcmczLCBwb3NpdGlvbnNdKTsKICB9IGVsc2UgewogICAgY291bnQgPSBNYXRoLm1pbihjb3VudCwgTUFYX0lNQUdFU19JTl9NQVNLU19CTE9DSyk7CiAgICBjb25zdCBpbWFnZXMgPSBbXTsKICAgIGZvciAobGV0IHEgPSAwOyBxIDwgY291bnQ7IHErKykgewogICAgICB0cmFuc2Zvcm1BcmdzID0gYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybSArIChxIDw8IDIpXTsKICAgICAgY29uc3QgbWFza1BhcmFtcyA9IGFyZ3NBcnJheVtpRmlyc3RQSU1YTyArIChxIDw8IDIpXVswXTsKICAgICAgaW1hZ2VzLnB1c2goewogICAgICAgIGRhdGE6IG1hc2tQYXJhbXMuZGF0YSwKICAgICAgICB3aWR0aDogbWFza1BhcmFtcy53aWR0aCwKICAgICAgICBoZWlnaHQ6IG1hc2tQYXJhbXMuaGVpZ2h0LAogICAgICAgIGludGVycG9sYXRlOiBtYXNrUGFyYW1zLmludGVycG9sYXRlLAogICAgICAgIGNvdW50OiBtYXNrUGFyYW1zLmNvdW50LAogICAgICAgIHRyYW5zZm9ybTogdHJhbnNmb3JtQXJncwogICAgICB9KTsKICAgIH0KICAgIGZuQXJyYXkuc3BsaWNlKGlGaXJzdFNhdmUsIGNvdW50ICogNCwgT1BTLnBhaW50SW1hZ2VNYXNrWE9iamVjdEdyb3VwKTsKICAgIGFyZ3NBcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBbaW1hZ2VzXSk7CiAgfQogIHJldHVybiBpRmlyc3RTYXZlICsgMTsKfSk7CmFkZFN0YXRlKEluaXRpYWxTdGF0ZSwgW09QUy5zYXZlLCBPUFMudHJhbnNmb3JtLCBPUFMucGFpbnRJbWFnZVhPYmplY3QsIE9QUy5yZXN0b3JlXSwgZnVuY3Rpb24gKGNvbnRleHQpIHsKICBjb25zdCBhcmdzQXJyYXkgPSBjb250ZXh0LmFyZ3NBcnJheTsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjb250ZXh0LmlDdXJyIC0gMjsKICByZXR1cm4gYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybV1bMV0gPT09IDAgJiYgYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybV1bMl0gPT09IDA7Cn0sIGZ1bmN0aW9uIGl0ZXJhdGVJbWFnZUdyb3VwKGNvbnRleHQsIGkpIHsKICBjb25zdCBmbkFycmF5ID0gY29udGV4dC5mbkFycmF5LAogICAgYXJnc0FycmF5ID0gY29udGV4dC5hcmdzQXJyYXk7CiAgY29uc3QgaUZpcnN0U2F2ZSA9IGNvbnRleHQuaUN1cnIgLSAzOwogIGNvbnN0IHBvcyA9IChpIC0gaUZpcnN0U2F2ZSkgJSA0OwogIHN3aXRjaCAocG9zKSB7CiAgICBjYXNlIDA6CiAgICAgIHJldHVybiBmbkFycmF5W2ldID09PSBPUFMuc2F2ZTsKICAgIGNhc2UgMToKICAgICAgaWYgKGZuQXJyYXlbaV0gIT09IE9QUy50cmFuc2Zvcm0pIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgaUZpcnN0VHJhbnNmb3JtID0gY29udGV4dC5pQ3VyciAtIDI7CiAgICAgIGNvbnN0IGZpcnN0VHJhbnNmb3JtQXJnMCA9IGFyZ3NBcnJheVtpRmlyc3RUcmFuc2Zvcm1dWzBdOwogICAgICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzMgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVszXTsKICAgICAgaWYgKGFyZ3NBcnJheVtpXVswXSAhPT0gZmlyc3RUcmFuc2Zvcm1BcmcwIHx8IGFyZ3NBcnJheVtpXVsxXSAhPT0gMCB8fCBhcmdzQXJyYXlbaV1bMl0gIT09IDAgfHwgYXJnc0FycmF5W2ldWzNdICE9PSBmaXJzdFRyYW5zZm9ybUFyZzMpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgcmV0dXJuIHRydWU7CiAgICBjYXNlIDI6CiAgICAgIGlmIChmbkFycmF5W2ldICE9PSBPUFMucGFpbnRJbWFnZVhPYmplY3QpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgaUZpcnN0UElYTyA9IGNvbnRleHQuaUN1cnIgLSAxOwogICAgICBjb25zdCBmaXJzdFBJWE9BcmcwID0gYXJnc0FycmF5W2lGaXJzdFBJWE9dWzBdOwogICAgICBpZiAoYXJnc0FycmF5W2ldWzBdICE9PSBmaXJzdFBJWE9BcmcwKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIHJldHVybiB0cnVlOwogICAgY2FzZSAzOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnJlc3RvcmU7CiAgfQogIHRocm93IG5ldyBFcnJvcihgaXRlcmF0ZUltYWdlR3JvdXAgLSBpbnZhbGlkIHBvczogJHtwb3N9YCk7Cn0sIGZ1bmN0aW9uIChjb250ZXh0LCBpKSB7CiAgY29uc3QgTUlOX0lNQUdFU19JTl9CTE9DSyA9IDM7CiAgY29uc3QgTUFYX0lNQUdFU19JTl9CTE9DSyA9IDEwMDA7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGN1cnIgPSBjb250ZXh0LmlDdXJyOwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjdXJyIC0gMzsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RQSVhPID0gY3VyciAtIDE7CiAgY29uc3QgZmlyc3RQSVhPQXJnMCA9IGFyZ3NBcnJheVtpRmlyc3RQSVhPXVswXTsKICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzAgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVswXTsKICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzMgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVszXTsKICBjb25zdCBjb3VudCA9IE1hdGgubWluKE1hdGguZmxvb3IoKGkgLSBpRmlyc3RTYXZlKSAvIDQpLCBNQVhfSU1BR0VTX0lOX0JMT0NLKTsKICBpZiAoY291bnQgPCBNSU5fSU1BR0VTX0lOX0JMT0NLKSB7CiAgICByZXR1cm4gaSAtIChpIC0gaUZpcnN0U2F2ZSkgJSA0OwogIH0KICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KGNvdW50ICogMik7CiAgbGV0IGlUcmFuc2Zvcm0gPSBpRmlyc3RUcmFuc2Zvcm07CiAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrLCBpVHJhbnNmb3JtICs9IDQpIHsKICAgIGNvbnN0IHRyYW5zZm9ybUFyZ3MgPSBhcmdzQXJyYXlbaVRyYW5zZm9ybV07CiAgICBwb3NpdGlvbnNbcSA8PCAxXSA9IHRyYW5zZm9ybUFyZ3NbNF07CiAgICBwb3NpdGlvbnNbKHEgPDwgMSkgKyAxXSA9IHRyYW5zZm9ybUFyZ3NbNV07CiAgfQogIGNvbnN0IGFyZ3MgPSBbZmlyc3RQSVhPQXJnMCwgZmlyc3RUcmFuc2Zvcm1BcmcwLCBmaXJzdFRyYW5zZm9ybUFyZzMsIHBvc2l0aW9uc107CiAgZm5BcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBPUFMucGFpbnRJbWFnZVhPYmplY3RSZXBlYXQpOwogIGFyZ3NBcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBhcmdzKTsKICByZXR1cm4gaUZpcnN0U2F2ZSArIDE7Cn0pOwphZGRTdGF0ZShJbml0aWFsU3RhdGUsIFtPUFMuYmVnaW5UZXh0LCBPUFMuc2V0Rm9udCwgT1BTLnNldFRleHRNYXRyaXgsIE9QUy5zaG93VGV4dCwgT1BTLmVuZFRleHRdLCBudWxsLCBmdW5jdGlvbiBpdGVyYXRlU2hvd1RleHRHcm91cChjb250ZXh0LCBpKSB7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjb250ZXh0LmlDdXJyIC0gNDsKICBjb25zdCBwb3MgPSAoaSAtIGlGaXJzdFNhdmUpICUgNTsKICBzd2l0Y2ggKHBvcykgewogICAgY2FzZSAwOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLmJlZ2luVGV4dDsKICAgIGNhc2UgMToKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IE9QUy5zZXRGb250OwogICAgY2FzZSAyOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnNldFRleHRNYXRyaXg7CiAgICBjYXNlIDM6CiAgICAgIGlmIChmbkFycmF5W2ldICE9PSBPUFMuc2hvd1RleHQpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgaUZpcnN0U2V0Rm9udCA9IGNvbnRleHQuaUN1cnIgLSAzOwogICAgICBjb25zdCBmaXJzdFNldEZvbnRBcmcwID0gYXJnc0FycmF5W2lGaXJzdFNldEZvbnRdWzBdOwogICAgICBjb25zdCBmaXJzdFNldEZvbnRBcmcxID0gYXJnc0FycmF5W2lGaXJzdFNldEZvbnRdWzFdOwogICAgICBpZiAoYXJnc0FycmF5W2ldWzBdICE9PSBmaXJzdFNldEZvbnRBcmcwIHx8IGFyZ3NBcnJheVtpXVsxXSAhPT0gZmlyc3RTZXRGb250QXJnMSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICByZXR1cm4gdHJ1ZTsKICAgIGNhc2UgNDoKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IE9QUy5lbmRUZXh0OwogIH0KICB0aHJvdyBuZXcgRXJyb3IoYGl0ZXJhdGVTaG93VGV4dEdyb3VwIC0gaW52YWxpZCBwb3M6ICR7cG9zfWApOwp9LCBmdW5jdGlvbiAoY29udGV4dCwgaSkgewogIGNvbnN0IE1JTl9DSEFSU19JTl9CTE9DSyA9IDM7CiAgY29uc3QgTUFYX0NIQVJTX0lOX0JMT0NLID0gMTAwMDsKICBjb25zdCBmbkFycmF5ID0gY29udGV4dC5mbkFycmF5LAogICAgYXJnc0FycmF5ID0gY29udGV4dC5hcmdzQXJyYXk7CiAgY29uc3QgY3VyciA9IGNvbnRleHQuaUN1cnI7CiAgY29uc3QgaUZpcnN0QmVnaW5UZXh0ID0gY3VyciAtIDQ7CiAgY29uc3QgaUZpcnN0U2V0Rm9udCA9IGN1cnIgLSAzOwogIGNvbnN0IGlGaXJzdFNldFRleHRNYXRyaXggPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RTaG93VGV4dCA9IGN1cnIgLSAxOwogIGNvbnN0IGlGaXJzdEVuZFRleHQgPSBjdXJyOwogIGNvbnN0IGZpcnN0U2V0Rm9udEFyZzAgPSBhcmdzQXJyYXlbaUZpcnN0U2V0Rm9udF1bMF07CiAgY29uc3QgZmlyc3RTZXRGb250QXJnMSA9IGFyZ3NBcnJheVtpRmlyc3RTZXRGb250XVsxXTsKICBsZXQgY291bnQgPSBNYXRoLm1pbihNYXRoLmZsb29yKChpIC0gaUZpcnN0QmVnaW5UZXh0KSAvIDUpLCBNQVhfQ0hBUlNfSU5fQkxPQ0spOwogIGlmIChjb3VudCA8IE1JTl9DSEFSU19JTl9CTE9DSykgewogICAgcmV0dXJuIGkgLSAoaSAtIGlGaXJzdEJlZ2luVGV4dCkgJSA1OwogIH0KICBsZXQgaUZpcnN0ID0gaUZpcnN0QmVnaW5UZXh0OwogIGlmIChpRmlyc3RCZWdpblRleHQgPj0gNCAmJiBmbkFycmF5W2lGaXJzdEJlZ2luVGV4dCAtIDRdID09PSBmbkFycmF5W2lGaXJzdFNldEZvbnRdICYmIGZuQXJyYXlbaUZpcnN0QmVnaW5UZXh0IC0gM10gPT09IGZuQXJyYXlbaUZpcnN0U2V0VGV4dE1hdHJpeF0gJiYgZm5BcnJheVtpRmlyc3RCZWdpblRleHQgLSAyXSA9PT0gZm5BcnJheVtpRmlyc3RTaG93VGV4dF0gJiYgZm5BcnJheVtpRmlyc3RCZWdpblRleHQgLSAxXSA9PT0gZm5BcnJheVtpRmlyc3RFbmRUZXh0XSAmJiBhcmdzQXJyYXlbaUZpcnN0QmVnaW5UZXh0IC0gNF1bMF0gPT09IGZpcnN0U2V0Rm9udEFyZzAgJiYgYXJnc0FycmF5W2lGaXJzdEJlZ2luVGV4dCAtIDRdWzFdID09PSBmaXJzdFNldEZvbnRBcmcxKSB7CiAgICBjb3VudCsrOwogICAgaUZpcnN0IC09IDU7CiAgfQogIGxldCBpRW5kVGV4dCA9IGlGaXJzdCArIDQ7CiAgZm9yIChsZXQgcSA9IDE7IHEgPCBjb3VudDsgcSsrKSB7CiAgICBmbkFycmF5LnNwbGljZShpRW5kVGV4dCwgMyk7CiAgICBhcmdzQXJyYXkuc3BsaWNlKGlFbmRUZXh0LCAzKTsKICAgIGlFbmRUZXh0ICs9IDI7CiAgfQogIHJldHVybiBpRW5kVGV4dCArIDE7Cn0pOwphZGRTdGF0ZShJbml0aWFsU3RhdGUsIFtPUFMuc2F2ZSwgT1BTLnRyYW5zZm9ybSwgT1BTLmNvbnN0cnVjdFBhdGgsIE9QUy5yZXN0b3JlXSwgY29udGV4dCA9PiB7CiAgY29uc3QgYXJnc0FycmF5ID0gY29udGV4dC5hcmdzQXJyYXk7CiAgY29uc3QgaUZpcnN0Q29uc3RydWN0UGF0aCA9IGNvbnRleHQuaUN1cnIgLSAxOwogIGNvbnN0IG9wID0gYXJnc0FycmF5W2lGaXJzdENvbnN0cnVjdFBhdGhdWzBdOwogIGlmIChvcCAhPT0gT1BTLnN0cm9rZSAmJiBvcCAhPT0gT1BTLmNsb3NlU3Ryb2tlICYmIG9wICE9PSBPUFMuZmlsbFN0cm9rZSAmJiBvcCAhPT0gT1BTLmVvRmlsbFN0cm9rZSAmJiBvcCAhPT0gT1BTLmNsb3NlRmlsbFN0cm9rZSAmJiBvcCAhPT0gT1BTLmNsb3NlRU9GaWxsU3Ryb2tlKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgY29uc3QgaUZpcnN0VHJhbnNmb3JtID0gY29udGV4dC5pQ3VyciAtIDI7CiAgY29uc3QgdHJhbnNmb3JtID0gYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybV07CiAgcmV0dXJuIHRyYW5zZm9ybVswXSA9PT0gMSAmJiB0cmFuc2Zvcm1bMV0gPT09IDAgJiYgdHJhbnNmb3JtWzJdID09PSAwICYmIHRyYW5zZm9ybVszXSA9PT0gMTsKfSwgKCkgPT4gZmFsc2UsIChjb250ZXh0LCBpKSA9PiB7CiAgY29uc3QgewogICAgZm5BcnJheSwKICAgIGFyZ3NBcnJheQogIH0gPSBjb250ZXh0OwogIGNvbnN0IGN1cnIgPSBjb250ZXh0LmlDdXJyOwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjdXJyIC0gMzsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RDb25zdHJ1Y3RQYXRoID0gY3VyciAtIDE7CiAgY29uc3QgYXJncyA9IGFyZ3NBcnJheVtpRmlyc3RDb25zdHJ1Y3RQYXRoXTsKICBjb25zdCB0cmFuc2Zvcm0gPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXTsKICBjb25zdCBbLCBbYnVmZmVyXSwgbWluTWF4XSA9IGFyZ3M7CiAgaWYgKG1pbk1heCkgewogICAgVXRpbC5zY2FsZU1pbk1heCh0cmFuc2Zvcm0sIG1pbk1heCk7CiAgICBmb3IgKGxldCBrID0gMCwga2sgPSBidWZmZXIubGVuZ3RoOyBrIDwga2s7KSB7CiAgICAgIHN3aXRjaCAoYnVmZmVyW2srK10pIHsKICAgICAgICBjYXNlIERyYXdPUFMubW92ZVRvOgogICAgICAgIGNhc2UgRHJhd09QUy5saW5lVG86CiAgICAgICAgICBVdGlsLmFwcGx5VHJhbnNmb3JtKGJ1ZmZlciwgdHJhbnNmb3JtLCBrKTsKICAgICAgICAgIGsgKz0gMjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgRHJhd09QUy5jdXJ2ZVRvOgogICAgICAgICAgVXRpbC5hcHBseVRyYW5zZm9ybVRvQmV6aWVyKGJ1ZmZlciwgdHJhbnNmb3JtLCBrKTsKICAgICAgICAgIGsgKz0gNjsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQogIGZuQXJyYXkuc3BsaWNlKGlGaXJzdFNhdmUsIDQsIE9QUy5jb25zdHJ1Y3RQYXRoKTsKICBhcmdzQXJyYXkuc3BsaWNlKGlGaXJzdFNhdmUsIDQsIGFyZ3MpOwogIHJldHVybiBpRmlyc3RTYXZlICsgMTsKfSk7CmNsYXNzIE51bGxPcHRpbWl6ZXIgewogIGNvbnN0cnVjdG9yKHF1ZXVlKSB7CiAgICB0aGlzLnF1ZXVlID0gcXVldWU7CiAgfQogIF9vcHRpbWl6ZSgpIHt9CiAgcHVzaChmbiwgYXJncykgewogICAgdGhpcy5xdWV1ZS5mbkFycmF5LnB1c2goZm4pOwogICAgdGhpcy5xdWV1ZS5hcmdzQXJyYXkucHVzaChhcmdzKTsKICAgIHRoaXMuX29wdGltaXplKCk7CiAgfQogIGZsdXNoKCkge30KICByZXNldCgpIHt9Cn0KY2xhc3MgUXVldWVPcHRpbWl6ZXIgZXh0ZW5kcyBOdWxsT3B0aW1pemVyIHsKICBjb25zdHJ1Y3RvcihxdWV1ZSkgewogICAgc3VwZXIocXVldWUpOwogICAgdGhpcy5zdGF0ZSA9IG51bGw7CiAgICB0aGlzLmNvbnRleHQgPSB7CiAgICAgIGlDdXJyOiAwLAogICAgICBmbkFycmF5OiBxdWV1ZS5mbkFycmF5LAogICAgICBhcmdzQXJyYXk6IHF1ZXVlLmFyZ3NBcnJheSwKICAgICAgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQ6IE9wZXJhdG9yTGlzdC5pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZAogICAgfTsKICAgIHRoaXMubWF0Y2ggPSBudWxsOwogICAgdGhpcy5sYXN0UHJvY2Vzc2VkID0gMDsKICB9CiAgX29wdGltaXplKCkgewogICAgY29uc3QgZm5BcnJheSA9IHRoaXMucXVldWUuZm5BcnJheTsKICAgIGxldCBpID0gdGhpcy5sYXN0UHJvY2Vzc2VkLAogICAgICBpaSA9IGZuQXJyYXkubGVuZ3RoOwogICAgbGV0IHN0YXRlID0gdGhpcy5zdGF0ZTsKICAgIGxldCBtYXRjaCA9IHRoaXMubWF0Y2g7CiAgICBpZiAoIXN0YXRlICYmICFtYXRjaCAmJiBpICsgMSA9PT0gaWkgJiYgIUluaXRpYWxTdGF0ZVtmbkFycmF5W2ldXSkgewogICAgICB0aGlzLmxhc3RQcm9jZXNzZWQgPSBpaTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgY29udGV4dCA9IHRoaXMuY29udGV4dDsKICAgIHdoaWxlIChpIDwgaWkpIHsKICAgICAgaWYgKG1hdGNoKSB7CiAgICAgICAgY29uc3QgaXRlcmF0ZSA9ICgwLCBtYXRjaC5pdGVyYXRlRm4pKGNvbnRleHQsIGkpOwogICAgICAgIGlmIChpdGVyYXRlKSB7CiAgICAgICAgICBpKys7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaSA9ICgwLCBtYXRjaC5wcm9jZXNzRm4pKGNvbnRleHQsIGkgKyAxKTsKICAgICAgICBpaSA9IGZuQXJyYXkubGVuZ3RoOwogICAgICAgIG1hdGNoID0gbnVsbDsKICAgICAgICBzdGF0ZSA9IG51bGw7CiAgICAgICAgaWYgKGkgPj0gaWkpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBzdGF0ZSA9IChzdGF0ZSB8fCBJbml0aWFsU3RhdGUpW2ZuQXJyYXlbaV1dOwogICAgICBpZiAoIXN0YXRlIHx8IEFycmF5LmlzQXJyYXkoc3RhdGUpKSB7CiAgICAgICAgaSsrOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnRleHQuaUN1cnIgPSBpOwogICAgICBpKys7CiAgICAgIGlmIChzdGF0ZS5jaGVja0ZuICYmICEoMCwgc3RhdGUuY2hlY2tGbikoY29udGV4dCkpIHsKICAgICAgICBzdGF0ZSA9IG51bGw7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbWF0Y2ggPSBzdGF0ZTsKICAgICAgc3RhdGUgPSBudWxsOwogICAgfQogICAgdGhpcy5zdGF0ZSA9IHN0YXRlOwogICAgdGhpcy5tYXRjaCA9IG1hdGNoOwogICAgdGhpcy5sYXN0UHJvY2Vzc2VkID0gaTsKICB9CiAgZmx1c2goKSB7CiAgICB3aGlsZSAodGhpcy5tYXRjaCkgewogICAgICBjb25zdCBsZW5ndGggPSB0aGlzLnF1ZXVlLmZuQXJyYXkubGVuZ3RoOwogICAgICB0aGlzLmxhc3RQcm9jZXNzZWQgPSAoMCwgdGhpcy5tYXRjaC5wcm9jZXNzRm4pKHRoaXMuY29udGV4dCwgbGVuZ3RoKTsKICAgICAgdGhpcy5tYXRjaCA9IG51bGw7CiAgICAgIHRoaXMuc3RhdGUgPSBudWxsOwogICAgICB0aGlzLl9vcHRpbWl6ZSgpOwogICAgfQogIH0KICByZXNldCgpIHsKICAgIHRoaXMuc3RhdGUgPSBudWxsOwogICAgdGhpcy5tYXRjaCA9IG51bGw7CiAgICB0aGlzLmxhc3RQcm9jZXNzZWQgPSAwOwogIH0KfQpjbGFzcyBPcGVyYXRvckxpc3QgewogIHN0YXRpYyBDSFVOS19TSVpFID0gMTAwMDsKICBzdGF0aWMgQ0hVTktfU0laRV9BQk9VVCA9IHRoaXMuQ0hVTktfU0laRSAtIDU7CiAgc3RhdGljIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkID0gZmFsc2U7CiAgY29uc3RydWN0b3IoaW50ZW50ID0gMCwgc3RyZWFtU2luaykgewogICAgdGhpcy5fc3RyZWFtU2luayA9IHN0cmVhbVNpbms7CiAgICB0aGlzLmZuQXJyYXkgPSBbXTsKICAgIHRoaXMuYXJnc0FycmF5ID0gW107CiAgICB0aGlzLm9wdGltaXplciA9IHN0cmVhbVNpbmsgJiYgIShpbnRlbnQgJiBSZW5kZXJpbmdJbnRlbnRGbGFnLk9QTElTVCkgPyBuZXcgUXVldWVPcHRpbWl6ZXIodGhpcykgOiBuZXcgTnVsbE9wdGltaXplcih0aGlzKTsKICAgIHRoaXMuZGVwZW5kZW5jaWVzID0gbmV3IFNldCgpOwogICAgdGhpcy5fdG90YWxMZW5ndGggPSAwOwogICAgdGhpcy53ZWlnaHQgPSAwOwogICAgdGhpcy5fcmVzb2x2ZWQgPSBzdHJlYW1TaW5rID8gbnVsbCA6IFByb21pc2UucmVzb2x2ZSgpOwogIH0KICBzdGF0aWMgc2V0T3B0aW9ucyh7CiAgICBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZAogIH0pIHsKICAgIHRoaXMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgPSBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZDsKICB9CiAgZ2V0IGxlbmd0aCgpIHsKICAgIHJldHVybiB0aGlzLmFyZ3NBcnJheS5sZW5ndGg7CiAgfQogIGdldCByZWFkeSgpIHsKICAgIHJldHVybiB0aGlzLl9yZXNvbHZlZCB8fCB0aGlzLl9zdHJlYW1TaW5rLnJlYWR5OwogIH0KICBnZXQgdG90YWxMZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5fdG90YWxMZW5ndGggKyB0aGlzLmxlbmd0aDsKICB9CiAgYWRkT3AoZm4sIGFyZ3MpIHsKICAgIHRoaXMub3B0aW1pemVyLnB1c2goZm4sIGFyZ3MpOwogICAgdGhpcy53ZWlnaHQrKzsKICAgIGlmICh0aGlzLl9zdHJlYW1TaW5rKSB7CiAgICAgIGlmICh0aGlzLndlaWdodCA+PSBPcGVyYXRvckxpc3QuQ0hVTktfU0laRSkgewogICAgICAgIHRoaXMuZmx1c2goKTsKICAgICAgfSBlbHNlIGlmICh0aGlzLndlaWdodCA+PSBPcGVyYXRvckxpc3QuQ0hVTktfU0laRV9BQk9VVCAmJiAoZm4gPT09IE9QUy5yZXN0b3JlIHx8IGZuID09PSBPUFMuZW5kVGV4dCkpIHsKICAgICAgICB0aGlzLmZsdXNoKCk7CiAgICAgIH0KICAgIH0KICB9CiAgYWRkSW1hZ2VPcHMoZm4sIGFyZ3MsIG9wdGlvbmFsQ29udGVudCwgaGFzTWFzayA9IGZhbHNlKSB7CiAgICBpZiAoaGFzTWFzaykgewogICAgICB0aGlzLmFkZE9wKE9QUy5zYXZlKTsKICAgICAgdGhpcy5hZGRPcChPUFMuc2V0R1N0YXRlLCBbW1siU01hc2siLCBmYWxzZV1dXSk7CiAgICB9CiAgICBpZiAob3B0aW9uYWxDb250ZW50ICE9PSB1bmRlZmluZWQpIHsKICAgICAgdGhpcy5hZGRPcChPUFMuYmVnaW5NYXJrZWRDb250ZW50UHJvcHMsIFsiT0MiLCBvcHRpb25hbENvbnRlbnRdKTsKICAgIH0KICAgIHRoaXMuYWRkT3AoZm4sIGFyZ3MpOwogICAgaWYgKG9wdGlvbmFsQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHRoaXMuYWRkT3AoT1BTLmVuZE1hcmtlZENvbnRlbnQsIFtdKTsKICAgIH0KICAgIGlmIChoYXNNYXNrKSB7CiAgICAgIHRoaXMuYWRkT3AoT1BTLnJlc3RvcmUpOwogICAgfQogIH0KICBhZGREZXBlbmRlbmN5KGRlcGVuZGVuY3kpIHsKICAgIGlmICh0aGlzLmRlcGVuZGVuY2llcy5oYXMoZGVwZW5kZW5jeSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5kZXBlbmRlbmNpZXMuYWRkKGRlcGVuZGVuY3kpOwogICAgdGhpcy5hZGRPcChPUFMuZGVwZW5kZW5jeSwgW2RlcGVuZGVuY3ldKTsKICB9CiAgYWRkRGVwZW5kZW5jaWVzKGRlcGVuZGVuY2llcykgewogICAgZm9yIChjb25zdCBkZXBlbmRlbmN5IG9mIGRlcGVuZGVuY2llcykgewogICAgICB0aGlzLmFkZERlcGVuZGVuY3koZGVwZW5kZW5jeSk7CiAgICB9CiAgfQogIGFkZE9wTGlzdChvcExpc3QpIHsKICAgIGlmICghKG9wTGlzdCBpbnN0YW5jZW9mIE9wZXJhdG9yTGlzdCkpIHsKICAgICAgd2FybignYWRkT3BMaXN0IC0gaWdub3JpbmcgaW52YWxpZCAib3BMaXN0IiBwYXJhbWV0ZXIuJyk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGZvciAoY29uc3QgZGVwZW5kZW5jeSBvZiBvcExpc3QuZGVwZW5kZW5jaWVzKSB7CiAgICAgIHRoaXMuZGVwZW5kZW5jaWVzLmFkZChkZXBlbmRlbmN5KTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IG9wTGlzdC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIHRoaXMuYWRkT3Aob3BMaXN0LmZuQXJyYXlbaV0sIG9wTGlzdC5hcmdzQXJyYXlbaV0pOwogICAgfQogIH0KICBnZXRJUigpIHsKICAgIHJldHVybiB7CiAgICAgIGZuQXJyYXk6IHRoaXMuZm5BcnJheSwKICAgICAgYXJnc0FycmF5OiB0aGlzLmFyZ3NBcnJheSwKICAgICAgbGVuZ3RoOiB0aGlzLmxlbmd0aAogICAgfTsKICB9CiAgZ2V0IF90cmFuc2ZlcnMoKSB7CiAgICBjb25zdCB0cmFuc2ZlcnMgPSBbXTsKICAgIGNvbnN0IHsKICAgICAgZm5BcnJheSwKICAgICAgYXJnc0FycmF5LAogICAgICBsZW5ndGgKICAgIH0gPSB0aGlzOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBzd2l0Y2ggKGZuQXJyYXlbaV0pIHsKICAgICAgICBjYXNlIE9QUy5wYWludElubGluZUltYWdlWE9iamVjdDoKICAgICAgICBjYXNlIE9QUy5wYWludElubGluZUltYWdlWE9iamVjdEdyb3VwOgogICAgICAgIGNhc2UgT1BTLnBhaW50SW1hZ2VNYXNrWE9iamVjdDoKICAgICAgICAgIHsKICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgIGJpdG1hcCwKICAgICAgICAgICAgICBkYXRhCiAgICAgICAgICAgIH0gPSBhcmdzQXJyYXlbaV1bMF07CiAgICAgICAgICAgIGlmIChiaXRtYXAgfHwgZGF0YT8uYnVmZmVyKSB7CiAgICAgICAgICAgICAgdHJhbnNmZXJzLnB1c2goYml0bWFwIHx8IGRhdGEuYnVmZmVyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICBjYXNlIE9QUy5jb25zdHJ1Y3RQYXRoOgogICAgICAgICAgewogICAgICAgICAgICBjb25zdCBbLCBbZGF0YV0sIG1pbk1heF0gPSBhcmdzQXJyYXlbaV07CiAgICAgICAgICAgIGlmIChkYXRhKSB7CiAgICAgICAgICAgICAgdHJhbnNmZXJzLnB1c2goZGF0YS5idWZmZXIsIG1pbk1heC5idWZmZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIGNhc2UgT1BTLnBhaW50Rm9ybVhPYmplY3RCZWdpbjoKICAgICAgICAgIGNvbnN0IFttYXRyaXgsIGJib3hdID0gYXJnc0FycmF5W2ldOwogICAgICAgICAgaWYgKG1hdHJpeCkgewogICAgICAgICAgICB0cmFuc2ZlcnMucHVzaChtYXRyaXguYnVmZmVyKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChiYm94KSB7CiAgICAgICAgICAgIHRyYW5zZmVycy5wdXNoKGJib3guYnVmZmVyKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgT1BTLnNldFRleHRNYXRyaXg6CiAgICAgICAgICB0cmFuc2ZlcnMucHVzaChhcmdzQXJyYXlbaV1bMF0uYnVmZmVyKTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJhbnNmZXJzOwogIH0KICBmbHVzaChsYXN0Q2h1bmsgPSBmYWxzZSwgc2VwYXJhdGVBbm5vdHMgPSBudWxsKSB7CiAgICB0aGlzLm9wdGltaXplci5mbHVzaCgpOwogICAgY29uc3QgbGVuZ3RoID0gdGhpcy5sZW5ndGg7CiAgICB0aGlzLl90b3RhbExlbmd0aCArPSBsZW5ndGg7CiAgICB0aGlzLl9zdHJlYW1TaW5rLmVucXVldWUoewogICAgICBmbkFycmF5OiB0aGlzLmZuQXJyYXksCiAgICAgIGFyZ3NBcnJheTogdGhpcy5hcmdzQXJyYXksCiAgICAgIGxhc3RDaHVuaywKICAgICAgc2VwYXJhdGVBbm5vdHMsCiAgICAgIGxlbmd0aAogICAgfSwgMSwgdGhpcy5fdHJhbnNmZXJzKTsKICAgIHRoaXMuZGVwZW5kZW5jaWVzLmNsZWFyKCk7CiAgICB0aGlzLmZuQXJyYXkubGVuZ3RoID0gMDsKICAgIHRoaXMuYXJnc0FycmF5Lmxlbmd0aCA9IDA7CiAgICB0aGlzLndlaWdodCA9IDA7CiAgICB0aGlzLm9wdGltaXplci5yZXNldCgpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvYmluYXJ5X2NtYXAuanMKCmZ1bmN0aW9uIGhleFRvSW50KGEsIHNpemUpIHsKICBsZXQgbiA9IDA7CiAgZm9yIChsZXQgaSA9IDA7IGkgPD0gc2l6ZTsgaSsrKSB7CiAgICBuID0gbiA8PCA4IHwgYVtpXTsKICB9CiAgcmV0dXJuIG4gPj4+IDA7Cn0KZnVuY3Rpb24gaGV4VG9TdHIoYSwgc2l6ZSkgewogIGlmIChzaXplID09PSAxKSB7CiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShhWzBdLCBhWzFdKTsKICB9CiAgaWYgKHNpemUgPT09IDMpIHsKICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGFbMF0sIGFbMV0sIGFbMl0sIGFbM10pOwogIH0KICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSguLi5hLnN1YmFycmF5KDAsIHNpemUgKyAxKSk7Cn0KZnVuY3Rpb24gYWRkSGV4KGEsIGIsIHNpemUpIHsKICBsZXQgYyA9IDA7CiAgZm9yIChsZXQgaSA9IHNpemU7IGkgPj0gMDsgaS0tKSB7CiAgICBjICs9IGFbaV0gKyBiW2ldOwogICAgYVtpXSA9IGMgJiAyNTU7CiAgICBjID4+PSA4OwogIH0KfQpmdW5jdGlvbiBpbmNIZXgoYSwgc2l6ZSkgewogIGxldCBjID0gMTsKICBmb3IgKGxldCBpID0gc2l6ZTsgaSA+PSAwICYmIGMgPiAwOyBpLS0pIHsKICAgIGMgKz0gYVtpXTsKICAgIGFbaV0gPSBjICYgMjU1OwogICAgYyA+Pj0gODsKICB9Cn0KY29uc3QgTUFYX05VTV9TSVpFID0gMTY7CmNvbnN0IE1BWF9FTkNPREVEX05VTV9TSVpFID0gMTk7CmNsYXNzIEJpbmFyeUNNYXBTdHJlYW0gewogIGNvbnN0cnVjdG9yKGRhdGEpIHsKICAgIHRoaXMuYnVmZmVyID0gZGF0YTsKICAgIHRoaXMucG9zID0gMDsKICAgIHRoaXMuZW5kID0gZGF0YS5sZW5ndGg7CiAgICB0aGlzLnRtcEJ1ZiA9IG5ldyBVaW50OEFycmF5KE1BWF9FTkNPREVEX05VTV9TSVpFKTsKICB9CiAgcmVhZEJ5dGUoKSB7CiAgICBpZiAodGhpcy5wb3MgPj0gdGhpcy5lbmQpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgcmV0dXJuIHRoaXMuYnVmZmVyW3RoaXMucG9zKytdOwogIH0KICByZWFkTnVtYmVyKCkgewogICAgbGV0IG4gPSAwOwogICAgbGV0IGxhc3Q7CiAgICBkbyB7CiAgICAgIGNvbnN0IGIgPSB0aGlzLnJlYWRCeXRlKCk7CiAgICAgIGlmIChiIDwgMCkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigidW5leHBlY3RlZCBFT0YgaW4gYmNtYXAiKTsKICAgICAgfQogICAgICBsYXN0ID0gIShiICYgMHg4MCk7CiAgICAgIG4gPSBuIDw8IDcgfCBiICYgMHg3ZjsKICAgIH0gd2hpbGUgKCFsYXN0KTsKICAgIHJldHVybiBuOwogIH0KICByZWFkU2lnbmVkKCkgewogICAgY29uc3QgbiA9IHRoaXMucmVhZE51bWJlcigpOwogICAgcmV0dXJuIG4gJiAxID8gfihuID4+PiAxKSA6IG4gPj4+IDE7CiAgfQogIHJlYWRIZXgobnVtLCBzaXplKSB7CiAgICBudW0uc2V0KHRoaXMuYnVmZmVyLnN1YmFycmF5KHRoaXMucG9zLCB0aGlzLnBvcyArIHNpemUgKyAxKSk7CiAgICB0aGlzLnBvcyArPSBzaXplICsgMTsKICB9CiAgcmVhZEhleE51bWJlcihudW0sIHNpemUpIHsKICAgIGxldCBsYXN0OwogICAgY29uc3Qgc3RhY2sgPSB0aGlzLnRtcEJ1ZjsKICAgIGxldCBzcCA9IDA7CiAgICBkbyB7CiAgICAgIGNvbnN0IGIgPSB0aGlzLnJlYWRCeXRlKCk7CiAgICAgIGlmIChiIDwgMCkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigidW5leHBlY3RlZCBFT0YgaW4gYmNtYXAiKTsKICAgICAgfQogICAgICBsYXN0ID0gIShiICYgMHg4MCk7CiAgICAgIHN0YWNrW3NwKytdID0gYiAmIDB4N2Y7CiAgICB9IHdoaWxlICghbGFzdCk7CiAgICBsZXQgaSA9IHNpemUsCiAgICAgIGJ1ZmZlciA9IDAsCiAgICAgIGJ1ZmZlclNpemUgPSAwOwogICAgd2hpbGUgKGkgPj0gMCkgewogICAgICB3aGlsZSAoYnVmZmVyU2l6ZSA8IDggJiYgc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgIGJ1ZmZlciB8PSBzdGFja1stLXNwXSA8PCBidWZmZXJTaXplOwogICAgICAgIGJ1ZmZlclNpemUgKz0gNzsKICAgICAgfQogICAgICBudW1baV0gPSBidWZmZXIgJiAyNTU7CiAgICAgIGktLTsKICAgICAgYnVmZmVyID4+PSA4OwogICAgICBidWZmZXJTaXplIC09IDg7CiAgICB9CiAgfQogIHJlYWRIZXhTaWduZWQobnVtLCBzaXplKSB7CiAgICB0aGlzLnJlYWRIZXhOdW1iZXIobnVtLCBzaXplKTsKICAgIGNvbnN0IHNpZ24gPSBudW1bc2l6ZV0gJiAxID8gMjU1IDogMDsKICAgIGxldCBjID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IHNpemU7IGkrKykgewogICAgICBjID0gKGMgJiAxKSA8PCA4IHwgbnVtW2ldOwogICAgICBudW1baV0gPSBjID4+IDEgXiBzaWduOwogICAgfQogIH0KICByZWFkU3RyaW5nKCkgewogICAgY29uc3QgbGVuID0gdGhpcy5yZWFkTnVtYmVyKCksCiAgICAgIGJ1ZiA9IG5ldyBBcnJheShsZW4pOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICBidWZbaV0gPSB0aGlzLnJlYWROdW1iZXIoKTsKICAgIH0KICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKC4uLmJ1Zik7CiAgfQp9CmNsYXNzIEJpbmFyeUNNYXBSZWFkZXIgewogIGFzeW5jIHByb2Nlc3MoZGF0YSwgY01hcCwgZXh0ZW5kKSB7CiAgICBjb25zdCBzdHJlYW0gPSBuZXcgQmluYXJ5Q01hcFN0cmVhbShkYXRhKTsKICAgIGNvbnN0IGhlYWRlciA9IHN0cmVhbS5yZWFkQnl0ZSgpOwogICAgY01hcC52ZXJ0aWNhbCA9ICEhKGhlYWRlciAmIDEpOwogICAgbGV0IHVzZUNNYXAgPSBudWxsOwogICAgY29uc3Qgc3RhcnQgPSBuZXcgVWludDhBcnJheShNQVhfTlVNX1NJWkUpOwogICAgY29uc3QgZW5kID0gbmV3IFVpbnQ4QXJyYXkoTUFYX05VTV9TSVpFKTsKICAgIGNvbnN0IGNoYXIgPSBuZXcgVWludDhBcnJheShNQVhfTlVNX1NJWkUpOwogICAgY29uc3QgY2hhckNvZGUgPSBuZXcgVWludDhBcnJheShNQVhfTlVNX1NJWkUpOwogICAgY29uc3QgdG1wID0gbmV3IFVpbnQ4QXJyYXkoTUFYX05VTV9TSVpFKTsKICAgIGxldCBjb2RlOwogICAgbGV0IGI7CiAgICB3aGlsZSAoKGIgPSBzdHJlYW0ucmVhZEJ5dGUoKSkgPj0gMCkgewogICAgICBjb25zdCB0eXBlID0gYiA+PiA1OwogICAgICBpZiAodHlwZSA9PT0gNykgewogICAgICAgIHN3aXRjaCAoYiAmIDB4MWYpIHsKICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgc3RyZWFtLnJlYWRTdHJpbmcoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHVzZUNNYXAgPSBzdHJlYW0ucmVhZFN0cmluZygpOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3Qgc2VxdWVuY2UgPSAhIShiICYgMHgxMCk7CiAgICAgIGNvbnN0IGRhdGFTaXplID0gYiAmIDE1OwogICAgICBpZiAoZGF0YVNpemUgKyAxID4gTUFYX05VTV9TSVpFKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJCaW5hcnlDTWFwUmVhZGVyLnByb2Nlc3M6IEludmFsaWQgZGF0YVNpemUuIik7CiAgICAgIH0KICAgICAgY29uc3QgdWNzMkRhdGFTaXplID0gMTsKICAgICAgY29uc3Qgc3ViaXRlbXNDb3VudCA9IHN0cmVhbS5yZWFkTnVtYmVyKCk7CiAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgIGNhc2UgMDoKICAgICAgICAgIHN0cmVhbS5yZWFkSGV4KHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihlbmQsIGRhdGFTaXplKTsKICAgICAgICAgIGFkZEhleChlbmQsIHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICBjTWFwLmFkZENvZGVzcGFjZVJhbmdlKGRhdGFTaXplICsgMSwgaGV4VG9JbnQoc3RhcnQsIGRhdGFTaXplKSwgaGV4VG9JbnQoZW5kLCBkYXRhU2l6ZSkpOwogICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzdWJpdGVtc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgaW5jSGV4KGVuZCwgZGF0YVNpemUpOwogICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgICBhZGRIZXgoc3RhcnQsIGVuZCwgZGF0YVNpemUpOwogICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihlbmQsIGRhdGFTaXplKTsKICAgICAgICAgICAgYWRkSGV4KGVuZCwgc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgICAgY01hcC5hZGRDb2Rlc3BhY2VSYW5nZShkYXRhU2l6ZSArIDEsIGhleFRvSW50KHN0YXJ0LCBkYXRhU2l6ZSksIGhleFRvSW50KGVuZCwgZGF0YVNpemUpKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMToKICAgICAgICAgIHN0cmVhbS5yZWFkSGV4KHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihlbmQsIGRhdGFTaXplKTsKICAgICAgICAgIGFkZEhleChlbmQsIHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICBzdHJlYW0ucmVhZE51bWJlcigpOwogICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzdWJpdGVtc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgaW5jSGV4KGVuZCwgZGF0YVNpemUpOwogICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgICBhZGRIZXgoc3RhcnQsIGVuZCwgZGF0YVNpemUpOwogICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihlbmQsIGRhdGFTaXplKTsKICAgICAgICAgICAgYWRkSGV4KGVuZCwgc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgICAgc3RyZWFtLnJlYWROdW1iZXIoKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjoKICAgICAgICAgIHN0cmVhbS5yZWFkSGV4KGNoYXIsIGRhdGFTaXplKTsKICAgICAgICAgIGNvZGUgPSBzdHJlYW0ucmVhZE51bWJlcigpOwogICAgICAgICAgY01hcC5tYXBPbmUoaGV4VG9JbnQoY2hhciwgZGF0YVNpemUpLCBjb2RlKTsKICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgc3ViaXRlbXNDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGluY0hleChjaGFyLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIGlmICghc2VxdWVuY2UpIHsKICAgICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcih0bXAsIGRhdGFTaXplKTsKICAgICAgICAgICAgICBhZGRIZXgoY2hhciwgdG1wLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29kZSA9IHN0cmVhbS5yZWFkU2lnbmVkKCkgKyAoY29kZSArIDEpOwogICAgICAgICAgICBjTWFwLm1hcE9uZShoZXhUb0ludChjaGFyLCBkYXRhU2l6ZSksIGNvZGUpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAzOgogICAgICAgICAgc3RyZWFtLnJlYWRIZXgoc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgIHN0cmVhbS5yZWFkSGV4TnVtYmVyKGVuZCwgZGF0YVNpemUpOwogICAgICAgICAgYWRkSGV4KGVuZCwgc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgIGNvZGUgPSBzdHJlYW0ucmVhZE51bWJlcigpOwogICAgICAgICAgY01hcC5tYXBDaWRSYW5nZShoZXhUb0ludChzdGFydCwgZGF0YVNpemUpLCBoZXhUb0ludChlbmQsIGRhdGFTaXplKSwgY29kZSk7CiAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHN1Yml0ZW1zQ291bnQ7IGkrKykgewogICAgICAgICAgICBpbmNIZXgoZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIGlmICghc2VxdWVuY2UpIHsKICAgICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgICAgIGFkZEhleChzdGFydCwgZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgc3RhcnQuc2V0KGVuZCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIGFkZEhleChlbmQsIHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIGNvZGUgPSBzdHJlYW0ucmVhZE51bWJlcigpOwogICAgICAgICAgICBjTWFwLm1hcENpZFJhbmdlKGhleFRvSW50KHN0YXJ0LCBkYXRhU2l6ZSksIGhleFRvSW50KGVuZCwgZGF0YVNpemUpLCBjb2RlKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNDoKICAgICAgICAgIHN0cmVhbS5yZWFkSGV4KGNoYXIsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICBzdHJlYW0ucmVhZEhleChjaGFyQ29kZSwgZGF0YVNpemUpOwogICAgICAgICAgY01hcC5tYXBPbmUoaGV4VG9JbnQoY2hhciwgdWNzMkRhdGFTaXplKSwgaGV4VG9TdHIoY2hhckNvZGUsIGRhdGFTaXplKSk7CiAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHN1Yml0ZW1zQ291bnQ7IGkrKykgewogICAgICAgICAgICBpbmNIZXgoY2hhciwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgaWYgKCFzZXF1ZW5jZSkgewogICAgICAgICAgICAgIHN0cmVhbS5yZWFkSGV4TnVtYmVyKHRtcCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgICBhZGRIZXgoY2hhciwgdG1wLCB1Y3MyRGF0YVNpemUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGluY0hleChjaGFyQ29kZSwgZGF0YVNpemUpOwogICAgICAgICAgICBzdHJlYW0ucmVhZEhleFNpZ25lZCh0bXAsIGRhdGFTaXplKTsKICAgICAgICAgICAgYWRkSGV4KGNoYXJDb2RlLCB0bXAsIGRhdGFTaXplKTsKICAgICAgICAgICAgY01hcC5tYXBPbmUoaGV4VG9JbnQoY2hhciwgdWNzMkRhdGFTaXplKSwgaGV4VG9TdHIoY2hhckNvZGUsIGRhdGFTaXplKSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDU6CiAgICAgICAgICBzdHJlYW0ucmVhZEhleChzdGFydCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgIHN0cmVhbS5yZWFkSGV4TnVtYmVyKGVuZCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgIGFkZEhleChlbmQsIHN0YXJ0LCB1Y3MyRGF0YVNpemUpOwogICAgICAgICAgc3RyZWFtLnJlYWRIZXgoY2hhckNvZGUsIGRhdGFTaXplKTsKICAgICAgICAgIGNNYXAubWFwQmZSYW5nZShoZXhUb0ludChzdGFydCwgdWNzMkRhdGFTaXplKSwgaGV4VG9JbnQoZW5kLCB1Y3MyRGF0YVNpemUpLCBoZXhUb1N0cihjaGFyQ29kZSwgZGF0YVNpemUpKTsKICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgc3ViaXRlbXNDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGluY0hleChlbmQsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICAgIGlmICghc2VxdWVuY2UpIHsKICAgICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihzdGFydCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgICBhZGRIZXgoc3RhcnQsIGVuZCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBzdGFydC5zZXQoZW5kKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihlbmQsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICAgIGFkZEhleChlbmQsIHN0YXJ0LCB1Y3MyRGF0YVNpemUpOwogICAgICAgICAgICBzdHJlYW0ucmVhZEhleChjaGFyQ29kZSwgZGF0YVNpemUpOwogICAgICAgICAgICBjTWFwLm1hcEJmUmFuZ2UoaGV4VG9JbnQoc3RhcnQsIHVjczJEYXRhU2l6ZSksIGhleFRvSW50KGVuZCwgdWNzMkRhdGFTaXplKSwgaGV4VG9TdHIoY2hhckNvZGUsIGRhdGFTaXplKSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBCaW5hcnlDTWFwUmVhZGVyLnByb2Nlc3MgLSB1bmtub3duIHR5cGU6ICR7dHlwZX1gKTsKICAgICAgfQogICAgfQogICAgaWYgKHVzZUNNYXApIHsKICAgICAgcmV0dXJuIGV4dGVuZCh1c2VDTWFwKTsKICAgIH0KICAgIHJldHVybiBjTWFwOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvYXNjaWlfODVfc3RyZWFtLmpzCgoKY2xhc3MgQXNjaWk4NVN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyLCBtYXliZUxlbmd0aCkgewogICAgaWYgKG1heWJlTGVuZ3RoKSB7CiAgICAgIG1heWJlTGVuZ3RoICo9IDAuODsKICAgIH0KICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyZWFtID0gc3RyOwogICAgdGhpcy5kaWN0ID0gc3RyLmRpY3Q7CiAgICB0aGlzLmlucHV0ID0gbmV3IFVpbnQ4QXJyYXkoNSk7CiAgfQogIHJlYWRCbG9jaygpIHsKICAgIGNvbnN0IFRJTERBX0NIQVIgPSAweDdlOwogICAgY29uc3QgWl9MT1dFUl9DSEFSID0gMHg3YTsKICAgIGNvbnN0IEVPRiA9IC0xOwogICAgY29uc3Qgc3RyID0gdGhpcy5zdHJlYW07CiAgICBsZXQgYyA9IHN0ci5nZXRCeXRlKCk7CiAgICB3aGlsZSAoaXNXaGl0ZVNwYWNlKGMpKSB7CiAgICAgIGMgPSBzdHIuZ2V0Qnl0ZSgpOwogICAgfQogICAgaWYgKGMgPT09IEVPRiB8fCBjID09PSBUSUxEQV9DSEFSKSB7CiAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJMZW5ndGg7CiAgICBsZXQgYnVmZmVyLCBpOwogICAgaWYgKGMgPT09IFpfTE9XRVJfQ0hBUikgewogICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihidWZmZXJMZW5ndGggKyA0KTsKICAgICAgZm9yIChpID0gMDsgaSA8IDQ7ICsraSkgewogICAgICAgIGJ1ZmZlcltidWZmZXJMZW5ndGggKyBpXSA9IDA7CiAgICAgIH0KICAgICAgdGhpcy5idWZmZXJMZW5ndGggKz0gNDsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGlucHV0ID0gdGhpcy5pbnB1dDsKICAgICAgaW5wdXRbMF0gPSBjOwogICAgICBmb3IgKGkgPSAxOyBpIDwgNTsgKytpKSB7CiAgICAgICAgYyA9IHN0ci5nZXRCeXRlKCk7CiAgICAgICAgd2hpbGUgKGlzV2hpdGVTcGFjZShjKSkgewogICAgICAgICAgYyA9IHN0ci5nZXRCeXRlKCk7CiAgICAgICAgfQogICAgICAgIGlucHV0W2ldID0gYzsKICAgICAgICBpZiAoYyA9PT0gRU9GIHx8IGMgPT09IFRJTERBX0NIQVIpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihidWZmZXJMZW5ndGggKyBpIC0gMSk7CiAgICAgIHRoaXMuYnVmZmVyTGVuZ3RoICs9IGkgLSAxOwogICAgICBpZiAoaSA8IDUpIHsKICAgICAgICBmb3IgKDsgaSA8IDU7ICsraSkgewogICAgICAgICAgaW5wdXRbaV0gPSAweDIxICsgODQ7CiAgICAgICAgfQogICAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgfQogICAgICBsZXQgdCA9IDA7CiAgICAgIGZvciAoaSA9IDA7IGkgPCA1OyArK2kpIHsKICAgICAgICB0ID0gdCAqIDg1ICsgKGlucHV0W2ldIC0gMHgyMSk7CiAgICAgIH0KICAgICAgZm9yIChpID0gMzsgaSA+PSAwOyAtLWkpIHsKICAgICAgICBidWZmZXJbYnVmZmVyTGVuZ3RoICsgaV0gPSB0ICYgMHhmZjsKICAgICAgICB0ID4+PSA4OwogICAgICB9CiAgICB9CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9hc2NpaV9oZXhfc3RyZWFtLmpzCgpjbGFzcyBBc2NpaUhleFN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyLCBtYXliZUxlbmd0aCkgewogICAgaWYgKG1heWJlTGVuZ3RoKSB7CiAgICAgIG1heWJlTGVuZ3RoICo9IDAuNTsKICAgIH0KICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyZWFtID0gc3RyOwogICAgdGhpcy5kaWN0ID0gc3RyLmRpY3Q7CiAgICB0aGlzLmZpcnN0RGlnaXQgPSAtMTsKICB9CiAgcmVhZEJsb2NrKCkgewogICAgY29uc3QgVVBTVFJFQU1fQkxPQ0tfU0laRSA9IDgwMDA7CiAgICBjb25zdCBieXRlcyA9IHRoaXMuc3RyZWFtLmdldEJ5dGVzKFVQU1RSRUFNX0JMT0NLX1NJWkUpOwogICAgaWYgKCFieXRlcy5sZW5ndGgpIHsKICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBtYXhEZWNvZGVMZW5ndGggPSBieXRlcy5sZW5ndGggKyAxID4+IDE7CiAgICBjb25zdCBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcih0aGlzLmJ1ZmZlckxlbmd0aCArIG1heERlY29kZUxlbmd0aCk7CiAgICBsZXQgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJMZW5ndGg7CiAgICBsZXQgZmlyc3REaWdpdCA9IHRoaXMuZmlyc3REaWdpdDsKICAgIGZvciAoY29uc3QgY2ggb2YgYnl0ZXMpIHsKICAgICAgbGV0IGRpZ2l0OwogICAgICBpZiAoY2ggPj0gMHgzMCAmJiBjaCA8PSAweDM5KSB7CiAgICAgICAgZGlnaXQgPSBjaCAmIDB4MGY7CiAgICAgIH0gZWxzZSBpZiAoY2ggPj0gMHg0MSAmJiBjaCA8PSAweDQ2IHx8IGNoID49IDB4NjEgJiYgY2ggPD0gMHg2NikgewogICAgICAgIGRpZ2l0ID0gKGNoICYgMHgwZikgKyA5OwogICAgICB9IGVsc2UgaWYgKGNoID09PSAweDNlKSB7CiAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICAgIGJyZWFrOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChmaXJzdERpZ2l0IDwgMCkgewogICAgICAgIGZpcnN0RGlnaXQgPSBkaWdpdDsKICAgICAgfSBlbHNlIHsKICAgICAgICBidWZmZXJbYnVmZmVyTGVuZ3RoKytdID0gZmlyc3REaWdpdCA8PCA0IHwgZGlnaXQ7CiAgICAgICAgZmlyc3REaWdpdCA9IC0xOwogICAgICB9CiAgICB9CiAgICBpZiAoZmlyc3REaWdpdCA+PSAwICYmIHRoaXMuZW9mKSB7CiAgICAgIGJ1ZmZlcltidWZmZXJMZW5ndGgrK10gPSBmaXJzdERpZ2l0IDw8IDQ7CiAgICAgIGZpcnN0RGlnaXQgPSAtMTsKICAgIH0KICAgIHRoaXMuZmlyc3REaWdpdCA9IGZpcnN0RGlnaXQ7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGJ1ZmZlckxlbmd0aDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2NjaXR0LmpzCgpjb25zdCBjY2l0dEVPTCA9IC0yOwpjb25zdCBjY2l0dEVPRiA9IC0xOwpjb25zdCB0d29EaW1QYXNzID0gMDsKY29uc3QgdHdvRGltSG9yaXogPSAxOwpjb25zdCB0d29EaW1WZXJ0MCA9IDI7CmNvbnN0IHR3b0RpbVZlcnRSMSA9IDM7CmNvbnN0IHR3b0RpbVZlcnRMMSA9IDQ7CmNvbnN0IHR3b0RpbVZlcnRSMiA9IDU7CmNvbnN0IHR3b0RpbVZlcnRMMiA9IDY7CmNvbnN0IHR3b0RpbVZlcnRSMyA9IDc7CmNvbnN0IHR3b0RpbVZlcnRMMyA9IDg7CmNvbnN0IHR3b0RpbVRhYmxlID0gW1stMSwgLTFdLCBbLTEsIC0xXSwgWzcsIHR3b0RpbVZlcnRMM10sIFs3LCB0d29EaW1WZXJ0UjNdLCBbNiwgdHdvRGltVmVydEwyXSwgWzYsIHR3b0RpbVZlcnRMMl0sIFs2LCB0d29EaW1WZXJ0UjJdLCBbNiwgdHdvRGltVmVydFIyXSwgWzQsIHR3b0RpbVBhc3NdLCBbNCwgdHdvRGltUGFzc10sIFs0LCB0d29EaW1QYXNzXSwgWzQsIHR3b0RpbVBhc3NdLCBbNCwgdHdvRGltUGFzc10sIFs0LCB0d29EaW1QYXNzXSwgWzQsIHR3b0RpbVBhc3NdLCBbNCwgdHdvRGltUGFzc10sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1Ib3Jpel0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXSwgWzEsIHR3b0RpbVZlcnQwXV07CmNvbnN0IHdoaXRlVGFibGUxID0gW1stMSwgLTFdLCBbMTIsIGNjaXR0RU9MXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbMTEsIDE3OTJdLCBbMTEsIDE3OTJdLCBbMTIsIDE5ODRdLCBbMTIsIDIwNDhdLCBbMTIsIDIxMTJdLCBbMTIsIDIxNzZdLCBbMTIsIDIyNDBdLCBbMTIsIDIzMDRdLCBbMTEsIDE4NTZdLCBbMTEsIDE4NTZdLCBbMTEsIDE5MjBdLCBbMTEsIDE5MjBdLCBbMTIsIDIzNjhdLCBbMTIsIDI0MzJdLCBbMTIsIDI0OTZdLCBbMTIsIDI1NjBdXTsKY29uc3Qgd2hpdGVUYWJsZTIgPSBbWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFs4LCAyOV0sIFs4LCAyOV0sIFs4LCAzMF0sIFs4LCAzMF0sIFs4LCA0NV0sIFs4LCA0NV0sIFs4LCA0Nl0sIFs4LCA0Nl0sIFs3LCAyMl0sIFs3LCAyMl0sIFs3LCAyMl0sIFs3LCAyMl0sIFs3LCAyM10sIFs3LCAyM10sIFs3LCAyM10sIFs3LCAyM10sIFs4LCA0N10sIFs4LCA0N10sIFs4LCA0OF0sIFs4LCA0OF0sIFs2LCAxM10sIFs2LCAxM10sIFs2LCAxM10sIFs2LCAxM10sIFs2LCAxM10sIFs2LCAxM10sIFs2LCAxM10sIFs2LCAxM10sIFs3LCAyMF0sIFs3LCAyMF0sIFs3LCAyMF0sIFs3LCAyMF0sIFs4LCAzM10sIFs4LCAzM10sIFs4LCAzNF0sIFs4LCAzNF0sIFs4LCAzNV0sIFs4LCAzNV0sIFs4LCAzNl0sIFs4LCAzNl0sIFs4LCAzN10sIFs4LCAzN10sIFs4LCAzOF0sIFs4LCAzOF0sIFs3LCAxOV0sIFs3LCAxOV0sIFs3LCAxOV0sIFs3LCAxOV0sIFs4LCAzMV0sIFs4LCAzMV0sIFs4LCAzMl0sIFs4LCAzMl0sIFs2LCAxXSwgWzYsIDFdLCBbNiwgMV0sIFs2LCAxXSwgWzYsIDFdLCBbNiwgMV0sIFs2LCAxXSwgWzYsIDFdLCBbNiwgMTJdLCBbNiwgMTJdLCBbNiwgMTJdLCBbNiwgMTJdLCBbNiwgMTJdLCBbNiwgMTJdLCBbNiwgMTJdLCBbNiwgMTJdLCBbOCwgNTNdLCBbOCwgNTNdLCBbOCwgNTRdLCBbOCwgNTRdLCBbNywgMjZdLCBbNywgMjZdLCBbNywgMjZdLCBbNywgMjZdLCBbOCwgMzldLCBbOCwgMzldLCBbOCwgNDBdLCBbOCwgNDBdLCBbOCwgNDFdLCBbOCwgNDFdLCBbOCwgNDJdLCBbOCwgNDJdLCBbOCwgNDNdLCBbOCwgNDNdLCBbOCwgNDRdLCBbOCwgNDRdLCBbNywgMjFdLCBbNywgMjFdLCBbNywgMjFdLCBbNywgMjFdLCBbNywgMjhdLCBbNywgMjhdLCBbNywgMjhdLCBbNywgMjhdLCBbOCwgNjFdLCBbOCwgNjFdLCBbOCwgNjJdLCBbOCwgNjJdLCBbOCwgNjNdLCBbOCwgNjNdLCBbOCwgMF0sIFs4LCAwXSwgWzgsIDMyMF0sIFs4LCAzMjBdLCBbOCwgMzg0XSwgWzgsIDM4NF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMF0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs1LCAxMV0sIFs3LCAyN10sIFs3LCAyN10sIFs3LCAyN10sIFs3LCAyN10sIFs4LCA1OV0sIFs4LCA1OV0sIFs4LCA2MF0sIFs4LCA2MF0sIFs5LCAxNDcyXSwgWzksIDE1MzZdLCBbOSwgMTYwMF0sIFs5LCAxNzI4XSwgWzcsIDE4XSwgWzcsIDE4XSwgWzcsIDE4XSwgWzcsIDE4XSwgWzcsIDI0XSwgWzcsIDI0XSwgWzcsIDI0XSwgWzcsIDI0XSwgWzgsIDQ5XSwgWzgsIDQ5XSwgWzgsIDUwXSwgWzgsIDUwXSwgWzgsIDUxXSwgWzgsIDUxXSwgWzgsIDUyXSwgWzgsIDUyXSwgWzcsIDI1XSwgWzcsIDI1XSwgWzcsIDI1XSwgWzcsIDI1XSwgWzgsIDU1XSwgWzgsIDU1XSwgWzgsIDU2XSwgWzgsIDU2XSwgWzgsIDU3XSwgWzgsIDU3XSwgWzgsIDU4XSwgWzgsIDU4XSwgWzYsIDE5Ml0sIFs2LCAxOTJdLCBbNiwgMTkyXSwgWzYsIDE5Ml0sIFs2LCAxOTJdLCBbNiwgMTkyXSwgWzYsIDE5Ml0sIFs2LCAxOTJdLCBbNiwgMTY2NF0sIFs2LCAxNjY0XSwgWzYsIDE2NjRdLCBbNiwgMTY2NF0sIFs2LCAxNjY0XSwgWzYsIDE2NjRdLCBbNiwgMTY2NF0sIFs2LCAxNjY0XSwgWzgsIDQ0OF0sIFs4LCA0NDhdLCBbOCwgNTEyXSwgWzgsIDUxMl0sIFs5LCA3MDRdLCBbOSwgNzY4XSwgWzgsIDY0MF0sIFs4LCA2NDBdLCBbOCwgNTc2XSwgWzgsIDU3Nl0sIFs5LCA4MzJdLCBbOSwgODk2XSwgWzksIDk2MF0sIFs5LCAxMDI0XSwgWzksIDEwODhdLCBbOSwgMTE1Ml0sIFs5LCAxMjE2XSwgWzksIDEyODBdLCBbOSwgMTM0NF0sIFs5LCAxNDA4XSwgWzcsIDI1Nl0sIFs3LCAyNTZdLCBbNywgMjU2XSwgWzcsIDI1Nl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNiwgMTZdLCBbNiwgMTZdLCBbNiwgMTZdLCBbNiwgMTZdLCBbNiwgMTZdLCBbNiwgMTZdLCBbNiwgMTZdLCBbNiwgMTZdLCBbNiwgMTddLCBbNiwgMTddLCBbNiwgMTddLCBbNiwgMTddLCBbNiwgMTddLCBbNiwgMTddLCBbNiwgMTddLCBbNiwgMTddLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs2LCAxNF0sIFs2LCAxNF0sIFs2LCAxNF0sIFs2LCAxNF0sIFs2LCAxNF0sIFs2LCAxNF0sIFs2LCAxNF0sIFs2LCAxNF0sIFs2LCAxNV0sIFs2LCAxNV0sIFs2LCAxNV0sIFs2LCAxNV0sIFs2LCAxNV0sIFs2LCAxNV0sIFs2LCAxNV0sIFs2LCAxNV0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs1LCA2NF0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XV07CmNvbnN0IGJsYWNrVGFibGUxID0gW1stMSwgLTFdLCBbLTEsIC0xXSwgWzEyLCBjY2l0dEVPTF0sIFsxMiwgY2NpdHRFT0xdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWzExLCAxNzkyXSwgWzExLCAxNzkyXSwgWzExLCAxNzkyXSwgWzExLCAxNzkyXSwgWzEyLCAxOTg0XSwgWzEyLCAxOTg0XSwgWzEyLCAyMDQ4XSwgWzEyLCAyMDQ4XSwgWzEyLCAyMTEyXSwgWzEyLCAyMTEyXSwgWzEyLCAyMTc2XSwgWzEyLCAyMTc2XSwgWzEyLCAyMjQwXSwgWzEyLCAyMjQwXSwgWzEyLCAyMzA0XSwgWzEyLCAyMzA0XSwgWzExLCAxODU2XSwgWzExLCAxODU2XSwgWzExLCAxODU2XSwgWzExLCAxODU2XSwgWzExLCAxOTIwXSwgWzExLCAxOTIwXSwgWzExLCAxOTIwXSwgWzExLCAxOTIwXSwgWzEyLCAyMzY4XSwgWzEyLCAyMzY4XSwgWzEyLCAyNDMyXSwgWzEyLCAyNDMyXSwgWzEyLCAyNDk2XSwgWzEyLCAyNDk2XSwgWzEyLCAyNTYwXSwgWzEyLCAyNTYwXSwgWzEwLCAxOF0sIFsxMCwgMThdLCBbMTAsIDE4XSwgWzEwLCAxOF0sIFsxMCwgMThdLCBbMTAsIDE4XSwgWzEwLCAxOF0sIFsxMCwgMThdLCBbMTIsIDUyXSwgWzEyLCA1Ml0sIFsxMywgNjQwXSwgWzEzLCA3MDRdLCBbMTMsIDc2OF0sIFsxMywgODMyXSwgWzEyLCA1NV0sIFsxMiwgNTVdLCBbMTIsIDU2XSwgWzEyLCA1Nl0sIFsxMywgMTI4MF0sIFsxMywgMTM0NF0sIFsxMywgMTQwOF0sIFsxMywgMTQ3Ml0sIFsxMiwgNTldLCBbMTIsIDU5XSwgWzEyLCA2MF0sIFsxMiwgNjBdLCBbMTMsIDE1MzZdLCBbMTMsIDE2MDBdLCBbMTEsIDI0XSwgWzExLCAyNF0sIFsxMSwgMjRdLCBbMTEsIDI0XSwgWzExLCAyNV0sIFsxMSwgMjVdLCBbMTEsIDI1XSwgWzExLCAyNV0sIFsxMywgMTY2NF0sIFsxMywgMTcyOF0sIFsxMiwgMzIwXSwgWzEyLCAzMjBdLCBbMTIsIDM4NF0sIFsxMiwgMzg0XSwgWzEyLCA0NDhdLCBbMTIsIDQ0OF0sIFsxMywgNTEyXSwgWzEzLCA1NzZdLCBbMTIsIDUzXSwgWzEyLCA1M10sIFsxMiwgNTRdLCBbMTIsIDU0XSwgWzEzLCA4OTZdLCBbMTMsIDk2MF0sIFsxMywgMTAyNF0sIFsxMywgMTA4OF0sIFsxMywgMTE1Ml0sIFsxMywgMTIxNl0sIFsxMCwgNjRdLCBbMTAsIDY0XSwgWzEwLCA2NF0sIFsxMCwgNjRdLCBbMTAsIDY0XSwgWzEwLCA2NF0sIFsxMCwgNjRdLCBbMTAsIDY0XV07CmNvbnN0IGJsYWNrVGFibGUyID0gW1s4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFs4LCAxM10sIFsxMSwgMjNdLCBbMTEsIDIzXSwgWzEyLCA1MF0sIFsxMiwgNTFdLCBbMTIsIDQ0XSwgWzEyLCA0NV0sIFsxMiwgNDZdLCBbMTIsIDQ3XSwgWzEyLCA1N10sIFsxMiwgNThdLCBbMTIsIDYxXSwgWzEyLCAyNTZdLCBbMTAsIDE2XSwgWzEwLCAxNl0sIFsxMCwgMTZdLCBbMTAsIDE2XSwgWzEwLCAxN10sIFsxMCwgMTddLCBbMTAsIDE3XSwgWzEwLCAxN10sIFsxMiwgNDhdLCBbMTIsIDQ5XSwgWzEyLCA2Ml0sIFsxMiwgNjNdLCBbMTIsIDMwXSwgWzEyLCAzMV0sIFsxMiwgMzJdLCBbMTIsIDMzXSwgWzEyLCA0MF0sIFsxMiwgNDFdLCBbMTEsIDIyXSwgWzExLCAyMl0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs4LCAxNF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMF0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs3LCAxMV0sIFs5LCAxNV0sIFs5LCAxNV0sIFs5LCAxNV0sIFs5LCAxNV0sIFs5LCAxNV0sIFs5LCAxNV0sIFs5LCAxNV0sIFs5LCAxNV0sIFsxMiwgMTI4XSwgWzEyLCAxOTJdLCBbMTIsIDI2XSwgWzEyLCAyN10sIFsxMiwgMjhdLCBbMTIsIDI5XSwgWzExLCAxOV0sIFsxMSwgMTldLCBbMTEsIDIwXSwgWzExLCAyMF0sIFsxMiwgMzRdLCBbMTIsIDM1XSwgWzEyLCAzNl0sIFsxMiwgMzddLCBbMTIsIDM4XSwgWzEyLCAzOV0sIFsxMSwgMjFdLCBbMTEsIDIxXSwgWzEyLCA0Ml0sIFsxMiwgNDNdLCBbMTAsIDBdLCBbMTAsIDBdLCBbMTAsIDBdLCBbMTAsIDBdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdLCBbNywgMTJdXTsKY29uc3QgYmxhY2tUYWJsZTMgPSBbWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFs2LCA5XSwgWzYsIDhdLCBbNSwgN10sIFs1LCA3XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFszLCAxXSwgWzMsIDFdLCBbMywgMV0sIFszLCAxXSwgWzMsIDFdLCBbMywgMV0sIFszLCAxXSwgWzMsIDFdLCBbMywgNF0sIFszLCA0XSwgWzMsIDRdLCBbMywgNF0sIFszLCA0XSwgWzMsIDRdLCBbMywgNF0sIFszLCA0XSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl1dOwpjbGFzcyBDQ0lUVEZheERlY29kZXIgewogIGNvbnN0cnVjdG9yKHNvdXJjZSwgb3B0aW9ucyA9IHt9KSB7CiAgICBpZiAodHlwZW9mIHNvdXJjZT8ubmV4dCAhPT0gImZ1bmN0aW9uIikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NDSVRURmF4RGVjb2RlciAtIGludmFsaWQgInNvdXJjZSIgcGFyYW1ldGVyLicpOwogICAgfQogICAgdGhpcy5zb3VyY2UgPSBzb3VyY2U7CiAgICB0aGlzLmVvZiA9IGZhbHNlOwogICAgdGhpcy5lbmNvZGluZyA9IG9wdGlvbnMuSyB8fCAwOwogICAgdGhpcy5lb2xpbmUgPSBvcHRpb25zLkVuZE9mTGluZSB8fCBmYWxzZTsKICAgIHRoaXMuYnl0ZUFsaWduID0gb3B0aW9ucy5FbmNvZGVkQnl0ZUFsaWduIHx8IGZhbHNlOwogICAgdGhpcy5jb2x1bW5zID0gb3B0aW9ucy5Db2x1bW5zIHx8IDE3Mjg7CiAgICB0aGlzLnJvd3MgPSBvcHRpb25zLlJvd3MgfHwgMDsKICAgIHRoaXMuZW9ibG9jayA9IG9wdGlvbnMuRW5kT2ZCbG9jayA/PyB0cnVlOwogICAgdGhpcy5ibGFjayA9IG9wdGlvbnMuQmxhY2tJczEgfHwgZmFsc2U7CiAgICB0aGlzLmNvZGluZ0xpbmUgPSBuZXcgVWludDMyQXJyYXkodGhpcy5jb2x1bW5zICsgMSk7CiAgICB0aGlzLnJlZkxpbmUgPSBuZXcgVWludDMyQXJyYXkodGhpcy5jb2x1bW5zICsgMik7CiAgICB0aGlzLmNvZGluZ0xpbmVbMF0gPSB0aGlzLmNvbHVtbnM7CiAgICB0aGlzLmNvZGluZ1BvcyA9IDA7CiAgICB0aGlzLnJvdyA9IDA7CiAgICB0aGlzLm5leHRMaW5lMkQgPSB0aGlzLmVuY29kaW5nIDwgMDsKICAgIHRoaXMuaW5wdXRCaXRzID0gMDsKICAgIHRoaXMuaW5wdXRCdWYgPSAwOwogICAgdGhpcy5vdXRwdXRCaXRzID0gMDsKICAgIHRoaXMucm93c0RvbmUgPSBmYWxzZTsKICAgIGxldCBjb2RlMTsKICAgIHdoaWxlICgoY29kZTEgPSB0aGlzLl9sb29rQml0cygxMikpID09PSAwKSB7CiAgICAgIHRoaXMuX2VhdEJpdHMoMSk7CiAgICB9CiAgICBpZiAoY29kZTEgPT09IDEpIHsKICAgICAgdGhpcy5fZWF0Qml0cygxMik7CiAgICB9CiAgICBpZiAodGhpcy5lbmNvZGluZyA+IDApIHsKICAgICAgdGhpcy5uZXh0TGluZTJEID0gIXRoaXMuX2xvb2tCaXRzKDEpOwogICAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgfQogIH0KICByZWFkTmV4dENoYXIoKSB7CiAgICBpZiAodGhpcy5lb2YpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgY29uc3QgcmVmTGluZSA9IHRoaXMucmVmTGluZTsKICAgIGNvbnN0IGNvZGluZ0xpbmUgPSB0aGlzLmNvZGluZ0xpbmU7CiAgICBjb25zdCBjb2x1bW5zID0gdGhpcy5jb2x1bW5zOwogICAgbGV0IHJlZlBvcywgYmxhY2tQaXhlbHMsIGJpdHMsIGk7CiAgICBpZiAodGhpcy5vdXRwdXRCaXRzID09PSAwKSB7CiAgICAgIGlmICh0aGlzLnJvd3NEb25lKSB7CiAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICB9CiAgICAgIGlmICh0aGlzLmVvZikgewogICAgICAgIHJldHVybiAtMTsKICAgICAgfQogICAgICB0aGlzLmVyciA9IGZhbHNlOwogICAgICBsZXQgY29kZTEsIGNvZGUyLCBjb2RlMzsKICAgICAgaWYgKHRoaXMubmV4dExpbmUyRCkgewogICAgICAgIGZvciAoaSA9IDA7IGNvZGluZ0xpbmVbaV0gPCBjb2x1bW5zOyArK2kpIHsKICAgICAgICAgIHJlZkxpbmVbaV0gPSBjb2RpbmdMaW5lW2ldOwogICAgICAgIH0KICAgICAgICByZWZMaW5lW2krK10gPSBjb2x1bW5zOwogICAgICAgIHJlZkxpbmVbaV0gPSBjb2x1bW5zOwogICAgICAgIGNvZGluZ0xpbmVbMF0gPSAwOwogICAgICAgIHRoaXMuY29kaW5nUG9zID0gMDsKICAgICAgICByZWZQb3MgPSAwOwogICAgICAgIGJsYWNrUGl4ZWxzID0gMDsKICAgICAgICB3aGlsZSAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICBjb2RlMSA9IHRoaXMuX2dldFR3b0RpbUNvZGUoKTsKICAgICAgICAgIHN3aXRjaCAoY29kZTEpIHsKICAgICAgICAgICAgY2FzZSB0d29EaW1QYXNzOgogICAgICAgICAgICAgIHRoaXMuX2FkZFBpeGVscyhyZWZMaW5lW3JlZlBvcyArIDFdLCBibGFja1BpeGVscyk7CiAgICAgICAgICAgICAgaWYgKHJlZkxpbmVbcmVmUG9zICsgMV0gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICByZWZQb3MgKz0gMjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgdHdvRGltSG9yaXo6CiAgICAgICAgICAgICAgY29kZTEgPSBjb2RlMiA9IDA7CiAgICAgICAgICAgICAgaWYgKGJsYWNrUGl4ZWxzKSB7CiAgICAgICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgICAgIGNvZGUxICs9IGNvZGUzID0gdGhpcy5fZ2V0QmxhY2tDb2RlKCk7CiAgICAgICAgICAgICAgICB9IHdoaWxlIChjb2RlMyA+PSA2NCk7CiAgICAgICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgICAgIGNvZGUyICs9IGNvZGUzID0gdGhpcy5fZ2V0V2hpdGVDb2RlKCk7CiAgICAgICAgICAgICAgICB9IHdoaWxlIChjb2RlMyA+PSA2NCk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAgICAgY29kZTEgKz0gY29kZTMgPSB0aGlzLl9nZXRXaGl0ZUNvZGUoKTsKICAgICAgICAgICAgICAgIH0gd2hpbGUgKGNvZGUzID49IDY0KTsKICAgICAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAgICAgY29kZTIgKz0gY29kZTMgPSB0aGlzLl9nZXRCbGFja0NvZGUoKTsKICAgICAgICAgICAgICAgIH0gd2hpbGUgKGNvZGUzID49IDY0KTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzKGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdICsgY29kZTEsIGJsYWNrUGl4ZWxzKTsKICAgICAgICAgICAgICBpZiAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHMoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gKyBjb2RlMiwgYmxhY2tQaXhlbHMgXiAxKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgd2hpbGUgKHJlZkxpbmVbcmVmUG9zXSA8PSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSAmJiByZWZMaW5lW3JlZlBvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICByZWZQb3MgKz0gMjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgdHdvRGltVmVydFIzOgogICAgICAgICAgICAgIHRoaXMuX2FkZFBpeGVscyhyZWZMaW5lW3JlZlBvc10gKyAzLCBibGFja1BpeGVscyk7CiAgICAgICAgICAgICAgYmxhY2tQaXhlbHMgXj0gMTsKICAgICAgICAgICAgICBpZiAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICArK3JlZlBvczsKICAgICAgICAgICAgICAgIHdoaWxlIChyZWZMaW5lW3JlZlBvc10gPD0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gJiYgcmVmTGluZVtyZWZQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgICByZWZQb3MgKz0gMjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgdHdvRGltVmVydFIyOgogICAgICAgICAgICAgIHRoaXMuX2FkZFBpeGVscyhyZWZMaW5lW3JlZlBvc10gKyAyLCBibGFja1BpeGVscyk7CiAgICAgICAgICAgICAgYmxhY2tQaXhlbHMgXj0gMTsKICAgICAgICAgICAgICBpZiAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICArK3JlZlBvczsKICAgICAgICAgICAgICAgIHdoaWxlIChyZWZMaW5lW3JlZlBvc10gPD0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gJiYgcmVmTGluZVtyZWZQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgICByZWZQb3MgKz0gMjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgdHdvRGltVmVydFIxOgogICAgICAgICAgICAgIHRoaXMuX2FkZFBpeGVscyhyZWZMaW5lW3JlZlBvc10gKyAxLCBibGFja1BpeGVscyk7CiAgICAgICAgICAgICAgYmxhY2tQaXhlbHMgXj0gMTsKICAgICAgICAgICAgICBpZiAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICArK3JlZlBvczsKICAgICAgICAgICAgICAgIHdoaWxlIChyZWZMaW5lW3JlZlBvc10gPD0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gJiYgcmVmTGluZVtyZWZQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgICByZWZQb3MgKz0gMjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgdHdvRGltVmVydDA6CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzKHJlZkxpbmVbcmVmUG9zXSwgYmxhY2tQaXhlbHMpOwogICAgICAgICAgICAgIGJsYWNrUGl4ZWxzIF49IDE7CiAgICAgICAgICAgICAgaWYgKGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgKytyZWZQb3M7CiAgICAgICAgICAgICAgICB3aGlsZSAocmVmTGluZVtyZWZQb3NdIDw9IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdICYmIHJlZkxpbmVbcmVmUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgICAgcmVmUG9zICs9IDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIHR3b0RpbVZlcnRMMzoKICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHNOZWcocmVmTGluZVtyZWZQb3NdIC0gMywgYmxhY2tQaXhlbHMpOwogICAgICAgICAgICAgIGJsYWNrUGl4ZWxzIF49IDE7CiAgICAgICAgICAgICAgaWYgKGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgaWYgKHJlZlBvcyA+IDApIHsKICAgICAgICAgICAgICAgICAgLS1yZWZQb3M7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICArK3JlZlBvczsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHdoaWxlIChyZWZMaW5lW3JlZlBvc10gPD0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gJiYgcmVmTGluZVtyZWZQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgICByZWZQb3MgKz0gMjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgdHdvRGltVmVydEwyOgogICAgICAgICAgICAgIHRoaXMuX2FkZFBpeGVsc05lZyhyZWZMaW5lW3JlZlBvc10gLSAyLCBibGFja1BpeGVscyk7CiAgICAgICAgICAgICAgYmxhY2tQaXhlbHMgXj0gMTsKICAgICAgICAgICAgICBpZiAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICBpZiAocmVmUG9zID4gMCkgewogICAgICAgICAgICAgICAgICAtLXJlZlBvczsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICsrcmVmUG9zOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgd2hpbGUgKHJlZkxpbmVbcmVmUG9zXSA8PSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSAmJiByZWZMaW5lW3JlZlBvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICAgIHJlZlBvcyArPSAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSB0d29EaW1WZXJ0TDE6CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzTmVnKHJlZkxpbmVbcmVmUG9zXSAtIDEsIGJsYWNrUGl4ZWxzKTsKICAgICAgICAgICAgICBibGFja1BpeGVscyBePSAxOwogICAgICAgICAgICAgIGlmIChjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgIGlmIChyZWZQb3MgPiAwKSB7CiAgICAgICAgICAgICAgICAgIC0tcmVmUG9zOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgKytyZWZQb3M7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB3aGlsZSAocmVmTGluZVtyZWZQb3NdIDw9IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdICYmIHJlZkxpbmVbcmVmUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgICAgcmVmUG9zICs9IDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIGNjaXR0RU9GOgogICAgICAgICAgICAgIHRoaXMuX2FkZFBpeGVscyhjb2x1bW5zLCAwKTsKICAgICAgICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgaW5mbygiYmFkIDJkIGNvZGUiKTsKICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHMoY29sdW1ucywgMCk7CiAgICAgICAgICAgICAgdGhpcy5lcnIgPSB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBjb2RpbmdMaW5lWzBdID0gMDsKICAgICAgICB0aGlzLmNvZGluZ1BvcyA9IDA7CiAgICAgICAgYmxhY2tQaXhlbHMgPSAwOwogICAgICAgIHdoaWxlIChjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgIGNvZGUxID0gMDsKICAgICAgICAgIGlmIChibGFja1BpeGVscykgewogICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgY29kZTEgKz0gY29kZTMgPSB0aGlzLl9nZXRCbGFja0NvZGUoKTsKICAgICAgICAgICAgfSB3aGlsZSAoY29kZTMgPj0gNjQpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgIGNvZGUxICs9IGNvZGUzID0gdGhpcy5fZ2V0V2hpdGVDb2RlKCk7CiAgICAgICAgICAgIH0gd2hpbGUgKGNvZGUzID49IDY0KTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuX2FkZFBpeGVscyhjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSArIGNvZGUxLCBibGFja1BpeGVscyk7CiAgICAgICAgICBibGFja1BpeGVscyBePSAxOwogICAgICAgIH0KICAgICAgfQogICAgICBsZXQgZ290RU9MID0gZmFsc2U7CiAgICAgIGlmICh0aGlzLmJ5dGVBbGlnbikgewogICAgICAgIHRoaXMuaW5wdXRCaXRzICY9IH43OwogICAgICB9CiAgICAgIGlmICghdGhpcy5lb2Jsb2NrICYmIHRoaXMucm93ID09PSB0aGlzLnJvd3MgLSAxKSB7CiAgICAgICAgdGhpcy5yb3dzRG9uZSA9IHRydWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29kZTEgPSB0aGlzLl9sb29rQml0cygxMik7CiAgICAgICAgaWYgKHRoaXMuZW9saW5lKSB7CiAgICAgICAgICB3aGlsZSAoY29kZTEgIT09IGNjaXR0RU9GICYmIGNvZGUxICE9PSAxKSB7CiAgICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMSk7CiAgICAgICAgICAgIGNvZGUxID0gdGhpcy5fbG9va0JpdHMoMTIpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB3aGlsZSAoY29kZTEgPT09IDApIHsKICAgICAgICAgICAgdGhpcy5fZWF0Qml0cygxKTsKICAgICAgICAgICAgY29kZTEgPSB0aGlzLl9sb29rQml0cygxMik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChjb2RlMSA9PT0gMSkgewogICAgICAgICAgdGhpcy5fZWF0Qml0cygxMik7CiAgICAgICAgICBnb3RFT0wgPSB0cnVlOwogICAgICAgIH0gZWxzZSBpZiAoY29kZTEgPT09IGNjaXR0RU9GKSB7CiAgICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICghdGhpcy5lb2YgJiYgdGhpcy5lbmNvZGluZyA+IDAgJiYgIXRoaXMucm93c0RvbmUpIHsKICAgICAgICB0aGlzLm5leHRMaW5lMkQgPSAhdGhpcy5fbG9va0JpdHMoMSk7CiAgICAgICAgdGhpcy5fZWF0Qml0cygxKTsKICAgICAgfQogICAgICBpZiAodGhpcy5lb2Jsb2NrICYmIGdvdEVPTCAmJiB0aGlzLmJ5dGVBbGlnbikgewogICAgICAgIGNvZGUxID0gdGhpcy5fbG9va0JpdHMoMTIpOwogICAgICAgIGlmIChjb2RlMSA9PT0gMSkgewogICAgICAgICAgdGhpcy5fZWF0Qml0cygxMik7CiAgICAgICAgICBpZiAodGhpcy5lbmNvZGluZyA+IDApIHsKICAgICAgICAgICAgdGhpcy5fbG9va0JpdHMoMSk7CiAgICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodGhpcy5lbmNvZGluZyA+PSAwKSB7CiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCA0OyArK2kpIHsKICAgICAgICAgICAgICBjb2RlMSA9IHRoaXMuX2xvb2tCaXRzKDEyKTsKICAgICAgICAgICAgICBpZiAoY29kZTEgIT09IDEpIHsKICAgICAgICAgICAgICAgIGluZm8oImJhZCBydGMgY29kZTogIiArIGNvZGUxKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGhpcy5fZWF0Qml0cygxMik7CiAgICAgICAgICAgICAgaWYgKHRoaXMuZW5jb2RpbmcgPiAwKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9sb29rQml0cygxKTsKICAgICAgICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKHRoaXMuZXJyICYmIHRoaXMuZW9saW5lKSB7CiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgIGNvZGUxID0gdGhpcy5fbG9va0JpdHMoMTMpOwogICAgICAgICAgaWYgKGNvZGUxID09PSBjY2l0dEVPRikgewogICAgICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgICAgICAgIHJldHVybiAtMTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChjb2RlMSA+PiAxID09PSAxKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5fZWF0Qml0cygxKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5fZWF0Qml0cygxMik7CiAgICAgICAgaWYgKHRoaXMuZW5jb2RpbmcgPiAwKSB7CiAgICAgICAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgICAgICAgdGhpcy5uZXh0TGluZTJEID0gIShjb2RlMSAmIDEpOwogICAgICAgIH0KICAgICAgfQogICAgICB0aGlzLm91dHB1dEJpdHMgPSBjb2RpbmdMaW5lWzBdID4gMCA/IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3MgPSAwXSA6IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3MgPSAxXTsKICAgICAgdGhpcy5yb3crKzsKICAgIH0KICAgIGxldCBjOwogICAgaWYgKHRoaXMub3V0cHV0Qml0cyA+PSA4KSB7CiAgICAgIGMgPSB0aGlzLmNvZGluZ1BvcyAmIDEgPyAwIDogMHhmZjsKICAgICAgdGhpcy5vdXRwdXRCaXRzIC09IDg7CiAgICAgIGlmICh0aGlzLm91dHB1dEJpdHMgPT09IDAgJiYgY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgdGhpcy5jb2RpbmdQb3MrKzsKICAgICAgICB0aGlzLm91dHB1dEJpdHMgPSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSAtIGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3MgLSAxXTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgYml0cyA9IDg7CiAgICAgIGMgPSAwOwogICAgICBkbyB7CiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm91dHB1dEJpdHMgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoJ0ludmFsaWQgL0NDSVRURmF4RGVjb2RlIGRhdGEsICJvdXRwdXRCaXRzIiBtdXN0IGJlIGEgbnVtYmVyLicpOwogICAgICAgIH0KICAgICAgICBpZiAodGhpcy5vdXRwdXRCaXRzID4gYml0cykgewogICAgICAgICAgYyA8PD0gYml0czsKICAgICAgICAgIGlmICghKHRoaXMuY29kaW5nUG9zICYgMSkpIHsKICAgICAgICAgICAgYyB8PSAweGZmID4+IDggLSBiaXRzOwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5vdXRwdXRCaXRzIC09IGJpdHM7CiAgICAgICAgICBiaXRzID0gMDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYyA8PD0gdGhpcy5vdXRwdXRCaXRzOwogICAgICAgICAgaWYgKCEodGhpcy5jb2RpbmdQb3MgJiAxKSkgewogICAgICAgICAgICBjIHw9IDB4ZmYgPj4gOCAtIHRoaXMub3V0cHV0Qml0czsKICAgICAgICAgIH0KICAgICAgICAgIGJpdHMgLT0gdGhpcy5vdXRwdXRCaXRzOwogICAgICAgICAgdGhpcy5vdXRwdXRCaXRzID0gMDsKICAgICAgICAgIGlmIChjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgdGhpcy5jb2RpbmdQb3MrKzsKICAgICAgICAgICAgdGhpcy5vdXRwdXRCaXRzID0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gLSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zIC0gMV07CiAgICAgICAgICB9IGVsc2UgaWYgKGJpdHMgPiAwKSB7CiAgICAgICAgICAgIGMgPDw9IGJpdHM7CiAgICAgICAgICAgIGJpdHMgPSAwOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSB3aGlsZSAoYml0cyk7CiAgICB9CiAgICBpZiAodGhpcy5ibGFjaykgewogICAgICBjIF49IDB4ZmY7CiAgICB9CiAgICByZXR1cm4gYzsKICB9CiAgX2FkZFBpeGVscyhhMSwgYmxhY2tQaXhlbHMpIHsKICAgIGNvbnN0IGNvZGluZ0xpbmUgPSB0aGlzLmNvZGluZ0xpbmU7CiAgICBsZXQgY29kaW5nUG9zID0gdGhpcy5jb2RpbmdQb3M7CiAgICBpZiAoYTEgPiBjb2RpbmdMaW5lW2NvZGluZ1Bvc10pIHsKICAgICAgaWYgKGExID4gdGhpcy5jb2x1bW5zKSB7CiAgICAgICAgaW5mbygicm93IGlzIHdyb25nIGxlbmd0aCIpOwogICAgICAgIHRoaXMuZXJyID0gdHJ1ZTsKICAgICAgICBhMSA9IHRoaXMuY29sdW1uczsKICAgICAgfQogICAgICBpZiAoY29kaW5nUG9zICYgMSBeIGJsYWNrUGl4ZWxzKSB7CiAgICAgICAgKytjb2RpbmdQb3M7CiAgICAgIH0KICAgICAgY29kaW5nTGluZVtjb2RpbmdQb3NdID0gYTE7CiAgICB9CiAgICB0aGlzLmNvZGluZ1BvcyA9IGNvZGluZ1BvczsKICB9CiAgX2FkZFBpeGVsc05lZyhhMSwgYmxhY2tQaXhlbHMpIHsKICAgIGNvbnN0IGNvZGluZ0xpbmUgPSB0aGlzLmNvZGluZ0xpbmU7CiAgICBsZXQgY29kaW5nUG9zID0gdGhpcy5jb2RpbmdQb3M7CiAgICBpZiAoYTEgPiBjb2RpbmdMaW5lW2NvZGluZ1Bvc10pIHsKICAgICAgaWYgKGExID4gdGhpcy5jb2x1bW5zKSB7CiAgICAgICAgaW5mbygicm93IGlzIHdyb25nIGxlbmd0aCIpOwogICAgICAgIHRoaXMuZXJyID0gdHJ1ZTsKICAgICAgICBhMSA9IHRoaXMuY29sdW1uczsKICAgICAgfQogICAgICBpZiAoY29kaW5nUG9zICYgMSBeIGJsYWNrUGl4ZWxzKSB7CiAgICAgICAgKytjb2RpbmdQb3M7CiAgICAgIH0KICAgICAgY29kaW5nTGluZVtjb2RpbmdQb3NdID0gYTE7CiAgICB9IGVsc2UgaWYgKGExIDwgY29kaW5nTGluZVtjb2RpbmdQb3NdKSB7CiAgICAgIGlmIChhMSA8IDApIHsKICAgICAgICBpbmZvKCJpbnZhbGlkIGNvZGUiKTsKICAgICAgICB0aGlzLmVyciA9IHRydWU7CiAgICAgICAgYTEgPSAwOwogICAgICB9CiAgICAgIHdoaWxlIChjb2RpbmdQb3MgPiAwICYmIGExIDwgY29kaW5nTGluZVtjb2RpbmdQb3MgLSAxXSkgewogICAgICAgIC0tY29kaW5nUG9zOwogICAgICB9CiAgICAgIGNvZGluZ0xpbmVbY29kaW5nUG9zXSA9IGExOwogICAgfQogICAgdGhpcy5jb2RpbmdQb3MgPSBjb2RpbmdQb3M7CiAgfQogIF9maW5kVGFibGVDb2RlKHN0YXJ0LCBlbmQsIHRhYmxlLCBsaW1pdCkgewogICAgY29uc3QgbGltaXRWYWx1ZSA9IGxpbWl0IHx8IDA7CiAgICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPD0gZW5kOyArK2kpIHsKICAgICAgbGV0IGNvZGUgPSB0aGlzLl9sb29rQml0cyhpKTsKICAgICAgaWYgKGNvZGUgPT09IGNjaXR0RU9GKSB7CiAgICAgICAgcmV0dXJuIFt0cnVlLCAxLCBmYWxzZV07CiAgICAgIH0KICAgICAgaWYgKGkgPCBlbmQpIHsKICAgICAgICBjb2RlIDw8PSBlbmQgLSBpOwogICAgICB9CiAgICAgIGlmICghbGltaXRWYWx1ZSB8fCBjb2RlID49IGxpbWl0VmFsdWUpIHsKICAgICAgICBjb25zdCBwID0gdGFibGVbY29kZSAtIGxpbWl0VmFsdWVdOwogICAgICAgIGlmIChwWzBdID09PSBpKSB7CiAgICAgICAgICB0aGlzLl9lYXRCaXRzKGkpOwogICAgICAgICAgcmV0dXJuIFt0cnVlLCBwWzFdLCB0cnVlXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBbZmFsc2UsIDAsIGZhbHNlXTsKICB9CiAgX2dldFR3b0RpbUNvZGUoKSB7CiAgICBsZXQgY29kZSA9IDA7CiAgICBsZXQgcDsKICAgIGlmICh0aGlzLmVvYmxvY2spIHsKICAgICAgY29kZSA9IHRoaXMuX2xvb2tCaXRzKDcpOwogICAgICBwID0gdHdvRGltVGFibGVbY29kZV07CiAgICAgIGlmIChwPy5bMF0gPiAwKSB7CiAgICAgICAgdGhpcy5fZWF0Qml0cyhwWzBdKTsKICAgICAgICByZXR1cm4gcFsxXTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fZmluZFRhYmxlQ29kZSgxLCA3LCB0d29EaW1UYWJsZSk7CiAgICAgIGlmIChyZXN1bHRbMF0gJiYgcmVzdWx0WzJdKSB7CiAgICAgICAgcmV0dXJuIHJlc3VsdFsxXTsKICAgICAgfQogICAgfQogICAgaW5mbygiQmFkIHR3byBkaW0gY29kZSIpOwogICAgcmV0dXJuIGNjaXR0RU9GOwogIH0KICBfZ2V0V2hpdGVDb2RlKCkgewogICAgbGV0IGNvZGUgPSAwOwogICAgbGV0IHA7CiAgICBpZiAodGhpcy5lb2Jsb2NrKSB7CiAgICAgIGNvZGUgPSB0aGlzLl9sb29rQml0cygxMik7CiAgICAgIGlmIChjb2RlID09PSBjY2l0dEVPRikgewogICAgICAgIHJldHVybiAxOwogICAgICB9CiAgICAgIHAgPSBjb2RlID4+IDUgPT09IDAgPyB3aGl0ZVRhYmxlMVtjb2RlXSA6IHdoaXRlVGFibGUyW2NvZGUgPj4gM107CiAgICAgIGlmIChwWzBdID4gMCkgewogICAgICAgIHRoaXMuX2VhdEJpdHMocFswXSk7CiAgICAgICAgcmV0dXJuIHBbMV07CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGxldCByZXN1bHQgPSB0aGlzLl9maW5kVGFibGVDb2RlKDEsIDksIHdoaXRlVGFibGUyKTsKICAgICAgaWYgKHJlc3VsdFswXSkgewogICAgICAgIHJldHVybiByZXN1bHRbMV07CiAgICAgIH0KICAgICAgcmVzdWx0ID0gdGhpcy5fZmluZFRhYmxlQ29kZSgxMSwgMTIsIHdoaXRlVGFibGUxKTsKICAgICAgaWYgKHJlc3VsdFswXSkgewogICAgICAgIHJldHVybiByZXN1bHRbMV07CiAgICAgIH0KICAgIH0KICAgIGluZm8oImJhZCB3aGl0ZSBjb2RlIik7CiAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgcmV0dXJuIDE7CiAgfQogIF9nZXRCbGFja0NvZGUoKSB7CiAgICBsZXQgY29kZSwgcDsKICAgIGlmICh0aGlzLmVvYmxvY2spIHsKICAgICAgY29kZSA9IHRoaXMuX2xvb2tCaXRzKDEzKTsKICAgICAgaWYgKGNvZGUgPT09IGNjaXR0RU9GKSB7CiAgICAgICAgcmV0dXJuIDE7CiAgICAgIH0KICAgICAgaWYgKGNvZGUgPj4gNyA9PT0gMCkgewogICAgICAgIHAgPSBibGFja1RhYmxlMVtjb2RlXTsKICAgICAgfSBlbHNlIGlmIChjb2RlID4+IDkgPT09IDAgJiYgY29kZSA+PiA3ICE9PSAwKSB7CiAgICAgICAgcCA9IGJsYWNrVGFibGUyWyhjb2RlID4+IDEpIC0gNjRdOwogICAgICB9IGVsc2UgewogICAgICAgIHAgPSBibGFja1RhYmxlM1tjb2RlID4+IDddOwogICAgICB9CiAgICAgIGlmIChwWzBdID4gMCkgewogICAgICAgIHRoaXMuX2VhdEJpdHMocFswXSk7CiAgICAgICAgcmV0dXJuIHBbMV07CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGxldCByZXN1bHQgPSB0aGlzLl9maW5kVGFibGVDb2RlKDIsIDYsIGJsYWNrVGFibGUzKTsKICAgICAgaWYgKHJlc3VsdFswXSkgewogICAgICAgIHJldHVybiByZXN1bHRbMV07CiAgICAgIH0KICAgICAgcmVzdWx0ID0gdGhpcy5fZmluZFRhYmxlQ29kZSg3LCAxMiwgYmxhY2tUYWJsZTIsIDY0KTsKICAgICAgaWYgKHJlc3VsdFswXSkgewogICAgICAgIHJldHVybiByZXN1bHRbMV07CiAgICAgIH0KICAgICAgcmVzdWx0ID0gdGhpcy5fZmluZFRhYmxlQ29kZSgxMCwgMTMsIGJsYWNrVGFibGUxKTsKICAgICAgaWYgKHJlc3VsdFswXSkgewogICAgICAgIHJldHVybiByZXN1bHRbMV07CiAgICAgIH0KICAgIH0KICAgIGluZm8oImJhZCBibGFjayBjb2RlIik7CiAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgcmV0dXJuIDE7CiAgfQogIF9sb29rQml0cyhuKSB7CiAgICBsZXQgYzsKICAgIHdoaWxlICh0aGlzLmlucHV0Qml0cyA8IG4pIHsKICAgICAgaWYgKChjID0gdGhpcy5zb3VyY2UubmV4dCgpKSA9PT0gLTEpIHsKICAgICAgICBpZiAodGhpcy5pbnB1dEJpdHMgPT09IDApIHsKICAgICAgICAgIHJldHVybiBjY2l0dEVPRjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXMuaW5wdXRCdWYgPDwgbiAtIHRoaXMuaW5wdXRCaXRzICYgMHhmZmZmID4+IDE2IC0gbjsKICAgICAgfQogICAgICB0aGlzLmlucHV0QnVmID0gdGhpcy5pbnB1dEJ1ZiA8PCA4IHwgYzsKICAgICAgdGhpcy5pbnB1dEJpdHMgKz0gODsKICAgIH0KICAgIHJldHVybiB0aGlzLmlucHV0QnVmID4+IHRoaXMuaW5wdXRCaXRzIC0gbiAmIDB4ZmZmZiA+PiAxNiAtIG47CiAgfQogIF9lYXRCaXRzKG4pIHsKICAgIGlmICgodGhpcy5pbnB1dEJpdHMgLT0gbikgPCAwKSB7CiAgICAgIHRoaXMuaW5wdXRCaXRzID0gMDsKICAgIH0KICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2NjaXR0X3N0cmVhbS5qcwoKCgpjbGFzcyBDQ0lUVEZheFN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyLCBtYXliZUxlbmd0aCwgcGFyYW1zKSB7CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0cmVhbSA9IHN0cjsKICAgIHRoaXMuZGljdCA9IHN0ci5kaWN0OwogICAgaWYgKCEocGFyYW1zIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcGFyYW1zID0gRGljdC5lbXB0eTsKICAgIH0KICAgIGNvbnN0IHNvdXJjZSA9IHsKICAgICAgbmV4dCgpIHsKICAgICAgICByZXR1cm4gc3RyLmdldEJ5dGUoKTsKICAgICAgfQogICAgfTsKICAgIHRoaXMuY2NpdHRGYXhEZWNvZGVyID0gbmV3IENDSVRURmF4RGVjb2Rlcihzb3VyY2UsIHsKICAgICAgSzogcGFyYW1zLmdldCgiSyIpLAogICAgICBFbmRPZkxpbmU6IHBhcmFtcy5nZXQoIkVuZE9mTGluZSIpLAogICAgICBFbmNvZGVkQnl0ZUFsaWduOiBwYXJhbXMuZ2V0KCJFbmNvZGVkQnl0ZUFsaWduIiksCiAgICAgIENvbHVtbnM6IHBhcmFtcy5nZXQoIkNvbHVtbnMiKSwKICAgICAgUm93czogcGFyYW1zLmdldCgiUm93cyIpLAogICAgICBFbmRPZkJsb2NrOiBwYXJhbXMuZ2V0KCJFbmRPZkJsb2NrIiksCiAgICAgIEJsYWNrSXMxOiBwYXJhbXMuZ2V0KCJCbGFja0lzMSIpCiAgICB9KTsKICB9CiAgcmVhZEJsb2NrKCkgewogICAgd2hpbGUgKCF0aGlzLmVvZikgewogICAgICBjb25zdCBjID0gdGhpcy5jY2l0dEZheERlY29kZXIucmVhZE5leHRDaGFyKCk7CiAgICAgIGlmIChjID09PSAtMSkgewogICAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhpcy5lbnN1cmVCdWZmZXIodGhpcy5idWZmZXJMZW5ndGggKyAxKTsKICAgICAgdGhpcy5idWZmZXJbdGhpcy5idWZmZXJMZW5ndGgrK10gPSBjOwogICAgfQogIH0KICBnZXQgaXNJbWFnZVN0cmVhbSgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvZmxhdGVfc3RyZWFtLmpzCgoKCmNvbnN0IGNvZGVMZW5Db2RlTWFwID0gbmV3IEludDMyQXJyYXkoWzE2LCAxNywgMTgsIDAsIDgsIDcsIDksIDYsIDEwLCA1LCAxMSwgNCwgMTIsIDMsIDEzLCAyLCAxNCwgMSwgMTVdKTsKY29uc3QgbGVuZ3RoRGVjb2RlID0gbmV3IEludDMyQXJyYXkoWzB4MDAwMDMsIDB4MDAwMDQsIDB4MDAwMDUsIDB4MDAwMDYsIDB4MDAwMDcsIDB4MDAwMDgsIDB4MDAwMDksIDB4MDAwMGEsIDB4MTAwMGIsIDB4MTAwMGQsIDB4MTAwMGYsIDB4MTAwMTEsIDB4MjAwMTMsIDB4MjAwMTcsIDB4MjAwMWIsIDB4MjAwMWYsIDB4MzAwMjMsIDB4MzAwMmIsIDB4MzAwMzMsIDB4MzAwM2IsIDB4NDAwNDMsIDB4NDAwNTMsIDB4NDAwNjMsIDB4NDAwNzMsIDB4NTAwODMsIDB4NTAwYTMsIDB4NTAwYzMsIDB4NTAwZTMsIDB4MDAxMDIsIDB4MDAxMDIsIDB4MDAxMDJdKTsKY29uc3QgZGlzdERlY29kZSA9IG5ldyBJbnQzMkFycmF5KFsweDAwMDAxLCAweDAwMDAyLCAweDAwMDAzLCAweDAwMDA0LCAweDEwMDA1LCAweDEwMDA3LCAweDIwMDA5LCAweDIwMDBkLCAweDMwMDExLCAweDMwMDE5LCAweDQwMDIxLCAweDQwMDMxLCAweDUwMDQxLCAweDUwMDYxLCAweDYwMDgxLCAweDYwMGMxLCAweDcwMTAxLCAweDcwMTgxLCAweDgwMjAxLCAweDgwMzAxLCAweDkwNDAxLCAweDkwNjAxLCAweGEwODAxLCAweGEwYzAxLCAweGIxMDAxLCAweGIxODAxLCAweGMyMDAxLCAweGMzMDAxLCAweGQ0MDAxLCAweGQ2MDAxXSk7CmNvbnN0IGZpeGVkTGl0Q29kZVRhYiA9IFtuZXcgSW50MzJBcnJheShbMHg3MDEwMCwgMHg4MDA1MCwgMHg4MDAxMCwgMHg4MDExOCwgMHg3MDExMCwgMHg4MDA3MCwgMHg4MDAzMCwgMHg5MDBjMCwgMHg3MDEwOCwgMHg4MDA2MCwgMHg4MDAyMCwgMHg5MDBhMCwgMHg4MDAwMCwgMHg4MDA4MCwgMHg4MDA0MCwgMHg5MDBlMCwgMHg3MDEwNCwgMHg4MDA1OCwgMHg4MDAxOCwgMHg5MDA5MCwgMHg3MDExNCwgMHg4MDA3OCwgMHg4MDAzOCwgMHg5MDBkMCwgMHg3MDEwYywgMHg4MDA2OCwgMHg4MDAyOCwgMHg5MDBiMCwgMHg4MDAwOCwgMHg4MDA4OCwgMHg4MDA0OCwgMHg5MDBmMCwgMHg3MDEwMiwgMHg4MDA1NCwgMHg4MDAxNCwgMHg4MDExYywgMHg3MDExMiwgMHg4MDA3NCwgMHg4MDAzNCwgMHg5MDBjOCwgMHg3MDEwYSwgMHg4MDA2NCwgMHg4MDAyNCwgMHg5MDBhOCwgMHg4MDAwNCwgMHg4MDA4NCwgMHg4MDA0NCwgMHg5MDBlOCwgMHg3MDEwNiwgMHg4MDA1YywgMHg4MDAxYywgMHg5MDA5OCwgMHg3MDExNiwgMHg4MDA3YywgMHg4MDAzYywgMHg5MDBkOCwgMHg3MDEwZSwgMHg4MDA2YywgMHg4MDAyYywgMHg5MDBiOCwgMHg4MDAwYywgMHg4MDA4YywgMHg4MDA0YywgMHg5MDBmOCwgMHg3MDEwMSwgMHg4MDA1MiwgMHg4MDAxMiwgMHg4MDExYSwgMHg3MDExMSwgMHg4MDA3MiwgMHg4MDAzMiwgMHg5MDBjNCwgMHg3MDEwOSwgMHg4MDA2MiwgMHg4MDAyMiwgMHg5MDBhNCwgMHg4MDAwMiwgMHg4MDA4MiwgMHg4MDA0MiwgMHg5MDBlNCwgMHg3MDEwNSwgMHg4MDA1YSwgMHg4MDAxYSwgMHg5MDA5NCwgMHg3MDExNSwgMHg4MDA3YSwgMHg4MDAzYSwgMHg5MDBkNCwgMHg3MDEwZCwgMHg4MDA2YSwgMHg4MDAyYSwgMHg5MDBiNCwgMHg4MDAwYSwgMHg4MDA4YSwgMHg4MDA0YSwgMHg5MDBmNCwgMHg3MDEwMywgMHg4MDA1NiwgMHg4MDAxNiwgMHg4MDExZSwgMHg3MDExMywgMHg4MDA3NiwgMHg4MDAzNiwgMHg5MDBjYywgMHg3MDEwYiwgMHg4MDA2NiwgMHg4MDAyNiwgMHg5MDBhYywgMHg4MDAwNiwgMHg4MDA4NiwgMHg4MDA0NiwgMHg5MDBlYywgMHg3MDEwNywgMHg4MDA1ZSwgMHg4MDAxZSwgMHg5MDA5YywgMHg3MDExNywgMHg4MDA3ZSwgMHg4MDAzZSwgMHg5MDBkYywgMHg3MDEwZiwgMHg4MDA2ZSwgMHg4MDAyZSwgMHg5MDBiYywgMHg4MDAwZSwgMHg4MDA4ZSwgMHg4MDA0ZSwgMHg5MDBmYywgMHg3MDEwMCwgMHg4MDA1MSwgMHg4MDAxMSwgMHg4MDExOSwgMHg3MDExMCwgMHg4MDA3MSwgMHg4MDAzMSwgMHg5MDBjMiwgMHg3MDEwOCwgMHg4MDA2MSwgMHg4MDAyMSwgMHg5MDBhMiwgMHg4MDAwMSwgMHg4MDA4MSwgMHg4MDA0MSwgMHg5MDBlMiwgMHg3MDEwNCwgMHg4MDA1OSwgMHg4MDAxOSwgMHg5MDA5MiwgMHg3MDExNCwgMHg4MDA3OSwgMHg4MDAzOSwgMHg5MDBkMiwgMHg3MDEwYywgMHg4MDA2OSwgMHg4MDAyOSwgMHg5MDBiMiwgMHg4MDAwOSwgMHg4MDA4OSwgMHg4MDA0OSwgMHg5MDBmMiwgMHg3MDEwMiwgMHg4MDA1NSwgMHg4MDAxNSwgMHg4MDExZCwgMHg3MDExMiwgMHg4MDA3NSwgMHg4MDAzNSwgMHg5MDBjYSwgMHg3MDEwYSwgMHg4MDA2NSwgMHg4MDAyNSwgMHg5MDBhYSwgMHg4MDAwNSwgMHg4MDA4NSwgMHg4MDA0NSwgMHg5MDBlYSwgMHg3MDEwNiwgMHg4MDA1ZCwgMHg4MDAxZCwgMHg5MDA5YSwgMHg3MDExNiwgMHg4MDA3ZCwgMHg4MDAzZCwgMHg5MDBkYSwgMHg3MDEwZSwgMHg4MDA2ZCwgMHg4MDAyZCwgMHg5MDBiYSwgMHg4MDAwZCwgMHg4MDA4ZCwgMHg4MDA0ZCwgMHg5MDBmYSwgMHg3MDEwMSwgMHg4MDA1MywgMHg4MDAxMywgMHg4MDExYiwgMHg3MDExMSwgMHg4MDA3MywgMHg4MDAzMywgMHg5MDBjNiwgMHg3MDEwOSwgMHg4MDA2MywgMHg4MDAyMywgMHg5MDBhNiwgMHg4MDAwMywgMHg4MDA4MywgMHg4MDA0MywgMHg5MDBlNiwgMHg3MDEwNSwgMHg4MDA1YiwgMHg4MDAxYiwgMHg5MDA5NiwgMHg3MDExNSwgMHg4MDA3YiwgMHg4MDAzYiwgMHg5MDBkNiwgMHg3MDEwZCwgMHg4MDA2YiwgMHg4MDAyYiwgMHg5MDBiNiwgMHg4MDAwYiwgMHg4MDA4YiwgMHg4MDA0YiwgMHg5MDBmNiwgMHg3MDEwMywgMHg4MDA1NywgMHg4MDAxNywgMHg4MDExZiwgMHg3MDExMywgMHg4MDA3NywgMHg4MDAzNywgMHg5MDBjZSwgMHg3MDEwYiwgMHg4MDA2NywgMHg4MDAyNywgMHg5MDBhZSwgMHg4MDAwNywgMHg4MDA4NywgMHg4MDA0NywgMHg5MDBlZSwgMHg3MDEwNywgMHg4MDA1ZiwgMHg4MDAxZiwgMHg5MDA5ZSwgMHg3MDExNywgMHg4MDA3ZiwgMHg4MDAzZiwgMHg5MDBkZSwgMHg3MDEwZiwgMHg4MDA2ZiwgMHg4MDAyZiwgMHg5MDBiZSwgMHg4MDAwZiwgMHg4MDA4ZiwgMHg4MDA0ZiwgMHg5MDBmZSwgMHg3MDEwMCwgMHg4MDA1MCwgMHg4MDAxMCwgMHg4MDExOCwgMHg3MDExMCwgMHg4MDA3MCwgMHg4MDAzMCwgMHg5MDBjMSwgMHg3MDEwOCwgMHg4MDA2MCwgMHg4MDAyMCwgMHg5MDBhMSwgMHg4MDAwMCwgMHg4MDA4MCwgMHg4MDA0MCwgMHg5MDBlMSwgMHg3MDEwNCwgMHg4MDA1OCwgMHg4MDAxOCwgMHg5MDA5MSwgMHg3MDExNCwgMHg4MDA3OCwgMHg4MDAzOCwgMHg5MDBkMSwgMHg3MDEwYywgMHg4MDA2OCwgMHg4MDAyOCwgMHg5MDBiMSwgMHg4MDAwOCwgMHg4MDA4OCwgMHg4MDA0OCwgMHg5MDBmMSwgMHg3MDEwMiwgMHg4MDA1NCwgMHg4MDAxNCwgMHg4MDExYywgMHg3MDExMiwgMHg4MDA3NCwgMHg4MDAzNCwgMHg5MDBjOSwgMHg3MDEwYSwgMHg4MDA2NCwgMHg4MDAyNCwgMHg5MDBhOSwgMHg4MDAwNCwgMHg4MDA4NCwgMHg4MDA0NCwgMHg5MDBlOSwgMHg3MDEwNiwgMHg4MDA1YywgMHg4MDAxYywgMHg5MDA5OSwgMHg3MDExNiwgMHg4MDA3YywgMHg4MDAzYywgMHg5MDBkOSwgMHg3MDEwZSwgMHg4MDA2YywgMHg4MDAyYywgMHg5MDBiOSwgMHg4MDAwYywgMHg4MDA4YywgMHg4MDA0YywgMHg5MDBmOSwgMHg3MDEwMSwgMHg4MDA1MiwgMHg4MDAxMiwgMHg4MDExYSwgMHg3MDExMSwgMHg4MDA3MiwgMHg4MDAzMiwgMHg5MDBjNSwgMHg3MDEwOSwgMHg4MDA2MiwgMHg4MDAyMiwgMHg5MDBhNSwgMHg4MDAwMiwgMHg4MDA4MiwgMHg4MDA0MiwgMHg5MDBlNSwgMHg3MDEwNSwgMHg4MDA1YSwgMHg4MDAxYSwgMHg5MDA5NSwgMHg3MDExNSwgMHg4MDA3YSwgMHg4MDAzYSwgMHg5MDBkNSwgMHg3MDEwZCwgMHg4MDA2YSwgMHg4MDAyYSwgMHg5MDBiNSwgMHg4MDAwYSwgMHg4MDA4YSwgMHg4MDA0YSwgMHg5MDBmNSwgMHg3MDEwMywgMHg4MDA1NiwgMHg4MDAxNiwgMHg4MDExZSwgMHg3MDExMywgMHg4MDA3NiwgMHg4MDAzNiwgMHg5MDBjZCwgMHg3MDEwYiwgMHg4MDA2NiwgMHg4MDAyNiwgMHg5MDBhZCwgMHg4MDAwNiwgMHg4MDA4NiwgMHg4MDA0NiwgMHg5MDBlZCwgMHg3MDEwNywgMHg4MDA1ZSwgMHg4MDAxZSwgMHg5MDA5ZCwgMHg3MDExNywgMHg4MDA3ZSwgMHg4MDAzZSwgMHg5MDBkZCwgMHg3MDEwZiwgMHg4MDA2ZSwgMHg4MDAyZSwgMHg5MDBiZCwgMHg4MDAwZSwgMHg4MDA4ZSwgMHg4MDA0ZSwgMHg5MDBmZCwgMHg3MDEwMCwgMHg4MDA1MSwgMHg4MDAxMSwgMHg4MDExOSwgMHg3MDExMCwgMHg4MDA3MSwgMHg4MDAzMSwgMHg5MDBjMywgMHg3MDEwOCwgMHg4MDA2MSwgMHg4MDAyMSwgMHg5MDBhMywgMHg4MDAwMSwgMHg4MDA4MSwgMHg4MDA0MSwgMHg5MDBlMywgMHg3MDEwNCwgMHg4MDA1OSwgMHg4MDAxOSwgMHg5MDA5MywgMHg3MDExNCwgMHg4MDA3OSwgMHg4MDAzOSwgMHg5MDBkMywgMHg3MDEwYywgMHg4MDA2OSwgMHg4MDAyOSwgMHg5MDBiMywgMHg4MDAwOSwgMHg4MDA4OSwgMHg4MDA0OSwgMHg5MDBmMywgMHg3MDEwMiwgMHg4MDA1NSwgMHg4MDAxNSwgMHg4MDExZCwgMHg3MDExMiwgMHg4MDA3NSwgMHg4MDAzNSwgMHg5MDBjYiwgMHg3MDEwYSwgMHg4MDA2NSwgMHg4MDAyNSwgMHg5MDBhYiwgMHg4MDAwNSwgMHg4MDA4NSwgMHg4MDA0NSwgMHg5MDBlYiwgMHg3MDEwNiwgMHg4MDA1ZCwgMHg4MDAxZCwgMHg5MDA5YiwgMHg3MDExNiwgMHg4MDA3ZCwgMHg4MDAzZCwgMHg5MDBkYiwgMHg3MDEwZSwgMHg4MDA2ZCwgMHg4MDAyZCwgMHg5MDBiYiwgMHg4MDAwZCwgMHg4MDA4ZCwgMHg4MDA0ZCwgMHg5MDBmYiwgMHg3MDEwMSwgMHg4MDA1MywgMHg4MDAxMywgMHg4MDExYiwgMHg3MDExMSwgMHg4MDA3MywgMHg4MDAzMywgMHg5MDBjNywgMHg3MDEwOSwgMHg4MDA2MywgMHg4MDAyMywgMHg5MDBhNywgMHg4MDAwMywgMHg4MDA4MywgMHg4MDA0MywgMHg5MDBlNywgMHg3MDEwNSwgMHg4MDA1YiwgMHg4MDAxYiwgMHg5MDA5NywgMHg3MDExNSwgMHg4MDA3YiwgMHg4MDAzYiwgMHg5MDBkNywgMHg3MDEwZCwgMHg4MDA2YiwgMHg4MDAyYiwgMHg5MDBiNywgMHg4MDAwYiwgMHg4MDA4YiwgMHg4MDA0YiwgMHg5MDBmNywgMHg3MDEwMywgMHg4MDA1NywgMHg4MDAxNywgMHg4MDExZiwgMHg3MDExMywgMHg4MDA3NywgMHg4MDAzNywgMHg5MDBjZiwgMHg3MDEwYiwgMHg4MDA2NywgMHg4MDAyNywgMHg5MDBhZiwgMHg4MDAwNywgMHg4MDA4NywgMHg4MDA0NywgMHg5MDBlZiwgMHg3MDEwNywgMHg4MDA1ZiwgMHg4MDAxZiwgMHg5MDA5ZiwgMHg3MDExNywgMHg4MDA3ZiwgMHg4MDAzZiwgMHg5MDBkZiwgMHg3MDEwZiwgMHg4MDA2ZiwgMHg4MDAyZiwgMHg5MDBiZiwgMHg4MDAwZiwgMHg4MDA4ZiwgMHg4MDA0ZiwgMHg5MDBmZl0pLCA5XTsKY29uc3QgZml4ZWREaXN0Q29kZVRhYiA9IFtuZXcgSW50MzJBcnJheShbMHg1MDAwMCwgMHg1MDAxMCwgMHg1MDAwOCwgMHg1MDAxOCwgMHg1MDAwNCwgMHg1MDAxNCwgMHg1MDAwYywgMHg1MDAxYywgMHg1MDAwMiwgMHg1MDAxMiwgMHg1MDAwYSwgMHg1MDAxYSwgMHg1MDAwNiwgMHg1MDAxNiwgMHg1MDAwZSwgMHgwMDAwMCwgMHg1MDAwMSwgMHg1MDAxMSwgMHg1MDAwOSwgMHg1MDAxOSwgMHg1MDAwNSwgMHg1MDAxNSwgMHg1MDAwZCwgMHg1MDAxZCwgMHg1MDAwMywgMHg1MDAxMywgMHg1MDAwYiwgMHg1MDAxYiwgMHg1MDAwNywgMHg1MDAxNywgMHg1MDAwZiwgMHgwMDAwMF0pLCA1XTsKY2xhc3MgRmxhdGVTdHJlYW0gZXh0ZW5kcyBEZWNvZGVTdHJlYW0gewogICNpc0FzeW5jID0gdHJ1ZTsKICBjb25zdHJ1Y3RvcihzdHIsIG1heWJlTGVuZ3RoKSB7CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0cmVhbSA9IHN0cjsKICAgIHRoaXMuZGljdCA9IHN0ci5kaWN0OwogICAgY29uc3QgY21mID0gc3RyLmdldEJ5dGUoKTsKICAgIGNvbnN0IGZsZyA9IHN0ci5nZXRCeXRlKCk7CiAgICBpZiAoY21mID09PSAtMSB8fCBmbGcgPT09IC0xKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBoZWFkZXIgaW4gZmxhdGUgc3RyZWFtOiAke2NtZn0sICR7ZmxnfWApOwogICAgfQogICAgaWYgKChjbWYgJiAweDBmKSAhPT0gMHgwOCkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVua25vd24gY29tcHJlc3Npb24gbWV0aG9kIGluIGZsYXRlIHN0cmVhbTogJHtjbWZ9LCAke2ZsZ31gKTsKICAgIH0KICAgIGlmICgoKGNtZiA8PCA4KSArIGZsZykgJSAzMSAhPT0gMCkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEJhZCBGQ0hFQ0sgaW4gZmxhdGUgc3RyZWFtOiAke2NtZn0sICR7ZmxnfWApOwogICAgfQogICAgaWYgKGZsZyAmIDB4MjApIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBGRElDVCBiaXQgc2V0IGluIGZsYXRlIHN0cmVhbTogJHtjbWZ9LCAke2ZsZ31gKTsKICAgIH0KICAgIHRoaXMuY29kZVNpemUgPSAwOwogICAgdGhpcy5jb2RlQnVmID0gMDsKICB9CiAgYXN5bmMgZ2V0SW1hZ2VEYXRhKGxlbmd0aCwgX2RlY29kZXJPcHRpb25zKSB7CiAgICBjb25zdCBkYXRhID0gYXdhaXQgdGhpcy5hc3luY0dldEJ5dGVzKCk7CiAgICBpZiAoIWRhdGEpIHsKICAgICAgcmV0dXJuIHRoaXMuZ2V0Qnl0ZXMobGVuZ3RoKTsKICAgIH0KICAgIGlmIChkYXRhLmxlbmd0aCA8PSBsZW5ndGgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9CiAgICByZXR1cm4gZGF0YS5zdWJhcnJheSgwLCBsZW5ndGgpOwogIH0KICBhc3luYyBhc3luY0dldEJ5dGVzKCkgewogICAgdGhpcy5zdHJlYW0ucmVzZXQoKTsKICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5zdHJlYW0uaXNBc3luYyA/IGF3YWl0IHRoaXMuc3RyZWFtLmFzeW5jR2V0Qnl0ZXMoKSA6IHRoaXMuc3RyZWFtLmdldEJ5dGVzKCk7CiAgICB0cnkgewogICAgICBjb25zdCB7CiAgICAgICAgcmVhZGFibGUsCiAgICAgICAgd3JpdGFibGUKICAgICAgfSA9IG5ldyBEZWNvbXByZXNzaW9uU3RyZWFtKCJkZWZsYXRlIik7CiAgICAgIGNvbnN0IHdyaXRlciA9IHdyaXRhYmxlLmdldFdyaXRlcigpOwogICAgICBhd2FpdCB3cml0ZXIucmVhZHk7CiAgICAgIHdyaXRlci53cml0ZShieXRlcykudGhlbihhc3luYyAoKSA9PiB7CiAgICAgICAgYXdhaXQgd3JpdGVyLnJlYWR5OwogICAgICAgIGF3YWl0IHdyaXRlci5jbG9zZSgpOwogICAgICB9KS5jYXRjaCgoKSA9PiB7fSk7CiAgICAgIGNvbnN0IGNodW5rcyA9IFtdOwogICAgICBsZXQgdG90YWxMZW5ndGggPSAwOwogICAgICBmb3IgYXdhaXQgKGNvbnN0IGNodW5rIG9mIHJlYWRhYmxlKSB7CiAgICAgICAgY2h1bmtzLnB1c2goY2h1bmspOwogICAgICAgIHRvdGFsTGVuZ3RoICs9IGNodW5rLmJ5dGVMZW5ndGg7CiAgICAgIH0KICAgICAgY29uc3QgZGF0YSA9IG5ldyBVaW50OEFycmF5KHRvdGFsTGVuZ3RoKTsKICAgICAgbGV0IG9mZnNldCA9IDA7CiAgICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzKSB7CiAgICAgICAgZGF0YS5zZXQoY2h1bmssIG9mZnNldCk7CiAgICAgICAgb2Zmc2V0ICs9IGNodW5rLmJ5dGVMZW5ndGg7CiAgICAgIH0KICAgICAgcmV0dXJuIGRhdGE7CiAgICB9IGNhdGNoIHsKICAgICAgdGhpcy4jaXNBc3luYyA9IGZhbHNlOwogICAgICB0aGlzLnN0cmVhbSA9IG5ldyBTdHJlYW0oYnl0ZXMsIDIsIGJ5dGVzLmxlbmd0aCwgdGhpcy5zdHJlYW0uZGljdCk7CiAgICAgIHRoaXMucmVzZXQoKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgfQogIGdldCBpc0FzeW5jKCkgewogICAgcmV0dXJuIHRoaXMuI2lzQXN5bmM7CiAgfQogIGdldEJpdHMoYml0cykgewogICAgY29uc3Qgc3RyID0gdGhpcy5zdHJlYW07CiAgICBsZXQgY29kZVNpemUgPSB0aGlzLmNvZGVTaXplOwogICAgbGV0IGNvZGVCdWYgPSB0aGlzLmNvZGVCdWY7CiAgICBsZXQgYjsKICAgIHdoaWxlIChjb2RlU2l6ZSA8IGJpdHMpIHsKICAgICAgaWYgKChiID0gc3RyLmdldEJ5dGUoKSkgPT09IC0xKSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJCYWQgZW5jb2RpbmcgaW4gZmxhdGUgc3RyZWFtIik7CiAgICAgIH0KICAgICAgY29kZUJ1ZiB8PSBiIDw8IGNvZGVTaXplOwogICAgICBjb2RlU2l6ZSArPSA4OwogICAgfQogICAgYiA9IGNvZGVCdWYgJiAoMSA8PCBiaXRzKSAtIDE7CiAgICB0aGlzLmNvZGVCdWYgPSBjb2RlQnVmID4+IGJpdHM7CiAgICB0aGlzLmNvZGVTaXplID0gY29kZVNpemUgLT0gYml0czsKICAgIHJldHVybiBiOwogIH0KICBnZXRDb2RlKHRhYmxlKSB7CiAgICBjb25zdCBzdHIgPSB0aGlzLnN0cmVhbTsKICAgIGNvbnN0IGNvZGVzID0gdGFibGVbMF07CiAgICBjb25zdCBtYXhMZW4gPSB0YWJsZVsxXTsKICAgIGxldCBjb2RlU2l6ZSA9IHRoaXMuY29kZVNpemU7CiAgICBsZXQgY29kZUJ1ZiA9IHRoaXMuY29kZUJ1ZjsKICAgIGxldCBiOwogICAgd2hpbGUgKGNvZGVTaXplIDwgbWF4TGVuKSB7CiAgICAgIGlmICgoYiA9IHN0ci5nZXRCeXRlKCkpID09PSAtMSkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNvZGVCdWYgfD0gYiA8PCBjb2RlU2l6ZTsKICAgICAgY29kZVNpemUgKz0gODsKICAgIH0KICAgIGNvbnN0IGNvZGUgPSBjb2Rlc1tjb2RlQnVmICYgKDEgPDwgbWF4TGVuKSAtIDFdOwogICAgY29uc3QgY29kZUxlbiA9IGNvZGUgPj4gMTY7CiAgICBjb25zdCBjb2RlVmFsID0gY29kZSAmIDB4ZmZmZjsKICAgIGlmIChjb2RlTGVuIDwgMSB8fCBjb2RlU2l6ZSA8IGNvZGVMZW4pIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJCYWQgZW5jb2RpbmcgaW4gZmxhdGUgc3RyZWFtIik7CiAgICB9CiAgICB0aGlzLmNvZGVCdWYgPSBjb2RlQnVmID4+IGNvZGVMZW47CiAgICB0aGlzLmNvZGVTaXplID0gY29kZVNpemUgLSBjb2RlTGVuOwogICAgcmV0dXJuIGNvZGVWYWw7CiAgfQogIGdlbmVyYXRlSHVmZm1hblRhYmxlKGxlbmd0aHMpIHsKICAgIGNvbnN0IG4gPSBsZW5ndGhzLmxlbmd0aDsKICAgIGxldCBtYXhMZW4gPSAwOwogICAgbGV0IGk7CiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7CiAgICAgIGlmIChsZW5ndGhzW2ldID4gbWF4TGVuKSB7CiAgICAgICAgbWF4TGVuID0gbGVuZ3Roc1tpXTsKICAgICAgfQogICAgfQogICAgY29uc3Qgc2l6ZSA9IDEgPDwgbWF4TGVuOwogICAgY29uc3QgY29kZXMgPSBuZXcgSW50MzJBcnJheShzaXplKTsKICAgIGZvciAobGV0IGxlbiA9IDEsIGNvZGUgPSAwLCBza2lwID0gMjsgbGVuIDw9IG1heExlbjsgKytsZW4sIGNvZGUgPDw9IDEsIHNraXAgPDw9IDEpIHsKICAgICAgZm9yIChsZXQgdmFsID0gMDsgdmFsIDwgbjsgKyt2YWwpIHsKICAgICAgICBpZiAobGVuZ3Roc1t2YWxdID09PSBsZW4pIHsKICAgICAgICAgIGxldCBjb2RlMiA9IDA7CiAgICAgICAgICBsZXQgdCA9IGNvZGU7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyArK2kpIHsKICAgICAgICAgICAgY29kZTIgPSBjb2RlMiA8PCAxIHwgdCAmIDE7CiAgICAgICAgICAgIHQgPj49IDE7CiAgICAgICAgICB9CiAgICAgICAgICBmb3IgKGkgPSBjb2RlMjsgaSA8IHNpemU7IGkgKz0gc2tpcCkgewogICAgICAgICAgICBjb2Rlc1tpXSA9IGxlbiA8PCAxNiB8IHZhbDsKICAgICAgICAgIH0KICAgICAgICAgICsrY29kZTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBbY29kZXMsIG1heExlbl07CiAgfQogICNlbmRzU3RyZWFtT25FcnJvcihlcnIpIHsKICAgIGluZm8oZXJyKTsKICAgIHRoaXMuZW9mID0gdHJ1ZTsKICB9CiAgcmVhZEJsb2NrKCkgewogICAgbGV0IGJ1ZmZlciwgaGRyLCBsZW47CiAgICBjb25zdCBzdHIgPSB0aGlzLnN0cmVhbTsKICAgIHRyeSB7CiAgICAgIGhkciA9IHRoaXMuZ2V0Qml0cygzKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIHRoaXMuI2VuZHNTdHJlYW1PbkVycm9yKGV4Lm1lc3NhZ2UpOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoaGRyICYgMSkgewogICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICB9CiAgICBoZHIgPj49IDE7CiAgICBpZiAoaGRyID09PSAwKSB7CiAgICAgIGxldCBiOwogICAgICBpZiAoKGIgPSBzdHIuZ2V0Qnl0ZSgpKSA9PT0gLTEpIHsKICAgICAgICB0aGlzLiNlbmRzU3RyZWFtT25FcnJvcigiQmFkIGJsb2NrIGhlYWRlciBpbiBmbGF0ZSBzdHJlYW0iKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgbGV0IGJsb2NrTGVuID0gYjsKICAgICAgaWYgKChiID0gc3RyLmdldEJ5dGUoKSkgPT09IC0xKSB7CiAgICAgICAgdGhpcy4jZW5kc1N0cmVhbU9uRXJyb3IoIkJhZCBibG9jayBoZWFkZXIgaW4gZmxhdGUgc3RyZWFtIik7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGJsb2NrTGVuIHw9IGIgPDwgODsKICAgICAgaWYgKChiID0gc3RyLmdldEJ5dGUoKSkgPT09IC0xKSB7CiAgICAgICAgdGhpcy4jZW5kc1N0cmVhbU9uRXJyb3IoIkJhZCBibG9jayBoZWFkZXIgaW4gZmxhdGUgc3RyZWFtIik7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGxldCBjaGVjayA9IGI7CiAgICAgIGlmICgoYiA9IHN0ci5nZXRCeXRlKCkpID09PSAtMSkgewogICAgICAgIHRoaXMuI2VuZHNTdHJlYW1PbkVycm9yKCJCYWQgYmxvY2sgaGVhZGVyIGluIGZsYXRlIHN0cmVhbSIpOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBjaGVjayB8PSBiIDw8IDg7CiAgICAgIGlmIChjaGVjayAhPT0gKH5ibG9ja0xlbiAmIDB4ZmZmZikgJiYgKGJsb2NrTGVuICE9PSAwIHx8IGNoZWNrICE9PSAwKSkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiQmFkIHVuY29tcHJlc3NlZCBibG9jayBsZW5ndGggaW4gZmxhdGUgc3RyZWFtIik7CiAgICAgIH0KICAgICAgdGhpcy5jb2RlQnVmID0gMDsKICAgICAgdGhpcy5jb2RlU2l6ZSA9IDA7CiAgICAgIGNvbnN0IGJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyTGVuZ3RoLAogICAgICAgIGVuZCA9IGJ1ZmZlckxlbmd0aCArIGJsb2NrTGVuOwogICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihlbmQpOwogICAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGVuZDsKICAgICAgaWYgKGJsb2NrTGVuID09PSAwKSB7CiAgICAgICAgaWYgKHN0ci5wZWVrQnl0ZSgpID09PSAtMSkgewogICAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBibG9jayA9IHN0ci5nZXRCeXRlcyhibG9ja0xlbik7CiAgICAgICAgYnVmZmVyLnNldChibG9jaywgYnVmZmVyTGVuZ3RoKTsKICAgICAgICBpZiAoYmxvY2subGVuZ3RoIDwgYmxvY2tMZW4pIHsKICAgICAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IGxpdENvZGVUYWJsZTsKICAgIGxldCBkaXN0Q29kZVRhYmxlOwogICAgaWYgKGhkciA9PT0gMSkgewogICAgICBsaXRDb2RlVGFibGUgPSBmaXhlZExpdENvZGVUYWI7CiAgICAgIGRpc3RDb2RlVGFibGUgPSBmaXhlZERpc3RDb2RlVGFiOwogICAgfSBlbHNlIGlmIChoZHIgPT09IDIpIHsKICAgICAgY29uc3QgbnVtTGl0Q29kZXMgPSB0aGlzLmdldEJpdHMoNSkgKyAyNTc7CiAgICAgIGNvbnN0IG51bURpc3RDb2RlcyA9IHRoaXMuZ2V0Qml0cyg1KSArIDE7CiAgICAgIGNvbnN0IG51bUNvZGVMZW5Db2RlcyA9IHRoaXMuZ2V0Qml0cyg0KSArIDQ7CiAgICAgIGNvbnN0IGNvZGVMZW5Db2RlTGVuZ3RocyA9IG5ldyBVaW50OEFycmF5KGNvZGVMZW5Db2RlTWFwLmxlbmd0aCk7CiAgICAgIGxldCBpOwogICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtQ29kZUxlbkNvZGVzOyArK2kpIHsKICAgICAgICBjb2RlTGVuQ29kZUxlbmd0aHNbY29kZUxlbkNvZGVNYXBbaV1dID0gdGhpcy5nZXRCaXRzKDMpOwogICAgICB9CiAgICAgIGNvbnN0IGNvZGVMZW5Db2RlVGFiID0gdGhpcy5nZW5lcmF0ZUh1ZmZtYW5UYWJsZShjb2RlTGVuQ29kZUxlbmd0aHMpOwogICAgICBsZW4gPSAwOwogICAgICBpID0gMDsKICAgICAgY29uc3QgY29kZXMgPSBudW1MaXRDb2RlcyArIG51bURpc3RDb2RlczsKICAgICAgY29uc3QgY29kZUxlbmd0aHMgPSBuZXcgVWludDhBcnJheShjb2Rlcyk7CiAgICAgIGxldCBiaXRzTGVuZ3RoLCBiaXRzT2Zmc2V0LCB3aGF0OwogICAgICB3aGlsZSAoaSA8IGNvZGVzKSB7CiAgICAgICAgY29uc3QgY29kZSA9IHRoaXMuZ2V0Q29kZShjb2RlTGVuQ29kZVRhYik7CiAgICAgICAgaWYgKGNvZGUgPT09IDE2KSB7CiAgICAgICAgICBiaXRzTGVuZ3RoID0gMjsKICAgICAgICAgIGJpdHNPZmZzZXQgPSAzOwogICAgICAgICAgd2hhdCA9IGxlbjsKICAgICAgICB9IGVsc2UgaWYgKGNvZGUgPT09IDE3KSB7CiAgICAgICAgICBiaXRzTGVuZ3RoID0gMzsKICAgICAgICAgIGJpdHNPZmZzZXQgPSAzOwogICAgICAgICAgd2hhdCA9IGxlbiA9IDA7CiAgICAgICAgfSBlbHNlIGlmIChjb2RlID09PSAxOCkgewogICAgICAgICAgYml0c0xlbmd0aCA9IDc7CiAgICAgICAgICBiaXRzT2Zmc2V0ID0gMTE7CiAgICAgICAgICB3aGF0ID0gbGVuID0gMDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29kZUxlbmd0aHNbaSsrXSA9IGxlbiA9IGNvZGU7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgbGV0IHJlcGVhdExlbmd0aCA9IHRoaXMuZ2V0Qml0cyhiaXRzTGVuZ3RoKSArIGJpdHNPZmZzZXQ7CiAgICAgICAgd2hpbGUgKHJlcGVhdExlbmd0aC0tID4gMCkgewogICAgICAgICAgY29kZUxlbmd0aHNbaSsrXSA9IHdoYXQ7CiAgICAgICAgfQogICAgICB9CiAgICAgIGxpdENvZGVUYWJsZSA9IHRoaXMuZ2VuZXJhdGVIdWZmbWFuVGFibGUoY29kZUxlbmd0aHMuc3ViYXJyYXkoMCwgbnVtTGl0Q29kZXMpKTsKICAgICAgZGlzdENvZGVUYWJsZSA9IHRoaXMuZ2VuZXJhdGVIdWZmbWFuVGFibGUoY29kZUxlbmd0aHMuc3ViYXJyYXkobnVtTGl0Q29kZXMsIGNvZGVzKSk7CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gYmxvY2sgdHlwZSBpbiBmbGF0ZSBzdHJlYW0iKTsKICAgIH0KICAgIGJ1ZmZlciA9IHRoaXMuYnVmZmVyOwogICAgbGV0IGxpbWl0ID0gYnVmZmVyID8gYnVmZmVyLmxlbmd0aCA6IDA7CiAgICBsZXQgcG9zID0gdGhpcy5idWZmZXJMZW5ndGg7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBsZXQgY29kZTEgPSB0aGlzLmdldENvZGUobGl0Q29kZVRhYmxlKTsKICAgICAgaWYgKGNvZGUxIDwgMjU2KSB7CiAgICAgICAgaWYgKHBvcyArIDEgPj0gbGltaXQpIHsKICAgICAgICAgIGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKHBvcyArIDEpOwogICAgICAgICAgbGltaXQgPSBidWZmZXIubGVuZ3RoOwogICAgICAgIH0KICAgICAgICBidWZmZXJbcG9zKytdID0gY29kZTE7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGNvZGUxID09PSAyNTYpIHsKICAgICAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IHBvczsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29kZTEgLT0gMjU3OwogICAgICBjb2RlMSA9IGxlbmd0aERlY29kZVtjb2RlMV07CiAgICAgIGxldCBjb2RlMiA9IGNvZGUxID4+IDE2OwogICAgICBpZiAoY29kZTIgPiAwKSB7CiAgICAgICAgY29kZTIgPSB0aGlzLmdldEJpdHMoY29kZTIpOwogICAgICB9CiAgICAgIGxlbiA9IChjb2RlMSAmIDB4ZmZmZikgKyBjb2RlMjsKICAgICAgY29kZTEgPSB0aGlzLmdldENvZGUoZGlzdENvZGVUYWJsZSk7CiAgICAgIGNvZGUxID0gZGlzdERlY29kZVtjb2RlMV07CiAgICAgIGNvZGUyID0gY29kZTEgPj4gMTY7CiAgICAgIGlmIChjb2RlMiA+IDApIHsKICAgICAgICBjb2RlMiA9IHRoaXMuZ2V0Qml0cyhjb2RlMik7CiAgICAgIH0KICAgICAgY29uc3QgZGlzdCA9IChjb2RlMSAmIDB4ZmZmZikgKyBjb2RlMjsKICAgICAgaWYgKHBvcyArIGxlbiA+PSBsaW1pdCkgewogICAgICAgIGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKHBvcyArIGxlbik7CiAgICAgICAgbGltaXQgPSBidWZmZXIubGVuZ3RoOwogICAgICB9CiAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgbGVuOyArK2ssICsrcG9zKSB7CiAgICAgICAgYnVmZmVyW3Bvc10gPSBidWZmZXJbcG9zIC0gZGlzdF07CiAgICAgIH0KICAgIH0KICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2FyaXRobWV0aWNfZGVjb2Rlci5qcwpjb25zdCBRZVRhYmxlID0gW3sKICBxZTogMHg1NjAxLAogIG5tcHM6IDEsCiAgbmxwczogMSwKICBzd2l0Y2hGbGFnOiAxCn0sIHsKICBxZTogMHgzNDAxLAogIG5tcHM6IDIsCiAgbmxwczogNiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxODAxLAogIG5tcHM6IDMsCiAgbmxwczogOSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwYWMxLAogIG5tcHM6IDQsCiAgbmxwczogMTIsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDUyMSwKICBubXBzOiA1LAogIG5scHM6IDI5LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAyMjEsCiAgbm1wczogMzgsCiAgbmxwczogMzMsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4NTYwMSwKICBubXBzOiA3LAogIG5scHM6IDYsCiAgc3dpdGNoRmxhZzogMQp9LCB7CiAgcWU6IDB4NTQwMSwKICBubXBzOiA4LAogIG5scHM6IDE0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDQ4MDEsCiAgbm1wczogOSwKICBubHBzOiAxNCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgzODAxLAogIG5tcHM6IDEwLAogIG5scHM6IDE0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDMwMDEsCiAgbm1wczogMTEsCiAgbmxwczogMTcsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MjQwMSwKICBubXBzOiAxMiwKICBubHBzOiAxOCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxYzAxLAogIG5tcHM6IDEzLAogIG5scHM6IDIwLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDE2MDEsCiAgbm1wczogMjksCiAgbmxwczogMjEsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4NTYwMSwKICBubXBzOiAxNSwKICBubHBzOiAxNCwKICBzd2l0Y2hGbGFnOiAxCn0sIHsKICBxZTogMHg1NDAxLAogIG5tcHM6IDE2LAogIG5scHM6IDE0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDUxMDEsCiAgbm1wczogMTcsCiAgbmxwczogMTUsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4NDgwMSwKICBubXBzOiAxOCwKICBubHBzOiAxNiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgzODAxLAogIG5tcHM6IDE5LAogIG5scHM6IDE3LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDM0MDEsCiAgbm1wczogMjAsCiAgbmxwczogMTgsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MzAwMSwKICBubXBzOiAyMSwKICBubHBzOiAxOSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgyODAxLAogIG5tcHM6IDIyLAogIG5scHM6IDE5LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDI0MDEsCiAgbm1wczogMjMsCiAgbmxwczogMjAsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MjIwMSwKICBubXBzOiAyNCwKICBubHBzOiAyMSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxYzAxLAogIG5tcHM6IDI1LAogIG5scHM6IDIyLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDE4MDEsCiAgbm1wczogMjYsCiAgbmxwczogMjMsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MTYwMSwKICBubXBzOiAyNywKICBubHBzOiAyNCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxNDAxLAogIG5tcHM6IDI4LAogIG5scHM6IDI1LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDEyMDEsCiAgbm1wczogMjksCiAgbmxwczogMjYsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MTEwMSwKICBubXBzOiAzMCwKICBubHBzOiAyNywKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwYWMxLAogIG5tcHM6IDMxLAogIG5scHM6IDI4LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDA5YzEsCiAgbm1wczogMzIsCiAgbmxwczogMjksCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDhhMSwKICBubXBzOiAzMywKICBubHBzOiAzMCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwNTIxLAogIG5tcHM6IDM0LAogIG5scHM6IDMxLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDA0NDEsCiAgbm1wczogMzUsCiAgbmxwczogMzIsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDJhMSwKICBubXBzOiAzNiwKICBubHBzOiAzMywKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMjIxLAogIG5tcHM6IDM3LAogIG5scHM6IDM0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAxNDEsCiAgbm1wczogMzgsCiAgbmxwczogMzUsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDExMSwKICBubXBzOiAzOSwKICBubHBzOiAzNiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMDg1LAogIG5tcHM6IDQwLAogIG5scHM6IDM3LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAwNDksCiAgbm1wczogNDEsCiAgbmxwczogMzgsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDAyNSwKICBubXBzOiA0MiwKICBubHBzOiAzOSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMDE1LAogIG5tcHM6IDQzLAogIG5scHM6IDQwLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAwMDksCiAgbm1wczogNDQsCiAgbmxwczogNDEsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDAwNSwKICBubXBzOiA0NSwKICBubHBzOiA0MiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMDAxLAogIG5tcHM6IDQ1LAogIG5scHM6IDQzLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDU2MDEsCiAgbm1wczogNDYsCiAgbmxwczogNDYsCiAgc3dpdGNoRmxhZzogMAp9XTsKY2xhc3MgQXJpdGhtZXRpY0RlY29kZXIgewogIGNvbnN0cnVjdG9yKGRhdGEsIHN0YXJ0LCBlbmQpIHsKICAgIHRoaXMuZGF0YSA9IGRhdGE7CiAgICB0aGlzLmJwID0gc3RhcnQ7CiAgICB0aGlzLmRhdGFFbmQgPSBlbmQ7CiAgICB0aGlzLmNoaWdoID0gZGF0YVtzdGFydF07CiAgICB0aGlzLmNsb3cgPSAwOwogICAgdGhpcy5ieXRlSW4oKTsKICAgIHRoaXMuY2hpZ2ggPSB0aGlzLmNoaWdoIDw8IDcgJiAweGZmZmYgfCB0aGlzLmNsb3cgPj4gOSAmIDB4N2Y7CiAgICB0aGlzLmNsb3cgPSB0aGlzLmNsb3cgPDwgNyAmIDB4ZmZmZjsKICAgIHRoaXMuY3QgLT0gNzsKICAgIHRoaXMuYSA9IDB4ODAwMDsKICB9CiAgYnl0ZUluKCkgewogICAgY29uc3QgZGF0YSA9IHRoaXMuZGF0YTsKICAgIGxldCBicCA9IHRoaXMuYnA7CiAgICBpZiAoZGF0YVticF0gPT09IDB4ZmYpIHsKICAgICAgaWYgKGRhdGFbYnAgKyAxXSA+IDB4OGYpIHsKICAgICAgICB0aGlzLmNsb3cgKz0gMHhmZjAwOwogICAgICAgIHRoaXMuY3QgPSA4OwogICAgICB9IGVsc2UgewogICAgICAgIGJwKys7CiAgICAgICAgdGhpcy5jbG93ICs9IGRhdGFbYnBdIDw8IDk7CiAgICAgICAgdGhpcy5jdCA9IDc7CiAgICAgICAgdGhpcy5icCA9IGJwOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBicCsrOwogICAgICB0aGlzLmNsb3cgKz0gYnAgPCB0aGlzLmRhdGFFbmQgPyBkYXRhW2JwXSA8PCA4IDogMHhmZjAwOwogICAgICB0aGlzLmN0ID0gODsKICAgICAgdGhpcy5icCA9IGJwOwogICAgfQogICAgaWYgKHRoaXMuY2xvdyA+IDB4ZmZmZikgewogICAgICB0aGlzLmNoaWdoICs9IHRoaXMuY2xvdyA+PiAxNjsKICAgICAgdGhpcy5jbG93ICY9IDB4ZmZmZjsKICAgIH0KICB9CiAgcmVhZEJpdChjb250ZXh0cywgcG9zKSB7CiAgICBsZXQgY3hfaW5kZXggPSBjb250ZXh0c1twb3NdID4+IDEsCiAgICAgIGN4X21wcyA9IGNvbnRleHRzW3Bvc10gJiAxOwogICAgY29uc3QgcWVUYWJsZUljeCA9IFFlVGFibGVbY3hfaW5kZXhdOwogICAgY29uc3QgcWVJY3ggPSBxZVRhYmxlSWN4LnFlOwogICAgbGV0IGQ7CiAgICBsZXQgYSA9IHRoaXMuYSAtIHFlSWN4OwogICAgaWYgKHRoaXMuY2hpZ2ggPCBxZUljeCkgewogICAgICBpZiAoYSA8IHFlSWN4KSB7CiAgICAgICAgYSA9IHFlSWN4OwogICAgICAgIGQgPSBjeF9tcHM7CiAgICAgICAgY3hfaW5kZXggPSBxZVRhYmxlSWN4Lm5tcHM7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYSA9IHFlSWN4OwogICAgICAgIGQgPSAxIF4gY3hfbXBzOwogICAgICAgIGlmIChxZVRhYmxlSWN4LnN3aXRjaEZsYWcgPT09IDEpIHsKICAgICAgICAgIGN4X21wcyA9IGQ7CiAgICAgICAgfQogICAgICAgIGN4X2luZGV4ID0gcWVUYWJsZUljeC5ubHBzOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmNoaWdoIC09IHFlSWN4OwogICAgICBpZiAoKGEgJiAweDgwMDApICE9PSAwKSB7CiAgICAgICAgdGhpcy5hID0gYTsKICAgICAgICByZXR1cm4gY3hfbXBzOwogICAgICB9CiAgICAgIGlmIChhIDwgcWVJY3gpIHsKICAgICAgICBkID0gMSBeIGN4X21wczsKICAgICAgICBpZiAocWVUYWJsZUljeC5zd2l0Y2hGbGFnID09PSAxKSB7CiAgICAgICAgICBjeF9tcHMgPSBkOwogICAgICAgIH0KICAgICAgICBjeF9pbmRleCA9IHFlVGFibGVJY3gubmxwczsKICAgICAgfSBlbHNlIHsKICAgICAgICBkID0gY3hfbXBzOwogICAgICAgIGN4X2luZGV4ID0gcWVUYWJsZUljeC5ubXBzOwogICAgICB9CiAgICB9CiAgICBkbyB7CiAgICAgIGlmICh0aGlzLmN0ID09PSAwKSB7CiAgICAgICAgdGhpcy5ieXRlSW4oKTsKICAgICAgfQogICAgICBhIDw8PSAxOwogICAgICB0aGlzLmNoaWdoID0gdGhpcy5jaGlnaCA8PCAxICYgMHhmZmZmIHwgdGhpcy5jbG93ID4+IDE1ICYgMTsKICAgICAgdGhpcy5jbG93ID0gdGhpcy5jbG93IDw8IDEgJiAweGZmZmY7CiAgICAgIHRoaXMuY3QtLTsKICAgIH0gd2hpbGUgKChhICYgMHg4MDAwKSA9PT0gMCk7CiAgICB0aGlzLmEgPSBhOwogICAgY29udGV4dHNbcG9zXSA9IGN4X2luZGV4IDw8IDEgfCBjeF9tcHM7CiAgICByZXR1cm4gZDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2piaWcyLmpzCgoKCgpjbGFzcyBKYmlnMkVycm9yIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJKYmlnMkVycm9yIik7CiAgfQp9CmNsYXNzIENvbnRleHRDYWNoZSB7CiAgZ2V0Q29udGV4dHMoaWQpIHsKICAgIGlmIChpZCBpbiB0aGlzKSB7CiAgICAgIHJldHVybiB0aGlzW2lkXTsKICAgIH0KICAgIHJldHVybiB0aGlzW2lkXSA9IG5ldyBJbnQ4QXJyYXkoMSA8PCAxNik7CiAgfQp9CmNsYXNzIERlY29kaW5nQ29udGV4dCB7CiAgY29uc3RydWN0b3IoZGF0YSwgc3RhcnQsIGVuZCkgewogICAgdGhpcy5kYXRhID0gZGF0YTsKICAgIHRoaXMuc3RhcnQgPSBzdGFydDsKICAgIHRoaXMuZW5kID0gZW5kOwogIH0KICBnZXQgZGVjb2RlcigpIHsKICAgIGNvbnN0IGRlY29kZXIgPSBuZXcgQXJpdGhtZXRpY0RlY29kZXIodGhpcy5kYXRhLCB0aGlzLnN0YXJ0LCB0aGlzLmVuZCk7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJkZWNvZGVyIiwgZGVjb2Rlcik7CiAgfQogIGdldCBjb250ZXh0Q2FjaGUoKSB7CiAgICBjb25zdCBjYWNoZSA9IG5ldyBDb250ZXh0Q2FjaGUoKTsKICAgIHJldHVybiBzaGFkb3codGhpcywgImNvbnRleHRDYWNoZSIsIGNhY2hlKTsKICB9Cn0KZnVuY3Rpb24gZGVjb2RlSW50ZWdlcihjb250ZXh0Q2FjaGUsIHByb2NlZHVyZSwgZGVjb2RlcikgewogIGNvbnN0IGNvbnRleHRzID0gY29udGV4dENhY2hlLmdldENvbnRleHRzKHByb2NlZHVyZSk7CiAgbGV0IHByZXYgPSAxOwogIGZ1bmN0aW9uIHJlYWRCaXRzKGxlbmd0aCkgewogICAgbGV0IHYgPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBjb25zdCBiaXQgPSBkZWNvZGVyLnJlYWRCaXQoY29udGV4dHMsIHByZXYpOwogICAgICBwcmV2ID0gcHJldiA8IDI1NiA/IHByZXYgPDwgMSB8IGJpdCA6IChwcmV2IDw8IDEgfCBiaXQpICYgNTExIHwgMjU2OwogICAgICB2ID0gdiA8PCAxIHwgYml0OwogICAgfQogICAgcmV0dXJuIHYgPj4+IDA7CiAgfQogIGNvbnN0IHNpZ24gPSByZWFkQml0cygxKTsKICBjb25zdCB2YWx1ZSA9IHJlYWRCaXRzKDEpID8gcmVhZEJpdHMoMSkgPyByZWFkQml0cygxKSA/IHJlYWRCaXRzKDEpID8gcmVhZEJpdHMoMSkgPyByZWFkQml0cygzMikgKyA0NDM2IDogcmVhZEJpdHMoMTIpICsgMzQwIDogcmVhZEJpdHMoOCkgKyA4NCA6IHJlYWRCaXRzKDYpICsgMjAgOiByZWFkQml0cyg0KSArIDQgOiByZWFkQml0cygyKTsKICBsZXQgc2lnbmVkVmFsdWU7CiAgaWYgKHNpZ24gPT09IDApIHsKICAgIHNpZ25lZFZhbHVlID0gdmFsdWU7CiAgfSBlbHNlIGlmICh2YWx1ZSA+IDApIHsKICAgIHNpZ25lZFZhbHVlID0gLXZhbHVlOwogIH0KICBpZiAoc2lnbmVkVmFsdWUgPj0gTUlOX0lOVF8zMiAmJiBzaWduZWRWYWx1ZSA8PSBNQVhfSU5UXzMyKSB7CiAgICByZXR1cm4gc2lnbmVkVmFsdWU7CiAgfQogIHJldHVybiBudWxsOwp9CmZ1bmN0aW9uIGRlY29kZUlBSUQoY29udGV4dENhY2hlLCBkZWNvZGVyLCBjb2RlTGVuZ3RoKSB7CiAgY29uc3QgY29udGV4dHMgPSBjb250ZXh0Q2FjaGUuZ2V0Q29udGV4dHMoIklBSUQiKTsKICBsZXQgcHJldiA9IDE7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb2RlTGVuZ3RoOyBpKyspIHsKICAgIGNvbnN0IGJpdCA9IGRlY29kZXIucmVhZEJpdChjb250ZXh0cywgcHJldik7CiAgICBwcmV2ID0gcHJldiA8PCAxIHwgYml0OwogIH0KICBpZiAoY29kZUxlbmd0aCA8IDMxKSB7CiAgICByZXR1cm4gcHJldiAmICgxIDw8IGNvZGVMZW5ndGgpIC0gMTsKICB9CiAgcmV0dXJuIHByZXYgJiAweDdmZmZmZmZmOwp9CmNvbnN0IFNlZ21lbnRUeXBlcyA9IFsiU3ltYm9sRGljdGlvbmFyeSIsIG51bGwsIG51bGwsIG51bGwsICJJbnRlcm1lZGlhdGVUZXh0UmVnaW9uIiwgbnVsbCwgIkltbWVkaWF0ZVRleHRSZWdpb24iLCAiSW1tZWRpYXRlTG9zc2xlc3NUZXh0UmVnaW9uIiwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgIlBhdHRlcm5EaWN0aW9uYXJ5IiwgbnVsbCwgbnVsbCwgbnVsbCwgIkludGVybWVkaWF0ZUhhbGZ0b25lUmVnaW9uIiwgbnVsbCwgIkltbWVkaWF0ZUhhbGZ0b25lUmVnaW9uIiwgIkltbWVkaWF0ZUxvc3NsZXNzSGFsZnRvbmVSZWdpb24iLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCAiSW50ZXJtZWRpYXRlR2VuZXJpY1JlZ2lvbiIsIG51bGwsICJJbW1lZGlhdGVHZW5lcmljUmVnaW9uIiwgIkltbWVkaWF0ZUxvc3NsZXNzR2VuZXJpY1JlZ2lvbiIsICJJbnRlcm1lZGlhdGVHZW5lcmljUmVmaW5lbWVudFJlZ2lvbiIsIG51bGwsICJJbW1lZGlhdGVHZW5lcmljUmVmaW5lbWVudFJlZ2lvbiIsICJJbW1lZGlhdGVMb3NzbGVzc0dlbmVyaWNSZWZpbmVtZW50UmVnaW9uIiwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgIlBhZ2VJbmZvcm1hdGlvbiIsICJFbmRPZlBhZ2UiLCAiRW5kT2ZTdHJpcGUiLCAiRW5kT2ZGaWxlIiwgIlByb2ZpbGVzIiwgIlRhYmxlcyIsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsICJFeHRlbnNpb24iXTsKY29uc3QgQ29kaW5nVGVtcGxhdGVzID0gW1t7CiAgeDogLTEsCiAgeTogLTIKfSwgewogIHg6IDAsCiAgeTogLTIKfSwgewogIHg6IDEsCiAgeTogLTIKfSwgewogIHg6IC0yLAogIHk6IC0xCn0sIHsKICB4OiAtMSwKICB5OiAtMQp9LCB7CiAgeDogMCwKICB5OiAtMQp9LCB7CiAgeDogMSwKICB5OiAtMQp9LCB7CiAgeDogMiwKICB5OiAtMQp9LCB7CiAgeDogLTQsCiAgeTogMAp9LCB7CiAgeDogLTMsCiAgeTogMAp9LCB7CiAgeDogLTIsCiAgeTogMAp9LCB7CiAgeDogLTEsCiAgeTogMAp9XSwgW3sKICB4OiAtMSwKICB5OiAtMgp9LCB7CiAgeDogMCwKICB5OiAtMgp9LCB7CiAgeDogMSwKICB5OiAtMgp9LCB7CiAgeDogMiwKICB5OiAtMgp9LCB7CiAgeDogLTIsCiAgeTogLTEKfSwgewogIHg6IC0xLAogIHk6IC0xCn0sIHsKICB4OiAwLAogIHk6IC0xCn0sIHsKICB4OiAxLAogIHk6IC0xCn0sIHsKICB4OiAyLAogIHk6IC0xCn0sIHsKICB4OiAtMywKICB5OiAwCn0sIHsKICB4OiAtMiwKICB5OiAwCn0sIHsKICB4OiAtMSwKICB5OiAwCn1dLCBbewogIHg6IC0xLAogIHk6IC0yCn0sIHsKICB4OiAwLAogIHk6IC0yCn0sIHsKICB4OiAxLAogIHk6IC0yCn0sIHsKICB4OiAtMiwKICB5OiAtMQp9LCB7CiAgeDogLTEsCiAgeTogLTEKfSwgewogIHg6IDAsCiAgeTogLTEKfSwgewogIHg6IDEsCiAgeTogLTEKfSwgewogIHg6IC0yLAogIHk6IDAKfSwgewogIHg6IC0xLAogIHk6IDAKfV0sIFt7CiAgeDogLTMsCiAgeTogLTEKfSwgewogIHg6IC0yLAogIHk6IC0xCn0sIHsKICB4OiAtMSwKICB5OiAtMQp9LCB7CiAgeDogMCwKICB5OiAtMQp9LCB7CiAgeDogMSwKICB5OiAtMQp9LCB7CiAgeDogLTQsCiAgeTogMAp9LCB7CiAgeDogLTMsCiAgeTogMAp9LCB7CiAgeDogLTIsCiAgeTogMAp9LCB7CiAgeDogLTEsCiAgeTogMAp9XV07CmNvbnN0IFJlZmluZW1lbnRUZW1wbGF0ZXMgPSBbewogIGNvZGluZzogW3sKICAgIHg6IDAsCiAgICB5OiAtMQogIH0sIHsKICAgIHg6IDEsCiAgICB5OiAtMQogIH0sIHsKICAgIHg6IC0xLAogICAgeTogMAogIH1dLAogIHJlZmVyZW5jZTogW3sKICAgIHg6IDAsCiAgICB5OiAtMQogIH0sIHsKICAgIHg6IDEsCiAgICB5OiAtMQogIH0sIHsKICAgIHg6IC0xLAogICAgeTogMAogIH0sIHsKICAgIHg6IDAsCiAgICB5OiAwCiAgfSwgewogICAgeDogMSwKICAgIHk6IDAKICB9LCB7CiAgICB4OiAtMSwKICAgIHk6IDEKICB9LCB7CiAgICB4OiAwLAogICAgeTogMQogIH0sIHsKICAgIHg6IDEsCiAgICB5OiAxCiAgfV0KfSwgewogIGNvZGluZzogW3sKICAgIHg6IC0xLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAwLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAxLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAtMSwKICAgIHk6IDAKICB9XSwKICByZWZlcmVuY2U6IFt7CiAgICB4OiAwLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAtMSwKICAgIHk6IDAKICB9LCB7CiAgICB4OiAwLAogICAgeTogMAogIH0sIHsKICAgIHg6IDEsCiAgICB5OiAwCiAgfSwgewogICAgeDogMCwKICAgIHk6IDEKICB9LCB7CiAgICB4OiAxLAogICAgeTogMQogIH1dCn1dOwpjb25zdCBSZXVzZWRDb250ZXh0cyA9IFsweDliMjUsIDB4MDc5NSwgMHgwMGU1LCAweDAxOTVdOwpjb25zdCBSZWZpbmVtZW50UmV1c2VkQ29udGV4dHMgPSBbMHgwMDIwLCAweDAwMDhdOwpmdW5jdGlvbiBkZWNvZGVCaXRtYXBUZW1wbGF0ZTAod2lkdGgsIGhlaWdodCwgZGVjb2RpbmdDb250ZXh0KSB7CiAgY29uc3QgZGVjb2RlciA9IGRlY29kaW5nQ29udGV4dC5kZWNvZGVyOwogIGNvbnN0IGNvbnRleHRzID0gZGVjb2RpbmdDb250ZXh0LmNvbnRleHRDYWNoZS5nZXRDb250ZXh0cygiR0IiKTsKICBjb25zdCBiaXRtYXAgPSBbXTsKICBsZXQgY29udGV4dExhYmVsLCBpLCBqLCBwaXhlbCwgcm93LCByb3cxLCByb3cyOwogIGNvbnN0IE9MRF9QSVhFTF9NQVNLID0gMHg3YmY3OwogIGZvciAoaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykgewogICAgcm93ID0gYml0bWFwW2ldID0gbmV3IFVpbnQ4QXJyYXkod2lkdGgpOwogICAgcm93MSA9IGkgPCAxID8gcm93IDogYml0bWFwW2kgLSAxXTsKICAgIHJvdzIgPSBpIDwgMiA/IHJvdyA6IGJpdG1hcFtpIC0gMl07CiAgICBjb250ZXh0TGFiZWwgPSByb3cyWzBdIDw8IDEzIHwgcm93MlsxXSA8PCAxMiB8IHJvdzJbMl0gPDwgMTEgfCByb3cxWzBdIDw8IDcgfCByb3cxWzFdIDw8IDYgfCByb3cxWzJdIDw8IDUgfCByb3cxWzNdIDw8IDQ7CiAgICBmb3IgKGogPSAwOyBqIDwgd2lkdGg7IGorKykgewogICAgICByb3dbal0gPSBwaXhlbCA9IGRlY29kZXIucmVhZEJpdChjb250ZXh0cywgY29udGV4dExhYmVsKTsKICAgICAgY29udGV4dExhYmVsID0gKGNvbnRleHRMYWJlbCAmIE9MRF9QSVhFTF9NQVNLKSA8PCAxIHwgKGogKyAzIDwgd2lkdGggPyByb3cyW2ogKyAzXSA8PCAxMSA6IDApIHwgKGogKyA0IDwgd2lkdGggPyByb3cxW2ogKyA0XSA8PCA0IDogMCkgfCBwaXhlbDsKICAgIH0KICB9CiAgcmV0dXJuIGJpdG1hcDsKfQpmdW5jdGlvbiBkZWNvZGVCaXRtYXAobW1yLCB3aWR0aCwgaGVpZ2h0LCB0ZW1wbGF0ZUluZGV4LCBwcmVkaWN0aW9uLCBza2lwLCBhdCwgZGVjb2RpbmdDb250ZXh0KSB7CiAgaWYgKG1tcikgewogICAgY29uc3QgaW5wdXQgPSBuZXcgUmVhZGVyKGRlY29kaW5nQ29udGV4dC5kYXRhLCBkZWNvZGluZ0NvbnRleHQuc3RhcnQsIGRlY29kaW5nQ29udGV4dC5lbmQpOwogICAgcmV0dXJuIGRlY29kZU1NUkJpdG1hcChpbnB1dCwgd2lkdGgsIGhlaWdodCwgZmFsc2UpOwogIH0KICBpZiAodGVtcGxhdGVJbmRleCA9PT0gMCAmJiAhc2tpcCAmJiAhcHJlZGljdGlvbiAmJiBhdC5sZW5ndGggPT09IDQgJiYgYXRbMF0ueCA9PT0gMyAmJiBhdFswXS55ID09PSAtMSAmJiBhdFsxXS54ID09PSAtMyAmJiBhdFsxXS55ID09PSAtMSAmJiBhdFsyXS54ID09PSAyICYmIGF0WzJdLnkgPT09IC0yICYmIGF0WzNdLnggPT09IC0yICYmIGF0WzNdLnkgPT09IC0yKSB7CiAgICByZXR1cm4gZGVjb2RlQml0bWFwVGVtcGxhdGUwKHdpZHRoLCBoZWlnaHQsIGRlY29kaW5nQ29udGV4dCk7CiAgfQogIGNvbnN0IHVzZXNraXAgPSAhIXNraXA7CiAgY29uc3QgdGVtcGxhdGUgPSBDb2RpbmdUZW1wbGF0ZXNbdGVtcGxhdGVJbmRleF0uY29uY2F0KGF0KTsKICB0ZW1wbGF0ZS5zb3J0KChhLCBiKSA9PiBhLnkgLSBiLnkgfHwgYS54IC0gYi54KTsKICBjb25zdCB0ZW1wbGF0ZUxlbmd0aCA9IHRlbXBsYXRlLmxlbmd0aDsKICBjb25zdCB0ZW1wbGF0ZVggPSBuZXcgSW50OEFycmF5KHRlbXBsYXRlTGVuZ3RoKTsKICBjb25zdCB0ZW1wbGF0ZVkgPSBuZXcgSW50OEFycmF5KHRlbXBsYXRlTGVuZ3RoKTsKICBjb25zdCBjaGFuZ2luZ1RlbXBsYXRlRW50cmllcyA9IFtdOwogIGxldCByZXVzZU1hc2sgPSAwLAogICAgbWluWCA9IDAsCiAgICBtYXhYID0gMCwKICAgIG1pblkgPSAwOwogIGxldCBjLCBrOwogIGZvciAoayA9IDA7IGsgPCB0ZW1wbGF0ZUxlbmd0aDsgaysrKSB7CiAgICB0ZW1wbGF0ZVhba10gPSB0ZW1wbGF0ZVtrXS54OwogICAgdGVtcGxhdGVZW2tdID0gdGVtcGxhdGVba10ueTsKICAgIG1pblggPSBNYXRoLm1pbihtaW5YLCB0ZW1wbGF0ZVtrXS54KTsKICAgIG1heFggPSBNYXRoLm1heChtYXhYLCB0ZW1wbGF0ZVtrXS54KTsKICAgIG1pblkgPSBNYXRoLm1pbihtaW5ZLCB0ZW1wbGF0ZVtrXS55KTsKICAgIGlmIChrIDwgdGVtcGxhdGVMZW5ndGggLSAxICYmIHRlbXBsYXRlW2tdLnkgPT09IHRlbXBsYXRlW2sgKyAxXS55ICYmIHRlbXBsYXRlW2tdLnggPT09IHRlbXBsYXRlW2sgKyAxXS54IC0gMSkgewogICAgICByZXVzZU1hc2sgfD0gMSA8PCB0ZW1wbGF0ZUxlbmd0aCAtIDEgLSBrOwogICAgfSBlbHNlIHsKICAgICAgY2hhbmdpbmdUZW1wbGF0ZUVudHJpZXMucHVzaChrKTsKICAgIH0KICB9CiAgY29uc3QgY2hhbmdpbmdFbnRyaWVzTGVuZ3RoID0gY2hhbmdpbmdUZW1wbGF0ZUVudHJpZXMubGVuZ3RoOwogIGNvbnN0IGNoYW5naW5nVGVtcGxhdGVYID0gbmV3IEludDhBcnJheShjaGFuZ2luZ0VudHJpZXNMZW5ndGgpOwogIGNvbnN0IGNoYW5naW5nVGVtcGxhdGVZID0gbmV3IEludDhBcnJheShjaGFuZ2luZ0VudHJpZXNMZW5ndGgpOwogIGNvbnN0IGNoYW5naW5nVGVtcGxhdGVCaXQgPSBuZXcgVWludDE2QXJyYXkoY2hhbmdpbmdFbnRyaWVzTGVuZ3RoKTsKICBmb3IgKGMgPSAwOyBjIDwgY2hhbmdpbmdFbnRyaWVzTGVuZ3RoOyBjKyspIHsKICAgIGsgPSBjaGFuZ2luZ1RlbXBsYXRlRW50cmllc1tjXTsKICAgIGNoYW5naW5nVGVtcGxhdGVYW2NdID0gdGVtcGxhdGVba10ueDsKICAgIGNoYW5naW5nVGVtcGxhdGVZW2NdID0gdGVtcGxhdGVba10ueTsKICAgIGNoYW5naW5nVGVtcGxhdGVCaXRbY10gPSAxIDw8IHRlbXBsYXRlTGVuZ3RoIC0gMSAtIGs7CiAgfQogIGNvbnN0IHNiYl9sZWZ0ID0gLW1pblg7CiAgY29uc3Qgc2JiX3RvcCA9IC1taW5ZOwogIGNvbnN0IHNiYl9yaWdodCA9IHdpZHRoIC0gbWF4WDsKICBjb25zdCBwc2V1ZG9QaXhlbENvbnRleHQgPSBSZXVzZWRDb250ZXh0c1t0ZW1wbGF0ZUluZGV4XTsKICBsZXQgcm93ID0gbmV3IFVpbnQ4QXJyYXkod2lkdGgpOwogIGNvbnN0IGJpdG1hcCA9IFtdOwogIGNvbnN0IGRlY29kZXIgPSBkZWNvZGluZ0NvbnRleHQuZGVjb2RlcjsKICBjb25zdCBjb250ZXh0cyA9IGRlY29kaW5nQ29udGV4dC5jb250ZXh0Q2FjaGUuZ2V0Q29udGV4dHMoIkdCIik7CiAgbGV0IGx0cCA9IDAsCiAgICBqLAogICAgaTAsCiAgICBqMCwKICAgIGNvbnRleHRMYWJlbCA9IDAsCiAgICBiaXQsCiAgICBzaGlmdDsKICBmb3IgKGxldCBpID0gMDsgaSA8IGhlaWdodDsgaSsrKSB7CiAgICBpZiAocHJlZGljdGlvbikgewogICAgICBjb25zdCBzbHRwID0gZGVjb2Rlci5yZWFkQml0KGNvbnRleHRzLCBwc2V1ZG9QaXhlbENvbnRleHQpOwogICAgICBsdHAgXj0gc2x0cDsKICAgICAgaWYgKGx0cCkgewogICAgICAgIGJpdG1hcC5wdXNoKHJvdyk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgIH0KICAgIHJvdyA9IG5ldyBVaW50OEFycmF5KHJvdyk7CiAgICBiaXRtYXAucHVzaChyb3cpOwogICAgZm9yIChqID0gMDsgaiA8IHdpZHRoOyBqKyspIHsKICAgICAgaWYgKHVzZXNraXAgJiYgc2tpcFtpXVtqXSkgewogICAgICAgIHJvd1tqXSA9IDA7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGogPj0gc2JiX2xlZnQgJiYgaiA8IHNiYl9yaWdodCAmJiBpID49IHNiYl90b3ApIHsKICAgICAgICBjb250ZXh0TGFiZWwgPSBjb250ZXh0TGFiZWwgPDwgMSAmIHJldXNlTWFzazsKICAgICAgICBmb3IgKGsgPSAwOyBrIDwgY2hhbmdpbmdFbnRyaWVzTGVuZ3RoOyBrKyspIHsKICAgICAgICAgIGkwID0gaSArIGNoYW5naW5nVGVtcGxhdGVZW2tdOwogICAgICAgICAgajAgPSBqICsgY2hhbmdpbmdUZW1wbGF0ZVhba107CiAgICAgICAgICBiaXQgPSBiaXRtYXBbaTBdW2owXTsKICAgICAgICAgIGlmIChiaXQpIHsKICAgICAgICAgICAgYml0ID0gY2hhbmdpbmdUZW1wbGF0ZUJpdFtrXTsKICAgICAgICAgICAgY29udGV4dExhYmVsIHw9IGJpdDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29udGV4dExhYmVsID0gMDsKICAgICAgICBzaGlmdCA9IHRlbXBsYXRlTGVuZ3RoIC0gMTsKICAgICAgICBmb3IgKGsgPSAwOyBrIDwgdGVtcGxhdGVMZW5ndGg7IGsrKywgc2hpZnQtLSkgewogICAgICAgICAgajAgPSBqICsgdGVtcGxhdGVYW2tdOwogICAgICAgICAgaWYgKGowID49IDAgJiYgajAgPCB3aWR0aCkgewogICAgICAgICAgICBpMCA9IGkgKyB0ZW1wbGF0ZVlba107CiAgICAgICAgICAgIGlmIChpMCA+PSAwKSB7CiAgICAgICAgICAgICAgYml0ID0gYml0bWFwW2kwXVtqMF07CiAgICAgICAgICAgICAgaWYgKGJpdCkgewogICAgICAgICAgICAgICAgY29udGV4dExhYmVsIHw9IGJpdCA8PCBzaGlmdDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgcGl4ZWwgPSBkZWNvZGVyLnJlYWRCaXQoY29udGV4dHMsIGNvbnRleHRMYWJlbCk7CiAgICAgIHJvd1tqXSA9IHBpeGVsOwogICAgfQogIH0KICByZXR1cm4gYml0bWFwOwp9CmZ1bmN0aW9uIGRlY29kZVJlZmluZW1lbnQod2lkdGgsIGhlaWdodCwgdGVtcGxhdGVJbmRleCwgcmVmZXJlbmNlQml0bWFwLCBvZmZzZXRYLCBvZmZzZXRZLCBwcmVkaWN0aW9uLCBhdCwgZGVjb2RpbmdDb250ZXh0KSB7CiAgbGV0IGNvZGluZ1RlbXBsYXRlID0gUmVmaW5lbWVudFRlbXBsYXRlc1t0ZW1wbGF0ZUluZGV4XS5jb2Rpbmc7CiAgaWYgKHRlbXBsYXRlSW5kZXggPT09IDApIHsKICAgIGNvZGluZ1RlbXBsYXRlID0gY29kaW5nVGVtcGxhdGUuY29uY2F0KFthdFswXV0pOwogIH0KICBjb25zdCBjb2RpbmdUZW1wbGF0ZUxlbmd0aCA9IGNvZGluZ1RlbXBsYXRlLmxlbmd0aDsKICBjb25zdCBjb2RpbmdUZW1wbGF0ZVggPSBuZXcgSW50MzJBcnJheShjb2RpbmdUZW1wbGF0ZUxlbmd0aCk7CiAgY29uc3QgY29kaW5nVGVtcGxhdGVZID0gbmV3IEludDMyQXJyYXkoY29kaW5nVGVtcGxhdGVMZW5ndGgpOwogIGxldCBrOwogIGZvciAoayA9IDA7IGsgPCBjb2RpbmdUZW1wbGF0ZUxlbmd0aDsgaysrKSB7CiAgICBjb2RpbmdUZW1wbGF0ZVhba10gPSBjb2RpbmdUZW1wbGF0ZVtrXS54OwogICAgY29kaW5nVGVtcGxhdGVZW2tdID0gY29kaW5nVGVtcGxhdGVba10ueTsKICB9CiAgbGV0IHJlZmVyZW5jZVRlbXBsYXRlID0gUmVmaW5lbWVudFRlbXBsYXRlc1t0ZW1wbGF0ZUluZGV4XS5yZWZlcmVuY2U7CiAgaWYgKHRlbXBsYXRlSW5kZXggPT09IDApIHsKICAgIHJlZmVyZW5jZVRlbXBsYXRlID0gcmVmZXJlbmNlVGVtcGxhdGUuY29uY2F0KFthdFsxXV0pOwogIH0KICBjb25zdCByZWZlcmVuY2VUZW1wbGF0ZUxlbmd0aCA9IHJlZmVyZW5jZVRlbXBsYXRlLmxlbmd0aDsKICBjb25zdCByZWZlcmVuY2VUZW1wbGF0ZVggPSBuZXcgSW50MzJBcnJheShyZWZlcmVuY2VUZW1wbGF0ZUxlbmd0aCk7CiAgY29uc3QgcmVmZXJlbmNlVGVtcGxhdGVZID0gbmV3IEludDMyQXJyYXkocmVmZXJlbmNlVGVtcGxhdGVMZW5ndGgpOwogIGZvciAoayA9IDA7IGsgPCByZWZlcmVuY2VUZW1wbGF0ZUxlbmd0aDsgaysrKSB7CiAgICByZWZlcmVuY2VUZW1wbGF0ZVhba10gPSByZWZlcmVuY2VUZW1wbGF0ZVtrXS54OwogICAgcmVmZXJlbmNlVGVtcGxhdGVZW2tdID0gcmVmZXJlbmNlVGVtcGxhdGVba10ueTsKICB9CiAgY29uc3QgcmVmZXJlbmNlV2lkdGggPSByZWZlcmVuY2VCaXRtYXBbMF0ubGVuZ3RoOwogIGNvbnN0IHJlZmVyZW5jZUhlaWdodCA9IHJlZmVyZW5jZUJpdG1hcC5sZW5ndGg7CiAgY29uc3QgcHNldWRvUGl4ZWxDb250ZXh0ID0gUmVmaW5lbWVudFJldXNlZENvbnRleHRzW3RlbXBsYXRlSW5kZXhdOwogIGNvbnN0IGJpdG1hcCA9IFtdOwogIGNvbnN0IGRlY29kZXIgPSBkZWNvZGluZ0NvbnRleHQuZGVjb2RlcjsKICBjb25zdCBjb250ZXh0cyA9IGRlY29kaW5nQ29udGV4dC5jb250ZXh0Q2FjaGUuZ2V0Q29udGV4dHMoIkdSIik7CiAgbGV0IGx0cCA9IDA7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykgewogICAgaWYgKHByZWRpY3Rpb24pIHsKICAgICAgY29uc3Qgc2x0cCA9IGRlY29kZXIucmVhZEJpdChjb250ZXh0cywgcHNldWRvUGl4ZWxDb250ZXh0KTsKICAgICAgbHRwIF49IHNsdHA7CiAgICAgIGlmIChsdHApIHsKICAgICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigicHJlZGljdGlvbiBpcyBub3Qgc3VwcG9ydGVkIik7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHJvdyA9IG5ldyBVaW50OEFycmF5KHdpZHRoKTsKICAgIGJpdG1hcC5wdXNoKHJvdyk7CiAgICBmb3IgKGxldCBqID0gMDsgaiA8IHdpZHRoOyBqKyspIHsKICAgICAgbGV0IGkwLCBqMDsKICAgICAgbGV0IGNvbnRleHRMYWJlbCA9IDA7CiAgICAgIGZvciAoayA9IDA7IGsgPCBjb2RpbmdUZW1wbGF0ZUxlbmd0aDsgaysrKSB7CiAgICAgICAgaTAgPSBpICsgY29kaW5nVGVtcGxhdGVZW2tdOwogICAgICAgIGowID0gaiArIGNvZGluZ1RlbXBsYXRlWFtrXTsKICAgICAgICBpZiAoaTAgPCAwIHx8IGowIDwgMCB8fCBqMCA+PSB3aWR0aCkgewogICAgICAgICAgY29udGV4dExhYmVsIDw8PSAxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb250ZXh0TGFiZWwgPSBjb250ZXh0TGFiZWwgPDwgMSB8IGJpdG1hcFtpMF1bajBdOwogICAgICAgIH0KICAgICAgfQogICAgICBmb3IgKGsgPSAwOyBrIDwgcmVmZXJlbmNlVGVtcGxhdGVMZW5ndGg7IGsrKykgewogICAgICAgIGkwID0gaSArIHJlZmVyZW5jZVRlbXBsYXRlWVtrXSAtIG9mZnNldFk7CiAgICAgICAgajAgPSBqICsgcmVmZXJlbmNlVGVtcGxhdGVYW2tdIC0gb2Zmc2V0WDsKICAgICAgICBpZiAoaTAgPCAwIHx8IGkwID49IHJlZmVyZW5jZUhlaWdodCB8fCBqMCA8IDAgfHwgajAgPj0gcmVmZXJlbmNlV2lkdGgpIHsKICAgICAgICAgIGNvbnRleHRMYWJlbCA8PD0gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29udGV4dExhYmVsID0gY29udGV4dExhYmVsIDw8IDEgfCByZWZlcmVuY2VCaXRtYXBbaTBdW2owXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgcGl4ZWwgPSBkZWNvZGVyLnJlYWRCaXQoY29udGV4dHMsIGNvbnRleHRMYWJlbCk7CiAgICAgIHJvd1tqXSA9IHBpeGVsOwogICAgfQogIH0KICByZXR1cm4gYml0bWFwOwp9CmZ1bmN0aW9uIGRlY29kZVN5bWJvbERpY3Rpb25hcnkoaHVmZm1hbiwgcmVmaW5lbWVudCwgc3ltYm9scywgbnVtYmVyT2ZOZXdTeW1ib2xzLCBudW1iZXJPZkV4cG9ydGVkU3ltYm9scywgaHVmZm1hblRhYmxlcywgdGVtcGxhdGVJbmRleCwgYXQsIHJlZmluZW1lbnRUZW1wbGF0ZUluZGV4LCByZWZpbmVtZW50QXQsIGRlY29kaW5nQ29udGV4dCwgaHVmZm1hbklucHV0KSB7CiAgaWYgKGh1ZmZtYW4gJiYgcmVmaW5lbWVudCkgewogICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoInN5bWJvbCByZWZpbmVtZW50IHdpdGggSHVmZm1hbiBpcyBub3Qgc3VwcG9ydGVkIik7CiAgfQogIGNvbnN0IG5ld1N5bWJvbHMgPSBbXTsKICBsZXQgY3VycmVudEhlaWdodCA9IDA7CiAgbGV0IHN5bWJvbENvZGVMZW5ndGggPSBsb2cyKHN5bWJvbHMubGVuZ3RoICsgbnVtYmVyT2ZOZXdTeW1ib2xzKTsKICBjb25zdCBkZWNvZGVyID0gZGVjb2RpbmdDb250ZXh0LmRlY29kZXI7CiAgY29uc3QgY29udGV4dENhY2hlID0gZGVjb2RpbmdDb250ZXh0LmNvbnRleHRDYWNoZTsKICBsZXQgdGFibGVCMSwgc3ltYm9sV2lkdGhzOwogIGlmIChodWZmbWFuKSB7CiAgICB0YWJsZUIxID0gZ2V0U3RhbmRhcmRUYWJsZSgxKTsKICAgIHN5bWJvbFdpZHRocyA9IFtdOwogICAgc3ltYm9sQ29kZUxlbmd0aCA9IE1hdGgubWF4KHN5bWJvbENvZGVMZW5ndGgsIDEpOwogIH0KICB3aGlsZSAobmV3U3ltYm9scy5sZW5ndGggPCBudW1iZXJPZk5ld1N5bWJvbHMpIHsKICAgIGNvbnN0IGRlbHRhSGVpZ2h0ID0gaHVmZm1hbiA/IGh1ZmZtYW5UYWJsZXMudGFibGVEZWx0YUhlaWdodC5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFESCIsIGRlY29kZXIpOwogICAgY3VycmVudEhlaWdodCArPSBkZWx0YUhlaWdodDsKICAgIGxldCBjdXJyZW50V2lkdGggPSAwLAogICAgICB0b3RhbFdpZHRoID0gMDsKICAgIGNvbnN0IGZpcnN0U3ltYm9sID0gaHVmZm1hbiA/IHN5bWJvbFdpZHRocy5sZW5ndGggOiAwOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgY29uc3QgZGVsdGFXaWR0aCA9IGh1ZmZtYW4gPyBodWZmbWFuVGFibGVzLnRhYmxlRGVsdGFXaWR0aC5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFEVyIsIGRlY29kZXIpOwogICAgICBpZiAoZGVsdGFXaWR0aCA9PT0gbnVsbCkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGN1cnJlbnRXaWR0aCArPSBkZWx0YVdpZHRoOwogICAgICB0b3RhbFdpZHRoICs9IGN1cnJlbnRXaWR0aDsKICAgICAgbGV0IGJpdG1hcDsKICAgICAgaWYgKHJlZmluZW1lbnQpIHsKICAgICAgICBjb25zdCBudW1iZXJPZkluc3RhbmNlcyA9IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFBSSIsIGRlY29kZXIpOwogICAgICAgIGlmIChudW1iZXJPZkluc3RhbmNlcyA+IDEpIHsKICAgICAgICAgIGJpdG1hcCA9IGRlY29kZVRleHRSZWdpb24oaHVmZm1hbiwgcmVmaW5lbWVudCwgY3VycmVudFdpZHRoLCBjdXJyZW50SGVpZ2h0LCAwLCBudW1iZXJPZkluc3RhbmNlcywgMSwgc3ltYm9scy5jb25jYXQobmV3U3ltYm9scyksIHN5bWJvbENvZGVMZW5ndGgsIDAsIDAsIDEsIDAsIGh1ZmZtYW5UYWJsZXMsIHJlZmluZW1lbnRUZW1wbGF0ZUluZGV4LCByZWZpbmVtZW50QXQsIGRlY29kaW5nQ29udGV4dCwgMCwgaHVmZm1hbklucHV0KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3Qgc3ltYm9sSWQgPSBkZWNvZGVJQUlEKGNvbnRleHRDYWNoZSwgZGVjb2Rlciwgc3ltYm9sQ29kZUxlbmd0aCk7CiAgICAgICAgICBjb25zdCByZHggPSBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBUkRYIiwgZGVjb2Rlcik7CiAgICAgICAgICBjb25zdCByZHkgPSBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBUkRZIiwgZGVjb2Rlcik7CiAgICAgICAgICBjb25zdCBzeW1ib2wgPSBzeW1ib2xJZCA8IHN5bWJvbHMubGVuZ3RoID8gc3ltYm9sc1tzeW1ib2xJZF0gOiBuZXdTeW1ib2xzW3N5bWJvbElkIC0gc3ltYm9scy5sZW5ndGhdOwogICAgICAgICAgYml0bWFwID0gZGVjb2RlUmVmaW5lbWVudChjdXJyZW50V2lkdGgsIGN1cnJlbnRIZWlnaHQsIHJlZmluZW1lbnRUZW1wbGF0ZUluZGV4LCBzeW1ib2wsIHJkeCwgcmR5LCBmYWxzZSwgcmVmaW5lbWVudEF0LCBkZWNvZGluZ0NvbnRleHQpOwogICAgICAgIH0KICAgICAgICBuZXdTeW1ib2xzLnB1c2goYml0bWFwKTsKICAgICAgfSBlbHNlIGlmIChodWZmbWFuKSB7CiAgICAgICAgc3ltYm9sV2lkdGhzLnB1c2goY3VycmVudFdpZHRoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBiaXRtYXAgPSBkZWNvZGVCaXRtYXAoZmFsc2UsIGN1cnJlbnRXaWR0aCwgY3VycmVudEhlaWdodCwgdGVtcGxhdGVJbmRleCwgZmFsc2UsIG51bGwsIGF0LCBkZWNvZGluZ0NvbnRleHQpOwogICAgICAgIG5ld1N5bWJvbHMucHVzaChiaXRtYXApOwogICAgICB9CiAgICB9CiAgICBpZiAoaHVmZm1hbiAmJiAhcmVmaW5lbWVudCkgewogICAgICBjb25zdCBiaXRtYXBTaXplID0gaHVmZm1hblRhYmxlcy50YWJsZUJpdG1hcFNpemUuZGVjb2RlKGh1ZmZtYW5JbnB1dCk7CiAgICAgIGh1ZmZtYW5JbnB1dC5ieXRlQWxpZ24oKTsKICAgICAgbGV0IGNvbGxlY3RpdmVCaXRtYXA7CiAgICAgIGlmIChiaXRtYXBTaXplID09PSAwKSB7CiAgICAgICAgY29sbGVjdGl2ZUJpdG1hcCA9IHJlYWRVbmNvbXByZXNzZWRCaXRtYXAoaHVmZm1hbklucHV0LCB0b3RhbFdpZHRoLCBjdXJyZW50SGVpZ2h0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBvcmlnaW5hbEVuZCA9IGh1ZmZtYW5JbnB1dC5lbmQ7CiAgICAgICAgY29uc3QgYml0bWFwRW5kID0gaHVmZm1hbklucHV0LnBvc2l0aW9uICsgYml0bWFwU2l6ZTsKICAgICAgICBodWZmbWFuSW5wdXQuZW5kID0gYml0bWFwRW5kOwogICAgICAgIGNvbGxlY3RpdmVCaXRtYXAgPSBkZWNvZGVNTVJCaXRtYXAoaHVmZm1hbklucHV0LCB0b3RhbFdpZHRoLCBjdXJyZW50SGVpZ2h0LCBmYWxzZSk7CiAgICAgICAgaHVmZm1hbklucHV0LmVuZCA9IG9yaWdpbmFsRW5kOwogICAgICAgIGh1ZmZtYW5JbnB1dC5wb3NpdGlvbiA9IGJpdG1hcEVuZDsKICAgICAgfQogICAgICBjb25zdCBudW1iZXJPZlN5bWJvbHNEZWNvZGVkID0gc3ltYm9sV2lkdGhzLmxlbmd0aDsKICAgICAgaWYgKGZpcnN0U3ltYm9sID09PSBudW1iZXJPZlN5bWJvbHNEZWNvZGVkIC0gMSkgewogICAgICAgIG5ld1N5bWJvbHMucHVzaChjb2xsZWN0aXZlQml0bWFwKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBsZXQgaSwKICAgICAgICAgIHksCiAgICAgICAgICB4TWluID0gMCwKICAgICAgICAgIHhNYXgsCiAgICAgICAgICBiaXRtYXBXaWR0aCwKICAgICAgICAgIHN5bWJvbEJpdG1hcDsKICAgICAgICBmb3IgKGkgPSBmaXJzdFN5bWJvbDsgaSA8IG51bWJlck9mU3ltYm9sc0RlY29kZWQ7IGkrKykgewogICAgICAgICAgYml0bWFwV2lkdGggPSBzeW1ib2xXaWR0aHNbaV07CiAgICAgICAgICB4TWF4ID0geE1pbiArIGJpdG1hcFdpZHRoOwogICAgICAgICAgc3ltYm9sQml0bWFwID0gW107CiAgICAgICAgICBmb3IgKHkgPSAwOyB5IDwgY3VycmVudEhlaWdodDsgeSsrKSB7CiAgICAgICAgICAgIHN5bWJvbEJpdG1hcC5wdXNoKGNvbGxlY3RpdmVCaXRtYXBbeV0uc3ViYXJyYXkoeE1pbiwgeE1heCkpOwogICAgICAgICAgfQogICAgICAgICAgbmV3U3ltYm9scy5wdXNoKHN5bWJvbEJpdG1hcCk7CiAgICAgICAgICB4TWluID0geE1heDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgY29uc3QgZXhwb3J0ZWRTeW1ib2xzID0gW10sCiAgICBmbGFncyA9IFtdOwogIGxldCBjdXJyZW50RmxhZyA9IGZhbHNlLAogICAgaSwKICAgIGlpOwogIGNvbnN0IHRvdGFsU3ltYm9sc0xlbmd0aCA9IHN5bWJvbHMubGVuZ3RoICsgbnVtYmVyT2ZOZXdTeW1ib2xzOwogIHdoaWxlIChmbGFncy5sZW5ndGggPCB0b3RhbFN5bWJvbHNMZW5ndGgpIHsKICAgIGxldCBydW5MZW5ndGggPSBodWZmbWFuID8gdGFibGVCMS5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFFWCIsIGRlY29kZXIpOwogICAgd2hpbGUgKHJ1bkxlbmd0aC0tKSB7CiAgICAgIGZsYWdzLnB1c2goY3VycmVudEZsYWcpOwogICAgfQogICAgY3VycmVudEZsYWcgPSAhY3VycmVudEZsYWc7CiAgfQogIGZvciAoaSA9IDAsIGlpID0gc3ltYm9scy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBpZiAoZmxhZ3NbaV0pIHsKICAgICAgZXhwb3J0ZWRTeW1ib2xzLnB1c2goc3ltYm9sc1tpXSk7CiAgICB9CiAgfQogIGZvciAobGV0IGogPSAwOyBqIDwgbnVtYmVyT2ZOZXdTeW1ib2xzOyBpKyssIGorKykgewogICAgaWYgKGZsYWdzW2ldKSB7CiAgICAgIGV4cG9ydGVkU3ltYm9scy5wdXNoKG5ld1N5bWJvbHNbal0pOwogICAgfQogIH0KICByZXR1cm4gZXhwb3J0ZWRTeW1ib2xzOwp9CmZ1bmN0aW9uIGRlY29kZVRleHRSZWdpb24oaHVmZm1hbiwgcmVmaW5lbWVudCwgd2lkdGgsIGhlaWdodCwgZGVmYXVsdFBpeGVsVmFsdWUsIG51bWJlck9mU3ltYm9sSW5zdGFuY2VzLCBzdHJpcFNpemUsIGlucHV0U3ltYm9scywgc3ltYm9sQ29kZUxlbmd0aCwgdHJhbnNwb3NlZCwgZHNPZmZzZXQsIHJlZmVyZW5jZUNvcm5lciwgY29tYmluYXRpb25PcGVyYXRvciwgaHVmZm1hblRhYmxlcywgcmVmaW5lbWVudFRlbXBsYXRlSW5kZXgsIHJlZmluZW1lbnRBdCwgZGVjb2RpbmdDb250ZXh0LCBsb2dTdHJpcFNpemUsIGh1ZmZtYW5JbnB1dCkgewogIGlmIChodWZmbWFuICYmIHJlZmluZW1lbnQpIHsKICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJyZWZpbmVtZW50IHdpdGggSHVmZm1hbiBpcyBub3Qgc3VwcG9ydGVkIik7CiAgfQogIGNvbnN0IGJpdG1hcCA9IFtdOwogIGxldCBpLCByb3c7CiAgZm9yIChpID0gMDsgaSA8IGhlaWdodDsgaSsrKSB7CiAgICByb3cgPSBuZXcgVWludDhBcnJheSh3aWR0aCk7CiAgICBpZiAoZGVmYXVsdFBpeGVsVmFsdWUpIHsKICAgICAgcm93LmZpbGwoZGVmYXVsdFBpeGVsVmFsdWUpOwogICAgfQogICAgYml0bWFwLnB1c2gocm93KTsKICB9CiAgY29uc3QgZGVjb2RlciA9IGRlY29kaW5nQ29udGV4dC5kZWNvZGVyOwogIGNvbnN0IGNvbnRleHRDYWNoZSA9IGRlY29kaW5nQ29udGV4dC5jb250ZXh0Q2FjaGU7CiAgbGV0IHN0cmlwVCA9IGh1ZmZtYW4gPyAtaHVmZm1hblRhYmxlcy50YWJsZURlbHRhVC5kZWNvZGUoaHVmZm1hbklucHV0KSA6IC1kZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBRFQiLCBkZWNvZGVyKTsKICBsZXQgZmlyc3RTID0gMDsKICBpID0gMDsKICB3aGlsZSAoaSA8IG51bWJlck9mU3ltYm9sSW5zdGFuY2VzKSB7CiAgICBjb25zdCBkZWx0YVQgPSBodWZmbWFuID8gaHVmZm1hblRhYmxlcy50YWJsZURlbHRhVC5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFEVCIsIGRlY29kZXIpOwogICAgc3RyaXBUICs9IGRlbHRhVDsKICAgIGNvbnN0IGRlbHRhRmlyc3RTID0gaHVmZm1hbiA/IGh1ZmZtYW5UYWJsZXMudGFibGVGaXJzdFMuZGVjb2RlKGh1ZmZtYW5JbnB1dCkgOiBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBRlMiLCBkZWNvZGVyKTsKICAgIGZpcnN0UyArPSBkZWx0YUZpcnN0UzsKICAgIGxldCBjdXJyZW50UyA9IGZpcnN0UzsKICAgIGRvIHsKICAgICAgbGV0IGN1cnJlbnRUID0gMDsKICAgICAgaWYgKHN0cmlwU2l6ZSA+IDEpIHsKICAgICAgICBjdXJyZW50VCA9IGh1ZmZtYW4gPyBodWZmbWFuSW5wdXQucmVhZEJpdHMobG9nU3RyaXBTaXplKSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFJVCIsIGRlY29kZXIpOwogICAgICB9CiAgICAgIGNvbnN0IHQgPSBzdHJpcFNpemUgKiBzdHJpcFQgKyBjdXJyZW50VDsKICAgICAgY29uc3Qgc3ltYm9sSWQgPSBodWZmbWFuID8gaHVmZm1hblRhYmxlcy5zeW1ib2xJRFRhYmxlLmRlY29kZShodWZmbWFuSW5wdXQpIDogZGVjb2RlSUFJRChjb250ZXh0Q2FjaGUsIGRlY29kZXIsIHN5bWJvbENvZGVMZW5ndGgpOwogICAgICBjb25zdCBhcHBseVJlZmluZW1lbnQgPSByZWZpbmVtZW50ICYmIChodWZmbWFuID8gaHVmZm1hbklucHV0LnJlYWRCaXQoKSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFSSSIsIGRlY29kZXIpKTsKICAgICAgbGV0IHN5bWJvbEJpdG1hcCA9IGlucHV0U3ltYm9sc1tzeW1ib2xJZF07CiAgICAgIGxldCBzeW1ib2xXaWR0aCA9IHN5bWJvbEJpdG1hcFswXS5sZW5ndGg7CiAgICAgIGxldCBzeW1ib2xIZWlnaHQgPSBzeW1ib2xCaXRtYXAubGVuZ3RoOwogICAgICBpZiAoYXBwbHlSZWZpbmVtZW50KSB7CiAgICAgICAgY29uc3QgcmR3ID0gZGVjb2RlSW50ZWdlcihjb250ZXh0Q2FjaGUsICJJQVJEVyIsIGRlY29kZXIpOwogICAgICAgIGNvbnN0IHJkaCA9IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFSREgiLCBkZWNvZGVyKTsKICAgICAgICBjb25zdCByZHggPSBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBUkRYIiwgZGVjb2Rlcik7CiAgICAgICAgY29uc3QgcmR5ID0gZGVjb2RlSW50ZWdlcihjb250ZXh0Q2FjaGUsICJJQVJEWSIsIGRlY29kZXIpOwogICAgICAgIHN5bWJvbFdpZHRoICs9IHJkdzsKICAgICAgICBzeW1ib2xIZWlnaHQgKz0gcmRoOwogICAgICAgIHN5bWJvbEJpdG1hcCA9IGRlY29kZVJlZmluZW1lbnQoc3ltYm9sV2lkdGgsIHN5bWJvbEhlaWdodCwgcmVmaW5lbWVudFRlbXBsYXRlSW5kZXgsIHN5bWJvbEJpdG1hcCwgKHJkdyA+PiAxKSArIHJkeCwgKHJkaCA+PiAxKSArIHJkeSwgZmFsc2UsIHJlZmluZW1lbnRBdCwgZGVjb2RpbmdDb250ZXh0KTsKICAgICAgfQogICAgICBsZXQgaW5jcmVtZW50ID0gMDsKICAgICAgaWYgKCF0cmFuc3Bvc2VkKSB7CiAgICAgICAgaWYgKHJlZmVyZW5jZUNvcm5lciA+IDEpIHsKICAgICAgICAgIGN1cnJlbnRTICs9IHN5bWJvbFdpZHRoIC0gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaW5jcmVtZW50ID0gc3ltYm9sV2lkdGggLSAxOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmICghKHJlZmVyZW5jZUNvcm5lciAmIDEpKSB7CiAgICAgICAgY3VycmVudFMgKz0gc3ltYm9sSGVpZ2h0IC0gMTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpbmNyZW1lbnQgPSBzeW1ib2xIZWlnaHQgLSAxOwogICAgICB9CiAgICAgIGNvbnN0IG9mZnNldFQgPSB0IC0gKHJlZmVyZW5jZUNvcm5lciAmIDEgPyAwIDogc3ltYm9sSGVpZ2h0IC0gMSk7CiAgICAgIGNvbnN0IG9mZnNldFMgPSBjdXJyZW50UyAtIChyZWZlcmVuY2VDb3JuZXIgJiAyID8gc3ltYm9sV2lkdGggLSAxIDogMCk7CiAgICAgIGxldCBzMiwgdDIsIHN5bWJvbFJvdzsKICAgICAgaWYgKHRyYW5zcG9zZWQpIHsKICAgICAgICBmb3IgKHMyID0gMDsgczIgPCBzeW1ib2xIZWlnaHQ7IHMyKyspIHsKICAgICAgICAgIHJvdyA9IGJpdG1hcFtvZmZzZXRTICsgczJdOwogICAgICAgICAgaWYgKCFyb3cpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBzeW1ib2xSb3cgPSBzeW1ib2xCaXRtYXBbczJdOwogICAgICAgICAgY29uc3QgbWF4V2lkdGggPSBNYXRoLm1pbih3aWR0aCAtIG9mZnNldFQsIHN5bWJvbFdpZHRoKTsKICAgICAgICAgIHN3aXRjaCAoY29tYmluYXRpb25PcGVyYXRvcikgewogICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgZm9yICh0MiA9IDA7IHQyIDwgbWF4V2lkdGg7IHQyKyspIHsKICAgICAgICAgICAgICAgIHJvd1tvZmZzZXRUICsgdDJdIHw9IHN5bWJvbFJvd1t0Ml07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgZm9yICh0MiA9IDA7IHQyIDwgbWF4V2lkdGg7IHQyKyspIHsKICAgICAgICAgICAgICAgIHJvd1tvZmZzZXRUICsgdDJdIF49IHN5bWJvbFJvd1t0Ml07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKGBvcGVyYXRvciAke2NvbWJpbmF0aW9uT3BlcmF0b3J9IGlzIG5vdCBzdXBwb3J0ZWRgKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yICh0MiA9IDA7IHQyIDwgc3ltYm9sSGVpZ2h0OyB0MisrKSB7CiAgICAgICAgICByb3cgPSBiaXRtYXBbb2Zmc2V0VCArIHQyXTsKICAgICAgICAgIGlmICghcm93KSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgc3ltYm9sUm93ID0gc3ltYm9sQml0bWFwW3QyXTsKICAgICAgICAgIHN3aXRjaCAoY29tYmluYXRpb25PcGVyYXRvcikgewogICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgZm9yIChzMiA9IDA7IHMyIDwgc3ltYm9sV2lkdGg7IHMyKyspIHsKICAgICAgICAgICAgICAgIHJvd1tvZmZzZXRTICsgczJdIHw9IHN5bWJvbFJvd1tzMl07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgZm9yIChzMiA9IDA7IHMyIDwgc3ltYm9sV2lkdGg7IHMyKyspIHsKICAgICAgICAgICAgICAgIHJvd1tvZmZzZXRTICsgczJdIF49IHN5bWJvbFJvd1tzMl07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKGBvcGVyYXRvciAke2NvbWJpbmF0aW9uT3BlcmF0b3J9IGlzIG5vdCBzdXBwb3J0ZWRgKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgaSsrOwogICAgICBjb25zdCBkZWx0YVMgPSBodWZmbWFuID8gaHVmZm1hblRhYmxlcy50YWJsZURlbHRhUy5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFEUyIsIGRlY29kZXIpOwogICAgICBpZiAoZGVsdGFTID09PSBudWxsKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY3VycmVudFMgKz0gaW5jcmVtZW50ICsgZGVsdGFTICsgZHNPZmZzZXQ7CiAgICB9IHdoaWxlICh0cnVlKTsKICB9CiAgcmV0dXJuIGJpdG1hcDsKfQpmdW5jdGlvbiBkZWNvZGVQYXR0ZXJuRGljdGlvbmFyeShtbXIsIHBhdHRlcm5XaWR0aCwgcGF0dGVybkhlaWdodCwgbWF4UGF0dGVybkluZGV4LCB0ZW1wbGF0ZSwgZGVjb2RpbmdDb250ZXh0KSB7CiAgY29uc3QgYXQgPSBbXTsKICBpZiAoIW1tcikgewogICAgYXQucHVzaCh7CiAgICAgIHg6IC1wYXR0ZXJuV2lkdGgsCiAgICAgIHk6IDAKICAgIH0pOwogICAgaWYgKHRlbXBsYXRlID09PSAwKSB7CiAgICAgIGF0LnB1c2goewogICAgICAgIHg6IC0zLAogICAgICAgIHk6IC0xCiAgICAgIH0sIHsKICAgICAgICB4OiAyLAogICAgICAgIHk6IC0yCiAgICAgIH0sIHsKICAgICAgICB4OiAtMiwKICAgICAgICB5OiAtMgogICAgICB9KTsKICAgIH0KICB9CiAgY29uc3QgY29sbGVjdGl2ZVdpZHRoID0gKG1heFBhdHRlcm5JbmRleCArIDEpICogcGF0dGVybldpZHRoOwogIGNvbnN0IGNvbGxlY3RpdmVCaXRtYXAgPSBkZWNvZGVCaXRtYXAobW1yLCBjb2xsZWN0aXZlV2lkdGgsIHBhdHRlcm5IZWlnaHQsIHRlbXBsYXRlLCBmYWxzZSwgbnVsbCwgYXQsIGRlY29kaW5nQ29udGV4dCk7CiAgY29uc3QgcGF0dGVybnMgPSBbXTsKICBmb3IgKGxldCBpID0gMDsgaSA8PSBtYXhQYXR0ZXJuSW5kZXg7IGkrKykgewogICAgY29uc3QgcGF0dGVybkJpdG1hcCA9IFtdOwogICAgY29uc3QgeE1pbiA9IHBhdHRlcm5XaWR0aCAqIGk7CiAgICBjb25zdCB4TWF4ID0geE1pbiArIHBhdHRlcm5XaWR0aDsKICAgIGZvciAobGV0IHkgPSAwOyB5IDwgcGF0dGVybkhlaWdodDsgeSsrKSB7CiAgICAgIHBhdHRlcm5CaXRtYXAucHVzaChjb2xsZWN0aXZlQml0bWFwW3ldLnN1YmFycmF5KHhNaW4sIHhNYXgpKTsKICAgIH0KICAgIHBhdHRlcm5zLnB1c2gocGF0dGVybkJpdG1hcCk7CiAgfQogIHJldHVybiBwYXR0ZXJuczsKfQpmdW5jdGlvbiBkZWNvZGVIYWxmdG9uZVJlZ2lvbihtbXIsIHBhdHRlcm5zLCB0ZW1wbGF0ZSwgcmVnaW9uV2lkdGgsIHJlZ2lvbkhlaWdodCwgZGVmYXVsdFBpeGVsVmFsdWUsIGVuYWJsZVNraXAsIGNvbWJpbmF0aW9uT3BlcmF0b3IsIGdyaWRXaWR0aCwgZ3JpZEhlaWdodCwgZ3JpZE9mZnNldFgsIGdyaWRPZmZzZXRZLCBncmlkVmVjdG9yWCwgZ3JpZFZlY3RvclksIGRlY29kaW5nQ29udGV4dCkgewogIGNvbnN0IHNraXAgPSBudWxsOwogIGlmIChlbmFibGVTa2lwKSB7CiAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigic2tpcCBpcyBub3Qgc3VwcG9ydGVkIik7CiAgfQogIGlmIChjb21iaW5hdGlvbk9wZXJhdG9yICE9PSAwKSB7CiAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcihgb3BlcmF0b3IgIiR7Y29tYmluYXRpb25PcGVyYXRvcn0iIGlzIG5vdCBzdXBwb3J0ZWQgaW4gaGFsZnRvbmUgcmVnaW9uYCk7CiAgfQogIGNvbnN0IHJlZ2lvbkJpdG1hcCA9IFtdOwogIGxldCBpLCBqLCByb3c7CiAgZm9yIChpID0gMDsgaSA8IHJlZ2lvbkhlaWdodDsgaSsrKSB7CiAgICByb3cgPSBuZXcgVWludDhBcnJheShyZWdpb25XaWR0aCk7CiAgICBpZiAoZGVmYXVsdFBpeGVsVmFsdWUpIHsKICAgICAgcm93LmZpbGwoZGVmYXVsdFBpeGVsVmFsdWUpOwogICAgfQogICAgcmVnaW9uQml0bWFwLnB1c2gocm93KTsKICB9CiAgY29uc3QgbnVtYmVyT2ZQYXR0ZXJucyA9IHBhdHRlcm5zLmxlbmd0aDsKICBjb25zdCBwYXR0ZXJuMCA9IHBhdHRlcm5zWzBdOwogIGNvbnN0IHBhdHRlcm5XaWR0aCA9IHBhdHRlcm4wWzBdLmxlbmd0aCwKICAgIHBhdHRlcm5IZWlnaHQgPSBwYXR0ZXJuMC5sZW5ndGg7CiAgY29uc3QgYml0c1BlclZhbHVlID0gbG9nMihudW1iZXJPZlBhdHRlcm5zKTsKICBjb25zdCBhdCA9IFtdOwogIGlmICghbW1yKSB7CiAgICBhdC5wdXNoKHsKICAgICAgeDogdGVtcGxhdGUgPD0gMSA/IDMgOiAyLAogICAgICB5OiAtMQogICAgfSk7CiAgICBpZiAodGVtcGxhdGUgPT09IDApIHsKICAgICAgYXQucHVzaCh7CiAgICAgICAgeDogLTMsCiAgICAgICAgeTogLTEKICAgICAgfSwgewogICAgICAgIHg6IDIsCiAgICAgICAgeTogLTIKICAgICAgfSwgewogICAgICAgIHg6IC0yLAogICAgICAgIHk6IC0yCiAgICAgIH0pOwogICAgfQogIH0KICBjb25zdCBncmF5U2NhbGVCaXRQbGFuZXMgPSBbXTsKICBsZXQgbW1ySW5wdXQsIGJpdG1hcDsKICBpZiAobW1yKSB7CiAgICBtbXJJbnB1dCA9IG5ldyBSZWFkZXIoZGVjb2RpbmdDb250ZXh0LmRhdGEsIGRlY29kaW5nQ29udGV4dC5zdGFydCwgZGVjb2RpbmdDb250ZXh0LmVuZCk7CiAgfQogIGZvciAoaSA9IGJpdHNQZXJWYWx1ZSAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICBpZiAobW1yKSB7CiAgICAgIGJpdG1hcCA9IGRlY29kZU1NUkJpdG1hcChtbXJJbnB1dCwgZ3JpZFdpZHRoLCBncmlkSGVpZ2h0LCB0cnVlKTsKICAgIH0gZWxzZSB7CiAgICAgIGJpdG1hcCA9IGRlY29kZUJpdG1hcChmYWxzZSwgZ3JpZFdpZHRoLCBncmlkSGVpZ2h0LCB0ZW1wbGF0ZSwgZmFsc2UsIHNraXAsIGF0LCBkZWNvZGluZ0NvbnRleHQpOwogICAgfQogICAgZ3JheVNjYWxlQml0UGxhbmVzW2ldID0gYml0bWFwOwogIH0KICBsZXQgbWcsIG5nLCBiaXQsIHBhdHRlcm5JbmRleCwgcGF0dGVybkJpdG1hcCwgeCwgeSwgcGF0dGVyblJvdywgcmVnaW9uUm93OwogIGZvciAobWcgPSAwOyBtZyA8IGdyaWRIZWlnaHQ7IG1nKyspIHsKICAgIGZvciAobmcgPSAwOyBuZyA8IGdyaWRXaWR0aDsgbmcrKykgewogICAgICBiaXQgPSAwOwogICAgICBwYXR0ZXJuSW5kZXggPSAwOwogICAgICBmb3IgKGogPSBiaXRzUGVyVmFsdWUgLSAxOyBqID49IDA7IGotLSkgewogICAgICAgIGJpdCBePSBncmF5U2NhbGVCaXRQbGFuZXNbal1bbWddW25nXTsKICAgICAgICBwYXR0ZXJuSW5kZXggfD0gYml0IDw8IGo7CiAgICAgIH0KICAgICAgcGF0dGVybkJpdG1hcCA9IHBhdHRlcm5zW3BhdHRlcm5JbmRleF07CiAgICAgIHggPSBncmlkT2Zmc2V0WCArIG1nICogZ3JpZFZlY3RvclkgKyBuZyAqIGdyaWRWZWN0b3JYID4+IDg7CiAgICAgIHkgPSBncmlkT2Zmc2V0WSArIG1nICogZ3JpZFZlY3RvclggLSBuZyAqIGdyaWRWZWN0b3JZID4+IDg7CiAgICAgIGlmICh4ID49IDAgJiYgeCArIHBhdHRlcm5XaWR0aCA8PSByZWdpb25XaWR0aCAmJiB5ID49IDAgJiYgeSArIHBhdHRlcm5IZWlnaHQgPD0gcmVnaW9uSGVpZ2h0KSB7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHBhdHRlcm5IZWlnaHQ7IGkrKykgewogICAgICAgICAgcmVnaW9uUm93ID0gcmVnaW9uQml0bWFwW3kgKyBpXTsKICAgICAgICAgIHBhdHRlcm5Sb3cgPSBwYXR0ZXJuQml0bWFwW2ldOwogICAgICAgICAgZm9yIChqID0gMDsgaiA8IHBhdHRlcm5XaWR0aDsgaisrKSB7CiAgICAgICAgICAgIHJlZ2lvblJvd1t4ICsgal0gfD0gcGF0dGVyblJvd1tqXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbGV0IHJlZ2lvblgsIHJlZ2lvblk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHBhdHRlcm5IZWlnaHQ7IGkrKykgewogICAgICAgICAgcmVnaW9uWSA9IHkgKyBpOwogICAgICAgICAgaWYgKHJlZ2lvblkgPCAwIHx8IHJlZ2lvblkgPj0gcmVnaW9uSGVpZ2h0KSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgcmVnaW9uUm93ID0gcmVnaW9uQml0bWFwW3JlZ2lvblldOwogICAgICAgICAgcGF0dGVyblJvdyA9IHBhdHRlcm5CaXRtYXBbaV07CiAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgcGF0dGVybldpZHRoOyBqKyspIHsKICAgICAgICAgICAgcmVnaW9uWCA9IHggKyBqOwogICAgICAgICAgICBpZiAocmVnaW9uWCA+PSAwICYmIHJlZ2lvblggPCByZWdpb25XaWR0aCkgewogICAgICAgICAgICAgIHJlZ2lvblJvd1tyZWdpb25YXSB8PSBwYXR0ZXJuUm93W2pdOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQogIHJldHVybiByZWdpb25CaXRtYXA7Cn0KZnVuY3Rpb24gcmVhZFNlZ21lbnRIZWFkZXIoZGF0YSwgc3RhcnQpIHsKICBjb25zdCBzZWdtZW50SGVhZGVyID0ge307CiAgc2VnbWVudEhlYWRlci5udW1iZXIgPSByZWFkVWludDMyKGRhdGEsIHN0YXJ0KTsKICBjb25zdCBmbGFncyA9IGRhdGFbc3RhcnQgKyA0XTsKICBjb25zdCBzZWdtZW50VHlwZSA9IGZsYWdzICYgMHgzZjsKICBpZiAoIVNlZ21lbnRUeXBlc1tzZWdtZW50VHlwZV0pIHsKICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJpbnZhbGlkIHNlZ21lbnQgdHlwZTogIiArIHNlZ21lbnRUeXBlKTsKICB9CiAgc2VnbWVudEhlYWRlci50eXBlID0gc2VnbWVudFR5cGU7CiAgc2VnbWVudEhlYWRlci50eXBlTmFtZSA9IFNlZ21lbnRUeXBlc1tzZWdtZW50VHlwZV07CiAgc2VnbWVudEhlYWRlci5kZWZlcnJlZE5vblJldGFpbiA9ICEhKGZsYWdzICYgMHg4MCk7CiAgY29uc3QgcGFnZUFzc29jaWF0aW9uRmllbGRTaXplID0gISEoZmxhZ3MgJiAweDQwKTsKICBjb25zdCByZWZlcnJlZEZsYWdzID0gZGF0YVtzdGFydCArIDVdOwogIGxldCByZWZlcnJlZFRvQ291bnQgPSByZWZlcnJlZEZsYWdzID4+IDUgJiA3OwogIGNvbnN0IHJldGFpbkJpdHMgPSBbcmVmZXJyZWRGbGFncyAmIDMxXTsKICBsZXQgcG9zaXRpb24gPSBzdGFydCArIDY7CiAgaWYgKHJlZmVycmVkVG9Db3VudCA9PT0gNykgewogICAgcmVmZXJyZWRUb0NvdW50ID0gcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbiAtIDEpICYgMHgxZmZmZmZmZjsKICAgIHBvc2l0aW9uICs9IDM7CiAgICBsZXQgYnl0ZXMgPSByZWZlcnJlZFRvQ291bnQgKyA4ID4+IDM7CiAgICByZXRhaW5CaXRzWzBdID0gZGF0YVtwb3NpdGlvbisrXTsKICAgIHdoaWxlICgtLWJ5dGVzID4gMCkgewogICAgICByZXRhaW5CaXRzLnB1c2goZGF0YVtwb3NpdGlvbisrXSk7CiAgICB9CiAgfSBlbHNlIGlmIChyZWZlcnJlZFRvQ291bnQgPT09IDUgfHwgcmVmZXJyZWRUb0NvdW50ID09PSA2KSB7CiAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCByZWZlcnJlZC10byBmbGFncyIpOwogIH0KICBzZWdtZW50SGVhZGVyLnJldGFpbkJpdHMgPSByZXRhaW5CaXRzOwogIGxldCByZWZlcnJlZFRvU2VnbWVudE51bWJlclNpemUgPSA0OwogIGlmIChzZWdtZW50SGVhZGVyLm51bWJlciA8PSAyNTYpIHsKICAgIHJlZmVycmVkVG9TZWdtZW50TnVtYmVyU2l6ZSA9IDE7CiAgfSBlbHNlIGlmIChzZWdtZW50SGVhZGVyLm51bWJlciA8PSA2NTUzNikgewogICAgcmVmZXJyZWRUb1NlZ21lbnROdW1iZXJTaXplID0gMjsKICB9CiAgY29uc3QgcmVmZXJyZWRUbyA9IFtdOwogIGxldCBpLCBpaTsKICBmb3IgKGkgPSAwOyBpIDwgcmVmZXJyZWRUb0NvdW50OyBpKyspIHsKICAgIGxldCBudW1iZXI7CiAgICBpZiAocmVmZXJyZWRUb1NlZ21lbnROdW1iZXJTaXplID09PSAxKSB7CiAgICAgIG51bWJlciA9IGRhdGFbcG9zaXRpb25dOwogICAgfSBlbHNlIGlmIChyZWZlcnJlZFRvU2VnbWVudE51bWJlclNpemUgPT09IDIpIHsKICAgICAgbnVtYmVyID0gcmVhZFVpbnQxNihkYXRhLCBwb3NpdGlvbik7CiAgICB9IGVsc2UgewogICAgICBudW1iZXIgPSByZWFkVWludDMyKGRhdGEsIHBvc2l0aW9uKTsKICAgIH0KICAgIHJlZmVycmVkVG8ucHVzaChudW1iZXIpOwogICAgcG9zaXRpb24gKz0gcmVmZXJyZWRUb1NlZ21lbnROdW1iZXJTaXplOwogIH0KICBzZWdtZW50SGVhZGVyLnJlZmVycmVkVG8gPSByZWZlcnJlZFRvOwogIGlmICghcGFnZUFzc29jaWF0aW9uRmllbGRTaXplKSB7CiAgICBzZWdtZW50SGVhZGVyLnBhZ2VBc3NvY2lhdGlvbiA9IGRhdGFbcG9zaXRpb24rK107CiAgfSBlbHNlIHsKICAgIHNlZ21lbnRIZWFkZXIucGFnZUFzc29jaWF0aW9uID0gcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbik7CiAgICBwb3NpdGlvbiArPSA0OwogIH0KICBzZWdtZW50SGVhZGVyLmxlbmd0aCA9IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24pOwogIHBvc2l0aW9uICs9IDQ7CiAgaWYgKHNlZ21lbnRIZWFkZXIubGVuZ3RoID09PSAweGZmZmZmZmZmKSB7CiAgICBpZiAoc2VnbWVudFR5cGUgPT09IDM4KSB7CiAgICAgIGNvbnN0IGdlbmVyaWNSZWdpb25JbmZvID0gcmVhZFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbihkYXRhLCBwb3NpdGlvbik7CiAgICAgIGNvbnN0IGdlbmVyaWNSZWdpb25TZWdtZW50RmxhZ3MgPSBkYXRhW3Bvc2l0aW9uICsgUmVnaW9uU2VnbWVudEluZm9ybWF0aW9uRmllbGRMZW5ndGhdOwogICAgICBjb25zdCBnZW5lcmljUmVnaW9uTW1yID0gISEoZ2VuZXJpY1JlZ2lvblNlZ21lbnRGbGFncyAmIDEpOwogICAgICBjb25zdCBzZWFyY2hQYXR0ZXJuTGVuZ3RoID0gNjsKICAgICAgY29uc3Qgc2VhcmNoUGF0dGVybiA9IG5ldyBVaW50OEFycmF5KHNlYXJjaFBhdHRlcm5MZW5ndGgpOwogICAgICBpZiAoIWdlbmVyaWNSZWdpb25NbXIpIHsKICAgICAgICBzZWFyY2hQYXR0ZXJuWzBdID0gMHhmZjsKICAgICAgICBzZWFyY2hQYXR0ZXJuWzFdID0gMHhhYzsKICAgICAgfQogICAgICBzZWFyY2hQYXR0ZXJuWzJdID0gZ2VuZXJpY1JlZ2lvbkluZm8uaGVpZ2h0ID4+PiAyNCAmIDB4ZmY7CiAgICAgIHNlYXJjaFBhdHRlcm5bM10gPSBnZW5lcmljUmVnaW9uSW5mby5oZWlnaHQgPj4gMTYgJiAweGZmOwogICAgICBzZWFyY2hQYXR0ZXJuWzRdID0gZ2VuZXJpY1JlZ2lvbkluZm8uaGVpZ2h0ID4+IDggJiAweGZmOwogICAgICBzZWFyY2hQYXR0ZXJuWzVdID0gZ2VuZXJpY1JlZ2lvbkluZm8uaGVpZ2h0ICYgMHhmZjsKICAgICAgZm9yIChpID0gcG9zaXRpb24sIGlpID0gZGF0YS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgbGV0IGogPSAwOwogICAgICAgIHdoaWxlIChqIDwgc2VhcmNoUGF0dGVybkxlbmd0aCAmJiBzZWFyY2hQYXR0ZXJuW2pdID09PSBkYXRhW2kgKyBqXSkgewogICAgICAgICAgaisrOwogICAgICAgIH0KICAgICAgICBpZiAoaiA9PT0gc2VhcmNoUGF0dGVybkxlbmd0aCkgewogICAgICAgICAgc2VnbWVudEhlYWRlci5sZW5ndGggPSBpICsgc2VhcmNoUGF0dGVybkxlbmd0aDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoc2VnbWVudEhlYWRlci5sZW5ndGggPT09IDB4ZmZmZmZmZmYpIHsKICAgICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigic2VnbWVudCBlbmQgd2FzIG5vdCBmb3VuZCIpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCB1bmtub3duIHNlZ21lbnQgbGVuZ3RoIik7CiAgICB9CiAgfQogIHNlZ21lbnRIZWFkZXIuaGVhZGVyRW5kID0gcG9zaXRpb247CiAgcmV0dXJuIHNlZ21lbnRIZWFkZXI7Cn0KZnVuY3Rpb24gcmVhZFNlZ21lbnRzKGhlYWRlciwgZGF0YSwgc3RhcnQsIGVuZCkgewogIGNvbnN0IHNlZ21lbnRzID0gW107CiAgbGV0IHBvc2l0aW9uID0gc3RhcnQ7CiAgd2hpbGUgKHBvc2l0aW9uIDwgZW5kKSB7CiAgICBjb25zdCBzZWdtZW50SGVhZGVyID0gcmVhZFNlZ21lbnRIZWFkZXIoZGF0YSwgcG9zaXRpb24pOwogICAgcG9zaXRpb24gPSBzZWdtZW50SGVhZGVyLmhlYWRlckVuZDsKICAgIGNvbnN0IHNlZ21lbnQgPSB7CiAgICAgIGhlYWRlcjogc2VnbWVudEhlYWRlciwKICAgICAgZGF0YQogICAgfTsKICAgIGlmICghaGVhZGVyLnJhbmRvbUFjY2VzcykgewogICAgICBzZWdtZW50LnN0YXJ0ID0gcG9zaXRpb247CiAgICAgIHBvc2l0aW9uICs9IHNlZ21lbnRIZWFkZXIubGVuZ3RoOwogICAgICBzZWdtZW50LmVuZCA9IHBvc2l0aW9uOwogICAgfQogICAgc2VnbWVudHMucHVzaChzZWdtZW50KTsKICAgIGlmIChzZWdtZW50SGVhZGVyLnR5cGUgPT09IDUxKSB7CiAgICAgIGJyZWFrOwogICAgfQogIH0KICBpZiAoaGVhZGVyLnJhbmRvbUFjY2VzcykgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gc2VnbWVudHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBzZWdtZW50c1tpXS5zdGFydCA9IHBvc2l0aW9uOwogICAgICBwb3NpdGlvbiArPSBzZWdtZW50c1tpXS5oZWFkZXIubGVuZ3RoOwogICAgICBzZWdtZW50c1tpXS5lbmQgPSBwb3NpdGlvbjsKICAgIH0KICB9CiAgcmV0dXJuIHNlZ21lbnRzOwp9CmZ1bmN0aW9uIHJlYWRSZWdpb25TZWdtZW50SW5mb3JtYXRpb24oZGF0YSwgc3RhcnQpIHsKICByZXR1cm4gewogICAgd2lkdGg6IHJlYWRVaW50MzIoZGF0YSwgc3RhcnQpLAogICAgaGVpZ2h0OiByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgNCksCiAgICB4OiByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgOCksCiAgICB5OiByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgMTIpLAogICAgY29tYmluYXRpb25PcGVyYXRvcjogZGF0YVtzdGFydCArIDE2XSAmIDcKICB9Owp9CmNvbnN0IFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbkZpZWxkTGVuZ3RoID0gMTc7CmZ1bmN0aW9uIHByb2Nlc3NTZWdtZW50KHNlZ21lbnQsIHZpc2l0b3IpIHsKICBjb25zdCBoZWFkZXIgPSBzZWdtZW50LmhlYWRlcjsKICBjb25zdCBkYXRhID0gc2VnbWVudC5kYXRhLAogICAgZW5kID0gc2VnbWVudC5lbmQ7CiAgbGV0IHBvc2l0aW9uID0gc2VnbWVudC5zdGFydDsKICBsZXQgYXJncywgYXQsIGksIGF0TGVuZ3RoOwogIHN3aXRjaCAoaGVhZGVyLnR5cGUpIHsKICAgIGNhc2UgMDoKICAgICAgY29uc3QgZGljdGlvbmFyeSA9IHt9OwogICAgICBjb25zdCBkaWN0aW9uYXJ5RmxhZ3MgPSByZWFkVWludDE2KGRhdGEsIHBvc2l0aW9uKTsKICAgICAgZGljdGlvbmFyeS5odWZmbWFuID0gISEoZGljdGlvbmFyeUZsYWdzICYgMSk7CiAgICAgIGRpY3Rpb25hcnkucmVmaW5lbWVudCA9ICEhKGRpY3Rpb25hcnlGbGFncyAmIDIpOwogICAgICBkaWN0aW9uYXJ5Lmh1ZmZtYW5ESFNlbGVjdG9yID0gZGljdGlvbmFyeUZsYWdzID4+IDIgJiAzOwogICAgICBkaWN0aW9uYXJ5Lmh1ZmZtYW5EV1NlbGVjdG9yID0gZGljdGlvbmFyeUZsYWdzID4+IDQgJiAzOwogICAgICBkaWN0aW9uYXJ5LmJpdG1hcFNpemVTZWxlY3RvciA9IGRpY3Rpb25hcnlGbGFncyA+PiA2ICYgMTsKICAgICAgZGljdGlvbmFyeS5hZ2dyZWdhdGlvbkluc3RhbmNlc1NlbGVjdG9yID0gZGljdGlvbmFyeUZsYWdzID4+IDcgJiAxOwogICAgICBkaWN0aW9uYXJ5LmJpdG1hcENvZGluZ0NvbnRleHRVc2VkID0gISEoZGljdGlvbmFyeUZsYWdzICYgMjU2KTsKICAgICAgZGljdGlvbmFyeS5iaXRtYXBDb2RpbmdDb250ZXh0UmV0YWluZWQgPSAhIShkaWN0aW9uYXJ5RmxhZ3MgJiA1MTIpOwogICAgICBkaWN0aW9uYXJ5LnRlbXBsYXRlID0gZGljdGlvbmFyeUZsYWdzID4+IDEwICYgMzsKICAgICAgZGljdGlvbmFyeS5yZWZpbmVtZW50VGVtcGxhdGUgPSBkaWN0aW9uYXJ5RmxhZ3MgPj4gMTIgJiAxOwogICAgICBwb3NpdGlvbiArPSAyOwogICAgICBpZiAoIWRpY3Rpb25hcnkuaHVmZm1hbikgewogICAgICAgIGF0TGVuZ3RoID0gZGljdGlvbmFyeS50ZW1wbGF0ZSA9PT0gMCA/IDQgOiAxOwogICAgICAgIGF0ID0gW107CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGF0TGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGF0LnB1c2goewogICAgICAgICAgICB4OiByZWFkSW50OChkYXRhLCBwb3NpdGlvbiksCiAgICAgICAgICAgIHk6IHJlYWRJbnQ4KGRhdGEsIHBvc2l0aW9uICsgMSkKICAgICAgICAgIH0pOwogICAgICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgICB9CiAgICAgICAgZGljdGlvbmFyeS5hdCA9IGF0OwogICAgICB9CiAgICAgIGlmIChkaWN0aW9uYXJ5LnJlZmluZW1lbnQgJiYgIWRpY3Rpb25hcnkucmVmaW5lbWVudFRlbXBsYXRlKSB7CiAgICAgICAgYXQgPSBbXTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMjsgaSsrKSB7CiAgICAgICAgICBhdC5wdXNoKHsKICAgICAgICAgICAgeDogcmVhZEludDgoZGF0YSwgcG9zaXRpb24pLAogICAgICAgICAgICB5OiByZWFkSW50OChkYXRhLCBwb3NpdGlvbiArIDEpCiAgICAgICAgICB9KTsKICAgICAgICAgIHBvc2l0aW9uICs9IDI7CiAgICAgICAgfQogICAgICAgIGRpY3Rpb25hcnkucmVmaW5lbWVudEF0ID0gYXQ7CiAgICAgIH0KICAgICAgZGljdGlvbmFyeS5udW1iZXJPZkV4cG9ydGVkU3ltYm9scyA9IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24pOwogICAgICBwb3NpdGlvbiArPSA0OwogICAgICBkaWN0aW9uYXJ5Lm51bWJlck9mTmV3U3ltYm9scyA9IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24pOwogICAgICBwb3NpdGlvbiArPSA0OwogICAgICBhcmdzID0gW2RpY3Rpb25hcnksIGhlYWRlci5udW1iZXIsIGhlYWRlci5yZWZlcnJlZFRvLCBkYXRhLCBwb3NpdGlvbiwgZW5kXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDY6CiAgICBjYXNlIDc6CiAgICAgIGNvbnN0IHRleHRSZWdpb24gPSB7fTsKICAgICAgdGV4dFJlZ2lvbi5pbmZvID0gcmVhZFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbihkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbkZpZWxkTGVuZ3RoOwogICAgICBjb25zdCB0ZXh0UmVnaW9uU2VnbWVudEZsYWdzID0gcmVhZFVpbnQxNihkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IDI7CiAgICAgIHRleHRSZWdpb24uaHVmZm1hbiA9ICEhKHRleHRSZWdpb25TZWdtZW50RmxhZ3MgJiAxKTsKICAgICAgdGV4dFJlZ2lvbi5yZWZpbmVtZW50ID0gISEodGV4dFJlZ2lvblNlZ21lbnRGbGFncyAmIDIpOwogICAgICB0ZXh0UmVnaW9uLmxvZ1N0cmlwU2l6ZSA9IHRleHRSZWdpb25TZWdtZW50RmxhZ3MgPj4gMiAmIDM7CiAgICAgIHRleHRSZWdpb24uc3RyaXBTaXplID0gMSA8PCB0ZXh0UmVnaW9uLmxvZ1N0cmlwU2l6ZTsKICAgICAgdGV4dFJlZ2lvbi5yZWZlcmVuY2VDb3JuZXIgPSB0ZXh0UmVnaW9uU2VnbWVudEZsYWdzID4+IDQgJiAzOwogICAgICB0ZXh0UmVnaW9uLnRyYW5zcG9zZWQgPSAhISh0ZXh0UmVnaW9uU2VnbWVudEZsYWdzICYgNjQpOwogICAgICB0ZXh0UmVnaW9uLmNvbWJpbmF0aW9uT3BlcmF0b3IgPSB0ZXh0UmVnaW9uU2VnbWVudEZsYWdzID4+IDcgJiAzOwogICAgICB0ZXh0UmVnaW9uLmRlZmF1bHRQaXhlbFZhbHVlID0gdGV4dFJlZ2lvblNlZ21lbnRGbGFncyA+PiA5ICYgMTsKICAgICAgdGV4dFJlZ2lvbi5kc09mZnNldCA9IHRleHRSZWdpb25TZWdtZW50RmxhZ3MgPDwgMTcgPj4gMjc7CiAgICAgIHRleHRSZWdpb24ucmVmaW5lbWVudFRlbXBsYXRlID0gdGV4dFJlZ2lvblNlZ21lbnRGbGFncyA+PiAxNSAmIDE7CiAgICAgIGlmICh0ZXh0UmVnaW9uLmh1ZmZtYW4pIHsKICAgICAgICBjb25zdCB0ZXh0UmVnaW9uSHVmZm1hbkZsYWdzID0gcmVhZFVpbnQxNihkYXRhLCBwb3NpdGlvbik7CiAgICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgICB0ZXh0UmVnaW9uLmh1ZmZtYW5GUyA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hbkRTID0gdGV4dFJlZ2lvbkh1ZmZtYW5GbGFncyA+PiAyICYgMzsKICAgICAgICB0ZXh0UmVnaW9uLmh1ZmZtYW5EVCA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgPj4gNCAmIDM7CiAgICAgICAgdGV4dFJlZ2lvbi5odWZmbWFuUmVmaW5lbWVudERXID0gdGV4dFJlZ2lvbkh1ZmZtYW5GbGFncyA+PiA2ICYgMzsKICAgICAgICB0ZXh0UmVnaW9uLmh1ZmZtYW5SZWZpbmVtZW50REggPSB0ZXh0UmVnaW9uSHVmZm1hbkZsYWdzID4+IDggJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hblJlZmluZW1lbnREWCA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgPj4gMTAgJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hblJlZmluZW1lbnREWSA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgPj4gMTIgJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hblJlZmluZW1lbnRTaXplU2VsZWN0b3IgPSAhISh0ZXh0UmVnaW9uSHVmZm1hbkZsYWdzICYgMHg0MDAwKTsKICAgICAgfQogICAgICBpZiAodGV4dFJlZ2lvbi5yZWZpbmVtZW50ICYmICF0ZXh0UmVnaW9uLnJlZmluZW1lbnRUZW1wbGF0ZSkgewogICAgICAgIGF0ID0gW107CiAgICAgICAgZm9yIChpID0gMDsgaSA8IDI7IGkrKykgewogICAgICAgICAgYXQucHVzaCh7CiAgICAgICAgICAgIHg6IHJlYWRJbnQ4KGRhdGEsIHBvc2l0aW9uKSwKICAgICAgICAgICAgeTogcmVhZEludDgoZGF0YSwgcG9zaXRpb24gKyAxKQogICAgICAgICAgfSk7CiAgICAgICAgICBwb3NpdGlvbiArPSAyOwogICAgICAgIH0KICAgICAgICB0ZXh0UmVnaW9uLnJlZmluZW1lbnRBdCA9IGF0OwogICAgICB9CiAgICAgIHRleHRSZWdpb24ubnVtYmVyT2ZTeW1ib2xJbnN0YW5jZXMgPSByZWFkVWludDMyKGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gNDsKICAgICAgYXJncyA9IFt0ZXh0UmVnaW9uLCBoZWFkZXIucmVmZXJyZWRUbywgZGF0YSwgcG9zaXRpb24sIGVuZF07CiAgICAgIGJyZWFrOwogICAgY2FzZSAxNjoKICAgICAgY29uc3QgcGF0dGVybkRpY3Rpb25hcnkgPSB7fTsKICAgICAgY29uc3QgcGF0dGVybkRpY3Rpb25hcnlGbGFncyA9IGRhdGFbcG9zaXRpb24rK107CiAgICAgIHBhdHRlcm5EaWN0aW9uYXJ5Lm1tciA9ICEhKHBhdHRlcm5EaWN0aW9uYXJ5RmxhZ3MgJiAxKTsKICAgICAgcGF0dGVybkRpY3Rpb25hcnkudGVtcGxhdGUgPSBwYXR0ZXJuRGljdGlvbmFyeUZsYWdzID4+IDEgJiAzOwogICAgICBwYXR0ZXJuRGljdGlvbmFyeS5wYXR0ZXJuV2lkdGggPSBkYXRhW3Bvc2l0aW9uKytdOwogICAgICBwYXR0ZXJuRGljdGlvbmFyeS5wYXR0ZXJuSGVpZ2h0ID0gZGF0YVtwb3NpdGlvbisrXTsKICAgICAgcGF0dGVybkRpY3Rpb25hcnkubWF4UGF0dGVybkluZGV4ID0gcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IDQ7CiAgICAgIGFyZ3MgPSBbcGF0dGVybkRpY3Rpb25hcnksIGhlYWRlci5udW1iZXIsIGRhdGEsIHBvc2l0aW9uLCBlbmRdOwogICAgICBicmVhazsKICAgIGNhc2UgMjI6CiAgICBjYXNlIDIzOgogICAgICBjb25zdCBoYWxmdG9uZVJlZ2lvbiA9IHt9OwogICAgICBoYWxmdG9uZVJlZ2lvbi5pbmZvID0gcmVhZFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbihkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbkZpZWxkTGVuZ3RoOwogICAgICBjb25zdCBoYWxmdG9uZVJlZ2lvbkZsYWdzID0gZGF0YVtwb3NpdGlvbisrXTsKICAgICAgaGFsZnRvbmVSZWdpb24ubW1yID0gISEoaGFsZnRvbmVSZWdpb25GbGFncyAmIDEpOwogICAgICBoYWxmdG9uZVJlZ2lvbi50ZW1wbGF0ZSA9IGhhbGZ0b25lUmVnaW9uRmxhZ3MgPj4gMSAmIDM7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmVuYWJsZVNraXAgPSAhIShoYWxmdG9uZVJlZ2lvbkZsYWdzICYgOCk7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmNvbWJpbmF0aW9uT3BlcmF0b3IgPSBoYWxmdG9uZVJlZ2lvbkZsYWdzID4+IDQgJiA3OwogICAgICBoYWxmdG9uZVJlZ2lvbi5kZWZhdWx0UGl4ZWxWYWx1ZSA9IGhhbGZ0b25lUmVnaW9uRmxhZ3MgPj4gNyAmIDE7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmdyaWRXaWR0aCA9IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24pOwogICAgICBwb3NpdGlvbiArPSA0OwogICAgICBoYWxmdG9uZVJlZ2lvbi5ncmlkSGVpZ2h0ID0gcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IDQ7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmdyaWRPZmZzZXRYID0gcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbikgJiAweGZmZmZmZmZmOwogICAgICBwb3NpdGlvbiArPSA0OwogICAgICBoYWxmdG9uZVJlZ2lvbi5ncmlkT2Zmc2V0WSA9IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24pICYgMHhmZmZmZmZmZjsKICAgICAgcG9zaXRpb24gKz0gNDsKICAgICAgaGFsZnRvbmVSZWdpb24uZ3JpZFZlY3RvclggPSByZWFkVWludDE2KGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgaGFsZnRvbmVSZWdpb24uZ3JpZFZlY3RvclkgPSByZWFkVWludDE2KGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgYXJncyA9IFtoYWxmdG9uZVJlZ2lvbiwgaGVhZGVyLnJlZmVycmVkVG8sIGRhdGEsIHBvc2l0aW9uLCBlbmRdOwogICAgICBicmVhazsKICAgIGNhc2UgMzg6CiAgICBjYXNlIDM5OgogICAgICBjb25zdCBnZW5lcmljUmVnaW9uID0ge307CiAgICAgIGdlbmVyaWNSZWdpb24uaW5mbyA9IHJlYWRSZWdpb25TZWdtZW50SW5mb3JtYXRpb24oZGF0YSwgcG9zaXRpb24pOwogICAgICBwb3NpdGlvbiArPSBSZWdpb25TZWdtZW50SW5mb3JtYXRpb25GaWVsZExlbmd0aDsKICAgICAgY29uc3QgZ2VuZXJpY1JlZ2lvblNlZ21lbnRGbGFncyA9IGRhdGFbcG9zaXRpb24rK107CiAgICAgIGdlbmVyaWNSZWdpb24ubW1yID0gISEoZ2VuZXJpY1JlZ2lvblNlZ21lbnRGbGFncyAmIDEpOwogICAgICBnZW5lcmljUmVnaW9uLnRlbXBsYXRlID0gZ2VuZXJpY1JlZ2lvblNlZ21lbnRGbGFncyA+PiAxICYgMzsKICAgICAgZ2VuZXJpY1JlZ2lvbi5wcmVkaWN0aW9uID0gISEoZ2VuZXJpY1JlZ2lvblNlZ21lbnRGbGFncyAmIDgpOwogICAgICBpZiAoIWdlbmVyaWNSZWdpb24ubW1yKSB7CiAgICAgICAgYXRMZW5ndGggPSBnZW5lcmljUmVnaW9uLnRlbXBsYXRlID09PSAwID8gNCA6IDE7CiAgICAgICAgYXQgPSBbXTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgYXRMZW5ndGg7IGkrKykgewogICAgICAgICAgYXQucHVzaCh7CiAgICAgICAgICAgIHg6IHJlYWRJbnQ4KGRhdGEsIHBvc2l0aW9uKSwKICAgICAgICAgICAgeTogcmVhZEludDgoZGF0YSwgcG9zaXRpb24gKyAxKQogICAgICAgICAgfSk7CiAgICAgICAgICBwb3NpdGlvbiArPSAyOwogICAgICAgIH0KICAgICAgICBnZW5lcmljUmVnaW9uLmF0ID0gYXQ7CiAgICAgIH0KICAgICAgYXJncyA9IFtnZW5lcmljUmVnaW9uLCBkYXRhLCBwb3NpdGlvbiwgZW5kXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDQ4OgogICAgICBjb25zdCBwYWdlSW5mbyA9IHsKICAgICAgICB3aWR0aDogcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbiksCiAgICAgICAgaGVpZ2h0OiByZWFkVWludDMyKGRhdGEsIHBvc2l0aW9uICsgNCksCiAgICAgICAgcmVzb2x1dGlvblg6IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24gKyA4KSwKICAgICAgICByZXNvbHV0aW9uWTogcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbiArIDEyKQogICAgICB9OwogICAgICBpZiAocGFnZUluZm8uaGVpZ2h0ID09PSAweGZmZmZmZmZmKSB7CiAgICAgICAgZGVsZXRlIHBhZ2VJbmZvLmhlaWdodDsKICAgICAgfQogICAgICBjb25zdCBwYWdlU2VnbWVudEZsYWdzID0gZGF0YVtwb3NpdGlvbiArIDE2XTsKICAgICAgcmVhZFVpbnQxNihkYXRhLCBwb3NpdGlvbiArIDE3KTsKICAgICAgcGFnZUluZm8ubG9zc2xlc3MgPSAhIShwYWdlU2VnbWVudEZsYWdzICYgMSk7CiAgICAgIHBhZ2VJbmZvLnJlZmluZW1lbnQgPSAhIShwYWdlU2VnbWVudEZsYWdzICYgMik7CiAgICAgIHBhZ2VJbmZvLmRlZmF1bHRQaXhlbFZhbHVlID0gcGFnZVNlZ21lbnRGbGFncyA+PiAyICYgMTsKICAgICAgcGFnZUluZm8uY29tYmluYXRpb25PcGVyYXRvciA9IHBhZ2VTZWdtZW50RmxhZ3MgPj4gMyAmIDM7CiAgICAgIHBhZ2VJbmZvLnJlcXVpcmVzQnVmZmVyID0gISEocGFnZVNlZ21lbnRGbGFncyAmIDMyKTsKICAgICAgcGFnZUluZm8uY29tYmluYXRpb25PcGVyYXRvck92ZXJyaWRlID0gISEocGFnZVNlZ21lbnRGbGFncyAmIDY0KTsKICAgICAgYXJncyA9IFtwYWdlSW5mb107CiAgICAgIGJyZWFrOwogICAgY2FzZSA0OToKICAgICAgYnJlYWs7CiAgICBjYXNlIDUwOgogICAgICBicmVhazsKICAgIGNhc2UgNTE6CiAgICAgIGJyZWFrOwogICAgY2FzZSA1MzoKICAgICAgYXJncyA9IFtoZWFkZXIubnVtYmVyLCBkYXRhLCBwb3NpdGlvbiwgZW5kXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDYyOgogICAgICBicmVhazsKICAgIGRlZmF1bHQ6CiAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKGBzZWdtZW50IHR5cGUgJHtoZWFkZXIudHlwZU5hbWV9KCR7aGVhZGVyLnR5cGV9KSBpcyBub3QgaW1wbGVtZW50ZWRgKTsKICB9CiAgY29uc3QgY2FsbGJhY2tOYW1lID0gIm9uIiArIGhlYWRlci50eXBlTmFtZTsKICBpZiAoY2FsbGJhY2tOYW1lIGluIHZpc2l0b3IpIHsKICAgIHZpc2l0b3JbY2FsbGJhY2tOYW1lXS5hcHBseSh2aXNpdG9yLCBhcmdzKTsKICB9Cn0KZnVuY3Rpb24gcHJvY2Vzc1NlZ21lbnRzKHNlZ21lbnRzLCB2aXNpdG9yKSB7CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gc2VnbWVudHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgcHJvY2Vzc1NlZ21lbnQoc2VnbWVudHNbaV0sIHZpc2l0b3IpOwogIH0KfQpmdW5jdGlvbiBwYXJzZUpiaWcyQ2h1bmtzKGNodW5rcykgewogIGNvbnN0IHZpc2l0b3IgPSBuZXcgU2ltcGxlU2VnbWVudFZpc2l0b3IoKTsKICBmb3IgKGxldCBpID0gMCwgaWkgPSBjaHVua3MubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgY29uc3QgY2h1bmsgPSBjaHVua3NbaV07CiAgICBjb25zdCBzZWdtZW50cyA9IHJlYWRTZWdtZW50cyh7fSwgY2h1bmsuZGF0YSwgY2h1bmsuc3RhcnQsIGNodW5rLmVuZCk7CiAgICBwcm9jZXNzU2VnbWVudHMoc2VnbWVudHMsIHZpc2l0b3IpOwogIH0KICByZXR1cm4gdmlzaXRvci5idWZmZXI7Cn0KY2xhc3MgU2ltcGxlU2VnbWVudFZpc2l0b3IgewogIG9uUGFnZUluZm9ybWF0aW9uKGluZm8pIHsKICAgIHRoaXMuY3VycmVudFBhZ2VJbmZvID0gaW5mbzsKICAgIGNvbnN0IHJvd1NpemUgPSBpbmZvLndpZHRoICsgNyA+PiAzOwogICAgY29uc3QgYnVmZmVyID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHJvd1NpemUgKiBpbmZvLmhlaWdodCk7CiAgICBpZiAoaW5mby5kZWZhdWx0UGl4ZWxWYWx1ZSkgewogICAgICBidWZmZXIuZmlsbCgweGZmKTsKICAgIH0KICAgIHRoaXMuYnVmZmVyID0gYnVmZmVyOwogIH0KICBkcmF3Qml0bWFwKHJlZ2lvbkluZm8sIGJpdG1hcCkgewogICAgY29uc3QgcGFnZUluZm8gPSB0aGlzLmN1cnJlbnRQYWdlSW5mbzsKICAgIGNvbnN0IHdpZHRoID0gcmVnaW9uSW5mby53aWR0aCwKICAgICAgaGVpZ2h0ID0gcmVnaW9uSW5mby5oZWlnaHQ7CiAgICBjb25zdCByb3dTaXplID0gcGFnZUluZm8ud2lkdGggKyA3ID4+IDM7CiAgICBjb25zdCBjb21iaW5hdGlvbk9wZXJhdG9yID0gcGFnZUluZm8uY29tYmluYXRpb25PcGVyYXRvck92ZXJyaWRlID8gcmVnaW9uSW5mby5jb21iaW5hdGlvbk9wZXJhdG9yIDogcGFnZUluZm8uY29tYmluYXRpb25PcGVyYXRvcjsKICAgIGNvbnN0IGJ1ZmZlciA9IHRoaXMuYnVmZmVyOwogICAgY29uc3QgbWFzazAgPSAxMjggPj4gKHJlZ2lvbkluZm8ueCAmIDcpOwogICAgbGV0IG9mZnNldDAgPSByZWdpb25JbmZvLnkgKiByb3dTaXplICsgKHJlZ2lvbkluZm8ueCA+PiAzKTsKICAgIGxldCBpLCBqLCBtYXNrLCBvZmZzZXQ7CiAgICBzd2l0Y2ggKGNvbWJpbmF0aW9uT3BlcmF0b3IpIHsKICAgICAgY2FzZSAwOgogICAgICAgIGZvciAoaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykgewogICAgICAgICAgbWFzayA9IG1hc2swOwogICAgICAgICAgb2Zmc2V0ID0gb2Zmc2V0MDsKICAgICAgICAgIGZvciAoaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7CiAgICAgICAgICAgIGlmIChiaXRtYXBbaV1bal0pIHsKICAgICAgICAgICAgICBidWZmZXJbb2Zmc2V0XSB8PSBtYXNrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG1hc2sgPj49IDE7CiAgICAgICAgICAgIGlmICghbWFzaykgewogICAgICAgICAgICAgIG1hc2sgPSAxMjg7CiAgICAgICAgICAgICAgb2Zmc2V0Kys7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIG9mZnNldDAgKz0gcm93U2l6ZTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMjoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgaGVpZ2h0OyBpKyspIHsKICAgICAgICAgIG1hc2sgPSBtYXNrMDsKICAgICAgICAgIG9mZnNldCA9IG9mZnNldDA7CiAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgd2lkdGg7IGorKykgewogICAgICAgICAgICBpZiAoYml0bWFwW2ldW2pdKSB7CiAgICAgICAgICAgICAgYnVmZmVyW29mZnNldF0gXj0gbWFzazsKICAgICAgICAgICAgfQogICAgICAgICAgICBtYXNrID4+PSAxOwogICAgICAgICAgICBpZiAoIW1hc2spIHsKICAgICAgICAgICAgICBtYXNrID0gMTI4OwogICAgICAgICAgICAgIG9mZnNldCsrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBvZmZzZXQwICs9IHJvd1NpemU7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKGBvcGVyYXRvciAke2NvbWJpbmF0aW9uT3BlcmF0b3J9IGlzIG5vdCBzdXBwb3J0ZWRgKTsKICAgIH0KICB9CiAgb25JbW1lZGlhdGVHZW5lcmljUmVnaW9uKHJlZ2lvbiwgZGF0YSwgc3RhcnQsIGVuZCkgewogICAgY29uc3QgcmVnaW9uSW5mbyA9IHJlZ2lvbi5pbmZvOwogICAgY29uc3QgZGVjb2RpbmdDb250ZXh0ID0gbmV3IERlY29kaW5nQ29udGV4dChkYXRhLCBzdGFydCwgZW5kKTsKICAgIGNvbnN0IGJpdG1hcCA9IGRlY29kZUJpdG1hcChyZWdpb24ubW1yLCByZWdpb25JbmZvLndpZHRoLCByZWdpb25JbmZvLmhlaWdodCwgcmVnaW9uLnRlbXBsYXRlLCByZWdpb24ucHJlZGljdGlvbiwgbnVsbCwgcmVnaW9uLmF0LCBkZWNvZGluZ0NvbnRleHQpOwogICAgdGhpcy5kcmF3Qml0bWFwKHJlZ2lvbkluZm8sIGJpdG1hcCk7CiAgfQogIG9uSW1tZWRpYXRlTG9zc2xlc3NHZW5lcmljUmVnaW9uKCkgewogICAgdGhpcy5vbkltbWVkaWF0ZUdlbmVyaWNSZWdpb24oLi4uYXJndW1lbnRzKTsKICB9CiAgb25TeW1ib2xEaWN0aW9uYXJ5KGRpY3Rpb25hcnksIGN1cnJlbnRTZWdtZW50LCByZWZlcnJlZFNlZ21lbnRzLCBkYXRhLCBzdGFydCwgZW5kKSB7CiAgICBsZXQgaHVmZm1hblRhYmxlcywgaHVmZm1hbklucHV0OwogICAgaWYgKGRpY3Rpb25hcnkuaHVmZm1hbikgewogICAgICBodWZmbWFuVGFibGVzID0gZ2V0U3ltYm9sRGljdGlvbmFyeUh1ZmZtYW5UYWJsZXMoZGljdGlvbmFyeSwgcmVmZXJyZWRTZWdtZW50cywgdGhpcy5jdXN0b21UYWJsZXMpOwogICAgICBodWZmbWFuSW5wdXQgPSBuZXcgUmVhZGVyKGRhdGEsIHN0YXJ0LCBlbmQpOwogICAgfQogICAgbGV0IHN5bWJvbHMgPSB0aGlzLnN5bWJvbHM7CiAgICBpZiAoIXN5bWJvbHMpIHsKICAgICAgdGhpcy5zeW1ib2xzID0gc3ltYm9scyA9IHt9OwogICAgfQogICAgY29uc3QgaW5wdXRTeW1ib2xzID0gW107CiAgICBmb3IgKGNvbnN0IHJlZmVycmVkU2VnbWVudCBvZiByZWZlcnJlZFNlZ21lbnRzKSB7CiAgICAgIGNvbnN0IHJlZmVycmVkU3ltYm9scyA9IHN5bWJvbHNbcmVmZXJyZWRTZWdtZW50XTsKICAgICAgaWYgKHJlZmVycmVkU3ltYm9scykgewogICAgICAgIGlucHV0U3ltYm9scy5wdXNoKC4uLnJlZmVycmVkU3ltYm9scyk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGRlY29kaW5nQ29udGV4dCA9IG5ldyBEZWNvZGluZ0NvbnRleHQoZGF0YSwgc3RhcnQsIGVuZCk7CiAgICBzeW1ib2xzW2N1cnJlbnRTZWdtZW50XSA9IGRlY29kZVN5bWJvbERpY3Rpb25hcnkoZGljdGlvbmFyeS5odWZmbWFuLCBkaWN0aW9uYXJ5LnJlZmluZW1lbnQsIGlucHV0U3ltYm9scywgZGljdGlvbmFyeS5udW1iZXJPZk5ld1N5bWJvbHMsIGRpY3Rpb25hcnkubnVtYmVyT2ZFeHBvcnRlZFN5bWJvbHMsIGh1ZmZtYW5UYWJsZXMsIGRpY3Rpb25hcnkudGVtcGxhdGUsIGRpY3Rpb25hcnkuYXQsIGRpY3Rpb25hcnkucmVmaW5lbWVudFRlbXBsYXRlLCBkaWN0aW9uYXJ5LnJlZmluZW1lbnRBdCwgZGVjb2RpbmdDb250ZXh0LCBodWZmbWFuSW5wdXQpOwogIH0KICBvbkltbWVkaWF0ZVRleHRSZWdpb24ocmVnaW9uLCByZWZlcnJlZFNlZ21lbnRzLCBkYXRhLCBzdGFydCwgZW5kKSB7CiAgICBjb25zdCByZWdpb25JbmZvID0gcmVnaW9uLmluZm87CiAgICBsZXQgaHVmZm1hblRhYmxlcywgaHVmZm1hbklucHV0OwogICAgY29uc3Qgc3ltYm9scyA9IHRoaXMuc3ltYm9sczsKICAgIGNvbnN0IGlucHV0U3ltYm9scyA9IFtdOwogICAgZm9yIChjb25zdCByZWZlcnJlZFNlZ21lbnQgb2YgcmVmZXJyZWRTZWdtZW50cykgewogICAgICBjb25zdCByZWZlcnJlZFN5bWJvbHMgPSBzeW1ib2xzW3JlZmVycmVkU2VnbWVudF07CiAgICAgIGlmIChyZWZlcnJlZFN5bWJvbHMpIHsKICAgICAgICBpbnB1dFN5bWJvbHMucHVzaCguLi5yZWZlcnJlZFN5bWJvbHMpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBzeW1ib2xDb2RlTGVuZ3RoID0gbG9nMihpbnB1dFN5bWJvbHMubGVuZ3RoKTsKICAgIGlmIChyZWdpb24uaHVmZm1hbikgewogICAgICBodWZmbWFuSW5wdXQgPSBuZXcgUmVhZGVyKGRhdGEsIHN0YXJ0LCBlbmQpOwogICAgICBodWZmbWFuVGFibGVzID0gZ2V0VGV4dFJlZ2lvbkh1ZmZtYW5UYWJsZXMocmVnaW9uLCByZWZlcnJlZFNlZ21lbnRzLCB0aGlzLmN1c3RvbVRhYmxlcywgaW5wdXRTeW1ib2xzLmxlbmd0aCwgaHVmZm1hbklucHV0KTsKICAgIH0KICAgIGNvbnN0IGRlY29kaW5nQ29udGV4dCA9IG5ldyBEZWNvZGluZ0NvbnRleHQoZGF0YSwgc3RhcnQsIGVuZCk7CiAgICBjb25zdCBiaXRtYXAgPSBkZWNvZGVUZXh0UmVnaW9uKHJlZ2lvbi5odWZmbWFuLCByZWdpb24ucmVmaW5lbWVudCwgcmVnaW9uSW5mby53aWR0aCwgcmVnaW9uSW5mby5oZWlnaHQsIHJlZ2lvbi5kZWZhdWx0UGl4ZWxWYWx1ZSwgcmVnaW9uLm51bWJlck9mU3ltYm9sSW5zdGFuY2VzLCByZWdpb24uc3RyaXBTaXplLCBpbnB1dFN5bWJvbHMsIHN5bWJvbENvZGVMZW5ndGgsIHJlZ2lvbi50cmFuc3Bvc2VkLCByZWdpb24uZHNPZmZzZXQsIHJlZ2lvbi5yZWZlcmVuY2VDb3JuZXIsIHJlZ2lvbi5jb21iaW5hdGlvbk9wZXJhdG9yLCBodWZmbWFuVGFibGVzLCByZWdpb24ucmVmaW5lbWVudFRlbXBsYXRlLCByZWdpb24ucmVmaW5lbWVudEF0LCBkZWNvZGluZ0NvbnRleHQsIHJlZ2lvbi5sb2dTdHJpcFNpemUsIGh1ZmZtYW5JbnB1dCk7CiAgICB0aGlzLmRyYXdCaXRtYXAocmVnaW9uSW5mbywgYml0bWFwKTsKICB9CiAgb25JbW1lZGlhdGVMb3NzbGVzc1RleHRSZWdpb24oKSB7CiAgICB0aGlzLm9uSW1tZWRpYXRlVGV4dFJlZ2lvbiguLi5hcmd1bWVudHMpOwogIH0KICBvblBhdHRlcm5EaWN0aW9uYXJ5KGRpY3Rpb25hcnksIGN1cnJlbnRTZWdtZW50LCBkYXRhLCBzdGFydCwgZW5kKSB7CiAgICBsZXQgcGF0dGVybnMgPSB0aGlzLnBhdHRlcm5zOwogICAgaWYgKCFwYXR0ZXJucykgewogICAgICB0aGlzLnBhdHRlcm5zID0gcGF0dGVybnMgPSB7fTsKICAgIH0KICAgIGNvbnN0IGRlY29kaW5nQ29udGV4dCA9IG5ldyBEZWNvZGluZ0NvbnRleHQoZGF0YSwgc3RhcnQsIGVuZCk7CiAgICBwYXR0ZXJuc1tjdXJyZW50U2VnbWVudF0gPSBkZWNvZGVQYXR0ZXJuRGljdGlvbmFyeShkaWN0aW9uYXJ5Lm1tciwgZGljdGlvbmFyeS5wYXR0ZXJuV2lkdGgsIGRpY3Rpb25hcnkucGF0dGVybkhlaWdodCwgZGljdGlvbmFyeS5tYXhQYXR0ZXJuSW5kZXgsIGRpY3Rpb25hcnkudGVtcGxhdGUsIGRlY29kaW5nQ29udGV4dCk7CiAgfQogIG9uSW1tZWRpYXRlSGFsZnRvbmVSZWdpb24ocmVnaW9uLCByZWZlcnJlZFNlZ21lbnRzLCBkYXRhLCBzdGFydCwgZW5kKSB7CiAgICBjb25zdCBwYXR0ZXJucyA9IHRoaXMucGF0dGVybnNbcmVmZXJyZWRTZWdtZW50c1swXV07CiAgICBjb25zdCByZWdpb25JbmZvID0gcmVnaW9uLmluZm87CiAgICBjb25zdCBkZWNvZGluZ0NvbnRleHQgPSBuZXcgRGVjb2RpbmdDb250ZXh0KGRhdGEsIHN0YXJ0LCBlbmQpOwogICAgY29uc3QgYml0bWFwID0gZGVjb2RlSGFsZnRvbmVSZWdpb24ocmVnaW9uLm1tciwgcGF0dGVybnMsIHJlZ2lvbi50ZW1wbGF0ZSwgcmVnaW9uSW5mby53aWR0aCwgcmVnaW9uSW5mby5oZWlnaHQsIHJlZ2lvbi5kZWZhdWx0UGl4ZWxWYWx1ZSwgcmVnaW9uLmVuYWJsZVNraXAsIHJlZ2lvbi5jb21iaW5hdGlvbk9wZXJhdG9yLCByZWdpb24uZ3JpZFdpZHRoLCByZWdpb24uZ3JpZEhlaWdodCwgcmVnaW9uLmdyaWRPZmZzZXRYLCByZWdpb24uZ3JpZE9mZnNldFksIHJlZ2lvbi5ncmlkVmVjdG9yWCwgcmVnaW9uLmdyaWRWZWN0b3JZLCBkZWNvZGluZ0NvbnRleHQpOwogICAgdGhpcy5kcmF3Qml0bWFwKHJlZ2lvbkluZm8sIGJpdG1hcCk7CiAgfQogIG9uSW1tZWRpYXRlTG9zc2xlc3NIYWxmdG9uZVJlZ2lvbigpIHsKICAgIHRoaXMub25JbW1lZGlhdGVIYWxmdG9uZVJlZ2lvbiguLi5hcmd1bWVudHMpOwogIH0KICBvblRhYmxlcyhjdXJyZW50U2VnbWVudCwgZGF0YSwgc3RhcnQsIGVuZCkgewogICAgbGV0IGN1c3RvbVRhYmxlcyA9IHRoaXMuY3VzdG9tVGFibGVzOwogICAgaWYgKCFjdXN0b21UYWJsZXMpIHsKICAgICAgdGhpcy5jdXN0b21UYWJsZXMgPSBjdXN0b21UYWJsZXMgPSB7fTsKICAgIH0KICAgIGN1c3RvbVRhYmxlc1tjdXJyZW50U2VnbWVudF0gPSBkZWNvZGVUYWJsZXNTZWdtZW50KGRhdGEsIHN0YXJ0LCBlbmQpOwogIH0KfQpjbGFzcyBIdWZmbWFuTGluZSB7CiAgY29uc3RydWN0b3IobGluZURhdGEpIHsKICAgIGlmIChsaW5lRGF0YS5sZW5ndGggPT09IDIpIHsKICAgICAgdGhpcy5pc09PQiA9IHRydWU7CiAgICAgIHRoaXMucmFuZ2VMb3cgPSAwOwogICAgICB0aGlzLnByZWZpeExlbmd0aCA9IGxpbmVEYXRhWzBdOwogICAgICB0aGlzLnJhbmdlTGVuZ3RoID0gMDsKICAgICAgdGhpcy5wcmVmaXhDb2RlID0gbGluZURhdGFbMV07CiAgICAgIHRoaXMuaXNMb3dlclJhbmdlID0gZmFsc2U7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmlzT09CID0gZmFsc2U7CiAgICAgIHRoaXMucmFuZ2VMb3cgPSBsaW5lRGF0YVswXTsKICAgICAgdGhpcy5wcmVmaXhMZW5ndGggPSBsaW5lRGF0YVsxXTsKICAgICAgdGhpcy5yYW5nZUxlbmd0aCA9IGxpbmVEYXRhWzJdOwogICAgICB0aGlzLnByZWZpeENvZGUgPSBsaW5lRGF0YVszXTsKICAgICAgdGhpcy5pc0xvd2VyUmFuZ2UgPSBsaW5lRGF0YVs0XSA9PT0gImxvd2VyIjsKICAgIH0KICB9Cn0KY2xhc3MgSHVmZm1hblRyZWVOb2RlIHsKICBjb25zdHJ1Y3RvcihsaW5lKSB7CiAgICB0aGlzLmNoaWxkcmVuID0gW107CiAgICBpZiAobGluZSkgewogICAgICB0aGlzLmlzTGVhZiA9IHRydWU7CiAgICAgIHRoaXMucmFuZ2VMZW5ndGggPSBsaW5lLnJhbmdlTGVuZ3RoOwogICAgICB0aGlzLnJhbmdlTG93ID0gbGluZS5yYW5nZUxvdzsKICAgICAgdGhpcy5pc0xvd2VyUmFuZ2UgPSBsaW5lLmlzTG93ZXJSYW5nZTsKICAgICAgdGhpcy5pc09PQiA9IGxpbmUuaXNPT0I7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmlzTGVhZiA9IGZhbHNlOwogICAgfQogIH0KICBidWlsZFRyZWUobGluZSwgc2hpZnQpIHsKICAgIGNvbnN0IGJpdCA9IGxpbmUucHJlZml4Q29kZSA+PiBzaGlmdCAmIDE7CiAgICBpZiAoc2hpZnQgPD0gMCkgewogICAgICB0aGlzLmNoaWxkcmVuW2JpdF0gPSBuZXcgSHVmZm1hblRyZWVOb2RlKGxpbmUpOwogICAgfSBlbHNlIHsKICAgICAgbGV0IG5vZGUgPSB0aGlzLmNoaWxkcmVuW2JpdF07CiAgICAgIGlmICghbm9kZSkgewogICAgICAgIHRoaXMuY2hpbGRyZW5bYml0XSA9IG5vZGUgPSBuZXcgSHVmZm1hblRyZWVOb2RlKG51bGwpOwogICAgICB9CiAgICAgIG5vZGUuYnVpbGRUcmVlKGxpbmUsIHNoaWZ0IC0gMSk7CiAgICB9CiAgfQogIGRlY29kZU5vZGUocmVhZGVyKSB7CiAgICBpZiAodGhpcy5pc0xlYWYpIHsKICAgICAgaWYgKHRoaXMuaXNPT0IpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBjb25zdCBodE9mZnNldCA9IHJlYWRlci5yZWFkQml0cyh0aGlzLnJhbmdlTGVuZ3RoKTsKICAgICAgcmV0dXJuIHRoaXMucmFuZ2VMb3cgKyAodGhpcy5pc0xvd2VyUmFuZ2UgPyAtaHRPZmZzZXQgOiBodE9mZnNldCk7CiAgICB9CiAgICBjb25zdCBub2RlID0gdGhpcy5jaGlsZHJlbltyZWFkZXIucmVhZEJpdCgpXTsKICAgIGlmICghbm9kZSkgewogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCBIdWZmbWFuIGRhdGEiKTsKICAgIH0KICAgIHJldHVybiBub2RlLmRlY29kZU5vZGUocmVhZGVyKTsKICB9Cn0KY2xhc3MgSHVmZm1hblRhYmxlIHsKICBjb25zdHJ1Y3RvcihsaW5lcywgcHJlZml4Q29kZXNEb25lKSB7CiAgICBpZiAoIXByZWZpeENvZGVzRG9uZSkgewogICAgICB0aGlzLmFzc2lnblByZWZpeENvZGVzKGxpbmVzKTsKICAgIH0KICAgIHRoaXMucm9vdE5vZGUgPSBuZXcgSHVmZm1hblRyZWVOb2RlKG51bGwpOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gbGluZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBsaW5lID0gbGluZXNbaV07CiAgICAgIGlmIChsaW5lLnByZWZpeExlbmd0aCA+IDApIHsKICAgICAgICB0aGlzLnJvb3ROb2RlLmJ1aWxkVHJlZShsaW5lLCBsaW5lLnByZWZpeExlbmd0aCAtIDEpOwogICAgICB9CiAgICB9CiAgfQogIGRlY29kZShyZWFkZXIpIHsKICAgIHJldHVybiB0aGlzLnJvb3ROb2RlLmRlY29kZU5vZGUocmVhZGVyKTsKICB9CiAgYXNzaWduUHJlZml4Q29kZXMobGluZXMpIHsKICAgIGNvbnN0IGxpbmVzTGVuZ3RoID0gbGluZXMubGVuZ3RoOwogICAgbGV0IHByZWZpeExlbmd0aE1heCA9IDA7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzTGVuZ3RoOyBpKyspIHsKICAgICAgcHJlZml4TGVuZ3RoTWF4ID0gTWF0aC5tYXgocHJlZml4TGVuZ3RoTWF4LCBsaW5lc1tpXS5wcmVmaXhMZW5ndGgpOwogICAgfQogICAgY29uc3QgaGlzdG9ncmFtID0gbmV3IFVpbnQzMkFycmF5KHByZWZpeExlbmd0aE1heCArIDEpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lc0xlbmd0aDsgaSsrKSB7CiAgICAgIGhpc3RvZ3JhbVtsaW5lc1tpXS5wcmVmaXhMZW5ndGhdKys7CiAgICB9CiAgICBsZXQgY3VycmVudExlbmd0aCA9IDEsCiAgICAgIGZpcnN0Q29kZSA9IDAsCiAgICAgIGN1cnJlbnRDb2RlLAogICAgICBjdXJyZW50VGVtcCwKICAgICAgbGluZTsKICAgIGhpc3RvZ3JhbVswXSA9IDA7CiAgICB3aGlsZSAoY3VycmVudExlbmd0aCA8PSBwcmVmaXhMZW5ndGhNYXgpIHsKICAgICAgZmlyc3RDb2RlID0gZmlyc3RDb2RlICsgaGlzdG9ncmFtW2N1cnJlbnRMZW5ndGggLSAxXSA8PCAxOwogICAgICBjdXJyZW50Q29kZSA9IGZpcnN0Q29kZTsKICAgICAgY3VycmVudFRlbXAgPSAwOwogICAgICB3aGlsZSAoY3VycmVudFRlbXAgPCBsaW5lc0xlbmd0aCkgewogICAgICAgIGxpbmUgPSBsaW5lc1tjdXJyZW50VGVtcF07CiAgICAgICAgaWYgKGxpbmUucHJlZml4TGVuZ3RoID09PSBjdXJyZW50TGVuZ3RoKSB7CiAgICAgICAgICBsaW5lLnByZWZpeENvZGUgPSBjdXJyZW50Q29kZTsKICAgICAgICAgIGN1cnJlbnRDb2RlKys7CiAgICAgICAgfQogICAgICAgIGN1cnJlbnRUZW1wKys7CiAgICAgIH0KICAgICAgY3VycmVudExlbmd0aCsrOwogICAgfQogIH0KfQpmdW5jdGlvbiBkZWNvZGVUYWJsZXNTZWdtZW50KGRhdGEsIHN0YXJ0LCBlbmQpIHsKICBjb25zdCBmbGFncyA9IGRhdGFbc3RhcnRdOwogIGNvbnN0IGxvd2VzdFZhbHVlID0gcmVhZFVpbnQzMihkYXRhLCBzdGFydCArIDEpICYgMHhmZmZmZmZmZjsKICBjb25zdCBoaWdoZXN0VmFsdWUgPSByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgNSkgJiAweGZmZmZmZmZmOwogIGNvbnN0IHJlYWRlciA9IG5ldyBSZWFkZXIoZGF0YSwgc3RhcnQgKyA5LCBlbmQpOwogIGNvbnN0IHByZWZpeFNpemVCaXRzID0gKGZsYWdzID4+IDEgJiA3KSArIDE7CiAgY29uc3QgcmFuZ2VTaXplQml0cyA9IChmbGFncyA+PiA0ICYgNykgKyAxOwogIGNvbnN0IGxpbmVzID0gW107CiAgbGV0IHByZWZpeExlbmd0aCwKICAgIHJhbmdlTGVuZ3RoLAogICAgY3VycmVudFJhbmdlTG93ID0gbG93ZXN0VmFsdWU7CiAgZG8gewogICAgcHJlZml4TGVuZ3RoID0gcmVhZGVyLnJlYWRCaXRzKHByZWZpeFNpemVCaXRzKTsKICAgIHJhbmdlTGVuZ3RoID0gcmVhZGVyLnJlYWRCaXRzKHJhbmdlU2l6ZUJpdHMpOwogICAgbGluZXMucHVzaChuZXcgSHVmZm1hbkxpbmUoW2N1cnJlbnRSYW5nZUxvdywgcHJlZml4TGVuZ3RoLCByYW5nZUxlbmd0aCwgMF0pKTsKICAgIGN1cnJlbnRSYW5nZUxvdyArPSAxIDw8IHJhbmdlTGVuZ3RoOwogIH0gd2hpbGUgKGN1cnJlbnRSYW5nZUxvdyA8IGhpZ2hlc3RWYWx1ZSk7CiAgcHJlZml4TGVuZ3RoID0gcmVhZGVyLnJlYWRCaXRzKHByZWZpeFNpemVCaXRzKTsKICBsaW5lcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbbG93ZXN0VmFsdWUgLSAxLCBwcmVmaXhMZW5ndGgsIDMyLCAwLCAibG93ZXIiXSkpOwogIHByZWZpeExlbmd0aCA9IHJlYWRlci5yZWFkQml0cyhwcmVmaXhTaXplQml0cyk7CiAgbGluZXMucHVzaChuZXcgSHVmZm1hbkxpbmUoW2hpZ2hlc3RWYWx1ZSwgcHJlZml4TGVuZ3RoLCAzMiwgMF0pKTsKICBpZiAoZmxhZ3MgJiAxKSB7CiAgICBwcmVmaXhMZW5ndGggPSByZWFkZXIucmVhZEJpdHMocHJlZml4U2l6ZUJpdHMpOwogICAgbGluZXMucHVzaChuZXcgSHVmZm1hbkxpbmUoW3ByZWZpeExlbmd0aCwgMF0pKTsKICB9CiAgcmV0dXJuIG5ldyBIdWZmbWFuVGFibGUobGluZXMsIGZhbHNlKTsKfQpjb25zdCBzdGFuZGFyZFRhYmxlc0NhY2hlID0ge307CmZ1bmN0aW9uIGdldFN0YW5kYXJkVGFibGUobnVtYmVyKSB7CiAgbGV0IHRhYmxlID0gc3RhbmRhcmRUYWJsZXNDYWNoZVtudW1iZXJdOwogIGlmICh0YWJsZSkgewogICAgcmV0dXJuIHRhYmxlOwogIH0KICBsZXQgbGluZXM7CiAgc3dpdGNoIChudW1iZXIpIHsKICAgIGNhc2UgMToKICAgICAgbGluZXMgPSBbWzAsIDEsIDQsIDB4MF0sIFsxNiwgMiwgOCwgMHgyXSwgWzI3MiwgMywgMTYsIDB4Nl0sIFs2NTgwOCwgMywgMzIsIDB4N11dOwogICAgICBicmVhazsKICAgIGNhc2UgMjoKICAgICAgbGluZXMgPSBbWzAsIDEsIDAsIDB4MF0sIFsxLCAyLCAwLCAweDJdLCBbMiwgMywgMCwgMHg2XSwgWzMsIDQsIDMsIDB4ZV0sIFsxMSwgNSwgNiwgMHgxZV0sIFs3NSwgNiwgMzIsIDB4M2VdLCBbNiwgMHgzZl1dOwogICAgICBicmVhazsKICAgIGNhc2UgMzoKICAgICAgbGluZXMgPSBbWy0yNTYsIDgsIDgsIDB4ZmVdLCBbMCwgMSwgMCwgMHgwXSwgWzEsIDIsIDAsIDB4Ml0sIFsyLCAzLCAwLCAweDZdLCBbMywgNCwgMywgMHhlXSwgWzExLCA1LCA2LCAweDFlXSwgWy0yNTcsIDgsIDMyLCAweGZmLCAibG93ZXIiXSwgWzc1LCA3LCAzMiwgMHg3ZV0sIFs2LCAweDNlXV07CiAgICAgIGJyZWFrOwogICAgY2FzZSA0OgogICAgICBsaW5lcyA9IFtbMSwgMSwgMCwgMHgwXSwgWzIsIDIsIDAsIDB4Ml0sIFszLCAzLCAwLCAweDZdLCBbNCwgNCwgMywgMHhlXSwgWzEyLCA1LCA2LCAweDFlXSwgWzc2LCA1LCAzMiwgMHgxZl1dOwogICAgICBicmVhazsKICAgIGNhc2UgNToKICAgICAgbGluZXMgPSBbWy0yNTUsIDcsIDgsIDB4N2VdLCBbMSwgMSwgMCwgMHgwXSwgWzIsIDIsIDAsIDB4Ml0sIFszLCAzLCAwLCAweDZdLCBbNCwgNCwgMywgMHhlXSwgWzEyLCA1LCA2LCAweDFlXSwgWy0yNTYsIDcsIDMyLCAweDdmLCAibG93ZXIiXSwgWzc2LCA2LCAzMiwgMHgzZV1dOwogICAgICBicmVhazsKICAgIGNhc2UgNjoKICAgICAgbGluZXMgPSBbWy0yMDQ4LCA1LCAxMCwgMHgxY10sIFstMTAyNCwgNCwgOSwgMHg4XSwgWy01MTIsIDQsIDgsIDB4OV0sIFstMjU2LCA0LCA3LCAweGFdLCBbLTEyOCwgNSwgNiwgMHgxZF0sIFstNjQsIDUsIDUsIDB4MWVdLCBbLTMyLCA0LCA1LCAweGJdLCBbMCwgMiwgNywgMHgwXSwgWzEyOCwgMywgNywgMHgyXSwgWzI1NiwgMywgOCwgMHgzXSwgWzUxMiwgNCwgOSwgMHhjXSwgWzEwMjQsIDQsIDEwLCAweGRdLCBbLTIwNDksIDYsIDMyLCAweDNlLCAibG93ZXIiXSwgWzIwNDgsIDYsIDMyLCAweDNmXV07CiAgICAgIGJyZWFrOwogICAgY2FzZSA3OgogICAgICBsaW5lcyA9IFtbLTEwMjQsIDQsIDksIDB4OF0sIFstNTEyLCAzLCA4LCAweDBdLCBbLTI1NiwgNCwgNywgMHg5XSwgWy0xMjgsIDUsIDYsIDB4MWFdLCBbLTY0LCA1LCA1LCAweDFiXSwgWy0zMiwgNCwgNSwgMHhhXSwgWzAsIDQsIDUsIDB4Yl0sIFszMiwgNSwgNSwgMHgxY10sIFs2NCwgNSwgNiwgMHgxZF0sIFsxMjgsIDQsIDcsIDB4Y10sIFsyNTYsIDMsIDgsIDB4MV0sIFs1MTIsIDMsIDksIDB4Ml0sIFsxMDI0LCAzLCAxMCwgMHgzXSwgWy0xMDI1LCA1LCAzMiwgMHgxZSwgImxvd2VyIl0sIFsyMDQ4LCA1LCAzMiwgMHgxZl1dOwogICAgICBicmVhazsKICAgIGNhc2UgODoKICAgICAgbGluZXMgPSBbWy0xNSwgOCwgMywgMHhmY10sIFstNywgOSwgMSwgMHgxZmNdLCBbLTUsIDgsIDEsIDB4ZmRdLCBbLTMsIDksIDAsIDB4MWZkXSwgWy0yLCA3LCAwLCAweDdjXSwgWy0xLCA0LCAwLCAweGFdLCBbMCwgMiwgMSwgMHgwXSwgWzIsIDUsIDAsIDB4MWFdLCBbMywgNiwgMCwgMHgzYV0sIFs0LCAzLCA0LCAweDRdLCBbMjAsIDYsIDEsIDB4M2JdLCBbMjIsIDQsIDQsIDB4Yl0sIFszOCwgNCwgNSwgMHhjXSwgWzcwLCA1LCA2LCAweDFiXSwgWzEzNCwgNSwgNywgMHgxY10sIFsyNjIsIDYsIDcsIDB4M2NdLCBbMzkwLCA3LCA4LCAweDdkXSwgWzY0NiwgNiwgMTAsIDB4M2RdLCBbLTE2LCA5LCAzMiwgMHgxZmUsICJsb3dlciJdLCBbMTY3MCwgOSwgMzIsIDB4MWZmXSwgWzIsIDB4MV1dOwogICAgICBicmVhazsKICAgIGNhc2UgOToKICAgICAgbGluZXMgPSBbWy0zMSwgOCwgNCwgMHhmY10sIFstMTUsIDksIDIsIDB4MWZjXSwgWy0xMSwgOCwgMiwgMHhmZF0sIFstNywgOSwgMSwgMHgxZmRdLCBbLTUsIDcsIDEsIDB4N2NdLCBbLTMsIDQsIDEsIDB4YV0sIFstMSwgMywgMSwgMHgyXSwgWzEsIDMsIDEsIDB4M10sIFszLCA1LCAxLCAweDFhXSwgWzUsIDYsIDEsIDB4M2FdLCBbNywgMywgNSwgMHg0XSwgWzM5LCA2LCAyLCAweDNiXSwgWzQzLCA0LCA1LCAweGJdLCBbNzUsIDQsIDYsIDB4Y10sIFsxMzksIDUsIDcsIDB4MWJdLCBbMjY3LCA1LCA4LCAweDFjXSwgWzUyMywgNiwgOCwgMHgzY10sIFs3NzksIDcsIDksIDB4N2RdLCBbMTI5MSwgNiwgMTEsIDB4M2RdLCBbLTMyLCA5LCAzMiwgMHgxZmUsICJsb3dlciJdLCBbMzMzOSwgOSwgMzIsIDB4MWZmXSwgWzIsIDB4MF1dOwogICAgICBicmVhazsKICAgIGNhc2UgMTA6CiAgICAgIGxpbmVzID0gW1stMjEsIDcsIDQsIDB4N2FdLCBbLTUsIDgsIDAsIDB4ZmNdLCBbLTQsIDcsIDAsIDB4N2JdLCBbLTMsIDUsIDAsIDB4MThdLCBbLTIsIDIsIDIsIDB4MF0sIFsyLCA1LCAwLCAweDE5XSwgWzMsIDYsIDAsIDB4MzZdLCBbNCwgNywgMCwgMHg3Y10sIFs1LCA4LCAwLCAweGZkXSwgWzYsIDIsIDYsIDB4MV0sIFs3MCwgNSwgNSwgMHgxYV0sIFsxMDIsIDYsIDUsIDB4MzddLCBbMTM0LCA2LCA2LCAweDM4XSwgWzE5OCwgNiwgNywgMHgzOV0sIFszMjYsIDYsIDgsIDB4M2FdLCBbNTgyLCA2LCA5LCAweDNiXSwgWzEwOTQsIDYsIDEwLCAweDNjXSwgWzIxMTgsIDcsIDExLCAweDdkXSwgWy0yMiwgOCwgMzIsIDB4ZmUsICJsb3dlciJdLCBbNDE2NiwgOCwgMzIsIDB4ZmZdLCBbMiwgMHgyXV07CiAgICAgIGJyZWFrOwogICAgY2FzZSAxMToKICAgICAgbGluZXMgPSBbWzEsIDEsIDAsIDB4MF0sIFsyLCAyLCAxLCAweDJdLCBbNCwgNCwgMCwgMHhjXSwgWzUsIDQsIDEsIDB4ZF0sIFs3LCA1LCAxLCAweDFjXSwgWzksIDUsIDIsIDB4MWRdLCBbMTMsIDYsIDIsIDB4M2NdLCBbMTcsIDcsIDIsIDB4N2FdLCBbMjEsIDcsIDMsIDB4N2JdLCBbMjksIDcsIDQsIDB4N2NdLCBbNDUsIDcsIDUsIDB4N2RdLCBbNzcsIDcsIDYsIDB4N2VdLCBbMTQxLCA3LCAzMiwgMHg3Zl1dOwogICAgICBicmVhazsKICAgIGNhc2UgMTI6CiAgICAgIGxpbmVzID0gW1sxLCAxLCAwLCAweDBdLCBbMiwgMiwgMCwgMHgyXSwgWzMsIDMsIDEsIDB4Nl0sIFs1LCA1LCAwLCAweDFjXSwgWzYsIDUsIDEsIDB4MWRdLCBbOCwgNiwgMSwgMHgzY10sIFsxMCwgNywgMCwgMHg3YV0sIFsxMSwgNywgMSwgMHg3Yl0sIFsxMywgNywgMiwgMHg3Y10sIFsxNywgNywgMywgMHg3ZF0sIFsyNSwgNywgNCwgMHg3ZV0sIFs0MSwgOCwgNSwgMHhmZV0sIFs3MywgOCwgMzIsIDB4ZmZdXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDEzOgogICAgICBsaW5lcyA9IFtbMSwgMSwgMCwgMHgwXSwgWzIsIDMsIDAsIDB4NF0sIFszLCA0LCAwLCAweGNdLCBbNCwgNSwgMCwgMHgxY10sIFs1LCA0LCAxLCAweGRdLCBbNywgMywgMywgMHg1XSwgWzE1LCA2LCAxLCAweDNhXSwgWzE3LCA2LCAyLCAweDNiXSwgWzIxLCA2LCAzLCAweDNjXSwgWzI5LCA2LCA0LCAweDNkXSwgWzQ1LCA2LCA1LCAweDNlXSwgWzc3LCA3LCA2LCAweDdlXSwgWzE0MSwgNywgMzIsIDB4N2ZdXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDE0OgogICAgICBsaW5lcyA9IFtbLTIsIDMsIDAsIDB4NF0sIFstMSwgMywgMCwgMHg1XSwgWzAsIDEsIDAsIDB4MF0sIFsxLCAzLCAwLCAweDZdLCBbMiwgMywgMCwgMHg3XV07CiAgICAgIGJyZWFrOwogICAgY2FzZSAxNToKICAgICAgbGluZXMgPSBbWy0yNCwgNywgNCwgMHg3Y10sIFstOCwgNiwgMiwgMHgzY10sIFstNCwgNSwgMSwgMHgxY10sIFstMiwgNCwgMCwgMHhjXSwgWy0xLCAzLCAwLCAweDRdLCBbMCwgMSwgMCwgMHgwXSwgWzEsIDMsIDAsIDB4NV0sIFsyLCA0LCAwLCAweGRdLCBbMywgNSwgMSwgMHgxZF0sIFs1LCA2LCAyLCAweDNkXSwgWzksIDcsIDQsIDB4N2RdLCBbLTI1LCA3LCAzMiwgMHg3ZSwgImxvd2VyIl0sIFsyNSwgNywgMzIsIDB4N2ZdXTsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcihgc3RhbmRhcmQgdGFibGUgQi4ke251bWJlcn0gZG9lcyBub3QgZXhpc3RgKTsKICB9CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gbGluZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgbGluZXNbaV0gPSBuZXcgSHVmZm1hbkxpbmUobGluZXNbaV0pOwogIH0KICB0YWJsZSA9IG5ldyBIdWZmbWFuVGFibGUobGluZXMsIHRydWUpOwogIHN0YW5kYXJkVGFibGVzQ2FjaGVbbnVtYmVyXSA9IHRhYmxlOwogIHJldHVybiB0YWJsZTsKfQpjbGFzcyBSZWFkZXIgewogIGNvbnN0cnVjdG9yKGRhdGEsIHN0YXJ0LCBlbmQpIHsKICAgIHRoaXMuZGF0YSA9IGRhdGE7CiAgICB0aGlzLnN0YXJ0ID0gc3RhcnQ7CiAgICB0aGlzLmVuZCA9IGVuZDsKICAgIHRoaXMucG9zaXRpb24gPSBzdGFydDsKICAgIHRoaXMuc2hpZnQgPSAtMTsKICAgIHRoaXMuY3VycmVudEJ5dGUgPSAwOwogIH0KICByZWFkQml0KCkgewogICAgaWYgKHRoaXMuc2hpZnQgPCAwKSB7CiAgICAgIGlmICh0aGlzLnBvc2l0aW9uID49IHRoaXMuZW5kKSB7CiAgICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImVuZCBvZiBkYXRhIHdoaWxlIHJlYWRpbmcgYml0Iik7CiAgICAgIH0KICAgICAgdGhpcy5jdXJyZW50Qnl0ZSA9IHRoaXMuZGF0YVt0aGlzLnBvc2l0aW9uKytdOwogICAgICB0aGlzLnNoaWZ0ID0gNzsKICAgIH0KICAgIGNvbnN0IGJpdCA9IHRoaXMuY3VycmVudEJ5dGUgPj4gdGhpcy5zaGlmdCAmIDE7CiAgICB0aGlzLnNoaWZ0LS07CiAgICByZXR1cm4gYml0OwogIH0KICByZWFkQml0cyhudW1CaXRzKSB7CiAgICBsZXQgcmVzdWx0ID0gMCwKICAgICAgaTsKICAgIGZvciAoaSA9IG51bUJpdHMgLSAxOyBpID49IDA7IGktLSkgewogICAgICByZXN1bHQgfD0gdGhpcy5yZWFkQml0KCkgPDwgaTsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGJ5dGVBbGlnbigpIHsKICAgIHRoaXMuc2hpZnQgPSAtMTsKICB9CiAgbmV4dCgpIHsKICAgIGlmICh0aGlzLnBvc2l0aW9uID49IHRoaXMuZW5kKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIHJldHVybiB0aGlzLmRhdGFbdGhpcy5wb3NpdGlvbisrXTsKICB9Cn0KZnVuY3Rpb24gZ2V0Q3VzdG9tSHVmZm1hblRhYmxlKGluZGV4LCByZWZlcnJlZFRvLCBjdXN0b21UYWJsZXMpIHsKICBsZXQgY3VycmVudEluZGV4ID0gMDsKICBmb3IgKGxldCBpID0gMCwgaWkgPSByZWZlcnJlZFRvLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IHRhYmxlID0gY3VzdG9tVGFibGVzW3JlZmVycmVkVG9baV1dOwogICAgaWYgKHRhYmxlKSB7CiAgICAgIGlmIChpbmRleCA9PT0gY3VycmVudEluZGV4KSB7CiAgICAgICAgcmV0dXJuIHRhYmxlOwogICAgICB9CiAgICAgIGN1cnJlbnRJbmRleCsrOwogICAgfQogIH0KICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiY2FuJ3QgZmluZCBjdXN0b20gSHVmZm1hbiB0YWJsZSIpOwp9CmZ1bmN0aW9uIGdldFRleHRSZWdpb25IdWZmbWFuVGFibGVzKHRleHRSZWdpb24sIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcywgbnVtYmVyT2ZTeW1ib2xzLCByZWFkZXIpIHsKICBjb25zdCBjb2RlcyA9IFtdOwogIGZvciAobGV0IGkgPSAwOyBpIDw9IDM0OyBpKyspIHsKICAgIGNvbnN0IGNvZGVMZW5ndGggPSByZWFkZXIucmVhZEJpdHMoNCk7CiAgICBjb2Rlcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbaSwgY29kZUxlbmd0aCwgMCwgMF0pKTsKICB9CiAgY29uc3QgcnVuQ29kZXNUYWJsZSA9IG5ldyBIdWZmbWFuVGFibGUoY29kZXMsIGZhbHNlKTsKICBjb2Rlcy5sZW5ndGggPSAwOwogIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZTeW1ib2xzOykgewogICAgY29uc3QgY29kZUxlbmd0aCA9IHJ1bkNvZGVzVGFibGUuZGVjb2RlKHJlYWRlcik7CiAgICBpZiAoY29kZUxlbmd0aCA+PSAzMikgewogICAgICBsZXQgcmVwZWF0ZWRMZW5ndGgsIG51bWJlck9mUmVwZWF0cywgajsKICAgICAgc3dpdGNoIChjb2RlTGVuZ3RoKSB7CiAgICAgICAgY2FzZSAzMjoKICAgICAgICAgIGlmIChpID09PSAwKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJubyBwcmV2aW91cyB2YWx1ZSBpbiBzeW1ib2wgSUQgdGFibGUiKTsKICAgICAgICAgIH0KICAgICAgICAgIG51bWJlck9mUmVwZWF0cyA9IHJlYWRlci5yZWFkQml0cygyKSArIDM7CiAgICAgICAgICByZXBlYXRlZExlbmd0aCA9IGNvZGVzW2kgLSAxXS5wcmVmaXhMZW5ndGg7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDMzOgogICAgICAgICAgbnVtYmVyT2ZSZXBlYXRzID0gcmVhZGVyLnJlYWRCaXRzKDMpICsgMzsKICAgICAgICAgIHJlcGVhdGVkTGVuZ3RoID0gMDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzQ6CiAgICAgICAgICBudW1iZXJPZlJlcGVhdHMgPSByZWFkZXIucmVhZEJpdHMoNykgKyAxMTsKICAgICAgICAgIHJlcGVhdGVkTGVuZ3RoID0gMDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCBjb2RlIGxlbmd0aCBpbiBzeW1ib2wgSUQgdGFibGUiKTsKICAgICAgfQogICAgICBmb3IgKGogPSAwOyBqIDwgbnVtYmVyT2ZSZXBlYXRzOyBqKyspIHsKICAgICAgICBjb2Rlcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbaSwgcmVwZWF0ZWRMZW5ndGgsIDAsIDBdKSk7CiAgICAgICAgaSsrOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb2Rlcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbaSwgY29kZUxlbmd0aCwgMCwgMF0pKTsKICAgICAgaSsrOwogICAgfQogIH0KICByZWFkZXIuYnl0ZUFsaWduKCk7CiAgY29uc3Qgc3ltYm9sSURUYWJsZSA9IG5ldyBIdWZmbWFuVGFibGUoY29kZXMsIGZhbHNlKTsKICBsZXQgY3VzdG9tSW5kZXggPSAwLAogICAgdGFibGVGaXJzdFMsCiAgICB0YWJsZURlbHRhUywKICAgIHRhYmxlRGVsdGFUOwogIHN3aXRjaCAodGV4dFJlZ2lvbi5odWZmbWFuRlMpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgICAgdGFibGVGaXJzdFMgPSBnZXRTdGFuZGFyZFRhYmxlKHRleHRSZWdpb24uaHVmZm1hbkZTICsgNik7CiAgICAgIGJyZWFrOwogICAgY2FzZSAzOgogICAgICB0YWJsZUZpcnN0UyA9IGdldEN1c3RvbUh1ZmZtYW5UYWJsZShjdXN0b21JbmRleCwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKTsKICAgICAgY3VzdG9tSW5kZXgrKzsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCBIdWZmbWFuIEZTIHNlbGVjdG9yIik7CiAgfQogIHN3aXRjaCAodGV4dFJlZ2lvbi5odWZmbWFuRFMpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgIGNhc2UgMjoKICAgICAgdGFibGVEZWx0YVMgPSBnZXRTdGFuZGFyZFRhYmxlKHRleHRSZWdpb24uaHVmZm1hbkRTICsgOCk7CiAgICAgIGJyZWFrOwogICAgY2FzZSAzOgogICAgICB0YWJsZURlbHRhUyA9IGdldEN1c3RvbUh1ZmZtYW5UYWJsZShjdXN0b21JbmRleCwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKTsKICAgICAgY3VzdG9tSW5kZXgrKzsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCBIdWZmbWFuIERTIHNlbGVjdG9yIik7CiAgfQogIHN3aXRjaCAodGV4dFJlZ2lvbi5odWZmbWFuRFQpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgIGNhc2UgMjoKICAgICAgdGFibGVEZWx0YVQgPSBnZXRTdGFuZGFyZFRhYmxlKHRleHRSZWdpb24uaHVmZm1hbkRUICsgMTEpOwogICAgICBicmVhazsKICAgIGNhc2UgMzoKICAgICAgdGFibGVEZWx0YVQgPSBnZXRDdXN0b21IdWZmbWFuVGFibGUoY3VzdG9tSW5kZXgsIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcyk7CiAgICAgIGN1c3RvbUluZGV4Kys7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBEVCBzZWxlY3RvciIpOwogIH0KICBpZiAodGV4dFJlZ2lvbi5yZWZpbmVtZW50KSB7CiAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigicmVmaW5lbWVudCB3aXRoIEh1ZmZtYW4gaXMgbm90IHN1cHBvcnRlZCIpOwogIH0KICByZXR1cm4gewogICAgc3ltYm9sSURUYWJsZSwKICAgIHRhYmxlRmlyc3RTLAogICAgdGFibGVEZWx0YVMsCiAgICB0YWJsZURlbHRhVAogIH07Cn0KZnVuY3Rpb24gZ2V0U3ltYm9sRGljdGlvbmFyeUh1ZmZtYW5UYWJsZXMoZGljdGlvbmFyeSwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKSB7CiAgbGV0IGN1c3RvbUluZGV4ID0gMCwKICAgIHRhYmxlRGVsdGFIZWlnaHQsCiAgICB0YWJsZURlbHRhV2lkdGg7CiAgc3dpdGNoIChkaWN0aW9uYXJ5Lmh1ZmZtYW5ESFNlbGVjdG9yKSB7CiAgICBjYXNlIDA6CiAgICBjYXNlIDE6CiAgICAgIHRhYmxlRGVsdGFIZWlnaHQgPSBnZXRTdGFuZGFyZFRhYmxlKGRpY3Rpb25hcnkuaHVmZm1hbkRIU2VsZWN0b3IgKyA0KTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDM6CiAgICAgIHRhYmxlRGVsdGFIZWlnaHQgPSBnZXRDdXN0b21IdWZmbWFuVGFibGUoY3VzdG9tSW5kZXgsIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcyk7CiAgICAgIGN1c3RvbUluZGV4Kys7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBESCBzZWxlY3RvciIpOwogIH0KICBzd2l0Y2ggKGRpY3Rpb25hcnkuaHVmZm1hbkRXU2VsZWN0b3IpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgICAgdGFibGVEZWx0YVdpZHRoID0gZ2V0U3RhbmRhcmRUYWJsZShkaWN0aW9uYXJ5Lmh1ZmZtYW5EV1NlbGVjdG9yICsgMik7CiAgICAgIGJyZWFrOwogICAgY2FzZSAzOgogICAgICB0YWJsZURlbHRhV2lkdGggPSBnZXRDdXN0b21IdWZmbWFuVGFibGUoY3VzdG9tSW5kZXgsIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcyk7CiAgICAgIGN1c3RvbUluZGV4Kys7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBEVyBzZWxlY3RvciIpOwogIH0KICBsZXQgdGFibGVCaXRtYXBTaXplLCB0YWJsZUFnZ3JlZ2F0ZUluc3RhbmNlczsKICBpZiAoZGljdGlvbmFyeS5iaXRtYXBTaXplU2VsZWN0b3IpIHsKICAgIHRhYmxlQml0bWFwU2l6ZSA9IGdldEN1c3RvbUh1ZmZtYW5UYWJsZShjdXN0b21JbmRleCwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKTsKICAgIGN1c3RvbUluZGV4Kys7CiAgfSBlbHNlIHsKICAgIHRhYmxlQml0bWFwU2l6ZSA9IGdldFN0YW5kYXJkVGFibGUoMSk7CiAgfQogIGlmIChkaWN0aW9uYXJ5LmFnZ3JlZ2F0aW9uSW5zdGFuY2VzU2VsZWN0b3IpIHsKICAgIHRhYmxlQWdncmVnYXRlSW5zdGFuY2VzID0gZ2V0Q3VzdG9tSHVmZm1hblRhYmxlKGN1c3RvbUluZGV4LCByZWZlcnJlZFRvLCBjdXN0b21UYWJsZXMpOwogIH0gZWxzZSB7CiAgICB0YWJsZUFnZ3JlZ2F0ZUluc3RhbmNlcyA9IGdldFN0YW5kYXJkVGFibGUoMSk7CiAgfQogIHJldHVybiB7CiAgICB0YWJsZURlbHRhSGVpZ2h0LAogICAgdGFibGVEZWx0YVdpZHRoLAogICAgdGFibGVCaXRtYXBTaXplLAogICAgdGFibGVBZ2dyZWdhdGVJbnN0YW5jZXMKICB9Owp9CmZ1bmN0aW9uIHJlYWRVbmNvbXByZXNzZWRCaXRtYXAocmVhZGVyLCB3aWR0aCwgaGVpZ2h0KSB7CiAgY29uc3QgYml0bWFwID0gW107CiAgZm9yIChsZXQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykgewogICAgY29uc3Qgcm93ID0gbmV3IFVpbnQ4QXJyYXkod2lkdGgpOwogICAgYml0bWFwLnB1c2gocm93KTsKICAgIGZvciAobGV0IHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewogICAgICByb3dbeF0gPSByZWFkZXIucmVhZEJpdCgpOwogICAgfQogICAgcmVhZGVyLmJ5dGVBbGlnbigpOwogIH0KICByZXR1cm4gYml0bWFwOwp9CmZ1bmN0aW9uIGRlY29kZU1NUkJpdG1hcChpbnB1dCwgd2lkdGgsIGhlaWdodCwgZW5kT2ZCbG9jaykgewogIGNvbnN0IHBhcmFtcyA9IHsKICAgIEs6IC0xLAogICAgQ29sdW1uczogd2lkdGgsCiAgICBSb3dzOiBoZWlnaHQsCiAgICBCbGFja0lzMTogdHJ1ZSwKICAgIEVuZE9mQmxvY2s6IGVuZE9mQmxvY2sKICB9OwogIGNvbnN0IGRlY29kZXIgPSBuZXcgQ0NJVFRGYXhEZWNvZGVyKGlucHV0LCBwYXJhbXMpOwogIGNvbnN0IGJpdG1hcCA9IFtdOwogIGxldCBjdXJyZW50Qnl0ZSwKICAgIGVvZiA9IGZhbHNlOwogIGZvciAobGV0IHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHsKICAgIGNvbnN0IHJvdyA9IG5ldyBVaW50OEFycmF5KHdpZHRoKTsKICAgIGJpdG1hcC5wdXNoKHJvdyk7CiAgICBsZXQgc2hpZnQgPSAtMTsKICAgIGZvciAobGV0IHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewogICAgICBpZiAoc2hpZnQgPCAwKSB7CiAgICAgICAgY3VycmVudEJ5dGUgPSBkZWNvZGVyLnJlYWROZXh0Q2hhcigpOwogICAgICAgIGlmIChjdXJyZW50Qnl0ZSA9PT0gLTEpIHsKICAgICAgICAgIGN1cnJlbnRCeXRlID0gMDsKICAgICAgICAgIGVvZiA9IHRydWU7CiAgICAgICAgfQogICAgICAgIHNoaWZ0ID0gNzsKICAgICAgfQogICAgICByb3dbeF0gPSBjdXJyZW50Qnl0ZSA+PiBzaGlmdCAmIDE7CiAgICAgIHNoaWZ0LS07CiAgICB9CiAgfQogIGlmIChlbmRPZkJsb2NrICYmICFlb2YpIHsKICAgIGNvbnN0IGxvb2tGb3JFT0ZMaW1pdCA9IDU7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxvb2tGb3JFT0ZMaW1pdDsgaSsrKSB7CiAgICAgIGlmIChkZWNvZGVyLnJlYWROZXh0Q2hhcigpID09PSAtMSkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiBiaXRtYXA7Cn0KY2xhc3MgSmJpZzJJbWFnZSB7CiAgcGFyc2VDaHVua3MoY2h1bmtzKSB7CiAgICByZXR1cm4gcGFyc2VKYmlnMkNodW5rcyhjaHVua3MpOwogIH0KICBwYXJzZShkYXRhKSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoIk5vdCBpbXBsZW1lbnRlZDogSmJpZzJJbWFnZS5wYXJzZSIpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvamJpZzJfc3RyZWFtLmpzCgoKCgoKCmNsYXNzIEpiaWcyU3RyZWFtIGV4dGVuZHMgRGVjb2RlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIG1heWJlTGVuZ3RoLCBwYXJhbXMpIHsKICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy5kaWN0ID0gc3RyZWFtLmRpY3Q7CiAgICB0aGlzLm1heWJlTGVuZ3RoID0gbWF5YmVMZW5ndGg7CiAgICB0aGlzLnBhcmFtcyA9IHBhcmFtczsKICB9CiAgZ2V0IGJ5dGVzKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiYnl0ZXMiLCB0aGlzLnN0cmVhbS5nZXRCeXRlcyh0aGlzLm1heWJlTGVuZ3RoKSk7CiAgfQogIGVuc3VyZUJ1ZmZlcihyZXF1ZXN0ZWQpIHt9CiAgcmVhZEJsb2NrKCkgewogICAgdGhpcy5kZWNvZGVJbWFnZSgpOwogIH0KICBnZXQgaXNBc3luY0RlY29kZXIoKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgZ2V0IGlzSW1hZ2VTdHJlYW0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgYXN5bmMgZGVjb2RlSW1hZ2UoYnl0ZXMsIF9kZWNvZGVyT3B0aW9ucykgewogICAgaWYgKHRoaXMuZW9mKSB7CiAgICAgIHJldHVybiB0aGlzLmJ1ZmZlcjsKICAgIH0KICAgIGJ5dGVzIHx8PSB0aGlzLmJ5dGVzOwogICAgdHJ5IHsKICAgICAgbGV0IGdsb2JhbHMgPSBudWxsOwogICAgICBpZiAodGhpcy5wYXJhbXMgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgICAgY29uc3QgZ2xvYmFsc1N0cmVhbSA9IHRoaXMucGFyYW1zLmdldCgiSkJJRzJHbG9iYWxzIik7CiAgICAgICAgaWYgKGdsb2JhbHNTdHJlYW0gaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgICAgICBnbG9iYWxzID0gZ2xvYmFsc1N0cmVhbS5nZXRCeXRlcygpOwogICAgICAgIH0KICAgICAgfQogICAgICB0aGlzLmJ1ZmZlciA9IGF3YWl0IEpCaWcyV2FzbUltYWdlLmRlY29kZShieXRlcywgdGhpcy5kaWN0LmdldCgiV2lkdGgiKSwgdGhpcy5kaWN0LmdldCgiSGVpZ2h0IiksIGdsb2JhbHMpOwogICAgfSBjYXRjaCB7CiAgICAgIHdhcm4oIkpiaWcyU3RyZWFtOiBGYWxsaW5nIGJhY2sgdG8gSlMgSkJJRzIgZGVjb2Rlci4iKTsKICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlSW1hZ2VGYWxsYmFjayhieXRlcyk7CiAgICB9CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyLmxlbmd0aDsKICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgIHJldHVybiB0aGlzLmJ1ZmZlcjsKICB9CiAgYXN5bmMgZGVjb2RlSW1hZ2VGYWxsYmFjayhieXRlcykgewogICAgaWYgKHRoaXMuZW9mKSB7CiAgICAgIHJldHVybiB0aGlzLmJ1ZmZlcjsKICAgIH0KICAgIGJ5dGVzIHx8PSB0aGlzLmJ5dGVzOwogICAgY29uc3QgamJpZzJJbWFnZSA9IG5ldyBKYmlnMkltYWdlKCk7CiAgICBjb25zdCBjaHVua3MgPSBbXTsKICAgIGlmICh0aGlzLnBhcmFtcyBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgY29uc3QgZ2xvYmFsc1N0cmVhbSA9IHRoaXMucGFyYW1zLmdldCgiSkJJRzJHbG9iYWxzIik7CiAgICAgIGlmIChnbG9iYWxzU3RyZWFtIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICAgIGNvbnN0IGdsb2JhbHMgPSBnbG9iYWxzU3RyZWFtLmdldEJ5dGVzKCk7CiAgICAgICAgY2h1bmtzLnB1c2goewogICAgICAgICAgZGF0YTogZ2xvYmFscywKICAgICAgICAgIHN0YXJ0OiAwLAogICAgICAgICAgZW5kOiBnbG9iYWxzLmxlbmd0aAogICAgICAgIH0pOwogICAgICB9CiAgICB9CiAgICBjaHVua3MucHVzaCh7CiAgICAgIGRhdGE6IGJ5dGVzLAogICAgICBzdGFydDogMCwKICAgICAgZW5kOiBieXRlcy5sZW5ndGgKICAgIH0pOwogICAgY29uc3QgZGF0YSA9IGpiaWcySW1hZ2UucGFyc2VDaHVua3MoY2h1bmtzKTsKICAgIGNvbnN0IGRhdGFMZW5ndGggPSBkYXRhLmxlbmd0aDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YUxlbmd0aDsgaSsrKSB7CiAgICAgIGRhdGFbaV0gXj0gMHhmZjsKICAgIH0KICAgIHRoaXMuYnVmZmVyID0gZGF0YTsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gZGF0YUxlbmd0aDsKICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgIHJldHVybiB0aGlzLmJ1ZmZlcjsKICB9CiAgZ2V0IGNhbkFzeW5jRGVjb2RlSW1hZ2VGcm9tQnVmZmVyKCkgewogICAgcmV0dXJuIHRoaXMuc3RyZWFtLmlzQXN5bmM7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9qcHhfc3RyZWFtLmpzCgoKCmNsYXNzIEpweFN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyZWFtLCBtYXliZUxlbmd0aCwgcGFyYW1zKSB7CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTsKICAgIHRoaXMuZGljdCA9IHN0cmVhbS5kaWN0OwogICAgdGhpcy5tYXliZUxlbmd0aCA9IG1heWJlTGVuZ3RoOwogICAgdGhpcy5wYXJhbXMgPSBwYXJhbXM7CiAgfQogIGdldCBieXRlcygpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgImJ5dGVzIiwgdGhpcy5zdHJlYW0uZ2V0Qnl0ZXModGhpcy5tYXliZUxlbmd0aCkpOwogIH0KICBlbnN1cmVCdWZmZXIocmVxdWVzdGVkKSB7fQogIHJlYWRCbG9jayhkZWNvZGVyT3B0aW9ucykgewogICAgdW5yZWFjaGFibGUoIkpweFN0cmVhbS5yZWFkQmxvY2siKTsKICB9CiAgZ2V0IGlzQXN5bmNEZWNvZGVyKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIGFzeW5jIGRlY29kZUltYWdlKGJ5dGVzLCBkZWNvZGVyT3B0aW9ucykgewogICAgaWYgKHRoaXMuZW9mKSB7CiAgICAgIHJldHVybiB0aGlzLmJ1ZmZlcjsKICAgIH0KICAgIGJ5dGVzIHx8PSB0aGlzLmJ5dGVzOwogICAgdGhpcy5idWZmZXIgPSBhd2FpdCBKcHhJbWFnZS5kZWNvZGUoYnl0ZXMsIGRlY29kZXJPcHRpb25zKTsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXIubGVuZ3RoOwogICAgdGhpcy5lb2YgPSB0cnVlOwogICAgcmV0dXJuIHRoaXMuYnVmZmVyOwogIH0KICBnZXQgY2FuQXN5bmNEZWNvZGVJbWFnZUZyb21CdWZmZXIoKSB7CiAgICByZXR1cm4gdGhpcy5zdHJlYW0uaXNBc3luYzsKICB9CiAgZ2V0IGlzSW1hZ2VTdHJlYW0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2x6d19zdHJlYW0uanMKCmNsYXNzIExaV1N0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyLCBtYXliZUxlbmd0aCwgZWFybHlDaGFuZ2UpIHsKICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyZWFtID0gc3RyOwogICAgdGhpcy5kaWN0ID0gc3RyLmRpY3Q7CiAgICB0aGlzLmNhY2hlZERhdGEgPSAwOwogICAgdGhpcy5iaXRzQ2FjaGVkID0gMDsKICAgIGNvbnN0IG1heEx6d0RpY3Rpb25hcnlTaXplID0gNDA5NjsKICAgIGNvbnN0IGx6d1N0YXRlID0gewogICAgICBlYXJseUNoYW5nZSwKICAgICAgY29kZUxlbmd0aDogOSwKICAgICAgbmV4dENvZGU6IDI1OCwKICAgICAgZGljdGlvbmFyeVZhbHVlczogbmV3IFVpbnQ4QXJyYXkobWF4THp3RGljdGlvbmFyeVNpemUpLAogICAgICBkaWN0aW9uYXJ5TGVuZ3RoczogbmV3IFVpbnQxNkFycmF5KG1heEx6d0RpY3Rpb25hcnlTaXplKSwKICAgICAgZGljdGlvbmFyeVByZXZDb2RlczogbmV3IFVpbnQxNkFycmF5KG1heEx6d0RpY3Rpb25hcnlTaXplKSwKICAgICAgY3VycmVudFNlcXVlbmNlOiBuZXcgVWludDhBcnJheShtYXhMendEaWN0aW9uYXJ5U2l6ZSksCiAgICAgIGN1cnJlbnRTZXF1ZW5jZUxlbmd0aDogMAogICAgfTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMjU2OyArK2kpIHsKICAgICAgbHp3U3RhdGUuZGljdGlvbmFyeVZhbHVlc1tpXSA9IGk7CiAgICAgIGx6d1N0YXRlLmRpY3Rpb25hcnlMZW5ndGhzW2ldID0gMTsKICAgIH0KICAgIHRoaXMubHp3U3RhdGUgPSBsendTdGF0ZTsKICB9CiAgcmVhZEJpdHMobikgewogICAgbGV0IGJpdHNDYWNoZWQgPSB0aGlzLmJpdHNDYWNoZWQ7CiAgICBsZXQgY2FjaGVkRGF0YSA9IHRoaXMuY2FjaGVkRGF0YTsKICAgIHdoaWxlIChiaXRzQ2FjaGVkIDwgbikgewogICAgICBjb25zdCBjID0gdGhpcy5zdHJlYW0uZ2V0Qnl0ZSgpOwogICAgICBpZiAoYyA9PT0gLTEpIHsKICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgY2FjaGVkRGF0YSA9IGNhY2hlZERhdGEgPDwgOCB8IGM7CiAgICAgIGJpdHNDYWNoZWQgKz0gODsKICAgIH0KICAgIHRoaXMuYml0c0NhY2hlZCA9IGJpdHNDYWNoZWQgLT0gbjsKICAgIHRoaXMuY2FjaGVkRGF0YSA9IGNhY2hlZERhdGE7CiAgICB0aGlzLmxhc3RDb2RlID0gbnVsbDsKICAgIHJldHVybiBjYWNoZWREYXRhID4+PiBiaXRzQ2FjaGVkICYgKDEgPDwgbikgLSAxOwogIH0KICByZWFkQmxvY2soKSB7CiAgICBjb25zdCBibG9ja1NpemUgPSA1MTIsCiAgICAgIGRlY29kZWRTaXplRGVsdGEgPSBibG9ja1NpemU7CiAgICBsZXQgZXN0aW1hdGVkRGVjb2RlZFNpemUgPSBibG9ja1NpemUgKiAyOwogICAgbGV0IGksIGosIHE7CiAgICBjb25zdCBsendTdGF0ZSA9IHRoaXMubHp3U3RhdGU7CiAgICBpZiAoIWx6d1N0YXRlKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGVhcmx5Q2hhbmdlID0gbHp3U3RhdGUuZWFybHlDaGFuZ2U7CiAgICBsZXQgbmV4dENvZGUgPSBsendTdGF0ZS5uZXh0Q29kZTsKICAgIGNvbnN0IGRpY3Rpb25hcnlWYWx1ZXMgPSBsendTdGF0ZS5kaWN0aW9uYXJ5VmFsdWVzOwogICAgY29uc3QgZGljdGlvbmFyeUxlbmd0aHMgPSBsendTdGF0ZS5kaWN0aW9uYXJ5TGVuZ3RoczsKICAgIGNvbnN0IGRpY3Rpb25hcnlQcmV2Q29kZXMgPSBsendTdGF0ZS5kaWN0aW9uYXJ5UHJldkNvZGVzOwogICAgbGV0IGNvZGVMZW5ndGggPSBsendTdGF0ZS5jb2RlTGVuZ3RoOwogICAgbGV0IHByZXZDb2RlID0gbHp3U3RhdGUucHJldkNvZGU7CiAgICBjb25zdCBjdXJyZW50U2VxdWVuY2UgPSBsendTdGF0ZS5jdXJyZW50U2VxdWVuY2U7CiAgICBsZXQgY3VycmVudFNlcXVlbmNlTGVuZ3RoID0gbHp3U3RhdGUuY3VycmVudFNlcXVlbmNlTGVuZ3RoOwogICAgbGV0IGRlY29kZWRMZW5ndGggPSAwOwogICAgbGV0IGN1cnJlbnRCdWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlckxlbmd0aDsKICAgIGxldCBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcih0aGlzLmJ1ZmZlckxlbmd0aCArIGVzdGltYXRlZERlY29kZWRTaXplKTsKICAgIGZvciAoaSA9IDA7IGkgPCBibG9ja1NpemU7IGkrKykgewogICAgICBjb25zdCBjb2RlID0gdGhpcy5yZWFkQml0cyhjb2RlTGVuZ3RoKTsKICAgICAgY29uc3QgaGFzUHJldiA9IGN1cnJlbnRTZXF1ZW5jZUxlbmd0aCA+IDA7CiAgICAgIGlmIChjb2RlIDwgMjU2KSB7CiAgICAgICAgY3VycmVudFNlcXVlbmNlWzBdID0gY29kZTsKICAgICAgICBjdXJyZW50U2VxdWVuY2VMZW5ndGggPSAxOwogICAgICB9IGVsc2UgaWYgKGNvZGUgPj0gMjU4KSB7CiAgICAgICAgaWYgKGNvZGUgPCBuZXh0Q29kZSkgewogICAgICAgICAgY3VycmVudFNlcXVlbmNlTGVuZ3RoID0gZGljdGlvbmFyeUxlbmd0aHNbY29kZV07CiAgICAgICAgICBmb3IgKGogPSBjdXJyZW50U2VxdWVuY2VMZW5ndGggLSAxLCBxID0gY29kZTsgaiA+PSAwOyBqLS0pIHsKICAgICAgICAgICAgY3VycmVudFNlcXVlbmNlW2pdID0gZGljdGlvbmFyeVZhbHVlc1txXTsKICAgICAgICAgICAgcSA9IGRpY3Rpb25hcnlQcmV2Q29kZXNbcV07CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGN1cnJlbnRTZXF1ZW5jZVtjdXJyZW50U2VxdWVuY2VMZW5ndGgrK10gPSBjdXJyZW50U2VxdWVuY2VbMF07CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGNvZGUgPT09IDI1NikgewogICAgICAgIGNvZGVMZW5ndGggPSA5OwogICAgICAgIG5leHRDb2RlID0gMjU4OwogICAgICAgIGN1cnJlbnRTZXF1ZW5jZUxlbmd0aCA9IDA7CiAgICAgICAgY29udGludWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICAgIGRlbGV0ZSB0aGlzLmx6d1N0YXRlOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmIChoYXNQcmV2KSB7CiAgICAgICAgZGljdGlvbmFyeVByZXZDb2Rlc1tuZXh0Q29kZV0gPSBwcmV2Q29kZTsKICAgICAgICBkaWN0aW9uYXJ5TGVuZ3Roc1tuZXh0Q29kZV0gPSBkaWN0aW9uYXJ5TGVuZ3Roc1twcmV2Q29kZV0gKyAxOwogICAgICAgIGRpY3Rpb25hcnlWYWx1ZXNbbmV4dENvZGVdID0gY3VycmVudFNlcXVlbmNlWzBdOwogICAgICAgIG5leHRDb2RlKys7CiAgICAgICAgY29kZUxlbmd0aCA9IG5leHRDb2RlICsgZWFybHlDaGFuZ2UgJiBuZXh0Q29kZSArIGVhcmx5Q2hhbmdlIC0gMSA/IGNvZGVMZW5ndGggOiBNYXRoLm1pbihNYXRoLmxvZyhuZXh0Q29kZSArIGVhcmx5Q2hhbmdlKSAvIDAuNjkzMTQ3MTgwNTU5OTQ1MyArIDEsIDEyKSB8IDA7CiAgICAgIH0KICAgICAgcHJldkNvZGUgPSBjb2RlOwogICAgICBkZWNvZGVkTGVuZ3RoICs9IGN1cnJlbnRTZXF1ZW5jZUxlbmd0aDsKICAgICAgaWYgKGVzdGltYXRlZERlY29kZWRTaXplIDwgZGVjb2RlZExlbmd0aCkgewogICAgICAgIGRvIHsKICAgICAgICAgIGVzdGltYXRlZERlY29kZWRTaXplICs9IGRlY29kZWRTaXplRGVsdGE7CiAgICAgICAgfSB3aGlsZSAoZXN0aW1hdGVkRGVjb2RlZFNpemUgPCBkZWNvZGVkTGVuZ3RoKTsKICAgICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcih0aGlzLmJ1ZmZlckxlbmd0aCArIGVzdGltYXRlZERlY29kZWRTaXplKTsKICAgICAgfQogICAgICBmb3IgKGogPSAwOyBqIDwgY3VycmVudFNlcXVlbmNlTGVuZ3RoOyBqKyspIHsKICAgICAgICBidWZmZXJbY3VycmVudEJ1ZmZlckxlbmd0aCsrXSA9IGN1cnJlbnRTZXF1ZW5jZVtqXTsKICAgICAgfQogICAgfQogICAgbHp3U3RhdGUubmV4dENvZGUgPSBuZXh0Q29kZTsKICAgIGx6d1N0YXRlLmNvZGVMZW5ndGggPSBjb2RlTGVuZ3RoOwogICAgbHp3U3RhdGUucHJldkNvZGUgPSBwcmV2Q29kZTsKICAgIGx6d1N0YXRlLmN1cnJlbnRTZXF1ZW5jZUxlbmd0aCA9IGN1cnJlbnRTZXF1ZW5jZUxlbmd0aDsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gY3VycmVudEJ1ZmZlckxlbmd0aDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3ByZWRpY3Rvcl9zdHJlYW0uanMKCgoKY2xhc3MgUHJlZGljdG9yU3RyZWFtIGV4dGVuZHMgRGVjb2RlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHIsIG1heWJlTGVuZ3RoLCBwYXJhbXMpIHsKICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIGlmICghKHBhcmFtcyBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybiBzdHI7CiAgICB9CiAgICBjb25zdCBwcmVkaWN0b3IgPSB0aGlzLnByZWRpY3RvciA9IHBhcmFtcy5nZXQoIlByZWRpY3RvciIpIHx8IDE7CiAgICBpZiAocHJlZGljdG9yIDw9IDEpIHsKICAgICAgcmV0dXJuIHN0cjsKICAgIH0KICAgIGlmIChwcmVkaWN0b3IgIT09IDIgJiYgKHByZWRpY3RvciA8IDEwIHx8IHByZWRpY3RvciA+IDE1KSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVuc3VwcG9ydGVkIHByZWRpY3RvcjogJHtwcmVkaWN0b3J9YCk7CiAgICB9CiAgICB0aGlzLnJlYWRCbG9jayA9IHByZWRpY3RvciA9PT0gMiA/IHRoaXMucmVhZEJsb2NrVGlmZiA6IHRoaXMucmVhZEJsb2NrUG5nOwogICAgdGhpcy5zdHJlYW0gPSBzdHI7CiAgICB0aGlzLmRpY3QgPSBzdHIuZGljdDsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuY29sb3JzID0gcGFyYW1zLmdldCgiQ29sb3JzIikgfHwgMTsKICAgIGNvbnN0IGJpdHMgPSB0aGlzLmJpdHMgPSBwYXJhbXMuZ2V0KCJCUEMiLCAiQml0c1BlckNvbXBvbmVudCIpIHx8IDg7CiAgICBjb25zdCBjb2x1bW5zID0gdGhpcy5jb2x1bW5zID0gcGFyYW1zLmdldCgiQ29sdW1ucyIpIHx8IDE7CiAgICB0aGlzLnBpeEJ5dGVzID0gY29sb3JzICogYml0cyArIDcgPj4gMzsKICAgIHRoaXMucm93Qnl0ZXMgPSBjb2x1bW5zICogY29sb3JzICogYml0cyArIDcgPj4gMzsKICAgIHJldHVybiB0aGlzOwogIH0KICByZWFkQmxvY2tUaWZmKCkgewogICAgY29uc3Qgcm93Qnl0ZXMgPSB0aGlzLnJvd0J5dGVzOwogICAgY29uc3QgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJMZW5ndGg7CiAgICBjb25zdCBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihidWZmZXJMZW5ndGggKyByb3dCeXRlcyk7CiAgICBjb25zdCBiaXRzID0gdGhpcy5iaXRzOwogICAgY29uc3QgY29sb3JzID0gdGhpcy5jb2xvcnM7CiAgICBjb25zdCByYXdCeXRlcyA9IHRoaXMuc3RyZWFtLmdldEJ5dGVzKHJvd0J5dGVzKTsKICAgIHRoaXMuZW9mID0gIXJhd0J5dGVzLmxlbmd0aDsKICAgIGlmICh0aGlzLmVvZikgewogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgaW5idWYgPSAwLAogICAgICBvdXRidWYgPSAwOwogICAgbGV0IGluYml0cyA9IDAsCiAgICAgIG91dGJpdHMgPSAwOwogICAgbGV0IHBvcyA9IGJ1ZmZlckxlbmd0aDsKICAgIGxldCBpOwogICAgaWYgKGJpdHMgPT09IDEgJiYgY29sb3JzID09PSAxKSB7CiAgICAgIGZvciAoaSA9IDA7IGkgPCByb3dCeXRlczsgKytpKSB7CiAgICAgICAgbGV0IGMgPSByYXdCeXRlc1tpXSBeIGluYnVmOwogICAgICAgIGMgXj0gYyA+PiAxOwogICAgICAgIGMgXj0gYyA+PiAyOwogICAgICAgIGMgXj0gYyA+PiA0OwogICAgICAgIGluYnVmID0gKGMgJiAxKSA8PCA3OwogICAgICAgIGJ1ZmZlcltwb3MrK10gPSBjOwogICAgICB9CiAgICB9IGVsc2UgaWYgKGJpdHMgPT09IDgpIHsKICAgICAgZm9yIChpID0gMDsgaSA8IGNvbG9yczsgKytpKSB7CiAgICAgICAgYnVmZmVyW3BvcysrXSA9IHJhd0J5dGVzW2ldOwogICAgICB9CiAgICAgIGZvciAoOyBpIDwgcm93Qnl0ZXM7ICsraSkgewogICAgICAgIGJ1ZmZlcltwb3NdID0gYnVmZmVyW3BvcyAtIGNvbG9yc10gKyByYXdCeXRlc1tpXTsKICAgICAgICBwb3MrKzsKICAgICAgfQogICAgfSBlbHNlIGlmIChiaXRzID09PSAxNikgewogICAgICBjb25zdCBieXRlc1BlclBpeGVsID0gY29sb3JzICogMjsKICAgICAgZm9yIChpID0gMDsgaSA8IGJ5dGVzUGVyUGl4ZWw7ICsraSkgewogICAgICAgIGJ1ZmZlcltwb3MrK10gPSByYXdCeXRlc1tpXTsKICAgICAgfQogICAgICBmb3IgKDsgaSA8IHJvd0J5dGVzOyBpICs9IDIpIHsKICAgICAgICBjb25zdCBzdW0gPSAoKHJhd0J5dGVzW2ldICYgMHhmZikgPDwgOCkgKyAocmF3Qnl0ZXNbaSArIDFdICYgMHhmZikgKyAoKGJ1ZmZlcltwb3MgLSBieXRlc1BlclBpeGVsXSAmIDB4ZmYpIDw8IDgpICsgKGJ1ZmZlcltwb3MgLSBieXRlc1BlclBpeGVsICsgMV0gJiAweGZmKTsKICAgICAgICBidWZmZXJbcG9zKytdID0gc3VtID4+IDggJiAweGZmOwogICAgICAgIGJ1ZmZlcltwb3MrK10gPSBzdW0gJiAweGZmOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBjb21wQXJyYXkgPSBuZXcgVWludDhBcnJheShjb2xvcnMgKyAxKTsKICAgICAgY29uc3QgYml0TWFzayA9ICgxIDw8IGJpdHMpIC0gMTsKICAgICAgbGV0IGogPSAwLAogICAgICAgIGsgPSBidWZmZXJMZW5ndGg7CiAgICAgIGNvbnN0IGNvbHVtbnMgPSB0aGlzLmNvbHVtbnM7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBjb2x1bW5zOyArK2kpIHsKICAgICAgICBmb3IgKGxldCBrayA9IDA7IGtrIDwgY29sb3JzOyArK2trKSB7CiAgICAgICAgICBpZiAoaW5iaXRzIDwgYml0cykgewogICAgICAgICAgICBpbmJ1ZiA9IGluYnVmIDw8IDggfCByYXdCeXRlc1tqKytdICYgMHhmZjsKICAgICAgICAgICAgaW5iaXRzICs9IDg7CiAgICAgICAgICB9CiAgICAgICAgICBjb21wQXJyYXlba2tdID0gY29tcEFycmF5W2trXSArIChpbmJ1ZiA+PiBpbmJpdHMgLSBiaXRzKSAmIGJpdE1hc2s7CiAgICAgICAgICBpbmJpdHMgLT0gYml0czsKICAgICAgICAgIG91dGJ1ZiA9IG91dGJ1ZiA8PCBiaXRzIHwgY29tcEFycmF5W2trXTsKICAgICAgICAgIG91dGJpdHMgKz0gYml0czsKICAgICAgICAgIGlmIChvdXRiaXRzID49IDgpIHsKICAgICAgICAgICAgYnVmZmVyW2srK10gPSBvdXRidWYgPj4gb3V0Yml0cyAtIDggJiAweGZmOwogICAgICAgICAgICBvdXRiaXRzIC09IDg7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChvdXRiaXRzID4gMCkgewogICAgICAgIGJ1ZmZlcltrKytdID0gKG91dGJ1ZiA8PCA4IC0gb3V0Yml0cykgKyAoaW5idWYgJiAoMSA8PCA4IC0gb3V0Yml0cykgLSAxKTsKICAgICAgfQogICAgfQogICAgdGhpcy5idWZmZXJMZW5ndGggKz0gcm93Qnl0ZXM7CiAgfQogIHJlYWRCbG9ja1BuZygpIHsKICAgIGNvbnN0IHJvd0J5dGVzID0gdGhpcy5yb3dCeXRlczsKICAgIGNvbnN0IHBpeEJ5dGVzID0gdGhpcy5waXhCeXRlczsKICAgIGNvbnN0IHByZWRpY3RvciA9IHRoaXMuc3RyZWFtLmdldEJ5dGUoKTsKICAgIGNvbnN0IHJhd0J5dGVzID0gdGhpcy5zdHJlYW0uZ2V0Qnl0ZXMocm93Qnl0ZXMpOwogICAgdGhpcy5lb2YgPSAhcmF3Qnl0ZXMubGVuZ3RoOwogICAgaWYgKHRoaXMuZW9mKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyTGVuZ3RoOwogICAgY29uc3QgYnVmZmVyID0gdGhpcy5lbnN1cmVCdWZmZXIoYnVmZmVyTGVuZ3RoICsgcm93Qnl0ZXMpOwogICAgbGV0IHByZXZSb3cgPSBidWZmZXIuc3ViYXJyYXkoYnVmZmVyTGVuZ3RoIC0gcm93Qnl0ZXMsIGJ1ZmZlckxlbmd0aCk7CiAgICBpZiAocHJldlJvdy5sZW5ndGggPT09IDApIHsKICAgICAgcHJldlJvdyA9IG5ldyBVaW50OEFycmF5KHJvd0J5dGVzKTsKICAgIH0KICAgIGxldCBpLAogICAgICBqID0gYnVmZmVyTGVuZ3RoLAogICAgICB1cCwKICAgICAgYzsKICAgIHN3aXRjaCAocHJlZGljdG9yKSB7CiAgICAgIGNhc2UgMDoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcm93Qnl0ZXM7ICsraSkgewogICAgICAgICAgYnVmZmVyW2orK10gPSByYXdCeXRlc1tpXTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMToKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcGl4Qnl0ZXM7ICsraSkgewogICAgICAgICAgYnVmZmVyW2orK10gPSByYXdCeXRlc1tpXTsKICAgICAgICB9CiAgICAgICAgZm9yICg7IGkgPCByb3dCeXRlczsgKytpKSB7CiAgICAgICAgICBidWZmZXJbal0gPSBidWZmZXJbaiAtIHBpeEJ5dGVzXSArIHJhd0J5dGVzW2ldICYgMHhmZjsKICAgICAgICAgIGorKzsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMjoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcm93Qnl0ZXM7ICsraSkgewogICAgICAgICAgYnVmZmVyW2orK10gPSBwcmV2Um93W2ldICsgcmF3Qnl0ZXNbaV0gJiAweGZmOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSAzOgogICAgICAgIGZvciAoaSA9IDA7IGkgPCBwaXhCeXRlczsgKytpKSB7CiAgICAgICAgICBidWZmZXJbaisrXSA9IChwcmV2Um93W2ldID4+IDEpICsgcmF3Qnl0ZXNbaV07CiAgICAgICAgfQogICAgICAgIGZvciAoOyBpIDwgcm93Qnl0ZXM7ICsraSkgewogICAgICAgICAgYnVmZmVyW2pdID0gKHByZXZSb3dbaV0gKyBidWZmZXJbaiAtIHBpeEJ5dGVzXSA+PiAxKSArIHJhd0J5dGVzW2ldICYgMHhmZjsKICAgICAgICAgIGorKzsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgNDoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcGl4Qnl0ZXM7ICsraSkgewogICAgICAgICAgdXAgPSBwcmV2Um93W2ldOwogICAgICAgICAgYyA9IHJhd0J5dGVzW2ldOwogICAgICAgICAgYnVmZmVyW2orK10gPSB1cCArIGM7CiAgICAgICAgfQogICAgICAgIGZvciAoOyBpIDwgcm93Qnl0ZXM7ICsraSkgewogICAgICAgICAgdXAgPSBwcmV2Um93W2ldOwogICAgICAgICAgY29uc3QgdXBMZWZ0ID0gcHJldlJvd1tpIC0gcGl4Qnl0ZXNdOwogICAgICAgICAgY29uc3QgbGVmdCA9IGJ1ZmZlcltqIC0gcGl4Qnl0ZXNdOwogICAgICAgICAgY29uc3QgcCA9IGxlZnQgKyB1cCAtIHVwTGVmdDsKICAgICAgICAgIGxldCBwYSA9IHAgLSBsZWZ0OwogICAgICAgICAgaWYgKHBhIDwgMCkgewogICAgICAgICAgICBwYSA9IC1wYTsKICAgICAgICAgIH0KICAgICAgICAgIGxldCBwYiA9IHAgLSB1cDsKICAgICAgICAgIGlmIChwYiA8IDApIHsKICAgICAgICAgICAgcGIgPSAtcGI7CiAgICAgICAgICB9CiAgICAgICAgICBsZXQgcGMgPSBwIC0gdXBMZWZ0OwogICAgICAgICAgaWYgKHBjIDwgMCkgewogICAgICAgICAgICBwYyA9IC1wYzsKICAgICAgICAgIH0KICAgICAgICAgIGMgPSByYXdCeXRlc1tpXTsKICAgICAgICAgIGlmIChwYSA8PSBwYiAmJiBwYSA8PSBwYykgewogICAgICAgICAgICBidWZmZXJbaisrXSA9IGxlZnQgKyBjOwogICAgICAgICAgfSBlbHNlIGlmIChwYiA8PSBwYykgewogICAgICAgICAgICBidWZmZXJbaisrXSA9IHVwICsgYzsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGJ1ZmZlcltqKytdID0gdXBMZWZ0ICsgYzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBVbnN1cHBvcnRlZCBwcmVkaWN0b3I6ICR7cHJlZGljdG9yfWApOwogICAgfQogICAgdGhpcy5idWZmZXJMZW5ndGggKz0gcm93Qnl0ZXM7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9ydW5fbGVuZ3RoX3N0cmVhbS5qcwoKY2xhc3MgUnVuTGVuZ3RoU3RyZWFtIGV4dGVuZHMgRGVjb2RlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHIsIG1heWJlTGVuZ3RoKSB7CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0cmVhbSA9IHN0cjsKICAgIHRoaXMuZGljdCA9IHN0ci5kaWN0OwogIH0KICByZWFkQmxvY2soKSB7CiAgICBjb25zdCByZXBlYXRIZWFkZXIgPSB0aGlzLnN0cmVhbS5nZXRCeXRlcygyKTsKICAgIGlmICghcmVwZWF0SGVhZGVyIHx8IHJlcGVhdEhlYWRlci5sZW5ndGggPCAyIHx8IHJlcGVhdEhlYWRlclswXSA9PT0gMTI4KSB7CiAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IGJ1ZmZlcjsKICAgIGxldCBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlckxlbmd0aDsKICAgIGxldCBuID0gcmVwZWF0SGVhZGVyWzBdOwogICAgaWYgKG4gPCAxMjgpIHsKICAgICAgYnVmZmVyID0gdGhpcy5lbnN1cmVCdWZmZXIoYnVmZmVyTGVuZ3RoICsgbiArIDEpOwogICAgICBidWZmZXJbYnVmZmVyTGVuZ3RoKytdID0gcmVwZWF0SGVhZGVyWzFdOwogICAgICBpZiAobiA+IDApIHsKICAgICAgICBjb25zdCBzb3VyY2UgPSB0aGlzLnN0cmVhbS5nZXRCeXRlcyhuKTsKICAgICAgICBidWZmZXIuc2V0KHNvdXJjZSwgYnVmZmVyTGVuZ3RoKTsKICAgICAgICBidWZmZXJMZW5ndGggKz0gbjsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgbiA9IDI1NyAtIG47CiAgICAgIGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKGJ1ZmZlckxlbmd0aCArIG4gKyAxKTsKICAgICAgYnVmZmVyLmZpbGwocmVwZWF0SGVhZGVyWzFdLCBidWZmZXJMZW5ndGgsIGJ1ZmZlckxlbmd0aCArIG4pOwogICAgICBidWZmZXJMZW5ndGggKz0gbjsKICAgIH0KICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gYnVmZmVyTGVuZ3RoOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvcGFyc2VyLmpzCgoKCgoKCgoKCgoKCgoKY29uc3QgTUFYX0xFTkdUSF9UT19DQUNIRSA9IDEwMDA7CmZ1bmN0aW9uIGdldElubGluZUltYWdlQ2FjaGVLZXkoYnl0ZXMpIHsKICBjb25zdCBzdHJCdWYgPSBbXSwKICAgIGlpID0gYnl0ZXMubGVuZ3RoOwogIGxldCBpID0gMDsKICB3aGlsZSAoaSA8IGlpIC0gMSkgewogICAgc3RyQnVmLnB1c2goYnl0ZXNbaSsrXSA8PCA4IHwgYnl0ZXNbaSsrXSk7CiAgfQogIGlmIChpIDwgaWkpIHsKICAgIHN0ckJ1Zi5wdXNoKGJ5dGVzW2ldKTsKICB9CiAgcmV0dXJuIGlpICsgIl8iICsgU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBzdHJCdWYpOwp9CmNsYXNzIFBhcnNlciB7CiAgY29uc3RydWN0b3IoewogICAgbGV4ZXIsCiAgICB4cmVmLAogICAgYWxsb3dTdHJlYW1zID0gZmFsc2UsCiAgICByZWNvdmVyeU1vZGUgPSBmYWxzZQogIH0pIHsKICAgIHRoaXMubGV4ZXIgPSBsZXhlcjsKICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgICB0aGlzLmFsbG93U3RyZWFtcyA9IGFsbG93U3RyZWFtczsKICAgIHRoaXMucmVjb3ZlcnlNb2RlID0gcmVjb3ZlcnlNb2RlOwogICAgdGhpcy5pbWFnZUNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHRoaXMuX2ltYWdlSWQgPSAwOwogICAgdGhpcy5yZWZpbGwoKTsKICB9CiAgcmVmaWxsKCkgewogICAgdGhpcy5idWYxID0gdGhpcy5sZXhlci5nZXRPYmooKTsKICAgIHRoaXMuYnVmMiA9IHRoaXMubGV4ZXIuZ2V0T2JqKCk7CiAgfQogIHNoaWZ0KCkgewogICAgaWYgKHRoaXMuYnVmMiBpbnN0YW5jZW9mIENtZCAmJiB0aGlzLmJ1ZjIuY21kID09PSAiSUQiKSB7CiAgICAgIHRoaXMuYnVmMSA9IHRoaXMuYnVmMjsKICAgICAgdGhpcy5idWYyID0gbnVsbDsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuYnVmMSA9IHRoaXMuYnVmMjsKICAgICAgdGhpcy5idWYyID0gdGhpcy5sZXhlci5nZXRPYmooKTsKICAgIH0KICB9CiAgdHJ5U2hpZnQoKSB7CiAgICB0cnkgewogICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSBjYXRjaCAoZSkgewogICAgICBpZiAoZSBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZTsKICAgICAgfQogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgfQogIGdldE9iaihjaXBoZXJUcmFuc2Zvcm0gPSBudWxsKSB7CiAgICBjb25zdCBidWYxID0gdGhpcy5idWYxOwogICAgdGhpcy5zaGlmdCgpOwogICAgaWYgKGJ1ZjEgaW5zdGFuY2VvZiBDbWQpIHsKICAgICAgc3dpdGNoIChidWYxLmNtZCkgewogICAgICAgIGNhc2UgIkJJIjoKICAgICAgICAgIHJldHVybiB0aGlzLm1ha2VJbmxpbmVJbWFnZShjaXBoZXJUcmFuc2Zvcm0pOwogICAgICAgIGNhc2UgIlsiOgogICAgICAgICAgY29uc3QgYXJyYXkgPSBbXTsKICAgICAgICAgIHdoaWxlICghaXNDbWQodGhpcy5idWYxLCAiXSIpICYmIHRoaXMuYnVmMSAhPT0gRU9GKSB7CiAgICAgICAgICAgIGFycmF5LnB1c2godGhpcy5nZXRPYmooY2lwaGVyVHJhbnNmb3JtKSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodGhpcy5idWYxID09PSBFT0YpIHsKICAgICAgICAgICAgaWYgKHRoaXMucmVjb3ZlcnlNb2RlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZXJFT0ZFeGNlcHRpb24oIkVuZCBvZiBmaWxlIGluc2lkZSBhcnJheS4iKTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuc2hpZnQoKTsKICAgICAgICAgIHJldHVybiBhcnJheTsKICAgICAgICBjYXNlICI8PCI6CiAgICAgICAgICBjb25zdCBkaWN0ID0gbmV3IERpY3QodGhpcy54cmVmKTsKICAgICAgICAgIHdoaWxlICghaXNDbWQodGhpcy5idWYxLCAiPj4iKSAmJiB0aGlzLmJ1ZjEgIT09IEVPRikgewogICAgICAgICAgICBpZiAoISh0aGlzLmJ1ZjEgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICAgICAgICAgIGluZm8oIk1hbGZvcm1lZCBkaWN0aW9uYXJ5OiBrZXkgbXVzdCBiZSBhIG5hbWUgb2JqZWN0Iik7CiAgICAgICAgICAgICAgdGhpcy5zaGlmdCgpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGtleSA9IHRoaXMuYnVmMS5uYW1lOwogICAgICAgICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgICAgICAgIGlmICh0aGlzLmJ1ZjEgPT09IEVPRikgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRpY3Quc2V0KGtleSwgdGhpcy5nZXRPYmooY2lwaGVyVHJhbnNmb3JtKSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodGhpcy5idWYxID09PSBFT0YpIHsKICAgICAgICAgICAgaWYgKHRoaXMucmVjb3ZlcnlNb2RlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGRpY3Q7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlckVPRkV4Y2VwdGlvbigiRW5kIG9mIGZpbGUgaW5zaWRlIGRpY3Rpb25hcnkuIik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoaXNDbWQodGhpcy5idWYyLCAic3RyZWFtIikpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWxsb3dTdHJlYW1zID8gdGhpcy5tYWtlU3RyZWFtKGRpY3QsIGNpcGhlclRyYW5zZm9ybSkgOiBkaWN0OwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5zaGlmdCgpOwogICAgICAgICAgcmV0dXJuIGRpY3Q7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHJldHVybiBidWYxOwogICAgICB9CiAgICB9CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihidWYxKSkgewogICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih0aGlzLmJ1ZjEpICYmIGlzQ21kKHRoaXMuYnVmMiwgIlIiKSkgewogICAgICAgIGNvbnN0IHJlZiA9IFJlZi5nZXQoYnVmMSwgdGhpcy5idWYxKTsKICAgICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgICAgdGhpcy5zaGlmdCgpOwogICAgICAgIHJldHVybiByZWY7CiAgICAgIH0KICAgICAgcmV0dXJuIGJ1ZjE7CiAgICB9CiAgICBpZiAodHlwZW9mIGJ1ZjEgPT09ICJzdHJpbmciKSB7CiAgICAgIGlmIChjaXBoZXJUcmFuc2Zvcm0pIHsKICAgICAgICByZXR1cm4gY2lwaGVyVHJhbnNmb3JtLmRlY3J5cHRTdHJpbmcoYnVmMSk7CiAgICAgIH0KICAgICAgcmV0dXJuIGJ1ZjE7CiAgICB9CiAgICByZXR1cm4gYnVmMTsKICB9CiAgZmluZERlZmF1bHRJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKSB7CiAgICBjb25zdCBFID0gMHg0NSwKICAgICAgSSA9IDB4NDksCiAgICAgIFNQQUNFID0gMHgyMCwKICAgICAgTEYgPSAweGEsCiAgICAgIENSID0gMHhkLAogICAgICBOVUwgPSAweDA7CiAgICBjb25zdCB7CiAgICAgICAga25vd25Db21tYW5kcwogICAgICB9ID0gdGhpcy5sZXhlciwKICAgICAgc3RhcnRQb3MgPSBzdHJlYW0ucG9zLAogICAgICBuID0gMTU7CiAgICBsZXQgc3RhdGUgPSAwLAogICAgICBjaCwKICAgICAgbWF5YmVFSVBvczsKICAgIHdoaWxlICgoY2ggPSBzdHJlYW0uZ2V0Qnl0ZSgpKSAhPT0gLTEpIHsKICAgICAgaWYgKHN0YXRlID09PSAwKSB7CiAgICAgICAgc3RhdGUgPSBjaCA9PT0gRSA/IDEgOiAwOwogICAgICB9IGVsc2UgaWYgKHN0YXRlID09PSAxKSB7CiAgICAgICAgc3RhdGUgPSBjaCA9PT0gSSA/IDIgOiAwOwogICAgICB9IGVsc2UgewogICAgICAgIGlmIChjaCA9PT0gU1BBQ0UgfHwgY2ggPT09IExGIHx8IGNoID09PSBDUikgewogICAgICAgICAgbWF5YmVFSVBvcyA9IHN0cmVhbS5wb3M7CiAgICAgICAgICBjb25zdCBmb2xsb3dpbmdCeXRlcyA9IHN0cmVhbS5wZWVrQnl0ZXMobik7CiAgICAgICAgICBjb25zdCBpaSA9IGZvbGxvd2luZ0J5dGVzLmxlbmd0aDsKICAgICAgICAgIGlmIChpaSA9PT0gMCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICBjaCA9IGZvbGxvd2luZ0J5dGVzW2ldOwogICAgICAgICAgICBpZiAoY2ggPT09IE5VTCAmJiBmb2xsb3dpbmdCeXRlc1tpICsgMV0gIT09IE5VTCkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChjaCAhPT0gTEYgJiYgY2ggIT09IENSICYmIChjaCA8IFNQQUNFIHx8IGNoID4gMHg3ZikpIHsKICAgICAgICAgICAgICBzdGF0ZSA9IDA7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChzdGF0ZSAhPT0gMikgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICgha25vd25Db21tYW5kcykgewogICAgICAgICAgICB3YXJuKCJmaW5kRGVmYXVsdElubGluZVN0cmVhbUVuZCAtIGBsZXhlci5rbm93bkNvbW1hbmRzYCBpcyB1bmRlZmluZWQuIik7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgdG1wTGV4ZXIgPSBuZXcgTGV4ZXIobmV3IFN0cmVhbShzdHJlYW0ucGVla0J5dGVzKDUgKiBuKSksIGtub3duQ29tbWFuZHMpOwogICAgICAgICAgdG1wTGV4ZXIuX2hleFN0cmluZ1dhcm4gPSAoKSA9PiB7fTsKICAgICAgICAgIGxldCBudW1BcmdzID0gMDsKICAgICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgIGNvbnN0IG5leHRPYmogPSB0bXBMZXhlci5nZXRPYmooKTsKICAgICAgICAgICAgaWYgKG5leHRPYmogPT09IEVPRikgewogICAgICAgICAgICAgIHN0YXRlID0gMDsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAobmV4dE9iaiBpbnN0YW5jZW9mIENtZCkgewogICAgICAgICAgICAgIGNvbnN0IGtub3duQ29tbWFuZCA9IGtub3duQ29tbWFuZHNbbmV4dE9iai5jbWRdOwogICAgICAgICAgICAgIGlmICgha25vd25Db21tYW5kKSB7CiAgICAgICAgICAgICAgICBzdGF0ZSA9IDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKGtub3duQ29tbWFuZC52YXJpYWJsZUFyZ3MgPyBudW1BcmdzIDw9IGtub3duQ29tbWFuZC5udW1BcmdzIDogbnVtQXJncyA9PT0ga25vd25Db21tYW5kLm51bUFyZ3MpIHsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBudW1BcmdzID0gMDsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBudW1BcmdzKys7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoc3RhdGUgPT09IDIpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN0YXRlID0gMDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChjaCA9PT0gLTEpIHsKICAgICAgd2FybigiZmluZERlZmF1bHRJbmxpbmVTdHJlYW1FbmQ6ICIgKyAiUmVhY2hlZCB0aGUgZW5kIG9mIHRoZSBzdHJlYW0gd2l0aG91dCBmaW5kaW5nIGEgdmFsaWQgRUkgbWFya2VyIik7CiAgICAgIGlmIChtYXliZUVJUG9zKSB7CiAgICAgICAgd2FybignLi4uIHRyeWluZyB0byByZWNvdmVyIGJ5IHVzaW5nIHRoZSBsYXN0ICJFSSIgb2NjdXJyZW5jZS4nKTsKICAgICAgICBzdHJlYW0uc2tpcCgtKHN0cmVhbS5wb3MgLSBtYXliZUVJUG9zKSk7CiAgICAgIH0KICAgIH0KICAgIGxldCBlbmRPZmZzZXQgPSA0OwogICAgc3RyZWFtLnNraXAoLWVuZE9mZnNldCk7CiAgICBjaCA9IHN0cmVhbS5wZWVrQnl0ZSgpOwogICAgc3RyZWFtLnNraXAoZW5kT2Zmc2V0KTsKICAgIGlmICghaXNXaGl0ZVNwYWNlKGNoKSkgewogICAgICBlbmRPZmZzZXQtLTsKICAgIH0KICAgIHJldHVybiBzdHJlYW0ucG9zIC0gZW5kT2Zmc2V0IC0gc3RhcnRQb3M7CiAgfQogIGZpbmREQ1REZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKSB7CiAgICBjb25zdCBzdGFydFBvcyA9IHN0cmVhbS5wb3M7CiAgICBsZXQgZm91bmRFT0kgPSBmYWxzZSwKICAgICAgYiwKICAgICAgbWFya2VyTGVuZ3RoOwogICAgd2hpbGUgKChiID0gc3RyZWFtLmdldEJ5dGUoKSkgIT09IC0xKSB7CiAgICAgIGlmIChiICE9PSAweGZmKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgc3dpdGNoIChzdHJlYW0uZ2V0Qnl0ZSgpKSB7CiAgICAgICAgY2FzZSAweDAwOgogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGZmOgogICAgICAgICAgc3RyZWFtLnNraXAoLTEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGQ5OgogICAgICAgICAgZm91bmRFT0kgPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGMwOgogICAgICAgIGNhc2UgMHhjMToKICAgICAgICBjYXNlIDB4YzI6CiAgICAgICAgY2FzZSAweGMzOgogICAgICAgIGNhc2UgMHhjNToKICAgICAgICBjYXNlIDB4YzY6CiAgICAgICAgY2FzZSAweGM3OgogICAgICAgIGNhc2UgMHhjOToKICAgICAgICBjYXNlIDB4Y2E6CiAgICAgICAgY2FzZSAweGNiOgogICAgICAgIGNhc2UgMHhjZDoKICAgICAgICBjYXNlIDB4Y2U6CiAgICAgICAgY2FzZSAweGNmOgogICAgICAgIGNhc2UgMHhjNDoKICAgICAgICBjYXNlIDB4Y2M6CiAgICAgICAgY2FzZSAweGRhOgogICAgICAgIGNhc2UgMHhkYjoKICAgICAgICBjYXNlIDB4ZGM6CiAgICAgICAgY2FzZSAweGRkOgogICAgICAgIGNhc2UgMHhkZToKICAgICAgICBjYXNlIDB4ZGY6CiAgICAgICAgY2FzZSAweGUwOgogICAgICAgIGNhc2UgMHhlMToKICAgICAgICBjYXNlIDB4ZTI6CiAgICAgICAgY2FzZSAweGUzOgogICAgICAgIGNhc2UgMHhlNDoKICAgICAgICBjYXNlIDB4ZTU6CiAgICAgICAgY2FzZSAweGU2OgogICAgICAgIGNhc2UgMHhlNzoKICAgICAgICBjYXNlIDB4ZTg6CiAgICAgICAgY2FzZSAweGU5OgogICAgICAgIGNhc2UgMHhlYToKICAgICAgICBjYXNlIDB4ZWI6CiAgICAgICAgY2FzZSAweGVjOgogICAgICAgIGNhc2UgMHhlZDoKICAgICAgICBjYXNlIDB4ZWU6CiAgICAgICAgY2FzZSAweGVmOgogICAgICAgIGNhc2UgMHhmZToKICAgICAgICAgIG1hcmtlckxlbmd0aCA9IHN0cmVhbS5nZXRVaW50MTYoKTsKICAgICAgICAgIGlmIChtYXJrZXJMZW5ndGggPiAyKSB7CiAgICAgICAgICAgIHN0cmVhbS5za2lwKG1hcmtlckxlbmd0aCAtIDIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RyZWFtLnNraXAoLTIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKGZvdW5kRU9JKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IHN0cmVhbS5wb3MgLSBzdGFydFBvczsKICAgIGlmIChiID09PSAtMSkgewogICAgICB3YXJuKCJJbmxpbmUgRENURGVjb2RlIGltYWdlIHN0cmVhbTogIiArICJFT0kgbWFya2VyIG5vdCBmb3VuZCwgc2VhcmNoaW5nIGZvciAvRUkvIGluc3RlYWQuIik7CiAgICAgIHN0cmVhbS5za2lwKC1sZW5ndGgpOwogICAgICByZXR1cm4gdGhpcy5maW5kRGVmYXVsdElubGluZVN0cmVhbUVuZChzdHJlYW0pOwogICAgfQogICAgdGhpcy5pbmxpbmVTdHJlYW1Ta2lwRUkoc3RyZWFtKTsKICAgIHJldHVybiBsZW5ndGg7CiAgfQogIGZpbmRBU0NJSTg1RGVjb2RlSW5saW5lU3RyZWFtRW5kKHN0cmVhbSkgewogICAgY29uc3QgVElMREUgPSAweDdlLAogICAgICBHVCA9IDB4M2U7CiAgICBjb25zdCBzdGFydFBvcyA9IHN0cmVhbS5wb3M7CiAgICBsZXQgY2g7CiAgICB3aGlsZSAoKGNoID0gc3RyZWFtLmdldEJ5dGUoKSkgIT09IC0xKSB7CiAgICAgIGlmIChjaCA9PT0gVElMREUpIHsKICAgICAgICBjb25zdCB0aWxkZVBvcyA9IHN0cmVhbS5wb3M7CiAgICAgICAgY2ggPSBzdHJlYW0ucGVla0J5dGUoKTsKICAgICAgICB3aGlsZSAoaXNXaGl0ZVNwYWNlKGNoKSkgewogICAgICAgICAgc3RyZWFtLnNraXAoKTsKICAgICAgICAgIGNoID0gc3RyZWFtLnBlZWtCeXRlKCk7CiAgICAgICAgfQogICAgICAgIGlmIChjaCA9PT0gR1QpIHsKICAgICAgICAgIHN0cmVhbS5za2lwKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgaWYgKHN0cmVhbS5wb3MgPiB0aWxkZVBvcykgewogICAgICAgICAgY29uc3QgbWF5YmVFSSA9IHN0cmVhbS5wZWVrQnl0ZXMoMik7CiAgICAgICAgICBpZiAobWF5YmVFSVswXSA9PT0gMHg0NSAmJiBtYXliZUVJWzFdID09PSAweDQ5KSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogICAgY29uc3QgbGVuZ3RoID0gc3RyZWFtLnBvcyAtIHN0YXJ0UG9zOwogICAgaWYgKGNoID09PSAtMSkgewogICAgICB3YXJuKCJJbmxpbmUgQVNDSUk4NURlY29kZSBpbWFnZSBzdHJlYW06ICIgKyAiRU9EIG1hcmtlciBub3QgZm91bmQsIHNlYXJjaGluZyBmb3IgL0VJLyBpbnN0ZWFkLiIpOwogICAgICBzdHJlYW0uc2tpcCgtbGVuZ3RoKTsKICAgICAgcmV0dXJuIHRoaXMuZmluZERlZmF1bHRJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKTsKICAgIH0KICAgIHRoaXMuaW5saW5lU3RyZWFtU2tpcEVJKHN0cmVhbSk7CiAgICByZXR1cm4gbGVuZ3RoOwogIH0KICBmaW5kQVNDSUlIZXhEZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKSB7CiAgICBjb25zdCBHVCA9IDB4M2U7CiAgICBjb25zdCBzdGFydFBvcyA9IHN0cmVhbS5wb3M7CiAgICBsZXQgY2g7CiAgICB3aGlsZSAoKGNoID0gc3RyZWFtLmdldEJ5dGUoKSkgIT09IC0xKSB7CiAgICAgIGlmIChjaCA9PT0gR1QpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgY29uc3QgbGVuZ3RoID0gc3RyZWFtLnBvcyAtIHN0YXJ0UG9zOwogICAgaWYgKGNoID09PSAtMSkgewogICAgICB3YXJuKCJJbmxpbmUgQVNDSUlIZXhEZWNvZGUgaW1hZ2Ugc3RyZWFtOiAiICsgIkVPRCBtYXJrZXIgbm90IGZvdW5kLCBzZWFyY2hpbmcgZm9yIC9FSS8gaW5zdGVhZC4iKTsKICAgICAgc3RyZWFtLnNraXAoLWxlbmd0aCk7CiAgICAgIHJldHVybiB0aGlzLmZpbmREZWZhdWx0SW5saW5lU3RyZWFtRW5kKHN0cmVhbSk7CiAgICB9CiAgICB0aGlzLmlubGluZVN0cmVhbVNraXBFSShzdHJlYW0pOwogICAgcmV0dXJuIGxlbmd0aDsKICB9CiAgaW5saW5lU3RyZWFtU2tpcEVJKHN0cmVhbSkgewogICAgY29uc3QgRSA9IDB4NDUsCiAgICAgIEkgPSAweDQ5OwogICAgbGV0IHN0YXRlID0gMCwKICAgICAgY2g7CiAgICB3aGlsZSAoKGNoID0gc3RyZWFtLmdldEJ5dGUoKSkgIT09IC0xKSB7CiAgICAgIGlmIChzdGF0ZSA9PT0gMCkgewogICAgICAgIHN0YXRlID0gY2ggPT09IEUgPyAxIDogMDsKICAgICAgfSBlbHNlIGlmIChzdGF0ZSA9PT0gMSkgewogICAgICAgIHN0YXRlID0gY2ggPT09IEkgPyAyIDogMDsKICAgICAgfSBlbHNlIGlmIChzdGF0ZSA9PT0gMikgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQogIG1ha2VJbmxpbmVJbWFnZShjaXBoZXJUcmFuc2Zvcm0pIHsKICAgIGNvbnN0IGxleGVyID0gdGhpcy5sZXhlcjsKICAgIGNvbnN0IHN0cmVhbSA9IGxleGVyLnN0cmVhbTsKICAgIGNvbnN0IGRpY3RNYXAgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgbGV0IGRpY3RMZW5ndGg7CiAgICB3aGlsZSAoIWlzQ21kKHRoaXMuYnVmMSwgIklEIikgJiYgdGhpcy5idWYxICE9PSBFT0YpIHsKICAgICAgaWYgKCEodGhpcy5idWYxIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkRpY3Rpb25hcnkga2V5IG11c3QgYmUgYSBuYW1lIG9iamVjdCIpOwogICAgICB9CiAgICAgIGNvbnN0IGtleSA9IHRoaXMuYnVmMS5uYW1lOwogICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgIGlmICh0aGlzLmJ1ZjEgPT09IEVPRikgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGRpY3RNYXBba2V5XSA9IHRoaXMuZ2V0T2JqKGNpcGhlclRyYW5zZm9ybSk7CiAgICB9CiAgICBpZiAobGV4ZXIuYmVnaW5JbmxpbmVJbWFnZVBvcyAhPT0gLTEpIHsKICAgICAgZGljdExlbmd0aCA9IHN0cmVhbS5wb3MgLSBsZXhlci5iZWdpbklubGluZUltYWdlUG9zOwogICAgfQogICAgY29uc3QgZmlsdGVyID0gdGhpcy54cmVmLmZldGNoSWZSZWYoZGljdE1hcC5GIHx8IGRpY3RNYXAuRmlsdGVyKTsKICAgIGxldCBmaWx0ZXJOYW1lOwogICAgaWYgKGZpbHRlciBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgZmlsdGVyTmFtZSA9IGZpbHRlci5uYW1lOwogICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGZpbHRlcikpIHsKICAgICAgY29uc3QgZmlsdGVyWmVybyA9IHRoaXMueHJlZi5mZXRjaElmUmVmKGZpbHRlclswXSk7CiAgICAgIGlmIChmaWx0ZXJaZXJvIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgIGZpbHRlck5hbWUgPSBmaWx0ZXJaZXJvLm5hbWU7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHN0YXJ0UG9zID0gc3RyZWFtLnBvczsKICAgIGxldCBsZW5ndGg7CiAgICBzd2l0Y2ggKGZpbHRlck5hbWUpIHsKICAgICAgY2FzZSAiRENUIjoKICAgICAgY2FzZSAiRENURGVjb2RlIjoKICAgICAgICBsZW5ndGggPSB0aGlzLmZpbmREQ1REZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiQTg1IjoKICAgICAgY2FzZSAiQVNDSUk4NURlY29kZSI6CiAgICAgICAgbGVuZ3RoID0gdGhpcy5maW5kQVNDSUk4NURlY29kZUlubGluZVN0cmVhbUVuZChzdHJlYW0pOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJBSHgiOgogICAgICBjYXNlICJBU0NJSUhleERlY29kZSI6CiAgICAgICAgbGVuZ3RoID0gdGhpcy5maW5kQVNDSUlIZXhEZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKTsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICBsZW5ndGggPSB0aGlzLmZpbmREZWZhdWx0SW5saW5lU3RyZWFtRW5kKHN0cmVhbSk7CiAgICB9CiAgICBsZXQgY2FjaGVLZXk7CiAgICBpZiAobGVuZ3RoIDwgTUFYX0xFTkdUSF9UT19DQUNIRSAmJiBkaWN0TGVuZ3RoID4gMCkgewogICAgICBjb25zdCBpbml0aWFsU3RyZWFtUG9zID0gc3RyZWFtLnBvczsKICAgICAgc3RyZWFtLnBvcyA9IGxleGVyLmJlZ2luSW5saW5lSW1hZ2VQb3M7CiAgICAgIGNhY2hlS2V5ID0gZ2V0SW5saW5lSW1hZ2VDYWNoZUtleShzdHJlYW0uZ2V0Qnl0ZXMoZGljdExlbmd0aCArIGxlbmd0aCkpOwogICAgICBzdHJlYW0ucG9zID0gaW5pdGlhbFN0cmVhbVBvczsKICAgICAgY29uc3QgY2FjaGVFbnRyeSA9IHRoaXMuaW1hZ2VDYWNoZVtjYWNoZUtleV07CiAgICAgIGlmIChjYWNoZUVudHJ5ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLmJ1ZjIgPSBDbWQuZ2V0KCJFSSIpOwogICAgICAgIHRoaXMuc2hpZnQoKTsKICAgICAgICBjYWNoZUVudHJ5LnJlc2V0KCk7CiAgICAgICAgcmV0dXJuIGNhY2hlRW50cnk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGRpY3QgPSBuZXcgRGljdCh0aGlzLnhyZWYpOwogICAgZm9yIChjb25zdCBrZXkgaW4gZGljdE1hcCkgewogICAgICBkaWN0LnNldChrZXksIGRpY3RNYXBba2V5XSk7CiAgICB9CiAgICBsZXQgaW1hZ2VTdHJlYW0gPSBzdHJlYW0ubWFrZVN1YlN0cmVhbShzdGFydFBvcywgbGVuZ3RoLCBkaWN0KTsKICAgIGlmIChjaXBoZXJUcmFuc2Zvcm0pIHsKICAgICAgaW1hZ2VTdHJlYW0gPSBjaXBoZXJUcmFuc2Zvcm0uY3JlYXRlU3RyZWFtKGltYWdlU3RyZWFtLCBsZW5ndGgpOwogICAgfQogICAgaW1hZ2VTdHJlYW0gPSB0aGlzLmZpbHRlcihpbWFnZVN0cmVhbSwgZGljdCwgbGVuZ3RoKTsKICAgIGltYWdlU3RyZWFtLmRpY3QgPSBkaWN0OwogICAgaWYgKGNhY2hlS2V5ICE9PSB1bmRlZmluZWQpIHsKICAgICAgaW1hZ2VTdHJlYW0uY2FjaGVLZXkgPSBgaW5saW5lX2ltZ18keysrdGhpcy5faW1hZ2VJZH1gOwogICAgICB0aGlzLmltYWdlQ2FjaGVbY2FjaGVLZXldID0gaW1hZ2VTdHJlYW07CiAgICB9CiAgICB0aGlzLmJ1ZjIgPSBDbWQuZ2V0KCJFSSIpOwogICAgdGhpcy5zaGlmdCgpOwogICAgcmV0dXJuIGltYWdlU3RyZWFtOwogIH0KICAjZmluZFN0cmVhbUxlbmd0aChzdGFydFBvcykgewogICAgY29uc3QgewogICAgICBzdHJlYW0KICAgIH0gPSB0aGlzLmxleGVyOwogICAgc3RyZWFtLnBvcyA9IHN0YXJ0UG9zOwogICAgY29uc3QgU0NBTl9CTE9DS19MRU5HVEggPSAyMDQ4OwogICAgY29uc3Qgc2lnbmF0dXJlTGVuZ3RoID0gImVuZHN0cmVhbSIubGVuZ3RoOwogICAgY29uc3QgRU5EX1NJR05BVFVSRSA9IG5ldyBVaW50OEFycmF5KFsweDY1LCAweDZlLCAweDY0XSk7CiAgICBjb25zdCBlbmRMZW5ndGggPSBFTkRfU0lHTkFUVVJFLmxlbmd0aDsKICAgIGNvbnN0IFBBUlRJQUxfU0lHTkFUVVJFID0gW25ldyBVaW50OEFycmF5KFsweDczLCAweDc0LCAweDcyLCAweDY1LCAweDYxLCAweDZkXSksIG5ldyBVaW50OEFycmF5KFsweDczLCAweDc0LCAweDY1LCAweDYxLCAweDZkXSksIG5ldyBVaW50OEFycmF5KFsweDczLCAweDc0LCAweDcyLCAweDY1LCAweDYxXSldOwogICAgY29uc3Qgbm9ybWFsTGVuZ3RoID0gc2lnbmF0dXJlTGVuZ3RoIC0gZW5kTGVuZ3RoOwogICAgd2hpbGUgKHN0cmVhbS5wb3MgPCBzdHJlYW0uZW5kKSB7CiAgICAgIGNvbnN0IHNjYW5CeXRlcyA9IHN0cmVhbS5wZWVrQnl0ZXMoU0NBTl9CTE9DS19MRU5HVEgpOwogICAgICBjb25zdCBzY2FuTGVuZ3RoID0gc2NhbkJ5dGVzLmxlbmd0aCAtIHNpZ25hdHVyZUxlbmd0aDsKICAgICAgaWYgKHNjYW5MZW5ndGggPD0gMCkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGxldCBwb3MgPSAwOwogICAgICB3aGlsZSAocG9zIDwgc2Nhbkxlbmd0aCkgewogICAgICAgIGxldCBqID0gMDsKICAgICAgICB3aGlsZSAoaiA8IGVuZExlbmd0aCAmJiBzY2FuQnl0ZXNbcG9zICsgal0gPT09IEVORF9TSUdOQVRVUkVbal0pIHsKICAgICAgICAgIGorKzsKICAgICAgICB9CiAgICAgICAgaWYgKGogPj0gZW5kTGVuZ3RoKSB7CiAgICAgICAgICBsZXQgZm91bmQgPSBmYWxzZTsKICAgICAgICAgIGZvciAoY29uc3QgcGFydCBvZiBQQVJUSUFMX1NJR05BVFVSRSkgewogICAgICAgICAgICBjb25zdCBwYXJ0TGVuID0gcGFydC5sZW5ndGg7CiAgICAgICAgICAgIGxldCBrID0gMDsKICAgICAgICAgICAgd2hpbGUgKGsgPCBwYXJ0TGVuICYmIHNjYW5CeXRlc1twb3MgKyBqICsga10gPT09IHBhcnRba10pIHsKICAgICAgICAgICAgICBrKys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGsgPj0gbm9ybWFsTGVuZ3RoKSB7CiAgICAgICAgICAgICAgZm91bmQgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChrID49IHBhcnRMZW4pIHsKICAgICAgICAgICAgICBjb25zdCBsYXN0Qnl0ZSA9IHNjYW5CeXRlc1twb3MgKyBqICsga107CiAgICAgICAgICAgICAgaWYgKGlzV2hpdGVTcGFjZShsYXN0Qnl0ZSkpIHsKICAgICAgICAgICAgICAgIGluZm8oYEZvdW5kICIke2J5dGVzVG9TdHJpbmcoWy4uLkVORF9TSUdOQVRVUkUsIC4uLnBhcnRdKX0iIHdoZW4gYCArICJzZWFyY2hpbmcgZm9yIGVuZHN0cmVhbSBjb21tYW5kLiIpOwogICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGZvdW5kKSB7CiAgICAgICAgICAgIHN0cmVhbS5wb3MgKz0gcG9zOwogICAgICAgICAgICByZXR1cm4gc3RyZWFtLnBvcyAtIHN0YXJ0UG9zOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBwb3MrKzsKICAgICAgfQogICAgICBzdHJlYW0ucG9zICs9IHNjYW5MZW5ndGg7CiAgICB9CiAgICByZXR1cm4gLTE7CiAgfQogIG1ha2VTdHJlYW0oZGljdCwgY2lwaGVyVHJhbnNmb3JtKSB7CiAgICBjb25zdCBsZXhlciA9IHRoaXMubGV4ZXI7CiAgICBsZXQgc3RyZWFtID0gbGV4ZXIuc3RyZWFtOwogICAgbGV4ZXIuc2tpcFRvTmV4dExpbmUoKTsKICAgIGNvbnN0IHN0YXJ0UG9zID0gc3RyZWFtLnBvcyAtIDE7CiAgICBsZXQgbGVuZ3RoID0gZGljdC5nZXQoIkxlbmd0aCIpOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGxlbmd0aCkpIHsKICAgICAgaW5mbyhgQmFkIGxlbmd0aCAiJHtsZW5ndGggJiYgbGVuZ3RoLnRvU3RyaW5nKCl9IiBpbiBzdHJlYW0uYCk7CiAgICAgIGxlbmd0aCA9IDA7CiAgICB9CiAgICBzdHJlYW0ucG9zID0gc3RhcnRQb3MgKyBsZW5ndGg7CiAgICBsZXhlci5uZXh0Q2hhcigpOwogICAgaWYgKHRoaXMudHJ5U2hpZnQoKSAmJiBpc0NtZCh0aGlzLmJ1ZjIsICJlbmRzdHJlYW0iKSkgewogICAgICB0aGlzLnNoaWZ0KCk7CiAgICB9IGVsc2UgewogICAgICBsZW5ndGggPSB0aGlzLiNmaW5kU3RyZWFtTGVuZ3RoKHN0YXJ0UG9zKTsKICAgICAgaWYgKGxlbmd0aCA8IDApIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk1pc3NpbmcgZW5kc3RyZWFtIGNvbW1hbmQuIik7CiAgICAgIH0KICAgICAgbGV4ZXIubmV4dENoYXIoKTsKICAgICAgdGhpcy5zaGlmdCgpOwogICAgICB0aGlzLnNoaWZ0KCk7CiAgICB9CiAgICB0aGlzLnNoaWZ0KCk7CiAgICBzdHJlYW0gPSBzdHJlYW0ubWFrZVN1YlN0cmVhbShzdGFydFBvcywgbGVuZ3RoLCBkaWN0KTsKICAgIGlmIChjaXBoZXJUcmFuc2Zvcm0pIHsKICAgICAgc3RyZWFtID0gY2lwaGVyVHJhbnNmb3JtLmNyZWF0ZVN0cmVhbShzdHJlYW0sIGxlbmd0aCk7CiAgICB9CiAgICBzdHJlYW0gPSB0aGlzLmZpbHRlcihzdHJlYW0sIGRpY3QsIGxlbmd0aCk7CiAgICBzdHJlYW0uZGljdCA9IGRpY3Q7CiAgICByZXR1cm4gc3RyZWFtOwogIH0KICBmaWx0ZXIoc3RyZWFtLCBkaWN0LCBsZW5ndGgpIHsKICAgIGxldCBmaWx0ZXIgPSBkaWN0LmdldCgiRiIsICJGaWx0ZXIiKTsKICAgIGxldCBwYXJhbXMgPSBkaWN0LmdldCgiRFAiLCAiRGVjb2RlUGFybXMiKTsKICAgIGlmIChmaWx0ZXIgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KHBhcmFtcykpIHsKICAgICAgICB3YXJuKCIvRGVjb2RlUGFybXMgc2hvdWxkIG5vdCBiZSBhbiBBcnJheSwgd2hlbiAvRmlsdGVyIGlzIGEgTmFtZS4iKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5tYWtlRmlsdGVyKHN0cmVhbSwgZmlsdGVyLm5hbWUsIGxlbmd0aCwgcGFyYW1zKTsKICAgIH0KICAgIGxldCBtYXliZUxlbmd0aCA9IGxlbmd0aDsKICAgIGlmIChBcnJheS5pc0FycmF5KGZpbHRlcikpIHsKICAgICAgY29uc3QgZmlsdGVyQXJyYXkgPSBmaWx0ZXI7CiAgICAgIGNvbnN0IHBhcmFtc0FycmF5ID0gcGFyYW1zOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBmaWx0ZXJBcnJheS5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICAgICAgZmlsdGVyID0gdGhpcy54cmVmLmZldGNoSWZSZWYoZmlsdGVyQXJyYXlbaV0pOwogICAgICAgIGlmICghKGZpbHRlciBpbnN0YW5jZW9mIE5hbWUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEJhZCBmaWx0ZXIgbmFtZSAiJHtmaWx0ZXJ9ImApOwogICAgICAgIH0KICAgICAgICBwYXJhbXMgPSBudWxsOwogICAgICAgIGlmIChBcnJheS5pc0FycmF5KHBhcmFtc0FycmF5KSAmJiBpIGluIHBhcmFtc0FycmF5KSB7CiAgICAgICAgICBwYXJhbXMgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihwYXJhbXNBcnJheVtpXSk7CiAgICAgICAgfQogICAgICAgIHN0cmVhbSA9IHRoaXMubWFrZUZpbHRlcihzdHJlYW0sIGZpbHRlci5uYW1lLCBtYXliZUxlbmd0aCwgcGFyYW1zKTsKICAgICAgICBtYXliZUxlbmd0aCA9IG51bGw7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzdHJlYW07CiAgfQogIG1ha2VGaWx0ZXIoc3RyZWFtLCBuYW1lLCBtYXliZUxlbmd0aCwgcGFyYW1zKSB7CiAgICBpZiAobWF5YmVMZW5ndGggPT09IDApIHsKICAgICAgd2FybihgRW1wdHkgIiR7bmFtZX0iIHN0cmVhbS5gKTsKICAgICAgcmV0dXJuIG5ldyBOdWxsU3RyZWFtKCk7CiAgICB9CiAgICB0cnkgewogICAgICBzd2l0Y2ggKG5hbWUpIHsKICAgICAgICBjYXNlICJGbCI6CiAgICAgICAgY2FzZSAiRmxhdGVEZWNvZGUiOgogICAgICAgICAgaWYgKHBhcmFtcykgewogICAgICAgICAgICByZXR1cm4gbmV3IFByZWRpY3RvclN0cmVhbShuZXcgRmxhdGVTdHJlYW0oc3RyZWFtLCBtYXliZUxlbmd0aCksIG1heWJlTGVuZ3RoLCBwYXJhbXMpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG5ldyBGbGF0ZVN0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoKTsKICAgICAgICBjYXNlICJMWlciOgogICAgICAgIGNhc2UgIkxaV0RlY29kZSI6CiAgICAgICAgICBsZXQgZWFybHlDaGFuZ2UgPSAxOwogICAgICAgICAgaWYgKHBhcmFtcykgewogICAgICAgICAgICBpZiAocGFyYW1zLmhhcygiRWFybHlDaGFuZ2UiKSkgewogICAgICAgICAgICAgIGVhcmx5Q2hhbmdlID0gcGFyYW1zLmdldCgiRWFybHlDaGFuZ2UiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbmV3IFByZWRpY3RvclN0cmVhbShuZXcgTFpXU3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgsIGVhcmx5Q2hhbmdlKSwgbWF5YmVMZW5ndGgsIHBhcmFtcyk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gbmV3IExaV1N0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoLCBlYXJseUNoYW5nZSk7CiAgICAgICAgY2FzZSAiRENUIjoKICAgICAgICBjYXNlICJEQ1REZWNvZGUiOgogICAgICAgICAgcmV0dXJuIG5ldyBKcGVnU3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgsIHBhcmFtcyk7CiAgICAgICAgY2FzZSAiSlBYIjoKICAgICAgICBjYXNlICJKUFhEZWNvZGUiOgogICAgICAgICAgcmV0dXJuIG5ldyBKcHhTdHJlYW0oc3RyZWFtLCBtYXliZUxlbmd0aCwgcGFyYW1zKTsKICAgICAgICBjYXNlICJBODUiOgogICAgICAgIGNhc2UgIkFTQ0lJODVEZWNvZGUiOgogICAgICAgICAgcmV0dXJuIG5ldyBBc2NpaTg1U3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgpOwogICAgICAgIGNhc2UgIkFIeCI6CiAgICAgICAgY2FzZSAiQVNDSUlIZXhEZWNvZGUiOgogICAgICAgICAgcmV0dXJuIG5ldyBBc2NpaUhleFN0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoKTsKICAgICAgICBjYXNlICJDQ0YiOgogICAgICAgIGNhc2UgIkNDSVRURmF4RGVjb2RlIjoKICAgICAgICAgIHJldHVybiBuZXcgQ0NJVFRGYXhTdHJlYW0oc3RyZWFtLCBtYXliZUxlbmd0aCwgcGFyYW1zKTsKICAgICAgICBjYXNlICJSTCI6CiAgICAgICAgY2FzZSAiUnVuTGVuZ3RoRGVjb2RlIjoKICAgICAgICAgIHJldHVybiBuZXcgUnVuTGVuZ3RoU3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgpOwogICAgICAgIGNhc2UgIkpCSUcyRGVjb2RlIjoKICAgICAgICAgIHJldHVybiBuZXcgSmJpZzJTdHJlYW0oc3RyZWFtLCBtYXliZUxlbmd0aCwgcGFyYW1zKTsKICAgICAgfQogICAgICB3YXJuKGBGaWx0ZXIgIiR7bmFtZX0iIGlzIG5vdCBzdXBwb3J0ZWQuYCk7CiAgICAgIHJldHVybiBzdHJlYW07CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIHdhcm4oYEludmFsaWQgc3RyZWFtOiAiJHtleH0iYCk7CiAgICAgIHJldHVybiBuZXcgTnVsbFN0cmVhbSgpOwogICAgfQogIH0KfQpjb25zdCBzcGVjaWFsQ2hhcnMgPSBbMSwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMSwgMSwgMCwgMSwgMSwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMSwgMCwgMCwgMCwgMCwgMiwgMCwgMCwgMiwgMiwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMF07CmZ1bmN0aW9uIHRvSGV4RGlnaXQoY2gpIHsKICBpZiAoY2ggPj0gMHgzMCAmJiBjaCA8PSAweDM5KSB7CiAgICByZXR1cm4gY2ggJiAweDBmOwogIH0KICBpZiAoY2ggPj0gMHg0MSAmJiBjaCA8PSAweDQ2IHx8IGNoID49IDB4NjEgJiYgY2ggPD0gMHg2NikgewogICAgcmV0dXJuIChjaCAmIDB4MGYpICsgOTsKICB9CiAgcmV0dXJuIC0xOwp9CmNsYXNzIExleGVyIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIGtub3duQ29tbWFuZHMgPSBudWxsKSB7CiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTsKICAgIHRoaXMubmV4dENoYXIoKTsKICAgIHRoaXMuc3RyQnVmID0gW107CiAgICB0aGlzLmtub3duQ29tbWFuZHMgPSBrbm93bkNvbW1hbmRzOwogICAgdGhpcy5faGV4U3RyaW5nTnVtV2FybiA9IDA7CiAgICB0aGlzLmJlZ2luSW5saW5lSW1hZ2VQb3MgPSAtMTsKICB9CiAgbmV4dENoYXIoKSB7CiAgICByZXR1cm4gdGhpcy5jdXJyZW50Q2hhciA9IHRoaXMuc3RyZWFtLmdldEJ5dGUoKTsKICB9CiAgcGVla0NoYXIoKSB7CiAgICByZXR1cm4gdGhpcy5zdHJlYW0ucGVla0J5dGUoKTsKICB9CiAgZ2V0TnVtYmVyKCkgewogICAgbGV0IGNoID0gdGhpcy5jdXJyZW50Q2hhcjsKICAgIGxldCBlTm90YXRpb24gPSBmYWxzZTsKICAgIGxldCBkaXZpZGVCeSA9IDA7CiAgICBsZXQgc2lnbiA9IDE7CiAgICBpZiAoY2ggPT09IDB4MmQpIHsKICAgICAgc2lnbiA9IC0xOwogICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgaWYgKGNoID09PSAweDJkKSB7CiAgICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MmIpIHsKICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICB9CiAgICBpZiAoY2ggPT09IDB4MGEgfHwgY2ggPT09IDB4MGQpIHsKICAgICAgZG8gewogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICB9IHdoaWxlIChjaCA9PT0gMHgwYSB8fCBjaCA9PT0gMHgwZCk7CiAgICB9CiAgICBpZiAoY2ggPT09IDB4MmUpIHsKICAgICAgZGl2aWRlQnkgPSAxMDsKICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICB9CiAgICBpZiAoY2ggPCAweDMwIHx8IGNoID4gMHgzOSkgewogICAgICBjb25zdCBtc2cgPSBgSW52YWxpZCBudW1iZXI6ICR7U3RyaW5nLmZyb21DaGFyQ29kZShjaCl9IChjaGFyQ29kZSAke2NofSlgOwogICAgICBpZiAoaXNXaGl0ZVNwYWNlKGNoKSB8fCBjaCA9PT0gMHgyOCB8fCBjaCA9PT0gMHgzYyB8fCBjaCA9PT0gLTEpIHsKICAgICAgICBpbmZvKGBMZXhlci5nZXROdW1iZXIgLSAiJHttc2d9Ii5gKTsKICAgICAgICByZXR1cm4gMDsKICAgICAgfQogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IobXNnKTsKICAgIH0KICAgIGxldCBiYXNlVmFsdWUgPSBjaCAtIDB4MzA7CiAgICBsZXQgcG93ZXJWYWx1ZSA9IDA7CiAgICBsZXQgcG93ZXJWYWx1ZVNpZ24gPSAxOwogICAgd2hpbGUgKChjaCA9IHRoaXMubmV4dENoYXIoKSkgPj0gMCkgewogICAgICBpZiAoY2ggPj0gMHgzMCAmJiBjaCA8PSAweDM5KSB7CiAgICAgICAgY29uc3QgY3VycmVudERpZ2l0ID0gY2ggLSAweDMwOwogICAgICAgIGlmIChlTm90YXRpb24pIHsKICAgICAgICAgIHBvd2VyVmFsdWUgPSBwb3dlclZhbHVlICogMTAgKyBjdXJyZW50RGlnaXQ7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChkaXZpZGVCeSAhPT0gMCkgewogICAgICAgICAgICBkaXZpZGVCeSAqPSAxMDsKICAgICAgICAgIH0KICAgICAgICAgIGJhc2VWYWx1ZSA9IGJhc2VWYWx1ZSAqIDEwICsgY3VycmVudERpZ2l0OwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChjaCA9PT0gMHgyZSkgewogICAgICAgIGlmIChkaXZpZGVCeSA9PT0gMCkgewogICAgICAgICAgZGl2aWRlQnkgPSAxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MmQpIHsKICAgICAgICB3YXJuKCJCYWRseSBmb3JtYXR0ZWQgbnVtYmVyOiBtaW51cyBzaWduIGluIHRoZSBtaWRkbGUiKTsKICAgICAgfSBlbHNlIGlmIChjaCA9PT0gMHg0NSB8fCBjaCA9PT0gMHg2NSkgewogICAgICAgIGNoID0gdGhpcy5wZWVrQ2hhcigpOwogICAgICAgIGlmIChjaCA9PT0gMHgyYiB8fCBjaCA9PT0gMHgyZCkgewogICAgICAgICAgcG93ZXJWYWx1ZVNpZ24gPSBjaCA9PT0gMHgyZCA/IC0xIDogMTsKICAgICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICB9IGVsc2UgaWYgKGNoIDwgMHgzMCB8fCBjaCA+IDB4MzkpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBlTm90YXRpb24gPSB0cnVlOwogICAgICB9IGVsc2UgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBpZiAoZGl2aWRlQnkgIT09IDApIHsKICAgICAgYmFzZVZhbHVlIC89IGRpdmlkZUJ5OwogICAgfQogICAgaWYgKGVOb3RhdGlvbikgewogICAgICBiYXNlVmFsdWUgKj0gMTAgKiogKHBvd2VyVmFsdWVTaWduICogcG93ZXJWYWx1ZSk7CiAgICB9CiAgICByZXR1cm4gc2lnbiAqIGJhc2VWYWx1ZTsKICB9CiAgZ2V0U3RyaW5nKCkgewogICAgbGV0IG51bVBhcmVuID0gMTsKICAgIGxldCBkb25lID0gZmFsc2U7CiAgICBjb25zdCBzdHJCdWYgPSB0aGlzLnN0ckJ1ZjsKICAgIHN0ckJ1Zi5sZW5ndGggPSAwOwogICAgbGV0IGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgbGV0IGNoYXJCdWZmZXJlZCA9IGZhbHNlOwogICAgICBzd2l0Y2ggKGNoIHwgMCkgewogICAgICAgIGNhc2UgLTE6CiAgICAgICAgICB3YXJuKCJVbnRlcm1pbmF0ZWQgc3RyaW5nIik7CiAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHgyODoKICAgICAgICAgICsrbnVtUGFyZW47CiAgICAgICAgICBzdHJCdWYucHVzaCgiKCIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDI5OgogICAgICAgICAgaWYgKC0tbnVtUGFyZW4gPT09IDApIHsKICAgICAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKCIpIik7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4NWM6CiAgICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICAgIHN3aXRjaCAoY2gpIHsKICAgICAgICAgICAgY2FzZSAtMToKICAgICAgICAgICAgICB3YXJuKCJVbnRlcm1pbmF0ZWQgc3RyaW5nIik7CiAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMHg2ZToKICAgICAgICAgICAgICBzdHJCdWYucHVzaCgiXG4iKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDcyOgogICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKCJcciIpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDB4NzQ6CiAgICAgICAgICAgICAgc3RyQnVmLnB1c2goIlx0Iik7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMHg2MjoKICAgICAgICAgICAgICBzdHJCdWYucHVzaCgiXGIiKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDY2OgogICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKCJcZiIpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDB4NWM6CiAgICAgICAgICAgIGNhc2UgMHgyODoKICAgICAgICAgICAgY2FzZSAweDI5OgogICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDMwOgogICAgICAgICAgICBjYXNlIDB4MzE6CiAgICAgICAgICAgIGNhc2UgMHgzMjoKICAgICAgICAgICAgY2FzZSAweDMzOgogICAgICAgICAgICBjYXNlIDB4MzQ6CiAgICAgICAgICAgIGNhc2UgMHgzNToKICAgICAgICAgICAgY2FzZSAweDM2OgogICAgICAgICAgICBjYXNlIDB4Mzc6CiAgICAgICAgICAgICAgbGV0IHggPSBjaCAmIDB4MGY7CiAgICAgICAgICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgICAgICAgY2hhckJ1ZmZlcmVkID0gdHJ1ZTsKICAgICAgICAgICAgICBpZiAoY2ggPj0gMHgzMCAmJiBjaCA8PSAweDM3KSB7CiAgICAgICAgICAgICAgICB4ID0gKHggPDwgMykgKyAoY2ggJiAweDBmKTsKICAgICAgICAgICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICAgICAgaWYgKGNoID49IDB4MzAgJiYgY2ggPD0gMHgzNykgewogICAgICAgICAgICAgICAgICBjaGFyQnVmZmVyZWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgeCA9ICh4IDw8IDMpICsgKGNoICYgMHgwZik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoeCkpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDB4MGQ6CiAgICAgICAgICAgICAgaWYgKHRoaXMucGVla0NoYXIoKSA9PT0gMHgwYSkgewogICAgICAgICAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDBhOgogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKSk7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoZG9uZSkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmICghY2hhckJ1ZmZlcmVkKSB7CiAgICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzdHJCdWYuam9pbigiIik7CiAgfQogIGdldE5hbWUoKSB7CiAgICBsZXQgY2gsIHByZXZpb3VzQ2g7CiAgICBjb25zdCBzdHJCdWYgPSB0aGlzLnN0ckJ1ZjsKICAgIHN0ckJ1Zi5sZW5ndGggPSAwOwogICAgd2hpbGUgKChjaCA9IHRoaXMubmV4dENoYXIoKSkgPj0gMCAmJiAhc3BlY2lhbENoYXJzW2NoXSkgewogICAgICBpZiAoY2ggPT09IDB4MjMpIHsKICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICBpZiAoc3BlY2lhbENoYXJzW2NoXSkgewogICAgICAgICAgd2FybigiTGV4ZXJfZ2V0TmFtZTogIiArICJOVU1CRVIgU0lHTiAoIykgc2hvdWxkIGJlIGZvbGxvd2VkIGJ5IGEgaGV4YWRlY2ltYWwgbnVtYmVyLiIpOwogICAgICAgICAgc3RyQnVmLnB1c2goIiMiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjb25zdCB4ID0gdG9IZXhEaWdpdChjaCk7CiAgICAgICAgaWYgKHggIT09IC0xKSB7CiAgICAgICAgICBwcmV2aW91c0NoID0gY2g7CiAgICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICAgIGNvbnN0IHgyID0gdG9IZXhEaWdpdChjaCk7CiAgICAgICAgICBpZiAoeDIgPT09IC0xKSB7CiAgICAgICAgICAgIHdhcm4oYExleGVyX2dldE5hbWU6IElsbGVnYWwgZGlnaXQgKCR7U3RyaW5nLmZyb21DaGFyQ29kZShjaCl9KSBgICsgImluIGhleGFkZWNpbWFsIG51bWJlci4iKTsKICAgICAgICAgICAgc3RyQnVmLnB1c2goIiMiLCBTdHJpbmcuZnJvbUNoYXJDb2RlKHByZXZpb3VzQ2gpKTsKICAgICAgICAgICAgaWYgKHNwZWNpYWxDaGFyc1tjaF0pIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKSk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZSh4IDw8IDQgfCB4MikpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdHJCdWYucHVzaCgiIyIsIFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjaCkpOwogICAgICB9CiAgICB9CiAgICBpZiAoc3RyQnVmLmxlbmd0aCA+IDEyNykgewogICAgICB3YXJuKGBOYW1lIHRva2VuIGlzIGxvbmdlciB0aGFuIGFsbG93ZWQgYnkgdGhlIHNwZWM6ICR7c3RyQnVmLmxlbmd0aH1gKTsKICAgIH0KICAgIHJldHVybiBOYW1lLmdldChzdHJCdWYuam9pbigiIikpOwogIH0KICBfaGV4U3RyaW5nV2FybihjaCkgewogICAgY29uc3QgTUFYX0hFWF9TVFJJTkdfTlVNX1dBUk4gPSA1OwogICAgaWYgKHRoaXMuX2hleFN0cmluZ051bVdhcm4rKyA9PT0gTUFYX0hFWF9TVFJJTkdfTlVNX1dBUk4pIHsKICAgICAgd2FybigiZ2V0SGV4U3RyaW5nIC0gaWdub3JpbmcgYWRkaXRpb25hbCBpbnZhbGlkIGNoYXJhY3RlcnMuIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0aGlzLl9oZXhTdHJpbmdOdW1XYXJuID4gTUFYX0hFWF9TVFJJTkdfTlVNX1dBUk4pIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgd2FybihgZ2V0SGV4U3RyaW5nIC0gaWdub3JpbmcgaW52YWxpZCBjaGFyYWN0ZXI6ICR7Y2h9YCk7CiAgfQogIGdldEhleFN0cmluZygpIHsKICAgIGNvbnN0IHN0ckJ1ZiA9IHRoaXMuc3RyQnVmOwogICAgc3RyQnVmLmxlbmd0aCA9IDA7CiAgICBsZXQgY2ggPSB0aGlzLmN1cnJlbnRDaGFyOwogICAgbGV0IGZpcnN0RGlnaXQgPSAtMSwKICAgICAgZGlnaXQgPSAtMTsKICAgIHRoaXMuX2hleFN0cmluZ051bVdhcm4gPSAwOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgaWYgKGNoIDwgMCkgewogICAgICAgIHdhcm4oIlVudGVybWluYXRlZCBoZXggc3RyaW5nIik7CiAgICAgICAgYnJlYWs7CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4M2UpIHsKICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0gZWxzZSBpZiAoc3BlY2lhbENoYXJzW2NoXSA9PT0gMSkgewogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgewogICAgICAgIGRpZ2l0ID0gdG9IZXhEaWdpdChjaCk7CiAgICAgICAgaWYgKGRpZ2l0ID09PSAtMSkgewogICAgICAgICAgdGhpcy5faGV4U3RyaW5nV2FybihjaCk7CiAgICAgICAgfSBlbHNlIGlmIChmaXJzdERpZ2l0ID09PSAtMSkgewogICAgICAgICAgZmlyc3REaWdpdCA9IGRpZ2l0OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGZpcnN0RGlnaXQgPDwgNCB8IGRpZ2l0KSk7CiAgICAgICAgICBmaXJzdERpZ2l0ID0gLTE7CiAgICAgICAgfQogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICB9CiAgICB9CiAgICBpZiAoZmlyc3REaWdpdCAhPT0gLTEpIHsKICAgICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShmaXJzdERpZ2l0IDw8IDQpKTsKICAgIH0KICAgIHJldHVybiBzdHJCdWYuam9pbigiIik7CiAgfQogIGdldE9iaigpIHsKICAgIGxldCBjb21tZW50ID0gZmFsc2U7CiAgICBsZXQgY2ggPSB0aGlzLmN1cnJlbnRDaGFyOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgaWYgKGNoIDwgMCkgewogICAgICAgIHJldHVybiBFT0Y7CiAgICAgIH0KICAgICAgaWYgKGNvbW1lbnQpIHsKICAgICAgICBpZiAoY2ggPT09IDB4MGEgfHwgY2ggPT09IDB4MGQpIHsKICAgICAgICAgIGNvbW1lbnQgPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MjUpIHsKICAgICAgICBjb21tZW50ID0gdHJ1ZTsKICAgICAgfSBlbHNlIGlmIChzcGVjaWFsQ2hhcnNbY2hdICE9PSAxKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICB9CiAgICBzd2l0Y2ggKGNoIHwgMCkgewogICAgICBjYXNlIDB4MzA6CiAgICAgIGNhc2UgMHgzMToKICAgICAgY2FzZSAweDMyOgogICAgICBjYXNlIDB4MzM6CiAgICAgIGNhc2UgMHgzNDoKICAgICAgY2FzZSAweDM1OgogICAgICBjYXNlIDB4MzY6CiAgICAgIGNhc2UgMHgzNzoKICAgICAgY2FzZSAweDM4OgogICAgICBjYXNlIDB4Mzk6CiAgICAgIGNhc2UgMHgyYjoKICAgICAgY2FzZSAweDJkOgogICAgICBjYXNlIDB4MmU6CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TnVtYmVyKCk7CiAgICAgIGNhc2UgMHgyODoKICAgICAgICByZXR1cm4gdGhpcy5nZXRTdHJpbmcoKTsKICAgICAgY2FzZSAweDJmOgogICAgICAgIHJldHVybiB0aGlzLmdldE5hbWUoKTsKICAgICAgY2FzZSAweDViOgogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICByZXR1cm4gQ21kLmdldCgiWyIpOwogICAgICBjYXNlIDB4NWQ6CiAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIHJldHVybiBDbWQuZ2V0KCJdIik7CiAgICAgIGNhc2UgMHgzYzoKICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICBpZiAoY2ggPT09IDB4M2MpIHsKICAgICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICAgIHJldHVybiBDbWQuZ2V0KCI8PCIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpcy5nZXRIZXhTdHJpbmcoKTsKICAgICAgY2FzZSAweDNlOgogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIGlmIChjaCA9PT0gMHgzZSkgewogICAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgcmV0dXJuIENtZC5nZXQoIj4+Iik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBDbWQuZ2V0KCI+Iik7CiAgICAgIGNhc2UgMHg3YjoKICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgcmV0dXJuIENtZC5nZXQoInsiKTsKICAgICAgY2FzZSAweDdkOgogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICByZXR1cm4gQ21kLmdldCgifSIpOwogICAgICBjYXNlIDB4Mjk6CiAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSWxsZWdhbCBjaGFyYWN0ZXI6ICR7Y2h9YCk7CiAgICB9CiAgICBsZXQgc3RyID0gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICBpZiAoY2ggPCAweDIwIHx8IGNoID4gMHg3ZikgewogICAgICBjb25zdCBuZXh0Q2ggPSB0aGlzLnBlZWtDaGFyKCk7CiAgICAgIGlmIChuZXh0Q2ggPj0gMHgyMCAmJiBuZXh0Q2ggPD0gMHg3ZikgewogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICByZXR1cm4gQ21kLmdldChzdHIpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBrbm93bkNvbW1hbmRzID0gdGhpcy5rbm93bkNvbW1hbmRzOwogICAgbGV0IGtub3duQ29tbWFuZEZvdW5kID0ga25vd25Db21tYW5kcz8uW3N0cl0gIT09IHVuZGVmaW5lZDsKICAgIHdoaWxlICgoY2ggPSB0aGlzLm5leHRDaGFyKCkpID49IDAgJiYgIXNwZWNpYWxDaGFyc1tjaF0pIHsKICAgICAgY29uc3QgcG9zc2libGVDb21tYW5kID0gc3RyICsgU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICAgIGlmIChrbm93bkNvbW1hbmRGb3VuZCAmJiBrbm93bkNvbW1hbmRzW3Bvc3NpYmxlQ29tbWFuZF0gPT09IHVuZGVmaW5lZCkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmIChzdHIubGVuZ3RoID09PSAxMjgpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYENvbW1hbmQgdG9rZW4gdG9vIGxvbmc6ICR7c3RyLmxlbmd0aH1gKTsKICAgICAgfQogICAgICBzdHIgPSBwb3NzaWJsZUNvbW1hbmQ7CiAgICAgIGtub3duQ29tbWFuZEZvdW5kID0ga25vd25Db21tYW5kcz8uW3N0cl0gIT09IHVuZGVmaW5lZDsKICAgIH0KICAgIGlmIChzdHIgPT09ICJ0cnVlIikgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmIChzdHIgPT09ICJmYWxzZSIpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKHN0ciA9PT0gIm51bGwiKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKHN0ciA9PT0gIkJJIikgewogICAgICB0aGlzLmJlZ2luSW5saW5lSW1hZ2VQb3MgPSB0aGlzLnN0cmVhbS5wb3M7CiAgICB9CiAgICByZXR1cm4gQ21kLmdldChzdHIpOwogIH0KICBza2lwVG9OZXh0TGluZSgpIHsKICAgIGxldCBjaCA9IHRoaXMuY3VycmVudENoYXI7CiAgICB3aGlsZSAoY2ggPj0gMCkgewogICAgICBpZiAoY2ggPT09IDB4MGQpIHsKICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICBpZiAoY2ggPT09IDB4MGEpIHsKICAgICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MGEpIHsKICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICB9CiAgfQp9CmNsYXNzIExpbmVhcml6YXRpb24gewogIHN0YXRpYyBjcmVhdGUoc3RyZWFtKSB7CiAgICBmdW5jdGlvbiBnZXRJbnQobGluRGljdCwgbmFtZSwgYWxsb3daZXJvVmFsdWUgPSBmYWxzZSkgewogICAgICBjb25zdCBvYmogPSBsaW5EaWN0LmdldChuYW1lKTsKICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIob2JqKSAmJiAoYWxsb3daZXJvVmFsdWUgPyBvYmogPj0gMCA6IG9iaiA+IDApKSB7CiAgICAgICAgcmV0dXJuIG9iajsKICAgICAgfQogICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSAiJHtuYW1lfSIgcGFyYW1ldGVyIGluIHRoZSBsaW5lYXJpemF0aW9uIGAgKyAiZGljdGlvbmFyeSBpcyBpbnZhbGlkLiIpOwogICAgfQogICAgZnVuY3Rpb24gZ2V0SGludHMobGluRGljdCkgewogICAgICBjb25zdCBoaW50cyA9IGxpbkRpY3QuZ2V0KCJIIik7CiAgICAgIGxldCBoaW50c0xlbmd0aDsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkoaGludHMpICYmICgoaGludHNMZW5ndGggPSBoaW50cy5sZW5ndGgpID09PSAyIHx8IGhpbnRzTGVuZ3RoID09PSA0KSkgewogICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBoaW50c0xlbmd0aDsgaW5kZXgrKykgewogICAgICAgICAgY29uc3QgaGludCA9IGhpbnRzW2luZGV4XTsKICAgICAgICAgIGlmICghKE51bWJlci5pc0ludGVnZXIoaGludCkgJiYgaGludCA+IDApKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSGludCAoJHtpbmRleH0pIGluIHRoZSBsaW5lYXJpemF0aW9uIGRpY3Rpb25hcnkgaXMgaW52YWxpZC5gKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGhpbnRzOwogICAgICB9CiAgICAgIHRocm93IG5ldyBFcnJvcigiSGludCBhcnJheSBpbiB0aGUgbGluZWFyaXphdGlvbiBkaWN0aW9uYXJ5IGlzIGludmFsaWQuIik7CiAgICB9CiAgICBjb25zdCBwYXJzZXIgPSBuZXcgUGFyc2VyKHsKICAgICAgbGV4ZXI6IG5ldyBMZXhlcihzdHJlYW0pLAogICAgICB4cmVmOiBudWxsCiAgICB9KTsKICAgIGNvbnN0IG9iajEgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICBjb25zdCBvYmoyID0gcGFyc2VyLmdldE9iaigpOwogICAgY29uc3Qgb2JqMyA9IHBhcnNlci5nZXRPYmooKTsKICAgIGNvbnN0IGxpbkRpY3QgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICBsZXQgb2JqLCBsZW5ndGg7CiAgICBpZiAoIShOdW1iZXIuaXNJbnRlZ2VyKG9iajEpICYmIE51bWJlci5pc0ludGVnZXIob2JqMikgJiYgaXNDbWQob2JqMywgIm9iaiIpICYmIGxpbkRpY3QgaW5zdGFuY2VvZiBEaWN0ICYmIHR5cGVvZiAob2JqID0gbGluRGljdC5nZXQoIkxpbmVhcml6ZWQiKSkgPT09ICJudW1iZXIiICYmIG9iaiA+IDApKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfSBlbHNlIGlmICgobGVuZ3RoID0gZ2V0SW50KGxpbkRpY3QsICJMIikpICE9PSBzdHJlYW0ubGVuZ3RoKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlICJMIiBwYXJhbWV0ZXIgaW4gdGhlIGxpbmVhcml6YXRpb24gZGljdGlvbmFyeSAnICsgImRvZXMgbm90IGVxdWFsIHRoZSBzdHJlYW0gbGVuZ3RoLiIpOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgbGVuZ3RoLAogICAgICBoaW50czogZ2V0SGludHMobGluRGljdCksCiAgICAgIG9iamVjdE51bWJlckZpcnN0OiBnZXRJbnQobGluRGljdCwgIk8iKSwKICAgICAgZW5kRmlyc3Q6IGdldEludChsaW5EaWN0LCAiRSIpLAogICAgICBudW1QYWdlczogZ2V0SW50KGxpbkRpY3QsICJOIiksCiAgICAgIG1haW5YUmVmRW50cmllc09mZnNldDogZ2V0SW50KGxpbkRpY3QsICJUIiksCiAgICAgIHBhZ2VGaXJzdDogbGluRGljdC5oYXMoIlAiKSA/IGdldEludChsaW5EaWN0LCAiUCIsIHRydWUpIDogMAogICAgfTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2NtYXAuanMKCgoKCgoKCmNvbnN0IEJVSUxUX0lOX0NNQVBTID0gWyJBZG9iZS1HQjEtVUNTMiIsICJBZG9iZS1DTlMxLVVDUzIiLCAiQWRvYmUtSmFwYW4xLVVDUzIiLCAiQWRvYmUtS29yZWExLVVDUzIiLCAiNzgtRVVDLUgiLCAiNzgtRVVDLVYiLCAiNzgtSCIsICI3OC1SS1NKLUgiLCAiNzgtUktTSi1WIiwgIjc4LVYiLCAiNzhtcy1SS1NKLUgiLCAiNzhtcy1SS1NKLVYiLCAiODNwdi1SS1NKLUgiLCAiOTBtcy1SS1NKLUgiLCAiOTBtcy1SS1NKLVYiLCAiOTBtc3AtUktTSi1IIiwgIjkwbXNwLVJLU0otViIsICI5MHB2LVJLU0otSCIsICI5MHB2LVJLU0otViIsICJBZGQtSCIsICJBZGQtUktTSi1IIiwgIkFkZC1SS1NKLVYiLCAiQWRkLVYiLCAiQWRvYmUtQ05TMS0wIiwgIkFkb2JlLUNOUzEtMSIsICJBZG9iZS1DTlMxLTIiLCAiQWRvYmUtQ05TMS0zIiwgIkFkb2JlLUNOUzEtNCIsICJBZG9iZS1DTlMxLTUiLCAiQWRvYmUtQ05TMS02IiwgIkFkb2JlLUdCMS0wIiwgIkFkb2JlLUdCMS0xIiwgIkFkb2JlLUdCMS0yIiwgIkFkb2JlLUdCMS0zIiwgIkFkb2JlLUdCMS00IiwgIkFkb2JlLUdCMS01IiwgIkFkb2JlLUphcGFuMS0wIiwgIkFkb2JlLUphcGFuMS0xIiwgIkFkb2JlLUphcGFuMS0yIiwgIkFkb2JlLUphcGFuMS0zIiwgIkFkb2JlLUphcGFuMS00IiwgIkFkb2JlLUphcGFuMS01IiwgIkFkb2JlLUphcGFuMS02IiwgIkFkb2JlLUtvcmVhMS0wIiwgIkFkb2JlLUtvcmVhMS0xIiwgIkFkb2JlLUtvcmVhMS0yIiwgIkI1LUgiLCAiQjUtViIsICJCNXBjLUgiLCAiQjVwYy1WIiwgIkNOUy1FVUMtSCIsICJDTlMtRVVDLVYiLCAiQ05TMS1IIiwgIkNOUzEtViIsICJDTlMyLUgiLCAiQ05TMi1WIiwgIkVUSEstQjUtSCIsICJFVEhLLUI1LVYiLCAiRVRlbi1CNS1IIiwgIkVUZW4tQjUtViIsICJFVGVubXMtQjUtSCIsICJFVGVubXMtQjUtViIsICJFVUMtSCIsICJFVUMtViIsICJFeHQtSCIsICJFeHQtUktTSi1IIiwgIkV4dC1SS1NKLVYiLCAiRXh0LVYiLCAiR0ItRVVDLUgiLCAiR0ItRVVDLVYiLCAiR0ItSCIsICJHQi1WIiwgIkdCSy1FVUMtSCIsICJHQkstRVVDLVYiLCAiR0JLMkstSCIsICJHQksySy1WIiwgIkdCS3AtRVVDLUgiLCAiR0JLcC1FVUMtViIsICJHQlQtRVVDLUgiLCAiR0JULUVVQy1WIiwgIkdCVC1IIiwgIkdCVC1WIiwgIkdCVHBjLUVVQy1IIiwgIkdCVHBjLUVVQy1WIiwgIkdCcGMtRVVDLUgiLCAiR0JwYy1FVUMtViIsICJIIiwgIkhLZGxhLUI1LUgiLCAiSEtkbGEtQjUtViIsICJIS2RsYi1CNS1IIiwgIkhLZGxiLUI1LVYiLCAiSEtnY2NzLUI1LUgiLCAiSEtnY2NzLUI1LVYiLCAiSEttMzE0LUI1LUgiLCAiSEttMzE0LUI1LVYiLCAiSEttNDcxLUI1LUgiLCAiSEttNDcxLUI1LVYiLCAiSEtzY3MtQjUtSCIsICJIS3Njcy1CNS1WIiwgIkhhbmtha3UiLCAiSGlyYWdhbmEiLCAiS1NDLUVVQy1IIiwgIktTQy1FVUMtViIsICJLU0MtSCIsICJLU0MtSm9oYWItSCIsICJLU0MtSm9oYWItViIsICJLU0MtViIsICJLU0Ntcy1VSEMtSCIsICJLU0Ntcy1VSEMtSFctSCIsICJLU0Ntcy1VSEMtSFctViIsICJLU0Ntcy1VSEMtViIsICJLU0NwYy1FVUMtSCIsICJLU0NwYy1FVUMtViIsICJLYXRha2FuYSIsICJOV1AtSCIsICJOV1AtViIsICJSS1NKLUgiLCAiUktTSi1WIiwgIlJvbWFuIiwgIlVuaUNOUy1VQ1MyLUgiLCAiVW5pQ05TLVVDUzItViIsICJVbmlDTlMtVVRGMTYtSCIsICJVbmlDTlMtVVRGMTYtViIsICJVbmlDTlMtVVRGMzItSCIsICJVbmlDTlMtVVRGMzItViIsICJVbmlDTlMtVVRGOC1IIiwgIlVuaUNOUy1VVEY4LVYiLCAiVW5pR0ItVUNTMi1IIiwgIlVuaUdCLVVDUzItViIsICJVbmlHQi1VVEYxNi1IIiwgIlVuaUdCLVVURjE2LVYiLCAiVW5pR0ItVVRGMzItSCIsICJVbmlHQi1VVEYzMi1WIiwgIlVuaUdCLVVURjgtSCIsICJVbmlHQi1VVEY4LVYiLCAiVW5pSklTLVVDUzItSCIsICJVbmlKSVMtVUNTMi1IVy1IIiwgIlVuaUpJUy1VQ1MyLUhXLVYiLCAiVW5pSklTLVVDUzItViIsICJVbmlKSVMtVVRGMTYtSCIsICJVbmlKSVMtVVRGMTYtViIsICJVbmlKSVMtVVRGMzItSCIsICJVbmlKSVMtVVRGMzItViIsICJVbmlKSVMtVVRGOC1IIiwgIlVuaUpJUy1VVEY4LVYiLCAiVW5pSklTMjAwNC1VVEYxNi1IIiwgIlVuaUpJUzIwMDQtVVRGMTYtViIsICJVbmlKSVMyMDA0LVVURjMyLUgiLCAiVW5pSklTMjAwNC1VVEYzMi1WIiwgIlVuaUpJUzIwMDQtVVRGOC1IIiwgIlVuaUpJUzIwMDQtVVRGOC1WIiwgIlVuaUpJU1Byby1VQ1MyLUhXLVYiLCAiVW5pSklTUHJvLVVDUzItViIsICJVbmlKSVNQcm8tVVRGOC1WIiwgIlVuaUpJU1gwMjEzLVVURjMyLUgiLCAiVW5pSklTWDAyMTMtVVRGMzItViIsICJVbmlKSVNYMDIxMzIwMDQtVVRGMzItSCIsICJVbmlKSVNYMDIxMzIwMDQtVVRGMzItViIsICJVbmlLUy1VQ1MyLUgiLCAiVW5pS1MtVUNTMi1WIiwgIlVuaUtTLVVURjE2LUgiLCAiVW5pS1MtVVRGMTYtViIsICJVbmlLUy1VVEYzMi1IIiwgIlVuaUtTLVVURjMyLVYiLCAiVW5pS1MtVVRGOC1IIiwgIlVuaUtTLVVURjgtViIsICJWIiwgIldQLVN5bWJvbCJdOwpjb25zdCBNQVhfTUFQX1JBTkdFID0gMiAqKiAyNCAtIDE7CmNsYXNzIENNYXAgewogIGNvbnN0cnVjdG9yKGJ1aWx0SW5DTWFwID0gZmFsc2UpIHsKICAgIHRoaXMuY29kZXNwYWNlUmFuZ2VzID0gW1tdLCBbXSwgW10sIFtdXTsKICAgIHRoaXMubnVtQ29kZXNwYWNlUmFuZ2VzID0gMDsKICAgIHRoaXMuX21hcCA9IFtdOwogICAgdGhpcy5uYW1lID0gIiI7CiAgICB0aGlzLnZlcnRpY2FsID0gZmFsc2U7CiAgICB0aGlzLnVzZUNNYXAgPSBudWxsOwogICAgdGhpcy5idWlsdEluQ01hcCA9IGJ1aWx0SW5DTWFwOwogIH0KICBhZGRDb2Rlc3BhY2VSYW5nZShuLCBsb3csIGhpZ2gpIHsKICAgIHRoaXMuY29kZXNwYWNlUmFuZ2VzW24gLSAxXS5wdXNoKGxvdywgaGlnaCk7CiAgICB0aGlzLm51bUNvZGVzcGFjZVJhbmdlcysrOwogIH0KICBtYXBDaWRSYW5nZShsb3csIGhpZ2gsIGRzdExvdykgewogICAgaWYgKGhpZ2ggLSBsb3cgPiBNQVhfTUFQX1JBTkdFKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigibWFwQ2lkUmFuZ2UgLSBpZ25vcmluZyBkYXRhIGFib3ZlIE1BWF9NQVBfUkFOR0UuIik7CiAgICB9CiAgICB3aGlsZSAobG93IDw9IGhpZ2gpIHsKICAgICAgdGhpcy5fbWFwW2xvdysrXSA9IGRzdExvdysrOwogICAgfQogIH0KICBtYXBCZlJhbmdlKGxvdywgaGlnaCwgZHN0TG93KSB7CiAgICBpZiAoaGlnaCAtIGxvdyA+IE1BWF9NQVBfUkFOR0UpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJtYXBCZlJhbmdlIC0gaWdub3JpbmcgZGF0YSBhYm92ZSBNQVhfTUFQX1JBTkdFLiIpOwogICAgfQogICAgY29uc3QgbGFzdEJ5dGUgPSBkc3RMb3cubGVuZ3RoIC0gMTsKICAgIHdoaWxlIChsb3cgPD0gaGlnaCkgewogICAgICB0aGlzLl9tYXBbbG93KytdID0gZHN0TG93OwogICAgICBjb25zdCBuZXh0Q2hhckNvZGUgPSBkc3RMb3cuY2hhckNvZGVBdChsYXN0Qnl0ZSkgKyAxOwogICAgICBpZiAobmV4dENoYXJDb2RlID4gMHhmZikgewogICAgICAgIGRzdExvdyA9IGRzdExvdy5zdWJzdHJpbmcoMCwgbGFzdEJ5dGUgLSAxKSArIFN0cmluZy5mcm9tQ2hhckNvZGUoZHN0TG93LmNoYXJDb2RlQXQobGFzdEJ5dGUgLSAxKSArIDEpICsgIlx4MDAiOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGRzdExvdyA9IGRzdExvdy5zdWJzdHJpbmcoMCwgbGFzdEJ5dGUpICsgU3RyaW5nLmZyb21DaGFyQ29kZShuZXh0Q2hhckNvZGUpOwogICAgfQogIH0KICBtYXBCZlJhbmdlVG9BcnJheShsb3csIGhpZ2gsIGFycmF5KSB7CiAgICBpZiAoaGlnaCAtIGxvdyA+IE1BWF9NQVBfUkFOR0UpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJtYXBCZlJhbmdlVG9BcnJheSAtIGlnbm9yaW5nIGRhdGEgYWJvdmUgTUFYX01BUF9SQU5HRS4iKTsKICAgIH0KICAgIGNvbnN0IGlpID0gYXJyYXkubGVuZ3RoOwogICAgbGV0IGkgPSAwOwogICAgd2hpbGUgKGxvdyA8PSBoaWdoICYmIGkgPCBpaSkgewogICAgICB0aGlzLl9tYXBbbG93XSA9IGFycmF5W2krK107CiAgICAgICsrbG93OwogICAgfQogIH0KICBtYXBPbmUoc3JjLCBkc3QpIHsKICAgIHRoaXMuX21hcFtzcmNdID0gZHN0OwogIH0KICBsb29rdXAoY29kZSkgewogICAgcmV0dXJuIHRoaXMuX21hcFtjb2RlXTsKICB9CiAgY29udGFpbnMoY29kZSkgewogICAgcmV0dXJuIHRoaXMuX21hcFtjb2RlXSAhPT0gdW5kZWZpbmVkOwogIH0KICBmb3JFYWNoKGNhbGxiYWNrKSB7CiAgICBjb25zdCBtYXAgPSB0aGlzLl9tYXA7CiAgICBjb25zdCBsZW5ndGggPSBtYXAubGVuZ3RoOwogICAgaWYgKGxlbmd0aCA8PSAweDEwMDAwKSB7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICBpZiAobWFwW2ldICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGNhbGxiYWNrKGksIG1hcFtpXSk7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBmb3IgKGNvbnN0IGkgaW4gbWFwKSB7CiAgICAgICAgY2FsbGJhY2soaSwgbWFwW2ldKTsKICAgICAgfQogICAgfQogIH0KICBjaGFyQ29kZU9mKHZhbHVlKSB7CiAgICBjb25zdCBtYXAgPSB0aGlzLl9tYXA7CiAgICBpZiAobWFwLmxlbmd0aCA8PSAweDEwMDAwKSB7CiAgICAgIHJldHVybiBtYXAuaW5kZXhPZih2YWx1ZSk7CiAgICB9CiAgICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIG1hcCkgewogICAgICBpZiAobWFwW2NoYXJDb2RlXSA9PT0gdmFsdWUpIHsKICAgICAgICByZXR1cm4gY2hhckNvZGUgfCAwOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gLTE7CiAgfQogIGdldE1hcCgpIHsKICAgIHJldHVybiB0aGlzLl9tYXA7CiAgfQogIHJlYWRDaGFyQ29kZShzdHIsIG9mZnNldCwgb3V0KSB7CiAgICBsZXQgYyA9IDA7CiAgICBjb25zdCBjb2Rlc3BhY2VSYW5nZXMgPSB0aGlzLmNvZGVzcGFjZVJhbmdlczsKICAgIGZvciAobGV0IG4gPSAwLCBubiA9IGNvZGVzcGFjZVJhbmdlcy5sZW5ndGg7IG4gPCBubjsgbisrKSB7CiAgICAgIGMgPSAoYyA8PCA4IHwgc3RyLmNoYXJDb2RlQXQob2Zmc2V0ICsgbikpID4+PiAwOwogICAgICBjb25zdCBjb2Rlc3BhY2VSYW5nZSA9IGNvZGVzcGFjZVJhbmdlc1tuXTsKICAgICAgZm9yIChsZXQgayA9IDAsIGtrID0gY29kZXNwYWNlUmFuZ2UubGVuZ3RoOyBrIDwga2s7KSB7CiAgICAgICAgY29uc3QgbG93ID0gY29kZXNwYWNlUmFuZ2VbaysrXTsKICAgICAgICBjb25zdCBoaWdoID0gY29kZXNwYWNlUmFuZ2VbaysrXTsKICAgICAgICBpZiAoYyA+PSBsb3cgJiYgYyA8PSBoaWdoKSB7CiAgICAgICAgICBvdXQuY2hhcmNvZGUgPSBjOwogICAgICAgICAgb3V0Lmxlbmd0aCA9IG4gKyAxOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgb3V0LmNoYXJjb2RlID0gMDsKICAgIG91dC5sZW5ndGggPSAxOwogIH0KICBnZXRDaGFyQ29kZUxlbmd0aChjaGFyQ29kZSkgewogICAgY29uc3QgY29kZXNwYWNlUmFuZ2VzID0gdGhpcy5jb2Rlc3BhY2VSYW5nZXM7CiAgICBmb3IgKGxldCBuID0gMCwgbm4gPSBjb2Rlc3BhY2VSYW5nZXMubGVuZ3RoOyBuIDwgbm47IG4rKykgewogICAgICBjb25zdCBjb2Rlc3BhY2VSYW5nZSA9IGNvZGVzcGFjZVJhbmdlc1tuXTsKICAgICAgZm9yIChsZXQgayA9IDAsIGtrID0gY29kZXNwYWNlUmFuZ2UubGVuZ3RoOyBrIDwga2s7KSB7CiAgICAgICAgY29uc3QgbG93ID0gY29kZXNwYWNlUmFuZ2VbaysrXTsKICAgICAgICBjb25zdCBoaWdoID0gY29kZXNwYWNlUmFuZ2VbaysrXTsKICAgICAgICBpZiAoY2hhckNvZGUgPj0gbG93ICYmIGNoYXJDb2RlIDw9IGhpZ2gpIHsKICAgICAgICAgIHJldHVybiBuICsgMTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiAxOwogIH0KICBnZXQgbGVuZ3RoKCkgewogICAgcmV0dXJuIHRoaXMuX21hcC5sZW5ndGg7CiAgfQogIGdldCBpc0lkZW50aXR5Q01hcCgpIHsKICAgIGlmICghKHRoaXMubmFtZSA9PT0gIklkZW50aXR5LUgiIHx8IHRoaXMubmFtZSA9PT0gIklkZW50aXR5LVYiKSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy5fbWFwLmxlbmd0aCAhPT0gMHgxMDAwMCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDB4MTAwMDA7IGkrKykgewogICAgICBpZiAodGhpcy5fbWFwW2ldICE9PSBpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KY2xhc3MgSWRlbnRpdHlDTWFwIGV4dGVuZHMgQ01hcCB7CiAgY29uc3RydWN0b3IodmVydGljYWwsIG4pIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLnZlcnRpY2FsID0gdmVydGljYWw7CiAgICB0aGlzLmFkZENvZGVzcGFjZVJhbmdlKG4sIDAsIDB4ZmZmZik7CiAgfQogIG1hcENpZFJhbmdlKGxvdywgaGlnaCwgZHN0TG93KSB7CiAgICB1bnJlYWNoYWJsZSgic2hvdWxkIG5vdCBjYWxsIG1hcENpZFJhbmdlIik7CiAgfQogIG1hcEJmUmFuZ2UobG93LCBoaWdoLCBkc3RMb3cpIHsKICAgIHVucmVhY2hhYmxlKCJzaG91bGQgbm90IGNhbGwgbWFwQmZSYW5nZSIpOwogIH0KICBtYXBCZlJhbmdlVG9BcnJheShsb3csIGhpZ2gsIGFycmF5KSB7CiAgICB1bnJlYWNoYWJsZSgic2hvdWxkIG5vdCBjYWxsIG1hcEJmUmFuZ2VUb0FycmF5Iik7CiAgfQogIG1hcE9uZShzcmMsIGRzdCkgewogICAgdW5yZWFjaGFibGUoInNob3VsZCBub3QgY2FsbCBtYXBDaWRPbmUiKTsKICB9CiAgbG9va3VwKGNvZGUpIHsKICAgIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKGNvZGUpICYmIGNvZGUgPD0gMHhmZmZmID8gY29kZSA6IHVuZGVmaW5lZDsKICB9CiAgY29udGFpbnMoY29kZSkgewogICAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIoY29kZSkgJiYgY29kZSA8PSAweGZmZmY7CiAgfQogIGZvckVhY2goY2FsbGJhY2spIHsKICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IDB4ZmZmZjsgaSsrKSB7CiAgICAgIGNhbGxiYWNrKGksIGkpOwogICAgfQogIH0KICBjaGFyQ29kZU9mKHZhbHVlKSB7CiAgICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcih2YWx1ZSkgJiYgdmFsdWUgPD0gMHhmZmZmID8gdmFsdWUgOiAtMTsKICB9CiAgZ2V0TWFwKCkgewogICAgY29uc3QgbWFwID0gbmV3IEFycmF5KDB4MTAwMDApOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gMHhmZmZmOyBpKyspIHsKICAgICAgbWFwW2ldID0gaTsKICAgIH0KICAgIHJldHVybiBtYXA7CiAgfQogIGdldCBsZW5ndGgoKSB7CiAgICByZXR1cm4gMHgxMDAwMDsKICB9CiAgZ2V0IGlzSWRlbnRpdHlDTWFwKCkgewogICAgdW5yZWFjaGFibGUoInNob3VsZCBub3QgYWNjZXNzIC5pc0lkZW50aXR5Q01hcCIpOwogIH0KfQpmdW5jdGlvbiBzdHJUb0ludChzdHIpIHsKICBsZXQgYSA9IDA7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHsKICAgIGEgPSBhIDw8IDggfCBzdHIuY2hhckNvZGVBdChpKTsKICB9CiAgcmV0dXJuIGEgPj4+IDA7Cn0KZnVuY3Rpb24gZXhwZWN0U3RyaW5nKG9iaikgewogIGlmICh0eXBlb2Ygb2JqICE9PSAic3RyaW5nIikgewogICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJNYWxmb3JtZWQgQ01hcDogZXhwZWN0ZWQgc3RyaW5nLiIpOwogIH0KfQpmdW5jdGlvbiBleHBlY3RJbnQob2JqKSB7CiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKG9iaikpIHsKICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiTWFsZm9ybWVkIENNYXA6IGV4cGVjdGVkIGludC4iKTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VCZkNoYXIoY01hcCwgbGV4ZXIpIHsKICB3aGlsZSAodHJ1ZSkgewogICAgbGV0IG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgaWYgKG9iaiA9PT0gRU9GKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgaWYgKGlzQ21kKG9iaiwgImVuZGJmY2hhciIpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGV4cGVjdFN0cmluZyhvYmopOwogICAgY29uc3Qgc3JjID0gc3RyVG9JbnQob2JqKTsKICAgIG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgZXhwZWN0U3RyaW5nKG9iaik7CiAgICBjb25zdCBkc3QgPSBvYmo7CiAgICBjTWFwLm1hcE9uZShzcmMsIGRzdCk7CiAgfQp9CmZ1bmN0aW9uIHBhcnNlQmZSYW5nZShjTWFwLCBsZXhlcikgewogIHdoaWxlICh0cnVlKSB7CiAgICBsZXQgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICBpZiAob2JqID09PSBFT0YpIHsKICAgICAgYnJlYWs7CiAgICB9CiAgICBpZiAoaXNDbWQob2JqLCAiZW5kYmZyYW5nZSIpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGV4cGVjdFN0cmluZyhvYmopOwogICAgY29uc3QgbG93ID0gc3RyVG9JbnQob2JqKTsKICAgIG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgZXhwZWN0U3RyaW5nKG9iaik7CiAgICBjb25zdCBoaWdoID0gc3RyVG9JbnQob2JqKTsKICAgIG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgaWYgKE51bWJlci5pc0ludGVnZXIob2JqKSB8fCB0eXBlb2Ygb2JqID09PSAic3RyaW5nIikgewogICAgICBjb25zdCBkc3RMb3cgPSBOdW1iZXIuaXNJbnRlZ2VyKG9iaikgPyBTdHJpbmcuZnJvbUNoYXJDb2RlKG9iaikgOiBvYmo7CiAgICAgIGNNYXAubWFwQmZSYW5nZShsb3csIGhpZ2gsIGRzdExvdyk7CiAgICB9IGVsc2UgaWYgKGlzQ21kKG9iaiwgIlsiKSkgewogICAgICBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgICAgY29uc3QgYXJyYXkgPSBbXTsKICAgICAgd2hpbGUgKCFpc0NtZChvYmosICJdIikgJiYgb2JqICE9PSBFT0YpIHsKICAgICAgICBhcnJheS5wdXNoKG9iaik7CiAgICAgICAgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICAgIH0KICAgICAgY01hcC5tYXBCZlJhbmdlVG9BcnJheShsb3csIGhpZ2gsIGFycmF5KTsKICAgIH0gZWxzZSB7CiAgICAgIGJyZWFrOwogICAgfQogIH0KICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgYmYgcmFuZ2UuIik7Cn0KZnVuY3Rpb24gcGFyc2VDaWRDaGFyKGNNYXAsIGxleGVyKSB7CiAgd2hpbGUgKHRydWUpIHsKICAgIGxldCBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgIGlmIChvYmogPT09IEVPRikgewogICAgICBicmVhazsKICAgIH0KICAgIGlmIChpc0NtZChvYmosICJlbmRjaWRjaGFyIikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgZXhwZWN0U3RyaW5nKG9iaik7CiAgICBjb25zdCBzcmMgPSBzdHJUb0ludChvYmopOwogICAgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICBleHBlY3RJbnQob2JqKTsKICAgIGNvbnN0IGRzdCA9IG9iajsKICAgIGNNYXAubWFwT25lKHNyYywgZHN0KTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VDaWRSYW5nZShjTWFwLCBsZXhlcikgewogIHdoaWxlICh0cnVlKSB7CiAgICBsZXQgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICBpZiAob2JqID09PSBFT0YpIHsKICAgICAgYnJlYWs7CiAgICB9CiAgICBpZiAoaXNDbWQob2JqLCAiZW5kY2lkcmFuZ2UiKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBleHBlY3RTdHJpbmcob2JqKTsKICAgIGNvbnN0IGxvdyA9IHN0clRvSW50KG9iaik7CiAgICBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgIGV4cGVjdFN0cmluZyhvYmopOwogICAgY29uc3QgaGlnaCA9IHN0clRvSW50KG9iaik7CiAgICBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgIGV4cGVjdEludChvYmopOwogICAgY29uc3QgZHN0TG93ID0gb2JqOwogICAgY01hcC5tYXBDaWRSYW5nZShsb3csIGhpZ2gsIGRzdExvdyk7CiAgfQp9CmZ1bmN0aW9uIHBhcnNlQ29kZXNwYWNlUmFuZ2UoY01hcCwgbGV4ZXIpIHsKICB3aGlsZSAodHJ1ZSkgewogICAgbGV0IG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgaWYgKG9iaiA9PT0gRU9GKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgaWYgKGlzQ21kKG9iaiwgImVuZGNvZGVzcGFjZXJhbmdlIikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKHR5cGVvZiBvYmogIT09ICJzdHJpbmciKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgY29uc3QgbG93ID0gc3RyVG9JbnQob2JqKTsKICAgIG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgaWYgKHR5cGVvZiBvYmogIT09ICJzdHJpbmciKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgY29uc3QgaGlnaCA9IHN0clRvSW50KG9iaik7CiAgICBjTWFwLmFkZENvZGVzcGFjZVJhbmdlKG9iai5sZW5ndGgsIGxvdywgaGlnaCk7CiAgfQogIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBjb2Rlc3BhY2UgcmFuZ2UuIik7Cn0KZnVuY3Rpb24gcGFyc2VXTW9kZShjTWFwLCBsZXhlcikgewogIGNvbnN0IG9iaiA9IGxleGVyLmdldE9iaigpOwogIGlmIChOdW1iZXIuaXNJbnRlZ2VyKG9iaikpIHsKICAgIGNNYXAudmVydGljYWwgPSAhIW9iajsKICB9Cn0KZnVuY3Rpb24gcGFyc2VDTWFwTmFtZShjTWFwLCBsZXhlcikgewogIGNvbnN0IG9iaiA9IGxleGVyLmdldE9iaigpOwogIGlmIChvYmogaW5zdGFuY2VvZiBOYW1lKSB7CiAgICBjTWFwLm5hbWUgPSBvYmoubmFtZTsKICB9Cn0KYXN5bmMgZnVuY3Rpb24gcGFyc2VDTWFwKGNNYXAsIGxleGVyLCBmZXRjaEJ1aWx0SW5DTWFwLCB1c2VDTWFwKSB7CiAgbGV0IHByZXZpb3VzLCBlbWJlZGRlZFVzZUNNYXA7CiAgb2JqTG9vcDogd2hpbGUgKHRydWUpIHsKICAgIHRyeSB7CiAgICAgIGNvbnN0IG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgICBpZiAob2JqID09PSBFT0YpIHsKICAgICAgICBicmVhazsKICAgICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgaWYgKG9iai5uYW1lID09PSAiV01vZGUiKSB7CiAgICAgICAgICBwYXJzZVdNb2RlKGNNYXAsIGxleGVyKTsKICAgICAgICB9IGVsc2UgaWYgKG9iai5uYW1lID09PSAiQ01hcE5hbWUiKSB7CiAgICAgICAgICBwYXJzZUNNYXBOYW1lKGNNYXAsIGxleGVyKTsKICAgICAgICB9CiAgICAgICAgcHJldmlvdXMgPSBvYmo7CiAgICAgIH0gZWxzZSBpZiAob2JqIGluc3RhbmNlb2YgQ21kKSB7CiAgICAgICAgc3dpdGNoIChvYmouY21kKSB7CiAgICAgICAgICBjYXNlICJlbmRjbWFwIjoKICAgICAgICAgICAgYnJlYWsgb2JqTG9vcDsKICAgICAgICAgIGNhc2UgInVzZWNtYXAiOgogICAgICAgICAgICBpZiAocHJldmlvdXMgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgICAgZW1iZWRkZWRVc2VDTWFwID0gcHJldmlvdXMubmFtZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgImJlZ2luY29kZXNwYWNlcmFuZ2UiOgogICAgICAgICAgICBwYXJzZUNvZGVzcGFjZVJhbmdlKGNNYXAsIGxleGVyKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICJiZWdpbmJmY2hhciI6CiAgICAgICAgICAgIHBhcnNlQmZDaGFyKGNNYXAsIGxleGVyKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICJiZWdpbmNpZGNoYXIiOgogICAgICAgICAgICBwYXJzZUNpZENoYXIoY01hcCwgbGV4ZXIpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgImJlZ2luYmZyYW5nZSI6CiAgICAgICAgICAgIHBhcnNlQmZSYW5nZShjTWFwLCBsZXhlcik7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAiYmVnaW5jaWRyYW5nZSI6CiAgICAgICAgICAgIHBhcnNlQ2lkUmFuZ2UoY01hcCwgbGV4ZXIpOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgd2FybigiSW52YWxpZCBjTWFwIGRhdGE6ICIgKyBleCk7CiAgICAgIGNvbnRpbnVlOwogICAgfQogIH0KICBpZiAoIXVzZUNNYXAgJiYgZW1iZWRkZWRVc2VDTWFwKSB7CiAgICB1c2VDTWFwID0gZW1iZWRkZWRVc2VDTWFwOwogIH0KICBpZiAodXNlQ01hcCkgewogICAgcmV0dXJuIGV4dGVuZENNYXAoY01hcCwgZmV0Y2hCdWlsdEluQ01hcCwgdXNlQ01hcCk7CiAgfQogIHJldHVybiBjTWFwOwp9CmFzeW5jIGZ1bmN0aW9uIGV4dGVuZENNYXAoY01hcCwgZmV0Y2hCdWlsdEluQ01hcCwgdXNlQ01hcCkgewogIGNNYXAudXNlQ01hcCA9IGF3YWl0IGNyZWF0ZUJ1aWx0SW5DTWFwKHVzZUNNYXAsIGZldGNoQnVpbHRJbkNNYXApOwogIGlmIChjTWFwLm51bUNvZGVzcGFjZVJhbmdlcyA9PT0gMCkgewogICAgY29uc3QgdXNlQ29kZXNwYWNlUmFuZ2VzID0gY01hcC51c2VDTWFwLmNvZGVzcGFjZVJhbmdlczsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdXNlQ29kZXNwYWNlUmFuZ2VzLmxlbmd0aDsgaSsrKSB7CiAgICAgIGNNYXAuY29kZXNwYWNlUmFuZ2VzW2ldID0gdXNlQ29kZXNwYWNlUmFuZ2VzW2ldLnNsaWNlKCk7CiAgICB9CiAgICBjTWFwLm51bUNvZGVzcGFjZVJhbmdlcyA9IGNNYXAudXNlQ01hcC5udW1Db2Rlc3BhY2VSYW5nZXM7CiAgfQogIGNNYXAudXNlQ01hcC5mb3JFYWNoKGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7CiAgICBpZiAoIWNNYXAuY29udGFpbnMoa2V5KSkgewogICAgICBjTWFwLm1hcE9uZShrZXksIHZhbHVlKTsKICAgIH0KICB9KTsKICByZXR1cm4gY01hcDsKfQphc3luYyBmdW5jdGlvbiBjcmVhdGVCdWlsdEluQ01hcChuYW1lLCBmZXRjaEJ1aWx0SW5DTWFwKSB7CiAgaWYgKG5hbWUgPT09ICJJZGVudGl0eS1IIikgewogICAgcmV0dXJuIG5ldyBJZGVudGl0eUNNYXAoZmFsc2UsIDIpOwogIH0gZWxzZSBpZiAobmFtZSA9PT0gIklkZW50aXR5LVYiKSB7CiAgICByZXR1cm4gbmV3IElkZW50aXR5Q01hcCh0cnVlLCAyKTsKICB9CiAgaWYgKCFCVUlMVF9JTl9DTUFQUy5pbmNsdWRlcyhuYW1lKSkgewogICAgdGhyb3cgbmV3IEVycm9yKCJVbmtub3duIENNYXAgbmFtZTogIiArIG5hbWUpOwogIH0KICBpZiAoIWZldGNoQnVpbHRJbkNNYXApIHsKICAgIHRocm93IG5ldyBFcnJvcigiQnVpbHQtaW4gQ01hcCBwYXJhbWV0ZXJzIGFyZSBub3QgcHJvdmlkZWQuIik7CiAgfQogIGNvbnN0IHsKICAgIGNNYXBEYXRhLAogICAgaXNDb21wcmVzc2VkCiAgfSA9IGF3YWl0IGZldGNoQnVpbHRJbkNNYXAobmFtZSk7CiAgY29uc3QgY01hcCA9IG5ldyBDTWFwKHRydWUpOwogIGlmIChpc0NvbXByZXNzZWQpIHsKICAgIHJldHVybiBuZXcgQmluYXJ5Q01hcFJlYWRlcigpLnByb2Nlc3MoY01hcERhdGEsIGNNYXAsIHVzZUNNYXAgPT4gZXh0ZW5kQ01hcChjTWFwLCBmZXRjaEJ1aWx0SW5DTWFwLCB1c2VDTWFwKSk7CiAgfQogIGNvbnN0IGxleGVyID0gbmV3IExleGVyKG5ldyBTdHJlYW0oY01hcERhdGEpKTsKICByZXR1cm4gcGFyc2VDTWFwKGNNYXAsIGxleGVyLCBmZXRjaEJ1aWx0SW5DTWFwLCBudWxsKTsKfQpjbGFzcyBDTWFwRmFjdG9yeSB7CiAgc3RhdGljIGFzeW5jIGNyZWF0ZSh7CiAgICBlbmNvZGluZywKICAgIGZldGNoQnVpbHRJbkNNYXAsCiAgICB1c2VDTWFwCiAgfSkgewogICAgaWYgKGVuY29kaW5nIGluc3RhbmNlb2YgTmFtZSkgewogICAgICByZXR1cm4gY3JlYXRlQnVpbHRJbkNNYXAoZW5jb2RpbmcubmFtZSwgZmV0Y2hCdWlsdEluQ01hcCk7CiAgICB9IGVsc2UgaWYgKGVuY29kaW5nIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICBpZiAoZW5jb2RpbmcuaXNBc3luYykgewogICAgICAgIGNvbnN0IGJ5dGVzID0gYXdhaXQgZW5jb2RpbmcuYXN5bmNHZXRCeXRlcygpOwogICAgICAgIGlmIChieXRlcykgewogICAgICAgICAgZW5jb2RpbmcgPSBuZXcgU3RyZWFtKGJ5dGVzLCAwLCBieXRlcy5sZW5ndGgsIGVuY29kaW5nLmRpY3QpOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBwYXJzZWRDTWFwID0gYXdhaXQgcGFyc2VDTWFwKG5ldyBDTWFwKCksIG5ldyBMZXhlcihlbmNvZGluZyksIGZldGNoQnVpbHRJbkNNYXAsIHVzZUNNYXApOwogICAgICBpZiAocGFyc2VkQ01hcC5pc0lkZW50aXR5Q01hcCkgewogICAgICAgIHJldHVybiBjcmVhdGVCdWlsdEluQ01hcChwYXJzZWRDTWFwLm5hbWUsIGZldGNoQnVpbHRJbkNNYXApOwogICAgICB9CiAgICAgIHJldHVybiBwYXJzZWRDTWFwOwogICAgfQogICAgdGhyb3cgbmV3IEVycm9yKCJFbmNvZGluZyByZXF1aXJlZC4iKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2VuY29kaW5ncy5qcwpjb25zdCBFeHBlcnRFbmNvZGluZyA9IFsiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJzcGFjZSIsICJleGNsYW1zbWFsbCIsICJIdW5nYXJ1bWxhdXRzbWFsbCIsICIiLCAiZG9sbGFyb2xkc3R5bGUiLCAiZG9sbGFyc3VwZXJpb3IiLCAiYW1wZXJzYW5kc21hbGwiLCAiQWN1dGVzbWFsbCIsICJwYXJlbmxlZnRzdXBlcmlvciIsICJwYXJlbnJpZ2h0c3VwZXJpb3IiLCAidHdvZG90ZW5sZWFkZXIiLCAib25lZG90ZW5sZWFkZXIiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJmcmFjdGlvbiIsICJ6ZXJvb2xkc3R5bGUiLCAib25lb2xkc3R5bGUiLCAidHdvb2xkc3R5bGUiLCAidGhyZWVvbGRzdHlsZSIsICJmb3Vyb2xkc3R5bGUiLCAiZml2ZW9sZHN0eWxlIiwgInNpeG9sZHN0eWxlIiwgInNldmVub2xkc3R5bGUiLCAiZWlnaHRvbGRzdHlsZSIsICJuaW5lb2xkc3R5bGUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgImNvbW1hc3VwZXJpb3IiLCAidGhyZWVxdWFydGVyc2VtZGFzaCIsICJwZXJpb2RzdXBlcmlvciIsICJxdWVzdGlvbnNtYWxsIiwgIiIsICJhc3VwZXJpb3IiLCAiYnN1cGVyaW9yIiwgImNlbnRzdXBlcmlvciIsICJkc3VwZXJpb3IiLCAiZXN1cGVyaW9yIiwgIiIsICIiLCAiIiwgImlzdXBlcmlvciIsICIiLCAiIiwgImxzdXBlcmlvciIsICJtc3VwZXJpb3IiLCAibnN1cGVyaW9yIiwgIm9zdXBlcmlvciIsICIiLCAiIiwgInJzdXBlcmlvciIsICJzc3VwZXJpb3IiLCAidHN1cGVyaW9yIiwgIiIsICJmZiIsICJmaSIsICJmbCIsICJmZmkiLCAiZmZsIiwgInBhcmVubGVmdGluZmVyaW9yIiwgIiIsICJwYXJlbnJpZ2h0aW5mZXJpb3IiLCAiQ2lyY3VtZmxleHNtYWxsIiwgImh5cGhlbnN1cGVyaW9yIiwgIkdyYXZlc21hbGwiLCAiQXNtYWxsIiwgIkJzbWFsbCIsICJDc21hbGwiLCAiRHNtYWxsIiwgIkVzbWFsbCIsICJGc21hbGwiLCAiR3NtYWxsIiwgIkhzbWFsbCIsICJJc21hbGwiLCAiSnNtYWxsIiwgIktzbWFsbCIsICJMc21hbGwiLCAiTXNtYWxsIiwgIk5zbWFsbCIsICJPc21hbGwiLCAiUHNtYWxsIiwgIlFzbWFsbCIsICJSc21hbGwiLCAiU3NtYWxsIiwgIlRzbWFsbCIsICJVc21hbGwiLCAiVnNtYWxsIiwgIldzbWFsbCIsICJYc21hbGwiLCAiWXNtYWxsIiwgIlpzbWFsbCIsICJjb2xvbm1vbmV0YXJ5IiwgIm9uZWZpdHRlZCIsICJydXBpYWgiLCAiVGlsZGVzbWFsbCIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiZXhjbGFtZG93bnNtYWxsIiwgImNlbnRvbGRzdHlsZSIsICJMc2xhc2hzbWFsbCIsICIiLCAiIiwgIlNjYXJvbnNtYWxsIiwgIlpjYXJvbnNtYWxsIiwgIkRpZXJlc2lzc21hbGwiLCAiQnJldmVzbWFsbCIsICJDYXJvbnNtYWxsIiwgIiIsICJEb3RhY2NlbnRzbWFsbCIsICIiLCAiIiwgIk1hY3JvbnNtYWxsIiwgIiIsICIiLCAiZmlndXJlZGFzaCIsICJoeXBoZW5pbmZlcmlvciIsICIiLCAiIiwgIk9nb25la3NtYWxsIiwgIlJpbmdzbWFsbCIsICJDZWRpbGxhc21hbGwiLCAiIiwgIiIsICIiLCAib25lcXVhcnRlciIsICJvbmVoYWxmIiwgInRocmVlcXVhcnRlcnMiLCAicXVlc3Rpb25kb3duc21hbGwiLCAib25lZWlnaHRoIiwgInRocmVlZWlnaHRocyIsICJmaXZlZWlnaHRocyIsICJzZXZlbmVpZ2h0aHMiLCAib25ldGhpcmQiLCAidHdvdGhpcmRzIiwgIiIsICIiLCAiemVyb3N1cGVyaW9yIiwgIm9uZXN1cGVyaW9yIiwgInR3b3N1cGVyaW9yIiwgInRocmVlc3VwZXJpb3IiLCAiZm91cnN1cGVyaW9yIiwgImZpdmVzdXBlcmlvciIsICJzaXhzdXBlcmlvciIsICJzZXZlbnN1cGVyaW9yIiwgImVpZ2h0c3VwZXJpb3IiLCAibmluZXN1cGVyaW9yIiwgInplcm9pbmZlcmlvciIsICJvbmVpbmZlcmlvciIsICJ0d29pbmZlcmlvciIsICJ0aHJlZWluZmVyaW9yIiwgImZvdXJpbmZlcmlvciIsICJmaXZlaW5mZXJpb3IiLCAic2l4aW5mZXJpb3IiLCAic2V2ZW5pbmZlcmlvciIsICJlaWdodGluZmVyaW9yIiwgIm5pbmVpbmZlcmlvciIsICJjZW50aW5mZXJpb3IiLCAiZG9sbGFyaW5mZXJpb3IiLCAicGVyaW9kaW5mZXJpb3IiLCAiY29tbWFpbmZlcmlvciIsICJBZ3JhdmVzbWFsbCIsICJBYWN1dGVzbWFsbCIsICJBY2lyY3VtZmxleHNtYWxsIiwgIkF0aWxkZXNtYWxsIiwgIkFkaWVyZXNpc3NtYWxsIiwgIkFyaW5nc21hbGwiLCAiQUVzbWFsbCIsICJDY2VkaWxsYXNtYWxsIiwgIkVncmF2ZXNtYWxsIiwgIkVhY3V0ZXNtYWxsIiwgIkVjaXJjdW1mbGV4c21hbGwiLCAiRWRpZXJlc2lzc21hbGwiLCAiSWdyYXZlc21hbGwiLCAiSWFjdXRlc21hbGwiLCAiSWNpcmN1bWZsZXhzbWFsbCIsICJJZGllcmVzaXNzbWFsbCIsICJFdGhzbWFsbCIsICJOdGlsZGVzbWFsbCIsICJPZ3JhdmVzbWFsbCIsICJPYWN1dGVzbWFsbCIsICJPY2lyY3VtZmxleHNtYWxsIiwgIk90aWxkZXNtYWxsIiwgIk9kaWVyZXNpc3NtYWxsIiwgIk9Fc21hbGwiLCAiT3NsYXNoc21hbGwiLCAiVWdyYXZlc21hbGwiLCAiVWFjdXRlc21hbGwiLCAiVWNpcmN1bWZsZXhzbWFsbCIsICJVZGllcmVzaXNzbWFsbCIsICJZYWN1dGVzbWFsbCIsICJUaG9ybnNtYWxsIiwgIllkaWVyZXNpc3NtYWxsIl07CmNvbnN0IE1hY0V4cGVydEVuY29kaW5nID0gWyIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgInNwYWNlIiwgImV4Y2xhbXNtYWxsIiwgIkh1bmdhcnVtbGF1dHNtYWxsIiwgImNlbnRvbGRzdHlsZSIsICJkb2xsYXJvbGRzdHlsZSIsICJkb2xsYXJzdXBlcmlvciIsICJhbXBlcnNhbmRzbWFsbCIsICJBY3V0ZXNtYWxsIiwgInBhcmVubGVmdHN1cGVyaW9yIiwgInBhcmVucmlnaHRzdXBlcmlvciIsICJ0d29kb3RlbmxlYWRlciIsICJvbmVkb3RlbmxlYWRlciIsICJjb21tYSIsICJoeXBoZW4iLCAicGVyaW9kIiwgImZyYWN0aW9uIiwgInplcm9vbGRzdHlsZSIsICJvbmVvbGRzdHlsZSIsICJ0d29vbGRzdHlsZSIsICJ0aHJlZW9sZHN0eWxlIiwgImZvdXJvbGRzdHlsZSIsICJmaXZlb2xkc3R5bGUiLCAic2l4b2xkc3R5bGUiLCAic2V2ZW5vbGRzdHlsZSIsICJlaWdodG9sZHN0eWxlIiwgIm5pbmVvbGRzdHlsZSIsICJjb2xvbiIsICJzZW1pY29sb24iLCAiIiwgInRocmVlcXVhcnRlcnNlbWRhc2giLCAiIiwgInF1ZXN0aW9uc21hbGwiLCAiIiwgIiIsICIiLCAiIiwgIkV0aHNtYWxsIiwgIiIsICIiLCAib25lcXVhcnRlciIsICJvbmVoYWxmIiwgInRocmVlcXVhcnRlcnMiLCAib25lZWlnaHRoIiwgInRocmVlZWlnaHRocyIsICJmaXZlZWlnaHRocyIsICJzZXZlbmVpZ2h0aHMiLCAib25ldGhpcmQiLCAidHdvdGhpcmRzIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgImZmIiwgImZpIiwgImZsIiwgImZmaSIsICJmZmwiLCAicGFyZW5sZWZ0aW5mZXJpb3IiLCAiIiwgInBhcmVucmlnaHRpbmZlcmlvciIsICJDaXJjdW1mbGV4c21hbGwiLCAiaHlwaGVuaW5mZXJpb3IiLCAiR3JhdmVzbWFsbCIsICJBc21hbGwiLCAiQnNtYWxsIiwgIkNzbWFsbCIsICJEc21hbGwiLCAiRXNtYWxsIiwgIkZzbWFsbCIsICJHc21hbGwiLCAiSHNtYWxsIiwgIklzbWFsbCIsICJKc21hbGwiLCAiS3NtYWxsIiwgIkxzbWFsbCIsICJNc21hbGwiLCAiTnNtYWxsIiwgIk9zbWFsbCIsICJQc21hbGwiLCAiUXNtYWxsIiwgIlJzbWFsbCIsICJTc21hbGwiLCAiVHNtYWxsIiwgIlVzbWFsbCIsICJWc21hbGwiLCAiV3NtYWxsIiwgIlhzbWFsbCIsICJZc21hbGwiLCAiWnNtYWxsIiwgImNvbG9ubW9uZXRhcnkiLCAib25lZml0dGVkIiwgInJ1cGlhaCIsICJUaWxkZXNtYWxsIiwgIiIsICIiLCAiYXN1cGVyaW9yIiwgImNlbnRzdXBlcmlvciIsICIiLCAiIiwgIiIsICIiLCAiQWFjdXRlc21hbGwiLCAiQWdyYXZlc21hbGwiLCAiQWNpcmN1bWZsZXhzbWFsbCIsICJBZGllcmVzaXNzbWFsbCIsICJBdGlsZGVzbWFsbCIsICJBcmluZ3NtYWxsIiwgIkNjZWRpbGxhc21hbGwiLCAiRWFjdXRlc21hbGwiLCAiRWdyYXZlc21hbGwiLCAiRWNpcmN1bWZsZXhzbWFsbCIsICJFZGllcmVzaXNzbWFsbCIsICJJYWN1dGVzbWFsbCIsICJJZ3JhdmVzbWFsbCIsICJJY2lyY3VtZmxleHNtYWxsIiwgIklkaWVyZXNpc3NtYWxsIiwgIk50aWxkZXNtYWxsIiwgIk9hY3V0ZXNtYWxsIiwgIk9ncmF2ZXNtYWxsIiwgIk9jaXJjdW1mbGV4c21hbGwiLCAiT2RpZXJlc2lzc21hbGwiLCAiT3RpbGRlc21hbGwiLCAiVWFjdXRlc21hbGwiLCAiVWdyYXZlc21hbGwiLCAiVWNpcmN1bWZsZXhzbWFsbCIsICJVZGllcmVzaXNzbWFsbCIsICIiLCAiZWlnaHRzdXBlcmlvciIsICJmb3VyaW5mZXJpb3IiLCAidGhyZWVpbmZlcmlvciIsICJzaXhpbmZlcmlvciIsICJlaWdodGluZmVyaW9yIiwgInNldmVuaW5mZXJpb3IiLCAiU2Nhcm9uc21hbGwiLCAiIiwgImNlbnRpbmZlcmlvciIsICJ0d29pbmZlcmlvciIsICIiLCAiRGllcmVzaXNzbWFsbCIsICIiLCAiQ2Fyb25zbWFsbCIsICJvc3VwZXJpb3IiLCAiZml2ZWluZmVyaW9yIiwgIiIsICJjb21tYWluZmVyaW9yIiwgInBlcmlvZGluZmVyaW9yIiwgIllhY3V0ZXNtYWxsIiwgIiIsICJkb2xsYXJpbmZlcmlvciIsICIiLCAiIiwgIlRob3Juc21hbGwiLCAiIiwgIm5pbmVpbmZlcmlvciIsICJ6ZXJvaW5mZXJpb3IiLCAiWmNhcm9uc21hbGwiLCAiQUVzbWFsbCIsICJPc2xhc2hzbWFsbCIsICJxdWVzdGlvbmRvd25zbWFsbCIsICJvbmVpbmZlcmlvciIsICJMc2xhc2hzbWFsbCIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJDZWRpbGxhc21hbGwiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJPRXNtYWxsIiwgImZpZ3VyZWRhc2giLCAiaHlwaGVuc3VwZXJpb3IiLCAiIiwgIiIsICIiLCAiIiwgImV4Y2xhbWRvd25zbWFsbCIsICIiLCAiWWRpZXJlc2lzc21hbGwiLCAiIiwgIm9uZXN1cGVyaW9yIiwgInR3b3N1cGVyaW9yIiwgInRocmVlc3VwZXJpb3IiLCAiZm91cnN1cGVyaW9yIiwgImZpdmVzdXBlcmlvciIsICJzaXhzdXBlcmlvciIsICJzZXZlbnN1cGVyaW9yIiwgIm5pbmVzdXBlcmlvciIsICJ6ZXJvc3VwZXJpb3IiLCAiIiwgImVzdXBlcmlvciIsICJyc3VwZXJpb3IiLCAidHN1cGVyaW9yIiwgIiIsICIiLCAiaXN1cGVyaW9yIiwgInNzdXBlcmlvciIsICJkc3VwZXJpb3IiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJsc3VwZXJpb3IiLCAiT2dvbmVrc21hbGwiLCAiQnJldmVzbWFsbCIsICJNYWNyb25zbWFsbCIsICJic3VwZXJpb3IiLCAibnN1cGVyaW9yIiwgIm1zdXBlcmlvciIsICJjb21tYXN1cGVyaW9yIiwgInBlcmlvZHN1cGVyaW9yIiwgIkRvdGFjY2VudHNtYWxsIiwgIlJpbmdzbWFsbCIsICIiLCAiIiwgIiIsICIiXTsKY29uc3QgTWFjUm9tYW5FbmNvZGluZyA9IFsiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJzcGFjZSIsICJleGNsYW0iLCAicXVvdGVkYmwiLCAibnVtYmVyc2lnbiIsICJkb2xsYXIiLCAicGVyY2VudCIsICJhbXBlcnNhbmQiLCAicXVvdGVzaW5nbGUiLCAicGFyZW5sZWZ0IiwgInBhcmVucmlnaHQiLCAiYXN0ZXJpc2siLCAicGx1cyIsICJjb21tYSIsICJoeXBoZW4iLCAicGVyaW9kIiwgInNsYXNoIiwgInplcm8iLCAib25lIiwgInR3byIsICJ0aHJlZSIsICJmb3VyIiwgImZpdmUiLCAic2l4IiwgInNldmVuIiwgImVpZ2h0IiwgIm5pbmUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgImxlc3MiLCAiZXF1YWwiLCAiZ3JlYXRlciIsICJxdWVzdGlvbiIsICJhdCIsICJBIiwgIkIiLCAiQyIsICJEIiwgIkUiLCAiRiIsICJHIiwgIkgiLCAiSSIsICJKIiwgIksiLCAiTCIsICJNIiwgIk4iLCAiTyIsICJQIiwgIlEiLCAiUiIsICJTIiwgIlQiLCAiVSIsICJWIiwgIlciLCAiWCIsICJZIiwgIloiLCAiYnJhY2tldGxlZnQiLCAiYmFja3NsYXNoIiwgImJyYWNrZXRyaWdodCIsICJhc2NpaWNpcmN1bSIsICJ1bmRlcnNjb3JlIiwgImdyYXZlIiwgImEiLCAiYiIsICJjIiwgImQiLCAiZSIsICJmIiwgImciLCAiaCIsICJpIiwgImoiLCAiayIsICJsIiwgIm0iLCAibiIsICJvIiwgInAiLCAicSIsICJyIiwgInMiLCAidCIsICJ1IiwgInYiLCAidyIsICJ4IiwgInkiLCAieiIsICJicmFjZWxlZnQiLCAiYmFyIiwgImJyYWNlcmlnaHQiLCAiYXNjaWl0aWxkZSIsICIiLCAiQWRpZXJlc2lzIiwgIkFyaW5nIiwgIkNjZWRpbGxhIiwgIkVhY3V0ZSIsICJOdGlsZGUiLCAiT2RpZXJlc2lzIiwgIlVkaWVyZXNpcyIsICJhYWN1dGUiLCAiYWdyYXZlIiwgImFjaXJjdW1mbGV4IiwgImFkaWVyZXNpcyIsICJhdGlsZGUiLCAiYXJpbmciLCAiY2NlZGlsbGEiLCAiZWFjdXRlIiwgImVncmF2ZSIsICJlY2lyY3VtZmxleCIsICJlZGllcmVzaXMiLCAiaWFjdXRlIiwgImlncmF2ZSIsICJpY2lyY3VtZmxleCIsICJpZGllcmVzaXMiLCAibnRpbGRlIiwgIm9hY3V0ZSIsICJvZ3JhdmUiLCAib2NpcmN1bWZsZXgiLCAib2RpZXJlc2lzIiwgIm90aWxkZSIsICJ1YWN1dGUiLCAidWdyYXZlIiwgInVjaXJjdW1mbGV4IiwgInVkaWVyZXNpcyIsICJkYWdnZXIiLCAiZGVncmVlIiwgImNlbnQiLCAic3RlcmxpbmciLCAic2VjdGlvbiIsICJidWxsZXQiLCAicGFyYWdyYXBoIiwgImdlcm1hbmRibHMiLCAicmVnaXN0ZXJlZCIsICJjb3B5cmlnaHQiLCAidHJhZGVtYXJrIiwgImFjdXRlIiwgImRpZXJlc2lzIiwgIm5vdGVxdWFsIiwgIkFFIiwgIk9zbGFzaCIsICJpbmZpbml0eSIsICJwbHVzbWludXMiLCAibGVzc2VxdWFsIiwgImdyZWF0ZXJlcXVhbCIsICJ5ZW4iLCAibXUiLCAicGFydGlhbGRpZmYiLCAic3VtbWF0aW9uIiwgInByb2R1Y3QiLCAicGkiLCAiaW50ZWdyYWwiLCAib3JkZmVtaW5pbmUiLCAib3JkbWFzY3VsaW5lIiwgIk9tZWdhIiwgImFlIiwgIm9zbGFzaCIsICJxdWVzdGlvbmRvd24iLCAiZXhjbGFtZG93biIsICJsb2dpY2Fsbm90IiwgInJhZGljYWwiLCAiZmxvcmluIiwgImFwcHJveGVxdWFsIiwgIkRlbHRhIiwgImd1aWxsZW1vdGxlZnQiLCAiZ3VpbGxlbW90cmlnaHQiLCAiZWxsaXBzaXMiLCAic3BhY2UiLCAiQWdyYXZlIiwgIkF0aWxkZSIsICJPdGlsZGUiLCAiT0UiLCAib2UiLCAiZW5kYXNoIiwgImVtZGFzaCIsICJxdW90ZWRibGxlZnQiLCAicXVvdGVkYmxyaWdodCIsICJxdW90ZWxlZnQiLCAicXVvdGVyaWdodCIsICJkaXZpZGUiLCAibG96ZW5nZSIsICJ5ZGllcmVzaXMiLCAiWWRpZXJlc2lzIiwgImZyYWN0aW9uIiwgImN1cnJlbmN5IiwgImd1aWxzaW5nbGxlZnQiLCAiZ3VpbHNpbmdscmlnaHQiLCAiZmkiLCAiZmwiLCAiZGFnZ2VyZGJsIiwgInBlcmlvZGNlbnRlcmVkIiwgInF1b3Rlc2luZ2xiYXNlIiwgInF1b3RlZGJsYmFzZSIsICJwZXJ0aG91c2FuZCIsICJBY2lyY3VtZmxleCIsICJFY2lyY3VtZmxleCIsICJBYWN1dGUiLCAiRWRpZXJlc2lzIiwgIkVncmF2ZSIsICJJYWN1dGUiLCAiSWNpcmN1bWZsZXgiLCAiSWRpZXJlc2lzIiwgIklncmF2ZSIsICJPYWN1dGUiLCAiT2NpcmN1bWZsZXgiLCAiYXBwbGUiLCAiT2dyYXZlIiwgIlVhY3V0ZSIsICJVY2lyY3VtZmxleCIsICJVZ3JhdmUiLCAiZG90bGVzc2kiLCAiY2lyY3VtZmxleCIsICJ0aWxkZSIsICJtYWNyb24iLCAiYnJldmUiLCAiZG90YWNjZW50IiwgInJpbmciLCAiY2VkaWxsYSIsICJodW5nYXJ1bWxhdXQiLCAib2dvbmVrIiwgImNhcm9uIl07CmNvbnN0IFN0YW5kYXJkRW5jb2RpbmcgPSBbIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAic3BhY2UiLCAiZXhjbGFtIiwgInF1b3RlZGJsIiwgIm51bWJlcnNpZ24iLCAiZG9sbGFyIiwgInBlcmNlbnQiLCAiYW1wZXJzYW5kIiwgInF1b3RlcmlnaHQiLCAicGFyZW5sZWZ0IiwgInBhcmVucmlnaHQiLCAiYXN0ZXJpc2siLCAicGx1cyIsICJjb21tYSIsICJoeXBoZW4iLCAicGVyaW9kIiwgInNsYXNoIiwgInplcm8iLCAib25lIiwgInR3byIsICJ0aHJlZSIsICJmb3VyIiwgImZpdmUiLCAic2l4IiwgInNldmVuIiwgImVpZ2h0IiwgIm5pbmUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgImxlc3MiLCAiZXF1YWwiLCAiZ3JlYXRlciIsICJxdWVzdGlvbiIsICJhdCIsICJBIiwgIkIiLCAiQyIsICJEIiwgIkUiLCAiRiIsICJHIiwgIkgiLCAiSSIsICJKIiwgIksiLCAiTCIsICJNIiwgIk4iLCAiTyIsICJQIiwgIlEiLCAiUiIsICJTIiwgIlQiLCAiVSIsICJWIiwgIlciLCAiWCIsICJZIiwgIloiLCAiYnJhY2tldGxlZnQiLCAiYmFja3NsYXNoIiwgImJyYWNrZXRyaWdodCIsICJhc2NpaWNpcmN1bSIsICJ1bmRlcnNjb3JlIiwgInF1b3RlbGVmdCIsICJhIiwgImIiLCAiYyIsICJkIiwgImUiLCAiZiIsICJnIiwgImgiLCAiaSIsICJqIiwgImsiLCAibCIsICJtIiwgIm4iLCAibyIsICJwIiwgInEiLCAiciIsICJzIiwgInQiLCAidSIsICJ2IiwgInciLCAieCIsICJ5IiwgInoiLCAiYnJhY2VsZWZ0IiwgImJhciIsICJicmFjZXJpZ2h0IiwgImFzY2lpdGlsZGUiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgImV4Y2xhbWRvd24iLCAiY2VudCIsICJzdGVybGluZyIsICJmcmFjdGlvbiIsICJ5ZW4iLCAiZmxvcmluIiwgInNlY3Rpb24iLCAiY3VycmVuY3kiLCAicXVvdGVzaW5nbGUiLCAicXVvdGVkYmxsZWZ0IiwgImd1aWxsZW1vdGxlZnQiLCAiZ3VpbHNpbmdsbGVmdCIsICJndWlsc2luZ2xyaWdodCIsICJmaSIsICJmbCIsICIiLCAiZW5kYXNoIiwgImRhZ2dlciIsICJkYWdnZXJkYmwiLCAicGVyaW9kY2VudGVyZWQiLCAiIiwgInBhcmFncmFwaCIsICJidWxsZXQiLCAicXVvdGVzaW5nbGJhc2UiLCAicXVvdGVkYmxiYXNlIiwgInF1b3RlZGJscmlnaHQiLCAiZ3VpbGxlbW90cmlnaHQiLCAiZWxsaXBzaXMiLCAicGVydGhvdXNhbmQiLCAiIiwgInF1ZXN0aW9uZG93biIsICIiLCAiZ3JhdmUiLCAiYWN1dGUiLCAiY2lyY3VtZmxleCIsICJ0aWxkZSIsICJtYWNyb24iLCAiYnJldmUiLCAiZG90YWNjZW50IiwgImRpZXJlc2lzIiwgIiIsICJyaW5nIiwgImNlZGlsbGEiLCAiIiwgImh1bmdhcnVtbGF1dCIsICJvZ29uZWsiLCAiY2Fyb24iLCAiZW1kYXNoIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJBRSIsICIiLCAib3JkZmVtaW5pbmUiLCAiIiwgIiIsICIiLCAiIiwgIkxzbGFzaCIsICJPc2xhc2giLCAiT0UiLCAib3JkbWFzY3VsaW5lIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiYWUiLCAiIiwgIiIsICIiLCAiZG90bGVzc2kiLCAiIiwgIiIsICJsc2xhc2giLCAib3NsYXNoIiwgIm9lIiwgImdlcm1hbmRibHMiLCAiIiwgIiIsICIiLCAiIl07CmNvbnN0IFdpbkFuc2lFbmNvZGluZyA9IFsiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJzcGFjZSIsICJleGNsYW0iLCAicXVvdGVkYmwiLCAibnVtYmVyc2lnbiIsICJkb2xsYXIiLCAicGVyY2VudCIsICJhbXBlcnNhbmQiLCAicXVvdGVzaW5nbGUiLCAicGFyZW5sZWZ0IiwgInBhcmVucmlnaHQiLCAiYXN0ZXJpc2siLCAicGx1cyIsICJjb21tYSIsICJoeXBoZW4iLCAicGVyaW9kIiwgInNsYXNoIiwgInplcm8iLCAib25lIiwgInR3byIsICJ0aHJlZSIsICJmb3VyIiwgImZpdmUiLCAic2l4IiwgInNldmVuIiwgImVpZ2h0IiwgIm5pbmUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgImxlc3MiLCAiZXF1YWwiLCAiZ3JlYXRlciIsICJxdWVzdGlvbiIsICJhdCIsICJBIiwgIkIiLCAiQyIsICJEIiwgIkUiLCAiRiIsICJHIiwgIkgiLCAiSSIsICJKIiwgIksiLCAiTCIsICJNIiwgIk4iLCAiTyIsICJQIiwgIlEiLCAiUiIsICJTIiwgIlQiLCAiVSIsICJWIiwgIlciLCAiWCIsICJZIiwgIloiLCAiYnJhY2tldGxlZnQiLCAiYmFja3NsYXNoIiwgImJyYWNrZXRyaWdodCIsICJhc2NpaWNpcmN1bSIsICJ1bmRlcnNjb3JlIiwgImdyYXZlIiwgImEiLCAiYiIsICJjIiwgImQiLCAiZSIsICJmIiwgImciLCAiaCIsICJpIiwgImoiLCAiayIsICJsIiwgIm0iLCAibiIsICJvIiwgInAiLCAicSIsICJyIiwgInMiLCAidCIsICJ1IiwgInYiLCAidyIsICJ4IiwgInkiLCAieiIsICJicmFjZWxlZnQiLCAiYmFyIiwgImJyYWNlcmlnaHQiLCAiYXNjaWl0aWxkZSIsICJidWxsZXQiLCAiRXVybyIsICJidWxsZXQiLCAicXVvdGVzaW5nbGJhc2UiLCAiZmxvcmluIiwgInF1b3RlZGJsYmFzZSIsICJlbGxpcHNpcyIsICJkYWdnZXIiLCAiZGFnZ2VyZGJsIiwgImNpcmN1bWZsZXgiLCAicGVydGhvdXNhbmQiLCAiU2Nhcm9uIiwgImd1aWxzaW5nbGxlZnQiLCAiT0UiLCAiYnVsbGV0IiwgIlpjYXJvbiIsICJidWxsZXQiLCAiYnVsbGV0IiwgInF1b3RlbGVmdCIsICJxdW90ZXJpZ2h0IiwgInF1b3RlZGJsbGVmdCIsICJxdW90ZWRibHJpZ2h0IiwgImJ1bGxldCIsICJlbmRhc2giLCAiZW1kYXNoIiwgInRpbGRlIiwgInRyYWRlbWFyayIsICJzY2Fyb24iLCAiZ3VpbHNpbmdscmlnaHQiLCAib2UiLCAiYnVsbGV0IiwgInpjYXJvbiIsICJZZGllcmVzaXMiLCAic3BhY2UiLCAiZXhjbGFtZG93biIsICJjZW50IiwgInN0ZXJsaW5nIiwgImN1cnJlbmN5IiwgInllbiIsICJicm9rZW5iYXIiLCAic2VjdGlvbiIsICJkaWVyZXNpcyIsICJjb3B5cmlnaHQiLCAib3JkZmVtaW5pbmUiLCAiZ3VpbGxlbW90bGVmdCIsICJsb2dpY2Fsbm90IiwgImh5cGhlbiIsICJyZWdpc3RlcmVkIiwgIm1hY3JvbiIsICJkZWdyZWUiLCAicGx1c21pbnVzIiwgInR3b3N1cGVyaW9yIiwgInRocmVlc3VwZXJpb3IiLCAiYWN1dGUiLCAibXUiLCAicGFyYWdyYXBoIiwgInBlcmlvZGNlbnRlcmVkIiwgImNlZGlsbGEiLCAib25lc3VwZXJpb3IiLCAib3JkbWFzY3VsaW5lIiwgImd1aWxsZW1vdHJpZ2h0IiwgIm9uZXF1YXJ0ZXIiLCAib25laGFsZiIsICJ0aHJlZXF1YXJ0ZXJzIiwgInF1ZXN0aW9uZG93biIsICJBZ3JhdmUiLCAiQWFjdXRlIiwgIkFjaXJjdW1mbGV4IiwgIkF0aWxkZSIsICJBZGllcmVzaXMiLCAiQXJpbmciLCAiQUUiLCAiQ2NlZGlsbGEiLCAiRWdyYXZlIiwgIkVhY3V0ZSIsICJFY2lyY3VtZmxleCIsICJFZGllcmVzaXMiLCAiSWdyYXZlIiwgIklhY3V0ZSIsICJJY2lyY3VtZmxleCIsICJJZGllcmVzaXMiLCAiRXRoIiwgIk50aWxkZSIsICJPZ3JhdmUiLCAiT2FjdXRlIiwgIk9jaXJjdW1mbGV4IiwgIk90aWxkZSIsICJPZGllcmVzaXMiLCAibXVsdGlwbHkiLCAiT3NsYXNoIiwgIlVncmF2ZSIsICJVYWN1dGUiLCAiVWNpcmN1bWZsZXgiLCAiVWRpZXJlc2lzIiwgIllhY3V0ZSIsICJUaG9ybiIsICJnZXJtYW5kYmxzIiwgImFncmF2ZSIsICJhYWN1dGUiLCAiYWNpcmN1bWZsZXgiLCAiYXRpbGRlIiwgImFkaWVyZXNpcyIsICJhcmluZyIsICJhZSIsICJjY2VkaWxsYSIsICJlZ3JhdmUiLCAiZWFjdXRlIiwgImVjaXJjdW1mbGV4IiwgImVkaWVyZXNpcyIsICJpZ3JhdmUiLCAiaWFjdXRlIiwgImljaXJjdW1mbGV4IiwgImlkaWVyZXNpcyIsICJldGgiLCAibnRpbGRlIiwgIm9ncmF2ZSIsICJvYWN1dGUiLCAib2NpcmN1bWZsZXgiLCAib3RpbGRlIiwgIm9kaWVyZXNpcyIsICJkaXZpZGUiLCAib3NsYXNoIiwgInVncmF2ZSIsICJ1YWN1dGUiLCAidWNpcmN1bWZsZXgiLCAidWRpZXJlc2lzIiwgInlhY3V0ZSIsICJ0aG9ybiIsICJ5ZGllcmVzaXMiXTsKY29uc3QgU3ltYm9sU2V0RW5jb2RpbmcgPSBbIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAic3BhY2UiLCAiZXhjbGFtIiwgInVuaXZlcnNhbCIsICJudW1iZXJzaWduIiwgImV4aXN0ZW50aWFsIiwgInBlcmNlbnQiLCAiYW1wZXJzYW5kIiwgInN1Y2h0aGF0IiwgInBhcmVubGVmdCIsICJwYXJlbnJpZ2h0IiwgImFzdGVyaXNrbWF0aCIsICJwbHVzIiwgImNvbW1hIiwgIm1pbnVzIiwgInBlcmlvZCIsICJzbGFzaCIsICJ6ZXJvIiwgIm9uZSIsICJ0d28iLCAidGhyZWUiLCAiZm91ciIsICJmaXZlIiwgInNpeCIsICJzZXZlbiIsICJlaWdodCIsICJuaW5lIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJsZXNzIiwgImVxdWFsIiwgImdyZWF0ZXIiLCAicXVlc3Rpb24iLCAiY29uZ3J1ZW50IiwgIkFscGhhIiwgIkJldGEiLCAiQ2hpIiwgIkRlbHRhIiwgIkVwc2lsb24iLCAiUGhpIiwgIkdhbW1hIiwgIkV0YSIsICJJb3RhIiwgInRoZXRhMSIsICJLYXBwYSIsICJMYW1iZGEiLCAiTXUiLCAiTnUiLCAiT21pY3JvbiIsICJQaSIsICJUaGV0YSIsICJSaG8iLCAiU2lnbWEiLCAiVGF1IiwgIlVwc2lsb24iLCAic2lnbWExIiwgIk9tZWdhIiwgIlhpIiwgIlBzaSIsICJaZXRhIiwgImJyYWNrZXRsZWZ0IiwgInRoZXJlZm9yZSIsICJicmFja2V0cmlnaHQiLCAicGVycGVuZGljdWxhciIsICJ1bmRlcnNjb3JlIiwgInJhZGljYWxleCIsICJhbHBoYSIsICJiZXRhIiwgImNoaSIsICJkZWx0YSIsICJlcHNpbG9uIiwgInBoaSIsICJnYW1tYSIsICJldGEiLCAiaW90YSIsICJwaGkxIiwgImthcHBhIiwgImxhbWJkYSIsICJtdSIsICJudSIsICJvbWljcm9uIiwgInBpIiwgInRoZXRhIiwgInJobyIsICJzaWdtYSIsICJ0YXUiLCAidXBzaWxvbiIsICJvbWVnYTEiLCAib21lZ2EiLCAieGkiLCAicHNpIiwgInpldGEiLCAiYnJhY2VsZWZ0IiwgImJhciIsICJicmFjZXJpZ2h0IiwgInNpbWlsYXIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiRXVybyIsICJVcHNpbG9uMSIsICJtaW51dGUiLCAibGVzc2VxdWFsIiwgImZyYWN0aW9uIiwgImluZmluaXR5IiwgImZsb3JpbiIsICJjbHViIiwgImRpYW1vbmQiLCAiaGVhcnQiLCAic3BhZGUiLCAiYXJyb3dib3RoIiwgImFycm93bGVmdCIsICJhcnJvd3VwIiwgImFycm93cmlnaHQiLCAiYXJyb3dkb3duIiwgImRlZ3JlZSIsICJwbHVzbWludXMiLCAic2Vjb25kIiwgImdyZWF0ZXJlcXVhbCIsICJtdWx0aXBseSIsICJwcm9wb3J0aW9uYWwiLCAicGFydGlhbGRpZmYiLCAiYnVsbGV0IiwgImRpdmlkZSIsICJub3RlcXVhbCIsICJlcXVpdmFsZW5jZSIsICJhcHByb3hlcXVhbCIsICJlbGxpcHNpcyIsICJhcnJvd3ZlcnRleCIsICJhcnJvd2hvcml6ZXgiLCAiY2FycmlhZ2VyZXR1cm4iLCAiYWxlcGgiLCAiSWZyYWt0dXIiLCAiUmZyYWt0dXIiLCAid2VpZXJzdHJhc3MiLCAiY2lyY2xlbXVsdGlwbHkiLCAiY2lyY2xlcGx1cyIsICJlbXB0eXNldCIsICJpbnRlcnNlY3Rpb24iLCAidW5pb24iLCAicHJvcGVyc3VwZXJzZXQiLCAicmVmbGV4c3VwZXJzZXQiLCAibm90c3Vic2V0IiwgInByb3BlcnN1YnNldCIsICJyZWZsZXhzdWJzZXQiLCAiZWxlbWVudCIsICJub3RlbGVtZW50IiwgImFuZ2xlIiwgImdyYWRpZW50IiwgInJlZ2lzdGVyc2VyaWYiLCAiY29weXJpZ2h0c2VyaWYiLCAidHJhZGVtYXJrc2VyaWYiLCAicHJvZHVjdCIsICJyYWRpY2FsIiwgImRvdG1hdGgiLCAibG9naWNhbG5vdCIsICJsb2dpY2FsYW5kIiwgImxvZ2ljYWxvciIsICJhcnJvd2RibGJvdGgiLCAiYXJyb3dkYmxsZWZ0IiwgImFycm93ZGJsdXAiLCAiYXJyb3dkYmxyaWdodCIsICJhcnJvd2RibGRvd24iLCAibG96ZW5nZSIsICJhbmdsZWxlZnQiLCAicmVnaXN0ZXJzYW5zIiwgImNvcHlyaWdodHNhbnMiLCAidHJhZGVtYXJrc2FucyIsICJzdW1tYXRpb24iLCAicGFyZW5sZWZ0dHAiLCAicGFyZW5sZWZ0ZXgiLCAicGFyZW5sZWZ0YnQiLCAiYnJhY2tldGxlZnR0cCIsICJicmFja2V0bGVmdGV4IiwgImJyYWNrZXRsZWZ0YnQiLCAiYnJhY2VsZWZ0dHAiLCAiYnJhY2VsZWZ0bWlkIiwgImJyYWNlbGVmdGJ0IiwgImJyYWNlZXgiLCAiIiwgImFuZ2xlcmlnaHQiLCAiaW50ZWdyYWwiLCAiaW50ZWdyYWx0cCIsICJpbnRlZ3JhbGV4IiwgImludGVncmFsYnQiLCAicGFyZW5yaWdodHRwIiwgInBhcmVucmlnaHRleCIsICJwYXJlbnJpZ2h0YnQiLCAiYnJhY2tldHJpZ2h0dHAiLCAiYnJhY2tldHJpZ2h0ZXgiLCAiYnJhY2tldHJpZ2h0YnQiLCAiYnJhY2VyaWdodHRwIiwgImJyYWNlcmlnaHRtaWQiLCAiYnJhY2VyaWdodGJ0IiwgIiJdOwpjb25zdCBaYXBmRGluZ2JhdHNFbmNvZGluZyA9IFsiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJzcGFjZSIsICJhMSIsICJhMiIsICJhMjAyIiwgImEzIiwgImE0IiwgImE1IiwgImExMTkiLCAiYTExOCIsICJhMTE3IiwgImExMSIsICJhMTIiLCAiYTEzIiwgImExNCIsICJhMTUiLCAiYTE2IiwgImExMDUiLCAiYTE3IiwgImExOCIsICJhMTkiLCAiYTIwIiwgImEyMSIsICJhMjIiLCAiYTIzIiwgImEyNCIsICJhMjUiLCAiYTI2IiwgImEyNyIsICJhMjgiLCAiYTYiLCAiYTciLCAiYTgiLCAiYTkiLCAiYTEwIiwgImEyOSIsICJhMzAiLCAiYTMxIiwgImEzMiIsICJhMzMiLCAiYTM0IiwgImEzNSIsICJhMzYiLCAiYTM3IiwgImEzOCIsICJhMzkiLCAiYTQwIiwgImE0MSIsICJhNDIiLCAiYTQzIiwgImE0NCIsICJhNDUiLCAiYTQ2IiwgImE0NyIsICJhNDgiLCAiYTQ5IiwgImE1MCIsICJhNTEiLCAiYTUyIiwgImE1MyIsICJhNTQiLCAiYTU1IiwgImE1NiIsICJhNTciLCAiYTU4IiwgImE1OSIsICJhNjAiLCAiYTYxIiwgImE2MiIsICJhNjMiLCAiYTY0IiwgImE2NSIsICJhNjYiLCAiYTY3IiwgImE2OCIsICJhNjkiLCAiYTcwIiwgImE3MSIsICJhNzIiLCAiYTczIiwgImE3NCIsICJhMjAzIiwgImE3NSIsICJhMjA0IiwgImE3NiIsICJhNzciLCAiYTc4IiwgImE3OSIsICJhODEiLCAiYTgyIiwgImE4MyIsICJhODQiLCAiYTk3IiwgImE5OCIsICJhOTkiLCAiYTEwMCIsICIiLCAiYTg5IiwgImE5MCIsICJhOTMiLCAiYTk0IiwgImE5MSIsICJhOTIiLCAiYTIwNSIsICJhODUiLCAiYTIwNiIsICJhODYiLCAiYTg3IiwgImE4OCIsICJhOTUiLCAiYTk2IiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJhMTAxIiwgImExMDIiLCAiYTEwMyIsICJhMTA0IiwgImExMDYiLCAiYTEwNyIsICJhMTA4IiwgImExMTIiLCAiYTExMSIsICJhMTEwIiwgImExMDkiLCAiYTEyMCIsICJhMTIxIiwgImExMjIiLCAiYTEyMyIsICJhMTI0IiwgImExMjUiLCAiYTEyNiIsICJhMTI3IiwgImExMjgiLCAiYTEyOSIsICJhMTMwIiwgImExMzEiLCAiYTEzMiIsICJhMTMzIiwgImExMzQiLCAiYTEzNSIsICJhMTM2IiwgImExMzciLCAiYTEzOCIsICJhMTM5IiwgImExNDAiLCAiYTE0MSIsICJhMTQyIiwgImExNDMiLCAiYTE0NCIsICJhMTQ1IiwgImExNDYiLCAiYTE0NyIsICJhMTQ4IiwgImExNDkiLCAiYTE1MCIsICJhMTUxIiwgImExNTIiLCAiYTE1MyIsICJhMTU0IiwgImExNTUiLCAiYTE1NiIsICJhMTU3IiwgImExNTgiLCAiYTE1OSIsICJhMTYwIiwgImExNjEiLCAiYTE2MyIsICJhMTY0IiwgImExOTYiLCAiYTE2NSIsICJhMTkyIiwgImExNjYiLCAiYTE2NyIsICJhMTY4IiwgImExNjkiLCAiYTE3MCIsICJhMTcxIiwgImExNzIiLCAiYTE3MyIsICJhMTYyIiwgImExNzQiLCAiYTE3NSIsICJhMTc2IiwgImExNzciLCAiYTE3OCIsICJhMTc5IiwgImExOTMiLCAiYTE4MCIsICJhMTk5IiwgImExODEiLCAiYTIwMCIsICJhMTgyIiwgIiIsICJhMjAxIiwgImExODMiLCAiYTE4NCIsICJhMTk3IiwgImExODUiLCAiYTE5NCIsICJhMTk4IiwgImExODYiLCAiYTE5NSIsICJhMTg3IiwgImExODgiLCAiYTE4OSIsICJhMTkwIiwgImExOTEiLCAiIl07CmZ1bmN0aW9uIGdldEVuY29kaW5nKGVuY29kaW5nTmFtZSkgewogIHN3aXRjaCAoZW5jb2RpbmdOYW1lKSB7CiAgICBjYXNlICJXaW5BbnNpRW5jb2RpbmciOgogICAgICByZXR1cm4gV2luQW5zaUVuY29kaW5nOwogICAgY2FzZSAiU3RhbmRhcmRFbmNvZGluZyI6CiAgICAgIHJldHVybiBTdGFuZGFyZEVuY29kaW5nOwogICAgY2FzZSAiTWFjUm9tYW5FbmNvZGluZyI6CiAgICAgIHJldHVybiBNYWNSb21hbkVuY29kaW5nOwogICAgY2FzZSAiU3ltYm9sU2V0RW5jb2RpbmciOgogICAgICByZXR1cm4gU3ltYm9sU2V0RW5jb2Rpbmc7CiAgICBjYXNlICJaYXBmRGluZ2JhdHNFbmNvZGluZyI6CiAgICAgIHJldHVybiBaYXBmRGluZ2JhdHNFbmNvZGluZzsKICAgIGNhc2UgIkV4cGVydEVuY29kaW5nIjoKICAgICAgcmV0dXJuIEV4cGVydEVuY29kaW5nOwogICAgY2FzZSAiTWFjRXhwZXJ0RW5jb2RpbmciOgogICAgICByZXR1cm4gTWFjRXhwZXJ0RW5jb2Rpbmc7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gbnVsbDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2dseXBobGlzdC5qcwoKY29uc3QgZ2V0R2x5cGhzVW5pY29kZSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHQuQSA9IDB4MDA0MTsKICB0LkFFID0gMHgwMGM2OwogIHQuQUVhY3V0ZSA9IDB4MDFmYzsKICB0LkFFbWFjcm9uID0gMHgwMWUyOwogIHQuQUVzbWFsbCA9IDB4ZjdlNjsKICB0LkFhY3V0ZSA9IDB4MDBjMTsKICB0LkFhY3V0ZXNtYWxsID0gMHhmN2UxOwogIHQuQWJyZXZlID0gMHgwMTAyOwogIHQuQWJyZXZlYWN1dGUgPSAweDFlYWU7CiAgdC5BYnJldmVjeXJpbGxpYyA9IDB4MDRkMDsKICB0LkFicmV2ZWRvdGJlbG93ID0gMHgxZWI2OwogIHQuQWJyZXZlZ3JhdmUgPSAweDFlYjA7CiAgdC5BYnJldmVob29rYWJvdmUgPSAweDFlYjI7CiAgdC5BYnJldmV0aWxkZSA9IDB4MWViNDsKICB0LkFjYXJvbiA9IDB4MDFjZDsKICB0LkFjaXJjbGUgPSAweDI0YjY7CiAgdC5BY2lyY3VtZmxleCA9IDB4MDBjMjsKICB0LkFjaXJjdW1mbGV4YWN1dGUgPSAweDFlYTQ7CiAgdC5BY2lyY3VtZmxleGRvdGJlbG93ID0gMHgxZWFjOwogIHQuQWNpcmN1bWZsZXhncmF2ZSA9IDB4MWVhNjsKICB0LkFjaXJjdW1mbGV4aG9va2Fib3ZlID0gMHgxZWE4OwogIHQuQWNpcmN1bWZsZXhzbWFsbCA9IDB4ZjdlMjsKICB0LkFjaXJjdW1mbGV4dGlsZGUgPSAweDFlYWE7CiAgdC5BY3V0ZSA9IDB4ZjZjOTsKICB0LkFjdXRlc21hbGwgPSAweGY3YjQ7CiAgdC5BY3lyaWxsaWMgPSAweDA0MTA7CiAgdC5BZGJsZ3JhdmUgPSAweDAyMDA7CiAgdC5BZGllcmVzaXMgPSAweDAwYzQ7CiAgdC5BZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRkMjsKICB0LkFkaWVyZXNpc21hY3JvbiA9IDB4MDFkZTsKICB0LkFkaWVyZXNpc3NtYWxsID0gMHhmN2U0OwogIHQuQWRvdGJlbG93ID0gMHgxZWEwOwogIHQuQWRvdG1hY3JvbiA9IDB4MDFlMDsKICB0LkFncmF2ZSA9IDB4MDBjMDsKICB0LkFncmF2ZXNtYWxsID0gMHhmN2UwOwogIHQuQWhvb2thYm92ZSA9IDB4MWVhMjsKICB0LkFpZWN5cmlsbGljID0gMHgwNGQ0OwogIHQuQWludmVydGVkYnJldmUgPSAweDAyMDI7CiAgdC5BbHBoYSA9IDB4MDM5MTsKICB0LkFscGhhdG9ub3MgPSAweDAzODY7CiAgdC5BbWFjcm9uID0gMHgwMTAwOwogIHQuQW1vbm9zcGFjZSA9IDB4ZmYyMTsKICB0LkFvZ29uZWsgPSAweDAxMDQ7CiAgdC5BcmluZyA9IDB4MDBjNTsKICB0LkFyaW5nYWN1dGUgPSAweDAxZmE7CiAgdC5BcmluZ2JlbG93ID0gMHgxZTAwOwogIHQuQXJpbmdzbWFsbCA9IDB4ZjdlNTsKICB0LkFzbWFsbCA9IDB4Zjc2MTsKICB0LkF0aWxkZSA9IDB4MDBjMzsKICB0LkF0aWxkZXNtYWxsID0gMHhmN2UzOwogIHQuQXliYXJtZW5pYW4gPSAweDA1MzE7CiAgdC5CID0gMHgwMDQyOwogIHQuQmNpcmNsZSA9IDB4MjRiNzsKICB0LkJkb3RhY2NlbnQgPSAweDFlMDI7CiAgdC5CZG90YmVsb3cgPSAweDFlMDQ7CiAgdC5CZWN5cmlsbGljID0gMHgwNDExOwogIHQuQmVuYXJtZW5pYW4gPSAweDA1MzI7CiAgdC5CZXRhID0gMHgwMzkyOwogIHQuQmhvb2sgPSAweDAxODE7CiAgdC5CbGluZWJlbG93ID0gMHgxZTA2OwogIHQuQm1vbm9zcGFjZSA9IDB4ZmYyMjsKICB0LkJyZXZlc21hbGwgPSAweGY2ZjQ7CiAgdC5Cc21hbGwgPSAweGY3NjI7CiAgdC5CdG9wYmFyID0gMHgwMTgyOwogIHQuQyA9IDB4MDA0MzsKICB0LkNhYXJtZW5pYW4gPSAweDA1M2U7CiAgdC5DYWN1dGUgPSAweDAxMDY7CiAgdC5DYXJvbiA9IDB4ZjZjYTsKICB0LkNhcm9uc21hbGwgPSAweGY2ZjU7CiAgdC5DY2Fyb24gPSAweDAxMGM7CiAgdC5DY2VkaWxsYSA9IDB4MDBjNzsKICB0LkNjZWRpbGxhYWN1dGUgPSAweDFlMDg7CiAgdC5DY2VkaWxsYXNtYWxsID0gMHhmN2U3OwogIHQuQ2NpcmNsZSA9IDB4MjRiODsKICB0LkNjaXJjdW1mbGV4ID0gMHgwMTA4OwogIHQuQ2RvdCA9IDB4MDEwYTsKICB0LkNkb3RhY2NlbnQgPSAweDAxMGE7CiAgdC5DZWRpbGxhc21hbGwgPSAweGY3Yjg7CiAgdC5DaGFhcm1lbmlhbiA9IDB4MDU0OTsKICB0LkNoZWFia2hhc2lhbmN5cmlsbGljID0gMHgwNGJjOwogIHQuQ2hlY3lyaWxsaWMgPSAweDA0Mjc7CiAgdC5DaGVkZXNjZW5kZXJhYmtoYXNpYW5jeXJpbGxpYyA9IDB4MDRiZTsKICB0LkNoZWRlc2NlbmRlcmN5cmlsbGljID0gMHgwNGI2OwogIHQuQ2hlZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRmNDsKICB0LkNoZWhhcm1lbmlhbiA9IDB4MDU0MzsKICB0LkNoZWtoYWthc3NpYW5jeXJpbGxpYyA9IDB4MDRjYjsKICB0LkNoZXZlcnRpY2Fsc3Ryb2tlY3lyaWxsaWMgPSAweDA0Yjg7CiAgdC5DaGkgPSAweDAzYTc7CiAgdC5DaG9vayA9IDB4MDE4NzsKICB0LkNpcmN1bWZsZXhzbWFsbCA9IDB4ZjZmNjsKICB0LkNtb25vc3BhY2UgPSAweGZmMjM7CiAgdC5Db2FybWVuaWFuID0gMHgwNTUxOwogIHQuQ3NtYWxsID0gMHhmNzYzOwogIHQuRCA9IDB4MDA0NDsKICB0LkRaID0gMHgwMWYxOwogIHQuRFpjYXJvbiA9IDB4MDFjNDsKICB0LkRhYXJtZW5pYW4gPSAweDA1MzQ7CiAgdC5EYWZyaWNhbiA9IDB4MDE4OTsKICB0LkRjYXJvbiA9IDB4MDEwZTsKICB0LkRjZWRpbGxhID0gMHgxZTEwOwogIHQuRGNpcmNsZSA9IDB4MjRiOTsKICB0LkRjaXJjdW1mbGV4YmVsb3cgPSAweDFlMTI7CiAgdC5EY3JvYXQgPSAweDAxMTA7CiAgdC5EZG90YWNjZW50ID0gMHgxZTBhOwogIHQuRGRvdGJlbG93ID0gMHgxZTBjOwogIHQuRGVjeXJpbGxpYyA9IDB4MDQxNDsKICB0LkRlaWNvcHRpYyA9IDB4MDNlZTsKICB0LkRlbHRhID0gMHgyMjA2OwogIHQuRGVsdGFncmVlayA9IDB4MDM5NDsKICB0LkRob29rID0gMHgwMThhOwogIHQuRGllcmVzaXMgPSAweGY2Y2I7CiAgdC5EaWVyZXNpc0FjdXRlID0gMHhmNmNjOwogIHQuRGllcmVzaXNHcmF2ZSA9IDB4ZjZjZDsKICB0LkRpZXJlc2lzc21hbGwgPSAweGY3YTg7CiAgdC5EaWdhbW1hZ3JlZWsgPSAweDAzZGM7CiAgdC5EamVjeXJpbGxpYyA9IDB4MDQwMjsKICB0LkRsaW5lYmVsb3cgPSAweDFlMGU7CiAgdC5EbW9ub3NwYWNlID0gMHhmZjI0OwogIHQuRG90YWNjZW50c21hbGwgPSAweGY2Zjc7CiAgdC5Ec2xhc2ggPSAweDAxMTA7CiAgdC5Ec21hbGwgPSAweGY3NjQ7CiAgdC5EdG9wYmFyID0gMHgwMThiOwogIHQuRHogPSAweDAxZjI7CiAgdC5EemNhcm9uID0gMHgwMWM1OwogIHQuRHplYWJraGFzaWFuY3lyaWxsaWMgPSAweDA0ZTA7CiAgdC5EemVjeXJpbGxpYyA9IDB4MDQwNTsKICB0LkR6aGVjeXJpbGxpYyA9IDB4MDQwZjsKICB0LkUgPSAweDAwNDU7CiAgdC5FYWN1dGUgPSAweDAwYzk7CiAgdC5FYWN1dGVzbWFsbCA9IDB4ZjdlOTsKICB0LkVicmV2ZSA9IDB4MDExNDsKICB0LkVjYXJvbiA9IDB4MDExYTsKICB0LkVjZWRpbGxhYnJldmUgPSAweDFlMWM7CiAgdC5FY2hhcm1lbmlhbiA9IDB4MDUzNTsKICB0LkVjaXJjbGUgPSAweDI0YmE7CiAgdC5FY2lyY3VtZmxleCA9IDB4MDBjYTsKICB0LkVjaXJjdW1mbGV4YWN1dGUgPSAweDFlYmU7CiAgdC5FY2lyY3VtZmxleGJlbG93ID0gMHgxZTE4OwogIHQuRWNpcmN1bWZsZXhkb3RiZWxvdyA9IDB4MWVjNjsKICB0LkVjaXJjdW1mbGV4Z3JhdmUgPSAweDFlYzA7CiAgdC5FY2lyY3VtZmxleGhvb2thYm92ZSA9IDB4MWVjMjsKICB0LkVjaXJjdW1mbGV4c21hbGwgPSAweGY3ZWE7CiAgdC5FY2lyY3VtZmxleHRpbGRlID0gMHgxZWM0OwogIHQuRWN5cmlsbGljID0gMHgwNDA0OwogIHQuRWRibGdyYXZlID0gMHgwMjA0OwogIHQuRWRpZXJlc2lzID0gMHgwMGNiOwogIHQuRWRpZXJlc2lzc21hbGwgPSAweGY3ZWI7CiAgdC5FZG90ID0gMHgwMTE2OwogIHQuRWRvdGFjY2VudCA9IDB4MDExNjsKICB0LkVkb3RiZWxvdyA9IDB4MWViODsKICB0LkVmY3lyaWxsaWMgPSAweDA0MjQ7CiAgdC5FZ3JhdmUgPSAweDAwYzg7CiAgdC5FZ3JhdmVzbWFsbCA9IDB4ZjdlODsKICB0LkVoYXJtZW5pYW4gPSAweDA1Mzc7CiAgdC5FaG9va2Fib3ZlID0gMHgxZWJhOwogIHQuRWlnaHRyb21hbiA9IDB4MjE2NzsKICB0LkVpbnZlcnRlZGJyZXZlID0gMHgwMjA2OwogIHQuRWlvdGlmaWVkY3lyaWxsaWMgPSAweDA0NjQ7CiAgdC5FbGN5cmlsbGljID0gMHgwNDFiOwogIHQuRWxldmVucm9tYW4gPSAweDIxNmE7CiAgdC5FbWFjcm9uID0gMHgwMTEyOwogIHQuRW1hY3JvbmFjdXRlID0gMHgxZTE2OwogIHQuRW1hY3JvbmdyYXZlID0gMHgxZTE0OwogIHQuRW1jeXJpbGxpYyA9IDB4MDQxYzsKICB0LkVtb25vc3BhY2UgPSAweGZmMjU7CiAgdC5FbmN5cmlsbGljID0gMHgwNDFkOwogIHQuRW5kZXNjZW5kZXJjeXJpbGxpYyA9IDB4MDRhMjsKICB0LkVuZyA9IDB4MDE0YTsKICB0LkVuZ2hlY3lyaWxsaWMgPSAweDA0YTQ7CiAgdC5Fbmhvb2tjeXJpbGxpYyA9IDB4MDRjNzsKICB0LkVvZ29uZWsgPSAweDAxMTg7CiAgdC5Fb3BlbiA9IDB4MDE5MDsKICB0LkVwc2lsb24gPSAweDAzOTU7CiAgdC5FcHNpbG9udG9ub3MgPSAweDAzODg7CiAgdC5FcmN5cmlsbGljID0gMHgwNDIwOwogIHQuRXJldmVyc2VkID0gMHgwMThlOwogIHQuRXJldmVyc2VkY3lyaWxsaWMgPSAweDA0MmQ7CiAgdC5Fc2N5cmlsbGljID0gMHgwNDIxOwogIHQuRXNkZXNjZW5kZXJjeXJpbGxpYyA9IDB4MDRhYTsKICB0LkVzaCA9IDB4MDFhOTsKICB0LkVzbWFsbCA9IDB4Zjc2NTsKICB0LkV0YSA9IDB4MDM5NzsKICB0LkV0YXJtZW5pYW4gPSAweDA1Mzg7CiAgdC5FdGF0b25vcyA9IDB4MDM4OTsKICB0LkV0aCA9IDB4MDBkMDsKICB0LkV0aHNtYWxsID0gMHhmN2YwOwogIHQuRXRpbGRlID0gMHgxZWJjOwogIHQuRXRpbGRlYmVsb3cgPSAweDFlMWE7CiAgdC5FdXJvID0gMHgyMGFjOwogIHQuRXpoID0gMHgwMWI3OwogIHQuRXpoY2Fyb24gPSAweDAxZWU7CiAgdC5FemhyZXZlcnNlZCA9IDB4MDFiODsKICB0LkYgPSAweDAwNDY7CiAgdC5GY2lyY2xlID0gMHgyNGJiOwogIHQuRmRvdGFjY2VudCA9IDB4MWUxZTsKICB0LkZlaGFybWVuaWFuID0gMHgwNTU2OwogIHQuRmVpY29wdGljID0gMHgwM2U0OwogIHQuRmhvb2sgPSAweDAxOTE7CiAgdC5GaXRhY3lyaWxsaWMgPSAweDA0NzI7CiAgdC5GaXZlcm9tYW4gPSAweDIxNjQ7CiAgdC5GbW9ub3NwYWNlID0gMHhmZjI2OwogIHQuRm91cnJvbWFuID0gMHgyMTYzOwogIHQuRnNtYWxsID0gMHhmNzY2OwogIHQuRyA9IDB4MDA0NzsKICB0LkdCc3F1YXJlID0gMHgzMzg3OwogIHQuR2FjdXRlID0gMHgwMWY0OwogIHQuR2FtbWEgPSAweDAzOTM7CiAgdC5HYW1tYWFmcmljYW4gPSAweDAxOTQ7CiAgdC5HYW5naWFjb3B0aWMgPSAweDAzZWE7CiAgdC5HYnJldmUgPSAweDAxMWU7CiAgdC5HY2Fyb24gPSAweDAxZTY7CiAgdC5HY2VkaWxsYSA9IDB4MDEyMjsKICB0LkdjaXJjbGUgPSAweDI0YmM7CiAgdC5HY2lyY3VtZmxleCA9IDB4MDExYzsKICB0Lkdjb21tYWFjY2VudCA9IDB4MDEyMjsKICB0Lkdkb3QgPSAweDAxMjA7CiAgdC5HZG90YWNjZW50ID0gMHgwMTIwOwogIHQuR2VjeXJpbGxpYyA9IDB4MDQxMzsKICB0LkdoYWRhcm1lbmlhbiA9IDB4MDU0MjsKICB0LkdoZW1pZGRsZWhvb2tjeXJpbGxpYyA9IDB4MDQ5NDsKICB0LkdoZXN0cm9rZWN5cmlsbGljID0gMHgwNDkyOwogIHQuR2hldXB0dXJuY3lyaWxsaWMgPSAweDA0OTA7CiAgdC5HaG9vayA9IDB4MDE5MzsKICB0LkdpbWFybWVuaWFuID0gMHgwNTMzOwogIHQuR2plY3lyaWxsaWMgPSAweDA0MDM7CiAgdC5HbWFjcm9uID0gMHgxZTIwOwogIHQuR21vbm9zcGFjZSA9IDB4ZmYyNzsKICB0LkdyYXZlID0gMHhmNmNlOwogIHQuR3JhdmVzbWFsbCA9IDB4Zjc2MDsKICB0LkdzbWFsbCA9IDB4Zjc2NzsKICB0LkdzbWFsbGhvb2sgPSAweDAyOWI7CiAgdC5Hc3Ryb2tlID0gMHgwMWU0OwogIHQuSCA9IDB4MDA0ODsKICB0LkgxODUzMyA9IDB4MjVjZjsKICB0LkgxODU0MyA9IDB4MjVhYTsKICB0LkgxODU1MSA9IDB4MjVhYjsKICB0LkgyMjA3MyA9IDB4MjVhMTsKICB0LkhQc3F1YXJlID0gMHgzM2NiOwogIHQuSGFhYmtoYXNpYW5jeXJpbGxpYyA9IDB4MDRhODsKICB0LkhhZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0YjI7CiAgdC5IYXJkc2lnbmN5cmlsbGljID0gMHgwNDJhOwogIHQuSGJhciA9IDB4MDEyNjsKICB0LkhicmV2ZWJlbG93ID0gMHgxZTJhOwogIHQuSGNlZGlsbGEgPSAweDFlMjg7CiAgdC5IY2lyY2xlID0gMHgyNGJkOwogIHQuSGNpcmN1bWZsZXggPSAweDAxMjQ7CiAgdC5IZGllcmVzaXMgPSAweDFlMjY7CiAgdC5IZG90YWNjZW50ID0gMHgxZTIyOwogIHQuSGRvdGJlbG93ID0gMHgxZTI0OwogIHQuSG1vbm9zcGFjZSA9IDB4ZmYyODsKICB0LkhvYXJtZW5pYW4gPSAweDA1NDA7CiAgdC5Ib3JpY29wdGljID0gMHgwM2U4OwogIHQuSHNtYWxsID0gMHhmNzY4OwogIHQuSHVuZ2FydW1sYXV0ID0gMHhmNmNmOwogIHQuSHVuZ2FydW1sYXV0c21hbGwgPSAweGY2Zjg7CiAgdC5IenNxdWFyZSA9IDB4MzM5MDsKICB0LkkgPSAweDAwNDk7CiAgdC5JQWN5cmlsbGljID0gMHgwNDJmOwogIHQuSUogPSAweDAxMzI7CiAgdC5JVWN5cmlsbGljID0gMHgwNDJlOwogIHQuSWFjdXRlID0gMHgwMGNkOwogIHQuSWFjdXRlc21hbGwgPSAweGY3ZWQ7CiAgdC5JYnJldmUgPSAweDAxMmM7CiAgdC5JY2Fyb24gPSAweDAxY2Y7CiAgdC5JY2lyY2xlID0gMHgyNGJlOwogIHQuSWNpcmN1bWZsZXggPSAweDAwY2U7CiAgdC5JY2lyY3VtZmxleHNtYWxsID0gMHhmN2VlOwogIHQuSWN5cmlsbGljID0gMHgwNDA2OwogIHQuSWRibGdyYXZlID0gMHgwMjA4OwogIHQuSWRpZXJlc2lzID0gMHgwMGNmOwogIHQuSWRpZXJlc2lzYWN1dGUgPSAweDFlMmU7CiAgdC5JZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRlNDsKICB0LklkaWVyZXNpc3NtYWxsID0gMHhmN2VmOwogIHQuSWRvdCA9IDB4MDEzMDsKICB0Lklkb3RhY2NlbnQgPSAweDAxMzA7CiAgdC5JZG90YmVsb3cgPSAweDFlY2E7CiAgdC5JZWJyZXZlY3lyaWxsaWMgPSAweDA0ZDY7CiAgdC5JZWN5cmlsbGljID0gMHgwNDE1OwogIHQuSWZyYWt0dXIgPSAweDIxMTE7CiAgdC5JZ3JhdmUgPSAweDAwY2M7CiAgdC5JZ3JhdmVzbWFsbCA9IDB4ZjdlYzsKICB0Lklob29rYWJvdmUgPSAweDFlYzg7CiAgdC5JaWN5cmlsbGljID0gMHgwNDE4OwogIHQuSWludmVydGVkYnJldmUgPSAweDAyMGE7CiAgdC5JaXNob3J0Y3lyaWxsaWMgPSAweDA0MTk7CiAgdC5JbWFjcm9uID0gMHgwMTJhOwogIHQuSW1hY3JvbmN5cmlsbGljID0gMHgwNGUyOwogIHQuSW1vbm9zcGFjZSA9IDB4ZmYyOTsKICB0LkluaWFybWVuaWFuID0gMHgwNTNiOwogIHQuSW9jeXJpbGxpYyA9IDB4MDQwMTsKICB0LklvZ29uZWsgPSAweDAxMmU7CiAgdC5Jb3RhID0gMHgwMzk5OwogIHQuSW90YWFmcmljYW4gPSAweDAxOTY7CiAgdC5Jb3RhZGllcmVzaXMgPSAweDAzYWE7CiAgdC5Jb3RhdG9ub3MgPSAweDAzOGE7CiAgdC5Jc21hbGwgPSAweGY3Njk7CiAgdC5Jc3Ryb2tlID0gMHgwMTk3OwogIHQuSXRpbGRlID0gMHgwMTI4OwogIHQuSXRpbGRlYmVsb3cgPSAweDFlMmM7CiAgdC5JemhpdHNhY3lyaWxsaWMgPSAweDA0NzQ7CiAgdC5JemhpdHNhZGJsZ3JhdmVjeXJpbGxpYyA9IDB4MDQ3NjsKICB0LkogPSAweDAwNGE7CiAgdC5KYWFybWVuaWFuID0gMHgwNTQxOwogIHQuSmNpcmNsZSA9IDB4MjRiZjsKICB0LkpjaXJjdW1mbGV4ID0gMHgwMTM0OwogIHQuSmVjeXJpbGxpYyA9IDB4MDQwODsKICB0LkpoZWhhcm1lbmlhbiA9IDB4MDU0YjsKICB0Lkptb25vc3BhY2UgPSAweGZmMmE7CiAgdC5Kc21hbGwgPSAweGY3NmE7CiAgdC5LID0gMHgwMDRiOwogIHQuS0JzcXVhcmUgPSAweDMzODU7CiAgdC5LS3NxdWFyZSA9IDB4MzNjZDsKICB0LkthYmFzaGtpcmN5cmlsbGljID0gMHgwNGEwOwogIHQuS2FjdXRlID0gMHgxZTMwOwogIHQuS2FjeXJpbGxpYyA9IDB4MDQxYTsKICB0LkthZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0OWE7CiAgdC5LYWhvb2tjeXJpbGxpYyA9IDB4MDRjMzsKICB0LkthcHBhID0gMHgwMzlhOwogIHQuS2FzdHJva2VjeXJpbGxpYyA9IDB4MDQ5ZTsKICB0LkthdmVydGljYWxzdHJva2VjeXJpbGxpYyA9IDB4MDQ5YzsKICB0LktjYXJvbiA9IDB4MDFlODsKICB0LktjZWRpbGxhID0gMHgwMTM2OwogIHQuS2NpcmNsZSA9IDB4MjRjMDsKICB0Lktjb21tYWFjY2VudCA9IDB4MDEzNjsKICB0Lktkb3RiZWxvdyA9IDB4MWUzMjsKICB0LktlaGFybWVuaWFuID0gMHgwNTU0OwogIHQuS2VuYXJtZW5pYW4gPSAweDA1M2Y7CiAgdC5LaGFjeXJpbGxpYyA9IDB4MDQyNTsKICB0LktoZWljb3B0aWMgPSAweDAzZTY7CiAgdC5LaG9vayA9IDB4MDE5ODsKICB0LktqZWN5cmlsbGljID0gMHgwNDBjOwogIHQuS2xpbmViZWxvdyA9IDB4MWUzNDsKICB0Lkttb25vc3BhY2UgPSAweGZmMmI7CiAgdC5Lb3BwYWN5cmlsbGljID0gMHgwNDgwOwogIHQuS29wcGFncmVlayA9IDB4MDNkZTsKICB0LktzaWN5cmlsbGljID0gMHgwNDZlOwogIHQuS3NtYWxsID0gMHhmNzZiOwogIHQuTCA9IDB4MDA0YzsKICB0LkxKID0gMHgwMWM3OwogIHQuTEwgPSAweGY2YmY7CiAgdC5MYWN1dGUgPSAweDAxMzk7CiAgdC5MYW1iZGEgPSAweDAzOWI7CiAgdC5MY2Fyb24gPSAweDAxM2Q7CiAgdC5MY2VkaWxsYSA9IDB4MDEzYjsKICB0LkxjaXJjbGUgPSAweDI0YzE7CiAgdC5MY2lyY3VtZmxleGJlbG93ID0gMHgxZTNjOwogIHQuTGNvbW1hYWNjZW50ID0gMHgwMTNiOwogIHQuTGRvdCA9IDB4MDEzZjsKICB0Lkxkb3RhY2NlbnQgPSAweDAxM2Y7CiAgdC5MZG90YmVsb3cgPSAweDFlMzY7CiAgdC5MZG90YmVsb3dtYWNyb24gPSAweDFlMzg7CiAgdC5MaXduYXJtZW5pYW4gPSAweDA1M2M7CiAgdC5MaiA9IDB4MDFjODsKICB0LkxqZWN5cmlsbGljID0gMHgwNDA5OwogIHQuTGxpbmViZWxvdyA9IDB4MWUzYTsKICB0Lkxtb25vc3BhY2UgPSAweGZmMmM7CiAgdC5Mc2xhc2ggPSAweDAxNDE7CiAgdC5Mc2xhc2hzbWFsbCA9IDB4ZjZmOTsKICB0LkxzbWFsbCA9IDB4Zjc2YzsKICB0Lk0gPSAweDAwNGQ7CiAgdC5NQnNxdWFyZSA9IDB4MzM4NjsKICB0Lk1hY3JvbiA9IDB4ZjZkMDsKICB0Lk1hY3JvbnNtYWxsID0gMHhmN2FmOwogIHQuTWFjdXRlID0gMHgxZTNlOwogIHQuTWNpcmNsZSA9IDB4MjRjMjsKICB0Lk1kb3RhY2NlbnQgPSAweDFlNDA7CiAgdC5NZG90YmVsb3cgPSAweDFlNDI7CiAgdC5NZW5hcm1lbmlhbiA9IDB4MDU0NDsKICB0Lk1tb25vc3BhY2UgPSAweGZmMmQ7CiAgdC5Nc21hbGwgPSAweGY3NmQ7CiAgdC5NdHVybmVkID0gMHgwMTljOwogIHQuTXUgPSAweDAzOWM7CiAgdC5OID0gMHgwMDRlOwogIHQuTkogPSAweDAxY2E7CiAgdC5OYWN1dGUgPSAweDAxNDM7CiAgdC5OY2Fyb24gPSAweDAxNDc7CiAgdC5OY2VkaWxsYSA9IDB4MDE0NTsKICB0Lk5jaXJjbGUgPSAweDI0YzM7CiAgdC5OY2lyY3VtZmxleGJlbG93ID0gMHgxZTRhOwogIHQuTmNvbW1hYWNjZW50ID0gMHgwMTQ1OwogIHQuTmRvdGFjY2VudCA9IDB4MWU0NDsKICB0Lk5kb3RiZWxvdyA9IDB4MWU0NjsKICB0Lk5ob29rbGVmdCA9IDB4MDE5ZDsKICB0Lk5pbmVyb21hbiA9IDB4MjE2ODsKICB0Lk5qID0gMHgwMWNiOwogIHQuTmplY3lyaWxsaWMgPSAweDA0MGE7CiAgdC5ObGluZWJlbG93ID0gMHgxZTQ4OwogIHQuTm1vbm9zcGFjZSA9IDB4ZmYyZTsKICB0Lk5vd2FybWVuaWFuID0gMHgwNTQ2OwogIHQuTnNtYWxsID0gMHhmNzZlOwogIHQuTnRpbGRlID0gMHgwMGQxOwogIHQuTnRpbGRlc21hbGwgPSAweGY3ZjE7CiAgdC5OdSA9IDB4MDM5ZDsKICB0Lk8gPSAweDAwNGY7CiAgdC5PRSA9IDB4MDE1MjsKICB0Lk9Fc21hbGwgPSAweGY2ZmE7CiAgdC5PYWN1dGUgPSAweDAwZDM7CiAgdC5PYWN1dGVzbWFsbCA9IDB4ZjdmMzsKICB0Lk9iYXJyZWRjeXJpbGxpYyA9IDB4MDRlODsKICB0Lk9iYXJyZWRkaWVyZXNpc2N5cmlsbGljID0gMHgwNGVhOwogIHQuT2JyZXZlID0gMHgwMTRlOwogIHQuT2Nhcm9uID0gMHgwMWQxOwogIHQuT2NlbnRlcmVkdGlsZGUgPSAweDAxOWY7CiAgdC5PY2lyY2xlID0gMHgyNGM0OwogIHQuT2NpcmN1bWZsZXggPSAweDAwZDQ7CiAgdC5PY2lyY3VtZmxleGFjdXRlID0gMHgxZWQwOwogIHQuT2NpcmN1bWZsZXhkb3RiZWxvdyA9IDB4MWVkODsKICB0Lk9jaXJjdW1mbGV4Z3JhdmUgPSAweDFlZDI7CiAgdC5PY2lyY3VtZmxleGhvb2thYm92ZSA9IDB4MWVkNDsKICB0Lk9jaXJjdW1mbGV4c21hbGwgPSAweGY3ZjQ7CiAgdC5PY2lyY3VtZmxleHRpbGRlID0gMHgxZWQ2OwogIHQuT2N5cmlsbGljID0gMHgwNDFlOwogIHQuT2RibGFjdXRlID0gMHgwMTUwOwogIHQuT2RibGdyYXZlID0gMHgwMjBjOwogIHQuT2RpZXJlc2lzID0gMHgwMGQ2OwogIHQuT2RpZXJlc2lzY3lyaWxsaWMgPSAweDA0ZTY7CiAgdC5PZGllcmVzaXNzbWFsbCA9IDB4ZjdmNjsKICB0Lk9kb3RiZWxvdyA9IDB4MWVjYzsKICB0Lk9nb25la3NtYWxsID0gMHhmNmZiOwogIHQuT2dyYXZlID0gMHgwMGQyOwogIHQuT2dyYXZlc21hbGwgPSAweGY3ZjI7CiAgdC5PaGFybWVuaWFuID0gMHgwNTU1OwogIHQuT2htID0gMHgyMTI2OwogIHQuT2hvb2thYm92ZSA9IDB4MWVjZTsKICB0Lk9ob3JuID0gMHgwMWEwOwogIHQuT2hvcm5hY3V0ZSA9IDB4MWVkYTsKICB0Lk9ob3JuZG90YmVsb3cgPSAweDFlZTI7CiAgdC5PaG9ybmdyYXZlID0gMHgxZWRjOwogIHQuT2hvcm5ob29rYWJvdmUgPSAweDFlZGU7CiAgdC5PaG9ybnRpbGRlID0gMHgxZWUwOwogIHQuT2h1bmdhcnVtbGF1dCA9IDB4MDE1MDsKICB0Lk9pID0gMHgwMWEyOwogIHQuT2ludmVydGVkYnJldmUgPSAweDAyMGU7CiAgdC5PbWFjcm9uID0gMHgwMTRjOwogIHQuT21hY3JvbmFjdXRlID0gMHgxZTUyOwogIHQuT21hY3JvbmdyYXZlID0gMHgxZTUwOwogIHQuT21lZ2EgPSAweDIxMjY7CiAgdC5PbWVnYWN5cmlsbGljID0gMHgwNDYwOwogIHQuT21lZ2FncmVlayA9IDB4MDNhOTsKICB0Lk9tZWdhcm91bmRjeXJpbGxpYyA9IDB4MDQ3YTsKICB0Lk9tZWdhdGl0bG9jeXJpbGxpYyA9IDB4MDQ3YzsKICB0Lk9tZWdhdG9ub3MgPSAweDAzOGY7CiAgdC5PbWljcm9uID0gMHgwMzlmOwogIHQuT21pY3JvbnRvbm9zID0gMHgwMzhjOwogIHQuT21vbm9zcGFjZSA9IDB4ZmYyZjsKICB0Lk9uZXJvbWFuID0gMHgyMTYwOwogIHQuT29nb25layA9IDB4MDFlYTsKICB0Lk9vZ29uZWttYWNyb24gPSAweDAxZWM7CiAgdC5Pb3BlbiA9IDB4MDE4NjsKICB0Lk9zbGFzaCA9IDB4MDBkODsKICB0Lk9zbGFzaGFjdXRlID0gMHgwMWZlOwogIHQuT3NsYXNoc21hbGwgPSAweGY3Zjg7CiAgdC5Pc21hbGwgPSAweGY3NmY7CiAgdC5Pc3Ryb2tlYWN1dGUgPSAweDAxZmU7CiAgdC5PdGN5cmlsbGljID0gMHgwNDdlOwogIHQuT3RpbGRlID0gMHgwMGQ1OwogIHQuT3RpbGRlYWN1dGUgPSAweDFlNGM7CiAgdC5PdGlsZGVkaWVyZXNpcyA9IDB4MWU0ZTsKICB0Lk90aWxkZXNtYWxsID0gMHhmN2Y1OwogIHQuUCA9IDB4MDA1MDsKICB0LlBhY3V0ZSA9IDB4MWU1NDsKICB0LlBjaXJjbGUgPSAweDI0YzU7CiAgdC5QZG90YWNjZW50ID0gMHgxZTU2OwogIHQuUGVjeXJpbGxpYyA9IDB4MDQxZjsKICB0LlBlaGFybWVuaWFuID0gMHgwNTRhOwogIHQuUGVtaWRkbGVob29rY3lyaWxsaWMgPSAweDA0YTY7CiAgdC5QaGkgPSAweDAzYTY7CiAgdC5QaG9vayA9IDB4MDFhNDsKICB0LlBpID0gMHgwM2EwOwogIHQuUGl3cmFybWVuaWFuID0gMHgwNTUzOwogIHQuUG1vbm9zcGFjZSA9IDB4ZmYzMDsKICB0LlBzaSA9IDB4MDNhODsKICB0LlBzaWN5cmlsbGljID0gMHgwNDcwOwogIHQuUHNtYWxsID0gMHhmNzcwOwogIHQuUSA9IDB4MDA1MTsKICB0LlFjaXJjbGUgPSAweDI0YzY7CiAgdC5RbW9ub3NwYWNlID0gMHhmZjMxOwogIHQuUXNtYWxsID0gMHhmNzcxOwogIHQuUiA9IDB4MDA1MjsKICB0LlJhYXJtZW5pYW4gPSAweDA1NGM7CiAgdC5SYWN1dGUgPSAweDAxNTQ7CiAgdC5SY2Fyb24gPSAweDAxNTg7CiAgdC5SY2VkaWxsYSA9IDB4MDE1NjsKICB0LlJjaXJjbGUgPSAweDI0Yzc7CiAgdC5SY29tbWFhY2NlbnQgPSAweDAxNTY7CiAgdC5SZGJsZ3JhdmUgPSAweDAyMTA7CiAgdC5SZG90YWNjZW50ID0gMHgxZTU4OwogIHQuUmRvdGJlbG93ID0gMHgxZTVhOwogIHQuUmRvdGJlbG93bWFjcm9uID0gMHgxZTVjOwogIHQuUmVoYXJtZW5pYW4gPSAweDA1NTA7CiAgdC5SZnJha3R1ciA9IDB4MjExYzsKICB0LlJobyA9IDB4MDNhMTsKICB0LlJpbmdzbWFsbCA9IDB4ZjZmYzsKICB0LlJpbnZlcnRlZGJyZXZlID0gMHgwMjEyOwogIHQuUmxpbmViZWxvdyA9IDB4MWU1ZTsKICB0LlJtb25vc3BhY2UgPSAweGZmMzI7CiAgdC5Sc21hbGwgPSAweGY3NzI7CiAgdC5Sc21hbGxpbnZlcnRlZCA9IDB4MDI4MTsKICB0LlJzbWFsbGludmVydGVkc3VwZXJpb3IgPSAweDAyYjY7CiAgdC5TID0gMHgwMDUzOwogIHQuU0YwMTAwMDAgPSAweDI1MGM7CiAgdC5TRjAyMDAwMCA9IDB4MjUxNDsKICB0LlNGMDMwMDAwID0gMHgyNTEwOwogIHQuU0YwNDAwMDAgPSAweDI1MTg7CiAgdC5TRjA1MDAwMCA9IDB4MjUzYzsKICB0LlNGMDYwMDAwID0gMHgyNTJjOwogIHQuU0YwNzAwMDAgPSAweDI1MzQ7CiAgdC5TRjA4MDAwMCA9IDB4MjUxYzsKICB0LlNGMDkwMDAwID0gMHgyNTI0OwogIHQuU0YxMDAwMDAgPSAweDI1MDA7CiAgdC5TRjExMDAwMCA9IDB4MjUwMjsKICB0LlNGMTkwMDAwID0gMHgyNTYxOwogIHQuU0YyMDAwMDAgPSAweDI1NjI7CiAgdC5TRjIxMDAwMCA9IDB4MjU1NjsKICB0LlNGMjIwMDAwID0gMHgyNTU1OwogIHQuU0YyMzAwMDAgPSAweDI1NjM7CiAgdC5TRjI0MDAwMCA9IDB4MjU1MTsKICB0LlNGMjUwMDAwID0gMHgyNTU3OwogIHQuU0YyNjAwMDAgPSAweDI1NWQ7CiAgdC5TRjI3MDAwMCA9IDB4MjU1YzsKICB0LlNGMjgwMDAwID0gMHgyNTViOwogIHQuU0YzNjAwMDAgPSAweDI1NWU7CiAgdC5TRjM3MDAwMCA9IDB4MjU1ZjsKICB0LlNGMzgwMDAwID0gMHgyNTVhOwogIHQuU0YzOTAwMDAgPSAweDI1NTQ7CiAgdC5TRjQwMDAwMCA9IDB4MjU2OTsKICB0LlNGNDEwMDAwID0gMHgyNTY2OwogIHQuU0Y0MjAwMDAgPSAweDI1NjA7CiAgdC5TRjQzMDAwMCA9IDB4MjU1MDsKICB0LlNGNDQwMDAwID0gMHgyNTZjOwogIHQuU0Y0NTAwMDAgPSAweDI1Njc7CiAgdC5TRjQ2MDAwMCA9IDB4MjU2ODsKICB0LlNGNDcwMDAwID0gMHgyNTY0OwogIHQuU0Y0ODAwMDAgPSAweDI1NjU7CiAgdC5TRjQ5MDAwMCA9IDB4MjU1OTsKICB0LlNGNTAwMDAwID0gMHgyNTU4OwogIHQuU0Y1MTAwMDAgPSAweDI1NTI7CiAgdC5TRjUyMDAwMCA9IDB4MjU1MzsKICB0LlNGNTMwMDAwID0gMHgyNTZiOwogIHQuU0Y1NDAwMDAgPSAweDI1NmE7CiAgdC5TYWN1dGUgPSAweDAxNWE7CiAgdC5TYWN1dGVkb3RhY2NlbnQgPSAweDFlNjQ7CiAgdC5TYW1waWdyZWVrID0gMHgwM2UwOwogIHQuU2Nhcm9uID0gMHgwMTYwOwogIHQuU2Nhcm9uZG90YWNjZW50ID0gMHgxZTY2OwogIHQuU2Nhcm9uc21hbGwgPSAweGY2ZmQ7CiAgdC5TY2VkaWxsYSA9IDB4MDE1ZTsKICB0LlNjaHdhID0gMHgwMThmOwogIHQuU2Nod2FjeXJpbGxpYyA9IDB4MDRkODsKICB0LlNjaHdhZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRkYTsKICB0LlNjaXJjbGUgPSAweDI0Yzg7CiAgdC5TY2lyY3VtZmxleCA9IDB4MDE1YzsKICB0LlNjb21tYWFjY2VudCA9IDB4MDIxODsKICB0LlNkb3RhY2NlbnQgPSAweDFlNjA7CiAgdC5TZG90YmVsb3cgPSAweDFlNjI7CiAgdC5TZG90YmVsb3dkb3RhY2NlbnQgPSAweDFlNjg7CiAgdC5TZWhhcm1lbmlhbiA9IDB4MDU0ZDsKICB0LlNldmVucm9tYW4gPSAweDIxNjY7CiAgdC5TaGFhcm1lbmlhbiA9IDB4MDU0NzsKICB0LlNoYWN5cmlsbGljID0gMHgwNDI4OwogIHQuU2hjaGFjeXJpbGxpYyA9IDB4MDQyOTsKICB0LlNoZWljb3B0aWMgPSAweDAzZTI7CiAgdC5TaGhhY3lyaWxsaWMgPSAweDA0YmE7CiAgdC5TaGltYWNvcHRpYyA9IDB4MDNlYzsKICB0LlNpZ21hID0gMHgwM2EzOwogIHQuU2l4cm9tYW4gPSAweDIxNjU7CiAgdC5TbW9ub3NwYWNlID0gMHhmZjMzOwogIHQuU29mdHNpZ25jeXJpbGxpYyA9IDB4MDQyYzsKICB0LlNzbWFsbCA9IDB4Zjc3MzsKICB0LlN0aWdtYWdyZWVrID0gMHgwM2RhOwogIHQuVCA9IDB4MDA1NDsKICB0LlRhdSA9IDB4MDNhNDsKICB0LlRiYXIgPSAweDAxNjY7CiAgdC5UY2Fyb24gPSAweDAxNjQ7CiAgdC5UY2VkaWxsYSA9IDB4MDE2MjsKICB0LlRjaXJjbGUgPSAweDI0Yzk7CiAgdC5UY2lyY3VtZmxleGJlbG93ID0gMHgxZTcwOwogIHQuVGNvbW1hYWNjZW50ID0gMHgwMTYyOwogIHQuVGRvdGFjY2VudCA9IDB4MWU2YTsKICB0LlRkb3RiZWxvdyA9IDB4MWU2YzsKICB0LlRlY3lyaWxsaWMgPSAweDA0MjI7CiAgdC5UZWRlc2NlbmRlcmN5cmlsbGljID0gMHgwNGFjOwogIHQuVGVucm9tYW4gPSAweDIxNjk7CiAgdC5UZXRzZWN5cmlsbGljID0gMHgwNGI0OwogIHQuVGhldGEgPSAweDAzOTg7CiAgdC5UaG9vayA9IDB4MDFhYzsKICB0LlRob3JuID0gMHgwMGRlOwogIHQuVGhvcm5zbWFsbCA9IDB4ZjdmZTsKICB0LlRocmVlcm9tYW4gPSAweDIxNjI7CiAgdC5UaWxkZXNtYWxsID0gMHhmNmZlOwogIHQuVGl3bmFybWVuaWFuID0gMHgwNTRmOwogIHQuVGxpbmViZWxvdyA9IDB4MWU2ZTsKICB0LlRtb25vc3BhY2UgPSAweGZmMzQ7CiAgdC5Ub2FybWVuaWFuID0gMHgwNTM5OwogIHQuVG9uZWZpdmUgPSAweDAxYmM7CiAgdC5Ub25lc2l4ID0gMHgwMTg0OwogIHQuVG9uZXR3byA9IDB4MDFhNzsKICB0LlRyZXRyb2ZsZXhob29rID0gMHgwMWFlOwogIHQuVHNlY3lyaWxsaWMgPSAweDA0MjY7CiAgdC5Uc2hlY3lyaWxsaWMgPSAweDA0MGI7CiAgdC5Uc21hbGwgPSAweGY3NzQ7CiAgdC5Ud2VsdmVyb21hbiA9IDB4MjE2YjsKICB0LlR3b3JvbWFuID0gMHgyMTYxOwogIHQuVSA9IDB4MDA1NTsKICB0LlVhY3V0ZSA9IDB4MDBkYTsKICB0LlVhY3V0ZXNtYWxsID0gMHhmN2ZhOwogIHQuVWJyZXZlID0gMHgwMTZjOwogIHQuVWNhcm9uID0gMHgwMWQzOwogIHQuVWNpcmNsZSA9IDB4MjRjYTsKICB0LlVjaXJjdW1mbGV4ID0gMHgwMGRiOwogIHQuVWNpcmN1bWZsZXhiZWxvdyA9IDB4MWU3NjsKICB0LlVjaXJjdW1mbGV4c21hbGwgPSAweGY3ZmI7CiAgdC5VY3lyaWxsaWMgPSAweDA0MjM7CiAgdC5VZGJsYWN1dGUgPSAweDAxNzA7CiAgdC5VZGJsZ3JhdmUgPSAweDAyMTQ7CiAgdC5VZGllcmVzaXMgPSAweDAwZGM7CiAgdC5VZGllcmVzaXNhY3V0ZSA9IDB4MDFkNzsKICB0LlVkaWVyZXNpc2JlbG93ID0gMHgxZTcyOwogIHQuVWRpZXJlc2lzY2Fyb24gPSAweDAxZDk7CiAgdC5VZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRmMDsKICB0LlVkaWVyZXNpc2dyYXZlID0gMHgwMWRiOwogIHQuVWRpZXJlc2lzbWFjcm9uID0gMHgwMWQ1OwogIHQuVWRpZXJlc2lzc21hbGwgPSAweGY3ZmM7CiAgdC5VZG90YmVsb3cgPSAweDFlZTQ7CiAgdC5VZ3JhdmUgPSAweDAwZDk7CiAgdC5VZ3JhdmVzbWFsbCA9IDB4ZjdmOTsKICB0LlVob29rYWJvdmUgPSAweDFlZTY7CiAgdC5VaG9ybiA9IDB4MDFhZjsKICB0LlVob3JuYWN1dGUgPSAweDFlZTg7CiAgdC5VaG9ybmRvdGJlbG93ID0gMHgxZWYwOwogIHQuVWhvcm5ncmF2ZSA9IDB4MWVlYTsKICB0LlVob3JuaG9va2Fib3ZlID0gMHgxZWVjOwogIHQuVWhvcm50aWxkZSA9IDB4MWVlZTsKICB0LlVodW5nYXJ1bWxhdXQgPSAweDAxNzA7CiAgdC5VaHVuZ2FydW1sYXV0Y3lyaWxsaWMgPSAweDA0ZjI7CiAgdC5VaW52ZXJ0ZWRicmV2ZSA9IDB4MDIxNjsKICB0LlVrY3lyaWxsaWMgPSAweDA0Nzg7CiAgdC5VbWFjcm9uID0gMHgwMTZhOwogIHQuVW1hY3JvbmN5cmlsbGljID0gMHgwNGVlOwogIHQuVW1hY3JvbmRpZXJlc2lzID0gMHgxZTdhOwogIHQuVW1vbm9zcGFjZSA9IDB4ZmYzNTsKICB0LlVvZ29uZWsgPSAweDAxNzI7CiAgdC5VcHNpbG9uID0gMHgwM2E1OwogIHQuVXBzaWxvbjEgPSAweDAzZDI7CiAgdC5VcHNpbG9uYWN1dGVob29rc3ltYm9sZ3JlZWsgPSAweDAzZDM7CiAgdC5VcHNpbG9uYWZyaWNhbiA9IDB4MDFiMTsKICB0LlVwc2lsb25kaWVyZXNpcyA9IDB4MDNhYjsKICB0LlVwc2lsb25kaWVyZXNpc2hvb2tzeW1ib2xncmVlayA9IDB4MDNkNDsKICB0LlVwc2lsb25ob29rc3ltYm9sID0gMHgwM2QyOwogIHQuVXBzaWxvbnRvbm9zID0gMHgwMzhlOwogIHQuVXJpbmcgPSAweDAxNmU7CiAgdC5Vc2hvcnRjeXJpbGxpYyA9IDB4MDQwZTsKICB0LlVzbWFsbCA9IDB4Zjc3NTsKICB0LlVzdHJhaWdodGN5cmlsbGljID0gMHgwNGFlOwogIHQuVXN0cmFpZ2h0c3Ryb2tlY3lyaWxsaWMgPSAweDA0YjA7CiAgdC5VdGlsZGUgPSAweDAxNjg7CiAgdC5VdGlsZGVhY3V0ZSA9IDB4MWU3ODsKICB0LlV0aWxkZWJlbG93ID0gMHgxZTc0OwogIHQuViA9IDB4MDA1NjsKICB0LlZjaXJjbGUgPSAweDI0Y2I7CiAgdC5WZG90YmVsb3cgPSAweDFlN2U7CiAgdC5WZWN5cmlsbGljID0gMHgwNDEyOwogIHQuVmV3YXJtZW5pYW4gPSAweDA1NGU7CiAgdC5WaG9vayA9IDB4MDFiMjsKICB0LlZtb25vc3BhY2UgPSAweGZmMzY7CiAgdC5Wb2FybWVuaWFuID0gMHgwNTQ4OwogIHQuVnNtYWxsID0gMHhmNzc2OwogIHQuVnRpbGRlID0gMHgxZTdjOwogIHQuVyA9IDB4MDA1NzsKICB0LldhY3V0ZSA9IDB4MWU4MjsKICB0LldjaXJjbGUgPSAweDI0Y2M7CiAgdC5XY2lyY3VtZmxleCA9IDB4MDE3NDsKICB0LldkaWVyZXNpcyA9IDB4MWU4NDsKICB0Lldkb3RhY2NlbnQgPSAweDFlODY7CiAgdC5XZG90YmVsb3cgPSAweDFlODg7CiAgdC5XZ3JhdmUgPSAweDFlODA7CiAgdC5XbW9ub3NwYWNlID0gMHhmZjM3OwogIHQuV3NtYWxsID0gMHhmNzc3OwogIHQuWCA9IDB4MDA1ODsKICB0LlhjaXJjbGUgPSAweDI0Y2Q7CiAgdC5YZGllcmVzaXMgPSAweDFlOGM7CiAgdC5YZG90YWNjZW50ID0gMHgxZThhOwogIHQuWGVoYXJtZW5pYW4gPSAweDA1M2Q7CiAgdC5YaSA9IDB4MDM5ZTsKICB0Llhtb25vc3BhY2UgPSAweGZmMzg7CiAgdC5Yc21hbGwgPSAweGY3Nzg7CiAgdC5ZID0gMHgwMDU5OwogIHQuWWFjdXRlID0gMHgwMGRkOwogIHQuWWFjdXRlc21hbGwgPSAweGY3ZmQ7CiAgdC5ZYXRjeXJpbGxpYyA9IDB4MDQ2MjsKICB0LlljaXJjbGUgPSAweDI0Y2U7CiAgdC5ZY2lyY3VtZmxleCA9IDB4MDE3NjsKICB0LllkaWVyZXNpcyA9IDB4MDE3ODsKICB0LllkaWVyZXNpc3NtYWxsID0gMHhmN2ZmOwogIHQuWWRvdGFjY2VudCA9IDB4MWU4ZTsKICB0Lllkb3RiZWxvdyA9IDB4MWVmNDsKICB0LlllcmljeXJpbGxpYyA9IDB4MDQyYjsKICB0LlllcnVkaWVyZXNpc2N5cmlsbGljID0gMHgwNGY4OwogIHQuWWdyYXZlID0gMHgxZWYyOwogIHQuWWhvb2sgPSAweDAxYjM7CiAgdC5ZaG9va2Fib3ZlID0gMHgxZWY2OwogIHQuWWlhcm1lbmlhbiA9IDB4MDU0NTsKICB0LllpY3lyaWxsaWMgPSAweDA0MDc7CiAgdC5ZaXduYXJtZW5pYW4gPSAweDA1NTI7CiAgdC5ZbW9ub3NwYWNlID0gMHhmZjM5OwogIHQuWXNtYWxsID0gMHhmNzc5OwogIHQuWXRpbGRlID0gMHgxZWY4OwogIHQuWXVzYmlnY3lyaWxsaWMgPSAweDA0NmE7CiAgdC5ZdXNiaWdpb3RpZmllZGN5cmlsbGljID0gMHgwNDZjOwogIHQuWXVzbGl0dGxlY3lyaWxsaWMgPSAweDA0NjY7CiAgdC5ZdXNsaXR0bGVpb3RpZmllZGN5cmlsbGljID0gMHgwNDY4OwogIHQuWiA9IDB4MDA1YTsKICB0LlphYXJtZW5pYW4gPSAweDA1MzY7CiAgdC5aYWN1dGUgPSAweDAxNzk7CiAgdC5aY2Fyb24gPSAweDAxN2Q7CiAgdC5aY2Fyb25zbWFsbCA9IDB4ZjZmZjsKICB0LlpjaXJjbGUgPSAweDI0Y2Y7CiAgdC5aY2lyY3VtZmxleCA9IDB4MWU5MDsKICB0Llpkb3QgPSAweDAxN2I7CiAgdC5aZG90YWNjZW50ID0gMHgwMTdiOwogIHQuWmRvdGJlbG93ID0gMHgxZTkyOwogIHQuWmVjeXJpbGxpYyA9IDB4MDQxNzsKICB0LlplZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0OTg7CiAgdC5aZWRpZXJlc2lzY3lyaWxsaWMgPSAweDA0ZGU7CiAgdC5aZXRhID0gMHgwMzk2OwogIHQuWmhlYXJtZW5pYW4gPSAweDA1M2E7CiAgdC5aaGVicmV2ZWN5cmlsbGljID0gMHgwNGMxOwogIHQuWmhlY3lyaWxsaWMgPSAweDA0MTY7CiAgdC5aaGVkZXNjZW5kZXJjeXJpbGxpYyA9IDB4MDQ5NjsKICB0LlpoZWRpZXJlc2lzY3lyaWxsaWMgPSAweDA0ZGM7CiAgdC5abGluZWJlbG93ID0gMHgxZTk0OwogIHQuWm1vbm9zcGFjZSA9IDB4ZmYzYTsKICB0LlpzbWFsbCA9IDB4Zjc3YTsKICB0LlpzdHJva2UgPSAweDAxYjU7CiAgdC5hID0gMHgwMDYxOwogIHQuYWFiZW5nYWxpID0gMHgwOTg2OwogIHQuYWFjdXRlID0gMHgwMGUxOwogIHQuYWFkZXZhID0gMHgwOTA2OwogIHQuYWFndWphcmF0aSA9IDB4MGE4NjsKICB0LmFhZ3VybXVraGkgPSAweDBhMDY7CiAgdC5hYW1hdHJhZ3VybXVraGkgPSAweDBhM2U7CiAgdC5hYXJ1c3F1YXJlID0gMHgzMzAzOwogIHQuYWF2b3dlbHNpZ25iZW5nYWxpID0gMHgwOWJlOwogIHQuYWF2b3dlbHNpZ25kZXZhID0gMHgwOTNlOwogIHQuYWF2b3dlbHNpZ25ndWphcmF0aSA9IDB4MGFiZTsKICB0LmFiYnJldmlhdGlvbm1hcmthcm1lbmlhbiA9IDB4MDU1ZjsKICB0LmFiYnJldmlhdGlvbnNpZ25kZXZhID0gMHgwOTcwOwogIHQuYWJlbmdhbGkgPSAweDA5ODU7CiAgdC5hYm9wb21vZm8gPSAweDMxMWE7CiAgdC5hYnJldmUgPSAweDAxMDM7CiAgdC5hYnJldmVhY3V0ZSA9IDB4MWVhZjsKICB0LmFicmV2ZWN5cmlsbGljID0gMHgwNGQxOwogIHQuYWJyZXZlZG90YmVsb3cgPSAweDFlYjc7CiAgdC5hYnJldmVncmF2ZSA9IDB4MWViMTsKICB0LmFicmV2ZWhvb2thYm92ZSA9IDB4MWViMzsKICB0LmFicmV2ZXRpbGRlID0gMHgxZWI1OwogIHQuYWNhcm9uID0gMHgwMWNlOwogIHQuYWNpcmNsZSA9IDB4MjRkMDsKICB0LmFjaXJjdW1mbGV4ID0gMHgwMGUyOwogIHQuYWNpcmN1bWZsZXhhY3V0ZSA9IDB4MWVhNTsKICB0LmFjaXJjdW1mbGV4ZG90YmVsb3cgPSAweDFlYWQ7CiAgdC5hY2lyY3VtZmxleGdyYXZlID0gMHgxZWE3OwogIHQuYWNpcmN1bWZsZXhob29rYWJvdmUgPSAweDFlYTk7CiAgdC5hY2lyY3VtZmxleHRpbGRlID0gMHgxZWFiOwogIHQuYWN1dGUgPSAweDAwYjQ7CiAgdC5hY3V0ZWJlbG93Y21iID0gMHgwMzE3OwogIHQuYWN1dGVjbWIgPSAweDAzMDE7CiAgdC5hY3V0ZWNvbWIgPSAweDAzMDE7CiAgdC5hY3V0ZWRldmEgPSAweDA5NTQ7CiAgdC5hY3V0ZWxvd21vZCA9IDB4MDJjZjsKICB0LmFjdXRldG9uZWNtYiA9IDB4MDM0MTsKICB0LmFjeXJpbGxpYyA9IDB4MDQzMDsKICB0LmFkYmxncmF2ZSA9IDB4MDIwMTsKICB0LmFkZGFrZ3VybXVraGkgPSAweDBhNzE7CiAgdC5hZGV2YSA9IDB4MDkwNTsKICB0LmFkaWVyZXNpcyA9IDB4MDBlNDsKICB0LmFkaWVyZXNpc2N5cmlsbGljID0gMHgwNGQzOwogIHQuYWRpZXJlc2lzbWFjcm9uID0gMHgwMWRmOwogIHQuYWRvdGJlbG93ID0gMHgxZWExOwogIHQuYWRvdG1hY3JvbiA9IDB4MDFlMTsKICB0LmFlID0gMHgwMGU2OwogIHQuYWVhY3V0ZSA9IDB4MDFmZDsKICB0LmFla29yZWFuID0gMHgzMTUwOwogIHQuYWVtYWNyb24gPSAweDAxZTM7CiAgdC5hZmlpMDAyMDggPSAweDIwMTU7CiAgdC5hZmlpMDg5NDEgPSAweDIwYTQ7CiAgdC5hZmlpMTAwMTcgPSAweDA0MTA7CiAgdC5hZmlpMTAwMTggPSAweDA0MTE7CiAgdC5hZmlpMTAwMTkgPSAweDA0MTI7CiAgdC5hZmlpMTAwMjAgPSAweDA0MTM7CiAgdC5hZmlpMTAwMjEgPSAweDA0MTQ7CiAgdC5hZmlpMTAwMjIgPSAweDA0MTU7CiAgdC5hZmlpMTAwMjMgPSAweDA0MDE7CiAgdC5hZmlpMTAwMjQgPSAweDA0MTY7CiAgdC5hZmlpMTAwMjUgPSAweDA0MTc7CiAgdC5hZmlpMTAwMjYgPSAweDA0MTg7CiAgdC5hZmlpMTAwMjcgPSAweDA0MTk7CiAgdC5hZmlpMTAwMjggPSAweDA0MWE7CiAgdC5hZmlpMTAwMjkgPSAweDA0MWI7CiAgdC5hZmlpMTAwMzAgPSAweDA0MWM7CiAgdC5hZmlpMTAwMzEgPSAweDA0MWQ7CiAgdC5hZmlpMTAwMzIgPSAweDA0MWU7CiAgdC5hZmlpMTAwMzMgPSAweDA0MWY7CiAgdC5hZmlpMTAwMzQgPSAweDA0MjA7CiAgdC5hZmlpMTAwMzUgPSAweDA0MjE7CiAgdC5hZmlpMTAwMzYgPSAweDA0MjI7CiAgdC5hZmlpMTAwMzcgPSAweDA0MjM7CiAgdC5hZmlpMTAwMzggPSAweDA0MjQ7CiAgdC5hZmlpMTAwMzkgPSAweDA0MjU7CiAgdC5hZmlpMTAwNDAgPSAweDA0MjY7CiAgdC5hZmlpMTAwNDEgPSAweDA0Mjc7CiAgdC5hZmlpMTAwNDIgPSAweDA0Mjg7CiAgdC5hZmlpMTAwNDMgPSAweDA0Mjk7CiAgdC5hZmlpMTAwNDQgPSAweDA0MmE7CiAgdC5hZmlpMTAwNDUgPSAweDA0MmI7CiAgdC5hZmlpMTAwNDYgPSAweDA0MmM7CiAgdC5hZmlpMTAwNDcgPSAweDA0MmQ7CiAgdC5hZmlpMTAwNDggPSAweDA0MmU7CiAgdC5hZmlpMTAwNDkgPSAweDA0MmY7CiAgdC5hZmlpMTAwNTAgPSAweDA0OTA7CiAgdC5hZmlpMTAwNTEgPSAweDA0MDI7CiAgdC5hZmlpMTAwNTIgPSAweDA0MDM7CiAgdC5hZmlpMTAwNTMgPSAweDA0MDQ7CiAgdC5hZmlpMTAwNTQgPSAweDA0MDU7CiAgdC5hZmlpMTAwNTUgPSAweDA0MDY7CiAgdC5hZmlpMTAwNTYgPSAweDA0MDc7CiAgdC5hZmlpMTAwNTcgPSAweDA0MDg7CiAgdC5hZmlpMTAwNTggPSAweDA0MDk7CiAgdC5hZmlpMTAwNTkgPSAweDA0MGE7CiAgdC5hZmlpMTAwNjAgPSAweDA0MGI7CiAgdC5hZmlpMTAwNjEgPSAweDA0MGM7CiAgdC5hZmlpMTAwNjIgPSAweDA0MGU7CiAgdC5hZmlpMTAwNjMgPSAweGY2YzQ7CiAgdC5hZmlpMTAwNjQgPSAweGY2YzU7CiAgdC5hZmlpMTAwNjUgPSAweDA0MzA7CiAgdC5hZmlpMTAwNjYgPSAweDA0MzE7CiAgdC5hZmlpMTAwNjcgPSAweDA0MzI7CiAgdC5hZmlpMTAwNjggPSAweDA0MzM7CiAgdC5hZmlpMTAwNjkgPSAweDA0MzQ7CiAgdC5hZmlpMTAwNzAgPSAweDA0MzU7CiAgdC5hZmlpMTAwNzEgPSAweDA0NTE7CiAgdC5hZmlpMTAwNzIgPSAweDA0MzY7CiAgdC5hZmlpMTAwNzMgPSAweDA0Mzc7CiAgdC5hZmlpMTAwNzQgPSAweDA0Mzg7CiAgdC5hZmlpMTAwNzUgPSAweDA0Mzk7CiAgdC5hZmlpMTAwNzYgPSAweDA0M2E7CiAgdC5hZmlpMTAwNzcgPSAweDA0M2I7CiAgdC5hZmlpMTAwNzggPSAweDA0M2M7CiAgdC5hZmlpMTAwNzkgPSAweDA0M2Q7CiAgdC5hZmlpMTAwODAgPSAweDA0M2U7CiAgdC5hZmlpMTAwODEgPSAweDA0M2Y7CiAgdC5hZmlpMTAwODIgPSAweDA0NDA7CiAgdC5hZmlpMTAwODMgPSAweDA0NDE7CiAgdC5hZmlpMTAwODQgPSAweDA0NDI7CiAgdC5hZmlpMTAwODUgPSAweDA0NDM7CiAgdC5hZmlpMTAwODYgPSAweDA0NDQ7CiAgdC5hZmlpMTAwODcgPSAweDA0NDU7CiAgdC5hZmlpMTAwODggPSAweDA0NDY7CiAgdC5hZmlpMTAwODkgPSAweDA0NDc7CiAgdC5hZmlpMTAwOTAgPSAweDA0NDg7CiAgdC5hZmlpMTAwOTEgPSAweDA0NDk7CiAgdC5hZmlpMTAwOTIgPSAweDA0NGE7CiAgdC5hZmlpMTAwOTMgPSAweDA0NGI7CiAgdC5hZmlpMTAwOTQgPSAweDA0NGM7CiAgdC5hZmlpMTAwOTUgPSAweDA0NGQ7CiAgdC5hZmlpMTAwOTYgPSAweDA0NGU7CiAgdC5hZmlpMTAwOTcgPSAweDA0NGY7CiAgdC5hZmlpMTAwOTggPSAweDA0OTE7CiAgdC5hZmlpMTAwOTkgPSAweDA0NTI7CiAgdC5hZmlpMTAxMDAgPSAweDA0NTM7CiAgdC5hZmlpMTAxMDEgPSAweDA0NTQ7CiAgdC5hZmlpMTAxMDIgPSAweDA0NTU7CiAgdC5hZmlpMTAxMDMgPSAweDA0NTY7CiAgdC5hZmlpMTAxMDQgPSAweDA0NTc7CiAgdC5hZmlpMTAxMDUgPSAweDA0NTg7CiAgdC5hZmlpMTAxMDYgPSAweDA0NTk7CiAgdC5hZmlpMTAxMDcgPSAweDA0NWE7CiAgdC5hZmlpMTAxMDggPSAweDA0NWI7CiAgdC5hZmlpMTAxMDkgPSAweDA0NWM7CiAgdC5hZmlpMTAxMTAgPSAweDA0NWU7CiAgdC5hZmlpMTAxNDUgPSAweDA0MGY7CiAgdC5hZmlpMTAxNDYgPSAweDA0NjI7CiAgdC5hZmlpMTAxNDcgPSAweDA0NzI7CiAgdC5hZmlpMTAxNDggPSAweDA0NzQ7CiAgdC5hZmlpMTAxOTIgPSAweGY2YzY7CiAgdC5hZmlpMTAxOTMgPSAweDA0NWY7CiAgdC5hZmlpMTAxOTQgPSAweDA0NjM7CiAgdC5hZmlpMTAxOTUgPSAweDA0NzM7CiAgdC5hZmlpMTAxOTYgPSAweDA0NzU7CiAgdC5hZmlpMTA4MzEgPSAweGY2Yzc7CiAgdC5hZmlpMTA4MzIgPSAweGY2Yzg7CiAgdC5hZmlpMTA4NDYgPSAweDA0ZDk7CiAgdC5hZmlpMjk5ID0gMHgyMDBlOwogIHQuYWZpaTMwMCA9IDB4MjAwZjsKICB0LmFmaWkzMDEgPSAweDIwMGQ7CiAgdC5hZmlpNTczODEgPSAweDA2NmE7CiAgdC5hZmlpNTczODggPSAweDA2MGM7CiAgdC5hZmlpNTczOTIgPSAweDA2NjA7CiAgdC5hZmlpNTczOTMgPSAweDA2NjE7CiAgdC5hZmlpNTczOTQgPSAweDA2NjI7CiAgdC5hZmlpNTczOTUgPSAweDA2NjM7CiAgdC5hZmlpNTczOTYgPSAweDA2NjQ7CiAgdC5hZmlpNTczOTcgPSAweDA2NjU7CiAgdC5hZmlpNTczOTggPSAweDA2NjY7CiAgdC5hZmlpNTczOTkgPSAweDA2Njc7CiAgdC5hZmlpNTc0MDAgPSAweDA2Njg7CiAgdC5hZmlpNTc0MDEgPSAweDA2Njk7CiAgdC5hZmlpNTc0MDMgPSAweDA2MWI7CiAgdC5hZmlpNTc0MDcgPSAweDA2MWY7CiAgdC5hZmlpNTc0MDkgPSAweDA2MjE7CiAgdC5hZmlpNTc0MTAgPSAweDA2MjI7CiAgdC5hZmlpNTc0MTEgPSAweDA2MjM7CiAgdC5hZmlpNTc0MTIgPSAweDA2MjQ7CiAgdC5hZmlpNTc0MTMgPSAweDA2MjU7CiAgdC5hZmlpNTc0MTQgPSAweDA2MjY7CiAgdC5hZmlpNTc0MTUgPSAweDA2Mjc7CiAgdC5hZmlpNTc0MTYgPSAweDA2Mjg7CiAgdC5hZmlpNTc0MTcgPSAweDA2Mjk7CiAgdC5hZmlpNTc0MTggPSAweDA2MmE7CiAgdC5hZmlpNTc0MTkgPSAweDA2MmI7CiAgdC5hZmlpNTc0MjAgPSAweDA2MmM7CiAgdC5hZmlpNTc0MjEgPSAweDA2MmQ7CiAgdC5hZmlpNTc0MjIgPSAweDA2MmU7CiAgdC5hZmlpNTc0MjMgPSAweDA2MmY7CiAgdC5hZmlpNTc0MjQgPSAweDA2MzA7CiAgdC5hZmlpNTc0MjUgPSAweDA2MzE7CiAgdC5hZmlpNTc0MjYgPSAweDA2MzI7CiAgdC5hZmlpNTc0MjcgPSAweDA2MzM7CiAgdC5hZmlpNTc0MjggPSAweDA2MzQ7CiAgdC5hZmlpNTc0MjkgPSAweDA2MzU7CiAgdC5hZmlpNTc0MzAgPSAweDA2MzY7CiAgdC5hZmlpNTc0MzEgPSAweDA2Mzc7CiAgdC5hZmlpNTc0MzIgPSAweDA2Mzg7CiAgdC5hZmlpNTc0MzMgPSAweDA2Mzk7CiAgdC5hZmlpNTc0MzQgPSAweDA2M2E7CiAgdC5hZmlpNTc0NDAgPSAweDA2NDA7CiAgdC5hZmlpNTc0NDEgPSAweDA2NDE7CiAgdC5hZmlpNTc0NDIgPSAweDA2NDI7CiAgdC5hZmlpNTc0NDMgPSAweDA2NDM7CiAgdC5hZmlpNTc0NDQgPSAweDA2NDQ7CiAgdC5hZmlpNTc0NDUgPSAweDA2NDU7CiAgdC5hZmlpNTc0NDYgPSAweDA2NDY7CiAgdC5hZmlpNTc0NDggPSAweDA2NDg7CiAgdC5hZmlpNTc0NDkgPSAweDA2NDk7CiAgdC5hZmlpNTc0NTAgPSAweDA2NGE7CiAgdC5hZmlpNTc0NTEgPSAweDA2NGI7CiAgdC5hZmlpNTc0NTIgPSAweDA2NGM7CiAgdC5hZmlpNTc0NTMgPSAweDA2NGQ7CiAgdC5hZmlpNTc0NTQgPSAweDA2NGU7CiAgdC5hZmlpNTc0NTUgPSAweDA2NGY7CiAgdC5hZmlpNTc0NTYgPSAweDA2NTA7CiAgdC5hZmlpNTc0NTcgPSAweDA2NTE7CiAgdC5hZmlpNTc0NTggPSAweDA2NTI7CiAgdC5hZmlpNTc0NzAgPSAweDA2NDc7CiAgdC5hZmlpNTc1MDUgPSAweDA2YTQ7CiAgdC5hZmlpNTc1MDYgPSAweDA2N2U7CiAgdC5hZmlpNTc1MDcgPSAweDA2ODY7CiAgdC5hZmlpNTc1MDggPSAweDA2OTg7CiAgdC5hZmlpNTc1MDkgPSAweDA2YWY7CiAgdC5hZmlpNTc1MTEgPSAweDA2Nzk7CiAgdC5hZmlpNTc1MTIgPSAweDA2ODg7CiAgdC5hZmlpNTc1MTMgPSAweDA2OTE7CiAgdC5hZmlpNTc1MTQgPSAweDA2YmE7CiAgdC5hZmlpNTc1MTkgPSAweDA2ZDI7CiAgdC5hZmlpNTc1MzQgPSAweDA2ZDU7CiAgdC5hZmlpNTc2MzYgPSAweDIwYWE7CiAgdC5hZmlpNTc2NDUgPSAweDA1YmU7CiAgdC5hZmlpNTc2NTggPSAweDA1YzM7CiAgdC5hZmlpNTc2NjQgPSAweDA1ZDA7CiAgdC5hZmlpNTc2NjUgPSAweDA1ZDE7CiAgdC5hZmlpNTc2NjYgPSAweDA1ZDI7CiAgdC5hZmlpNTc2NjcgPSAweDA1ZDM7CiAgdC5hZmlpNTc2NjggPSAweDA1ZDQ7CiAgdC5hZmlpNTc2NjkgPSAweDA1ZDU7CiAgdC5hZmlpNTc2NzAgPSAweDA1ZDY7CiAgdC5hZmlpNTc2NzEgPSAweDA1ZDc7CiAgdC5hZmlpNTc2NzIgPSAweDA1ZDg7CiAgdC5hZmlpNTc2NzMgPSAweDA1ZDk7CiAgdC5hZmlpNTc2NzQgPSAweDA1ZGE7CiAgdC5hZmlpNTc2NzUgPSAweDA1ZGI7CiAgdC5hZmlpNTc2NzYgPSAweDA1ZGM7CiAgdC5hZmlpNTc2NzcgPSAweDA1ZGQ7CiAgdC5hZmlpNTc2NzggPSAweDA1ZGU7CiAgdC5hZmlpNTc2NzkgPSAweDA1ZGY7CiAgdC5hZmlpNTc2ODAgPSAweDA1ZTA7CiAgdC5hZmlpNTc2ODEgPSAweDA1ZTE7CiAgdC5hZmlpNTc2ODIgPSAweDA1ZTI7CiAgdC5hZmlpNTc2ODMgPSAweDA1ZTM7CiAgdC5hZmlpNTc2ODQgPSAweDA1ZTQ7CiAgdC5hZmlpNTc2ODUgPSAweDA1ZTU7CiAgdC5hZmlpNTc2ODYgPSAweDA1ZTY7CiAgdC5hZmlpNTc2ODcgPSAweDA1ZTc7CiAgdC5hZmlpNTc2ODggPSAweDA1ZTg7CiAgdC5hZmlpNTc2ODkgPSAweDA1ZTk7CiAgdC5hZmlpNTc2OTAgPSAweDA1ZWE7CiAgdC5hZmlpNTc2OTQgPSAweGZiMmE7CiAgdC5hZmlpNTc2OTUgPSAweGZiMmI7CiAgdC5hZmlpNTc3MDAgPSAweGZiNGI7CiAgdC5hZmlpNTc3MDUgPSAweGZiMWY7CiAgdC5hZmlpNTc3MTYgPSAweDA1ZjA7CiAgdC5hZmlpNTc3MTcgPSAweDA1ZjE7CiAgdC5hZmlpNTc3MTggPSAweDA1ZjI7CiAgdC5hZmlpNTc3MjMgPSAweGZiMzU7CiAgdC5hZmlpNTc3OTMgPSAweDA1YjQ7CiAgdC5hZmlpNTc3OTQgPSAweDA1YjU7CiAgdC5hZmlpNTc3OTUgPSAweDA1YjY7CiAgdC5hZmlpNTc3OTYgPSAweDA1YmI7CiAgdC5hZmlpNTc3OTcgPSAweDA1Yjg7CiAgdC5hZmlpNTc3OTggPSAweDA1Yjc7CiAgdC5hZmlpNTc3OTkgPSAweDA1YjA7CiAgdC5hZmlpNTc4MDAgPSAweDA1YjI7CiAgdC5hZmlpNTc4MDEgPSAweDA1YjE7CiAgdC5hZmlpNTc4MDIgPSAweDA1YjM7CiAgdC5hZmlpNTc4MDMgPSAweDA1YzI7CiAgdC5hZmlpNTc4MDQgPSAweDA1YzE7CiAgdC5hZmlpNTc4MDYgPSAweDA1Yjk7CiAgdC5hZmlpNTc4MDcgPSAweDA1YmM7CiAgdC5hZmlpNTc4MzkgPSAweDA1YmQ7CiAgdC5hZmlpNTc4NDEgPSAweDA1YmY7CiAgdC5hZmlpNTc4NDIgPSAweDA1YzA7CiAgdC5hZmlpNTc5MjkgPSAweDAyYmM7CiAgdC5hZmlpNjEyNDggPSAweDIxMDU7CiAgdC5hZmlpNjEyODkgPSAweDIxMTM7CiAgdC5hZmlpNjEzNTIgPSAweDIxMTY7CiAgdC5hZmlpNjE1NzMgPSAweDIwMmM7CiAgdC5hZmlpNjE1NzQgPSAweDIwMmQ7CiAgdC5hZmlpNjE1NzUgPSAweDIwMmU7CiAgdC5hZmlpNjE2NjQgPSAweDIwMGM7CiAgdC5hZmlpNjMxNjcgPSAweDA2NmQ7CiAgdC5hZmlpNjQ5MzcgPSAweDAyYmQ7CiAgdC5hZ3JhdmUgPSAweDAwZTA7CiAgdC5hZ3VqYXJhdGkgPSAweDBhODU7CiAgdC5hZ3VybXVraGkgPSAweDBhMDU7CiAgdC5haGlyYWdhbmEgPSAweDMwNDI7CiAgdC5haG9va2Fib3ZlID0gMHgxZWEzOwogIHQuYWliZW5nYWxpID0gMHgwOTkwOwogIHQuYWlib3BvbW9mbyA9IDB4MzExZTsKICB0LmFpZGV2YSA9IDB4MDkxMDsKICB0LmFpZWN5cmlsbGljID0gMHgwNGQ1OwogIHQuYWlndWphcmF0aSA9IDB4MGE5MDsKICB0LmFpZ3VybXVraGkgPSAweDBhMTA7CiAgdC5haW1hdHJhZ3VybXVraGkgPSAweDBhNDg7CiAgdC5haW5hcmFiaWMgPSAweDA2Mzk7CiAgdC5haW5maW5hbGFyYWJpYyA9IDB4ZmVjYTsKICB0LmFpbmluaXRpYWxhcmFiaWMgPSAweGZlY2I7CiAgdC5haW5tZWRpYWxhcmFiaWMgPSAweGZlY2M7CiAgdC5haW52ZXJ0ZWRicmV2ZSA9IDB4MDIwMzsKICB0LmFpdm93ZWxzaWduYmVuZ2FsaSA9IDB4MDljODsKICB0LmFpdm93ZWxzaWduZGV2YSA9IDB4MDk0ODsKICB0LmFpdm93ZWxzaWduZ3VqYXJhdGkgPSAweDBhYzg7CiAgdC5ha2F0YWthbmEgPSAweDMwYTI7CiAgdC5ha2F0YWthbmFoYWxmd2lkdGggPSAweGZmNzE7CiAgdC5ha29yZWFuID0gMHgzMTRmOwogIHQuYWxlZiA9IDB4MDVkMDsKICB0LmFsZWZhcmFiaWMgPSAweDA2Mjc7CiAgdC5hbGVmZGFnZXNoaGVicmV3ID0gMHhmYjMwOwogIHQuYWxlZmZpbmFsYXJhYmljID0gMHhmZThlOwogIHQuYWxlZmhhbXphYWJvdmVhcmFiaWMgPSAweDA2MjM7CiAgdC5hbGVmaGFtemFhYm92ZWZpbmFsYXJhYmljID0gMHhmZTg0OwogIHQuYWxlZmhhbXphYmVsb3dhcmFiaWMgPSAweDA2MjU7CiAgdC5hbGVmaGFtemFiZWxvd2ZpbmFsYXJhYmljID0gMHhmZTg4OwogIHQuYWxlZmhlYnJldyA9IDB4MDVkMDsKICB0LmFsZWZsYW1lZGhlYnJldyA9IDB4ZmI0ZjsKICB0LmFsZWZtYWRkYWFib3ZlYXJhYmljID0gMHgwNjIyOwogIHQuYWxlZm1hZGRhYWJvdmVmaW5hbGFyYWJpYyA9IDB4ZmU4MjsKICB0LmFsZWZtYWtzdXJhYXJhYmljID0gMHgwNjQ5OwogIHQuYWxlZm1ha3N1cmFmaW5hbGFyYWJpYyA9IDB4ZmVmMDsKICB0LmFsZWZtYWtzdXJhaW5pdGlhbGFyYWJpYyA9IDB4ZmVmMzsKICB0LmFsZWZtYWtzdXJhbWVkaWFsYXJhYmljID0gMHhmZWY0OwogIHQuYWxlZnBhdGFoaGVicmV3ID0gMHhmYjJlOwogIHQuYWxlZnFhbWF0c2hlYnJldyA9IDB4ZmIyZjsKICB0LmFsZXBoID0gMHgyMTM1OwogIHQuYWxsZXF1YWwgPSAweDIyNGM7CiAgdC5hbHBoYSA9IDB4MDNiMTsKICB0LmFscGhhdG9ub3MgPSAweDAzYWM7CiAgdC5hbWFjcm9uID0gMHgwMTAxOwogIHQuYW1vbm9zcGFjZSA9IDB4ZmY0MTsKICB0LmFtcGVyc2FuZCA9IDB4MDAyNjsKICB0LmFtcGVyc2FuZG1vbm9zcGFjZSA9IDB4ZmYwNjsKICB0LmFtcGVyc2FuZHNtYWxsID0gMHhmNzI2OwogIHQuYW1zcXVhcmUgPSAweDMzYzI7CiAgdC5hbmJvcG9tb2ZvID0gMHgzMTIyOwogIHQuYW5nYm9wb21vZm8gPSAweDMxMjQ7CiAgdC5hbmdicmFja2V0bGVmdCA9IDB4MzAwODsKICB0LmFuZ2JyYWNrZXRyaWdodCA9IDB4MzAwOTsKICB0LmFuZ2toYW5raHV0aGFpID0gMHgwZTVhOwogIHQuYW5nbGUgPSAweDIyMjA7CiAgdC5hbmdsZWJyYWNrZXRsZWZ0ID0gMHgzMDA4OwogIHQuYW5nbGVicmFja2V0bGVmdHZlcnRpY2FsID0gMHhmZTNmOwogIHQuYW5nbGVicmFja2V0cmlnaHQgPSAweDMwMDk7CiAgdC5hbmdsZWJyYWNrZXRyaWdodHZlcnRpY2FsID0gMHhmZTQwOwogIHQuYW5nbGVsZWZ0ID0gMHgyMzI5OwogIHQuYW5nbGVyaWdodCA9IDB4MjMyYTsKICB0LmFuZ3N0cm9tID0gMHgyMTJiOwogIHQuYW5vdGVsZWlhID0gMHgwMzg3OwogIHQuYW51ZGF0dGFkZXZhID0gMHgwOTUyOwogIHQuYW51c3ZhcmFiZW5nYWxpID0gMHgwOTgyOwogIHQuYW51c3ZhcmFkZXZhID0gMHgwOTAyOwogIHQuYW51c3ZhcmFndWphcmF0aSA9IDB4MGE4MjsKICB0LmFvZ29uZWsgPSAweDAxMDU7CiAgdC5hcGFhdG9zcXVhcmUgPSAweDMzMDA7CiAgdC5hcGFyZW4gPSAweDI0OWM7CiAgdC5hcG9zdHJvcGhlYXJtZW5pYW4gPSAweDA1NWE7CiAgdC5hcG9zdHJvcGhlbW9kID0gMHgwMmJjOwogIHQuYXBwbGUgPSAweGY4ZmY7CiAgdC5hcHByb2FjaGVzID0gMHgyMjUwOwogIHQuYXBwcm94ZXF1YWwgPSAweDIyNDg7CiAgdC5hcHByb3hlcXVhbG9yaW1hZ2UgPSAweDIyNTI7CiAgdC5hcHByb3hpbWF0ZWx5ZXF1YWwgPSAweDIyNDU7CiAgdC5hcmFlYWVrb3JlYW4gPSAweDMxOGU7CiAgdC5hcmFlYWtvcmVhbiA9IDB4MzE4ZDsKICB0LmFyYyA9IDB4MjMxMjsKICB0LmFyaWdodGhhbGZyaW5nID0gMHgxZTlhOwogIHQuYXJpbmcgPSAweDAwZTU7CiAgdC5hcmluZ2FjdXRlID0gMHgwMWZiOwogIHQuYXJpbmdiZWxvdyA9IDB4MWUwMTsKICB0LmFycm93Ym90aCA9IDB4MjE5NDsKICB0LmFycm93ZGFzaGRvd24gPSAweDIxZTM7CiAgdC5hcnJvd2Rhc2hsZWZ0ID0gMHgyMWUwOwogIHQuYXJyb3dkYXNocmlnaHQgPSAweDIxZTI7CiAgdC5hcnJvd2Rhc2h1cCA9IDB4MjFlMTsKICB0LmFycm93ZGJsYm90aCA9IDB4MjFkNDsKICB0LmFycm93ZGJsZG93biA9IDB4MjFkMzsKICB0LmFycm93ZGJsbGVmdCA9IDB4MjFkMDsKICB0LmFycm93ZGJscmlnaHQgPSAweDIxZDI7CiAgdC5hcnJvd2RibHVwID0gMHgyMWQxOwogIHQuYXJyb3dkb3duID0gMHgyMTkzOwogIHQuYXJyb3dkb3dubGVmdCA9IDB4MjE5OTsKICB0LmFycm93ZG93bnJpZ2h0ID0gMHgyMTk4OwogIHQuYXJyb3dkb3dud2hpdGUgPSAweDIxZTk7CiAgdC5hcnJvd2hlYWRkb3dubW9kID0gMHgwMmM1OwogIHQuYXJyb3doZWFkbGVmdG1vZCA9IDB4MDJjMjsKICB0LmFycm93aGVhZHJpZ2h0bW9kID0gMHgwMmMzOwogIHQuYXJyb3doZWFkdXBtb2QgPSAweDAyYzQ7CiAgdC5hcnJvd2hvcml6ZXggPSAweGY4ZTc7CiAgdC5hcnJvd2xlZnQgPSAweDIxOTA7CiAgdC5hcnJvd2xlZnRkYmwgPSAweDIxZDA7CiAgdC5hcnJvd2xlZnRkYmxzdHJva2UgPSAweDIxY2Q7CiAgdC5hcnJvd2xlZnRvdmVycmlnaHQgPSAweDIxYzY7CiAgdC5hcnJvd2xlZnR3aGl0ZSA9IDB4MjFlNjsKICB0LmFycm93cmlnaHQgPSAweDIxOTI7CiAgdC5hcnJvd3JpZ2h0ZGJsc3Ryb2tlID0gMHgyMWNmOwogIHQuYXJyb3dyaWdodGhlYXZ5ID0gMHgyNzllOwogIHQuYXJyb3dyaWdodG92ZXJsZWZ0ID0gMHgyMWM0OwogIHQuYXJyb3dyaWdodHdoaXRlID0gMHgyMWU4OwogIHQuYXJyb3d0YWJsZWZ0ID0gMHgyMWU0OwogIHQuYXJyb3d0YWJyaWdodCA9IDB4MjFlNTsKICB0LmFycm93dXAgPSAweDIxOTE7CiAgdC5hcnJvd3VwZG4gPSAweDIxOTU7CiAgdC5hcnJvd3VwZG5ic2UgPSAweDIxYTg7CiAgdC5hcnJvd3VwZG93bmJhc2UgPSAweDIxYTg7CiAgdC5hcnJvd3VwbGVmdCA9IDB4MjE5NjsKICB0LmFycm93dXBsZWZ0b2Zkb3duID0gMHgyMWM1OwogIHQuYXJyb3d1cHJpZ2h0ID0gMHgyMTk3OwogIHQuYXJyb3d1cHdoaXRlID0gMHgyMWU3OwogIHQuYXJyb3d2ZXJ0ZXggPSAweGY4ZTY7CiAgdC5hc2NpaWNpcmN1bSA9IDB4MDA1ZTsKICB0LmFzY2lpY2lyY3VtbW9ub3NwYWNlID0gMHhmZjNlOwogIHQuYXNjaWl0aWxkZSA9IDB4MDA3ZTsKICB0LmFzY2lpdGlsZGVtb25vc3BhY2UgPSAweGZmNWU7CiAgdC5hc2NyaXB0ID0gMHgwMjUxOwogIHQuYXNjcmlwdHR1cm5lZCA9IDB4MDI1MjsKICB0LmFzbWFsbGhpcmFnYW5hID0gMHgzMDQxOwogIHQuYXNtYWxsa2F0YWthbmEgPSAweDMwYTE7CiAgdC5hc21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2NzsKICB0LmFzdGVyaXNrID0gMHgwMDJhOwogIHQuYXN0ZXJpc2thbHRvbmVhcmFiaWMgPSAweDA2NmQ7CiAgdC5hc3Rlcmlza2FyYWJpYyA9IDB4MDY2ZDsKICB0LmFzdGVyaXNrbWF0aCA9IDB4MjIxNzsKICB0LmFzdGVyaXNrbW9ub3NwYWNlID0gMHhmZjBhOwogIHQuYXN0ZXJpc2tzbWFsbCA9IDB4ZmU2MTsKICB0LmFzdGVyaXNtID0gMHgyMDQyOwogIHQuYXN1cGVyaW9yID0gMHhmNmU5OwogIHQuYXN5bXB0b3RpY2FsbHllcXVhbCA9IDB4MjI0MzsKICB0LmF0ID0gMHgwMDQwOwogIHQuYXRpbGRlID0gMHgwMGUzOwogIHQuYXRtb25vc3BhY2UgPSAweGZmMjA7CiAgdC5hdHNtYWxsID0gMHhmZTZiOwogIHQuYXR1cm5lZCA9IDB4MDI1MDsKICB0LmF1YmVuZ2FsaSA9IDB4MDk5NDsKICB0LmF1Ym9wb21vZm8gPSAweDMxMjA7CiAgdC5hdWRldmEgPSAweDA5MTQ7CiAgdC5hdWd1amFyYXRpID0gMHgwYTk0OwogIHQuYXVndXJtdWtoaSA9IDB4MGExNDsKICB0LmF1bGVuZ3RobWFya2JlbmdhbGkgPSAweDA5ZDc7CiAgdC5hdW1hdHJhZ3VybXVraGkgPSAweDBhNGM7CiAgdC5hdXZvd2Vsc2lnbmJlbmdhbGkgPSAweDA5Y2M7CiAgdC5hdXZvd2Vsc2lnbmRldmEgPSAweDA5NGM7CiAgdC5hdXZvd2Vsc2lnbmd1amFyYXRpID0gMHgwYWNjOwogIHQuYXZhZ3JhaGFkZXZhID0gMHgwOTNkOwogIHQuYXliYXJtZW5pYW4gPSAweDA1NjE7CiAgdC5heWluID0gMHgwNWUyOwogIHQuYXlpbmFsdG9uZWhlYnJldyA9IDB4ZmIyMDsKICB0LmF5aW5oZWJyZXcgPSAweDA1ZTI7CiAgdC5iID0gMHgwMDYyOwogIHQuYmFiZW5nYWxpID0gMHgwOWFjOwogIHQuYmFja3NsYXNoID0gMHgwMDVjOwogIHQuYmFja3NsYXNobW9ub3NwYWNlID0gMHhmZjNjOwogIHQuYmFkZXZhID0gMHgwOTJjOwogIHQuYmFndWphcmF0aSA9IDB4MGFhYzsKICB0LmJhZ3VybXVraGkgPSAweDBhMmM7CiAgdC5iYWhpcmFnYW5hID0gMHgzMDcwOwogIHQuYmFodHRoYWkgPSAweDBlM2Y7CiAgdC5iYWthdGFrYW5hID0gMHgzMGQwOwogIHQuYmFyID0gMHgwMDdjOwogIHQuYmFybW9ub3NwYWNlID0gMHhmZjVjOwogIHQuYmJvcG9tb2ZvID0gMHgzMTA1OwogIHQuYmNpcmNsZSA9IDB4MjRkMTsKICB0LmJkb3RhY2NlbnQgPSAweDFlMDM7CiAgdC5iZG90YmVsb3cgPSAweDFlMDU7CiAgdC5iZWFtZWRzaXh0ZWVudGhub3RlcyA9IDB4MjY2YzsKICB0LmJlY2F1c2UgPSAweDIyMzU7CiAgdC5iZWN5cmlsbGljID0gMHgwNDMxOwogIHQuYmVoYXJhYmljID0gMHgwNjI4OwogIHQuYmVoZmluYWxhcmFiaWMgPSAweGZlOTA7CiAgdC5iZWhpbml0aWFsYXJhYmljID0gMHhmZTkxOwogIHQuYmVoaXJhZ2FuYSA9IDB4MzA3OTsKICB0LmJlaG1lZGlhbGFyYWJpYyA9IDB4ZmU5MjsKICB0LmJlaG1lZW1pbml0aWFsYXJhYmljID0gMHhmYzlmOwogIHQuYmVobWVlbWlzb2xhdGVkYXJhYmljID0gMHhmYzA4OwogIHQuYmVobm9vbmZpbmFsYXJhYmljID0gMHhmYzZkOwogIHQuYmVrYXRha2FuYSA9IDB4MzBkOTsKICB0LmJlbmFybWVuaWFuID0gMHgwNTYyOwogIHQuYmV0ID0gMHgwNWQxOwogIHQuYmV0YSA9IDB4MDNiMjsKICB0LmJldGFzeW1ib2xncmVlayA9IDB4MDNkMDsKICB0LmJldGRhZ2VzaCA9IDB4ZmIzMTsKICB0LmJldGRhZ2VzaGhlYnJldyA9IDB4ZmIzMTsKICB0LmJldGhlYnJldyA9IDB4MDVkMTsKICB0LmJldHJhZmVoZWJyZXcgPSAweGZiNGM7CiAgdC5iaGFiZW5nYWxpID0gMHgwOWFkOwogIHQuYmhhZGV2YSA9IDB4MDkyZDsKICB0LmJoYWd1amFyYXRpID0gMHgwYWFkOwogIHQuYmhhZ3VybXVraGkgPSAweDBhMmQ7CiAgdC5iaG9vayA9IDB4MDI1MzsKICB0LmJpaGlyYWdhbmEgPSAweDMwNzM7CiAgdC5iaWthdGFrYW5hID0gMHgzMGQzOwogIHQuYmlsYWJpYWxjbGljayA9IDB4MDI5ODsKICB0LmJpbmRpZ3VybXVraGkgPSAweDBhMDI7CiAgdC5iaXJ1c3F1YXJlID0gMHgzMzMxOwogIHQuYmxhY2tjaXJjbGUgPSAweDI1Y2Y7CiAgdC5ibGFja2RpYW1vbmQgPSAweDI1YzY7CiAgdC5ibGFja2Rvd25wb2ludGluZ3RyaWFuZ2xlID0gMHgyNWJjOwogIHQuYmxhY2tsZWZ0cG9pbnRpbmdwb2ludGVyID0gMHgyNWM0OwogIHQuYmxhY2tsZWZ0cG9pbnRpbmd0cmlhbmdsZSA9IDB4MjVjMDsKICB0LmJsYWNrbGVudGljdWxhcmJyYWNrZXRsZWZ0ID0gMHgzMDEwOwogIHQuYmxhY2tsZW50aWN1bGFyYnJhY2tldGxlZnR2ZXJ0aWNhbCA9IDB4ZmUzYjsKICB0LmJsYWNrbGVudGljdWxhcmJyYWNrZXRyaWdodCA9IDB4MzAxMTsKICB0LmJsYWNrbGVudGljdWxhcmJyYWNrZXRyaWdodHZlcnRpY2FsID0gMHhmZTNjOwogIHQuYmxhY2tsb3dlcmxlZnR0cmlhbmdsZSA9IDB4MjVlMzsKICB0LmJsYWNrbG93ZXJyaWdodHRyaWFuZ2xlID0gMHgyNWUyOwogIHQuYmxhY2tyZWN0YW5nbGUgPSAweDI1YWM7CiAgdC5ibGFja3JpZ2h0cG9pbnRpbmdwb2ludGVyID0gMHgyNWJhOwogIHQuYmxhY2tyaWdodHBvaW50aW5ndHJpYW5nbGUgPSAweDI1YjY7CiAgdC5ibGFja3NtYWxsc3F1YXJlID0gMHgyNWFhOwogIHQuYmxhY2tzbWlsaW5nZmFjZSA9IDB4MjYzYjsKICB0LmJsYWNrc3F1YXJlID0gMHgyNWEwOwogIHQuYmxhY2tzdGFyID0gMHgyNjA1OwogIHQuYmxhY2t1cHBlcmxlZnR0cmlhbmdsZSA9IDB4MjVlNDsKICB0LmJsYWNrdXBwZXJyaWdodHRyaWFuZ2xlID0gMHgyNWU1OwogIHQuYmxhY2t1cHBvaW50aW5nc21hbGx0cmlhbmdsZSA9IDB4MjViNDsKICB0LmJsYWNrdXBwb2ludGluZ3RyaWFuZ2xlID0gMHgyNWIyOwogIHQuYmxhbmsgPSAweDI0MjM7CiAgdC5ibGluZWJlbG93ID0gMHgxZTA3OwogIHQuYmxvY2sgPSAweDI1ODg7CiAgdC5ibW9ub3NwYWNlID0gMHhmZjQyOwogIHQuYm9iYWltYWl0aGFpID0gMHgwZTFhOwogIHQuYm9oaXJhZ2FuYSA9IDB4MzA3YzsKICB0LmJva2F0YWthbmEgPSAweDMwZGM7CiAgdC5icGFyZW4gPSAweDI0OWQ7CiAgdC5icXNxdWFyZSA9IDB4MzNjMzsKICB0LmJyYWNlZXggPSAweGY4ZjQ7CiAgdC5icmFjZWxlZnQgPSAweDAwN2I7CiAgdC5icmFjZWxlZnRidCA9IDB4ZjhmMzsKICB0LmJyYWNlbGVmdG1pZCA9IDB4ZjhmMjsKICB0LmJyYWNlbGVmdG1vbm9zcGFjZSA9IDB4ZmY1YjsKICB0LmJyYWNlbGVmdHNtYWxsID0gMHhmZTViOwogIHQuYnJhY2VsZWZ0dHAgPSAweGY4ZjE7CiAgdC5icmFjZWxlZnR2ZXJ0aWNhbCA9IDB4ZmUzNzsKICB0LmJyYWNlcmlnaHQgPSAweDAwN2Q7CiAgdC5icmFjZXJpZ2h0YnQgPSAweGY4ZmU7CiAgdC5icmFjZXJpZ2h0bWlkID0gMHhmOGZkOwogIHQuYnJhY2VyaWdodG1vbm9zcGFjZSA9IDB4ZmY1ZDsKICB0LmJyYWNlcmlnaHRzbWFsbCA9IDB4ZmU1YzsKICB0LmJyYWNlcmlnaHR0cCA9IDB4ZjhmYzsKICB0LmJyYWNlcmlnaHR2ZXJ0aWNhbCA9IDB4ZmUzODsKICB0LmJyYWNrZXRsZWZ0ID0gMHgwMDViOwogIHQuYnJhY2tldGxlZnRidCA9IDB4ZjhmMDsKICB0LmJyYWNrZXRsZWZ0ZXggPSAweGY4ZWY7CiAgdC5icmFja2V0bGVmdG1vbm9zcGFjZSA9IDB4ZmYzYjsKICB0LmJyYWNrZXRsZWZ0dHAgPSAweGY4ZWU7CiAgdC5icmFja2V0cmlnaHQgPSAweDAwNWQ7CiAgdC5icmFja2V0cmlnaHRidCA9IDB4ZjhmYjsKICB0LmJyYWNrZXRyaWdodGV4ID0gMHhmOGZhOwogIHQuYnJhY2tldHJpZ2h0bW9ub3NwYWNlID0gMHhmZjNkOwogIHQuYnJhY2tldHJpZ2h0dHAgPSAweGY4Zjk7CiAgdC5icmV2ZSA9IDB4MDJkODsKICB0LmJyZXZlYmVsb3djbWIgPSAweDAzMmU7CiAgdC5icmV2ZWNtYiA9IDB4MDMwNjsKICB0LmJyZXZlaW52ZXJ0ZWRiZWxvd2NtYiA9IDB4MDMyZjsKICB0LmJyZXZlaW52ZXJ0ZWRjbWIgPSAweDAzMTE7CiAgdC5icmV2ZWludmVydGVkZG91YmxlY21iID0gMHgwMzYxOwogIHQuYnJpZGdlYmVsb3djbWIgPSAweDAzMmE7CiAgdC5icmlkZ2VpbnZlcnRlZGJlbG93Y21iID0gMHgwMzNhOwogIHQuYnJva2VuYmFyID0gMHgwMGE2OwogIHQuYnN0cm9rZSA9IDB4MDE4MDsKICB0LmJzdXBlcmlvciA9IDB4ZjZlYTsKICB0LmJ0b3BiYXIgPSAweDAxODM7CiAgdC5idWhpcmFnYW5hID0gMHgzMDc2OwogIHQuYnVrYXRha2FuYSA9IDB4MzBkNjsKICB0LmJ1bGxldCA9IDB4MjAyMjsKICB0LmJ1bGxldGludmVyc2UgPSAweDI1ZDg7CiAgdC5idWxsZXRvcGVyYXRvciA9IDB4MjIxOTsKICB0LmJ1bGxzZXllID0gMHgyNWNlOwogIHQuYyA9IDB4MDA2MzsKICB0LmNhYXJtZW5pYW4gPSAweDA1NmU7CiAgdC5jYWJlbmdhbGkgPSAweDA5OWE7CiAgdC5jYWN1dGUgPSAweDAxMDc7CiAgdC5jYWRldmEgPSAweDA5MWE7CiAgdC5jYWd1amFyYXRpID0gMHgwYTlhOwogIHQuY2FndXJtdWtoaSA9IDB4MGExYTsKICB0LmNhbHNxdWFyZSA9IDB4MzM4ODsKICB0LmNhbmRyYWJpbmR1YmVuZ2FsaSA9IDB4MDk4MTsKICB0LmNhbmRyYWJpbmR1Y21iID0gMHgwMzEwOwogIHQuY2FuZHJhYmluZHVkZXZhID0gMHgwOTAxOwogIHQuY2FuZHJhYmluZHVndWphcmF0aSA9IDB4MGE4MTsKICB0LmNhcHNsb2NrID0gMHgyMWVhOwogIHQuY2FyZW9mID0gMHgyMTA1OwogIHQuY2Fyb24gPSAweDAyYzc7CiAgdC5jYXJvbmJlbG93Y21iID0gMHgwMzJjOwogIHQuY2Fyb25jbWIgPSAweDAzMGM7CiAgdC5jYXJyaWFnZXJldHVybiA9IDB4MjFiNTsKICB0LmNib3BvbW9mbyA9IDB4MzExODsKICB0LmNjYXJvbiA9IDB4MDEwZDsKICB0LmNjZWRpbGxhID0gMHgwMGU3OwogIHQuY2NlZGlsbGFhY3V0ZSA9IDB4MWUwOTsKICB0LmNjaXJjbGUgPSAweDI0ZDI7CiAgdC5jY2lyY3VtZmxleCA9IDB4MDEwOTsKICB0LmNjdXJsID0gMHgwMjU1OwogIHQuY2RvdCA9IDB4MDEwYjsKICB0LmNkb3RhY2NlbnQgPSAweDAxMGI7CiAgdC5jZHNxdWFyZSA9IDB4MzNjNTsKICB0LmNlZGlsbGEgPSAweDAwYjg7CiAgdC5jZWRpbGxhY21iID0gMHgwMzI3OwogIHQuY2VudCA9IDB4MDBhMjsKICB0LmNlbnRpZ3JhZGUgPSAweDIxMDM7CiAgdC5jZW50aW5mZXJpb3IgPSAweGY2ZGY7CiAgdC5jZW50bW9ub3NwYWNlID0gMHhmZmUwOwogIHQuY2VudG9sZHN0eWxlID0gMHhmN2EyOwogIHQuY2VudHN1cGVyaW9yID0gMHhmNmUwOwogIHQuY2hhYXJtZW5pYW4gPSAweDA1Nzk7CiAgdC5jaGFiZW5nYWxpID0gMHgwOTliOwogIHQuY2hhZGV2YSA9IDB4MDkxYjsKICB0LmNoYWd1amFyYXRpID0gMHgwYTliOwogIHQuY2hhZ3VybXVraGkgPSAweDBhMWI7CiAgdC5jaGJvcG9tb2ZvID0gMHgzMTE0OwogIHQuY2hlYWJraGFzaWFuY3lyaWxsaWMgPSAweDA0YmQ7CiAgdC5jaGVja21hcmsgPSAweDI3MTM7CiAgdC5jaGVjeXJpbGxpYyA9IDB4MDQ0NzsKICB0LmNoZWRlc2NlbmRlcmFia2hhc2lhbmN5cmlsbGljID0gMHgwNGJmOwogIHQuY2hlZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0Yjc7CiAgdC5jaGVkaWVyZXNpc2N5cmlsbGljID0gMHgwNGY1OwogIHQuY2hlaGFybWVuaWFuID0gMHgwNTczOwogIHQuY2hla2hha2Fzc2lhbmN5cmlsbGljID0gMHgwNGNjOwogIHQuY2hldmVydGljYWxzdHJva2VjeXJpbGxpYyA9IDB4MDRiOTsKICB0LmNoaSA9IDB4MDNjNzsKICB0LmNoaWV1Y2hhY2lyY2xla29yZWFuID0gMHgzMjc3OwogIHQuY2hpZXVjaGFwYXJlbmtvcmVhbiA9IDB4MzIxNzsKICB0LmNoaWV1Y2hjaXJjbGVrb3JlYW4gPSAweDMyNjk7CiAgdC5jaGlldWNoa29yZWFuID0gMHgzMTRhOwogIHQuY2hpZXVjaHBhcmVua29yZWFuID0gMHgzMjA5OwogIHQuY2hvY2hhbmd0aGFpID0gMHgwZTBhOwogIHQuY2hvY2hhbnRoYWkgPSAweDBlMDg7CiAgdC5jaG9jaGluZ3RoYWkgPSAweDBlMDk7CiAgdC5jaG9jaG9ldGhhaSA9IDB4MGUwYzsKICB0LmNob29rID0gMHgwMTg4OwogIHQuY2lldWNhY2lyY2xla29yZWFuID0gMHgzMjc2OwogIHQuY2lldWNhcGFyZW5rb3JlYW4gPSAweDMyMTY7CiAgdC5jaWV1Y2NpcmNsZWtvcmVhbiA9IDB4MzI2ODsKICB0LmNpZXVja29yZWFuID0gMHgzMTQ4OwogIHQuY2lldWNwYXJlbmtvcmVhbiA9IDB4MzIwODsKICB0LmNpZXVjdXBhcmVua29yZWFuID0gMHgzMjFjOwogIHQuY2lyY2xlID0gMHgyNWNiOwogIHQuY2lyY2xlY29weXJ0ID0gMHgwMGE5OwogIHQuY2lyY2xlbXVsdGlwbHkgPSAweDIyOTc7CiAgdC5jaXJjbGVvdCA9IDB4MjI5OTsKICB0LmNpcmNsZXBsdXMgPSAweDIyOTU7CiAgdC5jaXJjbGVwb3N0YWxtYXJrID0gMHgzMDM2OwogIHQuY2lyY2xld2l0aGxlZnRoYWxmYmxhY2sgPSAweDI1ZDA7CiAgdC5jaXJjbGV3aXRocmlnaHRoYWxmYmxhY2sgPSAweDI1ZDE7CiAgdC5jaXJjdW1mbGV4ID0gMHgwMmM2OwogIHQuY2lyY3VtZmxleGJlbG93Y21iID0gMHgwMzJkOwogIHQuY2lyY3VtZmxleGNtYiA9IDB4MDMwMjsKICB0LmNsZWFyID0gMHgyMzI3OwogIHQuY2xpY2thbHZlb2xhciA9IDB4MDFjMjsKICB0LmNsaWNrZGVudGFsID0gMHgwMWMwOwogIHQuY2xpY2tsYXRlcmFsID0gMHgwMWMxOwogIHQuY2xpY2tyZXRyb2ZsZXggPSAweDAxYzM7CiAgdC5jbHViID0gMHgyNjYzOwogIHQuY2x1YnN1aXRibGFjayA9IDB4MjY2MzsKICB0LmNsdWJzdWl0d2hpdGUgPSAweDI2Njc7CiAgdC5jbWN1YmVkc3F1YXJlID0gMHgzM2E0OwogIHQuY21vbm9zcGFjZSA9IDB4ZmY0MzsKICB0LmNtc3F1YXJlZHNxdWFyZSA9IDB4MzNhMDsKICB0LmNvYXJtZW5pYW4gPSAweDA1ODE7CiAgdC5jb2xvbiA9IDB4MDAzYTsKICB0LmNvbG9ubW9uZXRhcnkgPSAweDIwYTE7CiAgdC5jb2xvbm1vbm9zcGFjZSA9IDB4ZmYxYTsKICB0LmNvbG9uc2lnbiA9IDB4MjBhMTsKICB0LmNvbG9uc21hbGwgPSAweGZlNTU7CiAgdC5jb2xvbnRyaWFuZ3VsYXJoYWxmbW9kID0gMHgwMmQxOwogIHQuY29sb250cmlhbmd1bGFybW9kID0gMHgwMmQwOwogIHQuY29tbWEgPSAweDAwMmM7CiAgdC5jb21tYWFib3ZlY21iID0gMHgwMzEzOwogIHQuY29tbWFhYm92ZXJpZ2h0Y21iID0gMHgwMzE1OwogIHQuY29tbWFhY2NlbnQgPSAweGY2YzM7CiAgdC5jb21tYWFyYWJpYyA9IDB4MDYwYzsKICB0LmNvbW1hYXJtZW5pYW4gPSAweDA1NWQ7CiAgdC5jb21tYWluZmVyaW9yID0gMHhmNmUxOwogIHQuY29tbWFtb25vc3BhY2UgPSAweGZmMGM7CiAgdC5jb21tYXJldmVyc2VkYWJvdmVjbWIgPSAweDAzMTQ7CiAgdC5jb21tYXJldmVyc2VkbW9kID0gMHgwMmJkOwogIHQuY29tbWFzbWFsbCA9IDB4ZmU1MDsKICB0LmNvbW1hc3VwZXJpb3IgPSAweGY2ZTI7CiAgdC5jb21tYXR1cm5lZGFib3ZlY21iID0gMHgwMzEyOwogIHQuY29tbWF0dXJuZWRtb2QgPSAweDAyYmI7CiAgdC5jb21wYXNzID0gMHgyNjNjOwogIHQuY29uZ3J1ZW50ID0gMHgyMjQ1OwogIHQuY29udG91cmludGVncmFsID0gMHgyMjJlOwogIHQuY29udHJvbCA9IDB4MjMwMzsKICB0LmNvbnRyb2xBQ0sgPSAweDAwMDY7CiAgdC5jb250cm9sQkVMID0gMHgwMDA3OwogIHQuY29udHJvbEJTID0gMHgwMDA4OwogIHQuY29udHJvbENBTiA9IDB4MDAxODsKICB0LmNvbnRyb2xDUiA9IDB4MDAwZDsKICB0LmNvbnRyb2xEQzEgPSAweDAwMTE7CiAgdC5jb250cm9sREMyID0gMHgwMDEyOwogIHQuY29udHJvbERDMyA9IDB4MDAxMzsKICB0LmNvbnRyb2xEQzQgPSAweDAwMTQ7CiAgdC5jb250cm9sREVMID0gMHgwMDdmOwogIHQuY29udHJvbERMRSA9IDB4MDAxMDsKICB0LmNvbnRyb2xFTSA9IDB4MDAxOTsKICB0LmNvbnRyb2xFTlEgPSAweDAwMDU7CiAgdC5jb250cm9sRU9UID0gMHgwMDA0OwogIHQuY29udHJvbEVTQyA9IDB4MDAxYjsKICB0LmNvbnRyb2xFVEIgPSAweDAwMTc7CiAgdC5jb250cm9sRVRYID0gMHgwMDAzOwogIHQuY29udHJvbEZGID0gMHgwMDBjOwogIHQuY29udHJvbEZTID0gMHgwMDFjOwogIHQuY29udHJvbEdTID0gMHgwMDFkOwogIHQuY29udHJvbEhUID0gMHgwMDA5OwogIHQuY29udHJvbExGID0gMHgwMDBhOwogIHQuY29udHJvbE5BSyA9IDB4MDAxNTsKICB0LmNvbnRyb2xOVUxMID0gMHgwMDAwOwogIHQuY29udHJvbFJTID0gMHgwMDFlOwogIHQuY29udHJvbFNJID0gMHgwMDBmOwogIHQuY29udHJvbFNPID0gMHgwMDBlOwogIHQuY29udHJvbFNPVCA9IDB4MDAwMjsKICB0LmNvbnRyb2xTVFggPSAweDAwMDE7CiAgdC5jb250cm9sU1VCID0gMHgwMDFhOwogIHQuY29udHJvbFNZTiA9IDB4MDAxNjsKICB0LmNvbnRyb2xVUyA9IDB4MDAxZjsKICB0LmNvbnRyb2xWVCA9IDB4MDAwYjsKICB0LmNvcHlyaWdodCA9IDB4MDBhOTsKICB0LmNvcHlyaWdodHNhbnMgPSAweGY4ZTk7CiAgdC5jb3B5cmlnaHRzZXJpZiA9IDB4ZjZkOTsKICB0LmNvcm5lcmJyYWNrZXRsZWZ0ID0gMHgzMDBjOwogIHQuY29ybmVyYnJhY2tldGxlZnRoYWxmd2lkdGggPSAweGZmNjI7CiAgdC5jb3JuZXJicmFja2V0bGVmdHZlcnRpY2FsID0gMHhmZTQxOwogIHQuY29ybmVyYnJhY2tldHJpZ2h0ID0gMHgzMDBkOwogIHQuY29ybmVyYnJhY2tldHJpZ2h0aGFsZndpZHRoID0gMHhmZjYzOwogIHQuY29ybmVyYnJhY2tldHJpZ2h0dmVydGljYWwgPSAweGZlNDI7CiAgdC5jb3Jwb3JhdGlvbnNxdWFyZSA9IDB4MzM3ZjsKICB0LmNvc3F1YXJlID0gMHgzM2M3OwogIHQuY292ZXJrZ3NxdWFyZSA9IDB4MzNjNjsKICB0LmNwYXJlbiA9IDB4MjQ5ZTsKICB0LmNydXplaXJvID0gMHgyMGEyOwogIHQuY3N0cmV0Y2hlZCA9IDB4MDI5NzsKICB0LmN1cmx5YW5kID0gMHgyMmNmOwogIHQuY3VybHlvciA9IDB4MjJjZTsKICB0LmN1cnJlbmN5ID0gMHgwMGE0OwogIHQuY3lyQnJldmUgPSAweGY2ZDE7CiAgdC5jeXJGbGV4ID0gMHhmNmQyOwogIHQuY3lyYnJldmUgPSAweGY2ZDQ7CiAgdC5jeXJmbGV4ID0gMHhmNmQ1OwogIHQuZCA9IDB4MDA2NDsKICB0LmRhYXJtZW5pYW4gPSAweDA1NjQ7CiAgdC5kYWJlbmdhbGkgPSAweDA5YTY7CiAgdC5kYWRhcmFiaWMgPSAweDA2MzY7CiAgdC5kYWRldmEgPSAweDA5MjY7CiAgdC5kYWRmaW5hbGFyYWJpYyA9IDB4ZmViZTsKICB0LmRhZGluaXRpYWxhcmFiaWMgPSAweGZlYmY7CiAgdC5kYWRtZWRpYWxhcmFiaWMgPSAweGZlYzA7CiAgdC5kYWdlc2ggPSAweDA1YmM7CiAgdC5kYWdlc2hoZWJyZXcgPSAweDA1YmM7CiAgdC5kYWdnZXIgPSAweDIwMjA7CiAgdC5kYWdnZXJkYmwgPSAweDIwMjE7CiAgdC5kYWd1amFyYXRpID0gMHgwYWE2OwogIHQuZGFndXJtdWtoaSA9IDB4MGEyNjsKICB0LmRhaGlyYWdhbmEgPSAweDMwNjA7CiAgdC5kYWthdGFrYW5hID0gMHgzMGMwOwogIHQuZGFsYXJhYmljID0gMHgwNjJmOwogIHQuZGFsZXQgPSAweDA1ZDM7CiAgdC5kYWxldGRhZ2VzaCA9IDB4ZmIzMzsKICB0LmRhbGV0ZGFnZXNoaGVicmV3ID0gMHhmYjMzOwogIHQuZGFsZXRoZWJyZXcgPSAweDA1ZDM7CiAgdC5kYWxmaW5hbGFyYWJpYyA9IDB4ZmVhYTsKICB0LmRhbW1hYXJhYmljID0gMHgwNjRmOwogIHQuZGFtbWFsb3dhcmFiaWMgPSAweDA2NGY7CiAgdC5kYW1tYXRhbmFsdG9uZWFyYWJpYyA9IDB4MDY0YzsKICB0LmRhbW1hdGFuYXJhYmljID0gMHgwNjRjOwogIHQuZGFuZGEgPSAweDA5NjQ7CiAgdC5kYXJnYWhlYnJldyA9IDB4MDVhNzsKICB0LmRhcmdhbGVmdGhlYnJldyA9IDB4MDVhNzsKICB0LmRhc2lhcG5ldW1hdGFjeXJpbGxpY2NtYiA9IDB4MDQ4NTsKICB0LmRibEdyYXZlID0gMHhmNmQzOwogIHQuZGJsYW5nbGVicmFja2V0bGVmdCA9IDB4MzAwYTsKICB0LmRibGFuZ2xlYnJhY2tldGxlZnR2ZXJ0aWNhbCA9IDB4ZmUzZDsKICB0LmRibGFuZ2xlYnJhY2tldHJpZ2h0ID0gMHgzMDBiOwogIHQuZGJsYW5nbGVicmFja2V0cmlnaHR2ZXJ0aWNhbCA9IDB4ZmUzZTsKICB0LmRibGFyY2hpbnZlcnRlZGJlbG93Y21iID0gMHgwMzJiOwogIHQuZGJsYXJyb3dsZWZ0ID0gMHgyMWQ0OwogIHQuZGJsYXJyb3dyaWdodCA9IDB4MjFkMjsKICB0LmRibGRhbmRhID0gMHgwOTY1OwogIHQuZGJsZ3JhdmUgPSAweGY2ZDY7CiAgdC5kYmxncmF2ZWNtYiA9IDB4MDMwZjsKICB0LmRibGludGVncmFsID0gMHgyMjJjOwogIHQuZGJsbG93bGluZSA9IDB4MjAxNzsKICB0LmRibGxvd2xpbmVjbWIgPSAweDAzMzM7CiAgdC5kYmxvdmVybGluZWNtYiA9IDB4MDMzZjsKICB0LmRibHByaW1lbW9kID0gMHgwMmJhOwogIHQuZGJsdmVydGljYWxiYXIgPSAweDIwMTY7CiAgdC5kYmx2ZXJ0aWNhbGxpbmVhYm92ZWNtYiA9IDB4MDMwZTsKICB0LmRib3BvbW9mbyA9IDB4MzEwOTsKICB0LmRic3F1YXJlID0gMHgzM2M4OwogIHQuZGNhcm9uID0gMHgwMTBmOwogIHQuZGNlZGlsbGEgPSAweDFlMTE7CiAgdC5kY2lyY2xlID0gMHgyNGQzOwogIHQuZGNpcmN1bWZsZXhiZWxvdyA9IDB4MWUxMzsKICB0LmRjcm9hdCA9IDB4MDExMTsKICB0LmRkYWJlbmdhbGkgPSAweDA5YTE7CiAgdC5kZGFkZXZhID0gMHgwOTIxOwogIHQuZGRhZ3VqYXJhdGkgPSAweDBhYTE7CiAgdC5kZGFndXJtdWtoaSA9IDB4MGEyMTsKICB0LmRkYWxhcmFiaWMgPSAweDA2ODg7CiAgdC5kZGFsZmluYWxhcmFiaWMgPSAweGZiODk7CiAgdC5kZGRoYWRldmEgPSAweDA5NWM7CiAgdC5kZGhhYmVuZ2FsaSA9IDB4MDlhMjsKICB0LmRkaGFkZXZhID0gMHgwOTIyOwogIHQuZGRoYWd1amFyYXRpID0gMHgwYWEyOwogIHQuZGRoYWd1cm11a2hpID0gMHgwYTIyOwogIHQuZGRvdGFjY2VudCA9IDB4MWUwYjsKICB0LmRkb3RiZWxvdyA9IDB4MWUwZDsKICB0LmRlY2ltYWxzZXBhcmF0b3JhcmFiaWMgPSAweDA2NmI7CiAgdC5kZWNpbWFsc2VwYXJhdG9ycGVyc2lhbiA9IDB4MDY2YjsKICB0LmRlY3lyaWxsaWMgPSAweDA0MzQ7CiAgdC5kZWdyZWUgPSAweDAwYjA7CiAgdC5kZWhpaGVicmV3ID0gMHgwNWFkOwogIHQuZGVoaXJhZ2FuYSA9IDB4MzA2NzsKICB0LmRlaWNvcHRpYyA9IDB4MDNlZjsKICB0LmRla2F0YWthbmEgPSAweDMwYzc7CiAgdC5kZWxldGVsZWZ0ID0gMHgyMzJiOwogIHQuZGVsZXRlcmlnaHQgPSAweDIzMjY7CiAgdC5kZWx0YSA9IDB4MDNiNDsKICB0LmRlbHRhdHVybmVkID0gMHgwMThkOwogIHQuZGVub21pbmF0b3JtaW51c29uZW51bWVyYXRvcmJlbmdhbGkgPSAweDA5Zjg7CiAgdC5kZXpoID0gMHgwMmE0OwogIHQuZGhhYmVuZ2FsaSA9IDB4MDlhNzsKICB0LmRoYWRldmEgPSAweDA5Mjc7CiAgdC5kaGFndWphcmF0aSA9IDB4MGFhNzsKICB0LmRoYWd1cm11a2hpID0gMHgwYTI3OwogIHQuZGhvb2sgPSAweDAyNTc7CiAgdC5kaWFseXRpa2F0b25vcyA9IDB4MDM4NTsKICB0LmRpYWx5dGlrYXRvbm9zY21iID0gMHgwMzQ0OwogIHQuZGlhbW9uZCA9IDB4MjY2NjsKICB0LmRpYW1vbmRzdWl0d2hpdGUgPSAweDI2NjI7CiAgdC5kaWVyZXNpcyA9IDB4MDBhODsKICB0LmRpZXJlc2lzYWN1dGUgPSAweGY2ZDc7CiAgdC5kaWVyZXNpc2JlbG93Y21iID0gMHgwMzI0OwogIHQuZGllcmVzaXNjbWIgPSAweDAzMDg7CiAgdC5kaWVyZXNpc2dyYXZlID0gMHhmNmQ4OwogIHQuZGllcmVzaXN0b25vcyA9IDB4MDM4NTsKICB0LmRpaGlyYWdhbmEgPSAweDMwNjI7CiAgdC5kaWthdGFrYW5hID0gMHgzMGMyOwogIHQuZGl0dG9tYXJrID0gMHgzMDAzOwogIHQuZGl2aWRlID0gMHgwMGY3OwogIHQuZGl2aWRlcyA9IDB4MjIyMzsKICB0LmRpdmlzaW9uc2xhc2ggPSAweDIyMTU7CiAgdC5kamVjeXJpbGxpYyA9IDB4MDQ1MjsKICB0LmRrc2hhZGUgPSAweDI1OTM7CiAgdC5kbGluZWJlbG93ID0gMHgxZTBmOwogIHQuZGxzcXVhcmUgPSAweDMzOTc7CiAgdC5kbWFjcm9uID0gMHgwMTExOwogIHQuZG1vbm9zcGFjZSA9IDB4ZmY0NDsKICB0LmRuYmxvY2sgPSAweDI1ODQ7CiAgdC5kb2NoYWRhdGhhaSA9IDB4MGUwZTsKICB0LmRvZGVrdGhhaSA9IDB4MGUxNDsKICB0LmRvaGlyYWdhbmEgPSAweDMwNjk7CiAgdC5kb2thdGFrYW5hID0gMHgzMGM5OwogIHQuZG9sbGFyID0gMHgwMDI0OwogIHQuZG9sbGFyaW5mZXJpb3IgPSAweGY2ZTM7CiAgdC5kb2xsYXJtb25vc3BhY2UgPSAweGZmMDQ7CiAgdC5kb2xsYXJvbGRzdHlsZSA9IDB4ZjcyNDsKICB0LmRvbGxhcnNtYWxsID0gMHhmZTY5OwogIHQuZG9sbGFyc3VwZXJpb3IgPSAweGY2ZTQ7CiAgdC5kb25nID0gMHgyMGFiOwogIHQuZG9ydXNxdWFyZSA9IDB4MzMyNjsKICB0LmRvdGFjY2VudCA9IDB4MDJkOTsKICB0LmRvdGFjY2VudGNtYiA9IDB4MDMwNzsKICB0LmRvdGJlbG93Y21iID0gMHgwMzIzOwogIHQuZG90YmVsb3djb21iID0gMHgwMzIzOwogIHQuZG90a2F0YWthbmEgPSAweDMwZmI7CiAgdC5kb3RsZXNzaSA9IDB4MDEzMTsKICB0LmRvdGxlc3NqID0gMHhmNmJlOwogIHQuZG90bGVzc2pzdHJva2Vob29rID0gMHgwMjg0OwogIHQuZG90bWF0aCA9IDB4MjJjNTsKICB0LmRvdHRlZGNpcmNsZSA9IDB4MjVjYzsKICB0LmRvdWJsZXlvZHBhdGFoID0gMHhmYjFmOwogIHQuZG91YmxleW9kcGF0YWhoZWJyZXcgPSAweGZiMWY7CiAgdC5kb3dudGFja2JlbG93Y21iID0gMHgwMzFlOwogIHQuZG93bnRhY2ttb2QgPSAweDAyZDU7CiAgdC5kcGFyZW4gPSAweDI0OWY7CiAgdC5kc3VwZXJpb3IgPSAweGY2ZWI7CiAgdC5kdGFpbCA9IDB4MDI1NjsKICB0LmR0b3BiYXIgPSAweDAxOGM7CiAgdC5kdWhpcmFnYW5hID0gMHgzMDY1OwogIHQuZHVrYXRha2FuYSA9IDB4MzBjNTsKICB0LmR6ID0gMHgwMWYzOwogIHQuZHphbHRvbmUgPSAweDAyYTM7CiAgdC5kemNhcm9uID0gMHgwMWM2OwogIHQuZHpjdXJsID0gMHgwMmE1OwogIHQuZHplYWJraGFzaWFuY3lyaWxsaWMgPSAweDA0ZTE7CiAgdC5kemVjeXJpbGxpYyA9IDB4MDQ1NTsKICB0LmR6aGVjeXJpbGxpYyA9IDB4MDQ1ZjsKICB0LmUgPSAweDAwNjU7CiAgdC5lYWN1dGUgPSAweDAwZTk7CiAgdC5lYXJ0aCA9IDB4MjY0MTsKICB0LmViZW5nYWxpID0gMHgwOThmOwogIHQuZWJvcG9tb2ZvID0gMHgzMTFjOwogIHQuZWJyZXZlID0gMHgwMTE1OwogIHQuZWNhbmRyYWRldmEgPSAweDA5MGQ7CiAgdC5lY2FuZHJhZ3VqYXJhdGkgPSAweDBhOGQ7CiAgdC5lY2FuZHJhdm93ZWxzaWduZGV2YSA9IDB4MDk0NTsKICB0LmVjYW5kcmF2b3dlbHNpZ25ndWphcmF0aSA9IDB4MGFjNTsKICB0LmVjYXJvbiA9IDB4MDExYjsKICB0LmVjZWRpbGxhYnJldmUgPSAweDFlMWQ7CiAgdC5lY2hhcm1lbmlhbiA9IDB4MDU2NTsKICB0LmVjaHlpd25hcm1lbmlhbiA9IDB4MDU4NzsKICB0LmVjaXJjbGUgPSAweDI0ZDQ7CiAgdC5lY2lyY3VtZmxleCA9IDB4MDBlYTsKICB0LmVjaXJjdW1mbGV4YWN1dGUgPSAweDFlYmY7CiAgdC5lY2lyY3VtZmxleGJlbG93ID0gMHgxZTE5OwogIHQuZWNpcmN1bWZsZXhkb3RiZWxvdyA9IDB4MWVjNzsKICB0LmVjaXJjdW1mbGV4Z3JhdmUgPSAweDFlYzE7CiAgdC5lY2lyY3VtZmxleGhvb2thYm92ZSA9IDB4MWVjMzsKICB0LmVjaXJjdW1mbGV4dGlsZGUgPSAweDFlYzU7CiAgdC5lY3lyaWxsaWMgPSAweDA0NTQ7CiAgdC5lZGJsZ3JhdmUgPSAweDAyMDU7CiAgdC5lZGV2YSA9IDB4MDkwZjsKICB0LmVkaWVyZXNpcyA9IDB4MDBlYjsKICB0LmVkb3QgPSAweDAxMTc7CiAgdC5lZG90YWNjZW50ID0gMHgwMTE3OwogIHQuZWRvdGJlbG93ID0gMHgxZWI5OwogIHQuZWVndXJtdWtoaSA9IDB4MGEwZjsKICB0LmVlbWF0cmFndXJtdWtoaSA9IDB4MGE0NzsKICB0LmVmY3lyaWxsaWMgPSAweDA0NDQ7CiAgdC5lZ3JhdmUgPSAweDAwZTg7CiAgdC5lZ3VqYXJhdGkgPSAweDBhOGY7CiAgdC5laGFybWVuaWFuID0gMHgwNTY3OwogIHQuZWhib3BvbW9mbyA9IDB4MzExZDsKICB0LmVoaXJhZ2FuYSA9IDB4MzA0ODsKICB0LmVob29rYWJvdmUgPSAweDFlYmI7CiAgdC5laWJvcG9tb2ZvID0gMHgzMTFmOwogIHQuZWlnaHQgPSAweDAwMzg7CiAgdC5laWdodGFyYWJpYyA9IDB4MDY2ODsKICB0LmVpZ2h0YmVuZ2FsaSA9IDB4MDllZTsKICB0LmVpZ2h0Y2lyY2xlID0gMHgyNDY3OwogIHQuZWlnaHRjaXJjbGVpbnZlcnNlc2Fuc3NlcmlmID0gMHgyNzkxOwogIHQuZWlnaHRkZXZhID0gMHgwOTZlOwogIHQuZWlnaHRlZW5jaXJjbGUgPSAweDI0NzE7CiAgdC5laWdodGVlbnBhcmVuID0gMHgyNDg1OwogIHQuZWlnaHRlZW5wZXJpb2QgPSAweDI0OTk7CiAgdC5laWdodGd1amFyYXRpID0gMHgwYWVlOwogIHQuZWlnaHRndXJtdWtoaSA9IDB4MGE2ZTsKICB0LmVpZ2h0aGFja2FyYWJpYyA9IDB4MDY2ODsKICB0LmVpZ2h0aGFuZ3pob3UgPSAweDMwMjg7CiAgdC5laWdodGhub3RlYmVhbWVkID0gMHgyNjZiOwogIHQuZWlnaHRpZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjI3OwogIHQuZWlnaHRpbmZlcmlvciA9IDB4MjA4ODsKICB0LmVpZ2h0bW9ub3NwYWNlID0gMHhmZjE4OwogIHQuZWlnaHRvbGRzdHlsZSA9IDB4ZjczODsKICB0LmVpZ2h0cGFyZW4gPSAweDI0N2I7CiAgdC5laWdodHBlcmlvZCA9IDB4MjQ4ZjsKICB0LmVpZ2h0cGVyc2lhbiA9IDB4MDZmODsKICB0LmVpZ2h0cm9tYW4gPSAweDIxNzc7CiAgdC5laWdodHN1cGVyaW9yID0gMHgyMDc4OwogIHQuZWlnaHR0aGFpID0gMHgwZTU4OwogIHQuZWludmVydGVkYnJldmUgPSAweDAyMDc7CiAgdC5laW90aWZpZWRjeXJpbGxpYyA9IDB4MDQ2NTsKICB0LmVrYXRha2FuYSA9IDB4MzBhODsKICB0LmVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3NDsKICB0LmVrb25rYXJndXJtdWtoaSA9IDB4MGE3NDsKICB0LmVrb3JlYW4gPSAweDMxNTQ7CiAgdC5lbGN5cmlsbGljID0gMHgwNDNiOwogIHQuZWxlbWVudCA9IDB4MjIwODsKICB0LmVsZXZlbmNpcmNsZSA9IDB4MjQ2YTsKICB0LmVsZXZlbnBhcmVuID0gMHgyNDdlOwogIHQuZWxldmVucGVyaW9kID0gMHgyNDkyOwogIHQuZWxldmVucm9tYW4gPSAweDIxN2E7CiAgdC5lbGxpcHNpcyA9IDB4MjAyNjsKICB0LmVsbGlwc2lzdmVydGljYWwgPSAweDIyZWU7CiAgdC5lbWFjcm9uID0gMHgwMTEzOwogIHQuZW1hY3JvbmFjdXRlID0gMHgxZTE3OwogIHQuZW1hY3JvbmdyYXZlID0gMHgxZTE1OwogIHQuZW1jeXJpbGxpYyA9IDB4MDQzYzsKICB0LmVtZGFzaCA9IDB4MjAxNDsKICB0LmVtZGFzaHZlcnRpY2FsID0gMHhmZTMxOwogIHQuZW1vbm9zcGFjZSA9IDB4ZmY0NTsKICB0LmVtcGhhc2lzbWFya2FybWVuaWFuID0gMHgwNTViOwogIHQuZW1wdHlzZXQgPSAweDIyMDU7CiAgdC5lbmJvcG9tb2ZvID0gMHgzMTIzOwogIHQuZW5jeXJpbGxpYyA9IDB4MDQzZDsKICB0LmVuZGFzaCA9IDB4MjAxMzsKICB0LmVuZGFzaHZlcnRpY2FsID0gMHhmZTMyOwogIHQuZW5kZXNjZW5kZXJjeXJpbGxpYyA9IDB4MDRhMzsKICB0LmVuZyA9IDB4MDE0YjsKICB0LmVuZ2JvcG9tb2ZvID0gMHgzMTI1OwogIHQuZW5naGVjeXJpbGxpYyA9IDB4MDRhNTsKICB0LmVuaG9va2N5cmlsbGljID0gMHgwNGM4OwogIHQuZW5zcGFjZSA9IDB4MjAwMjsKICB0LmVvZ29uZWsgPSAweDAxMTk7CiAgdC5lb2tvcmVhbiA9IDB4MzE1MzsKICB0LmVvcGVuID0gMHgwMjViOwogIHQuZW9wZW5jbG9zZWQgPSAweDAyOWE7CiAgdC5lb3BlbnJldmVyc2VkID0gMHgwMjVjOwogIHQuZW9wZW5yZXZlcnNlZGNsb3NlZCA9IDB4MDI1ZTsKICB0LmVvcGVucmV2ZXJzZWRob29rID0gMHgwMjVkOwogIHQuZXBhcmVuID0gMHgyNGEwOwogIHQuZXBzaWxvbiA9IDB4MDNiNTsKICB0LmVwc2lsb250b25vcyA9IDB4MDNhZDsKICB0LmVxdWFsID0gMHgwMDNkOwogIHQuZXF1YWxtb25vc3BhY2UgPSAweGZmMWQ7CiAgdC5lcXVhbHNtYWxsID0gMHhmZTY2OwogIHQuZXF1YWxzdXBlcmlvciA9IDB4MjA3YzsKICB0LmVxdWl2YWxlbmNlID0gMHgyMjYxOwogIHQuZXJib3BvbW9mbyA9IDB4MzEyNjsKICB0LmVyY3lyaWxsaWMgPSAweDA0NDA7CiAgdC5lcmV2ZXJzZWQgPSAweDAyNTg7CiAgdC5lcmV2ZXJzZWRjeXJpbGxpYyA9IDB4MDQ0ZDsKICB0LmVzY3lyaWxsaWMgPSAweDA0NDE7CiAgdC5lc2Rlc2NlbmRlcmN5cmlsbGljID0gMHgwNGFiOwogIHQuZXNoID0gMHgwMjgzOwogIHQuZXNoY3VybCA9IDB4MDI4NjsKICB0LmVzaG9ydGRldmEgPSAweDA5MGU7CiAgdC5lc2hvcnR2b3dlbHNpZ25kZXZhID0gMHgwOTQ2OwogIHQuZXNocmV2ZXJzZWRsb29wID0gMHgwMWFhOwogIHQuZXNoc3F1YXRyZXZlcnNlZCA9IDB4MDI4NTsKICB0LmVzbWFsbGhpcmFnYW5hID0gMHgzMDQ3OwogIHQuZXNtYWxsa2F0YWthbmEgPSAweDMwYTc7CiAgdC5lc21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2YTsKICB0LmVzdGltYXRlZCA9IDB4MjEyZTsKICB0LmVzdXBlcmlvciA9IDB4ZjZlYzsKICB0LmV0YSA9IDB4MDNiNzsKICB0LmV0YXJtZW5pYW4gPSAweDA1Njg7CiAgdC5ldGF0b25vcyA9IDB4MDNhZTsKICB0LmV0aCA9IDB4MDBmMDsKICB0LmV0aWxkZSA9IDB4MWViZDsKICB0LmV0aWxkZWJlbG93ID0gMHgxZTFiOwogIHQuZXRuYWh0YWZvdWtoaGVicmV3ID0gMHgwNTkxOwogIHQuZXRuYWh0YWZvdWtobGVmdGhlYnJldyA9IDB4MDU5MTsKICB0LmV0bmFodGFoZWJyZXcgPSAweDA1OTE7CiAgdC5ldG5haHRhbGVmdGhlYnJldyA9IDB4MDU5MTsKICB0LmV0dXJuZWQgPSAweDAxZGQ7CiAgdC5ldWtvcmVhbiA9IDB4MzE2MTsKICB0LmV1cm8gPSAweDIwYWM7CiAgdC5ldm93ZWxzaWduYmVuZ2FsaSA9IDB4MDljNzsKICB0LmV2b3dlbHNpZ25kZXZhID0gMHgwOTQ3OwogIHQuZXZvd2Vsc2lnbmd1amFyYXRpID0gMHgwYWM3OwogIHQuZXhjbGFtID0gMHgwMDIxOwogIHQuZXhjbGFtYXJtZW5pYW4gPSAweDA1NWM7CiAgdC5leGNsYW1kYmwgPSAweDIwM2M7CiAgdC5leGNsYW1kb3duID0gMHgwMGExOwogIHQuZXhjbGFtZG93bnNtYWxsID0gMHhmN2ExOwogIHQuZXhjbGFtbW9ub3NwYWNlID0gMHhmZjAxOwogIHQuZXhjbGFtc21hbGwgPSAweGY3MjE7CiAgdC5leGlzdGVudGlhbCA9IDB4MjIwMzsKICB0LmV6aCA9IDB4MDI5MjsKICB0LmV6aGNhcm9uID0gMHgwMWVmOwogIHQuZXpoY3VybCA9IDB4MDI5MzsKICB0LmV6aHJldmVyc2VkID0gMHgwMWI5OwogIHQuZXpodGFpbCA9IDB4MDFiYTsKICB0LmYgPSAweDAwNjY7CiAgdC5mYWRldmEgPSAweDA5NWU7CiAgdC5mYWd1cm11a2hpID0gMHgwYTVlOwogIHQuZmFocmVuaGVpdCA9IDB4MjEwOTsKICB0LmZhdGhhYXJhYmljID0gMHgwNjRlOwogIHQuZmF0aGFsb3dhcmFiaWMgPSAweDA2NGU7CiAgdC5mYXRoYXRhbmFyYWJpYyA9IDB4MDY0YjsKICB0LmZib3BvbW9mbyA9IDB4MzEwODsKICB0LmZjaXJjbGUgPSAweDI0ZDU7CiAgdC5mZG90YWNjZW50ID0gMHgxZTFmOwogIHQuZmVoYXJhYmljID0gMHgwNjQxOwogIHQuZmVoYXJtZW5pYW4gPSAweDA1ODY7CiAgdC5mZWhmaW5hbGFyYWJpYyA9IDB4ZmVkMjsKICB0LmZlaGluaXRpYWxhcmFiaWMgPSAweGZlZDM7CiAgdC5mZWhtZWRpYWxhcmFiaWMgPSAweGZlZDQ7CiAgdC5mZWljb3B0aWMgPSAweDAzZTU7CiAgdC5mZW1hbGUgPSAweDI2NDA7CiAgdC5mZiA9IDB4ZmIwMDsKICB0LmZfZiA9IDB4ZmIwMDsKICB0LmZmaSA9IDB4ZmIwMzsKICB0LmZfZl9pID0gMHhmYjAzOwogIHQuZmZsID0gMHhmYjA0OwogIHQuZl9mX2wgPSAweGZiMDQ7CiAgdC5maSA9IDB4ZmIwMTsKICB0LmZfaSA9IDB4ZmIwMTsKICB0LmZpZnRlZW5jaXJjbGUgPSAweDI0NmU7CiAgdC5maWZ0ZWVucGFyZW4gPSAweDI0ODI7CiAgdC5maWZ0ZWVucGVyaW9kID0gMHgyNDk2OwogIHQuZmlndXJlZGFzaCA9IDB4MjAxMjsKICB0LmZpbGxlZGJveCA9IDB4MjVhMDsKICB0LmZpbGxlZHJlY3QgPSAweDI1YWM7CiAgdC5maW5hbGthZiA9IDB4MDVkYTsKICB0LmZpbmFsa2FmZGFnZXNoID0gMHhmYjNhOwogIHQuZmluYWxrYWZkYWdlc2hoZWJyZXcgPSAweGZiM2E7CiAgdC5maW5hbGthZmhlYnJldyA9IDB4MDVkYTsKICB0LmZpbmFsbWVtID0gMHgwNWRkOwogIHQuZmluYWxtZW1oZWJyZXcgPSAweDA1ZGQ7CiAgdC5maW5hbG51biA9IDB4MDVkZjsKICB0LmZpbmFsbnVuaGVicmV3ID0gMHgwNWRmOwogIHQuZmluYWxwZSA9IDB4MDVlMzsKICB0LmZpbmFscGVoZWJyZXcgPSAweDA1ZTM7CiAgdC5maW5hbHRzYWRpID0gMHgwNWU1OwogIHQuZmluYWx0c2FkaWhlYnJldyA9IDB4MDVlNTsKICB0LmZpcnN0dG9uZWNoaW5lc2UgPSAweDAyYzk7CiAgdC5maXNoZXllID0gMHgyNWM5OwogIHQuZml0YWN5cmlsbGljID0gMHgwNDczOwogIHQuZml2ZSA9IDB4MDAzNTsKICB0LmZpdmVhcmFiaWMgPSAweDA2NjU7CiAgdC5maXZlYmVuZ2FsaSA9IDB4MDllYjsKICB0LmZpdmVjaXJjbGUgPSAweDI0NjQ7CiAgdC5maXZlY2lyY2xlaW52ZXJzZXNhbnNzZXJpZiA9IDB4Mjc4ZTsKICB0LmZpdmVkZXZhID0gMHgwOTZiOwogIHQuZml2ZWVpZ2h0aHMgPSAweDIxNWQ7CiAgdC5maXZlZ3VqYXJhdGkgPSAweDBhZWI7CiAgdC5maXZlZ3VybXVraGkgPSAweDBhNmI7CiAgdC5maXZlaGFja2FyYWJpYyA9IDB4MDY2NTsKICB0LmZpdmVoYW5nemhvdSA9IDB4MzAyNTsKICB0LmZpdmVpZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjI0OwogIHQuZml2ZWluZmVyaW9yID0gMHgyMDg1OwogIHQuZml2ZW1vbm9zcGFjZSA9IDB4ZmYxNTsKICB0LmZpdmVvbGRzdHlsZSA9IDB4ZjczNTsKICB0LmZpdmVwYXJlbiA9IDB4MjQ3ODsKICB0LmZpdmVwZXJpb2QgPSAweDI0OGM7CiAgdC5maXZlcGVyc2lhbiA9IDB4MDZmNTsKICB0LmZpdmVyb21hbiA9IDB4MjE3NDsKICB0LmZpdmVzdXBlcmlvciA9IDB4MjA3NTsKICB0LmZpdmV0aGFpID0gMHgwZTU1OwogIHQuZmwgPSAweGZiMDI7CiAgdC5mX2wgPSAweGZiMDI7CiAgdC5mbG9yaW4gPSAweDAxOTI7CiAgdC5mbW9ub3NwYWNlID0gMHhmZjQ2OwogIHQuZm1zcXVhcmUgPSAweDMzOTk7CiAgdC5mb2ZhbnRoYWkgPSAweDBlMWY7CiAgdC5mb2ZhdGhhaSA9IDB4MGUxZDsKICB0LmZvbmdtYW50aGFpID0gMHgwZTRmOwogIHQuZm9yYWxsID0gMHgyMjAwOwogIHQuZm91ciA9IDB4MDAzNDsKICB0LmZvdXJhcmFiaWMgPSAweDA2NjQ7CiAgdC5mb3VyYmVuZ2FsaSA9IDB4MDllYTsKICB0LmZvdXJjaXJjbGUgPSAweDI0NjM7CiAgdC5mb3VyY2lyY2xlaW52ZXJzZXNhbnNzZXJpZiA9IDB4Mjc4ZDsKICB0LmZvdXJkZXZhID0gMHgwOTZhOwogIHQuZm91cmd1amFyYXRpID0gMHgwYWVhOwogIHQuZm91cmd1cm11a2hpID0gMHgwYTZhOwogIHQuZm91cmhhY2thcmFiaWMgPSAweDA2NjQ7CiAgdC5mb3VyaGFuZ3pob3UgPSAweDMwMjQ7CiAgdC5mb3VyaWRlb2dyYXBoaWNwYXJlbiA9IDB4MzIyMzsKICB0LmZvdXJpbmZlcmlvciA9IDB4MjA4NDsKICB0LmZvdXJtb25vc3BhY2UgPSAweGZmMTQ7CiAgdC5mb3VybnVtZXJhdG9yYmVuZ2FsaSA9IDB4MDlmNzsKICB0LmZvdXJvbGRzdHlsZSA9IDB4ZjczNDsKICB0LmZvdXJwYXJlbiA9IDB4MjQ3NzsKICB0LmZvdXJwZXJpb2QgPSAweDI0OGI7CiAgdC5mb3VycGVyc2lhbiA9IDB4MDZmNDsKICB0LmZvdXJyb21hbiA9IDB4MjE3MzsKICB0LmZvdXJzdXBlcmlvciA9IDB4MjA3NDsKICB0LmZvdXJ0ZWVuY2lyY2xlID0gMHgyNDZkOwogIHQuZm91cnRlZW5wYXJlbiA9IDB4MjQ4MTsKICB0LmZvdXJ0ZWVucGVyaW9kID0gMHgyNDk1OwogIHQuZm91cnRoYWkgPSAweDBlNTQ7CiAgdC5mb3VydGh0b25lY2hpbmVzZSA9IDB4MDJjYjsKICB0LmZwYXJlbiA9IDB4MjRhMTsKICB0LmZyYWN0aW9uID0gMHgyMDQ0OwogIHQuZnJhbmMgPSAweDIwYTM7CiAgdC5nID0gMHgwMDY3OwogIHQuZ2FiZW5nYWxpID0gMHgwOTk3OwogIHQuZ2FjdXRlID0gMHgwMWY1OwogIHQuZ2FkZXZhID0gMHgwOTE3OwogIHQuZ2FmYXJhYmljID0gMHgwNmFmOwogIHQuZ2FmZmluYWxhcmFiaWMgPSAweGZiOTM7CiAgdC5nYWZpbml0aWFsYXJhYmljID0gMHhmYjk0OwogIHQuZ2FmbWVkaWFsYXJhYmljID0gMHhmYjk1OwogIHQuZ2FndWphcmF0aSA9IDB4MGE5NzsKICB0LmdhZ3VybXVraGkgPSAweDBhMTc7CiAgdC5nYWhpcmFnYW5hID0gMHgzMDRjOwogIHQuZ2FrYXRha2FuYSA9IDB4MzBhYzsKICB0LmdhbW1hID0gMHgwM2IzOwogIHQuZ2FtbWFsYXRpbnNtYWxsID0gMHgwMjYzOwogIHQuZ2FtbWFzdXBlcmlvciA9IDB4MDJlMDsKICB0LmdhbmdpYWNvcHRpYyA9IDB4MDNlYjsKICB0Lmdib3BvbW9mbyA9IDB4MzEwZDsKICB0LmdicmV2ZSA9IDB4MDExZjsKICB0LmdjYXJvbiA9IDB4MDFlNzsKICB0LmdjZWRpbGxhID0gMHgwMTIzOwogIHQuZ2NpcmNsZSA9IDB4MjRkNjsKICB0LmdjaXJjdW1mbGV4ID0gMHgwMTFkOwogIHQuZ2NvbW1hYWNjZW50ID0gMHgwMTIzOwogIHQuZ2RvdCA9IDB4MDEyMTsKICB0Lmdkb3RhY2NlbnQgPSAweDAxMjE7CiAgdC5nZWN5cmlsbGljID0gMHgwNDMzOwogIHQuZ2VoaXJhZ2FuYSA9IDB4MzA1MjsKICB0Lmdla2F0YWthbmEgPSAweDMwYjI7CiAgdC5nZW9tZXRyaWNhbGx5ZXF1YWwgPSAweDIyNTE7CiAgdC5nZXJlc2hhY2NlbnRoZWJyZXcgPSAweDA1OWM7CiAgdC5nZXJlc2hoZWJyZXcgPSAweDA1ZjM7CiAgdC5nZXJlc2htdXFkYW1oZWJyZXcgPSAweDA1OWQ7CiAgdC5nZXJtYW5kYmxzID0gMHgwMGRmOwogIHQuZ2Vyc2hheWltYWNjZW50aGVicmV3ID0gMHgwNTllOwogIHQuZ2Vyc2hheWltaGVicmV3ID0gMHgwNWY0OwogIHQuZ2V0YW1hcmsgPSAweDMwMTM7CiAgdC5naGFiZW5nYWxpID0gMHgwOTk4OwogIHQuZ2hhZGFybWVuaWFuID0gMHgwNTcyOwogIHQuZ2hhZGV2YSA9IDB4MDkxODsKICB0LmdoYWd1amFyYXRpID0gMHgwYTk4OwogIHQuZ2hhZ3VybXVraGkgPSAweDBhMTg7CiAgdC5naGFpbmFyYWJpYyA9IDB4MDYzYTsKICB0LmdoYWluZmluYWxhcmFiaWMgPSAweGZlY2U7CiAgdC5naGFpbmluaXRpYWxhcmFiaWMgPSAweGZlY2Y7CiAgdC5naGFpbm1lZGlhbGFyYWJpYyA9IDB4ZmVkMDsKICB0LmdoZW1pZGRsZWhvb2tjeXJpbGxpYyA9IDB4MDQ5NTsKICB0LmdoZXN0cm9rZWN5cmlsbGljID0gMHgwNDkzOwogIHQuZ2hldXB0dXJuY3lyaWxsaWMgPSAweDA0OTE7CiAgdC5naGhhZGV2YSA9IDB4MDk1YTsKICB0LmdoaGFndXJtdWtoaSA9IDB4MGE1YTsKICB0Lmdob29rID0gMHgwMjYwOwogIHQuZ2h6c3F1YXJlID0gMHgzMzkzOwogIHQuZ2loaXJhZ2FuYSA9IDB4MzA0ZTsKICB0Lmdpa2F0YWthbmEgPSAweDMwYWU7CiAgdC5naW1hcm1lbmlhbiA9IDB4MDU2MzsKICB0LmdpbWVsID0gMHgwNWQyOwogIHQuZ2ltZWxkYWdlc2ggPSAweGZiMzI7CiAgdC5naW1lbGRhZ2VzaGhlYnJldyA9IDB4ZmIzMjsKICB0LmdpbWVsaGVicmV3ID0gMHgwNWQyOwogIHQuZ2plY3lyaWxsaWMgPSAweDA0NTM7CiAgdC5nbG90dGFsaW52ZXJ0ZWRzdHJva2UgPSAweDAxYmU7CiAgdC5nbG90dGFsc3RvcCA9IDB4MDI5NDsKICB0Lmdsb3R0YWxzdG9waW52ZXJ0ZWQgPSAweDAyOTY7CiAgdC5nbG90dGFsc3RvcG1vZCA9IDB4MDJjMDsKICB0Lmdsb3R0YWxzdG9wcmV2ZXJzZWQgPSAweDAyOTU7CiAgdC5nbG90dGFsc3RvcHJldmVyc2VkbW9kID0gMHgwMmMxOwogIHQuZ2xvdHRhbHN0b3ByZXZlcnNlZHN1cGVyaW9yID0gMHgwMmU0OwogIHQuZ2xvdHRhbHN0b3BzdHJva2UgPSAweDAyYTE7CiAgdC5nbG90dGFsc3RvcHN0cm9rZXJldmVyc2VkID0gMHgwMmEyOwogIHQuZ21hY3JvbiA9IDB4MWUyMTsKICB0Lmdtb25vc3BhY2UgPSAweGZmNDc7CiAgdC5nb2hpcmFnYW5hID0gMHgzMDU0OwogIHQuZ29rYXRha2FuYSA9IDB4MzBiNDsKICB0LmdwYXJlbiA9IDB4MjRhMjsKICB0LmdwYXNxdWFyZSA9IDB4MzNhYzsKICB0LmdyYWRpZW50ID0gMHgyMjA3OwogIHQuZ3JhdmUgPSAweDAwNjA7CiAgdC5ncmF2ZWJlbG93Y21iID0gMHgwMzE2OwogIHQuZ3JhdmVjbWIgPSAweDAzMDA7CiAgdC5ncmF2ZWNvbWIgPSAweDAzMDA7CiAgdC5ncmF2ZWRldmEgPSAweDA5NTM7CiAgdC5ncmF2ZWxvd21vZCA9IDB4MDJjZTsKICB0LmdyYXZlbW9ub3NwYWNlID0gMHhmZjQwOwogIHQuZ3JhdmV0b25lY21iID0gMHgwMzQwOwogIHQuZ3JlYXRlciA9IDB4MDAzZTsKICB0LmdyZWF0ZXJlcXVhbCA9IDB4MjI2NTsKICB0LmdyZWF0ZXJlcXVhbG9ybGVzcyA9IDB4MjJkYjsKICB0LmdyZWF0ZXJtb25vc3BhY2UgPSAweGZmMWU7CiAgdC5ncmVhdGVyb3JlcXVpdmFsZW50ID0gMHgyMjczOwogIHQuZ3JlYXRlcm9ybGVzcyA9IDB4MjI3NzsKICB0LmdyZWF0ZXJvdmVyZXF1YWwgPSAweDIyNjc7CiAgdC5ncmVhdGVyc21hbGwgPSAweGZlNjU7CiAgdC5nc2NyaXB0ID0gMHgwMjYxOwogIHQuZ3N0cm9rZSA9IDB4MDFlNTsKICB0Lmd1aGlyYWdhbmEgPSAweDMwNTA7CiAgdC5ndWlsbGVtb3RsZWZ0ID0gMHgwMGFiOwogIHQuZ3VpbGxlbW90cmlnaHQgPSAweDAwYmI7CiAgdC5ndWlsc2luZ2xsZWZ0ID0gMHgyMDM5OwogIHQuZ3VpbHNpbmdscmlnaHQgPSAweDIwM2E7CiAgdC5ndWthdGFrYW5hID0gMHgzMGIwOwogIHQuZ3VyYW11c3F1YXJlID0gMHgzMzE4OwogIHQuZ3lzcXVhcmUgPSAweDMzYzk7CiAgdC5oID0gMHgwMDY4OwogIHQuaGFhYmtoYXNpYW5jeXJpbGxpYyA9IDB4MDRhOTsKICB0LmhhYWx0b25lYXJhYmljID0gMHgwNmMxOwogIHQuaGFiZW5nYWxpID0gMHgwOWI5OwogIHQuaGFkZXNjZW5kZXJjeXJpbGxpYyA9IDB4MDRiMzsKICB0LmhhZGV2YSA9IDB4MDkzOTsKICB0LmhhZ3VqYXJhdGkgPSAweDBhYjk7CiAgdC5oYWd1cm11a2hpID0gMHgwYTM5OwogIHQuaGFoYXJhYmljID0gMHgwNjJkOwogIHQuaGFoZmluYWxhcmFiaWMgPSAweGZlYTI7CiAgdC5oYWhpbml0aWFsYXJhYmljID0gMHhmZWEzOwogIHQuaGFoaXJhZ2FuYSA9IDB4MzA2ZjsKICB0LmhhaG1lZGlhbGFyYWJpYyA9IDB4ZmVhNDsKICB0LmhhaXR1c3F1YXJlID0gMHgzMzJhOwogIHQuaGFrYXRha2FuYSA9IDB4MzBjZjsKICB0Lmhha2F0YWthbmFoYWxmd2lkdGggPSAweGZmOGE7CiAgdC5oYWxhbnRndXJtdWtoaSA9IDB4MGE0ZDsKICB0LmhhbXphYXJhYmljID0gMHgwNjIxOwogIHQuaGFtemFsb3dhcmFiaWMgPSAweDA2MjE7CiAgdC5oYW5ndWxmaWxsZXIgPSAweDMxNjQ7CiAgdC5oYXJkc2lnbmN5cmlsbGljID0gMHgwNDRhOwogIHQuaGFycG9vbmxlZnRiYXJidXAgPSAweDIxYmM7CiAgdC5oYXJwb29ucmlnaHRiYXJidXAgPSAweDIxYzA7CiAgdC5oYXNxdWFyZSA9IDB4MzNjYTsKICB0LmhhdGFmcGF0YWggPSAweDA1YjI7CiAgdC5oYXRhZnBhdGFoMTYgPSAweDA1YjI7CiAgdC5oYXRhZnBhdGFoMjMgPSAweDA1YjI7CiAgdC5oYXRhZnBhdGFoMmYgPSAweDA1YjI7CiAgdC5oYXRhZnBhdGFoaGVicmV3ID0gMHgwNWIyOwogIHQuaGF0YWZwYXRhaG5hcnJvd2hlYnJldyA9IDB4MDViMjsKICB0LmhhdGFmcGF0YWhxdWFydGVyaGVicmV3ID0gMHgwNWIyOwogIHQuaGF0YWZwYXRhaHdpZGVoZWJyZXcgPSAweDA1YjI7CiAgdC5oYXRhZnFhbWF0cyA9IDB4MDViMzsKICB0LmhhdGFmcWFtYXRzMWIgPSAweDA1YjM7CiAgdC5oYXRhZnFhbWF0czI4ID0gMHgwNWIzOwogIHQuaGF0YWZxYW1hdHMzNCA9IDB4MDViMzsKICB0LmhhdGFmcWFtYXRzaGVicmV3ID0gMHgwNWIzOwogIHQuaGF0YWZxYW1hdHNuYXJyb3doZWJyZXcgPSAweDA1YjM7CiAgdC5oYXRhZnFhbWF0c3F1YXJ0ZXJoZWJyZXcgPSAweDA1YjM7CiAgdC5oYXRhZnFhbWF0c3dpZGVoZWJyZXcgPSAweDA1YjM7CiAgdC5oYXRhZnNlZ29sID0gMHgwNWIxOwogIHQuaGF0YWZzZWdvbDE3ID0gMHgwNWIxOwogIHQuaGF0YWZzZWdvbDI0ID0gMHgwNWIxOwogIHQuaGF0YWZzZWdvbDMwID0gMHgwNWIxOwogIHQuaGF0YWZzZWdvbGhlYnJldyA9IDB4MDViMTsKICB0LmhhdGFmc2Vnb2xuYXJyb3doZWJyZXcgPSAweDA1YjE7CiAgdC5oYXRhZnNlZ29scXVhcnRlcmhlYnJldyA9IDB4MDViMTsKICB0LmhhdGFmc2Vnb2x3aWRlaGVicmV3ID0gMHgwNWIxOwogIHQuaGJhciA9IDB4MDEyNzsKICB0Lmhib3BvbW9mbyA9IDB4MzEwZjsKICB0LmhicmV2ZWJlbG93ID0gMHgxZTJiOwogIHQuaGNlZGlsbGEgPSAweDFlMjk7CiAgdC5oY2lyY2xlID0gMHgyNGQ3OwogIHQuaGNpcmN1bWZsZXggPSAweDAxMjU7CiAgdC5oZGllcmVzaXMgPSAweDFlMjc7CiAgdC5oZG90YWNjZW50ID0gMHgxZTIzOwogIHQuaGRvdGJlbG93ID0gMHgxZTI1OwogIHQuaGUgPSAweDA1ZDQ7CiAgdC5oZWFydCA9IDB4MjY2NTsKICB0LmhlYXJ0c3VpdGJsYWNrID0gMHgyNjY1OwogIHQuaGVhcnRzdWl0d2hpdGUgPSAweDI2NjE7CiAgdC5oZWRhZ2VzaCA9IDB4ZmIzNDsKICB0LmhlZGFnZXNoaGVicmV3ID0gMHhmYjM0OwogIHQuaGVoYWx0b25lYXJhYmljID0gMHgwNmMxOwogIHQuaGVoYXJhYmljID0gMHgwNjQ3OwogIHQuaGVoZWJyZXcgPSAweDA1ZDQ7CiAgdC5oZWhmaW5hbGFsdG9uZWFyYWJpYyA9IDB4ZmJhNzsKICB0LmhlaGZpbmFsYWx0dHdvYXJhYmljID0gMHhmZWVhOwogIHQuaGVoZmluYWxhcmFiaWMgPSAweGZlZWE7CiAgdC5oZWhoYW16YWFib3ZlZmluYWxhcmFiaWMgPSAweGZiYTU7CiAgdC5oZWhoYW16YWFib3ZlaXNvbGF0ZWRhcmFiaWMgPSAweGZiYTQ7CiAgdC5oZWhpbml0aWFsYWx0b25lYXJhYmljID0gMHhmYmE4OwogIHQuaGVoaW5pdGlhbGFyYWJpYyA9IDB4ZmVlYjsKICB0LmhlaGlyYWdhbmEgPSAweDMwNzg7CiAgdC5oZWhtZWRpYWxhbHRvbmVhcmFiaWMgPSAweGZiYTk7CiAgdC5oZWhtZWRpYWxhcmFiaWMgPSAweGZlZWM7CiAgdC5oZWlzZWllcmFzcXVhcmUgPSAweDMzN2I7CiAgdC5oZWthdGFrYW5hID0gMHgzMGQ4OwogIHQuaGVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4ZDsKICB0Lmhla3V0YWFydXNxdWFyZSA9IDB4MzMzNjsKICB0Lmhlbmdob29rID0gMHgwMjY3OwogIHQuaGVydXR1c3F1YXJlID0gMHgzMzM5OwogIHQuaGV0ID0gMHgwNWQ3OwogIHQuaGV0aGVicmV3ID0gMHgwNWQ3OwogIHQuaGhvb2sgPSAweDAyNjY7CiAgdC5oaG9va3N1cGVyaW9yID0gMHgwMmIxOwogIHQuaGlldWhhY2lyY2xla29yZWFuID0gMHgzMjdiOwogIHQuaGlldWhhcGFyZW5rb3JlYW4gPSAweDMyMWI7CiAgdC5oaWV1aGNpcmNsZWtvcmVhbiA9IDB4MzI2ZDsKICB0LmhpZXVoa29yZWFuID0gMHgzMTRlOwogIHQuaGlldWhwYXJlbmtvcmVhbiA9IDB4MzIwZDsKICB0LmhpaGlyYWdhbmEgPSAweDMwNzI7CiAgdC5oaWthdGFrYW5hID0gMHgzMGQyOwogIHQuaGlrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4YjsKICB0LmhpcmlxID0gMHgwNWI0OwogIHQuaGlyaXExNCA9IDB4MDViNDsKICB0LmhpcmlxMjEgPSAweDA1YjQ7CiAgdC5oaXJpcTJkID0gMHgwNWI0OwogIHQuaGlyaXFoZWJyZXcgPSAweDA1YjQ7CiAgdC5oaXJpcW5hcnJvd2hlYnJldyA9IDB4MDViNDsKICB0LmhpcmlxcXVhcnRlcmhlYnJldyA9IDB4MDViNDsKICB0Lmhpcmlxd2lkZWhlYnJldyA9IDB4MDViNDsKICB0LmhsaW5lYmVsb3cgPSAweDFlOTY7CiAgdC5obW9ub3NwYWNlID0gMHhmZjQ4OwogIHQuaG9hcm1lbmlhbiA9IDB4MDU3MDsKICB0LmhvaGlwdGhhaSA9IDB4MGUyYjsKICB0LmhvaGlyYWdhbmEgPSAweDMwN2I7CiAgdC5ob2thdGFrYW5hID0gMHgzMGRiOwogIHQuaG9rYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4ZTsKICB0LmhvbGFtID0gMHgwNWI5OwogIHQuaG9sYW0xOSA9IDB4MDViOTsKICB0LmhvbGFtMjYgPSAweDA1Yjk7CiAgdC5ob2xhbTMyID0gMHgwNWI5OwogIHQuaG9sYW1oZWJyZXcgPSAweDA1Yjk7CiAgdC5ob2xhbW5hcnJvd2hlYnJldyA9IDB4MDViOTsKICB0LmhvbGFtcXVhcnRlcmhlYnJldyA9IDB4MDViOTsKICB0LmhvbGFtd2lkZWhlYnJldyA9IDB4MDViOTsKICB0Lmhvbm9raHVrdGhhaSA9IDB4MGUyZTsKICB0Lmhvb2thYm92ZWNvbWIgPSAweDAzMDk7CiAgdC5ob29rY21iID0gMHgwMzA5OwogIHQuaG9va3BhbGF0YWxpemVkYmVsb3djbWIgPSAweDAzMjE7CiAgdC5ob29rcmV0cm9mbGV4YmVsb3djbWIgPSAweDAzMjI7CiAgdC5ob29uc3F1YXJlID0gMHgzMzQyOwogIHQuaG9yaWNvcHRpYyA9IDB4MDNlOTsKICB0Lmhvcml6b250YWxiYXIgPSAweDIwMTU7CiAgdC5ob3JuY21iID0gMHgwMzFiOwogIHQuaG90c3ByaW5ncyA9IDB4MjY2ODsKICB0LmhvdXNlID0gMHgyMzAyOwogIHQuaHBhcmVuID0gMHgyNGEzOwogIHQuaHN1cGVyaW9yID0gMHgwMmIwOwogIHQuaHR1cm5lZCA9IDB4MDI2NTsKICB0Lmh1aGlyYWdhbmEgPSAweDMwNzU7CiAgdC5odWlpdG9zcXVhcmUgPSAweDMzMzM7CiAgdC5odWthdGFrYW5hID0gMHgzMGQ1OwogIHQuaHVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4YzsKICB0Lmh1bmdhcnVtbGF1dCA9IDB4MDJkZDsKICB0Lmh1bmdhcnVtbGF1dGNtYiA9IDB4MDMwYjsKICB0Lmh2ID0gMHgwMTk1OwogIHQuaHlwaGVuID0gMHgwMDJkOwogIHQuaHlwaGVuaW5mZXJpb3IgPSAweGY2ZTU7CiAgdC5oeXBoZW5tb25vc3BhY2UgPSAweGZmMGQ7CiAgdC5oeXBoZW5zbWFsbCA9IDB4ZmU2MzsKICB0Lmh5cGhlbnN1cGVyaW9yID0gMHhmNmU2OwogIHQuaHlwaGVudHdvID0gMHgyMDEwOwogIHQuaSA9IDB4MDA2OTsKICB0LmlhY3V0ZSA9IDB4MDBlZDsKICB0LmlhY3lyaWxsaWMgPSAweDA0NGY7CiAgdC5pYmVuZ2FsaSA9IDB4MDk4NzsKICB0Lmlib3BvbW9mbyA9IDB4MzEyNzsKICB0LmlicmV2ZSA9IDB4MDEyZDsKICB0LmljYXJvbiA9IDB4MDFkMDsKICB0LmljaXJjbGUgPSAweDI0ZDg7CiAgdC5pY2lyY3VtZmxleCA9IDB4MDBlZTsKICB0LmljeXJpbGxpYyA9IDB4MDQ1NjsKICB0LmlkYmxncmF2ZSA9IDB4MDIwOTsKICB0LmlkZW9ncmFwaGVhcnRoY2lyY2xlID0gMHgzMjhmOwogIHQuaWRlb2dyYXBoZmlyZWNpcmNsZSA9IDB4MzI4YjsKICB0LmlkZW9ncmFwaGljYWxsaWFuY2VwYXJlbiA9IDB4MzIzZjsKICB0LmlkZW9ncmFwaGljY2FsbHBhcmVuID0gMHgzMjNhOwogIHQuaWRlb2dyYXBoaWNjZW50cmVjaXJjbGUgPSAweDMyYTU7CiAgdC5pZGVvZ3JhcGhpY2Nsb3NlID0gMHgzMDA2OwogIHQuaWRlb2dyYXBoaWNjb21tYSA9IDB4MzAwMTsKICB0LmlkZW9ncmFwaGljY29tbWFsZWZ0ID0gMHhmZjY0OwogIHQuaWRlb2dyYXBoaWNjb25ncmF0dWxhdGlvbnBhcmVuID0gMHgzMjM3OwogIHQuaWRlb2dyYXBoaWNjb3JyZWN0Y2lyY2xlID0gMHgzMmEzOwogIHQuaWRlb2dyYXBoaWNlYXJ0aHBhcmVuID0gMHgzMjJmOwogIHQuaWRlb2dyYXBoaWNlbnRlcnByaXNlcGFyZW4gPSAweDMyM2Q7CiAgdC5pZGVvZ3JhcGhpY2V4Y2VsbGVudGNpcmNsZSA9IDB4MzI5ZDsKICB0LmlkZW9ncmFwaGljZmVzdGl2YWxwYXJlbiA9IDB4MzI0MDsKICB0LmlkZW9ncmFwaGljZmluYW5jaWFsY2lyY2xlID0gMHgzMjk2OwogIHQuaWRlb2dyYXBoaWNmaW5hbmNpYWxwYXJlbiA9IDB4MzIzNjsKICB0LmlkZW9ncmFwaGljZmlyZXBhcmVuID0gMHgzMjJiOwogIHQuaWRlb2dyYXBoaWNoYXZlcGFyZW4gPSAweDMyMzI7CiAgdC5pZGVvZ3JhcGhpY2hpZ2hjaXJjbGUgPSAweDMyYTQ7CiAgdC5pZGVvZ3JhcGhpY2l0ZXJhdGlvbm1hcmsgPSAweDMwMDU7CiAgdC5pZGVvZ3JhcGhpY2xhYm9yY2lyY2xlID0gMHgzMjk4OwogIHQuaWRlb2dyYXBoaWNsYWJvcnBhcmVuID0gMHgzMjM4OwogIHQuaWRlb2dyYXBoaWNsZWZ0Y2lyY2xlID0gMHgzMmE3OwogIHQuaWRlb2dyYXBoaWNsb3djaXJjbGUgPSAweDMyYTY7CiAgdC5pZGVvZ3JhcGhpY21lZGljaW5lY2lyY2xlID0gMHgzMmE5OwogIHQuaWRlb2dyYXBoaWNtZXRhbHBhcmVuID0gMHgzMjJlOwogIHQuaWRlb2dyYXBoaWNtb29ucGFyZW4gPSAweDMyMmE7CiAgdC5pZGVvZ3JhcGhpY25hbWVwYXJlbiA9IDB4MzIzNDsKICB0LmlkZW9ncmFwaGljcGVyaW9kID0gMHgzMDAyOwogIHQuaWRlb2dyYXBoaWNwcmludGNpcmNsZSA9IDB4MzI5ZTsKICB0LmlkZW9ncmFwaGljcmVhY2hwYXJlbiA9IDB4MzI0MzsKICB0LmlkZW9ncmFwaGljcmVwcmVzZW50cGFyZW4gPSAweDMyMzk7CiAgdC5pZGVvZ3JhcGhpY3Jlc291cmNlcGFyZW4gPSAweDMyM2U7CiAgdC5pZGVvZ3JhcGhpY3JpZ2h0Y2lyY2xlID0gMHgzMmE4OwogIHQuaWRlb2dyYXBoaWNzZWNyZXRjaXJjbGUgPSAweDMyOTk7CiAgdC5pZGVvZ3JhcGhpY3NlbGZwYXJlbiA9IDB4MzI0MjsKICB0LmlkZW9ncmFwaGljc29jaWV0eXBhcmVuID0gMHgzMjMzOwogIHQuaWRlb2dyYXBoaWNzcGFjZSA9IDB4MzAwMDsKICB0LmlkZW9ncmFwaGljc3BlY2lhbHBhcmVuID0gMHgzMjM1OwogIHQuaWRlb2dyYXBoaWNzdG9ja3BhcmVuID0gMHgzMjMxOwogIHQuaWRlb2dyYXBoaWNzdHVkeXBhcmVuID0gMHgzMjNiOwogIHQuaWRlb2dyYXBoaWNzdW5wYXJlbiA9IDB4MzIzMDsKICB0LmlkZW9ncmFwaGljc3VwZXJ2aXNlcGFyZW4gPSAweDMyM2M7CiAgdC5pZGVvZ3JhcGhpY3dhdGVycGFyZW4gPSAweDMyMmM7CiAgdC5pZGVvZ3JhcGhpY3dvb2RwYXJlbiA9IDB4MzIyZDsKICB0LmlkZW9ncmFwaGljemVybyA9IDB4MzAwNzsKICB0LmlkZW9ncmFwaG1ldGFsY2lyY2xlID0gMHgzMjhlOwogIHQuaWRlb2dyYXBobW9vbmNpcmNsZSA9IDB4MzI4YTsKICB0LmlkZW9ncmFwaG5hbWVjaXJjbGUgPSAweDMyOTQ7CiAgdC5pZGVvZ3JhcGhzdW5jaXJjbGUgPSAweDMyOTA7CiAgdC5pZGVvZ3JhcGh3YXRlcmNpcmNsZSA9IDB4MzI4YzsKICB0LmlkZW9ncmFwaHdvb2RjaXJjbGUgPSAweDMyOGQ7CiAgdC5pZGV2YSA9IDB4MDkwNzsKICB0LmlkaWVyZXNpcyA9IDB4MDBlZjsKICB0LmlkaWVyZXNpc2FjdXRlID0gMHgxZTJmOwogIHQuaWRpZXJlc2lzY3lyaWxsaWMgPSAweDA0ZTU7CiAgdC5pZG90YmVsb3cgPSAweDFlY2I7CiAgdC5pZWJyZXZlY3lyaWxsaWMgPSAweDA0ZDc7CiAgdC5pZWN5cmlsbGljID0gMHgwNDM1OwogIHQuaWV1bmdhY2lyY2xla29yZWFuID0gMHgzMjc1OwogIHQuaWV1bmdhcGFyZW5rb3JlYW4gPSAweDMyMTU7CiAgdC5pZXVuZ2NpcmNsZWtvcmVhbiA9IDB4MzI2NzsKICB0LmlldW5na29yZWFuID0gMHgzMTQ3OwogIHQuaWV1bmdwYXJlbmtvcmVhbiA9IDB4MzIwNzsKICB0LmlncmF2ZSA9IDB4MDBlYzsKICB0LmlndWphcmF0aSA9IDB4MGE4NzsKICB0LmlndXJtdWtoaSA9IDB4MGEwNzsKICB0LmloaXJhZ2FuYSA9IDB4MzA0NDsKICB0Lmlob29rYWJvdmUgPSAweDFlYzk7CiAgdC5paWJlbmdhbGkgPSAweDA5ODg7CiAgdC5paWN5cmlsbGljID0gMHgwNDM4OwogIHQuaWlkZXZhID0gMHgwOTA4OwogIHQuaWlndWphcmF0aSA9IDB4MGE4ODsKICB0LmlpZ3VybXVraGkgPSAweDBhMDg7CiAgdC5paW1hdHJhZ3VybXVraGkgPSAweDBhNDA7CiAgdC5paW52ZXJ0ZWRicmV2ZSA9IDB4MDIwYjsKICB0Lmlpc2hvcnRjeXJpbGxpYyA9IDB4MDQzOTsKICB0Lmlpdm93ZWxzaWduYmVuZ2FsaSA9IDB4MDljMDsKICB0Lmlpdm93ZWxzaWduZGV2YSA9IDB4MDk0MDsKICB0Lmlpdm93ZWxzaWduZ3VqYXJhdGkgPSAweDBhYzA7CiAgdC5paiA9IDB4MDEzMzsKICB0LmlrYXRha2FuYSA9IDB4MzBhNDsKICB0LmlrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3MjsKICB0Lmlrb3JlYW4gPSAweDMxNjM7CiAgdC5pbGRlID0gMHgwMmRjOwogIHQuaWx1eWhlYnJldyA9IDB4MDVhYzsKICB0LmltYWNyb24gPSAweDAxMmI7CiAgdC5pbWFjcm9uY3lyaWxsaWMgPSAweDA0ZTM7CiAgdC5pbWFnZW9yYXBwcm94aW1hdGVseWVxdWFsID0gMHgyMjUzOwogIHQuaW1hdHJhZ3VybXVraGkgPSAweDBhM2Y7CiAgdC5pbW9ub3NwYWNlID0gMHhmZjQ5OwogIHQuaW5jcmVtZW50ID0gMHgyMjA2OwogIHQuaW5maW5pdHkgPSAweDIyMWU7CiAgdC5pbmlhcm1lbmlhbiA9IDB4MDU2YjsKICB0LmludGVncmFsID0gMHgyMjJiOwogIHQuaW50ZWdyYWxib3R0b20gPSAweDIzMjE7CiAgdC5pbnRlZ3JhbGJ0ID0gMHgyMzIxOwogIHQuaW50ZWdyYWxleCA9IDB4ZjhmNTsKICB0LmludGVncmFsdG9wID0gMHgyMzIwOwogIHQuaW50ZWdyYWx0cCA9IDB4MjMyMDsKICB0LmludGVyc2VjdGlvbiA9IDB4MjIyOTsKICB0LmludGlzcXVhcmUgPSAweDMzMDU7CiAgdC5pbnZidWxsZXQgPSAweDI1ZDg7CiAgdC5pbnZjaXJjbGUgPSAweDI1ZDk7CiAgdC5pbnZzbWlsZWZhY2UgPSAweDI2M2I7CiAgdC5pb2N5cmlsbGljID0gMHgwNDUxOwogIHQuaW9nb25layA9IDB4MDEyZjsKICB0LmlvdGEgPSAweDAzYjk7CiAgdC5pb3RhZGllcmVzaXMgPSAweDAzY2E7CiAgdC5pb3RhZGllcmVzaXN0b25vcyA9IDB4MDM5MDsKICB0LmlvdGFsYXRpbiA9IDB4MDI2OTsKICB0LmlvdGF0b25vcyA9IDB4MDNhZjsKICB0LmlwYXJlbiA9IDB4MjRhNDsKICB0LmlyaWd1cm11a2hpID0gMHgwYTcyOwogIHQuaXNtYWxsaGlyYWdhbmEgPSAweDMwNDM7CiAgdC5pc21hbGxrYXRha2FuYSA9IDB4MzBhMzsKICB0LmlzbWFsbGthdGFrYW5haGFsZndpZHRoID0gMHhmZjY4OwogIHQuaXNzaGFyYmVuZ2FsaSA9IDB4MDlmYTsKICB0LmlzdHJva2UgPSAweDAyNjg7CiAgdC5pc3VwZXJpb3IgPSAweGY2ZWQ7CiAgdC5pdGVyYXRpb25oaXJhZ2FuYSA9IDB4MzA5ZDsKICB0Lml0ZXJhdGlvbmthdGFrYW5hID0gMHgzMGZkOwogIHQuaXRpbGRlID0gMHgwMTI5OwogIHQuaXRpbGRlYmVsb3cgPSAweDFlMmQ7CiAgdC5pdWJvcG9tb2ZvID0gMHgzMTI5OwogIHQuaXVjeXJpbGxpYyA9IDB4MDQ0ZTsKICB0Lml2b3dlbHNpZ25iZW5nYWxpID0gMHgwOWJmOwogIHQuaXZvd2Vsc2lnbmRldmEgPSAweDA5M2Y7CiAgdC5pdm93ZWxzaWduZ3VqYXJhdGkgPSAweDBhYmY7CiAgdC5pemhpdHNhY3lyaWxsaWMgPSAweDA0NzU7CiAgdC5pemhpdHNhZGJsZ3JhdmVjeXJpbGxpYyA9IDB4MDQ3NzsKICB0LmogPSAweDAwNmE7CiAgdC5qYWFybWVuaWFuID0gMHgwNTcxOwogIHQuamFiZW5nYWxpID0gMHgwOTljOwogIHQuamFkZXZhID0gMHgwOTFjOwogIHQuamFndWphcmF0aSA9IDB4MGE5YzsKICB0LmphZ3VybXVraGkgPSAweDBhMWM7CiAgdC5qYm9wb21vZm8gPSAweDMxMTA7CiAgdC5qY2Fyb24gPSAweDAxZjA7CiAgdC5qY2lyY2xlID0gMHgyNGQ5OwogIHQuamNpcmN1bWZsZXggPSAweDAxMzU7CiAgdC5qY3Jvc3NlZHRhaWwgPSAweDAyOWQ7CiAgdC5qZG90bGVzc3N0cm9rZSA9IDB4MDI1ZjsKICB0LmplY3lyaWxsaWMgPSAweDA0NTg7CiAgdC5qZWVtYXJhYmljID0gMHgwNjJjOwogIHQuamVlbWZpbmFsYXJhYmljID0gMHhmZTllOwogIHQuamVlbWluaXRpYWxhcmFiaWMgPSAweGZlOWY7CiAgdC5qZWVtbWVkaWFsYXJhYmljID0gMHhmZWEwOwogIHQuamVoYXJhYmljID0gMHgwNjk4OwogIHQuamVoZmluYWxhcmFiaWMgPSAweGZiOGI7CiAgdC5qaGFiZW5nYWxpID0gMHgwOTlkOwogIHQuamhhZGV2YSA9IDB4MDkxZDsKICB0LmpoYWd1amFyYXRpID0gMHgwYTlkOwogIHQuamhhZ3VybXVraGkgPSAweDBhMWQ7CiAgdC5qaGVoYXJtZW5pYW4gPSAweDA1N2I7CiAgdC5qaXMgPSAweDMwMDQ7CiAgdC5qbW9ub3NwYWNlID0gMHhmZjRhOwogIHQuanBhcmVuID0gMHgyNGE1OwogIHQuanN1cGVyaW9yID0gMHgwMmIyOwogIHQuayA9IDB4MDA2YjsKICB0LmthYmFzaGtpcmN5cmlsbGljID0gMHgwNGExOwogIHQua2FiZW5nYWxpID0gMHgwOTk1OwogIHQua2FjdXRlID0gMHgxZTMxOwogIHQua2FjeXJpbGxpYyA9IDB4MDQzYTsKICB0LmthZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0OWI7CiAgdC5rYWRldmEgPSAweDA5MTU7CiAgdC5rYWYgPSAweDA1ZGI7CiAgdC5rYWZhcmFiaWMgPSAweDA2NDM7CiAgdC5rYWZkYWdlc2ggPSAweGZiM2I7CiAgdC5rYWZkYWdlc2hoZWJyZXcgPSAweGZiM2I7CiAgdC5rYWZmaW5hbGFyYWJpYyA9IDB4ZmVkYTsKICB0LmthZmhlYnJldyA9IDB4MDVkYjsKICB0LmthZmluaXRpYWxhcmFiaWMgPSAweGZlZGI7CiAgdC5rYWZtZWRpYWxhcmFiaWMgPSAweGZlZGM7CiAgdC5rYWZyYWZlaGVicmV3ID0gMHhmYjRkOwogIHQua2FndWphcmF0aSA9IDB4MGE5NTsKICB0LmthZ3VybXVraGkgPSAweDBhMTU7CiAgdC5rYWhpcmFnYW5hID0gMHgzMDRiOwogIHQua2Fob29rY3lyaWxsaWMgPSAweDA0YzQ7CiAgdC5rYWthdGFrYW5hID0gMHgzMGFiOwogIHQua2FrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3NjsKICB0LmthcHBhID0gMHgwM2JhOwogIHQua2FwcGFzeW1ib2xncmVlayA9IDB4MDNmMDsKICB0LmthcHllb3VubWlldW1rb3JlYW4gPSAweDMxNzE7CiAgdC5rYXB5ZW91bnBoaWV1cGhrb3JlYW4gPSAweDMxODQ7CiAgdC5rYXB5ZW91bnBpZXVwa29yZWFuID0gMHgzMTc4OwogIHQua2FweWVvdW5zc2FuZ3BpZXVwa29yZWFuID0gMHgzMTc5OwogIHQua2Fyb3JpaXNxdWFyZSA9IDB4MzMwZDsKICB0Lmthc2hpZGFhdXRvYXJhYmljID0gMHgwNjQwOwogIHQua2FzaGlkYWF1dG9ub3NpZGViZWFyaW5nYXJhYmljID0gMHgwNjQwOwogIHQua2FzbWFsbGthdGFrYW5hID0gMHgzMGY1OwogIHQua2FzcXVhcmUgPSAweDMzODQ7CiAgdC5rYXNyYWFyYWJpYyA9IDB4MDY1MDsKICB0Lmthc3JhdGFuYXJhYmljID0gMHgwNjRkOwogIHQua2FzdHJva2VjeXJpbGxpYyA9IDB4MDQ5ZjsKICB0LmthdGFoaXJhcHJvbG9uZ21hcmtoYWxmd2lkdGggPSAweGZmNzA7CiAgdC5rYXZlcnRpY2Fsc3Ryb2tlY3lyaWxsaWMgPSAweDA0OWQ7CiAgdC5rYm9wb21vZm8gPSAweDMxMGU7CiAgdC5rY2Fsc3F1YXJlID0gMHgzMzg5OwogIHQua2Nhcm9uID0gMHgwMWU5OwogIHQua2NlZGlsbGEgPSAweDAxMzc7CiAgdC5rY2lyY2xlID0gMHgyNGRhOwogIHQua2NvbW1hYWNjZW50ID0gMHgwMTM3OwogIHQua2RvdGJlbG93ID0gMHgxZTMzOwogIHQua2VoYXJtZW5pYW4gPSAweDA1ODQ7CiAgdC5rZWhpcmFnYW5hID0gMHgzMDUxOwogIHQua2VrYXRha2FuYSA9IDB4MzBiMTsKICB0Lmtla2F0YWthbmFoYWxmd2lkdGggPSAweGZmNzk7CiAgdC5rZW5hcm1lbmlhbiA9IDB4MDU2ZjsKICB0Lmtlc21hbGxrYXRha2FuYSA9IDB4MzBmNjsKICB0LmtncmVlbmxhbmRpYyA9IDB4MDEzODsKICB0LmtoYWJlbmdhbGkgPSAweDA5OTY7CiAgdC5raGFjeXJpbGxpYyA9IDB4MDQ0NTsKICB0LmtoYWRldmEgPSAweDA5MTY7CiAgdC5raGFndWphcmF0aSA9IDB4MGE5NjsKICB0LmtoYWd1cm11a2hpID0gMHgwYTE2OwogIHQua2hhaGFyYWJpYyA9IDB4MDYyZTsKICB0LmtoYWhmaW5hbGFyYWJpYyA9IDB4ZmVhNjsKICB0LmtoYWhpbml0aWFsYXJhYmljID0gMHhmZWE3OwogIHQua2hhaG1lZGlhbGFyYWJpYyA9IDB4ZmVhODsKICB0LmtoZWljb3B0aWMgPSAweDAzZTc7CiAgdC5raGhhZGV2YSA9IDB4MDk1OTsKICB0LmtoaGFndXJtdWtoaSA9IDB4MGE1OTsKICB0LmtoaWV1a2hhY2lyY2xla29yZWFuID0gMHgzMjc4OwogIHQua2hpZXVraGFwYXJlbmtvcmVhbiA9IDB4MzIxODsKICB0LmtoaWV1a2hjaXJjbGVrb3JlYW4gPSAweDMyNmE7CiAgdC5raGlldWtoa29yZWFuID0gMHgzMTRiOwogIHQua2hpZXVraHBhcmVua29yZWFuID0gMHgzMjBhOwogIHQua2hva2hhaXRoYWkgPSAweDBlMDI7CiAgdC5raG9raG9udGhhaSA9IDB4MGUwNTsKICB0Lmtob2todWF0dGhhaSA9IDB4MGUwMzsKICB0Lmtob2tod2FpdGhhaSA9IDB4MGUwNDsKICB0Lmtob211dHRoYWkgPSAweDBlNWI7CiAgdC5raG9vayA9IDB4MDE5OTsKICB0Lmtob3Jha2hhbmd0aGFpID0gMHgwZTA2OwogIHQua2h6c3F1YXJlID0gMHgzMzkxOwogIHQua2loaXJhZ2FuYSA9IDB4MzA0ZDsKICB0Lmtpa2F0YWthbmEgPSAweDMwYWQ7CiAgdC5raWthdGFrYW5haGFsZndpZHRoID0gMHhmZjc3OwogIHQua2lyb2d1cmFtdXNxdWFyZSA9IDB4MzMxNTsKICB0Lmtpcm9tZWV0b3J1c3F1YXJlID0gMHgzMzE2OwogIHQua2lyb3NxdWFyZSA9IDB4MzMxNDsKICB0LmtpeWVva2FjaXJjbGVrb3JlYW4gPSAweDMyNmU7CiAgdC5raXllb2thcGFyZW5rb3JlYW4gPSAweDMyMGU7CiAgdC5raXllb2tjaXJjbGVrb3JlYW4gPSAweDMyNjA7CiAgdC5raXllb2trb3JlYW4gPSAweDMxMzE7CiAgdC5raXllb2twYXJlbmtvcmVhbiA9IDB4MzIwMDsKICB0LmtpeWVva3Npb3Nrb3JlYW4gPSAweDMxMzM7CiAgdC5ramVjeXJpbGxpYyA9IDB4MDQ1YzsKICB0LmtsaW5lYmVsb3cgPSAweDFlMzU7CiAgdC5rbHNxdWFyZSA9IDB4MzM5ODsKICB0LmttY3ViZWRzcXVhcmUgPSAweDMzYTY7CiAgdC5rbW9ub3NwYWNlID0gMHhmZjRiOwogIHQua21zcXVhcmVkc3F1YXJlID0gMHgzM2EyOwogIHQua29oaXJhZ2FuYSA9IDB4MzA1MzsKICB0LmtvaG1zcXVhcmUgPSAweDMzYzA7CiAgdC5rb2thaXRoYWkgPSAweDBlMDE7CiAgdC5rb2thdGFrYW5hID0gMHgzMGIzOwogIHQua29rYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3YTsKICB0Lmtvb3Bvc3F1YXJlID0gMHgzMzFlOwogIHQua29wcGFjeXJpbGxpYyA9IDB4MDQ4MTsKICB0LmtvcmVhbnN0YW5kYXJkc3ltYm9sID0gMHgzMjdmOwogIHQua29yb25pc2NtYiA9IDB4MDM0MzsKICB0LmtwYXJlbiA9IDB4MjRhNjsKICB0LmtwYXNxdWFyZSA9IDB4MzNhYTsKICB0LmtzaWN5cmlsbGljID0gMHgwNDZmOwogIHQua3RzcXVhcmUgPSAweDMzY2Y7CiAgdC5rdHVybmVkID0gMHgwMjllOwogIHQua3VoaXJhZ2FuYSA9IDB4MzA0ZjsKICB0Lmt1a2F0YWthbmEgPSAweDMwYWY7CiAgdC5rdWthdGFrYW5haGFsZndpZHRoID0gMHhmZjc4OwogIHQua3ZzcXVhcmUgPSAweDMzYjg7CiAgdC5rd3NxdWFyZSA9IDB4MzNiZTsKICB0LmwgPSAweDAwNmM7CiAgdC5sYWJlbmdhbGkgPSAweDA5YjI7CiAgdC5sYWN1dGUgPSAweDAxM2E7CiAgdC5sYWRldmEgPSAweDA5MzI7CiAgdC5sYWd1amFyYXRpID0gMHgwYWIyOwogIHQubGFndXJtdWtoaSA9IDB4MGEzMjsKICB0Lmxha2toYW5neWFvdGhhaSA9IDB4MGU0NTsKICB0LmxhbWFsZWZmaW5hbGFyYWJpYyA9IDB4ZmVmYzsKICB0LmxhbWFsZWZoYW16YWFib3ZlZmluYWxhcmFiaWMgPSAweGZlZjg7CiAgdC5sYW1hbGVmaGFtemFhYm92ZWlzb2xhdGVkYXJhYmljID0gMHhmZWY3OwogIHQubGFtYWxlZmhhbXphYmVsb3dmaW5hbGFyYWJpYyA9IDB4ZmVmYTsKICB0LmxhbWFsZWZoYW16YWJlbG93aXNvbGF0ZWRhcmFiaWMgPSAweGZlZjk7CiAgdC5sYW1hbGVmaXNvbGF0ZWRhcmFiaWMgPSAweGZlZmI7CiAgdC5sYW1hbGVmbWFkZGFhYm92ZWZpbmFsYXJhYmljID0gMHhmZWY2OwogIHQubGFtYWxlZm1hZGRhYWJvdmVpc29sYXRlZGFyYWJpYyA9IDB4ZmVmNTsKICB0LmxhbWFyYWJpYyA9IDB4MDY0NDsKICB0LmxhbWJkYSA9IDB4MDNiYjsKICB0LmxhbWJkYXN0cm9rZSA9IDB4MDE5YjsKICB0LmxhbWVkID0gMHgwNWRjOwogIHQubGFtZWRkYWdlc2ggPSAweGZiM2M7CiAgdC5sYW1lZGRhZ2VzaGhlYnJldyA9IDB4ZmIzYzsKICB0LmxhbWVkaGVicmV3ID0gMHgwNWRjOwogIHQubGFtZmluYWxhcmFiaWMgPSAweGZlZGU7CiAgdC5sYW1oYWhpbml0aWFsYXJhYmljID0gMHhmY2NhOwogIHQubGFtaW5pdGlhbGFyYWJpYyA9IDB4ZmVkZjsKICB0LmxhbWplZW1pbml0aWFsYXJhYmljID0gMHhmY2M5OwogIHQubGFta2hhaGluaXRpYWxhcmFiaWMgPSAweGZjY2I7CiAgdC5sYW1sYW1oZWhpc29sYXRlZGFyYWJpYyA9IDB4ZmRmMjsKICB0LmxhbW1lZGlhbGFyYWJpYyA9IDB4ZmVlMDsKICB0LmxhbW1lZW1oYWhpbml0aWFsYXJhYmljID0gMHhmZDg4OwogIHQubGFtbWVlbWluaXRpYWxhcmFiaWMgPSAweGZjY2M7CiAgdC5sYXJnZWNpcmNsZSA9IDB4MjVlZjsKICB0LmxiYXIgPSAweDAxOWE7CiAgdC5sYmVsdCA9IDB4MDI2YzsKICB0Lmxib3BvbW9mbyA9IDB4MzEwYzsKICB0LmxjYXJvbiA9IDB4MDEzZTsKICB0LmxjZWRpbGxhID0gMHgwMTNjOwogIHQubGNpcmNsZSA9IDB4MjRkYjsKICB0LmxjaXJjdW1mbGV4YmVsb3cgPSAweDFlM2Q7CiAgdC5sY29tbWFhY2NlbnQgPSAweDAxM2M7CiAgdC5sZG90ID0gMHgwMTQwOwogIHQubGRvdGFjY2VudCA9IDB4MDE0MDsKICB0Lmxkb3RiZWxvdyA9IDB4MWUzNzsKICB0Lmxkb3RiZWxvd21hY3JvbiA9IDB4MWUzOTsKICB0LmxlZnRhbmdsZWFib3ZlY21iID0gMHgwMzFhOwogIHQubGVmdHRhY2tiZWxvd2NtYiA9IDB4MDMxODsKICB0Lmxlc3MgPSAweDAwM2M7CiAgdC5sZXNzZXF1YWwgPSAweDIyNjQ7CiAgdC5sZXNzZXF1YWxvcmdyZWF0ZXIgPSAweDIyZGE7CiAgdC5sZXNzbW9ub3NwYWNlID0gMHhmZjFjOwogIHQubGVzc29yZXF1aXZhbGVudCA9IDB4MjI3MjsKICB0Lmxlc3NvcmdyZWF0ZXIgPSAweDIyNzY7CiAgdC5sZXNzb3ZlcmVxdWFsID0gMHgyMjY2OwogIHQubGVzc3NtYWxsID0gMHhmZTY0OwogIHQubGV6aCA9IDB4MDI2ZTsKICB0LmxmYmxvY2sgPSAweDI1OGM7CiAgdC5saG9va3JldHJvZmxleCA9IDB4MDI2ZDsKICB0LmxpcmEgPSAweDIwYTQ7CiAgdC5saXduYXJtZW5pYW4gPSAweDA1NmM7CiAgdC5saiA9IDB4MDFjOTsKICB0LmxqZWN5cmlsbGljID0gMHgwNDU5OwogIHQubGwgPSAweGY2YzA7CiAgdC5sbGFkZXZhID0gMHgwOTMzOwogIHQubGxhZ3VqYXJhdGkgPSAweDBhYjM7CiAgdC5sbGluZWJlbG93ID0gMHgxZTNiOwogIHQubGxsYWRldmEgPSAweDA5MzQ7CiAgdC5sbHZvY2FsaWNiZW5nYWxpID0gMHgwOWUxOwogIHQubGx2b2NhbGljZGV2YSA9IDB4MDk2MTsKICB0Lmxsdm9jYWxpY3Zvd2Vsc2lnbmJlbmdhbGkgPSAweDA5ZTM7CiAgdC5sbHZvY2FsaWN2b3dlbHNpZ25kZXZhID0gMHgwOTYzOwogIHQubG1pZGRsZXRpbGRlID0gMHgwMjZiOwogIHQubG1vbm9zcGFjZSA9IDB4ZmY0YzsKICB0Lmxtc3F1YXJlID0gMHgzM2QwOwogIHQubG9jaHVsYXRoYWkgPSAweDBlMmM7CiAgdC5sb2dpY2FsYW5kID0gMHgyMjI3OwogIHQubG9naWNhbG5vdCA9IDB4MDBhYzsKICB0LmxvZ2ljYWxub3RyZXZlcnNlZCA9IDB4MjMxMDsKICB0LmxvZ2ljYWxvciA9IDB4MjIyODsKICB0LmxvbGluZ3RoYWkgPSAweDBlMjU7CiAgdC5sb25ncyA9IDB4MDE3ZjsKICB0Lmxvd2xpbmVjZW50ZXJsaW5lID0gMHhmZTRlOwogIHQubG93bGluZWNtYiA9IDB4MDMzMjsKICB0Lmxvd2xpbmVkYXNoZWQgPSAweGZlNGQ7CiAgdC5sb3plbmdlID0gMHgyNWNhOwogIHQubHBhcmVuID0gMHgyNGE3OwogIHQubHNsYXNoID0gMHgwMTQyOwogIHQubHNxdWFyZSA9IDB4MjExMzsKICB0LmxzdXBlcmlvciA9IDB4ZjZlZTsKICB0Lmx0c2hhZGUgPSAweDI1OTE7CiAgdC5sdXRoYWkgPSAweDBlMjY7CiAgdC5sdm9jYWxpY2JlbmdhbGkgPSAweDA5OGM7CiAgdC5sdm9jYWxpY2RldmEgPSAweDA5MGM7CiAgdC5sdm9jYWxpY3Zvd2Vsc2lnbmJlbmdhbGkgPSAweDA5ZTI7CiAgdC5sdm9jYWxpY3Zvd2Vsc2lnbmRldmEgPSAweDA5NjI7CiAgdC5seHNxdWFyZSA9IDB4MzNkMzsKICB0Lm0gPSAweDAwNmQ7CiAgdC5tYWJlbmdhbGkgPSAweDA5YWU7CiAgdC5tYWNyb24gPSAweDAwYWY7CiAgdC5tYWNyb25iZWxvd2NtYiA9IDB4MDMzMTsKICB0Lm1hY3JvbmNtYiA9IDB4MDMwNDsKICB0Lm1hY3Jvbmxvd21vZCA9IDB4MDJjZDsKICB0Lm1hY3Jvbm1vbm9zcGFjZSA9IDB4ZmZlMzsKICB0Lm1hY3V0ZSA9IDB4MWUzZjsKICB0Lm1hZGV2YSA9IDB4MDkyZTsKICB0Lm1hZ3VqYXJhdGkgPSAweDBhYWU7CiAgdC5tYWd1cm11a2hpID0gMHgwYTJlOwogIHQubWFoYXBha2hoZWJyZXcgPSAweDA1YTQ7CiAgdC5tYWhhcGFraGxlZnRoZWJyZXcgPSAweDA1YTQ7CiAgdC5tYWhpcmFnYW5hID0gMHgzMDdlOwogIHQubWFpY2hhdHRhd2Fsb3dsZWZ0dGhhaSA9IDB4Zjg5NTsKICB0Lm1haWNoYXR0YXdhbG93cmlnaHR0aGFpID0gMHhmODk0OwogIHQubWFpY2hhdHRhd2F0aGFpID0gMHgwZTRiOwogIHQubWFpY2hhdHRhd2F1cHBlcmxlZnR0aGFpID0gMHhmODkzOwogIHQubWFpZWtsb3dsZWZ0dGhhaSA9IDB4Zjg4YzsKICB0Lm1haWVrbG93cmlnaHR0aGFpID0gMHhmODhiOwogIHQubWFpZWt0aGFpID0gMHgwZTQ4OwogIHQubWFpZWt1cHBlcmxlZnR0aGFpID0gMHhmODhhOwogIHQubWFpaGFuYWthdGxlZnR0aGFpID0gMHhmODg0OwogIHQubWFpaGFuYWthdHRoYWkgPSAweDBlMzE7CiAgdC5tYWl0YWlraHVsZWZ0dGhhaSA9IDB4Zjg4OTsKICB0Lm1haXRhaWtodXRoYWkgPSAweDBlNDc7CiAgdC5tYWl0aG9sb3dsZWZ0dGhhaSA9IDB4Zjg4ZjsKICB0Lm1haXRob2xvd3JpZ2h0dGhhaSA9IDB4Zjg4ZTsKICB0Lm1haXRob3RoYWkgPSAweDBlNDk7CiAgdC5tYWl0aG91cHBlcmxlZnR0aGFpID0gMHhmODhkOwogIHQubWFpdHJpbG93bGVmdHRoYWkgPSAweGY4OTI7CiAgdC5tYWl0cmlsb3dyaWdodHRoYWkgPSAweGY4OTE7CiAgdC5tYWl0cml0aGFpID0gMHgwZTRhOwogIHQubWFpdHJpdXBwZXJsZWZ0dGhhaSA9IDB4Zjg5MDsKICB0Lm1haXlhbW9rdGhhaSA9IDB4MGU0NjsKICB0Lm1ha2F0YWthbmEgPSAweDMwZGU7CiAgdC5tYWthdGFrYW5haGFsZndpZHRoID0gMHhmZjhmOwogIHQubWFsZSA9IDB4MjY0MjsKICB0Lm1hbnN5b25zcXVhcmUgPSAweDMzNDc7CiAgdC5tYXFhZmhlYnJldyA9IDB4MDViZTsKICB0Lm1hcnMgPSAweDI2NDI7CiAgdC5tYXNvcmFjaXJjbGVoZWJyZXcgPSAweDA1YWY7CiAgdC5tYXNxdWFyZSA9IDB4MzM4MzsKICB0Lm1ib3BvbW9mbyA9IDB4MzEwNzsKICB0Lm1ic3F1YXJlID0gMHgzM2Q0OwogIHQubWNpcmNsZSA9IDB4MjRkYzsKICB0Lm1jdWJlZHNxdWFyZSA9IDB4MzNhNTsKICB0Lm1kb3RhY2NlbnQgPSAweDFlNDE7CiAgdC5tZG90YmVsb3cgPSAweDFlNDM7CiAgdC5tZWVtYXJhYmljID0gMHgwNjQ1OwogIHQubWVlbWZpbmFsYXJhYmljID0gMHhmZWUyOwogIHQubWVlbWluaXRpYWxhcmFiaWMgPSAweGZlZTM7CiAgdC5tZWVtbWVkaWFsYXJhYmljID0gMHhmZWU0OwogIHQubWVlbW1lZW1pbml0aWFsYXJhYmljID0gMHhmY2QxOwogIHQubWVlbW1lZW1pc29sYXRlZGFyYWJpYyA9IDB4ZmM0ODsKICB0Lm1lZXRvcnVzcXVhcmUgPSAweDMzNGQ7CiAgdC5tZWhpcmFnYW5hID0gMHgzMDgxOwogIHQubWVpemllcmFzcXVhcmUgPSAweDMzN2U7CiAgdC5tZWthdGFrYW5hID0gMHgzMGUxOwogIHQubWVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY5MjsKICB0Lm1lbSA9IDB4MDVkZTsKICB0Lm1lbWRhZ2VzaCA9IDB4ZmIzZTsKICB0Lm1lbWRhZ2VzaGhlYnJldyA9IDB4ZmIzZTsKICB0Lm1lbWhlYnJldyA9IDB4MDVkZTsKICB0Lm1lbmFybWVuaWFuID0gMHgwNTc0OwogIHQubWVya2hhaGVicmV3ID0gMHgwNWE1OwogIHQubWVya2hha2VmdWxhaGVicmV3ID0gMHgwNWE2OwogIHQubWVya2hha2VmdWxhbGVmdGhlYnJldyA9IDB4MDVhNjsKICB0Lm1lcmtoYWxlZnRoZWJyZXcgPSAweDA1YTU7CiAgdC5taG9vayA9IDB4MDI3MTsKICB0Lm1oenNxdWFyZSA9IDB4MzM5MjsKICB0Lm1pZGRsZWRvdGthdGFrYW5haGFsZndpZHRoID0gMHhmZjY1OwogIHQubWlkZG90ID0gMHgwMGI3OwogIHQubWlldW1hY2lyY2xla29yZWFuID0gMHgzMjcyOwogIHQubWlldW1hcGFyZW5rb3JlYW4gPSAweDMyMTI7CiAgdC5taWV1bWNpcmNsZWtvcmVhbiA9IDB4MzI2NDsKICB0Lm1pZXVta29yZWFuID0gMHgzMTQxOwogIHQubWlldW1wYW5zaW9za29yZWFuID0gMHgzMTcwOwogIHQubWlldW1wYXJlbmtvcmVhbiA9IDB4MzIwNDsKICB0Lm1pZXVtcGlldXBrb3JlYW4gPSAweDMxNmU7CiAgdC5taWV1bXNpb3Nrb3JlYW4gPSAweDMxNmY7CiAgdC5taWhpcmFnYW5hID0gMHgzMDdmOwogIHQubWlrYXRha2FuYSA9IDB4MzBkZjsKICB0Lm1pa2F0YWthbmFoYWxmd2lkdGggPSAweGZmOTA7CiAgdC5taW51cyA9IDB4MjIxMjsKICB0Lm1pbnVzYmVsb3djbWIgPSAweDAzMjA7CiAgdC5taW51c2NpcmNsZSA9IDB4MjI5NjsKICB0Lm1pbnVzbW9kID0gMHgwMmQ3OwogIHQubWludXNwbHVzID0gMHgyMjEzOwogIHQubWludXRlID0gMHgyMDMyOwogIHQubWlyaWJhYXJ1c3F1YXJlID0gMHgzMzRhOwogIHQubWlyaXNxdWFyZSA9IDB4MzM0OTsKICB0Lm1sb25nbGVndHVybmVkID0gMHgwMjcwOwogIHQubWxzcXVhcmUgPSAweDMzOTY7CiAgdC5tbWN1YmVkc3F1YXJlID0gMHgzM2EzOwogIHQubW1vbm9zcGFjZSA9IDB4ZmY0ZDsKICB0Lm1tc3F1YXJlZHNxdWFyZSA9IDB4MzM5ZjsKICB0Lm1vaGlyYWdhbmEgPSAweDMwODI7CiAgdC5tb2htc3F1YXJlID0gMHgzM2MxOwogIHQubW9rYXRha2FuYSA9IDB4MzBlMjsKICB0Lm1va2F0YWthbmFoYWxmd2lkdGggPSAweGZmOTM7CiAgdC5tb2xzcXVhcmUgPSAweDMzZDY7CiAgdC5tb21hdGhhaSA9IDB4MGUyMTsKICB0Lm1vdmVyc3NxdWFyZSA9IDB4MzNhNzsKICB0Lm1vdmVyc3NxdWFyZWRzcXVhcmUgPSAweDMzYTg7CiAgdC5tcGFyZW4gPSAweDI0YTg7CiAgdC5tcGFzcXVhcmUgPSAweDMzYWI7CiAgdC5tc3NxdWFyZSA9IDB4MzNiMzsKICB0Lm1zdXBlcmlvciA9IDB4ZjZlZjsKICB0Lm10dXJuZWQgPSAweDAyNmY7CiAgdC5tdSA9IDB4MDBiNTsKICB0Lm11MSA9IDB4MDBiNTsKICB0Lm11YXNxdWFyZSA9IDB4MzM4MjsKICB0Lm11Y2hncmVhdGVyID0gMHgyMjZiOwogIHQubXVjaGxlc3MgPSAweDIyNmE7CiAgdC5tdWZzcXVhcmUgPSAweDMzOGM7CiAgdC5tdWdyZWVrID0gMHgwM2JjOwogIHQubXVnc3F1YXJlID0gMHgzMzhkOwogIHQubXVoaXJhZ2FuYSA9IDB4MzA4MDsKICB0Lm11a2F0YWthbmEgPSAweDMwZTA7CiAgdC5tdWthdGFrYW5haGFsZndpZHRoID0gMHhmZjkxOwogIHQubXVsc3F1YXJlID0gMHgzMzk1OwogIHQubXVsdGlwbHkgPSAweDAwZDc7CiAgdC5tdW1zcXVhcmUgPSAweDMzOWI7CiAgdC5tdW5haGhlYnJldyA9IDB4MDVhMzsKICB0Lm11bmFobGVmdGhlYnJldyA9IDB4MDVhMzsKICB0Lm11c2ljYWxub3RlID0gMHgyNjZhOwogIHQubXVzaWNhbG5vdGVkYmwgPSAweDI2NmI7CiAgdC5tdXNpY2ZsYXRzaWduID0gMHgyNjZkOwogIHQubXVzaWNzaGFycHNpZ24gPSAweDI2NmY7CiAgdC5tdXNzcXVhcmUgPSAweDMzYjI7CiAgdC5tdXZzcXVhcmUgPSAweDMzYjY7CiAgdC5tdXdzcXVhcmUgPSAweDMzYmM7CiAgdC5tdm1lZ2FzcXVhcmUgPSAweDMzYjk7CiAgdC5tdnNxdWFyZSA9IDB4MzNiNzsKICB0Lm13bWVnYXNxdWFyZSA9IDB4MzNiZjsKICB0Lm13c3F1YXJlID0gMHgzM2JkOwogIHQubiA9IDB4MDA2ZTsKICB0Lm5hYmVuZ2FsaSA9IDB4MDlhODsKICB0Lm5hYmxhID0gMHgyMjA3OwogIHQubmFjdXRlID0gMHgwMTQ0OwogIHQubmFkZXZhID0gMHgwOTI4OwogIHQubmFndWphcmF0aSA9IDB4MGFhODsKICB0Lm5hZ3VybXVraGkgPSAweDBhMjg7CiAgdC5uYWhpcmFnYW5hID0gMHgzMDZhOwogIHQubmFrYXRha2FuYSA9IDB4MzBjYTsKICB0Lm5ha2F0YWthbmFoYWxmd2lkdGggPSAweGZmODU7CiAgdC5uYXBvc3Ryb3BoZSA9IDB4MDE0OTsKICB0Lm5hc3F1YXJlID0gMHgzMzgxOwogIHQubmJvcG9tb2ZvID0gMHgzMTBiOwogIHQubmJzcGFjZSA9IDB4MDBhMDsKICB0Lm5jYXJvbiA9IDB4MDE0ODsKICB0Lm5jZWRpbGxhID0gMHgwMTQ2OwogIHQubmNpcmNsZSA9IDB4MjRkZDsKICB0Lm5jaXJjdW1mbGV4YmVsb3cgPSAweDFlNGI7CiAgdC5uY29tbWFhY2NlbnQgPSAweDAxNDY7CiAgdC5uZG90YWNjZW50ID0gMHgxZTQ1OwogIHQubmRvdGJlbG93ID0gMHgxZTQ3OwogIHQubmVoaXJhZ2FuYSA9IDB4MzA2ZDsKICB0Lm5la2F0YWthbmEgPSAweDMwY2Q7CiAgdC5uZWthdGFrYW5haGFsZndpZHRoID0gMHhmZjg4OwogIHQubmV3c2hlcWVsc2lnbiA9IDB4MjBhYTsKICB0Lm5mc3F1YXJlID0gMHgzMzhiOwogIHQubmdhYmVuZ2FsaSA9IDB4MDk5OTsKICB0Lm5nYWRldmEgPSAweDA5MTk7CiAgdC5uZ2FndWphcmF0aSA9IDB4MGE5OTsKICB0Lm5nYWd1cm11a2hpID0gMHgwYTE5OwogIHQubmdvbmd1dGhhaSA9IDB4MGUwNzsKICB0Lm5oaXJhZ2FuYSA9IDB4MzA5MzsKICB0Lm5ob29rbGVmdCA9IDB4MDI3MjsKICB0Lm5ob29rcmV0cm9mbGV4ID0gMHgwMjczOwogIHQubmlldW5hY2lyY2xla29yZWFuID0gMHgzMjZmOwogIHQubmlldW5hcGFyZW5rb3JlYW4gPSAweDMyMGY7CiAgdC5uaWV1bmNpZXVja29yZWFuID0gMHgzMTM1OwogIHQubmlldW5jaXJjbGVrb3JlYW4gPSAweDMyNjE7CiAgdC5uaWV1bmhpZXVoa29yZWFuID0gMHgzMTM2OwogIHQubmlldW5rb3JlYW4gPSAweDMxMzQ7CiAgdC5uaWV1bnBhbnNpb3Nrb3JlYW4gPSAweDMxNjg7CiAgdC5uaWV1bnBhcmVua29yZWFuID0gMHgzMjAxOwogIHQubmlldW5zaW9za29yZWFuID0gMHgzMTY3OwogIHQubmlldW50aWtldXRrb3JlYW4gPSAweDMxNjY7CiAgdC5uaWhpcmFnYW5hID0gMHgzMDZiOwogIHQubmlrYXRha2FuYSA9IDB4MzBjYjsKICB0Lm5pa2F0YWthbmFoYWxmd2lkdGggPSAweGZmODY7CiAgdC5uaWtoYWhpdGxlZnR0aGFpID0gMHhmODk5OwogIHQubmlraGFoaXR0aGFpID0gMHgwZTRkOwogIHQubmluZSA9IDB4MDAzOTsKICB0Lm5pbmVhcmFiaWMgPSAweDA2Njk7CiAgdC5uaW5lYmVuZ2FsaSA9IDB4MDllZjsKICB0Lm5pbmVjaXJjbGUgPSAweDI0Njg7CiAgdC5uaW5lY2lyY2xlaW52ZXJzZXNhbnNzZXJpZiA9IDB4Mjc5MjsKICB0Lm5pbmVkZXZhID0gMHgwOTZmOwogIHQubmluZWd1amFyYXRpID0gMHgwYWVmOwogIHQubmluZWd1cm11a2hpID0gMHgwYTZmOwogIHQubmluZWhhY2thcmFiaWMgPSAweDA2Njk7CiAgdC5uaW5laGFuZ3pob3UgPSAweDMwMjk7CiAgdC5uaW5laWRlb2dyYXBoaWNwYXJlbiA9IDB4MzIyODsKICB0Lm5pbmVpbmZlcmlvciA9IDB4MjA4OTsKICB0Lm5pbmVtb25vc3BhY2UgPSAweGZmMTk7CiAgdC5uaW5lb2xkc3R5bGUgPSAweGY3Mzk7CiAgdC5uaW5lcGFyZW4gPSAweDI0N2M7CiAgdC5uaW5lcGVyaW9kID0gMHgyNDkwOwogIHQubmluZXBlcnNpYW4gPSAweDA2Zjk7CiAgdC5uaW5lcm9tYW4gPSAweDIxNzg7CiAgdC5uaW5lc3VwZXJpb3IgPSAweDIwNzk7CiAgdC5uaW5ldGVlbmNpcmNsZSA9IDB4MjQ3MjsKICB0Lm5pbmV0ZWVucGFyZW4gPSAweDI0ODY7CiAgdC5uaW5ldGVlbnBlcmlvZCA9IDB4MjQ5YTsKICB0Lm5pbmV0aGFpID0gMHgwZTU5OwogIHQubmogPSAweDAxY2M7CiAgdC5uamVjeXJpbGxpYyA9IDB4MDQ1YTsKICB0Lm5rYXRha2FuYSA9IDB4MzBmMzsKICB0Lm5rYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY5ZDsKICB0Lm5sZWdyaWdodGxvbmcgPSAweDAxOWU7CiAgdC5ubGluZWJlbG93ID0gMHgxZTQ5OwogIHQubm1vbm9zcGFjZSA9IDB4ZmY0ZTsKICB0Lm5tc3F1YXJlID0gMHgzMzlhOwogIHQubm5hYmVuZ2FsaSA9IDB4MDlhMzsKICB0Lm5uYWRldmEgPSAweDA5MjM7CiAgdC5ubmFndWphcmF0aSA9IDB4MGFhMzsKICB0Lm5uYWd1cm11a2hpID0gMHgwYTIzOwogIHQubm5uYWRldmEgPSAweDA5Mjk7CiAgdC5ub2hpcmFnYW5hID0gMHgzMDZlOwogIHQubm9rYXRha2FuYSA9IDB4MzBjZTsKICB0Lm5va2F0YWthbmFoYWxmd2lkdGggPSAweGZmODk7CiAgdC5ub25icmVha2luZ3NwYWNlID0gMHgwMGEwOwogIHQubm9uZW50aGFpID0gMHgwZTEzOwogIHQubm9udXRoYWkgPSAweDBlMTk7CiAgdC5ub29uYXJhYmljID0gMHgwNjQ2OwogIHQubm9vbmZpbmFsYXJhYmljID0gMHhmZWU2OwogIHQubm9vbmdodW5uYWFyYWJpYyA9IDB4MDZiYTsKICB0Lm5vb25naHVubmFmaW5hbGFyYWJpYyA9IDB4ZmI5ZjsKICB0Lm5vb25pbml0aWFsYXJhYmljID0gMHhmZWU3OwogIHQubm9vbmplZW1pbml0aWFsYXJhYmljID0gMHhmY2QyOwogIHQubm9vbmplZW1pc29sYXRlZGFyYWJpYyA9IDB4ZmM0YjsKICB0Lm5vb25tZWRpYWxhcmFiaWMgPSAweGZlZTg7CiAgdC5ub29ubWVlbWluaXRpYWxhcmFiaWMgPSAweGZjZDU7CiAgdC5ub29ubWVlbWlzb2xhdGVkYXJhYmljID0gMHhmYzRlOwogIHQubm9vbm5vb25maW5hbGFyYWJpYyA9IDB4ZmM4ZDsKICB0Lm5vdGNvbnRhaW5zID0gMHgyMjBjOwogIHQubm90ZWxlbWVudCA9IDB4MjIwOTsKICB0Lm5vdGVsZW1lbnRvZiA9IDB4MjIwOTsKICB0Lm5vdGVxdWFsID0gMHgyMjYwOwogIHQubm90Z3JlYXRlciA9IDB4MjI2ZjsKICB0Lm5vdGdyZWF0ZXJub3JlcXVhbCA9IDB4MjI3MTsKICB0Lm5vdGdyZWF0ZXJub3JsZXNzID0gMHgyMjc5OwogIHQubm90aWRlbnRpY2FsID0gMHgyMjYyOwogIHQubm90bGVzcyA9IDB4MjI2ZTsKICB0Lm5vdGxlc3Nub3JlcXVhbCA9IDB4MjI3MDsKICB0Lm5vdHBhcmFsbGVsID0gMHgyMjI2OwogIHQubm90cHJlY2VkZXMgPSAweDIyODA7CiAgdC5ub3RzdWJzZXQgPSAweDIyODQ7CiAgdC5ub3RzdWNjZWVkcyA9IDB4MjI4MTsKICB0Lm5vdHN1cGVyc2V0ID0gMHgyMjg1OwogIHQubm93YXJtZW5pYW4gPSAweDA1NzY7CiAgdC5ucGFyZW4gPSAweDI0YTk7CiAgdC5uc3NxdWFyZSA9IDB4MzNiMTsKICB0Lm5zdXBlcmlvciA9IDB4MjA3ZjsKICB0Lm50aWxkZSA9IDB4MDBmMTsKICB0Lm51ID0gMHgwM2JkOwogIHQubnVoaXJhZ2FuYSA9IDB4MzA2YzsKICB0Lm51a2F0YWthbmEgPSAweDMwY2M7CiAgdC5udWthdGFrYW5haGFsZndpZHRoID0gMHhmZjg3OwogIHQubnVrdGFiZW5nYWxpID0gMHgwOWJjOwogIHQubnVrdGFkZXZhID0gMHgwOTNjOwogIHQubnVrdGFndWphcmF0aSA9IDB4MGFiYzsKICB0Lm51a3RhZ3VybXVraGkgPSAweDBhM2M7CiAgdC5udW1iZXJzaWduID0gMHgwMDIzOwogIHQubnVtYmVyc2lnbm1vbm9zcGFjZSA9IDB4ZmYwMzsKICB0Lm51bWJlcnNpZ25zbWFsbCA9IDB4ZmU1ZjsKICB0Lm51bWVyYWxzaWduZ3JlZWsgPSAweDAzNzQ7CiAgdC5udW1lcmFsc2lnbmxvd2VyZ3JlZWsgPSAweDAzNzU7CiAgdC5udW1lcm8gPSAweDIxMTY7CiAgdC5udW4gPSAweDA1ZTA7CiAgdC5udW5kYWdlc2ggPSAweGZiNDA7CiAgdC5udW5kYWdlc2hoZWJyZXcgPSAweGZiNDA7CiAgdC5udW5oZWJyZXcgPSAweDA1ZTA7CiAgdC5udnNxdWFyZSA9IDB4MzNiNTsKICB0Lm53c3F1YXJlID0gMHgzM2JiOwogIHQubnlhYmVuZ2FsaSA9IDB4MDk5ZTsKICB0Lm55YWRldmEgPSAweDA5MWU7CiAgdC5ueWFndWphcmF0aSA9IDB4MGE5ZTsKICB0Lm55YWd1cm11a2hpID0gMHgwYTFlOwogIHQubyA9IDB4MDA2ZjsKICB0Lm9hY3V0ZSA9IDB4MDBmMzsKICB0Lm9hbmd0aGFpID0gMHgwZTJkOwogIHQub2JhcnJlZCA9IDB4MDI3NTsKICB0Lm9iYXJyZWRjeXJpbGxpYyA9IDB4MDRlOTsKICB0Lm9iYXJyZWRkaWVyZXNpc2N5cmlsbGljID0gMHgwNGViOwogIHQub2JlbmdhbGkgPSAweDA5OTM7CiAgdC5vYm9wb21vZm8gPSAweDMxMWI7CiAgdC5vYnJldmUgPSAweDAxNGY7CiAgdC5vY2FuZHJhZGV2YSA9IDB4MDkxMTsKICB0Lm9jYW5kcmFndWphcmF0aSA9IDB4MGE5MTsKICB0Lm9jYW5kcmF2b3dlbHNpZ25kZXZhID0gMHgwOTQ5OwogIHQub2NhbmRyYXZvd2Vsc2lnbmd1amFyYXRpID0gMHgwYWM5OwogIHQub2Nhcm9uID0gMHgwMWQyOwogIHQub2NpcmNsZSA9IDB4MjRkZTsKICB0Lm9jaXJjdW1mbGV4ID0gMHgwMGY0OwogIHQub2NpcmN1bWZsZXhhY3V0ZSA9IDB4MWVkMTsKICB0Lm9jaXJjdW1mbGV4ZG90YmVsb3cgPSAweDFlZDk7CiAgdC5vY2lyY3VtZmxleGdyYXZlID0gMHgxZWQzOwogIHQub2NpcmN1bWZsZXhob29rYWJvdmUgPSAweDFlZDU7CiAgdC5vY2lyY3VtZmxleHRpbGRlID0gMHgxZWQ3OwogIHQub2N5cmlsbGljID0gMHgwNDNlOwogIHQub2RibGFjdXRlID0gMHgwMTUxOwogIHQub2RibGdyYXZlID0gMHgwMjBkOwogIHQub2RldmEgPSAweDA5MTM7CiAgdC5vZGllcmVzaXMgPSAweDAwZjY7CiAgdC5vZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRlNzsKICB0Lm9kb3RiZWxvdyA9IDB4MWVjZDsKICB0Lm9lID0gMHgwMTUzOwogIHQub2Vrb3JlYW4gPSAweDMxNWE7CiAgdC5vZ29uZWsgPSAweDAyZGI7CiAgdC5vZ29uZWtjbWIgPSAweDAzMjg7CiAgdC5vZ3JhdmUgPSAweDAwZjI7CiAgdC5vZ3VqYXJhdGkgPSAweDBhOTM7CiAgdC5vaGFybWVuaWFuID0gMHgwNTg1OwogIHQub2hpcmFnYW5hID0gMHgzMDRhOwogIHQub2hvb2thYm92ZSA9IDB4MWVjZjsKICB0Lm9ob3JuID0gMHgwMWExOwogIHQub2hvcm5hY3V0ZSA9IDB4MWVkYjsKICB0Lm9ob3JuZG90YmVsb3cgPSAweDFlZTM7CiAgdC5vaG9ybmdyYXZlID0gMHgxZWRkOwogIHQub2hvcm5ob29rYWJvdmUgPSAweDFlZGY7CiAgdC5vaG9ybnRpbGRlID0gMHgxZWUxOwogIHQub2h1bmdhcnVtbGF1dCA9IDB4MDE1MTsKICB0Lm9pID0gMHgwMWEzOwogIHQub2ludmVydGVkYnJldmUgPSAweDAyMGY7CiAgdC5va2F0YWthbmEgPSAweDMwYWE7CiAgdC5va2F0YWthbmFoYWxmd2lkdGggPSAweGZmNzU7CiAgdC5va29yZWFuID0gMHgzMTU3OwogIHQub2xlaGVicmV3ID0gMHgwNWFiOwogIHQub21hY3JvbiA9IDB4MDE0ZDsKICB0Lm9tYWNyb25hY3V0ZSA9IDB4MWU1MzsKICB0Lm9tYWNyb25ncmF2ZSA9IDB4MWU1MTsKICB0Lm9tZGV2YSA9IDB4MDk1MDsKICB0Lm9tZWdhID0gMHgwM2M5OwogIHQub21lZ2ExID0gMHgwM2Q2OwogIHQub21lZ2FjeXJpbGxpYyA9IDB4MDQ2MTsKICB0Lm9tZWdhbGF0aW5jbG9zZWQgPSAweDAyNzc7CiAgdC5vbWVnYXJvdW5kY3lyaWxsaWMgPSAweDA0N2I7CiAgdC5vbWVnYXRpdGxvY3lyaWxsaWMgPSAweDA0N2Q7CiAgdC5vbWVnYXRvbm9zID0gMHgwM2NlOwogIHQub21ndWphcmF0aSA9IDB4MGFkMDsKICB0Lm9taWNyb24gPSAweDAzYmY7CiAgdC5vbWljcm9udG9ub3MgPSAweDAzY2M7CiAgdC5vbW9ub3NwYWNlID0gMHhmZjRmOwogIHQub25lID0gMHgwMDMxOwogIHQub25lYXJhYmljID0gMHgwNjYxOwogIHQub25lYmVuZ2FsaSA9IDB4MDllNzsKICB0Lm9uZWNpcmNsZSA9IDB4MjQ2MDsKICB0Lm9uZWNpcmNsZWludmVyc2VzYW5zc2VyaWYgPSAweDI3OGE7CiAgdC5vbmVkZXZhID0gMHgwOTY3OwogIHQub25lZG90ZW5sZWFkZXIgPSAweDIwMjQ7CiAgdC5vbmVlaWdodGggPSAweDIxNWI7CiAgdC5vbmVmaXR0ZWQgPSAweGY2ZGM7CiAgdC5vbmVndWphcmF0aSA9IDB4MGFlNzsKICB0Lm9uZWd1cm11a2hpID0gMHgwYTY3OwogIHQub25laGFja2FyYWJpYyA9IDB4MDY2MTsKICB0Lm9uZWhhbGYgPSAweDAwYmQ7CiAgdC5vbmVoYW5nemhvdSA9IDB4MzAyMTsKICB0Lm9uZWlkZW9ncmFwaGljcGFyZW4gPSAweDMyMjA7CiAgdC5vbmVpbmZlcmlvciA9IDB4MjA4MTsKICB0Lm9uZW1vbm9zcGFjZSA9IDB4ZmYxMTsKICB0Lm9uZW51bWVyYXRvcmJlbmdhbGkgPSAweDA5ZjQ7CiAgdC5vbmVvbGRzdHlsZSA9IDB4ZjczMTsKICB0Lm9uZXBhcmVuID0gMHgyNDc0OwogIHQub25lcGVyaW9kID0gMHgyNDg4OwogIHQub25lcGVyc2lhbiA9IDB4MDZmMTsKICB0Lm9uZXF1YXJ0ZXIgPSAweDAwYmM7CiAgdC5vbmVyb21hbiA9IDB4MjE3MDsKICB0Lm9uZXN1cGVyaW9yID0gMHgwMGI5OwogIHQub25ldGhhaSA9IDB4MGU1MTsKICB0Lm9uZXRoaXJkID0gMHgyMTUzOwogIHQub29nb25layA9IDB4MDFlYjsKICB0Lm9vZ29uZWttYWNyb24gPSAweDAxZWQ7CiAgdC5vb2d1cm11a2hpID0gMHgwYTEzOwogIHQub29tYXRyYWd1cm11a2hpID0gMHgwYTRiOwogIHQub29wZW4gPSAweDAyNTQ7CiAgdC5vcGFyZW4gPSAweDI0YWE7CiAgdC5vcGVuYnVsbGV0ID0gMHgyNWU2OwogIHQub3B0aW9uID0gMHgyMzI1OwogIHQub3JkZmVtaW5pbmUgPSAweDAwYWE7CiAgdC5vcmRtYXNjdWxpbmUgPSAweDAwYmE7CiAgdC5vcnRob2dvbmFsID0gMHgyMjFmOwogIHQub3Nob3J0ZGV2YSA9IDB4MDkxMjsKICB0Lm9zaG9ydHZvd2Vsc2lnbmRldmEgPSAweDA5NGE7CiAgdC5vc2xhc2ggPSAweDAwZjg7CiAgdC5vc2xhc2hhY3V0ZSA9IDB4MDFmZjsKICB0Lm9zbWFsbGhpcmFnYW5hID0gMHgzMDQ5OwogIHQub3NtYWxsa2F0YWthbmEgPSAweDMwYTk7CiAgdC5vc21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2YjsKICB0Lm9zdHJva2VhY3V0ZSA9IDB4MDFmZjsKICB0Lm9zdXBlcmlvciA9IDB4ZjZmMDsKICB0Lm90Y3lyaWxsaWMgPSAweDA0N2Y7CiAgdC5vdGlsZGUgPSAweDAwZjU7CiAgdC5vdGlsZGVhY3V0ZSA9IDB4MWU0ZDsKICB0Lm90aWxkZWRpZXJlc2lzID0gMHgxZTRmOwogIHQub3Vib3BvbW9mbyA9IDB4MzEyMTsKICB0Lm92ZXJsaW5lID0gMHgyMDNlOwogIHQub3ZlcmxpbmVjZW50ZXJsaW5lID0gMHhmZTRhOwogIHQub3ZlcmxpbmVjbWIgPSAweDAzMDU7CiAgdC5vdmVybGluZWRhc2hlZCA9IDB4ZmU0OTsKICB0Lm92ZXJsaW5lZGJsd2F2eSA9IDB4ZmU0YzsKICB0Lm92ZXJsaW5ld2F2eSA9IDB4ZmU0YjsKICB0Lm92ZXJzY29yZSA9IDB4MDBhZjsKICB0Lm92b3dlbHNpZ25iZW5nYWxpID0gMHgwOWNiOwogIHQub3Zvd2Vsc2lnbmRldmEgPSAweDA5NGI7CiAgdC5vdm93ZWxzaWduZ3VqYXJhdGkgPSAweDBhY2I7CiAgdC5wID0gMHgwMDcwOwogIHQucGFhbXBzc3F1YXJlID0gMHgzMzgwOwogIHQucGFhc2VudG9zcXVhcmUgPSAweDMzMmI7CiAgdC5wYWJlbmdhbGkgPSAweDA5YWE7CiAgdC5wYWN1dGUgPSAweDFlNTU7CiAgdC5wYWRldmEgPSAweDA5MmE7CiAgdC5wYWdlZG93biA9IDB4MjFkZjsKICB0LnBhZ2V1cCA9IDB4MjFkZTsKICB0LnBhZ3VqYXJhdGkgPSAweDBhYWE7CiAgdC5wYWd1cm11a2hpID0gMHgwYTJhOwogIHQucGFoaXJhZ2FuYSA9IDB4MzA3MTsKICB0LnBhaXlhbm5vaXRoYWkgPSAweDBlMmY7CiAgdC5wYWthdGFrYW5hID0gMHgzMGQxOwogIHQucGFsYXRhbGl6YXRpb25jeXJpbGxpY2NtYiA9IDB4MDQ4NDsKICB0LnBhbG9jaGthY3lyaWxsaWMgPSAweDA0YzA7CiAgdC5wYW5zaW9za29yZWFuID0gMHgzMTdmOwogIHQucGFyYWdyYXBoID0gMHgwMGI2OwogIHQucGFyYWxsZWwgPSAweDIyMjU7CiAgdC5wYXJlbmxlZnQgPSAweDAwMjg7CiAgdC5wYXJlbmxlZnRhbHRvbmVhcmFiaWMgPSAweGZkM2U7CiAgdC5wYXJlbmxlZnRidCA9IDB4ZjhlZDsKICB0LnBhcmVubGVmdGV4ID0gMHhmOGVjOwogIHQucGFyZW5sZWZ0aW5mZXJpb3IgPSAweDIwOGQ7CiAgdC5wYXJlbmxlZnRtb25vc3BhY2UgPSAweGZmMDg7CiAgdC5wYXJlbmxlZnRzbWFsbCA9IDB4ZmU1OTsKICB0LnBhcmVubGVmdHN1cGVyaW9yID0gMHgyMDdkOwogIHQucGFyZW5sZWZ0dHAgPSAweGY4ZWI7CiAgdC5wYXJlbmxlZnR2ZXJ0aWNhbCA9IDB4ZmUzNTsKICB0LnBhcmVucmlnaHQgPSAweDAwMjk7CiAgdC5wYXJlbnJpZ2h0YWx0b25lYXJhYmljID0gMHhmZDNmOwogIHQucGFyZW5yaWdodGJ0ID0gMHhmOGY4OwogIHQucGFyZW5yaWdodGV4ID0gMHhmOGY3OwogIHQucGFyZW5yaWdodGluZmVyaW9yID0gMHgyMDhlOwogIHQucGFyZW5yaWdodG1vbm9zcGFjZSA9IDB4ZmYwOTsKICB0LnBhcmVucmlnaHRzbWFsbCA9IDB4ZmU1YTsKICB0LnBhcmVucmlnaHRzdXBlcmlvciA9IDB4MjA3ZTsKICB0LnBhcmVucmlnaHR0cCA9IDB4ZjhmNjsKICB0LnBhcmVucmlnaHR2ZXJ0aWNhbCA9IDB4ZmUzNjsKICB0LnBhcnRpYWxkaWZmID0gMHgyMjAyOwogIHQucGFzZXFoZWJyZXcgPSAweDA1YzA7CiAgdC5wYXNodGFoZWJyZXcgPSAweDA1OTk7CiAgdC5wYXNxdWFyZSA9IDB4MzNhOTsKICB0LnBhdGFoID0gMHgwNWI3OwogIHQucGF0YWgxMSA9IDB4MDViNzsKICB0LnBhdGFoMWQgPSAweDA1Yjc7CiAgdC5wYXRhaDJhID0gMHgwNWI3OwogIHQucGF0YWhoZWJyZXcgPSAweDA1Yjc7CiAgdC5wYXRhaG5hcnJvd2hlYnJldyA9IDB4MDViNzsKICB0LnBhdGFocXVhcnRlcmhlYnJldyA9IDB4MDViNzsKICB0LnBhdGFod2lkZWhlYnJldyA9IDB4MDViNzsKICB0LnBhemVyaGVicmV3ID0gMHgwNWExOwogIHQucGJvcG9tb2ZvID0gMHgzMTA2OwogIHQucGNpcmNsZSA9IDB4MjRkZjsKICB0LnBkb3RhY2NlbnQgPSAweDFlNTc7CiAgdC5wZSA9IDB4MDVlNDsKICB0LnBlY3lyaWxsaWMgPSAweDA0M2Y7CiAgdC5wZWRhZ2VzaCA9IDB4ZmI0NDsKICB0LnBlZGFnZXNoaGVicmV3ID0gMHhmYjQ0OwogIHQucGVlemlzcXVhcmUgPSAweDMzM2I7CiAgdC5wZWZpbmFsZGFnZXNoaGVicmV3ID0gMHhmYjQzOwogIHQucGVoYXJhYmljID0gMHgwNjdlOwogIHQucGVoYXJtZW5pYW4gPSAweDA1N2E7CiAgdC5wZWhlYnJldyA9IDB4MDVlNDsKICB0LnBlaGZpbmFsYXJhYmljID0gMHhmYjU3OwogIHQucGVoaW5pdGlhbGFyYWJpYyA9IDB4ZmI1ODsKICB0LnBlaGlyYWdhbmEgPSAweDMwN2E7CiAgdC5wZWhtZWRpYWxhcmFiaWMgPSAweGZiNTk7CiAgdC5wZWthdGFrYW5hID0gMHgzMGRhOwogIHQucGVtaWRkbGVob29rY3lyaWxsaWMgPSAweDA0YTc7CiAgdC5wZXJhZmVoZWJyZXcgPSAweGZiNGU7CiAgdC5wZXJjZW50ID0gMHgwMDI1OwogIHQucGVyY2VudGFyYWJpYyA9IDB4MDY2YTsKICB0LnBlcmNlbnRtb25vc3BhY2UgPSAweGZmMDU7CiAgdC5wZXJjZW50c21hbGwgPSAweGZlNmE7CiAgdC5wZXJpb2QgPSAweDAwMmU7CiAgdC5wZXJpb2Rhcm1lbmlhbiA9IDB4MDU4OTsKICB0LnBlcmlvZGNlbnRlcmVkID0gMHgwMGI3OwogIHQucGVyaW9kaGFsZndpZHRoID0gMHhmZjYxOwogIHQucGVyaW9kaW5mZXJpb3IgPSAweGY2ZTc7CiAgdC5wZXJpb2Rtb25vc3BhY2UgPSAweGZmMGU7CiAgdC5wZXJpb2RzbWFsbCA9IDB4ZmU1MjsKICB0LnBlcmlvZHN1cGVyaW9yID0gMHhmNmU4OwogIHQucGVyaXNwb21lbmlncmVla2NtYiA9IDB4MDM0MjsKICB0LnBlcnBlbmRpY3VsYXIgPSAweDIyYTU7CiAgdC5wZXJ0aG91c2FuZCA9IDB4MjAzMDsKICB0LnBlc2V0YSA9IDB4MjBhNzsKICB0LnBmc3F1YXJlID0gMHgzMzhhOwogIHQucGhhYmVuZ2FsaSA9IDB4MDlhYjsKICB0LnBoYWRldmEgPSAweDA5MmI7CiAgdC5waGFndWphcmF0aSA9IDB4MGFhYjsKICB0LnBoYWd1cm11a2hpID0gMHgwYTJiOwogIHQucGhpID0gMHgwM2M2OwogIHQucGhpMSA9IDB4MDNkNTsKICB0LnBoaWV1cGhhY2lyY2xla29yZWFuID0gMHgzMjdhOwogIHQucGhpZXVwaGFwYXJlbmtvcmVhbiA9IDB4MzIxYTsKICB0LnBoaWV1cGhjaXJjbGVrb3JlYW4gPSAweDMyNmM7CiAgdC5waGlldXBoa29yZWFuID0gMHgzMTRkOwogIHQucGhpZXVwaHBhcmVua29yZWFuID0gMHgzMjBjOwogIHQucGhpbGF0aW4gPSAweDAyNzg7CiAgdC5waGludGh1dGhhaSA9IDB4MGUzYTsKICB0LnBoaXN5bWJvbGdyZWVrID0gMHgwM2Q1OwogIHQucGhvb2sgPSAweDAxYTU7CiAgdC5waG9waGFudGhhaSA9IDB4MGUxZTsKICB0LnBob3BodW5ndGhhaSA9IDB4MGUxYzsKICB0LnBob3NhbXBoYW90aGFpID0gMHgwZTIwOwogIHQucGkgPSAweDAzYzA7CiAgdC5waWV1cGFjaXJjbGVrb3JlYW4gPSAweDMyNzM7CiAgdC5waWV1cGFwYXJlbmtvcmVhbiA9IDB4MzIxMzsKICB0LnBpZXVwY2lldWNrb3JlYW4gPSAweDMxNzY7CiAgdC5waWV1cGNpcmNsZWtvcmVhbiA9IDB4MzI2NTsKICB0LnBpZXVwa2l5ZW9ra29yZWFuID0gMHgzMTcyOwogIHQucGlldXBrb3JlYW4gPSAweDMxNDI7CiAgdC5waWV1cHBhcmVua29yZWFuID0gMHgzMjA1OwogIHQucGlldXBzaW9za2l5ZW9ra29yZWFuID0gMHgzMTc0OwogIHQucGlldXBzaW9za29yZWFuID0gMHgzMTQ0OwogIHQucGlldXBzaW9zdGlrZXV0a29yZWFuID0gMHgzMTc1OwogIHQucGlldXB0aGlldXRoa29yZWFuID0gMHgzMTc3OwogIHQucGlldXB0aWtldXRrb3JlYW4gPSAweDMxNzM7CiAgdC5waWhpcmFnYW5hID0gMHgzMDc0OwogIHQucGlrYXRha2FuYSA9IDB4MzBkNDsKICB0LnBpc3ltYm9sZ3JlZWsgPSAweDAzZDY7CiAgdC5waXdyYXJtZW5pYW4gPSAweDA1ODM7CiAgdC5wbGFuY2tvdmVyMnBpID0gMHgyMTBmOwogIHQucGxhbmNrb3ZlcjJwaTEgPSAweDIxMGY7CiAgdC5wbHVzID0gMHgwMDJiOwogIHQucGx1c2JlbG93Y21iID0gMHgwMzFmOwogIHQucGx1c2NpcmNsZSA9IDB4MjI5NTsKICB0LnBsdXNtaW51cyA9IDB4MDBiMTsKICB0LnBsdXNtb2QgPSAweDAyZDY7CiAgdC5wbHVzbW9ub3NwYWNlID0gMHhmZjBiOwogIHQucGx1c3NtYWxsID0gMHhmZTYyOwogIHQucGx1c3N1cGVyaW9yID0gMHgyMDdhOwogIHQucG1vbm9zcGFjZSA9IDB4ZmY1MDsKICB0LnBtc3F1YXJlID0gMHgzM2Q4OwogIHQucG9oaXJhZ2FuYSA9IDB4MzA3ZDsKICB0LnBvaW50aW5naW5kZXhkb3dud2hpdGUgPSAweDI2MWY7CiAgdC5wb2ludGluZ2luZGV4bGVmdHdoaXRlID0gMHgyNjFjOwogIHQucG9pbnRpbmdpbmRleHJpZ2h0d2hpdGUgPSAweDI2MWU7CiAgdC5wb2ludGluZ2luZGV4dXB3aGl0ZSA9IDB4MjYxZDsKICB0LnBva2F0YWthbmEgPSAweDMwZGQ7CiAgdC5wb3BsYXRoYWkgPSAweDBlMWI7CiAgdC5wb3N0YWxtYXJrID0gMHgzMDEyOwogIHQucG9zdGFsbWFya2ZhY2UgPSAweDMwMjA7CiAgdC5wcGFyZW4gPSAweDI0YWI7CiAgdC5wcmVjZWRlcyA9IDB4MjI3YTsKICB0LnByZXNjcmlwdGlvbiA9IDB4MjExZTsKICB0LnByaW1lbW9kID0gMHgwMmI5OwogIHQucHJpbWVyZXZlcnNlZCA9IDB4MjAzNTsKICB0LnByb2R1Y3QgPSAweDIyMGY7CiAgdC5wcm9qZWN0aXZlID0gMHgyMzA1OwogIHQucHJvbG9uZ2Vka2FuYSA9IDB4MzBmYzsKICB0LnByb3BlbGxvciA9IDB4MjMxODsKICB0LnByb3BlcnN1YnNldCA9IDB4MjI4MjsKICB0LnByb3BlcnN1cGVyc2V0ID0gMHgyMjgzOwogIHQucHJvcG9ydGlvbiA9IDB4MjIzNzsKICB0LnByb3BvcnRpb25hbCA9IDB4MjIxZDsKICB0LnBzaSA9IDB4MDNjODsKICB0LnBzaWN5cmlsbGljID0gMHgwNDcxOwogIHQucHNpbGlwbmV1bWF0YWN5cmlsbGljY21iID0gMHgwNDg2OwogIHQucHNzcXVhcmUgPSAweDMzYjA7CiAgdC5wdWhpcmFnYW5hID0gMHgzMDc3OwogIHQucHVrYXRha2FuYSA9IDB4MzBkNzsKICB0LnB2c3F1YXJlID0gMHgzM2I0OwogIHQucHdzcXVhcmUgPSAweDMzYmE7CiAgdC5xID0gMHgwMDcxOwogIHQucWFkZXZhID0gMHgwOTU4OwogIHQucWFkbWFoZWJyZXcgPSAweDA1YTg7CiAgdC5xYWZhcmFiaWMgPSAweDA2NDI7CiAgdC5xYWZmaW5hbGFyYWJpYyA9IDB4ZmVkNjsKICB0LnFhZmluaXRpYWxhcmFiaWMgPSAweGZlZDc7CiAgdC5xYWZtZWRpYWxhcmFiaWMgPSAweGZlZDg7CiAgdC5xYW1hdHMgPSAweDA1Yjg7CiAgdC5xYW1hdHMxMCA9IDB4MDViODsKICB0LnFhbWF0czFhID0gMHgwNWI4OwogIHQucWFtYXRzMWMgPSAweDA1Yjg7CiAgdC5xYW1hdHMyNyA9IDB4MDViODsKICB0LnFhbWF0czI5ID0gMHgwNWI4OwogIHQucWFtYXRzMzMgPSAweDA1Yjg7CiAgdC5xYW1hdHNkZSA9IDB4MDViODsKICB0LnFhbWF0c2hlYnJldyA9IDB4MDViODsKICB0LnFhbWF0c25hcnJvd2hlYnJldyA9IDB4MDViODsKICB0LnFhbWF0c3FhdGFuaGVicmV3ID0gMHgwNWI4OwogIHQucWFtYXRzcWF0YW5uYXJyb3doZWJyZXcgPSAweDA1Yjg7CiAgdC5xYW1hdHNxYXRhbnF1YXJ0ZXJoZWJyZXcgPSAweDA1Yjg7CiAgdC5xYW1hdHNxYXRhbndpZGVoZWJyZXcgPSAweDA1Yjg7CiAgdC5xYW1hdHNxdWFydGVyaGVicmV3ID0gMHgwNWI4OwogIHQucWFtYXRzd2lkZWhlYnJldyA9IDB4MDViODsKICB0LnFhcm5leXBhcmFoZWJyZXcgPSAweDA1OWY7CiAgdC5xYm9wb21vZm8gPSAweDMxMTE7CiAgdC5xY2lyY2xlID0gMHgyNGUwOwogIHQucWhvb2sgPSAweDAyYTA7CiAgdC5xbW9ub3NwYWNlID0gMHhmZjUxOwogIHQucW9mID0gMHgwNWU3OwogIHQucW9mZGFnZXNoID0gMHhmYjQ3OwogIHQucW9mZGFnZXNoaGVicmV3ID0gMHhmYjQ3OwogIHQucW9maGVicmV3ID0gMHgwNWU3OwogIHQucXBhcmVuID0gMHgyNGFjOwogIHQucXVhcnRlcm5vdGUgPSAweDI2Njk7CiAgdC5xdWJ1dHMgPSAweDA1YmI7CiAgdC5xdWJ1dHMxOCA9IDB4MDViYjsKICB0LnF1YnV0czI1ID0gMHgwNWJiOwogIHQucXVidXRzMzEgPSAweDA1YmI7CiAgdC5xdWJ1dHNoZWJyZXcgPSAweDA1YmI7CiAgdC5xdWJ1dHNuYXJyb3doZWJyZXcgPSAweDA1YmI7CiAgdC5xdWJ1dHNxdWFydGVyaGVicmV3ID0gMHgwNWJiOwogIHQucXVidXRzd2lkZWhlYnJldyA9IDB4MDViYjsKICB0LnF1ZXN0aW9uID0gMHgwMDNmOwogIHQucXVlc3Rpb25hcmFiaWMgPSAweDA2MWY7CiAgdC5xdWVzdGlvbmFybWVuaWFuID0gMHgwNTVlOwogIHQucXVlc3Rpb25kb3duID0gMHgwMGJmOwogIHQucXVlc3Rpb25kb3duc21hbGwgPSAweGY3YmY7CiAgdC5xdWVzdGlvbmdyZWVrID0gMHgwMzdlOwogIHQucXVlc3Rpb25tb25vc3BhY2UgPSAweGZmMWY7CiAgdC5xdWVzdGlvbnNtYWxsID0gMHhmNzNmOwogIHQucXVvdGVkYmwgPSAweDAwMjI7CiAgdC5xdW90ZWRibGJhc2UgPSAweDIwMWU7CiAgdC5xdW90ZWRibGxlZnQgPSAweDIwMWM7CiAgdC5xdW90ZWRibG1vbm9zcGFjZSA9IDB4ZmYwMjsKICB0LnF1b3RlZGJscHJpbWUgPSAweDMwMWU7CiAgdC5xdW90ZWRibHByaW1lcmV2ZXJzZWQgPSAweDMwMWQ7CiAgdC5xdW90ZWRibHJpZ2h0ID0gMHgyMDFkOwogIHQucXVvdGVsZWZ0ID0gMHgyMDE4OwogIHQucXVvdGVsZWZ0cmV2ZXJzZWQgPSAweDIwMWI7CiAgdC5xdW90ZXJldmVyc2VkID0gMHgyMDFiOwogIHQucXVvdGVyaWdodCA9IDB4MjAxOTsKICB0LnF1b3RlcmlnaHRuID0gMHgwMTQ5OwogIHQucXVvdGVzaW5nbGJhc2UgPSAweDIwMWE7CiAgdC5xdW90ZXNpbmdsZSA9IDB4MDAyNzsKICB0LnF1b3Rlc2luZ2xlbW9ub3NwYWNlID0gMHhmZjA3OwogIHQuciA9IDB4MDA3MjsKICB0LnJhYXJtZW5pYW4gPSAweDA1N2M7CiAgdC5yYWJlbmdhbGkgPSAweDA5YjA7CiAgdC5yYWN1dGUgPSAweDAxNTU7CiAgdC5yYWRldmEgPSAweDA5MzA7CiAgdC5yYWRpY2FsID0gMHgyMjFhOwogIHQucmFkaWNhbGV4ID0gMHhmOGU1OwogIHQucmFkb3ZlcnNzcXVhcmUgPSAweDMzYWU7CiAgdC5yYWRvdmVyc3NxdWFyZWRzcXVhcmUgPSAweDMzYWY7CiAgdC5yYWRzcXVhcmUgPSAweDMzYWQ7CiAgdC5yYWZlID0gMHgwNWJmOwogIHQucmFmZWhlYnJldyA9IDB4MDViZjsKICB0LnJhZ3VqYXJhdGkgPSAweDBhYjA7CiAgdC5yYWd1cm11a2hpID0gMHgwYTMwOwogIHQucmFoaXJhZ2FuYSA9IDB4MzA4OTsKICB0LnJha2F0YWthbmEgPSAweDMwZTk7CiAgdC5yYWthdGFrYW5haGFsZndpZHRoID0gMHhmZjk3OwogIHQucmFsb3dlcmRpYWdvbmFsYmVuZ2FsaSA9IDB4MDlmMTsKICB0LnJhbWlkZGxlZGlhZ29uYWxiZW5nYWxpID0gMHgwOWYwOwogIHQucmFtc2hvcm4gPSAweDAyNjQ7CiAgdC5yYXRpbyA9IDB4MjIzNjsKICB0LnJib3BvbW9mbyA9IDB4MzExNjsKICB0LnJjYXJvbiA9IDB4MDE1OTsKICB0LnJjZWRpbGxhID0gMHgwMTU3OwogIHQucmNpcmNsZSA9IDB4MjRlMTsKICB0LnJjb21tYWFjY2VudCA9IDB4MDE1NzsKICB0LnJkYmxncmF2ZSA9IDB4MDIxMTsKICB0LnJkb3RhY2NlbnQgPSAweDFlNTk7CiAgdC5yZG90YmVsb3cgPSAweDFlNWI7CiAgdC5yZG90YmVsb3dtYWNyb24gPSAweDFlNWQ7CiAgdC5yZWZlcmVuY2VtYXJrID0gMHgyMDNiOwogIHQucmVmbGV4c3Vic2V0ID0gMHgyMjg2OwogIHQucmVmbGV4c3VwZXJzZXQgPSAweDIyODc7CiAgdC5yZWdpc3RlcmVkID0gMHgwMGFlOwogIHQucmVnaXN0ZXJzYW5zID0gMHhmOGU4OwogIHQucmVnaXN0ZXJzZXJpZiA9IDB4ZjZkYTsKICB0LnJlaGFyYWJpYyA9IDB4MDYzMTsKICB0LnJlaGFybWVuaWFuID0gMHgwNTgwOwogIHQucmVoZmluYWxhcmFiaWMgPSAweGZlYWU7CiAgdC5yZWhpcmFnYW5hID0gMHgzMDhjOwogIHQucmVrYXRha2FuYSA9IDB4MzBlYzsKICB0LnJla2F0YWthbmFoYWxmd2lkdGggPSAweGZmOWE7CiAgdC5yZXNoID0gMHgwNWU4OwogIHQucmVzaGRhZ2VzaGhlYnJldyA9IDB4ZmI0ODsKICB0LnJlc2hoZWJyZXcgPSAweDA1ZTg7CiAgdC5yZXZlcnNlZHRpbGRlID0gMHgyMjNkOwogIHQucmV2aWFoZWJyZXcgPSAweDA1OTc7CiAgdC5yZXZpYW11Z3Jhc2hoZWJyZXcgPSAweDA1OTc7CiAgdC5yZXZsb2dpY2Fsbm90ID0gMHgyMzEwOwogIHQucmZpc2hob29rID0gMHgwMjdlOwogIHQucmZpc2hob29rcmV2ZXJzZWQgPSAweDAyN2Y7CiAgdC5yaGFiZW5nYWxpID0gMHgwOWRkOwogIHQucmhhZGV2YSA9IDB4MDk1ZDsKICB0LnJobyA9IDB4MDNjMTsKICB0LnJob29rID0gMHgwMjdkOwogIHQucmhvb2t0dXJuZWQgPSAweDAyN2I7CiAgdC5yaG9va3R1cm5lZHN1cGVyaW9yID0gMHgwMmI1OwogIHQucmhvc3ltYm9sZ3JlZWsgPSAweDAzZjE7CiAgdC5yaG90aWNob29rbW9kID0gMHgwMmRlOwogIHQucmlldWxhY2lyY2xla29yZWFuID0gMHgzMjcxOwogIHQucmlldWxhcGFyZW5rb3JlYW4gPSAweDMyMTE7CiAgdC5yaWV1bGNpcmNsZWtvcmVhbiA9IDB4MzI2MzsKICB0LnJpZXVsaGlldWhrb3JlYW4gPSAweDMxNDA7CiAgdC5yaWV1bGtpeWVva2tvcmVhbiA9IDB4MzEzYTsKICB0LnJpZXVsa2l5ZW9rc2lvc2tvcmVhbiA9IDB4MzE2OTsKICB0LnJpZXVsa29yZWFuID0gMHgzMTM5OwogIHQucmlldWxtaWV1bWtvcmVhbiA9IDB4MzEzYjsKICB0LnJpZXVscGFuc2lvc2tvcmVhbiA9IDB4MzE2YzsKICB0LnJpZXVscGFyZW5rb3JlYW4gPSAweDMyMDM7CiAgdC5yaWV1bHBoaWV1cGhrb3JlYW4gPSAweDMxM2Y7CiAgdC5yaWV1bHBpZXVwa29yZWFuID0gMHgzMTNjOwogIHQucmlldWxwaWV1cHNpb3Nrb3JlYW4gPSAweDMxNmI7CiAgdC5yaWV1bHNpb3Nrb3JlYW4gPSAweDMxM2Q7CiAgdC5yaWV1bHRoaWV1dGhrb3JlYW4gPSAweDMxM2U7CiAgdC5yaWV1bHRpa2V1dGtvcmVhbiA9IDB4MzE2YTsKICB0LnJpZXVseWVvcmluaGlldWhrb3JlYW4gPSAweDMxNmQ7CiAgdC5yaWdodGFuZ2xlID0gMHgyMjFmOwogIHQucmlnaHR0YWNrYmVsb3djbWIgPSAweDAzMTk7CiAgdC5yaWdodHRyaWFuZ2xlID0gMHgyMmJmOwogIHQucmloaXJhZ2FuYSA9IDB4MzA4YTsKICB0LnJpa2F0YWthbmEgPSAweDMwZWE7CiAgdC5yaWthdGFrYW5haGFsZndpZHRoID0gMHhmZjk4OwogIHQucmluZyA9IDB4MDJkYTsKICB0LnJpbmdiZWxvd2NtYiA9IDB4MDMyNTsKICB0LnJpbmdjbWIgPSAweDAzMGE7CiAgdC5yaW5naGFsZmxlZnQgPSAweDAyYmY7CiAgdC5yaW5naGFsZmxlZnRhcm1lbmlhbiA9IDB4MDU1OTsKICB0LnJpbmdoYWxmbGVmdGJlbG93Y21iID0gMHgwMzFjOwogIHQucmluZ2hhbGZsZWZ0Y2VudGVyZWQgPSAweDAyZDM7CiAgdC5yaW5naGFsZnJpZ2h0ID0gMHgwMmJlOwogIHQucmluZ2hhbGZyaWdodGJlbG93Y21iID0gMHgwMzM5OwogIHQucmluZ2hhbGZyaWdodGNlbnRlcmVkID0gMHgwMmQyOwogIHQucmludmVydGVkYnJldmUgPSAweDAyMTM7CiAgdC5yaXR0b3J1c3F1YXJlID0gMHgzMzUxOwogIHQucmxpbmViZWxvdyA9IDB4MWU1ZjsKICB0LnJsb25nbGVnID0gMHgwMjdjOwogIHQucmxvbmdsZWd0dXJuZWQgPSAweDAyN2E7CiAgdC5ybW9ub3NwYWNlID0gMHhmZjUyOwogIHQucm9oaXJhZ2FuYSA9IDB4MzA4ZDsKICB0LnJva2F0YWthbmEgPSAweDMwZWQ7CiAgdC5yb2thdGFrYW5haGFsZndpZHRoID0gMHhmZjliOwogIHQucm9ydWF0aGFpID0gMHgwZTIzOwogIHQucnBhcmVuID0gMHgyNGFkOwogIHQucnJhYmVuZ2FsaSA9IDB4MDlkYzsKICB0LnJyYWRldmEgPSAweDA5MzE7CiAgdC5ycmFndXJtdWtoaSA9IDB4MGE1YzsKICB0LnJyZWhhcmFiaWMgPSAweDA2OTE7CiAgdC5ycmVoZmluYWxhcmFiaWMgPSAweGZiOGQ7CiAgdC5ycnZvY2FsaWNiZW5nYWxpID0gMHgwOWUwOwogIHQucnJ2b2NhbGljZGV2YSA9IDB4MDk2MDsKICB0LnJydm9jYWxpY2d1amFyYXRpID0gMHgwYWUwOwogIHQucnJ2b2NhbGljdm93ZWxzaWduYmVuZ2FsaSA9IDB4MDljNDsKICB0LnJydm9jYWxpY3Zvd2Vsc2lnbmRldmEgPSAweDA5NDQ7CiAgdC5ycnZvY2FsaWN2b3dlbHNpZ25ndWphcmF0aSA9IDB4MGFjNDsKICB0LnJzdXBlcmlvciA9IDB4ZjZmMTsKICB0LnJ0YmxvY2sgPSAweDI1OTA7CiAgdC5ydHVybmVkID0gMHgwMjc5OwogIHQucnR1cm5lZHN1cGVyaW9yID0gMHgwMmI0OwogIHQucnVoaXJhZ2FuYSA9IDB4MzA4YjsKICB0LnJ1a2F0YWthbmEgPSAweDMwZWI7CiAgdC5ydWthdGFrYW5haGFsZndpZHRoID0gMHhmZjk5OwogIHQucnVwZWVtYXJrYmVuZ2FsaSA9IDB4MDlmMjsKICB0LnJ1cGVlc2lnbmJlbmdhbGkgPSAweDA5ZjM7CiAgdC5ydXBpYWggPSAweGY2ZGQ7CiAgdC5ydXRoYWkgPSAweDBlMjQ7CiAgdC5ydm9jYWxpY2JlbmdhbGkgPSAweDA5OGI7CiAgdC5ydm9jYWxpY2RldmEgPSAweDA5MGI7CiAgdC5ydm9jYWxpY2d1amFyYXRpID0gMHgwYThiOwogIHQucnZvY2FsaWN2b3dlbHNpZ25iZW5nYWxpID0gMHgwOWMzOwogIHQucnZvY2FsaWN2b3dlbHNpZ25kZXZhID0gMHgwOTQzOwogIHQucnZvY2FsaWN2b3dlbHNpZ25ndWphcmF0aSA9IDB4MGFjMzsKICB0LnMgPSAweDAwNzM7CiAgdC5zYWJlbmdhbGkgPSAweDA5Yjg7CiAgdC5zYWN1dGUgPSAweDAxNWI7CiAgdC5zYWN1dGVkb3RhY2NlbnQgPSAweDFlNjU7CiAgdC5zYWRhcmFiaWMgPSAweDA2MzU7CiAgdC5zYWRldmEgPSAweDA5Mzg7CiAgdC5zYWRmaW5hbGFyYWJpYyA9IDB4ZmViYTsKICB0LnNhZGluaXRpYWxhcmFiaWMgPSAweGZlYmI7CiAgdC5zYWRtZWRpYWxhcmFiaWMgPSAweGZlYmM7CiAgdC5zYWd1amFyYXRpID0gMHgwYWI4OwogIHQuc2FndXJtdWtoaSA9IDB4MGEzODsKICB0LnNhaGlyYWdhbmEgPSAweDMwNTU7CiAgdC5zYWthdGFrYW5hID0gMHgzMGI1OwogIHQuc2FrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3YjsKICB0LnNhbGxhbGxhaG91YWxheWhld2FzYWxsYW1hcmFiaWMgPSAweGZkZmE7CiAgdC5zYW1la2ggPSAweDA1ZTE7CiAgdC5zYW1la2hkYWdlc2ggPSAweGZiNDE7CiAgdC5zYW1la2hkYWdlc2hoZWJyZXcgPSAweGZiNDE7CiAgdC5zYW1la2hoZWJyZXcgPSAweDA1ZTE7CiAgdC5zYXJhYWF0aGFpID0gMHgwZTMyOwogIHQuc2FyYWFldGhhaSA9IDB4MGU0MTsKICB0LnNhcmFhaW1haW1hbGFpdGhhaSA9IDB4MGU0NDsKICB0LnNhcmFhaW1haW11YW50aGFpID0gMHgwZTQzOwogIHQuc2FyYWFtdGhhaSA9IDB4MGUzMzsKICB0LnNhcmFhdGhhaSA9IDB4MGUzMDsKICB0LnNhcmFldGhhaSA9IDB4MGU0MDsKICB0LnNhcmFpaWxlZnR0aGFpID0gMHhmODg2OwogIHQuc2FyYWlpdGhhaSA9IDB4MGUzNTsKICB0LnNhcmFpbGVmdHRoYWkgPSAweGY4ODU7CiAgdC5zYXJhaXRoYWkgPSAweDBlMzQ7CiAgdC5zYXJhb3RoYWkgPSAweDBlNDI7CiAgdC5zYXJhdWVlbGVmdHRoYWkgPSAweGY4ODg7CiAgdC5zYXJhdWVldGhhaSA9IDB4MGUzNzsKICB0LnNhcmF1ZWxlZnR0aGFpID0gMHhmODg3OwogIHQuc2FyYXVldGhhaSA9IDB4MGUzNjsKICB0LnNhcmF1dGhhaSA9IDB4MGUzODsKICB0LnNhcmF1dXRoYWkgPSAweDBlMzk7CiAgdC5zYm9wb21vZm8gPSAweDMxMTk7CiAgdC5zY2Fyb24gPSAweDAxNjE7CiAgdC5zY2Fyb25kb3RhY2NlbnQgPSAweDFlNjc7CiAgdC5zY2VkaWxsYSA9IDB4MDE1ZjsKICB0LnNjaHdhID0gMHgwMjU5OwogIHQuc2Nod2FjeXJpbGxpYyA9IDB4MDRkOTsKICB0LnNjaHdhZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRkYjsKICB0LnNjaHdhaG9vayA9IDB4MDI1YTsKICB0LnNjaXJjbGUgPSAweDI0ZTI7CiAgdC5zY2lyY3VtZmxleCA9IDB4MDE1ZDsKICB0LnNjb21tYWFjY2VudCA9IDB4MDIxOTsKICB0LnNkb3RhY2NlbnQgPSAweDFlNjE7CiAgdC5zZG90YmVsb3cgPSAweDFlNjM7CiAgdC5zZG90YmVsb3dkb3RhY2NlbnQgPSAweDFlNjk7CiAgdC5zZWFndWxsYmVsb3djbWIgPSAweDAzM2M7CiAgdC5zZWNvbmQgPSAweDIwMzM7CiAgdC5zZWNvbmR0b25lY2hpbmVzZSA9IDB4MDJjYTsKICB0LnNlY3Rpb24gPSAweDAwYTc7CiAgdC5zZWVuYXJhYmljID0gMHgwNjMzOwogIHQuc2VlbmZpbmFsYXJhYmljID0gMHhmZWIyOwogIHQuc2VlbmluaXRpYWxhcmFiaWMgPSAweGZlYjM7CiAgdC5zZWVubWVkaWFsYXJhYmljID0gMHhmZWI0OwogIHQuc2Vnb2wgPSAweDA1YjY7CiAgdC5zZWdvbDEzID0gMHgwNWI2OwogIHQuc2Vnb2wxZiA9IDB4MDViNjsKICB0LnNlZ29sMmMgPSAweDA1YjY7CiAgdC5zZWdvbGhlYnJldyA9IDB4MDViNjsKICB0LnNlZ29sbmFycm93aGVicmV3ID0gMHgwNWI2OwogIHQuc2Vnb2xxdWFydGVyaGVicmV3ID0gMHgwNWI2OwogIHQuc2Vnb2x0YWhlYnJldyA9IDB4MDU5MjsKICB0LnNlZ29sd2lkZWhlYnJldyA9IDB4MDViNjsKICB0LnNlaGFybWVuaWFuID0gMHgwNTdkOwogIHQuc2VoaXJhZ2FuYSA9IDB4MzA1YjsKICB0LnNla2F0YWthbmEgPSAweDMwYmI7CiAgdC5zZWthdGFrYW5haGFsZndpZHRoID0gMHhmZjdlOwogIHQuc2VtaWNvbG9uID0gMHgwMDNiOwogIHQuc2VtaWNvbG9uYXJhYmljID0gMHgwNjFiOwogIHQuc2VtaWNvbG9ubW9ub3NwYWNlID0gMHhmZjFiOwogIHQuc2VtaWNvbG9uc21hbGwgPSAweGZlNTQ7CiAgdC5zZW1pdm9pY2VkbWFya2thbmEgPSAweDMwOWM7CiAgdC5zZW1pdm9pY2VkbWFya2thbmFoYWxmd2lkdGggPSAweGZmOWY7CiAgdC5zZW50aXNxdWFyZSA9IDB4MzMyMjsKICB0LnNlbnRvc3F1YXJlID0gMHgzMzIzOwogIHQuc2V2ZW4gPSAweDAwMzc7CiAgdC5zZXZlbmFyYWJpYyA9IDB4MDY2NzsKICB0LnNldmVuYmVuZ2FsaSA9IDB4MDllZDsKICB0LnNldmVuY2lyY2xlID0gMHgyNDY2OwogIHQuc2V2ZW5jaXJjbGVpbnZlcnNlc2Fuc3NlcmlmID0gMHgyNzkwOwogIHQuc2V2ZW5kZXZhID0gMHgwOTZkOwogIHQuc2V2ZW5laWdodGhzID0gMHgyMTVlOwogIHQuc2V2ZW5ndWphcmF0aSA9IDB4MGFlZDsKICB0LnNldmVuZ3VybXVraGkgPSAweDBhNmQ7CiAgdC5zZXZlbmhhY2thcmFiaWMgPSAweDA2Njc7CiAgdC5zZXZlbmhhbmd6aG91ID0gMHgzMDI3OwogIHQuc2V2ZW5pZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjI2OwogIHQuc2V2ZW5pbmZlcmlvciA9IDB4MjA4NzsKICB0LnNldmVubW9ub3NwYWNlID0gMHhmZjE3OwogIHQuc2V2ZW5vbGRzdHlsZSA9IDB4ZjczNzsKICB0LnNldmVucGFyZW4gPSAweDI0N2E7CiAgdC5zZXZlbnBlcmlvZCA9IDB4MjQ4ZTsKICB0LnNldmVucGVyc2lhbiA9IDB4MDZmNzsKICB0LnNldmVucm9tYW4gPSAweDIxNzY7CiAgdC5zZXZlbnN1cGVyaW9yID0gMHgyMDc3OwogIHQuc2V2ZW50ZWVuY2lyY2xlID0gMHgyNDcwOwogIHQuc2V2ZW50ZWVucGFyZW4gPSAweDI0ODQ7CiAgdC5zZXZlbnRlZW5wZXJpb2QgPSAweDI0OTg7CiAgdC5zZXZlbnRoYWkgPSAweDBlNTc7CiAgdC5zZnRoeXBoZW4gPSAweDAwYWQ7CiAgdC5zaGFhcm1lbmlhbiA9IDB4MDU3NzsKICB0LnNoYWJlbmdhbGkgPSAweDA5YjY7CiAgdC5zaGFjeXJpbGxpYyA9IDB4MDQ0ODsKICB0LnNoYWRkYWFyYWJpYyA9IDB4MDY1MTsKICB0LnNoYWRkYWRhbW1hYXJhYmljID0gMHhmYzYxOwogIHQuc2hhZGRhZGFtbWF0YW5hcmFiaWMgPSAweGZjNWU7CiAgdC5zaGFkZGFmYXRoYWFyYWJpYyA9IDB4ZmM2MDsKICB0LnNoYWRkYWthc3JhYXJhYmljID0gMHhmYzYyOwogIHQuc2hhZGRha2FzcmF0YW5hcmFiaWMgPSAweGZjNWY7CiAgdC5zaGFkZSA9IDB4MjU5MjsKICB0LnNoYWRlZGFyayA9IDB4MjU5MzsKICB0LnNoYWRlbGlnaHQgPSAweDI1OTE7CiAgdC5zaGFkZW1lZGl1bSA9IDB4MjU5MjsKICB0LnNoYWRldmEgPSAweDA5MzY7CiAgdC5zaGFndWphcmF0aSA9IDB4MGFiNjsKICB0LnNoYWd1cm11a2hpID0gMHgwYTM2OwogIHQuc2hhbHNoZWxldGhlYnJldyA9IDB4MDU5MzsKICB0LnNoYm9wb21vZm8gPSAweDMxMTU7CiAgdC5zaGNoYWN5cmlsbGljID0gMHgwNDQ5OwogIHQuc2hlZW5hcmFiaWMgPSAweDA2MzQ7CiAgdC5zaGVlbmZpbmFsYXJhYmljID0gMHhmZWI2OwogIHQuc2hlZW5pbml0aWFsYXJhYmljID0gMHhmZWI3OwogIHQuc2hlZW5tZWRpYWxhcmFiaWMgPSAweGZlYjg7CiAgdC5zaGVpY29wdGljID0gMHgwM2UzOwogIHQuc2hlcWVsID0gMHgyMGFhOwogIHQuc2hlcWVsaGVicmV3ID0gMHgyMGFhOwogIHQuc2hldmEgPSAweDA1YjA7CiAgdC5zaGV2YTExNSA9IDB4MDViMDsKICB0LnNoZXZhMTUgPSAweDA1YjA7CiAgdC5zaGV2YTIyID0gMHgwNWIwOwogIHQuc2hldmEyZSA9IDB4MDViMDsKICB0LnNoZXZhaGVicmV3ID0gMHgwNWIwOwogIHQuc2hldmFuYXJyb3doZWJyZXcgPSAweDA1YjA7CiAgdC5zaGV2YXF1YXJ0ZXJoZWJyZXcgPSAweDA1YjA7CiAgdC5zaGV2YXdpZGVoZWJyZXcgPSAweDA1YjA7CiAgdC5zaGhhY3lyaWxsaWMgPSAweDA0YmI7CiAgdC5zaGltYWNvcHRpYyA9IDB4MDNlZDsKICB0LnNoaW4gPSAweDA1ZTk7CiAgdC5zaGluZGFnZXNoID0gMHhmYjQ5OwogIHQuc2hpbmRhZ2VzaGhlYnJldyA9IDB4ZmI0OTsKICB0LnNoaW5kYWdlc2hzaGluZG90ID0gMHhmYjJjOwogIHQuc2hpbmRhZ2VzaHNoaW5kb3RoZWJyZXcgPSAweGZiMmM7CiAgdC5zaGluZGFnZXNoc2luZG90ID0gMHhmYjJkOwogIHQuc2hpbmRhZ2VzaHNpbmRvdGhlYnJldyA9IDB4ZmIyZDsKICB0LnNoaW5kb3RoZWJyZXcgPSAweDA1YzE7CiAgdC5zaGluaGVicmV3ID0gMHgwNWU5OwogIHQuc2hpbnNoaW5kb3QgPSAweGZiMmE7CiAgdC5zaGluc2hpbmRvdGhlYnJldyA9IDB4ZmIyYTsKICB0LnNoaW5zaW5kb3QgPSAweGZiMmI7CiAgdC5zaGluc2luZG90aGVicmV3ID0gMHhmYjJiOwogIHQuc2hvb2sgPSAweDAyODI7CiAgdC5zaWdtYSA9IDB4MDNjMzsKICB0LnNpZ21hMSA9IDB4MDNjMjsKICB0LnNpZ21hZmluYWwgPSAweDAzYzI7CiAgdC5zaWdtYWx1bmF0ZXN5bWJvbGdyZWVrID0gMHgwM2YyOwogIHQuc2loaXJhZ2FuYSA9IDB4MzA1NzsKICB0LnNpa2F0YWthbmEgPSAweDMwYjc7CiAgdC5zaWthdGFrYW5haGFsZndpZHRoID0gMHhmZjdjOwogIHQuc2lsdXFoZWJyZXcgPSAweDA1YmQ7CiAgdC5zaWx1cWxlZnRoZWJyZXcgPSAweDA1YmQ7CiAgdC5zaW1pbGFyID0gMHgyMjNjOwogIHQuc2luZG90aGVicmV3ID0gMHgwNWMyOwogIHQuc2lvc2FjaXJjbGVrb3JlYW4gPSAweDMyNzQ7CiAgdC5zaW9zYXBhcmVua29yZWFuID0gMHgzMjE0OwogIHQuc2lvc2NpZXVja29yZWFuID0gMHgzMTdlOwogIHQuc2lvc2NpcmNsZWtvcmVhbiA9IDB4MzI2NjsKICB0LnNpb3NraXllb2trb3JlYW4gPSAweDMxN2E7CiAgdC5zaW9za29yZWFuID0gMHgzMTQ1OwogIHQuc2lvc25pZXVua29yZWFuID0gMHgzMTdiOwogIHQuc2lvc3BhcmVua29yZWFuID0gMHgzMjA2OwogIHQuc2lvc3BpZXVwa29yZWFuID0gMHgzMTdkOwogIHQuc2lvc3Rpa2V1dGtvcmVhbiA9IDB4MzE3YzsKICB0LnNpeCA9IDB4MDAzNjsKICB0LnNpeGFyYWJpYyA9IDB4MDY2NjsKICB0LnNpeGJlbmdhbGkgPSAweDA5ZWM7CiAgdC5zaXhjaXJjbGUgPSAweDI0NjU7CiAgdC5zaXhjaXJjbGVpbnZlcnNlc2Fuc3NlcmlmID0gMHgyNzhmOwogIHQuc2l4ZGV2YSA9IDB4MDk2YzsKICB0LnNpeGd1amFyYXRpID0gMHgwYWVjOwogIHQuc2l4Z3VybXVraGkgPSAweDBhNmM7CiAgdC5zaXhoYWNrYXJhYmljID0gMHgwNjY2OwogIHQuc2l4aGFuZ3pob3UgPSAweDMwMjY7CiAgdC5zaXhpZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjI1OwogIHQuc2l4aW5mZXJpb3IgPSAweDIwODY7CiAgdC5zaXhtb25vc3BhY2UgPSAweGZmMTY7CiAgdC5zaXhvbGRzdHlsZSA9IDB4ZjczNjsKICB0LnNpeHBhcmVuID0gMHgyNDc5OwogIHQuc2l4cGVyaW9kID0gMHgyNDhkOwogIHQuc2l4cGVyc2lhbiA9IDB4MDZmNjsKICB0LnNpeHJvbWFuID0gMHgyMTc1OwogIHQuc2l4c3VwZXJpb3IgPSAweDIwNzY7CiAgdC5zaXh0ZWVuY2lyY2xlID0gMHgyNDZmOwogIHQuc2l4dGVlbmN1cnJlbmN5ZGVub21pbmF0b3JiZW5nYWxpID0gMHgwOWY5OwogIHQuc2l4dGVlbnBhcmVuID0gMHgyNDgzOwogIHQuc2l4dGVlbnBlcmlvZCA9IDB4MjQ5NzsKICB0LnNpeHRoYWkgPSAweDBlNTY7CiAgdC5zbGFzaCA9IDB4MDAyZjsKICB0LnNsYXNobW9ub3NwYWNlID0gMHhmZjBmOwogIHQuc2xvbmcgPSAweDAxN2Y7CiAgdC5zbG9uZ2RvdGFjY2VudCA9IDB4MWU5YjsKICB0LnNtaWxlZmFjZSA9IDB4MjYzYTsKICB0LnNtb25vc3BhY2UgPSAweGZmNTM7CiAgdC5zb2ZwYXN1cWhlYnJldyA9IDB4MDVjMzsKICB0LnNvZnRoeXBoZW4gPSAweDAwYWQ7CiAgdC5zb2Z0c2lnbmN5cmlsbGljID0gMHgwNDRjOwogIHQuc29oaXJhZ2FuYSA9IDB4MzA1ZDsKICB0LnNva2F0YWthbmEgPSAweDMwYmQ7CiAgdC5zb2thdGFrYW5haGFsZndpZHRoID0gMHhmZjdmOwogIHQuc29saWR1c2xvbmdvdmVybGF5Y21iID0gMHgwMzM4OwogIHQuc29saWR1c3Nob3J0b3ZlcmxheWNtYiA9IDB4MDMzNzsKICB0LnNvcnVzaXRoYWkgPSAweDBlMjk7CiAgdC5zb3NhbGF0aGFpID0gMHgwZTI4OwogIHQuc29zb3RoYWkgPSAweDBlMGI7CiAgdC5zb3N1YXRoYWkgPSAweDBlMmE7CiAgdC5zcGFjZSA9IDB4MDAyMDsKICB0LnNwYWNlaGFja2FyYWJpYyA9IDB4MDAyMDsKICB0LnNwYWRlID0gMHgyNjYwOwogIHQuc3BhZGVzdWl0YmxhY2sgPSAweDI2NjA7CiAgdC5zcGFkZXN1aXR3aGl0ZSA9IDB4MjY2NDsKICB0LnNwYXJlbiA9IDB4MjRhZTsKICB0LnNxdWFyZWJlbG93Y21iID0gMHgwMzNiOwogIHQuc3F1YXJlY2MgPSAweDMzYzQ7CiAgdC5zcXVhcmVjbSA9IDB4MzM5ZDsKICB0LnNxdWFyZWRpYWdvbmFsY3Jvc3NoYXRjaGZpbGwgPSAweDI1YTk7CiAgdC5zcXVhcmVob3Jpem9udGFsZmlsbCA9IDB4MjVhNDsKICB0LnNxdWFyZWtnID0gMHgzMzhmOwogIHQuc3F1YXJla20gPSAweDMzOWU7CiAgdC5zcXVhcmVrbWNhcGl0YWwgPSAweDMzY2U7CiAgdC5zcXVhcmVsbiA9IDB4MzNkMTsKICB0LnNxdWFyZWxvZyA9IDB4MzNkMjsKICB0LnNxdWFyZW1nID0gMHgzMzhlOwogIHQuc3F1YXJlbWlsID0gMHgzM2Q1OwogIHQuc3F1YXJlbW0gPSAweDMzOWM7CiAgdC5zcXVhcmVtc3F1YXJlZCA9IDB4MzNhMTsKICB0LnNxdWFyZW9ydGhvZ29uYWxjcm9zc2hhdGNoZmlsbCA9IDB4MjVhNjsKICB0LnNxdWFyZXVwcGVybGVmdHRvbG93ZXJyaWdodGZpbGwgPSAweDI1YTc7CiAgdC5zcXVhcmV1cHBlcnJpZ2h0dG9sb3dlcmxlZnRmaWxsID0gMHgyNWE4OwogIHQuc3F1YXJldmVydGljYWxmaWxsID0gMHgyNWE1OwogIHQuc3F1YXJld2hpdGV3aXRoc21hbGxibGFjayA9IDB4MjVhMzsKICB0LnNyc3F1YXJlID0gMHgzM2RiOwogIHQuc3NhYmVuZ2FsaSA9IDB4MDliNzsKICB0LnNzYWRldmEgPSAweDA5Mzc7CiAgdC5zc2FndWphcmF0aSA9IDB4MGFiNzsKICB0LnNzYW5nY2lldWNrb3JlYW4gPSAweDMxNDk7CiAgdC5zc2FuZ2hpZXVoa29yZWFuID0gMHgzMTg1OwogIHQuc3NhbmdpZXVuZ2tvcmVhbiA9IDB4MzE4MDsKICB0LnNzYW5na2l5ZW9ra29yZWFuID0gMHgzMTMyOwogIHQuc3NhbmduaWV1bmtvcmVhbiA9IDB4MzE2NTsKICB0LnNzYW5ncGlldXBrb3JlYW4gPSAweDMxNDM7CiAgdC5zc2FuZ3Npb3Nrb3JlYW4gPSAweDMxNDY7CiAgdC5zc2FuZ3Rpa2V1dGtvcmVhbiA9IDB4MzEzODsKICB0LnNzdXBlcmlvciA9IDB4ZjZmMjsKICB0LnN0ZXJsaW5nID0gMHgwMGEzOwogIHQuc3Rlcmxpbmdtb25vc3BhY2UgPSAweGZmZTE7CiAgdC5zdHJva2Vsb25nb3ZlcmxheWNtYiA9IDB4MDMzNjsKICB0LnN0cm9rZXNob3J0b3ZlcmxheWNtYiA9IDB4MDMzNTsKICB0LnN1YnNldCA9IDB4MjI4MjsKICB0LnN1YnNldG5vdGVxdWFsID0gMHgyMjhhOwogIHQuc3Vic2V0b3JlcXVhbCA9IDB4MjI4NjsKICB0LnN1Y2NlZWRzID0gMHgyMjdiOwogIHQuc3VjaHRoYXQgPSAweDIyMGI7CiAgdC5zdWhpcmFnYW5hID0gMHgzMDU5OwogIHQuc3VrYXRha2FuYSA9IDB4MzBiOTsKICB0LnN1a2F0YWthbmFoYWxmd2lkdGggPSAweGZmN2Q7CiAgdC5zdWt1bmFyYWJpYyA9IDB4MDY1MjsKICB0LnN1bW1hdGlvbiA9IDB4MjIxMTsKICB0LnN1biA9IDB4MjYzYzsKICB0LnN1cGVyc2V0ID0gMHgyMjgzOwogIHQuc3VwZXJzZXRub3RlcXVhbCA9IDB4MjI4YjsKICB0LnN1cGVyc2V0b3JlcXVhbCA9IDB4MjI4NzsKICB0LnN2c3F1YXJlID0gMHgzM2RjOwogIHQuc3lvdXdhZXJhc3F1YXJlID0gMHgzMzdjOwogIHQudCA9IDB4MDA3NDsKICB0LnRhYmVuZ2FsaSA9IDB4MDlhNDsKICB0LnRhY2tkb3duID0gMHgyMmE0OwogIHQudGFja2xlZnQgPSAweDIyYTM7CiAgdC50YWRldmEgPSAweDA5MjQ7CiAgdC50YWd1amFyYXRpID0gMHgwYWE0OwogIHQudGFndXJtdWtoaSA9IDB4MGEyNDsKICB0LnRhaGFyYWJpYyA9IDB4MDYzNzsKICB0LnRhaGZpbmFsYXJhYmljID0gMHhmZWMyOwogIHQudGFoaW5pdGlhbGFyYWJpYyA9IDB4ZmVjMzsKICB0LnRhaGlyYWdhbmEgPSAweDMwNWY7CiAgdC50YWhtZWRpYWxhcmFiaWMgPSAweGZlYzQ7CiAgdC50YWlzeW91ZXJhc3F1YXJlID0gMHgzMzdkOwogIHQudGFrYXRha2FuYSA9IDB4MzBiZjsKICB0LnRha2F0YWthbmFoYWxmd2lkdGggPSAweGZmODA7CiAgdC50YXR3ZWVsYXJhYmljID0gMHgwNjQwOwogIHQudGF1ID0gMHgwM2M0OwogIHQudGF2ID0gMHgwNWVhOwogIHQudGF2ZGFnZXMgPSAweGZiNGE7CiAgdC50YXZkYWdlc2ggPSAweGZiNGE7CiAgdC50YXZkYWdlc2hoZWJyZXcgPSAweGZiNGE7CiAgdC50YXZoZWJyZXcgPSAweDA1ZWE7CiAgdC50YmFyID0gMHgwMTY3OwogIHQudGJvcG9tb2ZvID0gMHgzMTBhOwogIHQudGNhcm9uID0gMHgwMTY1OwogIHQudGNjdXJsID0gMHgwMmE4OwogIHQudGNlZGlsbGEgPSAweDAxNjM7CiAgdC50Y2hlaGFyYWJpYyA9IDB4MDY4NjsKICB0LnRjaGVoZmluYWxhcmFiaWMgPSAweGZiN2I7CiAgdC50Y2hlaGluaXRpYWxhcmFiaWMgPSAweGZiN2M7CiAgdC50Y2hlaG1lZGlhbGFyYWJpYyA9IDB4ZmI3ZDsKICB0LnRjaXJjbGUgPSAweDI0ZTM7CiAgdC50Y2lyY3VtZmxleGJlbG93ID0gMHgxZTcxOwogIHQudGNvbW1hYWNjZW50ID0gMHgwMTYzOwogIHQudGRpZXJlc2lzID0gMHgxZTk3OwogIHQudGRvdGFjY2VudCA9IDB4MWU2YjsKICB0LnRkb3RiZWxvdyA9IDB4MWU2ZDsKICB0LnRlY3lyaWxsaWMgPSAweDA0NDI7CiAgdC50ZWRlc2NlbmRlcmN5cmlsbGljID0gMHgwNGFkOwogIHQudGVoYXJhYmljID0gMHgwNjJhOwogIHQudGVoZmluYWxhcmFiaWMgPSAweGZlOTY7CiAgdC50ZWhoYWhpbml0aWFsYXJhYmljID0gMHhmY2EyOwogIHQudGVoaGFoaXNvbGF0ZWRhcmFiaWMgPSAweGZjMGM7CiAgdC50ZWhpbml0aWFsYXJhYmljID0gMHhmZTk3OwogIHQudGVoaXJhZ2FuYSA9IDB4MzA2NjsKICB0LnRlaGplZW1pbml0aWFsYXJhYmljID0gMHhmY2ExOwogIHQudGVoamVlbWlzb2xhdGVkYXJhYmljID0gMHhmYzBiOwogIHQudGVobWFyYnV0YWFyYWJpYyA9IDB4MDYyOTsKICB0LnRlaG1hcmJ1dGFmaW5hbGFyYWJpYyA9IDB4ZmU5NDsKICB0LnRlaG1lZGlhbGFyYWJpYyA9IDB4ZmU5ODsKICB0LnRlaG1lZW1pbml0aWFsYXJhYmljID0gMHhmY2E0OwogIHQudGVobWVlbWlzb2xhdGVkYXJhYmljID0gMHhmYzBlOwogIHQudGVobm9vbmZpbmFsYXJhYmljID0gMHhmYzczOwogIHQudGVrYXRha2FuYSA9IDB4MzBjNjsKICB0LnRla2F0YWthbmFoYWxmd2lkdGggPSAweGZmODM7CiAgdC50ZWxlcGhvbmUgPSAweDIxMjE7CiAgdC50ZWxlcGhvbmVibGFjayA9IDB4MjYwZTsKICB0LnRlbGlzaGFnZWRvbGFoZWJyZXcgPSAweDA1YTA7CiAgdC50ZWxpc2hhcWV0YW5haGVicmV3ID0gMHgwNWE5OwogIHQudGVuY2lyY2xlID0gMHgyNDY5OwogIHQudGVuaWRlb2dyYXBoaWNwYXJlbiA9IDB4MzIyOTsKICB0LnRlbnBhcmVuID0gMHgyNDdkOwogIHQudGVucGVyaW9kID0gMHgyNDkxOwogIHQudGVucm9tYW4gPSAweDIxNzk7CiAgdC50ZXNoID0gMHgwMmE3OwogIHQudGV0ID0gMHgwNWQ4OwogIHQudGV0ZGFnZXNoID0gMHhmYjM4OwogIHQudGV0ZGFnZXNoaGVicmV3ID0gMHhmYjM4OwogIHQudGV0aGVicmV3ID0gMHgwNWQ4OwogIHQudGV0c2VjeXJpbGxpYyA9IDB4MDRiNTsKICB0LnRldmlyaGVicmV3ID0gMHgwNTliOwogIHQudGV2aXJsZWZ0aGVicmV3ID0gMHgwNTliOwogIHQudGhhYmVuZ2FsaSA9IDB4MDlhNTsKICB0LnRoYWRldmEgPSAweDA5MjU7CiAgdC50aGFndWphcmF0aSA9IDB4MGFhNTsKICB0LnRoYWd1cm11a2hpID0gMHgwYTI1OwogIHQudGhhbGFyYWJpYyA9IDB4MDYzMDsKICB0LnRoYWxmaW5hbGFyYWJpYyA9IDB4ZmVhYzsKICB0LnRoYW50aGFraGF0bG93bGVmdHRoYWkgPSAweGY4OTg7CiAgdC50aGFudGhha2hhdGxvd3JpZ2h0dGhhaSA9IDB4Zjg5NzsKICB0LnRoYW50aGFraGF0dGhhaSA9IDB4MGU0YzsKICB0LnRoYW50aGFraGF0dXBwZXJsZWZ0dGhhaSA9IDB4Zjg5NjsKICB0LnRoZWhhcmFiaWMgPSAweDA2MmI7CiAgdC50aGVoZmluYWxhcmFiaWMgPSAweGZlOWE7CiAgdC50aGVoaW5pdGlhbGFyYWJpYyA9IDB4ZmU5YjsKICB0LnRoZWhtZWRpYWxhcmFiaWMgPSAweGZlOWM7CiAgdC50aGVyZWV4aXN0cyA9IDB4MjIwMzsKICB0LnRoZXJlZm9yZSA9IDB4MjIzNDsKICB0LnRoZXRhID0gMHgwM2I4OwogIHQudGhldGExID0gMHgwM2QxOwogIHQudGhldGFzeW1ib2xncmVlayA9IDB4MDNkMTsKICB0LnRoaWV1dGhhY2lyY2xla29yZWFuID0gMHgzMjc5OwogIHQudGhpZXV0aGFwYXJlbmtvcmVhbiA9IDB4MzIxOTsKICB0LnRoaWV1dGhjaXJjbGVrb3JlYW4gPSAweDMyNmI7CiAgdC50aGlldXRoa29yZWFuID0gMHgzMTRjOwogIHQudGhpZXV0aHBhcmVua29yZWFuID0gMHgzMjBiOwogIHQudGhpcnRlZW5jaXJjbGUgPSAweDI0NmM7CiAgdC50aGlydGVlbnBhcmVuID0gMHgyNDgwOwogIHQudGhpcnRlZW5wZXJpb2QgPSAweDI0OTQ7CiAgdC50aG9uYW5nbW9udGhvdGhhaSA9IDB4MGUxMTsKICB0LnRob29rID0gMHgwMWFkOwogIHQudGhvcGh1dGhhb3RoYWkgPSAweDBlMTI7CiAgdC50aG9ybiA9IDB4MDBmZTsKICB0LnRob3RoYWhhbnRoYWkgPSAweDBlMTc7CiAgdC50aG90aGFudGhhaSA9IDB4MGUxMDsKICB0LnRob3Rob25ndGhhaSA9IDB4MGUxODsKICB0LnRob3RodW5ndGhhaSA9IDB4MGUxNjsKICB0LnRob3VzYW5kY3lyaWxsaWMgPSAweDA0ODI7CiAgdC50aG91c2FuZHNzZXBhcmF0b3JhcmFiaWMgPSAweDA2NmM7CiAgdC50aG91c2FuZHNzZXBhcmF0b3JwZXJzaWFuID0gMHgwNjZjOwogIHQudGhyZWUgPSAweDAwMzM7CiAgdC50aHJlZWFyYWJpYyA9IDB4MDY2MzsKICB0LnRocmVlYmVuZ2FsaSA9IDB4MDllOTsKICB0LnRocmVlY2lyY2xlID0gMHgyNDYyOwogIHQudGhyZWVjaXJjbGVpbnZlcnNlc2Fuc3NlcmlmID0gMHgyNzhjOwogIHQudGhyZWVkZXZhID0gMHgwOTY5OwogIHQudGhyZWVlaWdodGhzID0gMHgyMTVjOwogIHQudGhyZWVndWphcmF0aSA9IDB4MGFlOTsKICB0LnRocmVlZ3VybXVraGkgPSAweDBhNjk7CiAgdC50aHJlZWhhY2thcmFiaWMgPSAweDA2NjM7CiAgdC50aHJlZWhhbmd6aG91ID0gMHgzMDIzOwogIHQudGhyZWVpZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjIyOwogIHQudGhyZWVpbmZlcmlvciA9IDB4MjA4MzsKICB0LnRocmVlbW9ub3NwYWNlID0gMHhmZjEzOwogIHQudGhyZWVudW1lcmF0b3JiZW5nYWxpID0gMHgwOWY2OwogIHQudGhyZWVvbGRzdHlsZSA9IDB4ZjczMzsKICB0LnRocmVlcGFyZW4gPSAweDI0NzY7CiAgdC50aHJlZXBlcmlvZCA9IDB4MjQ4YTsKICB0LnRocmVlcGVyc2lhbiA9IDB4MDZmMzsKICB0LnRocmVlcXVhcnRlcnMgPSAweDAwYmU7CiAgdC50aHJlZXF1YXJ0ZXJzZW1kYXNoID0gMHhmNmRlOwogIHQudGhyZWVyb21hbiA9IDB4MjE3MjsKICB0LnRocmVlc3VwZXJpb3IgPSAweDAwYjM7CiAgdC50aHJlZXRoYWkgPSAweDBlNTM7CiAgdC50aHpzcXVhcmUgPSAweDMzOTQ7CiAgdC50aWhpcmFnYW5hID0gMHgzMDYxOwogIHQudGlrYXRha2FuYSA9IDB4MzBjMTsKICB0LnRpa2F0YWthbmFoYWxmd2lkdGggPSAweGZmODE7CiAgdC50aWtldXRhY2lyY2xla29yZWFuID0gMHgzMjcwOwogIHQudGlrZXV0YXBhcmVua29yZWFuID0gMHgzMjEwOwogIHQudGlrZXV0Y2lyY2xla29yZWFuID0gMHgzMjYyOwogIHQudGlrZXV0a29yZWFuID0gMHgzMTM3OwogIHQudGlrZXV0cGFyZW5rb3JlYW4gPSAweDMyMDI7CiAgdC50aWxkZSA9IDB4MDJkYzsKICB0LnRpbGRlYmVsb3djbWIgPSAweDAzMzA7CiAgdC50aWxkZWNtYiA9IDB4MDMwMzsKICB0LnRpbGRlY29tYiA9IDB4MDMwMzsKICB0LnRpbGRlZG91YmxlY21iID0gMHgwMzYwOwogIHQudGlsZGVvcGVyYXRvciA9IDB4MjIzYzsKICB0LnRpbGRlb3ZlcmxheWNtYiA9IDB4MDMzNDsKICB0LnRpbGRldmVydGljYWxjbWIgPSAweDAzM2U7CiAgdC50aW1lc2NpcmNsZSA9IDB4MjI5NzsKICB0LnRpcGVoYWhlYnJldyA9IDB4MDU5NjsKICB0LnRpcGVoYWxlZnRoZWJyZXcgPSAweDA1OTY7CiAgdC50aXBwaWd1cm11a2hpID0gMHgwYTcwOwogIHQudGl0bG9jeXJpbGxpY2NtYiA9IDB4MDQ4MzsKICB0LnRpd25hcm1lbmlhbiA9IDB4MDU3ZjsKICB0LnRsaW5lYmVsb3cgPSAweDFlNmY7CiAgdC50bW9ub3NwYWNlID0gMHhmZjU0OwogIHQudG9hcm1lbmlhbiA9IDB4MDU2OTsKICB0LnRvaGlyYWdhbmEgPSAweDMwNjg7CiAgdC50b2thdGFrYW5hID0gMHgzMGM4OwogIHQudG9rYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4NDsKICB0LnRvbmViYXJleHRyYWhpZ2htb2QgPSAweDAyZTU7CiAgdC50b25lYmFyZXh0cmFsb3dtb2QgPSAweDAyZTk7CiAgdC50b25lYmFyaGlnaG1vZCA9IDB4MDJlNjsKICB0LnRvbmViYXJsb3dtb2QgPSAweDAyZTg7CiAgdC50b25lYmFybWlkbW9kID0gMHgwMmU3OwogIHQudG9uZWZpdmUgPSAweDAxYmQ7CiAgdC50b25lc2l4ID0gMHgwMTg1OwogIHQudG9uZXR3byA9IDB4MDFhODsKICB0LnRvbm9zID0gMHgwMzg0OwogIHQudG9uc3F1YXJlID0gMHgzMzI3OwogIHQudG9wYXRha3RoYWkgPSAweDBlMGY7CiAgdC50b3J0b2lzZXNoZWxsYnJhY2tldGxlZnQgPSAweDMwMTQ7CiAgdC50b3J0b2lzZXNoZWxsYnJhY2tldGxlZnRzbWFsbCA9IDB4ZmU1ZDsKICB0LnRvcnRvaXNlc2hlbGxicmFja2V0bGVmdHZlcnRpY2FsID0gMHhmZTM5OwogIHQudG9ydG9pc2VzaGVsbGJyYWNrZXRyaWdodCA9IDB4MzAxNTsKICB0LnRvcnRvaXNlc2hlbGxicmFja2V0cmlnaHRzbWFsbCA9IDB4ZmU1ZTsKICB0LnRvcnRvaXNlc2hlbGxicmFja2V0cmlnaHR2ZXJ0aWNhbCA9IDB4ZmUzYTsKICB0LnRvdGFvdGhhaSA9IDB4MGUxNTsKICB0LnRwYWxhdGFsaG9vayA9IDB4MDFhYjsKICB0LnRwYXJlbiA9IDB4MjRhZjsKICB0LnRyYWRlbWFyayA9IDB4MjEyMjsKICB0LnRyYWRlbWFya3NhbnMgPSAweGY4ZWE7CiAgdC50cmFkZW1hcmtzZXJpZiA9IDB4ZjZkYjsKICB0LnRyZXRyb2ZsZXhob29rID0gMHgwMjg4OwogIHQudHJpYWdkbiA9IDB4MjViYzsKICB0LnRyaWFnbGYgPSAweDI1YzQ7CiAgdC50cmlhZ3J0ID0gMHgyNWJhOwogIHQudHJpYWd1cCA9IDB4MjViMjsKICB0LnRzID0gMHgwMmE2OwogIHQudHNhZGkgPSAweDA1ZTY7CiAgdC50c2FkaWRhZ2VzaCA9IDB4ZmI0NjsKICB0LnRzYWRpZGFnZXNoaGVicmV3ID0gMHhmYjQ2OwogIHQudHNhZGloZWJyZXcgPSAweDA1ZTY7CiAgdC50c2VjeXJpbGxpYyA9IDB4MDQ0NjsKICB0LnRzZXJlID0gMHgwNWI1OwogIHQudHNlcmUxMiA9IDB4MDViNTsKICB0LnRzZXJlMWUgPSAweDA1YjU7CiAgdC50c2VyZTJiID0gMHgwNWI1OwogIHQudHNlcmVoZWJyZXcgPSAweDA1YjU7CiAgdC50c2VyZW5hcnJvd2hlYnJldyA9IDB4MDViNTsKICB0LnRzZXJlcXVhcnRlcmhlYnJldyA9IDB4MDViNTsKICB0LnRzZXJld2lkZWhlYnJldyA9IDB4MDViNTsKICB0LnRzaGVjeXJpbGxpYyA9IDB4MDQ1YjsKICB0LnRzdXBlcmlvciA9IDB4ZjZmMzsKICB0LnR0YWJlbmdhbGkgPSAweDA5OWY7CiAgdC50dGFkZXZhID0gMHgwOTFmOwogIHQudHRhZ3VqYXJhdGkgPSAweDBhOWY7CiAgdC50dGFndXJtdWtoaSA9IDB4MGExZjsKICB0LnR0ZWhhcmFiaWMgPSAweDA2Nzk7CiAgdC50dGVoZmluYWxhcmFiaWMgPSAweGZiNjc7CiAgdC50dGVoaW5pdGlhbGFyYWJpYyA9IDB4ZmI2ODsKICB0LnR0ZWhtZWRpYWxhcmFiaWMgPSAweGZiNjk7CiAgdC50dGhhYmVuZ2FsaSA9IDB4MDlhMDsKICB0LnR0aGFkZXZhID0gMHgwOTIwOwogIHQudHRoYWd1amFyYXRpID0gMHgwYWEwOwogIHQudHRoYWd1cm11a2hpID0gMHgwYTIwOwogIHQudHR1cm5lZCA9IDB4MDI4NzsKICB0LnR1aGlyYWdhbmEgPSAweDMwNjQ7CiAgdC50dWthdGFrYW5hID0gMHgzMGM0OwogIHQudHVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4MjsKICB0LnR1c21hbGxoaXJhZ2FuYSA9IDB4MzA2MzsKICB0LnR1c21hbGxrYXRha2FuYSA9IDB4MzBjMzsKICB0LnR1c21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2ZjsKICB0LnR3ZWx2ZWNpcmNsZSA9IDB4MjQ2YjsKICB0LnR3ZWx2ZXBhcmVuID0gMHgyNDdmOwogIHQudHdlbHZlcGVyaW9kID0gMHgyNDkzOwogIHQudHdlbHZlcm9tYW4gPSAweDIxN2I7CiAgdC50d2VudHljaXJjbGUgPSAweDI0NzM7CiAgdC50d2VudHloYW5nemhvdSA9IDB4NTM0NDsKICB0LnR3ZW50eXBhcmVuID0gMHgyNDg3OwogIHQudHdlbnR5cGVyaW9kID0gMHgyNDliOwogIHQudHdvID0gMHgwMDMyOwogIHQudHdvYXJhYmljID0gMHgwNjYyOwogIHQudHdvYmVuZ2FsaSA9IDB4MDllODsKICB0LnR3b2NpcmNsZSA9IDB4MjQ2MTsKICB0LnR3b2NpcmNsZWludmVyc2VzYW5zc2VyaWYgPSAweDI3OGI7CiAgdC50d29kZXZhID0gMHgwOTY4OwogIHQudHdvZG90ZW5sZWFkZXIgPSAweDIwMjU7CiAgdC50d29kb3RsZWFkZXIgPSAweDIwMjU7CiAgdC50d29kb3RsZWFkZXJ2ZXJ0aWNhbCA9IDB4ZmUzMDsKICB0LnR3b2d1amFyYXRpID0gMHgwYWU4OwogIHQudHdvZ3VybXVraGkgPSAweDBhNjg7CiAgdC50d29oYWNrYXJhYmljID0gMHgwNjYyOwogIHQudHdvaGFuZ3pob3UgPSAweDMwMjI7CiAgdC50d29pZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjIxOwogIHQudHdvaW5mZXJpb3IgPSAweDIwODI7CiAgdC50d29tb25vc3BhY2UgPSAweGZmMTI7CiAgdC50d29udW1lcmF0b3JiZW5nYWxpID0gMHgwOWY1OwogIHQudHdvb2xkc3R5bGUgPSAweGY3MzI7CiAgdC50d29wYXJlbiA9IDB4MjQ3NTsKICB0LnR3b3BlcmlvZCA9IDB4MjQ4OTsKICB0LnR3b3BlcnNpYW4gPSAweDA2ZjI7CiAgdC50d29yb21hbiA9IDB4MjE3MTsKICB0LnR3b3N0cm9rZSA9IDB4MDFiYjsKICB0LnR3b3N1cGVyaW9yID0gMHgwMGIyOwogIHQudHdvdGhhaSA9IDB4MGU1MjsKICB0LnR3b3RoaXJkcyA9IDB4MjE1NDsKICB0LnUgPSAweDAwNzU7CiAgdC51YWN1dGUgPSAweDAwZmE7CiAgdC51YmFyID0gMHgwMjg5OwogIHQudWJlbmdhbGkgPSAweDA5ODk7CiAgdC51Ym9wb21vZm8gPSAweDMxMjg7CiAgdC51YnJldmUgPSAweDAxNmQ7CiAgdC51Y2Fyb24gPSAweDAxZDQ7CiAgdC51Y2lyY2xlID0gMHgyNGU0OwogIHQudWNpcmN1bWZsZXggPSAweDAwZmI7CiAgdC51Y2lyY3VtZmxleGJlbG93ID0gMHgxZTc3OwogIHQudWN5cmlsbGljID0gMHgwNDQzOwogIHQudWRhdHRhZGV2YSA9IDB4MDk1MTsKICB0LnVkYmxhY3V0ZSA9IDB4MDE3MTsKICB0LnVkYmxncmF2ZSA9IDB4MDIxNTsKICB0LnVkZXZhID0gMHgwOTA5OwogIHQudWRpZXJlc2lzID0gMHgwMGZjOwogIHQudWRpZXJlc2lzYWN1dGUgPSAweDAxZDg7CiAgdC51ZGllcmVzaXNiZWxvdyA9IDB4MWU3MzsKICB0LnVkaWVyZXNpc2Nhcm9uID0gMHgwMWRhOwogIHQudWRpZXJlc2lzY3lyaWxsaWMgPSAweDA0ZjE7CiAgdC51ZGllcmVzaXNncmF2ZSA9IDB4MDFkYzsKICB0LnVkaWVyZXNpc21hY3JvbiA9IDB4MDFkNjsKICB0LnVkb3RiZWxvdyA9IDB4MWVlNTsKICB0LnVncmF2ZSA9IDB4MDBmOTsKICB0LnVndWphcmF0aSA9IDB4MGE4OTsKICB0LnVndXJtdWtoaSA9IDB4MGEwOTsKICB0LnVoaXJhZ2FuYSA9IDB4MzA0NjsKICB0LnVob29rYWJvdmUgPSAweDFlZTc7CiAgdC51aG9ybiA9IDB4MDFiMDsKICB0LnVob3JuYWN1dGUgPSAweDFlZTk7CiAgdC51aG9ybmRvdGJlbG93ID0gMHgxZWYxOwogIHQudWhvcm5ncmF2ZSA9IDB4MWVlYjsKICB0LnVob3JuaG9va2Fib3ZlID0gMHgxZWVkOwogIHQudWhvcm50aWxkZSA9IDB4MWVlZjsKICB0LnVodW5nYXJ1bWxhdXQgPSAweDAxNzE7CiAgdC51aHVuZ2FydW1sYXV0Y3lyaWxsaWMgPSAweDA0ZjM7CiAgdC51aW52ZXJ0ZWRicmV2ZSA9IDB4MDIxNzsKICB0LnVrYXRha2FuYSA9IDB4MzBhNjsKICB0LnVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3MzsKICB0LnVrY3lyaWxsaWMgPSAweDA0Nzk7CiAgdC51a29yZWFuID0gMHgzMTVjOwogIHQudW1hY3JvbiA9IDB4MDE2YjsKICB0LnVtYWNyb25jeXJpbGxpYyA9IDB4MDRlZjsKICB0LnVtYWNyb25kaWVyZXNpcyA9IDB4MWU3YjsKICB0LnVtYXRyYWd1cm11a2hpID0gMHgwYTQxOwogIHQudW1vbm9zcGFjZSA9IDB4ZmY1NTsKICB0LnVuZGVyc2NvcmUgPSAweDAwNWY7CiAgdC51bmRlcnNjb3JlZGJsID0gMHgyMDE3OwogIHQudW5kZXJzY29yZW1vbm9zcGFjZSA9IDB4ZmYzZjsKICB0LnVuZGVyc2NvcmV2ZXJ0aWNhbCA9IDB4ZmUzMzsKICB0LnVuZGVyc2NvcmV3YXZ5ID0gMHhmZTRmOwogIHQudW5pb24gPSAweDIyMmE7CiAgdC51bml2ZXJzYWwgPSAweDIyMDA7CiAgdC51b2dvbmVrID0gMHgwMTczOwogIHQudXBhcmVuID0gMHgyNGIwOwogIHQudXBibG9jayA9IDB4MjU4MDsKICB0LnVwcGVyZG90aGVicmV3ID0gMHgwNWM0OwogIHQudXBzaWxvbiA9IDB4MDNjNTsKICB0LnVwc2lsb25kaWVyZXNpcyA9IDB4MDNjYjsKICB0LnVwc2lsb25kaWVyZXNpc3Rvbm9zID0gMHgwM2IwOwogIHQudXBzaWxvbmxhdGluID0gMHgwMjhhOwogIHQudXBzaWxvbnRvbm9zID0gMHgwM2NkOwogIHQudXB0YWNrYmVsb3djbWIgPSAweDAzMWQ7CiAgdC51cHRhY2ttb2QgPSAweDAyZDQ7CiAgdC51cmFndXJtdWtoaSA9IDB4MGE3MzsKICB0LnVyaW5nID0gMHgwMTZmOwogIHQudXNob3J0Y3lyaWxsaWMgPSAweDA0NWU7CiAgdC51c21hbGxoaXJhZ2FuYSA9IDB4MzA0NTsKICB0LnVzbWFsbGthdGFrYW5hID0gMHgzMGE1OwogIHQudXNtYWxsa2F0YWthbmFoYWxmd2lkdGggPSAweGZmNjk7CiAgdC51c3RyYWlnaHRjeXJpbGxpYyA9IDB4MDRhZjsKICB0LnVzdHJhaWdodHN0cm9rZWN5cmlsbGljID0gMHgwNGIxOwogIHQudXRpbGRlID0gMHgwMTY5OwogIHQudXRpbGRlYWN1dGUgPSAweDFlNzk7CiAgdC51dGlsZGViZWxvdyA9IDB4MWU3NTsKICB0LnV1YmVuZ2FsaSA9IDB4MDk4YTsKICB0LnV1ZGV2YSA9IDB4MDkwYTsKICB0LnV1Z3VqYXJhdGkgPSAweDBhOGE7CiAgdC51dWd1cm11a2hpID0gMHgwYTBhOwogIHQudXVtYXRyYWd1cm11a2hpID0gMHgwYTQyOwogIHQudXV2b3dlbHNpZ25iZW5nYWxpID0gMHgwOWMyOwogIHQudXV2b3dlbHNpZ25kZXZhID0gMHgwOTQyOwogIHQudXV2b3dlbHNpZ25ndWphcmF0aSA9IDB4MGFjMjsKICB0LnV2b3dlbHNpZ25iZW5nYWxpID0gMHgwOWMxOwogIHQudXZvd2Vsc2lnbmRldmEgPSAweDA5NDE7CiAgdC51dm93ZWxzaWduZ3VqYXJhdGkgPSAweDBhYzE7CiAgdC52ID0gMHgwMDc2OwogIHQudmFkZXZhID0gMHgwOTM1OwogIHQudmFndWphcmF0aSA9IDB4MGFiNTsKICB0LnZhZ3VybXVraGkgPSAweDBhMzU7CiAgdC52YWthdGFrYW5hID0gMHgzMGY3OwogIHQudmF2ID0gMHgwNWQ1OwogIHQudmF2ZGFnZXNoID0gMHhmYjM1OwogIHQudmF2ZGFnZXNoNjUgPSAweGZiMzU7CiAgdC52YXZkYWdlc2hoZWJyZXcgPSAweGZiMzU7CiAgdC52YXZoZWJyZXcgPSAweDA1ZDU7CiAgdC52YXZob2xhbSA9IDB4ZmI0YjsKICB0LnZhdmhvbGFtaGVicmV3ID0gMHhmYjRiOwogIHQudmF2dmF2aGVicmV3ID0gMHgwNWYwOwogIHQudmF2eW9kaGVicmV3ID0gMHgwNWYxOwogIHQudmNpcmNsZSA9IDB4MjRlNTsKICB0LnZkb3RiZWxvdyA9IDB4MWU3ZjsKICB0LnZlY3lyaWxsaWMgPSAweDA0MzI7CiAgdC52ZWhhcmFiaWMgPSAweDA2YTQ7CiAgdC52ZWhmaW5hbGFyYWJpYyA9IDB4ZmI2YjsKICB0LnZlaGluaXRpYWxhcmFiaWMgPSAweGZiNmM7CiAgdC52ZWhtZWRpYWxhcmFiaWMgPSAweGZiNmQ7CiAgdC52ZWthdGFrYW5hID0gMHgzMGY5OwogIHQudmVudXMgPSAweDI2NDA7CiAgdC52ZXJ0aWNhbGJhciA9IDB4MDA3YzsKICB0LnZlcnRpY2FsbGluZWFib3ZlY21iID0gMHgwMzBkOwogIHQudmVydGljYWxsaW5lYmVsb3djbWIgPSAweDAzMjk7CiAgdC52ZXJ0aWNhbGxpbmVsb3dtb2QgPSAweDAyY2M7CiAgdC52ZXJ0aWNhbGxpbmVtb2QgPSAweDAyYzg7CiAgdC52ZXdhcm1lbmlhbiA9IDB4MDU3ZTsKICB0LnZob29rID0gMHgwMjhiOwogIHQudmlrYXRha2FuYSA9IDB4MzBmODsKICB0LnZpcmFtYWJlbmdhbGkgPSAweDA5Y2Q7CiAgdC52aXJhbWFkZXZhID0gMHgwOTRkOwogIHQudmlyYW1hZ3VqYXJhdGkgPSAweDBhY2Q7CiAgdC52aXNhcmdhYmVuZ2FsaSA9IDB4MDk4MzsKICB0LnZpc2FyZ2FkZXZhID0gMHgwOTAzOwogIHQudmlzYXJnYWd1amFyYXRpID0gMHgwYTgzOwogIHQudm1vbm9zcGFjZSA9IDB4ZmY1NjsKICB0LnZvYXJtZW5pYW4gPSAweDA1Nzg7CiAgdC52b2ljZWRpdGVyYXRpb25oaXJhZ2FuYSA9IDB4MzA5ZTsKICB0LnZvaWNlZGl0ZXJhdGlvbmthdGFrYW5hID0gMHgzMGZlOwogIHQudm9pY2VkbWFya2thbmEgPSAweDMwOWI7CiAgdC52b2ljZWRtYXJra2FuYWhhbGZ3aWR0aCA9IDB4ZmY5ZTsKICB0LnZva2F0YWthbmEgPSAweDMwZmE7CiAgdC52cGFyZW4gPSAweDI0YjE7CiAgdC52dGlsZGUgPSAweDFlN2Q7CiAgdC52dHVybmVkID0gMHgwMjhjOwogIHQudnVoaXJhZ2FuYSA9IDB4MzA5NDsKICB0LnZ1a2F0YWthbmEgPSAweDMwZjQ7CiAgdC53ID0gMHgwMDc3OwogIHQud2FjdXRlID0gMHgxZTgzOwogIHQud2Fla29yZWFuID0gMHgzMTU5OwogIHQud2FoaXJhZ2FuYSA9IDB4MzA4ZjsKICB0Lndha2F0YWthbmEgPSAweDMwZWY7CiAgdC53YWthdGFrYW5haGFsZndpZHRoID0gMHhmZjljOwogIHQud2Frb3JlYW4gPSAweDMxNTg7CiAgdC53YXNtYWxsaGlyYWdhbmEgPSAweDMwOGU7CiAgdC53YXNtYWxsa2F0YWthbmEgPSAweDMwZWU7CiAgdC53YXR0b3NxdWFyZSA9IDB4MzM1NzsKICB0LndhdmVkYXNoID0gMHgzMDFjOwogIHQud2F2eXVuZGVyc2NvcmV2ZXJ0aWNhbCA9IDB4ZmUzNDsKICB0Lndhd2FyYWJpYyA9IDB4MDY0ODsKICB0Lndhd2ZpbmFsYXJhYmljID0gMHhmZWVlOwogIHQud2F3aGFtemFhYm92ZWFyYWJpYyA9IDB4MDYyNDsKICB0Lndhd2hhbXphYWJvdmVmaW5hbGFyYWJpYyA9IDB4ZmU4NjsKICB0Lndic3F1YXJlID0gMHgzM2RkOwogIHQud2NpcmNsZSA9IDB4MjRlNjsKICB0LndjaXJjdW1mbGV4ID0gMHgwMTc1OwogIHQud2RpZXJlc2lzID0gMHgxZTg1OwogIHQud2RvdGFjY2VudCA9IDB4MWU4NzsKICB0Lndkb3RiZWxvdyA9IDB4MWU4OTsKICB0LndlaGlyYWdhbmEgPSAweDMwOTE7CiAgdC53ZWllcnN0cmFzcyA9IDB4MjExODsKICB0Lndla2F0YWthbmEgPSAweDMwZjE7CiAgdC53ZWtvcmVhbiA9IDB4MzE1ZTsKICB0Lndlb2tvcmVhbiA9IDB4MzE1ZDsKICB0LndncmF2ZSA9IDB4MWU4MTsKICB0LndoaXRlYnVsbGV0ID0gMHgyNWU2OwogIHQud2hpdGVjaXJjbGUgPSAweDI1Y2I7CiAgdC53aGl0ZWNpcmNsZWludmVyc2UgPSAweDI1ZDk7CiAgdC53aGl0ZWNvcm5lcmJyYWNrZXRsZWZ0ID0gMHgzMDBlOwogIHQud2hpdGVjb3JuZXJicmFja2V0bGVmdHZlcnRpY2FsID0gMHhmZTQzOwogIHQud2hpdGVjb3JuZXJicmFja2V0cmlnaHQgPSAweDMwMGY7CiAgdC53aGl0ZWNvcm5lcmJyYWNrZXRyaWdodHZlcnRpY2FsID0gMHhmZTQ0OwogIHQud2hpdGVkaWFtb25kID0gMHgyNWM3OwogIHQud2hpdGVkaWFtb25kY29udGFpbmluZ2JsYWNrc21hbGxkaWFtb25kID0gMHgyNWM4OwogIHQud2hpdGVkb3ducG9pbnRpbmdzbWFsbHRyaWFuZ2xlID0gMHgyNWJmOwogIHQud2hpdGVkb3ducG9pbnRpbmd0cmlhbmdsZSA9IDB4MjViZDsKICB0LndoaXRlbGVmdHBvaW50aW5nc21hbGx0cmlhbmdsZSA9IDB4MjVjMzsKICB0LndoaXRlbGVmdHBvaW50aW5ndHJpYW5nbGUgPSAweDI1YzE7CiAgdC53aGl0ZWxlbnRpY3VsYXJicmFja2V0bGVmdCA9IDB4MzAxNjsKICB0LndoaXRlbGVudGljdWxhcmJyYWNrZXRyaWdodCA9IDB4MzAxNzsKICB0LndoaXRlcmlnaHRwb2ludGluZ3NtYWxsdHJpYW5nbGUgPSAweDI1Yjk7CiAgdC53aGl0ZXJpZ2h0cG9pbnRpbmd0cmlhbmdsZSA9IDB4MjViNzsKICB0LndoaXRlc21hbGxzcXVhcmUgPSAweDI1YWI7CiAgdC53aGl0ZXNtaWxpbmdmYWNlID0gMHgyNjNhOwogIHQud2hpdGVzcXVhcmUgPSAweDI1YTE7CiAgdC53aGl0ZXN0YXIgPSAweDI2MDY7CiAgdC53aGl0ZXRlbGVwaG9uZSA9IDB4MjYwZjsKICB0LndoaXRldG9ydG9pc2VzaGVsbGJyYWNrZXRsZWZ0ID0gMHgzMDE4OwogIHQud2hpdGV0b3J0b2lzZXNoZWxsYnJhY2tldHJpZ2h0ID0gMHgzMDE5OwogIHQud2hpdGV1cHBvaW50aW5nc21hbGx0cmlhbmdsZSA9IDB4MjViNTsKICB0LndoaXRldXBwb2ludGluZ3RyaWFuZ2xlID0gMHgyNWIzOwogIHQud2loaXJhZ2FuYSA9IDB4MzA5MDsKICB0Lndpa2F0YWthbmEgPSAweDMwZjA7CiAgdC53aWtvcmVhbiA9IDB4MzE1ZjsKICB0Lndtb25vc3BhY2UgPSAweGZmNTc7CiAgdC53b2hpcmFnYW5hID0gMHgzMDkyOwogIHQud29rYXRha2FuYSA9IDB4MzBmMjsKICB0Lndva2F0YWthbmFoYWxmd2lkdGggPSAweGZmNjY7CiAgdC53b24gPSAweDIwYTk7CiAgdC53b25tb25vc3BhY2UgPSAweGZmZTY7CiAgdC53b3dhZW50aGFpID0gMHgwZTI3OwogIHQud3BhcmVuID0gMHgyNGIyOwogIHQud3JpbmcgPSAweDFlOTg7CiAgdC53c3VwZXJpb3IgPSAweDAyYjc7CiAgdC53dHVybmVkID0gMHgwMjhkOwogIHQud3lubiA9IDB4MDFiZjsKICB0LnggPSAweDAwNzg7CiAgdC54YWJvdmVjbWIgPSAweDAzM2Q7CiAgdC54Ym9wb21vZm8gPSAweDMxMTI7CiAgdC54Y2lyY2xlID0gMHgyNGU3OwogIHQueGRpZXJlc2lzID0gMHgxZThkOwogIHQueGRvdGFjY2VudCA9IDB4MWU4YjsKICB0LnhlaGFybWVuaWFuID0gMHgwNTZkOwogIHQueGkgPSAweDAzYmU7CiAgdC54bW9ub3NwYWNlID0gMHhmZjU4OwogIHQueHBhcmVuID0gMHgyNGIzOwogIHQueHN1cGVyaW9yID0gMHgwMmUzOwogIHQueSA9IDB4MDA3OTsKICB0LnlhYWRvc3F1YXJlID0gMHgzMzRlOwogIHQueWFiZW5nYWxpID0gMHgwOWFmOwogIHQueWFjdXRlID0gMHgwMGZkOwogIHQueWFkZXZhID0gMHgwOTJmOwogIHQueWFla29yZWFuID0gMHgzMTUyOwogIHQueWFndWphcmF0aSA9IDB4MGFhZjsKICB0LnlhZ3VybXVraGkgPSAweDBhMmY7CiAgdC55YWhpcmFnYW5hID0gMHgzMDg0OwogIHQueWFrYXRha2FuYSA9IDB4MzBlNDsKICB0Lnlha2F0YWthbmFoYWxmd2lkdGggPSAweGZmOTQ7CiAgdC55YWtvcmVhbiA9IDB4MzE1MTsKICB0LnlhbWFra2FudGhhaSA9IDB4MGU0ZTsKICB0Lnlhc21hbGxoaXJhZ2FuYSA9IDB4MzA4MzsKICB0Lnlhc21hbGxrYXRha2FuYSA9IDB4MzBlMzsKICB0Lnlhc21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2YzsKICB0LnlhdGN5cmlsbGljID0gMHgwNDYzOwogIHQueWNpcmNsZSA9IDB4MjRlODsKICB0LnljaXJjdW1mbGV4ID0gMHgwMTc3OwogIHQueWRpZXJlc2lzID0gMHgwMGZmOwogIHQueWRvdGFjY2VudCA9IDB4MWU4ZjsKICB0Lnlkb3RiZWxvdyA9IDB4MWVmNTsKICB0LnllaGFyYWJpYyA9IDB4MDY0YTsKICB0LnllaGJhcnJlZWFyYWJpYyA9IDB4MDZkMjsKICB0LnllaGJhcnJlZWZpbmFsYXJhYmljID0gMHhmYmFmOwogIHQueWVoZmluYWxhcmFiaWMgPSAweGZlZjI7CiAgdC55ZWhoYW16YWFib3ZlYXJhYmljID0gMHgwNjI2OwogIHQueWVoaGFtemFhYm92ZWZpbmFsYXJhYmljID0gMHhmZThhOwogIHQueWVoaGFtemFhYm92ZWluaXRpYWxhcmFiaWMgPSAweGZlOGI7CiAgdC55ZWhoYW16YWFib3ZlbWVkaWFsYXJhYmljID0gMHhmZThjOwogIHQueWVoaW5pdGlhbGFyYWJpYyA9IDB4ZmVmMzsKICB0LnllaG1lZGlhbGFyYWJpYyA9IDB4ZmVmNDsKICB0LnllaG1lZW1pbml0aWFsYXJhYmljID0gMHhmY2RkOwogIHQueWVobWVlbWlzb2xhdGVkYXJhYmljID0gMHhmYzU4OwogIHQueWVobm9vbmZpbmFsYXJhYmljID0gMHhmYzk0OwogIHQueWVodGhyZWVkb3RzYmVsb3dhcmFiaWMgPSAweDA2ZDE7CiAgdC55ZWtvcmVhbiA9IDB4MzE1NjsKICB0LnllbiA9IDB4MDBhNTsKICB0Lnllbm1vbm9zcGFjZSA9IDB4ZmZlNTsKICB0Lnllb2tvcmVhbiA9IDB4MzE1NTsKICB0Lnllb3JpbmhpZXVoa29yZWFuID0gMHgzMTg2OwogIHQueWVyYWhiZW55b21vaGVicmV3ID0gMHgwNWFhOwogIHQueWVyYWhiZW55b21vbGVmdGhlYnJldyA9IDB4MDVhYTsKICB0LnllcmljeXJpbGxpYyA9IDB4MDQ0YjsKICB0LnllcnVkaWVyZXNpc2N5cmlsbGljID0gMHgwNGY5OwogIHQueWVzaWV1bmdrb3JlYW4gPSAweDMxODE7CiAgdC55ZXNpZXVuZ3BhbnNpb3Nrb3JlYW4gPSAweDMxODM7CiAgdC55ZXNpZXVuZ3Npb3Nrb3JlYW4gPSAweDMxODI7CiAgdC55ZXRpdmhlYnJldyA9IDB4MDU5YTsKICB0LnlncmF2ZSA9IDB4MWVmMzsKICB0Lnlob29rID0gMHgwMWI0OwogIHQueWhvb2thYm92ZSA9IDB4MWVmNzsKICB0LnlpYXJtZW5pYW4gPSAweDA1NzU7CiAgdC55aWN5cmlsbGljID0gMHgwNDU3OwogIHQueWlrb3JlYW4gPSAweDMxNjI7CiAgdC55aW55YW5nID0gMHgyNjJmOwogIHQueWl3bmFybWVuaWFuID0gMHgwNTgyOwogIHQueW1vbm9zcGFjZSA9IDB4ZmY1OTsKICB0LnlvZCA9IDB4MDVkOTsKICB0LnlvZGRhZ2VzaCA9IDB4ZmIzOTsKICB0LnlvZGRhZ2VzaGhlYnJldyA9IDB4ZmIzOTsKICB0LnlvZGhlYnJldyA9IDB4MDVkOTsKICB0LnlvZHlvZGhlYnJldyA9IDB4MDVmMjsKICB0LnlvZHlvZHBhdGFoaGVicmV3ID0gMHhmYjFmOwogIHQueW9oaXJhZ2FuYSA9IDB4MzA4ODsKICB0LnlvaWtvcmVhbiA9IDB4MzE4OTsKICB0Lnlva2F0YWthbmEgPSAweDMwZTg7CiAgdC55b2thdGFrYW5haGFsZndpZHRoID0gMHhmZjk2OwogIHQueW9rb3JlYW4gPSAweDMxNWI7CiAgdC55b3NtYWxsaGlyYWdhbmEgPSAweDMwODc7CiAgdC55b3NtYWxsa2F0YWthbmEgPSAweDMwZTc7CiAgdC55b3NtYWxsa2F0YWthbmFoYWxmd2lkdGggPSAweGZmNmU7CiAgdC55b3RncmVlayA9IDB4MDNmMzsKICB0LnlveWFla29yZWFuID0gMHgzMTg4OwogIHQueW95YWtvcmVhbiA9IDB4MzE4NzsKICB0LnlveWFrdGhhaSA9IDB4MGUyMjsKICB0LnlveWluZ3RoYWkgPSAweDBlMGQ7CiAgdC55cGFyZW4gPSAweDI0YjQ7CiAgdC55cG9nZWdyYW1tZW5pID0gMHgwMzdhOwogIHQueXBvZ2VncmFtbWVuaWdyZWVrY21iID0gMHgwMzQ1OwogIHQueXIgPSAweDAxYTY7CiAgdC55cmluZyA9IDB4MWU5OTsKICB0LnlzdXBlcmlvciA9IDB4MDJiODsKICB0Lnl0aWxkZSA9IDB4MWVmOTsKICB0Lnl0dXJuZWQgPSAweDAyOGU7CiAgdC55dWhpcmFnYW5hID0gMHgzMDg2OwogIHQueXVpa29yZWFuID0gMHgzMThjOwogIHQueXVrYXRha2FuYSA9IDB4MzBlNjsKICB0Lnl1a2F0YWthbmFoYWxmd2lkdGggPSAweGZmOTU7CiAgdC55dWtvcmVhbiA9IDB4MzE2MDsKICB0Lnl1c2JpZ2N5cmlsbGljID0gMHgwNDZiOwogIHQueXVzYmlnaW90aWZpZWRjeXJpbGxpYyA9IDB4MDQ2ZDsKICB0Lnl1c2xpdHRsZWN5cmlsbGljID0gMHgwNDY3OwogIHQueXVzbGl0dGxlaW90aWZpZWRjeXJpbGxpYyA9IDB4MDQ2OTsKICB0Lnl1c21hbGxoaXJhZ2FuYSA9IDB4MzA4NTsKICB0Lnl1c21hbGxrYXRha2FuYSA9IDB4MzBlNTsKICB0Lnl1c21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2ZDsKICB0Lnl1eWVrb3JlYW4gPSAweDMxOGI7CiAgdC55dXllb2tvcmVhbiA9IDB4MzE4YTsKICB0Lnl5YWJlbmdhbGkgPSAweDA5ZGY7CiAgdC55eWFkZXZhID0gMHgwOTVmOwogIHQueiA9IDB4MDA3YTsKICB0LnphYXJtZW5pYW4gPSAweDA1NjY7CiAgdC56YWN1dGUgPSAweDAxN2E7CiAgdC56YWRldmEgPSAweDA5NWI7CiAgdC56YWd1cm11a2hpID0gMHgwYTViOwogIHQuemFoYXJhYmljID0gMHgwNjM4OwogIHQuemFoZmluYWxhcmFiaWMgPSAweGZlYzY7CiAgdC56YWhpbml0aWFsYXJhYmljID0gMHhmZWM3OwogIHQuemFoaXJhZ2FuYSA9IDB4MzA1NjsKICB0LnphaG1lZGlhbGFyYWJpYyA9IDB4ZmVjODsKICB0LnphaW5hcmFiaWMgPSAweDA2MzI7CiAgdC56YWluZmluYWxhcmFiaWMgPSAweGZlYjA7CiAgdC56YWthdGFrYW5hID0gMHgzMGI2OwogIHQuemFxZWZnYWRvbGhlYnJldyA9IDB4MDU5NTsKICB0LnphcWVmcWF0YW5oZWJyZXcgPSAweDA1OTQ7CiAgdC56YXJxYWhlYnJldyA9IDB4MDU5ODsKICB0LnpheWluID0gMHgwNWQ2OwogIHQuemF5aW5kYWdlc2ggPSAweGZiMzY7CiAgdC56YXlpbmRhZ2VzaGhlYnJldyA9IDB4ZmIzNjsKICB0LnpheWluaGVicmV3ID0gMHgwNWQ2OwogIHQuemJvcG9tb2ZvID0gMHgzMTE3OwogIHQuemNhcm9uID0gMHgwMTdlOwogIHQuemNpcmNsZSA9IDB4MjRlOTsKICB0LnpjaXJjdW1mbGV4ID0gMHgxZTkxOwogIHQuemN1cmwgPSAweDAyOTE7CiAgdC56ZG90ID0gMHgwMTdjOwogIHQuemRvdGFjY2VudCA9IDB4MDE3YzsKICB0Lnpkb3RiZWxvdyA9IDB4MWU5MzsKICB0LnplY3lyaWxsaWMgPSAweDA0Mzc7CiAgdC56ZWRlc2NlbmRlcmN5cmlsbGljID0gMHgwNDk5OwogIHQuemVkaWVyZXNpc2N5cmlsbGljID0gMHgwNGRmOwogIHQuemVoaXJhZ2FuYSA9IDB4MzA1YzsKICB0Lnpla2F0YWthbmEgPSAweDMwYmM7CiAgdC56ZXJvID0gMHgwMDMwOwogIHQuemVyb2FyYWJpYyA9IDB4MDY2MDsKICB0Lnplcm9iZW5nYWxpID0gMHgwOWU2OwogIHQuemVyb2RldmEgPSAweDA5NjY7CiAgdC56ZXJvZ3VqYXJhdGkgPSAweDBhZTY7CiAgdC56ZXJvZ3VybXVraGkgPSAweDBhNjY7CiAgdC56ZXJvaGFja2FyYWJpYyA9IDB4MDY2MDsKICB0Lnplcm9pbmZlcmlvciA9IDB4MjA4MDsKICB0Lnplcm9tb25vc3BhY2UgPSAweGZmMTA7CiAgdC56ZXJvb2xkc3R5bGUgPSAweGY3MzA7CiAgdC56ZXJvcGVyc2lhbiA9IDB4MDZmMDsKICB0Lnplcm9zdXBlcmlvciA9IDB4MjA3MDsKICB0Lnplcm90aGFpID0gMHgwZTUwOwogIHQuemVyb3dpZHRoam9pbmVyID0gMHhmZWZmOwogIHQuemVyb3dpZHRobm9uam9pbmVyID0gMHgyMDBjOwogIHQuemVyb3dpZHRoc3BhY2UgPSAweDIwMGI7CiAgdC56ZXRhID0gMHgwM2I2OwogIHQuemhib3BvbW9mbyA9IDB4MzExMzsKICB0LnpoZWFybWVuaWFuID0gMHgwNTZhOwogIHQuemhlYnJldmVjeXJpbGxpYyA9IDB4MDRjMjsKICB0LnpoZWN5cmlsbGljID0gMHgwNDM2OwogIHQuemhlZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0OTc7CiAgdC56aGVkaWVyZXNpc2N5cmlsbGljID0gMHgwNGRkOwogIHQuemloaXJhZ2FuYSA9IDB4MzA1ODsKICB0Lnppa2F0YWthbmEgPSAweDMwYjg7CiAgdC56aW5vcmhlYnJldyA9IDB4MDVhZTsKICB0LnpsaW5lYmVsb3cgPSAweDFlOTU7CiAgdC56bW9ub3NwYWNlID0gMHhmZjVhOwogIHQuem9oaXJhZ2FuYSA9IDB4MzA1ZTsKICB0Lnpva2F0YWthbmEgPSAweDMwYmU7CiAgdC56cGFyZW4gPSAweDI0YjU7CiAgdC56cmV0cm9mbGV4aG9vayA9IDB4MDI5MDsKICB0LnpzdHJva2UgPSAweDAxYjY7CiAgdC56dWhpcmFnYW5hID0gMHgzMDVhOwogIHQuenVrYXRha2FuYSA9IDB4MzBiYTsKICB0WyIubm90ZGVmIl0gPSAweDAwMDA7CiAgdC5hbmdicmFja2V0bGVmdGJpZyA9IDB4MjMyOTsKICB0LmFuZ2JyYWNrZXRsZWZ0QmlnID0gMHgyMzI5OwogIHQuYW5nYnJhY2tldGxlZnRiaWdnID0gMHgyMzI5OwogIHQuYW5nYnJhY2tldGxlZnRCaWdnID0gMHgyMzI5OwogIHQuYW5nYnJhY2tldHJpZ2h0QmlnID0gMHgyMzJhOwogIHQuYW5nYnJhY2tldHJpZ2h0YmlnID0gMHgyMzJhOwogIHQuYW5nYnJhY2tldHJpZ2h0QmlnZyA9IDB4MjMyYTsKICB0LmFuZ2JyYWNrZXRyaWdodGJpZ2cgPSAweDIzMmE7CiAgdC5hcnJvd2hvb2tsZWZ0ID0gMHgyMWFhOwogIHQuYXJyb3dob29rcmlnaHQgPSAweDIxYTk7CiAgdC5hcnJvd2xlZnR0b3BoYWxmID0gMHgyMWJjOwogIHQuYXJyb3dsZWZ0Ym90aGFsZiA9IDB4MjFiZDsKICB0LmFycm93bm9ydGhlYXN0ID0gMHgyMTk3OwogIHQuYXJyb3dub3J0aHdlc3QgPSAweDIxOTY7CiAgdC5hcnJvd3JpZ2h0dG9waGFsZiA9IDB4MjFjMDsKICB0LmFycm93cmlnaHRib3RoYWxmID0gMHgyMWMxOwogIHQuYXJyb3dzb3V0aGVhc3QgPSAweDIxOTg7CiAgdC5hcnJvd3NvdXRod2VzdCA9IDB4MjE5OTsKICB0LmJhY2tzbGFzaGJpZyA9IDB4MjIxNjsKICB0LmJhY2tzbGFzaEJpZyA9IDB4MjIxNjsKICB0LmJhY2tzbGFzaEJpZ2cgPSAweDIyMTY7CiAgdC5iYWNrc2xhc2hiaWdnID0gMHgyMjE2OwogIHQuYmFyZGJsID0gMHgyMDE2OwogIHQuYnJhY2VodGlwZG93bmxlZnQgPSAweGZlMzc7CiAgdC5icmFjZWh0aXBkb3ducmlnaHQgPSAweGZlMzc7CiAgdC5icmFjZWh0aXB1cGxlZnQgPSAweGZlMzg7CiAgdC5icmFjZWh0aXB1cHJpZ2h0ID0gMHhmZTM4OwogIHQuYnJhY2VsZWZ0QmlnID0gMHgwMDdiOwogIHQuYnJhY2VsZWZ0YmlnID0gMHgwMDdiOwogIHQuYnJhY2VsZWZ0YmlnZyA9IDB4MDA3YjsKICB0LmJyYWNlbGVmdEJpZ2cgPSAweDAwN2I7CiAgdC5icmFjZXJpZ2h0QmlnID0gMHgwMDdkOwogIHQuYnJhY2VyaWdodGJpZyA9IDB4MDA3ZDsKICB0LmJyYWNlcmlnaHRiaWdnID0gMHgwMDdkOwogIHQuYnJhY2VyaWdodEJpZ2cgPSAweDAwN2Q7CiAgdC5icmFja2V0bGVmdGJpZyA9IDB4MDA1YjsKICB0LmJyYWNrZXRsZWZ0QmlnID0gMHgwMDViOwogIHQuYnJhY2tldGxlZnRiaWdnID0gMHgwMDViOwogIHQuYnJhY2tldGxlZnRCaWdnID0gMHgwMDViOwogIHQuYnJhY2tldHJpZ2h0QmlnID0gMHgwMDVkOwogIHQuYnJhY2tldHJpZ2h0YmlnID0gMHgwMDVkOwogIHQuYnJhY2tldHJpZ2h0YmlnZyA9IDB4MDA1ZDsKICB0LmJyYWNrZXRyaWdodEJpZ2cgPSAweDAwNWQ7CiAgdC5jZWlsaW5nbGVmdGJpZyA9IDB4MjMwODsKICB0LmNlaWxpbmdsZWZ0QmlnID0gMHgyMzA4OwogIHQuY2VpbGluZ2xlZnRCaWdnID0gMHgyMzA4OwogIHQuY2VpbGluZ2xlZnRiaWdnID0gMHgyMzA4OwogIHQuY2VpbGluZ3JpZ2h0YmlnID0gMHgyMzA5OwogIHQuY2VpbGluZ3JpZ2h0QmlnID0gMHgyMzA5OwogIHQuY2VpbGluZ3JpZ2h0YmlnZyA9IDB4MjMwOTsKICB0LmNlaWxpbmdyaWdodEJpZ2cgPSAweDIzMDk7CiAgdC5jaXJjbGVkb3RkaXNwbGF5ID0gMHgyMjk5OwogIHQuY2lyY2xlZG90dGV4dCA9IDB4MjI5OTsKICB0LmNpcmNsZW11bHRpcGx5ZGlzcGxheSA9IDB4MjI5NzsKICB0LmNpcmNsZW11bHRpcGx5dGV4dCA9IDB4MjI5NzsKICB0LmNpcmNsZXBsdXNkaXNwbGF5ID0gMHgyMjk1OwogIHQuY2lyY2xlcGx1c3RleHQgPSAweDIyOTU7CiAgdC5jb250aW50ZWdyYWxkaXNwbGF5ID0gMHgyMjJlOwogIHQuY29udGludGVncmFsdGV4dCA9IDB4MjIyZTsKICB0LmNvcHJvZHVjdGRpc3BsYXkgPSAweDIyMTA7CiAgdC5jb3Byb2R1Y3R0ZXh0ID0gMHgyMjEwOwogIHQuZmxvb3JsZWZ0QmlnID0gMHgyMzBhOwogIHQuZmxvb3JsZWZ0YmlnID0gMHgyMzBhOwogIHQuZmxvb3JsZWZ0YmlnZyA9IDB4MjMwYTsKICB0LmZsb29ybGVmdEJpZ2cgPSAweDIzMGE7CiAgdC5mbG9vcnJpZ2h0YmlnID0gMHgyMzBiOwogIHQuZmxvb3JyaWdodEJpZyA9IDB4MjMwYjsKICB0LmZsb29ycmlnaHRCaWdnID0gMHgyMzBiOwogIHQuZmxvb3JyaWdodGJpZ2cgPSAweDIzMGI7CiAgdC5oYXR3aWRlID0gMHgwMzAyOwogIHQuaGF0d2lkZXIgPSAweDAzMDI7CiAgdC5oYXR3aWRlc3QgPSAweDAzMDI7CiAgdC5pbnRlcmNhbCA9IDB4MWQ0MDsKICB0LmludGVncmFsZGlzcGxheSA9IDB4MjIyYjsKICB0LmludGVncmFsdGV4dCA9IDB4MjIyYjsKICB0LmludGVyc2VjdGlvbmRpc3BsYXkgPSAweDIyYzI7CiAgdC5pbnRlcnNlY3Rpb250ZXh0ID0gMHgyMmMyOwogIHQubG9naWNhbGFuZGRpc3BsYXkgPSAweDIyMjc7CiAgdC5sb2dpY2FsYW5kdGV4dCA9IDB4MjIyNzsKICB0LmxvZ2ljYWxvcmRpc3BsYXkgPSAweDIyMjg7CiAgdC5sb2dpY2Fsb3J0ZXh0ID0gMHgyMjI4OwogIHQucGFyZW5sZWZ0QmlnID0gMHgwMDI4OwogIHQucGFyZW5sZWZ0YmlnID0gMHgwMDI4OwogIHQucGFyZW5sZWZ0QmlnZyA9IDB4MDAyODsKICB0LnBhcmVubGVmdGJpZ2cgPSAweDAwMjg7CiAgdC5wYXJlbnJpZ2h0QmlnID0gMHgwMDI5OwogIHQucGFyZW5yaWdodGJpZyA9IDB4MDAyOTsKICB0LnBhcmVucmlnaHRCaWdnID0gMHgwMDI5OwogIHQucGFyZW5yaWdodGJpZ2cgPSAweDAwMjk7CiAgdC5wcmltZSA9IDB4MjAzMjsKICB0LnByb2R1Y3RkaXNwbGF5ID0gMHgyMjBmOwogIHQucHJvZHVjdHRleHQgPSAweDIyMGY7CiAgdC5yYWRpY2FsYmlnID0gMHgyMjFhOwogIHQucmFkaWNhbEJpZyA9IDB4MjIxYTsKICB0LnJhZGljYWxCaWdnID0gMHgyMjFhOwogIHQucmFkaWNhbGJpZ2cgPSAweDIyMWE7CiAgdC5yYWRpY2FsYnQgPSAweDIyMWE7CiAgdC5yYWRpY2FsdHAgPSAweDIyMWE7CiAgdC5yYWRpY2FsdmVydGV4ID0gMHgyMjFhOwogIHQuc2xhc2hiaWcgPSAweDAwMmY7CiAgdC5zbGFzaEJpZyA9IDB4MDAyZjsKICB0LnNsYXNoQmlnZyA9IDB4MDAyZjsKICB0LnNsYXNoYmlnZyA9IDB4MDAyZjsKICB0LnN1bW1hdGlvbmRpc3BsYXkgPSAweDIyMTE7CiAgdC5zdW1tYXRpb250ZXh0ID0gMHgyMjExOwogIHQudGlsZGV3aWRlID0gMHgwMmRjOwogIHQudGlsZGV3aWRlciA9IDB4MDJkYzsKICB0LnRpbGRld2lkZXN0ID0gMHgwMmRjOwogIHQudW5pb25kaXNwbGF5ID0gMHgyMmMzOwogIHQudW5pb25tdWx0aWRpc3BsYXkgPSAweDIyOGU7CiAgdC51bmlvbm11bHRpdGV4dCA9IDB4MjI4ZTsKICB0LnVuaW9uc3FkaXNwbGF5ID0gMHgyMjk0OwogIHQudW5pb25zcXRleHQgPSAweDIyOTQ7CiAgdC51bmlvbnRleHQgPSAweDIyYzM7CiAgdC52ZXh0ZW5kZG91YmxlID0gMHgyMjI1OwogIHQudmV4dGVuZHNpbmdsZSA9IDB4MjIyMzsKfSk7CmNvbnN0IGdldERpbmdiYXRzR2x5cGhzVW5pY29kZSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHQuc3BhY2UgPSAweDAwMjA7CiAgdC5hMSA9IDB4MjcwMTsKICB0LmEyID0gMHgyNzAyOwogIHQuYTIwMiA9IDB4MjcwMzsKICB0LmEzID0gMHgyNzA0OwogIHQuYTQgPSAweDI2MGU7CiAgdC5hNSA9IDB4MjcwNjsKICB0LmExMTkgPSAweDI3MDc7CiAgdC5hMTE4ID0gMHgyNzA4OwogIHQuYTExNyA9IDB4MjcwOTsKICB0LmExMSA9IDB4MjYxYjsKICB0LmExMiA9IDB4MjYxZTsKICB0LmExMyA9IDB4MjcwYzsKICB0LmExNCA9IDB4MjcwZDsKICB0LmExNSA9IDB4MjcwZTsKICB0LmExNiA9IDB4MjcwZjsKICB0LmExMDUgPSAweDI3MTA7CiAgdC5hMTcgPSAweDI3MTE7CiAgdC5hMTggPSAweDI3MTI7CiAgdC5hMTkgPSAweDI3MTM7CiAgdC5hMjAgPSAweDI3MTQ7CiAgdC5hMjEgPSAweDI3MTU7CiAgdC5hMjIgPSAweDI3MTY7CiAgdC5hMjMgPSAweDI3MTc7CiAgdC5hMjQgPSAweDI3MTg7CiAgdC5hMjUgPSAweDI3MTk7CiAgdC5hMjYgPSAweDI3MWE7CiAgdC5hMjcgPSAweDI3MWI7CiAgdC5hMjggPSAweDI3MWM7CiAgdC5hNiA9IDB4MjcxZDsKICB0LmE3ID0gMHgyNzFlOwogIHQuYTggPSAweDI3MWY7CiAgdC5hOSA9IDB4MjcyMDsKICB0LmExMCA9IDB4MjcyMTsKICB0LmEyOSA9IDB4MjcyMjsKICB0LmEzMCA9IDB4MjcyMzsKICB0LmEzMSA9IDB4MjcyNDsKICB0LmEzMiA9IDB4MjcyNTsKICB0LmEzMyA9IDB4MjcyNjsKICB0LmEzNCA9IDB4MjcyNzsKICB0LmEzNSA9IDB4MjYwNTsKICB0LmEzNiA9IDB4MjcyOTsKICB0LmEzNyA9IDB4MjcyYTsKICB0LmEzOCA9IDB4MjcyYjsKICB0LmEzOSA9IDB4MjcyYzsKICB0LmE0MCA9IDB4MjcyZDsKICB0LmE0MSA9IDB4MjcyZTsKICB0LmE0MiA9IDB4MjcyZjsKICB0LmE0MyA9IDB4MjczMDsKICB0LmE0NCA9IDB4MjczMTsKICB0LmE0NSA9IDB4MjczMjsKICB0LmE0NiA9IDB4MjczMzsKICB0LmE0NyA9IDB4MjczNDsKICB0LmE0OCA9IDB4MjczNTsKICB0LmE0OSA9IDB4MjczNjsKICB0LmE1MCA9IDB4MjczNzsKICB0LmE1MSA9IDB4MjczODsKICB0LmE1MiA9IDB4MjczOTsKICB0LmE1MyA9IDB4MjczYTsKICB0LmE1NCA9IDB4MjczYjsKICB0LmE1NSA9IDB4MjczYzsKICB0LmE1NiA9IDB4MjczZDsKICB0LmE1NyA9IDB4MjczZTsKICB0LmE1OCA9IDB4MjczZjsKICB0LmE1OSA9IDB4Mjc0MDsKICB0LmE2MCA9IDB4Mjc0MTsKICB0LmE2MSA9IDB4Mjc0MjsKICB0LmE2MiA9IDB4Mjc0MzsKICB0LmE2MyA9IDB4Mjc0NDsKICB0LmE2NCA9IDB4Mjc0NTsKICB0LmE2NSA9IDB4Mjc0NjsKICB0LmE2NiA9IDB4Mjc0NzsKICB0LmE2NyA9IDB4Mjc0ODsKICB0LmE2OCA9IDB4Mjc0OTsKICB0LmE2OSA9IDB4Mjc0YTsKICB0LmE3MCA9IDB4Mjc0YjsKICB0LmE3MSA9IDB4MjVjZjsKICB0LmE3MiA9IDB4Mjc0ZDsKICB0LmE3MyA9IDB4MjVhMDsKICB0LmE3NCA9IDB4Mjc0ZjsKICB0LmEyMDMgPSAweDI3NTA7CiAgdC5hNzUgPSAweDI3NTE7CiAgdC5hMjA0ID0gMHgyNzUyOwogIHQuYTc2ID0gMHgyNWIyOwogIHQuYTc3ID0gMHgyNWJjOwogIHQuYTc4ID0gMHgyNWM2OwogIHQuYTc5ID0gMHgyNzU2OwogIHQuYTgxID0gMHgyNWQ3OwogIHQuYTgyID0gMHgyNzU4OwogIHQuYTgzID0gMHgyNzU5OwogIHQuYTg0ID0gMHgyNzVhOwogIHQuYTk3ID0gMHgyNzViOwogIHQuYTk4ID0gMHgyNzVjOwogIHQuYTk5ID0gMHgyNzVkOwogIHQuYTEwMCA9IDB4Mjc1ZTsKICB0LmExMDEgPSAweDI3NjE7CiAgdC5hMTAyID0gMHgyNzYyOwogIHQuYTEwMyA9IDB4Mjc2MzsKICB0LmExMDQgPSAweDI3NjQ7CiAgdC5hMTA2ID0gMHgyNzY1OwogIHQuYTEwNyA9IDB4Mjc2NjsKICB0LmExMDggPSAweDI3Njc7CiAgdC5hMTEyID0gMHgyNjYzOwogIHQuYTExMSA9IDB4MjY2NjsKICB0LmExMTAgPSAweDI2NjU7CiAgdC5hMTA5ID0gMHgyNjYwOwogIHQuYTEyMCA9IDB4MjQ2MDsKICB0LmExMjEgPSAweDI0NjE7CiAgdC5hMTIyID0gMHgyNDYyOwogIHQuYTEyMyA9IDB4MjQ2MzsKICB0LmExMjQgPSAweDI0NjQ7CiAgdC5hMTI1ID0gMHgyNDY1OwogIHQuYTEyNiA9IDB4MjQ2NjsKICB0LmExMjcgPSAweDI0Njc7CiAgdC5hMTI4ID0gMHgyNDY4OwogIHQuYTEyOSA9IDB4MjQ2OTsKICB0LmExMzAgPSAweDI3NzY7CiAgdC5hMTMxID0gMHgyNzc3OwogIHQuYTEzMiA9IDB4Mjc3ODsKICB0LmExMzMgPSAweDI3Nzk7CiAgdC5hMTM0ID0gMHgyNzdhOwogIHQuYTEzNSA9IDB4Mjc3YjsKICB0LmExMzYgPSAweDI3N2M7CiAgdC5hMTM3ID0gMHgyNzdkOwogIHQuYTEzOCA9IDB4Mjc3ZTsKICB0LmExMzkgPSAweDI3N2Y7CiAgdC5hMTQwID0gMHgyNzgwOwogIHQuYTE0MSA9IDB4Mjc4MTsKICB0LmExNDIgPSAweDI3ODI7CiAgdC5hMTQzID0gMHgyNzgzOwogIHQuYTE0NCA9IDB4Mjc4NDsKICB0LmExNDUgPSAweDI3ODU7CiAgdC5hMTQ2ID0gMHgyNzg2OwogIHQuYTE0NyA9IDB4Mjc4NzsKICB0LmExNDggPSAweDI3ODg7CiAgdC5hMTQ5ID0gMHgyNzg5OwogIHQuYTE1MCA9IDB4Mjc4YTsKICB0LmExNTEgPSAweDI3OGI7CiAgdC5hMTUyID0gMHgyNzhjOwogIHQuYTE1MyA9IDB4Mjc4ZDsKICB0LmExNTQgPSAweDI3OGU7CiAgdC5hMTU1ID0gMHgyNzhmOwogIHQuYTE1NiA9IDB4Mjc5MDsKICB0LmExNTcgPSAweDI3OTE7CiAgdC5hMTU4ID0gMHgyNzkyOwogIHQuYTE1OSA9IDB4Mjc5MzsKICB0LmExNjAgPSAweDI3OTQ7CiAgdC5hMTYxID0gMHgyMTkyOwogIHQuYTE2MyA9IDB4MjE5NDsKICB0LmExNjQgPSAweDIxOTU7CiAgdC5hMTk2ID0gMHgyNzk4OwogIHQuYTE2NSA9IDB4Mjc5OTsKICB0LmExOTIgPSAweDI3OWE7CiAgdC5hMTY2ID0gMHgyNzliOwogIHQuYTE2NyA9IDB4Mjc5YzsKICB0LmExNjggPSAweDI3OWQ7CiAgdC5hMTY5ID0gMHgyNzllOwogIHQuYTE3MCA9IDB4Mjc5ZjsKICB0LmExNzEgPSAweDI3YTA7CiAgdC5hMTcyID0gMHgyN2ExOwogIHQuYTE3MyA9IDB4MjdhMjsKICB0LmExNjIgPSAweDI3YTM7CiAgdC5hMTc0ID0gMHgyN2E0OwogIHQuYTE3NSA9IDB4MjdhNTsKICB0LmExNzYgPSAweDI3YTY7CiAgdC5hMTc3ID0gMHgyN2E3OwogIHQuYTE3OCA9IDB4MjdhODsKICB0LmExNzkgPSAweDI3YTk7CiAgdC5hMTkzID0gMHgyN2FhOwogIHQuYTE4MCA9IDB4MjdhYjsKICB0LmExOTkgPSAweDI3YWM7CiAgdC5hMTgxID0gMHgyN2FkOwogIHQuYTIwMCA9IDB4MjdhZTsKICB0LmExODIgPSAweDI3YWY7CiAgdC5hMjAxID0gMHgyN2IxOwogIHQuYTE4MyA9IDB4MjdiMjsKICB0LmExODQgPSAweDI3YjM7CiAgdC5hMTk3ID0gMHgyN2I0OwogIHQuYTE4NSA9IDB4MjdiNTsKICB0LmExOTQgPSAweDI3YjY7CiAgdC5hMTk4ID0gMHgyN2I3OwogIHQuYTE4NiA9IDB4MjdiODsKICB0LmExOTUgPSAweDI3Yjk7CiAgdC5hMTg3ID0gMHgyN2JhOwogIHQuYTE4OCA9IDB4MjdiYjsKICB0LmExODkgPSAweDI3YmM7CiAgdC5hMTkwID0gMHgyN2JkOwogIHQuYTE5MSA9IDB4MjdiZTsKICB0LmE4OSA9IDB4Mjc2ODsKICB0LmE5MCA9IDB4Mjc2OTsKICB0LmE5MyA9IDB4Mjc2YTsKICB0LmE5NCA9IDB4Mjc2YjsKICB0LmE5MSA9IDB4Mjc2YzsKICB0LmE5MiA9IDB4Mjc2ZDsKICB0LmEyMDUgPSAweDI3NmU7CiAgdC5hODUgPSAweDI3NmY7CiAgdC5hMjA2ID0gMHgyNzcwOwogIHQuYTg2ID0gMHgyNzcxOwogIHQuYTg3ID0gMHgyNzcyOwogIHQuYTg4ID0gMHgyNzczOwogIHQuYTk1ID0gMHgyNzc0OwogIHQuYTk2ID0gMHgyNzc1OwogIHRbIi5ub3RkZWYiXSA9IDB4MDAwMDsKfSk7Cgo7Ly8gLi9zcmMvY29yZS91bmljb2RlLmpzCgpjb25zdCBnZXRTcGVjaWFsUFVBU3ltYm9scyA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHRbNjM3MjFdID0gMHgwMGE5OwogIHRbNjMxOTNdID0gMHgwMGE5OwogIHRbNjM3MjBdID0gMHgwMGFlOwogIHRbNjMxOTRdID0gMHgwMGFlOwogIHRbNjM3MjJdID0gMHgyMTIyOwogIHRbNjMxOTVdID0gMHgyMTIyOwogIHRbNjM3MjldID0gMHgyM2E3OwogIHRbNjM3MzBdID0gMHgyM2E4OwogIHRbNjM3MzFdID0gMHgyM2E5OwogIHRbNjM3NDBdID0gMHgyM2FiOwogIHRbNjM3NDFdID0gMHgyM2FjOwogIHRbNjM3NDJdID0gMHgyM2FkOwogIHRbNjM3MjZdID0gMHgyM2ExOwogIHRbNjM3MjddID0gMHgyM2EyOwogIHRbNjM3MjhdID0gMHgyM2EzOwogIHRbNjM3MzddID0gMHgyM2E0OwogIHRbNjM3MzhdID0gMHgyM2E1OwogIHRbNjM3MzldID0gMHgyM2E2OwogIHRbNjM3MjNdID0gMHgyMzliOwogIHRbNjM3MjRdID0gMHgyMzljOwogIHRbNjM3MjVdID0gMHgyMzlkOwogIHRbNjM3MzRdID0gMHgyMzllOwogIHRbNjM3MzVdID0gMHgyMzlmOwogIHRbNjM3MzZdID0gMHgyM2EwOwp9KTsKZnVuY3Rpb24gbWFwU3BlY2lhbFVuaWNvZGVWYWx1ZXMoY29kZSkgewogIGlmIChjb2RlID49IDB4ZmZmMCAmJiBjb2RlIDw9IDB4ZmZmZikgewogICAgcmV0dXJuIDA7CiAgfSBlbHNlIGlmIChjb2RlID49IDB4ZjYwMCAmJiBjb2RlIDw9IDB4ZjhmZikgewogICAgcmV0dXJuIGdldFNwZWNpYWxQVUFTeW1ib2xzKClbY29kZV0gfHwgY29kZTsKICB9IGVsc2UgaWYgKGNvZGUgPT09IDB4MDBhZCkgewogICAgcmV0dXJuIDB4MDAyZDsKICB9CiAgcmV0dXJuIGNvZGU7Cn0KZnVuY3Rpb24gZ2V0VW5pY29kZUZvckdseXBoKG5hbWUsIGdseXBoc1VuaWNvZGVNYXApIHsKICBsZXQgdW5pY29kZSA9IGdseXBoc1VuaWNvZGVNYXBbbmFtZV07CiAgaWYgKHVuaWNvZGUgIT09IHVuZGVmaW5lZCkgewogICAgcmV0dXJuIHVuaWNvZGU7CiAgfQogIGlmICghbmFtZSkgewogICAgcmV0dXJuIC0xOwogIH0KICBpZiAobmFtZVswXSA9PT0gInUiKSB7CiAgICBjb25zdCBuYW1lTGVuID0gbmFtZS5sZW5ndGg7CiAgICBsZXQgaGV4U3RyOwogICAgaWYgKG5hbWVMZW4gPT09IDcgJiYgbmFtZVsxXSA9PT0gIm4iICYmIG5hbWVbMl0gPT09ICJpIikgewogICAgICBoZXhTdHIgPSBuYW1lLnN1YnN0cmluZygzKTsKICAgIH0gZWxzZSBpZiAobmFtZUxlbiA+PSA1ICYmIG5hbWVMZW4gPD0gNykgewogICAgICBoZXhTdHIgPSBuYW1lLnN1YnN0cmluZygxKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGlmIChoZXhTdHIgPT09IGhleFN0ci50b1VwcGVyQ2FzZSgpKSB7CiAgICAgIHVuaWNvZGUgPSBwYXJzZUludChoZXhTdHIsIDE2KTsKICAgICAgaWYgKHVuaWNvZGUgPj0gMCkgewogICAgICAgIHJldHVybiB1bmljb2RlOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiAtMTsKfQpjb25zdCBVbmljb2RlUmFuZ2VzID0gW1sweDAwMDAsIDB4MDA3Zl0sIFsweDAwODAsIDB4MDBmZl0sIFsweDAxMDAsIDB4MDE3Zl0sIFsweDAxODAsIDB4MDI0Zl0sIFsweDAyNTAsIDB4MDJhZiwgMHgxZDAwLCAweDFkN2YsIDB4MWQ4MCwgMHgxZGJmXSwgWzB4MDJiMCwgMHgwMmZmLCAweGE3MDAsIDB4YTcxZl0sIFsweDAzMDAsIDB4MDM2ZiwgMHgxZGMwLCAweDFkZmZdLCBbMHgwMzcwLCAweDAzZmZdLCBbMHgyYzgwLCAweDJjZmZdLCBbMHgwNDAwLCAweDA0ZmYsIDB4MDUwMCwgMHgwNTJmLCAweDJkZTAsIDB4MmRmZiwgMHhhNjQwLCAweGE2OWZdLCBbMHgwNTMwLCAweDA1OGZdLCBbMHgwNTkwLCAweDA1ZmZdLCBbMHhhNTAwLCAweGE2M2ZdLCBbMHgwNjAwLCAweDA2ZmYsIDB4MDc1MCwgMHgwNzdmXSwgWzB4MDdjMCwgMHgwN2ZmXSwgWzB4MDkwMCwgMHgwOTdmXSwgWzB4MDk4MCwgMHgwOWZmXSwgWzB4MGEwMCwgMHgwYTdmXSwgWzB4MGE4MCwgMHgwYWZmXSwgWzB4MGIwMCwgMHgwYjdmXSwgWzB4MGI4MCwgMHgwYmZmXSwgWzB4MGMwMCwgMHgwYzdmXSwgWzB4MGM4MCwgMHgwY2ZmXSwgWzB4MGQwMCwgMHgwZDdmXSwgWzB4MGUwMCwgMHgwZTdmXSwgWzB4MGU4MCwgMHgwZWZmXSwgWzB4MTBhMCwgMHgxMGZmLCAweDJkMDAsIDB4MmQyZl0sIFsweDFiMDAsIDB4MWI3Zl0sIFsweDExMDAsIDB4MTFmZl0sIFsweDFlMDAsIDB4MWVmZiwgMHgyYzYwLCAweDJjN2YsIDB4YTcyMCwgMHhhN2ZmXSwgWzB4MWYwMCwgMHgxZmZmXSwgWzB4MjAwMCwgMHgyMDZmLCAweDJlMDAsIDB4MmU3Zl0sIFsweDIwNzAsIDB4MjA5Zl0sIFsweDIwYTAsIDB4MjBjZl0sIFsweDIwZDAsIDB4MjBmZl0sIFsweDIxMDAsIDB4MjE0Zl0sIFsweDIxNTAsIDB4MjE4Zl0sIFsweDIxOTAsIDB4MjFmZiwgMHgyN2YwLCAweDI3ZmYsIDB4MjkwMCwgMHgyOTdmLCAweDJiMDAsIDB4MmJmZl0sIFsweDIyMDAsIDB4MjJmZiwgMHgyYTAwLCAweDJhZmYsIDB4MjdjMCwgMHgyN2VmLCAweDI5ODAsIDB4MjlmZl0sIFsweDIzMDAsIDB4MjNmZl0sIFsweDI0MDAsIDB4MjQzZl0sIFsweDI0NDAsIDB4MjQ1Zl0sIFsweDI0NjAsIDB4MjRmZl0sIFsweDI1MDAsIDB4MjU3Zl0sIFsweDI1ODAsIDB4MjU5Zl0sIFsweDI1YTAsIDB4MjVmZl0sIFsweDI2MDAsIDB4MjZmZl0sIFsweDI3MDAsIDB4MjdiZl0sIFsweDMwMDAsIDB4MzAzZl0sIFsweDMwNDAsIDB4MzA5Zl0sIFsweDMwYTAsIDB4MzBmZiwgMHgzMWYwLCAweDMxZmZdLCBbMHgzMTAwLCAweDMxMmYsIDB4MzFhMCwgMHgzMWJmXSwgWzB4MzEzMCwgMHgzMThmXSwgWzB4YTg0MCwgMHhhODdmXSwgWzB4MzIwMCwgMHgzMmZmXSwgWzB4MzMwMCwgMHgzM2ZmXSwgWzB4YWMwMCwgMHhkN2FmXSwgWzB4ZDgwMCwgMHhkZmZmXSwgWzB4MTA5MDAsIDB4MTA5MWZdLCBbMHg0ZTAwLCAweDlmZmYsIDB4MmU4MCwgMHgyZWZmLCAweDJmMDAsIDB4MmZkZiwgMHgyZmYwLCAweDJmZmYsIDB4MzQwMCwgMHg0ZGJmLCAweDIwMDAwLCAweDJhNmRmLCAweDMxOTAsIDB4MzE5Zl0sIFsweGUwMDAsIDB4ZjhmZl0sIFsweDMxYzAsIDB4MzFlZiwgMHhmOTAwLCAweGZhZmYsIDB4MmY4MDAsIDB4MmZhMWZdLCBbMHhmYjAwLCAweGZiNGZdLCBbMHhmYjUwLCAweGZkZmZdLCBbMHhmZTIwLCAweGZlMmZdLCBbMHhmZTEwLCAweGZlMWZdLCBbMHhmZTUwLCAweGZlNmZdLCBbMHhmZTcwLCAweGZlZmZdLCBbMHhmZjAwLCAweGZmZWZdLCBbMHhmZmYwLCAweGZmZmZdLCBbMHgwZjAwLCAweDBmZmZdLCBbMHgwNzAwLCAweDA3NGZdLCBbMHgwNzgwLCAweDA3YmZdLCBbMHgwZDgwLCAweDBkZmZdLCBbMHgxMDAwLCAweDEwOWZdLCBbMHgxMjAwLCAweDEzN2YsIDB4MTM4MCwgMHgxMzlmLCAweDJkODAsIDB4MmRkZl0sIFsweDEzYTAsIDB4MTNmZl0sIFsweDE0MDAsIDB4MTY3Zl0sIFsweDE2ODAsIDB4MTY5Zl0sIFsweDE2YTAsIDB4MTZmZl0sIFsweDE3ODAsIDB4MTdmZl0sIFsweDE4MDAsIDB4MThhZl0sIFsweDI4MDAsIDB4MjhmZl0sIFsweGEwMDAsIDB4YTQ4Zl0sIFsweDE3MDAsIDB4MTcxZiwgMHgxNzIwLCAweDE3M2YsIDB4MTc0MCwgMHgxNzVmLCAweDE3NjAsIDB4MTc3Zl0sIFsweDEwMzAwLCAweDEwMzJmXSwgWzB4MTAzMzAsIDB4MTAzNGZdLCBbMHgxMDQwMCwgMHgxMDQ0Zl0sIFsweDFkMDAwLCAweDFkMGZmLCAweDFkMTAwLCAweDFkMWZmLCAweDFkMjAwLCAweDFkMjRmXSwgWzB4MWQ0MDAsIDB4MWQ3ZmZdLCBbMHhmZjAwMCwgMHhmZmZmZF0sIFsweGZlMDAsIDB4ZmUwZiwgMHhlMDEwMCwgMHhlMDFlZl0sIFsweGUwMDAwLCAweGUwMDdmXSwgWzB4MTkwMCwgMHgxOTRmXSwgWzB4MTk1MCwgMHgxOTdmXSwgWzB4MTk4MCwgMHgxOWRmXSwgWzB4MWEwMCwgMHgxYTFmXSwgWzB4MmMwMCwgMHgyYzVmXSwgWzB4MmQzMCwgMHgyZDdmXSwgWzB4NGRjMCwgMHg0ZGZmXSwgWzB4YTgwMCwgMHhhODJmXSwgWzB4MTAwMDAsIDB4MTAwN2YsIDB4MTAwODAsIDB4MTAwZmYsIDB4MTAxMDAsIDB4MTAxM2ZdLCBbMHgxMDE0MCwgMHgxMDE4Zl0sIFsweDEwMzgwLCAweDEwMzlmXSwgWzB4MTAzYTAsIDB4MTAzZGZdLCBbMHgxMDQ1MCwgMHgxMDQ3Zl0sIFsweDEwNDgwLCAweDEwNGFmXSwgWzB4MTA4MDAsIDB4MTA4M2ZdLCBbMHgxMGEwMCwgMHgxMGE1Zl0sIFsweDFkMzAwLCAweDFkMzVmXSwgWzB4MTIwMDAsIDB4MTIzZmYsIDB4MTI0MDAsIDB4MTI0N2ZdLCBbMHgxZDM2MCwgMHgxZDM3Zl0sIFsweDFiODAsIDB4MWJiZl0sIFsweDFjMDAsIDB4MWM0Zl0sIFsweDFjNTAsIDB4MWM3Zl0sIFsweGE4ODAsIDB4YThkZl0sIFsweGE5MDAsIDB4YTkyZl0sIFsweGE5MzAsIDB4YTk1Zl0sIFsweGFhMDAsIDB4YWE1Zl0sIFsweDEwMTkwLCAweDEwMWNmXSwgWzB4MTAxZDAsIDB4MTAxZmZdLCBbMHgxMDJhMCwgMHgxMDJkZiwgMHgxMDI4MCwgMHgxMDI5ZiwgMHgxMDkyMCwgMHgxMDkzZl0sIFsweDFmMDMwLCAweDFmMDlmLCAweDFmMDAwLCAweDFmMDJmXV07CmZ1bmN0aW9uIGdldFVuaWNvZGVSYW5nZUZvcih2YWx1ZSwgbGFzdFBvc2l0aW9uID0gLTEpIHsKICBpZiAobGFzdFBvc2l0aW9uICE9PSAtMSkgewogICAgY29uc3QgcmFuZ2UgPSBVbmljb2RlUmFuZ2VzW2xhc3RQb3NpdGlvbl07CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSByYW5nZS5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7CiAgICAgIGlmICh2YWx1ZSA+PSByYW5nZVtpXSAmJiB2YWx1ZSA8PSByYW5nZVtpICsgMV0pIHsKICAgICAgICByZXR1cm4gbGFzdFBvc2l0aW9uOwogICAgICB9CiAgICB9CiAgfQogIGZvciAobGV0IGkgPSAwLCBpaSA9IFVuaWNvZGVSYW5nZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgY29uc3QgcmFuZ2UgPSBVbmljb2RlUmFuZ2VzW2ldOwogICAgZm9yIChsZXQgaiA9IDAsIGpqID0gcmFuZ2UubGVuZ3RoOyBqIDwgamo7IGogKz0gMikgewogICAgICBpZiAodmFsdWUgPj0gcmFuZ2Vbal0gJiYgdmFsdWUgPD0gcmFuZ2VbaiArIDFdKSB7CiAgICAgICAgcmV0dXJuIGk7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIC0xOwp9CmNvbnN0IFNwZWNpYWxDaGFyUmVnRXhwID0gbmV3IFJlZ0V4cCgiXihcXHMpfChcXHB7TW59KXwoXFxwe0NmfSkkIiwgInUiKTsKY29uc3QgQ2F0ZWdvcnlDYWNoZSA9IG5ldyBNYXAoKTsKZnVuY3Rpb24gZ2V0Q2hhclVuaWNvZGVDYXRlZ29yeShjaGFyKSB7CiAgY29uc3QgY2FjaGVkQ2F0ZWdvcnkgPSBDYXRlZ29yeUNhY2hlLmdldChjaGFyKTsKICBpZiAoY2FjaGVkQ2F0ZWdvcnkpIHsKICAgIHJldHVybiBjYWNoZWRDYXRlZ29yeTsKICB9CiAgY29uc3QgZ3JvdXBzID0gY2hhci5tYXRjaChTcGVjaWFsQ2hhclJlZ0V4cCk7CiAgY29uc3QgY2F0ZWdvcnkgPSB7CiAgICBpc1doaXRlc3BhY2U6ICEhZ3JvdXBzPy5bMV0sCiAgICBpc1plcm9XaWR0aERpYWNyaXRpYzogISFncm91cHM/LlsyXSwKICAgIGlzSW52aXNpYmxlRm9ybWF0TWFyazogISFncm91cHM/LlszXQogIH07CiAgQ2F0ZWdvcnlDYWNoZS5zZXQoY2hhciwgY2F0ZWdvcnkpOwogIHJldHVybiBjYXRlZ29yeTsKfQpmdW5jdGlvbiBjbGVhclVuaWNvZGVDYWNoZXMoKSB7CiAgQ2F0ZWdvcnlDYWNoZS5jbGVhcigpOwp9Cgo7Ly8gLi9zcmMvY29yZS9mb250c191dGlscy5qcwoKCgoKCmNvbnN0IFNFQUNfQU5BTFlTSVNfRU5BQkxFRCA9IHRydWU7CmNvbnN0IEZvbnRGbGFncyA9IHsKICBGaXhlZFBpdGNoOiAxLAogIFNlcmlmOiAyLAogIFN5bWJvbGljOiA0LAogIFNjcmlwdDogOCwKICBOb25zeW1ib2xpYzogMzIsCiAgSXRhbGljOiA2NCwKICBBbGxDYXA6IDY1NTM2LAogIFNtYWxsQ2FwOiAxMzEwNzIsCiAgRm9yY2VCb2xkOiAyNjIxNDQKfTsKY29uc3QgTWFjU3RhbmRhcmRHbHlwaE9yZGVyaW5nID0gWyIubm90ZGVmIiwgIi5udWxsIiwgIm5vbm1hcmtpbmdyZXR1cm4iLCAic3BhY2UiLCAiZXhjbGFtIiwgInF1b3RlZGJsIiwgIm51bWJlcnNpZ24iLCAiZG9sbGFyIiwgInBlcmNlbnQiLCAiYW1wZXJzYW5kIiwgInF1b3Rlc2luZ2xlIiwgInBhcmVubGVmdCIsICJwYXJlbnJpZ2h0IiwgImFzdGVyaXNrIiwgInBsdXMiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJzbGFzaCIsICJ6ZXJvIiwgIm9uZSIsICJ0d28iLCAidGhyZWUiLCAiZm91ciIsICJmaXZlIiwgInNpeCIsICJzZXZlbiIsICJlaWdodCIsICJuaW5lIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJsZXNzIiwgImVxdWFsIiwgImdyZWF0ZXIiLCAicXVlc3Rpb24iLCAiYXQiLCAiQSIsICJCIiwgIkMiLCAiRCIsICJFIiwgIkYiLCAiRyIsICJIIiwgIkkiLCAiSiIsICJLIiwgIkwiLCAiTSIsICJOIiwgIk8iLCAiUCIsICJRIiwgIlIiLCAiUyIsICJUIiwgIlUiLCAiViIsICJXIiwgIlgiLCAiWSIsICJaIiwgImJyYWNrZXRsZWZ0IiwgImJhY2tzbGFzaCIsICJicmFja2V0cmlnaHQiLCAiYXNjaWljaXJjdW0iLCAidW5kZXJzY29yZSIsICJncmF2ZSIsICJhIiwgImIiLCAiYyIsICJkIiwgImUiLCAiZiIsICJnIiwgImgiLCAiaSIsICJqIiwgImsiLCAibCIsICJtIiwgIm4iLCAibyIsICJwIiwgInEiLCAiciIsICJzIiwgInQiLCAidSIsICJ2IiwgInciLCAieCIsICJ5IiwgInoiLCAiYnJhY2VsZWZ0IiwgImJhciIsICJicmFjZXJpZ2h0IiwgImFzY2lpdGlsZGUiLCAiQWRpZXJlc2lzIiwgIkFyaW5nIiwgIkNjZWRpbGxhIiwgIkVhY3V0ZSIsICJOdGlsZGUiLCAiT2RpZXJlc2lzIiwgIlVkaWVyZXNpcyIsICJhYWN1dGUiLCAiYWdyYXZlIiwgImFjaXJjdW1mbGV4IiwgImFkaWVyZXNpcyIsICJhdGlsZGUiLCAiYXJpbmciLCAiY2NlZGlsbGEiLCAiZWFjdXRlIiwgImVncmF2ZSIsICJlY2lyY3VtZmxleCIsICJlZGllcmVzaXMiLCAiaWFjdXRlIiwgImlncmF2ZSIsICJpY2lyY3VtZmxleCIsICJpZGllcmVzaXMiLCAibnRpbGRlIiwgIm9hY3V0ZSIsICJvZ3JhdmUiLCAib2NpcmN1bWZsZXgiLCAib2RpZXJlc2lzIiwgIm90aWxkZSIsICJ1YWN1dGUiLCAidWdyYXZlIiwgInVjaXJjdW1mbGV4IiwgInVkaWVyZXNpcyIsICJkYWdnZXIiLCAiZGVncmVlIiwgImNlbnQiLCAic3RlcmxpbmciLCAic2VjdGlvbiIsICJidWxsZXQiLCAicGFyYWdyYXBoIiwgImdlcm1hbmRibHMiLCAicmVnaXN0ZXJlZCIsICJjb3B5cmlnaHQiLCAidHJhZGVtYXJrIiwgImFjdXRlIiwgImRpZXJlc2lzIiwgIm5vdGVxdWFsIiwgIkFFIiwgIk9zbGFzaCIsICJpbmZpbml0eSIsICJwbHVzbWludXMiLCAibGVzc2VxdWFsIiwgImdyZWF0ZXJlcXVhbCIsICJ5ZW4iLCAibXUiLCAicGFydGlhbGRpZmYiLCAic3VtbWF0aW9uIiwgInByb2R1Y3QiLCAicGkiLCAiaW50ZWdyYWwiLCAib3JkZmVtaW5pbmUiLCAib3JkbWFzY3VsaW5lIiwgIk9tZWdhIiwgImFlIiwgIm9zbGFzaCIsICJxdWVzdGlvbmRvd24iLCAiZXhjbGFtZG93biIsICJsb2dpY2Fsbm90IiwgInJhZGljYWwiLCAiZmxvcmluIiwgImFwcHJveGVxdWFsIiwgIkRlbHRhIiwgImd1aWxsZW1vdGxlZnQiLCAiZ3VpbGxlbW90cmlnaHQiLCAiZWxsaXBzaXMiLCAibm9uYnJlYWtpbmdzcGFjZSIsICJBZ3JhdmUiLCAiQXRpbGRlIiwgIk90aWxkZSIsICJPRSIsICJvZSIsICJlbmRhc2giLCAiZW1kYXNoIiwgInF1b3RlZGJsbGVmdCIsICJxdW90ZWRibHJpZ2h0IiwgInF1b3RlbGVmdCIsICJxdW90ZXJpZ2h0IiwgImRpdmlkZSIsICJsb3plbmdlIiwgInlkaWVyZXNpcyIsICJZZGllcmVzaXMiLCAiZnJhY3Rpb24iLCAiY3VycmVuY3kiLCAiZ3VpbHNpbmdsbGVmdCIsICJndWlsc2luZ2xyaWdodCIsICJmaSIsICJmbCIsICJkYWdnZXJkYmwiLCAicGVyaW9kY2VudGVyZWQiLCAicXVvdGVzaW5nbGJhc2UiLCAicXVvdGVkYmxiYXNlIiwgInBlcnRob3VzYW5kIiwgIkFjaXJjdW1mbGV4IiwgIkVjaXJjdW1mbGV4IiwgIkFhY3V0ZSIsICJFZGllcmVzaXMiLCAiRWdyYXZlIiwgIklhY3V0ZSIsICJJY2lyY3VtZmxleCIsICJJZGllcmVzaXMiLCAiSWdyYXZlIiwgIk9hY3V0ZSIsICJPY2lyY3VtZmxleCIsICJhcHBsZSIsICJPZ3JhdmUiLCAiVWFjdXRlIiwgIlVjaXJjdW1mbGV4IiwgIlVncmF2ZSIsICJkb3RsZXNzaSIsICJjaXJjdW1mbGV4IiwgInRpbGRlIiwgIm1hY3JvbiIsICJicmV2ZSIsICJkb3RhY2NlbnQiLCAicmluZyIsICJjZWRpbGxhIiwgImh1bmdhcnVtbGF1dCIsICJvZ29uZWsiLCAiY2Fyb24iLCAiTHNsYXNoIiwgImxzbGFzaCIsICJTY2Fyb24iLCAic2Nhcm9uIiwgIlpjYXJvbiIsICJ6Y2Fyb24iLCAiYnJva2VuYmFyIiwgIkV0aCIsICJldGgiLCAiWWFjdXRlIiwgInlhY3V0ZSIsICJUaG9ybiIsICJ0aG9ybiIsICJtaW51cyIsICJtdWx0aXBseSIsICJvbmVzdXBlcmlvciIsICJ0d29zdXBlcmlvciIsICJ0aHJlZXN1cGVyaW9yIiwgIm9uZWhhbGYiLCAib25lcXVhcnRlciIsICJ0aHJlZXF1YXJ0ZXJzIiwgImZyYW5jIiwgIkdicmV2ZSIsICJnYnJldmUiLCAiSWRvdGFjY2VudCIsICJTY2VkaWxsYSIsICJzY2VkaWxsYSIsICJDYWN1dGUiLCAiY2FjdXRlIiwgIkNjYXJvbiIsICJjY2Fyb24iLCAiZGNyb2F0Il07CmZ1bmN0aW9uIHJlY292ZXJHbHlwaE5hbWUobmFtZSwgZ2x5cGhzVW5pY29kZU1hcCkgewogIGlmIChnbHlwaHNVbmljb2RlTWFwW25hbWVdICE9PSB1bmRlZmluZWQpIHsKICAgIHJldHVybiBuYW1lOwogIH0KICBjb25zdCB1bmljb2RlID0gZ2V0VW5pY29kZUZvckdseXBoKG5hbWUsIGdseXBoc1VuaWNvZGVNYXApOwogIGlmICh1bmljb2RlICE9PSAtMSkgewogICAgZm9yIChjb25zdCBrZXkgaW4gZ2x5cGhzVW5pY29kZU1hcCkgewogICAgICBpZiAoZ2x5cGhzVW5pY29kZU1hcFtrZXldID09PSB1bmljb2RlKSB7CiAgICAgICAgcmV0dXJuIGtleTsKICAgICAgfQogICAgfQogIH0KICBpbmZvKCJVbmFibGUgdG8gcmVjb3ZlciBhIHN0YW5kYXJkIGdseXBoIG5hbWUgZm9yOiAiICsgbmFtZSk7CiAgcmV0dXJuIG5hbWU7Cn0KZnVuY3Rpb24gdHlwZTFGb250R2x5cGhNYXBwaW5nKHByb3BlcnRpZXMsIGJ1aWx0SW5FbmNvZGluZywgZ2x5cGhOYW1lcykgewogIGNvbnN0IGNoYXJDb2RlVG9HbHlwaElkID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBsZXQgZ2x5cGhJZCwgY2hhckNvZGUsIGJhc2VFbmNvZGluZzsKICBjb25zdCBpc1N5bWJvbGljRm9udCA9ICEhKHByb3BlcnRpZXMuZmxhZ3MgJiBGb250RmxhZ3MuU3ltYm9saWMpOwogIGlmIChwcm9wZXJ0aWVzLmlzSW50ZXJuYWxGb250KSB7CiAgICBiYXNlRW5jb2RpbmcgPSBidWlsdEluRW5jb2Rpbmc7CiAgICBmb3IgKGNoYXJDb2RlID0gMDsgY2hhckNvZGUgPCBiYXNlRW5jb2RpbmcubGVuZ3RoOyBjaGFyQ29kZSsrKSB7CiAgICAgIGdseXBoSWQgPSBnbHlwaE5hbWVzLmluZGV4T2YoYmFzZUVuY29kaW5nW2NoYXJDb2RlXSk7CiAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IGdseXBoSWQgPj0gMCA/IGdseXBoSWQgOiAwOwogICAgfQogIH0gZWxzZSBpZiAocHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lKSB7CiAgICBiYXNlRW5jb2RpbmcgPSBnZXRFbmNvZGluZyhwcm9wZXJ0aWVzLmJhc2VFbmNvZGluZ05hbWUpOwogICAgZm9yIChjaGFyQ29kZSA9IDA7IGNoYXJDb2RlIDwgYmFzZUVuY29kaW5nLmxlbmd0aDsgY2hhckNvZGUrKykgewogICAgICBnbHlwaElkID0gZ2x5cGhOYW1lcy5pbmRleE9mKGJhc2VFbmNvZGluZ1tjaGFyQ29kZV0pOwogICAgICBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBnbHlwaElkID49IDAgPyBnbHlwaElkIDogMDsKICAgIH0KICB9IGVsc2UgaWYgKGlzU3ltYm9saWNGb250KSB7CiAgICBmb3IgKGNoYXJDb2RlIGluIGJ1aWx0SW5FbmNvZGluZykgewogICAgICBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBidWlsdEluRW5jb2RpbmdbY2hhckNvZGVdOwogICAgfQogIH0gZWxzZSB7CiAgICBiYXNlRW5jb2RpbmcgPSBTdGFuZGFyZEVuY29kaW5nOwogICAgZm9yIChjaGFyQ29kZSA9IDA7IGNoYXJDb2RlIDwgYmFzZUVuY29kaW5nLmxlbmd0aDsgY2hhckNvZGUrKykgewogICAgICBnbHlwaElkID0gZ2x5cGhOYW1lcy5pbmRleE9mKGJhc2VFbmNvZGluZ1tjaGFyQ29kZV0pOwogICAgICBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBnbHlwaElkID49IDAgPyBnbHlwaElkIDogMDsKICAgIH0KICB9CiAgY29uc3QgZGlmZmVyZW5jZXMgPSBwcm9wZXJ0aWVzLmRpZmZlcmVuY2VzOwogIGxldCBnbHlwaHNVbmljb2RlTWFwOwogIGlmIChkaWZmZXJlbmNlcykgewogICAgZm9yIChjaGFyQ29kZSBpbiBkaWZmZXJlbmNlcykgewogICAgICBjb25zdCBnbHlwaE5hbWUgPSBkaWZmZXJlbmNlc1tjaGFyQ29kZV07CiAgICAgIGdseXBoSWQgPSBnbHlwaE5hbWVzLmluZGV4T2YoZ2x5cGhOYW1lKTsKICAgICAgaWYgKGdseXBoSWQgPT09IC0xKSB7CiAgICAgICAgaWYgKCFnbHlwaHNVbmljb2RlTWFwKSB7CiAgICAgICAgICBnbHlwaHNVbmljb2RlTWFwID0gZ2V0R2x5cGhzVW5pY29kZSgpOwogICAgICAgIH0KICAgICAgICBjb25zdCBzdGFuZGFyZEdseXBoTmFtZSA9IHJlY292ZXJHbHlwaE5hbWUoZ2x5cGhOYW1lLCBnbHlwaHNVbmljb2RlTWFwKTsKICAgICAgICBpZiAoc3RhbmRhcmRHbHlwaE5hbWUgIT09IGdseXBoTmFtZSkgewogICAgICAgICAgZ2x5cGhJZCA9IGdseXBoTmFtZXMuaW5kZXhPZihzdGFuZGFyZEdseXBoTmFtZSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IGdseXBoSWQgPj0gMCA/IGdseXBoSWQgOiAwOwogICAgfQogIH0KICByZXR1cm4gY2hhckNvZGVUb0dseXBoSWQ7Cn0KZnVuY3Rpb24gbm9ybWFsaXplRm9udE5hbWUobmFtZSkgewogIHJldHVybiBuYW1lLnJlcGxhY2VBbGwoL1ssX10vZywgIi0iKS5yZXBsYWNlQWxsKC9ccy9nLCAiIik7Cn0KY29uc3QgZ2V0VmVydGljYWxQcmVzZW50YXRpb25Gb3JtID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KHQgPT4gewogIHRbMHgyMDEzXSA9IDB4ZmUzMjsKICB0WzB4MjAxNF0gPSAweGZlMzE7CiAgdFsweDIwMjVdID0gMHhmZTMwOwogIHRbMHgyMDI2XSA9IDB4ZmUxOTsKICB0WzB4MzAwMV0gPSAweGZlMTE7CiAgdFsweDMwMDJdID0gMHhmZTEyOwogIHRbMHgzMDA4XSA9IDB4ZmUzZjsKICB0WzB4MzAwOV0gPSAweGZlNDA7CiAgdFsweDMwMGFdID0gMHhmZTNkOwogIHRbMHgzMDBiXSA9IDB4ZmUzZTsKICB0WzB4MzAwY10gPSAweGZlNDE7CiAgdFsweDMwMGRdID0gMHhmZTQyOwogIHRbMHgzMDBlXSA9IDB4ZmU0MzsKICB0WzB4MzAwZl0gPSAweGZlNDQ7CiAgdFsweDMwMTBdID0gMHhmZTNiOwogIHRbMHgzMDExXSA9IDB4ZmUzYzsKICB0WzB4MzAxNF0gPSAweGZlMzk7CiAgdFsweDMwMTVdID0gMHhmZTNhOwogIHRbMHgzMDE2XSA9IDB4ZmUxNzsKICB0WzB4MzAxN10gPSAweGZlMTg7CiAgdFsweGZlNGZdID0gMHhmZTM0OwogIHRbMHhmZjAxXSA9IDB4ZmUxNTsKICB0WzB4ZmYwOF0gPSAweGZlMzU7CiAgdFsweGZmMDldID0gMHhmZTM2OwogIHRbMHhmZjBjXSA9IDB4ZmUxMDsKICB0WzB4ZmYxYV0gPSAweGZlMTM7CiAgdFsweGZmMWJdID0gMHhmZTE0OwogIHRbMHhmZjFmXSA9IDB4ZmUxNjsKICB0WzB4ZmYzYl0gPSAweGZlNDc7CiAgdFsweGZmM2RdID0gMHhmZTQ4OwogIHRbMHhmZjNmXSA9IDB4ZmUzMzsKICB0WzB4ZmY1Yl0gPSAweGZlMzc7CiAgdFsweGZmNWRdID0gMHhmZTM4Owp9KTsKY29uc3QgTUFYX1NJWkVfVE9fQ09NUElMRSA9IDEwMDA7CmZ1bmN0aW9uIGNvbXBpbGVUeXBlM0dseXBoKHsKICBkYXRhOiBpbWcsCiAgd2lkdGgsCiAgaGVpZ2h0Cn0pIHsKICBpZiAod2lkdGggPiBNQVhfU0laRV9UT19DT01QSUxFIHx8IGhlaWdodCA+IE1BWF9TSVpFX1RPX0NPTVBJTEUpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCBQT0lOVF9UT19QUk9DRVNTX0xJTUlUID0gMTAwMDsKICBjb25zdCBQT0lOVF9UWVBFUyA9IG5ldyBVaW50OEFycmF5KFswLCAyLCA0LCAwLCAxLCAwLCA1LCA0LCA4LCAxMCwgMCwgOCwgMCwgMiwgMSwgMF0pOwogIGNvbnN0IHdpZHRoMSA9IHdpZHRoICsgMTsKICBjb25zdCBwb2ludHMgPSBuZXcgVWludDhBcnJheSh3aWR0aDEgKiAoaGVpZ2h0ICsgMSkpOwogIGxldCBpLCBqLCBqMDsKICBjb25zdCBsaW5lU2l6ZSA9IHdpZHRoICsgNyAmIH43OwogIGNvbnN0IGRhdGEgPSBuZXcgVWludDhBcnJheShsaW5lU2l6ZSAqIGhlaWdodCk7CiAgbGV0IHBvcyA9IDA7CiAgZm9yIChjb25zdCBlbGVtIG9mIGltZykgewogICAgbGV0IG1hc2sgPSAxMjg7CiAgICB3aGlsZSAobWFzayA+IDApIHsKICAgICAgZGF0YVtwb3MrK10gPSBlbGVtICYgbWFzayA/IDAgOiAyNTU7CiAgICAgIG1hc2sgPj49IDE7CiAgICB9CiAgfQogIGxldCBjb3VudCA9IDA7CiAgcG9zID0gMDsKICBpZiAoZGF0YVtwb3NdICE9PSAwKSB7CiAgICBwb2ludHNbMF0gPSAxOwogICAgKytjb3VudDsKICB9CiAgZm9yIChqID0gMTsgaiA8IHdpZHRoOyBqKyspIHsKICAgIGlmIChkYXRhW3Bvc10gIT09IGRhdGFbcG9zICsgMV0pIHsKICAgICAgcG9pbnRzW2pdID0gZGF0YVtwb3NdID8gMiA6IDE7CiAgICAgICsrY291bnQ7CiAgICB9CiAgICBwb3MrKzsKICB9CiAgaWYgKGRhdGFbcG9zXSAhPT0gMCkgewogICAgcG9pbnRzW2pdID0gMjsKICAgICsrY291bnQ7CiAgfQogIGZvciAoaSA9IDE7IGkgPCBoZWlnaHQ7IGkrKykgewogICAgcG9zID0gaSAqIGxpbmVTaXplOwogICAgajAgPSBpICogd2lkdGgxOwogICAgaWYgKGRhdGFbcG9zIC0gbGluZVNpemVdICE9PSBkYXRhW3Bvc10pIHsKICAgICAgcG9pbnRzW2owXSA9IGRhdGFbcG9zXSA/IDEgOiA4OwogICAgICArK2NvdW50OwogICAgfQogICAgbGV0IHN1bSA9IChkYXRhW3Bvc10gPyA0IDogMCkgKyAoZGF0YVtwb3MgLSBsaW5lU2l6ZV0gPyA4IDogMCk7CiAgICBmb3IgKGogPSAxOyBqIDwgd2lkdGg7IGorKykgewogICAgICBzdW0gPSAoc3VtID4+IDIpICsgKGRhdGFbcG9zICsgMV0gPyA0IDogMCkgKyAoZGF0YVtwb3MgLSBsaW5lU2l6ZSArIDFdID8gOCA6IDApOwogICAgICBpZiAoUE9JTlRfVFlQRVNbc3VtXSkgewogICAgICAgIHBvaW50c1tqMCArIGpdID0gUE9JTlRfVFlQRVNbc3VtXTsKICAgICAgICArK2NvdW50OwogICAgICB9CiAgICAgIHBvcysrOwogICAgfQogICAgaWYgKGRhdGFbcG9zIC0gbGluZVNpemVdICE9PSBkYXRhW3Bvc10pIHsKICAgICAgcG9pbnRzW2owICsgal0gPSBkYXRhW3Bvc10gPyAyIDogNDsKICAgICAgKytjb3VudDsKICAgIH0KICAgIGlmIChjb3VudCA+IFBPSU5UX1RPX1BST0NFU1NfTElNSVQpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgfQogIHBvcyA9IGxpbmVTaXplICogKGhlaWdodCAtIDEpOwogIGowID0gaSAqIHdpZHRoMTsKICBpZiAoZGF0YVtwb3NdICE9PSAwKSB7CiAgICBwb2ludHNbajBdID0gODsKICAgICsrY291bnQ7CiAgfQogIGZvciAoaiA9IDE7IGogPCB3aWR0aDsgaisrKSB7CiAgICBpZiAoZGF0YVtwb3NdICE9PSBkYXRhW3BvcyArIDFdKSB7CiAgICAgIHBvaW50c1tqMCArIGpdID0gZGF0YVtwb3NdID8gNCA6IDg7CiAgICAgICsrY291bnQ7CiAgICB9CiAgICBwb3MrKzsKICB9CiAgaWYgKGRhdGFbcG9zXSAhPT0gMCkgewogICAgcG9pbnRzW2owICsgal0gPSA0OwogICAgKytjb3VudDsKICB9CiAgaWYgKGNvdW50ID4gUE9JTlRfVE9fUFJPQ0VTU19MSU1JVCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGNvbnN0IHN0ZXBzID0gbmV3IEludDMyQXJyYXkoWzAsIHdpZHRoMSwgLTEsIDAsIC13aWR0aDEsIDAsIDAsIDAsIDFdKTsKICBjb25zdCBwYXRoQnVmID0gW107CiAgY29uc3QgewogICAgYSwKICAgIGIsCiAgICBjLAogICAgZCwKICAgIGUsCiAgICBmCiAgfSA9IG5ldyBET01NYXRyaXgoKS5zY2FsZVNlbGYoMSAvIHdpZHRoLCAtMSAvIGhlaWdodCkudHJhbnNsYXRlU2VsZigwLCAtaGVpZ2h0KTsKICBmb3IgKGkgPSAwOyBjb3VudCAmJiBpIDw9IGhlaWdodDsgaSsrKSB7CiAgICBsZXQgcCA9IGkgKiB3aWR0aDE7CiAgICBjb25zdCBlbmQgPSBwICsgd2lkdGg7CiAgICB3aGlsZSAocCA8IGVuZCAmJiAhcG9pbnRzW3BdKSB7CiAgICAgIHArKzsKICAgIH0KICAgIGlmIChwID09PSBlbmQpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBsZXQgeCA9IHAgJSB3aWR0aDE7CiAgICBsZXQgeSA9IGk7CiAgICBwYXRoQnVmLnB1c2goRHJhd09QUy5tb3ZlVG8sIGEgKiB4ICsgYyAqIHkgKyBlLCBiICogeCArIGQgKiB5ICsgZik7CiAgICBjb25zdCBwMCA9IHA7CiAgICBsZXQgdHlwZSA9IHBvaW50c1twXTsKICAgIGRvIHsKICAgICAgY29uc3Qgc3RlcCA9IHN0ZXBzW3R5cGVdOwogICAgICBkbyB7CiAgICAgICAgcCArPSBzdGVwOwogICAgICB9IHdoaWxlICghcG9pbnRzW3BdKTsKICAgICAgY29uc3QgcHAgPSBwb2ludHNbcF07CiAgICAgIGlmIChwcCAhPT0gNSAmJiBwcCAhPT0gMTApIHsKICAgICAgICB0eXBlID0gcHA7CiAgICAgICAgcG9pbnRzW3BdID0gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0eXBlID0gcHAgJiAweDMzICogdHlwZSA+PiA0OwogICAgICAgIHBvaW50c1twXSAmPSB0eXBlID4+IDIgfCB0eXBlIDw8IDI7CiAgICAgIH0KICAgICAgeCA9IHAgJSB3aWR0aDE7CiAgICAgIHkgPSBwIC8gd2lkdGgxIHwgMDsKICAgICAgcGF0aEJ1Zi5wdXNoKERyYXdPUFMubGluZVRvLCBhICogeCArIGMgKiB5ICsgZSwgYiAqIHggKyBkICogeSArIGYpOwogICAgICBpZiAoIXBvaW50c1twXSkgewogICAgICAgIC0tY291bnQ7CiAgICAgIH0KICAgIH0gd2hpbGUgKHAwICE9PSBwKTsKICAgIC0taTsKICB9CiAgcmV0dXJuIFtPUFMucmF3RmlsbFBhdGgsIFtuZXcgRmxvYXQzMkFycmF5KHBhdGhCdWYpXSwgbmV3IEZsb2F0MzJBcnJheShbMCwgMCwgd2lkdGgsIGhlaWdodF0pXTsKfQoKOy8vIC4vc3JjL2NvcmUvY2hhcnNldHMuanMKY29uc3QgSVNPQWRvYmVDaGFyc2V0ID0gWyIubm90ZGVmIiwgInNwYWNlIiwgImV4Y2xhbSIsICJxdW90ZWRibCIsICJudW1iZXJzaWduIiwgImRvbGxhciIsICJwZXJjZW50IiwgImFtcGVyc2FuZCIsICJxdW90ZXJpZ2h0IiwgInBhcmVubGVmdCIsICJwYXJlbnJpZ2h0IiwgImFzdGVyaXNrIiwgInBsdXMiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJzbGFzaCIsICJ6ZXJvIiwgIm9uZSIsICJ0d28iLCAidGhyZWUiLCAiZm91ciIsICJmaXZlIiwgInNpeCIsICJzZXZlbiIsICJlaWdodCIsICJuaW5lIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJsZXNzIiwgImVxdWFsIiwgImdyZWF0ZXIiLCAicXVlc3Rpb24iLCAiYXQiLCAiQSIsICJCIiwgIkMiLCAiRCIsICJFIiwgIkYiLCAiRyIsICJIIiwgIkkiLCAiSiIsICJLIiwgIkwiLCAiTSIsICJOIiwgIk8iLCAiUCIsICJRIiwgIlIiLCAiUyIsICJUIiwgIlUiLCAiViIsICJXIiwgIlgiLCAiWSIsICJaIiwgImJyYWNrZXRsZWZ0IiwgImJhY2tzbGFzaCIsICJicmFja2V0cmlnaHQiLCAiYXNjaWljaXJjdW0iLCAidW5kZXJzY29yZSIsICJxdW90ZWxlZnQiLCAiYSIsICJiIiwgImMiLCAiZCIsICJlIiwgImYiLCAiZyIsICJoIiwgImkiLCAiaiIsICJrIiwgImwiLCAibSIsICJuIiwgIm8iLCAicCIsICJxIiwgInIiLCAicyIsICJ0IiwgInUiLCAidiIsICJ3IiwgIngiLCAieSIsICJ6IiwgImJyYWNlbGVmdCIsICJiYXIiLCAiYnJhY2VyaWdodCIsICJhc2NpaXRpbGRlIiwgImV4Y2xhbWRvd24iLCAiY2VudCIsICJzdGVybGluZyIsICJmcmFjdGlvbiIsICJ5ZW4iLCAiZmxvcmluIiwgInNlY3Rpb24iLCAiY3VycmVuY3kiLCAicXVvdGVzaW5nbGUiLCAicXVvdGVkYmxsZWZ0IiwgImd1aWxsZW1vdGxlZnQiLCAiZ3VpbHNpbmdsbGVmdCIsICJndWlsc2luZ2xyaWdodCIsICJmaSIsICJmbCIsICJlbmRhc2giLCAiZGFnZ2VyIiwgImRhZ2dlcmRibCIsICJwZXJpb2RjZW50ZXJlZCIsICJwYXJhZ3JhcGgiLCAiYnVsbGV0IiwgInF1b3Rlc2luZ2xiYXNlIiwgInF1b3RlZGJsYmFzZSIsICJxdW90ZWRibHJpZ2h0IiwgImd1aWxsZW1vdHJpZ2h0IiwgImVsbGlwc2lzIiwgInBlcnRob3VzYW5kIiwgInF1ZXN0aW9uZG93biIsICJncmF2ZSIsICJhY3V0ZSIsICJjaXJjdW1mbGV4IiwgInRpbGRlIiwgIm1hY3JvbiIsICJicmV2ZSIsICJkb3RhY2NlbnQiLCAiZGllcmVzaXMiLCAicmluZyIsICJjZWRpbGxhIiwgImh1bmdhcnVtbGF1dCIsICJvZ29uZWsiLCAiY2Fyb24iLCAiZW1kYXNoIiwgIkFFIiwgIm9yZGZlbWluaW5lIiwgIkxzbGFzaCIsICJPc2xhc2giLCAiT0UiLCAib3JkbWFzY3VsaW5lIiwgImFlIiwgImRvdGxlc3NpIiwgImxzbGFzaCIsICJvc2xhc2giLCAib2UiLCAiZ2VybWFuZGJscyIsICJvbmVzdXBlcmlvciIsICJsb2dpY2Fsbm90IiwgIm11IiwgInRyYWRlbWFyayIsICJFdGgiLCAib25laGFsZiIsICJwbHVzbWludXMiLCAiVGhvcm4iLCAib25lcXVhcnRlciIsICJkaXZpZGUiLCAiYnJva2VuYmFyIiwgImRlZ3JlZSIsICJ0aG9ybiIsICJ0aHJlZXF1YXJ0ZXJzIiwgInR3b3N1cGVyaW9yIiwgInJlZ2lzdGVyZWQiLCAibWludXMiLCAiZXRoIiwgIm11bHRpcGx5IiwgInRocmVlc3VwZXJpb3IiLCAiY29weXJpZ2h0IiwgIkFhY3V0ZSIsICJBY2lyY3VtZmxleCIsICJBZGllcmVzaXMiLCAiQWdyYXZlIiwgIkFyaW5nIiwgIkF0aWxkZSIsICJDY2VkaWxsYSIsICJFYWN1dGUiLCAiRWNpcmN1bWZsZXgiLCAiRWRpZXJlc2lzIiwgIkVncmF2ZSIsICJJYWN1dGUiLCAiSWNpcmN1bWZsZXgiLCAiSWRpZXJlc2lzIiwgIklncmF2ZSIsICJOdGlsZGUiLCAiT2FjdXRlIiwgIk9jaXJjdW1mbGV4IiwgIk9kaWVyZXNpcyIsICJPZ3JhdmUiLCAiT3RpbGRlIiwgIlNjYXJvbiIsICJVYWN1dGUiLCAiVWNpcmN1bWZsZXgiLCAiVWRpZXJlc2lzIiwgIlVncmF2ZSIsICJZYWN1dGUiLCAiWWRpZXJlc2lzIiwgIlpjYXJvbiIsICJhYWN1dGUiLCAiYWNpcmN1bWZsZXgiLCAiYWRpZXJlc2lzIiwgImFncmF2ZSIsICJhcmluZyIsICJhdGlsZGUiLCAiY2NlZGlsbGEiLCAiZWFjdXRlIiwgImVjaXJjdW1mbGV4IiwgImVkaWVyZXNpcyIsICJlZ3JhdmUiLCAiaWFjdXRlIiwgImljaXJjdW1mbGV4IiwgImlkaWVyZXNpcyIsICJpZ3JhdmUiLCAibnRpbGRlIiwgIm9hY3V0ZSIsICJvY2lyY3VtZmxleCIsICJvZGllcmVzaXMiLCAib2dyYXZlIiwgIm90aWxkZSIsICJzY2Fyb24iLCAidWFjdXRlIiwgInVjaXJjdW1mbGV4IiwgInVkaWVyZXNpcyIsICJ1Z3JhdmUiLCAieWFjdXRlIiwgInlkaWVyZXNpcyIsICJ6Y2Fyb24iXTsKY29uc3QgRXhwZXJ0Q2hhcnNldCA9IFsiLm5vdGRlZiIsICJzcGFjZSIsICJleGNsYW1zbWFsbCIsICJIdW5nYXJ1bWxhdXRzbWFsbCIsICJkb2xsYXJvbGRzdHlsZSIsICJkb2xsYXJzdXBlcmlvciIsICJhbXBlcnNhbmRzbWFsbCIsICJBY3V0ZXNtYWxsIiwgInBhcmVubGVmdHN1cGVyaW9yIiwgInBhcmVucmlnaHRzdXBlcmlvciIsICJ0d29kb3RlbmxlYWRlciIsICJvbmVkb3RlbmxlYWRlciIsICJjb21tYSIsICJoeXBoZW4iLCAicGVyaW9kIiwgImZyYWN0aW9uIiwgInplcm9vbGRzdHlsZSIsICJvbmVvbGRzdHlsZSIsICJ0d29vbGRzdHlsZSIsICJ0aHJlZW9sZHN0eWxlIiwgImZvdXJvbGRzdHlsZSIsICJmaXZlb2xkc3R5bGUiLCAic2l4b2xkc3R5bGUiLCAic2V2ZW5vbGRzdHlsZSIsICJlaWdodG9sZHN0eWxlIiwgIm5pbmVvbGRzdHlsZSIsICJjb2xvbiIsICJzZW1pY29sb24iLCAiY29tbWFzdXBlcmlvciIsICJ0aHJlZXF1YXJ0ZXJzZW1kYXNoIiwgInBlcmlvZHN1cGVyaW9yIiwgInF1ZXN0aW9uc21hbGwiLCAiYXN1cGVyaW9yIiwgImJzdXBlcmlvciIsICJjZW50c3VwZXJpb3IiLCAiZHN1cGVyaW9yIiwgImVzdXBlcmlvciIsICJpc3VwZXJpb3IiLCAibHN1cGVyaW9yIiwgIm1zdXBlcmlvciIsICJuc3VwZXJpb3IiLCAib3N1cGVyaW9yIiwgInJzdXBlcmlvciIsICJzc3VwZXJpb3IiLCAidHN1cGVyaW9yIiwgImZmIiwgImZpIiwgImZsIiwgImZmaSIsICJmZmwiLCAicGFyZW5sZWZ0aW5mZXJpb3IiLCAicGFyZW5yaWdodGluZmVyaW9yIiwgIkNpcmN1bWZsZXhzbWFsbCIsICJoeXBoZW5zdXBlcmlvciIsICJHcmF2ZXNtYWxsIiwgIkFzbWFsbCIsICJCc21hbGwiLCAiQ3NtYWxsIiwgIkRzbWFsbCIsICJFc21hbGwiLCAiRnNtYWxsIiwgIkdzbWFsbCIsICJIc21hbGwiLCAiSXNtYWxsIiwgIkpzbWFsbCIsICJLc21hbGwiLCAiTHNtYWxsIiwgIk1zbWFsbCIsICJOc21hbGwiLCAiT3NtYWxsIiwgIlBzbWFsbCIsICJRc21hbGwiLCAiUnNtYWxsIiwgIlNzbWFsbCIsICJUc21hbGwiLCAiVXNtYWxsIiwgIlZzbWFsbCIsICJXc21hbGwiLCAiWHNtYWxsIiwgIllzbWFsbCIsICJac21hbGwiLCAiY29sb25tb25ldGFyeSIsICJvbmVmaXR0ZWQiLCAicnVwaWFoIiwgIlRpbGRlc21hbGwiLCAiZXhjbGFtZG93bnNtYWxsIiwgImNlbnRvbGRzdHlsZSIsICJMc2xhc2hzbWFsbCIsICJTY2Fyb25zbWFsbCIsICJaY2Fyb25zbWFsbCIsICJEaWVyZXNpc3NtYWxsIiwgIkJyZXZlc21hbGwiLCAiQ2Fyb25zbWFsbCIsICJEb3RhY2NlbnRzbWFsbCIsICJNYWNyb25zbWFsbCIsICJmaWd1cmVkYXNoIiwgImh5cGhlbmluZmVyaW9yIiwgIk9nb25la3NtYWxsIiwgIlJpbmdzbWFsbCIsICJDZWRpbGxhc21hbGwiLCAib25lcXVhcnRlciIsICJvbmVoYWxmIiwgInRocmVlcXVhcnRlcnMiLCAicXVlc3Rpb25kb3duc21hbGwiLCAib25lZWlnaHRoIiwgInRocmVlZWlnaHRocyIsICJmaXZlZWlnaHRocyIsICJzZXZlbmVpZ2h0aHMiLCAib25ldGhpcmQiLCAidHdvdGhpcmRzIiwgInplcm9zdXBlcmlvciIsICJvbmVzdXBlcmlvciIsICJ0d29zdXBlcmlvciIsICJ0aHJlZXN1cGVyaW9yIiwgImZvdXJzdXBlcmlvciIsICJmaXZlc3VwZXJpb3IiLCAic2l4c3VwZXJpb3IiLCAic2V2ZW5zdXBlcmlvciIsICJlaWdodHN1cGVyaW9yIiwgIm5pbmVzdXBlcmlvciIsICJ6ZXJvaW5mZXJpb3IiLCAib25laW5mZXJpb3IiLCAidHdvaW5mZXJpb3IiLCAidGhyZWVpbmZlcmlvciIsICJmb3VyaW5mZXJpb3IiLCAiZml2ZWluZmVyaW9yIiwgInNpeGluZmVyaW9yIiwgInNldmVuaW5mZXJpb3IiLCAiZWlnaHRpbmZlcmlvciIsICJuaW5laW5mZXJpb3IiLCAiY2VudGluZmVyaW9yIiwgImRvbGxhcmluZmVyaW9yIiwgInBlcmlvZGluZmVyaW9yIiwgImNvbW1haW5mZXJpb3IiLCAiQWdyYXZlc21hbGwiLCAiQWFjdXRlc21hbGwiLCAiQWNpcmN1bWZsZXhzbWFsbCIsICJBdGlsZGVzbWFsbCIsICJBZGllcmVzaXNzbWFsbCIsICJBcmluZ3NtYWxsIiwgIkFFc21hbGwiLCAiQ2NlZGlsbGFzbWFsbCIsICJFZ3JhdmVzbWFsbCIsICJFYWN1dGVzbWFsbCIsICJFY2lyY3VtZmxleHNtYWxsIiwgIkVkaWVyZXNpc3NtYWxsIiwgIklncmF2ZXNtYWxsIiwgIklhY3V0ZXNtYWxsIiwgIkljaXJjdW1mbGV4c21hbGwiLCAiSWRpZXJlc2lzc21hbGwiLCAiRXRoc21hbGwiLCAiTnRpbGRlc21hbGwiLCAiT2dyYXZlc21hbGwiLCAiT2FjdXRlc21hbGwiLCAiT2NpcmN1bWZsZXhzbWFsbCIsICJPdGlsZGVzbWFsbCIsICJPZGllcmVzaXNzbWFsbCIsICJPRXNtYWxsIiwgIk9zbGFzaHNtYWxsIiwgIlVncmF2ZXNtYWxsIiwgIlVhY3V0ZXNtYWxsIiwgIlVjaXJjdW1mbGV4c21hbGwiLCAiVWRpZXJlc2lzc21hbGwiLCAiWWFjdXRlc21hbGwiLCAiVGhvcm5zbWFsbCIsICJZZGllcmVzaXNzbWFsbCJdOwpjb25zdCBFeHBlcnRTdWJzZXRDaGFyc2V0ID0gWyIubm90ZGVmIiwgInNwYWNlIiwgImRvbGxhcm9sZHN0eWxlIiwgImRvbGxhcnN1cGVyaW9yIiwgInBhcmVubGVmdHN1cGVyaW9yIiwgInBhcmVucmlnaHRzdXBlcmlvciIsICJ0d29kb3RlbmxlYWRlciIsICJvbmVkb3RlbmxlYWRlciIsICJjb21tYSIsICJoeXBoZW4iLCAicGVyaW9kIiwgImZyYWN0aW9uIiwgInplcm9vbGRzdHlsZSIsICJvbmVvbGRzdHlsZSIsICJ0d29vbGRzdHlsZSIsICJ0aHJlZW9sZHN0eWxlIiwgImZvdXJvbGRzdHlsZSIsICJmaXZlb2xkc3R5bGUiLCAic2l4b2xkc3R5bGUiLCAic2V2ZW5vbGRzdHlsZSIsICJlaWdodG9sZHN0eWxlIiwgIm5pbmVvbGRzdHlsZSIsICJjb2xvbiIsICJzZW1pY29sb24iLCAiY29tbWFzdXBlcmlvciIsICJ0aHJlZXF1YXJ0ZXJzZW1kYXNoIiwgInBlcmlvZHN1cGVyaW9yIiwgImFzdXBlcmlvciIsICJic3VwZXJpb3IiLCAiY2VudHN1cGVyaW9yIiwgImRzdXBlcmlvciIsICJlc3VwZXJpb3IiLCAiaXN1cGVyaW9yIiwgImxzdXBlcmlvciIsICJtc3VwZXJpb3IiLCAibnN1cGVyaW9yIiwgIm9zdXBlcmlvciIsICJyc3VwZXJpb3IiLCAic3N1cGVyaW9yIiwgInRzdXBlcmlvciIsICJmZiIsICJmaSIsICJmbCIsICJmZmkiLCAiZmZsIiwgInBhcmVubGVmdGluZmVyaW9yIiwgInBhcmVucmlnaHRpbmZlcmlvciIsICJoeXBoZW5zdXBlcmlvciIsICJjb2xvbm1vbmV0YXJ5IiwgIm9uZWZpdHRlZCIsICJydXBpYWgiLCAiY2VudG9sZHN0eWxlIiwgImZpZ3VyZWRhc2giLCAiaHlwaGVuaW5mZXJpb3IiLCAib25lcXVhcnRlciIsICJvbmVoYWxmIiwgInRocmVlcXVhcnRlcnMiLCAib25lZWlnaHRoIiwgInRocmVlZWlnaHRocyIsICJmaXZlZWlnaHRocyIsICJzZXZlbmVpZ2h0aHMiLCAib25ldGhpcmQiLCAidHdvdGhpcmRzIiwgInplcm9zdXBlcmlvciIsICJvbmVzdXBlcmlvciIsICJ0d29zdXBlcmlvciIsICJ0aHJlZXN1cGVyaW9yIiwgImZvdXJzdXBlcmlvciIsICJmaXZlc3VwZXJpb3IiLCAic2l4c3VwZXJpb3IiLCAic2V2ZW5zdXBlcmlvciIsICJlaWdodHN1cGVyaW9yIiwgIm5pbmVzdXBlcmlvciIsICJ6ZXJvaW5mZXJpb3IiLCAib25laW5mZXJpb3IiLCAidHdvaW5mZXJpb3IiLCAidGhyZWVpbmZlcmlvciIsICJmb3VyaW5mZXJpb3IiLCAiZml2ZWluZmVyaW9yIiwgInNpeGluZmVyaW9yIiwgInNldmVuaW5mZXJpb3IiLCAiZWlnaHRpbmZlcmlvciIsICJuaW5laW5mZXJpb3IiLCAiY2VudGluZmVyaW9yIiwgImRvbGxhcmluZmVyaW9yIiwgInBlcmlvZGluZmVyaW9yIiwgImNvbW1haW5mZXJpb3IiXTsKCjsvLyAuL3NyYy9jb3JlL2NmZl9wYXJzZXIuanMKCgoKCmNvbnN0IE1BWF9TVUJSX05FU1RJTkcgPSAxMDsKY29uc3QgQ0ZGU3RhbmRhcmRTdHJpbmdzID0gWyIubm90ZGVmIiwgInNwYWNlIiwgImV4Y2xhbSIsICJxdW90ZWRibCIsICJudW1iZXJzaWduIiwgImRvbGxhciIsICJwZXJjZW50IiwgImFtcGVyc2FuZCIsICJxdW90ZXJpZ2h0IiwgInBhcmVubGVmdCIsICJwYXJlbnJpZ2h0IiwgImFzdGVyaXNrIiwgInBsdXMiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJzbGFzaCIsICJ6ZXJvIiwgIm9uZSIsICJ0d28iLCAidGhyZWUiLCAiZm91ciIsICJmaXZlIiwgInNpeCIsICJzZXZlbiIsICJlaWdodCIsICJuaW5lIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJsZXNzIiwgImVxdWFsIiwgImdyZWF0ZXIiLCAicXVlc3Rpb24iLCAiYXQiLCAiQSIsICJCIiwgIkMiLCAiRCIsICJFIiwgIkYiLCAiRyIsICJIIiwgIkkiLCAiSiIsICJLIiwgIkwiLCAiTSIsICJOIiwgIk8iLCAiUCIsICJRIiwgIlIiLCAiUyIsICJUIiwgIlUiLCAiViIsICJXIiwgIlgiLCAiWSIsICJaIiwgImJyYWNrZXRsZWZ0IiwgImJhY2tzbGFzaCIsICJicmFja2V0cmlnaHQiLCAiYXNjaWljaXJjdW0iLCAidW5kZXJzY29yZSIsICJxdW90ZWxlZnQiLCAiYSIsICJiIiwgImMiLCAiZCIsICJlIiwgImYiLCAiZyIsICJoIiwgImkiLCAiaiIsICJrIiwgImwiLCAibSIsICJuIiwgIm8iLCAicCIsICJxIiwgInIiLCAicyIsICJ0IiwgInUiLCAidiIsICJ3IiwgIngiLCAieSIsICJ6IiwgImJyYWNlbGVmdCIsICJiYXIiLCAiYnJhY2VyaWdodCIsICJhc2NpaXRpbGRlIiwgImV4Y2xhbWRvd24iLCAiY2VudCIsICJzdGVybGluZyIsICJmcmFjdGlvbiIsICJ5ZW4iLCAiZmxvcmluIiwgInNlY3Rpb24iLCAiY3VycmVuY3kiLCAicXVvdGVzaW5nbGUiLCAicXVvdGVkYmxsZWZ0IiwgImd1aWxsZW1vdGxlZnQiLCAiZ3VpbHNpbmdsbGVmdCIsICJndWlsc2luZ2xyaWdodCIsICJmaSIsICJmbCIsICJlbmRhc2giLCAiZGFnZ2VyIiwgImRhZ2dlcmRibCIsICJwZXJpb2RjZW50ZXJlZCIsICJwYXJhZ3JhcGgiLCAiYnVsbGV0IiwgInF1b3Rlc2luZ2xiYXNlIiwgInF1b3RlZGJsYmFzZSIsICJxdW90ZWRibHJpZ2h0IiwgImd1aWxsZW1vdHJpZ2h0IiwgImVsbGlwc2lzIiwgInBlcnRob3VzYW5kIiwgInF1ZXN0aW9uZG93biIsICJncmF2ZSIsICJhY3V0ZSIsICJjaXJjdW1mbGV4IiwgInRpbGRlIiwgIm1hY3JvbiIsICJicmV2ZSIsICJkb3RhY2NlbnQiLCAiZGllcmVzaXMiLCAicmluZyIsICJjZWRpbGxhIiwgImh1bmdhcnVtbGF1dCIsICJvZ29uZWsiLCAiY2Fyb24iLCAiZW1kYXNoIiwgIkFFIiwgIm9yZGZlbWluaW5lIiwgIkxzbGFzaCIsICJPc2xhc2giLCAiT0UiLCAib3JkbWFzY3VsaW5lIiwgImFlIiwgImRvdGxlc3NpIiwgImxzbGFzaCIsICJvc2xhc2giLCAib2UiLCAiZ2VybWFuZGJscyIsICJvbmVzdXBlcmlvciIsICJsb2dpY2Fsbm90IiwgIm11IiwgInRyYWRlbWFyayIsICJFdGgiLCAib25laGFsZiIsICJwbHVzbWludXMiLCAiVGhvcm4iLCAib25lcXVhcnRlciIsICJkaXZpZGUiLCAiYnJva2VuYmFyIiwgImRlZ3JlZSIsICJ0aG9ybiIsICJ0aHJlZXF1YXJ0ZXJzIiwgInR3b3N1cGVyaW9yIiwgInJlZ2lzdGVyZWQiLCAibWludXMiLCAiZXRoIiwgIm11bHRpcGx5IiwgInRocmVlc3VwZXJpb3IiLCAiY29weXJpZ2h0IiwgIkFhY3V0ZSIsICJBY2lyY3VtZmxleCIsICJBZGllcmVzaXMiLCAiQWdyYXZlIiwgIkFyaW5nIiwgIkF0aWxkZSIsICJDY2VkaWxsYSIsICJFYWN1dGUiLCAiRWNpcmN1bWZsZXgiLCAiRWRpZXJlc2lzIiwgIkVncmF2ZSIsICJJYWN1dGUiLCAiSWNpcmN1bWZsZXgiLCAiSWRpZXJlc2lzIiwgIklncmF2ZSIsICJOdGlsZGUiLCAiT2FjdXRlIiwgIk9jaXJjdW1mbGV4IiwgIk9kaWVyZXNpcyIsICJPZ3JhdmUiLCAiT3RpbGRlIiwgIlNjYXJvbiIsICJVYWN1dGUiLCAiVWNpcmN1bWZsZXgiLCAiVWRpZXJlc2lzIiwgIlVncmF2ZSIsICJZYWN1dGUiLCAiWWRpZXJlc2lzIiwgIlpjYXJvbiIsICJhYWN1dGUiLCAiYWNpcmN1bWZsZXgiLCAiYWRpZXJlc2lzIiwgImFncmF2ZSIsICJhcmluZyIsICJhdGlsZGUiLCAiY2NlZGlsbGEiLCAiZWFjdXRlIiwgImVjaXJjdW1mbGV4IiwgImVkaWVyZXNpcyIsICJlZ3JhdmUiLCAiaWFjdXRlIiwgImljaXJjdW1mbGV4IiwgImlkaWVyZXNpcyIsICJpZ3JhdmUiLCAibnRpbGRlIiwgIm9hY3V0ZSIsICJvY2lyY3VtZmxleCIsICJvZGllcmVzaXMiLCAib2dyYXZlIiwgIm90aWxkZSIsICJzY2Fyb24iLCAidWFjdXRlIiwgInVjaXJjdW1mbGV4IiwgInVkaWVyZXNpcyIsICJ1Z3JhdmUiLCAieWFjdXRlIiwgInlkaWVyZXNpcyIsICJ6Y2Fyb24iLCAiZXhjbGFtc21hbGwiLCAiSHVuZ2FydW1sYXV0c21hbGwiLCAiZG9sbGFyb2xkc3R5bGUiLCAiZG9sbGFyc3VwZXJpb3IiLCAiYW1wZXJzYW5kc21hbGwiLCAiQWN1dGVzbWFsbCIsICJwYXJlbmxlZnRzdXBlcmlvciIsICJwYXJlbnJpZ2h0c3VwZXJpb3IiLCAidHdvZG90ZW5sZWFkZXIiLCAib25lZG90ZW5sZWFkZXIiLCAiemVyb29sZHN0eWxlIiwgIm9uZW9sZHN0eWxlIiwgInR3b29sZHN0eWxlIiwgInRocmVlb2xkc3R5bGUiLCAiZm91cm9sZHN0eWxlIiwgImZpdmVvbGRzdHlsZSIsICJzaXhvbGRzdHlsZSIsICJzZXZlbm9sZHN0eWxlIiwgImVpZ2h0b2xkc3R5bGUiLCAibmluZW9sZHN0eWxlIiwgImNvbW1hc3VwZXJpb3IiLCAidGhyZWVxdWFydGVyc2VtZGFzaCIsICJwZXJpb2RzdXBlcmlvciIsICJxdWVzdGlvbnNtYWxsIiwgImFzdXBlcmlvciIsICJic3VwZXJpb3IiLCAiY2VudHN1cGVyaW9yIiwgImRzdXBlcmlvciIsICJlc3VwZXJpb3IiLCAiaXN1cGVyaW9yIiwgImxzdXBlcmlvciIsICJtc3VwZXJpb3IiLCAibnN1cGVyaW9yIiwgIm9zdXBlcmlvciIsICJyc3VwZXJpb3IiLCAic3N1cGVyaW9yIiwgInRzdXBlcmlvciIsICJmZiIsICJmZmkiLCAiZmZsIiwgInBhcmVubGVmdGluZmVyaW9yIiwgInBhcmVucmlnaHRpbmZlcmlvciIsICJDaXJjdW1mbGV4c21hbGwiLCAiaHlwaGVuc3VwZXJpb3IiLCAiR3JhdmVzbWFsbCIsICJBc21hbGwiLCAiQnNtYWxsIiwgIkNzbWFsbCIsICJEc21hbGwiLCAiRXNtYWxsIiwgIkZzbWFsbCIsICJHc21hbGwiLCAiSHNtYWxsIiwgIklzbWFsbCIsICJKc21hbGwiLCAiS3NtYWxsIiwgIkxzbWFsbCIsICJNc21hbGwiLCAiTnNtYWxsIiwgIk9zbWFsbCIsICJQc21hbGwiLCAiUXNtYWxsIiwgIlJzbWFsbCIsICJTc21hbGwiLCAiVHNtYWxsIiwgIlVzbWFsbCIsICJWc21hbGwiLCAiV3NtYWxsIiwgIlhzbWFsbCIsICJZc21hbGwiLCAiWnNtYWxsIiwgImNvbG9ubW9uZXRhcnkiLCAib25lZml0dGVkIiwgInJ1cGlhaCIsICJUaWxkZXNtYWxsIiwgImV4Y2xhbWRvd25zbWFsbCIsICJjZW50b2xkc3R5bGUiLCAiTHNsYXNoc21hbGwiLCAiU2Nhcm9uc21hbGwiLCAiWmNhcm9uc21hbGwiLCAiRGllcmVzaXNzbWFsbCIsICJCcmV2ZXNtYWxsIiwgIkNhcm9uc21hbGwiLCAiRG90YWNjZW50c21hbGwiLCAiTWFjcm9uc21hbGwiLCAiZmlndXJlZGFzaCIsICJoeXBoZW5pbmZlcmlvciIsICJPZ29uZWtzbWFsbCIsICJSaW5nc21hbGwiLCAiQ2VkaWxsYXNtYWxsIiwgInF1ZXN0aW9uZG93bnNtYWxsIiwgIm9uZWVpZ2h0aCIsICJ0aHJlZWVpZ2h0aHMiLCAiZml2ZWVpZ2h0aHMiLCAic2V2ZW5laWdodGhzIiwgIm9uZXRoaXJkIiwgInR3b3RoaXJkcyIsICJ6ZXJvc3VwZXJpb3IiLCAiZm91cnN1cGVyaW9yIiwgImZpdmVzdXBlcmlvciIsICJzaXhzdXBlcmlvciIsICJzZXZlbnN1cGVyaW9yIiwgImVpZ2h0c3VwZXJpb3IiLCAibmluZXN1cGVyaW9yIiwgInplcm9pbmZlcmlvciIsICJvbmVpbmZlcmlvciIsICJ0d29pbmZlcmlvciIsICJ0aHJlZWluZmVyaW9yIiwgImZvdXJpbmZlcmlvciIsICJmaXZlaW5mZXJpb3IiLCAic2l4aW5mZXJpb3IiLCAic2V2ZW5pbmZlcmlvciIsICJlaWdodGluZmVyaW9yIiwgIm5pbmVpbmZlcmlvciIsICJjZW50aW5mZXJpb3IiLCAiZG9sbGFyaW5mZXJpb3IiLCAicGVyaW9kaW5mZXJpb3IiLCAiY29tbWFpbmZlcmlvciIsICJBZ3JhdmVzbWFsbCIsICJBYWN1dGVzbWFsbCIsICJBY2lyY3VtZmxleHNtYWxsIiwgIkF0aWxkZXNtYWxsIiwgIkFkaWVyZXNpc3NtYWxsIiwgIkFyaW5nc21hbGwiLCAiQUVzbWFsbCIsICJDY2VkaWxsYXNtYWxsIiwgIkVncmF2ZXNtYWxsIiwgIkVhY3V0ZXNtYWxsIiwgIkVjaXJjdW1mbGV4c21hbGwiLCAiRWRpZXJlc2lzc21hbGwiLCAiSWdyYXZlc21hbGwiLCAiSWFjdXRlc21hbGwiLCAiSWNpcmN1bWZsZXhzbWFsbCIsICJJZGllcmVzaXNzbWFsbCIsICJFdGhzbWFsbCIsICJOdGlsZGVzbWFsbCIsICJPZ3JhdmVzbWFsbCIsICJPYWN1dGVzbWFsbCIsICJPY2lyY3VtZmxleHNtYWxsIiwgIk90aWxkZXNtYWxsIiwgIk9kaWVyZXNpc3NtYWxsIiwgIk9Fc21hbGwiLCAiT3NsYXNoc21hbGwiLCAiVWdyYXZlc21hbGwiLCAiVWFjdXRlc21hbGwiLCAiVWNpcmN1bWZsZXhzbWFsbCIsICJVZGllcmVzaXNzbWFsbCIsICJZYWN1dGVzbWFsbCIsICJUaG9ybnNtYWxsIiwgIllkaWVyZXNpc3NtYWxsIiwgIjAwMS4wMDAiLCAiMDAxLjAwMSIsICIwMDEuMDAyIiwgIjAwMS4wMDMiLCAiQmxhY2siLCAiQm9sZCIsICJCb29rIiwgIkxpZ2h0IiwgIk1lZGl1bSIsICJSZWd1bGFyIiwgIlJvbWFuIiwgIlNlbWlib2xkIl07CmNvbnN0IE5VTV9TVEFOREFSRF9DRkZfU1RSSU5HUyA9IDM5MTsKY29uc3QgQ2hhcnN0cmluZ1ZhbGlkYXRpb25EYXRhID0gW251bGwsIHsKICBpZDogImhzdGVtIiwKICBtaW46IDIsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZSwKICBzdGVtOiB0cnVlCn0sIG51bGwsIHsKICBpZDogInZzdGVtIiwKICBtaW46IDIsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZSwKICBzdGVtOiB0cnVlCn0sIHsKICBpZDogInZtb3ZldG8iLAogIG1pbjogMSwKICBzdGFja0NsZWFyaW5nOiB0cnVlCn0sIHsKICBpZDogInJsaW5ldG8iLAogIG1pbjogMiwKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogImhsaW5ldG8iLAogIG1pbjogMSwKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogInZsaW5ldG8iLAogIG1pbjogMSwKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogInJyY3VydmV0byIsCiAgbWluOiA2LAogIHJlc2V0U3RhY2s6IHRydWUKfSwgbnVsbCwgewogIGlkOiAiY2FsbHN1YnIiLAogIG1pbjogMQp9LCB7CiAgaWQ6ICJyZXR1cm4iLAogIG1pbjogMAp9LCBudWxsLCBudWxsLCB7CiAgaWQ6ICJlbmRjaGFyIiwKICBtaW46IDAsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZQp9LCBudWxsLCBudWxsLCBudWxsLCB7CiAgaWQ6ICJoc3RlbWhtIiwKICBtaW46IDIsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZSwKICBzdGVtOiB0cnVlCn0sIHsKICBpZDogImhpbnRtYXNrIiwKICBtaW46IDAsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZQp9LCB7CiAgaWQ6ICJjbnRybWFzayIsCiAgbWluOiAwLAogIHN0YWNrQ2xlYXJpbmc6IHRydWUKfSwgewogIGlkOiAicm1vdmV0byIsCiAgbWluOiAyLAogIHN0YWNrQ2xlYXJpbmc6IHRydWUKfSwgewogIGlkOiAiaG1vdmV0byIsCiAgbWluOiAxLAogIHN0YWNrQ2xlYXJpbmc6IHRydWUKfSwgewogIGlkOiAidnN0ZW1obSIsCiAgbWluOiAyLAogIHN0YWNrQ2xlYXJpbmc6IHRydWUsCiAgc3RlbTogdHJ1ZQp9LCB7CiAgaWQ6ICJyY3VydmVsaW5lIiwKICBtaW46IDgsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJybGluZWN1cnZlIiwKICBtaW46IDgsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJ2dmN1cnZldG8iLAogIG1pbjogNCwKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogImhoY3VydmV0byIsCiAgbWluOiA0LAogIHJlc2V0U3RhY2s6IHRydWUKfSwgbnVsbCwgewogIGlkOiAiY2FsbGdzdWJyIiwKICBtaW46IDEKfSwgewogIGlkOiAidmhjdXJ2ZXRvIiwKICBtaW46IDQsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJodmN1cnZldG8iLAogIG1pbjogNCwKICByZXNldFN0YWNrOiB0cnVlCn1dOwpjb25zdCBDaGFyc3RyaW5nVmFsaWRhdGlvbkRhdGExMiA9IFtudWxsLCBudWxsLCBudWxsLCB7CiAgaWQ6ICJhbmQiLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAtMQp9LCB7CiAgaWQ6ICJvciIsCiAgbWluOiAyLAogIHN0YWNrRGVsdGE6IC0xCn0sIHsKICBpZDogIm5vdCIsCiAgbWluOiAxLAogIHN0YWNrRGVsdGE6IDAKfSwgbnVsbCwgbnVsbCwgbnVsbCwgewogIGlkOiAiYWJzIiwKICBtaW46IDEsCiAgc3RhY2tEZWx0YTogMAp9LCB7CiAgaWQ6ICJhZGQiLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAtMSwKICBzdGFja0ZuKHN0YWNrLCBpbmRleCkgewogICAgc3RhY2tbaW5kZXggLSAyXSA9IHN0YWNrW2luZGV4IC0gMl0gKyBzdGFja1tpbmRleCAtIDFdOwogIH0KfSwgewogIGlkOiAic3ViIiwKICBtaW46IDIsCiAgc3RhY2tEZWx0YTogLTEsCiAgc3RhY2tGbihzdGFjaywgaW5kZXgpIHsKICAgIHN0YWNrW2luZGV4IC0gMl0gPSBzdGFja1tpbmRleCAtIDJdIC0gc3RhY2tbaW5kZXggLSAxXTsKICB9Cn0sIHsKICBpZDogImRpdiIsCiAgbWluOiAyLAogIHN0YWNrRGVsdGE6IC0xLAogIHN0YWNrRm4oc3RhY2ssIGluZGV4KSB7CiAgICBzdGFja1tpbmRleCAtIDJdID0gc3RhY2tbaW5kZXggLSAyXSAvIHN0YWNrW2luZGV4IC0gMV07CiAgfQp9LCBudWxsLCB7CiAgaWQ6ICJuZWciLAogIG1pbjogMSwKICBzdGFja0RlbHRhOiAwLAogIHN0YWNrRm4oc3RhY2ssIGluZGV4KSB7CiAgICBzdGFja1tpbmRleCAtIDFdID0gLXN0YWNrW2luZGV4IC0gMV07CiAgfQp9LCB7CiAgaWQ6ICJlcSIsCiAgbWluOiAyLAogIHN0YWNrRGVsdGE6IC0xCn0sIG51bGwsIG51bGwsIHsKICBpZDogImRyb3AiLAogIG1pbjogMSwKICBzdGFja0RlbHRhOiAtMQp9LCBudWxsLCB7CiAgaWQ6ICJwdXQiLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAtMgp9LCB7CiAgaWQ6ICJnZXQiLAogIG1pbjogMSwKICBzdGFja0RlbHRhOiAwCn0sIHsKICBpZDogImlmZWxzZSIsCiAgbWluOiA0LAogIHN0YWNrRGVsdGE6IC0zCn0sIHsKICBpZDogInJhbmRvbSIsCiAgbWluOiAwLAogIHN0YWNrRGVsdGE6IDEKfSwgewogIGlkOiAibXVsIiwKICBtaW46IDIsCiAgc3RhY2tEZWx0YTogLTEsCiAgc3RhY2tGbihzdGFjaywgaW5kZXgpIHsKICAgIHN0YWNrW2luZGV4IC0gMl0gPSBzdGFja1tpbmRleCAtIDJdICogc3RhY2tbaW5kZXggLSAxXTsKICB9Cn0sIG51bGwsIHsKICBpZDogInNxcnQiLAogIG1pbjogMSwKICBzdGFja0RlbHRhOiAwCn0sIHsKICBpZDogImR1cCIsCiAgbWluOiAxLAogIHN0YWNrRGVsdGE6IDEKfSwgewogIGlkOiAiZXhjaCIsCiAgbWluOiAyLAogIHN0YWNrRGVsdGE6IDAKfSwgewogIGlkOiAiaW5kZXgiLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAwCn0sIHsKICBpZDogInJvbGwiLAogIG1pbjogMywKICBzdGFja0RlbHRhOiAtMgp9LCBudWxsLCBudWxsLCBudWxsLCB7CiAgaWQ6ICJoZmxleCIsCiAgbWluOiA3LAogIHJlc2V0U3RhY2s6IHRydWUKfSwgewogIGlkOiAiZmxleCIsCiAgbWluOiAxMywKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogImhmbGV4MSIsCiAgbWluOiA5LAogIHJlc2V0U3RhY2s6IHRydWUKfSwgewogIGlkOiAiZmxleDEiLAogIG1pbjogMTEsCiAgcmVzZXRTdGFjazogdHJ1ZQp9XTsKY2xhc3MgQ0ZGUGFyc2VyIHsKICBjb25zdHJ1Y3RvcihmaWxlLCBwcm9wZXJ0aWVzLCBzZWFjQW5hbHlzaXNFbmFibGVkKSB7CiAgICB0aGlzLmJ5dGVzID0gZmlsZS5nZXRCeXRlcygpOwogICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllczsKICAgIHRoaXMuc2VhY0FuYWx5c2lzRW5hYmxlZCA9ICEhc2VhY0FuYWx5c2lzRW5hYmxlZDsKICB9CiAgcGFyc2UoKSB7CiAgICBjb25zdCBwcm9wZXJ0aWVzID0gdGhpcy5wcm9wZXJ0aWVzOwogICAgY29uc3QgY2ZmID0gbmV3IENGRigpOwogICAgdGhpcy5jZmYgPSBjZmY7CiAgICBjb25zdCBoZWFkZXIgPSB0aGlzLnBhcnNlSGVhZGVyKCk7CiAgICBjb25zdCBuYW1lSW5kZXggPSB0aGlzLnBhcnNlSW5kZXgoaGVhZGVyLmVuZFBvcyk7CiAgICBjb25zdCB0b3BEaWN0SW5kZXggPSB0aGlzLnBhcnNlSW5kZXgobmFtZUluZGV4LmVuZFBvcyk7CiAgICBjb25zdCBzdHJpbmdJbmRleCA9IHRoaXMucGFyc2VJbmRleCh0b3BEaWN0SW5kZXguZW5kUG9zKTsKICAgIGNvbnN0IGdsb2JhbFN1YnJJbmRleCA9IHRoaXMucGFyc2VJbmRleChzdHJpbmdJbmRleC5lbmRQb3MpOwogICAgY29uc3QgdG9wRGljdFBhcnNlZCA9IHRoaXMucGFyc2VEaWN0KHRvcERpY3RJbmRleC5vYmouZ2V0KDApKTsKICAgIGNvbnN0IHRvcERpY3QgPSB0aGlzLmNyZWF0ZURpY3QoQ0ZGVG9wRGljdCwgdG9wRGljdFBhcnNlZCwgY2ZmLnN0cmluZ3MpOwogICAgY2ZmLmhlYWRlciA9IGhlYWRlci5vYmo7CiAgICBjZmYubmFtZXMgPSB0aGlzLnBhcnNlTmFtZUluZGV4KG5hbWVJbmRleC5vYmopOwogICAgY2ZmLnN0cmluZ3MgPSB0aGlzLnBhcnNlU3RyaW5nSW5kZXgoc3RyaW5nSW5kZXgub2JqKTsKICAgIGNmZi50b3BEaWN0ID0gdG9wRGljdDsKICAgIGNmZi5nbG9iYWxTdWJySW5kZXggPSBnbG9iYWxTdWJySW5kZXgub2JqOwogICAgdGhpcy5wYXJzZVByaXZhdGVEaWN0KGNmZi50b3BEaWN0KTsKICAgIGNmZi5pc0NJREZvbnQgPSB0b3BEaWN0Lmhhc05hbWUoIlJPUyIpOwogICAgY29uc3QgY2hhclN0cmluZ09mZnNldCA9IHRvcERpY3QuZ2V0QnlOYW1lKCJDaGFyU3RyaW5ncyIpOwogICAgY29uc3QgY2hhclN0cmluZ0luZGV4ID0gdGhpcy5wYXJzZUluZGV4KGNoYXJTdHJpbmdPZmZzZXQpLm9iajsKICAgIGNmZi5jaGFyU3RyaW5nQ291bnQgPSBjaGFyU3RyaW5nSW5kZXguY291bnQ7CiAgICBjb25zdCBmb250TWF0cml4ID0gdG9wRGljdC5nZXRCeU5hbWUoIkZvbnRNYXRyaXgiKTsKICAgIGlmIChmb250TWF0cml4KSB7CiAgICAgIHByb3BlcnRpZXMuZm9udE1hdHJpeCA9IGZvbnRNYXRyaXg7CiAgICB9CiAgICBjb25zdCBmb250QkJveCA9IHRvcERpY3QuZ2V0QnlOYW1lKCJGb250QkJveCIpOwogICAgaWYgKGZvbnRCQm94KSB7CiAgICAgIHByb3BlcnRpZXMuYXNjZW50ID0gTWF0aC5tYXgoZm9udEJCb3hbM10sIGZvbnRCQm94WzFdKTsKICAgICAgcHJvcGVydGllcy5kZXNjZW50ID0gTWF0aC5taW4oZm9udEJCb3hbMV0sIGZvbnRCQm94WzNdKTsKICAgICAgcHJvcGVydGllcy5hc2NlbnRTY2FsZWQgPSB0cnVlOwogICAgfQogICAgbGV0IGNoYXJzZXQsIGVuY29kaW5nOwogICAgaWYgKGNmZi5pc0NJREZvbnQpIHsKICAgICAgY29uc3QgZmRBcnJheUluZGV4ID0gdGhpcy5wYXJzZUluZGV4KHRvcERpY3QuZ2V0QnlOYW1lKCJGREFycmF5IikpLm9iajsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZmRBcnJheUluZGV4LmNvdW50OyBpIDwgaWk7ICsraSkgewogICAgICAgIGNvbnN0IGRpY3RSYXcgPSBmZEFycmF5SW5kZXguZ2V0KGkpOwogICAgICAgIGNvbnN0IGZvbnREaWN0ID0gdGhpcy5jcmVhdGVEaWN0KENGRlRvcERpY3QsIHRoaXMucGFyc2VEaWN0KGRpY3RSYXcpLCBjZmYuc3RyaW5ncyk7CiAgICAgICAgdGhpcy5wYXJzZVByaXZhdGVEaWN0KGZvbnREaWN0KTsKICAgICAgICBjZmYuZmRBcnJheS5wdXNoKGZvbnREaWN0KTsKICAgICAgfQogICAgICBlbmNvZGluZyA9IG51bGw7CiAgICAgIGNoYXJzZXQgPSB0aGlzLnBhcnNlQ2hhcnNldHModG9wRGljdC5nZXRCeU5hbWUoImNoYXJzZXQiKSwgY2hhclN0cmluZ0luZGV4LmNvdW50LCBjZmYuc3RyaW5ncywgdHJ1ZSk7CiAgICAgIGNmZi5mZFNlbGVjdCA9IHRoaXMucGFyc2VGRFNlbGVjdCh0b3BEaWN0LmdldEJ5TmFtZSgiRkRTZWxlY3QiKSwgY2hhclN0cmluZ0luZGV4LmNvdW50KTsKICAgIH0gZWxzZSB7CiAgICAgIGNoYXJzZXQgPSB0aGlzLnBhcnNlQ2hhcnNldHModG9wRGljdC5nZXRCeU5hbWUoImNoYXJzZXQiKSwgY2hhclN0cmluZ0luZGV4LmNvdW50LCBjZmYuc3RyaW5ncywgZmFsc2UpOwogICAgICBlbmNvZGluZyA9IHRoaXMucGFyc2VFbmNvZGluZyh0b3BEaWN0LmdldEJ5TmFtZSgiRW5jb2RpbmciKSwgcHJvcGVydGllcywgY2ZmLnN0cmluZ3MsIGNoYXJzZXQuY2hhcnNldCk7CiAgICB9CiAgICBjZmYuY2hhcnNldCA9IGNoYXJzZXQ7CiAgICBjZmYuZW5jb2RpbmcgPSBlbmNvZGluZzsKICAgIGNvbnN0IGNoYXJTdHJpbmdzQW5kU2VhY3MgPSB0aGlzLnBhcnNlQ2hhclN0cmluZ3MoewogICAgICBjaGFyU3RyaW5nczogY2hhclN0cmluZ0luZGV4LAogICAgICBsb2NhbFN1YnJJbmRleDogdG9wRGljdC5wcml2YXRlRGljdC5zdWJyc0luZGV4LAogICAgICBnbG9iYWxTdWJySW5kZXg6IGdsb2JhbFN1YnJJbmRleC5vYmosCiAgICAgIGZkU2VsZWN0OiBjZmYuZmRTZWxlY3QsCiAgICAgIGZkQXJyYXk6IGNmZi5mZEFycmF5LAogICAgICBwcml2YXRlRGljdDogdG9wRGljdC5wcml2YXRlRGljdAogICAgfSk7CiAgICBjZmYuY2hhclN0cmluZ3MgPSBjaGFyU3RyaW5nc0FuZFNlYWNzLmNoYXJTdHJpbmdzOwogICAgY2ZmLnNlYWNzID0gY2hhclN0cmluZ3NBbmRTZWFjcy5zZWFjczsKICAgIGNmZi53aWR0aHMgPSBjaGFyU3RyaW5nc0FuZFNlYWNzLndpZHRoczsKICAgIHJldHVybiBjZmY7CiAgfQogIHBhcnNlSGVhZGVyKCkgewogICAgbGV0IGJ5dGVzID0gdGhpcy5ieXRlczsKICAgIGNvbnN0IGJ5dGVzTGVuZ3RoID0gYnl0ZXMubGVuZ3RoOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICB3aGlsZSAob2Zmc2V0IDwgYnl0ZXNMZW5ndGggJiYgYnl0ZXNbb2Zmc2V0XSAhPT0gMSkgewogICAgICArK29mZnNldDsKICAgIH0KICAgIGlmIChvZmZzZXQgPj0gYnl0ZXNMZW5ndGgpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIENGRiBoZWFkZXIiKTsKICAgIH0KICAgIGlmIChvZmZzZXQgIT09IDApIHsKICAgICAgaW5mbygiY2ZmIGRhdGEgaXMgc2hpZnRlZCIpOwogICAgICBieXRlcyA9IGJ5dGVzLnN1YmFycmF5KG9mZnNldCk7CiAgICAgIHRoaXMuYnl0ZXMgPSBieXRlczsKICAgIH0KICAgIGNvbnN0IG1ham9yID0gYnl0ZXNbMF07CiAgICBjb25zdCBtaW5vciA9IGJ5dGVzWzFdOwogICAgY29uc3QgaGRyU2l6ZSA9IGJ5dGVzWzJdOwogICAgY29uc3Qgb2ZmU2l6ZSA9IGJ5dGVzWzNdOwogICAgY29uc3QgaGVhZGVyID0gbmV3IENGRkhlYWRlcihtYWpvciwgbWlub3IsIGhkclNpemUsIG9mZlNpemUpOwogICAgcmV0dXJuIHsKICAgICAgb2JqOiBoZWFkZXIsCiAgICAgIGVuZFBvczogaGRyU2l6ZQogICAgfTsKICB9CiAgcGFyc2VEaWN0KGRpY3QpIHsKICAgIGxldCBwb3MgPSAwOwogICAgZnVuY3Rpb24gcGFyc2VPcGVyYW5kKCkgewogICAgICBsZXQgdmFsdWUgPSBkaWN0W3BvcysrXTsKICAgICAgaWYgKHZhbHVlID09PSAzMCkgewogICAgICAgIHJldHVybiBwYXJzZUZsb2F0T3BlcmFuZCgpOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAyOCkgewogICAgICAgIHZhbHVlID0gcmVhZEludDE2KGRpY3QsIHBvcyk7CiAgICAgICAgcG9zICs9IDI7CiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAyOSkgewogICAgICAgIHZhbHVlID0gZGljdFtwb3MrK107CiAgICAgICAgdmFsdWUgPSB2YWx1ZSA8PCA4IHwgZGljdFtwb3MrK107CiAgICAgICAgdmFsdWUgPSB2YWx1ZSA8PCA4IHwgZGljdFtwb3MrK107CiAgICAgICAgdmFsdWUgPSB2YWx1ZSA8PCA4IHwgZGljdFtwb3MrK107CiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID49IDMyICYmIHZhbHVlIDw9IDI0NikgewogICAgICAgIHJldHVybiB2YWx1ZSAtIDEzOTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAyNDcgJiYgdmFsdWUgPD0gMjUwKSB7CiAgICAgICAgcmV0dXJuICh2YWx1ZSAtIDI0NykgKiAyNTYgKyBkaWN0W3BvcysrXSArIDEwODsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAyNTEgJiYgdmFsdWUgPD0gMjU0KSB7CiAgICAgICAgcmV0dXJuIC0oKHZhbHVlIC0gMjUxKSAqIDI1NikgLSBkaWN0W3BvcysrXSAtIDEwODsKICAgICAgfQogICAgICB3YXJuKCdDRkZQYXJzZXJfcGFyc2VEaWN0OiAiJyArIHZhbHVlICsgJyIgaXMgYSByZXNlcnZlZCBjb21tYW5kLicpOwogICAgICByZXR1cm4gTmFOOwogICAgfQogICAgZnVuY3Rpb24gcGFyc2VGbG9hdE9wZXJhbmQoKSB7CiAgICAgIGxldCBzdHIgPSAiIjsKICAgICAgY29uc3QgZW9mID0gMTU7CiAgICAgIGNvbnN0IGxvb2t1cCA9IFsiMCIsICIxIiwgIjIiLCAiMyIsICI0IiwgIjUiLCAiNiIsICI3IiwgIjgiLCAiOSIsICIuIiwgIkUiLCAiRS0iLCBudWxsLCAiLSJdOwogICAgICBjb25zdCBsZW5ndGggPSBkaWN0Lmxlbmd0aDsKICAgICAgd2hpbGUgKHBvcyA8IGxlbmd0aCkgewogICAgICAgIGNvbnN0IGIgPSBkaWN0W3BvcysrXTsKICAgICAgICBjb25zdCBiMSA9IGIgPj4gNDsKICAgICAgICBjb25zdCBiMiA9IGIgJiAxNTsKICAgICAgICBpZiAoYjEgPT09IGVvZikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHN0ciArPSBsb29rdXBbYjFdOwogICAgICAgIGlmIChiMiA9PT0gZW9mKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgc3RyICs9IGxvb2t1cFtiMl07CiAgICAgIH0KICAgICAgcmV0dXJuIHBhcnNlRmxvYXQoc3RyKTsKICAgIH0KICAgIGxldCBvcGVyYW5kcyA9IFtdOwogICAgY29uc3QgZW50cmllcyA9IFtdOwogICAgcG9zID0gMDsKICAgIGNvbnN0IGVuZCA9IGRpY3QubGVuZ3RoOwogICAgd2hpbGUgKHBvcyA8IGVuZCkgewogICAgICBsZXQgYiA9IGRpY3RbcG9zXTsKICAgICAgaWYgKGIgPD0gMjEpIHsKICAgICAgICBpZiAoYiA9PT0gMTIpIHsKICAgICAgICAgIGIgPSBiIDw8IDggfCBkaWN0WysrcG9zXTsKICAgICAgICB9CiAgICAgICAgZW50cmllcy5wdXNoKFtiLCBvcGVyYW5kc10pOwogICAgICAgIG9wZXJhbmRzID0gW107CiAgICAgICAgKytwb3M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgb3BlcmFuZHMucHVzaChwYXJzZU9wZXJhbmQoKSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBlbnRyaWVzOwogIH0KICBwYXJzZUluZGV4KHBvcykgewogICAgY29uc3QgY2ZmSW5kZXggPSBuZXcgQ0ZGSW5kZXgoKTsKICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5ieXRlczsKICAgIGNvbnN0IGNvdW50ID0gYnl0ZXNbcG9zKytdIDw8IDggfCBieXRlc1twb3MrK107CiAgICBjb25zdCBvZmZzZXRzID0gW107CiAgICBsZXQgZW5kID0gcG9zOwogICAgbGV0IGksIGlpOwogICAgaWYgKGNvdW50ICE9PSAwKSB7CiAgICAgIGNvbnN0IG9mZnNldFNpemUgPSBieXRlc1twb3MrK107CiAgICAgIGNvbnN0IHN0YXJ0UG9zID0gcG9zICsgKGNvdW50ICsgMSkgKiBvZmZzZXRTaXplIC0gMTsKICAgICAgZm9yIChpID0gMCwgaWkgPSBjb3VudCArIDE7IGkgPCBpaTsgKytpKSB7CiAgICAgICAgbGV0IG9mZnNldCA9IDA7CiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBvZmZzZXRTaXplOyArK2opIHsKICAgICAgICAgIG9mZnNldCA8PD0gODsKICAgICAgICAgIG9mZnNldCArPSBieXRlc1twb3MrK107CiAgICAgICAgfQogICAgICAgIG9mZnNldHMucHVzaChzdGFydFBvcyArIG9mZnNldCk7CiAgICAgIH0KICAgICAgZW5kID0gb2Zmc2V0c1tjb3VudF07CiAgICB9CiAgICBmb3IgKGkgPSAwLCBpaSA9IG9mZnNldHMubGVuZ3RoIC0gMTsgaSA8IGlpOyArK2kpIHsKICAgICAgY29uc3Qgb2Zmc2V0U3RhcnQgPSBvZmZzZXRzW2ldOwogICAgICBjb25zdCBvZmZzZXRFbmQgPSBvZmZzZXRzW2kgKyAxXTsKICAgICAgY2ZmSW5kZXguYWRkKGJ5dGVzLnN1YmFycmF5KG9mZnNldFN0YXJ0LCBvZmZzZXRFbmQpKTsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIG9iajogY2ZmSW5kZXgsCiAgICAgIGVuZFBvczogZW5kCiAgICB9OwogIH0KICBwYXJzZU5hbWVJbmRleChpbmRleCkgewogICAgY29uc3QgbmFtZXMgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGluZGV4LmNvdW50OyBpIDwgaWk7ICsraSkgewogICAgICBjb25zdCBuYW1lID0gaW5kZXguZ2V0KGkpOwogICAgICBuYW1lcy5wdXNoKGJ5dGVzVG9TdHJpbmcobmFtZSkpOwogICAgfQogICAgcmV0dXJuIG5hbWVzOwogIH0KICBwYXJzZVN0cmluZ0luZGV4KGluZGV4KSB7CiAgICBjb25zdCBzdHJpbmdzID0gbmV3IENGRlN0cmluZ3MoKTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGluZGV4LmNvdW50OyBpIDwgaWk7ICsraSkgewogICAgICBjb25zdCBkYXRhID0gaW5kZXguZ2V0KGkpOwogICAgICBzdHJpbmdzLmFkZChieXRlc1RvU3RyaW5nKGRhdGEpKTsKICAgIH0KICAgIHJldHVybiBzdHJpbmdzOwogIH0KICBjcmVhdGVEaWN0KFR5cGUsIGRpY3QsIHN0cmluZ3MpIHsKICAgIGNvbnN0IGNmZkRpY3QgPSBuZXcgVHlwZShzdHJpbmdzKTsKICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIGRpY3QpIHsKICAgICAgY2ZmRGljdC5zZXRCeUtleShrZXksIHZhbHVlKTsKICAgIH0KICAgIHJldHVybiBjZmZEaWN0OwogIH0KICBwYXJzZUNoYXJTdHJpbmcoc3RhdGUsIGRhdGEsIGxvY2FsU3VickluZGV4LCBnbG9iYWxTdWJySW5kZXgpIHsKICAgIGlmICghZGF0YSB8fCBzdGF0ZS5jYWxsRGVwdGggPiBNQVhfU1VCUl9ORVNUSU5HKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGxldCBzdGFja1NpemUgPSBzdGF0ZS5zdGFja1NpemU7CiAgICBjb25zdCBzdGFjayA9IHN0YXRlLnN0YWNrOwogICAgbGV0IGxlbmd0aCA9IGRhdGEubGVuZ3RoOwogICAgZm9yIChsZXQgaiA9IDA7IGogPCBsZW5ndGg7KSB7CiAgICAgIGNvbnN0IHZhbHVlID0gZGF0YVtqKytdOwogICAgICBsZXQgdmFsaWRhdGlvbkNvbW1hbmQgPSBudWxsOwogICAgICBpZiAodmFsdWUgPT09IDEyKSB7CiAgICAgICAgY29uc3QgcSA9IGRhdGFbaisrXTsKICAgICAgICBpZiAocSA9PT0gMCkgewogICAgICAgICAgZGF0YVtqIC0gMl0gPSAxMzk7CiAgICAgICAgICBkYXRhW2ogLSAxXSA9IDIyOwogICAgICAgICAgc3RhY2tTaXplID0gMDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFsaWRhdGlvbkNvbW1hbmQgPSBDaGFyc3RyaW5nVmFsaWRhdGlvbkRhdGExMltxXTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDI4KSB7CiAgICAgICAgc3RhY2tbc3RhY2tTaXplXSA9IHJlYWRJbnQxNihkYXRhLCBqKTsKICAgICAgICBqICs9IDI7CiAgICAgICAgc3RhY2tTaXplKys7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDE0KSB7CiAgICAgICAgaWYgKHN0YWNrU2l6ZSA+PSA0KSB7CiAgICAgICAgICBzdGFja1NpemUgLT0gNDsKICAgICAgICAgIGlmICh0aGlzLnNlYWNBbmFseXNpc0VuYWJsZWQpIHsKICAgICAgICAgICAgc3RhdGUuc2VhYyA9IHN0YWNrLnNsaWNlKHN0YWNrU2l6ZSwgc3RhY2tTaXplICsgNCk7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgdmFsaWRhdGlvbkNvbW1hbmQgPSBDaGFyc3RyaW5nVmFsaWRhdGlvbkRhdGFbdmFsdWVdOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID49IDMyICYmIHZhbHVlIDw9IDI0NikgewogICAgICAgIHN0YWNrW3N0YWNrU2l6ZV0gPSB2YWx1ZSAtIDEzOTsKICAgICAgICBzdGFja1NpemUrKzsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAyNDcgJiYgdmFsdWUgPD0gMjU0KSB7CiAgICAgICAgc3RhY2tbc3RhY2tTaXplXSA9IHZhbHVlIDwgMjUxID8gKHZhbHVlIC0gMjQ3IDw8IDgpICsgZGF0YVtqXSArIDEwOCA6IC0odmFsdWUgLSAyNTEgPDwgOCkgLSBkYXRhW2pdIC0gMTA4OwogICAgICAgIGorKzsKICAgICAgICBzdGFja1NpemUrKzsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gMjU1KSB7CiAgICAgICAgc3RhY2tbc3RhY2tTaXplXSA9IChkYXRhW2pdIDw8IDI0IHwgZGF0YVtqICsgMV0gPDwgMTYgfCBkYXRhW2ogKyAyXSA8PCA4IHwgZGF0YVtqICsgM10pIC8gNjU1MzY7CiAgICAgICAgaiArPSA0OwogICAgICAgIHN0YWNrU2l6ZSsrOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAxOSB8fCB2YWx1ZSA9PT0gMjApIHsKICAgICAgICBzdGF0ZS5oaW50cyArPSBzdGFja1NpemUgPj4gMTsKICAgICAgICBpZiAoc3RhdGUuaGludHMgPT09IDApIHsKICAgICAgICAgIGRhdGEuY29weVdpdGhpbihqIC0gMSwgaiwgLTEpOwogICAgICAgICAgaiAtPSAxOwogICAgICAgICAgbGVuZ3RoIC09IDE7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaiArPSBzdGF0ZS5oaW50cyArIDcgPj4gMzsKICAgICAgICBzdGFja1NpemUgJT0gMjsKICAgICAgICB2YWxpZGF0aW9uQ29tbWFuZCA9IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YVt2YWx1ZV07CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDEwIHx8IHZhbHVlID09PSAyOSkgewogICAgICAgIGNvbnN0IHN1YnJzSW5kZXggPSB2YWx1ZSA9PT0gMTAgPyBsb2NhbFN1YnJJbmRleCA6IGdsb2JhbFN1YnJJbmRleDsKICAgICAgICBpZiAoIXN1YnJzSW5kZXgpIHsKICAgICAgICAgIHZhbGlkYXRpb25Db21tYW5kID0gQ2hhcnN0cmluZ1ZhbGlkYXRpb25EYXRhW3ZhbHVlXTsKICAgICAgICAgIHdhcm4oIk1pc3Npbmcgc3VicnNJbmRleCBmb3IgIiArIHZhbGlkYXRpb25Db21tYW5kLmlkKTsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgbGV0IGJpYXMgPSAzMjc2ODsKICAgICAgICBpZiAoc3VicnNJbmRleC5jb3VudCA8IDEyNDApIHsKICAgICAgICAgIGJpYXMgPSAxMDc7CiAgICAgICAgfSBlbHNlIGlmIChzdWJyc0luZGV4LmNvdW50IDwgMzM5MDApIHsKICAgICAgICAgIGJpYXMgPSAxMTMxOwogICAgICAgIH0KICAgICAgICBjb25zdCBzdWJyTnVtYmVyID0gc3RhY2tbLS1zdGFja1NpemVdICsgYmlhczsKICAgICAgICBpZiAoc3Vick51bWJlciA8IDAgfHwgc3Vick51bWJlciA+PSBzdWJyc0luZGV4LmNvdW50IHx8IGlzTmFOKHN1YnJOdW1iZXIpKSB7CiAgICAgICAgICB2YWxpZGF0aW9uQ29tbWFuZCA9IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YVt2YWx1ZV07CiAgICAgICAgICB3YXJuKCJPdXQgb2YgYm91bmRzIHN1YnJJbmRleCBmb3IgIiArIHZhbGlkYXRpb25Db21tYW5kLmlkKTsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgc3RhdGUuc3RhY2tTaXplID0gc3RhY2tTaXplOwogICAgICAgIHN0YXRlLmNhbGxEZXB0aCsrOwogICAgICAgIGNvbnN0IHZhbGlkID0gdGhpcy5wYXJzZUNoYXJTdHJpbmcoc3RhdGUsIHN1YnJzSW5kZXguZ2V0KHN1YnJOdW1iZXIpLCBsb2NhbFN1YnJJbmRleCwgZ2xvYmFsU3VickluZGV4KTsKICAgICAgICBpZiAoIXZhbGlkKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHN0YXRlLmNhbGxEZXB0aC0tOwogICAgICAgIHN0YWNrU2l6ZSA9IHN0YXRlLnN0YWNrU2l6ZTsKICAgICAgICBjb250aW51ZTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gMTEpIHsKICAgICAgICBzdGF0ZS5zdGFja1NpemUgPSBzdGFja1NpemU7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDAgJiYgaiA9PT0gZGF0YS5sZW5ndGgpIHsKICAgICAgICBkYXRhW2ogLSAxXSA9IDE0OwogICAgICAgIHZhbGlkYXRpb25Db21tYW5kID0gQ2hhcnN0cmluZ1ZhbGlkYXRpb25EYXRhWzE0XTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gOSkgewogICAgICAgIGRhdGEuY29weVdpdGhpbihqIC0gMSwgaiwgLTEpOwogICAgICAgIGogLT0gMTsKICAgICAgICBsZW5ndGggLT0gMTsKICAgICAgICBjb250aW51ZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YWxpZGF0aW9uQ29tbWFuZCA9IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YVt2YWx1ZV07CiAgICAgIH0KICAgICAgaWYgKHZhbGlkYXRpb25Db21tYW5kKSB7CiAgICAgICAgaWYgKHZhbGlkYXRpb25Db21tYW5kLnN0ZW0pIHsKICAgICAgICAgIHN0YXRlLmhpbnRzICs9IHN0YWNrU2l6ZSA+PiAxOwogICAgICAgICAgaWYgKHZhbHVlID09PSAzIHx8IHZhbHVlID09PSAyMykgewogICAgICAgICAgICBzdGF0ZS5oYXNWU3RlbXMgPSB0cnVlOwogICAgICAgICAgfSBlbHNlIGlmIChzdGF0ZS5oYXNWU3RlbXMgJiYgKHZhbHVlID09PSAxIHx8IHZhbHVlID09PSAxOCkpIHsKICAgICAgICAgICAgd2FybigiQ0ZGIHN0ZW0gaGludHMgYXJlIGluIHdyb25nIG9yZGVyIik7CiAgICAgICAgICAgIGRhdGFbaiAtIDFdID0gdmFsdWUgPT09IDEgPyAzIDogMjM7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChzdGFja1NpemUgPCB2YWxpZGF0aW9uQ29tbWFuZC5taW4pIHsKICAgICAgICAgIHdhcm4oIk5vdCBlbm91Z2ggcGFyYW1ldGVycyBmb3IgIiArIHZhbGlkYXRpb25Db21tYW5kLmlkICsgIjsgYWN0dWFsOiAiICsgc3RhY2tTaXplICsgIiwgZXhwZWN0ZWQ6ICIgKyB2YWxpZGF0aW9uQ29tbWFuZC5taW4pOwogICAgICAgICAgaWYgKHN0YWNrU2l6ZSA9PT0gMCkgewogICAgICAgICAgICBkYXRhW2ogLSAxXSA9IDE0OwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKHN0YXRlLmZpcnN0U3RhY2tDbGVhcmluZyAmJiB2YWxpZGF0aW9uQ29tbWFuZC5zdGFja0NsZWFyaW5nKSB7CiAgICAgICAgICBzdGF0ZS5maXJzdFN0YWNrQ2xlYXJpbmcgPSBmYWxzZTsKICAgICAgICAgIHN0YWNrU2l6ZSAtPSB2YWxpZGF0aW9uQ29tbWFuZC5taW47CiAgICAgICAgICBpZiAoc3RhY2tTaXplID49IDIgJiYgdmFsaWRhdGlvbkNvbW1hbmQuc3RlbSkgewogICAgICAgICAgICBzdGFja1NpemUgJT0gMjsKICAgICAgICAgIH0gZWxzZSBpZiAoc3RhY2tTaXplID4gMSkgewogICAgICAgICAgICB3YXJuKCJGb3VuZCB0b28gbWFueSBwYXJhbWV0ZXJzIGZvciBzdGFjay1jbGVhcmluZyBjb21tYW5kIik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoc3RhY2tTaXplID4gMCkgewogICAgICAgICAgICBzdGF0ZS53aWR0aCA9IHN0YWNrW3N0YWNrU2l6ZSAtIDFdOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoInN0YWNrRGVsdGEiIGluIHZhbGlkYXRpb25Db21tYW5kKSB7CiAgICAgICAgICBpZiAoInN0YWNrRm4iIGluIHZhbGlkYXRpb25Db21tYW5kKSB7CiAgICAgICAgICAgIHZhbGlkYXRpb25Db21tYW5kLnN0YWNrRm4oc3RhY2ssIHN0YWNrU2l6ZSk7CiAgICAgICAgICB9CiAgICAgICAgICBzdGFja1NpemUgKz0gdmFsaWRhdGlvbkNvbW1hbmQuc3RhY2tEZWx0YTsKICAgICAgICB9IGVsc2UgaWYgKHZhbGlkYXRpb25Db21tYW5kLnN0YWNrQ2xlYXJpbmcgfHwgdmFsaWRhdGlvbkNvbW1hbmQucmVzZXRTdGFjaykgewogICAgICAgICAgc3RhY2tTaXplID0gMDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChsZW5ndGggPCBkYXRhLmxlbmd0aCkgewogICAgICBkYXRhLmZpbGwoMTQsIGxlbmd0aCk7CiAgICB9CiAgICBzdGF0ZS5zdGFja1NpemUgPSBzdGFja1NpemU7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgcGFyc2VDaGFyU3RyaW5ncyh7CiAgICBjaGFyU3RyaW5ncywKICAgIGxvY2FsU3VickluZGV4LAogICAgZ2xvYmFsU3VickluZGV4LAogICAgZmRTZWxlY3QsCiAgICBmZEFycmF5LAogICAgcHJpdmF0ZURpY3QKICB9KSB7CiAgICBjb25zdCBzZWFjcyA9IFtdOwogICAgY29uc3Qgd2lkdGhzID0gW107CiAgICBjb25zdCBjb3VudCA9IGNoYXJTdHJpbmdzLmNvdW50OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIGNvbnN0IGNoYXJzdHJpbmcgPSBjaGFyU3RyaW5ncy5nZXQoaSk7CiAgICAgIGNvbnN0IHN0YXRlID0gewogICAgICAgIGNhbGxEZXB0aDogMCwKICAgICAgICBzdGFja1NpemU6IDAsCiAgICAgICAgc3RhY2s6IFtdLAogICAgICAgIGhpbnRzOiAwLAogICAgICAgIGZpcnN0U3RhY2tDbGVhcmluZzogdHJ1ZSwKICAgICAgICBzZWFjOiBudWxsLAogICAgICAgIHdpZHRoOiBudWxsLAogICAgICAgIGhhc1ZTdGVtczogZmFsc2UKICAgICAgfTsKICAgICAgbGV0IHZhbGlkID0gdHJ1ZTsKICAgICAgbGV0IGxvY2FsU3ViclRvVXNlID0gbnVsbDsKICAgICAgbGV0IHByaXZhdGVEaWN0VG9Vc2UgPSBwcml2YXRlRGljdDsKICAgICAgaWYgKGZkU2VsZWN0ICYmIGZkQXJyYXkubGVuZ3RoKSB7CiAgICAgICAgY29uc3QgZmRJbmRleCA9IGZkU2VsZWN0LmdldEZESW5kZXgoaSk7CiAgICAgICAgaWYgKGZkSW5kZXggPT09IC0xKSB7CiAgICAgICAgICB3YXJuKCJHbHlwaCBpbmRleCBpcyBub3QgaW4gZmQgc2VsZWN0LiIpOwogICAgICAgICAgdmFsaWQgPSBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKGZkSW5kZXggPj0gZmRBcnJheS5sZW5ndGgpIHsKICAgICAgICAgIHdhcm4oIkludmFsaWQgZmQgaW5kZXggZm9yIGdseXBoIGluZGV4LiIpOwogICAgICAgICAgdmFsaWQgPSBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKHZhbGlkKSB7CiAgICAgICAgICBwcml2YXRlRGljdFRvVXNlID0gZmRBcnJheVtmZEluZGV4XS5wcml2YXRlRGljdDsKICAgICAgICAgIGxvY2FsU3ViclRvVXNlID0gcHJpdmF0ZURpY3RUb1VzZS5zdWJyc0luZGV4OwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChsb2NhbFN1YnJJbmRleCkgewogICAgICAgIGxvY2FsU3ViclRvVXNlID0gbG9jYWxTdWJySW5kZXg7CiAgICAgIH0KICAgICAgaWYgKHZhbGlkKSB7CiAgICAgICAgdmFsaWQgPSB0aGlzLnBhcnNlQ2hhclN0cmluZyhzdGF0ZSwgY2hhcnN0cmluZywgbG9jYWxTdWJyVG9Vc2UsIGdsb2JhbFN1YnJJbmRleCk7CiAgICAgIH0KICAgICAgaWYgKHN0YXRlLndpZHRoICE9PSBudWxsKSB7CiAgICAgICAgY29uc3Qgbm9taW5hbFdpZHRoID0gcHJpdmF0ZURpY3RUb1VzZS5nZXRCeU5hbWUoIm5vbWluYWxXaWR0aFgiKTsKICAgICAgICB3aWR0aHNbaV0gPSBub21pbmFsV2lkdGggKyBzdGF0ZS53aWR0aDsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBkZWZhdWx0V2lkdGggPSBwcml2YXRlRGljdFRvVXNlLmdldEJ5TmFtZSgiZGVmYXVsdFdpZHRoWCIpOwogICAgICAgIHdpZHRoc1tpXSA9IGRlZmF1bHRXaWR0aDsKICAgICAgfQogICAgICBpZiAoc3RhdGUuc2VhYyAhPT0gbnVsbCkgewogICAgICAgIHNlYWNzW2ldID0gc3RhdGUuc2VhYzsKICAgICAgfQogICAgICBpZiAoIXZhbGlkKSB7CiAgICAgICAgY2hhclN0cmluZ3Muc2V0KGksIG5ldyBVaW50OEFycmF5KFsxNF0pKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHsKICAgICAgY2hhclN0cmluZ3MsCiAgICAgIHNlYWNzLAogICAgICB3aWR0aHMKICAgIH07CiAgfQogIGVtcHR5UHJpdmF0ZURpY3Rpb25hcnkocGFyZW50RGljdCkgewogICAgY29uc3QgcHJpdmF0ZURpY3QgPSB0aGlzLmNyZWF0ZURpY3QoQ0ZGUHJpdmF0ZURpY3QsIFtdLCBwYXJlbnREaWN0LnN0cmluZ3MpOwogICAgcGFyZW50RGljdC5zZXRCeUtleSgxOCwgWzAsIDBdKTsKICAgIHBhcmVudERpY3QucHJpdmF0ZURpY3QgPSBwcml2YXRlRGljdDsKICB9CiAgcGFyc2VQcml2YXRlRGljdChwYXJlbnREaWN0KSB7CiAgICBpZiAoIXBhcmVudERpY3QuaGFzTmFtZSgiUHJpdmF0ZSIpKSB7CiAgICAgIHRoaXMuZW1wdHlQcml2YXRlRGljdGlvbmFyeShwYXJlbnREaWN0KTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgcHJpdmF0ZU9mZnNldCA9IHBhcmVudERpY3QuZ2V0QnlOYW1lKCJQcml2YXRlIik7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkocHJpdmF0ZU9mZnNldCkgfHwgcHJpdmF0ZU9mZnNldC5sZW5ndGggIT09IDIpIHsKICAgICAgcGFyZW50RGljdC5yZW1vdmVCeU5hbWUoIlByaXZhdGUiKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgc2l6ZSA9IHByaXZhdGVPZmZzZXRbMF07CiAgICBjb25zdCBvZmZzZXQgPSBwcml2YXRlT2Zmc2V0WzFdOwogICAgaWYgKHNpemUgPT09IDAgfHwgb2Zmc2V0ID49IHRoaXMuYnl0ZXMubGVuZ3RoKSB7CiAgICAgIHRoaXMuZW1wdHlQcml2YXRlRGljdGlvbmFyeShwYXJlbnREaWN0KTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgcHJpdmF0ZURpY3RFbmQgPSBvZmZzZXQgKyBzaXplOwogICAgY29uc3QgZGljdERhdGEgPSB0aGlzLmJ5dGVzLnN1YmFycmF5KG9mZnNldCwgcHJpdmF0ZURpY3RFbmQpOwogICAgY29uc3QgZGljdCA9IHRoaXMucGFyc2VEaWN0KGRpY3REYXRhKTsKICAgIGNvbnN0IHByaXZhdGVEaWN0ID0gdGhpcy5jcmVhdGVEaWN0KENGRlByaXZhdGVEaWN0LCBkaWN0LCBwYXJlbnREaWN0LnN0cmluZ3MpOwogICAgcGFyZW50RGljdC5wcml2YXRlRGljdCA9IHByaXZhdGVEaWN0OwogICAgaWYgKHByaXZhdGVEaWN0LmdldEJ5TmFtZSgiRXhwYW5zaW9uRmFjdG9yIikgPT09IDApIHsKICAgICAgcHJpdmF0ZURpY3Quc2V0QnlOYW1lKCJFeHBhbnNpb25GYWN0b3IiLCAwLjA2KTsKICAgIH0KICAgIGlmICghcHJpdmF0ZURpY3QuZ2V0QnlOYW1lKCJTdWJycyIpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHN1YnJzT2Zmc2V0ID0gcHJpdmF0ZURpY3QuZ2V0QnlOYW1lKCJTdWJycyIpOwogICAgY29uc3QgcmVsYXRpdmVPZmZzZXQgPSBvZmZzZXQgKyBzdWJyc09mZnNldDsKICAgIGlmIChzdWJyc09mZnNldCA9PT0gMCB8fCByZWxhdGl2ZU9mZnNldCA+PSB0aGlzLmJ5dGVzLmxlbmd0aCkgewogICAgICB0aGlzLmVtcHR5UHJpdmF0ZURpY3Rpb25hcnkocGFyZW50RGljdCk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHN1YnJzSW5kZXggPSB0aGlzLnBhcnNlSW5kZXgocmVsYXRpdmVPZmZzZXQpOwogICAgcHJpdmF0ZURpY3Quc3VicnNJbmRleCA9IHN1YnJzSW5kZXgub2JqOwogIH0KICBwYXJzZUNoYXJzZXRzKHBvcywgbGVuZ3RoLCBzdHJpbmdzLCBjaWQpIHsKICAgIGlmIChwb3MgPT09IDApIHsKICAgICAgcmV0dXJuIG5ldyBDRkZDaGFyc2V0KHRydWUsIENGRkNoYXJzZXRQcmVkZWZpbmVkVHlwZXMuSVNPX0FET0JFLCBJU09BZG9iZUNoYXJzZXQpOwogICAgfSBlbHNlIGlmIChwb3MgPT09IDEpIHsKICAgICAgcmV0dXJuIG5ldyBDRkZDaGFyc2V0KHRydWUsIENGRkNoYXJzZXRQcmVkZWZpbmVkVHlwZXMuRVhQRVJULCBFeHBlcnRDaGFyc2V0KTsKICAgIH0gZWxzZSBpZiAocG9zID09PSAyKSB7CiAgICAgIHJldHVybiBuZXcgQ0ZGQ2hhcnNldCh0cnVlLCBDRkZDaGFyc2V0UHJlZGVmaW5lZFR5cGVzLkVYUEVSVF9TVUJTRVQsIEV4cGVydFN1YnNldENoYXJzZXQpOwogICAgfQogICAgY29uc3QgYnl0ZXMgPSB0aGlzLmJ5dGVzOwogICAgY29uc3Qgc3RhcnQgPSBwb3M7CiAgICBjb25zdCBmb3JtYXQgPSBieXRlc1twb3MrK107CiAgICBjb25zdCBjaGFyc2V0ID0gW2NpZCA/IDAgOiAiLm5vdGRlZiJdOwogICAgbGV0IGlkLCBjb3VudCwgaTsKICAgIGxlbmd0aCAtPSAxOwogICAgc3dpdGNoIChmb3JtYXQpIHsKICAgICAgY2FzZSAwOgogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgaWQgPSBieXRlc1twb3MrK10gPDwgOCB8IGJ5dGVzW3BvcysrXTsKICAgICAgICAgIGNoYXJzZXQucHVzaChjaWQgPyBpZCA6IHN0cmluZ3MuZ2V0KGlkKSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDE6CiAgICAgICAgd2hpbGUgKGNoYXJzZXQubGVuZ3RoIDw9IGxlbmd0aCkgewogICAgICAgICAgaWQgPSBieXRlc1twb3MrK10gPDwgOCB8IGJ5dGVzW3BvcysrXTsKICAgICAgICAgIGNvdW50ID0gYnl0ZXNbcG9zKytdOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8PSBjb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGNoYXJzZXQucHVzaChjaWQgPyBpZCsrIDogc3RyaW5ncy5nZXQoaWQrKykpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSAyOgogICAgICAgIHdoaWxlIChjaGFyc2V0Lmxlbmd0aCA8PSBsZW5ndGgpIHsKICAgICAgICAgIGlkID0gYnl0ZXNbcG9zKytdIDw8IDggfCBieXRlc1twb3MrK107CiAgICAgICAgICBjb3VudCA9IGJ5dGVzW3BvcysrXSA8PCA4IHwgYnl0ZXNbcG9zKytdOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8PSBjb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGNoYXJzZXQucHVzaChjaWQgPyBpZCsrIDogc3RyaW5ncy5nZXQoaWQrKykpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gY2hhcnNldCBmb3JtYXQiKTsKICAgIH0KICAgIGNvbnN0IGVuZCA9IHBvczsKICAgIGNvbnN0IHJhdyA9IGJ5dGVzLnN1YmFycmF5KHN0YXJ0LCBlbmQpOwogICAgcmV0dXJuIG5ldyBDRkZDaGFyc2V0KGZhbHNlLCBmb3JtYXQsIGNoYXJzZXQsIHJhdyk7CiAgfQogIHBhcnNlRW5jb2RpbmcocG9zLCBwcm9wZXJ0aWVzLCBzdHJpbmdzLCBjaGFyc2V0KSB7CiAgICBjb25zdCBlbmNvZGluZyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBjb25zdCBieXRlcyA9IHRoaXMuYnl0ZXM7CiAgICBsZXQgcHJlZGVmaW5lZCA9IGZhbHNlOwogICAgbGV0IGZvcm1hdCwgaSwgaWk7CiAgICBsZXQgcmF3ID0gbnVsbDsKICAgIGZ1bmN0aW9uIHJlYWRTdXBwbGVtZW50KCkgewogICAgICBjb25zdCBzdXBwbGVtZW50c0NvdW50ID0gYnl0ZXNbcG9zKytdOwogICAgICBmb3IgKGkgPSAwOyBpIDwgc3VwcGxlbWVudHNDb3VudDsgaSsrKSB7CiAgICAgICAgY29uc3QgY29kZSA9IGJ5dGVzW3BvcysrXTsKICAgICAgICBjb25zdCBzaWQgPSAoYnl0ZXNbcG9zKytdIDw8IDgpICsgKGJ5dGVzW3BvcysrXSAmIDB4ZmYpOwogICAgICAgIGVuY29kaW5nW2NvZGVdID0gY2hhcnNldC5pbmRleE9mKHN0cmluZ3MuZ2V0KHNpZCkpOwogICAgICB9CiAgICB9CiAgICBpZiAocG9zID09PSAwIHx8IHBvcyA9PT0gMSkgewogICAgICBwcmVkZWZpbmVkID0gdHJ1ZTsKICAgICAgZm9ybWF0ID0gcG9zOwogICAgICBjb25zdCBiYXNlRW5jb2RpbmcgPSBwb3MgPyBFeHBlcnRFbmNvZGluZyA6IFN0YW5kYXJkRW5jb2Rpbmc7CiAgICAgIGZvciAoaSA9IDAsIGlpID0gY2hhcnNldC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3QgaW5kZXggPSBiYXNlRW5jb2RpbmcuaW5kZXhPZihjaGFyc2V0W2ldKTsKICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7CiAgICAgICAgICBlbmNvZGluZ1tpbmRleF0gPSBpOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgY29uc3QgZGF0YVN0YXJ0ID0gcG9zOwogICAgICBmb3JtYXQgPSBieXRlc1twb3MrK107CiAgICAgIHN3aXRjaCAoZm9ybWF0ICYgMHg3ZikgewogICAgICAgIGNhc2UgMDoKICAgICAgICAgIGNvbnN0IGdseXBoc0NvdW50ID0gYnl0ZXNbcG9zKytdOwogICAgICAgICAgZm9yIChpID0gMTsgaSA8PSBnbHlwaHNDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGVuY29kaW5nW2J5dGVzW3BvcysrXV0gPSBpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxOgogICAgICAgICAgY29uc3QgcmFuZ2VzQ291bnQgPSBieXRlc1twb3MrK107CiAgICAgICAgICBsZXQgZ2lkID0gMTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCByYW5nZXNDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGNvbnN0IHN0YXJ0ID0gYnl0ZXNbcG9zKytdOwogICAgICAgICAgICBjb25zdCBsZWZ0ID0gYnl0ZXNbcG9zKytdOwogICAgICAgICAgICBmb3IgKGxldCBqID0gc3RhcnQ7IGogPD0gc3RhcnQgKyBsZWZ0OyBqKyspIHsKICAgICAgICAgICAgICBlbmNvZGluZ1tqXSA9IGdpZCsrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBVbmtub3duIGVuY29kaW5nIGZvcm1hdDogJHtmb3JtYXR9IGluIENGRmApOwogICAgICB9CiAgICAgIGNvbnN0IGRhdGFFbmQgPSBwb3M7CiAgICAgIGlmIChmb3JtYXQgJiAweDgwKSB7CiAgICAgICAgYnl0ZXNbZGF0YVN0YXJ0XSAmPSAweDdmOwogICAgICAgIHJlYWRTdXBwbGVtZW50KCk7CiAgICAgIH0KICAgICAgcmF3ID0gYnl0ZXMuc3ViYXJyYXkoZGF0YVN0YXJ0LCBkYXRhRW5kKTsKICAgIH0KICAgIGZvcm1hdCAmPSAweDdmOwogICAgcmV0dXJuIG5ldyBDRkZFbmNvZGluZyhwcmVkZWZpbmVkLCBmb3JtYXQsIGVuY29kaW5nLCByYXcpOwogIH0KICBwYXJzZUZEU2VsZWN0KHBvcywgbGVuZ3RoKSB7CiAgICBjb25zdCBieXRlcyA9IHRoaXMuYnl0ZXM7CiAgICBjb25zdCBmb3JtYXQgPSBieXRlc1twb3MrK107CiAgICBjb25zdCBmZFNlbGVjdCA9IFtdOwogICAgbGV0IGk7CiAgICBzd2l0Y2ggKGZvcm1hdCkgewogICAgICBjYXNlIDA6CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICBjb25zdCBpZCA9IGJ5dGVzW3BvcysrXTsKICAgICAgICAgIGZkU2VsZWN0LnB1c2goaWQpOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSAzOgogICAgICAgIGNvbnN0IHJhbmdlc0NvdW50ID0gYnl0ZXNbcG9zKytdIDw8IDggfCBieXRlc1twb3MrK107CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHJhbmdlc0NvdW50OyArK2kpIHsKICAgICAgICAgIGxldCBmaXJzdCA9IGJ5dGVzW3BvcysrXSA8PCA4IHwgYnl0ZXNbcG9zKytdOwogICAgICAgICAgaWYgKGkgPT09IDAgJiYgZmlyc3QgIT09IDApIHsKICAgICAgICAgICAgd2FybigicGFyc2VGRFNlbGVjdDogVGhlIGZpcnN0IHJhbmdlIG11c3QgaGF2ZSBhIGZpcnN0IEdJRCBvZiAwIiArICIgLS0gdHJ5aW5nIHRvIHJlY292ZXIuIik7CiAgICAgICAgICAgIGZpcnN0ID0gMDsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGZkSW5kZXggPSBieXRlc1twb3MrK107CiAgICAgICAgICBjb25zdCBuZXh0ID0gYnl0ZXNbcG9zXSA8PCA4IHwgYnl0ZXNbcG9zICsgMV07CiAgICAgICAgICBmb3IgKGxldCBqID0gZmlyc3Q7IGogPCBuZXh0OyArK2opIHsKICAgICAgICAgICAgZmRTZWxlY3QucHVzaChmZEluZGV4KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcG9zICs9IDI7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBwYXJzZUZEU2VsZWN0OiBVbmtub3duIGZvcm1hdCAiJHtmb3JtYXR9Ii5gKTsKICAgIH0KICAgIGlmIChmZFNlbGVjdC5sZW5ndGggIT09IGxlbmd0aCkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoInBhcnNlRkRTZWxlY3Q6IEludmFsaWQgZm9udCBkYXRhLiIpOwogICAgfQogICAgcmV0dXJuIG5ldyBDRkZGRFNlbGVjdChmb3JtYXQsIGZkU2VsZWN0KTsKICB9Cn0KY2xhc3MgQ0ZGIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMuaGVhZGVyID0gbnVsbDsKICAgIHRoaXMubmFtZXMgPSBbXTsKICAgIHRoaXMudG9wRGljdCA9IG51bGw7CiAgICB0aGlzLnN0cmluZ3MgPSBuZXcgQ0ZGU3RyaW5ncygpOwogICAgdGhpcy5nbG9iYWxTdWJySW5kZXggPSBudWxsOwogICAgdGhpcy5lbmNvZGluZyA9IG51bGw7CiAgICB0aGlzLmNoYXJzZXQgPSBudWxsOwogICAgdGhpcy5jaGFyU3RyaW5ncyA9IG51bGw7CiAgICB0aGlzLmZkQXJyYXkgPSBbXTsKICAgIHRoaXMuZmRTZWxlY3QgPSBudWxsOwogICAgdGhpcy5pc0NJREZvbnQgPSBmYWxzZTsKICAgIHRoaXMuY2hhclN0cmluZ0NvdW50ID0gMDsKICB9CiAgZHVwbGljYXRlRmlyc3RHbHlwaCgpIHsKICAgIGlmICh0aGlzLmNoYXJTdHJpbmdzLmNvdW50ID49IDY1NTM1KSB7CiAgICAgIHdhcm4oIk5vdCBlbm91Z2ggc3BhY2UgaW4gY2hhcnN0cmluZ3MgdG8gZHVwbGljYXRlIGZpcnN0IGdseXBoLiIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBnbHlwaFplcm8gPSB0aGlzLmNoYXJTdHJpbmdzLmdldCgwKTsKICAgIHRoaXMuY2hhclN0cmluZ3MuYWRkKGdseXBoWmVybyk7CiAgICBpZiAodGhpcy5pc0NJREZvbnQpIHsKICAgICAgdGhpcy5mZFNlbGVjdC5mZFNlbGVjdC5wdXNoKHRoaXMuZmRTZWxlY3QuZmRTZWxlY3RbMF0pOwogICAgfQogIH0KICBoYXNHbHlwaElkKGlkKSB7CiAgICBpZiAoaWQgPCAwIHx8IGlkID49IHRoaXMuY2hhclN0cmluZ3MuY291bnQpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgY29uc3QgZ2x5cGggPSB0aGlzLmNoYXJTdHJpbmdzLmdldChpZCk7CiAgICByZXR1cm4gZ2x5cGgubGVuZ3RoID4gMDsKICB9Cn0KY2xhc3MgQ0ZGSGVhZGVyIHsKICBjb25zdHJ1Y3RvcihtYWpvciwgbWlub3IsIGhkclNpemUsIG9mZlNpemUpIHsKICAgIHRoaXMubWFqb3IgPSBtYWpvcjsKICAgIHRoaXMubWlub3IgPSBtaW5vcjsKICAgIHRoaXMuaGRyU2l6ZSA9IGhkclNpemU7CiAgICB0aGlzLm9mZlNpemUgPSBvZmZTaXplOwogIH0KfQpjbGFzcyBDRkZTdHJpbmdzIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMuc3RyaW5ncyA9IFtdOwogIH0KICBnZXQoaW5kZXgpIHsKICAgIGlmIChpbmRleCA+PSAwICYmIGluZGV4IDw9IE5VTV9TVEFOREFSRF9DRkZfU1RSSU5HUyAtIDEpIHsKICAgICAgcmV0dXJuIENGRlN0YW5kYXJkU3RyaW5nc1tpbmRleF07CiAgICB9CiAgICBpZiAoaW5kZXggLSBOVU1fU1RBTkRBUkRfQ0ZGX1NUUklOR1MgPD0gdGhpcy5zdHJpbmdzLmxlbmd0aCkgewogICAgICByZXR1cm4gdGhpcy5zdHJpbmdzW2luZGV4IC0gTlVNX1NUQU5EQVJEX0NGRl9TVFJJTkdTXTsKICAgIH0KICAgIHJldHVybiBDRkZTdGFuZGFyZFN0cmluZ3NbMF07CiAgfQogIGdldFNJRChzdHIpIHsKICAgIGxldCBpbmRleCA9IENGRlN0YW5kYXJkU3RyaW5ncy5pbmRleE9mKHN0cik7CiAgICBpZiAoaW5kZXggIT09IC0xKSB7CiAgICAgIHJldHVybiBpbmRleDsKICAgIH0KICAgIGluZGV4ID0gdGhpcy5zdHJpbmdzLmluZGV4T2Yoc3RyKTsKICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgcmV0dXJuIGluZGV4ICsgTlVNX1NUQU5EQVJEX0NGRl9TVFJJTkdTOwogICAgfQogICAgcmV0dXJuIC0xOwogIH0KICBhZGQodmFsdWUpIHsKICAgIHRoaXMuc3RyaW5ncy5wdXNoKHZhbHVlKTsKICB9CiAgZ2V0IGNvdW50KCkgewogICAgcmV0dXJuIHRoaXMuc3RyaW5ncy5sZW5ndGg7CiAgfQp9CmNsYXNzIENGRkluZGV4IHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMub2JqZWN0cyA9IFtdOwogICAgdGhpcy5sZW5ndGggPSAwOwogIH0KICBhZGQoZGF0YSkgewogICAgdGhpcy5sZW5ndGggKz0gZGF0YS5sZW5ndGg7CiAgICB0aGlzLm9iamVjdHMucHVzaChkYXRhKTsKICB9CiAgc2V0KGluZGV4LCBkYXRhKSB7CiAgICB0aGlzLmxlbmd0aCArPSBkYXRhLmxlbmd0aCAtIHRoaXMub2JqZWN0c1tpbmRleF0ubGVuZ3RoOwogICAgdGhpcy5vYmplY3RzW2luZGV4XSA9IGRhdGE7CiAgfQogIGdldChpbmRleCkgewogICAgcmV0dXJuIHRoaXMub2JqZWN0c1tpbmRleF07CiAgfQogIGdldCBjb3VudCgpIHsKICAgIHJldHVybiB0aGlzLm9iamVjdHMubGVuZ3RoOwogIH0KfQpjbGFzcyBDRkZEaWN0IHsKICBjb25zdHJ1Y3Rvcih0YWJsZXMsIHN0cmluZ3MpIHsKICAgIHRoaXMua2V5VG9OYW1lTWFwID0gdGFibGVzLmtleVRvTmFtZU1hcDsKICAgIHRoaXMubmFtZVRvS2V5TWFwID0gdGFibGVzLm5hbWVUb0tleU1hcDsKICAgIHRoaXMuZGVmYXVsdHMgPSB0YWJsZXMuZGVmYXVsdHM7CiAgICB0aGlzLnR5cGVzID0gdGFibGVzLnR5cGVzOwogICAgdGhpcy5vcGNvZGVzID0gdGFibGVzLm9wY29kZXM7CiAgICB0aGlzLm9yZGVyID0gdGFibGVzLm9yZGVyOwogICAgdGhpcy5zdHJpbmdzID0gc3RyaW5nczsKICAgIHRoaXMudmFsdWVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICB9CiAgc2V0QnlLZXkoa2V5LCB2YWx1ZSkgewogICAgaWYgKCEoa2V5IGluIHRoaXMua2V5VG9OYW1lTWFwKSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodmFsdWUubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgZm9yIChjb25zdCB2YWwgb2YgdmFsdWUpIHsKICAgICAgaWYgKGlzTmFOKHZhbCkpIHsKICAgICAgICB3YXJuKGBJbnZhbGlkIENGRkRpY3QgdmFsdWU6ICIke3ZhbHVlfSIgZm9yIGtleSAiJHtrZXl9Ii5gKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgfQogICAgY29uc3QgdHlwZSA9IHRoaXMudHlwZXNba2V5XTsKICAgIGlmICh0eXBlID09PSAibnVtIiB8fCB0eXBlID09PSAic2lkIiB8fCB0eXBlID09PSAib2Zmc2V0IikgewogICAgICB2YWx1ZSA9IHZhbHVlWzBdOwogICAgfQogICAgdGhpcy52YWx1ZXNba2V5XSA9IHZhbHVlOwogICAgcmV0dXJuIHRydWU7CiAgfQogIHNldEJ5TmFtZShuYW1lLCB2YWx1ZSkgewogICAgaWYgKCEobmFtZSBpbiB0aGlzLm5hbWVUb0tleU1hcCkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIGRpY3Rpb25hcnkgbmFtZSAiJHtuYW1lfSJgKTsKICAgIH0KICAgIHRoaXMudmFsdWVzW3RoaXMubmFtZVRvS2V5TWFwW25hbWVdXSA9IHZhbHVlOwogIH0KICBoYXNOYW1lKG5hbWUpIHsKICAgIHJldHVybiB0aGlzLm5hbWVUb0tleU1hcFtuYW1lXSBpbiB0aGlzLnZhbHVlczsKICB9CiAgZ2V0QnlOYW1lKG5hbWUpIHsKICAgIGlmICghKG5hbWUgaW4gdGhpcy5uYW1lVG9LZXlNYXApKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBkaWN0aW9uYXJ5IG5hbWUgJHtuYW1lfSJgKTsKICAgIH0KICAgIGNvbnN0IGtleSA9IHRoaXMubmFtZVRvS2V5TWFwW25hbWVdOwogICAgaWYgKCEoa2V5IGluIHRoaXMudmFsdWVzKSkgewogICAgICByZXR1cm4gdGhpcy5kZWZhdWx0c1trZXldOwogICAgfQogICAgcmV0dXJuIHRoaXMudmFsdWVzW2tleV07CiAgfQogIHJlbW92ZUJ5TmFtZShuYW1lKSB7CiAgICBkZWxldGUgdGhpcy52YWx1ZXNbdGhpcy5uYW1lVG9LZXlNYXBbbmFtZV1dOwogIH0KICBzdGF0aWMgY3JlYXRlVGFibGVzKGxheW91dCkgewogICAgY29uc3QgdGFibGVzID0gewogICAgICBrZXlUb05hbWVNYXA6IHt9LAogICAgICBuYW1lVG9LZXlNYXA6IHt9LAogICAgICBkZWZhdWx0czoge30sCiAgICAgIHR5cGVzOiB7fSwKICAgICAgb3Bjb2Rlczoge30sCiAgICAgIG9yZGVyOiBbXQogICAgfTsKICAgIGZvciAoY29uc3QgZW50cnkgb2YgbGF5b3V0KSB7CiAgICAgIGNvbnN0IGtleSA9IEFycmF5LmlzQXJyYXkoZW50cnlbMF0pID8gKGVudHJ5WzBdWzBdIDw8IDgpICsgZW50cnlbMF1bMV0gOiBlbnRyeVswXTsKICAgICAgdGFibGVzLmtleVRvTmFtZU1hcFtrZXldID0gZW50cnlbMV07CiAgICAgIHRhYmxlcy5uYW1lVG9LZXlNYXBbZW50cnlbMV1dID0ga2V5OwogICAgICB0YWJsZXMudHlwZXNba2V5XSA9IGVudHJ5WzJdOwogICAgICB0YWJsZXMuZGVmYXVsdHNba2V5XSA9IGVudHJ5WzNdOwogICAgICB0YWJsZXMub3Bjb2Rlc1trZXldID0gQXJyYXkuaXNBcnJheShlbnRyeVswXSkgPyBlbnRyeVswXSA6IFtlbnRyeVswXV07CiAgICAgIHRhYmxlcy5vcmRlci5wdXNoKGtleSk7CiAgICB9CiAgICByZXR1cm4gdGFibGVzOwogIH0KfQpjb25zdCBDRkZUb3BEaWN0TGF5b3V0ID0gW1tbMTIsIDMwXSwgIlJPUyIsIFsic2lkIiwgInNpZCIsICJudW0iXSwgbnVsbF0sIFtbMTIsIDIwXSwgIlN5bnRoZXRpY0Jhc2UiLCAibnVtIiwgbnVsbF0sIFswLCAidmVyc2lvbiIsICJzaWQiLCBudWxsXSwgWzEsICJOb3RpY2UiLCAic2lkIiwgbnVsbF0sIFtbMTIsIDBdLCAiQ29weXJpZ2h0IiwgInNpZCIsIG51bGxdLCBbMiwgIkZ1bGxOYW1lIiwgInNpZCIsIG51bGxdLCBbMywgIkZhbWlseU5hbWUiLCAic2lkIiwgbnVsbF0sIFs0LCAiV2VpZ2h0IiwgInNpZCIsIG51bGxdLCBbWzEyLCAxXSwgImlzRml4ZWRQaXRjaCIsICJudW0iLCAwXSwgW1sxMiwgMl0sICJJdGFsaWNBbmdsZSIsICJudW0iLCAwXSwgW1sxMiwgM10sICJVbmRlcmxpbmVQb3NpdGlvbiIsICJudW0iLCAtMTAwXSwgW1sxMiwgNF0sICJVbmRlcmxpbmVUaGlja25lc3MiLCAibnVtIiwgNTBdLCBbWzEyLCA1XSwgIlBhaW50VHlwZSIsICJudW0iLCAwXSwgW1sxMiwgNl0sICJDaGFyc3RyaW5nVHlwZSIsICJudW0iLCAyXSwgW1sxMiwgN10sICJGb250TWF0cml4IiwgWyJudW0iLCAibnVtIiwgIm51bSIsICJudW0iLCAibnVtIiwgIm51bSJdLCBbMC4wMDEsIDAsIDAsIDAuMDAxLCAwLCAwXV0sIFsxMywgIlVuaXF1ZUlEIiwgIm51bSIsIG51bGxdLCBbNSwgIkZvbnRCQm94IiwgWyJudW0iLCAibnVtIiwgIm51bSIsICJudW0iXSwgWzAsIDAsIDAsIDBdXSwgW1sxMiwgOF0sICJTdHJva2VXaWR0aCIsICJudW0iLCAwXSwgWzE0LCAiWFVJRCIsICJhcnJheSIsIG51bGxdLCBbMTUsICJjaGFyc2V0IiwgIm9mZnNldCIsIDBdLCBbMTYsICJFbmNvZGluZyIsICJvZmZzZXQiLCAwXSwgWzE3LCAiQ2hhclN0cmluZ3MiLCAib2Zmc2V0IiwgMF0sIFsxOCwgIlByaXZhdGUiLCBbIm9mZnNldCIsICJvZmZzZXQiXSwgbnVsbF0sIFtbMTIsIDIxXSwgIlBvc3RTY3JpcHQiLCAic2lkIiwgbnVsbF0sIFtbMTIsIDIyXSwgIkJhc2VGb250TmFtZSIsICJzaWQiLCBudWxsXSwgW1sxMiwgMjNdLCAiQmFzZUZvbnRCbGVuZCIsICJkZWx0YSIsIG51bGxdLCBbWzEyLCAzMV0sICJDSURGb250VmVyc2lvbiIsICJudW0iLCAwXSwgW1sxMiwgMzJdLCAiQ0lERm9udFJldmlzaW9uIiwgIm51bSIsIDBdLCBbWzEyLCAzM10sICJDSURGb250VHlwZSIsICJudW0iLCAwXSwgW1sxMiwgMzRdLCAiQ0lEQ291bnQiLCAibnVtIiwgODcyMF0sIFtbMTIsIDM1XSwgIlVJREJhc2UiLCAibnVtIiwgbnVsbF0sIFtbMTIsIDM3XSwgIkZEU2VsZWN0IiwgIm9mZnNldCIsIG51bGxdLCBbWzEyLCAzNl0sICJGREFycmF5IiwgIm9mZnNldCIsIG51bGxdLCBbWzEyLCAzOF0sICJGb250TmFtZSIsICJzaWQiLCBudWxsXV07CmNsYXNzIENGRlRvcERpY3QgZXh0ZW5kcyBDRkZEaWN0IHsKICBzdGF0aWMgZ2V0IHRhYmxlcygpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgInRhYmxlcyIsIHRoaXMuY3JlYXRlVGFibGVzKENGRlRvcERpY3RMYXlvdXQpKTsKICB9CiAgY29uc3RydWN0b3Ioc3RyaW5ncykgewogICAgc3VwZXIoQ0ZGVG9wRGljdC50YWJsZXMsIHN0cmluZ3MpOwogICAgdGhpcy5wcml2YXRlRGljdCA9IG51bGw7CiAgfQp9CmNvbnN0IENGRlByaXZhdGVEaWN0TGF5b3V0ID0gW1s2LCAiQmx1ZVZhbHVlcyIsICJkZWx0YSIsIG51bGxdLCBbNywgIk90aGVyQmx1ZXMiLCAiZGVsdGEiLCBudWxsXSwgWzgsICJGYW1pbHlCbHVlcyIsICJkZWx0YSIsIG51bGxdLCBbOSwgIkZhbWlseU90aGVyQmx1ZXMiLCAiZGVsdGEiLCBudWxsXSwgW1sxMiwgOV0sICJCbHVlU2NhbGUiLCAibnVtIiwgMC4wMzk2MjVdLCBbWzEyLCAxMF0sICJCbHVlU2hpZnQiLCAibnVtIiwgN10sIFtbMTIsIDExXSwgIkJsdWVGdXp6IiwgIm51bSIsIDFdLCBbMTAsICJTdGRIVyIsICJudW0iLCBudWxsXSwgWzExLCAiU3RkVlciLCAibnVtIiwgbnVsbF0sIFtbMTIsIDEyXSwgIlN0ZW1TbmFwSCIsICJkZWx0YSIsIG51bGxdLCBbWzEyLCAxM10sICJTdGVtU25hcFYiLCAiZGVsdGEiLCBudWxsXSwgW1sxMiwgMTRdLCAiRm9yY2VCb2xkIiwgIm51bSIsIDBdLCBbWzEyLCAxN10sICJMYW5ndWFnZUdyb3VwIiwgIm51bSIsIDBdLCBbWzEyLCAxOF0sICJFeHBhbnNpb25GYWN0b3IiLCAibnVtIiwgMC4wNl0sIFtbMTIsIDE5XSwgImluaXRpYWxSYW5kb21TZWVkIiwgIm51bSIsIDBdLCBbMjAsICJkZWZhdWx0V2lkdGhYIiwgIm51bSIsIDBdLCBbMjEsICJub21pbmFsV2lkdGhYIiwgIm51bSIsIDBdLCBbMTksICJTdWJycyIsICJvZmZzZXQiLCBudWxsXV07CmNsYXNzIENGRlByaXZhdGVEaWN0IGV4dGVuZHMgQ0ZGRGljdCB7CiAgc3RhdGljIGdldCB0YWJsZXMoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJ0YWJsZXMiLCB0aGlzLmNyZWF0ZVRhYmxlcyhDRkZQcml2YXRlRGljdExheW91dCkpOwogIH0KICBjb25zdHJ1Y3RvcihzdHJpbmdzKSB7CiAgICBzdXBlcihDRkZQcml2YXRlRGljdC50YWJsZXMsIHN0cmluZ3MpOwogICAgdGhpcy5zdWJyc0luZGV4ID0gbnVsbDsKICB9Cn0KY29uc3QgQ0ZGQ2hhcnNldFByZWRlZmluZWRUeXBlcyA9IHsKICBJU09fQURPQkU6IDAsCiAgRVhQRVJUOiAxLAogIEVYUEVSVF9TVUJTRVQ6IDIKfTsKY2xhc3MgQ0ZGQ2hhcnNldCB7CiAgY29uc3RydWN0b3IocHJlZGVmaW5lZCwgZm9ybWF0LCBjaGFyc2V0LCByYXcpIHsKICAgIHRoaXMucHJlZGVmaW5lZCA9IHByZWRlZmluZWQ7CiAgICB0aGlzLmZvcm1hdCA9IGZvcm1hdDsKICAgIHRoaXMuY2hhcnNldCA9IGNoYXJzZXQ7CiAgICB0aGlzLnJhdyA9IHJhdzsKICB9Cn0KY2xhc3MgQ0ZGRW5jb2RpbmcgewogIGNvbnN0cnVjdG9yKHByZWRlZmluZWQsIGZvcm1hdCwgZW5jb2RpbmcsIHJhdykgewogICAgdGhpcy5wcmVkZWZpbmVkID0gcHJlZGVmaW5lZDsKICAgIHRoaXMuZm9ybWF0ID0gZm9ybWF0OwogICAgdGhpcy5lbmNvZGluZyA9IGVuY29kaW5nOwogICAgdGhpcy5yYXcgPSByYXc7CiAgfQp9CmNsYXNzIENGRkZEU2VsZWN0IHsKICBjb25zdHJ1Y3Rvcihmb3JtYXQsIGZkU2VsZWN0KSB7CiAgICB0aGlzLmZvcm1hdCA9IGZvcm1hdDsKICAgIHRoaXMuZmRTZWxlY3QgPSBmZFNlbGVjdDsKICB9CiAgZ2V0RkRJbmRleChnbHlwaEluZGV4KSB7CiAgICBpZiAoZ2x5cGhJbmRleCA8IDAgfHwgZ2x5cGhJbmRleCA+PSB0aGlzLmZkU2VsZWN0Lmxlbmd0aCkgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICByZXR1cm4gdGhpcy5mZFNlbGVjdFtnbHlwaEluZGV4XTsKICB9Cn0KY2xhc3MgQ0ZGT2Zmc2V0VHJhY2tlciB7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLm9mZnNldHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIH0KICBpc1RyYWNraW5nKGtleSkgewogICAgcmV0dXJuIGtleSBpbiB0aGlzLm9mZnNldHM7CiAgfQogIHRyYWNrKGtleSwgbG9jYXRpb24pIHsKICAgIGlmIChrZXkgaW4gdGhpcy5vZmZzZXRzKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgQWxyZWFkeSB0cmFja2luZyBsb2NhdGlvbiBvZiAke2tleX1gKTsKICAgIH0KICAgIHRoaXMub2Zmc2V0c1trZXldID0gbG9jYXRpb247CiAgfQogIG9mZnNldCh2YWx1ZSkgewogICAgZm9yIChjb25zdCBrZXkgaW4gdGhpcy5vZmZzZXRzKSB7CiAgICAgIHRoaXMub2Zmc2V0c1trZXldICs9IHZhbHVlOwogICAgfQogIH0KICBzZXRFbnRyeUxvY2F0aW9uKGtleSwgdmFsdWVzLCBvdXRwdXQpIHsKICAgIGlmICghKGtleSBpbiB0aGlzLm9mZnNldHMpKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgTm90IHRyYWNraW5nIGxvY2F0aW9uIG9mICR7a2V5fWApOwogICAgfQogICAgY29uc3QgZGF0YSA9IG91dHB1dC5kYXRhOwogICAgY29uc3QgZGF0YU9mZnNldCA9IHRoaXMub2Zmc2V0c1trZXldOwogICAgY29uc3Qgc2l6ZSA9IDU7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB2YWx1ZXMubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICBjb25zdCBvZmZzZXQwID0gaSAqIHNpemUgKyBkYXRhT2Zmc2V0OwogICAgICBjb25zdCBvZmZzZXQxID0gb2Zmc2V0MCArIDE7CiAgICAgIGNvbnN0IG9mZnNldDIgPSBvZmZzZXQwICsgMjsKICAgICAgY29uc3Qgb2Zmc2V0MyA9IG9mZnNldDAgKyAzOwogICAgICBjb25zdCBvZmZzZXQ0ID0gb2Zmc2V0MCArIDQ7CiAgICAgIGlmIChkYXRhW29mZnNldDBdICE9PSAweDFkIHx8IGRhdGFbb2Zmc2V0MV0gIT09IDAgfHwgZGF0YVtvZmZzZXQyXSAhPT0gMCB8fCBkYXRhW29mZnNldDNdICE9PSAwIHx8IGRhdGFbb2Zmc2V0NF0gIT09IDApIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIndyaXRpbmcgdG8gYW4gb2Zmc2V0IHRoYXQgaXMgbm90IGVtcHR5Iik7CiAgICAgIH0KICAgICAgY29uc3QgdmFsdWUgPSB2YWx1ZXNbaV07CiAgICAgIGRhdGFbb2Zmc2V0MF0gPSAweDFkOwogICAgICBkYXRhW29mZnNldDFdID0gdmFsdWUgPj4gMjQgJiAweGZmOwogICAgICBkYXRhW29mZnNldDJdID0gdmFsdWUgPj4gMTYgJiAweGZmOwogICAgICBkYXRhW29mZnNldDNdID0gdmFsdWUgPj4gOCAmIDB4ZmY7CiAgICAgIGRhdGFbb2Zmc2V0NF0gPSB2YWx1ZSAmIDB4ZmY7CiAgICB9CiAgfQp9CmNsYXNzIENGRkNvbXBpbGVyIHsKICBjb25zdHJ1Y3RvcihjZmYpIHsKICAgIHRoaXMuY2ZmID0gY2ZmOwogIH0KICBjb21waWxlKCkgewogICAgY29uc3QgY2ZmID0gdGhpcy5jZmY7CiAgICBjb25zdCBvdXRwdXQgPSB7CiAgICAgIGRhdGE6IFtdLAogICAgICBsZW5ndGg6IDAsCiAgICAgIGFkZChkYXRhKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHRoaXMuZGF0YS5wdXNoKC4uLmRhdGEpOwogICAgICAgIH0gY2F0Y2ggewogICAgICAgICAgdGhpcy5kYXRhID0gdGhpcy5kYXRhLmNvbmNhdChkYXRhKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5sZW5ndGggPSB0aGlzLmRhdGEubGVuZ3RoOwogICAgICB9CiAgICB9OwogICAgY29uc3QgaGVhZGVyID0gdGhpcy5jb21waWxlSGVhZGVyKGNmZi5oZWFkZXIpOwogICAgb3V0cHV0LmFkZChoZWFkZXIpOwogICAgY29uc3QgbmFtZUluZGV4ID0gdGhpcy5jb21waWxlTmFtZUluZGV4KGNmZi5uYW1lcyk7CiAgICBvdXRwdXQuYWRkKG5hbWVJbmRleCk7CiAgICBpZiAoY2ZmLmlzQ0lERm9udCkgewogICAgICBpZiAoY2ZmLnRvcERpY3QuaGFzTmFtZSgiRm9udE1hdHJpeCIpKSB7CiAgICAgICAgY29uc3QgYmFzZSA9IGNmZi50b3BEaWN0LmdldEJ5TmFtZSgiRm9udE1hdHJpeCIpOwogICAgICAgIGNmZi50b3BEaWN0LnJlbW92ZUJ5TmFtZSgiRm9udE1hdHJpeCIpOwogICAgICAgIGZvciAoY29uc3Qgc3ViRGljdCBvZiBjZmYuZmRBcnJheSkgewogICAgICAgICAgbGV0IG1hdHJpeCA9IGJhc2Uuc2xpY2UoMCk7CiAgICAgICAgICBpZiAoc3ViRGljdC5oYXNOYW1lKCJGb250TWF0cml4IikpIHsKICAgICAgICAgICAgbWF0cml4ID0gVXRpbC50cmFuc2Zvcm0obWF0cml4LCBzdWJEaWN0LmdldEJ5TmFtZSgiRm9udE1hdHJpeCIpKTsKICAgICAgICAgIH0KICAgICAgICAgIHN1YkRpY3Quc2V0QnlOYW1lKCJGb250TWF0cml4IiwgbWF0cml4KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHh1aWQgPSBjZmYudG9wRGljdC5nZXRCeU5hbWUoIlhVSUQiKTsKICAgIGlmICh4dWlkPy5sZW5ndGggPiAxNikgewogICAgICBjZmYudG9wRGljdC5yZW1vdmVCeU5hbWUoIlhVSUQiKTsKICAgIH0KICAgIGNmZi50b3BEaWN0LnNldEJ5TmFtZSgiY2hhcnNldCIsIDApOwogICAgbGV0IGNvbXBpbGVkID0gdGhpcy5jb21waWxlVG9wRGljdHMoW2NmZi50b3BEaWN0XSwgb3V0cHV0Lmxlbmd0aCwgY2ZmLmlzQ0lERm9udCk7CiAgICBvdXRwdXQuYWRkKGNvbXBpbGVkLm91dHB1dCk7CiAgICBjb25zdCB0b3BEaWN0VHJhY2tlciA9IGNvbXBpbGVkLnRyYWNrZXJzWzBdOwogICAgY29uc3Qgc3RyaW5nSW5kZXggPSB0aGlzLmNvbXBpbGVTdHJpbmdJbmRleChjZmYuc3RyaW5ncy5zdHJpbmdzKTsKICAgIG91dHB1dC5hZGQoc3RyaW5nSW5kZXgpOwogICAgY29uc3QgZ2xvYmFsU3VickluZGV4ID0gdGhpcy5jb21waWxlSW5kZXgoY2ZmLmdsb2JhbFN1YnJJbmRleCk7CiAgICBvdXRwdXQuYWRkKGdsb2JhbFN1YnJJbmRleCk7CiAgICBpZiAoY2ZmLmVuY29kaW5nICYmIGNmZi50b3BEaWN0Lmhhc05hbWUoIkVuY29kaW5nIikpIHsKICAgICAgaWYgKGNmZi5lbmNvZGluZy5wcmVkZWZpbmVkKSB7CiAgICAgICAgdG9wRGljdFRyYWNrZXIuc2V0RW50cnlMb2NhdGlvbigiRW5jb2RpbmciLCBbY2ZmLmVuY29kaW5nLmZvcm1hdF0sIG91dHB1dCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgZW5jb2RpbmcgPSB0aGlzLmNvbXBpbGVFbmNvZGluZyhjZmYuZW5jb2RpbmcpOwogICAgICAgIHRvcERpY3RUcmFja2VyLnNldEVudHJ5TG9jYXRpb24oIkVuY29kaW5nIiwgW291dHB1dC5sZW5ndGhdLCBvdXRwdXQpOwogICAgICAgIG91dHB1dC5hZGQoZW5jb2RpbmcpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBjaGFyc2V0ID0gdGhpcy5jb21waWxlQ2hhcnNldChjZmYuY2hhcnNldCwgY2ZmLmNoYXJTdHJpbmdzLmNvdW50LCBjZmYuc3RyaW5ncywgY2ZmLmlzQ0lERm9udCk7CiAgICB0b3BEaWN0VHJhY2tlci5zZXRFbnRyeUxvY2F0aW9uKCJjaGFyc2V0IiwgW291dHB1dC5sZW5ndGhdLCBvdXRwdXQpOwogICAgb3V0cHV0LmFkZChjaGFyc2V0KTsKICAgIGNvbnN0IGNoYXJTdHJpbmdzID0gdGhpcy5jb21waWxlQ2hhclN0cmluZ3MoY2ZmLmNoYXJTdHJpbmdzKTsKICAgIHRvcERpY3RUcmFja2VyLnNldEVudHJ5TG9jYXRpb24oIkNoYXJTdHJpbmdzIiwgW291dHB1dC5sZW5ndGhdLCBvdXRwdXQpOwogICAgb3V0cHV0LmFkZChjaGFyU3RyaW5ncyk7CiAgICBpZiAoY2ZmLmlzQ0lERm9udCkgewogICAgICB0b3BEaWN0VHJhY2tlci5zZXRFbnRyeUxvY2F0aW9uKCJGRFNlbGVjdCIsIFtvdXRwdXQubGVuZ3RoXSwgb3V0cHV0KTsKICAgICAgY29uc3QgZmRTZWxlY3QgPSB0aGlzLmNvbXBpbGVGRFNlbGVjdChjZmYuZmRTZWxlY3QpOwogICAgICBvdXRwdXQuYWRkKGZkU2VsZWN0KTsKICAgICAgY29tcGlsZWQgPSB0aGlzLmNvbXBpbGVUb3BEaWN0cyhjZmYuZmRBcnJheSwgb3V0cHV0Lmxlbmd0aCwgdHJ1ZSk7CiAgICAgIHRvcERpY3RUcmFja2VyLnNldEVudHJ5TG9jYXRpb24oIkZEQXJyYXkiLCBbb3V0cHV0Lmxlbmd0aF0sIG91dHB1dCk7CiAgICAgIG91dHB1dC5hZGQoY29tcGlsZWQub3V0cHV0KTsKICAgICAgY29uc3QgZm9udERpY3RUcmFja2VycyA9IGNvbXBpbGVkLnRyYWNrZXJzOwogICAgICB0aGlzLmNvbXBpbGVQcml2YXRlRGljdHMoY2ZmLmZkQXJyYXksIGZvbnREaWN0VHJhY2tlcnMsIG91dHB1dCk7CiAgICB9CiAgICB0aGlzLmNvbXBpbGVQcml2YXRlRGljdHMoW2NmZi50b3BEaWN0XSwgW3RvcERpY3RUcmFja2VyXSwgb3V0cHV0KTsKICAgIG91dHB1dC5hZGQoWzBdKTsKICAgIHJldHVybiBvdXRwdXQuZGF0YTsKICB9CiAgZW5jb2RlTnVtYmVyKHZhbHVlKSB7CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih2YWx1ZSkpIHsKICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlSW50ZWdlcih2YWx1ZSk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5lbmNvZGVGbG9hdCh2YWx1ZSk7CiAgfQogIHN0YXRpYyBnZXQgRW5jb2RlRmxvYXRSZWdFeHAoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJFbmNvZGVGbG9hdFJlZ0V4cCIsIC9cLihcZCo/KSg/Ojl7NSwyMH18MHs1LDIwfSlcZHswLDJ9KD86ZSguKyl8JCkvKTsKICB9CiAgZW5jb2RlRmxvYXQobnVtKSB7CiAgICBsZXQgdmFsdWUgPSBudW0udG9TdHJpbmcoKTsKICAgIGNvbnN0IG0gPSBDRkZDb21waWxlci5FbmNvZGVGbG9hdFJlZ0V4cC5leGVjKHZhbHVlKTsKICAgIGlmIChtKSB7CiAgICAgIGNvbnN0IGVwc2lsb24gPSBwYXJzZUZsb2F0KCIxZSIgKyAoKG1bMl0gPyArbVsyXSA6IDApICsgbVsxXS5sZW5ndGgpKTsKICAgICAgdmFsdWUgPSAoTWF0aC5yb3VuZChudW0gKiBlcHNpbG9uKSAvIGVwc2lsb24pLnRvU3RyaW5nKCk7CiAgICB9CiAgICBsZXQgbmliYmxlcyA9ICIiOwogICAgbGV0IGksIGlpOwogICAgZm9yIChpID0gMCwgaWkgPSB2YWx1ZS5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICAgIGNvbnN0IGEgPSB2YWx1ZVtpXTsKICAgICAgaWYgKGEgPT09ICJlIikgewogICAgICAgIG5pYmJsZXMgKz0gdmFsdWVbKytpXSA9PT0gIi0iID8gImMiIDogImIiOwogICAgICB9IGVsc2UgaWYgKGEgPT09ICIuIikgewogICAgICAgIG5pYmJsZXMgKz0gImEiOwogICAgICB9IGVsc2UgaWYgKGEgPT09ICItIikgewogICAgICAgIG5pYmJsZXMgKz0gImUiOwogICAgICB9IGVsc2UgewogICAgICAgIG5pYmJsZXMgKz0gYTsKICAgICAgfQogICAgfQogICAgbmliYmxlcyArPSBuaWJibGVzLmxlbmd0aCAmIDEgPyAiZiIgOiAiZmYiOwogICAgY29uc3Qgb3V0ID0gWzMwXTsKICAgIGZvciAoaSA9IDAsIGlpID0gbmliYmxlcy5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7CiAgICAgIG91dC5wdXNoKHBhcnNlSW50KG5pYmJsZXMuc3Vic3RyaW5nKGksIGkgKyAyKSwgMTYpKTsKICAgIH0KICAgIHJldHVybiBvdXQ7CiAgfQogIGVuY29kZUludGVnZXIodmFsdWUpIHsKICAgIGxldCBjb2RlOwogICAgaWYgKHZhbHVlID49IC0xMDcgJiYgdmFsdWUgPD0gMTA3KSB7CiAgICAgIGNvZGUgPSBbdmFsdWUgKyAxMzldOwogICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAxMDggJiYgdmFsdWUgPD0gMTEzMSkgewogICAgICB2YWx1ZSAtPSAxMDg7CiAgICAgIGNvZGUgPSBbKHZhbHVlID4+IDgpICsgMjQ3LCB2YWx1ZSAmIDB4ZmZdOwogICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAtMTEzMSAmJiB2YWx1ZSA8PSAtMTA4KSB7CiAgICAgIHZhbHVlID0gLXZhbHVlIC0gMTA4OwogICAgICBjb2RlID0gWyh2YWx1ZSA+PiA4KSArIDI1MSwgdmFsdWUgJiAweGZmXTsKICAgIH0gZWxzZSBpZiAodmFsdWUgPj0gLTMyNzY4ICYmIHZhbHVlIDw9IDMyNzY3KSB7CiAgICAgIGNvZGUgPSBbMHgxYywgdmFsdWUgPj4gOCAmIDB4ZmYsIHZhbHVlICYgMHhmZl07CiAgICB9IGVsc2UgewogICAgICBjb2RlID0gWzB4MWQsIHZhbHVlID4+IDI0ICYgMHhmZiwgdmFsdWUgPj4gMTYgJiAweGZmLCB2YWx1ZSA+PiA4ICYgMHhmZiwgdmFsdWUgJiAweGZmXTsKICAgIH0KICAgIHJldHVybiBjb2RlOwogIH0KICBjb21waWxlSGVhZGVyKGhlYWRlcikgewogICAgcmV0dXJuIFtoZWFkZXIubWFqb3IsIGhlYWRlci5taW5vciwgNCwgaGVhZGVyLm9mZlNpemVdOwogIH0KICBjb21waWxlTmFtZUluZGV4KG5hbWVzKSB7CiAgICBjb25zdCBuYW1lSW5kZXggPSBuZXcgQ0ZGSW5kZXgoKTsKICAgIGZvciAoY29uc3QgbmFtZSBvZiBuYW1lcykgewogICAgICBjb25zdCBsZW5ndGggPSBNYXRoLm1pbihuYW1lLmxlbmd0aCwgMTI3KTsKICAgICAgbGV0IHNhbml0aXplZE5hbWUgPSBuZXcgQXJyYXkobGVuZ3RoKTsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBsZW5ndGg7IGorKykgewogICAgICAgIGxldCBjaGFyID0gbmFtZVtqXTsKICAgICAgICBpZiAoY2hhciA8ICIhIiB8fCBjaGFyID4gIn4iIHx8IGNoYXIgPT09ICJbIiB8fCBjaGFyID09PSAiXSIgfHwgY2hhciA9PT0gIigiIHx8IGNoYXIgPT09ICIpIiB8fCBjaGFyID09PSAieyIgfHwgY2hhciA9PT0gIn0iIHx8IGNoYXIgPT09ICI8IiB8fCBjaGFyID09PSAiPiIgfHwgY2hhciA9PT0gIi8iIHx8IGNoYXIgPT09ICIlIikgewogICAgICAgICAgY2hhciA9ICJfIjsKICAgICAgICB9CiAgICAgICAgc2FuaXRpemVkTmFtZVtqXSA9IGNoYXI7CiAgICAgIH0KICAgICAgc2FuaXRpemVkTmFtZSA9IHNhbml0aXplZE5hbWUuam9pbigiIik7CiAgICAgIGlmIChzYW5pdGl6ZWROYW1lID09PSAiIikgewogICAgICAgIHNhbml0aXplZE5hbWUgPSAiQmFkX0ZvbnRfTmFtZSI7CiAgICAgIH0KICAgICAgbmFtZUluZGV4LmFkZChzdHJpbmdUb0J5dGVzKHNhbml0aXplZE5hbWUpKTsKICAgIH0KICAgIHJldHVybiB0aGlzLmNvbXBpbGVJbmRleChuYW1lSW5kZXgpOwogIH0KICBjb21waWxlVG9wRGljdHMoZGljdHMsIGxlbmd0aCwgcmVtb3ZlQ2lkS2V5cykgewogICAgY29uc3QgZm9udERpY3RUcmFja2VycyA9IFtdOwogICAgbGV0IGZkQXJyYXlJbmRleCA9IG5ldyBDRkZJbmRleCgpOwogICAgZm9yIChjb25zdCBmb250RGljdCBvZiBkaWN0cykgewogICAgICBpZiAocmVtb3ZlQ2lkS2V5cykgewogICAgICAgIGZvbnREaWN0LnJlbW92ZUJ5TmFtZSgiQ0lERm9udFZlcnNpb24iKTsKICAgICAgICBmb250RGljdC5yZW1vdmVCeU5hbWUoIkNJREZvbnRSZXZpc2lvbiIpOwogICAgICAgIGZvbnREaWN0LnJlbW92ZUJ5TmFtZSgiQ0lERm9udFR5cGUiKTsKICAgICAgICBmb250RGljdC5yZW1vdmVCeU5hbWUoIkNJRENvdW50Iik7CiAgICAgICAgZm9udERpY3QucmVtb3ZlQnlOYW1lKCJVSURCYXNlIik7CiAgICAgIH0KICAgICAgY29uc3QgZm9udERpY3RUcmFja2VyID0gbmV3IENGRk9mZnNldFRyYWNrZXIoKTsKICAgICAgY29uc3QgZm9udERpY3REYXRhID0gdGhpcy5jb21waWxlRGljdChmb250RGljdCwgZm9udERpY3RUcmFja2VyKTsKICAgICAgZm9udERpY3RUcmFja2Vycy5wdXNoKGZvbnREaWN0VHJhY2tlcik7CiAgICAgIGZkQXJyYXlJbmRleC5hZGQoZm9udERpY3REYXRhKTsKICAgICAgZm9udERpY3RUcmFja2VyLm9mZnNldChsZW5ndGgpOwogICAgfQogICAgZmRBcnJheUluZGV4ID0gdGhpcy5jb21waWxlSW5kZXgoZmRBcnJheUluZGV4LCBmb250RGljdFRyYWNrZXJzKTsKICAgIHJldHVybiB7CiAgICAgIHRyYWNrZXJzOiBmb250RGljdFRyYWNrZXJzLAogICAgICBvdXRwdXQ6IGZkQXJyYXlJbmRleAogICAgfTsKICB9CiAgY29tcGlsZVByaXZhdGVEaWN0cyhkaWN0cywgdHJhY2tlcnMsIG91dHB1dCkgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZGljdHMubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICBjb25zdCBmb250RGljdCA9IGRpY3RzW2ldOwogICAgICBjb25zdCBwcml2YXRlRGljdCA9IGZvbnREaWN0LnByaXZhdGVEaWN0OwogICAgICBpZiAoIXByaXZhdGVEaWN0IHx8ICFmb250RGljdC5oYXNOYW1lKCJQcml2YXRlIikpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlRoZXJlIG11c3QgYmUgYSBwcml2YXRlIGRpY3Rpb25hcnkuIik7CiAgICAgIH0KICAgICAgY29uc3QgcHJpdmF0ZURpY3RUcmFja2VyID0gbmV3IENGRk9mZnNldFRyYWNrZXIoKTsKICAgICAgY29uc3QgcHJpdmF0ZURpY3REYXRhID0gdGhpcy5jb21waWxlRGljdChwcml2YXRlRGljdCwgcHJpdmF0ZURpY3RUcmFja2VyKTsKICAgICAgbGV0IG91dHB1dExlbmd0aCA9IG91dHB1dC5sZW5ndGg7CiAgICAgIHByaXZhdGVEaWN0VHJhY2tlci5vZmZzZXQob3V0cHV0TGVuZ3RoKTsKICAgICAgaWYgKCFwcml2YXRlRGljdERhdGEubGVuZ3RoKSB7CiAgICAgICAgb3V0cHV0TGVuZ3RoID0gMDsKICAgICAgfQogICAgICB0cmFja2Vyc1tpXS5zZXRFbnRyeUxvY2F0aW9uKCJQcml2YXRlIiwgW3ByaXZhdGVEaWN0RGF0YS5sZW5ndGgsIG91dHB1dExlbmd0aF0sIG91dHB1dCk7CiAgICAgIG91dHB1dC5hZGQocHJpdmF0ZURpY3REYXRhKTsKICAgICAgaWYgKHByaXZhdGVEaWN0LnN1YnJzSW5kZXggJiYgcHJpdmF0ZURpY3QuaGFzTmFtZSgiU3VicnMiKSkgewogICAgICAgIGNvbnN0IHN1YnJzID0gdGhpcy5jb21waWxlSW5kZXgocHJpdmF0ZURpY3Quc3VicnNJbmRleCk7CiAgICAgICAgcHJpdmF0ZURpY3RUcmFja2VyLnNldEVudHJ5TG9jYXRpb24oIlN1YnJzIiwgW3ByaXZhdGVEaWN0RGF0YS5sZW5ndGhdLCBvdXRwdXQpOwogICAgICAgIG91dHB1dC5hZGQoc3VicnMpOwogICAgICB9CiAgICB9CiAgfQogIGNvbXBpbGVEaWN0KGRpY3QsIG9mZnNldFRyYWNrZXIpIHsKICAgIGNvbnN0IG91dCA9IFtdOwogICAgZm9yIChjb25zdCBrZXkgb2YgZGljdC5vcmRlcikgewogICAgICBpZiAoIShrZXkgaW4gZGljdC52YWx1ZXMpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbGV0IHZhbHVlcyA9IGRpY3QudmFsdWVzW2tleV07CiAgICAgIGxldCB0eXBlcyA9IGRpY3QudHlwZXNba2V5XTsKICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHR5cGVzKSkgewogICAgICAgIHR5cGVzID0gW3R5cGVzXTsKICAgICAgfQogICAgICBpZiAoIUFycmF5LmlzQXJyYXkodmFsdWVzKSkgewogICAgICAgIHZhbHVlcyA9IFt2YWx1ZXNdOwogICAgICB9CiAgICAgIGlmICh2YWx1ZXMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChsZXQgaiA9IDAsIGpqID0gdHlwZXMubGVuZ3RoOyBqIDwgamo7ICsraikgewogICAgICAgIGNvbnN0IHR5cGUgPSB0eXBlc1tqXTsKICAgICAgICBjb25zdCB2YWx1ZSA9IHZhbHVlc1tqXTsKICAgICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICAgIGNhc2UgIm51bSI6CiAgICAgICAgICBjYXNlICJzaWQiOgogICAgICAgICAgICBvdXQucHVzaCguLi50aGlzLmVuY29kZU51bWJlcih2YWx1ZSkpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgIm9mZnNldCI6CiAgICAgICAgICAgIGNvbnN0IG5hbWUgPSBkaWN0LmtleVRvTmFtZU1hcFtrZXldOwogICAgICAgICAgICBpZiAoIW9mZnNldFRyYWNrZXIuaXNUcmFja2luZyhuYW1lKSkgewogICAgICAgICAgICAgIG9mZnNldFRyYWNrZXIudHJhY2sobmFtZSwgb3V0Lmxlbmd0aCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb3V0LnB1c2goMHgxZCwgMCwgMCwgMCwgMCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAiYXJyYXkiOgogICAgICAgICAgY2FzZSAiZGVsdGEiOgogICAgICAgICAgICBvdXQucHVzaCguLi50aGlzLmVuY29kZU51bWJlcih2YWx1ZSkpOwogICAgICAgICAgICBmb3IgKGxldCBrID0gMSwga2sgPSB2YWx1ZXMubGVuZ3RoOyBrIDwga2s7ICsraykgewogICAgICAgICAgICAgIG91dC5wdXNoKC4uLnRoaXMuZW5jb2RlTnVtYmVyKHZhbHVlc1trXSkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBVbmtub3duIGRhdGEgdHlwZSBvZiAke3R5cGV9YCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIG91dC5wdXNoKC4uLmRpY3Qub3Bjb2Rlc1trZXldKTsKICAgIH0KICAgIHJldHVybiBvdXQ7CiAgfQogIGNvbXBpbGVTdHJpbmdJbmRleChzdHJpbmdzKSB7CiAgICBjb25zdCBzdHJpbmdJbmRleCA9IG5ldyBDRkZJbmRleCgpOwogICAgZm9yIChjb25zdCBzdHJpbmcgb2Ygc3RyaW5ncykgewogICAgICBzdHJpbmdJbmRleC5hZGQoc3RyaW5nVG9CeXRlcyhzdHJpbmcpKTsKICAgIH0KICAgIHJldHVybiB0aGlzLmNvbXBpbGVJbmRleChzdHJpbmdJbmRleCk7CiAgfQogIGNvbXBpbGVDaGFyU3RyaW5ncyhjaGFyU3RyaW5ncykgewogICAgY29uc3QgY2hhclN0cmluZ3NJbmRleCA9IG5ldyBDRkZJbmRleCgpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGFyU3RyaW5ncy5jb3VudDsgaSsrKSB7CiAgICAgIGNvbnN0IGdseXBoID0gY2hhclN0cmluZ3MuZ2V0KGkpOwogICAgICBpZiAoZ2x5cGgubGVuZ3RoID09PSAwKSB7CiAgICAgICAgY2hhclN0cmluZ3NJbmRleC5hZGQobmV3IFVpbnQ4QXJyYXkoWzB4OGIsIDB4MGVdKSk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY2hhclN0cmluZ3NJbmRleC5hZGQoZ2x5cGgpOwogICAgfQogICAgcmV0dXJuIHRoaXMuY29tcGlsZUluZGV4KGNoYXJTdHJpbmdzSW5kZXgpOwogIH0KICBjb21waWxlQ2hhcnNldChjaGFyc2V0LCBudW1HbHlwaHMsIHN0cmluZ3MsIGlzQ0lERm9udCkgewogICAgbGV0IG91dDsKICAgIGNvbnN0IG51bUdseXBoc0xlc3NOb3REZWYgPSBudW1HbHlwaHMgLSAxOwogICAgaWYgKGlzQ0lERm9udCkgewogICAgICBjb25zdCBuTGVmdCA9IG51bUdseXBoc0xlc3NOb3REZWYgLSAxOwogICAgICBvdXQgPSBuZXcgVWludDhBcnJheShbMiwgMCwgMSwgbkxlZnQgPj4gOCAmIDB4ZmYsIG5MZWZ0ICYgMHhmZl0pOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgbGVuZ3RoID0gMSArIG51bUdseXBoc0xlc3NOb3REZWYgKiAyOwogICAgICBvdXQgPSBuZXcgVWludDhBcnJheShsZW5ndGgpOwogICAgICBvdXRbMF0gPSAwOwogICAgICBsZXQgY2hhcnNldEluZGV4ID0gMDsKICAgICAgY29uc3QgbnVtQ2hhcnNldHMgPSBjaGFyc2V0LmNoYXJzZXQubGVuZ3RoOwogICAgICBsZXQgd2FybmVkID0gZmFsc2U7CiAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgb3V0Lmxlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgbGV0IHNpZCA9IDA7CiAgICAgICAgaWYgKGNoYXJzZXRJbmRleCA8IG51bUNoYXJzZXRzKSB7CiAgICAgICAgICBjb25zdCBuYW1lID0gY2hhcnNldC5jaGFyc2V0W2NoYXJzZXRJbmRleCsrXTsKICAgICAgICAgIHNpZCA9IHN0cmluZ3MuZ2V0U0lEKG5hbWUpOwogICAgICAgICAgaWYgKHNpZCA9PT0gLTEpIHsKICAgICAgICAgICAgc2lkID0gMDsKICAgICAgICAgICAgaWYgKCF3YXJuZWQpIHsKICAgICAgICAgICAgICB3YXJuZWQgPSB0cnVlOwogICAgICAgICAgICAgIHdhcm4oYENvdWxkbid0IGZpbmQgJHtuYW1lfSBpbiBDRkYgc3RyaW5nc2ApOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG91dFtpXSA9IHNpZCA+PiA4ICYgMHhmZjsKICAgICAgICBvdXRbaSArIDFdID0gc2lkICYgMHhmZjsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHRoaXMuY29tcGlsZVR5cGVkQXJyYXkob3V0KTsKICB9CiAgY29tcGlsZUVuY29kaW5nKGVuY29kaW5nKSB7CiAgICByZXR1cm4gdGhpcy5jb21waWxlVHlwZWRBcnJheShlbmNvZGluZy5yYXcpOwogIH0KICBjb21waWxlRkRTZWxlY3QoZmRTZWxlY3QpIHsKICAgIGNvbnN0IGZvcm1hdCA9IGZkU2VsZWN0LmZvcm1hdDsKICAgIGxldCBvdXQsIGk7CiAgICBzd2l0Y2ggKGZvcm1hdCkgewogICAgICBjYXNlIDA6CiAgICAgICAgb3V0ID0gbmV3IFVpbnQ4QXJyYXkoMSArIGZkU2VsZWN0LmZkU2VsZWN0Lmxlbmd0aCk7CiAgICAgICAgb3V0WzBdID0gZm9ybWF0OwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBmZFNlbGVjdC5mZFNlbGVjdC5sZW5ndGg7IGkrKykgewogICAgICAgICAgb3V0W2kgKyAxXSA9IGZkU2VsZWN0LmZkU2VsZWN0W2ldOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSAzOgogICAgICAgIGNvbnN0IHN0YXJ0ID0gMDsKICAgICAgICBsZXQgbGFzdEZEID0gZmRTZWxlY3QuZmRTZWxlY3RbMF07CiAgICAgICAgY29uc3QgcmFuZ2VzID0gW2Zvcm1hdCwgMCwgMCwgc3RhcnQgPj4gOCAmIDB4ZmYsIHN0YXJ0ICYgMHhmZiwgbGFzdEZEXTsKICAgICAgICBmb3IgKGkgPSAxOyBpIDwgZmRTZWxlY3QuZmRTZWxlY3QubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGNvbnN0IGN1cnJlbnRGRCA9IGZkU2VsZWN0LmZkU2VsZWN0W2ldOwogICAgICAgICAgaWYgKGN1cnJlbnRGRCAhPT0gbGFzdEZEKSB7CiAgICAgICAgICAgIHJhbmdlcy5wdXNoKGkgPj4gOCAmIDB4ZmYsIGkgJiAweGZmLCBjdXJyZW50RkQpOwogICAgICAgICAgICBsYXN0RkQgPSBjdXJyZW50RkQ7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IG51bVJhbmdlcyA9IChyYW5nZXMubGVuZ3RoIC0gMykgLyAzOwogICAgICAgIHJhbmdlc1sxXSA9IG51bVJhbmdlcyA+PiA4ICYgMHhmZjsKICAgICAgICByYW5nZXNbMl0gPSBudW1SYW5nZXMgJiAweGZmOwogICAgICAgIHJhbmdlcy5wdXNoKGkgPj4gOCAmIDB4ZmYsIGkgJiAweGZmKTsKICAgICAgICBvdXQgPSBuZXcgVWludDhBcnJheShyYW5nZXMpOwogICAgICAgIGJyZWFrOwogICAgfQogICAgcmV0dXJuIHRoaXMuY29tcGlsZVR5cGVkQXJyYXkob3V0KTsKICB9CiAgY29tcGlsZVR5cGVkQXJyYXkoZGF0YSkgewogICAgcmV0dXJuIEFycmF5LmZyb20oZGF0YSk7CiAgfQogIGNvbXBpbGVJbmRleChpbmRleCwgdHJhY2tlcnMgPSBbXSkgewogICAgY29uc3Qgb2JqZWN0cyA9IGluZGV4Lm9iamVjdHM7CiAgICBjb25zdCBjb3VudCA9IG9iamVjdHMubGVuZ3RoOwogICAgaWYgKGNvdW50ID09PSAwKSB7CiAgICAgIHJldHVybiBbMCwgMF07CiAgICB9CiAgICBjb25zdCBkYXRhID0gW2NvdW50ID4+IDggJiAweGZmLCBjb3VudCAmIDB4ZmZdOwogICAgbGV0IGxhc3RPZmZzZXQgPSAxLAogICAgICBpOwogICAgZm9yIChpID0gMDsgaSA8IGNvdW50OyArK2kpIHsKICAgICAgbGFzdE9mZnNldCArPSBvYmplY3RzW2ldLmxlbmd0aDsKICAgIH0KICAgIGxldCBvZmZzZXRTaXplOwogICAgaWYgKGxhc3RPZmZzZXQgPCAweDEwMCkgewogICAgICBvZmZzZXRTaXplID0gMTsKICAgIH0gZWxzZSBpZiAobGFzdE9mZnNldCA8IDB4MTAwMDApIHsKICAgICAgb2Zmc2V0U2l6ZSA9IDI7CiAgICB9IGVsc2UgaWYgKGxhc3RPZmZzZXQgPCAweDEwMDAwMDApIHsKICAgICAgb2Zmc2V0U2l6ZSA9IDM7CiAgICB9IGVsc2UgewogICAgICBvZmZzZXRTaXplID0gNDsKICAgIH0KICAgIGRhdGEucHVzaChvZmZzZXRTaXplKTsKICAgIGxldCByZWxhdGl2ZU9mZnNldCA9IDE7CiAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQgKyAxOyBpKyspIHsKICAgICAgaWYgKG9mZnNldFNpemUgPT09IDEpIHsKICAgICAgICBkYXRhLnB1c2gocmVsYXRpdmVPZmZzZXQgJiAweGZmKTsKICAgICAgfSBlbHNlIGlmIChvZmZzZXRTaXplID09PSAyKSB7CiAgICAgICAgZGF0YS5wdXNoKHJlbGF0aXZlT2Zmc2V0ID4+IDggJiAweGZmLCByZWxhdGl2ZU9mZnNldCAmIDB4ZmYpOwogICAgICB9IGVsc2UgaWYgKG9mZnNldFNpemUgPT09IDMpIHsKICAgICAgICBkYXRhLnB1c2gocmVsYXRpdmVPZmZzZXQgPj4gMTYgJiAweGZmLCByZWxhdGl2ZU9mZnNldCA+PiA4ICYgMHhmZiwgcmVsYXRpdmVPZmZzZXQgJiAweGZmKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBkYXRhLnB1c2gocmVsYXRpdmVPZmZzZXQgPj4+IDI0ICYgMHhmZiwgcmVsYXRpdmVPZmZzZXQgPj4gMTYgJiAweGZmLCByZWxhdGl2ZU9mZnNldCA+PiA4ICYgMHhmZiwgcmVsYXRpdmVPZmZzZXQgJiAweGZmKTsKICAgICAgfQogICAgICBpZiAob2JqZWN0c1tpXSkgewogICAgICAgIHJlbGF0aXZlT2Zmc2V0ICs9IG9iamVjdHNbaV0ubGVuZ3RoOwogICAgICB9CiAgICB9CiAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewogICAgICBpZiAodHJhY2tlcnNbaV0pIHsKICAgICAgICB0cmFja2Vyc1tpXS5vZmZzZXQoZGF0YS5sZW5ndGgpOwogICAgICB9CiAgICAgIGRhdGEucHVzaCguLi5vYmplY3RzW2ldKTsKICAgIH0KICAgIHJldHVybiBkYXRhOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvc3RhbmRhcmRfZm9udHMuanMKCgpjb25zdCBnZXRTdGRGb250TWFwID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uICh0KSB7CiAgdFsiVGltZXMtUm9tYW4iXSA9ICJUaW1lcy1Sb21hbiI7CiAgdC5IZWx2ZXRpY2EgPSAiSGVsdmV0aWNhIjsKICB0LkNvdXJpZXIgPSAiQ291cmllciI7CiAgdC5TeW1ib2wgPSAiU3ltYm9sIjsKICB0WyJUaW1lcy1Cb2xkIl0gPSAiVGltZXMtQm9sZCI7CiAgdFsiSGVsdmV0aWNhLUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiQ291cmllci1Cb2xkIl0gPSAiQ291cmllci1Cb2xkIjsKICB0LlphcGZEaW5nYmF0cyA9ICJaYXBmRGluZ2JhdHMiOwogIHRbIlRpbWVzLUl0YWxpYyJdID0gIlRpbWVzLUl0YWxpYyI7CiAgdFsiSGVsdmV0aWNhLU9ibGlxdWUiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdFsiQ291cmllci1PYmxpcXVlIl0gPSAiQ291cmllci1PYmxpcXVlIjsKICB0WyJUaW1lcy1Cb2xkSXRhbGljIl0gPSAiVGltZXMtQm9sZEl0YWxpYyI7CiAgdFsiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJDb3VyaWVyLUJvbGRPYmxpcXVlIl0gPSAiQ291cmllci1Cb2xkT2JsaXF1ZSI7CiAgdC5BcmlhbE5hcnJvdyA9ICJIZWx2ZXRpY2EiOwogIHRbIkFyaWFsTmFycm93LUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiQXJpYWxOYXJyb3ctQm9sZEl0YWxpYyJdID0gIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7CiAgdFsiQXJpYWxOYXJyb3ctSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHQuQXJpYWxCbGFjayA9ICJIZWx2ZXRpY2EiOwogIHRbIkFyaWFsQmxhY2stQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJBcmlhbEJsYWNrLUJvbGRJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkFyaWFsQmxhY2stSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHRbIkFyaWFsLUJsYWNrIl0gPSAiSGVsdmV0aWNhIjsKICB0WyJBcmlhbC1CbGFjay1Cb2xkIl0gPSAiSGVsdmV0aWNhLUJvbGQiOwogIHRbIkFyaWFsLUJsYWNrLUJvbGRJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkFyaWFsLUJsYWNrLUl0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0LkFyaWFsID0gIkhlbHZldGljYSI7CiAgdFsiQXJpYWwtQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJBcmlhbC1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJBcmlhbC1JdGFsaWMiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdC5BcmlhbE1UID0gIkhlbHZldGljYSI7CiAgdFsiQXJpYWwtQm9sZEl0YWxpY01UIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJBcmlhbC1Cb2xkTVQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiQXJpYWwtSXRhbGljTVQiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdFsiQXJpYWwtQm9sZEl0YWxpY01ULUJvbGRJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkFyaWFsLUJvbGRNVC1Cb2xkIl0gPSAiSGVsdmV0aWNhLUJvbGQiOwogIHRbIkFyaWFsLUl0YWxpY01ULUl0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0LkFyaWFsVW5pY29kZU1TID0gIkhlbHZldGljYSI7CiAgdFsiQXJpYWxVbmljb2RlTVMtQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJBcmlhbFVuaWNvZGVNUy1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJBcmlhbFVuaWNvZGVNUy1JdGFsaWMiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdFsiQ291cmllci1Cb2xkSXRhbGljIl0gPSAiQ291cmllci1Cb2xkT2JsaXF1ZSI7CiAgdFsiQ291cmllci1JdGFsaWMiXSA9ICJDb3VyaWVyLU9ibGlxdWUiOwogIHQuQ291cmllck5ldyA9ICJDb3VyaWVyIjsKICB0WyJDb3VyaWVyTmV3LUJvbGQiXSA9ICJDb3VyaWVyLUJvbGQiOwogIHRbIkNvdXJpZXJOZXctQm9sZEl0YWxpYyJdID0gIkNvdXJpZXItQm9sZE9ibGlxdWUiOwogIHRbIkNvdXJpZXJOZXctSXRhbGljIl0gPSAiQ291cmllci1PYmxpcXVlIjsKICB0WyJDb3VyaWVyTmV3UFMtQm9sZEl0YWxpY01UIl0gPSAiQ291cmllci1Cb2xkT2JsaXF1ZSI7CiAgdFsiQ291cmllck5ld1BTLUJvbGRNVCJdID0gIkNvdXJpZXItQm9sZCI7CiAgdFsiQ291cmllck5ld1BTLUl0YWxpY01UIl0gPSAiQ291cmllci1PYmxpcXVlIjsKICB0LkNvdXJpZXJOZXdQU01UID0gIkNvdXJpZXIiOwogIHRbIkhlbHZldGljYS1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJIZWx2ZXRpY2EtSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHRbIkhlbHZldGljYUxUU3RkLUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiU3ltYm9sLUJvbGQiXSA9ICJTeW1ib2wiOwogIHRbIlN5bWJvbC1Cb2xkSXRhbGljIl0gPSAiU3ltYm9sIjsKICB0WyJTeW1ib2wtSXRhbGljIl0gPSAiU3ltYm9sIjsKICB0LlRpbWVzTmV3Um9tYW4gPSAiVGltZXMtUm9tYW4iOwogIHRbIlRpbWVzTmV3Um9tYW4tQm9sZCJdID0gIlRpbWVzLUJvbGQiOwogIHRbIlRpbWVzTmV3Um9tYW4tQm9sZEl0YWxpYyJdID0gIlRpbWVzLUJvbGRJdGFsaWMiOwogIHRbIlRpbWVzTmV3Um9tYW4tSXRhbGljIl0gPSAiVGltZXMtSXRhbGljIjsKICB0LlRpbWVzTmV3Um9tYW5QUyA9ICJUaW1lcy1Sb21hbiI7CiAgdFsiVGltZXNOZXdSb21hblBTLUJvbGQiXSA9ICJUaW1lcy1Cb2xkIjsKICB0WyJUaW1lc05ld1JvbWFuUFMtQm9sZEl0YWxpYyJdID0gIlRpbWVzLUJvbGRJdGFsaWMiOwogIHRbIlRpbWVzTmV3Um9tYW5QUy1Cb2xkSXRhbGljTVQiXSA9ICJUaW1lcy1Cb2xkSXRhbGljIjsKICB0WyJUaW1lc05ld1JvbWFuUFMtQm9sZE1UIl0gPSAiVGltZXMtQm9sZCI7CiAgdFsiVGltZXNOZXdSb21hblBTLUl0YWxpYyJdID0gIlRpbWVzLUl0YWxpYyI7CiAgdFsiVGltZXNOZXdSb21hblBTLUl0YWxpY01UIl0gPSAiVGltZXMtSXRhbGljIjsKICB0LlRpbWVzTmV3Um9tYW5QU01UID0gIlRpbWVzLVJvbWFuIjsKICB0WyJUaW1lc05ld1JvbWFuUFNNVC1Cb2xkIl0gPSAiVGltZXMtQm9sZCI7CiAgdFsiVGltZXNOZXdSb21hblBTTVQtQm9sZEl0YWxpYyJdID0gIlRpbWVzLUJvbGRJdGFsaWMiOwogIHRbIlRpbWVzTmV3Um9tYW5QU01ULUl0YWxpYyJdID0gIlRpbWVzLUl0YWxpYyI7Cn0pOwpjb25zdCBnZXRGb250TmFtZVRvRmlsZU1hcCA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHQuQ291cmllciA9ICJGb3hpdEZpeGVkLnBmYiI7CiAgdFsiQ291cmllci1Cb2xkIl0gPSAiRm94aXRGaXhlZEJvbGQucGZiIjsKICB0WyJDb3VyaWVyLUJvbGRPYmxpcXVlIl0gPSAiRm94aXRGaXhlZEJvbGRJdGFsaWMucGZiIjsKICB0WyJDb3VyaWVyLU9ibGlxdWUiXSA9ICJGb3hpdEZpeGVkSXRhbGljLnBmYiI7CiAgdC5IZWx2ZXRpY2EgPSAiTGliZXJhdGlvblNhbnMtUmVndWxhci50dGYiOwogIHRbIkhlbHZldGljYS1Cb2xkIl0gPSAiTGliZXJhdGlvblNhbnMtQm9sZC50dGYiOwogIHRbIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSJdID0gIkxpYmVyYXRpb25TYW5zLUJvbGRJdGFsaWMudHRmIjsKICB0WyJIZWx2ZXRpY2EtT2JsaXF1ZSJdID0gIkxpYmVyYXRpb25TYW5zLUl0YWxpYy50dGYiOwogIHRbIlRpbWVzLVJvbWFuIl0gPSAiRm94aXRTZXJpZi5wZmIiOwogIHRbIlRpbWVzLUJvbGQiXSA9ICJGb3hpdFNlcmlmQm9sZC5wZmIiOwogIHRbIlRpbWVzLUJvbGRJdGFsaWMiXSA9ICJGb3hpdFNlcmlmQm9sZEl0YWxpYy5wZmIiOwogIHRbIlRpbWVzLUl0YWxpYyJdID0gIkZveGl0U2VyaWZJdGFsaWMucGZiIjsKICB0LlN5bWJvbCA9ICJGb3hpdFN5bWJvbC5wZmIiOwogIHQuWmFwZkRpbmdiYXRzID0gIkZveGl0RGluZ2JhdHMucGZiIjsKICB0WyJMaWJlcmF0aW9uU2Fucy1SZWd1bGFyIl0gPSAiTGliZXJhdGlvblNhbnMtUmVndWxhci50dGYiOwogIHRbIkxpYmVyYXRpb25TYW5zLUJvbGQiXSA9ICJMaWJlcmF0aW9uU2Fucy1Cb2xkLnR0ZiI7CiAgdFsiTGliZXJhdGlvblNhbnMtSXRhbGljIl0gPSAiTGliZXJhdGlvblNhbnMtSXRhbGljLnR0ZiI7CiAgdFsiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYyJdID0gIkxpYmVyYXRpb25TYW5zLUJvbGRJdGFsaWMudHRmIjsKfSk7CmNvbnN0IGdldE5vblN0ZEZvbnRNYXAgPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICB0LkNhbGlicmkgPSAiSGVsdmV0aWNhIjsKICB0WyJDYWxpYnJpLUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiQ2FsaWJyaS1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJDYWxpYnJpLUl0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0LkNlbnR1cnlHb3RoaWMgPSAiSGVsdmV0aWNhIjsKICB0WyJDZW50dXJ5R290aGljLUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiQ2VudHVyeUdvdGhpYy1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJDZW50dXJ5R290aGljLUl0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0LkNvbWljU2Fuc01TID0gIkNvbWljIFNhbnMgTVMiOwogIHRbIkNvbWljU2Fuc01TLUJvbGQiXSA9ICJDb21pYyBTYW5zIE1TLUJvbGQiOwogIHRbIkNvbWljU2Fuc01TLUJvbGRJdGFsaWMiXSA9ICJDb21pYyBTYW5zIE1TLUJvbGRJdGFsaWMiOwogIHRbIkNvbWljU2Fuc01TLUl0YWxpYyJdID0gIkNvbWljIFNhbnMgTVMtSXRhbGljIjsKICB0LkdpbGxTYW5zTVQgPSAiSGVsdmV0aWNhIjsKICB0WyJHaWxsU2Fuc01ULUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiR2lsbFNhbnNNVC1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJHaWxsU2Fuc01ULUl0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0LkltcGFjdCA9ICJIZWx2ZXRpY2EiOwogIHRbIkl0Y1N5bWJvbC1Cb2xkIl0gPSAiSGVsdmV0aWNhLUJvbGQiOwogIHRbIkl0Y1N5bWJvbC1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJJdGNTeW1ib2wtQm9vayJdID0gIkhlbHZldGljYSI7CiAgdFsiSXRjU3ltYm9sLUJvb2tJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdFsiSXRjU3ltYm9sLU1lZGl1bSJdID0gIkhlbHZldGljYSI7CiAgdFsiSXRjU3ltYm9sLU1lZGl1bUl0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0Lkx1Y2lkYUNvbnNvbGUgPSAiQ291cmllciI7CiAgdFsiTHVjaWRhQ29uc29sZS1Cb2xkIl0gPSAiQ291cmllci1Cb2xkIjsKICB0WyJMdWNpZGFDb25zb2xlLUJvbGRJdGFsaWMiXSA9ICJDb3VyaWVyLUJvbGRPYmxpcXVlIjsKICB0WyJMdWNpZGFDb25zb2xlLUl0YWxpYyJdID0gIkNvdXJpZXItT2JsaXF1ZSI7CiAgdFsiTHVjaWRhU2Fucy1EZW1pIl0gPSAiSGVsdmV0aWNhLUJvbGQiOwogIHRbIk1TLUdvdGhpYyJdID0gIk1TIEdvdGhpYyI7CiAgdFsiTVMtR290aGljLUJvbGQiXSA9ICJNUyBHb3RoaWMtQm9sZCI7CiAgdFsiTVMtR290aGljLUJvbGRJdGFsaWMiXSA9ICJNUyBHb3RoaWMtQm9sZEl0YWxpYyI7CiAgdFsiTVMtR290aGljLUl0YWxpYyJdID0gIk1TIEdvdGhpYy1JdGFsaWMiOwogIHRbIk1TLU1pbmNobyJdID0gIk1TIE1pbmNobyI7CiAgdFsiTVMtTWluY2hvLUJvbGQiXSA9ICJNUyBNaW5jaG8tQm9sZCI7CiAgdFsiTVMtTWluY2hvLUJvbGRJdGFsaWMiXSA9ICJNUyBNaW5jaG8tQm9sZEl0YWxpYyI7CiAgdFsiTVMtTWluY2hvLUl0YWxpYyJdID0gIk1TIE1pbmNoby1JdGFsaWMiOwogIHRbIk1TLVBHb3RoaWMiXSA9ICJNUyBQR290aGljIjsKICB0WyJNUy1QR290aGljLUJvbGQiXSA9ICJNUyBQR290aGljLUJvbGQiOwogIHRbIk1TLVBHb3RoaWMtQm9sZEl0YWxpYyJdID0gIk1TIFBHb3RoaWMtQm9sZEl0YWxpYyI7CiAgdFsiTVMtUEdvdGhpYy1JdGFsaWMiXSA9ICJNUyBQR290aGljLUl0YWxpYyI7CiAgdFsiTVMtUE1pbmNobyJdID0gIk1TIFBNaW5jaG8iOwogIHRbIk1TLVBNaW5jaG8tQm9sZCJdID0gIk1TIFBNaW5jaG8tQm9sZCI7CiAgdFsiTVMtUE1pbmNoby1Cb2xkSXRhbGljIl0gPSAiTVMgUE1pbmNoby1Cb2xkSXRhbGljIjsKICB0WyJNUy1QTWluY2hvLUl0YWxpYyJdID0gIk1TIFBNaW5jaG8tSXRhbGljIjsKICB0Lk51cHRpYWxTY3JpcHQgPSAiVGltZXMtSXRhbGljIjsKICB0LlNlZ29lVUlTeW1ib2wgPSAiSGVsdmV0aWNhIjsKfSk7CmNvbnN0IGdldFNlcmlmRm9udHMgPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICB0WyJBZG9iZSBKZW5zb24iXSA9IHRydWU7CiAgdFsiQWRvYmUgVGV4dCJdID0gdHJ1ZTsKICB0LkFsYmVydHVzID0gdHJ1ZTsKICB0LkFsZHVzID0gdHJ1ZTsKICB0LkFsZXhhbmRyaWEgPSB0cnVlOwogIHQuQWxnZXJpYW4gPSB0cnVlOwogIHRbIkFtZXJpY2FuIFR5cGV3cml0ZXIiXSA9IHRydWU7CiAgdC5BbnRpcXVhID0gdHJ1ZTsKICB0LkFwZXggPSB0cnVlOwogIHQuQXJubyA9IHRydWU7CiAgdC5Bc3RlciA9IHRydWU7CiAgdC5BdXJvcmEgPSB0cnVlOwogIHQuQmFza2VydmlsbGUgPSB0cnVlOwogIHQuQmVsbCA9IHRydWU7CiAgdC5CZW1ibyA9IHRydWU7CiAgdFsiQmVtYm8gU2Nob29sYm9vayJdID0gdHJ1ZTsKICB0LkJlbmd1aWF0ID0gdHJ1ZTsKICB0WyJCZXJrZWxleSBPbGQgU3R5bGUiXSA9IHRydWU7CiAgdFsiQmVybmhhcmQgTW9kZXJuIl0gPSB0cnVlOwogIHRbIkJlcnRob2xkIENpdHkiXSA9IHRydWU7CiAgdC5Cb2RvbmkgPSB0cnVlOwogIHRbIkJhdWVyIEJvZG9uaSJdID0gdHJ1ZTsKICB0WyJCb29rIEFudGlxdWEiXSA9IHRydWU7CiAgdC5Cb29rbWFuID0gdHJ1ZTsKICB0WyJCb3JkZWF1eCBSb21hbiJdID0gdHJ1ZTsKICB0WyJDYWxpZm9ybmlhbiBGQiJdID0gdHJ1ZTsKICB0LkNhbGlzdG8gPSB0cnVlOwogIHQuQ2FsdmVydCA9IHRydWU7CiAgdC5DYXBpdGFscyA9IHRydWU7CiAgdC5DYW1icmlhID0gdHJ1ZTsKICB0LkNhcnRpZXIgPSB0cnVlOwogIHQuQ2FzbG9uID0gdHJ1ZTsKICB0LkNhdHVsbCA9IHRydWU7CiAgdC5DZW50YXVyID0gdHJ1ZTsKICB0WyJDZW50dXJ5IE9sZCBTdHlsZSJdID0gdHJ1ZTsKICB0WyJDZW50dXJ5IFNjaG9vbGJvb2siXSA9IHRydWU7CiAgdC5DaGFwYXJyYWwgPSB0cnVlOwogIHRbIkNoYXJpcyBTSUwiXSA9IHRydWU7CiAgdC5DaGVsdGVuaGFtID0gdHJ1ZTsKICB0WyJDaG9sbGEgU2xhYiJdID0gdHJ1ZTsKICB0LkNsYXJlbmRvbiA9IHRydWU7CiAgdC5DbGVhcmZhY2UgPSB0cnVlOwogIHQuQ29jaGluID0gdHJ1ZTsKICB0LkNvbG9ubmEgPSB0cnVlOwogIHRbIkNvbXB1dGVyIE1vZGVybiJdID0gdHJ1ZTsKICB0WyJDb25jcmV0ZSBSb21hbiJdID0gdHJ1ZTsKICB0LkNvbnN0YW50aWEgPSB0cnVlOwogIHRbIkNvb3BlciBCbGFjayJdID0gdHJ1ZTsKICB0LkNvcm9uYSA9IHRydWU7CiAgdC5FY290eXBlID0gdHJ1ZTsKICB0LkVneXB0aWVubmUgPSB0cnVlOwogIHQuRWxlcGhhbnQgPSB0cnVlOwogIHQuRXhjZWxzaW9yID0gdHJ1ZTsKICB0LkZhaXJmaWVsZCA9IHRydWU7CiAgdFsiRkYgU2NhbGEiXSA9IHRydWU7CiAgdC5Gb2xrYXJkID0gdHJ1ZTsKICB0LkZvb3RsaWdodCA9IHRydWU7CiAgdC5GcmVlU2VyaWYgPSB0cnVlOwogIHRbIkZyaXogUXVhZHJhdGEiXSA9IHRydWU7CiAgdC5HYXJhbW9uZCA9IHRydWU7CiAgdC5HZW50aXVtID0gdHJ1ZTsKICB0Lkdlb3JnaWEgPSB0cnVlOwogIHQuR2xvdWNlc3RlciA9IHRydWU7CiAgdFsiR291ZHkgT2xkIFN0eWxlIl0gPSB0cnVlOwogIHRbIkdvdWR5IFNjaG9vbGJvb2siXSA9IHRydWU7CiAgdFsiR291ZHkgUHJvIEZvbnQiXSA9IHRydWU7CiAgdC5HcmFuam9uID0gdHJ1ZTsKICB0WyJHdWFyZGlhbiBFZ3lwdGlhbiJdID0gdHJ1ZTsKICB0LkhlYXRoZXIgPSB0cnVlOwogIHQuSGVyY3VsZXMgPSB0cnVlOwogIHRbIkhpZ2ggVG93ZXIgVGV4dCJdID0gdHJ1ZTsKICB0Lkhpcm9zaGlnZSA9IHRydWU7CiAgdFsiSG9lZmxlciBUZXh0Il0gPSB0cnVlOwogIHRbIkh1bWFuYSBTZXJpZiJdID0gdHJ1ZTsKICB0LkltcHJpbnQgPSB0cnVlOwogIHRbIklvbmljIE5vLiA1Il0gPSB0cnVlOwogIHQuSmFuc29uID0gdHJ1ZTsKICB0LkpvYW5uYSA9IHRydWU7CiAgdC5Lb3Jpbm5hID0gdHJ1ZTsKICB0LkxleGljb24gPSB0cnVlOwogIHQuTGliZXJhdGlvblNlcmlmID0gdHJ1ZTsKICB0WyJMaWJlcmF0aW9uIFNlcmlmIl0gPSB0cnVlOwogIHRbIkxpbnV4IExpYmVydGluZSJdID0gdHJ1ZTsKICB0LkxpdGVyYXR1cm5heWEgPSB0cnVlOwogIHQuTHVjaWRhID0gdHJ1ZTsKICB0WyJMdWNpZGEgQnJpZ2h0Il0gPSB0cnVlOwogIHQuTWVsaW9yID0gdHJ1ZTsKICB0Lk1lbXBoaXMgPSB0cnVlOwogIHQuTWlsbGVyID0gdHJ1ZTsKICB0Lk1pbmlvbiA9IHRydWU7CiAgdC5Nb2Rlcm4gPSB0cnVlOwogIHRbIk1vbmEgTGlzYSJdID0gdHJ1ZTsKICB0WyJNcnMgRWF2ZXMiXSA9IHRydWU7CiAgdFsiTVMgU2VyaWYiXSA9IHRydWU7CiAgdFsiTXVzZW8gU2xhYiJdID0gdHJ1ZTsKICB0WyJOZXcgWW9yayJdID0gdHJ1ZTsKICB0WyJOaW1idXMgUm9tYW4iXSA9IHRydWU7CiAgdFsiTlBTIFJhd2xpbnNvbiBSb2Fkd2F5Il0gPSB0cnVlOwogIHQuTnVwdGlhbFNjcmlwdCA9IHRydWU7CiAgdC5QYWxhdGlubyA9IHRydWU7CiAgdC5QZXJwZXR1YSA9IHRydWU7CiAgdC5QbGFudGluID0gdHJ1ZTsKICB0WyJQbGFudGluIFNjaG9vbGJvb2siXSA9IHRydWU7CiAgdC5QbGF5YmlsbCA9IHRydWU7CiAgdFsiUG9vciBSaWNoYXJkIl0gPSB0cnVlOwogIHRbIlJhd2xpbnNvbiBSb2Fkd2F5Il0gPSB0cnVlOwogIHQuUmVuYXVsdCA9IHRydWU7CiAgdC5SZXF1aWVtID0gdHJ1ZTsKICB0LlJvY2t3ZWxsID0gdHJ1ZTsKICB0LlJvbWFuID0gdHJ1ZTsKICB0WyJSb3RpcyBTZXJpZiJdID0gdHJ1ZTsKICB0LlNhYm9uID0gdHJ1ZTsKICB0LlNjYWxhID0gdHJ1ZTsKICB0LlNlYWd1bGwgPSB0cnVlOwogIHQuU2lzdGluYSA9IHRydWU7CiAgdC5Tb3V2ZW5pciA9IHRydWU7CiAgdC5TVElYID0gdHJ1ZTsKICB0WyJTdG9uZSBJbmZvcm1hbCJdID0gdHJ1ZTsKICB0WyJTdG9uZSBTZXJpZiJdID0gdHJ1ZTsKICB0LlN5bGZhZW4gPSB0cnVlOwogIHQuVGltZXMgPSB0cnVlOwogIHQuVHJhamFuID0gdHJ1ZTsKICB0WyJUcmluaXTDqSJdID0gdHJ1ZTsKICB0WyJUcnVtcCBNZWRpYWV2YWwiXSA9IHRydWU7CiAgdC5VdG9waWEgPSB0cnVlOwogIHRbIlZhbGUgVHlwZSJdID0gdHJ1ZTsKICB0WyJCaXRzdHJlYW0gVmVyYSJdID0gdHJ1ZTsKICB0WyJWZXJhIFNlcmlmIl0gPSB0cnVlOwogIHQuVmVyc2FpbGxlcyA9IHRydWU7CiAgdC5XYW50ZWQgPSB0cnVlOwogIHQuV2Vpc3MgPSB0cnVlOwogIHRbIldpZGUgTGF0aW4iXSA9IHRydWU7CiAgdC5XaW5kc29yID0gdHJ1ZTsKICB0LlhJVFMgPSB0cnVlOwp9KTsKY29uc3QgZ2V0U3ltYm9sc0ZvbnRzID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uICh0KSB7CiAgdC5EaW5nYmF0cyA9IHRydWU7CiAgdC5TeW1ib2wgPSB0cnVlOwogIHQuWmFwZkRpbmdiYXRzID0gdHJ1ZTsKICB0LldpbmdkaW5ncyA9IHRydWU7CiAgdFsiV2luZ2RpbmdzLUJvbGQiXSA9IHRydWU7CiAgdFsiV2luZ2RpbmdzLVJlZ3VsYXIiXSA9IHRydWU7Cn0pOwpjb25zdCBnZXRHbHlwaE1hcEZvclN0YW5kYXJkRm9udHMgPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICB0WzJdID0gMTA7CiAgdFszXSA9IDMyOwogIHRbNF0gPSAzMzsKICB0WzVdID0gMzQ7CiAgdFs2XSA9IDM1OwogIHRbN10gPSAzNjsKICB0WzhdID0gMzc7CiAgdFs5XSA9IDM4OwogIHRbMTBdID0gMzk7CiAgdFsxMV0gPSA0MDsKICB0WzEyXSA9IDQxOwogIHRbMTNdID0gNDI7CiAgdFsxNF0gPSA0MzsKICB0WzE1XSA9IDQ0OwogIHRbMTZdID0gNDU7CiAgdFsxN10gPSA0NjsKICB0WzE4XSA9IDQ3OwogIHRbMTldID0gNDg7CiAgdFsyMF0gPSA0OTsKICB0WzIxXSA9IDUwOwogIHRbMjJdID0gNTE7CiAgdFsyM10gPSA1MjsKICB0WzI0XSA9IDUzOwogIHRbMjVdID0gNTQ7CiAgdFsyNl0gPSA1NTsKICB0WzI3XSA9IDU2OwogIHRbMjhdID0gNTc7CiAgdFsyOV0gPSA1ODsKICB0WzMwXSA9IDg5NDsKICB0WzMxXSA9IDYwOwogIHRbMzJdID0gNjE7CiAgdFszM10gPSA2MjsKICB0WzM0XSA9IDYzOwogIHRbMzVdID0gNjQ7CiAgdFszNl0gPSA2NTsKICB0WzM3XSA9IDY2OwogIHRbMzhdID0gNjc7CiAgdFszOV0gPSA2ODsKICB0WzQwXSA9IDY5OwogIHRbNDFdID0gNzA7CiAgdFs0Ml0gPSA3MTsKICB0WzQzXSA9IDcyOwogIHRbNDRdID0gNzM7CiAgdFs0NV0gPSA3NDsKICB0WzQ2XSA9IDc1OwogIHRbNDddID0gNzY7CiAgdFs0OF0gPSA3NzsKICB0WzQ5XSA9IDc4OwogIHRbNTBdID0gNzk7CiAgdFs1MV0gPSA4MDsKICB0WzUyXSA9IDgxOwogIHRbNTNdID0gODI7CiAgdFs1NF0gPSA4MzsKICB0WzU1XSA9IDg0OwogIHRbNTZdID0gODU7CiAgdFs1N10gPSA4NjsKICB0WzU4XSA9IDg3OwogIHRbNTldID0gODg7CiAgdFs2MF0gPSA4OTsKICB0WzYxXSA9IDkwOwogIHRbNjJdID0gOTE7CiAgdFs2M10gPSA5MjsKICB0WzY0XSA9IDkzOwogIHRbNjVdID0gOTQ7CiAgdFs2Nl0gPSA5NTsKICB0WzY3XSA9IDk2OwogIHRbNjhdID0gOTc7CiAgdFs2OV0gPSA5ODsKICB0WzcwXSA9IDk5OwogIHRbNzFdID0gMTAwOwogIHRbNzJdID0gMTAxOwogIHRbNzNdID0gMTAyOwogIHRbNzRdID0gMTAzOwogIHRbNzVdID0gMTA0OwogIHRbNzZdID0gMTA1OwogIHRbNzddID0gMTA2OwogIHRbNzhdID0gMTA3OwogIHRbNzldID0gMTA4OwogIHRbODBdID0gMTA5OwogIHRbODFdID0gMTEwOwogIHRbODJdID0gMTExOwogIHRbODNdID0gMTEyOwogIHRbODRdID0gMTEzOwogIHRbODVdID0gMTE0OwogIHRbODZdID0gMTE1OwogIHRbODddID0gMTE2OwogIHRbODhdID0gMTE3OwogIHRbODldID0gMTE4OwogIHRbOTBdID0gMTE5OwogIHRbOTFdID0gMTIwOwogIHRbOTJdID0gMTIxOwogIHRbOTNdID0gMTIyOwogIHRbOTRdID0gMTIzOwogIHRbOTVdID0gMTI0OwogIHRbOTZdID0gMTI1OwogIHRbOTddID0gMTI2OwogIHRbOThdID0gMTk2OwogIHRbOTldID0gMTk3OwogIHRbMTAwXSA9IDE5OTsKICB0WzEwMV0gPSAyMDE7CiAgdFsxMDJdID0gMjA5OwogIHRbMTAzXSA9IDIxNDsKICB0WzEwNF0gPSAyMjA7CiAgdFsxMDVdID0gMjI1OwogIHRbMTA2XSA9IDIyNDsKICB0WzEwN10gPSAyMjY7CiAgdFsxMDhdID0gMjI4OwogIHRbMTA5XSA9IDIyNzsKICB0WzExMF0gPSAyMjk7CiAgdFsxMTFdID0gMjMxOwogIHRbMTEyXSA9IDIzMzsKICB0WzExM10gPSAyMzI7CiAgdFsxMTRdID0gMjM0OwogIHRbMTE1XSA9IDIzNTsKICB0WzExNl0gPSAyMzc7CiAgdFsxMTddID0gMjM2OwogIHRbMTE4XSA9IDIzODsKICB0WzExOV0gPSAyMzk7CiAgdFsxMjBdID0gMjQxOwogIHRbMTIxXSA9IDI0MzsKICB0WzEyMl0gPSAyNDI7CiAgdFsxMjNdID0gMjQ0OwogIHRbMTI0XSA9IDI0NjsKICB0WzEyNV0gPSAyNDU7CiAgdFsxMjZdID0gMjUwOwogIHRbMTI3XSA9IDI0OTsKICB0WzEyOF0gPSAyNTE7CiAgdFsxMjldID0gMjUyOwogIHRbMTMwXSA9IDgyMjQ7CiAgdFsxMzFdID0gMTc2OwogIHRbMTMyXSA9IDE2MjsKICB0WzEzM10gPSAxNjM7CiAgdFsxMzRdID0gMTY3OwogIHRbMTM1XSA9IDgyMjY7CiAgdFsxMzZdID0gMTgyOwogIHRbMTM3XSA9IDIyMzsKICB0WzEzOF0gPSAxNzQ7CiAgdFsxMzldID0gMTY5OwogIHRbMTQwXSA9IDg0ODI7CiAgdFsxNDFdID0gMTgwOwogIHRbMTQyXSA9IDE2ODsKICB0WzE0M10gPSA4ODAwOwogIHRbMTQ0XSA9IDE5ODsKICB0WzE0NV0gPSAyMTY7CiAgdFsxNDZdID0gODczNDsKICB0WzE0N10gPSAxNzc7CiAgdFsxNDhdID0gODgwNDsKICB0WzE0OV0gPSA4ODA1OwogIHRbMTUwXSA9IDE2NTsKICB0WzE1MV0gPSAxODE7CiAgdFsxNTJdID0gODcwNjsKICB0WzE1M10gPSA4NzIxOwogIHRbMTU0XSA9IDg3MTk7CiAgdFsxNTZdID0gODc0NzsKICB0WzE1N10gPSAxNzA7CiAgdFsxNThdID0gMTg2OwogIHRbMTU5XSA9IDg0ODY7CiAgdFsxNjBdID0gMjMwOwogIHRbMTYxXSA9IDI0ODsKICB0WzE2Ml0gPSAxOTE7CiAgdFsxNjNdID0gMTYxOwogIHRbMTY0XSA9IDE3MjsKICB0WzE2NV0gPSA4NzMwOwogIHRbMTY2XSA9IDQwMjsKICB0WzE2N10gPSA4Nzc2OwogIHRbMTY4XSA9IDg3MTA7CiAgdFsxNjldID0gMTcxOwogIHRbMTcwXSA9IDE4NzsKICB0WzE3MV0gPSA4MjMwOwogIHRbMTc5XSA9IDgyMjA7CiAgdFsxODBdID0gODIyMTsKICB0WzE4MV0gPSA4MjE2OwogIHRbMTgyXSA9IDgyMTc7CiAgdFsyMDBdID0gMTkzOwogIHRbMjAzXSA9IDIwNTsKICB0WzIwN10gPSAyMTE7CiAgdFsyMTBdID0gMjE4OwogIHRbMjIzXSA9IDcxMTsKICB0WzIyNF0gPSAzMjE7CiAgdFsyMjVdID0gMzIyOwogIHRbMjI2XSA9IDM1MjsKICB0WzIyN10gPSAzNTM7CiAgdFsyMjhdID0gMzgxOwogIHRbMjI5XSA9IDM4MjsKICB0WzIzM10gPSAyMjE7CiAgdFsyMzRdID0gMjUzOwogIHRbMjUyXSA9IDI2MzsKICB0WzI1M10gPSAyNjg7CiAgdFsyNTRdID0gMjY5OwogIHRbMjU4XSA9IDI1ODsKICB0WzI2MF0gPSAyNjA7CiAgdFsyNjFdID0gMjYxOwogIHRbMjY1XSA9IDI4MDsKICB0WzI2Nl0gPSAyODE7CiAgdFsyNjddID0gMjgyOwogIHRbMjY4XSA9IDI4MzsKICB0WzI2OV0gPSAzMTM7CiAgdFsyNzVdID0gMzIzOwogIHRbMjc2XSA9IDMyNDsKICB0WzI3OF0gPSAzMjg7CiAgdFsyODNdID0gMzQ0OwogIHRbMjg0XSA9IDM0NTsKICB0WzI4NV0gPSAzNDY7CiAgdFsyODZdID0gMzQ3OwogIHRbMjkyXSA9IDM2NzsKICB0WzI5NV0gPSAzNzc7CiAgdFsyOTZdID0gMzc4OwogIHRbMjk4XSA9IDM4MDsKICB0WzMwNV0gPSA5NjM7CiAgdFszMDZdID0gOTY0OwogIHRbMzA3XSA9IDk2NjsKICB0WzMwOF0gPSA4MjE1OwogIHRbMzA5XSA9IDgyNTI7CiAgdFszMTBdID0gODMxOTsKICB0WzMxMV0gPSA4MzU5OwogIHRbMzEyXSA9IDg1OTI7CiAgdFszMTNdID0gODU5MzsKICB0WzMzN10gPSA5NTUyOwogIHRbNDkzXSA9IDEwMzk7CiAgdFs0OTRdID0gMTA0MDsKICB0WzU3MF0gPSAxMDQwOwogIHRbNTcxXSA9IDEwNDE7CiAgdFs1NzJdID0gMTA0MjsKICB0WzU3M10gPSAxMDQzOwogIHRbNTc0XSA9IDEwNDQ7CiAgdFs1NzVdID0gMTA0NTsKICB0WzU3Nl0gPSAxMDQ2OwogIHRbNTc3XSA9IDEwNDc7CiAgdFs1NzhdID0gMTA0ODsKICB0WzU3OV0gPSAxMDQ5OwogIHRbNTgwXSA9IDEwNTA7CiAgdFs1ODFdID0gMTA1MTsKICB0WzU4Ml0gPSAxMDUyOwogIHRbNTgzXSA9IDEwNTM7CiAgdFs1ODRdID0gMTA1NDsKICB0WzU4NV0gPSAxMDU1OwogIHRbNTg2XSA9IDEwNTY7CiAgdFs1ODddID0gMTA1NzsKICB0WzU4OF0gPSAxMDU4OwogIHRbNTg5XSA9IDEwNTk7CiAgdFs1OTBdID0gMTA2MDsKICB0WzU5MV0gPSAxMDYxOwogIHRbNTkyXSA9IDEwNjI7CiAgdFs1OTNdID0gMTA2MzsKICB0WzU5NF0gPSAxMDY0OwogIHRbNTk1XSA9IDEwNjU7CiAgdFs1OTZdID0gMTA2NjsKICB0WzU5N10gPSAxMDY3OwogIHRbNTk4XSA9IDEwNjg7CiAgdFs1OTldID0gMTA2OTsKICB0WzYwMF0gPSAxMDcwOwogIHRbNjAxXSA9IDEwNzE7CiAgdFs2MDJdID0gMTA3MjsKICB0WzYwM10gPSAxMDczOwogIHRbNjA0XSA9IDEwNzQ7CiAgdFs2MDVdID0gMTA3NTsKICB0WzYwNl0gPSAxMDc2OwogIHRbNjA3XSA9IDEwNzc7CiAgdFs2MDhdID0gMTA3ODsKICB0WzYwOV0gPSAxMDc5OwogIHRbNjEwXSA9IDEwODA7CiAgdFs2MTFdID0gMTA4MTsKICB0WzYxMl0gPSAxMDgyOwogIHRbNjEzXSA9IDEwODM7CiAgdFs2MTRdID0gMTA4NDsKICB0WzYxNV0gPSAxMDg1OwogIHRbNjE2XSA9IDEwODY7CiAgdFs2MTddID0gMTA4NzsKICB0WzYxOF0gPSAxMDg4OwogIHRbNjE5XSA9IDEwODk7CiAgdFs2MjBdID0gMTA5MDsKICB0WzYyMV0gPSAxMDkxOwogIHRbNjIyXSA9IDEwOTI7CiAgdFs2MjNdID0gMTA5MzsKICB0WzYyNF0gPSAxMDk0OwogIHRbNjI1XSA9IDEwOTU7CiAgdFs2MjZdID0gMTA5NjsKICB0WzYyN10gPSAxMDk3OwogIHRbNjI4XSA9IDEwOTg7CiAgdFs2MjldID0gMTA5OTsKICB0WzYzMF0gPSAxMTAwOwogIHRbNjMxXSA9IDExMDE7CiAgdFs2MzJdID0gMTEwMjsKICB0WzYzM10gPSAxMTAzOwogIHRbNjcyXSA9IDE0ODg7CiAgdFs2NzNdID0gMTQ4OTsKICB0WzY3NF0gPSAxNDkwOwogIHRbNjc1XSA9IDE0OTE7CiAgdFs2NzZdID0gMTQ5MjsKICB0WzY3N10gPSAxNDkzOwogIHRbNjc4XSA9IDE0OTQ7CiAgdFs2NzldID0gMTQ5NTsKICB0WzY4MF0gPSAxNDk2OwogIHRbNjgxXSA9IDE0OTc7CiAgdFs2ODJdID0gMTQ5ODsKICB0WzY4M10gPSAxNDk5OwogIHRbNjg0XSA9IDE1MDA7CiAgdFs2ODVdID0gMTUwMTsKICB0WzY4Nl0gPSAxNTAyOwogIHRbNjg3XSA9IDE1MDM7CiAgdFs2ODhdID0gMTUwNDsKICB0WzY4OV0gPSAxNTA1OwogIHRbNjkwXSA9IDE1MDY7CiAgdFs2OTFdID0gMTUwNzsKICB0WzY5Ml0gPSAxNTA4OwogIHRbNjkzXSA9IDE1MDk7CiAgdFs2OTRdID0gMTUxMDsKICB0WzY5NV0gPSAxNTExOwogIHRbNjk2XSA9IDE1MTI7CiAgdFs2OTddID0gMTUxMzsKICB0WzY5OF0gPSAxNTE0OwogIHRbNzA1XSA9IDE1MjQ7CiAgdFs3MDZdID0gODM2MjsKICB0WzcxMF0gPSA2NDI4ODsKICB0WzcxMV0gPSA2NDI5ODsKICB0Wzc1OV0gPSAxNjE3OwogIHRbNzYxXSA9IDE3NzY7CiAgdFs3NjNdID0gMTc3ODsKICB0Wzc3NV0gPSAxNjUyOwogIHRbNzc3XSA9IDE3NjQ7CiAgdFs3NzhdID0gMTc4MDsKICB0Wzc3OV0gPSAxNzgxOwogIHRbNzgwXSA9IDE3ODI7CiAgdFs3ODJdID0gNzcxOwogIHRbNzgzXSA9IDY0NzI2OwogIHRbNzg2XSA9IDgzNjM7CiAgdFs3ODhdID0gODUzMjsKICB0Wzc5MF0gPSA3Njg7CiAgdFs3OTFdID0gNzY5OwogIHRbNzkyXSA9IDc2ODsKICB0Wzc5NV0gPSA4MDM7CiAgdFs3OTddID0gNjQzMzY7CiAgdFs3OThdID0gNjQzMzc7CiAgdFs3OTldID0gNjQzNDI7CiAgdFs4MDBdID0gNjQzNDM7CiAgdFs4MDFdID0gNjQzNDQ7CiAgdFs4MDJdID0gNjQzNDU7CiAgdFs4MDNdID0gNjQzNjI7CiAgdFs4MDRdID0gNjQzNjM7CiAgdFs4MDVdID0gNjQzNjQ7CiAgdFsyNDI0XSA9IDc4MjE7CiAgdFsyNDI1XSA9IDc4MjI7CiAgdFsyNDI2XSA9IDc4MjM7CiAgdFsyNDI3XSA9IDc4MjQ7CiAgdFsyNDI4XSA9IDc4MjU7CiAgdFsyNDI5XSA9IDc4MjY7CiAgdFsyNDMwXSA9IDc4Mjc7CiAgdFsyNDMzXSA9IDc2ODI7CiAgdFsyNjc4XSA9IDgwNDU7CiAgdFsyNjc5XSA9IDgwNDY7CiAgdFsyODMwXSA9IDE1NTI7CiAgdFsyODM4XSA9IDY4NjsKICB0WzI4NDBdID0gNzUxOwogIHRbMjg0Ml0gPSA3NTM7CiAgdFsyODQzXSA9IDc1NDsKICB0WzI4NDRdID0gNzU1OwogIHRbMjg0Nl0gPSA3NTc7CiAgdFsyODU2XSA9IDc2NzsKICB0WzI4NTddID0gODQ4OwogIHRbMjg1OF0gPSA4NDk7CiAgdFsyODYyXSA9IDg1MzsKICB0WzI4NjNdID0gODU0OwogIHRbMjg2NF0gPSA4NTU7CiAgdFsyODY1XSA9IDg2MTsKICB0WzI4NjZdID0gODYyOwogIHRbMjkwNl0gPSA3NDYwOwogIHRbMjkwOF0gPSA3NDYyOwogIHRbMjkwOV0gPSA3NDYzOwogIHRbMjkxMF0gPSA3NDY0OwogIHRbMjkxMl0gPSA3NDY2OwogIHRbMjkxM10gPSA3NDY3OwogIHRbMjkxNF0gPSA3NDY4OwogIHRbMjkxNl0gPSA3NDcwOwogIHRbMjkxN10gPSA3NDcxOwogIHRbMjkxOF0gPSA3NDcyOwogIHRbMjkyMF0gPSA3NDc0OwogIHRbMjkyMV0gPSA3NDc1OwogIHRbMjkyMl0gPSA3NDc2OwogIHRbMjkyNF0gPSA3NDc4OwogIHRbMjkyNV0gPSA3NDc5OwogIHRbMjkyNl0gPSA3NDgwOwogIHRbMjkyOF0gPSA3NDgyOwogIHRbMjkyOV0gPSA3NDgzOwogIHRbMjkzMF0gPSA3NDg0OwogIHRbMjkzMl0gPSA3NDg2OwogIHRbMjkzM10gPSA3NDg3OwogIHRbMjkzNF0gPSA3NDg4OwogIHRbMjkzNl0gPSA3NDkwOwogIHRbMjkzN10gPSA3NDkxOwogIHRbMjkzOF0gPSA3NDkyOwogIHRbMjk0MF0gPSA3NDk0OwogIHRbMjk0MV0gPSA3NDk1OwogIHRbMjk0Ml0gPSA3NDk2OwogIHRbMjk0NF0gPSA3NDk4OwogIHRbMjk0Nl0gPSA3NTAwOwogIHRbMjk0OF0gPSA3NTAyOwogIHRbMjk1MF0gPSA3NTA0OwogIHRbMjk1MV0gPSA3NTA1OwogIHRbMjk1Ml0gPSA3NTA2OwogIHRbMjk1NF0gPSA3NTA4OwogIHRbMjk1NV0gPSA3NTA5OwogIHRbMjk1Nl0gPSA3NTEwOwogIHRbMjk1OF0gPSA3NTEyOwogIHRbMjk1OV0gPSA3NTEzOwogIHRbMjk2MF0gPSA3NTE0OwogIHRbMjk2Ml0gPSA3NTE2OwogIHRbMjk2M10gPSA3NTE3OwogIHRbMjk2NF0gPSA3NTE4OwogIHRbMjk2Nl0gPSA3NTIwOwogIHRbMjk2N10gPSA3NTIxOwogIHRbMjk2OF0gPSA3NTIyOwogIHRbMjk3MF0gPSA3NTI0OwogIHRbMjk3MV0gPSA3NTI1OwogIHRbMjk3Ml0gPSA3NTI2OwogIHRbMjk3NF0gPSA3NTI4OwogIHRbMjk3NV0gPSA3NTI5OwogIHRbMjk3Nl0gPSA3NTMwOwogIHRbMjk3OF0gPSAxNTM3OwogIHRbMjk3OV0gPSAxNTM4OwogIHRbMjk4MF0gPSAxNTM5OwogIHRbMjk4Ml0gPSAxNTQ5OwogIHRbMjk4M10gPSAxNTUxOwogIHRbMjk4NF0gPSAxNTUyOwogIHRbMjk4Nl0gPSAxNTU0OwogIHRbMjk4N10gPSAxNTU1OwogIHRbMjk4OF0gPSAxNTU2OwogIHRbMjk5MF0gPSAxNjIzOwogIHRbMjk5MV0gPSAxNjI0OwogIHRbMjk5NV0gPSAxNzc1OwogIHRbMjk5OV0gPSAxNzkxOwogIHRbMzAwMl0gPSA2NDI5MDsKICB0WzMwMDNdID0gNjQyOTE7CiAgdFszMDA0XSA9IDY0MjkyOwogIHRbMzAwNl0gPSA2NDI5NDsKICB0WzMwMDddID0gNjQyOTU7CiAgdFszMDA4XSA9IDY0Mjk2OwogIHRbMzAxMV0gPSAxOTAwOwogIHRbMzAxNF0gPSA4MjIzOwogIHRbMzAxNV0gPSA4MjQ0OwogIHRbMzAxN10gPSA3NTMyOwogIHRbMzAxOF0gPSA3NTMzOwogIHRbMzAxOV0gPSA3NTM0OwogIHRbMzA3NV0gPSA3NTkwOwogIHRbMzA3Nl0gPSA3NTkxOwogIHRbMzA3OV0gPSA3NTk0OwogIHRbMzA4MF0gPSA3NTk1OwogIHRbMzA4M10gPSA3NTk4OwogIHRbMzA4NF0gPSA3NTk5OwogIHRbMzA4N10gPSA3NjAyOwogIHRbMzA4OF0gPSA3NjAzOwogIHRbMzA5MV0gPSA3NjA2OwogIHRbMzA5Ml0gPSA3NjA3OwogIHRbMzA5NV0gPSA3NjEwOwogIHRbMzA5Nl0gPSA3NjExOwogIHRbMzA5OV0gPSA3NjE0OwogIHRbMzEwMF0gPSA3NjE1OwogIHRbMzEwM10gPSA3NjE4OwogIHRbMzEwNF0gPSA3NjE5OwogIHRbMzEwN10gPSA4MzM3OwogIHRbMzEwOF0gPSA4MzM4OwogIHRbMzExNl0gPSAxODg0OwogIHRbMzExOV0gPSAxODg1OwogIHRbMzEyMF0gPSAxODg1OwogIHRbMzEyM10gPSAxODg2OwogIHRbMzEyNF0gPSAxODg2OwogIHRbMzEyN10gPSAxODg3OwogIHRbMzEyOF0gPSAxODg3OwogIHRbMzEzMV0gPSAxODg4OwogIHRbMzEzMl0gPSAxODg4OwogIHRbMzEzNV0gPSAxODg5OwogIHRbMzEzNl0gPSAxODg5OwogIHRbMzEzOV0gPSAxODkwOwogIHRbMzE0MF0gPSAxODkwOwogIHRbMzE0M10gPSAxODkxOwogIHRbMzE0NF0gPSAxODkxOwogIHRbMzE0N10gPSAxODkyOwogIHRbMzE0OF0gPSAxODkyOwogIHRbMzE1M10gPSA1ODA7CiAgdFszMTU0XSA9IDU4MTsKICB0WzMxNTddID0gNTg0OwogIHRbMzE1OF0gPSA1ODU7CiAgdFszMTYxXSA9IDU4ODsKICB0WzMxNjJdID0gNTg5OwogIHRbMzE2NV0gPSA4OTE7CiAgdFszMTY2XSA9IDg5MjsKICB0WzMxNjldID0gMTI3NDsKICB0WzMxNzBdID0gMTI3NTsKICB0WzMxNzNdID0gMTI3ODsKICB0WzMxNzRdID0gMTI3OTsKICB0WzMxODFdID0gNzYyMjsKICB0WzMxODJdID0gNzYyMzsKICB0WzMyODJdID0gMTE3OTk7CiAgdFszMzE2XSA9IDU3ODsKICB0WzMzNzldID0gNDI3ODU7CiAgdFszMzkzXSA9IDExNTk7CiAgdFszNDE2XSA9IDgzNzc7Cn0pOwpjb25zdCBnZXRTdXBwbGVtZW50YWxHbHlwaE1hcEZvckFyaWFsQmxhY2sgPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICB0WzIyN10gPSAzMjI7CiAgdFsyNjRdID0gMjYxOwogIHRbMjkxXSA9IDM0NjsKfSk7CmNvbnN0IGdldFN1cHBsZW1lbnRhbEdseXBoTWFwRm9yQ2FsaWJyaSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHRbMV0gPSAzMjsKICB0WzRdID0gNjU7CiAgdFs1XSA9IDE5MjsKICB0WzZdID0gMTkzOwogIHRbOV0gPSAxOTY7CiAgdFsxN10gPSA2NjsKICB0WzE4XSA9IDY3OwogIHRbMjFdID0gMjY4OwogIHRbMjRdID0gNjg7CiAgdFsyOF0gPSA2OTsKICB0WzI5XSA9IDIwMDsKICB0WzMwXSA9IDIwMTsKICB0WzMyXSA9IDI4MjsKICB0WzM4XSA9IDcwOwogIHRbMzldID0gNzE7CiAgdFs0NF0gPSA3MjsKICB0WzQ3XSA9IDczOwogIHRbNDhdID0gMjA0OwogIHRbNDldID0gMjA1OwogIHRbNThdID0gNzQ7CiAgdFs2MF0gPSA3NTsKICB0WzYyXSA9IDc2OwogIHRbNjhdID0gNzc7CiAgdFs2OV0gPSA3ODsKICB0Wzc1XSA9IDc5OwogIHRbNzZdID0gMjEwOwogIHRbODBdID0gMjE0OwogIHRbODddID0gODA7CiAgdFs4OV0gPSA4MTsKICB0WzkwXSA9IDgyOwogIHRbOTJdID0gMzQ0OwogIHRbOTRdID0gODM7CiAgdFs5N10gPSAzNTI7CiAgdFsxMDBdID0gODQ7CiAgdFsxMDRdID0gODU7CiAgdFsxMDldID0gMjIwOwogIHRbMTE1XSA9IDg2OwogIHRbMTE2XSA9IDg3OwogIHRbMTIxXSA9IDg4OwogIHRbMTIyXSA9IDg5OwogIHRbMTI0XSA9IDIyMTsKICB0WzEyN10gPSA5MDsKICB0WzEyOV0gPSAzODE7CiAgdFsyNThdID0gOTc7CiAgdFsyNTldID0gMjI0OwogIHRbMjYwXSA9IDIyNTsKICB0WzI2M10gPSAyMjg7CiAgdFsyNjhdID0gMjYxOwogIHRbMjcxXSA9IDk4OwogIHRbMjcyXSA9IDk5OwogIHRbMjczXSA9IDI2MzsKICB0WzI3NV0gPSAyNjk7CiAgdFsyODJdID0gMTAwOwogIHRbMjg2XSA9IDEwMTsKICB0WzI4N10gPSAyMzI7CiAgdFsyODhdID0gMjMzOwogIHRbMjkwXSA9IDI4MzsKICB0WzI5NV0gPSAyODE7CiAgdFsyOTZdID0gMTAyOwogIHRbMzM2XSA9IDEwMzsKICB0WzM0Nl0gPSAxMDQ7CiAgdFszNDldID0gMTA1OwogIHRbMzUwXSA9IDIzNjsKICB0WzM1MV0gPSAyMzc7CiAgdFszNjFdID0gMTA2OwogIHRbMzY0XSA9IDEwNzsKICB0WzM2N10gPSAxMDg7CiAgdFszNzFdID0gMzIyOwogIHRbMzczXSA9IDEwOTsKICB0WzM3NF0gPSAxMTA7CiAgdFszODFdID0gMTExOwogIHRbMzgyXSA9IDI0MjsKICB0WzM4M10gPSAyNDM7CiAgdFszODZdID0gMjQ2OwogIHRbMzkzXSA9IDExMjsKICB0WzM5NV0gPSAxMTM7CiAgdFszOTZdID0gMTE0OwogIHRbMzk4XSA9IDM0NTsKICB0WzQwMF0gPSAxMTU7CiAgdFs0MDFdID0gMzQ3OwogIHRbNDAzXSA9IDM1MzsKICB0WzQxMF0gPSAxMTY7CiAgdFs0MzddID0gMTE3OwogIHRbNDQyXSA9IDI1MjsKICB0WzQ0OF0gPSAxMTg7CiAgdFs0NDldID0gMTE5OwogIHRbNDU0XSA9IDEyMDsKICB0WzQ1NV0gPSAxMjE7CiAgdFs0NTddID0gMjUzOwogIHRbNDYwXSA9IDEyMjsKICB0WzQ2Ml0gPSAzODI7CiAgdFs0NjNdID0gMzgwOwogIHRbODUzXSA9IDQ0OwogIHRbODU1XSA9IDU4OwogIHRbODU2XSA9IDQ2OwogIHRbODc2XSA9IDQ3OwogIHRbODc4XSA9IDQ1OwogIHRbODgyXSA9IDQ1OwogIHRbODk0XSA9IDQwOwogIHRbODk1XSA9IDQxOwogIHRbODk2XSA9IDkxOwogIHRbODk3XSA9IDkzOwogIHRbOTIzXSA9IDY0OwogIHRbOTQwXSA9IDE2MzsKICB0WzEwMDRdID0gNDg7CiAgdFsxMDA1XSA9IDQ5OwogIHRbMTAwNl0gPSA1MDsKICB0WzEwMDddID0gNTE7CiAgdFsxMDA4XSA9IDUyOwogIHRbMTAwOV0gPSA1MzsKICB0WzEwMTBdID0gNTQ7CiAgdFsxMDExXSA9IDU1OwogIHRbMTAxMl0gPSA1NjsKICB0WzEwMTNdID0gNTc7CiAgdFsxMDgxXSA9IDM3OwogIHRbMTA4NV0gPSA0MzsKICB0WzEwODZdID0gNDU7Cn0pOwpmdW5jdGlvbiBnZXRTdGFuZGFyZEZvbnROYW1lKG5hbWUpIHsKICBjb25zdCBmb250TmFtZSA9IG5vcm1hbGl6ZUZvbnROYW1lKG5hbWUpOwogIGNvbnN0IHN0ZEZvbnRNYXAgPSBnZXRTdGRGb250TWFwKCk7CiAgcmV0dXJuIHN0ZEZvbnRNYXBbZm9udE5hbWVdOwp9CmZ1bmN0aW9uIGlzS25vd25Gb250TmFtZShuYW1lKSB7CiAgY29uc3QgZm9udE5hbWUgPSBub3JtYWxpemVGb250TmFtZShuYW1lKTsKICByZXR1cm4gISEoZ2V0U3RkRm9udE1hcCgpW2ZvbnROYW1lXSB8fCBnZXROb25TdGRGb250TWFwKClbZm9udE5hbWVdIHx8IGdldFNlcmlmRm9udHMoKVtmb250TmFtZV0gfHwgZ2V0U3ltYm9sc0ZvbnRzKClbZm9udE5hbWVdKTsKfQoKOy8vIC4vc3JjL2NvcmUvdG9fdW5pY29kZV9tYXAuanMKCmNsYXNzIFRvVW5pY29kZU1hcCB7CiAgY29uc3RydWN0b3IoY21hcCA9IFtdKSB7CiAgICB0aGlzLl9tYXAgPSBjbWFwOwogIH0KICBnZXQgbGVuZ3RoKCkgewogICAgcmV0dXJuIHRoaXMuX21hcC5sZW5ndGg7CiAgfQogIGZvckVhY2goY2FsbGJhY2spIHsKICAgIGZvciAoY29uc3QgY2hhckNvZGUgaW4gdGhpcy5fbWFwKSB7CiAgICAgIGNhbGxiYWNrKGNoYXJDb2RlLCB0aGlzLl9tYXBbY2hhckNvZGVdLmNvZGVQb2ludEF0KDApKTsKICAgIH0KICB9CiAgaGFzKGkpIHsKICAgIHJldHVybiB0aGlzLl9tYXBbaV0gIT09IHVuZGVmaW5lZDsKICB9CiAgZ2V0KGkpIHsKICAgIHJldHVybiB0aGlzLl9tYXBbaV07CiAgfQogIGNoYXJDb2RlT2YodmFsdWUpIHsKICAgIGNvbnN0IG1hcCA9IHRoaXMuX21hcDsKICAgIGlmIChtYXAubGVuZ3RoIDw9IDB4MTAwMDApIHsKICAgICAgcmV0dXJuIG1hcC5pbmRleE9mKHZhbHVlKTsKICAgIH0KICAgIGZvciAoY29uc3QgY2hhckNvZGUgaW4gbWFwKSB7CiAgICAgIGlmIChtYXBbY2hhckNvZGVdID09PSB2YWx1ZSkgewogICAgICAgIHJldHVybiBjaGFyQ29kZSB8IDA7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiAtMTsKICB9CiAgYW1lbmQobWFwKSB7CiAgICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIG1hcCkgewogICAgICB0aGlzLl9tYXBbY2hhckNvZGVdID0gbWFwW2NoYXJDb2RlXTsKICAgIH0KICB9Cn0KY2xhc3MgSWRlbnRpdHlUb1VuaWNvZGVNYXAgewogIGNvbnN0cnVjdG9yKGZpcnN0Q2hhciwgbGFzdENoYXIpIHsKICAgIHRoaXMuZmlyc3RDaGFyID0gZmlyc3RDaGFyOwogICAgdGhpcy5sYXN0Q2hhciA9IGxhc3RDaGFyOwogIH0KICBnZXQgbGVuZ3RoKCkgewogICAgcmV0dXJuIHRoaXMubGFzdENoYXIgKyAxIC0gdGhpcy5maXJzdENoYXI7CiAgfQogIGZvckVhY2goY2FsbGJhY2spIHsKICAgIGZvciAobGV0IGkgPSB0aGlzLmZpcnN0Q2hhciwgaWkgPSB0aGlzLmxhc3RDaGFyOyBpIDw9IGlpOyBpKyspIHsKICAgICAgY2FsbGJhY2soaSwgaSk7CiAgICB9CiAgfQogIGhhcyhpKSB7CiAgICByZXR1cm4gdGhpcy5maXJzdENoYXIgPD0gaSAmJiBpIDw9IHRoaXMubGFzdENoYXI7CiAgfQogIGdldChpKSB7CiAgICBpZiAodGhpcy5maXJzdENoYXIgPD0gaSAmJiBpIDw9IHRoaXMubGFzdENoYXIpIHsKICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoaSk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBjaGFyQ29kZU9mKHYpIHsKICAgIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHYpICYmIHYgPj0gdGhpcy5maXJzdENoYXIgJiYgdiA8PSB0aGlzLmxhc3RDaGFyID8gdiA6IC0xOwogIH0KICBhbWVuZChtYXApIHsKICAgIHVucmVhY2hhYmxlKCJTaG91bGQgbm90IGNhbGwgYW1lbmQoKSIpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvY2ZmX2ZvbnQuanMKCgoKY2xhc3MgQ0ZGRm9udCB7CiAgY29uc3RydWN0b3IoZmlsZSwgcHJvcGVydGllcykgewogICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllczsKICAgIGNvbnN0IHBhcnNlciA9IG5ldyBDRkZQYXJzZXIoZmlsZSwgcHJvcGVydGllcywgU0VBQ19BTkFMWVNJU19FTkFCTEVEKTsKICAgIHRoaXMuY2ZmID0gcGFyc2VyLnBhcnNlKCk7CiAgICB0aGlzLmNmZi5kdXBsaWNhdGVGaXJzdEdseXBoKCk7CiAgICBjb25zdCBjb21waWxlciA9IG5ldyBDRkZDb21waWxlcih0aGlzLmNmZik7CiAgICB0aGlzLnNlYWNzID0gdGhpcy5jZmYuc2VhY3M7CiAgICB0cnkgewogICAgICB0aGlzLmRhdGEgPSBjb21waWxlci5jb21waWxlKCk7CiAgICB9IGNhdGNoIHsKICAgICAgd2FybigiRmFpbGVkIHRvIGNvbXBpbGUgZm9udCAiICsgcHJvcGVydGllcy5sb2FkZWROYW1lKTsKICAgICAgdGhpcy5kYXRhID0gZmlsZTsKICAgIH0KICAgIHRoaXMuX2NyZWF0ZUJ1aWx0SW5FbmNvZGluZygpOwogIH0KICBnZXQgbnVtR2x5cGhzKCkgewogICAgcmV0dXJuIHRoaXMuY2ZmLmNoYXJTdHJpbmdzLmNvdW50OwogIH0KICBnZXRDaGFyc2V0KCkgewogICAgcmV0dXJuIHRoaXMuY2ZmLmNoYXJzZXQuY2hhcnNldDsKICB9CiAgZ2V0R2x5cGhNYXBwaW5nKCkgewogICAgY29uc3QgY2ZmID0gdGhpcy5jZmY7CiAgICBjb25zdCBwcm9wZXJ0aWVzID0gdGhpcy5wcm9wZXJ0aWVzOwogICAgY29uc3QgewogICAgICBjaWRUb0dpZE1hcCwKICAgICAgY01hcAogICAgfSA9IHByb3BlcnRpZXM7CiAgICBjb25zdCBjaGFyc2V0cyA9IGNmZi5jaGFyc2V0LmNoYXJzZXQ7CiAgICBsZXQgY2hhckNvZGVUb0dseXBoSWQ7CiAgICBsZXQgZ2x5cGhJZDsKICAgIGlmIChwcm9wZXJ0aWVzLmNvbXBvc2l0ZSkgewogICAgICBsZXQgaW52Q2lkVG9HaWRNYXA7CiAgICAgIGlmIChjaWRUb0dpZE1hcD8ubGVuZ3RoID4gMCkgewogICAgICAgIGludkNpZFRvR2lkTWFwID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBjaWRUb0dpZE1hcC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICBjb25zdCBnaWQgPSBjaWRUb0dpZE1hcFtpXTsKICAgICAgICAgIGlmIChnaWQgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBpbnZDaWRUb0dpZE1hcFtnaWRdID0gaTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgY2hhckNvZGVUb0dseXBoSWQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBsZXQgY2hhckNvZGU7CiAgICAgIGlmIChjZmYuaXNDSURGb250KSB7CiAgICAgICAgZm9yIChnbHlwaElkID0gMDsgZ2x5cGhJZCA8IGNoYXJzZXRzLmxlbmd0aDsgZ2x5cGhJZCsrKSB7CiAgICAgICAgICBjb25zdCBjaWQgPSBjaGFyc2V0c1tnbHlwaElkXTsKICAgICAgICAgIGNoYXJDb2RlID0gY01hcC5jaGFyQ29kZU9mKGNpZCk7CiAgICAgICAgICBpZiAoaW52Q2lkVG9HaWRNYXA/LltjaGFyQ29kZV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBjaGFyQ29kZSA9IGludkNpZFRvR2lkTWFwW2NoYXJDb2RlXTsKICAgICAgICAgIH0KICAgICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGZvciAoZ2x5cGhJZCA9IDA7IGdseXBoSWQgPCBjZmYuY2hhclN0cmluZ3MuY291bnQ7IGdseXBoSWQrKykgewogICAgICAgICAgY2hhckNvZGUgPSBjTWFwLmNoYXJDb2RlT2YoZ2x5cGhJZCk7CiAgICAgICAgICBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBnbHlwaElkOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gY2hhckNvZGVUb0dseXBoSWQ7CiAgICB9CiAgICBsZXQgZW5jb2RpbmcgPSBjZmYuZW5jb2RpbmcgPyBjZmYuZW5jb2RpbmcuZW5jb2RpbmcgOiBudWxsOwogICAgaWYgKHByb3BlcnRpZXMuaXNJbnRlcm5hbEZvbnQpIHsKICAgICAgZW5jb2RpbmcgPSBwcm9wZXJ0aWVzLmRlZmF1bHRFbmNvZGluZzsKICAgIH0KICAgIGNoYXJDb2RlVG9HbHlwaElkID0gdHlwZTFGb250R2x5cGhNYXBwaW5nKHByb3BlcnRpZXMsIGVuY29kaW5nLCBjaGFyc2V0cyk7CiAgICByZXR1cm4gY2hhckNvZGVUb0dseXBoSWQ7CiAgfQogIGhhc0dseXBoSWQoaWQpIHsKICAgIHJldHVybiB0aGlzLmNmZi5oYXNHbHlwaElkKGlkKTsKICB9CiAgX2NyZWF0ZUJ1aWx0SW5FbmNvZGluZygpIHsKICAgIGNvbnN0IHsKICAgICAgY2hhcnNldCwKICAgICAgZW5jb2RpbmcKICAgIH0gPSB0aGlzLmNmZjsKICAgIGlmICghY2hhcnNldCB8fCAhZW5jb2RpbmcpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgY2hhcnNldHMgPSBjaGFyc2V0LmNoYXJzZXQsCiAgICAgIGVuY29kaW5ncyA9IGVuY29kaW5nLmVuY29kaW5nOwogICAgY29uc3QgbWFwID0gW107CiAgICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIGVuY29kaW5ncykgewogICAgICBjb25zdCBnbHlwaElkID0gZW5jb2RpbmdzW2NoYXJDb2RlXTsKICAgICAgaWYgKGdseXBoSWQgPj0gMCkgewogICAgICAgIGNvbnN0IGdseXBoTmFtZSA9IGNoYXJzZXRzW2dseXBoSWRdOwogICAgICAgIGlmIChnbHlwaE5hbWUpIHsKICAgICAgICAgIG1hcFtjaGFyQ29kZV0gPSBnbHlwaE5hbWU7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAobWFwLmxlbmd0aCA+IDApIHsKICAgICAgdGhpcy5wcm9wZXJ0aWVzLmJ1aWx0SW5FbmNvZGluZyA9IG1hcDsKICAgIH0KICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2ZvbnRfcmVuZGVyZXIuanMKCgoKCgoKZnVuY3Rpb24gZ2V0RmxvYXQyMTQoZGF0YSwgb2Zmc2V0KSB7CiAgcmV0dXJuIHJlYWRJbnQxNihkYXRhLCBvZmZzZXQpIC8gMTYzODQ7Cn0KZnVuY3Rpb24gZ2V0U3Vicm91dGluZUJpYXMoc3VicnMpIHsKICBjb25zdCBudW1TdWJycyA9IHN1YnJzLmxlbmd0aDsKICBsZXQgYmlhcyA9IDMyNzY4OwogIGlmIChudW1TdWJycyA8IDEyNDApIHsKICAgIGJpYXMgPSAxMDc7CiAgfSBlbHNlIGlmIChudW1TdWJycyA8IDMzOTAwKSB7CiAgICBiaWFzID0gMTEzMTsKICB9CiAgcmV0dXJuIGJpYXM7Cn0KZnVuY3Rpb24gcGFyc2VDbWFwKGRhdGEsIHN0YXJ0LCBlbmQpIHsKICBjb25zdCBvZmZzZXQgPSByZWFkVWludDE2KGRhdGEsIHN0YXJ0ICsgMikgPT09IDEgPyByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgOCkgOiByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgMTYpOwogIGNvbnN0IGZvcm1hdCA9IHJlYWRVaW50MTYoZGF0YSwgc3RhcnQgKyBvZmZzZXQpOwogIGxldCByYW5nZXMsIHAsIGk7CiAgaWYgKGZvcm1hdCA9PT0gNCkgewogICAgcmVhZFVpbnQxNihkYXRhLCBzdGFydCArIG9mZnNldCArIDIpOwogICAgY29uc3Qgc2VnQ291bnQgPSByZWFkVWludDE2KGRhdGEsIHN0YXJ0ICsgb2Zmc2V0ICsgNikgPj4gMTsKICAgIHAgPSBzdGFydCArIG9mZnNldCArIDE0OwogICAgcmFuZ2VzID0gW107CiAgICBmb3IgKGkgPSAwOyBpIDwgc2VnQ291bnQ7IGkrKywgcCArPSAyKSB7CiAgICAgIHJhbmdlc1tpXSA9IHsKICAgICAgICBlbmQ6IHJlYWRVaW50MTYoZGF0YSwgcCkKICAgICAgfTsKICAgIH0KICAgIHAgKz0gMjsKICAgIGZvciAoaSA9IDA7IGkgPCBzZWdDb3VudDsgaSsrLCBwICs9IDIpIHsKICAgICAgcmFuZ2VzW2ldLnN0YXJ0ID0gcmVhZFVpbnQxNihkYXRhLCBwKTsKICAgIH0KICAgIGZvciAoaSA9IDA7IGkgPCBzZWdDb3VudDsgaSsrLCBwICs9IDIpIHsKICAgICAgcmFuZ2VzW2ldLmlkRGVsdGEgPSByZWFkVWludDE2KGRhdGEsIHApOwogICAgfQogICAgZm9yIChpID0gMDsgaSA8IHNlZ0NvdW50OyBpKyssIHAgKz0gMikgewogICAgICBsZXQgaWRPZmZzZXQgPSByZWFkVWludDE2KGRhdGEsIHApOwogICAgICBpZiAoaWRPZmZzZXQgPT09IDApIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICByYW5nZXNbaV0uaWRzID0gW107CiAgICAgIGZvciAobGV0IGogPSAwLCBqaiA9IHJhbmdlc1tpXS5lbmQgLSByYW5nZXNbaV0uc3RhcnQgKyAxOyBqIDwgamo7IGorKykgewogICAgICAgIHJhbmdlc1tpXS5pZHNbal0gPSByZWFkVWludDE2KGRhdGEsIHAgKyBpZE9mZnNldCk7CiAgICAgICAgaWRPZmZzZXQgKz0gMjsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHJhbmdlczsKICB9IGVsc2UgaWYgKGZvcm1hdCA9PT0gMTIpIHsKICAgIGNvbnN0IGdyb3VwcyA9IHJlYWRVaW50MzIoZGF0YSwgc3RhcnQgKyBvZmZzZXQgKyAxMik7CiAgICBwID0gc3RhcnQgKyBvZmZzZXQgKyAxNjsKICAgIHJhbmdlcyA9IFtdOwogICAgZm9yIChpID0gMDsgaSA8IGdyb3VwczsgaSsrKSB7CiAgICAgIHN0YXJ0ID0gcmVhZFVpbnQzMihkYXRhLCBwKTsKICAgICAgcmFuZ2VzLnB1c2goewogICAgICAgIHN0YXJ0LAogICAgICAgIGVuZDogcmVhZFVpbnQzMihkYXRhLCBwICsgNCksCiAgICAgICAgaWREZWx0YTogcmVhZFVpbnQzMihkYXRhLCBwICsgOCkgLSBzdGFydAogICAgICB9KTsKICAgICAgcCArPSAxMjsKICAgIH0KICAgIHJldHVybiByYW5nZXM7CiAgfQogIHRocm93IG5ldyBGb3JtYXRFcnJvcihgdW5zdXBwb3J0ZWQgY21hcDogJHtmb3JtYXR9YCk7Cn0KZnVuY3Rpb24gcGFyc2VDZmYoZGF0YSwgc3RhcnQsIGVuZCwgc2VhY0FuYWx5c2lzRW5hYmxlZCkgewogIGNvbnN0IHByb3BlcnRpZXMgPSB7fTsKICBjb25zdCBwYXJzZXIgPSBuZXcgQ0ZGUGFyc2VyKG5ldyBTdHJlYW0oZGF0YSwgc3RhcnQsIGVuZCAtIHN0YXJ0KSwgcHJvcGVydGllcywgc2VhY0FuYWx5c2lzRW5hYmxlZCk7CiAgY29uc3QgY2ZmID0gcGFyc2VyLnBhcnNlKCk7CiAgcmV0dXJuIHsKICAgIGdseXBoczogY2ZmLmNoYXJTdHJpbmdzLm9iamVjdHMsCiAgICBzdWJyczogY2ZmLnRvcERpY3QucHJpdmF0ZURpY3Q/LnN1YnJzSW5kZXg/Lm9iamVjdHMsCiAgICBnc3VicnM6IGNmZi5nbG9iYWxTdWJySW5kZXg/Lm9iamVjdHMsCiAgICBpc0NGRkNJREZvbnQ6IGNmZi5pc0NJREZvbnQsCiAgICBmZFNlbGVjdDogY2ZmLmZkU2VsZWN0LAogICAgZmRBcnJheTogY2ZmLmZkQXJyYXkKICB9Owp9CmZ1bmN0aW9uIHBhcnNlR2x5ZlRhYmxlKGdseWYsIGxvY2EsIGlzR2x5cGhMb2NhdGlvbnNMb25nKSB7CiAgbGV0IGl0ZW1TaXplLCBpdGVtRGVjb2RlOwogIGlmIChpc0dseXBoTG9jYXRpb25zTG9uZykgewogICAgaXRlbVNpemUgPSA0OwogICAgaXRlbURlY29kZSA9IHJlYWRVaW50MzI7CiAgfSBlbHNlIHsKICAgIGl0ZW1TaXplID0gMjsKICAgIGl0ZW1EZWNvZGUgPSAoZGF0YSwgb2Zmc2V0KSA9PiAyICogcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpOwogIH0KICBjb25zdCBnbHlwaHMgPSBbXTsKICBsZXQgc3RhcnRPZmZzZXQgPSBpdGVtRGVjb2RlKGxvY2EsIDApOwogIGZvciAobGV0IGogPSBpdGVtU2l6ZTsgaiA8IGxvY2EubGVuZ3RoOyBqICs9IGl0ZW1TaXplKSB7CiAgICBjb25zdCBlbmRPZmZzZXQgPSBpdGVtRGVjb2RlKGxvY2EsIGopOwogICAgZ2x5cGhzLnB1c2goZ2x5Zi5zdWJhcnJheShzdGFydE9mZnNldCwgZW5kT2Zmc2V0KSk7CiAgICBzdGFydE9mZnNldCA9IGVuZE9mZnNldDsKICB9CiAgcmV0dXJuIGdseXBoczsKfQpmdW5jdGlvbiBsb29rdXBDbWFwKHJhbmdlcywgdW5pY29kZSkgewogIGNvbnN0IGNvZGUgPSB1bmljb2RlLmNvZGVQb2ludEF0KDApOwogIGxldCBnaWQgPSAwLAogICAgbCA9IDAsCiAgICByID0gcmFuZ2VzLmxlbmd0aCAtIDE7CiAgd2hpbGUgKGwgPCByKSB7CiAgICBjb25zdCBjID0gbCArIHIgKyAxID4+IDE7CiAgICBpZiAoY29kZSA8IHJhbmdlc1tjXS5zdGFydCkgewogICAgICByID0gYyAtIDE7CiAgICB9IGVsc2UgewogICAgICBsID0gYzsKICAgIH0KICB9CiAgaWYgKHJhbmdlc1tsXS5zdGFydCA8PSBjb2RlICYmIGNvZGUgPD0gcmFuZ2VzW2xdLmVuZCkgewogICAgZ2lkID0gcmFuZ2VzW2xdLmlkRGVsdGEgKyAocmFuZ2VzW2xdLmlkcyA/IHJhbmdlc1tsXS5pZHNbY29kZSAtIHJhbmdlc1tsXS5zdGFydF0gOiBjb2RlKSAmIDB4ZmZmZjsKICB9CiAgcmV0dXJuIHsKICAgIGNoYXJDb2RlOiBjb2RlLAogICAgZ2x5cGhJZDogZ2lkCiAgfTsKfQpmdW5jdGlvbiBjb21waWxlR2x5Zihjb2RlLCBjbWRzLCBmb250KSB7CiAgZnVuY3Rpb24gbW92ZVRvKHgsIHkpIHsKICAgIGlmIChmaXJzdFBvaW50KSB7CiAgICAgIGNtZHMuYWRkKERyYXdPUFMubGluZVRvLCBmaXJzdFBvaW50KTsKICAgIH0KICAgIGZpcnN0UG9pbnQgPSBbeCwgeV07CiAgICBjbWRzLmFkZChEcmF3T1BTLm1vdmVUbywgW3gsIHldKTsKICB9CiAgZnVuY3Rpb24gbGluZVRvKHgsIHkpIHsKICAgIGNtZHMuYWRkKERyYXdPUFMubGluZVRvLCBbeCwgeV0pOwogIH0KICBmdW5jdGlvbiBxdWFkcmF0aWNDdXJ2ZVRvKHhhLCB5YSwgeCwgeSkgewogICAgY21kcy5hZGQoRHJhd09QUy5xdWFkcmF0aWNDdXJ2ZVRvLCBbeGEsIHlhLCB4LCB5XSk7CiAgfQogIGxldCBpID0gMDsKICBjb25zdCBudW1iZXJPZkNvbnRvdXJzID0gcmVhZEludDE2KGNvZGUsIGkpOwogIGxldCBmbGFnczsKICBsZXQgZmlyc3RQb2ludCA9IG51bGw7CiAgbGV0IHggPSAwLAogICAgeSA9IDA7CiAgaSArPSAxMDsKICBpZiAobnVtYmVyT2ZDb250b3VycyA8IDApIHsKICAgIGRvIHsKICAgICAgZmxhZ3MgPSByZWFkVWludDE2KGNvZGUsIGkpOwogICAgICBjb25zdCBnbHlwaEluZGV4ID0gcmVhZFVpbnQxNihjb2RlLCBpICsgMik7CiAgICAgIGkgKz0gNDsKICAgICAgbGV0IGFyZzEsIGFyZzI7CiAgICAgIGlmIChmbGFncyAmIDB4MDEpIHsKICAgICAgICBpZiAoZmxhZ3MgJiAweDAyKSB7CiAgICAgICAgICBhcmcxID0gcmVhZEludDE2KGNvZGUsIGkpOwogICAgICAgICAgYXJnMiA9IHJlYWRJbnQxNihjb2RlLCBpICsgMik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGFyZzEgPSByZWFkVWludDE2KGNvZGUsIGkpOwogICAgICAgICAgYXJnMiA9IHJlYWRVaW50MTYoY29kZSwgaSArIDIpOwogICAgICAgIH0KICAgICAgICBpICs9IDQ7CiAgICAgIH0gZWxzZSBpZiAoZmxhZ3MgJiAweDAyKSB7CiAgICAgICAgYXJnMSA9IHJlYWRJbnQ4KGNvZGUsIGkrKyk7CiAgICAgICAgYXJnMiA9IHJlYWRJbnQ4KGNvZGUsIGkrKyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYXJnMSA9IGNvZGVbaSsrXTsKICAgICAgICBhcmcyID0gY29kZVtpKytdOwogICAgICB9CiAgICAgIGlmIChmbGFncyAmIDB4MDIpIHsKICAgICAgICB4ID0gYXJnMTsKICAgICAgICB5ID0gYXJnMjsKICAgICAgfSBlbHNlIHsKICAgICAgICB4ID0gMDsKICAgICAgICB5ID0gMDsKICAgICAgfQogICAgICBsZXQgc2NhbGVYID0gMSwKICAgICAgICBzY2FsZVkgPSAxLAogICAgICAgIHNjYWxlMDEgPSAwLAogICAgICAgIHNjYWxlMTAgPSAwOwogICAgICBpZiAoZmxhZ3MgJiAweDA4KSB7CiAgICAgICAgc2NhbGVYID0gc2NhbGVZID0gZ2V0RmxvYXQyMTQoY29kZSwgaSk7CiAgICAgICAgaSArPSAyOwogICAgICB9IGVsc2UgaWYgKGZsYWdzICYgMHg0MCkgewogICAgICAgIHNjYWxlWCA9IGdldEZsb2F0MjE0KGNvZGUsIGkpOwogICAgICAgIHNjYWxlWSA9IGdldEZsb2F0MjE0KGNvZGUsIGkgKyAyKTsKICAgICAgICBpICs9IDQ7CiAgICAgIH0gZWxzZSBpZiAoZmxhZ3MgJiAweDgwKSB7CiAgICAgICAgc2NhbGVYID0gZ2V0RmxvYXQyMTQoY29kZSwgaSk7CiAgICAgICAgc2NhbGUwMSA9IGdldEZsb2F0MjE0KGNvZGUsIGkgKyAyKTsKICAgICAgICBzY2FsZTEwID0gZ2V0RmxvYXQyMTQoY29kZSwgaSArIDQpOwogICAgICAgIHNjYWxlWSA9IGdldEZsb2F0MjE0KGNvZGUsIGkgKyA2KTsKICAgICAgICBpICs9IDg7CiAgICAgIH0KICAgICAgY29uc3Qgc3ViZ2x5cGggPSBmb250LmdseXBoc1tnbHlwaEluZGV4XTsKICAgICAgaWYgKHN1YmdseXBoKSB7CiAgICAgICAgY21kcy5zYXZlKCk7CiAgICAgICAgY21kcy50cmFuc2Zvcm0oW3NjYWxlWCwgc2NhbGUwMSwgc2NhbGUxMCwgc2NhbGVZLCB4LCB5XSk7CiAgICAgICAgaWYgKCEoZmxhZ3MgJiAweDAyKSkge30KICAgICAgICBjb21waWxlR2x5ZihzdWJnbHlwaCwgY21kcywgZm9udCk7CiAgICAgICAgY21kcy5yZXN0b3JlKCk7CiAgICAgIH0KICAgIH0gd2hpbGUgKGZsYWdzICYgMHgyMCk7CiAgfSBlbHNlIHsKICAgIGNvbnN0IGVuZFB0c09mQ29udG91cnMgPSBbXTsKICAgIGxldCBqLCBqajsKICAgIGZvciAoaiA9IDA7IGogPCBudW1iZXJPZkNvbnRvdXJzOyBqKyspIHsKICAgICAgZW5kUHRzT2ZDb250b3Vycy5wdXNoKHJlYWRVaW50MTYoY29kZSwgaSkpOwogICAgICBpICs9IDI7CiAgICB9CiAgICBjb25zdCBpbnN0cnVjdGlvbkxlbmd0aCA9IHJlYWRVaW50MTYoY29kZSwgaSk7CiAgICBpICs9IDIgKyBpbnN0cnVjdGlvbkxlbmd0aDsKICAgIGNvbnN0IG51bWJlck9mUG9pbnRzID0gZW5kUHRzT2ZDb250b3Vycy5hdCgtMSkgKyAxOwogICAgY29uc3QgcG9pbnRzID0gW107CiAgICB3aGlsZSAocG9pbnRzLmxlbmd0aCA8IG51bWJlck9mUG9pbnRzKSB7CiAgICAgIGZsYWdzID0gY29kZVtpKytdOwogICAgICBsZXQgcmVwZWF0ID0gMTsKICAgICAgaWYgKGZsYWdzICYgMHgwOCkgewogICAgICAgIHJlcGVhdCArPSBjb2RlW2krK107CiAgICAgIH0KICAgICAgd2hpbGUgKHJlcGVhdC0tID4gMCkgewogICAgICAgIHBvaW50cy5wdXNoKHsKICAgICAgICAgIGZsYWdzCiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIGZvciAoaiA9IDA7IGogPCBudW1iZXJPZlBvaW50czsgaisrKSB7CiAgICAgIHN3aXRjaCAocG9pbnRzW2pdLmZsYWdzICYgMHgxMikgewogICAgICAgIGNhc2UgMHgwMDoKICAgICAgICAgIHggKz0gcmVhZEludDE2KGNvZGUsIGkpOwogICAgICAgICAgaSArPSAyOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDAyOgogICAgICAgICAgeCAtPSBjb2RlW2krK107CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4MTI6CiAgICAgICAgICB4ICs9IGNvZGVbaSsrXTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHBvaW50c1tqXS54ID0geDsKICAgIH0KICAgIGZvciAoaiA9IDA7IGogPCBudW1iZXJPZlBvaW50czsgaisrKSB7CiAgICAgIHN3aXRjaCAocG9pbnRzW2pdLmZsYWdzICYgMHgyNCkgewogICAgICAgIGNhc2UgMHgwMDoKICAgICAgICAgIHkgKz0gcmVhZEludDE2KGNvZGUsIGkpOwogICAgICAgICAgaSArPSAyOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDA0OgogICAgICAgICAgeSAtPSBjb2RlW2krK107CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4MjQ6CiAgICAgICAgICB5ICs9IGNvZGVbaSsrXTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHBvaW50c1tqXS55ID0geTsKICAgIH0KICAgIGxldCBzdGFydFBvaW50ID0gMDsKICAgIGZvciAoaSA9IDA7IGkgPCBudW1iZXJPZkNvbnRvdXJzOyBpKyspIHsKICAgICAgY29uc3QgZW5kUG9pbnQgPSBlbmRQdHNPZkNvbnRvdXJzW2ldOwogICAgICBjb25zdCBjb250b3VyID0gcG9pbnRzLnNsaWNlKHN0YXJ0UG9pbnQsIGVuZFBvaW50ICsgMSk7CiAgICAgIGlmIChjb250b3VyWzBdLmZsYWdzICYgMSkgewogICAgICAgIGNvbnRvdXIucHVzaChjb250b3VyWzBdKTsKICAgICAgfSBlbHNlIGlmIChjb250b3VyLmF0KC0xKS5mbGFncyAmIDEpIHsKICAgICAgICBjb250b3VyLnVuc2hpZnQoY29udG91ci5hdCgtMSkpOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IHAgPSB7CiAgICAgICAgICBmbGFnczogMSwKICAgICAgICAgIHg6IChjb250b3VyWzBdLnggKyBjb250b3VyLmF0KC0xKS54KSAvIDIsCiAgICAgICAgICB5OiAoY29udG91clswXS55ICsgY29udG91ci5hdCgtMSkueSkgLyAyCiAgICAgICAgfTsKICAgICAgICBjb250b3VyLnVuc2hpZnQocCk7CiAgICAgICAgY29udG91ci5wdXNoKHApOwogICAgICB9CiAgICAgIG1vdmVUbyhjb250b3VyWzBdLngsIGNvbnRvdXJbMF0ueSk7CiAgICAgIGZvciAoaiA9IDEsIGpqID0gY29udG91ci5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgICAgaWYgKGNvbnRvdXJbal0uZmxhZ3MgJiAxKSB7CiAgICAgICAgICBsaW5lVG8oY29udG91cltqXS54LCBjb250b3VyW2pdLnkpOwogICAgICAgIH0gZWxzZSBpZiAoY29udG91cltqICsgMV0uZmxhZ3MgJiAxKSB7CiAgICAgICAgICBxdWFkcmF0aWNDdXJ2ZVRvKGNvbnRvdXJbal0ueCwgY29udG91cltqXS55LCBjb250b3VyW2ogKyAxXS54LCBjb250b3VyW2ogKyAxXS55KTsKICAgICAgICAgIGorKzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcXVhZHJhdGljQ3VydmVUbyhjb250b3VyW2pdLngsIGNvbnRvdXJbal0ueSwgKGNvbnRvdXJbal0ueCArIGNvbnRvdXJbaiArIDFdLngpIC8gMiwgKGNvbnRvdXJbal0ueSArIGNvbnRvdXJbaiArIDFdLnkpIC8gMik7CiAgICAgICAgfQogICAgICB9CiAgICAgIHN0YXJ0UG9pbnQgPSBlbmRQb2ludCArIDE7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGNvbXBpbGVDaGFyU3RyaW5nKGNoYXJTdHJpbmdDb2RlLCBjbWRzLCBmb250LCBnbHlwaElkKSB7CiAgZnVuY3Rpb24gbW92ZVRvKHgsIHkpIHsKICAgIGlmIChmaXJzdFBvaW50KSB7CiAgICAgIGNtZHMuYWRkKERyYXdPUFMubGluZVRvLCBmaXJzdFBvaW50KTsKICAgIH0KICAgIGZpcnN0UG9pbnQgPSBbeCwgeV07CiAgICBjbWRzLmFkZChEcmF3T1BTLm1vdmVUbywgW3gsIHldKTsKICB9CiAgZnVuY3Rpb24gbGluZVRvKHgsIHkpIHsKICAgIGNtZHMuYWRkKERyYXdPUFMubGluZVRvLCBbeCwgeV0pOwogIH0KICBmdW5jdGlvbiBiZXppZXJDdXJ2ZVRvKHgxLCB5MSwgeDIsIHkyLCB4LCB5KSB7CiAgICBjbWRzLmFkZChEcmF3T1BTLmN1cnZlVG8sIFt4MSwgeTEsIHgyLCB5MiwgeCwgeV0pOwogIH0KICBjb25zdCBzdGFjayA9IFtdOwogIGxldCB4ID0gMCwKICAgIHkgPSAwOwogIGxldCBzdGVtcyA9IDA7CiAgbGV0IGZpcnN0UG9pbnQgPSBudWxsOwogIGZ1bmN0aW9uIHBhcnNlKGNvZGUpIHsKICAgIGxldCBpID0gMDsKICAgIHdoaWxlIChpIDwgY29kZS5sZW5ndGgpIHsKICAgICAgbGV0IHN0YWNrQ2xlYW4gPSBmYWxzZTsKICAgICAgbGV0IHYgPSBjb2RlW2krK107CiAgICAgIGxldCB4YSwgeGIsIHlhLCB5YiwgeTEsIHkyLCB5Mywgbiwgc3VickNvZGU7CiAgICAgIHN3aXRjaCAodikgewogICAgICAgIGNhc2UgMToKICAgICAgICAgIHN0ZW1zICs9IHN0YWNrLmxlbmd0aCA+PiAxOwogICAgICAgICAgc3RhY2tDbGVhbiA9IHRydWU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDM6CiAgICAgICAgICBzdGVtcyArPSBzdGFjay5sZW5ndGggPj4gMTsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA0OgogICAgICAgICAgeSArPSBzdGFjay5wb3AoKTsKICAgICAgICAgIG1vdmVUbyh4LCB5KTsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1OgogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgeCArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIGxpbmVUbyh4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNjoKICAgICAgICAgIHdoaWxlIChzdGFjay5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIHggKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgbGluZVRvKHgsIHkpOwogICAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgeSArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICBsaW5lVG8oeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDc6CiAgICAgICAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgICB5ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIGxpbmVUbyh4LCB5KTsKICAgICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHggKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgbGluZVRvKHgsIHkpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA4OgogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWEgPSB5ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHliID0geWEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB4ID0geGIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5ID0geWIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTA6CiAgICAgICAgICBuID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdWJyQ29kZSA9IG51bGw7CiAgICAgICAgICBpZiAoZm9udC5pc0NGRkNJREZvbnQpIHsKICAgICAgICAgICAgY29uc3QgZmRJbmRleCA9IGZvbnQuZmRTZWxlY3QuZ2V0RkRJbmRleChnbHlwaElkKTsKICAgICAgICAgICAgaWYgKGZkSW5kZXggPj0gMCAmJiBmZEluZGV4IDwgZm9udC5mZEFycmF5Lmxlbmd0aCkgewogICAgICAgICAgICAgIGNvbnN0IGZvbnREaWN0ID0gZm9udC5mZEFycmF5W2ZkSW5kZXhdOwogICAgICAgICAgICAgIGxldCBzdWJyczsKICAgICAgICAgICAgICBpZiAoZm9udERpY3QucHJpdmF0ZURpY3Q/LnN1YnJzSW5kZXgpIHsKICAgICAgICAgICAgICAgIHN1YnJzID0gZm9udERpY3QucHJpdmF0ZURpY3Quc3VicnNJbmRleC5vYmplY3RzOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoc3VicnMpIHsKICAgICAgICAgICAgICAgIG4gKz0gZ2V0U3Vicm91dGluZUJpYXMoc3VicnMpOwogICAgICAgICAgICAgICAgc3VickNvZGUgPSBzdWJyc1tuXTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgd2FybigiSW52YWxpZCBmZCBpbmRleCBmb3IgZ2x5cGggaW5kZXguIik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN1YnJDb2RlID0gZm9udC5zdWJyc1tuICsgZm9udC5zdWJyc0JpYXNdOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHN1YnJDb2RlKSB7CiAgICAgICAgICAgIHBhcnNlKHN1YnJDb2RlKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTE6CiAgICAgICAgICByZXR1cm47CiAgICAgICAgY2FzZSAxMjoKICAgICAgICAgIHYgPSBjb2RlW2krK107CiAgICAgICAgICBzd2l0Y2ggKHYpIHsKICAgICAgICAgICAgY2FzZSAzNDoKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHkxID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5LCB4YiwgeTEsIHgsIHkxKTsKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeTEsIHhiLCB5LCB4LCB5KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAzNToKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5ID0geWIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIGJlemllckN1cnZlVG8oeGEsIHlhLCB4YiwgeWIsIHgsIHkpOwogICAgICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeWEgPSB5ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB4YiA9IHhhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB4ID0geGIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHkgPSB5YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICAgICAgc3RhY2sucG9wKCk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzY6CiAgICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5MSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHkyID0geTEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeTEsIHhiLCB5MiwgeCwgeTIpOwogICAgICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeTMgPSB5MiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5MiwgeGIsIHkzLCB4LCB5KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAzNzoKICAgICAgICAgICAgICBjb25zdCB4MCA9IHgsCiAgICAgICAgICAgICAgICB5MCA9IHk7CiAgICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5YSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHliID0geWEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeSA9IHliICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiOwogICAgICAgICAgICAgIHkgPSB5YjsKICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMoeCAtIHgwKSA+IE1hdGguYWJzKHkgLSB5MCkpIHsKICAgICAgICAgICAgICAgIHggKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgeSArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYHVua25vd24gb3BlcmF0b3I6IDEyICR7dn1gKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTQ6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoID49IDQpIHsKICAgICAgICAgICAgY29uc3QgYWNoYXIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgICAgY29uc3QgYmNoYXIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgICAgeSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgICB4ID0gc3RhY2sucG9wKCk7CiAgICAgICAgICAgIGNtZHMuc2F2ZSgpOwogICAgICAgICAgICBjbWRzLnRyYW5zbGF0ZSh4LCB5KTsKICAgICAgICAgICAgbGV0IGNtYXAgPSBsb29rdXBDbWFwKGZvbnQuY21hcCwgU3RyaW5nLmZyb21DaGFyQ29kZShmb250LmdseXBoTmFtZU1hcFtTdGFuZGFyZEVuY29kaW5nW2FjaGFyXV0pKTsKICAgICAgICAgICAgY29tcGlsZUNoYXJTdHJpbmcoZm9udC5nbHlwaHNbY21hcC5nbHlwaElkXSwgY21kcywgZm9udCwgY21hcC5nbHlwaElkKTsKICAgICAgICAgICAgY21kcy5yZXN0b3JlKCk7CiAgICAgICAgICAgIGNtYXAgPSBsb29rdXBDbWFwKGZvbnQuY21hcCwgU3RyaW5nLmZyb21DaGFyQ29kZShmb250LmdseXBoTmFtZU1hcFtTdGFuZGFyZEVuY29kaW5nW2JjaGFyXV0pKTsKICAgICAgICAgICAgY29tcGlsZUNoYXJTdHJpbmcoZm9udC5nbHlwaHNbY21hcC5nbHlwaElkXSwgY21kcywgZm9udCwgY21hcC5nbHlwaElkKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybjsKICAgICAgICBjYXNlIDE4OgogICAgICAgICAgc3RlbXMgKz0gc3RhY2subGVuZ3RoID4+IDE7CiAgICAgICAgICBzdGFja0NsZWFuID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTk6CiAgICAgICAgICBzdGVtcyArPSBzdGFjay5sZW5ndGggPj4gMTsKICAgICAgICAgIGkgKz0gc3RlbXMgKyA3ID4+IDM7CiAgICAgICAgICBzdGFja0NsZWFuID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjA6CiAgICAgICAgICBzdGVtcyArPSBzdGFjay5sZW5ndGggPj4gMTsKICAgICAgICAgIGkgKz0gc3RlbXMgKyA3ID4+IDM7CiAgICAgICAgICBzdGFja0NsZWFuID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjE6CiAgICAgICAgICB5ICs9IHN0YWNrLnBvcCgpOwogICAgICAgICAgeCArPSBzdGFjay5wb3AoKTsKICAgICAgICAgIG1vdmVUbyh4LCB5KTsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyMjoKICAgICAgICAgIHggKz0gc3RhY2sucG9wKCk7CiAgICAgICAgICBtb3ZlVG8oeCwgeSk7CiAgICAgICAgICBzdGFja0NsZWFuID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjM6CiAgICAgICAgICBzdGVtcyArPSBzdGFjay5sZW5ndGggPj4gMTsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyNDoKICAgICAgICAgIHdoaWxlIChzdGFjay5sZW5ndGggPiAyKSB7CiAgICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeSA9IHliICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICB4ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICB5ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICBsaW5lVG8oeCwgeSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI1OgogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDYpIHsKICAgICAgICAgICAgeCArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIGxpbmVUbyh4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICB5YSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICB5ID0geWIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI2OgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCAlIDIpIHsKICAgICAgICAgICAgeCArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgfQogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgeGEgPSB4OwogICAgICAgICAgICB5YSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB4YiA9IHhhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHggPSB4YjsKICAgICAgICAgICAgeSA9IHliICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI3OgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCAlIDIpIHsKICAgICAgICAgICAgeSArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgfQogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWEgPSB5OwogICAgICAgICAgICB4YiA9IHhhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHkgPSB5YjsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI4OgogICAgICAgICAgc3RhY2sucHVzaChyZWFkSW50MTYoY29kZSwgaSkpOwogICAgICAgICAgaSArPSAyOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyOToKICAgICAgICAgIG4gPSBzdGFjay5wb3AoKSArIGZvbnQuZ3N1YnJzQmlhczsKICAgICAgICAgIHN1YnJDb2RlID0gZm9udC5nc3VicnNbbl07CiAgICAgICAgICBpZiAoc3VickNvZGUpIHsKICAgICAgICAgICAgcGFyc2Uoc3VickNvZGUpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAzMDoKICAgICAgICAgIHdoaWxlIChzdGFjay5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIHhhID0geDsKICAgICAgICAgICAgeWEgPSB5ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHliID0geWEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB4ID0geGIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5ID0geWIgKyAoc3RhY2subGVuZ3RoID09PSAxID8gc3RhY2suc2hpZnQoKSA6IDApOwogICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHlhID0geTsKICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHliID0geWEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5ID0geWIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB4ID0geGIgKyAoc3RhY2subGVuZ3RoID09PSAxID8gc3RhY2suc2hpZnQoKSA6IDApOwogICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzE6CiAgICAgICAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YSA9IHk7CiAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeSA9IHliICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeCA9IHhiICsgKHN0YWNrLmxlbmd0aCA9PT0gMSA/IHN0YWNrLnNoaWZ0KCkgOiAwKTsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICB4YSA9IHg7CiAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeSA9IHliICsgKHN0YWNrLmxlbmd0aCA9PT0gMSA/IHN0YWNrLnNoaWZ0KCkgOiAwKTsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgaWYgKHYgPCAzMikgewogICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYHVua25vd24gb3BlcmF0b3I6ICR7dn1gKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2IDwgMjQ3KSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2godiAtIDEzOSk7CiAgICAgICAgICB9IGVsc2UgaWYgKHYgPCAyNTEpIHsKICAgICAgICAgICAgc3RhY2sucHVzaCgodiAtIDI0NykgKiAyNTYgKyBjb2RlW2krK10gKyAxMDgpOwogICAgICAgICAgfSBlbHNlIGlmICh2IDwgMjU1KSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goLSh2IC0gMjUxKSAqIDI1NiAtIGNvZGVbaSsrXSAtIDEwOCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdGFjay5wdXNoKChjb2RlW2ldIDw8IDI0IHwgY29kZVtpICsgMV0gPDwgMTYgfCBjb2RlW2kgKyAyXSA8PCA4IHwgY29kZVtpICsgM10pIC8gNjU1MzYpOwogICAgICAgICAgICBpICs9IDQ7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoc3RhY2tDbGVhbikgewogICAgICAgIHN0YWNrLmxlbmd0aCA9IDA7CiAgICAgIH0KICAgIH0KICB9CiAgcGFyc2UoY2hhclN0cmluZ0NvZGUpOwp9CmNvbnN0IE5PT1AgPSAiIjsKY2xhc3MgQ29tbWFuZHMgewogIGNtZHMgPSBbXTsKICB0cmFuc2Zvcm1TdGFjayA9IFtdOwogIGN1cnJlbnRUcmFuc2Zvcm0gPSBbMSwgMCwgMCwgMSwgMCwgMF07CiAgYWRkKGNtZCwgYXJncykgewogICAgaWYgKGFyZ3MpIHsKICAgICAgY29uc3QgewogICAgICAgIGN1cnJlbnRUcmFuc2Zvcm0KICAgICAgfSA9IHRoaXM7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGFyZ3MubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgIFV0aWwuYXBwbHlUcmFuc2Zvcm0oYXJncywgY3VycmVudFRyYW5zZm9ybSwgaSk7CiAgICAgIH0KICAgICAgdGhpcy5jbWRzLnB1c2goY21kLCAuLi5hcmdzKTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuY21kcy5wdXNoKGNtZCk7CiAgICB9CiAgfQogIHRyYW5zZm9ybSh0cmFuc2YpIHsKICAgIHRoaXMuY3VycmVudFRyYW5zZm9ybSA9IFV0aWwudHJhbnNmb3JtKHRoaXMuY3VycmVudFRyYW5zZm9ybSwgdHJhbnNmKTsKICB9CiAgdHJhbnNsYXRlKHgsIHkpIHsKICAgIHRoaXMudHJhbnNmb3JtKFsxLCAwLCAwLCAxLCB4LCB5XSk7CiAgfQogIHNhdmUoKSB7CiAgICB0aGlzLnRyYW5zZm9ybVN0YWNrLnB1c2godGhpcy5jdXJyZW50VHJhbnNmb3JtLnNsaWNlKCkpOwogIH0KICByZXN0b3JlKCkgewogICAgdGhpcy5jdXJyZW50VHJhbnNmb3JtID0gdGhpcy50cmFuc2Zvcm1TdGFjay5wb3AoKSB8fCBbMSwgMCwgMCwgMSwgMCwgMF07CiAgfQogIGdldFBhdGgoKSB7CiAgICByZXR1cm4gbmV3IChGZWF0dXJlVGVzdC5pc0Zsb2F0MTZBcnJheVN1cHBvcnRlZCA/IEZsb2F0MTZBcnJheSA6IEZsb2F0MzJBcnJheSkodGhpcy5jbWRzKTsKICB9Cn0KY2xhc3MgQ29tcGlsZWRGb250IHsKICBjb25zdHJ1Y3Rvcihmb250TWF0cml4KSB7CiAgICB0aGlzLmZvbnRNYXRyaXggPSBmb250TWF0cml4OwogICAgdGhpcy5jb21waWxlZEdseXBocyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB0aGlzLmNvbXBpbGVkQ2hhckNvZGVUb0dseXBoSWQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIH0KICBnZXRQYXRoSnModW5pY29kZSkgewogICAgY29uc3QgewogICAgICBjaGFyQ29kZSwKICAgICAgZ2x5cGhJZAogICAgfSA9IGxvb2t1cENtYXAodGhpcy5jbWFwLCB1bmljb2RlKTsKICAgIGxldCBmbiA9IHRoaXMuY29tcGlsZWRHbHlwaHNbZ2x5cGhJZF0sCiAgICAgIGNvbXBpbGVFeDsKICAgIGlmIChmbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHRyeSB7CiAgICAgICAgZm4gPSB0aGlzLmNvbXBpbGVHbHlwaCh0aGlzLmdseXBoc1tnbHlwaElkXSwgZ2x5cGhJZCk7CiAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgZm4gPSBOT09QOwogICAgICAgIGNvbXBpbGVFeCA9IGV4OwogICAgICB9CiAgICAgIHRoaXMuY29tcGlsZWRHbHlwaHNbZ2x5cGhJZF0gPSBmbjsKICAgIH0KICAgIHRoaXMuY29tcGlsZWRDaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPz89IGdseXBoSWQ7CiAgICBpZiAoY29tcGlsZUV4KSB7CiAgICAgIHRocm93IGNvbXBpbGVFeDsKICAgIH0KICAgIHJldHVybiBmbjsKICB9CiAgY29tcGlsZUdseXBoKGNvZGUsIGdseXBoSWQpIHsKICAgIGlmICghY29kZT8ubGVuZ3RoIHx8IGNvZGVbMF0gPT09IDE0KSB7CiAgICAgIHJldHVybiBOT09QOwogICAgfQogICAgbGV0IGZvbnRNYXRyaXggPSB0aGlzLmZvbnRNYXRyaXg7CiAgICBpZiAodGhpcy5pc0NGRkNJREZvbnQpIHsKICAgICAgY29uc3QgZmRJbmRleCA9IHRoaXMuZmRTZWxlY3QuZ2V0RkRJbmRleChnbHlwaElkKTsKICAgICAgaWYgKGZkSW5kZXggPj0gMCAmJiBmZEluZGV4IDwgdGhpcy5mZEFycmF5Lmxlbmd0aCkgewogICAgICAgIGNvbnN0IGZvbnREaWN0ID0gdGhpcy5mZEFycmF5W2ZkSW5kZXhdOwogICAgICAgIGZvbnRNYXRyaXggPSBmb250RGljdC5nZXRCeU5hbWUoIkZvbnRNYXRyaXgiKSB8fCBGT05UX0lERU5USVRZX01BVFJJWDsKICAgICAgfSBlbHNlIHsKICAgICAgICB3YXJuKCJJbnZhbGlkIGZkIGluZGV4IGZvciBnbHlwaCBpbmRleC4iKTsKICAgICAgfQogICAgfQogICAgYXNzZXJ0KGlzTnVtYmVyQXJyYXkoZm9udE1hdHJpeCwgNiksICJFeHBlY3RlZCBhIHZhbGlkIGZvbnRNYXRyaXguIik7CiAgICBjb25zdCBjbWRzID0gbmV3IENvbW1hbmRzKCk7CiAgICBjbWRzLnRyYW5zZm9ybShmb250TWF0cml4LnNsaWNlKCkpOwogICAgdGhpcy5jb21waWxlR2x5cGhJbXBsKGNvZGUsIGNtZHMsIGdseXBoSWQpOwogICAgY21kcy5hZGQoRHJhd09QUy5jbG9zZVBhdGgpOwogICAgcmV0dXJuIGNtZHMuZ2V0UGF0aCgpOwogIH0KICBjb21waWxlR2x5cGhJbXBsKCkgewogICAgdW5yZWFjaGFibGUoIkNoaWxkcmVuIGNsYXNzZXMgc2hvdWxkIGltcGxlbWVudCB0aGlzLiIpOwogIH0KICBoYXNCdWlsdFBhdGgodW5pY29kZSkgewogICAgY29uc3QgewogICAgICBjaGFyQ29kZSwKICAgICAgZ2x5cGhJZAogICAgfSA9IGxvb2t1cENtYXAodGhpcy5jbWFwLCB1bmljb2RlKTsKICAgIHJldHVybiB0aGlzLmNvbXBpbGVkR2x5cGhzW2dseXBoSWRdICE9PSB1bmRlZmluZWQgJiYgdGhpcy5jb21waWxlZENoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSAhPT0gdW5kZWZpbmVkOwogIH0KfQpjbGFzcyBUcnVlVHlwZUNvbXBpbGVkIGV4dGVuZHMgQ29tcGlsZWRGb250IHsKICBjb25zdHJ1Y3RvcihnbHlwaHMsIGNtYXAsIGZvbnRNYXRyaXgpIHsKICAgIHN1cGVyKGZvbnRNYXRyaXggfHwgWzAuMDAwNDg4LCAwLCAwLCAwLjAwMDQ4OCwgMCwgMF0pOwogICAgdGhpcy5nbHlwaHMgPSBnbHlwaHM7CiAgICB0aGlzLmNtYXAgPSBjbWFwOwogIH0KICBjb21waWxlR2x5cGhJbXBsKGNvZGUsIGNtZHMpIHsKICAgIGNvbXBpbGVHbHlmKGNvZGUsIGNtZHMsIHRoaXMpOwogIH0KfQpjbGFzcyBUeXBlMkNvbXBpbGVkIGV4dGVuZHMgQ29tcGlsZWRGb250IHsKICBjb25zdHJ1Y3RvcihjZmZJbmZvLCBjbWFwLCBmb250TWF0cml4KSB7CiAgICBzdXBlcihmb250TWF0cml4IHx8IFswLjAwMSwgMCwgMCwgMC4wMDEsIDAsIDBdKTsKICAgIHRoaXMuZ2x5cGhzID0gY2ZmSW5mby5nbHlwaHM7CiAgICB0aGlzLmdzdWJycyA9IGNmZkluZm8uZ3N1YnJzIHx8IFtdOwogICAgdGhpcy5zdWJycyA9IGNmZkluZm8uc3VicnMgfHwgW107CiAgICB0aGlzLmNtYXAgPSBjbWFwOwogICAgdGhpcy5nbHlwaE5hbWVNYXAgPSBnZXRHbHlwaHNVbmljb2RlKCk7CiAgICB0aGlzLmdzdWJyc0JpYXMgPSBnZXRTdWJyb3V0aW5lQmlhcyh0aGlzLmdzdWJycyk7CiAgICB0aGlzLnN1YnJzQmlhcyA9IGdldFN1YnJvdXRpbmVCaWFzKHRoaXMuc3VicnMpOwogICAgdGhpcy5pc0NGRkNJREZvbnQgPSBjZmZJbmZvLmlzQ0ZGQ0lERm9udDsKICAgIHRoaXMuZmRTZWxlY3QgPSBjZmZJbmZvLmZkU2VsZWN0OwogICAgdGhpcy5mZEFycmF5ID0gY2ZmSW5mby5mZEFycmF5OwogIH0KICBjb21waWxlR2x5cGhJbXBsKGNvZGUsIGNtZHMsIGdseXBoSWQpIHsKICAgIGNvbXBpbGVDaGFyU3RyaW5nKGNvZGUsIGNtZHMsIHRoaXMsIGdseXBoSWQpOwogIH0KfQpjbGFzcyBGb250UmVuZGVyZXJGYWN0b3J5IHsKICBzdGF0aWMgY3JlYXRlKGZvbnQsIHNlYWNBbmFseXNpc0VuYWJsZWQpIHsKICAgIGNvbnN0IGRhdGEgPSBuZXcgVWludDhBcnJheShmb250LmRhdGEpOwogICAgbGV0IGNtYXAsIGdseWYsIGxvY2EsIGNmZiwgaW5kZXhUb0xvY0Zvcm1hdCwgdW5pdHNQZXJFbTsKICAgIGNvbnN0IG51bVRhYmxlcyA9IHJlYWRVaW50MTYoZGF0YSwgNCk7CiAgICBmb3IgKGxldCBpID0gMCwgcCA9IDEyOyBpIDwgbnVtVGFibGVzOyBpKyssIHAgKz0gMTYpIHsKICAgICAgY29uc3QgdGFnID0gYnl0ZXNUb1N0cmluZyhkYXRhLnN1YmFycmF5KHAsIHAgKyA0KSk7CiAgICAgIGNvbnN0IG9mZnNldCA9IHJlYWRVaW50MzIoZGF0YSwgcCArIDgpOwogICAgICBjb25zdCBsZW5ndGggPSByZWFkVWludDMyKGRhdGEsIHAgKyAxMik7CiAgICAgIHN3aXRjaCAodGFnKSB7CiAgICAgICAgY2FzZSAiY21hcCI6CiAgICAgICAgICBjbWFwID0gcGFyc2VDbWFwKGRhdGEsIG9mZnNldCwgb2Zmc2V0ICsgbGVuZ3RoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImdseWYiOgogICAgICAgICAgZ2x5ZiA9IGRhdGEuc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKyBsZW5ndGgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibG9jYSI6CiAgICAgICAgICBsb2NhID0gZGF0YS5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIGxlbmd0aCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJoZWFkIjoKICAgICAgICAgIHVuaXRzUGVyRW0gPSByZWFkVWludDE2KGRhdGEsIG9mZnNldCArIDE4KTsKICAgICAgICAgIGluZGV4VG9Mb2NGb3JtYXQgPSByZWFkVWludDE2KGRhdGEsIG9mZnNldCArIDUwKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkNGRiAiOgogICAgICAgICAgY2ZmID0gcGFyc2VDZmYoZGF0YSwgb2Zmc2V0LCBvZmZzZXQgKyBsZW5ndGgsIHNlYWNBbmFseXNpc0VuYWJsZWQpOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGlmIChnbHlmKSB7CiAgICAgIGNvbnN0IGZvbnRNYXRyaXggPSAhdW5pdHNQZXJFbSA/IGZvbnQuZm9udE1hdHJpeCA6IFsxIC8gdW5pdHNQZXJFbSwgMCwgMCwgMSAvIHVuaXRzUGVyRW0sIDAsIDBdOwogICAgICByZXR1cm4gbmV3IFRydWVUeXBlQ29tcGlsZWQocGFyc2VHbHlmVGFibGUoZ2x5ZiwgbG9jYSwgaW5kZXhUb0xvY0Zvcm1hdCksIGNtYXAsIGZvbnRNYXRyaXgpOwogICAgfQogICAgcmV0dXJuIG5ldyBUeXBlMkNvbXBpbGVkKGNmZiwgY21hcCwgZm9udC5mb250TWF0cml4KTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL21ldHJpY3MuanMKCmNvbnN0IGdldE1ldHJpY3MgPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICB0LkNvdXJpZXIgPSA2MDA7CiAgdFsiQ291cmllci1Cb2xkIl0gPSA2MDA7CiAgdFsiQ291cmllci1Cb2xkT2JsaXF1ZSJdID0gNjAwOwogIHRbIkNvdXJpZXItT2JsaXF1ZSJdID0gNjAwOwogIHQuSGVsdmV0aWNhID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uICh0KSB7CiAgICB0LnNwYWNlID0gMjc4OwogICAgdC5leGNsYW0gPSAyNzg7CiAgICB0LnF1b3RlZGJsID0gMzU1OwogICAgdC5udW1iZXJzaWduID0gNTU2OwogICAgdC5kb2xsYXIgPSA1NTY7CiAgICB0LnBlcmNlbnQgPSA4ODk7CiAgICB0LmFtcGVyc2FuZCA9IDY2NzsKICAgIHQucXVvdGVyaWdodCA9IDIyMjsKICAgIHQucGFyZW5sZWZ0ID0gMzMzOwogICAgdC5wYXJlbnJpZ2h0ID0gMzMzOwogICAgdC5hc3RlcmlzayA9IDM4OTsKICAgIHQucGx1cyA9IDU4NDsKICAgIHQuY29tbWEgPSAyNzg7CiAgICB0Lmh5cGhlbiA9IDMzMzsKICAgIHQucGVyaW9kID0gMjc4OwogICAgdC5zbGFzaCA9IDI3ODsKICAgIHQuemVybyA9IDU1NjsKICAgIHQub25lID0gNTU2OwogICAgdC50d28gPSA1NTY7CiAgICB0LnRocmVlID0gNTU2OwogICAgdC5mb3VyID0gNTU2OwogICAgdC5maXZlID0gNTU2OwogICAgdC5zaXggPSA1NTY7CiAgICB0LnNldmVuID0gNTU2OwogICAgdC5laWdodCA9IDU1NjsKICAgIHQubmluZSA9IDU1NjsKICAgIHQuY29sb24gPSAyNzg7CiAgICB0LnNlbWljb2xvbiA9IDI3ODsKICAgIHQubGVzcyA9IDU4NDsKICAgIHQuZXF1YWwgPSA1ODQ7CiAgICB0LmdyZWF0ZXIgPSA1ODQ7CiAgICB0LnF1ZXN0aW9uID0gNTU2OwogICAgdC5hdCA9IDEwMTU7CiAgICB0LkEgPSA2Njc7CiAgICB0LkIgPSA2Njc7CiAgICB0LkMgPSA3MjI7CiAgICB0LkQgPSA3MjI7CiAgICB0LkUgPSA2Njc7CiAgICB0LkYgPSA2MTE7CiAgICB0LkcgPSA3Nzg7CiAgICB0LkggPSA3MjI7CiAgICB0LkkgPSAyNzg7CiAgICB0LkogPSA1MDA7CiAgICB0LksgPSA2Njc7CiAgICB0LkwgPSA1NTY7CiAgICB0Lk0gPSA4MzM7CiAgICB0Lk4gPSA3MjI7CiAgICB0Lk8gPSA3Nzg7CiAgICB0LlAgPSA2Njc7CiAgICB0LlEgPSA3Nzg7CiAgICB0LlIgPSA3MjI7CiAgICB0LlMgPSA2Njc7CiAgICB0LlQgPSA2MTE7CiAgICB0LlUgPSA3MjI7CiAgICB0LlYgPSA2Njc7CiAgICB0LlcgPSA5NDQ7CiAgICB0LlggPSA2Njc7CiAgICB0LlkgPSA2Njc7CiAgICB0LlogPSA2MTE7CiAgICB0LmJyYWNrZXRsZWZ0ID0gMjc4OwogICAgdC5iYWNrc2xhc2ggPSAyNzg7CiAgICB0LmJyYWNrZXRyaWdodCA9IDI3ODsKICAgIHQuYXNjaWljaXJjdW0gPSA0Njk7CiAgICB0LnVuZGVyc2NvcmUgPSA1NTY7CiAgICB0LnF1b3RlbGVmdCA9IDIyMjsKICAgIHQuYSA9IDU1NjsKICAgIHQuYiA9IDU1NjsKICAgIHQuYyA9IDUwMDsKICAgIHQuZCA9IDU1NjsKICAgIHQuZSA9IDU1NjsKICAgIHQuZiA9IDI3ODsKICAgIHQuZyA9IDU1NjsKICAgIHQuaCA9IDU1NjsKICAgIHQuaSA9IDIyMjsKICAgIHQuaiA9IDIyMjsKICAgIHQuayA9IDUwMDsKICAgIHQubCA9IDIyMjsKICAgIHQubSA9IDgzMzsKICAgIHQubiA9IDU1NjsKICAgIHQubyA9IDU1NjsKICAgIHQucCA9IDU1NjsKICAgIHQucSA9IDU1NjsKICAgIHQuciA9IDMzMzsKICAgIHQucyA9IDUwMDsKICAgIHQudCA9IDI3ODsKICAgIHQudSA9IDU1NjsKICAgIHQudiA9IDUwMDsKICAgIHQudyA9IDcyMjsKICAgIHQueCA9IDUwMDsKICAgIHQueSA9IDUwMDsKICAgIHQueiA9IDUwMDsKICAgIHQuYnJhY2VsZWZ0ID0gMzM0OwogICAgdC5iYXIgPSAyNjA7CiAgICB0LmJyYWNlcmlnaHQgPSAzMzQ7CiAgICB0LmFzY2lpdGlsZGUgPSA1ODQ7CiAgICB0LmV4Y2xhbWRvd24gPSAzMzM7CiAgICB0LmNlbnQgPSA1NTY7CiAgICB0LnN0ZXJsaW5nID0gNTU2OwogICAgdC5mcmFjdGlvbiA9IDE2NzsKICAgIHQueWVuID0gNTU2OwogICAgdC5mbG9yaW4gPSA1NTY7CiAgICB0LnNlY3Rpb24gPSA1NTY7CiAgICB0LmN1cnJlbmN5ID0gNTU2OwogICAgdC5xdW90ZXNpbmdsZSA9IDE5MTsKICAgIHQucXVvdGVkYmxsZWZ0ID0gMzMzOwogICAgdC5ndWlsbGVtb3RsZWZ0ID0gNTU2OwogICAgdC5ndWlsc2luZ2xsZWZ0ID0gMzMzOwogICAgdC5ndWlsc2luZ2xyaWdodCA9IDMzMzsKICAgIHQuZmkgPSA1MDA7CiAgICB0LmZsID0gNTAwOwogICAgdC5lbmRhc2ggPSA1NTY7CiAgICB0LmRhZ2dlciA9IDU1NjsKICAgIHQuZGFnZ2VyZGJsID0gNTU2OwogICAgdC5wZXJpb2RjZW50ZXJlZCA9IDI3ODsKICAgIHQucGFyYWdyYXBoID0gNTM3OwogICAgdC5idWxsZXQgPSAzNTA7CiAgICB0LnF1b3Rlc2luZ2xiYXNlID0gMjIyOwogICAgdC5xdW90ZWRibGJhc2UgPSAzMzM7CiAgICB0LnF1b3RlZGJscmlnaHQgPSAzMzM7CiAgICB0Lmd1aWxsZW1vdHJpZ2h0ID0gNTU2OwogICAgdC5lbGxpcHNpcyA9IDEwMDA7CiAgICB0LnBlcnRob3VzYW5kID0gMTAwMDsKICAgIHQucXVlc3Rpb25kb3duID0gNjExOwogICAgdC5ncmF2ZSA9IDMzMzsKICAgIHQuYWN1dGUgPSAzMzM7CiAgICB0LmNpcmN1bWZsZXggPSAzMzM7CiAgICB0LnRpbGRlID0gMzMzOwogICAgdC5tYWNyb24gPSAzMzM7CiAgICB0LmJyZXZlID0gMzMzOwogICAgdC5kb3RhY2NlbnQgPSAzMzM7CiAgICB0LmRpZXJlc2lzID0gMzMzOwogICAgdC5yaW5nID0gMzMzOwogICAgdC5jZWRpbGxhID0gMzMzOwogICAgdC5odW5nYXJ1bWxhdXQgPSAzMzM7CiAgICB0Lm9nb25layA9IDMzMzsKICAgIHQuY2Fyb24gPSAzMzM7CiAgICB0LmVtZGFzaCA9IDEwMDA7CiAgICB0LkFFID0gMTAwMDsKICAgIHQub3JkZmVtaW5pbmUgPSAzNzA7CiAgICB0LkxzbGFzaCA9IDU1NjsKICAgIHQuT3NsYXNoID0gNzc4OwogICAgdC5PRSA9IDEwMDA7CiAgICB0Lm9yZG1hc2N1bGluZSA9IDM2NTsKICAgIHQuYWUgPSA4ODk7CiAgICB0LmRvdGxlc3NpID0gMjc4OwogICAgdC5sc2xhc2ggPSAyMjI7CiAgICB0Lm9zbGFzaCA9IDYxMTsKICAgIHQub2UgPSA5NDQ7CiAgICB0Lmdlcm1hbmRibHMgPSA2MTE7CiAgICB0LklkaWVyZXNpcyA9IDI3ODsKICAgIHQuZWFjdXRlID0gNTU2OwogICAgdC5hYnJldmUgPSA1NTY7CiAgICB0LnVodW5nYXJ1bWxhdXQgPSA1NTY7CiAgICB0LmVjYXJvbiA9IDU1NjsKICAgIHQuWWRpZXJlc2lzID0gNjY3OwogICAgdC5kaXZpZGUgPSA1ODQ7CiAgICB0LllhY3V0ZSA9IDY2NzsKICAgIHQuQWNpcmN1bWZsZXggPSA2Njc7CiAgICB0LmFhY3V0ZSA9IDU1NjsKICAgIHQuVWNpcmN1bWZsZXggPSA3MjI7CiAgICB0LnlhY3V0ZSA9IDUwMDsKICAgIHQuc2NvbW1hYWNjZW50ID0gNTAwOwogICAgdC5lY2lyY3VtZmxleCA9IDU1NjsKICAgIHQuVXJpbmcgPSA3MjI7CiAgICB0LlVkaWVyZXNpcyA9IDcyMjsKICAgIHQuYW9nb25layA9IDU1NjsKICAgIHQuVWFjdXRlID0gNzIyOwogICAgdC51b2dvbmVrID0gNTU2OwogICAgdC5FZGllcmVzaXMgPSA2Njc7CiAgICB0LkRjcm9hdCA9IDcyMjsKICAgIHQuY29tbWFhY2NlbnQgPSAyNTA7CiAgICB0LmNvcHlyaWdodCA9IDczNzsKICAgIHQuRW1hY3JvbiA9IDY2NzsKICAgIHQuY2Nhcm9uID0gNTAwOwogICAgdC5hcmluZyA9IDU1NjsKICAgIHQuTmNvbW1hYWNjZW50ID0gNzIyOwogICAgdC5sYWN1dGUgPSAyMjI7CiAgICB0LmFncmF2ZSA9IDU1NjsKICAgIHQuVGNvbW1hYWNjZW50ID0gNjExOwogICAgdC5DYWN1dGUgPSA3MjI7CiAgICB0LmF0aWxkZSA9IDU1NjsKICAgIHQuRWRvdGFjY2VudCA9IDY2NzsKICAgIHQuc2Nhcm9uID0gNTAwOwogICAgdC5zY2VkaWxsYSA9IDUwMDsKICAgIHQuaWFjdXRlID0gMjc4OwogICAgdC5sb3plbmdlID0gNDcxOwogICAgdC5SY2Fyb24gPSA3MjI7CiAgICB0Lkdjb21tYWFjY2VudCA9IDc3ODsKICAgIHQudWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LmFjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5BbWFjcm9uID0gNjY3OwogICAgdC5yY2Fyb24gPSAzMzM7CiAgICB0LmNjZWRpbGxhID0gNTAwOwogICAgdC5aZG90YWNjZW50ID0gNjExOwogICAgdC5UaG9ybiA9IDY2NzsKICAgIHQuT21hY3JvbiA9IDc3ODsKICAgIHQuUmFjdXRlID0gNzIyOwogICAgdC5TYWN1dGUgPSA2Njc7CiAgICB0LmRjYXJvbiA9IDY0MzsKICAgIHQuVW1hY3JvbiA9IDcyMjsKICAgIHQudXJpbmcgPSA1NTY7CiAgICB0LnRocmVlc3VwZXJpb3IgPSAzMzM7CiAgICB0Lk9ncmF2ZSA9IDc3ODsKICAgIHQuQWdyYXZlID0gNjY3OwogICAgdC5BYnJldmUgPSA2Njc7CiAgICB0Lm11bHRpcGx5ID0gNTg0OwogICAgdC51YWN1dGUgPSA1NTY7CiAgICB0LlRjYXJvbiA9IDYxMTsKICAgIHQucGFydGlhbGRpZmYgPSA0NzY7CiAgICB0LnlkaWVyZXNpcyA9IDUwMDsKICAgIHQuTmFjdXRlID0gNzIyOwogICAgdC5pY2lyY3VtZmxleCA9IDI3ODsKICAgIHQuRWNpcmN1bWZsZXggPSA2Njc7CiAgICB0LmFkaWVyZXNpcyA9IDU1NjsKICAgIHQuZWRpZXJlc2lzID0gNTU2OwogICAgdC5jYWN1dGUgPSA1MDA7CiAgICB0Lm5hY3V0ZSA9IDU1NjsKICAgIHQudW1hY3JvbiA9IDU1NjsKICAgIHQuTmNhcm9uID0gNzIyOwogICAgdC5JYWN1dGUgPSAyNzg7CiAgICB0LnBsdXNtaW51cyA9IDU4NDsKICAgIHQuYnJva2VuYmFyID0gMjYwOwogICAgdC5yZWdpc3RlcmVkID0gNzM3OwogICAgdC5HYnJldmUgPSA3Nzg7CiAgICB0Lklkb3RhY2NlbnQgPSAyNzg7CiAgICB0LnN1bW1hdGlvbiA9IDYwMDsKICAgIHQuRWdyYXZlID0gNjY3OwogICAgdC5yYWN1dGUgPSAzMzM7CiAgICB0Lm9tYWNyb24gPSA1NTY7CiAgICB0LlphY3V0ZSA9IDYxMTsKICAgIHQuWmNhcm9uID0gNjExOwogICAgdC5ncmVhdGVyZXF1YWwgPSA1NDk7CiAgICB0LkV0aCA9IDcyMjsKICAgIHQuQ2NlZGlsbGEgPSA3MjI7CiAgICB0Lmxjb21tYWFjY2VudCA9IDIyMjsKICAgIHQudGNhcm9uID0gMzE3OwogICAgdC5lb2dvbmVrID0gNTU2OwogICAgdC5Vb2dvbmVrID0gNzIyOwogICAgdC5BYWN1dGUgPSA2Njc7CiAgICB0LkFkaWVyZXNpcyA9IDY2NzsKICAgIHQuZWdyYXZlID0gNTU2OwogICAgdC56YWN1dGUgPSA1MDA7CiAgICB0LmlvZ29uZWsgPSAyMjI7CiAgICB0Lk9hY3V0ZSA9IDc3ODsKICAgIHQub2FjdXRlID0gNTU2OwogICAgdC5hbWFjcm9uID0gNTU2OwogICAgdC5zYWN1dGUgPSA1MDA7CiAgICB0LmlkaWVyZXNpcyA9IDI3ODsKICAgIHQuT2NpcmN1bWZsZXggPSA3Nzg7CiAgICB0LlVncmF2ZSA9IDcyMjsKICAgIHQuRGVsdGEgPSA2MTI7CiAgICB0LnRob3JuID0gNTU2OwogICAgdC50d29zdXBlcmlvciA9IDMzMzsKICAgIHQuT2RpZXJlc2lzID0gNzc4OwogICAgdC5tdSA9IDU1NjsKICAgIHQuaWdyYXZlID0gMjc4OwogICAgdC5vaHVuZ2FydW1sYXV0ID0gNTU2OwogICAgdC5Fb2dvbmVrID0gNjY3OwogICAgdC5kY3JvYXQgPSA1NTY7CiAgICB0LnRocmVlcXVhcnRlcnMgPSA4MzQ7CiAgICB0LlNjZWRpbGxhID0gNjY3OwogICAgdC5sY2Fyb24gPSAyOTk7CiAgICB0Lktjb21tYWFjY2VudCA9IDY2NzsKICAgIHQuTGFjdXRlID0gNTU2OwogICAgdC50cmFkZW1hcmsgPSAxMDAwOwogICAgdC5lZG90YWNjZW50ID0gNTU2OwogICAgdC5JZ3JhdmUgPSAyNzg7CiAgICB0LkltYWNyb24gPSAyNzg7CiAgICB0LkxjYXJvbiA9IDU1NjsKICAgIHQub25laGFsZiA9IDgzNDsKICAgIHQubGVzc2VxdWFsID0gNTQ5OwogICAgdC5vY2lyY3VtZmxleCA9IDU1NjsKICAgIHQubnRpbGRlID0gNTU2OwogICAgdC5VaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5FYWN1dGUgPSA2Njc7CiAgICB0LmVtYWNyb24gPSA1NTY7CiAgICB0LmdicmV2ZSA9IDU1NjsKICAgIHQub25lcXVhcnRlciA9IDgzNDsKICAgIHQuU2Nhcm9uID0gNjY3OwogICAgdC5TY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0Lk9odW5nYXJ1bWxhdXQgPSA3Nzg7CiAgICB0LmRlZ3JlZSA9IDQwMDsKICAgIHQub2dyYXZlID0gNTU2OwogICAgdC5DY2Fyb24gPSA3MjI7CiAgICB0LnVncmF2ZSA9IDU1NjsKICAgIHQucmFkaWNhbCA9IDQ1MzsKICAgIHQuRGNhcm9uID0gNzIyOwogICAgdC5yY29tbWFhY2NlbnQgPSAzMzM7CiAgICB0Lk50aWxkZSA9IDcyMjsKICAgIHQub3RpbGRlID0gNTU2OwogICAgdC5SY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0Lkxjb21tYWFjY2VudCA9IDU1NjsKICAgIHQuQXRpbGRlID0gNjY3OwogICAgdC5Bb2dvbmVrID0gNjY3OwogICAgdC5BcmluZyA9IDY2NzsKICAgIHQuT3RpbGRlID0gNzc4OwogICAgdC56ZG90YWNjZW50ID0gNTAwOwogICAgdC5FY2Fyb24gPSA2Njc7CiAgICB0LklvZ29uZWsgPSAyNzg7CiAgICB0Lmtjb21tYWFjY2VudCA9IDUwMDsKICAgIHQubWludXMgPSA1ODQ7CiAgICB0LkljaXJjdW1mbGV4ID0gMjc4OwogICAgdC5uY2Fyb24gPSA1NTY7CiAgICB0LnRjb21tYWFjY2VudCA9IDI3ODsKICAgIHQubG9naWNhbG5vdCA9IDU4NDsKICAgIHQub2RpZXJlc2lzID0gNTU2OwogICAgdC51ZGllcmVzaXMgPSA1NTY7CiAgICB0Lm5vdGVxdWFsID0gNTQ5OwogICAgdC5nY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0LmV0aCA9IDU1NjsKICAgIHQuemNhcm9uID0gNTAwOwogICAgdC5uY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0Lm9uZXN1cGVyaW9yID0gMzMzOwogICAgdC5pbWFjcm9uID0gMjc4OwogICAgdC5FdXJvID0gNTU2OwogIH0pOwogIHRbIkhlbHZldGljYS1Cb2xkIl0gPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICAgIHQuc3BhY2UgPSAyNzg7CiAgICB0LmV4Y2xhbSA9IDMzMzsKICAgIHQucXVvdGVkYmwgPSA0NzQ7CiAgICB0Lm51bWJlcnNpZ24gPSA1NTY7CiAgICB0LmRvbGxhciA9IDU1NjsKICAgIHQucGVyY2VudCA9IDg4OTsKICAgIHQuYW1wZXJzYW5kID0gNzIyOwogICAgdC5xdW90ZXJpZ2h0ID0gMjc4OwogICAgdC5wYXJlbmxlZnQgPSAzMzM7CiAgICB0LnBhcmVucmlnaHQgPSAzMzM7CiAgICB0LmFzdGVyaXNrID0gMzg5OwogICAgdC5wbHVzID0gNTg0OwogICAgdC5jb21tYSA9IDI3ODsKICAgIHQuaHlwaGVuID0gMzMzOwogICAgdC5wZXJpb2QgPSAyNzg7CiAgICB0LnNsYXNoID0gMjc4OwogICAgdC56ZXJvID0gNTU2OwogICAgdC5vbmUgPSA1NTY7CiAgICB0LnR3byA9IDU1NjsKICAgIHQudGhyZWUgPSA1NTY7CiAgICB0LmZvdXIgPSA1NTY7CiAgICB0LmZpdmUgPSA1NTY7CiAgICB0LnNpeCA9IDU1NjsKICAgIHQuc2V2ZW4gPSA1NTY7CiAgICB0LmVpZ2h0ID0gNTU2OwogICAgdC5uaW5lID0gNTU2OwogICAgdC5jb2xvbiA9IDMzMzsKICAgIHQuc2VtaWNvbG9uID0gMzMzOwogICAgdC5sZXNzID0gNTg0OwogICAgdC5lcXVhbCA9IDU4NDsKICAgIHQuZ3JlYXRlciA9IDU4NDsKICAgIHQucXVlc3Rpb24gPSA2MTE7CiAgICB0LmF0ID0gOTc1OwogICAgdC5BID0gNzIyOwogICAgdC5CID0gNzIyOwogICAgdC5DID0gNzIyOwogICAgdC5EID0gNzIyOwogICAgdC5FID0gNjY3OwogICAgdC5GID0gNjExOwogICAgdC5HID0gNzc4OwogICAgdC5IID0gNzIyOwogICAgdC5JID0gMjc4OwogICAgdC5KID0gNTU2OwogICAgdC5LID0gNzIyOwogICAgdC5MID0gNjExOwogICAgdC5NID0gODMzOwogICAgdC5OID0gNzIyOwogICAgdC5PID0gNzc4OwogICAgdC5QID0gNjY3OwogICAgdC5RID0gNzc4OwogICAgdC5SID0gNzIyOwogICAgdC5TID0gNjY3OwogICAgdC5UID0gNjExOwogICAgdC5VID0gNzIyOwogICAgdC5WID0gNjY3OwogICAgdC5XID0gOTQ0OwogICAgdC5YID0gNjY3OwogICAgdC5ZID0gNjY3OwogICAgdC5aID0gNjExOwogICAgdC5icmFja2V0bGVmdCA9IDMzMzsKICAgIHQuYmFja3NsYXNoID0gMjc4OwogICAgdC5icmFja2V0cmlnaHQgPSAzMzM7CiAgICB0LmFzY2lpY2lyY3VtID0gNTg0OwogICAgdC51bmRlcnNjb3JlID0gNTU2OwogICAgdC5xdW90ZWxlZnQgPSAyNzg7CiAgICB0LmEgPSA1NTY7CiAgICB0LmIgPSA2MTE7CiAgICB0LmMgPSA1NTY7CiAgICB0LmQgPSA2MTE7CiAgICB0LmUgPSA1NTY7CiAgICB0LmYgPSAzMzM7CiAgICB0LmcgPSA2MTE7CiAgICB0LmggPSA2MTE7CiAgICB0LmkgPSAyNzg7CiAgICB0LmogPSAyNzg7CiAgICB0LmsgPSA1NTY7CiAgICB0LmwgPSAyNzg7CiAgICB0Lm0gPSA4ODk7CiAgICB0Lm4gPSA2MTE7CiAgICB0Lm8gPSA2MTE7CiAgICB0LnAgPSA2MTE7CiAgICB0LnEgPSA2MTE7CiAgICB0LnIgPSAzODk7CiAgICB0LnMgPSA1NTY7CiAgICB0LnQgPSAzMzM7CiAgICB0LnUgPSA2MTE7CiAgICB0LnYgPSA1NTY7CiAgICB0LncgPSA3Nzg7CiAgICB0LnggPSA1NTY7CiAgICB0LnkgPSA1NTY7CiAgICB0LnogPSA1MDA7CiAgICB0LmJyYWNlbGVmdCA9IDM4OTsKICAgIHQuYmFyID0gMjgwOwogICAgdC5icmFjZXJpZ2h0ID0gMzg5OwogICAgdC5hc2NpaXRpbGRlID0gNTg0OwogICAgdC5leGNsYW1kb3duID0gMzMzOwogICAgdC5jZW50ID0gNTU2OwogICAgdC5zdGVybGluZyA9IDU1NjsKICAgIHQuZnJhY3Rpb24gPSAxNjc7CiAgICB0LnllbiA9IDU1NjsKICAgIHQuZmxvcmluID0gNTU2OwogICAgdC5zZWN0aW9uID0gNTU2OwogICAgdC5jdXJyZW5jeSA9IDU1NjsKICAgIHQucXVvdGVzaW5nbGUgPSAyMzg7CiAgICB0LnF1b3RlZGJsbGVmdCA9IDUwMDsKICAgIHQuZ3VpbGxlbW90bGVmdCA9IDU1NjsKICAgIHQuZ3VpbHNpbmdsbGVmdCA9IDMzMzsKICAgIHQuZ3VpbHNpbmdscmlnaHQgPSAzMzM7CiAgICB0LmZpID0gNjExOwogICAgdC5mbCA9IDYxMTsKICAgIHQuZW5kYXNoID0gNTU2OwogICAgdC5kYWdnZXIgPSA1NTY7CiAgICB0LmRhZ2dlcmRibCA9IDU1NjsKICAgIHQucGVyaW9kY2VudGVyZWQgPSAyNzg7CiAgICB0LnBhcmFncmFwaCA9IDU1NjsKICAgIHQuYnVsbGV0ID0gMzUwOwogICAgdC5xdW90ZXNpbmdsYmFzZSA9IDI3ODsKICAgIHQucXVvdGVkYmxiYXNlID0gNTAwOwogICAgdC5xdW90ZWRibHJpZ2h0ID0gNTAwOwogICAgdC5ndWlsbGVtb3RyaWdodCA9IDU1NjsKICAgIHQuZWxsaXBzaXMgPSAxMDAwOwogICAgdC5wZXJ0aG91c2FuZCA9IDEwMDA7CiAgICB0LnF1ZXN0aW9uZG93biA9IDYxMTsKICAgIHQuZ3JhdmUgPSAzMzM7CiAgICB0LmFjdXRlID0gMzMzOwogICAgdC5jaXJjdW1mbGV4ID0gMzMzOwogICAgdC50aWxkZSA9IDMzMzsKICAgIHQubWFjcm9uID0gMzMzOwogICAgdC5icmV2ZSA9IDMzMzsKICAgIHQuZG90YWNjZW50ID0gMzMzOwogICAgdC5kaWVyZXNpcyA9IDMzMzsKICAgIHQucmluZyA9IDMzMzsKICAgIHQuY2VkaWxsYSA9IDMzMzsKICAgIHQuaHVuZ2FydW1sYXV0ID0gMzMzOwogICAgdC5vZ29uZWsgPSAzMzM7CiAgICB0LmNhcm9uID0gMzMzOwogICAgdC5lbWRhc2ggPSAxMDAwOwogICAgdC5BRSA9IDEwMDA7CiAgICB0Lm9yZGZlbWluaW5lID0gMzcwOwogICAgdC5Mc2xhc2ggPSA2MTE7CiAgICB0Lk9zbGFzaCA9IDc3ODsKICAgIHQuT0UgPSAxMDAwOwogICAgdC5vcmRtYXNjdWxpbmUgPSAzNjU7CiAgICB0LmFlID0gODg5OwogICAgdC5kb3RsZXNzaSA9IDI3ODsKICAgIHQubHNsYXNoID0gMjc4OwogICAgdC5vc2xhc2ggPSA2MTE7CiAgICB0Lm9lID0gOTQ0OwogICAgdC5nZXJtYW5kYmxzID0gNjExOwogICAgdC5JZGllcmVzaXMgPSAyNzg7CiAgICB0LmVhY3V0ZSA9IDU1NjsKICAgIHQuYWJyZXZlID0gNTU2OwogICAgdC51aHVuZ2FydW1sYXV0ID0gNjExOwogICAgdC5lY2Fyb24gPSA1NTY7CiAgICB0LllkaWVyZXNpcyA9IDY2NzsKICAgIHQuZGl2aWRlID0gNTg0OwogICAgdC5ZYWN1dGUgPSA2Njc7CiAgICB0LkFjaXJjdW1mbGV4ID0gNzIyOwogICAgdC5hYWN1dGUgPSA1NTY7CiAgICB0LlVjaXJjdW1mbGV4ID0gNzIyOwogICAgdC55YWN1dGUgPSA1NTY7CiAgICB0LnNjb21tYWFjY2VudCA9IDU1NjsKICAgIHQuZWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LlVyaW5nID0gNzIyOwogICAgdC5VZGllcmVzaXMgPSA3MjI7CiAgICB0LmFvZ29uZWsgPSA1NTY7CiAgICB0LlVhY3V0ZSA9IDcyMjsKICAgIHQudW9nb25layA9IDYxMTsKICAgIHQuRWRpZXJlc2lzID0gNjY3OwogICAgdC5EY3JvYXQgPSA3MjI7CiAgICB0LmNvbW1hYWNjZW50ID0gMjUwOwogICAgdC5jb3B5cmlnaHQgPSA3Mzc7CiAgICB0LkVtYWNyb24gPSA2Njc7CiAgICB0LmNjYXJvbiA9IDU1NjsKICAgIHQuYXJpbmcgPSA1NTY7CiAgICB0Lk5jb21tYWFjY2VudCA9IDcyMjsKICAgIHQubGFjdXRlID0gMjc4OwogICAgdC5hZ3JhdmUgPSA1NTY7CiAgICB0LlRjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQ2FjdXRlID0gNzIyOwogICAgdC5hdGlsZGUgPSA1NTY7CiAgICB0LkVkb3RhY2NlbnQgPSA2Njc7CiAgICB0LnNjYXJvbiA9IDU1NjsKICAgIHQuc2NlZGlsbGEgPSA1NTY7CiAgICB0LmlhY3V0ZSA9IDI3ODsKICAgIHQubG96ZW5nZSA9IDQ5NDsKICAgIHQuUmNhcm9uID0gNzIyOwogICAgdC5HY29tbWFhY2NlbnQgPSA3Nzg7CiAgICB0LnVjaXJjdW1mbGV4ID0gNjExOwogICAgdC5hY2lyY3VtZmxleCA9IDU1NjsKICAgIHQuQW1hY3JvbiA9IDcyMjsKICAgIHQucmNhcm9uID0gMzg5OwogICAgdC5jY2VkaWxsYSA9IDU1NjsKICAgIHQuWmRvdGFjY2VudCA9IDYxMTsKICAgIHQuVGhvcm4gPSA2Njc7CiAgICB0Lk9tYWNyb24gPSA3Nzg7CiAgICB0LlJhY3V0ZSA9IDcyMjsKICAgIHQuU2FjdXRlID0gNjY3OwogICAgdC5kY2Fyb24gPSA3NDM7CiAgICB0LlVtYWNyb24gPSA3MjI7CiAgICB0LnVyaW5nID0gNjExOwogICAgdC50aHJlZXN1cGVyaW9yID0gMzMzOwogICAgdC5PZ3JhdmUgPSA3Nzg7CiAgICB0LkFncmF2ZSA9IDcyMjsKICAgIHQuQWJyZXZlID0gNzIyOwogICAgdC5tdWx0aXBseSA9IDU4NDsKICAgIHQudWFjdXRlID0gNjExOwogICAgdC5UY2Fyb24gPSA2MTE7CiAgICB0LnBhcnRpYWxkaWZmID0gNDk0OwogICAgdC55ZGllcmVzaXMgPSA1NTY7CiAgICB0Lk5hY3V0ZSA9IDcyMjsKICAgIHQuaWNpcmN1bWZsZXggPSAyNzg7CiAgICB0LkVjaXJjdW1mbGV4ID0gNjY3OwogICAgdC5hZGllcmVzaXMgPSA1NTY7CiAgICB0LmVkaWVyZXNpcyA9IDU1NjsKICAgIHQuY2FjdXRlID0gNTU2OwogICAgdC5uYWN1dGUgPSA2MTE7CiAgICB0LnVtYWNyb24gPSA2MTE7CiAgICB0Lk5jYXJvbiA9IDcyMjsKICAgIHQuSWFjdXRlID0gMjc4OwogICAgdC5wbHVzbWludXMgPSA1ODQ7CiAgICB0LmJyb2tlbmJhciA9IDI4MDsKICAgIHQucmVnaXN0ZXJlZCA9IDczNzsKICAgIHQuR2JyZXZlID0gNzc4OwogICAgdC5JZG90YWNjZW50ID0gMjc4OwogICAgdC5zdW1tYXRpb24gPSA2MDA7CiAgICB0LkVncmF2ZSA9IDY2NzsKICAgIHQucmFjdXRlID0gMzg5OwogICAgdC5vbWFjcm9uID0gNjExOwogICAgdC5aYWN1dGUgPSA2MTE7CiAgICB0LlpjYXJvbiA9IDYxMTsKICAgIHQuZ3JlYXRlcmVxdWFsID0gNTQ5OwogICAgdC5FdGggPSA3MjI7CiAgICB0LkNjZWRpbGxhID0gNzIyOwogICAgdC5sY29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LnRjYXJvbiA9IDM4OTsKICAgIHQuZW9nb25layA9IDU1NjsKICAgIHQuVW9nb25layA9IDcyMjsKICAgIHQuQWFjdXRlID0gNzIyOwogICAgdC5BZGllcmVzaXMgPSA3MjI7CiAgICB0LmVncmF2ZSA9IDU1NjsKICAgIHQuemFjdXRlID0gNTAwOwogICAgdC5pb2dvbmVrID0gMjc4OwogICAgdC5PYWN1dGUgPSA3Nzg7CiAgICB0Lm9hY3V0ZSA9IDYxMTsKICAgIHQuYW1hY3JvbiA9IDU1NjsKICAgIHQuc2FjdXRlID0gNTU2OwogICAgdC5pZGllcmVzaXMgPSAyNzg7CiAgICB0Lk9jaXJjdW1mbGV4ID0gNzc4OwogICAgdC5VZ3JhdmUgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC50aG9ybiA9IDYxMTsKICAgIHQudHdvc3VwZXJpb3IgPSAzMzM7CiAgICB0Lk9kaWVyZXNpcyA9IDc3ODsKICAgIHQubXUgPSA2MTE7CiAgICB0LmlncmF2ZSA9IDI3ODsKICAgIHQub2h1bmdhcnVtbGF1dCA9IDYxMTsKICAgIHQuRW9nb25layA9IDY2NzsKICAgIHQuZGNyb2F0ID0gNjExOwogICAgdC50aHJlZXF1YXJ0ZXJzID0gODM0OwogICAgdC5TY2VkaWxsYSA9IDY2NzsKICAgIHQubGNhcm9uID0gNDAwOwogICAgdC5LY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LkxhY3V0ZSA9IDYxMTsKICAgIHQudHJhZGVtYXJrID0gMTAwMDsKICAgIHQuZWRvdGFjY2VudCA9IDU1NjsKICAgIHQuSWdyYXZlID0gMjc4OwogICAgdC5JbWFjcm9uID0gMjc4OwogICAgdC5MY2Fyb24gPSA2MTE7CiAgICB0Lm9uZWhhbGYgPSA4MzQ7CiAgICB0Lmxlc3NlcXVhbCA9IDU0OTsKICAgIHQub2NpcmN1bWZsZXggPSA2MTE7CiAgICB0Lm50aWxkZSA9IDYxMTsKICAgIHQuVWh1bmdhcnVtbGF1dCA9IDcyMjsKICAgIHQuRWFjdXRlID0gNjY3OwogICAgdC5lbWFjcm9uID0gNTU2OwogICAgdC5nYnJldmUgPSA2MTE7CiAgICB0Lm9uZXF1YXJ0ZXIgPSA4MzQ7CiAgICB0LlNjYXJvbiA9IDY2NzsKICAgIHQuU2NvbW1hYWNjZW50ID0gNjY3OwogICAgdC5PaHVuZ2FydW1sYXV0ID0gNzc4OwogICAgdC5kZWdyZWUgPSA0MDA7CiAgICB0Lm9ncmF2ZSA9IDYxMTsKICAgIHQuQ2Nhcm9uID0gNzIyOwogICAgdC51Z3JhdmUgPSA2MTE7CiAgICB0LnJhZGljYWwgPSA1NDk7CiAgICB0LkRjYXJvbiA9IDcyMjsKICAgIHQucmNvbW1hYWNjZW50ID0gMzg5OwogICAgdC5OdGlsZGUgPSA3MjI7CiAgICB0Lm90aWxkZSA9IDYxMTsKICAgIHQuUmNvbW1hYWNjZW50ID0gNzIyOwogICAgdC5MY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LkF0aWxkZSA9IDcyMjsKICAgIHQuQW9nb25layA9IDcyMjsKICAgIHQuQXJpbmcgPSA3MjI7CiAgICB0Lk90aWxkZSA9IDc3ODsKICAgIHQuemRvdGFjY2VudCA9IDUwMDsKICAgIHQuRWNhcm9uID0gNjY3OwogICAgdC5Jb2dvbmVrID0gMjc4OwogICAgdC5rY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0Lm1pbnVzID0gNTg0OwogICAgdC5JY2lyY3VtZmxleCA9IDI3ODsKICAgIHQubmNhcm9uID0gNjExOwogICAgdC50Y29tbWFhY2NlbnQgPSAzMzM7CiAgICB0LmxvZ2ljYWxub3QgPSA1ODQ7CiAgICB0Lm9kaWVyZXNpcyA9IDYxMTsKICAgIHQudWRpZXJlc2lzID0gNjExOwogICAgdC5ub3RlcXVhbCA9IDU0OTsKICAgIHQuZ2NvbW1hYWNjZW50ID0gNjExOwogICAgdC5ldGggPSA2MTE7CiAgICB0LnpjYXJvbiA9IDUwMDsKICAgIHQubmNvbW1hYWNjZW50ID0gNjExOwogICAgdC5vbmVzdXBlcmlvciA9IDMzMzsKICAgIHQuaW1hY3JvbiA9IDI3ODsKICAgIHQuRXVybyA9IDU1NjsKICB9KTsKICB0WyJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiXSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI3ODsKICAgIHQuZXhjbGFtID0gMzMzOwogICAgdC5xdW90ZWRibCA9IDQ3NDsKICAgIHQubnVtYmVyc2lnbiA9IDU1NjsKICAgIHQuZG9sbGFyID0gNTU2OwogICAgdC5wZXJjZW50ID0gODg5OwogICAgdC5hbXBlcnNhbmQgPSA3MjI7CiAgICB0LnF1b3RlcmlnaHQgPSAyNzg7CiAgICB0LnBhcmVubGVmdCA9IDMzMzsKICAgIHQucGFyZW5yaWdodCA9IDMzMzsKICAgIHQuYXN0ZXJpc2sgPSAzODk7CiAgICB0LnBsdXMgPSA1ODQ7CiAgICB0LmNvbW1hID0gMjc4OwogICAgdC5oeXBoZW4gPSAzMzM7CiAgICB0LnBlcmlvZCA9IDI3ODsKICAgIHQuc2xhc2ggPSAyNzg7CiAgICB0Lnplcm8gPSA1NTY7CiAgICB0Lm9uZSA9IDU1NjsKICAgIHQudHdvID0gNTU2OwogICAgdC50aHJlZSA9IDU1NjsKICAgIHQuZm91ciA9IDU1NjsKICAgIHQuZml2ZSA9IDU1NjsKICAgIHQuc2l4ID0gNTU2OwogICAgdC5zZXZlbiA9IDU1NjsKICAgIHQuZWlnaHQgPSA1NTY7CiAgICB0Lm5pbmUgPSA1NTY7CiAgICB0LmNvbG9uID0gMzMzOwogICAgdC5zZW1pY29sb24gPSAzMzM7CiAgICB0Lmxlc3MgPSA1ODQ7CiAgICB0LmVxdWFsID0gNTg0OwogICAgdC5ncmVhdGVyID0gNTg0OwogICAgdC5xdWVzdGlvbiA9IDYxMTsKICAgIHQuYXQgPSA5NzU7CiAgICB0LkEgPSA3MjI7CiAgICB0LkIgPSA3MjI7CiAgICB0LkMgPSA3MjI7CiAgICB0LkQgPSA3MjI7CiAgICB0LkUgPSA2Njc7CiAgICB0LkYgPSA2MTE7CiAgICB0LkcgPSA3Nzg7CiAgICB0LkggPSA3MjI7CiAgICB0LkkgPSAyNzg7CiAgICB0LkogPSA1NTY7CiAgICB0LksgPSA3MjI7CiAgICB0LkwgPSA2MTE7CiAgICB0Lk0gPSA4MzM7CiAgICB0Lk4gPSA3MjI7CiAgICB0Lk8gPSA3Nzg7CiAgICB0LlAgPSA2Njc7CiAgICB0LlEgPSA3Nzg7CiAgICB0LlIgPSA3MjI7CiAgICB0LlMgPSA2Njc7CiAgICB0LlQgPSA2MTE7CiAgICB0LlUgPSA3MjI7CiAgICB0LlYgPSA2Njc7CiAgICB0LlcgPSA5NDQ7CiAgICB0LlggPSA2Njc7CiAgICB0LlkgPSA2Njc7CiAgICB0LlogPSA2MTE7CiAgICB0LmJyYWNrZXRsZWZ0ID0gMzMzOwogICAgdC5iYWNrc2xhc2ggPSAyNzg7CiAgICB0LmJyYWNrZXRyaWdodCA9IDMzMzsKICAgIHQuYXNjaWljaXJjdW0gPSA1ODQ7CiAgICB0LnVuZGVyc2NvcmUgPSA1NTY7CiAgICB0LnF1b3RlbGVmdCA9IDI3ODsKICAgIHQuYSA9IDU1NjsKICAgIHQuYiA9IDYxMTsKICAgIHQuYyA9IDU1NjsKICAgIHQuZCA9IDYxMTsKICAgIHQuZSA9IDU1NjsKICAgIHQuZiA9IDMzMzsKICAgIHQuZyA9IDYxMTsKICAgIHQuaCA9IDYxMTsKICAgIHQuaSA9IDI3ODsKICAgIHQuaiA9IDI3ODsKICAgIHQuayA9IDU1NjsKICAgIHQubCA9IDI3ODsKICAgIHQubSA9IDg4OTsKICAgIHQubiA9IDYxMTsKICAgIHQubyA9IDYxMTsKICAgIHQucCA9IDYxMTsKICAgIHQucSA9IDYxMTsKICAgIHQuciA9IDM4OTsKICAgIHQucyA9IDU1NjsKICAgIHQudCA9IDMzMzsKICAgIHQudSA9IDYxMTsKICAgIHQudiA9IDU1NjsKICAgIHQudyA9IDc3ODsKICAgIHQueCA9IDU1NjsKICAgIHQueSA9IDU1NjsKICAgIHQueiA9IDUwMDsKICAgIHQuYnJhY2VsZWZ0ID0gMzg5OwogICAgdC5iYXIgPSAyODA7CiAgICB0LmJyYWNlcmlnaHQgPSAzODk7CiAgICB0LmFzY2lpdGlsZGUgPSA1ODQ7CiAgICB0LmV4Y2xhbWRvd24gPSAzMzM7CiAgICB0LmNlbnQgPSA1NTY7CiAgICB0LnN0ZXJsaW5nID0gNTU2OwogICAgdC5mcmFjdGlvbiA9IDE2NzsKICAgIHQueWVuID0gNTU2OwogICAgdC5mbG9yaW4gPSA1NTY7CiAgICB0LnNlY3Rpb24gPSA1NTY7CiAgICB0LmN1cnJlbmN5ID0gNTU2OwogICAgdC5xdW90ZXNpbmdsZSA9IDIzODsKICAgIHQucXVvdGVkYmxsZWZ0ID0gNTAwOwogICAgdC5ndWlsbGVtb3RsZWZ0ID0gNTU2OwogICAgdC5ndWlsc2luZ2xsZWZ0ID0gMzMzOwogICAgdC5ndWlsc2luZ2xyaWdodCA9IDMzMzsKICAgIHQuZmkgPSA2MTE7CiAgICB0LmZsID0gNjExOwogICAgdC5lbmRhc2ggPSA1NTY7CiAgICB0LmRhZ2dlciA9IDU1NjsKICAgIHQuZGFnZ2VyZGJsID0gNTU2OwogICAgdC5wZXJpb2RjZW50ZXJlZCA9IDI3ODsKICAgIHQucGFyYWdyYXBoID0gNTU2OwogICAgdC5idWxsZXQgPSAzNTA7CiAgICB0LnF1b3Rlc2luZ2xiYXNlID0gMjc4OwogICAgdC5xdW90ZWRibGJhc2UgPSA1MDA7CiAgICB0LnF1b3RlZGJscmlnaHQgPSA1MDA7CiAgICB0Lmd1aWxsZW1vdHJpZ2h0ID0gNTU2OwogICAgdC5lbGxpcHNpcyA9IDEwMDA7CiAgICB0LnBlcnRob3VzYW5kID0gMTAwMDsKICAgIHQucXVlc3Rpb25kb3duID0gNjExOwogICAgdC5ncmF2ZSA9IDMzMzsKICAgIHQuYWN1dGUgPSAzMzM7CiAgICB0LmNpcmN1bWZsZXggPSAzMzM7CiAgICB0LnRpbGRlID0gMzMzOwogICAgdC5tYWNyb24gPSAzMzM7CiAgICB0LmJyZXZlID0gMzMzOwogICAgdC5kb3RhY2NlbnQgPSAzMzM7CiAgICB0LmRpZXJlc2lzID0gMzMzOwogICAgdC5yaW5nID0gMzMzOwogICAgdC5jZWRpbGxhID0gMzMzOwogICAgdC5odW5nYXJ1bWxhdXQgPSAzMzM7CiAgICB0Lm9nb25layA9IDMzMzsKICAgIHQuY2Fyb24gPSAzMzM7CiAgICB0LmVtZGFzaCA9IDEwMDA7CiAgICB0LkFFID0gMTAwMDsKICAgIHQub3JkZmVtaW5pbmUgPSAzNzA7CiAgICB0LkxzbGFzaCA9IDYxMTsKICAgIHQuT3NsYXNoID0gNzc4OwogICAgdC5PRSA9IDEwMDA7CiAgICB0Lm9yZG1hc2N1bGluZSA9IDM2NTsKICAgIHQuYWUgPSA4ODk7CiAgICB0LmRvdGxlc3NpID0gMjc4OwogICAgdC5sc2xhc2ggPSAyNzg7CiAgICB0Lm9zbGFzaCA9IDYxMTsKICAgIHQub2UgPSA5NDQ7CiAgICB0Lmdlcm1hbmRibHMgPSA2MTE7CiAgICB0LklkaWVyZXNpcyA9IDI3ODsKICAgIHQuZWFjdXRlID0gNTU2OwogICAgdC5hYnJldmUgPSA1NTY7CiAgICB0LnVodW5nYXJ1bWxhdXQgPSA2MTE7CiAgICB0LmVjYXJvbiA9IDU1NjsKICAgIHQuWWRpZXJlc2lzID0gNjY3OwogICAgdC5kaXZpZGUgPSA1ODQ7CiAgICB0LllhY3V0ZSA9IDY2NzsKICAgIHQuQWNpcmN1bWZsZXggPSA3MjI7CiAgICB0LmFhY3V0ZSA9IDU1NjsKICAgIHQuVWNpcmN1bWZsZXggPSA3MjI7CiAgICB0LnlhY3V0ZSA9IDU1NjsKICAgIHQuc2NvbW1hYWNjZW50ID0gNTU2OwogICAgdC5lY2lyY3VtZmxleCA9IDU1NjsKICAgIHQuVXJpbmcgPSA3MjI7CiAgICB0LlVkaWVyZXNpcyA9IDcyMjsKICAgIHQuYW9nb25layA9IDU1NjsKICAgIHQuVWFjdXRlID0gNzIyOwogICAgdC51b2dvbmVrID0gNjExOwogICAgdC5FZGllcmVzaXMgPSA2Njc7CiAgICB0LkRjcm9hdCA9IDcyMjsKICAgIHQuY29tbWFhY2NlbnQgPSAyNTA7CiAgICB0LmNvcHlyaWdodCA9IDczNzsKICAgIHQuRW1hY3JvbiA9IDY2NzsKICAgIHQuY2Nhcm9uID0gNTU2OwogICAgdC5hcmluZyA9IDU1NjsKICAgIHQuTmNvbW1hYWNjZW50ID0gNzIyOwogICAgdC5sYWN1dGUgPSAyNzg7CiAgICB0LmFncmF2ZSA9IDU1NjsKICAgIHQuVGNvbW1hYWNjZW50ID0gNjExOwogICAgdC5DYWN1dGUgPSA3MjI7CiAgICB0LmF0aWxkZSA9IDU1NjsKICAgIHQuRWRvdGFjY2VudCA9IDY2NzsKICAgIHQuc2Nhcm9uID0gNTU2OwogICAgdC5zY2VkaWxsYSA9IDU1NjsKICAgIHQuaWFjdXRlID0gMjc4OwogICAgdC5sb3plbmdlID0gNDk0OwogICAgdC5SY2Fyb24gPSA3MjI7CiAgICB0Lkdjb21tYWFjY2VudCA9IDc3ODsKICAgIHQudWNpcmN1bWZsZXggPSA2MTE7CiAgICB0LmFjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5BbWFjcm9uID0gNzIyOwogICAgdC5yY2Fyb24gPSAzODk7CiAgICB0LmNjZWRpbGxhID0gNTU2OwogICAgdC5aZG90YWNjZW50ID0gNjExOwogICAgdC5UaG9ybiA9IDY2NzsKICAgIHQuT21hY3JvbiA9IDc3ODsKICAgIHQuUmFjdXRlID0gNzIyOwogICAgdC5TYWN1dGUgPSA2Njc7CiAgICB0LmRjYXJvbiA9IDc0MzsKICAgIHQuVW1hY3JvbiA9IDcyMjsKICAgIHQudXJpbmcgPSA2MTE7CiAgICB0LnRocmVlc3VwZXJpb3IgPSAzMzM7CiAgICB0Lk9ncmF2ZSA9IDc3ODsKICAgIHQuQWdyYXZlID0gNzIyOwogICAgdC5BYnJldmUgPSA3MjI7CiAgICB0Lm11bHRpcGx5ID0gNTg0OwogICAgdC51YWN1dGUgPSA2MTE7CiAgICB0LlRjYXJvbiA9IDYxMTsKICAgIHQucGFydGlhbGRpZmYgPSA0OTQ7CiAgICB0LnlkaWVyZXNpcyA9IDU1NjsKICAgIHQuTmFjdXRlID0gNzIyOwogICAgdC5pY2lyY3VtZmxleCA9IDI3ODsKICAgIHQuRWNpcmN1bWZsZXggPSA2Njc7CiAgICB0LmFkaWVyZXNpcyA9IDU1NjsKICAgIHQuZWRpZXJlc2lzID0gNTU2OwogICAgdC5jYWN1dGUgPSA1NTY7CiAgICB0Lm5hY3V0ZSA9IDYxMTsKICAgIHQudW1hY3JvbiA9IDYxMTsKICAgIHQuTmNhcm9uID0gNzIyOwogICAgdC5JYWN1dGUgPSAyNzg7CiAgICB0LnBsdXNtaW51cyA9IDU4NDsKICAgIHQuYnJva2VuYmFyID0gMjgwOwogICAgdC5yZWdpc3RlcmVkID0gNzM3OwogICAgdC5HYnJldmUgPSA3Nzg7CiAgICB0Lklkb3RhY2NlbnQgPSAyNzg7CiAgICB0LnN1bW1hdGlvbiA9IDYwMDsKICAgIHQuRWdyYXZlID0gNjY3OwogICAgdC5yYWN1dGUgPSAzODk7CiAgICB0Lm9tYWNyb24gPSA2MTE7CiAgICB0LlphY3V0ZSA9IDYxMTsKICAgIHQuWmNhcm9uID0gNjExOwogICAgdC5ncmVhdGVyZXF1YWwgPSA1NDk7CiAgICB0LkV0aCA9IDcyMjsKICAgIHQuQ2NlZGlsbGEgPSA3MjI7CiAgICB0Lmxjb21tYWFjY2VudCA9IDI3ODsKICAgIHQudGNhcm9uID0gMzg5OwogICAgdC5lb2dvbmVrID0gNTU2OwogICAgdC5Vb2dvbmVrID0gNzIyOwogICAgdC5BYWN1dGUgPSA3MjI7CiAgICB0LkFkaWVyZXNpcyA9IDcyMjsKICAgIHQuZWdyYXZlID0gNTU2OwogICAgdC56YWN1dGUgPSA1MDA7CiAgICB0LmlvZ29uZWsgPSAyNzg7CiAgICB0Lk9hY3V0ZSA9IDc3ODsKICAgIHQub2FjdXRlID0gNjExOwogICAgdC5hbWFjcm9uID0gNTU2OwogICAgdC5zYWN1dGUgPSA1NTY7CiAgICB0LmlkaWVyZXNpcyA9IDI3ODsKICAgIHQuT2NpcmN1bWZsZXggPSA3Nzg7CiAgICB0LlVncmF2ZSA9IDcyMjsKICAgIHQuRGVsdGEgPSA2MTI7CiAgICB0LnRob3JuID0gNjExOwogICAgdC50d29zdXBlcmlvciA9IDMzMzsKICAgIHQuT2RpZXJlc2lzID0gNzc4OwogICAgdC5tdSA9IDYxMTsKICAgIHQuaWdyYXZlID0gMjc4OwogICAgdC5vaHVuZ2FydW1sYXV0ID0gNjExOwogICAgdC5Fb2dvbmVrID0gNjY3OwogICAgdC5kY3JvYXQgPSA2MTE7CiAgICB0LnRocmVlcXVhcnRlcnMgPSA4MzQ7CiAgICB0LlNjZWRpbGxhID0gNjY3OwogICAgdC5sY2Fyb24gPSA0MDA7CiAgICB0Lktjb21tYWFjY2VudCA9IDcyMjsKICAgIHQuTGFjdXRlID0gNjExOwogICAgdC50cmFkZW1hcmsgPSAxMDAwOwogICAgdC5lZG90YWNjZW50ID0gNTU2OwogICAgdC5JZ3JhdmUgPSAyNzg7CiAgICB0LkltYWNyb24gPSAyNzg7CiAgICB0LkxjYXJvbiA9IDYxMTsKICAgIHQub25laGFsZiA9IDgzNDsKICAgIHQubGVzc2VxdWFsID0gNTQ5OwogICAgdC5vY2lyY3VtZmxleCA9IDYxMTsKICAgIHQubnRpbGRlID0gNjExOwogICAgdC5VaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5FYWN1dGUgPSA2Njc7CiAgICB0LmVtYWNyb24gPSA1NTY7CiAgICB0LmdicmV2ZSA9IDYxMTsKICAgIHQub25lcXVhcnRlciA9IDgzNDsKICAgIHQuU2Nhcm9uID0gNjY3OwogICAgdC5TY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0Lk9odW5nYXJ1bWxhdXQgPSA3Nzg7CiAgICB0LmRlZ3JlZSA9IDQwMDsKICAgIHQub2dyYXZlID0gNjExOwogICAgdC5DY2Fyb24gPSA3MjI7CiAgICB0LnVncmF2ZSA9IDYxMTsKICAgIHQucmFkaWNhbCA9IDU0OTsKICAgIHQuRGNhcm9uID0gNzIyOwogICAgdC5yY29tbWFhY2NlbnQgPSAzODk7CiAgICB0Lk50aWxkZSA9IDcyMjsKICAgIHQub3RpbGRlID0gNjExOwogICAgdC5SY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0Lkxjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQXRpbGRlID0gNzIyOwogICAgdC5Bb2dvbmVrID0gNzIyOwogICAgdC5BcmluZyA9IDcyMjsKICAgIHQuT3RpbGRlID0gNzc4OwogICAgdC56ZG90YWNjZW50ID0gNTAwOwogICAgdC5FY2Fyb24gPSA2Njc7CiAgICB0LklvZ29uZWsgPSAyNzg7CiAgICB0Lmtjb21tYWFjY2VudCA9IDU1NjsKICAgIHQubWludXMgPSA1ODQ7CiAgICB0LkljaXJjdW1mbGV4ID0gMjc4OwogICAgdC5uY2Fyb24gPSA2MTE7CiAgICB0LnRjb21tYWFjY2VudCA9IDMzMzsKICAgIHQubG9naWNhbG5vdCA9IDU4NDsKICAgIHQub2RpZXJlc2lzID0gNjExOwogICAgdC51ZGllcmVzaXMgPSA2MTE7CiAgICB0Lm5vdGVxdWFsID0gNTQ5OwogICAgdC5nY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LmV0aCA9IDYxMTsKICAgIHQuemNhcm9uID0gNTAwOwogICAgdC5uY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0Lm9uZXN1cGVyaW9yID0gMzMzOwogICAgdC5pbWFjcm9uID0gMjc4OwogICAgdC5FdXJvID0gNTU2OwogIH0pOwogIHRbIkhlbHZldGljYS1PYmxpcXVlIl0gPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICAgIHQuc3BhY2UgPSAyNzg7CiAgICB0LmV4Y2xhbSA9IDI3ODsKICAgIHQucXVvdGVkYmwgPSAzNTU7CiAgICB0Lm51bWJlcnNpZ24gPSA1NTY7CiAgICB0LmRvbGxhciA9IDU1NjsKICAgIHQucGVyY2VudCA9IDg4OTsKICAgIHQuYW1wZXJzYW5kID0gNjY3OwogICAgdC5xdW90ZXJpZ2h0ID0gMjIyOwogICAgdC5wYXJlbmxlZnQgPSAzMzM7CiAgICB0LnBhcmVucmlnaHQgPSAzMzM7CiAgICB0LmFzdGVyaXNrID0gMzg5OwogICAgdC5wbHVzID0gNTg0OwogICAgdC5jb21tYSA9IDI3ODsKICAgIHQuaHlwaGVuID0gMzMzOwogICAgdC5wZXJpb2QgPSAyNzg7CiAgICB0LnNsYXNoID0gMjc4OwogICAgdC56ZXJvID0gNTU2OwogICAgdC5vbmUgPSA1NTY7CiAgICB0LnR3byA9IDU1NjsKICAgIHQudGhyZWUgPSA1NTY7CiAgICB0LmZvdXIgPSA1NTY7CiAgICB0LmZpdmUgPSA1NTY7CiAgICB0LnNpeCA9IDU1NjsKICAgIHQuc2V2ZW4gPSA1NTY7CiAgICB0LmVpZ2h0ID0gNTU2OwogICAgdC5uaW5lID0gNTU2OwogICAgdC5jb2xvbiA9IDI3ODsKICAgIHQuc2VtaWNvbG9uID0gMjc4OwogICAgdC5sZXNzID0gNTg0OwogICAgdC5lcXVhbCA9IDU4NDsKICAgIHQuZ3JlYXRlciA9IDU4NDsKICAgIHQucXVlc3Rpb24gPSA1NTY7CiAgICB0LmF0ID0gMTAxNTsKICAgIHQuQSA9IDY2NzsKICAgIHQuQiA9IDY2NzsKICAgIHQuQyA9IDcyMjsKICAgIHQuRCA9IDcyMjsKICAgIHQuRSA9IDY2NzsKICAgIHQuRiA9IDYxMTsKICAgIHQuRyA9IDc3ODsKICAgIHQuSCA9IDcyMjsKICAgIHQuSSA9IDI3ODsKICAgIHQuSiA9IDUwMDsKICAgIHQuSyA9IDY2NzsKICAgIHQuTCA9IDU1NjsKICAgIHQuTSA9IDgzMzsKICAgIHQuTiA9IDcyMjsKICAgIHQuTyA9IDc3ODsKICAgIHQuUCA9IDY2NzsKICAgIHQuUSA9IDc3ODsKICAgIHQuUiA9IDcyMjsKICAgIHQuUyA9IDY2NzsKICAgIHQuVCA9IDYxMTsKICAgIHQuVSA9IDcyMjsKICAgIHQuViA9IDY2NzsKICAgIHQuVyA9IDk0NDsKICAgIHQuWCA9IDY2NzsKICAgIHQuWSA9IDY2NzsKICAgIHQuWiA9IDYxMTsKICAgIHQuYnJhY2tldGxlZnQgPSAyNzg7CiAgICB0LmJhY2tzbGFzaCA9IDI3ODsKICAgIHQuYnJhY2tldHJpZ2h0ID0gMjc4OwogICAgdC5hc2NpaWNpcmN1bSA9IDQ2OTsKICAgIHQudW5kZXJzY29yZSA9IDU1NjsKICAgIHQucXVvdGVsZWZ0ID0gMjIyOwogICAgdC5hID0gNTU2OwogICAgdC5iID0gNTU2OwogICAgdC5jID0gNTAwOwogICAgdC5kID0gNTU2OwogICAgdC5lID0gNTU2OwogICAgdC5mID0gMjc4OwogICAgdC5nID0gNTU2OwogICAgdC5oID0gNTU2OwogICAgdC5pID0gMjIyOwogICAgdC5qID0gMjIyOwogICAgdC5rID0gNTAwOwogICAgdC5sID0gMjIyOwogICAgdC5tID0gODMzOwogICAgdC5uID0gNTU2OwogICAgdC5vID0gNTU2OwogICAgdC5wID0gNTU2OwogICAgdC5xID0gNTU2OwogICAgdC5yID0gMzMzOwogICAgdC5zID0gNTAwOwogICAgdC50ID0gMjc4OwogICAgdC51ID0gNTU2OwogICAgdC52ID0gNTAwOwogICAgdC53ID0gNzIyOwogICAgdC54ID0gNTAwOwogICAgdC55ID0gNTAwOwogICAgdC56ID0gNTAwOwogICAgdC5icmFjZWxlZnQgPSAzMzQ7CiAgICB0LmJhciA9IDI2MDsKICAgIHQuYnJhY2VyaWdodCA9IDMzNDsKICAgIHQuYXNjaWl0aWxkZSA9IDU4NDsKICAgIHQuZXhjbGFtZG93biA9IDMzMzsKICAgIHQuY2VudCA9IDU1NjsKICAgIHQuc3RlcmxpbmcgPSA1NTY7CiAgICB0LmZyYWN0aW9uID0gMTY3OwogICAgdC55ZW4gPSA1NTY7CiAgICB0LmZsb3JpbiA9IDU1NjsKICAgIHQuc2VjdGlvbiA9IDU1NjsKICAgIHQuY3VycmVuY3kgPSA1NTY7CiAgICB0LnF1b3Rlc2luZ2xlID0gMTkxOwogICAgdC5xdW90ZWRibGxlZnQgPSAzMzM7CiAgICB0Lmd1aWxsZW1vdGxlZnQgPSA1NTY7CiAgICB0Lmd1aWxzaW5nbGxlZnQgPSAzMzM7CiAgICB0Lmd1aWxzaW5nbHJpZ2h0ID0gMzMzOwogICAgdC5maSA9IDUwMDsKICAgIHQuZmwgPSA1MDA7CiAgICB0LmVuZGFzaCA9IDU1NjsKICAgIHQuZGFnZ2VyID0gNTU2OwogICAgdC5kYWdnZXJkYmwgPSA1NTY7CiAgICB0LnBlcmlvZGNlbnRlcmVkID0gMjc4OwogICAgdC5wYXJhZ3JhcGggPSA1Mzc7CiAgICB0LmJ1bGxldCA9IDM1MDsKICAgIHQucXVvdGVzaW5nbGJhc2UgPSAyMjI7CiAgICB0LnF1b3RlZGJsYmFzZSA9IDMzMzsKICAgIHQucXVvdGVkYmxyaWdodCA9IDMzMzsKICAgIHQuZ3VpbGxlbW90cmlnaHQgPSA1NTY7CiAgICB0LmVsbGlwc2lzID0gMTAwMDsKICAgIHQucGVydGhvdXNhbmQgPSAxMDAwOwogICAgdC5xdWVzdGlvbmRvd24gPSA2MTE7CiAgICB0LmdyYXZlID0gMzMzOwogICAgdC5hY3V0ZSA9IDMzMzsKICAgIHQuY2lyY3VtZmxleCA9IDMzMzsKICAgIHQudGlsZGUgPSAzMzM7CiAgICB0Lm1hY3JvbiA9IDMzMzsKICAgIHQuYnJldmUgPSAzMzM7CiAgICB0LmRvdGFjY2VudCA9IDMzMzsKICAgIHQuZGllcmVzaXMgPSAzMzM7CiAgICB0LnJpbmcgPSAzMzM7CiAgICB0LmNlZGlsbGEgPSAzMzM7CiAgICB0Lmh1bmdhcnVtbGF1dCA9IDMzMzsKICAgIHQub2dvbmVrID0gMzMzOwogICAgdC5jYXJvbiA9IDMzMzsKICAgIHQuZW1kYXNoID0gMTAwMDsKICAgIHQuQUUgPSAxMDAwOwogICAgdC5vcmRmZW1pbmluZSA9IDM3MDsKICAgIHQuTHNsYXNoID0gNTU2OwogICAgdC5Pc2xhc2ggPSA3Nzg7CiAgICB0Lk9FID0gMTAwMDsKICAgIHQub3JkbWFzY3VsaW5lID0gMzY1OwogICAgdC5hZSA9IDg4OTsKICAgIHQuZG90bGVzc2kgPSAyNzg7CiAgICB0LmxzbGFzaCA9IDIyMjsKICAgIHQub3NsYXNoID0gNjExOwogICAgdC5vZSA9IDk0NDsKICAgIHQuZ2VybWFuZGJscyA9IDYxMTsKICAgIHQuSWRpZXJlc2lzID0gMjc4OwogICAgdC5lYWN1dGUgPSA1NTY7CiAgICB0LmFicmV2ZSA9IDU1NjsKICAgIHQudWh1bmdhcnVtbGF1dCA9IDU1NjsKICAgIHQuZWNhcm9uID0gNTU2OwogICAgdC5ZZGllcmVzaXMgPSA2Njc7CiAgICB0LmRpdmlkZSA9IDU4NDsKICAgIHQuWWFjdXRlID0gNjY3OwogICAgdC5BY2lyY3VtZmxleCA9IDY2NzsKICAgIHQuYWFjdXRlID0gNTU2OwogICAgdC5VY2lyY3VtZmxleCA9IDcyMjsKICAgIHQueWFjdXRlID0gNTAwOwogICAgdC5zY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0LmVjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5VcmluZyA9IDcyMjsKICAgIHQuVWRpZXJlc2lzID0gNzIyOwogICAgdC5hb2dvbmVrID0gNTU2OwogICAgdC5VYWN1dGUgPSA3MjI7CiAgICB0LnVvZ29uZWsgPSA1NTY7CiAgICB0LkVkaWVyZXNpcyA9IDY2NzsKICAgIHQuRGNyb2F0ID0gNzIyOwogICAgdC5jb21tYWFjY2VudCA9IDI1MDsKICAgIHQuY29weXJpZ2h0ID0gNzM3OwogICAgdC5FbWFjcm9uID0gNjY3OwogICAgdC5jY2Fyb24gPSA1MDA7CiAgICB0LmFyaW5nID0gNTU2OwogICAgdC5OY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LmxhY3V0ZSA9IDIyMjsKICAgIHQuYWdyYXZlID0gNTU2OwogICAgdC5UY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LkNhY3V0ZSA9IDcyMjsKICAgIHQuYXRpbGRlID0gNTU2OwogICAgdC5FZG90YWNjZW50ID0gNjY3OwogICAgdC5zY2Fyb24gPSA1MDA7CiAgICB0LnNjZWRpbGxhID0gNTAwOwogICAgdC5pYWN1dGUgPSAyNzg7CiAgICB0LmxvemVuZ2UgPSA0NzE7CiAgICB0LlJjYXJvbiA9IDcyMjsKICAgIHQuR2NvbW1hYWNjZW50ID0gNzc4OwogICAgdC51Y2lyY3VtZmxleCA9IDU1NjsKICAgIHQuYWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LkFtYWNyb24gPSA2Njc7CiAgICB0LnJjYXJvbiA9IDMzMzsKICAgIHQuY2NlZGlsbGEgPSA1MDA7CiAgICB0Llpkb3RhY2NlbnQgPSA2MTE7CiAgICB0LlRob3JuID0gNjY3OwogICAgdC5PbWFjcm9uID0gNzc4OwogICAgdC5SYWN1dGUgPSA3MjI7CiAgICB0LlNhY3V0ZSA9IDY2NzsKICAgIHQuZGNhcm9uID0gNjQzOwogICAgdC5VbWFjcm9uID0gNzIyOwogICAgdC51cmluZyA9IDU1NjsKICAgIHQudGhyZWVzdXBlcmlvciA9IDMzMzsKICAgIHQuT2dyYXZlID0gNzc4OwogICAgdC5BZ3JhdmUgPSA2Njc7CiAgICB0LkFicmV2ZSA9IDY2NzsKICAgIHQubXVsdGlwbHkgPSA1ODQ7CiAgICB0LnVhY3V0ZSA9IDU1NjsKICAgIHQuVGNhcm9uID0gNjExOwogICAgdC5wYXJ0aWFsZGlmZiA9IDQ3NjsKICAgIHQueWRpZXJlc2lzID0gNTAwOwogICAgdC5OYWN1dGUgPSA3MjI7CiAgICB0LmljaXJjdW1mbGV4ID0gMjc4OwogICAgdC5FY2lyY3VtZmxleCA9IDY2NzsKICAgIHQuYWRpZXJlc2lzID0gNTU2OwogICAgdC5lZGllcmVzaXMgPSA1NTY7CiAgICB0LmNhY3V0ZSA9IDUwMDsKICAgIHQubmFjdXRlID0gNTU2OwogICAgdC51bWFjcm9uID0gNTU2OwogICAgdC5OY2Fyb24gPSA3MjI7CiAgICB0LklhY3V0ZSA9IDI3ODsKICAgIHQucGx1c21pbnVzID0gNTg0OwogICAgdC5icm9rZW5iYXIgPSAyNjA7CiAgICB0LnJlZ2lzdGVyZWQgPSA3Mzc7CiAgICB0LkdicmV2ZSA9IDc3ODsKICAgIHQuSWRvdGFjY2VudCA9IDI3ODsKICAgIHQuc3VtbWF0aW9uID0gNjAwOwogICAgdC5FZ3JhdmUgPSA2Njc7CiAgICB0LnJhY3V0ZSA9IDMzMzsKICAgIHQub21hY3JvbiA9IDU1NjsKICAgIHQuWmFjdXRlID0gNjExOwogICAgdC5aY2Fyb24gPSA2MTE7CiAgICB0LmdyZWF0ZXJlcXVhbCA9IDU0OTsKICAgIHQuRXRoID0gNzIyOwogICAgdC5DY2VkaWxsYSA9IDcyMjsKICAgIHQubGNvbW1hYWNjZW50ID0gMjIyOwogICAgdC50Y2Fyb24gPSAzMTc7CiAgICB0LmVvZ29uZWsgPSA1NTY7CiAgICB0LlVvZ29uZWsgPSA3MjI7CiAgICB0LkFhY3V0ZSA9IDY2NzsKICAgIHQuQWRpZXJlc2lzID0gNjY3OwogICAgdC5lZ3JhdmUgPSA1NTY7CiAgICB0LnphY3V0ZSA9IDUwMDsKICAgIHQuaW9nb25layA9IDIyMjsKICAgIHQuT2FjdXRlID0gNzc4OwogICAgdC5vYWN1dGUgPSA1NTY7CiAgICB0LmFtYWNyb24gPSA1NTY7CiAgICB0LnNhY3V0ZSA9IDUwMDsKICAgIHQuaWRpZXJlc2lzID0gMjc4OwogICAgdC5PY2lyY3VtZmxleCA9IDc3ODsKICAgIHQuVWdyYXZlID0gNzIyOwogICAgdC5EZWx0YSA9IDYxMjsKICAgIHQudGhvcm4gPSA1NTY7CiAgICB0LnR3b3N1cGVyaW9yID0gMzMzOwogICAgdC5PZGllcmVzaXMgPSA3Nzg7CiAgICB0Lm11ID0gNTU2OwogICAgdC5pZ3JhdmUgPSAyNzg7CiAgICB0Lm9odW5nYXJ1bWxhdXQgPSA1NTY7CiAgICB0LkVvZ29uZWsgPSA2Njc7CiAgICB0LmRjcm9hdCA9IDU1NjsKICAgIHQudGhyZWVxdWFydGVycyA9IDgzNDsKICAgIHQuU2NlZGlsbGEgPSA2Njc7CiAgICB0LmxjYXJvbiA9IDI5OTsKICAgIHQuS2NvbW1hYWNjZW50ID0gNjY3OwogICAgdC5MYWN1dGUgPSA1NTY7CiAgICB0LnRyYWRlbWFyayA9IDEwMDA7CiAgICB0LmVkb3RhY2NlbnQgPSA1NTY7CiAgICB0LklncmF2ZSA9IDI3ODsKICAgIHQuSW1hY3JvbiA9IDI3ODsKICAgIHQuTGNhcm9uID0gNTU2OwogICAgdC5vbmVoYWxmID0gODM0OwogICAgdC5sZXNzZXF1YWwgPSA1NDk7CiAgICB0Lm9jaXJjdW1mbGV4ID0gNTU2OwogICAgdC5udGlsZGUgPSA1NTY7CiAgICB0LlVodW5nYXJ1bWxhdXQgPSA3MjI7CiAgICB0LkVhY3V0ZSA9IDY2NzsKICAgIHQuZW1hY3JvbiA9IDU1NjsKICAgIHQuZ2JyZXZlID0gNTU2OwogICAgdC5vbmVxdWFydGVyID0gODM0OwogICAgdC5TY2Fyb24gPSA2Njc7CiAgICB0LlNjb21tYWFjY2VudCA9IDY2NzsKICAgIHQuT2h1bmdhcnVtbGF1dCA9IDc3ODsKICAgIHQuZGVncmVlID0gNDAwOwogICAgdC5vZ3JhdmUgPSA1NTY7CiAgICB0LkNjYXJvbiA9IDcyMjsKICAgIHQudWdyYXZlID0gNTU2OwogICAgdC5yYWRpY2FsID0gNDUzOwogICAgdC5EY2Fyb24gPSA3MjI7CiAgICB0LnJjb21tYWFjY2VudCA9IDMzMzsKICAgIHQuTnRpbGRlID0gNzIyOwogICAgdC5vdGlsZGUgPSA1NTY7CiAgICB0LlJjb21tYWFjY2VudCA9IDcyMjsKICAgIHQuTGNvbW1hYWNjZW50ID0gNTU2OwogICAgdC5BdGlsZGUgPSA2Njc7CiAgICB0LkFvZ29uZWsgPSA2Njc7CiAgICB0LkFyaW5nID0gNjY3OwogICAgdC5PdGlsZGUgPSA3Nzg7CiAgICB0Lnpkb3RhY2NlbnQgPSA1MDA7CiAgICB0LkVjYXJvbiA9IDY2NzsKICAgIHQuSW9nb25layA9IDI3ODsKICAgIHQua2NvbW1hYWNjZW50ID0gNTAwOwogICAgdC5taW51cyA9IDU4NDsKICAgIHQuSWNpcmN1bWZsZXggPSAyNzg7CiAgICB0Lm5jYXJvbiA9IDU1NjsKICAgIHQudGNvbW1hYWNjZW50ID0gMjc4OwogICAgdC5sb2dpY2Fsbm90ID0gNTg0OwogICAgdC5vZGllcmVzaXMgPSA1NTY7CiAgICB0LnVkaWVyZXNpcyA9IDU1NjsKICAgIHQubm90ZXF1YWwgPSA1NDk7CiAgICB0Lmdjb21tYWFjY2VudCA9IDU1NjsKICAgIHQuZXRoID0gNTU2OwogICAgdC56Y2Fyb24gPSA1MDA7CiAgICB0Lm5jb21tYWFjY2VudCA9IDU1NjsKICAgIHQub25lc3VwZXJpb3IgPSAzMzM7CiAgICB0LmltYWNyb24gPSAyNzg7CiAgICB0LkV1cm8gPSA1NTY7CiAgfSk7CiAgdC5TeW1ib2wgPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICAgIHQuc3BhY2UgPSAyNTA7CiAgICB0LmV4Y2xhbSA9IDMzMzsKICAgIHQudW5pdmVyc2FsID0gNzEzOwogICAgdC5udW1iZXJzaWduID0gNTAwOwogICAgdC5leGlzdGVudGlhbCA9IDU0OTsKICAgIHQucGVyY2VudCA9IDgzMzsKICAgIHQuYW1wZXJzYW5kID0gNzc4OwogICAgdC5zdWNodGhhdCA9IDQzOTsKICAgIHQucGFyZW5sZWZ0ID0gMzMzOwogICAgdC5wYXJlbnJpZ2h0ID0gMzMzOwogICAgdC5hc3Rlcmlza21hdGggPSA1MDA7CiAgICB0LnBsdXMgPSA1NDk7CiAgICB0LmNvbW1hID0gMjUwOwogICAgdC5taW51cyA9IDU0OTsKICAgIHQucGVyaW9kID0gMjUwOwogICAgdC5zbGFzaCA9IDI3ODsKICAgIHQuemVybyA9IDUwMDsKICAgIHQub25lID0gNTAwOwogICAgdC50d28gPSA1MDA7CiAgICB0LnRocmVlID0gNTAwOwogICAgdC5mb3VyID0gNTAwOwogICAgdC5maXZlID0gNTAwOwogICAgdC5zaXggPSA1MDA7CiAgICB0LnNldmVuID0gNTAwOwogICAgdC5laWdodCA9IDUwMDsKICAgIHQubmluZSA9IDUwMDsKICAgIHQuY29sb24gPSAyNzg7CiAgICB0LnNlbWljb2xvbiA9IDI3ODsKICAgIHQubGVzcyA9IDU0OTsKICAgIHQuZXF1YWwgPSA1NDk7CiAgICB0LmdyZWF0ZXIgPSA1NDk7CiAgICB0LnF1ZXN0aW9uID0gNDQ0OwogICAgdC5jb25ncnVlbnQgPSA1NDk7CiAgICB0LkFscGhhID0gNzIyOwogICAgdC5CZXRhID0gNjY3OwogICAgdC5DaGkgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC5FcHNpbG9uID0gNjExOwogICAgdC5QaGkgPSA3NjM7CiAgICB0LkdhbW1hID0gNjAzOwogICAgdC5FdGEgPSA3MjI7CiAgICB0LklvdGEgPSAzMzM7CiAgICB0LnRoZXRhMSA9IDYzMTsKICAgIHQuS2FwcGEgPSA3MjI7CiAgICB0LkxhbWJkYSA9IDY4NjsKICAgIHQuTXUgPSA4ODk7CiAgICB0Lk51ID0gNzIyOwogICAgdC5PbWljcm9uID0gNzIyOwogICAgdC5QaSA9IDc2ODsKICAgIHQuVGhldGEgPSA3NDE7CiAgICB0LlJobyA9IDU1NjsKICAgIHQuU2lnbWEgPSA1OTI7CiAgICB0LlRhdSA9IDYxMTsKICAgIHQuVXBzaWxvbiA9IDY5MDsKICAgIHQuc2lnbWExID0gNDM5OwogICAgdC5PbWVnYSA9IDc2ODsKICAgIHQuWGkgPSA2NDU7CiAgICB0LlBzaSA9IDc5NTsKICAgIHQuWmV0YSA9IDYxMTsKICAgIHQuYnJhY2tldGxlZnQgPSAzMzM7CiAgICB0LnRoZXJlZm9yZSA9IDg2MzsKICAgIHQuYnJhY2tldHJpZ2h0ID0gMzMzOwogICAgdC5wZXJwZW5kaWN1bGFyID0gNjU4OwogICAgdC51bmRlcnNjb3JlID0gNTAwOwogICAgdC5yYWRpY2FsZXggPSA1MDA7CiAgICB0LmFscGhhID0gNjMxOwogICAgdC5iZXRhID0gNTQ5OwogICAgdC5jaGkgPSA1NDk7CiAgICB0LmRlbHRhID0gNDk0OwogICAgdC5lcHNpbG9uID0gNDM5OwogICAgdC5waGkgPSA1MjE7CiAgICB0LmdhbW1hID0gNDExOwogICAgdC5ldGEgPSA2MDM7CiAgICB0LmlvdGEgPSAzMjk7CiAgICB0LnBoaTEgPSA2MDM7CiAgICB0LmthcHBhID0gNTQ5OwogICAgdC5sYW1iZGEgPSA1NDk7CiAgICB0Lm11ID0gNTc2OwogICAgdC5udSA9IDUyMTsKICAgIHQub21pY3JvbiA9IDU0OTsKICAgIHQucGkgPSA1NDk7CiAgICB0LnRoZXRhID0gNTIxOwogICAgdC5yaG8gPSA1NDk7CiAgICB0LnNpZ21hID0gNjAzOwogICAgdC50YXUgPSA0Mzk7CiAgICB0LnVwc2lsb24gPSA1NzY7CiAgICB0Lm9tZWdhMSA9IDcxMzsKICAgIHQub21lZ2EgPSA2ODY7CiAgICB0LnhpID0gNDkzOwogICAgdC5wc2kgPSA2ODY7CiAgICB0LnpldGEgPSA0OTQ7CiAgICB0LmJyYWNlbGVmdCA9IDQ4MDsKICAgIHQuYmFyID0gMjAwOwogICAgdC5icmFjZXJpZ2h0ID0gNDgwOwogICAgdC5zaW1pbGFyID0gNTQ5OwogICAgdC5FdXJvID0gNzUwOwogICAgdC5VcHNpbG9uMSA9IDYyMDsKICAgIHQubWludXRlID0gMjQ3OwogICAgdC5sZXNzZXF1YWwgPSA1NDk7CiAgICB0LmZyYWN0aW9uID0gMTY3OwogICAgdC5pbmZpbml0eSA9IDcxMzsKICAgIHQuZmxvcmluID0gNTAwOwogICAgdC5jbHViID0gNzUzOwogICAgdC5kaWFtb25kID0gNzUzOwogICAgdC5oZWFydCA9IDc1MzsKICAgIHQuc3BhZGUgPSA3NTM7CiAgICB0LmFycm93Ym90aCA9IDEwNDI7CiAgICB0LmFycm93bGVmdCA9IDk4NzsKICAgIHQuYXJyb3d1cCA9IDYwMzsKICAgIHQuYXJyb3dyaWdodCA9IDk4NzsKICAgIHQuYXJyb3dkb3duID0gNjAzOwogICAgdC5kZWdyZWUgPSA0MDA7CiAgICB0LnBsdXNtaW51cyA9IDU0OTsKICAgIHQuc2Vjb25kID0gNDExOwogICAgdC5ncmVhdGVyZXF1YWwgPSA1NDk7CiAgICB0Lm11bHRpcGx5ID0gNTQ5OwogICAgdC5wcm9wb3J0aW9uYWwgPSA3MTM7CiAgICB0LnBhcnRpYWxkaWZmID0gNDk0OwogICAgdC5idWxsZXQgPSA0NjA7CiAgICB0LmRpdmlkZSA9IDU0OTsKICAgIHQubm90ZXF1YWwgPSA1NDk7CiAgICB0LmVxdWl2YWxlbmNlID0gNTQ5OwogICAgdC5hcHByb3hlcXVhbCA9IDU0OTsKICAgIHQuZWxsaXBzaXMgPSAxMDAwOwogICAgdC5hcnJvd3ZlcnRleCA9IDYwMzsKICAgIHQuYXJyb3dob3JpemV4ID0gMTAwMDsKICAgIHQuY2FycmlhZ2VyZXR1cm4gPSA2NTg7CiAgICB0LmFsZXBoID0gODIzOwogICAgdC5JZnJha3R1ciA9IDY4NjsKICAgIHQuUmZyYWt0dXIgPSA3OTU7CiAgICB0LndlaWVyc3RyYXNzID0gOTg3OwogICAgdC5jaXJjbGVtdWx0aXBseSA9IDc2ODsKICAgIHQuY2lyY2xlcGx1cyA9IDc2ODsKICAgIHQuZW1wdHlzZXQgPSA4MjM7CiAgICB0LmludGVyc2VjdGlvbiA9IDc2ODsKICAgIHQudW5pb24gPSA3Njg7CiAgICB0LnByb3BlcnN1cGVyc2V0ID0gNzEzOwogICAgdC5yZWZsZXhzdXBlcnNldCA9IDcxMzsKICAgIHQubm90c3Vic2V0ID0gNzEzOwogICAgdC5wcm9wZXJzdWJzZXQgPSA3MTM7CiAgICB0LnJlZmxleHN1YnNldCA9IDcxMzsKICAgIHQuZWxlbWVudCA9IDcxMzsKICAgIHQubm90ZWxlbWVudCA9IDcxMzsKICAgIHQuYW5nbGUgPSA3Njg7CiAgICB0LmdyYWRpZW50ID0gNzEzOwogICAgdC5yZWdpc3RlcnNlcmlmID0gNzkwOwogICAgdC5jb3B5cmlnaHRzZXJpZiA9IDc5MDsKICAgIHQudHJhZGVtYXJrc2VyaWYgPSA4OTA7CiAgICB0LnByb2R1Y3QgPSA4MjM7CiAgICB0LnJhZGljYWwgPSA1NDk7CiAgICB0LmRvdG1hdGggPSAyNTA7CiAgICB0LmxvZ2ljYWxub3QgPSA3MTM7CiAgICB0LmxvZ2ljYWxhbmQgPSA2MDM7CiAgICB0LmxvZ2ljYWxvciA9IDYwMzsKICAgIHQuYXJyb3dkYmxib3RoID0gMTA0MjsKICAgIHQuYXJyb3dkYmxsZWZ0ID0gOTg3OwogICAgdC5hcnJvd2RibHVwID0gNjAzOwogICAgdC5hcnJvd2RibHJpZ2h0ID0gOTg3OwogICAgdC5hcnJvd2RibGRvd24gPSA2MDM7CiAgICB0LmxvemVuZ2UgPSA0OTQ7CiAgICB0LmFuZ2xlbGVmdCA9IDMyOTsKICAgIHQucmVnaXN0ZXJzYW5zID0gNzkwOwogICAgdC5jb3B5cmlnaHRzYW5zID0gNzkwOwogICAgdC50cmFkZW1hcmtzYW5zID0gNzg2OwogICAgdC5zdW1tYXRpb24gPSA3MTM7CiAgICB0LnBhcmVubGVmdHRwID0gMzg0OwogICAgdC5wYXJlbmxlZnRleCA9IDM4NDsKICAgIHQucGFyZW5sZWZ0YnQgPSAzODQ7CiAgICB0LmJyYWNrZXRsZWZ0dHAgPSAzODQ7CiAgICB0LmJyYWNrZXRsZWZ0ZXggPSAzODQ7CiAgICB0LmJyYWNrZXRsZWZ0YnQgPSAzODQ7CiAgICB0LmJyYWNlbGVmdHRwID0gNDk0OwogICAgdC5icmFjZWxlZnRtaWQgPSA0OTQ7CiAgICB0LmJyYWNlbGVmdGJ0ID0gNDk0OwogICAgdC5icmFjZWV4ID0gNDk0OwogICAgdC5hbmdsZXJpZ2h0ID0gMzI5OwogICAgdC5pbnRlZ3JhbCA9IDI3NDsKICAgIHQuaW50ZWdyYWx0cCA9IDY4NjsKICAgIHQuaW50ZWdyYWxleCA9IDY4NjsKICAgIHQuaW50ZWdyYWxidCA9IDY4NjsKICAgIHQucGFyZW5yaWdodHRwID0gMzg0OwogICAgdC5wYXJlbnJpZ2h0ZXggPSAzODQ7CiAgICB0LnBhcmVucmlnaHRidCA9IDM4NDsKICAgIHQuYnJhY2tldHJpZ2h0dHAgPSAzODQ7CiAgICB0LmJyYWNrZXRyaWdodGV4ID0gMzg0OwogICAgdC5icmFja2V0cmlnaHRidCA9IDM4NDsKICAgIHQuYnJhY2VyaWdodHRwID0gNDk0OwogICAgdC5icmFjZXJpZ2h0bWlkID0gNDk0OwogICAgdC5icmFjZXJpZ2h0YnQgPSA0OTQ7CiAgICB0LmFwcGxlID0gNzkwOwogIH0pOwogIHRbIlRpbWVzLVJvbWFuIl0gPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICAgIHQuc3BhY2UgPSAyNTA7CiAgICB0LmV4Y2xhbSA9IDMzMzsKICAgIHQucXVvdGVkYmwgPSA0MDg7CiAgICB0Lm51bWJlcnNpZ24gPSA1MDA7CiAgICB0LmRvbGxhciA9IDUwMDsKICAgIHQucGVyY2VudCA9IDgzMzsKICAgIHQuYW1wZXJzYW5kID0gNzc4OwogICAgdC5xdW90ZXJpZ2h0ID0gMzMzOwogICAgdC5wYXJlbmxlZnQgPSAzMzM7CiAgICB0LnBhcmVucmlnaHQgPSAzMzM7CiAgICB0LmFzdGVyaXNrID0gNTAwOwogICAgdC5wbHVzID0gNTY0OwogICAgdC5jb21tYSA9IDI1MDsKICAgIHQuaHlwaGVuID0gMzMzOwogICAgdC5wZXJpb2QgPSAyNTA7CiAgICB0LnNsYXNoID0gMjc4OwogICAgdC56ZXJvID0gNTAwOwogICAgdC5vbmUgPSA1MDA7CiAgICB0LnR3byA9IDUwMDsKICAgIHQudGhyZWUgPSA1MDA7CiAgICB0LmZvdXIgPSA1MDA7CiAgICB0LmZpdmUgPSA1MDA7CiAgICB0LnNpeCA9IDUwMDsKICAgIHQuc2V2ZW4gPSA1MDA7CiAgICB0LmVpZ2h0ID0gNTAwOwogICAgdC5uaW5lID0gNTAwOwogICAgdC5jb2xvbiA9IDI3ODsKICAgIHQuc2VtaWNvbG9uID0gMjc4OwogICAgdC5sZXNzID0gNTY0OwogICAgdC5lcXVhbCA9IDU2NDsKICAgIHQuZ3JlYXRlciA9IDU2NDsKICAgIHQucXVlc3Rpb24gPSA0NDQ7CiAgICB0LmF0ID0gOTIxOwogICAgdC5BID0gNzIyOwogICAgdC5CID0gNjY3OwogICAgdC5DID0gNjY3OwogICAgdC5EID0gNzIyOwogICAgdC5FID0gNjExOwogICAgdC5GID0gNTU2OwogICAgdC5HID0gNzIyOwogICAgdC5IID0gNzIyOwogICAgdC5JID0gMzMzOwogICAgdC5KID0gMzg5OwogICAgdC5LID0gNzIyOwogICAgdC5MID0gNjExOwogICAgdC5NID0gODg5OwogICAgdC5OID0gNzIyOwogICAgdC5PID0gNzIyOwogICAgdC5QID0gNTU2OwogICAgdC5RID0gNzIyOwogICAgdC5SID0gNjY3OwogICAgdC5TID0gNTU2OwogICAgdC5UID0gNjExOwogICAgdC5VID0gNzIyOwogICAgdC5WID0gNzIyOwogICAgdC5XID0gOTQ0OwogICAgdC5YID0gNzIyOwogICAgdC5ZID0gNzIyOwogICAgdC5aID0gNjExOwogICAgdC5icmFja2V0bGVmdCA9IDMzMzsKICAgIHQuYmFja3NsYXNoID0gMjc4OwogICAgdC5icmFja2V0cmlnaHQgPSAzMzM7CiAgICB0LmFzY2lpY2lyY3VtID0gNDY5OwogICAgdC51bmRlcnNjb3JlID0gNTAwOwogICAgdC5xdW90ZWxlZnQgPSAzMzM7CiAgICB0LmEgPSA0NDQ7CiAgICB0LmIgPSA1MDA7CiAgICB0LmMgPSA0NDQ7CiAgICB0LmQgPSA1MDA7CiAgICB0LmUgPSA0NDQ7CiAgICB0LmYgPSAzMzM7CiAgICB0LmcgPSA1MDA7CiAgICB0LmggPSA1MDA7CiAgICB0LmkgPSAyNzg7CiAgICB0LmogPSAyNzg7CiAgICB0LmsgPSA1MDA7CiAgICB0LmwgPSAyNzg7CiAgICB0Lm0gPSA3Nzg7CiAgICB0Lm4gPSA1MDA7CiAgICB0Lm8gPSA1MDA7CiAgICB0LnAgPSA1MDA7CiAgICB0LnEgPSA1MDA7CiAgICB0LnIgPSAzMzM7CiAgICB0LnMgPSAzODk7CiAgICB0LnQgPSAyNzg7CiAgICB0LnUgPSA1MDA7CiAgICB0LnYgPSA1MDA7CiAgICB0LncgPSA3MjI7CiAgICB0LnggPSA1MDA7CiAgICB0LnkgPSA1MDA7CiAgICB0LnogPSA0NDQ7CiAgICB0LmJyYWNlbGVmdCA9IDQ4MDsKICAgIHQuYmFyID0gMjAwOwogICAgdC5icmFjZXJpZ2h0ID0gNDgwOwogICAgdC5hc2NpaXRpbGRlID0gNTQxOwogICAgdC5leGNsYW1kb3duID0gMzMzOwogICAgdC5jZW50ID0gNTAwOwogICAgdC5zdGVybGluZyA9IDUwMDsKICAgIHQuZnJhY3Rpb24gPSAxNjc7CiAgICB0LnllbiA9IDUwMDsKICAgIHQuZmxvcmluID0gNTAwOwogICAgdC5zZWN0aW9uID0gNTAwOwogICAgdC5jdXJyZW5jeSA9IDUwMDsKICAgIHQucXVvdGVzaW5nbGUgPSAxODA7CiAgICB0LnF1b3RlZGJsbGVmdCA9IDQ0NDsKICAgIHQuZ3VpbGxlbW90bGVmdCA9IDUwMDsKICAgIHQuZ3VpbHNpbmdsbGVmdCA9IDMzMzsKICAgIHQuZ3VpbHNpbmdscmlnaHQgPSAzMzM7CiAgICB0LmZpID0gNTU2OwogICAgdC5mbCA9IDU1NjsKICAgIHQuZW5kYXNoID0gNTAwOwogICAgdC5kYWdnZXIgPSA1MDA7CiAgICB0LmRhZ2dlcmRibCA9IDUwMDsKICAgIHQucGVyaW9kY2VudGVyZWQgPSAyNTA7CiAgICB0LnBhcmFncmFwaCA9IDQ1MzsKICAgIHQuYnVsbGV0ID0gMzUwOwogICAgdC5xdW90ZXNpbmdsYmFzZSA9IDMzMzsKICAgIHQucXVvdGVkYmxiYXNlID0gNDQ0OwogICAgdC5xdW90ZWRibHJpZ2h0ID0gNDQ0OwogICAgdC5ndWlsbGVtb3RyaWdodCA9IDUwMDsKICAgIHQuZWxsaXBzaXMgPSAxMDAwOwogICAgdC5wZXJ0aG91c2FuZCA9IDEwMDA7CiAgICB0LnF1ZXN0aW9uZG93biA9IDQ0NDsKICAgIHQuZ3JhdmUgPSAzMzM7CiAgICB0LmFjdXRlID0gMzMzOwogICAgdC5jaXJjdW1mbGV4ID0gMzMzOwogICAgdC50aWxkZSA9IDMzMzsKICAgIHQubWFjcm9uID0gMzMzOwogICAgdC5icmV2ZSA9IDMzMzsKICAgIHQuZG90YWNjZW50ID0gMzMzOwogICAgdC5kaWVyZXNpcyA9IDMzMzsKICAgIHQucmluZyA9IDMzMzsKICAgIHQuY2VkaWxsYSA9IDMzMzsKICAgIHQuaHVuZ2FydW1sYXV0ID0gMzMzOwogICAgdC5vZ29uZWsgPSAzMzM7CiAgICB0LmNhcm9uID0gMzMzOwogICAgdC5lbWRhc2ggPSAxMDAwOwogICAgdC5BRSA9IDg4OTsKICAgIHQub3JkZmVtaW5pbmUgPSAyNzY7CiAgICB0LkxzbGFzaCA9IDYxMTsKICAgIHQuT3NsYXNoID0gNzIyOwogICAgdC5PRSA9IDg4OTsKICAgIHQub3JkbWFzY3VsaW5lID0gMzEwOwogICAgdC5hZSA9IDY2NzsKICAgIHQuZG90bGVzc2kgPSAyNzg7CiAgICB0LmxzbGFzaCA9IDI3ODsKICAgIHQub3NsYXNoID0gNTAwOwogICAgdC5vZSA9IDcyMjsKICAgIHQuZ2VybWFuZGJscyA9IDUwMDsKICAgIHQuSWRpZXJlc2lzID0gMzMzOwogICAgdC5lYWN1dGUgPSA0NDQ7CiAgICB0LmFicmV2ZSA9IDQ0NDsKICAgIHQudWh1bmdhcnVtbGF1dCA9IDUwMDsKICAgIHQuZWNhcm9uID0gNDQ0OwogICAgdC5ZZGllcmVzaXMgPSA3MjI7CiAgICB0LmRpdmlkZSA9IDU2NDsKICAgIHQuWWFjdXRlID0gNzIyOwogICAgdC5BY2lyY3VtZmxleCA9IDcyMjsKICAgIHQuYWFjdXRlID0gNDQ0OwogICAgdC5VY2lyY3VtZmxleCA9IDcyMjsKICAgIHQueWFjdXRlID0gNTAwOwogICAgdC5zY29tbWFhY2NlbnQgPSAzODk7CiAgICB0LmVjaXJjdW1mbGV4ID0gNDQ0OwogICAgdC5VcmluZyA9IDcyMjsKICAgIHQuVWRpZXJlc2lzID0gNzIyOwogICAgdC5hb2dvbmVrID0gNDQ0OwogICAgdC5VYWN1dGUgPSA3MjI7CiAgICB0LnVvZ29uZWsgPSA1MDA7CiAgICB0LkVkaWVyZXNpcyA9IDYxMTsKICAgIHQuRGNyb2F0ID0gNzIyOwogICAgdC5jb21tYWFjY2VudCA9IDI1MDsKICAgIHQuY29weXJpZ2h0ID0gNzYwOwogICAgdC5FbWFjcm9uID0gNjExOwogICAgdC5jY2Fyb24gPSA0NDQ7CiAgICB0LmFyaW5nID0gNDQ0OwogICAgdC5OY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LmxhY3V0ZSA9IDI3ODsKICAgIHQuYWdyYXZlID0gNDQ0OwogICAgdC5UY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LkNhY3V0ZSA9IDY2NzsKICAgIHQuYXRpbGRlID0gNDQ0OwogICAgdC5FZG90YWNjZW50ID0gNjExOwogICAgdC5zY2Fyb24gPSAzODk7CiAgICB0LnNjZWRpbGxhID0gMzg5OwogICAgdC5pYWN1dGUgPSAyNzg7CiAgICB0LmxvemVuZ2UgPSA0NzE7CiAgICB0LlJjYXJvbiA9IDY2NzsKICAgIHQuR2NvbW1hYWNjZW50ID0gNzIyOwogICAgdC51Y2lyY3VtZmxleCA9IDUwMDsKICAgIHQuYWNpcmN1bWZsZXggPSA0NDQ7CiAgICB0LkFtYWNyb24gPSA3MjI7CiAgICB0LnJjYXJvbiA9IDMzMzsKICAgIHQuY2NlZGlsbGEgPSA0NDQ7CiAgICB0Llpkb3RhY2NlbnQgPSA2MTE7CiAgICB0LlRob3JuID0gNTU2OwogICAgdC5PbWFjcm9uID0gNzIyOwogICAgdC5SYWN1dGUgPSA2Njc7CiAgICB0LlNhY3V0ZSA9IDU1NjsKICAgIHQuZGNhcm9uID0gNTg4OwogICAgdC5VbWFjcm9uID0gNzIyOwogICAgdC51cmluZyA9IDUwMDsKICAgIHQudGhyZWVzdXBlcmlvciA9IDMwMDsKICAgIHQuT2dyYXZlID0gNzIyOwogICAgdC5BZ3JhdmUgPSA3MjI7CiAgICB0LkFicmV2ZSA9IDcyMjsKICAgIHQubXVsdGlwbHkgPSA1NjQ7CiAgICB0LnVhY3V0ZSA9IDUwMDsKICAgIHQuVGNhcm9uID0gNjExOwogICAgdC5wYXJ0aWFsZGlmZiA9IDQ3NjsKICAgIHQueWRpZXJlc2lzID0gNTAwOwogICAgdC5OYWN1dGUgPSA3MjI7CiAgICB0LmljaXJjdW1mbGV4ID0gMjc4OwogICAgdC5FY2lyY3VtZmxleCA9IDYxMTsKICAgIHQuYWRpZXJlc2lzID0gNDQ0OwogICAgdC5lZGllcmVzaXMgPSA0NDQ7CiAgICB0LmNhY3V0ZSA9IDQ0NDsKICAgIHQubmFjdXRlID0gNTAwOwogICAgdC51bWFjcm9uID0gNTAwOwogICAgdC5OY2Fyb24gPSA3MjI7CiAgICB0LklhY3V0ZSA9IDMzMzsKICAgIHQucGx1c21pbnVzID0gNTY0OwogICAgdC5icm9rZW5iYXIgPSAyMDA7CiAgICB0LnJlZ2lzdGVyZWQgPSA3NjA7CiAgICB0LkdicmV2ZSA9IDcyMjsKICAgIHQuSWRvdGFjY2VudCA9IDMzMzsKICAgIHQuc3VtbWF0aW9uID0gNjAwOwogICAgdC5FZ3JhdmUgPSA2MTE7CiAgICB0LnJhY3V0ZSA9IDMzMzsKICAgIHQub21hY3JvbiA9IDUwMDsKICAgIHQuWmFjdXRlID0gNjExOwogICAgdC5aY2Fyb24gPSA2MTE7CiAgICB0LmdyZWF0ZXJlcXVhbCA9IDU0OTsKICAgIHQuRXRoID0gNzIyOwogICAgdC5DY2VkaWxsYSA9IDY2NzsKICAgIHQubGNvbW1hYWNjZW50ID0gMjc4OwogICAgdC50Y2Fyb24gPSAzMjY7CiAgICB0LmVvZ29uZWsgPSA0NDQ7CiAgICB0LlVvZ29uZWsgPSA3MjI7CiAgICB0LkFhY3V0ZSA9IDcyMjsKICAgIHQuQWRpZXJlc2lzID0gNzIyOwogICAgdC5lZ3JhdmUgPSA0NDQ7CiAgICB0LnphY3V0ZSA9IDQ0NDsKICAgIHQuaW9nb25layA9IDI3ODsKICAgIHQuT2FjdXRlID0gNzIyOwogICAgdC5vYWN1dGUgPSA1MDA7CiAgICB0LmFtYWNyb24gPSA0NDQ7CiAgICB0LnNhY3V0ZSA9IDM4OTsKICAgIHQuaWRpZXJlc2lzID0gMjc4OwogICAgdC5PY2lyY3VtZmxleCA9IDcyMjsKICAgIHQuVWdyYXZlID0gNzIyOwogICAgdC5EZWx0YSA9IDYxMjsKICAgIHQudGhvcm4gPSA1MDA7CiAgICB0LnR3b3N1cGVyaW9yID0gMzAwOwogICAgdC5PZGllcmVzaXMgPSA3MjI7CiAgICB0Lm11ID0gNTAwOwogICAgdC5pZ3JhdmUgPSAyNzg7CiAgICB0Lm9odW5nYXJ1bWxhdXQgPSA1MDA7CiAgICB0LkVvZ29uZWsgPSA2MTE7CiAgICB0LmRjcm9hdCA9IDUwMDsKICAgIHQudGhyZWVxdWFydGVycyA9IDc1MDsKICAgIHQuU2NlZGlsbGEgPSA1NTY7CiAgICB0LmxjYXJvbiA9IDM0NDsKICAgIHQuS2NvbW1hYWNjZW50ID0gNzIyOwogICAgdC5MYWN1dGUgPSA2MTE7CiAgICB0LnRyYWRlbWFyayA9IDk4MDsKICAgIHQuZWRvdGFjY2VudCA9IDQ0NDsKICAgIHQuSWdyYXZlID0gMzMzOwogICAgdC5JbWFjcm9uID0gMzMzOwogICAgdC5MY2Fyb24gPSA2MTE7CiAgICB0Lm9uZWhhbGYgPSA3NTA7CiAgICB0Lmxlc3NlcXVhbCA9IDU0OTsKICAgIHQub2NpcmN1bWZsZXggPSA1MDA7CiAgICB0Lm50aWxkZSA9IDUwMDsKICAgIHQuVWh1bmdhcnVtbGF1dCA9IDcyMjsKICAgIHQuRWFjdXRlID0gNjExOwogICAgdC5lbWFjcm9uID0gNDQ0OwogICAgdC5nYnJldmUgPSA1MDA7CiAgICB0Lm9uZXF1YXJ0ZXIgPSA3NTA7CiAgICB0LlNjYXJvbiA9IDU1NjsKICAgIHQuU2NvbW1hYWNjZW50ID0gNTU2OwogICAgdC5PaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5kZWdyZWUgPSA0MDA7CiAgICB0Lm9ncmF2ZSA9IDUwMDsKICAgIHQuQ2Nhcm9uID0gNjY3OwogICAgdC51Z3JhdmUgPSA1MDA7CiAgICB0LnJhZGljYWwgPSA0NTM7CiAgICB0LkRjYXJvbiA9IDcyMjsKICAgIHQucmNvbW1hYWNjZW50ID0gMzMzOwogICAgdC5OdGlsZGUgPSA3MjI7CiAgICB0Lm90aWxkZSA9IDUwMDsKICAgIHQuUmNvbW1hYWNjZW50ID0gNjY3OwogICAgdC5MY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LkF0aWxkZSA9IDcyMjsKICAgIHQuQW9nb25layA9IDcyMjsKICAgIHQuQXJpbmcgPSA3MjI7CiAgICB0Lk90aWxkZSA9IDcyMjsKICAgIHQuemRvdGFjY2VudCA9IDQ0NDsKICAgIHQuRWNhcm9uID0gNjExOwogICAgdC5Jb2dvbmVrID0gMzMzOwogICAgdC5rY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0Lm1pbnVzID0gNTY0OwogICAgdC5JY2lyY3VtZmxleCA9IDMzMzsKICAgIHQubmNhcm9uID0gNTAwOwogICAgdC50Y29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LmxvZ2ljYWxub3QgPSA1NjQ7CiAgICB0Lm9kaWVyZXNpcyA9IDUwMDsKICAgIHQudWRpZXJlc2lzID0gNTAwOwogICAgdC5ub3RlcXVhbCA9IDU0OTsKICAgIHQuZ2NvbW1hYWNjZW50ID0gNTAwOwogICAgdC5ldGggPSA1MDA7CiAgICB0LnpjYXJvbiA9IDQ0NDsKICAgIHQubmNvbW1hYWNjZW50ID0gNTAwOwogICAgdC5vbmVzdXBlcmlvciA9IDMwMDsKICAgIHQuaW1hY3JvbiA9IDI3ODsKICAgIHQuRXVybyA9IDUwMDsKICB9KTsKICB0WyJUaW1lcy1Cb2xkIl0gPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICAgIHQuc3BhY2UgPSAyNTA7CiAgICB0LmV4Y2xhbSA9IDMzMzsKICAgIHQucXVvdGVkYmwgPSA1NTU7CiAgICB0Lm51bWJlcnNpZ24gPSA1MDA7CiAgICB0LmRvbGxhciA9IDUwMDsKICAgIHQucGVyY2VudCA9IDEwMDA7CiAgICB0LmFtcGVyc2FuZCA9IDgzMzsKICAgIHQucXVvdGVyaWdodCA9IDMzMzsKICAgIHQucGFyZW5sZWZ0ID0gMzMzOwogICAgdC5wYXJlbnJpZ2h0ID0gMzMzOwogICAgdC5hc3RlcmlzayA9IDUwMDsKICAgIHQucGx1cyA9IDU3MDsKICAgIHQuY29tbWEgPSAyNTA7CiAgICB0Lmh5cGhlbiA9IDMzMzsKICAgIHQucGVyaW9kID0gMjUwOwogICAgdC5zbGFzaCA9IDI3ODsKICAgIHQuemVybyA9IDUwMDsKICAgIHQub25lID0gNTAwOwogICAgdC50d28gPSA1MDA7CiAgICB0LnRocmVlID0gNTAwOwogICAgdC5mb3VyID0gNTAwOwogICAgdC5maXZlID0gNTAwOwogICAgdC5zaXggPSA1MDA7CiAgICB0LnNldmVuID0gNTAwOwogICAgdC5laWdodCA9IDUwMDsKICAgIHQubmluZSA9IDUwMDsKICAgIHQuY29sb24gPSAzMzM7CiAgICB0LnNlbWljb2xvbiA9IDMzMzsKICAgIHQubGVzcyA9IDU3MDsKICAgIHQuZXF1YWwgPSA1NzA7CiAgICB0LmdyZWF0ZXIgPSA1NzA7CiAgICB0LnF1ZXN0aW9uID0gNTAwOwogICAgdC5hdCA9IDkzMDsKICAgIHQuQSA9IDcyMjsKICAgIHQuQiA9IDY2NzsKICAgIHQuQyA9IDcyMjsKICAgIHQuRCA9IDcyMjsKICAgIHQuRSA9IDY2NzsKICAgIHQuRiA9IDYxMTsKICAgIHQuRyA9IDc3ODsKICAgIHQuSCA9IDc3ODsKICAgIHQuSSA9IDM4OTsKICAgIHQuSiA9IDUwMDsKICAgIHQuSyA9IDc3ODsKICAgIHQuTCA9IDY2NzsKICAgIHQuTSA9IDk0NDsKICAgIHQuTiA9IDcyMjsKICAgIHQuTyA9IDc3ODsKICAgIHQuUCA9IDYxMTsKICAgIHQuUSA9IDc3ODsKICAgIHQuUiA9IDcyMjsKICAgIHQuUyA9IDU1NjsKICAgIHQuVCA9IDY2NzsKICAgIHQuVSA9IDcyMjsKICAgIHQuViA9IDcyMjsKICAgIHQuVyA9IDEwMDA7CiAgICB0LlggPSA3MjI7CiAgICB0LlkgPSA3MjI7CiAgICB0LlogPSA2Njc7CiAgICB0LmJyYWNrZXRsZWZ0ID0gMzMzOwogICAgdC5iYWNrc2xhc2ggPSAyNzg7CiAgICB0LmJyYWNrZXRyaWdodCA9IDMzMzsKICAgIHQuYXNjaWljaXJjdW0gPSA1ODE7CiAgICB0LnVuZGVyc2NvcmUgPSA1MDA7CiAgICB0LnF1b3RlbGVmdCA9IDMzMzsKICAgIHQuYSA9IDUwMDsKICAgIHQuYiA9IDU1NjsKICAgIHQuYyA9IDQ0NDsKICAgIHQuZCA9IDU1NjsKICAgIHQuZSA9IDQ0NDsKICAgIHQuZiA9IDMzMzsKICAgIHQuZyA9IDUwMDsKICAgIHQuaCA9IDU1NjsKICAgIHQuaSA9IDI3ODsKICAgIHQuaiA9IDMzMzsKICAgIHQuayA9IDU1NjsKICAgIHQubCA9IDI3ODsKICAgIHQubSA9IDgzMzsKICAgIHQubiA9IDU1NjsKICAgIHQubyA9IDUwMDsKICAgIHQucCA9IDU1NjsKICAgIHQucSA9IDU1NjsKICAgIHQuciA9IDQ0NDsKICAgIHQucyA9IDM4OTsKICAgIHQudCA9IDMzMzsKICAgIHQudSA9IDU1NjsKICAgIHQudiA9IDUwMDsKICAgIHQudyA9IDcyMjsKICAgIHQueCA9IDUwMDsKICAgIHQueSA9IDUwMDsKICAgIHQueiA9IDQ0NDsKICAgIHQuYnJhY2VsZWZ0ID0gMzk0OwogICAgdC5iYXIgPSAyMjA7CiAgICB0LmJyYWNlcmlnaHQgPSAzOTQ7CiAgICB0LmFzY2lpdGlsZGUgPSA1MjA7CiAgICB0LmV4Y2xhbWRvd24gPSAzMzM7CiAgICB0LmNlbnQgPSA1MDA7CiAgICB0LnN0ZXJsaW5nID0gNTAwOwogICAgdC5mcmFjdGlvbiA9IDE2NzsKICAgIHQueWVuID0gNTAwOwogICAgdC5mbG9yaW4gPSA1MDA7CiAgICB0LnNlY3Rpb24gPSA1MDA7CiAgICB0LmN1cnJlbmN5ID0gNTAwOwogICAgdC5xdW90ZXNpbmdsZSA9IDI3ODsKICAgIHQucXVvdGVkYmxsZWZ0ID0gNTAwOwogICAgdC5ndWlsbGVtb3RsZWZ0ID0gNTAwOwogICAgdC5ndWlsc2luZ2xsZWZ0ID0gMzMzOwogICAgdC5ndWlsc2luZ2xyaWdodCA9IDMzMzsKICAgIHQuZmkgPSA1NTY7CiAgICB0LmZsID0gNTU2OwogICAgdC5lbmRhc2ggPSA1MDA7CiAgICB0LmRhZ2dlciA9IDUwMDsKICAgIHQuZGFnZ2VyZGJsID0gNTAwOwogICAgdC5wZXJpb2RjZW50ZXJlZCA9IDI1MDsKICAgIHQucGFyYWdyYXBoID0gNTQwOwogICAgdC5idWxsZXQgPSAzNTA7CiAgICB0LnF1b3Rlc2luZ2xiYXNlID0gMzMzOwogICAgdC5xdW90ZWRibGJhc2UgPSA1MDA7CiAgICB0LnF1b3RlZGJscmlnaHQgPSA1MDA7CiAgICB0Lmd1aWxsZW1vdHJpZ2h0ID0gNTAwOwogICAgdC5lbGxpcHNpcyA9IDEwMDA7CiAgICB0LnBlcnRob3VzYW5kID0gMTAwMDsKICAgIHQucXVlc3Rpb25kb3duID0gNTAwOwogICAgdC5ncmF2ZSA9IDMzMzsKICAgIHQuYWN1dGUgPSAzMzM7CiAgICB0LmNpcmN1bWZsZXggPSAzMzM7CiAgICB0LnRpbGRlID0gMzMzOwogICAgdC5tYWNyb24gPSAzMzM7CiAgICB0LmJyZXZlID0gMzMzOwogICAgdC5kb3RhY2NlbnQgPSAzMzM7CiAgICB0LmRpZXJlc2lzID0gMzMzOwogICAgdC5yaW5nID0gMzMzOwogICAgdC5jZWRpbGxhID0gMzMzOwogICAgdC5odW5nYXJ1bWxhdXQgPSAzMzM7CiAgICB0Lm9nb25layA9IDMzMzsKICAgIHQuY2Fyb24gPSAzMzM7CiAgICB0LmVtZGFzaCA9IDEwMDA7CiAgICB0LkFFID0gMTAwMDsKICAgIHQub3JkZmVtaW5pbmUgPSAzMDA7CiAgICB0LkxzbGFzaCA9IDY2NzsKICAgIHQuT3NsYXNoID0gNzc4OwogICAgdC5PRSA9IDEwMDA7CiAgICB0Lm9yZG1hc2N1bGluZSA9IDMzMDsKICAgIHQuYWUgPSA3MjI7CiAgICB0LmRvdGxlc3NpID0gMjc4OwogICAgdC5sc2xhc2ggPSAyNzg7CiAgICB0Lm9zbGFzaCA9IDUwMDsKICAgIHQub2UgPSA3MjI7CiAgICB0Lmdlcm1hbmRibHMgPSA1NTY7CiAgICB0LklkaWVyZXNpcyA9IDM4OTsKICAgIHQuZWFjdXRlID0gNDQ0OwogICAgdC5hYnJldmUgPSA1MDA7CiAgICB0LnVodW5nYXJ1bWxhdXQgPSA1NTY7CiAgICB0LmVjYXJvbiA9IDQ0NDsKICAgIHQuWWRpZXJlc2lzID0gNzIyOwogICAgdC5kaXZpZGUgPSA1NzA7CiAgICB0LllhY3V0ZSA9IDcyMjsKICAgIHQuQWNpcmN1bWZsZXggPSA3MjI7CiAgICB0LmFhY3V0ZSA9IDUwMDsKICAgIHQuVWNpcmN1bWZsZXggPSA3MjI7CiAgICB0LnlhY3V0ZSA9IDUwMDsKICAgIHQuc2NvbW1hYWNjZW50ID0gMzg5OwogICAgdC5lY2lyY3VtZmxleCA9IDQ0NDsKICAgIHQuVXJpbmcgPSA3MjI7CiAgICB0LlVkaWVyZXNpcyA9IDcyMjsKICAgIHQuYW9nb25layA9IDUwMDsKICAgIHQuVWFjdXRlID0gNzIyOwogICAgdC51b2dvbmVrID0gNTU2OwogICAgdC5FZGllcmVzaXMgPSA2Njc7CiAgICB0LkRjcm9hdCA9IDcyMjsKICAgIHQuY29tbWFhY2NlbnQgPSAyNTA7CiAgICB0LmNvcHlyaWdodCA9IDc0NzsKICAgIHQuRW1hY3JvbiA9IDY2NzsKICAgIHQuY2Nhcm9uID0gNDQ0OwogICAgdC5hcmluZyA9IDUwMDsKICAgIHQuTmNvbW1hYWNjZW50ID0gNzIyOwogICAgdC5sYWN1dGUgPSAyNzg7CiAgICB0LmFncmF2ZSA9IDUwMDsKICAgIHQuVGNvbW1hYWNjZW50ID0gNjY3OwogICAgdC5DYWN1dGUgPSA3MjI7CiAgICB0LmF0aWxkZSA9IDUwMDsKICAgIHQuRWRvdGFjY2VudCA9IDY2NzsKICAgIHQuc2Nhcm9uID0gMzg5OwogICAgdC5zY2VkaWxsYSA9IDM4OTsKICAgIHQuaWFjdXRlID0gMjc4OwogICAgdC5sb3plbmdlID0gNDk0OwogICAgdC5SY2Fyb24gPSA3MjI7CiAgICB0Lkdjb21tYWFjY2VudCA9IDc3ODsKICAgIHQudWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LmFjaXJjdW1mbGV4ID0gNTAwOwogICAgdC5BbWFjcm9uID0gNzIyOwogICAgdC5yY2Fyb24gPSA0NDQ7CiAgICB0LmNjZWRpbGxhID0gNDQ0OwogICAgdC5aZG90YWNjZW50ID0gNjY3OwogICAgdC5UaG9ybiA9IDYxMTsKICAgIHQuT21hY3JvbiA9IDc3ODsKICAgIHQuUmFjdXRlID0gNzIyOwogICAgdC5TYWN1dGUgPSA1NTY7CiAgICB0LmRjYXJvbiA9IDY3MjsKICAgIHQuVW1hY3JvbiA9IDcyMjsKICAgIHQudXJpbmcgPSA1NTY7CiAgICB0LnRocmVlc3VwZXJpb3IgPSAzMDA7CiAgICB0Lk9ncmF2ZSA9IDc3ODsKICAgIHQuQWdyYXZlID0gNzIyOwogICAgdC5BYnJldmUgPSA3MjI7CiAgICB0Lm11bHRpcGx5ID0gNTcwOwogICAgdC51YWN1dGUgPSA1NTY7CiAgICB0LlRjYXJvbiA9IDY2NzsKICAgIHQucGFydGlhbGRpZmYgPSA0OTQ7CiAgICB0LnlkaWVyZXNpcyA9IDUwMDsKICAgIHQuTmFjdXRlID0gNzIyOwogICAgdC5pY2lyY3VtZmxleCA9IDI3ODsKICAgIHQuRWNpcmN1bWZsZXggPSA2Njc7CiAgICB0LmFkaWVyZXNpcyA9IDUwMDsKICAgIHQuZWRpZXJlc2lzID0gNDQ0OwogICAgdC5jYWN1dGUgPSA0NDQ7CiAgICB0Lm5hY3V0ZSA9IDU1NjsKICAgIHQudW1hY3JvbiA9IDU1NjsKICAgIHQuTmNhcm9uID0gNzIyOwogICAgdC5JYWN1dGUgPSAzODk7CiAgICB0LnBsdXNtaW51cyA9IDU3MDsKICAgIHQuYnJva2VuYmFyID0gMjIwOwogICAgdC5yZWdpc3RlcmVkID0gNzQ3OwogICAgdC5HYnJldmUgPSA3Nzg7CiAgICB0Lklkb3RhY2NlbnQgPSAzODk7CiAgICB0LnN1bW1hdGlvbiA9IDYwMDsKICAgIHQuRWdyYXZlID0gNjY3OwogICAgdC5yYWN1dGUgPSA0NDQ7CiAgICB0Lm9tYWNyb24gPSA1MDA7CiAgICB0LlphY3V0ZSA9IDY2NzsKICAgIHQuWmNhcm9uID0gNjY3OwogICAgdC5ncmVhdGVyZXF1YWwgPSA1NDk7CiAgICB0LkV0aCA9IDcyMjsKICAgIHQuQ2NlZGlsbGEgPSA3MjI7CiAgICB0Lmxjb21tYWFjY2VudCA9IDI3ODsKICAgIHQudGNhcm9uID0gNDE2OwogICAgdC5lb2dvbmVrID0gNDQ0OwogICAgdC5Vb2dvbmVrID0gNzIyOwogICAgdC5BYWN1dGUgPSA3MjI7CiAgICB0LkFkaWVyZXNpcyA9IDcyMjsKICAgIHQuZWdyYXZlID0gNDQ0OwogICAgdC56YWN1dGUgPSA0NDQ7CiAgICB0LmlvZ29uZWsgPSAyNzg7CiAgICB0Lk9hY3V0ZSA9IDc3ODsKICAgIHQub2FjdXRlID0gNTAwOwogICAgdC5hbWFjcm9uID0gNTAwOwogICAgdC5zYWN1dGUgPSAzODk7CiAgICB0LmlkaWVyZXNpcyA9IDI3ODsKICAgIHQuT2NpcmN1bWZsZXggPSA3Nzg7CiAgICB0LlVncmF2ZSA9IDcyMjsKICAgIHQuRGVsdGEgPSA2MTI7CiAgICB0LnRob3JuID0gNTU2OwogICAgdC50d29zdXBlcmlvciA9IDMwMDsKICAgIHQuT2RpZXJlc2lzID0gNzc4OwogICAgdC5tdSA9IDU1NjsKICAgIHQuaWdyYXZlID0gMjc4OwogICAgdC5vaHVuZ2FydW1sYXV0ID0gNTAwOwogICAgdC5Fb2dvbmVrID0gNjY3OwogICAgdC5kY3JvYXQgPSA1NTY7CiAgICB0LnRocmVlcXVhcnRlcnMgPSA3NTA7CiAgICB0LlNjZWRpbGxhID0gNTU2OwogICAgdC5sY2Fyb24gPSAzOTQ7CiAgICB0Lktjb21tYWFjY2VudCA9IDc3ODsKICAgIHQuTGFjdXRlID0gNjY3OwogICAgdC50cmFkZW1hcmsgPSAxMDAwOwogICAgdC5lZG90YWNjZW50ID0gNDQ0OwogICAgdC5JZ3JhdmUgPSAzODk7CiAgICB0LkltYWNyb24gPSAzODk7CiAgICB0LkxjYXJvbiA9IDY2NzsKICAgIHQub25laGFsZiA9IDc1MDsKICAgIHQubGVzc2VxdWFsID0gNTQ5OwogICAgdC5vY2lyY3VtZmxleCA9IDUwMDsKICAgIHQubnRpbGRlID0gNTU2OwogICAgdC5VaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5FYWN1dGUgPSA2Njc7CiAgICB0LmVtYWNyb24gPSA0NDQ7CiAgICB0LmdicmV2ZSA9IDUwMDsKICAgIHQub25lcXVhcnRlciA9IDc1MDsKICAgIHQuU2Nhcm9uID0gNTU2OwogICAgdC5TY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0Lk9odW5nYXJ1bWxhdXQgPSA3Nzg7CiAgICB0LmRlZ3JlZSA9IDQwMDsKICAgIHQub2dyYXZlID0gNTAwOwogICAgdC5DY2Fyb24gPSA3MjI7CiAgICB0LnVncmF2ZSA9IDU1NjsKICAgIHQucmFkaWNhbCA9IDU0OTsKICAgIHQuRGNhcm9uID0gNzIyOwogICAgdC5yY29tbWFhY2NlbnQgPSA0NDQ7CiAgICB0Lk50aWxkZSA9IDcyMjsKICAgIHQub3RpbGRlID0gNTAwOwogICAgdC5SY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0Lkxjb21tYWFjY2VudCA9IDY2NzsKICAgIHQuQXRpbGRlID0gNzIyOwogICAgdC5Bb2dvbmVrID0gNzIyOwogICAgdC5BcmluZyA9IDcyMjsKICAgIHQuT3RpbGRlID0gNzc4OwogICAgdC56ZG90YWNjZW50ID0gNDQ0OwogICAgdC5FY2Fyb24gPSA2Njc7CiAgICB0LklvZ29uZWsgPSAzODk7CiAgICB0Lmtjb21tYWFjY2VudCA9IDU1NjsKICAgIHQubWludXMgPSA1NzA7CiAgICB0LkljaXJjdW1mbGV4ID0gMzg5OwogICAgdC5uY2Fyb24gPSA1NTY7CiAgICB0LnRjb21tYWFjY2VudCA9IDMzMzsKICAgIHQubG9naWNhbG5vdCA9IDU3MDsKICAgIHQub2RpZXJlc2lzID0gNTAwOwogICAgdC51ZGllcmVzaXMgPSA1NTY7CiAgICB0Lm5vdGVxdWFsID0gNTQ5OwogICAgdC5nY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0LmV0aCA9IDUwMDsKICAgIHQuemNhcm9uID0gNDQ0OwogICAgdC5uY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0Lm9uZXN1cGVyaW9yID0gMzAwOwogICAgdC5pbWFjcm9uID0gMjc4OwogICAgdC5FdXJvID0gNTAwOwogIH0pOwogIHRbIlRpbWVzLUJvbGRJdGFsaWMiXSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI1MDsKICAgIHQuZXhjbGFtID0gMzg5OwogICAgdC5xdW90ZWRibCA9IDU1NTsKICAgIHQubnVtYmVyc2lnbiA9IDUwMDsKICAgIHQuZG9sbGFyID0gNTAwOwogICAgdC5wZXJjZW50ID0gODMzOwogICAgdC5hbXBlcnNhbmQgPSA3Nzg7CiAgICB0LnF1b3RlcmlnaHQgPSAzMzM7CiAgICB0LnBhcmVubGVmdCA9IDMzMzsKICAgIHQucGFyZW5yaWdodCA9IDMzMzsKICAgIHQuYXN0ZXJpc2sgPSA1MDA7CiAgICB0LnBsdXMgPSA1NzA7CiAgICB0LmNvbW1hID0gMjUwOwogICAgdC5oeXBoZW4gPSAzMzM7CiAgICB0LnBlcmlvZCA9IDI1MDsKICAgIHQuc2xhc2ggPSAyNzg7CiAgICB0Lnplcm8gPSA1MDA7CiAgICB0Lm9uZSA9IDUwMDsKICAgIHQudHdvID0gNTAwOwogICAgdC50aHJlZSA9IDUwMDsKICAgIHQuZm91ciA9IDUwMDsKICAgIHQuZml2ZSA9IDUwMDsKICAgIHQuc2l4ID0gNTAwOwogICAgdC5zZXZlbiA9IDUwMDsKICAgIHQuZWlnaHQgPSA1MDA7CiAgICB0Lm5pbmUgPSA1MDA7CiAgICB0LmNvbG9uID0gMzMzOwogICAgdC5zZW1pY29sb24gPSAzMzM7CiAgICB0Lmxlc3MgPSA1NzA7CiAgICB0LmVxdWFsID0gNTcwOwogICAgdC5ncmVhdGVyID0gNTcwOwogICAgdC5xdWVzdGlvbiA9IDUwMDsKICAgIHQuYXQgPSA4MzI7CiAgICB0LkEgPSA2Njc7CiAgICB0LkIgPSA2Njc7CiAgICB0LkMgPSA2Njc7CiAgICB0LkQgPSA3MjI7CiAgICB0LkUgPSA2Njc7CiAgICB0LkYgPSA2Njc7CiAgICB0LkcgPSA3MjI7CiAgICB0LkggPSA3Nzg7CiAgICB0LkkgPSAzODk7CiAgICB0LkogPSA1MDA7CiAgICB0LksgPSA2Njc7CiAgICB0LkwgPSA2MTE7CiAgICB0Lk0gPSA4ODk7CiAgICB0Lk4gPSA3MjI7CiAgICB0Lk8gPSA3MjI7CiAgICB0LlAgPSA2MTE7CiAgICB0LlEgPSA3MjI7CiAgICB0LlIgPSA2Njc7CiAgICB0LlMgPSA1NTY7CiAgICB0LlQgPSA2MTE7CiAgICB0LlUgPSA3MjI7CiAgICB0LlYgPSA2Njc7CiAgICB0LlcgPSA4ODk7CiAgICB0LlggPSA2Njc7CiAgICB0LlkgPSA2MTE7CiAgICB0LlogPSA2MTE7CiAgICB0LmJyYWNrZXRsZWZ0ID0gMzMzOwogICAgdC5iYWNrc2xhc2ggPSAyNzg7CiAgICB0LmJyYWNrZXRyaWdodCA9IDMzMzsKICAgIHQuYXNjaWljaXJjdW0gPSA1NzA7CiAgICB0LnVuZGVyc2NvcmUgPSA1MDA7CiAgICB0LnF1b3RlbGVmdCA9IDMzMzsKICAgIHQuYSA9IDUwMDsKICAgIHQuYiA9IDUwMDsKICAgIHQuYyA9IDQ0NDsKICAgIHQuZCA9IDUwMDsKICAgIHQuZSA9IDQ0NDsKICAgIHQuZiA9IDMzMzsKICAgIHQuZyA9IDUwMDsKICAgIHQuaCA9IDU1NjsKICAgIHQuaSA9IDI3ODsKICAgIHQuaiA9IDI3ODsKICAgIHQuayA9IDUwMDsKICAgIHQubCA9IDI3ODsKICAgIHQubSA9IDc3ODsKICAgIHQubiA9IDU1NjsKICAgIHQubyA9IDUwMDsKICAgIHQucCA9IDUwMDsKICAgIHQucSA9IDUwMDsKICAgIHQuciA9IDM4OTsKICAgIHQucyA9IDM4OTsKICAgIHQudCA9IDI3ODsKICAgIHQudSA9IDU1NjsKICAgIHQudiA9IDQ0NDsKICAgIHQudyA9IDY2NzsKICAgIHQueCA9IDUwMDsKICAgIHQueSA9IDQ0NDsKICAgIHQueiA9IDM4OTsKICAgIHQuYnJhY2VsZWZ0ID0gMzQ4OwogICAgdC5iYXIgPSAyMjA7CiAgICB0LmJyYWNlcmlnaHQgPSAzNDg7CiAgICB0LmFzY2lpdGlsZGUgPSA1NzA7CiAgICB0LmV4Y2xhbWRvd24gPSAzODk7CiAgICB0LmNlbnQgPSA1MDA7CiAgICB0LnN0ZXJsaW5nID0gNTAwOwogICAgdC5mcmFjdGlvbiA9IDE2NzsKICAgIHQueWVuID0gNTAwOwogICAgdC5mbG9yaW4gPSA1MDA7CiAgICB0LnNlY3Rpb24gPSA1MDA7CiAgICB0LmN1cnJlbmN5ID0gNTAwOwogICAgdC5xdW90ZXNpbmdsZSA9IDI3ODsKICAgIHQucXVvdGVkYmxsZWZ0ID0gNTAwOwogICAgdC5ndWlsbGVtb3RsZWZ0ID0gNTAwOwogICAgdC5ndWlsc2luZ2xsZWZ0ID0gMzMzOwogICAgdC5ndWlsc2luZ2xyaWdodCA9IDMzMzsKICAgIHQuZmkgPSA1NTY7CiAgICB0LmZsID0gNTU2OwogICAgdC5lbmRhc2ggPSA1MDA7CiAgICB0LmRhZ2dlciA9IDUwMDsKICAgIHQuZGFnZ2VyZGJsID0gNTAwOwogICAgdC5wZXJpb2RjZW50ZXJlZCA9IDI1MDsKICAgIHQucGFyYWdyYXBoID0gNTAwOwogICAgdC5idWxsZXQgPSAzNTA7CiAgICB0LnF1b3Rlc2luZ2xiYXNlID0gMzMzOwogICAgdC5xdW90ZWRibGJhc2UgPSA1MDA7CiAgICB0LnF1b3RlZGJscmlnaHQgPSA1MDA7CiAgICB0Lmd1aWxsZW1vdHJpZ2h0ID0gNTAwOwogICAgdC5lbGxpcHNpcyA9IDEwMDA7CiAgICB0LnBlcnRob3VzYW5kID0gMTAwMDsKICAgIHQucXVlc3Rpb25kb3duID0gNTAwOwogICAgdC5ncmF2ZSA9IDMzMzsKICAgIHQuYWN1dGUgPSAzMzM7CiAgICB0LmNpcmN1bWZsZXggPSAzMzM7CiAgICB0LnRpbGRlID0gMzMzOwogICAgdC5tYWNyb24gPSAzMzM7CiAgICB0LmJyZXZlID0gMzMzOwogICAgdC5kb3RhY2NlbnQgPSAzMzM7CiAgICB0LmRpZXJlc2lzID0gMzMzOwogICAgdC5yaW5nID0gMzMzOwogICAgdC5jZWRpbGxhID0gMzMzOwogICAgdC5odW5nYXJ1bWxhdXQgPSAzMzM7CiAgICB0Lm9nb25layA9IDMzMzsKICAgIHQuY2Fyb24gPSAzMzM7CiAgICB0LmVtZGFzaCA9IDEwMDA7CiAgICB0LkFFID0gOTQ0OwogICAgdC5vcmRmZW1pbmluZSA9IDI2NjsKICAgIHQuTHNsYXNoID0gNjExOwogICAgdC5Pc2xhc2ggPSA3MjI7CiAgICB0Lk9FID0gOTQ0OwogICAgdC5vcmRtYXNjdWxpbmUgPSAzMDA7CiAgICB0LmFlID0gNzIyOwogICAgdC5kb3RsZXNzaSA9IDI3ODsKICAgIHQubHNsYXNoID0gMjc4OwogICAgdC5vc2xhc2ggPSA1MDA7CiAgICB0Lm9lID0gNzIyOwogICAgdC5nZXJtYW5kYmxzID0gNTAwOwogICAgdC5JZGllcmVzaXMgPSAzODk7CiAgICB0LmVhY3V0ZSA9IDQ0NDsKICAgIHQuYWJyZXZlID0gNTAwOwogICAgdC51aHVuZ2FydW1sYXV0ID0gNTU2OwogICAgdC5lY2Fyb24gPSA0NDQ7CiAgICB0LllkaWVyZXNpcyA9IDYxMTsKICAgIHQuZGl2aWRlID0gNTcwOwogICAgdC5ZYWN1dGUgPSA2MTE7CiAgICB0LkFjaXJjdW1mbGV4ID0gNjY3OwogICAgdC5hYWN1dGUgPSA1MDA7CiAgICB0LlVjaXJjdW1mbGV4ID0gNzIyOwogICAgdC55YWN1dGUgPSA0NDQ7CiAgICB0LnNjb21tYWFjY2VudCA9IDM4OTsKICAgIHQuZWNpcmN1bWZsZXggPSA0NDQ7CiAgICB0LlVyaW5nID0gNzIyOwogICAgdC5VZGllcmVzaXMgPSA3MjI7CiAgICB0LmFvZ29uZWsgPSA1MDA7CiAgICB0LlVhY3V0ZSA9IDcyMjsKICAgIHQudW9nb25layA9IDU1NjsKICAgIHQuRWRpZXJlc2lzID0gNjY3OwogICAgdC5EY3JvYXQgPSA3MjI7CiAgICB0LmNvbW1hYWNjZW50ID0gMjUwOwogICAgdC5jb3B5cmlnaHQgPSA3NDc7CiAgICB0LkVtYWNyb24gPSA2Njc7CiAgICB0LmNjYXJvbiA9IDQ0NDsKICAgIHQuYXJpbmcgPSA1MDA7CiAgICB0Lk5jb21tYWFjY2VudCA9IDcyMjsKICAgIHQubGFjdXRlID0gMjc4OwogICAgdC5hZ3JhdmUgPSA1MDA7CiAgICB0LlRjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQ2FjdXRlID0gNjY3OwogICAgdC5hdGlsZGUgPSA1MDA7CiAgICB0LkVkb3RhY2NlbnQgPSA2Njc7CiAgICB0LnNjYXJvbiA9IDM4OTsKICAgIHQuc2NlZGlsbGEgPSAzODk7CiAgICB0LmlhY3V0ZSA9IDI3ODsKICAgIHQubG96ZW5nZSA9IDQ5NDsKICAgIHQuUmNhcm9uID0gNjY3OwogICAgdC5HY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LnVjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5hY2lyY3VtZmxleCA9IDUwMDsKICAgIHQuQW1hY3JvbiA9IDY2NzsKICAgIHQucmNhcm9uID0gMzg5OwogICAgdC5jY2VkaWxsYSA9IDQ0NDsKICAgIHQuWmRvdGFjY2VudCA9IDYxMTsKICAgIHQuVGhvcm4gPSA2MTE7CiAgICB0Lk9tYWNyb24gPSA3MjI7CiAgICB0LlJhY3V0ZSA9IDY2NzsKICAgIHQuU2FjdXRlID0gNTU2OwogICAgdC5kY2Fyb24gPSA2MDg7CiAgICB0LlVtYWNyb24gPSA3MjI7CiAgICB0LnVyaW5nID0gNTU2OwogICAgdC50aHJlZXN1cGVyaW9yID0gMzAwOwogICAgdC5PZ3JhdmUgPSA3MjI7CiAgICB0LkFncmF2ZSA9IDY2NzsKICAgIHQuQWJyZXZlID0gNjY3OwogICAgdC5tdWx0aXBseSA9IDU3MDsKICAgIHQudWFjdXRlID0gNTU2OwogICAgdC5UY2Fyb24gPSA2MTE7CiAgICB0LnBhcnRpYWxkaWZmID0gNDk0OwogICAgdC55ZGllcmVzaXMgPSA0NDQ7CiAgICB0Lk5hY3V0ZSA9IDcyMjsKICAgIHQuaWNpcmN1bWZsZXggPSAyNzg7CiAgICB0LkVjaXJjdW1mbGV4ID0gNjY3OwogICAgdC5hZGllcmVzaXMgPSA1MDA7CiAgICB0LmVkaWVyZXNpcyA9IDQ0NDsKICAgIHQuY2FjdXRlID0gNDQ0OwogICAgdC5uYWN1dGUgPSA1NTY7CiAgICB0LnVtYWNyb24gPSA1NTY7CiAgICB0Lk5jYXJvbiA9IDcyMjsKICAgIHQuSWFjdXRlID0gMzg5OwogICAgdC5wbHVzbWludXMgPSA1NzA7CiAgICB0LmJyb2tlbmJhciA9IDIyMDsKICAgIHQucmVnaXN0ZXJlZCA9IDc0NzsKICAgIHQuR2JyZXZlID0gNzIyOwogICAgdC5JZG90YWNjZW50ID0gMzg5OwogICAgdC5zdW1tYXRpb24gPSA2MDA7CiAgICB0LkVncmF2ZSA9IDY2NzsKICAgIHQucmFjdXRlID0gMzg5OwogICAgdC5vbWFjcm9uID0gNTAwOwogICAgdC5aYWN1dGUgPSA2MTE7CiAgICB0LlpjYXJvbiA9IDYxMTsKICAgIHQuZ3JlYXRlcmVxdWFsID0gNTQ5OwogICAgdC5FdGggPSA3MjI7CiAgICB0LkNjZWRpbGxhID0gNjY3OwogICAgdC5sY29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LnRjYXJvbiA9IDM2NjsKICAgIHQuZW9nb25layA9IDQ0NDsKICAgIHQuVW9nb25layA9IDcyMjsKICAgIHQuQWFjdXRlID0gNjY3OwogICAgdC5BZGllcmVzaXMgPSA2Njc7CiAgICB0LmVncmF2ZSA9IDQ0NDsKICAgIHQuemFjdXRlID0gMzg5OwogICAgdC5pb2dvbmVrID0gMjc4OwogICAgdC5PYWN1dGUgPSA3MjI7CiAgICB0Lm9hY3V0ZSA9IDUwMDsKICAgIHQuYW1hY3JvbiA9IDUwMDsKICAgIHQuc2FjdXRlID0gMzg5OwogICAgdC5pZGllcmVzaXMgPSAyNzg7CiAgICB0Lk9jaXJjdW1mbGV4ID0gNzIyOwogICAgdC5VZ3JhdmUgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC50aG9ybiA9IDUwMDsKICAgIHQudHdvc3VwZXJpb3IgPSAzMDA7CiAgICB0Lk9kaWVyZXNpcyA9IDcyMjsKICAgIHQubXUgPSA1NzY7CiAgICB0LmlncmF2ZSA9IDI3ODsKICAgIHQub2h1bmdhcnVtbGF1dCA9IDUwMDsKICAgIHQuRW9nb25layA9IDY2NzsKICAgIHQuZGNyb2F0ID0gNTAwOwogICAgdC50aHJlZXF1YXJ0ZXJzID0gNzUwOwogICAgdC5TY2VkaWxsYSA9IDU1NjsKICAgIHQubGNhcm9uID0gMzgyOwogICAgdC5LY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0LkxhY3V0ZSA9IDYxMTsKICAgIHQudHJhZGVtYXJrID0gMTAwMDsKICAgIHQuZWRvdGFjY2VudCA9IDQ0NDsKICAgIHQuSWdyYXZlID0gMzg5OwogICAgdC5JbWFjcm9uID0gMzg5OwogICAgdC5MY2Fyb24gPSA2MTE7CiAgICB0Lm9uZWhhbGYgPSA3NTA7CiAgICB0Lmxlc3NlcXVhbCA9IDU0OTsKICAgIHQub2NpcmN1bWZsZXggPSA1MDA7CiAgICB0Lm50aWxkZSA9IDU1NjsKICAgIHQuVWh1bmdhcnVtbGF1dCA9IDcyMjsKICAgIHQuRWFjdXRlID0gNjY3OwogICAgdC5lbWFjcm9uID0gNDQ0OwogICAgdC5nYnJldmUgPSA1MDA7CiAgICB0Lm9uZXF1YXJ0ZXIgPSA3NTA7CiAgICB0LlNjYXJvbiA9IDU1NjsKICAgIHQuU2NvbW1hYWNjZW50ID0gNTU2OwogICAgdC5PaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5kZWdyZWUgPSA0MDA7CiAgICB0Lm9ncmF2ZSA9IDUwMDsKICAgIHQuQ2Nhcm9uID0gNjY3OwogICAgdC51Z3JhdmUgPSA1NTY7CiAgICB0LnJhZGljYWwgPSA1NDk7CiAgICB0LkRjYXJvbiA9IDcyMjsKICAgIHQucmNvbW1hYWNjZW50ID0gMzg5OwogICAgdC5OdGlsZGUgPSA3MjI7CiAgICB0Lm90aWxkZSA9IDUwMDsKICAgIHQuUmNvbW1hYWNjZW50ID0gNjY3OwogICAgdC5MY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LkF0aWxkZSA9IDY2NzsKICAgIHQuQW9nb25layA9IDY2NzsKICAgIHQuQXJpbmcgPSA2Njc7CiAgICB0Lk90aWxkZSA9IDcyMjsKICAgIHQuemRvdGFjY2VudCA9IDM4OTsKICAgIHQuRWNhcm9uID0gNjY3OwogICAgdC5Jb2dvbmVrID0gMzg5OwogICAgdC5rY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0Lm1pbnVzID0gNjA2OwogICAgdC5JY2lyY3VtZmxleCA9IDM4OTsKICAgIHQubmNhcm9uID0gNTU2OwogICAgdC50Y29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LmxvZ2ljYWxub3QgPSA2MDY7CiAgICB0Lm9kaWVyZXNpcyA9IDUwMDsKICAgIHQudWRpZXJlc2lzID0gNTU2OwogICAgdC5ub3RlcXVhbCA9IDU0OTsKICAgIHQuZ2NvbW1hYWNjZW50ID0gNTAwOwogICAgdC5ldGggPSA1MDA7CiAgICB0LnpjYXJvbiA9IDM4OTsKICAgIHQubmNvbW1hYWNjZW50ID0gNTU2OwogICAgdC5vbmVzdXBlcmlvciA9IDMwMDsKICAgIHQuaW1hY3JvbiA9IDI3ODsKICAgIHQuRXVybyA9IDUwMDsKICB9KTsKICB0WyJUaW1lcy1JdGFsaWMiXSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI1MDsKICAgIHQuZXhjbGFtID0gMzMzOwogICAgdC5xdW90ZWRibCA9IDQyMDsKICAgIHQubnVtYmVyc2lnbiA9IDUwMDsKICAgIHQuZG9sbGFyID0gNTAwOwogICAgdC5wZXJjZW50ID0gODMzOwogICAgdC5hbXBlcnNhbmQgPSA3Nzg7CiAgICB0LnF1b3RlcmlnaHQgPSAzMzM7CiAgICB0LnBhcmVubGVmdCA9IDMzMzsKICAgIHQucGFyZW5yaWdodCA9IDMzMzsKICAgIHQuYXN0ZXJpc2sgPSA1MDA7CiAgICB0LnBsdXMgPSA2NzU7CiAgICB0LmNvbW1hID0gMjUwOwogICAgdC5oeXBoZW4gPSAzMzM7CiAgICB0LnBlcmlvZCA9IDI1MDsKICAgIHQuc2xhc2ggPSAyNzg7CiAgICB0Lnplcm8gPSA1MDA7CiAgICB0Lm9uZSA9IDUwMDsKICAgIHQudHdvID0gNTAwOwogICAgdC50aHJlZSA9IDUwMDsKICAgIHQuZm91ciA9IDUwMDsKICAgIHQuZml2ZSA9IDUwMDsKICAgIHQuc2l4ID0gNTAwOwogICAgdC5zZXZlbiA9IDUwMDsKICAgIHQuZWlnaHQgPSA1MDA7CiAgICB0Lm5pbmUgPSA1MDA7CiAgICB0LmNvbG9uID0gMzMzOwogICAgdC5zZW1pY29sb24gPSAzMzM7CiAgICB0Lmxlc3MgPSA2NzU7CiAgICB0LmVxdWFsID0gNjc1OwogICAgdC5ncmVhdGVyID0gNjc1OwogICAgdC5xdWVzdGlvbiA9IDUwMDsKICAgIHQuYXQgPSA5MjA7CiAgICB0LkEgPSA2MTE7CiAgICB0LkIgPSA2MTE7CiAgICB0LkMgPSA2Njc7CiAgICB0LkQgPSA3MjI7CiAgICB0LkUgPSA2MTE7CiAgICB0LkYgPSA2MTE7CiAgICB0LkcgPSA3MjI7CiAgICB0LkggPSA3MjI7CiAgICB0LkkgPSAzMzM7CiAgICB0LkogPSA0NDQ7CiAgICB0LksgPSA2Njc7CiAgICB0LkwgPSA1NTY7CiAgICB0Lk0gPSA4MzM7CiAgICB0Lk4gPSA2Njc7CiAgICB0Lk8gPSA3MjI7CiAgICB0LlAgPSA2MTE7CiAgICB0LlEgPSA3MjI7CiAgICB0LlIgPSA2MTE7CiAgICB0LlMgPSA1MDA7CiAgICB0LlQgPSA1NTY7CiAgICB0LlUgPSA3MjI7CiAgICB0LlYgPSA2MTE7CiAgICB0LlcgPSA4MzM7CiAgICB0LlggPSA2MTE7CiAgICB0LlkgPSA1NTY7CiAgICB0LlogPSA1NTY7CiAgICB0LmJyYWNrZXRsZWZ0ID0gMzg5OwogICAgdC5iYWNrc2xhc2ggPSAyNzg7CiAgICB0LmJyYWNrZXRyaWdodCA9IDM4OTsKICAgIHQuYXNjaWljaXJjdW0gPSA0MjI7CiAgICB0LnVuZGVyc2NvcmUgPSA1MDA7CiAgICB0LnF1b3RlbGVmdCA9IDMzMzsKICAgIHQuYSA9IDUwMDsKICAgIHQuYiA9IDUwMDsKICAgIHQuYyA9IDQ0NDsKICAgIHQuZCA9IDUwMDsKICAgIHQuZSA9IDQ0NDsKICAgIHQuZiA9IDI3ODsKICAgIHQuZyA9IDUwMDsKICAgIHQuaCA9IDUwMDsKICAgIHQuaSA9IDI3ODsKICAgIHQuaiA9IDI3ODsKICAgIHQuayA9IDQ0NDsKICAgIHQubCA9IDI3ODsKICAgIHQubSA9IDcyMjsKICAgIHQubiA9IDUwMDsKICAgIHQubyA9IDUwMDsKICAgIHQucCA9IDUwMDsKICAgIHQucSA9IDUwMDsKICAgIHQuciA9IDM4OTsKICAgIHQucyA9IDM4OTsKICAgIHQudCA9IDI3ODsKICAgIHQudSA9IDUwMDsKICAgIHQudiA9IDQ0NDsKICAgIHQudyA9IDY2NzsKICAgIHQueCA9IDQ0NDsKICAgIHQueSA9IDQ0NDsKICAgIHQueiA9IDM4OTsKICAgIHQuYnJhY2VsZWZ0ID0gNDAwOwogICAgdC5iYXIgPSAyNzU7CiAgICB0LmJyYWNlcmlnaHQgPSA0MDA7CiAgICB0LmFzY2lpdGlsZGUgPSA1NDE7CiAgICB0LmV4Y2xhbWRvd24gPSAzODk7CiAgICB0LmNlbnQgPSA1MDA7CiAgICB0LnN0ZXJsaW5nID0gNTAwOwogICAgdC5mcmFjdGlvbiA9IDE2NzsKICAgIHQueWVuID0gNTAwOwogICAgdC5mbG9yaW4gPSA1MDA7CiAgICB0LnNlY3Rpb24gPSA1MDA7CiAgICB0LmN1cnJlbmN5ID0gNTAwOwogICAgdC5xdW90ZXNpbmdsZSA9IDIxNDsKICAgIHQucXVvdGVkYmxsZWZ0ID0gNTU2OwogICAgdC5ndWlsbGVtb3RsZWZ0ID0gNTAwOwogICAgdC5ndWlsc2luZ2xsZWZ0ID0gMzMzOwogICAgdC5ndWlsc2luZ2xyaWdodCA9IDMzMzsKICAgIHQuZmkgPSA1MDA7CiAgICB0LmZsID0gNTAwOwogICAgdC5lbmRhc2ggPSA1MDA7CiAgICB0LmRhZ2dlciA9IDUwMDsKICAgIHQuZGFnZ2VyZGJsID0gNTAwOwogICAgdC5wZXJpb2RjZW50ZXJlZCA9IDI1MDsKICAgIHQucGFyYWdyYXBoID0gNTIzOwogICAgdC5idWxsZXQgPSAzNTA7CiAgICB0LnF1b3Rlc2luZ2xiYXNlID0gMzMzOwogICAgdC5xdW90ZWRibGJhc2UgPSA1NTY7CiAgICB0LnF1b3RlZGJscmlnaHQgPSA1NTY7CiAgICB0Lmd1aWxsZW1vdHJpZ2h0ID0gNTAwOwogICAgdC5lbGxpcHNpcyA9IDg4OTsKICAgIHQucGVydGhvdXNhbmQgPSAxMDAwOwogICAgdC5xdWVzdGlvbmRvd24gPSA1MDA7CiAgICB0LmdyYXZlID0gMzMzOwogICAgdC5hY3V0ZSA9IDMzMzsKICAgIHQuY2lyY3VtZmxleCA9IDMzMzsKICAgIHQudGlsZGUgPSAzMzM7CiAgICB0Lm1hY3JvbiA9IDMzMzsKICAgIHQuYnJldmUgPSAzMzM7CiAgICB0LmRvdGFjY2VudCA9IDMzMzsKICAgIHQuZGllcmVzaXMgPSAzMzM7CiAgICB0LnJpbmcgPSAzMzM7CiAgICB0LmNlZGlsbGEgPSAzMzM7CiAgICB0Lmh1bmdhcnVtbGF1dCA9IDMzMzsKICAgIHQub2dvbmVrID0gMzMzOwogICAgdC5jYXJvbiA9IDMzMzsKICAgIHQuZW1kYXNoID0gODg5OwogICAgdC5BRSA9IDg4OTsKICAgIHQub3JkZmVtaW5pbmUgPSAyNzY7CiAgICB0LkxzbGFzaCA9IDU1NjsKICAgIHQuT3NsYXNoID0gNzIyOwogICAgdC5PRSA9IDk0NDsKICAgIHQub3JkbWFzY3VsaW5lID0gMzEwOwogICAgdC5hZSA9IDY2NzsKICAgIHQuZG90bGVzc2kgPSAyNzg7CiAgICB0LmxzbGFzaCA9IDI3ODsKICAgIHQub3NsYXNoID0gNTAwOwogICAgdC5vZSA9IDY2NzsKICAgIHQuZ2VybWFuZGJscyA9IDUwMDsKICAgIHQuSWRpZXJlc2lzID0gMzMzOwogICAgdC5lYWN1dGUgPSA0NDQ7CiAgICB0LmFicmV2ZSA9IDUwMDsKICAgIHQudWh1bmdhcnVtbGF1dCA9IDUwMDsKICAgIHQuZWNhcm9uID0gNDQ0OwogICAgdC5ZZGllcmVzaXMgPSA1NTY7CiAgICB0LmRpdmlkZSA9IDY3NTsKICAgIHQuWWFjdXRlID0gNTU2OwogICAgdC5BY2lyY3VtZmxleCA9IDYxMTsKICAgIHQuYWFjdXRlID0gNTAwOwogICAgdC5VY2lyY3VtZmxleCA9IDcyMjsKICAgIHQueWFjdXRlID0gNDQ0OwogICAgdC5zY29tbWFhY2NlbnQgPSAzODk7CiAgICB0LmVjaXJjdW1mbGV4ID0gNDQ0OwogICAgdC5VcmluZyA9IDcyMjsKICAgIHQuVWRpZXJlc2lzID0gNzIyOwogICAgdC5hb2dvbmVrID0gNTAwOwogICAgdC5VYWN1dGUgPSA3MjI7CiAgICB0LnVvZ29uZWsgPSA1MDA7CiAgICB0LkVkaWVyZXNpcyA9IDYxMTsKICAgIHQuRGNyb2F0ID0gNzIyOwogICAgdC5jb21tYWFjY2VudCA9IDI1MDsKICAgIHQuY29weXJpZ2h0ID0gNzYwOwogICAgdC5FbWFjcm9uID0gNjExOwogICAgdC5jY2Fyb24gPSA0NDQ7CiAgICB0LmFyaW5nID0gNTAwOwogICAgdC5OY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0LmxhY3V0ZSA9IDI3ODsKICAgIHQuYWdyYXZlID0gNTAwOwogICAgdC5UY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0LkNhY3V0ZSA9IDY2NzsKICAgIHQuYXRpbGRlID0gNTAwOwogICAgdC5FZG90YWNjZW50ID0gNjExOwogICAgdC5zY2Fyb24gPSAzODk7CiAgICB0LnNjZWRpbGxhID0gMzg5OwogICAgdC5pYWN1dGUgPSAyNzg7CiAgICB0LmxvemVuZ2UgPSA0NzE7CiAgICB0LlJjYXJvbiA9IDYxMTsKICAgIHQuR2NvbW1hYWNjZW50ID0gNzIyOwogICAgdC51Y2lyY3VtZmxleCA9IDUwMDsKICAgIHQuYWNpcmN1bWZsZXggPSA1MDA7CiAgICB0LkFtYWNyb24gPSA2MTE7CiAgICB0LnJjYXJvbiA9IDM4OTsKICAgIHQuY2NlZGlsbGEgPSA0NDQ7CiAgICB0Llpkb3RhY2NlbnQgPSA1NTY7CiAgICB0LlRob3JuID0gNjExOwogICAgdC5PbWFjcm9uID0gNzIyOwogICAgdC5SYWN1dGUgPSA2MTE7CiAgICB0LlNhY3V0ZSA9IDUwMDsKICAgIHQuZGNhcm9uID0gNTQ0OwogICAgdC5VbWFjcm9uID0gNzIyOwogICAgdC51cmluZyA9IDUwMDsKICAgIHQudGhyZWVzdXBlcmlvciA9IDMwMDsKICAgIHQuT2dyYXZlID0gNzIyOwogICAgdC5BZ3JhdmUgPSA2MTE7CiAgICB0LkFicmV2ZSA9IDYxMTsKICAgIHQubXVsdGlwbHkgPSA2NzU7CiAgICB0LnVhY3V0ZSA9IDUwMDsKICAgIHQuVGNhcm9uID0gNTU2OwogICAgdC5wYXJ0aWFsZGlmZiA9IDQ3NjsKICAgIHQueWRpZXJlc2lzID0gNDQ0OwogICAgdC5OYWN1dGUgPSA2Njc7CiAgICB0LmljaXJjdW1mbGV4ID0gMjc4OwogICAgdC5FY2lyY3VtZmxleCA9IDYxMTsKICAgIHQuYWRpZXJlc2lzID0gNTAwOwogICAgdC5lZGllcmVzaXMgPSA0NDQ7CiAgICB0LmNhY3V0ZSA9IDQ0NDsKICAgIHQubmFjdXRlID0gNTAwOwogICAgdC51bWFjcm9uID0gNTAwOwogICAgdC5OY2Fyb24gPSA2Njc7CiAgICB0LklhY3V0ZSA9IDMzMzsKICAgIHQucGx1c21pbnVzID0gNjc1OwogICAgdC5icm9rZW5iYXIgPSAyNzU7CiAgICB0LnJlZ2lzdGVyZWQgPSA3NjA7CiAgICB0LkdicmV2ZSA9IDcyMjsKICAgIHQuSWRvdGFjY2VudCA9IDMzMzsKICAgIHQuc3VtbWF0aW9uID0gNjAwOwogICAgdC5FZ3JhdmUgPSA2MTE7CiAgICB0LnJhY3V0ZSA9IDM4OTsKICAgIHQub21hY3JvbiA9IDUwMDsKICAgIHQuWmFjdXRlID0gNTU2OwogICAgdC5aY2Fyb24gPSA1NTY7CiAgICB0LmdyZWF0ZXJlcXVhbCA9IDU0OTsKICAgIHQuRXRoID0gNzIyOwogICAgdC5DY2VkaWxsYSA9IDY2NzsKICAgIHQubGNvbW1hYWNjZW50ID0gMjc4OwogICAgdC50Y2Fyb24gPSAzMDA7CiAgICB0LmVvZ29uZWsgPSA0NDQ7CiAgICB0LlVvZ29uZWsgPSA3MjI7CiAgICB0LkFhY3V0ZSA9IDYxMTsKICAgIHQuQWRpZXJlc2lzID0gNjExOwogICAgdC5lZ3JhdmUgPSA0NDQ7CiAgICB0LnphY3V0ZSA9IDM4OTsKICAgIHQuaW9nb25layA9IDI3ODsKICAgIHQuT2FjdXRlID0gNzIyOwogICAgdC5vYWN1dGUgPSA1MDA7CiAgICB0LmFtYWNyb24gPSA1MDA7CiAgICB0LnNhY3V0ZSA9IDM4OTsKICAgIHQuaWRpZXJlc2lzID0gMjc4OwogICAgdC5PY2lyY3VtZmxleCA9IDcyMjsKICAgIHQuVWdyYXZlID0gNzIyOwogICAgdC5EZWx0YSA9IDYxMjsKICAgIHQudGhvcm4gPSA1MDA7CiAgICB0LnR3b3N1cGVyaW9yID0gMzAwOwogICAgdC5PZGllcmVzaXMgPSA3MjI7CiAgICB0Lm11ID0gNTAwOwogICAgdC5pZ3JhdmUgPSAyNzg7CiAgICB0Lm9odW5nYXJ1bWxhdXQgPSA1MDA7CiAgICB0LkVvZ29uZWsgPSA2MTE7CiAgICB0LmRjcm9hdCA9IDUwMDsKICAgIHQudGhyZWVxdWFydGVycyA9IDc1MDsKICAgIHQuU2NlZGlsbGEgPSA1MDA7CiAgICB0LmxjYXJvbiA9IDMwMDsKICAgIHQuS2NvbW1hYWNjZW50ID0gNjY3OwogICAgdC5MYWN1dGUgPSA1NTY7CiAgICB0LnRyYWRlbWFyayA9IDk4MDsKICAgIHQuZWRvdGFjY2VudCA9IDQ0NDsKICAgIHQuSWdyYXZlID0gMzMzOwogICAgdC5JbWFjcm9uID0gMzMzOwogICAgdC5MY2Fyb24gPSA2MTE7CiAgICB0Lm9uZWhhbGYgPSA3NTA7CiAgICB0Lmxlc3NlcXVhbCA9IDU0OTsKICAgIHQub2NpcmN1bWZsZXggPSA1MDA7CiAgICB0Lm50aWxkZSA9IDUwMDsKICAgIHQuVWh1bmdhcnVtbGF1dCA9IDcyMjsKICAgIHQuRWFjdXRlID0gNjExOwogICAgdC5lbWFjcm9uID0gNDQ0OwogICAgdC5nYnJldmUgPSA1MDA7CiAgICB0Lm9uZXF1YXJ0ZXIgPSA3NTA7CiAgICB0LlNjYXJvbiA9IDUwMDsKICAgIHQuU2NvbW1hYWNjZW50ID0gNTAwOwogICAgdC5PaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5kZWdyZWUgPSA0MDA7CiAgICB0Lm9ncmF2ZSA9IDUwMDsKICAgIHQuQ2Nhcm9uID0gNjY3OwogICAgdC51Z3JhdmUgPSA1MDA7CiAgICB0LnJhZGljYWwgPSA0NTM7CiAgICB0LkRjYXJvbiA9IDcyMjsKICAgIHQucmNvbW1hYWNjZW50ID0gMzg5OwogICAgdC5OdGlsZGUgPSA2Njc7CiAgICB0Lm90aWxkZSA9IDUwMDsKICAgIHQuUmNvbW1hYWNjZW50ID0gNjExOwogICAgdC5MY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0LkF0aWxkZSA9IDYxMTsKICAgIHQuQW9nb25layA9IDYxMTsKICAgIHQuQXJpbmcgPSA2MTE7CiAgICB0Lk90aWxkZSA9IDcyMjsKICAgIHQuemRvdGFjY2VudCA9IDM4OTsKICAgIHQuRWNhcm9uID0gNjExOwogICAgdC5Jb2dvbmVrID0gMzMzOwogICAgdC5rY29tbWFhY2NlbnQgPSA0NDQ7CiAgICB0Lm1pbnVzID0gNjc1OwogICAgdC5JY2lyY3VtZmxleCA9IDMzMzsKICAgIHQubmNhcm9uID0gNTAwOwogICAgdC50Y29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LmxvZ2ljYWxub3QgPSA2NzU7CiAgICB0Lm9kaWVyZXNpcyA9IDUwMDsKICAgIHQudWRpZXJlc2lzID0gNTAwOwogICAgdC5ub3RlcXVhbCA9IDU0OTsKICAgIHQuZ2NvbW1hYWNjZW50ID0gNTAwOwogICAgdC5ldGggPSA1MDA7CiAgICB0LnpjYXJvbiA9IDM4OTsKICAgIHQubmNvbW1hYWNjZW50ID0gNTAwOwogICAgdC5vbmVzdXBlcmlvciA9IDMwMDsKICAgIHQuaW1hY3JvbiA9IDI3ODsKICAgIHQuRXVybyA9IDUwMDsKICB9KTsKICB0LlphcGZEaW5nYmF0cyA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI3ODsKICAgIHQuYTEgPSA5NzQ7CiAgICB0LmEyID0gOTYxOwogICAgdC5hMjAyID0gOTc0OwogICAgdC5hMyA9IDk4MDsKICAgIHQuYTQgPSA3MTk7CiAgICB0LmE1ID0gNzg5OwogICAgdC5hMTE5ID0gNzkwOwogICAgdC5hMTE4ID0gNzkxOwogICAgdC5hMTE3ID0gNjkwOwogICAgdC5hMTEgPSA5NjA7CiAgICB0LmExMiA9IDkzOTsKICAgIHQuYTEzID0gNTQ5OwogICAgdC5hMTQgPSA4NTU7CiAgICB0LmExNSA9IDkxMTsKICAgIHQuYTE2ID0gOTMzOwogICAgdC5hMTA1ID0gOTExOwogICAgdC5hMTcgPSA5NDU7CiAgICB0LmExOCA9IDk3NDsKICAgIHQuYTE5ID0gNzU1OwogICAgdC5hMjAgPSA4NDY7CiAgICB0LmEyMSA9IDc2MjsKICAgIHQuYTIyID0gNzYxOwogICAgdC5hMjMgPSA1NzE7CiAgICB0LmEyNCA9IDY3NzsKICAgIHQuYTI1ID0gNzYzOwogICAgdC5hMjYgPSA3NjA7CiAgICB0LmEyNyA9IDc1OTsKICAgIHQuYTI4ID0gNzU0OwogICAgdC5hNiA9IDQ5NDsKICAgIHQuYTcgPSA1NTI7CiAgICB0LmE4ID0gNTM3OwogICAgdC5hOSA9IDU3NzsKICAgIHQuYTEwID0gNjkyOwogICAgdC5hMjkgPSA3ODY7CiAgICB0LmEzMCA9IDc4ODsKICAgIHQuYTMxID0gNzg4OwogICAgdC5hMzIgPSA3OTA7CiAgICB0LmEzMyA9IDc5MzsKICAgIHQuYTM0ID0gNzk0OwogICAgdC5hMzUgPSA4MTY7CiAgICB0LmEzNiA9IDgyMzsKICAgIHQuYTM3ID0gNzg5OwogICAgdC5hMzggPSA4NDE7CiAgICB0LmEzOSA9IDgyMzsKICAgIHQuYTQwID0gODMzOwogICAgdC5hNDEgPSA4MTY7CiAgICB0LmE0MiA9IDgzMTsKICAgIHQuYTQzID0gOTIzOwogICAgdC5hNDQgPSA3NDQ7CiAgICB0LmE0NSA9IDcyMzsKICAgIHQuYTQ2ID0gNzQ5OwogICAgdC5hNDcgPSA3OTA7CiAgICB0LmE0OCA9IDc5MjsKICAgIHQuYTQ5ID0gNjk1OwogICAgdC5hNTAgPSA3NzY7CiAgICB0LmE1MSA9IDc2ODsKICAgIHQuYTUyID0gNzkyOwogICAgdC5hNTMgPSA3NTk7CiAgICB0LmE1NCA9IDcwNzsKICAgIHQuYTU1ID0gNzA4OwogICAgdC5hNTYgPSA2ODI7CiAgICB0LmE1NyA9IDcwMTsKICAgIHQuYTU4ID0gODI2OwogICAgdC5hNTkgPSA4MTU7CiAgICB0LmE2MCA9IDc4OTsKICAgIHQuYTYxID0gNzg5OwogICAgdC5hNjIgPSA3MDc7CiAgICB0LmE2MyA9IDY4NzsKICAgIHQuYTY0ID0gNjk2OwogICAgdC5hNjUgPSA2ODk7CiAgICB0LmE2NiA9IDc4NjsKICAgIHQuYTY3ID0gNzg3OwogICAgdC5hNjggPSA3MTM7CiAgICB0LmE2OSA9IDc5MTsKICAgIHQuYTcwID0gNzg1OwogICAgdC5hNzEgPSA3OTE7CiAgICB0LmE3MiA9IDg3MzsKICAgIHQuYTczID0gNzYxOwogICAgdC5hNzQgPSA3NjI7CiAgICB0LmEyMDMgPSA3NjI7CiAgICB0LmE3NSA9IDc1OTsKICAgIHQuYTIwNCA9IDc1OTsKICAgIHQuYTc2ID0gODkyOwogICAgdC5hNzcgPSA4OTI7CiAgICB0LmE3OCA9IDc4ODsKICAgIHQuYTc5ID0gNzg0OwogICAgdC5hODEgPSA0Mzg7CiAgICB0LmE4MiA9IDEzODsKICAgIHQuYTgzID0gMjc3OwogICAgdC5hODQgPSA0MTU7CiAgICB0LmE5NyA9IDM5MjsKICAgIHQuYTk4ID0gMzkyOwogICAgdC5hOTkgPSA2Njg7CiAgICB0LmExMDAgPSA2Njg7CiAgICB0LmE4OSA9IDM5MDsKICAgIHQuYTkwID0gMzkwOwogICAgdC5hOTMgPSAzMTc7CiAgICB0LmE5NCA9IDMxNzsKICAgIHQuYTkxID0gMjc2OwogICAgdC5hOTIgPSAyNzY7CiAgICB0LmEyMDUgPSA1MDk7CiAgICB0LmE4NSA9IDUwOTsKICAgIHQuYTIwNiA9IDQxMDsKICAgIHQuYTg2ID0gNDEwOwogICAgdC5hODcgPSAyMzQ7CiAgICB0LmE4OCA9IDIzNDsKICAgIHQuYTk1ID0gMzM0OwogICAgdC5hOTYgPSAzMzQ7CiAgICB0LmExMDEgPSA3MzI7CiAgICB0LmExMDIgPSA1NDQ7CiAgICB0LmExMDMgPSA1NDQ7CiAgICB0LmExMDQgPSA5MTA7CiAgICB0LmExMDYgPSA2Njc7CiAgICB0LmExMDcgPSA3NjA7CiAgICB0LmExMDggPSA3NjA7CiAgICB0LmExMTIgPSA3NzY7CiAgICB0LmExMTEgPSA1OTU7CiAgICB0LmExMTAgPSA2OTQ7CiAgICB0LmExMDkgPSA2MjY7CiAgICB0LmExMjAgPSA3ODg7CiAgICB0LmExMjEgPSA3ODg7CiAgICB0LmExMjIgPSA3ODg7CiAgICB0LmExMjMgPSA3ODg7CiAgICB0LmExMjQgPSA3ODg7CiAgICB0LmExMjUgPSA3ODg7CiAgICB0LmExMjYgPSA3ODg7CiAgICB0LmExMjcgPSA3ODg7CiAgICB0LmExMjggPSA3ODg7CiAgICB0LmExMjkgPSA3ODg7CiAgICB0LmExMzAgPSA3ODg7CiAgICB0LmExMzEgPSA3ODg7CiAgICB0LmExMzIgPSA3ODg7CiAgICB0LmExMzMgPSA3ODg7CiAgICB0LmExMzQgPSA3ODg7CiAgICB0LmExMzUgPSA3ODg7CiAgICB0LmExMzYgPSA3ODg7CiAgICB0LmExMzcgPSA3ODg7CiAgICB0LmExMzggPSA3ODg7CiAgICB0LmExMzkgPSA3ODg7CiAgICB0LmExNDAgPSA3ODg7CiAgICB0LmExNDEgPSA3ODg7CiAgICB0LmExNDIgPSA3ODg7CiAgICB0LmExNDMgPSA3ODg7CiAgICB0LmExNDQgPSA3ODg7CiAgICB0LmExNDUgPSA3ODg7CiAgICB0LmExNDYgPSA3ODg7CiAgICB0LmExNDcgPSA3ODg7CiAgICB0LmExNDggPSA3ODg7CiAgICB0LmExNDkgPSA3ODg7CiAgICB0LmExNTAgPSA3ODg7CiAgICB0LmExNTEgPSA3ODg7CiAgICB0LmExNTIgPSA3ODg7CiAgICB0LmExNTMgPSA3ODg7CiAgICB0LmExNTQgPSA3ODg7CiAgICB0LmExNTUgPSA3ODg7CiAgICB0LmExNTYgPSA3ODg7CiAgICB0LmExNTcgPSA3ODg7CiAgICB0LmExNTggPSA3ODg7CiAgICB0LmExNTkgPSA3ODg7CiAgICB0LmExNjAgPSA4OTQ7CiAgICB0LmExNjEgPSA4Mzg7CiAgICB0LmExNjMgPSAxMDE2OwogICAgdC5hMTY0ID0gNDU4OwogICAgdC5hMTk2ID0gNzQ4OwogICAgdC5hMTY1ID0gOTI0OwogICAgdC5hMTkyID0gNzQ4OwogICAgdC5hMTY2ID0gOTE4OwogICAgdC5hMTY3ID0gOTI3OwogICAgdC5hMTY4ID0gOTI4OwogICAgdC5hMTY5ID0gOTI4OwogICAgdC5hMTcwID0gODM0OwogICAgdC5hMTcxID0gODczOwogICAgdC5hMTcyID0gODI4OwogICAgdC5hMTczID0gOTI0OwogICAgdC5hMTYyID0gOTI0OwogICAgdC5hMTc0ID0gOTE3OwogICAgdC5hMTc1ID0gOTMwOwogICAgdC5hMTc2ID0gOTMxOwogICAgdC5hMTc3ID0gNDYzOwogICAgdC5hMTc4ID0gODgzOwogICAgdC5hMTc5ID0gODM2OwogICAgdC5hMTkzID0gODM2OwogICAgdC5hMTgwID0gODY3OwogICAgdC5hMTk5ID0gODY3OwogICAgdC5hMTgxID0gNjk2OwogICAgdC5hMjAwID0gNjk2OwogICAgdC5hMTgyID0gODc0OwogICAgdC5hMjAxID0gODc0OwogICAgdC5hMTgzID0gNzYwOwogICAgdC5hMTg0ID0gOTQ2OwogICAgdC5hMTk3ID0gNzcxOwogICAgdC5hMTg1ID0gODY1OwogICAgdC5hMTk0ID0gNzcxOwogICAgdC5hMTk4ID0gODg4OwogICAgdC5hMTg2ID0gOTY3OwogICAgdC5hMTk1ID0gODg4OwogICAgdC5hMTg3ID0gODMxOwogICAgdC5hMTg4ID0gODczOwogICAgdC5hMTg5ID0gOTI3OwogICAgdC5hMTkwID0gOTcwOwogICAgdC5hMTkxID0gOTE4OwogIH0pOwp9KTsKY29uc3QgZ2V0Rm9udEJhc2ljTWV0cmljcyA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHQuQ291cmllciA9IHsKICAgIGFzY2VudDogNjI5LAogICAgZGVzY2VudDogLTE1NywKICAgIGNhcEhlaWdodDogNTYyLAogICAgeEhlaWdodDogLTQyNgogIH07CiAgdFsiQ291cmllci1Cb2xkIl0gPSB7CiAgICBhc2NlbnQ6IDYyOSwKICAgIGRlc2NlbnQ6IC0xNTcsCiAgICBjYXBIZWlnaHQ6IDU2MiwKICAgIHhIZWlnaHQ6IDQzOQogIH07CiAgdFsiQ291cmllci1PYmxpcXVlIl0gPSB7CiAgICBhc2NlbnQ6IDYyOSwKICAgIGRlc2NlbnQ6IC0xNTcsCiAgICBjYXBIZWlnaHQ6IDU2MiwKICAgIHhIZWlnaHQ6IDQyNgogIH07CiAgdFsiQ291cmllci1Cb2xkT2JsaXF1ZSJdID0gewogICAgYXNjZW50OiA2MjksCiAgICBkZXNjZW50OiAtMTU3LAogICAgY2FwSGVpZ2h0OiA1NjIsCiAgICB4SGVpZ2h0OiA0MjYKICB9OwogIHQuSGVsdmV0aWNhID0gewogICAgYXNjZW50OiA3MTgsCiAgICBkZXNjZW50OiAtMjA3LAogICAgY2FwSGVpZ2h0OiA3MTgsCiAgICB4SGVpZ2h0OiA1MjMKICB9OwogIHRbIkhlbHZldGljYS1Cb2xkIl0gPSB7CiAgICBhc2NlbnQ6IDcxOCwKICAgIGRlc2NlbnQ6IC0yMDcsCiAgICBjYXBIZWlnaHQ6IDcxOCwKICAgIHhIZWlnaHQ6IDUzMgogIH07CiAgdFsiSGVsdmV0aWNhLU9ibGlxdWUiXSA9IHsKICAgIGFzY2VudDogNzE4LAogICAgZGVzY2VudDogLTIwNywKICAgIGNhcEhlaWdodDogNzE4LAogICAgeEhlaWdodDogNTIzCiAgfTsKICB0WyJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiXSA9IHsKICAgIGFzY2VudDogNzE4LAogICAgZGVzY2VudDogLTIwNywKICAgIGNhcEhlaWdodDogNzE4LAogICAgeEhlaWdodDogNTMyCiAgfTsKICB0WyJUaW1lcy1Sb21hbiJdID0gewogICAgYXNjZW50OiA2ODMsCiAgICBkZXNjZW50OiAtMjE3LAogICAgY2FwSGVpZ2h0OiA2NjIsCiAgICB4SGVpZ2h0OiA0NTAKICB9OwogIHRbIlRpbWVzLUJvbGQiXSA9IHsKICAgIGFzY2VudDogNjgzLAogICAgZGVzY2VudDogLTIxNywKICAgIGNhcEhlaWdodDogNjc2LAogICAgeEhlaWdodDogNDYxCiAgfTsKICB0WyJUaW1lcy1JdGFsaWMiXSA9IHsKICAgIGFzY2VudDogNjgzLAogICAgZGVzY2VudDogLTIxNywKICAgIGNhcEhlaWdodDogNjUzLAogICAgeEhlaWdodDogNDQxCiAgfTsKICB0WyJUaW1lcy1Cb2xkSXRhbGljIl0gPSB7CiAgICBhc2NlbnQ6IDY4MywKICAgIGRlc2NlbnQ6IC0yMTcsCiAgICBjYXBIZWlnaHQ6IDY2OSwKICAgIHhIZWlnaHQ6IDQ2MgogIH07CiAgdC5TeW1ib2wgPSB7CiAgICBhc2NlbnQ6IE1hdGguTmFOLAogICAgZGVzY2VudDogTWF0aC5OYU4sCiAgICBjYXBIZWlnaHQ6IE1hdGguTmFOLAogICAgeEhlaWdodDogTWF0aC5OYU4KICB9OwogIHQuWmFwZkRpbmdiYXRzID0gewogICAgYXNjZW50OiBNYXRoLk5hTiwKICAgIGRlc2NlbnQ6IE1hdGguTmFOLAogICAgY2FwSGVpZ2h0OiBNYXRoLk5hTiwKICAgIHhIZWlnaHQ6IE1hdGguTmFOCiAgfTsKfSk7Cgo7Ly8gLi9zcmMvY29yZS9nbHlmLmpzCmNvbnN0IE9OX0NVUlZFX1BPSU5UID0gMSA8PCAwOwpjb25zdCBYX1NIT1JUX1ZFQ1RPUiA9IDEgPDwgMTsKY29uc3QgWV9TSE9SVF9WRUNUT1IgPSAxIDw8IDI7CmNvbnN0IFJFUEVBVF9GTEFHID0gMSA8PCAzOwpjb25zdCBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1IgPSAxIDw8IDQ7CmNvbnN0IFlfSVNfU0FNRV9PUl9QT1NJVElWRV9ZX1NIT1JUX1ZFQ1RPUiA9IDEgPDwgNTsKY29uc3QgT1ZFUkxBUF9TSU1QTEUgPSAxIDw8IDY7CmNvbnN0IEFSR18xX0FORF8yX0FSRV9XT1JEUyA9IDEgPDwgMDsKY29uc3QgQVJHU19BUkVfWFlfVkFMVUVTID0gMSA8PCAxOwpjb25zdCBXRV9IQVZFX0FfU0NBTEUgPSAxIDw8IDM7CmNvbnN0IE1PUkVfQ09NUE9ORU5UUyA9IDEgPDwgNTsKY29uc3QgV0VfSEFWRV9BTl9YX0FORF9ZX1NDQUxFID0gMSA8PCA2Owpjb25zdCBXRV9IQVZFX0FfVFdPX0JZX1RXTyA9IDEgPDwgNzsKY29uc3QgV0VfSEFWRV9JTlNUUlVDVElPTlMgPSAxIDw8IDg7CmNsYXNzIEdseWZUYWJsZSB7CiAgY29uc3RydWN0b3IoewogICAgZ2x5ZlRhYmxlLAogICAgaXNHbHlwaExvY2F0aW9uc0xvbmcsCiAgICBsb2NhVGFibGUsCiAgICBudW1HbHlwaHMKICB9KSB7CiAgICB0aGlzLmdseXBocyA9IFtdOwogICAgY29uc3QgbG9jYSA9IG5ldyBEYXRhVmlldyhsb2NhVGFibGUuYnVmZmVyLCBsb2NhVGFibGUuYnl0ZU9mZnNldCwgbG9jYVRhYmxlLmJ5dGVMZW5ndGgpOwogICAgY29uc3QgZ2x5ZiA9IG5ldyBEYXRhVmlldyhnbHlmVGFibGUuYnVmZmVyLCBnbHlmVGFibGUuYnl0ZU9mZnNldCwgZ2x5ZlRhYmxlLmJ5dGVMZW5ndGgpOwogICAgY29uc3Qgb2Zmc2V0U2l6ZSA9IGlzR2x5cGhMb2NhdGlvbnNMb25nID8gNCA6IDI7CiAgICBsZXQgcHJldiA9IGlzR2x5cGhMb2NhdGlvbnNMb25nID8gbG9jYS5nZXRVaW50MzIoMCkgOiAyICogbG9jYS5nZXRVaW50MTYoMCk7CiAgICBsZXQgcG9zID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtR2x5cGhzOyBpKyspIHsKICAgICAgcG9zICs9IG9mZnNldFNpemU7CiAgICAgIGNvbnN0IG5leHQgPSBpc0dseXBoTG9jYXRpb25zTG9uZyA/IGxvY2EuZ2V0VWludDMyKHBvcykgOiAyICogbG9jYS5nZXRVaW50MTYocG9zKTsKICAgICAgaWYgKG5leHQgPT09IHByZXYpIHsKICAgICAgICB0aGlzLmdseXBocy5wdXNoKG5ldyBHbHlwaCh7fSkpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGdseXBoID0gR2x5cGgucGFyc2UocHJldiwgZ2x5Zik7CiAgICAgIHRoaXMuZ2x5cGhzLnB1c2goZ2x5cGgpOwogICAgICBwcmV2ID0gbmV4dDsKICAgIH0KICB9CiAgZ2V0U2l6ZSgpIHsKICAgIHJldHVybiBNYXRoLnN1bVByZWNpc2UodGhpcy5nbHlwaHMubWFwKGcgPT4gZy5nZXRTaXplKCkgKyAzICYgfjMpKTsKICB9CiAgd3JpdGUoKSB7CiAgICBjb25zdCB0b3RhbFNpemUgPSB0aGlzLmdldFNpemUoKTsKICAgIGNvbnN0IGdseWZUYWJsZSA9IG5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIodG90YWxTaXplKSk7CiAgICBjb25zdCBpc0xvY2F0aW9uTG9uZyA9IHRvdGFsU2l6ZSA+IDB4MWZmZmU7CiAgICBjb25zdCBvZmZzZXRTaXplID0gaXNMb2NhdGlvbkxvbmcgPyA0IDogMjsKICAgIGNvbnN0IGxvY2FUYWJsZSA9IG5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIoKHRoaXMuZ2x5cGhzLmxlbmd0aCArIDEpICogb2Zmc2V0U2l6ZSkpOwogICAgaWYgKGlzTG9jYXRpb25Mb25nKSB7CiAgICAgIGxvY2FUYWJsZS5zZXRVaW50MzIoMCwgMCk7CiAgICB9IGVsc2UgewogICAgICBsb2NhVGFibGUuc2V0VWludDE2KDAsIDApOwogICAgfQogICAgbGV0IHBvcyA9IDA7CiAgICBsZXQgbG9jYUluZGV4ID0gMDsKICAgIGZvciAoY29uc3QgZ2x5cGggb2YgdGhpcy5nbHlwaHMpIHsKICAgICAgcG9zICs9IGdseXBoLndyaXRlKHBvcywgZ2x5ZlRhYmxlKTsKICAgICAgcG9zID0gcG9zICsgMyAmIH4zOwogICAgICBsb2NhSW5kZXggKz0gb2Zmc2V0U2l6ZTsKICAgICAgaWYgKGlzTG9jYXRpb25Mb25nKSB7CiAgICAgICAgbG9jYVRhYmxlLnNldFVpbnQzMihsb2NhSW5kZXgsIHBvcyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbG9jYVRhYmxlLnNldFVpbnQxNihsb2NhSW5kZXgsIHBvcyA+PiAxKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHsKICAgICAgaXNMb2NhdGlvbkxvbmcsCiAgICAgIGxvY2E6IG5ldyBVaW50OEFycmF5KGxvY2FUYWJsZS5idWZmZXIpLAogICAgICBnbHlmOiBuZXcgVWludDhBcnJheShnbHlmVGFibGUuYnVmZmVyKQogICAgfTsKICB9CiAgc2NhbGUoZmFjdG9ycykgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdGhpcy5nbHlwaHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICB0aGlzLmdseXBoc1tpXS5zY2FsZShmYWN0b3JzW2ldKTsKICAgIH0KICB9Cn0KY2xhc3MgR2x5cGggewogIGNvbnN0cnVjdG9yKHsKICAgIGhlYWRlciA9IG51bGwsCiAgICBzaW1wbGUgPSBudWxsLAogICAgY29tcG9zaXRlcyA9IG51bGwKICB9KSB7CiAgICB0aGlzLmhlYWRlciA9IGhlYWRlcjsKICAgIHRoaXMuc2ltcGxlID0gc2ltcGxlOwogICAgdGhpcy5jb21wb3NpdGVzID0gY29tcG9zaXRlczsKICB9CiAgc3RhdGljIHBhcnNlKHBvcywgZ2x5ZikgewogICAgY29uc3QgW3JlYWQsIGhlYWRlcl0gPSBHbHlwaEhlYWRlci5wYXJzZShwb3MsIGdseWYpOwogICAgcG9zICs9IHJlYWQ7CiAgICBpZiAoaGVhZGVyLm51bWJlck9mQ29udG91cnMgPCAwKSB7CiAgICAgIGNvbnN0IGNvbXBvc2l0ZXMgPSBbXTsKICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICBjb25zdCBbbiwgY29tcG9zaXRlXSA9IENvbXBvc2l0ZUdseXBoLnBhcnNlKHBvcywgZ2x5Zik7CiAgICAgICAgcG9zICs9IG47CiAgICAgICAgY29tcG9zaXRlcy5wdXNoKGNvbXBvc2l0ZSk7CiAgICAgICAgaWYgKCEoY29tcG9zaXRlLmZsYWdzICYgTU9SRV9DT01QT05FTlRTKSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBuZXcgR2x5cGgoewogICAgICAgIGhlYWRlciwKICAgICAgICBjb21wb3NpdGVzCiAgICAgIH0pOwogICAgfQogICAgY29uc3Qgc2ltcGxlID0gU2ltcGxlR2x5cGgucGFyc2UocG9zLCBnbHlmLCBoZWFkZXIubnVtYmVyT2ZDb250b3Vycyk7CiAgICByZXR1cm4gbmV3IEdseXBoKHsKICAgICAgaGVhZGVyLAogICAgICBzaW1wbGUKICAgIH0pOwogIH0KICBnZXRTaXplKCkgewogICAgaWYgKCF0aGlzLmhlYWRlcikgewogICAgICByZXR1cm4gMDsKICAgIH0KICAgIGNvbnN0IHNpemUgPSB0aGlzLnNpbXBsZSA/IHRoaXMuc2ltcGxlLmdldFNpemUoKSA6IE1hdGguc3VtUHJlY2lzZSh0aGlzLmNvbXBvc2l0ZXMubWFwKGMgPT4gYy5nZXRTaXplKCkpKTsKICAgIHJldHVybiB0aGlzLmhlYWRlci5nZXRTaXplKCkgKyBzaXplOwogIH0KICB3cml0ZShwb3MsIGJ1ZikgewogICAgaWYgKCF0aGlzLmhlYWRlcikgewogICAgICByZXR1cm4gMDsKICAgIH0KICAgIGNvbnN0IHNwb3MgPSBwb3M7CiAgICBwb3MgKz0gdGhpcy5oZWFkZXIud3JpdGUocG9zLCBidWYpOwogICAgaWYgKHRoaXMuc2ltcGxlKSB7CiAgICAgIHBvcyArPSB0aGlzLnNpbXBsZS53cml0ZShwb3MsIGJ1Zik7CiAgICB9IGVsc2UgewogICAgICBmb3IgKGNvbnN0IGNvbXBvc2l0ZSBvZiB0aGlzLmNvbXBvc2l0ZXMpIHsKICAgICAgICBwb3MgKz0gY29tcG9zaXRlLndyaXRlKHBvcywgYnVmKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHBvcyAtIHNwb3M7CiAgfQogIHNjYWxlKGZhY3RvcikgewogICAgaWYgKCF0aGlzLmhlYWRlcikgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCB4TWlkZGxlID0gKHRoaXMuaGVhZGVyLnhNaW4gKyB0aGlzLmhlYWRlci54TWF4KSAvIDI7CiAgICB0aGlzLmhlYWRlci5zY2FsZSh4TWlkZGxlLCBmYWN0b3IpOwogICAgaWYgKHRoaXMuc2ltcGxlKSB7CiAgICAgIHRoaXMuc2ltcGxlLnNjYWxlKHhNaWRkbGUsIGZhY3Rvcik7CiAgICB9IGVsc2UgewogICAgICBmb3IgKGNvbnN0IGNvbXBvc2l0ZSBvZiB0aGlzLmNvbXBvc2l0ZXMpIHsKICAgICAgICBjb21wb3NpdGUuc2NhbGUoeE1pZGRsZSwgZmFjdG9yKTsKICAgICAgfQogICAgfQogIH0KfQpjbGFzcyBHbHlwaEhlYWRlciB7CiAgY29uc3RydWN0b3IoewogICAgbnVtYmVyT2ZDb250b3VycywKICAgIHhNaW4sCiAgICB5TWluLAogICAgeE1heCwKICAgIHlNYXgKICB9KSB7CiAgICB0aGlzLm51bWJlck9mQ29udG91cnMgPSBudW1iZXJPZkNvbnRvdXJzOwogICAgdGhpcy54TWluID0geE1pbjsKICAgIHRoaXMueU1pbiA9IHlNaW47CiAgICB0aGlzLnhNYXggPSB4TWF4OwogICAgdGhpcy55TWF4ID0geU1heDsKICB9CiAgc3RhdGljIHBhcnNlKHBvcywgZ2x5ZikgewogICAgcmV0dXJuIFsxMCwgbmV3IEdseXBoSGVhZGVyKHsKICAgICAgbnVtYmVyT2ZDb250b3VyczogZ2x5Zi5nZXRJbnQxNihwb3MpLAogICAgICB4TWluOiBnbHlmLmdldEludDE2KHBvcyArIDIpLAogICAgICB5TWluOiBnbHlmLmdldEludDE2KHBvcyArIDQpLAogICAgICB4TWF4OiBnbHlmLmdldEludDE2KHBvcyArIDYpLAogICAgICB5TWF4OiBnbHlmLmdldEludDE2KHBvcyArIDgpCiAgICB9KV07CiAgfQogIGdldFNpemUoKSB7CiAgICByZXR1cm4gMTA7CiAgfQogIHdyaXRlKHBvcywgYnVmKSB7CiAgICBidWYuc2V0SW50MTYocG9zLCB0aGlzLm51bWJlck9mQ29udG91cnMpOwogICAgYnVmLnNldEludDE2KHBvcyArIDIsIHRoaXMueE1pbik7CiAgICBidWYuc2V0SW50MTYocG9zICsgNCwgdGhpcy55TWluKTsKICAgIGJ1Zi5zZXRJbnQxNihwb3MgKyA2LCB0aGlzLnhNYXgpOwogICAgYnVmLnNldEludDE2KHBvcyArIDgsIHRoaXMueU1heCk7CiAgICByZXR1cm4gMTA7CiAgfQogIHNjYWxlKHgsIGZhY3RvcikgewogICAgdGhpcy54TWluID0gTWF0aC5yb3VuZCh4ICsgKHRoaXMueE1pbiAtIHgpICogZmFjdG9yKTsKICAgIHRoaXMueE1heCA9IE1hdGgucm91bmQoeCArICh0aGlzLnhNYXggLSB4KSAqIGZhY3Rvcik7CiAgfQp9CmNsYXNzIENvbnRvdXIgewogIGNvbnN0cnVjdG9yKHsKICAgIGZsYWdzLAogICAgeENvb3JkaW5hdGVzLAogICAgeUNvb3JkaW5hdGVzCiAgfSkgewogICAgdGhpcy54Q29vcmRpbmF0ZXMgPSB4Q29vcmRpbmF0ZXM7CiAgICB0aGlzLnlDb29yZGluYXRlcyA9IHlDb29yZGluYXRlczsKICAgIHRoaXMuZmxhZ3MgPSBmbGFnczsKICB9Cn0KY2xhc3MgU2ltcGxlR2x5cGggewogIGNvbnN0cnVjdG9yKHsKICAgIGNvbnRvdXJzLAogICAgaW5zdHJ1Y3Rpb25zCiAgfSkgewogICAgdGhpcy5jb250b3VycyA9IGNvbnRvdXJzOwogICAgdGhpcy5pbnN0cnVjdGlvbnMgPSBpbnN0cnVjdGlvbnM7CiAgfQogIHN0YXRpYyBwYXJzZShwb3MsIGdseWYsIG51bWJlck9mQ29udG91cnMpIHsKICAgIGNvbnN0IGVuZFB0c09mQ29udG91cnMgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZDb250b3VyczsgaSsrKSB7CiAgICAgIGNvbnN0IGVuZFB0ID0gZ2x5Zi5nZXRVaW50MTYocG9zKTsKICAgICAgcG9zICs9IDI7CiAgICAgIGVuZFB0c09mQ29udG91cnMucHVzaChlbmRQdCk7CiAgICB9CiAgICBjb25zdCBudW1iZXJPZlB0ID0gZW5kUHRzT2ZDb250b3Vyc1tudW1iZXJPZkNvbnRvdXJzIC0gMV0gKyAxOwogICAgY29uc3QgaW5zdHJ1Y3Rpb25MZW5ndGggPSBnbHlmLmdldFVpbnQxNihwb3MpOwogICAgcG9zICs9IDI7CiAgICBjb25zdCBpbnN0cnVjdGlvbnMgPSBuZXcgVWludDhBcnJheShnbHlmKS5zbGljZShwb3MsIHBvcyArIGluc3RydWN0aW9uTGVuZ3RoKTsKICAgIHBvcyArPSBpbnN0cnVjdGlvbkxlbmd0aDsKICAgIGNvbnN0IGZsYWdzID0gW107CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlck9mUHQ7IHBvcysrLCBpKyspIHsKICAgICAgbGV0IGZsYWcgPSBnbHlmLmdldFVpbnQ4KHBvcyk7CiAgICAgIGZsYWdzLnB1c2goZmxhZyk7CiAgICAgIGlmIChmbGFnICYgUkVQRUFUX0ZMQUcpIHsKICAgICAgICBjb25zdCBjb3VudCA9IGdseWYuZ2V0VWludDgoKytwb3MpOwogICAgICAgIGZsYWcgXj0gUkVQRUFUX0ZMQUc7CiAgICAgICAgZm9yIChsZXQgbSA9IDA7IG0gPCBjb3VudDsgbSsrKSB7CiAgICAgICAgICBmbGFncy5wdXNoKGZsYWcpOwogICAgICAgIH0KICAgICAgICBpICs9IGNvdW50OwogICAgICB9CiAgICB9CiAgICBjb25zdCBhbGxYQ29vcmRpbmF0ZXMgPSBbXTsKICAgIGxldCB4Q29vcmRpbmF0ZXMgPSBbXTsKICAgIGxldCB5Q29vcmRpbmF0ZXMgPSBbXTsKICAgIGxldCBwb2ludEZsYWdzID0gW107CiAgICBjb25zdCBjb250b3VycyA9IFtdOwogICAgbGV0IGVuZFB0c09mQ29udG91cnNJbmRleCA9IDA7CiAgICBsZXQgbGFzdENvb3JkaW5hdGUgPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZlB0OyBpKyspIHsKICAgICAgY29uc3QgZmxhZyA9IGZsYWdzW2ldOwogICAgICBpZiAoZmxhZyAmIFhfU0hPUlRfVkVDVE9SKSB7CiAgICAgICAgY29uc3QgeCA9IGdseWYuZ2V0VWludDgocG9zKyspOwogICAgICAgIGxhc3RDb29yZGluYXRlICs9IGZsYWcgJiBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1IgPyB4IDogLXg7CiAgICAgICAgeENvb3JkaW5hdGVzLnB1c2gobGFzdENvb3JkaW5hdGUpOwogICAgICB9IGVsc2UgaWYgKGZsYWcgJiBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1IpIHsKICAgICAgICB4Q29vcmRpbmF0ZXMucHVzaChsYXN0Q29vcmRpbmF0ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbGFzdENvb3JkaW5hdGUgKz0gZ2x5Zi5nZXRJbnQxNihwb3MpOwogICAgICAgIHBvcyArPSAyOwogICAgICAgIHhDb29yZGluYXRlcy5wdXNoKGxhc3RDb29yZGluYXRlKTsKICAgICAgfQogICAgICBpZiAoZW5kUHRzT2ZDb250b3Vyc1tlbmRQdHNPZkNvbnRvdXJzSW5kZXhdID09PSBpKSB7CiAgICAgICAgZW5kUHRzT2ZDb250b3Vyc0luZGV4Kys7CiAgICAgICAgYWxsWENvb3JkaW5hdGVzLnB1c2goeENvb3JkaW5hdGVzKTsKICAgICAgICB4Q29vcmRpbmF0ZXMgPSBbXTsKICAgICAgfQogICAgfQogICAgbGFzdENvb3JkaW5hdGUgPSAwOwogICAgZW5kUHRzT2ZDb250b3Vyc0luZGV4ID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZQdDsgaSsrKSB7CiAgICAgIGNvbnN0IGZsYWcgPSBmbGFnc1tpXTsKICAgICAgaWYgKGZsYWcgJiBZX1NIT1JUX1ZFQ1RPUikgewogICAgICAgIGNvbnN0IHkgPSBnbHlmLmdldFVpbnQ4KHBvcysrKTsKICAgICAgICBsYXN0Q29vcmRpbmF0ZSArPSBmbGFnICYgWV9JU19TQU1FX09SX1BPU0lUSVZFX1lfU0hPUlRfVkVDVE9SID8geSA6IC15OwogICAgICAgIHlDb29yZGluYXRlcy5wdXNoKGxhc3RDb29yZGluYXRlKTsKICAgICAgfSBlbHNlIGlmIChmbGFnICYgWV9JU19TQU1FX09SX1BPU0lUSVZFX1lfU0hPUlRfVkVDVE9SKSB7CiAgICAgICAgeUNvb3JkaW5hdGVzLnB1c2gobGFzdENvb3JkaW5hdGUpOwogICAgICB9IGVsc2UgewogICAgICAgIGxhc3RDb29yZGluYXRlICs9IGdseWYuZ2V0SW50MTYocG9zKTsKICAgICAgICBwb3MgKz0gMjsKICAgICAgICB5Q29vcmRpbmF0ZXMucHVzaChsYXN0Q29vcmRpbmF0ZSk7CiAgICAgIH0KICAgICAgcG9pbnRGbGFncy5wdXNoKGZsYWcgJiBPTl9DVVJWRV9QT0lOVCB8IGZsYWcgJiBPVkVSTEFQX1NJTVBMRSk7CiAgICAgIGlmIChlbmRQdHNPZkNvbnRvdXJzW2VuZFB0c09mQ29udG91cnNJbmRleF0gPT09IGkpIHsKICAgICAgICB4Q29vcmRpbmF0ZXMgPSBhbGxYQ29vcmRpbmF0ZXNbZW5kUHRzT2ZDb250b3Vyc0luZGV4XTsKICAgICAgICBlbmRQdHNPZkNvbnRvdXJzSW5kZXgrKzsKICAgICAgICBjb250b3Vycy5wdXNoKG5ldyBDb250b3VyKHsKICAgICAgICAgIGZsYWdzOiBwb2ludEZsYWdzLAogICAgICAgICAgeENvb3JkaW5hdGVzLAogICAgICAgICAgeUNvb3JkaW5hdGVzCiAgICAgICAgfSkpOwogICAgICAgIHlDb29yZGluYXRlcyA9IFtdOwogICAgICAgIHBvaW50RmxhZ3MgPSBbXTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG5ldyBTaW1wbGVHbHlwaCh7CiAgICAgIGNvbnRvdXJzLAogICAgICBpbnN0cnVjdGlvbnMKICAgIH0pOwogIH0KICBnZXRTaXplKCkgewogICAgbGV0IHNpemUgPSB0aGlzLmNvbnRvdXJzLmxlbmd0aCAqIDIgKyAyICsgdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoOwogICAgbGV0IGxhc3RYID0gMDsKICAgIGxldCBsYXN0WSA9IDA7CiAgICBmb3IgKGNvbnN0IGNvbnRvdXIgb2YgdGhpcy5jb250b3VycykgewogICAgICBzaXplICs9IGNvbnRvdXIuZmxhZ3MubGVuZ3RoOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBjb250b3VyLnhDb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3QgeCA9IGNvbnRvdXIueENvb3JkaW5hdGVzW2ldOwogICAgICAgIGNvbnN0IHkgPSBjb250b3VyLnlDb29yZGluYXRlc1tpXTsKICAgICAgICBsZXQgYWJzID0gTWF0aC5hYnMoeCAtIGxhc3RYKTsKICAgICAgICBpZiAoYWJzID4gMjU1KSB7CiAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgfSBlbHNlIGlmIChhYnMgPiAwKSB7CiAgICAgICAgICBzaXplICs9IDE7CiAgICAgICAgfQogICAgICAgIGxhc3RYID0geDsKICAgICAgICBhYnMgPSBNYXRoLmFicyh5IC0gbGFzdFkpOwogICAgICAgIGlmIChhYnMgPiAyNTUpIHsKICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICB9IGVsc2UgaWYgKGFicyA+IDApIHsKICAgICAgICAgIHNpemUgKz0gMTsKICAgICAgICB9CiAgICAgICAgbGFzdFkgPSB5OwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2l6ZTsKICB9CiAgd3JpdGUocG9zLCBidWYpIHsKICAgIGNvbnN0IHNwb3MgPSBwb3M7CiAgICBjb25zdCB4Q29vcmRpbmF0ZXMgPSBbXTsKICAgIGNvbnN0IHlDb29yZGluYXRlcyA9IFtdOwogICAgY29uc3QgZmxhZ3MgPSBbXTsKICAgIGxldCBsYXN0WCA9IDA7CiAgICBsZXQgbGFzdFkgPSAwOwogICAgZm9yIChjb25zdCBjb250b3VyIG9mIHRoaXMuY29udG91cnMpIHsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gY29udG91ci54Q29vcmRpbmF0ZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGxldCBmbGFnID0gY29udG91ci5mbGFnc1tpXTsKICAgICAgICBjb25zdCB4ID0gY29udG91ci54Q29vcmRpbmF0ZXNbaV07CiAgICAgICAgbGV0IGRlbHRhID0geCAtIGxhc3RYOwogICAgICAgIGlmIChkZWx0YSA9PT0gMCkgewogICAgICAgICAgZmxhZyB8PSBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1I7CiAgICAgICAgICB4Q29vcmRpbmF0ZXMucHVzaCgwKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgYWJzID0gTWF0aC5hYnMoZGVsdGEpOwogICAgICAgICAgaWYgKGFicyA8PSAyNTUpIHsKICAgICAgICAgICAgZmxhZyB8PSBkZWx0YSA+PSAwID8gWF9TSE9SVF9WRUNUT1IgfCBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1IgOiBYX1NIT1JUX1ZFQ1RPUjsKICAgICAgICAgICAgeENvb3JkaW5hdGVzLnB1c2goYWJzKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHhDb29yZGluYXRlcy5wdXNoKGRlbHRhKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbGFzdFggPSB4OwogICAgICAgIGNvbnN0IHkgPSBjb250b3VyLnlDb29yZGluYXRlc1tpXTsKICAgICAgICBkZWx0YSA9IHkgLSBsYXN0WTsKICAgICAgICBpZiAoZGVsdGEgPT09IDApIHsKICAgICAgICAgIGZsYWcgfD0gWV9JU19TQU1FX09SX1BPU0lUSVZFX1lfU0hPUlRfVkVDVE9SOwogICAgICAgICAgeUNvb3JkaW5hdGVzLnB1c2goMCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvbnN0IGFicyA9IE1hdGguYWJzKGRlbHRhKTsKICAgICAgICAgIGlmIChhYnMgPD0gMjU1KSB7CiAgICAgICAgICAgIGZsYWcgfD0gZGVsdGEgPj0gMCA/IFlfU0hPUlRfVkVDVE9SIHwgWV9JU19TQU1FX09SX1BPU0lUSVZFX1lfU0hPUlRfVkVDVE9SIDogWV9TSE9SVF9WRUNUT1I7CiAgICAgICAgICAgIHlDb29yZGluYXRlcy5wdXNoKGFicyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB5Q29vcmRpbmF0ZXMucHVzaChkZWx0YSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGxhc3RZID0geTsKICAgICAgICBmbGFncy5wdXNoKGZsYWcpOwogICAgICB9CiAgICAgIGJ1Zi5zZXRVaW50MTYocG9zLCB4Q29vcmRpbmF0ZXMubGVuZ3RoIC0gMSk7CiAgICAgIHBvcyArPSAyOwogICAgfQogICAgYnVmLnNldFVpbnQxNihwb3MsIHRoaXMuaW5zdHJ1Y3Rpb25zLmxlbmd0aCk7CiAgICBwb3MgKz0gMjsKICAgIGlmICh0aGlzLmluc3RydWN0aW9ucy5sZW5ndGgpIHsKICAgICAgbmV3IFVpbnQ4QXJyYXkoYnVmLmJ1ZmZlciwgMCwgYnVmLmJ1ZmZlci5ieXRlTGVuZ3RoKS5zZXQodGhpcy5pbnN0cnVjdGlvbnMsIHBvcyk7CiAgICAgIHBvcyArPSB0aGlzLmluc3RydWN0aW9ucy5sZW5ndGg7CiAgICB9CiAgICBmb3IgKGNvbnN0IGZsYWcgb2YgZmxhZ3MpIHsKICAgICAgYnVmLnNldFVpbnQ4KHBvcysrLCBmbGFnKTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHhDb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IHggPSB4Q29vcmRpbmF0ZXNbaV07CiAgICAgIGNvbnN0IGZsYWcgPSBmbGFnc1tpXTsKICAgICAgaWYgKGZsYWcgJiBYX1NIT1JUX1ZFQ1RPUikgewogICAgICAgIGJ1Zi5zZXRVaW50OChwb3MrKywgeCk7CiAgICAgIH0gZWxzZSBpZiAoIShmbGFnICYgWF9JU19TQU1FX09SX1BPU0lUSVZFX1hfU0hPUlRfVkVDVE9SKSkgewogICAgICAgIGJ1Zi5zZXRJbnQxNihwb3MsIHgpOwogICAgICAgIHBvcyArPSAyOwogICAgICB9CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB5Q29vcmRpbmF0ZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCB5ID0geUNvb3JkaW5hdGVzW2ldOwogICAgICBjb25zdCBmbGFnID0gZmxhZ3NbaV07CiAgICAgIGlmIChmbGFnICYgWV9TSE9SVF9WRUNUT1IpIHsKICAgICAgICBidWYuc2V0VWludDgocG9zKyssIHkpOwogICAgICB9IGVsc2UgaWYgKCEoZmxhZyAmIFlfSVNfU0FNRV9PUl9QT1NJVElWRV9ZX1NIT1JUX1ZFQ1RPUikpIHsKICAgICAgICBidWYuc2V0SW50MTYocG9zLCB5KTsKICAgICAgICBwb3MgKz0gMjsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHBvcyAtIHNwb3M7CiAgfQogIHNjYWxlKHgsIGZhY3RvcikgewogICAgZm9yIChjb25zdCBjb250b3VyIG9mIHRoaXMuY29udG91cnMpIHsKICAgICAgaWYgKGNvbnRvdXIueENvb3JkaW5hdGVzLmxlbmd0aCA9PT0gMCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGNvbnRvdXIueENvb3JkaW5hdGVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb250b3VyLnhDb29yZGluYXRlc1tpXSA9IE1hdGgucm91bmQoeCArIChjb250b3VyLnhDb29yZGluYXRlc1tpXSAtIHgpICogZmFjdG9yKTsKICAgICAgfQogICAgfQogIH0KfQpjbGFzcyBDb21wb3NpdGVHbHlwaCB7CiAgY29uc3RydWN0b3IoewogICAgZmxhZ3MsCiAgICBnbHlwaEluZGV4LAogICAgYXJndW1lbnQxLAogICAgYXJndW1lbnQyLAogICAgdHJhbnNmLAogICAgaW5zdHJ1Y3Rpb25zCiAgfSkgewogICAgdGhpcy5mbGFncyA9IGZsYWdzOwogICAgdGhpcy5nbHlwaEluZGV4ID0gZ2x5cGhJbmRleDsKICAgIHRoaXMuYXJndW1lbnQxID0gYXJndW1lbnQxOwogICAgdGhpcy5hcmd1bWVudDIgPSBhcmd1bWVudDI7CiAgICB0aGlzLnRyYW5zZiA9IHRyYW5zZjsKICAgIHRoaXMuaW5zdHJ1Y3Rpb25zID0gaW5zdHJ1Y3Rpb25zOwogIH0KICBzdGF0aWMgcGFyc2UocG9zLCBnbHlmKSB7CiAgICBjb25zdCBzcG9zID0gcG9zOwogICAgY29uc3QgdHJhbnNmID0gW107CiAgICBsZXQgZmxhZ3MgPSBnbHlmLmdldFVpbnQxNihwb3MpOwogICAgY29uc3QgZ2x5cGhJbmRleCA9IGdseWYuZ2V0VWludDE2KHBvcyArIDIpOwogICAgcG9zICs9IDQ7CiAgICBsZXQgYXJndW1lbnQxLCBhcmd1bWVudDI7CiAgICBpZiAoZmxhZ3MgJiBBUkdfMV9BTkRfMl9BUkVfV09SRFMpIHsKICAgICAgaWYgKGZsYWdzICYgQVJHU19BUkVfWFlfVkFMVUVTKSB7CiAgICAgICAgYXJndW1lbnQxID0gZ2x5Zi5nZXRJbnQxNihwb3MpOwogICAgICAgIGFyZ3VtZW50MiA9IGdseWYuZ2V0SW50MTYocG9zICsgMik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYXJndW1lbnQxID0gZ2x5Zi5nZXRVaW50MTYocG9zKTsKICAgICAgICBhcmd1bWVudDIgPSBnbHlmLmdldFVpbnQxNihwb3MgKyAyKTsKICAgICAgfQogICAgICBwb3MgKz0gNDsKICAgICAgZmxhZ3MgXj0gQVJHXzFfQU5EXzJfQVJFX1dPUkRTOwogICAgfSBlbHNlIHsKICAgICAgaWYgKGZsYWdzICYgQVJHU19BUkVfWFlfVkFMVUVTKSB7CiAgICAgICAgYXJndW1lbnQxID0gZ2x5Zi5nZXRJbnQ4KHBvcyk7CiAgICAgICAgYXJndW1lbnQyID0gZ2x5Zi5nZXRJbnQ4KHBvcyArIDEpOwogICAgICB9IGVsc2UgewogICAgICAgIGFyZ3VtZW50MSA9IGdseWYuZ2V0VWludDgocG9zKTsKICAgICAgICBhcmd1bWVudDIgPSBnbHlmLmdldFVpbnQ4KHBvcyArIDEpOwogICAgICB9CiAgICAgIHBvcyArPSAyOwogICAgfQogICAgaWYgKGZsYWdzICYgV0VfSEFWRV9BX1NDQUxFKSB7CiAgICAgIHRyYW5zZi5wdXNoKGdseWYuZ2V0VWludDE2KHBvcykpOwogICAgICBwb3MgKz0gMjsKICAgIH0gZWxzZSBpZiAoZmxhZ3MgJiBXRV9IQVZFX0FOX1hfQU5EX1lfU0NBTEUpIHsKICAgICAgdHJhbnNmLnB1c2goZ2x5Zi5nZXRVaW50MTYocG9zKSwgZ2x5Zi5nZXRVaW50MTYocG9zICsgMikpOwogICAgICBwb3MgKz0gNDsKICAgIH0gZWxzZSBpZiAoZmxhZ3MgJiBXRV9IQVZFX0FfVFdPX0JZX1RXTykgewogICAgICB0cmFuc2YucHVzaChnbHlmLmdldFVpbnQxNihwb3MpLCBnbHlmLmdldFVpbnQxNihwb3MgKyAyKSwgZ2x5Zi5nZXRVaW50MTYocG9zICsgNCksIGdseWYuZ2V0VWludDE2KHBvcyArIDYpKTsKICAgICAgcG9zICs9IDg7CiAgICB9CiAgICBsZXQgaW5zdHJ1Y3Rpb25zID0gbnVsbDsKICAgIGlmIChmbGFncyAmIFdFX0hBVkVfSU5TVFJVQ1RJT05TKSB7CiAgICAgIGNvbnN0IGluc3RydWN0aW9uTGVuZ3RoID0gZ2x5Zi5nZXRVaW50MTYocG9zKTsKICAgICAgcG9zICs9IDI7CiAgICAgIGluc3RydWN0aW9ucyA9IG5ldyBVaW50OEFycmF5KGdseWYpLnNsaWNlKHBvcywgcG9zICsgaW5zdHJ1Y3Rpb25MZW5ndGgpOwogICAgICBwb3MgKz0gaW5zdHJ1Y3Rpb25MZW5ndGg7CiAgICB9CiAgICByZXR1cm4gW3BvcyAtIHNwb3MsIG5ldyBDb21wb3NpdGVHbHlwaCh7CiAgICAgIGZsYWdzLAogICAgICBnbHlwaEluZGV4LAogICAgICBhcmd1bWVudDEsCiAgICAgIGFyZ3VtZW50MiwKICAgICAgdHJhbnNmLAogICAgICBpbnN0cnVjdGlvbnMKICAgIH0pXTsKICB9CiAgZ2V0U2l6ZSgpIHsKICAgIGxldCBzaXplID0gMiArIDIgKyB0aGlzLnRyYW5zZi5sZW5ndGggKiAyOwogICAgaWYgKHRoaXMuZmxhZ3MgJiBXRV9IQVZFX0lOU1RSVUNUSU9OUykgewogICAgICBzaXplICs9IDIgKyB0aGlzLmluc3RydWN0aW9ucy5sZW5ndGg7CiAgICB9CiAgICBzaXplICs9IDI7CiAgICBpZiAodGhpcy5mbGFncyAmIDIpIHsKICAgICAgaWYgKCEodGhpcy5hcmd1bWVudDEgPj0gLTEyOCAmJiB0aGlzLmFyZ3VtZW50MSA8PSAxMjcgJiYgdGhpcy5hcmd1bWVudDIgPj0gLTEyOCAmJiB0aGlzLmFyZ3VtZW50MiA8PSAxMjcpKSB7CiAgICAgICAgc2l6ZSArPSAyOwogICAgICB9CiAgICB9IGVsc2UgaWYgKCEodGhpcy5hcmd1bWVudDEgPj0gMCAmJiB0aGlzLmFyZ3VtZW50MSA8PSAyNTUgJiYgdGhpcy5hcmd1bWVudDIgPj0gMCAmJiB0aGlzLmFyZ3VtZW50MiA8PSAyNTUpKSB7CiAgICAgIHNpemUgKz0gMjsKICAgIH0KICAgIHJldHVybiBzaXplOwogIH0KICB3cml0ZShwb3MsIGJ1ZikgewogICAgY29uc3Qgc3BvcyA9IHBvczsKICAgIGlmICh0aGlzLmZsYWdzICYgQVJHU19BUkVfWFlfVkFMVUVTKSB7CiAgICAgIGlmICghKHRoaXMuYXJndW1lbnQxID49IC0xMjggJiYgdGhpcy5hcmd1bWVudDEgPD0gMTI3ICYmIHRoaXMuYXJndW1lbnQyID49IC0xMjggJiYgdGhpcy5hcmd1bWVudDIgPD0gMTI3KSkgewogICAgICAgIHRoaXMuZmxhZ3MgfD0gQVJHXzFfQU5EXzJfQVJFX1dPUkRTOwogICAgICB9CiAgICB9IGVsc2UgaWYgKCEodGhpcy5hcmd1bWVudDEgPj0gMCAmJiB0aGlzLmFyZ3VtZW50MSA8PSAyNTUgJiYgdGhpcy5hcmd1bWVudDIgPj0gMCAmJiB0aGlzLmFyZ3VtZW50MiA8PSAyNTUpKSB7CiAgICAgIHRoaXMuZmxhZ3MgfD0gQVJHXzFfQU5EXzJfQVJFX1dPUkRTOwogICAgfQogICAgYnVmLnNldFVpbnQxNihwb3MsIHRoaXMuZmxhZ3MpOwogICAgYnVmLnNldFVpbnQxNihwb3MgKyAyLCB0aGlzLmdseXBoSW5kZXgpOwogICAgcG9zICs9IDQ7CiAgICBpZiAodGhpcy5mbGFncyAmIEFSR18xX0FORF8yX0FSRV9XT1JEUykgewogICAgICBpZiAodGhpcy5mbGFncyAmIEFSR1NfQVJFX1hZX1ZBTFVFUykgewogICAgICAgIGJ1Zi5zZXRJbnQxNihwb3MsIHRoaXMuYXJndW1lbnQxKTsKICAgICAgICBidWYuc2V0SW50MTYocG9zICsgMiwgdGhpcy5hcmd1bWVudDIpOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1Zi5zZXRVaW50MTYocG9zLCB0aGlzLmFyZ3VtZW50MSk7CiAgICAgICAgYnVmLnNldFVpbnQxNihwb3MgKyAyLCB0aGlzLmFyZ3VtZW50Mik7CiAgICAgIH0KICAgICAgcG9zICs9IDQ7CiAgICB9IGVsc2UgewogICAgICBidWYuc2V0VWludDgocG9zLCB0aGlzLmFyZ3VtZW50MSk7CiAgICAgIGJ1Zi5zZXRVaW50OChwb3MgKyAxLCB0aGlzLmFyZ3VtZW50Mik7CiAgICAgIHBvcyArPSAyOwogICAgfQogICAgaWYgKHRoaXMuZmxhZ3MgJiBXRV9IQVZFX0lOU1RSVUNUSU9OUykgewogICAgICBidWYuc2V0VWludDE2KHBvcywgdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoKTsKICAgICAgcG9zICs9IDI7CiAgICAgIGlmICh0aGlzLmluc3RydWN0aW9ucy5sZW5ndGgpIHsKICAgICAgICBuZXcgVWludDhBcnJheShidWYuYnVmZmVyLCAwLCBidWYuYnVmZmVyLmJ5dGVMZW5ndGgpLnNldCh0aGlzLmluc3RydWN0aW9ucywgcG9zKTsKICAgICAgICBwb3MgKz0gdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcG9zIC0gc3BvczsKICB9CiAgc2NhbGUoeCwgZmFjdG9yKSB7fQp9Cgo7Ly8gLi9zcmMvY29yZS9vcGVudHlwZV9maWxlX2J1aWxkZXIuanMKCgpmdW5jdGlvbiB3cml0ZUludDE2KGRlc3QsIG9mZnNldCwgbnVtKSB7CiAgZGVzdFtvZmZzZXRdID0gbnVtID4+IDggJiAweGZmOwogIGRlc3Rbb2Zmc2V0ICsgMV0gPSBudW0gJiAweGZmOwp9CmZ1bmN0aW9uIHdyaXRlSW50MzIoZGVzdCwgb2Zmc2V0LCBudW0pIHsKICBkZXN0W29mZnNldF0gPSBudW0gPj4gMjQgJiAweGZmOwogIGRlc3Rbb2Zmc2V0ICsgMV0gPSBudW0gPj4gMTYgJiAweGZmOwogIGRlc3Rbb2Zmc2V0ICsgMl0gPSBudW0gPj4gOCAmIDB4ZmY7CiAgZGVzdFtvZmZzZXQgKyAzXSA9IG51bSAmIDB4ZmY7Cn0KZnVuY3Rpb24gd3JpdGVEYXRhKGRlc3QsIG9mZnNldCwgZGF0YSkgewogIGlmIChkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSkgewogICAgZGVzdC5zZXQoZGF0YSwgb2Zmc2V0KTsKICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhID09PSAic3RyaW5nIikgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZGF0YS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGRlc3Rbb2Zmc2V0KytdID0gZGF0YS5jaGFyQ29kZUF0KGkpICYgMHhmZjsKICAgIH0KICB9IGVsc2UgewogICAgZm9yIChjb25zdCBudW0gb2YgZGF0YSkgewogICAgICBkZXN0W29mZnNldCsrXSA9IG51bSAmIDB4ZmY7CiAgICB9CiAgfQp9CmNvbnN0IE9URl9IRUFERVJfU0laRSA9IDEyOwpjb25zdCBPVEZfVEFCTEVfRU5UUllfU0laRSA9IDE2OwpjbGFzcyBPcGVuVHlwZUZpbGVCdWlsZGVyIHsKICBjb25zdHJ1Y3RvcihzZm50KSB7CiAgICB0aGlzLnNmbnQgPSBzZm50OwogICAgdGhpcy50YWJsZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIH0KICBzdGF0aWMgZ2V0U2VhcmNoUGFyYW1zKGVudHJpZXNDb3VudCwgZW50cnlTaXplKSB7CiAgICBsZXQgbWF4UG93ZXIyID0gMSwKICAgICAgbG9nMiA9IDA7CiAgICB3aGlsZSAoKG1heFBvd2VyMiBeIGVudHJpZXNDb3VudCkgPiBtYXhQb3dlcjIpIHsKICAgICAgbWF4UG93ZXIyIDw8PSAxOwogICAgICBsb2cyKys7CiAgICB9CiAgICBjb25zdCBzZWFyY2hSYW5nZSA9IG1heFBvd2VyMiAqIGVudHJ5U2l6ZTsKICAgIHJldHVybiB7CiAgICAgIHJhbmdlOiBzZWFyY2hSYW5nZSwKICAgICAgZW50cnk6IGxvZzIsCiAgICAgIHJhbmdlU2hpZnQ6IGVudHJ5U2l6ZSAqIGVudHJpZXNDb3VudCAtIHNlYXJjaFJhbmdlCiAgICB9OwogIH0KICB0b0FycmF5KCkgewogICAgbGV0IHNmbnQgPSB0aGlzLnNmbnQ7CiAgICBjb25zdCB0YWJsZXMgPSB0aGlzLnRhYmxlczsKICAgIGNvbnN0IHRhYmxlc05hbWVzID0gT2JqZWN0LmtleXModGFibGVzKTsKICAgIHRhYmxlc05hbWVzLnNvcnQoKTsKICAgIGNvbnN0IG51bVRhYmxlcyA9IHRhYmxlc05hbWVzLmxlbmd0aDsKICAgIGxldCBpLCBqLCBqaiwgdGFibGUsIHRhYmxlTmFtZTsKICAgIGxldCBvZmZzZXQgPSBPVEZfSEVBREVSX1NJWkUgKyBudW1UYWJsZXMgKiBPVEZfVEFCTEVfRU5UUllfU0laRTsKICAgIGNvbnN0IHRhYmxlT2Zmc2V0cyA9IFtvZmZzZXRdOwogICAgZm9yIChpID0gMDsgaSA8IG51bVRhYmxlczsgaSsrKSB7CiAgICAgIHRhYmxlID0gdGFibGVzW3RhYmxlc05hbWVzW2ldXTsKICAgICAgY29uc3QgcGFkZGVkTGVuZ3RoID0gKHRhYmxlLmxlbmd0aCArIDMgJiB+MykgPj4+IDA7CiAgICAgIG9mZnNldCArPSBwYWRkZWRMZW5ndGg7CiAgICAgIHRhYmxlT2Zmc2V0cy5wdXNoKG9mZnNldCk7CiAgICB9CiAgICBjb25zdCBmaWxlID0gbmV3IFVpbnQ4QXJyYXkob2Zmc2V0KTsKICAgIGZvciAoaSA9IDA7IGkgPCBudW1UYWJsZXM7IGkrKykgewogICAgICB0YWJsZSA9IHRhYmxlc1t0YWJsZXNOYW1lc1tpXV07CiAgICAgIHdyaXRlRGF0YShmaWxlLCB0YWJsZU9mZnNldHNbaV0sIHRhYmxlKTsKICAgIH0KICAgIGlmIChzZm50ID09PSAidHJ1ZSIpIHsKICAgICAgc2ZudCA9IHN0cmluZzMyKDB4MDAwMTAwMDApOwogICAgfQogICAgZmlsZVswXSA9IHNmbnQuY2hhckNvZGVBdCgwKSAmIDB4ZmY7CiAgICBmaWxlWzFdID0gc2ZudC5jaGFyQ29kZUF0KDEpICYgMHhmZjsKICAgIGZpbGVbMl0gPSBzZm50LmNoYXJDb2RlQXQoMikgJiAweGZmOwogICAgZmlsZVszXSA9IHNmbnQuY2hhckNvZGVBdCgzKSAmIDB4ZmY7CiAgICB3cml0ZUludDE2KGZpbGUsIDQsIG51bVRhYmxlcyk7CiAgICBjb25zdCBzZWFyY2hQYXJhbXMgPSBPcGVuVHlwZUZpbGVCdWlsZGVyLmdldFNlYXJjaFBhcmFtcyhudW1UYWJsZXMsIDE2KTsKICAgIHdyaXRlSW50MTYoZmlsZSwgNiwgc2VhcmNoUGFyYW1zLnJhbmdlKTsKICAgIHdyaXRlSW50MTYoZmlsZSwgOCwgc2VhcmNoUGFyYW1zLmVudHJ5KTsKICAgIHdyaXRlSW50MTYoZmlsZSwgMTAsIHNlYXJjaFBhcmFtcy5yYW5nZVNoaWZ0KTsKICAgIG9mZnNldCA9IE9URl9IRUFERVJfU0laRTsKICAgIGZvciAoaSA9IDA7IGkgPCBudW1UYWJsZXM7IGkrKykgewogICAgICB0YWJsZU5hbWUgPSB0YWJsZXNOYW1lc1tpXTsKICAgICAgZmlsZVtvZmZzZXRdID0gdGFibGVOYW1lLmNoYXJDb2RlQXQoMCkgJiAweGZmOwogICAgICBmaWxlW29mZnNldCArIDFdID0gdGFibGVOYW1lLmNoYXJDb2RlQXQoMSkgJiAweGZmOwogICAgICBmaWxlW29mZnNldCArIDJdID0gdGFibGVOYW1lLmNoYXJDb2RlQXQoMikgJiAweGZmOwogICAgICBmaWxlW29mZnNldCArIDNdID0gdGFibGVOYW1lLmNoYXJDb2RlQXQoMykgJiAweGZmOwogICAgICBsZXQgY2hlY2tzdW0gPSAwOwogICAgICBmb3IgKGogPSB0YWJsZU9mZnNldHNbaV0sIGpqID0gdGFibGVPZmZzZXRzW2kgKyAxXTsgaiA8IGpqOyBqICs9IDQpIHsKICAgICAgICBjb25zdCBxdWFkID0gcmVhZFVpbnQzMihmaWxlLCBqKTsKICAgICAgICBjaGVja3N1bSA9IGNoZWNrc3VtICsgcXVhZCA+Pj4gMDsKICAgICAgfQogICAgICB3cml0ZUludDMyKGZpbGUsIG9mZnNldCArIDQsIGNoZWNrc3VtKTsKICAgICAgd3JpdGVJbnQzMihmaWxlLCBvZmZzZXQgKyA4LCB0YWJsZU9mZnNldHNbaV0pOwogICAgICB3cml0ZUludDMyKGZpbGUsIG9mZnNldCArIDEyLCB0YWJsZXNbdGFibGVOYW1lXS5sZW5ndGgpOwogICAgICBvZmZzZXQgKz0gT1RGX1RBQkxFX0VOVFJZX1NJWkU7CiAgICB9CiAgICByZXR1cm4gZmlsZTsKICB9CiAgYWRkVGFibGUodGFnLCBkYXRhKSB7CiAgICBpZiAodGFnIGluIHRoaXMudGFibGVzKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiVGFibGUgIiArIHRhZyArICIgYWxyZWFkeSBleGlzdHMiKTsKICAgIH0KICAgIHRoaXMudGFibGVzW3RhZ10gPSBkYXRhOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvdHlwZTFfcGFyc2VyLmpzCgoKCgpjb25zdCBISU5USU5HX0VOQUJMRUQgPSBmYWxzZTsKY29uc3QgQ09NTUFORF9NQVAgPSB7CiAgaHN0ZW06IFsxXSwKICB2c3RlbTogWzNdLAogIHZtb3ZldG86IFs0XSwKICBybGluZXRvOiBbNV0sCiAgaGxpbmV0bzogWzZdLAogIHZsaW5ldG86IFs3XSwKICBycmN1cnZldG86IFs4XSwKICBjYWxsc3VicjogWzEwXSwKICBmbGV4OiBbMTIsIDM1XSwKICBkcm9wOiBbMTIsIDE4XSwKICBlbmRjaGFyOiBbMTRdLAogIHJtb3ZldG86IFsyMV0sCiAgaG1vdmV0bzogWzIyXSwKICB2aGN1cnZldG86IFszMF0sCiAgaHZjdXJ2ZXRvOiBbMzFdCn07CmNsYXNzIFR5cGUxQ2hhclN0cmluZyB7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLndpZHRoID0gMDsKICAgIHRoaXMubHNiID0gMDsKICAgIHRoaXMuZmxleGluZyA9IGZhbHNlOwogICAgdGhpcy5vdXRwdXQgPSBbXTsKICAgIHRoaXMuc3RhY2sgPSBbXTsKICB9CiAgY29udmVydChlbmNvZGVkLCBzdWJycywgc2VhY0FuYWx5c2lzRW5hYmxlZCkgewogICAgY29uc3QgY291bnQgPSBlbmNvZGVkLmxlbmd0aDsKICAgIGxldCBlcnJvciA9IGZhbHNlOwogICAgbGV0IHd4LCBzYngsIHN1YnJOdW1iZXI7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgbGV0IHZhbHVlID0gZW5jb2RlZFtpXTsKICAgICAgaWYgKHZhbHVlIDwgMzIpIHsKICAgICAgICBpZiAodmFsdWUgPT09IDEyKSB7CiAgICAgICAgICB2YWx1ZSA9ICh2YWx1ZSA8PCA4KSArIGVuY29kZWRbKytpXTsKICAgICAgICB9CiAgICAgICAgc3dpdGNoICh2YWx1ZSkgewogICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICBpZiAoIUhJTlRJTkdfRU5BQkxFRCkgewogICAgICAgICAgICAgIHRoaXMuc3RhY2sgPSBbXTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMiwgQ09NTUFORF9NQVAuaHN0ZW0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgaWYgKCFISU5USU5HX0VOQUJMRUQpIHsKICAgICAgICAgICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDIsIENPTU1BTkRfTUFQLnZzdGVtKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDQ6CiAgICAgICAgICAgIGlmICh0aGlzLmZsZXhpbmcpIHsKICAgICAgICAgICAgICBpZiAodGhpcy5zdGFjay5sZW5ndGggPCAxKSB7CiAgICAgICAgICAgICAgICBlcnJvciA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgZHkgPSB0aGlzLnN0YWNrLnBvcCgpOwogICAgICAgICAgICAgIHRoaXMuc3RhY2sucHVzaCgwLCBkeSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDEsIENPTU1BTkRfTUFQLnZtb3ZldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgNToKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDIsIENPTU1BTkRfTUFQLnJsaW5ldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgNjoKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDEsIENPTU1BTkRfTUFQLmhsaW5ldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgNzoKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDEsIENPTU1BTkRfTUFQLnZsaW5ldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgODoKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDYsIENPTU1BTkRfTUFQLnJyY3VydmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSA5OgogICAgICAgICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAxMDoKICAgICAgICAgICAgaWYgKHRoaXMuc3RhY2subGVuZ3RoIDwgMSkgewogICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdWJyTnVtYmVyID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgaWYgKCFzdWJyc1tzdWJyTnVtYmVyXSkgewogICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBlcnJvciA9IHRoaXMuY29udmVydChzdWJyc1tzdWJyTnVtYmVyXSwgc3VicnMsIHNlYWNBbmFseXNpc0VuYWJsZWQpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMTE6CiAgICAgICAgICAgIHJldHVybiBlcnJvcjsKICAgICAgICAgIGNhc2UgMTM6CiAgICAgICAgICAgIGlmICh0aGlzLnN0YWNrLmxlbmd0aCA8IDIpIHsKICAgICAgICAgICAgICBlcnJvciA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgd3ggPSB0aGlzLnN0YWNrLnBvcCgpOwogICAgICAgICAgICBzYnggPSB0aGlzLnN0YWNrLnBvcCgpOwogICAgICAgICAgICB0aGlzLmxzYiA9IHNieDsKICAgICAgICAgICAgdGhpcy53aWR0aCA9IHd4OwogICAgICAgICAgICB0aGlzLnN0YWNrLnB1c2god3gsIHNieCk7CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCgyLCBDT01NQU5EX01BUC5obW92ZXRvKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDE0OgogICAgICAgICAgICB0aGlzLm91dHB1dC5wdXNoKENPTU1BTkRfTUFQLmVuZGNoYXJbMF0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMjE6CiAgICAgICAgICAgIGlmICh0aGlzLmZsZXhpbmcpIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMiwgQ09NTUFORF9NQVAucm1vdmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAyMjoKICAgICAgICAgICAgaWYgKHRoaXMuZmxleGluZykgewogICAgICAgICAgICAgIHRoaXMuc3RhY2sucHVzaCgwKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMSwgQ09NTUFORF9NQVAuaG1vdmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAzMDoKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDQsIENPTU1BTkRfTUFQLnZoY3VydmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAzMToKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDQsIENPTU1BTkRfTUFQLmh2Y3VydmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAoMTIgPDwgOCkgKyAwOgogICAgICAgICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAoMTIgPDwgOCkgKyAxOgogICAgICAgICAgICBpZiAoIUhJTlRJTkdfRU5BQkxFRCkgewogICAgICAgICAgICAgIHRoaXMuc3RhY2sgPSBbXTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMiwgQ09NTUFORF9NQVAudnN0ZW0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgKDEyIDw8IDgpICsgMjoKICAgICAgICAgICAgaWYgKCFISU5USU5HX0VOQUJMRUQpIHsKICAgICAgICAgICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDIsIENPTU1BTkRfTUFQLmhzdGVtKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICgxMiA8PCA4KSArIDY6CiAgICAgICAgICAgIGlmIChzZWFjQW5hbHlzaXNFbmFibGVkKSB7CiAgICAgICAgICAgICAgY29uc3QgYXNiID0gdGhpcy5zdGFjay5hdCgtNSk7CiAgICAgICAgICAgICAgdGhpcy5zZWFjID0gdGhpcy5zdGFjay5zcGxpY2UoLTQsIDQpOwogICAgICAgICAgICAgIHRoaXMuc2VhY1swXSArPSB0aGlzLmxzYiAtIGFzYjsKICAgICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMCwgQ09NTUFORF9NQVAuZW5kY2hhcik7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDQsIENPTU1BTkRfTUFQLmVuZGNoYXIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAoMTIgPDwgOCkgKyA3OgogICAgICAgICAgICBpZiAodGhpcy5zdGFjay5sZW5ndGggPCA0KSB7CiAgICAgICAgICAgICAgZXJyb3IgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuc3RhY2sucG9wKCk7CiAgICAgICAgICAgIHd4ID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgY29uc3Qgc2J5ID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgc2J4ID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgdGhpcy5sc2IgPSBzYng7CiAgICAgICAgICAgIHRoaXMud2lkdGggPSB3eDsKICAgICAgICAgICAgdGhpcy5zdGFjay5wdXNoKHd4LCBzYngsIHNieSk7CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCgzLCBDT01NQU5EX01BUC5ybW92ZXRvKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICgxMiA8PCA4KSArIDEyOgogICAgICAgICAgICBpZiAodGhpcy5zdGFjay5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgICAgZXJyb3IgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IG51bTIgPSB0aGlzLnN0YWNrLnBvcCgpOwogICAgICAgICAgICBjb25zdCBudW0xID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgdGhpcy5zdGFjay5wdXNoKG51bTEgLyBudW0yKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICgxMiA8PCA4KSArIDE2OgogICAgICAgICAgICBpZiAodGhpcy5zdGFjay5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgICAgZXJyb3IgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1YnJOdW1iZXIgPSB0aGlzLnN0YWNrLnBvcCgpOwogICAgICAgICAgICBjb25zdCBudW1BcmdzID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgaWYgKHN1YnJOdW1iZXIgPT09IDAgJiYgbnVtQXJncyA9PT0gMykgewogICAgICAgICAgICAgIGNvbnN0IGZsZXhBcmdzID0gdGhpcy5zdGFjay5zcGxpY2UoLTE3LCAxNyk7CiAgICAgICAgICAgICAgdGhpcy5zdGFjay5wdXNoKGZsZXhBcmdzWzJdICsgZmxleEFyZ3NbMF0sIGZsZXhBcmdzWzNdICsgZmxleEFyZ3NbMV0sIGZsZXhBcmdzWzRdLCBmbGV4QXJnc1s1XSwgZmxleEFyZ3NbNl0sIGZsZXhBcmdzWzddLCBmbGV4QXJnc1s4XSwgZmxleEFyZ3NbOV0sIGZsZXhBcmdzWzEwXSwgZmxleEFyZ3NbMTFdLCBmbGV4QXJnc1sxMl0sIGZsZXhBcmdzWzEzXSwgZmxleEFyZ3NbMTRdKTsKICAgICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMTMsIENPTU1BTkRfTUFQLmZsZXgsIHRydWUpOwogICAgICAgICAgICAgIHRoaXMuZmxleGluZyA9IGZhbHNlOwogICAgICAgICAgICAgIHRoaXMuc3RhY2sucHVzaChmbGV4QXJnc1sxNV0sIGZsZXhBcmdzWzE2XSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoc3Vick51bWJlciA9PT0gMSAmJiBudW1BcmdzID09PSAwKSB7CiAgICAgICAgICAgICAgdGhpcy5mbGV4aW5nID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgKDEyIDw8IDgpICsgMTc6CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAoMTIgPDwgOCkgKyAzMzoKICAgICAgICAgICAgdGhpcy5zdGFjayA9IFtdOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHdhcm4oJ1Vua25vd24gdHlwZSAxIGNoYXJzdHJpbmcgY29tbWFuZCBvZiAiJyArIHZhbHVlICsgJyInKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmIChlcnJvcikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgaWYgKHZhbHVlIDw9IDI0NikgewogICAgICAgIHZhbHVlIC09IDEzOTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA8PSAyNTApIHsKICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAtIDI0NykgKiAyNTYgKyBlbmNvZGVkWysraV0gKyAxMDg7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPD0gMjU0KSB7CiAgICAgICAgdmFsdWUgPSAtKCh2YWx1ZSAtIDI1MSkgKiAyNTYpIC0gZW5jb2RlZFsrK2ldIC0gMTA4OwogICAgICB9IGVsc2UgewogICAgICAgIHZhbHVlID0gKGVuY29kZWRbKytpXSAmIDB4ZmYpIDw8IDI0IHwgKGVuY29kZWRbKytpXSAmIDB4ZmYpIDw8IDE2IHwgKGVuY29kZWRbKytpXSAmIDB4ZmYpIDw8IDggfCAoZW5jb2RlZFsrK2ldICYgMHhmZikgPDwgMDsKICAgICAgfQogICAgICB0aGlzLnN0YWNrLnB1c2godmFsdWUpOwogICAgfQogICAgcmV0dXJuIGVycm9yOwogIH0KICBleGVjdXRlQ29tbWFuZChob3dNYW55QXJncywgY29tbWFuZCwga2VlcFN0YWNrKSB7CiAgICBjb25zdCBzdGFja0xlbmd0aCA9IHRoaXMuc3RhY2subGVuZ3RoOwogICAgaWYgKGhvd01hbnlBcmdzID4gc3RhY2tMZW5ndGgpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBjb25zdCBzdGFydCA9IHN0YWNrTGVuZ3RoIC0gaG93TWFueUFyZ3M7CiAgICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBzdGFja0xlbmd0aDsgaSsrKSB7CiAgICAgIGxldCB2YWx1ZSA9IHRoaXMuc3RhY2tbaV07CiAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSkgewogICAgICAgIHRoaXMub3V0cHV0LnB1c2goMjgsIHZhbHVlID4+IDggJiAweGZmLCB2YWx1ZSAmIDB4ZmYpOwogICAgICB9IGVsc2UgewogICAgICAgIHZhbHVlID0gNjU1MzYgKiB2YWx1ZSB8IDA7CiAgICAgICAgdGhpcy5vdXRwdXQucHVzaCgyNTUsIHZhbHVlID4+IDI0ICYgMHhmZiwgdmFsdWUgPj4gMTYgJiAweGZmLCB2YWx1ZSA+PiA4ICYgMHhmZiwgdmFsdWUgJiAweGZmKTsKICAgICAgfQogICAgfQogICAgdGhpcy5vdXRwdXQucHVzaCguLi5jb21tYW5kKTsKICAgIGlmIChrZWVwU3RhY2spIHsKICAgICAgdGhpcy5zdGFjay5zcGxpY2Uoc3RhcnQsIGhvd01hbnlBcmdzKTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuc3RhY2subGVuZ3RoID0gMDsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9Cn0KY29uc3QgRUVYRUNfRU5DUllQVF9LRVkgPSA1NTY2NTsKY29uc3QgQ0hBUl9TVFJTX0VOQ1JZUFRfS0VZID0gNDMzMDsKZnVuY3Rpb24gaXNIZXhEaWdpdChjb2RlKSB7CiAgcmV0dXJuIGNvZGUgPj0gNDggJiYgY29kZSA8PSA1NyB8fCBjb2RlID49IDY1ICYmIGNvZGUgPD0gNzAgfHwgY29kZSA+PSA5NyAmJiBjb2RlIDw9IDEwMjsKfQpmdW5jdGlvbiBkZWNyeXB0KGRhdGEsIGtleSwgZGlzY2FyZE51bWJlcikgewogIGlmIChkaXNjYXJkTnVtYmVyID49IGRhdGEubGVuZ3RoKSB7CiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCk7CiAgfQogIGNvbnN0IGMxID0gNTI4NDUsCiAgICBjMiA9IDIyNzE5OwogIGxldCByID0ga2V5IHwgMCwKICAgIGksCiAgICBqOwogIGZvciAoaSA9IDA7IGkgPCBkaXNjYXJkTnVtYmVyOyBpKyspIHsKICAgIHIgPSAoZGF0YVtpXSArIHIpICogYzEgKyBjMiAmICgxIDw8IDE2KSAtIDE7CiAgfQogIGNvbnN0IGNvdW50ID0gZGF0YS5sZW5ndGggLSBkaXNjYXJkTnVtYmVyOwogIGNvbnN0IGRlY3J5cHRlZCA9IG5ldyBVaW50OEFycmF5KGNvdW50KTsKICBmb3IgKGkgPSBkaXNjYXJkTnVtYmVyLCBqID0gMDsgaiA8IGNvdW50OyBpKyssIGorKykgewogICAgY29uc3QgdmFsdWUgPSBkYXRhW2ldOwogICAgZGVjcnlwdGVkW2pdID0gdmFsdWUgXiByID4+IDg7CiAgICByID0gKHZhbHVlICsgcikgKiBjMSArIGMyICYgKDEgPDwgMTYpIC0gMTsKICB9CiAgcmV0dXJuIGRlY3J5cHRlZDsKfQpmdW5jdGlvbiBkZWNyeXB0QXNjaWkoZGF0YSwga2V5LCBkaXNjYXJkTnVtYmVyKSB7CiAgY29uc3QgYzEgPSA1Mjg0NSwKICAgIGMyID0gMjI3MTk7CiAgbGV0IHIgPSBrZXkgfCAwOwogIGNvbnN0IGNvdW50ID0gZGF0YS5sZW5ndGgsCiAgICBtYXliZUxlbmd0aCA9IGNvdW50ID4+PiAxOwogIGNvbnN0IGRlY3J5cHRlZCA9IG5ldyBVaW50OEFycmF5KG1heWJlTGVuZ3RoKTsKICBsZXQgaSwgajsKICBmb3IgKGkgPSAwLCBqID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgIGNvbnN0IGRpZ2l0MSA9IGRhdGFbaV07CiAgICBpZiAoIWlzSGV4RGlnaXQoZGlnaXQxKSkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGkrKzsKICAgIGxldCBkaWdpdDI7CiAgICB3aGlsZSAoaSA8IGNvdW50ICYmICFpc0hleERpZ2l0KGRpZ2l0MiA9IGRhdGFbaV0pKSB7CiAgICAgIGkrKzsKICAgIH0KICAgIGlmIChpIDwgY291bnQpIHsKICAgICAgY29uc3QgdmFsdWUgPSBwYXJzZUludChTdHJpbmcuZnJvbUNoYXJDb2RlKGRpZ2l0MSwgZGlnaXQyKSwgMTYpOwogICAgICBkZWNyeXB0ZWRbaisrXSA9IHZhbHVlIF4gciA+PiA4OwogICAgICByID0gKHZhbHVlICsgcikgKiBjMSArIGMyICYgKDEgPDwgMTYpIC0gMTsKICAgIH0KICB9CiAgcmV0dXJuIGRlY3J5cHRlZC5zbGljZShkaXNjYXJkTnVtYmVyLCBqKTsKfQpmdW5jdGlvbiBpc1NwZWNpYWwoYykgewogIHJldHVybiBjID09PSAweDJmIHx8IGMgPT09IDB4NWIgfHwgYyA9PT0gMHg1ZCB8fCBjID09PSAweDdiIHx8IGMgPT09IDB4N2QgfHwgYyA9PT0gMHgyOCB8fCBjID09PSAweDI5Owp9CmNsYXNzIFR5cGUxUGFyc2VyIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIGVuY3J5cHRlZCwgc2VhY0FuYWx5c2lzRW5hYmxlZCkgewogICAgaWYgKGVuY3J5cHRlZCkgewogICAgICBjb25zdCBkYXRhID0gc3RyZWFtLmdldEJ5dGVzKCk7CiAgICAgIGNvbnN0IGlzQmluYXJ5ID0gISgoaXNIZXhEaWdpdChkYXRhWzBdKSB8fCBpc1doaXRlU3BhY2UoZGF0YVswXSkpICYmIGlzSGV4RGlnaXQoZGF0YVsxXSkgJiYgaXNIZXhEaWdpdChkYXRhWzJdKSAmJiBpc0hleERpZ2l0KGRhdGFbM10pICYmIGlzSGV4RGlnaXQoZGF0YVs0XSkgJiYgaXNIZXhEaWdpdChkYXRhWzVdKSAmJiBpc0hleERpZ2l0KGRhdGFbNl0pICYmIGlzSGV4RGlnaXQoZGF0YVs3XSkpOwogICAgICBzdHJlYW0gPSBuZXcgU3RyZWFtKGlzQmluYXJ5ID8gZGVjcnlwdChkYXRhLCBFRVhFQ19FTkNSWVBUX0tFWSwgNCkgOiBkZWNyeXB0QXNjaWkoZGF0YSwgRUVYRUNfRU5DUllQVF9LRVksIDQpKTsKICAgIH0KICAgIHRoaXMuc2VhY0FuYWx5c2lzRW5hYmxlZCA9ICEhc2VhY0FuYWx5c2lzRW5hYmxlZDsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy5uZXh0Q2hhcigpOwogIH0KICByZWFkTnVtYmVyQXJyYXkoKSB7CiAgICB0aGlzLmdldFRva2VuKCk7CiAgICBjb25zdCBhcnJheSA9IFtdOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgY29uc3QgdG9rZW4gPSB0aGlzLmdldFRva2VuKCk7CiAgICAgIGlmICh0b2tlbiA9PT0gbnVsbCB8fCB0b2tlbiA9PT0gIl0iIHx8IHRva2VuID09PSAifSIpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBhcnJheS5wdXNoKHBhcnNlRmxvYXQodG9rZW4gfHwgMCkpOwogICAgfQogICAgcmV0dXJuIGFycmF5OwogIH0KICByZWFkTnVtYmVyKCkgewogICAgY29uc3QgdG9rZW4gPSB0aGlzLmdldFRva2VuKCk7CiAgICByZXR1cm4gcGFyc2VGbG9hdCh0b2tlbiB8fCAwKTsKICB9CiAgcmVhZEludCgpIHsKICAgIGNvbnN0IHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgcmV0dXJuIHBhcnNlSW50KHRva2VuIHx8IDAsIDEwKSB8IDA7CiAgfQogIHJlYWRCb29sZWFuKCkgewogICAgY29uc3QgdG9rZW4gPSB0aGlzLmdldFRva2VuKCk7CiAgICByZXR1cm4gdG9rZW4gPT09ICJ0cnVlIiA/IDEgOiAwOwogIH0KICBuZXh0Q2hhcigpIHsKICAgIHJldHVybiB0aGlzLmN1cnJlbnRDaGFyID0gdGhpcy5zdHJlYW0uZ2V0Qnl0ZSgpOwogIH0KICBwcmV2Q2hhcigpIHsKICAgIHRoaXMuc3RyZWFtLnNraXAoLTIpOwogICAgcmV0dXJuIHRoaXMuY3VycmVudENoYXIgPSB0aGlzLnN0cmVhbS5nZXRCeXRlKCk7CiAgfQogIGdldFRva2VuKCkgewogICAgbGV0IGNvbW1lbnQgPSBmYWxzZTsKICAgIGxldCBjaCA9IHRoaXMuY3VycmVudENoYXI7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBpZiAoY2ggPT09IC0xKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgaWYgKGNvbW1lbnQpIHsKICAgICAgICBpZiAoY2ggPT09IDB4MGEgfHwgY2ggPT09IDB4MGQpIHsKICAgICAgICAgIGNvbW1lbnQgPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MjUpIHsKICAgICAgICBjb21tZW50ID0gdHJ1ZTsKICAgICAgfSBlbHNlIGlmICghaXNXaGl0ZVNwYWNlKGNoKSkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgfQogICAgaWYgKGlzU3BlY2lhbChjaCkpIHsKICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICB9CiAgICBsZXQgdG9rZW4gPSAiIjsKICAgIGRvIHsKICAgICAgdG9rZW4gKz0gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgfSB3aGlsZSAoY2ggPj0gMCAmJiAhaXNXaGl0ZVNwYWNlKGNoKSAmJiAhaXNTcGVjaWFsKGNoKSk7CiAgICByZXR1cm4gdG9rZW47CiAgfQogIHJlYWRDaGFyU3RyaW5ncyhieXRlcywgbGVuSVYpIHsKICAgIGlmIChsZW5JViA9PT0gLTEpIHsKICAgICAgcmV0dXJuIGJ5dGVzOwogICAgfQogICAgcmV0dXJuIGRlY3J5cHQoYnl0ZXMsIENIQVJfU1RSU19FTkNSWVBUX0tFWSwgbGVuSVYpOwogIH0KICBleHRyYWN0Rm9udFByb2dyYW0ocHJvcGVydGllcykgewogICAgY29uc3Qgc3RyZWFtID0gdGhpcy5zdHJlYW07CiAgICBjb25zdCBzdWJycyA9IFtdLAogICAgICBjaGFyc3RyaW5ncyA9IFtdOwogICAgY29uc3QgcHJpdmF0ZURhdGEgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgcHJpdmF0ZURhdGEubGVuSVYgPSA0OwogICAgY29uc3QgcHJvZ3JhbSA9IHsKICAgICAgc3VicnM6IFtdLAogICAgICBjaGFyc3RyaW5nczogW10sCiAgICAgIHByb3BlcnRpZXM6IHsKICAgICAgICBwcml2YXRlRGF0YQogICAgICB9CiAgICB9OwogICAgbGV0IHRva2VuLCBsZW5ndGgsIGRhdGEsIGxlbklWOwogICAgd2hpbGUgKCh0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKSkgIT09IG51bGwpIHsKICAgICAgaWYgKHRva2VuICE9PSAiLyIpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICB0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgc3dpdGNoICh0b2tlbikgewogICAgICAgIGNhc2UgIkNoYXJTdHJpbmdzIjoKICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgIHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICBpZiAodG9rZW4gPT09IG51bGwgfHwgdG9rZW4gPT09ICJlbmQiKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHRva2VuICE9PSAiLyIpIHsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBnbHlwaCA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgbGVuZ3RoID0gdGhpcy5yZWFkSW50KCk7CiAgICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgZGF0YSA9IGxlbmd0aCA+IDAgPyBzdHJlYW0uZ2V0Qnl0ZXMobGVuZ3RoKSA6IG5ldyBVaW50OEFycmF5KDApOwogICAgICAgICAgICBsZW5JViA9IHByb2dyYW0ucHJvcGVydGllcy5wcml2YXRlRGF0YS5sZW5JVjsKICAgICAgICAgICAgY29uc3QgZW5jb2RlZCA9IHRoaXMucmVhZENoYXJTdHJpbmdzKGRhdGEsIGxlbklWKTsKICAgICAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICB0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgaWYgKHRva2VuID09PSAibm9hY2Nlc3MiKSB7CiAgICAgICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICB9IGVsc2UgaWYgKHRva2VuID09PSAiLyIpIHsKICAgICAgICAgICAgICB0aGlzLnByZXZDaGFyKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2hhcnN0cmluZ3MucHVzaCh7CiAgICAgICAgICAgICAgZ2x5cGgsCiAgICAgICAgICAgICAgZW5jb2RlZAogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlN1YnJzIjoKICAgICAgICAgIHRoaXMucmVhZEludCgpOwogICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgd2hpbGUgKHRoaXMuZ2V0VG9rZW4oKSA9PT0gImR1cCIpIHsKICAgICAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnJlYWRJbnQoKTsKICAgICAgICAgICAgbGVuZ3RoID0gdGhpcy5yZWFkSW50KCk7CiAgICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgZGF0YSA9IGxlbmd0aCA+IDAgPyBzdHJlYW0uZ2V0Qnl0ZXMobGVuZ3RoKSA6IG5ldyBVaW50OEFycmF5KDApOwogICAgICAgICAgICBsZW5JViA9IHByb2dyYW0ucHJvcGVydGllcy5wcml2YXRlRGF0YS5sZW5JVjsKICAgICAgICAgICAgY29uc3QgZW5jb2RlZCA9IHRoaXMucmVhZENoYXJTdHJpbmdzKGRhdGEsIGxlbklWKTsKICAgICAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICB0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgaWYgKHRva2VuID09PSAibm9hY2Nlc3MiKSB7CiAgICAgICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1YnJzW2luZGV4XSA9IGVuY29kZWQ7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJCbHVlVmFsdWVzIjoKICAgICAgICBjYXNlICJPdGhlckJsdWVzIjoKICAgICAgICBjYXNlICJGYW1pbHlCbHVlcyI6CiAgICAgICAgY2FzZSAiRmFtaWx5T3RoZXJCbHVlcyI6CiAgICAgICAgICBjb25zdCBibHVlQXJyYXkgPSB0aGlzLnJlYWROdW1iZXJBcnJheSgpOwogICAgICAgICAgaWYgKGJsdWVBcnJheS5sZW5ndGggPiAwICYmIGJsdWVBcnJheS5sZW5ndGggJSAyID09PSAwICYmIEhJTlRJTkdfRU5BQkxFRCkgewogICAgICAgICAgICBwcm9ncmFtLnByb3BlcnRpZXMucHJpdmF0ZURhdGFbdG9rZW5dID0gYmx1ZUFycmF5OwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiU3RlbVNuYXBIIjoKICAgICAgICBjYXNlICJTdGVtU25hcFYiOgogICAgICAgICAgcHJvZ3JhbS5wcm9wZXJ0aWVzLnByaXZhdGVEYXRhW3Rva2VuXSA9IHRoaXMucmVhZE51bWJlckFycmF5KCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJTdGRIVyI6CiAgICAgICAgY2FzZSAiU3RkVlciOgogICAgICAgICAgcHJvZ3JhbS5wcm9wZXJ0aWVzLnByaXZhdGVEYXRhW3Rva2VuXSA9IHRoaXMucmVhZE51bWJlckFycmF5KClbMF07CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJCbHVlU2hpZnQiOgogICAgICAgIGNhc2UgImxlbklWIjoKICAgICAgICBjYXNlICJCbHVlRnV6eiI6CiAgICAgICAgY2FzZSAiQmx1ZVNjYWxlIjoKICAgICAgICBjYXNlICJMYW5ndWFnZUdyb3VwIjoKICAgICAgICAgIHByb2dyYW0ucHJvcGVydGllcy5wcml2YXRlRGF0YVt0b2tlbl0gPSB0aGlzLnJlYWROdW1iZXIoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkV4cGFuc2lvbkZhY3RvciI6CiAgICAgICAgICBwcm9ncmFtLnByb3BlcnRpZXMucHJpdmF0ZURhdGFbdG9rZW5dID0gdGhpcy5yZWFkTnVtYmVyKCkgfHwgMC4wNjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkZvcmNlQm9sZCI6CiAgICAgICAgICBwcm9ncmFtLnByb3BlcnRpZXMucHJpdmF0ZURhdGFbdG9rZW5dID0gdGhpcy5yZWFkQm9vbGVhbigpOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgewogICAgICBlbmNvZGVkLAogICAgICBnbHlwaAogICAgfSBvZiBjaGFyc3RyaW5ncykgewogICAgICBjb25zdCBjaGFyU3RyaW5nID0gbmV3IFR5cGUxQ2hhclN0cmluZygpOwogICAgICBjb25zdCBlcnJvciA9IGNoYXJTdHJpbmcuY29udmVydChlbmNvZGVkLCBzdWJycywgdGhpcy5zZWFjQW5hbHlzaXNFbmFibGVkKTsKICAgICAgbGV0IG91dHB1dCA9IGNoYXJTdHJpbmcub3V0cHV0OwogICAgICBpZiAoZXJyb3IpIHsKICAgICAgICBvdXRwdXQgPSBbMTRdOwogICAgICB9CiAgICAgIGNvbnN0IGNoYXJTdHJpbmdPYmplY3QgPSB7CiAgICAgICAgZ2x5cGhOYW1lOiBnbHlwaCwKICAgICAgICBjaGFyc3RyaW5nOiBvdXRwdXQsCiAgICAgICAgd2lkdGg6IGNoYXJTdHJpbmcud2lkdGgsCiAgICAgICAgbHNiOiBjaGFyU3RyaW5nLmxzYiwKICAgICAgICBzZWFjOiBjaGFyU3RyaW5nLnNlYWMKICAgICAgfTsKICAgICAgaWYgKGdseXBoID09PSAiLm5vdGRlZiIpIHsKICAgICAgICBwcm9ncmFtLmNoYXJzdHJpbmdzLnVuc2hpZnQoY2hhclN0cmluZ09iamVjdCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcHJvZ3JhbS5jaGFyc3RyaW5ncy5wdXNoKGNoYXJTdHJpbmdPYmplY3QpOwogICAgICB9CiAgICAgIGlmIChwcm9wZXJ0aWVzLmJ1aWx0SW5FbmNvZGluZykgewogICAgICAgIGNvbnN0IGluZGV4ID0gcHJvcGVydGllcy5idWlsdEluRW5jb2RpbmcuaW5kZXhPZihnbHlwaCk7CiAgICAgICAgaWYgKGluZGV4ID4gLTEgJiYgcHJvcGVydGllcy53aWR0aHNbaW5kZXhdID09PSB1bmRlZmluZWQgJiYgaW5kZXggPj0gcHJvcGVydGllcy5maXJzdENoYXIgJiYgaW5kZXggPD0gcHJvcGVydGllcy5sYXN0Q2hhcikgewogICAgICAgICAgcHJvcGVydGllcy53aWR0aHNbaW5kZXhdID0gY2hhclN0cmluZy53aWR0aDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBwcm9ncmFtOwogIH0KICBleHRyYWN0Rm9udEhlYWRlcihwcm9wZXJ0aWVzKSB7CiAgICBsZXQgdG9rZW47CiAgICB3aGlsZSAoKHRva2VuID0gdGhpcy5nZXRUb2tlbigpKSAhPT0gbnVsbCkgewogICAgICBpZiAodG9rZW4gIT09ICIvIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgICBzd2l0Y2ggKHRva2VuKSB7CiAgICAgICAgY2FzZSAiRm9udE1hdHJpeCI6CiAgICAgICAgICBjb25zdCBtYXRyaXggPSB0aGlzLnJlYWROdW1iZXJBcnJheSgpOwogICAgICAgICAgcHJvcGVydGllcy5mb250TWF0cml4ID0gbWF0cml4OwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiRW5jb2RpbmciOgogICAgICAgICAgY29uc3QgZW5jb2RpbmdBcmcgPSB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICBsZXQgZW5jb2Rpbmc7CiAgICAgICAgICBpZiAoIS9eXGQrJC8udGVzdChlbmNvZGluZ0FyZykpIHsKICAgICAgICAgICAgZW5jb2RpbmcgPSBnZXRFbmNvZGluZyhlbmNvZGluZ0FyZyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbmNvZGluZyA9IFtdOwogICAgICAgICAgICBjb25zdCBzaXplID0gcGFyc2VJbnQoZW5jb2RpbmdBcmcsIDEwKSB8IDA7CiAgICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBzaXplOyBqKyspIHsKICAgICAgICAgICAgICB0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgICB3aGlsZSAodG9rZW4gIT09ICJkdXAiICYmIHRva2VuICE9PSAiZGVmIikgewogICAgICAgICAgICAgICAgdG9rZW4gPSB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgICAgICBpZiAodG9rZW4gPT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAodG9rZW4gPT09ICJkZWYiKSB7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnJlYWRJbnQoKTsKICAgICAgICAgICAgICB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgICAgY29uc3QgZ2x5cGggPSB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgICAgZW5jb2RpbmdbaW5kZXhdID0gZ2x5cGg7CiAgICAgICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBwcm9wZXJ0aWVzLmJ1aWx0SW5FbmNvZGluZyA9IGVuY29kaW5nOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiRm9udEJCb3giOgogICAgICAgICAgY29uc3QgZm9udEJCb3ggPSB0aGlzLnJlYWROdW1iZXJBcnJheSgpOwogICAgICAgICAgcHJvcGVydGllcy5hc2NlbnQgPSBNYXRoLm1heChmb250QkJveFszXSwgZm9udEJCb3hbMV0pOwogICAgICAgICAgcHJvcGVydGllcy5kZXNjZW50ID0gTWF0aC5taW4oZm9udEJCb3hbMV0sIGZvbnRCQm94WzNdKTsKICAgICAgICAgIHByb3BlcnRpZXMuYXNjZW50U2NhbGVkID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS90eXBlMV9mb250LmpzCgoKCgoKCmZ1bmN0aW9uIGZpbmRCbG9jayhzdHJlYW1CeXRlcywgc2lnbmF0dXJlLCBzdGFydEluZGV4KSB7CiAgY29uc3Qgc3RyZWFtQnl0ZXNMZW5ndGggPSBzdHJlYW1CeXRlcy5sZW5ndGg7CiAgY29uc3Qgc2lnbmF0dXJlTGVuZ3RoID0gc2lnbmF0dXJlLmxlbmd0aDsKICBjb25zdCBzY2FuTGVuZ3RoID0gc3RyZWFtQnl0ZXNMZW5ndGggLSBzaWduYXR1cmVMZW5ndGg7CiAgbGV0IGkgPSBzdGFydEluZGV4LAogICAgZm91bmQgPSBmYWxzZTsKICB3aGlsZSAoaSA8IHNjYW5MZW5ndGgpIHsKICAgIGxldCBqID0gMDsKICAgIHdoaWxlIChqIDwgc2lnbmF0dXJlTGVuZ3RoICYmIHN0cmVhbUJ5dGVzW2kgKyBqXSA9PT0gc2lnbmF0dXJlW2pdKSB7CiAgICAgIGorKzsKICAgIH0KICAgIGlmIChqID49IHNpZ25hdHVyZUxlbmd0aCkgewogICAgICBpICs9IGo7CiAgICAgIHdoaWxlIChpIDwgc3RyZWFtQnl0ZXNMZW5ndGggJiYgaXNXaGl0ZVNwYWNlKHN0cmVhbUJ5dGVzW2ldKSkgewogICAgICAgIGkrKzsKICAgICAgfQogICAgICBmb3VuZCA9IHRydWU7CiAgICAgIGJyZWFrOwogICAgfQogICAgaSsrOwogIH0KICByZXR1cm4gewogICAgZm91bmQsCiAgICBsZW5ndGg6IGkKICB9Owp9CmZ1bmN0aW9uIGdldEhlYWRlckJsb2NrKHN0cmVhbSwgc3VnZ2VzdGVkTGVuZ3RoKSB7CiAgY29uc3QgRUVYRUNfU0lHTkFUVVJFID0gWzB4NjUsIDB4NjUsIDB4NzgsIDB4NjUsIDB4NjNdOwogIGNvbnN0IHN0cmVhbVN0YXJ0UG9zID0gc3RyZWFtLnBvczsKICBsZXQgaGVhZGVyQnl0ZXMsIGhlYWRlckJ5dGVzTGVuZ3RoLCBibG9jazsKICB0cnkgewogICAgaGVhZGVyQnl0ZXMgPSBzdHJlYW0uZ2V0Qnl0ZXMoc3VnZ2VzdGVkTGVuZ3RoKTsKICAgIGhlYWRlckJ5dGVzTGVuZ3RoID0gaGVhZGVyQnl0ZXMubGVuZ3RoOwogIH0gY2F0Y2gge30KICBpZiAoaGVhZGVyQnl0ZXNMZW5ndGggPT09IHN1Z2dlc3RlZExlbmd0aCkgewogICAgYmxvY2sgPSBmaW5kQmxvY2soaGVhZGVyQnl0ZXMsIEVFWEVDX1NJR05BVFVSRSwgc3VnZ2VzdGVkTGVuZ3RoIC0gMiAqIEVFWEVDX1NJR05BVFVSRS5sZW5ndGgpOwogICAgaWYgKGJsb2NrLmZvdW5kICYmIGJsb2NrLmxlbmd0aCA9PT0gc3VnZ2VzdGVkTGVuZ3RoKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgc3RyZWFtOiBuZXcgU3RyZWFtKGhlYWRlckJ5dGVzKSwKICAgICAgICBsZW5ndGg6IHN1Z2dlc3RlZExlbmd0aAogICAgICB9OwogICAgfQogIH0KICB3YXJuKCdJbnZhbGlkICJMZW5ndGgxIiBwcm9wZXJ0eSBpbiBUeXBlMSBmb250IC0tIHRyeWluZyB0byByZWNvdmVyLicpOwogIHN0cmVhbS5wb3MgPSBzdHJlYW1TdGFydFBvczsKICBjb25zdCBTQ0FOX0JMT0NLX0xFTkdUSCA9IDIwNDg7CiAgbGV0IGFjdHVhbExlbmd0aDsKICB3aGlsZSAodHJ1ZSkgewogICAgY29uc3Qgc2NhbkJ5dGVzID0gc3RyZWFtLnBlZWtCeXRlcyhTQ0FOX0JMT0NLX0xFTkdUSCk7CiAgICBibG9jayA9IGZpbmRCbG9jayhzY2FuQnl0ZXMsIEVFWEVDX1NJR05BVFVSRSwgMCk7CiAgICBpZiAoYmxvY2subGVuZ3RoID09PSAwKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgc3RyZWFtLnBvcyArPSBibG9jay5sZW5ndGg7CiAgICBpZiAoYmxvY2suZm91bmQpIHsKICAgICAgYWN0dWFsTGVuZ3RoID0gc3RyZWFtLnBvcyAtIHN0cmVhbVN0YXJ0UG9zOwogICAgICBicmVhazsKICAgIH0KICB9CiAgc3RyZWFtLnBvcyA9IHN0cmVhbVN0YXJ0UG9zOwogIGlmIChhY3R1YWxMZW5ndGgpIHsKICAgIHJldHVybiB7CiAgICAgIHN0cmVhbTogbmV3IFN0cmVhbShzdHJlYW0uZ2V0Qnl0ZXMoYWN0dWFsTGVuZ3RoKSksCiAgICAgIGxlbmd0aDogYWN0dWFsTGVuZ3RoCiAgICB9OwogIH0KICB3YXJuKCdVbmFibGUgdG8gcmVjb3ZlciAiTGVuZ3RoMSIgcHJvcGVydHkgaW4gVHlwZTEgZm9udCAtLSB1c2luZyBhcyBpcy4nKTsKICByZXR1cm4gewogICAgc3RyZWFtOiBuZXcgU3RyZWFtKHN0cmVhbS5nZXRCeXRlcyhzdWdnZXN0ZWRMZW5ndGgpKSwKICAgIGxlbmd0aDogc3VnZ2VzdGVkTGVuZ3RoCiAgfTsKfQpmdW5jdGlvbiBnZXRFZXhlY0Jsb2NrKHN0cmVhbSwgc3VnZ2VzdGVkTGVuZ3RoKSB7CiAgY29uc3QgZWV4ZWNCeXRlcyA9IHN0cmVhbS5nZXRCeXRlcygpOwogIGlmIChlZXhlY0J5dGVzLmxlbmd0aCA9PT0gMCkgewogICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJnZXRFZXhlY0Jsb2NrIC0gbm8gZm9udCBwcm9ncmFtIGZvdW5kLiIpOwogIH0KICByZXR1cm4gewogICAgc3RyZWFtOiBuZXcgU3RyZWFtKGVleGVjQnl0ZXMpLAogICAgbGVuZ3RoOiBlZXhlY0J5dGVzLmxlbmd0aAogIH07Cn0KY2xhc3MgVHlwZTFGb250IHsKICBjb25zdHJ1Y3RvcihuYW1lLCBmaWxlLCBwcm9wZXJ0aWVzKSB7CiAgICBjb25zdCBQRkJfSEVBREVSX1NJWkUgPSA2OwogICAgbGV0IGhlYWRlckJsb2NrTGVuZ3RoID0gcHJvcGVydGllcy5sZW5ndGgxOwogICAgbGV0IGVleGVjQmxvY2tMZW5ndGggPSBwcm9wZXJ0aWVzLmxlbmd0aDI7CiAgICBsZXQgcGZiSGVhZGVyID0gZmlsZS5wZWVrQnl0ZXMoUEZCX0hFQURFUl9TSVpFKTsKICAgIGNvbnN0IHBmYkhlYWRlclByZXNlbnQgPSBwZmJIZWFkZXJbMF0gPT09IDB4ODAgJiYgcGZiSGVhZGVyWzFdID09PSAweDAxOwogICAgaWYgKHBmYkhlYWRlclByZXNlbnQpIHsKICAgICAgZmlsZS5za2lwKFBGQl9IRUFERVJfU0laRSk7CiAgICAgIGhlYWRlckJsb2NrTGVuZ3RoID0gcGZiSGVhZGVyWzVdIDw8IDI0IHwgcGZiSGVhZGVyWzRdIDw8IDE2IHwgcGZiSGVhZGVyWzNdIDw8IDggfCBwZmJIZWFkZXJbMl07CiAgICB9CiAgICBjb25zdCBoZWFkZXJCbG9jayA9IGdldEhlYWRlckJsb2NrKGZpbGUsIGhlYWRlckJsb2NrTGVuZ3RoKTsKICAgIGNvbnN0IGhlYWRlckJsb2NrUGFyc2VyID0gbmV3IFR5cGUxUGFyc2VyKGhlYWRlckJsb2NrLnN0cmVhbSwgZmFsc2UsIFNFQUNfQU5BTFlTSVNfRU5BQkxFRCk7CiAgICBoZWFkZXJCbG9ja1BhcnNlci5leHRyYWN0Rm9udEhlYWRlcihwcm9wZXJ0aWVzKTsKICAgIGlmIChwZmJIZWFkZXJQcmVzZW50KSB7CiAgICAgIHBmYkhlYWRlciA9IGZpbGUuZ2V0Qnl0ZXMoUEZCX0hFQURFUl9TSVpFKTsKICAgICAgZWV4ZWNCbG9ja0xlbmd0aCA9IHBmYkhlYWRlcls1XSA8PCAyNCB8IHBmYkhlYWRlcls0XSA8PCAxNiB8IHBmYkhlYWRlclszXSA8PCA4IHwgcGZiSGVhZGVyWzJdOwogICAgfQogICAgY29uc3QgZWV4ZWNCbG9jayA9IGdldEVleGVjQmxvY2soZmlsZSwgZWV4ZWNCbG9ja0xlbmd0aCk7CiAgICBjb25zdCBlZXhlY0Jsb2NrUGFyc2VyID0gbmV3IFR5cGUxUGFyc2VyKGVleGVjQmxvY2suc3RyZWFtLCB0cnVlLCBTRUFDX0FOQUxZU0lTX0VOQUJMRUQpOwogICAgY29uc3QgZGF0YSA9IGVleGVjQmxvY2tQYXJzZXIuZXh0cmFjdEZvbnRQcm9ncmFtKHByb3BlcnRpZXMpOwogICAgZm9yIChjb25zdCBrZXkgaW4gZGF0YS5wcm9wZXJ0aWVzKSB7CiAgICAgIHByb3BlcnRpZXNba2V5XSA9IGRhdGEucHJvcGVydGllc1trZXldOwogICAgfQogICAgY29uc3QgY2hhcnN0cmluZ3MgPSBkYXRhLmNoYXJzdHJpbmdzOwogICAgY29uc3QgdHlwZTJDaGFyc3RyaW5ncyA9IHRoaXMuZ2V0VHlwZTJDaGFyc3RyaW5ncyhjaGFyc3RyaW5ncyk7CiAgICBjb25zdCBzdWJycyA9IHRoaXMuZ2V0VHlwZTJTdWJycyhkYXRhLnN1YnJzKTsKICAgIHRoaXMuY2hhcnN0cmluZ3MgPSBjaGFyc3RyaW5nczsKICAgIHRoaXMuZGF0YSA9IHRoaXMud3JhcChuYW1lLCB0eXBlMkNoYXJzdHJpbmdzLCB0aGlzLmNoYXJzdHJpbmdzLCBzdWJycywgcHJvcGVydGllcyk7CiAgICB0aGlzLnNlYWNzID0gdGhpcy5nZXRTZWFjcyhkYXRhLmNoYXJzdHJpbmdzKTsKICB9CiAgZ2V0IG51bUdseXBocygpIHsKICAgIHJldHVybiB0aGlzLmNoYXJzdHJpbmdzLmxlbmd0aCArIDE7CiAgfQogIGdldENoYXJzZXQoKSB7CiAgICBjb25zdCBjaGFyc2V0ID0gWyIubm90ZGVmIl07CiAgICBmb3IgKGNvbnN0IHsKICAgICAgZ2x5cGhOYW1lCiAgICB9IG9mIHRoaXMuY2hhcnN0cmluZ3MpIHsKICAgICAgY2hhcnNldC5wdXNoKGdseXBoTmFtZSk7CiAgICB9CiAgICByZXR1cm4gY2hhcnNldDsKICB9CiAgZ2V0R2x5cGhNYXBwaW5nKHByb3BlcnRpZXMpIHsKICAgIGNvbnN0IGNoYXJzdHJpbmdzID0gdGhpcy5jaGFyc3RyaW5nczsKICAgIGlmIChwcm9wZXJ0aWVzLmNvbXBvc2l0ZSkgewogICAgICBjb25zdCBjaGFyQ29kZVRvR2x5cGhJZCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIGZvciAobGV0IGdseXBoSWQgPSAwLCBjaGFyc3RyaW5nc0xlbiA9IGNoYXJzdHJpbmdzLmxlbmd0aDsgZ2x5cGhJZCA8IGNoYXJzdHJpbmdzTGVuOyBnbHlwaElkKyspIHsKICAgICAgICBjb25zdCBjaGFyQ29kZSA9IHByb3BlcnRpZXMuY01hcC5jaGFyQ29kZU9mKGdseXBoSWQpOwogICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IGdseXBoSWQgKyAxOwogICAgICB9CiAgICAgIHJldHVybiBjaGFyQ29kZVRvR2x5cGhJZDsKICAgIH0KICAgIGNvbnN0IGdseXBoTmFtZXMgPSBbIi5ub3RkZWYiXTsKICAgIGxldCBidWlsdEluRW5jb2RpbmcsIGdseXBoSWQ7CiAgICBmb3IgKGdseXBoSWQgPSAwOyBnbHlwaElkIDwgY2hhcnN0cmluZ3MubGVuZ3RoOyBnbHlwaElkKyspIHsKICAgICAgZ2x5cGhOYW1lcy5wdXNoKGNoYXJzdHJpbmdzW2dseXBoSWRdLmdseXBoTmFtZSk7CiAgICB9CiAgICBjb25zdCBlbmNvZGluZyA9IHByb3BlcnRpZXMuYnVpbHRJbkVuY29kaW5nOwogICAgaWYgKGVuY29kaW5nKSB7CiAgICAgIGJ1aWx0SW5FbmNvZGluZyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIGZvciAoY29uc3QgY2hhckNvZGUgaW4gZW5jb2RpbmcpIHsKICAgICAgICBnbHlwaElkID0gZ2x5cGhOYW1lcy5pbmRleE9mKGVuY29kaW5nW2NoYXJDb2RlXSk7CiAgICAgICAgaWYgKGdseXBoSWQgPj0gMCkgewogICAgICAgICAgYnVpbHRJbkVuY29kaW5nW2NoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHlwZTFGb250R2x5cGhNYXBwaW5nKHByb3BlcnRpZXMsIGJ1aWx0SW5FbmNvZGluZywgZ2x5cGhOYW1lcyk7CiAgfQogIGhhc0dseXBoSWQoaWQpIHsKICAgIGlmIChpZCA8IDAgfHwgaWQgPj0gdGhpcy5udW1HbHlwaHMpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKGlkID09PSAwKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgY29uc3QgZ2x5cGggPSB0aGlzLmNoYXJzdHJpbmdzW2lkIC0gMV07CiAgICByZXR1cm4gZ2x5cGguY2hhcnN0cmluZy5sZW5ndGggPiAwOwogIH0KICBnZXRTZWFjcyhjaGFyc3RyaW5ncykgewogICAgY29uc3Qgc2VhY01hcCA9IFtdOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gY2hhcnN0cmluZ3MubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBjaGFyc3RyaW5nID0gY2hhcnN0cmluZ3NbaV07CiAgICAgIGlmIChjaGFyc3RyaW5nLnNlYWMpIHsKICAgICAgICBzZWFjTWFwW2kgKyAxXSA9IGNoYXJzdHJpbmcuc2VhYzsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHNlYWNNYXA7CiAgfQogIGdldFR5cGUyQ2hhcnN0cmluZ3ModHlwZTFDaGFyc3RyaW5ncykgewogICAgY29uc3QgdHlwZTJDaGFyc3RyaW5ncyA9IFtdOwogICAgZm9yIChjb25zdCB0eXBlMUNoYXJzdHJpbmcgb2YgdHlwZTFDaGFyc3RyaW5ncykgewogICAgICB0eXBlMkNoYXJzdHJpbmdzLnB1c2godHlwZTFDaGFyc3RyaW5nLmNoYXJzdHJpbmcpOwogICAgfQogICAgcmV0dXJuIHR5cGUyQ2hhcnN0cmluZ3M7CiAgfQogIGdldFR5cGUyU3VicnModHlwZTFTdWJycykgewogICAgbGV0IGJpYXMgPSAwOwogICAgY29uc3QgY291bnQgPSB0eXBlMVN1YnJzLmxlbmd0aDsKICAgIGlmIChjb3VudCA8IDExMzMpIHsKICAgICAgYmlhcyA9IDEwNzsKICAgIH0gZWxzZSBpZiAoY291bnQgPCAzMzc2OSkgewogICAgICBiaWFzID0gMTEzMTsKICAgIH0gZWxzZSB7CiAgICAgIGJpYXMgPSAzMjc2ODsKICAgIH0KICAgIGNvbnN0IHR5cGUyU3VicnMgPSBbXTsKICAgIGxldCBpOwogICAgZm9yIChpID0gMDsgaSA8IGJpYXM7IGkrKykgewogICAgICB0eXBlMlN1YnJzLnB1c2goWzB4MGJdKTsKICAgIH0KICAgIGZvciAoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIHR5cGUyU3VicnMucHVzaCh0eXBlMVN1YnJzW2ldKTsKICAgIH0KICAgIHJldHVybiB0eXBlMlN1YnJzOwogIH0KICB3cmFwKG5hbWUsIGdseXBocywgY2hhcnN0cmluZ3MsIHN1YnJzLCBwcm9wZXJ0aWVzKSB7CiAgICBjb25zdCBjZmYgPSBuZXcgQ0ZGKCk7CiAgICBjZmYuaGVhZGVyID0gbmV3IENGRkhlYWRlcigxLCAwLCA0LCA0KTsKICAgIGNmZi5uYW1lcyA9IFtuYW1lXTsKICAgIGNvbnN0IHRvcERpY3QgPSBuZXcgQ0ZGVG9wRGljdCgpOwogICAgdG9wRGljdC5zZXRCeU5hbWUoInZlcnNpb24iLCAzOTEpOwogICAgdG9wRGljdC5zZXRCeU5hbWUoIk5vdGljZSIsIDM5Mik7CiAgICB0b3BEaWN0LnNldEJ5TmFtZSgiRnVsbE5hbWUiLCAzOTMpOwogICAgdG9wRGljdC5zZXRCeU5hbWUoIkZhbWlseU5hbWUiLCAzOTQpOwogICAgdG9wRGljdC5zZXRCeU5hbWUoIldlaWdodCIsIDM5NSk7CiAgICB0b3BEaWN0LnNldEJ5TmFtZSgiRW5jb2RpbmciLCBudWxsKTsKICAgIHRvcERpY3Quc2V0QnlOYW1lKCJGb250TWF0cml4IiwgcHJvcGVydGllcy5mb250TWF0cml4KTsKICAgIHRvcERpY3Quc2V0QnlOYW1lKCJGb250QkJveCIsIHByb3BlcnRpZXMuYmJveCk7CiAgICB0b3BEaWN0LnNldEJ5TmFtZSgiY2hhcnNldCIsIG51bGwpOwogICAgdG9wRGljdC5zZXRCeU5hbWUoIkNoYXJTdHJpbmdzIiwgbnVsbCk7CiAgICB0b3BEaWN0LnNldEJ5TmFtZSgiUHJpdmF0ZSIsIG51bGwpOwogICAgY2ZmLnRvcERpY3QgPSB0b3BEaWN0OwogICAgY29uc3Qgc3RyaW5ncyA9IG5ldyBDRkZTdHJpbmdzKCk7CiAgICBzdHJpbmdzLmFkZCgiVmVyc2lvbiAwLjExIik7CiAgICBzdHJpbmdzLmFkZCgiU2VlIG9yaWdpbmFsIG5vdGljZSIpOwogICAgc3RyaW5ncy5hZGQobmFtZSk7CiAgICBzdHJpbmdzLmFkZChuYW1lKTsKICAgIHN0cmluZ3MuYWRkKCJNZWRpdW0iKTsKICAgIGNmZi5zdHJpbmdzID0gc3RyaW5nczsKICAgIGNmZi5nbG9iYWxTdWJySW5kZXggPSBuZXcgQ0ZGSW5kZXgoKTsKICAgIGNvbnN0IGNvdW50ID0gZ2x5cGhzLmxlbmd0aDsKICAgIGNvbnN0IGNoYXJzZXRBcnJheSA9IFsiLm5vdGRlZiJdOwogICAgbGV0IGksIGlpOwogICAgZm9yIChpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgY29uc3QgZ2x5cGhOYW1lID0gY2hhcnN0cmluZ3NbaV0uZ2x5cGhOYW1lOwogICAgICBjb25zdCBpbmRleCA9IENGRlN0YW5kYXJkU3RyaW5ncy5pbmRleE9mKGdseXBoTmFtZSk7CiAgICAgIGlmIChpbmRleCA9PT0gLTEpIHsKICAgICAgICBzdHJpbmdzLmFkZChnbHlwaE5hbWUpOwogICAgICB9CiAgICAgIGNoYXJzZXRBcnJheS5wdXNoKGdseXBoTmFtZSk7CiAgICB9CiAgICBjZmYuY2hhcnNldCA9IG5ldyBDRkZDaGFyc2V0KGZhbHNlLCAwLCBjaGFyc2V0QXJyYXkpOwogICAgY29uc3QgY2hhclN0cmluZ3NJbmRleCA9IG5ldyBDRkZJbmRleCgpOwogICAgY2hhclN0cmluZ3NJbmRleC5hZGQoWzB4OGIsIDB4MGVdKTsKICAgIGZvciAoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIGNoYXJTdHJpbmdzSW5kZXguYWRkKGdseXBoc1tpXSk7CiAgICB9CiAgICBjZmYuY2hhclN0cmluZ3MgPSBjaGFyU3RyaW5nc0luZGV4OwogICAgY29uc3QgcHJpdmF0ZURpY3QgPSBuZXcgQ0ZGUHJpdmF0ZURpY3QoKTsKICAgIHByaXZhdGVEaWN0LnNldEJ5TmFtZSgiU3VicnMiLCBudWxsKTsKICAgIGNvbnN0IGZpZWxkcyA9IFsiQmx1ZVZhbHVlcyIsICJPdGhlckJsdWVzIiwgIkZhbWlseUJsdWVzIiwgIkZhbWlseU90aGVyQmx1ZXMiLCAiU3RlbVNuYXBIIiwgIlN0ZW1TbmFwViIsICJCbHVlU2hpZnQiLCAiQmx1ZUZ1enoiLCAiQmx1ZVNjYWxlIiwgIkxhbmd1YWdlR3JvdXAiLCAiRXhwYW5zaW9uRmFjdG9yIiwgIkZvcmNlQm9sZCIsICJTdGRIVyIsICJTdGRWVyJdOwogICAgZm9yIChpID0gMCwgaWkgPSBmaWVsZHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBmaWVsZCA9IGZpZWxkc1tpXTsKICAgICAgaWYgKCEoZmllbGQgaW4gcHJvcGVydGllcy5wcml2YXRlRGF0YSkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB2YWx1ZSA9IHByb3BlcnRpZXMucHJpdmF0ZURhdGFbZmllbGRdOwogICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgICBmb3IgKGxldCBqID0gdmFsdWUubGVuZ3RoIC0gMTsgaiA+IDA7IGotLSkgewogICAgICAgICAgdmFsdWVbal0gLT0gdmFsdWVbaiAtIDFdOwogICAgICAgIH0KICAgICAgfQogICAgICBwcml2YXRlRGljdC5zZXRCeU5hbWUoZmllbGQsIHZhbHVlKTsKICAgIH0KICAgIGNmZi50b3BEaWN0LnByaXZhdGVEaWN0ID0gcHJpdmF0ZURpY3Q7CiAgICBjb25zdCBzdWJySW5kZXggPSBuZXcgQ0ZGSW5kZXgoKTsKICAgIGZvciAoaSA9IDAsIGlpID0gc3VicnMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBzdWJySW5kZXguYWRkKHN1YnJzW2ldKTsKICAgIH0KICAgIHByaXZhdGVEaWN0LnN1YnJzSW5kZXggPSBzdWJySW5kZXg7CiAgICBjb25zdCBjb21waWxlciA9IG5ldyBDRkZDb21waWxlcihjZmYpOwogICAgcmV0dXJuIGNvbXBpbGVyLmNvbXBpbGUoKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2ZvbnRzLmpzCgoKCgoKCgoKCgoKCgoKCgpjb25zdCBQUklWQVRFX1VTRV9BUkVBUyA9IFtbMHhlMDAwLCAweGY4ZmZdLCBbMHgxMDAwMDAsIDB4MTBmZmZkXV07CmNvbnN0IFBERl9HTFlQSF9TUEFDRV9VTklUUyA9IDEwMDA7CmNvbnN0IEVYUE9SVF9EQVRBX1BST1BFUlRJRVMgPSBbImFzY2VudCIsICJiYm94IiwgImJsYWNrIiwgImJvbGQiLCAiY2hhclByb2NPcGVyYXRvckxpc3QiLCAiY3NzRm9udEluZm8iLCAiZGF0YSIsICJkZWZhdWx0Vk1ldHJpY3MiLCAiZGVmYXVsdFdpZHRoIiwgImRlc2NlbnQiLCAiZGlzYWJsZUZvbnRGYWNlIiwgImZhbGxiYWNrTmFtZSIsICJmb250RXh0cmFQcm9wZXJ0aWVzIiwgImZvbnRNYXRyaXgiLCAiaXNJbnZhbGlkUERGanNGb250IiwgImlzVHlwZTNGb250IiwgIml0YWxpYyIsICJsb2FkZWROYW1lIiwgIm1pbWV0eXBlIiwgIm1pc3NpbmdGaWxlIiwgIm5hbWUiLCAicmVtZWFzdXJlIiwgInN5c3RlbUZvbnRJbmZvIiwgInZlcnRpY2FsIl07CmNvbnN0IEVYUE9SVF9EQVRBX0VYVFJBX1BST1BFUlRJRVMgPSBbImNNYXAiLCAiY29tcG9zaXRlIiwgImRlZmF1bHRFbmNvZGluZyIsICJkaWZmZXJlbmNlcyIsICJpc01vbm9zcGFjZSIsICJpc1NlcmlmRm9udCIsICJpc1N5bWJvbGljRm9udCIsICJzZWFjTWFwIiwgInN1YnR5cGUiLCAidG9Gb250Q2hhciIsICJ0b1VuaWNvZGUiLCAidHlwZSIsICJ2bWV0cmljcyIsICJ3aWR0aHMiXTsKZnVuY3Rpb24gYWRqdXN0V2lkdGhzKHByb3BlcnRpZXMpIHsKICBpZiAoIXByb3BlcnRpZXMuZm9udE1hdHJpeCkgewogICAgcmV0dXJuOwogIH0KICBpZiAocHJvcGVydGllcy5mb250TWF0cml4WzBdID09PSBGT05UX0lERU5USVRZX01BVFJJWFswXSkgewogICAgcmV0dXJuOwogIH0KICBjb25zdCBzY2FsZSA9IDAuMDAxIC8gcHJvcGVydGllcy5mb250TWF0cml4WzBdOwogIGNvbnN0IGdseXBoc1dpZHRocyA9IHByb3BlcnRpZXMud2lkdGhzOwogIGZvciAoY29uc3QgZ2x5cGggaW4gZ2x5cGhzV2lkdGhzKSB7CiAgICBnbHlwaHNXaWR0aHNbZ2x5cGhdICo9IHNjYWxlOwogIH0KICBwcm9wZXJ0aWVzLmRlZmF1bHRXaWR0aCAqPSBzY2FsZTsKfQpmdW5jdGlvbiBhZGp1c3RUcnVlVHlwZVRvVW5pY29kZShwcm9wZXJ0aWVzLCBpc1N5bWJvbGljRm9udCwgbmFtZVJlY29yZHMpIHsKICBpZiAocHJvcGVydGllcy5pc0ludGVybmFsRm9udCkgewogICAgcmV0dXJuOwogIH0KICBpZiAocHJvcGVydGllcy5oYXNJbmNsdWRlZFRvVW5pY29kZU1hcCkgewogICAgcmV0dXJuOwogIH0KICBpZiAocHJvcGVydGllcy5oYXNFbmNvZGluZykgewogICAgcmV0dXJuOwogIH0KICBpZiAocHJvcGVydGllcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBJZGVudGl0eVRvVW5pY29kZU1hcCkgewogICAgcmV0dXJuOwogIH0KICBpZiAoIWlzU3ltYm9saWNGb250KSB7CiAgICByZXR1cm47CiAgfQogIGlmIChuYW1lUmVjb3Jkcy5sZW5ndGggPT09IDApIHsKICAgIHJldHVybjsKICB9CiAgaWYgKHByb3BlcnRpZXMuZGVmYXVsdEVuY29kaW5nID09PSBXaW5BbnNpRW5jb2RpbmcpIHsKICAgIHJldHVybjsKICB9CiAgZm9yIChjb25zdCByIG9mIG5hbWVSZWNvcmRzKSB7CiAgICBpZiAoIWlzV2luTmFtZVJlY29yZChyKSkgewogICAgICByZXR1cm47CiAgICB9CiAgfQogIGNvbnN0IGVuY29kaW5nID0gV2luQW5zaUVuY29kaW5nOwogIGNvbnN0IHRvVW5pY29kZSA9IFtdLAogICAgZ2x5cGhzVW5pY29kZU1hcCA9IGdldEdseXBoc1VuaWNvZGUoKTsKICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIGVuY29kaW5nKSB7CiAgICBjb25zdCBnbHlwaE5hbWUgPSBlbmNvZGluZ1tjaGFyQ29kZV07CiAgICBpZiAoZ2x5cGhOYW1lID09PSAiIikgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGNvbnN0IHVuaWNvZGUgPSBnbHlwaHNVbmljb2RlTWFwW2dseXBoTmFtZV07CiAgICBpZiAodW5pY29kZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgdG9Vbmljb2RlW2NoYXJDb2RlXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUodW5pY29kZSk7CiAgfQogIGlmICh0b1VuaWNvZGUubGVuZ3RoID4gMCkgewogICAgcHJvcGVydGllcy50b1VuaWNvZGUuYW1lbmQodG9Vbmljb2RlKTsKICB9Cn0KZnVuY3Rpb24gYWRqdXN0VHlwZTFUb1VuaWNvZGUocHJvcGVydGllcywgYnVpbHRJbkVuY29kaW5nKSB7CiAgaWYgKHByb3BlcnRpZXMuaXNJbnRlcm5hbEZvbnQpIHsKICAgIHJldHVybjsKICB9CiAgaWYgKHByb3BlcnRpZXMuaGFzSW5jbHVkZWRUb1VuaWNvZGVNYXApIHsKICAgIHJldHVybjsKICB9CiAgaWYgKGJ1aWx0SW5FbmNvZGluZyA9PT0gcHJvcGVydGllcy5kZWZhdWx0RW5jb2RpbmcpIHsKICAgIHJldHVybjsKICB9CiAgaWYgKHByb3BlcnRpZXMudG9Vbmljb2RlIGluc3RhbmNlb2YgSWRlbnRpdHlUb1VuaWNvZGVNYXApIHsKICAgIHJldHVybjsKICB9CiAgY29uc3QgdG9Vbmljb2RlID0gW10sCiAgICBnbHlwaHNVbmljb2RlTWFwID0gZ2V0R2x5cGhzVW5pY29kZSgpOwogIGZvciAoY29uc3QgY2hhckNvZGUgaW4gYnVpbHRJbkVuY29kaW5nKSB7CiAgICBpZiAocHJvcGVydGllcy5oYXNFbmNvZGluZykgewogICAgICBpZiAocHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lIHx8IHByb3BlcnRpZXMuZGlmZmVyZW5jZXNbY2hhckNvZGVdICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgfQogICAgY29uc3QgZ2x5cGhOYW1lID0gYnVpbHRJbkVuY29kaW5nW2NoYXJDb2RlXTsKICAgIGNvbnN0IHVuaWNvZGUgPSBnZXRVbmljb2RlRm9yR2x5cGgoZ2x5cGhOYW1lLCBnbHlwaHNVbmljb2RlTWFwKTsKICAgIGlmICh1bmljb2RlICE9PSAtMSkgewogICAgICB0b1VuaWNvZGVbY2hhckNvZGVdID0gU3RyaW5nLmZyb21DaGFyQ29kZSh1bmljb2RlKTsKICAgIH0KICB9CiAgaWYgKHRvVW5pY29kZS5sZW5ndGggPiAwKSB7CiAgICBwcm9wZXJ0aWVzLnRvVW5pY29kZS5hbWVuZCh0b1VuaWNvZGUpOwogIH0KfQpmdW5jdGlvbiBhbWVuZEZhbGxiYWNrVG9Vbmljb2RlKHByb3BlcnRpZXMpIHsKICBpZiAoIXByb3BlcnRpZXMuZmFsbGJhY2tUb1VuaWNvZGUpIHsKICAgIHJldHVybjsKICB9CiAgaWYgKHByb3BlcnRpZXMudG9Vbmljb2RlIGluc3RhbmNlb2YgSWRlbnRpdHlUb1VuaWNvZGVNYXApIHsKICAgIHJldHVybjsKICB9CiAgY29uc3QgdG9Vbmljb2RlID0gW107CiAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBwcm9wZXJ0aWVzLmZhbGxiYWNrVG9Vbmljb2RlKSB7CiAgICBpZiAocHJvcGVydGllcy50b1VuaWNvZGUuaGFzKGNoYXJDb2RlKSkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIHRvVW5pY29kZVtjaGFyQ29kZV0gPSBwcm9wZXJ0aWVzLmZhbGxiYWNrVG9Vbmljb2RlW2NoYXJDb2RlXTsKICB9CiAgaWYgKHRvVW5pY29kZS5sZW5ndGggPiAwKSB7CiAgICBwcm9wZXJ0aWVzLnRvVW5pY29kZS5hbWVuZCh0b1VuaWNvZGUpOwogIH0KfQpjbGFzcyBmb250c19HbHlwaCB7CiAgY29uc3RydWN0b3Iob3JpZ2luYWxDaGFyQ29kZSwgZm9udENoYXIsIHVuaWNvZGUsIGFjY2VudCwgd2lkdGgsIHZtZXRyaWMsIG9wZXJhdG9yTGlzdElkLCBpc1NwYWNlLCBpc0luRm9udCkgewogICAgdGhpcy5vcmlnaW5hbENoYXJDb2RlID0gb3JpZ2luYWxDaGFyQ29kZTsKICAgIHRoaXMuZm9udENoYXIgPSBmb250Q2hhcjsKICAgIHRoaXMudW5pY29kZSA9IHVuaWNvZGU7CiAgICB0aGlzLmFjY2VudCA9IGFjY2VudDsKICAgIHRoaXMud2lkdGggPSB3aWR0aDsKICAgIHRoaXMudm1ldHJpYyA9IHZtZXRyaWM7CiAgICB0aGlzLm9wZXJhdG9yTGlzdElkID0gb3BlcmF0b3JMaXN0SWQ7CiAgICB0aGlzLmlzU3BhY2UgPSBpc1NwYWNlOwogICAgdGhpcy5pc0luRm9udCA9IGlzSW5Gb250OwogIH0KICBnZXQgY2F0ZWdvcnkoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJjYXRlZ29yeSIsIGdldENoYXJVbmljb2RlQ2F0ZWdvcnkodGhpcy51bmljb2RlKSwgdHJ1ZSk7CiAgfQp9CmZ1bmN0aW9uIGludDE2KGIwLCBiMSkgewogIHJldHVybiAoYjAgPDwgOCkgKyBiMTsKfQpmdW5jdGlvbiB3cml0ZVNpZ25lZEludDE2KGJ5dGVzLCBpbmRleCwgdmFsdWUpIHsKICBieXRlc1tpbmRleCArIDFdID0gdmFsdWU7CiAgYnl0ZXNbaW5kZXhdID0gdmFsdWUgPj4+IDg7Cn0KZnVuY3Rpb24gc2lnbmVkSW50MTYoYjAsIGIxKSB7CiAgY29uc3QgdmFsdWUgPSAoYjAgPDwgOCkgKyBiMTsKICByZXR1cm4gdmFsdWUgJiAxIDw8IDE1ID8gdmFsdWUgLSAweDEwMDAwIDogdmFsdWU7Cn0KZnVuY3Rpb24gd3JpdGVVaW50MzIoYnl0ZXMsIGluZGV4LCB2YWx1ZSkgewogIGJ5dGVzW2luZGV4ICsgM10gPSB2YWx1ZSAmIDB4ZmY7CiAgYnl0ZXNbaW5kZXggKyAyXSA9IHZhbHVlID4+PiA4OwogIGJ5dGVzW2luZGV4ICsgMV0gPSB2YWx1ZSA+Pj4gMTY7CiAgYnl0ZXNbaW5kZXhdID0gdmFsdWUgPj4+IDI0Owp9CmZ1bmN0aW9uIGludDMyKGIwLCBiMSwgYjIsIGIzKSB7CiAgcmV0dXJuIChiMCA8PCAyNCkgKyAoYjEgPDwgMTYpICsgKGIyIDw8IDgpICsgYjM7Cn0KZnVuY3Rpb24gc3RyaW5nMTYodmFsdWUpIHsKICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSh2YWx1ZSA+PiA4ICYgMHhmZiwgdmFsdWUgJiAweGZmKTsKfQpmdW5jdGlvbiBzYWZlU3RyaW5nMTYodmFsdWUpIHsKICBpZiAodmFsdWUgPiAweDdmZmYpIHsKICAgIHZhbHVlID0gMHg3ZmZmOwogIH0gZWxzZSBpZiAodmFsdWUgPCAtMHg4MDAwKSB7CiAgICB2YWx1ZSA9IC0weDgwMDA7CiAgfQogIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKHZhbHVlID4+IDggJiAweGZmLCB2YWx1ZSAmIDB4ZmYpOwp9CmZ1bmN0aW9uIGlzVHJ1ZVR5cGVGaWxlKGZpbGUpIHsKICBjb25zdCBoZWFkZXIgPSBmaWxlLnBlZWtCeXRlcyg0KTsKICByZXR1cm4gcmVhZFVpbnQzMihoZWFkZXIsIDApID09PSAweDAwMDEwMDAwIHx8IGJ5dGVzVG9TdHJpbmcoaGVhZGVyKSA9PT0gInRydWUiOwp9CmZ1bmN0aW9uIGlzVHJ1ZVR5cGVDb2xsZWN0aW9uRmlsZShmaWxlKSB7CiAgY29uc3QgaGVhZGVyID0gZmlsZS5wZWVrQnl0ZXMoNCk7CiAgcmV0dXJuIGJ5dGVzVG9TdHJpbmcoaGVhZGVyKSA9PT0gInR0Y2YiOwp9CmZ1bmN0aW9uIGlzT3BlblR5cGVGaWxlKGZpbGUpIHsKICBjb25zdCBoZWFkZXIgPSBmaWxlLnBlZWtCeXRlcyg0KTsKICByZXR1cm4gYnl0ZXNUb1N0cmluZyhoZWFkZXIpID09PSAiT1RUTyI7Cn0KZnVuY3Rpb24gaXNUeXBlMUZpbGUoZmlsZSkgewogIGNvbnN0IGhlYWRlciA9IGZpbGUucGVla0J5dGVzKDIpOwogIGlmIChoZWFkZXJbMF0gPT09IDB4MjUgJiYgaGVhZGVyWzFdID09PSAweDIxKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgaWYgKGhlYWRlclswXSA9PT0gMHg4MCAmJiBoZWFkZXJbMV0gPT09IDB4MDEpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICByZXR1cm4gZmFsc2U7Cn0KZnVuY3Rpb24gaXNDRkZGaWxlKGZpbGUpIHsKICBjb25zdCBoZWFkZXIgPSBmaWxlLnBlZWtCeXRlcyg0KTsKICBpZiAoaGVhZGVyWzBdID49IDEgJiYgaGVhZGVyWzNdID49IDEgJiYgaGVhZGVyWzNdIDw9IDQpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICByZXR1cm4gZmFsc2U7Cn0KZnVuY3Rpb24gZ2V0Rm9udEZpbGVUeXBlKGZpbGUsIHsKICB0eXBlLAogIHN1YnR5cGUsCiAgY29tcG9zaXRlCn0pIHsKICBsZXQgZmlsZVR5cGUsIGZpbGVTdWJ0eXBlOwogIGlmIChpc1RydWVUeXBlRmlsZShmaWxlKSB8fCBpc1RydWVUeXBlQ29sbGVjdGlvbkZpbGUoZmlsZSkpIHsKICAgIGZpbGVUeXBlID0gY29tcG9zaXRlID8gIkNJREZvbnRUeXBlMiIgOiAiVHJ1ZVR5cGUiOwogIH0gZWxzZSBpZiAoaXNPcGVuVHlwZUZpbGUoZmlsZSkpIHsKICAgIGZpbGVUeXBlID0gY29tcG9zaXRlID8gIkNJREZvbnRUeXBlMiIgOiAiT3BlblR5cGUiOwogIH0gZWxzZSBpZiAoaXNUeXBlMUZpbGUoZmlsZSkpIHsKICAgIGlmIChjb21wb3NpdGUpIHsKICAgICAgZmlsZVR5cGUgPSAiQ0lERm9udFR5cGUwIjsKICAgIH0gZWxzZSB7CiAgICAgIGZpbGVUeXBlID0gdHlwZSA9PT0gIk1NVHlwZTEiID8gIk1NVHlwZTEiIDogIlR5cGUxIjsKICAgIH0KICB9IGVsc2UgaWYgKGlzQ0ZGRmlsZShmaWxlKSkgewogICAgaWYgKGNvbXBvc2l0ZSkgewogICAgICBmaWxlVHlwZSA9ICJDSURGb250VHlwZTAiOwogICAgICBmaWxlU3VidHlwZSA9ICJDSURGb250VHlwZTBDIjsKICAgIH0gZWxzZSB7CiAgICAgIGZpbGVUeXBlID0gdHlwZSA9PT0gIk1NVHlwZTEiID8gIk1NVHlwZTEiIDogIlR5cGUxIjsKICAgICAgZmlsZVN1YnR5cGUgPSAiVHlwZTFDIjsKICAgIH0KICB9IGVsc2UgewogICAgd2FybigiZ2V0Rm9udEZpbGVUeXBlOiBVbmFibGUgdG8gZGV0ZWN0IGNvcnJlY3QgZm9udCBmaWxlIFR5cGUvU3VidHlwZS4iKTsKICAgIGZpbGVUeXBlID0gdHlwZTsKICAgIGZpbGVTdWJ0eXBlID0gc3VidHlwZTsKICB9CiAgcmV0dXJuIFtmaWxlVHlwZSwgZmlsZVN1YnR5cGVdOwp9CmZ1bmN0aW9uIGFwcGx5U3RhbmRhcmRGb250R2x5cGhNYXAobWFwLCBnbHlwaE1hcCkgewogIGZvciAoY29uc3QgY2hhckNvZGUgaW4gZ2x5cGhNYXApIHsKICAgIG1hcFsrY2hhckNvZGVdID0gZ2x5cGhNYXBbY2hhckNvZGVdOwogIH0KfQpmdW5jdGlvbiBidWlsZFRvRm9udENoYXIoZW5jb2RpbmcsIGdseXBoc1VuaWNvZGVNYXAsIGRpZmZlcmVuY2VzKSB7CiAgY29uc3QgdG9Gb250Q2hhciA9IFtdOwogIGxldCB1bmljb2RlOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IGVuY29kaW5nLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIHVuaWNvZGUgPSBnZXRVbmljb2RlRm9yR2x5cGgoZW5jb2RpbmdbaV0sIGdseXBoc1VuaWNvZGVNYXApOwogICAgaWYgKHVuaWNvZGUgIT09IC0xKSB7CiAgICAgIHRvRm9udENoYXJbaV0gPSB1bmljb2RlOwogICAgfQogIH0KICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIGRpZmZlcmVuY2VzKSB7CiAgICB1bmljb2RlID0gZ2V0VW5pY29kZUZvckdseXBoKGRpZmZlcmVuY2VzW2NoYXJDb2RlXSwgZ2x5cGhzVW5pY29kZU1hcCk7CiAgICBpZiAodW5pY29kZSAhPT0gLTEpIHsKICAgICAgdG9Gb250Q2hhclsrY2hhckNvZGVdID0gdW5pY29kZTsKICAgIH0KICB9CiAgcmV0dXJuIHRvRm9udENoYXI7Cn0KZnVuY3Rpb24gaXNNYWNOYW1lUmVjb3JkKHIpIHsKICByZXR1cm4gci5wbGF0Zm9ybSA9PT0gMSAmJiByLmVuY29kaW5nID09PSAwICYmIHIubGFuZ3VhZ2UgPT09IDA7Cn0KZnVuY3Rpb24gaXNXaW5OYW1lUmVjb3JkKHIpIHsKICByZXR1cm4gci5wbGF0Zm9ybSA9PT0gMyAmJiByLmVuY29kaW5nID09PSAxICYmIHIubGFuZ3VhZ2UgPT09IDB4NDA5Owp9CmZ1bmN0aW9uIGNvbnZlcnRDaWRTdHJpbmcoY2hhckNvZGUsIGNpZCwgc2hvdWxkVGhyb3cgPSBmYWxzZSkgewogIHN3aXRjaCAoY2lkLmxlbmd0aCkgewogICAgY2FzZSAxOgogICAgICByZXR1cm4gY2lkLmNoYXJDb2RlQXQoMCk7CiAgICBjYXNlIDI6CiAgICAgIHJldHVybiBjaWQuY2hhckNvZGVBdCgwKSA8PCA4IHwgY2lkLmNoYXJDb2RlQXQoMSk7CiAgfQogIGNvbnN0IG1zZyA9IGBVbnN1cHBvcnRlZCBDSUQgc3RyaW5nIChjaGFyQ29kZSAke2NoYXJDb2RlfSk6ICIke2NpZH0iLmA7CiAgaWYgKHNob3VsZFRocm93KSB7CiAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IobXNnKTsKICB9CiAgd2Fybihtc2cpOwogIHJldHVybiBjaWQ7Cn0KZnVuY3Rpb24gYWRqdXN0TWFwcGluZyhjaGFyQ29kZVRvR2x5cGhJZCwgaGFzR2x5cGgsIG5ld0dseXBoWmVyb0lkLCB0b1VuaWNvZGUpIHsKICBjb25zdCBuZXdNYXAgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIGNvbnN0IHRvVW5pY29kZUV4dHJhTWFwID0gbmV3IE1hcCgpOwogIGNvbnN0IHRvRm9udENoYXIgPSBbXTsKICBjb25zdCB1c2VkR2x5cGhJZHMgPSBuZXcgU2V0KCk7CiAgbGV0IHByaXZhdGVVc2VBcmVhSW5kZXggPSAwOwogIGNvbnN0IHByaXZhdGVVc2VPZmZldFN0YXJ0ID0gUFJJVkFURV9VU0VfQVJFQVNbcHJpdmF0ZVVzZUFyZWFJbmRleF1bMF07CiAgbGV0IG5leHRBdmFpbGFibGVGb250Q2hhckNvZGUgPSBwcml2YXRlVXNlT2ZmZXRTdGFydDsKICBsZXQgcHJpdmF0ZVVzZU9mZmV0RW5kID0gUFJJVkFURV9VU0VfQVJFQVNbcHJpdmF0ZVVzZUFyZWFJbmRleF1bMV07CiAgY29uc3QgaXNJblByaXZhdGVBcmVhID0gY29kZSA9PiBQUklWQVRFX1VTRV9BUkVBU1swXVswXSA8PSBjb2RlICYmIGNvZGUgPD0gUFJJVkFURV9VU0VfQVJFQVNbMF1bMV0gfHwgUFJJVkFURV9VU0VfQVJFQVNbMV1bMF0gPD0gY29kZSAmJiBjb2RlIDw9IFBSSVZBVEVfVVNFX0FSRUFTWzFdWzFdOwogIGxldCBMSUdBVFVSRV9UT19VTklDT0RFID0gbnVsbDsKICBmb3IgKGNvbnN0IG9yaWdpbmFsQ2hhckNvZGUgaW4gY2hhckNvZGVUb0dseXBoSWQpIHsKICAgIGxldCBnbHlwaElkID0gY2hhckNvZGVUb0dseXBoSWRbb3JpZ2luYWxDaGFyQ29kZV07CiAgICBpZiAoIWhhc0dseXBoKGdseXBoSWQpKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgaWYgKG5leHRBdmFpbGFibGVGb250Q2hhckNvZGUgPiBwcml2YXRlVXNlT2ZmZXRFbmQpIHsKICAgICAgcHJpdmF0ZVVzZUFyZWFJbmRleCsrOwogICAgICBpZiAocHJpdmF0ZVVzZUFyZWFJbmRleCA+PSBQUklWQVRFX1VTRV9BUkVBUy5sZW5ndGgpIHsKICAgICAgICB3YXJuKCJSYW4gb3V0IG9mIHNwYWNlIGluIGZvbnQgcHJpdmF0ZSB1c2UgYXJlYS4iKTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBuZXh0QXZhaWxhYmxlRm9udENoYXJDb2RlID0gUFJJVkFURV9VU0VfQVJFQVNbcHJpdmF0ZVVzZUFyZWFJbmRleF1bMF07CiAgICAgIHByaXZhdGVVc2VPZmZldEVuZCA9IFBSSVZBVEVfVVNFX0FSRUFTW3ByaXZhdGVVc2VBcmVhSW5kZXhdWzFdOwogICAgfQogICAgY29uc3QgZm9udENoYXJDb2RlID0gbmV4dEF2YWlsYWJsZUZvbnRDaGFyQ29kZSsrOwogICAgaWYgKGdseXBoSWQgPT09IDApIHsKICAgICAgZ2x5cGhJZCA9IG5ld0dseXBoWmVyb0lkOwogICAgfQogICAgbGV0IHVuaWNvZGUgPSB0b1VuaWNvZGUuZ2V0KG9yaWdpbmFsQ2hhckNvZGUpOwogICAgaWYgKHR5cGVvZiB1bmljb2RlID09PSAic3RyaW5nIikgewogICAgICBpZiAodW5pY29kZS5sZW5ndGggPT09IDEpIHsKICAgICAgICB1bmljb2RlID0gdW5pY29kZS5jb2RlUG9pbnRBdCgwKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAoIUxJR0FUVVJFX1RPX1VOSUNPREUpIHsKICAgICAgICAgIExJR0FUVVJFX1RPX1VOSUNPREUgPSBuZXcgTWFwKCk7CiAgICAgICAgICBmb3IgKGxldCBpID0gMHhmYjAwOyBpIDw9IDB4ZmI0ZjsgaSsrKSB7CiAgICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGkpLm5vcm1hbGl6ZSgiTkZLRCIpOwogICAgICAgICAgICBpZiAobm9ybWFsaXplZC5sZW5ndGggPiAxKSB7CiAgICAgICAgICAgICAgTElHQVRVUkVfVE9fVU5JQ09ERS5zZXQobm9ybWFsaXplZCwgaSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgdW5pY29kZSA9IExJR0FUVVJFX1RPX1VOSUNPREUuZ2V0KHVuaWNvZGUpIHx8IHVuaWNvZGUuY29kZVBvaW50QXQoMCk7CiAgICAgIH0KICAgIH0KICAgIGlmICh1bmljb2RlICYmICFpc0luUHJpdmF0ZUFyZWEodW5pY29kZSkgJiYgIXVzZWRHbHlwaElkcy5oYXMoZ2x5cGhJZCkpIHsKICAgICAgdG9Vbmljb2RlRXh0cmFNYXAuc2V0KHVuaWNvZGUsIGdseXBoSWQpOwogICAgICB1c2VkR2x5cGhJZHMuYWRkKGdseXBoSWQpOwogICAgfQogICAgbmV3TWFwW2ZvbnRDaGFyQ29kZV0gPSBnbHlwaElkOwogICAgdG9Gb250Q2hhcltvcmlnaW5hbENoYXJDb2RlXSA9IGZvbnRDaGFyQ29kZTsKICB9CiAgcmV0dXJuIHsKICAgIHRvRm9udENoYXIsCiAgICBjaGFyQ29kZVRvR2x5cGhJZDogbmV3TWFwLAogICAgdG9Vbmljb2RlRXh0cmFNYXAsCiAgICBuZXh0QXZhaWxhYmxlRm9udENoYXJDb2RlCiAgfTsKfQpmdW5jdGlvbiBnZXRSYW5nZXMoZ2x5cGhzLCB0b1VuaWNvZGVFeHRyYU1hcCwgbnVtR2x5cGhzKSB7CiAgY29uc3QgY29kZXMgPSBbXTsKICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIGdseXBocykgewogICAgaWYgKGdseXBoc1tjaGFyQ29kZV0gPj0gbnVtR2x5cGhzKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgY29kZXMucHVzaCh7CiAgICAgIGZvbnRDaGFyQ29kZTogY2hhckNvZGUgfCAwLAogICAgICBnbHlwaElkOiBnbHlwaHNbY2hhckNvZGVdCiAgICB9KTsKICB9CiAgaWYgKHRvVW5pY29kZUV4dHJhTWFwKSB7CiAgICBmb3IgKGNvbnN0IFt1bmljb2RlLCBnbHlwaElkXSBvZiB0b1VuaWNvZGVFeHRyYU1hcCkgewogICAgICBpZiAoZ2x5cGhJZCA+PSBudW1HbHlwaHMpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb2Rlcy5wdXNoKHsKICAgICAgICBmb250Q2hhckNvZGU6IHVuaWNvZGUsCiAgICAgICAgZ2x5cGhJZAogICAgICB9KTsKICAgIH0KICB9CiAgaWYgKGNvZGVzLmxlbmd0aCA9PT0gMCkgewogICAgY29kZXMucHVzaCh7CiAgICAgIGZvbnRDaGFyQ29kZTogMCwKICAgICAgZ2x5cGhJZDogMAogICAgfSk7CiAgfQogIGNvZGVzLnNvcnQoKGEsIGIpID0+IGEuZm9udENoYXJDb2RlIC0gYi5mb250Q2hhckNvZGUpOwogIGNvbnN0IHJhbmdlcyA9IFtdOwogIGNvbnN0IGxlbmd0aCA9IGNvZGVzLmxlbmd0aDsKICBmb3IgKGxldCBuID0gMDsgbiA8IGxlbmd0aDspIHsKICAgIGNvbnN0IHN0YXJ0ID0gY29kZXNbbl0uZm9udENoYXJDb2RlOwogICAgY29uc3QgY29kZUluZGljZXMgPSBbY29kZXNbbl0uZ2x5cGhJZF07CiAgICArK247CiAgICBsZXQgZW5kID0gc3RhcnQ7CiAgICB3aGlsZSAobiA8IGxlbmd0aCAmJiBlbmQgKyAxID09PSBjb2Rlc1tuXS5mb250Q2hhckNvZGUpIHsKICAgICAgY29kZUluZGljZXMucHVzaChjb2Rlc1tuXS5nbHlwaElkKTsKICAgICAgKytlbmQ7CiAgICAgICsrbjsKICAgICAgaWYgKGVuZCA9PT0gMHhmZmZmKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHJhbmdlcy5wdXNoKFtzdGFydCwgZW5kLCBjb2RlSW5kaWNlc10pOwogIH0KICByZXR1cm4gcmFuZ2VzOwp9CmZ1bmN0aW9uIGNyZWF0ZUNtYXBUYWJsZShnbHlwaHMsIHRvVW5pY29kZUV4dHJhTWFwLCBudW1HbHlwaHMpIHsKICBjb25zdCByYW5nZXMgPSBnZXRSYW5nZXMoZ2x5cGhzLCB0b1VuaWNvZGVFeHRyYU1hcCwgbnVtR2x5cGhzKTsKICBjb25zdCBudW1UYWJsZXMgPSByYW5nZXMuYXQoLTEpWzFdID4gMHhmZmZmID8gMiA6IDE7CiAgbGV0IGNtYXAgPSAiXHgwMFx4MDAiICsgc3RyaW5nMTYobnVtVGFibGVzKSArICJceDAwXHgwMyIgKyAiXHgwMFx4MDEiICsgc3RyaW5nMzIoNCArIG51bVRhYmxlcyAqIDgpOwogIGxldCBpLCBpaSwgaiwgamo7CiAgZm9yIChpID0gcmFuZ2VzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICBpZiAocmFuZ2VzW2ldWzBdIDw9IDB4ZmZmZikgewogICAgICBicmVhazsKICAgIH0KICB9CiAgY29uc3QgYm1wTGVuZ3RoID0gaSArIDE7CiAgaWYgKHJhbmdlc1tpXVswXSA8IDB4ZmZmZiAmJiByYW5nZXNbaV1bMV0gPT09IDB4ZmZmZikgewogICAgcmFuZ2VzW2ldWzFdID0gMHhmZmZlOwogIH0KICBjb25zdCB0cmFpbGluZ1Jhbmdlc0NvdW50ID0gcmFuZ2VzW2ldWzFdIDwgMHhmZmZmID8gMSA6IDA7CiAgY29uc3Qgc2VnQ291bnQgPSBibXBMZW5ndGggKyB0cmFpbGluZ1Jhbmdlc0NvdW50OwogIGNvbnN0IHNlYXJjaFBhcmFtcyA9IE9wZW5UeXBlRmlsZUJ1aWxkZXIuZ2V0U2VhcmNoUGFyYW1zKHNlZ0NvdW50LCAyKTsKICBsZXQgc3RhcnRDb3VudCA9ICIiOwogIGxldCBlbmRDb3VudCA9ICIiOwogIGxldCBpZERlbHRhcyA9ICIiOwogIGxldCBpZFJhbmdlT2Zmc2V0cyA9ICIiOwogIGxldCBnbHlwaHNJZHMgPSAiIjsKICBsZXQgYmlhcyA9IDA7CiAgbGV0IHJhbmdlLCBzdGFydCwgZW5kLCBjb2RlczsKICBmb3IgKGkgPSAwLCBpaSA9IGJtcExlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIHJhbmdlID0gcmFuZ2VzW2ldOwogICAgc3RhcnQgPSByYW5nZVswXTsKICAgIGVuZCA9IHJhbmdlWzFdOwogICAgc3RhcnRDb3VudCArPSBzdHJpbmcxNihzdGFydCk7CiAgICBlbmRDb3VudCArPSBzdHJpbmcxNihlbmQpOwogICAgY29kZXMgPSByYW5nZVsyXTsKICAgIGxldCBjb250aWd1b3VzID0gdHJ1ZTsKICAgIGZvciAoaiA9IDEsIGpqID0gY29kZXMubGVuZ3RoOyBqIDwgamo7ICsraikgewogICAgICBpZiAoY29kZXNbal0gIT09IGNvZGVzW2ogLSAxXSArIDEpIHsKICAgICAgICBjb250aWd1b3VzID0gZmFsc2U7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGlmICghY29udGlndW91cykgewogICAgICBjb25zdCBvZmZzZXQgPSAoc2VnQ291bnQgLSBpKSAqIDIgKyBiaWFzICogMjsKICAgICAgYmlhcyArPSBlbmQgLSBzdGFydCArIDE7CiAgICAgIGlkRGVsdGFzICs9IHN0cmluZzE2KDApOwogICAgICBpZFJhbmdlT2Zmc2V0cyArPSBzdHJpbmcxNihvZmZzZXQpOwogICAgICBmb3IgKGogPSAwLCBqaiA9IGNvZGVzLmxlbmd0aDsgaiA8IGpqOyArK2opIHsKICAgICAgICBnbHlwaHNJZHMgKz0gc3RyaW5nMTYoY29kZXNbal0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBzdGFydENvZGUgPSBjb2Rlc1swXTsKICAgICAgaWREZWx0YXMgKz0gc3RyaW5nMTYoc3RhcnRDb2RlIC0gc3RhcnQgJiAweGZmZmYpOwogICAgICBpZFJhbmdlT2Zmc2V0cyArPSBzdHJpbmcxNigwKTsKICAgIH0KICB9CiAgaWYgKHRyYWlsaW5nUmFuZ2VzQ291bnQgPiAwKSB7CiAgICBlbmRDb3VudCArPSAiXHhGRlx4RkYiOwogICAgc3RhcnRDb3VudCArPSAiXHhGRlx4RkYiOwogICAgaWREZWx0YXMgKz0gIlx4MDBceDAxIjsKICAgIGlkUmFuZ2VPZmZzZXRzICs9ICJceDAwXHgwMCI7CiAgfQogIGNvbnN0IGZvcm1hdDMxNCA9ICJceDAwXHgwMCIgKyBzdHJpbmcxNigyICogc2VnQ291bnQpICsgc3RyaW5nMTYoc2VhcmNoUGFyYW1zLnJhbmdlKSArIHN0cmluZzE2KHNlYXJjaFBhcmFtcy5lbnRyeSkgKyBzdHJpbmcxNihzZWFyY2hQYXJhbXMucmFuZ2VTaGlmdCkgKyBlbmRDb3VudCArICJceDAwXHgwMCIgKyBzdGFydENvdW50ICsgaWREZWx0YXMgKyBpZFJhbmdlT2Zmc2V0cyArIGdseXBoc0lkczsKICBsZXQgZm9ybWF0MzEwMTIgPSAiIjsKICBsZXQgaGVhZGVyMzEwMTIgPSAiIjsKICBpZiAobnVtVGFibGVzID4gMSkgewogICAgY21hcCArPSAiXHgwMFx4MDMiICsgIlx4MDBceDBBIiArIHN0cmluZzMyKDQgKyBudW1UYWJsZXMgKiA4ICsgNCArIGZvcm1hdDMxNC5sZW5ndGgpOwogICAgZm9ybWF0MzEwMTIgPSAiIjsKICAgIGZvciAoaSA9IDAsIGlpID0gcmFuZ2VzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgcmFuZ2UgPSByYW5nZXNbaV07CiAgICAgIHN0YXJ0ID0gcmFuZ2VbMF07CiAgICAgIGNvZGVzID0gcmFuZ2VbMl07CiAgICAgIGxldCBjb2RlID0gY29kZXNbMF07CiAgICAgIGZvciAoaiA9IDEsIGpqID0gY29kZXMubGVuZ3RoOyBqIDwgamo7ICsraikgewogICAgICAgIGlmIChjb2Rlc1tqXSAhPT0gY29kZXNbaiAtIDFdICsgMSkgewogICAgICAgICAgZW5kID0gcmFuZ2VbMF0gKyBqIC0gMTsKICAgICAgICAgIGZvcm1hdDMxMDEyICs9IHN0cmluZzMyKHN0YXJ0KSArIHN0cmluZzMyKGVuZCkgKyBzdHJpbmczMihjb2RlKTsKICAgICAgICAgIHN0YXJ0ID0gZW5kICsgMTsKICAgICAgICAgIGNvZGUgPSBjb2Rlc1tqXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgZm9ybWF0MzEwMTIgKz0gc3RyaW5nMzIoc3RhcnQpICsgc3RyaW5nMzIocmFuZ2VbMV0pICsgc3RyaW5nMzIoY29kZSk7CiAgICB9CiAgICBoZWFkZXIzMTAxMiA9ICJceDAwXHgwQyIgKyAiXHgwMFx4MDAiICsgc3RyaW5nMzIoZm9ybWF0MzEwMTIubGVuZ3RoICsgMTYpICsgIlx4MDBceDAwXHgwMFx4MDAiICsgc3RyaW5nMzIoZm9ybWF0MzEwMTIubGVuZ3RoIC8gMTIpOwogIH0KICByZXR1cm4gY21hcCArICJceDAwXHgwNCIgKyBzdHJpbmcxNihmb3JtYXQzMTQubGVuZ3RoICsgNCkgKyBmb3JtYXQzMTQgKyBoZWFkZXIzMTAxMiArIGZvcm1hdDMxMDEyOwp9CmZ1bmN0aW9uIHZhbGlkYXRlT1MyVGFibGUob3MyLCBmaWxlKSB7CiAgZmlsZS5wb3MgPSAoZmlsZS5zdGFydCB8fCAwKSArIG9zMi5vZmZzZXQ7CiAgY29uc3QgdmVyc2lvbiA9IGZpbGUuZ2V0VWludDE2KCk7CiAgZmlsZS5za2lwKDYwKTsKICBjb25zdCBzZWxlY3Rpb24gPSBmaWxlLmdldFVpbnQxNigpOwogIGlmICh2ZXJzaW9uIDwgNCAmJiBzZWxlY3Rpb24gJiAweDAzMDApIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgY29uc3QgZmlyc3RDaGFyID0gZmlsZS5nZXRVaW50MTYoKTsKICBjb25zdCBsYXN0Q2hhciA9IGZpbGUuZ2V0VWludDE2KCk7CiAgaWYgKGZpcnN0Q2hhciA+IGxhc3RDaGFyKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGZpbGUuc2tpcCg2KTsKICBjb25zdCB1c1dpbkFzY2VudCA9IGZpbGUuZ2V0VWludDE2KCk7CiAgaWYgKHVzV2luQXNjZW50ID09PSAwKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIG9zMi5kYXRhWzhdID0gb3MyLmRhdGFbOV0gPSAwOwogIHJldHVybiB0cnVlOwp9CmZ1bmN0aW9uIGNyZWF0ZU9TMlRhYmxlKHByb3BlcnRpZXMsIGNoYXJzdHJpbmdzLCBvdmVycmlkZSkgewogIG92ZXJyaWRlIHx8PSB7CiAgICB1bml0c1BlckVtOiAwLAogICAgeU1heDogMCwKICAgIHlNaW46IDAsCiAgICBhc2NlbnQ6IDAsCiAgICBkZXNjZW50OiAwCiAgfTsKICBsZXQgdWxVbmljb2RlUmFuZ2UxID0gMDsKICBsZXQgdWxVbmljb2RlUmFuZ2UyID0gMDsKICBsZXQgdWxVbmljb2RlUmFuZ2UzID0gMDsKICBsZXQgdWxVbmljb2RlUmFuZ2U0ID0gMDsKICBsZXQgZmlyc3RDaGFySW5kZXggPSBudWxsOwogIGxldCBsYXN0Q2hhckluZGV4ID0gMDsKICBsZXQgcG9zaXRpb24gPSAtMTsKICBpZiAoY2hhcnN0cmluZ3MpIHsKICAgIGZvciAobGV0IGNvZGUgaW4gY2hhcnN0cmluZ3MpIHsKICAgICAgY29kZSB8PSAwOwogICAgICBpZiAoZmlyc3RDaGFySW5kZXggPiBjb2RlIHx8ICFmaXJzdENoYXJJbmRleCkgewogICAgICAgIGZpcnN0Q2hhckluZGV4ID0gY29kZTsKICAgICAgfQogICAgICBpZiAobGFzdENoYXJJbmRleCA8IGNvZGUpIHsKICAgICAgICBsYXN0Q2hhckluZGV4ID0gY29kZTsKICAgICAgfQogICAgICBwb3NpdGlvbiA9IGdldFVuaWNvZGVSYW5nZUZvcihjb2RlLCBwb3NpdGlvbik7CiAgICAgIGlmIChwb3NpdGlvbiA8IDMyKSB7CiAgICAgICAgdWxVbmljb2RlUmFuZ2UxIHw9IDEgPDwgcG9zaXRpb247CiAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPCA2NCkgewogICAgICAgIHVsVW5pY29kZVJhbmdlMiB8PSAxIDw8IHBvc2l0aW9uIC0gMzI7CiAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPCA5NikgewogICAgICAgIHVsVW5pY29kZVJhbmdlMyB8PSAxIDw8IHBvc2l0aW9uIC0gNjQ7CiAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPCAxMjMpIHsKICAgICAgICB1bFVuaWNvZGVSYW5nZTQgfD0gMSA8PCBwb3NpdGlvbiAtIDk2OwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiVW5pY29kZSByYW5nZXMgQml0cyA+IDEyMyBhcmUgcmVzZXJ2ZWQgZm9yIGludGVybmFsIHVzYWdlIik7CiAgICAgIH0KICAgIH0KICAgIGlmIChsYXN0Q2hhckluZGV4ID4gMHhmZmZmKSB7CiAgICAgIGxhc3RDaGFySW5kZXggPSAweGZmZmY7CiAgICB9CiAgfSBlbHNlIHsKICAgIGZpcnN0Q2hhckluZGV4ID0gMDsKICAgIGxhc3RDaGFySW5kZXggPSAyNTU7CiAgfQogIGNvbnN0IGJib3ggPSBwcm9wZXJ0aWVzLmJib3ggfHwgWzAsIDAsIDAsIDBdOwogIGNvbnN0IHVuaXRzUGVyRW0gPSBvdmVycmlkZS51bml0c1BlckVtIHx8IChwcm9wZXJ0aWVzLmZvbnRNYXRyaXggPyAxIC8gTWF0aC5tYXgoLi4ucHJvcGVydGllcy5mb250TWF0cml4LnNsaWNlKDAsIDQpLm1hcChNYXRoLmFicykpIDogMTAwMCk7CiAgY29uc3Qgc2NhbGUgPSBwcm9wZXJ0aWVzLmFzY2VudFNjYWxlZCA/IDEuMCA6IHVuaXRzUGVyRW0gLyBQREZfR0xZUEhfU1BBQ0VfVU5JVFM7CiAgY29uc3QgdHlwb0FzY2VudCA9IG92ZXJyaWRlLmFzY2VudCB8fCBNYXRoLnJvdW5kKHNjYWxlICogKHByb3BlcnRpZXMuYXNjZW50IHx8IGJib3hbM10pKTsKICBsZXQgdHlwb0Rlc2NlbnQgPSBvdmVycmlkZS5kZXNjZW50IHx8IE1hdGgucm91bmQoc2NhbGUgKiAocHJvcGVydGllcy5kZXNjZW50IHx8IGJib3hbMV0pKTsKICBpZiAodHlwb0Rlc2NlbnQgPiAwICYmIHByb3BlcnRpZXMuZGVzY2VudCA+IDAgJiYgYmJveFsxXSA8IDApIHsKICAgIHR5cG9EZXNjZW50ID0gLXR5cG9EZXNjZW50OwogIH0KICBjb25zdCB3aW5Bc2NlbnQgPSBvdmVycmlkZS55TWF4IHx8IHR5cG9Bc2NlbnQ7CiAgY29uc3Qgd2luRGVzY2VudCA9IC1vdmVycmlkZS55TWluIHx8IC10eXBvRGVzY2VudDsKICByZXR1cm4gIlx4MDBceDAzIiArICJceDAyXHgyNCIgKyAiXHgwMVx4RjQiICsgIlx4MDBceDA1IiArICJceDAwXHgwMCIgKyAiXHgwMlx4OEEiICsgIlx4MDJceEJCIiArICJceDAwXHgwMCIgKyAiXHgwMFx4OEMiICsgIlx4MDJceDhBIiArICJceDAyXHhCQiIgKyAiXHgwMFx4MDAiICsgIlx4MDFceERGIiArICJceDAwXHgzMSIgKyAiXHgwMVx4MDIiICsgIlx4MDBceDAwIiArICJceDAwXHgwMFx4MDYiICsgU3RyaW5nLmZyb21DaGFyQ29kZShwcm9wZXJ0aWVzLmZpeGVkUGl0Y2ggPyAweDA5IDogMHgwMCkgKyAiXHgwMFx4MDBceDAwXHgwMFx4MDBceDAwIiArIHN0cmluZzMyKHVsVW5pY29kZVJhbmdlMSkgKyBzdHJpbmczMih1bFVuaWNvZGVSYW5nZTIpICsgc3RyaW5nMzIodWxVbmljb2RlUmFuZ2UzKSArIHN0cmluZzMyKHVsVW5pY29kZVJhbmdlNCkgKyAiXHgyQVx4MzJceDMxXHgyQSIgKyBzdHJpbmcxNihwcm9wZXJ0aWVzLml0YWxpY0FuZ2xlID8gMSA6IDApICsgc3RyaW5nMTYoZmlyc3RDaGFySW5kZXggfHwgcHJvcGVydGllcy5maXJzdENoYXIpICsgc3RyaW5nMTYobGFzdENoYXJJbmRleCB8fCBwcm9wZXJ0aWVzLmxhc3RDaGFyKSArIHN0cmluZzE2KHR5cG9Bc2NlbnQpICsgc3RyaW5nMTYodHlwb0Rlc2NlbnQpICsgIlx4MDBceDY0IiArIHN0cmluZzE2KHdpbkFzY2VudCkgKyBzdHJpbmcxNih3aW5EZXNjZW50KSArICJceDAwXHgwMFx4MDBceDAwIiArICJceDAwXHgwMFx4MDBceDAwIiArIHN0cmluZzE2KHByb3BlcnRpZXMueEhlaWdodCkgKyBzdHJpbmcxNihwcm9wZXJ0aWVzLmNhcEhlaWdodCkgKyBzdHJpbmcxNigwKSArIHN0cmluZzE2KGZpcnN0Q2hhckluZGV4IHx8IHByb3BlcnRpZXMuZmlyc3RDaGFyKSArICJceDAwXHgwMyI7Cn0KZnVuY3Rpb24gY3JlYXRlUG9zdFRhYmxlKHByb3BlcnRpZXMpIHsKICBjb25zdCBhbmdsZSA9IE1hdGguZmxvb3IocHJvcGVydGllcy5pdGFsaWNBbmdsZSAqIDIgKiogMTYpOwogIHJldHVybiAiXHgwMFx4MDNceDAwXHgwMCIgKyBzdHJpbmczMihhbmdsZSkgKyAiXHgwMFx4MDAiICsgIlx4MDBceDAwIiArIHN0cmluZzMyKHByb3BlcnRpZXMuZml4ZWRQaXRjaCA/IDEgOiAwKSArICJceDAwXHgwMFx4MDBceDAwIiArICJceDAwXHgwMFx4MDBceDAwIiArICJceDAwXHgwMFx4MDBceDAwIiArICJceDAwXHgwMFx4MDBceDAwIjsKfQpmdW5jdGlvbiBjcmVhdGVQb3N0c2NyaXB0TmFtZShuYW1lKSB7CiAgcmV0dXJuIG5hbWUucmVwbGFjZUFsbCgvW15ceDIxLVx4N0VdfFtbXF0oKXt9PD4vJV0vZywgIiIpLnNsaWNlKDAsIDYzKTsKfQpmdW5jdGlvbiBjcmVhdGVOYW1lVGFibGUobmFtZSwgcHJvdG8pIHsKICBpZiAoIXByb3RvKSB7CiAgICBwcm90byA9IFtbXSwgW11dOwogIH0KICBjb25zdCBzdHJpbmdzID0gW3Byb3RvWzBdWzBdIHx8ICJPcmlnaW5hbCBsaWNlbmNlIiwgcHJvdG9bMF1bMV0gfHwgbmFtZSwgcHJvdG9bMF1bMl0gfHwgIlVua25vd24iLCBwcm90b1swXVszXSB8fCAidW5pcXVlSUQiLCBwcm90b1swXVs0XSB8fCBuYW1lLCBwcm90b1swXVs1XSB8fCAiVmVyc2lvbiAwLjExIiwgcHJvdG9bMF1bNl0gfHwgY3JlYXRlUG9zdHNjcmlwdE5hbWUobmFtZSksIHByb3RvWzBdWzddIHx8ICJVbmtub3duIiwgcHJvdG9bMF1bOF0gfHwgIlVua25vd24iLCBwcm90b1swXVs5XSB8fCAiVW5rbm93biJdOwogIGNvbnN0IHN0cmluZ3NVbmljb2RlID0gW107CiAgbGV0IGksIGlpLCBqLCBqaiwgc3RyOwogIGZvciAoaSA9IDAsIGlpID0gc3RyaW5ncy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBzdHIgPSBwcm90b1sxXVtpXSB8fCBzdHJpbmdzW2ldOwogICAgY29uc3Qgc3RyQnVmVW5pY29kZSA9IFtdOwogICAgZm9yIChqID0gMCwgamogPSBzdHIubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICBzdHJCdWZVbmljb2RlLnB1c2goc3RyaW5nMTYoc3RyLmNoYXJDb2RlQXQoaikpKTsKICAgIH0KICAgIHN0cmluZ3NVbmljb2RlLnB1c2goc3RyQnVmVW5pY29kZS5qb2luKCIiKSk7CiAgfQogIGNvbnN0IG5hbWVzID0gW3N0cmluZ3MsIHN0cmluZ3NVbmljb2RlXTsKICBjb25zdCBwbGF0Zm9ybXMgPSBbIlx4MDBceDAxIiwgIlx4MDBceDAzIl07CiAgY29uc3QgZW5jb2RpbmdzID0gWyJceDAwXHgwMCIsICJceDAwXHgwMSJdOwogIGNvbnN0IGxhbmd1YWdlcyA9IFsiXHgwMFx4MDAiLCAiXHgwNFx4MDkiXTsKICBjb25zdCBuYW1lc1JlY29yZENvdW50ID0gc3RyaW5ncy5sZW5ndGggKiBwbGF0Zm9ybXMubGVuZ3RoOwogIGxldCBuYW1lVGFibGUgPSAiXHgwMFx4MDAiICsgc3RyaW5nMTYobmFtZXNSZWNvcmRDb3VudCkgKyBzdHJpbmcxNihuYW1lc1JlY29yZENvdW50ICogMTIgKyA2KTsKICBsZXQgc3RyT2Zmc2V0ID0gMDsKICBmb3IgKGkgPSAwLCBpaSA9IHBsYXRmb3Jtcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCBzdHJzID0gbmFtZXNbaV07CiAgICBmb3IgKGogPSAwLCBqaiA9IHN0cnMubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICBzdHIgPSBzdHJzW2pdOwogICAgICBjb25zdCBuYW1lUmVjb3JkID0gcGxhdGZvcm1zW2ldICsgZW5jb2RpbmdzW2ldICsgbGFuZ3VhZ2VzW2ldICsgc3RyaW5nMTYoaikgKyBzdHJpbmcxNihzdHIubGVuZ3RoKSArIHN0cmluZzE2KHN0ck9mZnNldCk7CiAgICAgIG5hbWVUYWJsZSArPSBuYW1lUmVjb3JkOwogICAgICBzdHJPZmZzZXQgKz0gc3RyLmxlbmd0aDsKICAgIH0KICB9CiAgbmFtZVRhYmxlICs9IHN0cmluZ3Muam9pbigiIikgKyBzdHJpbmdzVW5pY29kZS5qb2luKCIiKTsKICByZXR1cm4gbmFtZVRhYmxlOwp9CmNsYXNzIEZvbnQgewogIGNvbnN0cnVjdG9yKG5hbWUsIGZpbGUsIHByb3BlcnRpZXMsIGV2YWx1YXRvck9wdGlvbnMpIHsKICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICB0aGlzLnBzTmFtZSA9IG51bGw7CiAgICB0aGlzLm1pbWV0eXBlID0gbnVsbDsKICAgIHRoaXMuZGlzYWJsZUZvbnRGYWNlID0gZXZhbHVhdG9yT3B0aW9ucy5kaXNhYmxlRm9udEZhY2U7CiAgICB0aGlzLmZvbnRFeHRyYVByb3BlcnRpZXMgPSBldmFsdWF0b3JPcHRpb25zLmZvbnRFeHRyYVByb3BlcnRpZXM7CiAgICB0aGlzLmxvYWRlZE5hbWUgPSBwcm9wZXJ0aWVzLmxvYWRlZE5hbWU7CiAgICB0aGlzLmlzVHlwZTNGb250ID0gcHJvcGVydGllcy5pc1R5cGUzRm9udDsKICAgIHRoaXMubWlzc2luZ0ZpbGUgPSBmYWxzZTsKICAgIHRoaXMuY3NzRm9udEluZm8gPSBwcm9wZXJ0aWVzLmNzc0ZvbnRJbmZvOwogICAgdGhpcy5fY2hhcnNDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB0aGlzLl9nbHlwaENhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGxldCBpc1NlcmlmRm9udCA9ICEhKHByb3BlcnRpZXMuZmxhZ3MgJiBGb250RmxhZ3MuU2VyaWYpOwogICAgaWYgKCFpc1NlcmlmRm9udCAmJiAhcHJvcGVydGllcy5pc1NpbXVsYXRlZEZsYWdzKSB7CiAgICAgIGNvbnN0IHN0ZEZvbnRNYXAgPSBnZXRTdGRGb250TWFwKCksCiAgICAgICAgbm9uU3RkRm9udE1hcCA9IGdldE5vblN0ZEZvbnRNYXAoKSwKICAgICAgICBzZXJpZkZvbnRzID0gZ2V0U2VyaWZGb250cygpOwogICAgICBmb3IgKGNvbnN0IG5hbWVQYXJ0IG9mIG5hbWUuc3BsaXQoIisiKSkgewogICAgICAgIGxldCBmb250TmFtZSA9IG5hbWVQYXJ0LnJlcGxhY2VBbGwoL1ssX10vZywgIi0iKTsKICAgICAgICBmb250TmFtZSA9IHN0ZEZvbnRNYXBbZm9udE5hbWVdIHx8IG5vblN0ZEZvbnRNYXBbZm9udE5hbWVdIHx8IGZvbnROYW1lOwogICAgICAgIGZvbnROYW1lID0gZm9udE5hbWUuc3BsaXQoIi0iLCAxKVswXTsKICAgICAgICBpZiAoc2VyaWZGb250c1tmb250TmFtZV0pIHsKICAgICAgICAgIGlzU2VyaWZGb250ID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgdGhpcy5pc1NlcmlmRm9udCA9IGlzU2VyaWZGb250OwogICAgdGhpcy5pc1N5bWJvbGljRm9udCA9ICEhKHByb3BlcnRpZXMuZmxhZ3MgJiBGb250RmxhZ3MuU3ltYm9saWMpOwogICAgdGhpcy5pc01vbm9zcGFjZSA9ICEhKHByb3BlcnRpZXMuZmxhZ3MgJiBGb250RmxhZ3MuRml4ZWRQaXRjaCk7CiAgICBsZXQgewogICAgICB0eXBlLAogICAgICBzdWJ0eXBlCiAgICB9ID0gcHJvcGVydGllczsKICAgIHRoaXMudHlwZSA9IHR5cGU7CiAgICB0aGlzLnN1YnR5cGUgPSBzdWJ0eXBlOwogICAgdGhpcy5zeXN0ZW1Gb250SW5mbyA9IHByb3BlcnRpZXMuc3lzdGVtRm9udEluZm87CiAgICBjb25zdCBtYXRjaGVzID0gbmFtZS5tYXRjaCgvXkludmFsaWRQREZqc0ZvbnRfKC4qKV9cZCskLyk7CiAgICB0aGlzLmlzSW52YWxpZFBERmpzRm9udCA9ICEhbWF0Y2hlczsKICAgIGlmICh0aGlzLmlzSW52YWxpZFBERmpzRm9udCkgewogICAgICB0aGlzLmZhbGxiYWNrTmFtZSA9IG1hdGNoZXNbMV07CiAgICB9IGVsc2UgaWYgKHRoaXMuaXNNb25vc3BhY2UpIHsKICAgICAgdGhpcy5mYWxsYmFja05hbWUgPSAibW9ub3NwYWNlIjsKICAgIH0gZWxzZSBpZiAodGhpcy5pc1NlcmlmRm9udCkgewogICAgICB0aGlzLmZhbGxiYWNrTmFtZSA9ICJzZXJpZiI7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmZhbGxiYWNrTmFtZSA9ICJzYW5zLXNlcmlmIjsKICAgIH0KICAgIGlmICh0aGlzLnN5c3RlbUZvbnRJbmZvPy5ndWVzc0ZhbGxiYWNrKSB7CiAgICAgIHRoaXMuc3lzdGVtRm9udEluZm8uZ3Vlc3NGYWxsYmFjayA9IGZhbHNlOwogICAgICB0aGlzLnN5c3RlbUZvbnRJbmZvLmNzcyArPSBgLCR7dGhpcy5mYWxsYmFja05hbWV9YDsKICAgIH0KICAgIHRoaXMuZGlmZmVyZW5jZXMgPSBwcm9wZXJ0aWVzLmRpZmZlcmVuY2VzOwogICAgdGhpcy53aWR0aHMgPSBwcm9wZXJ0aWVzLndpZHRoczsKICAgIHRoaXMuZGVmYXVsdFdpZHRoID0gcHJvcGVydGllcy5kZWZhdWx0V2lkdGg7CiAgICB0aGlzLmNvbXBvc2l0ZSA9IHByb3BlcnRpZXMuY29tcG9zaXRlOwogICAgdGhpcy5jTWFwID0gcHJvcGVydGllcy5jTWFwOwogICAgdGhpcy5jYXBIZWlnaHQgPSBwcm9wZXJ0aWVzLmNhcEhlaWdodCAvIFBERl9HTFlQSF9TUEFDRV9VTklUUzsKICAgIHRoaXMuYXNjZW50ID0gcHJvcGVydGllcy5hc2NlbnQgLyBQREZfR0xZUEhfU1BBQ0VfVU5JVFM7CiAgICB0aGlzLmRlc2NlbnQgPSBwcm9wZXJ0aWVzLmRlc2NlbnQgLyBQREZfR0xZUEhfU1BBQ0VfVU5JVFM7CiAgICB0aGlzLmxpbmVIZWlnaHQgPSB0aGlzLmFzY2VudCAtIHRoaXMuZGVzY2VudDsKICAgIHRoaXMuZm9udE1hdHJpeCA9IHByb3BlcnRpZXMuZm9udE1hdHJpeDsKICAgIHRoaXMuYmJveCA9IHByb3BlcnRpZXMuYmJveDsKICAgIHRoaXMuZGVmYXVsdEVuY29kaW5nID0gcHJvcGVydGllcy5kZWZhdWx0RW5jb2Rpbmc7CiAgICB0aGlzLnRvVW5pY29kZSA9IHByb3BlcnRpZXMudG9Vbmljb2RlOwogICAgdGhpcy50b0ZvbnRDaGFyID0gW107CiAgICBpZiAocHJvcGVydGllcy50eXBlID09PSAiVHlwZTMiKSB7CiAgICAgIGZvciAobGV0IGNoYXJDb2RlID0gMDsgY2hhckNvZGUgPCAyNTY7IGNoYXJDb2RlKyspIHsKICAgICAgICB0aGlzLnRvRm9udENoYXJbY2hhckNvZGVdID0gdGhpcy5kaWZmZXJlbmNlc1tjaGFyQ29kZV0gfHwgcHJvcGVydGllcy5kZWZhdWx0RW5jb2RpbmdbY2hhckNvZGVdOwogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuY2lkRW5jb2RpbmcgPSBwcm9wZXJ0aWVzLmNpZEVuY29kaW5nIHx8ICIiOwogICAgdGhpcy52ZXJ0aWNhbCA9ICEhcHJvcGVydGllcy52ZXJ0aWNhbDsKICAgIGlmICh0aGlzLnZlcnRpY2FsKSB7CiAgICAgIHRoaXMudm1ldHJpY3MgPSBwcm9wZXJ0aWVzLnZtZXRyaWNzOwogICAgICB0aGlzLmRlZmF1bHRWTWV0cmljcyA9IHByb3BlcnRpZXMuZGVmYXVsdFZNZXRyaWNzOwogICAgfQogICAgaWYgKCFmaWxlIHx8IGZpbGUuaXNFbXB0eSkgewogICAgICBpZiAoZmlsZSkgewogICAgICAgIHdhcm4oJ0ZvbnQgZmlsZSBpcyBlbXB0eSBpbiAiJyArIG5hbWUgKyAnIiAoJyArIHRoaXMubG9hZGVkTmFtZSArICIpIik7CiAgICAgIH0KICAgICAgdGhpcy5mYWxsYmFja1RvU3lzdGVtRm9udChwcm9wZXJ0aWVzKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgW3R5cGUsIHN1YnR5cGVdID0gZ2V0Rm9udEZpbGVUeXBlKGZpbGUsIHByb3BlcnRpZXMpOwogICAgaWYgKHR5cGUgIT09IHRoaXMudHlwZSB8fCBzdWJ0eXBlICE9PSB0aGlzLnN1YnR5cGUpIHsKICAgICAgaW5mbygiSW5jb25zaXN0ZW50IGZvbnQgZmlsZSBUeXBlL1N1YlR5cGUsIGV4cGVjdGVkOiAiICsgYCR7dGhpcy50eXBlfS8ke3RoaXMuc3VidHlwZX0gYnV0IGZvdW5kOiAke3R5cGV9LyR7c3VidHlwZX0uYCk7CiAgICB9CiAgICBsZXQgZGF0YTsKICAgIHRyeSB7CiAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgIGNhc2UgIk1NVHlwZTEiOgogICAgICAgICAgaW5mbygiTU1UeXBlMSBmb250ICgiICsgbmFtZSArICIpLCBmYWxsaW5nIGJhY2sgdG8gVHlwZTEuIik7CiAgICAgICAgY2FzZSAiVHlwZTEiOgogICAgICAgIGNhc2UgIkNJREZvbnRUeXBlMCI6CiAgICAgICAgICB0aGlzLm1pbWV0eXBlID0gImZvbnQvb3BlbnR5cGUiOwogICAgICAgICAgY29uc3QgY2ZmID0gc3VidHlwZSA9PT0gIlR5cGUxQyIgfHwgc3VidHlwZSA9PT0gIkNJREZvbnRUeXBlMEMiID8gbmV3IENGRkZvbnQoZmlsZSwgcHJvcGVydGllcykgOiBuZXcgVHlwZTFGb250KG5hbWUsIGZpbGUsIHByb3BlcnRpZXMpOwogICAgICAgICAgYWRqdXN0V2lkdGhzKHByb3BlcnRpZXMpOwogICAgICAgICAgZGF0YSA9IHRoaXMuY29udmVydChuYW1lLCBjZmYsIHByb3BlcnRpZXMpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiT3BlblR5cGUiOgogICAgICAgIGNhc2UgIlRydWVUeXBlIjoKICAgICAgICBjYXNlICJDSURGb250VHlwZTIiOgogICAgICAgICAgdGhpcy5taW1ldHlwZSA9ICJmb250L29wZW50eXBlIjsKICAgICAgICAgIGRhdGEgPSB0aGlzLmNoZWNrQW5kUmVwYWlyKG5hbWUsIGZpbGUsIHByb3BlcnRpZXMpOwogICAgICAgICAgYWRqdXN0V2lkdGhzKHByb3BlcnRpZXMpOwogICAgICAgICAgaWYgKHRoaXMuaXNPcGVuVHlwZSkgewogICAgICAgICAgICB0eXBlID0gIk9wZW5UeXBlIjsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEZvbnQgJHt0eXBlfSBpcyBub3Qgc3VwcG9ydGVkYCk7CiAgICAgIH0KICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgd2FybihlKTsKICAgICAgdGhpcy5mYWxsYmFja1RvU3lzdGVtRm9udChwcm9wZXJ0aWVzKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgYW1lbmRGYWxsYmFja1RvVW5pY29kZShwcm9wZXJ0aWVzKTsKICAgIHRoaXMuZGF0YSA9IGRhdGE7CiAgICB0aGlzLnR5cGUgPSB0eXBlOwogICAgdGhpcy5zdWJ0eXBlID0gc3VidHlwZTsKICAgIHRoaXMuZm9udE1hdHJpeCA9IHByb3BlcnRpZXMuZm9udE1hdHJpeDsKICAgIHRoaXMud2lkdGhzID0gcHJvcGVydGllcy53aWR0aHM7CiAgICB0aGlzLmRlZmF1bHRXaWR0aCA9IHByb3BlcnRpZXMuZGVmYXVsdFdpZHRoOwogICAgdGhpcy50b1VuaWNvZGUgPSBwcm9wZXJ0aWVzLnRvVW5pY29kZTsKICAgIHRoaXMuc2VhY01hcCA9IHByb3BlcnRpZXMuc2VhY01hcDsKICB9CiAgZ2V0IHJlbmRlcmVyKCkgewogICAgY29uc3QgcmVuZGVyZXIgPSBGb250UmVuZGVyZXJGYWN0b3J5LmNyZWF0ZSh0aGlzLCBTRUFDX0FOQUxZU0lTX0VOQUJMRUQpOwogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAicmVuZGVyZXIiLCByZW5kZXJlcik7CiAgfQogIGV4cG9ydERhdGEoKSB7CiAgICBjb25zdCBkYXRhID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGZvciAoY29uc3QgcHJvcCBvZiBFWFBPUlRfREFUQV9QUk9QRVJUSUVTKSB7CiAgICAgIGNvbnN0IHZhbHVlID0gdGhpc1twcm9wXTsKICAgICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBkYXRhW3Byb3BdID0gdmFsdWU7CiAgICAgIH0KICAgIH0KICAgIGlmICghdGhpcy5mb250RXh0cmFQcm9wZXJ0aWVzKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgZGF0YQogICAgICB9OwogICAgfQogICAgY29uc3QgZXh0cmEgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgZm9yIChjb25zdCBwcm9wIG9mIEVYUE9SVF9EQVRBX0VYVFJBX1BST1BFUlRJRVMpIHsKICAgICAgY29uc3QgdmFsdWUgPSB0aGlzW3Byb3BdOwogICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGV4dHJhW3Byb3BdID0gdmFsdWU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7CiAgICAgIGRhdGEsCiAgICAgIGV4dHJhCiAgICB9OwogIH0KICBmYWxsYmFja1RvU3lzdGVtRm9udChwcm9wZXJ0aWVzKSB7CiAgICB0aGlzLm1pc3NpbmdGaWxlID0gdHJ1ZTsKICAgIGNvbnN0IHsKICAgICAgbmFtZSwKICAgICAgdHlwZQogICAgfSA9IHRoaXM7CiAgICBsZXQgZm9udE5hbWUgPSBub3JtYWxpemVGb250TmFtZShuYW1lKTsKICAgIGNvbnN0IHN0ZEZvbnRNYXAgPSBnZXRTdGRGb250TWFwKCksCiAgICAgIG5vblN0ZEZvbnRNYXAgPSBnZXROb25TdGRGb250TWFwKCk7CiAgICBjb25zdCBpc1N0YW5kYXJkRm9udCA9ICEhc3RkRm9udE1hcFtmb250TmFtZV07CiAgICBjb25zdCBpc01hcHBlZFRvU3RhbmRhcmRGb250ID0gISEobm9uU3RkRm9udE1hcFtmb250TmFtZV0gJiYgc3RkRm9udE1hcFtub25TdGRGb250TWFwW2ZvbnROYW1lXV0pOwogICAgZm9udE5hbWUgPSBzdGRGb250TWFwW2ZvbnROYW1lXSB8fCBub25TdGRGb250TWFwW2ZvbnROYW1lXSB8fCBmb250TmFtZTsKICAgIGNvbnN0IGZvbnRCYXNpY01ldHJpY3NNYXAgPSBnZXRGb250QmFzaWNNZXRyaWNzKCk7CiAgICBjb25zdCBtZXRyaWNzID0gZm9udEJhc2ljTWV0cmljc01hcFtmb250TmFtZV07CiAgICBpZiAobWV0cmljcykgewogICAgICBpZiAoaXNOYU4odGhpcy5hc2NlbnQpKSB7CiAgICAgICAgdGhpcy5hc2NlbnQgPSBtZXRyaWNzLmFzY2VudCAvIFBERl9HTFlQSF9TUEFDRV9VTklUUzsKICAgICAgfQogICAgICBpZiAoaXNOYU4odGhpcy5kZXNjZW50KSkgewogICAgICAgIHRoaXMuZGVzY2VudCA9IG1ldHJpY3MuZGVzY2VudCAvIFBERl9HTFlQSF9TUEFDRV9VTklUUzsKICAgICAgfQogICAgICBpZiAoaXNOYU4odGhpcy5jYXBIZWlnaHQpKSB7CiAgICAgICAgdGhpcy5jYXBIZWlnaHQgPSBtZXRyaWNzLmNhcEhlaWdodCAvIFBERl9HTFlQSF9TUEFDRV9VTklUUzsKICAgICAgfQogICAgfQogICAgdGhpcy5ib2xkID0gL2JvbGQvZ2kudGVzdChmb250TmFtZSk7CiAgICB0aGlzLml0YWxpYyA9IC9vYmxpcXVlfGl0YWxpYy9naS50ZXN0KGZvbnROYW1lKTsKICAgIHRoaXMuYmxhY2sgPSAvQmxhY2svZy50ZXN0KG5hbWUpOwogICAgY29uc3QgaXNOYXJyb3cgPSAvTmFycm93L2cudGVzdChuYW1lKTsKICAgIHRoaXMucmVtZWFzdXJlID0gKCFpc1N0YW5kYXJkRm9udCB8fCBpc05hcnJvdykgJiYgT2JqZWN0LmtleXModGhpcy53aWR0aHMpLmxlbmd0aCA+IDA7CiAgICBpZiAoKGlzU3RhbmRhcmRGb250IHx8IGlzTWFwcGVkVG9TdGFuZGFyZEZvbnQpICYmIHR5cGUgPT09ICJDSURGb250VHlwZTIiICYmIHRoaXMuY2lkRW5jb2Rpbmcuc3RhcnRzV2l0aCgiSWRlbnRpdHktIikpIHsKICAgICAgY29uc3QgY2lkVG9HaWRNYXAgPSBwcm9wZXJ0aWVzLmNpZFRvR2lkTWFwOwogICAgICBjb25zdCBtYXAgPSBbXTsKICAgICAgYXBwbHlTdGFuZGFyZEZvbnRHbHlwaE1hcChtYXAsIGdldEdseXBoTWFwRm9yU3RhbmRhcmRGb250cygpKTsKICAgICAgaWYgKC9BcmlhbC0/QmxhY2svaS50ZXN0KG5hbWUpKSB7CiAgICAgICAgYXBwbHlTdGFuZGFyZEZvbnRHbHlwaE1hcChtYXAsIGdldFN1cHBsZW1lbnRhbEdseXBoTWFwRm9yQXJpYWxCbGFjaygpKTsKICAgICAgfSBlbHNlIGlmICgvQ2FsaWJyaS9pLnRlc3QobmFtZSkpIHsKICAgICAgICBhcHBseVN0YW5kYXJkRm9udEdseXBoTWFwKG1hcCwgZ2V0U3VwcGxlbWVudGFsR2x5cGhNYXBGb3JDYWxpYnJpKCkpOwogICAgICB9CiAgICAgIGlmIChjaWRUb0dpZE1hcCkgewogICAgICAgIGZvciAoY29uc3QgY2hhckNvZGUgaW4gbWFwKSB7CiAgICAgICAgICBjb25zdCBjaWQgPSBtYXBbY2hhckNvZGVdOwogICAgICAgICAgaWYgKGNpZFRvR2lkTWFwW2NpZF0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBtYXBbK2NoYXJDb2RlXSA9IGNpZFRvR2lkTWFwW2NpZF07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChjaWRUb0dpZE1hcC5sZW5ndGggIT09IHRoaXMudG9Vbmljb2RlLmxlbmd0aCAmJiBwcm9wZXJ0aWVzLmhhc0luY2x1ZGVkVG9Vbmljb2RlTWFwICYmIHRoaXMudG9Vbmljb2RlIGluc3RhbmNlb2YgSWRlbnRpdHlUb1VuaWNvZGVNYXApIHsKICAgICAgICAgIHRoaXMudG9Vbmljb2RlLmZvckVhY2goZnVuY3Rpb24gKGNoYXJDb2RlLCB1bmljb2RlQ2hhckNvZGUpIHsKICAgICAgICAgICAgY29uc3QgY2lkID0gbWFwW2NoYXJDb2RlXTsKICAgICAgICAgICAgaWYgKGNpZFRvR2lkTWFwW2NpZF0gPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIG1hcFsrY2hhckNvZGVdID0gdW5pY29kZUNoYXJDb2RlOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCEodGhpcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBJZGVudGl0eVRvVW5pY29kZU1hcCkpIHsKICAgICAgICB0aGlzLnRvVW5pY29kZS5mb3JFYWNoKGZ1bmN0aW9uIChjaGFyQ29kZSwgdW5pY29kZUNoYXJDb2RlKSB7CiAgICAgICAgICBtYXBbK2NoYXJDb2RlXSA9IHVuaWNvZGVDaGFyQ29kZTsKICAgICAgICB9KTsKICAgICAgfQogICAgICB0aGlzLnRvRm9udENoYXIgPSBtYXA7CiAgICAgIHRoaXMudG9Vbmljb2RlID0gbmV3IFRvVW5pY29kZU1hcChtYXApOwogICAgfSBlbHNlIGlmICgvU3ltYm9sL2kudGVzdChmb250TmFtZSkpIHsKICAgICAgdGhpcy50b0ZvbnRDaGFyID0gYnVpbGRUb0ZvbnRDaGFyKFN5bWJvbFNldEVuY29kaW5nLCBnZXRHbHlwaHNVbmljb2RlKCksIHRoaXMuZGlmZmVyZW5jZXMpOwogICAgfSBlbHNlIGlmICgvRGluZ2JhdHMvaS50ZXN0KGZvbnROYW1lKSkgewogICAgICB0aGlzLnRvRm9udENoYXIgPSBidWlsZFRvRm9udENoYXIoWmFwZkRpbmdiYXRzRW5jb2RpbmcsIGdldERpbmdiYXRzR2x5cGhzVW5pY29kZSgpLCB0aGlzLmRpZmZlcmVuY2VzKTsKICAgIH0gZWxzZSBpZiAoaXNTdGFuZGFyZEZvbnQgfHwgaXNNYXBwZWRUb1N0YW5kYXJkRm9udCkgewogICAgICBjb25zdCBtYXAgPSBidWlsZFRvRm9udENoYXIodGhpcy5kZWZhdWx0RW5jb2RpbmcsIGdldEdseXBoc1VuaWNvZGUoKSwgdGhpcy5kaWZmZXJlbmNlcyk7CiAgICAgIGlmICh0eXBlID09PSAiQ0lERm9udFR5cGUyIiAmJiAhdGhpcy5jaWRFbmNvZGluZy5zdGFydHNXaXRoKCJJZGVudGl0eS0iKSAmJiAhKHRoaXMudG9Vbmljb2RlIGluc3RhbmNlb2YgSWRlbnRpdHlUb1VuaWNvZGVNYXApKSB7CiAgICAgICAgdGhpcy50b1VuaWNvZGUuZm9yRWFjaChmdW5jdGlvbiAoY2hhckNvZGUsIHVuaWNvZGVDaGFyQ29kZSkgewogICAgICAgICAgbWFwWytjaGFyQ29kZV0gPSB1bmljb2RlQ2hhckNvZGU7CiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgdGhpcy50b0ZvbnRDaGFyID0gbWFwOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgZ2x5cGhzVW5pY29kZU1hcCA9IGdldEdseXBoc1VuaWNvZGUoKTsKICAgICAgY29uc3QgbWFwID0gW107CiAgICAgIHRoaXMudG9Vbmljb2RlLmZvckVhY2goKGNoYXJDb2RlLCB1bmljb2RlQ2hhckNvZGUpID0+IHsKICAgICAgICBpZiAoIXRoaXMuY29tcG9zaXRlKSB7CiAgICAgICAgICBjb25zdCBnbHlwaE5hbWUgPSB0aGlzLmRpZmZlcmVuY2VzW2NoYXJDb2RlXSB8fCB0aGlzLmRlZmF1bHRFbmNvZGluZ1tjaGFyQ29kZV07CiAgICAgICAgICBjb25zdCB1bmljb2RlID0gZ2V0VW5pY29kZUZvckdseXBoKGdseXBoTmFtZSwgZ2x5cGhzVW5pY29kZU1hcCk7CiAgICAgICAgICBpZiAodW5pY29kZSAhPT0gLTEpIHsKICAgICAgICAgICAgdW5pY29kZUNoYXJDb2RlID0gdW5pY29kZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbWFwWytjaGFyQ29kZV0gPSB1bmljb2RlQ2hhckNvZGU7CiAgICAgIH0pOwogICAgICBpZiAodGhpcy5jb21wb3NpdGUgJiYgdGhpcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBJZGVudGl0eVRvVW5pY29kZU1hcCkgewogICAgICAgIGlmICgvVGFob21hfFZlcmRhbmEvaS50ZXN0KG5hbWUpKSB7CiAgICAgICAgICBhcHBseVN0YW5kYXJkRm9udEdseXBoTWFwKG1hcCwgZ2V0R2x5cGhNYXBGb3JTdGFuZGFyZEZvbnRzKCkpOwogICAgICAgIH0KICAgICAgfQogICAgICB0aGlzLnRvRm9udENoYXIgPSBtYXA7CiAgICB9CiAgICBhbWVuZEZhbGxiYWNrVG9Vbmljb2RlKHByb3BlcnRpZXMpOwogICAgdGhpcy5sb2FkZWROYW1lID0gZm9udE5hbWUuc3BsaXQoIi0iLCAxKVswXTsKICB9CiAgY2hlY2tBbmRSZXBhaXIobmFtZSwgZm9udCwgcHJvcGVydGllcykgewogICAgY29uc3QgVkFMSURfVEFCTEVTID0gWyJPUy8yIiwgImNtYXAiLCAiaGVhZCIsICJoaGVhIiwgImhtdHgiLCAibWF4cCIsICJuYW1lIiwgInBvc3QiLCAibG9jYSIsICJnbHlmIiwgImZwZ20iLCAicHJlcCIsICJjdnQgIiwgIkNGRiAiXTsKICAgIGZ1bmN0aW9uIHJlYWRUYWJsZXMoZmlsZSwgbnVtVGFibGVzKSB7CiAgICAgIGNvbnN0IHRhYmxlcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHRhYmxlc1siT1MvMiJdID0gbnVsbDsKICAgICAgdGFibGVzLmNtYXAgPSBudWxsOwogICAgICB0YWJsZXMuaGVhZCA9IG51bGw7CiAgICAgIHRhYmxlcy5oaGVhID0gbnVsbDsKICAgICAgdGFibGVzLmhtdHggPSBudWxsOwogICAgICB0YWJsZXMubWF4cCA9IG51bGw7CiAgICAgIHRhYmxlcy5uYW1lID0gbnVsbDsKICAgICAgdGFibGVzLnBvc3QgPSBudWxsOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bVRhYmxlczsgaSsrKSB7CiAgICAgICAgY29uc3QgdGFibGUgPSByZWFkVGFibGVFbnRyeShmaWxlKTsKICAgICAgICBpZiAoIVZBTElEX1RBQkxFUy5pbmNsdWRlcyh0YWJsZS50YWcpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKHRhYmxlLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIHRhYmxlc1t0YWJsZS50YWddID0gdGFibGU7CiAgICAgIH0KICAgICAgcmV0dXJuIHRhYmxlczsKICAgIH0KICAgIGZ1bmN0aW9uIHJlYWRUYWJsZUVudHJ5KGZpbGUpIHsKICAgICAgY29uc3QgdGFnID0gZmlsZS5nZXRTdHJpbmcoNCk7CiAgICAgIGNvbnN0IGNoZWNrc3VtID0gZmlsZS5nZXRJbnQzMigpID4+PiAwOwogICAgICBjb25zdCBvZmZzZXQgPSBmaWxlLmdldEludDMyKCkgPj4+IDA7CiAgICAgIGNvbnN0IGxlbmd0aCA9IGZpbGUuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgY29uc3QgcHJldmlvdXNQb3NpdGlvbiA9IGZpbGUucG9zOwogICAgICBmaWxlLnBvcyA9IGZpbGUuc3RhcnQgfHwgMDsKICAgICAgZmlsZS5za2lwKG9mZnNldCk7CiAgICAgIGNvbnN0IGRhdGEgPSBmaWxlLmdldEJ5dGVzKGxlbmd0aCk7CiAgICAgIGZpbGUucG9zID0gcHJldmlvdXNQb3NpdGlvbjsKICAgICAgaWYgKHRhZyA9PT0gImhlYWQiKSB7CiAgICAgICAgZGF0YVs4XSA9IGRhdGFbOV0gPSBkYXRhWzEwXSA9IGRhdGFbMTFdID0gMDsKICAgICAgICBkYXRhWzE3XSB8PSAweDIwOwogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgdGFnLAogICAgICAgIGNoZWNrc3VtLAogICAgICAgIGxlbmd0aCwKICAgICAgICBvZmZzZXQsCiAgICAgICAgZGF0YQogICAgICB9OwogICAgfQogICAgZnVuY3Rpb24gcmVhZE9wZW5UeXBlSGVhZGVyKHR0ZikgewogICAgICByZXR1cm4gewogICAgICAgIHZlcnNpb246IHR0Zi5nZXRTdHJpbmcoNCksCiAgICAgICAgbnVtVGFibGVzOiB0dGYuZ2V0VWludDE2KCksCiAgICAgICAgc2VhcmNoUmFuZ2U6IHR0Zi5nZXRVaW50MTYoKSwKICAgICAgICBlbnRyeVNlbGVjdG9yOiB0dGYuZ2V0VWludDE2KCksCiAgICAgICAgcmFuZ2VTaGlmdDogdHRmLmdldFVpbnQxNigpCiAgICAgIH07CiAgICB9CiAgICBmdW5jdGlvbiByZWFkVHJ1ZVR5cGVDb2xsZWN0aW9uSGVhZGVyKHR0YykgewogICAgICBjb25zdCB0dGNUYWcgPSB0dGMuZ2V0U3RyaW5nKDQpOwogICAgICBhc3NlcnQodHRjVGFnID09PSAidHRjZiIsICJNdXN0IGJlIGEgVHJ1ZVR5cGUgQ29sbGVjdGlvbiBmb250LiIpOwogICAgICBjb25zdCBtYWpvclZlcnNpb24gPSB0dGMuZ2V0VWludDE2KCk7CiAgICAgIGNvbnN0IG1pbm9yVmVyc2lvbiA9IHR0Yy5nZXRVaW50MTYoKTsKICAgICAgY29uc3QgbnVtRm9udHMgPSB0dGMuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgY29uc3Qgb2Zmc2V0VGFibGUgPSBbXTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Gb250czsgaSsrKSB7CiAgICAgICAgb2Zmc2V0VGFibGUucHVzaCh0dGMuZ2V0SW50MzIoKSA+Pj4gMCk7CiAgICAgIH0KICAgICAgY29uc3QgaGVhZGVyID0gewogICAgICAgIHR0Y1RhZywKICAgICAgICBtYWpvclZlcnNpb24sCiAgICAgICAgbWlub3JWZXJzaW9uLAogICAgICAgIG51bUZvbnRzLAogICAgICAgIG9mZnNldFRhYmxlCiAgICAgIH07CiAgICAgIHN3aXRjaCAobWFqb3JWZXJzaW9uKSB7CiAgICAgICAgY2FzZSAxOgogICAgICAgICAgcmV0dXJuIGhlYWRlcjsKICAgICAgICBjYXNlIDI6CiAgICAgICAgICBoZWFkZXIuZHNpZ1RhZyA9IHR0Yy5nZXRJbnQzMigpID4+PiAwOwogICAgICAgICAgaGVhZGVyLmRzaWdMZW5ndGggPSB0dGMuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICAgIGhlYWRlci5kc2lnT2Zmc2V0ID0gdHRjLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgICByZXR1cm4gaGVhZGVyOwogICAgICB9CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBUcnVlVHlwZSBDb2xsZWN0aW9uIG1ham9yVmVyc2lvbjogJHttYWpvclZlcnNpb259LmApOwogICAgfQogICAgZnVuY3Rpb24gcmVhZFRydWVUeXBlQ29sbGVjdGlvbkRhdGEodHRjLCBmb250TmFtZSkgewogICAgICBjb25zdCB7CiAgICAgICAgbnVtRm9udHMsCiAgICAgICAgb2Zmc2V0VGFibGUKICAgICAgfSA9IHJlYWRUcnVlVHlwZUNvbGxlY3Rpb25IZWFkZXIodHRjKTsKICAgICAgY29uc3QgZm9udE5hbWVQYXJ0cyA9IGZvbnROYW1lLnNwbGl0KCIrIik7CiAgICAgIGxldCBmYWxsYmFja0RhdGE7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtRm9udHM7IGkrKykgewogICAgICAgIHR0Yy5wb3MgPSAodHRjLnN0YXJ0IHx8IDApICsgb2Zmc2V0VGFibGVbaV07CiAgICAgICAgY29uc3QgcG90ZW50aWFsSGVhZGVyID0gcmVhZE9wZW5UeXBlSGVhZGVyKHR0Yyk7CiAgICAgICAgY29uc3QgcG90ZW50aWFsVGFibGVzID0gcmVhZFRhYmxlcyh0dGMsIHBvdGVudGlhbEhlYWRlci5udW1UYWJsZXMpOwogICAgICAgIGlmICghcG90ZW50aWFsVGFibGVzLm5hbWUpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcignVHJ1ZVR5cGUgQ29sbGVjdGlvbiBmb250IG11c3QgY29udGFpbiBhICJuYW1lIiB0YWJsZS4nKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgW25hbWVUYWJsZV0gPSByZWFkTmFtZVRhYmxlKHBvdGVudGlhbFRhYmxlcy5uYW1lKTsKICAgICAgICBmb3IgKGxldCBqID0gMCwgamogPSBuYW1lVGFibGUubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICAgICAgZm9yIChsZXQgayA9IDAsIGtrID0gbmFtZVRhYmxlW2pdLmxlbmd0aDsgayA8IGtrOyBrKyspIHsKICAgICAgICAgICAgY29uc3QgbmFtZUVudHJ5ID0gbmFtZVRhYmxlW2pdW2tdPy5yZXBsYWNlQWxsKC9ccy9nLCAiIik7CiAgICAgICAgICAgIGlmICghbmFtZUVudHJ5KSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKG5hbWVFbnRyeSA9PT0gZm9udE5hbWUpIHsKICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgaGVhZGVyOiBwb3RlbnRpYWxIZWFkZXIsCiAgICAgICAgICAgICAgICB0YWJsZXM6IHBvdGVudGlhbFRhYmxlcwogICAgICAgICAgICAgIH07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGZvbnROYW1lUGFydHMubGVuZ3RoIDwgMikgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvciAoY29uc3QgcGFydCBvZiBmb250TmFtZVBhcnRzKSB7CiAgICAgICAgICAgICAgaWYgKG5hbWVFbnRyeSA9PT0gcGFydCkgewogICAgICAgICAgICAgICAgZmFsbGJhY2tEYXRhID0gewogICAgICAgICAgICAgICAgICBuYW1lOiBwYXJ0LAogICAgICAgICAgICAgICAgICBoZWFkZXI6IHBvdGVudGlhbEhlYWRlciwKICAgICAgICAgICAgICAgICAgdGFibGVzOiBwb3RlbnRpYWxUYWJsZXMKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChmYWxsYmFja0RhdGEpIHsKICAgICAgICB3YXJuKGBUcnVlVHlwZSBDb2xsZWN0aW9uIGRvZXMgbm90IGNvbnRhaW4gIiR7Zm9udE5hbWV9IiBmb250LCBgICsgYGZhbGxpbmcgYmFjayB0byAiJHtmYWxsYmFja0RhdGEubmFtZX0iIGZvbnQgaW5zdGVhZC5gKTsKICAgICAgICByZXR1cm4gewogICAgICAgICAgaGVhZGVyOiBmYWxsYmFja0RhdGEuaGVhZGVyLAogICAgICAgICAgdGFibGVzOiBmYWxsYmFja0RhdGEudGFibGVzCiAgICAgICAgfTsKICAgICAgfQogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFRydWVUeXBlIENvbGxlY3Rpb24gZG9lcyBub3QgY29udGFpbiAiJHtmb250TmFtZX0iIGZvbnQuYCk7CiAgICB9CiAgICBmdW5jdGlvbiByZWFkQ21hcFRhYmxlKGNtYXAsIGZpbGUsIGlzU3ltYm9saWNGb250LCBoYXNFbmNvZGluZykgewogICAgICBpZiAoIWNtYXApIHsKICAgICAgICB3YXJuKCJObyBjbWFwIHRhYmxlIGF2YWlsYWJsZS4iKTsKICAgICAgICByZXR1cm4gewogICAgICAgICAgcGxhdGZvcm1JZDogLTEsCiAgICAgICAgICBlbmNvZGluZ0lkOiAtMSwKICAgICAgICAgIG1hcHBpbmdzOiBbXSwKICAgICAgICAgIGhhc1Nob3J0Q21hcDogZmFsc2UKICAgICAgICB9OwogICAgICB9CiAgICAgIGxldCBzZWdtZW50OwogICAgICBsZXQgc3RhcnQgPSAoZmlsZS5zdGFydCB8fCAwKSArIGNtYXAub2Zmc2V0OwogICAgICBmaWxlLnBvcyA9IHN0YXJ0OwogICAgICBmaWxlLnNraXAoMik7CiAgICAgIGNvbnN0IG51bVRhYmxlcyA9IGZpbGUuZ2V0VWludDE2KCk7CiAgICAgIGxldCBwb3RlbnRpYWxUYWJsZTsKICAgICAgbGV0IGNhbkJyZWFrID0gZmFsc2U7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtVGFibGVzOyBpKyspIHsKICAgICAgICBjb25zdCBwbGF0Zm9ybUlkID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICBjb25zdCBlbmNvZGluZ0lkID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICBjb25zdCBvZmZzZXQgPSBmaWxlLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgbGV0IHVzZVRhYmxlID0gZmFsc2U7CiAgICAgICAgaWYgKHBvdGVudGlhbFRhYmxlPy5wbGF0Zm9ybUlkID09PSBwbGF0Zm9ybUlkICYmIHBvdGVudGlhbFRhYmxlPy5lbmNvZGluZ0lkID09PSBlbmNvZGluZ0lkKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKHBsYXRmb3JtSWQgPT09IDAgJiYgKGVuY29kaW5nSWQgPT09IDAgfHwgZW5jb2RpbmdJZCA9PT0gMSB8fCBlbmNvZGluZ0lkID09PSAzKSkgewogICAgICAgICAgdXNlVGFibGUgPSB0cnVlOwogICAgICAgIH0gZWxzZSBpZiAocGxhdGZvcm1JZCA9PT0gMSAmJiBlbmNvZGluZ0lkID09PSAwKSB7CiAgICAgICAgICB1c2VUYWJsZSA9IHRydWU7CiAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybUlkID09PSAzICYmIGVuY29kaW5nSWQgPT09IDEgJiYgKGhhc0VuY29kaW5nIHx8ICFwb3RlbnRpYWxUYWJsZSkpIHsKICAgICAgICAgIHVzZVRhYmxlID0gdHJ1ZTsKICAgICAgICAgIGlmICghaXNTeW1ib2xpY0ZvbnQpIHsKICAgICAgICAgICAgY2FuQnJlYWsgPSB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoaXNTeW1ib2xpY0ZvbnQgJiYgcGxhdGZvcm1JZCA9PT0gMyAmJiBlbmNvZGluZ0lkID09PSAwKSB7CiAgICAgICAgICB1c2VUYWJsZSA9IHRydWU7CiAgICAgICAgICBsZXQgY29ycmVjdGx5U29ydGVkID0gdHJ1ZTsKICAgICAgICAgIGlmIChpIDwgbnVtVGFibGVzIC0gMSkgewogICAgICAgICAgICBjb25zdCBuZXh0Qnl0ZXMgPSBmaWxlLnBlZWtCeXRlcygyKSwKICAgICAgICAgICAgICBuZXh0UGxhdGZvcm1JZCA9IGludDE2KG5leHRCeXRlc1swXSwgbmV4dEJ5dGVzWzFdKTsKICAgICAgICAgICAgaWYgKG5leHRQbGF0Zm9ybUlkIDwgcGxhdGZvcm1JZCkgewogICAgICAgICAgICAgIGNvcnJlY3RseVNvcnRlZCA9IGZhbHNlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoY29ycmVjdGx5U29ydGVkKSB7CiAgICAgICAgICAgIGNhbkJyZWFrID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHVzZVRhYmxlKSB7CiAgICAgICAgICBwb3RlbnRpYWxUYWJsZSA9IHsKICAgICAgICAgICAgcGxhdGZvcm1JZCwKICAgICAgICAgICAgZW5jb2RpbmdJZCwKICAgICAgICAgICAgb2Zmc2V0CiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICBpZiAoY2FuQnJlYWspIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAocG90ZW50aWFsVGFibGUpIHsKICAgICAgICBmaWxlLnBvcyA9IHN0YXJ0ICsgcG90ZW50aWFsVGFibGUub2Zmc2V0OwogICAgICB9CiAgICAgIGlmICghcG90ZW50aWFsVGFibGUgfHwgZmlsZS5wZWVrQnl0ZSgpID09PSAtMSkgewogICAgICAgIHdhcm4oIkNvdWxkIG5vdCBmaW5kIGEgcHJlZmVycmVkIGNtYXAgdGFibGUuIik7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHBsYXRmb3JtSWQ6IC0xLAogICAgICAgICAgZW5jb2RpbmdJZDogLTEsCiAgICAgICAgICBtYXBwaW5nczogW10sCiAgICAgICAgICBoYXNTaG9ydENtYXA6IGZhbHNlCiAgICAgICAgfTsKICAgICAgfQogICAgICBjb25zdCBmb3JtYXQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICBsZXQgaGFzU2hvcnRDbWFwID0gZmFsc2U7CiAgICAgIGNvbnN0IG1hcHBpbmdzID0gW107CiAgICAgIGxldCBqLCBnbHlwaElkOwogICAgICBpZiAoZm9ybWF0ID09PSAwKSB7CiAgICAgICAgZmlsZS5za2lwKDIgKyAyKTsKICAgICAgICBmb3IgKGogPSAwOyBqIDwgMjU2OyBqKyspIHsKICAgICAgICAgIGNvbnN0IGluZGV4ID0gZmlsZS5nZXRCeXRlKCk7CiAgICAgICAgICBpZiAoIWluZGV4KSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgbWFwcGluZ3MucHVzaCh7CiAgICAgICAgICAgIGNoYXJDb2RlOiBqLAogICAgICAgICAgICBnbHlwaElkOiBpbmRleAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGhhc1Nob3J0Q21hcCA9IHRydWU7CiAgICAgIH0gZWxzZSBpZiAoZm9ybWF0ID09PSAyKSB7CiAgICAgICAgZmlsZS5za2lwKDIgKyAyKTsKICAgICAgICBjb25zdCBzdWJIZWFkZXJLZXlzID0gW107CiAgICAgICAgbGV0IG1heFN1YkhlYWRlcktleSA9IDA7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAyNTY7IGkrKykgewogICAgICAgICAgY29uc3Qgc3ViSGVhZGVyS2V5ID0gZmlsZS5nZXRVaW50MTYoKSA+PiAzOwogICAgICAgICAgc3ViSGVhZGVyS2V5cy5wdXNoKHN1YkhlYWRlcktleSk7CiAgICAgICAgICBtYXhTdWJIZWFkZXJLZXkgPSBNYXRoLm1heChzdWJIZWFkZXJLZXksIG1heFN1YkhlYWRlcktleSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHN1YkhlYWRlcnMgPSBbXTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8PSBtYXhTdWJIZWFkZXJLZXk7IGkrKykgewogICAgICAgICAgc3ViSGVhZGVycy5wdXNoKHsKICAgICAgICAgICAgZmlyc3RDb2RlOiBmaWxlLmdldFVpbnQxNigpLAogICAgICAgICAgICBlbnRyeUNvdW50OiBmaWxlLmdldFVpbnQxNigpLAogICAgICAgICAgICBpZERlbHRhOiBzaWduZWRJbnQxNihmaWxlLmdldEJ5dGUoKSwgZmlsZS5nZXRCeXRlKCkpLAogICAgICAgICAgICBpZFJhbmdlUG9zOiBmaWxlLnBvcyArIGZpbGUuZ2V0VWludDE2KCkKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgaSsrKSB7CiAgICAgICAgICBpZiAoc3ViSGVhZGVyS2V5c1tpXSA9PT0gMCkgewogICAgICAgICAgICBmaWxlLnBvcyA9IHN1YkhlYWRlcnNbMF0uaWRSYW5nZVBvcyArIDIgKiBpOwogICAgICAgICAgICBnbHlwaElkID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICAgICAgbWFwcGluZ3MucHVzaCh7CiAgICAgICAgICAgICAgY2hhckNvZGU6IGksCiAgICAgICAgICAgICAgZ2x5cGhJZAogICAgICAgICAgICB9KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGNvbnN0IHMgPSBzdWJIZWFkZXJzW3N1YkhlYWRlcktleXNbaV1dOwogICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgcy5lbnRyeUNvdW50OyBqKyspIHsKICAgICAgICAgICAgICBjb25zdCBjaGFyQ29kZSA9IChpIDw8IDgpICsgaiArIHMuZmlyc3RDb2RlOwogICAgICAgICAgICAgIGZpbGUucG9zID0gcy5pZFJhbmdlUG9zICsgMiAqIGo7CiAgICAgICAgICAgICAgZ2x5cGhJZCA9IGZpbGUuZ2V0VWludDE2KCk7CiAgICAgICAgICAgICAgaWYgKGdseXBoSWQgIT09IDApIHsKICAgICAgICAgICAgICAgIGdseXBoSWQgPSAoZ2x5cGhJZCArIHMuaWREZWx0YSkgJSA2NTUzNjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgbWFwcGluZ3MucHVzaCh7CiAgICAgICAgICAgICAgICBjaGFyQ29kZSwKICAgICAgICAgICAgICAgIGdseXBoSWQKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09IDQpIHsKICAgICAgICBmaWxlLnNraXAoMiArIDIpOwogICAgICAgIGNvbnN0IHNlZ0NvdW50ID0gZmlsZS5nZXRVaW50MTYoKSA+PiAxOwogICAgICAgIGZpbGUuc2tpcCg2KTsKICAgICAgICBjb25zdCBzZWdtZW50cyA9IFtdOwogICAgICAgIGxldCBzZWdJbmRleDsKICAgICAgICBmb3IgKHNlZ0luZGV4ID0gMDsgc2VnSW5kZXggPCBzZWdDb3VudDsgc2VnSW5kZXgrKykgewogICAgICAgICAgc2VnbWVudHMucHVzaCh7CiAgICAgICAgICAgIGVuZDogZmlsZS5nZXRVaW50MTYoKQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGZpbGUuc2tpcCgyKTsKICAgICAgICBmb3IgKHNlZ0luZGV4ID0gMDsgc2VnSW5kZXggPCBzZWdDb3VudDsgc2VnSW5kZXgrKykgewogICAgICAgICAgc2VnbWVudHNbc2VnSW5kZXhdLnN0YXJ0ID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICB9CiAgICAgICAgZm9yIChzZWdJbmRleCA9IDA7IHNlZ0luZGV4IDwgc2VnQ291bnQ7IHNlZ0luZGV4KyspIHsKICAgICAgICAgIHNlZ21lbnRzW3NlZ0luZGV4XS5kZWx0YSA9IGZpbGUuZ2V0VWludDE2KCk7CiAgICAgICAgfQogICAgICAgIGxldCBvZmZzZXRzQ291bnQgPSAwLAogICAgICAgICAgb2Zmc2V0SW5kZXg7CiAgICAgICAgZm9yIChzZWdJbmRleCA9IDA7IHNlZ0luZGV4IDwgc2VnQ291bnQ7IHNlZ0luZGV4KyspIHsKICAgICAgICAgIHNlZ21lbnQgPSBzZWdtZW50c1tzZWdJbmRleF07CiAgICAgICAgICBjb25zdCByYW5nZU9mZnNldCA9IGZpbGUuZ2V0VWludDE2KCk7CiAgICAgICAgICBpZiAoIXJhbmdlT2Zmc2V0KSB7CiAgICAgICAgICAgIHNlZ21lbnQub2Zmc2V0SW5kZXggPSAtMTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBvZmZzZXRJbmRleCA9IChyYW5nZU9mZnNldCA+PiAxKSAtIChzZWdDb3VudCAtIHNlZ0luZGV4KTsKICAgICAgICAgIHNlZ21lbnQub2Zmc2V0SW5kZXggPSBvZmZzZXRJbmRleDsKICAgICAgICAgIG9mZnNldHNDb3VudCA9IE1hdGgubWF4KG9mZnNldHNDb3VudCwgb2Zmc2V0SW5kZXggKyBzZWdtZW50LmVuZCAtIHNlZ21lbnQuc3RhcnQgKyAxKTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgb2Zmc2V0cyA9IFtdOwogICAgICAgIGZvciAoaiA9IDA7IGogPCBvZmZzZXRzQ291bnQ7IGorKykgewogICAgICAgICAgb2Zmc2V0cy5wdXNoKGZpbGUuZ2V0VWludDE2KCkpOwogICAgICAgIH0KICAgICAgICBmb3IgKHNlZ0luZGV4ID0gMDsgc2VnSW5kZXggPCBzZWdDb3VudDsgc2VnSW5kZXgrKykgewogICAgICAgICAgc2VnbWVudCA9IHNlZ21lbnRzW3NlZ0luZGV4XTsKICAgICAgICAgIHN0YXJ0ID0gc2VnbWVudC5zdGFydDsKICAgICAgICAgIGNvbnN0IGVuZCA9IHNlZ21lbnQuZW5kOwogICAgICAgICAgY29uc3QgZGVsdGEgPSBzZWdtZW50LmRlbHRhOwogICAgICAgICAgb2Zmc2V0SW5kZXggPSBzZWdtZW50Lm9mZnNldEluZGV4OwogICAgICAgICAgZm9yIChqID0gc3RhcnQ7IGogPD0gZW5kOyBqKyspIHsKICAgICAgICAgICAgaWYgKGogPT09IDB4ZmZmZikgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGdseXBoSWQgPSBvZmZzZXRJbmRleCA8IDAgPyBqIDogb2Zmc2V0c1tvZmZzZXRJbmRleCArIGogLSBzdGFydF07CiAgICAgICAgICAgIGdseXBoSWQgPSBnbHlwaElkICsgZGVsdGEgJiAweGZmZmY7CiAgICAgICAgICAgIG1hcHBpbmdzLnB1c2goewogICAgICAgICAgICAgIGNoYXJDb2RlOiBqLAogICAgICAgICAgICAgIGdseXBoSWQKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGZvcm1hdCA9PT0gNikgewogICAgICAgIGZpbGUuc2tpcCgyICsgMik7CiAgICAgICAgY29uc3QgZmlyc3RDb2RlID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICBjb25zdCBlbnRyeUNvdW50ID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICBmb3IgKGogPSAwOyBqIDwgZW50cnlDb3VudDsgaisrKSB7CiAgICAgICAgICBnbHlwaElkID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICAgIGNvbnN0IGNoYXJDb2RlID0gZmlyc3RDb2RlICsgajsKICAgICAgICAgIG1hcHBpbmdzLnB1c2goewogICAgICAgICAgICBjaGFyQ29kZSwKICAgICAgICAgICAgZ2x5cGhJZAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGZvcm1hdCA9PT0gMTIpIHsKICAgICAgICBmaWxlLnNraXAoMiArIDQgKyA0KTsKICAgICAgICBjb25zdCBuR3JvdXBzID0gZmlsZS5nZXRJbnQzMigpID4+PiAwOwogICAgICAgIGZvciAoaiA9IDA7IGogPCBuR3JvdXBzOyBqKyspIHsKICAgICAgICAgIGNvbnN0IHN0YXJ0Q2hhckNvZGUgPSBmaWxlLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgICBjb25zdCBlbmRDaGFyQ29kZSA9IGZpbGUuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICAgIGxldCBnbHlwaENvZGUgPSBmaWxlLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgICBmb3IgKGxldCBjaGFyQ29kZSA9IHN0YXJ0Q2hhckNvZGU7IGNoYXJDb2RlIDw9IGVuZENoYXJDb2RlOyBjaGFyQ29kZSsrKSB7CiAgICAgICAgICAgIG1hcHBpbmdzLnB1c2goewogICAgICAgICAgICAgIGNoYXJDb2RlLAogICAgICAgICAgICAgIGdseXBoSWQ6IGdseXBoQ29kZSsrCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB3YXJuKCJjbWFwIHRhYmxlIGhhcyB1bnN1cHBvcnRlZCBmb3JtYXQ6ICIgKyBmb3JtYXQpOwogICAgICAgIHJldHVybiB7CiAgICAgICAgICBwbGF0Zm9ybUlkOiAtMSwKICAgICAgICAgIGVuY29kaW5nSWQ6IC0xLAogICAgICAgICAgbWFwcGluZ3M6IFtdLAogICAgICAgICAgaGFzU2hvcnRDbWFwOiBmYWxzZQogICAgICAgIH07CiAgICAgIH0KICAgICAgbWFwcGluZ3Muc29ydCgoYSwgYikgPT4gYS5jaGFyQ29kZSAtIGIuY2hhckNvZGUpOwogICAgICBjb25zdCBmaW5hbE1hcHBpbmdzID0gW10sCiAgICAgICAgc2VlbkNoYXJDb2RlcyA9IG5ldyBTZXQoKTsKICAgICAgZm9yIChjb25zdCBtYXAgb2YgbWFwcGluZ3MpIHsKICAgICAgICBjb25zdCB7CiAgICAgICAgICBjaGFyQ29kZQogICAgICAgIH0gPSBtYXA7CiAgICAgICAgaWYgKHNlZW5DaGFyQ29kZXMuaGFzKGNoYXJDb2RlKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIHNlZW5DaGFyQ29kZXMuYWRkKGNoYXJDb2RlKTsKICAgICAgICBmaW5hbE1hcHBpbmdzLnB1c2gobWFwKTsKICAgICAgfQogICAgICByZXR1cm4gewogICAgICAgIHBsYXRmb3JtSWQ6IHBvdGVudGlhbFRhYmxlLnBsYXRmb3JtSWQsCiAgICAgICAgZW5jb2RpbmdJZDogcG90ZW50aWFsVGFibGUuZW5jb2RpbmdJZCwKICAgICAgICBtYXBwaW5nczogZmluYWxNYXBwaW5ncywKICAgICAgICBoYXNTaG9ydENtYXAKICAgICAgfTsKICAgIH0KICAgIGZ1bmN0aW9uIHNhbml0aXplTWV0cmljcyhmaWxlLCBoZWFkZXIsIG1ldHJpY3MsIGhlYWRUYWJsZSwgbnVtR2x5cGhzLCBkdXBGaXJzdEVudHJ5KSB7CiAgICAgIGlmICghaGVhZGVyKSB7CiAgICAgICAgaWYgKG1ldHJpY3MpIHsKICAgICAgICAgIG1ldHJpY3MuZGF0YSA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBmaWxlLnBvcyA9IChmaWxlLnN0YXJ0IHx8IDApICsgaGVhZGVyLm9mZnNldDsKICAgICAgZmlsZS5wb3MgKz0gNDsKICAgICAgZmlsZS5wb3MgKz0gMjsKICAgICAgZmlsZS5wb3MgKz0gMjsKICAgICAgZmlsZS5wb3MgKz0gMjsKICAgICAgZmlsZS5wb3MgKz0gMjsKICAgICAgZmlsZS5wb3MgKz0gMjsKICAgICAgZmlsZS5wb3MgKz0gMjsKICAgICAgZmlsZS5wb3MgKz0gMjsKICAgICAgZmlsZS5wb3MgKz0gMjsKICAgICAgZmlsZS5wb3MgKz0gMjsKICAgICAgY29uc3QgY2FyZXRPZmZzZXQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICBmaWxlLnBvcyArPSA4OwogICAgICBmaWxlLnBvcyArPSAyOwogICAgICBsZXQgbnVtT2ZNZXRyaWNzID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgaWYgKGNhcmV0T2Zmc2V0ICE9PSAwKSB7CiAgICAgICAgY29uc3QgbWFjU3R5bGUgPSBpbnQxNihoZWFkVGFibGUuZGF0YVs0NF0sIGhlYWRUYWJsZS5kYXRhWzQ1XSk7CiAgICAgICAgaWYgKCEobWFjU3R5bGUgJiAyKSkgewogICAgICAgICAgaGVhZGVyLmRhdGFbMjJdID0gMDsKICAgICAgICAgIGhlYWRlci5kYXRhWzIzXSA9IDA7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChudW1PZk1ldHJpY3MgPiBudW1HbHlwaHMpIHsKICAgICAgICBpbmZvKGBUaGUgbnVtT2ZNZXRyaWNzICgke251bU9mTWV0cmljc30pIHNob3VsZCBub3QgYmUgYCArIGBncmVhdGVyIHRoYW4gdGhlIG51bUdseXBocyAoJHtudW1HbHlwaHN9KS5gKTsKICAgICAgICBudW1PZk1ldHJpY3MgPSBudW1HbHlwaHM7CiAgICAgICAgaGVhZGVyLmRhdGFbMzRdID0gKG51bU9mTWV0cmljcyAmIDB4ZmYwMCkgPj4gODsKICAgICAgICBoZWFkZXIuZGF0YVszNV0gPSBudW1PZk1ldHJpY3MgJiAweDAwZmY7CiAgICAgIH0KICAgICAgY29uc3QgbnVtT2ZTaWRlYmVhcmluZ3MgPSBudW1HbHlwaHMgLSBudW1PZk1ldHJpY3M7CiAgICAgIGNvbnN0IG51bU1pc3NpbmcgPSBudW1PZlNpZGViZWFyaW5ncyAtIChtZXRyaWNzLmxlbmd0aCAtIG51bU9mTWV0cmljcyAqIDQgPj4gMSk7CiAgICAgIGlmIChudW1NaXNzaW5nID4gMCkgewogICAgICAgIGNvbnN0IGVudHJpZXMgPSBuZXcgVWludDhBcnJheShtZXRyaWNzLmxlbmd0aCArIG51bU1pc3NpbmcgKiAyKTsKICAgICAgICBlbnRyaWVzLnNldChtZXRyaWNzLmRhdGEpOwogICAgICAgIGlmIChkdXBGaXJzdEVudHJ5KSB7CiAgICAgICAgICBlbnRyaWVzW21ldHJpY3MubGVuZ3RoXSA9IG1ldHJpY3MuZGF0YVsyXTsKICAgICAgICAgIGVudHJpZXNbbWV0cmljcy5sZW5ndGggKyAxXSA9IG1ldHJpY3MuZGF0YVszXTsKICAgICAgICB9CiAgICAgICAgbWV0cmljcy5kYXRhID0gZW50cmllczsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gc2FuaXRpemVHbHlwaChzb3VyY2UsIHNvdXJjZVN0YXJ0LCBzb3VyY2VFbmQsIGRlc3QsIGRlc3RTdGFydCwgaGludHNWYWxpZCkgewogICAgICBjb25zdCBnbHlwaFByb2ZpbGUgPSB7CiAgICAgICAgbGVuZ3RoOiAwLAogICAgICAgIHNpemVPZkluc3RydWN0aW9uczogMAogICAgICB9OwogICAgICBpZiAoc291cmNlU3RhcnQgPCAwIHx8IHNvdXJjZVN0YXJ0ID49IHNvdXJjZS5sZW5ndGggfHwgc291cmNlRW5kID4gc291cmNlLmxlbmd0aCB8fCBzb3VyY2VFbmQgLSBzb3VyY2VTdGFydCA8PSAxMikgewogICAgICAgIHJldHVybiBnbHlwaFByb2ZpbGU7CiAgICAgIH0KICAgICAgY29uc3QgZ2x5ZiA9IHNvdXJjZS5zdWJhcnJheShzb3VyY2VTdGFydCwgc291cmNlRW5kKTsKICAgICAgY29uc3QgeE1pbiA9IHNpZ25lZEludDE2KGdseWZbMl0sIGdseWZbM10pOwogICAgICBjb25zdCB5TWluID0gc2lnbmVkSW50MTYoZ2x5Zls0XSwgZ2x5Zls1XSk7CiAgICAgIGNvbnN0IHhNYXggPSBzaWduZWRJbnQxNihnbHlmWzZdLCBnbHlmWzddKTsKICAgICAgY29uc3QgeU1heCA9IHNpZ25lZEludDE2KGdseWZbOF0sIGdseWZbOV0pOwogICAgICBpZiAoeE1pbiA+IHhNYXgpIHsKICAgICAgICB3cml0ZVNpZ25lZEludDE2KGdseWYsIDIsIHhNYXgpOwogICAgICAgIHdyaXRlU2lnbmVkSW50MTYoZ2x5ZiwgNiwgeE1pbik7CiAgICAgIH0KICAgICAgaWYgKHlNaW4gPiB5TWF4KSB7CiAgICAgICAgd3JpdGVTaWduZWRJbnQxNihnbHlmLCA0LCB5TWF4KTsKICAgICAgICB3cml0ZVNpZ25lZEludDE2KGdseWYsIDgsIHlNaW4pOwogICAgICB9CiAgICAgIGNvbnN0IGNvbnRvdXJzQ291bnQgPSBzaWduZWRJbnQxNihnbHlmWzBdLCBnbHlmWzFdKTsKICAgICAgaWYgKGNvbnRvdXJzQ291bnQgPCAwKSB7CiAgICAgICAgaWYgKGNvbnRvdXJzQ291bnQgPCAtMSkgewogICAgICAgICAgcmV0dXJuIGdseXBoUHJvZmlsZTsKICAgICAgICB9CiAgICAgICAgZGVzdC5zZXQoZ2x5ZiwgZGVzdFN0YXJ0KTsKICAgICAgICBnbHlwaFByb2ZpbGUubGVuZ3RoID0gZ2x5Zi5sZW5ndGg7CiAgICAgICAgcmV0dXJuIGdseXBoUHJvZmlsZTsKICAgICAgfQogICAgICBsZXQgaSwKICAgICAgICBqID0gMTAsCiAgICAgICAgZmxhZ3NDb3VudCA9IDA7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBjb250b3Vyc0NvdW50OyBpKyspIHsKICAgICAgICBjb25zdCBlbmRQb2ludCA9IGdseWZbal0gPDwgOCB8IGdseWZbaiArIDFdOwogICAgICAgIGZsYWdzQ291bnQgPSBlbmRQb2ludCArIDE7CiAgICAgICAgaiArPSAyOwogICAgICB9CiAgICAgIGNvbnN0IGluc3RydWN0aW9uc1N0YXJ0ID0gajsKICAgICAgY29uc3QgaW5zdHJ1Y3Rpb25zTGVuZ3RoID0gZ2x5ZltqXSA8PCA4IHwgZ2x5ZltqICsgMV07CiAgICAgIGdseXBoUHJvZmlsZS5zaXplT2ZJbnN0cnVjdGlvbnMgPSBpbnN0cnVjdGlvbnNMZW5ndGg7CiAgICAgIGogKz0gMiArIGluc3RydWN0aW9uc0xlbmd0aDsKICAgICAgY29uc3QgaW5zdHJ1Y3Rpb25zRW5kID0gajsKICAgICAgbGV0IGNvb3JkaW5hdGVzTGVuZ3RoID0gMDsKICAgICAgZm9yIChpID0gMDsgaSA8IGZsYWdzQ291bnQ7IGkrKykgewogICAgICAgIGNvbnN0IGZsYWcgPSBnbHlmW2orK107CiAgICAgICAgaWYgKGZsYWcgJiAweGMwKSB7CiAgICAgICAgICBnbHlmW2ogLSAxXSA9IGZsYWcgJiAweDNmOwogICAgICAgIH0KICAgICAgICBsZXQgeExlbmd0aCA9IDI7CiAgICAgICAgaWYgKGZsYWcgJiAyKSB7CiAgICAgICAgICB4TGVuZ3RoID0gMTsKICAgICAgICB9IGVsc2UgaWYgKGZsYWcgJiAxNikgewogICAgICAgICAgeExlbmd0aCA9IDA7CiAgICAgICAgfQogICAgICAgIGxldCB5TGVuZ3RoID0gMjsKICAgICAgICBpZiAoZmxhZyAmIDQpIHsKICAgICAgICAgIHlMZW5ndGggPSAxOwogICAgICAgIH0gZWxzZSBpZiAoZmxhZyAmIDMyKSB7CiAgICAgICAgICB5TGVuZ3RoID0gMDsKICAgICAgICB9CiAgICAgICAgY29uc3QgeHlMZW5ndGggPSB4TGVuZ3RoICsgeUxlbmd0aDsKICAgICAgICBjb29yZGluYXRlc0xlbmd0aCArPSB4eUxlbmd0aDsKICAgICAgICBpZiAoZmxhZyAmIDgpIHsKICAgICAgICAgIGNvbnN0IHJlcGVhdCA9IGdseWZbaisrXTsKICAgICAgICAgIGlmIChyZXBlYXQgPT09IDApIHsKICAgICAgICAgICAgZ2x5ZltqIC0gMV0gXj0gODsKICAgICAgICAgIH0KICAgICAgICAgIGkgKz0gcmVwZWF0OwogICAgICAgICAgY29vcmRpbmF0ZXNMZW5ndGggKz0gcmVwZWF0ICogeHlMZW5ndGg7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChjb29yZGluYXRlc0xlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybiBnbHlwaFByb2ZpbGU7CiAgICAgIH0KICAgICAgbGV0IGdseXBoRGF0YUxlbmd0aCA9IGogKyBjb29yZGluYXRlc0xlbmd0aDsKICAgICAgaWYgKGdseXBoRGF0YUxlbmd0aCA+IGdseWYubGVuZ3RoKSB7CiAgICAgICAgcmV0dXJuIGdseXBoUHJvZmlsZTsKICAgICAgfQogICAgICBpZiAoIWhpbnRzVmFsaWQgJiYgaW5zdHJ1Y3Rpb25zTGVuZ3RoID4gMCkgewogICAgICAgIGRlc3Quc2V0KGdseWYuc3ViYXJyYXkoMCwgaW5zdHJ1Y3Rpb25zU3RhcnQpLCBkZXN0U3RhcnQpOwogICAgICAgIGRlc3Quc2V0KFswLCAwXSwgZGVzdFN0YXJ0ICsgaW5zdHJ1Y3Rpb25zU3RhcnQpOwogICAgICAgIGRlc3Quc2V0KGdseWYuc3ViYXJyYXkoaW5zdHJ1Y3Rpb25zRW5kLCBnbHlwaERhdGFMZW5ndGgpLCBkZXN0U3RhcnQgKyBpbnN0cnVjdGlvbnNTdGFydCArIDIpOwogICAgICAgIGdseXBoRGF0YUxlbmd0aCAtPSBpbnN0cnVjdGlvbnNMZW5ndGg7CiAgICAgICAgaWYgKGdseWYubGVuZ3RoIC0gZ2x5cGhEYXRhTGVuZ3RoID4gMykgewogICAgICAgICAgZ2x5cGhEYXRhTGVuZ3RoID0gZ2x5cGhEYXRhTGVuZ3RoICsgMyAmIH4zOwogICAgICAgIH0KICAgICAgICBnbHlwaFByb2ZpbGUubGVuZ3RoID0gZ2x5cGhEYXRhTGVuZ3RoOwogICAgICAgIHJldHVybiBnbHlwaFByb2ZpbGU7CiAgICAgIH0KICAgICAgaWYgKGdseWYubGVuZ3RoIC0gZ2x5cGhEYXRhTGVuZ3RoID4gMykgewogICAgICAgIGdseXBoRGF0YUxlbmd0aCA9IGdseXBoRGF0YUxlbmd0aCArIDMgJiB+MzsKICAgICAgICBkZXN0LnNldChnbHlmLnN1YmFycmF5KDAsIGdseXBoRGF0YUxlbmd0aCksIGRlc3RTdGFydCk7CiAgICAgICAgZ2x5cGhQcm9maWxlLmxlbmd0aCA9IGdseXBoRGF0YUxlbmd0aDsKICAgICAgICByZXR1cm4gZ2x5cGhQcm9maWxlOwogICAgICB9CiAgICAgIGRlc3Quc2V0KGdseWYsIGRlc3RTdGFydCk7CiAgICAgIGdseXBoUHJvZmlsZS5sZW5ndGggPSBnbHlmLmxlbmd0aDsKICAgICAgcmV0dXJuIGdseXBoUHJvZmlsZTsKICAgIH0KICAgIGZ1bmN0aW9uIHNhbml0aXplSGVhZChoZWFkLCBudW1HbHlwaHMsIGxvY2FMZW5ndGgpIHsKICAgICAgY29uc3QgZGF0YSA9IGhlYWQuZGF0YTsKICAgICAgY29uc3QgdmVyc2lvbiA9IGludDMyKGRhdGFbMF0sIGRhdGFbMV0sIGRhdGFbMl0sIGRhdGFbM10pOwogICAgICBpZiAodmVyc2lvbiA+PiAxNiAhPT0gMSkgewogICAgICAgIGluZm8oIkF0dGVtcHRpbmcgdG8gZml4IGludmFsaWQgdmVyc2lvbiBpbiBoZWFkIHRhYmxlOiAiICsgdmVyc2lvbik7CiAgICAgICAgZGF0YVswXSA9IDA7CiAgICAgICAgZGF0YVsxXSA9IDE7CiAgICAgICAgZGF0YVsyXSA9IDA7CiAgICAgICAgZGF0YVszXSA9IDA7CiAgICAgIH0KICAgICAgY29uc3QgaW5kZXhUb0xvY0Zvcm1hdCA9IGludDE2KGRhdGFbNTBdLCBkYXRhWzUxXSk7CiAgICAgIGlmIChpbmRleFRvTG9jRm9ybWF0IDwgMCB8fCBpbmRleFRvTG9jRm9ybWF0ID4gMSkgewogICAgICAgIGluZm8oIkF0dGVtcHRpbmcgdG8gZml4IGludmFsaWQgaW5kZXhUb0xvY0Zvcm1hdCBpbiBoZWFkIHRhYmxlOiAiICsgaW5kZXhUb0xvY0Zvcm1hdCk7CiAgICAgICAgY29uc3QgbnVtR2x5cGhzUGx1c09uZSA9IG51bUdseXBocyArIDE7CiAgICAgICAgaWYgKGxvY2FMZW5ndGggPT09IG51bUdseXBoc1BsdXNPbmUgPDwgMSkgewogICAgICAgICAgZGF0YVs1MF0gPSAwOwogICAgICAgICAgZGF0YVs1MV0gPSAwOwogICAgICAgIH0gZWxzZSBpZiAobG9jYUxlbmd0aCA9PT0gbnVtR2x5cGhzUGx1c09uZSA8PCAyKSB7CiAgICAgICAgICBkYXRhWzUwXSA9IDA7CiAgICAgICAgICBkYXRhWzUxXSA9IDE7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiQ291bGQgbm90IGZpeCBpbmRleFRvTG9jRm9ybWF0OiAiICsgaW5kZXhUb0xvY0Zvcm1hdCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBzYW5pdGl6ZUdseXBoTG9jYXRpb25zKGxvY2EsIGdseWYsIG51bUdseXBocywgaXNHbHlwaExvY2F0aW9uc0xvbmcsIGhpbnRzVmFsaWQsIGR1cEZpcnN0RW50cnksIG1heFNpemVPZkluc3RydWN0aW9ucykgewogICAgICBsZXQgaXRlbVNpemUsIGl0ZW1EZWNvZGUsIGl0ZW1FbmNvZGU7CiAgICAgIGlmIChpc0dseXBoTG9jYXRpb25zTG9uZykgewogICAgICAgIGl0ZW1TaXplID0gNDsKICAgICAgICBpdGVtRGVjb2RlID0gZnVuY3Rpb24gZm9udEl0ZW1EZWNvZGVMb25nKGRhdGEsIG9mZnNldCkgewogICAgICAgICAgcmV0dXJuIGRhdGFbb2Zmc2V0XSA8PCAyNCB8IGRhdGFbb2Zmc2V0ICsgMV0gPDwgMTYgfCBkYXRhW29mZnNldCArIDJdIDw8IDggfCBkYXRhW29mZnNldCArIDNdOwogICAgICAgIH07CiAgICAgICAgaXRlbUVuY29kZSA9IGZ1bmN0aW9uIGZvbnRJdGVtRW5jb2RlTG9uZyhkYXRhLCBvZmZzZXQsIHZhbHVlKSB7CiAgICAgICAgICBkYXRhW29mZnNldF0gPSB2YWx1ZSA+Pj4gMjQgJiAweGZmOwogICAgICAgICAgZGF0YVtvZmZzZXQgKyAxXSA9IHZhbHVlID4+IDE2ICYgMHhmZjsKICAgICAgICAgIGRhdGFbb2Zmc2V0ICsgMl0gPSB2YWx1ZSA+PiA4ICYgMHhmZjsKICAgICAgICAgIGRhdGFbb2Zmc2V0ICsgM10gPSB2YWx1ZSAmIDB4ZmY7CiAgICAgICAgfTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpdGVtU2l6ZSA9IDI7CiAgICAgICAgaXRlbURlY29kZSA9IGZ1bmN0aW9uIGZvbnRJdGVtRGVjb2RlKGRhdGEsIG9mZnNldCkgewogICAgICAgICAgcmV0dXJuIGRhdGFbb2Zmc2V0XSA8PCA5IHwgZGF0YVtvZmZzZXQgKyAxXSA8PCAxOwogICAgICAgIH07CiAgICAgICAgaXRlbUVuY29kZSA9IGZ1bmN0aW9uIGZvbnRJdGVtRW5jb2RlKGRhdGEsIG9mZnNldCwgdmFsdWUpIHsKICAgICAgICAgIGRhdGFbb2Zmc2V0XSA9IHZhbHVlID4+IDkgJiAweGZmOwogICAgICAgICAgZGF0YVtvZmZzZXQgKyAxXSA9IHZhbHVlID4+IDEgJiAweGZmOwogICAgICAgIH07CiAgICAgIH0KICAgICAgY29uc3QgbnVtR2x5cGhzT3V0ID0gZHVwRmlyc3RFbnRyeSA/IG51bUdseXBocyArIDEgOiBudW1HbHlwaHM7CiAgICAgIGNvbnN0IGxvY2FEYXRhU2l6ZSA9IGl0ZW1TaXplICogKDEgKyBudW1HbHlwaHNPdXQpOwogICAgICBjb25zdCBsb2NhRGF0YSA9IG5ldyBVaW50OEFycmF5KGxvY2FEYXRhU2l6ZSk7CiAgICAgIGxvY2FEYXRhLnNldChsb2NhLmRhdGEuc3ViYXJyYXkoMCwgbG9jYURhdGFTaXplKSk7CiAgICAgIGxvY2EuZGF0YSA9IGxvY2FEYXRhOwogICAgICBjb25zdCBvbGRHbHlmRGF0YSA9IGdseWYuZGF0YTsKICAgICAgY29uc3Qgb2xkR2x5ZkRhdGFMZW5ndGggPSBvbGRHbHlmRGF0YS5sZW5ndGg7CiAgICAgIGNvbnN0IG5ld0dseWZEYXRhID0gbmV3IFVpbnQ4QXJyYXkob2xkR2x5ZkRhdGFMZW5ndGgpOwogICAgICBsZXQgaSwgajsKICAgICAgY29uc3QgbG9jYUVudHJpZXMgPSBbXTsKICAgICAgZm9yIChpID0gMCwgaiA9IDA7IGkgPCBudW1HbHlwaHMgKyAxOyBpKyssIGogKz0gaXRlbVNpemUpIHsKICAgICAgICBsZXQgb2Zmc2V0ID0gaXRlbURlY29kZShsb2NhRGF0YSwgaik7CiAgICAgICAgaWYgKG9mZnNldCA+IG9sZEdseWZEYXRhTGVuZ3RoKSB7CiAgICAgICAgICBvZmZzZXQgPSBvbGRHbHlmRGF0YUxlbmd0aDsKICAgICAgICB9CiAgICAgICAgbG9jYUVudHJpZXMucHVzaCh7CiAgICAgICAgICBpbmRleDogaSwKICAgICAgICAgIG9mZnNldCwKICAgICAgICAgIGVuZE9mZnNldDogMAogICAgICAgIH0pOwogICAgICB9CiAgICAgIGxvY2FFbnRyaWVzLnNvcnQoKGEsIGIpID0+IGEub2Zmc2V0IC0gYi5vZmZzZXQpOwogICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtR2x5cGhzOyBpKyspIHsKICAgICAgICBsb2NhRW50cmllc1tpXS5lbmRPZmZzZXQgPSBsb2NhRW50cmllc1tpICsgMV0ub2Zmc2V0OwogICAgICB9CiAgICAgIGxvY2FFbnRyaWVzLnNvcnQoKGEsIGIpID0+IGEuaW5kZXggLSBiLmluZGV4KTsKICAgICAgZm9yIChpID0gMDsgaSA8IG51bUdseXBoczsgaSsrKSB7CiAgICAgICAgY29uc3QgewogICAgICAgICAgb2Zmc2V0LAogICAgICAgICAgZW5kT2Zmc2V0CiAgICAgICAgfSA9IGxvY2FFbnRyaWVzW2ldOwogICAgICAgIGlmIChvZmZzZXQgIT09IDAgfHwgZW5kT2Zmc2V0ICE9PSAwKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgY29uc3QgbmV4dE9mZnNldCA9IGxvY2FFbnRyaWVzW2kgKyAxXS5vZmZzZXQ7CiAgICAgICAgaWYgKG5leHRPZmZzZXQgPT09IDApIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBsb2NhRW50cmllc1tpXS5lbmRPZmZzZXQgPSBuZXh0T2Zmc2V0OwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNvbnN0IGxhc3QgPSBsb2NhRW50cmllcy5hdCgtMik7CiAgICAgIGlmIChsYXN0Lm9mZnNldCAhPT0gMCAmJiBsYXN0LmVuZE9mZnNldCA9PT0gMCkgewogICAgICAgIGxhc3QuZW5kT2Zmc2V0ID0gb2xkR2x5ZkRhdGFMZW5ndGg7CiAgICAgIH0KICAgICAgY29uc3QgbWlzc2luZ0dseXBocyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIGxldCB3cml0ZU9mZnNldCA9IDA7CiAgICAgIGl0ZW1FbmNvZGUobG9jYURhdGEsIDAsIHdyaXRlT2Zmc2V0KTsKICAgICAgZm9yIChpID0gMCwgaiA9IGl0ZW1TaXplOyBpIDwgbnVtR2x5cGhzOyBpKyssIGogKz0gaXRlbVNpemUpIHsKICAgICAgICBjb25zdCBnbHlwaFByb2ZpbGUgPSBzYW5pdGl6ZUdseXBoKG9sZEdseWZEYXRhLCBsb2NhRW50cmllc1tpXS5vZmZzZXQsIGxvY2FFbnRyaWVzW2ldLmVuZE9mZnNldCwgbmV3R2x5ZkRhdGEsIHdyaXRlT2Zmc2V0LCBoaW50c1ZhbGlkKTsKICAgICAgICBjb25zdCBuZXdMZW5ndGggPSBnbHlwaFByb2ZpbGUubGVuZ3RoOwogICAgICAgIGlmIChuZXdMZW5ndGggPT09IDApIHsKICAgICAgICAgIG1pc3NpbmdHbHlwaHNbaV0gPSB0cnVlOwogICAgICAgIH0KICAgICAgICBpZiAoZ2x5cGhQcm9maWxlLnNpemVPZkluc3RydWN0aW9ucyA+IG1heFNpemVPZkluc3RydWN0aW9ucykgewogICAgICAgICAgbWF4U2l6ZU9mSW5zdHJ1Y3Rpb25zID0gZ2x5cGhQcm9maWxlLnNpemVPZkluc3RydWN0aW9uczsKICAgICAgICB9CiAgICAgICAgd3JpdGVPZmZzZXQgKz0gbmV3TGVuZ3RoOwogICAgICAgIGl0ZW1FbmNvZGUobG9jYURhdGEsIGosIHdyaXRlT2Zmc2V0KTsKICAgICAgfQogICAgICBpZiAod3JpdGVPZmZzZXQgPT09IDApIHsKICAgICAgICBjb25zdCBzaW1wbGVHbHlwaCA9IG5ldyBVaW50OEFycmF5KFswLCAxLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCA0OSwgMF0pOwogICAgICAgIGZvciAoaSA9IDAsIGogPSBpdGVtU2l6ZTsgaSA8IG51bUdseXBoc091dDsgaSsrLCBqICs9IGl0ZW1TaXplKSB7CiAgICAgICAgICBpdGVtRW5jb2RlKGxvY2FEYXRhLCBqLCBzaW1wbGVHbHlwaC5sZW5ndGgpOwogICAgICAgIH0KICAgICAgICBnbHlmLmRhdGEgPSBzaW1wbGVHbHlwaDsKICAgICAgfSBlbHNlIGlmIChkdXBGaXJzdEVudHJ5KSB7CiAgICAgICAgY29uc3QgZmlyc3RFbnRyeUxlbmd0aCA9IGl0ZW1EZWNvZGUobG9jYURhdGEsIGl0ZW1TaXplKTsKICAgICAgICBpZiAobmV3R2x5ZkRhdGEubGVuZ3RoID4gZmlyc3RFbnRyeUxlbmd0aCArIHdyaXRlT2Zmc2V0KSB7CiAgICAgICAgICBnbHlmLmRhdGEgPSBuZXdHbHlmRGF0YS5zdWJhcnJheSgwLCBmaXJzdEVudHJ5TGVuZ3RoICsgd3JpdGVPZmZzZXQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBnbHlmLmRhdGEgPSBuZXcgVWludDhBcnJheShmaXJzdEVudHJ5TGVuZ3RoICsgd3JpdGVPZmZzZXQpOwogICAgICAgICAgZ2x5Zi5kYXRhLnNldChuZXdHbHlmRGF0YS5zdWJhcnJheSgwLCB3cml0ZU9mZnNldCkpOwogICAgICAgIH0KICAgICAgICBnbHlmLmRhdGEuc2V0KG5ld0dseWZEYXRhLnN1YmFycmF5KDAsIGZpcnN0RW50cnlMZW5ndGgpLCB3cml0ZU9mZnNldCk7CiAgICAgICAgaXRlbUVuY29kZShsb2NhLmRhdGEsIGxvY2FEYXRhLmxlbmd0aCAtIGl0ZW1TaXplLCB3cml0ZU9mZnNldCArIGZpcnN0RW50cnlMZW5ndGgpOwogICAgICB9IGVsc2UgewogICAgICAgIGdseWYuZGF0YSA9IG5ld0dseWZEYXRhLnN1YmFycmF5KDAsIHdyaXRlT2Zmc2V0KTsKICAgICAgfQogICAgICByZXR1cm4gewogICAgICAgIG1pc3NpbmdHbHlwaHMsCiAgICAgICAgbWF4U2l6ZU9mSW5zdHJ1Y3Rpb25zCiAgICAgIH07CiAgICB9CiAgICBmdW5jdGlvbiByZWFkUG9zdFNjcmlwdFRhYmxlKHBvc3QsIHByb3BlcnRpZXNPYmosIG1heHBOdW1HbHlwaHMpIHsKICAgICAgY29uc3Qgc3RhcnQgPSAoZm9udC5zdGFydCB8fCAwKSArIHBvc3Qub2Zmc2V0OwogICAgICBmb250LnBvcyA9IHN0YXJ0OwogICAgICBjb25zdCBsZW5ndGggPSBwb3N0Lmxlbmd0aCwKICAgICAgICBlbmQgPSBzdGFydCArIGxlbmd0aDsKICAgICAgY29uc3QgdmVyc2lvbiA9IGZvbnQuZ2V0SW50MzIoKTsKICAgICAgZm9udC5za2lwKDI4KTsKICAgICAgbGV0IGdseXBoTmFtZXM7CiAgICAgIGxldCB2YWxpZCA9IHRydWU7CiAgICAgIGxldCBpOwogICAgICBzd2l0Y2ggKHZlcnNpb24pIHsKICAgICAgICBjYXNlIDB4MDAwMTAwMDA6CiAgICAgICAgICBnbHlwaE5hbWVzID0gTWFjU3RhbmRhcmRHbHlwaE9yZGVyaW5nOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDAwMDIwMDAwOgogICAgICAgICAgY29uc3QgbnVtR2x5cGhzID0gZm9udC5nZXRVaW50MTYoKTsKICAgICAgICAgIGlmIChudW1HbHlwaHMgIT09IG1heHBOdW1HbHlwaHMpIHsKICAgICAgICAgICAgdmFsaWQgPSBmYWxzZTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBnbHlwaE5hbWVJbmRleGVzID0gW107CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtR2x5cGhzOyArK2kpIHsKICAgICAgICAgICAgY29uc3QgaW5kZXggPSBmb250LmdldFVpbnQxNigpOwogICAgICAgICAgICBpZiAoaW5kZXggPj0gMzI3NjgpIHsKICAgICAgICAgICAgICB2YWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGdseXBoTmFtZUluZGV4ZXMucHVzaChpbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIXZhbGlkKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgY3VzdG9tTmFtZXMgPSBbXSwKICAgICAgICAgICAgc3RyQnVmID0gW107CiAgICAgICAgICB3aGlsZSAoZm9udC5wb3MgPCBlbmQpIHsKICAgICAgICAgICAgY29uc3Qgc3RyaW5nTGVuZ3RoID0gZm9udC5nZXRCeXRlKCk7CiAgICAgICAgICAgIHN0ckJ1Zi5sZW5ndGggPSBzdHJpbmdMZW5ndGg7CiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzdHJpbmdMZW5ndGg7ICsraSkgewogICAgICAgICAgICAgIHN0ckJ1ZltpXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoZm9udC5nZXRCeXRlKCkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGN1c3RvbU5hbWVzLnB1c2goc3RyQnVmLmpvaW4oIiIpKTsKICAgICAgICAgIH0KICAgICAgICAgIGdseXBoTmFtZXMgPSBbXTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1HbHlwaHM7ICsraSkgewogICAgICAgICAgICBjb25zdCBqID0gZ2x5cGhOYW1lSW5kZXhlc1tpXTsKICAgICAgICAgICAgaWYgKGogPCAyNTgpIHsKICAgICAgICAgICAgICBnbHlwaE5hbWVzLnB1c2goTWFjU3RhbmRhcmRHbHlwaE9yZGVyaW5nW2pdKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBnbHlwaE5hbWVzLnB1c2goY3VzdG9tTmFtZXNbaiAtIDI1OF0pOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDAwMDMwMDAwOgogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHdhcm4oIlVua25vd24vdW5zdXBwb3J0ZWQgcG9zdCB0YWJsZSB2ZXJzaW9uICIgKyB2ZXJzaW9uKTsKICAgICAgICAgIHZhbGlkID0gZmFsc2U7CiAgICAgICAgICBpZiAocHJvcGVydGllc09iai5kZWZhdWx0RW5jb2RpbmcpIHsKICAgICAgICAgICAgZ2x5cGhOYW1lcyA9IHByb3BlcnRpZXNPYmouZGVmYXVsdEVuY29kaW5nOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgcHJvcGVydGllc09iai5nbHlwaE5hbWVzID0gZ2x5cGhOYW1lczsKICAgICAgcmV0dXJuIHZhbGlkOwogICAgfQogICAgZnVuY3Rpb24gcmVhZE5hbWVUYWJsZShuYW1lVGFibGUpIHsKICAgICAgY29uc3Qgc3RhcnQgPSAoZm9udC5zdGFydCB8fCAwKSArIG5hbWVUYWJsZS5vZmZzZXQ7CiAgICAgIGZvbnQucG9zID0gc3RhcnQ7CiAgICAgIGNvbnN0IG5hbWVzID0gW1tdLCBbXV0sCiAgICAgICAgcmVjb3JkcyA9IFtdOwogICAgICBjb25zdCBsZW5ndGggPSBuYW1lVGFibGUubGVuZ3RoLAogICAgICAgIGVuZCA9IHN0YXJ0ICsgbGVuZ3RoOwogICAgICBjb25zdCBmb3JtYXQgPSBmb250LmdldFVpbnQxNigpOwogICAgICBjb25zdCBGT1JNQVRfMF9IRUFERVJfTEVOR1RIID0gNjsKICAgICAgaWYgKGZvcm1hdCAhPT0gMCB8fCBsZW5ndGggPCBGT1JNQVRfMF9IRUFERVJfTEVOR1RIKSB7CiAgICAgICAgcmV0dXJuIFtuYW1lcywgcmVjb3Jkc107CiAgICAgIH0KICAgICAgY29uc3QgbnVtUmVjb3JkcyA9IGZvbnQuZ2V0VWludDE2KCk7CiAgICAgIGNvbnN0IHN0cmluZ3NTdGFydCA9IGZvbnQuZ2V0VWludDE2KCk7CiAgICAgIGNvbnN0IE5BTUVfUkVDT1JEX0xFTkdUSCA9IDEyOwogICAgICBsZXQgaSwgaWk7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1SZWNvcmRzICYmIGZvbnQucG9zICsgTkFNRV9SRUNPUkRfTEVOR1RIIDw9IGVuZDsgaSsrKSB7CiAgICAgICAgY29uc3QgciA9IHsKICAgICAgICAgIHBsYXRmb3JtOiBmb250LmdldFVpbnQxNigpLAogICAgICAgICAgZW5jb2Rpbmc6IGZvbnQuZ2V0VWludDE2KCksCiAgICAgICAgICBsYW5ndWFnZTogZm9udC5nZXRVaW50MTYoKSwKICAgICAgICAgIG5hbWU6IGZvbnQuZ2V0VWludDE2KCksCiAgICAgICAgICBsZW5ndGg6IGZvbnQuZ2V0VWludDE2KCksCiAgICAgICAgICBvZmZzZXQ6IGZvbnQuZ2V0VWludDE2KCkKICAgICAgICB9OwogICAgICAgIGlmIChpc01hY05hbWVSZWNvcmQocikgfHwgaXNXaW5OYW1lUmVjb3JkKHIpKSB7CiAgICAgICAgICByZWNvcmRzLnB1c2gocik7CiAgICAgICAgfQogICAgICB9CiAgICAgIGZvciAoaSA9IDAsIGlpID0gcmVjb3Jkcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3QgcmVjb3JkID0gcmVjb3Jkc1tpXTsKICAgICAgICBpZiAocmVjb3JkLmxlbmd0aCA8PSAwKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcG9zID0gc3RhcnQgKyBzdHJpbmdzU3RhcnQgKyByZWNvcmQub2Zmc2V0OwogICAgICAgIGlmIChwb3MgKyByZWNvcmQubGVuZ3RoID4gZW5kKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgZm9udC5wb3MgPSBwb3M7CiAgICAgICAgY29uc3QgbmFtZUluZGV4ID0gcmVjb3JkLm5hbWU7CiAgICAgICAgaWYgKHJlY29yZC5lbmNvZGluZykgewogICAgICAgICAgbGV0IHN0ciA9ICIiOwogICAgICAgICAgZm9yIChsZXQgaiA9IDAsIGpqID0gcmVjb3JkLmxlbmd0aDsgaiA8IGpqOyBqICs9IDIpIHsKICAgICAgICAgICAgc3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZm9udC5nZXRVaW50MTYoKSk7CiAgICAgICAgICB9CiAgICAgICAgICBuYW1lc1sxXVtuYW1lSW5kZXhdID0gc3RyOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBuYW1lc1swXVtuYW1lSW5kZXhdID0gZm9udC5nZXRTdHJpbmcocmVjb3JkLmxlbmd0aCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBbbmFtZXMsIHJlY29yZHNdOwogICAgfQogICAgY29uc3QgVFRPcHNTdGFja0RlbHRhcyA9IFswLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAtMiwgLTIsIC0yLCAtMiwgMCwgMCwgLTIsIC01LCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIDAsIDAsIC0xLCAwLCAtMSwgLTEsIC0xLCAtMSwgMSwgLTEsIC05OTksIDAsIDEsIDAsIC0xLCAtMiwgMCwgLTEsIC0yLCAtMSwgLTEsIDAsIC0xLCAtMSwgMCwgMCwgLTk5OSwgLTk5OSwgLTEsIC0xLCAtMSwgLTEsIC0yLCAtOTk5LCAtMiwgLTIsIC05OTksIDAsIC0yLCAtMiwgMCwgMCwgLTIsIDAsIC0yLCAwLCAwLCAwLCAtMiwgLTEsIC0xLCAxLCAxLCAwLCAwLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgMCwgMCwgLTEsIDAsIC0xLCAtMSwgMCwgLTk5OSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgLTIsIC05OTksIC05OTksIC05OTksIC05OTksIC05OTksIC0xLCAtMSwgLTIsIC0yLCAwLCAwLCAwLCAwLCAtMSwgLTEsIC05OTksIC0yLCAtMiwgMCwgMCwgLTEsIC0yLCAtMiwgMCwgMCwgMCwgLTEsIC0xLCAtMSwgLTJdOwogICAgZnVuY3Rpb24gc2FuaXRpemVUVFByb2dyYW0odGFibGUsIHR0Q29udGV4dCkgewogICAgICBsZXQgZGF0YSA9IHRhYmxlLmRhdGE7CiAgICAgIGxldCBpID0gMCwKICAgICAgICBqLAogICAgICAgIG4sCiAgICAgICAgYiwKICAgICAgICBmdW5jSWQsCiAgICAgICAgcGMsCiAgICAgICAgbGFzdEVuZGYgPSAwLAogICAgICAgIGxhc3REZWZmID0gMDsKICAgICAgY29uc3Qgc3RhY2sgPSBbXTsKICAgICAgY29uc3QgY2FsbHN0YWNrID0gW107CiAgICAgIGNvbnN0IGZ1bmN0aW9uc0NhbGxlZCA9IFtdOwogICAgICBsZXQgdG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zID0gdHRDb250ZXh0LnRvb0NvbXBsZXhUb0ZvbGxvd0Z1bmN0aW9uczsKICAgICAgbGV0IGluRkRFRiA9IGZhbHNlLAogICAgICAgIGlmTGV2ZWwgPSAwLAogICAgICAgIGluRUxTRSA9IDA7CiAgICAgIGZvciAobGV0IGlpID0gZGF0YS5sZW5ndGg7IGkgPCBpaTspIHsKICAgICAgICBjb25zdCBvcCA9IGRhdGFbaSsrXTsKICAgICAgICBpZiAob3AgPT09IDB4NDApIHsKICAgICAgICAgIG4gPSBkYXRhW2krK107CiAgICAgICAgICBpZiAoaW5GREVGIHx8IGluRUxTRSkgewogICAgICAgICAgICBpICs9IG47CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbjsgaisrKSB7CiAgICAgICAgICAgICAgc3RhY2sucHVzaChkYXRhW2krK10pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChvcCA9PT0gMHg0MSkgewogICAgICAgICAgbiA9IGRhdGFbaSsrXTsKICAgICAgICAgIGlmIChpbkZERUYgfHwgaW5FTFNFKSB7CiAgICAgICAgICAgIGkgKz0gbiAqIDI7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbjsgaisrKSB7CiAgICAgICAgICAgICAgYiA9IGRhdGFbaSsrXTsKICAgICAgICAgICAgICBzdGFjay5wdXNoKGIgPDwgOCB8IGRhdGFbaSsrXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKChvcCAmIDB4ZjgpID09PSAweGIwKSB7CiAgICAgICAgICBuID0gb3AgLSAweGIwICsgMTsKICAgICAgICAgIGlmIChpbkZERUYgfHwgaW5FTFNFKSB7CiAgICAgICAgICAgIGkgKz0gbjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBuOyBqKyspIHsKICAgICAgICAgICAgICBzdGFjay5wdXNoKGRhdGFbaSsrXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKChvcCAmIDB4ZjgpID09PSAweGI4KSB7CiAgICAgICAgICBuID0gb3AgLSAweGI4ICsgMTsKICAgICAgICAgIGlmIChpbkZERUYgfHwgaW5FTFNFKSB7CiAgICAgICAgICAgIGkgKz0gbiAqIDI7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbjsgaisrKSB7CiAgICAgICAgICAgICAgYiA9IGRhdGFbaSsrXTsKICAgICAgICAgICAgICBzdGFjay5wdXNoKHNpZ25lZEludDE2KGIsIGRhdGFbaSsrXSkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChvcCA9PT0gMHgyYiAmJiAhdG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zKSB7CiAgICAgICAgICBpZiAoIWluRkRFRiAmJiAhaW5FTFNFKSB7CiAgICAgICAgICAgIGZ1bmNJZCA9IHN0YWNrLmF0KC0xKTsKICAgICAgICAgICAgaWYgKGlzTmFOKGZ1bmNJZCkpIHsKICAgICAgICAgICAgICBpbmZvKCJUVDogQ0FMTCBlbXB0eSBzdGFjayAob3IgaW52YWxpZCBlbnRyeSkuIik7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdHRDb250ZXh0LmZ1bmN0aW9uc1VzZWRbZnVuY0lkXSA9IHRydWU7CiAgICAgICAgICAgICAgaWYgKGZ1bmNJZCBpbiB0dENvbnRleHQuZnVuY3Rpb25zU3RhY2tEZWx0YXMpIHsKICAgICAgICAgICAgICAgIGNvbnN0IG5ld1N0YWNrTGVuZ3RoID0gc3RhY2subGVuZ3RoICsgdHRDb250ZXh0LmZ1bmN0aW9uc1N0YWNrRGVsdGFzW2Z1bmNJZF07CiAgICAgICAgICAgICAgICBpZiAobmV3U3RhY2tMZW5ndGggPCAwKSB7CiAgICAgICAgICAgICAgICAgIHdhcm4oIlRUOiBDQUxMIGludmFsaWQgZnVuY3Rpb25zIHN0YWNrIGRlbHRhLiIpOwogICAgICAgICAgICAgICAgICB0dENvbnRleHQuaGludHNWYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdGFjay5sZW5ndGggPSBuZXdTdGFja0xlbmd0aDsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKGZ1bmNJZCBpbiB0dENvbnRleHQuZnVuY3Rpb25zRGVmaW5lZCAmJiAhZnVuY3Rpb25zQ2FsbGVkLmluY2x1ZGVzKGZ1bmNJZCkpIHsKICAgICAgICAgICAgICAgIGNhbGxzdGFjay5wdXNoKHsKICAgICAgICAgICAgICAgICAgZGF0YSwKICAgICAgICAgICAgICAgICAgaSwKICAgICAgICAgICAgICAgICAgc3RhY2tUb3A6IHN0YWNrLmxlbmd0aCAtIDEKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgZnVuY3Rpb25zQ2FsbGVkLnB1c2goZnVuY0lkKTsKICAgICAgICAgICAgICAgIHBjID0gdHRDb250ZXh0LmZ1bmN0aW9uc0RlZmluZWRbZnVuY0lkXTsKICAgICAgICAgICAgICAgIGlmICghcGMpIHsKICAgICAgICAgICAgICAgICAgd2FybigiVFQ6IENBTEwgbm9uLWV4aXN0ZW50IGZ1bmN0aW9uIik7CiAgICAgICAgICAgICAgICAgIHR0Q29udGV4dC5oaW50c1ZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGRhdGEgPSBwYy5kYXRhOwogICAgICAgICAgICAgICAgaSA9IHBjLmk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChvcCA9PT0gMHgyYyAmJiAhdG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zKSB7CiAgICAgICAgICBpZiAoaW5GREVGIHx8IGluRUxTRSkgewogICAgICAgICAgICB3YXJuKCJUVDogbmVzdGVkIEZERUZzIG5vdCBhbGxvd2VkIik7CiAgICAgICAgICAgIHRvb0NvbXBsZXhUb0ZvbGxvd0Z1bmN0aW9ucyA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICBpbkZERUYgPSB0cnVlOwogICAgICAgICAgbGFzdERlZmYgPSBpOwogICAgICAgICAgZnVuY0lkID0gc3RhY2sucG9wKCk7CiAgICAgICAgICB0dENvbnRleHQuZnVuY3Rpb25zRGVmaW5lZFtmdW5jSWRdID0gewogICAgICAgICAgICBkYXRhLAogICAgICAgICAgICBpCiAgICAgICAgICB9OwogICAgICAgIH0gZWxzZSBpZiAob3AgPT09IDB4MmQpIHsKICAgICAgICAgIGlmIChpbkZERUYpIHsKICAgICAgICAgICAgaW5GREVGID0gZmFsc2U7CiAgICAgICAgICAgIGxhc3RFbmRmID0gaTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHBjID0gY2FsbHN0YWNrLnBvcCgpOwogICAgICAgICAgICBpZiAoIXBjKSB7CiAgICAgICAgICAgICAgd2FybigiVFQ6IEVOREYgYmFkIHN0YWNrIik7CiAgICAgICAgICAgICAgdHRDb250ZXh0LmhpbnRzVmFsaWQgPSBmYWxzZTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZnVuY0lkID0gZnVuY3Rpb25zQ2FsbGVkLnBvcCgpOwogICAgICAgICAgICBkYXRhID0gcGMuZGF0YTsKICAgICAgICAgICAgaSA9IHBjLmk7CiAgICAgICAgICAgIHR0Q29udGV4dC5mdW5jdGlvbnNTdGFja0RlbHRhc1tmdW5jSWRdID0gc3RhY2subGVuZ3RoIC0gcGMuc3RhY2tUb3A7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChvcCA9PT0gMHg4OSkgewogICAgICAgICAgaWYgKGluRkRFRiB8fCBpbkVMU0UpIHsKICAgICAgICAgICAgd2FybigiVFQ6IG5lc3RlZCBJREVGcyBub3QgYWxsb3dlZCIpOwogICAgICAgICAgICB0b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnMgPSB0cnVlOwogICAgICAgICAgfQogICAgICAgICAgaW5GREVGID0gdHJ1ZTsKICAgICAgICAgIGxhc3REZWZmID0gaTsKICAgICAgICB9IGVsc2UgaWYgKG9wID09PSAweDU4KSB7CiAgICAgICAgICArK2lmTGV2ZWw7CiAgICAgICAgfSBlbHNlIGlmIChvcCA9PT0gMHgxYikgewogICAgICAgICAgaW5FTFNFID0gaWZMZXZlbDsKICAgICAgICB9IGVsc2UgaWYgKG9wID09PSAweDU5KSB7CiAgICAgICAgICBpZiAoaW5FTFNFID09PSBpZkxldmVsKSB7CiAgICAgICAgICAgIGluRUxTRSA9IDA7CiAgICAgICAgICB9CiAgICAgICAgICAtLWlmTGV2ZWw7CiAgICAgICAgfSBlbHNlIGlmIChvcCA9PT0gMHgxYykgewogICAgICAgICAgaWYgKCFpbkZERUYgJiYgIWluRUxTRSkgewogICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBzdGFjay5hdCgtMSk7CiAgICAgICAgICAgIGlmIChvZmZzZXQgPiAwKSB7CiAgICAgICAgICAgICAgaSArPSBvZmZzZXQgLSAxOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICghaW5GREVGICYmICFpbkVMU0UpIHsKICAgICAgICAgIGxldCBzdGFja0RlbHRhID0gMDsKICAgICAgICAgIGlmIChvcCA8PSAweDhlKSB7CiAgICAgICAgICAgIHN0YWNrRGVsdGEgPSBUVE9wc1N0YWNrRGVsdGFzW29wXTsKICAgICAgICAgIH0gZWxzZSBpZiAob3AgPj0gMHhjMCAmJiBvcCA8PSAweGRmKSB7CiAgICAgICAgICAgIHN0YWNrRGVsdGEgPSAtMTsKICAgICAgICAgIH0gZWxzZSBpZiAob3AgPj0gMHhlMCkgewogICAgICAgICAgICBzdGFja0RlbHRhID0gLTI7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAob3AgPj0gMHg3MSAmJiBvcCA8PSAweDc1KSB7CiAgICAgICAgICAgIG4gPSBzdGFjay5wb3AoKTsKICAgICAgICAgICAgaWYgKCFpc05hTihuKSkgewogICAgICAgICAgICAgIHN0YWNrRGVsdGEgPSAtbiAqIDI7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHdoaWxlIChzdGFja0RlbHRhIDwgMCAmJiBzdGFjay5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIHN0YWNrLnBvcCgpOwogICAgICAgICAgICBzdGFja0RlbHRhKys7CiAgICAgICAgICB9CiAgICAgICAgICB3aGlsZSAoc3RhY2tEZWx0YSA+IDApIHsKICAgICAgICAgICAgc3RhY2sucHVzaChOYU4pOwogICAgICAgICAgICBzdGFja0RlbHRhLS07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIHR0Q29udGV4dC50b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnMgPSB0b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnM7CiAgICAgIGNvbnN0IGNvbnRlbnQgPSBbZGF0YV07CiAgICAgIGlmIChpID4gZGF0YS5sZW5ndGgpIHsKICAgICAgICBjb250ZW50LnB1c2gobmV3IFVpbnQ4QXJyYXkoaSAtIGRhdGEubGVuZ3RoKSk7CiAgICAgIH0KICAgICAgaWYgKGxhc3REZWZmID4gbGFzdEVuZGYpIHsKICAgICAgICB3YXJuKCJUVDogY29tcGxlbWVudGluZyBhIG1pc3NpbmcgZnVuY3Rpb24gdGFpbCIpOwogICAgICAgIGNvbnRlbnQucHVzaChuZXcgVWludDhBcnJheShbMHgyMiwgMHgyZF0pKTsKICAgICAgfQogICAgICBmb2xkVFRUYWJsZSh0YWJsZSwgY29udGVudCk7CiAgICB9CiAgICBmdW5jdGlvbiBjaGVja0ludmFsaWRGdW5jdGlvbnModHRDb250ZXh0LCBtYXhGdW5jdGlvbkRlZnMpIHsKICAgICAgaWYgKHR0Q29udGV4dC50b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnMpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKHR0Q29udGV4dC5mdW5jdGlvbnNEZWZpbmVkLmxlbmd0aCA+IG1heEZ1bmN0aW9uRGVmcykgewogICAgICAgIHdhcm4oIlRUOiBtb3JlIGZ1bmN0aW9ucyBkZWZpbmVkIHRoYW4gZXhwZWN0ZWQiKTsKICAgICAgICB0dENvbnRleHQuaGludHNWYWxpZCA9IGZhbHNlOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBmb3IgKGxldCBqID0gMCwgamogPSB0dENvbnRleHQuZnVuY3Rpb25zVXNlZC5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgICAgaWYgKGogPiBtYXhGdW5jdGlvbkRlZnMpIHsKICAgICAgICAgIHdhcm4oIlRUOiBpbnZhbGlkIGZ1bmN0aW9uIGlkOiAiICsgaik7CiAgICAgICAgICB0dENvbnRleHQuaGludHNWYWxpZCA9IGZhbHNlOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBpZiAodHRDb250ZXh0LmZ1bmN0aW9uc1VzZWRbal0gJiYgIXR0Q29udGV4dC5mdW5jdGlvbnNEZWZpbmVkW2pdKSB7CiAgICAgICAgICB3YXJuKCJUVDogdW5kZWZpbmVkIGZ1bmN0aW9uOiAiICsgaik7CiAgICAgICAgICB0dENvbnRleHQuaGludHNWYWxpZCA9IGZhbHNlOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gZm9sZFRUVGFibGUodGFibGUsIGNvbnRlbnQpIHsKICAgICAgaWYgKGNvbnRlbnQubGVuZ3RoID4gMSkgewogICAgICAgIGxldCBuZXdMZW5ndGggPSAwOwogICAgICAgIGxldCBqLCBqajsKICAgICAgICBmb3IgKGogPSAwLCBqaiA9IGNvbnRlbnQubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICAgICAgbmV3TGVuZ3RoICs9IGNvbnRlbnRbal0ubGVuZ3RoOwogICAgICAgIH0KICAgICAgICBuZXdMZW5ndGggPSBuZXdMZW5ndGggKyAzICYgfjM7CiAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkobmV3TGVuZ3RoKTsKICAgICAgICBsZXQgcG9zID0gMDsKICAgICAgICBmb3IgKGogPSAwLCBqaiA9IGNvbnRlbnQubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICAgICAgcmVzdWx0LnNldChjb250ZW50W2pdLCBwb3MpOwogICAgICAgICAgcG9zICs9IGNvbnRlbnRbal0ubGVuZ3RoOwogICAgICAgIH0KICAgICAgICB0YWJsZS5kYXRhID0gcmVzdWx0OwogICAgICAgIHRhYmxlLmxlbmd0aCA9IG5ld0xlbmd0aDsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gc2FuaXRpemVUVFByb2dyYW1zKGZwZ20sIHByZXAsIGN2dCwgbWF4RnVuY3Rpb25EZWZzKSB7CiAgICAgIGNvbnN0IHR0Q29udGV4dCA9IHsKICAgICAgICBmdW5jdGlvbnNEZWZpbmVkOiBbXSwKICAgICAgICBmdW5jdGlvbnNVc2VkOiBbXSwKICAgICAgICBmdW5jdGlvbnNTdGFja0RlbHRhczogW10sCiAgICAgICAgdG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zOiBmYWxzZSwKICAgICAgICBoaW50c1ZhbGlkOiB0cnVlCiAgICAgIH07CiAgICAgIGlmIChmcGdtKSB7CiAgICAgICAgc2FuaXRpemVUVFByb2dyYW0oZnBnbSwgdHRDb250ZXh0KTsKICAgICAgfQogICAgICBpZiAocHJlcCkgewogICAgICAgIHNhbml0aXplVFRQcm9ncmFtKHByZXAsIHR0Q29udGV4dCk7CiAgICAgIH0KICAgICAgaWYgKGZwZ20pIHsKICAgICAgICBjaGVja0ludmFsaWRGdW5jdGlvbnModHRDb250ZXh0LCBtYXhGdW5jdGlvbkRlZnMpOwogICAgICB9CiAgICAgIGlmIChjdnQgJiYgY3Z0Lmxlbmd0aCAmIDEpIHsKICAgICAgICBjb25zdCBjdnREYXRhID0gbmV3IFVpbnQ4QXJyYXkoY3Z0Lmxlbmd0aCArIDEpOwogICAgICAgIGN2dERhdGEuc2V0KGN2dC5kYXRhKTsKICAgICAgICBjdnQuZGF0YSA9IGN2dERhdGE7CiAgICAgIH0KICAgICAgcmV0dXJuIHR0Q29udGV4dC5oaW50c1ZhbGlkOwogICAgfQogICAgZm9udCA9IG5ldyBTdHJlYW0obmV3IFVpbnQ4QXJyYXkoZm9udC5nZXRCeXRlcygpKSk7CiAgICBsZXQgaGVhZGVyLCB0YWJsZXM7CiAgICBpZiAoaXNUcnVlVHlwZUNvbGxlY3Rpb25GaWxlKGZvbnQpKSB7CiAgICAgIGNvbnN0IHR0Y0RhdGEgPSByZWFkVHJ1ZVR5cGVDb2xsZWN0aW9uRGF0YShmb250LCB0aGlzLm5hbWUpOwogICAgICBoZWFkZXIgPSB0dGNEYXRhLmhlYWRlcjsKICAgICAgdGFibGVzID0gdHRjRGF0YS50YWJsZXM7CiAgICB9IGVsc2UgewogICAgICBoZWFkZXIgPSByZWFkT3BlblR5cGVIZWFkZXIoZm9udCk7CiAgICAgIHRhYmxlcyA9IHJlYWRUYWJsZXMoZm9udCwgaGVhZGVyLm51bVRhYmxlcyk7CiAgICB9CiAgICBjb25zdCBpc1RydWVUeXBlID0gIXRhYmxlc1siQ0ZGICJdOwogICAgaWYgKCFpc1RydWVUeXBlKSB7CiAgICAgIGlmIChoZWFkZXIudmVyc2lvbiA9PT0gIk9UVE8iICYmICFwcm9wZXJ0aWVzLmNvbXBvc2l0ZSB8fCAhdGFibGVzLmhlYWQgfHwgIXRhYmxlcy5oaGVhIHx8ICF0YWJsZXMubWF4cCB8fCAhdGFibGVzLnBvc3QpIHsKICAgICAgICByZXR1cm4gdGhpcy5jb252ZXJ0KG5hbWUsIG5ldyBDRkZGb250KG5ldyBTdHJlYW0odGFibGVzWyJDRkYgIl0uZGF0YSksIHByb3BlcnRpZXMpLCBwcm9wZXJ0aWVzKTsKICAgICAgfQogICAgICBkZWxldGUgdGFibGVzLmdseWY7CiAgICAgIGRlbGV0ZSB0YWJsZXMubG9jYTsKICAgICAgZGVsZXRlIHRhYmxlcy5mcGdtOwogICAgICBkZWxldGUgdGFibGVzLnByZXA7CiAgICAgIGRlbGV0ZSB0YWJsZXNbImN2dCAiXTsKICAgICAgdGhpcy5pc09wZW5UeXBlID0gdHJ1ZTsKICAgIH0gZWxzZSB7CiAgICAgIGlmICghdGFibGVzLmxvY2EpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoJ1JlcXVpcmVkICJsb2NhIiB0YWJsZSBpcyBub3QgZm91bmQnKTsKICAgICAgfQogICAgICBpZiAoIXRhYmxlcy5nbHlmKSB7CiAgICAgICAgd2FybignUmVxdWlyZWQgImdseWYiIHRhYmxlIGlzIG5vdCBmb3VuZCAtLSB0cnlpbmcgdG8gcmVjb3Zlci4nKTsKICAgICAgICB0YWJsZXMuZ2x5ZiA9IHsKICAgICAgICAgIHRhZzogImdseWYiLAogICAgICAgICAgZGF0YTogbmV3IFVpbnQ4QXJyYXkoMCkKICAgICAgICB9OwogICAgICB9CiAgICAgIHRoaXMuaXNPcGVuVHlwZSA9IGZhbHNlOwogICAgfQogICAgaWYgKCF0YWJsZXMubWF4cCkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoJ1JlcXVpcmVkICJtYXhwIiB0YWJsZSBpcyBub3QgZm91bmQnKTsKICAgIH0KICAgIGxldCBudW1HbHlwaHNGcm9tQ0ZGOwogICAgaWYgKCFpc1RydWVUeXBlKSB7CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3QgcGFyc2VyID0gbmV3IENGRlBhcnNlcihuZXcgU3RyZWFtKHRhYmxlc1siQ0ZGICJdLmRhdGEpLCBwcm9wZXJ0aWVzLCBTRUFDX0FOQUxZU0lTX0VOQUJMRUQpOwogICAgICAgIGNvbnN0IGNmZiA9IHBhcnNlci5wYXJzZSgpOwogICAgICAgIGNmZi5kdXBsaWNhdGVGaXJzdEdseXBoKCk7CiAgICAgICAgY29uc3QgY29tcGlsZXIgPSBuZXcgQ0ZGQ29tcGlsZXIoY2ZmKTsKICAgICAgICB0YWJsZXNbIkNGRiAiXS5kYXRhID0gY29tcGlsZXIuY29tcGlsZSgpOwogICAgICAgIG51bUdseXBoc0Zyb21DRkYgPSBjZmYuY2hhclN0cmluZ0NvdW50OwogICAgICB9IGNhdGNoIHsKICAgICAgICB3YXJuKCJGYWlsZWQgdG8gY29tcGlsZSBmb250ICIgKyBwcm9wZXJ0aWVzLmxvYWRlZE5hbWUpOwogICAgICB9CiAgICB9CiAgICBmb250LnBvcyA9IChmb250LnN0YXJ0IHx8IDApICsgdGFibGVzLm1heHAub2Zmc2V0OwogICAgbGV0IHZlcnNpb24gPSBmb250LmdldEludDMyKCk7CiAgICBjb25zdCBudW1HbHlwaHMgPSBudW1HbHlwaHNGcm9tQ0ZGID8/IGZvbnQuZ2V0VWludDE2KCk7CiAgICBpZiAodmVyc2lvbiA9PT0gMHgwMDAwNTAwMCAmJiB0YWJsZXMubWF4cC5sZW5ndGggIT09IDYpIHsKICAgICAgdGFibGVzLm1heHAuZGF0YSA9IHRhYmxlcy5tYXhwLmRhdGEuc3ViYXJyYXkoMCwgNik7CiAgICAgIHRhYmxlcy5tYXhwLmxlbmd0aCA9IDY7CiAgICB9CiAgICBpZiAodmVyc2lvbiAhPT0gMHgwMDAxMDAwMCAmJiB2ZXJzaW9uICE9PSAweDAwMDA1MDAwKSB7CiAgICAgIGlmICh0YWJsZXMubWF4cC5sZW5ndGggPT09IDYpIHsKICAgICAgICB2ZXJzaW9uID0gMHgwMDA1MDAwOwogICAgICB9IGVsc2UgaWYgKHRhYmxlcy5tYXhwLmxlbmd0aCA+PSAzMikgewogICAgICAgIHZlcnNpb24gPSAweDAwMDEwMDAwOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgIm1heHAiIHRhYmxlIGhhcyBhIHdyb25nIHZlcnNpb24gbnVtYmVyYCk7CiAgICAgIH0KICAgICAgd3JpdGVVaW50MzIodGFibGVzLm1heHAuZGF0YSwgMCwgdmVyc2lvbik7CiAgICB9CiAgICBsZXQgaXNHbHlwaExvY2F0aW9uc0xvbmcgPSBpbnQxNih0YWJsZXMuaGVhZC5kYXRhWzUwXSwgdGFibGVzLmhlYWQuZGF0YVs1MV0pOwogICAgaWYgKHRhYmxlcy5sb2NhKSB7CiAgICAgIGNvbnN0IGxvY2FMZW5ndGggPSBpc0dseXBoTG9jYXRpb25zTG9uZyA/IChudW1HbHlwaHMgKyAxKSAqIDQgOiAobnVtR2x5cGhzICsgMSkgKiAyOwogICAgICBpZiAodGFibGVzLmxvY2EubGVuZ3RoICE9PSBsb2NhTGVuZ3RoKSB7CiAgICAgICAgd2FybigiSW5jb3JyZWN0ICdsb2NhJyB0YWJsZSBsZW5ndGggLS0gYXR0ZW1wdGluZyB0byBmaXggaXQuIik7CiAgICAgICAgY29uc3Qgc29ydGVkVGFibGVzID0gT2JqZWN0LnZhbHVlcyh0YWJsZXMpLmZpbHRlcihCb29sZWFuKS5zb3J0KChhLCBiKSA9PiBhLm9mZnNldCAtIGIub2Zmc2V0KTsKICAgICAgICBjb25zdCBsb2NhSW5kZXggPSBzb3J0ZWRUYWJsZXMuaW5kZXhPZih0YWJsZXMubG9jYSk7CiAgICAgICAgY29uc3QgbmV4dFRhYmxlID0gc29ydGVkVGFibGVzW2xvY2FJbmRleCArIDFdIHx8IG51bGw7CiAgICAgICAgaWYgKG5leHRUYWJsZSAmJiB0YWJsZXMubG9jYS5vZmZzZXQgKyBsb2NhTGVuZ3RoIDwgbmV4dFRhYmxlLm9mZnNldCkgewogICAgICAgICAgY29uc3QgcHJldmlvdXNQb3MgPSBmb250LnBvczsKICAgICAgICAgIGZvbnQucG9zID0gZm9udC5zdGFydCB8fCAwOwogICAgICAgICAgZm9udC5za2lwKHRhYmxlcy5sb2NhLm9mZnNldCk7CiAgICAgICAgICB0YWJsZXMubG9jYS5kYXRhID0gZm9udC5nZXRCeXRlcyhsb2NhTGVuZ3RoKTsKICAgICAgICAgIHRhYmxlcy5sb2NhLmxlbmd0aCA9IGxvY2FMZW5ndGg7CiAgICAgICAgICBmb250LnBvcyA9IHByZXZpb3VzUG9zOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKHByb3BlcnRpZXMuc2NhbGVGYWN0b3JzPy5sZW5ndGggPT09IG51bUdseXBocyAmJiBpc1RydWVUeXBlKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBzY2FsZUZhY3RvcnMKICAgICAgfSA9IHByb3BlcnRpZXM7CiAgICAgIGNvbnN0IGdseXBocyA9IG5ldyBHbHlmVGFibGUoewogICAgICAgIGdseWZUYWJsZTogdGFibGVzLmdseWYuZGF0YSwKICAgICAgICBpc0dseXBoTG9jYXRpb25zTG9uZywKICAgICAgICBsb2NhVGFibGU6IHRhYmxlcy5sb2NhLmRhdGEsCiAgICAgICAgbnVtR2x5cGhzCiAgICAgIH0pOwogICAgICBnbHlwaHMuc2NhbGUoc2NhbGVGYWN0b3JzKTsKICAgICAgY29uc3QgewogICAgICAgIGdseWYsCiAgICAgICAgbG9jYSwKICAgICAgICBpc0xvY2F0aW9uTG9uZwogICAgICB9ID0gZ2x5cGhzLndyaXRlKCk7CiAgICAgIHRhYmxlcy5nbHlmLmRhdGEgPSBnbHlmOwogICAgICB0YWJsZXMubG9jYS5kYXRhID0gbG9jYTsKICAgICAgaWYgKGlzTG9jYXRpb25Mb25nICE9PSAhIWlzR2x5cGhMb2NhdGlvbnNMb25nKSB7CiAgICAgICAgdGFibGVzLmhlYWQuZGF0YVs1MF0gPSAwOwogICAgICAgIGlzR2x5cGhMb2NhdGlvbnNMb25nID0gdGFibGVzLmhlYWQuZGF0YVs1MV0gPSBpc0xvY2F0aW9uTG9uZyA/IDEgOiAwOwogICAgICB9CiAgICAgIGNvbnN0IG1ldHJpY3MgPSB0YWJsZXMuaG10eC5kYXRhOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUdseXBoczsgaSsrKSB7CiAgICAgICAgY29uc3QgaiA9IDQgKiBpOwogICAgICAgIGNvbnN0IGFkdmFuY2VXaWR0aCA9IE1hdGgucm91bmQoc2NhbGVGYWN0b3JzW2ldICogaW50MTYobWV0cmljc1tqXSwgbWV0cmljc1tqICsgMV0pKTsKICAgICAgICBtZXRyaWNzW2pdID0gYWR2YW5jZVdpZHRoID4+IDggJiAweGZmOwogICAgICAgIG1ldHJpY3NbaiArIDFdID0gYWR2YW5jZVdpZHRoICYgMHhmZjsKICAgICAgICBjb25zdCBsc2IgPSBNYXRoLnJvdW5kKHNjYWxlRmFjdG9yc1tpXSAqIHNpZ25lZEludDE2KG1ldHJpY3NbaiArIDJdLCBtZXRyaWNzW2ogKyAzXSkpOwogICAgICAgIHdyaXRlU2lnbmVkSW50MTYobWV0cmljcywgaiArIDIsIGxzYik7CiAgICAgIH0KICAgIH0KICAgIGxldCBudW1HbHlwaHNPdXQgPSBudW1HbHlwaHMgKyAxOwogICAgbGV0IGR1cEZpcnN0RW50cnkgPSB0cnVlOwogICAgaWYgKG51bUdseXBoc091dCA+IDB4ZmZmZikgewogICAgICBkdXBGaXJzdEVudHJ5ID0gZmFsc2U7CiAgICAgIG51bUdseXBoc091dCA9IG51bUdseXBoczsKICAgICAgd2FybigiTm90IGVub3VnaCBzcGFjZSBpbiBnbHlmcyB0byBkdXBsaWNhdGUgZmlyc3QgZ2x5cGguIik7CiAgICB9CiAgICBsZXQgbWF4RnVuY3Rpb25EZWZzID0gMDsKICAgIGxldCBtYXhTaXplT2ZJbnN0cnVjdGlvbnMgPSAwOwogICAgaWYgKHZlcnNpb24gPj0gMHgwMDAxMDAwMCAmJiB0YWJsZXMubWF4cC5sZW5ndGggPj0gMzIpIHsKICAgICAgZm9udC5wb3MgKz0gODsKICAgICAgY29uc3QgbWF4Wm9uZXMgPSBmb250LmdldFVpbnQxNigpOwogICAgICBpZiAobWF4Wm9uZXMgPiAyKSB7CiAgICAgICAgdGFibGVzLm1heHAuZGF0YVsxNF0gPSAwOwogICAgICAgIHRhYmxlcy5tYXhwLmRhdGFbMTVdID0gMjsKICAgICAgfQogICAgICBmb250LnBvcyArPSA0OwogICAgICBtYXhGdW5jdGlvbkRlZnMgPSBmb250LmdldFVpbnQxNigpOwogICAgICBmb250LnBvcyArPSA0OwogICAgICBtYXhTaXplT2ZJbnN0cnVjdGlvbnMgPSBmb250LmdldFVpbnQxNigpOwogICAgfQogICAgdGFibGVzLm1heHAuZGF0YVs0XSA9IG51bUdseXBoc091dCA+PiA4OwogICAgdGFibGVzLm1heHAuZGF0YVs1XSA9IG51bUdseXBoc091dCAmIDI1NTsKICAgIGNvbnN0IGhpbnRzVmFsaWQgPSBzYW5pdGl6ZVRUUHJvZ3JhbXModGFibGVzLmZwZ20sIHRhYmxlcy5wcmVwLCB0YWJsZXNbImN2dCAiXSwgbWF4RnVuY3Rpb25EZWZzKTsKICAgIGlmICghaGludHNWYWxpZCkgewogICAgICBkZWxldGUgdGFibGVzLmZwZ207CiAgICAgIGRlbGV0ZSB0YWJsZXMucHJlcDsKICAgICAgZGVsZXRlIHRhYmxlc1siY3Z0ICJdOwogICAgfQogICAgc2FuaXRpemVNZXRyaWNzKGZvbnQsIHRhYmxlcy5oaGVhLCB0YWJsZXMuaG10eCwgdGFibGVzLmhlYWQsIG51bUdseXBoc091dCwgZHVwRmlyc3RFbnRyeSk7CiAgICBpZiAoIXRhYmxlcy5oZWFkKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcignUmVxdWlyZWQgImhlYWQiIHRhYmxlIGlzIG5vdCBmb3VuZCcpOwogICAgfQogICAgc2FuaXRpemVIZWFkKHRhYmxlcy5oZWFkLCBudW1HbHlwaHMsIGlzVHJ1ZVR5cGUgPyB0YWJsZXMubG9jYS5sZW5ndGggOiAwKTsKICAgIGxldCBtaXNzaW5nR2x5cGhzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGlmIChpc1RydWVUeXBlKSB7CiAgICAgIGNvbnN0IGdseXBoc0luZm8gPSBzYW5pdGl6ZUdseXBoTG9jYXRpb25zKHRhYmxlcy5sb2NhLCB0YWJsZXMuZ2x5ZiwgbnVtR2x5cGhzLCBpc0dseXBoTG9jYXRpb25zTG9uZywgaGludHNWYWxpZCwgZHVwRmlyc3RFbnRyeSwgbWF4U2l6ZU9mSW5zdHJ1Y3Rpb25zKTsKICAgICAgbWlzc2luZ0dseXBocyA9IGdseXBoc0luZm8ubWlzc2luZ0dseXBoczsKICAgICAgaWYgKHZlcnNpb24gPj0gMHgwMDAxMDAwMCAmJiB0YWJsZXMubWF4cC5sZW5ndGggPj0gMzIpIHsKICAgICAgICB0YWJsZXMubWF4cC5kYXRhWzI2XSA9IGdseXBoc0luZm8ubWF4U2l6ZU9mSW5zdHJ1Y3Rpb25zID4+IDg7CiAgICAgICAgdGFibGVzLm1heHAuZGF0YVsyN10gPSBnbHlwaHNJbmZvLm1heFNpemVPZkluc3RydWN0aW9ucyAmIDI1NTsKICAgICAgfQogICAgfQogICAgaWYgKCF0YWJsZXMuaGhlYSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoJ1JlcXVpcmVkICJoaGVhIiB0YWJsZSBpcyBub3QgZm91bmQnKTsKICAgIH0KICAgIGlmICh0YWJsZXMuaGhlYS5kYXRhWzEwXSA9PT0gMCAmJiB0YWJsZXMuaGhlYS5kYXRhWzExXSA9PT0gMCkgewogICAgICB0YWJsZXMuaGhlYS5kYXRhWzEwXSA9IDB4ZmY7CiAgICAgIHRhYmxlcy5oaGVhLmRhdGFbMTFdID0gMHhmZjsKICAgIH0KICAgIGNvbnN0IG1ldHJpY3NPdmVycmlkZSA9IHsKICAgICAgdW5pdHNQZXJFbTogaW50MTYodGFibGVzLmhlYWQuZGF0YVsxOF0sIHRhYmxlcy5oZWFkLmRhdGFbMTldKSwKICAgICAgeU1heDogc2lnbmVkSW50MTYodGFibGVzLmhlYWQuZGF0YVs0Ml0sIHRhYmxlcy5oZWFkLmRhdGFbNDNdKSwKICAgICAgeU1pbjogc2lnbmVkSW50MTYodGFibGVzLmhlYWQuZGF0YVszOF0sIHRhYmxlcy5oZWFkLmRhdGFbMzldKSwKICAgICAgYXNjZW50OiBzaWduZWRJbnQxNih0YWJsZXMuaGhlYS5kYXRhWzRdLCB0YWJsZXMuaGhlYS5kYXRhWzVdKSwKICAgICAgZGVzY2VudDogc2lnbmVkSW50MTYodGFibGVzLmhoZWEuZGF0YVs2XSwgdGFibGVzLmhoZWEuZGF0YVs3XSksCiAgICAgIGxpbmVHYXA6IHNpZ25lZEludDE2KHRhYmxlcy5oaGVhLmRhdGFbOF0sIHRhYmxlcy5oaGVhLmRhdGFbOV0pCiAgICB9OwogICAgdGhpcy5hc2NlbnQgPSBtZXRyaWNzT3ZlcnJpZGUuYXNjZW50IC8gbWV0cmljc092ZXJyaWRlLnVuaXRzUGVyRW07CiAgICB0aGlzLmRlc2NlbnQgPSBtZXRyaWNzT3ZlcnJpZGUuZGVzY2VudCAvIG1ldHJpY3NPdmVycmlkZS51bml0c1BlckVtOwogICAgdGhpcy5saW5lR2FwID0gbWV0cmljc092ZXJyaWRlLmxpbmVHYXAgLyBtZXRyaWNzT3ZlcnJpZGUudW5pdHNQZXJFbTsKICAgIGlmICh0aGlzLmNzc0ZvbnRJbmZvPy5saW5lSGVpZ2h0KSB7CiAgICAgIHRoaXMubGluZUhlaWdodCA9IHRoaXMuY3NzRm9udEluZm8ubWV0cmljcy5saW5lSGVpZ2h0OwogICAgICB0aGlzLmxpbmVHYXAgPSB0aGlzLmNzc0ZvbnRJbmZvLm1ldHJpY3MubGluZUdhcDsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMubGluZUhlaWdodCA9IHRoaXMuYXNjZW50IC0gdGhpcy5kZXNjZW50ICsgdGhpcy5saW5lR2FwOwogICAgfQogICAgaWYgKHRhYmxlcy5wb3N0KSB7CiAgICAgIHJlYWRQb3N0U2NyaXB0VGFibGUodGFibGVzLnBvc3QsIHByb3BlcnRpZXMsIG51bUdseXBocyk7CiAgICB9CiAgICB0YWJsZXMucG9zdCA9IHsKICAgICAgdGFnOiAicG9zdCIsCiAgICAgIGRhdGE6IGNyZWF0ZVBvc3RUYWJsZShwcm9wZXJ0aWVzKQogICAgfTsKICAgIGNvbnN0IGNoYXJDb2RlVG9HbHlwaElkID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGZ1bmN0aW9uIGhhc0dseXBoKGdseXBoSWQpIHsKICAgICAgcmV0dXJuICFtaXNzaW5nR2x5cGhzW2dseXBoSWRdOwogICAgfQogICAgaWYgKHByb3BlcnRpZXMuY29tcG9zaXRlKSB7CiAgICAgIGNvbnN0IGNpZFRvR2lkTWFwID0gcHJvcGVydGllcy5jaWRUb0dpZE1hcCB8fCBbXTsKICAgICAgY29uc3QgaXNDaWRUb0dpZE1hcEVtcHR5ID0gY2lkVG9HaWRNYXAubGVuZ3RoID09PSAwOwogICAgICBwcm9wZXJ0aWVzLmNNYXAuZm9yRWFjaChmdW5jdGlvbiAoY2hhckNvZGUsIGNpZCkgewogICAgICAgIGlmICh0eXBlb2YgY2lkID09PSAic3RyaW5nIikgewogICAgICAgICAgY2lkID0gY29udmVydENpZFN0cmluZyhjaGFyQ29kZSwgY2lkLCB0cnVlKTsKICAgICAgICB9CiAgICAgICAgaWYgKGNpZCA+IDB4ZmZmZikgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJNYXggc2l6ZSBvZiBDSUQgaXMgNjUsNTM1Iik7CiAgICAgICAgfQogICAgICAgIGxldCBnbHlwaElkID0gLTE7CiAgICAgICAgaWYgKGlzQ2lkVG9HaWRNYXBFbXB0eSkgewogICAgICAgICAgZ2x5cGhJZCA9IGNpZDsKICAgICAgICB9IGVsc2UgaWYgKGNpZFRvR2lkTWFwW2NpZF0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgZ2x5cGhJZCA9IGNpZFRvR2lkTWFwW2NpZF07CiAgICAgICAgfQogICAgICAgIGlmIChnbHlwaElkID49IDAgJiYgZ2x5cGhJZCA8IG51bUdseXBocyAmJiBoYXNHbHlwaChnbHlwaElkKSkgewogICAgICAgICAgY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gZ2x5cGhJZDsKICAgICAgICB9CiAgICAgIH0pOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgY21hcFRhYmxlID0gcmVhZENtYXBUYWJsZSh0YWJsZXMuY21hcCwgZm9udCwgdGhpcy5pc1N5bWJvbGljRm9udCwgcHJvcGVydGllcy5oYXNFbmNvZGluZyk7CiAgICAgIGNvbnN0IGNtYXBQbGF0Zm9ybUlkID0gY21hcFRhYmxlLnBsYXRmb3JtSWQ7CiAgICAgIGNvbnN0IGNtYXBFbmNvZGluZ0lkID0gY21hcFRhYmxlLmVuY29kaW5nSWQ7CiAgICAgIGNvbnN0IGNtYXBNYXBwaW5ncyA9IGNtYXBUYWJsZS5tYXBwaW5nczsKICAgICAgbGV0IGJhc2VFbmNvZGluZyA9IFtdLAogICAgICAgIGZvcmNlUG9zdFRhYmxlID0gZmFsc2U7CiAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc0VuY29kaW5nICYmIChwcm9wZXJ0aWVzLmJhc2VFbmNvZGluZ05hbWUgPT09ICJNYWNSb21hbkVuY29kaW5nIiB8fCBwcm9wZXJ0aWVzLmJhc2VFbmNvZGluZ05hbWUgPT09ICJXaW5BbnNpRW5jb2RpbmciKSkgewogICAgICAgIGJhc2VFbmNvZGluZyA9IGdldEVuY29kaW5nKHByb3BlcnRpZXMuYmFzZUVuY29kaW5nTmFtZSk7CiAgICAgIH0KICAgICAgaWYgKHByb3BlcnRpZXMuaGFzRW5jb2RpbmcgJiYgIXRoaXMuaXNTeW1ib2xpY0ZvbnQgJiYgKGNtYXBQbGF0Zm9ybUlkID09PSAzICYmIGNtYXBFbmNvZGluZ0lkID09PSAxIHx8IGNtYXBQbGF0Zm9ybUlkID09PSAxICYmIGNtYXBFbmNvZGluZ0lkID09PSAwKSkgewogICAgICAgIGNvbnN0IGdseXBoc1VuaWNvZGVNYXAgPSBnZXRHbHlwaHNVbmljb2RlKCk7CiAgICAgICAgZm9yIChsZXQgY2hhckNvZGUgPSAwOyBjaGFyQ29kZSA8IDI1NjsgY2hhckNvZGUrKykgewogICAgICAgICAgbGV0IGdseXBoTmFtZTsKICAgICAgICAgIGlmICh0aGlzLmRpZmZlcmVuY2VzW2NoYXJDb2RlXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGdseXBoTmFtZSA9IHRoaXMuZGlmZmVyZW5jZXNbY2hhckNvZGVdOwogICAgICAgICAgfSBlbHNlIGlmIChiYXNlRW5jb2RpbmcubGVuZ3RoICYmIGJhc2VFbmNvZGluZ1tjaGFyQ29kZV0gIT09ICIiKSB7CiAgICAgICAgICAgIGdseXBoTmFtZSA9IGJhc2VFbmNvZGluZ1tjaGFyQ29kZV07CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBnbHlwaE5hbWUgPSBTdGFuZGFyZEVuY29kaW5nW2NoYXJDb2RlXTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghZ2x5cGhOYW1lKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3Qgc3RhbmRhcmRHbHlwaE5hbWUgPSByZWNvdmVyR2x5cGhOYW1lKGdseXBoTmFtZSwgZ2x5cGhzVW5pY29kZU1hcCk7CiAgICAgICAgICBsZXQgdW5pY29kZU9yQ2hhckNvZGU7CiAgICAgICAgICBpZiAoY21hcFBsYXRmb3JtSWQgPT09IDMgJiYgY21hcEVuY29kaW5nSWQgPT09IDEpIHsKICAgICAgICAgICAgdW5pY29kZU9yQ2hhckNvZGUgPSBnbHlwaHNVbmljb2RlTWFwW3N0YW5kYXJkR2x5cGhOYW1lXTsKICAgICAgICAgIH0gZWxzZSBpZiAoY21hcFBsYXRmb3JtSWQgPT09IDEgJiYgY21hcEVuY29kaW5nSWQgPT09IDApIHsKICAgICAgICAgICAgdW5pY29kZU9yQ2hhckNvZGUgPSBNYWNSb21hbkVuY29kaW5nLmluZGV4T2Yoc3RhbmRhcmRHbHlwaE5hbWUpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHVuaWNvZGVPckNoYXJDb2RlID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgaWYgKCFwcm9wZXJ0aWVzLmdseXBoTmFtZXMgJiYgcHJvcGVydGllcy5oYXNJbmNsdWRlZFRvVW5pY29kZU1hcCAmJiAhKHRoaXMudG9Vbmljb2RlIGluc3RhbmNlb2YgSWRlbnRpdHlUb1VuaWNvZGVNYXApKSB7CiAgICAgICAgICAgICAgY29uc3QgdW5pY29kZSA9IHRoaXMudG9Vbmljb2RlLmdldChjaGFyQ29kZSk7CiAgICAgICAgICAgICAgaWYgKHVuaWNvZGUpIHsKICAgICAgICAgICAgICAgIHVuaWNvZGVPckNoYXJDb2RlID0gdW5pY29kZS5jb2RlUG9pbnRBdCgwKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHVuaWNvZGVPckNoYXJDb2RlID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZm9yIChjb25zdCBtYXBwaW5nIG9mIGNtYXBNYXBwaW5ncykgewogICAgICAgICAgICBpZiAobWFwcGluZy5jaGFyQ29kZSAhPT0gdW5pY29kZU9yQ2hhckNvZGUpIHsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBtYXBwaW5nLmdseXBoSWQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChjbWFwUGxhdGZvcm1JZCA9PT0gMCkgewogICAgICAgIGZvciAoY29uc3QgbWFwcGluZyBvZiBjbWFwTWFwcGluZ3MpIHsKICAgICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW21hcHBpbmcuY2hhckNvZGVdID0gbWFwcGluZy5nbHlwaElkOwogICAgICAgIH0KICAgICAgICBmb3JjZVBvc3RUYWJsZSA9IHRydWU7CiAgICAgIH0gZWxzZSBpZiAoY21hcFBsYXRmb3JtSWQgPT09IDMgJiYgY21hcEVuY29kaW5nSWQgPT09IDApIHsKICAgICAgICBmb3IgKGNvbnN0IG1hcHBpbmcgb2YgY21hcE1hcHBpbmdzKSB7CiAgICAgICAgICBsZXQgY2hhckNvZGUgPSBtYXBwaW5nLmNoYXJDb2RlOwogICAgICAgICAgaWYgKGNoYXJDb2RlID49IDB4ZjAwMCAmJiBjaGFyQ29kZSA8PSAweGYwZmYpIHsKICAgICAgICAgICAgY2hhckNvZGUgJj0gMHhmZjsKICAgICAgICAgIH0KICAgICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IG1hcHBpbmcuZ2x5cGhJZDsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yIChjb25zdCBtYXBwaW5nIG9mIGNtYXBNYXBwaW5ncykgewogICAgICAgICAgY2hhckNvZGVUb0dseXBoSWRbbWFwcGluZy5jaGFyQ29kZV0gPSBtYXBwaW5nLmdseXBoSWQ7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChwcm9wZXJ0aWVzLmdseXBoTmFtZXMgJiYgKGJhc2VFbmNvZGluZy5sZW5ndGggfHwgdGhpcy5kaWZmZXJlbmNlcy5sZW5ndGgpKSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAyNTY7ICsraSkgewogICAgICAgICAgaWYgKCFmb3JjZVBvc3RUYWJsZSAmJiBjaGFyQ29kZVRvR2x5cGhJZFtpXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgZ2x5cGhOYW1lID0gdGhpcy5kaWZmZXJlbmNlc1tpXSB8fCBiYXNlRW5jb2RpbmdbaV07CiAgICAgICAgICBpZiAoIWdseXBoTmFtZSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGdseXBoSWQgPSBwcm9wZXJ0aWVzLmdseXBoTmFtZXMuaW5kZXhPZihnbHlwaE5hbWUpOwogICAgICAgICAgaWYgKGdseXBoSWQgPiAwICYmIGhhc0dseXBoKGdseXBoSWQpKSB7CiAgICAgICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2ldID0gZ2x5cGhJZDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChjaGFyQ29kZVRvR2x5cGhJZC5sZW5ndGggPT09IDApIHsKICAgICAgY2hhckNvZGVUb0dseXBoSWRbMF0gPSAwOwogICAgfQogICAgbGV0IGdseXBoWmVyb0lkID0gbnVtR2x5cGhzT3V0IC0gMTsKICAgIGlmICghZHVwRmlyc3RFbnRyeSkgewogICAgICBnbHlwaFplcm9JZCA9IDA7CiAgICB9CiAgICBpZiAoIXByb3BlcnRpZXMuY3NzRm9udEluZm8pIHsKICAgICAgY29uc3QgbmV3TWFwcGluZyA9IGFkanVzdE1hcHBpbmcoY2hhckNvZGVUb0dseXBoSWQsIGhhc0dseXBoLCBnbHlwaFplcm9JZCwgdGhpcy50b1VuaWNvZGUpOwogICAgICB0aGlzLnRvRm9udENoYXIgPSBuZXdNYXBwaW5nLnRvRm9udENoYXI7CiAgICAgIHRhYmxlcy5jbWFwID0gewogICAgICAgIHRhZzogImNtYXAiLAogICAgICAgIGRhdGE6IGNyZWF0ZUNtYXBUYWJsZShuZXdNYXBwaW5nLmNoYXJDb2RlVG9HbHlwaElkLCBuZXdNYXBwaW5nLnRvVW5pY29kZUV4dHJhTWFwLCBudW1HbHlwaHNPdXQpCiAgICAgIH07CiAgICAgIGlmICghdGFibGVzWyJPUy8yIl0gfHwgIXZhbGlkYXRlT1MyVGFibGUodGFibGVzWyJPUy8yIl0sIGZvbnQpKSB7CiAgICAgICAgdGFibGVzWyJPUy8yIl0gPSB7CiAgICAgICAgICB0YWc6ICJPUy8yIiwKICAgICAgICAgIGRhdGE6IGNyZWF0ZU9TMlRhYmxlKHByb3BlcnRpZXMsIG5ld01hcHBpbmcuY2hhckNvZGVUb0dseXBoSWQsIG1ldHJpY3NPdmVycmlkZSkKICAgICAgICB9OwogICAgICB9CiAgICB9CiAgICBpZiAoIXRhYmxlcy5uYW1lKSB7CiAgICAgIHRhYmxlcy5uYW1lID0gewogICAgICAgIHRhZzogIm5hbWUiLAogICAgICAgIGRhdGE6IGNyZWF0ZU5hbWVUYWJsZSh0aGlzLm5hbWUpCiAgICAgIH07CiAgICB9IGVsc2UgewogICAgICBjb25zdCBbbmFtZVByb3RvdHlwZSwgbmFtZVJlY29yZHNdID0gcmVhZE5hbWVUYWJsZSh0YWJsZXMubmFtZSk7CiAgICAgIHRhYmxlcy5uYW1lLmRhdGEgPSBjcmVhdGVOYW1lVGFibGUobmFtZSwgbmFtZVByb3RvdHlwZSk7CiAgICAgIHRoaXMucHNOYW1lID0gbmFtZVByb3RvdHlwZVswXVs2XSB8fCBudWxsOwogICAgICBpZiAoIXByb3BlcnRpZXMuY29tcG9zaXRlKSB7CiAgICAgICAgYWRqdXN0VHJ1ZVR5cGVUb1VuaWNvZGUocHJvcGVydGllcywgdGhpcy5pc1N5bWJvbGljRm9udCwgbmFtZVJlY29yZHMpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBidWlsZGVyID0gbmV3IE9wZW5UeXBlRmlsZUJ1aWxkZXIoaGVhZGVyLnZlcnNpb24pOwogICAgZm9yIChjb25zdCB0YWJsZVRhZyBpbiB0YWJsZXMpIHsKICAgICAgYnVpbGRlci5hZGRUYWJsZSh0YWJsZVRhZywgdGFibGVzW3RhYmxlVGFnXS5kYXRhKTsKICAgIH0KICAgIHJldHVybiBidWlsZGVyLnRvQXJyYXkoKTsKICB9CiAgY29udmVydChmb250TmFtZSwgZm9udCwgcHJvcGVydGllcykgewogICAgcHJvcGVydGllcy5maXhlZFBpdGNoID0gZmFsc2U7CiAgICBpZiAocHJvcGVydGllcy5idWlsdEluRW5jb2RpbmcpIHsKICAgICAgYWRqdXN0VHlwZTFUb1VuaWNvZGUocHJvcGVydGllcywgcHJvcGVydGllcy5idWlsdEluRW5jb2RpbmcpOwogICAgfQogICAgbGV0IGdseXBoWmVyb0lkID0gMTsKICAgIGlmIChmb250IGluc3RhbmNlb2YgQ0ZGRm9udCkgewogICAgICBnbHlwaFplcm9JZCA9IGZvbnQubnVtR2x5cGhzIC0gMTsKICAgIH0KICAgIGNvbnN0IG1hcHBpbmcgPSBmb250LmdldEdseXBoTWFwcGluZyhwcm9wZXJ0aWVzKTsKICAgIGxldCBuZXdNYXBwaW5nID0gbnVsbDsKICAgIGxldCBuZXdDaGFyQ29kZVRvR2x5cGhJZCA9IG1hcHBpbmc7CiAgICBsZXQgdG9Vbmljb2RlRXh0cmFNYXAgPSBudWxsOwogICAgaWYgKCFwcm9wZXJ0aWVzLmNzc0ZvbnRJbmZvKSB7CiAgICAgIG5ld01hcHBpbmcgPSBhZGp1c3RNYXBwaW5nKG1hcHBpbmcsIGZvbnQuaGFzR2x5cGhJZC5iaW5kKGZvbnQpLCBnbHlwaFplcm9JZCwgdGhpcy50b1VuaWNvZGUpOwogICAgICB0aGlzLnRvRm9udENoYXIgPSBuZXdNYXBwaW5nLnRvRm9udENoYXI7CiAgICAgIG5ld0NoYXJDb2RlVG9HbHlwaElkID0gbmV3TWFwcGluZy5jaGFyQ29kZVRvR2x5cGhJZDsKICAgICAgdG9Vbmljb2RlRXh0cmFNYXAgPSBuZXdNYXBwaW5nLnRvVW5pY29kZUV4dHJhTWFwOwogICAgfQogICAgY29uc3QgbnVtR2x5cGhzID0gZm9udC5udW1HbHlwaHM7CiAgICBmdW5jdGlvbiBnZXRDaGFyQ29kZXMoY2hhckNvZGVUb0dseXBoSWQsIGdseXBoSWQpIHsKICAgICAgbGV0IGNoYXJDb2RlcyA9IG51bGw7CiAgICAgIGZvciAoY29uc3QgY2hhckNvZGUgaW4gY2hhckNvZGVUb0dseXBoSWQpIHsKICAgICAgICBpZiAoZ2x5cGhJZCA9PT0gY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdKSB7CiAgICAgICAgICAoY2hhckNvZGVzIHx8PSBbXSkucHVzaChjaGFyQ29kZSB8IDApOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gY2hhckNvZGVzOwogICAgfQogICAgZnVuY3Rpb24gY3JlYXRlQ2hhckNvZGUoY2hhckNvZGVUb0dseXBoSWQsIGdseXBoSWQpIHsKICAgICAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBjaGFyQ29kZVRvR2x5cGhJZCkgewogICAgICAgIGlmIChnbHlwaElkID09PSBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0pIHsKICAgICAgICAgIHJldHVybiBjaGFyQ29kZSB8IDA7CiAgICAgICAgfQogICAgICB9CiAgICAgIG5ld01hcHBpbmcuY2hhckNvZGVUb0dseXBoSWRbbmV3TWFwcGluZy5uZXh0QXZhaWxhYmxlRm9udENoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICAgIHJldHVybiBuZXdNYXBwaW5nLm5leHRBdmFpbGFibGVGb250Q2hhckNvZGUrKzsKICAgIH0KICAgIGNvbnN0IHNlYWNzID0gZm9udC5zZWFjczsKICAgIGlmIChuZXdNYXBwaW5nICYmIFNFQUNfQU5BTFlTSVNfRU5BQkxFRCAmJiBzZWFjcz8ubGVuZ3RoKSB7CiAgICAgIGNvbnN0IG1hdHJpeCA9IHByb3BlcnRpZXMuZm9udE1hdHJpeCB8fCBGT05UX0lERU5USVRZX01BVFJJWDsKICAgICAgY29uc3QgY2hhcnNldCA9IGZvbnQuZ2V0Q2hhcnNldCgpOwogICAgICBjb25zdCBzZWFjTWFwID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgZm9yIChsZXQgZ2x5cGhJZCBpbiBzZWFjcykgewogICAgICAgIGdseXBoSWQgfD0gMDsKICAgICAgICBjb25zdCBzZWFjID0gc2VhY3NbZ2x5cGhJZF07CiAgICAgICAgY29uc3QgYmFzZUdseXBoTmFtZSA9IFN0YW5kYXJkRW5jb2Rpbmdbc2VhY1syXV07CiAgICAgICAgY29uc3QgYWNjZW50R2x5cGhOYW1lID0gU3RhbmRhcmRFbmNvZGluZ1tzZWFjWzNdXTsKICAgICAgICBjb25zdCBiYXNlR2x5cGhJZCA9IGNoYXJzZXQuaW5kZXhPZihiYXNlR2x5cGhOYW1lKTsKICAgICAgICBjb25zdCBhY2NlbnRHbHlwaElkID0gY2hhcnNldC5pbmRleE9mKGFjY2VudEdseXBoTmFtZSk7CiAgICAgICAgaWYgKGJhc2VHbHlwaElkIDwgMCB8fCBhY2NlbnRHbHlwaElkIDwgMCkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGFjY2VudE9mZnNldCA9IHsKICAgICAgICAgIHg6IHNlYWNbMF0gKiBtYXRyaXhbMF0gKyBzZWFjWzFdICogbWF0cml4WzJdICsgbWF0cml4WzRdLAogICAgICAgICAgeTogc2VhY1swXSAqIG1hdHJpeFsxXSArIHNlYWNbMV0gKiBtYXRyaXhbM10gKyBtYXRyaXhbNV0KICAgICAgICB9OwogICAgICAgIGNvbnN0IGNoYXJDb2RlcyA9IGdldENoYXJDb2RlcyhtYXBwaW5nLCBnbHlwaElkKTsKICAgICAgICBpZiAoIWNoYXJDb2RlcykgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGZvciAoY29uc3QgY2hhckNvZGUgb2YgY2hhckNvZGVzKSB7CiAgICAgICAgICBjb25zdCBjaGFyQ29kZVRvR2x5cGhJZCA9IG5ld01hcHBpbmcuY2hhckNvZGVUb0dseXBoSWQ7CiAgICAgICAgICBjb25zdCBiYXNlRm9udENoYXJDb2RlID0gY3JlYXRlQ2hhckNvZGUoY2hhckNvZGVUb0dseXBoSWQsIGJhc2VHbHlwaElkKTsKICAgICAgICAgIGNvbnN0IGFjY2VudEZvbnRDaGFyQ29kZSA9IGNyZWF0ZUNoYXJDb2RlKGNoYXJDb2RlVG9HbHlwaElkLCBhY2NlbnRHbHlwaElkKTsKICAgICAgICAgIHNlYWNNYXBbY2hhckNvZGVdID0gewogICAgICAgICAgICBiYXNlRm9udENoYXJDb2RlLAogICAgICAgICAgICBhY2NlbnRGb250Q2hhckNvZGUsCiAgICAgICAgICAgIGFjY2VudE9mZnNldAogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcHJvcGVydGllcy5zZWFjTWFwID0gc2VhY01hcDsKICAgIH0KICAgIGNvbnN0IHVuaXRzUGVyRW0gPSBwcm9wZXJ0aWVzLmZvbnRNYXRyaXggPyAxIC8gTWF0aC5tYXgoLi4ucHJvcGVydGllcy5mb250TWF0cml4LnNsaWNlKDAsIDQpLm1hcChNYXRoLmFicykpIDogMTAwMDsKICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgT3BlblR5cGVGaWxlQnVpbGRlcigiXHg0Rlx4NTRceDU0XHg0RiIpOwogICAgYnVpbGRlci5hZGRUYWJsZSgiQ0ZGICIsIGZvbnQuZGF0YSk7CiAgICBidWlsZGVyLmFkZFRhYmxlKCJPUy8yIiwgY3JlYXRlT1MyVGFibGUocHJvcGVydGllcywgbmV3Q2hhckNvZGVUb0dseXBoSWQpKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoImNtYXAiLCBjcmVhdGVDbWFwVGFibGUobmV3Q2hhckNvZGVUb0dseXBoSWQsIHRvVW5pY29kZUV4dHJhTWFwLCBudW1HbHlwaHMpKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoImhlYWQiLCAiXHgwMFx4MDFceDAwXHgwMCIgKyAiXHgwMFx4MDBceDEwXHgwMCIgKyAiXHgwMFx4MDBceDAwXHgwMCIgKyAiXHg1Rlx4MEZceDNDXHhGNSIgKyAiXHgwMFx4MDAiICsgc2FmZVN0cmluZzE2KHVuaXRzUGVyRW0pICsgIlx4MDBceDAwXHgwMFx4MDBceDllXHgwYlx4N2VceDI3IiArICJceDAwXHgwMFx4MDBceDAwXHg5ZVx4MGJceDdlXHgyNyIgKyAiXHgwMFx4MDAiICsgc2FmZVN0cmluZzE2KHByb3BlcnRpZXMuZGVzY2VudCkgKyAiXHgwRlx4RkYiICsgc2FmZVN0cmluZzE2KHByb3BlcnRpZXMuYXNjZW50KSArIHN0cmluZzE2KHByb3BlcnRpZXMuaXRhbGljQW5nbGUgPyAyIDogMCkgKyAiXHgwMFx4MTEiICsgIlx4MDBceDAwIiArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoImhoZWEiLCAiXHgwMFx4MDFceDAwXHgwMCIgKyBzYWZlU3RyaW5nMTYocHJvcGVydGllcy5hc2NlbnQpICsgc2FmZVN0cmluZzE2KHByb3BlcnRpZXMuZGVzY2VudCkgKyAiXHgwMFx4MDAiICsgIlx4RkZceEZGIiArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiICsgIlx4MDBceDAwIiArIHNhZmVTdHJpbmcxNihwcm9wZXJ0aWVzLmNhcEhlaWdodCkgKyBzYWZlU3RyaW5nMTYoTWF0aC50YW4ocHJvcGVydGllcy5pdGFsaWNBbmdsZSkgKiBwcm9wZXJ0aWVzLnhIZWlnaHQpICsgIlx4MDBceDAwIiArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiICsgIlx4MDBceDAwIiArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiICsgc3RyaW5nMTYobnVtR2x5cGhzKSk7CiAgICBidWlsZGVyLmFkZFRhYmxlKCJobXR4IiwgZnVuY3Rpb24gZm9udEZpZWxkc0htdHgoKSB7CiAgICAgIGNvbnN0IGNoYXJzdHJpbmdzID0gZm9udC5jaGFyc3RyaW5nczsKICAgICAgY29uc3QgY2ZmV2lkdGhzID0gZm9udC5jZmYgPyBmb250LmNmZi53aWR0aHMgOiBudWxsOwogICAgICBsZXQgaG10eCA9ICJceDAwXHgwMFx4MDBceDAwIjsKICAgICAgZm9yIChsZXQgaSA9IDEsIGlpID0gbnVtR2x5cGhzOyBpIDwgaWk7IGkrKykgewogICAgICAgIGxldCB3aWR0aCA9IDA7CiAgICAgICAgaWYgKGNoYXJzdHJpbmdzKSB7CiAgICAgICAgICBjb25zdCBjaGFyc3RyaW5nID0gY2hhcnN0cmluZ3NbaSAtIDFdOwogICAgICAgICAgd2lkdGggPSAid2lkdGgiIGluIGNoYXJzdHJpbmcgPyBjaGFyc3RyaW5nLndpZHRoIDogMDsKICAgICAgICB9IGVsc2UgaWYgKGNmZldpZHRocykgewogICAgICAgICAgd2lkdGggPSBNYXRoLmNlaWwoY2ZmV2lkdGhzW2ldIHx8IDApOwogICAgICAgIH0KICAgICAgICBobXR4ICs9IHN0cmluZzE2KHdpZHRoKSArIHN0cmluZzE2KDApOwogICAgICB9CiAgICAgIHJldHVybiBobXR4OwogICAgfSgpKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoIm1heHAiLCAiXHgwMFx4MDBceDUwXHgwMCIgKyBzdHJpbmcxNihudW1HbHlwaHMpKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoIm5hbWUiLCBjcmVhdGVOYW1lVGFibGUoZm9udE5hbWUpKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoInBvc3QiLCBjcmVhdGVQb3N0VGFibGUocHJvcGVydGllcykpOwogICAgcmV0dXJuIGJ1aWxkZXIudG9BcnJheSgpOwogIH0KICBnZXQgX3NwYWNlV2lkdGgoKSB7CiAgICBjb25zdCBwb3NzaWJsZVNwYWNlUmVwbGFjZW1lbnRzID0gWyJzcGFjZSIsICJtaW51cyIsICJvbmUiLCAiaSIsICJJIl07CiAgICBsZXQgd2lkdGg7CiAgICBmb3IgKGNvbnN0IGdseXBoTmFtZSBvZiBwb3NzaWJsZVNwYWNlUmVwbGFjZW1lbnRzKSB7CiAgICAgIGlmIChnbHlwaE5hbWUgaW4gdGhpcy53aWR0aHMpIHsKICAgICAgICB3aWR0aCA9IHRoaXMud2lkdGhzW2dseXBoTmFtZV07CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY29uc3QgZ2x5cGhzVW5pY29kZU1hcCA9IGdldEdseXBoc1VuaWNvZGUoKTsKICAgICAgY29uc3QgZ2x5cGhVbmljb2RlID0gZ2x5cGhzVW5pY29kZU1hcFtnbHlwaE5hbWVdOwogICAgICBsZXQgY2hhcmNvZGUgPSAwOwogICAgICBpZiAodGhpcy5jb21wb3NpdGUgJiYgdGhpcy5jTWFwLmNvbnRhaW5zKGdseXBoVW5pY29kZSkpIHsKICAgICAgICBjaGFyY29kZSA9IHRoaXMuY01hcC5sb29rdXAoZ2x5cGhVbmljb2RlKTsKICAgICAgICBpZiAodHlwZW9mIGNoYXJjb2RlID09PSAic3RyaW5nIikgewogICAgICAgICAgY2hhcmNvZGUgPSBjb252ZXJ0Q2lkU3RyaW5nKGdseXBoVW5pY29kZSwgY2hhcmNvZGUpOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoIWNoYXJjb2RlICYmIHRoaXMudG9Vbmljb2RlKSB7CiAgICAgICAgY2hhcmNvZGUgPSB0aGlzLnRvVW5pY29kZS5jaGFyQ29kZU9mKGdseXBoVW5pY29kZSk7CiAgICAgIH0KICAgICAgaWYgKGNoYXJjb2RlIDw9IDApIHsKICAgICAgICBjaGFyY29kZSA9IGdseXBoVW5pY29kZTsKICAgICAgfQogICAgICB3aWR0aCA9IHRoaXMud2lkdGhzW2NoYXJjb2RlXTsKICAgICAgaWYgKHdpZHRoKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgIl9zcGFjZVdpZHRoIiwgd2lkdGggfHwgdGhpcy5kZWZhdWx0V2lkdGgpOwogIH0KICBfY2hhclRvR2x5cGgoY2hhcmNvZGUsIGlzU3BhY2UgPSBmYWxzZSkgewogICAgbGV0IGdseXBoID0gdGhpcy5fZ2x5cGhDYWNoZVtjaGFyY29kZV07CiAgICBpZiAoZ2x5cGg/LmlzU3BhY2UgPT09IGlzU3BhY2UpIHsKICAgICAgcmV0dXJuIGdseXBoOwogICAgfQogICAgbGV0IGZvbnRDaGFyQ29kZSwgd2lkdGgsIG9wZXJhdG9yTGlzdElkOwogICAgbGV0IHdpZHRoQ29kZSA9IGNoYXJjb2RlOwogICAgaWYgKHRoaXMuY01hcD8uY29udGFpbnMoY2hhcmNvZGUpKSB7CiAgICAgIHdpZHRoQ29kZSA9IHRoaXMuY01hcC5sb29rdXAoY2hhcmNvZGUpOwogICAgICBpZiAodHlwZW9mIHdpZHRoQ29kZSA9PT0gInN0cmluZyIpIHsKICAgICAgICB3aWR0aENvZGUgPSBjb252ZXJ0Q2lkU3RyaW5nKGNoYXJjb2RlLCB3aWR0aENvZGUpOwogICAgICB9CiAgICB9CiAgICB3aWR0aCA9IHRoaXMud2lkdGhzW3dpZHRoQ29kZV07CiAgICBpZiAodHlwZW9mIHdpZHRoICE9PSAibnVtYmVyIikgewogICAgICB3aWR0aCA9IHRoaXMuZGVmYXVsdFdpZHRoOwogICAgfQogICAgY29uc3Qgdm1ldHJpYyA9IHRoaXMudm1ldHJpY3M/Llt3aWR0aENvZGVdOwogICAgbGV0IHVuaWNvZGUgPSB0aGlzLnRvVW5pY29kZS5nZXQoY2hhcmNvZGUpIHx8IGNoYXJjb2RlOwogICAgaWYgKHR5cGVvZiB1bmljb2RlID09PSAibnVtYmVyIikgewogICAgICB1bmljb2RlID0gU3RyaW5nLmZyb21DaGFyQ29kZSh1bmljb2RlKTsKICAgIH0KICAgIGxldCBpc0luRm9udCA9IHRoaXMudG9Gb250Q2hhcltjaGFyY29kZV0gIT09IHVuZGVmaW5lZDsKICAgIGZvbnRDaGFyQ29kZSA9IHRoaXMudG9Gb250Q2hhcltjaGFyY29kZV0gfHwgY2hhcmNvZGU7CiAgICBpZiAodGhpcy5taXNzaW5nRmlsZSkgewogICAgICBjb25zdCBnbHlwaE5hbWUgPSB0aGlzLmRpZmZlcmVuY2VzW2NoYXJjb2RlXSB8fCB0aGlzLmRlZmF1bHRFbmNvZGluZ1tjaGFyY29kZV07CiAgICAgIGlmICgoZ2x5cGhOYW1lID09PSAiLm5vdGRlZiIgfHwgZ2x5cGhOYW1lID09PSAiIikgJiYgdGhpcy50eXBlID09PSAiVHlwZTEiKSB7CiAgICAgICAgZm9udENoYXJDb2RlID0gMHgyMDsKICAgICAgICBpZiAoZ2x5cGhOYW1lID09PSAiIikgewogICAgICAgICAgd2lkdGggfHw9IHRoaXMuX3NwYWNlV2lkdGg7CiAgICAgICAgICB1bmljb2RlID0gU3RyaW5nLmZyb21DaGFyQ29kZShmb250Q2hhckNvZGUpOwogICAgICAgIH0KICAgICAgfQogICAgICBmb250Q2hhckNvZGUgPSBtYXBTcGVjaWFsVW5pY29kZVZhbHVlcyhmb250Q2hhckNvZGUpOwogICAgfQogICAgaWYgKHRoaXMuaXNUeXBlM0ZvbnQpIHsKICAgICAgb3BlcmF0b3JMaXN0SWQgPSBmb250Q2hhckNvZGU7CiAgICB9CiAgICBsZXQgYWNjZW50ID0gbnVsbDsKICAgIGlmICh0aGlzLnNlYWNNYXA/LltjaGFyY29kZV0pIHsKICAgICAgaXNJbkZvbnQgPSB0cnVlOwogICAgICBjb25zdCBzZWFjID0gdGhpcy5zZWFjTWFwW2NoYXJjb2RlXTsKICAgICAgZm9udENoYXJDb2RlID0gc2VhYy5iYXNlRm9udENoYXJDb2RlOwogICAgICBhY2NlbnQgPSB7CiAgICAgICAgZm9udENoYXI6IFN0cmluZy5mcm9tQ29kZVBvaW50KHNlYWMuYWNjZW50Rm9udENoYXJDb2RlKSwKICAgICAgICBvZmZzZXQ6IHNlYWMuYWNjZW50T2Zmc2V0CiAgICAgIH07CiAgICB9CiAgICBsZXQgZm9udENoYXIgPSAiIjsKICAgIGlmICh0eXBlb2YgZm9udENoYXJDb2RlID09PSAibnVtYmVyIikgewogICAgICBpZiAoZm9udENoYXJDb2RlIDw9IDB4MTBmZmZmKSB7CiAgICAgICAgZm9udENoYXIgPSBTdHJpbmcuZnJvbUNvZGVQb2ludChmb250Q2hhckNvZGUpOwogICAgICB9IGVsc2UgewogICAgICAgIHdhcm4oYGNoYXJUb0dseXBoIC0gaW52YWxpZCBmb250Q2hhckNvZGU6ICR7Zm9udENoYXJDb2RlfWApOwogICAgICB9CiAgICB9CiAgICBpZiAodGhpcy5taXNzaW5nRmlsZSAmJiB0aGlzLnZlcnRpY2FsICYmIGZvbnRDaGFyLmxlbmd0aCA9PT0gMSkgewogICAgICBjb25zdCB2ZXJ0aWNhbCA9IGdldFZlcnRpY2FsUHJlc2VudGF0aW9uRm9ybSgpW2ZvbnRDaGFyLmNoYXJDb2RlQXQoMCldOwogICAgICBpZiAodmVydGljYWwpIHsKICAgICAgICBmb250Q2hhciA9IHVuaWNvZGUgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHZlcnRpY2FsKTsKICAgICAgfQogICAgfQogICAgZ2x5cGggPSBuZXcgZm9udHNfR2x5cGgoY2hhcmNvZGUsIGZvbnRDaGFyLCB1bmljb2RlLCBhY2NlbnQsIHdpZHRoLCB2bWV0cmljLCBvcGVyYXRvckxpc3RJZCwgaXNTcGFjZSwgaXNJbkZvbnQpOwogICAgcmV0dXJuIHRoaXMuX2dseXBoQ2FjaGVbY2hhcmNvZGVdID0gZ2x5cGg7CiAgfQogIGNoYXJzVG9HbHlwaHMoY2hhcnMpIHsKICAgIGxldCBnbHlwaHMgPSB0aGlzLl9jaGFyc0NhY2hlW2NoYXJzXTsKICAgIGlmIChnbHlwaHMpIHsKICAgICAgcmV0dXJuIGdseXBoczsKICAgIH0KICAgIGdseXBocyA9IFtdOwogICAgaWYgKHRoaXMuY01hcCkgewogICAgICBjb25zdCBjID0gT2JqZWN0LmNyZWF0ZShudWxsKSwKICAgICAgICBpaSA9IGNoYXJzLmxlbmd0aDsKICAgICAgbGV0IGkgPSAwOwogICAgICB3aGlsZSAoaSA8IGlpKSB7CiAgICAgICAgdGhpcy5jTWFwLnJlYWRDaGFyQ29kZShjaGFycywgaSwgYyk7CiAgICAgICAgY29uc3QgewogICAgICAgICAgY2hhcmNvZGUsCiAgICAgICAgICBsZW5ndGgKICAgICAgICB9ID0gYzsKICAgICAgICBpICs9IGxlbmd0aDsKICAgICAgICBjb25zdCBnbHlwaCA9IHRoaXMuX2NoYXJUb0dseXBoKGNoYXJjb2RlLCBsZW5ndGggPT09IDEgJiYgY2hhcnMuY2hhckNvZGVBdChpIC0gMSkgPT09IDB4MjApOwogICAgICAgIGdseXBocy5wdXNoKGdseXBoKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gY2hhcnMubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICAgIGNvbnN0IGNoYXJjb2RlID0gY2hhcnMuY2hhckNvZGVBdChpKTsKICAgICAgICBjb25zdCBnbHlwaCA9IHRoaXMuX2NoYXJUb0dseXBoKGNoYXJjb2RlLCBjaGFyY29kZSA9PT0gMHgyMCk7CiAgICAgICAgZ2x5cGhzLnB1c2goZ2x5cGgpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdGhpcy5fY2hhcnNDYWNoZVtjaGFyc10gPSBnbHlwaHM7CiAgfQogIGdldENoYXJQb3NpdGlvbnMoY2hhcnMpIHsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IFtdOwogICAgaWYgKHRoaXMuY01hcCkgewogICAgICBjb25zdCBjID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgbGV0IGkgPSAwOwogICAgICB3aGlsZSAoaSA8IGNoYXJzLmxlbmd0aCkgewogICAgICAgIHRoaXMuY01hcC5yZWFkQ2hhckNvZGUoY2hhcnMsIGksIGMpOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IGMubGVuZ3RoOwogICAgICAgIHBvc2l0aW9ucy5wdXNoKFtpLCBpICsgbGVuZ3RoXSk7CiAgICAgICAgaSArPSBsZW5ndGg7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGNoYXJzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgICBwb3NpdGlvbnMucHVzaChbaSwgaSArIDFdKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHBvc2l0aW9uczsKICB9CiAgZ2V0IGdseXBoQ2FjaGVWYWx1ZXMoKSB7CiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLl9nbHlwaENhY2hlKTsKICB9CiAgZW5jb2RlU3RyaW5nKHN0cikgewogICAgY29uc3QgYnVmZmVycyA9IFtdOwogICAgY29uc3QgY3VycmVudEJ1ZiA9IFtdOwogICAgY29uc3QgaGFzQ3VycmVudEJ1ZkVycm9ycyA9ICgpID0+IGJ1ZmZlcnMubGVuZ3RoICUgMiA9PT0gMTsKICAgIGNvbnN0IGdldENoYXJDb2RlID0gdGhpcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBJZGVudGl0eVRvVW5pY29kZU1hcCA/IHVuaWNvZGUgPT4gdGhpcy50b1VuaWNvZGUuY2hhckNvZGVPZih1bmljb2RlKSA6IHVuaWNvZGUgPT4gdGhpcy50b1VuaWNvZGUuY2hhckNvZGVPZihTdHJpbmcuZnJvbUNvZGVQb2ludCh1bmljb2RlKSk7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzdHIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCB1bmljb2RlID0gc3RyLmNvZGVQb2ludEF0KGkpOwogICAgICBpZiAodW5pY29kZSA+IDB4ZDdmZiAmJiAodW5pY29kZSA8IDB4ZTAwMCB8fCB1bmljb2RlID4gMHhmZmZkKSkgewogICAgICAgIGkrKzsKICAgICAgfQogICAgICBpZiAodGhpcy50b1VuaWNvZGUpIHsKICAgICAgICBjb25zdCBjaGFyQ29kZSA9IGdldENoYXJDb2RlKHVuaWNvZGUpOwogICAgICAgIGlmIChjaGFyQ29kZSAhPT0gLTEpIHsKICAgICAgICAgIGlmIChoYXNDdXJyZW50QnVmRXJyb3JzKCkpIHsKICAgICAgICAgICAgYnVmZmVycy5wdXNoKGN1cnJlbnRCdWYuam9pbigiIikpOwogICAgICAgICAgICBjdXJyZW50QnVmLmxlbmd0aCA9IDA7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBjaGFyQ29kZUxlbmd0aCA9IHRoaXMuY01hcCA/IHRoaXMuY01hcC5nZXRDaGFyQ29kZUxlbmd0aChjaGFyQ29kZSkgOiAxOwogICAgICAgICAgZm9yIChsZXQgaiA9IGNoYXJDb2RlTGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHsKICAgICAgICAgICAgY3VycmVudEJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhckNvZGUgPj4gOCAqIGogJiAweGZmKSk7CiAgICAgICAgICB9CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCFoYXNDdXJyZW50QnVmRXJyb3JzKCkpIHsKICAgICAgICBidWZmZXJzLnB1c2goY3VycmVudEJ1Zi5qb2luKCIiKSk7CiAgICAgICAgY3VycmVudEJ1Zi5sZW5ndGggPSAwOwogICAgICB9CiAgICAgIGN1cnJlbnRCdWYucHVzaChTdHJpbmcuZnJvbUNvZGVQb2ludCh1bmljb2RlKSk7CiAgICB9CiAgICBidWZmZXJzLnB1c2goY3VycmVudEJ1Zi5qb2luKCIiKSk7CiAgICByZXR1cm4gYnVmZmVyczsKICB9Cn0KY2xhc3MgRXJyb3JGb250IHsKICBjb25zdHJ1Y3RvcihlcnJvcikgewogICAgdGhpcy5lcnJvciA9IGVycm9yOwogICAgdGhpcy5sb2FkZWROYW1lID0gImdfZm9udF9lcnJvciI7CiAgICB0aGlzLm1pc3NpbmdGaWxlID0gdHJ1ZTsKICB9CiAgY2hhcnNUb0dseXBocygpIHsKICAgIHJldHVybiBbXTsKICB9CiAgZW5jb2RlU3RyaW5nKGNoYXJzKSB7CiAgICByZXR1cm4gW2NoYXJzXTsKICB9CiAgZXhwb3J0RGF0YSgpIHsKICAgIHJldHVybiB7CiAgICAgIGVycm9yOiB0aGlzLmVycm9yCiAgICB9OwogIH0KfQoKOy8vIC4vc3JjL3NoYXJlZC9vYmotYmluLXRyYW5zZm9ybS5qcwoKY2xhc3MgQ3NzRm9udEluZm8gewogICNidWZmZXI7CiAgI3ZpZXc7CiAgI2RlY29kZXI7CiAgc3RhdGljIHN0cmluZ3MgPSBbImZvbnRGYW1pbHkiLCAiZm9udFdlaWdodCIsICJpdGFsaWNBbmdsZSJdOwogIHN0YXRpYyB3cml0ZShpbmZvKSB7CiAgICBjb25zdCBlbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKCk7CiAgICBjb25zdCBlbmNvZGVkU3RyaW5ncyA9IHt9OwogICAgbGV0IHN0cmluZ3NMZW5ndGggPSAwOwogICAgZm9yIChjb25zdCBwcm9wIG9mIENzc0ZvbnRJbmZvLnN0cmluZ3MpIHsKICAgICAgY29uc3QgZW5jb2RlZCA9IGVuY29kZXIuZW5jb2RlKGluZm9bcHJvcF0pOwogICAgICBlbmNvZGVkU3RyaW5nc1twcm9wXSA9IGVuY29kZWQ7CiAgICAgIHN0cmluZ3NMZW5ndGggKz0gNCArIGVuY29kZWQubGVuZ3RoOwogICAgfQogICAgY29uc3QgYnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKHN0cmluZ3NMZW5ndGgpOwogICAgY29uc3QgZGF0YSA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlcik7CiAgICBjb25zdCB2aWV3ID0gbmV3IERhdGFWaWV3KGJ1ZmZlcik7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIGZvciAoY29uc3QgcHJvcCBvZiBDc3NGb250SW5mby5zdHJpbmdzKSB7CiAgICAgIGNvbnN0IGVuY29kZWQgPSBlbmNvZGVkU3RyaW5nc1twcm9wXTsKICAgICAgY29uc3QgbGVuZ3RoID0gZW5jb2RlZC5sZW5ndGg7CiAgICAgIHZpZXcuc2V0VWludDMyKG9mZnNldCwgbGVuZ3RoKTsKICAgICAgZGF0YS5zZXQoZW5jb2RlZCwgb2Zmc2V0ICsgNCk7CiAgICAgIG9mZnNldCArPSA0ICsgbGVuZ3RoOwogICAgfQogICAgYXNzZXJ0KG9mZnNldCA9PT0gYnVmZmVyLmJ5dGVMZW5ndGgsICJDc3NGb250SW5mby53cml0ZTogQnVmZmVyIG92ZXJmbG93Iik7CiAgICByZXR1cm4gYnVmZmVyOwogIH0KICBjb25zdHJ1Y3RvcihidWZmZXIpIHsKICAgIHRoaXMuI2J1ZmZlciA9IGJ1ZmZlcjsKICAgIHRoaXMuI3ZpZXcgPSBuZXcgRGF0YVZpZXcodGhpcy4jYnVmZmVyKTsKICAgIHRoaXMuI2RlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTsKICB9CiAgI3JlYWRTdHJpbmcoaW5kZXgpIHsKICAgIGFzc2VydChpbmRleCA8IENzc0ZvbnRJbmZvLnN0cmluZ3MubGVuZ3RoLCAiSW52YWxpZCBzdHJpbmcgaW5kZXgiKTsKICAgIGxldCBvZmZzZXQgPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbmRleDsgaSsrKSB7CiAgICAgIG9mZnNldCArPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpICsgNDsKICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICByZXR1cm4gdGhpcy4jZGVjb2Rlci5kZWNvZGUobmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBsZW5ndGgpKTsKICB9CiAgZ2V0IGZvbnRGYW1pbHkoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZFN0cmluZygwKTsKICB9CiAgZ2V0IGZvbnRXZWlnaHQoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZFN0cmluZygxKTsKICB9CiAgZ2V0IGl0YWxpY0FuZ2xlKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRTdHJpbmcoMik7CiAgfQp9CmNsYXNzIFN5c3RlbUZvbnRJbmZvIHsKICAjYnVmZmVyOwogICN2aWV3OwogICNkZWNvZGVyOwogIHN0YXRpYyBzdHJpbmdzID0gWyJjc3MiLCAibG9hZGVkTmFtZSIsICJiYXNlRm9udE5hbWUiLCAic3JjIl07CiAgc3RhdGljIHdyaXRlKGluZm8pIHsKICAgIGNvbnN0IGVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKTsKICAgIGNvbnN0IGVuY29kZWRTdHJpbmdzID0ge307CiAgICBsZXQgc3RyaW5nc0xlbmd0aCA9IDA7CiAgICBmb3IgKGNvbnN0IHByb3Agb2YgU3lzdGVtRm9udEluZm8uc3RyaW5ncykgewogICAgICBjb25zdCBlbmNvZGVkID0gZW5jb2Rlci5lbmNvZGUoaW5mb1twcm9wXSk7CiAgICAgIGVuY29kZWRTdHJpbmdzW3Byb3BdID0gZW5jb2RlZDsKICAgICAgc3RyaW5nc0xlbmd0aCArPSA0ICsgZW5jb2RlZC5sZW5ndGg7CiAgICB9CiAgICBzdHJpbmdzTGVuZ3RoICs9IDQ7CiAgICBsZXQgZW5jb2RlZFN0eWxlU3R5bGUsCiAgICAgIGVuY29kZWRTdHlsZVdlaWdodCwKICAgICAgbGVuZ3RoRXN0aW1hdGUgPSAxICsgc3RyaW5nc0xlbmd0aDsKICAgIGlmIChpbmZvLnN0eWxlKSB7CiAgICAgIGVuY29kZWRTdHlsZVN0eWxlID0gZW5jb2Rlci5lbmNvZGUoaW5mby5zdHlsZS5zdHlsZSk7CiAgICAgIGVuY29kZWRTdHlsZVdlaWdodCA9IGVuY29kZXIuZW5jb2RlKGluZm8uc3R5bGUud2VpZ2h0KTsKICAgICAgbGVuZ3RoRXN0aW1hdGUgKz0gNCArIGVuY29kZWRTdHlsZVN0eWxlLmxlbmd0aCArIDQgKyBlbmNvZGVkU3R5bGVXZWlnaHQubGVuZ3RoOwogICAgfQogICAgY29uc3QgYnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKGxlbmd0aEVzdGltYXRlKTsKICAgIGNvbnN0IGRhdGEgPSBuZXcgVWludDhBcnJheShidWZmZXIpOwogICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhidWZmZXIpOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICB2aWV3LnNldFVpbnQ4KG9mZnNldCsrLCBpbmZvLmd1ZXNzRmFsbGJhY2sgPyAxIDogMCk7CiAgICB2aWV3LnNldFVpbnQzMihvZmZzZXQsIDApOwogICAgb2Zmc2V0ICs9IDQ7CiAgICBzdHJpbmdzTGVuZ3RoID0gMDsKICAgIGZvciAoY29uc3QgcHJvcCBvZiBTeXN0ZW1Gb250SW5mby5zdHJpbmdzKSB7CiAgICAgIGNvbnN0IGVuY29kZWQgPSBlbmNvZGVkU3RyaW5nc1twcm9wXTsKICAgICAgY29uc3QgbGVuZ3RoID0gZW5jb2RlZC5sZW5ndGg7CiAgICAgIHN0cmluZ3NMZW5ndGggKz0gNCArIGxlbmd0aDsKICAgICAgdmlldy5zZXRVaW50MzIob2Zmc2V0LCBsZW5ndGgpOwogICAgICBkYXRhLnNldChlbmNvZGVkLCBvZmZzZXQgKyA0KTsKICAgICAgb2Zmc2V0ICs9IDQgKyBsZW5ndGg7CiAgICB9CiAgICB2aWV3LnNldFVpbnQzMihvZmZzZXQgLSBzdHJpbmdzTGVuZ3RoIC0gNCwgc3RyaW5nc0xlbmd0aCk7CiAgICBpZiAoaW5mby5zdHlsZSkgewogICAgICB2aWV3LnNldFVpbnQzMihvZmZzZXQsIGVuY29kZWRTdHlsZVN0eWxlLmxlbmd0aCk7CiAgICAgIGRhdGEuc2V0KGVuY29kZWRTdHlsZVN0eWxlLCBvZmZzZXQgKyA0KTsKICAgICAgb2Zmc2V0ICs9IDQgKyBlbmNvZGVkU3R5bGVTdHlsZS5sZW5ndGg7CiAgICAgIHZpZXcuc2V0VWludDMyKG9mZnNldCwgZW5jb2RlZFN0eWxlV2VpZ2h0Lmxlbmd0aCk7CiAgICAgIGRhdGEuc2V0KGVuY29kZWRTdHlsZVdlaWdodCwgb2Zmc2V0ICsgNCk7CiAgICAgIG9mZnNldCArPSA0ICsgZW5jb2RlZFN0eWxlV2VpZ2h0Lmxlbmd0aDsKICAgIH0KICAgIGFzc2VydChvZmZzZXQgPD0gYnVmZmVyLmJ5dGVMZW5ndGgsICJTdWJzdGl0aW9uSW5mby53cml0ZTogQnVmZmVyIG92ZXJmbG93Iik7CiAgICByZXR1cm4gYnVmZmVyLnRyYW5zZmVyVG9GaXhlZExlbmd0aChvZmZzZXQpOwogIH0KICBjb25zdHJ1Y3RvcihidWZmZXIpIHsKICAgIHRoaXMuI2J1ZmZlciA9IGJ1ZmZlcjsKICAgIHRoaXMuI3ZpZXcgPSBuZXcgRGF0YVZpZXcodGhpcy4jYnVmZmVyKTsKICAgIHRoaXMuI2RlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTsKICB9CiAgZ2V0IGd1ZXNzRmFsbGJhY2soKSB7CiAgICByZXR1cm4gdGhpcy4jdmlldy5nZXRVaW50OCgwKSAhPT0gMDsKICB9CiAgI3JlYWRTdHJpbmcoaW5kZXgpIHsKICAgIGFzc2VydChpbmRleCA8IFN5c3RlbUZvbnRJbmZvLnN0cmluZ3MubGVuZ3RoLCAiSW52YWxpZCBzdHJpbmcgaW5kZXgiKTsKICAgIGxldCBvZmZzZXQgPSA1OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbmRleDsgaSsrKSB7CiAgICAgIG9mZnNldCArPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpICsgNDsKICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICByZXR1cm4gdGhpcy4jZGVjb2Rlci5kZWNvZGUobmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBsZW5ndGgpKTsKICB9CiAgZ2V0IGNzcygpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkU3RyaW5nKDApOwogIH0KICBnZXQgbG9hZGVkTmFtZSgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkU3RyaW5nKDEpOwogIH0KICBnZXQgYmFzZUZvbnROYW1lKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRTdHJpbmcoMik7CiAgfQogIGdldCBzcmMoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZFN0cmluZygzKTsKICB9CiAgZ2V0IHN0eWxlKCkgewogICAgbGV0IG9mZnNldCA9IDE7CiAgICBvZmZzZXQgKz0gNCArIHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBjb25zdCBzdHlsZUxlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBjb25zdCBzdHlsZSA9IHRoaXMuI2RlY29kZXIuZGVjb2RlKG5ldyBVaW50OEFycmF5KHRoaXMuI2J1ZmZlciwgb2Zmc2V0ICsgNCwgc3R5bGVMZW5ndGgpKTsKICAgIG9mZnNldCArPSA0ICsgc3R5bGVMZW5ndGg7CiAgICBjb25zdCB3ZWlnaHRMZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgY29uc3Qgd2VpZ2h0ID0gdGhpcy4jZGVjb2Rlci5kZWNvZGUobmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCB3ZWlnaHRMZW5ndGgpKTsKICAgIHJldHVybiB7CiAgICAgIHN0eWxlLAogICAgICB3ZWlnaHQKICAgIH07CiAgfQp9CmNsYXNzIEZvbnRJbmZvIHsKICBzdGF0aWMgYm9vbHMgPSBbImJsYWNrIiwgImJvbGQiLCAiZGlzYWJsZUZvbnRGYWNlIiwgImZvbnRFeHRyYVByb3BlcnRpZXMiLCAiaXNJbnZhbGlkUERGanNGb250IiwgImlzVHlwZTNGb250IiwgIml0YWxpYyIsICJtaXNzaW5nRmlsZSIsICJyZW1lYXN1cmUiLCAidmVydGljYWwiXTsKICBzdGF0aWMgbnVtYmVycyA9IFsiYXNjZW50IiwgImRlZmF1bHRXaWR0aCIsICJkZXNjZW50Il07CiAgc3RhdGljIHN0cmluZ3MgPSBbImZhbGxiYWNrTmFtZSIsICJsb2FkZWROYW1lIiwgIm1pbWV0eXBlIiwgIm5hbWUiXTsKICBzdGF0aWMgI09GRlNFVF9OVU1CRVJTID0gTWF0aC5jZWlsKHRoaXMuYm9vbHMubGVuZ3RoICogMiAvIDgpOwogIHN0YXRpYyAjT0ZGU0VUX0JCT1ggPSB0aGlzLiNPRkZTRVRfTlVNQkVSUyArIHRoaXMubnVtYmVycy5sZW5ndGggKiA4OwogIHN0YXRpYyAjT0ZGU0VUX0ZPTlRfTUFUUklYID0gdGhpcy4jT0ZGU0VUX0JCT1ggKyAxICsgMiAqIDQ7CiAgc3RhdGljICNPRkZTRVRfREVGQVVMVF9WTUVUUklDUyA9IHRoaXMuI09GRlNFVF9GT05UX01BVFJJWCArIDEgKyA4ICogNjsKICBzdGF0aWMgI09GRlNFVF9TVFJJTkdTID0gdGhpcy4jT0ZGU0VUX0RFRkFVTFRfVk1FVFJJQ1MgKyAxICsgMiAqIDM7CiAgI2J1ZmZlcjsKICAjZGVjb2RlcjsKICAjdmlldzsKICBjb25zdHJ1Y3Rvcih7CiAgICBkYXRhLAogICAgZXh0cmEKICB9KSB7CiAgICB0aGlzLiNidWZmZXIgPSBkYXRhOwogICAgdGhpcy4jZGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigpOwogICAgdGhpcy4jdmlldyA9IG5ldyBEYXRhVmlldyh0aGlzLiNidWZmZXIpOwogICAgaWYgKGV4dHJhKSB7CiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgZXh0cmEpOwogICAgfQogIH0KICAjcmVhZEJvb2xlYW4oaW5kZXgpIHsKICAgIGFzc2VydChpbmRleCA8IEZvbnRJbmZvLmJvb2xzLmxlbmd0aCwgIkludmFsaWQgYm9vbGVhbiBpbmRleCIpOwogICAgY29uc3QgYnl0ZU9mZnNldCA9IE1hdGguZmxvb3IoaW5kZXggLyA0KTsKICAgIGNvbnN0IGJpdE9mZnNldCA9IGluZGV4ICogMiAlIDg7CiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuI3ZpZXcuZ2V0VWludDgoYnl0ZU9mZnNldCkgPj4gYml0T2Zmc2V0ICYgMHgwMzsKICAgIHJldHVybiB2YWx1ZSA9PT0gMHgwMCA/IHVuZGVmaW5lZCA6IHZhbHVlID09PSAweDAyOwogIH0KICBnZXQgYmxhY2soKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZEJvb2xlYW4oMCk7CiAgfQogIGdldCBib2xkKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRCb29sZWFuKDEpOwogIH0KICBnZXQgZGlzYWJsZUZvbnRGYWNlKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRCb29sZWFuKDIpOwogIH0KICBnZXQgZm9udEV4dHJhUHJvcGVydGllcygpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkQm9vbGVhbigzKTsKICB9CiAgZ2V0IGlzSW52YWxpZFBERmpzRm9udCgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkQm9vbGVhbig0KTsKICB9CiAgZ2V0IGlzVHlwZTNGb250KCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRCb29sZWFuKDUpOwogIH0KICBnZXQgaXRhbGljKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRCb29sZWFuKDYpOwogIH0KICBnZXQgbWlzc2luZ0ZpbGUoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZEJvb2xlYW4oNyk7CiAgfQogIGdldCByZW1lYXN1cmUoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZEJvb2xlYW4oOCk7CiAgfQogIGdldCB2ZXJ0aWNhbCgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkQm9vbGVhbig5KTsKICB9CiAgI3JlYWROdW1iZXIoaW5kZXgpIHsKICAgIGFzc2VydChpbmRleCA8IEZvbnRJbmZvLm51bWJlcnMubGVuZ3RoLCAiSW52YWxpZCBudW1iZXIgaW5kZXgiKTsKICAgIHJldHVybiB0aGlzLiN2aWV3LmdldEZsb2F0NjQoRm9udEluZm8uI09GRlNFVF9OVU1CRVJTICsgaW5kZXggKiA4KTsKICB9CiAgZ2V0IGFzY2VudCgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkTnVtYmVyKDApOwogIH0KICBnZXQgZGVmYXVsdFdpZHRoKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWROdW1iZXIoMSk7CiAgfQogIGdldCBkZXNjZW50KCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWROdW1iZXIoMik7CiAgfQogIGdldCBiYm94KCkgewogICAgbGV0IG9mZnNldCA9IEZvbnRJbmZvLiNPRkZTRVRfQkJPWDsKICAgIGNvbnN0IG51bUNvb3JkcyA9IHRoaXMuI3ZpZXcuZ2V0VWludDgob2Zmc2V0KTsKICAgIGlmIChudW1Db29yZHMgPT09IDApIHsKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH0KICAgIG9mZnNldCArPSAxOwogICAgY29uc3QgYmJveCA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCA0OyBpKyspIHsKICAgICAgYmJveC5wdXNoKHRoaXMuI3ZpZXcuZ2V0SW50MTYob2Zmc2V0LCB0cnVlKSk7CiAgICAgIG9mZnNldCArPSAyOwogICAgfQogICAgcmV0dXJuIGJib3g7CiAgfQogIGdldCBmb250TWF0cml4KCkgewogICAgbGV0IG9mZnNldCA9IEZvbnRJbmZvLiNPRkZTRVRfRk9OVF9NQVRSSVg7CiAgICBjb25zdCBudW1Qb2ludHMgPSB0aGlzLiN2aWV3LmdldFVpbnQ4KG9mZnNldCk7CiAgICBpZiAobnVtUG9pbnRzID09PSAwKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICBvZmZzZXQgKz0gMTsKICAgIGNvbnN0IGZvbnRNYXRyaXggPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNjsgaSsrKSB7CiAgICAgIGZvbnRNYXRyaXgucHVzaCh0aGlzLiN2aWV3LmdldEZsb2F0NjQob2Zmc2V0LCB0cnVlKSk7CiAgICAgIG9mZnNldCArPSA4OwogICAgfQogICAgcmV0dXJuIGZvbnRNYXRyaXg7CiAgfQogIGdldCBkZWZhdWx0Vk1ldHJpY3MoKSB7CiAgICBsZXQgb2Zmc2V0ID0gRm9udEluZm8uI09GRlNFVF9ERUZBVUxUX1ZNRVRSSUNTOwogICAgY29uc3QgbnVtTWV0cmljcyA9IHRoaXMuI3ZpZXcuZ2V0VWludDgob2Zmc2V0KTsKICAgIGlmIChudW1NZXRyaWNzID09PSAwKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICBvZmZzZXQgKz0gMTsKICAgIGNvbnN0IGRlZmF1bHRWTWV0cmljcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzOyBpKyspIHsKICAgICAgZGVmYXVsdFZNZXRyaWNzLnB1c2godGhpcy4jdmlldy5nZXRJbnQxNihvZmZzZXQsIHRydWUpKTsKICAgICAgb2Zmc2V0ICs9IDI7CiAgICB9CiAgICByZXR1cm4gZGVmYXVsdFZNZXRyaWNzOwogIH0KICAjcmVhZFN0cmluZyhpbmRleCkgewogICAgYXNzZXJ0KGluZGV4IDwgRm9udEluZm8uc3RyaW5ncy5sZW5ndGgsICJJbnZhbGlkIHN0cmluZyBpbmRleCIpOwogICAgbGV0IG9mZnNldCA9IEZvbnRJbmZvLiNPRkZTRVRfU1RSSU5HUyArIDQ7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluZGV4OyBpKyspIHsKICAgICAgb2Zmc2V0ICs9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCkgKyA0OwogICAgfQogICAgY29uc3QgbGVuZ3RoID0gdGhpcy4jdmlldy5nZXRVaW50MzIob2Zmc2V0KTsKICAgIGNvbnN0IHN0cmluZ0RhdGEgPSBuZXcgVWludDhBcnJheShsZW5ndGgpOwogICAgc3RyaW5nRGF0YS5zZXQobmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBsZW5ndGgpKTsKICAgIHJldHVybiB0aGlzLiNkZWNvZGVyLmRlY29kZShzdHJpbmdEYXRhKTsKICB9CiAgZ2V0IGZhbGxiYWNrTmFtZSgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkU3RyaW5nKDApOwogIH0KICBnZXQgbG9hZGVkTmFtZSgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkU3RyaW5nKDEpOwogIH0KICBnZXQgbWltZXR5cGUoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZFN0cmluZygyKTsKICB9CiAgZ2V0IG5hbWUoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZFN0cmluZygzKTsKICB9CiAgZ2V0IGRhdGEoKSB7CiAgICBsZXQgb2Zmc2V0ID0gRm9udEluZm8uI09GRlNFVF9TVFJJTkdTOwogICAgY29uc3Qgc3RyaW5nc0xlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBvZmZzZXQgKz0gNCArIHN0cmluZ3NMZW5ndGg7CiAgICBjb25zdCBzeXN0ZW1Gb250SW5mb0xlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBvZmZzZXQgKz0gNCArIHN5c3RlbUZvbnRJbmZvTGVuZ3RoOwogICAgY29uc3QgY3NzRm9udEluZm9MZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDQgKyBjc3NGb250SW5mb0xlbmd0aDsKICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBsZW5ndGgpOwogIH0KICBjbGVhckRhdGEoKSB7CiAgICBsZXQgb2Zmc2V0ID0gRm9udEluZm8uI09GRlNFVF9TVFJJTkdTOwogICAgY29uc3Qgc3RyaW5nc0xlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBvZmZzZXQgKz0gNCArIHN0cmluZ3NMZW5ndGg7CiAgICBjb25zdCBzeXN0ZW1Gb250SW5mb0xlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBvZmZzZXQgKz0gNCArIHN5c3RlbUZvbnRJbmZvTGVuZ3RoOwogICAgY29uc3QgY3NzRm9udEluZm9MZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDQgKyBjc3NGb250SW5mb0xlbmd0aDsKICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBsZW5ndGgpOwogICAgZGF0YS5maWxsKDApOwogICAgdGhpcy4jdmlldy5zZXRVaW50MzIob2Zmc2V0LCAwKTsKICB9CiAgZ2V0IGNzc0ZvbnRJbmZvKCkgewogICAgbGV0IG9mZnNldCA9IEZvbnRJbmZvLiNPRkZTRVRfU1RSSU5HUzsKICAgIGNvbnN0IHN0cmluZ3NMZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDQgKyBzdHJpbmdzTGVuZ3RoOwogICAgY29uc3Qgc3lzdGVtRm9udEluZm9MZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDQgKyBzeXN0ZW1Gb250SW5mb0xlbmd0aDsKICAgIGNvbnN0IGNzc0ZvbnRJbmZvTGVuZ3RoID0gdGhpcy4jdmlldy5nZXRVaW50MzIob2Zmc2V0KTsKICAgIGlmIChjc3NGb250SW5mb0xlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGNzc0ZvbnRJbmZvRGF0YSA9IG5ldyBVaW50OEFycmF5KGNzc0ZvbnRJbmZvTGVuZ3RoKTsKICAgIGNzc0ZvbnRJbmZvRGF0YS5zZXQobmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBjc3NGb250SW5mb0xlbmd0aCkpOwogICAgcmV0dXJuIG5ldyBDc3NGb250SW5mbyhjc3NGb250SW5mb0RhdGEuYnVmZmVyKTsKICB9CiAgZ2V0IHN5c3RlbUZvbnRJbmZvKCkgewogICAgbGV0IG9mZnNldCA9IEZvbnRJbmZvLiNPRkZTRVRfU1RSSU5HUzsKICAgIGNvbnN0IHN0cmluZ3NMZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDQgKyBzdHJpbmdzTGVuZ3RoOwogICAgY29uc3Qgc3lzdGVtRm9udEluZm9MZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgaWYgKHN5c3RlbUZvbnRJbmZvTGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3Qgc3lzdGVtRm9udEluZm9EYXRhID0gbmV3IFVpbnQ4QXJyYXkoc3lzdGVtRm9udEluZm9MZW5ndGgpOwogICAgc3lzdGVtRm9udEluZm9EYXRhLnNldChuZXcgVWludDhBcnJheSh0aGlzLiNidWZmZXIsIG9mZnNldCArIDQsIHN5c3RlbUZvbnRJbmZvTGVuZ3RoKSk7CiAgICByZXR1cm4gbmV3IFN5c3RlbUZvbnRJbmZvKHN5c3RlbUZvbnRJbmZvRGF0YS5idWZmZXIpOwogIH0KICBzdGF0aWMgd3JpdGUoZm9udCkgewogICAgY29uc3Qgc3lzdGVtRm9udEluZm9CdWZmZXIgPSBmb250LnN5c3RlbUZvbnRJbmZvID8gU3lzdGVtRm9udEluZm8ud3JpdGUoZm9udC5zeXN0ZW1Gb250SW5mbykgOiBudWxsOwogICAgY29uc3QgY3NzRm9udEluZm9CdWZmZXIgPSBmb250LmNzc0ZvbnRJbmZvID8gQ3NzRm9udEluZm8ud3JpdGUoZm9udC5jc3NGb250SW5mbykgOiBudWxsOwogICAgY29uc3QgZW5jb2RlciA9IG5ldyBUZXh0RW5jb2RlcigpOwogICAgY29uc3QgZW5jb2RlZFN0cmluZ3MgPSB7fTsKICAgIGxldCBzdHJpbmdzTGVuZ3RoID0gMDsKICAgIGZvciAoY29uc3QgcHJvcCBvZiBGb250SW5mby5zdHJpbmdzKSB7CiAgICAgIGVuY29kZWRTdHJpbmdzW3Byb3BdID0gZW5jb2Rlci5lbmNvZGUoZm9udFtwcm9wXSk7CiAgICAgIHN0cmluZ3NMZW5ndGggKz0gNCArIGVuY29kZWRTdHJpbmdzW3Byb3BdLmxlbmd0aDsKICAgIH0KICAgIGNvbnN0IGxlbmd0aEVzdGltYXRlID0gRm9udEluZm8uI09GRlNFVF9TVFJJTkdTICsgNCArIHN0cmluZ3NMZW5ndGggKyA0ICsgKHN5c3RlbUZvbnRJbmZvQnVmZmVyID8gc3lzdGVtRm9udEluZm9CdWZmZXIuYnl0ZUxlbmd0aCA6IDApICsgNCArIChjc3NGb250SW5mb0J1ZmZlciA/IGNzc0ZvbnRJbmZvQnVmZmVyLmJ5dGVMZW5ndGggOiAwKSArIDQgKyAoZm9udC5kYXRhID8gZm9udC5kYXRhLmxlbmd0aCA6IDApOwogICAgY29uc3QgYnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKGxlbmd0aEVzdGltYXRlKTsKICAgIGNvbnN0IGRhdGEgPSBuZXcgVWludDhBcnJheShidWZmZXIpOwogICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhidWZmZXIpOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICBjb25zdCBudW1Cb29scyA9IEZvbnRJbmZvLmJvb2xzLmxlbmd0aDsKICAgIGxldCBib29sQnl0ZSA9IDAsCiAgICAgIGJvb2xCaXQgPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Cb29sczsgaSsrKSB7CiAgICAgIGNvbnN0IHZhbHVlID0gZm9udFtGb250SW5mby5ib29sc1tpXV07CiAgICAgIGNvbnN0IGJpdHMgPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gMHgwMCA6IHZhbHVlID8gMHgwMiA6IDB4MDE7CiAgICAgIGJvb2xCeXRlIHw9IGJpdHMgPDwgYm9vbEJpdDsKICAgICAgYm9vbEJpdCArPSAyOwogICAgICBpZiAoYm9vbEJpdCA9PT0gOCB8fCBpID09PSBudW1Cb29scyAtIDEpIHsKICAgICAgICB2aWV3LnNldFVpbnQ4KG9mZnNldCsrLCBib29sQnl0ZSk7CiAgICAgICAgYm9vbEJ5dGUgPSAwOwogICAgICAgIGJvb2xCaXQgPSAwOwogICAgICB9CiAgICB9CiAgICBhc3NlcnQob2Zmc2V0ID09PSBGb250SW5mby4jT0ZGU0VUX05VTUJFUlMsICJGb250SW5mby53cml0ZTogQm9vbGVhbiBwcm9wZXJ0aWVzIG9mZnNldCBtaXNtYXRjaCIpOwogICAgZm9yIChjb25zdCBwcm9wIG9mIEZvbnRJbmZvLm51bWJlcnMpIHsKICAgICAgdmlldy5zZXRGbG9hdDY0KG9mZnNldCwgZm9udFtwcm9wXSk7CiAgICAgIG9mZnNldCArPSA4OwogICAgfQogICAgYXNzZXJ0KG9mZnNldCA9PT0gRm9udEluZm8uI09GRlNFVF9CQk9YLCAiRm9udEluZm8ud3JpdGU6IE51bWJlciBwcm9wZXJ0aWVzIG9mZnNldCBtaXNtYXRjaCIpOwogICAgaWYgKGZvbnQuYmJveCkgewogICAgICB2aWV3LnNldFVpbnQ4KG9mZnNldCsrLCA0KTsKICAgICAgZm9yIChjb25zdCBjb29yZCBvZiBmb250LmJib3gpIHsKICAgICAgICB2aWV3LnNldEludDE2KG9mZnNldCwgY29vcmQsIHRydWUpOwogICAgICAgIG9mZnNldCArPSAyOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB2aWV3LnNldFVpbnQ4KG9mZnNldCsrLCAwKTsKICAgICAgb2Zmc2V0ICs9IDIgKiA0OwogICAgfQogICAgYXNzZXJ0KG9mZnNldCA9PT0gRm9udEluZm8uI09GRlNFVF9GT05UX01BVFJJWCwgIkZvbnRJbmZvLndyaXRlOiBCQm94IHByb3BlcnRpZXMgb2Zmc2V0IG1pc21hdGNoIik7CiAgICBpZiAoZm9udC5mb250TWF0cml4KSB7CiAgICAgIHZpZXcuc2V0VWludDgob2Zmc2V0KyssIDYpOwogICAgICBmb3IgKGNvbnN0IHBvaW50IG9mIGZvbnQuZm9udE1hdHJpeCkgewogICAgICAgIHZpZXcuc2V0RmxvYXQ2NChvZmZzZXQsIHBvaW50LCB0cnVlKTsKICAgICAgICBvZmZzZXQgKz0gODsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdmlldy5zZXRVaW50OChvZmZzZXQrKywgMCk7CiAgICAgIG9mZnNldCArPSA4ICogNjsKICAgIH0KICAgIGFzc2VydChvZmZzZXQgPT09IEZvbnRJbmZvLiNPRkZTRVRfREVGQVVMVF9WTUVUUklDUywgIkZvbnRJbmZvLndyaXRlOiBGb250TWF0cml4IHByb3BlcnRpZXMgb2Zmc2V0IG1pc21hdGNoIik7CiAgICBpZiAoZm9udC5kZWZhdWx0Vk1ldHJpY3MpIHsKICAgICAgdmlldy5zZXRVaW50OChvZmZzZXQrKywgMSk7CiAgICAgIGZvciAoY29uc3QgbWV0cmljIG9mIGZvbnQuZGVmYXVsdFZNZXRyaWNzKSB7CiAgICAgICAgdmlldy5zZXRJbnQxNihvZmZzZXQsIG1ldHJpYywgdHJ1ZSk7CiAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZpZXcuc2V0VWludDgob2Zmc2V0KyssIDApOwogICAgICBvZmZzZXQgKz0gMyAqIDI7CiAgICB9CiAgICBhc3NlcnQob2Zmc2V0ID09PSBGb250SW5mby4jT0ZGU0VUX1NUUklOR1MsICJGb250SW5mby53cml0ZTogRGVmYXVsdFZNZXRyaWNzIHByb3BlcnRpZXMgb2Zmc2V0IG1pc21hdGNoIik7CiAgICB2aWV3LnNldFVpbnQzMihGb250SW5mby4jT0ZGU0VUX1NUUklOR1MsIDApOwogICAgb2Zmc2V0ICs9IDQ7CiAgICBmb3IgKGNvbnN0IHByb3Agb2YgRm9udEluZm8uc3RyaW5ncykgewogICAgICBjb25zdCBlbmNvZGVkID0gZW5jb2RlZFN0cmluZ3NbcHJvcF07CiAgICAgIGNvbnN0IGxlbmd0aCA9IGVuY29kZWQubGVuZ3RoOwogICAgICB2aWV3LnNldFVpbnQzMihvZmZzZXQsIGxlbmd0aCk7CiAgICAgIGRhdGEuc2V0KGVuY29kZWQsIG9mZnNldCArIDQpOwogICAgICBvZmZzZXQgKz0gNCArIGxlbmd0aDsKICAgIH0KICAgIHZpZXcuc2V0VWludDMyKEZvbnRJbmZvLiNPRkZTRVRfU1RSSU5HUywgb2Zmc2V0IC0gRm9udEluZm8uI09GRlNFVF9TVFJJTkdTIC0gNCk7CiAgICBpZiAoIXN5c3RlbUZvbnRJbmZvQnVmZmVyKSB7CiAgICAgIHZpZXcuc2V0VWludDMyKG9mZnNldCwgMCk7CiAgICAgIG9mZnNldCArPSA0OwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgbGVuZ3RoID0gc3lzdGVtRm9udEluZm9CdWZmZXIuYnl0ZUxlbmd0aDsKICAgICAgdmlldy5zZXRVaW50MzIob2Zmc2V0LCBsZW5ndGgpOwogICAgICBhc3NlcnQob2Zmc2V0ICsgNCArIGxlbmd0aCA8PSBidWZmZXIuYnl0ZUxlbmd0aCwgIkZvbnRJbmZvLndyaXRlOiBCdWZmZXIgb3ZlcmZsb3cgYXQgc3lzdGVtRm9udEluZm8iKTsKICAgICAgZGF0YS5zZXQobmV3IFVpbnQ4QXJyYXkoc3lzdGVtRm9udEluZm9CdWZmZXIpLCBvZmZzZXQgKyA0KTsKICAgICAgb2Zmc2V0ICs9IDQgKyBsZW5ndGg7CiAgICB9CiAgICBpZiAoIWNzc0ZvbnRJbmZvQnVmZmVyKSB7CiAgICAgIHZpZXcuc2V0VWludDMyKG9mZnNldCwgMCk7CiAgICAgIG9mZnNldCArPSA0OwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgbGVuZ3RoID0gY3NzRm9udEluZm9CdWZmZXIuYnl0ZUxlbmd0aDsKICAgICAgdmlldy5zZXRVaW50MzIob2Zmc2V0LCBsZW5ndGgpOwogICAgICBhc3NlcnQob2Zmc2V0ICsgNCArIGxlbmd0aCA8PSBidWZmZXIuYnl0ZUxlbmd0aCwgIkZvbnRJbmZvLndyaXRlOiBCdWZmZXIgb3ZlcmZsb3cgYXQgY3NzRm9udEluZm8iKTsKICAgICAgZGF0YS5zZXQobmV3IFVpbnQ4QXJyYXkoY3NzRm9udEluZm9CdWZmZXIpLCBvZmZzZXQgKyA0KTsKICAgICAgb2Zmc2V0ICs9IDQgKyBsZW5ndGg7CiAgICB9CiAgICBpZiAoZm9udC5kYXRhID09PSB1bmRlZmluZWQpIHsKICAgICAgdmlldy5zZXRVaW50MzIob2Zmc2V0LCAwKTsKICAgICAgb2Zmc2V0ICs9IDQ7CiAgICB9IGVsc2UgewogICAgICB2aWV3LnNldFVpbnQzMihvZmZzZXQsIGZvbnQuZGF0YS5sZW5ndGgpOwogICAgICBkYXRhLnNldChmb250LmRhdGEsIG9mZnNldCArIDQpOwogICAgICBvZmZzZXQgKz0gNCArIGZvbnQuZGF0YS5sZW5ndGg7CiAgICB9CiAgICBhc3NlcnQob2Zmc2V0IDw9IGJ1ZmZlci5ieXRlTGVuZ3RoLCAiRm9udEluZm8ud3JpdGU6IEJ1ZmZlciBvdmVyZmxvdyIpOwogICAgcmV0dXJuIGJ1ZmZlci50cmFuc2ZlclRvRml4ZWRMZW5ndGgob2Zmc2V0KTsKICB9Cn0KY2xhc3MgUGF0dGVybkluZm8gewogIHN0YXRpYyAjS0lORCA9IDA7CiAgc3RhdGljICNIQVNfQkJPWCA9IDE7CiAgc3RhdGljICNIQVNfQkFDS0dST1VORCA9IDI7CiAgc3RhdGljICNTSEFESU5HX1RZUEUgPSAzOwogIHN0YXRpYyAjTl9DT09SRCA9IDQ7CiAgc3RhdGljICNOX0NPTE9SID0gODsKICBzdGF0aWMgI05fU1RPUCA9IDEyOwogIHN0YXRpYyAjTl9GSUdVUkVTID0gMTY7CiAgY29uc3RydWN0b3IoYnVmZmVyKSB7CiAgICB0aGlzLmJ1ZmZlciA9IGJ1ZmZlcjsKICAgIHRoaXMudmlldyA9IG5ldyBEYXRhVmlldyhidWZmZXIpOwogICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyKTsKICB9CiAgc3RhdGljIHdyaXRlKGlyKSB7CiAgICBsZXQga2luZCwKICAgICAgYmJveCA9IG51bGwsCiAgICAgIGNvb3JkcyA9IFtdLAogICAgICBjb2xvcnMgPSBbXSwKICAgICAgY29sb3JTdG9wcyA9IFtdLAogICAgICBmaWd1cmVzID0gW10sCiAgICAgIHNoYWRpbmdUeXBlID0gbnVsbCwKICAgICAgYmFja2dyb3VuZCA9IG51bGw7CiAgICBzd2l0Y2ggKGlyWzBdKSB7CiAgICAgIGNhc2UgIlJhZGlhbEF4aWFsIjoKICAgICAgICBraW5kID0gaXJbMV0gPT09ICJheGlhbCIgPyAxIDogMjsKICAgICAgICBiYm94ID0gaXJbMl07CiAgICAgICAgY29sb3JTdG9wcyA9IGlyWzNdOwogICAgICAgIGlmIChraW5kID09PSAxKSB7CiAgICAgICAgICBjb29yZHMucHVzaCguLi5pcls0XSwgLi4uaXJbNV0pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb29yZHMucHVzaChpcls0XVswXSwgaXJbNF1bMV0sIGlyWzZdLCBpcls1XVswXSwgaXJbNV1bMV0sIGlyWzddKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIk1lc2giOgogICAgICAgIGtpbmQgPSAzOwogICAgICAgIHNoYWRpbmdUeXBlID0gaXJbMV07CiAgICAgICAgY29vcmRzID0gaXJbMl07CiAgICAgICAgY29sb3JzID0gaXJbM107CiAgICAgICAgZmlndXJlcyA9IGlyWzRdIHx8IFtdOwogICAgICAgIGJib3ggPSBpcls2XTsKICAgICAgICBiYWNrZ3JvdW5kID0gaXJbN107CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBwYXR0ZXJuIHR5cGU6ICR7aXJbMF19YCk7CiAgICB9CiAgICBjb25zdCBuQ29vcmQgPSBNYXRoLmZsb29yKGNvb3Jkcy5sZW5ndGggLyAyKTsKICAgIGNvbnN0IG5Db2xvciA9IE1hdGguZmxvb3IoY29sb3JzLmxlbmd0aCAvIDMpOwogICAgY29uc3QgblN0b3AgPSBjb2xvclN0b3BzLmxlbmd0aDsKICAgIGNvbnN0IG5GaWd1cmVzID0gZmlndXJlcy5sZW5ndGg7CiAgICBsZXQgZmlndXJlc1NpemUgPSAwOwogICAgZm9yIChjb25zdCBmaWd1cmUgb2YgZmlndXJlcykgewogICAgICBmaWd1cmVzU2l6ZSArPSAxOwogICAgICBmaWd1cmVzU2l6ZSA9IE1hdGguY2VpbChmaWd1cmVzU2l6ZSAvIDQpICogNDsKICAgICAgZmlndXJlc1NpemUgKz0gNCArIGZpZ3VyZS5jb29yZHMubGVuZ3RoICogNDsKICAgICAgZmlndXJlc1NpemUgKz0gNCArIGZpZ3VyZS5jb2xvcnMubGVuZ3RoICogNDsKICAgICAgaWYgKGZpZ3VyZS52ZXJ0aWNlc1BlclJvdyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZmlndXJlc1NpemUgKz0gNDsKICAgICAgfQogICAgfQogICAgY29uc3QgYnl0ZUxlbiA9IDIwICsgbkNvb3JkICogOCArIG5Db2xvciAqIDMgKyBuU3RvcCAqIDggKyAoYmJveCA/IDE2IDogMCkgKyAoYmFja2dyb3VuZCA/IDMgOiAwKSArIGZpZ3VyZXNTaXplOwogICAgY29uc3QgYnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKGJ5dGVMZW4pOwogICAgY29uc3QgZGF0YVZpZXcgPSBuZXcgRGF0YVZpZXcoYnVmZmVyKTsKICAgIGNvbnN0IHU4ZGF0YSA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlcik7CiAgICBkYXRhVmlldy5zZXRVaW50OChQYXR0ZXJuSW5mby4jS0lORCwga2luZCk7CiAgICBkYXRhVmlldy5zZXRVaW50OChQYXR0ZXJuSW5mby4jSEFTX0JCT1gsIGJib3ggPyAxIDogMCk7CiAgICBkYXRhVmlldy5zZXRVaW50OChQYXR0ZXJuSW5mby4jSEFTX0JBQ0tHUk9VTkQsIGJhY2tncm91bmQgPyAxIDogMCk7CiAgICBkYXRhVmlldy5zZXRVaW50OChQYXR0ZXJuSW5mby4jU0hBRElOR19UWVBFLCBzaGFkaW5nVHlwZSk7CiAgICBkYXRhVmlldy5zZXRVaW50MzIoUGF0dGVybkluZm8uI05fQ09PUkQsIG5Db29yZCwgdHJ1ZSk7CiAgICBkYXRhVmlldy5zZXRVaW50MzIoUGF0dGVybkluZm8uI05fQ09MT1IsIG5Db2xvciwgdHJ1ZSk7CiAgICBkYXRhVmlldy5zZXRVaW50MzIoUGF0dGVybkluZm8uI05fU1RPUCwgblN0b3AsIHRydWUpOwogICAgZGF0YVZpZXcuc2V0VWludDMyKFBhdHRlcm5JbmZvLiNOX0ZJR1VSRVMsIG5GaWd1cmVzLCB0cnVlKTsKICAgIGxldCBvZmZzZXQgPSAyMDsKICAgIGNvbnN0IGNvb3Jkc1ZpZXcgPSBuZXcgRmxvYXQzMkFycmF5KGJ1ZmZlciwgb2Zmc2V0LCBuQ29vcmQgKiAyKTsKICAgIGNvb3Jkc1ZpZXcuc2V0KGNvb3Jkcyk7CiAgICBvZmZzZXQgKz0gbkNvb3JkICogODsKICAgIHU4ZGF0YS5zZXQoY29sb3JzLCBvZmZzZXQpOwogICAgb2Zmc2V0ICs9IG5Db2xvciAqIDM7CiAgICBmb3IgKGNvbnN0IFtwb3MsIGhleF0gb2YgY29sb3JTdG9wcykgewogICAgICBkYXRhVmlldy5zZXRGbG9hdDMyKG9mZnNldCwgcG9zLCB0cnVlKTsKICAgICAgb2Zmc2V0ICs9IDQ7CiAgICAgIGRhdGFWaWV3LnNldFVpbnQzMihvZmZzZXQsIHBhcnNlSW50KGhleC5zbGljZSgxKSwgMTYpLCB0cnVlKTsKICAgICAgb2Zmc2V0ICs9IDQ7CiAgICB9CiAgICBpZiAoYmJveCkgewogICAgICBmb3IgKGNvbnN0IHYgb2YgYmJveCkgewogICAgICAgIGRhdGFWaWV3LnNldEZsb2F0MzIob2Zmc2V0LCB2LCB0cnVlKTsKICAgICAgICBvZmZzZXQgKz0gNDsKICAgICAgfQogICAgfQogICAgaWYgKGJhY2tncm91bmQpIHsKICAgICAgdThkYXRhLnNldChiYWNrZ3JvdW5kLCBvZmZzZXQpOwogICAgICBvZmZzZXQgKz0gMzsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmlndXJlcy5sZW5ndGg7IGkrKykgewogICAgICBjb25zdCBmaWd1cmUgPSBmaWd1cmVzW2ldOwogICAgICBkYXRhVmlldy5zZXRVaW50OChvZmZzZXQsIGZpZ3VyZS50eXBlKTsKICAgICAgb2Zmc2V0ICs9IDE7CiAgICAgIG9mZnNldCA9IE1hdGguY2VpbChvZmZzZXQgLyA0KSAqIDQ7CiAgICAgIGRhdGFWaWV3LnNldFVpbnQzMihvZmZzZXQsIGZpZ3VyZS5jb29yZHMubGVuZ3RoLCB0cnVlKTsKICAgICAgb2Zmc2V0ICs9IDQ7CiAgICAgIGNvbnN0IGZpZ3VyZUNvb3Jkc1ZpZXcgPSBuZXcgSW50MzJBcnJheShidWZmZXIsIG9mZnNldCwgZmlndXJlLmNvb3Jkcy5sZW5ndGgpOwogICAgICBmaWd1cmVDb29yZHNWaWV3LnNldChmaWd1cmUuY29vcmRzKTsKICAgICAgb2Zmc2V0ICs9IGZpZ3VyZS5jb29yZHMubGVuZ3RoICogNDsKICAgICAgZGF0YVZpZXcuc2V0VWludDMyKG9mZnNldCwgZmlndXJlLmNvbG9ycy5sZW5ndGgsIHRydWUpOwogICAgICBvZmZzZXQgKz0gNDsKICAgICAgY29uc3QgY29sb3JzVmlldyA9IG5ldyBJbnQzMkFycmF5KGJ1ZmZlciwgb2Zmc2V0LCBmaWd1cmUuY29sb3JzLmxlbmd0aCk7CiAgICAgIGNvbG9yc1ZpZXcuc2V0KGZpZ3VyZS5jb2xvcnMpOwogICAgICBvZmZzZXQgKz0gZmlndXJlLmNvbG9ycy5sZW5ndGggKiA0OwogICAgICBpZiAoZmlndXJlLnZlcnRpY2VzUGVyUm93ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBkYXRhVmlldy5zZXRVaW50MzIob2Zmc2V0LCBmaWd1cmUudmVydGljZXNQZXJSb3csIHRydWUpOwogICAgICAgIG9mZnNldCArPSA0OwogICAgICB9CiAgICB9CiAgICByZXR1cm4gYnVmZmVyOwogIH0KICBnZXRJUigpIHsKICAgIGNvbnN0IGRhdGFWaWV3ID0gdGhpcy52aWV3OwogICAgY29uc3Qga2luZCA9IHRoaXMuZGF0YVtQYXR0ZXJuSW5mby4jS0lORF07CiAgICBjb25zdCBoYXNCQm94ID0gISF0aGlzLmRhdGFbUGF0dGVybkluZm8uI0hBU19CQk9YXTsKICAgIGNvbnN0IGhhc0JhY2tncm91bmQgPSAhIXRoaXMuZGF0YVtQYXR0ZXJuSW5mby4jSEFTX0JBQ0tHUk9VTkRdOwogICAgY29uc3QgbkNvb3JkID0gZGF0YVZpZXcuZ2V0VWludDMyKFBhdHRlcm5JbmZvLiNOX0NPT1JELCB0cnVlKTsKICAgIGNvbnN0IG5Db2xvciA9IGRhdGFWaWV3LmdldFVpbnQzMihQYXR0ZXJuSW5mby4jTl9DT0xPUiwgdHJ1ZSk7CiAgICBjb25zdCBuU3RvcCA9IGRhdGFWaWV3LmdldFVpbnQzMihQYXR0ZXJuSW5mby4jTl9TVE9QLCB0cnVlKTsKICAgIGNvbnN0IG5GaWd1cmVzID0gZGF0YVZpZXcuZ2V0VWludDMyKFBhdHRlcm5JbmZvLiNOX0ZJR1VSRVMsIHRydWUpOwogICAgbGV0IG9mZnNldCA9IDIwOwogICAgY29uc3QgY29vcmRzID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmJ1ZmZlciwgb2Zmc2V0LCBuQ29vcmQgKiAyKTsKICAgIG9mZnNldCArPSBuQ29vcmQgKiA4OwogICAgY29uc3QgY29sb3JzID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5idWZmZXIsIG9mZnNldCwgbkNvbG9yICogMyk7CiAgICBvZmZzZXQgKz0gbkNvbG9yICogMzsKICAgIGNvbnN0IHN0b3BzID0gW107CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5TdG9wOyArK2kpIHsKICAgICAgY29uc3QgcCA9IGRhdGFWaWV3LmdldEZsb2F0MzIob2Zmc2V0LCB0cnVlKTsKICAgICAgb2Zmc2V0ICs9IDQ7CiAgICAgIGNvbnN0IHJnYiA9IGRhdGFWaWV3LmdldFVpbnQzMihvZmZzZXQsIHRydWUpOwogICAgICBvZmZzZXQgKz0gNDsKICAgICAgc3RvcHMucHVzaChbcCwgYCMke3JnYi50b1N0cmluZygxNikucGFkU3RhcnQoNiwgIjAiKX1gXSk7CiAgICB9CiAgICBsZXQgYmJveCA9IG51bGw7CiAgICBpZiAoaGFzQkJveCkgewogICAgICBiYm94ID0gW107CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNDsgKytpKSB7CiAgICAgICAgYmJveC5wdXNoKGRhdGFWaWV3LmdldEZsb2F0MzIob2Zmc2V0LCB0cnVlKSk7CiAgICAgICAgb2Zmc2V0ICs9IDQ7CiAgICAgIH0KICAgIH0KICAgIGxldCBiYWNrZ3JvdW5kID0gbnVsbDsKICAgIGlmIChoYXNCYWNrZ3JvdW5kKSB7CiAgICAgIGJhY2tncm91bmQgPSBuZXcgVWludDhBcnJheSh0aGlzLmJ1ZmZlciwgb2Zmc2V0LCAzKTsKICAgICAgb2Zmc2V0ICs9IDM7CiAgICB9CiAgICBjb25zdCBmaWd1cmVzID0gW107CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5GaWd1cmVzOyArK2kpIHsKICAgICAgY29uc3QgdHlwZSA9IGRhdGFWaWV3LmdldFVpbnQ4KG9mZnNldCk7CiAgICAgIG9mZnNldCArPSAxOwogICAgICBvZmZzZXQgPSBNYXRoLmNlaWwob2Zmc2V0IC8gNCkgKiA0OwogICAgICBjb25zdCBjb29yZHNMZW5ndGggPSBkYXRhVmlldy5nZXRVaW50MzIob2Zmc2V0LCB0cnVlKTsKICAgICAgb2Zmc2V0ICs9IDQ7CiAgICAgIGNvbnN0IGZpZ3VyZUNvb3JkcyA9IG5ldyBJbnQzMkFycmF5KHRoaXMuYnVmZmVyLCBvZmZzZXQsIGNvb3Jkc0xlbmd0aCk7CiAgICAgIG9mZnNldCArPSBjb29yZHNMZW5ndGggKiA0OwogICAgICBjb25zdCBjb2xvcnNMZW5ndGggPSBkYXRhVmlldy5nZXRVaW50MzIob2Zmc2V0LCB0cnVlKTsKICAgICAgb2Zmc2V0ICs9IDQ7CiAgICAgIGNvbnN0IGZpZ3VyZUNvbG9ycyA9IG5ldyBJbnQzMkFycmF5KHRoaXMuYnVmZmVyLCBvZmZzZXQsIGNvbG9yc0xlbmd0aCk7CiAgICAgIG9mZnNldCArPSBjb2xvcnNMZW5ndGggKiA0OwogICAgICBjb25zdCBmaWd1cmUgPSB7CiAgICAgICAgdHlwZSwKICAgICAgICBjb29yZHM6IGZpZ3VyZUNvb3JkcywKICAgICAgICBjb2xvcnM6IGZpZ3VyZUNvbG9ycwogICAgICB9OwogICAgICBpZiAodHlwZSA9PT0gTWVzaEZpZ3VyZVR5cGUuTEFUVElDRSkgewogICAgICAgIGZpZ3VyZS52ZXJ0aWNlc1BlclJvdyA9IGRhdGFWaWV3LmdldFVpbnQzMihvZmZzZXQsIHRydWUpOwogICAgICAgIG9mZnNldCArPSA0OwogICAgICB9CiAgICAgIGZpZ3VyZXMucHVzaChmaWd1cmUpOwogICAgfQogICAgaWYgKGtpbmQgPT09IDEpIHsKICAgICAgcmV0dXJuIFsiUmFkaWFsQXhpYWwiLCAiYXhpYWwiLCBiYm94LCBzdG9wcywgQXJyYXkuZnJvbShjb29yZHMuc2xpY2UoMCwgMikpLCBBcnJheS5mcm9tKGNvb3Jkcy5zbGljZSgyLCA0KSksIG51bGwsIG51bGxdOwogICAgfQogICAgaWYgKGtpbmQgPT09IDIpIHsKICAgICAgcmV0dXJuIFsiUmFkaWFsQXhpYWwiLCAicmFkaWFsIiwgYmJveCwgc3RvcHMsIFtjb29yZHNbMF0sIGNvb3Jkc1sxXV0sIFtjb29yZHNbM10sIGNvb3Jkc1s0XV0sIGNvb3Jkc1syXSwgY29vcmRzWzVdXTsKICAgIH0KICAgIGlmIChraW5kID09PSAzKSB7CiAgICAgIGNvbnN0IHNoYWRpbmdUeXBlID0gdGhpcy5kYXRhW1BhdHRlcm5JbmZvLiNTSEFESU5HX1RZUEVdOwogICAgICBsZXQgYm91bmRzID0gbnVsbDsKICAgICAgaWYgKGNvb3Jkcy5sZW5ndGggPiAwKSB7CiAgICAgICAgbGV0IG1pblggPSBjb29yZHNbMF0sCiAgICAgICAgICBtYXhYID0gY29vcmRzWzBdOwogICAgICAgIGxldCBtaW5ZID0gY29vcmRzWzFdLAogICAgICAgICAgbWF4WSA9IGNvb3Jkc1sxXTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkgKz0gMikgewogICAgICAgICAgY29uc3QgeCA9IGNvb3Jkc1tpXSwKICAgICAgICAgICAgeSA9IGNvb3Jkc1tpICsgMV07CiAgICAgICAgICBtaW5YID0gbWluWCA+IHggPyB4IDogbWluWDsKICAgICAgICAgIG1pblkgPSBtaW5ZID4geSA/IHkgOiBtaW5ZOwogICAgICAgICAgbWF4WCA9IG1heFggPCB4ID8geCA6IG1heFg7CiAgICAgICAgICBtYXhZID0gbWF4WSA8IHkgPyB5IDogbWF4WTsKICAgICAgICB9CiAgICAgICAgYm91bmRzID0gW21pblgsIG1pblksIG1heFgsIG1heFldOwogICAgICB9CiAgICAgIHJldHVybiBbIk1lc2giLCBzaGFkaW5nVHlwZSwgY29vcmRzLCBjb2xvcnMsIGZpZ3VyZXMsIGJvdW5kcywgYmJveCwgYmFja2dyb3VuZF07CiAgICB9CiAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIHBhdHRlcm4ga2luZDogJHtraW5kfWApOwogIH0KfQpjbGFzcyBGb250UGF0aEluZm8gewogIHN0YXRpYyB3cml0ZShwYXRoKSB7CiAgICBsZXQgZGF0YTsKICAgIGxldCBidWZmZXI7CiAgICBpZiAoRmVhdHVyZVRlc3QuaXNGbG9hdDE2QXJyYXlTdXBwb3J0ZWQpIHsKICAgICAgYnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKHBhdGgubGVuZ3RoICogMik7CiAgICAgIGRhdGEgPSBuZXcgRmxvYXQxNkFycmF5KGJ1ZmZlcik7CiAgICB9IGVsc2UgewogICAgICBidWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIocGF0aC5sZW5ndGggKiA0KTsKICAgICAgZGF0YSA9IG5ldyBGbG9hdDMyQXJyYXkoYnVmZmVyKTsKICAgIH0KICAgIGRhdGEuc2V0KHBhdGgpOwogICAgcmV0dXJuIGJ1ZmZlcjsKICB9CiAgI2J1ZmZlcjsKICBjb25zdHJ1Y3RvcihidWZmZXIpIHsKICAgIHRoaXMuI2J1ZmZlciA9IGJ1ZmZlcjsKICB9CiAgZ2V0IHBhdGgoKSB7CiAgICBpZiAoRmVhdHVyZVRlc3QuaXNGbG9hdDE2QXJyYXlTdXBwb3J0ZWQpIHsKICAgICAgcmV0dXJuIG5ldyBGbG9hdDE2QXJyYXkodGhpcy4jYnVmZmVyKTsKICAgIH0KICAgIHJldHVybiBuZXcgRmxvYXQzMkFycmF5KHRoaXMuI2J1ZmZlcik7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9wYXR0ZXJuLmpzCgoKCgpjb25zdCBTaGFkaW5nVHlwZSA9IHsKICBGVU5DVElPTl9CQVNFRDogMSwKICBBWElBTDogMiwKICBSQURJQUw6IDMsCiAgRlJFRV9GT1JNX01FU0g6IDQsCiAgTEFUVElDRV9GT1JNX01FU0g6IDUsCiAgQ09PTlNfUEFUQ0hfTUVTSDogNiwKICBURU5TT1JfUEFUQ0hfTUVTSDogNwp9OwpjbGFzcyBQYXR0ZXJuIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHVucmVhY2hhYmxlKCJDYW5ub3QgaW5pdGlhbGl6ZSBQYXR0ZXJuLiIpOwogIH0KICBzdGF0aWMgcGFyc2VTaGFkaW5nKHNoYWRpbmcsIHhyZWYsIHJlcywgcGRmRnVuY3Rpb25GYWN0b3J5LCBnbG9iYWxDb2xvclNwYWNlQ2FjaGUsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKSB7CiAgICBjb25zdCBkaWN0ID0gc2hhZGluZyBpbnN0YW5jZW9mIEJhc2VTdHJlYW0gPyBzaGFkaW5nLmRpY3QgOiBzaGFkaW5nOwogICAgY29uc3QgdHlwZSA9IGRpY3QuZ2V0KCJTaGFkaW5nVHlwZSIpOwogICAgdHJ5IHsKICAgICAgc3dpdGNoICh0eXBlKSB7CiAgICAgICAgY2FzZSBTaGFkaW5nVHlwZS5BWElBTDoKICAgICAgICBjYXNlIFNoYWRpbmdUeXBlLlJBRElBTDoKICAgICAgICAgIHJldHVybiBuZXcgUmFkaWFsQXhpYWxTaGFkaW5nKGRpY3QsIHhyZWYsIHJlcywgcGRmRnVuY3Rpb25GYWN0b3J5LCBnbG9iYWxDb2xvclNwYWNlQ2FjaGUsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKTsKICAgICAgICBjYXNlIFNoYWRpbmdUeXBlLkZSRUVfRk9STV9NRVNIOgogICAgICAgIGNhc2UgU2hhZGluZ1R5cGUuTEFUVElDRV9GT1JNX01FU0g6CiAgICAgICAgY2FzZSBTaGFkaW5nVHlwZS5DT09OU19QQVRDSF9NRVNIOgogICAgICAgIGNhc2UgU2hhZGluZ1R5cGUuVEVOU09SX1BBVENIX01FU0g6CiAgICAgICAgICByZXR1cm4gbmV3IE1lc2hTaGFkaW5nKHNoYWRpbmcsIHhyZWYsIHJlcywgcGRmRnVuY3Rpb25GYWN0b3J5LCBnbG9iYWxDb2xvclNwYWNlQ2FjaGUsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKTsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJVbnN1cHBvcnRlZCBTaGFkaW5nVHlwZTogIiArIHR5cGUpOwogICAgICB9CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIHdhcm4oZXgpOwogICAgICByZXR1cm4gbmV3IER1bW15U2hhZGluZygpOwogICAgfQogIH0KfQpjbGFzcyBCYXNlU2hhZGluZyB7CiAgc3RhdGljIFNNQUxMX05VTUJFUiA9IDFlLTY7CiAgZ2V0SVIoKSB7CiAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGBnZXRJUmAgY2FsbGVkLiIpOwogIH0KfQpjbGFzcyBSYWRpYWxBeGlhbFNoYWRpbmcgZXh0ZW5kcyBCYXNlU2hhZGluZyB7CiAgY29uc3RydWN0b3IoZGljdCwgeHJlZiwgcmVzb3VyY2VzLCBwZGZGdW5jdGlvbkZhY3RvcnksIGdsb2JhbENvbG9yU3BhY2VDYWNoZSwgbG9jYWxDb2xvclNwYWNlQ2FjaGUpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLnNoYWRpbmdUeXBlID0gZGljdC5nZXQoIlNoYWRpbmdUeXBlIik7CiAgICBsZXQgY29vcmRzTGVuID0gMDsKICAgIGlmICh0aGlzLnNoYWRpbmdUeXBlID09PSBTaGFkaW5nVHlwZS5BWElBTCkgewogICAgICBjb29yZHNMZW4gPSA0OwogICAgfSBlbHNlIGlmICh0aGlzLnNoYWRpbmdUeXBlID09PSBTaGFkaW5nVHlwZS5SQURJQUwpIHsKICAgICAgY29vcmRzTGVuID0gNjsKICAgIH0KICAgIHRoaXMuY29vcmRzQXJyID0gZGljdC5nZXRBcnJheSgiQ29vcmRzIik7CiAgICBpZiAoIWlzTnVtYmVyQXJyYXkodGhpcy5jb29yZHNBcnIsIGNvb3Jkc0xlbikpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJSYWRpYWxBeGlhbFNoYWRpbmc6IEludmFsaWQgL0Nvb3JkcyBhcnJheS4iKTsKICAgIH0KICAgIGNvbnN0IGNzID0gQ29sb3JTcGFjZVV0aWxzLnBhcnNlKHsKICAgICAgY3M6IGRpY3QuZ2V0UmF3KCJDUyIpIHx8IGRpY3QuZ2V0UmF3KCJDb2xvclNwYWNlIiksCiAgICAgIHhyZWYsCiAgICAgIHJlc291cmNlcywKICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGUsCiAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICB9KTsKICAgIHRoaXMuYmJveCA9IGxvb2t1cE5vcm1hbFJlY3QoZGljdC5nZXRBcnJheSgiQkJveCIpLCBudWxsKTsKICAgIGxldCB0MCA9IDAuMCwKICAgICAgdDEgPSAxLjA7CiAgICBjb25zdCBkb21haW5BcnIgPSBkaWN0LmdldEFycmF5KCJEb21haW4iKTsKICAgIGlmIChpc051bWJlckFycmF5KGRvbWFpbkFyciwgMikpIHsKICAgICAgW3QwLCB0MV0gPSBkb21haW5BcnI7CiAgICB9CiAgICBsZXQgZXh0ZW5kU3RhcnQgPSBmYWxzZSwKICAgICAgZXh0ZW5kRW5kID0gZmFsc2U7CiAgICBjb25zdCBleHRlbmRBcnIgPSBkaWN0LmdldEFycmF5KCJFeHRlbmQiKTsKICAgIGlmIChpc0Jvb2xlYW5BcnJheShleHRlbmRBcnIsIDIpKSB7CiAgICAgIFtleHRlbmRTdGFydCwgZXh0ZW5kRW5kXSA9IGV4dGVuZEFycjsKICAgIH0KICAgIGlmICh0aGlzLnNoYWRpbmdUeXBlID09PSBTaGFkaW5nVHlwZS5SQURJQUwgJiYgKCFleHRlbmRTdGFydCB8fCAhZXh0ZW5kRW5kKSkgewogICAgICBjb25zdCBbeDEsIHkxLCByMSwgeDIsIHkyLCByMl0gPSB0aGlzLmNvb3Jkc0FycjsKICAgICAgY29uc3QgZGlzdGFuY2UgPSBNYXRoLmh5cG90KHgxIC0geDIsIHkxIC0geTIpOwogICAgICBpZiAocjEgPD0gcjIgKyBkaXN0YW5jZSAmJiByMiA8PSByMSArIGRpc3RhbmNlKSB7CiAgICAgICAgd2FybigiVW5zdXBwb3J0ZWQgcmFkaWFsIGdyYWRpZW50LiIpOwogICAgICB9CiAgICB9CiAgICB0aGlzLmV4dGVuZFN0YXJ0ID0gZXh0ZW5kU3RhcnQ7CiAgICB0aGlzLmV4dGVuZEVuZCA9IGV4dGVuZEVuZDsKICAgIGNvbnN0IGZuT2JqID0gZGljdC5nZXRSYXcoIkZ1bmN0aW9uIik7CiAgICBjb25zdCBmbiA9IHBkZkZ1bmN0aW9uRmFjdG9yeS5jcmVhdGUoZm5PYmosIHRydWUpOwogICAgY29uc3QgTlVNQkVSX09GX1NBTVBMRVMgPSA4NDA7CiAgICBjb25zdCBzdGVwID0gKHQxIC0gdDApIC8gTlVNQkVSX09GX1NBTVBMRVM7CiAgICBjb25zdCBjb2xvclN0b3BzID0gdGhpcy5jb2xvclN0b3BzID0gW107CiAgICBpZiAodDAgPj0gdDEgfHwgc3RlcCA8PSAwKSB7CiAgICAgIGluZm8oIkJhZCBzaGFkaW5nIGRvbWFpbi4iKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgY29sb3IgPSBuZXcgRmxvYXQzMkFycmF5KGNzLm51bUNvbXBzKSwKICAgICAgcmF0aW8gPSBuZXcgRmxvYXQzMkFycmF5KDEpOwogICAgbGV0IGlCYXNlID0gMDsKICAgIHJhdGlvWzBdID0gdDA7CiAgICBmbihyYXRpbywgMCwgY29sb3IsIDApOwogICAgY29uc3QgcmdiQnVmZmVyID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDMpOwogICAgY3MuZ2V0UmdiKGNvbG9yLCAwLCByZ2JCdWZmZXIpOwogICAgbGV0IFtyQmFzZSwgZ0Jhc2UsIGJCYXNlXSA9IHJnYkJ1ZmZlcjsKICAgIGNvbG9yU3RvcHMucHVzaChbMCwgVXRpbC5tYWtlSGV4Q29sb3IockJhc2UsIGdCYXNlLCBiQmFzZSldKTsKICAgIGxldCBpUHJldiA9IDE7CiAgICByYXRpb1swXSA9IHQwICsgc3RlcDsKICAgIGZuKHJhdGlvLCAwLCBjb2xvciwgMCk7CiAgICBjcy5nZXRSZ2IoY29sb3IsIDAsIHJnYkJ1ZmZlcik7CiAgICBsZXQgW3JQcmV2LCBnUHJldiwgYlByZXZdID0gcmdiQnVmZmVyOwogICAgbGV0IG1heFNsb3BlUiA9IHJQcmV2IC0gckJhc2UgKyAxOwogICAgbGV0IG1heFNsb3BlRyA9IGdQcmV2IC0gZ0Jhc2UgKyAxOwogICAgbGV0IG1heFNsb3BlQiA9IGJQcmV2IC0gYkJhc2UgKyAxOwogICAgbGV0IG1pblNsb3BlUiA9IHJQcmV2IC0gckJhc2UgLSAxOwogICAgbGV0IG1pblNsb3BlRyA9IGdQcmV2IC0gZ0Jhc2UgLSAxOwogICAgbGV0IG1pblNsb3BlQiA9IGJQcmV2IC0gYkJhc2UgLSAxOwogICAgZm9yIChsZXQgaSA9IDI7IGkgPCBOVU1CRVJfT0ZfU0FNUExFUzsgaSsrKSB7CiAgICAgIHJhdGlvWzBdID0gdDAgKyBpICogc3RlcDsKICAgICAgZm4ocmF0aW8sIDAsIGNvbG9yLCAwKTsKICAgICAgY3MuZ2V0UmdiKGNvbG9yLCAwLCByZ2JCdWZmZXIpOwogICAgICBjb25zdCBbciwgZywgYl0gPSByZ2JCdWZmZXI7CiAgICAgIGNvbnN0IHJ1biA9IGkgLSBpQmFzZTsKICAgICAgbWF4U2xvcGVSID0gTWF0aC5taW4obWF4U2xvcGVSLCAociAtIHJCYXNlICsgMSkgLyBydW4pOwogICAgICBtYXhTbG9wZUcgPSBNYXRoLm1pbihtYXhTbG9wZUcsIChnIC0gZ0Jhc2UgKyAxKSAvIHJ1bik7CiAgICAgIG1heFNsb3BlQiA9IE1hdGgubWluKG1heFNsb3BlQiwgKGIgLSBiQmFzZSArIDEpIC8gcnVuKTsKICAgICAgbWluU2xvcGVSID0gTWF0aC5tYXgobWluU2xvcGVSLCAociAtIHJCYXNlIC0gMSkgLyBydW4pOwogICAgICBtaW5TbG9wZUcgPSBNYXRoLm1heChtaW5TbG9wZUcsIChnIC0gZ0Jhc2UgLSAxKSAvIHJ1bik7CiAgICAgIG1pblNsb3BlQiA9IE1hdGgubWF4KG1pblNsb3BlQiwgKGIgLSBiQmFzZSAtIDEpIC8gcnVuKTsKICAgICAgY29uc3Qgc2xvcGVzRXhpc3QgPSBtaW5TbG9wZVIgPD0gbWF4U2xvcGVSICYmIG1pblNsb3BlRyA8PSBtYXhTbG9wZUcgJiYgbWluU2xvcGVCIDw9IG1heFNsb3BlQjsKICAgICAgaWYgKCFzbG9wZXNFeGlzdCkgewogICAgICAgIGNvbnN0IGNzc0NvbG9yID0gVXRpbC5tYWtlSGV4Q29sb3IoclByZXYsIGdQcmV2LCBiUHJldik7CiAgICAgICAgY29sb3JTdG9wcy5wdXNoKFtpUHJldiAvIE5VTUJFUl9PRl9TQU1QTEVTLCBjc3NDb2xvcl0pOwogICAgICAgIG1heFNsb3BlUiA9IHIgLSByUHJldiArIDE7CiAgICAgICAgbWF4U2xvcGVHID0gZyAtIGdQcmV2ICsgMTsKICAgICAgICBtYXhTbG9wZUIgPSBiIC0gYlByZXYgKyAxOwogICAgICAgIG1pblNsb3BlUiA9IHIgLSByUHJldiAtIDE7CiAgICAgICAgbWluU2xvcGVHID0gZyAtIGdQcmV2IC0gMTsKICAgICAgICBtaW5TbG9wZUIgPSBiIC0gYlByZXYgLSAxOwogICAgICAgIGlCYXNlID0gaVByZXY7CiAgICAgICAgckJhc2UgPSByUHJldjsKICAgICAgICBnQmFzZSA9IGdQcmV2OwogICAgICAgIGJCYXNlID0gYlByZXY7CiAgICAgIH0KICAgICAgaVByZXYgPSBpOwogICAgICByUHJldiA9IHI7CiAgICAgIGdQcmV2ID0gZzsKICAgICAgYlByZXYgPSBiOwogICAgfQogICAgY29sb3JTdG9wcy5wdXNoKFsxLCBVdGlsLm1ha2VIZXhDb2xvcihyUHJldiwgZ1ByZXYsIGJQcmV2KV0pOwogICAgbGV0IGJhY2tncm91bmQgPSAidHJhbnNwYXJlbnQiOwogICAgaWYgKGRpY3QuaGFzKCJCYWNrZ3JvdW5kIikpIHsKICAgICAgYmFja2dyb3VuZCA9IGNzLmdldFJnYkhleChkaWN0LmdldCgiQmFja2dyb3VuZCIpLCAwKTsKICAgIH0KICAgIGlmICghZXh0ZW5kU3RhcnQpIHsKICAgICAgY29sb3JTdG9wcy51bnNoaWZ0KFswLCBiYWNrZ3JvdW5kXSk7CiAgICAgIGNvbG9yU3RvcHNbMV1bMF0gKz0gQmFzZVNoYWRpbmcuU01BTExfTlVNQkVSOwogICAgfQogICAgaWYgKCFleHRlbmRFbmQpIHsKICAgICAgY29sb3JTdG9wcy5hdCgtMSlbMF0gLT0gQmFzZVNoYWRpbmcuU01BTExfTlVNQkVSOwogICAgICBjb2xvclN0b3BzLnB1c2goWzEsIGJhY2tncm91bmRdKTsKICAgIH0KICAgIHRoaXMuY29sb3JTdG9wcyA9IGNvbG9yU3RvcHM7CiAgfQogIGdldElSKCkgewogICAgY29uc3QgewogICAgICBjb29yZHNBcnIsCiAgICAgIHNoYWRpbmdUeXBlCiAgICB9ID0gdGhpczsKICAgIGxldCB0eXBlLCBwMCwgcDEsIHIwLCByMTsKICAgIGlmIChzaGFkaW5nVHlwZSA9PT0gU2hhZGluZ1R5cGUuQVhJQUwpIHsKICAgICAgcDAgPSBbY29vcmRzQXJyWzBdLCBjb29yZHNBcnJbMV1dOwogICAgICBwMSA9IFtjb29yZHNBcnJbMl0sIGNvb3Jkc0FyclszXV07CiAgICAgIHIwID0gbnVsbDsKICAgICAgcjEgPSBudWxsOwogICAgICB0eXBlID0gImF4aWFsIjsKICAgIH0gZWxzZSBpZiAoc2hhZGluZ1R5cGUgPT09IFNoYWRpbmdUeXBlLlJBRElBTCkgewogICAgICBwMCA9IFtjb29yZHNBcnJbMF0sIGNvb3Jkc0FyclsxXV07CiAgICAgIHAxID0gW2Nvb3Jkc0FyclszXSwgY29vcmRzQXJyWzRdXTsKICAgICAgcjAgPSBjb29yZHNBcnJbMl07CiAgICAgIHIxID0gY29vcmRzQXJyWzVdOwogICAgICB0eXBlID0gInJhZGlhbCI7CiAgICB9IGVsc2UgewogICAgICB1bnJlYWNoYWJsZShgZ2V0UGF0dGVybiB0eXBlIHVua25vd246ICR7c2hhZGluZ1R5cGV9YCk7CiAgICB9CiAgICByZXR1cm4gWyJSYWRpYWxBeGlhbCIsIHR5cGUsIHRoaXMuYmJveCwgdGhpcy5jb2xvclN0b3BzLCBwMCwgcDEsIHIwLCByMV07CiAgfQp9CmNsYXNzIE1lc2hTdHJlYW1SZWFkZXIgewogIGNvbnN0cnVjdG9yKHN0cmVhbSwgY29udGV4dCkgewogICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07CiAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0OwogICAgdGhpcy5idWZmZXIgPSAwOwogICAgdGhpcy5idWZmZXJMZW5ndGggPSAwOwogICAgY29uc3QgbnVtQ29tcHMgPSBjb250ZXh0Lm51bUNvbXBzOwogICAgdGhpcy50bXBDb21wc0J1ZiA9IG5ldyBGbG9hdDMyQXJyYXkobnVtQ29tcHMpOwogICAgY29uc3QgY3NOdW1Db21wcyA9IGNvbnRleHQuY29sb3JTcGFjZS5udW1Db21wczsKICAgIHRoaXMudG1wQ3NDb21wc0J1ZiA9IGNvbnRleHQuY29sb3JGbiA/IG5ldyBGbG9hdDMyQXJyYXkoY3NOdW1Db21wcykgOiB0aGlzLnRtcENvbXBzQnVmOwogIH0KICBnZXQgaGFzRGF0YSgpIHsKICAgIGlmICh0aGlzLnN0cmVhbS5lbmQpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RyZWFtLnBvcyA8IHRoaXMuc3RyZWFtLmVuZDsKICAgIH0KICAgIGlmICh0aGlzLmJ1ZmZlckxlbmd0aCA+IDApIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBjb25zdCBuZXh0Qnl0ZSA9IHRoaXMuc3RyZWFtLmdldEJ5dGUoKTsKICAgIGlmIChuZXh0Qnl0ZSA8IDApIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgdGhpcy5idWZmZXIgPSBuZXh0Qnl0ZTsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gODsKICAgIHJldHVybiB0cnVlOwogIH0KICByZWFkQml0cyhuKSB7CiAgICBjb25zdCB7CiAgICAgIHN0cmVhbQogICAgfSA9IHRoaXM7CiAgICBsZXQgewogICAgICBidWZmZXIsCiAgICAgIGJ1ZmZlckxlbmd0aAogICAgfSA9IHRoaXM7CiAgICBpZiAobiA9PT0gMzIpIHsKICAgICAgaWYgKGJ1ZmZlckxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybiBzdHJlYW0uZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgfQogICAgICBidWZmZXIgPSBidWZmZXIgPDwgMjQgfCBzdHJlYW0uZ2V0Qnl0ZSgpIDw8IDE2IHwgc3RyZWFtLmdldEJ5dGUoKSA8PCA4IHwgc3RyZWFtLmdldEJ5dGUoKTsKICAgICAgY29uc3QgbmV4dEJ5dGUgPSBzdHJlYW0uZ2V0Qnl0ZSgpOwogICAgICB0aGlzLmJ1ZmZlciA9IG5leHRCeXRlICYgKDEgPDwgYnVmZmVyTGVuZ3RoKSAtIDE7CiAgICAgIHJldHVybiAoYnVmZmVyIDw8IDggLSBidWZmZXJMZW5ndGggfCAobmV4dEJ5dGUgJiAweGZmKSA+PiBidWZmZXJMZW5ndGgpID4+PiAwOwogICAgfQogICAgaWYgKG4gPT09IDggJiYgYnVmZmVyTGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBzdHJlYW0uZ2V0Qnl0ZSgpOwogICAgfQogICAgd2hpbGUgKGJ1ZmZlckxlbmd0aCA8IG4pIHsKICAgICAgYnVmZmVyID0gYnVmZmVyIDw8IDggfCBzdHJlYW0uZ2V0Qnl0ZSgpOwogICAgICBidWZmZXJMZW5ndGggKz0gODsKICAgIH0KICAgIGJ1ZmZlckxlbmd0aCAtPSBuOwogICAgdGhpcy5idWZmZXJMZW5ndGggPSBidWZmZXJMZW5ndGg7CiAgICB0aGlzLmJ1ZmZlciA9IGJ1ZmZlciAmICgxIDw8IGJ1ZmZlckxlbmd0aCkgLSAxOwogICAgcmV0dXJuIGJ1ZmZlciA+PiBidWZmZXJMZW5ndGg7CiAgfQogIGFsaWduKCkgewogICAgdGhpcy5idWZmZXIgPSAwOwogICAgdGhpcy5idWZmZXJMZW5ndGggPSAwOwogIH0KICByZWFkRmxhZygpIHsKICAgIHJldHVybiB0aGlzLnJlYWRCaXRzKHRoaXMuY29udGV4dC5iaXRzUGVyRmxhZyk7CiAgfQogIHJlYWRDb29yZGluYXRlKCkgewogICAgY29uc3QgewogICAgICBiaXRzUGVyQ29vcmRpbmF0ZSwKICAgICAgZGVjb2RlCiAgICB9ID0gdGhpcy5jb250ZXh0OwogICAgY29uc3QgeGkgPSB0aGlzLnJlYWRCaXRzKGJpdHNQZXJDb29yZGluYXRlKTsKICAgIGNvbnN0IHlpID0gdGhpcy5yZWFkQml0cyhiaXRzUGVyQ29vcmRpbmF0ZSk7CiAgICBjb25zdCBzY2FsZSA9IGJpdHNQZXJDb29yZGluYXRlIDwgMzIgPyAxIC8gKCgxIDw8IGJpdHNQZXJDb29yZGluYXRlKSAtIDEpIDogMi4zMjgzMDY0MzY1Mzg2OTYzZS0xMDsKICAgIHJldHVybiBbeGkgKiBzY2FsZSAqIChkZWNvZGVbMV0gLSBkZWNvZGVbMF0pICsgZGVjb2RlWzBdLCB5aSAqIHNjYWxlICogKGRlY29kZVszXSAtIGRlY29kZVsyXSkgKyBkZWNvZGVbMl1dOwogIH0KICByZWFkQ29tcG9uZW50cygpIHsKICAgIGNvbnN0IHsKICAgICAgYml0c1BlckNvbXBvbmVudCwKICAgICAgY29sb3JGbiwKICAgICAgY29sb3JTcGFjZSwKICAgICAgZGVjb2RlLAogICAgICBudW1Db21wcwogICAgfSA9IHRoaXMuY29udGV4dDsKICAgIGNvbnN0IHNjYWxlID0gYml0c1BlckNvbXBvbmVudCA8IDMyID8gMSAvICgoMSA8PCBiaXRzUGVyQ29tcG9uZW50KSAtIDEpIDogMi4zMjgzMDY0MzY1Mzg2OTYzZS0xMDsKICAgIGNvbnN0IGNvbXBvbmVudHMgPSB0aGlzLnRtcENvbXBzQnVmOwogICAgZm9yIChsZXQgaSA9IDAsIGogPSA0OyBpIDwgbnVtQ29tcHM7IGkrKywgaiArPSAyKSB7CiAgICAgIGNvbnN0IGNpID0gdGhpcy5yZWFkQml0cyhiaXRzUGVyQ29tcG9uZW50KTsKICAgICAgY29tcG9uZW50c1tpXSA9IGNpICogc2NhbGUgKiAoZGVjb2RlW2ogKyAxXSAtIGRlY29kZVtqXSkgKyBkZWNvZGVbal07CiAgICB9CiAgICBjb25zdCBjb2xvciA9IHRoaXMudG1wQ3NDb21wc0J1ZjsKICAgIGNvbG9yRm4/Lihjb21wb25lbnRzLCAwLCBjb2xvciwgMCk7CiAgICByZXR1cm4gY29sb3JTcGFjZS5nZXRSZ2IoY29sb3IsIDApOwogIH0KfQpsZXQgYkNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKZnVuY3Rpb24gYnVpbGRCKGNvdW50KSB7CiAgY29uc3QgbHV0ID0gW107CiAgZm9yIChsZXQgaSA9IDA7IGkgPD0gY291bnQ7IGkrKykgewogICAgY29uc3QgdCA9IGkgLyBjb3VudCwKICAgICAgdF8gPSAxIC0gdDsKICAgIGx1dC5wdXNoKG5ldyBGbG9hdDMyQXJyYXkoW3RfICoqIDMsIDMgKiB0ICogdF8gKiogMiwgMyAqIHQgKiogMiAqIHRfLCB0ICoqIDNdKSk7CiAgfQogIHJldHVybiBsdXQ7Cn0KZnVuY3Rpb24gZ2V0Qihjb3VudCkgewogIHJldHVybiBiQ2FjaGVbY291bnRdIHx8PSBidWlsZEIoY291bnQpOwp9CmZ1bmN0aW9uIGNsZWFyUGF0dGVybkNhY2hlcygpIHsKICBiQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwp9CmNsYXNzIE1lc2hTaGFkaW5nIGV4dGVuZHMgQmFzZVNoYWRpbmcgewogIHN0YXRpYyBNSU5fU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCA9IDM7CiAgc3RhdGljIE1BWF9TUExJVF9QQVRDSF9DSFVOS1NfQU1PVU5UID0gMjA7CiAgc3RhdGljIFRSSUFOR0xFX0RFTlNJVFkgPSAyMDsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIHhyZWYsIHJlc291cmNlcywgcGRmRnVuY3Rpb25GYWN0b3J5LCBnbG9iYWxDb2xvclNwYWNlQ2FjaGUsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKSB7CiAgICBzdXBlcigpOwogICAgaWYgKCEoc3RyZWFtIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJNZXNoIGRhdGEgaXMgbm90IGEgc3RyZWFtIik7CiAgICB9CiAgICBjb25zdCBkaWN0ID0gc3RyZWFtLmRpY3Q7CiAgICB0aGlzLnNoYWRpbmdUeXBlID0gZGljdC5nZXQoIlNoYWRpbmdUeXBlIik7CiAgICB0aGlzLmJib3ggPSBsb29rdXBOb3JtYWxSZWN0KGRpY3QuZ2V0QXJyYXkoIkJCb3giKSwgbnVsbCk7CiAgICBjb25zdCBjcyA9IENvbG9yU3BhY2VVdGlscy5wYXJzZSh7CiAgICAgIGNzOiBkaWN0LmdldFJhdygiQ1MiKSB8fCBkaWN0LmdldFJhdygiQ29sb3JTcGFjZSIpLAogICAgICB4cmVmLAogICAgICByZXNvdXJjZXMsCiAgICAgIHBkZkZ1bmN0aW9uRmFjdG9yeSwKICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgfSk7CiAgICB0aGlzLmJhY2tncm91bmQgPSBkaWN0LmhhcygiQmFja2dyb3VuZCIpID8gY3MuZ2V0UmdiKGRpY3QuZ2V0KCJCYWNrZ3JvdW5kIiksIDApIDogbnVsbDsKICAgIGNvbnN0IGZuT2JqID0gZGljdC5nZXRSYXcoIkZ1bmN0aW9uIik7CiAgICBjb25zdCBmbiA9IGZuT2JqID8gcGRmRnVuY3Rpb25GYWN0b3J5LmNyZWF0ZShmbk9iaiwgdHJ1ZSkgOiBudWxsOwogICAgdGhpcy5jb29yZHMgPSBbXTsKICAgIHRoaXMuY29sb3JzID0gW107CiAgICB0aGlzLmZpZ3VyZXMgPSBbXTsKICAgIGNvbnN0IGRlY29kZUNvbnRleHQgPSB7CiAgICAgIGJpdHNQZXJDb29yZGluYXRlOiBkaWN0LmdldCgiQml0c1BlckNvb3JkaW5hdGUiKSwKICAgICAgYml0c1BlckNvbXBvbmVudDogZGljdC5nZXQoIkJpdHNQZXJDb21wb25lbnQiKSwKICAgICAgYml0c1BlckZsYWc6IGRpY3QuZ2V0KCJCaXRzUGVyRmxhZyIpLAogICAgICBkZWNvZGU6IGRpY3QuZ2V0QXJyYXkoIkRlY29kZSIpLAogICAgICBjb2xvckZuOiBmbiwKICAgICAgY29sb3JTcGFjZTogY3MsCiAgICAgIG51bUNvbXBzOiBmbiA/IDEgOiBjcy5udW1Db21wcwogICAgfTsKICAgIGNvbnN0IHJlYWRlciA9IG5ldyBNZXNoU3RyZWFtUmVhZGVyKHN0cmVhbSwgZGVjb2RlQ29udGV4dCk7CiAgICBsZXQgcGF0Y2hNZXNoID0gZmFsc2U7CiAgICBzd2l0Y2ggKHRoaXMuc2hhZGluZ1R5cGUpIHsKICAgICAgY2FzZSBTaGFkaW5nVHlwZS5GUkVFX0ZPUk1fTUVTSDoKICAgICAgICB0aGlzLl9kZWNvZGVUeXBlNFNoYWRpbmcocmVhZGVyKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBTaGFkaW5nVHlwZS5MQVRUSUNFX0ZPUk1fTUVTSDoKICAgICAgICBjb25zdCB2ZXJ0aWNlc1BlclJvdyA9IGRpY3QuZ2V0KCJWZXJ0aWNlc1BlclJvdyIpIHwgMDsKICAgICAgICBpZiAodmVydGljZXNQZXJSb3cgPCAyKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgVmVydGljZXNQZXJSb3ciKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5fZGVjb2RlVHlwZTVTaGFkaW5nKHJlYWRlciwgdmVydGljZXNQZXJSb3cpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFNoYWRpbmdUeXBlLkNPT05TX1BBVENIX01FU0g6CiAgICAgICAgdGhpcy5fZGVjb2RlVHlwZTZTaGFkaW5nKHJlYWRlcik7CiAgICAgICAgcGF0Y2hNZXNoID0gdHJ1ZTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBTaGFkaW5nVHlwZS5URU5TT1JfUEFUQ0hfTUVTSDoKICAgICAgICB0aGlzLl9kZWNvZGVUeXBlN1NoYWRpbmcocmVhZGVyKTsKICAgICAgICBwYXRjaE1lc2ggPSB0cnVlOwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHVucmVhY2hhYmxlKCJVbnN1cHBvcnRlZCBtZXNoIHR5cGUuIik7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBpZiAocGF0Y2hNZXNoKSB7CiAgICAgIHRoaXMuX3VwZGF0ZUJvdW5kcygpOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB0aGlzLmZpZ3VyZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIHRoaXMuX2J1aWxkRmlndXJlRnJvbVBhdGNoKGkpOwogICAgICB9CiAgICB9CiAgICB0aGlzLl91cGRhdGVCb3VuZHMoKTsKICAgIHRoaXMuX3BhY2tEYXRhKCk7CiAgfQogIF9kZWNvZGVUeXBlNFNoYWRpbmcocmVhZGVyKSB7CiAgICBjb25zdCBjb29yZHMgPSB0aGlzLmNvb3JkczsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuY29sb3JzOwogICAgY29uc3Qgb3BlcmF0b3JzID0gW107CiAgICBjb25zdCBwcyA9IFtdOwogICAgbGV0IHZlcnRpY2VzTGVmdCA9IDA7CiAgICB3aGlsZSAocmVhZGVyLmhhc0RhdGEpIHsKICAgICAgY29uc3QgZiA9IHJlYWRlci5yZWFkRmxhZygpOwogICAgICBjb25zdCBjb29yZCA9IHJlYWRlci5yZWFkQ29vcmRpbmF0ZSgpOwogICAgICBjb25zdCBjb2xvciA9IHJlYWRlci5yZWFkQ29tcG9uZW50cygpOwogICAgICBpZiAodmVydGljZXNMZWZ0ID09PSAwKSB7CiAgICAgICAgaWYgKCEoMCA8PSBmICYmIGYgPD0gMikpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiVW5rbm93biB0eXBlNCBmbGFnIik7CiAgICAgICAgfQogICAgICAgIHN3aXRjaCAoZikgewogICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICB2ZXJ0aWNlc0xlZnQgPSAzOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgcHMucHVzaChwcy5hdCgtMiksIHBzLmF0KC0xKSk7CiAgICAgICAgICAgIHZlcnRpY2VzTGVmdCA9IDE7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICBwcy5wdXNoKHBzLmF0KC0zKSwgcHMuYXQoLTEpKTsKICAgICAgICAgICAgdmVydGljZXNMZWZ0ID0gMTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIG9wZXJhdG9ycy5wdXNoKGYpOwogICAgICB9CiAgICAgIHBzLnB1c2goY29vcmRzLmxlbmd0aCk7CiAgICAgIGNvb3Jkcy5wdXNoKGNvb3JkKTsKICAgICAgY29sb3JzLnB1c2goY29sb3IpOwogICAgICB2ZXJ0aWNlc0xlZnQtLTsKICAgICAgcmVhZGVyLmFsaWduKCk7CiAgICB9CiAgICB0aGlzLmZpZ3VyZXMucHVzaCh7CiAgICAgIHR5cGU6IE1lc2hGaWd1cmVUeXBlLlRSSUFOR0xFUywKICAgICAgY29vcmRzOiBuZXcgSW50MzJBcnJheShwcyksCiAgICAgIGNvbG9yczogbmV3IEludDMyQXJyYXkocHMpCiAgICB9KTsKICB9CiAgX2RlY29kZVR5cGU1U2hhZGluZyhyZWFkZXIsIHZlcnRpY2VzUGVyUm93KSB7CiAgICBjb25zdCBjb29yZHMgPSB0aGlzLmNvb3JkczsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuY29sb3JzOwogICAgY29uc3QgcHMgPSBbXTsKICAgIHdoaWxlIChyZWFkZXIuaGFzRGF0YSkgewogICAgICBjb25zdCBjb29yZCA9IHJlYWRlci5yZWFkQ29vcmRpbmF0ZSgpOwogICAgICBjb25zdCBjb2xvciA9IHJlYWRlci5yZWFkQ29tcG9uZW50cygpOwogICAgICBwcy5wdXNoKGNvb3Jkcy5sZW5ndGgpOwogICAgICBjb29yZHMucHVzaChjb29yZCk7CiAgICAgIGNvbG9ycy5wdXNoKGNvbG9yKTsKICAgIH0KICAgIHRoaXMuZmlndXJlcy5wdXNoKHsKICAgICAgdHlwZTogTWVzaEZpZ3VyZVR5cGUuTEFUVElDRSwKICAgICAgY29vcmRzOiBuZXcgSW50MzJBcnJheShwcyksCiAgICAgIGNvbG9yczogbmV3IEludDMyQXJyYXkocHMpLAogICAgICB2ZXJ0aWNlc1BlclJvdwogICAgfSk7CiAgfQogIF9kZWNvZGVUeXBlNlNoYWRpbmcocmVhZGVyKSB7CiAgICBjb25zdCBjb29yZHMgPSB0aGlzLmNvb3JkczsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuY29sb3JzOwogICAgY29uc3QgcHMgPSBuZXcgSW50MzJBcnJheSgxNik7CiAgICBjb25zdCBjcyA9IG5ldyBJbnQzMkFycmF5KDQpOwogICAgd2hpbGUgKHJlYWRlci5oYXNEYXRhKSB7CiAgICAgIGNvbnN0IGYgPSByZWFkZXIucmVhZEZsYWcoKTsKICAgICAgaWYgKCEoMCA8PSBmICYmIGYgPD0gMykpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gdHlwZTYgZmxhZyIpOwogICAgICB9CiAgICAgIGNvbnN0IHBpID0gY29vcmRzLmxlbmd0aDsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZiAhPT0gMCA/IDggOiAxMjsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb29yZHMucHVzaChyZWFkZXIucmVhZENvb3JkaW5hdGUoKSk7CiAgICAgIH0KICAgICAgY29uc3QgY2kgPSBjb2xvcnMubGVuZ3RoOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBmICE9PSAwID8gMiA6IDQ7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29sb3JzLnB1c2gocmVhZGVyLnJlYWRDb21wb25lbnRzKCkpOwogICAgICB9CiAgICAgIGxldCB0bXAxLCB0bXAyLCB0bXAzLCB0bXA0OwogICAgICBzd2l0Y2ggKGYpIHsKICAgICAgICBjYXNlIDA6CiAgICAgICAgICBwc1sxMl0gPSBwaSArIDM7CiAgICAgICAgICBwc1sxM10gPSBwaSArIDQ7CiAgICAgICAgICBwc1sxNF0gPSBwaSArIDU7CiAgICAgICAgICBwc1sxNV0gPSBwaSArIDY7CiAgICAgICAgICBwc1s4XSA9IHBpICsgMjsKICAgICAgICAgIHBzWzExXSA9IHBpICsgNzsKICAgICAgICAgIHBzWzRdID0gcGkgKyAxOwogICAgICAgICAgcHNbN10gPSBwaSArIDg7CiAgICAgICAgICBwc1swXSA9IHBpOwogICAgICAgICAgcHNbMV0gPSBwaSArIDExOwogICAgICAgICAgcHNbMl0gPSBwaSArIDEwOwogICAgICAgICAgcHNbM10gPSBwaSArIDk7CiAgICAgICAgICBjc1syXSA9IGNpICsgMTsKICAgICAgICAgIGNzWzNdID0gY2kgKyAyOwogICAgICAgICAgY3NbMF0gPSBjaTsKICAgICAgICAgIGNzWzFdID0gY2kgKyAzOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxOgogICAgICAgICAgdG1wMSA9IHBzWzEyXTsKICAgICAgICAgIHRtcDIgPSBwc1sxM107CiAgICAgICAgICB0bXAzID0gcHNbMTRdOwogICAgICAgICAgdG1wNCA9IHBzWzE1XTsKICAgICAgICAgIHBzWzEyXSA9IHRtcDQ7CiAgICAgICAgICBwc1sxM10gPSBwaSArIDA7CiAgICAgICAgICBwc1sxNF0gPSBwaSArIDE7CiAgICAgICAgICBwc1sxNV0gPSBwaSArIDI7CiAgICAgICAgICBwc1s4XSA9IHRtcDM7CiAgICAgICAgICBwc1sxMV0gPSBwaSArIDM7CiAgICAgICAgICBwc1s0XSA9IHRtcDI7CiAgICAgICAgICBwc1s3XSA9IHBpICsgNDsKICAgICAgICAgIHBzWzBdID0gdG1wMTsKICAgICAgICAgIHBzWzFdID0gcGkgKyA3OwogICAgICAgICAgcHNbMl0gPSBwaSArIDY7CiAgICAgICAgICBwc1szXSA9IHBpICsgNTsKICAgICAgICAgIHRtcDEgPSBjc1syXTsKICAgICAgICAgIHRtcDIgPSBjc1szXTsKICAgICAgICAgIGNzWzJdID0gdG1wMjsKICAgICAgICAgIGNzWzNdID0gY2k7CiAgICAgICAgICBjc1swXSA9IHRtcDE7CiAgICAgICAgICBjc1sxXSA9IGNpICsgMTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjoKICAgICAgICAgIHRtcDEgPSBwc1sxNV07CiAgICAgICAgICB0bXAyID0gcHNbMTFdOwogICAgICAgICAgcHNbMTJdID0gcHNbM107CiAgICAgICAgICBwc1sxM10gPSBwaSArIDA7CiAgICAgICAgICBwc1sxNF0gPSBwaSArIDE7CiAgICAgICAgICBwc1sxNV0gPSBwaSArIDI7CiAgICAgICAgICBwc1s4XSA9IHBzWzddOwogICAgICAgICAgcHNbMTFdID0gcGkgKyAzOwogICAgICAgICAgcHNbNF0gPSB0bXAyOwogICAgICAgICAgcHNbN10gPSBwaSArIDQ7CiAgICAgICAgICBwc1swXSA9IHRtcDE7CiAgICAgICAgICBwc1sxXSA9IHBpICsgNzsKICAgICAgICAgIHBzWzJdID0gcGkgKyA2OwogICAgICAgICAgcHNbM10gPSBwaSArIDU7CiAgICAgICAgICB0bXAxID0gY3NbM107CiAgICAgICAgICBjc1syXSA9IGNzWzFdOwogICAgICAgICAgY3NbM10gPSBjaTsKICAgICAgICAgIGNzWzBdID0gdG1wMTsKICAgICAgICAgIGNzWzFdID0gY2kgKyAxOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAzOgogICAgICAgICAgcHNbMTJdID0gcHNbMF07CiAgICAgICAgICBwc1sxM10gPSBwaSArIDA7CiAgICAgICAgICBwc1sxNF0gPSBwaSArIDE7CiAgICAgICAgICBwc1sxNV0gPSBwaSArIDI7CiAgICAgICAgICBwc1s4XSA9IHBzWzFdOwogICAgICAgICAgcHNbMTFdID0gcGkgKyAzOwogICAgICAgICAgcHNbNF0gPSBwc1syXTsKICAgICAgICAgIHBzWzddID0gcGkgKyA0OwogICAgICAgICAgcHNbMF0gPSBwc1szXTsKICAgICAgICAgIHBzWzFdID0gcGkgKyA3OwogICAgICAgICAgcHNbMl0gPSBwaSArIDY7CiAgICAgICAgICBwc1szXSA9IHBpICsgNTsKICAgICAgICAgIGNzWzJdID0gY3NbMF07CiAgICAgICAgICBjc1szXSA9IGNpOwogICAgICAgICAgY3NbMF0gPSBjc1sxXTsKICAgICAgICAgIGNzWzFdID0gY2kgKyAxOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgcHNbNV0gPSBjb29yZHMubGVuZ3RoOwogICAgICBjb29yZHMucHVzaChbKC00ICogY29vcmRzW3BzWzBdXVswXSAtIGNvb3Jkc1twc1sxNV1dWzBdICsgNiAqIChjb29yZHNbcHNbNF1dWzBdICsgY29vcmRzW3BzWzFdXVswXSkgLSAyICogKGNvb3Jkc1twc1sxMl1dWzBdICsgY29vcmRzW3BzWzNdXVswXSkgKyAzICogKGNvb3Jkc1twc1sxM11dWzBdICsgY29vcmRzW3BzWzddXVswXSkpIC8gOSwgKC00ICogY29vcmRzW3BzWzBdXVsxXSAtIGNvb3Jkc1twc1sxNV1dWzFdICsgNiAqIChjb29yZHNbcHNbNF1dWzFdICsgY29vcmRzW3BzWzFdXVsxXSkgLSAyICogKGNvb3Jkc1twc1sxMl1dWzFdICsgY29vcmRzW3BzWzNdXVsxXSkgKyAzICogKGNvb3Jkc1twc1sxM11dWzFdICsgY29vcmRzW3BzWzddXVsxXSkpIC8gOV0pOwogICAgICBwc1s2XSA9IGNvb3Jkcy5sZW5ndGg7CiAgICAgIGNvb3Jkcy5wdXNoKFsoLTQgKiBjb29yZHNbcHNbM11dWzBdIC0gY29vcmRzW3BzWzEyXV1bMF0gKyA2ICogKGNvb3Jkc1twc1syXV1bMF0gKyBjb29yZHNbcHNbN11dWzBdKSAtIDIgKiAoY29vcmRzW3BzWzBdXVswXSArIGNvb3Jkc1twc1sxNV1dWzBdKSArIDMgKiAoY29vcmRzW3BzWzRdXVswXSArIGNvb3Jkc1twc1sxNF1dWzBdKSkgLyA5LCAoLTQgKiBjb29yZHNbcHNbM11dWzFdIC0gY29vcmRzW3BzWzEyXV1bMV0gKyA2ICogKGNvb3Jkc1twc1syXV1bMV0gKyBjb29yZHNbcHNbN11dWzFdKSAtIDIgKiAoY29vcmRzW3BzWzBdXVsxXSArIGNvb3Jkc1twc1sxNV1dWzFdKSArIDMgKiAoY29vcmRzW3BzWzRdXVsxXSArIGNvb3Jkc1twc1sxNF1dWzFdKSkgLyA5XSk7CiAgICAgIHBzWzldID0gY29vcmRzLmxlbmd0aDsKICAgICAgY29vcmRzLnB1c2goWygtNCAqIGNvb3Jkc1twc1sxMl1dWzBdIC0gY29vcmRzW3BzWzNdXVswXSArIDYgKiAoY29vcmRzW3BzWzhdXVswXSArIGNvb3Jkc1twc1sxM11dWzBdKSAtIDIgKiAoY29vcmRzW3BzWzBdXVswXSArIGNvb3Jkc1twc1sxNV1dWzBdKSArIDMgKiAoY29vcmRzW3BzWzExXV1bMF0gKyBjb29yZHNbcHNbMV1dWzBdKSkgLyA5LCAoLTQgKiBjb29yZHNbcHNbMTJdXVsxXSAtIGNvb3Jkc1twc1szXV1bMV0gKyA2ICogKGNvb3Jkc1twc1s4XV1bMV0gKyBjb29yZHNbcHNbMTNdXVsxXSkgLSAyICogKGNvb3Jkc1twc1swXV1bMV0gKyBjb29yZHNbcHNbMTVdXVsxXSkgKyAzICogKGNvb3Jkc1twc1sxMV1dWzFdICsgY29vcmRzW3BzWzFdXVsxXSkpIC8gOV0pOwogICAgICBwc1sxMF0gPSBjb29yZHMubGVuZ3RoOwogICAgICBjb29yZHMucHVzaChbKC00ICogY29vcmRzW3BzWzE1XV1bMF0gLSBjb29yZHNbcHNbMF1dWzBdICsgNiAqIChjb29yZHNbcHNbMTFdXVswXSArIGNvb3Jkc1twc1sxNF1dWzBdKSAtIDIgKiAoY29vcmRzW3BzWzEyXV1bMF0gKyBjb29yZHNbcHNbM11dWzBdKSArIDMgKiAoY29vcmRzW3BzWzJdXVswXSArIGNvb3Jkc1twc1s4XV1bMF0pKSAvIDksICgtNCAqIGNvb3Jkc1twc1sxNV1dWzFdIC0gY29vcmRzW3BzWzBdXVsxXSArIDYgKiAoY29vcmRzW3BzWzExXV1bMV0gKyBjb29yZHNbcHNbMTRdXVsxXSkgLSAyICogKGNvb3Jkc1twc1sxMl1dWzFdICsgY29vcmRzW3BzWzNdXVsxXSkgKyAzICogKGNvb3Jkc1twc1syXV1bMV0gKyBjb29yZHNbcHNbOF1dWzFdKSkgLyA5XSk7CiAgICAgIHRoaXMuZmlndXJlcy5wdXNoKHsKICAgICAgICB0eXBlOiBNZXNoRmlndXJlVHlwZS5QQVRDSCwKICAgICAgICBjb29yZHM6IG5ldyBJbnQzMkFycmF5KHBzKSwKICAgICAgICBjb2xvcnM6IG5ldyBJbnQzMkFycmF5KGNzKQogICAgICB9KTsKICAgIH0KICB9CiAgX2RlY29kZVR5cGU3U2hhZGluZyhyZWFkZXIpIHsKICAgIGNvbnN0IGNvb3JkcyA9IHRoaXMuY29vcmRzOwogICAgY29uc3QgY29sb3JzID0gdGhpcy5jb2xvcnM7CiAgICBjb25zdCBwcyA9IG5ldyBJbnQzMkFycmF5KDE2KTsKICAgIGNvbnN0IGNzID0gbmV3IEludDMyQXJyYXkoNCk7CiAgICB3aGlsZSAocmVhZGVyLmhhc0RhdGEpIHsKICAgICAgY29uc3QgZiA9IHJlYWRlci5yZWFkRmxhZygpOwogICAgICBpZiAoISgwIDw9IGYgJiYgZiA8PSAzKSkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiVW5rbm93biB0eXBlNyBmbGFnIik7CiAgICAgIH0KICAgICAgY29uc3QgcGkgPSBjb29yZHMubGVuZ3RoOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBmICE9PSAwID8gMTIgOiAxNjsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb29yZHMucHVzaChyZWFkZXIucmVhZENvb3JkaW5hdGUoKSk7CiAgICAgIH0KICAgICAgY29uc3QgY2kgPSBjb2xvcnMubGVuZ3RoOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBmICE9PSAwID8gMiA6IDQ7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29sb3JzLnB1c2gocmVhZGVyLnJlYWRDb21wb25lbnRzKCkpOwogICAgICB9CiAgICAgIGxldCB0bXAxLCB0bXAyLCB0bXAzLCB0bXA0OwogICAgICBzd2l0Y2ggKGYpIHsKICAgICAgICBjYXNlIDA6CiAgICAgICAgICBwc1sxMl0gPSBwaSArIDM7CiAgICAgICAgICBwc1sxM10gPSBwaSArIDQ7CiAgICAgICAgICBwc1sxNF0gPSBwaSArIDU7CiAgICAgICAgICBwc1sxNV0gPSBwaSArIDY7CiAgICAgICAgICBwc1s4XSA9IHBpICsgMjsKICAgICAgICAgIHBzWzldID0gcGkgKyAxMzsKICAgICAgICAgIHBzWzEwXSA9IHBpICsgMTQ7CiAgICAgICAgICBwc1sxMV0gPSBwaSArIDc7CiAgICAgICAgICBwc1s0XSA9IHBpICsgMTsKICAgICAgICAgIHBzWzVdID0gcGkgKyAxMjsKICAgICAgICAgIHBzWzZdID0gcGkgKyAxNTsKICAgICAgICAgIHBzWzddID0gcGkgKyA4OwogICAgICAgICAgcHNbMF0gPSBwaTsKICAgICAgICAgIHBzWzFdID0gcGkgKyAxMTsKICAgICAgICAgIHBzWzJdID0gcGkgKyAxMDsKICAgICAgICAgIHBzWzNdID0gcGkgKyA5OwogICAgICAgICAgY3NbMl0gPSBjaSArIDE7CiAgICAgICAgICBjc1szXSA9IGNpICsgMjsKICAgICAgICAgIGNzWzBdID0gY2k7CiAgICAgICAgICBjc1sxXSA9IGNpICsgMzsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMToKICAgICAgICAgIHRtcDEgPSBwc1sxMl07CiAgICAgICAgICB0bXAyID0gcHNbMTNdOwogICAgICAgICAgdG1wMyA9IHBzWzE0XTsKICAgICAgICAgIHRtcDQgPSBwc1sxNV07CiAgICAgICAgICBwc1sxMl0gPSB0bXA0OwogICAgICAgICAgcHNbMTNdID0gcGkgKyAwOwogICAgICAgICAgcHNbMTRdID0gcGkgKyAxOwogICAgICAgICAgcHNbMTVdID0gcGkgKyAyOwogICAgICAgICAgcHNbOF0gPSB0bXAzOwogICAgICAgICAgcHNbOV0gPSBwaSArIDk7CiAgICAgICAgICBwc1sxMF0gPSBwaSArIDEwOwogICAgICAgICAgcHNbMTFdID0gcGkgKyAzOwogICAgICAgICAgcHNbNF0gPSB0bXAyOwogICAgICAgICAgcHNbNV0gPSBwaSArIDg7CiAgICAgICAgICBwc1s2XSA9IHBpICsgMTE7CiAgICAgICAgICBwc1s3XSA9IHBpICsgNDsKICAgICAgICAgIHBzWzBdID0gdG1wMTsKICAgICAgICAgIHBzWzFdID0gcGkgKyA3OwogICAgICAgICAgcHNbMl0gPSBwaSArIDY7CiAgICAgICAgICBwc1szXSA9IHBpICsgNTsKICAgICAgICAgIHRtcDEgPSBjc1syXTsKICAgICAgICAgIHRtcDIgPSBjc1szXTsKICAgICAgICAgIGNzWzJdID0gdG1wMjsKICAgICAgICAgIGNzWzNdID0gY2k7CiAgICAgICAgICBjc1swXSA9IHRtcDE7CiAgICAgICAgICBjc1sxXSA9IGNpICsgMTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjoKICAgICAgICAgIHRtcDEgPSBwc1sxNV07CiAgICAgICAgICB0bXAyID0gcHNbMTFdOwogICAgICAgICAgcHNbMTJdID0gcHNbM107CiAgICAgICAgICBwc1sxM10gPSBwaSArIDA7CiAgICAgICAgICBwc1sxNF0gPSBwaSArIDE7CiAgICAgICAgICBwc1sxNV0gPSBwaSArIDI7CiAgICAgICAgICBwc1s4XSA9IHBzWzddOwogICAgICAgICAgcHNbOV0gPSBwaSArIDk7CiAgICAgICAgICBwc1sxMF0gPSBwaSArIDEwOwogICAgICAgICAgcHNbMTFdID0gcGkgKyAzOwogICAgICAgICAgcHNbNF0gPSB0bXAyOwogICAgICAgICAgcHNbNV0gPSBwaSArIDg7CiAgICAgICAgICBwc1s2XSA9IHBpICsgMTE7CiAgICAgICAgICBwc1s3XSA9IHBpICsgNDsKICAgICAgICAgIHBzWzBdID0gdG1wMTsKICAgICAgICAgIHBzWzFdID0gcGkgKyA3OwogICAgICAgICAgcHNbMl0gPSBwaSArIDY7CiAgICAgICAgICBwc1szXSA9IHBpICsgNTsKICAgICAgICAgIHRtcDEgPSBjc1szXTsKICAgICAgICAgIGNzWzJdID0gY3NbMV07CiAgICAgICAgICBjc1szXSA9IGNpOwogICAgICAgICAgY3NbMF0gPSB0bXAxOwogICAgICAgICAgY3NbMV0gPSBjaSArIDE7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDM6CiAgICAgICAgICBwc1sxMl0gPSBwc1swXTsKICAgICAgICAgIHBzWzEzXSA9IHBpICsgMDsKICAgICAgICAgIHBzWzE0XSA9IHBpICsgMTsKICAgICAgICAgIHBzWzE1XSA9IHBpICsgMjsKICAgICAgICAgIHBzWzhdID0gcHNbMV07CiAgICAgICAgICBwc1s5XSA9IHBpICsgOTsKICAgICAgICAgIHBzWzEwXSA9IHBpICsgMTA7CiAgICAgICAgICBwc1sxMV0gPSBwaSArIDM7CiAgICAgICAgICBwc1s0XSA9IHBzWzJdOwogICAgICAgICAgcHNbNV0gPSBwaSArIDg7CiAgICAgICAgICBwc1s2XSA9IHBpICsgMTE7CiAgICAgICAgICBwc1s3XSA9IHBpICsgNDsKICAgICAgICAgIHBzWzBdID0gcHNbM107CiAgICAgICAgICBwc1sxXSA9IHBpICsgNzsKICAgICAgICAgIHBzWzJdID0gcGkgKyA2OwogICAgICAgICAgcHNbM10gPSBwaSArIDU7CiAgICAgICAgICBjc1syXSA9IGNzWzBdOwogICAgICAgICAgY3NbM10gPSBjaTsKICAgICAgICAgIGNzWzBdID0gY3NbMV07CiAgICAgICAgICBjc1sxXSA9IGNpICsgMTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHRoaXMuZmlndXJlcy5wdXNoKHsKICAgICAgICB0eXBlOiBNZXNoRmlndXJlVHlwZS5QQVRDSCwKICAgICAgICBjb29yZHM6IG5ldyBJbnQzMkFycmF5KHBzKSwKICAgICAgICBjb2xvcnM6IG5ldyBJbnQzMkFycmF5KGNzKQogICAgICB9KTsKICAgIH0KICB9CiAgX2J1aWxkRmlndXJlRnJvbVBhdGNoKGluZGV4KSB7CiAgICBjb25zdCBmaWd1cmUgPSB0aGlzLmZpZ3VyZXNbaW5kZXhdOwogICAgYXNzZXJ0KGZpZ3VyZS50eXBlID09PSBNZXNoRmlndXJlVHlwZS5QQVRDSCwgIlVuZXhwZWN0ZWQgcGF0Y2ggbWVzaCBmaWd1cmUiKTsKICAgIGNvbnN0IGNvb3JkcyA9IHRoaXMuY29vcmRzLAogICAgICBjb2xvcnMgPSB0aGlzLmNvbG9yczsKICAgIGNvbnN0IHBpID0gZmlndXJlLmNvb3JkczsKICAgIGNvbnN0IGNpID0gZmlndXJlLmNvbG9yczsKICAgIGNvbnN0IGZpZ3VyZU1pblggPSBNYXRoLm1pbihjb29yZHNbcGlbMF1dWzBdLCBjb29yZHNbcGlbM11dWzBdLCBjb29yZHNbcGlbMTJdXVswXSwgY29vcmRzW3BpWzE1XV1bMF0pOwogICAgY29uc3QgZmlndXJlTWluWSA9IE1hdGgubWluKGNvb3Jkc1twaVswXV1bMV0sIGNvb3Jkc1twaVszXV1bMV0sIGNvb3Jkc1twaVsxMl1dWzFdLCBjb29yZHNbcGlbMTVdXVsxXSk7CiAgICBjb25zdCBmaWd1cmVNYXhYID0gTWF0aC5tYXgoY29vcmRzW3BpWzBdXVswXSwgY29vcmRzW3BpWzNdXVswXSwgY29vcmRzW3BpWzEyXV1bMF0sIGNvb3Jkc1twaVsxNV1dWzBdKTsKICAgIGNvbnN0IGZpZ3VyZU1heFkgPSBNYXRoLm1heChjb29yZHNbcGlbMF1dWzFdLCBjb29yZHNbcGlbM11dWzFdLCBjb29yZHNbcGlbMTJdXVsxXSwgY29vcmRzW3BpWzE1XV1bMV0pOwogICAgbGV0IHNwbGl0WEJ5ID0gTWF0aC5jZWlsKChmaWd1cmVNYXhYIC0gZmlndXJlTWluWCkgKiBNZXNoU2hhZGluZy5UUklBTkdMRV9ERU5TSVRZIC8gKHRoaXMuYm91bmRzWzJdIC0gdGhpcy5ib3VuZHNbMF0pKTsKICAgIHNwbGl0WEJ5ID0gTWF0aENsYW1wKHNwbGl0WEJ5LCBNZXNoU2hhZGluZy5NSU5fU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCwgTWVzaFNoYWRpbmcuTUFYX1NQTElUX1BBVENIX0NIVU5LU19BTU9VTlQpOwogICAgbGV0IHNwbGl0WUJ5ID0gTWF0aC5jZWlsKChmaWd1cmVNYXhZIC0gZmlndXJlTWluWSkgKiBNZXNoU2hhZGluZy5UUklBTkdMRV9ERU5TSVRZIC8gKHRoaXMuYm91bmRzWzNdIC0gdGhpcy5ib3VuZHNbMV0pKTsKICAgIHNwbGl0WUJ5ID0gTWF0aENsYW1wKHNwbGl0WUJ5LCBNZXNoU2hhZGluZy5NSU5fU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCwgTWVzaFNoYWRpbmcuTUFYX1NQTElUX1BBVENIX0NIVU5LU19BTU9VTlQpOwogICAgY29uc3QgdmVydGljZXNQZXJSb3cgPSBzcGxpdFhCeSArIDE7CiAgICBjb25zdCBmaWd1cmVDb29yZHMgPSBuZXcgSW50MzJBcnJheSgoc3BsaXRZQnkgKyAxKSAqIHZlcnRpY2VzUGVyUm93KTsKICAgIGNvbnN0IGZpZ3VyZUNvbG9ycyA9IG5ldyBJbnQzMkFycmF5KChzcGxpdFlCeSArIDEpICogdmVydGljZXNQZXJSb3cpOwogICAgbGV0IGsgPSAwOwogICAgY29uc3QgY2wgPSBuZXcgVWludDhBcnJheSgzKSwKICAgICAgY3IgPSBuZXcgVWludDhBcnJheSgzKTsKICAgIGNvbnN0IGMwID0gY29sb3JzW2NpWzBdXSwKICAgICAgYzEgPSBjb2xvcnNbY2lbMV1dLAogICAgICBjMiA9IGNvbG9yc1tjaVsyXV0sCiAgICAgIGMzID0gY29sb3JzW2NpWzNdXTsKICAgIGNvbnN0IGJSb3cgPSBnZXRCKHNwbGl0WUJ5KSwKICAgICAgYkNvbCA9IGdldEIoc3BsaXRYQnkpOwogICAgZm9yIChsZXQgcm93ID0gMDsgcm93IDw9IHNwbGl0WUJ5OyByb3crKykgewogICAgICBjbFswXSA9IChjMFswXSAqIChzcGxpdFlCeSAtIHJvdykgKyBjMlswXSAqIHJvdykgLyBzcGxpdFlCeSB8IDA7CiAgICAgIGNsWzFdID0gKGMwWzFdICogKHNwbGl0WUJ5IC0gcm93KSArIGMyWzFdICogcm93KSAvIHNwbGl0WUJ5IHwgMDsKICAgICAgY2xbMl0gPSAoYzBbMl0gKiAoc3BsaXRZQnkgLSByb3cpICsgYzJbMl0gKiByb3cpIC8gc3BsaXRZQnkgfCAwOwogICAgICBjclswXSA9IChjMVswXSAqIChzcGxpdFlCeSAtIHJvdykgKyBjM1swXSAqIHJvdykgLyBzcGxpdFlCeSB8IDA7CiAgICAgIGNyWzFdID0gKGMxWzFdICogKHNwbGl0WUJ5IC0gcm93KSArIGMzWzFdICogcm93KSAvIHNwbGl0WUJ5IHwgMDsKICAgICAgY3JbMl0gPSAoYzFbMl0gKiAoc3BsaXRZQnkgLSByb3cpICsgYzNbMl0gKiByb3cpIC8gc3BsaXRZQnkgfCAwOwogICAgICBmb3IgKGxldCBjb2wgPSAwOyBjb2wgPD0gc3BsaXRYQnk7IGNvbCsrLCBrKyspIHsKICAgICAgICBpZiAoKHJvdyA9PT0gMCB8fCByb3cgPT09IHNwbGl0WUJ5KSAmJiAoY29sID09PSAwIHx8IGNvbCA9PT0gc3BsaXRYQnkpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgbGV0IHggPSAwLAogICAgICAgICAgeSA9IDA7CiAgICAgICAgbGV0IHEgPSAwOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IDM7IGkrKykgewogICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPD0gMzsgaisrLCBxKyspIHsKICAgICAgICAgICAgY29uc3QgbSA9IGJSb3dbcm93XVtpXSAqIGJDb2xbY29sXVtqXTsKICAgICAgICAgICAgeCArPSBjb29yZHNbcGlbcV1dWzBdICogbTsKICAgICAgICAgICAgeSArPSBjb29yZHNbcGlbcV1dWzFdICogbTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZmlndXJlQ29vcmRzW2tdID0gY29vcmRzLmxlbmd0aDsKICAgICAgICBjb29yZHMucHVzaChbeCwgeV0pOwogICAgICAgIGZpZ3VyZUNvbG9yc1trXSA9IGNvbG9ycy5sZW5ndGg7CiAgICAgICAgY29uc3QgbmV3Q29sb3IgPSBuZXcgVWludDhBcnJheSgzKTsKICAgICAgICBuZXdDb2xvclswXSA9IChjbFswXSAqIChzcGxpdFhCeSAtIGNvbCkgKyBjclswXSAqIGNvbCkgLyBzcGxpdFhCeSB8IDA7CiAgICAgICAgbmV3Q29sb3JbMV0gPSAoY2xbMV0gKiAoc3BsaXRYQnkgLSBjb2wpICsgY3JbMV0gKiBjb2wpIC8gc3BsaXRYQnkgfCAwOwogICAgICAgIG5ld0NvbG9yWzJdID0gKGNsWzJdICogKHNwbGl0WEJ5IC0gY29sKSArIGNyWzJdICogY29sKSAvIHNwbGl0WEJ5IHwgMDsKICAgICAgICBjb2xvcnMucHVzaChuZXdDb2xvcik7CiAgICAgIH0KICAgIH0KICAgIGZpZ3VyZUNvb3Jkc1swXSA9IHBpWzBdOwogICAgZmlndXJlQ29sb3JzWzBdID0gY2lbMF07CiAgICBmaWd1cmVDb29yZHNbc3BsaXRYQnldID0gcGlbM107CiAgICBmaWd1cmVDb2xvcnNbc3BsaXRYQnldID0gY2lbMV07CiAgICBmaWd1cmVDb29yZHNbdmVydGljZXNQZXJSb3cgKiBzcGxpdFlCeV0gPSBwaVsxMl07CiAgICBmaWd1cmVDb2xvcnNbdmVydGljZXNQZXJSb3cgKiBzcGxpdFlCeV0gPSBjaVsyXTsKICAgIGZpZ3VyZUNvb3Jkc1t2ZXJ0aWNlc1BlclJvdyAqIHNwbGl0WUJ5ICsgc3BsaXRYQnldID0gcGlbMTVdOwogICAgZmlndXJlQ29sb3JzW3ZlcnRpY2VzUGVyUm93ICogc3BsaXRZQnkgKyBzcGxpdFhCeV0gPSBjaVszXTsKICAgIHRoaXMuZmlndXJlc1tpbmRleF0gPSB7CiAgICAgIHR5cGU6IE1lc2hGaWd1cmVUeXBlLkxBVFRJQ0UsCiAgICAgIGNvb3JkczogZmlndXJlQ29vcmRzLAogICAgICBjb2xvcnM6IGZpZ3VyZUNvbG9ycywKICAgICAgdmVydGljZXNQZXJSb3cKICAgIH07CiAgfQogIF91cGRhdGVCb3VuZHMoKSB7CiAgICBsZXQgbWluWCA9IHRoaXMuY29vcmRzWzBdWzBdLAogICAgICBtaW5ZID0gdGhpcy5jb29yZHNbMF1bMV0sCiAgICAgIG1heFggPSBtaW5YLAogICAgICBtYXhZID0gbWluWTsKICAgIGZvciAobGV0IGkgPSAxLCBpaSA9IHRoaXMuY29vcmRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgeCA9IHRoaXMuY29vcmRzW2ldWzBdLAogICAgICAgIHkgPSB0aGlzLmNvb3Jkc1tpXVsxXTsKICAgICAgbWluWCA9IG1pblggPiB4ID8geCA6IG1pblg7CiAgICAgIG1pblkgPSBtaW5ZID4geSA/IHkgOiBtaW5ZOwogICAgICBtYXhYID0gbWF4WCA8IHggPyB4IDogbWF4WDsKICAgICAgbWF4WSA9IG1heFkgPCB5ID8geSA6IG1heFk7CiAgICB9CiAgICB0aGlzLmJvdW5kcyA9IFttaW5YLCBtaW5ZLCBtYXhYLCBtYXhZXTsKICB9CiAgX3BhY2tEYXRhKCkgewogICAgbGV0IGksIGlpLCBqLCBqajsKICAgIGNvbnN0IGNvb3JkcyA9IHRoaXMuY29vcmRzOwogICAgY29uc3QgY29vcmRzUGFja2VkID0gbmV3IEZsb2F0MzJBcnJheShjb29yZHMubGVuZ3RoICogMik7CiAgICBmb3IgKGkgPSAwLCBqID0gMCwgaWkgPSBjb29yZHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCB4eSA9IGNvb3Jkc1tpXTsKICAgICAgY29vcmRzUGFja2VkW2orK10gPSB4eVswXTsKICAgICAgY29vcmRzUGFja2VkW2orK10gPSB4eVsxXTsKICAgIH0KICAgIHRoaXMuY29vcmRzID0gY29vcmRzUGFja2VkOwogICAgY29uc3QgY29sb3JzID0gdGhpcy5jb2xvcnM7CiAgICBjb25zdCBjb2xvcnNQYWNrZWQgPSBuZXcgVWludDhBcnJheShjb2xvcnMubGVuZ3RoICogMyk7CiAgICBmb3IgKGkgPSAwLCBqID0gMCwgaWkgPSBjb2xvcnMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBjID0gY29sb3JzW2ldOwogICAgICBjb2xvcnNQYWNrZWRbaisrXSA9IGNbMF07CiAgICAgIGNvbG9yc1BhY2tlZFtqKytdID0gY1sxXTsKICAgICAgY29sb3JzUGFja2VkW2orK10gPSBjWzJdOwogICAgfQogICAgdGhpcy5jb2xvcnMgPSBjb2xvcnNQYWNrZWQ7CiAgICBjb25zdCBmaWd1cmVzID0gdGhpcy5maWd1cmVzOwogICAgZm9yIChpID0gMCwgaWkgPSBmaWd1cmVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgZmlndXJlID0gZmlndXJlc1tpXSwKICAgICAgICBwcyA9IGZpZ3VyZS5jb29yZHMsCiAgICAgICAgY3MgPSBmaWd1cmUuY29sb3JzOwogICAgICBmb3IgKGogPSAwLCBqaiA9IHBzLmxlbmd0aDsgaiA8IGpqOyBqKyspIHsKICAgICAgICBwc1tqXSAqPSAyOwogICAgICAgIGNzW2pdICo9IDM7CiAgICAgIH0KICAgIH0KICB9CiAgZ2V0SVIoKSB7CiAgICBjb25zdCB7CiAgICAgIGJvdW5kcwogICAgfSA9IHRoaXM7CiAgICBpZiAoYm91bmRzWzJdIC0gYm91bmRzWzBdID09PSAwIHx8IGJvdW5kc1szXSAtIGJvdW5kc1sxXSA9PT0gMCkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgTWVzaFNoYWRpbmcgYm91bmRzOiBbJHtib3VuZHN9XS5gKTsKICAgIH0KICAgIHJldHVybiBbIk1lc2giLCB0aGlzLnNoYWRpbmdUeXBlLCB0aGlzLmNvb3JkcywgdGhpcy5jb2xvcnMsIHRoaXMuZmlndXJlcywgYm91bmRzLCB0aGlzLmJib3gsIHRoaXMuYmFja2dyb3VuZF07CiAgfQp9CmNsYXNzIER1bW15U2hhZGluZyBleHRlbmRzIEJhc2VTaGFkaW5nIHsKICBnZXRJUigpIHsKICAgIHJldHVybiBbIkR1bW15Il07CiAgfQp9CmZ1bmN0aW9uIGdldFRpbGluZ1BhdHRlcm5JUihvcGVyYXRvckxpc3QsIGRpY3QsIGNvbG9yKSB7CiAgY29uc3QgbWF0cml4ID0gbG9va3VwTWF0cml4KGRpY3QuZ2V0QXJyYXkoIk1hdHJpeCIpLCBJREVOVElUWV9NQVRSSVgpOwogIGNvbnN0IGJib3ggPSBsb29rdXBOb3JtYWxSZWN0KGRpY3QuZ2V0QXJyYXkoIkJCb3giKSwgbnVsbCk7CiAgaWYgKCFiYm94IHx8IGJib3hbMl0gLSBiYm94WzBdID09PSAwIHx8IGJib3hbM10gLSBiYm94WzFdID09PSAwKSB7CiAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgZ2V0VGlsaW5nUGF0dGVybklSIC9CQm94IGFycmF5LmApOwogIH0KICBjb25zdCB4c3RlcCA9IGRpY3QuZ2V0KCJYU3RlcCIpOwogIGlmICh0eXBlb2YgeHN0ZXAgIT09ICJudW1iZXIiKSB7CiAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgZ2V0VGlsaW5nUGF0dGVybklSIC9YU3RlcCB2YWx1ZS5gKTsKICB9CiAgY29uc3QgeXN0ZXAgPSBkaWN0LmdldCgiWVN0ZXAiKTsKICBpZiAodHlwZW9mIHlzdGVwICE9PSAibnVtYmVyIikgewogICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIGdldFRpbGluZ1BhdHRlcm5JUiAvWVN0ZXAgdmFsdWUuYCk7CiAgfQogIGNvbnN0IHBhaW50VHlwZSA9IGRpY3QuZ2V0KCJQYWludFR5cGUiKTsKICBpZiAoIU51bWJlci5pc0ludGVnZXIocGFpbnRUeXBlKSkgewogICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIGdldFRpbGluZ1BhdHRlcm5JUiAvUGFpbnRUeXBlIHZhbHVlLmApOwogIH0KICBjb25zdCB0aWxpbmdUeXBlID0gZGljdC5nZXQoIlRpbGluZ1R5cGUiKTsKICBpZiAoIU51bWJlci5pc0ludGVnZXIodGlsaW5nVHlwZSkpIHsKICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBnZXRUaWxpbmdQYXR0ZXJuSVIgL1RpbGluZ1R5cGUgdmFsdWUuYCk7CiAgfQogIHJldHVybiBbIlRpbGluZ1BhdHRlcm4iLCBjb2xvciwgb3BlcmF0b3JMaXN0LCBtYXRyaXgsIGJib3gsIHhzdGVwLCB5c3RlcCwgcGFpbnRUeXBlLCB0aWxpbmdUeXBlXTsKfQoKOy8vIC4vc3JjL2NvcmUvY2FsaWJyaV9mYWN0b3JzLmpzCmNvbnN0IENhbGlicmlCb2xkRmFjdG9ycyA9IFsxLjM4NzcsIDEsIDEsIDEsIDAuOTc4MDEsIDAuOTI0ODIsIDAuODk1NTIsIDAuOTExMzMsIDAuODE5ODgsIDAuOTc1NjYsIDAuOTgxNTIsIDAuOTM1NDgsIDAuOTM1NDgsIDEuMjc5OCwgMC44NTI4NCwgMC45Mjc5NCwgMSwgMC45NjEzNCwgMS41NDY1NywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC44Mjg0NSwgMC44Mjg0NSwgMC44NTI4NCwgMC44NTI4NCwgMC44NTI4NCwgMC43NTg1OSwgMC45MjEzOCwgMC44MzkwOCwgMC43NzYyLCAwLjczMjkzLCAwLjg3Mjg5LCAwLjczMTMzLCAwLjc1MTQsIDAuODE5MjEsIDAuODczNTYsIDAuOTU5NTgsIDAuNTk1MjYsIDAuNzU3MjcsIDAuNjkyMjUsIDEuMDQ5MjQsIDAuOTEyMSwgMC44Njk0MywgMC43OTc5NSwgMC44ODE5OCwgMC43Nzk1OCwgMC43MDg2NCwgMC44MTA1NSwgMC45MDM5OSwgMC44ODY1MywgMC45NjAxNywgMC44MjU3NywgMC43Nzg5MiwgMC43ODI1NywgMC45NzUwNywgMS41NDY1NywgMC45NzUwNywgMC44NTI4NCwgMC44OTU1MiwgMC45MDE3NiwgMC44ODc2MiwgMC44Nzg1LCAwLjc1MjQxLCAwLjg3ODUsIDAuOTA1MTgsIDAuOTUwMTUsIDAuNzc2MTgsIDAuODc4NSwgMC44ODQwMSwgMC45MTkxNiwgMC44NjMwNCwgMC44ODQwMSwgMC45MTQ4OCwgMC44Nzg1LCAwLjg4MDEsIDAuODc4NSwgMC44Nzg1LCAwLjkxMzQzLCAwLjcxNzMsIDEuMDQxMDYsIDAuODc4NSwgMC44NTA3NSwgMC45NTc5NCwgMC44MjYxNiwgMC44NTE2MiwgMC43OTQ5MiwgMC44ODMzMSwgMS42OTgwOCwgMC44ODMzMSwgMC44NTI4NCwgMC45NzgwMSwgMC44OTU1MiwgMC45MTEzMywgMC44OTU1MiwgMC45MTEzMywgMS43ODAxLCAwLjg5NTUyLCAxLjI0NDg3LCAxLjEzMjU0LCAxLjEyNDAxLCAwLjk2ODM5LCAwLjg1Mjg0LCAwLjY4Nzg3LCAwLjcwNjQ1LCAwLjg1NTkyLCAwLjkwNzQ3LCAxLjAxNDY2LCAxLjAwODgsIDAuOTAzMjMsIDEsIDEuMDc0NjMsIDEsIDAuOTEwNTYsIDAuNzU4MDYsIDEuMTkxMTgsIDAuOTY4MzksIDAuNzg4NjQsIDAuODI4NDUsIDAuODQxMzMsIDAuNzU4NTksIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuNzc1MzksIDAuNzMyOTMsIDAuNzMxMzMsIDAuNzMxMzMsIDAuNzMxMzMsIDAuNzMxMzMsIDAuOTU5NTgsIDAuOTU5NTgsIDAuOTU5NTgsIDAuOTU5NTgsIDAuODg1MDYsIDAuOTEyMSwgMC44Njk0MywgMC44Njk0MywgMC44Njk0MywgMC44Njk0MywgMC44Njk0MywgMC44NTI4NCwgMC44NzUwOCwgMC45MDM5OSwgMC45MDM5OSwgMC45MDM5OSwgMC45MDM5OSwgMC43Nzg5MiwgMC43OTc5NSwgMC45MDgwNywgMC44ODc2MiwgMC44ODc2MiwgMC44ODc2MiwgMC44ODc2MiwgMC44ODc2MiwgMC44ODc2MiwgMC44NzE1LCAwLjc1MjQxLCAwLjkwNTE4LCAwLjkwNTE4LCAwLjkwNTE4LCAwLjkwNTE4LCAwLjg4NDAxLCAwLjg4NDAxLCAwLjg4NDAxLCAwLjg4NDAxLCAwLjg3ODUsIDAuODc4NSwgMC44ODAxLCAwLjg4MDEsIDAuODgwMSwgMC44ODAxLCAwLjg4MDEsIDAuOTA3NDcsIDAuODkwNDksIDAuODc4NSwgMC44Nzg1LCAwLjg3ODUsIDAuODc4NSwgMC44NTE2MiwgMC44Nzg1LCAwLjg1MTYyLCAwLjgzOTA4LCAwLjg4NzYyLCAwLjgzOTA4LCAwLjg4NzYyLCAwLjgzOTA4LCAwLjg4NzYyLCAwLjczMjkzLCAwLjc1MjQxLCAwLjczMjkzLCAwLjc1MjQxLCAwLjczMjkzLCAwLjc1MjQxLCAwLjczMjkzLCAwLjc1MjQxLCAwLjg3Mjg5LCAwLjgzMDE2LCAwLjg4NTA2LCAwLjkzMTI1LCAwLjczMTMzLCAwLjkwNTE4LCAwLjczMTMzLCAwLjkwNTE4LCAwLjczMTMzLCAwLjkwNTE4LCAwLjczMTMzLCAwLjkwNTE4LCAwLjczMTMzLCAwLjkwNTE4LCAwLjgxOTIxLCAwLjc3NjE4LCAwLjgxOTIxLCAwLjc3NjE4LCAwLjgxOTIxLCAwLjc3NjE4LCAxLCAxLCAwLjg3MzU2LCAwLjg3ODUsIDAuOTEwNzUsIDAuODk2MDgsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuNzYyMjksIDAuOTAxNjcsIDAuNTk1MjYsIDAuOTE5MTYsIDEsIDEsIDAuODYzMDQsIDAuNjkyMjUsIDAuODg0MDEsIDEsIDEsIDAuNzA0MjQsIDAuNzk0NjgsIDAuOTE5MjYsIDAuODgxNzUsIDAuNzA4MjMsIDAuOTQ5MDMsIDAuOTEyMSwgMC44Nzg1LCAxLCAxLCAwLjkxMjEsIDAuODc4NSwgMC44NzgwMiwgMC44ODY1NiwgMC44Nzg1LCAwLjg2OTQzLCAwLjg4MDEsIDAuODY5NDMsIDAuODgwMSwgMC44Njk0MywgMC44ODAxLCAwLjg3NDAyLCAwLjg5MjkxLCAwLjc3OTU4LCAwLjkxMzQzLCAxLCAxLCAwLjc3OTU4LCAwLjkxMzQzLCAwLjcwODY0LCAwLjcxNzMsIDAuNzA4NjQsIDAuNzE3MywgMC43MDg2NCwgMC43MTczLCAwLjcwODY0LCAwLjcxNzMsIDEsIDEsIDAuODEwNTUsIDAuNzU4NDEsIDAuODEwNTUsIDEuMDY0NTIsIDAuOTAzOTksIDAuODc4NSwgMC45MDM5OSwgMC44Nzg1LCAwLjkwMzk5LCAwLjg3ODUsIDAuOTAzOTksIDAuODc4NSwgMC45MDM5OSwgMC44Nzg1LCAwLjkwMzk5LCAwLjg3ODUsIDAuOTYwMTcsIDAuOTU3OTQsIDAuNzc4OTIsIDAuODUxNjIsIDAuNzc4OTIsIDAuNzgyNTcsIDAuNzk0OTIsIDAuNzgyNTcsIDAuNzk0OTIsIDAuNzgyNTcsIDAuNzk0OTIsIDAuOTI5NywgMC41Njg5MiwgMC44MzkwOCwgMC44ODc2MiwgMC43NzUzOSwgMC44NzE1LCAwLjg3NTA4LCAwLjg5MDQ5LCAxLCAxLCAwLjgxMDU1LCAxLjA0MTA2LCAxLjIwNTI4LCAxLjIwNTI4LCAxLCAxLjE1NTQzLCAwLjcwNjc0LCAwLjk4Mzg3LCAwLjk0NzIxLCAxLjMzNDMxLCAxLjQ1ODk0LCAwLjk1MTYxLCAxLjA2MzAzLCAwLjgzOTA4LCAwLjgwMzUyLCAwLjU3MTg0LCAwLjY5NjUsIDAuNTYyODksIDAuODIwMDEsIDAuNTYwMjksIDAuODEyMzUsIDEuMDI5ODgsIDAuODM5MDgsIDAuNzc2MiwgMC42ODE1NiwgMC44MDM2NywgMC43MzEzMywgMC43ODI1NywgMC44NzM1NiwgMC44Njk0MywgMC45NTk1OCwgMC43NTcyNywgMC44OTAxOSwgMS4wNDkyNCwgMC45MTIxLCAwLjc2NDgsIDAuODY5NDMsIDAuODczNTYsIDAuNzk3OTUsIDAuNzgyNzUsIDAuODEwNTUsIDAuNzc4OTIsIDAuOTc2MiwgMC44MjU3NywgMC45OTgxOSwgMC44NDg5NiwgMC45NTk1OCwgMC43Nzg5MiwgMC45NjEwOCwgMS4wMTQwNywgMC44OTA0OSwgMS4wMjk4OCwgMC45NDIxMSwgMC45NjEwOCwgMC44OTM2LCAwLjg0MDIxLCAwLjg3ODQyLCAwLjk2Mzk5LCAwLjc5MTA5LCAwLjg5MDQ5LCAxLjAwODEzLCAxLjAyOTg4LCAwLjg2MDc3LCAwLjg3NDQ1LCAwLjkyMDk5LCAwLjg0NzIzLCAwLjg2NTEzLCAwLjg4MDEsIDAuNzU2MzgsIDAuODU3MTQsIDAuNzgyMTYsIDAuNzk1ODYsIDAuODc5NjUsIDAuOTQyMTEsIDAuOTc3NDcsIDAuNzgyODcsIDAuOTc5MjYsIDAuODQ5NzEsIDEuMDI5ODgsIDAuOTQyMTEsIDAuODgwMSwgMC45NDIxMSwgMC44NDk3MSwgMC43MzEzMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MDI2NCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MDUxOCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MDU0OCwgMSwgMSwgMSwgMSwgMSwgMSwgMC45NjAxNywgMC45NTc5NCwgMC45NjAxNywgMC45NTc5NCwgMC45NjAxNywgMC45NTc5NCwgMC43Nzg5MiwgMC44NTE2MiwgMSwgMSwgMC44OTU1MiwgMC45MDUyNywgMSwgMC45MDM2MywgMC45Mjc5NCwgMC45Mjc5NCwgMC45Mjc5NCwgMC45Mjc5NCwgMC44NzAxMiwgMC44NzAxMiwgMC44NzAxMiwgMC44OTU1MiwgMC44OTU1MiwgMS40MjI1OSwgMC43MTE0MywgMS4wNjE1MiwgMSwgMSwgMS4wMzM3MiwgMS4wMzM3MiwgMC45NzE3MSwgMS40OTU2LCAyLjI4MDcsIDAuOTM4MzUsIDAuODM0MDYsIDAuOTExMzMsIDAuODQxMDcsIDAuOTExMzMsIDEsIDEsIDEsIDAuNzIwMjEsIDEsIDEuMjMxMDgsIDAuODM0ODksIDAuODg1MjUsIDAuODg1MjUsIDAuODE0OTksIDAuOTA1MjcsIDEuODEwNTUsIDAuOTA1MjcsIDEuODEwNTUsIDEuMzEwMDYsIDEuNTM3MTEsIDAuOTQ0MzQsIDEuMDg2OTYsIDEsIDAuOTUwMTgsIDAuNzcxOTIsIDAuODUyODQsIDAuOTA3NDcsIDEuMTc1MzQsIDAuNjk4MjUsIDAuOTcxNiwgMS4zNzA3NywgMC45MDc0NywgMC45MDc0NywgMC44NTM1NiwgMC45MDc0NywgMC45MDc0NywgMS40NDk0NywgMC44NTI4NCwgMC44OTQxLCAwLjg5NDEsIDAuNzA1NzIsIDAuOCwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45OTg2MiwgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMS4wODAwNCwgMC45MTAyNywgMSwgMSwgMSwgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MDcyNywgMC45MDcyNywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmNvbnN0IENhbGlicmlCb2xkTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjIyMDcsCiAgbGluZUdhcDogMC4yMjA3Cn07CmNvbnN0IENhbGlicmlCb2xkSXRhbGljRmFjdG9ycyA9IFsxLjM4NzcsIDEsIDEsIDEsIDAuOTc4MDEsIDAuOTI0ODIsIDAuODk1NTIsIDAuOTExMzMsIDAuODE5ODgsIDAuOTc1NjYsIDAuOTgxNTIsIDAuOTM1NDgsIDAuOTM1NDgsIDEuMjc5OCwgMC44NTI4NCwgMC45Mjc5NCwgMSwgMC45NjEzNCwgMS41NjIzOSwgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC44Mjg0NSwgMC44Mjg0NSwgMC44NTI4NCwgMC44NTI4NCwgMC44NTI4NCwgMC43NTg1OSwgMC45MjEzOCwgMC44MzkwOCwgMC43NzYyLCAwLjcxODA1LCAwLjg3Mjg5LCAwLjczMTMzLCAwLjc1MTQsIDAuODE5MjEsIDAuODczNTYsIDAuOTU5NTgsIDAuNTk1MjYsIDAuNzU3MjcsIDAuNjkyMjUsIDEuMDQ5MjQsIDAuOTA4NzIsIDAuODU5MzgsIDAuNzk3OTUsIDAuODcwNjgsIDAuNzc5NTgsIDAuNjk3NjYsIDAuODEwNTUsIDAuOTAzOTksIDAuODg2NTMsIDAuOTYwNjgsIDAuODI1NzcsIDAuNzc4OTIsIDAuNzgyNTcsIDAuOTc1MDcsIDEuNTI5LCAwLjk3NTA3LCAwLjg1Mjg0LCAwLjg5NTUyLCAwLjkwMTc2LCAwLjk0OTA4LCAwLjg2NDExLCAwLjc0MDEyLCAwLjg2NDExLCAwLjg4MzIzLCAwLjk1MDE1LCAwLjg2NDExLCAwLjg2MzMxLCAwLjg4NDAxLCAwLjkxOTE2LCAwLjg2MzA0LCAwLjg4NDAxLCAwLjkwMzksIDAuODYzMzEsIDAuODYzMzEsIDAuODY0MTEsIDAuODY0MTEsIDAuOTA0NjQsIDAuNzA4NTIsIDEuMDQxMDYsIDAuODYzMzEsIDAuODQzNzIsIDAuOTU3OTQsIDAuODI2MTYsIDAuODQ1NDgsIDAuNzk0OTIsIDAuODgzMzEsIDEuNjk4MDgsIDAuODgzMzEsIDAuODUyODQsIDAuOTc4MDEsIDAuODk1NTIsIDAuOTExMzMsIDAuODk1NTIsIDAuOTExMzMsIDEuNzgwMSwgMC44OTU1MiwgMS4yNDQ4NywgMS4xMzI1NCwgMS4xOTEyOSwgMC45NjgzOSwgMC44NTI4NCwgMC42ODc4NywgMC43MDY0NSwgMC44NTU5MiwgMC45MDc0NywgMS4wMTQ2NiwgMS4wMDg4LCAwLjkwMzIzLCAxLCAxLjA3NDYzLCAxLCAwLjkxMDU2LCAwLjc1ODA2LCAxLjE5MTE4LCAwLjk2ODM5LCAwLjc4ODY0LCAwLjgyODQ1LCAwLjg0MTMzLCAwLjc1ODU5LCAwLjgzOTA4LCAwLjgzOTA4LCAwLjgzOTA4LCAwLjgzOTA4LCAwLjgzOTA4LCAwLjgzOTA4LCAwLjc3NTM5LCAwLjcxODA1LCAwLjczMTMzLCAwLjczMTMzLCAwLjczMTMzLCAwLjczMTMzLCAwLjk1OTU4LCAwLjk1OTU4LCAwLjk1OTU4LCAwLjk1OTU4LCAwLjg4NTA2LCAwLjkwODcyLCAwLjg1OTM4LCAwLjg1OTM4LCAwLjg1OTM4LCAwLjg1OTM4LCAwLjg1OTM4LCAwLjg1Mjg0LCAwLjg3MDY4LCAwLjkwMzk5LCAwLjkwMzk5LCAwLjkwMzk5LCAwLjkwMzk5LCAwLjc3ODkyLCAwLjc5Nzk1LCAwLjkwODA3LCAwLjk0OTA4LCAwLjk0OTA4LCAwLjk0OTA4LCAwLjk0OTA4LCAwLjk0OTA4LCAwLjk0OTA4LCAwLjg1ODg3LCAwLjc0MDEyLCAwLjg4MzIzLCAwLjg4MzIzLCAwLjg4MzIzLCAwLjg4MzIzLCAwLjg4NDAxLCAwLjg4NDAxLCAwLjg4NDAxLCAwLjg4NDAxLCAwLjg3ODUsIDAuODYzMzEsIDAuODYzMzEsIDAuODYzMzEsIDAuODYzMzEsIDAuODYzMzEsIDAuODYzMzEsIDAuOTA3NDcsIDAuODkwNDksIDAuODYzMzEsIDAuODYzMzEsIDAuODYzMzEsIDAuODYzMzEsIDAuODQ1NDgsIDAuODY0MTEsIDAuODQ1NDgsIDAuODM5MDgsIDAuOTQ5MDgsIDAuODM5MDgsIDAuOTQ5MDgsIDAuODM5MDgsIDAuOTQ5MDgsIDAuNzE4MDUsIDAuNzQwMTIsIDAuNzE4MDUsIDAuNzQwMTIsIDAuNzE4MDUsIDAuNzQwMTIsIDAuNzE4MDUsIDAuNzQwMTIsIDAuODcyODksIDAuNzk1MzgsIDAuODg1MDYsIDAuOTI3MjYsIDAuNzMxMzMsIDAuODgzMjMsIDAuNzMxMzMsIDAuODgzMjMsIDAuNzMxMzMsIDAuODgzMjMsIDAuNzMxMzMsIDAuODgzMjMsIDAuNzMxMzMsIDAuODgzMjMsIDAuODE5MjEsIDAuODY0MTEsIDAuODE5MjEsIDAuODY0MTEsIDAuODE5MjEsIDAuODY0MTEsIDEsIDEsIDAuODczNTYsIDAuODYzMzEsIDAuOTEwNzUsIDAuODc3NywgMC45NTk1OCwgMC44ODQwMSwgMC45NTk1OCwgMC44ODQwMSwgMC45NTk1OCwgMC44ODQwMSwgMC45NTk1OCwgMC44ODQwMSwgMC45NTk1OCwgMC44ODQwMSwgMC43NjQ2NywgMC45MDE2NywgMC41OTUyNiwgMC45MTkxNiwgMSwgMSwgMC44NjMwNCwgMC42OTIyNSwgMC44ODQwMSwgMSwgMSwgMC43MDQyNCwgMC43NzMxMiwgMC45MTkyNiwgMC44ODE3NSwgMC43MDgyMywgMC45NDkwMywgMC45MDg3MiwgMC44NjMzMSwgMSwgMSwgMC45MDg3MiwgMC44NjMzMSwgMC44NjkwNiwgMC44ODExNiwgMC44NjMzMSwgMC44NTkzOCwgMC44NjMzMSwgMC44NTkzOCwgMC44NjMzMSwgMC44NTkzOCwgMC44NjMzMSwgMC44NzQwMiwgMC44NjU0OSwgMC43Nzk1OCwgMC45MDQ2NCwgMSwgMSwgMC43Nzk1OCwgMC45MDQ2NCwgMC42OTc2NiwgMC43MDg1MiwgMC42OTc2NiwgMC43MDg1MiwgMC42OTc2NiwgMC43MDg1MiwgMC42OTc2NiwgMC43MDg1MiwgMSwgMSwgMC44MTA1NSwgMC43NTg0MSwgMC44MTA1NSwgMS4wNjQ1MiwgMC45MDM5OSwgMC44NjMzMSwgMC45MDM5OSwgMC44NjMzMSwgMC45MDM5OSwgMC44NjMzMSwgMC45MDM5OSwgMC44NjMzMSwgMC45MDM5OSwgMC44NjMzMSwgMC45MDM5OSwgMC44NjMzMSwgMC45NjA2OCwgMC45NTc5NCwgMC43Nzg5MiwgMC44NDU0OCwgMC43Nzg5MiwgMC43ODI1NywgMC43OTQ5MiwgMC43ODI1NywgMC43OTQ5MiwgMC43ODI1NywgMC43OTQ5MiwgMC45Mjk3LCAwLjU2ODkyLCAwLjgzOTA4LCAwLjk0OTA4LCAwLjc3NTM5LCAwLjg1ODg3LCAwLjg3MDY4LCAwLjg5MDQ5LCAxLCAxLCAwLjgxMDU1LCAxLjA0MTA2LCAxLjIwNTI4LCAxLjIwNTI4LCAxLCAxLjE1NTQzLCAwLjcwMDg4LCAwLjk4Mzg3LCAwLjk0NzIxLCAxLjMzNDMxLCAxLjQ1ODk0LCAwLjk1MTYxLCAxLjQ4Mzg3LCAwLjgzOTA4LCAwLjgwMzUyLCAwLjU3MTE4LCAwLjY5NjUsIDAuNTYzNDcsIDAuNzkxNzksIDAuNTU4NTMsIDAuODAzNDYsIDEuMDI5ODgsIDAuODM5MDgsIDAuNzc2MiwgMC42NzE3NCwgMC44NjAzNiwgMC43MzEzMywgMC43ODI1NywgMC44NzM1NiwgMC44NjQ0MSwgMC45NTk1OCwgMC43NTcyNywgMC44OTAxOSwgMS4wNDkyNCwgMC45MDg3MiwgMC43NDg4OSwgMC44NTkzOCwgMC44Nzg5MSwgMC43OTc5NSwgMC43OTU3LCAwLjgxMDU1LCAwLjc3ODkyLCAwLjk3NDQ3LCAwLjgyNTc3LCAwLjk3NDY2LCAwLjg3MTc5LCAwLjk1OTU4LCAwLjc3ODkyLCAwLjk0MjUyLCAwLjk1NjEyLCAwLjg3NTMsIDEuMDI5ODgsIDAuOTI3MzMsIDAuOTQyNTIsIDAuODc0MTEsIDAuODQwMjEsIDAuODcyOCwgMC45NTYxMiwgMC43NDA4MSwgMC44NzUzLCAxLjAyMTg5LCAxLjAyOTg4LCAwLjg0ODE0LCAwLjg3NDQ1LCAwLjkxODIyLCAwLjg0NzIzLCAwLjg1NjY4LCAwLjg2MzMxLCAwLjgxMzQ0LCAwLjg3NTgxLCAwLjc2NDIyLCAwLjgyMDQ2LCAwLjk2MDU3LCAwLjkyNzMzLCAwLjk5Mzc1LCAwLjc4MDIyLCAwLjk1NDUyLCAwLjg2MDE1LCAxLjAyOTg4LCAwLjkyNzMzLCAwLjg2MzMxLCAwLjkyNzMzLCAwLjg2MDE1LCAwLjczMTMzLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjkwNjMxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjg4MzIzLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjg1MTc0LCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk2MDY4LCAwLjk1Nzk0LCAwLjk2MDY4LCAwLjk1Nzk0LCAwLjk2MDY4LCAwLjk1Nzk0LCAwLjc3ODkyLCAwLjg0NTQ4LCAxLCAxLCAwLjg5NTUyLCAwLjkwNTI3LCAxLCAwLjkwMzYzLCAwLjkyNzk0LCAwLjkyNzk0LCAwLjkyNzk0LCAwLjg5ODA3LCAwLjg3MDEyLCAwLjg3MDEyLCAwLjg3MDEyLCAwLjg5NTUyLCAwLjg5NTUyLCAxLjQyMjU5LCAwLjcxMDk0LCAxLjA2MTUyLCAxLCAxLCAxLjAzMzcyLCAxLjAzMzcyLCAwLjk3MTcxLCAxLjQ5NTYsIDIuMjgwNywgMC45Mjk3MiwgMC44MzQwNiwgMC45MTEzMywgMC44MzMyNiwgMC45MTEzMywgMSwgMSwgMSwgMC43MjAyMSwgMSwgMS4yMzEwOCwgMC44MzQ4OSwgMC44ODUyNSwgMC44ODUyNSwgMC44MTQ5OSwgMC45MDYxNiwgMS44MTA1NSwgMC45MDUyNywgMS44MTA1NSwgMS4zMTA3LCAxLjUzNzExLCAwLjk0NDM0LCAxLjA4Njk2LCAxLCAwLjk1MDE4LCAwLjc3MTkyLCAwLjg1Mjg0LCAwLjkwNzQ3LCAxLjE3NTM0LCAwLjY5ODI1LCAwLjk3MTYsIDEuMzcwNzcsIDAuOTA3NDcsIDAuOTA3NDcsIDAuODUzNTYsIDAuOTA3NDcsIDAuOTA3NDcsIDEuNDQ5NDcsIDAuODUyODQsIDAuODk0MSwgMC44OTQxLCAwLjcwNTcyLCAwLjgsIDAuNzA1NzIsIDAuNzA1NzIsIDAuNzA1NzIsIDAuNzA1NzIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTk4NjIsIDAuOTk4NjIsIDEsIDEsIDEsIDEsIDEsIDEuMDgwMDQsIDAuOTEwMjcsIDEsIDEsIDEsIDAuOTk4NjIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTA3MjcsIDAuOTA3MjcsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBDYWxpYnJpQm9sZEl0YWxpY01ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yMjA3LAogIGxpbmVHYXA6IDAuMjIwNwp9Owpjb25zdCBDYWxpYnJpSXRhbGljRmFjdG9ycyA9IFsxLjM4NzcsIDEsIDEsIDEsIDEuMTcyMjMsIDEuMTI5MywgMC44OTU1MiwgMC45MTEzMywgMC44MDM5NSwgMS4wMjI2OSwgMS4xNTYwMSwgMC45MTA1NiwgMC45MTA1NiwgMS4yNzk4LCAwLjg1Mjg0LCAwLjg5ODA3LCAxLCAwLjkwODYxLCAxLjM5NTQzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjk2MzA5LCAwLjk2MzA5LCAwLjg1Mjg0LCAwLjg1Mjg0LCAwLjg1Mjg0LCAwLjgzMzE5LCAwLjg4MDcxLCAwLjg2NzUsIDAuODE1NTIsIDAuNzIzNDYsIDAuODUxOTMsIDAuNzMyMDYsIDAuNzUyMiwgMC44MTEwNSwgMC44NjI3NSwgMC45MDY4NSwgMC42Mzc3LCAwLjc3ODkyLCAwLjc1NTkzLCAxLjAyNjM4LCAwLjg5MjQ5LCAwLjg0MTE4LCAwLjc3NDUyLCAwLjg1Mzc0LCAwLjc1MTg2LCAwLjY3Nzg5LCAwLjc5Nzc2LCAwLjg4ODQ0LCAwLjg1MDY2LCAwLjk0MzA5LCAwLjc3ODE4LCAwLjczMDYsIDAuNzY2NTksIDEuMTAzNjksIDEuMzgzMTMsIDEuMTAzNjksIDEuMDYxMzksIDAuODk1NTIsIDAuODczOSwgMC45MjQ1LCAwLjkyNDUsIDAuODMyMDMsIDAuOTI0NSwgMC44NTg2NSwgMS4wOTg0MiwgMC45MjQ1LCAwLjkyNDUsIDEuMDMyOTcsIDEuMDc2OTIsIDAuOTA5MTgsIDEuMDMyOTcsIDAuOTQ5NTksIDAuOTI0NSwgMC45MjI3NCwgMC45MjQ1LCAwLjkyNDUsIDEuMDI5MzMsIDAuNzc4MzIsIDEuMjA1NjIsIDAuOTI0NSwgMC44OTE2LCAwLjk4OTg2LCAwLjg2NjIxLCAwLjg5NDUzLCAwLjc5MDA0LCAwLjk0MTUyLCAxLjc3MjU2LCAwLjk0MTUyLCAwLjg1Mjg0LCAwLjk3ODAxLCAwLjg5NTUyLCAwLjkxMTMzLCAwLjg5NTUyLCAwLjkxMTMzLCAxLjkxNzI5LCAwLjg5NTUyLCAxLjE3ODg5LCAxLjEzMjU0LCAxLjE2MzU5LCAwLjkyMDk4LCAwLjg1Mjg0LCAwLjY4Nzg3LCAwLjcxMzUzLCAwLjg0NzM3LCAwLjkwNzQ3LCAxLjAwODgsIDEuMDA0NCwgMC44NzY4MywgMSwgMS4wOTA5MSwgMSwgMC45MjIyOSwgMC43MzksIDEuMTU2NDIsIDAuOTIwOTgsIDAuNzYyODgsIDAuODA1MDQsIDAuODA5NzIsIDAuNzU4NTksIDAuODY3NSwgMC44Njc1LCAwLjg2NzUsIDAuODY3NSwgMC44Njc1LCAwLjg2NzUsIDAuNzYzMTgsIDAuNzIzNDYsIDAuNzMyMDYsIDAuNzMyMDYsIDAuNzMyMDYsIDAuNzMyMDYsIDAuOTA2ODUsIDAuOTA2ODUsIDAuOTA2ODUsIDAuOTA2ODUsIDAuODY0NzcsIDAuODkyNDksIDAuODQxMTgsIDAuODQxMTgsIDAuODQxMTgsIDAuODQxMTgsIDAuODQxMTgsIDAuODUyODQsIDAuODQ1NTcsIDAuODg4NDQsIDAuODg4NDQsIDAuODg4NDQsIDAuODg4NDQsIDAuNzMwNiwgMC43NzQ1MiwgMC44NjMzMSwgMC45MjQ1LCAwLjkyNDUsIDAuOTI0NSwgMC45MjQ1LCAwLjkyNDUsIDAuOTI0NSwgMC44NDg0MywgMC44MzIwMywgMC44NTg2NSwgMC44NTg2NSwgMC44NTg2NSwgMC44NTg2NSwgMC44MjYwMSwgMC44MjYwMSwgMC44MjYwMSwgMC44MjYwMSwgMC45NDQ2OSwgMC45MjQ1LCAwLjkyMjc0LCAwLjkyMjc0LCAwLjkyMjc0LCAwLjkyMjc0LCAwLjkyMjc0LCAwLjkwNzQ3LCAwLjg2NjUxLCAwLjkyNDUsIDAuOTI0NSwgMC45MjQ1LCAwLjkyNDUsIDAuODk0NTMsIDAuOTI0NSwgMC44OTQ1MywgMC44Njc1LCAwLjkyNDUsIDAuODY3NSwgMC45MjQ1LCAwLjg2NzUsIDAuOTI0NSwgMC43MjM0NiwgMC44MzIwMywgMC43MjM0NiwgMC44MzIwMywgMC43MjM0NiwgMC44MzIwMywgMC43MjM0NiwgMC44MzIwMywgMC44NTE5MywgMC44ODc1LCAwLjg2NDc3LCAwLjk5MDM0LCAwLjczMjA2LCAwLjg1ODY1LCAwLjczMjA2LCAwLjg1ODY1LCAwLjczMjA2LCAwLjg1ODY1LCAwLjczMjA2LCAwLjg1ODY1LCAwLjczMjA2LCAwLjg1ODY1LCAwLjgxMTA1LCAwLjkyNDUsIDAuODExMDUsIDAuOTI0NSwgMC44MTEwNSwgMC45MjQ1LCAxLCAxLCAwLjg2Mjc1LCAwLjkyNDUsIDAuOTA4NzIsIDAuOTM1OTEsIDAuOTA2ODUsIDAuODI2MDEsIDAuOTA2ODUsIDAuODI2MDEsIDAuOTA2ODUsIDAuODI2MDEsIDAuOTA2ODUsIDEuMDMyOTcsIDAuOTA2ODUsIDAuODI2MDEsIDAuNzc4OTYsIDEuMDU2MTEsIDAuNjM3NywgMS4wNzY5MiwgMSwgMSwgMC45MDkxOCwgMC43NTU5MywgMS4wMzI5NywgMSwgMSwgMC43NjAzMiwgMC45Mzc1LCAwLjk4MTU2LCAwLjkzNDA3LCAwLjc3MjYxLCAxLjExNDI5LCAwLjg5MjQ5LCAwLjkyNDUsIDEsIDEsIDAuODkyNDksIDAuOTI0NSwgMC45MjUzNCwgMC44NjY5OCwgMC45MjQ1LCAwLjg0MTE4LCAwLjkyMjc0LCAwLjg0MTE4LCAwLjkyMjc0LCAwLjg0MTE4LCAwLjkyMjc0LCAwLjg2NjcsIDAuODYyOTEsIDAuNzUxODYsIDEuMDI5MzMsIDEsIDEsIDAuNzUxODYsIDEuMDI5MzMsIDAuNjc3ODksIDAuNzc4MzIsIDAuNjc3ODksIDAuNzc4MzIsIDAuNjc3ODksIDAuNzc4MzIsIDAuNjc3ODksIDAuNzc4MzIsIDEsIDEsIDAuNzk3NzYsIDAuOTc2NTUsIDAuNzk3NzYsIDEuMjMwMjMsIDAuODg4NDQsIDAuOTI0NSwgMC44ODg0NCwgMC45MjQ1LCAwLjg4ODQ0LCAwLjkyNDUsIDAuODg4NDQsIDAuOTI0NSwgMC44ODg0NCwgMC45MjQ1LCAwLjg4ODQ0LCAwLjkyNDUsIDAuOTQzMDksIDAuOTg5ODYsIDAuNzMwNiwgMC44OTQ1MywgMC43MzA2LCAwLjc2NjU5LCAwLjc5MDA0LCAwLjc2NjU5LCAwLjc5MDA0LCAwLjc2NjU5LCAwLjc5MDA0LCAxLjA5MjMxLCAwLjU0ODczLCAwLjg2NzUsIDAuOTI0NSwgMC43NjMxOCwgMC44NDg0MywgMC44NDU1NywgMC44NjY1MSwgMSwgMSwgMC43OTc3NiwgMS4yMDU2MiwgMS4xODYyMiwgMS4xODYyMiwgMSwgMS4xNDM3LCAwLjY3MDA5LCAwLjk2MzM0LCAwLjkzNjk1LCAxLjM1MTkxLCAxLjQwOTA5LCAwLjk1MTYxLCAxLjQ4Mzg3LCAwLjg2NzUsIDAuOTA4NjEsIDAuNjE5MiwgMC43MzYzLCAwLjY0ODI0LCAwLjgyNDExLCAwLjU2MzIxLCAwLjg1Njk2LCAxLjIzNTE2LCAwLjg2NzUsIDAuODE1NTIsIDAuNzI4NiwgMC44NDEzNCwgMC43MzIwNiwgMC43NjY1OSwgMC44NjI3NSwgMC44NDM2OSwgMC45MDY4NSwgMC43Nzg5MiwgMC44NTg3MSwgMS4wMjYzOCwgMC44OTI0OSwgMC43NTgyOCwgMC44NDExOCwgMC44NTk4NCwgMC43NzQ1MiwgMC43NjQ2NiwgMC43OTc3NiwgMC43MzA2LCAwLjkwNzgyLCAwLjc3ODE4LCAwLjkwMywgMC44NzI5MSwgMC45MDY4NSwgMC43MzA2LCAwLjk5MDU4LCAxLjAzNjY3LCAwLjk0NjM1LCAxLjIzNTE2LCAwLjk4NDksIDAuOTkwNTgsIDAuOTIzOTMsIDAuODkxNiwgMC45NDIsIDEuMDM2NjcsIDAuNzUwMjYsIDAuOTQ2MzUsIDEuMDI5NywgMS4yMzUxNiwgMC45MDkxOCwgMC45NDA0OCwgMC45ODIxNywgMC44OTc0NiwgMC44NDE1MywgMC45MjI3NCwgMC44MjUwNywgMC44ODgzMiwgMC44NDQzOCwgMC44ODE3OCwgMS4wMzUyNSwgMC45ODQ5LCAxLjAwMjI1LCAwLjc4MDg2LCAwLjk3MjQ4LCAwLjg5NDA0LCAxLjIzNTE2LCAwLjk4NDksIDAuOTIyNzQsIDAuOTg0OSwgMC44OTQwNCwgMC43MzIwNiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC44OTY5MywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC44NTg2NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MDkzMywgMSwgMSwgMSwgMSwgMSwgMSwgMC45NDMwOSwgMC45ODk4NiwgMC45NDMwOSwgMC45ODk4NiwgMC45NDMwOSwgMC45ODk4NiwgMC43MzA2LCAwLjg5NDUzLCAxLCAxLCAwLjg5NTUyLCAwLjkwNTI3LCAxLCAwLjkwMTg2LCAxLjEyMzA4LCAxLjEyMzA4LCAxLjEyMzA4LCAxLjEyMzA4LCAxLjI1NjYsIDEuMjU2NiwgMS4yNTY2LCAwLjg5NTUyLCAwLjg5NTUyLCAxLjQyMjU5LCAwLjY4OTk0LCAxLjAzODA5LCAxLCAxLCAxLjAxNzYsIDEuMDE3NiwgMS4xMTUyMywgMS40OTU2LCAyLjAxNDYyLCAwLjk3ODU4LCAwLjgyNjE2LCAwLjkxMTMzLCAwLjgzNDM3LCAwLjkxMTMzLCAxLCAxLCAxLCAwLjcwNTA4LCAxLCAxLjIzMTA4LCAwLjc5ODAxLCAwLjg0NDI2LCAwLjg0NDI2LCAwLjc3NCwgMC45MDU3MiwgMS44MTA1NSwgMC45MDc0OSwgMS44MTA1NSwgMS4yODgwOSwgMS41NTQ2OSwgMC45NDQzNCwgMS4wNzgwNiwgMSwgMC45NzA5NCwgMC43NTg5LCAwLjg1Mjg0LCAwLjkwNzQ3LCAxLjE5NjU4LCAwLjY5ODI1LCAwLjk3NjIyLCAxLjMzNTEyLCAwLjkwNzQ3LCAwLjkwNzQ3LCAwLjg1Mjg0LCAwLjkwNzQ3LCAwLjkwNzQ3LCAxLjQ0OTQ3LCAwLjg1Mjg0LCAwLjg5NDEsIDAuODk0MSwgMC43MDU3MiwgMC44LCAwLjcwNTcyLCAwLjcwNTcyLCAwLjcwNTcyLCAwLjcwNTcyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk5ODYyLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLjAzMzYsIDAuOTEwMjcsIDEsIDEsIDEsIDAuOTk4NjIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDU4NTksIDEuMDU4NTksIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBDYWxpYnJpSXRhbGljTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjIyMDcsCiAgbGluZUdhcDogMC4yMjA3Cn07CmNvbnN0IENhbGlicmlSZWd1bGFyRmFjdG9ycyA9IFsxLjM4NzcsIDEsIDEsIDEsIDEuMTcyMjMsIDEuMTI5MywgMC44OTU1MiwgMC45MTEzMywgMC44MDM5NSwgMS4wMjI2OSwgMS4xNTYwMSwgMC45MTA1NiwgMC45MTA1NiwgMS4yNzk4LCAwLjg1Mjg0LCAwLjg5ODA3LCAxLCAwLjkwODYxLCAxLjM5MDE2LCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjk2MzA5LCAwLjk2MzA5LCAwLjg1Mjg0LCAwLjg1Mjg0LCAwLjg1Mjg0LCAwLjgzMzE5LCAwLjg4MDcxLCAwLjg2NzUsIDAuODE1NTIsIDAuNzM4MzQsIDAuODUxOTMsIDAuNzMyMDYsIDAuNzUyMiwgMC44MTEwNSwgMC44NjI3NSwgMC45MDY4NSwgMC42Mzc3LCAwLjc3ODkyLCAwLjc1NTkzLCAxLjAyNjM4LCAwLjg5Mzg1LCAwLjg1MTIyLCAwLjc3NDUyLCAwLjg2NTAzLCAwLjc1MTg2LCAwLjY4ODg3LCAwLjc5Nzc2LCAwLjg4ODQ0LCAwLjg1MDY2LCAwLjk0MjU4LCAwLjc3ODE4LCAwLjczMDYsIDAuNzY2NTksIDEuMTAzNjksIDEuMzkwMTYsIDEuMTAzNjksIDEuMDYxMzksIDAuODk1NTIsIDAuODczOSwgMC44NjEyOCwgMC45NDQ2OSwgMC44NDU3LCAwLjk0NDY5LCAwLjg5NDY0LCAxLjA5ODQyLCAwLjg0NjM2LCAwLjk0NDY5LCAxLjAzMjk3LCAxLjA3NjkyLCAwLjkwOTE4LCAxLjAzMjk3LCAwLjk1ODk3LCAwLjk0NDY5LCAwLjk0ODIsIDAuOTQ0NjksIDAuOTQ0NjksIDEuMDQ2OTIsIDAuNzgyMjMsIDEuMjA1NjIsIDAuOTQ0NjksIDAuOTAzMzIsIDAuOTg5ODYsIDAuODY2MjEsIDAuOTA1MjcsIDAuNzkwMDQsIDAuOTQxNTIsIDEuNzcyNTYsIDAuOTQxNTIsIDAuODUyODQsIDAuOTc4MDEsIDAuODk1NTIsIDAuOTExMzMsIDAuODk1NTIsIDAuOTExMzMsIDEuOTE3MjksIDAuODk1NTIsIDEuMTc4ODksIDEuMTMyNTQsIDEuMDg3MDcsIDAuOTIwOTgsIDAuODUyODQsIDAuNjg3ODcsIDAuNzEzNTMsIDAuODQ3MzcsIDAuOTA3NDcsIDEuMDA4OCwgMS4wMDQ0LCAwLjg3NjgzLCAxLCAxLjA5MDkxLCAxLCAwLjkyMjI5LCAwLjczOSwgMS4xNTY0MiwgMC45MjA5OCwgMC43NjI4OCwgMC44MDUwNCwgMC44MDk3MiwgMC43NTg1OSwgMC44Njc1LCAwLjg2NzUsIDAuODY3NSwgMC44Njc1LCAwLjg2NzUsIDAuODY3NSwgMC43NjMxOCwgMC43MzgzNCwgMC43MzIwNiwgMC43MzIwNiwgMC43MzIwNiwgMC43MzIwNiwgMC45MDY4NSwgMC45MDY4NSwgMC45MDY4NSwgMC45MDY4NSwgMC44NjQ3NywgMC44OTM4NSwgMC44NTEyMiwgMC44NTEyMiwgMC44NTEyMiwgMC44NTEyMiwgMC44NTEyMiwgMC44NTI4NCwgMC44NTMxMSwgMC44ODg0NCwgMC44ODg0NCwgMC44ODg0NCwgMC44ODg0NCwgMC43MzA2LCAwLjc3NDUyLCAwLjg2MzMxLCAwLjg2MTI4LCAwLjg2MTI4LCAwLjg2MTI4LCAwLjg2MTI4LCAwLjg2MTI4LCAwLjg2MTI4LCAwLjg2OTMsIDAuODQ1NywgMC44OTQ2NCwgMC44OTQ2NCwgMC44OTQ2NCwgMC44OTQ2NCwgMC44MjYwMSwgMC44MjYwMSwgMC44MjYwMSwgMC44MjYwMSwgMC45NDQ2OSwgMC45NDQ2OSwgMC45NDgyLCAwLjk0ODIsIDAuOTQ4MiwgMC45NDgyLCAwLjk0ODIsIDAuOTA3NDcsIDAuODY2NTEsIDAuOTQ0NjksIDAuOTQ0NjksIDAuOTQ0NjksIDAuOTQ0NjksIDAuOTA1MjcsIDAuOTQ0NjksIDAuOTA1MjcsIDAuODY3NSwgMC44NjEyOCwgMC44Njc1LCAwLjg2MTI4LCAwLjg2NzUsIDAuODYxMjgsIDAuNzM4MzQsIDAuODQ1NywgMC43MzgzNCwgMC44NDU3LCAwLjczODM0LCAwLjg0NTcsIDAuNzM4MzQsIDAuODQ1NywgMC44NTE5MywgMC45MjQ1NCwgMC44NjQ3NywgMC45OTIxLCAwLjczMjA2LCAwLjg5NDY0LCAwLjczMjA2LCAwLjg5NDY0LCAwLjczMjA2LCAwLjg5NDY0LCAwLjczMjA2LCAwLjg5NDY0LCAwLjczMjA2LCAwLjg5NDY0LCAwLjgxMTA1LCAwLjg0NjM2LCAwLjgxMTA1LCAwLjg0NjM2LCAwLjgxMTA1LCAwLjg0NjM2LCAxLCAxLCAwLjg2Mjc1LCAwLjk0NDY5LCAwLjkwODcyLCAwLjk1Nzg2LCAwLjkwNjg1LCAwLjgyNjAxLCAwLjkwNjg1LCAwLjgyNjAxLCAwLjkwNjg1LCAwLjgyNjAxLCAwLjkwNjg1LCAxLjAzMjk3LCAwLjkwNjg1LCAwLjgyNjAxLCAwLjc3NzQxLCAxLjA1NjExLCAwLjYzNzcsIDEuMDc2OTIsIDEsIDEsIDAuOTA5MTgsIDAuNzU1OTMsIDEuMDMyOTcsIDEsIDEsIDAuNzYwMzIsIDAuOTA0NTIsIDAuOTgxNTYsIDEuMTE4NDIsIDAuNzcyNjEsIDEuMTE0MjksIDAuODkzODUsIDAuOTQ0NjksIDEsIDEsIDAuODkzODUsIDAuOTQ0NjksIDAuOTU4NzcsIDAuODY5MDEsIDAuOTQ0NjksIDAuODUxMjIsIDAuOTQ4MiwgMC44NTEyMiwgMC45NDgyLCAwLjg1MTIyLCAwLjk0ODIsIDAuODY2NywgMC45MDAxNiwgMC43NTE4NiwgMS4wNDY5MiwgMSwgMSwgMC43NTE4NiwgMS4wNDY5MiwgMC42ODg4NywgMC43ODIyMywgMC42ODg4NywgMC43ODIyMywgMC42ODg4NywgMC43ODIyMywgMC42ODg4NywgMC43ODIyMywgMSwgMSwgMC43OTc3NiwgMC45MjE4OCwgMC43OTc3NiwgMS4yMzAyMywgMC44ODg0NCwgMC45NDQ2OSwgMC44ODg0NCwgMC45NDQ2OSwgMC44ODg0NCwgMC45NDQ2OSwgMC44ODg0NCwgMC45NDQ2OSwgMC44ODg0NCwgMC45NDQ2OSwgMC44ODg0NCwgMC45NDQ2OSwgMC45NDI1OCwgMC45ODk4NiwgMC43MzA2LCAwLjkwNTI3LCAwLjczMDYsIDAuNzY2NTksIDAuNzkwMDQsIDAuNzY2NTksIDAuNzkwMDQsIDAuNzY2NTksIDAuNzkwMDQsIDEuMDkyMzEsIDAuNTQ4NzMsIDAuODY3NSwgMC44NjEyOCwgMC43NjMxOCwgMC44NjkzLCAwLjg1MzExLCAwLjg2NjUxLCAxLCAxLCAwLjc5Nzc2LCAxLjIwNTYyLCAxLjE4NjIyLCAxLjE4NjIyLCAxLCAxLjE0MzcsIDAuNjc3NDIsIDAuOTYzMzQsIDAuOTM2OTUsIDEuMzUxOTEsIDEuNDA5MDksIDAuOTUxNjEsIDEuNDgzODcsIDAuODY2ODYsIDAuOTA4NjEsIDAuNjIyNjcsIDAuNzQzNTksIDAuNjU2NDksIDAuODU0OTgsIDAuNTY5NjMsIDAuODgyNTQsIDEuMjM1MTYsIDAuODY3NSwgMC44MTU1MiwgMC43NTQ0MywgMC44NDUwMywgMC43MzIwNiwgMC43NjY1OSwgMC44NjI3NSwgMC44NTEyMiwgMC45MDY4NSwgMC43Nzg5MiwgMC44NTc0NiwgMS4wMjYzOCwgMC44OTM4NSwgMC43NTY1NywgMC44NTEyMiwgMC44NjI3NSwgMC43NzQ1MiwgMC43NDE3MSwgMC43OTc3NiwgMC43MzA2LCAwLjk1MTY1LCAwLjc3ODE4LCAwLjg5NzcyLCAwLjg4ODMxLCAwLjkwNjg1LCAwLjczMDYsIDAuOTgxNDIsIDEuMDIxOTEsIDAuOTY1NzYsIDEuMjM1MTYsIDAuOTkwMTgsIDAuOTgxNDIsIDAuOTIzNiwgMC44OTI1OCwgMC45NDAzNSwgMS4wMjE5MSwgMC43ODg0OCwgMC45NjU3NiwgMC45NTYxLCAxLjIzNTE2LCAwLjkwOTE4LCAwLjkyNTc4LCAwLjk1NDI0LCAwLjg5NzQ2LCAwLjgzOTY5LCAwLjk0ODIsIDAuODAxMTMsIDAuODk0NDIsIDAuODUyMDgsIDAuODYxNTUsIDAuOTgwMjIsIDAuOTkwMTgsIDEuMDA0NTIsIDAuODEyMDksIDAuOTkyNDcsIDAuODkxODEsIDEuMjM1MTYsIDAuOTkwMTgsIDAuOTQ4MiwgMC45OTAxOCwgMC44OTE4MSwgMC43MzIwNiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC44ODg0NCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC44OTQ2NCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45Njc2NiwgMSwgMSwgMSwgMSwgMSwgMSwgMC45NDI1OCwgMC45ODk4NiwgMC45NDI1OCwgMC45ODk4NiwgMC45NDI1OCwgMC45ODk4NiwgMC43MzA2LCAwLjkwNTI3LCAxLCAxLCAwLjg5NTUyLCAwLjkwNTI3LCAxLCAwLjkwMTg2LCAxLjEyMzA4LCAxLjEyMzA4LCAxLjEyMzA4LCAxLjEyMzA4LCAxLjI1NjYsIDEuMjU2NiwgMS4yNTY2LCAwLjg5NTUyLCAwLjg5NTUyLCAxLjQyMjU5LCAwLjY5MDQzLCAxLjAzODA5LCAxLCAxLCAxLjAxNzYsIDEuMDE3NiwgMS4xMTUyMywgMS40OTU2LCAyLjAxNDYyLCAwLjk5MzMxLCAwLjgyNjE2LCAwLjkxMTMzLCAwLjg0Mjg2LCAwLjkxMTMzLCAxLCAxLCAxLCAwLjcwNTA4LCAxLCAxLjIzMTA4LCAwLjc5ODAxLCAwLjg0NDI2LCAwLjg0NDI2LCAwLjc3NCwgMC45MDUyNywgMS44MTA1NSwgMC45MDUyNywgMS44MTA1NSwgMS4yODgwOSwgMS41NTQ2OSwgMC45NDQzNCwgMS4wNzgwNiwgMSwgMC45NzA5NCwgMC43NTg5LCAwLjg1Mjg0LCAwLjkwNzQ3LCAxLjE5NjU4LCAwLjY5ODI1LCAwLjk3NjIyLCAxLjMzNTEyLCAwLjkwNzQ3LCAwLjkwNzQ3LCAwLjg1MzU2LCAwLjkwNzQ3LCAwLjkwNzQ3LCAxLjQ0OTQ3LCAwLjg1Mjg0LCAwLjg5NDEsIDAuODk0MSwgMC43MDU3MiwgMC44LCAwLjcwNTcyLCAwLjcwNTcyLCAwLjcwNTcyLCAwLjcwNTcyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk5ODYyLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLjAzMzYsIDAuOTEwMjcsIDEsIDEsIDEsIDAuOTk4NjIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDU4NTksIDEuMDU4NTksIDEsIDEsIDEsIDEuMDcxODUsIDAuOTk0MTMsIDAuOTYzMzQsIDEuMDgwNjUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBDYWxpYnJpUmVndWxhck1ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yMjA3LAogIGxpbmVHYXA6IDAuMjIwNwp9OwoKOy8vIC4vc3JjL2NvcmUvaGVsdmV0aWNhX2ZhY3RvcnMuanMKY29uc3QgSGVsdmV0aWNhQm9sZEZhY3RvcnMgPSBbMC43NjExNiwgMSwgMSwgMS4wMDA2LCAwLjk5OTk4LCAwLjk5OTc0LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTgyLCAwLjk5OTc3LCAxLjAwMDg3LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTU5LCAxLjAwMDAzLCAxLjAwMDYsIDAuOTk5OTgsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTk4LCAxLCAxLjAwMDAzLCAxLjAwMDAzLCAxLjAwMDAzLCAxLjAwMDI2LCAwLjk5OTksIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMjYsIDEuMDAwMjIsIDAuOTk5NzcsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3NywgMS4wMDAyNiwgMC45OTk5OSwgMC45OTk3NywgMS4wMDAyMiwgMS4wMDAwMSwgMS4wMDAyMiwgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAxNiwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk5OCwgMS4wMDA2LCAwLjk5OTk4LCAxLjAwMDAzLCAwLjk5OTczLCAwLjk5OTk4LCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTczLCAwLjk5OTk4LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MywgMS4wMDA2LCAwLjk5OTgyLCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAwLjk5OTU5LCAwLjk5OTczLCAwLjk5OTk4LCAxLjAwMDI2LCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAwLjk5OTczLCAxLCAwLjk5OTU5LCAxLjAwMDc3LCAwLjk5OTU5LCAxLjAwMDAzLCAwLjk5OTk4LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDc3LCAwLjk5OTczLCAwLjk5OTk4LCAxLjAwMDI1LCAwLjk5OTY4LCAwLjk5OTczLCAxLjAwMDAzLCAxLjAwMDI1LCAwLjYwMjk5LCAxLjAwMDI0LCAxLjA2NDA5LCAxLCAxLCAwLjk5OTk4LCAxLCAwLjk5OTczLCAxLjAwMDYsIDAuOTk5OTgsIDEsIDAuOTk5MzYsIDAuOTk5NzMsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMjYsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDEsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3NywgMC45OTk3NywgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAwMywgMS4wMDAyMiwgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk4MiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjA2NDA5LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAxLjAzMzc0LCAwLjk5OTc3LCAxLjAwMDI2LCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNDIsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMC45OTk3NywgMC45OTk3MywgMC45OTk3MywgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwMjYsIDEuMDM4MjgsIDEuMDAwMjYsIDAuOTk5OTksIDEuMDAwMjYsIDEuMDAwNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTkzLCAwLjk5OTgsIDEuMDAwMjYsIDEuMDAwMjIsIDEuMDAwMjYsIDEuMDAwMjIsIDEuMDAwMjYsIDEuMDAwMjIsIDEuMDAwMjYsIDEsIDEuMDAwMTYsIDAuOTk5NzcsIDAuOTk5NTksIDAuOTk5NzcsIDAuOTk5NTksIDAuOTk5NzcsIDAuOTk5NTksIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMjYsIDAuOTk5OTgsIDEuMDAwMjYsIDAuODEyMSwgMS4wMDAyNiwgMC45OTk5OCwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMS4wMDAxNiwgMS4wMDAyMiwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMS4wMDAyNiwgMSwgMS4wMDAyNiwgMSwgMS4wMDAyNiwgMSwgMS4wMDA2LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLCAwLjk5OTgyLCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAxLjAwMDM0LCAwLjk5OTc3LCAxLCAwLjk5OTk3LCAxLjAwMDI2LCAxLjAwMDc4LCAxLjAwMDM2LCAwLjk5OTczLCAxLjAwMDEzLCAxLjAwMDYsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5ODgsIDAuODUxNDgsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwNiwgMC45OTk3NywgMS4wMDAwMSwgMC45OTk5OSwgMC45OTk3NywgMS4wMDA2OSwgMS4wMDAyMiwgMC45OTk3NywgMS4wMDAwMSwgMC45OTk4NCwgMS4wMDAyNiwgMS4wMDAwMSwgMS4wMDAyNCwgMS4wMDAwMSwgMC45OTk5LCAxLCAxLjAwMDYsIDEuMDAwMDEsIDEuMDAwNDEsIDAuOTk5NjIsIDEuMDAwMjYsIDEuMDAwNiwgMC45OTk5NSwgMS4wMDA0MSwgMC45OTk0MiwgMC45OTk3MywgMC45OTkyNywgMS4wMDA4MiwgMC45OTkwMiwgMS4wMDAyNiwgMS4wMDA4NywgMS4wMDA2LCAxLjAwMDY5LCAwLjk5OTczLCAwLjk5ODY3LCAwLjk5OTczLCAwLjk5OTMsIDEuMDAwMjYsIDEuMDAwNDksIDEuMDAwNTYsIDEsIDAuOTk5ODgsIDAuOTk5MzUsIDAuOTk5OTUsIDAuOTk5NTQsIDEuMDAwNTUsIDAuOTk5NDUsIDEuMDAwMzIsIDEuMDAwNiwgMC45OTk5NSwgMS4wMDAyNiwgMC45OTk5NSwgMS4wMDAzMiwgMS4wMDAwMSwgMS4wMDAwOCwgMC45OTk3MSwgMS4wMDAxOSwgMC45OTk0LCAxLjAwMDAxLCAxLjAwMDYsIDEuMDAwNDQsIDAuOTk5NzMsIDEuMDAwMjMsIDEuMDAwNDcsIDEsIDAuOTk5NDIsIDAuOTk1NjEsIDAuOTk5ODksIDEuMDAwMzUsIDAuOTk5NzcsIDEuMDAwMzUsIDAuOTk5NzcsIDEuMDAwMTksIDAuOTk5NDQsIDEuMDAwMDEsIDEuMDAwMjEsIDAuOTk5MjYsIDEuMDAwMzUsIDEuMDAwMzUsIDAuOTk5NDIsIDEuMDAwNDgsIDAuOTk5OTksIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMzUsIDEuMDAwMDEsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5ODksIDEuMDAwNTcsIDEuMDAwMDEsIDAuOTk5MzYsIDEuMDAwNTIsIDEuMDAwMTIsIDAuOTk5OTYsIDEuMDAwNDMsIDEsIDEuMDAwMzUsIDAuOTk5NCwgMC45OTk3NiwgMS4wMDAzNSwgMC45OTk3MywgMS4wMDA1MiwgMS4wMDA0MSwgMS4wMDExOSwgMS4wMDAzNywgMC45OTk3MywgMS4wMDAwMiwgMC45OTk4NiwgMS4wMDA0MSwgMS4wMDA0MSwgMC45OTkwMiwgMC45OTk2LCAxLjAwMDM0LCAwLjk5OTk5LCAxLjAwMDI2LCAwLjk5OTk5LCAxLjAwMDI2LCAwLjk5OTczLCAxLjAwMDUyLCAwLjk5OTczLCAxLCAwLjk5OTczLCAxLjAwMDQxLCAxLjAwMDc1LCAwLjk5OTQsIDEuMDAwMywgMC45OTk5OSwgMSwgMS4wMDA0MSwgMC45OTk1NSwgMSwgMC45OTkxNSwgMC45OTk3MywgMC45OTk3MywgMS4wMDAyNiwgMS4wMDExOSwgMC45OTk1NSwgMC45OTk3MywgMS4wMDA2LCAwLjk5OTExLCAxLjAwMDYsIDEuMDAwMjYsIDAuOTk5NzIsIDEuMDAwMjYsIDAuOTk5MDIsIDEuMDAwNDEsIDAuOTk5NzMsIDAuOTk5OTksIDEsIDEsIDEuMDAwMzgsIDEuMDAwNSwgMS4wMDAxNiwgMS4wMDAyMiwgMS4wMDAxNiwgMS4wMDAyMiwgMS4wMDAxNiwgMS4wMDAyMiwgMS4wMDAwMSwgMC45OTk3MywgMSwgMSwgMC45OTk3MywgMSwgMSwgMC45OTk1NSwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLCAxLCAxLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTcyLCAxLCAxLCAxLjAwMTA2LCAwLjk5OTk5LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk5LCAwLjk5OTk4LCAxLjY2NDc1LCAxLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDIzLCAwLjk5OTczLCAwLjk5OTcxLCAxLjAwMDQ3LCAxLjAwMDIzLCAxLCAwLjk5OTkxLCAwLjk5OTg0LCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk5OTcyLCAxLCAxLjIwOTg1LCAxLjM5NzEzLCAxLjAwMDAzLCAxLjAwMDMxLCAxLjAwMDE1LCAxLCAwLjk5NTYxLCAxLjAwMDI3LCAxLjAwMDMxLCAxLjAwMDMxLCAwLjk5OTE1LCAxLjAwMDMxLCAxLjAwMDMxLCAwLjk5OTk5LCAxLjAwMDAzLCAwLjk5OTk5LCAwLjk5OTk5LCAxLjQxMTQ0LCAxLjYsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDA1NzksIDEuNDA1NzksIDEuMzY2MjUsIDAuOTk5OTksIDEsIDAuOTk4NjEsIDAuOTk4NjEsIDEsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDAuOTk5NzIsIDAuOTk5OTksIDAuOTk5OTksIDAuOTk5OTksIDAuOTk5OTksIDEuNDA0ODMsIDEsIDAuOTk5NzcsIDEuMDAwNTQsIDEsIDEsIDAuOTk5NTMsIDAuOTk5NjIsIDEuMDAwNDIsIDAuOTk5NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmNvbnN0IEhlbHZldGljYUJvbGRNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMiwKICBsaW5lR2FwOiAwLjIKfTsKY29uc3QgSGVsdmV0aWNhQm9sZEl0YWxpY0ZhY3RvcnMgPSBbMC43NjExNiwgMSwgMSwgMS4wMDA2LCAwLjk5OTk4LCAwLjk5OTc0LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTgyLCAwLjk5OTc3LCAxLjAwMDg3LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTU5LCAxLjAwMDAzLCAxLjAwMDYsIDAuOTk5OTgsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTk4LCAxLCAxLjAwMDAzLCAxLjAwMDAzLCAxLjAwMDAzLCAxLjAwMDI2LCAwLjk5OTksIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMjYsIDEuMDAwMjIsIDAuOTk5NzcsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3NywgMS4wMDAyNiwgMC45OTk5OSwgMC45OTk3NywgMS4wMDAyMiwgMS4wMDAwMSwgMS4wMDAyMiwgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAxNiwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk5OCwgMS4wMDA2LCAwLjk5OTk4LCAxLjAwMDAzLCAwLjk5OTczLCAwLjk5OTk4LCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTczLCAwLjk5OTk4LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MywgMS4wMDA2LCAwLjk5OTgyLCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAwLjk5OTU5LCAwLjk5OTczLCAwLjk5OTk4LCAxLjAwMDI2LCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAwLjk5OTczLCAxLCAwLjk5OTU5LCAxLjAwMDc3LCAwLjk5OTU5LCAxLjAwMDAzLCAwLjk5OTk4LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDc3LCAwLjk5OTczLCAwLjk5OTk4LCAxLjAwMDI1LCAwLjk5OTY4LCAwLjk5OTczLCAxLjAwMDAzLCAxLjAwMDI1LCAwLjYwMjk5LCAxLjAwMDI0LCAxLjA2NDA5LCAxLCAxLCAwLjk5OTk4LCAxLCAwLjk5OTczLCAxLjAwMDYsIDAuOTk5OTgsIDEsIDAuOTk5MzYsIDAuOTk5NzMsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMjYsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDEsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3NywgMC45OTk3NywgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAwMywgMS4wMDAyMiwgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk4MiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjA2NDA5LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAxLjAwNDQsIDAuOTk5NzcsIDEuMDAwMjYsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMjIsIDEuMDAwMjYsIDEuMDAwMjIsIDEuMDAwMjYsIDEuMDAwMjIsIDEuMDAwMjYsIDEuMDAwMjIsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MSwgMC45OTk3MywgMC45OTk3MywgMS4wMDA2LCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDAyNiwgMS4wMTAxMSwgMS4wMDAyNiwgMC45OTk5OSwgMS4wMDAyNiwgMS4wMDA2LCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTMsIDAuOTk5OCwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMSwgMS4wMDAxNiwgMC45OTk3NywgMC45OTk1OSwgMC45OTk3NywgMC45OTk1OSwgMC45OTk3NywgMC45OTk1OSwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk5OCwgMS4wMDAyNiwgMC44MTIxLCAxLjAwMDI2LCAwLjk5OTk4LCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDI2LCAxLjAwMDE2LCAxLjAwMDIyLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAxLjAwMDI2LCAxLCAxLjAwMDI2LCAxLCAxLjAwMDI2LCAxLCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzcsIDAuOTk5NzMsIDEsIDAuOTk5ODIsIDEuMDAwMjIsIDEuMDAwMjYsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMjYsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5NzcsIDEsIDEsIDEuMDAwMjYsIDAuOTk5NjksIDAuOTk5NzIsIDAuOTk5ODEsIDAuOTk5OCwgMS4wMDA2LCAwLjk5OTc3LCAwLjk5OTc3LCAxLjAwMDIyLCAwLjkxMTU1LCAxLjAwMDAxLCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDYsIDAuOTk5NzcsIDEuMDAwMDEsIDAuOTk5OTksIDAuOTk5NzcsIDAuOTk5NjYsIDEuMDAwMjIsIDEuMDAwMzIsIDEuMDAwMDEsIDAuOTk5NDQsIDEuMDAwMjYsIDEuMDAwMDEsIDAuOTk5NjgsIDEuMDAwMDEsIDEuMDAwNDcsIDEsIDEuMDAwNiwgMS4wMDAwMSwgMC45OTk4MSwgMS4wMDEwMSwgMS4wMDAyNiwgMS4wMDA2LCAwLjk5OTQ4LCAwLjk5OTgxLCAxLjAwMDY0LCAwLjk5OTczLCAwLjk5OTQyLCAxLjAwMTAxLCAxLjAwMDYxLCAxLjAwMDI2LCAxLjAwMDY5LCAxLjAwMDYsIDEuMDAwMTQsIDAuOTk5NzMsIDEuMDEzMjIsIDAuOTk5NzMsIDEuMDAwNjUsIDEuMDAwMjYsIDEuMDAwMTIsIDAuOTk5MjMsIDEsIDEuMDAwNjQsIDEuMDAwNzYsIDAuOTk5NDgsIDEuMDAwNTUsIDEuMDAwNjMsIDEuMDAwMDcsIDAuOTk5NDMsIDEuMDAwNiwgMC45OTk0OCwgMS4wMDAyNiwgMC45OTk0OCwgMC45OTk0MywgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAyOSwgMS4wMDAzOCwgMS4wMDAzNSwgMS4wMDAwMSwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzgsIDEuMDAwMDEsIDEuMDAwNTcsIDAuOTk5ODksIDAuOTk5NjcsIDAuOTk5NjQsIDAuOTk5NjcsIDAuOTk5NzcsIDAuOTk5OTksIDAuOTk5NzcsIDEuMDAwMzgsIDAuOTk5NzcsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwNjYsIDAuOTk5NjcsIDAuOTk5NjcsIDEuMDAwNDEsIDAuOTk5OTgsIDAuOTk5OTksIDAuOTk5NzcsIDEuMDAwMjIsIDAuOTk5NjcsIDEuMDAwMDEsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NjQsIDEuMDAwMzEsIDEuMDAwMDEsIDAuOTk5OTksIDAuOTk5OTksIDEsIDEuMDAwMjMsIDEsIDEsIDAuOTk5OTksIDEuMDAwMzUsIDEuMDAwMDEsIDAuOTk5OTksIDAuOTk5NzMsIDAuOTk5NzcsIDAuOTk5OTksIDEuMDAwNTgsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NTUsIDAuOTk5NSwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAzMiwgMC45OTk4OSwgMS4wMDAzNCwgMC45OTk5OSwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMC45OTk3MywgMC40NTk5OCwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk5OSwgMC45OTk4MiwgMC45OTk5NCwgMC45OTk5NiwgMSwgMS4wMDA0MiwgMS4wMDA0NCwgMS4wMDAyOSwgMS4wMDAyMywgMC45OTk3MywgMC45OTk3MywgMS4wMDAyNiwgMC45OTk0OSwgMS4wMDAwMiwgMC45OTk3MywgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3NSwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAzMiwgMC45ODY4NSwgMC45OTk3MywgMS4wMDAyNiwgMSwgMSwgMC45OTk2NiwgMS4wMDA0NCwgMS4wMDAxNiwgMS4wMDAyMiwgMS4wMDAxNiwgMS4wMDAyMiwgMS4wMDAxNiwgMS4wMDAyMiwgMS4wMDAwMSwgMC45OTk3MywgMSwgMSwgMC45OTk3MywgMSwgMSwgMC45OTk1NSwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLCAxLCAxLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTcyLCAxLCAxLCAxLjAwMTA2LCAwLjk5OTk5LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk5LCAwLjk5OTk4LCAxLjY2NDc1LCAxLCAwLjk5OTczLCAwLjk5OTczLCAxLCAwLjk5OTczLCAwLjk5OTcxLCAwLjk5OTc4LCAxLCAxLCAwLjk5OTkxLCAwLjk5OTg0LCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDk4LCAxLCAxLCAxLCAxLjAwMDQ5LCAxLCAxLCAwLjk5OTcyLCAxLCAxLjIwOTg1LCAxLjM5NzEzLCAxLjAwMDAzLCAxLjAwMDMxLCAxLjAwMDE1LCAxLCAwLjk5NTYxLCAxLjAwMDI3LCAxLjAwMDMxLCAxLjAwMDMxLCAwLjk5OTE1LCAxLjAwMDMxLCAxLjAwMDMxLCAwLjk5OTk5LCAxLjAwMDAzLCAwLjk5OTk5LCAwLjk5OTk5LCAxLjQxMTQ0LCAxLjYsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDA1NzksIDEuNDA1NzksIDEuMzY2MjUsIDAuOTk5OTksIDEsIDAuOTk4NjEsIDAuOTk4NjEsIDEsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDAuOTk5NzIsIDAuOTk5OTksIDAuOTk5OTksIDAuOTk5OTksIDAuOTk5OTksIDEuNDA0ODMsIDEsIDAuOTk5NzcsIDEuMDAwNTQsIDEsIDEsIDAuOTk5NTMsIDAuOTk5NjIsIDEuMDAwNDIsIDAuOTk5NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmNvbnN0IEhlbHZldGljYUJvbGRJdGFsaWNNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMzUsCiAgbGluZUdhcDogMC4yCn07CmNvbnN0IEhlbHZldGljYUl0YWxpY0ZhY3RvcnMgPSBbMC43NjExNiwgMSwgMSwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwMDYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5ODIsIDEuMDAwMDEsIDEuMDAwNDMsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5NTksIDEuMDAwMDMsIDEuMDAwNiwgMC45OTk5OCwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMSwgMS4wMDAwMywgMS4wMDAwMywgMS4wMDAwMywgMC45OTk3MywgMC45OTk4NywgMS4wMDAwMSwgMS4wMDAwMSwgMC45OTk3NywgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAyNiwgMS4wMDAyMiwgMC45OTk3NywgMS4wMDA2LCAxLCAxLjAwMDAxLCAwLjk5OTczLCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDAxLCAxLjAwMDIyLCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDE2LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTQ5LCAwLjk5OTczLCAwLjk5OTk4LCAwLjk5OTczLCAwLjk5OTczLCAxLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5MjQsIDAuOTk5MjQsIDEsIDAuOTk5MjQsIDAuOTk5OTksIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5OTgsIDEsIDEuMDAwNiwgMC45OTk3MywgMSwgMC45OTk3NywgMSwgMSwgMSwgMS4wMDAwNSwgMS4wMDA5LCAxLjAwMDA1LCAxLjAwMDAzLCAwLjk5OTk4LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDksIDAuOTk5NzMsIDAuOTk5OTgsIDEuMDAwMjUsIDAuOTk5NjgsIDAuOTk5NzMsIDEuMDAwMDMsIDEuMDAwMjUsIDAuNjAyOTksIDEuMDAwMjQsIDEuMDY0MDksIDEsIDEsIDAuOTk5OTgsIDEsIDAuOTk5OCwgMS4wMDA2LCAwLjk5OTk4LCAxLCAwLjk5OTM2LCAwLjk5OTczLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDI2LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMDMsIDEuMDAwMjIsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5ODIsIDEsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wNjQwOSwgMS4wMDAyNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMSwgMC45OTk3MywgMSwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMC45OTk3NywgMSwgMC45OTk3NywgMSwgMC45OTk3NywgMSwgMC45OTk3NywgMSwgMC45OTk3NywgMS4wMjg4LCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5MjQsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTQ2LCAxLjAwMDM0LCAxLCAwLjk5OTI0LCAxLjAwMDAxLCAxLCAxLCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTczLCAxLjA2MzExLCAwLjk5OTczLCAxLjAwMDI0LCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDQxLCAwLjk5OTgsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEsIDEuMDAwMTYsIDAuOTk5NzcsIDAuOTk5OTgsIDAuOTk5NzcsIDAuOTk5OTgsIDAuOTk5NzcsIDAuOTk5OTgsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDAyNiwgMC44OTU0NywgMS4wMDAyNiwgMS4wMDA2LCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDAxLCAxLCAxLjAwMDAxLCAxLjAwMDI2LCAxLCAxLjAwMDI2LCAxLCAxLjAwMDI2LCAxLCAwLjk5OTI0LCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLCAwLjk5OTgyLCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDAxLCAxLCAxLjAwMDI2LCAxLjAwMDYsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDEuMDAwMDEsIDEsIDEuMDAwNTQsIDAuOTk5NzcsIDEuMDAwODQsIDEuMDAwMDcsIDAuOTk5NzMsIDEuMDAwMTMsIDAuOTk5MjQsIDEuMDAwMDEsIDEuMDAwMDEsIDAuOTk5NDUsIDAuOTEyMjEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwNiwgMS4wMDAwMSwgMS4wMDAwMSwgMC45OTk5OSwgMC45OTk3NywgMC45OTkzMywgMS4wMDAyMiwgMS4wMDA1NCwgMS4wMDAwMSwgMS4wMDA2NSwgMS4wMDAyNiwgMS4wMDAwMSwgMS4wMDAxLCAxLjAwMDAxLCAxLjAwMDUyLCAxLCAxLjAwMDYsIDEuMDAwMDEsIDAuOTk5NDUsIDAuOTk4OTcsIDAuOTk5NjgsIDAuOTk5MjQsIDEuMDAwMzYsIDAuOTk5NDUsIDAuOTk5NDksIDEsIDEuMDAwNiwgMC45OTg5NywgMC45OTkxOCwgMC45OTk2OCwgMC45OTkxMSwgMC45OTkyNCwgMSwgMC45OTk2MiwgMS4wMTQ4NywgMSwgMS4wMDA1LCAwLjk5OTczLCAxLjAwMDEyLCAxLjAwMDQzLCAxLCAwLjk5OTk1LCAwLjk5OTk0LCAxLjAwMDM2LCAwLjk5OTQ3LCAxLjAwMDE5LCAxLjAwMDYzLCAxLjAwMDI1LCAwLjk5OTI0LCAxLjAwMDM2LCAwLjk5OTczLCAxLjAwMDM2LCAxLjAwMDI1LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDI3LCAxLjAwMDEsIDEuMDAwNjgsIDEuMDAwMDEsIDEuMDAwNiwgMS4wMDA2LCAxLCAxLjAwMDA4LCAwLjk5OTU3LCAwLjk5OTcyLCAwLjk5OTQsIDAuOTk5NTQsIDAuOTk5NzUsIDEuMDAwNTEsIDEuMDAwMDEsIDEuMDAwMTksIDEuMDAwMDEsIDEuMDAwMSwgMC45OTk4NiwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAzOCwgMC45OTk1NCwgMC45OTk1NCwgMC45OTk0LCAxLjAwMDY2LCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDU0LCAxLjAwMDAxLCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTc1LCAxLjAwMDEsIDEuMDAwMDEsIDAuOTk5OTMsIDAuOTk5NSwgMC45OTk1NSwgMS4wMDAxNiwgMC45OTk3OCwgMC45OTk3NCwgMS4wMDAxOSwgMS4wMDAyMiwgMC45OTk1NSwgMS4wMDA1MywgMC45OTk3MywgMS4wMDA4OSwgMS4wMDAwNSwgMC45OTk2NywgMS4wMDA0OCwgMC45OTk3MywgMS4wMDAwMiwgMS4wMDAzNCwgMC45OTk3MywgMC45OTk3MywgMC45OTk2NCwgMS4wMDAwNiwgMS4wMDA2NiwgMC45OTk0NywgMC45OTk3MywgMC45ODg5NCwgMC45OTk3MywgMSwgMC40NDg5OCwgMSwgMC45OTk0NiwgMSwgMS4wMDAzOSwgMS4wMDA4MiwgMC45OTk5MSwgMC45OTk5MSwgMC45OTk4NSwgMS4wMDAyMiwgMS4wMDAyMywgMS4wMDA2MSwgMS4wMDAwNiwgMC45OTk2NiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDAxOSwgMS4wMDA4LCAxLCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTgzLCAxLjAwMDQ0LCAwLjk5OTczLCAwLjk5OTY0LCAwLjk4MzMyLCAxLCAwLjk5OTczLCAxLCAxLCAwLjk5OTYyLCAwLjk5ODk1LCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDAxLCAxLCAxLCAxLCAwLjk5OTczLCAxLCAxLCAwLjk5OTU1LCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTcyLCAxLCAxLCAxLjAwMjY3LCAwLjk5OTk5LCAwLjk5OTk4LCAwLjk5OTk4LCAxLCAwLjk5OTk4LCAxLjY2NDc1LCAxLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDIzLCAwLjk5OTczLCAxLjAwNDIzLCAwLjk5OTI1LCAwLjk5OTk5LCAxLCAwLjk5OTkxLCAwLjk5OTg0LCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDQ5LCAxLCAxLjAwMjQ1LCAxLCAxLCAxLCAxLCAwLjk2MzI5LCAxLCAxLjIwOTg1LCAxLjM5NzEzLCAxLjAwMDAzLCAwLjgyNTQsIDEuMDAwMTUsIDEsIDEuMDAwMzUsIDEuMDAwMjcsIDEuMDAwMzEsIDEuMDAwMzEsIDEuMDAwMDMsIDEuMDAwMzEsIDEuMDAwMzEsIDAuOTk5OTksIDEuMDAwMDMsIDAuOTk5OTksIDAuOTk5OTksIDEuNDExNDQsIDEuNiwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MDU3OSwgMS40MDU3OSwgMS4zNjYyNSwgMC45OTk5OSwgMSwgMC45OTg2MSwgMC45OTg2MSwgMSwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMC45NTMxNywgMC45OTk5OSwgMC45OTk5OSwgMC45OTk5OSwgMC45OTk5OSwgMS40MDQ4MywgMSwgMC45OTk3NywgMS4wMDA1NCwgMSwgMSwgMC45OTk1MywgMC45OTk2MiwgMS4wMDA0MiwgMC45OTk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKY29uc3QgSGVsdmV0aWNhSXRhbGljTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjM1LAogIGxpbmVHYXA6IDAuMgp9Owpjb25zdCBIZWx2ZXRpY2FSZWd1bGFyRmFjdG9ycyA9IFswLjc2MTE2LCAxLCAxLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk4MiwgMS4wMDAwMSwgMS4wMDA0MywgMC45OTk5OCwgMC45OTk5OCwgMC45OTk1OSwgMS4wMDAwMywgMS4wMDA2LCAwLjk5OTk4LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDA2LCAxLCAxLjAwMDAzLCAxLjAwMDAzLCAxLjAwMDAzLCAwLjk5OTczLCAwLjk5OTg3LCAxLjAwMDAxLCAxLjAwMDAxLCAwLjk5OTc3LCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDI2LCAxLjAwMDIyLCAwLjk5OTc3LCAxLjAwMDYsIDEsIDEuMDAwMDEsIDAuOTk5NzMsIDAuOTk5OTksIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMDEsIDEuMDAwMjIsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMTYsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NDksIDAuOTk5NzMsIDAuOTk5OTgsIDAuOTk5NzMsIDAuOTk5NzMsIDEsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTkyNCwgMC45OTkyNCwgMSwgMC45OTkyNCwgMC45OTk5OSwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk5OCwgMSwgMS4wMDA2LCAwLjk5OTczLCAxLCAwLjk5OTc3LCAxLCAxLCAxLCAxLjAwMDA1LCAxLjAwMDksIDEuMDAwMDUsIDEuMDAwMDMsIDAuOTk5OTgsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwOSwgMC45OTk3MywgMC45OTk5OCwgMS4wMDAyNSwgMC45OTk2OCwgMC45OTk3MywgMS4wMDAwMywgMS4wMDAyNSwgMC42MDI5OSwgMS4wMDAyNCwgMS4wNjQwOSwgMSwgMSwgMC45OTk5OCwgMSwgMC45OTk4LCAxLjAwMDYsIDAuOTk5OTgsIDEsIDAuOTk5MzYsIDAuOTk5NzMsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMjYsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3NywgMC45OTk3NywgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAwMywgMS4wMDAyMiwgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk4MiwgMSwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLjA2NDA5LCAxLjAwMDI2LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLCAwLjk5OTczLCAxLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAwLjk5OTc3LCAxLCAwLjk5OTc3LCAxLCAwLjk5OTc3LCAxLCAwLjk5OTc3LCAxLCAwLjk5OTc3LCAxLjA0NTk2LCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5MjQsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDE5LCAxLjAwMDM0LCAxLCAwLjk5OTI0LCAxLjAwMDAxLCAxLCAxLCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTczLCAxLjAyNTcyLCAwLjk5OTczLCAxLjAwMDA1LCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTk5LCAwLjk5OTgsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEsIDEuMDAwMTYsIDAuOTk5NzcsIDAuOTk5OTgsIDAuOTk5NzcsIDAuOTk5OTgsIDAuOTk5NzcsIDAuOTk5OTgsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDAyNiwgMC44NDUzMywgMS4wMDAyNiwgMS4wMDA2LCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDAxLCAxLCAxLjAwMDAxLCAxLjAwMDI2LCAxLCAxLjAwMDI2LCAxLCAxLjAwMDI2LCAxLCAwLjk5OTI0LCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLCAwLjk5OTgyLCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDAxLCAxLCAxLjAwMDI2LCAxLjAwMDYsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5MjgsIDEsIDAuOTk5NzcsIDEuMDAwMTMsIDEuMDAwNTUsIDAuOTk5NDcsIDAuOTk5NDUsIDAuOTk5NDEsIDAuOTk5MjQsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwNCwgMC45MTYyMSwgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyMiwgMS4wMDA2LCAxLjAwMDAxLCAxLjAwMDA1LCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDE1LCAxLjAwMDIyLCAwLjk5OTc3LCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDI2LCAxLjAwMDAxLCAxLjAwMDE5LCAxLjAwMDAxLCAwLjk5OTQ2LCAxLCAxLjAwMDYsIDEuMDAwMDEsIDAuOTk5NzgsIDEuMDAwNDUsIDAuOTk5NzMsIDAuOTk5MjQsIDEuMDAwMjMsIDAuOTk5NzgsIDAuOTk5NjYsIDEsIDEuMDAwNjUsIDEuMDAwNDUsIDEuMDAwMTksIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5MjQsIDEsIDEsIDAuOTY0OTksIDEsIDEuMDAwNTUsIDAuOTk5NzMsIDEuMDAwMDgsIDEuMDAwMjcsIDEsIDAuOTk5NywgMC45OTk5NSwgMS4wMDAyMywgMC45OTkzMywgMS4wMDAxOSwgMS4wMDAxNSwgMS4wMDAzMSwgMC45OTkyNCwgMS4wMDAyMywgMC45OTk3MywgMS4wMDAyMywgMS4wMDAzMSwgMS4wMDAwMSwgMC45OTkyOCwgMS4wMDAyOSwgMS4wMDA5MiwgMS4wMDAzNSwgMS4wMDAwMSwgMS4wMDA2LCAxLjAwMDYsIDEsIDAuOTk5ODgsIDAuOTk5NzUsIDEsIDEuMDAwODIsIDAuOTk1NjEsIDAuOTk5NiwgMS4wMDAzNSwgMS4wMDAwMSwgMC45OTk2MiwgMS4wMDAwMSwgMS4wMDA5MiwgMC45OTk2NCwgMS4wMDAwMSwgMC45OTk2MywgMC45OTk5OSwgMS4wMDAzNSwgMS4wMDAzNSwgMS4wMDA4MiwgMC45OTk2MiwgMC45OTk5OSwgMC45OTk3NywgMS4wMDAyMiwgMS4wMDAzNSwgMS4wMDAwMSwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk2LCAwLjk5OTY3LCAxLjAwMDAxLCAxLjAwMDM0LCAxLjAwMDc0LCAxLjAwMDU0LCAxLjAwMDUzLCAxLjAwMDYzLCAwLjk5OTcxLCAwLjk5OTYyLCAxLjAwMDM1LCAwLjk5OTc1LCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDQzLCAwLjk5OTUzLCAxLjAwMDcsIDAuOTk5MTUsIDAuOTk5NzMsIDEuMDAwMDgsIDAuOTk4OTIsIDEuMDAwNzMsIDEuMDAwNzMsIDEuMDAxMTQsIDAuOTk5MTUsIDEuMDAwNzMsIDAuOTk5NTUsIDAuOTk5NzMsIDEuMDAwOTIsIDAuOTk5NzMsIDEsIDAuOTk5OTgsIDEsIDEuMDAwMywgMSwgMS4wMDA0MywgMS4wMDAwMSwgMC45OTk2OSwgMS4wMDAzLCAxLCAxLjAwMDM1LCAxLjAwMDAxLCAwLjk5OTUsIDEsIDEuMDAwOTIsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNywgMC45OTk1LCAxLCAwLjk5OTI0LCAxLjAwMDYsIDAuOTk5MjQsIDAuOTk5NzIsIDEuMDAwNjIsIDAuOTk5NzMsIDEuMDAxMTQsIDEuMDAwNzMsIDEsIDAuOTk5NTUsIDEsIDEsIDEuMDAwNDcsIDAuOTk5NjgsIDEuMDAwMTYsIDAuOTk5NzcsIDEuMDAwMTYsIDAuOTk5NzcsIDEuMDAwMTYsIDAuOTk5NzcsIDEuMDAwMDEsIDEsIDEsIDEsIDAuOTk5NzMsIDEsIDEsIDAuOTk5NTUsIDAuOTk5MjQsIDAuOTk5MjQsIDAuOTk5MjQsIDAuOTk5MjQsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzIsIDEsIDEsIDEuMDAyNjcsIDAuOTk5OTksIDAuOTk5OTgsIDAuOTk5OTgsIDEsIDAuOTk5OTgsIDEuNjY0NzUsIDEsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwMjMsIDAuOTk5NzMsIDAuOTk5NzEsIDAuOTk5MjUsIDEuMDAwMjMsIDEsIDAuOTk5OTEsIDAuOTk5ODQsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMDIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTYzMjksIDEsIDEuMjA5ODUsIDEuMzk3MTMsIDEuMDAwMDMsIDAuODI1NCwgMS4wMDAxNSwgMSwgMS4wMDAzNSwgMS4wMDAyNywgMS4wMDAzMSwgMS4wMDAzMSwgMC45OTkxNSwgMS4wMDAzMSwgMS4wMDAzMSwgMC45OTk5OSwgMS4wMDAwMywgMC45OTk5OSwgMC45OTk5OSwgMS40MTE0NCwgMS42LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQwNTc5LCAxLjQwNTc5LCAxLjM2NjI1LCAwLjk5OTk5LCAxLCAwLjk5ODYxLCAwLjk5ODYxLCAxLCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAwLjk1MzE3LCAwLjk5OTk5LCAwLjk5OTk5LCAwLjk5OTk5LCAwLjk5OTk5LCAxLjQwNDgzLCAxLCAwLjk5OTc3LCAxLjAwMDU0LCAxLCAxLCAwLjk5OTUzLCAwLjk5OTYyLCAxLjAwMDQyLCAwLjk5OTUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBIZWx2ZXRpY2FSZWd1bGFyTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjIsCiAgbGluZUdhcDogMC4yCn07Cgo7Ly8gLi9zcmMvY29yZS9saWJlcmF0aW9uc2Fuc193aWR0aHMuanMKY29uc3QgTGliZXJhdGlvblNhbnNCb2xkV2lkdGhzID0gWzM2NSwgMCwgMzMzLCAyNzgsIDMzMywgNDc0LCA1NTYsIDU1NiwgODg5LCA3MjIsIDIzOCwgMzMzLCAzMzMsIDM4OSwgNTg0LCAyNzgsIDMzMywgMjc4LCAyNzgsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMzMzLCAzMzMsIDU4NCwgNTg0LCA1ODQsIDYxMSwgOTc1LCA3MjIsIDcyMiwgNzIyLCA3MjIsIDY2NywgNjExLCA3NzgsIDcyMiwgMjc4LCA1NTYsIDcyMiwgNjExLCA4MzMsIDcyMiwgNzc4LCA2NjcsIDc3OCwgNzIyLCA2NjcsIDYxMSwgNzIyLCA2NjcsIDk0NCwgNjY3LCA2NjcsIDYxMSwgMzMzLCAyNzgsIDMzMywgNTg0LCA1NTYsIDMzMywgNTU2LCA2MTEsIDU1NiwgNjExLCA1NTYsIDMzMywgNjExLCA2MTEsIDI3OCwgMjc4LCA1NTYsIDI3OCwgODg5LCA2MTEsIDYxMSwgNjExLCA2MTEsIDM4OSwgNTU2LCAzMzMsIDYxMSwgNTU2LCA3NzgsIDU1NiwgNTU2LCA1MDAsIDM4OSwgMjgwLCAzODksIDU4NCwgMzMzLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDI4MCwgNTU2LCAzMzMsIDczNywgMzcwLCA1NTYsIDU4NCwgNzM3LCA1NTIsIDQwMCwgNTQ5LCAzMzMsIDMzMywgMzMzLCA1NzYsIDU1NiwgMjc4LCAzMzMsIDMzMywgMzY1LCA1NTYsIDgzNCwgODM0LCA4MzQsIDYxMSwgNzIyLCA3MjIsIDcyMiwgNzIyLCA3MjIsIDcyMiwgMTAwMCwgNzIyLCA2NjcsIDY2NywgNjY3LCA2NjcsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNzIyLCA3MjIsIDc3OCwgNzc4LCA3NzgsIDc3OCwgNzc4LCA1ODQsIDc3OCwgNzIyLCA3MjIsIDcyMiwgNzIyLCA2NjcsIDY2NywgNjExLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA4ODksIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDYxMSwgNjExLCA2MTEsIDYxMSwgNjExLCA2MTEsIDYxMSwgNTQ5LCA2MTEsIDYxMSwgNjExLCA2MTEsIDYxMSwgNTU2LCA2MTEsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNzE5LCA3MjIsIDYxMSwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA3NzgsIDYxMSwgNzc4LCA2MTEsIDc3OCwgNjExLCA3NzgsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDc4NSwgNTU2LCA1NTYsIDI3OCwgNzIyLCA1NTYsIDU1NiwgNjExLCAyNzgsIDYxMSwgMjc4LCA2MTEsIDM4NSwgNjExLCA0NzksIDYxMSwgMjc4LCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA3MDgsIDcyMywgNjExLCA3NzgsIDYxMSwgNzc4LCA2MTEsIDc3OCwgNjExLCAxMDAwLCA5NDQsIDcyMiwgMzg5LCA3MjIsIDM4OSwgNzIyLCAzODksIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2MTEsIDMzMywgNjExLCA0NzksIDYxMSwgMzMzLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA5NDQsIDc3OCwgNjY3LCA1NTYsIDY2NywgNjExLCA1MDAsIDYxMSwgNTAwLCA2MTEsIDUwMCwgMjc4LCA1NTYsIDcyMiwgNTU2LCAxMDAwLCA4ODksIDc3OCwgNjExLCA2NjcsIDU1NiwgNjExLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgNDY1LCA3MjIsIDMzMywgODUzLCA5MDYsIDQ3NCwgODI1LCA5MjcsIDgzOCwgMjc4LCA3MjIsIDcyMiwgNjAxLCA3MTksIDY2NywgNjExLCA3MjIsIDc3OCwgMjc4LCA3MjIsIDY2NywgODMzLCA3MjIsIDY0NCwgNzc4LCA3MjIsIDY2NywgNjAwLCA2MTEsIDY2NywgODIxLCA2NjcsIDgwOSwgODAyLCAyNzgsIDY2NywgNjE1LCA0NTEsIDYxMSwgMjc4LCA1ODIsIDYxNSwgNjEwLCA1NTYsIDYwNiwgNDc1LCA0NjAsIDYxMSwgNTQxLCAyNzgsIDU1OCwgNTU2LCA2MTIsIDU1NiwgNDQ1LCA2MTEsIDc2NiwgNjE5LCA1MjAsIDY4NCwgNDQ2LCA1ODIsIDcxNSwgNTc2LCA3NTMsIDg0NSwgMjc4LCA1ODIsIDYxMSwgNTgyLCA4NDUsIDY2NywgNjY5LCA4ODUsIDU2NywgNzExLCA2NjcsIDI3OCwgMjc2LCA1NTYsIDEwOTQsIDEwNjIsIDg3NSwgNjEwLCA3MjIsIDYyMiwgNzE5LCA3MjIsIDcxOSwgNzIyLCA1NjcsIDcxMiwgNjY3LCA5MDQsIDYyNiwgNzE5LCA3MTksIDYxMCwgNzAyLCA4MzMsIDcyMiwgNzc4LCA3MTksIDY2NywgNzIyLCA2MTEsIDYyMiwgODU0LCA2NjcsIDczMCwgNzAzLCAxMDA1LCAxMDE5LCA4NzAsIDk3OSwgNzE5LCA3MTEsIDEwMzEsIDcxOSwgNTU2LCA2MTgsIDYxNSwgNDE3LCA2MzUsIDU1NiwgNzA5LCA0OTcsIDYxNSwgNjE1LCA1MDAsIDYzNSwgNzQwLCA2MDQsIDYxMSwgNjA0LCA2MTEsIDU1NiwgNDkwLCA1NTYsIDg3NSwgNTU2LCA2MTUsIDU4MSwgODMzLCA4NDQsIDcyOSwgODU0LCA2MTUsIDU1MiwgODU0LCA1ODMsIDU1NiwgNTU2LCA2MTEsIDQxNywgNTUyLCA1NTYsIDI3OCwgMjgxLCAyNzgsIDk2OSwgOTA2LCA2MTEsIDUwMCwgNjE1LCA1NTYsIDYwNCwgNzc4LCA2MTEsIDQ4NywgNDQ3LCA5NDQsIDc3OCwgOTQ0LCA3NzgsIDk0NCwgNzc4LCA2NjcsIDU1NiwgMzMzLCAzMzMsIDU1NiwgMTAwMCwgMTAwMCwgNTUyLCAyNzgsIDI3OCwgMjc4LCAyNzgsIDUwMCwgNTAwLCA1MDAsIDU1NiwgNTU2LCAzNTAsIDEwMDAsIDEwMDAsIDI0MCwgNDc5LCAzMzMsIDMzMywgNjA0LCAzMzMsIDE2NywgMzk2LCA1NTYsIDU1NiwgMTA5NCwgNTU2LCA4ODUsIDQ4OSwgMTExNSwgMTAwMCwgNzY4LCA2MDAsIDgzNCwgODM0LCA4MzQsIDgzNCwgMTAwMCwgNTAwLCAxMDAwLCA1MDAsIDEwMDAsIDUwMCwgNTAwLCA0OTQsIDYxMiwgODIzLCA3MTMsIDU4NCwgNTQ5LCA3MTMsIDk3OSwgNzIyLCAyNzQsIDU0OSwgNTQ5LCA1ODMsIDU0OSwgNTQ5LCA2MDQsIDU4NCwgNjA0LCA2MDQsIDcwOCwgNjI1LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MjksIDYwNCwgNjA0LCAzNTQsIDM1NCwgMTAwMCwgOTkwLCA5OTAsIDk5MCwgOTkwLCA0OTQsIDYwNCwgNjA0LCA2MDQsIDYwNCwgMzU0LCAxMDIxLCAxMDUyLCA5MTcsIDc1MCwgNzUwLCA1MzEsIDY1NiwgNTk0LCA1MTAsIDUwMCwgNzUwLCA3NTAsIDYxMSwgNjExLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMjIyLCAyMjIsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzXTsKY29uc3QgTGliZXJhdGlvblNhbnNCb2xkTWFwcGluZyA9IFstMSwgLTEsIC0xLCAzMiwgMzMsIDM0LCAzNSwgMzYsIDM3LCAzOCwgMzksIDQwLCA0MSwgNDIsIDQzLCA0NCwgNDUsIDQ2LCA0NywgNDgsIDQ5LCA1MCwgNTEsIDUyLCA1MywgNTQsIDU1LCA1NiwgNTcsIDU4LCA1OSwgNjAsIDYxLCA2MiwgNjMsIDY0LCA2NSwgNjYsIDY3LCA2OCwgNjksIDcwLCA3MSwgNzIsIDczLCA3NCwgNzUsIDc2LCA3NywgNzgsIDc5LCA4MCwgODEsIDgyLCA4MywgODQsIDg1LCA4NiwgODcsIDg4LCA4OSwgOTAsIDkxLCA5MiwgOTMsIDk0LCA5NSwgOTYsIDk3LCA5OCwgOTksIDEwMCwgMTAxLCAxMDIsIDEwMywgMTA0LCAxMDUsIDEwNiwgMTA3LCAxMDgsIDEwOSwgMTEwLCAxMTEsIDExMiwgMTEzLCAxMTQsIDExNSwgMTE2LCAxMTcsIDExOCwgMTE5LCAxMjAsIDEyMSwgMTIyLCAxMjMsIDEyNCwgMTI1LCAxMjYsIDE2MSwgMTYyLCAxNjMsIDE2NCwgMTY1LCAxNjYsIDE2NywgMTY4LCAxNjksIDE3MCwgMTcxLCAxNzIsIDE3NCwgMTc1LCAxNzYsIDE3NywgMTc4LCAxNzksIDE4MCwgMTgxLCAxODIsIDE4MywgMTg0LCAxODUsIDE4NiwgMTg3LCAxODgsIDE4OSwgMTkwLCAxOTEsIDE5MiwgMTkzLCAxOTQsIDE5NSwgMTk2LCAxOTcsIDE5OCwgMTk5LCAyMDAsIDIwMSwgMjAyLCAyMDMsIDIwNCwgMjA1LCAyMDYsIDIwNywgMjA4LCAyMDksIDIxMCwgMjExLCAyMTIsIDIxMywgMjE0LCAyMTUsIDIxNiwgMjE3LCAyMTgsIDIxOSwgMjIwLCAyMjEsIDIyMiwgMjIzLCAyMjQsIDIyNSwgMjI2LCAyMjcsIDIyOCwgMjI5LCAyMzAsIDIzMSwgMjMyLCAyMzMsIDIzNCwgMjM1LCAyMzYsIDIzNywgMjM4LCAyMzksIDI0MCwgMjQxLCAyNDIsIDI0MywgMjQ0LCAyNDUsIDI0NiwgMjQ3LCAyNDgsIDI0OSwgMjUwLCAyNTEsIDI1MiwgMjUzLCAyNTQsIDI1NSwgMjU2LCAyNTcsIDI1OCwgMjU5LCAyNjAsIDI2MSwgMjYyLCAyNjMsIDI2NCwgMjY1LCAyNjYsIDI2NywgMjY4LCAyNjksIDI3MCwgMjcxLCAyNzIsIDI3MywgMjc0LCAyNzUsIDI3NiwgMjc3LCAyNzgsIDI3OSwgMjgwLCAyODEsIDI4MiwgMjgzLCAyODQsIDI4NSwgMjg2LCAyODcsIDI4OCwgMjg5LCAyOTAsIDI5MSwgMjkyLCAyOTMsIDI5NCwgMjk1LCAyOTYsIDI5NywgMjk4LCAyOTksIDMwMCwgMzAxLCAzMDIsIDMwMywgMzA0LCAzMDUsIDMwNiwgMzA3LCAzMDgsIDMwOSwgMzEwLCAzMTEsIDMxMiwgMzEzLCAzMTQsIDMxNSwgMzE2LCAzMTcsIDMxOCwgMzE5LCAzMjAsIDMyMSwgMzIyLCAzMjMsIDMyNCwgMzI1LCAzMjYsIDMyNywgMzI4LCAzMjksIDMzMCwgMzMxLCAzMzIsIDMzMywgMzM0LCAzMzUsIDMzNiwgMzM3LCAzMzgsIDMzOSwgMzQwLCAzNDEsIDM0MiwgMzQzLCAzNDQsIDM0NSwgMzQ2LCAzNDcsIDM0OCwgMzQ5LCAzNTAsIDM1MSwgMzUyLCAzNTMsIDM1NCwgMzU1LCAzNTYsIDM1NywgMzU4LCAzNTksIDM2MCwgMzYxLCAzNjIsIDM2MywgMzY0LCAzNjUsIDM2NiwgMzY3LCAzNjgsIDM2OSwgMzcwLCAzNzEsIDM3MiwgMzczLCAzNzQsIDM3NSwgMzc2LCAzNzcsIDM3OCwgMzc5LCAzODAsIDM4MSwgMzgyLCAzODMsIDQwMiwgNTA2LCA1MDcsIDUwOCwgNTA5LCA1MTAsIDUxMSwgNTM2LCA1MzcsIDUzOCwgNTM5LCA3MTAsIDcxMSwgNzEzLCA3MjgsIDcyOSwgNzMwLCA3MzEsIDczMiwgNzMzLCA5MDAsIDkwMSwgOTAyLCA5MDMsIDkwNCwgOTA1LCA5MDYsIDkwOCwgOTEwLCA5MTEsIDkxMiwgOTEzLCA5MTQsIDkxNSwgOTE2LCA5MTcsIDkxOCwgOTE5LCA5MjAsIDkyMSwgOTIyLCA5MjMsIDkyNCwgOTI1LCA5MjYsIDkyNywgOTI4LCA5MjksIDkzMSwgOTMyLCA5MzMsIDkzNCwgOTM1LCA5MzYsIDkzNywgOTM4LCA5MzksIDk0MCwgOTQxLCA5NDIsIDk0MywgOTQ0LCA5NDUsIDk0NiwgOTQ3LCA5NDgsIDk0OSwgOTUwLCA5NTEsIDk1MiwgOTUzLCA5NTQsIDk1NSwgOTU2LCA5NTcsIDk1OCwgOTU5LCA5NjAsIDk2MSwgOTYyLCA5NjMsIDk2NCwgOTY1LCA5NjYsIDk2NywgOTY4LCA5NjksIDk3MCwgOTcxLCA5NzIsIDk3MywgOTc0LCAxMDI0LCAxMDI1LCAxMDI2LCAxMDI3LCAxMDI4LCAxMDI5LCAxMDMwLCAxMDMxLCAxMDMyLCAxMDMzLCAxMDM0LCAxMDM1LCAxMDM2LCAxMDM3LCAxMDM4LCAxMDM5LCAxMDQwLCAxMDQxLCAxMDQyLCAxMDQzLCAxMDQ0LCAxMDQ1LCAxMDQ2LCAxMDQ3LCAxMDQ4LCAxMDQ5LCAxMDUwLCAxMDUxLCAxMDUyLCAxMDUzLCAxMDU0LCAxMDU1LCAxMDU2LCAxMDU3LCAxMDU4LCAxMDU5LCAxMDYwLCAxMDYxLCAxMDYyLCAxMDYzLCAxMDY0LCAxMDY1LCAxMDY2LCAxMDY3LCAxMDY4LCAxMDY5LCAxMDcwLCAxMDcxLCAxMDcyLCAxMDczLCAxMDc0LCAxMDc1LCAxMDc2LCAxMDc3LCAxMDc4LCAxMDc5LCAxMDgwLCAxMDgxLCAxMDgyLCAxMDgzLCAxMDg0LCAxMDg1LCAxMDg2LCAxMDg3LCAxMDg4LCAxMDg5LCAxMDkwLCAxMDkxLCAxMDkyLCAxMDkzLCAxMDk0LCAxMDk1LCAxMDk2LCAxMDk3LCAxMDk4LCAxMDk5LCAxMTAwLCAxMTAxLCAxMTAyLCAxMTAzLCAxMTA0LCAxMTA1LCAxMTA2LCAxMTA3LCAxMTA4LCAxMTA5LCAxMTEwLCAxMTExLCAxMTEyLCAxMTEzLCAxMTE0LCAxMTE1LCAxMTE2LCAxMTE3LCAxMTE4LCAxMTE5LCAxMTM4LCAxMTM5LCAxMTY4LCAxMTY5LCA3ODA4LCA3ODA5LCA3ODEwLCA3ODExLCA3ODEyLCA3ODEzLCA3OTIyLCA3OTIzLCA4MjA4LCA4MjA5LCA4MjExLCA4MjEyLCA4MjEzLCA4MjE1LCA4MjE2LCA4MjE3LCA4MjE4LCA4MjE5LCA4MjIwLCA4MjIxLCA4MjIyLCA4MjI0LCA4MjI1LCA4MjI2LCA4MjMwLCA4MjQwLCA4MjQyLCA4MjQzLCA4MjQ5LCA4MjUwLCA4MjUyLCA4MjU0LCA4MjYwLCA4MzE5LCA4MzU1LCA4MzU2LCA4MzU5LCA4MzY0LCA4NDUzLCA4NDY3LCA4NDcwLCA4NDgyLCA4NDg2LCA4NDk0LCA4NTM5LCA4NTQwLCA4NTQxLCA4NTQyLCA4NTkyLCA4NTkzLCA4NTk0LCA4NTk1LCA4NTk2LCA4NTk3LCA4NjE2LCA4NzA2LCA4NzEwLCA4NzE5LCA4NzIxLCA4NzIyLCA4NzMwLCA4NzM0LCA4NzM1LCA4NzQ1LCA4NzQ3LCA4Nzc2LCA4ODAwLCA4ODAxLCA4ODA0LCA4ODA1LCA4OTYyLCA4OTc2LCA4OTkyLCA4OTkzLCA5NDcyLCA5NDc0LCA5NDg0LCA5NDg4LCA5NDkyLCA5NDk2LCA5NTAwLCA5NTA4LCA5NTE2LCA5NTI0LCA5NTMyLCA5NTUyLCA5NTUzLCA5NTU0LCA5NTU1LCA5NTU2LCA5NTU3LCA5NTU4LCA5NTU5LCA5NTYwLCA5NTYxLCA5NTYyLCA5NTYzLCA5NTY0LCA5NTY1LCA5NTY2LCA5NTY3LCA5NTY4LCA5NTY5LCA5NTcwLCA5NTcxLCA5NTcyLCA5NTczLCA5NTc0LCA5NTc1LCA5NTc2LCA5NTc3LCA5NTc4LCA5NTc5LCA5NTgwLCA5NjAwLCA5NjA0LCA5NjA4LCA5NjEyLCA5NjE2LCA5NjE3LCA5NjE4LCA5NjE5LCA5NjMyLCA5NjMzLCA5NjQyLCA5NjQzLCA5NjQ0LCA5NjUwLCA5NjU4LCA5NjYwLCA5NjY4LCA5Njc0LCA5Njc1LCA5Njc5LCA5Njg4LCA5Njg5LCA5NzAyLCA5Nzg2LCA5Nzg3LCA5Nzg4LCA5NzkyLCA5Nzk0LCA5ODI0LCA5ODI3LCA5ODI5LCA5ODMwLCA5ODM0LCA5ODM1LCA5ODM2LCA2MTQ0MSwgNjE0NDIsIDYxNDQ1LCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTFdOwpjb25zdCBMaWJlcmF0aW9uU2Fuc0JvbGRJdGFsaWNXaWR0aHMgPSBbMzY1LCAwLCAzMzMsIDI3OCwgMzMzLCA0NzQsIDU1NiwgNTU2LCA4ODksIDcyMiwgMjM4LCAzMzMsIDMzMywgMzg5LCA1ODQsIDI3OCwgMzMzLCAyNzgsIDI3OCwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCAzMzMsIDMzMywgNTg0LCA1ODQsIDU4NCwgNjExLCA5NzUsIDcyMiwgNzIyLCA3MjIsIDcyMiwgNjY3LCA2MTEsIDc3OCwgNzIyLCAyNzgsIDU1NiwgNzIyLCA2MTEsIDgzMywgNzIyLCA3NzgsIDY2NywgNzc4LCA3MjIsIDY2NywgNjExLCA3MjIsIDY2NywgOTQ0LCA2NjcsIDY2NywgNjExLCAzMzMsIDI3OCwgMzMzLCA1ODQsIDU1NiwgMzMzLCA1NTYsIDYxMSwgNTU2LCA2MTEsIDU1NiwgMzMzLCA2MTEsIDYxMSwgMjc4LCAyNzgsIDU1NiwgMjc4LCA4ODksIDYxMSwgNjExLCA2MTEsIDYxMSwgMzg5LCA1NTYsIDMzMywgNjExLCA1NTYsIDc3OCwgNTU2LCA1NTYsIDUwMCwgMzg5LCAyODAsIDM4OSwgNTg0LCAzMzMsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMjgwLCA1NTYsIDMzMywgNzM3LCAzNzAsIDU1NiwgNTg0LCA3MzcsIDU1MiwgNDAwLCA1NDksIDMzMywgMzMzLCAzMzMsIDU3NiwgNTU2LCAyNzgsIDMzMywgMzMzLCAzNjUsIDU1NiwgODM0LCA4MzQsIDgzNCwgNjExLCA3MjIsIDcyMiwgNzIyLCA3MjIsIDcyMiwgNzIyLCAxMDAwLCA3MjIsIDY2NywgNjY3LCA2NjcsIDY2NywgMjc4LCAyNzgsIDI3OCwgMjc4LCA3MjIsIDcyMiwgNzc4LCA3NzgsIDc3OCwgNzc4LCA3NzgsIDU4NCwgNzc4LCA3MjIsIDcyMiwgNzIyLCA3MjIsIDY2NywgNjY3LCA2MTEsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDg4OSwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNjExLCA2MTEsIDYxMSwgNjExLCA2MTEsIDYxMSwgNjExLCA1NDksIDYxMSwgNjExLCA2MTEsIDYxMSwgNjExLCA1NTYsIDYxMSwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA3NDAsIDcyMiwgNjExLCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDc3OCwgNjExLCA3NzgsIDYxMSwgNzc4LCA2MTEsIDc3OCwgNjExLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNzgyLCA1NTYsIDU1NiwgMjc4LCA3MjIsIDU1NiwgNTU2LCA2MTEsIDI3OCwgNjExLCAyNzgsIDYxMSwgMzk2LCA2MTEsIDQ3OSwgNjExLCAyNzgsIDcyMiwgNjExLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcwOCwgNzIzLCA2MTEsIDc3OCwgNjExLCA3NzgsIDYxMSwgNzc4LCA2MTEsIDEwMDAsIDk0NCwgNzIyLCAzODksIDcyMiwgMzg5LCA3MjIsIDM4OSwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDYxMSwgMzMzLCA2MTEsIDQ3OSwgNjExLCAzMzMsIDcyMiwgNjExLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDk0NCwgNzc4LCA2NjcsIDU1NiwgNjY3LCA2MTEsIDUwMCwgNjExLCA1MDAsIDYxMSwgNTAwLCAyNzgsIDU1NiwgNzIyLCA1NTYsIDEwMDAsIDg4OSwgNzc4LCA2MTEsIDY2NywgNTU2LCA2MTEsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDcyMiwgMzMzLCA4NTQsIDkwNiwgNDczLCA4NDQsIDkzMCwgODQ3LCAyNzgsIDcyMiwgNzIyLCA2MTAsIDY3MSwgNjY3LCA2MTEsIDcyMiwgNzc4LCAyNzgsIDcyMiwgNjY3LCA4MzMsIDcyMiwgNjU3LCA3NzgsIDcxOCwgNjY3LCA1OTAsIDYxMSwgNjY3LCA4MjIsIDY2NywgODI5LCA3ODEsIDI3OCwgNjY3LCA2MjAsIDQ3OSwgNjExLCAyNzgsIDU5MSwgNjIwLCA2MjEsIDU1NiwgNjEwLCA0NzksIDQ5MiwgNjExLCA1NTgsIDI3OCwgNTY2LCA1NTYsIDYwMywgNTU2LCA0NTAsIDYxMSwgNzEyLCA2MDUsIDUzMiwgNjY0LCA0MDksIDU5MSwgNzA0LCA1NzgsIDc3MywgODM0LCAyNzgsIDU5MSwgNjExLCA1OTEsIDgzNCwgNjY3LCA2NjcsIDg4NiwgNjE0LCA3MTksIDY2NywgMjc4LCAyNzgsIDU1NiwgMTA5NCwgMTA0MiwgODU0LCA2MjIsIDcxOSwgNjc3LCA3MTksIDcyMiwgNzA4LCA3MjIsIDYxNCwgNzIyLCA2NjcsIDkyNywgNjQzLCA3MTksIDcxOSwgNjE1LCA2ODcsIDgzMywgNzIyLCA3NzgsIDcxOSwgNjY3LCA3MjIsIDYxMSwgNjc3LCA3ODEsIDY2NywgNzI5LCA3MDgsIDk3OSwgOTg5LCA4NTQsIDEwMDAsIDcwOCwgNzE5LCAxMDQyLCA3MjksIDU1NiwgNjE5LCA2MDQsIDUzNCwgNjE4LCA1NTYsIDczNiwgNTEwLCA2MTEsIDYxMSwgNTA3LCA2MjIsIDc0MCwgNjA0LCA2MTEsIDYxMSwgNjExLCA1NTYsIDg4OSwgNTU2LCA4ODUsIDU1NiwgNjQ2LCA1ODMsIDg4OSwgOTM1LCA3MDcsIDg1NCwgNTk0LCA1NTIsIDg2NSwgNTg5LCA1NTYsIDU1NiwgNjExLCA0NjksIDU2MywgNTU2LCAyNzgsIDI3OCwgMjc4LCA5NjksIDkwNiwgNjExLCA1MDcsIDYxOSwgNTU2LCA2MTEsIDc3OCwgNjExLCA1NzUsIDQ2NywgOTQ0LCA3NzgsIDk0NCwgNzc4LCA5NDQsIDc3OCwgNjY3LCA1NTYsIDMzMywgMzMzLCA1NTYsIDEwMDAsIDEwMDAsIDU1MiwgMjc4LCAyNzgsIDI3OCwgMjc4LCA1MDAsIDUwMCwgNTAwLCA1NTYsIDU1NiwgMzUwLCAxMDAwLCAxMDAwLCAyNDAsIDQ3OSwgMzMzLCAzMzMsIDYwNCwgMzMzLCAxNjcsIDM5NiwgNTU2LCA1NTYsIDExMDQsIDU1NiwgODg1LCA1MTYsIDExNDYsIDEwMDAsIDc2OCwgNjAwLCA4MzQsIDgzNCwgODM0LCA4MzQsIDk5OSwgNTAwLCAxMDAwLCA1MDAsIDEwMDAsIDUwMCwgNTAwLCA0OTQsIDYxMiwgODIzLCA3MTMsIDU4NCwgNTQ5LCA3MTMsIDk3OSwgNzIyLCAyNzQsIDU0OSwgNTQ5LCA1ODMsIDU0OSwgNTQ5LCA2MDQsIDU4NCwgNjA0LCA2MDQsIDcwOCwgNjI1LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MjksIDYwNCwgNjA0LCAzNTQsIDM1NCwgMTAwMCwgOTkwLCA5OTAsIDk5MCwgOTkwLCA0OTQsIDYwNCwgNjA0LCA2MDQsIDYwNCwgMzU0LCAxMDIxLCAxMDUyLCA5MTcsIDc1MCwgNzUwLCA1MzEsIDY1NiwgNTk0LCA1MTAsIDUwMCwgNzUwLCA3NTAsIDYxMSwgNjExLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMjIyLCAyMjIsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzXTsKY29uc3QgTGliZXJhdGlvblNhbnNCb2xkSXRhbGljTWFwcGluZyA9IFstMSwgLTEsIC0xLCAzMiwgMzMsIDM0LCAzNSwgMzYsIDM3LCAzOCwgMzksIDQwLCA0MSwgNDIsIDQzLCA0NCwgNDUsIDQ2LCA0NywgNDgsIDQ5LCA1MCwgNTEsIDUyLCA1MywgNTQsIDU1LCA1NiwgNTcsIDU4LCA1OSwgNjAsIDYxLCA2MiwgNjMsIDY0LCA2NSwgNjYsIDY3LCA2OCwgNjksIDcwLCA3MSwgNzIsIDczLCA3NCwgNzUsIDc2LCA3NywgNzgsIDc5LCA4MCwgODEsIDgyLCA4MywgODQsIDg1LCA4NiwgODcsIDg4LCA4OSwgOTAsIDkxLCA5MiwgOTMsIDk0LCA5NSwgOTYsIDk3LCA5OCwgOTksIDEwMCwgMTAxLCAxMDIsIDEwMywgMTA0LCAxMDUsIDEwNiwgMTA3LCAxMDgsIDEwOSwgMTEwLCAxMTEsIDExMiwgMTEzLCAxMTQsIDExNSwgMTE2LCAxMTcsIDExOCwgMTE5LCAxMjAsIDEyMSwgMTIyLCAxMjMsIDEyNCwgMTI1LCAxMjYsIDE2MSwgMTYyLCAxNjMsIDE2NCwgMTY1LCAxNjYsIDE2NywgMTY4LCAxNjksIDE3MCwgMTcxLCAxNzIsIDE3NCwgMTc1LCAxNzYsIDE3NywgMTc4LCAxNzksIDE4MCwgMTgxLCAxODIsIDE4MywgMTg0LCAxODUsIDE4NiwgMTg3LCAxODgsIDE4OSwgMTkwLCAxOTEsIDE5MiwgMTkzLCAxOTQsIDE5NSwgMTk2LCAxOTcsIDE5OCwgMTk5LCAyMDAsIDIwMSwgMjAyLCAyMDMsIDIwNCwgMjA1LCAyMDYsIDIwNywgMjA4LCAyMDksIDIxMCwgMjExLCAyMTIsIDIxMywgMjE0LCAyMTUsIDIxNiwgMjE3LCAyMTgsIDIxOSwgMjIwLCAyMjEsIDIyMiwgMjIzLCAyMjQsIDIyNSwgMjI2LCAyMjcsIDIyOCwgMjI5LCAyMzAsIDIzMSwgMjMyLCAyMzMsIDIzNCwgMjM1LCAyMzYsIDIzNywgMjM4LCAyMzksIDI0MCwgMjQxLCAyNDIsIDI0MywgMjQ0LCAyNDUsIDI0NiwgMjQ3LCAyNDgsIDI0OSwgMjUwLCAyNTEsIDI1MiwgMjUzLCAyNTQsIDI1NSwgMjU2LCAyNTcsIDI1OCwgMjU5LCAyNjAsIDI2MSwgMjYyLCAyNjMsIDI2NCwgMjY1LCAyNjYsIDI2NywgMjY4LCAyNjksIDI3MCwgMjcxLCAyNzIsIDI3MywgMjc0LCAyNzUsIDI3NiwgMjc3LCAyNzgsIDI3OSwgMjgwLCAyODEsIDI4MiwgMjgzLCAyODQsIDI4NSwgMjg2LCAyODcsIDI4OCwgMjg5LCAyOTAsIDI5MSwgMjkyLCAyOTMsIDI5NCwgMjk1LCAyOTYsIDI5NywgMjk4LCAyOTksIDMwMCwgMzAxLCAzMDIsIDMwMywgMzA0LCAzMDUsIDMwNiwgMzA3LCAzMDgsIDMwOSwgMzEwLCAzMTEsIDMxMiwgMzEzLCAzMTQsIDMxNSwgMzE2LCAzMTcsIDMxOCwgMzE5LCAzMjAsIDMyMSwgMzIyLCAzMjMsIDMyNCwgMzI1LCAzMjYsIDMyNywgMzI4LCAzMjksIDMzMCwgMzMxLCAzMzIsIDMzMywgMzM0LCAzMzUsIDMzNiwgMzM3LCAzMzgsIDMzOSwgMzQwLCAzNDEsIDM0MiwgMzQzLCAzNDQsIDM0NSwgMzQ2LCAzNDcsIDM0OCwgMzQ5LCAzNTAsIDM1MSwgMzUyLCAzNTMsIDM1NCwgMzU1LCAzNTYsIDM1NywgMzU4LCAzNTksIDM2MCwgMzYxLCAzNjIsIDM2MywgMzY0LCAzNjUsIDM2NiwgMzY3LCAzNjgsIDM2OSwgMzcwLCAzNzEsIDM3MiwgMzczLCAzNzQsIDM3NSwgMzc2LCAzNzcsIDM3OCwgMzc5LCAzODAsIDM4MSwgMzgyLCAzODMsIDQwMiwgNTA2LCA1MDcsIDUwOCwgNTA5LCA1MTAsIDUxMSwgNTM2LCA1MzcsIDUzOCwgNTM5LCA3MTAsIDcxMSwgNzEzLCA3MjgsIDcyOSwgNzMwLCA3MzEsIDczMiwgNzMzLCA5MDAsIDkwMSwgOTAyLCA5MDMsIDkwNCwgOTA1LCA5MDYsIDkwOCwgOTEwLCA5MTEsIDkxMiwgOTEzLCA5MTQsIDkxNSwgOTE2LCA5MTcsIDkxOCwgOTE5LCA5MjAsIDkyMSwgOTIyLCA5MjMsIDkyNCwgOTI1LCA5MjYsIDkyNywgOTI4LCA5MjksIDkzMSwgOTMyLCA5MzMsIDkzNCwgOTM1LCA5MzYsIDkzNywgOTM4LCA5MzksIDk0MCwgOTQxLCA5NDIsIDk0MywgOTQ0LCA5NDUsIDk0NiwgOTQ3LCA5NDgsIDk0OSwgOTUwLCA5NTEsIDk1MiwgOTUzLCA5NTQsIDk1NSwgOTU2LCA5NTcsIDk1OCwgOTU5LCA5NjAsIDk2MSwgOTYyLCA5NjMsIDk2NCwgOTY1LCA5NjYsIDk2NywgOTY4LCA5NjksIDk3MCwgOTcxLCA5NzIsIDk3MywgOTc0LCAxMDI0LCAxMDI1LCAxMDI2LCAxMDI3LCAxMDI4LCAxMDI5LCAxMDMwLCAxMDMxLCAxMDMyLCAxMDMzLCAxMDM0LCAxMDM1LCAxMDM2LCAxMDM3LCAxMDM4LCAxMDM5LCAxMDQwLCAxMDQxLCAxMDQyLCAxMDQzLCAxMDQ0LCAxMDQ1LCAxMDQ2LCAxMDQ3LCAxMDQ4LCAxMDQ5LCAxMDUwLCAxMDUxLCAxMDUyLCAxMDUzLCAxMDU0LCAxMDU1LCAxMDU2LCAxMDU3LCAxMDU4LCAxMDU5LCAxMDYwLCAxMDYxLCAxMDYyLCAxMDYzLCAxMDY0LCAxMDY1LCAxMDY2LCAxMDY3LCAxMDY4LCAxMDY5LCAxMDcwLCAxMDcxLCAxMDcyLCAxMDczLCAxMDc0LCAxMDc1LCAxMDc2LCAxMDc3LCAxMDc4LCAxMDc5LCAxMDgwLCAxMDgxLCAxMDgyLCAxMDgzLCAxMDg0LCAxMDg1LCAxMDg2LCAxMDg3LCAxMDg4LCAxMDg5LCAxMDkwLCAxMDkxLCAxMDkyLCAxMDkzLCAxMDk0LCAxMDk1LCAxMDk2LCAxMDk3LCAxMDk4LCAxMDk5LCAxMTAwLCAxMTAxLCAxMTAyLCAxMTAzLCAxMTA0LCAxMTA1LCAxMTA2LCAxMTA3LCAxMTA4LCAxMTA5LCAxMTEwLCAxMTExLCAxMTEyLCAxMTEzLCAxMTE0LCAxMTE1LCAxMTE2LCAxMTE3LCAxMTE4LCAxMTE5LCAxMTM4LCAxMTM5LCAxMTY4LCAxMTY5LCA3ODA4LCA3ODA5LCA3ODEwLCA3ODExLCA3ODEyLCA3ODEzLCA3OTIyLCA3OTIzLCA4MjA4LCA4MjA5LCA4MjExLCA4MjEyLCA4MjEzLCA4MjE1LCA4MjE2LCA4MjE3LCA4MjE4LCA4MjE5LCA4MjIwLCA4MjIxLCA4MjIyLCA4MjI0LCA4MjI1LCA4MjI2LCA4MjMwLCA4MjQwLCA4MjQyLCA4MjQzLCA4MjQ5LCA4MjUwLCA4MjUyLCA4MjU0LCA4MjYwLCA4MzE5LCA4MzU1LCA4MzU2LCA4MzU5LCA4MzY0LCA4NDUzLCA4NDY3LCA4NDcwLCA4NDgyLCA4NDg2LCA4NDk0LCA4NTM5LCA4NTQwLCA4NTQxLCA4NTQyLCA4NTkyLCA4NTkzLCA4NTk0LCA4NTk1LCA4NTk2LCA4NTk3LCA4NjE2LCA4NzA2LCA4NzEwLCA4NzE5LCA4NzIxLCA4NzIyLCA4NzMwLCA4NzM0LCA4NzM1LCA4NzQ1LCA4NzQ3LCA4Nzc2LCA4ODAwLCA4ODAxLCA4ODA0LCA4ODA1LCA4OTYyLCA4OTc2LCA4OTkyLCA4OTkzLCA5NDcyLCA5NDc0LCA5NDg0LCA5NDg4LCA5NDkyLCA5NDk2LCA5NTAwLCA5NTA4LCA5NTE2LCA5NTI0LCA5NTMyLCA5NTUyLCA5NTUzLCA5NTU0LCA5NTU1LCA5NTU2LCA5NTU3LCA5NTU4LCA5NTU5LCA5NTYwLCA5NTYxLCA5NTYyLCA5NTYzLCA5NTY0LCA5NTY1LCA5NTY2LCA5NTY3LCA5NTY4LCA5NTY5LCA5NTcwLCA5NTcxLCA5NTcyLCA5NTczLCA5NTc0LCA5NTc1LCA5NTc2LCA5NTc3LCA5NTc4LCA5NTc5LCA5NTgwLCA5NjAwLCA5NjA0LCA5NjA4LCA5NjEyLCA5NjE2LCA5NjE3LCA5NjE4LCA5NjE5LCA5NjMyLCA5NjMzLCA5NjQyLCA5NjQzLCA5NjQ0LCA5NjUwLCA5NjU4LCA5NjYwLCA5NjY4LCA5Njc0LCA5Njc1LCA5Njc5LCA5Njg4LCA5Njg5LCA5NzAyLCA5Nzg2LCA5Nzg3LCA5Nzg4LCA5NzkyLCA5Nzk0LCA5ODI0LCA5ODI3LCA5ODI5LCA5ODMwLCA5ODM0LCA5ODM1LCA5ODM2LCA2MTQ0MSwgNjE0NDIsIDYxNDQ1LCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTFdOwpjb25zdCBMaWJlcmF0aW9uU2Fuc0l0YWxpY1dpZHRocyA9IFszNjUsIDAsIDMzMywgMjc4LCAyNzgsIDM1NSwgNTU2LCA1NTYsIDg4OSwgNjY3LCAxOTEsIDMzMywgMzMzLCAzODksIDU4NCwgMjc4LCAzMzMsIDI3OCwgMjc4LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDI3OCwgMjc4LCA1ODQsIDU4NCwgNTg0LCA1NTYsIDEwMTUsIDY2NywgNjY3LCA3MjIsIDcyMiwgNjY3LCA2MTEsIDc3OCwgNzIyLCAyNzgsIDUwMCwgNjY3LCA1NTYsIDgzMywgNzIyLCA3NzgsIDY2NywgNzc4LCA3MjIsIDY2NywgNjExLCA3MjIsIDY2NywgOTQ0LCA2NjcsIDY2NywgNjExLCAyNzgsIDI3OCwgMjc4LCA0NjksIDU1NiwgMzMzLCA1NTYsIDU1NiwgNTAwLCA1NTYsIDU1NiwgMjc4LCA1NTYsIDU1NiwgMjIyLCAyMjIsIDUwMCwgMjIyLCA4MzMsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMzMzLCA1MDAsIDI3OCwgNTU2LCA1MDAsIDcyMiwgNTAwLCA1MDAsIDUwMCwgMzM0LCAyNjAsIDMzNCwgNTg0LCAzMzMsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMjYwLCA1NTYsIDMzMywgNzM3LCAzNzAsIDU1NiwgNTg0LCA3MzcsIDU1MiwgNDAwLCA1NDksIDMzMywgMzMzLCAzMzMsIDU3NiwgNTM3LCAyNzgsIDMzMywgMzMzLCAzNjUsIDU1NiwgODM0LCA4MzQsIDgzNCwgNjExLCA2NjcsIDY2NywgNjY3LCA2NjcsIDY2NywgNjY3LCAxMDAwLCA3MjIsIDY2NywgNjY3LCA2NjcsIDY2NywgMjc4LCAyNzgsIDI3OCwgMjc4LCA3MjIsIDcyMiwgNzc4LCA3NzgsIDc3OCwgNzc4LCA3NzgsIDU4NCwgNzc4LCA3MjIsIDcyMiwgNzIyLCA3MjIsIDY2NywgNjY3LCA2MTEsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDg4OSwgNTAwLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NDksIDYxMSwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1MDAsIDU1NiwgNTAwLCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA3MjIsIDUwMCwgNzIyLCA1MDAsIDcyMiwgNTAwLCA3MjIsIDUwMCwgNzIyLCA2MjUsIDcyMiwgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDc3OCwgNTU2LCA3NzgsIDU1NiwgNzc4LCA1NTYsIDc3OCwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjIyLCAyNzgsIDI3OCwgNzMzLCA0NDQsIDUwMCwgMjIyLCA2NjcsIDUwMCwgNTAwLCA1NTYsIDIyMiwgNTU2LCAyMjIsIDU1NiwgMjgxLCA1NTYsIDQwMCwgNTU2LCAyMjIsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDYxNSwgNzIzLCA1NTYsIDc3OCwgNTU2LCA3NzgsIDU1NiwgNzc4LCA1NTYsIDEwMDAsIDk0NCwgNzIyLCAzMzMsIDcyMiwgMzMzLCA3MjIsIDMzMywgNjY3LCA1MDAsIDY2NywgNTAwLCA2NjcsIDUwMCwgNjY3LCA1MDAsIDYxMSwgMjc4LCA2MTEsIDM1NCwgNjExLCAyNzgsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDk0NCwgNzIyLCA2NjcsIDUwMCwgNjY3LCA2MTEsIDUwMCwgNjExLCA1MDAsIDYxMSwgNTAwLCAyMjIsIDU1NiwgNjY3LCA1NTYsIDEwMDAsIDg4OSwgNzc4LCA2MTEsIDY2NywgNTAwLCA2MTEsIDI3OCwgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDY2NywgMjc4LCA3ODksIDg0NiwgMzg5LCA3OTQsIDg2NSwgNzc1LCAyMjIsIDY2NywgNjY3LCA1NzAsIDY3MSwgNjY3LCA2MTEsIDcyMiwgNzc4LCAyNzgsIDY2NywgNjY3LCA4MzMsIDcyMiwgNjQ4LCA3NzgsIDcyNSwgNjY3LCA2MDAsIDYxMSwgNjY3LCA4MzcsIDY2NywgODMxLCA3NjEsIDI3OCwgNjY3LCA1NzAsIDQzOSwgNTU1LCAyMjIsIDU1MCwgNTcwLCA1NzEsIDUwMCwgNTU2LCA0MzksIDQ2MywgNTU1LCA1NDIsIDIyMiwgNTAwLCA0OTIsIDU0OCwgNTAwLCA0NDcsIDU1NiwgNjcwLCA1NzMsIDQ4NiwgNjAzLCAzNzQsIDU1MCwgNjUyLCA1NDYsIDcyOCwgNzc5LCAyMjIsIDU1MCwgNTU2LCA1NTAsIDc3OSwgNjY3LCA2NjcsIDg0MywgNTQ0LCA3MDgsIDY2NywgMjc4LCAyNzgsIDUwMCwgMTA2NiwgOTgyLCA4NDQsIDU4OSwgNzE1LCA2MzksIDcyNCwgNjY3LCA2NTEsIDY2NywgNTQ0LCA3MDQsIDY2NywgOTE3LCA2MTQsIDcxNSwgNzE1LCA1ODksIDY4NiwgODMzLCA3MjIsIDc3OCwgNzI1LCA2NjcsIDcyMiwgNjExLCA2MzksIDc5NSwgNjY3LCA3MjcsIDY3MywgOTIwLCA5MjMsIDgwNSwgODg2LCA2NTEsIDY5NCwgMTAyMiwgNjgyLCA1NTYsIDU2MiwgNTIyLCA0OTMsIDU1MywgNTU2LCA2ODgsIDQ2NSwgNTU2LCA1NTYsIDQ3MiwgNTY0LCA2ODYsIDU1MCwgNTU2LCA1NTYsIDU1NiwgNTAwLCA4MzMsIDUwMCwgODM1LCA1MDAsIDU3MiwgNTE4LCA4MzAsIDg1MSwgNjIxLCA3MzYsIDUyNiwgNDkyLCA3NTIsIDUzNCwgNTU2LCA1NTYsIDU1NiwgMzc4LCA0OTYsIDUwMCwgMjIyLCAyMjIsIDIyMiwgOTEwLCA4MjgsIDU1NiwgNDcyLCA1NjUsIDUwMCwgNTU2LCA3NzgsIDU1NiwgNDkyLCAzMzksIDk0NCwgNzIyLCA5NDQsIDcyMiwgOTQ0LCA3MjIsIDY2NywgNTAwLCAzMzMsIDMzMywgNTU2LCAxMDAwLCAxMDAwLCA1NTIsIDIyMiwgMjIyLCAyMjIsIDIyMiwgMzMzLCAzMzMsIDMzMywgNTU2LCA1NTYsIDM1MCwgMTAwMCwgMTAwMCwgMTg4LCAzNTQsIDMzMywgMzMzLCA1MDAsIDMzMywgMTY3LCAzNjUsIDU1NiwgNTU2LCAxMDk0LCA1NTYsIDg4NSwgMzIzLCAxMDgzLCAxMDAwLCA3NjgsIDYwMCwgODM0LCA4MzQsIDgzNCwgODM0LCAxMDAwLCA1MDAsIDk5OCwgNTAwLCAxMDAwLCA1MDAsIDUwMCwgNDk0LCA2MTIsIDgyMywgNzEzLCA1ODQsIDU0OSwgNzEzLCA5NzksIDcxOSwgMjc0LCA1NDksIDU0OSwgNTg0LCA1NDksIDU0OSwgNjA0LCA1ODQsIDYwNCwgNjA0LCA3MDgsIDYyNSwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzI5LCA2MDQsIDYwNCwgMzU0LCAzNTQsIDEwMDAsIDk5MCwgOTkwLCA5OTAsIDk5MCwgNDk0LCA2MDQsIDYwNCwgNjA0LCA2MDQsIDM1NCwgMTAyMSwgMTA1MiwgOTE3LCA3NTAsIDc1MCwgNTMxLCA2NTYsIDU5NCwgNTEwLCA1MDAsIDc1MCwgNzUwLCA1MDAsIDUwMCwgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDIyMiwgMjIyLCAyOTQsIDI5NCwgMzI0LCAzMjQsIDMxNiwgMzI4LCAzOTgsIDI4NV07CmNvbnN0IExpYmVyYXRpb25TYW5zSXRhbGljTWFwcGluZyA9IFstMSwgLTEsIC0xLCAzMiwgMzMsIDM0LCAzNSwgMzYsIDM3LCAzOCwgMzksIDQwLCA0MSwgNDIsIDQzLCA0NCwgNDUsIDQ2LCA0NywgNDgsIDQ5LCA1MCwgNTEsIDUyLCA1MywgNTQsIDU1LCA1NiwgNTcsIDU4LCA1OSwgNjAsIDYxLCA2MiwgNjMsIDY0LCA2NSwgNjYsIDY3LCA2OCwgNjksIDcwLCA3MSwgNzIsIDczLCA3NCwgNzUsIDc2LCA3NywgNzgsIDc5LCA4MCwgODEsIDgyLCA4MywgODQsIDg1LCA4NiwgODcsIDg4LCA4OSwgOTAsIDkxLCA5MiwgOTMsIDk0LCA5NSwgOTYsIDk3LCA5OCwgOTksIDEwMCwgMTAxLCAxMDIsIDEwMywgMTA0LCAxMDUsIDEwNiwgMTA3LCAxMDgsIDEwOSwgMTEwLCAxMTEsIDExMiwgMTEzLCAxMTQsIDExNSwgMTE2LCAxMTcsIDExOCwgMTE5LCAxMjAsIDEyMSwgMTIyLCAxMjMsIDEyNCwgMTI1LCAxMjYsIDE2MSwgMTYyLCAxNjMsIDE2NCwgMTY1LCAxNjYsIDE2NywgMTY4LCAxNjksIDE3MCwgMTcxLCAxNzIsIDE3NCwgMTc1LCAxNzYsIDE3NywgMTc4LCAxNzksIDE4MCwgMTgxLCAxODIsIDE4MywgMTg0LCAxODUsIDE4NiwgMTg3LCAxODgsIDE4OSwgMTkwLCAxOTEsIDE5MiwgMTkzLCAxOTQsIDE5NSwgMTk2LCAxOTcsIDE5OCwgMTk5LCAyMDAsIDIwMSwgMjAyLCAyMDMsIDIwNCwgMjA1LCAyMDYsIDIwNywgMjA4LCAyMDksIDIxMCwgMjExLCAyMTIsIDIxMywgMjE0LCAyMTUsIDIxNiwgMjE3LCAyMTgsIDIxOSwgMjIwLCAyMjEsIDIyMiwgMjIzLCAyMjQsIDIyNSwgMjI2LCAyMjcsIDIyOCwgMjI5LCAyMzAsIDIzMSwgMjMyLCAyMzMsIDIzNCwgMjM1LCAyMzYsIDIzNywgMjM4LCAyMzksIDI0MCwgMjQxLCAyNDIsIDI0MywgMjQ0LCAyNDUsIDI0NiwgMjQ3LCAyNDgsIDI0OSwgMjUwLCAyNTEsIDI1MiwgMjUzLCAyNTQsIDI1NSwgMjU2LCAyNTcsIDI1OCwgMjU5LCAyNjAsIDI2MSwgMjYyLCAyNjMsIDI2NCwgMjY1LCAyNjYsIDI2NywgMjY4LCAyNjksIDI3MCwgMjcxLCAyNzIsIDI3MywgMjc0LCAyNzUsIDI3NiwgMjc3LCAyNzgsIDI3OSwgMjgwLCAyODEsIDI4MiwgMjgzLCAyODQsIDI4NSwgMjg2LCAyODcsIDI4OCwgMjg5LCAyOTAsIDI5MSwgMjkyLCAyOTMsIDI5NCwgMjk1LCAyOTYsIDI5NywgMjk4LCAyOTksIDMwMCwgMzAxLCAzMDIsIDMwMywgMzA0LCAzMDUsIDMwNiwgMzA3LCAzMDgsIDMwOSwgMzEwLCAzMTEsIDMxMiwgMzEzLCAzMTQsIDMxNSwgMzE2LCAzMTcsIDMxOCwgMzE5LCAzMjAsIDMyMSwgMzIyLCAzMjMsIDMyNCwgMzI1LCAzMjYsIDMyNywgMzI4LCAzMjksIDMzMCwgMzMxLCAzMzIsIDMzMywgMzM0LCAzMzUsIDMzNiwgMzM3LCAzMzgsIDMzOSwgMzQwLCAzNDEsIDM0MiwgMzQzLCAzNDQsIDM0NSwgMzQ2LCAzNDcsIDM0OCwgMzQ5LCAzNTAsIDM1MSwgMzUyLCAzNTMsIDM1NCwgMzU1LCAzNTYsIDM1NywgMzU4LCAzNTksIDM2MCwgMzYxLCAzNjIsIDM2MywgMzY0LCAzNjUsIDM2NiwgMzY3LCAzNjgsIDM2OSwgMzcwLCAzNzEsIDM3MiwgMzczLCAzNzQsIDM3NSwgMzc2LCAzNzcsIDM3OCwgMzc5LCAzODAsIDM4MSwgMzgyLCAzODMsIDQwMiwgNTA2LCA1MDcsIDUwOCwgNTA5LCA1MTAsIDUxMSwgNTM2LCA1MzcsIDUzOCwgNTM5LCA3MTAsIDcxMSwgNzEzLCA3MjgsIDcyOSwgNzMwLCA3MzEsIDczMiwgNzMzLCA5MDAsIDkwMSwgOTAyLCA5MDMsIDkwNCwgOTA1LCA5MDYsIDkwOCwgOTEwLCA5MTEsIDkxMiwgOTEzLCA5MTQsIDkxNSwgOTE2LCA5MTcsIDkxOCwgOTE5LCA5MjAsIDkyMSwgOTIyLCA5MjMsIDkyNCwgOTI1LCA5MjYsIDkyNywgOTI4LCA5MjksIDkzMSwgOTMyLCA5MzMsIDkzNCwgOTM1LCA5MzYsIDkzNywgOTM4LCA5MzksIDk0MCwgOTQxLCA5NDIsIDk0MywgOTQ0LCA5NDUsIDk0NiwgOTQ3LCA5NDgsIDk0OSwgOTUwLCA5NTEsIDk1MiwgOTUzLCA5NTQsIDk1NSwgOTU2LCA5NTcsIDk1OCwgOTU5LCA5NjAsIDk2MSwgOTYyLCA5NjMsIDk2NCwgOTY1LCA5NjYsIDk2NywgOTY4LCA5NjksIDk3MCwgOTcxLCA5NzIsIDk3MywgOTc0LCAxMDI0LCAxMDI1LCAxMDI2LCAxMDI3LCAxMDI4LCAxMDI5LCAxMDMwLCAxMDMxLCAxMDMyLCAxMDMzLCAxMDM0LCAxMDM1LCAxMDM2LCAxMDM3LCAxMDM4LCAxMDM5LCAxMDQwLCAxMDQxLCAxMDQyLCAxMDQzLCAxMDQ0LCAxMDQ1LCAxMDQ2LCAxMDQ3LCAxMDQ4LCAxMDQ5LCAxMDUwLCAxMDUxLCAxMDUyLCAxMDUzLCAxMDU0LCAxMDU1LCAxMDU2LCAxMDU3LCAxMDU4LCAxMDU5LCAxMDYwLCAxMDYxLCAxMDYyLCAxMDYzLCAxMDY0LCAxMDY1LCAxMDY2LCAxMDY3LCAxMDY4LCAxMDY5LCAxMDcwLCAxMDcxLCAxMDcyLCAxMDczLCAxMDc0LCAxMDc1LCAxMDc2LCAxMDc3LCAxMDc4LCAxMDc5LCAxMDgwLCAxMDgxLCAxMDgyLCAxMDgzLCAxMDg0LCAxMDg1LCAxMDg2LCAxMDg3LCAxMDg4LCAxMDg5LCAxMDkwLCAxMDkxLCAxMDkyLCAxMDkzLCAxMDk0LCAxMDk1LCAxMDk2LCAxMDk3LCAxMDk4LCAxMDk5LCAxMTAwLCAxMTAxLCAxMTAyLCAxMTAzLCAxMTA0LCAxMTA1LCAxMTA2LCAxMTA3LCAxMTA4LCAxMTA5LCAxMTEwLCAxMTExLCAxMTEyLCAxMTEzLCAxMTE0LCAxMTE1LCAxMTE2LCAxMTE3LCAxMTE4LCAxMTE5LCAxMTM4LCAxMTM5LCAxMTY4LCAxMTY5LCA3ODA4LCA3ODA5LCA3ODEwLCA3ODExLCA3ODEyLCA3ODEzLCA3OTIyLCA3OTIzLCA4MjA4LCA4MjA5LCA4MjExLCA4MjEyLCA4MjEzLCA4MjE1LCA4MjE2LCA4MjE3LCA4MjE4LCA4MjE5LCA4MjIwLCA4MjIxLCA4MjIyLCA4MjI0LCA4MjI1LCA4MjI2LCA4MjMwLCA4MjQwLCA4MjQyLCA4MjQzLCA4MjQ5LCA4MjUwLCA4MjUyLCA4MjU0LCA4MjYwLCA4MzE5LCA4MzU1LCA4MzU2LCA4MzU5LCA4MzY0LCA4NDUzLCA4NDY3LCA4NDcwLCA4NDgyLCA4NDg2LCA4NDk0LCA4NTM5LCA4NTQwLCA4NTQxLCA4NTQyLCA4NTkyLCA4NTkzLCA4NTk0LCA4NTk1LCA4NTk2LCA4NTk3LCA4NjE2LCA4NzA2LCA4NzEwLCA4NzE5LCA4NzIxLCA4NzIyLCA4NzMwLCA4NzM0LCA4NzM1LCA4NzQ1LCA4NzQ3LCA4Nzc2LCA4ODAwLCA4ODAxLCA4ODA0LCA4ODA1LCA4OTYyLCA4OTc2LCA4OTkyLCA4OTkzLCA5NDcyLCA5NDc0LCA5NDg0LCA5NDg4LCA5NDkyLCA5NDk2LCA5NTAwLCA5NTA4LCA5NTE2LCA5NTI0LCA5NTMyLCA5NTUyLCA5NTUzLCA5NTU0LCA5NTU1LCA5NTU2LCA5NTU3LCA5NTU4LCA5NTU5LCA5NTYwLCA5NTYxLCA5NTYyLCA5NTYzLCA5NTY0LCA5NTY1LCA5NTY2LCA5NTY3LCA5NTY4LCA5NTY5LCA5NTcwLCA5NTcxLCA5NTcyLCA5NTczLCA5NTc0LCA5NTc1LCA5NTc2LCA5NTc3LCA5NTc4LCA5NTc5LCA5NTgwLCA5NjAwLCA5NjA0LCA5NjA4LCA5NjEyLCA5NjE2LCA5NjE3LCA5NjE4LCA5NjE5LCA5NjMyLCA5NjMzLCA5NjQyLCA5NjQzLCA5NjQ0LCA5NjUwLCA5NjU4LCA5NjYwLCA5NjY4LCA5Njc0LCA5Njc1LCA5Njc5LCA5Njg4LCA5Njg5LCA5NzAyLCA5Nzg2LCA5Nzg3LCA5Nzg4LCA5NzkyLCA5Nzk0LCA5ODI0LCA5ODI3LCA5ODI5LCA5ODMwLCA5ODM0LCA5ODM1LCA5ODM2LCA2MTQ0MSwgNjE0NDIsIDYxNDQ1LCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTFdOwpjb25zdCBMaWJlcmF0aW9uU2Fuc1JlZ3VsYXJXaWR0aHMgPSBbMzY1LCAwLCAzMzMsIDI3OCwgMjc4LCAzNTUsIDU1NiwgNTU2LCA4ODksIDY2NywgMTkxLCAzMzMsIDMzMywgMzg5LCA1ODQsIDI3OCwgMzMzLCAyNzgsIDI3OCwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCAyNzgsIDI3OCwgNTg0LCA1ODQsIDU4NCwgNTU2LCAxMDE1LCA2NjcsIDY2NywgNzIyLCA3MjIsIDY2NywgNjExLCA3NzgsIDcyMiwgMjc4LCA1MDAsIDY2NywgNTU2LCA4MzMsIDcyMiwgNzc4LCA2NjcsIDc3OCwgNzIyLCA2NjcsIDYxMSwgNzIyLCA2NjcsIDk0NCwgNjY3LCA2NjcsIDYxMSwgMjc4LCAyNzgsIDI3OCwgNDY5LCA1NTYsIDMzMywgNTU2LCA1NTYsIDUwMCwgNTU2LCA1NTYsIDI3OCwgNTU2LCA1NTYsIDIyMiwgMjIyLCA1MDAsIDIyMiwgODMzLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDMzMywgNTAwLCAyNzgsIDU1NiwgNTAwLCA3MjIsIDUwMCwgNTAwLCA1MDAsIDMzNCwgMjYwLCAzMzQsIDU4NCwgMzMzLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDI2MCwgNTU2LCAzMzMsIDczNywgMzcwLCA1NTYsIDU4NCwgNzM3LCA1NTIsIDQwMCwgNTQ5LCAzMzMsIDMzMywgMzMzLCA1NzYsIDUzNywgMjc4LCAzMzMsIDMzMywgMzY1LCA1NTYsIDgzNCwgODM0LCA4MzQsIDYxMSwgNjY3LCA2NjcsIDY2NywgNjY3LCA2NjcsIDY2NywgMTAwMCwgNzIyLCA2NjcsIDY2NywgNjY3LCA2NjcsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNzIyLCA3MjIsIDc3OCwgNzc4LCA3NzgsIDc3OCwgNzc4LCA1ODQsIDc3OCwgNzIyLCA3MjIsIDcyMiwgNzIyLCA2NjcsIDY2NywgNjExLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA4ODksIDUwMCwgNTU2LCA1NTYsIDU1NiwgNTU2LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTQ5LCA2MTEsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTAwLCA1NTYsIDUwMCwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNzIyLCA1MDAsIDcyMiwgNTAwLCA3MjIsIDUwMCwgNzIyLCA1MDAsIDcyMiwgNjE1LCA3MjIsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA3NzgsIDU1NiwgNzc4LCA1NTYsIDc3OCwgNTU2LCA3NzgsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDIyMiwgMjc4LCAyNzgsIDczNSwgNDQ0LCA1MDAsIDIyMiwgNjY3LCA1MDAsIDUwMCwgNTU2LCAyMjIsIDU1NiwgMjIyLCA1NTYsIDI5MiwgNTU2LCAzMzQsIDU1NiwgMjIyLCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA2MDQsIDcyMywgNTU2LCA3NzgsIDU1NiwgNzc4LCA1NTYsIDc3OCwgNTU2LCAxMDAwLCA5NDQsIDcyMiwgMzMzLCA3MjIsIDMzMywgNzIyLCAzMzMsIDY2NywgNTAwLCA2NjcsIDUwMCwgNjY3LCA1MDAsIDY2NywgNTAwLCA2MTEsIDI3OCwgNjExLCAzNzUsIDYxMSwgMjc4LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA5NDQsIDcyMiwgNjY3LCA1MDAsIDY2NywgNjExLCA1MDAsIDYxMSwgNTAwLCA2MTEsIDUwMCwgMjIyLCA1NTYsIDY2NywgNTU2LCAxMDAwLCA4ODksIDc3OCwgNjExLCA2NjcsIDUwMCwgNjExLCAyNzgsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCA2NjcsIDI3OCwgNzg0LCA4MzgsIDM4NCwgNzc0LCA4NTUsIDc1MiwgMjIyLCA2NjcsIDY2NywgNTUxLCA2NjgsIDY2NywgNjExLCA3MjIsIDc3OCwgMjc4LCA2NjcsIDY2OCwgODMzLCA3MjIsIDY1MCwgNzc4LCA3MjIsIDY2NywgNjE4LCA2MTEsIDY2NywgNzk4LCA2NjcsIDgzNSwgNzQ4LCAyNzgsIDY2NywgNTc4LCA0NDYsIDU1NiwgMjIyLCA1NDcsIDU3OCwgNTc1LCA1MDAsIDU1NywgNDQ2LCA0NDEsIDU1NiwgNTU2LCAyMjIsIDUwMCwgNTAwLCA1NzYsIDUwMCwgNDQ4LCA1NTYsIDY5MCwgNTY5LCA0ODIsIDYxNywgMzk1LCA1NDcsIDY0OCwgNTI1LCA3MTMsIDc4MSwgMjIyLCA1NDcsIDU1NiwgNTQ3LCA3ODEsIDY2NywgNjY3LCA4NjUsIDU0MiwgNzE5LCA2NjcsIDI3OCwgMjc4LCA1MDAsIDEwNTcsIDEwMTAsIDg1NCwgNTgzLCA3MjIsIDYzNSwgNzE5LCA2NjcsIDY1NiwgNjY3LCA1NDIsIDY3NywgNjY3LCA5MjMsIDYwNCwgNzE5LCA3MTksIDU4MywgNjU2LCA4MzMsIDcyMiwgNzc4LCA3MTksIDY2NywgNzIyLCA2MTEsIDYzNSwgNzYwLCA2NjcsIDc0MCwgNjY3LCA5MTcsIDkzOCwgNzkyLCA4ODUsIDY1NiwgNzE5LCAxMDEwLCA3MjIsIDU1NiwgNTczLCA1MzEsIDM2NSwgNTgzLCA1NTYsIDY2OSwgNDU4LCA1NTksIDU1OSwgNDM4LCA1ODMsIDY4OCwgNTUyLCA1NTYsIDU0MiwgNTU2LCA1MDAsIDQ1OCwgNTAwLCA4MjMsIDUwMCwgNTczLCA1MjEsIDgwMiwgODIzLCA2MjUsIDcxOSwgNTIxLCA1MTAsIDc1MCwgNTQyLCA1NTYsIDU1NiwgNTU2LCAzNjUsIDUxMCwgNTAwLCAyMjIsIDI3OCwgMjIyLCA5MDYsIDgxMiwgNTU2LCA0MzgsIDU1OSwgNTAwLCA1NTIsIDc3OCwgNTU2LCA0ODksIDQxMSwgOTQ0LCA3MjIsIDk0NCwgNzIyLCA5NDQsIDcyMiwgNjY3LCA1MDAsIDMzMywgMzMzLCA1NTYsIDEwMDAsIDEwMDAsIDU1MiwgMjIyLCAyMjIsIDIyMiwgMjIyLCAzMzMsIDMzMywgMzMzLCA1NTYsIDU1NiwgMzUwLCAxMDAwLCAxMDAwLCAxODgsIDM1NCwgMzMzLCAzMzMsIDUwMCwgMzMzLCAxNjcsIDM2NSwgNTU2LCA1NTYsIDEwOTQsIDU1NiwgODg1LCAzMjMsIDEwNzMsIDEwMDAsIDc2OCwgNjAwLCA4MzQsIDgzNCwgODM0LCA4MzQsIDEwMDAsIDUwMCwgMTAwMCwgNTAwLCAxMDAwLCA1MDAsIDUwMCwgNDk0LCA2MTIsIDgyMywgNzEzLCA1ODQsIDU0OSwgNzEzLCA5NzksIDcxOSwgMjc0LCA1NDksIDU0OSwgNTgzLCA1NDksIDU0OSwgNjA0LCA1ODQsIDYwNCwgNjA0LCA3MDgsIDYyNSwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzI5LCA2MDQsIDYwNCwgMzU0LCAzNTQsIDEwMDAsIDk5MCwgOTkwLCA5OTAsIDk5MCwgNDk0LCA2MDQsIDYwNCwgNjA0LCA2MDQsIDM1NCwgMTAyMSwgMTA1MiwgOTE3LCA3NTAsIDc1MCwgNTMxLCA2NTYsIDU5NCwgNTEwLCA1MDAsIDc1MCwgNzUwLCA1MDAsIDUwMCwgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDIyMiwgMjIyLCAyOTQsIDI5NCwgMzI0LCAzMjQsIDMxNiwgMzI4LCAzOTgsIDI4NV07CmNvbnN0IExpYmVyYXRpb25TYW5zUmVndWxhck1hcHBpbmcgPSBbLTEsIC0xLCAtMSwgMzIsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDEsIDQyLCA0MywgNDQsIDQ1LCA0NiwgNDcsIDQ4LCA0OSwgNTAsIDUxLCA1MiwgNTMsIDU0LCA1NSwgNTYsIDU3LCA1OCwgNTksIDYwLCA2MSwgNjIsIDYzLCA2NCwgNjUsIDY2LCA2NywgNjgsIDY5LCA3MCwgNzEsIDcyLCA3MywgNzQsIDc1LCA3NiwgNzcsIDc4LCA3OSwgODAsIDgxLCA4MiwgODMsIDg0LCA4NSwgODYsIDg3LCA4OCwgODksIDkwLCA5MSwgOTIsIDkzLCA5NCwgOTUsIDk2LCA5NywgOTgsIDk5LCAxMDAsIDEwMSwgMTAyLCAxMDMsIDEwNCwgMTA1LCAxMDYsIDEwNywgMTA4LCAxMDksIDExMCwgMTExLCAxMTIsIDExMywgMTE0LCAxMTUsIDExNiwgMTE3LCAxMTgsIDExOSwgMTIwLCAxMjEsIDEyMiwgMTIzLCAxMjQsIDEyNSwgMTI2LCAxNjEsIDE2MiwgMTYzLCAxNjQsIDE2NSwgMTY2LCAxNjcsIDE2OCwgMTY5LCAxNzAsIDE3MSwgMTcyLCAxNzQsIDE3NSwgMTc2LCAxNzcsIDE3OCwgMTc5LCAxODAsIDE4MSwgMTgyLCAxODMsIDE4NCwgMTg1LCAxODYsIDE4NywgMTg4LCAxODksIDE5MCwgMTkxLCAxOTIsIDE5MywgMTk0LCAxOTUsIDE5NiwgMTk3LCAxOTgsIDE5OSwgMjAwLCAyMDEsIDIwMiwgMjAzLCAyMDQsIDIwNSwgMjA2LCAyMDcsIDIwOCwgMjA5LCAyMTAsIDIxMSwgMjEyLCAyMTMsIDIxNCwgMjE1LCAyMTYsIDIxNywgMjE4LCAyMTksIDIyMCwgMjIxLCAyMjIsIDIyMywgMjI0LCAyMjUsIDIyNiwgMjI3LCAyMjgsIDIyOSwgMjMwLCAyMzEsIDIzMiwgMjMzLCAyMzQsIDIzNSwgMjM2LCAyMzcsIDIzOCwgMjM5LCAyNDAsIDI0MSwgMjQyLCAyNDMsIDI0NCwgMjQ1LCAyNDYsIDI0NywgMjQ4LCAyNDksIDI1MCwgMjUxLCAyNTIsIDI1MywgMjU0LCAyNTUsIDI1NiwgMjU3LCAyNTgsIDI1OSwgMjYwLCAyNjEsIDI2MiwgMjYzLCAyNjQsIDI2NSwgMjY2LCAyNjcsIDI2OCwgMjY5LCAyNzAsIDI3MSwgMjcyLCAyNzMsIDI3NCwgMjc1LCAyNzYsIDI3NywgMjc4LCAyNzksIDI4MCwgMjgxLCAyODIsIDI4MywgMjg0LCAyODUsIDI4NiwgMjg3LCAyODgsIDI4OSwgMjkwLCAyOTEsIDI5MiwgMjkzLCAyOTQsIDI5NSwgMjk2LCAyOTcsIDI5OCwgMjk5LCAzMDAsIDMwMSwgMzAyLCAzMDMsIDMwNCwgMzA1LCAzMDYsIDMwNywgMzA4LCAzMDksIDMxMCwgMzExLCAzMTIsIDMxMywgMzE0LCAzMTUsIDMxNiwgMzE3LCAzMTgsIDMxOSwgMzIwLCAzMjEsIDMyMiwgMzIzLCAzMjQsIDMyNSwgMzI2LCAzMjcsIDMyOCwgMzI5LCAzMzAsIDMzMSwgMzMyLCAzMzMsIDMzNCwgMzM1LCAzMzYsIDMzNywgMzM4LCAzMzksIDM0MCwgMzQxLCAzNDIsIDM0MywgMzQ0LCAzNDUsIDM0NiwgMzQ3LCAzNDgsIDM0OSwgMzUwLCAzNTEsIDM1MiwgMzUzLCAzNTQsIDM1NSwgMzU2LCAzNTcsIDM1OCwgMzU5LCAzNjAsIDM2MSwgMzYyLCAzNjMsIDM2NCwgMzY1LCAzNjYsIDM2NywgMzY4LCAzNjksIDM3MCwgMzcxLCAzNzIsIDM3MywgMzc0LCAzNzUsIDM3NiwgMzc3LCAzNzgsIDM3OSwgMzgwLCAzODEsIDM4MiwgMzgzLCA0MDIsIDUwNiwgNTA3LCA1MDgsIDUwOSwgNTEwLCA1MTEsIDUzNiwgNTM3LCA1MzgsIDUzOSwgNzEwLCA3MTEsIDcxMywgNzI4LCA3MjksIDczMCwgNzMxLCA3MzIsIDczMywgOTAwLCA5MDEsIDkwMiwgOTAzLCA5MDQsIDkwNSwgOTA2LCA5MDgsIDkxMCwgOTExLCA5MTIsIDkxMywgOTE0LCA5MTUsIDkxNiwgOTE3LCA5MTgsIDkxOSwgOTIwLCA5MjEsIDkyMiwgOTIzLCA5MjQsIDkyNSwgOTI2LCA5MjcsIDkyOCwgOTI5LCA5MzEsIDkzMiwgOTMzLCA5MzQsIDkzNSwgOTM2LCA5MzcsIDkzOCwgOTM5LCA5NDAsIDk0MSwgOTQyLCA5NDMsIDk0NCwgOTQ1LCA5NDYsIDk0NywgOTQ4LCA5NDksIDk1MCwgOTUxLCA5NTIsIDk1MywgOTU0LCA5NTUsIDk1NiwgOTU3LCA5NTgsIDk1OSwgOTYwLCA5NjEsIDk2MiwgOTYzLCA5NjQsIDk2NSwgOTY2LCA5NjcsIDk2OCwgOTY5LCA5NzAsIDk3MSwgOTcyLCA5NzMsIDk3NCwgMTAyNCwgMTAyNSwgMTAyNiwgMTAyNywgMTAyOCwgMTAyOSwgMTAzMCwgMTAzMSwgMTAzMiwgMTAzMywgMTAzNCwgMTAzNSwgMTAzNiwgMTAzNywgMTAzOCwgMTAzOSwgMTA0MCwgMTA0MSwgMTA0MiwgMTA0MywgMTA0NCwgMTA0NSwgMTA0NiwgMTA0NywgMTA0OCwgMTA0OSwgMTA1MCwgMTA1MSwgMTA1MiwgMTA1MywgMTA1NCwgMTA1NSwgMTA1NiwgMTA1NywgMTA1OCwgMTA1OSwgMTA2MCwgMTA2MSwgMTA2MiwgMTA2MywgMTA2NCwgMTA2NSwgMTA2NiwgMTA2NywgMTA2OCwgMTA2OSwgMTA3MCwgMTA3MSwgMTA3MiwgMTA3MywgMTA3NCwgMTA3NSwgMTA3NiwgMTA3NywgMTA3OCwgMTA3OSwgMTA4MCwgMTA4MSwgMTA4MiwgMTA4MywgMTA4NCwgMTA4NSwgMTA4NiwgMTA4NywgMTA4OCwgMTA4OSwgMTA5MCwgMTA5MSwgMTA5MiwgMTA5MywgMTA5NCwgMTA5NSwgMTA5NiwgMTA5NywgMTA5OCwgMTA5OSwgMTEwMCwgMTEwMSwgMTEwMiwgMTEwMywgMTEwNCwgMTEwNSwgMTEwNiwgMTEwNywgMTEwOCwgMTEwOSwgMTExMCwgMTExMSwgMTExMiwgMTExMywgMTExNCwgMTExNSwgMTExNiwgMTExNywgMTExOCwgMTExOSwgMTEzOCwgMTEzOSwgMTE2OCwgMTE2OSwgNzgwOCwgNzgwOSwgNzgxMCwgNzgxMSwgNzgxMiwgNzgxMywgNzkyMiwgNzkyMywgODIwOCwgODIwOSwgODIxMSwgODIxMiwgODIxMywgODIxNSwgODIxNiwgODIxNywgODIxOCwgODIxOSwgODIyMCwgODIyMSwgODIyMiwgODIyNCwgODIyNSwgODIyNiwgODIzMCwgODI0MCwgODI0MiwgODI0MywgODI0OSwgODI1MCwgODI1MiwgODI1NCwgODI2MCwgODMxOSwgODM1NSwgODM1NiwgODM1OSwgODM2NCwgODQ1MywgODQ2NywgODQ3MCwgODQ4MiwgODQ4NiwgODQ5NCwgODUzOSwgODU0MCwgODU0MSwgODU0MiwgODU5MiwgODU5MywgODU5NCwgODU5NSwgODU5NiwgODU5NywgODYxNiwgODcwNiwgODcxMCwgODcxOSwgODcyMSwgODcyMiwgODczMCwgODczNCwgODczNSwgODc0NSwgODc0NywgODc3NiwgODgwMCwgODgwMSwgODgwNCwgODgwNSwgODk2MiwgODk3NiwgODk5MiwgODk5MywgOTQ3MiwgOTQ3NCwgOTQ4NCwgOTQ4OCwgOTQ5MiwgOTQ5NiwgOTUwMCwgOTUwOCwgOTUxNiwgOTUyNCwgOTUzMiwgOTU1MiwgOTU1MywgOTU1NCwgOTU1NSwgOTU1NiwgOTU1NywgOTU1OCwgOTU1OSwgOTU2MCwgOTU2MSwgOTU2MiwgOTU2MywgOTU2NCwgOTU2NSwgOTU2NiwgOTU2NywgOTU2OCwgOTU2OSwgOTU3MCwgOTU3MSwgOTU3MiwgOTU3MywgOTU3NCwgOTU3NSwgOTU3NiwgOTU3NywgOTU3OCwgOTU3OSwgOTU4MCwgOTYwMCwgOTYwNCwgOTYwOCwgOTYxMiwgOTYxNiwgOTYxNywgOTYxOCwgOTYxOSwgOTYzMiwgOTYzMywgOTY0MiwgOTY0MywgOTY0NCwgOTY1MCwgOTY1OCwgOTY2MCwgOTY2OCwgOTY3NCwgOTY3NSwgOTY3OSwgOTY4OCwgOTY4OSwgOTcwMiwgOTc4NiwgOTc4NywgOTc4OCwgOTc5MiwgOTc5NCwgOTgyNCwgOTgyNywgOTgyOSwgOTgzMCwgOTgzNCwgOTgzNSwgOTgzNiwgNjE0NDEsIDYxNDQyLCA2MTQ0NSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xXTsKCjsvLyAuL3NyYy9jb3JlL215cmlhZHByb19mYWN0b3JzLmpzCmNvbnN0IE15cmlhZFByb0JvbGRGYWN0b3JzID0gWzEuMzY4OTgsIDEsIDEsIDAuNzI3MDYsIDAuODA0NzksIDAuODM3MzQsIDAuOTg4OTQsIDAuOTk3OTMsIDAuOTg5NywgMC45Mzg4NCwgMC44NjIwOSwgMC45NDI5MiwgMC45NDI5MiwgMS4xNjY2MSwgMS4wMjA1OCwgMC45MzU4MiwgMC45NjY5NCwgMC45MzU4MiwgMS4xOTEzNywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC43ODA3NiwgMC43ODA3NiwgMS4wMjA1OCwgMS4wMjA1OCwgMS4wMjA1OCwgMC43Mjg1MSwgMC43ODk2NiwgMC45MDgzOCwgMC44MzYzNywgMC44MjM5MSwgMC45NjM3NiwgMC44MDA2MSwgMC44NjI3NSwgMC44NzY4LCAwLjk1NDA3LCAxLjAyNTgsIDAuNzM5MDEsIDAuODUwMjIsIDAuODM2NTUsIDEuMDE1NiwgMC45NTU0NiwgMC45MjE3OSwgMC44NzEwNywgMC45MjE3OSwgMC44MjExNCwgMC44MDk2LCAwLjg5NzEzLCAwLjk0NDM4LCAwLjk1MzUzLCAwLjk0MDgzLCAwLjkxOTA1LCAwLjkwNDA2LCAwLjk0NDYsIDAuOTQyOTIsIDEuMTg3NzcsIDAuOTQyOTIsIDEuMDIwNTgsIDAuODk5MDMsIDAuOTAwODgsIDAuOTQ5MzgsIDAuOTc4OTgsIDAuODEwOTMsIDAuOTc1NzEsIDAuOTQ5MzgsIDEuMDI0LCAwLjk1NzcsIDAuOTU5MzMsIDAuOTg2MjEsIDEuMDQ3NCwgMC45NzQ1NSwgMC45ODk4MSwgMC45NjcyLCAwLjk1OTMzLCAwLjk0NDYsIDAuOTc4OTgsIDAuOTc0MDcsIDAuOTc2NDYsIDAuNzgwMzYsIDEuMTAyMDgsIDAuOTU0NDIsIDAuOTUyOTgsIDAuOTc1NzksIDAuOTMzMiwgMC45NDAzOSwgMC45MzgsIDAuODA2ODcsIDEuMDExNDksIDAuODA2ODcsIDEuMDIwNTgsIDAuODA0NzksIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDEuMDExNDksIDEuMDA4NzIsIDAuOTAwODgsIDAuOTE4ODIsIDEuMDIxMywgMC44MzYxLCAxLjAyMDU4LCAwLjYyMjk1LCAwLjU0MzI0LCAwLjg5MDIyLCAxLjA4NTk1LCAxLCAxLCAwLjkwMDg4LCAxLCAwLjk3NDU1LCAwLjkzNTgyLCAwLjkwMDg4LCAxLCAxLjA1Njg2LCAwLjgzNjEsIDAuOTk2NDIsIDAuOTk2NDIsIDAuOTk2NDIsIDAuNzI4NTEsIDAuOTA4MzgsIDAuOTA4MzgsIDAuOTA4MzgsIDAuOTA4MzgsIDAuOTA4MzgsIDAuOTA4MzgsIDAuODY4LCAwLjgyMzkxLCAwLjgwMDYxLCAwLjgwMDYxLCAwLjgwMDYxLCAwLjgwMDYxLCAxLjAyNTgsIDEuMDI1OCwgMS4wMjU4LCAxLjAyNTgsIDAuOTc0ODQsIDAuOTU1NDYsIDAuOTIxNzksIDAuOTIxNzksIDAuOTIxNzksIDAuOTIxNzksIDAuOTIxNzksIDEuMDIwNTgsIDAuOTIxNzksIDAuOTQ0MzgsIDAuOTQ0MzgsIDAuOTQ0MzgsIDAuOTQ0MzgsIDAuOTA0MDYsIDAuODY5NTgsIDAuOTgyMjUsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTAzMSwgMC44MTA5MywgMC45NDkzOCwgMC45NDkzOCwgMC45NDkzOCwgMC45NDkzOCwgMC45ODYyMSwgMC45ODYyMSwgMC45ODYyMSwgMC45ODYyMSwgMC45Mzk2OSwgMC45NTkzMywgMC45NDQ2LCAwLjk0NDYsIDAuOTQ0NiwgMC45NDQ2LCAwLjk0NDYsIDEuMDg1OTUsIDAuOTQ0NiwgMC45NTQ0MiwgMC45NTQ0MiwgMC45NTQ0MiwgMC45NTQ0MiwgMC45NDAzOSwgMC45Nzg5OCwgMC45NDAzOSwgMC45MDgzOCwgMC45NDkzOCwgMC45MDgzOCwgMC45NDkzOCwgMC45MDgzOCwgMC45NDkzOCwgMC44MjM5MSwgMC44MTA5MywgMC44MjM5MSwgMC44MTA5MywgMC44MjM5MSwgMC44MTA5MywgMC44MjM5MSwgMC44MTA5MywgMC45NjM3NiwgMC44NDMxMywgMC45NzQ4NCwgMC45NzU3MSwgMC44MDA2MSwgMC45NDkzOCwgMC44MDA2MSwgMC45NDkzOCwgMC44MDA2MSwgMC45NDkzOCwgMC44MDA2MSwgMC45NDkzOCwgMC44MDA2MSwgMC45NDkzOCwgMC44NzY4LCAwLjk1NzcsIDAuODc2OCwgMC45NTc3LCAwLjg3NjgsIDAuOTU3NywgMSwgMSwgMC45NTQwNywgMC45NTkzMywgMC45NzA2OSwgMC45NTkzMywgMS4wMjU4LCAwLjk4NjIxLCAxLjAyNTgsIDAuOTg2MjEsIDEuMDI1OCwgMC45ODYyMSwgMS4wMjU4LCAwLjk4NjIxLCAxLjAyNTgsIDAuOTg2MjEsIDAuODg3LCAxLjAxNTkxLCAwLjczOTAxLCAxLjA0NzQsIDEsIDEsIDAuOTc0NTUsIDAuODM2NTUsIDAuOTg5ODEsIDEsIDEsIDAuODM2NTUsIDAuNzM5NzcsIDAuODM2NTUsIDAuNzM5MDMsIDAuODQ2MzgsIDEuMDMzLCAwLjk1NTQ2LCAwLjk1OTMzLCAxLCAxLCAwLjk1NTQ2LCAwLjk1OTMzLCAwLjgyNzEsIDAuOTU0MTcsIDAuOTU5MzMsIDAuOTIxNzksIDAuOTQ0NiwgMC45MjE3OSwgMC45NDQ2LCAwLjkyMTc5LCAwLjk0NDYsIDAuOTM2LCAwLjkxOTY0LCAwLjgyMTE0LCAwLjk3NjQ2LCAxLCAxLCAwLjgyMTE0LCAwLjk3NjQ2LCAwLjgwOTYsIDAuNzgwMzYsIDAuODA5NiwgMC43ODAzNiwgMSwgMSwgMC44MDk2LCAwLjc4MDM2LCAxLCAxLCAwLjg5NzEzLCAwLjc3NDUyLCAwLjg5NzEzLCAxLjEwMjA4LCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0MDgzLCAwLjk3NTc5LCAwLjkwNDA2LCAwLjk0MDM5LCAwLjkwNDA2LCAwLjk0NDYsIDAuOTM4LCAwLjk0NDYsIDAuOTM4LCAwLjk0NDYsIDAuOTM4LCAxLCAwLjk5NzkzLCAwLjkwODM4LCAwLjk0OTM4LCAwLjg2OCwgMC45MDMxLCAwLjkyMTc5LCAwLjk0NDYsIDEsIDEsIDAuODk3MTMsIDEuMTAyMDgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTA5ODksIDAuOTM1OCwgMC45MTk0NSwgMC44MzE4MSwgMC43NTI2MSwgMC44Nzk5MiwgMC44Mjk3NiwgMC45NjAzNCwgMC44MzY4OSwgMC45NzI2OCwgMS4wMDc4LCAwLjkwODM4LCAwLjgzNjM3LCAwLjgwMTksIDAuOTAxNTcsIDAuODAwNjEsIDAuOTQ0NiwgMC45NTQwNywgMC45MjQzNiwgMS4wMjU4LCAwLjg1MDIyLCAwLjk3MTUzLCAxLjAxNTYsIDAuOTU1NDYsIDAuODkxOTIsIDAuOTIxNzksIDAuOTIzNjEsIDAuODcxMDcsIDAuOTYzMTgsIDAuODk3MTMsIDAuOTM3MDQsIDAuOTU2MzgsIDAuOTE5MDUsIDAuOTE3MDksIDAuOTI3OTYsIDEuMDI1OCwgMC45MzcwNCwgMC45NDgzNiwgMS4wMzczLCAwLjk1OTMzLCAxLjAwNzgsIDAuOTU4NzEsIDAuOTQ4MzYsIDAuOTYxNzQsIDAuOTI2MDEsIDAuOTQ5OCwgMC45ODYwNywgMC45NTc3NiwgMC45NTkzMywgMS4wNTQ1MywgMS4wMDc4LCAwLjk4Mjc1LCAwLjkzMTQsIDAuOTU2MTcsIDAuOTE3MDEsIDEuMDU5OTMsIDAuOTQ0NiwgMC43ODM2NywgMC45NTUzLCAxLCAwLjg2ODMyLCAxLjAxMjgsIDAuOTU4NzEsIDAuOTkzOTQsIDAuODc1NDgsIDAuOTYzNjEsIDAuODY3NzQsIDEuMDA3OCwgMC45NTg3MSwgMC45NDQ2LCAwLjk1ODcxLCAwLjg2Nzc0LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk0MDgzLCAwLjk3NTc5LCAwLjk0MDgzLCAwLjk3NTc5LCAwLjk0MDgzLCAwLjk3NTc5LCAwLjkwNDA2LCAwLjk0MDM5LCAwLjk2Njk0LCAxLCAwLjg5OTAzLCAxLCAxLCAxLCAwLjkzNTgyLCAwLjkzNTgyLCAwLjkzNTgyLCAxLCAwLjkwOCwgMC45MDgsIDAuOTE4LCAwLjk0MjE5LCAwLjk0MjE5LCAwLjk2NTQ0LCAxLCAxLjI4NSwgMSwgMSwgMC44MTA3OSwgMC44MTA3OSwgMSwgMSwgMC43NDg1NCwgMSwgMSwgMSwgMSwgMC45OTc5MywgMSwgMSwgMSwgMC42NSwgMSwgMS4zNjE0NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4xNzE3MywgMSwgMC44MDUzNSwgMC43NjE2OSwgMS4wMjA1OCwgMS4wNzMyLCAxLjA1NDg2LCAxLCAxLCAxLjMwNjkyLCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjE2MTYxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKY29uc3QgTXlyaWFkUHJvQm9sZE1ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yLAogIGxpbmVHYXA6IDAuMgp9Owpjb25zdCBNeXJpYWRQcm9Cb2xkSXRhbGljRmFjdG9ycyA9IFsxLjM2ODk4LCAxLCAxLCAwLjY2MjI3LCAwLjgwNzc5LCAwLjgxNjI1LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjk3NzMzLCAwLjkyMjIyLCAwLjgzMjY2LCAwLjk0MjkyLCAwLjk0MjkyLCAxLjE2MTQ4LCAxLjAyMDU4LCAwLjkzNTgyLCAwLjk2Njk0LCAwLjkzNTgyLCAxLjE3MzM3LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjc4MDc2LCAwLjc4MDc2LCAxLjAyMDU4LCAxLjAyMDU4LCAxLjAyMDU4LCAwLjcxNTQxLCAwLjc2ODEzLCAwLjg1NTc2LCAwLjgwNTkxLCAwLjgwNzI5LCAwLjk0Mjk5LCAwLjc3NTEyLCAwLjgzNjU1LCAwLjg2NTIzLCAwLjkyMjIyLCAwLjk4NjIxLCAwLjcxNzQzLCAwLjgxNjk4LCAwLjc5NzI2LCAwLjk4NTU4LCAwLjkyMjIyLCAwLjkwNjM3LCAwLjgzODA5LCAwLjkwNjM3LCAwLjgwNzI5LCAwLjc2NDYzLCAwLjg2Mjc1LCAwLjkwNjk5LCAwLjkxNjA1LCAwLjkxNTQsIDAuODUzMDgsIDAuODU0NTgsIDAuOTA1MzEsIDAuOTQyOTIsIDEuMjEyOTYsIDAuOTQyOTIsIDEuMDIwNTgsIDAuODk5MDMsIDEuMTg2MTYsIDAuOTk2MTMsIDAuOTE2NzcsIDAuNzgyMTYsIDAuOTE2NzcsIDAuOTAwODMsIDAuOTg3OTYsIDAuOTEzNSwgMC45MjE2OCwgMC45NTM4MSwgMC45ODk4MSwgMC45NTI5OCwgMC45NTM4MSwgMC45MzQ1OSwgMC45MjE2OCwgMC45MTUxMywgMC45MjAwNCwgMC45MTY3NywgMC45NTA3NywgMC43NDgsIDEuMDQ1MDIsIDAuOTE2NzcsIDAuOTIwNjEsIDAuOTQyMzYsIDAuODk1NDQsIDAuODkzNjQsIDAuOSwgMC44MDY4NywgMC44NTc4LCAwLjgwNjg3LCAxLjAyMDU4LCAwLjgwNzc5LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjk3Mjc2LCAwLjg1NzgsIDAuOTk5NzMsIDEuMTg2MTYsIDAuOTEzMzksIDEuMDgwNzQsIDAuODI4OTEsIDEuMDIwNTgsIDAuNTU1MDksIDAuNzE1MjYsIDAuODkwMjIsIDEuMDg1OTUsIDEsIDEsIDEuMTg2MTYsIDEsIDAuOTY3MzYsIDAuOTM1ODIsIDEuMTg2MTYsIDEsIDEuMDQ4NjQsIDAuODI3MTEsIDAuOTkwNDMsIDAuOTkwNDMsIDAuOTkwNDMsIDAuNzE1NDEsIDAuODU1NzYsIDAuODU1NzYsIDAuODU1NzYsIDAuODU1NzYsIDAuODU1NzYsIDAuODU1NzYsIDAuODQ1LCAwLjgwNzI5LCAwLjc3NTEyLCAwLjc3NTEyLCAwLjc3NTEyLCAwLjc3NTEyLCAwLjk4NjIxLCAwLjk4NjIxLCAwLjk4NjIxLCAwLjk4NjIxLCAwLjk1OTYxLCAwLjkyMjIyLCAwLjkwNjM3LCAwLjkwNjM3LCAwLjkwNjM3LCAwLjkwNjM3LCAwLjkwNjM3LCAxLjAyMDU4LCAwLjkwMjUxLCAwLjkwNjk5LCAwLjkwNjk5LCAwLjkwNjk5LCAwLjkwNjk5LCAwLjg1NDU4LCAwLjgzNjU5LCAwLjk0OTUxLCAwLjk5NjEzLCAwLjk5NjEzLCAwLjk5NjEzLCAwLjk5NjEzLCAwLjk5NjEzLCAwLjk5NjEzLCAwLjg1ODExLCAwLjc4MjE2LCAwLjkwMDgzLCAwLjkwMDgzLCAwLjkwMDgzLCAwLjkwMDgzLCAwLjk1MzgxLCAwLjk1MzgxLCAwLjk1MzgxLCAwLjk1MzgxLCAwLjkxMzUsIDAuOTIxNjgsIDAuOTE1MTMsIDAuOTE1MTMsIDAuOTE1MTMsIDAuOTE1MTMsIDAuOTE1MTMsIDEuMDg1OTUsIDAuOTE2NzcsIDAuOTE2NzcsIDAuOTE2NzcsIDAuOTE2NzcsIDAuOTE2NzcsIDAuODkzNjQsIDAuOTIzMzIsIDAuODkzNjQsIDAuODU1NzYsIDAuOTk2MTMsIDAuODU1NzYsIDAuOTk2MTMsIDAuODU1NzYsIDAuOTk2MTMsIDAuODA3MjksIDAuNzgyMTYsIDAuODA3MjksIDAuNzgyMTYsIDAuODA3MjksIDAuNzgyMTYsIDAuODA3MjksIDAuNzgyMTYsIDAuOTQyOTksIDAuNzY3ODMsIDAuOTU5NjEsIDAuOTE2NzcsIDAuNzc1MTIsIDAuOTAwODMsIDAuNzc1MTIsIDAuOTAwODMsIDAuNzc1MTIsIDAuOTAwODMsIDAuNzc1MTIsIDAuOTAwODMsIDAuNzc1MTIsIDAuOTAwODMsIDAuODY1MjMsIDAuOTEzNSwgMC44NjUyMywgMC45MTM1LCAwLjg2NTIzLCAwLjkxMzUsIDEsIDEsIDAuOTIyMjIsIDAuOTIxNjgsIDAuOTIyMjIsIDAuOTIxNjgsIDAuOTg2MjEsIDAuOTUzODEsIDAuOTg2MjEsIDAuOTUzODEsIDAuOTg2MjEsIDAuOTUzODEsIDAuOTg2MjEsIDAuOTUzODEsIDAuOTg2MjEsIDAuOTUzODEsIDAuODYwMzYsIDAuOTcwOTYsIDAuNzE3NDMsIDAuOTg5ODEsIDEsIDEsIDAuOTUyOTgsIDAuNzk3MjYsIDAuOTUzODEsIDEsIDEsIDAuNzk3MjYsIDAuNjg5NCwgMC43OTcyNiwgMC43NDMyMSwgMC44MTY5MSwgMS4wMDA2LCAwLjkyMjIyLCAwLjkyMTY4LCAxLCAxLCAwLjkyMjIyLCAwLjkyMTY4LCAwLjc5NDY0LCAwLjkyMDk4LCAwLjkyMTY4LCAwLjkwNjM3LCAwLjkxNTEzLCAwLjkwNjM3LCAwLjkxNTEzLCAwLjkwNjM3LCAwLjkxNTEzLCAwLjkwOSwgMC44NzUxNCwgMC44MDcyOSwgMC45NTA3NywgMSwgMSwgMC44MDcyOSwgMC45NTA3NywgMC43NjQ2MywgMC43NDgsIDAuNzY0NjMsIDAuNzQ4LCAxLCAxLCAwLjc2NDYzLCAwLjc0OCwgMSwgMSwgMC44NjI3NSwgMC43MjY1MSwgMC44NjI3NSwgMS4wNDUwMiwgMC45MDY5OSwgMC45MTY3NywgMC45MDY5OSwgMC45MTY3NywgMC45MDY5OSwgMC45MTY3NywgMC45MDY5OSwgMC45MTY3NywgMC45MDY5OSwgMC45MTY3NywgMC45MDY5OSwgMC45MTY3NywgMC45MTU0LCAwLjk0MjM2LCAwLjg1NDU4LCAwLjg5MzY0LCAwLjg1NDU4LCAwLjkwNTMxLCAwLjksIDAuOTA1MzEsIDAuOSwgMC45MDUzMSwgMC45LCAxLCAwLjk3Mjc2LCAwLjg1NTc2LCAwLjk5NjEzLCAwLjg0NSwgMC44NTgxMSwgMC45MDI1MSwgMC45MTY3NywgMSwgMSwgMC44NjI3NSwgMS4wNDUwMiwgMS4xODYxNiwgMS4xODYxNiwgMS4xODYxNiwgMS4xODYxNiwgMS4xODYxNiwgMS4xODYxNiwgMS4xODYxNiwgMS4xODYxNiwgMS4xODYxNiwgMS4wMDg5OSwgMS4zMDYyOCwgMC44NTU3NiwgMC44MDE3OCwgMC42Njg2MiwgMC43OTI3LCAwLjY5MzIzLCAwLjg4MTI3LCAwLjcyNDU5LCAwLjg5NzExLCAwLjk1MzgxLCAwLjg1NTc2LCAwLjgwNTkxLCAwLjc4MDUsIDAuOTQ3MjksIDAuNzc1MTIsIDAuOTA1MzEsIDAuOTIyMjIsIDAuOTA2MzcsIDAuOTg2MjEsIDAuODE2OTgsIDAuOTI2NTUsIDAuOTg1NTgsIDAuOTIyMjIsIDAuODUzNTksIDAuOTA2MzcsIDAuOTA5NzYsIDAuODM4MDksIDAuOTQ1MjMsIDAuODYyNzUsIDAuODM1MDksIDAuOTMxNTcsIDAuODUzMDgsIDAuODMzOTIsIDAuOTIzNDYsIDAuOTg2MjEsIDAuODM1MDksIDAuOTI4ODYsIDAuOTEzMjQsIDAuOTIxNjgsIDAuOTUzODEsIDAuOTA2NDYsIDAuOTI4ODYsIDAuOTA1NTcsIDAuODY4NDcsIDAuOTAyNzYsIDAuOTEzMjQsIDAuODY4NDIsIDAuOTIxNjgsIDAuOTk1MzEsIDAuOTUzODEsIDAuOTIyNCwgMC44NTQwOCwgMC45MjY5OSwgMC44Njg0NywgMS4wMDUxLCAwLjkxNTEzLCAwLjgwNDg3LCAwLjkzNDgxLCAxLCAwLjg4MTU5LCAxLjA1MjE0LCAwLjkwNjQ2LCAwLjk3MzU1LCAwLjgxNTM5LCAwLjg5Mzk4LCAwLjg1OTIzLCAwLjk1MzgxLCAwLjkwNjQ2LCAwLjkxNTEzLCAwLjkwNjQ2LCAwLjg1OTIzLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjkxNTQsIDAuOTQyMzYsIDAuOTE1NCwgMC45NDIzNiwgMC45MTU0LCAwLjk0MjM2LCAwLjg1NDU4LCAwLjg5MzY0LCAwLjk2Njk0LCAxLCAwLjg5OTAzLCAxLCAxLCAxLCAwLjkxNzgyLCAwLjkxNzgyLCAwLjkxNzgyLCAxLCAwLjg5NiwgMC44OTYsIDAuODk2LCAwLjkzMzIsIDAuOTMzMiwgMC45NTk3MywgMSwgMS4yNiwgMSwgMSwgMC44MDQ3OSwgMC44MDE3OCwgMSwgMSwgMC44NTYzMywgMSwgMSwgMSwgMSwgMC45NzI3NiwgMSwgMSwgMSwgMC42OTgsIDEsIDEuMzYxNDUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMTQ1NDIsIDEsIDAuNzkxOTksIDAuNzg2OTQsIDEuMDIwNTgsIDEuMDM0OTMsIDEuMDU0ODYsIDEsIDEsIDEuMjMwMjYsIDEuMDg1OTUsIDEuMDg1OTUsIDEsIDEuMDg1OTUsIDEuMDg1OTUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMjAwMDYsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBNeXJpYWRQcm9Cb2xkSXRhbGljTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjIsCiAgbGluZUdhcDogMC4yCn07CmNvbnN0IE15cmlhZFByb0l0YWxpY0ZhY3RvcnMgPSBbMS4zNjg5OCwgMSwgMSwgMC42NTUwNywgMC44NDk0MywgMC44NTYzOSwgMC44ODQ2NSwgMC44ODQ2NSwgMC44NjkzNiwgMC44ODMwNywgMC44Njk0OCwgMC44NTI4MywgMC44NTI4MywgMS4wNjM4MywgMS4wMjA1OCwgMC43NTk0NSwgMC45MjE5LCAwLjc1OTQ1LCAxLjE3MzM3LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjc1OTQ1LCAwLjc1OTQ1LCAxLjAyMDU4LCAxLjAyMDU4LCAxLjAyMDU4LCAwLjY5MDQ2LCAwLjcwOTI2LCAwLjg1MTU4LCAwLjc3ODEyLCAwLjc2ODUyLCAwLjg5NTkxLCAwLjcwNDY2LCAwLjc2MTI1LCAwLjgwMDk0LCAwLjg2ODIyLCAwLjgzODY0LCAwLjcyOCwgMC43NzIxMiwgMC43OTQ3NSwgMC45MzYzNywgMC44NzUxNCwgMC44NTg4LCAwLjc2MDEzLCAwLjg1ODgsIDAuNzI0MjEsIDAuNjk4NjYsIDAuNzc1OTgsIDAuODU5OTEsIDAuODA4MTEsIDAuODc4MzIsIDAuNzgxMTIsIDAuNzc1MTIsIDAuODU2MiwgMS4wMjIyLCAxLjE4NDE3LCAxLjAyMjIsIDEuMjcwMTQsIDAuODk5MDMsIDEuMTUwMTIsIDAuOTM4NTksIDAuOTQzOTksIDAuODQ2LCAwLjk0Mzk5LCAwLjgxNDUzLCAxLjAxODYsIDAuOTQyMTksIDAuOTYwMTcsIDEuMDMwNzUsIDEuMDIxNzUsIDAuOTEyLCAxLjAzMDc1LCAwLjk2OTk4LCAwLjk2MDE3LCAwLjkzODU5LCAwLjk0Mzk5LCAwLjk0Mzk5LCAwLjk1NDkzLCAwLjc0NiwgMS4xMjY1OCwgMC45NDU3OCwgMC45MSwgMC45NzksIDAuODgyLCAwLjg4MiwgMC44MywgMC44NTAzNCwgMC44MzUzNywgMC44NTAzNCwgMS4wMjA1OCwgMC43MDg2OSwgMC44ODQ2NSwgMC44ODQ2NSwgMC44ODQ2NSwgMC44ODQ2NSwgMC44MzUzNywgMC45MDA4MywgMS4xNTAxMiwgMC45MTYxLCAwLjk0NTY1LCAwLjczNTQxLCAxLjAyMDU4LCAwLjUzNjA5LCAwLjY5MzUzLCAwLjc5NTE5LCAxLjA4NTk1LCAxLCAxLCAxLjE1MDEyLCAxLCAwLjkxOTc0LCAwLjc1OTQ1LCAxLjE1MDEyLCAxLCAwLjk0NDYsIDAuNzMzNjEsIDAuOTAwNSwgMC45MDA1LCAwLjkwMDUsIDAuNjI4NjQsIDAuODUxNTgsIDAuODUxNTgsIDAuODUxNTgsIDAuODUxNTgsIDAuODUxNTgsIDAuODUxNTgsIDAuNzczLCAwLjc2ODUyLCAwLjcwNDY2LCAwLjcwNDY2LCAwLjcwNDY2LCAwLjcwNDY2LCAwLjgzODY0LCAwLjgzODY0LCAwLjgzODY0LCAwLjgzODY0LCAwLjkwNTYxLCAwLjg3NTE0LCAwLjg1ODgsIDAuODU4OCwgMC44NTg4LCAwLjg1ODgsIDAuODU4OCwgMS4wMjA1OCwgMC44NTc1MSwgMC44NTk5MSwgMC44NTk5MSwgMC44NTk5MSwgMC44NTk5MSwgMC43NzUxMiwgMC43NjAxMywgMC44ODA3NSwgMC45Mzg1OSwgMC45Mzg1OSwgMC45Mzg1OSwgMC45Mzg1OSwgMC45Mzg1OSwgMC45Mzg1OSwgMC44MDc1LCAwLjg0NiwgMC44MTQ1MywgMC44MTQ1MywgMC44MTQ1MywgMC44MTQ1MywgMC44MjQyNCwgMC44MjQyNCwgMC44MjQyNCwgMC44MjQyNCwgMC45Mjc4LCAwLjk2MDE3LCAwLjkzODU5LCAwLjkzODU5LCAwLjkzODU5LCAwLjkzODU5LCAwLjkzODU5LCAxLjA4NTk1LCAwLjg1NjIsIDAuOTQ1NzgsIDAuOTQ1NzgsIDAuOTQ1NzgsIDAuOTQ1NzgsIDAuODgyLCAwLjk0NTc4LCAwLjg4MiwgMC44NTE1OCwgMC45Mzg1OSwgMC44NTE1OCwgMC45Mzg1OSwgMC44NTE1OCwgMC45Mzg1OSwgMC43Njg1MiwgMC44NDYsIDAuNzY4NTIsIDAuODQ2LCAwLjc2ODUyLCAwLjg0NiwgMC43Njg1MiwgMC44NDYsIDAuODk1OTEsIDAuODU0NCwgMC45MDU2MSwgMC45NDM5OSwgMC43MDQ2NiwgMC44MTQ1MywgMC43MDQ2NiwgMC44MTQ1MywgMC43MDQ2NiwgMC44MTQ1MywgMC43MDQ2NiwgMC44MTQ1MywgMC43MDQ2NiwgMC44MTQ1MywgMC44MDA5NCwgMC45NDIxOSwgMC44MDA5NCwgMC45NDIxOSwgMC44MDA5NCwgMC45NDIxOSwgMSwgMSwgMC44NjgyMiwgMC45NjAxNywgMC44NjgyMiwgMC45NjAxNywgMC44Mzg2NCwgMC44MjQyNCwgMC44Mzg2NCwgMC44MjQyNCwgMC44Mzg2NCwgMC44MjQyNCwgMC44Mzg2NCwgMS4wMzA3NSwgMC44Mzg2NCwgMC44MjQyNCwgMC44MTQwMiwgMS4wMjczOCwgMC43MjgsIDEuMDIxNzUsIDEsIDEsIDAuOTEyLCAwLjc5NDc1LCAxLjAzMDc1LCAxLCAxLCAwLjc5NDc1LCAwLjgzOTExLCAwLjc5NDc1LCAwLjY2MjY2LCAwLjgwNTUzLCAxLjA2Njc2LCAwLjg3NTE0LCAwLjk2MDE3LCAxLCAxLCAwLjg3NTE0LCAwLjk2MDE3LCAwLjg2ODY1LCAwLjg3Mzk2LCAwLjk2MDE3LCAwLjg1ODgsIDAuOTM4NTksIDAuODU4OCwgMC45Mzg1OSwgMC44NTg4LCAwLjkzODU5LCAwLjg2NywgMC44NDc1OSwgMC43MjQyMSwgMC45NTQ5MywgMSwgMSwgMC43MjQyMSwgMC45NTQ5MywgMC42OTg2NiwgMC43NDYsIDAuNjk4NjYsIDAuNzQ2LCAxLCAxLCAwLjY5ODY2LCAwLjc0NiwgMSwgMSwgMC43NzU5OCwgMC44ODQxNywgMC43NzU5OCwgMS4xMjY1OCwgMC44NTk5MSwgMC45NDU3OCwgMC44NTk5MSwgMC45NDU3OCwgMC44NTk5MSwgMC45NDU3OCwgMC44NTk5MSwgMC45NDU3OCwgMC44NTk5MSwgMC45NDU3OCwgMC44NTk5MSwgMC45NDU3OCwgMC44NzgzMiwgMC45NzksIDAuNzc1MTIsIDAuODgyLCAwLjc3NTEyLCAwLjg1NjIsIDAuODMsIDAuODU2MiwgMC44MywgMC44NTYyLCAwLjgzLCAxLCAwLjg4NDY1LCAwLjg1MTU4LCAwLjkzODU5LCAwLjc3MywgMC44MDc1LCAwLjg1NzUxLCAwLjg1NjIsIDEsIDEsIDAuNzc1OTgsIDEuMTI2NTgsIDEuMTUwMTIsIDEuMTUwMTIsIDEuMTUwMTIsIDEuMTUwMTIsIDEuMTUwMTIsIDEuMTUzMTMsIDEuMTUwMTIsIDEuMTUwMTIsIDEuMTUwMTIsIDEuMDgxMDYsIDEuMDM5MDEsIDAuODUxNTgsIDAuNzcwMjUsIDAuNjIyNjQsIDAuNzY0NiwgMC42NTM1MSwgMC44NjAyNiwgMC42OTQ2MSwgMC44OTk0NywgMS4wMzA3NSwgMC44NTE1OCwgMC43NzgxMiwgMC43NjQ0OSwgMC44ODgzNiwgMC43MDQ2NiwgMC44NTYyLCAwLjg2ODIyLCAwLjg1ODgsIDAuODM4NjQsIDAuNzcyMTIsIDAuODUzMDgsIDAuOTM2MzcsIDAuODc1MTQsIDAuODIzNTIsIDAuODU4OCwgMC44NTcwMSwgMC43NjAxMywgMC44OTA1OCwgMC43NzU5OCwgMC44MTU2LCAwLjgyNTY1LCAwLjc4MTEyLCAwLjc3ODk5LCAwLjg5Mzg2LCAwLjgzODY0LCAwLjgxNTYsIDAuOTQ4NiwgMC45MjM4OCwgMC45NjE4NiwgMS4wMzA3NSwgMC45MTEyMywgMC45NDg2LCAwLjkzMjk4LCAwLjg3OCwgMC45Mzk0MiwgMC45MjM4OCwgMC44NDU5NiwgMC45NjE4NiwgMC45NTExOSwgMS4wMzA3NSwgMC45MjIsIDAuODg3ODcsIDAuOTU4MjksIDAuODgsIDAuOTM1NTksIDAuOTM4NTksIDAuNzg4MTUsIDAuOTM3NTgsIDEsIDAuODkyMTcsIDEuMDM3MzcsIDAuOTExMjMsIDAuOTM5NjksIDAuNzc0ODcsIDAuODU3NjksIDAuODY3OTksIDEuMDMwNzUsIDAuOTExMjMsIDAuOTM4NTksIDAuOTExMjMsIDAuODY3OTksIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuODc4MzIsIDAuOTc5LCAwLjg3ODMyLCAwLjk3OSwgMC44NzgzMiwgMC45NzksIDAuNzc1MTIsIDAuODgyLCAwLjkyMTksIDEsIDAuODk5MDMsIDEsIDEsIDEsIDAuODczMjEsIDAuODczMjEsIDAuODczMjEsIDEsIDEuMDI3LCAxLjAyNywgMS4wMjcsIDAuODY4NDcsIDAuODY4NDcsIDAuNzkxMjEsIDEsIDEuMTI0LCAxLCAxLCAwLjczNTcyLCAwLjczNTcyLCAxLCAxLCAwLjg1MDM0LCAxLCAxLCAxLCAxLCAwLjg4NDY1LCAxLCAxLCAxLCAwLjY2OSwgMSwgMS4zNjE0NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wNDgyOCwgMSwgMC43NDk0OCwgMC43NTE4NywgMS4wMjA1OCwgMC45ODM5MSwgMS4wMjExOSwgMSwgMSwgMS4wNjIzMywgMS4wODU5NSwgMS4wODU5NSwgMSwgMS4wODU5NSwgMS4wODU5NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wNTIzMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmNvbnN0IE15cmlhZFByb0l0YWxpY01ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yLAogIGxpbmVHYXA6IDAuMgp9Owpjb25zdCBNeXJpYWRQcm9SZWd1bGFyRmFjdG9ycyA9IFsxLjM2ODk4LCAxLCAxLCAwLjc2MzA1LCAwLjgyNzg0LCAwLjk0OTM1LCAwLjg5MzY0LCAwLjkyMjQxLCAwLjg5MDczLCAwLjkwNzA2LCAwLjk4NDcyLCAwLjg1MjgzLCAwLjg1MjgzLCAxLjA2NjQsIDEuMDIwNTgsIDAuNzQ1MDUsIDAuOTIxOSwgMC43NDUwNSwgMS4yMzQ1NiwgMC45MjI0MSwgMC45MjI0MSwgMC45MjI0MSwgMC45MjI0MSwgMC45MjI0MSwgMC45MjI0MSwgMC45MjI0MSwgMC45MjI0MSwgMC45MjI0MSwgMC45MjI0MSwgMC43NDUwNSwgMC43NDUwNSwgMS4wMjA1OCwgMS4wMjA1OCwgMS4wMjA1OCwgMC43MzAwMiwgMC43MjYwMSwgMC45MTc1NSwgMC44MTI2LCAwLjgwMzE0LCAwLjkyMjIyLCAwLjczNzY0LCAwLjc5NzI2LCAwLjgzMDUxLCAwLjkwMjg0LCAwLjg2MDIzLCAwLjc0LCAwLjgxMjYsIDAuODQ4NjksIDAuOTY1MTgsIDAuOTExMTUsIDAuODg1OCwgMC43OTc2MSwgMC44ODU4LCAwLjc0NDk4LCAwLjczOTE0LCAwLjgxMzYzLCAwLjg5NTkxLCAwLjgzNjU5LCAwLjg5NjMzLCAwLjg1NjA4LCAwLjgxMTEsIDAuOTA1MzEsIDEuMDIyMiwgMS4yMjczNiwgMS4wMjIyLCAxLjI3MDE0LCAwLjg5OTAzLCAwLjkwMDg4LCAwLjg2NjY3LCAxLjAyMzEsIDAuODk2LCAxLjAxNDExLCAwLjkwMDgzLCAxLjA1MDk5LCAxLjAwNTEyLCAwLjk5NzkzLCAxLjA1MzI2LCAxLjA5Mzc3LCAwLjkzOCwgMS4wNjIyNiwgMS4wMDExOSwgMC45OTc5MywgMC45ODcxNCwgMS4wMjMxLCAxLjAxMjMxLCAwLjk4MTk2LCAwLjc5MiwgMS4xOTEzNywgMC45OTA3NCwgMC45NjIsIDEuMDE5MTUsIDAuOTI2LCAwLjk0MiwgMC44NTYsIDAuODUwMzQsIDAuOTIwMDYsIDAuODUwMzQsIDEuMDIwNTgsIDAuNjkwNjcsIDAuOTIyNDEsIDAuOTIyNDEsIDAuOTIyNDEsIDAuOTIyNDEsIDAuOTIwMDYsIDAuOTMzMiwgMC45MDA4OCwgMC45MTg4MiwgMC45MzQ4NCwgMC43NTMzOSwgMS4wMjA1OCwgMC41Njg2NiwgMC41NDMyNCwgMC43OTUxOSwgMS4wODU5NSwgMSwgMSwgMC45MDA4OCwgMSwgMC45NTMyNSwgMC43NDUwNSwgMC45MDA4OCwgMSwgMC45NzE5OCwgMC43NTMzOSwgMC45MTAwOSwgMC45MTAwOSwgMC45MTAwOSwgMC42NjQ2NiwgMC45MTc1NSwgMC45MTc1NSwgMC45MTc1NSwgMC45MTc1NSwgMC45MTc1NSwgMC45MTc1NSwgMC43ODgsIDAuODAzMTQsIDAuNzM3NjQsIDAuNzM3NjQsIDAuNzM3NjQsIDAuNzM3NjQsIDAuODYwMjMsIDAuODYwMjMsIDAuODYwMjMsIDAuODYwMjMsIDAuOTI5MTUsIDAuOTExMTUsIDAuODg1OCwgMC44ODU4LCAwLjg4NTgsIDAuODg1OCwgMC44ODU4LCAxLjAyMDU4LCAwLjg4NTgsIDAuODk1OTEsIDAuODk1OTEsIDAuODk1OTEsIDAuODk1OTEsIDAuODExMSwgMC43OTYxMSwgMC44OTcxMywgMC44NjY2NywgMC44NjY2NywgMC44NjY2NywgMC44NjY2NywgMC44NjY2NywgMC44NjY2NywgMC44NjkzNiwgMC44OTYsIDAuOTAwODMsIDAuOTAwODMsIDAuOTAwODMsIDAuOTAwODMsIDAuODQyMjQsIDAuODQyMjQsIDAuODQyMjQsIDAuODQyMjQsIDAuOTcyNzYsIDAuOTk3OTMsIDAuOTg3MTQsIDAuOTg3MTQsIDAuOTg3MTQsIDAuOTg3MTQsIDAuOTg3MTQsIDEuMDg1OTUsIDAuODk4NzYsIDAuOTkwNzQsIDAuOTkwNzQsIDAuOTkwNzQsIDAuOTkwNzQsIDAuOTQyLCAxLjAyMzEsIDAuOTQyLCAwLjkxNzU1LCAwLjg2NjY3LCAwLjkxNzU1LCAwLjg2NjY3LCAwLjkxNzU1LCAwLjg2NjY3LCAwLjgwMzE0LCAwLjg5NiwgMC44MDMxNCwgMC44OTYsIDAuODAzMTQsIDAuODk2LCAwLjgwMzE0LCAwLjg5NiwgMC45MjIyMiwgMC45MzM3MiwgMC45MjkxNSwgMS4wMTQxMSwgMC43Mzc2NCwgMC45MDA4MywgMC43Mzc2NCwgMC45MDA4MywgMC43Mzc2NCwgMC45MDA4MywgMC43Mzc2NCwgMC45MDA4MywgMC43Mzc2NCwgMC45MDA4MywgMC44MzA1MSwgMS4wMDUxMiwgMC44MzA1MSwgMS4wMDUxMiwgMC44MzA1MSwgMS4wMDUxMiwgMSwgMSwgMC45MDI4NCwgMC45OTc5MywgMC45MDk3NiwgMC45OTc5MywgMC44NjAyMywgMC44NDIyNCwgMC44NjAyMywgMC44NDIyNCwgMC44NjAyMywgMC44NDIyNCwgMC44NjAyMywgMS4wNTMyNiwgMC44NjAyMywgMC44NDIyNCwgMC44Mjg3MywgMS4wNzQ2OSwgMC43NCwgMS4wOTM3NywgMSwgMSwgMC45MzgsIDAuODQ4NjksIDEuMDYyMjYsIDEsIDEsIDAuODQ4NjksIDAuODM3MDQsIDAuODQ4NjksIDAuODE0NDEsIDAuODU1ODgsIDEuMDg5MjcsIDAuOTExMTUsIDAuOTk3OTMsIDEsIDEsIDAuOTExMTUsIDAuOTk3OTMsIDAuOTE4ODcsIDAuOTA5OTEsIDAuOTk3OTMsIDAuODg1OCwgMC45ODcxNCwgMC44ODU4LCAwLjk4NzE0LCAwLjg4NTgsIDAuOTg3MTQsIDAuODk0LCAwLjkxNDM0LCAwLjc0NDk4LCAwLjk4MTk2LCAxLCAxLCAwLjc0NDk4LCAwLjk4MTk2LCAwLjczOTE0LCAwLjc5MiwgMC43MzkxNCwgMC43OTIsIDEsIDEsIDAuNzM5MTQsIDAuNzkyLCAxLCAxLCAwLjgxMzYzLCAwLjkwNCwgMC44MTM2MywgMS4xOTEzNywgMC44OTU5MSwgMC45OTA3NCwgMC44OTU5MSwgMC45OTA3NCwgMC44OTU5MSwgMC45OTA3NCwgMC44OTU5MSwgMC45OTA3NCwgMC44OTU5MSwgMC45OTA3NCwgMC44OTU5MSwgMC45OTA3NCwgMC44OTYzMywgMS4wMTkxNSwgMC44MTExLCAwLjk0MiwgMC44MTExLCAwLjkwNTMxLCAwLjg1NiwgMC45MDUzMSwgMC44NTYsIDAuOTA1MzEsIDAuODU2LCAxLCAwLjkyMjQxLCAwLjkxNzU1LCAwLjg2NjY3LCAwLjc4OCwgMC44NjkzNiwgMC44ODU4LCAwLjg5ODc2LCAxLCAxLCAwLjgxMzYzLCAxLjE5MTM3LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMzg4LCAxLjAzOTAxLCAwLjkyMTM4LCAwLjc4MTA1LCAwLjcxNTQsIDAuODYxNjksIDAuODA1MTMsIDAuOTQwMDcsIDAuODI1MjgsIDAuOTg2MTIsIDEuMDYyMjYsIDAuOTE3NTUsIDAuODEyNiwgMC44MTg4NCwgMC45MjgxOSwgMC43Mzc2NCwgMC45MDUzMSwgMC45MDI4NCwgMC44ODU4LCAwLjg2MDIzLCAwLjgxMjYsIDAuOTExNzIsIDAuOTY1MTgsIDAuOTExMTUsIDAuODMwODksIDAuODg1OCwgMC44Nzc5MSwgMC43OTc2MSwgMC44OTI5NywgMC44MTM2MywgMC44ODE1NywgMC44OTk5MiwgMC44NTYwOCwgMC44MTk5MiwgMC45NDMwNywgMC44NjAyMywgMC44ODE1NywgMC45NTMwOCwgMC45ODY5OSwgMC45OTc5MywgMS4wNjIyNiwgMC45NTgxNywgMC45NTMwOCwgMC45NzM1OCwgMC45MjgsIDAuOTgwODgsIDAuOTg2OTksIDAuOTI3NjEsIDAuOTk3OTMsIDAuOTYwMTcsIDEuMDYyMjYsIDAuOTg2LCAwLjk0NCwgMC45NTk3OCwgMC45MzgsIDAuOTY3MDUsIDAuOTg3MTQsIDAuODA0NDIsIDAuOTg5NzIsIDEsIDAuODk3NjIsIDEuMDQ1NTIsIDAuOTU4MTcsIDAuOTkwMDcsIDAuODcwNjQsIDAuOTE4NzksIDAuODg4ODgsIDEuMDYyMjYsIDAuOTU4MTcsIDAuOTg3MTQsIDAuOTU4MTcsIDAuODg4ODgsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuODk2MzMsIDEuMDE5MTUsIDAuODk2MzMsIDEuMDE5MTUsIDAuODk2MzMsIDEuMDE5MTUsIDAuODExMSwgMC45NDIsIDAuOTIxOSwgMSwgMC44OTkwMywgMSwgMSwgMSwgMC45MzE3MywgMC45MzE3MywgMC45MzE3MywgMSwgMS4wNjMwNCwgMS4wNjMwNCwgMS4wNjkwNCwgMC44OTkwMywgMC44OTkwMywgMC44MDU0OSwgMSwgMS4xNTYsIDEsIDEsIDAuNzY1NzUsIDAuNzY1NzUsIDEsIDEsIDAuNzI0NTgsIDEsIDEsIDEsIDEsIDAuOTIyNDEsIDEsIDEsIDEsIDAuNjE5LCAxLCAxLjM2MTQ1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjA3MjU3LCAxLCAwLjc0NzA1LCAwLjcxMTE5LCAxLjAyMDU4LCAxLjAyNCwgMS4wMjExOSwgMSwgMSwgMS4xNTM2LCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjA1NjM4LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKY29uc3QgTXlyaWFkUHJvUmVndWxhck1ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yLAogIGxpbmVHYXA6IDAuMgp9OwoKOy8vIC4vc3JjL2NvcmUvc2Vnb2V1aV9mYWN0b3JzLmpzCmNvbnN0IFNlZ29ldWlCb2xkRmFjdG9ycyA9IFsxLjc2NzM4LCAxLCAxLCAwLjk5Mjk3LCAwLjk4MjQsIDEuMDQwMTYsIDEuMDY0OTcsIDEuMDM0MjQsIDAuOTc1MjksIDEuMTc2NDcsIDEuMjMyMDMsIDEuMTA4NSwgMS4xMDg1LCAxLjE2OTM5LCAxLjIxMDcsIDAuOTc1NCwgMS4yMTQwOCwgMC45NzU0LCAxLjU5NTc4LCAxLjAzNDI0LCAxLjAzNDI0LCAxLjAzNDI0LCAxLjAzNDI0LCAxLjAzNDI0LCAxLjAzNDI0LCAxLjAzNDI0LCAxLjAzNDI0LCAxLjAzNDI0LCAxLjAzNDI0LCAwLjgxMzc4LCAwLjgxMzc4LCAxLjIxMDcsIDEuMjEwNywgMS4yMTA3LCAwLjcxNzAzLCAwLjk3ODQ3LCAwLjk3MzYzLCAwLjg4Nzc2LCAwLjg2NDEsIDEuMDIwOTYsIDAuNzk3OTUsIDAuODUxMzIsIDAuOTE0LCAxLjA2MDg1LCAxLjE0MDYsIDAuODAwNywgMC44OTg1OCwgMC44MzY5MywgMS4xNDg4OSwgMS4wOTM5OCwgMC45NzQ4OSwgMC45MjA5NCwgMC45NzQ4OSwgMC45MDM5OSwgMC44NDA0MSwgMC45NTkyMywgMS4wMDEzNSwgMSwgMS4wNjQ2NywgMC45ODI0MywgMC45MDk5NiwgMC45OTM2MSwgMS4xMDg1LCAxLjU2OTQyLCAxLjEwODUsIDEuMjEwNywgMC43NDYyNywgMC45NDI4MiwgMC45Njc1MiwgMS4wMTUxOSwgMC44NjMwNCwgMS4wMTM1OSwgMC45NzI3OCwgMS4xNTEwMywgMS4wMTM1OSwgMC45ODU2MSwgMS4wMjI4NSwgMS4wMjI4NSwgMS4wMDUyNywgMS4wMjI4NSwgMS4wMzAyLCAwLjk5MDQxLCAxLjAwMDgsIDEuMDE1MTksIDEuMDEzNTksIDEuMDIyNTgsIDAuNzkxMDQsIDEuMTY4NjIsIDAuOTkwNDEsIDAuOTc0NTQsIDEuMDI1MTEsIDAuOTkyOTgsIDAuOTY3NTIsIDAuOTU4MDEsIDAuOTQ4NTYsIDEuMTY1NzksIDAuOTQ4NTYsIDEuMjEwNywgMC45ODI0LCAxLjAzNDI0LCAxLjAzNDI0LCAxLCAxLjAzNDI0LCAxLjE2NTc5LCAwLjg3MjcsIDEuMzg3MSwgMS4xODYyMiwgMS4xMDgxOCwgMS4wNDQ3OCwgMS4yMTA3LCAxLjE4NjIyLCAwLjc1MTU1LCAwLjk0OTk0LCAxLjI4ODI2LCAxLjIxNDA4LCAxLjIxNDA4LCAwLjkxMDU2LCAxLCAwLjkxNTcyLCAwLjk3NTQsIDAuNjQ2NjMsIDEuMTgzMjgsIDEuMjQ4NjYsIDEuMDQ0NzgsIDEuMTQxNjksIDEuMTU3NDksIDEuMTczODksIDAuNzE3MDMsIDAuOTczNjMsIDAuOTczNjMsIDAuOTczNjMsIDAuOTczNjMsIDAuOTczNjMsIDAuOTczNjMsIDAuOTM1MDYsIDAuODY0MSwgMC43OTc5NSwgMC43OTc5NSwgMC43OTc5NSwgMC43OTc5NSwgMS4xNDA2LCAxLjE0MDYsIDEuMTQwNiwgMS4xNDA2LCAxLjAyMDk2LCAxLjA5Mzk4LCAwLjk3NDI2LCAwLjk3NDI2LCAwLjk3NDI2LCAwLjk3NDI2LCAwLjk3NDI2LCAxLjIxMDcsIDAuOTc0ODksIDEuMDAxMzUsIDEuMDAxMzUsIDEuMDAxMzUsIDEuMDAxMzUsIDAuOTA5OTYsIDAuOTIwOTQsIDEuMDI3OTgsIDAuOTY3NTIsIDAuOTY3NTIsIDAuOTY3NTIsIDAuOTY3NTIsIDAuOTY3NTIsIDAuOTY3NTIsIDAuOTMxMzYsIDAuODYzMDQsIDAuOTcyNzgsIDAuOTcyNzgsIDAuOTcyNzgsIDAuOTcyNzgsIDEuMDIyODUsIDEuMDIyODUsIDEuMDIyODUsIDEuMDIyODUsIDAuOTcxMjIsIDAuOTkwNDEsIDEsIDEsIDEsIDEsIDEsIDEuMjg4MjYsIDEuMDAwOCwgMC45OTA0MSwgMC45OTA0MSwgMC45OTA0MSwgMC45OTA0MSwgMC45Njc1MiwgMS4wMTUxOSwgMC45Njc1MiwgMC45NzM2MywgMC45Njc1MiwgMC45NzM2MywgMC45Njc1MiwgMC45NzM2MywgMC45Njc1MiwgMC44NjQxLCAwLjg2MzA0LCAwLjg2NDEsIDAuODYzMDQsIDAuODY0MSwgMC44NjMwNCwgMC44NjQxLCAwLjg2MzA0LCAxLjAyMDk2LCAxLjAzMDU3LCAxLjAyMDk2LCAxLjAzNTE3LCAwLjc5Nzk1LCAwLjk3Mjc4LCAwLjc5Nzk1LCAwLjk3Mjc4LCAwLjc5Nzk1LCAwLjk3Mjc4LCAwLjc5Nzk1LCAwLjk3Mjc4LCAwLjc5Nzk1LCAwLjk3Mjc4LCAwLjkxNCwgMS4wMTM1OSwgMC45MTQsIDEuMDEzNTksIDAuOTE0LCAxLjAxMzU5LCAxLCAxLCAxLjA2MDg1LCAwLjk4NTYxLCAxLjA2MDg1LCAxLjAwODc5LCAxLjE0MDYsIDEuMDIyODUsIDEuMTQwNiwgMS4wMjI4NSwgMS4xNDA2LCAxLjAyMjg1LCAxLjE0MDYsIDEuMDIyODUsIDEuMTQwNiwgMS4wMjI4NSwgMC45NzEzOCwgMS4wODY5MiwgMC44MDA3LCAxLjAyMjg1LCAxLCAxLCAxLjAwNTI3LCAwLjgzNjkzLCAxLjAyMjg1LCAxLCAxLCAwLjgzNjkzLCAwLjk0NTUsIDAuODM2OTMsIDAuOTA0MTgsIDAuODM2OTMsIDEuMTMwMDUsIDEuMDkzOTgsIDAuOTkwNDEsIDEsIDEsIDEuMDkzOTgsIDAuOTkwNDEsIDAuOTY2OTIsIDEuMDkyNTEsIDAuOTkwNDEsIDAuOTc0ODksIDEuMDAwOCwgMC45NzQ4OSwgMS4wMDA4LCAwLjk3NDg5LCAxLjAwMDgsIDAuOTM5OTQsIDAuOTc5MzEsIDAuOTAzOTksIDEuMDIyNTgsIDEsIDEsIDAuOTAzOTksIDEuMDIyNTgsIDAuODQwNDEsIDAuNzkxMDQsIDAuODQwNDEsIDAuNzkxMDQsIDAuODQwNDEsIDAuNzkxMDQsIDAuODQwNDEsIDAuNzkxMDQsIDEsIDEsIDAuOTU5MjMsIDEuMDcwMzQsIDAuOTU5MjMsIDEuMTY4NjIsIDEuMDAxMzUsIDAuOTkwNDEsIDEuMDAxMzUsIDAuOTkwNDEsIDEuMDAxMzUsIDAuOTkwNDEsIDEuMDAxMzUsIDAuOTkwNDEsIDEuMDAxMzUsIDAuOTkwNDEsIDEuMDAxMzUsIDAuOTkwNDEsIDEuMDY0NjcsIDEuMDI1MTEsIDAuOTA5OTYsIDAuOTY3NTIsIDAuOTA5OTYsIDAuOTkzNjEsIDAuOTU4MDEsIDAuOTkzNjEsIDAuOTU4MDEsIDAuOTkzNjEsIDAuOTU4MDEsIDEuMDc3MzMsIDEuMDM0MjQsIDAuOTczNjMsIDAuOTY3NTIsIDAuOTM1MDYsIDAuOTMxMzYsIDAuOTc0ODksIDEuMDAwOCwgMSwgMSwgMC45NTkyMywgMS4xNjg2MiwgMS4xNTEwMywgMS4xNTEwMywgMS4wMTE3MywgMS4wMzk1OSwgMC43NTk1MywgMC44MTM3OCwgMC43OTkxMiwgMS4xNTEwMywgMS4yMTk5NCwgMC45NTE2MSwgMC44NzgxNSwgMS4wMTE0OSwgMC44MTUyNSwgMC43Njc2LCAwLjk4MTY3LCAxLjAxMTM0LCAxLjAyNTQ2LCAwLjg0MDk3LCAxLjAzMDg5LCAxLjE4MTAyLCAwLjk3MzYzLCAwLjg4Nzc2LCAwLjg1MTM0LCAwLjk3ODI2LCAwLjc5Nzk1LCAwLjk5MzYxLCAxLjA2MDg1LCAwLjk3NDg5LCAxLjE0MDYsIDAuODk4NTgsIDEuMDM4OCwgMS4xNDg4OSwgMS4wOTM5OCwgMC44NjAzOSwgMC45NzQ4OSwgMS4wNTk1LCAwLjkyMDk0LCAwLjk0NzkzLCAwLjk1OTIzLCAwLjkwOTk2LCAwLjk5MzQ2LCAwLjk4MjQzLCAxLjAyMTEyLCAwLjk1NDkzLCAxLjE0MDYsIDAuOTA5OTYsIDEuMDM1NzQsIDEuMDI1OTcsIDEuMDAwOCwgMS4xODEwMiwgMS4wNjYyOCwgMS4wMzU3NCwgMS4wMTkyLCAxLjAxOTMyLCAxLjAwODg2LCAwLjk3NTMxLCAxLjAxMDYsIDEuMDAwOCwgMS4xMzE4OSwgMS4xODEwMiwgMS4wMjI3NywgMC45ODY4MywgMS4wMDE2LCAwLjk5NTYxLCAxLjA3MjM3LCAxLjAwMDgsIDAuOTA0MzQsIDAuOTk5MjEsIDAuOTM4MDMsIDAuODk2NSwgMS4yMzA4NSwgMS4wNjYyOCwgMS4wNDk4MywgMC45NjI2OCwgMS4wNDk5LCAwLjk4NDM5LCAxLjE4MTAyLCAxLjA2NjI4LCAxLjAwMDgsIDEuMDY2MjgsIDAuOTg0MzksIDAuNzk3OTUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDk0NjYsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTcyNzgsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDIwNjUsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDY0NjcsIDEuMDI1MTEsIDEuMDY0NjcsIDEuMDI1MTEsIDEuMDY0NjcsIDEuMDI1MTEsIDAuOTA5OTYsIDAuOTY3NTIsIDEsIDEuMjE0MDgsIDAuODk5MDMsIDEsIDEsIDAuNzUxNTUsIDEuMDQzOTQsIDEuMDQzOTQsIDEuMDQzOTQsIDEuMDQzOTQsIDAuOTg2MzMsIDAuOTg2MzMsIDAuOTg2MzMsIDAuNzMwNDcsIDAuNzMwNDcsIDEuMjA2NDIsIDAuOTEyMTEsIDEuMjU2MzUsIDEuMjIyLCAxLjAyOTU2LCAxLjAzMzcyLCAxLjAzMzcyLCAwLjk2MDM5LCAxLjI0NjMzLCAxLCAxLjEyNDU0LCAwLjkzNTAzLCAxLjAzNDI0LCAxLjE5Njg3LCAxLjAzNDI0LCAxLCAxLCAxLCAwLjc3MSwgMSwgMSwgMS4xNTc0OSwgMS4xNTc0OSwgMS4xNTc0OSwgMS4xMDk0OCwgMC44NjI3OSwgMC45NDQzNCwgMC44NjI3OSwgMC45NDQzNCwgMC44NjE4MiwgMSwgMSwgMS4xNjg5NywgMSwgMC45NjA4NSwgMC45MDEzNywgMS4yMTA3LCAxLjE4NDE2LCAxLjEzOTczLCAwLjY5ODI1LCAwLjk3MTYsIDIuMTAzMzksIDEuMjkwMDQsIDEuMjkwMDQsIDEuMjExNzIsIDEuMjkwMDQsIDEuMjkwMDQsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuNDI2MDMsIDEsIDAuOTk4NjIsIDAuOTk4NjIsIDEsIDAuODcwMjUsIDAuODcwMjUsIDAuODcwMjUsIDAuODcwMjUsIDEuMTg4NzQsIDEuNDI2MDMsIDEsIDEuNDI2MDMsIDEuNDI2MDMsIDAuOTk4NjIsIDEsIDEsIDEsIDEsIDEsIDEuMjg4NiwgMS4wNDMxNSwgMS4xNTI5NiwgMS4zNDE2MywgMSwgMSwgMSwgMS4wOTE5MywgMS4wOTE5MywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmNvbnN0IFNlZ29ldWlCb2xkTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjMzMDA4LAogIGxpbmVHYXA6IDAKfTsKY29uc3QgU2Vnb2V1aUJvbGRJdGFsaWNGYWN0b3JzID0gWzEuNzY3MzgsIDEsIDEsIDAuOTg5NDYsIDEuMDM5NTksIDEuMDQwMTYsIDEuMDI4MDksIDEuMDM2LCAwLjk3NjM5LCAxLjEwOTUzLCAxLjIzMjAzLCAxLjExMTQ0LCAxLjExMTQ0LCAxLjE2OTM5LCAxLjIxMjM3LCAwLjk3NTQsIDEuMjEyNjEsIDAuOTc1NCwgMS41OTc1NCwgMS4wMzYsIDEuMDM2LCAxLjAzNiwgMS4wMzYsIDEuMDM2LCAxLjAzNiwgMS4wMzYsIDEuMDM2LCAxLjAzNiwgMS4wMzYsIDAuODEzNzgsIDAuODEzNzgsIDEuMjEyMzcsIDEuMjEyMzcsIDEuMjEyMzcsIDAuNzM1NDEsIDAuOTc4NDcsIDAuOTczNjMsIDAuODk3MjMsIDAuODc4OTcsIDEuMDQyNiwgMC43OTQyOSwgMC44NTI5MiwgMC45MTE0OSwgMS4wNTgxNSwgMS4xNDA2LCAwLjc5NjMxLCAwLjkwMTI4LCAwLjgzODUzLCAxLjA0Mzk2LCAxLjEwNjE1LCAwLjk3NTUyLCAwLjk0NDM2LCAwLjk3NTUyLCAwLjg4NjQxLCAwLjgwNTI3LCAwLjk2MDgzLCAxLjAwMTM1LCAxLCAxLjA2Nzc3LCAwLjk4MTcsIDAuOTExNDIsIDAuOTkzNjEsIDEuMTExNDQsIDEuNTcyOTMsIDEuMTExNDQsIDEuMjEyMzcsIDAuNzQ2MjcsIDEuMzE4MTgsIDEuMDY1ODUsIDAuOTcwNDIsIDAuODMwNTUsIDAuOTcwNDIsIDAuOTM1MDMsIDEuMTI2MSwgMC45NzA0MiwgMC45NzkyMiwgMS4xNDIzNiwgMC45NDU1MiwgMS4wMTA1NCwgMS4xNDIzNiwgMS4wMjQ3MSwgMC45NzkyMiwgMC45NDE2NSwgMC45NzA0MiwgMC45NzA0MiwgMS4wMjc2LCAwLjc4OTI5LCAxLjEyNjEsIDAuOTc5MjIsIDAuOTU4NzQsIDEuMDIxOTcsIDAuOTg1MDcsIDAuOTY3NTIsIDAuOTcxNjgsIDAuOTUxMDcsIDEuMTY1NzksIDAuOTUxMDcsIDEuMjEyMzcsIDEuMDM5NTksIDEuMDM2LCAxLjAzNiwgMSwgMS4wMzYsIDEuMTY1NzksIDAuODczNTcsIDEuMzE4MTgsIDEuMTg3NTQsIDEuMjY3ODEsIDEuMDUzNTYsIDEuMjEyMzcsIDEuMTg2MjIsIDAuNzk0ODcsIDAuOTQ5OTQsIDEuMjkwMDQsIDEuMjQwNDcsIDEuMjQwNDcsIDEuMzE4MTgsIDEsIDAuOTE0ODQsIDAuOTc1NCwgMS4zMTgxOCwgMS4xMzQ5LCAxLjI0ODY2LCAxLjA1MzU2LCAxLjEzOTM0LCAxLjE1NTc0LCAxLjE3Mzg5LCAwLjczNTQxLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk0Mzg1LCAwLjg3ODk3LCAwLjc5NDI5LCAwLjc5NDI5LCAwLjc5NDI5LCAwLjc5NDI5LCAxLjE0MDYsIDEuMTQwNiwgMS4xNDA2LCAxLjE0MDYsIDEuMDQyNiwgMS4xMDYxNSwgMC45NzU1MiwgMC45NzU1MiwgMC45NzU1MiwgMC45NzU1MiwgMC45NzU1MiwgMS4yMTIzNywgMC45NzU1MiwgMS4wMDEzNSwgMS4wMDEzNSwgMS4wMDEzNSwgMS4wMDEzNSwgMC45MTE0MiwgMC45NDQzNiwgMC45ODcyMSwgMS4wNjU4NSwgMS4wNjU4NSwgMS4wNjU4NSwgMS4wNjU4NSwgMS4wNjU4NSwgMS4wNjU4NSwgMC45NjcwNSwgMC44MzA1NSwgMC45MzUwMywgMC45MzUwMywgMC45MzUwMywgMC45MzUwMywgMS4xNDIzNiwgMS4xNDIzNiwgMS4xNDIzNiwgMS4xNDIzNiwgMC45MzEyNSwgMC45NzkyMiwgMC45NDE2NSwgMC45NDE2NSwgMC45NDE2NSwgMC45NDE2NSwgMC45NDE2NSwgMS4yOTAwNCwgMC45NDE2NSwgMC45NzkyMiwgMC45NzkyMiwgMC45NzkyMiwgMC45NzkyMiwgMC45Njc1MiwgMC45NzA0MiwgMC45Njc1MiwgMC45NzM2MywgMS4wNjU4NSwgMC45NzM2MywgMS4wNjU4NSwgMC45NzM2MywgMS4wNjU4NSwgMC44Nzg5NywgMC44MzA1NSwgMC44Nzg5NywgMC44MzA1NSwgMC44Nzg5NywgMC44MzA1NSwgMC44Nzg5NywgMC44MzA1NSwgMS4wNDI2LCAxLjAwMzMsIDEuMDQyNiwgMC45NzA0MiwgMC43OTQyOSwgMC45MzUwMywgMC43OTQyOSwgMC45MzUwMywgMC43OTQyOSwgMC45MzUwMywgMC43OTQyOSwgMC45MzUwMywgMC43OTQyOSwgMC45MzUwMywgMC45MTE0OSwgMC45NzA0MiwgMC45MTE0OSwgMC45NzA0MiwgMC45MTE0OSwgMC45NzA0MiwgMSwgMSwgMS4wNTgxNSwgMC45NzkyMiwgMS4wNTgxNSwgMC45NzkyMiwgMS4xNDA2LCAxLjE0MjM2LCAxLjE0MDYsIDEuMTQyMzYsIDEuMTQwNiwgMS4xNDIzNiwgMS4xNDA2LCAxLjE0MjM2LCAxLjE0MDYsIDEuMTQyMzYsIDAuOTc0NDEsIDEuMDQzMDIsIDAuNzk2MzEsIDEuMDE1ODIsIDEsIDEsIDEuMDEwNTQsIDAuODM4NTMsIDEuMTQyMzYsIDEsIDEsIDAuODM4NTMsIDEuMDkxMjUsIDAuODM4NTMsIDAuOTA0MTgsIDAuODM4NTMsIDEuMTk1MDgsIDEuMTA2MTUsIDAuOTc5MjIsIDEsIDEsIDEuMTA2MTUsIDAuOTc5MjIsIDEuMDEwMzQsIDEuMTA0NjYsIDAuOTc5MjIsIDAuOTc1NTIsIDAuOTQxNjUsIDAuOTc1NTIsIDAuOTQxNjUsIDAuOTc1NTIsIDAuOTQxNjUsIDAuOTE2MDIsIDAuOTE5ODEsIDAuODg2NDEsIDEuMDI3NiwgMSwgMSwgMC44ODY0MSwgMS4wMjc2LCAwLjgwNTI3LCAwLjc4OTI5LCAwLjgwNTI3LCAwLjc4OTI5LCAwLjgwNTI3LCAwLjc4OTI5LCAwLjgwNTI3LCAwLjc4OTI5LCAxLCAxLCAwLjk2MDgzLCAxLjA1NDAzLCAwLjk1OTIzLCAxLjE2ODYyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjA2Nzc3LCAxLjAyMTk3LCAwLjkxMTQyLCAwLjk2NzUyLCAwLjkxMTQyLCAwLjk5MzYxLCAwLjk3MTY4LCAwLjk5MzYxLCAwLjk3MTY4LCAwLjk5MzYxLCAwLjk3MTY4LCAxLjIzMTk5LCAxLjAzNiwgMC45NzM2MywgMS4wNjU4NSwgMC45NDM4NSwgMC45NjcwNSwgMC45NzU1MiwgMC45NDE2NSwgMSwgMSwgMC45NjA4MywgMS4xMjYxLCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAwLjk1MTYxLCAxLjI3MTI2LCAxLjAwODExLCAwLjgzMjg0LCAwLjc3NzAyLCAwLjk5MTM3LCAwLjk1MjUzLCAxLjAzNDcsIDAuODYxNDIsIDEuMDcyMDUsIDEuMTQyMzYsIDAuOTczNjMsIDAuODk3MjMsIDAuODY4NjksIDEuMDk4MTgsIDAuNzk0MjksIDAuOTkzNjEsIDEuMDU4MTUsIDAuOTc1NTIsIDEuMTQwNiwgMC45MDEyOCwgMS4wNjY2MiwgMS4wNDM5NiwgMS4xMDYxNSwgMC44NDkxOCwgMC45NzU1MiwgMS4wNDY5NCwgMC45NDQzNiwgMC45ODAxNSwgMC45NjA4MywgMC45MTE0MiwgMS4wMDM1NiwgMC45ODE3LCAxLjAxOTQ1LCAwLjk4OTk5LCAxLjE0MDYsIDAuOTExNDIsIDEuMDQ5NjEsIDAuOTg5OCwgMS4wMDYzOSwgMS4xNDIzNiwgMS4wNzUxNCwgMS4wNDk2MSwgMC45OTYwNywgMS4wMjg5NywgMS4wMDgsIDAuOTg5OCwgMC45NTEzNCwgMS4wMDYzOSwgMS4xMTEyMSwgMS4xNDIzNiwgMS4wMDUxOCwgMC45Nzk4MSwgMS4wMjE4NiwgMSwgMS4wODU3OCwgMC45NDE2NSwgMC45OTMxNCwgMC45ODM4NywgMC45MzAyOCwgMC45MzM3NywgMS4zNTEyNSwgMS4wNzUxNCwgMS4xMDY4NywgMC45MzQ5MSwgMS4wNDIzMiwgMS4wMDM1MSwgMS4xNDIzNiwgMS4wNzUxNCwgMC45NDE2NSwgMS4wNzUxNCwgMS4wMDM1MSwgMC43OTQyOSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wOTA5NywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MzUwMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45NjYwOSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wNjc3NywgMS4wMjE5NywgMS4wNjc3NywgMS4wMjE5NywgMS4wNjc3NywgMS4wMjE5NywgMC45MTE0MiwgMC45Njc1MiwgMSwgMS4yMTI2MSwgMC44OTkwMywgMSwgMSwgMC43NTE1NSwgMS4wNDc0NSwgMS4wNDc0NSwgMS4wNDc0NSwgMS4wNDM5NCwgMC45ODYzMywgMC45ODYzMywgMC45ODYzMywgMC43Mjk1OSwgMC43Mjk1OSwgMS4yMDUwMiwgMC45MTQwNiwgMS4yNjUxNCwgMS4yMjIsIDEuMDI5NTYsIDEuMDMzNzIsIDEuMDMzNzIsIDAuOTYwMzksIDEuMjQ2MzMsIDEsIDEuMDkxMjUsIDAuOTMzMjcsIDEuMDMzMzYsIDEuMTY1NDEsIDEuMDM2LCAxLCAxLCAxLCAwLjc3MSwgMSwgMSwgMS4xNTU3NCwgMS4xNTU3NCwgMS4xNTU3NCwgMS4xNTU3NCwgMC44NjM2NCwgMC45NDQzNCwgMC44NjI3OSwgMC45NDQzNCwgMC44NjIyNCwgMSwgMSwgMS4xNjc5OCwgMSwgMC45NjA4NSwgMC45MDA2OCwgMS4yMTIzNywgMS4xODQxNiwgMS4xMzkwNCwgMC42OTgyNSwgMC45NzE2LCAyLjEwMzM5LCAxLjI5MDA0LCAxLjI5MDA0LCAxLjIxMzM5LCAxLjI5MDA0LCAxLjI5MDA0LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjQyNjAzLCAxLCAwLjk5ODYyLCAwLjk5ODYyLCAxLCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAxLjE4Nzc1LCAxLjQyNjAzLCAxLCAxLjQyNjAzLCAxLjQyNjAzLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLjI4ODYsIDEuMDQzMTUsIDEuMTUyOTYsIDEuMzQxNjMsIDEsIDEsIDEsIDEuMTMyNjksIDEuMTMyNjksIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBTZWdvZXVpQm9sZEl0YWxpY01ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4zMzAwOCwKICBsaW5lR2FwOiAwCn07CmNvbnN0IFNlZ29ldWlJdGFsaWNGYWN0b3JzID0gWzEuNzY3MzgsIDEsIDEsIDAuOTg5NDYsIDEuMTQ3NjMsIDEuMDUzNjUsIDEuMDYyMzQsIDAuOTY5MjcsIDAuOTI1ODYsIDEuMTUzNzMsIDEuMTg0MTQsIDAuOTEzNDksIDAuOTEzNDksIDEuMDc0MDMsIDEuMTczMDgsIDAuNzgzODMsIDEuMjAwODgsIDAuNzgzODMsIDEuNDI1MzEsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuNzgzODMsIDAuNzgzODMsIDEuMTczMDgsIDEuMTczMDgsIDEuMTczMDgsIDAuNzczNDksIDAuOTQ1NjUsIDAuOTQ3MjksIDAuODU5NDQsIDAuODg1MDYsIDAuOTg1OCwgMC43NDgxNywgMC44MDAxNiwgMC44ODQ0OSwgMC45ODAzOSwgMC45NTc4MiwgMC42OTIzOCwgMC44OTg5OCwgMC44MzIzMSwgMC45ODE4MywgMS4wMzk4OSwgMC45NjkyNCwgMC44NjIzNywgMC45NjkyNCwgMC44MDU5NSwgMC43NDUyNCwgMC44NjA5MSwgMC45NTQwMiwgMC45NDE0MywgMC45ODQ0OCwgMC44ODU4LCAwLjgzMDg5LCAwLjkzMjg1LCAxLjA5NDksIDEuMzkwMTYsIDEuMDk0OSwgMS40NTk5NCwgMC43NDYyNywgMS4wNDgzOSwgMC45NzQ1NCwgMC45NzQ1NCwgMC44NzIwNywgMC45NzQ1NCwgMC44NzUzMywgMS4wNjE1MSwgMC45NzQ1NCwgMS4wMDE3NiwgMS4xNjQ4NCwgMS4wODEzMiwgMC45ODA0NywgMS4xNjQ4NCwgMS4wMjk4OSwgMS4wMTA1NCwgMC45NjIyNSwgMC45NzQ1NCwgMC45NzQ1NCwgMS4wNjU5OCwgMC43OTAwNCwgMS4xNjM0NCwgMS4wMDM1MSwgMC45NDYyOSwgMC45OTczLCAwLjkxMDE2LCAwLjk2Nzc3LCAwLjkwNDMsIDAuOTEwODIsIDAuOTI0ODEsIDAuOTEwODIsIDEuMTczMDgsIDAuOTU3NDgsIDAuOTY5MjcsIDAuOTY5MjcsIDEsIDAuOTY5MjcsIDAuOTI0ODEsIDAuODA1OTcsIDEuMDQ4MzksIDEuMjMzOTMsIDEuMTc4MSwgMC45MjQ1LCAxLjE3MzA4LCAxLjIwODA4LCAwLjYzMjE4LCAwLjk0MjYxLCAxLjI0ODIyLCAxLjA5OTcxLCAxLjA5OTcxLCAxLjA0ODM5LCAxLCAwLjg1MjczLCAwLjc4MDMyLCAxLjA0ODM5LCAxLjA5OTcxLCAxLjIyMzI2LCAwLjkyNDUsIDEuMDk4MzYsIDEuMTM1MjUsIDEuMTUyMjIsIDAuNzA0MjQsIDAuOTQ3MjksIDAuOTQ3MjksIDAuOTQ3MjksIDAuOTQ3MjksIDAuOTQ3MjksIDAuOTQ3MjksIDAuODU0OTgsIDAuODg1MDYsIDAuNzQ4MTcsIDAuNzQ4MTcsIDAuNzQ4MTcsIDAuNzQ4MTcsIDAuOTU3ODIsIDAuOTU3ODIsIDAuOTU3ODIsIDAuOTU3ODIsIDAuOTg1OCwgMS4wMzk4OSwgMC45NjkyNCwgMC45NjkyNCwgMC45NjkyNCwgMC45NjkyNCwgMC45NjkyNCwgMS4xNzMwOCwgMC45NjkyNCwgMC45NTQwMiwgMC45NTQwMiwgMC45NTQwMiwgMC45NTQwMiwgMC44MzA4OSwgMC44NjIzNywgMC44ODQwOSwgMC45NzQ1NCwgMC45NzQ1NCwgMC45NzQ1NCwgMC45NzQ1NCwgMC45NzQ1NCwgMC45NzQ1NCwgMC45MjkxNiwgMC44NzIwNywgMC44NzUzMywgMC44NzUzMywgMC44NzUzMywgMC44NzUzMywgMC45MzE0NiwgMC45MzE0NiwgMC45MzE0NiwgMC45MzE0NiwgMC45Mzg1NCwgMS4wMTA1NCwgMC45NjIyNSwgMC45NjIyNSwgMC45NjIyNSwgMC45NjIyNSwgMC45NjIyNSwgMS4yNDgyMiwgMC44NzYxLCAxLjAwMzUxLCAxLjAwMzUxLCAxLjAwMzUxLCAxLjAwMzUxLCAwLjk2Nzc3LCAwLjk3NDU0LCAwLjk2Nzc3LCAwLjk0NzI5LCAwLjk3NDU0LCAwLjk0NzI5LCAwLjk3NDU0LCAwLjk0NzI5LCAwLjk3NDU0LCAwLjg4NTA2LCAwLjg3MjA3LCAwLjg4NTA2LCAwLjg3MjA3LCAwLjg4NTA2LCAwLjg3MjA3LCAwLjg4NTA2LCAwLjg3MjA3LCAwLjk4NTgsIDAuOTUzOTEsIDAuOTg1OCwgMC45NzQ1NCwgMC43NDgxNywgMC44NzUzMywgMC43NDgxNywgMC44NzUzMywgMC43NDgxNywgMC44NzUzMywgMC43NDgxNywgMC44NzUzMywgMC43NDgxNywgMC44NzUzMywgMC44ODQ0OSwgMC45NzQ1NCwgMC44ODQ0OSwgMC45NzQ1NCwgMC44ODQ0OSwgMC45NzQ1NCwgMSwgMSwgMC45ODAzOSwgMS4wMDE3NiwgMC45ODAzOSwgMS4wMDE3NiwgMC45NTc4MiwgMC45MzE0NiwgMC45NTc4MiwgMC45MzE0NiwgMC45NTc4MiwgMC45MzE0NiwgMC45NTc4MiwgMS4xNjQ4NCwgMC45NTc4MiwgMC45MzE0NiwgMC44NDQyMSwgMS4xMjc2MSwgMC42OTIzOCwgMS4wODEzMiwgMSwgMSwgMC45ODA0NywgMC44MzIzMSwgMS4xNjQ4NCwgMSwgMSwgMC44NDcyMywgMS4wNDg2MSwgMC44NDcyMywgMC43ODc1NSwgMC44MzIzMSwgMS4yMzczNiwgMS4wMzk4OSwgMS4wMTA1NCwgMSwgMSwgMS4wMzk4OSwgMS4wMTA1NCwgMC45ODU3LCAxLjAzODQ5LCAxLjAxMDU0LCAwLjk2OTI0LCAwLjk2MjI1LCAwLjk2OTI0LCAwLjk2MjI1LCAwLjk2OTI0LCAwLjk2MjI1LCAwLjkyMzgzLCAwLjkwMTcxLCAwLjgwNTk1LCAxLjA2NTk4LCAxLCAxLCAwLjgwNTk1LCAxLjA2NTk4LCAwLjc0NTI0LCAwLjc5MDA0LCAwLjc0NTI0LCAwLjc5MDA0LCAwLjc0NTI0LCAwLjc5MDA0LCAwLjc0NTI0LCAwLjc5MDA0LCAxLCAxLCAwLjg2MDkxLCAxLjAyNzU5LCAwLjg1NzcxLCAxLjE2MzQ0LCAwLjk1NDAyLCAxLjAwMzUxLCAwLjk1NDAyLCAxLjAwMzUxLCAwLjk1NDAyLCAxLjAwMzUxLCAwLjk1NDAyLCAxLjAwMzUxLCAwLjk1NDAyLCAxLjAwMzUxLCAwLjk1NDAyLCAxLjAwMzUxLCAwLjk4NDQ4LCAwLjk5NzMsIDAuODMwODksIDAuOTY3NzcsIDAuODMwODksIDAuOTMyODUsIDAuOTA0MywgMC45MzI4NSwgMC45MDQzLCAwLjkzMjg1LCAwLjkwNDMsIDEuMzE4NjgsIDAuOTY5MjcsIDAuOTQ3MjksIDAuOTc0NTQsIDAuODU0OTgsIDAuOTI5MTYsIDAuOTY5MjQsIDAuODc2MSwgMSwgMSwgMC44NjA5MSwgMS4xNjM0NCwgMS4wNDgzOSwgMS4wNDgzOSwgMS4wNDgzOSwgMS4wNDgzOSwgMS4wNDgzOSwgMS4wNDgzOSwgMS4wNDgzOSwgMS4wNDgzOSwgMS4wNDgzOSwgMC44MTk2NSwgMC44MTk2NSwgMC45NDcyOSwgMC43ODAzMiwgMC43MTAyMiwgMC45MDg4MywgMC44NDE3MSwgMC45OTg3NywgMC43NzU5NiwgMS4wNTczNCwgMS4yLCAwLjk0NzI5LCAwLjg1OTQ0LCAwLjgyNzkxLCAwLjk2MDcsIDAuNzQ4MTcsIDAuOTMyODUsIDAuOTgwMzksIDAuOTY5MjQsIDAuOTU3ODIsIDAuODk4OTgsIDAuOTgzMTYsIDAuOTgxODMsIDEuMDM5ODksIDAuNzg2MTQsIDAuOTY5MjQsIDAuOTc2NDIsIDAuODYyMzcsIDAuODYwNzUsIDAuODYwOTEsIDAuODMwODksIDAuOTAwODIsIDAuODg1OCwgMC45NzI5NiwgMS4wMTI4NCwgMC45NTc4MiwgMC44MzA4OSwgMS4wOTc2LCAxLjA0LCAxLjAzMzQyLCAxLjIsIDEuMDY3NSwgMS4wOTc2LCAwLjk4MjA1LCAxLjAzODA5LCAxLjA1MDk3LCAxLjA0LCAwLjk1MzY0LCAxLjAzMzQyLCAxLjA1NDAxLCAxLjIsIDEuMDIxNDgsIDEuMDExOSwgMS4wNDcyNCwgMS4wMTI3LCAxLjAyNzMyLCAwLjk2MjI1LCAwLjg5NjUsIDAuOTc3ODMsIDAuOTM1NzQsIDAuOTQ4MTgsIDEuMzA2NzksIDEuMDY3NSwgMS4xMTgyNiwgMC45OTgyMSwgMS4wNTU3LCAxLjAzMjYsIDEuMiwgMS4wNjc1LCAwLjk2MjI1LCAxLjA2NzUsIDEuMDMyNiwgMC43NDgxNywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wMzc1NCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC44NzUzMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45ODcwNSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45ODQ0OCwgMC45OTczLCAwLjk4NDQ4LCAwLjk5NzMsIDAuOTg0NDgsIDAuOTk3MywgMC44MzA4OSwgMC45Njc3NywgMSwgMS4yMDA4OCwgMC44OTkwMywgMSwgMSwgMC43NTE1NSwgMC45NDk0NSwgMC45NDk0NSwgMC45NDk0NSwgMC45NDk0NSwgMS4xMjMxNywgMS4xMjMxNywgMS4xMjMxNywgMC42NzYwMywgMC42NzYwMywgMS4xNTYyMSwgMC43MzU4NCwgMS4yMTE5MSwgMS4yMjEzNSwgMS4wNjQ4MywgMC45NDg2OCwgMC45NDg2OCwgMC45NTk5NiwgMS4yNDYzMywgMSwgMS4wNzQ5NywgMC44NzcwOSwgMC45NjkyNywgMS4wMTQ3MywgMC45NjkyNywgMSwgMSwgMSwgMC43NzI5NSwgMSwgMSwgMS4wOTgzNiwgMS4wOTgzNiwgMS4wOTgzNiwgMS4wMTUyMiwgMC44NjMyMSwgMC45NDQzNCwgMC44NjQ5LCAwLjk0NDM0LCAwLjg2MTgyLCAxLCAxLCAxLjA4MywgMSwgMC45MTU3OCwgMC44NjQzOCwgMS4xNzMwOCwgMS4xODQxNiwgMS4xNDU4OSwgMC42OTgyNSwgMC45NzYyMiwgMS45Njc5MSwgMS4yNDgyMiwgMS4yNDgyMiwgMS4xNzMwOCwgMS4yNDgyMiwgMS4yNDgyMiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS40MjYwMywgMSwgMC45OTg2MiwgMC45OTg2MiwgMSwgMC44NzAyNSwgMC44NzAyNSwgMC44NzAyNSwgMC44NzAyNSwgMS4xNzk4NCwgMS40MjYwMywgMSwgMS40MjYwMywgMS40MjYwMywgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMS4yODg2LCAxLjA0MzE1LCAxLjE1Mjk2LCAxLjM0MTYzLCAxLCAxLCAxLCAxLjEwNzQyLCAxLjEwNzQyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKY29uc3QgU2Vnb2V1aUl0YWxpY01ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4zMzAwOCwKICBsaW5lR2FwOiAwCn07CmNvbnN0IFNlZ29ldWlSZWd1bGFyRmFjdG9ycyA9IFsxLjc2NzM4LCAxLCAxLCAwLjk4NTk0LCAxLjAyMjg1LCAxLjEwNDU0LCAxLjA2MjM0LCAwLjk2OTI3LCAwLjkyMDM3LCAxLjE5OTg1LCAxLjIwNDYsIDAuOTA2MTYsIDAuOTA2MTYsIDEuMDcxNTIsIDEuMTcxNCwgMC43ODAzMiwgMS4yMDA4OCwgMC43ODAzMiwgMS40MDI0NiwgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC43ODAzMiwgMC43ODAzMiwgMS4xNzE0LCAxLjE3MTQsIDEuMTcxNCwgMC44MDU5NywgMC45NDA4NCwgMC45NjcwNiwgMC44NTk0NCwgMC44NTczNCwgMC45NzA5MywgMC43NTg0MiwgMC43OTkzNiwgMC44ODE5OCwgMC45ODMxLCAwLjk1NzgyLCAwLjcxMzg3LCAwLjg2OTY5LCAwLjg0NjM2LCAxLjA3Nzk2LCAxLjAzNTg0LCAwLjk2OTI0LCAwLjgzOTY4LCAwLjk2OTI0LCAwLjgyODI2LCAwLjc5NjQ5LCAwLjg1NzcxLCAwLjk1MTMyLCAwLjkzMTE5LCAwLjk4OTY1LCAwLjg4NDMzLCAwLjgyODcsIDAuOTMzNjUsIDEuMDg2MTIsIDEuMzYzOCwgMS4wODYxMiwgMS40NTc4NiwgMC43NDYyNywgMC44MDQ5OSwgMC45MTQ4NCwgMS4wNTcwNywgMC45MjM4MywgMS4wNTg4MiwgMC45NDAzLCAxLjEyNjU0LCAxLjA1ODgyLCAxLjAxNzU2LCAxLjA5MDExLCAxLjA5MDExLCAwLjk5NDE0LCAxLjA5MDExLCAxLjAzNCwgMS4wMTc1NiwgMS4wNTM1NiwgMS4wNTcwNywgMS4wNTg4MiwgMS4wNDM5OSwgMC44NDg2MywgMS4yMTk2OCwgMS4wMTc1NiwgMC45NTgwMSwgMS4wMDA2OCwgMC45MTc5NywgMC45Njc3NywgMC45MDQzLCAwLjkwMzUxLCAwLjkyMTA1LCAwLjkwMzUxLCAxLjE3MTQsIDAuODUzMzcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTk5MTIsIDAuOTY5MjcsIDAuOTIxMDUsIDAuODA1OTcsIDEuMjQzNCwgMS4yMDgwOCwgMS4wNTkzNywgMC45MDk1NywgMS4xNzE0LCAxLjIwODA4LCAwLjc1MTU1LCAwLjk0MjYxLCAxLjI0NjQ0LCAxLjA5OTcxLCAxLjA5OTcxLCAwLjg0NzUxLCAxLCAwLjg1MjczLCAwLjc4MDMyLCAwLjYxNTg0LCAxLjA1NDI1LCAxLjE3OTE0LCAwLjkwOTU3LCAxLjA4NjY1LCAxLjExNTkzLCAxLjE0MTY5LCAwLjczMzgxLCAwLjk2NzA2LCAwLjk2NzA2LCAwLjk2NzA2LCAwLjk2NzA2LCAwLjk2NzA2LCAwLjk2NzA2LCAwLjg2MDM1LCAwLjg1NzM0LCAwLjc1ODQyLCAwLjc1ODQyLCAwLjc1ODQyLCAwLjc1ODQyLCAwLjk1NzgyLCAwLjk1NzgyLCAwLjk1NzgyLCAwLjk1NzgyLCAwLjk3MDkzLCAxLjAzNTg0LCAwLjk2OTI0LCAwLjk2OTI0LCAwLjk2OTI0LCAwLjk2OTI0LCAwLjk2OTI0LCAxLjE3MTQsIDAuOTY5MjQsIDAuOTUxMzIsIDAuOTUxMzIsIDAuOTUxMzIsIDAuOTUxMzIsIDAuODI4NywgMC44Mzk2OCwgMC44OTA0OSwgMC45MTQ4NCwgMC45MTQ4NCwgMC45MTQ4NCwgMC45MTQ4NCwgMC45MTQ4NCwgMC45MTQ4NCwgMC45MzU3NSwgMC45MjM4MywgMC45NDAzLCAwLjk0MDMsIDAuOTQwMywgMC45NDAzLCAwLjg3MTcsIDAuODcxNywgMC44NzE3LCAwLjg3MTcsIDEuMDA1MjcsIDEuMDE3NTYsIDEuMDUzNTYsIDEuMDUzNTYsIDEuMDUzNTYsIDEuMDUzNTYsIDEuMDUzNTYsIDEuMjQ2NDQsIDAuOTU5MjMsIDEuMDE3NTYsIDEuMDE3NTYsIDEuMDE3NTYsIDEuMDE3NTYsIDAuOTY3NzcsIDEuMDU3MDcsIDAuOTY3NzcsIDAuOTY3MDYsIDAuOTE0ODQsIDAuOTY3MDYsIDAuOTE0ODQsIDAuOTY3MDYsIDAuOTE0ODQsIDAuODU3MzQsIDAuOTIzODMsIDAuODU3MzQsIDAuOTIzODMsIDAuODU3MzQsIDAuOTIzODMsIDAuODU3MzQsIDAuOTIzODMsIDAuOTcwOTMsIDEuMDk2OSwgMC45NzA5MywgMS4wNTg4MiwgMC43NTg0MiwgMC45NDAzLCAwLjc1ODQyLCAwLjk0MDMsIDAuNzU4NDIsIDAuOTQwMywgMC43NTg0MiwgMC45NDAzLCAwLjc1ODQyLCAwLjk0MDMsIDAuODgxOTgsIDEuMDU4ODIsIDAuODgxOTgsIDEuMDU4ODIsIDAuODgxOTgsIDEuMDU4ODIsIDEsIDEsIDAuOTgzMSwgMS4wMTc1NiwgMC45ODMxLCAxLjAxNzU2LCAwLjk1NzgyLCAwLjg3MTcsIDAuOTU3ODIsIDAuODcxNywgMC45NTc4MiwgMC44NzE3LCAwLjk1NzgyLCAxLjA5MDExLCAwLjk1NzgyLCAwLjg3MTcsIDAuODQ3ODQsIDEuMTE1NTEsIDAuNzEzODcsIDEuMDkwMTEsIDEsIDEsIDAuOTk0MTQsIDAuODQ2MzYsIDEuMDkwMTEsIDEsIDEsIDAuODQ2MzYsIDEuMDUzNiwgMC44NDYzNiwgMC45NDI5OCwgMC44NDYzNiwgMS4yMzI5NywgMS4wMzU4NCwgMS4wMTc1NiwgMSwgMSwgMS4wMzU4NCwgMS4wMTc1NiwgMS4wMDMyMywgMS4wMzQ0NCwgMS4wMTc1NiwgMC45NjkyNCwgMS4wNTM1NiwgMC45NjkyNCwgMS4wNTM1NiwgMC45NjkyNCwgMS4wNTM1NiwgMC45MzA2NiwgMC45ODI5MywgMC44MjgyNiwgMS4wNDM5OSwgMSwgMSwgMC44MjgyNiwgMS4wNDM5OSwgMC43OTY0OSwgMC44NDg2MywgMC43OTY0OSwgMC44NDg2MywgMC43OTY0OSwgMC44NDg2MywgMC43OTY0OSwgMC44NDg2MywgMSwgMSwgMC44NTc3MSwgMS4xNzMxOCwgMC44NTc3MSwgMS4yMTk2OCwgMC45NTEzMiwgMS4wMTc1NiwgMC45NTEzMiwgMS4wMTc1NiwgMC45NTEzMiwgMS4wMTc1NiwgMC45NTEzMiwgMS4wMTc1NiwgMC45NTEzMiwgMS4wMTc1NiwgMC45NTEzMiwgMS4wMTc1NiwgMC45ODk2NSwgMS4wMDA2OCwgMC44Mjg3LCAwLjk2Nzc3LCAwLjgyODcsIDAuOTMzNjUsIDAuOTA0MywgMC45MzM2NSwgMC45MDQzLCAwLjkzMzY1LCAwLjkwNDMsIDEuMDg1NzEsIDAuOTY5MjcsIDAuOTY3MDYsIDAuOTE0ODQsIDAuODYwMzUsIDAuOTM1NzUsIDAuOTY5MjQsIDAuOTU5MjMsIDEsIDEsIDAuODU3NzEsIDEuMjE5NjgsIDEuMTE0MzcsIDEuMTE0MzcsIDAuOTMxMDksIDAuOTEyMDIsIDAuNjA0MTEsIDAuODQxNjQsIDAuNTU1NzIsIDEuMDExNzMsIDAuOTczNjEsIDAuODE4MTgsIDAuODE4MTgsIDAuOTY2MzUsIDAuNzgwMzIsIDAuNzI3MjcsIDAuOTIzNjYsIDAuOTg2MDEsIDEuMDM0MDUsIDAuNzc5NjgsIDEuMDk3OTksIDEuMiwgMC45NjcwNiwgMC44NTk0NCwgMC44NTYzOCwgMC45NjQ5MSwgMC43NTg0MiwgMC45MzM2NSwgMC45ODMxLCAwLjk2OTI0LCAwLjk1NzgyLCAwLjg2OTY5LCAwLjk0MTUyLCAxLjA3Nzk2LCAxLjAzNTg0LCAwLjc4NDM3LCAwLjk2OTI0LCAwLjk4NzE1LCAwLjgzOTY4LCAwLjgzNDkxLCAwLjg1NzcxLCAwLjgyODcsIDAuOTQ0OTIsIDAuODg0MzMsIDAuOTI4NywgMS4wMDk4LCAwLjk1NzgyLCAwLjgyODcsIDEuMDYyNSwgMC45ODI0OCwgMS4wMzQyNCwgMS4yLCAxLjAxMDcxLCAxLjA2MjUsIDAuOTUyNDYsIDEuMDM4MDksIDEuMDQ5MTIsIDAuOTgyNDgsIDEuMDAyMjEsIDEuMDM0MjQsIDEuMDU0NDMsIDEuMiwgMS4wNDc4NSwgMC45OTYwOSwgMS4wMDE2OSwgMS4wNTE3NiwgMC45OTM0NiwgMS4wNTM1NiwgMC45MDg3LCAxLjAzMDA0LCAwLjk1NTQyLCAwLjkzMTE3LCAxLjIzMzYyLCAxLjAxMDcxLCAxLjA3ODMxLCAxLjAyNTEyLCAxLjA1MjA1LCAxLjAzNTAyLCAxLjIsIDEuMDEwNzEsIDEuMDUzNTYsIDEuMDEwNzEsIDEuMDM1MDIsIDAuNzU4NDIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDM3MTksIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTQwMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wNDAyMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45ODk2NSwgMS4wMDA2OCwgMC45ODk2NSwgMS4wMDA2OCwgMC45ODk2NSwgMS4wMDA2OCwgMC44Mjg3LCAwLjk2Nzc3LCAxLCAxLjIwMDg4LCAwLjg5OTAzLCAxLCAxLCAwLjc1MTU1LCAxLjAzMDc3LCAxLjAzMDc3LCAxLjAzMDc3LCAxLjAzMDc3LCAxLjEzMTk2LCAxLjEzMTk2LCAxLjEzMTk2LCAwLjY3NDI4LCAwLjY3NDI4LCAxLjE2MDM5LCAwLjczMjkxLCAxLjIwOTk2LCAxLjIyMTM1LCAxLjA2NDgzLCAwLjk0ODY4LCAwLjk0ODY4LCAwLjk1OTk2LCAxLjI0NjMzLCAxLCAxLjA3NDk3LCAwLjg3Nzk2LCAwLjk2OTI3LCAxLjAxNTE4LCAwLjk2OTI3LCAxLCAxLCAxLCAwLjc3Mjk1LCAxLCAxLCAxLjEwNTM5LCAxLjEwNTM5LCAxLjExMzU4LCAxLjA2OTY3LCAwLjg2Mjc5LCAwLjk0NDM0LCAwLjg2Mjc5LCAwLjk0NDM0LCAwLjg2MTgyLCAxLCAxLCAxLjA4MywgMSwgMC45MTU3OCwgMC44NjUwNywgMS4xNzE0LCAxLjE4NDE2LCAxLjE0NTg5LCAwLjY5ODI1LCAwLjk3NjIyLCAxLjk2OTcsIDEuMjQ4MjIsIDEuMjQ4MjIsIDEuMTcyMzgsIDEuMjQ4MjIsIDEuMjQ4MjIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuNDI2MDMsIDEsIDAuOTk4NjIsIDAuOTk4NjIsIDEsIDAuODcwMjUsIDAuODcwMjUsIDAuODcwMjUsIDAuODcwMjUsIDEuMTgwODMsIDEuNDI2MDMsIDEsIDEuNDI2MDMsIDEuNDI2MDMsIDAuOTk4NjIsIDEsIDEsIDEsIDEsIDEsIDEuMjg4NiwgMS4wNDMxNSwgMS4xNTI5NiwgMS4zNDE2MywgMSwgMSwgMSwgMS4xMDkzOCwgMS4xMDkzOCwgMSwgMSwgMSwgMS4wNTQyNSwgMS4wOTk3MSwgMS4wOTk3MSwgMS4wOTk3MSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmNvbnN0IFNlZ29ldWlSZWd1bGFyTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjMzMDA4LAogIGxpbmVHYXA6IDAKfTsKCjsvLyAuL3NyYy9jb3JlL3hmYV9mb250cy5qcwoKCgoKCgoKCmNvbnN0IGdldFhGQUZvbnRNYXAgPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICB0WyJNeXJpYWRQcm8tUmVndWxhciJdID0gdFsiUGRmSlMtRmFsbGJhY2stUmVndWxhciJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIiLAogICAgZmFjdG9yczogTXlyaWFkUHJvUmVndWxhckZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc1JlZ3VsYXJXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNSZWd1bGFyTWFwcGluZywKICAgIG1ldHJpY3M6IE15cmlhZFByb1JlZ3VsYXJNZXRyaWNzCiAgfTsKICB0WyJNeXJpYWRQcm8tQm9sZCJdID0gdFsiUGRmSlMtRmFsbGJhY2stQm9sZCJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUJvbGQiLAogICAgZmFjdG9yczogTXlyaWFkUHJvQm9sZEZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0JvbGRXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNCb2xkTWFwcGluZywKICAgIG1ldHJpY3M6IE15cmlhZFByb0JvbGRNZXRyaWNzCiAgfTsKICB0WyJNeXJpYWRQcm8tSXQiXSA9IHRbIk15cmlhZFByby1JdGFsaWMiXSA9IHRbIlBkZkpTLUZhbGxiYWNrLUl0YWxpYyJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUl0YWxpYyIsCiAgICBmYWN0b3JzOiBNeXJpYWRQcm9JdGFsaWNGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNJdGFsaWNXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNJdGFsaWNNYXBwaW5nLAogICAgbWV0cmljczogTXlyaWFkUHJvSXRhbGljTWV0cmljcwogIH07CiAgdFsiTXlyaWFkUHJvLUJvbGRJdCJdID0gdFsiTXlyaWFkUHJvLUJvbGRJdGFsaWMiXSA9IHRbIlBkZkpTLUZhbGxiYWNrLUJvbGRJdGFsaWMiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1Cb2xkSXRhbGljIiwKICAgIGZhY3RvcnM6IE15cmlhZFByb0JvbGRJdGFsaWNGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNCb2xkSXRhbGljV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zQm9sZEl0YWxpY01hcHBpbmcsCiAgICBtZXRyaWNzOiBNeXJpYWRQcm9Cb2xkSXRhbGljTWV0cmljcwogIH07CiAgdC5BcmlhbE1UID0gdC5BcmlhbCA9IHRbIkFyaWFsLVJlZ3VsYXIiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1SZWd1bGFyIiwKICAgIGJhc2VXaWR0aHM6IExpYmVyYXRpb25TYW5zUmVndWxhcldpZHRocywKICAgIGJhc2VNYXBwaW5nOiBMaWJlcmF0aW9uU2Fuc1JlZ3VsYXJNYXBwaW5nCiAgfTsKICB0WyJBcmlhbC1Cb2xkTVQiXSA9IHRbIkFyaWFsLUJvbGQiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1Cb2xkIiwKICAgIGJhc2VXaWR0aHM6IExpYmVyYXRpb25TYW5zQm9sZFdpZHRocywKICAgIGJhc2VNYXBwaW5nOiBMaWJlcmF0aW9uU2Fuc0JvbGRNYXBwaW5nCiAgfTsKICB0WyJBcmlhbC1JdGFsaWNNVCJdID0gdFsiQXJpYWwtSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtSXRhbGljIiwKICAgIGJhc2VXaWR0aHM6IExpYmVyYXRpb25TYW5zSXRhbGljV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zSXRhbGljTWFwcGluZwogIH07CiAgdFsiQXJpYWwtQm9sZEl0YWxpY01UIl0gPSB0WyJBcmlhbC1Cb2xkSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYyIsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0JvbGRJdGFsaWNXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNCb2xkSXRhbGljTWFwcGluZwogIH07CiAgdFsiQ2FsaWJyaS1SZWd1bGFyIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtUmVndWxhciIsCiAgICBmYWN0b3JzOiBDYWxpYnJpUmVndWxhckZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc1JlZ3VsYXJXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNSZWd1bGFyTWFwcGluZywKICAgIG1ldHJpY3M6IENhbGlicmlSZWd1bGFyTWV0cmljcwogIH07CiAgdFsiQ2FsaWJyaS1Cb2xkIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZCIsCiAgICBmYWN0b3JzOiBDYWxpYnJpQm9sZEZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0JvbGRXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNCb2xkTWFwcGluZywKICAgIG1ldHJpY3M6IENhbGlicmlCb2xkTWV0cmljcwogIH07CiAgdFsiQ2FsaWJyaS1JdGFsaWMiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiLAogICAgZmFjdG9yczogQ2FsaWJyaUl0YWxpY0ZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0l0YWxpY1dpZHRocywKICAgIGJhc2VNYXBwaW5nOiBMaWJlcmF0aW9uU2Fuc0l0YWxpY01hcHBpbmcsCiAgICBtZXRyaWNzOiBDYWxpYnJpSXRhbGljTWV0cmljcwogIH07CiAgdFsiQ2FsaWJyaS1Cb2xkSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYyIsCiAgICBmYWN0b3JzOiBDYWxpYnJpQm9sZEl0YWxpY0ZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0JvbGRJdGFsaWNXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNCb2xkSXRhbGljTWFwcGluZywKICAgIG1ldHJpY3M6IENhbGlicmlCb2xkSXRhbGljTWV0cmljcwogIH07CiAgdFsiU2Vnb2V1aS1SZWd1bGFyIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtUmVndWxhciIsCiAgICBmYWN0b3JzOiBTZWdvZXVpUmVndWxhckZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc1JlZ3VsYXJXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNSZWd1bGFyTWFwcGluZywKICAgIG1ldHJpY3M6IFNlZ29ldWlSZWd1bGFyTWV0cmljcwogIH07CiAgdFsiU2Vnb2V1aS1Cb2xkIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZCIsCiAgICBmYWN0b3JzOiBTZWdvZXVpQm9sZEZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0JvbGRXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNCb2xkTWFwcGluZywKICAgIG1ldHJpY3M6IFNlZ29ldWlCb2xkTWV0cmljcwogIH07CiAgdFsiU2Vnb2V1aS1JdGFsaWMiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiLAogICAgZmFjdG9yczogU2Vnb2V1aUl0YWxpY0ZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0l0YWxpY1dpZHRocywKICAgIGJhc2VNYXBwaW5nOiBMaWJlcmF0aW9uU2Fuc0l0YWxpY01hcHBpbmcsCiAgICBtZXRyaWNzOiBTZWdvZXVpSXRhbGljTWV0cmljcwogIH07CiAgdFsiU2Vnb2V1aS1Cb2xkSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYyIsCiAgICBmYWN0b3JzOiBTZWdvZXVpQm9sZEl0YWxpY0ZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0JvbGRJdGFsaWNXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNCb2xkSXRhbGljTWFwcGluZywKICAgIG1ldHJpY3M6IFNlZ29ldWlCb2xkSXRhbGljTWV0cmljcwogIH07CiAgdFsiSGVsdmV0aWNhLVJlZ3VsYXIiXSA9IHQuSGVsdmV0aWNhID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIiLAogICAgZmFjdG9yczogSGVsdmV0aWNhUmVndWxhckZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc1JlZ3VsYXJXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNSZWd1bGFyTWFwcGluZywKICAgIG1ldHJpY3M6IEhlbHZldGljYVJlZ3VsYXJNZXRyaWNzCiAgfTsKICB0WyJIZWx2ZXRpY2EtQm9sZCJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUJvbGQiLAogICAgZmFjdG9yczogSGVsdmV0aWNhQm9sZEZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0JvbGRXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNCb2xkTWFwcGluZywKICAgIG1ldHJpY3M6IEhlbHZldGljYUJvbGRNZXRyaWNzCiAgfTsKICB0WyJIZWx2ZXRpY2EtSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtSXRhbGljIiwKICAgIGZhY3RvcnM6IEhlbHZldGljYUl0YWxpY0ZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0l0YWxpY1dpZHRocywKICAgIGJhc2VNYXBwaW5nOiBMaWJlcmF0aW9uU2Fuc0l0YWxpY01hcHBpbmcsCiAgICBtZXRyaWNzOiBIZWx2ZXRpY2FJdGFsaWNNZXRyaWNzCiAgfTsKICB0WyJIZWx2ZXRpY2EtQm9sZEl0YWxpYyJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUJvbGRJdGFsaWMiLAogICAgZmFjdG9yczogSGVsdmV0aWNhQm9sZEl0YWxpY0ZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0JvbGRJdGFsaWNXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNCb2xkSXRhbGljTWFwcGluZywKICAgIG1ldHJpY3M6IEhlbHZldGljYUJvbGRJdGFsaWNNZXRyaWNzCiAgfTsKfSk7CmZ1bmN0aW9uIGdldFhmYUZvbnROYW1lKG5hbWUpIHsKICBjb25zdCBmb250TmFtZSA9IG5vcm1hbGl6ZUZvbnROYW1lKG5hbWUpOwogIGNvbnN0IGZvbnRNYXAgPSBnZXRYRkFGb250TWFwKCk7CiAgcmV0dXJuIGZvbnRNYXBbZm9udE5hbWVdOwp9CmZ1bmN0aW9uIGdldFhmYUZvbnRXaWR0aHMobmFtZSkgewogIGNvbnN0IGluZm8gPSBnZXRYZmFGb250TmFtZShuYW1lKTsKICBpZiAoIWluZm8pIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCB7CiAgICBiYXNlV2lkdGhzLAogICAgYmFzZU1hcHBpbmcsCiAgICBmYWN0b3JzCiAgfSA9IGluZm87CiAgY29uc3QgcmVzY2FsZWRCYXNlV2lkdGhzID0gIWZhY3RvcnMgPyBiYXNlV2lkdGhzIDogYmFzZVdpZHRocy5tYXAoKHcsIGkpID0+IHcgKiBmYWN0b3JzW2ldKTsKICBsZXQgY3VycmVudENvZGUgPSAtMjsKICBsZXQgY3VycmVudEFycmF5OwogIGNvbnN0IG5ld1dpZHRocyA9IFtdOwogIGZvciAoY29uc3QgW3VuaWNvZGUsIGdseXBoSW5kZXhdIG9mIGJhc2VNYXBwaW5nLm1hcCgoY2hhclVuaWNvZGUsIGluZGV4KSA9PiBbY2hhclVuaWNvZGUsIGluZGV4XSkuc29ydCgoW3VuaWNvZGUxXSwgW3VuaWNvZGUyXSkgPT4gdW5pY29kZTEgLSB1bmljb2RlMikpIHsKICAgIGlmICh1bmljb2RlID09PSAtMSkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGlmICh1bmljb2RlID09PSBjdXJyZW50Q29kZSArIDEpIHsKICAgICAgY3VycmVudEFycmF5LnB1c2gocmVzY2FsZWRCYXNlV2lkdGhzW2dseXBoSW5kZXhdKTsKICAgICAgY3VycmVudENvZGUgKz0gMTsKICAgIH0gZWxzZSB7CiAgICAgIGN1cnJlbnRDb2RlID0gdW5pY29kZTsKICAgICAgY3VycmVudEFycmF5ID0gW3Jlc2NhbGVkQmFzZVdpZHRoc1tnbHlwaEluZGV4XV07CiAgICAgIG5ld1dpZHRocy5wdXNoKHVuaWNvZGUsIGN1cnJlbnRBcnJheSk7CiAgICB9CiAgfQogIHJldHVybiBuZXdXaWR0aHM7Cn0KZnVuY3Rpb24gZ2V0WGZhRm9udERpY3QobmFtZSkgewogIGNvbnN0IHdpZHRocyA9IGdldFhmYUZvbnRXaWR0aHMobmFtZSk7CiAgY29uc3QgZGljdCA9IG5ldyBEaWN0KG51bGwpOwogIGRpY3Quc2V0KCJCYXNlRm9udCIsIE5hbWUuZ2V0KG5hbWUpKTsKICBkaWN0LnNldCgiVHlwZSIsIE5hbWUuZ2V0KCJGb250IikpOwogIGRpY3Quc2V0KCJTdWJ0eXBlIiwgTmFtZS5nZXQoIkNJREZvbnRUeXBlMiIpKTsKICBkaWN0LnNldCgiRW5jb2RpbmciLCBOYW1lLmdldCgiSWRlbnRpdHktSCIpKTsKICBkaWN0LnNldCgiQ0lEVG9HSURNYXAiLCBOYW1lLmdldCgiSWRlbnRpdHkiKSk7CiAgZGljdC5zZXQoIlciLCB3aWR0aHMpOwogIGRpY3Quc2V0KCJGaXJzdENoYXIiLCB3aWR0aHNbMF0pOwogIGRpY3Quc2V0KCJMYXN0Q2hhciIsIHdpZHRocy5hdCgtMikgKyB3aWR0aHMuYXQoLTEpLmxlbmd0aCAtIDEpOwogIGNvbnN0IGRlc2NyaXB0b3IgPSBuZXcgRGljdChudWxsKTsKICBkaWN0LnNldCgiRm9udERlc2NyaXB0b3IiLCBkZXNjcmlwdG9yKTsKICBjb25zdCBzeXN0ZW1JbmZvID0gbmV3IERpY3QobnVsbCk7CiAgc3lzdGVtSW5mby5zZXQoIk9yZGVyaW5nIiwgIklkZW50aXR5Iik7CiAgc3lzdGVtSW5mby5zZXQoIlJlZ2lzdHJ5IiwgIkFkb2JlIik7CiAgc3lzdGVtSW5mby5zZXQoIlN1cHBsZW1lbnQiLCAwKTsKICBkaWN0LnNldCgiQ0lEU3lzdGVtSW5mbyIsIHN5c3RlbUluZm8pOwogIHJldHVybiBkaWN0Owp9Cgo7Ly8gLi9zcmMvY29yZS9wc19wYXJzZXIuanMKCgoKY2xhc3MgUG9zdFNjcmlwdFBhcnNlciB7CiAgY29uc3RydWN0b3IobGV4ZXIpIHsKICAgIHRoaXMubGV4ZXIgPSBsZXhlcjsKICAgIHRoaXMub3BlcmF0b3JzID0gW107CiAgICB0aGlzLnRva2VuID0gbnVsbDsKICAgIHRoaXMucHJldiA9IG51bGw7CiAgfQogIG5leHRUb2tlbigpIHsKICAgIHRoaXMucHJldiA9IHRoaXMudG9rZW47CiAgICB0aGlzLnRva2VuID0gdGhpcy5sZXhlci5nZXRUb2tlbigpOwogIH0KICBhY2NlcHQodHlwZSkgewogICAgaWYgKHRoaXMudG9rZW4udHlwZSA9PT0gdHlwZSkgewogICAgICB0aGlzLm5leHRUb2tlbigpOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9CiAgZXhwZWN0KHR5cGUpIHsKICAgIGlmICh0aGlzLmFjY2VwdCh0eXBlKSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgVW5leHBlY3RlZCBzeW1ib2w6IGZvdW5kICR7dGhpcy50b2tlbi50eXBlfSBleHBlY3RlZCAke3R5cGV9LmApOwogIH0KICBwYXJzZSgpIHsKICAgIHRoaXMubmV4dFRva2VuKCk7CiAgICB0aGlzLmV4cGVjdChQb3N0U2NyaXB0VG9rZW5UeXBlcy5MQlJBQ0UpOwogICAgdGhpcy5wYXJzZUJsb2NrKCk7CiAgICB0aGlzLmV4cGVjdChQb3N0U2NyaXB0VG9rZW5UeXBlcy5SQlJBQ0UpOwogICAgcmV0dXJuIHRoaXMub3BlcmF0b3JzOwogIH0KICBwYXJzZUJsb2NrKCkgewogICAgd2hpbGUgKHRydWUpIHsKICAgICAgaWYgKHRoaXMuYWNjZXB0KFBvc3RTY3JpcHRUb2tlblR5cGVzLk5VTUJFUikpIHsKICAgICAgICB0aGlzLm9wZXJhdG9ycy5wdXNoKHRoaXMucHJldi52YWx1ZSk7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5hY2NlcHQoUG9zdFNjcmlwdFRva2VuVHlwZXMuT1BFUkFUT1IpKSB7CiAgICAgICAgdGhpcy5vcGVyYXRvcnMucHVzaCh0aGlzLnByZXYudmFsdWUpOwogICAgICB9IGVsc2UgaWYgKHRoaXMuYWNjZXB0KFBvc3RTY3JpcHRUb2tlblR5cGVzLkxCUkFDRSkpIHsKICAgICAgICB0aGlzLnBhcnNlQ29uZGl0aW9uKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICB9CiAgfQogIHBhcnNlQ29uZGl0aW9uKCkgewogICAgY29uc3QgY29uZGl0aW9uTG9jYXRpb24gPSB0aGlzLm9wZXJhdG9ycy5sZW5ndGg7CiAgICB0aGlzLm9wZXJhdG9ycy5wdXNoKG51bGwsIG51bGwpOwogICAgdGhpcy5wYXJzZUJsb2NrKCk7CiAgICB0aGlzLmV4cGVjdChQb3N0U2NyaXB0VG9rZW5UeXBlcy5SQlJBQ0UpOwogICAgaWYgKHRoaXMuYWNjZXB0KFBvc3RTY3JpcHRUb2tlblR5cGVzLklGKSkgewogICAgICB0aGlzLm9wZXJhdG9yc1tjb25kaXRpb25Mb2NhdGlvbl0gPSB0aGlzLm9wZXJhdG9ycy5sZW5ndGg7CiAgICAgIHRoaXMub3BlcmF0b3JzW2NvbmRpdGlvbkxvY2F0aW9uICsgMV0gPSAianoiOwogICAgfSBlbHNlIGlmICh0aGlzLmFjY2VwdChQb3N0U2NyaXB0VG9rZW5UeXBlcy5MQlJBQ0UpKSB7CiAgICAgIGNvbnN0IGp1bXBMb2NhdGlvbiA9IHRoaXMub3BlcmF0b3JzLmxlbmd0aDsKICAgICAgdGhpcy5vcGVyYXRvcnMucHVzaChudWxsLCBudWxsKTsKICAgICAgY29uc3QgZW5kT2ZUcnVlID0gdGhpcy5vcGVyYXRvcnMubGVuZ3RoOwogICAgICB0aGlzLnBhcnNlQmxvY2soKTsKICAgICAgdGhpcy5leHBlY3QoUG9zdFNjcmlwdFRva2VuVHlwZXMuUkJSQUNFKTsKICAgICAgdGhpcy5leHBlY3QoUG9zdFNjcmlwdFRva2VuVHlwZXMuSUZFTFNFKTsKICAgICAgdGhpcy5vcGVyYXRvcnNbanVtcExvY2F0aW9uXSA9IHRoaXMub3BlcmF0b3JzLmxlbmd0aDsKICAgICAgdGhpcy5vcGVyYXRvcnNbanVtcExvY2F0aW9uICsgMV0gPSAiaiI7CiAgICAgIHRoaXMub3BlcmF0b3JzW2NvbmRpdGlvbkxvY2F0aW9uXSA9IGVuZE9mVHJ1ZTsKICAgICAgdGhpcy5vcGVyYXRvcnNbY29uZGl0aW9uTG9jYXRpb24gKyAxXSA9ICJqeiI7CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlBTIEZ1bmN0aW9uOiBlcnJvciBwYXJzaW5nIGNvbmRpdGlvbmFsLiIpOwogICAgfQogIH0KfQpjb25zdCBQb3N0U2NyaXB0VG9rZW5UeXBlcyA9IHsKICBMQlJBQ0U6IDAsCiAgUkJSQUNFOiAxLAogIE5VTUJFUjogMiwKICBPUEVSQVRPUjogMywKICBJRjogNCwKICBJRkVMU0U6IDUKfTsKY2xhc3MgUG9zdFNjcmlwdFRva2VuIHsKICBzdGF0aWMgZ2V0IG9wQ2FjaGUoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJvcENhY2hlIiwgT2JqZWN0LmNyZWF0ZShudWxsKSk7CiAgfQogIGNvbnN0cnVjdG9yKHR5cGUsIHZhbHVlKSB7CiAgICB0aGlzLnR5cGUgPSB0eXBlOwogICAgdGhpcy52YWx1ZSA9IHZhbHVlOwogIH0KICBzdGF0aWMgZ2V0T3BlcmF0b3Iob3ApIHsKICAgIHJldHVybiBQb3N0U2NyaXB0VG9rZW4ub3BDYWNoZVtvcF0gfHw9IG5ldyBQb3N0U2NyaXB0VG9rZW4oUG9zdFNjcmlwdFRva2VuVHlwZXMuT1BFUkFUT1IsIG9wKTsKICB9CiAgc3RhdGljIGdldCBMQlJBQ0UoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJMQlJBQ0UiLCBuZXcgUG9zdFNjcmlwdFRva2VuKFBvc3RTY3JpcHRUb2tlblR5cGVzLkxCUkFDRSwgInsiKSk7CiAgfQogIHN0YXRpYyBnZXQgUkJSQUNFKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiUkJSQUNFIiwgbmV3IFBvc3RTY3JpcHRUb2tlbihQb3N0U2NyaXB0VG9rZW5UeXBlcy5SQlJBQ0UsICJ9IikpOwogIH0KICBzdGF0aWMgZ2V0IElGKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiSUYiLCBuZXcgUG9zdFNjcmlwdFRva2VuKFBvc3RTY3JpcHRUb2tlblR5cGVzLklGLCAiSUYiKSk7CiAgfQogIHN0YXRpYyBnZXQgSUZFTFNFKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiSUZFTFNFIiwgbmV3IFBvc3RTY3JpcHRUb2tlbihQb3N0U2NyaXB0VG9rZW5UeXBlcy5JRkVMU0UsICJJRkVMU0UiKSk7CiAgfQp9CmNsYXNzIFBvc3RTY3JpcHRMZXhlciB7CiAgY29uc3RydWN0b3Ioc3RyZWFtKSB7CiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTsKICAgIHRoaXMubmV4dENoYXIoKTsKICAgIHRoaXMuc3RyQnVmID0gW107CiAgfQogIG5leHRDaGFyKCkgewogICAgcmV0dXJuIHRoaXMuY3VycmVudENoYXIgPSB0aGlzLnN0cmVhbS5nZXRCeXRlKCk7CiAgfQogIGdldFRva2VuKCkgewogICAgbGV0IGNvbW1lbnQgPSBmYWxzZTsKICAgIGxldCBjaCA9IHRoaXMuY3VycmVudENoYXI7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBpZiAoY2ggPCAwKSB7CiAgICAgICAgcmV0dXJuIEVPRjsKICAgICAgfQogICAgICBpZiAoY29tbWVudCkgewogICAgICAgIGlmIChjaCA9PT0gMHgwYSB8fCBjaCA9PT0gMHgwZCkgewogICAgICAgICAgY29tbWVudCA9IGZhbHNlOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChjaCA9PT0gMHgyNSkgewogICAgICAgIGNvbW1lbnQgPSB0cnVlOwogICAgICB9IGVsc2UgaWYgKCFpc1doaXRlU3BhY2UoY2gpKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICB9CiAgICBzd2l0Y2ggKGNoIHwgMCkgewogICAgICBjYXNlIDB4MzA6CiAgICAgIGNhc2UgMHgzMToKICAgICAgY2FzZSAweDMyOgogICAgICBjYXNlIDB4MzM6CiAgICAgIGNhc2UgMHgzNDoKICAgICAgY2FzZSAweDM1OgogICAgICBjYXNlIDB4MzY6CiAgICAgIGNhc2UgMHgzNzoKICAgICAgY2FzZSAweDM4OgogICAgICBjYXNlIDB4Mzk6CiAgICAgIGNhc2UgMHgyYjoKICAgICAgY2FzZSAweDJkOgogICAgICBjYXNlIDB4MmU6CiAgICAgICAgcmV0dXJuIG5ldyBQb3N0U2NyaXB0VG9rZW4oUG9zdFNjcmlwdFRva2VuVHlwZXMuTlVNQkVSLCB0aGlzLmdldE51bWJlcigpKTsKICAgICAgY2FzZSAweDdiOgogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICByZXR1cm4gUG9zdFNjcmlwdFRva2VuLkxCUkFDRTsKICAgICAgY2FzZSAweDdkOgogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICByZXR1cm4gUG9zdFNjcmlwdFRva2VuLlJCUkFDRTsKICAgIH0KICAgIGNvbnN0IHN0ckJ1ZiA9IHRoaXMuc3RyQnVmOwogICAgc3RyQnVmLmxlbmd0aCA9IDA7CiAgICBzdHJCdWZbMF0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKTsKICAgIHdoaWxlICgoY2ggPSB0aGlzLm5leHRDaGFyKCkpID49IDAgJiYgKGNoID49IDB4NDEgJiYgY2ggPD0gMHg1YSB8fCBjaCA+PSAweDYxICYmIGNoIDw9IDB4N2EpKSB7CiAgICAgIHN0ckJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpKTsKICAgIH0KICAgIGNvbnN0IHN0ciA9IHN0ckJ1Zi5qb2luKCIiKTsKICAgIHN3aXRjaCAoc3RyLnRvTG93ZXJDYXNlKCkpIHsKICAgICAgY2FzZSAiaWYiOgogICAgICAgIHJldHVybiBQb3N0U2NyaXB0VG9rZW4uSUY7CiAgICAgIGNhc2UgImlmZWxzZSI6CiAgICAgICAgcmV0dXJuIFBvc3RTY3JpcHRUb2tlbi5JRkVMU0U7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuIFBvc3RTY3JpcHRUb2tlbi5nZXRPcGVyYXRvcihzdHIpOwogICAgfQogIH0KICBnZXROdW1iZXIoKSB7CiAgICBsZXQgY2ggPSB0aGlzLmN1cnJlbnRDaGFyOwogICAgY29uc3Qgc3RyQnVmID0gdGhpcy5zdHJCdWY7CiAgICBzdHJCdWYubGVuZ3RoID0gMDsKICAgIHN0ckJ1ZlswXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpOwogICAgd2hpbGUgKChjaCA9IHRoaXMubmV4dENoYXIoKSkgPj0gMCkgewogICAgICBpZiAoY2ggPj0gMHgzMCAmJiBjaCA8PSAweDM5IHx8IGNoID09PSAweDJkIHx8IGNoID09PSAweDJlKSB7CiAgICAgICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjaCkpOwogICAgICB9IGVsc2UgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBjb25zdCB2YWx1ZSA9IHBhcnNlRmxvYXQoc3RyQnVmLmpvaW4oIiIpKTsKICAgIGlmIChpc05hTih2YWx1ZSkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIGZsb2F0aW5nIHBvaW50IG51bWJlcjogJHt2YWx1ZX1gKTsKICAgIH0KICAgIHJldHVybiB2YWx1ZTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2ltYWdlX3V0aWxzLmpzCgoKY2xhc3MgQmFzZUxvY2FsQ2FjaGUgewogIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHsKICAgIHRoaXMuX29ubHlSZWZzID0gb3B0aW9ucz8ub25seVJlZnMgPT09IHRydWU7CiAgICBpZiAoIXRoaXMuX29ubHlSZWZzKSB7CiAgICAgIHRoaXMuX25hbWVSZWZNYXAgPSBuZXcgTWFwKCk7CiAgICAgIHRoaXMuX2ltYWdlTWFwID0gbmV3IE1hcCgpOwogICAgfQogICAgdGhpcy5faW1hZ2VDYWNoZSA9IG5ldyBSZWZTZXRDYWNoZSgpOwogIH0KICBnZXRCeU5hbWUobmFtZSkgewogICAgaWYgKHRoaXMuX29ubHlSZWZzKSB7CiAgICAgIHVucmVhY2hhYmxlKCJTaG91bGQgbm90IGNhbGwgYGdldEJ5TmFtZWAgbWV0aG9kLiIpOwogICAgfQogICAgY29uc3QgcmVmID0gdGhpcy5fbmFtZVJlZk1hcC5nZXQobmFtZSk7CiAgICBpZiAocmVmKSB7CiAgICAgIHJldHVybiB0aGlzLmdldEJ5UmVmKHJlZik7CiAgICB9CiAgICByZXR1cm4gdGhpcy5faW1hZ2VNYXAuZ2V0KG5hbWUpIHx8IG51bGw7CiAgfQogIGdldEJ5UmVmKHJlZikgewogICAgcmV0dXJuIHRoaXMuX2ltYWdlQ2FjaGUuZ2V0KHJlZikgfHwgbnVsbDsKICB9CiAgc2V0KG5hbWUsIHJlZiwgZGF0YSkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgc2V0YCBjYWxsZWQuIik7CiAgfQp9CmNsYXNzIExvY2FsSW1hZ2VDYWNoZSBleHRlbmRzIEJhc2VMb2NhbENhY2hlIHsKICBzZXQobmFtZSwgcmVmID0gbnVsbCwgZGF0YSkgewogICAgaWYgKHR5cGVvZiBuYW1lICE9PSAic3RyaW5nIikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvY2FsSW1hZ2VDYWNoZS5zZXQgLSBleHBlY3RlZCAibmFtZSIgYXJndW1lbnQuJyk7CiAgICB9CiAgICBpZiAocmVmKSB7CiAgICAgIGlmICh0aGlzLl9pbWFnZUNhY2hlLmhhcyhyZWYpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHRoaXMuX25hbWVSZWZNYXAuc2V0KG5hbWUsIHJlZik7CiAgICAgIHRoaXMuX2ltYWdlQ2FjaGUucHV0KHJlZiwgZGF0YSk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0aGlzLl9pbWFnZU1hcC5oYXMobmFtZSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5faW1hZ2VNYXAuc2V0KG5hbWUsIGRhdGEpOwogIH0KfQpjbGFzcyBMb2NhbENvbG9yU3BhY2VDYWNoZSBleHRlbmRzIEJhc2VMb2NhbENhY2hlIHsKICBzZXQobmFtZSA9IG51bGwsIHJlZiA9IG51bGwsIGRhdGEpIHsKICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gInN0cmluZyIgJiYgIXJlZikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvY2FsQ29sb3JTcGFjZUNhY2hlLnNldCAtIGV4cGVjdGVkICJuYW1lIiBhbmQvb3IgInJlZiIgYXJndW1lbnQuJyk7CiAgICB9CiAgICBpZiAocmVmKSB7CiAgICAgIGlmICh0aGlzLl9pbWFnZUNhY2hlLmhhcyhyZWYpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmIChuYW1lICE9PSBudWxsKSB7CiAgICAgICAgdGhpcy5fbmFtZVJlZk1hcC5zZXQobmFtZSwgcmVmKTsKICAgICAgfQogICAgICB0aGlzLl9pbWFnZUNhY2hlLnB1dChyZWYsIGRhdGEpOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAodGhpcy5faW1hZ2VNYXAuaGFzKG5hbWUpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX2ltYWdlTWFwLnNldChuYW1lLCBkYXRhKTsKICB9Cn0KY2xhc3MgTG9jYWxGdW5jdGlvbkNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGUgewogIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHsKICAgIHN1cGVyKHsKICAgICAgb25seVJlZnM6IHRydWUKICAgIH0pOwogIH0KICBzZXQobmFtZSA9IG51bGwsIHJlZiwgZGF0YSkgewogICAgaWYgKCFyZWYpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdMb2NhbEZ1bmN0aW9uQ2FjaGUuc2V0IC0gZXhwZWN0ZWQgInJlZiIgYXJndW1lbnQuJyk7CiAgICB9CiAgICBpZiAodGhpcy5faW1hZ2VDYWNoZS5oYXMocmVmKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9pbWFnZUNhY2hlLnB1dChyZWYsIGRhdGEpOwogIH0KfQpjbGFzcyBMb2NhbEdTdGF0ZUNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGUgewogIHNldChuYW1lLCByZWYgPSBudWxsLCBkYXRhKSB7CiAgICBpZiAodHlwZW9mIG5hbWUgIT09ICJzdHJpbmciKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignTG9jYWxHU3RhdGVDYWNoZS5zZXQgLSBleHBlY3RlZCAibmFtZSIgYXJndW1lbnQuJyk7CiAgICB9CiAgICBpZiAocmVmKSB7CiAgICAgIGlmICh0aGlzLl9pbWFnZUNhY2hlLmhhcyhyZWYpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHRoaXMuX25hbWVSZWZNYXAuc2V0KG5hbWUsIHJlZik7CiAgICAgIHRoaXMuX2ltYWdlQ2FjaGUucHV0KHJlZiwgZGF0YSk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0aGlzLl9pbWFnZU1hcC5oYXMobmFtZSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5faW1hZ2VNYXAuc2V0KG5hbWUsIGRhdGEpOwogIH0KfQpjbGFzcyBMb2NhbFRpbGluZ1BhdHRlcm5DYWNoZSBleHRlbmRzIEJhc2VMb2NhbENhY2hlIHsKICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICBzdXBlcih7CiAgICAgIG9ubHlSZWZzOiB0cnVlCiAgICB9KTsKICB9CiAgc2V0KG5hbWUgPSBudWxsLCByZWYsIGRhdGEpIHsKICAgIGlmICghcmVmKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignTG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUuc2V0IC0gZXhwZWN0ZWQgInJlZiIgYXJndW1lbnQuJyk7CiAgICB9CiAgICBpZiAodGhpcy5faW1hZ2VDYWNoZS5oYXMocmVmKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9pbWFnZUNhY2hlLnB1dChyZWYsIGRhdGEpOwogIH0KfQpjbGFzcyBSZWdpb25hbEltYWdlQ2FjaGUgZXh0ZW5kcyBCYXNlTG9jYWxDYWNoZSB7CiAgY29uc3RydWN0b3Iob3B0aW9ucykgewogICAgc3VwZXIoewogICAgICBvbmx5UmVmczogdHJ1ZQogICAgfSk7CiAgfQogIHNldChuYW1lID0gbnVsbCwgcmVmLCBkYXRhKSB7CiAgICBpZiAoIXJlZikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlZ2lvbmFsSW1hZ2VDYWNoZS5zZXQgLSBleHBlY3RlZCAicmVmIiBhcmd1bWVudC4nKTsKICAgIH0KICAgIGlmICh0aGlzLl9pbWFnZUNhY2hlLmhhcyhyZWYpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX2ltYWdlQ2FjaGUucHV0KHJlZiwgZGF0YSk7CiAgfQp9CmNsYXNzIEdsb2JhbENvbG9yU3BhY2VDYWNoZSBleHRlbmRzIEJhc2VMb2NhbENhY2hlIHsKICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICBzdXBlcih7CiAgICAgIG9ubHlSZWZzOiB0cnVlCiAgICB9KTsKICB9CiAgc2V0KG5hbWUgPSBudWxsLCByZWYsIGRhdGEpIHsKICAgIGlmICghcmVmKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignR2xvYmFsQ29sb3JTcGFjZUNhY2hlLnNldCAtIGV4cGVjdGVkICJyZWYiIGFyZ3VtZW50LicpOwogICAgfQogICAgaWYgKHRoaXMuX2ltYWdlQ2FjaGUuaGFzKHJlZikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5faW1hZ2VDYWNoZS5wdXQocmVmLCBkYXRhKTsKICB9CiAgY2xlYXIoKSB7CiAgICB0aGlzLl9pbWFnZUNhY2hlLmNsZWFyKCk7CiAgfQp9CmNsYXNzIEdsb2JhbEltYWdlQ2FjaGUgewogIHN0YXRpYyBOVU1fUEFHRVNfVEhSRVNIT0xEID0gMjsKICBzdGF0aWMgTUlOX0lNQUdFU19UT19DQUNIRSA9IDEwOwogIHN0YXRpYyBNQVhfQllURV9TSVpFID0gNWU3OwogICNkZWNvZGVGYWlsZWRTZXQgPSBuZXcgUmVmU2V0KCk7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLl9yZWZDYWNoZSA9IG5ldyBSZWZTZXRDYWNoZSgpOwogICAgdGhpcy5faW1hZ2VDYWNoZSA9IG5ldyBSZWZTZXRDYWNoZSgpOwogIH0KICBnZXQgI2J5dGVTaXplKCkgewogICAgbGV0IGJ5dGVTaXplID0gMDsKICAgIGZvciAoY29uc3QgaW1hZ2VEYXRhIG9mIHRoaXMuX2ltYWdlQ2FjaGUpIHsKICAgICAgYnl0ZVNpemUgKz0gaW1hZ2VEYXRhLmJ5dGVTaXplOwogICAgfQogICAgcmV0dXJuIGJ5dGVTaXplOwogIH0KICBnZXQgI2NhY2hlTGltaXRSZWFjaGVkKCkgewogICAgaWYgKHRoaXMuX2ltYWdlQ2FjaGUuc2l6ZSA8IEdsb2JhbEltYWdlQ2FjaGUuTUlOX0lNQUdFU19UT19DQUNIRSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy4jYnl0ZVNpemUgPCBHbG9iYWxJbWFnZUNhY2hlLk1BWF9CWVRFX1NJWkUpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfQogIHNob3VsZENhY2hlKHJlZiwgcGFnZUluZGV4KSB7CiAgICBsZXQgcGFnZUluZGV4U2V0ID0gdGhpcy5fcmVmQ2FjaGUuZ2V0KHJlZik7CiAgICBpZiAoIXBhZ2VJbmRleFNldCkgewogICAgICBwYWdlSW5kZXhTZXQgPSBuZXcgU2V0KCk7CiAgICAgIHRoaXMuX3JlZkNhY2hlLnB1dChyZWYsIHBhZ2VJbmRleFNldCk7CiAgICB9CiAgICBwYWdlSW5kZXhTZXQuYWRkKHBhZ2VJbmRleCk7CiAgICBpZiAocGFnZUluZGV4U2V0LnNpemUgPCBHbG9iYWxJbWFnZUNhY2hlLk5VTV9QQUdFU19USFJFU0hPTEQpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKCF0aGlzLl9pbWFnZUNhY2hlLmhhcyhyZWYpICYmIHRoaXMuI2NhY2hlTGltaXRSZWFjaGVkKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHJldHVybiB0cnVlOwogIH0KICBhZGREZWNvZGVGYWlsZWQocmVmKSB7CiAgICB0aGlzLiNkZWNvZGVGYWlsZWRTZXQucHV0KHJlZik7CiAgfQogIGhhc0RlY29kZUZhaWxlZChyZWYpIHsKICAgIHJldHVybiB0aGlzLiNkZWNvZGVGYWlsZWRTZXQuaGFzKHJlZik7CiAgfQogIGFkZEJ5dGVTaXplKHJlZiwgYnl0ZVNpemUpIHsKICAgIGNvbnN0IGltYWdlRGF0YSA9IHRoaXMuX2ltYWdlQ2FjaGUuZ2V0KHJlZik7CiAgICBpZiAoIWltYWdlRGF0YSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoaW1hZ2VEYXRhLmJ5dGVTaXplKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGltYWdlRGF0YS5ieXRlU2l6ZSA9IGJ5dGVTaXplOwogIH0KICBnZXREYXRhKHJlZiwgcGFnZUluZGV4KSB7CiAgICBjb25zdCBwYWdlSW5kZXhTZXQgPSB0aGlzLl9yZWZDYWNoZS5nZXQocmVmKTsKICAgIGlmICghcGFnZUluZGV4U2V0KSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKHBhZ2VJbmRleFNldC5zaXplIDwgR2xvYmFsSW1hZ2VDYWNoZS5OVU1fUEFHRVNfVEhSRVNIT0xEKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgaW1hZ2VEYXRhID0gdGhpcy5faW1hZ2VDYWNoZS5nZXQocmVmKTsKICAgIGlmICghaW1hZ2VEYXRhKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcGFnZUluZGV4U2V0LmFkZChwYWdlSW5kZXgpOwogICAgcmV0dXJuIGltYWdlRGF0YTsKICB9CiAgc2V0RGF0YShyZWYsIGRhdGEpIHsKICAgIGlmICghdGhpcy5fcmVmQ2FjaGUuaGFzKHJlZikpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdHbG9iYWxJbWFnZUNhY2hlLnNldERhdGEgLSBleHBlY3RlZCAic2hvdWxkQ2FjaGUiIHRvIGhhdmUgYmVlbiBjYWxsZWQuJyk7CiAgICB9CiAgICBpZiAodGhpcy5faW1hZ2VDYWNoZS5oYXMocmVmKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAodGhpcy4jY2FjaGVMaW1pdFJlYWNoZWQpIHsKICAgICAgd2FybigiR2xvYmFsSW1hZ2VDYWNoZS5zZXREYXRhIC0gY2FjaGUgbGltaXQgcmVhY2hlZC4iKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5faW1hZ2VDYWNoZS5wdXQocmVmLCBkYXRhKTsKICB9CiAgY2xlYXIob25seURhdGEgPSBmYWxzZSkgewogICAgaWYgKCFvbmx5RGF0YSkgewogICAgICB0aGlzLiNkZWNvZGVGYWlsZWRTZXQuY2xlYXIoKTsKICAgICAgdGhpcy5fcmVmQ2FjaGUuY2xlYXIoKTsKICAgIH0KICAgIHRoaXMuX2ltYWdlQ2FjaGUuY2xlYXIoKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2Z1bmN0aW9uLmpzCgoKCgoKCmNsYXNzIFBERkZ1bmN0aW9uRmFjdG9yeSB7CiAgY29uc3RydWN0b3IoewogICAgeHJlZiwKICAgIGlzRXZhbFN1cHBvcnRlZCA9IHRydWUKICB9KSB7CiAgICB0aGlzLnhyZWYgPSB4cmVmOwogICAgdGhpcy5pc0V2YWxTdXBwb3J0ZWQgPSBpc0V2YWxTdXBwb3J0ZWQgIT09IGZhbHNlOwogIH0KICBjcmVhdGUoZm4sIHBhcnNlQXJyYXkgPSBmYWxzZSkgewogICAgbGV0IGZuUmVmLCBwYXJzZWRGbjsKICAgIGlmIChmbiBpbnN0YW5jZW9mIFJlZikgewogICAgICBmblJlZiA9IGZuOwogICAgfSBlbHNlIGlmIChmbiBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgZm5SZWYgPSBmbi5vYmpJZDsKICAgIH0gZWxzZSBpZiAoZm4gaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgIGZuUmVmID0gZm4uZGljdD8ub2JqSWQ7CiAgICB9CiAgICBpZiAoZm5SZWYpIHsKICAgICAgY29uc3QgY2FjaGVkRm4gPSB0aGlzLl9sb2NhbEZ1bmN0aW9uQ2FjaGUuZ2V0QnlSZWYoZm5SZWYpOwogICAgICBpZiAoY2FjaGVkRm4pIHsKICAgICAgICByZXR1cm4gY2FjaGVkRm47CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGZuT2JqID0gdGhpcy54cmVmLmZldGNoSWZSZWYoZm4pOwogICAgaWYgKEFycmF5LmlzQXJyYXkoZm5PYmopKSB7CiAgICAgIGlmICghcGFyc2VBcnJheSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcignUERGRnVuY3Rpb25GYWN0b3J5LmNyZWF0ZSAtIGV4cGVjdGVkICJwYXJzZUFycmF5IiBhcmd1bWVudC4nKTsKICAgICAgfQogICAgICBwYXJzZWRGbiA9IFBERkZ1bmN0aW9uLnBhcnNlQXJyYXkodGhpcywgZm5PYmopOwogICAgfSBlbHNlIHsKICAgICAgcGFyc2VkRm4gPSBQREZGdW5jdGlvbi5wYXJzZSh0aGlzLCBmbk9iaik7CiAgICB9CiAgICBpZiAoZm5SZWYpIHsKICAgICAgdGhpcy5fbG9jYWxGdW5jdGlvbkNhY2hlLnNldChudWxsLCBmblJlZiwgcGFyc2VkRm4pOwogICAgfQogICAgcmV0dXJuIHBhcnNlZEZuOwogIH0KICBnZXQgX2xvY2FsRnVuY3Rpb25DYWNoZSgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgIl9sb2NhbEZ1bmN0aW9uQ2FjaGUiLCBuZXcgTG9jYWxGdW5jdGlvbkNhY2hlKCkpOwogIH0KfQpmdW5jdGlvbiB0b051bWJlckFycmF5KGFycikgewogIGlmICghQXJyYXkuaXNBcnJheShhcnIpKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgaWYgKCFpc051bWJlckFycmF5KGFyciwgbnVsbCkpIHsKICAgIHJldHVybiBhcnIubWFwKHggPT4gK3gpOwogIH0KICByZXR1cm4gYXJyOwp9CmNsYXNzIFBERkZ1bmN0aW9uIHsKICBzdGF0aWMgZ2V0U2FtcGxlQXJyYXkoc2l6ZSwgb3V0cHV0U2l6ZSwgYnBzLCBzdHJlYW0pIHsKICAgIGxldCBpLCBpaTsKICAgIGxldCBsZW5ndGggPSAxOwogICAgZm9yIChpID0gMCwgaWkgPSBzaXplLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgbGVuZ3RoICo9IHNpemVbaV07CiAgICB9CiAgICBsZW5ndGggKj0gb3V0cHV0U2l6ZTsKICAgIGNvbnN0IGFycmF5ID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICBsZXQgY29kZVNpemUgPSAwOwogICAgbGV0IGNvZGVCdWYgPSAwOwogICAgY29uc3Qgc2FtcGxlTXVsID0gMS4wIC8gKDIuMCAqKiBicHMgLSAxKTsKICAgIGNvbnN0IHN0ckJ5dGVzID0gc3RyZWFtLmdldEJ5dGVzKChsZW5ndGggKiBicHMgKyA3KSAvIDgpOwogICAgbGV0IHN0cklkeCA9IDA7CiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgd2hpbGUgKGNvZGVTaXplIDwgYnBzKSB7CiAgICAgICAgY29kZUJ1ZiA8PD0gODsKICAgICAgICBjb2RlQnVmIHw9IHN0ckJ5dGVzW3N0cklkeCsrXTsKICAgICAgICBjb2RlU2l6ZSArPSA4OwogICAgICB9CiAgICAgIGNvZGVTaXplIC09IGJwczsKICAgICAgYXJyYXlbaV0gPSAoY29kZUJ1ZiA+PiBjb2RlU2l6ZSkgKiBzYW1wbGVNdWw7CiAgICAgIGNvZGVCdWYgJj0gKDEgPDwgY29kZVNpemUpIC0gMTsKICAgIH0KICAgIHJldHVybiBhcnJheTsKICB9CiAgc3RhdGljIHBhcnNlKGZhY3RvcnksIGZuKSB7CiAgICBjb25zdCBkaWN0ID0gZm4uZGljdCB8fCBmbjsKICAgIGNvbnN0IHR5cGVOdW0gPSBkaWN0LmdldCgiRnVuY3Rpb25UeXBlIik7CiAgICBzd2l0Y2ggKHR5cGVOdW0pIHsKICAgICAgY2FzZSAwOgogICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdFNhbXBsZWQoZmFjdG9yeSwgZm4sIGRpY3QpOwogICAgICBjYXNlIDE6CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMjoKICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3RJbnRlcnBvbGF0ZWQoZmFjdG9yeSwgZGljdCk7CiAgICAgIGNhc2UgMzoKICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3RTdGljaGVkKGZhY3RvcnksIGRpY3QpOwogICAgICBjYXNlIDQ6CiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0UG9zdFNjcmlwdChmYWN0b3J5LCBmbiwgZGljdCk7CiAgICB9CiAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gdHlwZSBvZiBmdW5jdGlvbiIpOwogIH0KICBzdGF0aWMgcGFyc2VBcnJheShmYWN0b3J5LCBmbk9iaikgewogICAgY29uc3QgewogICAgICB4cmVmCiAgICB9ID0gZmFjdG9yeTsKICAgIGNvbnN0IGZuQXJyYXkgPSBbXTsKICAgIGZvciAoY29uc3QgZm4gb2YgZm5PYmopIHsKICAgICAgZm5BcnJheS5wdXNoKHRoaXMucGFyc2UoZmFjdG9yeSwgeHJlZi5mZXRjaElmUmVmKGZuKSkpOwogICAgfQogICAgcmV0dXJuIGZ1bmN0aW9uIChzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBmbkFycmF5Lmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBmbkFycmF5W2ldKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0ICsgaSk7CiAgICAgIH0KICAgIH07CiAgfQogIHN0YXRpYyBjb25zdHJ1Y3RTYW1wbGVkKGZhY3RvcnksIGZuLCBkaWN0KSB7CiAgICBmdW5jdGlvbiB0b011bHRpQXJyYXkoYXJyKSB7CiAgICAgIGNvbnN0IGlucHV0TGVuZ3RoID0gYXJyLmxlbmd0aDsKICAgICAgY29uc3Qgb3V0ID0gW107CiAgICAgIGxldCBpbmRleCA9IDA7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRMZW5ndGg7IGkgKz0gMikgewogICAgICAgIG91dFtpbmRleCsrXSA9IFthcnJbaV0sIGFycltpICsgMV1dOwogICAgICB9CiAgICAgIHJldHVybiBvdXQ7CiAgICB9CiAgICBmdW5jdGlvbiBpbnRlcnBvbGF0ZSh4LCB4bWluLCB4bWF4LCB5bWluLCB5bWF4KSB7CiAgICAgIHJldHVybiB5bWluICsgKHggLSB4bWluKSAqICgoeW1heCAtIHltaW4pIC8gKHhtYXggLSB4bWluKSk7CiAgICB9CiAgICBsZXQgZG9tYWluID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJEb21haW4iKSk7CiAgICBsZXQgcmFuZ2UgPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIlJhbmdlIikpOwogICAgaWYgKCFkb21haW4gfHwgIXJhbmdlKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiTm8gZG9tYWluIG9yIHJhbmdlIik7CiAgICB9CiAgICBjb25zdCBpbnB1dFNpemUgPSBkb21haW4ubGVuZ3RoIC8gMjsKICAgIGNvbnN0IG91dHB1dFNpemUgPSByYW5nZS5sZW5ndGggLyAyOwogICAgZG9tYWluID0gdG9NdWx0aUFycmF5KGRvbWFpbik7CiAgICByYW5nZSA9IHRvTXVsdGlBcnJheShyYW5nZSk7CiAgICBjb25zdCBzaXplID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJTaXplIikpOwogICAgY29uc3QgYnBzID0gZGljdC5nZXQoIkJpdHNQZXJTYW1wbGUiKTsKICAgIGNvbnN0IG9yZGVyID0gZGljdC5nZXQoIk9yZGVyIikgfHwgMTsKICAgIGlmIChvcmRlciAhPT0gMSkgewogICAgICBpbmZvKCJObyBzdXBwb3J0IGZvciBjdWJpYyBzcGxpbmUgaW50ZXJwb2xhdGlvbjogIiArIG9yZGVyKTsKICAgIH0KICAgIGxldCBlbmNvZGUgPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIkVuY29kZSIpKTsKICAgIGlmICghZW5jb2RlKSB7CiAgICAgIGVuY29kZSA9IFtdOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0U2l6ZTsgKytpKSB7CiAgICAgICAgZW5jb2RlLnB1c2goWzAsIHNpemVbaV0gLSAxXSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGVuY29kZSA9IHRvTXVsdGlBcnJheShlbmNvZGUpOwogICAgfQogICAgbGV0IGRlY29kZSA9IHRvTnVtYmVyQXJyYXkoZGljdC5nZXRBcnJheSgiRGVjb2RlIikpOwogICAgZGVjb2RlID0gIWRlY29kZSA/IHJhbmdlIDogdG9NdWx0aUFycmF5KGRlY29kZSk7CiAgICBjb25zdCBzYW1wbGVzID0gdGhpcy5nZXRTYW1wbGVBcnJheShzaXplLCBvdXRwdXRTaXplLCBicHMsIGZuKTsKICAgIHJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RTYW1wbGVkRm4oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgICAgY29uc3QgY3ViZVZlcnRpY2VzID0gMSA8PCBpbnB1dFNpemU7CiAgICAgIGNvbnN0IGN1YmVOID0gbmV3IEZsb2F0NjRBcnJheShjdWJlVmVydGljZXMpLmZpbGwoMSk7CiAgICAgIGNvbnN0IGN1YmVWZXJ0ZXggPSBuZXcgVWludDMyQXJyYXkoY3ViZVZlcnRpY2VzKTsKICAgICAgbGV0IGksIGo7CiAgICAgIGxldCBrID0gb3V0cHV0U2l6ZSwKICAgICAgICBwb3MgPSAxOwogICAgICBmb3IgKGkgPSAwOyBpIDwgaW5wdXRTaXplOyArK2kpIHsKICAgICAgICBjb25zdCBkb21haW5fMmkgPSBkb21haW5baV1bMF07CiAgICAgICAgY29uc3QgZG9tYWluXzJpXzEgPSBkb21haW5baV1bMV07CiAgICAgICAgY29uc3QgeGkgPSBNYXRoQ2xhbXAoc3JjW3NyY09mZnNldCArIGldLCBkb21haW5fMmksIGRvbWFpbl8yaV8xKTsKICAgICAgICBsZXQgZSA9IGludGVycG9sYXRlKHhpLCBkb21haW5fMmksIGRvbWFpbl8yaV8xLCBlbmNvZGVbaV1bMF0sIGVuY29kZVtpXVsxXSk7CiAgICAgICAgY29uc3Qgc2l6ZV9pID0gc2l6ZVtpXTsKICAgICAgICBlID0gTWF0aENsYW1wKGUsIDAsIHNpemVfaSAtIDEpOwogICAgICAgIGNvbnN0IGUwID0gZSA8IHNpemVfaSAtIDEgPyBNYXRoLmZsb29yKGUpIDogZSAtIDE7CiAgICAgICAgY29uc3QgbjAgPSBlMCArIDEgLSBlOwogICAgICAgIGNvbnN0IG4xID0gZSAtIGUwOwogICAgICAgIGNvbnN0IG9mZnNldDAgPSBlMCAqIGs7CiAgICAgICAgY29uc3Qgb2Zmc2V0MSA9IG9mZnNldDAgKyBrOwogICAgICAgIGZvciAoaiA9IDA7IGogPCBjdWJlVmVydGljZXM7IGorKykgewogICAgICAgICAgaWYgKGogJiBwb3MpIHsKICAgICAgICAgICAgY3ViZU5bal0gKj0gbjE7CiAgICAgICAgICAgIGN1YmVWZXJ0ZXhbal0gKz0gb2Zmc2V0MTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGN1YmVOW2pdICo9IG4wOwogICAgICAgICAgICBjdWJlVmVydGV4W2pdICs9IG9mZnNldDA7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGsgKj0gc2l6ZV9pOwogICAgICAgIHBvcyA8PD0gMTsKICAgICAgfQogICAgICBmb3IgKGogPSAwOyBqIDwgb3V0cHV0U2l6ZTsgKytqKSB7CiAgICAgICAgbGV0IHJqID0gMDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY3ViZVZlcnRpY2VzOyBpKyspIHsKICAgICAgICAgIHJqICs9IHNhbXBsZXNbY3ViZVZlcnRleFtpXSArIGpdICogY3ViZU5baV07CiAgICAgICAgfQogICAgICAgIHJqID0gaW50ZXJwb2xhdGUocmosIDAsIDEsIGRlY29kZVtqXVswXSwgZGVjb2RlW2pdWzFdKTsKICAgICAgICBkZXN0W2Rlc3RPZmZzZXQgKyBqXSA9IE1hdGhDbGFtcChyaiwgcmFuZ2Vbal1bMF0sIHJhbmdlW2pdWzFdKTsKICAgICAgfQogICAgfTsKICB9CiAgc3RhdGljIGNvbnN0cnVjdEludGVycG9sYXRlZChmYWN0b3J5LCBkaWN0KSB7CiAgICBjb25zdCBjMCA9IHRvTnVtYmVyQXJyYXkoZGljdC5nZXRBcnJheSgiQzAiKSkgfHwgWzBdOwogICAgY29uc3QgYzEgPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIkMxIikpIHx8IFsxXTsKICAgIGNvbnN0IG4gPSBkaWN0LmdldCgiTiIpOwogICAgY29uc3QgZGlmZiA9IFtdOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gYzAubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICBkaWZmLnB1c2goYzFbaV0gLSBjMFtpXSk7CiAgICB9CiAgICBjb25zdCBsZW5ndGggPSBkaWZmLmxlbmd0aDsKICAgIHJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RJbnRlcnBvbGF0ZWRGbihzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgICBjb25zdCB4ID0gbiA9PT0gMSA/IHNyY1tzcmNPZmZzZXRdIDogc3JjW3NyY09mZnNldF0gKiogbjsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBsZW5ndGg7ICsraikgewogICAgICAgIGRlc3RbZGVzdE9mZnNldCArIGpdID0gYzBbal0gKyB4ICogZGlmZltqXTsKICAgICAgfQogICAgfTsKICB9CiAgc3RhdGljIGNvbnN0cnVjdFN0aWNoZWQoZmFjdG9yeSwgZGljdCkgewogICAgY29uc3QgZG9tYWluID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJEb21haW4iKSk7CiAgICBpZiAoIWRvbWFpbikgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk5vIGRvbWFpbiIpOwogICAgfQogICAgY29uc3QgaW5wdXRTaXplID0gZG9tYWluLmxlbmd0aCAvIDI7CiAgICBpZiAoaW5wdXRTaXplICE9PSAxKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiQmFkIGRvbWFpbiBmb3Igc3RpY2hlZCBmdW5jdGlvbiIpOwogICAgfQogICAgY29uc3QgewogICAgICB4cmVmCiAgICB9ID0gZmFjdG9yeTsKICAgIGNvbnN0IGZucyA9IFtdOwogICAgZm9yIChjb25zdCBmbiBvZiBkaWN0LmdldCgiRnVuY3Rpb25zIikpIHsKICAgICAgZm5zLnB1c2godGhpcy5wYXJzZShmYWN0b3J5LCB4cmVmLmZldGNoSWZSZWYoZm4pKSk7CiAgICB9CiAgICBjb25zdCBib3VuZHMgPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIkJvdW5kcyIpKTsKICAgIGNvbnN0IGVuY29kZSA9IHRvTnVtYmVyQXJyYXkoZGljdC5nZXRBcnJheSgiRW5jb2RlIikpOwogICAgY29uc3QgdG1wQnVmID0gbmV3IEZsb2F0MzJBcnJheSgxKTsKICAgIHJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RTdGljaGVkRm4oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgICAgY29uc3QgdiA9IE1hdGhDbGFtcChzcmNbc3JjT2Zmc2V0XSwgZG9tYWluWzBdLCBkb21haW5bMV0pOwogICAgICBjb25zdCBsZW5ndGggPSBib3VuZHMubGVuZ3RoOwogICAgICBsZXQgaTsKICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgaWYgKHYgPCBib3VuZHNbaV0pIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBsZXQgZG1pbiA9IGRvbWFpblswXTsKICAgICAgaWYgKGkgPiAwKSB7CiAgICAgICAgZG1pbiA9IGJvdW5kc1tpIC0gMV07CiAgICAgIH0KICAgICAgbGV0IGRtYXggPSBkb21haW5bMV07CiAgICAgIGlmIChpIDwgYm91bmRzLmxlbmd0aCkgewogICAgICAgIGRtYXggPSBib3VuZHNbaV07CiAgICAgIH0KICAgICAgY29uc3Qgcm1pbiA9IGVuY29kZVsyICogaV07CiAgICAgIGNvbnN0IHJtYXggPSBlbmNvZGVbMiAqIGkgKyAxXTsKICAgICAgdG1wQnVmWzBdID0gZG1pbiA9PT0gZG1heCA/IHJtaW4gOiBybWluICsgKHYgLSBkbWluKSAqIChybWF4IC0gcm1pbikgLyAoZG1heCAtIGRtaW4pOwogICAgICBmbnNbaV0odG1wQnVmLCAwLCBkZXN0LCBkZXN0T2Zmc2V0KTsKICAgIH07CiAgfQogIHN0YXRpYyBjb25zdHJ1Y3RQb3N0U2NyaXB0KGZhY3RvcnksIGZuLCBkaWN0KSB7CiAgICBjb25zdCBkb21haW4gPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIkRvbWFpbiIpKTsKICAgIGNvbnN0IHJhbmdlID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJSYW5nZSIpKTsKICAgIGlmICghZG9tYWluKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiTm8gZG9tYWluLiIpOwogICAgfQogICAgaWYgKCFyYW5nZSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk5vIHJhbmdlLiIpOwogICAgfQogICAgY29uc3QgbGV4ZXIgPSBuZXcgUG9zdFNjcmlwdExleGVyKGZuKTsKICAgIGNvbnN0IHBhcnNlciA9IG5ldyBQb3N0U2NyaXB0UGFyc2VyKGxleGVyKTsKICAgIGNvbnN0IGNvZGUgPSBwYXJzZXIucGFyc2UoKTsKICAgIGlmIChmYWN0b3J5LmlzRXZhbFN1cHBvcnRlZCAmJiBGZWF0dXJlVGVzdC5pc0V2YWxTdXBwb3J0ZWQpIHsKICAgICAgY29uc3QgY29tcGlsZWQgPSBuZXcgUG9zdFNjcmlwdENvbXBpbGVyKCkuY29tcGlsZShjb2RlLCBkb21haW4sIHJhbmdlKTsKICAgICAgaWYgKGNvbXBpbGVkKSB7CiAgICAgICAgcmV0dXJuIG5ldyBGdW5jdGlvbigic3JjIiwgInNyY09mZnNldCIsICJkZXN0IiwgImRlc3RPZmZzZXQiLCBjb21waWxlZCk7CiAgICAgIH0KICAgIH0KICAgIGluZm8oIlVuYWJsZSB0byBjb21waWxlIFBTIGZ1bmN0aW9uIik7CiAgICBjb25zdCBudW1PdXRwdXRzID0gcmFuZ2UubGVuZ3RoID4+IDE7CiAgICBjb25zdCBudW1JbnB1dHMgPSBkb21haW4ubGVuZ3RoID4+IDE7CiAgICBjb25zdCBldmFsdWF0b3IgPSBuZXcgUG9zdFNjcmlwdEV2YWx1YXRvcihjb2RlKTsKICAgIGNvbnN0IGNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGNvbnN0IE1BWF9DQUNIRV9TSVpFID0gMjA0OCAqIDQ7CiAgICBsZXQgY2FjaGVfYXZhaWxhYmxlID0gTUFYX0NBQ0hFX1NJWkU7CiAgICBjb25zdCB0bXBCdWYgPSBuZXcgRmxvYXQzMkFycmF5KG51bUlucHV0cyk7CiAgICByZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0UG9zdFNjcmlwdEZuKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICAgIGxldCBpLCB2YWx1ZTsKICAgICAgbGV0IGtleSA9ICIiOwogICAgICBjb25zdCBpbnB1dCA9IHRtcEJ1ZjsKICAgICAgZm9yIChpID0gMDsgaSA8IG51bUlucHV0czsgaSsrKSB7CiAgICAgICAgdmFsdWUgPSBzcmNbc3JjT2Zmc2V0ICsgaV07CiAgICAgICAgaW5wdXRbaV0gPSB2YWx1ZTsKICAgICAgICBrZXkgKz0gdmFsdWUgKyAiXyI7CiAgICAgIH0KICAgICAgY29uc3QgY2FjaGVkVmFsdWUgPSBjYWNoZVtrZXldOwogICAgICBpZiAoY2FjaGVkVmFsdWUgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGRlc3Quc2V0KGNhY2hlZFZhbHVlLCBkZXN0T2Zmc2V0KTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29uc3Qgb3V0cHV0ID0gbmV3IEZsb2F0MzJBcnJheShudW1PdXRwdXRzKTsKICAgICAgY29uc3Qgc3RhY2sgPSBldmFsdWF0b3IuZXhlY3V0ZShpbnB1dCk7CiAgICAgIGNvbnN0IHN0YWNrSW5kZXggPSBzdGFjay5sZW5ndGggLSBudW1PdXRwdXRzOwogICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtT3V0cHV0czsgaSsrKSB7CiAgICAgICAgdmFsdWUgPSBzdGFja1tzdGFja0luZGV4ICsgaV07CiAgICAgICAgbGV0IGJvdW5kID0gcmFuZ2VbaSAqIDJdOwogICAgICAgIGlmICh2YWx1ZSA8IGJvdW5kKSB7CiAgICAgICAgICB2YWx1ZSA9IGJvdW5kOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBib3VuZCA9IHJhbmdlW2kgKiAyICsgMV07CiAgICAgICAgICBpZiAodmFsdWUgPiBib3VuZCkgewogICAgICAgICAgICB2YWx1ZSA9IGJvdW5kOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBvdXRwdXRbaV0gPSB2YWx1ZTsKICAgICAgfQogICAgICBpZiAoY2FjaGVfYXZhaWxhYmxlID4gMCkgewogICAgICAgIGNhY2hlX2F2YWlsYWJsZS0tOwogICAgICAgIGNhY2hlW2tleV0gPSBvdXRwdXQ7CiAgICAgIH0KICAgICAgZGVzdC5zZXQob3V0cHV0LCBkZXN0T2Zmc2V0KTsKICAgIH07CiAgfQp9CmZ1bmN0aW9uIGlzUERGRnVuY3Rpb24odikgewogIGxldCBmbkRpY3Q7CiAgaWYgKHYgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICBmbkRpY3QgPSB2OwogIH0gZWxzZSBpZiAodiBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgIGZuRGljdCA9IHYuZGljdDsKICB9IGVsc2UgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICByZXR1cm4gZm5EaWN0LmhhcygiRnVuY3Rpb25UeXBlIik7Cn0KY2xhc3MgUG9zdFNjcmlwdFN0YWNrIHsKICBzdGF0aWMgTUFYX1NUQUNLX1NJWkUgPSAxMDA7CiAgY29uc3RydWN0b3IoaW5pdGlhbFN0YWNrKSB7CiAgICB0aGlzLnN0YWNrID0gaW5pdGlhbFN0YWNrID8gQXJyYXkuZnJvbShpbml0aWFsU3RhY2spIDogW107CiAgfQogIHB1c2godmFsdWUpIHsKICAgIGlmICh0aGlzLnN0YWNrLmxlbmd0aCA+PSBQb3N0U2NyaXB0U3RhY2suTUFYX1NUQUNLX1NJWkUpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJQb3N0U2NyaXB0IGZ1bmN0aW9uIHN0YWNrIG92ZXJmbG93LiIpOwogICAgfQogICAgdGhpcy5zdGFjay5wdXNoKHZhbHVlKTsKICB9CiAgcG9wKCkgewogICAgaWYgKHRoaXMuc3RhY2subGVuZ3RoIDw9IDApIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJQb3N0U2NyaXB0IGZ1bmN0aW9uIHN0YWNrIHVuZGVyZmxvdy4iKTsKICAgIH0KICAgIHJldHVybiB0aGlzLnN0YWNrLnBvcCgpOwogIH0KICBjb3B5KG4pIHsKICAgIGlmICh0aGlzLnN0YWNrLmxlbmd0aCArIG4gPj0gUG9zdFNjcmlwdFN0YWNrLk1BWF9TVEFDS19TSVpFKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiUG9zdFNjcmlwdCBmdW5jdGlvbiBzdGFjayBvdmVyZmxvdy4iKTsKICAgIH0KICAgIGNvbnN0IHN0YWNrID0gdGhpcy5zdGFjazsKICAgIGZvciAobGV0IGkgPSBzdGFjay5sZW5ndGggLSBuLCBqID0gbiAtIDE7IGogPj0gMDsgai0tLCBpKyspIHsKICAgICAgc3RhY2sucHVzaChzdGFja1tpXSk7CiAgICB9CiAgfQogIGluZGV4KG4pIHsKICAgIHRoaXMucHVzaCh0aGlzLnN0YWNrW3RoaXMuc3RhY2subGVuZ3RoIC0gbiAtIDFdKTsKICB9CiAgcm9sbChuLCBwKSB7CiAgICBjb25zdCBzdGFjayA9IHRoaXMuc3RhY2s7CiAgICBjb25zdCBsID0gc3RhY2subGVuZ3RoIC0gbjsKICAgIGNvbnN0IHIgPSBzdGFjay5sZW5ndGggLSAxOwogICAgY29uc3QgYyA9IGwgKyAocCAtIE1hdGguZmxvb3IocCAvIG4pICogbik7CiAgICBmb3IgKGxldCBpID0gbCwgaiA9IHI7IGkgPCBqOyBpKyssIGotLSkgewogICAgICBjb25zdCB0ID0gc3RhY2tbaV07CiAgICAgIHN0YWNrW2ldID0gc3RhY2tbal07CiAgICAgIHN0YWNrW2pdID0gdDsKICAgIH0KICAgIGZvciAobGV0IGkgPSBsLCBqID0gYyAtIDE7IGkgPCBqOyBpKyssIGotLSkgewogICAgICBjb25zdCB0ID0gc3RhY2tbaV07CiAgICAgIHN0YWNrW2ldID0gc3RhY2tbal07CiAgICAgIHN0YWNrW2pdID0gdDsKICAgIH0KICAgIGZvciAobGV0IGkgPSBjLCBqID0gcjsgaSA8IGo7IGkrKywgai0tKSB7CiAgICAgIGNvbnN0IHQgPSBzdGFja1tpXTsKICAgICAgc3RhY2tbaV0gPSBzdGFja1tqXTsKICAgICAgc3RhY2tbal0gPSB0OwogICAgfQogIH0KfQpjbGFzcyBQb3N0U2NyaXB0RXZhbHVhdG9yIHsKICBjb25zdHJ1Y3RvcihvcGVyYXRvcnMpIHsKICAgIHRoaXMub3BlcmF0b3JzID0gb3BlcmF0b3JzOwogIH0KICBleGVjdXRlKGluaXRpYWxTdGFjaykgewogICAgY29uc3Qgc3RhY2sgPSBuZXcgUG9zdFNjcmlwdFN0YWNrKGluaXRpYWxTdGFjayk7CiAgICBsZXQgY291bnRlciA9IDA7CiAgICBjb25zdCBvcGVyYXRvcnMgPSB0aGlzLm9wZXJhdG9yczsKICAgIGNvbnN0IGxlbmd0aCA9IG9wZXJhdG9ycy5sZW5ndGg7CiAgICBsZXQgb3BlcmF0b3IsIGEsIGI7CiAgICB3aGlsZSAoY291bnRlciA8IGxlbmd0aCkgewogICAgICBvcGVyYXRvciA9IG9wZXJhdG9yc1tjb3VudGVyKytdOwogICAgICBpZiAodHlwZW9mIG9wZXJhdG9yID09PSAibnVtYmVyIikgewogICAgICAgIHN0YWNrLnB1c2gob3BlcmF0b3IpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHN3aXRjaCAob3BlcmF0b3IpIHsKICAgICAgICBjYXNlICJqeiI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBpZiAoIWEpIHsKICAgICAgICAgICAgY291bnRlciA9IGI7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJqIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGNvdW50ZXIgPSBhOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiYWJzIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goTWF0aC5hYnMoYSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiYWRkIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYSArIGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiYW5kIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGlmICh0eXBlb2YgYSA9PT0gImJvb2xlYW4iICYmIHR5cGVvZiBiID09PSAiYm9vbGVhbiIpIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhICYmIGIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhICYgYik7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJhdGFuIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBNYXRoLmF0YW4yKGEsIGIpIC8gTWF0aC5QSSAqIDE4MDsKICAgICAgICAgIGlmIChhIDwgMCkgewogICAgICAgICAgICBhICs9IDM2MDsKICAgICAgICAgIH0KICAgICAgICAgIHN0YWNrLnB1c2goYSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJiaXRzaGlmdCI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBpZiAoYSA+IDApIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhIDw8IGIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhID4+IGIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiY2VpbGluZyI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKE1hdGguY2VpbChhKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJjb3B5IjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLmNvcHkoYSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJjb3MiOgogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChNYXRoLmNvcyhhICUgMzYwIC8gMTgwICogTWF0aC5QSSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiY3ZpIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKSB8IDA7CiAgICAgICAgICBzdGFjay5wdXNoKGEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiY3ZyIjoKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImRpdiI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgLyBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImR1cCI6CiAgICAgICAgICBzdGFjay5jb3B5KDEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZXEiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhID09PSBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImV4Y2giOgogICAgICAgICAgc3RhY2sucm9sbCgyLCAxKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImV4cCI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgKiogYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJmYWxzZSI6CiAgICAgICAgICBzdGFjay5wdXNoKGZhbHNlKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImZsb29yIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goTWF0aC5mbG9vcihhKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJnZSI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgPj0gYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJndCI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgPiBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImlkaXYiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhIC8gYiB8IDApOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiaW5kZXgiOgogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2suaW5kZXgoYSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJsZSI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgPD0gYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJsbiI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKE1hdGgubG9nKGEpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImxvZyI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKE1hdGgubG9nMTAoYSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibHQiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhIDwgYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJtb2QiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhICUgYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJtdWwiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhICogYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJuZSI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgIT09IGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibmVnIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goLWEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibm90IjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGlmICh0eXBlb2YgYSA9PT0gImJvb2xlYW4iKSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goIWEpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RhY2sucHVzaCh+YSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJvciI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBpZiAodHlwZW9mIGEgPT09ICJib29sZWFuIiAmJiB0eXBlb2YgYiA9PT0gImJvb2xlYW4iKSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goYSB8fCBiKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goYSB8IGIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAicG9wIjoKICAgICAgICAgIHN0YWNrLnBvcCgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAicm9sbCI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5yb2xsKGEsIGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAicm91bmQiOgogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChNYXRoLnJvdW5kKGEpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInNpbiI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKE1hdGguc2luKGEgJSAzNjAgLyAxODAgKiBNYXRoLlBJKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJzcXJ0IjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goTWF0aC5zcXJ0KGEpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInN1YiI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgLSBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInRydWUiOgogICAgICAgICAgc3RhY2sucHVzaCh0cnVlKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInRydW5jYXRlIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBhIDwgMCA/IE1hdGguY2VpbChhKSA6IE1hdGguZmxvb3IoYSk7CiAgICAgICAgICBzdGFjay5wdXNoKGEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAieG9yIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGlmICh0eXBlb2YgYSA9PT0gImJvb2xlYW4iICYmIHR5cGVvZiBiID09PSAiYm9vbGVhbiIpIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhICE9PSBiKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goYSBeIGIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgVW5rbm93biBvcGVyYXRvciAke29wZXJhdG9yfWApOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc3RhY2suc3RhY2s7CiAgfQp9CmNsYXNzIEFzdE5vZGUgewogIGNvbnN0cnVjdG9yKHR5cGUpIHsKICAgIHRoaXMudHlwZSA9IHR5cGU7CiAgfQogIHZpc2l0KHZpc2l0b3IpIHsKICAgIHVucmVhY2hhYmxlKCJhYnN0cmFjdCBtZXRob2QiKTsKICB9Cn0KY2xhc3MgQXN0QXJndW1lbnQgZXh0ZW5kcyBBc3ROb2RlIHsKICBjb25zdHJ1Y3RvcihpbmRleCwgbWluLCBtYXgpIHsKICAgIHN1cGVyKCJhcmdzIik7CiAgICB0aGlzLmluZGV4ID0gaW5kZXg7CiAgICB0aGlzLm1pbiA9IG1pbjsKICAgIHRoaXMubWF4ID0gbWF4OwogIH0KICB2aXNpdCh2aXNpdG9yKSB7CiAgICB2aXNpdG9yLnZpc2l0QXJndW1lbnQodGhpcyk7CiAgfQp9CmNsYXNzIEFzdExpdGVyYWwgZXh0ZW5kcyBBc3ROb2RlIHsKICBjb25zdHJ1Y3RvcihudW1iZXIpIHsKICAgIHN1cGVyKCJsaXRlcmFsIik7CiAgICB0aGlzLm51bWJlciA9IG51bWJlcjsKICAgIHRoaXMubWluID0gbnVtYmVyOwogICAgdGhpcy5tYXggPSBudW1iZXI7CiAgfQogIHZpc2l0KHZpc2l0b3IpIHsKICAgIHZpc2l0b3IudmlzaXRMaXRlcmFsKHRoaXMpOwogIH0KfQpjbGFzcyBBc3RCaW5hcnlPcGVyYXRpb24gZXh0ZW5kcyBBc3ROb2RlIHsKICBjb25zdHJ1Y3RvcihvcCwgYXJnMSwgYXJnMiwgbWluLCBtYXgpIHsKICAgIHN1cGVyKCJiaW5hcnkiKTsKICAgIHRoaXMub3AgPSBvcDsKICAgIHRoaXMuYXJnMSA9IGFyZzE7CiAgICB0aGlzLmFyZzIgPSBhcmcyOwogICAgdGhpcy5taW4gPSBtaW47CiAgICB0aGlzLm1heCA9IG1heDsKICB9CiAgdmlzaXQodmlzaXRvcikgewogICAgdmlzaXRvci52aXNpdEJpbmFyeU9wZXJhdGlvbih0aGlzKTsKICB9Cn0KY2xhc3MgQXN0TWluIGV4dGVuZHMgQXN0Tm9kZSB7CiAgY29uc3RydWN0b3IoYXJnLCBtYXgpIHsKICAgIHN1cGVyKCJtYXgiKTsKICAgIHRoaXMuYXJnID0gYXJnOwogICAgdGhpcy5taW4gPSBhcmcubWluOwogICAgdGhpcy5tYXggPSBtYXg7CiAgfQogIHZpc2l0KHZpc2l0b3IpIHsKICAgIHZpc2l0b3IudmlzaXRNaW4odGhpcyk7CiAgfQp9CmNsYXNzIEFzdFZhcmlhYmxlIGV4dGVuZHMgQXN0Tm9kZSB7CiAgY29uc3RydWN0b3IoaW5kZXgsIG1pbiwgbWF4KSB7CiAgICBzdXBlcigidmFyIik7CiAgICB0aGlzLmluZGV4ID0gaW5kZXg7CiAgICB0aGlzLm1pbiA9IG1pbjsKICAgIHRoaXMubWF4ID0gbWF4OwogIH0KICB2aXNpdCh2aXNpdG9yKSB7CiAgICB2aXNpdG9yLnZpc2l0VmFyaWFibGUodGhpcyk7CiAgfQp9CmNsYXNzIEFzdFZhcmlhYmxlRGVmaW5pdGlvbiBleHRlbmRzIEFzdE5vZGUgewogIGNvbnN0cnVjdG9yKHZhcmlhYmxlLCBhcmcpIHsKICAgIHN1cGVyKCJkZWZpbml0aW9uIik7CiAgICB0aGlzLnZhcmlhYmxlID0gdmFyaWFibGU7CiAgICB0aGlzLmFyZyA9IGFyZzsKICB9CiAgdmlzaXQodmlzaXRvcikgewogICAgdmlzaXRvci52aXNpdFZhcmlhYmxlRGVmaW5pdGlvbih0aGlzKTsKICB9Cn0KY2xhc3MgRXhwcmVzc2lvbkJ1aWxkZXJWaXNpdG9yIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMucGFydHMgPSBbXTsKICB9CiAgdmlzaXRBcmd1bWVudChhcmcpIHsKICAgIHRoaXMucGFydHMucHVzaCgiTWF0aC5tYXgoIiwgYXJnLm1pbiwgIiwgTWF0aC5taW4oIiwgYXJnLm1heCwgIiwgc3JjW3NyY09mZnNldCArICIsIGFyZy5pbmRleCwgIl0pKSIpOwogIH0KICB2aXNpdFZhcmlhYmxlKHZhcmlhYmxlKSB7CiAgICB0aGlzLnBhcnRzLnB1c2goInYiLCB2YXJpYWJsZS5pbmRleCk7CiAgfQogIHZpc2l0TGl0ZXJhbChsaXRlcmFsKSB7CiAgICB0aGlzLnBhcnRzLnB1c2gobGl0ZXJhbC5udW1iZXIpOwogIH0KICB2aXNpdEJpbmFyeU9wZXJhdGlvbihvcGVyYXRpb24pIHsKICAgIHRoaXMucGFydHMucHVzaCgiKCIpOwogICAgb3BlcmF0aW9uLmFyZzEudmlzaXQodGhpcyk7CiAgICB0aGlzLnBhcnRzLnB1c2goIiAiLCBvcGVyYXRpb24ub3AsICIgIik7CiAgICBvcGVyYXRpb24uYXJnMi52aXNpdCh0aGlzKTsKICAgIHRoaXMucGFydHMucHVzaCgiKSIpOwogIH0KICB2aXNpdFZhcmlhYmxlRGVmaW5pdGlvbihkZWZpbml0aW9uKSB7CiAgICB0aGlzLnBhcnRzLnB1c2goInZhciAiKTsKICAgIGRlZmluaXRpb24udmFyaWFibGUudmlzaXQodGhpcyk7CiAgICB0aGlzLnBhcnRzLnB1c2goIiA9ICIpOwogICAgZGVmaW5pdGlvbi5hcmcudmlzaXQodGhpcyk7CiAgICB0aGlzLnBhcnRzLnB1c2goIjsiKTsKICB9CiAgdmlzaXRNaW4obWF4KSB7CiAgICB0aGlzLnBhcnRzLnB1c2goIk1hdGgubWluKCIpOwogICAgbWF4LmFyZy52aXNpdCh0aGlzKTsKICAgIHRoaXMucGFydHMucHVzaCgiLCAiLCBtYXgubWF4LCAiKSIpOwogIH0KICB0b1N0cmluZygpIHsKICAgIHJldHVybiB0aGlzLnBhcnRzLmpvaW4oIiIpOwogIH0KfQpmdW5jdGlvbiBidWlsZEFkZE9wZXJhdGlvbihudW0xLCBudW0yKSB7CiAgaWYgKG51bTIudHlwZSA9PT0gImxpdGVyYWwiICYmIG51bTIubnVtYmVyID09PSAwKSB7CiAgICByZXR1cm4gbnVtMTsKICB9CiAgaWYgKG51bTEudHlwZSA9PT0gImxpdGVyYWwiICYmIG51bTEubnVtYmVyID09PSAwKSB7CiAgICByZXR1cm4gbnVtMjsKICB9CiAgaWYgKG51bTIudHlwZSA9PT0gImxpdGVyYWwiICYmIG51bTEudHlwZSA9PT0gImxpdGVyYWwiKSB7CiAgICByZXR1cm4gbmV3IEFzdExpdGVyYWwobnVtMS5udW1iZXIgKyBudW0yLm51bWJlcik7CiAgfQogIHJldHVybiBuZXcgQXN0QmluYXJ5T3BlcmF0aW9uKCIrIiwgbnVtMSwgbnVtMiwgbnVtMS5taW4gKyBudW0yLm1pbiwgbnVtMS5tYXggKyBudW0yLm1heCk7Cn0KZnVuY3Rpb24gYnVpbGRNdWxPcGVyYXRpb24obnVtMSwgbnVtMikgewogIGlmIChudW0yLnR5cGUgPT09ICJsaXRlcmFsIikgewogICAgaWYgKG51bTIubnVtYmVyID09PSAwKSB7CiAgICAgIHJldHVybiBuZXcgQXN0TGl0ZXJhbCgwKTsKICAgIH0gZWxzZSBpZiAobnVtMi5udW1iZXIgPT09IDEpIHsKICAgICAgcmV0dXJuIG51bTE7CiAgICB9IGVsc2UgaWYgKG51bTEudHlwZSA9PT0gImxpdGVyYWwiKSB7CiAgICAgIHJldHVybiBuZXcgQXN0TGl0ZXJhbChudW0xLm51bWJlciAqIG51bTIubnVtYmVyKTsKICAgIH0KICB9CiAgaWYgKG51bTEudHlwZSA9PT0gImxpdGVyYWwiKSB7CiAgICBpZiAobnVtMS5udW1iZXIgPT09IDApIHsKICAgICAgcmV0dXJuIG5ldyBBc3RMaXRlcmFsKDApOwogICAgfSBlbHNlIGlmIChudW0xLm51bWJlciA9PT0gMSkgewogICAgICByZXR1cm4gbnVtMjsKICAgIH0KICB9CiAgY29uc3QgbWluID0gTWF0aC5taW4obnVtMS5taW4gKiBudW0yLm1pbiwgbnVtMS5taW4gKiBudW0yLm1heCwgbnVtMS5tYXggKiBudW0yLm1pbiwgbnVtMS5tYXggKiBudW0yLm1heCk7CiAgY29uc3QgbWF4ID0gTWF0aC5tYXgobnVtMS5taW4gKiBudW0yLm1pbiwgbnVtMS5taW4gKiBudW0yLm1heCwgbnVtMS5tYXggKiBudW0yLm1pbiwgbnVtMS5tYXggKiBudW0yLm1heCk7CiAgcmV0dXJuIG5ldyBBc3RCaW5hcnlPcGVyYXRpb24oIioiLCBudW0xLCBudW0yLCBtaW4sIG1heCk7Cn0KZnVuY3Rpb24gYnVpbGRTdWJPcGVyYXRpb24obnVtMSwgbnVtMikgewogIGlmIChudW0yLnR5cGUgPT09ICJsaXRlcmFsIikgewogICAgaWYgKG51bTIubnVtYmVyID09PSAwKSB7CiAgICAgIHJldHVybiBudW0xOwogICAgfSBlbHNlIGlmIChudW0xLnR5cGUgPT09ICJsaXRlcmFsIikgewogICAgICByZXR1cm4gbmV3IEFzdExpdGVyYWwobnVtMS5udW1iZXIgLSBudW0yLm51bWJlcik7CiAgICB9CiAgfQogIGlmIChudW0yLnR5cGUgPT09ICJiaW5hcnkiICYmIG51bTIub3AgPT09ICItIiAmJiBudW0xLnR5cGUgPT09ICJsaXRlcmFsIiAmJiBudW0xLm51bWJlciA9PT0gMSAmJiBudW0yLmFyZzEudHlwZSA9PT0gImxpdGVyYWwiICYmIG51bTIuYXJnMS5udW1iZXIgPT09IDEpIHsKICAgIHJldHVybiBudW0yLmFyZzI7CiAgfQogIHJldHVybiBuZXcgQXN0QmluYXJ5T3BlcmF0aW9uKCItIiwgbnVtMSwgbnVtMiwgbnVtMS5taW4gLSBudW0yLm1heCwgbnVtMS5tYXggLSBudW0yLm1pbik7Cn0KZnVuY3Rpb24gYnVpbGRNaW5PcGVyYXRpb24obnVtMSwgbWF4KSB7CiAgaWYgKG51bTEubWluID49IG1heCkgewogICAgcmV0dXJuIG5ldyBBc3RMaXRlcmFsKG1heCk7CiAgfSBlbHNlIGlmIChudW0xLm1heCA8PSBtYXgpIHsKICAgIHJldHVybiBudW0xOwogIH0KICByZXR1cm4gbmV3IEFzdE1pbihudW0xLCBtYXgpOwp9CmNsYXNzIFBvc3RTY3JpcHRDb21waWxlciB7CiAgY29tcGlsZShjb2RlLCBkb21haW4sIHJhbmdlKSB7CiAgICBjb25zdCBzdGFjayA9IFtdOwogICAgY29uc3QgaW5zdHJ1Y3Rpb25zID0gW107CiAgICBjb25zdCBpbnB1dFNpemUgPSBkb21haW4ubGVuZ3RoID4+IDEsCiAgICAgIG91dHB1dFNpemUgPSByYW5nZS5sZW5ndGggPj4gMTsKICAgIGxldCBsYXN0UmVnaXN0ZXIgPSAwOwogICAgbGV0IG4sIGo7CiAgICBsZXQgbnVtMSwgbnVtMiwgYXN0MSwgYXN0MiwgdG1wVmFyLCBpdGVtOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dFNpemU7IGkrKykgewogICAgICBzdGFjay5wdXNoKG5ldyBBc3RBcmd1bWVudChpLCBkb21haW5baSAqIDJdLCBkb21haW5baSAqIDIgKyAxXSkpOwogICAgfQogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gY29kZS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGl0ZW0gPSBjb2RlW2ldOwogICAgICBpZiAodHlwZW9mIGl0ZW0gPT09ICJudW1iZXIiKSB7CiAgICAgICAgc3RhY2sucHVzaChuZXcgQXN0TGl0ZXJhbChpdGVtKSk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgc3dpdGNoIChpdGVtKSB7CiAgICAgICAgY2FzZSAiYWRkIjoKICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgbnVtMiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgbnVtMSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChidWlsZEFkZE9wZXJhdGlvbihudW0xLCBudW0yKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJjdnIiOgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA8IDEpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJtdWwiOgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA8IDIpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBudW0yID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBudW0xID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGJ1aWxkTXVsT3BlcmF0aW9uKG51bTEsIG51bTIpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInN1YiI6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoIDwgMikgewogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIG51bTIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIG51bTEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYnVpbGRTdWJPcGVyYXRpb24obnVtMSwgbnVtMikpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZXhjaCI6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoIDwgMikgewogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIGFzdDEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGFzdDIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYXN0MSwgYXN0Mik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJwb3AiOgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA8IDEpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBzdGFjay5wb3AoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImluZGV4IjoKICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPCAxKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgbnVtMSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgaWYgKG51bTEudHlwZSAhPT0gImxpdGVyYWwiKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgbiA9IG51bTEubnVtYmVyOwogICAgICAgICAgaWYgKG4gPCAwIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG4pIHx8IHN0YWNrLmxlbmd0aCA8IG4pIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBhc3QxID0gc3RhY2tbc3RhY2subGVuZ3RoIC0gbiAtIDFdOwogICAgICAgICAgaWYgKGFzdDEudHlwZSA9PT0gImxpdGVyYWwiIHx8IGFzdDEudHlwZSA9PT0gInZhciIpIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhc3QxKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICB0bXBWYXIgPSBuZXcgQXN0VmFyaWFibGUobGFzdFJlZ2lzdGVyKyssIGFzdDEubWluLCBhc3QxLm1heCk7CiAgICAgICAgICBzdGFja1tzdGFjay5sZW5ndGggLSBuIC0gMV0gPSB0bXBWYXI7CiAgICAgICAgICBzdGFjay5wdXNoKHRtcFZhcik7CiAgICAgICAgICBpbnN0cnVjdGlvbnMucHVzaChuZXcgQXN0VmFyaWFibGVEZWZpbml0aW9uKHRtcFZhciwgYXN0MSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZHVwIjoKICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPCAxKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHR5cGVvZiBjb2RlW2kgKyAxXSA9PT0gIm51bWJlciIgJiYgY29kZVtpICsgMl0gPT09ICJndCIgJiYgY29kZVtpICsgM10gPT09IGkgKyA3ICYmIGNvZGVbaSArIDRdID09PSAianoiICYmIGNvZGVbaSArIDVdID09PSAicG9wIiAmJiBjb2RlW2kgKyA2XSA9PT0gY29kZVtpICsgMV0pIHsKICAgICAgICAgICAgbnVtMSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgICBzdGFjay5wdXNoKGJ1aWxkTWluT3BlcmF0aW9uKG51bTEsIGNvZGVbaSArIDFdKSk7CiAgICAgICAgICAgIGkgKz0gNjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBhc3QxID0gc3RhY2suYXQoLTEpOwogICAgICAgICAgaWYgKGFzdDEudHlwZSA9PT0gImxpdGVyYWwiIHx8IGFzdDEudHlwZSA9PT0gInZhciIpIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhc3QxKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICB0bXBWYXIgPSBuZXcgQXN0VmFyaWFibGUobGFzdFJlZ2lzdGVyKyssIGFzdDEubWluLCBhc3QxLm1heCk7CiAgICAgICAgICBzdGFja1tzdGFjay5sZW5ndGggLSAxXSA9IHRtcFZhcjsKICAgICAgICAgIHN0YWNrLnB1c2godG1wVmFyKTsKICAgICAgICAgIGluc3RydWN0aW9ucy5wdXNoKG5ldyBBc3RWYXJpYWJsZURlZmluaXRpb24odG1wVmFyLCBhc3QxKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJyb2xsIjoKICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgbnVtMiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgbnVtMSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgaWYgKG51bTIudHlwZSAhPT0gImxpdGVyYWwiIHx8IG51bTEudHlwZSAhPT0gImxpdGVyYWwiKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgaiA9IG51bTIubnVtYmVyOwogICAgICAgICAgbiA9IG51bTEubnVtYmVyOwogICAgICAgICAgaWYgKG4gPD0gMCB8fCAhTnVtYmVyLmlzSW50ZWdlcihuKSB8fCAhTnVtYmVyLmlzSW50ZWdlcihqKSB8fCBzdGFjay5sZW5ndGggPCBuKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgaiA9IChqICUgbiArIG4pICUgbjsKICAgICAgICAgIGlmIChqID09PSAwKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgc3RhY2sucHVzaCguLi5zdGFjay5zcGxpY2Uoc3RhY2subGVuZ3RoIC0gbiwgbiAtIGopKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQogICAgaWYgKHN0YWNrLmxlbmd0aCAhPT0gb3V0cHV0U2l6ZSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHJlc3VsdCA9IFtdOwogICAgZm9yIChjb25zdCBpbnN0cnVjdGlvbiBvZiBpbnN0cnVjdGlvbnMpIHsKICAgICAgY29uc3Qgc3RhdGVtZW50QnVpbGRlciA9IG5ldyBFeHByZXNzaW9uQnVpbGRlclZpc2l0b3IoKTsKICAgICAgaW5zdHJ1Y3Rpb24udmlzaXQoc3RhdGVtZW50QnVpbGRlcik7CiAgICAgIHJlc3VsdC5wdXNoKHN0YXRlbWVudEJ1aWxkZXIudG9TdHJpbmcoKSk7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzdGFjay5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IGV4cHIgPSBzdGFja1tpXSwKICAgICAgICBzdGF0ZW1lbnRCdWlsZGVyID0gbmV3IEV4cHJlc3Npb25CdWlsZGVyVmlzaXRvcigpOwogICAgICBleHByLnZpc2l0KHN0YXRlbWVudEJ1aWxkZXIpOwogICAgICBjb25zdCBtaW4gPSByYW5nZVtpICogMl0sCiAgICAgICAgbWF4ID0gcmFuZ2VbaSAqIDIgKyAxXTsKICAgICAgY29uc3Qgb3V0ID0gW3N0YXRlbWVudEJ1aWxkZXIudG9TdHJpbmcoKV07CiAgICAgIGlmIChtaW4gPiBleHByLm1pbikgewogICAgICAgIG91dC51bnNoaWZ0KCJNYXRoLm1heCgiLCBtaW4sICIsICIpOwogICAgICAgIG91dC5wdXNoKCIpIik7CiAgICAgIH0KICAgICAgaWYgKG1heCA8IGV4cHIubWF4KSB7CiAgICAgICAgb3V0LnVuc2hpZnQoIk1hdGgubWluKCIsIG1heCwgIiwgIik7CiAgICAgICAgb3V0LnB1c2goIikiKTsKICAgICAgfQogICAgICBvdXQudW5zaGlmdCgiZGVzdFtkZXN0T2Zmc2V0ICsgIiwgaSwgIl0gPSAiKTsKICAgICAgb3V0LnB1c2goIjsiKTsKICAgICAgcmVzdWx0LnB1c2gob3V0LmpvaW4oIiIpKTsKICAgIH0KICAgIHJldHVybiByZXN1bHQuam9pbigiXG4iKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2JpZGkuanMKCmNvbnN0IGJhc2VUeXBlcyA9IFsiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiUyIsICJCIiwgIlMiLCAiV1MiLCAiQiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCIiwgIkIiLCAiQiIsICJTIiwgIldTIiwgIk9OIiwgIk9OIiwgIkVUIiwgIkVUIiwgIkVUIiwgIk9OIiwgIk9OIiwgIk9OIiwgIk9OIiwgIk9OIiwgIkVTIiwgIkNTIiwgIkVTIiwgIkNTIiwgIkNTIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkNTIiwgIk9OIiwgIk9OIiwgIk9OIiwgIk9OIiwgIk9OIiwgIk9OIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiT04iLCAiT04iLCAiT04iLCAiT04iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJDUyIsICJPTiIsICJFVCIsICJFVCIsICJFVCIsICJFVCIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJMIiwgIk9OIiwgIk9OIiwgIkJOIiwgIk9OIiwgIk9OIiwgIkVUIiwgIkVUIiwgIkVOIiwgIkVOIiwgIk9OIiwgIkwiLCAiT04iLCAiT04iLCAiT04iLCAiRU4iLCAiTCIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiT04iLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJPTiIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiXTsKY29uc3QgYXJhYmljVHlwZXMgPSBbIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIk9OIiwgIk9OIiwgIkFMIiwgIkVUIiwgIkVUIiwgIkFMIiwgIkNTIiwgIkFMIiwgIk9OIiwgIk9OIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiQUwiLCAiQUwiLCAiIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkVUIiwgIkFOIiwgIkFOIiwgIkFMIiwgIkFMIiwgIkFMIiwgIk5TTSIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiQU4iLCAiT04iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiQUwiLCAiQUwiLCAiTlNNIiwgIk5TTSIsICJPTiIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiQUwiLCAiQUwiLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiXTsKZnVuY3Rpb24gaXNPZGQoaSkgewogIHJldHVybiAoaSAmIDEpICE9PSAwOwp9CmZ1bmN0aW9uIGlzRXZlbihpKSB7CiAgcmV0dXJuIChpICYgMSkgPT09IDA7Cn0KZnVuY3Rpb24gZmluZFVuZXF1YWwoYXJyLCBzdGFydCwgdmFsdWUpIHsKICBsZXQgaiwgamo7CiAgZm9yIChqID0gc3RhcnQsIGpqID0gYXJyLmxlbmd0aDsgaiA8IGpqOyArK2opIHsKICAgIGlmIChhcnJbal0gIT09IHZhbHVlKSB7CiAgICAgIHJldHVybiBqOwogICAgfQogIH0KICByZXR1cm4gajsKfQpmdW5jdGlvbiByZXZlcnNlVmFsdWVzKGFyciwgc3RhcnQsIGVuZCkgewogIGZvciAobGV0IGkgPSBzdGFydCwgaiA9IGVuZCAtIDE7IGkgPCBqOyArK2ksIC0taikgewogICAgY29uc3QgdGVtcCA9IGFycltpXTsKICAgIGFycltpXSA9IGFycltqXTsKICAgIGFycltqXSA9IHRlbXA7CiAgfQp9CmZ1bmN0aW9uIGNyZWF0ZUJpZGlUZXh0KHN0ciwgaXNMVFIsIHZlcnRpY2FsID0gZmFsc2UpIHsKICBsZXQgZGlyID0gImx0ciI7CiAgaWYgKHZlcnRpY2FsKSB7CiAgICBkaXIgPSAidHRiIjsKICB9IGVsc2UgaWYgKCFpc0xUUikgewogICAgZGlyID0gInJ0bCI7CiAgfQogIHJldHVybiB7CiAgICBzdHIsCiAgICBkaXIKICB9Owp9CmNvbnN0IGNoYXJzID0gW107CmNvbnN0IHR5cGVzID0gW107CmZ1bmN0aW9uIGJpZGkoc3RyLCBzdGFydExldmVsID0gLTEsIHZlcnRpY2FsID0gZmFsc2UpIHsKICBsZXQgaXNMVFIgPSB0cnVlOwogIGNvbnN0IHN0ckxlbmd0aCA9IHN0ci5sZW5ndGg7CiAgaWYgKHN0ckxlbmd0aCA9PT0gMCB8fCB2ZXJ0aWNhbCkgewogICAgcmV0dXJuIGNyZWF0ZUJpZGlUZXh0KHN0ciwgaXNMVFIsIHZlcnRpY2FsKTsKICB9CiAgY2hhcnMubGVuZ3RoID0gc3RyTGVuZ3RoOwogIHR5cGVzLmxlbmd0aCA9IHN0ckxlbmd0aDsKICBsZXQgbnVtQmlkaSA9IDA7CiAgbGV0IGksIGlpOwogIGZvciAoaSA9IDA7IGkgPCBzdHJMZW5ndGg7ICsraSkgewogICAgY2hhcnNbaV0gPSBzdHIuY2hhckF0KGkpOwogICAgY29uc3QgY2hhckNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTsKICAgIGxldCBjaGFyVHlwZSA9ICJMIjsKICAgIGlmIChjaGFyQ29kZSA8PSAweDAwZmYpIHsKICAgICAgY2hhclR5cGUgPSBiYXNlVHlwZXNbY2hhckNvZGVdOwogICAgfSBlbHNlIGlmICgweDA1OTAgPD0gY2hhckNvZGUgJiYgY2hhckNvZGUgPD0gMHgwNWY0KSB7CiAgICAgIGNoYXJUeXBlID0gIlIiOwogICAgfSBlbHNlIGlmICgweDA2MDAgPD0gY2hhckNvZGUgJiYgY2hhckNvZGUgPD0gMHgwNmZmKSB7CiAgICAgIGNoYXJUeXBlID0gYXJhYmljVHlwZXNbY2hhckNvZGUgJiAweGZmXTsKICAgICAgaWYgKCFjaGFyVHlwZSkgewogICAgICAgIHdhcm4oIkJpZGk6IGludmFsaWQgVW5pY29kZSBjaGFyYWN0ZXIgIiArIGNoYXJDb2RlLnRvU3RyaW5nKDE2KSk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoMHgwNzAwIDw9IGNoYXJDb2RlICYmIGNoYXJDb2RlIDw9IDB4MDhhYyB8fCAweGZiNTAgPD0gY2hhckNvZGUgJiYgY2hhckNvZGUgPD0gMHhmZGZmIHx8IDB4ZmU3MCA8PSBjaGFyQ29kZSAmJiBjaGFyQ29kZSA8PSAweGZlZmYpIHsKICAgICAgY2hhclR5cGUgPSAiQUwiOwogICAgfQogICAgaWYgKGNoYXJUeXBlID09PSAiUiIgfHwgY2hhclR5cGUgPT09ICJBTCIgfHwgY2hhclR5cGUgPT09ICJBTiIpIHsKICAgICAgbnVtQmlkaSsrOwogICAgfQogICAgdHlwZXNbaV0gPSBjaGFyVHlwZTsKICB9CiAgaWYgKG51bUJpZGkgPT09IDApIHsKICAgIGlzTFRSID0gdHJ1ZTsKICAgIHJldHVybiBjcmVhdGVCaWRpVGV4dChzdHIsIGlzTFRSKTsKICB9CiAgaWYgKHN0YXJ0TGV2ZWwgPT09IC0xKSB7CiAgICBpZiAobnVtQmlkaSAvIHN0ckxlbmd0aCA8IDAuMyAmJiBzdHJMZW5ndGggPiA0KSB7CiAgICAgIGlzTFRSID0gdHJ1ZTsKICAgICAgc3RhcnRMZXZlbCA9IDA7CiAgICB9IGVsc2UgewogICAgICBpc0xUUiA9IGZhbHNlOwogICAgICBzdGFydExldmVsID0gMTsKICAgIH0KICB9CiAgY29uc3QgbGV2ZWxzID0gW107CiAgZm9yIChpID0gMDsgaSA8IHN0ckxlbmd0aDsgKytpKSB7CiAgICBsZXZlbHNbaV0gPSBzdGFydExldmVsOwogIH0KICBjb25zdCBlID0gaXNPZGQoc3RhcnRMZXZlbCkgPyAiUiIgOiAiTCI7CiAgY29uc3Qgc29yID0gZTsKICBjb25zdCBlb3IgPSBzb3I7CiAgbGV0IGxhc3RUeXBlID0gc29yOwogIGZvciAoaSA9IDA7IGkgPCBzdHJMZW5ndGg7ICsraSkgewogICAgaWYgKHR5cGVzW2ldID09PSAiTlNNIikgewogICAgICB0eXBlc1tpXSA9IGxhc3RUeXBlOwogICAgfSBlbHNlIHsKICAgICAgbGFzdFR5cGUgPSB0eXBlc1tpXTsKICAgIH0KICB9CiAgbGFzdFR5cGUgPSBzb3I7CiAgbGV0IHQ7CiAgZm9yIChpID0gMDsgaSA8IHN0ckxlbmd0aDsgKytpKSB7CiAgICB0ID0gdHlwZXNbaV07CiAgICBpZiAodCA9PT0gIkVOIikgewogICAgICB0eXBlc1tpXSA9IGxhc3RUeXBlID09PSAiQUwiID8gIkFOIiA6ICJFTiI7CiAgICB9IGVsc2UgaWYgKHQgPT09ICJSIiB8fCB0ID09PSAiTCIgfHwgdCA9PT0gIkFMIikgewogICAgICBsYXN0VHlwZSA9IHQ7CiAgICB9CiAgfQogIGZvciAoaSA9IDA7IGkgPCBzdHJMZW5ndGg7ICsraSkgewogICAgdCA9IHR5cGVzW2ldOwogICAgaWYgKHQgPT09ICJBTCIpIHsKICAgICAgdHlwZXNbaV0gPSAiUiI7CiAgICB9CiAgfQogIGZvciAoaSA9IDE7IGkgPCBzdHJMZW5ndGggLSAxOyArK2kpIHsKICAgIGlmICh0eXBlc1tpXSA9PT0gIkVTIiAmJiB0eXBlc1tpIC0gMV0gPT09ICJFTiIgJiYgdHlwZXNbaSArIDFdID09PSAiRU4iKSB7CiAgICAgIHR5cGVzW2ldID0gIkVOIjsKICAgIH0KICAgIGlmICh0eXBlc1tpXSA9PT0gIkNTIiAmJiAodHlwZXNbaSAtIDFdID09PSAiRU4iIHx8IHR5cGVzW2kgLSAxXSA9PT0gIkFOIikgJiYgdHlwZXNbaSArIDFdID09PSB0eXBlc1tpIC0gMV0pIHsKICAgICAgdHlwZXNbaV0gPSB0eXBlc1tpIC0gMV07CiAgICB9CiAgfQogIGZvciAoaSA9IDA7IGkgPCBzdHJMZW5ndGg7ICsraSkgewogICAgaWYgKHR5cGVzW2ldID09PSAiRU4iKSB7CiAgICAgIGZvciAobGV0IGogPSBpIC0gMTsgaiA+PSAwOyAtLWopIHsKICAgICAgICBpZiAodHlwZXNbal0gIT09ICJFVCIpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICB0eXBlc1tqXSA9ICJFTiI7CiAgICAgIH0KICAgICAgZm9yIChsZXQgaiA9IGkgKyAxOyBqIDwgc3RyTGVuZ3RoOyArK2opIHsKICAgICAgICBpZiAodHlwZXNbal0gIT09ICJFVCIpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICB0eXBlc1tqXSA9ICJFTiI7CiAgICAgIH0KICAgIH0KICB9CiAgZm9yIChpID0gMDsgaSA8IHN0ckxlbmd0aDsgKytpKSB7CiAgICB0ID0gdHlwZXNbaV07CiAgICBpZiAodCA9PT0gIldTIiB8fCB0ID09PSAiRVMiIHx8IHQgPT09ICJFVCIgfHwgdCA9PT0gIkNTIikgewogICAgICB0eXBlc1tpXSA9ICJPTiI7CiAgICB9CiAgfQogIGxhc3RUeXBlID0gc29yOwogIGZvciAoaSA9IDA7IGkgPCBzdHJMZW5ndGg7ICsraSkgewogICAgdCA9IHR5cGVzW2ldOwogICAgaWYgKHQgPT09ICJFTiIpIHsKICAgICAgdHlwZXNbaV0gPSBsYXN0VHlwZSA9PT0gIkwiID8gIkwiIDogIkVOIjsKICAgIH0gZWxzZSBpZiAodCA9PT0gIlIiIHx8IHQgPT09ICJMIikgewogICAgICBsYXN0VHlwZSA9IHQ7CiAgICB9CiAgfQogIGZvciAoaSA9IDA7IGkgPCBzdHJMZW5ndGg7ICsraSkgewogICAgaWYgKHR5cGVzW2ldID09PSAiT04iKSB7CiAgICAgIGNvbnN0IGVuZCA9IGZpbmRVbmVxdWFsKHR5cGVzLCBpICsgMSwgIk9OIik7CiAgICAgIGxldCBiZWZvcmUgPSBzb3I7CiAgICAgIGlmIChpID4gMCkgewogICAgICAgIGJlZm9yZSA9IHR5cGVzW2kgLSAxXTsKICAgICAgfQogICAgICBsZXQgYWZ0ZXIgPSBlb3I7CiAgICAgIGlmIChlbmQgKyAxIDwgc3RyTGVuZ3RoKSB7CiAgICAgICAgYWZ0ZXIgPSB0eXBlc1tlbmQgKyAxXTsKICAgICAgfQogICAgICBpZiAoYmVmb3JlICE9PSAiTCIpIHsKICAgICAgICBiZWZvcmUgPSAiUiI7CiAgICAgIH0KICAgICAgaWYgKGFmdGVyICE9PSAiTCIpIHsKICAgICAgICBhZnRlciA9ICJSIjsKICAgICAgfQogICAgICBpZiAoYmVmb3JlID09PSBhZnRlcikgewogICAgICAgIHR5cGVzLmZpbGwoYmVmb3JlLCBpLCBlbmQpOwogICAgICB9CiAgICAgIGkgPSBlbmQgLSAxOwogICAgfQogIH0KICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIGlmICh0eXBlc1tpXSA9PT0gIk9OIikgewogICAgICB0eXBlc1tpXSA9IGU7CiAgICB9CiAgfQogIGZvciAoaSA9IDA7IGkgPCBzdHJMZW5ndGg7ICsraSkgewogICAgdCA9IHR5cGVzW2ldOwogICAgaWYgKGlzRXZlbihsZXZlbHNbaV0pKSB7CiAgICAgIGlmICh0ID09PSAiUiIpIHsKICAgICAgICBsZXZlbHNbaV0gKz0gMTsKICAgICAgfSBlbHNlIGlmICh0ID09PSAiQU4iIHx8IHQgPT09ICJFTiIpIHsKICAgICAgICBsZXZlbHNbaV0gKz0gMjsKICAgICAgfQogICAgfSBlbHNlIGlmICh0ID09PSAiTCIgfHwgdCA9PT0gIkFOIiB8fCB0ID09PSAiRU4iKSB7CiAgICAgIGxldmVsc1tpXSArPSAxOwogICAgfQogIH0KICBsZXQgaGlnaGVzdExldmVsID0gLTE7CiAgbGV0IGxvd2VzdE9kZExldmVsID0gOTk7CiAgbGV0IGxldmVsOwogIGZvciAoaSA9IDAsIGlpID0gbGV2ZWxzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgIGxldmVsID0gbGV2ZWxzW2ldOwogICAgaWYgKGhpZ2hlc3RMZXZlbCA8IGxldmVsKSB7CiAgICAgIGhpZ2hlc3RMZXZlbCA9IGxldmVsOwogICAgfQogICAgaWYgKGxvd2VzdE9kZExldmVsID4gbGV2ZWwgJiYgaXNPZGQobGV2ZWwpKSB7CiAgICAgIGxvd2VzdE9kZExldmVsID0gbGV2ZWw7CiAgICB9CiAgfQogIGZvciAobGV2ZWwgPSBoaWdoZXN0TGV2ZWw7IGxldmVsID49IGxvd2VzdE9kZExldmVsOyAtLWxldmVsKSB7CiAgICBsZXQgc3RhcnQgPSAtMTsKICAgIGZvciAoaSA9IDAsIGlpID0gbGV2ZWxzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgaWYgKGxldmVsc1tpXSA8IGxldmVsKSB7CiAgICAgICAgaWYgKHN0YXJ0ID49IDApIHsKICAgICAgICAgIHJldmVyc2VWYWx1ZXMoY2hhcnMsIHN0YXJ0LCBpKTsKICAgICAgICAgIHN0YXJ0ID0gLTE7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKHN0YXJ0IDwgMCkgewogICAgICAgIHN0YXJ0ID0gaTsKICAgICAgfQogICAgfQogICAgaWYgKHN0YXJ0ID49IDApIHsKICAgICAgcmV2ZXJzZVZhbHVlcyhjaGFycywgc3RhcnQsIGxldmVscy5sZW5ndGgpOwogICAgfQogIH0KICBmb3IgKGkgPSAwLCBpaSA9IGNoYXJzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgIGNvbnN0IGNoID0gY2hhcnNbaV07CiAgICBpZiAoY2ggPT09ICI8IiB8fCBjaCA9PT0gIj4iKSB7CiAgICAgIGNoYXJzW2ldID0gIiI7CiAgICB9CiAgfQogIHJldHVybiBjcmVhdGVCaWRpVGV4dChjaGFycy5qb2luKCIiKSwgaXNMVFIpOwp9Cgo7Ly8gLi9zcmMvY29yZS9mb250X3N1YnN0aXR1dGlvbnMuanMKCgoKY29uc3QgTk9STUFMID0gewogIHN0eWxlOiAibm9ybWFsIiwKICB3ZWlnaHQ6ICJub3JtYWwiCn07CmNvbnN0IEJPTEQgPSB7CiAgc3R5bGU6ICJub3JtYWwiLAogIHdlaWdodDogImJvbGQiCn07CmNvbnN0IElUQUxJQyA9IHsKICBzdHlsZTogIml0YWxpYyIsCiAgd2VpZ2h0OiAibm9ybWFsIgp9Owpjb25zdCBCT0xESVRBTElDID0gewogIHN0eWxlOiAiaXRhbGljIiwKICB3ZWlnaHQ6ICJib2xkIgp9Owpjb25zdCBzdWJzdGl0dXRpb25NYXAgPSBuZXcgTWFwKFtbIlRpbWVzLVJvbWFuIiwgewogIGxvY2FsOiBbIlRpbWVzIE5ldyBSb21hbiIsICJUaW1lcy1Sb21hbiIsICJUaW1lcyIsICJMaWJlcmF0aW9uIFNlcmlmIiwgIk5pbWJ1cyBSb21hbiIsICJOaW1idXMgUm9tYW4gTCIsICJUaW5vcyIsICJUaG9ybmRhbGUiLCAiVGVYIEd5cmUgVGVybWVzIiwgIkZyZWVTZXJpZiIsICJMaW51eCBMaWJlcnRpbmUgTyIsICJMaWJlcnRpbnVzIFNlcmlmIiwgIlBUIEFzdHJhIFNlcmlmIiwgIkRlamFWdSBTZXJpZiIsICJCaXRzdHJlYW0gVmVyYSBTZXJpZiIsICJVYnVudHUiXSwKICBzdHlsZTogTk9STUFMLAogIHVsdGltYXRlOiAic2VyaWYiCn1dLCBbIlRpbWVzLUJvbGQiLCB7CiAgYWxpYXM6ICJUaW1lcy1Sb21hbiIsCiAgc3R5bGU6IEJPTEQsCiAgdWx0aW1hdGU6ICJzZXJpZiIKfV0sIFsiVGltZXMtSXRhbGljIiwgewogIGFsaWFzOiAiVGltZXMtUm9tYW4iLAogIHN0eWxlOiBJVEFMSUMsCiAgdWx0aW1hdGU6ICJzZXJpZiIKfV0sIFsiVGltZXMtQm9sZEl0YWxpYyIsIHsKICBhbGlhczogIlRpbWVzLVJvbWFuIiwKICBzdHlsZTogQk9MRElUQUxJQywKICB1bHRpbWF0ZTogInNlcmlmIgp9XSwgWyJIZWx2ZXRpY2EiLCB7CiAgbG9jYWw6IFsiSGVsdmV0aWNhIiwgIkhlbHZldGljYSBOZXVlIiwgIkFyaWFsIiwgIkFyaWFsIE5vdmEiLCAiTGliZXJhdGlvbiBTYW5zIiwgIkFyaW1vIiwgIk5pbWJ1cyBTYW5zIiwgIk5pbWJ1cyBTYW5zIEwiLCAiQTAzMCIsICJUZVggR3lyZSBIZXJvcyIsICJGcmVlU2FucyIsICJEZWphVnUgU2FucyIsICJBbGJhbnkiLCAiQml0c3RyZWFtIFZlcmEgU2FucyIsICJBcmlhbCBVbmljb2RlIE1TIiwgIk1pY3Jvc29mdCBTYW5zIFNlcmlmIiwgIkFwcGxlIFN5bWJvbHMiLCAiQ2FudGFyZWxsIl0sCiAgcGF0aDogIkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIudHRmIiwKICBzdHlsZTogTk9STUFMLAogIHVsdGltYXRlOiAic2Fucy1zZXJpZiIKfV0sIFsiSGVsdmV0aWNhLUJvbGQiLCB7CiAgYWxpYXM6ICJIZWx2ZXRpY2EiLAogIHBhdGg6ICJMaWJlcmF0aW9uU2Fucy1Cb2xkLnR0ZiIsCiAgc3R5bGU6IEJPTEQsCiAgdWx0aW1hdGU6ICJzYW5zLXNlcmlmIgp9XSwgWyJIZWx2ZXRpY2EtT2JsaXF1ZSIsIHsKICBhbGlhczogIkhlbHZldGljYSIsCiAgcGF0aDogIkxpYmVyYXRpb25TYW5zLUl0YWxpYy50dGYiLAogIHN0eWxlOiBJVEFMSUMsCiAgdWx0aW1hdGU6ICJzYW5zLXNlcmlmIgp9XSwgWyJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiLCB7CiAgYWxpYXM6ICJIZWx2ZXRpY2EiLAogIHBhdGg6ICJMaWJlcmF0aW9uU2Fucy1Cb2xkSXRhbGljLnR0ZiIsCiAgc3R5bGU6IEJPTERJVEFMSUMsCiAgdWx0aW1hdGU6ICJzYW5zLXNlcmlmIgp9XSwgWyJDb3VyaWVyIiwgewogIGxvY2FsOiBbIkNvdXJpZXIiLCAiQ291cmllciBOZXciLCAiTGliZXJhdGlvbiBNb25vIiwgIk5pbWJ1cyBNb25vIiwgIk5pbWJ1cyBNb25vIEwiLCAiQ291c2luZSIsICJDdW1iZXJsYW5kIiwgIlRlWCBHeXJlIEN1cnNvciIsICJGcmVlTW9ubyIsICJMaW51eCBMaWJlcnRpbmUgTW9ubyBPIiwgIkxpYmVydGludXMgTW9ubyJdLAogIHN0eWxlOiBOT1JNQUwsCiAgdWx0aW1hdGU6ICJtb25vc3BhY2UiCn1dLCBbIkNvdXJpZXItQm9sZCIsIHsKICBhbGlhczogIkNvdXJpZXIiLAogIHN0eWxlOiBCT0xELAogIHVsdGltYXRlOiAibW9ub3NwYWNlIgp9XSwgWyJDb3VyaWVyLU9ibGlxdWUiLCB7CiAgYWxpYXM6ICJDb3VyaWVyIiwKICBzdHlsZTogSVRBTElDLAogIHVsdGltYXRlOiAibW9ub3NwYWNlIgp9XSwgWyJDb3VyaWVyLUJvbGRPYmxpcXVlIiwgewogIGFsaWFzOiAiQ291cmllciIsCiAgc3R5bGU6IEJPTERJVEFMSUMsCiAgdWx0aW1hdGU6ICJtb25vc3BhY2UiCn1dLCBbIkFyaWFsQmxhY2siLCB7CiAgbG9jYWw6IFsiQXJpYWwgQmxhY2siXSwKICBzdHlsZTogewogICAgc3R5bGU6ICJub3JtYWwiLAogICAgd2VpZ2h0OiAiOTAwIgogIH0sCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtQm9sZCIKfV0sIFsiQXJpYWxCbGFjay1Cb2xkIiwgewogIGFsaWFzOiAiQXJpYWxCbGFjayIKfV0sIFsiQXJpYWxCbGFjay1JdGFsaWMiLCB7CiAgYWxpYXM6ICJBcmlhbEJsYWNrIiwKICBzdHlsZTogewogICAgc3R5bGU6ICJpdGFsaWMiLAogICAgd2VpZ2h0OiAiOTAwIgogIH0sCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiCn1dLCBbIkFyaWFsQmxhY2stQm9sZEl0YWxpYyIsIHsKICBhbGlhczogIkFyaWFsQmxhY2stSXRhbGljIgp9XSwgWyJBcmlhbE5hcnJvdyIsIHsKICBsb2NhbDogWyJBcmlhbCBOYXJyb3ciLCAiTGliZXJhdGlvbiBTYW5zIE5hcnJvdyIsICJIZWx2ZXRpY2EgQ29uZGVuc2VkIiwgIk5pbWJ1cyBTYW5zIE5hcnJvdyIsICJUZVggR3lyZSBIZXJvcyBDbiJdLAogIHN0eWxlOiBOT1JNQUwsCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EiCn1dLCBbIkFyaWFsTmFycm93LUJvbGQiLCB7CiAgYWxpYXM6ICJBcmlhbE5hcnJvdyIsCiAgc3R5bGU6IEJPTEQsCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtQm9sZCIKfV0sIFsiQXJpYWxOYXJyb3ctSXRhbGljIiwgewogIGFsaWFzOiAiQXJpYWxOYXJyb3ciLAogIHN0eWxlOiBJVEFMSUMsCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtT2JsaXF1ZSIKfV0sIFsiQXJpYWxOYXJyb3ctQm9sZEl0YWxpYyIsIHsKICBhbGlhczogIkFyaWFsTmFycm93IiwKICBzdHlsZTogQk9MRElUQUxJQywKICBmYWxsYmFjazogIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSIKfV0sIFsiQ2FsaWJyaSIsIHsKICBsb2NhbDogWyJDYWxpYnJpIiwgIkNhcmxpdG8iXSwKICBzdHlsZTogTk9STUFMLAogIGZhbGxiYWNrOiAiSGVsdmV0aWNhIgp9XSwgWyJDYWxpYnJpLUJvbGQiLCB7CiAgYWxpYXM6ICJDYWxpYnJpIiwKICBzdHlsZTogQk9MRCwKICBmYWxsYmFjazogIkhlbHZldGljYS1Cb2xkIgp9XSwgWyJDYWxpYnJpLUl0YWxpYyIsIHsKICBhbGlhczogIkNhbGlicmkiLAogIHN0eWxlOiBJVEFMSUMsCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtT2JsaXF1ZSIKfV0sIFsiQ2FsaWJyaS1Cb2xkSXRhbGljIiwgewogIGFsaWFzOiAiQ2FsaWJyaSIsCiAgc3R5bGU6IEJPTERJVEFMSUMsCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiCn1dLCBbIldpbmdkaW5ncyIsIHsKICBsb2NhbDogWyJXaW5nZGluZ3MiLCAiVVJXIERpbmdiYXRzIl0sCiAgc3R5bGU6IE5PUk1BTAp9XSwgWyJXaW5nZGluZ3MtUmVndWxhciIsIHsKICBhbGlhczogIldpbmdkaW5ncyIKfV0sIFsiV2luZ2RpbmdzLUJvbGQiLCB7CiAgYWxpYXM6ICJXaW5nZGluZ3MiCn1dLCBbIlx4Q0JceENFXHhDQ1x4RTUiLCB7CiAgbG9jYWw6IFsiU2ltU3VuIiwgIlNpbVN1biBSZWd1bGFyIiwgIk5TaW1TdW4iXSwKICBzdHlsZTogTk9STUFMLAogIHVsdGltYXRlOiAic2VyaWYiCn1dLCBbIlx4QkFceERBXHhDQ1x4RTUiLCB7CiAgbG9jYWw6IFsiU2ltSGVpIiwgIlNpbUhlaSBSZWd1bGFyIl0sCiAgc3R5bGU6IE5PUk1BTCwKICB1bHRpbWF0ZTogInNhbnMtc2VyaWYiCn1dLCBbIlx4QkZceEFDXHhDQ1x4RTUiLCB7CiAgbG9jYWw6IFsiS2FpVGkiLCAiU2ltS2FpIiwgIlNpbUthaSBSZWd1bGFyIl0sCiAgc3R5bGU6IE5PUk1BTCwKICB1bHRpbWF0ZTogInNhbnMtc2VyaWYiCn1dLCBbIlx4QjdceEMyXHhDQlx4Q0UiLCB7CiAgbG9jYWw6IFsiRmFuZ1NvbmciLCAiU2ltRmFuZyIsICJTaW1GYW5nIFJlZ3VsYXIiXSwKICBzdHlsZTogTk9STUFMLAogIHVsdGltYXRlOiAic2VyaWYiCn1dLCBbIlx4QkZceEFDXHhDQ1x4RTVfR0IyMzEyIiwgewogIGFsaWFzOiAiXHhCRlx4QUNceENDXHhFNSIKfV0sIFsiXHhCN1x4QzJceENCXHhDRV9HQjIzMTIiLCB7CiAgYWxpYXM6ICJceEI3XHhDMlx4Q0JceENFIgp9XSwgWyJceEMxXHhBNVx4Q0FceEU5IiwgewogIGxvY2FsOiBbIlNpbUxpIiwgIlNpbUxpIFJlZ3VsYXIiXSwKICBzdHlsZTogTk9STUFMLAogIHVsdGltYXRlOiAic2VyaWYiCn1dLCBbIlx4RDBceEMyXHhDQlx4Q0UiLCB7CiAgYWxpYXM6ICJceENCXHhDRVx4Q0NceEU1Igp9XV0pOwpjb25zdCBmb250QWxpYXNlcyA9IG5ldyBNYXAoW1siQXJpYWwtQmxhY2siLCAiQXJpYWxCbGFjayJdXSk7CmZ1bmN0aW9uIGdldFN0eWxlVG9BcHBlbmQoc3R5bGUpIHsKICBzd2l0Y2ggKHN0eWxlKSB7CiAgICBjYXNlIEJPTEQ6CiAgICAgIHJldHVybiAiQm9sZCI7CiAgICBjYXNlIElUQUxJQzoKICAgICAgcmV0dXJuICJJdGFsaWMiOwogICAgY2FzZSBCT0xESVRBTElDOgogICAgICByZXR1cm4gIkJvbGQgSXRhbGljIjsKICAgIGRlZmF1bHQ6CiAgICAgIGlmIChzdHlsZT8ud2VpZ2h0ID09PSAiYm9sZCIpIHsKICAgICAgICByZXR1cm4gIkJvbGQiOwogICAgICB9CiAgICAgIGlmIChzdHlsZT8uc3R5bGUgPT09ICJpdGFsaWMiKSB7CiAgICAgICAgcmV0dXJuICJJdGFsaWMiOwogICAgICB9CiAgfQogIHJldHVybiAiIjsKfQpmdW5jdGlvbiBnZXRGYW1pbHlOYW1lKHN0cikgewogIGNvbnN0IGtleXdvcmRzID0gbmV3IFNldChbInRoaW4iLCAiZXh0cmFsaWdodCIsICJ1bHRyYWxpZ2h0IiwgImRlbWlsaWdodCIsICJzZW1pbGlnaHQiLCAibGlnaHQiLCAiYm9vayIsICJyZWd1bGFyIiwgIm5vcm1hbCIsICJtZWRpdW0iLCAiZGVtaWJvbGQiLCAic2VtaWJvbGQiLCAiYm9sZCIsICJleHRyYWJvbGQiLCAidWx0cmFib2xkIiwgImJsYWNrIiwgImhlYXZ5IiwgImV4dHJhYmxhY2siLCAidWx0cmFibGFjayIsICJyb21hbiIsICJpdGFsaWMiLCAib2JsaXF1ZSIsICJ1bHRyYWNvbmRlbnNlZCIsICJleHRyYWNvbmRlbnNlZCIsICJjb25kZW5zZWQiLCAic2VtaWNvbmRlbnNlZCIsICJub3JtYWwiLCAic2VtaWV4cGFuZGVkIiwgImV4cGFuZGVkIiwgImV4dHJhZXhwYW5kZWQiLCAidWx0cmFleHBhbmRlZCIsICJib2xkaXRhbGljIl0pOwogIHJldHVybiBzdHIuc3BsaXQoL1stICwrXSsvZykuZmlsdGVyKHRvayA9PiAha2V5d29yZHMuaGFzKHRvay50b0xvd2VyQ2FzZSgpKSkuam9pbigiICIpOwp9CmZ1bmN0aW9uIGdlbmVyYXRlRm9udCh7CiAgYWxpYXMsCiAgbG9jYWwsCiAgcGF0aCwKICBmYWxsYmFjaywKICBzdHlsZSwKICB1bHRpbWF0ZQp9LCBzcmMsIGxvY2FsRm9udFBhdGgsIHVzZUZhbGxiYWNrID0gdHJ1ZSwgdXNlUGF0aCA9IHRydWUsIGFwcGVuZCA9ICIiKSB7CiAgY29uc3QgcmVzdWx0ID0gewogICAgc3R5bGU6IG51bGwsCiAgICB1bHRpbWF0ZTogbnVsbAogIH07CiAgaWYgKGxvY2FsKSB7CiAgICBjb25zdCBleHRyYSA9IGFwcGVuZCA/IGAgJHthcHBlbmR9YCA6ICIiOwogICAgZm9yIChjb25zdCBuYW1lIG9mIGxvY2FsKSB7CiAgICAgIHNyYy5wdXNoKGBsb2NhbCgke25hbWV9JHtleHRyYX0pYCk7CiAgICB9CiAgfQogIGlmIChhbGlhcykgewogICAgY29uc3Qgc3Vic3RpdHV0aW9uID0gc3Vic3RpdHV0aW9uTWFwLmdldChhbGlhcyk7CiAgICBjb25zdCBhbGlhc0FwcGVuZCA9IGFwcGVuZCB8fCBnZXRTdHlsZVRvQXBwZW5kKHN0eWxlKTsKICAgIE9iamVjdC5hc3NpZ24ocmVzdWx0LCBnZW5lcmF0ZUZvbnQoc3Vic3RpdHV0aW9uLCBzcmMsIGxvY2FsRm9udFBhdGgsIHVzZUZhbGxiYWNrICYmICFmYWxsYmFjaywgdXNlUGF0aCAmJiAhcGF0aCwgYWxpYXNBcHBlbmQpKTsKICB9CiAgaWYgKHN0eWxlKSB7CiAgICByZXN1bHQuc3R5bGUgPSBzdHlsZTsKICB9CiAgaWYgKHVsdGltYXRlKSB7CiAgICByZXN1bHQudWx0aW1hdGUgPSB1bHRpbWF0ZTsKICB9CiAgaWYgKHVzZUZhbGxiYWNrICYmIGZhbGxiYWNrKSB7CiAgICBjb25zdCBmYWxsYmFja0luZm8gPSBzdWJzdGl0dXRpb25NYXAuZ2V0KGZhbGxiYWNrKTsKICAgIGNvbnN0IHsKICAgICAgdWx0aW1hdGU6IGZhbGxiYWNrVWx0aW1hdGUKICAgIH0gPSBnZW5lcmF0ZUZvbnQoZmFsbGJhY2tJbmZvLCBzcmMsIGxvY2FsRm9udFBhdGgsIHVzZUZhbGxiYWNrLCB1c2VQYXRoICYmICFwYXRoLCBhcHBlbmQpOwogICAgcmVzdWx0LnVsdGltYXRlIHx8PSBmYWxsYmFja1VsdGltYXRlOwogIH0KICBpZiAodXNlUGF0aCAmJiBwYXRoICYmIGxvY2FsRm9udFBhdGgpIHsKICAgIHNyYy5wdXNoKGB1cmwoJHtsb2NhbEZvbnRQYXRofSR7cGF0aH0pYCk7CiAgfQogIHJldHVybiByZXN1bHQ7Cn0KZnVuY3Rpb24gZ2V0Rm9udFN1YnN0aXR1dGlvbihzeXN0ZW1Gb250Q2FjaGUsIGlkRmFjdG9yeSwgbG9jYWxGb250UGF0aCwgYmFzZUZvbnROYW1lLCBzdGFuZGFyZEZvbnROYW1lLCB0eXBlKSB7CiAgaWYgKGJhc2VGb250TmFtZS5zdGFydHNXaXRoKCJJbnZhbGlkUERGanNGb250XyIpKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgaWYgKCh0eXBlID09PSAiVHJ1ZVR5cGUiIHx8IHR5cGUgPT09ICJUeXBlMSIpICYmIC9eW0EtWl17Nn1cKy8udGVzdChiYXNlRm9udE5hbWUpKSB7CiAgICBiYXNlRm9udE5hbWUgPSBiYXNlRm9udE5hbWUuc2xpY2UoNyk7CiAgfQogIGJhc2VGb250TmFtZSA9IG5vcm1hbGl6ZUZvbnROYW1lKGJhc2VGb250TmFtZSk7CiAgY29uc3Qga2V5ID0gYmFzZUZvbnROYW1lOwogIGxldCBzdWJzdGl0dXRpb25JbmZvID0gc3lzdGVtRm9udENhY2hlLmdldChrZXkpOwogIGlmIChzdWJzdGl0dXRpb25JbmZvKSB7CiAgICByZXR1cm4gc3Vic3RpdHV0aW9uSW5mbzsKICB9CiAgbGV0IHN1YnN0aXR1dGlvbiA9IHN1YnN0aXR1dGlvbk1hcC5nZXQoYmFzZUZvbnROYW1lKTsKICBpZiAoIXN1YnN0aXR1dGlvbikgewogICAgZm9yIChjb25zdCBbYWxpYXMsIHN1YnN0XSBvZiBmb250QWxpYXNlcykgewogICAgICBpZiAoYmFzZUZvbnROYW1lLnN0YXJ0c1dpdGgoYWxpYXMpKSB7CiAgICAgICAgYmFzZUZvbnROYW1lID0gYCR7c3Vic3R9JHtiYXNlRm9udE5hbWUuc3Vic3RyaW5nKGFsaWFzLmxlbmd0aCl9YDsKICAgICAgICBzdWJzdGl0dXRpb24gPSBzdWJzdGl0dXRpb25NYXAuZ2V0KGJhc2VGb250TmFtZSk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICB9CiAgbGV0IG11c3RBZGRCYXNlRm9udCA9IGZhbHNlOwogIGlmICghc3Vic3RpdHV0aW9uKSB7CiAgICBzdWJzdGl0dXRpb24gPSBzdWJzdGl0dXRpb25NYXAuZ2V0KHN0YW5kYXJkRm9udE5hbWUpOwogICAgbXVzdEFkZEJhc2VGb250ID0gdHJ1ZTsKICB9CiAgY29uc3QgbG9hZGVkTmFtZSA9IGAke2lkRmFjdG9yeS5nZXREb2NJZCgpfV9zJHtpZEZhY3RvcnkuY3JlYXRlRm9udElkKCl9YDsKICBpZiAoIXN1YnN0aXR1dGlvbikgewogICAgaWYgKCF2YWxpZGF0ZUZvbnROYW1lKGJhc2VGb250TmFtZSkpIHsKICAgICAgd2FybihgQ2Fubm90IHN1YnN0aXR1dGUgdGhlIGZvbnQgYmVjYXVzZSBvZiBpdHMgbmFtZTogJHtiYXNlRm9udE5hbWV9YCk7CiAgICAgIHN5c3RlbUZvbnRDYWNoZS5zZXQoa2V5LCBudWxsKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBib2xkID0gL2JvbGQvZ2kudGVzdChiYXNlRm9udE5hbWUpOwogICAgY29uc3QgaXRhbGljID0gL29ibGlxdWV8aXRhbGljL2dpLnRlc3QoYmFzZUZvbnROYW1lKTsKICAgIGNvbnN0IHN0eWxlID0gYm9sZCAmJiBpdGFsaWMgJiYgQk9MRElUQUxJQyB8fCBib2xkICYmIEJPTEQgfHwgaXRhbGljICYmIElUQUxJQyB8fCBOT1JNQUw7CiAgICBzdWJzdGl0dXRpb25JbmZvID0gewogICAgICBjc3M6IGAiJHtnZXRGYW1pbHlOYW1lKGJhc2VGb250TmFtZSl9Iiwke2xvYWRlZE5hbWV9YCwKICAgICAgZ3Vlc3NGYWxsYmFjazogdHJ1ZSwKICAgICAgbG9hZGVkTmFtZSwKICAgICAgYmFzZUZvbnROYW1lLAogICAgICBzcmM6IGBsb2NhbCgke2Jhc2VGb250TmFtZX0pYCwKICAgICAgc3R5bGUKICAgIH07CiAgICBzeXN0ZW1Gb250Q2FjaGUuc2V0KGtleSwgc3Vic3RpdHV0aW9uSW5mbyk7CiAgICByZXR1cm4gc3Vic3RpdHV0aW9uSW5mbzsKICB9CiAgY29uc3Qgc3JjID0gW107CiAgaWYgKG11c3RBZGRCYXNlRm9udCAmJiB2YWxpZGF0ZUZvbnROYW1lKGJhc2VGb250TmFtZSkpIHsKICAgIHNyYy5wdXNoKGBsb2NhbCgke2Jhc2VGb250TmFtZX0pYCk7CiAgfQogIGNvbnN0IHsKICAgIHN0eWxlLAogICAgdWx0aW1hdGUKICB9ID0gZ2VuZXJhdGVGb250KHN1YnN0aXR1dGlvbiwgc3JjLCBsb2NhbEZvbnRQYXRoKTsKICBjb25zdCBndWVzc0ZhbGxiYWNrID0gdWx0aW1hdGUgPT09IG51bGw7CiAgY29uc3QgZmFsbGJhY2sgPSBndWVzc0ZhbGxiYWNrID8gIiIgOiBgLCR7dWx0aW1hdGV9YDsKICBzdWJzdGl0dXRpb25JbmZvID0gewogICAgY3NzOiBgIiR7Z2V0RmFtaWx5TmFtZShiYXNlRm9udE5hbWUpfSIsJHtsb2FkZWROYW1lfSR7ZmFsbGJhY2t9YCwKICAgIGd1ZXNzRmFsbGJhY2ssCiAgICBsb2FkZWROYW1lLAogICAgYmFzZUZvbnROYW1lLAogICAgc3JjOiBzcmMuam9pbigiLCIpLAogICAgc3R5bGUKICB9OwogIHN5c3RlbUZvbnRDYWNoZS5zZXQoa2V5LCBzdWJzdGl0dXRpb25JbmZvKTsKICByZXR1cm4gc3Vic3RpdHV0aW9uSW5mbzsKfQoKOy8vIC4vc3JjL3NoYXJlZC9tdXJtdXJoYXNoMy5qcwpjb25zdCBTRUVEID0gMHhjM2QyZTFmMDsKY29uc3QgTUFTS19ISUdIID0gMHhmZmZmMDAwMDsKY29uc3QgTUFTS19MT1cgPSAweGZmZmY7CmNsYXNzIE11cm11ckhhc2gzXzY0IHsKICBjb25zdHJ1Y3RvcihzZWVkKSB7CiAgICB0aGlzLmgxID0gc2VlZCA/IHNlZWQgJiAweGZmZmZmZmZmIDogU0VFRDsKICAgIHRoaXMuaDIgPSBzZWVkID8gc2VlZCAmIDB4ZmZmZmZmZmYgOiBTRUVEOwogIH0KICB1cGRhdGUoaW5wdXQpIHsKICAgIGxldCBkYXRhLCBsZW5ndGg7CiAgICBpZiAodHlwZW9mIGlucHV0ID09PSAic3RyaW5nIikgewogICAgICBkYXRhID0gbmV3IFVpbnQ4QXJyYXkoaW5wdXQubGVuZ3RoICogMik7CiAgICAgIGxlbmd0aCA9IDA7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGlucHV0Lmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb25zdCBjb2RlID0gaW5wdXQuY2hhckNvZGVBdChpKTsKICAgICAgICBpZiAoY29kZSA8PSAweGZmKSB7CiAgICAgICAgICBkYXRhW2xlbmd0aCsrXSA9IGNvZGU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGRhdGFbbGVuZ3RoKytdID0gY29kZSA+Pj4gODsKICAgICAgICAgIGRhdGFbbGVuZ3RoKytdID0gY29kZSAmIDB4ZmY7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgaWYgKEFycmF5QnVmZmVyLmlzVmlldyhpbnB1dCkpIHsKICAgICAgZGF0YSA9IGlucHV0LnNsaWNlKCk7CiAgICAgIGxlbmd0aCA9IGRhdGEuYnl0ZUxlbmd0aDsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiSW52YWxpZCBkYXRhIGZvcm1hdCwgbXVzdCBiZSBhIHN0cmluZyBvciBUeXBlZEFycmF5LiIpOwogICAgfQogICAgY29uc3QgYmxvY2tDb3VudHMgPSBsZW5ndGggPj4gMjsKICAgIGNvbnN0IHRhaWxMZW5ndGggPSBsZW5ndGggLSBibG9ja0NvdW50cyAqIDQ7CiAgICBjb25zdCBkYXRhVWludDMyID0gbmV3IFVpbnQzMkFycmF5KGRhdGEuYnVmZmVyLCAwLCBibG9ja0NvdW50cyk7CiAgICBsZXQgazEgPSAwLAogICAgICBrMiA9IDA7CiAgICBsZXQgaDEgPSB0aGlzLmgxLAogICAgICBoMiA9IHRoaXMuaDI7CiAgICBjb25zdCBDMSA9IDB4Y2M5ZTJkNTEsCiAgICAgIEMyID0gMHgxYjg3MzU5MzsKICAgIGNvbnN0IEMxX0xPVyA9IEMxICYgTUFTS19MT1csCiAgICAgIEMyX0xPVyA9IEMyICYgTUFTS19MT1c7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJsb2NrQ291bnRzOyBpKyspIHsKICAgICAgaWYgKGkgJiAxKSB7CiAgICAgICAgazEgPSBkYXRhVWludDMyW2ldOwogICAgICAgIGsxID0gazEgKiBDMSAmIE1BU0tfSElHSCB8IGsxICogQzFfTE9XICYgTUFTS19MT1c7CiAgICAgICAgazEgPSBrMSA8PCAxNSB8IGsxID4+PiAxNzsKICAgICAgICBrMSA9IGsxICogQzIgJiBNQVNLX0hJR0ggfCBrMSAqIEMyX0xPVyAmIE1BU0tfTE9XOwogICAgICAgIGgxIF49IGsxOwogICAgICAgIGgxID0gaDEgPDwgMTMgfCBoMSA+Pj4gMTk7CiAgICAgICAgaDEgPSBoMSAqIDUgKyAweGU2NTQ2YjY0OwogICAgICB9IGVsc2UgewogICAgICAgIGsyID0gZGF0YVVpbnQzMltpXTsKICAgICAgICBrMiA9IGsyICogQzEgJiBNQVNLX0hJR0ggfCBrMiAqIEMxX0xPVyAmIE1BU0tfTE9XOwogICAgICAgIGsyID0gazIgPDwgMTUgfCBrMiA+Pj4gMTc7CiAgICAgICAgazIgPSBrMiAqIEMyICYgTUFTS19ISUdIIHwgazIgKiBDMl9MT1cgJiBNQVNLX0xPVzsKICAgICAgICBoMiBePSBrMjsKICAgICAgICBoMiA9IGgyIDw8IDEzIHwgaDIgPj4+IDE5OwogICAgICAgIGgyID0gaDIgKiA1ICsgMHhlNjU0NmI2NDsKICAgICAgfQogICAgfQogICAgazEgPSAwOwogICAgc3dpdGNoICh0YWlsTGVuZ3RoKSB7CiAgICAgIGNhc2UgMzoKICAgICAgICBrMSBePSBkYXRhW2Jsb2NrQ291bnRzICogNCArIDJdIDw8IDE2OwogICAgICBjYXNlIDI6CiAgICAgICAgazEgXj0gZGF0YVtibG9ja0NvdW50cyAqIDQgKyAxXSA8PCA4OwogICAgICBjYXNlIDE6CiAgICAgICAgazEgXj0gZGF0YVtibG9ja0NvdW50cyAqIDRdOwogICAgICAgIGsxID0gazEgKiBDMSAmIE1BU0tfSElHSCB8IGsxICogQzFfTE9XICYgTUFTS19MT1c7CiAgICAgICAgazEgPSBrMSA8PCAxNSB8IGsxID4+PiAxNzsKICAgICAgICBrMSA9IGsxICogQzIgJiBNQVNLX0hJR0ggfCBrMSAqIEMyX0xPVyAmIE1BU0tfTE9XOwogICAgICAgIGlmIChibG9ja0NvdW50cyAmIDEpIHsKICAgICAgICAgIGgxIF49IGsxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBoMiBePSBrMTsKICAgICAgICB9CiAgICB9CiAgICB0aGlzLmgxID0gaDE7CiAgICB0aGlzLmgyID0gaDI7CiAgfQogIGhleGRpZ2VzdCgpIHsKICAgIGxldCBoMSA9IHRoaXMuaDEsCiAgICAgIGgyID0gdGhpcy5oMjsKICAgIGgxIF49IGgyID4+PiAxOwogICAgaDEgPSBoMSAqIDB4ZWQ1NThjY2QgJiBNQVNLX0hJR0ggfCBoMSAqIDB4OGNjZCAmIE1BU0tfTE9XOwogICAgaDIgPSBoMiAqIDB4ZmY1MWFmZDcgJiBNQVNLX0hJR0ggfCAoKGgyIDw8IDE2IHwgaDEgPj4+IDE2KSAqIDB4YWZkN2VkNTUgJiBNQVNLX0hJR0gpID4+PiAxNjsKICAgIGgxIF49IGgyID4+PiAxOwogICAgaDEgPSBoMSAqIDB4MWE4NWVjNTMgJiBNQVNLX0hJR0ggfCBoMSAqIDB4ZWM1MyAmIE1BU0tfTE9XOwogICAgaDIgPSBoMiAqIDB4YzRjZWI5ZmUgJiBNQVNLX0hJR0ggfCAoKGgyIDw8IDE2IHwgaDEgPj4+IDE2KSAqIDB4YjlmZTFhODUgJiBNQVNLX0hJR0gpID4+PiAxNjsKICAgIGgxIF49IGgyID4+PiAxOwogICAgcmV0dXJuIChoMSA+Pj4gMCkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDgsICIwIikgKyAoaDIgPj4+IDApLnRvU3RyaW5nKDE2KS5wYWRTdGFydCg4LCAiMCIpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvaW1hZ2UuanMKCgoKCgoKCgoKCmZ1bmN0aW9uIHJlc2l6ZUltYWdlTWFzayhzcmMsIGJwYywgdzEsIGgxLCB3MiwgaDIpIHsKICBjb25zdCBsZW5ndGggPSB3MiAqIGgyOwogIGxldCBkZXN0OwogIGlmIChicGMgPD0gOCkgewogICAgZGVzdCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCk7CiAgfSBlbHNlIGlmIChicGMgPD0gMTYpIHsKICAgIGRlc3QgPSBuZXcgVWludDE2QXJyYXkobGVuZ3RoKTsKICB9IGVsc2UgewogICAgZGVzdCA9IG5ldyBVaW50MzJBcnJheShsZW5ndGgpOwogIH0KICBjb25zdCB4UmF0aW8gPSB3MSAvIHcyOwogIGNvbnN0IHlSYXRpbyA9IGgxIC8gaDI7CiAgbGV0IGksCiAgICBqLAogICAgcHksCiAgICBuZXdJbmRleCA9IDAsCiAgICBvbGRJbmRleDsKICBjb25zdCB4U2NhbGVkID0gbmV3IFVpbnQxNkFycmF5KHcyKTsKICBjb25zdCB3MVNjYW5saW5lID0gdzE7CiAgZm9yIChpID0gMDsgaSA8IHcyOyBpKyspIHsKICAgIHhTY2FsZWRbaV0gPSBNYXRoLmZsb29yKGkgKiB4UmF0aW8pOwogIH0KICBmb3IgKGkgPSAwOyBpIDwgaDI7IGkrKykgewogICAgcHkgPSBNYXRoLmZsb29yKGkgKiB5UmF0aW8pICogdzFTY2FubGluZTsKICAgIGZvciAoaiA9IDA7IGogPCB3MjsgaisrKSB7CiAgICAgIG9sZEluZGV4ID0gcHkgKyB4U2NhbGVkW2pdOwogICAgICBkZXN0W25ld0luZGV4KytdID0gc3JjW29sZEluZGV4XTsKICAgIH0KICB9CiAgcmV0dXJuIGRlc3Q7Cn0KY2xhc3MgUERGSW1hZ2UgewogIGNvbnN0cnVjdG9yKHsKICAgIHhyZWYsCiAgICByZXMsCiAgICBpbWFnZSwKICAgIGlzSW5saW5lID0gZmFsc2UsCiAgICBzbWFzayA9IG51bGwsCiAgICBtYXNrID0gbnVsbCwKICAgIGlzTWFzayA9IGZhbHNlLAogICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICB9KSB7CiAgICB0aGlzLmltYWdlID0gaW1hZ2U7CiAgICBjb25zdCBkaWN0ID0gaW1hZ2UuZGljdDsKICAgIGNvbnN0IGZpbHRlciA9IGRpY3QuZ2V0KCJGIiwgIkZpbHRlciIpOwogICAgbGV0IGZpbHRlck5hbWU7CiAgICBpZiAoZmlsdGVyIGluc3RhbmNlb2YgTmFtZSkgewogICAgICBmaWx0ZXJOYW1lID0gZmlsdGVyLm5hbWU7CiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZmlsdGVyKSkgewogICAgICBjb25zdCBmaWx0ZXJaZXJvID0geHJlZi5mZXRjaElmUmVmKGZpbHRlclswXSk7CiAgICAgIGlmIChmaWx0ZXJaZXJvIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgIGZpbHRlck5hbWUgPSBmaWx0ZXJaZXJvLm5hbWU7CiAgICAgIH0KICAgIH0KICAgIHN3aXRjaCAoZmlsdGVyTmFtZSkgewogICAgICBjYXNlICJKUFhEZWNvZGUiOgogICAgICAgICh7CiAgICAgICAgICB3aWR0aDogaW1hZ2Uud2lkdGgsCiAgICAgICAgICBoZWlnaHQ6IGltYWdlLmhlaWdodCwKICAgICAgICAgIGNvbXBvbmVudHNDb3VudDogaW1hZ2UubnVtQ29tcHMsCiAgICAgICAgICBiaXRzUGVyQ29tcG9uZW50OiBpbWFnZS5iaXRzUGVyQ29tcG9uZW50CiAgICAgICAgfSA9IEpweEltYWdlLnBhcnNlSW1hZ2VQcm9wZXJ0aWVzKGltYWdlLnN0cmVhbSkpOwogICAgICAgIGltYWdlLnN0cmVhbS5yZXNldCgpOwogICAgICAgIGNvbnN0IHJlZHVjZVBvd2VyID0gSW1hZ2VSZXNpemVyLmdldFJlZHVjZVBvd2VyRm9ySlBYKGltYWdlLndpZHRoLCBpbWFnZS5oZWlnaHQsIGltYWdlLm51bUNvbXBzKTsKICAgICAgICB0aGlzLmpweERlY29kZXJPcHRpb25zID0gewogICAgICAgICAgbnVtQ29tcG9uZW50czogMCwKICAgICAgICAgIGlzSW5kZXhlZENvbG9ybWFwOiBmYWxzZSwKICAgICAgICAgIHNtYXNrSW5EYXRhOiBkaWN0LmhhcygiU01hc2tJbkRhdGEiKSwKICAgICAgICAgIHJlZHVjZVBvd2VyCiAgICAgICAgfTsKICAgICAgICBpZiAocmVkdWNlUG93ZXIpIHsKICAgICAgICAgIGNvbnN0IGZhY3RvciA9IDIgKiogcmVkdWNlUG93ZXI7CiAgICAgICAgICBpbWFnZS53aWR0aCA9IE1hdGguY2VpbChpbWFnZS53aWR0aCAvIGZhY3Rvcik7CiAgICAgICAgICBpbWFnZS5oZWlnaHQgPSBNYXRoLmNlaWwoaW1hZ2UuaGVpZ2h0IC8gZmFjdG9yKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIkpCSUcyRGVjb2RlIjoKICAgICAgICBpbWFnZS5iaXRzUGVyQ29tcG9uZW50ID0gMTsKICAgICAgICBpbWFnZS5udW1Db21wcyA9IDE7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBsZXQgd2lkdGggPSBkaWN0LmdldCgiVyIsICJXaWR0aCIpOwogICAgbGV0IGhlaWdodCA9IGRpY3QuZ2V0KCJIIiwgIkhlaWdodCIpOwogICAgaWYgKE51bWJlci5pc0ludGVnZXIoaW1hZ2Uud2lkdGgpICYmIGltYWdlLndpZHRoID4gMCAmJiBOdW1iZXIuaXNJbnRlZ2VyKGltYWdlLmhlaWdodCkgJiYgaW1hZ2UuaGVpZ2h0ID4gMCAmJiAoaW1hZ2Uud2lkdGggIT09IHdpZHRoIHx8IGltYWdlLmhlaWdodCAhPT0gaGVpZ2h0KSkgewogICAgICB3YXJuKCJQREZJbWFnZSAtIHVzaW5nIHRoZSBXaWR0aC9IZWlnaHQgb2YgdGhlIGltYWdlIGRhdGEsICIgKyAicmF0aGVyIHRoYW4gdGhlIGltYWdlIGRpY3Rpb25hcnkuIik7CiAgICAgIHdpZHRoID0gaW1hZ2Uud2lkdGg7CiAgICAgIGhlaWdodCA9IGltYWdlLmhlaWdodDsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IHZhbGlkV2lkdGggPSB0eXBlb2Ygd2lkdGggPT09ICJudW1iZXIiICYmIHdpZHRoID4gMCwKICAgICAgICB2YWxpZEhlaWdodCA9IHR5cGVvZiBoZWlnaHQgPT09ICJudW1iZXIiICYmIGhlaWdodCA+IDA7CiAgICAgIGlmICghdmFsaWRXaWR0aCB8fCAhdmFsaWRIZWlnaHQpIHsKICAgICAgICBpZiAoIWltYWdlLmZhbGxiYWNrRGltcykgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIGltYWdlIHdpZHRoOiAke3dpZHRofSBvciBoZWlnaHQ6ICR7aGVpZ2h0fWApOwogICAgICAgIH0KICAgICAgICB3YXJuKCJQREZJbWFnZSAtIHVzaW5nIHRoZSBXaWR0aC9IZWlnaHQgb2YgdGhlIHBhcmVudCBpbWFnZSwgZm9yIFNNYXNrL01hc2sgZGF0YS4iKTsKICAgICAgICBpZiAoIXZhbGlkV2lkdGgpIHsKICAgICAgICAgIHdpZHRoID0gaW1hZ2UuZmFsbGJhY2tEaW1zLndpZHRoOwogICAgICAgIH0KICAgICAgICBpZiAoIXZhbGlkSGVpZ2h0KSB7CiAgICAgICAgICBoZWlnaHQgPSBpbWFnZS5mYWxsYmFja0RpbXMuaGVpZ2h0OwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgdGhpcy53aWR0aCA9IHdpZHRoOwogICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7CiAgICB0aGlzLmludGVycG9sYXRlID0gZGljdC5nZXQoIkkiLCAiSW50ZXJwb2xhdGUiKTsKICAgIHRoaXMuaW1hZ2VNYXNrID0gZGljdC5nZXQoIklNIiwgIkltYWdlTWFzayIpIHx8IGZhbHNlOwogICAgdGhpcy5tYXR0ZSA9IGRpY3QuZ2V0KCJNYXR0ZSIpIHx8IGZhbHNlOwogICAgbGV0IGJpdHNQZXJDb21wb25lbnQgPSBpbWFnZS5iaXRzUGVyQ29tcG9uZW50OwogICAgaWYgKCFiaXRzUGVyQ29tcG9uZW50KSB7CiAgICAgIGJpdHNQZXJDb21wb25lbnQgPSBkaWN0LmdldCgiQlBDIiwgIkJpdHNQZXJDb21wb25lbnQiKTsKICAgICAgaWYgKCFiaXRzUGVyQ29tcG9uZW50KSB7CiAgICAgICAgaWYgKHRoaXMuaW1hZ2VNYXNrKSB7CiAgICAgICAgICBiaXRzUGVyQ29tcG9uZW50ID0gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBCaXRzIHBlciBjb21wb25lbnQgbWlzc2luZyBpbiBpbWFnZTogJHt0aGlzLmltYWdlTWFza31gKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHRoaXMuYnBjID0gYml0c1BlckNvbXBvbmVudDsKICAgIGlmICghdGhpcy5pbWFnZU1hc2spIHsKICAgICAgbGV0IGNvbG9yU3BhY2UgPSBkaWN0LmdldFJhdygiQ1MiKSB8fCBkaWN0LmdldFJhdygiQ29sb3JTcGFjZSIpOwogICAgICBjb25zdCBoYXNDb2xvclNwYWNlID0gISFjb2xvclNwYWNlOwogICAgICBpZiAoIWhhc0NvbG9yU3BhY2UpIHsKICAgICAgICBpZiAodGhpcy5qcHhEZWNvZGVyT3B0aW9ucykgewogICAgICAgICAgY29sb3JTcGFjZSA9IE5hbWUuZ2V0KCJEZXZpY2VSR0JBIik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN3aXRjaCAoaW1hZ2UubnVtQ29tcHMpIHsKICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgIGNvbG9yU3BhY2UgPSBOYW1lLmdldCgiRGV2aWNlR3JheSIpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgICAgY29sb3JTcGFjZSA9IE5hbWUuZ2V0KCJEZXZpY2VSR0IiKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICAgIGNvbG9yU3BhY2UgPSBOYW1lLmdldCgiRGV2aWNlQ01ZSyIpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW1hZ2VzIHdpdGggJHtpbWFnZS5udW1Db21wc30gY29sb3IgY29tcG9uZW50cyBub3Qgc3VwcG9ydGVkLmApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIGlmICh0aGlzLmpweERlY29kZXJPcHRpb25zPy5zbWFza0luRGF0YSkgewogICAgICAgIGNvbG9yU3BhY2UgPSBOYW1lLmdldCgiRGV2aWNlUkdCQSIpOwogICAgICB9CiAgICAgIHRoaXMuY29sb3JTcGFjZSA9IENvbG9yU3BhY2VVdGlscy5wYXJzZSh7CiAgICAgICAgY3M6IGNvbG9yU3BhY2UsCiAgICAgICAgeHJlZiwKICAgICAgICByZXNvdXJjZXM6IGlzSW5saW5lID8gcmVzIDogbnVsbCwKICAgICAgICBwZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICAgIH0pOwogICAgICB0aGlzLm51bUNvbXBzID0gdGhpcy5jb2xvclNwYWNlLm51bUNvbXBzOwogICAgICBpZiAodGhpcy5qcHhEZWNvZGVyT3B0aW9ucykgewogICAgICAgIHRoaXMuanB4RGVjb2Rlck9wdGlvbnMubnVtQ29tcG9uZW50cyA9IGhhc0NvbG9yU3BhY2UgPyB0aGlzLm51bUNvbXBzIDogMDsKICAgICAgICB0aGlzLmpweERlY29kZXJPcHRpb25zLmlzSW5kZXhlZENvbG9ybWFwID0gdGhpcy5jb2xvclNwYWNlLm5hbWUgPT09ICJJbmRleGVkIjsKICAgICAgfQogICAgfQogICAgdGhpcy5kZWNvZGUgPSBkaWN0LmdldEFycmF5KCJEIiwgIkRlY29kZSIpOwogICAgdGhpcy5uZWVkc0RlY29kZSA9IGZhbHNlOwogICAgaWYgKHRoaXMuZGVjb2RlICYmICh0aGlzLmNvbG9yU3BhY2UgJiYgIXRoaXMuY29sb3JTcGFjZS5pc0RlZmF1bHREZWNvZGUodGhpcy5kZWNvZGUsIGJpdHNQZXJDb21wb25lbnQpIHx8IGlzTWFzayAmJiAhQ29sb3JTcGFjZS5pc0RlZmF1bHREZWNvZGUodGhpcy5kZWNvZGUsIDEpKSkgewogICAgICB0aGlzLm5lZWRzRGVjb2RlID0gdHJ1ZTsKICAgICAgY29uc3QgbWF4ID0gKDEgPDwgYml0c1BlckNvbXBvbmVudCkgLSAxOwogICAgICB0aGlzLmRlY29kZUNvZWZmaWNpZW50cyA9IFtdOwogICAgICB0aGlzLmRlY29kZUFkZGVuZHMgPSBbXTsKICAgICAgY29uc3QgaXNJbmRleGVkID0gdGhpcy5jb2xvclNwYWNlPy5uYW1lID09PSAiSW5kZXhlZCI7CiAgICAgIGZvciAobGV0IGkgPSAwLCBqID0gMDsgaSA8IHRoaXMuZGVjb2RlLmxlbmd0aDsgaSArPSAyLCArK2opIHsKICAgICAgICBjb25zdCBkbWluID0gdGhpcy5kZWNvZGVbaV07CiAgICAgICAgY29uc3QgZG1heCA9IHRoaXMuZGVjb2RlW2kgKyAxXTsKICAgICAgICB0aGlzLmRlY29kZUNvZWZmaWNpZW50c1tqXSA9IGlzSW5kZXhlZCA/IChkbWF4IC0gZG1pbikgLyBtYXggOiBkbWF4IC0gZG1pbjsKICAgICAgICB0aGlzLmRlY29kZUFkZGVuZHNbal0gPSBpc0luZGV4ZWQgPyBkbWluIDogbWF4ICogZG1pbjsKICAgICAgfQogICAgfQogICAgaWYgKHNtYXNrKSB7CiAgICAgIHNtYXNrLmZhbGxiYWNrRGltcyA/Pz0gewogICAgICAgIHdpZHRoLAogICAgICAgIGhlaWdodAogICAgICB9OwogICAgICB0aGlzLnNtYXNrID0gbmV3IFBERkltYWdlKHsKICAgICAgICB4cmVmLAogICAgICAgIHJlcywKICAgICAgICBpbWFnZTogc21hc2ssCiAgICAgICAgaXNJbmxpbmUsCiAgICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgICB9KTsKICAgIH0gZWxzZSBpZiAobWFzaykgewogICAgICBpZiAobWFzayBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgICBjb25zdCBtYXNrRGljdCA9IG1hc2suZGljdCwKICAgICAgICAgIGltYWdlTWFzayA9IG1hc2tEaWN0LmdldCgiSU0iLCAiSW1hZ2VNYXNrIik7CiAgICAgICAgaWYgKCFpbWFnZU1hc2spIHsKICAgICAgICAgIHdhcm4oIklnbm9yaW5nIC9NYXNrIGluIGltYWdlIHdpdGhvdXQgL0ltYWdlTWFzay4iKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbWFzay5mYWxsYmFja0RpbXMgPz89IHsKICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgIGhlaWdodAogICAgICAgICAgfTsKICAgICAgICAgIHRoaXMubWFzayA9IG5ldyBQREZJbWFnZSh7CiAgICAgICAgICAgIHhyZWYsCiAgICAgICAgICAgIHJlcywKICAgICAgICAgICAgaW1hZ2U6IG1hc2ssCiAgICAgICAgICAgIGlzSW5saW5lLAogICAgICAgICAgICBpc01hc2s6IHRydWUsCiAgICAgICAgICAgIHBkZkZ1bmN0aW9uRmFjdG9yeSwKICAgICAgICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMubWFzayA9IG1hc2s7CiAgICAgIH0KICAgIH0KICB9CiAgc3RhdGljIGFzeW5jIGJ1aWxkSW1hZ2UoewogICAgeHJlZiwKICAgIHJlcywKICAgIGltYWdlLAogICAgaXNJbmxpbmUgPSBmYWxzZSwKICAgIHBkZkZ1bmN0aW9uRmFjdG9yeSwKICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgfSkgewogICAgY29uc3QgaW1hZ2VEYXRhID0gaW1hZ2U7CiAgICBsZXQgc21hc2tEYXRhID0gbnVsbDsKICAgIGxldCBtYXNrRGF0YSA9IG51bGw7CiAgICBjb25zdCBzbWFzayA9IGltYWdlLmRpY3QuZ2V0KCJTTWFzayIpOwogICAgY29uc3QgbWFzayA9IGltYWdlLmRpY3QuZ2V0KCJNYXNrIik7CiAgICBpZiAoc21hc2spIHsKICAgICAgaWYgKHNtYXNrIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICAgIHNtYXNrRGF0YSA9IHNtYXNrOwogICAgICB9IGVsc2UgewogICAgICAgIHdhcm4oIlVuc3VwcG9ydGVkIC9TTWFzayBmb3JtYXQuIik7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAobWFzaykgewogICAgICBpZiAobWFzayBpbnN0YW5jZW9mIEJhc2VTdHJlYW0gfHwgQXJyYXkuaXNBcnJheShtYXNrKSkgewogICAgICAgIG1hc2tEYXRhID0gbWFzazsKICAgICAgfSBlbHNlIHsKICAgICAgICB3YXJuKCJVbnN1cHBvcnRlZCAvTWFzayBmb3JtYXQuIik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBuZXcgUERGSW1hZ2UoewogICAgICB4cmVmLAogICAgICByZXMsCiAgICAgIGltYWdlOiBpbWFnZURhdGEsCiAgICAgIGlzSW5saW5lLAogICAgICBzbWFzazogc21hc2tEYXRhLAogICAgICBtYXNrOiBtYXNrRGF0YSwKICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGUsCiAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICB9KTsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZU1hc2soewogICAgaW1hZ2UsCiAgICBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCA9IGZhbHNlCiAgfSkgewogICAgY29uc3QgewogICAgICBkaWN0CiAgICB9ID0gaW1hZ2U7CiAgICBjb25zdCB3aWR0aCA9IGRpY3QuZ2V0KCJXIiwgIldpZHRoIik7CiAgICBjb25zdCBoZWlnaHQgPSBkaWN0LmdldCgiSCIsICJIZWlnaHQiKTsKICAgIGNvbnN0IGludGVycG9sYXRlID0gZGljdC5nZXQoIkkiLCAiSW50ZXJwb2xhdGUiKTsKICAgIGNvbnN0IGRlY29kZSA9IGRpY3QuZ2V0QXJyYXkoIkQiLCAiRGVjb2RlIik7CiAgICBjb25zdCBpbnZlcnNlRGVjb2RlID0gZGVjb2RlPy5bMF0gPiAwOwogICAgY29uc3QgY29tcHV0ZWRMZW5ndGggPSAod2lkdGggKyA3ID4+IDMpICogaGVpZ2h0OwogICAgY29uc3QgaW1nQXJyYXkgPSBhd2FpdCBpbWFnZS5nZXRJbWFnZURhdGEoY29tcHV0ZWRMZW5ndGgpOwogICAgY29uc3QgaXNTaW5nbGVPcGFxdWVQaXhlbCA9IHdpZHRoID09PSAxICYmIGhlaWdodCA9PT0gMSAmJiBpbnZlcnNlRGVjb2RlID09PSAoaW1nQXJyYXkubGVuZ3RoID09PSAwIHx8ICEhKGltZ0FycmF5WzBdICYgMTI4KSk7CiAgICBpZiAoaXNTaW5nbGVPcGFxdWVQaXhlbCkgewogICAgICByZXR1cm4gewogICAgICAgIGlzU2luZ2xlT3BhcXVlUGl4ZWwKICAgICAgfTsKICAgIH0KICAgIGlmIChpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCkgewogICAgICBpZiAoSW1hZ2VSZXNpemVyLm5lZWRzVG9CZVJlc2l6ZWQod2lkdGgsIGhlaWdodCkpIHsKICAgICAgICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHdpZHRoICogaGVpZ2h0ICogNCk7CiAgICAgICAgY29udmVydEJsYWNrQW5kV2hpdGVUb1JHQkEoewogICAgICAgICAgc3JjOiBpbWdBcnJheSwKICAgICAgICAgIGRlc3Q6IGRhdGEsCiAgICAgICAgICB3aWR0aCwKICAgICAgICAgIGhlaWdodCwKICAgICAgICAgIG5vbkJsYWNrQ29sb3I6IDAsCiAgICAgICAgICBpbnZlcnNlRGVjb2RlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIEltYWdlUmVzaXplci5jcmVhdGVJbWFnZSh7CiAgICAgICAgICBraW5kOiBJbWFnZUtpbmQuUkdCQV8zMkJQUCwKICAgICAgICAgIGRhdGEsCiAgICAgICAgICB3aWR0aCwKICAgICAgICAgIGhlaWdodCwKICAgICAgICAgIGludGVycG9sYXRlCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgY29uc3QgY2FudmFzID0gbmV3IE9mZnNjcmVlbkNhbnZhcyh3aWR0aCwgaGVpZ2h0KTsKICAgICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgICAgIGNvbnN0IGltZ0RhdGEgPSBjdHguY3JlYXRlSW1hZ2VEYXRhKHdpZHRoLCBoZWlnaHQpOwogICAgICBjb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQSh7CiAgICAgICAgc3JjOiBpbWdBcnJheSwKICAgICAgICBkZXN0OiBpbWdEYXRhLmRhdGEsCiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0LAogICAgICAgIG5vbkJsYWNrQ29sb3I6IDAsCiAgICAgICAgaW52ZXJzZURlY29kZQogICAgICB9KTsKICAgICAgY3R4LnB1dEltYWdlRGF0YShpbWdEYXRhLCAwLCAwKTsKICAgICAgY29uc3QgYml0bWFwID0gY2FudmFzLnRyYW5zZmVyVG9JbWFnZUJpdG1hcCgpOwogICAgICByZXR1cm4gewogICAgICAgIGRhdGE6IG51bGwsCiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0LAogICAgICAgIGludGVycG9sYXRlLAogICAgICAgIGJpdG1hcAogICAgICB9OwogICAgfQogICAgY29uc3QgYWN0dWFsTGVuZ3RoID0gaW1nQXJyYXkuYnl0ZUxlbmd0aDsKICAgIGNvbnN0IGhhdmVGdWxsRGF0YSA9IGNvbXB1dGVkTGVuZ3RoID09PSBhY3R1YWxMZW5ndGg7CiAgICBsZXQgZGF0YTsKICAgIGlmIChpbWFnZSBpbnN0YW5jZW9mIERlY29kZVN0cmVhbSAmJiAoIWludmVyc2VEZWNvZGUgfHwgaGF2ZUZ1bGxEYXRhKSkgewogICAgICBkYXRhID0gaW1nQXJyYXk7CiAgICB9IGVsc2UgaWYgKCFpbnZlcnNlRGVjb2RlKSB7CiAgICAgIGRhdGEgPSBuZXcgVWludDhBcnJheShpbWdBcnJheSk7CiAgICB9IGVsc2UgewogICAgICBkYXRhID0gbmV3IFVpbnQ4QXJyYXkoY29tcHV0ZWRMZW5ndGgpOwogICAgICBkYXRhLnNldChpbWdBcnJheSk7CiAgICAgIGRhdGEuZmlsbCgweGZmLCBhY3R1YWxMZW5ndGgpOwogICAgfQogICAgaWYgKGludmVyc2VEZWNvZGUpIHsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhY3R1YWxMZW5ndGg7IGkrKykgewogICAgICAgIGRhdGFbaV0gXj0gMHhmZjsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHsKICAgICAgZGF0YSwKICAgICAgd2lkdGgsCiAgICAgIGhlaWdodCwKICAgICAgaW50ZXJwb2xhdGUKICAgIH07CiAgfQogIGdldCBkcmF3V2lkdGgoKSB7CiAgICByZXR1cm4gTWF0aC5tYXgodGhpcy53aWR0aCwgdGhpcy5zbWFzaz8ud2lkdGggfHwgMCwgdGhpcy5tYXNrPy53aWR0aCB8fCAwKTsKICB9CiAgZ2V0IGRyYXdIZWlnaHQoKSB7CiAgICByZXR1cm4gTWF0aC5tYXgodGhpcy5oZWlnaHQsIHRoaXMuc21hc2s/LmhlaWdodCB8fCAwLCB0aGlzLm1hc2s/LmhlaWdodCB8fCAwKTsKICB9CiAgZGVjb2RlQnVmZmVyKGJ1ZmZlcikgewogICAgY29uc3QgYnBjID0gdGhpcy5icGM7CiAgICBjb25zdCBudW1Db21wcyA9IHRoaXMubnVtQ29tcHM7CiAgICBjb25zdCBkZWNvZGVBZGRlbmRzID0gdGhpcy5kZWNvZGVBZGRlbmRzOwogICAgY29uc3QgZGVjb2RlQ29lZmZpY2llbnRzID0gdGhpcy5kZWNvZGVDb2VmZmljaWVudHM7CiAgICBjb25zdCBtYXggPSAoMSA8PCBicGMpIC0gMTsKICAgIGxldCBpLCBpaTsKICAgIGlmIChicGMgPT09IDEpIHsKICAgICAgZm9yIChpID0gMCwgaWkgPSBidWZmZXIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGJ1ZmZlcltpXSA9ICshYnVmZmVyW2ldOwogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCBpbmRleCA9IDA7CiAgICBmb3IgKGkgPSAwLCBpaSA9IHRoaXMud2lkdGggKiB0aGlzLmhlaWdodDsgaSA8IGlpOyBpKyspIHsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBudW1Db21wczsgaisrKSB7CiAgICAgICAgYnVmZmVyW2luZGV4XSA9IE1hdGhDbGFtcChkZWNvZGVBZGRlbmRzW2pdICsgYnVmZmVyW2luZGV4XSAqIGRlY29kZUNvZWZmaWNpZW50c1tqXSwgMCwgbWF4KTsKICAgICAgICBpbmRleCsrOwogICAgICB9CiAgICB9CiAgfQogIGdldENvbXBvbmVudHMoYnVmZmVyKSB7CiAgICBjb25zdCBicGMgPSB0aGlzLmJwYzsKICAgIGlmIChicGMgPT09IDgpIHsKICAgICAgcmV0dXJuIGJ1ZmZlcjsKICAgIH0KICAgIGNvbnN0IHdpZHRoID0gdGhpcy53aWR0aDsKICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuaGVpZ2h0OwogICAgY29uc3QgbnVtQ29tcHMgPSB0aGlzLm51bUNvbXBzOwogICAgY29uc3QgbGVuZ3RoID0gd2lkdGggKiBoZWlnaHQgKiBudW1Db21wczsKICAgIGxldCBidWZmZXJQb3MgPSAwOwogICAgbGV0IG91dHB1dDsKICAgIGlmIChicGMgPD0gOCkgewogICAgICBvdXRwdXQgPSBuZXcgVWludDhBcnJheShsZW5ndGgpOwogICAgfSBlbHNlIGlmIChicGMgPD0gMTYpIHsKICAgICAgb3V0cHV0ID0gbmV3IFVpbnQxNkFycmF5KGxlbmd0aCk7CiAgICB9IGVsc2UgewogICAgICBvdXRwdXQgPSBuZXcgVWludDMyQXJyYXkobGVuZ3RoKTsKICAgIH0KICAgIGNvbnN0IHJvd0NvbXBzID0gd2lkdGggKiBudW1Db21wczsKICAgIGNvbnN0IG1heCA9ICgxIDw8IGJwYykgLSAxOwogICAgbGV0IGkgPSAwLAogICAgICBpaSwKICAgICAgYnVmOwogICAgaWYgKGJwYyA9PT0gMSkgewogICAgICBsZXQgbWFzaywgbG9vcDFFbmQsIGxvb3AyRW5kOwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGhlaWdodDsgaisrKSB7CiAgICAgICAgbG9vcDFFbmQgPSBpICsgKHJvd0NvbXBzICYgfjcpOwogICAgICAgIGxvb3AyRW5kID0gaSArIHJvd0NvbXBzOwogICAgICAgIHdoaWxlIChpIDwgbG9vcDFFbmQpIHsKICAgICAgICAgIGJ1ZiA9IGJ1ZmZlcltidWZmZXJQb3MrK107CiAgICAgICAgICBvdXRwdXRbaV0gPSBidWYgPj4gNyAmIDE7CiAgICAgICAgICBvdXRwdXRbaSArIDFdID0gYnVmID4+IDYgJiAxOwogICAgICAgICAgb3V0cHV0W2kgKyAyXSA9IGJ1ZiA+PiA1ICYgMTsKICAgICAgICAgIG91dHB1dFtpICsgM10gPSBidWYgPj4gNCAmIDE7CiAgICAgICAgICBvdXRwdXRbaSArIDRdID0gYnVmID4+IDMgJiAxOwogICAgICAgICAgb3V0cHV0W2kgKyA1XSA9IGJ1ZiA+PiAyICYgMTsKICAgICAgICAgIG91dHB1dFtpICsgNl0gPSBidWYgPj4gMSAmIDE7CiAgICAgICAgICBvdXRwdXRbaSArIDddID0gYnVmICYgMTsKICAgICAgICAgIGkgKz0gODsKICAgICAgICB9CiAgICAgICAgaWYgKGkgPCBsb29wMkVuZCkgewogICAgICAgICAgYnVmID0gYnVmZmVyW2J1ZmZlclBvcysrXTsKICAgICAgICAgIG1hc2sgPSAxMjg7CiAgICAgICAgICB3aGlsZSAoaSA8IGxvb3AyRW5kKSB7CiAgICAgICAgICAgIG91dHB1dFtpKytdID0gKyEhKGJ1ZiAmIG1hc2spOwogICAgICAgICAgICBtYXNrID4+PSAxOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgbGV0IGJpdHMgPSAwOwogICAgICBidWYgPSAwOwogICAgICBmb3IgKGkgPSAwLCBpaSA9IGxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgICBpZiAoaSAlIHJvd0NvbXBzID09PSAwKSB7CiAgICAgICAgICBidWYgPSAwOwogICAgICAgICAgYml0cyA9IDA7CiAgICAgICAgfQogICAgICAgIHdoaWxlIChiaXRzIDwgYnBjKSB7CiAgICAgICAgICBidWYgPSBidWYgPDwgOCB8IGJ1ZmZlcltidWZmZXJQb3MrK107CiAgICAgICAgICBiaXRzICs9IDg7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHJlbWFpbmluZ0JpdHMgPSBiaXRzIC0gYnBjOwogICAgICAgIGxldCB2YWx1ZSA9IGJ1ZiA+PiByZW1haW5pbmdCaXRzOwogICAgICAgIGlmICh2YWx1ZSA8IDApIHsKICAgICAgICAgIHZhbHVlID0gMDsKICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID4gbWF4KSB7CiAgICAgICAgICB2YWx1ZSA9IG1heDsKICAgICAgICB9CiAgICAgICAgb3V0cHV0W2ldID0gdmFsdWU7CiAgICAgICAgYnVmICY9ICgxIDw8IHJlbWFpbmluZ0JpdHMpIC0gMTsKICAgICAgICBiaXRzID0gcmVtYWluaW5nQml0czsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG91dHB1dDsKICB9CiAgYXN5bmMgZmlsbE9wYWNpdHkocmdiYUJ1Ziwgd2lkdGgsIGhlaWdodCwgYWN0dWFsSGVpZ2h0LCBpbWFnZSkgewogICAgY29uc3Qgc21hc2sgPSB0aGlzLnNtYXNrOwogICAgY29uc3QgbWFzayA9IHRoaXMubWFzazsKICAgIGxldCBhbHBoYUJ1Ziwgc3csIHNoLCBpLCBpaSwgajsKICAgIGlmIChzbWFzaykgewogICAgICBzdyA9IHNtYXNrLndpZHRoOwogICAgICBzaCA9IHNtYXNrLmhlaWdodDsKICAgICAgYWxwaGFCdWYgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoc3cgKiBzaCk7CiAgICAgIGF3YWl0IHNtYXNrLmZpbGxHcmF5QnVmZmVyKGFscGhhQnVmKTsKICAgICAgaWYgKHN3ICE9PSB3aWR0aCB8fCBzaCAhPT0gaGVpZ2h0KSB7CiAgICAgICAgYWxwaGFCdWYgPSByZXNpemVJbWFnZU1hc2soYWxwaGFCdWYsIHNtYXNrLmJwYywgc3csIHNoLCB3aWR0aCwgaGVpZ2h0KTsKICAgICAgfQogICAgfSBlbHNlIGlmIChtYXNrKSB7CiAgICAgIGlmIChtYXNrIGluc3RhbmNlb2YgUERGSW1hZ2UpIHsKICAgICAgICBzdyA9IG1hc2sud2lkdGg7CiAgICAgICAgc2ggPSBtYXNrLmhlaWdodDsKICAgICAgICBhbHBoYUJ1ZiA9IG5ldyBVaW50OENsYW1wZWRBcnJheShzdyAqIHNoKTsKICAgICAgICBtYXNrLm51bUNvbXBzID0gMTsKICAgICAgICBhd2FpdCBtYXNrLmZpbGxHcmF5QnVmZmVyKGFscGhhQnVmKTsKICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IHN3ICogc2g7IGkgPCBpaTsgKytpKSB7CiAgICAgICAgICBhbHBoYUJ1ZltpXSA9IDI1NSAtIGFscGhhQnVmW2ldOwogICAgICAgIH0KICAgICAgICBpZiAoc3cgIT09IHdpZHRoIHx8IHNoICE9PSBoZWlnaHQpIHsKICAgICAgICAgIGFscGhhQnVmID0gcmVzaXplSW1hZ2VNYXNrKGFscGhhQnVmLCBtYXNrLmJwYywgc3csIHNoLCB3aWR0aCwgaGVpZ2h0KTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShtYXNrKSkgewogICAgICAgIGFscGhhQnVmID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHdpZHRoICogaGVpZ2h0KTsKICAgICAgICBjb25zdCBudW1Db21wcyA9IHRoaXMubnVtQ29tcHM7CiAgICAgICAgZm9yIChpID0gMCwgaWkgPSB3aWR0aCAqIGhlaWdodDsgaSA8IGlpOyArK2kpIHsKICAgICAgICAgIGxldCBvcGFjaXR5ID0gMDsKICAgICAgICAgIGNvbnN0IGltYWdlT2Zmc2V0ID0gaSAqIG51bUNvbXBzOwogICAgICAgICAgZm9yIChqID0gMDsgaiA8IG51bUNvbXBzOyArK2opIHsKICAgICAgICAgICAgY29uc3QgY29sb3IgPSBpbWFnZVtpbWFnZU9mZnNldCArIGpdOwogICAgICAgICAgICBjb25zdCBtYXNrT2Zmc2V0ID0gaiAqIDI7CiAgICAgICAgICAgIGlmIChjb2xvciA8IG1hc2tbbWFza09mZnNldF0gfHwgY29sb3IgPiBtYXNrW21hc2tPZmZzZXQgKyAxXSkgewogICAgICAgICAgICAgIG9wYWNpdHkgPSAyNTU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGFscGhhQnVmW2ldID0gb3BhY2l0eTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJVbmtub3duIG1hc2sgZm9ybWF0LiIpOwogICAgICB9CiAgICB9CiAgICBpZiAoYWxwaGFCdWYpIHsKICAgICAgZm9yIChpID0gMCwgaiA9IDMsIGlpID0gd2lkdGggKiBhY3R1YWxIZWlnaHQ7IGkgPCBpaTsgKytpLCBqICs9IDQpIHsKICAgICAgICByZ2JhQnVmW2pdID0gYWxwaGFCdWZbaV07CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGZvciAoaSA9IDAsIGogPSAzLCBpaSA9IHdpZHRoICogYWN0dWFsSGVpZ2h0OyBpIDwgaWk7ICsraSwgaiArPSA0KSB7CiAgICAgICAgcmdiYUJ1ZltqXSA9IDI1NTsKICAgICAgfQogICAgfQogIH0KICB1bmRvUHJlYmxlbmQoYnVmZmVyLCB3aWR0aCwgaGVpZ2h0KSB7CiAgICBjb25zdCBtYXR0ZSA9IHRoaXMuc21hc2s/Lm1hdHRlOwogICAgaWYgKCFtYXR0ZSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBtYXR0ZVJnYiA9IHRoaXMuY29sb3JTcGFjZS5nZXRSZ2IobWF0dGUsIDApOwogICAgY29uc3QgbWF0dGVSID0gbWF0dGVSZ2JbMF07CiAgICBjb25zdCBtYXR0ZUcgPSBtYXR0ZVJnYlsxXTsKICAgIGNvbnN0IG1hdHRlQiA9IG1hdHRlUmdiWzJdOwogICAgY29uc3QgbGVuZ3RoID0gd2lkdGggKiBoZWlnaHQgKiA0OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gNCkgewogICAgICBjb25zdCBhbHBoYSA9IGJ1ZmZlcltpICsgM107CiAgICAgIGlmIChhbHBoYSA9PT0gMCkgewogICAgICAgIGJ1ZmZlcltpXSA9IDI1NTsKICAgICAgICBidWZmZXJbaSArIDFdID0gMjU1OwogICAgICAgIGJ1ZmZlcltpICsgMl0gPSAyNTU7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgayA9IDI1NSAvIGFscGhhOwogICAgICBidWZmZXJbaV0gPSAoYnVmZmVyW2ldIC0gbWF0dGVSKSAqIGsgKyBtYXR0ZVI7CiAgICAgIGJ1ZmZlcltpICsgMV0gPSAoYnVmZmVyW2kgKyAxXSAtIG1hdHRlRykgKiBrICsgbWF0dGVHOwogICAgICBidWZmZXJbaSArIDJdID0gKGJ1ZmZlcltpICsgMl0gLSBtYXR0ZUIpICogayArIG1hdHRlQjsKICAgIH0KICB9CiAgYXN5bmMgY3JlYXRlSW1hZ2VEYXRhKGZvcmNlUkdCQSA9IGZhbHNlLCBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCA9IGZhbHNlKSB7CiAgICBjb25zdCBkcmF3V2lkdGggPSB0aGlzLmRyYXdXaWR0aDsKICAgIGNvbnN0IGRyYXdIZWlnaHQgPSB0aGlzLmRyYXdIZWlnaHQ7CiAgICBjb25zdCBpbWdEYXRhID0gewogICAgICB3aWR0aDogZHJhd1dpZHRoLAogICAgICBoZWlnaHQ6IGRyYXdIZWlnaHQsCiAgICAgIGludGVycG9sYXRlOiB0aGlzLmludGVycG9sYXRlLAogICAgICBraW5kOiAwLAogICAgICBkYXRhOiBudWxsCiAgICB9OwogICAgY29uc3QgbnVtQ29tcHMgPSB0aGlzLm51bUNvbXBzOwogICAgY29uc3Qgb3JpZ2luYWxXaWR0aCA9IHRoaXMud2lkdGg7CiAgICBjb25zdCBvcmlnaW5hbEhlaWdodCA9IHRoaXMuaGVpZ2h0OwogICAgY29uc3QgYnBjID0gdGhpcy5icGM7CiAgICBjb25zdCByb3dCeXRlcyA9IG9yaWdpbmFsV2lkdGggKiBudW1Db21wcyAqIGJwYyArIDcgPj4gMzsKICAgIGNvbnN0IG11c3RCZVJlc2l6ZWQgPSBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCAmJiBJbWFnZVJlc2l6ZXIubmVlZHNUb0JlUmVzaXplZChkcmF3V2lkdGgsIGRyYXdIZWlnaHQpOwogICAgaWYgKCF0aGlzLnNtYXNrICYmICF0aGlzLm1hc2sgJiYgdGhpcy5jb2xvclNwYWNlLm5hbWUgPT09ICJEZXZpY2VSR0JBIikgewogICAgICBpbWdEYXRhLmtpbmQgPSBJbWFnZUtpbmQuUkdCQV8zMkJQUDsKICAgICAgY29uc3QgaW1nQXJyYXkgPSBpbWdEYXRhLmRhdGEgPSBhd2FpdCB0aGlzLmdldEltYWdlQnl0ZXMob3JpZ2luYWxIZWlnaHQgKiBvcmlnaW5hbFdpZHRoICogNCwge30pOwogICAgICBpZiAoaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpIHsKICAgICAgICBpZiAoIW11c3RCZVJlc2l6ZWQpIHsKICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUJpdG1hcChJbWFnZUtpbmQuUkdCQV8zMkJQUCwgZHJhd1dpZHRoLCBkcmF3SGVpZ2h0LCBpbWdBcnJheSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBJbWFnZVJlc2l6ZXIuY3JlYXRlSW1hZ2UoaW1nRGF0YSwgZmFsc2UpOwogICAgICB9CiAgICAgIHJldHVybiBpbWdEYXRhOwogICAgfQogICAgaWYgKCFmb3JjZVJHQkEpIHsKICAgICAgbGV0IGtpbmQ7CiAgICAgIGlmICh0aGlzLmNvbG9yU3BhY2UubmFtZSA9PT0gIkRldmljZUdyYXkiICYmIGJwYyA9PT0gMSkgewogICAgICAgIGtpbmQgPSBJbWFnZUtpbmQuR1JBWVNDQUxFXzFCUFA7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5jb2xvclNwYWNlLm5hbWUgPT09ICJEZXZpY2VSR0IiICYmIGJwYyA9PT0gOCAmJiAhdGhpcy5uZWVkc0RlY29kZSkgewogICAgICAgIGtpbmQgPSBJbWFnZUtpbmQuUkdCXzI0QlBQOwogICAgICB9CiAgICAgIGlmIChraW5kICYmICF0aGlzLnNtYXNrICYmICF0aGlzLm1hc2sgJiYgZHJhd1dpZHRoID09PSBvcmlnaW5hbFdpZHRoICYmIGRyYXdIZWlnaHQgPT09IG9yaWdpbmFsSGVpZ2h0KSB7CiAgICAgICAgY29uc3QgaW1hZ2UgPSBhd2FpdCB0aGlzLiNnZXRJbWFnZShvcmlnaW5hbFdpZHRoLCBvcmlnaW5hbEhlaWdodCk7CiAgICAgICAgaWYgKGltYWdlKSB7CiAgICAgICAgICByZXR1cm4gaW1hZ2U7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLmdldEltYWdlQnl0ZXMob3JpZ2luYWxIZWlnaHQgKiByb3dCeXRlcywge30pOwogICAgICAgIGlmIChpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCkgewogICAgICAgICAgaWYgKG11c3RCZVJlc2l6ZWQpIHsKICAgICAgICAgICAgcmV0dXJuIEltYWdlUmVzaXplci5jcmVhdGVJbWFnZSh7CiAgICAgICAgICAgICAgZGF0YSwKICAgICAgICAgICAgICBraW5kLAogICAgICAgICAgICAgIHdpZHRoOiBkcmF3V2lkdGgsCiAgICAgICAgICAgICAgaGVpZ2h0OiBkcmF3SGVpZ2h0LAogICAgICAgICAgICAgIGludGVycG9sYXRlOiB0aGlzLmludGVycG9sYXRlCiAgICAgICAgICAgIH0sIHRoaXMubmVlZHNEZWNvZGUpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlQml0bWFwKGtpbmQsIG9yaWdpbmFsV2lkdGgsIG9yaWdpbmFsSGVpZ2h0LCBkYXRhKTsKICAgICAgICB9CiAgICAgICAgaW1nRGF0YS5raW5kID0ga2luZDsKICAgICAgICBpbWdEYXRhLmRhdGEgPSBkYXRhOwogICAgICAgIGlmICh0aGlzLm5lZWRzRGVjb2RlKSB7CiAgICAgICAgICBhc3NlcnQoa2luZCA9PT0gSW1hZ2VLaW5kLkdSQVlTQ0FMRV8xQlBQLCAiUERGSW1hZ2UuY3JlYXRlSW1hZ2VEYXRhOiBUaGUgaW1hZ2UgbXVzdCBiZSBncmF5c2NhbGUuIik7CiAgICAgICAgICBjb25zdCBidWZmZXIgPSBpbWdEYXRhLmRhdGE7CiAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBidWZmZXIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICBidWZmZXJbaV0gXj0gMHhmZjsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGltZ0RhdGE7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuaW1hZ2UgaW5zdGFuY2VvZiBKcGVnU3RyZWFtICYmICF0aGlzLnNtYXNrICYmICF0aGlzLm1hc2sgJiYgIXRoaXMubmVlZHNEZWNvZGUpIHsKICAgICAgICBsZXQgaW1hZ2VMZW5ndGggPSBvcmlnaW5hbEhlaWdodCAqIHJvd0J5dGVzOwogICAgICAgIGlmIChpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCAmJiAhbXVzdEJlUmVzaXplZCkgewogICAgICAgICAgbGV0IGlzSGFuZGxlZCA9IGZhbHNlOwogICAgICAgICAgc3dpdGNoICh0aGlzLmNvbG9yU3BhY2UubmFtZSkgewogICAgICAgICAgICBjYXNlICJEZXZpY2VHcmF5IjoKICAgICAgICAgICAgICBpbWFnZUxlbmd0aCAqPSA0OwogICAgICAgICAgICAgIGlzSGFuZGxlZCA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgIkRldmljZVJHQiI6CiAgICAgICAgICAgICAgaW1hZ2VMZW5ndGggPSBpbWFnZUxlbmd0aCAvIDMgKiA0OwogICAgICAgICAgICAgIGlzSGFuZGxlZCA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgIkRldmljZUNNWUsiOgogICAgICAgICAgICAgIGlzSGFuZGxlZCA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoaXNIYW5kbGVkKSB7CiAgICAgICAgICAgIGNvbnN0IGltYWdlID0gYXdhaXQgdGhpcy4jZ2V0SW1hZ2UoZHJhd1dpZHRoLCBkcmF3SGVpZ2h0KTsKICAgICAgICAgICAgaWYgKGltYWdlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGltYWdlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IHJnYmEgPSBhd2FpdCB0aGlzLmdldEltYWdlQnl0ZXMoaW1hZ2VMZW5ndGgsIHsKICAgICAgICAgICAgICBkcmF3V2lkdGgsCiAgICAgICAgICAgICAgZHJhd0hlaWdodCwKICAgICAgICAgICAgICBmb3JjZVJHQkE6IHRydWUKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUJpdG1hcChJbWFnZUtpbmQuUkdCQV8zMkJQUCwgZHJhd1dpZHRoLCBkcmF3SGVpZ2h0LCByZ2JhKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3dpdGNoICh0aGlzLmNvbG9yU3BhY2UubmFtZSkgewogICAgICAgICAgICBjYXNlICJEZXZpY2VHcmF5IjoKICAgICAgICAgICAgICBpbWFnZUxlbmd0aCAqPSAzOwogICAgICAgICAgICBjYXNlICJEZXZpY2VSR0IiOgogICAgICAgICAgICBjYXNlICJEZXZpY2VDTVlLIjoKICAgICAgICAgICAgICBpbWdEYXRhLmtpbmQgPSBJbWFnZUtpbmQuUkdCXzI0QlBQOwogICAgICAgICAgICAgIGltZ0RhdGEuZGF0YSA9IGF3YWl0IHRoaXMuZ2V0SW1hZ2VCeXRlcyhpbWFnZUxlbmd0aCwgewogICAgICAgICAgICAgICAgZHJhd1dpZHRoLAogICAgICAgICAgICAgICAgZHJhd0hlaWdodCwKICAgICAgICAgICAgICAgIGZvcmNlUkdCOiB0cnVlCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgaWYgKG11c3RCZVJlc2l6ZWQpIHsKICAgICAgICAgICAgICAgIHJldHVybiBJbWFnZVJlc2l6ZXIuY3JlYXRlSW1hZ2UoaW1nRGF0YSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiBpbWdEYXRhOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogICAgY29uc3QgaW1nQXJyYXkgPSBhd2FpdCB0aGlzLmdldEltYWdlQnl0ZXMob3JpZ2luYWxIZWlnaHQgKiByb3dCeXRlcywgewogICAgICBpbnRlcm5hbDogdHJ1ZQogICAgfSk7CiAgICBjb25zdCBhY3R1YWxIZWlnaHQgPSAwIHwgaW1nQXJyYXkubGVuZ3RoIC8gcm93Qnl0ZXMgKiBkcmF3SGVpZ2h0IC8gb3JpZ2luYWxIZWlnaHQ7CiAgICBjb25zdCBjb21wcyA9IHRoaXMuZ2V0Q29tcG9uZW50cyhpbWdBcnJheSk7CiAgICBsZXQgYWxwaGEwMSwgbWF5YmVVbmRvUHJlYmxlbmQ7CiAgICBsZXQgY2FudmFzLCBjdHgsIGNhbnZhc0ltZ0RhdGEsIGRhdGE7CiAgICBpZiAoaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgJiYgIW11c3RCZVJlc2l6ZWQpIHsKICAgICAgY2FudmFzID0gbmV3IE9mZnNjcmVlbkNhbnZhcyhkcmF3V2lkdGgsIGRyYXdIZWlnaHQpOwogICAgICBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgiMmQiKTsKICAgICAgY2FudmFzSW1nRGF0YSA9IGN0eC5jcmVhdGVJbWFnZURhdGEoZHJhd1dpZHRoLCBkcmF3SGVpZ2h0KTsKICAgICAgZGF0YSA9IGNhbnZhc0ltZ0RhdGEuZGF0YTsKICAgIH0KICAgIGltZ0RhdGEua2luZCA9IEltYWdlS2luZC5SR0JBXzMyQlBQOwogICAgaWYgKCFmb3JjZVJHQkEgJiYgIXRoaXMuc21hc2sgJiYgIXRoaXMubWFzaykgewogICAgICBpZiAoIWlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkIHx8IG11c3RCZVJlc2l6ZWQpIHsKICAgICAgICBpbWdEYXRhLmtpbmQgPSBJbWFnZUtpbmQuUkdCXzI0QlBQOwogICAgICAgIGRhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoZHJhd1dpZHRoICogZHJhd0hlaWdodCAqIDMpOwogICAgICAgIGFscGhhMDEgPSAwOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGFyciA9IG5ldyBVaW50MzJBcnJheShkYXRhLmJ1ZmZlcik7CiAgICAgICAgYXJyLmZpbGwoRmVhdHVyZVRlc3QuaXNMaXR0bGVFbmRpYW4gPyAweGZmMDAwMDAwIDogMHgwMDAwMDBmZik7CiAgICAgICAgYWxwaGEwMSA9IDE7CiAgICAgIH0KICAgICAgbWF5YmVVbmRvUHJlYmxlbmQgPSBmYWxzZTsKICAgIH0gZWxzZSB7CiAgICAgIGlmICghaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgfHwgbXVzdEJlUmVzaXplZCkgewogICAgICAgIGRhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoZHJhd1dpZHRoICogZHJhd0hlaWdodCAqIDQpOwogICAgICB9CiAgICAgIGFscGhhMDEgPSAxOwogICAgICBtYXliZVVuZG9QcmVibGVuZCA9IHRydWU7CiAgICAgIGF3YWl0IHRoaXMuZmlsbE9wYWNpdHkoZGF0YSwgZHJhd1dpZHRoLCBkcmF3SGVpZ2h0LCBhY3R1YWxIZWlnaHQsIGNvbXBzKTsKICAgIH0KICAgIGlmICh0aGlzLm5lZWRzRGVjb2RlKSB7CiAgICAgIHRoaXMuZGVjb2RlQnVmZmVyKGNvbXBzKTsKICAgIH0KICAgIHRoaXMuY29sb3JTcGFjZS5maWxsUmdiKGRhdGEsIG9yaWdpbmFsV2lkdGgsIG9yaWdpbmFsSGVpZ2h0LCBkcmF3V2lkdGgsIGRyYXdIZWlnaHQsIGFjdHVhbEhlaWdodCwgYnBjLCBjb21wcywgYWxwaGEwMSk7CiAgICBpZiAobWF5YmVVbmRvUHJlYmxlbmQpIHsKICAgICAgdGhpcy51bmRvUHJlYmxlbmQoZGF0YSwgZHJhd1dpZHRoLCBhY3R1YWxIZWlnaHQpOwogICAgfQogICAgaWYgKGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkICYmICFtdXN0QmVSZXNpemVkKSB7CiAgICAgIGN0eC5wdXRJbWFnZURhdGEoY2FudmFzSW1nRGF0YSwgMCwgMCk7CiAgICAgIGNvbnN0IGJpdG1hcCA9IGNhbnZhcy50cmFuc2ZlclRvSW1hZ2VCaXRtYXAoKTsKICAgICAgcmV0dXJuIHsKICAgICAgICBkYXRhOiBudWxsLAogICAgICAgIHdpZHRoOiBkcmF3V2lkdGgsCiAgICAgICAgaGVpZ2h0OiBkcmF3SGVpZ2h0LAogICAgICAgIGJpdG1hcCwKICAgICAgICBpbnRlcnBvbGF0ZTogdGhpcy5pbnRlcnBvbGF0ZQogICAgICB9OwogICAgfQogICAgaW1nRGF0YS5kYXRhID0gZGF0YTsKICAgIGlmIChtdXN0QmVSZXNpemVkKSB7CiAgICAgIHJldHVybiBJbWFnZVJlc2l6ZXIuY3JlYXRlSW1hZ2UoaW1nRGF0YSk7CiAgICB9CiAgICByZXR1cm4gaW1nRGF0YTsKICB9CiAgYXN5bmMgZmlsbEdyYXlCdWZmZXIoYnVmZmVyKSB7CiAgICBjb25zdCBudW1Db21wcyA9IHRoaXMubnVtQ29tcHM7CiAgICBpZiAobnVtQ29tcHMgIT09IDEpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBSZWFkaW5nIGdyYXkgc2NhbGUgZnJvbSBhIGNvbG9yIGltYWdlOiAke251bUNvbXBzfWApOwogICAgfQogICAgY29uc3Qgd2lkdGggPSB0aGlzLndpZHRoOwogICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7CiAgICBjb25zdCBicGMgPSB0aGlzLmJwYzsKICAgIGNvbnN0IHJvd0J5dGVzID0gd2lkdGggKiBudW1Db21wcyAqIGJwYyArIDcgPj4gMzsKICAgIGNvbnN0IGltZ0FycmF5ID0gYXdhaXQgdGhpcy5nZXRJbWFnZUJ5dGVzKGhlaWdodCAqIHJvd0J5dGVzLCB7CiAgICAgIGludGVybmFsOiB0cnVlCiAgICB9KTsKICAgIGNvbnN0IGNvbXBzID0gdGhpcy5nZXRDb21wb25lbnRzKGltZ0FycmF5KTsKICAgIGxldCBpLCBsZW5ndGg7CiAgICBpZiAoYnBjID09PSAxKSB7CiAgICAgIGxlbmd0aCA9IHdpZHRoICogaGVpZ2h0OwogICAgICBpZiAodGhpcy5uZWVkc0RlY29kZSkgewogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgYnVmZmVyW2ldID0gY29tcHNbaV0gLSAxICYgMjU1OwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgIGJ1ZmZlcltpXSA9IC1jb21wc1tpXSAmIDI1NTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKHRoaXMubmVlZHNEZWNvZGUpIHsKICAgICAgdGhpcy5kZWNvZGVCdWZmZXIoY29tcHMpOwogICAgfQogICAgbGVuZ3RoID0gd2lkdGggKiBoZWlnaHQ7CiAgICBjb25zdCBzY2FsZSA9IDI1NSAvICgoMSA8PCBicGMpIC0gMSk7CiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgYnVmZmVyW2ldID0gc2NhbGUgKiBjb21wc1tpXTsKICAgIH0KICB9CiAgY3JlYXRlQml0bWFwKGtpbmQsIHdpZHRoLCBoZWlnaHQsIHNyYykgewogICAgY29uc3QgY2FudmFzID0gbmV3IE9mZnNjcmVlbkNhbnZhcyh3aWR0aCwgaGVpZ2h0KTsKICAgIGNvbnN0IGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCIyZCIpOwogICAgbGV0IGltZ0RhdGE7CiAgICBpZiAoa2luZCA9PT0gSW1hZ2VLaW5kLlJHQkFfMzJCUFApIHsKICAgICAgaW1nRGF0YSA9IG5ldyBJbWFnZURhdGEoc3JjLCB3aWR0aCwgaGVpZ2h0KTsKICAgIH0gZWxzZSB7CiAgICAgIGltZ0RhdGEgPSBjdHguY3JlYXRlSW1hZ2VEYXRhKHdpZHRoLCBoZWlnaHQpOwogICAgICBjb252ZXJ0VG9SR0JBKHsKICAgICAgICBraW5kLAogICAgICAgIHNyYywKICAgICAgICBkZXN0OiBuZXcgVWludDMyQXJyYXkoaW1nRGF0YS5kYXRhLmJ1ZmZlciksCiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0LAogICAgICAgIGludmVyc2VEZWNvZGU6IHRoaXMubmVlZHNEZWNvZGUKICAgICAgfSk7CiAgICB9CiAgICBjdHgucHV0SW1hZ2VEYXRhKGltZ0RhdGEsIDAsIDApOwogICAgY29uc3QgYml0bWFwID0gY2FudmFzLnRyYW5zZmVyVG9JbWFnZUJpdG1hcCgpOwogICAgcmV0dXJuIHsKICAgICAgZGF0YTogbnVsbCwKICAgICAgd2lkdGgsCiAgICAgIGhlaWdodCwKICAgICAgYml0bWFwLAogICAgICBpbnRlcnBvbGF0ZTogdGhpcy5pbnRlcnBvbGF0ZQogICAgfTsKICB9CiAgYXN5bmMgI2dldEltYWdlKHdpZHRoLCBoZWlnaHQpIHsKICAgIGNvbnN0IGJpdG1hcCA9IGF3YWl0IHRoaXMuaW1hZ2UuZ2V0VHJhbnNmZXJhYmxlSW1hZ2UoKTsKICAgIGlmICghYml0bWFwKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgZGF0YTogbnVsbCwKICAgICAgd2lkdGgsCiAgICAgIGhlaWdodCwKICAgICAgYml0bWFwLAogICAgICBpbnRlcnBvbGF0ZTogdGhpcy5pbnRlcnBvbGF0ZQogICAgfTsKICB9CiAgYXN5bmMgZ2V0SW1hZ2VCeXRlcyhsZW5ndGgsIHsKICAgIGRyYXdXaWR0aCwKICAgIGRyYXdIZWlnaHQsCiAgICBmb3JjZVJHQkEgPSBmYWxzZSwKICAgIGZvcmNlUkdCID0gZmFsc2UsCiAgICBpbnRlcm5hbCA9IGZhbHNlCiAgfSkgewogICAgdGhpcy5pbWFnZS5yZXNldCgpOwogICAgdGhpcy5pbWFnZS5kcmF3V2lkdGggPSBkcmF3V2lkdGggfHwgdGhpcy53aWR0aDsKICAgIHRoaXMuaW1hZ2UuZHJhd0hlaWdodCA9IGRyYXdIZWlnaHQgfHwgdGhpcy5oZWlnaHQ7CiAgICB0aGlzLmltYWdlLmZvcmNlUkdCQSA9ICEhZm9yY2VSR0JBOwogICAgdGhpcy5pbWFnZS5mb3JjZVJHQiA9ICEhZm9yY2VSR0I7CiAgICBjb25zdCBpbWFnZUJ5dGVzID0gYXdhaXQgdGhpcy5pbWFnZS5nZXRJbWFnZURhdGEobGVuZ3RoLCB0aGlzLmpweERlY29kZXJPcHRpb25zKTsKICAgIGlmIChpbnRlcm5hbCB8fCB0aGlzLmltYWdlIGluc3RhbmNlb2YgRGVjb2RlU3RyZWFtKSB7CiAgICAgIHJldHVybiBpbWFnZUJ5dGVzOwogICAgfQogICAgYXNzZXJ0KGltYWdlQnl0ZXMgaW5zdGFuY2VvZiBVaW50OEFycmF5LCAnUERGSW1hZ2UuZ2V0SW1hZ2VCeXRlczogVW5zdXBwb3J0ZWQgImltYWdlQnl0ZXMiIHR5cGUuJyk7CiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoaW1hZ2VCeXRlcyk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9ldmFsdWF0b3IuanMKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKY29uc3QgRGVmYXVsdFBhcnRpYWxFdmFsdWF0b3JPcHRpb25zID0gT2JqZWN0LmZyZWV6ZSh7CiAgbWF4SW1hZ2VTaXplOiAtMSwKICBkaXNhYmxlRm9udEZhY2U6IGZhbHNlLAogIGlnbm9yZUVycm9yczogZmFsc2UsCiAgaXNFdmFsU3VwcG9ydGVkOiB0cnVlLAogIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkOiBmYWxzZSwKICBpc0ltYWdlRGVjb2RlclN1cHBvcnRlZDogZmFsc2UsCiAgY2FudmFzTWF4QXJlYUluQnl0ZXM6IC0xLAogIGZvbnRFeHRyYVByb3BlcnRpZXM6IGZhbHNlLAogIHVzZVN5c3RlbUZvbnRzOiB0cnVlLAogIHVzZVdhc206IHRydWUsCiAgdXNlV29ya2VyRmV0Y2g6IHRydWUsCiAgY01hcFVybDogbnVsbCwKICBpY2NVcmw6IG51bGwsCiAgc3RhbmRhcmRGb250RGF0YVVybDogbnVsbCwKICB3YXNtVXJsOiBudWxsCn0pOwpjb25zdCBQYXR0ZXJuVHlwZSA9IHsKICBUSUxJTkc6IDEsCiAgU0hBRElORzogMgp9Owpjb25zdCBURVhUX0NIVU5LX0JBVENIX1NJWkUgPSAxMDsKY29uc3QgZGVmZXJyZWQgPSBQcm9taXNlLnJlc29sdmUoKTsKZnVuY3Rpb24gbm9ybWFsaXplQmxlbmRNb2RlKHZhbHVlLCBwYXJzaW5nQXJyYXkgPSBmYWxzZSkgewogIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkgewogICAgZm9yIChjb25zdCB2YWwgb2YgdmFsdWUpIHsKICAgICAgY29uc3QgbWF5YmVCTSA9IG5vcm1hbGl6ZUJsZW5kTW9kZSh2YWwsIHRydWUpOwogICAgICBpZiAobWF5YmVCTSkgewogICAgICAgIHJldHVybiBtYXliZUJNOwogICAgICB9CiAgICB9CiAgICB3YXJuKGBVbnN1cHBvcnRlZCBibGVuZCBtb2RlIEFycmF5OiAke3ZhbHVlfWApOwogICAgcmV0dXJuICJzb3VyY2Utb3ZlciI7CiAgfQogIGlmICghKHZhbHVlIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgIGlmIChwYXJzaW5nQXJyYXkpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gInNvdXJjZS1vdmVyIjsKICB9CiAgc3dpdGNoICh2YWx1ZS5uYW1lKSB7CiAgICBjYXNlICJOb3JtYWwiOgogICAgY2FzZSAiQ29tcGF0aWJsZSI6CiAgICAgIHJldHVybiAic291cmNlLW92ZXIiOwogICAgY2FzZSAiTXVsdGlwbHkiOgogICAgICByZXR1cm4gIm11bHRpcGx5IjsKICAgIGNhc2UgIlNjcmVlbiI6CiAgICAgIHJldHVybiAic2NyZWVuIjsKICAgIGNhc2UgIk92ZXJsYXkiOgogICAgICByZXR1cm4gIm92ZXJsYXkiOwogICAgY2FzZSAiRGFya2VuIjoKICAgICAgcmV0dXJuICJkYXJrZW4iOwogICAgY2FzZSAiTGlnaHRlbiI6CiAgICAgIHJldHVybiAibGlnaHRlbiI7CiAgICBjYXNlICJDb2xvckRvZGdlIjoKICAgICAgcmV0dXJuICJjb2xvci1kb2RnZSI7CiAgICBjYXNlICJDb2xvckJ1cm4iOgogICAgICByZXR1cm4gImNvbG9yLWJ1cm4iOwogICAgY2FzZSAiSGFyZExpZ2h0IjoKICAgICAgcmV0dXJuICJoYXJkLWxpZ2h0IjsKICAgIGNhc2UgIlNvZnRMaWdodCI6CiAgICAgIHJldHVybiAic29mdC1saWdodCI7CiAgICBjYXNlICJEaWZmZXJlbmNlIjoKICAgICAgcmV0dXJuICJkaWZmZXJlbmNlIjsKICAgIGNhc2UgIkV4Y2x1c2lvbiI6CiAgICAgIHJldHVybiAiZXhjbHVzaW9uIjsKICAgIGNhc2UgIkh1ZSI6CiAgICAgIHJldHVybiAiaHVlIjsKICAgIGNhc2UgIlNhdHVyYXRpb24iOgogICAgICByZXR1cm4gInNhdHVyYXRpb24iOwogICAgY2FzZSAiQ29sb3IiOgogICAgICByZXR1cm4gImNvbG9yIjsKICAgIGNhc2UgIkx1bWlub3NpdHkiOgogICAgICByZXR1cm4gImx1bWlub3NpdHkiOwogIH0KICBpZiAocGFyc2luZ0FycmF5KSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgd2FybihgVW5zdXBwb3J0ZWQgYmxlbmQgbW9kZTogJHt2YWx1ZS5uYW1lfWApOwogIHJldHVybiAic291cmNlLW92ZXIiOwp9CmZ1bmN0aW9uIGFkZENhY2hlZEltYWdlT3BzKG9wTGlzdCwgewogIG9iaklkLAogIGZuLAogIGFyZ3MsCiAgb3B0aW9uYWxDb250ZW50LAogIGhhc01hc2sKfSkgewogIGlmIChvYmpJZCkgewogICAgb3BMaXN0LmFkZERlcGVuZGVuY3kob2JqSWQpOwogIH0KICBvcExpc3QuYWRkSW1hZ2VPcHMoZm4sIGFyZ3MsIG9wdGlvbmFsQ29udGVudCwgaGFzTWFzayk7CiAgaWYgKGZuID09PSBPUFMucGFpbnRJbWFnZU1hc2tYT2JqZWN0ICYmIGFyZ3NbMF0/LmNvdW50ID4gMCkgewogICAgYXJnc1swXS5jb3VudCsrOwogIH0KfQpjbGFzcyBUaW1lU2xvdE1hbmFnZXIgewogIHN0YXRpYyBUSU1FX1NMT1RfRFVSQVRJT05fTVMgPSAyMDsKICBzdGF0aWMgQ0hFQ0tfVElNRV9FVkVSWSA9IDEwMDsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMucmVzZXQoKTsKICB9CiAgY2hlY2soKSB7CiAgICBpZiAoKyt0aGlzLmNoZWNrZWQgPCBUaW1lU2xvdE1hbmFnZXIuQ0hFQ0tfVElNRV9FVkVSWSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICB0aGlzLmNoZWNrZWQgPSAwOwogICAgcmV0dXJuIHRoaXMuZW5kVGltZSA8PSBEYXRlLm5vdygpOwogIH0KICByZXNldCgpIHsKICAgIHRoaXMuZW5kVGltZSA9IERhdGUubm93KCkgKyBUaW1lU2xvdE1hbmFnZXIuVElNRV9TTE9UX0RVUkFUSU9OX01TOwogICAgdGhpcy5jaGVja2VkID0gMDsKICB9Cn0KY2xhc3MgUGFydGlhbEV2YWx1YXRvciB7CiAgY29uc3RydWN0b3IoewogICAgeHJlZiwKICAgIGhhbmRsZXIsCiAgICBwYWdlSW5kZXgsCiAgICBpZEZhY3RvcnksCiAgICBmb250Q2FjaGUsCiAgICBidWlsdEluQ01hcENhY2hlLAogICAgc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgZ2xvYmFsSW1hZ2VDYWNoZSwKICAgIHN5c3RlbUZvbnRDYWNoZSwKICAgIG9wdGlvbnMgPSBudWxsCiAgfSkgewogICAgdGhpcy54cmVmID0geHJlZjsKICAgIHRoaXMuaGFuZGxlciA9IGhhbmRsZXI7CiAgICB0aGlzLnBhZ2VJbmRleCA9IHBhZ2VJbmRleDsKICAgIHRoaXMuaWRGYWN0b3J5ID0gaWRGYWN0b3J5OwogICAgdGhpcy5mb250Q2FjaGUgPSBmb250Q2FjaGU7CiAgICB0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUgPSBidWlsdEluQ01hcENhY2hlOwogICAgdGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUgPSBzdGFuZGFyZEZvbnREYXRhQ2FjaGU7CiAgICB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSA9IGdsb2JhbENvbG9yU3BhY2VDYWNoZTsKICAgIHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZSA9IGdsb2JhbEltYWdlQ2FjaGU7CiAgICB0aGlzLnN5c3RlbUZvbnRDYWNoZSA9IHN5c3RlbUZvbnRDYWNoZTsKICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnMgfHwgRGVmYXVsdFBhcnRpYWxFdmFsdWF0b3JPcHRpb25zOwogICAgdGhpcy50eXBlM0ZvbnRSZWZzID0gbnVsbDsKICAgIHRoaXMuX3JlZ2lvbmFsSW1hZ2VDYWNoZSA9IG5ldyBSZWdpb25hbEltYWdlQ2FjaGUoKTsKICAgIHRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCA9IHRoaXMuZmV0Y2hCdWlsdEluQ01hcC5iaW5kKHRoaXMpOwogIH0KICBnZXQgX3BkZkZ1bmN0aW9uRmFjdG9yeSgpIHsKICAgIGNvbnN0IHBkZkZ1bmN0aW9uRmFjdG9yeSA9IG5ldyBQREZGdW5jdGlvbkZhY3RvcnkoewogICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgIGlzRXZhbFN1cHBvcnRlZDogdGhpcy5vcHRpb25zLmlzRXZhbFN1cHBvcnRlZAogICAgfSk7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJfcGRmRnVuY3Rpb25GYWN0b3J5IiwgcGRmRnVuY3Rpb25GYWN0b3J5KTsKICB9CiAgZ2V0IHBhcnNpbmdUeXBlM0ZvbnQoKSB7CiAgICByZXR1cm4gISF0aGlzLnR5cGUzRm9udFJlZnM7CiAgfQogIGNsb25lKG5ld09wdGlvbnMgPSBudWxsKSB7CiAgICBjb25zdCBuZXdFdmFsdWF0b3IgPSBPYmplY3QuY3JlYXRlKHRoaXMpOwogICAgbmV3RXZhbHVhdG9yLm9wdGlvbnMgPSBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobnVsbCksIHRoaXMub3B0aW9ucywgbmV3T3B0aW9ucyk7CiAgICByZXR1cm4gbmV3RXZhbHVhdG9yOwogIH0KICBoYXNCbGVuZE1vZGVzKHJlc291cmNlcywgbm9uQmxlbmRNb2Rlc1NldCkgewogICAgaWYgKCEocmVzb3VyY2VzIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKHJlc291cmNlcy5vYmpJZCAmJiBub25CbGVuZE1vZGVzU2V0LmhhcyhyZXNvdXJjZXMub2JqSWQpKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGNvbnN0IHByb2Nlc3NlZCA9IG5ldyBSZWZTZXQobm9uQmxlbmRNb2Rlc1NldCk7CiAgICBpZiAocmVzb3VyY2VzLm9iaklkKSB7CiAgICAgIHByb2Nlc3NlZC5wdXQocmVzb3VyY2VzLm9iaklkKTsKICAgIH0KICAgIGNvbnN0IG5vZGVzID0gW3Jlc291cmNlc10sCiAgICAgIHhyZWYgPSB0aGlzLnhyZWY7CiAgICB3aGlsZSAobm9kZXMubGVuZ3RoKSB7CiAgICAgIGNvbnN0IG5vZGUgPSBub2Rlcy5zaGlmdCgpOwogICAgICBjb25zdCBncmFwaGljU3RhdGVzID0gbm9kZS5nZXQoIkV4dEdTdGF0ZSIpOwogICAgICBpZiAoZ3JhcGhpY1N0YXRlcyBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICBmb3IgKGxldCBncmFwaGljU3RhdGUgb2YgZ3JhcGhpY1N0YXRlcy5nZXRSYXdWYWx1ZXMoKSkgewogICAgICAgICAgaWYgKGdyYXBoaWNTdGF0ZSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgICBpZiAocHJvY2Vzc2VkLmhhcyhncmFwaGljU3RhdGUpKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBncmFwaGljU3RhdGUgPSB4cmVmLmZldGNoKGdyYXBoaWNTdGF0ZSk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgICAgcHJvY2Vzc2VkLnB1dChncmFwaGljU3RhdGUpOwogICAgICAgICAgICAgIGluZm8oYGhhc0JsZW5kTW9kZXMgLSBpZ25vcmluZyBFeHRHU3RhdGU6ICIke2V4fSIuYCk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmICghKGdyYXBoaWNTdGF0ZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGdyYXBoaWNTdGF0ZS5vYmpJZCkgewogICAgICAgICAgICBwcm9jZXNzZWQucHV0KGdyYXBoaWNTdGF0ZS5vYmpJZCk7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBibSA9IGdyYXBoaWNTdGF0ZS5nZXQoIkJNIik7CiAgICAgICAgICBpZiAoYm0gaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgIGlmIChibS5uYW1lICE9PSAiTm9ybWFsIikgewogICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGJtICE9PSB1bmRlZmluZWQgJiYgQXJyYXkuaXNBcnJheShibSkpIHsKICAgICAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGJtKSB7CiAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgaW5zdGFuY2VvZiBOYW1lICYmIGVsZW1lbnQubmFtZSAhPT0gIk5vcm1hbCIpIHsKICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCB4T2JqZWN0cyA9IG5vZGUuZ2V0KCJYT2JqZWN0Iik7CiAgICAgIGlmICghKHhPYmplY3RzIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBmb3IgKGxldCB4T2JqZWN0IG9mIHhPYmplY3RzLmdldFJhd1ZhbHVlcygpKSB7CiAgICAgICAgaWYgKHhPYmplY3QgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgIGlmIChwcm9jZXNzZWQuaGFzKHhPYmplY3QpKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgeE9iamVjdCA9IHhyZWYuZmV0Y2goeE9iamVjdCk7CiAgICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgICBwcm9jZXNzZWQucHV0KHhPYmplY3QpOwogICAgICAgICAgICBpbmZvKGBoYXNCbGVuZE1vZGVzIC0gaWdub3JpbmcgWE9iamVjdDogIiR7ZXh9Ii5gKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICghKHhPYmplY3QgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICh4T2JqZWN0LmRpY3Qub2JqSWQpIHsKICAgICAgICAgIHByb2Nlc3NlZC5wdXQoeE9iamVjdC5kaWN0Lm9iaklkKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgeFJlc291cmNlcyA9IHhPYmplY3QuZGljdC5nZXQoIlJlc291cmNlcyIpOwogICAgICAgIGlmICghKHhSZXNvdXJjZXMgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICh4UmVzb3VyY2VzLm9iaklkICYmIHByb2Nlc3NlZC5oYXMoeFJlc291cmNlcy5vYmpJZCkpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBub2Rlcy5wdXNoKHhSZXNvdXJjZXMpOwogICAgICAgIGlmICh4UmVzb3VyY2VzLm9iaklkKSB7CiAgICAgICAgICBwcm9jZXNzZWQucHV0KHhSZXNvdXJjZXMub2JqSWQpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCByZWYgb2YgcHJvY2Vzc2VkKSB7CiAgICAgIG5vbkJsZW5kTW9kZXNTZXQucHV0KHJlZik7CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGFzeW5jIGZldGNoQnVpbHRJbkNNYXAobmFtZSkgewogICAgY29uc3QgY2FjaGVkRGF0YSA9IHRoaXMuYnVpbHRJbkNNYXBDYWNoZS5nZXQobmFtZSk7CiAgICBpZiAoY2FjaGVkRGF0YSkgewogICAgICByZXR1cm4gY2FjaGVkRGF0YTsKICAgIH0KICAgIGxldCBkYXRhOwogICAgaWYgKHRoaXMub3B0aW9ucy51c2VXb3JrZXJGZXRjaCkgewogICAgICBkYXRhID0gewogICAgICAgIGNNYXBEYXRhOiBhd2FpdCBmZXRjaEJpbmFyeURhdGEoYCR7dGhpcy5vcHRpb25zLmNNYXBVcmx9JHtuYW1lfS5iY21hcGApLAogICAgICAgIGlzQ29tcHJlc3NlZDogdHJ1ZQogICAgICB9OwogICAgfSBlbHNlIHsKICAgICAgZGF0YSA9IGF3YWl0IHRoaXMuaGFuZGxlci5zZW5kV2l0aFByb21pc2UoIkZldGNoQmluYXJ5RGF0YSIsIHsKICAgICAgICB0eXBlOiAiY01hcFJlYWRlckZhY3RvcnkiLAogICAgICAgIG5hbWUKICAgICAgfSk7CiAgICB9CiAgICB0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUuc2V0KG5hbWUsIGRhdGEpOwogICAgcmV0dXJuIGRhdGE7CiAgfQogIGFzeW5jIGZldGNoU3RhbmRhcmRGb250RGF0YShuYW1lKSB7CiAgICBjb25zdCBjYWNoZWREYXRhID0gdGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUuZ2V0KG5hbWUpOwogICAgaWYgKGNhY2hlZERhdGEpIHsKICAgICAgcmV0dXJuIG5ldyBTdHJlYW0oY2FjaGVkRGF0YSk7CiAgICB9CiAgICBpZiAodGhpcy5vcHRpb25zLnVzZVN5c3RlbUZvbnRzICYmIG5hbWUgIT09ICJTeW1ib2wiICYmIG5hbWUgIT09ICJaYXBmRGluZ2JhdHMiKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3Qgc3RhbmRhcmRGb250TmFtZVRvRmlsZU5hbWUgPSBnZXRGb250TmFtZVRvRmlsZU1hcCgpLAogICAgICBmaWxlbmFtZSA9IHN0YW5kYXJkRm9udE5hbWVUb0ZpbGVOYW1lW25hbWVdOwogICAgbGV0IGRhdGE7CiAgICB0cnkgewogICAgICBpZiAodGhpcy5vcHRpb25zLnVzZVdvcmtlckZldGNoKSB7CiAgICAgICAgZGF0YSA9IGF3YWl0IGZldGNoQmluYXJ5RGF0YShgJHt0aGlzLm9wdGlvbnMuc3RhbmRhcmRGb250RGF0YVVybH0ke2ZpbGVuYW1lfWApOwogICAgICB9IGVsc2UgewogICAgICAgIGRhdGEgPSBhd2FpdCB0aGlzLmhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJGZXRjaEJpbmFyeURhdGEiLCB7CiAgICAgICAgICB0eXBlOiAic3RhbmRhcmRGb250RGF0YUZhY3RvcnkiLAogICAgICAgICAgZmlsZW5hbWUKICAgICAgICB9KTsKICAgICAgfQogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgd2FybihleCk7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgdGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUuc2V0KG5hbWUsIGRhdGEpOwogICAgcmV0dXJuIG5ldyBTdHJlYW0oZGF0YSk7CiAgfQogIGFzeW5jIGJ1aWxkRm9ybVhPYmplY3QocmVzb3VyY2VzLCB4b2JqLCBzbWFzaywgb3BlcmF0b3JMaXN0LCB0YXNrLCBpbml0aWFsU3RhdGUsIGxvY2FsQ29sb3JTcGFjZUNhY2hlLCBzZWVuUmVmcykgewogICAgY29uc3QgewogICAgICBkaWN0CiAgICB9ID0geG9iajsKICAgIGNvbnN0IG1hdHJpeCA9IGxvb2t1cE1hdHJpeChkaWN0LmdldEFycmF5KCJNYXRyaXgiKSwgbnVsbCk7CiAgICBjb25zdCBiYm94ID0gbG9va3VwTm9ybWFsUmVjdChkaWN0LmdldEFycmF5KCJCQm94IiksIG51bGwpOwogICAgbGV0IG9wdGlvbmFsQ29udGVudCwgZ3JvdXBPcHRpb25zOwogICAgaWYgKGRpY3QuaGFzKCJPQyIpKSB7CiAgICAgIG9wdGlvbmFsQ29udGVudCA9IGF3YWl0IHRoaXMucGFyc2VNYXJrZWRDb250ZW50UHJvcHMoZGljdC5nZXQoIk9DIiksIHJlc291cmNlcyk7CiAgICB9CiAgICBpZiAob3B0aW9uYWxDb250ZW50ICE9PSB1bmRlZmluZWQpIHsKICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5iZWdpbk1hcmtlZENvbnRlbnRQcm9wcywgWyJPQyIsIG9wdGlvbmFsQ29udGVudF0pOwogICAgfQogICAgY29uc3QgZ3JvdXAgPSBkaWN0LmdldCgiR3JvdXAiKTsKICAgIGlmIChncm91cCkgewogICAgICBncm91cE9wdGlvbnMgPSB7CiAgICAgICAgbWF0cml4LAogICAgICAgIGJib3gsCiAgICAgICAgc21hc2ssCiAgICAgICAgaXNvbGF0ZWQ6IGZhbHNlLAogICAgICAgIGtub2Nrb3V0OiBmYWxzZQogICAgICB9OwogICAgICBjb25zdCBncm91cFN1YnR5cGUgPSBncm91cC5nZXQoIlMiKTsKICAgICAgbGV0IGNvbG9yU3BhY2UgPSBudWxsOwogICAgICBpZiAoaXNOYW1lKGdyb3VwU3VidHlwZSwgIlRyYW5zcGFyZW5jeSIpKSB7CiAgICAgICAgZ3JvdXBPcHRpb25zLmlzb2xhdGVkID0gZ3JvdXAuZ2V0KCJJIikgfHwgZmFsc2U7CiAgICAgICAgZ3JvdXBPcHRpb25zLmtub2Nrb3V0ID0gZ3JvdXAuZ2V0KCJLIikgfHwgZmFsc2U7CiAgICAgICAgaWYgKGdyb3VwLmhhcygiQ1MiKSkgewogICAgICAgICAgY29uc3QgY3MgPSB0aGlzLl9nZXRDb2xvclNwYWNlKGdyb3VwLmdldFJhdygiQ1MiKSwgcmVzb3VyY2VzLCBsb2NhbENvbG9yU3BhY2VDYWNoZSk7CiAgICAgICAgICBjb2xvclNwYWNlID0gY3MgaW5zdGFuY2VvZiBDb2xvclNwYWNlID8gY3MgOiBhd2FpdCB0aGlzLl9oYW5kbGVDb2xvclNwYWNlKGNzKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHNtYXNrPy5iYWNrZHJvcCkgewogICAgICAgIGNvbG9yU3BhY2UgfHw9IENvbG9yU3BhY2VVdGlscy5yZ2I7CiAgICAgICAgc21hc2suYmFja2Ryb3AgPSBjb2xvclNwYWNlLmdldFJnYkhleChzbWFzay5iYWNrZHJvcCwgMCk7CiAgICAgIH0KICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5iZWdpbkdyb3VwLCBbZ3JvdXBPcHRpb25zXSk7CiAgICB9CiAgICBjb25zdCBmMzJtYXRyaXggPSBtYXRyaXggJiYgbmV3IEZsb2F0MzJBcnJheShtYXRyaXgpOwogICAgY29uc3QgZjMyYmJveCA9ICFncm91cCAmJiBiYm94ICYmIG5ldyBGbG9hdDMyQXJyYXkoYmJveCkgfHwgbnVsbDsKICAgIGNvbnN0IGFyZ3MgPSBbZjMybWF0cml4LCBmMzJiYm94XTsKICAgIG9wZXJhdG9yTGlzdC5hZGRPcChPUFMucGFpbnRGb3JtWE9iamVjdEJlZ2luLCBhcmdzKTsKICAgIGNvbnN0IGxvY2FsUmVzb3VyY2VzID0gZGljdC5nZXQoIlJlc291cmNlcyIpOwogICAgYXdhaXQgdGhpcy5nZXRPcGVyYXRvckxpc3QoewogICAgICBzdHJlYW06IHhvYmosCiAgICAgIHRhc2ssCiAgICAgIHJlc291cmNlczogbG9jYWxSZXNvdXJjZXMgaW5zdGFuY2VvZiBEaWN0ID8gbG9jYWxSZXNvdXJjZXMgOiByZXNvdXJjZXMsCiAgICAgIG9wZXJhdG9yTGlzdCwKICAgICAgaW5pdGlhbFN0YXRlLAogICAgICBwcmV2UmVmczogc2VlblJlZnMKICAgIH0pOwogICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5wYWludEZvcm1YT2JqZWN0RW5kLCBbXSk7CiAgICBpZiAoZ3JvdXApIHsKICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5lbmRHcm91cCwgW2dyb3VwT3B0aW9uc10pOwogICAgfQogICAgaWYgKG9wdGlvbmFsQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChPUFMuZW5kTWFya2VkQ29udGVudCwgW10pOwogICAgfQogIH0KICBfc2VuZEltZ0RhdGEob2JqSWQsIGltZ0RhdGEsIGNhY2hlR2xvYmFsbHkgPSBmYWxzZSkgewogICAgY29uc3QgdHJhbnNmZXJzID0gaW1nRGF0YSA/IFtpbWdEYXRhLmJpdG1hcCB8fCBpbWdEYXRhLmRhdGEuYnVmZmVyXSA6IG51bGw7CiAgICBpZiAodGhpcy5wYXJzaW5nVHlwZTNGb250IHx8IGNhY2hlR2xvYmFsbHkpIHsKICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlci5zZW5kKCJjb21tb25vYmoiLCBbb2JqSWQsICJJbWFnZSIsIGltZ0RhdGFdLCB0cmFuc2ZlcnMpOwogICAgfQogICAgcmV0dXJuIHRoaXMuaGFuZGxlci5zZW5kKCJvYmoiLCBbb2JqSWQsIHRoaXMucGFnZUluZGV4LCAiSW1hZ2UiLCBpbWdEYXRhXSwgdHJhbnNmZXJzKTsKICB9CiAgYXN5bmMgYnVpbGRQYWludEltYWdlWE9iamVjdCh7CiAgICByZXNvdXJjZXMsCiAgICBpbWFnZSwKICAgIGlzSW5saW5lID0gZmFsc2UsCiAgICBvcGVyYXRvckxpc3QsCiAgICBjYWNoZUtleSwKICAgIGxvY2FsSW1hZ2VDYWNoZSwKICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgfSkgewogICAgY29uc3QgewogICAgICBtYXhJbWFnZVNpemUsCiAgICAgIGlnbm9yZUVycm9ycywKICAgICAgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQKICAgIH0gPSB0aGlzLm9wdGlvbnM7CiAgICBjb25zdCB7CiAgICAgIGRpY3QKICAgIH0gPSBpbWFnZTsKICAgIGNvbnN0IGltYWdlUmVmID0gZGljdC5vYmpJZDsKICAgIGNvbnN0IHcgPSBkaWN0LmdldCgiVyIsICJXaWR0aCIpOwogICAgY29uc3QgaCA9IGRpY3QuZ2V0KCJIIiwgIkhlaWdodCIpOwogICAgaWYgKCEodyAmJiB0eXBlb2YgdyA9PT0gIm51bWJlciIpIHx8ICEoaCAmJiB0eXBlb2YgaCA9PT0gIm51bWJlciIpKSB7CiAgICAgIHdhcm4oIkltYWdlIGRpbWVuc2lvbnMgYXJlIG1pc3NpbmcsIG9yIG5vdCBudW1iZXJzLiIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAobWF4SW1hZ2VTaXplICE9PSAtMSAmJiB3ICogaCA+IG1heEltYWdlU2l6ZSkgewogICAgICBjb25zdCBtc2cgPSAiSW1hZ2UgZXhjZWVkZWQgbWF4aW11bSBhbGxvd2VkIHNpemUgYW5kIHdhcyByZW1vdmVkLiI7CiAgICAgIGlmICghaWdub3JlRXJyb3JzKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7CiAgICAgIH0KICAgICAgd2Fybihtc2cpOwogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgb3B0aW9uYWxDb250ZW50OwogICAgaWYgKGRpY3QuaGFzKCJPQyIpKSB7CiAgICAgIG9wdGlvbmFsQ29udGVudCA9IGF3YWl0IHRoaXMucGFyc2VNYXJrZWRDb250ZW50UHJvcHMoZGljdC5nZXQoIk9DIiksIHJlc291cmNlcyk7CiAgICB9CiAgICBjb25zdCBpbWFnZU1hc2sgPSBkaWN0LmdldCgiSU0iLCAiSW1hZ2VNYXNrIikgfHwgZmFsc2U7CiAgICBsZXQgaW1nRGF0YSwgZm4sIGFyZ3M7CiAgICBpZiAoaW1hZ2VNYXNrKSB7CiAgICAgIGltZ0RhdGEgPSBhd2FpdCBQREZJbWFnZS5jcmVhdGVNYXNrKHsKICAgICAgICBpbWFnZSwKICAgICAgICBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZDogaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgJiYgIXRoaXMucGFyc2luZ1R5cGUzRm9udAogICAgICB9KTsKICAgICAgaWYgKGltZ0RhdGEuaXNTaW5nbGVPcGFxdWVQaXhlbCkgewogICAgICAgIGZuID0gT1BTLnBhaW50U29saWRDb2xvckltYWdlTWFzazsKICAgICAgICBhcmdzID0gW107CiAgICAgICAgb3BlcmF0b3JMaXN0LmFkZEltYWdlT3BzKGZuLCBhcmdzLCBvcHRpb25hbENvbnRlbnQpOwogICAgICAgIGlmIChjYWNoZUtleSkgewogICAgICAgICAgY29uc3QgY2FjaGVEYXRhID0gewogICAgICAgICAgICBmbiwKICAgICAgICAgICAgYXJncywKICAgICAgICAgICAgb3B0aW9uYWxDb250ZW50CiAgICAgICAgICB9OwogICAgICAgICAgbG9jYWxJbWFnZUNhY2hlLnNldChjYWNoZUtleSwgaW1hZ2VSZWYsIGNhY2hlRGF0YSk7CiAgICAgICAgICBpZiAoaW1hZ2VSZWYpIHsKICAgICAgICAgICAgdGhpcy5fcmVnaW9uYWxJbWFnZUNhY2hlLnNldChudWxsLCBpbWFnZVJlZiwgY2FjaGVEYXRhKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICh0aGlzLnBhcnNpbmdUeXBlM0ZvbnQpIHsKICAgICAgICBhcmdzID0gY29tcGlsZVR5cGUzR2x5cGgoaW1nRGF0YSk7CiAgICAgICAgaWYgKGFyZ3MpIHsKICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRJbWFnZU9wcyhPUFMuY29uc3RydWN0UGF0aCwgYXJncywgb3B0aW9uYWxDb250ZW50KTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgd2FybigiQ2Fubm90IGNvbXBpbGUgVHlwZTMgZ2x5cGguIik7CiAgICAgICAgb3BlcmF0b3JMaXN0LmFkZEltYWdlT3BzKE9QUy5wYWludEltYWdlTWFza1hPYmplY3QsIFtpbWdEYXRhXSwgb3B0aW9uYWxDb250ZW50KTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29uc3Qgb2JqSWQgPSBgbWFza18ke3RoaXMuaWRGYWN0b3J5LmNyZWF0ZU9iaklkKCl9YDsKICAgICAgb3BlcmF0b3JMaXN0LmFkZERlcGVuZGVuY3kob2JqSWQpOwogICAgICBpbWdEYXRhLmRhdGFMZW4gPSBpbWdEYXRhLmJpdG1hcCA/IGltZ0RhdGEud2lkdGggKiBpbWdEYXRhLmhlaWdodCAqIDQgOiBpbWdEYXRhLmRhdGEubGVuZ3RoOwogICAgICB0aGlzLl9zZW5kSW1nRGF0YShvYmpJZCwgaW1nRGF0YSk7CiAgICAgIGZuID0gT1BTLnBhaW50SW1hZ2VNYXNrWE9iamVjdDsKICAgICAgYXJncyA9IFt7CiAgICAgICAgZGF0YTogb2JqSWQsCiAgICAgICAgd2lkdGg6IGltZ0RhdGEud2lkdGgsCiAgICAgICAgaGVpZ2h0OiBpbWdEYXRhLmhlaWdodCwKICAgICAgICBpbnRlcnBvbGF0ZTogaW1nRGF0YS5pbnRlcnBvbGF0ZSwKICAgICAgICBjb3VudDogMQogICAgICB9XTsKICAgICAgb3BlcmF0b3JMaXN0LmFkZEltYWdlT3BzKGZuLCBhcmdzLCBvcHRpb25hbENvbnRlbnQpOwogICAgICBpZiAoY2FjaGVLZXkpIHsKICAgICAgICBjb25zdCBjYWNoZURhdGEgPSB7CiAgICAgICAgICBvYmpJZCwKICAgICAgICAgIGZuLAogICAgICAgICAgYXJncywKICAgICAgICAgIG9wdGlvbmFsQ29udGVudAogICAgICAgIH07CiAgICAgICAgbG9jYWxJbWFnZUNhY2hlLnNldChjYWNoZUtleSwgaW1hZ2VSZWYsIGNhY2hlRGF0YSk7CiAgICAgICAgaWYgKGltYWdlUmVmKSB7CiAgICAgICAgICB0aGlzLl9yZWdpb25hbEltYWdlQ2FjaGUuc2V0KG51bGwsIGltYWdlUmVmLCBjYWNoZURhdGEpOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBTTUFMTF9JTUFHRV9ESU1FTlNJT05TID0gMjAwOwogICAgY29uc3QgaGFzTWFzayA9IGRpY3QuaGFzKCJTTWFzayIpIHx8IGRpY3QuaGFzKCJNYXNrIik7CiAgICBpZiAoaXNJbmxpbmUgJiYgdyArIGggPCBTTUFMTF9JTUFHRV9ESU1FTlNJT05TICYmICFoYXNNYXNrKSB7CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3QgaW1hZ2VPYmogPSBuZXcgUERGSW1hZ2UoewogICAgICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICAgICAgcmVzOiByZXNvdXJjZXMsCiAgICAgICAgICBpbWFnZSwKICAgICAgICAgIGlzSW5saW5lLAogICAgICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5OiB0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGU6IHRoaXMuZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgICAgICB9KTsKICAgICAgICBpbWdEYXRhID0gYXdhaXQgaW1hZ2VPYmouY3JlYXRlSW1hZ2VEYXRhKHRydWUsIGZhbHNlKTsKICAgICAgICBvcGVyYXRvckxpc3QuYWRkSW1hZ2VPcHMoT1BTLnBhaW50SW5saW5lSW1hZ2VYT2JqZWN0LCBbaW1nRGF0YV0sIG9wdGlvbmFsQ29udGVudCk7CiAgICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICAgIGNvbnN0IG1zZyA9IGBVbmFibGUgdG8gZGVjb2RlIGlubGluZSBpbWFnZTogIiR7cmVhc29ufSIuYDsKICAgICAgICBpZiAoIWlnbm9yZUVycm9ycykgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7CiAgICAgICAgfQogICAgICAgIHdhcm4obXNnKTsKICAgICAgfQogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgb2JqSWQgPSBgaW1nXyR7dGhpcy5pZEZhY3RvcnkuY3JlYXRlT2JqSWQoKX1gLAogICAgICBjYWNoZUdsb2JhbGx5ID0gZmFsc2UsCiAgICAgIGdsb2JhbENhY2hlRGF0YSA9IG51bGw7CiAgICBpZiAodGhpcy5wYXJzaW5nVHlwZTNGb250KSB7CiAgICAgIG9iaklkID0gYCR7dGhpcy5pZEZhY3RvcnkuZ2V0RG9jSWQoKX1fdHlwZTNfJHtvYmpJZH1gOwogICAgfSBlbHNlIGlmIChjYWNoZUtleSAmJiBpbWFnZVJlZikgewogICAgICBjYWNoZUdsb2JhbGx5ID0gdGhpcy5nbG9iYWxJbWFnZUNhY2hlLnNob3VsZENhY2hlKGltYWdlUmVmLCB0aGlzLnBhZ2VJbmRleCk7CiAgICAgIGlmIChjYWNoZUdsb2JhbGx5KSB7CiAgICAgICAgYXNzZXJ0KCFpc0lubGluZSwgIkNhbm5vdCBjYWNoZSBhbiBpbmxpbmUgaW1hZ2UgZ2xvYmFsbHkuIik7CiAgICAgICAgb2JqSWQgPSBgJHt0aGlzLmlkRmFjdG9yeS5nZXREb2NJZCgpfV8ke29iaklkfWA7CiAgICAgIH0KICAgIH0KICAgIG9wZXJhdG9yTGlzdC5hZGREZXBlbmRlbmN5KG9iaklkKTsKICAgIGZuID0gT1BTLnBhaW50SW1hZ2VYT2JqZWN0OwogICAgYXJncyA9IFtvYmpJZCwgdywgaF07CiAgICBvcGVyYXRvckxpc3QuYWRkSW1hZ2VPcHMoZm4sIGFyZ3MsIG9wdGlvbmFsQ29udGVudCwgaGFzTWFzayk7CiAgICBpZiAoY2FjaGVHbG9iYWxseSkgewogICAgICBnbG9iYWxDYWNoZURhdGEgPSB7CiAgICAgICAgb2JqSWQsCiAgICAgICAgZm4sCiAgICAgICAgYXJncywKICAgICAgICBvcHRpb25hbENvbnRlbnQsCiAgICAgICAgaGFzTWFzaywKICAgICAgICBieXRlU2l6ZTogMAogICAgICB9OwogICAgICBpZiAodGhpcy5nbG9iYWxJbWFnZUNhY2hlLmhhc0RlY29kZUZhaWxlZChpbWFnZVJlZikpIHsKICAgICAgICB0aGlzLmdsb2JhbEltYWdlQ2FjaGUuc2V0RGF0YShpbWFnZVJlZiwgZ2xvYmFsQ2FjaGVEYXRhKTsKICAgICAgICB0aGlzLl9zZW5kSW1nRGF0YShvYmpJZCwgbnVsbCwgY2FjaGVHbG9iYWxseSk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICh3ICogaCA+IDI1MDAwMCB8fCBoYXNNYXNrKSB7CiAgICAgICAgY29uc3QgbG9jYWxMZW5ndGggPSBhd2FpdCB0aGlzLmhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJjb21tb25vYmoiLCBbb2JqSWQsICJDb3B5TG9jYWxJbWFnZSIsIHsKICAgICAgICAgIGltYWdlUmVmCiAgICAgICAgfV0pOwogICAgICAgIGlmIChsb2NhbExlbmd0aCkgewogICAgICAgICAgdGhpcy5nbG9iYWxJbWFnZUNhY2hlLnNldERhdGEoaW1hZ2VSZWYsIGdsb2JhbENhY2hlRGF0YSk7CiAgICAgICAgICB0aGlzLmdsb2JhbEltYWdlQ2FjaGUuYWRkQnl0ZVNpemUoaW1hZ2VSZWYsIGxvY2FsTGVuZ3RoKTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIFBERkltYWdlLmJ1aWxkSW1hZ2UoewogICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgIHJlczogcmVzb3VyY2VzLAogICAgICBpbWFnZSwKICAgICAgaXNJbmxpbmUsCiAgICAgIHBkZkZ1bmN0aW9uRmFjdG9yeTogdGhpcy5fcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGU6IHRoaXMuZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgfSkudGhlbihhc3luYyBpbWFnZU9iaiA9PiB7CiAgICAgIGltZ0RhdGEgPSBhd2FpdCBpbWFnZU9iai5jcmVhdGVJbWFnZURhdGEoZmFsc2UsIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKTsKICAgICAgaW1nRGF0YS5kYXRhTGVuID0gaW1nRGF0YS5iaXRtYXAgPyBpbWdEYXRhLndpZHRoICogaW1nRGF0YS5oZWlnaHQgKiA0IDogaW1nRGF0YS5kYXRhLmxlbmd0aDsKICAgICAgaW1nRGF0YS5yZWYgPSBpbWFnZVJlZjsKICAgICAgaWYgKGNhY2hlR2xvYmFsbHkpIHsKICAgICAgICB0aGlzLmdsb2JhbEltYWdlQ2FjaGUuYWRkQnl0ZVNpemUoaW1hZ2VSZWYsIGltZ0RhdGEuZGF0YUxlbik7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX3NlbmRJbWdEYXRhKG9iaklkLCBpbWdEYXRhLCBjYWNoZUdsb2JhbGx5KTsKICAgIH0pLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgIHdhcm4oYFVuYWJsZSB0byBkZWNvZGUgaW1hZ2UgIiR7b2JqSWR9IjogIiR7cmVhc29ufSIuYCk7CiAgICAgIGlmIChpbWFnZVJlZikgewogICAgICAgIHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZS5hZGREZWNvZGVGYWlsZWQoaW1hZ2VSZWYpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLl9zZW5kSW1nRGF0YShvYmpJZCwgbnVsbCwgY2FjaGVHbG9iYWxseSk7CiAgICB9KTsKICAgIGlmIChjYWNoZUtleSkgewogICAgICBjb25zdCBjYWNoZURhdGEgPSB7CiAgICAgICAgb2JqSWQsCiAgICAgICAgZm4sCiAgICAgICAgYXJncywKICAgICAgICBvcHRpb25hbENvbnRlbnQsCiAgICAgICAgaGFzTWFzawogICAgICB9OwogICAgICBsb2NhbEltYWdlQ2FjaGUuc2V0KGNhY2hlS2V5LCBpbWFnZVJlZiwgY2FjaGVEYXRhKTsKICAgICAgaWYgKGltYWdlUmVmKSB7CiAgICAgICAgdGhpcy5fcmVnaW9uYWxJbWFnZUNhY2hlLnNldChudWxsLCBpbWFnZVJlZiwgY2FjaGVEYXRhKTsKICAgICAgICBpZiAoY2FjaGVHbG9iYWxseSkgewogICAgICAgICAgYXNzZXJ0KGdsb2JhbENhY2hlRGF0YSwgIlRoZSBnbG9iYWwgY2FjaGUtZGF0YSBtdXN0IGJlIGF2YWlsYWJsZS4iKTsKICAgICAgICAgIHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZS5zZXREYXRhKGltYWdlUmVmLCBnbG9iYWxDYWNoZURhdGEpOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICBoYW5kbGVTTWFzayhzbWFzaywgcmVzb3VyY2VzLCBvcGVyYXRvckxpc3QsIHRhc2ssIHN0YXRlTWFuYWdlciwgbG9jYWxDb2xvclNwYWNlQ2FjaGUsIHNlZW5SZWZzKSB7CiAgICBjb25zdCBzbWFza0NvbnRlbnQgPSBzbWFzay5nZXQoIkciKTsKICAgIGNvbnN0IHNtYXNrT3B0aW9ucyA9IHsKICAgICAgc3VidHlwZTogc21hc2suZ2V0KCJTIikubmFtZSwKICAgICAgYmFja2Ryb3A6IHNtYXNrLmdldCgiQkMiKQogICAgfTsKICAgIGNvbnN0IHRyYW5zZmVyT2JqID0gc21hc2suZ2V0KCJUUiIpOwogICAgaWYgKGlzUERGRnVuY3Rpb24odHJhbnNmZXJPYmopKSB7CiAgICAgIGNvbnN0IHRyYW5zZmVyRm4gPSB0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnkuY3JlYXRlKHRyYW5zZmVyT2JqKTsKICAgICAgY29uc3QgdHJhbnNmZXJNYXAgPSBuZXcgVWludDhBcnJheSgyNTYpOwogICAgICBjb25zdCB0bXAgPSBuZXcgRmxvYXQzMkFycmF5KDEpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgaSsrKSB7CiAgICAgICAgdG1wWzBdID0gaSAvIDI1NTsKICAgICAgICB0cmFuc2ZlckZuKHRtcCwgMCwgdG1wLCAwKTsKICAgICAgICB0cmFuc2Zlck1hcFtpXSA9IHRtcFswXSAqIDI1NSB8IDA7CiAgICAgIH0KICAgICAgc21hc2tPcHRpb25zLnRyYW5zZmVyTWFwID0gdHJhbnNmZXJNYXA7CiAgICB9CiAgICByZXR1cm4gdGhpcy5idWlsZEZvcm1YT2JqZWN0KHJlc291cmNlcywgc21hc2tDb250ZW50LCBzbWFza09wdGlvbnMsIG9wZXJhdG9yTGlzdCwgdGFzaywgc3RhdGVNYW5hZ2VyLnN0YXRlLmNsb25lKHsKICAgICAgbmV3UGF0aDogdHJ1ZQogICAgfSksIGxvY2FsQ29sb3JTcGFjZUNhY2hlLCBzZWVuUmVmcyk7CiAgfQogIGhhbmRsZVRyYW5zZmVyRnVuY3Rpb24odHIpIHsKICAgIGxldCB0cmFuc2ZlckFycmF5OwogICAgaWYgKEFycmF5LmlzQXJyYXkodHIpKSB7CiAgICAgIHRyYW5zZmVyQXJyYXkgPSB0cjsKICAgIH0gZWxzZSBpZiAoaXNQREZGdW5jdGlvbih0cikpIHsKICAgICAgdHJhbnNmZXJBcnJheSA9IFt0cl07CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHRyYW5zZmVyTWFwcyA9IFtdOwogICAgbGV0IG51bUZucyA9IDAsCiAgICAgIG51bUVmZmVjdGZ1bEZucyA9IDA7CiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIHRyYW5zZmVyQXJyYXkpIHsKICAgICAgY29uc3QgdHJhbnNmZXJPYmogPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihlbnRyeSk7CiAgICAgIG51bUZucysrOwogICAgICBpZiAoaXNOYW1lKHRyYW5zZmVyT2JqLCAiSWRlbnRpdHkiKSkgewogICAgICAgIHRyYW5zZmVyTWFwcy5wdXNoKG51bGwpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgaWYgKCFpc1BERkZ1bmN0aW9uKHRyYW5zZmVyT2JqKSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IHRyYW5zZmVyRm4gPSB0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnkuY3JlYXRlKHRyYW5zZmVyT2JqKTsKICAgICAgY29uc3QgdHJhbnNmZXJNYXAgPSBuZXcgVWludDhBcnJheSgyNTYpLAogICAgICAgIHRtcCA9IG5ldyBGbG9hdDMyQXJyYXkoMSk7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMjU2OyBqKyspIHsKICAgICAgICB0bXBbMF0gPSBqIC8gMjU1OwogICAgICAgIHRyYW5zZmVyRm4odG1wLCAwLCB0bXAsIDApOwogICAgICAgIHRyYW5zZmVyTWFwW2pdID0gdG1wWzBdICogMjU1IHwgMDsKICAgICAgfQogICAgICB0cmFuc2Zlck1hcHMucHVzaCh0cmFuc2Zlck1hcCk7CiAgICAgIG51bUVmZmVjdGZ1bEZucysrOwogICAgfQogICAgaWYgKCEobnVtRm5zID09PSAxIHx8IG51bUZucyA9PT0gNCkpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBpZiAobnVtRWZmZWN0ZnVsRm5zID09PSAwKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcmV0dXJuIHRyYW5zZmVyTWFwczsKICB9CiAgaGFuZGxlVGlsaW5nVHlwZShmbiwgY29sb3IsIHJlc291cmNlcywgcGF0dGVybiwgcGF0dGVybkRpY3QsIG9wZXJhdG9yTGlzdCwgdGFzaywgbG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUpIHsKICAgIGNvbnN0IHRpbGluZ09wTGlzdCA9IG5ldyBPcGVyYXRvckxpc3QoKTsKICAgIGNvbnN0IHBhdHRlcm5SZXNvdXJjZXMgPSBEaWN0Lm1lcmdlKHsKICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICBkaWN0QXJyYXk6IFtwYXR0ZXJuRGljdC5nZXQoIlJlc291cmNlcyIpLCByZXNvdXJjZXNdCiAgICB9KTsKICAgIHJldHVybiB0aGlzLmdldE9wZXJhdG9yTGlzdCh7CiAgICAgIHN0cmVhbTogcGF0dGVybiwKICAgICAgdGFzaywKICAgICAgcmVzb3VyY2VzOiBwYXR0ZXJuUmVzb3VyY2VzLAogICAgICBvcGVyYXRvckxpc3Q6IHRpbGluZ09wTGlzdAogICAgfSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgIGNvbnN0IG9wZXJhdG9yTGlzdElSID0gdGlsaW5nT3BMaXN0LmdldElSKCk7CiAgICAgIGNvbnN0IHRpbGluZ1BhdHRlcm5JUiA9IGdldFRpbGluZ1BhdHRlcm5JUihvcGVyYXRvckxpc3RJUiwgcGF0dGVybkRpY3QsIGNvbG9yKTsKICAgICAgb3BlcmF0b3JMaXN0LmFkZERlcGVuZGVuY2llcyh0aWxpbmdPcExpc3QuZGVwZW5kZW5jaWVzKTsKICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKGZuLCB0aWxpbmdQYXR0ZXJuSVIpOwogICAgICBpZiAocGF0dGVybkRpY3Qub2JqSWQpIHsKICAgICAgICBsb2NhbFRpbGluZ1BhdHRlcm5DYWNoZS5zZXQobnVsbCwgcGF0dGVybkRpY3Qub2JqSWQsIHsKICAgICAgICAgIG9wZXJhdG9yTGlzdElSLAogICAgICAgICAgZGljdDogcGF0dGVybkRpY3QKICAgICAgICB9KTsKICAgICAgfQogICAgfSkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIEFib3J0RXhjZXB0aW9uKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgd2FybihgaGFuZGxlVGlsaW5nVHlwZSAtIGlnbm9yaW5nIHBhdHRlcm46ICIke3JlYXNvbn0iLmApOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICB0aHJvdyByZWFzb247CiAgICB9KTsKICB9CiAgYXN5bmMgaGFuZGxlU2V0Rm9udChyZXNvdXJjZXMsIGZvbnRBcmdzLCBmb250UmVmLCBvcGVyYXRvckxpc3QsIHRhc2ssIHN0YXRlLCBmYWxsYmFja0ZvbnREaWN0ID0gbnVsbCwgY3NzRm9udEluZm8gPSBudWxsKSB7CiAgICBjb25zdCBmb250TmFtZSA9IGZvbnRBcmdzPy5bMF0gaW5zdGFuY2VvZiBOYW1lID8gZm9udEFyZ3NbMF0ubmFtZSA6IG51bGw7CiAgICBjb25zdCB0cmFuc2xhdGVkID0gYXdhaXQgdGhpcy5sb2FkRm9udChmb250TmFtZSwgZm9udFJlZiwgcmVzb3VyY2VzLCB0YXNrLCBmYWxsYmFja0ZvbnREaWN0LCBjc3NGb250SW5mbyk7CiAgICBpZiAodHJhbnNsYXRlZC5mb250LmlzVHlwZTNGb250KSB7CiAgICAgIG9wZXJhdG9yTGlzdC5hZGREZXBlbmRlbmNpZXModHJhbnNsYXRlZC50eXBlM0RlcGVuZGVuY2llcyk7CiAgICB9CiAgICBzdGF0ZS5mb250ID0gdHJhbnNsYXRlZC5mb250OwogICAgdHJhbnNsYXRlZC5zZW5kKHRoaXMuaGFuZGxlcik7CiAgICByZXR1cm4gdHJhbnNsYXRlZC5sb2FkZWROYW1lOwogIH0KICBoYW5kbGVUZXh0KGNoYXJzLCBzdGF0ZSkgewogICAgY29uc3QgZm9udCA9IHN0YXRlLmZvbnQ7CiAgICBjb25zdCBnbHlwaHMgPSBmb250LmNoYXJzVG9HbHlwaHMoY2hhcnMpOwogICAgaWYgKGZvbnQuZGF0YSkgewogICAgICBjb25zdCBpc0FkZFRvUGF0aFNldCA9ICEhKHN0YXRlLnRleHRSZW5kZXJpbmdNb2RlICYgVGV4dFJlbmRlcmluZ01vZGUuQUREX1RPX1BBVEhfRkxBRyk7CiAgICAgIGlmIChpc0FkZFRvUGF0aFNldCB8fCBzdGF0ZS5maWxsQ29sb3JTcGFjZS5uYW1lID09PSAiUGF0dGVybiIgfHwgc3RhdGUuc3Ryb2tlQ29sb3JTcGFjZS5uYW1lID09PSAiUGF0dGVybiIgfHwgZm9udC5kaXNhYmxlRm9udEZhY2UpIHsKICAgICAgICBQYXJ0aWFsRXZhbHVhdG9yLmJ1aWxkRm9udFBhdGhzKGZvbnQsIGdseXBocywgdGhpcy5oYW5kbGVyLCB0aGlzLm9wdGlvbnMpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZ2x5cGhzOwogIH0KICBlbnN1cmVTdGF0ZUZvbnQoc3RhdGUpIHsKICAgIGlmIChzdGF0ZS5mb250KSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHJlYXNvbiA9IG5ldyBGb3JtYXRFcnJvcigiTWlzc2luZyBzZXRGb250IChUZikgb3BlcmF0b3IgYmVmb3JlIHRleHQgcmVuZGVyaW5nIG9wZXJhdG9yLiIpOwogICAgaWYgKHRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgd2FybihgZW5zdXJlU3RhdGVGb250OiAiJHtyZWFzb259Ii5gKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhyb3cgcmVhc29uOwogIH0KICBhc3luYyBzZXRHU3RhdGUoewogICAgcmVzb3VyY2VzLAogICAgZ1N0YXRlLAogICAgb3BlcmF0b3JMaXN0LAogICAgY2FjaGVLZXksCiAgICB0YXNrLAogICAgc3RhdGVNYW5hZ2VyLAogICAgbG9jYWxHU3RhdGVDYWNoZSwKICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlLAogICAgc2VlblJlZnMKICB9KSB7CiAgICBjb25zdCBnU3RhdGVSZWYgPSBnU3RhdGUub2JqSWQ7CiAgICBsZXQgaXNTaW1wbGVHU3RhdGUgPSB0cnVlOwogICAgY29uc3QgZ1N0YXRlT2JqID0gW107CiAgICBsZXQgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpOwogICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgZ1N0YXRlKSB7CiAgICAgIHN3aXRjaCAoa2V5KSB7CiAgICAgICAgY2FzZSAiVHlwZSI6CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJMVyI6CiAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAibnVtYmVyIikgewogICAgICAgICAgICB3YXJuKGBJbnZhbGlkIExXIChsaW5lIHdpZHRoKTogJHt2YWx1ZX1gKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBnU3RhdGVPYmoucHVzaChba2V5LCBNYXRoLmFicyh2YWx1ZSldKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkxDIjoKICAgICAgICBjYXNlICJMSiI6CiAgICAgICAgY2FzZSAiTUwiOgogICAgICAgIGNhc2UgIkQiOgogICAgICAgIGNhc2UgIlJJIjoKICAgICAgICBjYXNlICJGTCI6CiAgICAgICAgY2FzZSAiQ0EiOgogICAgICAgIGNhc2UgImNhIjoKICAgICAgICAgIGdTdGF0ZU9iai5wdXNoKFtrZXksIHZhbHVlXSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJGb250IjoKICAgICAgICAgIGlzU2ltcGxlR1N0YXRlID0gZmFsc2U7CiAgICAgICAgICBwcm9taXNlID0gcHJvbWlzZS50aGVuKCgpID0+IHRoaXMuaGFuZGxlU2V0Rm9udChyZXNvdXJjZXMsIG51bGwsIHZhbHVlWzBdLCBvcGVyYXRvckxpc3QsIHRhc2ssIHN0YXRlTWFuYWdlci5zdGF0ZSkudGhlbihmdW5jdGlvbiAobG9hZGVkTmFtZSkgewogICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkRGVwZW5kZW5jeShsb2FkZWROYW1lKTsKICAgICAgICAgICAgZ1N0YXRlT2JqLnB1c2goW2tleSwgW2xvYWRlZE5hbWUsIHZhbHVlWzFdXV0pOwogICAgICAgICAgfSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiQk0iOgogICAgICAgICAgZ1N0YXRlT2JqLnB1c2goW2tleSwgbm9ybWFsaXplQmxlbmRNb2RlKHZhbHVlKV0pOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiU01hc2siOgogICAgICAgICAgaWYgKGlzTmFtZSh2YWx1ZSwgIk5vbmUiKSkgewogICAgICAgICAgICBnU3RhdGVPYmoucHVzaChba2V5LCBmYWxzZV0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICAgICAgaXNTaW1wbGVHU3RhdGUgPSBmYWxzZTsKICAgICAgICAgICAgcHJvbWlzZSA9IHByb21pc2UudGhlbigoKSA9PiB0aGlzLmhhbmRsZVNNYXNrKHZhbHVlLCByZXNvdXJjZXMsIG9wZXJhdG9yTGlzdCwgdGFzaywgc3RhdGVNYW5hZ2VyLCBsb2NhbENvbG9yU3BhY2VDYWNoZSwgc2VlblJlZnMpKTsKICAgICAgICAgICAgZ1N0YXRlT2JqLnB1c2goW2tleSwgdHJ1ZV0pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgd2FybigiVW5zdXBwb3J0ZWQgU01hc2sgdHlwZSIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiVFIiOgogICAgICAgICAgY29uc3QgdHJhbnNmZXJNYXBzID0gdGhpcy5oYW5kbGVUcmFuc2ZlckZ1bmN0aW9uKHZhbHVlKTsKICAgICAgICAgIGdTdGF0ZU9iai5wdXNoKFtrZXksIHRyYW5zZmVyTWFwc10pOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiT1AiOgogICAgICAgIGNhc2UgIm9wIjoKICAgICAgICBjYXNlICJPUE0iOgogICAgICAgIGNhc2UgIkJHIjoKICAgICAgICBjYXNlICJCRzIiOgogICAgICAgIGNhc2UgIlVDUiI6CiAgICAgICAgY2FzZSAiVUNSMiI6CiAgICAgICAgY2FzZSAiVFIyIjoKICAgICAgICBjYXNlICJIVCI6CiAgICAgICAgY2FzZSAiU00iOgogICAgICAgIGNhc2UgIlNBIjoKICAgICAgICBjYXNlICJBSVMiOgogICAgICAgIGNhc2UgIlRLIjoKICAgICAgICAgIGluZm8oImdyYXBoaWMgc3RhdGUgb3BlcmF0b3IgIiArIGtleSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgaW5mbygiVW5rbm93biBncmFwaGljIHN0YXRlIG9wZXJhdG9yICIgKyBrZXkpOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGF3YWl0IHByb21pc2U7CiAgICBpZiAoZ1N0YXRlT2JqLmxlbmd0aCA+IDApIHsKICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5zZXRHU3RhdGUsIFtnU3RhdGVPYmpdKTsKICAgIH0KICAgIGlmIChpc1NpbXBsZUdTdGF0ZSkgewogICAgICBsb2NhbEdTdGF0ZUNhY2hlLnNldChjYWNoZUtleSwgZ1N0YXRlUmVmLCBnU3RhdGVPYmopOwogICAgfQogIH0KICBsb2FkRm9udChmb250TmFtZSwgZm9udCwgcmVzb3VyY2VzLCB0YXNrLCBmYWxsYmFja0ZvbnREaWN0ID0gbnVsbCwgY3NzRm9udEluZm8gPSBudWxsKSB7CiAgICBjb25zdCBlcnJvckZvbnQgPSBhc3luYyAoKSA9PiBuZXcgVHJhbnNsYXRlZEZvbnQoewogICAgICBsb2FkZWROYW1lOiAiZ19mb250X2Vycm9yIiwKICAgICAgZm9udDogbmV3IEVycm9yRm9udChgRm9udCAiJHtmb250TmFtZX0iIGlzIG5vdCBhdmFpbGFibGUuYCksCiAgICAgIGRpY3Q6IGZvbnQKICAgIH0pOwogICAgbGV0IGZvbnRSZWY7CiAgICBpZiAoZm9udCkgewogICAgICBpZiAoZm9udCBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIGZvbnRSZWYgPSBmb250OwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBmb250UmVzID0gcmVzb3VyY2VzLmdldCgiRm9udCIpOwogICAgICBpZiAoZm9udFJlcykgewogICAgICAgIGZvbnRSZWYgPSBmb250UmVzLmdldFJhdyhmb250TmFtZSk7CiAgICAgIH0KICAgIH0KICAgIGlmIChmb250UmVmKSB7CiAgICAgIGlmICh0aGlzLnR5cGUzRm9udFJlZnM/Lmhhcyhmb250UmVmKSkgewogICAgICAgIHJldHVybiBlcnJvckZvbnQoKTsKICAgICAgfQogICAgICBpZiAodGhpcy5mb250Q2FjaGUuaGFzKGZvbnRSZWYpKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZm9udENhY2hlLmdldChmb250UmVmKTsKICAgICAgfQogICAgICB0cnkgewogICAgICAgIGZvbnQgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihmb250UmVmKTsKICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICB3YXJuKGBsb2FkRm9udCAtIGxvb2t1cCBmYWlsZWQ6ICIke2V4fSIuYCk7CiAgICAgIH0KICAgIH0KICAgIGlmICghKGZvbnQgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICBpZiAoIXRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMgJiYgIXRoaXMucGFyc2luZ1R5cGUzRm9udCkgewogICAgICAgIHdhcm4oYEZvbnQgIiR7Zm9udE5hbWV9IiBpcyBub3QgYXZhaWxhYmxlLmApOwogICAgICAgIHJldHVybiBlcnJvckZvbnQoKTsKICAgICAgfQogICAgICB3YXJuKGBGb250ICIke2ZvbnROYW1lfSIgaXMgbm90IGF2YWlsYWJsZSAtLSBhdHRlbXB0aW5nIHRvIGZhbGxiYWNrIHRvIGEgZGVmYXVsdCBmb250LmApOwogICAgICBmb250ID0gZmFsbGJhY2tGb250RGljdCB8fCBQYXJ0aWFsRXZhbHVhdG9yLmZhbGxiYWNrRm9udERpY3Q7CiAgICB9CiAgICBpZiAoZm9udC5jYWNoZUtleSAmJiB0aGlzLmZvbnRDYWNoZS5oYXMoZm9udC5jYWNoZUtleSkpIHsKICAgICAgcmV0dXJuIHRoaXMuZm9udENhY2hlLmdldChmb250LmNhY2hlS2V5KTsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgcHJvbWlzZSwKICAgICAgcmVzb2x2ZQogICAgfSA9IFByb21pc2Uud2l0aFJlc29sdmVycygpOwogICAgbGV0IHByZUV2YWx1YXRlZEZvbnQ7CiAgICB0cnkgewogICAgICBwcmVFdmFsdWF0ZWRGb250ID0gdGhpcy5wcmVFdmFsdWF0ZUZvbnQoZm9udCk7CiAgICAgIHByZUV2YWx1YXRlZEZvbnQuY3NzRm9udEluZm8gPSBjc3NGb250SW5mbzsKICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICB3YXJuKGBsb2FkRm9udCAtIHByZUV2YWx1YXRlRm9udCBmYWlsZWQ6ICIke3JlYXNvbn0iLmApOwogICAgICByZXR1cm4gZXJyb3JGb250KCk7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIGRlc2NyaXB0b3IsCiAgICAgIGhhc2gKICAgIH0gPSBwcmVFdmFsdWF0ZWRGb250OwogICAgY29uc3QgZm9udFJlZklzUmVmID0gZm9udFJlZiBpbnN0YW5jZW9mIFJlZjsKICAgIGxldCBmb250SUQ7CiAgICBpZiAoaGFzaCAmJiBkZXNjcmlwdG9yIGluc3RhbmNlb2YgRGljdCkgewogICAgICBjb25zdCBmb250QWxpYXNlcyA9IGRlc2NyaXB0b3IuZm9udEFsaWFzZXMgfHw9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIGlmIChmb250QWxpYXNlc1toYXNoXSkgewogICAgICAgIGNvbnN0IGFsaWFzRm9udFJlZiA9IGZvbnRBbGlhc2VzW2hhc2hdLmFsaWFzUmVmOwogICAgICAgIGlmIChmb250UmVmSXNSZWYgJiYgYWxpYXNGb250UmVmICYmIHRoaXMuZm9udENhY2hlLmhhcyhhbGlhc0ZvbnRSZWYpKSB7CiAgICAgICAgICB0aGlzLmZvbnRDYWNoZS5wdXRBbGlhcyhmb250UmVmLCBhbGlhc0ZvbnRSZWYpOwogICAgICAgICAgcmV0dXJuIHRoaXMuZm9udENhY2hlLmdldChmb250UmVmKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9udEFsaWFzZXNbaGFzaF0gPSB7CiAgICAgICAgICBmb250SUQ6IHRoaXMuaWRGYWN0b3J5LmNyZWF0ZUZvbnRJZCgpCiAgICAgICAgfTsKICAgICAgfQogICAgICBpZiAoZm9udFJlZklzUmVmKSB7CiAgICAgICAgZm9udEFsaWFzZXNbaGFzaF0uYWxpYXNSZWYgPSBmb250UmVmOwogICAgICB9CiAgICAgIGZvbnRJRCA9IGZvbnRBbGlhc2VzW2hhc2hdLmZvbnRJRDsKICAgIH0gZWxzZSB7CiAgICAgIGZvbnRJRCA9IHRoaXMuaWRGYWN0b3J5LmNyZWF0ZUZvbnRJZCgpOwogICAgfQogICAgYXNzZXJ0KGZvbnRJRD8uc3RhcnRzV2l0aCgiZiIpLCAnVGhlICJmb250SUQiIG11c3QgYmUgKGNvcnJlY3RseSkgZGVmaW5lZC4nKTsKICAgIGlmIChmb250UmVmSXNSZWYpIHsKICAgICAgdGhpcy5mb250Q2FjaGUucHV0KGZvbnRSZWYsIHByb21pc2UpOwogICAgfSBlbHNlIHsKICAgICAgZm9udC5jYWNoZUtleSA9IGBjYWNoZUtleV8ke2ZvbnRJRH1gOwogICAgICB0aGlzLmZvbnRDYWNoZS5wdXQoZm9udC5jYWNoZUtleSwgcHJvbWlzZSk7CiAgICB9CiAgICBmb250LmxvYWRlZE5hbWUgPSBgJHt0aGlzLmlkRmFjdG9yeS5nZXREb2NJZCgpfV8ke2ZvbnRJRH1gOwogICAgdGhpcy50cmFuc2xhdGVGb250KHByZUV2YWx1YXRlZEZvbnQpLnRoZW4oYXN5bmMgdHJhbnNsYXRlZEZvbnQgPT4gewogICAgICBjb25zdCB0cmFuc2xhdGVkID0gbmV3IFRyYW5zbGF0ZWRGb250KHsKICAgICAgICBsb2FkZWROYW1lOiBmb250LmxvYWRlZE5hbWUsCiAgICAgICAgZm9udDogdHJhbnNsYXRlZEZvbnQsCiAgICAgICAgZGljdDogZm9udAogICAgICB9KTsKICAgICAgaWYgKHRyYW5zbGF0ZWRGb250LmlzVHlwZTNGb250KSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGF3YWl0IHRyYW5zbGF0ZWQubG9hZFR5cGUzRGF0YSh0aGlzLCByZXNvdXJjZXMsIHRhc2spOwogICAgICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUeXBlMyBmb250IGxvYWQgZXJyb3I6ICR7cmVhc29ufWApOwogICAgICAgIH0KICAgICAgfQogICAgICByZXNvbHZlKHRyYW5zbGF0ZWQpOwogICAgfSkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgd2FybihgbG9hZEZvbnQgLSB0cmFuc2xhdGVGb250IGZhaWxlZDogIiR7cmVhc29ufSIuYCk7CiAgICAgIHJlc29sdmUobmV3IFRyYW5zbGF0ZWRGb250KHsKICAgICAgICBsb2FkZWROYW1lOiBmb250LmxvYWRlZE5hbWUsCiAgICAgICAgZm9udDogbmV3IEVycm9yRm9udChyZWFzb24/Lm1lc3NhZ2UpLAogICAgICAgIGRpY3Q6IGZvbnQKICAgICAgfSkpOwogICAgfSk7CiAgICByZXR1cm4gcHJvbWlzZTsKICB9CiAgYnVpbGRQYXRoKGZuLCBhcmdzLCBzdGF0ZSkgewogICAgY29uc3QgewogICAgICBwYXRoTWluTWF4OiBtaW5NYXgsCiAgICAgIHBhdGhCdWZmZXIKICAgIH0gPSBzdGF0ZTsKICAgIHN3aXRjaCAoZm4gfCAwKSB7CiAgICAgIGNhc2UgT1BTLnJlY3RhbmdsZToKICAgICAgICB7CiAgICAgICAgICBjb25zdCB4ID0gc3RhdGUuY3VycmVudFBvaW50WCA9IGFyZ3NbMF07CiAgICAgICAgICBjb25zdCB5ID0gc3RhdGUuY3VycmVudFBvaW50WSA9IGFyZ3NbMV07CiAgICAgICAgICBjb25zdCB3aWR0aCA9IGFyZ3NbMl07CiAgICAgICAgICBjb25zdCBoZWlnaHQgPSBhcmdzWzNdOwogICAgICAgICAgY29uc3QgeHcgPSB4ICsgd2lkdGg7CiAgICAgICAgICBjb25zdCB5aCA9IHkgKyBoZWlnaHQ7CiAgICAgICAgICBpZiAod2lkdGggPT09IDAgfHwgaGVpZ2h0ID09PSAwKSB7CiAgICAgICAgICAgIHBhdGhCdWZmZXIucHVzaChEcmF3T1BTLm1vdmVUbywgeCwgeSwgRHJhd09QUy5saW5lVG8sIHh3LCB5aCwgRHJhd09QUy5jbG9zZVBhdGgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcGF0aEJ1ZmZlci5wdXNoKERyYXdPUFMubW92ZVRvLCB4LCB5LCBEcmF3T1BTLmxpbmVUbywgeHcsIHksIERyYXdPUFMubGluZVRvLCB4dywgeWgsIERyYXdPUFMubGluZVRvLCB4LCB5aCwgRHJhd09QUy5jbG9zZVBhdGgpOwogICAgICAgICAgfQogICAgICAgICAgVXRpbC5yZWN0Qm91bmRpbmdCb3goeCwgeSwgeHcsIHloLCBtaW5NYXgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICBjYXNlIE9QUy5tb3ZlVG86CiAgICAgICAgewogICAgICAgICAgY29uc3QgeCA9IHN0YXRlLmN1cnJlbnRQb2ludFggPSBhcmdzWzBdOwogICAgICAgICAgY29uc3QgeSA9IHN0YXRlLmN1cnJlbnRQb2ludFkgPSBhcmdzWzFdOwogICAgICAgICAgcGF0aEJ1ZmZlci5wdXNoKERyYXdPUFMubW92ZVRvLCB4LCB5KTsKICAgICAgICAgIFV0aWwucG9pbnRCb3VuZGluZ0JveCh4LCB5LCBtaW5NYXgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICBjYXNlIE9QUy5saW5lVG86CiAgICAgICAgewogICAgICAgICAgY29uc3QgeCA9IHN0YXRlLmN1cnJlbnRQb2ludFggPSBhcmdzWzBdOwogICAgICAgICAgY29uc3QgeSA9IHN0YXRlLmN1cnJlbnRQb2ludFkgPSBhcmdzWzFdOwogICAgICAgICAgcGF0aEJ1ZmZlci5wdXNoKERyYXdPUFMubGluZVRvLCB4LCB5KTsKICAgICAgICAgIFV0aWwucG9pbnRCb3VuZGluZ0JveCh4LCB5LCBtaW5NYXgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICBjYXNlIE9QUy5jdXJ2ZVRvOgogICAgICAgIHsKICAgICAgICAgIGNvbnN0IHN0YXJ0WCA9IHN0YXRlLmN1cnJlbnRQb2ludFg7CiAgICAgICAgICBjb25zdCBzdGFydFkgPSBzdGF0ZS5jdXJyZW50UG9pbnRZOwogICAgICAgICAgY29uc3QgW3gxLCB5MSwgeDIsIHkyLCB4LCB5XSA9IGFyZ3M7CiAgICAgICAgICBzdGF0ZS5jdXJyZW50UG9pbnRYID0geDsKICAgICAgICAgIHN0YXRlLmN1cnJlbnRQb2ludFkgPSB5OwogICAgICAgICAgcGF0aEJ1ZmZlci5wdXNoKERyYXdPUFMuY3VydmVUbywgeDEsIHkxLCB4MiwgeTIsIHgsIHkpOwogICAgICAgICAgVXRpbC5iZXppZXJCb3VuZGluZ0JveChzdGFydFgsIHN0YXJ0WSwgeDEsIHkxLCB4MiwgeTIsIHgsIHksIG1pbk1heCk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIGNhc2UgT1BTLmN1cnZlVG8yOgogICAgICAgIHsKICAgICAgICAgIGNvbnN0IHN0YXJ0WCA9IHN0YXRlLmN1cnJlbnRQb2ludFg7CiAgICAgICAgICBjb25zdCBzdGFydFkgPSBzdGF0ZS5jdXJyZW50UG9pbnRZOwogICAgICAgICAgY29uc3QgW3gxLCB5MSwgeCwgeV0gPSBhcmdzOwogICAgICAgICAgc3RhdGUuY3VycmVudFBvaW50WCA9IHg7CiAgICAgICAgICBzdGF0ZS5jdXJyZW50UG9pbnRZID0geTsKICAgICAgICAgIHBhdGhCdWZmZXIucHVzaChEcmF3T1BTLmN1cnZlVG8sIHN0YXJ0WCwgc3RhcnRZLCB4MSwgeTEsIHgsIHkpOwogICAgICAgICAgVXRpbC5iZXppZXJCb3VuZGluZ0JveChzdGFydFgsIHN0YXJ0WSwgc3RhcnRYLCBzdGFydFksIHgxLCB5MSwgeCwgeSwgbWluTWF4KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgY2FzZSBPUFMuY3VydmVUbzM6CiAgICAgICAgewogICAgICAgICAgY29uc3Qgc3RhcnRYID0gc3RhdGUuY3VycmVudFBvaW50WDsKICAgICAgICAgIGNvbnN0IHN0YXJ0WSA9IHN0YXRlLmN1cnJlbnRQb2ludFk7CiAgICAgICAgICBjb25zdCBbeDEsIHkxLCB4LCB5XSA9IGFyZ3M7CiAgICAgICAgICBzdGF0ZS5jdXJyZW50UG9pbnRYID0geDsKICAgICAgICAgIHN0YXRlLmN1cnJlbnRQb2ludFkgPSB5OwogICAgICAgICAgcGF0aEJ1ZmZlci5wdXNoKERyYXdPUFMuY3VydmVUbywgeDEsIHkxLCB4LCB5LCB4LCB5KTsKICAgICAgICAgIFV0aWwuYmV6aWVyQm91bmRpbmdCb3goc3RhcnRYLCBzdGFydFksIHgxLCB5MSwgeCwgeSwgeCwgeSwgbWluTWF4KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgY2FzZSBPUFMuY2xvc2VQYXRoOgogICAgICAgIHBhdGhCdWZmZXIucHVzaChEcmF3T1BTLmNsb3NlUGF0aCk7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfQogIF9nZXRDb2xvclNwYWNlKGNzLCByZXNvdXJjZXMsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKSB7CiAgICByZXR1cm4gQ29sb3JTcGFjZVV0aWxzLnBhcnNlKHsKICAgICAgY3MsCiAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgcmVzb3VyY2VzLAogICAgICBwZGZGdW5jdGlvbkZhY3Rvcnk6IHRoaXMuX3BkZkZ1bmN0aW9uRmFjdG9yeSwKICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOiB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUsCiAgICAgIGFzeW5jSWZOb3RDYWNoZWQ6IHRydWUKICAgIH0pOwogIH0KICBhc3luYyBfaGFuZGxlQ29sb3JTcGFjZShjc1Byb21pc2UpIHsKICAgIHRyeSB7CiAgICAgIHJldHVybiBhd2FpdCBjc1Byb21pc2U7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgd2FybihgX2hhbmRsZUNvbG9yU3BhY2UgLSBpZ25vcmluZyBDb2xvclNwYWNlOiAiJHtleH0iLmApOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHRocm93IGV4OwogICAgfQogIH0KICBwYXJzZVNoYWRpbmcoewogICAgc2hhZGluZywKICAgIHJlc291cmNlcywKICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlLAogICAgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlCiAgfSkgewogICAgbGV0IGlkID0gbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlLmdldChzaGFkaW5nKTsKICAgIGlmIChpZCkgewogICAgICByZXR1cm4gaWQ7CiAgICB9CiAgICBsZXQgcGF0dGVybklSOwogICAgdHJ5IHsKICAgICAgY29uc3Qgc2hhZGluZ0ZpbGwgPSBQYXR0ZXJuLnBhcnNlU2hhZGluZyhzaGFkaW5nLCB0aGlzLnhyZWYsIHJlc291cmNlcywgdGhpcy5fcGRmRnVuY3Rpb25GYWN0b3J5LCB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSwgbG9jYWxDb2xvclNwYWNlQ2FjaGUpOwogICAgICBwYXR0ZXJuSVIgPSBzaGFkaW5nRmlsbC5nZXRJUigpOwogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgd2FybihgcGFyc2VTaGFkaW5nIC0gaWdub3Jpbmcgc2hhZGluZzogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlLnNldChzaGFkaW5nLCBudWxsKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICB0aHJvdyByZWFzb247CiAgICB9CiAgICBpZCA9IGBwYXR0ZXJuXyR7dGhpcy5pZEZhY3RvcnkuY3JlYXRlT2JqSWQoKX1gOwogICAgaWYgKHRoaXMucGFyc2luZ1R5cGUzRm9udCkgewogICAgICBpZCA9IGAke3RoaXMuaWRGYWN0b3J5LmdldERvY0lkKCl9X3R5cGUzXyR7aWR9YDsKICAgIH0KICAgIGxvY2FsU2hhZGluZ1BhdHRlcm5DYWNoZS5zZXQoc2hhZGluZywgaWQpOwogICAgaWYgKHRoaXMucGFyc2luZ1R5cGUzRm9udCkgewogICAgICBjb25zdCB0cmFuc2ZlcnMgPSBbXTsKICAgICAgY29uc3QgcGF0dGVybkJ1ZmZlciA9IFBhdHRlcm5JbmZvLndyaXRlKHBhdHRlcm5JUik7CiAgICAgIHRyYW5zZmVycy5wdXNoKHBhdHRlcm5CdWZmZXIpOwogICAgICB0aGlzLmhhbmRsZXIuc2VuZCgiY29tbW9ub2JqIiwgW2lkLCAiUGF0dGVybiIsIHBhdHRlcm5CdWZmZXJdLCB0cmFuc2ZlcnMpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5oYW5kbGVyLnNlbmQoIm9iaiIsIFtpZCwgdGhpcy5wYWdlSW5kZXgsICJQYXR0ZXJuIiwgcGF0dGVybklSXSk7CiAgICB9CiAgICByZXR1cm4gaWQ7CiAgfQogIGhhbmRsZUNvbG9yTihvcGVyYXRvckxpc3QsIGZuLCBhcmdzLCBjcywgcGF0dGVybnMsIHJlc291cmNlcywgdGFzaywgbG9jYWxDb2xvclNwYWNlQ2FjaGUsIGxvY2FsVGlsaW5nUGF0dGVybkNhY2hlLCBsb2NhbFNoYWRpbmdQYXR0ZXJuQ2FjaGUpIHsKICAgIGNvbnN0IHBhdHRlcm5OYW1lID0gYXJncy5wb3AoKTsKICAgIGlmIChwYXR0ZXJuTmFtZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgY29uc3QgcmF3UGF0dGVybiA9IHBhdHRlcm5zLmdldFJhdyhwYXR0ZXJuTmFtZS5uYW1lKTsKICAgICAgY29uc3QgbG9jYWxUaWxpbmdQYXR0ZXJuID0gcmF3UGF0dGVybiBpbnN0YW5jZW9mIFJlZiAmJiBsb2NhbFRpbGluZ1BhdHRlcm5DYWNoZS5nZXRCeVJlZihyYXdQYXR0ZXJuKTsKICAgICAgaWYgKGxvY2FsVGlsaW5nUGF0dGVybikgewogICAgICAgIHRyeSB7CiAgICAgICAgICBjb25zdCBjb2xvciA9IGNzLmJhc2UgPyBjcy5iYXNlLmdldFJnYkhleChhcmdzLCAwKSA6IG51bGw7CiAgICAgICAgICBjb25zdCB0aWxpbmdQYXR0ZXJuSVIgPSBnZXRUaWxpbmdQYXR0ZXJuSVIobG9jYWxUaWxpbmdQYXR0ZXJuLm9wZXJhdG9yTGlzdElSLCBsb2NhbFRpbGluZ1BhdHRlcm4uZGljdCwgY29sb3IpOwogICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKGZuLCB0aWxpbmdQYXR0ZXJuSVIpOwogICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgICAgICB9IGNhdGNoIHt9CiAgICAgIH0KICAgICAgY29uc3QgcGF0dGVybiA9IHRoaXMueHJlZi5mZXRjaElmUmVmKHJhd1BhdHRlcm4pOwogICAgICBpZiAocGF0dGVybikgewogICAgICAgIGNvbnN0IGRpY3QgPSBwYXR0ZXJuIGluc3RhbmNlb2YgQmFzZVN0cmVhbSA/IHBhdHRlcm4uZGljdCA6IHBhdHRlcm47CiAgICAgICAgY29uc3QgdHlwZU51bSA9IGRpY3QuZ2V0KCJQYXR0ZXJuVHlwZSIpOwogICAgICAgIGlmICh0eXBlTnVtID09PSBQYXR0ZXJuVHlwZS5USUxJTkcpIHsKICAgICAgICAgIGNvbnN0IGNvbG9yID0gY3MuYmFzZSA/IGNzLmJhc2UuZ2V0UmdiSGV4KGFyZ3MsIDApIDogbnVsbDsKICAgICAgICAgIHJldHVybiB0aGlzLmhhbmRsZVRpbGluZ1R5cGUoZm4sIGNvbG9yLCByZXNvdXJjZXMsIHBhdHRlcm4sIGRpY3QsIG9wZXJhdG9yTGlzdCwgdGFzaywgbG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUpOwogICAgICAgIH0gZWxzZSBpZiAodHlwZU51bSA9PT0gUGF0dGVyblR5cGUuU0hBRElORykgewogICAgICAgICAgY29uc3Qgc2hhZGluZyA9IGRpY3QuZ2V0KCJTaGFkaW5nIik7CiAgICAgICAgICBjb25zdCBvYmpJZCA9IHRoaXMucGFyc2VTaGFkaW5nKHsKICAgICAgICAgICAgc2hhZGluZywKICAgICAgICAgICAgcmVzb3VyY2VzLAogICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgICAgICAgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlCiAgICAgICAgICB9KTsKICAgICAgICAgIGlmIChvYmpJZCkgewogICAgICAgICAgICBjb25zdCBtYXRyaXggPSBsb29rdXBNYXRyaXgoZGljdC5nZXRBcnJheSgiTWF0cml4IiksIG51bGwpOwogICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoZm4sIFsiU2hhZGluZyIsIG9iaklkLCBtYXRyaXhdKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICAgICAgfQogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgVW5rbm93biBQYXR0ZXJuVHlwZTogJHt0eXBlTnVtfWApOwogICAgICB9CiAgICB9CiAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVua25vd24gUGF0dGVybk5hbWU6ICR7cGF0dGVybk5hbWV9YCk7CiAgfQogIF9wYXJzZVZpc2liaWxpdHlFeHByZXNzaW9uKGFycmF5LCBuZXN0aW5nQ291bnRlciwgY3VycmVudFJlc3VsdCkgewogICAgY29uc3QgTUFYX05FU1RJTkcgPSAxMDsKICAgIGlmICgrK25lc3RpbmdDb3VudGVyID4gTUFYX05FU1RJTkcpIHsKICAgICAgd2FybigiVmlzaWJpbGl0eSBleHByZXNzaW9uIGlzIHRvbyBkZWVwbHkgbmVzdGVkIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IGFycmF5Lmxlbmd0aDsKICAgIGNvbnN0IG9wZXJhdG9yID0gdGhpcy54cmVmLmZldGNoSWZSZWYoYXJyYXlbMF0pOwogICAgaWYgKGxlbmd0aCA8IDIgfHwgIShvcGVyYXRvciBpbnN0YW5jZW9mIE5hbWUpKSB7CiAgICAgIHdhcm4oIkludmFsaWQgdmlzaWJpbGl0eSBleHByZXNzaW9uIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHN3aXRjaCAob3BlcmF0b3IubmFtZSkgewogICAgICBjYXNlICJBbmQiOgogICAgICBjYXNlICJPciI6CiAgICAgIGNhc2UgIk5vdCI6CiAgICAgICAgY3VycmVudFJlc3VsdC5wdXNoKG9wZXJhdG9yLm5hbWUpOwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHdhcm4oYEludmFsaWQgb3BlcmF0b3IgJHtvcGVyYXRvci5uYW1lfSBpbiB2aXNpYmlsaXR5IGV4cHJlc3Npb25gKTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGxldCBpID0gMTsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIGNvbnN0IHJhdyA9IGFycmF5W2ldOwogICAgICBjb25zdCBvYmplY3QgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihyYXcpOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShvYmplY3QpKSB7CiAgICAgICAgY29uc3QgbmVzdGVkUmVzdWx0ID0gW107CiAgICAgICAgY3VycmVudFJlc3VsdC5wdXNoKG5lc3RlZFJlc3VsdCk7CiAgICAgICAgdGhpcy5fcGFyc2VWaXNpYmlsaXR5RXhwcmVzc2lvbihvYmplY3QsIG5lc3RpbmdDb3VudGVyLCBuZXN0ZWRSZXN1bHQpOwogICAgICB9IGVsc2UgaWYgKHJhdyBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIGN1cnJlbnRSZXN1bHQucHVzaChyYXcudG9TdHJpbmcoKSk7CiAgICAgIH0KICAgIH0KICB9CiAgYXN5bmMgcGFyc2VNYXJrZWRDb250ZW50UHJvcHMoY29udGVudFByb3BlcnRpZXMsIHJlc291cmNlcykgewogICAgbGV0IG9wdGlvbmFsQ29udGVudDsKICAgIGlmIChjb250ZW50UHJvcGVydGllcyBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgY29uc3QgcHJvcGVydGllcyA9IHJlc291cmNlcy5nZXQoIlByb3BlcnRpZXMiKTsKICAgICAgb3B0aW9uYWxDb250ZW50ID0gcHJvcGVydGllcy5nZXQoY29udGVudFByb3BlcnRpZXMubmFtZSk7CiAgICB9IGVsc2UgaWYgKGNvbnRlbnRQcm9wZXJ0aWVzIGluc3RhbmNlb2YgRGljdCkgewogICAgICBvcHRpb25hbENvbnRlbnQgPSBjb250ZW50UHJvcGVydGllczsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiT3B0aW9uYWwgY29udGVudCBwcm9wZXJ0aWVzIG1hbGZvcm1lZC4iKTsKICAgIH0KICAgIGNvbnN0IG9wdGlvbmFsQ29udGVudFR5cGUgPSBvcHRpb25hbENvbnRlbnQuZ2V0KCJUeXBlIik/Lm5hbWU7CiAgICBpZiAob3B0aW9uYWxDb250ZW50VHlwZSA9PT0gIk9DRyIpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICB0eXBlOiBvcHRpb25hbENvbnRlbnRUeXBlLAogICAgICAgIGlkOiBvcHRpb25hbENvbnRlbnQub2JqSWQKICAgICAgfTsKICAgIH0gZWxzZSBpZiAob3B0aW9uYWxDb250ZW50VHlwZSA9PT0gIk9DTUQiKSB7CiAgICAgIGNvbnN0IGV4cHJlc3Npb24gPSBvcHRpb25hbENvbnRlbnQuZ2V0KCJWRSIpOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShleHByZXNzaW9uKSkgewogICAgICAgIGNvbnN0IHJlc3VsdCA9IFtdOwogICAgICAgIHRoaXMuX3BhcnNlVmlzaWJpbGl0eUV4cHJlc3Npb24oZXhwcmVzc2lvbiwgMCwgcmVzdWx0KTsKICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCA+IDApIHsKICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIHR5cGU6ICJPQ01EIiwKICAgICAgICAgICAgZXhwcmVzc2lvbjogcmVzdWx0CiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBvcHRpb25hbENvbnRlbnRHcm91cHMgPSBvcHRpb25hbENvbnRlbnQuZ2V0KCJPQ0dzIik7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KG9wdGlvbmFsQ29udGVudEdyb3VwcykgfHwgb3B0aW9uYWxDb250ZW50R3JvdXBzIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIGNvbnN0IGdyb3VwSWRzID0gW107CiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9uYWxDb250ZW50R3JvdXBzKSkgewogICAgICAgICAgZm9yIChjb25zdCBvY2cgb2Ygb3B0aW9uYWxDb250ZW50R3JvdXBzKSB7CiAgICAgICAgICAgIGdyb3VwSWRzLnB1c2gob2NnLnRvU3RyaW5nKCkpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBncm91cElkcy5wdXNoKG9wdGlvbmFsQ29udGVudEdyb3Vwcy5vYmpJZCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiBvcHRpb25hbENvbnRlbnRUeXBlLAogICAgICAgICAgaWRzOiBncm91cElkcywKICAgICAgICAgIHBvbGljeTogb3B0aW9uYWxDb250ZW50LmdldCgiUCIpIGluc3RhbmNlb2YgTmFtZSA/IG9wdGlvbmFsQ29udGVudC5nZXQoIlAiKS5uYW1lIDogbnVsbCwKICAgICAgICAgIGV4cHJlc3Npb246IG51bGwKICAgICAgICB9OwogICAgICB9IGVsc2UgaWYgKG9wdGlvbmFsQ29udGVudEdyb3VwcyBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiBvcHRpb25hbENvbnRlbnRUeXBlLAogICAgICAgICAgaWQ6IG9wdGlvbmFsQ29udGVudEdyb3Vwcy50b1N0cmluZygpCiAgICAgICAgfTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogIGFzeW5jIGdldE9wZXJhdG9yTGlzdCh7CiAgICBzdHJlYW0sCiAgICB0YXNrLAogICAgcmVzb3VyY2VzLAogICAgb3BlcmF0b3JMaXN0LAogICAgaW5pdGlhbFN0YXRlID0gbnVsbCwKICAgIGZhbGxiYWNrRm9udERpY3QgPSBudWxsLAogICAgcHJldlJlZnMgPSBudWxsCiAgfSkgewogICAgaWYgKHN0cmVhbS5pc0FzeW5jKSB7CiAgICAgIGNvbnN0IGJ5dGVzID0gYXdhaXQgc3RyZWFtLmFzeW5jR2V0Qnl0ZXMoKTsKICAgICAgaWYgKGJ5dGVzKSB7CiAgICAgICAgc3RyZWFtID0gbmV3IFN0cmVhbShieXRlcywgMCwgYnl0ZXMubGVuZ3RoLCBzdHJlYW0uZGljdCk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IG9iaklkID0gc3RyZWFtLmRpY3Q/Lm9iaklkOwogICAgY29uc3Qgc2VlblJlZnMgPSBuZXcgUmVmU2V0KHByZXZSZWZzKTsKICAgIGlmIChvYmpJZCkgewogICAgICBpZiAocHJldlJlZnM/LmhhcyhvYmpJZCkpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGdldE9wZXJhdG9yTGlzdCAtIGlnbm9yaW5nIGNpcmN1bGFyIHJlZmVyZW5jZTogJHtvYmpJZH1gKTsKICAgICAgfQogICAgICBzZWVuUmVmcy5wdXQob2JqSWQpOwogICAgfQogICAgcmVzb3VyY2VzIHx8PSBEaWN0LmVtcHR5OwogICAgaW5pdGlhbFN0YXRlIHx8PSBuZXcgRXZhbFN0YXRlKCk7CiAgICBpZiAoIW9wZXJhdG9yTGlzdCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dldE9wZXJhdG9yTGlzdDogbWlzc2luZyAib3BlcmF0b3JMaXN0IiBwYXJhbWV0ZXInKTsKICAgIH0KICAgIGNvbnN0IHNlbGYgPSB0aGlzOwogICAgY29uc3QgeHJlZiA9IHRoaXMueHJlZjsKICAgIGNvbnN0IGxvY2FsSW1hZ2VDYWNoZSA9IG5ldyBMb2NhbEltYWdlQ2FjaGUoKTsKICAgIGNvbnN0IGxvY2FsQ29sb3JTcGFjZUNhY2hlID0gbmV3IExvY2FsQ29sb3JTcGFjZUNhY2hlKCk7CiAgICBjb25zdCBsb2NhbEdTdGF0ZUNhY2hlID0gbmV3IExvY2FsR1N0YXRlQ2FjaGUoKTsKICAgIGNvbnN0IGxvY2FsVGlsaW5nUGF0dGVybkNhY2hlID0gbmV3IExvY2FsVGlsaW5nUGF0dGVybkNhY2hlKCk7CiAgICBjb25zdCBsb2NhbFNoYWRpbmdQYXR0ZXJuQ2FjaGUgPSBuZXcgTWFwKCk7CiAgICBjb25zdCB4b2JqcyA9IHJlc291cmNlcy5nZXQoIlhPYmplY3QiKSB8fCBEaWN0LmVtcHR5OwogICAgY29uc3QgcGF0dGVybnMgPSByZXNvdXJjZXMuZ2V0KCJQYXR0ZXJuIikgfHwgRGljdC5lbXB0eTsKICAgIGNvbnN0IHN0YXRlTWFuYWdlciA9IG5ldyBTdGF0ZU1hbmFnZXIoaW5pdGlhbFN0YXRlKTsKICAgIGNvbnN0IHByZXByb2Nlc3NvciA9IG5ldyBFdmFsdWF0b3JQcmVwcm9jZXNzb3Ioc3RyZWFtLCB4cmVmLCBzdGF0ZU1hbmFnZXIpOwogICAgY29uc3QgdGltZVNsb3RNYW5hZ2VyID0gbmV3IFRpbWVTbG90TWFuYWdlcigpOwogICAgZnVuY3Rpb24gY2xvc2VQZW5kaW5nUmVzdG9yZU9QUyhhcmd1bWVudCkgewogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBwcmVwcm9jZXNzb3Iuc2F2ZWRTdGF0ZXNEZXB0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoT1BTLnJlc3RvcmUsIFtdKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIHByb21pc2VCb2R5KHJlc29sdmUsIHJlamVjdCkgewogICAgICBjb25zdCBuZXh0ID0gZnVuY3Rpb24gKHByb21pc2UpIHsKICAgICAgICBQcm9taXNlLmFsbChbcHJvbWlzZSwgb3BlcmF0b3JMaXN0LnJlYWR5XSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBwcm9taXNlQm9keShyZXNvbHZlLCByZWplY3QpOwogICAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgICAgcmVqZWN0KGV4KTsKICAgICAgICAgIH0KICAgICAgICB9LCByZWplY3QpOwogICAgICB9OwogICAgICB0YXNrLmVuc3VyZU5vdFRlcm1pbmF0ZWQoKTsKICAgICAgdGltZVNsb3RNYW5hZ2VyLnJlc2V0KCk7CiAgICAgIGNvbnN0IG9wZXJhdGlvbiA9IHt9OwogICAgICBsZXQgc3RvcCwgaSwgaWksIGNzLCBuYW1lLCBpc1ZhbGlkTmFtZTsKICAgICAgd2hpbGUgKCEoc3RvcCA9IHRpbWVTbG90TWFuYWdlci5jaGVjaygpKSkgewogICAgICAgIG9wZXJhdGlvbi5hcmdzID0gbnVsbDsKICAgICAgICBpZiAoIXByZXByb2Nlc3Nvci5yZWFkKG9wZXJhdGlvbikpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBsZXQgYXJncyA9IG9wZXJhdGlvbi5hcmdzOwogICAgICAgIGxldCBmbiA9IG9wZXJhdGlvbi5mbjsKICAgICAgICBzd2l0Y2ggKGZuIHwgMCkgewogICAgICAgICAgY2FzZSBPUFMucGFpbnRYT2JqZWN0OgogICAgICAgICAgICBpc1ZhbGlkTmFtZSA9IGFyZ3NbMF0gaW5zdGFuY2VvZiBOYW1lOwogICAgICAgICAgICBuYW1lID0gYXJnc1swXS5uYW1lOwogICAgICAgICAgICBpZiAoaXNWYWxpZE5hbWUpIHsKICAgICAgICAgICAgICBjb25zdCBsb2NhbEltYWdlID0gbG9jYWxJbWFnZUNhY2hlLmdldEJ5TmFtZShuYW1lKTsKICAgICAgICAgICAgICBpZiAobG9jYWxJbWFnZSkgewogICAgICAgICAgICAgICAgYWRkQ2FjaGVkSW1hZ2VPcHMob3BlcmF0b3JMaXN0LCBsb2NhbEltYWdlKTsKICAgICAgICAgICAgICAgIGFyZ3MgPSBudWxsOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIG5leHQobmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmVYT2JqZWN0LCByZWplY3RYT2JqZWN0KSB7CiAgICAgICAgICAgICAgaWYgKCFpc1ZhbGlkTmFtZSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJYT2JqZWN0IG11c3QgYmUgcmVmZXJyZWQgdG8gYnkgbmFtZS4iKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgbGV0IHhvYmogPSB4b2Jqcy5nZXRSYXcobmFtZSk7CiAgICAgICAgICAgICAgaWYgKHhvYmogaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgICAgICAgIGNvbnN0IGNhY2hlZEltYWdlID0gbG9jYWxJbWFnZUNhY2hlLmdldEJ5UmVmKHhvYmopIHx8IHNlbGYuX3JlZ2lvbmFsSW1hZ2VDYWNoZS5nZXRCeVJlZih4b2JqKSB8fCBzZWxmLmdsb2JhbEltYWdlQ2FjaGUuZ2V0RGF0YSh4b2JqLCBzZWxmLnBhZ2VJbmRleCk7CiAgICAgICAgICAgICAgICBpZiAoY2FjaGVkSW1hZ2UpIHsKICAgICAgICAgICAgICAgICAgYWRkQ2FjaGVkSW1hZ2VPcHMob3BlcmF0b3JMaXN0LCBjYWNoZWRJbWFnZSk7CiAgICAgICAgICAgICAgICAgIHJlc29sdmVYT2JqZWN0KCk7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHhvYmogPSB4cmVmLmZldGNoKHhvYmopOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoISh4b2JqIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiWE9iamVjdCBzaG91bGQgYmUgYSBzdHJlYW0iKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgdHlwZSA9IHhvYmouZGljdC5nZXQoIlN1YnR5cGUiKTsKICAgICAgICAgICAgICBpZiAoISh0eXBlIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiWE9iamVjdCBzaG91bGQgaGF2ZSBhIE5hbWUgc3VidHlwZSIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAodHlwZS5uYW1lID09PSAiRm9ybSIpIHsKICAgICAgICAgICAgICAgIHN0YXRlTWFuYWdlci5zYXZlKCk7CiAgICAgICAgICAgICAgICBzZWxmLmJ1aWxkRm9ybVhPYmplY3QocmVzb3VyY2VzLCB4b2JqLCBudWxsLCBvcGVyYXRvckxpc3QsIHRhc2ssIHN0YXRlTWFuYWdlci5zdGF0ZS5jbG9uZSh7CiAgICAgICAgICAgICAgICAgIG5ld1BhdGg6IHRydWUKICAgICAgICAgICAgICAgIH0pLCBsb2NhbENvbG9yU3BhY2VDYWNoZSwgc2VlblJlZnMpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICBzdGF0ZU1hbmFnZXIucmVzdG9yZSgpOwogICAgICAgICAgICAgICAgICByZXNvbHZlWE9iamVjdCgpOwogICAgICAgICAgICAgICAgfSwgcmVqZWN0WE9iamVjdCk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlLm5hbWUgPT09ICJJbWFnZSIpIHsKICAgICAgICAgICAgICAgIHNlbGYuYnVpbGRQYWludEltYWdlWE9iamVjdCh7CiAgICAgICAgICAgICAgICAgIHJlc291cmNlcywKICAgICAgICAgICAgICAgICAgaW1hZ2U6IHhvYmosCiAgICAgICAgICAgICAgICAgIG9wZXJhdG9yTGlzdCwKICAgICAgICAgICAgICAgICAgY2FjaGVLZXk6IG5hbWUsCiAgICAgICAgICAgICAgICAgIGxvY2FsSW1hZ2VDYWNoZSwKICAgICAgICAgICAgICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgICAgICAgICAgICAgIH0pLnRoZW4ocmVzb2x2ZVhPYmplY3QsIHJlamVjdFhPYmplY3QpOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZS5uYW1lID09PSAiUFMiKSB7CiAgICAgICAgICAgICAgICBpbmZvKCJJZ25vcmVkIFhPYmplY3Qgc3VidHlwZSBQUyIpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVuaGFuZGxlZCBYT2JqZWN0IHN1YnR5cGUgJHt0eXBlLm5hbWV9YCk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJlc29sdmVYT2JqZWN0KCk7CiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24pIHsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHNlbGYub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgICAgICAgIHdhcm4oYGdldE9wZXJhdG9yTGlzdCAtIGlnbm9yaW5nIFhPYmplY3Q6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0aHJvdyByZWFzb247CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgY2FzZSBPUFMuc2V0Rm9udDoKICAgICAgICAgICAgY29uc3QgZm9udFNpemUgPSBhcmdzWzFdOwogICAgICAgICAgICBuZXh0KHNlbGYuaGFuZGxlU2V0Rm9udChyZXNvdXJjZXMsIGFyZ3MsIG51bGwsIG9wZXJhdG9yTGlzdCwgdGFzaywgc3RhdGVNYW5hZ2VyLnN0YXRlLCBmYWxsYmFja0ZvbnREaWN0KS50aGVuKGZ1bmN0aW9uIChsb2FkZWROYW1lKSB7CiAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZERlcGVuZGVuY3kobG9hZGVkTmFtZSk7CiAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5zZXRGb250LCBbbG9hZGVkTmFtZSwgZm9udFNpemVdKTsKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICBjYXNlIE9QUy5lbmRJbmxpbmVJbWFnZToKICAgICAgICAgICAgY29uc3QgY2FjaGVLZXkgPSBhcmdzWzBdLmNhY2hlS2V5OwogICAgICAgICAgICBpZiAoY2FjaGVLZXkpIHsKICAgICAgICAgICAgICBjb25zdCBsb2NhbEltYWdlID0gbG9jYWxJbWFnZUNhY2hlLmdldEJ5TmFtZShjYWNoZUtleSk7CiAgICAgICAgICAgICAgaWYgKGxvY2FsSW1hZ2UpIHsKICAgICAgICAgICAgICAgIGFkZENhY2hlZEltYWdlT3BzKG9wZXJhdG9yTGlzdCwgbG9jYWxJbWFnZSk7CiAgICAgICAgICAgICAgICBhcmdzID0gbnVsbDsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBuZXh0KHNlbGYuYnVpbGRQYWludEltYWdlWE9iamVjdCh7CiAgICAgICAgICAgICAgcmVzb3VyY2VzLAogICAgICAgICAgICAgIGltYWdlOiBhcmdzWzBdLAogICAgICAgICAgICAgIGlzSW5saW5lOiB0cnVlLAogICAgICAgICAgICAgIG9wZXJhdG9yTGlzdCwKICAgICAgICAgICAgICBjYWNoZUtleSwKICAgICAgICAgICAgICBsb2NhbEltYWdlQ2FjaGUsCiAgICAgICAgICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICBjYXNlIE9QUy5zaG93VGV4dDoKICAgICAgICAgICAgaWYgKCFzdGF0ZU1hbmFnZXIuc3RhdGUuZm9udCkgewogICAgICAgICAgICAgIHNlbGYuZW5zdXJlU3RhdGVGb250KHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYXJnc1swXSA9IHNlbGYuaGFuZGxlVGV4dChhcmdzWzBdLCBzdGF0ZU1hbmFnZXIuc3RhdGUpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNob3dTcGFjZWRUZXh0OgogICAgICAgICAgICBpZiAoIXN0YXRlTWFuYWdlci5zdGF0ZS5mb250KSB7CiAgICAgICAgICAgICAgc2VsZi5lbnN1cmVTdGF0ZUZvbnQoc3RhdGVNYW5hZ2VyLnN0YXRlKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBjb21iaW5lZEdseXBocyA9IFtdLAogICAgICAgICAgICAgIHN0YXRlID0gc3RhdGVNYW5hZ2VyLnN0YXRlOwogICAgICAgICAgICBmb3IgKGNvbnN0IGFyckl0ZW0gb2YgYXJnc1swXSkgewogICAgICAgICAgICAgIGlmICh0eXBlb2YgYXJySXRlbSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICAgIGNvbWJpbmVkR2x5cGhzLnB1c2goLi4uc2VsZi5oYW5kbGVUZXh0KGFyckl0ZW0sIHN0YXRlKSk7CiAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYXJySXRlbSA9PT0gIm51bWJlciIpIHsKICAgICAgICAgICAgICAgIGNvbWJpbmVkR2x5cGhzLnB1c2goYXJySXRlbSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGFyZ3NbMF0gPSBjb21iaW5lZEdseXBoczsKICAgICAgICAgICAgZm4gPSBPUFMuc2hvd1RleHQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMubmV4dExpbmVTaG93VGV4dDoKICAgICAgICAgICAgaWYgKCFzdGF0ZU1hbmFnZXIuc3RhdGUuZm9udCkgewogICAgICAgICAgICAgIHNlbGYuZW5zdXJlU3RhdGVGb250KHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5uZXh0TGluZSk7CiAgICAgICAgICAgIGFyZ3NbMF0gPSBzZWxmLmhhbmRsZVRleHQoYXJnc1swXSwgc3RhdGVNYW5hZ2VyLnN0YXRlKTsKICAgICAgICAgICAgZm4gPSBPUFMuc2hvd1RleHQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMubmV4dExpbmVTZXRTcGFjaW5nU2hvd1RleHQ6CiAgICAgICAgICAgIGlmICghc3RhdGVNYW5hZ2VyLnN0YXRlLmZvbnQpIHsKICAgICAgICAgICAgICBzZWxmLmVuc3VyZVN0YXRlRm9udChzdGF0ZU1hbmFnZXIuc3RhdGUpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChPUFMubmV4dExpbmUpOwogICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoT1BTLnNldFdvcmRTcGFjaW5nLCBbYXJncy5zaGlmdCgpXSk7CiAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChPUFMuc2V0Q2hhclNwYWNpbmcsIFthcmdzLnNoaWZ0KCldKTsKICAgICAgICAgICAgYXJnc1swXSA9IHNlbGYuaGFuZGxlVGV4dChhcmdzWzBdLCBzdGF0ZU1hbmFnZXIuc3RhdGUpOwogICAgICAgICAgICBmbiA9IE9QUy5zaG93VGV4dDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRUZXh0UmVuZGVyaW5nTW9kZToKICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnN0YXRlLnRleHRSZW5kZXJpbmdNb2RlID0gYXJnc1swXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGaWxsQ29sb3JTcGFjZToKICAgICAgICAgICAgewogICAgICAgICAgICAgIGNvbnN0IGZpbGxDUyA9IHNlbGYuX2dldENvbG9yU3BhY2UoYXJnc1swXSwgcmVzb3VyY2VzLCBsb2NhbENvbG9yU3BhY2VDYWNoZSk7CiAgICAgICAgICAgICAgaWYgKGZpbGxDUyBpbnN0YW5jZW9mIENvbG9yU3BhY2UpIHsKICAgICAgICAgICAgICAgIHN0YXRlTWFuYWdlci5zdGF0ZS5maWxsQ29sb3JTcGFjZSA9IGZpbGxDUzsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBuZXh0KHNlbGYuX2hhbmRsZUNvbG9yU3BhY2UoZmlsbENTKS50aGVuKGNvbG9yU3BhY2UgPT4gewogICAgICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnN0YXRlLmZpbGxDb2xvclNwYWNlID0gY29sb3JTcGFjZSB8fCBDb2xvclNwYWNlVXRpbHMuZ3JheTsKICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICBjYXNlIE9QUy5zZXRTdHJva2VDb2xvclNwYWNlOgogICAgICAgICAgICB7CiAgICAgICAgICAgICAgY29uc3Qgc3Ryb2tlQ1MgPSBzZWxmLl9nZXRDb2xvclNwYWNlKGFyZ3NbMF0sIHJlc291cmNlcywgbG9jYWxDb2xvclNwYWNlQ2FjaGUpOwogICAgICAgICAgICAgIGlmIChzdHJva2VDUyBpbnN0YW5jZW9mIENvbG9yU3BhY2UpIHsKICAgICAgICAgICAgICAgIHN0YXRlTWFuYWdlci5zdGF0ZS5zdHJva2VDb2xvclNwYWNlID0gc3Ryb2tlQ1M7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgbmV4dChzZWxmLl9oYW5kbGVDb2xvclNwYWNlKHN0cm9rZUNTKS50aGVuKGNvbG9yU3BhY2UgPT4gewogICAgICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnN0YXRlLnN0cm9rZUNvbG9yU3BhY2UgPSBjb2xvclNwYWNlIHx8IENvbG9yU3BhY2VVdGlscy5ncmF5OwogICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT1BTLnNldEZpbGxDb2xvcjoKICAgICAgICAgICAgY3MgPSBzdGF0ZU1hbmFnZXIuc3RhdGUuZmlsbENvbG9yU3BhY2U7CiAgICAgICAgICAgIGFyZ3MgPSBbY3MuZ2V0UmdiSGV4KGFyZ3MsIDApXTsKICAgICAgICAgICAgZm4gPSBPUFMuc2V0RmlsbFJHQkNvbG9yOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldFN0cm9rZUNvbG9yOgogICAgICAgICAgICBjcyA9IHN0YXRlTWFuYWdlci5zdGF0ZS5zdHJva2VDb2xvclNwYWNlOwogICAgICAgICAgICBhcmdzID0gW2NzLmdldFJnYkhleChhcmdzLCAwKV07CiAgICAgICAgICAgIGZuID0gT1BTLnNldFN0cm9rZVJHQkNvbG9yOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldEZpbGxHcmF5OgogICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuZmlsbENvbG9yU3BhY2UgPSBDb2xvclNwYWNlVXRpbHMuZ3JheTsKICAgICAgICAgICAgYXJncyA9IFtDb2xvclNwYWNlVXRpbHMuZ3JheS5nZXRSZ2JIZXgoYXJncywgMCldOwogICAgICAgICAgICBmbiA9IE9QUy5zZXRGaWxsUkdCQ29sb3I7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0U3Ryb2tlR3JheToKICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnN0YXRlLnN0cm9rZUNvbG9yU3BhY2UgPSBDb2xvclNwYWNlVXRpbHMuZ3JheTsKICAgICAgICAgICAgYXJncyA9IFtDb2xvclNwYWNlVXRpbHMuZ3JheS5nZXRSZ2JIZXgoYXJncywgMCldOwogICAgICAgICAgICBmbiA9IE9QUy5zZXRTdHJva2VSR0JDb2xvcjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGaWxsQ01ZS0NvbG9yOgogICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuZmlsbENvbG9yU3BhY2UgPSBDb2xvclNwYWNlVXRpbHMuY215azsKICAgICAgICAgICAgYXJncyA9IFtDb2xvclNwYWNlVXRpbHMuY215ay5nZXRSZ2JIZXgoYXJncywgMCldOwogICAgICAgICAgICBmbiA9IE9QUy5zZXRGaWxsUkdCQ29sb3I7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0U3Ryb2tlQ01ZS0NvbG9yOgogICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuc3Ryb2tlQ29sb3JTcGFjZSA9IENvbG9yU3BhY2VVdGlscy5jbXlrOwogICAgICAgICAgICBhcmdzID0gW0NvbG9yU3BhY2VVdGlscy5jbXlrLmdldFJnYkhleChhcmdzLCAwKV07CiAgICAgICAgICAgIGZuID0gT1BTLnNldFN0cm9rZVJHQkNvbG9yOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldEZpbGxSR0JDb2xvcjoKICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnN0YXRlLmZpbGxDb2xvclNwYWNlID0gQ29sb3JTcGFjZVV0aWxzLnJnYjsKICAgICAgICAgICAgYXJncyA9IFtDb2xvclNwYWNlVXRpbHMucmdiLmdldFJnYkhleChhcmdzLCAwKV07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0U3Ryb2tlUkdCQ29sb3I6CiAgICAgICAgICAgIHN0YXRlTWFuYWdlci5zdGF0ZS5zdHJva2VDb2xvclNwYWNlID0gQ29sb3JTcGFjZVV0aWxzLnJnYjsKICAgICAgICAgICAgYXJncyA9IFtDb2xvclNwYWNlVXRpbHMucmdiLmdldFJnYkhleChhcmdzLCAwKV07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0RmlsbENvbG9yTjoKICAgICAgICAgICAgY3MgPSBzdGF0ZU1hbmFnZXIuc3RhdGUucGF0dGVybkZpbGxDb2xvclNwYWNlOwogICAgICAgICAgICBpZiAoIWNzKSB7CiAgICAgICAgICAgICAgaWYgKGlzTnVtYmVyQXJyYXkoYXJncywgbnVsbCkpIHsKICAgICAgICAgICAgICAgIGFyZ3MgPSBbQ29sb3JTcGFjZVV0aWxzLmdyYXkuZ2V0UmdiSGV4KGFyZ3MsIDApXTsKICAgICAgICAgICAgICAgIGZuID0gT1BTLnNldEZpbGxSR0JDb2xvcjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBhcmdzID0gW107CiAgICAgICAgICAgICAgZm4gPSBPUFMuc2V0RmlsbFRyYW5zcGFyZW50OwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChjcy5uYW1lID09PSAiUGF0dGVybiIpIHsKICAgICAgICAgICAgICBuZXh0KHNlbGYuaGFuZGxlQ29sb3JOKG9wZXJhdG9yTGlzdCwgT1BTLnNldEZpbGxDb2xvck4sIGFyZ3MsIGNzLCBwYXR0ZXJucywgcmVzb3VyY2VzLCB0YXNrLCBsb2NhbENvbG9yU3BhY2VDYWNoZSwgbG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUsIGxvY2FsU2hhZGluZ1BhdHRlcm5DYWNoZSkpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBhcmdzID0gW2NzLmdldFJnYkhleChhcmdzLCAwKV07CiAgICAgICAgICAgIGZuID0gT1BTLnNldEZpbGxSR0JDb2xvcjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRTdHJva2VDb2xvck46CiAgICAgICAgICAgIGNzID0gc3RhdGVNYW5hZ2VyLnN0YXRlLnBhdHRlcm5TdHJva2VDb2xvclNwYWNlOwogICAgICAgICAgICBpZiAoIWNzKSB7CiAgICAgICAgICAgICAgaWYgKGlzTnVtYmVyQXJyYXkoYXJncywgbnVsbCkpIHsKICAgICAgICAgICAgICAgIGFyZ3MgPSBbQ29sb3JTcGFjZVV0aWxzLmdyYXkuZ2V0UmdiSGV4KGFyZ3MsIDApXTsKICAgICAgICAgICAgICAgIGZuID0gT1BTLnNldFN0cm9rZVJHQkNvbG9yOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGFyZ3MgPSBbXTsKICAgICAgICAgICAgICBmbiA9IE9QUy5zZXRTdHJva2VUcmFuc3BhcmVudDsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoY3MubmFtZSA9PT0gIlBhdHRlcm4iKSB7CiAgICAgICAgICAgICAgbmV4dChzZWxmLmhhbmRsZUNvbG9yTihvcGVyYXRvckxpc3QsIE9QUy5zZXRTdHJva2VDb2xvck4sIGFyZ3MsIGNzLCBwYXR0ZXJucywgcmVzb3VyY2VzLCB0YXNrLCBsb2NhbENvbG9yU3BhY2VDYWNoZSwgbG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUsIGxvY2FsU2hhZGluZ1BhdHRlcm5DYWNoZSkpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBhcmdzID0gW2NzLmdldFJnYkhleChhcmdzLCAwKV07CiAgICAgICAgICAgIGZuID0gT1BTLnNldFN0cm9rZVJHQkNvbG9yOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNoYWRpbmdGaWxsOgogICAgICAgICAgICBsZXQgc2hhZGluZzsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBjb25zdCBzaGFkaW5nUmVzID0gcmVzb3VyY2VzLmdldCgiU2hhZGluZyIpOwogICAgICAgICAgICAgIGlmICghc2hhZGluZ1JlcykgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJObyBzaGFkaW5nIHJlc291cmNlIGZvdW5kIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHNoYWRpbmcgPSBzaGFkaW5nUmVzLmdldChhcmdzWzBdLm5hbWUpOwogICAgICAgICAgICAgIGlmICghc2hhZGluZykgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJObyBzaGFkaW5nIG9iamVjdCBmb3VuZCIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgICAgICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIEFib3J0RXhjZXB0aW9uKSB7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHNlbGYub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgICAgICAgIHdhcm4oYGdldE9wZXJhdG9yTGlzdCAtIGlnbm9yaW5nIFNoYWRpbmc6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRocm93IHJlYXNvbjsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBwYXR0ZXJuSWQgPSBzZWxmLnBhcnNlU2hhZGluZyh7CiAgICAgICAgICAgICAgc2hhZGluZywKICAgICAgICAgICAgICByZXNvdXJjZXMsCiAgICAgICAgICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUsCiAgICAgICAgICAgICAgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBpZiAoIXBhdHRlcm5JZCkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGFyZ3MgPSBbcGF0dGVybklkXTsKICAgICAgICAgICAgZm4gPSBPUFMuc2hhZGluZ0ZpbGw7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0R1N0YXRlOgogICAgICAgICAgICBpc1ZhbGlkTmFtZSA9IGFyZ3NbMF0gaW5zdGFuY2VvZiBOYW1lOwogICAgICAgICAgICBuYW1lID0gYXJnc1swXS5uYW1lOwogICAgICAgICAgICBpZiAoaXNWYWxpZE5hbWUpIHsKICAgICAgICAgICAgICBjb25zdCBsb2NhbEdTdGF0ZU9iaiA9IGxvY2FsR1N0YXRlQ2FjaGUuZ2V0QnlOYW1lKG5hbWUpOwogICAgICAgICAgICAgIGlmIChsb2NhbEdTdGF0ZU9iaikgewogICAgICAgICAgICAgICAgaWYgKGxvY2FsR1N0YXRlT2JqLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5zZXRHU3RhdGUsIFtsb2NhbEdTdGF0ZU9ial0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYXJncyA9IG51bGw7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbmV4dChuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZUdTdGF0ZSwgcmVqZWN0R1N0YXRlKSB7CiAgICAgICAgICAgICAgaWYgKCFpc1ZhbGlkTmFtZSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJHU3RhdGUgbXVzdCBiZSByZWZlcnJlZCB0byBieSBuYW1lLiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCBleHRHU3RhdGUgPSByZXNvdXJjZXMuZ2V0KCJFeHRHU3RhdGUiKTsKICAgICAgICAgICAgICBpZiAoIShleHRHU3RhdGUgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJFeHRHU3RhdGUgc2hvdWxkIGJlIGEgZGljdGlvbmFyeS4iKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgZ1N0YXRlID0gZXh0R1N0YXRlLmdldChuYW1lKTsKICAgICAgICAgICAgICBpZiAoIShnU3RhdGUgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJHU3RhdGUgc2hvdWxkIGJlIGEgZGljdGlvbmFyeS4iKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgc2VsZi5zZXRHU3RhdGUoewogICAgICAgICAgICAgICAgcmVzb3VyY2VzLAogICAgICAgICAgICAgICAgZ1N0YXRlLAogICAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LAogICAgICAgICAgICAgICAgY2FjaGVLZXk6IG5hbWUsCiAgICAgICAgICAgICAgICB0YXNrLAogICAgICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLAogICAgICAgICAgICAgICAgbG9jYWxHU3RhdGVDYWNoZSwKICAgICAgICAgICAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlLAogICAgICAgICAgICAgICAgc2VlblJlZnMKICAgICAgICAgICAgICB9KS50aGVuKHJlc29sdmVHU3RhdGUsIHJlamVjdEdTdGF0ZSk7CiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24pIHsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHNlbGYub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgICAgICAgIHdhcm4oYGdldE9wZXJhdG9yTGlzdCAtIGlnbm9yaW5nIEV4dEdTdGF0ZTogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRocm93IHJlYXNvbjsKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICBjYXNlIE9QUy5zZXRMaW5lV2lkdGg6CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICBjb25zdCBbdGhpY2tuZXNzXSA9IGFyZ3M7CiAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlja25lc3MgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgICAgICB3YXJuKGBJbnZhbGlkIHNldExpbmVXaWR0aDogJHt0aGlja25lc3N9YCk7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYXJnc1swXSA9IE1hdGguYWJzKHRoaWNrbmVzcyk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT1BTLnNldERhc2g6CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICBjb25zdCBkYXNoUGhhc2UgPSBhcmdzWzFdOwogICAgICAgICAgICAgIGlmICh0eXBlb2YgZGFzaFBoYXNlICE9PSAibnVtYmVyIikgewogICAgICAgICAgICAgICAgd2FybihgSW52YWxpZCBzZXREYXNoOiAke2Rhc2hQaGFzZX1gKTsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCBkYXNoQXJyYXkgPSBhcmdzWzBdOwogICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShkYXNoQXJyYXkpKSB7CiAgICAgICAgICAgICAgICB3YXJuKGBJbnZhbGlkIHNldERhc2g6ICR7ZGFzaEFycmF5fWApOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChkYXNoQXJyYXkuc29tZSh4ID0+IHR5cGVvZiB4ICE9PSAibnVtYmVyIikpIHsKICAgICAgICAgICAgICAgIGFyZ3NbMF0gPSBkYXNoQXJyYXkuZmlsdGVyKHggPT4gdHlwZW9mIHggPT09ICJudW1iZXIiKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT1BTLm1vdmVUbzoKICAgICAgICAgIGNhc2UgT1BTLmxpbmVUbzoKICAgICAgICAgIGNhc2UgT1BTLmN1cnZlVG86CiAgICAgICAgICBjYXNlIE9QUy5jdXJ2ZVRvMjoKICAgICAgICAgIGNhc2UgT1BTLmN1cnZlVG8zOgogICAgICAgICAgY2FzZSBPUFMuY2xvc2VQYXRoOgogICAgICAgICAgY2FzZSBPUFMucmVjdGFuZ2xlOgogICAgICAgICAgICBzZWxmLmJ1aWxkUGF0aChmbiwgYXJncywgc3RhdGVNYW5hZ2VyLnN0YXRlKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICBjYXNlIE9QUy5zdHJva2U6CiAgICAgICAgICBjYXNlIE9QUy5jbG9zZVN0cm9rZToKICAgICAgICAgIGNhc2UgT1BTLmZpbGw6CiAgICAgICAgICBjYXNlIE9QUy5lb0ZpbGw6CiAgICAgICAgICBjYXNlIE9QUy5maWxsU3Ryb2tlOgogICAgICAgICAgY2FzZSBPUFMuZW9GaWxsU3Ryb2tlOgogICAgICAgICAgY2FzZSBPUFMuY2xvc2VGaWxsU3Ryb2tlOgogICAgICAgICAgY2FzZSBPUFMuY2xvc2VFT0ZpbGxTdHJva2U6CiAgICAgICAgICBjYXNlIE9QUy5lbmRQYXRoOgogICAgICAgICAgICB7CiAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgc3RhdGU6IHsKICAgICAgICAgICAgICAgICAgcGF0aEJ1ZmZlciwKICAgICAgICAgICAgICAgICAgcGF0aE1pbk1heAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0gPSBzdGF0ZU1hbmFnZXI7CiAgICAgICAgICAgICAgaWYgKGZuID09PSBPUFMuY2xvc2VTdHJva2UgfHwgZm4gPT09IE9QUy5jbG9zZUZpbGxTdHJva2UgfHwgZm4gPT09IE9QUy5jbG9zZUVPRmlsbFN0cm9rZSkgewogICAgICAgICAgICAgICAgcGF0aEJ1ZmZlci5wdXNoKERyYXdPUFMuY2xvc2VQYXRoKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHBhdGhCdWZmZXIubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoT1BTLmNvbnN0cnVjdFBhdGgsIFtmbiwgW251bGxdLCBudWxsXSk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChPUFMuY29uc3RydWN0UGF0aCwgW2ZuLCBbbmV3IEZsb2F0MzJBcnJheShwYXRoQnVmZmVyKV0sIHBhdGhNaW5NYXguc2xpY2UoKV0pOwogICAgICAgICAgICAgICAgcGF0aEJ1ZmZlci5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgcGF0aE1pbk1heC5zZXQoW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldLCAwKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT1BTLnNldFRleHRNYXRyaXg6CiAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChmbiwgW25ldyBGbG9hdDMyQXJyYXkoYXJncyldKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICBjYXNlIE9QUy5tYXJrUG9pbnQ6CiAgICAgICAgICBjYXNlIE9QUy5tYXJrUG9pbnRQcm9wczoKICAgICAgICAgIGNhc2UgT1BTLmJlZ2luQ29tcGF0OgogICAgICAgICAgY2FzZSBPUFMuZW5kQ29tcGF0OgogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIGNhc2UgT1BTLmJlZ2luTWFya2VkQ29udGVudFByb3BzOgogICAgICAgICAgICBpZiAoIShhcmdzWzBdIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgICAgICAgICAgICB3YXJuKGBFeHBlY3RlZCBuYW1lIGZvciBiZWdpbk1hcmtlZENvbnRlbnRQcm9wcyBhcmcwPSR7YXJnc1swXX1gKTsKICAgICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoT1BTLmJlZ2luTWFya2VkQ29udGVudFByb3BzLCBbIk9DIiwgbnVsbF0pOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChhcmdzWzBdLm5hbWUgPT09ICJPQyIpIHsKICAgICAgICAgICAgICBuZXh0KHNlbGYucGFyc2VNYXJrZWRDb250ZW50UHJvcHMoYXJnc1sxXSwgcmVzb3VyY2VzKS50aGVuKGRhdGEgPT4gewogICAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5iZWdpbk1hcmtlZENvbnRlbnRQcm9wcywgWyJPQyIsIGRhdGFdKTsKICAgICAgICAgICAgICB9KS5jYXRjaChyZWFzb24gPT4gewogICAgICAgICAgICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIEFib3J0RXhjZXB0aW9uKSB7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChzZWxmLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgICAgICAgICAgIHdhcm4oYGdldE9wZXJhdG9yTGlzdCAtIGlnbm9yaW5nIGJlZ2luTWFya2VkQ29udGVudFByb3BzOiAiJHtyZWFzb259Ii5gKTsKICAgICAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5iZWdpbk1hcmtlZENvbnRlbnRQcm9wcywgWyJPQyIsIG51bGxdKTsKICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhyb3cgcmVhc29uOwogICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYXJncyA9IFthcmdzWzBdLm5hbWUsIGFyZ3NbMV0gaW5zdGFuY2VvZiBEaWN0ID8gYXJnc1sxXS5nZXQoIk1DSUQiKSA6IG51bGxdOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLmJlZ2luTWFya2VkQ29udGVudDoKICAgICAgICAgIGNhc2UgT1BTLmVuZE1hcmtlZENvbnRlbnQ6CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICBpZiAoYXJncyAhPT0gbnVsbCkgewogICAgICAgICAgICAgIGZvciAoaSA9IDAsIGlpID0gYXJncy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICAgICAgICBpZiAoYXJnc1tpXSBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChpIDwgaWkpIHsKICAgICAgICAgICAgICAgIHdhcm4oImdldE9wZXJhdG9yTGlzdCAtIGlnbm9yaW5nIG9wZXJhdG9yOiAiICsgZm4pOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChmbiwgYXJncyk7CiAgICAgIH0KICAgICAgaWYgKHN0b3ApIHsKICAgICAgICBuZXh0KGRlZmVycmVkKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY2xvc2VQZW5kaW5nUmVzdG9yZU9QUygpOwogICAgICByZXNvbHZlKCk7CiAgICB9KS5jYXRjaChyZWFzb24gPT4gewogICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24pIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKHRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICB3YXJuKGBnZXRPcGVyYXRvckxpc3QgLSBpZ25vcmluZyBlcnJvcnMgZHVyaW5nICIke3Rhc2submFtZX0iIGAgKyBgdGFzazogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgY2xvc2VQZW5kaW5nUmVzdG9yZU9QUygpOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICB0aHJvdyByZWFzb247CiAgICB9KTsKICB9CiAgYXN5bmMgZ2V0VGV4dENvbnRlbnQoewogICAgc3RyZWFtLAogICAgdGFzaywKICAgIHJlc291cmNlcywKICAgIHN0YXRlTWFuYWdlciA9IG51bGwsCiAgICBpbmNsdWRlTWFya2VkQ29udGVudCA9IGZhbHNlLAogICAgc2luaywKICAgIHNlZW5TdHlsZXMgPSBuZXcgU2V0KCksCiAgICB2aWV3Qm94LAogICAgbGFuZyA9IG51bGwsCiAgICBtYXJrZWRDb250ZW50RGF0YSA9IG51bGwsCiAgICBkaXNhYmxlTm9ybWFsaXphdGlvbiA9IGZhbHNlLAogICAga2VlcFdoaXRlU3BhY2UgPSBmYWxzZSwKICAgIHByZXZSZWZzID0gbnVsbCwKICAgIGludGVyc2VjdG9yID0gbnVsbAogIH0pIHsKICAgIGlmIChzdHJlYW0uaXNBc3luYykgewogICAgICBjb25zdCBieXRlcyA9IGF3YWl0IHN0cmVhbS5hc3luY0dldEJ5dGVzKCk7CiAgICAgIGlmIChieXRlcykgewogICAgICAgIHN0cmVhbSA9IG5ldyBTdHJlYW0oYnl0ZXMsIDAsIGJ5dGVzLmxlbmd0aCwgc3RyZWFtLmRpY3QpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBvYmpJZCA9IHN0cmVhbS5kaWN0Py5vYmpJZDsKICAgIGNvbnN0IHNlZW5SZWZzID0gbmV3IFJlZlNldChwcmV2UmVmcyk7CiAgICBpZiAob2JqSWQpIHsKICAgICAgaWYgKHByZXZSZWZzPy5oYXMob2JqSWQpKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBnZXRUZXh0Q29udGVudCAtIGlnbm9yaW5nIGNpcmN1bGFyIHJlZmVyZW5jZTogJHtvYmpJZH1gKTsKICAgICAgfQogICAgICBzZWVuUmVmcy5wdXQob2JqSWQpOwogICAgfQogICAgcmVzb3VyY2VzIHx8PSBEaWN0LmVtcHR5OwogICAgc3RhdGVNYW5hZ2VyIHx8PSBuZXcgU3RhdGVNYW5hZ2VyKG5ldyBUZXh0U3RhdGUoKSk7CiAgICBpZiAoaW5jbHVkZU1hcmtlZENvbnRlbnQpIHsKICAgICAgbWFya2VkQ29udGVudERhdGEgfHw9IHsKICAgICAgICBsZXZlbDogMAogICAgICB9OwogICAgfQogICAgY29uc3QgdGV4dENvbnRlbnQgPSB7CiAgICAgIGl0ZW1zOiBbXSwKICAgICAgc3R5bGVzOiBPYmplY3QuY3JlYXRlKG51bGwpLAogICAgICBsYW5nCiAgICB9OwogICAgY29uc3QgdGV4dENvbnRlbnRJdGVtID0gewogICAgICBpbml0aWFsaXplZDogZmFsc2UsCiAgICAgIHN0cjogW10sCiAgICAgIHRvdGFsV2lkdGg6IDAsCiAgICAgIHRvdGFsSGVpZ2h0OiAwLAogICAgICB3aWR0aDogMCwKICAgICAgaGVpZ2h0OiAwLAogICAgICB2ZXJ0aWNhbDogZmFsc2UsCiAgICAgIHByZXZUcmFuc2Zvcm06IG51bGwsCiAgICAgIHRleHRBZHZhbmNlU2NhbGU6IDAsCiAgICAgIHNwYWNlSW5GbG93TWluOiAwLAogICAgICBzcGFjZUluRmxvd01heDogMCwKICAgICAgdHJhY2tpbmdTcGFjZU1pbjogSW5maW5pdHksCiAgICAgIG5lZ2F0aXZlU3BhY2VNYXg6IC1JbmZpbml0eSwKICAgICAgbm90QVNwYWNlOiAtSW5maW5pdHksCiAgICAgIHRyYW5zZm9ybTogbnVsbCwKICAgICAgZm9udE5hbWU6IG51bGwsCiAgICAgIGhhc0VPTDogZmFsc2UKICAgIH07CiAgICBjb25zdCB0d29MYXN0Q2hhcnMgPSBbIiAiLCAiICJdOwogICAgbGV0IHR3b0xhc3RDaGFyc1BvcyA9IDA7CiAgICBmdW5jdGlvbiBzYXZlTGFzdENoYXIoY2hhcikgewogICAgICBjb25zdCBuZXh0UG9zID0gKHR3b0xhc3RDaGFyc1BvcyArIDEpICUgMjsKICAgICAgY29uc3QgcmV0ID0gdHdvTGFzdENoYXJzW3R3b0xhc3RDaGFyc1Bvc10gIT09ICIgIiAmJiB0d29MYXN0Q2hhcnNbbmV4dFBvc10gPT09ICIgIjsKICAgICAgdHdvTGFzdENoYXJzW3R3b0xhc3RDaGFyc1Bvc10gPSBjaGFyOwogICAgICB0d29MYXN0Q2hhcnNQb3MgPSBuZXh0UG9zOwogICAgICByZXR1cm4gIWtlZXBXaGl0ZVNwYWNlICYmIHJldDsKICAgIH0KICAgIGZ1bmN0aW9uIHNob3VsZEFkZFdoaXRlcHNhY2UoKSB7CiAgICAgIHJldHVybiAha2VlcFdoaXRlU3BhY2UgJiYgdHdvTGFzdENoYXJzW3R3b0xhc3RDaGFyc1Bvc10gIT09ICIgIiAmJiB0d29MYXN0Q2hhcnNbKHR3b0xhc3RDaGFyc1BvcyArIDEpICUgMl0gPT09ICIgIjsKICAgIH0KICAgIGZ1bmN0aW9uIHJlc2V0TGFzdENoYXJzKCkgewogICAgICB0d29MYXN0Q2hhcnNbMF0gPSB0d29MYXN0Q2hhcnNbMV0gPSAiICI7CiAgICAgIHR3b0xhc3RDaGFyc1BvcyA9IDA7CiAgICB9CiAgICBjb25zdCBUUkFDS0lOR19TUEFDRV9GQUNUT1IgPSAwLjEwMjsKICAgIGNvbnN0IE5PVF9BX1NQQUNFX0ZBQ1RPUiA9IDAuMDM7CiAgICBjb25zdCBORUdBVElWRV9TUEFDRV9GQUNUT1IgPSAtMC4yOwogICAgY29uc3QgU1BBQ0VfSU5fRkxPV19NSU5fRkFDVE9SID0gMC4xMDI7CiAgICBjb25zdCBTUEFDRV9JTl9GTE9XX01BWF9GQUNUT1IgPSAwLjY7CiAgICBjb25zdCBWRVJUSUNBTF9TSElGVF9SQVRJTyA9IDAuMjU7CiAgICBjb25zdCBzZWxmID0gdGhpczsKICAgIGNvbnN0IHhyZWYgPSB0aGlzLnhyZWY7CiAgICBjb25zdCBzaG93U3BhY2VkVGV4dEJ1ZmZlciA9IFtdOwogICAgbGV0IHhvYmpzID0gbnVsbDsKICAgIGNvbnN0IGVtcHR5WE9iamVjdENhY2hlID0gbmV3IExvY2FsSW1hZ2VDYWNoZSgpOwogICAgY29uc3QgZW1wdHlHU3RhdGVDYWNoZSA9IG5ldyBMb2NhbEdTdGF0ZUNhY2hlKCk7CiAgICBjb25zdCBwcmVwcm9jZXNzb3IgPSBuZXcgRXZhbHVhdG9yUHJlcHJvY2Vzc29yKHN0cmVhbSwgeHJlZiwgc3RhdGVNYW5hZ2VyKTsKICAgIGxldCB0ZXh0U3RhdGU7CiAgICBmdW5jdGlvbiBwdXNoV2hpdGVzcGFjZSh7CiAgICAgIHdpZHRoID0gMCwKICAgICAgaGVpZ2h0ID0gMCwKICAgICAgdHJhbnNmb3JtID0gdGV4dENvbnRlbnRJdGVtLnByZXZUcmFuc2Zvcm0sCiAgICAgIGZvbnROYW1lID0gdGV4dENvbnRlbnRJdGVtLmZvbnROYW1lCiAgICB9KSB7CiAgICAgIGludGVyc2VjdG9yPy5hZGRFeHRyYUNoYXIoIiAiKTsKICAgICAgdGV4dENvbnRlbnQuaXRlbXMucHVzaCh7CiAgICAgICAgc3RyOiAiICIsCiAgICAgICAgZGlyOiAibHRyIiwKICAgICAgICB3aWR0aCwKICAgICAgICBoZWlnaHQsCiAgICAgICAgdHJhbnNmb3JtLAogICAgICAgIGZvbnROYW1lLAogICAgICAgIGhhc0VPTDogZmFsc2UKICAgICAgfSk7CiAgICB9CiAgICBmdW5jdGlvbiBnZXRDdXJyZW50VGV4dFRyYW5zZm9ybSgpIHsKICAgICAgY29uc3QgZm9udCA9IHRleHRTdGF0ZS5mb250OwogICAgICBjb25zdCB0c20gPSBbdGV4dFN0YXRlLmZvbnRTaXplICogdGV4dFN0YXRlLnRleHRIU2NhbGUsIDAsIDAsIHRleHRTdGF0ZS5mb250U2l6ZSwgMCwgdGV4dFN0YXRlLnRleHRSaXNlXTsKICAgICAgaWYgKGZvbnQuaXNUeXBlM0ZvbnQgJiYgKHRleHRTdGF0ZS5mb250U2l6ZSA8PSAxIHx8IGZvbnQuaXNDaGFyQkJveCkgJiYgIWlzQXJyYXlFcXVhbCh0ZXh0U3RhdGUuZm9udE1hdHJpeCwgRk9OVF9JREVOVElUWV9NQVRSSVgpKSB7CiAgICAgICAgY29uc3QgZ2x5cGhIZWlnaHQgPSBmb250LmJib3hbM10gLSBmb250LmJib3hbMV07CiAgICAgICAgaWYgKGdseXBoSGVpZ2h0ID4gMCkgewogICAgICAgICAgdHNtWzNdICo9IGdseXBoSGVpZ2h0ICogdGV4dFN0YXRlLmZvbnRNYXRyaXhbM107CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBVdGlsLnRyYW5zZm9ybSh0ZXh0U3RhdGUuY3RtLCBVdGlsLnRyYW5zZm9ybSh0ZXh0U3RhdGUudGV4dE1hdHJpeCwgdHNtKSk7CiAgICB9CiAgICBmdW5jdGlvbiBlbnN1cmVUZXh0Q29udGVudEl0ZW0oKSB7CiAgICAgIGlmICh0ZXh0Q29udGVudEl0ZW0uaW5pdGlhbGl6ZWQpIHsKICAgICAgICByZXR1cm4gdGV4dENvbnRlbnRJdGVtOwogICAgICB9CiAgICAgIGNvbnN0IHsKICAgICAgICBmb250LAogICAgICAgIGxvYWRlZE5hbWUKICAgICAgfSA9IHRleHRTdGF0ZTsKICAgICAgaWYgKCFzZWVuU3R5bGVzLmhhcyhsb2FkZWROYW1lKSkgewogICAgICAgIHNlZW5TdHlsZXMuYWRkKGxvYWRlZE5hbWUpOwogICAgICAgIHRleHRDb250ZW50LnN0eWxlc1tsb2FkZWROYW1lXSA9IHsKICAgICAgICAgIGZvbnRGYW1pbHk6IGZvbnQuZmFsbGJhY2tOYW1lLAogICAgICAgICAgYXNjZW50OiBmb250LmFzY2VudCwKICAgICAgICAgIGRlc2NlbnQ6IGZvbnQuZGVzY2VudCwKICAgICAgICAgIHZlcnRpY2FsOiBmb250LnZlcnRpY2FsCiAgICAgICAgfTsKICAgICAgICBpZiAoc2VsZi5vcHRpb25zLmZvbnRFeHRyYVByb3BlcnRpZXMgJiYgZm9udC5zeXN0ZW1Gb250SW5mbykgewogICAgICAgICAgY29uc3Qgc3R5bGUgPSB0ZXh0Q29udGVudC5zdHlsZXNbbG9hZGVkTmFtZV07CiAgICAgICAgICBzdHlsZS5mb250U3Vic3RpdHV0aW9uID0gZm9udC5zeXN0ZW1Gb250SW5mby5jc3M7CiAgICAgICAgICBzdHlsZS5mb250U3Vic3RpdHV0aW9uTG9hZGVkTmFtZSA9IGZvbnQuc3lzdGVtRm9udEluZm8ubG9hZGVkTmFtZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgdGV4dENvbnRlbnRJdGVtLmZvbnROYW1lID0gbG9hZGVkTmFtZTsKICAgICAgY29uc3QgdHJtID0gdGV4dENvbnRlbnRJdGVtLnRyYW5zZm9ybSA9IGdldEN1cnJlbnRUZXh0VHJhbnNmb3JtKCk7CiAgICAgIGlmICghZm9udC52ZXJ0aWNhbCkgewogICAgICAgIHRleHRDb250ZW50SXRlbS53aWR0aCA9IHRleHRDb250ZW50SXRlbS50b3RhbFdpZHRoID0gMDsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0uaGVpZ2h0ID0gdGV4dENvbnRlbnRJdGVtLnRvdGFsSGVpZ2h0ID0gTWF0aC5oeXBvdCh0cm1bMl0sIHRybVszXSk7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLnZlcnRpY2FsID0gZmFsc2U7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLndpZHRoID0gdGV4dENvbnRlbnRJdGVtLnRvdGFsV2lkdGggPSBNYXRoLmh5cG90KHRybVswXSwgdHJtWzFdKTsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0uaGVpZ2h0ID0gdGV4dENvbnRlbnRJdGVtLnRvdGFsSGVpZ2h0ID0gMDsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0udmVydGljYWwgPSB0cnVlOwogICAgICB9CiAgICAgIGNvbnN0IHNjYWxlTGluZVggPSBNYXRoLmh5cG90KHRleHRTdGF0ZS50ZXh0TGluZU1hdHJpeFswXSwgdGV4dFN0YXRlLnRleHRMaW5lTWF0cml4WzFdKTsKICAgICAgY29uc3Qgc2NhbGVDdG1YID0gTWF0aC5oeXBvdCh0ZXh0U3RhdGUuY3RtWzBdLCB0ZXh0U3RhdGUuY3RtWzFdKTsKICAgICAgdGV4dENvbnRlbnRJdGVtLnRleHRBZHZhbmNlU2NhbGUgPSBzY2FsZUN0bVggKiBzY2FsZUxpbmVYOwogICAgICBjb25zdCB7CiAgICAgICAgZm9udFNpemUKICAgICAgfSA9IHRleHRTdGF0ZTsKICAgICAgdGV4dENvbnRlbnRJdGVtLnRyYWNraW5nU3BhY2VNaW4gPSBmb250U2l6ZSAqIFRSQUNLSU5HX1NQQUNFX0ZBQ1RPUjsKICAgICAgdGV4dENvbnRlbnRJdGVtLm5vdEFTcGFjZSA9IGZvbnRTaXplICogTk9UX0FfU1BBQ0VfRkFDVE9SOwogICAgICB0ZXh0Q29udGVudEl0ZW0ubmVnYXRpdmVTcGFjZU1heCA9IGZvbnRTaXplICogTkVHQVRJVkVfU1BBQ0VfRkFDVE9SOwogICAgICB0ZXh0Q29udGVudEl0ZW0uc3BhY2VJbkZsb3dNaW4gPSBmb250U2l6ZSAqIFNQQUNFX0lOX0ZMT1dfTUlOX0ZBQ1RPUjsKICAgICAgdGV4dENvbnRlbnRJdGVtLnNwYWNlSW5GbG93TWF4ID0gZm9udFNpemUgKiBTUEFDRV9JTl9GTE9XX01BWF9GQUNUT1I7CiAgICAgIHRleHRDb250ZW50SXRlbS5oYXNFT0wgPSBmYWxzZTsKICAgICAgdGV4dENvbnRlbnRJdGVtLmluaXRpYWxpemVkID0gdHJ1ZTsKICAgICAgcmV0dXJuIHRleHRDb250ZW50SXRlbTsKICAgIH0KICAgIGZ1bmN0aW9uIHVwZGF0ZUFkdmFuY2VTY2FsZSgpIHsKICAgICAgaWYgKCF0ZXh0Q29udGVudEl0ZW0uaW5pdGlhbGl6ZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29uc3Qgc2NhbGVMaW5lWCA9IE1hdGguaHlwb3QodGV4dFN0YXRlLnRleHRMaW5lTWF0cml4WzBdLCB0ZXh0U3RhdGUudGV4dExpbmVNYXRyaXhbMV0pOwogICAgICBjb25zdCBzY2FsZUN0bVggPSBNYXRoLmh5cG90KHRleHRTdGF0ZS5jdG1bMF0sIHRleHRTdGF0ZS5jdG1bMV0pOwogICAgICBjb25zdCBzY2FsZUZhY3RvciA9IHNjYWxlQ3RtWCAqIHNjYWxlTGluZVg7CiAgICAgIGlmIChzY2FsZUZhY3RvciA9PT0gdGV4dENvbnRlbnRJdGVtLnRleHRBZHZhbmNlU2NhbGUpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKCF0ZXh0Q29udGVudEl0ZW0udmVydGljYWwpIHsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0udG90YWxXaWR0aCArPSB0ZXh0Q29udGVudEl0ZW0ud2lkdGggKiB0ZXh0Q29udGVudEl0ZW0udGV4dEFkdmFuY2VTY2FsZTsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0ud2lkdGggPSAwOwogICAgICB9IGVsc2UgewogICAgICAgIHRleHRDb250ZW50SXRlbS50b3RhbEhlaWdodCArPSB0ZXh0Q29udGVudEl0ZW0uaGVpZ2h0ICogdGV4dENvbnRlbnRJdGVtLnRleHRBZHZhbmNlU2NhbGU7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLmhlaWdodCA9IDA7CiAgICAgIH0KICAgICAgdGV4dENvbnRlbnRJdGVtLnRleHRBZHZhbmNlU2NhbGUgPSBzY2FsZUZhY3RvcjsKICAgIH0KICAgIGZ1bmN0aW9uIHJ1bkJpZGlUcmFuc2Zvcm0odGV4dENodW5rKSB7CiAgICAgIGxldCB0ZXh0ID0gdGV4dENodW5rLnN0ci5qb2luKCIiKTsKICAgICAgaWYgKCFkaXNhYmxlTm9ybWFsaXphdGlvbikgewogICAgICAgIHRleHQgPSBub3JtYWxpemVVbmljb2RlKHRleHQpOwogICAgICB9CiAgICAgIGNvbnN0IGJpZGlSZXN1bHQgPSBiaWRpKHRleHQsIC0xLCB0ZXh0Q2h1bmsudmVydGljYWwpOwogICAgICByZXR1cm4gewogICAgICAgIHN0cjogYmlkaVJlc3VsdC5zdHIsCiAgICAgICAgZGlyOiBiaWRpUmVzdWx0LmRpciwKICAgICAgICB3aWR0aDogTWF0aC5hYnModGV4dENodW5rLnRvdGFsV2lkdGgpLAogICAgICAgIGhlaWdodDogTWF0aC5hYnModGV4dENodW5rLnRvdGFsSGVpZ2h0KSwKICAgICAgICB0cmFuc2Zvcm06IHRleHRDaHVuay50cmFuc2Zvcm0sCiAgICAgICAgZm9udE5hbWU6IHRleHRDaHVuay5mb250TmFtZSwKICAgICAgICBoYXNFT0w6IHRleHRDaHVuay5oYXNFT0wKICAgICAgfTsKICAgIH0KICAgIGFzeW5jIGZ1bmN0aW9uIGhhbmRsZVNldEZvbnQoZm9udE5hbWUsIGZvbnRSZWYpIHsKICAgICAgY29uc3QgdHJhbnNsYXRlZCA9IGF3YWl0IHNlbGYubG9hZEZvbnQoZm9udE5hbWUsIGZvbnRSZWYsIHJlc291cmNlcywgdGFzayk7CiAgICAgIHRleHRTdGF0ZS5sb2FkZWROYW1lID0gdHJhbnNsYXRlZC5sb2FkZWROYW1lOwogICAgICB0ZXh0U3RhdGUuZm9udCA9IHRyYW5zbGF0ZWQuZm9udDsKICAgICAgdGV4dFN0YXRlLmZvbnRNYXRyaXggPSB0cmFuc2xhdGVkLmZvbnQuZm9udE1hdHJpeCB8fCBGT05UX0lERU5USVRZX01BVFJJWDsKICAgIH0KICAgIGZ1bmN0aW9uIGFwcGx5SW52ZXJzZVJvdGF0aW9uKHgsIHksIG1hdHJpeCkgewogICAgICBjb25zdCBzY2FsZSA9IE1hdGguaHlwb3QobWF0cml4WzBdLCBtYXRyaXhbMV0pOwogICAgICByZXR1cm4gWyhtYXRyaXhbMF0gKiB4ICsgbWF0cml4WzFdICogeSkgLyBzY2FsZSwgKG1hdHJpeFsyXSAqIHggKyBtYXRyaXhbM10gKiB5KSAvIHNjYWxlXTsKICAgIH0KICAgIGZ1bmN0aW9uIGNvbXBhcmVXaXRoTGFzdFBvc2l0aW9uKGdseXBoV2lkdGgpIHsKICAgICAgY29uc3QgY3VycmVudFRyYW5zZm9ybSA9IGdldEN1cnJlbnRUZXh0VHJhbnNmb3JtKCk7CiAgICAgIGxldCBwb3NYID0gY3VycmVudFRyYW5zZm9ybVs0XTsKICAgICAgbGV0IHBvc1kgPSBjdXJyZW50VHJhbnNmb3JtWzVdOwogICAgICBpZiAodGV4dFN0YXRlLmZvbnQ/LnZlcnRpY2FsKSB7CiAgICAgICAgaWYgKHBvc1ggPCB2aWV3Qm94WzBdIHx8IHBvc1ggPiB2aWV3Qm94WzJdIHx8IHBvc1kgKyBnbHlwaFdpZHRoIDwgdmlld0JveFsxXSB8fCBwb3NZID4gdmlld0JveFszXSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChwb3NYICsgZ2x5cGhXaWR0aCA8IHZpZXdCb3hbMF0gfHwgcG9zWCA+IHZpZXdCb3hbMl0gfHwgcG9zWSA8IHZpZXdCb3hbMV0gfHwgcG9zWSA+IHZpZXdCb3hbM10pIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKCF0ZXh0U3RhdGUuZm9udCB8fCAhdGV4dENvbnRlbnRJdGVtLnByZXZUcmFuc2Zvcm0pIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBsZXQgbGFzdFBvc1ggPSB0ZXh0Q29udGVudEl0ZW0ucHJldlRyYW5zZm9ybVs0XTsKICAgICAgbGV0IGxhc3RQb3NZID0gdGV4dENvbnRlbnRJdGVtLnByZXZUcmFuc2Zvcm1bNV07CiAgICAgIGlmIChsYXN0UG9zWCA9PT0gcG9zWCAmJiBsYXN0UG9zWSA9PT0gcG9zWSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGxldCByb3RhdGUgPSAtMTsKICAgICAgaWYgKGN1cnJlbnRUcmFuc2Zvcm1bMF0gJiYgY3VycmVudFRyYW5zZm9ybVsxXSA9PT0gMCAmJiBjdXJyZW50VHJhbnNmb3JtWzJdID09PSAwKSB7CiAgICAgICAgcm90YXRlID0gY3VycmVudFRyYW5zZm9ybVswXSA+IDAgPyAwIDogMTgwOwogICAgICB9IGVsc2UgaWYgKGN1cnJlbnRUcmFuc2Zvcm1bMV0gJiYgY3VycmVudFRyYW5zZm9ybVswXSA9PT0gMCAmJiBjdXJyZW50VHJhbnNmb3JtWzNdID09PSAwKSB7CiAgICAgICAgcm90YXRlID0gY3VycmVudFRyYW5zZm9ybVsxXSA+IDAgPyA5MCA6IDI3MDsKICAgICAgfQogICAgICBzd2l0Y2ggKHJvdGF0ZSkgewogICAgICAgIGNhc2UgMDoKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgOTA6CiAgICAgICAgICBbcG9zWCwgcG9zWV0gPSBbcG9zWSwgcG9zWF07CiAgICAgICAgICBbbGFzdFBvc1gsIGxhc3RQb3NZXSA9IFtsYXN0UG9zWSwgbGFzdFBvc1hdOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxODA6CiAgICAgICAgICBbcG9zWCwgcG9zWSwgbGFzdFBvc1gsIGxhc3RQb3NZXSA9IFstcG9zWCwgLXBvc1ksIC1sYXN0UG9zWCwgLWxhc3RQb3NZXTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjcwOgogICAgICAgICAgW3Bvc1gsIHBvc1ldID0gWy1wb3NZLCAtcG9zWF07CiAgICAgICAgICBbbGFzdFBvc1gsIGxhc3RQb3NZXSA9IFstbGFzdFBvc1ksIC1sYXN0UG9zWF07CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgW3Bvc1gsIHBvc1ldID0gYXBwbHlJbnZlcnNlUm90YXRpb24ocG9zWCwgcG9zWSwgY3VycmVudFRyYW5zZm9ybSk7CiAgICAgICAgICBbbGFzdFBvc1gsIGxhc3RQb3NZXSA9IGFwcGx5SW52ZXJzZVJvdGF0aW9uKGxhc3RQb3NYLCBsYXN0UG9zWSwgdGV4dENvbnRlbnRJdGVtLnByZXZUcmFuc2Zvcm0pOwogICAgICB9CiAgICAgIGlmICh0ZXh0U3RhdGUuZm9udC52ZXJ0aWNhbCkgewogICAgICAgIGNvbnN0IGFkdmFuY2VZID0gKGxhc3RQb3NZIC0gcG9zWSkgLyB0ZXh0Q29udGVudEl0ZW0udGV4dEFkdmFuY2VTY2FsZTsKICAgICAgICBjb25zdCBhZHZhbmNlWCA9IHBvc1ggLSBsYXN0UG9zWDsKICAgICAgICBjb25zdCB0ZXh0T3JpZW50YXRpb24gPSBNYXRoLnNpZ24odGV4dENvbnRlbnRJdGVtLmhlaWdodCk7CiAgICAgICAgaWYgKGFkdmFuY2VZIDwgdGV4dE9yaWVudGF0aW9uICogdGV4dENvbnRlbnRJdGVtLm5lZ2F0aXZlU3BhY2VNYXgpIHsKICAgICAgICAgIGlmIChNYXRoLmFicyhhZHZhbmNlWCkgPiAwLjUgKiB0ZXh0Q29udGVudEl0ZW0ud2lkdGgpIHsKICAgICAgICAgICAgYXBwZW5kRU9MKCk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgfQogICAgICAgICAgcmVzZXRMYXN0Q2hhcnMoKTsKICAgICAgICAgIGZsdXNoVGV4dENvbnRlbnRJdGVtKCk7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKE1hdGguYWJzKGFkdmFuY2VYKSA+IHRleHRDb250ZW50SXRlbS53aWR0aCkgewogICAgICAgICAgYXBwZW5kRU9MKCk7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKGFkdmFuY2VZIDw9IHRleHRPcmllbnRhdGlvbiAqIHRleHRDb250ZW50SXRlbS5ub3RBU3BhY2UpIHsKICAgICAgICAgIHJlc2V0TGFzdENoYXJzKCk7CiAgICAgICAgfQogICAgICAgIGlmIChhZHZhbmNlWSA8PSB0ZXh0T3JpZW50YXRpb24gKiB0ZXh0Q29udGVudEl0ZW0udHJhY2tpbmdTcGFjZU1pbikgewogICAgICAgICAgaWYgKHNob3VsZEFkZFdoaXRlcHNhY2UoKSkgewogICAgICAgICAgICByZXNldExhc3RDaGFycygpOwogICAgICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgICAgICBwdXNoV2hpdGVzcGFjZSh7CiAgICAgICAgICAgICAgaGVpZ2h0OiBNYXRoLmFicyhhZHZhbmNlWSkKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0ZXh0Q29udGVudEl0ZW0uaGVpZ2h0ICs9IGFkdmFuY2VZOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoIWFkZEZha2VTcGFjZXMoYWR2YW5jZVksIHRleHRDb250ZW50SXRlbS5wcmV2VHJhbnNmb3JtLCB0ZXh0T3JpZW50YXRpb24pKSB7CiAgICAgICAgICBpZiAodGV4dENvbnRlbnRJdGVtLnN0ci5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgcmVzZXRMYXN0Q2hhcnMoKTsKICAgICAgICAgICAgcHVzaFdoaXRlc3BhY2UoewogICAgICAgICAgICAgIGhlaWdodDogTWF0aC5hYnMoYWR2YW5jZVkpCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGV4dENvbnRlbnRJdGVtLmhlaWdodCArPSBhZHZhbmNlWTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKE1hdGguYWJzKGFkdmFuY2VYKSA+IHRleHRDb250ZW50SXRlbS53aWR0aCAqIFZFUlRJQ0FMX1NISUZUX1JBVElPKSB7CiAgICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBjb25zdCBhZHZhbmNlWCA9IChwb3NYIC0gbGFzdFBvc1gpIC8gdGV4dENvbnRlbnRJdGVtLnRleHRBZHZhbmNlU2NhbGU7CiAgICAgIGNvbnN0IGFkdmFuY2VZID0gcG9zWSAtIGxhc3RQb3NZOwogICAgICBjb25zdCB0ZXh0T3JpZW50YXRpb24gPSBNYXRoLnNpZ24odGV4dENvbnRlbnRJdGVtLndpZHRoKTsKICAgICAgaWYgKGFkdmFuY2VYIDwgdGV4dE9yaWVudGF0aW9uICogdGV4dENvbnRlbnRJdGVtLm5lZ2F0aXZlU3BhY2VNYXgpIHsKICAgICAgICBpZiAoTWF0aC5hYnMoYWR2YW5jZVkpID4gMC41ICogdGV4dENvbnRlbnRJdGVtLmhlaWdodCkgewogICAgICAgICAgYXBwZW5kRU9MKCk7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgcmVzZXRMYXN0Q2hhcnMoKTsKICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmIChNYXRoLmFicyhhZHZhbmNlWSkgPiB0ZXh0Q29udGVudEl0ZW0uaGVpZ2h0KSB7CiAgICAgICAgYXBwZW5kRU9MKCk7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKGFkdmFuY2VYIDw9IHRleHRPcmllbnRhdGlvbiAqIHRleHRDb250ZW50SXRlbS5ub3RBU3BhY2UpIHsKICAgICAgICByZXNldExhc3RDaGFycygpOwogICAgICB9CiAgICAgIGlmIChhZHZhbmNlWCA8PSB0ZXh0T3JpZW50YXRpb24gKiB0ZXh0Q29udGVudEl0ZW0udHJhY2tpbmdTcGFjZU1pbikgewogICAgICAgIGlmIChzaG91bGRBZGRXaGl0ZXBzYWNlKCkpIHsKICAgICAgICAgIHJlc2V0TGFzdENoYXJzKCk7CiAgICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgICAgcHVzaFdoaXRlc3BhY2UoewogICAgICAgICAgICB3aWR0aDogTWF0aC5hYnMoYWR2YW5jZVgpCiAgICAgICAgICB9KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGV4dENvbnRlbnRJdGVtLndpZHRoICs9IGFkdmFuY2VYOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmICghYWRkRmFrZVNwYWNlcyhhZHZhbmNlWCwgdGV4dENvbnRlbnRJdGVtLnByZXZUcmFuc2Zvcm0sIHRleHRPcmllbnRhdGlvbikpIHsKICAgICAgICBpZiAodGV4dENvbnRlbnRJdGVtLnN0ci5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHJlc2V0TGFzdENoYXJzKCk7CiAgICAgICAgICBwdXNoV2hpdGVzcGFjZSh7CiAgICAgICAgICAgIHdpZHRoOiBNYXRoLmFicyhhZHZhbmNlWCkKICAgICAgICAgIH0pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0ZXh0Q29udGVudEl0ZW0ud2lkdGggKz0gYWR2YW5jZVg7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChNYXRoLmFicyhhZHZhbmNlWSkgPiB0ZXh0Q29udGVudEl0ZW0uaGVpZ2h0ICogVkVSVElDQUxfU0hJRlRfUkFUSU8pIHsKICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICB9CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgZnVuY3Rpb24gYnVpbGRUZXh0Q29udGVudEl0ZW0oewogICAgICBjaGFycywKICAgICAgZXh0cmFTcGFjaW5nCiAgICB9KSB7CiAgICAgIGNvbnN0IGZvbnQgPSB0ZXh0U3RhdGUuZm9udDsKICAgICAgaWYgKCFjaGFycykgewogICAgICAgIGNvbnN0IGNoYXJTcGFjaW5nID0gdGV4dFN0YXRlLmNoYXJTcGFjaW5nICsgZXh0cmFTcGFjaW5nOwogICAgICAgIGlmIChjaGFyU3BhY2luZykgewogICAgICAgICAgaWYgKCFmb250LnZlcnRpY2FsKSB7CiAgICAgICAgICAgIHRleHRTdGF0ZS50cmFuc2xhdGVUZXh0TWF0cml4KGNoYXJTcGFjaW5nICogdGV4dFN0YXRlLnRleHRIU2NhbGUsIDApOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGV4dFN0YXRlLnRyYW5zbGF0ZVRleHRNYXRyaXgoMCwgLWNoYXJTcGFjaW5nKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGtlZXBXaGl0ZVNwYWNlKSB7CiAgICAgICAgICBjb21wYXJlV2l0aExhc3RQb3NpdGlvbigwKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvbnN0IGdseXBocyA9IGZvbnQuY2hhcnNUb0dseXBocyhjaGFycyk7CiAgICAgIGNvbnN0IHNjYWxlID0gdGV4dFN0YXRlLmZvbnRNYXRyaXhbMF0gKiB0ZXh0U3RhdGUuZm9udFNpemU7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGdseXBocy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3QgZ2x5cGggPSBnbHlwaHNbaV07CiAgICAgICAgY29uc3QgewogICAgICAgICAgY2F0ZWdvcnksCiAgICAgICAgICBvcmlnaW5hbENoYXJDb2RlCiAgICAgICAgfSA9IGdseXBoOwogICAgICAgIGlmIChjYXRlZ29yeS5pc0ludmlzaWJsZUZvcm1hdE1hcmspIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBsZXQgY2hhclNwYWNpbmcgPSB0ZXh0U3RhdGUuY2hhclNwYWNpbmcgKyAoaSArIDEgPT09IGlpID8gZXh0cmFTcGFjaW5nIDogMCk7CiAgICAgICAgbGV0IGdseXBoV2lkdGggPSBnbHlwaC53aWR0aDsKICAgICAgICBpZiAoZm9udC52ZXJ0aWNhbCkgewogICAgICAgICAgZ2x5cGhXaWR0aCA9IGdseXBoLnZtZXRyaWMgPyBnbHlwaC52bWV0cmljWzBdIDogLWdseXBoV2lkdGg7CiAgICAgICAgfQogICAgICAgIGxldCBzY2FsZWREaW0gPSBnbHlwaFdpZHRoICogc2NhbGU7CiAgICAgICAgaWYgKG9yaWdpbmFsQ2hhckNvZGUgPT09IDB4MjApIHsKICAgICAgICAgIGNoYXJTcGFjaW5nICs9IHRleHRTdGF0ZS53b3JkU3BhY2luZzsKICAgICAgICB9CiAgICAgICAgaWYgKCFrZWVwV2hpdGVTcGFjZSAmJiBjYXRlZ29yeS5pc1doaXRlc3BhY2UpIHsKICAgICAgICAgIGlmICghZm9udC52ZXJ0aWNhbCkgewogICAgICAgICAgICBjaGFyU3BhY2luZyArPSBzY2FsZWREaW07CiAgICAgICAgICAgIHRleHRTdGF0ZS50cmFuc2xhdGVUZXh0TWF0cml4KGNoYXJTcGFjaW5nICogdGV4dFN0YXRlLnRleHRIU2NhbGUsIDApOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgY2hhclNwYWNpbmcgKz0gLXNjYWxlZERpbTsKICAgICAgICAgICAgdGV4dFN0YXRlLnRyYW5zbGF0ZVRleHRNYXRyaXgoMCwgLWNoYXJTcGFjaW5nKTsKICAgICAgICAgIH0KICAgICAgICAgIHNhdmVMYXN0Q2hhcigiICIpOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICghY2F0ZWdvcnkuaXNaZXJvV2lkdGhEaWFjcml0aWMgJiYgIWNvbXBhcmVXaXRoTGFzdFBvc2l0aW9uKHNjYWxlZERpbSkpIHsKICAgICAgICAgIGlmICghZm9udC52ZXJ0aWNhbCkgewogICAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dE1hdHJpeChzY2FsZWREaW0gKiB0ZXh0U3RhdGUudGV4dEhTY2FsZSwgMCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dE1hdHJpeCgwLCBzY2FsZWREaW0pOwogICAgICAgICAgfQogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHRleHRDaHVuayA9IGVuc3VyZVRleHRDb250ZW50SXRlbSgpOwogICAgICAgIGlmIChjYXRlZ29yeS5pc1plcm9XaWR0aERpYWNyaXRpYykgewogICAgICAgICAgc2NhbGVkRGltID0gMDsKICAgICAgICB9CiAgICAgICAgaWYgKCFmb250LnZlcnRpY2FsKSB7CiAgICAgICAgICBzY2FsZWREaW0gKj0gdGV4dFN0YXRlLnRleHRIU2NhbGU7CiAgICAgICAgICBpbnRlcnNlY3Rvcj8uYWRkR2x5cGgoZ2V0Q3VycmVudFRleHRUcmFuc2Zvcm0oKSwgc2NhbGVkRGltLCAwLCBnbHlwaC51bmljb2RlKTsKICAgICAgICAgIHRleHRTdGF0ZS50cmFuc2xhdGVUZXh0TWF0cml4KHNjYWxlZERpbSwgMCk7CiAgICAgICAgICB0ZXh0Q2h1bmsud2lkdGggKz0gc2NhbGVkRGltOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpbnRlcnNlY3Rvcj8uYWRkR2x5cGgoZ2V0Q3VycmVudFRleHRUcmFuc2Zvcm0oKSwgMCwgc2NhbGVkRGltLCBnbHlwaC51bmljb2RlKTsKICAgICAgICAgIHRleHRTdGF0ZS50cmFuc2xhdGVUZXh0TWF0cml4KDAsIHNjYWxlZERpbSk7CiAgICAgICAgICBzY2FsZWREaW0gPSBNYXRoLmFicyhzY2FsZWREaW0pOwogICAgICAgICAgdGV4dENodW5rLmhlaWdodCArPSBzY2FsZWREaW07CiAgICAgICAgfQogICAgICAgIGlmIChzY2FsZWREaW0pIHsKICAgICAgICAgIHRleHRDaHVuay5wcmV2VHJhbnNmb3JtID0gZ2V0Q3VycmVudFRleHRUcmFuc2Zvcm0oKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZ2x5cGhVbmljb2RlID0gZ2x5cGgudW5pY29kZTsKICAgICAgICBpZiAoc2F2ZUxhc3RDaGFyKGdseXBoVW5pY29kZSkpIHsKICAgICAgICAgIHRleHRDaHVuay5zdHIucHVzaCgiICIpOwogICAgICAgICAgaW50ZXJzZWN0b3I/LmFkZEV4dHJhQ2hhcigiICIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWludGVyc2VjdG9yKSB7CiAgICAgICAgICB0ZXh0Q2h1bmsuc3RyLnB1c2goZ2x5cGhVbmljb2RlKTsKICAgICAgICB9CiAgICAgICAgaWYgKGNoYXJTcGFjaW5nKSB7CiAgICAgICAgICBpZiAoIWZvbnQudmVydGljYWwpIHsKICAgICAgICAgICAgdGV4dFN0YXRlLnRyYW5zbGF0ZVRleHRNYXRyaXgoY2hhclNwYWNpbmcgKiB0ZXh0U3RhdGUudGV4dEhTY2FsZSwgMCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dE1hdHJpeCgwLCAtY2hhclNwYWNpbmcpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gYXBwZW5kRU9MKCkgewogICAgICBpbnRlcnNlY3Rvcj8uYWRkRXh0cmFDaGFyKCJcbiIpOwogICAgICByZXNldExhc3RDaGFycygpOwogICAgICBpZiAodGV4dENvbnRlbnRJdGVtLmluaXRpYWxpemVkKSB7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLmhhc0VPTCA9IHRydWU7CiAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0ZXh0Q29udGVudC5pdGVtcy5wdXNoKHsKICAgICAgICAgIHN0cjogIiIsCiAgICAgICAgICBkaXI6ICJsdHIiLAogICAgICAgICAgd2lkdGg6IDAsCiAgICAgICAgICBoZWlnaHQ6IDAsCiAgICAgICAgICB0cmFuc2Zvcm06IGdldEN1cnJlbnRUZXh0VHJhbnNmb3JtKCksCiAgICAgICAgICBmb250TmFtZTogdGV4dFN0YXRlLmxvYWRlZE5hbWUsCiAgICAgICAgICBoYXNFT0w6IHRydWUKICAgICAgICB9KTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gYWRkRmFrZVNwYWNlcyh3aWR0aCwgdHJhbnNmLCB0ZXh0T3JpZW50YXRpb24pIHsKICAgICAgaWYgKHRleHRPcmllbnRhdGlvbiAqIHRleHRDb250ZW50SXRlbS5zcGFjZUluRmxvd01pbiA8PSB3aWR0aCAmJiB3aWR0aCA8PSB0ZXh0T3JpZW50YXRpb24gKiB0ZXh0Q29udGVudEl0ZW0uc3BhY2VJbkZsb3dNYXgpIHsKICAgICAgICBpZiAodGV4dENvbnRlbnRJdGVtLmluaXRpYWxpemVkKSB7CiAgICAgICAgICByZXNldExhc3RDaGFycygpOwogICAgICAgICAgdGV4dENvbnRlbnRJdGVtLnN0ci5wdXNoKCIgIik7CiAgICAgICAgICBpbnRlcnNlY3Rvcj8uYWRkRXh0cmFDaGFyKCIgIik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBjb25zdCBmb250TmFtZSA9IHRleHRDb250ZW50SXRlbS5mb250TmFtZTsKICAgICAgbGV0IGhlaWdodCA9IDA7CiAgICAgIGlmICh0ZXh0Q29udGVudEl0ZW0udmVydGljYWwpIHsKICAgICAgICBoZWlnaHQgPSB3aWR0aDsKICAgICAgICB3aWR0aCA9IDA7CiAgICAgIH0KICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgcmVzZXRMYXN0Q2hhcnMoKTsKICAgICAgcHVzaFdoaXRlc3BhY2UoewogICAgICAgIHdpZHRoOiBNYXRoLmFicyh3aWR0aCksCiAgICAgICAgaGVpZ2h0OiBNYXRoLmFicyhoZWlnaHQpLAogICAgICAgIHRyYW5zZm9ybTogdHJhbnNmIHx8IGdldEN1cnJlbnRUZXh0VHJhbnNmb3JtKCksCiAgICAgICAgZm9udE5hbWUKICAgICAgfSk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgZnVuY3Rpb24gZmx1c2hUZXh0Q29udGVudEl0ZW0oKSB7CiAgICAgIGlmICghdGV4dENvbnRlbnRJdGVtLmluaXRpYWxpemVkIHx8ICF0ZXh0Q29udGVudEl0ZW0uc3RyKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICghdGV4dENvbnRlbnRJdGVtLnZlcnRpY2FsKSB7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLnRvdGFsV2lkdGggKz0gdGV4dENvbnRlbnRJdGVtLndpZHRoICogdGV4dENvbnRlbnRJdGVtLnRleHRBZHZhbmNlU2NhbGU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLnRvdGFsSGVpZ2h0ICs9IHRleHRDb250ZW50SXRlbS5oZWlnaHQgKiB0ZXh0Q29udGVudEl0ZW0udGV4dEFkdmFuY2VTY2FsZTsKICAgICAgfQogICAgICB0ZXh0Q29udGVudC5pdGVtcy5wdXNoKHJ1bkJpZGlUcmFuc2Zvcm0odGV4dENvbnRlbnRJdGVtKSk7CiAgICAgIHRleHRDb250ZW50SXRlbS5pbml0aWFsaXplZCA9IGZhbHNlOwogICAgICB0ZXh0Q29udGVudEl0ZW0uc3RyLmxlbmd0aCA9IDA7CiAgICB9CiAgICBmdW5jdGlvbiBlbnF1ZXVlQ2h1bmsoYmF0Y2ggPSBmYWxzZSkgewogICAgICBjb25zdCBsZW5ndGggPSB0ZXh0Q29udGVudC5pdGVtcy5sZW5ndGg7CiAgICAgIGlmIChsZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKGJhdGNoICYmIGxlbmd0aCA8IFRFWFRfQ0hVTktfQkFUQ0hfU0laRSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBzaW5rPy5lbnF1ZXVlKHRleHRDb250ZW50LCBsZW5ndGgpOwogICAgICB0ZXh0Q29udGVudC5pdGVtcyA9IFtdOwogICAgICB0ZXh0Q29udGVudC5zdHlsZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgfQogICAgY29uc3QgdGltZVNsb3RNYW5hZ2VyID0gbmV3IFRpbWVTbG90TWFuYWdlcigpOwogICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIHByb21pc2VCb2R5KHJlc29sdmUsIHJlamVjdCkgewogICAgICBjb25zdCBuZXh0ID0gZnVuY3Rpb24gKHByb21pc2UpIHsKICAgICAgICBlbnF1ZXVlQ2h1bmsodHJ1ZSk7CiAgICAgICAgUHJvbWlzZS5hbGwoW3Byb21pc2UsIHNpbms/LnJlYWR5XSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBwcm9taXNlQm9keShyZXNvbHZlLCByZWplY3QpOwogICAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgICAgcmVqZWN0KGV4KTsKICAgICAgICAgIH0KICAgICAgICB9LCByZWplY3QpOwogICAgICB9OwogICAgICB0YXNrLmVuc3VyZU5vdFRlcm1pbmF0ZWQoKTsKICAgICAgdGltZVNsb3RNYW5hZ2VyLnJlc2V0KCk7CiAgICAgIGNvbnN0IG9wZXJhdGlvbiA9IHt9OwogICAgICBsZXQgc3RvcCwKICAgICAgICBuYW1lLAogICAgICAgIGlzVmFsaWROYW1lLAogICAgICAgIGFyZ3MgPSBbXTsKICAgICAgd2hpbGUgKCEoc3RvcCA9IHRpbWVTbG90TWFuYWdlci5jaGVjaygpKSkgewogICAgICAgIGFyZ3MubGVuZ3RoID0gMDsKICAgICAgICBvcGVyYXRpb24uYXJncyA9IGFyZ3M7CiAgICAgICAgaWYgKCFwcmVwcm9jZXNzb3IucmVhZChvcGVyYXRpb24pKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgY29uc3QgcHJldmlvdXNTdGF0ZSA9IHRleHRTdGF0ZTsKICAgICAgICB0ZXh0U3RhdGUgPSBzdGF0ZU1hbmFnZXIuc3RhdGU7CiAgICAgICAgY29uc3QgZm4gPSBvcGVyYXRpb24uZm47CiAgICAgICAgYXJncyA9IG9wZXJhdGlvbi5hcmdzOwogICAgICAgIHN3aXRjaCAoZm4gfCAwKSB7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGb250OgogICAgICAgICAgICBjb25zdCBmb250TmFtZUFyZyA9IGFyZ3NbMF0ubmFtZSwKICAgICAgICAgICAgICBmb250U2l6ZUFyZyA9IGFyZ3NbMV07CiAgICAgICAgICAgIGlmICh0ZXh0U3RhdGUuZm9udCAmJiBmb250TmFtZUFyZyA9PT0gdGV4dFN0YXRlLmZvbnROYW1lICYmIGZvbnRTaXplQXJnID09PSB0ZXh0U3RhdGUuZm9udFNpemUpIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgICAgICB0ZXh0U3RhdGUuZm9udE5hbWUgPSBmb250TmFtZUFyZzsKICAgICAgICAgICAgdGV4dFN0YXRlLmZvbnRTaXplID0gZm9udFNpemVBcmc7CiAgICAgICAgICAgIG5leHQoaGFuZGxlU2V0Rm9udChmb250TmFtZUFyZywgbnVsbCkpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICBjYXNlIE9QUy5zZXRUZXh0UmlzZToKICAgICAgICAgICAgdGV4dFN0YXRlLnRleHRSaXNlID0gYXJnc1swXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRIU2NhbGU6CiAgICAgICAgICAgIHRleHRTdGF0ZS50ZXh0SFNjYWxlID0gYXJnc1swXSAvIDEwMDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRMZWFkaW5nOgogICAgICAgICAgICB0ZXh0U3RhdGUubGVhZGluZyA9IGFyZ3NbMF07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMubW92ZVRleHQ6CiAgICAgICAgICAgIHRleHRTdGF0ZS50cmFuc2xhdGVUZXh0TGluZU1hdHJpeChhcmdzWzBdLCBhcmdzWzFdKTsKICAgICAgICAgICAgdGV4dFN0YXRlLnRleHRNYXRyaXggPSB0ZXh0U3RhdGUudGV4dExpbmVNYXRyaXguc2xpY2UoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRMZWFkaW5nTW92ZVRleHQ6CiAgICAgICAgICAgIHRleHRTdGF0ZS5sZWFkaW5nID0gLWFyZ3NbMV07CiAgICAgICAgICAgIHRleHRTdGF0ZS50cmFuc2xhdGVUZXh0TGluZU1hdHJpeChhcmdzWzBdLCBhcmdzWzFdKTsKICAgICAgICAgICAgdGV4dFN0YXRlLnRleHRNYXRyaXggPSB0ZXh0U3RhdGUudGV4dExpbmVNYXRyaXguc2xpY2UoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5uZXh0TGluZToKICAgICAgICAgICAgdGV4dFN0YXRlLmNhcnJpYWdlUmV0dXJuKCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0VGV4dE1hdHJpeDoKICAgICAgICAgICAgdGV4dFN0YXRlLnNldFRleHRNYXRyaXgoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSwgYXJnc1s1XSk7CiAgICAgICAgICAgIHRleHRTdGF0ZS5zZXRUZXh0TGluZU1hdHJpeChhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdLCBhcmdzWzNdLCBhcmdzWzRdLCBhcmdzWzVdKTsKICAgICAgICAgICAgdXBkYXRlQWR2YW5jZVNjYWxlKCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0Q2hhclNwYWNpbmc6CiAgICAgICAgICAgIHRleHRTdGF0ZS5jaGFyU3BhY2luZyA9IGFyZ3NbMF07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0V29yZFNwYWNpbmc6CiAgICAgICAgICAgIHRleHRTdGF0ZS53b3JkU3BhY2luZyA9IGFyZ3NbMF07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuYmVnaW5UZXh0OgogICAgICAgICAgICB0ZXh0U3RhdGUudGV4dE1hdHJpeCA9IElERU5USVRZX01BVFJJWC5zbGljZSgpOwogICAgICAgICAgICB0ZXh0U3RhdGUudGV4dExpbmVNYXRyaXggPSBJREVOVElUWV9NQVRSSVguc2xpY2UoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zaG93U3BhY2VkVGV4dDoKICAgICAgICAgICAgaWYgKCFzdGF0ZU1hbmFnZXIuc3RhdGUuZm9udCkgewogICAgICAgICAgICAgIHNlbGYuZW5zdXJlU3RhdGVGb250KHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3Qgc3BhY2VGYWN0b3IgPSAodGV4dFN0YXRlLmZvbnQudmVydGljYWwgPyAxIDogLTEpICogdGV4dFN0YXRlLmZvbnRTaXplIC8gMTAwMDsKICAgICAgICAgICAgY29uc3QgZWxlbWVudHMgPSBhcmdzWzBdOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBlbGVtZW50cy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICAgICAgY29uc3QgaXRlbSA9IGVsZW1lbnRzW2ldOwogICAgICAgICAgICAgIGlmICh0eXBlb2YgaXRlbSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICAgIHNob3dTcGFjZWRUZXh0QnVmZmVyLnB1c2goaXRlbSk7CiAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgaXRlbSA9PT0gIm51bWJlciIgJiYgaXRlbSAhPT0gMCkgewogICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gc2hvd1NwYWNlZFRleHRCdWZmZXIuam9pbigiIik7CiAgICAgICAgICAgICAgICBzaG93U3BhY2VkVGV4dEJ1ZmZlci5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgYnVpbGRUZXh0Q29udGVudEl0ZW0oewogICAgICAgICAgICAgICAgICBjaGFyczogc3RyLAogICAgICAgICAgICAgICAgICBleHRyYVNwYWNpbmc6IGl0ZW0gKiBzcGFjZUZhY3RvcgogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChzaG93U3BhY2VkVGV4dEJ1ZmZlci5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgY29uc3Qgc3RyID0gc2hvd1NwYWNlZFRleHRCdWZmZXIuam9pbigiIik7CiAgICAgICAgICAgICAgc2hvd1NwYWNlZFRleHRCdWZmZXIubGVuZ3RoID0gMDsKICAgICAgICAgICAgICBidWlsZFRleHRDb250ZW50SXRlbSh7CiAgICAgICAgICAgICAgICBjaGFyczogc3RyLAogICAgICAgICAgICAgICAgZXh0cmFTcGFjaW5nOiAwCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zaG93VGV4dDoKICAgICAgICAgICAgaWYgKCFzdGF0ZU1hbmFnZXIuc3RhdGUuZm9udCkgewogICAgICAgICAgICAgIHNlbGYuZW5zdXJlU3RhdGVGb250KHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnVpbGRUZXh0Q29udGVudEl0ZW0oewogICAgICAgICAgICAgIGNoYXJzOiBhcmdzWzBdLAogICAgICAgICAgICAgIGV4dHJhU3BhY2luZzogMAogICAgICAgICAgICB9KTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5uZXh0TGluZVNob3dUZXh0OgogICAgICAgICAgICBpZiAoIXN0YXRlTWFuYWdlci5zdGF0ZS5mb250KSB7CiAgICAgICAgICAgICAgc2VsZi5lbnN1cmVTdGF0ZUZvbnQoc3RhdGVNYW5hZ2VyLnN0YXRlKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0ZXh0U3RhdGUuY2FycmlhZ2VSZXR1cm4oKTsKICAgICAgICAgICAgYnVpbGRUZXh0Q29udGVudEl0ZW0oewogICAgICAgICAgICAgIGNoYXJzOiBhcmdzWzBdLAogICAgICAgICAgICAgIGV4dHJhU3BhY2luZzogMAogICAgICAgICAgICB9KTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5uZXh0TGluZVNldFNwYWNpbmdTaG93VGV4dDoKICAgICAgICAgICAgaWYgKCFzdGF0ZU1hbmFnZXIuc3RhdGUuZm9udCkgewogICAgICAgICAgICAgIHNlbGYuZW5zdXJlU3RhdGVGb250KHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGV4dFN0YXRlLndvcmRTcGFjaW5nID0gYXJnc1swXTsKICAgICAgICAgICAgdGV4dFN0YXRlLmNoYXJTcGFjaW5nID0gYXJnc1sxXTsKICAgICAgICAgICAgdGV4dFN0YXRlLmNhcnJpYWdlUmV0dXJuKCk7CiAgICAgICAgICAgIGJ1aWxkVGV4dENvbnRlbnRJdGVtKHsKICAgICAgICAgICAgICBjaGFyczogYXJnc1syXSwKICAgICAgICAgICAgICBleHRyYVNwYWNpbmc6IDAKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMucGFpbnRYT2JqZWN0OgogICAgICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgICAgICB4b2JqcyA/Pz0gcmVzb3VyY2VzLmdldCgiWE9iamVjdCIpIHx8IERpY3QuZW1wdHk7CiAgICAgICAgICAgIGlzVmFsaWROYW1lID0gYXJnc1swXSBpbnN0YW5jZW9mIE5hbWU7CiAgICAgICAgICAgIG5hbWUgPSBhcmdzWzBdLm5hbWU7CiAgICAgICAgICAgIGlmIChpc1ZhbGlkTmFtZSAmJiBlbXB0eVhPYmplY3RDYWNoZS5nZXRCeU5hbWUobmFtZSkpIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBuZXh0KG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlWE9iamVjdCwgcmVqZWN0WE9iamVjdCkgewogICAgICAgICAgICAgIGlmICghaXNWYWxpZE5hbWUpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiWE9iamVjdCBtdXN0IGJlIHJlZmVycmVkIHRvIGJ5IG5hbWUuIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGxldCB4b2JqID0geG9ianMuZ2V0UmF3KG5hbWUpOwogICAgICAgICAgICAgIGlmICh4b2JqIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICAgICAgICBpZiAoZW1wdHlYT2JqZWN0Q2FjaGUuZ2V0QnlSZWYoeG9iaikpIHsKICAgICAgICAgICAgICAgICAgcmVzb2x2ZVhPYmplY3QoKTsKICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY29uc3QgZ2xvYmFsSW1hZ2UgPSBzZWxmLmdsb2JhbEltYWdlQ2FjaGUuZ2V0RGF0YSh4b2JqLCBzZWxmLnBhZ2VJbmRleCk7CiAgICAgICAgICAgICAgICBpZiAoZ2xvYmFsSW1hZ2UpIHsKICAgICAgICAgICAgICAgICAgcmVzb2x2ZVhPYmplY3QoKTsKICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgeG9iaiA9IHhyZWYuZmV0Y2goeG9iaik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICghKHhvYmogaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJYT2JqZWN0IHNob3VsZCBiZSBhIHN0cmVhbSIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICBkaWN0CiAgICAgICAgICAgICAgfSA9IHhvYmo7CiAgICAgICAgICAgICAgY29uc3QgdHlwZSA9IGRpY3QuZ2V0KCJTdWJ0eXBlIik7CiAgICAgICAgICAgICAgaWYgKCEodHlwZSBpbnN0YW5jZW9mIE5hbWUpKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlhPYmplY3Qgc2hvdWxkIGhhdmUgYSBOYW1lIHN1YnR5cGUiKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHR5cGUubmFtZSAhPT0gIkZvcm0iKSB7CiAgICAgICAgICAgICAgICBlbXB0eVhPYmplY3RDYWNoZS5zZXQobmFtZSwgZGljdC5vYmpJZCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICByZXNvbHZlWE9iamVjdCgpOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCBjdXJyZW50U3RhdGUgPSBzdGF0ZU1hbmFnZXIuc3RhdGUuY2xvbmUoKTsKICAgICAgICAgICAgICBjb25zdCB4T2JqU3RhdGVNYW5hZ2VyID0gbmV3IFN0YXRlTWFuYWdlcihjdXJyZW50U3RhdGUpOwogICAgICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IGxvb2t1cE1hdHJpeChkaWN0LmdldEFycmF5KCJNYXRyaXgiKSwgbnVsbCk7CiAgICAgICAgICAgICAgaWYgKG1hdHJpeCkgewogICAgICAgICAgICAgICAgeE9ialN0YXRlTWFuYWdlci50cmFuc2Zvcm0obWF0cml4KTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgbG9jYWxSZXNvdXJjZXMgPSBkaWN0LmdldCgiUmVzb3VyY2VzIik7CiAgICAgICAgICAgICAgZW5xdWV1ZUNodW5rKCk7CiAgICAgICAgICAgICAgY29uc3Qgc2lua1dyYXBwZXIgPSB7CiAgICAgICAgICAgICAgICBlbnF1ZXVlSW52b2tlZDogZmFsc2UsCiAgICAgICAgICAgICAgICBlbnF1ZXVlKGNodW5rLCBzaXplKSB7CiAgICAgICAgICAgICAgICAgIHRoaXMuZW5xdWV1ZUludm9rZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICBzaW5rLmVucXVldWUoY2h1bmssIHNpemUpOwogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIGdldCBkZXNpcmVkU2l6ZSgpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuIHNpbmsuZGVzaXJlZFNpemUgPz8gMDsKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICBnZXQgcmVhZHkoKSB7CiAgICAgICAgICAgICAgICAgIHJldHVybiBzaW5rLnJlYWR5OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgc2VsZi5nZXRUZXh0Q29udGVudCh7CiAgICAgICAgICAgICAgICBzdHJlYW06IHhvYmosCiAgICAgICAgICAgICAgICB0YXNrLAogICAgICAgICAgICAgICAgcmVzb3VyY2VzOiBsb2NhbFJlc291cmNlcyBpbnN0YW5jZW9mIERpY3QgPyBsb2NhbFJlc291cmNlcyA6IHJlc291cmNlcywKICAgICAgICAgICAgICAgIHN0YXRlTWFuYWdlcjogeE9ialN0YXRlTWFuYWdlciwKICAgICAgICAgICAgICAgIGluY2x1ZGVNYXJrZWRDb250ZW50LAogICAgICAgICAgICAgICAgc2luazogc2luayAmJiBzaW5rV3JhcHBlciwKICAgICAgICAgICAgICAgIHNlZW5TdHlsZXMsCiAgICAgICAgICAgICAgICB2aWV3Qm94LAogICAgICAgICAgICAgICAgbGFuZywKICAgICAgICAgICAgICAgIG1hcmtlZENvbnRlbnREYXRhLAogICAgICAgICAgICAgICAgZGlzYWJsZU5vcm1hbGl6YXRpb24sCiAgICAgICAgICAgICAgICBrZWVwV2hpdGVTcGFjZSwKICAgICAgICAgICAgICAgIHByZXZSZWZzOiBzZWVuUmVmcwogICAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgaWYgKCFzaW5rV3JhcHBlci5lbnF1ZXVlSW52b2tlZCkgewogICAgICAgICAgICAgICAgICBlbXB0eVhPYmplY3RDYWNoZS5zZXQobmFtZSwgZGljdC5vYmpJZCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXNvbHZlWE9iamVjdCgpOwogICAgICAgICAgICAgIH0sIHJlamVjdFhPYmplY3QpOwogICAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIEFib3J0RXhjZXB0aW9uKSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChzZWxmLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgICAgICAgICB3YXJuKGBnZXRUZXh0Q29udGVudCAtIGlnbm9yaW5nIFhPYmplY3Q6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0aHJvdyByZWFzb247CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgY2FzZSBPUFMuc2V0R1N0YXRlOgogICAgICAgICAgICBpc1ZhbGlkTmFtZSA9IGFyZ3NbMF0gaW5zdGFuY2VvZiBOYW1lOwogICAgICAgICAgICBuYW1lID0gYXJnc1swXS5uYW1lOwogICAgICAgICAgICBpZiAoaXNWYWxpZE5hbWUgJiYgZW1wdHlHU3RhdGVDYWNoZS5nZXRCeU5hbWUobmFtZSkpIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBuZXh0KG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlR1N0YXRlLCByZWplY3RHU3RhdGUpIHsKICAgICAgICAgICAgICBpZiAoIWlzVmFsaWROYW1lKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkdTdGF0ZSBtdXN0IGJlIHJlZmVycmVkIHRvIGJ5IG5hbWUuIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNvbnN0IGV4dEdTdGF0ZSA9IHJlc291cmNlcy5nZXQoIkV4dEdTdGF0ZSIpOwogICAgICAgICAgICAgIGlmICghKGV4dEdTdGF0ZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkV4dEdTdGF0ZSBzaG91bGQgYmUgYSBkaWN0aW9uYXJ5LiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCBnU3RhdGUgPSBleHRHU3RhdGUuZ2V0KG5hbWUpOwogICAgICAgICAgICAgIGlmICghKGdTdGF0ZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkdTdGF0ZSBzaG91bGQgYmUgYSBkaWN0aW9uYXJ5LiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCBnU3RhdGVGb250ID0gZ1N0YXRlLmdldCgiRm9udCIpOwogICAgICAgICAgICAgIGlmICghZ1N0YXRlRm9udCkgewogICAgICAgICAgICAgICAgZW1wdHlHU3RhdGVDYWNoZS5zZXQobmFtZSwgZ1N0YXRlLm9iaklkLCB0cnVlKTsKICAgICAgICAgICAgICAgIHJlc29sdmVHU3RhdGUoKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICAgICAgICB0ZXh0U3RhdGUuZm9udE5hbWUgPSBudWxsOwogICAgICAgICAgICAgIHRleHRTdGF0ZS5mb250U2l6ZSA9IGdTdGF0ZUZvbnRbMV07CiAgICAgICAgICAgICAgaGFuZGxlU2V0Rm9udChudWxsLCBnU3RhdGVGb250WzBdKS50aGVuKHJlc29sdmVHU3RhdGUsIHJlamVjdEdTdGF0ZSk7CiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24pIHsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHNlbGYub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgICAgICAgIHdhcm4oYGdldFRleHRDb250ZW50IC0gaWdub3JpbmcgRXh0R1N0YXRlOiAiJHtyZWFzb259Ii5gKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGhyb3cgcmVhc29uOwogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIGNhc2UgT1BTLmJlZ2luTWFya2VkQ29udGVudDoKICAgICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICAgICAgaWYgKGluY2x1ZGVNYXJrZWRDb250ZW50KSB7CiAgICAgICAgICAgICAgbWFya2VkQ29udGVudERhdGEubGV2ZWwrKzsKICAgICAgICAgICAgICB0ZXh0Q29udGVudC5pdGVtcy5wdXNoKHsKICAgICAgICAgICAgICAgIHR5cGU6ICJiZWdpbk1hcmtlZENvbnRlbnQiLAogICAgICAgICAgICAgICAgdGFnOiBhcmdzWzBdIGluc3RhbmNlb2YgTmFtZSA/IGFyZ3NbMF0ubmFtZSA6IG51bGwKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLmJlZ2luTWFya2VkQ29udGVudFByb3BzOgogICAgICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgICAgICBpZiAoaW5jbHVkZU1hcmtlZENvbnRlbnQpIHsKICAgICAgICAgICAgICBtYXJrZWRDb250ZW50RGF0YS5sZXZlbCsrOwogICAgICAgICAgICAgIGxldCBtY2lkID0gbnVsbDsKICAgICAgICAgICAgICBpZiAoYXJnc1sxXSBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICAgICAgICAgIG1jaWQgPSBhcmdzWzFdLmdldCgiTUNJRCIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0ZXh0Q29udGVudC5pdGVtcy5wdXNoKHsKICAgICAgICAgICAgICAgIHR5cGU6ICJiZWdpbk1hcmtlZENvbnRlbnRQcm9wcyIsCiAgICAgICAgICAgICAgICBpZDogTnVtYmVyLmlzSW50ZWdlcihtY2lkKSA/IGAke3NlbGYuaWRGYWN0b3J5LmdldFBhZ2VPYmpJZCgpfV9tYyR7bWNpZH1gIDogbnVsbCwKICAgICAgICAgICAgICAgIHRhZzogYXJnc1swXSBpbnN0YW5jZW9mIE5hbWUgPyBhcmdzWzBdLm5hbWUgOiBudWxsCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5lbmRNYXJrZWRDb250ZW50OgogICAgICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgICAgICBpZiAoaW5jbHVkZU1hcmtlZENvbnRlbnQpIHsKICAgICAgICAgICAgICBpZiAobWFya2VkQ29udGVudERhdGEubGV2ZWwgPT09IDApIHsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBtYXJrZWRDb250ZW50RGF0YS5sZXZlbC0tOwogICAgICAgICAgICAgIHRleHRDb250ZW50Lml0ZW1zLnB1c2goewogICAgICAgICAgICAgICAgdHlwZTogImVuZE1hcmtlZENvbnRlbnQiCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5yZXN0b3JlOgogICAgICAgICAgICBpZiAocHJldmlvdXNTdGF0ZSAmJiAocHJldmlvdXNTdGF0ZS5mb250ICE9PSB0ZXh0U3RhdGUuZm9udCB8fCBwcmV2aW91c1N0YXRlLmZvbnRTaXplICE9PSB0ZXh0U3RhdGUuZm9udFNpemUgfHwgcHJldmlvdXNTdGF0ZS5mb250TmFtZSAhPT0gdGV4dFN0YXRlLmZvbnROYW1lKSkgewogICAgICAgICAgICAgIGZsdXNoVGV4dENvbnRlbnRJdGVtKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmICh0ZXh0Q29udGVudC5pdGVtcy5sZW5ndGggPj0gKHNpbms/LmRlc2lyZWRTaXplID8/IDEpKSB7CiAgICAgICAgICBzdG9wID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoc3RvcCkgewogICAgICAgIG5leHQoZGVmZXJyZWQpOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICBlbnF1ZXVlQ2h1bmsoKTsKICAgICAgcmVzb2x2ZSgpOwogICAgfSkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIEFib3J0RXhjZXB0aW9uKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgd2FybihgZ2V0VGV4dENvbnRlbnQgLSBpZ25vcmluZyBlcnJvcnMgZHVyaW5nICIke3Rhc2submFtZX0iIGAgKyBgdGFzazogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICBlbnF1ZXVlQ2h1bmsoKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhyb3cgcmVhc29uOwogICAgfSk7CiAgfQogIGFzeW5jIGV4dHJhY3REYXRhU3RydWN0dXJlcyhkaWN0LCBwcm9wZXJ0aWVzKSB7CiAgICBjb25zdCB4cmVmID0gdGhpcy54cmVmOwogICAgbGV0IGNpZFRvR2lkQnl0ZXM7CiAgICBjb25zdCB0b1VuaWNvZGVQcm9taXNlID0gdGhpcy5yZWFkVG9Vbmljb2RlKHByb3BlcnRpZXMudG9Vbmljb2RlKTsKICAgIGlmIChwcm9wZXJ0aWVzLmNvbXBvc2l0ZSkgewogICAgICBjb25zdCBjaWRTeXN0ZW1JbmZvID0gZGljdC5nZXQoIkNJRFN5c3RlbUluZm8iKTsKICAgICAgaWYgKGNpZFN5c3RlbUluZm8gaW5zdGFuY2VvZiBEaWN0ICYmICFwcm9wZXJ0aWVzLmNpZFN5c3RlbUluZm8pIHsKICAgICAgICBwcm9wZXJ0aWVzLmNpZFN5c3RlbUluZm8gPSB7CiAgICAgICAgICByZWdpc3RyeTogc3RyaW5nVG9QREZTdHJpbmcoY2lkU3lzdGVtSW5mby5nZXQoIlJlZ2lzdHJ5IikpLAogICAgICAgICAgb3JkZXJpbmc6IHN0cmluZ1RvUERGU3RyaW5nKGNpZFN5c3RlbUluZm8uZ2V0KCJPcmRlcmluZyIpKSwKICAgICAgICAgIHN1cHBsZW1lbnQ6IGNpZFN5c3RlbUluZm8uZ2V0KCJTdXBwbGVtZW50IikKICAgICAgICB9OwogICAgICB9CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3QgY2lkVG9HaWRNYXAgPSBkaWN0LmdldCgiQ0lEVG9HSURNYXAiKTsKICAgICAgICBpZiAoY2lkVG9HaWRNYXAgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgICAgICBjaWRUb0dpZEJ5dGVzID0gY2lkVG9HaWRNYXAuZ2V0Qnl0ZXMoKTsKICAgICAgICB9CiAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgaWYgKCF0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgICB0aHJvdyBleDsKICAgICAgICB9CiAgICAgICAgd2FybihgZXh0cmFjdERhdGFTdHJ1Y3R1cmVzIC0gaWdub3JpbmcgQ0lEVG9HSURNYXAgZGF0YTogIiR7ZXh9Ii5gKTsKICAgICAgfQogICAgfQogICAgY29uc3QgZGlmZmVyZW5jZXMgPSBbXTsKICAgIGxldCBiYXNlRW5jb2RpbmdOYW1lID0gbnVsbDsKICAgIGxldCBlbmNvZGluZzsKICAgIGlmIChkaWN0LmhhcygiRW5jb2RpbmciKSkgewogICAgICBlbmNvZGluZyA9IGRpY3QuZ2V0KCJFbmNvZGluZyIpOwogICAgICBpZiAoZW5jb2RpbmcgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgICAgYmFzZUVuY29kaW5nTmFtZSA9IGVuY29kaW5nLmdldCgiQmFzZUVuY29kaW5nIik7CiAgICAgICAgYmFzZUVuY29kaW5nTmFtZSA9IGJhc2VFbmNvZGluZ05hbWUgaW5zdGFuY2VvZiBOYW1lID8gYmFzZUVuY29kaW5nTmFtZS5uYW1lIDogbnVsbDsKICAgICAgICBpZiAoZW5jb2RpbmcuaGFzKCJEaWZmZXJlbmNlcyIpKSB7CiAgICAgICAgICBjb25zdCBkaWZmRW5jb2RpbmcgPSBlbmNvZGluZy5nZXQoIkRpZmZlcmVuY2VzIik7CiAgICAgICAgICBsZXQgaW5kZXggPSAwOwogICAgICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiBkaWZmRW5jb2RpbmcpIHsKICAgICAgICAgICAgY29uc3QgZGF0YSA9IHhyZWYuZmV0Y2hJZlJlZihlbnRyeSk7CiAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gIm51bWJlciIpIHsKICAgICAgICAgICAgICBpbmRleCA9IGRhdGE7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoZGF0YSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgICAgICBkaWZmZXJlbmNlc1tpbmRleCsrXSA9IGRhdGEubmFtZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgZW50cnkgaW4gJ0RpZmZlcmVuY2VzJyBhcnJheTogJHtkYXRhfWApOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGVuY29kaW5nIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgIGJhc2VFbmNvZGluZ05hbWUgPSBlbmNvZGluZy5uYW1lOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IG1zZyA9ICJFbmNvZGluZyBpcyBub3QgYSBOYW1lIG5vciBhIERpY3QiOwogICAgICAgIGlmICghdGhpcy5vcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKG1zZyk7CiAgICAgICAgfQogICAgICAgIHdhcm4obXNnKTsKICAgICAgfQogICAgICBpZiAoYmFzZUVuY29kaW5nTmFtZSAhPT0gIk1hY1JvbWFuRW5jb2RpbmciICYmIGJhc2VFbmNvZGluZ05hbWUgIT09ICJNYWNFeHBlcnRFbmNvZGluZyIgJiYgYmFzZUVuY29kaW5nTmFtZSAhPT0gIldpbkFuc2lFbmNvZGluZyIpIHsKICAgICAgICBiYXNlRW5jb2RpbmdOYW1lID0gbnVsbDsKICAgICAgfQogICAgfQogICAgY29uc3Qgbm9uRW1iZWRkZWRGb250ID0gIXByb3BlcnRpZXMuZmlsZSB8fCBwcm9wZXJ0aWVzLmlzSW50ZXJuYWxGb250LAogICAgICBpc1N5bWJvbHNGb250TmFtZSA9IGdldFN5bWJvbHNGb250cygpW3Byb3BlcnRpZXMubmFtZV07CiAgICBpZiAoYmFzZUVuY29kaW5nTmFtZSAmJiBub25FbWJlZGRlZEZvbnQgJiYgaXNTeW1ib2xzRm9udE5hbWUpIHsKICAgICAgYmFzZUVuY29kaW5nTmFtZSA9IG51bGw7CiAgICB9CiAgICBpZiAoYmFzZUVuY29kaW5nTmFtZSA9PT0gIldpbkFuc2lFbmNvZGluZyIgJiYgbm9uRW1iZWRkZWRGb250ICYmIHByb3BlcnRpZXMubmFtZT8uY2hhckNvZGVBdCgwKSA+PSAweGI3KSB7CiAgICAgIGNvbnN0IGZvbnROYW1lID0gcHJvcGVydGllcy5uYW1lOwogICAgICBjb25zdCBjaGluZXNlRm9udE5hbWVzID0gWyJceENCXHhDRVx4Q0NceEU1IiwgIlx4QkFceERBXHhDQ1x4RTUiLCAiXHhCRlx4QUNceENDXHhFNSIsICJceEI3XHhDMlx4Q0JceENFIiwgIlx4QkZceEFDXHhDQ1x4RTVfR0IyMzEyIiwgIlx4QjdceEMyXHhDQlx4Q0VfR0IyMzEyIiwgIlx4QzFceEE1XHhDQVx4RTkiLCAiXHhEMFx4QzJceENCXHhDRSJdOwogICAgICBpZiAoY2hpbmVzZUZvbnROYW1lcy5pbmNsdWRlcyhmb250TmFtZSkpIHsKICAgICAgICBiYXNlRW5jb2RpbmdOYW1lID0gbnVsbDsKICAgICAgICBwcm9wZXJ0aWVzLmRlZmF1bHRFbmNvZGluZyA9ICJBZG9iZS1HQjEtVUNTMiI7CiAgICAgICAgcHJvcGVydGllcy5jb21wb3NpdGUgPSB0cnVlOwogICAgICAgIHByb3BlcnRpZXMuY2lkRW5jb2RpbmcgPSBOYW1lLmdldCgiR0JLLUVVQy1IIik7CiAgICAgICAgY29uc3QgY01hcCA9IGF3YWl0IENNYXBGYWN0b3J5LmNyZWF0ZSh7CiAgICAgICAgICBlbmNvZGluZzogcHJvcGVydGllcy5jaWRFbmNvZGluZywKICAgICAgICAgIGZldGNoQnVpbHRJbkNNYXA6IHRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCwKICAgICAgICAgIHVzZUNNYXA6IG51bGwKICAgICAgICB9KTsKICAgICAgICBwcm9wZXJ0aWVzLmNNYXAgPSBjTWFwOwogICAgICAgIHByb3BlcnRpZXMudmVydGljYWwgPSBwcm9wZXJ0aWVzLmNNYXAudmVydGljYWw7CiAgICAgICAgcHJvcGVydGllcy5jaWRTeXN0ZW1JbmZvID0gewogICAgICAgICAgcmVnaXN0cnk6ICJBZG9iZSIsCiAgICAgICAgICBvcmRlcmluZzogIkdCMSIsCiAgICAgICAgICBzdXBwbGVtZW50OiAwCiAgICAgICAgfTsKICAgICAgfQogICAgfQogICAgaWYgKGJhc2VFbmNvZGluZ05hbWUpIHsKICAgICAgcHJvcGVydGllcy5kZWZhdWx0RW5jb2RpbmcgPSBnZXRFbmNvZGluZyhiYXNlRW5jb2RpbmdOYW1lKTsKICAgIH0gZWxzZSB7CiAgICAgIGxldCBpc1N5bWJvbGljRm9udCA9ICEhKHByb3BlcnRpZXMuZmxhZ3MgJiBGb250RmxhZ3MuU3ltYm9saWMpOwogICAgICBjb25zdCBpc05vbnN5bWJvbGljRm9udCA9ICEhKHByb3BlcnRpZXMuZmxhZ3MgJiBGb250RmxhZ3MuTm9uc3ltYm9saWMpOwogICAgICBpZiAocHJvcGVydGllcy50eXBlID09PSAiVHJ1ZVR5cGUiICYmIGlzU3ltYm9saWNGb250ICYmIGlzTm9uc3ltYm9saWNGb250ICYmIGRpZmZlcmVuY2VzLmxlbmd0aCAhPT0gMCkgewogICAgICAgIHByb3BlcnRpZXMuZmxhZ3MgJj0gfkZvbnRGbGFncy5TeW1ib2xpYzsKICAgICAgICBpc1N5bWJvbGljRm9udCA9IGZhbHNlOwogICAgICB9CiAgICAgIGVuY29kaW5nID0gU3RhbmRhcmRFbmNvZGluZzsKICAgICAgaWYgKHByb3BlcnRpZXMudHlwZSA9PT0gIlRydWVUeXBlIiAmJiAhaXNOb25zeW1ib2xpY0ZvbnQpIHsKICAgICAgICBlbmNvZGluZyA9IFdpbkFuc2lFbmNvZGluZzsKICAgICAgfQogICAgICBpZiAoaXNTeW1ib2xpY0ZvbnQgfHwgaXNTeW1ib2xzRm9udE5hbWUpIHsKICAgICAgICBlbmNvZGluZyA9IE1hY1JvbWFuRW5jb2Rpbmc7CiAgICAgICAgaWYgKG5vbkVtYmVkZGVkRm9udCkgewogICAgICAgICAgaWYgKC9TeW1ib2wvaS50ZXN0KHByb3BlcnRpZXMubmFtZSkpIHsKICAgICAgICAgICAgZW5jb2RpbmcgPSBTeW1ib2xTZXRFbmNvZGluZzsKICAgICAgICAgIH0gZWxzZSBpZiAoL0RpbmdiYXRzL2kudGVzdChwcm9wZXJ0aWVzLm5hbWUpKSB7CiAgICAgICAgICAgIGVuY29kaW5nID0gWmFwZkRpbmdiYXRzRW5jb2Rpbmc7CiAgICAgICAgICB9IGVsc2UgaWYgKC9XaW5nZGluZ3MvaS50ZXN0KHByb3BlcnRpZXMubmFtZSkpIHsKICAgICAgICAgICAgZW5jb2RpbmcgPSBXaW5BbnNpRW5jb2Rpbmc7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIHByb3BlcnRpZXMuZGVmYXVsdEVuY29kaW5nID0gZW5jb2Rpbmc7CiAgICB9CiAgICBwcm9wZXJ0aWVzLmRpZmZlcmVuY2VzID0gZGlmZmVyZW5jZXM7CiAgICBwcm9wZXJ0aWVzLmJhc2VFbmNvZGluZ05hbWUgPSBiYXNlRW5jb2RpbmdOYW1lOwogICAgcHJvcGVydGllcy5oYXNFbmNvZGluZyA9ICEhYmFzZUVuY29kaW5nTmFtZSB8fCBkaWZmZXJlbmNlcy5sZW5ndGggPiAwOwogICAgcHJvcGVydGllcy5kaWN0ID0gZGljdDsKICAgIHByb3BlcnRpZXMudG9Vbmljb2RlID0gYXdhaXQgdG9Vbmljb2RlUHJvbWlzZTsKICAgIGNvbnN0IGJ1aWx0VG9Vbmljb2RlID0gYXdhaXQgdGhpcy5idWlsZFRvVW5pY29kZShwcm9wZXJ0aWVzKTsKICAgIHByb3BlcnRpZXMudG9Vbmljb2RlID0gYnVpbHRUb1VuaWNvZGU7CiAgICBpZiAoY2lkVG9HaWRCeXRlcykgewogICAgICBwcm9wZXJ0aWVzLmNpZFRvR2lkTWFwID0gdGhpcy5yZWFkQ2lkVG9HaWRNYXAoY2lkVG9HaWRCeXRlcywgYnVpbHRUb1VuaWNvZGUpOwogICAgfQogICAgcmV0dXJuIHByb3BlcnRpZXM7CiAgfQogIF9zaW1wbGVGb250VG9Vbmljb2RlKHByb3BlcnRpZXMsIGZvcmNlR2x5cGhzID0gZmFsc2UpIHsKICAgIGFzc2VydCghcHJvcGVydGllcy5jb21wb3NpdGUsICJNdXN0IGJlIGEgc2ltcGxlIGZvbnQuIik7CiAgICBjb25zdCB0b1VuaWNvZGUgPSBbXTsKICAgIGNvbnN0IGVuY29kaW5nID0gcHJvcGVydGllcy5kZWZhdWx0RW5jb2Rpbmcuc2xpY2UoKTsKICAgIGNvbnN0IGJhc2VFbmNvZGluZ05hbWUgPSBwcm9wZXJ0aWVzLmJhc2VFbmNvZGluZ05hbWU7CiAgICBjb25zdCBkaWZmZXJlbmNlcyA9IHByb3BlcnRpZXMuZGlmZmVyZW5jZXM7CiAgICBmb3IgKGNvbnN0IGNoYXJjb2RlIGluIGRpZmZlcmVuY2VzKSB7CiAgICAgIGNvbnN0IGdseXBoTmFtZSA9IGRpZmZlcmVuY2VzW2NoYXJjb2RlXTsKICAgICAgaWYgKGdseXBoTmFtZSA9PT0gIi5ub3RkZWYiKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZW5jb2RpbmdbY2hhcmNvZGVdID0gZ2x5cGhOYW1lOwogICAgfQogICAgY29uc3QgZ2x5cGhzVW5pY29kZU1hcCA9IGdldEdseXBoc1VuaWNvZGUoKTsKICAgIGZvciAoY29uc3QgY2hhcmNvZGUgaW4gZW5jb2RpbmcpIHsKICAgICAgbGV0IGdseXBoTmFtZSA9IGVuY29kaW5nW2NoYXJjb2RlXTsKICAgICAgaWYgKGdseXBoTmFtZSA9PT0gIiIpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBsZXQgdW5pY29kZSA9IGdseXBoc1VuaWNvZGVNYXBbZ2x5cGhOYW1lXTsKICAgICAgaWYgKHVuaWNvZGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHRvVW5pY29kZVtjaGFyY29kZV0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHVuaWNvZGUpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGxldCBjb2RlID0gMDsKICAgICAgc3dpdGNoIChnbHlwaE5hbWVbMF0pIHsKICAgICAgICBjYXNlICJHIjoKICAgICAgICAgIGlmIChnbHlwaE5hbWUubGVuZ3RoID09PSAzKSB7CiAgICAgICAgICAgIGNvZGUgPSBwYXJzZUludChnbHlwaE5hbWUuc3Vic3RyaW5nKDEpLCAxNik7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJnIjoKICAgICAgICAgIGlmIChnbHlwaE5hbWUubGVuZ3RoID09PSA1KSB7CiAgICAgICAgICAgIGNvZGUgPSBwYXJzZUludChnbHlwaE5hbWUuc3Vic3RyaW5nKDEpLCAxNik7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJDIjoKICAgICAgICBjYXNlICJjIjoKICAgICAgICAgIGlmIChnbHlwaE5hbWUubGVuZ3RoID49IDMgJiYgZ2x5cGhOYW1lLmxlbmd0aCA8PSA0KSB7CiAgICAgICAgICAgIGNvbnN0IGNvZGVTdHIgPSBnbHlwaE5hbWUuc3Vic3RyaW5nKDEpOwogICAgICAgICAgICBpZiAoZm9yY2VHbHlwaHMpIHsKICAgICAgICAgICAgICBjb2RlID0gcGFyc2VJbnQoY29kZVN0ciwgMTYpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvZGUgPSArY29kZVN0cjsKICAgICAgICAgICAgaWYgKE51bWJlci5pc05hTihjb2RlKSAmJiBOdW1iZXIuaXNJbnRlZ2VyKHBhcnNlSW50KGNvZGVTdHIsIDE2KSkpIHsKICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fc2ltcGxlRm9udFRvVW5pY29kZShwcm9wZXJ0aWVzLCB0cnVlKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAidSI6CiAgICAgICAgICB1bmljb2RlID0gZ2V0VW5pY29kZUZvckdseXBoKGdseXBoTmFtZSwgZ2x5cGhzVW5pY29kZU1hcCk7CiAgICAgICAgICBpZiAodW5pY29kZSAhPT0gLTEpIHsKICAgICAgICAgICAgY29kZSA9IHVuaWNvZGU7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgc3dpdGNoIChnbHlwaE5hbWUpIHsKICAgICAgICAgICAgY2FzZSAiZl9oIjoKICAgICAgICAgICAgY2FzZSAiZl90IjoKICAgICAgICAgICAgY2FzZSAiVF9oIjoKICAgICAgICAgICAgICB0b1VuaWNvZGVbY2hhcmNvZGVdID0gZ2x5cGhOYW1lLnJlcGxhY2VBbGwoIl8iLCAiIik7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoY29kZSA+IDAgJiYgY29kZSA8PSAweDEwZmZmZiAmJiBOdW1iZXIuaXNJbnRlZ2VyKGNvZGUpKSB7CiAgICAgICAgaWYgKGJhc2VFbmNvZGluZ05hbWUgJiYgY29kZSA9PT0gK2NoYXJjb2RlKSB7CiAgICAgICAgICBjb25zdCBiYXNlRW5jb2RpbmcgPSBnZXRFbmNvZGluZyhiYXNlRW5jb2RpbmdOYW1lKTsKICAgICAgICAgIGlmIChiYXNlRW5jb2RpbmcgJiYgKGdseXBoTmFtZSA9IGJhc2VFbmNvZGluZ1tjaGFyY29kZV0pKSB7CiAgICAgICAgICAgIHRvVW5pY29kZVtjaGFyY29kZV0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGdseXBoc1VuaWNvZGVNYXBbZ2x5cGhOYW1lXSk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB0b1VuaWNvZGVbY2hhcmNvZGVdID0gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB0b1VuaWNvZGU7CiAgfQogIGFzeW5jIGJ1aWxkVG9Vbmljb2RlKHByb3BlcnRpZXMpIHsKICAgIHByb3BlcnRpZXMuaGFzSW5jbHVkZWRUb1VuaWNvZGVNYXAgPSBwcm9wZXJ0aWVzLnRvVW5pY29kZT8ubGVuZ3RoID4gMDsKICAgIGlmIChwcm9wZXJ0aWVzLmhhc0luY2x1ZGVkVG9Vbmljb2RlTWFwKSB7CiAgICAgIGlmICghcHJvcGVydGllcy5jb21wb3NpdGUgJiYgcHJvcGVydGllcy5oYXNFbmNvZGluZykgewogICAgICAgIHByb3BlcnRpZXMuZmFsbGJhY2tUb1VuaWNvZGUgPSB0aGlzLl9zaW1wbGVGb250VG9Vbmljb2RlKHByb3BlcnRpZXMpOwogICAgICB9CiAgICAgIHJldHVybiBwcm9wZXJ0aWVzLnRvVW5pY29kZTsKICAgIH0KICAgIGlmICghcHJvcGVydGllcy5jb21wb3NpdGUpIHsKICAgICAgcmV0dXJuIG5ldyBUb1VuaWNvZGVNYXAodGhpcy5fc2ltcGxlRm9udFRvVW5pY29kZShwcm9wZXJ0aWVzKSk7CiAgICB9CiAgICBpZiAocHJvcGVydGllcy5jb21wb3NpdGUgJiYgKHByb3BlcnRpZXMuY01hcC5idWlsdEluQ01hcCAmJiAhKHByb3BlcnRpZXMuY01hcCBpbnN0YW5jZW9mIElkZW50aXR5Q01hcCkgfHwgcHJvcGVydGllcy5jaWRTeXN0ZW1JbmZvPy5yZWdpc3RyeSA9PT0gIkFkb2JlIiAmJiAocHJvcGVydGllcy5jaWRTeXN0ZW1JbmZvLm9yZGVyaW5nID09PSAiR0IxIiB8fCBwcm9wZXJ0aWVzLmNpZFN5c3RlbUluZm8ub3JkZXJpbmcgPT09ICJDTlMxIiB8fCBwcm9wZXJ0aWVzLmNpZFN5c3RlbUluZm8ub3JkZXJpbmcgPT09ICJKYXBhbjEiIHx8IHByb3BlcnRpZXMuY2lkU3lzdGVtSW5mby5vcmRlcmluZyA9PT0gIktvcmVhMSIpKSkgewogICAgICBjb25zdCB7CiAgICAgICAgcmVnaXN0cnksCiAgICAgICAgb3JkZXJpbmcKICAgICAgfSA9IHByb3BlcnRpZXMuY2lkU3lzdGVtSW5mbzsKICAgICAgY29uc3QgdWNzMkNNYXBOYW1lID0gTmFtZS5nZXQoYCR7cmVnaXN0cnl9LSR7b3JkZXJpbmd9LVVDUzJgKTsKICAgICAgY29uc3QgdWNzMkNNYXAgPSBhd2FpdCBDTWFwRmFjdG9yeS5jcmVhdGUoewogICAgICAgIGVuY29kaW5nOiB1Y3MyQ01hcE5hbWUsCiAgICAgICAgZmV0Y2hCdWlsdEluQ01hcDogdGhpcy5fZmV0Y2hCdWlsdEluQ01hcEJvdW5kLAogICAgICAgIHVzZUNNYXA6IG51bGwKICAgICAgfSk7CiAgICAgIGNvbnN0IHRvVW5pY29kZSA9IFtdLAogICAgICAgIGJ1ZiA9IFtdOwogICAgICBwcm9wZXJ0aWVzLmNNYXAuZm9yRWFjaChmdW5jdGlvbiAoY2hhcmNvZGUsIGNpZCkgewogICAgICAgIGlmIChjaWQgPiAweGZmZmYpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiTWF4IHNpemUgb2YgQ0lEIGlzIDY1LDUzNSIpOwogICAgICAgIH0KICAgICAgICBjb25zdCB1Y3MyID0gdWNzMkNNYXAubG9va3VwKGNpZCk7CiAgICAgICAgaWYgKHVjczIpIHsKICAgICAgICAgIGJ1Zi5sZW5ndGggPSAwOwogICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdWNzMi5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7CiAgICAgICAgICAgIGJ1Zi5wdXNoKCh1Y3MyLmNoYXJDb2RlQXQoaSkgPDwgOCkgKyB1Y3MyLmNoYXJDb2RlQXQoaSArIDEpKTsKICAgICAgICAgIH0KICAgICAgICAgIHRvVW5pY29kZVtjaGFyY29kZV0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKC4uLmJ1Zik7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIG5ldyBUb1VuaWNvZGVNYXAodG9Vbmljb2RlKTsKICAgIH0KICAgIHJldHVybiBuZXcgSWRlbnRpdHlUb1VuaWNvZGVNYXAocHJvcGVydGllcy5maXJzdENoYXIsIHByb3BlcnRpZXMubGFzdENoYXIpOwogIH0KICBhc3luYyByZWFkVG9Vbmljb2RlKGNtYXBPYmopIHsKICAgIGlmICghY21hcE9iaikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGlmIChjbWFwT2JqIGluc3RhbmNlb2YgTmFtZSkgewogICAgICBjb25zdCBjbWFwID0gYXdhaXQgQ01hcEZhY3RvcnkuY3JlYXRlKHsKICAgICAgICBlbmNvZGluZzogY21hcE9iaiwKICAgICAgICBmZXRjaEJ1aWx0SW5DTWFwOiB0aGlzLl9mZXRjaEJ1aWx0SW5DTWFwQm91bmQsCiAgICAgICAgdXNlQ01hcDogbnVsbAogICAgICB9KTsKICAgICAgaWYgKGNtYXAgaW5zdGFuY2VvZiBJZGVudGl0eUNNYXApIHsKICAgICAgICByZXR1cm4gbmV3IElkZW50aXR5VG9Vbmljb2RlTWFwKDAsIDB4ZmZmZik7CiAgICAgIH0KICAgICAgcmV0dXJuIG5ldyBUb1VuaWNvZGVNYXAoY21hcC5nZXRNYXAoKSk7CiAgICB9CiAgICBpZiAoY21hcE9iaiBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgdHJ5IHsKICAgICAgICBjb25zdCBjbWFwID0gYXdhaXQgQ01hcEZhY3RvcnkuY3JlYXRlKHsKICAgICAgICAgIGVuY29kaW5nOiBjbWFwT2JqLAogICAgICAgICAgZmV0Y2hCdWlsdEluQ01hcDogdGhpcy5fZmV0Y2hCdWlsdEluQ01hcEJvdW5kLAogICAgICAgICAgdXNlQ01hcDogbnVsbAogICAgICAgIH0pOwogICAgICAgIGlmIChjbWFwIGluc3RhbmNlb2YgSWRlbnRpdHlDTWFwKSB7CiAgICAgICAgICByZXR1cm4gbmV3IElkZW50aXR5VG9Vbmljb2RlTWFwKDAsIDB4ZmZmZik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG1hcCA9IG5ldyBBcnJheShjbWFwLmxlbmd0aCk7CiAgICAgICAgY21hcC5mb3JFYWNoKGZ1bmN0aW9uIChjaGFyQ29kZSwgdG9rZW4pIHsKICAgICAgICAgIGlmICh0eXBlb2YgdG9rZW4gPT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgIG1hcFtjaGFyQ29kZV0gPSBTdHJpbmcuZnJvbUNvZGVQb2ludCh0b2tlbik7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh0b2tlbi5sZW5ndGggJSAyICE9PSAwKSB7CiAgICAgICAgICAgIHRva2VuID0gIlx1MDAwMCIgKyB0b2tlbjsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHN0ciA9IFtdOwogICAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCB0b2tlbi5sZW5ndGg7IGsgKz0gMikgewogICAgICAgICAgICBjb25zdCB3MSA9IHRva2VuLmNoYXJDb2RlQXQoaykgPDwgOCB8IHRva2VuLmNoYXJDb2RlQXQoayArIDEpOwogICAgICAgICAgICBpZiAoKHcxICYgMHhmODAwKSAhPT0gMHhkODAwKSB7CiAgICAgICAgICAgICAgc3RyLnB1c2godzEpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGsgKz0gMjsKICAgICAgICAgICAgY29uc3QgdzIgPSB0b2tlbi5jaGFyQ29kZUF0KGspIDw8IDggfCB0b2tlbi5jaGFyQ29kZUF0KGsgKyAxKTsKICAgICAgICAgICAgc3RyLnB1c2goKCh3MSAmIDB4M2ZmKSA8PCAxMCkgKyAodzIgJiAweDNmZikgKyAweDEwMDAwKTsKICAgICAgICAgIH0KICAgICAgICAgIG1hcFtjaGFyQ29kZV0gPSBTdHJpbmcuZnJvbUNvZGVQb2ludCguLi5zdHIpOwogICAgICAgIH0pOwogICAgICAgIHJldHVybiBuZXcgVG9Vbmljb2RlTWFwKG1hcCk7CiAgICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgICB3YXJuKGByZWFkVG9Vbmljb2RlIC0gaWdub3JpbmcgVG9Vbmljb2RlIGRhdGE6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIHRocm93IHJlYXNvbjsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogIHJlYWRDaWRUb0dpZE1hcChnbHlwaHNEYXRhLCB0b1VuaWNvZGUpIHsKICAgIGNvbnN0IHJlc3VsdCA9IFtdOwogICAgZm9yIChsZXQgaiA9IDAsIGpqID0gZ2x5cGhzRGF0YS5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgIGNvbnN0IGdseXBoSUQgPSBnbHlwaHNEYXRhW2orK10gPDwgOCB8IGdseXBoc0RhdGFbal07CiAgICAgIGNvbnN0IGNvZGUgPSBqID4+IDE7CiAgICAgIGlmIChnbHlwaElEID09PSAwICYmICF0b1VuaWNvZGUuaGFzKGNvZGUpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgcmVzdWx0W2NvZGVdID0gZ2x5cGhJRDsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGV4dHJhY3RXaWR0aHMoZGljdCwgZGVzY3JpcHRvciwgcHJvcGVydGllcykgewogICAgY29uc3QgeHJlZiA9IHRoaXMueHJlZjsKICAgIGxldCBnbHlwaHNXaWR0aHMgPSBbXTsKICAgIGxldCBkZWZhdWx0V2lkdGggPSAwOwogICAgY29uc3QgZ2x5cGhzVk1ldHJpY3MgPSBbXTsKICAgIGxldCBkZWZhdWx0Vk1ldHJpY3M7CiAgICBpZiAocHJvcGVydGllcy5jb21wb3NpdGUpIHsKICAgICAgY29uc3QgZHcgPSBkaWN0LmdldCgiRFciKTsKICAgICAgZGVmYXVsdFdpZHRoID0gdHlwZW9mIGR3ID09PSAibnVtYmVyIiA/IE1hdGguY2VpbChkdykgOiAxMDAwOwogICAgICBjb25zdCB3aWR0aHMgPSBkaWN0LmdldCgiVyIpOwogICAgICBpZiAoQXJyYXkuaXNBcnJheSh3aWR0aHMpKSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gd2lkdGhzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgIGxldCBzdGFydCA9IHhyZWYuZmV0Y2hJZlJlZih3aWR0aHNbaSsrXSk7CiAgICAgICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoc3RhcnQpKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgY29kZSA9IHhyZWYuZmV0Y2hJZlJlZih3aWR0aHNbaV0pOwogICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29kZSkpIHsKICAgICAgICAgICAgZm9yIChjb25zdCBjIG9mIGNvZGUpIHsKICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IHhyZWYuZmV0Y2hJZlJlZihjKTsKICAgICAgICAgICAgICBpZiAodHlwZW9mIHdpZHRoID09PSAibnVtYmVyIikgewogICAgICAgICAgICAgICAgZ2x5cGhzV2lkdGhzW3N0YXJ0XSA9IHdpZHRoOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBzdGFydCsrOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgaWYgKE51bWJlci5pc0ludGVnZXIoY29kZSkpIHsKICAgICAgICAgICAgY29uc3Qgd2lkdGggPSB4cmVmLmZldGNoSWZSZWYod2lkdGhzWysraV0pOwogICAgICAgICAgICBpZiAodHlwZW9mIHdpZHRoICE9PSAibnVtYmVyIikgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvciAobGV0IGogPSBzdGFydDsgaiA8PSBjb2RlOyBqKyspIHsKICAgICAgICAgICAgICBnbHlwaHNXaWR0aHNbal0gPSB3aWR0aDsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChwcm9wZXJ0aWVzLnZlcnRpY2FsKSB7CiAgICAgICAgY29uc3QgZHcyID0gZGljdC5nZXRBcnJheSgiRFcyIik7CiAgICAgICAgbGV0IHZtZXRyaWNzID0gaXNOdW1iZXJBcnJheShkdzIsIDIpID8gZHcyIDogWzg4MCwgLTEwMDBdOwogICAgICAgIGRlZmF1bHRWTWV0cmljcyA9IFt2bWV0cmljc1sxXSwgZGVmYXVsdFdpZHRoICogMC41LCB2bWV0cmljc1swXV07CiAgICAgICAgdm1ldHJpY3MgPSBkaWN0LmdldCgiVzIiKTsKICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2bWV0cmljcykpIHsKICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHZtZXRyaWNzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgICAgbGV0IHN0YXJ0ID0geHJlZi5mZXRjaElmUmVmKHZtZXRyaWNzW2krK10pOwogICAgICAgICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoc3RhcnQpKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgY29kZSA9IHhyZWYuZmV0Y2hJZlJlZih2bWV0cmljc1tpXSk7CiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvZGUpKSB7CiAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDAsIGpqID0gY29kZS5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgICAgICAgICAgICBjb25zdCB2bWV0cmljID0gW3hyZWYuZmV0Y2hJZlJlZihjb2RlW2orK10pLCB4cmVmLmZldGNoSWZSZWYoY29kZVtqKytdKSwgeHJlZi5mZXRjaElmUmVmKGNvZGVbal0pXTsKICAgICAgICAgICAgICAgIGlmIChpc051bWJlckFycmF5KHZtZXRyaWMsIG51bGwpKSB7CiAgICAgICAgICAgICAgICAgIGdseXBoc1ZNZXRyaWNzW3N0YXJ0XSA9IHZtZXRyaWM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdGFydCsrOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGNvZGUpKSB7CiAgICAgICAgICAgICAgY29uc3Qgdm1ldHJpYyA9IFt4cmVmLmZldGNoSWZSZWYodm1ldHJpY3NbKytpXSksIHhyZWYuZmV0Y2hJZlJlZih2bWV0cmljc1srK2ldKSwgeHJlZi5mZXRjaElmUmVmKHZtZXRyaWNzWysraV0pXTsKICAgICAgICAgICAgICBpZiAoIWlzTnVtYmVyQXJyYXkodm1ldHJpYywgbnVsbCkpIHsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBmb3IgKGxldCBqID0gc3RhcnQ7IGogPD0gY29kZTsgaisrKSB7CiAgICAgICAgICAgICAgICBnbHlwaHNWTWV0cmljc1tqXSA9IHZtZXRyaWM7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCB3aWR0aHMgPSBkaWN0LmdldCgiV2lkdGhzIik7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KHdpZHRocykpIHsKICAgICAgICBsZXQgaiA9IHByb3BlcnRpZXMuZmlyc3RDaGFyOwogICAgICAgIGZvciAoY29uc3QgdyBvZiB3aWR0aHMpIHsKICAgICAgICAgIGNvbnN0IHdpZHRoID0geHJlZi5mZXRjaElmUmVmKHcpOwogICAgICAgICAgaWYgKHR5cGVvZiB3aWR0aCA9PT0gIm51bWJlciIpIHsKICAgICAgICAgICAgZ2x5cGhzV2lkdGhzW2pdID0gd2lkdGg7CiAgICAgICAgICB9CiAgICAgICAgICBqKys7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG1pc3NpbmdXaWR0aCA9IGRlc2NyaXB0b3IuZ2V0KCJNaXNzaW5nV2lkdGgiKTsKICAgICAgICBkZWZhdWx0V2lkdGggPSB0eXBlb2YgbWlzc2luZ1dpZHRoID09PSAibnVtYmVyIiA/IG1pc3NpbmdXaWR0aCA6IDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgYmFzZUZvbnROYW1lID0gZGljdC5nZXQoIkJhc2VGb250Iik7CiAgICAgICAgaWYgKGJhc2VGb250TmFtZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB0aGlzLmdldEJhc2VGb250TWV0cmljcyhiYXNlRm9udE5hbWUubmFtZSk7CiAgICAgICAgICBnbHlwaHNXaWR0aHMgPSB0aGlzLmJ1aWxkQ2hhckNvZGVUb1dpZHRoKG1ldHJpY3Mud2lkdGhzLCBwcm9wZXJ0aWVzKTsKICAgICAgICAgIGRlZmF1bHRXaWR0aCA9IG1ldHJpY3MuZGVmYXVsdFdpZHRoOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgbGV0IGlzTW9ub3NwYWNlID0gdHJ1ZTsKICAgIGxldCBmaXJzdFdpZHRoID0gZGVmYXVsdFdpZHRoOwogICAgZm9yIChjb25zdCBnbHlwaCBpbiBnbHlwaHNXaWR0aHMpIHsKICAgICAgY29uc3QgZ2x5cGhXaWR0aCA9IGdseXBoc1dpZHRoc1tnbHlwaF07CiAgICAgIGlmICghZ2x5cGhXaWR0aCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICghZmlyc3RXaWR0aCkgewogICAgICAgIGZpcnN0V2lkdGggPSBnbHlwaFdpZHRoOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChmaXJzdFdpZHRoICE9PSBnbHlwaFdpZHRoKSB7CiAgICAgICAgaXNNb25vc3BhY2UgPSBmYWxzZTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgaWYgKGlzTW9ub3NwYWNlKSB7CiAgICAgIHByb3BlcnRpZXMuZmxhZ3MgfD0gRm9udEZsYWdzLkZpeGVkUGl0Y2g7CiAgICB9IGVsc2UgewogICAgICBwcm9wZXJ0aWVzLmZsYWdzICY9IH5Gb250RmxhZ3MuRml4ZWRQaXRjaDsKICAgIH0KICAgIHByb3BlcnRpZXMuZGVmYXVsdFdpZHRoID0gZGVmYXVsdFdpZHRoOwogICAgcHJvcGVydGllcy53aWR0aHMgPSBnbHlwaHNXaWR0aHM7CiAgICBwcm9wZXJ0aWVzLmRlZmF1bHRWTWV0cmljcyA9IGRlZmF1bHRWTWV0cmljczsKICAgIHByb3BlcnRpZXMudm1ldHJpY3MgPSBnbHlwaHNWTWV0cmljczsKICB9CiAgaXNTZXJpZkZvbnQoYmFzZUZvbnROYW1lKSB7CiAgICBjb25zdCBmb250TmFtZVdvU3R5bGUgPSBiYXNlRm9udE5hbWUuc3BsaXQoIi0iLCAxKVswXTsKICAgIHJldHVybiBmb250TmFtZVdvU3R5bGUgaW4gZ2V0U2VyaWZGb250cygpIHx8IC9zZXJpZi9naS50ZXN0KGZvbnROYW1lV29TdHlsZSk7CiAgfQogIGdldEJhc2VGb250TWV0cmljcyhuYW1lKSB7CiAgICBsZXQgZGVmYXVsdFdpZHRoID0gMDsKICAgIGxldCB3aWR0aHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgbGV0IG1vbm9zcGFjZSA9IGZhbHNlOwogICAgY29uc3Qgc3RkRm9udE1hcCA9IGdldFN0ZEZvbnRNYXAoKTsKICAgIGxldCBsb29rdXBOYW1lID0gc3RkRm9udE1hcFtuYW1lXSB8fCBuYW1lOwogICAgY29uc3QgTWV0cmljcyA9IGdldE1ldHJpY3MoKTsKICAgIGlmICghKGxvb2t1cE5hbWUgaW4gTWV0cmljcykpIHsKICAgICAgbG9va3VwTmFtZSA9IHRoaXMuaXNTZXJpZkZvbnQobmFtZSkgPyAiVGltZXMtUm9tYW4iIDogIkhlbHZldGljYSI7CiAgICB9CiAgICBjb25zdCBnbHlwaFdpZHRocyA9IE1ldHJpY3NbbG9va3VwTmFtZV07CiAgICBpZiAodHlwZW9mIGdseXBoV2lkdGhzID09PSAibnVtYmVyIikgewogICAgICBkZWZhdWx0V2lkdGggPSBnbHlwaFdpZHRoczsKICAgICAgbW9ub3NwYWNlID0gdHJ1ZTsKICAgIH0gZWxzZSB7CiAgICAgIHdpZHRocyA9IGdseXBoV2lkdGhzKCk7CiAgICB9CiAgICByZXR1cm4gewogICAgICBkZWZhdWx0V2lkdGgsCiAgICAgIG1vbm9zcGFjZSwKICAgICAgd2lkdGhzCiAgICB9OwogIH0KICBidWlsZENoYXJDb2RlVG9XaWR0aCh3aWR0aHNCeUdseXBoTmFtZSwgcHJvcGVydGllcykgewogICAgY29uc3Qgd2lkdGhzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGNvbnN0IGRpZmZlcmVuY2VzID0gcHJvcGVydGllcy5kaWZmZXJlbmNlczsKICAgIGNvbnN0IGVuY29kaW5nID0gcHJvcGVydGllcy5kZWZhdWx0RW5jb2Rpbmc7CiAgICBmb3IgKGxldCBjaGFyQ29kZSA9IDA7IGNoYXJDb2RlIDwgMjU2OyBjaGFyQ29kZSsrKSB7CiAgICAgIGlmIChjaGFyQ29kZSBpbiBkaWZmZXJlbmNlcyAmJiB3aWR0aHNCeUdseXBoTmFtZVtkaWZmZXJlbmNlc1tjaGFyQ29kZV1dKSB7CiAgICAgICAgd2lkdGhzW2NoYXJDb2RlXSA9IHdpZHRoc0J5R2x5cGhOYW1lW2RpZmZlcmVuY2VzW2NoYXJDb2RlXV07CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGNoYXJDb2RlIGluIGVuY29kaW5nICYmIHdpZHRoc0J5R2x5cGhOYW1lW2VuY29kaW5nW2NoYXJDb2RlXV0pIHsKICAgICAgICB3aWR0aHNbY2hhckNvZGVdID0gd2lkdGhzQnlHbHlwaE5hbWVbZW5jb2RpbmdbY2hhckNvZGVdXTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHdpZHRoczsKICB9CiAgcHJlRXZhbHVhdGVGb250KGRpY3QpIHsKICAgIGNvbnN0IGJhc2VEaWN0ID0gZGljdDsKICAgIGxldCB0eXBlID0gZGljdC5nZXQoIlN1YnR5cGUiKTsKICAgIGlmICghKHR5cGUgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoImludmFsaWQgZm9udCBTdWJ0eXBlIik7CiAgICB9CiAgICBsZXQgY29tcG9zaXRlID0gZmFsc2U7CiAgICBsZXQgaGFzaDsKICAgIGlmICh0eXBlLm5hbWUgPT09ICJUeXBlMCIpIHsKICAgICAgY29uc3QgZGYgPSBkaWN0LmdldCgiRGVzY2VuZGFudEZvbnRzIik7CiAgICAgIGlmICghZGYpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkRlc2NlbmRhbnQgZm9udHMgYXJlIG5vdCBzcGVjaWZpZWQiKTsKICAgICAgfQogICAgICBkaWN0ID0gQXJyYXkuaXNBcnJheShkZikgPyB0aGlzLnhyZWYuZmV0Y2hJZlJlZihkZlswXSkgOiBkZjsKICAgICAgaWYgKCEoZGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJEZXNjZW5kYW50IGZvbnQgaXMgbm90IGEgZGljdGlvbmFyeS4iKTsKICAgICAgfQogICAgICB0eXBlID0gZGljdC5nZXQoIlN1YnR5cGUiKTsKICAgICAgaWYgKCEodHlwZSBpbnN0YW5jZW9mIE5hbWUpKSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJpbnZhbGlkIGZvbnQgU3VidHlwZSIpOwogICAgICB9CiAgICAgIGNvbXBvc2l0ZSA9IHRydWU7CiAgICB9CiAgICBsZXQgZmlyc3RDaGFyID0gZGljdC5nZXQoIkZpcnN0Q2hhciIpOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGZpcnN0Q2hhcikpIHsKICAgICAgZmlyc3RDaGFyID0gMDsKICAgIH0KICAgIGxldCBsYXN0Q2hhciA9IGRpY3QuZ2V0KCJMYXN0Q2hhciIpOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGxhc3RDaGFyKSkgewogICAgICBsYXN0Q2hhciA9IGNvbXBvc2l0ZSA/IDB4ZmZmZiA6IDB4ZmY7CiAgICB9CiAgICBjb25zdCBkZXNjcmlwdG9yID0gZGljdC5nZXQoIkZvbnREZXNjcmlwdG9yIik7CiAgICBjb25zdCB0b1VuaWNvZGUgPSBkaWN0LmdldCgiVG9Vbmljb2RlIikgfHwgYmFzZURpY3QuZ2V0KCJUb1VuaWNvZGUiKTsKICAgIGlmIChkZXNjcmlwdG9yKSB7CiAgICAgIGhhc2ggPSBuZXcgTXVybXVySGFzaDNfNjQoKTsKICAgICAgY29uc3QgZW5jb2RpbmcgPSBiYXNlRGljdC5nZXRSYXcoIkVuY29kaW5nIik7CiAgICAgIGlmIChlbmNvZGluZyBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICBoYXNoLnVwZGF0ZShlbmNvZGluZy5uYW1lKTsKICAgICAgfSBlbHNlIGlmIChlbmNvZGluZyBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIGhhc2gudXBkYXRlKGVuY29kaW5nLnRvU3RyaW5nKCkpOwogICAgICB9IGVsc2UgaWYgKGVuY29kaW5nIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIGZvciAoY29uc3QgZW50cnkgb2YgZW5jb2RpbmcuZ2V0UmF3VmFsdWVzKCkpIHsKICAgICAgICAgIGlmIChlbnRyeSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgICAgaGFzaC51cGRhdGUoZW50cnkubmFtZSk7CiAgICAgICAgICB9IGVsc2UgaWYgKGVudHJ5IGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICAgIGhhc2gudXBkYXRlKGVudHJ5LnRvU3RyaW5nKCkpOwogICAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGVudHJ5KSkgewogICAgICAgICAgICBjb25zdCBkaWZmTGVuZ3RoID0gZW50cnkubGVuZ3RoLAogICAgICAgICAgICAgIGRpZmZCdWYgPSBuZXcgQXJyYXkoZGlmZkxlbmd0aCk7CiAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgZGlmZkxlbmd0aDsgaisrKSB7CiAgICAgICAgICAgICAgY29uc3QgZGlmZkVudHJ5ID0gZW50cnlbal07CiAgICAgICAgICAgICAgaWYgKGRpZmZFbnRyeSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgICAgICAgIGRpZmZCdWZbal0gPSBkaWZmRW50cnkubmFtZTsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkaWZmRW50cnkgPT09ICJudW1iZXIiIHx8IGRpZmZFbnRyeSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgICAgICAgZGlmZkJ1ZltqXSA9IGRpZmZFbnRyeS50b1N0cmluZygpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBoYXNoLnVwZGF0ZShkaWZmQnVmLmpvaW4oKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGhhc2gudXBkYXRlKGAke2ZpcnN0Q2hhcn0tJHtsYXN0Q2hhcn1gKTsKICAgICAgaWYgKHRvVW5pY29kZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgICBjb25zdCBzdHJlYW0gPSB0b1VuaWNvZGUuc3RyZWFtIHx8IHRvVW5pY29kZTsKICAgICAgICBjb25zdCB1aW50OGFycmF5ID0gc3RyZWFtLmJ1ZmZlciA/IG5ldyBVaW50OEFycmF5KHN0cmVhbS5idWZmZXIuYnVmZmVyLCAwLCBzdHJlYW0uYnVmZmVyTGVuZ3RoKSA6IG5ldyBVaW50OEFycmF5KHN0cmVhbS5ieXRlcy5idWZmZXIsIHN0cmVhbS5zdGFydCwgc3RyZWFtLmVuZCAtIHN0cmVhbS5zdGFydCk7CiAgICAgICAgaGFzaC51cGRhdGUodWludDhhcnJheSk7CiAgICAgIH0gZWxzZSBpZiAodG9Vbmljb2RlIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgIGhhc2gudXBkYXRlKHRvVW5pY29kZS5uYW1lKTsKICAgICAgfQogICAgICBjb25zdCB3aWR0aHMgPSBkaWN0LmdldCgiV2lkdGhzIikgfHwgYmFzZURpY3QuZ2V0KCJXaWR0aHMiKTsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkod2lkdGhzKSkgewogICAgICAgIGNvbnN0IHdpZHRoc0J1ZiA9IFtdOwogICAgICAgIGZvciAoY29uc3QgZW50cnkgb2Ygd2lkdGhzKSB7CiAgICAgICAgICBpZiAodHlwZW9mIGVudHJ5ID09PSAibnVtYmVyIiB8fCBlbnRyeSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgICB3aWR0aHNCdWYucHVzaChlbnRyeS50b1N0cmluZygpKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaGFzaC51cGRhdGUod2lkdGhzQnVmLmpvaW4oKSk7CiAgICAgIH0KICAgICAgaWYgKGNvbXBvc2l0ZSkgewogICAgICAgIGhhc2gudXBkYXRlKCJjb21wb3NpdGVGb250Iik7CiAgICAgICAgY29uc3QgY29tcG9zaXRlV2lkdGhzID0gZGljdC5nZXQoIlciKSB8fCBiYXNlRGljdC5nZXQoIlciKTsKICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjb21wb3NpdGVXaWR0aHMpKSB7CiAgICAgICAgICBjb25zdCB3aWR0aHNCdWYgPSBbXTsKICAgICAgICAgIGZvciAoY29uc3QgZW50cnkgb2YgY29tcG9zaXRlV2lkdGhzKSB7CiAgICAgICAgICAgIGlmICh0eXBlb2YgZW50cnkgPT09ICJudW1iZXIiIHx8IGVudHJ5IGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICAgICAgd2lkdGhzQnVmLnB1c2goZW50cnkudG9TdHJpbmcoKSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShlbnRyeSkpIHsKICAgICAgICAgICAgICBjb25zdCBzdWJXaWR0aHNCdWYgPSBbXTsKICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZW50cnkpIHsKICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZWxlbWVudCA9PT0gIm51bWJlciIgfHwgZWxlbWVudCBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgICAgICAgICBzdWJXaWR0aHNCdWYucHVzaChlbGVtZW50LnRvU3RyaW5nKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB3aWR0aHNCdWYucHVzaChgWyR7c3ViV2lkdGhzQnVmLmpvaW4oKX1dYCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGhhc2gudXBkYXRlKHdpZHRoc0J1Zi5qb2luKCkpOwogICAgICAgIH0KICAgICAgICBjb25zdCBjaWRUb0dpZE1hcCA9IGRpY3QuZ2V0UmF3KCJDSURUb0dJRE1hcCIpIHx8IGJhc2VEaWN0LmdldFJhdygiQ0lEVG9HSURNYXAiKTsKICAgICAgICBpZiAoY2lkVG9HaWRNYXAgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICBoYXNoLnVwZGF0ZShjaWRUb0dpZE1hcC5uYW1lKTsKICAgICAgICB9IGVsc2UgaWYgKGNpZFRvR2lkTWFwIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICBoYXNoLnVwZGF0ZShjaWRUb0dpZE1hcC50b1N0cmluZygpKTsKICAgICAgICB9IGVsc2UgaWYgKGNpZFRvR2lkTWFwIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICAgICAgaGFzaC51cGRhdGUoY2lkVG9HaWRNYXAucGVla0J5dGVzKCkpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHsKICAgICAgZGVzY3JpcHRvciwKICAgICAgZGljdCwKICAgICAgYmFzZURpY3QsCiAgICAgIGNvbXBvc2l0ZSwKICAgICAgdHlwZTogdHlwZS5uYW1lLAogICAgICBmaXJzdENoYXIsCiAgICAgIGxhc3RDaGFyLAogICAgICB0b1VuaWNvZGUsCiAgICAgIGhhc2g6IGhhc2ggPyBoYXNoLmhleGRpZ2VzdCgpIDogIiIKICAgIH07CiAgfQogIGFzeW5jIHRyYW5zbGF0ZUZvbnQoewogICAgZGVzY3JpcHRvciwKICAgIGRpY3QsCiAgICBiYXNlRGljdCwKICAgIGNvbXBvc2l0ZSwKICAgIHR5cGUsCiAgICBmaXJzdENoYXIsCiAgICBsYXN0Q2hhciwKICAgIHRvVW5pY29kZSwKICAgIGNzc0ZvbnRJbmZvCiAgfSkgewogICAgY29uc3QgaXNUeXBlM0ZvbnQgPSB0eXBlID09PSAiVHlwZTMiOwogICAgaWYgKCFkZXNjcmlwdG9yKSB7CiAgICAgIGlmIChpc1R5cGUzRm9udCkgewogICAgICAgIGRlc2NyaXB0b3IgPSBEaWN0LmVtcHR5OwogICAgICB9IGVsc2UgewogICAgICAgIGxldCBiYXNlRm9udE5hbWUgPSBkaWN0LmdldCgiQmFzZUZvbnQiKTsKICAgICAgICBpZiAoIShiYXNlRm9udE5hbWUgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJCYXNlIGZvbnQgaXMgbm90IHNwZWNpZmllZCIpOwogICAgICAgIH0KICAgICAgICBiYXNlRm9udE5hbWUgPSBiYXNlRm9udE5hbWUubmFtZS5yZXBsYWNlQWxsKC9bLF9dL2csICItIik7CiAgICAgICAgY29uc3QgbWV0cmljcyA9IHRoaXMuZ2V0QmFzZUZvbnRNZXRyaWNzKGJhc2VGb250TmFtZSk7CiAgICAgICAgY29uc3QgZm9udE5hbWVXb1N0eWxlID0gYmFzZUZvbnROYW1lLnNwbGl0KCItIiwgMSlbMF07CiAgICAgICAgY29uc3QgZmxhZ3MgPSAodGhpcy5pc1NlcmlmRm9udChmb250TmFtZVdvU3R5bGUpID8gRm9udEZsYWdzLlNlcmlmIDogMCkgfCAobWV0cmljcy5tb25vc3BhY2UgPyBGb250RmxhZ3MuRml4ZWRQaXRjaCA6IDApIHwgKGdldFN5bWJvbHNGb250cygpW2ZvbnROYW1lV29TdHlsZV0gPyBGb250RmxhZ3MuU3ltYm9saWMgOiBGb250RmxhZ3MuTm9uc3ltYm9saWMpOwogICAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSB7CiAgICAgICAgICB0eXBlLAogICAgICAgICAgbmFtZTogYmFzZUZvbnROYW1lLAogICAgICAgICAgbG9hZGVkTmFtZTogYmFzZURpY3QubG9hZGVkTmFtZSwKICAgICAgICAgIHN5c3RlbUZvbnRJbmZvOiBudWxsLAogICAgICAgICAgd2lkdGhzOiBtZXRyaWNzLndpZHRocywKICAgICAgICAgIGRlZmF1bHRXaWR0aDogbWV0cmljcy5kZWZhdWx0V2lkdGgsCiAgICAgICAgICBpc1NpbXVsYXRlZEZsYWdzOiB0cnVlLAogICAgICAgICAgZmxhZ3MsCiAgICAgICAgICBmaXJzdENoYXIsCiAgICAgICAgICBsYXN0Q2hhciwKICAgICAgICAgIHRvVW5pY29kZSwKICAgICAgICAgIHhIZWlnaHQ6IDAsCiAgICAgICAgICBjYXBIZWlnaHQ6IDAsCiAgICAgICAgICBpdGFsaWNBbmdsZTogMCwKICAgICAgICAgIGlzVHlwZTNGb250CiAgICAgICAgfTsKICAgICAgICBjb25zdCB3aWR0aHMgPSBkaWN0LmdldCgiV2lkdGhzIik7CiAgICAgICAgY29uc3Qgc3RhbmRhcmRGb250TmFtZSA9IGdldFN0YW5kYXJkRm9udE5hbWUoYmFzZUZvbnROYW1lKTsKICAgICAgICBsZXQgZmlsZSA9IG51bGw7CiAgICAgICAgaWYgKHN0YW5kYXJkRm9udE5hbWUpIHsKICAgICAgICAgIGZpbGUgPSBhd2FpdCB0aGlzLmZldGNoU3RhbmRhcmRGb250RGF0YShzdGFuZGFyZEZvbnROYW1lKTsKICAgICAgICAgIHByb3BlcnRpZXMuaXNJbnRlcm5hbEZvbnQgPSAhIWZpbGU7CiAgICAgICAgfQogICAgICAgIGlmICghcHJvcGVydGllcy5pc0ludGVybmFsRm9udCAmJiB0aGlzLm9wdGlvbnMudXNlU3lzdGVtRm9udHMpIHsKICAgICAgICAgIHByb3BlcnRpZXMuc3lzdGVtRm9udEluZm8gPSBnZXRGb250U3Vic3RpdHV0aW9uKHRoaXMuc3lzdGVtRm9udENhY2hlLCB0aGlzLmlkRmFjdG9yeSwgdGhpcy5vcHRpb25zLnN0YW5kYXJkRm9udERhdGFVcmwsIGJhc2VGb250TmFtZSwgc3RhbmRhcmRGb250TmFtZSwgdHlwZSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG5ld1Byb3BlcnRpZXMgPSBhd2FpdCB0aGlzLmV4dHJhY3REYXRhU3RydWN0dXJlcyhkaWN0LCBwcm9wZXJ0aWVzKTsKICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh3aWR0aHMpKSB7CiAgICAgICAgICBjb25zdCBnbHlwaFdpZHRocyA9IFtdOwogICAgICAgICAgbGV0IGogPSBmaXJzdENoYXI7CiAgICAgICAgICBmb3IgKGNvbnN0IHcgb2Ygd2lkdGhzKSB7CiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy54cmVmLmZldGNoSWZSZWYodyk7CiAgICAgICAgICAgIGlmICh0eXBlb2Ygd2lkdGggPT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgICAgZ2x5cGhXaWR0aHNbal0gPSB3aWR0aDsKICAgICAgICAgICAgfQogICAgICAgICAgICBqKys7CiAgICAgICAgICB9CiAgICAgICAgICBuZXdQcm9wZXJ0aWVzLndpZHRocyA9IGdseXBoV2lkdGhzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBuZXdQcm9wZXJ0aWVzLndpZHRocyA9IHRoaXMuYnVpbGRDaGFyQ29kZVRvV2lkdGgobWV0cmljcy53aWR0aHMsIG5ld1Byb3BlcnRpZXMpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IEZvbnQoYmFzZUZvbnROYW1lLCBmaWxlLCBuZXdQcm9wZXJ0aWVzLCB0aGlzLm9wdGlvbnMpOwogICAgICB9CiAgICB9CiAgICBsZXQgZm9udE5hbWUgPSBkZXNjcmlwdG9yLmdldCgiRm9udE5hbWUiKTsKICAgIGxldCBiYXNlRm9udCA9IGRpY3QuZ2V0KCJCYXNlRm9udCIpOwogICAgaWYgKHR5cGVvZiBmb250TmFtZSA9PT0gInN0cmluZyIpIHsKICAgICAgZm9udE5hbWUgPSBOYW1lLmdldChmb250TmFtZSk7CiAgICB9CiAgICBpZiAodHlwZW9mIGJhc2VGb250ID09PSAic3RyaW5nIikgewogICAgICBiYXNlRm9udCA9IE5hbWUuZ2V0KGJhc2VGb250KTsKICAgIH0KICAgIGNvbnN0IGZvbnROYW1lU3RyID0gZm9udE5hbWU/Lm5hbWU7CiAgICBjb25zdCBiYXNlRm9udFN0ciA9IGJhc2VGb250Py5uYW1lOwogICAgaWYgKGlzVHlwZTNGb250KSB7CiAgICAgIGlmICghZm9udE5hbWVTdHIpIHsKICAgICAgICBmb250TmFtZSA9IE5hbWUuZ2V0KHR5cGUpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKGZvbnROYW1lU3RyICE9PSBiYXNlRm9udFN0cikgewogICAgICBpbmZvKGBUaGUgRm9udERlc2NyaXB0b3IncyBGb250TmFtZSBpcyAiJHtmb250TmFtZVN0cn0iIGJ1dCBgICsgYHNob3VsZCBiZSB0aGUgc2FtZSBhcyB0aGUgRm9udCdzIEJhc2VGb250ICIke2Jhc2VGb250U3RyfSIuYCk7CiAgICAgIGlmIChmb250TmFtZVN0ciAmJiBiYXNlRm9udFN0ciAmJiAoYmFzZUZvbnRTdHIuc3RhcnRzV2l0aChmb250TmFtZVN0cikgfHwgIWlzS25vd25Gb250TmFtZShmb250TmFtZVN0cikgJiYgaXNLbm93bkZvbnROYW1lKGJhc2VGb250U3RyKSkpIHsKICAgICAgICBmb250TmFtZSA9IG51bGw7CiAgICAgIH0KICAgICAgZm9udE5hbWUgfHw9IGJhc2VGb250OwogICAgfQogICAgaWYgKCEoZm9udE5hbWUgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoImludmFsaWQgZm9udCBuYW1lIik7CiAgICB9CiAgICBsZXQgZm9udEZpbGUsIHN1YnR5cGUsIGxlbmd0aDEsIGxlbmd0aDIsIGxlbmd0aDM7CiAgICB0cnkgewogICAgICBmb250RmlsZSA9IGRlc2NyaXB0b3IuZ2V0KCJGb250RmlsZSIsICJGb250RmlsZTIiLCAiRm9udEZpbGUzIik7CiAgICAgIGlmIChmb250RmlsZSkgewogICAgICAgIGlmICghKGZvbnRGaWxlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiRm9udEZpbGUgc2hvdWxkIGJlIGEgc3RyZWFtIik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChmb250RmlsZS5pc0FzeW5jKSB7CiAgICAgICAgICAgIGNvbnN0IGJ5dGVzID0gYXdhaXQgZm9udEZpbGUuYXN5bmNHZXRCeXRlcygpOwogICAgICAgICAgICBpZiAoYnl0ZXMpIHsKICAgICAgICAgICAgICBmb250RmlsZSA9IG5ldyBTdHJlYW0oYnl0ZXMsIDAsIGJ5dGVzLmxlbmd0aCwgZm9udEZpbGUuZGljdCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChmb250RmlsZS5pc0VtcHR5KSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiRm9udEZpbGUgaXMgZW1wdHkiKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmICghdGhpcy5vcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIHdhcm4oYHRyYW5zbGF0ZUZvbnQgLSBmZXRjaGluZyAiJHtmb250TmFtZS5uYW1lfSIgZm9udCBmaWxlOiAiJHtleH0iLmApOwogICAgICBmb250RmlsZSA9IG51bGw7CiAgICB9CiAgICBsZXQgaXNJbnRlcm5hbEZvbnQgPSBmYWxzZTsKICAgIGxldCBnbHlwaFNjYWxlRmFjdG9ycyA9IG51bGw7CiAgICBsZXQgc3lzdGVtRm9udEluZm8gPSBudWxsOwogICAgaWYgKGZvbnRGaWxlKSB7CiAgICAgIGlmIChmb250RmlsZS5kaWN0KSB7CiAgICAgICAgY29uc3Qgc3VidHlwZUVudHJ5ID0gZm9udEZpbGUuZGljdC5nZXQoIlN1YnR5cGUiKTsKICAgICAgICBpZiAoc3VidHlwZUVudHJ5IGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgc3VidHlwZSA9IHN1YnR5cGVFbnRyeS5uYW1lOwogICAgICAgIH0KICAgICAgICBsZW5ndGgxID0gZm9udEZpbGUuZGljdC5nZXQoIkxlbmd0aDEiKTsKICAgICAgICBsZW5ndGgyID0gZm9udEZpbGUuZGljdC5nZXQoIkxlbmd0aDIiKTsKICAgICAgICBsZW5ndGgzID0gZm9udEZpbGUuZGljdC5nZXQoIkxlbmd0aDMiKTsKICAgICAgfQogICAgfSBlbHNlIGlmIChjc3NGb250SW5mbykgewogICAgICBjb25zdCBzdGFuZGFyZEZvbnROYW1lID0gZ2V0WGZhRm9udE5hbWUoZm9udE5hbWUubmFtZSk7CiAgICAgIGlmIChzdGFuZGFyZEZvbnROYW1lKSB7CiAgICAgICAgY3NzRm9udEluZm8uZm9udEZhbWlseSA9IGAke2Nzc0ZvbnRJbmZvLmZvbnRGYW1pbHl9LVBkZkpTLVhGQWA7CiAgICAgICAgY3NzRm9udEluZm8ubWV0cmljcyA9IHN0YW5kYXJkRm9udE5hbWUubWV0cmljcyB8fCBudWxsOwogICAgICAgIGdseXBoU2NhbGVGYWN0b3JzID0gc3RhbmRhcmRGb250TmFtZS5mYWN0b3JzIHx8IG51bGw7CiAgICAgICAgZm9udEZpbGUgPSBhd2FpdCB0aGlzLmZldGNoU3RhbmRhcmRGb250RGF0YShzdGFuZGFyZEZvbnROYW1lLm5hbWUpOwogICAgICAgIGlzSW50ZXJuYWxGb250ID0gISFmb250RmlsZTsKICAgICAgICBiYXNlRGljdCA9IGRpY3QgPSBnZXRYZmFGb250RGljdChmb250TmFtZS5uYW1lKTsKICAgICAgICBjb21wb3NpdGUgPSB0cnVlOwogICAgICB9CiAgICB9IGVsc2UgaWYgKCFpc1R5cGUzRm9udCkgewogICAgICBjb25zdCBzdGFuZGFyZEZvbnROYW1lID0gZ2V0U3RhbmRhcmRGb250TmFtZShmb250TmFtZS5uYW1lKTsKICAgICAgaWYgKHN0YW5kYXJkRm9udE5hbWUpIHsKICAgICAgICBmb250RmlsZSA9IGF3YWl0IHRoaXMuZmV0Y2hTdGFuZGFyZEZvbnREYXRhKHN0YW5kYXJkRm9udE5hbWUpOwogICAgICAgIGlzSW50ZXJuYWxGb250ID0gISFmb250RmlsZTsKICAgICAgfQogICAgICBpZiAoIWlzSW50ZXJuYWxGb250ICYmIHRoaXMub3B0aW9ucy51c2VTeXN0ZW1Gb250cykgewogICAgICAgIHN5c3RlbUZvbnRJbmZvID0gZ2V0Rm9udFN1YnN0aXR1dGlvbih0aGlzLnN5c3RlbUZvbnRDYWNoZSwgdGhpcy5pZEZhY3RvcnksIHRoaXMub3B0aW9ucy5zdGFuZGFyZEZvbnREYXRhVXJsLCBmb250TmFtZS5uYW1lLCBzdGFuZGFyZEZvbnROYW1lLCB0eXBlKTsKICAgICAgfQogICAgfQogICAgY29uc3QgZm9udE1hdHJpeCA9IGxvb2t1cE1hdHJpeChkaWN0LmdldEFycmF5KCJGb250TWF0cml4IiksIEZPTlRfSURFTlRJVFlfTUFUUklYKTsKICAgIGNvbnN0IGJib3ggPSBsb29rdXBOb3JtYWxSZWN0KGRlc2NyaXB0b3IuZ2V0QXJyYXkoIkZvbnRCQm94IikgfHwgZGljdC5nZXRBcnJheSgiRm9udEJCb3giKSwgaXNUeXBlM0ZvbnQgPyBbMCwgMCwgMCwgMF0gOiB1bmRlZmluZWQpOwogICAgbGV0IGFzY2VudCA9IGRlc2NyaXB0b3IuZ2V0KCJBc2NlbnQiKTsKICAgIGlmICh0eXBlb2YgYXNjZW50ICE9PSAibnVtYmVyIikgewogICAgICBhc2NlbnQgPSB1bmRlZmluZWQ7CiAgICB9CiAgICBsZXQgZGVzY2VudCA9IGRlc2NyaXB0b3IuZ2V0KCJEZXNjZW50Iik7CiAgICBpZiAodHlwZW9mIGRlc2NlbnQgIT09ICJudW1iZXIiKSB7CiAgICAgIGRlc2NlbnQgPSB1bmRlZmluZWQ7CiAgICB9CiAgICBsZXQgeEhlaWdodCA9IGRlc2NyaXB0b3IuZ2V0KCJYSGVpZ2h0Iik7CiAgICBpZiAodHlwZW9mIHhIZWlnaHQgIT09ICJudW1iZXIiKSB7CiAgICAgIHhIZWlnaHQgPSAwOwogICAgfQogICAgbGV0IGNhcEhlaWdodCA9IGRlc2NyaXB0b3IuZ2V0KCJDYXBIZWlnaHQiKTsKICAgIGlmICh0eXBlb2YgY2FwSGVpZ2h0ICE9PSAibnVtYmVyIikgewogICAgICBjYXBIZWlnaHQgPSAwOwogICAgfQogICAgbGV0IGZsYWdzID0gZGVzY3JpcHRvci5nZXQoIkZsYWdzIik7CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoZmxhZ3MpKSB7CiAgICAgIGZsYWdzID0gMDsKICAgIH0KICAgIGxldCBpdGFsaWNBbmdsZSA9IGRlc2NyaXB0b3IuZ2V0KCJJdGFsaWNBbmdsZSIpOwogICAgaWYgKHR5cGVvZiBpdGFsaWNBbmdsZSAhPT0gIm51bWJlciIpIHsKICAgICAgaXRhbGljQW5nbGUgPSAwOwogICAgfQogICAgY29uc3QgcHJvcGVydGllcyA9IHsKICAgICAgdHlwZSwKICAgICAgbmFtZTogZm9udE5hbWUubmFtZSwKICAgICAgc3VidHlwZSwKICAgICAgZmlsZTogZm9udEZpbGUsCiAgICAgIGxlbmd0aDEsCiAgICAgIGxlbmd0aDIsCiAgICAgIGxlbmd0aDMsCiAgICAgIGlzSW50ZXJuYWxGb250LAogICAgICBsb2FkZWROYW1lOiBiYXNlRGljdC5sb2FkZWROYW1lLAogICAgICBjb21wb3NpdGUsCiAgICAgIGZpeGVkUGl0Y2g6IGZhbHNlLAogICAgICBmb250TWF0cml4LAogICAgICBmaXJzdENoYXIsCiAgICAgIGxhc3RDaGFyLAogICAgICB0b1VuaWNvZGUsCiAgICAgIGJib3gsCiAgICAgIGFzY2VudCwKICAgICAgZGVzY2VudCwKICAgICAgeEhlaWdodCwKICAgICAgY2FwSGVpZ2h0LAogICAgICBmbGFncywKICAgICAgaXRhbGljQW5nbGUsCiAgICAgIGlzVHlwZTNGb250LAogICAgICBjc3NGb250SW5mbywKICAgICAgc2NhbGVGYWN0b3JzOiBnbHlwaFNjYWxlRmFjdG9ycywKICAgICAgc3lzdGVtRm9udEluZm8KICAgIH07CiAgICBpZiAoY29tcG9zaXRlKSB7CiAgICAgIGNvbnN0IGNpZEVuY29kaW5nID0gYmFzZURpY3QuZ2V0KCJFbmNvZGluZyIpOwogICAgICBpZiAoY2lkRW5jb2RpbmcgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgcHJvcGVydGllcy5jaWRFbmNvZGluZyA9IGNpZEVuY29kaW5nLm5hbWU7CiAgICAgIH0KICAgICAgY29uc3QgY01hcCA9IGF3YWl0IENNYXBGYWN0b3J5LmNyZWF0ZSh7CiAgICAgICAgZW5jb2Rpbmc6IGNpZEVuY29kaW5nLAogICAgICAgIGZldGNoQnVpbHRJbkNNYXA6IHRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCwKICAgICAgICB1c2VDTWFwOiBudWxsCiAgICAgIH0pOwogICAgICBwcm9wZXJ0aWVzLmNNYXAgPSBjTWFwOwogICAgICBwcm9wZXJ0aWVzLnZlcnRpY2FsID0gcHJvcGVydGllcy5jTWFwLnZlcnRpY2FsOwogICAgfQogICAgY29uc3QgbmV3UHJvcGVydGllcyA9IGF3YWl0IHRoaXMuZXh0cmFjdERhdGFTdHJ1Y3R1cmVzKGRpY3QsIHByb3BlcnRpZXMpOwogICAgdGhpcy5leHRyYWN0V2lkdGhzKGRpY3QsIGRlc2NyaXB0b3IsIG5ld1Byb3BlcnRpZXMpOwogICAgcmV0dXJuIG5ldyBGb250KGZvbnROYW1lLm5hbWUsIGZvbnRGaWxlLCBuZXdQcm9wZXJ0aWVzLCB0aGlzLm9wdGlvbnMpOwogIH0KICBzdGF0aWMgYnVpbGRGb250UGF0aHMoZm9udCwgZ2x5cGhzLCBoYW5kbGVyLCBldmFsdWF0b3JPcHRpb25zKSB7CiAgICBmdW5jdGlvbiBidWlsZFBhdGgoZm9udENoYXIpIHsKICAgICAgY29uc3QgZ2x5cGhOYW1lID0gYCR7Zm9udC5sb2FkZWROYW1lfV9wYXRoXyR7Zm9udENoYXJ9YDsKICAgICAgdHJ5IHsKICAgICAgICBpZiAoZm9udC5yZW5kZXJlci5oYXNCdWlsdFBhdGgoZm9udENoYXIpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IGJ1ZmZlciA9IEZvbnRQYXRoSW5mby53cml0ZShmb250LnJlbmRlcmVyLmdldFBhdGhKcyhmb250Q2hhcikpOwogICAgICAgIGhhbmRsZXIuc2VuZCgiY29tbW9ub2JqIiwgW2dseXBoTmFtZSwgIkZvbnRQYXRoIiwgYnVmZmVyXSwgW2J1ZmZlcl0pOwogICAgICB9IGNhdGNoIChyZWFzb24pIHsKICAgICAgICBpZiAoZXZhbHVhdG9yT3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgIHdhcm4oYGJ1aWxkRm9udFBhdGhzIC0gaWdub3JpbmcgJHtnbHlwaE5hbWV9IGdseXBoOiAiJHtyZWFzb259Ii5gKTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgdGhyb3cgcmVhc29uOwogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IGdseXBoIG9mIGdseXBocykgewogICAgICBidWlsZFBhdGgoZ2x5cGguZm9udENoYXIpOwogICAgICBjb25zdCBhY2NlbnQgPSBnbHlwaC5hY2NlbnQ7CiAgICAgIGlmIChhY2NlbnQ/LmZvbnRDaGFyKSB7CiAgICAgICAgYnVpbGRQYXRoKGFjY2VudC5mb250Q2hhcik7CiAgICAgIH0KICAgIH0KICB9CiAgc3RhdGljIGdldCBmYWxsYmFja0ZvbnREaWN0KCkgewogICAgY29uc3QgZGljdCA9IG5ldyBEaWN0KCk7CiAgICBkaWN0LnNldCgiQmFzZUZvbnQiLCBOYW1lLmdldCgiSGVsdmV0aWNhIikpOwogICAgZGljdC5zZXQoIlR5cGUiLCBOYW1lLmdldCgiRmFsbGJhY2tUeXBlIikpOwogICAgZGljdC5zZXQoIlN1YnR5cGUiLCBOYW1lLmdldCgiRmFsbGJhY2tUeXBlIikpOwogICAgZGljdC5zZXQoIkVuY29kaW5nIiwgTmFtZS5nZXQoIldpbkFuc2lFbmNvZGluZyIpKTsKICAgIHJldHVybiBzaGFkb3codGhpcywgImZhbGxiYWNrRm9udERpY3QiLCBkaWN0KTsKICB9Cn0KY2xhc3MgVHJhbnNsYXRlZEZvbnQgewogICNzZW50ID0gZmFsc2U7CiAgI3R5cGUzTG9hZGVkID0gbnVsbDsKICBjb25zdHJ1Y3Rvcih7CiAgICBsb2FkZWROYW1lLAogICAgZm9udCwKICAgIGRpY3QKICB9KSB7CiAgICB0aGlzLmxvYWRlZE5hbWUgPSBsb2FkZWROYW1lOwogICAgdGhpcy5mb250ID0gZm9udDsKICAgIHRoaXMuZGljdCA9IGRpY3Q7CiAgICB0aGlzLnR5cGUzRGVwZW5kZW5jaWVzID0gZm9udC5pc1R5cGUzRm9udCA/IG5ldyBTZXQoKSA6IG51bGw7CiAgfQogIHNlbmQoaGFuZGxlcikgewogICAgaWYgKHRoaXMuI3NlbnQpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy4jc2VudCA9IHRydWU7CiAgICBjb25zdCBmb250RGF0YSA9IHRoaXMuZm9udC5leHBvcnREYXRhKCk7CiAgICBjb25zdCB0cmFuc2ZlciA9IFtdOwogICAgaWYgKGZvbnREYXRhLmRhdGEpIHsKICAgICAgaWYgKGZvbnREYXRhLmRhdGEuY2hhclByb2NPcGVyYXRvckxpc3QpIHsKICAgICAgICBmb250RGF0YS5jaGFyUHJvY09wZXJhdG9yTGlzdCA9IGZvbnREYXRhLmRhdGEuY2hhclByb2NPcGVyYXRvckxpc3Q7CiAgICAgIH0KICAgICAgZm9udERhdGEuZGF0YSA9IEZvbnRJbmZvLndyaXRlKGZvbnREYXRhLmRhdGEpOwogICAgICB0cmFuc2Zlci5wdXNoKGZvbnREYXRhLmRhdGEpOwogICAgfQogICAgaGFuZGxlci5zZW5kKCJjb21tb25vYmoiLCBbdGhpcy5sb2FkZWROYW1lLCAiRm9udCIsIGZvbnREYXRhXSwgdHJhbnNmZXIpOwogIH0KICBmYWxsYmFjayhoYW5kbGVyLCBldmFsdWF0b3JPcHRpb25zKSB7CiAgICBpZiAoIXRoaXMuZm9udC5kYXRhKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuZm9udC5kaXNhYmxlRm9udEZhY2UgPSB0cnVlOwogICAgUGFydGlhbEV2YWx1YXRvci5idWlsZEZvbnRQYXRocyh0aGlzLmZvbnQsIHRoaXMuZm9udC5nbHlwaENhY2hlVmFsdWVzLCBoYW5kbGVyLCBldmFsdWF0b3JPcHRpb25zKTsKICB9CiAgbG9hZFR5cGUzRGF0YShldmFsdWF0b3IsIHJlc291cmNlcywgdGFzaykgewogICAgaWYgKHRoaXMuI3R5cGUzTG9hZGVkKSB7CiAgICAgIHJldHVybiB0aGlzLiN0eXBlM0xvYWRlZDsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgZm9udCwKICAgICAgdHlwZTNEZXBlbmRlbmNpZXMKICAgIH0gPSB0aGlzOwogICAgYXNzZXJ0KGZvbnQuaXNUeXBlM0ZvbnQsICJNdXN0IGJlIGEgVHlwZTMgZm9udC4iKTsKICAgIGNvbnN0IHR5cGUzRXZhbHVhdG9yID0gZXZhbHVhdG9yLmNsb25lKHsKICAgICAgaWdub3JlRXJyb3JzOiBmYWxzZQogICAgfSk7CiAgICBjb25zdCB0eXBlM0ZvbnRSZWZzID0gbmV3IFJlZlNldChldmFsdWF0b3IudHlwZTNGb250UmVmcyk7CiAgICBpZiAodGhpcy5kaWN0Lm9iaklkICYmICF0eXBlM0ZvbnRSZWZzLmhhcyh0aGlzLmRpY3Qub2JqSWQpKSB7CiAgICAgIHR5cGUzRm9udFJlZnMucHV0KHRoaXMuZGljdC5vYmpJZCk7CiAgICB9CiAgICB0eXBlM0V2YWx1YXRvci50eXBlM0ZvbnRSZWZzID0gdHlwZTNGb250UmVmczsKICAgIGxldCBsb2FkQ2hhclByb2NzUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpOwogICAgY29uc3QgY2hhclByb2NzID0gdGhpcy5kaWN0LmdldCgiQ2hhclByb2NzIik7CiAgICBjb25zdCBmb250UmVzb3VyY2VzID0gdGhpcy5kaWN0LmdldCgiUmVzb3VyY2VzIikgfHwgcmVzb3VyY2VzOwogICAgY29uc3QgY2hhclByb2NPcGVyYXRvckxpc3QgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgY29uc3QgW3gwLCB5MCwgeDEsIHkxXSA9IGZvbnQuYmJveCwKICAgICAgd2lkdGggPSB4MSAtIHgwLAogICAgICBoZWlnaHQgPSB5MSAtIHkwOwogICAgY29uc3QgZm9udEJCb3hTaXplID0gTWF0aC5oeXBvdCh3aWR0aCwgaGVpZ2h0KTsKICAgIGZvciAoY29uc3Qga2V5IG9mIGNoYXJQcm9jcy5nZXRLZXlzKCkpIHsKICAgICAgbG9hZENoYXJQcm9jc1Byb21pc2UgPSBsb2FkQ2hhclByb2NzUHJvbWlzZS50aGVuKCgpID0+IHsKICAgICAgICBjb25zdCBnbHlwaFN0cmVhbSA9IGNoYXJQcm9jcy5nZXQoa2V5KTsKICAgICAgICBjb25zdCBvcGVyYXRvckxpc3QgPSBuZXcgT3BlcmF0b3JMaXN0KCk7CiAgICAgICAgcmV0dXJuIHR5cGUzRXZhbHVhdG9yLmdldE9wZXJhdG9yTGlzdCh7CiAgICAgICAgICBzdHJlYW06IGdseXBoU3RyZWFtLAogICAgICAgICAgdGFzaywKICAgICAgICAgIHJlc291cmNlczogZm9udFJlc291cmNlcywKICAgICAgICAgIG9wZXJhdG9yTGlzdAogICAgICAgIH0pLnRoZW4oKCkgPT4gewogICAgICAgICAgc3dpdGNoIChvcGVyYXRvckxpc3QuZm5BcnJheVswXSkgewogICAgICAgICAgICBjYXNlIE9QUy5zZXRDaGFyV2lkdGhBbmRCb3VuZHM6CiAgICAgICAgICAgICAgdGhpcy4jcmVtb3ZlVHlwZTNDb2xvck9wZXJhdG9ycyhvcGVyYXRvckxpc3QsIGZvbnRCQm94U2l6ZSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgT1BTLnNldENoYXJXaWR0aDoKICAgICAgICAgICAgICBpZiAoIWZvbnRCQm94U2l6ZSkgewogICAgICAgICAgICAgICAgdGhpcy4jZ3Vlc3NUeXBlM0ZvbnRCQm94KG9wZXJhdG9yTGlzdCk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2hhclByb2NPcGVyYXRvckxpc3Rba2V5XSA9IG9wZXJhdG9yTGlzdC5nZXRJUigpOwogICAgICAgICAgZm9yIChjb25zdCBkZXBlbmRlbmN5IG9mIG9wZXJhdG9yTGlzdC5kZXBlbmRlbmNpZXMpIHsKICAgICAgICAgICAgdHlwZTNEZXBlbmRlbmNpZXMuYWRkKGRlcGVuZGVuY3kpOwogICAgICAgICAgfQogICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgIHdhcm4oYFR5cGUzIGZvbnQgcmVzb3VyY2UgIiR7a2V5fSIgaXMgbm90IGF2YWlsYWJsZS5gKTsKICAgICAgICAgIGNvbnN0IGR1bW15T3BlcmF0b3JMaXN0ID0gbmV3IE9wZXJhdG9yTGlzdCgpOwogICAgICAgICAgY2hhclByb2NPcGVyYXRvckxpc3Rba2V5XSA9IGR1bW15T3BlcmF0b3JMaXN0LmdldElSKCk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfQogICAgdGhpcy4jdHlwZTNMb2FkZWQgPSBsb2FkQ2hhclByb2NzUHJvbWlzZS50aGVuKCgpID0+IHsKICAgICAgZm9udC5jaGFyUHJvY09wZXJhdG9yTGlzdCA9IGNoYXJQcm9jT3BlcmF0b3JMaXN0OwogICAgICBpZiAodGhpcy5fYmJveCkgewogICAgICAgIGZvbnQuaXNDaGFyQkJveCA9IHRydWU7CiAgICAgICAgZm9udC5iYm94ID0gdGhpcy5fYmJveDsKICAgICAgfQogICAgfSk7CiAgICByZXR1cm4gdGhpcy4jdHlwZTNMb2FkZWQ7CiAgfQogICNyZW1vdmVUeXBlM0NvbG9yT3BlcmF0b3JzKG9wZXJhdG9yTGlzdCwgZm9udEJCb3hTaXplID0gTmFOKSB7CiAgICBjb25zdCBjaGFyQkJveCA9IFV0aWwubm9ybWFsaXplUmVjdChvcGVyYXRvckxpc3QuYXJnc0FycmF5WzBdLnNsaWNlKDIpKSwKICAgICAgd2lkdGggPSBjaGFyQkJveFsyXSAtIGNoYXJCQm94WzBdLAogICAgICBoZWlnaHQgPSBjaGFyQkJveFszXSAtIGNoYXJCQm94WzFdOwogICAgY29uc3QgY2hhckJCb3hTaXplID0gTWF0aC5oeXBvdCh3aWR0aCwgaGVpZ2h0KTsKICAgIGlmICh3aWR0aCA9PT0gMCB8fCBoZWlnaHQgPT09IDApIHsKICAgICAgb3BlcmF0b3JMaXN0LmZuQXJyYXkuc3BsaWNlKDAsIDEpOwogICAgICBvcGVyYXRvckxpc3QuYXJnc0FycmF5LnNwbGljZSgwLCAxKTsKICAgIH0gZWxzZSBpZiAoZm9udEJCb3hTaXplID09PSAwIHx8IE1hdGgucm91bmQoY2hhckJCb3hTaXplIC8gZm9udEJCb3hTaXplKSA+PSAxMCkgewogICAgICB0aGlzLl9iYm94ID8/PSBbSW5maW5pdHksIEluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV07CiAgICAgIFV0aWwucmVjdEJvdW5kaW5nQm94KC4uLmNoYXJCQm94LCB0aGlzLl9iYm94KTsKICAgIH0KICAgIGxldCBpID0gMCwKICAgICAgaWkgPSBvcGVyYXRvckxpc3QubGVuZ3RoOwogICAgd2hpbGUgKGkgPCBpaSkgewogICAgICBzd2l0Y2ggKG9wZXJhdG9yTGlzdC5mbkFycmF5W2ldKSB7CiAgICAgICAgY2FzZSBPUFMuc2V0Q2hhcldpZHRoQW5kQm91bmRzOgogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBPUFMuc2V0U3Ryb2tlQ29sb3JTcGFjZToKICAgICAgICBjYXNlIE9QUy5zZXRGaWxsQ29sb3JTcGFjZToKICAgICAgICBjYXNlIE9QUy5zZXRTdHJva2VDb2xvcjoKICAgICAgICBjYXNlIE9QUy5zZXRTdHJva2VDb2xvck46CiAgICAgICAgY2FzZSBPUFMuc2V0RmlsbENvbG9yOgogICAgICAgIGNhc2UgT1BTLnNldEZpbGxDb2xvck46CiAgICAgICAgY2FzZSBPUFMuc2V0U3Ryb2tlR3JheToKICAgICAgICBjYXNlIE9QUy5zZXRGaWxsR3JheToKICAgICAgICBjYXNlIE9QUy5zZXRTdHJva2VSR0JDb2xvcjoKICAgICAgICBjYXNlIE9QUy5zZXRGaWxsUkdCQ29sb3I6CiAgICAgICAgY2FzZSBPUFMuc2V0U3Ryb2tlQ01ZS0NvbG9yOgogICAgICAgIGNhc2UgT1BTLnNldEZpbGxDTVlLQ29sb3I6CiAgICAgICAgY2FzZSBPUFMuc2hhZGluZ0ZpbGw6CiAgICAgICAgY2FzZSBPUFMuc2V0UmVuZGVyaW5nSW50ZW50OgogICAgICAgICAgb3BlcmF0b3JMaXN0LmZuQXJyYXkuc3BsaWNlKGksIDEpOwogICAgICAgICAgb3BlcmF0b3JMaXN0LmFyZ3NBcnJheS5zcGxpY2UoaSwgMSk7CiAgICAgICAgICBpaS0tOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgY2FzZSBPUFMuc2V0R1N0YXRlOgogICAgICAgICAgY29uc3QgW2dTdGF0ZU9ial0gPSBvcGVyYXRvckxpc3QuYXJnc0FycmF5W2ldOwogICAgICAgICAgbGV0IGogPSAwLAogICAgICAgICAgICBqaiA9IGdTdGF0ZU9iai5sZW5ndGg7CiAgICAgICAgICB3aGlsZSAoaiA8IGpqKSB7CiAgICAgICAgICAgIGNvbnN0IFtnU3RhdGVLZXldID0gZ1N0YXRlT2JqW2pdOwogICAgICAgICAgICBzd2l0Y2ggKGdTdGF0ZUtleSkgewogICAgICAgICAgICAgIGNhc2UgIlRSIjoKICAgICAgICAgICAgICBjYXNlICJUUjIiOgogICAgICAgICAgICAgIGNhc2UgIkhUIjoKICAgICAgICAgICAgICBjYXNlICJCRyI6CiAgICAgICAgICAgICAgY2FzZSAiQkcyIjoKICAgICAgICAgICAgICBjYXNlICJVQ1IiOgogICAgICAgICAgICAgIGNhc2UgIlVDUjIiOgogICAgICAgICAgICAgICAgZ1N0YXRlT2JqLnNwbGljZShqLCAxKTsKICAgICAgICAgICAgICAgIGpqLS07CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBqKys7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpKys7CiAgICB9CiAgfQogICNndWVzc1R5cGUzRm9udEJCb3gob3BlcmF0b3JMaXN0KSB7CiAgICBsZXQgaSA9IDE7CiAgICBjb25zdCBpaSA9IG9wZXJhdG9yTGlzdC5sZW5ndGg7CiAgICB3aGlsZSAoaSA8IGlpKSB7CiAgICAgIHN3aXRjaCAob3BlcmF0b3JMaXN0LmZuQXJyYXlbaV0pIHsKICAgICAgICBjYXNlIE9QUy5jb25zdHJ1Y3RQYXRoOgogICAgICAgICAgY29uc3QgbWluTWF4ID0gb3BlcmF0b3JMaXN0LmFyZ3NBcnJheVtpXVsyXTsKICAgICAgICAgIHRoaXMuX2Jib3ggPz89IFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XTsKICAgICAgICAgIFV0aWwucmVjdEJvdW5kaW5nQm94KC4uLm1pbk1heCwgdGhpcy5fYmJveCk7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpKys7CiAgICB9CiAgfQp9CmNsYXNzIFN0YXRlTWFuYWdlciB7CiAgY29uc3RydWN0b3IoaW5pdGlhbFN0YXRlID0gbmV3IEV2YWxTdGF0ZSgpKSB7CiAgICB0aGlzLnN0YXRlID0gaW5pdGlhbFN0YXRlOwogICAgdGhpcy5zdGF0ZVN0YWNrID0gW107CiAgfQogIHNhdmUoKSB7CiAgICBjb25zdCBvbGQgPSB0aGlzLnN0YXRlOwogICAgdGhpcy5zdGF0ZVN0YWNrLnB1c2godGhpcy5zdGF0ZSk7CiAgICB0aGlzLnN0YXRlID0gb2xkLmNsb25lKCk7CiAgfQogIHJlc3RvcmUoKSB7CiAgICBjb25zdCBwcmV2ID0gdGhpcy5zdGF0ZVN0YWNrLnBvcCgpOwogICAgaWYgKHByZXYpIHsKICAgICAgdGhpcy5zdGF0ZSA9IHByZXY7CiAgICB9CiAgfQogIHRyYW5zZm9ybShhcmdzKSB7CiAgICB0aGlzLnN0YXRlLmN0bSA9IFV0aWwudHJhbnNmb3JtKHRoaXMuc3RhdGUuY3RtLCBhcmdzKTsKICB9Cn0KY2xhc3MgVGV4dFN0YXRlIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMuY3RtID0gbmV3IEZsb2F0MzJBcnJheShJREVOVElUWV9NQVRSSVgpOwogICAgdGhpcy5mb250TmFtZSA9IG51bGw7CiAgICB0aGlzLmZvbnRTaXplID0gMDsKICAgIHRoaXMubG9hZGVkTmFtZSA9IG51bGw7CiAgICB0aGlzLmZvbnQgPSBudWxsOwogICAgdGhpcy5mb250TWF0cml4ID0gRk9OVF9JREVOVElUWV9NQVRSSVg7CiAgICB0aGlzLnRleHRNYXRyaXggPSBJREVOVElUWV9NQVRSSVguc2xpY2UoKTsKICAgIHRoaXMudGV4dExpbmVNYXRyaXggPSBJREVOVElUWV9NQVRSSVguc2xpY2UoKTsKICAgIHRoaXMuY2hhclNwYWNpbmcgPSAwOwogICAgdGhpcy53b3JkU3BhY2luZyA9IDA7CiAgICB0aGlzLmxlYWRpbmcgPSAwOwogICAgdGhpcy50ZXh0SFNjYWxlID0gMTsKICAgIHRoaXMudGV4dFJpc2UgPSAwOwogIH0KICBzZXRUZXh0TWF0cml4KGEsIGIsIGMsIGQsIGUsIGYpIHsKICAgIGNvbnN0IG0gPSB0aGlzLnRleHRNYXRyaXg7CiAgICBtWzBdID0gYTsKICAgIG1bMV0gPSBiOwogICAgbVsyXSA9IGM7CiAgICBtWzNdID0gZDsKICAgIG1bNF0gPSBlOwogICAgbVs1XSA9IGY7CiAgfQogIHNldFRleHRMaW5lTWF0cml4KGEsIGIsIGMsIGQsIGUsIGYpIHsKICAgIGNvbnN0IG0gPSB0aGlzLnRleHRMaW5lTWF0cml4OwogICAgbVswXSA9IGE7CiAgICBtWzFdID0gYjsKICAgIG1bMl0gPSBjOwogICAgbVszXSA9IGQ7CiAgICBtWzRdID0gZTsKICAgIG1bNV0gPSBmOwogIH0KICB0cmFuc2xhdGVUZXh0TWF0cml4KHgsIHkpIHsKICAgIGNvbnN0IG0gPSB0aGlzLnRleHRNYXRyaXg7CiAgICBtWzRdID0gbVswXSAqIHggKyBtWzJdICogeSArIG1bNF07CiAgICBtWzVdID0gbVsxXSAqIHggKyBtWzNdICogeSArIG1bNV07CiAgfQogIHRyYW5zbGF0ZVRleHRMaW5lTWF0cml4KHgsIHkpIHsKICAgIGNvbnN0IG0gPSB0aGlzLnRleHRMaW5lTWF0cml4OwogICAgbVs0XSA9IG1bMF0gKiB4ICsgbVsyXSAqIHkgKyBtWzRdOwogICAgbVs1XSA9IG1bMV0gKiB4ICsgbVszXSAqIHkgKyBtWzVdOwogIH0KICBjYXJyaWFnZVJldHVybigpIHsKICAgIHRoaXMudHJhbnNsYXRlVGV4dExpbmVNYXRyaXgoMCwgLXRoaXMubGVhZGluZyk7CiAgICB0aGlzLnRleHRNYXRyaXggPSB0aGlzLnRleHRMaW5lTWF0cml4LnNsaWNlKCk7CiAgfQogIGNsb25lKCkgewogICAgY29uc3QgY2xvbmUgPSBPYmplY3QuY3JlYXRlKHRoaXMpOwogICAgY2xvbmUudGV4dE1hdHJpeCA9IHRoaXMudGV4dE1hdHJpeC5zbGljZSgpOwogICAgY2xvbmUudGV4dExpbmVNYXRyaXggPSB0aGlzLnRleHRMaW5lTWF0cml4LnNsaWNlKCk7CiAgICBjbG9uZS5mb250TWF0cml4ID0gdGhpcy5mb250TWF0cml4LnNsaWNlKCk7CiAgICByZXR1cm4gY2xvbmU7CiAgfQp9CmNsYXNzIEV2YWxTdGF0ZSB7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLmN0bSA9IG5ldyBGbG9hdDMyQXJyYXkoSURFTlRJVFlfTUFUUklYKTsKICAgIHRoaXMuZm9udCA9IG51bGw7CiAgICB0aGlzLnRleHRSZW5kZXJpbmdNb2RlID0gVGV4dFJlbmRlcmluZ01vZGUuRklMTDsKICAgIHRoaXMuX2ZpbGxDb2xvclNwYWNlID0gdGhpcy5fc3Ryb2tlQ29sb3JTcGFjZSA9IENvbG9yU3BhY2VVdGlscy5ncmF5OwogICAgdGhpcy5wYXR0ZXJuRmlsbENvbG9yU3BhY2UgPSBudWxsOwogICAgdGhpcy5wYXR0ZXJuU3Ryb2tlQ29sb3JTcGFjZSA9IG51bGw7CiAgICB0aGlzLmN1cnJlbnRQb2ludFggPSB0aGlzLmN1cnJlbnRQb2ludFkgPSAwOwogICAgdGhpcy5wYXRoTWluTWF4ID0gbmV3IEZsb2F0MzJBcnJheShbSW5maW5pdHksIEluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV0pOwogICAgdGhpcy5wYXRoQnVmZmVyID0gW107CiAgfQogIGdldCBmaWxsQ29sb3JTcGFjZSgpIHsKICAgIHJldHVybiB0aGlzLl9maWxsQ29sb3JTcGFjZTsKICB9CiAgc2V0IGZpbGxDb2xvclNwYWNlKGNvbG9yU3BhY2UpIHsKICAgIHRoaXMuX2ZpbGxDb2xvclNwYWNlID0gdGhpcy5wYXR0ZXJuRmlsbENvbG9yU3BhY2UgPSBjb2xvclNwYWNlOwogIH0KICBnZXQgc3Ryb2tlQ29sb3JTcGFjZSgpIHsKICAgIHJldHVybiB0aGlzLl9zdHJva2VDb2xvclNwYWNlOwogIH0KICBzZXQgc3Ryb2tlQ29sb3JTcGFjZShjb2xvclNwYWNlKSB7CiAgICB0aGlzLl9zdHJva2VDb2xvclNwYWNlID0gdGhpcy5wYXR0ZXJuU3Ryb2tlQ29sb3JTcGFjZSA9IGNvbG9yU3BhY2U7CiAgfQogIGNsb25lKHsKICAgIG5ld1BhdGggPSBmYWxzZQogIH0gPSB7fSkgewogICAgY29uc3QgY2xvbmUgPSBPYmplY3QuY3JlYXRlKHRoaXMpOwogICAgaWYgKG5ld1BhdGgpIHsKICAgICAgY2xvbmUucGF0aEJ1ZmZlciA9IFtdOwogICAgICBjbG9uZS5wYXRoTWluTWF4ID0gbmV3IEZsb2F0MzJBcnJheShbSW5maW5pdHksIEluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV0pOwogICAgfQogICAgcmV0dXJuIGNsb25lOwogIH0KfQpjbGFzcyBFdmFsdWF0b3JQcmVwcm9jZXNzb3IgewogIHN0YXRpYyBnZXQgb3BNYXAoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJvcE1hcCIsIE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShudWxsKSwgewogICAgICB3OiB7CiAgICAgICAgaWQ6IE9QUy5zZXRMaW5lV2lkdGgsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIEo6IHsKICAgICAgICBpZDogT1BTLnNldExpbmVDYXAsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIGo6IHsKICAgICAgICBpZDogT1BTLnNldExpbmVKb2luLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBNOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRNaXRlckxpbWl0LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBkOiB7CiAgICAgICAgaWQ6IE9QUy5zZXREYXNoLAogICAgICAgIG51bUFyZ3M6IDIsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICByaTogewogICAgICAgIGlkOiBPUFMuc2V0UmVuZGVyaW5nSW50ZW50LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBpOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRGbGF0bmVzcywKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgZ3M6IHsKICAgICAgICBpZDogT1BTLnNldEdTdGF0ZSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgcTogewogICAgICAgIGlkOiBPUFMuc2F2ZSwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgUTogewogICAgICAgIGlkOiBPUFMucmVzdG9yZSwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgY206IHsKICAgICAgICBpZDogT1BTLnRyYW5zZm9ybSwKICAgICAgICBudW1BcmdzOiA2LAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgbTogewogICAgICAgIGlkOiBPUFMubW92ZVRvLAogICAgICAgIG51bUFyZ3M6IDIsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBsOiB7CiAgICAgICAgaWQ6IE9QUy5saW5lVG8sCiAgICAgICAgbnVtQXJnczogMiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIGM6IHsKICAgICAgICBpZDogT1BTLmN1cnZlVG8sCiAgICAgICAgbnVtQXJnczogNiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIHY6IHsKICAgICAgICBpZDogT1BTLmN1cnZlVG8yLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICB5OiB7CiAgICAgICAgaWQ6IE9QUy5jdXJ2ZVRvMywKICAgICAgICBudW1BcmdzOiA0LAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgaDogewogICAgICAgIGlkOiBPUFMuY2xvc2VQYXRoLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICByZTogewogICAgICAgIGlkOiBPUFMucmVjdGFuZ2xlLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBTOiB7CiAgICAgICAgaWQ6IE9QUy5zdHJva2UsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIHM6IHsKICAgICAgICBpZDogT1BTLmNsb3NlU3Ryb2tlLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBmOiB7CiAgICAgICAgaWQ6IE9QUy5maWxsLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBGOiB7CiAgICAgICAgaWQ6IE9QUy5maWxsLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICAiZioiOiB7CiAgICAgICAgaWQ6IE9QUy5lb0ZpbGwsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIEI6IHsKICAgICAgICBpZDogT1BTLmZpbGxTdHJva2UsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgICJCKiI6IHsKICAgICAgICBpZDogT1BTLmVvRmlsbFN0cm9rZSwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgYjogewogICAgICAgIGlkOiBPUFMuY2xvc2VGaWxsU3Ryb2tlLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICAiYioiOiB7CiAgICAgICAgaWQ6IE9QUy5jbG9zZUVPRmlsbFN0cm9rZSwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgbjogewogICAgICAgIGlkOiBPUFMuZW5kUGF0aCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgVzogewogICAgICAgIGlkOiBPUFMuY2xpcCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgIlcqIjogewogICAgICAgIGlkOiBPUFMuZW9DbGlwLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBCVDogewogICAgICAgIGlkOiBPUFMuYmVnaW5UZXh0LAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBFVDogewogICAgICAgIGlkOiBPUFMuZW5kVGV4dCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgVGM6IHsKICAgICAgICBpZDogT1BTLnNldENoYXJTcGFjaW5nLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBUdzogewogICAgICAgIGlkOiBPUFMuc2V0V29yZFNwYWNpbmcsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIFR6OiB7CiAgICAgICAgaWQ6IE9QUy5zZXRIU2NhbGUsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIFRMOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRMZWFkaW5nLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBUZjogewogICAgICAgIGlkOiBPUFMuc2V0Rm9udCwKICAgICAgICBudW1BcmdzOiAyLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgVHI6IHsKICAgICAgICBpZDogT1BTLnNldFRleHRSZW5kZXJpbmdNb2RlLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBUczogewogICAgICAgIGlkOiBPUFMuc2V0VGV4dFJpc2UsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIFRkOiB7CiAgICAgICAgaWQ6IE9QUy5tb3ZlVGV4dCwKICAgICAgICBudW1BcmdzOiAyLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgVEQ6IHsKICAgICAgICBpZDogT1BTLnNldExlYWRpbmdNb3ZlVGV4dCwKICAgICAgICBudW1BcmdzOiAyLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgVG06IHsKICAgICAgICBpZDogT1BTLnNldFRleHRNYXRyaXgsCiAgICAgICAgbnVtQXJnczogNiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgICJUKiI6IHsKICAgICAgICBpZDogT1BTLm5leHRMaW5lLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBUajogewogICAgICAgIGlkOiBPUFMuc2hvd1RleHQsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIFRKOiB7CiAgICAgICAgaWQ6IE9QUy5zaG93U3BhY2VkVGV4dCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgIiciOiB7CiAgICAgICAgaWQ6IE9QUy5uZXh0TGluZVNob3dUZXh0LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICAnIic6IHsKICAgICAgICBpZDogT1BTLm5leHRMaW5lU2V0U3BhY2luZ1Nob3dUZXh0LAogICAgICAgIG51bUFyZ3M6IDMsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBkMDogewogICAgICAgIGlkOiBPUFMuc2V0Q2hhcldpZHRoLAogICAgICAgIG51bUFyZ3M6IDIsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBkMTogewogICAgICAgIGlkOiBPUFMuc2V0Q2hhcldpZHRoQW5kQm91bmRzLAogICAgICAgIG51bUFyZ3M6IDYsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBDUzogewogICAgICAgIGlkOiBPUFMuc2V0U3Ryb2tlQ29sb3JTcGFjZSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgY3M6IHsKICAgICAgICBpZDogT1BTLnNldEZpbGxDb2xvclNwYWNlLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBTQzogewogICAgICAgIGlkOiBPUFMuc2V0U3Ryb2tlQ29sb3IsCiAgICAgICAgbnVtQXJnczogNCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IHRydWUKICAgICAgfSwKICAgICAgU0NOOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRTdHJva2VDb2xvck4sCiAgICAgICAgbnVtQXJnczogMzMsCiAgICAgICAgdmFyaWFibGVBcmdzOiB0cnVlCiAgICAgIH0sCiAgICAgIHNjOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRGaWxsQ29sb3IsCiAgICAgICAgbnVtQXJnczogNCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IHRydWUKICAgICAgfSwKICAgICAgc2NuOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRGaWxsQ29sb3JOLAogICAgICAgIG51bUFyZ3M6IDMzLAogICAgICAgIHZhcmlhYmxlQXJnczogdHJ1ZQogICAgICB9LAogICAgICBHOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRTdHJva2VHcmF5LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBnOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRGaWxsR3JheSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgUkc6IHsKICAgICAgICBpZDogT1BTLnNldFN0cm9rZVJHQkNvbG9yLAogICAgICAgIG51bUFyZ3M6IDMsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICByZzogewogICAgICAgIGlkOiBPUFMuc2V0RmlsbFJHQkNvbG9yLAogICAgICAgIG51bUFyZ3M6IDMsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBLOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRTdHJva2VDTVlLQ29sb3IsCiAgICAgICAgbnVtQXJnczogNCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIGs6IHsKICAgICAgICBpZDogT1BTLnNldEZpbGxDTVlLQ29sb3IsCiAgICAgICAgbnVtQXJnczogNCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIHNoOiB7CiAgICAgICAgaWQ6IE9QUy5zaGFkaW5nRmlsbCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgQkk6IHsKICAgICAgICBpZDogT1BTLmJlZ2luSW5saW5lSW1hZ2UsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIElEOiB7CiAgICAgICAgaWQ6IE9QUy5iZWdpbkltYWdlRGF0YSwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgRUk6IHsKICAgICAgICBpZDogT1BTLmVuZElubGluZUltYWdlLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBEbzogewogICAgICAgIGlkOiBPUFMucGFpbnRYT2JqZWN0LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBNUDogewogICAgICAgIGlkOiBPUFMubWFya1BvaW50LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBEUDogewogICAgICAgIGlkOiBPUFMubWFya1BvaW50UHJvcHMsCiAgICAgICAgbnVtQXJnczogMiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIEJNQzogewogICAgICAgIGlkOiBPUFMuYmVnaW5NYXJrZWRDb250ZW50LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBCREM6IHsKICAgICAgICBpZDogT1BTLmJlZ2luTWFya2VkQ29udGVudFByb3BzLAogICAgICAgIG51bUFyZ3M6IDIsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBFTUM6IHsKICAgICAgICBpZDogT1BTLmVuZE1hcmtlZENvbnRlbnQsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIEJYOiB7CiAgICAgICAgaWQ6IE9QUy5iZWdpbkNvbXBhdCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgRVg6IHsKICAgICAgICBpZDogT1BTLmVuZENvbXBhdCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgQk06IG51bGwsCiAgICAgIEJEOiBudWxsLAogICAgICB0cnVlOiBudWxsLAogICAgICBmYTogbnVsbCwKICAgICAgZmFsOiBudWxsLAogICAgICBmYWxzOiBudWxsLAogICAgICBmYWxzZTogbnVsbCwKICAgICAgbnU6IG51bGwsCiAgICAgIG51bDogbnVsbCwKICAgICAgbnVsbDogbnVsbAogICAgfSkpOwogIH0KICBzdGF0aWMgTUFYX0lOVkFMSURfUEFUSF9PUFMgPSAxMDsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIHhyZWYsIHN0YXRlTWFuYWdlciA9IG5ldyBTdGF0ZU1hbmFnZXIoKSkgewogICAgdGhpcy5wYXJzZXIgPSBuZXcgUGFyc2VyKHsKICAgICAgbGV4ZXI6IG5ldyBMZXhlcihzdHJlYW0sIEV2YWx1YXRvclByZXByb2Nlc3Nvci5vcE1hcCksCiAgICAgIHhyZWYKICAgIH0pOwogICAgdGhpcy5zdGF0ZU1hbmFnZXIgPSBzdGF0ZU1hbmFnZXI7CiAgICB0aGlzLm5vblByb2Nlc3NlZEFyZ3MgPSBbXTsKICAgIHRoaXMuX2lzUGF0aE9wID0gZmFsc2U7CiAgICB0aGlzLl9udW1JbnZhbGlkUGF0aE9QUyA9IDA7CiAgfQogIGdldCBzYXZlZFN0YXRlc0RlcHRoKCkgewogICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyLnN0YXRlU3RhY2subGVuZ3RoOwogIH0KICByZWFkKG9wZXJhdGlvbikgewogICAgbGV0IGFyZ3MgPSBvcGVyYXRpb24uYXJnczsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGNvbnN0IG9iaiA9IHRoaXMucGFyc2VyLmdldE9iaigpOwogICAgICBpZiAob2JqIGluc3RhbmNlb2YgQ21kKSB7CiAgICAgICAgY29uc3QgY21kID0gb2JqLmNtZDsKICAgICAgICBjb25zdCBvcFNwZWMgPSBFdmFsdWF0b3JQcmVwcm9jZXNzb3Iub3BNYXBbY21kXTsKICAgICAgICBpZiAoIW9wU3BlYykgewogICAgICAgICAgd2FybihgVW5rbm93biBjb21tYW5kICIke2NtZH0iLmApOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGZuID0gb3BTcGVjLmlkOwogICAgICAgIGNvbnN0IG51bUFyZ3MgPSBvcFNwZWMubnVtQXJnczsKICAgICAgICBsZXQgYXJnc0xlbmd0aCA9IGFyZ3MgIT09IG51bGwgPyBhcmdzLmxlbmd0aCA6IDA7CiAgICAgICAgaWYgKCF0aGlzLl9pc1BhdGhPcCkgewogICAgICAgICAgdGhpcy5fbnVtSW52YWxpZFBhdGhPUFMgPSAwOwogICAgICAgIH0KICAgICAgICB0aGlzLl9pc1BhdGhPcCA9IGZuID49IE9QUy5tb3ZlVG8gJiYgZm4gPD0gT1BTLmVuZFBhdGg7CiAgICAgICAgaWYgKCFvcFNwZWMudmFyaWFibGVBcmdzKSB7CiAgICAgICAgICBpZiAoYXJnc0xlbmd0aCAhPT0gbnVtQXJncykgewogICAgICAgICAgICBjb25zdCBub25Qcm9jZXNzZWRBcmdzID0gdGhpcy5ub25Qcm9jZXNzZWRBcmdzOwogICAgICAgICAgICB3aGlsZSAoYXJnc0xlbmd0aCA+IG51bUFyZ3MpIHsKICAgICAgICAgICAgICBub25Qcm9jZXNzZWRBcmdzLnB1c2goYXJncy5zaGlmdCgpKTsKICAgICAgICAgICAgICBhcmdzTGVuZ3RoLS07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgd2hpbGUgKGFyZ3NMZW5ndGggPCBudW1BcmdzICYmIG5vblByb2Nlc3NlZEFyZ3MubGVuZ3RoICE9PSAwKSB7CiAgICAgICAgICAgICAgaWYgKGFyZ3MgPT09IG51bGwpIHsKICAgICAgICAgICAgICAgIGFyZ3MgPSBbXTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYXJncy51bnNoaWZ0KG5vblByb2Nlc3NlZEFyZ3MucG9wKCkpOwogICAgICAgICAgICAgIGFyZ3NMZW5ndGgrKzsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGFyZ3NMZW5ndGggPCBudW1BcmdzKSB7CiAgICAgICAgICAgIGNvbnN0IHBhcnRpYWxNc2cgPSBgY29tbWFuZCAke2NtZH06IGV4cGVjdGVkICR7bnVtQXJnc30gYXJncywgYCArIGBidXQgcmVjZWl2ZWQgJHthcmdzTGVuZ3RofSBhcmdzLmA7CiAgICAgICAgICAgIGlmICh0aGlzLl9pc1BhdGhPcCAmJiArK3RoaXMuX251bUludmFsaWRQYXRoT1BTID4gRXZhbHVhdG9yUHJlcHJvY2Vzc29yLk1BWF9JTlZBTElEX1BBVEhfT1BTKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkICR7cGFydGlhbE1zZ31gKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB3YXJuKGBTa2lwcGluZyAke3BhcnRpYWxNc2d9YCk7CiAgICAgICAgICAgIGlmIChhcmdzICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgYXJncy5sZW5ndGggPSAwOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoYXJnc0xlbmd0aCA+IG51bUFyZ3MpIHsKICAgICAgICAgIGluZm8oYENvbW1hbmQgJHtjbWR9OiBleHBlY3RlZCBbMCwgJHtudW1BcmdzfV0gYXJncywgYCArIGBidXQgcmVjZWl2ZWQgJHthcmdzTGVuZ3RofSBhcmdzLmApOwogICAgICAgIH0KICAgICAgICB0aGlzLnByZXByb2Nlc3NDb21tYW5kKGZuLCBhcmdzKTsKICAgICAgICBvcGVyYXRpb24uZm4gPSBmbjsKICAgICAgICBvcGVyYXRpb24uYXJncyA9IGFyZ3M7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKG9iaiA9PT0gRU9GKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChvYmogIT09IG51bGwpIHsKICAgICAgICBpZiAoYXJncyA9PT0gbnVsbCkgewogICAgICAgICAgYXJncyA9IFtdOwogICAgICAgIH0KICAgICAgICBhcmdzLnB1c2gob2JqKTsKICAgICAgICBpZiAoYXJncy5sZW5ndGggPiAzMykgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJUb28gbWFueSBhcmd1bWVudHMiKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgcHJlcHJvY2Vzc0NvbW1hbmQoZm4sIGFyZ3MpIHsKICAgIHN3aXRjaCAoZm4gfCAwKSB7CiAgICAgIGNhc2UgT1BTLnNhdmU6CiAgICAgICAgdGhpcy5zdGF0ZU1hbmFnZXIuc2F2ZSgpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIE9QUy5yZXN0b3JlOgogICAgICAgIHRoaXMuc3RhdGVNYW5hZ2VyLnJlc3RvcmUoKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBPUFMudHJhbnNmb3JtOgogICAgICAgIHRoaXMuc3RhdGVNYW5hZ2VyLnRyYW5zZm9ybShhcmdzKTsKICAgICAgICBicmVhazsKICAgIH0KICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2RlZmF1bHRfYXBwZWFyYW5jZS5qcwoKCgoKCgoKCmNsYXNzIERlZmF1bHRBcHBlYXJhbmNlRXZhbHVhdG9yIGV4dGVuZHMgRXZhbHVhdG9yUHJlcHJvY2Vzc29yIHsKICBjb25zdHJ1Y3RvcihzdHIpIHsKICAgIHN1cGVyKG5ldyBTdHJpbmdTdHJlYW0oc3RyKSk7CiAgfQogIHBhcnNlKCkgewogICAgY29uc3Qgb3BlcmF0aW9uID0gewogICAgICBmbjogMCwKICAgICAgYXJnczogW10KICAgIH07CiAgICBjb25zdCByZXN1bHQgPSB7CiAgICAgIGZvbnRTaXplOiAwLAogICAgICBmb250TmFtZTogIiIsCiAgICAgIGZvbnRDb2xvcjogbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDMpCiAgICB9OwogICAgdHJ5IHsKICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICBvcGVyYXRpb24uYXJncy5sZW5ndGggPSAwOwogICAgICAgIGlmICghdGhpcy5yZWFkKG9wZXJhdGlvbikpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAodGhpcy5zYXZlZFN0YXRlc0RlcHRoICE9PSAwKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgewogICAgICAgICAgZm4sCiAgICAgICAgICBhcmdzCiAgICAgICAgfSA9IG9wZXJhdGlvbjsKICAgICAgICBzd2l0Y2ggKGZuIHwgMCkgewogICAgICAgICAgY2FzZSBPUFMuc2V0Rm9udDoKICAgICAgICAgICAgY29uc3QgW2ZvbnROYW1lLCBmb250U2l6ZV0gPSBhcmdzOwogICAgICAgICAgICBpZiAoZm9udE5hbWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgICAgcmVzdWx0LmZvbnROYW1lID0gZm9udE5hbWUubmFtZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodHlwZW9mIGZvbnRTaXplID09PSAibnVtYmVyIiAmJiBmb250U2l6ZSA+IDApIHsKICAgICAgICAgICAgICByZXN1bHQuZm9udFNpemUgPSBmb250U2l6ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldEZpbGxSR0JDb2xvcjoKICAgICAgICAgICAgQ29sb3JTcGFjZVV0aWxzLnJnYi5nZXRSZ2JJdGVtKGFyZ3MsIDAsIHJlc3VsdC5mb250Q29sb3IsIDApOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldEZpbGxHcmF5OgogICAgICAgICAgICBDb2xvclNwYWNlVXRpbHMuZ3JheS5nZXRSZ2JJdGVtKGFyZ3MsIDAsIHJlc3VsdC5mb250Q29sb3IsIDApOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldEZpbGxDTVlLQ29sb3I6CiAgICAgICAgICAgIENvbG9yU3BhY2VVdGlscy5jbXlrLmdldFJnYkl0ZW0oYXJncywgMCwgcmVzdWx0LmZvbnRDb2xvciwgMCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIHdhcm4oYHBhcnNlRGVmYXVsdEFwcGVhcmFuY2UgLSBpZ25vcmluZyBlcnJvcnM6ICIke3JlYXNvbn0iLmApOwogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9Cn0KZnVuY3Rpb24gcGFyc2VEZWZhdWx0QXBwZWFyYW5jZShzdHIpIHsKICByZXR1cm4gbmV3IERlZmF1bHRBcHBlYXJhbmNlRXZhbHVhdG9yKHN0cikucGFyc2UoKTsKfQpjbGFzcyBBcHBlYXJhbmNlU3RyZWFtRXZhbHVhdG9yIGV4dGVuZHMgRXZhbHVhdG9yUHJlcHJvY2Vzc29yIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIGV2YWx1YXRvck9wdGlvbnMsIHhyZWYsIGdsb2JhbENvbG9yU3BhY2VDYWNoZSkgewogICAgc3VwZXIoc3RyZWFtKTsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy5ldmFsdWF0b3JPcHRpb25zID0gZXZhbHVhdG9yT3B0aW9uczsKICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgICB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSA9IGdsb2JhbENvbG9yU3BhY2VDYWNoZTsKICAgIHRoaXMucmVzb3VyY2VzID0gc3RyZWFtLmRpY3Q/LmdldCgiUmVzb3VyY2VzIik7CiAgfQogIHBhcnNlKCkgewogICAgY29uc3Qgb3BlcmF0aW9uID0gewogICAgICBmbjogMCwKICAgICAgYXJnczogW10KICAgIH07CiAgICBsZXQgcmVzdWx0ID0gewogICAgICBzY2FsZUZhY3RvcjogMSwKICAgICAgZm9udFNpemU6IDAsCiAgICAgIGZvbnROYW1lOiAiIiwKICAgICAgZm9udENvbG9yOiBuZXcgVWludDhDbGFtcGVkQXJyYXkoMyksCiAgICAgIGZpbGxDb2xvclNwYWNlOiBDb2xvclNwYWNlVXRpbHMuZ3JheQogICAgfTsKICAgIGxldCBicmVha0xvb3AgPSBmYWxzZTsKICAgIGNvbnN0IHN0YWNrID0gW107CiAgICB0cnkgewogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgIG9wZXJhdGlvbi5hcmdzLmxlbmd0aCA9IDA7CiAgICAgICAgaWYgKGJyZWFrTG9vcCB8fCAhdGhpcy5yZWFkKG9wZXJhdGlvbikpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjb25zdCB7CiAgICAgICAgICBmbiwKICAgICAgICAgIGFyZ3MKICAgICAgICB9ID0gb3BlcmF0aW9uOwogICAgICAgIHN3aXRjaCAoZm4gfCAwKSB7CiAgICAgICAgICBjYXNlIE9QUy5zYXZlOgogICAgICAgICAgICBzdGFjay5wdXNoKHsKICAgICAgICAgICAgICBzY2FsZUZhY3RvcjogcmVzdWx0LnNjYWxlRmFjdG9yLAogICAgICAgICAgICAgIGZvbnRTaXplOiByZXN1bHQuZm9udFNpemUsCiAgICAgICAgICAgICAgZm9udE5hbWU6IHJlc3VsdC5mb250TmFtZSwKICAgICAgICAgICAgICBmb250Q29sb3I6IHJlc3VsdC5mb250Q29sb3Iuc2xpY2UoKSwKICAgICAgICAgICAgICBmaWxsQ29sb3JTcGFjZTogcmVzdWx0LmZpbGxDb2xvclNwYWNlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnJlc3RvcmU6CiAgICAgICAgICAgIHJlc3VsdCA9IHN0YWNrLnBvcCgpIHx8IHJlc3VsdDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRUZXh0TWF0cml4OgogICAgICAgICAgICByZXN1bHQuc2NhbGVGYWN0b3IgKj0gTWF0aC5oeXBvdChhcmdzWzBdLCBhcmdzWzFdKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGb250OgogICAgICAgICAgICBjb25zdCBbZm9udE5hbWUsIGZvbnRTaXplXSA9IGFyZ3M7CiAgICAgICAgICAgIGlmIChmb250TmFtZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgICAgICByZXN1bHQuZm9udE5hbWUgPSBmb250TmFtZS5uYW1lOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh0eXBlb2YgZm9udFNpemUgPT09ICJudW1iZXIiICYmIGZvbnRTaXplID4gMCkgewogICAgICAgICAgICAgIHJlc3VsdC5mb250U2l6ZSA9IGZvbnRTaXplICogcmVzdWx0LnNjYWxlRmFjdG9yOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0RmlsbENvbG9yU3BhY2U6CiAgICAgICAgICAgIHJlc3VsdC5maWxsQ29sb3JTcGFjZSA9IENvbG9yU3BhY2VVdGlscy5wYXJzZSh7CiAgICAgICAgICAgICAgY3M6IGFyZ3NbMF0sCiAgICAgICAgICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICAgICAgICAgIHJlc291cmNlczogdGhpcy5yZXNvdXJjZXMsCiAgICAgICAgICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5OiB0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgICAgICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOiB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZTogdGhpcy5fbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0RmlsbENvbG9yOgogICAgICAgICAgICBjb25zdCBjcyA9IHJlc3VsdC5maWxsQ29sb3JTcGFjZTsKICAgICAgICAgICAgY3MuZ2V0UmdiSXRlbShhcmdzLCAwLCByZXN1bHQuZm9udENvbG9yLCAwKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGaWxsUkdCQ29sb3I6CiAgICAgICAgICAgIENvbG9yU3BhY2VVdGlscy5yZ2IuZ2V0UmdiSXRlbShhcmdzLCAwLCByZXN1bHQuZm9udENvbG9yLCAwKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGaWxsR3JheToKICAgICAgICAgICAgQ29sb3JTcGFjZVV0aWxzLmdyYXkuZ2V0UmdiSXRlbShhcmdzLCAwLCByZXN1bHQuZm9udENvbG9yLCAwKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGaWxsQ01ZS0NvbG9yOgogICAgICAgICAgICBDb2xvclNwYWNlVXRpbHMuY215ay5nZXRSZ2JJdGVtKGFyZ3MsIDAsIHJlc3VsdC5mb250Q29sb3IsIDApOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNob3dUZXh0OgogICAgICAgICAgY2FzZSBPUFMuc2hvd1NwYWNlZFRleHQ6CiAgICAgICAgICBjYXNlIE9QUy5uZXh0TGluZVNob3dUZXh0OgogICAgICAgICAgY2FzZSBPUFMubmV4dExpbmVTZXRTcGFjaW5nU2hvd1RleHQ6CiAgICAgICAgICAgIGJyZWFrTG9vcCA9IHRydWU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIHdhcm4oYHBhcnNlQXBwZWFyYW5jZVN0cmVhbSAtIGlnbm9yaW5nIGVycm9yczogIiR7cmVhc29ufSIuYCk7CiAgICB9CiAgICB0aGlzLnN0cmVhbS5yZXNldCgpOwogICAgZGVsZXRlIHJlc3VsdC5zY2FsZUZhY3RvcjsKICAgIGRlbGV0ZSByZXN1bHQuZmlsbENvbG9yU3BhY2U7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICBnZXQgX2xvY2FsQ29sb3JTcGFjZUNhY2hlKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiX2xvY2FsQ29sb3JTcGFjZUNhY2hlIiwgbmV3IExvY2FsQ29sb3JTcGFjZUNhY2hlKCkpOwogIH0KICBnZXQgX3BkZkZ1bmN0aW9uRmFjdG9yeSgpIHsKICAgIGNvbnN0IHBkZkZ1bmN0aW9uRmFjdG9yeSA9IG5ldyBQREZGdW5jdGlvbkZhY3RvcnkoewogICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgIGlzRXZhbFN1cHBvcnRlZDogdGhpcy5ldmFsdWF0b3JPcHRpb25zLmlzRXZhbFN1cHBvcnRlZAogICAgfSk7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJfcGRmRnVuY3Rpb25GYWN0b3J5IiwgcGRmRnVuY3Rpb25GYWN0b3J5KTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VBcHBlYXJhbmNlU3RyZWFtKHN0cmVhbSwgZXZhbHVhdG9yT3B0aW9ucywgeHJlZiwgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlKSB7CiAgcmV0dXJuIG5ldyBBcHBlYXJhbmNlU3RyZWFtRXZhbHVhdG9yKHN0cmVhbSwgZXZhbHVhdG9yT3B0aW9ucywgeHJlZiwgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlKS5wYXJzZSgpOwp9CmZ1bmN0aW9uIGdldFBkZkNvbG9yKGNvbG9yLCBpc0ZpbGwpIHsKICBpZiAoY29sb3JbMF0gPT09IGNvbG9yWzFdICYmIGNvbG9yWzFdID09PSBjb2xvclsyXSkgewogICAgY29uc3QgZ3JheSA9IGNvbG9yWzBdIC8gMjU1OwogICAgcmV0dXJuIGAke251bWJlclRvU3RyaW5nKGdyYXkpfSAke2lzRmlsbCA/ICJnIiA6ICJHIn1gOwogIH0KICByZXR1cm4gQXJyYXkuZnJvbShjb2xvciwgYyA9PiBudW1iZXJUb1N0cmluZyhjIC8gMjU1KSkuam9pbigiICIpICsgYCAke2lzRmlsbCA/ICJyZyIgOiAiUkcifWA7Cn0KZnVuY3Rpb24gY3JlYXRlRGVmYXVsdEFwcGVhcmFuY2UoewogIGZvbnRTaXplLAogIGZvbnROYW1lLAogIGZvbnRDb2xvcgp9KSB7CiAgcmV0dXJuIGAvJHtlc2NhcGVQREZOYW1lKGZvbnROYW1lKX0gJHtmb250U2l6ZX0gVGYgJHtnZXRQZGZDb2xvcihmb250Q29sb3IsIHRydWUpfWA7Cn0KY2xhc3MgRmFrZVVuaWNvZGVGb250IHsKICBjb25zdHJ1Y3Rvcih4cmVmLCBmb250RmFtaWx5KSB7CiAgICB0aGlzLnhyZWYgPSB4cmVmOwogICAgdGhpcy53aWR0aHMgPSBudWxsOwogICAgdGhpcy5maXJzdENoYXIgPSBJbmZpbml0eTsKICAgIHRoaXMubGFzdENoYXIgPSAtSW5maW5pdHk7CiAgICB0aGlzLmZvbnRGYW1pbHkgPSBmb250RmFtaWx5OwogICAgY29uc3QgY2FudmFzID0gbmV3IE9mZnNjcmVlbkNhbnZhcygxLCAxKTsKICAgIHRoaXMuY3R4TWVhc3VyZSA9IGNhbnZhcy5nZXRDb250ZXh0KCIyZCIsIHsKICAgICAgd2lsbFJlYWRGcmVxdWVudGx5OiB0cnVlCiAgICB9KTsKICAgIGlmICghRmFrZVVuaWNvZGVGb250Ll9mb250TmFtZUlkKSB7CiAgICAgIEZha2VVbmljb2RlRm9udC5fZm9udE5hbWVJZCA9IDE7CiAgICB9CiAgICB0aGlzLmZvbnROYW1lID0gTmFtZS5nZXQoYEludmFsaWRQREZqc0ZvbnRfJHtmb250RmFtaWx5fV8ke0Zha2VVbmljb2RlRm9udC5fZm9udE5hbWVJZCsrfWApOwogIH0KICBnZXQgZm9udERlc2NyaXB0b3JSZWYoKSB7CiAgICBpZiAoIUZha2VVbmljb2RlRm9udC5fZm9udERlc2NyaXB0b3JSZWYpIHsKICAgICAgY29uc3QgZm9udERlc2NyaXB0b3IgPSBuZXcgRGljdCh0aGlzLnhyZWYpOwogICAgICBmb250RGVzY3JpcHRvci5zZXRJZk5hbWUoIlR5cGUiLCAiRm9udERlc2NyaXB0b3IiKTsKICAgICAgZm9udERlc2NyaXB0b3Iuc2V0KCJGb250TmFtZSIsIHRoaXMuZm9udE5hbWUpOwogICAgICBmb250RGVzY3JpcHRvci5zZXQoIkZvbnRGYW1pbHkiLCAiTXlyaWFkUHJvIFJlZ3VsYXIiKTsKICAgICAgZm9udERlc2NyaXB0b3Iuc2V0KCJGb250QkJveCIsIFswLCAwLCAwLCAwXSk7CiAgICAgIGZvbnREZXNjcmlwdG9yLnNldElmTmFtZSgiRm9udFN0cmV0Y2giLCAiTm9ybWFsIik7CiAgICAgIGZvbnREZXNjcmlwdG9yLnNldCgiRm9udFdlaWdodCIsIDQwMCk7CiAgICAgIGZvbnREZXNjcmlwdG9yLnNldCgiSXRhbGljQW5nbGUiLCAwKTsKICAgICAgRmFrZVVuaWNvZGVGb250Ll9mb250RGVzY3JpcHRvclJlZiA9IHRoaXMueHJlZi5nZXROZXdQZXJzaXN0ZW50UmVmKGZvbnREZXNjcmlwdG9yKTsKICAgIH0KICAgIHJldHVybiBGYWtlVW5pY29kZUZvbnQuX2ZvbnREZXNjcmlwdG9yUmVmOwogIH0KICBnZXQgZGVzY2VuZGFudEZvbnRSZWYoKSB7CiAgICBjb25zdCBkZXNjZW5kYW50Rm9udCA9IG5ldyBEaWN0KHRoaXMueHJlZik7CiAgICBkZXNjZW5kYW50Rm9udC5zZXQoIkJhc2VGb250IiwgdGhpcy5mb250TmFtZSk7CiAgICBkZXNjZW5kYW50Rm9udC5zZXRJZk5hbWUoIlR5cGUiLCAiRm9udCIpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIkNJREZvbnRUeXBlMCIpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0SWZOYW1lKCJDSURUb0dJRE1hcCIsICJJZGVudGl0eSIpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0KCJGaXJzdENoYXIiLCB0aGlzLmZpcnN0Q2hhcik7CiAgICBkZXNjZW5kYW50Rm9udC5zZXQoIkxhc3RDaGFyIiwgdGhpcy5sYXN0Q2hhcik7CiAgICBkZXNjZW5kYW50Rm9udC5zZXQoIkZvbnREZXNjcmlwdG9yIiwgdGhpcy5mb250RGVzY3JpcHRvclJlZik7CiAgICBkZXNjZW5kYW50Rm9udC5zZXQoIkRXIiwgMTAwMCk7CiAgICBjb25zdCB3aWR0aHMgPSBbXTsKICAgIGNvbnN0IGNoYXJzID0gWy4uLnRoaXMud2lkdGhzLmVudHJpZXMoKV0uc29ydCgpOwogICAgbGV0IGN1cnJlbnRDaGFyID0gbnVsbDsKICAgIGxldCBjdXJyZW50V2lkdGhzID0gbnVsbDsKICAgIGZvciAoY29uc3QgW2NoYXIsIHdpZHRoXSBvZiBjaGFycykgewogICAgICBpZiAoIWN1cnJlbnRDaGFyKSB7CiAgICAgICAgY3VycmVudENoYXIgPSBjaGFyOwogICAgICAgIGN1cnJlbnRXaWR0aHMgPSBbd2lkdGhdOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChjaGFyID09PSBjdXJyZW50Q2hhciArIGN1cnJlbnRXaWR0aHMubGVuZ3RoKSB7CiAgICAgICAgY3VycmVudFdpZHRocy5wdXNoKHdpZHRoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB3aWR0aHMucHVzaChjdXJyZW50Q2hhciwgY3VycmVudFdpZHRocyk7CiAgICAgICAgY3VycmVudENoYXIgPSBjaGFyOwogICAgICAgIGN1cnJlbnRXaWR0aHMgPSBbd2lkdGhdOwogICAgICB9CiAgICB9CiAgICBpZiAoY3VycmVudENoYXIpIHsKICAgICAgd2lkdGhzLnB1c2goY3VycmVudENoYXIsIGN1cnJlbnRXaWR0aHMpOwogICAgfQogICAgZGVzY2VuZGFudEZvbnQuc2V0KCJXIiwgd2lkdGhzKTsKICAgIGNvbnN0IGNpZFN5c3RlbUluZm8gPSBuZXcgRGljdCh0aGlzLnhyZWYpOwogICAgY2lkU3lzdGVtSW5mby5zZXQoIk9yZGVyaW5nIiwgIklkZW50aXR5Iik7CiAgICBjaWRTeXN0ZW1JbmZvLnNldCgiUmVnaXN0cnkiLCAiQWRvYmUiKTsKICAgIGNpZFN5c3RlbUluZm8uc2V0KCJTdXBwbGVtZW50IiwgMCk7CiAgICBkZXNjZW5kYW50Rm9udC5zZXQoIkNJRFN5c3RlbUluZm8iLCBjaWRTeXN0ZW1JbmZvKTsKICAgIHJldHVybiB0aGlzLnhyZWYuZ2V0TmV3UGVyc2lzdGVudFJlZihkZXNjZW5kYW50Rm9udCk7CiAgfQogIGdldCBiYXNlRm9udFJlZigpIHsKICAgIGNvbnN0IGJhc2VGb250ID0gbmV3IERpY3QodGhpcy54cmVmKTsKICAgIGJhc2VGb250LnNldCgiQmFzZUZvbnQiLCB0aGlzLmZvbnROYW1lKTsKICAgIGJhc2VGb250LnNldElmTmFtZSgiVHlwZSIsICJGb250Iik7CiAgICBiYXNlRm9udC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiVHlwZTAiKTsKICAgIGJhc2VGb250LnNldElmTmFtZSgiRW5jb2RpbmciLCAiSWRlbnRpdHktSCIpOwogICAgYmFzZUZvbnQuc2V0KCJEZXNjZW5kYW50Rm9udHMiLCBbdGhpcy5kZXNjZW5kYW50Rm9udFJlZl0pOwogICAgYmFzZUZvbnQuc2V0SWZOYW1lKCJUb1VuaWNvZGUiLCAiSWRlbnRpdHktSCIpOwogICAgcmV0dXJuIHRoaXMueHJlZi5nZXROZXdQZXJzaXN0ZW50UmVmKGJhc2VGb250KTsKICB9CiAgZ2V0IHJlc291cmNlcygpIHsKICAgIGNvbnN0IHJlc291cmNlcyA9IG5ldyBEaWN0KHRoaXMueHJlZik7CiAgICBjb25zdCBmb250ID0gbmV3IERpY3QodGhpcy54cmVmKTsKICAgIGZvbnQuc2V0KHRoaXMuZm9udE5hbWUubmFtZSwgdGhpcy5iYXNlRm9udFJlZik7CiAgICByZXNvdXJjZXMuc2V0KCJGb250IiwgZm9udCk7CiAgICByZXR1cm4gcmVzb3VyY2VzOwogIH0KICBfY3JlYXRlQ29udGV4dCgpIHsKICAgIHRoaXMud2lkdGhzID0gbmV3IE1hcCgpOwogICAgdGhpcy5jdHhNZWFzdXJlLmZvbnQgPSBgMTAwMHB4ICR7dGhpcy5mb250RmFtaWx5fWA7CiAgICByZXR1cm4gdGhpcy5jdHhNZWFzdXJlOwogIH0KICBjcmVhdGVGb250UmVzb3VyY2VzKHRleHQpIHsKICAgIGNvbnN0IGN0eCA9IHRoaXMuX2NyZWF0ZUNvbnRleHQoKTsKICAgIGZvciAoY29uc3QgbGluZSBvZiB0ZXh0LnNwbGl0KC9cclxuP3xcbi8pKSB7CiAgICAgIGZvciAoY29uc3QgY2hhciBvZiBsaW5lLnNwbGl0KCIiKSkgewogICAgICAgIGNvbnN0IGNvZGUgPSBjaGFyLmNoYXJDb2RlQXQoMCk7CiAgICAgICAgaWYgKHRoaXMud2lkdGhzLmhhcyhjb2RlKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG1ldHJpY3MgPSBjdHgubWVhc3VyZVRleHQoY2hhcik7CiAgICAgICAgY29uc3Qgd2lkdGggPSBNYXRoLmNlaWwobWV0cmljcy53aWR0aCk7CiAgICAgICAgdGhpcy53aWR0aHMuc2V0KGNvZGUsIHdpZHRoKTsKICAgICAgICB0aGlzLmZpcnN0Q2hhciA9IE1hdGgubWluKGNvZGUsIHRoaXMuZmlyc3RDaGFyKTsKICAgICAgICB0aGlzLmxhc3RDaGFyID0gTWF0aC5tYXgoY29kZSwgdGhpcy5sYXN0Q2hhcik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB0aGlzLnJlc291cmNlczsKICB9CiAgc3RhdGljIGdldEZpcnN0UG9zaXRpb25JbmZvKHJlY3QsIHJvdGF0aW9uLCBmb250U2l6ZSkgewogICAgY29uc3QgW3gxLCB5MSwgeDIsIHkyXSA9IHJlY3Q7CiAgICBsZXQgdyA9IHgyIC0geDE7CiAgICBsZXQgaCA9IHkyIC0geTE7CiAgICBpZiAocm90YXRpb24gJSAxODAgIT09IDApIHsKICAgICAgW3csIGhdID0gW2gsIHddOwogICAgfQogICAgY29uc3QgbGluZUhlaWdodCA9IExJTkVfRkFDVE9SICogZm9udFNpemU7CiAgICBjb25zdCBsaW5lRGVzY2VudCA9IExJTkVfREVTQ0VOVF9GQUNUT1IgKiBmb250U2l6ZTsKICAgIHJldHVybiB7CiAgICAgIGNvb3JkczogWzAsIGggKyBsaW5lRGVzY2VudCAtIGxpbmVIZWlnaHRdLAogICAgICBiYm94OiBbMCwgMCwgdywgaF0sCiAgICAgIG1hdHJpeDogcm90YXRpb24gIT09IDAgPyBnZXRSb3RhdGlvbk1hdHJpeChyb3RhdGlvbiwgaCwgbGluZUhlaWdodCkgOiB1bmRlZmluZWQKICAgIH07CiAgfQogIGNyZWF0ZUFwcGVhcmFuY2UodGV4dCwgcmVjdCwgcm90YXRpb24sIGZvbnRTaXplLCBiZ0NvbG9yLCBzdHJva2VBbHBoYSkgewogICAgY29uc3QgY3R4ID0gdGhpcy5fY3JlYXRlQ29udGV4dCgpOwogICAgY29uc3QgbGluZXMgPSBbXTsKICAgIGxldCBtYXhXaWR0aCA9IC1JbmZpbml0eTsKICAgIGZvciAoY29uc3QgbGluZSBvZiB0ZXh0LnNwbGl0KC9cclxuP3xcbi8pKSB7CiAgICAgIGxpbmVzLnB1c2gobGluZSk7CiAgICAgIGNvbnN0IGxpbmVXaWR0aCA9IGN0eC5tZWFzdXJlVGV4dChsaW5lKS53aWR0aDsKICAgICAgbWF4V2lkdGggPSBNYXRoLm1heChtYXhXaWR0aCwgbGluZVdpZHRoKTsKICAgICAgZm9yIChjb25zdCBjb2RlIG9mIGNvZGVQb2ludEl0ZXIobGluZSkpIHsKICAgICAgICBjb25zdCBjaGFyID0gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZSk7CiAgICAgICAgbGV0IHdpZHRoID0gdGhpcy53aWR0aHMuZ2V0KGNvZGUpOwogICAgICAgIGlmICh3aWR0aCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBjb25zdCBtZXRyaWNzID0gY3R4Lm1lYXN1cmVUZXh0KGNoYXIpOwogICAgICAgICAgd2lkdGggPSBNYXRoLmNlaWwobWV0cmljcy53aWR0aCk7CiAgICAgICAgICB0aGlzLndpZHRocy5zZXQoY29kZSwgd2lkdGgpOwogICAgICAgICAgdGhpcy5maXJzdENoYXIgPSBNYXRoLm1pbihjb2RlLCB0aGlzLmZpcnN0Q2hhcik7CiAgICAgICAgICB0aGlzLmxhc3RDaGFyID0gTWF0aC5tYXgoY29kZSwgdGhpcy5sYXN0Q2hhcik7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBtYXhXaWR0aCAqPSBmb250U2l6ZSAvIDEwMDA7CiAgICBjb25zdCBbeDEsIHkxLCB4MiwgeTJdID0gcmVjdDsKICAgIGxldCB3ID0geDIgLSB4MTsKICAgIGxldCBoID0geTIgLSB5MTsKICAgIGlmIChyb3RhdGlvbiAlIDE4MCAhPT0gMCkgewogICAgICBbdywgaF0gPSBbaCwgd107CiAgICB9CiAgICBsZXQgaHNjYWxlID0gMTsKICAgIGlmIChtYXhXaWR0aCA+IHcpIHsKICAgICAgaHNjYWxlID0gdyAvIG1heFdpZHRoOwogICAgfQogICAgbGV0IHZzY2FsZSA9IDE7CiAgICBjb25zdCBsaW5lSGVpZ2h0ID0gTElORV9GQUNUT1IgKiBmb250U2l6ZTsKICAgIGNvbnN0IGxpbmVEZXNjZW50ID0gTElORV9ERVNDRU5UX0ZBQ1RPUiAqIGZvbnRTaXplOwogICAgY29uc3QgbWF4SGVpZ2h0ID0gbGluZUhlaWdodCAqIGxpbmVzLmxlbmd0aDsKICAgIGlmIChtYXhIZWlnaHQgPiBoKSB7CiAgICAgIHZzY2FsZSA9IGggLyBtYXhIZWlnaHQ7CiAgICB9CiAgICBjb25zdCBmc2NhbGUgPSBNYXRoLm1pbihoc2NhbGUsIHZzY2FsZSk7CiAgICBjb25zdCBuZXdGb250U2l6ZSA9IGZvbnRTaXplICogZnNjYWxlOwogICAgY29uc3QgYnVmZmVyID0gWyJxIiwgYDAgMCAke251bWJlclRvU3RyaW5nKHcpfSAke251bWJlclRvU3RyaW5nKGgpfSByZSBXIG5gLCBgQlRgLCBgMSAwIDAgMSAwICR7bnVtYmVyVG9TdHJpbmcoaCArIGxpbmVEZXNjZW50KX0gVG0gMCBUYyAke2dldFBkZkNvbG9yKGJnQ29sb3IsIHRydWUpfWAsIGAvJHt0aGlzLmZvbnROYW1lLm5hbWV9ICR7bnVtYmVyVG9TdHJpbmcobmV3Rm9udFNpemUpfSBUZmBdOwogICAgY29uc3QgewogICAgICByZXNvdXJjZXMKICAgIH0gPSB0aGlzOwogICAgc3Ryb2tlQWxwaGEgPSB0eXBlb2Ygc3Ryb2tlQWxwaGEgPT09ICJudW1iZXIiICYmIHN0cm9rZUFscGhhID49IDAgJiYgc3Ryb2tlQWxwaGEgPD0gMSA/IHN0cm9rZUFscGhhIDogMTsKICAgIGlmIChzdHJva2VBbHBoYSAhPT0gMSkgewogICAgICBidWZmZXIucHVzaCgiL1IwIGdzIik7CiAgICAgIGNvbnN0IGV4dEdTdGF0ZSA9IG5ldyBEaWN0KHRoaXMueHJlZik7CiAgICAgIGNvbnN0IHIwID0gbmV3IERpY3QodGhpcy54cmVmKTsKICAgICAgcjAuc2V0KCJjYSIsIHN0cm9rZUFscGhhKTsKICAgICAgcjAuc2V0KCJDQSIsIHN0cm9rZUFscGhhKTsKICAgICAgcjAuc2V0SWZOYW1lKCJUeXBlIiwgIkV4dEdTdGF0ZSIpOwogICAgICBleHRHU3RhdGUuc2V0KCJSMCIsIHIwKTsKICAgICAgcmVzb3VyY2VzLnNldCgiRXh0R1N0YXRlIiwgZXh0R1N0YXRlKTsKICAgIH0KICAgIGNvbnN0IHZTaGlmdCA9IG51bWJlclRvU3RyaW5nKGxpbmVIZWlnaHQpOwogICAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7CiAgICAgIGJ1ZmZlci5wdXNoKGAwIC0ke3ZTaGlmdH0gVGQgPCR7c3RyaW5nVG9VVEYxNkhleFN0cmluZyhsaW5lKX0+IFRqYCk7CiAgICB9CiAgICBidWZmZXIucHVzaCgiRVQiLCAiUSIpOwogICAgY29uc3QgYXBwZWFyYW5jZSA9IGJ1ZmZlci5qb2luKCJcbiIpOwogICAgY29uc3QgYXBwZWFyYW5jZVN0cmVhbURpY3QgPSBuZXcgRGljdCh0aGlzLnhyZWYpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIkZvcm0iKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldElmTmFtZSgiVHlwZSIsICJYT2JqZWN0Iik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkJCb3giLCBbMCwgMCwgdywgaF0pOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJMZW5ndGgiLCBhcHBlYXJhbmNlLmxlbmd0aCk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlJlc291cmNlcyIsIHJlc291cmNlcyk7CiAgICBpZiAocm90YXRpb24pIHsKICAgICAgY29uc3QgbWF0cml4ID0gZ2V0Um90YXRpb25NYXRyaXgocm90YXRpb24sIHcsIGgpOwogICAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIk1hdHJpeCIsIG1hdHJpeCk7CiAgICB9CiAgICBjb25zdCBhcCA9IG5ldyBTdHJpbmdTdHJlYW0oYXBwZWFyYW5jZSk7CiAgICBhcC5kaWN0ID0gYXBwZWFyYW5jZVN0cmVhbURpY3Q7CiAgICByZXR1cm4gYXA7CiAgfQp9Cgo7Ly8gLi9zcmMvc2hhcmVkL3NjcmlwdGluZ191dGlscy5qcwpmdW5jdGlvbiBtYWtlQ29sb3JDb21wKG4pIHsKICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBuKSkgKiAyNTUpLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAiMCIpOwp9CmZ1bmN0aW9uIHNjYWxlQW5kQ2xhbXAoeCkgewogIHJldHVybiBNYXRoLm1heCgwLCBNYXRoLm1pbigyNTUsIDI1NSAqIHgpKTsKfQpjbGFzcyBDb2xvckNvbnZlcnRlcnMgewogIHN0YXRpYyBDTVlLX0coW2MsIHksIG0sIGtdKSB7CiAgICByZXR1cm4gWyJHIiwgMSAtIE1hdGgubWluKDEsIDAuMyAqIGMgKyAwLjU5ICogbSArIDAuMTEgKiB5ICsgayldOwogIH0KICBzdGF0aWMgR19DTVlLKFtnXSkgewogICAgcmV0dXJuIFsiQ01ZSyIsIDAsIDAsIDAsIDEgLSBnXTsKICB9CiAgc3RhdGljIEdfUkdCKFtnXSkgewogICAgcmV0dXJuIFsiUkdCIiwgZywgZywgZ107CiAgfQogIHN0YXRpYyBHX3JnYihbZ10pIHsKICAgIGcgPSBzY2FsZUFuZENsYW1wKGcpOwogICAgcmV0dXJuIFtnLCBnLCBnXTsKICB9CiAgc3RhdGljIEdfSFRNTChbZ10pIHsKICAgIGNvbnN0IEcgPSBtYWtlQ29sb3JDb21wKGcpOwogICAgcmV0dXJuIGAjJHtHfSR7R30ke0d9YDsKICB9CiAgc3RhdGljIFJHQl9HKFtyLCBnLCBiXSkgewogICAgcmV0dXJuIFsiRyIsIDAuMyAqIHIgKyAwLjU5ICogZyArIDAuMTEgKiBiXTsKICB9CiAgc3RhdGljIFJHQl9yZ2IoY29sb3IpIHsKICAgIHJldHVybiBjb2xvci5tYXAoc2NhbGVBbmRDbGFtcCk7CiAgfQogIHN0YXRpYyBSR0JfSFRNTChjb2xvcikgewogICAgcmV0dXJuIGAjJHtjb2xvci5tYXAobWFrZUNvbG9yQ29tcCkuam9pbigiIil9YDsKICB9CiAgc3RhdGljIFRfSFRNTCgpIHsKICAgIHJldHVybiAiIzAwMDAwMDAwIjsKICB9CiAgc3RhdGljIFRfcmdiKCkgewogICAgcmV0dXJuIFtudWxsXTsKICB9CiAgc3RhdGljIENNWUtfUkdCKFtjLCB5LCBtLCBrXSkgewogICAgcmV0dXJuIFsiUkdCIiwgMSAtIE1hdGgubWluKDEsIGMgKyBrKSwgMSAtIE1hdGgubWluKDEsIG0gKyBrKSwgMSAtIE1hdGgubWluKDEsIHkgKyBrKV07CiAgfQogIHN0YXRpYyBDTVlLX3JnYihbYywgeSwgbSwga10pIHsKICAgIHJldHVybiBbc2NhbGVBbmRDbGFtcCgxIC0gTWF0aC5taW4oMSwgYyArIGspKSwgc2NhbGVBbmRDbGFtcCgxIC0gTWF0aC5taW4oMSwgbSArIGspKSwgc2NhbGVBbmRDbGFtcCgxIC0gTWF0aC5taW4oMSwgeSArIGspKV07CiAgfQogIHN0YXRpYyBDTVlLX0hUTUwoY29tcG9uZW50cykgewogICAgY29uc3QgcmdiID0gdGhpcy5DTVlLX1JHQihjb21wb25lbnRzKS5zbGljZSgxKTsKICAgIHJldHVybiB0aGlzLlJHQl9IVE1MKHJnYik7CiAgfQogIHN0YXRpYyBSR0JfQ01ZSyhbciwgZywgYl0pIHsKICAgIGNvbnN0IGMgPSAxIC0gcjsKICAgIGNvbnN0IG0gPSAxIC0gZzsKICAgIGNvbnN0IHkgPSAxIC0gYjsKICAgIGNvbnN0IGsgPSBNYXRoLm1pbihjLCBtLCB5KTsKICAgIHJldHVybiBbIkNNWUsiLCBjLCBtLCB5LCBrXTsKICB9Cn0KY29uc3QgRGF0ZUZvcm1hdHMgPSBbIm0vZCIsICJtL2QveXkiLCAibW0vZGQveXkiLCAibW0veXkiLCAiZC1tbW0iLCAiZC1tbW0teXkiLCAiZGQtbW1tLXl5IiwgInl5LW1tLWRkIiwgIm1tbS15eSIsICJtbW1tLXl5IiwgIm1tbSBkLCB5eXl5IiwgIm1tbW0gZCwgeXl5eSIsICJtL2QveXkgaDpNTSB0dCIsICJtL2QveXkgSEg6TU0iXTsKY29uc3QgVGltZUZvcm1hdHMgPSBbIkhIOk1NIiwgImg6TU0gdHQiLCAiSEg6TU06c3MiLCAiaDpNTTpzcyB0dCJdOwoKOy8vIC4vc3JjL2NvcmUvbmFtZV9udW1iZXJfdHJlZS5qcwoKCmNsYXNzIE5hbWVPck51bWJlclRyZWUgewogIGNvbnN0cnVjdG9yKHJvb3QsIHhyZWYsIHR5cGUpIHsKICAgIHRoaXMucm9vdCA9IHJvb3Q7CiAgICB0aGlzLnhyZWYgPSB4cmVmOwogICAgdGhpcy5fdHlwZSA9IHR5cGU7CiAgfQogIGdldEFsbChpc1JhdyA9IGZhbHNlKSB7CiAgICBjb25zdCBtYXAgPSBuZXcgTWFwKCk7CiAgICBpZiAoIXRoaXMucm9vdCkgewogICAgICByZXR1cm4gbWFwOwogICAgfQogICAgY29uc3QgeHJlZiA9IHRoaXMueHJlZjsKICAgIGNvbnN0IHByb2Nlc3NlZCA9IG5ldyBSZWZTZXQoKTsKICAgIHByb2Nlc3NlZC5wdXQodGhpcy5yb290KTsKICAgIGNvbnN0IHF1ZXVlID0gW3RoaXMucm9vdF07CiAgICB3aGlsZSAocXVldWUubGVuZ3RoID4gMCkgewogICAgICBjb25zdCBvYmogPSB4cmVmLmZldGNoSWZSZWYocXVldWUuc2hpZnQoKSk7CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKG9iai5oYXMoIktpZHMiKSkgewogICAgICAgIGNvbnN0IGtpZHMgPSBvYmouZ2V0KCJLaWRzIik7CiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGtpZHMpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgZm9yIChjb25zdCBraWQgb2Yga2lkcykgewogICAgICAgICAgaWYgKHByb2Nlc3NlZC5oYXMoa2lkKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYER1cGxpY2F0ZSBlbnRyeSBpbiAiJHt0aGlzLl90eXBlfSIgdHJlZS5gKTsKICAgICAgICAgIH0KICAgICAgICAgIHF1ZXVlLnB1c2goa2lkKTsKICAgICAgICAgIHByb2Nlc3NlZC5wdXQoa2lkKTsKICAgICAgICB9CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgZW50cmllcyA9IG9iai5nZXQodGhpcy5fdHlwZSk7CiAgICAgIGlmICghQXJyYXkuaXNBcnJheShlbnRyaWVzKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGVudHJpZXMubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgIG1hcC5zZXQoeHJlZi5mZXRjaElmUmVmKGVudHJpZXNbaV0pLCBpc1JhdyA/IGVudHJpZXNbaSArIDFdIDogeHJlZi5mZXRjaElmUmVmKGVudHJpZXNbaSArIDFdKSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBtYXA7CiAgfQogIGdldFJhdyhrZXkpIHsKICAgIGlmICghdGhpcy5yb290KSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgeHJlZiA9IHRoaXMueHJlZjsKICAgIGxldCBraWRzT3JFbnRyaWVzID0geHJlZi5mZXRjaElmUmVmKHRoaXMucm9vdCk7CiAgICBsZXQgbG9vcENvdW50ID0gMDsKICAgIGNvbnN0IE1BWF9MRVZFTFMgPSAxMDsKICAgIHdoaWxlIChraWRzT3JFbnRyaWVzLmhhcygiS2lkcyIpKSB7CiAgICAgIGlmICgrK2xvb3BDb3VudCA+IE1BWF9MRVZFTFMpIHsKICAgICAgICB3YXJuKGBTZWFyY2ggZGVwdGggbGltaXQgcmVhY2hlZCBmb3IgIiR7dGhpcy5fdHlwZX0iIHRyZWUuYCk7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgY29uc3Qga2lkcyA9IGtpZHNPckVudHJpZXMuZ2V0KCJLaWRzIik7CiAgICAgIGlmICghQXJyYXkuaXNBcnJheShraWRzKSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGxldCBsID0gMCwKICAgICAgICByID0ga2lkcy5sZW5ndGggLSAxOwogICAgICB3aGlsZSAobCA8PSByKSB7CiAgICAgICAgY29uc3QgbSA9IGwgKyByID4+IDE7CiAgICAgICAgY29uc3Qga2lkID0geHJlZi5mZXRjaElmUmVmKGtpZHNbbV0pOwogICAgICAgIGNvbnN0IGxpbWl0cyA9IGtpZC5nZXQoIkxpbWl0cyIpOwogICAgICAgIGlmIChrZXkgPCB4cmVmLmZldGNoSWZSZWYobGltaXRzWzBdKSkgewogICAgICAgICAgciA9IG0gLSAxOwogICAgICAgIH0gZWxzZSBpZiAoa2V5ID4geHJlZi5mZXRjaElmUmVmKGxpbWl0c1sxXSkpIHsKICAgICAgICAgIGwgPSBtICsgMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAga2lkc09yRW50cmllcyA9IGtpZDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAobCA+IHIpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQogICAgY29uc3QgZW50cmllcyA9IGtpZHNPckVudHJpZXMuZ2V0KHRoaXMuX3R5cGUpOwogICAgaWYgKEFycmF5LmlzQXJyYXkoZW50cmllcykpIHsKICAgICAgbGV0IGwgPSAwLAogICAgICAgIHIgPSBlbnRyaWVzLmxlbmd0aCAtIDI7CiAgICAgIHdoaWxlIChsIDw9IHIpIHsKICAgICAgICBjb25zdCB0bXAgPSBsICsgciA+PiAxLAogICAgICAgICAgbSA9IHRtcCArICh0bXAgJiAxKTsKICAgICAgICBjb25zdCBjdXJyZW50S2V5ID0geHJlZi5mZXRjaElmUmVmKGVudHJpZXNbbV0pOwogICAgICAgIGlmIChrZXkgPCBjdXJyZW50S2V5KSB7CiAgICAgICAgICByID0gbSAtIDI7CiAgICAgICAgfSBlbHNlIGlmIChrZXkgPiBjdXJyZW50S2V5KSB7CiAgICAgICAgICBsID0gbSArIDI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBlbnRyaWVzW20gKyAxXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICBnZXQoa2V5KSB7CiAgICByZXR1cm4gdGhpcy54cmVmLmZldGNoSWZSZWYodGhpcy5nZXRSYXcoa2V5KSk7CiAgfQp9CmNsYXNzIE5hbWVUcmVlIGV4dGVuZHMgTmFtZU9yTnVtYmVyVHJlZSB7CiAgY29uc3RydWN0b3Iocm9vdCwgeHJlZikgewogICAgc3VwZXIocm9vdCwgeHJlZiwgIk5hbWVzIik7CiAgfQp9CmNsYXNzIE51bWJlclRyZWUgZXh0ZW5kcyBOYW1lT3JOdW1iZXJUcmVlIHsKICBjb25zdHJ1Y3Rvcihyb290LCB4cmVmKSB7CiAgICBzdXBlcihyb290LCB4cmVmLCAiTnVtcyIpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvY2xlYW51cF9oZWxwZXIuanMKCgoKCmZ1bmN0aW9uIGNsZWFyR2xvYmFsQ2FjaGVzKCkgewogIGNsZWFyUGF0dGVybkNhY2hlcygpOwogIGNsZWFyUHJpbWl0aXZlQ2FjaGVzKCk7CiAgY2xlYXJVbmljb2RlQ2FjaGVzKCk7CiAgSnB4SW1hZ2UuY2xlYW51cCgpOwp9Cgo7Ly8gLi9zcmMvY29yZS9maWxlX3NwZWMuanMKCgoKZnVuY3Rpb24gcGlja1BsYXRmb3JtSXRlbShkaWN0KSB7CiAgaWYgKGRpY3QgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICBmb3IgKGNvbnN0IGtleSBvZiBbIlVGIiwgIkYiLCAiVW5peCIsICJNYWMiLCAiRE9TIl0pIHsKICAgICAgaWYgKGRpY3QuaGFzKGtleSkpIHsKICAgICAgICByZXR1cm4gZGljdC5nZXQoa2V5KTsKICAgICAgfQogICAgfQogIH0KICByZXR1cm4gbnVsbDsKfQpmdW5jdGlvbiBzdHJpcFBhdGgoc3RyKSB7CiAgcmV0dXJuIHN0ci5zdWJzdHJpbmcoc3RyLmxhc3RJbmRleE9mKCIvIikgKyAxKTsKfQpjbGFzcyBGaWxlU3BlYyB7CiAgI2NvbnRlbnRBdmFpbGFibGUgPSBmYWxzZTsKICBjb25zdHJ1Y3Rvcihyb290LCBza2lwQ29udGVudCA9IGZhbHNlKSB7CiAgICBpZiAoIShyb290IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5yb290ID0gcm9vdDsKICAgIGlmIChyb290LmhhcygiRlMiKSkgewogICAgICB0aGlzLmZzID0gcm9vdC5nZXQoIkZTIik7CiAgICB9CiAgICBpZiAocm9vdC5oYXMoIlJGIikpIHsKICAgICAgd2FybigiUmVsYXRlZCBmaWxlIHNwZWNpZmljYXRpb25zIGFyZSBub3Qgc3VwcG9ydGVkIik7CiAgICB9CiAgICBpZiAoIXNraXBDb250ZW50KSB7CiAgICAgIGlmIChyb290LmhhcygiRUYiKSkgewogICAgICAgIHRoaXMuI2NvbnRlbnRBdmFpbGFibGUgPSB0cnVlOwogICAgICB9IGVsc2UgewogICAgICAgIHdhcm4oIk5vbi1lbWJlZGRlZCBmaWxlIHNwZWNpZmljYXRpb25zIGFyZSBub3Qgc3VwcG9ydGVkIik7CiAgICAgIH0KICAgIH0KICB9CiAgZ2V0IGZpbGVuYW1lKCkgewogICAgY29uc3QgaXRlbSA9IHBpY2tQbGF0Zm9ybUl0ZW0odGhpcy5yb290KTsKICAgIGlmIChpdGVtICYmIHR5cGVvZiBpdGVtID09PSAic3RyaW5nIikgewogICAgICByZXR1cm4gc3RyaW5nVG9QREZTdHJpbmcoaXRlbSwgdHJ1ZSkucmVwbGFjZUFsbCgiXFxcXCIsICJcXCIpLnJlcGxhY2VBbGwoIlxcLyIsICIvIikucmVwbGFjZUFsbCgiXFwiLCAiLyIpOwogICAgfQogICAgcmV0dXJuICIiOwogIH0KICBnZXQgY29udGVudCgpIHsKICAgIGlmICghdGhpcy4jY29udGVudEF2YWlsYWJsZSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGVmID0gcGlja1BsYXRmb3JtSXRlbSh0aGlzLnJvb3Q/LmdldCgiRUYiKSk7CiAgICBpZiAoZWYgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgIHJldHVybiBlZi5nZXRCeXRlcygpOwogICAgfQogICAgd2FybigiRW1iZWRkZWQgZmlsZSBzcGVjaWZpY2F0aW9uIHBvaW50cyB0byBub24tZXhpc3RpbmcvaW52YWxpZCBjb250ZW50Iik7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgZ2V0IGRlc2NyaXB0aW9uKCkgewogICAgY29uc3QgZGVzYyA9IHRoaXMucm9vdD8uZ2V0KCJEZXNjIik7CiAgICBpZiAoZGVzYyAmJiB0eXBlb2YgZGVzYyA9PT0gInN0cmluZyIpIHsKICAgICAgcmV0dXJuIHN0cmluZ1RvUERGU3RyaW5nKGRlc2MpOwogICAgfQogICAgcmV0dXJuICIiOwogIH0KICBnZXQgc2VyaWFsaXphYmxlKCkgewogICAgY29uc3QgewogICAgICBmaWxlbmFtZSwKICAgICAgY29udGVudCwKICAgICAgZGVzY3JpcHRpb24KICAgIH0gPSB0aGlzOwogICAgcmV0dXJuIHsKICAgICAgcmF3RmlsZW5hbWU6IGZpbGVuYW1lLAogICAgICBmaWxlbmFtZTogc3RyaXBQYXRoKGZpbGVuYW1lKSB8fCAidW5uYW1lZCIsCiAgICAgIGNvbnRlbnQsCiAgICAgIGRlc2NyaXB0aW9uCiAgICB9OwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveG1sX3BhcnNlci5qcwoKY29uc3QgWE1MUGFyc2VyRXJyb3JDb2RlID0gewogIE5vRXJyb3I6IDAsCiAgRW5kT2ZEb2N1bWVudDogLTEsCiAgVW50ZXJtaW5hdGVkQ2RhdDogLTIsCiAgVW50ZXJtaW5hdGVkWG1sRGVjbGFyYXRpb246IC0zLAogIFVudGVybWluYXRlZERvY3R5cGVEZWNsYXJhdGlvbjogLTQsCiAgVW50ZXJtaW5hdGVkQ29tbWVudDogLTUsCiAgTWFsZm9ybWVkRWxlbWVudDogLTYsCiAgT3V0T2ZNZW1vcnk6IC03LAogIFVudGVybWluYXRlZEF0dHJpYnV0ZVZhbHVlOiAtOCwKICBVbnRlcm1pbmF0ZWRFbGVtZW50OiAtOSwKICBFbGVtZW50TmV2ZXJCZWd1bjogLTEwCn07CmZ1bmN0aW9uIGlzV2hpdGVzcGFjZShzLCBpbmRleCkgewogIGNvbnN0IGNoID0gc1tpbmRleF07CiAgcmV0dXJuIGNoID09PSAiICIgfHwgY2ggPT09ICJcbiIgfHwgY2ggPT09ICJcciIgfHwgY2ggPT09ICJcdCI7Cn0KZnVuY3Rpb24gaXNXaGl0ZXNwYWNlU3RyaW5nKHMpIHsKICBmb3IgKGxldCBpID0gMCwgaWkgPSBzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGlmICghaXNXaGl0ZXNwYWNlKHMsIGkpKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9CiAgcmV0dXJuIHRydWU7Cn0KY2xhc3MgWE1MUGFyc2VyQmFzZSB7CiAgX3Jlc29sdmVFbnRpdGllcyhzKSB7CiAgICByZXR1cm4gcy5yZXBsYWNlQWxsKC8mKFteO10rKTsvZywgKGFsbCwgZW50aXR5KSA9PiB7CiAgICAgIGlmIChlbnRpdHkuc3Vic3RyaW5nKDAsIDIpID09PSAiI3giKSB7CiAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KHBhcnNlSW50KGVudGl0eS5zdWJzdHJpbmcoMiksIDE2KSk7CiAgICAgIH0gZWxzZSBpZiAoZW50aXR5LnN1YnN0cmluZygwLCAxKSA9PT0gIiMiKSB7CiAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KHBhcnNlSW50KGVudGl0eS5zdWJzdHJpbmcoMSksIDEwKSk7CiAgICAgIH0KICAgICAgc3dpdGNoIChlbnRpdHkpIHsKICAgICAgICBjYXNlICJsdCI6CiAgICAgICAgICByZXR1cm4gIjwiOwogICAgICAgIGNhc2UgImd0IjoKICAgICAgICAgIHJldHVybiAiPiI7CiAgICAgICAgY2FzZSAiYW1wIjoKICAgICAgICAgIHJldHVybiAiJiI7CiAgICAgICAgY2FzZSAicXVvdCI6CiAgICAgICAgICByZXR1cm4gJyInOwogICAgICAgIGNhc2UgImFwb3MiOgogICAgICAgICAgcmV0dXJuICInIjsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5vblJlc29sdmVFbnRpdHkoZW50aXR5KTsKICAgIH0pOwogIH0KICBfcGFyc2VDb250ZW50KHMsIHN0YXJ0KSB7CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gW107CiAgICBsZXQgcG9zID0gc3RhcnQ7CiAgICBmdW5jdGlvbiBza2lwV3MoKSB7CiAgICAgIHdoaWxlIChwb3MgPCBzLmxlbmd0aCAmJiBpc1doaXRlc3BhY2UocywgcG9zKSkgewogICAgICAgICsrcG9zOwogICAgICB9CiAgICB9CiAgICB3aGlsZSAocG9zIDwgcy5sZW5ndGggJiYgIWlzV2hpdGVzcGFjZShzLCBwb3MpICYmIHNbcG9zXSAhPT0gIj4iICYmIHNbcG9zXSAhPT0gIi8iKSB7CiAgICAgICsrcG9zOwogICAgfQogICAgY29uc3QgbmFtZSA9IHMuc3Vic3RyaW5nKHN0YXJ0LCBwb3MpOwogICAgc2tpcFdzKCk7CiAgICB3aGlsZSAocG9zIDwgcy5sZW5ndGggJiYgc1twb3NdICE9PSAiPiIgJiYgc1twb3NdICE9PSAiLyIgJiYgc1twb3NdICE9PSAiPyIpIHsKICAgICAgc2tpcFdzKCk7CiAgICAgIGxldCBhdHRyTmFtZSA9ICIiLAogICAgICAgIGF0dHJWYWx1ZSA9ICIiOwogICAgICB3aGlsZSAocG9zIDwgcy5sZW5ndGggJiYgIWlzV2hpdGVzcGFjZShzLCBwb3MpICYmIHNbcG9zXSAhPT0gIj0iKSB7CiAgICAgICAgYXR0ck5hbWUgKz0gc1twb3NdOwogICAgICAgICsrcG9zOwogICAgICB9CiAgICAgIHNraXBXcygpOwogICAgICBpZiAoc1twb3NdICE9PSAiPSIpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICArK3BvczsKICAgICAgc2tpcFdzKCk7CiAgICAgIGNvbnN0IGF0dHJFbmRDaGFyID0gc1twb3NdOwogICAgICBpZiAoYXR0ckVuZENoYXIgIT09ICciJyAmJiBhdHRyRW5kQ2hhciAhPT0gIiciKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgY29uc3QgYXR0ckVuZEluZGV4ID0gcy5pbmRleE9mKGF0dHJFbmRDaGFyLCArK3Bvcyk7CiAgICAgIGlmIChhdHRyRW5kSW5kZXggPCAwKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgYXR0clZhbHVlID0gcy5zdWJzdHJpbmcocG9zLCBhdHRyRW5kSW5kZXgpOwogICAgICBhdHRyaWJ1dGVzLnB1c2goewogICAgICAgIG5hbWU6IGF0dHJOYW1lLAogICAgICAgIHZhbHVlOiB0aGlzLl9yZXNvbHZlRW50aXRpZXMoYXR0clZhbHVlKQogICAgICB9KTsKICAgICAgcG9zID0gYXR0ckVuZEluZGV4ICsgMTsKICAgICAgc2tpcFdzKCk7CiAgICB9CiAgICByZXR1cm4gewogICAgICBuYW1lLAogICAgICBhdHRyaWJ1dGVzLAogICAgICBwYXJzZWQ6IHBvcyAtIHN0YXJ0CiAgICB9OwogIH0KICBfcGFyc2VQcm9jZXNzaW5nSW5zdHJ1Y3Rpb24ocywgc3RhcnQpIHsKICAgIGxldCBwb3MgPSBzdGFydDsKICAgIGZ1bmN0aW9uIHNraXBXcygpIHsKICAgICAgd2hpbGUgKHBvcyA8IHMubGVuZ3RoICYmIGlzV2hpdGVzcGFjZShzLCBwb3MpKSB7CiAgICAgICAgKytwb3M7CiAgICAgIH0KICAgIH0KICAgIHdoaWxlIChwb3MgPCBzLmxlbmd0aCAmJiAhaXNXaGl0ZXNwYWNlKHMsIHBvcykgJiYgc1twb3NdICE9PSAiPiIgJiYgc1twb3NdICE9PSAiPyIgJiYgc1twb3NdICE9PSAiLyIpIHsKICAgICAgKytwb3M7CiAgICB9CiAgICBjb25zdCBuYW1lID0gcy5zdWJzdHJpbmcoc3RhcnQsIHBvcyk7CiAgICBza2lwV3MoKTsKICAgIGNvbnN0IGF0dHJTdGFydCA9IHBvczsKICAgIHdoaWxlIChwb3MgPCBzLmxlbmd0aCAmJiAoc1twb3NdICE9PSAiPyIgfHwgc1twb3MgKyAxXSAhPT0gIj4iKSkgewogICAgICArK3BvczsKICAgIH0KICAgIGNvbnN0IHZhbHVlID0gcy5zdWJzdHJpbmcoYXR0clN0YXJ0LCBwb3MpOwogICAgcmV0dXJuIHsKICAgICAgbmFtZSwKICAgICAgdmFsdWUsCiAgICAgIHBhcnNlZDogcG9zIC0gc3RhcnQKICAgIH07CiAgfQogIHBhcnNlWG1sKHMpIHsKICAgIGxldCBpID0gMDsKICAgIHdoaWxlIChpIDwgcy5sZW5ndGgpIHsKICAgICAgY29uc3QgY2ggPSBzW2ldOwogICAgICBsZXQgaiA9IGk7CiAgICAgIGlmIChjaCA9PT0gIjwiKSB7CiAgICAgICAgKytqOwogICAgICAgIGNvbnN0IGNoMiA9IHNbal07CiAgICAgICAgbGV0IHE7CiAgICAgICAgc3dpdGNoIChjaDIpIHsKICAgICAgICAgIGNhc2UgIi8iOgogICAgICAgICAgICArK2o7CiAgICAgICAgICAgIHEgPSBzLmluZGV4T2YoIj4iLCBqKTsKICAgICAgICAgICAgaWYgKHEgPCAwKSB7CiAgICAgICAgICAgICAgdGhpcy5vbkVycm9yKFhNTFBhcnNlckVycm9yQ29kZS5VbnRlcm1pbmF0ZWRFbGVtZW50KTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5vbkVuZEVsZW1lbnQocy5zdWJzdHJpbmcoaiwgcSkpOwogICAgICAgICAgICBqID0gcSArIDE7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAiPyI6CiAgICAgICAgICAgICsrajsKICAgICAgICAgICAgY29uc3QgcGkgPSB0aGlzLl9wYXJzZVByb2Nlc3NpbmdJbnN0cnVjdGlvbihzLCBqKTsKICAgICAgICAgICAgaWYgKHMuc3Vic3RyaW5nKGogKyBwaS5wYXJzZWQsIGogKyBwaS5wYXJzZWQgKyAyKSAhPT0gIj8+IikgewogICAgICAgICAgICAgIHRoaXMub25FcnJvcihYTUxQYXJzZXJFcnJvckNvZGUuVW50ZXJtaW5hdGVkWG1sRGVjbGFyYXRpb24pOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLm9uUGkocGkubmFtZSwgcGkudmFsdWUpOwogICAgICAgICAgICBqICs9IHBpLnBhcnNlZCArIDI7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAiISI6CiAgICAgICAgICAgIGlmIChzLnN1YnN0cmluZyhqICsgMSwgaiArIDMpID09PSAiLS0iKSB7CiAgICAgICAgICAgICAgcSA9IHMuaW5kZXhPZigiLS0+IiwgaiArIDMpOwogICAgICAgICAgICAgIGlmIChxIDwgMCkgewogICAgICAgICAgICAgICAgdGhpcy5vbkVycm9yKFhNTFBhcnNlckVycm9yQ29kZS5VbnRlcm1pbmF0ZWRDb21tZW50KTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGhpcy5vbkNvbW1lbnQocy5zdWJzdHJpbmcoaiArIDMsIHEpKTsKICAgICAgICAgICAgICBqID0gcSArIDM7CiAgICAgICAgICAgIH0gZWxzZSBpZiAocy5zdWJzdHJpbmcoaiArIDEsIGogKyA4KSA9PT0gIltDREFUQVsiKSB7CiAgICAgICAgICAgICAgcSA9IHMuaW5kZXhPZigiXV0+IiwgaiArIDgpOwogICAgICAgICAgICAgIGlmIChxIDwgMCkgewogICAgICAgICAgICAgICAgdGhpcy5vbkVycm9yKFhNTFBhcnNlckVycm9yQ29kZS5VbnRlcm1pbmF0ZWRDZGF0KTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGhpcy5vbkNkYXRhKHMuc3Vic3RyaW5nKGogKyA4LCBxKSk7CiAgICAgICAgICAgICAgaiA9IHEgKyAzOwogICAgICAgICAgICB9IGVsc2UgaWYgKHMuc3Vic3RyaW5nKGogKyAxLCBqICsgOCkgPT09ICJET0NUWVBFIikgewogICAgICAgICAgICAgIGNvbnN0IHEyID0gcy5pbmRleE9mKCJbIiwgaiArIDgpOwogICAgICAgICAgICAgIGxldCBjb21wbGV4RG9jdHlwZSA9IGZhbHNlOwogICAgICAgICAgICAgIHEgPSBzLmluZGV4T2YoIj4iLCBqICsgOCk7CiAgICAgICAgICAgICAgaWYgKHEgPCAwKSB7CiAgICAgICAgICAgICAgICB0aGlzLm9uRXJyb3IoWE1MUGFyc2VyRXJyb3JDb2RlLlVudGVybWluYXRlZERvY3R5cGVEZWNsYXJhdGlvbik7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChxMiA+IDAgJiYgcSA+IHEyKSB7CiAgICAgICAgICAgICAgICBxID0gcy5pbmRleE9mKCJdPiIsIGogKyA4KTsKICAgICAgICAgICAgICAgIGlmIChxIDwgMCkgewogICAgICAgICAgICAgICAgICB0aGlzLm9uRXJyb3IoWE1MUGFyc2VyRXJyb3JDb2RlLlVudGVybWluYXRlZERvY3R5cGVEZWNsYXJhdGlvbik7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNvbXBsZXhEb2N0eXBlID0gdHJ1ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgZG9jdHlwZUNvbnRlbnQgPSBzLnN1YnN0cmluZyhqICsgOCwgcSArIChjb21wbGV4RG9jdHlwZSA/IDEgOiAwKSk7CiAgICAgICAgICAgICAgdGhpcy5vbkRvY3R5cGUoZG9jdHlwZUNvbnRlbnQpOwogICAgICAgICAgICAgIGogPSBxICsgKGNvbXBsZXhEb2N0eXBlID8gMiA6IDEpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRoaXMub25FcnJvcihYTUxQYXJzZXJFcnJvckNvZGUuTWFsZm9ybWVkRWxlbWVudCk7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgY29uc3QgY29udGVudCA9IHRoaXMuX3BhcnNlQ29udGVudChzLCBqKTsKICAgICAgICAgICAgaWYgKGNvbnRlbnQgPT09IG51bGwpIHsKICAgICAgICAgICAgICB0aGlzLm9uRXJyb3IoWE1MUGFyc2VyRXJyb3JDb2RlLk1hbGZvcm1lZEVsZW1lbnQpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgaXNDbG9zZWQgPSBmYWxzZTsKICAgICAgICAgICAgaWYgKHMuc3Vic3RyaW5nKGogKyBjb250ZW50LnBhcnNlZCwgaiArIGNvbnRlbnQucGFyc2VkICsgMikgPT09ICIvPiIpIHsKICAgICAgICAgICAgICBpc0Nsb3NlZCA9IHRydWU7CiAgICAgICAgICAgIH0gZWxzZSBpZiAocy5zdWJzdHJpbmcoaiArIGNvbnRlbnQucGFyc2VkLCBqICsgY29udGVudC5wYXJzZWQgKyAxKSAhPT0gIj4iKSB7CiAgICAgICAgICAgICAgdGhpcy5vbkVycm9yKFhNTFBhcnNlckVycm9yQ29kZS5VbnRlcm1pbmF0ZWRFbGVtZW50KTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5vbkJlZ2luRWxlbWVudChjb250ZW50Lm5hbWUsIGNvbnRlbnQuYXR0cmlidXRlcywgaXNDbG9zZWQpOwogICAgICAgICAgICBqICs9IGNvbnRlbnQucGFyc2VkICsgKGlzQ2xvc2VkID8gMiA6IDEpOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgd2hpbGUgKGogPCBzLmxlbmd0aCAmJiBzW2pdICE9PSAiPCIpIHsKICAgICAgICAgIGorKzsKICAgICAgICB9CiAgICAgICAgY29uc3QgdGV4dCA9IHMuc3Vic3RyaW5nKGksIGopOwogICAgICAgIHRoaXMub25UZXh0KHRoaXMuX3Jlc29sdmVFbnRpdGllcyh0ZXh0KSk7CiAgICAgIH0KICAgICAgaSA9IGo7CiAgICB9CiAgfQogIG9uUmVzb2x2ZUVudGl0eShuYW1lKSB7CiAgICByZXR1cm4gYCYke25hbWV9O2A7CiAgfQogIG9uUGkobmFtZSwgdmFsdWUpIHt9CiAgb25Db21tZW50KHRleHQpIHt9CiAgb25DZGF0YSh0ZXh0KSB7fQogIG9uRG9jdHlwZShkb2N0eXBlQ29udGVudCkge30KICBvblRleHQodGV4dCkge30KICBvbkJlZ2luRWxlbWVudChuYW1lLCBhdHRyaWJ1dGVzLCBpc0VtcHR5KSB7fQogIG9uRW5kRWxlbWVudChuYW1lKSB7fQogIG9uRXJyb3IoY29kZSkge30KfQpjbGFzcyBTaW1wbGVET01Ob2RlIHsKICBjb25zdHJ1Y3Rvcihub2RlTmFtZSwgbm9kZVZhbHVlKSB7CiAgICB0aGlzLm5vZGVOYW1lID0gbm9kZU5hbWU7CiAgICB0aGlzLm5vZGVWYWx1ZSA9IG5vZGVWYWx1ZTsKICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAicGFyZW50Tm9kZSIsIHsKICAgICAgdmFsdWU6IG51bGwsCiAgICAgIHdyaXRhYmxlOiB0cnVlCiAgICB9KTsKICB9CiAgZ2V0IGZpcnN0Q2hpbGQoKSB7CiAgICByZXR1cm4gdGhpcy5jaGlsZE5vZGVzPy5bMF07CiAgfQogIGdldCBuZXh0U2libGluZygpIHsKICAgIGNvbnN0IGNoaWxkTm9kZXMgPSB0aGlzLnBhcmVudE5vZGUuY2hpbGROb2RlczsKICAgIGlmICghY2hpbGROb2RlcykgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogICAgY29uc3QgaW5kZXggPSBjaGlsZE5vZGVzLmluZGV4T2YodGhpcyk7CiAgICBpZiAoaW5kZXggPT09IC0xKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICByZXR1cm4gY2hpbGROb2Rlc1tpbmRleCArIDFdOwogIH0KICBnZXQgdGV4dENvbnRlbnQoKSB7CiAgICBpZiAoIXRoaXMuY2hpbGROb2RlcykgewogICAgICByZXR1cm4gdGhpcy5ub2RlVmFsdWUgfHwgIiI7CiAgICB9CiAgICByZXR1cm4gdGhpcy5jaGlsZE5vZGVzLm1hcChjaGlsZCA9PiBjaGlsZC50ZXh0Q29udGVudCkuam9pbigiIik7CiAgfQogIGdldCBjaGlsZHJlbigpIHsKICAgIHJldHVybiB0aGlzLmNoaWxkTm9kZXMgfHwgW107CiAgfQogIGhhc0NoaWxkTm9kZXMoKSB7CiAgICByZXR1cm4gdGhpcy5jaGlsZE5vZGVzPy5sZW5ndGggPiAwOwogIH0KICBzZWFyY2hOb2RlKHBhdGhzLCBwb3MpIHsKICAgIGlmIChwb3MgPj0gcGF0aHMubGVuZ3RoKSB7CiAgICAgIHJldHVybiB0aGlzOwogICAgfQogICAgY29uc3QgY29tcG9uZW50ID0gcGF0aHNbcG9zXTsKICAgIGlmIChjb21wb25lbnQubmFtZS5zdGFydHNXaXRoKCIjIikgJiYgcG9zIDwgcGF0aHMubGVuZ3RoIC0gMSkgewogICAgICByZXR1cm4gdGhpcy5zZWFyY2hOb2RlKHBhdGhzLCBwb3MgKyAxKTsKICAgIH0KICAgIGNvbnN0IHN0YWNrID0gW107CiAgICBsZXQgbm9kZSA9IHRoaXM7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBpZiAoY29tcG9uZW50Lm5hbWUgPT09IG5vZGUubm9kZU5hbWUpIHsKICAgICAgICBpZiAoY29tcG9uZW50LnBvcyA9PT0gMCkgewogICAgICAgICAgY29uc3QgcmVzID0gbm9kZS5zZWFyY2hOb2RlKHBhdGhzLCBwb3MgKyAxKTsKICAgICAgICAgIGlmIChyZXMgIT09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIHJlczsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKHN0YWNrLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvbnN0IFtwYXJlbnRdID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBsZXQgc2libGluZ1BvcyA9IDA7CiAgICAgICAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHBhcmVudC5jaGlsZE5vZGVzKSB7CiAgICAgICAgICAgIGlmIChjb21wb25lbnQubmFtZSA9PT0gY2hpbGQubm9kZU5hbWUpIHsKICAgICAgICAgICAgICBpZiAoc2libGluZ1BvcyA9PT0gY29tcG9uZW50LnBvcykgewogICAgICAgICAgICAgICAgcmV0dXJuIGNoaWxkLnNlYXJjaE5vZGUocGF0aHMsIHBvcyArIDEpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBzaWJsaW5nUG9zKys7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBub2RlLnNlYXJjaE5vZGUocGF0aHMsIHBvcyArIDEpOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAobm9kZS5jaGlsZE5vZGVzPy5sZW5ndGggPiAwKSB7CiAgICAgICAgc3RhY2sucHVzaChbbm9kZSwgMF0pOwogICAgICAgIG5vZGUgPSBub2RlLmNoaWxkTm9kZXNbMF07CiAgICAgIH0gZWxzZSBpZiAoc3RhY2subGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCAhPT0gMCkgewogICAgICAgICAgY29uc3QgW3BhcmVudCwgY3VycmVudFBvc10gPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGNvbnN0IG5ld1BvcyA9IGN1cnJlbnRQb3MgKyAxOwogICAgICAgICAgaWYgKG5ld1BvcyA8IHBhcmVudC5jaGlsZE5vZGVzLmxlbmd0aCkgewogICAgICAgICAgICBzdGFjay5wdXNoKFtwYXJlbnQsIG5ld1Bvc10pOwogICAgICAgICAgICBub2RlID0gcGFyZW50LmNoaWxkTm9kZXNbbmV3UG9zXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChzdGFjay5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICBkdW1wKGJ1ZmZlcikgewogICAgaWYgKHRoaXMubm9kZU5hbWUgPT09ICIjdGV4dCIpIHsKICAgICAgYnVmZmVyLnB1c2goZW5jb2RlVG9YbWxTdHJpbmcodGhpcy5ub2RlVmFsdWUpKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgYnVmZmVyLnB1c2goYDwke3RoaXMubm9kZU5hbWV9YCk7CiAgICBpZiAodGhpcy5hdHRyaWJ1dGVzKSB7CiAgICAgIGZvciAoY29uc3QgYXR0cmlidXRlIG9mIHRoaXMuYXR0cmlidXRlcykgewogICAgICAgIGJ1ZmZlci5wdXNoKGAgJHthdHRyaWJ1dGUubmFtZX09IiR7ZW5jb2RlVG9YbWxTdHJpbmcoYXR0cmlidXRlLnZhbHVlKX0iYCk7CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzLmhhc0NoaWxkTm9kZXMoKSkgewogICAgICBidWZmZXIucHVzaCgiPiIpOwogICAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXMuY2hpbGROb2RlcykgewogICAgICAgIGNoaWxkLmR1bXAoYnVmZmVyKTsKICAgICAgfQogICAgICBidWZmZXIucHVzaChgPC8ke3RoaXMubm9kZU5hbWV9PmApOwogICAgfSBlbHNlIGlmICh0aGlzLm5vZGVWYWx1ZSkgewogICAgICBidWZmZXIucHVzaChgPiR7ZW5jb2RlVG9YbWxTdHJpbmcodGhpcy5ub2RlVmFsdWUpfTwvJHt0aGlzLm5vZGVOYW1lfT5gKTsKICAgIH0gZWxzZSB7CiAgICAgIGJ1ZmZlci5wdXNoKCIvPiIpOwogICAgfQogIH0KfQpjbGFzcyBTaW1wbGVYTUxQYXJzZXIgZXh0ZW5kcyBYTUxQYXJzZXJCYXNlIHsKICBjb25zdHJ1Y3Rvcih7CiAgICBoYXNBdHRyaWJ1dGVzID0gZmFsc2UsCiAgICBsb3dlckNhc2VOYW1lID0gZmFsc2UKICB9KSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5fY3VycmVudEZyYWdtZW50ID0gbnVsbDsKICAgIHRoaXMuX3N0YWNrID0gbnVsbDsKICAgIHRoaXMuX2Vycm9yQ29kZSA9IFhNTFBhcnNlckVycm9yQ29kZS5Ob0Vycm9yOwogICAgdGhpcy5faGFzQXR0cmlidXRlcyA9IGhhc0F0dHJpYnV0ZXM7CiAgICB0aGlzLl9sb3dlckNhc2VOYW1lID0gbG93ZXJDYXNlTmFtZTsKICB9CiAgcGFyc2VGcm9tU3RyaW5nKGRhdGEpIHsKICAgIHRoaXMuX2N1cnJlbnRGcmFnbWVudCA9IFtdOwogICAgdGhpcy5fc3RhY2sgPSBbXTsKICAgIHRoaXMuX2Vycm9yQ29kZSA9IFhNTFBhcnNlckVycm9yQ29kZS5Ob0Vycm9yOwogICAgdGhpcy5wYXJzZVhtbChkYXRhKTsKICAgIGlmICh0aGlzLl9lcnJvckNvZGUgIT09IFhNTFBhcnNlckVycm9yQ29kZS5Ob0Vycm9yKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICBjb25zdCBbZG9jdW1lbnRFbGVtZW50XSA9IHRoaXMuX2N1cnJlbnRGcmFnbWVudDsKICAgIGlmICghZG9jdW1lbnRFbGVtZW50KSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICByZXR1cm4gewogICAgICBkb2N1bWVudEVsZW1lbnQKICAgIH07CiAgfQogIG9uVGV4dCh0ZXh0KSB7CiAgICBpZiAoaXNXaGl0ZXNwYWNlU3RyaW5nKHRleHQpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG5vZGUgPSBuZXcgU2ltcGxlRE9NTm9kZSgiI3RleHQiLCB0ZXh0KTsKICAgIHRoaXMuX2N1cnJlbnRGcmFnbWVudC5wdXNoKG5vZGUpOwogIH0KICBvbkNkYXRhKHRleHQpIHsKICAgIGNvbnN0IG5vZGUgPSBuZXcgU2ltcGxlRE9NTm9kZSgiI3RleHQiLCB0ZXh0KTsKICAgIHRoaXMuX2N1cnJlbnRGcmFnbWVudC5wdXNoKG5vZGUpOwogIH0KICBvbkJlZ2luRWxlbWVudChuYW1lLCBhdHRyaWJ1dGVzLCBpc0VtcHR5KSB7CiAgICBpZiAodGhpcy5fbG93ZXJDYXNlTmFtZSkgewogICAgICBuYW1lID0gbmFtZS50b0xvd2VyQ2FzZSgpOwogICAgfQogICAgY29uc3Qgbm9kZSA9IG5ldyBTaW1wbGVET01Ob2RlKG5hbWUpOwogICAgbm9kZS5jaGlsZE5vZGVzID0gW107CiAgICBpZiAodGhpcy5faGFzQXR0cmlidXRlcykgewogICAgICBub2RlLmF0dHJpYnV0ZXMgPSBhdHRyaWJ1dGVzOwogICAgfQogICAgdGhpcy5fY3VycmVudEZyYWdtZW50LnB1c2gobm9kZSk7CiAgICBpZiAoaXNFbXB0eSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9zdGFjay5wdXNoKHRoaXMuX2N1cnJlbnRGcmFnbWVudCk7CiAgICB0aGlzLl9jdXJyZW50RnJhZ21lbnQgPSBub2RlLmNoaWxkTm9kZXM7CiAgfQogIG9uRW5kRWxlbWVudChuYW1lKSB7CiAgICB0aGlzLl9jdXJyZW50RnJhZ21lbnQgPSB0aGlzLl9zdGFjay5wb3AoKSB8fCBbXTsKICAgIGNvbnN0IGxhc3RFbGVtZW50ID0gdGhpcy5fY3VycmVudEZyYWdtZW50LmF0KC0xKTsKICAgIGlmICghbGFzdEVsZW1lbnQpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBmb3IgKGNvbnN0IGNoaWxkTm9kZSBvZiBsYXN0RWxlbWVudC5jaGlsZE5vZGVzKSB7CiAgICAgIGNoaWxkTm9kZS5wYXJlbnROb2RlID0gbGFzdEVsZW1lbnQ7CiAgICB9CiAgICByZXR1cm4gbGFzdEVsZW1lbnQ7CiAgfQogIG9uRXJyb3IoY29kZSkgewogICAgdGhpcy5fZXJyb3JDb2RlID0gY29kZTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL21ldGFkYXRhX3BhcnNlci5qcwoKY2xhc3MgTWV0YWRhdGFQYXJzZXIgewogIGNvbnN0cnVjdG9yKGRhdGEpIHsKICAgIGRhdGEgPSB0aGlzLl9yZXBhaXIoZGF0YSk7CiAgICBjb25zdCBwYXJzZXIgPSBuZXcgU2ltcGxlWE1MUGFyc2VyKHsKICAgICAgbG93ZXJDYXNlTmFtZTogdHJ1ZQogICAgfSk7CiAgICBjb25zdCB4bWxEb2N1bWVudCA9IHBhcnNlci5wYXJzZUZyb21TdHJpbmcoZGF0YSk7CiAgICB0aGlzLl9tZXRhZGF0YU1hcCA9IG5ldyBNYXAoKTsKICAgIHRoaXMuX2RhdGEgPSBkYXRhOwogICAgaWYgKHhtbERvY3VtZW50KSB7CiAgICAgIHRoaXMuX3BhcnNlKHhtbERvY3VtZW50KTsKICAgIH0KICB9CiAgX3JlcGFpcihkYXRhKSB7CiAgICByZXR1cm4gZGF0YS5yZXBsYWNlKC9eW148XSsvLCAiIikucmVwbGFjZUFsbCgvPlxcMzc2XFwzNzcoW148XSspL2csIGZ1bmN0aW9uIChhbGwsIGNvZGVzKSB7CiAgICAgIGNvbnN0IGJ5dGVzID0gY29kZXMucmVwbGFjZUFsbCgvXFwoWzAtM10pKFswLTddKShbMC03XSkvZywgZnVuY3Rpb24gKGNvZGUsIGQxLCBkMiwgZDMpIHsKICAgICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShkMSAqIDY0ICsgZDIgKiA4ICsgZDMgKiAxKTsKICAgICAgfSkucmVwbGFjZUFsbCgvJihhbXB8YXBvc3xndHxsdHxxdW90KTsvZywgZnVuY3Rpb24gKHN0ciwgbmFtZSkgewogICAgICAgIHN3aXRjaCAobmFtZSkgewogICAgICAgICAgY2FzZSAiYW1wIjoKICAgICAgICAgICAgcmV0dXJuICImIjsKICAgICAgICAgIGNhc2UgImFwb3MiOgogICAgICAgICAgICByZXR1cm4gIiciOwogICAgICAgICAgY2FzZSAiZ3QiOgogICAgICAgICAgICByZXR1cm4gIj4iOwogICAgICAgICAgY2FzZSAibHQiOgogICAgICAgICAgICByZXR1cm4gIjwiOwogICAgICAgICAgY2FzZSAicXVvdCI6CiAgICAgICAgICAgIHJldHVybiAnIic7CiAgICAgICAgfQogICAgICAgIHRocm93IG5ldyBFcnJvcihgX3JlcGFpcjogJHtuYW1lfSBpc24ndCBkZWZpbmVkLmApOwogICAgICB9KTsKICAgICAgY29uc3QgY2hhckJ1ZiA9IFsiPiJdOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBieXRlcy5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7CiAgICAgICAgY29uc3QgY29kZSA9IGJ5dGVzLmNoYXJDb2RlQXQoaSkgKiAyNTYgKyBieXRlcy5jaGFyQ29kZUF0KGkgKyAxKTsKICAgICAgICBpZiAoY29kZSA+PSAzMiAmJiBjb2RlIDwgMTI3ICYmIGNvZGUgIT09IDYwICYmIGNvZGUgIT09IDYyICYmIGNvZGUgIT09IDM4KSB7CiAgICAgICAgICBjaGFyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjb2RlKSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNoYXJCdWYucHVzaCgiJiN4IiArICgweDEwMDAwICsgY29kZSkudG9TdHJpbmcoMTYpLnN1YnN0cmluZygxKSArICI7Iik7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBjaGFyQnVmLmpvaW4oIiIpOwogICAgfSk7CiAgfQogIF9nZXRTZXF1ZW5jZShlbnRyeSkgewogICAgY29uc3QgbmFtZSA9IGVudHJ5Lm5vZGVOYW1lOwogICAgaWYgKG5hbWUgIT09ICJyZGY6YmFnIiAmJiBuYW1lICE9PSAicmRmOnNlcSIgJiYgbmFtZSAhPT0gInJkZjphbHQiKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcmV0dXJuIGVudHJ5LmNoaWxkTm9kZXMuZmlsdGVyKG5vZGUgPT4gbm9kZS5ub2RlTmFtZSA9PT0gInJkZjpsaSIpOwogIH0KICBfcGFyc2VBcnJheShlbnRyeSkgewogICAgaWYgKCFlbnRyeS5oYXNDaGlsZE5vZGVzKCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgW3NlcU5vZGVdID0gZW50cnkuY2hpbGROb2RlczsKICAgIGNvbnN0IHNlcXVlbmNlID0gdGhpcy5fZ2V0U2VxdWVuY2Uoc2VxTm9kZSkgfHwgW107CiAgICB0aGlzLl9tZXRhZGF0YU1hcC5zZXQoZW50cnkubm9kZU5hbWUsIHNlcXVlbmNlLm1hcChub2RlID0+IG5vZGUudGV4dENvbnRlbnQudHJpbSgpKSk7CiAgfQogIF9wYXJzZSh4bWxEb2N1bWVudCkgewogICAgbGV0IHJkZiA9IHhtbERvY3VtZW50LmRvY3VtZW50RWxlbWVudDsKICAgIGlmIChyZGYubm9kZU5hbWUgIT09ICJyZGY6cmRmIikgewogICAgICByZGYgPSByZGYuZmlyc3RDaGlsZDsKICAgICAgd2hpbGUgKHJkZiAmJiByZGYubm9kZU5hbWUgIT09ICJyZGY6cmRmIikgewogICAgICAgIHJkZiA9IHJkZi5uZXh0U2libGluZzsKICAgICAgfQogICAgfQogICAgaWYgKCFyZGYgfHwgcmRmLm5vZGVOYW1lICE9PSAicmRmOnJkZiIgfHwgIXJkZi5oYXNDaGlsZE5vZGVzKCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgZm9yIChjb25zdCBkZXNjIG9mIHJkZi5jaGlsZE5vZGVzKSB7CiAgICAgIGlmIChkZXNjLm5vZGVOYW1lICE9PSAicmRmOmRlc2NyaXB0aW9uIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGZvciAoY29uc3QgZW50cnkgb2YgZGVzYy5jaGlsZE5vZGVzKSB7CiAgICAgICAgY29uc3QgbmFtZSA9IGVudHJ5Lm5vZGVOYW1lOwogICAgICAgIHN3aXRjaCAobmFtZSkgewogICAgICAgICAgY2FzZSAiI3RleHQiOgogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIGNhc2UgImRjOmNyZWF0b3IiOgogICAgICAgICAgY2FzZSAiZGM6c3ViamVjdCI6CiAgICAgICAgICAgIHRoaXMuX3BhcnNlQXJyYXkoZW50cnkpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgdGhpcy5fbWV0YWRhdGFNYXAuc2V0KG5hbWUsIGVudHJ5LnRleHRDb250ZW50LnRyaW0oKSk7CiAgICAgIH0KICAgIH0KICB9CiAgZ2V0IHNlcmlhbGl6YWJsZSgpIHsKICAgIHJldHVybiB7CiAgICAgIHBhcnNlZERhdGE6IHRoaXMuX21ldGFkYXRhTWFwLAogICAgICByYXdEYXRhOiB0aGlzLl9kYXRhCiAgICB9OwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvc3RydWN0X3RyZWUuanMKCgoKCgpjb25zdCBNQVhfREVQVEggPSA0MDsKY29uc3QgU3RydWN0RWxlbWVudFR5cGUgPSB7CiAgUEFHRV9DT05URU5UOiAxLAogIFNUUkVBTV9DT05URU5UOiAyLAogIE9CSkVDVDogMywKICBBTk5PVEFUSU9OOiA0LAogIEVMRU1FTlQ6IDUKfTsKY2xhc3MgU3RydWN0VHJlZVJvb3QgewogIGNvbnN0cnVjdG9yKHhyZWYsIHJvb3REaWN0LCByb290UmVmKSB7CiAgICB0aGlzLnhyZWYgPSB4cmVmOwogICAgdGhpcy5kaWN0ID0gcm9vdERpY3Q7CiAgICB0aGlzLnJlZiA9IHJvb3RSZWYgaW5zdGFuY2VvZiBSZWYgPyByb290UmVmIDogbnVsbDsKICAgIHRoaXMucm9sZU1hcCA9IG5ldyBNYXAoKTsKICAgIHRoaXMuc3RydWN0UGFyZW50SWRzID0gbnVsbDsKICAgIHRoaXMua2lkUmVmVG9Qb3NpdGlvbiA9IHVuZGVmaW5lZDsKICAgIHRoaXMucGFyZW50VHJlZSA9IG51bGw7CiAgfQogIGdldEtpZFBvc2l0aW9uKGtpZFJlZikgewogICAgaWYgKHRoaXMua2lkUmVmVG9Qb3NpdGlvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGNvbnN0IG9iaiA9IHRoaXMuZGljdC5nZXQoIksiKTsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkgewogICAgICAgIGNvbnN0IG1hcCA9IHRoaXMua2lkUmVmVG9Qb3NpdGlvbiA9IG5ldyBNYXAoKTsKICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBvYmoubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgY29uc3QgcmVmID0gb2JqW2ldOwogICAgICAgICAgaWYgKHJlZikgewogICAgICAgICAgICBtYXAuc2V0KHJlZi50b1N0cmluZygpLCBpKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAob2JqIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIHRoaXMua2lkUmVmVG9Qb3NpdGlvbiA9IG5ldyBNYXAoW1tvYmoub2JqSWQsIDBdXSk7CiAgICAgIH0gZWxzZSBpZiAoIW9iaikgewogICAgICAgIHRoaXMua2lkUmVmVG9Qb3NpdGlvbiA9IG5ldyBNYXAoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLmtpZFJlZlRvUG9zaXRpb24gPSBudWxsOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdGhpcy5raWRSZWZUb1Bvc2l0aW9uID8gdGhpcy5raWRSZWZUb1Bvc2l0aW9uLmdldChraWRSZWYpID8/IE5hTiA6IC0xOwogIH0KICBpbml0KCkgewogICAgdGhpcy5yZWFkUm9sZU1hcCgpOwogICAgY29uc3QgcGFyZW50VHJlZSA9IHRoaXMuZGljdC5nZXQoIlBhcmVudFRyZWUiKTsKICAgIGlmICghcGFyZW50VHJlZSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLnBhcmVudFRyZWUgPSBuZXcgTnVtYmVyVHJlZShwYXJlbnRUcmVlLCB0aGlzLnhyZWYpOwogIH0KICAjYWRkSWRUb1BhZ2UocGFnZVJlZiwgaWQsIHR5cGUpIHsKICAgIGlmICghKHBhZ2VSZWYgaW5zdGFuY2VvZiBSZWYpIHx8IGlkIDwgMCkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLnN0cnVjdFBhcmVudElkcyB8fD0gbmV3IFJlZlNldENhY2hlKCk7CiAgICBsZXQgaWRzID0gdGhpcy5zdHJ1Y3RQYXJlbnRJZHMuZ2V0KHBhZ2VSZWYpOwogICAgaWYgKCFpZHMpIHsKICAgICAgaWRzID0gW107CiAgICAgIHRoaXMuc3RydWN0UGFyZW50SWRzLnB1dChwYWdlUmVmLCBpZHMpOwogICAgfQogICAgaWRzLnB1c2goW2lkLCB0eXBlXSk7CiAgfQogIGFkZEFubm90YXRpb25JZFRvUGFnZShwYWdlUmVmLCBpZCkgewogICAgdGhpcy4jYWRkSWRUb1BhZ2UocGFnZVJlZiwgaWQsIFN0cnVjdEVsZW1lbnRUeXBlLkFOTk9UQVRJT04pOwogIH0KICByZWFkUm9sZU1hcCgpIHsKICAgIGNvbnN0IHJvbGVNYXBEaWN0ID0gdGhpcy5kaWN0LmdldCgiUm9sZU1hcCIpOwogICAgaWYgKCEocm9sZU1hcERpY3QgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiByb2xlTWFwRGljdCkgewogICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgdGhpcy5yb2xlTWFwLnNldChrZXksIHZhbHVlLm5hbWUpOwogICAgICB9CiAgICB9CiAgfQogIHN0YXRpYyBhc3luYyBjYW5DcmVhdGVTdHJ1Y3R1cmVUcmVlKHsKICAgIGNhdGFsb2dSZWYsCiAgICBwZGZNYW5hZ2VyLAogICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UKICB9KSB7CiAgICBpZiAoIShjYXRhbG9nUmVmIGluc3RhbmNlb2YgUmVmKSkgewogICAgICB3YXJuKCJDYW5ub3Qgc2F2ZSB0aGUgc3RydWN0IHRyZWU6IG5vIGNhdGFsb2cgcmVmZXJlbmNlLiIpOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBsZXQgbmV4dEtleSA9IDA7CiAgICBsZXQgaGFzTm90aGluZ1RvVXBkYXRlID0gdHJ1ZTsKICAgIGZvciAoY29uc3QgW3BhZ2VJbmRleCwgZWxlbWVudHNdIG9mIG5ld0Fubm90YXRpb25zQnlQYWdlKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICByZWY6IHBhZ2VSZWYKICAgICAgfSA9IGF3YWl0IHBkZk1hbmFnZXIuZ2V0UGFnZShwYWdlSW5kZXgpOwogICAgICBpZiAoIShwYWdlUmVmIGluc3RhbmNlb2YgUmVmKSkgewogICAgICAgIHdhcm4oYENhbm5vdCBzYXZlIHRoZSBzdHJ1Y3QgdHJlZTogcGFnZSAke3BhZ2VJbmRleH0gaGFzIG5vIHJlZi5gKTsKICAgICAgICBoYXNOb3RoaW5nVG9VcGRhdGUgPSB0cnVlOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbGVtZW50cykgewogICAgICAgIGlmIChlbGVtZW50LmFjY2Vzc2liaWxpdHlEYXRhPy50eXBlKSB7CiAgICAgICAgICBlbGVtZW50LnBhcmVudFRyZWVJZCA9IG5leHRLZXkrKzsKICAgICAgICAgIGhhc05vdGhpbmdUb1VwZGF0ZSA9IGZhbHNlOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKGhhc05vdGhpbmdUb1VwZGF0ZSkgewogICAgICBmb3IgKGNvbnN0IGVsZW1lbnRzIG9mIG5ld0Fubm90YXRpb25zQnlQYWdlLnZhbHVlcygpKSB7CiAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGVsZW1lbnRzKSB7CiAgICAgICAgICBkZWxldGUgZWxlbWVudC5wYXJlbnRUcmVlSWQ7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHJldHVybiB0cnVlOwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlU3RydWN0dXJlVHJlZSh7CiAgICBuZXdBbm5vdGF0aW9uc0J5UGFnZSwKICAgIHhyZWYsCiAgICBjYXRhbG9nUmVmLAogICAgcGRmTWFuYWdlciwKICAgIGNoYW5nZXMKICB9KSB7CiAgICBjb25zdCByb290ID0gYXdhaXQgcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJjbG9uZURpY3QiKTsKICAgIGNvbnN0IGNhY2hlID0gbmV3IFJlZlNldENhY2hlKCk7CiAgICBjYWNoZS5wdXQoY2F0YWxvZ1JlZiwgcm9vdCk7CiAgICBjb25zdCBzdHJ1Y3RUcmVlUm9vdFJlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICByb290LnNldCgiU3RydWN0VHJlZVJvb3QiLCBzdHJ1Y3RUcmVlUm9vdFJlZik7CiAgICBjb25zdCBzdHJ1Y3RUcmVlUm9vdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgc3RydWN0VHJlZVJvb3Quc2V0KCJUeXBlIiwgTmFtZS5nZXQoIlN0cnVjdFRyZWVSb290IikpOwogICAgY29uc3QgcGFyZW50VHJlZVJlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICBzdHJ1Y3RUcmVlUm9vdC5zZXQoIlBhcmVudFRyZWUiLCBwYXJlbnRUcmVlUmVmKTsKICAgIGNvbnN0IGtpZHMgPSBbXTsKICAgIHN0cnVjdFRyZWVSb290LnNldCgiSyIsIGtpZHMpOwogICAgY2FjaGUucHV0KHN0cnVjdFRyZWVSb290UmVmLCBzdHJ1Y3RUcmVlUm9vdCk7CiAgICBjb25zdCBwYXJlbnRUcmVlID0gbmV3IERpY3QoeHJlZik7CiAgICBjb25zdCBudW1zID0gW107CiAgICBwYXJlbnRUcmVlLnNldCgiTnVtcyIsIG51bXMpOwogICAgY29uc3QgbmV4dEtleSA9IGF3YWl0IHRoaXMuI3dyaXRlS2lkcyh7CiAgICAgIG5ld0Fubm90YXRpb25zQnlQYWdlLAogICAgICBzdHJ1Y3RUcmVlUm9vdFJlZiwKICAgICAgc3RydWN0VHJlZVJvb3Q6IG51bGwsCiAgICAgIGtpZHMsCiAgICAgIG51bXMsCiAgICAgIHhyZWYsCiAgICAgIHBkZk1hbmFnZXIsCiAgICAgIGNoYW5nZXMsCiAgICAgIGNhY2hlCiAgICB9KTsKICAgIHN0cnVjdFRyZWVSb290LnNldCgiUGFyZW50VHJlZU5leHRLZXkiLCBuZXh0S2V5KTsKICAgIGNhY2hlLnB1dChwYXJlbnRUcmVlUmVmLCBwYXJlbnRUcmVlKTsKICAgIGZvciAoY29uc3QgW3JlZiwgb2JqXSBvZiBjYWNoZS5pdGVtcygpKSB7CiAgICAgIGNoYW5nZXMucHV0KHJlZiwgewogICAgICAgIGRhdGE6IG9iagogICAgICB9KTsKICAgIH0KICB9CiAgYXN5bmMgY2FuVXBkYXRlU3RydWN0VHJlZSh7CiAgICBwZGZNYW5hZ2VyLAogICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UKICB9KSB7CiAgICBpZiAoIXRoaXMucmVmKSB7CiAgICAgIHdhcm4oIkNhbm5vdCB1cGRhdGUgdGhlIHN0cnVjdCB0cmVlOiBubyByb290IHJlZmVyZW5jZS4iKTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgbGV0IG5leHRLZXkgPSB0aGlzLmRpY3QuZ2V0KCJQYXJlbnRUcmVlTmV4dEtleSIpOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKG5leHRLZXkpIHx8IG5leHRLZXkgPCAwKSB7CiAgICAgIHdhcm4oIkNhbm5vdCB1cGRhdGUgdGhlIHN0cnVjdCB0cmVlOiBpbnZhbGlkIG5leHQga2V5LiIpOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBjb25zdCBwYXJlbnRUcmVlID0gdGhpcy5kaWN0LmdldCgiUGFyZW50VHJlZSIpOwogICAgaWYgKCEocGFyZW50VHJlZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHdhcm4oIkNhbm5vdCB1cGRhdGUgdGhlIHN0cnVjdCB0cmVlOiBQYXJlbnRUcmVlIGlzbid0IGEgZGljdC4iKTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgY29uc3QgbnVtcyA9IHBhcmVudFRyZWUuZ2V0KCJOdW1zIik7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkobnVtcykpIHsKICAgICAgd2FybigiQ2Fubm90IHVwZGF0ZSB0aGUgc3RydWN0IHRyZWU6IG51bXMgaXNuJ3QgYW4gYXJyYXkuIik7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGNvbnN0IG51bWJlclRyZWUgPSBuZXcgTnVtYmVyVHJlZShwYXJlbnRUcmVlLCB0aGlzLnhyZWYpOwogICAgZm9yIChjb25zdCBwYWdlSW5kZXggb2YgbmV3QW5ub3RhdGlvbnNCeVBhZ2Uua2V5cygpKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBwYWdlRGljdAogICAgICB9ID0gYXdhaXQgcGRmTWFuYWdlci5nZXRQYWdlKHBhZ2VJbmRleCk7CiAgICAgIGlmICghcGFnZURpY3QuaGFzKCJTdHJ1Y3RQYXJlbnRzIikpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBpZCA9IHBhZ2VEaWN0LmdldCgiU3RydWN0UGFyZW50cyIpOwogICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoaWQpIHx8ICFBcnJheS5pc0FycmF5KG51bWJlclRyZWUuZ2V0KGlkKSkpIHsKICAgICAgICB3YXJuKGBDYW5ub3Qgc2F2ZSB0aGUgc3RydWN0IHRyZWU6IHBhZ2UgJHtwYWdlSW5kZXh9IGhhcyBhIHdyb25nIGlkLmApOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQogICAgbGV0IGhhc05vdGhpbmdUb1VwZGF0ZSA9IHRydWU7CiAgICBmb3IgKGNvbnN0IFtwYWdlSW5kZXgsIGVsZW1lbnRzXSBvZiBuZXdBbm5vdGF0aW9uc0J5UGFnZSkgewogICAgICBjb25zdCB7CiAgICAgICAgcGFnZURpY3QKICAgICAgfSA9IGF3YWl0IHBkZk1hbmFnZXIuZ2V0UGFnZShwYWdlSW5kZXgpOwogICAgICBTdHJ1Y3RUcmVlUm9vdC4jY29sbGVjdFBhcmVudHMoewogICAgICAgIGVsZW1lbnRzLAogICAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgICBwYWdlRGljdCwKICAgICAgICBudW1iZXJUcmVlCiAgICAgIH0pOwogICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbWVudHMpIHsKICAgICAgICBpZiAoZWxlbWVudC5hY2Nlc3NpYmlsaXR5RGF0YT8udHlwZSkgewogICAgICAgICAgaWYgKCEoZWxlbWVudC5hY2Nlc3NpYmlsaXR5RGF0YS5zdHJ1Y3RQYXJlbnQgPj0gMCkpIHsKICAgICAgICAgICAgZWxlbWVudC5wYXJlbnRUcmVlSWQgPSBuZXh0S2V5Kys7CiAgICAgICAgICB9CiAgICAgICAgICBoYXNOb3RoaW5nVG9VcGRhdGUgPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChoYXNOb3RoaW5nVG9VcGRhdGUpIHsKICAgICAgZm9yIChjb25zdCBlbGVtZW50cyBvZiBuZXdBbm5vdGF0aW9uc0J5UGFnZS52YWx1ZXMoKSkgewogICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbGVtZW50cykgewogICAgICAgICAgZGVsZXRlIGVsZW1lbnQucGFyZW50VHJlZUlkOwogICAgICAgICAgZGVsZXRlIGVsZW1lbnQuc3RydWN0VHJlZVBhcmVudDsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfQogIGFzeW5jIHVwZGF0ZVN0cnVjdHVyZVRyZWUoewogICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UsCiAgICBwZGZNYW5hZ2VyLAogICAgY2hhbmdlcwogIH0pIHsKICAgIGNvbnN0IHsKICAgICAgcmVmOiBzdHJ1Y3RUcmVlUm9vdFJlZiwKICAgICAgeHJlZgogICAgfSA9IHRoaXM7CiAgICBjb25zdCBzdHJ1Y3RUcmVlUm9vdCA9IHRoaXMuZGljdC5jbG9uZSgpOwogICAgY29uc3QgY2FjaGUgPSBuZXcgUmVmU2V0Q2FjaGUoKTsKICAgIGNhY2hlLnB1dChzdHJ1Y3RUcmVlUm9vdFJlZiwgc3RydWN0VHJlZVJvb3QpOwogICAgbGV0IHBhcmVudFRyZWVSZWYgPSBzdHJ1Y3RUcmVlUm9vdC5nZXRSYXcoIlBhcmVudFRyZWUiKTsKICAgIGxldCBwYXJlbnRUcmVlOwogICAgaWYgKHBhcmVudFRyZWVSZWYgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgcGFyZW50VHJlZSA9IHhyZWYuZmV0Y2gocGFyZW50VHJlZVJlZik7CiAgICB9IGVsc2UgewogICAgICBwYXJlbnRUcmVlID0gcGFyZW50VHJlZVJlZjsKICAgICAgcGFyZW50VHJlZVJlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICAgIHN0cnVjdFRyZWVSb290LnNldCgiUGFyZW50VHJlZSIsIHBhcmVudFRyZWVSZWYpOwogICAgfQogICAgcGFyZW50VHJlZSA9IHBhcmVudFRyZWUuY2xvbmUoKTsKICAgIGNhY2hlLnB1dChwYXJlbnRUcmVlUmVmLCBwYXJlbnRUcmVlKTsKICAgIGxldCBudW1zID0gcGFyZW50VHJlZS5nZXRSYXcoIk51bXMiKTsKICAgIGxldCBudW1zUmVmID0gbnVsbDsKICAgIGlmIChudW1zIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgIG51bXNSZWYgPSBudW1zOwogICAgICBudW1zID0geHJlZi5mZXRjaChudW1zUmVmKTsKICAgIH0KICAgIG51bXMgPSBudW1zLnNsaWNlKCk7CiAgICBpZiAoIW51bXNSZWYpIHsKICAgICAgcGFyZW50VHJlZS5zZXQoIk51bXMiLCBudW1zKTsKICAgIH0KICAgIGNvbnN0IG5ld05leHRLZXkgPSBhd2FpdCBTdHJ1Y3RUcmVlUm9vdC4jd3JpdGVLaWRzKHsKICAgICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UsCiAgICAgIHN0cnVjdFRyZWVSb290UmVmLAogICAgICBzdHJ1Y3RUcmVlUm9vdDogdGhpcywKICAgICAga2lkczogbnVsbCwKICAgICAgbnVtcywKICAgICAgeHJlZiwKICAgICAgcGRmTWFuYWdlciwKICAgICAgY2hhbmdlcywKICAgICAgY2FjaGUKICAgIH0pOwogICAgaWYgKG5ld05leHRLZXkgPT09IC0xKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHN0cnVjdFRyZWVSb290LnNldCgiUGFyZW50VHJlZU5leHRLZXkiLCBuZXdOZXh0S2V5KTsKICAgIGlmIChudW1zUmVmKSB7CiAgICAgIGNhY2hlLnB1dChudW1zUmVmLCBudW1zKTsKICAgIH0KICAgIGZvciAoY29uc3QgW3JlZiwgb2JqXSBvZiBjYWNoZS5pdGVtcygpKSB7CiAgICAgIGNoYW5nZXMucHV0KHJlZiwgewogICAgICAgIGRhdGE6IG9iagogICAgICB9KTsKICAgIH0KICB9CiAgc3RhdGljIGFzeW5jICN3cml0ZUtpZHMoewogICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UsCiAgICBzdHJ1Y3RUcmVlUm9vdFJlZiwKICAgIHN0cnVjdFRyZWVSb290LAogICAga2lkcywKICAgIG51bXMsCiAgICB4cmVmLAogICAgcGRmTWFuYWdlciwKICAgIGNoYW5nZXMsCiAgICBjYWNoZQogIH0pIHsKICAgIGNvbnN0IG9ianIgPSBOYW1lLmdldCgiT0JKUiIpOwogICAgbGV0IG5leHRLZXkgPSAtMTsKICAgIGxldCBzdHJ1Y3RUcmVlUGFnZU9ianM7CiAgICBmb3IgKGNvbnN0IFtwYWdlSW5kZXgsIGVsZW1lbnRzXSBvZiBuZXdBbm5vdGF0aW9uc0J5UGFnZSkgewogICAgICBjb25zdCBwYWdlID0gYXdhaXQgcGRmTWFuYWdlci5nZXRQYWdlKHBhZ2VJbmRleCk7CiAgICAgIGNvbnN0IHsKICAgICAgICByZWY6IHBhZ2VSZWYKICAgICAgfSA9IHBhZ2U7CiAgICAgIGNvbnN0IGlzUGFnZVJlZiA9IHBhZ2VSZWYgaW5zdGFuY2VvZiBSZWY7CiAgICAgIGZvciAoY29uc3QgewogICAgICAgIGFjY2Vzc2liaWxpdHlEYXRhLAogICAgICAgIHJlZiwKICAgICAgICBwYXJlbnRUcmVlSWQsCiAgICAgICAgc3RydWN0VHJlZVBhcmVudAogICAgICB9IG9mIGVsZW1lbnRzKSB7CiAgICAgICAgaWYgKCFhY2Nlc3NpYmlsaXR5RGF0YT8udHlwZSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHsKICAgICAgICAgIHN0cnVjdFBhcmVudAogICAgICAgIH0gPSBhY2Nlc3NpYmlsaXR5RGF0YTsKICAgICAgICBpZiAoc3RydWN0VHJlZVJvb3QgJiYgTnVtYmVyLmlzSW50ZWdlcihzdHJ1Y3RQYXJlbnQpICYmIHN0cnVjdFBhcmVudCA+PSAwKSB7CiAgICAgICAgICBsZXQgb2JqcyA9IChzdHJ1Y3RUcmVlUGFnZU9ianMgfHw9IG5ldyBNYXAoKSkuZ2V0KHBhZ2VJbmRleCk7CiAgICAgICAgICBpZiAob2JqcyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGNvbnN0IHN0cnVjdFRyZWVQYWdlID0gbmV3IFN0cnVjdFRyZWVQYWdlKHN0cnVjdFRyZWVSb290LCBwYWdlLnBhZ2VEaWN0KTsKICAgICAgICAgICAgb2JqcyA9IHN0cnVjdFRyZWVQYWdlLmNvbGxlY3RPYmplY3RzKHBhZ2VSZWYpOwogICAgICAgICAgICBzdHJ1Y3RUcmVlUGFnZU9ianMuc2V0KHBhZ2VJbmRleCwgb2Jqcyk7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBvYmpSZWYgPSBvYmpzPy5nZXQoc3RydWN0UGFyZW50KTsKICAgICAgICAgIGlmIChvYmpSZWYpIHsKICAgICAgICAgICAgY29uc3QgdGFnRGljdCA9IHhyZWYuZmV0Y2gob2JqUmVmKS5jbG9uZSgpOwogICAgICAgICAgICBTdHJ1Y3RUcmVlUm9vdC4jd3JpdGVQcm9wZXJ0aWVzKHRhZ0RpY3QsIGFjY2Vzc2liaWxpdHlEYXRhKTsKICAgICAgICAgICAgY2hhbmdlcy5wdXQob2JqUmVmLCB7CiAgICAgICAgICAgICAgZGF0YTogdGFnRGljdAogICAgICAgICAgICB9KTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG5leHRLZXkgPSBNYXRoLm1heChuZXh0S2V5LCBwYXJlbnRUcmVlSWQpOwogICAgICAgIGNvbnN0IHRhZ1JlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICAgICAgY29uc3QgdGFnRGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgICAgIFN0cnVjdFRyZWVSb290LiN3cml0ZVByb3BlcnRpZXModGFnRGljdCwgYWNjZXNzaWJpbGl0eURhdGEpOwogICAgICAgIGF3YWl0IHRoaXMuI3VwZGF0ZVBhcmVudFRhZyh7CiAgICAgICAgICBzdHJ1Y3RUcmVlUGFyZW50LAogICAgICAgICAgdGFnRGljdCwKICAgICAgICAgIG5ld1RhZ1JlZjogdGFnUmVmLAogICAgICAgICAgc3RydWN0VHJlZVJvb3RSZWYsCiAgICAgICAgICBmYWxsYmFja0tpZHM6IGtpZHMsCiAgICAgICAgICB4cmVmLAogICAgICAgICAgY2FjaGUKICAgICAgICB9KTsKICAgICAgICBjb25zdCBvYmpEaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICAgICAgdGFnRGljdC5zZXQoIksiLCBvYmpEaWN0KTsKICAgICAgICBvYmpEaWN0LnNldCgiVHlwZSIsIG9ianIpOwogICAgICAgIGlmIChpc1BhZ2VSZWYpIHsKICAgICAgICAgIG9iakRpY3Quc2V0KCJQZyIsIHBhZ2VSZWYpOwogICAgICAgIH0KICAgICAgICBvYmpEaWN0LnNldCgiT2JqIiwgcmVmKTsKICAgICAgICBjYWNoZS5wdXQodGFnUmVmLCB0YWdEaWN0KTsKICAgICAgICBudW1zLnB1c2gocGFyZW50VHJlZUlkLCB0YWdSZWYpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbmV4dEtleSArIDE7CiAgfQogIHN0YXRpYyAjd3JpdGVQcm9wZXJ0aWVzKHRhZ0RpY3QsIHsKICAgIHR5cGUsCiAgICB0aXRsZSwKICAgIGxhbmcsCiAgICBhbHQsCiAgICBleHBhbmRlZCwKICAgIGFjdHVhbFRleHQKICB9KSB7CiAgICB0YWdEaWN0LnNldCgiUyIsIE5hbWUuZ2V0KHR5cGUpKTsKICAgIGlmICh0aXRsZSkgewogICAgICB0YWdEaWN0LnNldCgiVCIsIHN0cmluZ1RvQXNjaWlPclVURjE2QkUodGl0bGUpKTsKICAgIH0KICAgIGlmIChsYW5nKSB7CiAgICAgIHRhZ0RpY3Quc2V0KCJMYW5nIiwgc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRShsYW5nKSk7CiAgICB9CiAgICBpZiAoYWx0KSB7CiAgICAgIHRhZ0RpY3Quc2V0KCJBbHQiLCBzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKGFsdCkpOwogICAgfQogICAgaWYgKGV4cGFuZGVkKSB7CiAgICAgIHRhZ0RpY3Quc2V0KCJFIiwgc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRShleHBhbmRlZCkpOwogICAgfQogICAgaWYgKGFjdHVhbFRleHQpIHsKICAgICAgdGFnRGljdC5zZXQoIkFjdHVhbFRleHQiLCBzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKGFjdHVhbFRleHQpKTsKICAgIH0KICB9CiAgc3RhdGljICNjb2xsZWN0UGFyZW50cyh7CiAgICBlbGVtZW50cywKICAgIHhyZWYsCiAgICBwYWdlRGljdCwKICAgIG51bWJlclRyZWUKICB9KSB7CiAgICBjb25zdCBpZFRvRWxlbWVudHMgPSBuZXcgTWFwKCk7CiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbWVudHMpIHsKICAgICAgaWYgKGVsZW1lbnQuc3RydWN0VHJlZVBhcmVudElkKSB7CiAgICAgICAgY29uc3QgaWQgPSBwYXJzZUludChlbGVtZW50LnN0cnVjdFRyZWVQYXJlbnRJZC5zcGxpdCgiX21jIilbMV0sIDEwKTsKICAgICAgICBsZXQgZWxlbXMgPSBpZFRvRWxlbWVudHMuZ2V0KGlkKTsKICAgICAgICBpZiAoIWVsZW1zKSB7CiAgICAgICAgICBlbGVtcyA9IFtdOwogICAgICAgICAgaWRUb0VsZW1lbnRzLnNldChpZCwgZWxlbXMpOwogICAgICAgIH0KICAgICAgICBlbGVtcy5wdXNoKGVsZW1lbnQpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBpZCA9IHBhZ2VEaWN0LmdldCgiU3RydWN0UGFyZW50cyIpOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGlkKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBwYXJlbnRBcnJheSA9IG51bWJlclRyZWUuZ2V0KGlkKTsKICAgIGNvbnN0IHVwZGF0ZUVsZW1lbnQgPSAoa2lkLCBwYWdlS2lkLCBraWRSZWYpID0+IHsKICAgICAgY29uc3QgZWxlbXMgPSBpZFRvRWxlbWVudHMuZ2V0KGtpZCk7CiAgICAgIGlmIChlbGVtcykgewogICAgICAgIGNvbnN0IHBhcmVudFJlZiA9IHBhZ2VLaWQuZ2V0UmF3KCJQIik7CiAgICAgICAgY29uc3QgcGFyZW50RGljdCA9IHhyZWYuZmV0Y2hJZlJlZihwYXJlbnRSZWYpOwogICAgICAgIGlmIChwYXJlbnRSZWYgaW5zdGFuY2VvZiBSZWYgJiYgcGFyZW50RGljdCBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IHsKICAgICAgICAgICAgcmVmOiBraWRSZWYsCiAgICAgICAgICAgIGRpY3Q6IHBhZ2VLaWQKICAgICAgICAgIH07CiAgICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbXMpIHsKICAgICAgICAgICAgZWxlbWVudC5zdHJ1Y3RUcmVlUGFyZW50ID0gcGFyYW1zOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICByZXR1cm4gZmFsc2U7CiAgICB9OwogICAgZm9yIChjb25zdCBraWRSZWYgb2YgcGFyZW50QXJyYXkpIHsKICAgICAgaWYgKCEoa2lkUmVmIGluc3RhbmNlb2YgUmVmKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IHBhZ2VLaWQgPSB4cmVmLmZldGNoKGtpZFJlZik7CiAgICAgIGNvbnN0IGsgPSBwYWdlS2lkLmdldCgiSyIpOwogICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihrKSkgewogICAgICAgIHVwZGF0ZUVsZW1lbnQoaywgcGFnZUtpZCwga2lkUmVmKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIUFycmF5LmlzQXJyYXkoaykpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBmb3IgKGxldCBraWQgb2YgaykgewogICAgICAgIGtpZCA9IHhyZWYuZmV0Y2hJZlJlZihraWQpOwogICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGtpZCkgJiYgdXBkYXRlRWxlbWVudChraWQsIHBhZ2VLaWQsIGtpZFJlZikpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAoIShraWQgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICghaXNOYW1lKGtpZC5nZXQoIlR5cGUiKSwgIk1DUiIpKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgY29uc3QgbWNpZCA9IGtpZC5nZXQoIk1DSUQiKTsKICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihtY2lkKSAmJiB1cGRhdGVFbGVtZW50KG1jaWQsIHBhZ2VLaWQsIGtpZFJlZikpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICBzdGF0aWMgYXN5bmMgI3VwZGF0ZVBhcmVudFRhZyh7CiAgICBzdHJ1Y3RUcmVlUGFyZW50LAogICAgdGFnRGljdCwKICAgIG5ld1RhZ1JlZiwKICAgIHN0cnVjdFRyZWVSb290UmVmLAogICAgZmFsbGJhY2tLaWRzLAogICAgeHJlZiwKICAgIGNhY2hlCiAgfSkgewogICAgbGV0IHJlZiA9IG51bGw7CiAgICBsZXQgcGFyZW50UmVmOwogICAgaWYgKHN0cnVjdFRyZWVQYXJlbnQpIHsKICAgICAgKHsKICAgICAgICByZWYKICAgICAgfSA9IHN0cnVjdFRyZWVQYXJlbnQpOwogICAgICBwYXJlbnRSZWYgPSBzdHJ1Y3RUcmVlUGFyZW50LmRpY3QuZ2V0UmF3KCJQIikgfHwgc3RydWN0VHJlZVJvb3RSZWY7CiAgICB9IGVsc2UgewogICAgICBwYXJlbnRSZWYgPSBzdHJ1Y3RUcmVlUm9vdFJlZjsKICAgIH0KICAgIHRhZ0RpY3Quc2V0KCJQIiwgcGFyZW50UmVmKTsKICAgIGNvbnN0IHBhcmVudERpY3QgPSB4cmVmLmZldGNoSWZSZWYocGFyZW50UmVmKTsKICAgIGlmICghcGFyZW50RGljdCkgewogICAgICBmYWxsYmFja0tpZHMucHVzaChuZXdUYWdSZWYpOwogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgY2FjaGVkUGFyZW50RGljdCA9IGNhY2hlLmdldChwYXJlbnRSZWYpOwogICAgaWYgKCFjYWNoZWRQYXJlbnREaWN0KSB7CiAgICAgIGNhY2hlZFBhcmVudERpY3QgPSBwYXJlbnREaWN0LmNsb25lKCk7CiAgICAgIGNhY2hlLnB1dChwYXJlbnRSZWYsIGNhY2hlZFBhcmVudERpY3QpOwogICAgfQogICAgY29uc3QgcGFyZW50S2lkc1JhdyA9IGNhY2hlZFBhcmVudERpY3QuZ2V0UmF3KCJLIik7CiAgICBsZXQgY2FjaGVkUGFyZW50S2lkcyA9IHBhcmVudEtpZHNSYXcgaW5zdGFuY2VvZiBSZWYgPyBjYWNoZS5nZXQocGFyZW50S2lkc1JhdykgOiBudWxsOwogICAgaWYgKCFjYWNoZWRQYXJlbnRLaWRzKSB7CiAgICAgIGNhY2hlZFBhcmVudEtpZHMgPSB4cmVmLmZldGNoSWZSZWYocGFyZW50S2lkc1Jhdyk7CiAgICAgIGNhY2hlZFBhcmVudEtpZHMgPSBBcnJheS5pc0FycmF5KGNhY2hlZFBhcmVudEtpZHMpID8gY2FjaGVkUGFyZW50S2lkcy5zbGljZSgpIDogW3BhcmVudEtpZHNSYXddOwogICAgICBjb25zdCBwYXJlbnRLaWRzUmVmID0geHJlZi5nZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgY2FjaGVkUGFyZW50RGljdC5zZXQoIksiLCBwYXJlbnRLaWRzUmVmKTsKICAgICAgY2FjaGUucHV0KHBhcmVudEtpZHNSZWYsIGNhY2hlZFBhcmVudEtpZHMpOwogICAgfQogICAgY29uc3QgaW5kZXggPSBjYWNoZWRQYXJlbnRLaWRzLmluZGV4T2YocmVmKTsKICAgIGNhY2hlZFBhcmVudEtpZHMuc3BsaWNlKGluZGV4ID49IDAgPyBpbmRleCArIDEgOiBjYWNoZWRQYXJlbnRLaWRzLmxlbmd0aCwgMCwgbmV3VGFnUmVmKTsKICB9Cn0KY2xhc3MgU3RydWN0RWxlbWVudE5vZGUgewogIGNvbnN0cnVjdG9yKHRyZWUsIGRpY3QpIHsKICAgIHRoaXMudHJlZSA9IHRyZWU7CiAgICB0aGlzLnhyZWYgPSB0cmVlLnhyZWY7CiAgICB0aGlzLmRpY3QgPSBkaWN0OwogICAgdGhpcy5raWRzID0gW107CiAgICB0aGlzLnBhcnNlS2lkcygpOwogIH0KICBnZXQgcm9sZSgpIHsKICAgIGNvbnN0IG5hbWVPYmogPSB0aGlzLmRpY3QuZ2V0KCJTIik7CiAgICBjb25zdCBuYW1lID0gbmFtZU9iaiBpbnN0YW5jZW9mIE5hbWUgPyBuYW1lT2JqLm5hbWUgOiAiIjsKICAgIGNvbnN0IHsKICAgICAgcm9vdAogICAgfSA9IHRoaXMudHJlZTsKICAgIHJldHVybiByb290LnJvbGVNYXAuZ2V0KG5hbWUpID8/IG5hbWU7CiAgfQogIGdldCBtYXRoTUwoKSB7CiAgICBsZXQgQUZzID0gdGhpcy5kaWN0LmdldCgiQUYiKSB8fCBbXTsKICAgIGlmICghQXJyYXkuaXNBcnJheShBRnMpKSB7CiAgICAgIEFGcyA9IFtBRnNdOwogICAgfQogICAgZm9yIChsZXQgYWYgb2YgQUZzKSB7CiAgICAgIGFmID0gdGhpcy54cmVmLmZldGNoSWZSZWYoYWYpOwogICAgICBpZiAoIShhZiBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKCFpc05hbWUoYWYuZ2V0KCJUeXBlIiksICJGaWxlc3BlYyIpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKCFpc05hbWUoYWYuZ2V0KCJBRlJlbGF0aW9uc2hpcCIpLCAiU3VwcGxlbWVudCIpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgZWYgPSBhZi5nZXQoIkVGIik7CiAgICAgIGlmICghKGVmIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBmaWxlU3RyZWFtID0gZWYuZ2V0KCJVRiIpIHx8IGVmLmdldCgiRiIpOwogICAgICBpZiAoIShmaWxlU3RyZWFtIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIWlzTmFtZShmaWxlU3RyZWFtLmRpY3QuZ2V0KCJUeXBlIiksICJFbWJlZGRlZEZpbGUiKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICghaXNOYW1lKGZpbGVTdHJlYW0uZGljdC5nZXQoIlN1YnR5cGUiKSwgImFwcGxpY2F0aW9uL21hdGhtbCt4bWwiKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHJldHVybiBzdHJpbmdUb1VURjhTdHJpbmcoZmlsZVN0cmVhbS5nZXRTdHJpbmcoKSk7CiAgICB9CiAgICBjb25zdCBBID0gdGhpcy5kaWN0LmdldCgiQSIpOwogICAgaWYgKEEgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGNvbnN0IE8gPSBBLmdldCgiTyIpOwogICAgICBpZiAoaXNOYW1lKE8sICJNU0ZUX09mZmljZSIpKSB7CiAgICAgICAgY29uc3QgbWF0aG1sID0gQS5nZXQoIk1TRlRfTWF0aE1MIik7CiAgICAgICAgcmV0dXJuIG1hdGhtbCA/IHN0cmluZ1RvUERGU3RyaW5nKG1hdGhtbCkgOiBudWxsOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgcGFyc2VLaWRzKCkgewogICAgbGV0IHBhZ2VPYmpJZCA9IG51bGw7CiAgICBjb25zdCBvYmpSZWYgPSB0aGlzLmRpY3QuZ2V0UmF3KCJQZyIpOwogICAgaWYgKG9ialJlZiBpbnN0YW5jZW9mIFJlZikgewogICAgICBwYWdlT2JqSWQgPSBvYmpSZWYudG9TdHJpbmcoKTsKICAgIH0KICAgIGNvbnN0IGtpZHMgPSB0aGlzLmRpY3QuZ2V0KCJLIik7CiAgICBpZiAoQXJyYXkuaXNBcnJheShraWRzKSkgewogICAgICBmb3IgKGNvbnN0IGtpZCBvZiBraWRzKSB7CiAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMucGFyc2VLaWQocGFnZU9iaklkLCB0aGlzLnhyZWYuZmV0Y2hJZlJlZihraWQpKTsKICAgICAgICBpZiAoZWxlbWVudCkgewogICAgICAgICAgdGhpcy5raWRzLnB1c2goZWxlbWVudCk7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5wYXJzZUtpZChwYWdlT2JqSWQsIGtpZHMpOwogICAgICBpZiAoZWxlbWVudCkgewogICAgICAgIHRoaXMua2lkcy5wdXNoKGVsZW1lbnQpOwogICAgICB9CiAgICB9CiAgfQogIHBhcnNlS2lkKHBhZ2VPYmpJZCwga2lkKSB7CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihraWQpKSB7CiAgICAgIGlmICh0aGlzLnRyZWUucGFnZURpY3Qub2JqSWQgIT09IHBhZ2VPYmpJZCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHJldHVybiBuZXcgU3RydWN0RWxlbWVudCh7CiAgICAgICAgdHlwZTogU3RydWN0RWxlbWVudFR5cGUuUEFHRV9DT05URU5ULAogICAgICAgIG1jaWQ6IGtpZCwKICAgICAgICBwYWdlT2JqSWQKICAgICAgfSk7CiAgICB9CiAgICBpZiAoIShraWQgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHBhZ2VSZWYgPSBraWQuZ2V0UmF3KCJQZyIpOwogICAgaWYgKHBhZ2VSZWYgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgcGFnZU9iaklkID0gcGFnZVJlZi50b1N0cmluZygpOwogICAgfQogICAgY29uc3QgdHlwZSA9IGtpZC5nZXQoIlR5cGUiKSBpbnN0YW5jZW9mIE5hbWUgPyBraWQuZ2V0KCJUeXBlIikubmFtZSA6IG51bGw7CiAgICBpZiAodHlwZSA9PT0gIk1DUiIpIHsKICAgICAgaWYgKHRoaXMudHJlZS5wYWdlRGljdC5vYmpJZCAhPT0gcGFnZU9iaklkKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgY29uc3Qga2lkUmVmID0ga2lkLmdldFJhdygiU3RtIik7CiAgICAgIHJldHVybiBuZXcgU3RydWN0RWxlbWVudCh7CiAgICAgICAgdHlwZTogU3RydWN0RWxlbWVudFR5cGUuU1RSRUFNX0NPTlRFTlQsCiAgICAgICAgcmVmT2JqSWQ6IGtpZFJlZiBpbnN0YW5jZW9mIFJlZiA/IGtpZFJlZi50b1N0cmluZygpIDogbnVsbCwKICAgICAgICBwYWdlT2JqSWQsCiAgICAgICAgbWNpZDoga2lkLmdldCgiTUNJRCIpCiAgICAgIH0pOwogICAgfQogICAgaWYgKHR5cGUgPT09ICJPQkpSIikgewogICAgICBpZiAodGhpcy50cmVlLnBhZ2VEaWN0Lm9iaklkICE9PSBwYWdlT2JqSWQpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBjb25zdCBraWRSZWYgPSBraWQuZ2V0UmF3KCJPYmoiKTsKICAgICAgcmV0dXJuIG5ldyBTdHJ1Y3RFbGVtZW50KHsKICAgICAgICB0eXBlOiBTdHJ1Y3RFbGVtZW50VHlwZS5PQkpFQ1QsCiAgICAgICAgcmVmT2JqSWQ6IGtpZFJlZiBpbnN0YW5jZW9mIFJlZiA/IGtpZFJlZi50b1N0cmluZygpIDogbnVsbCwKICAgICAgICBwYWdlT2JqSWQKICAgICAgfSk7CiAgICB9CiAgICByZXR1cm4gbmV3IFN0cnVjdEVsZW1lbnQoewogICAgICB0eXBlOiBTdHJ1Y3RFbGVtZW50VHlwZS5FTEVNRU5ULAogICAgICBkaWN0OiBraWQKICAgIH0pOwogIH0KfQpjbGFzcyBTdHJ1Y3RFbGVtZW50IHsKICBjb25zdHJ1Y3Rvcih7CiAgICB0eXBlLAogICAgZGljdCA9IG51bGwsCiAgICBtY2lkID0gbnVsbCwKICAgIHBhZ2VPYmpJZCA9IG51bGwsCiAgICByZWZPYmpJZCA9IG51bGwKICB9KSB7CiAgICB0aGlzLnR5cGUgPSB0eXBlOwogICAgdGhpcy5kaWN0ID0gZGljdDsKICAgIHRoaXMubWNpZCA9IG1jaWQ7CiAgICB0aGlzLnBhZ2VPYmpJZCA9IHBhZ2VPYmpJZDsKICAgIHRoaXMucmVmT2JqSWQgPSByZWZPYmpJZDsKICAgIHRoaXMucGFyZW50Tm9kZSA9IG51bGw7CiAgfQp9CmNsYXNzIFN0cnVjdFRyZWVQYWdlIHsKICBjb25zdHJ1Y3RvcihzdHJ1Y3RUcmVlUm9vdCwgcGFnZURpY3QpIHsKICAgIHRoaXMucm9vdCA9IHN0cnVjdFRyZWVSb290OwogICAgdGhpcy54cmVmID0gc3RydWN0VHJlZVJvb3Q/LnhyZWYgPz8gbnVsbDsKICAgIHRoaXMucm9vdERpY3QgPSBzdHJ1Y3RUcmVlUm9vdD8uZGljdCA/PyBudWxsOwogICAgdGhpcy5wYWdlRGljdCA9IHBhZ2VEaWN0OwogICAgdGhpcy5ub2RlcyA9IFtdOwogIH0KICBjb2xsZWN0T2JqZWN0cyhwYWdlUmVmKSB7CiAgICBpZiAoIXRoaXMucm9vdCB8fCAhdGhpcy5yb290RGljdCB8fCAhKHBhZ2VSZWYgaW5zdGFuY2VvZiBSZWYpKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgcGFyZW50VHJlZSA9IHRoaXMucm9vdERpY3QuZ2V0KCJQYXJlbnRUcmVlIik7CiAgICBpZiAoIXBhcmVudFRyZWUpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBpZHMgPSB0aGlzLnJvb3Quc3RydWN0UGFyZW50SWRzPy5nZXQocGFnZVJlZik7CiAgICBpZiAoIWlkcykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IG1hcCA9IG5ldyBNYXAoKTsKICAgIGNvbnN0IG51bWJlclRyZWUgPSBuZXcgTnVtYmVyVHJlZShwYXJlbnRUcmVlLCB0aGlzLnhyZWYpOwogICAgZm9yIChjb25zdCBbZWxlbUlkXSBvZiBpZHMpIHsKICAgICAgY29uc3Qgb2JqID0gbnVtYmVyVHJlZS5nZXRSYXcoZWxlbUlkKTsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIG1hcC5zZXQoZWxlbUlkLCBvYmopOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbWFwOwogIH0KICBwYXJzZShwYWdlUmVmKSB7CiAgICBpZiAoIXRoaXMucm9vdCB8fCAhdGhpcy5yb290RGljdCB8fCAhKHBhZ2VSZWYgaW5zdGFuY2VvZiBSZWYpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgcGFyZW50VHJlZQogICAgfSA9IHRoaXMucm9vdDsKICAgIGlmICghcGFyZW50VHJlZSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBpZCA9IHRoaXMucGFnZURpY3QuZ2V0KCJTdHJ1Y3RQYXJlbnRzIik7CiAgICBjb25zdCBpZHMgPSB0aGlzLnJvb3Quc3RydWN0UGFyZW50SWRzPy5nZXQocGFnZVJlZik7CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoaWQpICYmICFpZHMpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgbWFwID0gbmV3IE1hcCgpOwogICAgaWYgKE51bWJlci5pc0ludGVnZXIoaWQpKSB7CiAgICAgIGNvbnN0IHBhcmVudEFycmF5ID0gcGFyZW50VHJlZS5nZXQoaWQpOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShwYXJlbnRBcnJheSkpIHsKICAgICAgICBmb3IgKGNvbnN0IHJlZiBvZiBwYXJlbnRBcnJheSkgewogICAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgICB0aGlzLmFkZE5vZGUodGhpcy54cmVmLmZldGNoKHJlZiksIG1hcCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAoIWlkcykgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGNvbnN0IFtlbGVtSWQsIHR5cGVdIG9mIGlkcykgewogICAgICBjb25zdCBvYmogPSBwYXJlbnRUcmVlLmdldChlbGVtSWQpOwogICAgICBpZiAob2JqKSB7CiAgICAgICAgY29uc3QgZWxlbSA9IHRoaXMuYWRkTm9kZSh0aGlzLnhyZWYuZmV0Y2hJZlJlZihvYmopLCBtYXApOwogICAgICAgIGlmIChlbGVtPy5raWRzPy5sZW5ndGggPT09IDEgJiYgZWxlbS5raWRzWzBdLnR5cGUgPT09IFN0cnVjdEVsZW1lbnRUeXBlLk9CSkVDVCkgewogICAgICAgICAgZWxlbS5raWRzWzBdLnR5cGUgPSB0eXBlOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICBhZGROb2RlKGRpY3QsIG1hcCwgbGV2ZWwgPSAwKSB7CiAgICBpZiAobGV2ZWwgPiBNQVhfREVQVEgpIHsKICAgICAgd2FybigiU3RydWN0VHJlZSBNQVhfREVQVEggcmVhY2hlZC4iKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBpZiAoIShkaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBpZiAobWFwLmhhcyhkaWN0KSkgewogICAgICByZXR1cm4gbWFwLmdldChkaWN0KTsKICAgIH0KICAgIGNvbnN0IGVsZW1lbnQgPSBuZXcgU3RydWN0RWxlbWVudE5vZGUodGhpcywgZGljdCk7CiAgICBtYXAuc2V0KGRpY3QsIGVsZW1lbnQpOwogICAgc3dpdGNoIChlbGVtZW50LnJvbGUpIHsKICAgICAgY2FzZSAiTCI6CiAgICAgIGNhc2UgIkxCb2R5IjoKICAgICAgY2FzZSAiTEkiOgogICAgICBjYXNlICJUYWJsZSI6CiAgICAgIGNhc2UgIlRIZWFkIjoKICAgICAgY2FzZSAiVEJvZHkiOgogICAgICBjYXNlICJURm9vdCI6CiAgICAgIGNhc2UgIlRSIjoKICAgICAgICB7CiAgICAgICAgICBmb3IgKGNvbnN0IGtpZCBvZiBlbGVtZW50LmtpZHMpIHsKICAgICAgICAgICAgaWYgKGtpZC50eXBlID09PSBTdHJ1Y3RFbGVtZW50VHlwZS5FTEVNRU5UKSB7CiAgICAgICAgICAgICAgdGhpcy5hZGROb2RlKGtpZC5kaWN0LCBtYXAsIGxldmVsIC0gMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICBjb25zdCBwYXJlbnQgPSBkaWN0LmdldCgiUCIpOwogICAgaWYgKCEocGFyZW50IGluc3RhbmNlb2YgRGljdCkgfHwgaXNOYW1lKHBhcmVudC5nZXQoIlR5cGUiKSwgIlN0cnVjdFRyZWVSb290IikpIHsKICAgICAgaWYgKCF0aGlzLmFkZFRvcExldmVsTm9kZShkaWN0LCBlbGVtZW50KSkgewogICAgICAgIG1hcC5kZWxldGUoZGljdCk7CiAgICAgIH0KICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9CiAgICBjb25zdCBwYXJlbnROb2RlID0gdGhpcy5hZGROb2RlKHBhcmVudCwgbWFwLCBsZXZlbCArIDEpOwogICAgaWYgKCFwYXJlbnROb2RlKSB7CiAgICAgIHJldHVybiBlbGVtZW50OwogICAgfQogICAgbGV0IHNhdmUgPSBmYWxzZTsKICAgIGZvciAoY29uc3Qga2lkIG9mIHBhcmVudE5vZGUua2lkcykgewogICAgICBpZiAoa2lkLnR5cGUgPT09IFN0cnVjdEVsZW1lbnRUeXBlLkVMRU1FTlQgJiYga2lkLmRpY3QgPT09IGRpY3QpIHsKICAgICAgICBraWQucGFyZW50Tm9kZSA9IGVsZW1lbnQ7CiAgICAgICAgc2F2ZSA9IHRydWU7CiAgICAgIH0KICAgIH0KICAgIGlmICghc2F2ZSkgewogICAgICBtYXAuZGVsZXRlKGRpY3QpOwogICAgfQogICAgcmV0dXJuIGVsZW1lbnQ7CiAgfQogIGFkZFRvcExldmVsTm9kZShkaWN0LCBlbGVtZW50KSB7CiAgICBjb25zdCBpbmRleCA9IHRoaXMucm9vdC5nZXRLaWRQb3NpdGlvbihkaWN0Lm9iaklkKTsKICAgIGlmIChpc05hTihpbmRleCkpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKGluZGV4ICE9PSAtMSkgewogICAgICB0aGlzLm5vZGVzW2luZGV4XSA9IGVsZW1lbnQ7CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgZ2V0IHNlcmlhbGl6YWJsZSgpIHsKICAgIGZ1bmN0aW9uIG5vZGVUb1NlcmlhbGl6YWJsZShub2RlLCBwYXJlbnQsIGxldmVsID0gMCkgewogICAgICBpZiAobGV2ZWwgPiBNQVhfREVQVEgpIHsKICAgICAgICB3YXJuKCJTdHJ1Y3RUcmVlIHRvbyBkZWVwIHRvIGJlIGZ1bGx5IHNlcmlhbGl6ZWQuIik7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvbnN0IG9iaiA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIG9iai5yb2xlID0gbm9kZS5yb2xlOwogICAgICBvYmouY2hpbGRyZW4gPSBbXTsKICAgICAgcGFyZW50LmNoaWxkcmVuLnB1c2gob2JqKTsKICAgICAgbGV0IGFsdCA9IG5vZGUuZGljdC5nZXQoIkFsdCIpOwogICAgICBpZiAodHlwZW9mIGFsdCAhPT0gInN0cmluZyIpIHsKICAgICAgICBhbHQgPSBub2RlLmRpY3QuZ2V0KCJBY3R1YWxUZXh0Iik7CiAgICAgIH0KICAgICAgaWYgKHR5cGVvZiBhbHQgPT09ICJzdHJpbmciKSB7CiAgICAgICAgb2JqLmFsdCA9IHN0cmluZ1RvUERGU3RyaW5nKGFsdCk7CiAgICAgIH0KICAgICAgaWYgKG9iai5yb2xlID09PSAiRm9ybXVsYSIpIHsKICAgICAgICBjb25zdCB7CiAgICAgICAgICBtYXRoTUwKICAgICAgICB9ID0gbm9kZTsKICAgICAgICBpZiAobWF0aE1MKSB7CiAgICAgICAgICBvYmoubWF0aE1MID0gbWF0aE1MOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBhID0gbm9kZS5kaWN0LmdldCgiQSIpOwogICAgICBpZiAoYSBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICBjb25zdCBiYm94ID0gbG9va3VwTm9ybWFsUmVjdChhLmdldEFycmF5KCJCQm94IiksIG51bGwpOwogICAgICAgIGlmIChiYm94KSB7CiAgICAgICAgICBvYmouYmJveCA9IGJib3g7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvbnN0IHdpZHRoID0gYS5nZXQoIldpZHRoIik7CiAgICAgICAgICBjb25zdCBoZWlnaHQgPSBhLmdldCgiSGVpZ2h0Iik7CiAgICAgICAgICBpZiAodHlwZW9mIHdpZHRoID09PSAibnVtYmVyIiAmJiB3aWR0aCA+IDAgJiYgdHlwZW9mIGhlaWdodCA9PT0gIm51bWJlciIgJiYgaGVpZ2h0ID4gMCkgewogICAgICAgICAgICBvYmouYmJveCA9IFswLCAwLCB3aWR0aCwgaGVpZ2h0XTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgbGFuZyA9IG5vZGUuZGljdC5nZXQoIkxhbmciKTsKICAgICAgaWYgKHR5cGVvZiBsYW5nID09PSAic3RyaW5nIikgewogICAgICAgIG9iai5sYW5nID0gc3RyaW5nVG9QREZTdHJpbmcobGFuZyk7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBraWQgb2Ygbm9kZS5raWRzKSB7CiAgICAgICAgY29uc3Qga2lkRWxlbWVudCA9IGtpZC50eXBlID09PSBTdHJ1Y3RFbGVtZW50VHlwZS5FTEVNRU5UID8ga2lkLnBhcmVudE5vZGUgOiBudWxsOwogICAgICAgIGlmIChraWRFbGVtZW50KSB7CiAgICAgICAgICBub2RlVG9TZXJpYWxpemFibGUoa2lkRWxlbWVudCwgb2JqLCBsZXZlbCArIDEpOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfSBlbHNlIGlmIChraWQudHlwZSA9PT0gU3RydWN0RWxlbWVudFR5cGUuUEFHRV9DT05URU5UIHx8IGtpZC50eXBlID09PSBTdHJ1Y3RFbGVtZW50VHlwZS5TVFJFQU1fQ09OVEVOVCkgewogICAgICAgICAgb2JqLmNoaWxkcmVuLnB1c2goewogICAgICAgICAgICB0eXBlOiAiY29udGVudCIsCiAgICAgICAgICAgIGlkOiBgcCR7a2lkLnBhZ2VPYmpJZH1fbWMke2tpZC5tY2lkfWAKICAgICAgICAgIH0pOwogICAgICAgIH0gZWxzZSBpZiAoa2lkLnR5cGUgPT09IFN0cnVjdEVsZW1lbnRUeXBlLk9CSkVDVCkgewogICAgICAgICAgb2JqLmNoaWxkcmVuLnB1c2goewogICAgICAgICAgICB0eXBlOiAib2JqZWN0IiwKICAgICAgICAgICAgaWQ6IGtpZC5yZWZPYmpJZAogICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIGlmIChraWQudHlwZSA9PT0gU3RydWN0RWxlbWVudFR5cGUuQU5OT1RBVElPTikgewogICAgICAgICAgb2JqLmNoaWxkcmVuLnB1c2goewogICAgICAgICAgICB0eXBlOiAiYW5ub3RhdGlvbiIsCiAgICAgICAgICAgIGlkOiBgJHtBbm5vdGF0aW9uUHJlZml4fSR7a2lkLnJlZk9iaklkfWAKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgY29uc3Qgcm9vdCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICByb290LmNoaWxkcmVuID0gW107CiAgICByb290LnJvbGUgPSAiUm9vdCI7CiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXMubm9kZXMpIHsKICAgICAgaWYgKCFjaGlsZCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIG5vZGVUb1NlcmlhbGl6YWJsZShjaGlsZCwgcm9vdCk7CiAgICB9CiAgICByZXR1cm4gcm9vdDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2NhdGFsb2cuanMKCgoKCgoKCgoKCgpjb25zdCBpc1JlZiA9IHYgPT4gdiBpbnN0YW5jZW9mIFJlZjsKY29uc3QgaXNWYWxpZEV4cGxpY2l0RGVzdCA9IF9pc1ZhbGlkRXhwbGljaXREZXN0LmJpbmQobnVsbCwgaXNSZWYsIGlzTmFtZSk7CmZ1bmN0aW9uIGZldGNoRGVzdChkZXN0KSB7CiAgaWYgKGRlc3QgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICBkZXN0ID0gZGVzdC5nZXQoIkQiKTsKICB9CiAgcmV0dXJuIGlzVmFsaWRFeHBsaWNpdERlc3QoZGVzdCkgPyBkZXN0IDogbnVsbDsKfQpmdW5jdGlvbiBmZXRjaFJlbW90ZURlc3QoYWN0aW9uKSB7CiAgbGV0IGRlc3QgPSBhY3Rpb24uZ2V0KCJEIik7CiAgaWYgKGRlc3QpIHsKICAgIGlmIChkZXN0IGluc3RhbmNlb2YgTmFtZSkgewogICAgICBkZXN0ID0gZGVzdC5uYW1lOwogICAgfQogICAgaWYgKHR5cGVvZiBkZXN0ID09PSAic3RyaW5nIikgewogICAgICByZXR1cm4gc3RyaW5nVG9QREZTdHJpbmcoZGVzdCwgdHJ1ZSk7CiAgICB9IGVsc2UgaWYgKGlzVmFsaWRFeHBsaWNpdERlc3QoZGVzdCkpIHsKICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGRlc3QpOwogICAgfQogIH0KICByZXR1cm4gbnVsbDsKfQpjbGFzcyBDYXRhbG9nIHsKICAjYWN0dWFsTnVtUGFnZXMgPSBudWxsOwogICNjYXREaWN0ID0gbnVsbDsKICBidWlsdEluQ01hcENhY2hlID0gbmV3IE1hcCgpOwogIGZvbnRDYWNoZSA9IG5ldyBSZWZTZXRDYWNoZSgpOwogIGdsb2JhbENvbG9yU3BhY2VDYWNoZSA9IG5ldyBHbG9iYWxDb2xvclNwYWNlQ2FjaGUoKTsKICBnbG9iYWxJbWFnZUNhY2hlID0gbmV3IEdsb2JhbEltYWdlQ2FjaGUoKTsKICBub25CbGVuZE1vZGVzU2V0ID0gbmV3IFJlZlNldCgpOwogIHBhZ2VEaWN0Q2FjaGUgPSBuZXcgUmVmU2V0Q2FjaGUoKTsKICBwYWdlSW5kZXhDYWNoZSA9IG5ldyBSZWZTZXRDYWNoZSgpOwogIHBhZ2VLaWRzQ291bnRDYWNoZSA9IG5ldyBSZWZTZXRDYWNoZSgpOwogIHN0YW5kYXJkRm9udERhdGFDYWNoZSA9IG5ldyBNYXAoKTsKICBzeXN0ZW1Gb250Q2FjaGUgPSBuZXcgTWFwKCk7CiAgY29uc3RydWN0b3IocGRmTWFuYWdlciwgeHJlZikgewogICAgdGhpcy5wZGZNYW5hZ2VyID0gcGRmTWFuYWdlcjsKICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgICB0aGlzLiNjYXREaWN0ID0geHJlZi5nZXRDYXRhbG9nT2JqKCk7CiAgICBpZiAoISh0aGlzLiNjYXREaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJDYXRhbG9nIG9iamVjdCBpcyBub3QgYSBkaWN0aW9uYXJ5LiIpOwogICAgfQogICAgdGhpcy50b3BsZXZlbFBhZ2VzRGljdDsKICB9CiAgY2xvbmVEaWN0KCkgewogICAgcmV0dXJuIHRoaXMuI2NhdERpY3QuY2xvbmUoKTsKICB9CiAgZ2V0IHZlcnNpb24oKSB7CiAgICBjb25zdCB2ZXJzaW9uID0gdGhpcy4jY2F0RGljdC5nZXQoIlZlcnNpb24iKTsKICAgIGlmICh2ZXJzaW9uIGluc3RhbmNlb2YgTmFtZSkgewogICAgICBpZiAoUERGX1ZFUlNJT05fUkVHRVhQLnRlc3QodmVyc2lvbi5uYW1lKSkgewogICAgICAgIHJldHVybiBzaGFkb3codGhpcywgInZlcnNpb24iLCB2ZXJzaW9uLm5hbWUpOwogICAgICB9CiAgICAgIHdhcm4oYEludmFsaWQgUERGIGNhdGFsb2cgdmVyc2lvbjogJHt2ZXJzaW9uLm5hbWV9YCk7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJ2ZXJzaW9uIiwgbnVsbCk7CiAgfQogIGdldCBsYW5nKCkgewogICAgY29uc3QgbGFuZyA9IHRoaXMuI2NhdERpY3QuZ2V0KCJMYW5nIik7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJsYW5nIiwgbGFuZyAmJiB0eXBlb2YgbGFuZyA9PT0gInN0cmluZyIgPyBzdHJpbmdUb1BERlN0cmluZyhsYW5nKSA6IG51bGwpOwogIH0KICBnZXQgbmVlZHNSZW5kZXJpbmcoKSB7CiAgICBjb25zdCBuZWVkc1JlbmRlcmluZyA9IHRoaXMuI2NhdERpY3QuZ2V0KCJOZWVkc1JlbmRlcmluZyIpOwogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAibmVlZHNSZW5kZXJpbmciLCB0eXBlb2YgbmVlZHNSZW5kZXJpbmcgPT09ICJib29sZWFuIiA/IG5lZWRzUmVuZGVyaW5nIDogZmFsc2UpOwogIH0KICBnZXQgY29sbGVjdGlvbigpIHsKICAgIGxldCBjb2xsZWN0aW9uID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIGNvbnN0IG9iaiA9IHRoaXMuI2NhdERpY3QuZ2V0KCJDb2xsZWN0aW9uIik7CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBEaWN0ICYmIG9iai5zaXplID4gMCkgewogICAgICAgIGNvbGxlY3Rpb24gPSBvYmo7CiAgICAgIH0KICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgaW5mbygiQ2Fubm90IGZldGNoIENvbGxlY3Rpb24gZW50cnk7IGFzc3VtaW5nIG5vIGNvbGxlY3Rpb24gaXMgcHJlc2VudC4iKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImNvbGxlY3Rpb24iLCBjb2xsZWN0aW9uKTsKICB9CiAgZ2V0IGFjcm9Gb3JtKCkgewogICAgbGV0IGFjcm9Gb3JtID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIGNvbnN0IG9iaiA9IHRoaXMuI2NhdERpY3QuZ2V0KCJBY3JvRm9ybSIpOwogICAgICBpZiAob2JqIGluc3RhbmNlb2YgRGljdCAmJiBvYmouc2l6ZSA+IDApIHsKICAgICAgICBhY3JvRm9ybSA9IG9iajsKICAgICAgfQogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICBpbmZvKCJDYW5ub3QgZmV0Y2ggQWNyb0Zvcm0gZW50cnk7IGFzc3VtaW5nIG5vIGZvcm1zIGFyZSBwcmVzZW50LiIpOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiYWNyb0Zvcm0iLCBhY3JvRm9ybSk7CiAgfQogIGdldCBhY3JvRm9ybVJlZigpIHsKICAgIGNvbnN0IHZhbHVlID0gdGhpcy4jY2F0RGljdC5nZXRSYXcoIkFjcm9Gb3JtIik7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJhY3JvRm9ybVJlZiIsIHZhbHVlIGluc3RhbmNlb2YgUmVmID8gdmFsdWUgOiBudWxsKTsKICB9CiAgZ2V0IG1ldGFkYXRhKCkgewogICAgY29uc3Qgc3RyZWFtUmVmID0gdGhpcy4jY2F0RGljdC5nZXRSYXcoIk1ldGFkYXRhIik7CiAgICBpZiAoIShzdHJlYW1SZWYgaW5zdGFuY2VvZiBSZWYpKSB7CiAgICAgIHJldHVybiBzaGFkb3codGhpcywgIm1ldGFkYXRhIiwgbnVsbCk7CiAgICB9CiAgICBsZXQgbWV0YWRhdGEgPSBudWxsOwogICAgdHJ5IHsKICAgICAgY29uc3Qgc3RyZWFtID0gdGhpcy54cmVmLmZldGNoKHN0cmVhbVJlZiwgIXRoaXMueHJlZi5lbmNyeXB0Py5lbmNyeXB0TWV0YWRhdGEpOwogICAgICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgQmFzZVN0cmVhbSAmJiBzdHJlYW0uZGljdCBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICBjb25zdCB0eXBlID0gc3RyZWFtLmRpY3QuZ2V0KCJUeXBlIik7CiAgICAgICAgY29uc3Qgc3VidHlwZSA9IHN0cmVhbS5kaWN0LmdldCgiU3VidHlwZSIpOwogICAgICAgIGlmIChpc05hbWUodHlwZSwgIk1ldGFkYXRhIikgJiYgaXNOYW1lKHN1YnR5cGUsICJYTUwiKSkgewogICAgICAgICAgY29uc3QgZGF0YSA9IHN0cmluZ1RvVVRGOFN0cmluZyhzdHJlYW0uZ2V0U3RyaW5nKCkpOwogICAgICAgICAgaWYgKGRhdGEpIHsKICAgICAgICAgICAgbWV0YWRhdGEgPSBuZXcgTWV0YWRhdGFQYXJzZXIoZGF0YSkuc2VyaWFsaXphYmxlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICBpbmZvKGBTa2lwcGluZyBpbnZhbGlkIE1ldGFkYXRhOiAiJHtleH0iLmApOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAibWV0YWRhdGEiLCBtZXRhZGF0YSk7CiAgfQogIGdldCBtYXJrSW5mbygpIHsKICAgIGxldCBtYXJrSW5mbyA9IG51bGw7CiAgICB0cnkgewogICAgICBtYXJrSW5mbyA9IHRoaXMuI3JlYWRNYXJrSW5mbygpOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICB3YXJuKCJVbmFibGUgdG8gcmVhZCBtYXJrIGluZm8uIik7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJtYXJrSW5mbyIsIG1hcmtJbmZvKTsKICB9CiAgI3JlYWRNYXJrSW5mbygpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuI2NhdERpY3QuZ2V0KCJNYXJrSW5mbyIpOwogICAgaWYgKCEob2JqIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBtYXJrSW5mbyA9IHsKICAgICAgTWFya2VkOiBmYWxzZSwKICAgICAgVXNlclByb3BlcnRpZXM6IGZhbHNlLAogICAgICBTdXNwZWN0czogZmFsc2UKICAgIH07CiAgICBmb3IgKGNvbnN0IGtleSBpbiBtYXJrSW5mbykgewogICAgICBjb25zdCB2YWx1ZSA9IG9iai5nZXQoa2V5KTsKICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gImJvb2xlYW4iKSB7CiAgICAgICAgbWFya0luZm9ba2V5XSA9IHZhbHVlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbWFya0luZm87CiAgfQogIGdldCBoYXNTdHJ1Y3RUcmVlKCkgewogICAgcmV0dXJuIHRoaXMuI2NhdERpY3QuaGFzKCJTdHJ1Y3RUcmVlUm9vdCIpOwogIH0KICBnZXQgc3RydWN0VHJlZVJvb3QoKSB7CiAgICBsZXQgc3RydWN0VHJlZSA9IG51bGw7CiAgICB0cnkgewogICAgICBzdHJ1Y3RUcmVlID0gdGhpcy4jcmVhZFN0cnVjdFRyZWVSb290KCk7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIHdhcm4oIlVuYWJsZSByZWFkIHRvIHN0cnVjdFRyZWVSb290IGluZm8uIik7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJzdHJ1Y3RUcmVlUm9vdCIsIHN0cnVjdFRyZWUpOwogIH0KICAjcmVhZFN0cnVjdFRyZWVSb290KCkgewogICAgY29uc3QgcmF3T2JqID0gdGhpcy4jY2F0RGljdC5nZXRSYXcoIlN0cnVjdFRyZWVSb290Iik7CiAgICBjb25zdCBvYmogPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihyYXdPYmopOwogICAgaWYgKCEob2JqIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCByb290ID0gbmV3IFN0cnVjdFRyZWVSb290KHRoaXMueHJlZiwgb2JqLCByYXdPYmopOwogICAgcm9vdC5pbml0KCk7CiAgICByZXR1cm4gcm9vdDsKICB9CiAgZ2V0IHRvcGxldmVsUGFnZXNEaWN0KCkgewogICAgY29uc3QgcGFnZXNPYmogPSB0aGlzLiNjYXREaWN0LmdldCgiUGFnZXMiKTsKICAgIGlmICghKHBhZ2VzT2JqIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIHRvcC1sZXZlbCBwYWdlcyBkaWN0aW9uYXJ5LiIpOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAidG9wbGV2ZWxQYWdlc0RpY3QiLCBwYWdlc09iaik7CiAgfQogIGdldCBkb2N1bWVudE91dGxpbmUoKSB7CiAgICBsZXQgb2JqID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIG9iaiA9IHRoaXMuI3JlYWREb2N1bWVudE91dGxpbmUoKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgd2FybigiVW5hYmxlIHRvIHJlYWQgZG9jdW1lbnQgb3V0bGluZS4iKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImRvY3VtZW50T3V0bGluZSIsIG9iaik7CiAgfQogICNyZWFkRG9jdW1lbnRPdXRsaW5lKCkgewogICAgbGV0IG9iaiA9IHRoaXMuI2NhdERpY3QuZ2V0KCJPdXRsaW5lcyIpOwogICAgaWYgKCEob2JqIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBvYmogPSBvYmouZ2V0UmF3KCJGaXJzdCIpOwogICAgaWYgKCEob2JqIGluc3RhbmNlb2YgUmVmKSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHJvb3QgPSB7CiAgICAgIGl0ZW1zOiBbXQogICAgfTsKICAgIGNvbnN0IHF1ZXVlID0gW3sKICAgICAgb2JqLAogICAgICBwYXJlbnQ6IHJvb3QKICAgIH1dOwogICAgY29uc3QgcHJvY2Vzc2VkID0gbmV3IFJlZlNldCgpOwogICAgcHJvY2Vzc2VkLnB1dChvYmopOwogICAgY29uc3QgeHJlZiA9IHRoaXMueHJlZiwKICAgICAgYmxhY2tDb2xvciA9IG5ldyBVaW50OENsYW1wZWRBcnJheSgzKTsKICAgIHdoaWxlIChxdWV1ZS5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IGkgPSBxdWV1ZS5zaGlmdCgpOwogICAgICBjb25zdCBvdXRsaW5lRGljdCA9IHhyZWYuZmV0Y2hJZlJlZihpLm9iaik7CiAgICAgIGlmIChvdXRsaW5lRGljdCA9PT0gbnVsbCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICghb3V0bGluZURpY3QuaGFzKCJUaXRsZSIpKSB7CiAgICAgICAgd2FybigiSW52YWxpZCBvdXRsaW5lIGl0ZW0gZW5jb3VudGVyZWQuIik7CiAgICAgIH0KICAgICAgY29uc3QgZGF0YSA9IHsKICAgICAgICB1cmw6IG51bGwsCiAgICAgICAgZGVzdDogbnVsbCwKICAgICAgICBhY3Rpb246IG51bGwKICAgICAgfTsKICAgICAgQ2F0YWxvZy5wYXJzZURlc3REaWN0aW9uYXJ5KHsKICAgICAgICBkZXN0RGljdDogb3V0bGluZURpY3QsCiAgICAgICAgcmVzdWx0T2JqOiBkYXRhLAogICAgICAgIGRvY0Jhc2VVcmw6IHRoaXMuYmFzZVVybCwKICAgICAgICBkb2NBdHRhY2htZW50czogdGhpcy5hdHRhY2htZW50cwogICAgICB9KTsKICAgICAgY29uc3QgdGl0bGUgPSBvdXRsaW5lRGljdC5nZXQoIlRpdGxlIik7CiAgICAgIGNvbnN0IGZsYWdzID0gb3V0bGluZURpY3QuZ2V0KCJGIikgfHwgMDsKICAgICAgY29uc3QgY29sb3IgPSBvdXRsaW5lRGljdC5nZXRBcnJheSgiQyIpOwogICAgICBjb25zdCBjb3VudCA9IG91dGxpbmVEaWN0LmdldCgiQ291bnQiKTsKICAgICAgbGV0IHJnYkNvbG9yID0gYmxhY2tDb2xvcjsKICAgICAgaWYgKGlzTnVtYmVyQXJyYXkoY29sb3IsIDMpICYmIChjb2xvclswXSAhPT0gMCB8fCBjb2xvclsxXSAhPT0gMCB8fCBjb2xvclsyXSAhPT0gMCkpIHsKICAgICAgICByZ2JDb2xvciA9IENvbG9yU3BhY2VVdGlscy5yZ2IuZ2V0UmdiKGNvbG9yLCAwKTsKICAgICAgfQogICAgICBjb25zdCBvdXRsaW5lSXRlbSA9IHsKICAgICAgICBhY3Rpb246IGRhdGEuYWN0aW9uLAogICAgICAgIGF0dGFjaG1lbnQ6IGRhdGEuYXR0YWNobWVudCwKICAgICAgICBkZXN0OiBkYXRhLmRlc3QsCiAgICAgICAgdXJsOiBkYXRhLnVybCwKICAgICAgICB1bnNhZmVVcmw6IGRhdGEudW5zYWZlVXJsLAogICAgICAgIG5ld1dpbmRvdzogZGF0YS5uZXdXaW5kb3csCiAgICAgICAgc2V0T0NHU3RhdGU6IGRhdGEuc2V0T0NHU3RhdGUsCiAgICAgICAgdGl0bGU6IHR5cGVvZiB0aXRsZSA9PT0gInN0cmluZyIgPyBzdHJpbmdUb1BERlN0cmluZyh0aXRsZSkgOiAiIiwKICAgICAgICBjb2xvcjogcmdiQ29sb3IsCiAgICAgICAgY291bnQ6IE51bWJlci5pc0ludGVnZXIoY291bnQpID8gY291bnQgOiB1bmRlZmluZWQsCiAgICAgICAgYm9sZDogISEoZmxhZ3MgJiAyKSwKICAgICAgICBpdGFsaWM6ICEhKGZsYWdzICYgMSksCiAgICAgICAgaXRlbXM6IFtdCiAgICAgIH07CiAgICAgIGkucGFyZW50Lml0ZW1zLnB1c2gob3V0bGluZUl0ZW0pOwogICAgICBvYmogPSBvdXRsaW5lRGljdC5nZXRSYXcoIkZpcnN0Iik7CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBSZWYgJiYgIXByb2Nlc3NlZC5oYXMob2JqKSkgewogICAgICAgIHF1ZXVlLnB1c2goewogICAgICAgICAgb2JqLAogICAgICAgICAgcGFyZW50OiBvdXRsaW5lSXRlbQogICAgICAgIH0pOwogICAgICAgIHByb2Nlc3NlZC5wdXQob2JqKTsKICAgICAgfQogICAgICBvYmogPSBvdXRsaW5lRGljdC5nZXRSYXcoIk5leHQiKTsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIFJlZiAmJiAhcHJvY2Vzc2VkLmhhcyhvYmopKSB7CiAgICAgICAgcXVldWUucHVzaCh7CiAgICAgICAgICBvYmosCiAgICAgICAgICBwYXJlbnQ6IGkucGFyZW50CiAgICAgICAgfSk7CiAgICAgICAgcHJvY2Vzc2VkLnB1dChvYmopOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcm9vdC5pdGVtcy5sZW5ndGggPiAwID8gcm9vdC5pdGVtcyA6IG51bGw7CiAgfQogIGdldCBwZXJtaXNzaW9ucygpIHsKICAgIGxldCBwZXJtaXNzaW9ucyA9IG51bGw7CiAgICB0cnkgewogICAgICBwZXJtaXNzaW9ucyA9IHRoaXMuI3JlYWRQZXJtaXNzaW9ucygpOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICB3YXJuKCJVbmFibGUgdG8gcmVhZCBwZXJtaXNzaW9ucy4iKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInBlcm1pc3Npb25zIiwgcGVybWlzc2lvbnMpOwogIH0KICAjcmVhZFBlcm1pc3Npb25zKCkgewogICAgY29uc3QgZW5jcnlwdCA9IHRoaXMueHJlZi50cmFpbGVyLmdldCgiRW5jcnlwdCIpOwogICAgaWYgKCEoZW5jcnlwdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgbGV0IGZsYWdzID0gZW5jcnlwdC5nZXQoIlAiKTsKICAgIGlmICh0eXBlb2YgZmxhZ3MgIT09ICJudW1iZXIiKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgZmxhZ3MgKz0gMiAqKiAzMjsKICAgIGNvbnN0IHBlcm1pc3Npb25zID0gW107CiAgICBmb3IgKGNvbnN0IGtleSBpbiBQZXJtaXNzaW9uRmxhZykgewogICAgICBjb25zdCB2YWx1ZSA9IFBlcm1pc3Npb25GbGFnW2tleV07CiAgICAgIGlmIChmbGFncyAmIHZhbHVlKSB7CiAgICAgICAgcGVybWlzc2lvbnMucHVzaCh2YWx1ZSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBwZXJtaXNzaW9uczsKICB9CiAgZ2V0IG9wdGlvbmFsQ29udGVudENvbmZpZygpIHsKICAgIGxldCBjb25maWcgPSBudWxsOwogICAgdHJ5IHsKICAgICAgY29uc3QgcHJvcGVydGllcyA9IHRoaXMuI2NhdERpY3QuZ2V0KCJPQ1Byb3BlcnRpZXMiKTsKICAgICAgaWYgKCFwcm9wZXJ0aWVzKSB7CiAgICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAib3B0aW9uYWxDb250ZW50Q29uZmlnIiwgbnVsbCk7CiAgICAgIH0KICAgICAgY29uc3QgZGVmYXVsdENvbmZpZyA9IHByb3BlcnRpZXMuZ2V0KCJEIik7CiAgICAgIGlmICghZGVmYXVsdENvbmZpZykgewogICAgICAgIHJldHVybiBzaGFkb3codGhpcywgIm9wdGlvbmFsQ29udGVudENvbmZpZyIsIG51bGwpOwogICAgICB9CiAgICAgIGNvbnN0IGdyb3Vwc0RhdGEgPSBwcm9wZXJ0aWVzLmdldCgiT0NHcyIpOwogICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZ3JvdXBzRGF0YSkpIHsKICAgICAgICByZXR1cm4gc2hhZG93KHRoaXMsICJvcHRpb25hbENvbnRlbnRDb25maWciLCBudWxsKTsKICAgICAgfQogICAgICBjb25zdCBncm91cFJlZkNhY2hlID0gbmV3IFJlZlNldENhY2hlKCk7CiAgICAgIGZvciAoY29uc3QgZ3JvdXBSZWYgb2YgZ3JvdXBzRGF0YSkgewogICAgICAgIGlmICghKGdyb3VwUmVmIGluc3RhbmNlb2YgUmVmKSB8fCBncm91cFJlZkNhY2hlLmhhcyhncm91cFJlZikpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBncm91cFJlZkNhY2hlLnB1dChncm91cFJlZiwgdGhpcy4jcmVhZE9wdGlvbmFsQ29udGVudEdyb3VwKGdyb3VwUmVmKSk7CiAgICAgIH0KICAgICAgY29uZmlnID0gdGhpcy4jcmVhZE9wdGlvbmFsQ29udGVudENvbmZpZyhkZWZhdWx0Q29uZmlnLCBncm91cFJlZkNhY2hlKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgd2FybihgVW5hYmxlIHRvIHJlYWQgb3B0aW9uYWwgY29udGVudCBjb25maWc6ICR7ZXh9YCk7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJvcHRpb25hbENvbnRlbnRDb25maWciLCBjb25maWcpOwogIH0KICAjcmVhZE9wdGlvbmFsQ29udGVudEdyb3VwKGdyb3VwUmVmKSB7CiAgICBjb25zdCBncm91cCA9IHRoaXMueHJlZi5mZXRjaChncm91cFJlZik7CiAgICBjb25zdCBvYmogPSB7CiAgICAgIGlkOiBncm91cFJlZi50b1N0cmluZygpLAogICAgICBuYW1lOiBudWxsLAogICAgICBpbnRlbnQ6IG51bGwsCiAgICAgIHVzYWdlOiB7CiAgICAgICAgcHJpbnQ6IG51bGwsCiAgICAgICAgdmlldzogbnVsbAogICAgICB9LAogICAgICByYkdyb3VwczogW10KICAgIH07CiAgICBjb25zdCBuYW1lID0gZ3JvdXAuZ2V0KCJOYW1lIik7CiAgICBpZiAodHlwZW9mIG5hbWUgPT09ICJzdHJpbmciKSB7CiAgICAgIG9iai5uYW1lID0gc3RyaW5nVG9QREZTdHJpbmcobmFtZSk7CiAgICB9CiAgICBsZXQgaW50ZW50ID0gZ3JvdXAuZ2V0QXJyYXkoIkludGVudCIpOwogICAgaWYgKCFBcnJheS5pc0FycmF5KGludGVudCkpIHsKICAgICAgaW50ZW50ID0gW2ludGVudF07CiAgICB9CiAgICBpZiAoaW50ZW50LmV2ZXJ5KGkgPT4gaSBpbnN0YW5jZW9mIE5hbWUpKSB7CiAgICAgIG9iai5pbnRlbnQgPSBpbnRlbnQubWFwKGkgPT4gaS5uYW1lKTsKICAgIH0KICAgIGNvbnN0IHVzYWdlID0gZ3JvdXAuZ2V0KCJVc2FnZSIpOwogICAgaWYgKCEodXNhZ2UgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm4gb2JqOwogICAgfQogICAgY29uc3QgdXNhZ2VPYmogPSBvYmoudXNhZ2U7CiAgICBjb25zdCBwcmludCA9IHVzYWdlLmdldCgiUHJpbnQiKTsKICAgIGlmIChwcmludCBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgY29uc3QgcHJpbnRTdGF0ZSA9IHByaW50LmdldCgiUHJpbnRTdGF0ZSIpOwogICAgICBpZiAocHJpbnRTdGF0ZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICBzd2l0Y2ggKHByaW50U3RhdGUubmFtZSkgewogICAgICAgICAgY2FzZSAiT04iOgogICAgICAgICAgY2FzZSAiT0ZGIjoKICAgICAgICAgICAgdXNhZ2VPYmoucHJpbnQgPSB7CiAgICAgICAgICAgICAgcHJpbnRTdGF0ZTogcHJpbnRTdGF0ZS5uYW1lCiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBjb25zdCB2aWV3ID0gdXNhZ2UuZ2V0KCJWaWV3Iik7CiAgICBpZiAodmlldyBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgY29uc3Qgdmlld1N0YXRlID0gdmlldy5nZXQoIlZpZXdTdGF0ZSIpOwogICAgICBpZiAodmlld1N0YXRlIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgIHN3aXRjaCAodmlld1N0YXRlLm5hbWUpIHsKICAgICAgICAgIGNhc2UgIk9OIjoKICAgICAgICAgIGNhc2UgIk9GRiI6CiAgICAgICAgICAgIHVzYWdlT2JqLnZpZXcgPSB7CiAgICAgICAgICAgICAgdmlld1N0YXRlOiB2aWV3U3RhdGUubmFtZQogICAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIG9iajsKICB9CiAgI3JlYWRPcHRpb25hbENvbnRlbnRDb25maWcoY29uZmlnLCBncm91cFJlZkNhY2hlKSB7CiAgICBmdW5jdGlvbiBwYXJzZU9uT2ZmKHJlZnMpIHsKICAgICAgY29uc3Qgb25QYXJzZWQgPSBbXTsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVmcykpIHsKICAgICAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIHJlZnMpIHsKICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFJlZiAmJiBncm91cFJlZkNhY2hlLmhhcyh2YWx1ZSkpIHsKICAgICAgICAgICAgb25QYXJzZWQucHVzaCh2YWx1ZS50b1N0cmluZygpKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG9uUGFyc2VkOwogICAgfQogICAgZnVuY3Rpb24gcGFyc2VPcmRlcihyZWZzLCBuZXN0ZWRMZXZlbHMgPSAwKSB7CiAgICAgIGlmICghQXJyYXkuaXNBcnJheShyZWZzKSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IG9yZGVyID0gW107CiAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgcmVmcykgewogICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFJlZiAmJiBncm91cFJlZkNhY2hlLmhhcyh2YWx1ZSkpIHsKICAgICAgICAgIHBhcnNlZE9yZGVyUmVmcy5wdXQodmFsdWUpOwogICAgICAgICAgb3JkZXIucHVzaCh2YWx1ZS50b1N0cmluZygpKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBuZXN0ZWRPcmRlciA9IHBhcnNlTmVzdGVkT3JkZXIodmFsdWUsIG5lc3RlZExldmVscyk7CiAgICAgICAgaWYgKG5lc3RlZE9yZGVyKSB7CiAgICAgICAgICBvcmRlci5wdXNoKG5lc3RlZE9yZGVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKG5lc3RlZExldmVscyA+IDApIHsKICAgICAgICByZXR1cm4gb3JkZXI7CiAgICAgIH0KICAgICAgY29uc3QgaGlkZGVuR3JvdXBzID0gW107CiAgICAgIGZvciAoY29uc3QgW2dyb3VwUmVmXSBvZiBncm91cFJlZkNhY2hlLml0ZW1zKCkpIHsKICAgICAgICBpZiAocGFyc2VkT3JkZXJSZWZzLmhhcyhncm91cFJlZikpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBoaWRkZW5Hcm91cHMucHVzaChncm91cFJlZi50b1N0cmluZygpKTsKICAgICAgfQogICAgICBpZiAoaGlkZGVuR3JvdXBzLmxlbmd0aCkgewogICAgICAgIG9yZGVyLnB1c2goewogICAgICAgICAgbmFtZTogbnVsbCwKICAgICAgICAgIG9yZGVyOiBoaWRkZW5Hcm91cHMKICAgICAgICB9KTsKICAgICAgfQogICAgICByZXR1cm4gb3JkZXI7CiAgICB9CiAgICBmdW5jdGlvbiBwYXJzZU5lc3RlZE9yZGVyKHJlZiwgbmVzdGVkTGV2ZWxzKSB7CiAgICAgIGlmICgrK25lc3RlZExldmVscyA+IE1BWF9ORVNURURfTEVWRUxTKSB7CiAgICAgICAgd2FybigicGFyc2VOZXN0ZWRPcmRlciAtIHJlYWNoZWQgTUFYX05FU1RFRF9MRVZFTFMuIik7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgY29uc3QgdmFsdWUgPSB4cmVmLmZldGNoSWZSZWYocmVmKTsKICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IG5lc3RlZE5hbWUgPSB4cmVmLmZldGNoSWZSZWYodmFsdWVbMF0pOwogICAgICBpZiAodHlwZW9mIG5lc3RlZE5hbWUgIT09ICJzdHJpbmciKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgY29uc3QgbmVzdGVkT3JkZXIgPSBwYXJzZU9yZGVyKHZhbHVlLnNsaWNlKDEpLCBuZXN0ZWRMZXZlbHMpOwogICAgICBpZiAoIW5lc3RlZE9yZGVyPy5sZW5ndGgpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICByZXR1cm4gewogICAgICAgIG5hbWU6IHN0cmluZ1RvUERGU3RyaW5nKG5lc3RlZE5hbWUpLAogICAgICAgIG9yZGVyOiBuZXN0ZWRPcmRlcgogICAgICB9OwogICAgfQogICAgZnVuY3Rpb24gcGFyc2VSQkdyb3VwcyhyYkdyb3VwcykgewogICAgICBpZiAoIUFycmF5LmlzQXJyYXkocmJHcm91cHMpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgcmJHcm91cHMpIHsKICAgICAgICBjb25zdCByYkdyb3VwID0geHJlZi5mZXRjaElmUmVmKHZhbHVlKTsKICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkocmJHcm91cCkgfHwgIXJiR3JvdXAubGVuZ3RoKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcGFyc2VkUmJHcm91cCA9IG5ldyBTZXQoKTsKICAgICAgICBmb3IgKGNvbnN0IHJlZiBvZiByYkdyb3VwKSB7CiAgICAgICAgICBpZiAocmVmIGluc3RhbmNlb2YgUmVmICYmIGdyb3VwUmVmQ2FjaGUuaGFzKHJlZikgJiYgIXBhcnNlZFJiR3JvdXAuaGFzKHJlZi50b1N0cmluZygpKSkgewogICAgICAgICAgICBwYXJzZWRSYkdyb3VwLmFkZChyZWYudG9TdHJpbmcoKSk7CiAgICAgICAgICAgIGdyb3VwUmVmQ2FjaGUuZ2V0KHJlZikucmJHcm91cHMucHVzaChwYXJzZWRSYkdyb3VwKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHhyZWYgPSB0aGlzLnhyZWYsCiAgICAgIHBhcnNlZE9yZGVyUmVmcyA9IG5ldyBSZWZTZXQoKSwKICAgICAgTUFYX05FU1RFRF9MRVZFTFMgPSAxMDsKICAgIHBhcnNlUkJHcm91cHMoY29uZmlnLmdldCgiUkJHcm91cHMiKSk7CiAgICByZXR1cm4gewogICAgICBuYW1lOiB0eXBlb2YgY29uZmlnLmdldCgiTmFtZSIpID09PSAic3RyaW5nIiA/IHN0cmluZ1RvUERGU3RyaW5nKGNvbmZpZy5nZXQoIk5hbWUiKSkgOiBudWxsLAogICAgICBjcmVhdG9yOiB0eXBlb2YgY29uZmlnLmdldCgiQ3JlYXRvciIpID09PSAic3RyaW5nIiA/IHN0cmluZ1RvUERGU3RyaW5nKGNvbmZpZy5nZXQoIkNyZWF0b3IiKSkgOiBudWxsLAogICAgICBiYXNlU3RhdGU6IGNvbmZpZy5nZXQoIkJhc2VTdGF0ZSIpIGluc3RhbmNlb2YgTmFtZSA/IGNvbmZpZy5nZXQoIkJhc2VTdGF0ZSIpLm5hbWUgOiBudWxsLAogICAgICBvbjogcGFyc2VPbk9mZihjb25maWcuZ2V0KCJPTiIpKSwKICAgICAgb2ZmOiBwYXJzZU9uT2ZmKGNvbmZpZy5nZXQoIk9GRiIpKSwKICAgICAgb3JkZXI6IHBhcnNlT3JkZXIoY29uZmlnLmdldCgiT3JkZXIiKSksCiAgICAgIGdyb3VwczogWy4uLmdyb3VwUmVmQ2FjaGVdCiAgICB9OwogIH0KICBzZXRBY3R1YWxOdW1QYWdlcyhudW0gPSBudWxsKSB7CiAgICB0aGlzLiNhY3R1YWxOdW1QYWdlcyA9IG51bTsKICB9CiAgZ2V0IGhhc0FjdHVhbE51bVBhZ2VzKCkgewogICAgcmV0dXJuIHRoaXMuI2FjdHVhbE51bVBhZ2VzICE9PSBudWxsOwogIH0KICBnZXQgX3BhZ2VzQ291bnQoKSB7CiAgICBjb25zdCBvYmogPSB0aGlzLnRvcGxldmVsUGFnZXNEaWN0LmdldCgiQ291bnQiKTsKICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihvYmopKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiUGFnZSBjb3VudCBpbiB0b3AtbGV2ZWwgcGFnZXMgZGljdGlvbmFyeSBpcyBub3QgYW4gaW50ZWdlci4iKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgIl9wYWdlc0NvdW50Iiwgb2JqKTsKICB9CiAgZ2V0IG51bVBhZ2VzKCkgewogICAgcmV0dXJuIHRoaXMuI2FjdHVhbE51bVBhZ2VzID8/IHRoaXMuX3BhZ2VzQ291bnQ7CiAgfQogIGdldCBkZXN0aW5hdGlvbnMoKSB7CiAgICBjb25zdCByYXdEZXN0cyA9IHRoaXMuI3JlYWREZXN0cygpLAogICAgICBkZXN0cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBmb3IgKGNvbnN0IG9iaiBvZiByYXdEZXN0cykgewogICAgICBpZiAob2JqIGluc3RhbmNlb2YgTmFtZVRyZWUpIHsKICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBvYmouZ2V0QWxsKCkpIHsKICAgICAgICAgIGNvbnN0IGRlc3QgPSBmZXRjaERlc3QodmFsdWUpOwogICAgICAgICAgaWYgKGRlc3QpIHsKICAgICAgICAgICAgZGVzdHNbc3RyaW5nVG9QREZTdHJpbmcoa2V5LCB0cnVlKV0gPSBkZXN0OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2Ygb2JqKSB7CiAgICAgICAgICBjb25zdCBkZXN0ID0gZmV0Y2hEZXN0KHZhbHVlKTsKICAgICAgICAgIGlmIChkZXN0KSB7CiAgICAgICAgICAgIGRlc3RzW3N0cmluZ1RvUERGU3RyaW5nKGtleSwgdHJ1ZSldIHx8PSBkZXN0OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiZGVzdGluYXRpb25zIiwgZGVzdHMpOwogIH0KICBnZXREZXN0aW5hdGlvbihpZCkgewogICAgaWYgKHRoaXMuaGFzT3duUHJvcGVydHkoImRlc3RpbmF0aW9ucyIpKSB7CiAgICAgIHJldHVybiB0aGlzLmRlc3RpbmF0aW9uc1tpZF0gPz8gbnVsbDsKICAgIH0KICAgIGNvbnN0IHJhd0Rlc3RzID0gdGhpcy4jcmVhZERlc3RzKCk7CiAgICBmb3IgKGNvbnN0IG9iaiBvZiByYXdEZXN0cykgewogICAgICBpZiAob2JqIGluc3RhbmNlb2YgTmFtZVRyZWUgfHwgb2JqIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIGNvbnN0IGRlc3QgPSBmZXRjaERlc3Qob2JqLmdldChpZCkpOwogICAgICAgIGlmIChkZXN0KSB7CiAgICAgICAgICByZXR1cm4gZGVzdDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChyYXdEZXN0cy5sZW5ndGgpIHsKICAgICAgY29uc3QgZGVzdCA9IHRoaXMuZGVzdGluYXRpb25zW2lkXTsKICAgICAgaWYgKGRlc3QpIHsKICAgICAgICByZXR1cm4gZGVzdDsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogICNyZWFkRGVzdHMoKSB7CiAgICBjb25zdCBvYmogPSB0aGlzLiNjYXREaWN0LmdldCgiTmFtZXMiKTsKICAgIGNvbnN0IHJhd0Rlc3RzID0gW107CiAgICBpZiAob2JqPy5oYXMoIkRlc3RzIikpIHsKICAgICAgcmF3RGVzdHMucHVzaChuZXcgTmFtZVRyZWUob2JqLmdldFJhdygiRGVzdHMiKSwgdGhpcy54cmVmKSk7CiAgICB9CiAgICBpZiAodGhpcy4jY2F0RGljdC5oYXMoIkRlc3RzIikpIHsKICAgICAgcmF3RGVzdHMucHVzaCh0aGlzLiNjYXREaWN0LmdldCgiRGVzdHMiKSk7CiAgICB9CiAgICByZXR1cm4gcmF3RGVzdHM7CiAgfQogIGdldCByYXdQYWdlTGFiZWxzKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy4jY2F0RGljdC5nZXRSYXcoIlBhZ2VMYWJlbHMiKTsKICAgIGlmICghb2JqKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgbnVtYmVyVHJlZSA9IG5ldyBOdW1iZXJUcmVlKG9iaiwgdGhpcy54cmVmKTsKICAgIHJldHVybiBudW1iZXJUcmVlLmdldEFsbCgpOwogIH0KICBnZXQgcGFnZUxhYmVscygpIHsKICAgIGxldCBvYmogPSBudWxsOwogICAgdHJ5IHsKICAgICAgb2JqID0gdGhpcy4jcmVhZFBhZ2VMYWJlbHMoKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgd2FybigiVW5hYmxlIHRvIHJlYWQgcGFnZSBsYWJlbHMuIik7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJwYWdlTGFiZWxzIiwgb2JqKTsKICB9CiAgI3JlYWRQYWdlTGFiZWxzKCkgewogICAgY29uc3QgbnVtcyA9IHRoaXMucmF3UGFnZUxhYmVsczsKICAgIGlmICghbnVtcykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHBhZ2VMYWJlbHMgPSBuZXcgQXJyYXkodGhpcy5udW1QYWdlcyk7CiAgICBsZXQgc3R5bGUgPSBudWxsLAogICAgICBwcmVmaXggPSAiIjsKICAgIGxldCBjdXJyZW50TGFiZWwgPSAiIiwKICAgICAgY3VycmVudEluZGV4ID0gMTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHRoaXMubnVtUGFnZXM7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IGxhYmVsRGljdCA9IG51bXMuZ2V0KGkpOwogICAgICBpZiAobGFiZWxEaWN0ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBpZiAoIShsYWJlbERpY3QgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJQYWdlTGFiZWwgaXMgbm90IGEgZGljdGlvbmFyeS4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKGxhYmVsRGljdC5oYXMoIlR5cGUiKSAmJiAhaXNOYW1lKGxhYmVsRGljdC5nZXQoIlR5cGUiKSwgIlBhZ2VMYWJlbCIpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgdHlwZSBpbiBQYWdlTGFiZWwgZGljdGlvbmFyeS4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKGxhYmVsRGljdC5oYXMoIlMiKSkgewogICAgICAgICAgY29uc3QgcyA9IGxhYmVsRGljdC5nZXQoIlMiKTsKICAgICAgICAgIGlmICghKHMgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgc3R5bGUgaW4gUGFnZUxhYmVsIGRpY3Rpb25hcnkuIik7CiAgICAgICAgICB9CiAgICAgICAgICBzdHlsZSA9IHMubmFtZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3R5bGUgPSBudWxsOwogICAgICAgIH0KICAgICAgICBpZiAobGFiZWxEaWN0LmhhcygiUCIpKSB7CiAgICAgICAgICBjb25zdCBwID0gbGFiZWxEaWN0LmdldCgiUCIpOwogICAgICAgICAgaWYgKHR5cGVvZiBwICE9PSAic3RyaW5nIikgewogICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgcHJlZml4IGluIFBhZ2VMYWJlbCBkaWN0aW9uYXJ5LiIpOwogICAgICAgICAgfQogICAgICAgICAgcHJlZml4ID0gc3RyaW5nVG9QREZTdHJpbmcocCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHByZWZpeCA9ICIiOwogICAgICAgIH0KICAgICAgICBpZiAobGFiZWxEaWN0LmhhcygiU3QiKSkgewogICAgICAgICAgY29uc3Qgc3QgPSBsYWJlbERpY3QuZ2V0KCJTdCIpOwogICAgICAgICAgaWYgKCEoTnVtYmVyLmlzSW50ZWdlcihzdCkgJiYgc3QgPj0gMSkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIHN0YXJ0IGluIFBhZ2VMYWJlbCBkaWN0aW9uYXJ5LiIpOwogICAgICAgICAgfQogICAgICAgICAgY3VycmVudEluZGV4ID0gc3Q7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGN1cnJlbnRJbmRleCA9IDE7CiAgICAgICAgfQogICAgICB9CiAgICAgIHN3aXRjaCAoc3R5bGUpIHsKICAgICAgICBjYXNlICJEIjoKICAgICAgICAgIGN1cnJlbnRMYWJlbCA9IGN1cnJlbnRJbmRleDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlIiOgogICAgICAgIGNhc2UgInIiOgogICAgICAgICAgY3VycmVudExhYmVsID0gdG9Sb21hbk51bWVyYWxzKGN1cnJlbnRJbmRleCwgc3R5bGUgPT09ICJyIik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJBIjoKICAgICAgICBjYXNlICJhIjoKICAgICAgICAgIGNvbnN0IExJTUlUID0gMjY7CiAgICAgICAgICBjb25zdCBBX1VQUEVSX0NBU0UgPSAweDQxLAogICAgICAgICAgICBBX0xPV0VSX0NBU0UgPSAweDYxOwogICAgICAgICAgY29uc3QgYmFzZUNoYXJDb2RlID0gc3R5bGUgPT09ICJhIiA/IEFfTE9XRVJfQ0FTRSA6IEFfVVBQRVJfQ0FTRTsKICAgICAgICAgIGNvbnN0IGxldHRlckluZGV4ID0gY3VycmVudEluZGV4IC0gMTsKICAgICAgICAgIGNvbnN0IGNoYXJhY3RlciA9IFN0cmluZy5mcm9tQ2hhckNvZGUoYmFzZUNoYXJDb2RlICsgbGV0dGVySW5kZXggJSBMSU1JVCk7CiAgICAgICAgICBjdXJyZW50TGFiZWwgPSBjaGFyYWN0ZXIucmVwZWF0KE1hdGguZmxvb3IobGV0dGVySW5kZXggLyBMSU1JVCkgKyAxKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBpZiAoc3R5bGUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIHN0eWxlICIke3N0eWxlfSIgaW4gUGFnZUxhYmVsIGRpY3Rpb25hcnkuYCk7CiAgICAgICAgICB9CiAgICAgICAgICBjdXJyZW50TGFiZWwgPSAiIjsKICAgICAgfQogICAgICBwYWdlTGFiZWxzW2ldID0gcHJlZml4ICsgY3VycmVudExhYmVsOwogICAgICBjdXJyZW50SW5kZXgrKzsKICAgIH0KICAgIHJldHVybiBwYWdlTGFiZWxzOwogIH0KICBnZXQgcGFnZUxheW91dCgpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuI2NhdERpY3QuZ2V0KCJQYWdlTGF5b3V0Iik7CiAgICBsZXQgcGFnZUxheW91dCA9ICIiOwogICAgaWYgKG9iaiBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgc3dpdGNoIChvYmoubmFtZSkgewogICAgICAgIGNhc2UgIlNpbmdsZVBhZ2UiOgogICAgICAgIGNhc2UgIk9uZUNvbHVtbiI6CiAgICAgICAgY2FzZSAiVHdvQ29sdW1uTGVmdCI6CiAgICAgICAgY2FzZSAiVHdvQ29sdW1uUmlnaHQiOgogICAgICAgIGNhc2UgIlR3b1BhZ2VMZWZ0IjoKICAgICAgICBjYXNlICJUd29QYWdlUmlnaHQiOgogICAgICAgICAgcGFnZUxheW91dCA9IG9iai5uYW1lOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJwYWdlTGF5b3V0IiwgcGFnZUxheW91dCk7CiAgfQogIGdldCBwYWdlTW9kZSgpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuI2NhdERpY3QuZ2V0KCJQYWdlTW9kZSIpOwogICAgbGV0IHBhZ2VNb2RlID0gIlVzZU5vbmUiOwogICAgaWYgKG9iaiBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgc3dpdGNoIChvYmoubmFtZSkgewogICAgICAgIGNhc2UgIlVzZU5vbmUiOgogICAgICAgIGNhc2UgIlVzZU91dGxpbmVzIjoKICAgICAgICBjYXNlICJVc2VUaHVtYnMiOgogICAgICAgIGNhc2UgIkZ1bGxTY3JlZW4iOgogICAgICAgIGNhc2UgIlVzZU9DIjoKICAgICAgICBjYXNlICJVc2VBdHRhY2htZW50cyI6CiAgICAgICAgICBwYWdlTW9kZSA9IG9iai5uYW1lOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJwYWdlTW9kZSIsIHBhZ2VNb2RlKTsKICB9CiAgZ2V0IHZpZXdlclByZWZlcmVuY2VzKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy4jY2F0RGljdC5nZXQoIlZpZXdlclByZWZlcmVuY2VzIik7CiAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm4gc2hhZG93KHRoaXMsICJ2aWV3ZXJQcmVmZXJlbmNlcyIsIG51bGwpOwogICAgfQogICAgbGV0IHByZWZzID0gbnVsbDsKICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIG9iaikgewogICAgICBsZXQgcHJlZlZhbHVlOwogICAgICBzd2l0Y2ggKGtleSkgewogICAgICAgIGNhc2UgIkhpZGVUb29sYmFyIjoKICAgICAgICBjYXNlICJIaWRlTWVudWJhciI6CiAgICAgICAgY2FzZSAiSGlkZVdpbmRvd1VJIjoKICAgICAgICBjYXNlICJGaXRXaW5kb3ciOgogICAgICAgIGNhc2UgIkNlbnRlcldpbmRvdyI6CiAgICAgICAgY2FzZSAiRGlzcGxheURvY1RpdGxlIjoKICAgICAgICBjYXNlICJQaWNrVHJheUJ5UERGU2l6ZSI6CiAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAiYm9vbGVhbiIpIHsKICAgICAgICAgICAgcHJlZlZhbHVlID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJOb25GdWxsU2NyZWVuUGFnZU1vZGUiOgogICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgICBzd2l0Y2ggKHZhbHVlLm5hbWUpIHsKICAgICAgICAgICAgICBjYXNlICJVc2VOb25lIjoKICAgICAgICAgICAgICBjYXNlICJVc2VPdXRsaW5lcyI6CiAgICAgICAgICAgICAgY2FzZSAiVXNlVGh1bWJzIjoKICAgICAgICAgICAgICBjYXNlICJVc2VPQyI6CiAgICAgICAgICAgICAgICBwcmVmVmFsdWUgPSB2YWx1ZS5uYW1lOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHByZWZWYWx1ZSA9ICJVc2VOb25lIjsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiRGlyZWN0aW9uIjoKICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgICAgc3dpdGNoICh2YWx1ZS5uYW1lKSB7CiAgICAgICAgICAgICAgY2FzZSAiTDJSIjoKICAgICAgICAgICAgICBjYXNlICJSMkwiOgogICAgICAgICAgICAgICAgcHJlZlZhbHVlID0gdmFsdWUubmFtZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBwcmVmVmFsdWUgPSAiTDJSIjsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiVmlld0FyZWEiOgogICAgICAgIGNhc2UgIlZpZXdDbGlwIjoKICAgICAgICBjYXNlICJQcmludEFyZWEiOgogICAgICAgIGNhc2UgIlByaW50Q2xpcCI6CiAgICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgIHN3aXRjaCAodmFsdWUubmFtZSkgewogICAgICAgICAgICAgIGNhc2UgIk1lZGlhQm94IjoKICAgICAgICAgICAgICBjYXNlICJDcm9wQm94IjoKICAgICAgICAgICAgICBjYXNlICJCbGVlZEJveCI6CiAgICAgICAgICAgICAgY2FzZSAiVHJpbUJveCI6CiAgICAgICAgICAgICAgY2FzZSAiQXJ0Qm94IjoKICAgICAgICAgICAgICAgIHByZWZWYWx1ZSA9IHZhbHVlLm5hbWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgcHJlZlZhbHVlID0gIkNyb3BCb3giOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJQcmludFNjYWxpbmciOgogICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgICBzd2l0Y2ggKHZhbHVlLm5hbWUpIHsKICAgICAgICAgICAgICBjYXNlICJOb25lIjoKICAgICAgICAgICAgICBjYXNlICJBcHBEZWZhdWx0IjoKICAgICAgICAgICAgICAgIHByZWZWYWx1ZSA9IHZhbHVlLm5hbWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgcHJlZlZhbHVlID0gIkFwcERlZmF1bHQiOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJEdXBsZXgiOgogICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgICBzd2l0Y2ggKHZhbHVlLm5hbWUpIHsKICAgICAgICAgICAgICBjYXNlICJTaW1wbGV4IjoKICAgICAgICAgICAgICBjYXNlICJEdXBsZXhGbGlwU2hvcnRFZGdlIjoKICAgICAgICAgICAgICBjYXNlICJEdXBsZXhGbGlwTG9uZ0VkZ2UiOgogICAgICAgICAgICAgICAgcHJlZlZhbHVlID0gdmFsdWUubmFtZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBwcmVmVmFsdWUgPSAiTm9uZSI7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlByaW50UGFnZVJhbmdlIjoKICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggJSAyID09PSAwKSB7CiAgICAgICAgICAgIGNvbnN0IGlzVmFsaWQgPSB2YWx1ZS5ldmVyeSgocGFnZSwgaSwgYXJyKSA9PiBOdW1iZXIuaXNJbnRlZ2VyKHBhZ2UpICYmIHBhZ2UgPiAwICYmIChpID09PSAwIHx8IHBhZ2UgPj0gYXJyW2kgLSAxXSkgJiYgcGFnZSA8PSB0aGlzLm51bVBhZ2VzKTsKICAgICAgICAgICAgaWYgKGlzVmFsaWQpIHsKICAgICAgICAgICAgICBwcmVmVmFsdWUgPSB2YWx1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiTnVtQ29waWVzIjoKICAgICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSAmJiB2YWx1ZSA+IDApIHsKICAgICAgICAgICAgcHJlZlZhbHVlID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgd2FybihgSWdub3Jpbmcgbm9uLXN0YW5kYXJkIGtleSBpbiBWaWV3ZXJQcmVmZXJlbmNlczogJHtrZXl9LmApOwogICAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKHByZWZWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgd2FybihgQmFkIHZhbHVlLCBmb3Iga2V5ICIke2tleX0iLCBpbiBWaWV3ZXJQcmVmZXJlbmNlczogJHt2YWx1ZX0uYCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgcHJlZnMgPz89IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHByZWZzW2tleV0gPSBwcmVmVmFsdWU7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJ2aWV3ZXJQcmVmZXJlbmNlcyIsIHByZWZzKTsKICB9CiAgZ2V0IG9wZW5BY3Rpb24oKSB7CiAgICBjb25zdCBvYmogPSB0aGlzLiNjYXREaWN0LmdldCgiT3BlbkFjdGlvbiIpOwogICAgY29uc3Qgb3BlbkFjdGlvbiA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgRGljdCkgewogICAgICBjb25zdCBkZXN0RGljdCA9IG5ldyBEaWN0KHRoaXMueHJlZik7CiAgICAgIGRlc3REaWN0LnNldCgiQSIsIG9iaik7CiAgICAgIGNvbnN0IHJlc3VsdE9iaiA9IHsKICAgICAgICB1cmw6IG51bGwsCiAgICAgICAgZGVzdDogbnVsbCwKICAgICAgICBhY3Rpb246IG51bGwKICAgICAgfTsKICAgICAgQ2F0YWxvZy5wYXJzZURlc3REaWN0aW9uYXJ5KHsKICAgICAgICBkZXN0RGljdCwKICAgICAgICByZXN1bHRPYmoKICAgICAgfSk7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KHJlc3VsdE9iai5kZXN0KSkgewogICAgICAgIG9wZW5BY3Rpb24uZGVzdCA9IHJlc3VsdE9iai5kZXN0OwogICAgICB9IGVsc2UgaWYgKHJlc3VsdE9iai5hY3Rpb24pIHsKICAgICAgICBvcGVuQWN0aW9uLmFjdGlvbiA9IHJlc3VsdE9iai5hY3Rpb247CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoaXNWYWxpZEV4cGxpY2l0RGVzdChvYmopKSB7CiAgICAgIG9wZW5BY3Rpb24uZGVzdCA9IG9iajsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgIm9wZW5BY3Rpb24iLCBvYmplY3RTaXplKG9wZW5BY3Rpb24pID4gMCA/IG9wZW5BY3Rpb24gOiBudWxsKTsKICB9CiAgZ2V0IGF0dGFjaG1lbnRzKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy4jY2F0RGljdC5nZXQoIk5hbWVzIik7CiAgICBsZXQgYXR0YWNobWVudHMgPSBudWxsOwogICAgaWYgKG9iaiBpbnN0YW5jZW9mIERpY3QgJiYgb2JqLmhhcygiRW1iZWRkZWRGaWxlcyIpKSB7CiAgICAgIGNvbnN0IG5hbWVUcmVlID0gbmV3IE5hbWVUcmVlKG9iai5nZXRSYXcoIkVtYmVkZGVkRmlsZXMiKSwgdGhpcy54cmVmKTsKICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgbmFtZVRyZWUuZ2V0QWxsKCkpIHsKICAgICAgICBjb25zdCBmcyA9IG5ldyBGaWxlU3BlYyh2YWx1ZSk7CiAgICAgICAgYXR0YWNobWVudHMgPz89IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgYXR0YWNobWVudHNbc3RyaW5nVG9QREZTdHJpbmcoa2V5LCB0cnVlKV0gPSBmcy5zZXJpYWxpemFibGU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImF0dGFjaG1lbnRzIiwgYXR0YWNobWVudHMpOwogIH0KICBnZXQgeGZhSW1hZ2VzKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy4jY2F0RGljdC5nZXQoIk5hbWVzIik7CiAgICBsZXQgeGZhSW1hZ2VzID0gbnVsbDsKICAgIGlmIChvYmogaW5zdGFuY2VvZiBEaWN0ICYmIG9iai5oYXMoIlhGQUltYWdlcyIpKSB7CiAgICAgIGNvbnN0IG5hbWVUcmVlID0gbmV3IE5hbWVUcmVlKG9iai5nZXRSYXcoIlhGQUltYWdlcyIpLCB0aGlzLnhyZWYpOwogICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBuYW1lVHJlZS5nZXRBbGwoKSkgewogICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgICAgIHhmYUltYWdlcyA/Pz0gbmV3IE1hcCgpOwogICAgICAgICAgeGZhSW1hZ2VzLnNldChzdHJpbmdUb1BERlN0cmluZyhrZXksIHRydWUpLCB2YWx1ZS5nZXRCeXRlcygpKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInhmYUltYWdlcyIsIHhmYUltYWdlcyk7CiAgfQogICNjb2xsZWN0SmF2YVNjcmlwdCgpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuI2NhdERpY3QuZ2V0KCJOYW1lcyIpOwogICAgbGV0IGphdmFTY3JpcHQgPSBudWxsOwogICAgZnVuY3Rpb24gYXBwZW5kSWZKYXZhU2NyaXB0RGljdChuYW1lLCBqc0RpY3QpIHsKICAgICAgaWYgKCEoanNEaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKCFpc05hbWUoanNEaWN0LmdldCgiUyIpLCAiSmF2YVNjcmlwdCIpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGxldCBqcyA9IGpzRGljdC5nZXQoIkpTIik7CiAgICAgIGlmIChqcyBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgICBqcyA9IGpzLmdldFN0cmluZygpOwogICAgICB9IGVsc2UgaWYgKHR5cGVvZiBqcyAhPT0gInN0cmluZyIpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAganMgPSBzdHJpbmdUb1BERlN0cmluZyhqcywgdHJ1ZSkucmVwbGFjZUFsbCgiXHgwMCIsICIiKTsKICAgICAgaWYgKGpzKSB7CiAgICAgICAgKGphdmFTY3JpcHQgfHw9IG5ldyBNYXAoKSkuc2V0KG5hbWUsIGpzKTsKICAgICAgfQogICAgfQogICAgaWYgKG9iaiBpbnN0YW5jZW9mIERpY3QgJiYgb2JqLmhhcygiSmF2YVNjcmlwdCIpKSB7CiAgICAgIGNvbnN0IG5hbWVUcmVlID0gbmV3IE5hbWVUcmVlKG9iai5nZXRSYXcoIkphdmFTY3JpcHQiKSwgdGhpcy54cmVmKTsKICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgbmFtZVRyZWUuZ2V0QWxsKCkpIHsKICAgICAgICBhcHBlbmRJZkphdmFTY3JpcHREaWN0KHN0cmluZ1RvUERGU3RyaW5nKGtleSwgdHJ1ZSksIHZhbHVlKTsKICAgICAgfQogICAgfQogICAgY29uc3Qgb3BlbkFjdGlvbiA9IHRoaXMuI2NhdERpY3QuZ2V0KCJPcGVuQWN0aW9uIik7CiAgICBpZiAob3BlbkFjdGlvbikgewogICAgICBhcHBlbmRJZkphdmFTY3JpcHREaWN0KCJPcGVuQWN0aW9uIiwgb3BlbkFjdGlvbik7CiAgICB9CiAgICByZXR1cm4gamF2YVNjcmlwdDsKICB9CiAgZ2V0IGpzQWN0aW9ucygpIHsKICAgIGNvbnN0IGphdmFTY3JpcHQgPSB0aGlzLiNjb2xsZWN0SmF2YVNjcmlwdCgpOwogICAgbGV0IGFjdGlvbnMgPSBjb2xsZWN0QWN0aW9ucyh0aGlzLnhyZWYsIHRoaXMuI2NhdERpY3QsIERvY3VtZW50QWN0aW9uRXZlbnRUeXBlKTsKICAgIGlmIChqYXZhU2NyaXB0KSB7CiAgICAgIGFjdGlvbnMgfHw9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiBqYXZhU2NyaXB0KSB7CiAgICAgICAgaWYgKGtleSBpbiBhY3Rpb25zKSB7CiAgICAgICAgICBhY3Rpb25zW2tleV0ucHVzaCh2YWwpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBhY3Rpb25zW2tleV0gPSBbdmFsXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImpzQWN0aW9ucyIsIGFjdGlvbnMpOwogIH0KICBhc3luYyBjbGVhbnVwKG1hbnVhbGx5VHJpZ2dlcmVkID0gZmFsc2UpIHsKICAgIGNsZWFyR2xvYmFsQ2FjaGVzKCk7CiAgICB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZS5jbGVhcigpOwogICAgdGhpcy5nbG9iYWxJbWFnZUNhY2hlLmNsZWFyKG1hbnVhbGx5VHJpZ2dlcmVkKTsKICAgIHRoaXMucGFnZUtpZHNDb3VudENhY2hlLmNsZWFyKCk7CiAgICB0aGlzLnBhZ2VJbmRleENhY2hlLmNsZWFyKCk7CiAgICB0aGlzLnBhZ2VEaWN0Q2FjaGUuY2xlYXIoKTsKICAgIHRoaXMubm9uQmxlbmRNb2Rlc1NldC5jbGVhcigpOwogICAgZm9yIChjb25zdCB7CiAgICAgIGRpY3QKICAgIH0gb2YgYXdhaXQgUHJvbWlzZS5hbGwodGhpcy5mb250Q2FjaGUpKSB7CiAgICAgIGRlbGV0ZSBkaWN0LmNhY2hlS2V5OwogICAgfQogICAgdGhpcy5mb250Q2FjaGUuY2xlYXIoKTsKICAgIHRoaXMuYnVpbHRJbkNNYXBDYWNoZS5jbGVhcigpOwogICAgdGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUuY2xlYXIoKTsKICAgIHRoaXMuc3lzdGVtRm9udENhY2hlLmNsZWFyKCk7CiAgfQogIGFzeW5jIGdldFBhZ2VEaWN0KHBhZ2VJbmRleCkgewogICAgY29uc3Qgbm9kZXNUb1Zpc2l0ID0gW3RoaXMudG9wbGV2ZWxQYWdlc0RpY3RdOwogICAgY29uc3QgdmlzaXRlZE5vZGVzID0gbmV3IFJlZlNldCgpOwogICAgY29uc3QgcGFnZXNSZWYgPSB0aGlzLiNjYXREaWN0LmdldFJhdygiUGFnZXMiKTsKICAgIGlmIChwYWdlc1JlZiBpbnN0YW5jZW9mIFJlZikgewogICAgICB2aXNpdGVkTm9kZXMucHV0KHBhZ2VzUmVmKTsKICAgIH0KICAgIGNvbnN0IHhyZWYgPSB0aGlzLnhyZWYsCiAgICAgIHBhZ2VLaWRzQ291bnRDYWNoZSA9IHRoaXMucGFnZUtpZHNDb3VudENhY2hlLAogICAgICBwYWdlSW5kZXhDYWNoZSA9IHRoaXMucGFnZUluZGV4Q2FjaGUsCiAgICAgIHBhZ2VEaWN0Q2FjaGUgPSB0aGlzLnBhZ2VEaWN0Q2FjaGU7CiAgICBsZXQgY3VycmVudFBhZ2VJbmRleCA9IDA7CiAgICB3aGlsZSAobm9kZXNUb1Zpc2l0Lmxlbmd0aCkgewogICAgICBjb25zdCBjdXJyZW50Tm9kZSA9IG5vZGVzVG9WaXNpdC5wb3AoKTsKICAgICAgaWYgKGN1cnJlbnROb2RlIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgY29uc3QgY291bnQgPSBwYWdlS2lkc0NvdW50Q2FjaGUuZ2V0KGN1cnJlbnROb2RlKTsKICAgICAgICBpZiAoY291bnQgPj0gMCAmJiBjdXJyZW50UGFnZUluZGV4ICsgY291bnQgPD0gcGFnZUluZGV4KSB7CiAgICAgICAgICBjdXJyZW50UGFnZUluZGV4ICs9IGNvdW50OwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICh2aXNpdGVkTm9kZXMuaGFzKGN1cnJlbnROb2RlKSkgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJQYWdlcyB0cmVlIGNvbnRhaW5zIGNpcmN1bGFyIHJlZmVyZW5jZS4iKTsKICAgICAgICB9CiAgICAgICAgdmlzaXRlZE5vZGVzLnB1dChjdXJyZW50Tm9kZSk7CiAgICAgICAgY29uc3Qgb2JqID0gYXdhaXQgKHBhZ2VEaWN0Q2FjaGUuZ2V0KGN1cnJlbnROb2RlKSB8fCB4cmVmLmZldGNoQXN5bmMoY3VycmVudE5vZGUpKTsKICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgICAgbGV0IHR5cGUgPSBvYmouZ2V0UmF3KCJUeXBlIik7CiAgICAgICAgICBpZiAodHlwZSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgICB0eXBlID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKHR5cGUpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGlzTmFtZSh0eXBlLCAiUGFnZSIpIHx8ICFvYmouaGFzKCJLaWRzIikpIHsKICAgICAgICAgICAgaWYgKCFwYWdlS2lkc0NvdW50Q2FjaGUuaGFzKGN1cnJlbnROb2RlKSkgewogICAgICAgICAgICAgIHBhZ2VLaWRzQ291bnRDYWNoZS5wdXQoY3VycmVudE5vZGUsIDEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICghcGFnZUluZGV4Q2FjaGUuaGFzKGN1cnJlbnROb2RlKSkgewogICAgICAgICAgICAgIHBhZ2VJbmRleENhY2hlLnB1dChjdXJyZW50Tm9kZSwgY3VycmVudFBhZ2VJbmRleCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGN1cnJlbnRQYWdlSW5kZXggPT09IHBhZ2VJbmRleCkgewogICAgICAgICAgICAgIHJldHVybiBbb2JqLCBjdXJyZW50Tm9kZV07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY3VycmVudFBhZ2VJbmRleCsrOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbm9kZXNUb1Zpc2l0LnB1c2gob2JqKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIShjdXJyZW50Tm9kZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJQYWdlIGRpY3Rpb25hcnkga2lkIHJlZmVyZW5jZSBwb2ludHMgdG8gd3JvbmcgdHlwZSBvZiBvYmplY3QuIik7CiAgICAgIH0KICAgICAgY29uc3QgewogICAgICAgIG9iaklkCiAgICAgIH0gPSBjdXJyZW50Tm9kZTsKICAgICAgbGV0IGNvdW50ID0gY3VycmVudE5vZGUuZ2V0UmF3KCJDb3VudCIpOwogICAgICBpZiAoY291bnQgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICBjb3VudCA9IGF3YWl0IHhyZWYuZmV0Y2hBc3luYyhjb3VudCk7CiAgICAgIH0KICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIoY291bnQpICYmIGNvdW50ID49IDApIHsKICAgICAgICBpZiAob2JqSWQgJiYgIXBhZ2VLaWRzQ291bnRDYWNoZS5oYXMob2JqSWQpKSB7CiAgICAgICAgICBwYWdlS2lkc0NvdW50Q2FjaGUucHV0KG9iaklkLCBjb3VudCk7CiAgICAgICAgfQogICAgICAgIGlmIChjdXJyZW50UGFnZUluZGV4ICsgY291bnQgPD0gcGFnZUluZGV4KSB7CiAgICAgICAgICBjdXJyZW50UGFnZUluZGV4ICs9IGNvdW50OwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIGxldCBraWRzID0gY3VycmVudE5vZGUuZ2V0UmF3KCJLaWRzIik7CiAgICAgIGlmIChraWRzIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAga2lkcyA9IGF3YWl0IHhyZWYuZmV0Y2hBc3luYyhraWRzKTsKICAgICAgfQogICAgICBpZiAoIUFycmF5LmlzQXJyYXkoa2lkcykpIHsKICAgICAgICBsZXQgdHlwZSA9IGN1cnJlbnROb2RlLmdldFJhdygiVHlwZSIpOwogICAgICAgIGlmICh0eXBlIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICB0eXBlID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKHR5cGUpOwogICAgICAgIH0KICAgICAgICBpZiAoaXNOYW1lKHR5cGUsICJQYWdlIikgfHwgIWN1cnJlbnROb2RlLmhhcygiS2lkcyIpKSB7CiAgICAgICAgICBpZiAoY3VycmVudFBhZ2VJbmRleCA9PT0gcGFnZUluZGV4KSB7CiAgICAgICAgICAgIHJldHVybiBbY3VycmVudE5vZGUsIG51bGxdOwogICAgICAgICAgfQogICAgICAgICAgY3VycmVudFBhZ2VJbmRleCsrOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiUGFnZSBkaWN0aW9uYXJ5IGtpZHMgb2JqZWN0IGlzIG5vdCBhbiBhcnJheS4iKTsKICAgICAgfQogICAgICBmb3IgKGxldCBsYXN0ID0ga2lkcy5sZW5ndGggLSAxOyBsYXN0ID49IDA7IGxhc3QtLSkgewogICAgICAgIGNvbnN0IGxhc3RLaWQgPSBraWRzW2xhc3RdOwogICAgICAgIG5vZGVzVG9WaXNpdC5wdXNoKGxhc3RLaWQpOwogICAgICAgIGlmIChjdXJyZW50Tm9kZSA9PT0gdGhpcy50b3BsZXZlbFBhZ2VzRGljdCAmJiBsYXN0S2lkIGluc3RhbmNlb2YgUmVmICYmICFwYWdlRGljdENhY2hlLmhhcyhsYXN0S2lkKSkgewogICAgICAgICAgcGFnZURpY3RDYWNoZS5wdXQobGFzdEtpZCwgeHJlZi5mZXRjaEFzeW5jKGxhc3RLaWQpKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHRocm93IG5ldyBFcnJvcihgUGFnZSBpbmRleCAke3BhZ2VJbmRleH0gbm90IGZvdW5kLmApOwogIH0KICBhc3luYyBnZXRBbGxQYWdlRGljdHMocmVjb3ZlcnlNb2RlID0gZmFsc2UpIHsKICAgIGNvbnN0IHsKICAgICAgaWdub3JlRXJyb3JzCiAgICB9ID0gdGhpcy5wZGZNYW5hZ2VyLmV2YWx1YXRvck9wdGlvbnM7CiAgICBjb25zdCBxdWV1ZSA9IFt7CiAgICAgIGN1cnJlbnROb2RlOiB0aGlzLnRvcGxldmVsUGFnZXNEaWN0LAogICAgICBwb3NJbktpZHM6IDAKICAgIH1dOwogICAgY29uc3QgdmlzaXRlZE5vZGVzID0gbmV3IFJlZlNldCgpOwogICAgY29uc3QgcGFnZXNSZWYgPSB0aGlzLiNjYXREaWN0LmdldFJhdygiUGFnZXMiKTsKICAgIGlmIChwYWdlc1JlZiBpbnN0YW5jZW9mIFJlZikgewogICAgICB2aXNpdGVkTm9kZXMucHV0KHBhZ2VzUmVmKTsKICAgIH0KICAgIGNvbnN0IG1hcCA9IG5ldyBNYXAoKSwKICAgICAgeHJlZiA9IHRoaXMueHJlZiwKICAgICAgcGFnZUluZGV4Q2FjaGUgPSB0aGlzLnBhZ2VJbmRleENhY2hlOwogICAgbGV0IHBhZ2VJbmRleCA9IDA7CiAgICBmdW5jdGlvbiBhZGRQYWdlRGljdChwYWdlRGljdCwgcGFnZVJlZikgewogICAgICBpZiAocGFnZVJlZiAmJiAhcGFnZUluZGV4Q2FjaGUuaGFzKHBhZ2VSZWYpKSB7CiAgICAgICAgcGFnZUluZGV4Q2FjaGUucHV0KHBhZ2VSZWYsIHBhZ2VJbmRleCk7CiAgICAgIH0KICAgICAgbWFwLnNldChwYWdlSW5kZXgrKywgW3BhZ2VEaWN0LCBwYWdlUmVmXSk7CiAgICB9CiAgICBmdW5jdGlvbiBhZGRQYWdlRXJyb3IoZXJyb3IpIHsKICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgWFJlZkVudHJ5RXhjZXB0aW9uICYmICFyZWNvdmVyeU1vZGUpIHsKICAgICAgICB0aHJvdyBlcnJvcjsKICAgICAgfQogICAgICBpZiAocmVjb3ZlcnlNb2RlICYmIGlnbm9yZUVycm9ycyAmJiBwYWdlSW5kZXggPT09IDApIHsKICAgICAgICB3YXJuKGBnZXRBbGxQYWdlRGljdHMgLSBTa2lwcGluZyBpbnZhbGlkIGZpcnN0IHBhZ2U6ICIke2Vycm9yfSIuYCk7CiAgICAgICAgZXJyb3IgPSBEaWN0LmVtcHR5OwogICAgICB9CiAgICAgIG1hcC5zZXQocGFnZUluZGV4KyssIFtlcnJvciwgbnVsbF0pOwogICAgfQogICAgd2hpbGUgKHF1ZXVlLmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgcXVldWVJdGVtID0gcXVldWUuYXQoLTEpOwogICAgICBjb25zdCB7CiAgICAgICAgY3VycmVudE5vZGUsCiAgICAgICAgcG9zSW5LaWRzCiAgICAgIH0gPSBxdWV1ZUl0ZW07CiAgICAgIGxldCBraWRzID0gY3VycmVudE5vZGUuZ2V0UmF3KCJLaWRzIik7CiAgICAgIGlmIChraWRzIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGtpZHMgPSBhd2FpdCB4cmVmLmZldGNoQXN5bmMoa2lkcyk7CiAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgIGFkZFBhZ2VFcnJvcihleCk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGtpZHMpKSB7CiAgICAgICAgYWRkUGFnZUVycm9yKG5ldyBGb3JtYXRFcnJvcigiUGFnZSBkaWN0aW9uYXJ5IGtpZHMgb2JqZWN0IGlzIG5vdCBhbiBhcnJheS4iKSk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKHBvc0luS2lkcyA+PSBraWRzLmxlbmd0aCkgewogICAgICAgIHF1ZXVlLnBvcCgpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGtpZE9iaiA9IGtpZHNbcG9zSW5LaWRzXTsKICAgICAgbGV0IG9iajsKICAgICAgaWYgKGtpZE9iaiBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIGlmICh2aXNpdGVkTm9kZXMuaGFzKGtpZE9iaikpIHsKICAgICAgICAgIGFkZFBhZ2VFcnJvcihuZXcgRm9ybWF0RXJyb3IoIlBhZ2VzIHRyZWUgY29udGFpbnMgY2lyY3VsYXIgcmVmZXJlbmNlLiIpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICB2aXNpdGVkTm9kZXMucHV0KGtpZE9iaik7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIG9iaiA9IGF3YWl0IHhyZWYuZmV0Y2hBc3luYyhraWRPYmopOwogICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICBhZGRQYWdlRXJyb3IoZXgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIG9iaiA9IGtpZE9iajsKICAgICAgfQogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgIGFkZFBhZ2VFcnJvcihuZXcgRm9ybWF0RXJyb3IoIlBhZ2UgZGljdGlvbmFyeSBraWQgcmVmZXJlbmNlIHBvaW50cyB0byB3cm9uZyB0eXBlIG9mIG9iamVjdC4iKSk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgbGV0IHR5cGUgPSBvYmouZ2V0UmF3KCJUeXBlIik7CiAgICAgIGlmICh0eXBlIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHR5cGUgPSBhd2FpdCB4cmVmLmZldGNoQXN5bmModHlwZSk7CiAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgIGFkZFBhZ2VFcnJvcihleCk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGlzTmFtZSh0eXBlLCAiUGFnZSIpIHx8ICFvYmouaGFzKCJLaWRzIikpIHsKICAgICAgICBhZGRQYWdlRGljdChvYmosIGtpZE9iaiBpbnN0YW5jZW9mIFJlZiA/IGtpZE9iaiA6IG51bGwpOwogICAgICB9IGVsc2UgewogICAgICAgIHF1ZXVlLnB1c2goewogICAgICAgICAgY3VycmVudE5vZGU6IG9iaiwKICAgICAgICAgIHBvc0luS2lkczogMAogICAgICAgIH0pOwogICAgICB9CiAgICAgIHF1ZXVlSXRlbS5wb3NJbktpZHMrKzsKICAgIH0KICAgIHJldHVybiBtYXA7CiAgfQogIGdldFBhZ2VJbmRleChwYWdlUmVmKSB7CiAgICBjb25zdCBjYWNoZWRQYWdlSW5kZXggPSB0aGlzLnBhZ2VJbmRleENhY2hlLmdldChwYWdlUmVmKTsKICAgIGlmIChjYWNoZWRQYWdlSW5kZXggIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGNhY2hlZFBhZ2VJbmRleCk7CiAgICB9CiAgICBjb25zdCB4cmVmID0gdGhpcy54cmVmOwogICAgZnVuY3Rpb24gcGFnZXNCZWZvcmVSZWYoa2lkUmVmKSB7CiAgICAgIGxldCB0b3RhbCA9IDAsCiAgICAgICAgcGFyZW50UmVmOwogICAgICByZXR1cm4geHJlZi5mZXRjaEFzeW5jKGtpZFJlZikudGhlbihmdW5jdGlvbiAobm9kZSkgewogICAgICAgIGlmIChpc1JlZnNFcXVhbChraWRSZWYsIHBhZ2VSZWYpICYmICFpc0RpY3Qobm9kZSwgIlBhZ2UiKSAmJiAhKG5vZGUgaW5zdGFuY2VvZiBEaWN0ICYmICFub2RlLmhhcygiVHlwZSIpICYmIG5vZGUuaGFzKCJDb250ZW50cyIpKSkgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJUaGUgcmVmZXJlbmNlIGRvZXMgbm90IHBvaW50IHRvIGEgL1BhZ2UgZGljdGlvbmFyeS4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFub2RlKSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgICAgaWYgKCEobm9kZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk5vZGUgbXVzdCBiZSBhIGRpY3Rpb25hcnkuIik7CiAgICAgICAgfQogICAgICAgIHBhcmVudFJlZiA9IG5vZGUuZ2V0UmF3KCJQYXJlbnQiKTsKICAgICAgICByZXR1cm4gbm9kZS5nZXRBc3luYygiUGFyZW50Iik7CiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKHBhcmVudCkgewogICAgICAgIGlmICghcGFyZW50KSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgICAgaWYgKCEocGFyZW50IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiUGFyZW50IG11c3QgYmUgYSBkaWN0aW9uYXJ5LiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcGFyZW50LmdldEFzeW5jKCJLaWRzIik7CiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKGtpZHMpIHsKICAgICAgICBpZiAoIWtpZHMpIHsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgICBjb25zdCBraWRQcm9taXNlcyA9IFtdOwogICAgICAgIGxldCBmb3VuZCA9IGZhbHNlOwogICAgICAgIGZvciAoY29uc3Qga2lkIG9mIGtpZHMpIHsKICAgICAgICAgIGlmICghKGtpZCBpbnN0YW5jZW9mIFJlZikpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJLaWQgbXVzdCBiZSBhIHJlZmVyZW5jZS4iKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChpc1JlZnNFcXVhbChraWQsIGtpZFJlZikpIHsKICAgICAgICAgICAgZm91bmQgPSB0cnVlOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGtpZFByb21pc2VzLnB1c2goeHJlZi5mZXRjaEFzeW5jKGtpZCkudGhlbihmdW5jdGlvbiAob2JqKSB7CiAgICAgICAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJLaWQgbm9kZSBtdXN0IGJlIGEgZGljdGlvbmFyeS4iKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAob2JqLmhhcygiQ291bnQiKSkgewogICAgICAgICAgICAgIHRvdGFsICs9IG9iai5nZXQoIkNvdW50Iik7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdG90YWwrKzsKICAgICAgICAgICAgfQogICAgICAgICAgfSkpOwogICAgICAgIH0KICAgICAgICBpZiAoIWZvdW5kKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIktpZCByZWZlcmVuY2Ugbm90IGZvdW5kIGluIHBhcmVudCdzIGtpZHMuIik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBQcm9taXNlLmFsbChraWRQcm9taXNlcykudGhlbigoKSA9PiBbdG90YWwsIHBhcmVudFJlZl0pOwogICAgICB9KTsKICAgIH0KICAgIGxldCB0b3RhbCA9IDA7CiAgICBjb25zdCBuZXh0ID0gcmVmID0+IHBhZ2VzQmVmb3JlUmVmKHJlZikudGhlbihhcmdzID0+IHsKICAgICAgaWYgKCFhcmdzKSB7CiAgICAgICAgdGhpcy5wYWdlSW5kZXhDYWNoZS5wdXQocGFnZVJlZiwgdG90YWwpOwogICAgICAgIHJldHVybiB0b3RhbDsKICAgICAgfQogICAgICBjb25zdCBbY291bnQsIHBhcmVudFJlZl0gPSBhcmdzOwogICAgICB0b3RhbCArPSBjb3VudDsKICAgICAgcmV0dXJuIG5leHQocGFyZW50UmVmKTsKICAgIH0pOwogICAgcmV0dXJuIG5leHQocGFnZVJlZik7CiAgfQogIGdldCBiYXNlVXJsKCkgewogICAgY29uc3QgdXJpID0gdGhpcy4jY2F0RGljdC5nZXQoIlVSSSIpOwogICAgaWYgKHVyaSBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgY29uc3QgYmFzZSA9IHVyaS5nZXQoIkJhc2UiKTsKICAgICAgaWYgKHR5cGVvZiBiYXNlID09PSAic3RyaW5nIikgewogICAgICAgIGNvbnN0IGFic29sdXRlVXJsID0gY3JlYXRlVmFsaWRBYnNvbHV0ZVVybChiYXNlLCBudWxsLCB7CiAgICAgICAgICB0cnlDb252ZXJ0RW5jb2Rpbmc6IHRydWUKICAgICAgICB9KTsKICAgICAgICBpZiAoYWJzb2x1dGVVcmwpIHsKICAgICAgICAgIHJldHVybiBzaGFkb3codGhpcywgImJhc2VVcmwiLCBhYnNvbHV0ZVVybC5ocmVmKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImJhc2VVcmwiLCB0aGlzLnBkZk1hbmFnZXIuZG9jQmFzZVVybCk7CiAgfQogIHN0YXRpYyBwYXJzZURlc3REaWN0aW9uYXJ5KHsKICAgIGRlc3REaWN0LAogICAgcmVzdWx0T2JqLAogICAgZG9jQmFzZVVybCA9IG51bGwsCiAgICBkb2NBdHRhY2htZW50cyA9IG51bGwKICB9KSB7CiAgICBpZiAoIShkZXN0RGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHdhcm4oInBhcnNlRGVzdERpY3Rpb25hcnk6IGBkZXN0RGljdGAgbXVzdCBiZSBhIGRpY3Rpb25hcnkuIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCBhY3Rpb24gPSBkZXN0RGljdC5nZXQoIkEiKSwKICAgICAgdXJsLAogICAgICBkZXN0OwogICAgaWYgKCEoYWN0aW9uIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgaWYgKGRlc3REaWN0LmhhcygiRGVzdCIpKSB7CiAgICAgICAgYWN0aW9uID0gZGVzdERpY3QuZ2V0KCJEZXN0Iik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYWN0aW9uID0gZGVzdERpY3QuZ2V0KCJBQSIpOwogICAgICAgIGlmIChhY3Rpb24gaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgICAgICBpZiAoYWN0aW9uLmhhcygiRCIpKSB7CiAgICAgICAgICAgIGFjdGlvbiA9IGFjdGlvbi5nZXQoIkQiKTsKICAgICAgICAgIH0gZWxzZSBpZiAoYWN0aW9uLmhhcygiVSIpKSB7CiAgICAgICAgICAgIGFjdGlvbiA9IGFjdGlvbi5nZXQoIlUiKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChhY3Rpb24gaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGNvbnN0IGFjdGlvblR5cGUgPSBhY3Rpb24uZ2V0KCJTIik7CiAgICAgIGlmICghKGFjdGlvblR5cGUgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICAgIHdhcm4oInBhcnNlRGVzdERpY3Rpb25hcnk6IEludmFsaWQgdHlwZSBpbiBBY3Rpb24gZGljdGlvbmFyeS4iKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29uc3QgYWN0aW9uTmFtZSA9IGFjdGlvblR5cGUubmFtZTsKICAgICAgc3dpdGNoIChhY3Rpb25OYW1lKSB7CiAgICAgICAgY2FzZSAiUmVzZXRGb3JtIjoKICAgICAgICAgIGNvbnN0IGZsYWdzID0gYWN0aW9uLmdldCgiRmxhZ3MiKTsKICAgICAgICAgIGNvbnN0IGluY2x1ZGUgPSAoKHR5cGVvZiBmbGFncyA9PT0gIm51bWJlciIgPyBmbGFncyA6IDApICYgMSkgPT09IDA7CiAgICAgICAgICBjb25zdCBmaWVsZHMgPSBbXTsKICAgICAgICAgIGNvbnN0IHJlZnMgPSBbXTsKICAgICAgICAgIGZvciAoY29uc3Qgb2JqIG9mIGFjdGlvbi5nZXQoIkZpZWxkcyIpIHx8IFtdKSB7CiAgICAgICAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgICAgICByZWZzLnB1c2gob2JqLnRvU3RyaW5nKCkpOwogICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBvYmogPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgICAgZmllbGRzLnB1c2goc3RyaW5nVG9QREZTdHJpbmcob2JqKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHJlc3VsdE9iai5yZXNldEZvcm0gPSB7CiAgICAgICAgICAgIGZpZWxkcywKICAgICAgICAgICAgcmVmcywKICAgICAgICAgICAgaW5jbHVkZQogICAgICAgICAgfTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlVSSSI6CiAgICAgICAgICB1cmwgPSBhY3Rpb24uZ2V0KCJVUkkiKTsKICAgICAgICAgIGlmICh1cmwgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgIHVybCA9ICIvIiArIHVybC5uYW1lOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiR29UbyI6CiAgICAgICAgICBkZXN0ID0gYWN0aW9uLmdldCgiRCIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiTGF1bmNoIjoKICAgICAgICBjYXNlICJHb1RvUiI6CiAgICAgICAgICBjb25zdCB1cmxEaWN0ID0gYWN0aW9uLmdldCgiRiIpOwogICAgICAgICAgaWYgKHVybERpY3QgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgICAgICAgIGNvbnN0IGZzID0gbmV3IEZpbGVTcGVjKHVybERpY3QsIHRydWUpOwogICAgICAgICAgICAoewogICAgICAgICAgICAgIHJhd0ZpbGVuYW1lOiB1cmwKICAgICAgICAgICAgfSA9IGZzLnNlcmlhbGl6YWJsZSk7CiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB1cmxEaWN0ID09PSAic3RyaW5nIikgewogICAgICAgICAgICB1cmwgPSB1cmxEaWN0OwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCByZW1vdGVEZXN0ID0gZmV0Y2hSZW1vdGVEZXN0KGFjdGlvbik7CiAgICAgICAgICBpZiAocmVtb3RlRGVzdCkgewogICAgICAgICAgICB1cmwgPSB1cmwuc3BsaXQoIiMiLCAxKVswXSArICIjIiArIHJlbW90ZURlc3Q7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBuZXdXaW5kb3cgPSBhY3Rpb24uZ2V0KCJOZXdXaW5kb3ciKTsKICAgICAgICAgIGlmICh0eXBlb2YgbmV3V2luZG93ID09PSAiYm9vbGVhbiIpIHsKICAgICAgICAgICAgcmVzdWx0T2JqLm5ld1dpbmRvdyA9IG5ld1dpbmRvdzsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkdvVG9FIjoKICAgICAgICAgIGNvbnN0IHRhcmdldCA9IGFjdGlvbi5nZXQoIlQiKTsKICAgICAgICAgIGxldCBhdHRhY2htZW50OwogICAgICAgICAgaWYgKGRvY0F0dGFjaG1lbnRzICYmIHRhcmdldCBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICAgICAgY29uc3QgcmVsYXRpb25zaGlwID0gdGFyZ2V0LmdldCgiUiIpOwogICAgICAgICAgICBjb25zdCBuYW1lID0gdGFyZ2V0LmdldCgiTiIpOwogICAgICAgICAgICBpZiAoaXNOYW1lKHJlbGF0aW9uc2hpcCwgIkMiKSAmJiB0eXBlb2YgbmFtZSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICBhdHRhY2htZW50ID0gZG9jQXR0YWNobWVudHNbc3RyaW5nVG9QREZTdHJpbmcobmFtZSwgdHJ1ZSldOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoYXR0YWNobWVudCkgewogICAgICAgICAgICByZXN1bHRPYmouYXR0YWNobWVudCA9IGF0dGFjaG1lbnQ7CiAgICAgICAgICAgIGNvbnN0IGF0dGFjaG1lbnREZXN0ID0gZmV0Y2hSZW1vdGVEZXN0KGFjdGlvbik7CiAgICAgICAgICAgIGlmIChhdHRhY2htZW50RGVzdCkgewogICAgICAgICAgICAgIHJlc3VsdE9iai5hdHRhY2htZW50RGVzdCA9IGF0dGFjaG1lbnREZXN0OwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB3YXJuKGBwYXJzZURlc3REaWN0aW9uYXJ5IC0gdW5pbXBsZW1lbnRlZCAiR29Ub0UiIGFjdGlvbi5gKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIk5hbWVkIjoKICAgICAgICAgIGNvbnN0IG5hbWVkQWN0aW9uID0gYWN0aW9uLmdldCgiTiIpOwogICAgICAgICAgaWYgKG5hbWVkQWN0aW9uIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgICByZXN1bHRPYmouYWN0aW9uID0gbmFtZWRBY3Rpb24ubmFtZTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlNldE9DR1N0YXRlIjoKICAgICAgICAgIGNvbnN0IHN0YXRlID0gYWN0aW9uLmdldCgiU3RhdGUiKTsKICAgICAgICAgIGNvbnN0IHByZXNlcnZlUkIgPSBhY3Rpb24uZ2V0KCJQcmVzZXJ2ZVJCIik7CiAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoc3RhdGUpIHx8IHN0YXRlLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHN0YXRlQXJyID0gW107CiAgICAgICAgICBmb3IgKGNvbnN0IGVsZW0gb2Ygc3RhdGUpIHsKICAgICAgICAgICAgaWYgKGVsZW0gaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgICAgc3dpdGNoIChlbGVtLm5hbWUpIHsKICAgICAgICAgICAgICAgIGNhc2UgIk9OIjoKICAgICAgICAgICAgICAgIGNhc2UgIk9GRiI6CiAgICAgICAgICAgICAgICBjYXNlICJUb2dnbGUiOgogICAgICAgICAgICAgICAgICBzdGF0ZUFyci5wdXNoKGVsZW0ubmFtZSk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIGlmIChlbGVtIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICAgICAgc3RhdGVBcnIucHVzaChlbGVtLnRvU3RyaW5nKCkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoc3RhdGVBcnIubGVuZ3RoICE9PSBzdGF0ZS5sZW5ndGgpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHRPYmouc2V0T0NHU3RhdGUgPSB7CiAgICAgICAgICAgIHN0YXRlOiBzdGF0ZUFyciwKICAgICAgICAgICAgcHJlc2VydmVSQjogdHlwZW9mIHByZXNlcnZlUkIgPT09ICJib29sZWFuIiA/IHByZXNlcnZlUkIgOiB0cnVlCiAgICAgICAgICB9OwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiSmF2YVNjcmlwdCI6CiAgICAgICAgICBjb25zdCBqc0FjdGlvbiA9IGFjdGlvbi5nZXQoIkpTIik7CiAgICAgICAgICBsZXQganM7CiAgICAgICAgICBpZiAoanNBY3Rpb24gaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgICAgICAgIGpzID0ganNBY3Rpb24uZ2V0U3RyaW5nKCk7CiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBqc0FjdGlvbiA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAganMgPSBqc0FjdGlvbjsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGpzVVJMID0ganMgJiYgcmVjb3ZlckpzVVJMKHN0cmluZ1RvUERGU3RyaW5nKGpzLCB0cnVlKSk7CiAgICAgICAgICBpZiAoanNVUkwpIHsKICAgICAgICAgICAgdXJsID0ganNVUkwudXJsOwogICAgICAgICAgICByZXN1bHRPYmoubmV3V2luZG93ID0ganNVUkwubmV3V2luZG93OwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICBkZWZhdWx0OgogICAgICAgICAgaWYgKGFjdGlvbk5hbWUgPT09ICJKYXZhU2NyaXB0IiB8fCBhY3Rpb25OYW1lID09PSAiU3VibWl0Rm9ybSIpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICB3YXJuKGBwYXJzZURlc3REaWN0aW9uYXJ5IC0gdW5zdXBwb3J0ZWQgYWN0aW9uOiAiJHthY3Rpb25OYW1lfSIuYCk7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgfSBlbHNlIGlmIChkZXN0RGljdC5oYXMoIkRlc3QiKSkgewogICAgICBkZXN0ID0gZGVzdERpY3QuZ2V0KCJEZXN0Iik7CiAgICB9CiAgICBpZiAodHlwZW9mIHVybCA9PT0gInN0cmluZyIpIHsKICAgICAgY29uc3QgYWJzb2x1dGVVcmwgPSBjcmVhdGVWYWxpZEFic29sdXRlVXJsKHVybCwgZG9jQmFzZVVybCwgewogICAgICAgIGFkZERlZmF1bHRQcm90b2NvbDogdHJ1ZSwKICAgICAgICB0cnlDb252ZXJ0RW5jb2Rpbmc6IHRydWUKICAgICAgfSk7CiAgICAgIGlmIChhYnNvbHV0ZVVybCkgewogICAgICAgIHJlc3VsdE9iai51cmwgPSBhYnNvbHV0ZVVybC5ocmVmOwogICAgICB9CiAgICAgIHJlc3VsdE9iai51bnNhZmVVcmwgPSB1cmw7CiAgICB9CiAgICBpZiAoZGVzdCkgewogICAgICBpZiAoZGVzdCBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICBkZXN0ID0gZGVzdC5uYW1lOwogICAgICB9CiAgICAgIGlmICh0eXBlb2YgZGVzdCA9PT0gInN0cmluZyIpIHsKICAgICAgICByZXN1bHRPYmouZGVzdCA9IHN0cmluZ1RvUERGU3RyaW5nKGRlc3QsIHRydWUpOwogICAgICB9IGVsc2UgaWYgKGlzVmFsaWRFeHBsaWNpdERlc3QoZGVzdCkpIHsKICAgICAgICByZXN1bHRPYmouZGVzdCA9IGRlc3Q7CiAgICAgIH0KICAgIH0KICB9Cn0KCjsvLyAuL3NyYy9jb3JlL29iamVjdF9sb2FkZXIuanMKCgoKCmZ1bmN0aW9uIG1heUhhdmVDaGlsZHJlbih2YWx1ZSkgewogIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFJlZiB8fCB2YWx1ZSBpbnN0YW5jZW9mIERpY3QgfHwgdmFsdWUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtIHx8IEFycmF5LmlzQXJyYXkodmFsdWUpOwp9CmZ1bmN0aW9uIGFkZENoaWxkcmVuKG5vZGUsIG5vZGVzVG9WaXNpdCkgewogIGlmIChub2RlIGluc3RhbmNlb2YgRGljdCkgewogICAgbm9kZSA9IG5vZGUuZ2V0UmF3VmFsdWVzKCk7CiAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgbm9kZSA9IG5vZGUuZGljdC5nZXRSYXdWYWx1ZXMoKTsKICB9IGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KG5vZGUpKSB7CiAgICByZXR1cm47CiAgfQogIGZvciAoY29uc3QgcmF3VmFsdWUgb2Ygbm9kZSkgewogICAgaWYgKG1heUhhdmVDaGlsZHJlbihyYXdWYWx1ZSkpIHsKICAgICAgbm9kZXNUb1Zpc2l0LnB1c2gocmF3VmFsdWUpOwogICAgfQogIH0KfQpjbGFzcyBPYmplY3RMb2FkZXIgewogIHJlZlNldCA9IG5ldyBSZWZTZXQoKTsKICBjb25zdHJ1Y3RvcihkaWN0LCBrZXlzLCB4cmVmKSB7CiAgICB0aGlzLmRpY3QgPSBkaWN0OwogICAgdGhpcy5rZXlzID0ga2V5czsKICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgfQogIGFzeW5jIGxvYWQoKSB7CiAgICBjb25zdCB7CiAgICAgIGtleXMsCiAgICAgIGRpY3QKICAgIH0gPSB0aGlzOwogICAgY29uc3Qgbm9kZXNUb1Zpc2l0ID0gW107CiAgICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7CiAgICAgIGNvbnN0IHJhd1ZhbHVlID0gZGljdC5nZXRSYXcoa2V5KTsKICAgICAgaWYgKHJhd1ZhbHVlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBub2Rlc1RvVmlzaXQucHVzaChyYXdWYWx1ZSk7CiAgICAgIH0KICAgIH0KICAgIGF3YWl0IHRoaXMuI3dhbGsobm9kZXNUb1Zpc2l0KTsKICAgIHRoaXMucmVmU2V0ID0gbnVsbDsKICB9CiAgYXN5bmMgI3dhbGsobm9kZXNUb1Zpc2l0KSB7CiAgICBjb25zdCBub2Rlc1RvUmV2aXNpdCA9IFtdOwogICAgY29uc3QgcGVuZGluZ1JlcXVlc3RzID0gW107CiAgICB3aGlsZSAobm9kZXNUb1Zpc2l0Lmxlbmd0aCkgewogICAgICBsZXQgY3VycmVudE5vZGUgPSBub2Rlc1RvVmlzaXQucG9wKCk7CiAgICAgIGlmIChjdXJyZW50Tm9kZSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIGlmICh0aGlzLnJlZlNldC5oYXMoY3VycmVudE5vZGUpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHRoaXMucmVmU2V0LnB1dChjdXJyZW50Tm9kZSk7CiAgICAgICAgICBjdXJyZW50Tm9kZSA9IHRoaXMueHJlZi5mZXRjaChjdXJyZW50Tm9kZSk7CiAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgIGlmICghKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pKSB7CiAgICAgICAgICAgIHdhcm4oYE9iamVjdExvYWRlci4jd2FsayAtIHJlcXVlc3RpbmcgYWxsIGRhdGE6ICIke2V4fSIuYCk7CiAgICAgICAgICAgIGF3YWl0IHRoaXMueHJlZi5zdHJlYW0ubWFuYWdlci5yZXF1ZXN0QWxsQ2h1bmtzKCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIG5vZGVzVG9SZXZpc2l0LnB1c2goY3VycmVudE5vZGUpOwogICAgICAgICAgcGVuZGluZ1JlcXVlc3RzLnB1c2goewogICAgICAgICAgICBiZWdpbjogZXguYmVnaW4sCiAgICAgICAgICAgIGVuZDogZXguZW5kCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGN1cnJlbnROb2RlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICAgIGNvbnN0IGJhc2VTdHJlYW1zID0gY3VycmVudE5vZGUuZ2V0QmFzZVN0cmVhbXMoKTsKICAgICAgICBpZiAoYmFzZVN0cmVhbXMpIHsKICAgICAgICAgIGxldCBmb3VuZE1pc3NpbmdEYXRhID0gZmFsc2U7CiAgICAgICAgICBmb3IgKGNvbnN0IHN0cmVhbSBvZiBiYXNlU3RyZWFtcykgewogICAgICAgICAgICBpZiAoc3RyZWFtLmlzRGF0YUxvYWRlZCkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvdW5kTWlzc2luZ0RhdGEgPSB0cnVlOwogICAgICAgICAgICBwZW5kaW5nUmVxdWVzdHMucHVzaCh7CiAgICAgICAgICAgICAgYmVnaW46IHN0cmVhbS5zdGFydCwKICAgICAgICAgICAgICBlbmQ6IHN0cmVhbS5lbmQKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZm91bmRNaXNzaW5nRGF0YSkgewogICAgICAgICAgICBub2Rlc1RvUmV2aXNpdC5wdXNoKGN1cnJlbnROb2RlKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgYWRkQ2hpbGRyZW4oY3VycmVudE5vZGUsIG5vZGVzVG9WaXNpdCk7CiAgICB9CiAgICBpZiAocGVuZGluZ1JlcXVlc3RzLmxlbmd0aCkgewogICAgICBhd2FpdCB0aGlzLnhyZWYuc3RyZWFtLm1hbmFnZXIucmVxdWVzdFJhbmdlcyhwZW5kaW5nUmVxdWVzdHMpOwogICAgICBmb3IgKGNvbnN0IG5vZGUgb2Ygbm9kZXNUb1JldmlzaXQpIHsKICAgICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgdGhpcy5yZWZTZXQucmVtb3ZlKG5vZGUpOwogICAgICAgIH0KICAgICAgfQogICAgICBhd2FpdCB0aGlzLiN3YWxrKG5vZGVzVG9SZXZpc2l0KTsKICAgIH0KICB9CiAgc3RhdGljIGFzeW5jIGxvYWQob2JqLCBrZXlzLCB4cmVmKSB7CiAgICBpZiAoeHJlZi5zdHJlYW0uaXNEYXRhTG9hZGVkKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG9iakxvYWRlciA9IG5ldyBPYmplY3RMb2FkZXIob2JqLCBrZXlzLCB4cmVmKTsKICAgIGF3YWl0IG9iakxvYWRlci5sb2FkKCk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvc3ltYm9sX3V0aWxzLmpzCmNvbnN0ICRhY2NlcHRXaGl0ZXNwYWNlID0gU3ltYm9sKCk7CmNvbnN0ICRhZGRIVE1MID0gU3ltYm9sKCk7CmNvbnN0ICRhcHBlbmRDaGlsZCA9IFN5bWJvbCgpOwpjb25zdCAkY2hpbGRyZW5Ub0hUTUwgPSBTeW1ib2woKTsKY29uc3QgJGNsZWFuID0gU3ltYm9sKCk7CmNvbnN0ICRjbGVhblBhZ2UgPSBTeW1ib2woKTsKY29uc3QgJGNsZWFudXAgPSBTeW1ib2woKTsKY29uc3QgJGNsb25lID0gU3ltYm9sKCk7CmNvbnN0ICRjb25zdW1lZCA9IFN5bWJvbCgpOwpjb25zdCAkY29udGVudCA9IFN5bWJvbCgiY29udGVudCIpOwpjb25zdCAkZGF0YSA9IFN5bWJvbCgiZGF0YSIpOwpjb25zdCAkZHVtcCA9IFN5bWJvbCgpOwpjb25zdCAkZXh0cmEgPSBTeW1ib2woImV4dHJhIik7CmNvbnN0ICRmaW5hbGl6ZSA9IFN5bWJvbCgpOwpjb25zdCAkZmx1c2hIVE1MID0gU3ltYm9sKCk7CmNvbnN0ICRnZXRBdHRyaWJ1dGVJdCA9IFN5bWJvbCgpOwpjb25zdCAkZ2V0QXR0cmlidXRlcyA9IFN5bWJvbCgpOwpjb25zdCAkZ2V0QXZhaWxhYmxlU3BhY2UgPSBTeW1ib2woKTsKY29uc3QgJGdldENoaWxkcmVuQnlDbGFzcyA9IFN5bWJvbCgpOwpjb25zdCAkZ2V0Q2hpbGRyZW5CeU5hbWUgPSBTeW1ib2woKTsKY29uc3QgJGdldENoaWxkcmVuQnlOYW1lSXQgPSBTeW1ib2woKTsKY29uc3QgJGdldERhdGFWYWx1ZSA9IFN5bWJvbCgpOwpjb25zdCAkZ2V0RXh0cmEgPSBTeW1ib2woKTsKY29uc3QgJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0ID0gU3ltYm9sKCk7CmNvbnN0ICRnZXRDaGlsZHJlbiA9IFN5bWJvbCgpOwpjb25zdCAkZ2V0Q29udGFpbmVkQ2hpbGRyZW4gPSBTeW1ib2woKTsKY29uc3QgJGdldE5leHRQYWdlID0gU3ltYm9sKCk7CmNvbnN0ICRnZXRTdWJmb3JtUGFyZW50ID0gU3ltYm9sKCk7CmNvbnN0ICRnZXRQYXJlbnQgPSBTeW1ib2woKTsKY29uc3QgJGdldFRlbXBsYXRlUm9vdCA9IFN5bWJvbCgpOwpjb25zdCAkZ2xvYmFsRGF0YSA9IFN5bWJvbCgpOwpjb25zdCAkaGFzU2V0dGFibGVWYWx1ZSA9IFN5bWJvbCgpOwpjb25zdCAkaWRzID0gU3ltYm9sKCk7CmNvbnN0ICRpbmRleE9mID0gU3ltYm9sKCk7CmNvbnN0ICRpbnNlcnRBdCA9IFN5bWJvbCgpOwpjb25zdCAkaXNDREFUQVhtbCA9IFN5bWJvbCgpOwpjb25zdCAkaXNCaW5kYWJsZSA9IFN5bWJvbCgpOwpjb25zdCAkaXNEYXRhVmFsdWUgPSBTeW1ib2woKTsKY29uc3QgJGlzRGVzY2VuZGVudCA9IFN5bWJvbCgpOwpjb25zdCAkaXNOc0Fnbm9zdGljID0gU3ltYm9sKCk7CmNvbnN0ICRpc1NwbGl0dGFibGUgPSBTeW1ib2woKTsKY29uc3QgJGlzVGhlcmVNb3JlV2lkdGggPSBTeW1ib2woKTsKY29uc3QgJGlzVHJhbnNwYXJlbnQgPSBTeW1ib2woKTsKY29uc3QgJGlzVXNhYmxlID0gU3ltYm9sKCk7CmNvbnN0ICRsYXN0QXR0cmlidXRlID0gU3ltYm9sKCk7CmNvbnN0ICRuYW1lc3BhY2VJZCA9IFN5bWJvbCgibmFtZXNwYWNlSWQiKTsKY29uc3QgJG5vZGVOYW1lID0gU3ltYm9sKCJub2RlTmFtZSIpOwpjb25zdCAkbnNBdHRyaWJ1dGVzID0gU3ltYm9sKCk7CmNvbnN0ICRvbkNoaWxkID0gU3ltYm9sKCk7CmNvbnN0ICRvbkNoaWxkQ2hlY2sgPSBTeW1ib2woKTsKY29uc3QgJG9uVGV4dCA9IFN5bWJvbCgpOwpjb25zdCAkcHVzaEdseXBocyA9IFN5bWJvbCgpOwpjb25zdCAkcG9wUGFyYSA9IFN5bWJvbCgpOwpjb25zdCAkcHVzaFBhcmEgPSBTeW1ib2woKTsKY29uc3QgJHJlbW92ZUNoaWxkID0gU3ltYm9sKCk7CmNvbnN0ICRyb290ID0gU3ltYm9sKCJyb290Iik7CmNvbnN0ICRyZXNvbHZlUHJvdG90eXBlcyA9IFN5bWJvbCgpOwpjb25zdCAkc2VhcmNoTm9kZSA9IFN5bWJvbCgpOwpjb25zdCAkc2V0SWQgPSBTeW1ib2woKTsKY29uc3QgJHNldFNldEF0dHJpYnV0ZXMgPSBTeW1ib2woKTsKY29uc3QgJHNldFZhbHVlID0gU3ltYm9sKCk7CmNvbnN0ICR0YWJJbmRleCA9IFN5bWJvbCgpOwpjb25zdCAkdGV4dCA9IFN5bWJvbCgpOwpjb25zdCAkdG9QYWdlcyA9IFN5bWJvbCgpOwpjb25zdCAkdG9IVE1MID0gU3ltYm9sKCk7CmNvbnN0ICR0b1N0cmluZyA9IFN5bWJvbCgpOwpjb25zdCAkdG9TdHlsZSA9IFN5bWJvbCgpOwpjb25zdCAkdWlkID0gU3ltYm9sKCJ1aWQiKTsKCjsvLyAuL3NyYy9jb3JlL3hmYS9uYW1lc3BhY2VzLmpzCmNvbnN0ICRidWlsZFhGQU9iamVjdCA9IFN5bWJvbCgpOwpjb25zdCBOYW1lc3BhY2VJZHMgPSB7CiAgY29uZmlnOiB7CiAgICBpZDogMCwKICAgIGNoZWNrOiBucyA9PiBucy5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hjaS8iKQogIH0sCiAgY29ubmVjdGlvblNldDogewogICAgaWQ6IDEsCiAgICBjaGVjazogbnMgPT4gbnMuc3RhcnRzV2l0aCgiaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtY29ubmVjdGlvbi1zZXQvIikKICB9LAogIGRhdGFzZXRzOiB7CiAgICBpZDogMiwKICAgIGNoZWNrOiBucyA9PiBucy5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1kYXRhLyIpCiAgfSwKICBmb3JtOiB7CiAgICBpZDogMywKICAgIGNoZWNrOiBucyA9PiBucy5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1mb3JtLyIpCiAgfSwKICBsb2NhbGVTZXQ6IHsKICAgIGlkOiA0LAogICAgY2hlY2s6IG5zID0+IG5zLnN0YXJ0c1dpdGgoImh0dHA6Ly93d3cueGZhLm9yZy9zY2hlbWEveGZhLWxvY2FsZS1zZXQvIikKICB9LAogIHBkZjogewogICAgaWQ6IDUsCiAgICBjaGVjazogbnMgPT4gbnMgPT09ICJodHRwOi8vbnMuYWRvYmUuY29tL3hkcC9wZGYvIgogIH0sCiAgc2lnbmF0dXJlOiB7CiAgICBpZDogNiwKICAgIGNoZWNrOiBucyA9PiBucyA9PT0gImh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiCiAgfSwKICBzb3VyY2VTZXQ6IHsKICAgIGlkOiA3LAogICAgY2hlY2s6IG5zID0+IG5zLnN0YXJ0c1dpdGgoImh0dHA6Ly93d3cueGZhLm9yZy9zY2hlbWEveGZhLXNvdXJjZS1zZXQvIikKICB9LAogIHN0eWxlc2hlZXQ6IHsKICAgIGlkOiA4LAogICAgY2hlY2s6IG5zID0+IG5zID09PSAiaHR0cDovL3d3dy53My5vcmcvMTk5OS9YU0wvVHJhbnNmb3JtIgogIH0sCiAgdGVtcGxhdGU6IHsKICAgIGlkOiA5LAogICAgY2hlY2s6IG5zID0+IG5zLnN0YXJ0c1dpdGgoImh0dHA6Ly93d3cueGZhLm9yZy9zY2hlbWEveGZhLXRlbXBsYXRlLyIpCiAgfSwKICB4ZGM6IHsKICAgIGlkOiAxMCwKICAgIGNoZWNrOiBucyA9PiBucy5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hkYy8iKQogIH0sCiAgeGRwOiB7CiAgICBpZDogMTEsCiAgICBjaGVjazogbnMgPT4gbnMgPT09ICJodHRwOi8vbnMuYWRvYmUuY29tL3hkcC8iCiAgfSwKICB4ZmRmOiB7CiAgICBpZDogMTIsCiAgICBjaGVjazogbnMgPT4gbnMgPT09ICJodHRwOi8vbnMuYWRvYmUuY29tL3hmZGYvIgogIH0sCiAgeGh0bWw6IHsKICAgIGlkOiAxMywKICAgIGNoZWNrOiBucyA9PiBucyA9PT0gImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiCiAgfSwKICB4bXBtZXRhOiB7CiAgICBpZDogMTQsCiAgICBjaGVjazogbnMgPT4gbnMgPT09ICJodHRwOi8vbnMuYWRvYmUuY29tL3htcG1ldGEvIgogIH0KfTsKCjsvLyAuL3NyYy9jb3JlL3hmYS91dGlscy5qcwoKY29uc3QgZGltQ29udmVydGVycyA9IHsKICBwdDogeCA9PiB4LAogIGNtOiB4ID0+IHggLyAyLjU0ICogNzIsCiAgbW06IHggPT4geCAvICgxMCAqIDIuNTQpICogNzIsCiAgaW46IHggPT4geCAqIDcyLAogIHB4OiB4ID0+IHgKfTsKY29uc3QgbWVhc3VyZW1lbnRQYXR0ZXJuID0gLyhbKy1dP1xkK1wuP1xkKikoLiopLzsKZnVuY3Rpb24gc3RyaXBRdW90ZXMoc3RyKSB7CiAgaWYgKHN0ci5zdGFydHNXaXRoKCInIikgfHwgc3RyLnN0YXJ0c1dpdGgoJyInKSkgewogICAgcmV0dXJuIHN0ci5zbGljZSgxLCAtMSk7CiAgfQogIHJldHVybiBzdHI7Cn0KZnVuY3Rpb24gZ2V0SW50ZWdlcih7CiAgZGF0YSwKICBkZWZhdWx0VmFsdWUsCiAgdmFsaWRhdGUKfSkgewogIGlmICghZGF0YSkgewogICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKICB9CiAgZGF0YSA9IGRhdGEudHJpbSgpOwogIGNvbnN0IG4gPSBwYXJzZUludChkYXRhLCAxMCk7CiAgaWYgKCFpc05hTihuKSAmJiB2YWxpZGF0ZShuKSkgewogICAgcmV0dXJuIG47CiAgfQogIHJldHVybiBkZWZhdWx0VmFsdWU7Cn0KZnVuY3Rpb24gZ2V0RmxvYXQoewogIGRhdGEsCiAgZGVmYXVsdFZhbHVlLAogIHZhbGlkYXRlCn0pIHsKICBpZiAoIWRhdGEpIHsKICAgIHJldHVybiBkZWZhdWx0VmFsdWU7CiAgfQogIGRhdGEgPSBkYXRhLnRyaW0oKTsKICBjb25zdCBuID0gcGFyc2VGbG9hdChkYXRhKTsKICBpZiAoIWlzTmFOKG4pICYmIHZhbGlkYXRlKG4pKSB7CiAgICByZXR1cm4gbjsKICB9CiAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKfQpmdW5jdGlvbiBnZXRLZXl3b3JkKHsKICBkYXRhLAogIGRlZmF1bHRWYWx1ZSwKICB2YWxpZGF0ZQp9KSB7CiAgaWYgKCFkYXRhKSB7CiAgICByZXR1cm4gZGVmYXVsdFZhbHVlOwogIH0KICBkYXRhID0gZGF0YS50cmltKCk7CiAgaWYgKHZhbGlkYXRlKGRhdGEpKSB7CiAgICByZXR1cm4gZGF0YTsKICB9CiAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKfQpmdW5jdGlvbiBnZXRTdHJpbmdPcHRpb24oZGF0YSwgb3B0aW9ucykgewogIHJldHVybiBnZXRLZXl3b3JkKHsKICAgIGRhdGEsCiAgICBkZWZhdWx0VmFsdWU6IG9wdGlvbnNbMF0sCiAgICB2YWxpZGF0ZTogayA9PiBvcHRpb25zLmluY2x1ZGVzKGspCiAgfSk7Cn0KZnVuY3Rpb24gZ2V0TWVhc3VyZW1lbnQoc3RyLCBkZWYgPSAiMCIpIHsKICBkZWYgfHw9ICIwIjsKICBpZiAoIXN0cikgewogICAgcmV0dXJuIGdldE1lYXN1cmVtZW50KGRlZik7CiAgfQogIGNvbnN0IG1hdGNoID0gc3RyLnRyaW0oKS5tYXRjaChtZWFzdXJlbWVudFBhdHRlcm4pOwogIGlmICghbWF0Y2gpIHsKICAgIHJldHVybiBnZXRNZWFzdXJlbWVudChkZWYpOwogIH0KICBjb25zdCBbLCB2YWx1ZVN0ciwgdW5pdF0gPSBtYXRjaDsKICBjb25zdCB2YWx1ZSA9IHBhcnNlRmxvYXQodmFsdWVTdHIpOwogIGlmIChpc05hTih2YWx1ZSkpIHsKICAgIHJldHVybiBnZXRNZWFzdXJlbWVudChkZWYpOwogIH0KICBpZiAodmFsdWUgPT09IDApIHsKICAgIHJldHVybiAwOwogIH0KICBjb25zdCBjb252ID0gZGltQ29udmVydGVyc1t1bml0XTsKICBpZiAoY29udikgewogICAgcmV0dXJuIGNvbnYodmFsdWUpOwogIH0KICByZXR1cm4gdmFsdWU7Cn0KZnVuY3Rpb24gZ2V0UmF0aW8oZGF0YSkgewogIGlmICghZGF0YSkgewogICAgcmV0dXJuIHsKICAgICAgbnVtOiAxLAogICAgICBkZW46IDEKICAgIH07CiAgfQogIGNvbnN0IHJhdGlvID0gZGF0YS5zcGxpdCgiOiIsIDIpLm1hcCh4ID0+IHBhcnNlRmxvYXQoeC50cmltKCkpKS5maWx0ZXIoeCA9PiAhaXNOYU4oeCkpOwogIGlmIChyYXRpby5sZW5ndGggPT09IDEpIHsKICAgIHJhdGlvLnB1c2goMSk7CiAgfQogIGlmIChyYXRpby5sZW5ndGggPT09IDApIHsKICAgIHJldHVybiB7CiAgICAgIG51bTogMSwKICAgICAgZGVuOiAxCiAgICB9OwogIH0KICBjb25zdCBbbnVtLCBkZW5dID0gcmF0aW87CiAgcmV0dXJuIHsKICAgIG51bSwKICAgIGRlbgogIH07Cn0KZnVuY3Rpb24gZ2V0UmVsZXZhbnQoZGF0YSkgewogIGlmICghZGF0YSkgewogICAgcmV0dXJuIFtdOwogIH0KICByZXR1cm4gZGF0YS50cmltKCkuc3BsaXQoL1xzKy8pLm1hcChlID0+ICh7CiAgICBleGNsdWRlZDogZVswXSA9PT0gIi0iLAogICAgdmlld25hbWU6IGUuc3Vic3RyaW5nKDEpCiAgfSkpOwp9CmZ1bmN0aW9uIGdldENvbG9yKGRhdGEsIGRlZiA9IFswLCAwLCAwXSkgewogIGxldCBbciwgZywgYl0gPSBkZWY7CiAgaWYgKCFkYXRhKSB7CiAgICByZXR1cm4gewogICAgICByLAogICAgICBnLAogICAgICBiCiAgICB9OwogIH0KICBjb25zdCBjb2xvciA9IGRhdGEuc3BsaXQoIiwiLCAzKS5tYXAoYyA9PiBNYXRoQ2xhbXAocGFyc2VJbnQoYy50cmltKCksIDEwKSwgMCwgMjU1KSkubWFwKGMgPT4gaXNOYU4oYykgPyAwIDogYyk7CiAgaWYgKGNvbG9yLmxlbmd0aCA8IDMpIHsKICAgIHJldHVybiB7CiAgICAgIHIsCiAgICAgIGcsCiAgICAgIGIKICAgIH07CiAgfQogIFtyLCBnLCBiXSA9IGNvbG9yOwogIHJldHVybiB7CiAgICByLAogICAgZywKICAgIGIKICB9Owp9CmZ1bmN0aW9uIGdldEJCb3goZGF0YSkgewogIGNvbnN0IGRlZiA9IC0xOwogIGlmICghZGF0YSkgewogICAgcmV0dXJuIHsKICAgICAgeDogZGVmLAogICAgICB5OiBkZWYsCiAgICAgIHdpZHRoOiBkZWYsCiAgICAgIGhlaWdodDogZGVmCiAgICB9OwogIH0KICBjb25zdCBiYm94ID0gZGF0YS5zcGxpdCgiLCIsIDQpLm1hcChtID0+IGdldE1lYXN1cmVtZW50KG0udHJpbSgpLCAiLTEiKSk7CiAgaWYgKGJib3gubGVuZ3RoIDwgNCB8fCBiYm94WzJdIDwgMCB8fCBiYm94WzNdIDwgMCkgewogICAgcmV0dXJuIHsKICAgICAgeDogZGVmLAogICAgICB5OiBkZWYsCiAgICAgIHdpZHRoOiBkZWYsCiAgICAgIGhlaWdodDogZGVmCiAgICB9OwogIH0KICBjb25zdCBbeCwgeSwgd2lkdGgsIGhlaWdodF0gPSBiYm94OwogIHJldHVybiB7CiAgICB4LAogICAgeSwKICAgIHdpZHRoLAogICAgaGVpZ2h0CiAgfTsKfQpjbGFzcyBIVE1MUmVzdWx0IHsKICBzdGF0aWMgZ2V0IEZBSUxVUkUoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJGQUlMVVJFIiwgbmV3IEhUTUxSZXN1bHQoZmFsc2UsIG51bGwsIG51bGwsIG51bGwpKTsKICB9CiAgc3RhdGljIGdldCBFTVBUWSgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgIkVNUFRZIiwgbmV3IEhUTUxSZXN1bHQodHJ1ZSwgbnVsbCwgbnVsbCwgbnVsbCkpOwogIH0KICBjb25zdHJ1Y3RvcihzdWNjZXNzLCBodG1sLCBiYm94LCBicmVha05vZGUpIHsKICAgIHRoaXMuc3VjY2VzcyA9IHN1Y2Nlc3M7CiAgICB0aGlzLmh0bWwgPSBodG1sOwogICAgdGhpcy5iYm94ID0gYmJveDsKICAgIHRoaXMuYnJlYWtOb2RlID0gYnJlYWtOb2RlOwogIH0KICBpc0JyZWFrKCkgewogICAgcmV0dXJuICEhdGhpcy5icmVha05vZGU7CiAgfQogIHN0YXRpYyBicmVha05vZGUobm9kZSkgewogICAgcmV0dXJuIG5ldyBIVE1MUmVzdWx0KGZhbHNlLCBudWxsLCBudWxsLCBub2RlKTsKICB9CiAgc3RhdGljIHN1Y2Nlc3MoaHRtbCwgYmJveCA9IG51bGwpIHsKICAgIHJldHVybiBuZXcgSFRNTFJlc3VsdCh0cnVlLCBodG1sLCBiYm94LCBudWxsKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3hmYS9mb250cy5qcwoKCgpjbGFzcyBGb250RmluZGVyIHsKICBjb25zdHJ1Y3RvcihwZGZGb250cykgewogICAgdGhpcy5mb250cyA9IG5ldyBNYXAoKTsKICAgIHRoaXMuY2FjaGUgPSBuZXcgTWFwKCk7CiAgICB0aGlzLndhcm5lZCA9IG5ldyBTZXQoKTsKICAgIHRoaXMuZGVmYXVsdEZvbnQgPSBudWxsOwogICAgdGhpcy5hZGQocGRmRm9udHMpOwogIH0KICBhZGQocGRmRm9udHMsIHJlYWxseU1pc3NpbmdGb250cyA9IG51bGwpIHsKICAgIGZvciAoY29uc3QgcGRmRm9udCBvZiBwZGZGb250cykgewogICAgICB0aGlzLmFkZFBkZkZvbnQocGRmRm9udCk7CiAgICB9CiAgICBmb3IgKGNvbnN0IHBkZkZvbnQgb2YgdGhpcy5mb250cy52YWx1ZXMoKSkgewogICAgICBpZiAoIXBkZkZvbnQucmVndWxhcikgewogICAgICAgIHBkZkZvbnQucmVndWxhciA9IHBkZkZvbnQuaXRhbGljIHx8IHBkZkZvbnQuYm9sZCB8fCBwZGZGb250LmJvbGRpdGFsaWM7CiAgICAgIH0KICAgIH0KICAgIGlmICghcmVhbGx5TWlzc2luZ0ZvbnRzIHx8IHJlYWxseU1pc3NpbmdGb250cy5zaXplID09PSAwKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG15cmlhZCA9IHRoaXMuZm9udHMuZ2V0KCJQZGZKUy1GYWxsYmFjay1QZGZKUy1YRkEiKTsKICAgIGZvciAoY29uc3QgbWlzc2luZyBvZiByZWFsbHlNaXNzaW5nRm9udHMpIHsKICAgICAgdGhpcy5mb250cy5zZXQobWlzc2luZywgbXlyaWFkKTsKICAgIH0KICB9CiAgYWRkUGRmRm9udChwZGZGb250KSB7CiAgICBjb25zdCBjc3NGb250SW5mbyA9IHBkZkZvbnQuY3NzRm9udEluZm87CiAgICBjb25zdCBuYW1lID0gY3NzRm9udEluZm8uZm9udEZhbWlseTsKICAgIGxldCBmb250ID0gdGhpcy5mb250cy5nZXQobmFtZSk7CiAgICBpZiAoIWZvbnQpIHsKICAgICAgZm9udCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHRoaXMuZm9udHMuc2V0KG5hbWUsIGZvbnQpOwogICAgICBpZiAoIXRoaXMuZGVmYXVsdEZvbnQpIHsKICAgICAgICB0aGlzLmRlZmF1bHRGb250ID0gZm9udDsKICAgICAgfQogICAgfQogICAgbGV0IHByb3BlcnR5ID0gIiI7CiAgICBjb25zdCBmb250V2VpZ2h0ID0gcGFyc2VGbG9hdChjc3NGb250SW5mby5mb250V2VpZ2h0KTsKICAgIGlmIChwYXJzZUZsb2F0KGNzc0ZvbnRJbmZvLml0YWxpY0FuZ2xlKSAhPT0gMCkgewogICAgICBwcm9wZXJ0eSA9IGZvbnRXZWlnaHQgPj0gNzAwID8gImJvbGRpdGFsaWMiIDogIml0YWxpYyI7CiAgICB9IGVsc2UgaWYgKGZvbnRXZWlnaHQgPj0gNzAwKSB7CiAgICAgIHByb3BlcnR5ID0gImJvbGQiOwogICAgfQogICAgaWYgKCFwcm9wZXJ0eSkgewogICAgICBpZiAocGRmRm9udC5uYW1lLmluY2x1ZGVzKCJCb2xkIikgfHwgcGRmRm9udC5wc05hbWU/LmluY2x1ZGVzKCJCb2xkIikpIHsKICAgICAgICBwcm9wZXJ0eSA9ICJib2xkIjsKICAgICAgfQogICAgICBpZiAocGRmRm9udC5uYW1lLmluY2x1ZGVzKCJJdGFsaWMiKSB8fCBwZGZGb250Lm5hbWUuZW5kc1dpdGgoIkl0IikgfHwgcGRmRm9udC5wc05hbWU/LmluY2x1ZGVzKCJJdGFsaWMiKSB8fCBwZGZGb250LnBzTmFtZT8uZW5kc1dpdGgoIkl0IikpIHsKICAgICAgICBwcm9wZXJ0eSArPSAiaXRhbGljIjsKICAgICAgfQogICAgfQogICAgaWYgKCFwcm9wZXJ0eSkgewogICAgICBwcm9wZXJ0eSA9ICJyZWd1bGFyIjsKICAgIH0KICAgIGZvbnRbcHJvcGVydHldID0gcGRmRm9udDsKICB9CiAgZ2V0RGVmYXVsdCgpIHsKICAgIHJldHVybiB0aGlzLmRlZmF1bHRGb250OwogIH0KICBmaW5kKGZvbnROYW1lLCBtdXN0V2FybiA9IHRydWUpIHsKICAgIGxldCBmb250ID0gdGhpcy5mb250cy5nZXQoZm9udE5hbWUpIHx8IHRoaXMuY2FjaGUuZ2V0KGZvbnROYW1lKTsKICAgIGlmIChmb250KSB7CiAgICAgIHJldHVybiBmb250OwogICAgfQogICAgY29uc3QgcGF0dGVybiA9IC8sfC18X3wgfGJvbGRpdGFsaWN8Ym9sZHxpdGFsaWN8cmVndWxhcnxpdC9naTsKICAgIGxldCBuYW1lID0gZm9udE5hbWUucmVwbGFjZUFsbChwYXR0ZXJuLCAiIik7CiAgICBmb250ID0gdGhpcy5mb250cy5nZXQobmFtZSk7CiAgICBpZiAoZm9udCkgewogICAgICB0aGlzLmNhY2hlLnNldChmb250TmFtZSwgZm9udCk7CiAgICAgIHJldHVybiBmb250OwogICAgfQogICAgbmFtZSA9IG5hbWUudG9Mb3dlckNhc2UoKTsKICAgIGNvbnN0IG1heWJlID0gW107CiAgICBmb3IgKGNvbnN0IFtmYW1pbHksIHBkZkZvbnRdIG9mIHRoaXMuZm9udHMuZW50cmllcygpKSB7CiAgICAgIGlmIChmYW1pbHkucmVwbGFjZUFsbChwYXR0ZXJuLCAiIikudG9Mb3dlckNhc2UoKS5zdGFydHNXaXRoKG5hbWUpKSB7CiAgICAgICAgbWF5YmUucHVzaChwZGZGb250KTsKICAgICAgfQogICAgfQogICAgaWYgKG1heWJlLmxlbmd0aCA9PT0gMCkgewogICAgICBmb3IgKGNvbnN0IFssIHBkZkZvbnRdIG9mIHRoaXMuZm9udHMuZW50cmllcygpKSB7CiAgICAgICAgaWYgKHBkZkZvbnQucmVndWxhci5uYW1lPy5yZXBsYWNlQWxsKHBhdHRlcm4sICIiKS50b0xvd2VyQ2FzZSgpLnN0YXJ0c1dpdGgobmFtZSkpIHsKICAgICAgICAgIG1heWJlLnB1c2gocGRmRm9udCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAobWF5YmUubGVuZ3RoID09PSAwKSB7CiAgICAgIG5hbWUgPSBuYW1lLnJlcGxhY2VBbGwoL3BzbXR8bXQvZ2ksICIiKTsKICAgICAgZm9yIChjb25zdCBbZmFtaWx5LCBwZGZGb250XSBvZiB0aGlzLmZvbnRzLmVudHJpZXMoKSkgewogICAgICAgIGlmIChmYW1pbHkucmVwbGFjZUFsbChwYXR0ZXJuLCAiIikudG9Mb3dlckNhc2UoKS5zdGFydHNXaXRoKG5hbWUpKSB7CiAgICAgICAgICBtYXliZS5wdXNoKHBkZkZvbnQpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKG1heWJlLmxlbmd0aCA9PT0gMCkgewogICAgICBmb3IgKGNvbnN0IHBkZkZvbnQgb2YgdGhpcy5mb250cy52YWx1ZXMoKSkgewogICAgICAgIGlmIChwZGZGb250LnJlZ3VsYXIubmFtZT8ucmVwbGFjZUFsbChwYXR0ZXJuLCAiIikudG9Mb3dlckNhc2UoKS5zdGFydHNXaXRoKG5hbWUpKSB7CiAgICAgICAgICBtYXliZS5wdXNoKHBkZkZvbnQpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKG1heWJlLmxlbmd0aCA+PSAxKSB7CiAgICAgIGlmIChtYXliZS5sZW5ndGggIT09IDEgJiYgbXVzdFdhcm4pIHsKICAgICAgICB3YXJuKGBYRkEgLSBUb28gbWFueSBjaG9pY2VzIHRvIGd1ZXNzIHRoZSBjb3JyZWN0IGZvbnQ6ICR7Zm9udE5hbWV9YCk7CiAgICAgIH0KICAgICAgdGhpcy5jYWNoZS5zZXQoZm9udE5hbWUsIG1heWJlWzBdKTsKICAgICAgcmV0dXJuIG1heWJlWzBdOwogICAgfQogICAgaWYgKG11c3RXYXJuICYmICF0aGlzLndhcm5lZC5oYXMoZm9udE5hbWUpKSB7CiAgICAgIHRoaXMud2FybmVkLmFkZChmb250TmFtZSk7CiAgICAgIHdhcm4oYFhGQSAtIENhbm5vdCBmaW5kIHRoZSBmb250OiAke2ZvbnROYW1lfWApOwogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQp9CmZ1bmN0aW9uIHNlbGVjdEZvbnQoeGZhRm9udCwgdHlwZWZhY2UpIHsKICBpZiAoeGZhRm9udC5wb3N0dXJlID09PSAiaXRhbGljIikgewogICAgaWYgKHhmYUZvbnQud2VpZ2h0ID09PSAiYm9sZCIpIHsKICAgICAgcmV0dXJuIHR5cGVmYWNlLmJvbGRpdGFsaWM7CiAgICB9CiAgICByZXR1cm4gdHlwZWZhY2UuaXRhbGljOwogIH0gZWxzZSBpZiAoeGZhRm9udC53ZWlnaHQgPT09ICJib2xkIikgewogICAgcmV0dXJuIHR5cGVmYWNlLmJvbGQ7CiAgfQogIHJldHVybiB0eXBlZmFjZS5yZWd1bGFyOwp9CmZ1bmN0aW9uIGZvbnRzX2dldE1ldHJpY3MoeGZhRm9udCwgcmVhbCA9IGZhbHNlKSB7CiAgbGV0IHBkZkZvbnQgPSBudWxsOwogIGlmICh4ZmFGb250KSB7CiAgICBjb25zdCBuYW1lID0gc3RyaXBRdW90ZXMoeGZhRm9udC50eXBlZmFjZSk7CiAgICBjb25zdCB0eXBlZmFjZSA9IHhmYUZvbnRbJGdsb2JhbERhdGFdLmZvbnRGaW5kZXIuZmluZChuYW1lKTsKICAgIHBkZkZvbnQgPSBzZWxlY3RGb250KHhmYUZvbnQsIHR5cGVmYWNlKTsKICB9CiAgaWYgKCFwZGZGb250KSB7CiAgICByZXR1cm4gewogICAgICBsaW5lSGVpZ2h0OiAxMiwKICAgICAgbGluZUdhcDogMiwKICAgICAgbGluZU5vR2FwOiAxMAogICAgfTsKICB9CiAgY29uc3Qgc2l6ZSA9IHhmYUZvbnQuc2l6ZSB8fCAxMDsKICBjb25zdCBsaW5lSGVpZ2h0ID0gcGRmRm9udC5saW5lSGVpZ2h0ID8gTWF0aC5tYXgocmVhbCA/IDAgOiAxLjIsIHBkZkZvbnQubGluZUhlaWdodCkgOiAxLjI7CiAgY29uc3QgbGluZUdhcCA9IHBkZkZvbnQubGluZUdhcCA9PT0gdW5kZWZpbmVkID8gMC4yIDogcGRmRm9udC5saW5lR2FwOwogIHJldHVybiB7CiAgICBsaW5lSGVpZ2h0OiBsaW5lSGVpZ2h0ICogc2l6ZSwKICAgIGxpbmVHYXA6IGxpbmVHYXAgKiBzaXplLAogICAgbGluZU5vR2FwOiBNYXRoLm1heCgxLCBsaW5lSGVpZ2h0IC0gbGluZUdhcCkgKiBzaXplCiAgfTsKfQoKOy8vIC4vc3JjL2NvcmUveGZhL3RleHQuanMKCmNvbnN0IFdJRFRIX0ZBQ1RPUiA9IDEuMDI7CmNsYXNzIHRleHRfRm9udEluZm8gewogIGNvbnN0cnVjdG9yKHhmYUZvbnQsIG1hcmdpbiwgbGluZUhlaWdodCwgZm9udEZpbmRlcikgewogICAgdGhpcy5saW5lSGVpZ2h0ID0gbGluZUhlaWdodDsKICAgIHRoaXMucGFyYU1hcmdpbiA9IG1hcmdpbiB8fCB7CiAgICAgIHRvcDogMCwKICAgICAgYm90dG9tOiAwLAogICAgICBsZWZ0OiAwLAogICAgICByaWdodDogMAogICAgfTsKICAgIGlmICgheGZhRm9udCkgewogICAgICBbdGhpcy5wZGZGb250LCB0aGlzLnhmYUZvbnRdID0gdGhpcy5kZWZhdWx0Rm9udChmb250RmluZGVyKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy54ZmFGb250ID0gewogICAgICB0eXBlZmFjZTogeGZhRm9udC50eXBlZmFjZSwKICAgICAgcG9zdHVyZTogeGZhRm9udC5wb3N0dXJlLAogICAgICB3ZWlnaHQ6IHhmYUZvbnQud2VpZ2h0LAogICAgICBzaXplOiB4ZmFGb250LnNpemUsCiAgICAgIGxldHRlclNwYWNpbmc6IHhmYUZvbnQubGV0dGVyU3BhY2luZwogICAgfTsKICAgIGNvbnN0IHR5cGVmYWNlID0gZm9udEZpbmRlci5maW5kKHhmYUZvbnQudHlwZWZhY2UpOwogICAgaWYgKCF0eXBlZmFjZSkgewogICAgICBbdGhpcy5wZGZGb250LCB0aGlzLnhmYUZvbnRdID0gdGhpcy5kZWZhdWx0Rm9udChmb250RmluZGVyKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5wZGZGb250ID0gc2VsZWN0Rm9udCh4ZmFGb250LCB0eXBlZmFjZSk7CiAgICBpZiAoIXRoaXMucGRmRm9udCkgewogICAgICBbdGhpcy5wZGZGb250LCB0aGlzLnhmYUZvbnRdID0gdGhpcy5kZWZhdWx0Rm9udChmb250RmluZGVyKTsKICAgIH0KICB9CiAgZGVmYXVsdEZvbnQoZm9udEZpbmRlcikgewogICAgY29uc3QgZm9udCA9IGZvbnRGaW5kZXIuZmluZCgiSGVsdmV0aWNhIiwgZmFsc2UpIHx8IGZvbnRGaW5kZXIuZmluZCgiTXlyaWFkIFBybyIsIGZhbHNlKSB8fCBmb250RmluZGVyLmZpbmQoIkFyaWFsIiwgZmFsc2UpIHx8IGZvbnRGaW5kZXIuZ2V0RGVmYXVsdCgpOwogICAgaWYgKGZvbnQ/LnJlZ3VsYXIpIHsKICAgICAgY29uc3QgcGRmRm9udCA9IGZvbnQucmVndWxhcjsKICAgICAgY29uc3QgaW5mbyA9IHBkZkZvbnQuY3NzRm9udEluZm87CiAgICAgIGNvbnN0IHhmYUZvbnQgPSB7CiAgICAgICAgdHlwZWZhY2U6IGluZm8uZm9udEZhbWlseSwKICAgICAgICBwb3N0dXJlOiAibm9ybWFsIiwKICAgICAgICB3ZWlnaHQ6ICJub3JtYWwiLAogICAgICAgIHNpemU6IDEwLAogICAgICAgIGxldHRlclNwYWNpbmc6IDAKICAgICAgfTsKICAgICAgcmV0dXJuIFtwZGZGb250LCB4ZmFGb250XTsKICAgIH0KICAgIGNvbnN0IHhmYUZvbnQgPSB7CiAgICAgIHR5cGVmYWNlOiAiQ291cmllciIsCiAgICAgIHBvc3R1cmU6ICJub3JtYWwiLAogICAgICB3ZWlnaHQ6ICJub3JtYWwiLAogICAgICBzaXplOiAxMCwKICAgICAgbGV0dGVyU3BhY2luZzogMAogICAgfTsKICAgIHJldHVybiBbbnVsbCwgeGZhRm9udF07CiAgfQp9CmNsYXNzIEZvbnRTZWxlY3RvciB7CiAgY29uc3RydWN0b3IoZGVmYXVsdFhmYUZvbnQsIGRlZmF1bHRQYXJhTWFyZ2luLCBkZWZhdWx0TGluZUhlaWdodCwgZm9udEZpbmRlcikgewogICAgdGhpcy5mb250RmluZGVyID0gZm9udEZpbmRlcjsKICAgIHRoaXMuc3RhY2sgPSBbbmV3IHRleHRfRm9udEluZm8oZGVmYXVsdFhmYUZvbnQsIGRlZmF1bHRQYXJhTWFyZ2luLCBkZWZhdWx0TGluZUhlaWdodCwgZm9udEZpbmRlcildOwogIH0KICBwdXNoRGF0YSh4ZmFGb250LCBtYXJnaW4sIGxpbmVIZWlnaHQpIHsKICAgIGNvbnN0IGxhc3RGb250ID0gdGhpcy5zdGFjay5hdCgtMSk7CiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgWyJ0eXBlZmFjZSIsICJwb3N0dXJlIiwgIndlaWdodCIsICJzaXplIiwgImxldHRlclNwYWNpbmciXSkgewogICAgICBpZiAoIXhmYUZvbnRbbmFtZV0pIHsKICAgICAgICB4ZmFGb250W25hbWVdID0gbGFzdEZvbnQueGZhRm9udFtuYW1lXTsKICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCBuYW1lIG9mIFsidG9wIiwgImJvdHRvbSIsICJsZWZ0IiwgInJpZ2h0Il0pIHsKICAgICAgaWYgKGlzTmFOKG1hcmdpbltuYW1lXSkpIHsKICAgICAgICBtYXJnaW5bbmFtZV0gPSBsYXN0Rm9udC5wYXJhTWFyZ2luW25hbWVdOwogICAgICB9CiAgICB9CiAgICBjb25zdCBmb250SW5mbyA9IG5ldyB0ZXh0X0ZvbnRJbmZvKHhmYUZvbnQsIG1hcmdpbiwgbGluZUhlaWdodCB8fCBsYXN0Rm9udC5saW5lSGVpZ2h0LCB0aGlzLmZvbnRGaW5kZXIpOwogICAgaWYgKCFmb250SW5mby5wZGZGb250KSB7CiAgICAgIGZvbnRJbmZvLnBkZkZvbnQgPSBsYXN0Rm9udC5wZGZGb250OwogICAgfQogICAgdGhpcy5zdGFjay5wdXNoKGZvbnRJbmZvKTsKICB9CiAgcG9wRm9udCgpIHsKICAgIHRoaXMuc3RhY2sucG9wKCk7CiAgfQogIHRvcEZvbnQoKSB7CiAgICByZXR1cm4gdGhpcy5zdGFjay5hdCgtMSk7CiAgfQp9CmNsYXNzIFRleHRNZWFzdXJlIHsKICBjb25zdHJ1Y3RvcihkZWZhdWx0WGZhRm9udCwgZGVmYXVsdFBhcmFNYXJnaW4sIGRlZmF1bHRMaW5lSGVpZ2h0LCBmb250cykgewogICAgdGhpcy5nbHlwaHMgPSBbXTsKICAgIHRoaXMuZm9udFNlbGVjdG9yID0gbmV3IEZvbnRTZWxlY3RvcihkZWZhdWx0WGZhRm9udCwgZGVmYXVsdFBhcmFNYXJnaW4sIGRlZmF1bHRMaW5lSGVpZ2h0LCBmb250cyk7CiAgICB0aGlzLmV4dHJhSGVpZ2h0ID0gMDsKICB9CiAgcHVzaERhdGEoeGZhRm9udCwgbWFyZ2luLCBsaW5lSGVpZ2h0KSB7CiAgICB0aGlzLmZvbnRTZWxlY3Rvci5wdXNoRGF0YSh4ZmFGb250LCBtYXJnaW4sIGxpbmVIZWlnaHQpOwogIH0KICBwb3BGb250KHhmYUZvbnQpIHsKICAgIHJldHVybiB0aGlzLmZvbnRTZWxlY3Rvci5wb3BGb250KCk7CiAgfQogIGFkZFBhcmEoKSB7CiAgICBjb25zdCBsYXN0Rm9udCA9IHRoaXMuZm9udFNlbGVjdG9yLnRvcEZvbnQoKTsKICAgIHRoaXMuZXh0cmFIZWlnaHQgKz0gbGFzdEZvbnQucGFyYU1hcmdpbi50b3AgKyBsYXN0Rm9udC5wYXJhTWFyZ2luLmJvdHRvbTsKICB9CiAgYWRkU3RyaW5nKHN0cikgewogICAgaWYgKCFzdHIpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgbGFzdEZvbnQgPSB0aGlzLmZvbnRTZWxlY3Rvci50b3BGb250KCk7CiAgICBjb25zdCBmb250U2l6ZSA9IGxhc3RGb250LnhmYUZvbnQuc2l6ZTsKICAgIGlmIChsYXN0Rm9udC5wZGZGb250KSB7CiAgICAgIGNvbnN0IGxldHRlclNwYWNpbmcgPSBsYXN0Rm9udC54ZmFGb250LmxldHRlclNwYWNpbmc7CiAgICAgIGNvbnN0IHBkZkZvbnQgPSBsYXN0Rm9udC5wZGZGb250OwogICAgICBjb25zdCBmb250TGluZUhlaWdodCA9IHBkZkZvbnQubGluZUhlaWdodCB8fCAxLjI7CiAgICAgIGNvbnN0IGxpbmVIZWlnaHQgPSBsYXN0Rm9udC5saW5lSGVpZ2h0IHx8IE1hdGgubWF4KDEuMiwgZm9udExpbmVIZWlnaHQpICogZm9udFNpemU7CiAgICAgIGNvbnN0IGxpbmVHYXAgPSBwZGZGb250LmxpbmVHYXAgPT09IHVuZGVmaW5lZCA/IDAuMiA6IHBkZkZvbnQubGluZUdhcDsKICAgICAgY29uc3Qgbm9HYXAgPSBmb250TGluZUhlaWdodCAtIGxpbmVHYXA7CiAgICAgIGNvbnN0IGZpcnN0TGluZUhlaWdodCA9IE1hdGgubWF4KDEsIG5vR2FwKSAqIGZvbnRTaXplOwogICAgICBjb25zdCBzY2FsZSA9IGZvbnRTaXplIC8gMTAwMDsKICAgICAgY29uc3QgZmFsbGJhY2tXaWR0aCA9IHBkZkZvbnQuZGVmYXVsdFdpZHRoIHx8IHBkZkZvbnQuY2hhcnNUb0dseXBocygiICIpWzBdLndpZHRoOwogICAgICBmb3IgKGNvbnN0IGxpbmUgb2Ygc3RyLnNwbGl0KC9bXHUyMDI5XG5dLykpIHsKICAgICAgICBjb25zdCBlbmNvZGVkTGluZSA9IHBkZkZvbnQuZW5jb2RlU3RyaW5nKGxpbmUpLmpvaW4oIiIpOwogICAgICAgIGNvbnN0IGdseXBocyA9IHBkZkZvbnQuY2hhcnNUb0dseXBocyhlbmNvZGVkTGluZSk7CiAgICAgICAgZm9yIChjb25zdCBnbHlwaCBvZiBnbHlwaHMpIHsKICAgICAgICAgIGNvbnN0IHdpZHRoID0gZ2x5cGgud2lkdGggfHwgZmFsbGJhY2tXaWR0aDsKICAgICAgICAgIHRoaXMuZ2x5cGhzLnB1c2goW3dpZHRoICogc2NhbGUgKyBsZXR0ZXJTcGFjaW5nLCBsaW5lSGVpZ2h0LCBmaXJzdExpbmVIZWlnaHQsIGdseXBoLnVuaWNvZGUsIGZhbHNlXSk7CiAgICAgICAgfQogICAgICAgIHRoaXMuZ2x5cGhzLnB1c2goWzAsIDAsIDAsICJcbiIsIHRydWVdKTsKICAgICAgfQogICAgICB0aGlzLmdseXBocy5wb3AoKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgZm9yIChjb25zdCBsaW5lIG9mIHN0ci5zcGxpdCgvW1x1MjAyOVxuXS8pKSB7CiAgICAgIGZvciAoY29uc3QgY2hhciBvZiBsaW5lLnNwbGl0KCIiKSkgewogICAgICAgIHRoaXMuZ2x5cGhzLnB1c2goW2ZvbnRTaXplLCAxLjIgKiBmb250U2l6ZSwgZm9udFNpemUsIGNoYXIsIGZhbHNlXSk7CiAgICAgIH0KICAgICAgdGhpcy5nbHlwaHMucHVzaChbMCwgMCwgMCwgIlxuIiwgdHJ1ZV0pOwogICAgfQogICAgdGhpcy5nbHlwaHMucG9wKCk7CiAgfQogIGNvbXB1dGUobWF4V2lkdGgpIHsKICAgIGxldCBsYXN0U3BhY2VQb3MgPSAtMSwKICAgICAgbGFzdFNwYWNlV2lkdGggPSAwLAogICAgICB3aWR0aCA9IDAsCiAgICAgIGhlaWdodCA9IDAsCiAgICAgIGN1cnJlbnRMaW5lV2lkdGggPSAwLAogICAgICBjdXJyZW50TGluZUhlaWdodCA9IDA7CiAgICBsZXQgaXNCcm9rZW4gPSBmYWxzZTsKICAgIGxldCBpc0ZpcnN0TGluZSA9IHRydWU7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB0aGlzLmdseXBocy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IFtnbHlwaFdpZHRoLCBsaW5lSGVpZ2h0LCBmaXJzdExpbmVIZWlnaHQsIGNoYXIsIGlzRU9MXSA9IHRoaXMuZ2x5cGhzW2ldOwogICAgICBjb25zdCBpc1NwYWNlID0gY2hhciA9PT0gIiAiOwogICAgICBjb25zdCBnbHlwaEhlaWdodCA9IGlzRmlyc3RMaW5lID8gZmlyc3RMaW5lSGVpZ2h0IDogbGluZUhlaWdodDsKICAgICAgaWYgKGlzRU9MKSB7CiAgICAgICAgd2lkdGggPSBNYXRoLm1heCh3aWR0aCwgY3VycmVudExpbmVXaWR0aCk7CiAgICAgICAgY3VycmVudExpbmVXaWR0aCA9IDA7CiAgICAgICAgaGVpZ2h0ICs9IGN1cnJlbnRMaW5lSGVpZ2h0OwogICAgICAgIGN1cnJlbnRMaW5lSGVpZ2h0ID0gZ2x5cGhIZWlnaHQ7CiAgICAgICAgbGFzdFNwYWNlUG9zID0gLTE7CiAgICAgICAgbGFzdFNwYWNlV2lkdGggPSAwOwogICAgICAgIGlzRmlyc3RMaW5lID0gZmFsc2U7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGlzU3BhY2UpIHsKICAgICAgICBpZiAoY3VycmVudExpbmVXaWR0aCArIGdseXBoV2lkdGggPiBtYXhXaWR0aCkgewogICAgICAgICAgd2lkdGggPSBNYXRoLm1heCh3aWR0aCwgY3VycmVudExpbmVXaWR0aCk7CiAgICAgICAgICBjdXJyZW50TGluZVdpZHRoID0gMDsKICAgICAgICAgIGhlaWdodCArPSBjdXJyZW50TGluZUhlaWdodDsKICAgICAgICAgIGN1cnJlbnRMaW5lSGVpZ2h0ID0gZ2x5cGhIZWlnaHQ7CiAgICAgICAgICBsYXN0U3BhY2VQb3MgPSAtMTsKICAgICAgICAgIGxhc3RTcGFjZVdpZHRoID0gMDsKICAgICAgICAgIGlzQnJva2VuID0gdHJ1ZTsKICAgICAgICAgIGlzRmlyc3RMaW5lID0gZmFsc2U7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGN1cnJlbnRMaW5lSGVpZ2h0ID0gTWF0aC5tYXgoZ2x5cGhIZWlnaHQsIGN1cnJlbnRMaW5lSGVpZ2h0KTsKICAgICAgICAgIGxhc3RTcGFjZVdpZHRoID0gY3VycmVudExpbmVXaWR0aDsKICAgICAgICAgIGN1cnJlbnRMaW5lV2lkdGggKz0gZ2x5cGhXaWR0aDsKICAgICAgICAgIGxhc3RTcGFjZVBvcyA9IGk7CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChjdXJyZW50TGluZVdpZHRoICsgZ2x5cGhXaWR0aCA+IG1heFdpZHRoKSB7CiAgICAgICAgaGVpZ2h0ICs9IGN1cnJlbnRMaW5lSGVpZ2h0OwogICAgICAgIGN1cnJlbnRMaW5lSGVpZ2h0ID0gZ2x5cGhIZWlnaHQ7CiAgICAgICAgaWYgKGxhc3RTcGFjZVBvcyAhPT0gLTEpIHsKICAgICAgICAgIGkgPSBsYXN0U3BhY2VQb3M7CiAgICAgICAgICB3aWR0aCA9IE1hdGgubWF4KHdpZHRoLCBsYXN0U3BhY2VXaWR0aCk7CiAgICAgICAgICBjdXJyZW50TGluZVdpZHRoID0gMDsKICAgICAgICAgIGxhc3RTcGFjZVBvcyA9IC0xOwogICAgICAgICAgbGFzdFNwYWNlV2lkdGggPSAwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB3aWR0aCA9IE1hdGgubWF4KHdpZHRoLCBjdXJyZW50TGluZVdpZHRoKTsKICAgICAgICAgIGN1cnJlbnRMaW5lV2lkdGggPSBnbHlwaFdpZHRoOwogICAgICAgIH0KICAgICAgICBpc0Jyb2tlbiA9IHRydWU7CiAgICAgICAgaXNGaXJzdExpbmUgPSBmYWxzZTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjdXJyZW50TGluZVdpZHRoICs9IGdseXBoV2lkdGg7CiAgICAgIGN1cnJlbnRMaW5lSGVpZ2h0ID0gTWF0aC5tYXgoZ2x5cGhIZWlnaHQsIGN1cnJlbnRMaW5lSGVpZ2h0KTsKICAgIH0KICAgIHdpZHRoID0gTWF0aC5tYXgod2lkdGgsIGN1cnJlbnRMaW5lV2lkdGgpOwogICAgaGVpZ2h0ICs9IGN1cnJlbnRMaW5lSGVpZ2h0ICsgdGhpcy5leHRyYUhlaWdodDsKICAgIHJldHVybiB7CiAgICAgIHdpZHRoOiBXSURUSF9GQUNUT1IgKiB3aWR0aCwKICAgICAgaGVpZ2h0LAogICAgICBpc0Jyb2tlbgogICAgfTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3hmYS9zb20uanMKCgpjb25zdCBuYW1lUGF0dGVybiA9IC9eW14uW10rLzsKY29uc3QgaW5kZXhQYXR0ZXJuID0gL15bXlxdXSsvOwpjb25zdCBvcGVyYXRvcnMgPSB7CiAgZG90OiAwLAogIGRvdERvdDogMSwKICBkb3RIYXNoOiAyLAogIGRvdEJyYWNrZXQ6IDMsCiAgZG90UGFyZW46IDQKfTsKY29uc3Qgc2hvcnRjdXRzID0gbmV3IE1hcChbWyIkZGF0YSIsIChyb290LCBjdXJyZW50KSA9PiByb290LmRhdGFzZXRzID8gcm9vdC5kYXRhc2V0cy5kYXRhIDogcm9vdF0sIFsiJHJlY29yZCIsIChyb290LCBjdXJyZW50KSA9PiAocm9vdC5kYXRhc2V0cyA/IHJvb3QuZGF0YXNldHMuZGF0YSA6IHJvb3QpWyRnZXRDaGlsZHJlbl0oKVswXV0sIFsiJHRlbXBsYXRlIiwgKHJvb3QsIGN1cnJlbnQpID0+IHJvb3QudGVtcGxhdGVdLCBbIiRjb25uZWN0aW9uU2V0IiwgKHJvb3QsIGN1cnJlbnQpID0+IHJvb3QuY29ubmVjdGlvblNldF0sIFsiJGZvcm0iLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC5mb3JtXSwgWyIkbGF5b3V0IiwgKHJvb3QsIGN1cnJlbnQpID0+IHJvb3QubGF5b3V0XSwgWyIkaG9zdCIsIChyb290LCBjdXJyZW50KSA9PiByb290Lmhvc3RdLCBbIiRkYXRhV2luZG93IiwgKHJvb3QsIGN1cnJlbnQpID0+IHJvb3QuZGF0YVdpbmRvd10sIFsiJGV2ZW50IiwgKHJvb3QsIGN1cnJlbnQpID0+IHJvb3QuZXZlbnRdLCBbIiEiLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC5kYXRhc2V0c10sIFsiJHhmYSIsIChyb290LCBjdXJyZW50KSA9PiByb290XSwgWyJ4ZmEiLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdF0sIFsiJCIsIChyb290LCBjdXJyZW50KSA9PiBjdXJyZW50XV0pOwpjb25zdCBzb21DYWNoZSA9IG5ldyBXZWFrTWFwKCk7CmZ1bmN0aW9uIHBhcnNlSW5kZXgoaW5kZXgpIHsKICBpbmRleCA9IGluZGV4LnRyaW0oKTsKICBpZiAoaW5kZXggPT09ICIqIikgewogICAgcmV0dXJuIEluZmluaXR5OwogIH0KICByZXR1cm4gcGFyc2VJbnQoaW5kZXgsIDEwKSB8fCAwOwp9CmZ1bmN0aW9uIHBhcnNlRXhwcmVzc2lvbihleHByLCBkb3REb3RBbGxvd2VkLCBub0V4cHIgPSB0cnVlKSB7CiAgbGV0IG1hdGNoID0gZXhwci5tYXRjaChuYW1lUGF0dGVybik7CiAgaWYgKCFtYXRjaCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGxldCBbbmFtZV0gPSBtYXRjaDsKICBjb25zdCBwYXJzZWQgPSBbewogICAgbmFtZSwKICAgIGNhY2hlTmFtZTogIi4iICsgbmFtZSwKICAgIGluZGV4OiAwLAogICAganM6IG51bGwsCiAgICBmb3JtQ2FsYzogbnVsbCwKICAgIG9wZXJhdG9yOiBvcGVyYXRvcnMuZG90CiAgfV07CiAgbGV0IHBvcyA9IG5hbWUubGVuZ3RoOwogIHdoaWxlIChwb3MgPCBleHByLmxlbmd0aCkgewogICAgY29uc3Qgc3BvcyA9IHBvczsKICAgIGNvbnN0IGNoYXIgPSBleHByLmNoYXJBdChwb3MrKyk7CiAgICBpZiAoY2hhciA9PT0gIlsiKSB7CiAgICAgIG1hdGNoID0gZXhwci5zbGljZShwb3MpLm1hdGNoKGluZGV4UGF0dGVybik7CiAgICAgIGlmICghbWF0Y2gpIHsKICAgICAgICB3YXJuKCJYRkEgLSBJbnZhbGlkIGluZGV4IGluIFNPTSBleHByZXNzaW9uIik7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgcGFyc2VkLmF0KC0xKS5pbmRleCA9IHBhcnNlSW5kZXgobWF0Y2hbMF0pOwogICAgICBwb3MgKz0gbWF0Y2hbMF0ubGVuZ3RoICsgMTsKICAgICAgY29udGludWU7CiAgICB9CiAgICBsZXQgb3BlcmF0b3I7CiAgICBzd2l0Y2ggKGV4cHIuY2hhckF0KHBvcykpIHsKICAgICAgY2FzZSAiLiI6CiAgICAgICAgaWYgKCFkb3REb3RBbGxvd2VkKSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgICAgcG9zKys7CiAgICAgICAgb3BlcmF0b3IgPSBvcGVyYXRvcnMuZG90RG90OwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICIjIjoKICAgICAgICBwb3MrKzsKICAgICAgICBvcGVyYXRvciA9IG9wZXJhdG9ycy5kb3RIYXNoOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJbIjoKICAgICAgICBpZiAobm9FeHByKSB7CiAgICAgICAgICB3YXJuKCJYRkEgLSBTT00gZXhwcmVzc2lvbiBjb250YWlucyBhIEZvcm1DYWxjIHN1YmV4cHJlc3Npb24gd2hpY2ggaXMgbm90IHN1cHBvcnRlZCBmb3Igbm93LiIpOwogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIG9wZXJhdG9yID0gb3BlcmF0b3JzLmRvdEJyYWNrZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIigiOgogICAgICAgIGlmIChub0V4cHIpIHsKICAgICAgICAgIHdhcm4oIlhGQSAtIFNPTSBleHByZXNzaW9uIGNvbnRhaW5zIGEgSmF2YVNjcmlwdCBzdWJleHByZXNzaW9uIHdoaWNoIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIG5vdy4iKTsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgICBvcGVyYXRvciA9IG9wZXJhdG9ycy5kb3RQYXJlbjsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICBvcGVyYXRvciA9IG9wZXJhdG9ycy5kb3Q7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBtYXRjaCA9IGV4cHIuc2xpY2UocG9zKS5tYXRjaChuYW1lUGF0dGVybik7CiAgICBpZiAoIW1hdGNoKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgW25hbWVdID0gbWF0Y2g7CiAgICBwb3MgKz0gbmFtZS5sZW5ndGg7CiAgICBwYXJzZWQucHVzaCh7CiAgICAgIG5hbWUsCiAgICAgIGNhY2hlTmFtZTogZXhwci5zbGljZShzcG9zLCBwb3MpLAogICAgICBvcGVyYXRvciwKICAgICAgaW5kZXg6IDAsCiAgICAgIGpzOiBudWxsLAogICAgICBmb3JtQ2FsYzogbnVsbAogICAgfSk7CiAgfQogIHJldHVybiBwYXJzZWQ7Cn0KZnVuY3Rpb24gc2VhcmNoTm9kZShyb290LCBjb250YWluZXIsIGV4cHIsIGRvdERvdEFsbG93ZWQgPSB0cnVlLCB1c2VDYWNoZSA9IHRydWUpIHsKICBjb25zdCBwYXJzZWQgPSBwYXJzZUV4cHJlc3Npb24oZXhwciwgZG90RG90QWxsb3dlZCk7CiAgaWYgKCFwYXJzZWQpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCBmbiA9IHNob3J0Y3V0cy5nZXQocGFyc2VkWzBdLm5hbWUpOwogIGxldCBpID0gMDsKICBsZXQgaXNRdWFsaWZpZWQ7CiAgaWYgKGZuKSB7CiAgICBpc1F1YWxpZmllZCA9IHRydWU7CiAgICByb290ID0gW2ZuKHJvb3QsIGNvbnRhaW5lcildOwogICAgaSA9IDE7CiAgfSBlbHNlIHsKICAgIGlzUXVhbGlmaWVkID0gY29udGFpbmVyID09PSBudWxsOwogICAgcm9vdCA9IFtjb250YWluZXIgfHwgcm9vdF07CiAgfQogIGZvciAobGV0IGlpID0gcGFyc2VkLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IHsKICAgICAgbmFtZSwKICAgICAgY2FjaGVOYW1lLAogICAgICBvcGVyYXRvciwKICAgICAgaW5kZXgKICAgIH0gPSBwYXJzZWRbaV07CiAgICBjb25zdCBub2RlcyA9IFtdOwogICAgZm9yIChjb25zdCBub2RlIG9mIHJvb3QpIHsKICAgICAgaWYgKCFub2RlLmlzWEZBT2JqZWN0KSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbGV0IGNoaWxkcmVuLCBjYWNoZWQ7CiAgICAgIGlmICh1c2VDYWNoZSkgewogICAgICAgIGNhY2hlZCA9IHNvbUNhY2hlLmdldChub2RlKTsKICAgICAgICBpZiAoIWNhY2hlZCkgewogICAgICAgICAgY2FjaGVkID0gbmV3IE1hcCgpOwogICAgICAgICAgc29tQ2FjaGUuc2V0KG5vZGUsIGNhY2hlZCk7CiAgICAgICAgfQogICAgICAgIGNoaWxkcmVuID0gY2FjaGVkLmdldChjYWNoZU5hbWUpOwogICAgICB9CiAgICAgIGlmICghY2hpbGRyZW4pIHsKICAgICAgICBzd2l0Y2ggKG9wZXJhdG9yKSB7CiAgICAgICAgICBjYXNlIG9wZXJhdG9ycy5kb3Q6CiAgICAgICAgICAgIGNoaWxkcmVuID0gbm9kZVskZ2V0Q2hpbGRyZW5CeU5hbWVdKG5hbWUsIGZhbHNlKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIG9wZXJhdG9ycy5kb3REb3Q6CiAgICAgICAgICAgIGNoaWxkcmVuID0gbm9kZVskZ2V0Q2hpbGRyZW5CeU5hbWVdKG5hbWUsIHRydWUpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2Ugb3BlcmF0b3JzLmRvdEhhc2g6CiAgICAgICAgICAgIGNoaWxkcmVuID0gbm9kZVskZ2V0Q2hpbGRyZW5CeUNsYXNzXShuYW1lKTsKICAgICAgICAgICAgY2hpbGRyZW4gPSBjaGlsZHJlbi5pc1hGQU9iamVjdEFycmF5ID8gY2hpbGRyZW4uY2hpbGRyZW4gOiBbY2hpbGRyZW5dOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAodXNlQ2FjaGUpIHsKICAgICAgICAgIGNhY2hlZC5zZXQoY2FjaGVOYW1lLCBjaGlsZHJlbik7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPiAwKSB7CiAgICAgICAgbm9kZXMucHVzaChjaGlsZHJlbik7CiAgICAgIH0KICAgIH0KICAgIGlmIChub2Rlcy5sZW5ndGggPT09IDAgJiYgIWlzUXVhbGlmaWVkICYmIGkgPT09IDApIHsKICAgICAgY29uc3QgcGFyZW50ID0gY29udGFpbmVyWyRnZXRQYXJlbnRdKCk7CiAgICAgIGNvbnRhaW5lciA9IHBhcmVudDsKICAgICAgaWYgKCFjb250YWluZXIpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBpID0gLTE7CiAgICAgIHJvb3QgPSBbY29udGFpbmVyXTsKICAgICAgY29udGludWU7CiAgICB9CiAgICByb290ID0gaXNGaW5pdGUoaW5kZXgpID8gbm9kZXMuZmlsdGVyKG5vZGUgPT4gaW5kZXggPCBub2RlLmxlbmd0aCkubWFwKG5vZGUgPT4gbm9kZVtpbmRleF0pIDogbm9kZXMuZmxhdCgpOwogIH0KICBpZiAocm9vdC5sZW5ndGggPT09IDApIHsKICAgIHJldHVybiBudWxsOwogIH0KICByZXR1cm4gcm9vdDsKfQpmdW5jdGlvbiBjcmVhdGVEYXRhTm9kZShyb290LCBjb250YWluZXIsIGV4cHIpIHsKICBjb25zdCBwYXJzZWQgPSBwYXJzZUV4cHJlc3Npb24oZXhwcik7CiAgaWYgKCFwYXJzZWQpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBpZiAocGFyc2VkLnNvbWUoeCA9PiB4Lm9wZXJhdG9yID09PSBvcGVyYXRvcnMuZG90RG90KSkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGNvbnN0IGZuID0gc2hvcnRjdXRzLmdldChwYXJzZWRbMF0ubmFtZSk7CiAgbGV0IGkgPSAwOwogIGlmIChmbikgewogICAgcm9vdCA9IGZuKHJvb3QsIGNvbnRhaW5lcik7CiAgICBpID0gMTsKICB9IGVsc2UgewogICAgcm9vdCA9IGNvbnRhaW5lciB8fCByb290OwogIH0KICBmb3IgKGxldCBpaSA9IHBhcnNlZC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCB7CiAgICAgIG5hbWUsCiAgICAgIG9wZXJhdG9yLAogICAgICBpbmRleAogICAgfSA9IHBhcnNlZFtpXTsKICAgIGlmICghaXNGaW5pdGUoaW5kZXgpKSB7CiAgICAgIHBhcnNlZFtpXS5pbmRleCA9IDA7CiAgICAgIHJldHVybiByb290LmNyZWF0ZU5vZGVzKHBhcnNlZC5zbGljZShpKSk7CiAgICB9CiAgICBsZXQgY2hpbGRyZW47CiAgICBzd2l0Y2ggKG9wZXJhdG9yKSB7CiAgICAgIGNhc2Ugb3BlcmF0b3JzLmRvdDoKICAgICAgICBjaGlsZHJlbiA9IHJvb3RbJGdldENoaWxkcmVuQnlOYW1lXShuYW1lLCBmYWxzZSk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2Ugb3BlcmF0b3JzLmRvdERvdDoKICAgICAgICBjaGlsZHJlbiA9IHJvb3RbJGdldENoaWxkcmVuQnlOYW1lXShuYW1lLCB0cnVlKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBvcGVyYXRvcnMuZG90SGFzaDoKICAgICAgICBjaGlsZHJlbiA9IHJvb3RbJGdldENoaWxkcmVuQnlDbGFzc10obmFtZSk7CiAgICAgICAgY2hpbGRyZW4gPSBjaGlsZHJlbi5pc1hGQU9iamVjdEFycmF5ID8gY2hpbGRyZW4uY2hpbGRyZW4gOiBbY2hpbGRyZW5dOwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIGJyZWFrOwogICAgfQogICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gcm9vdC5jcmVhdGVOb2RlcyhwYXJzZWQuc2xpY2UoaSkpOwogICAgfQogICAgaWYgKGluZGV4IDwgY2hpbGRyZW4ubGVuZ3RoKSB7CiAgICAgIGNvbnN0IGNoaWxkID0gY2hpbGRyZW5baW5kZXhdOwogICAgICBpZiAoIWNoaWxkLmlzWEZBT2JqZWN0KSB7CiAgICAgICAgd2FybihgWEZBIC0gQ2Fubm90IGNyZWF0ZSBhIG5vZGUuYCk7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgcm9vdCA9IGNoaWxkOwogICAgfSBlbHNlIHsKICAgICAgcGFyc2VkW2ldLmluZGV4ID0gaW5kZXggLSBjaGlsZHJlbi5sZW5ndGg7CiAgICAgIHJldHVybiByb290LmNyZWF0ZU5vZGVzKHBhcnNlZC5zbGljZShpKSk7CiAgICB9CiAgfQogIHJldHVybiBudWxsOwp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEveGZhX29iamVjdC5qcwoKCgoKCgpjb25zdCBfYXBwbHlQcm90b3R5cGUgPSBTeW1ib2woKTsKY29uc3QgX2F0dHJpYnV0ZXMgPSBTeW1ib2woKTsKY29uc3QgX2F0dHJpYnV0ZU5hbWVzID0gU3ltYm9sKCk7CmNvbnN0IF9jaGlsZHJlbiA9IFN5bWJvbCgiX2NoaWxkcmVuIik7CmNvbnN0IF9jbG9uZUF0dHJpYnV0ZSA9IFN5bWJvbCgpOwpjb25zdCBfZGF0YVZhbHVlID0gU3ltYm9sKCk7CmNvbnN0IF9kZWZhdWx0VmFsdWUgPSBTeW1ib2woKTsKY29uc3QgX2ZpbHRlcmVkQ2hpbGRyZW5HZW5lcmF0b3IgPSBTeW1ib2woKTsKY29uc3QgX2dldFByb3RvdHlwZSA9IFN5bWJvbCgpOwpjb25zdCBfZ2V0VW5zZXRBdHRyaWJ1dGVzID0gU3ltYm9sKCk7CmNvbnN0IF9oYXNDaGlsZHJlbiA9IFN5bWJvbCgpOwpjb25zdCBfbWF4ID0gU3ltYm9sKCk7CmNvbnN0IF9vcHRpb25zID0gU3ltYm9sKCk7CmNvbnN0IF9wYXJlbnQgPSBTeW1ib2woInBhcmVudCIpOwpjb25zdCBfcmVzb2x2ZVByb3RvdHlwZXNIZWxwZXIgPSBTeW1ib2woKTsKY29uc3QgX3NldEF0dHJpYnV0ZXMgPSBTeW1ib2woKTsKY29uc3QgX3ZhbGlkYXRvciA9IFN5bWJvbCgpOwpsZXQgdWlkID0gMDsKY29uc3QgTlNfREFUQVNFVFMgPSBOYW1lc3BhY2VJZHMuZGF0YXNldHMuaWQ7CmNsYXNzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IobnNJZCwgbmFtZSwgaGFzQ2hpbGRyZW4gPSBmYWxzZSkgewogICAgdGhpc1skbmFtZXNwYWNlSWRdID0gbnNJZDsKICAgIHRoaXNbJG5vZGVOYW1lXSA9IG5hbWU7CiAgICB0aGlzW19oYXNDaGlsZHJlbl0gPSBoYXNDaGlsZHJlbjsKICAgIHRoaXNbX3BhcmVudF0gPSBudWxsOwogICAgdGhpc1tfY2hpbGRyZW5dID0gW107CiAgICB0aGlzWyR1aWRdID0gYCR7bmFtZX0ke3VpZCsrfWA7CiAgICB0aGlzWyRnbG9iYWxEYXRhXSA9IG51bGw7CiAgfQogIGdldCBpc1hGQU9iamVjdCgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBnZXQgaXNYRkFPYmplY3RBcnJheSgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgY3JlYXRlTm9kZXMocGF0aCkgewogICAgbGV0IHJvb3QgPSB0aGlzLAogICAgICBub2RlID0gbnVsbDsKICAgIGZvciAoY29uc3QgewogICAgICBuYW1lLAogICAgICBpbmRleAogICAgfSBvZiBwYXRoKSB7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGlzRmluaXRlKGluZGV4KSA/IGluZGV4IDogMDsgaSA8PSBpaTsgaSsrKSB7CiAgICAgICAgY29uc3QgbnNJZCA9IHJvb3RbJG5hbWVzcGFjZUlkXSA9PT0gTlNfREFUQVNFVFMgPyAtMSA6IHJvb3RbJG5hbWVzcGFjZUlkXTsKICAgICAgICBub2RlID0gbmV3IFhtbE9iamVjdChuc0lkLCBuYW1lKTsKICAgICAgICByb290WyRhcHBlbmRDaGlsZF0obm9kZSk7CiAgICAgIH0KICAgICAgcm9vdCA9IG5vZGU7CiAgICB9CiAgICByZXR1cm4gbm9kZTsKICB9CiAgWyRvbkNoaWxkXShjaGlsZCkgewogICAgaWYgKCF0aGlzW19oYXNDaGlsZHJlbl0gfHwgIXRoaXNbJG9uQ2hpbGRDaGVja10oY2hpbGQpKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGNvbnN0IG5hbWUgPSBjaGlsZFskbm9kZU5hbWVdOwogICAgY29uc3Qgbm9kZSA9IHRoaXNbbmFtZV07CiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIFhGQU9iamVjdEFycmF5KSB7CiAgICAgIGlmIChub2RlLnB1c2goY2hpbGQpKSB7CiAgICAgICAgdGhpc1skYXBwZW5kQ2hpbGRdKGNoaWxkKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgaWYgKG5vZGUgIT09IG51bGwpIHsKICAgICAgICB0aGlzWyRyZW1vdmVDaGlsZF0obm9kZSk7CiAgICAgIH0KICAgICAgdGhpc1tuYW1lXSA9IGNoaWxkOwogICAgICB0aGlzWyRhcHBlbmRDaGlsZF0oY2hpbGQpOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGxldCBpZCA9ICIiOwogICAgaWYgKHRoaXMuaWQpIHsKICAgICAgaWQgPSBgIChpZDogJHt0aGlzLmlkfSlgOwogICAgfSBlbHNlIGlmICh0aGlzLm5hbWUpIHsKICAgICAgaWQgPSBgIChuYW1lOiAke3RoaXMubmFtZX0gJHt0aGlzLmgudmFsdWV9KWA7CiAgICB9CiAgICB3YXJuKGBYRkEgLSBub2RlICIke3RoaXNbJG5vZGVOYW1lXX0iJHtpZH0gaGFzIGFscmVhZHkgZW5vdWdoICIke25hbWV9IiFgKTsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgWyRvbkNoaWxkQ2hlY2tdKGNoaWxkKSB7CiAgICByZXR1cm4gdGhpcy5oYXNPd25Qcm9wZXJ0eShjaGlsZFskbm9kZU5hbWVdKSAmJiBjaGlsZFskbmFtZXNwYWNlSWRdID09PSB0aGlzWyRuYW1lc3BhY2VJZF07CiAgfQogIFskaXNOc0Fnbm9zdGljXSgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgWyRhY2NlcHRXaGl0ZXNwYWNlXSgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgWyRpc0NEQVRBWG1sXSgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgWyRpc0JpbmRhYmxlXSgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgWyRwb3BQYXJhXSgpIHsKICAgIGlmICh0aGlzLnBhcmEpIHsKICAgICAgdGhpc1skZ2V0VGVtcGxhdGVSb290XSgpWyRleHRyYV0ucGFyYVN0YWNrLnBvcCgpOwogICAgfQogIH0KICBbJHB1c2hQYXJhXSgpIHsKICAgIHRoaXNbJGdldFRlbXBsYXRlUm9vdF0oKVskZXh0cmFdLnBhcmFTdGFjay5wdXNoKHRoaXMucGFyYSk7CiAgfQogIFskc2V0SWRdKGlkcykgewogICAgaWYgKHRoaXMuaWQgJiYgdGhpc1skbmFtZXNwYWNlSWRdID09PSBOYW1lc3BhY2VJZHMudGVtcGxhdGUuaWQpIHsKICAgICAgaWRzLnNldCh0aGlzLmlkLCB0aGlzKTsKICAgIH0KICB9CiAgWyRnZXRUZW1wbGF0ZVJvb3RdKCkgewogICAgcmV0dXJuIHRoaXNbJGdsb2JhbERhdGFdLnRlbXBsYXRlOwogIH0KICBbJGlzU3BsaXR0YWJsZV0oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskaXNUaGVyZU1vcmVXaWR0aF0oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskYXBwZW5kQ2hpbGRdKGNoaWxkKSB7CiAgICBjaGlsZFtfcGFyZW50XSA9IHRoaXM7CiAgICB0aGlzW19jaGlsZHJlbl0ucHVzaChjaGlsZCk7CiAgICBpZiAoIWNoaWxkWyRnbG9iYWxEYXRhXSAmJiB0aGlzWyRnbG9iYWxEYXRhXSkgewogICAgICBjaGlsZFskZ2xvYmFsRGF0YV0gPSB0aGlzWyRnbG9iYWxEYXRhXTsKICAgIH0KICB9CiAgWyRyZW1vdmVDaGlsZF0oY2hpbGQpIHsKICAgIGNvbnN0IGkgPSB0aGlzW19jaGlsZHJlbl0uaW5kZXhPZihjaGlsZCk7CiAgICB0aGlzW19jaGlsZHJlbl0uc3BsaWNlKGksIDEpOwogIH0KICBbJGhhc1NldHRhYmxlVmFsdWVdKCkgewogICAgcmV0dXJuIHRoaXMuaGFzT3duUHJvcGVydHkoInZhbHVlIik7CiAgfQogIFskc2V0VmFsdWVdKF8pIHt9CiAgWyRvblRleHRdKF8pIHt9CiAgWyRmaW5hbGl6ZV0oKSB7fQogIFskY2xlYW5dKGJ1aWxkZXIpIHsKICAgIGRlbGV0ZSB0aGlzW19oYXNDaGlsZHJlbl07CiAgICBpZiAodGhpc1skY2xlYW51cF0pIHsKICAgICAgYnVpbGRlci5jbGVhbih0aGlzWyRjbGVhbnVwXSk7CiAgICAgIGRlbGV0ZSB0aGlzWyRjbGVhbnVwXTsKICAgIH0KICB9CiAgWyRpbmRleE9mXShjaGlsZCkgewogICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXS5pbmRleE9mKGNoaWxkKTsKICB9CiAgWyRpbnNlcnRBdF0oaSwgY2hpbGQpIHsKICAgIGNoaWxkW19wYXJlbnRdID0gdGhpczsKICAgIHRoaXNbX2NoaWxkcmVuXS5zcGxpY2UoaSwgMCwgY2hpbGQpOwogICAgaWYgKCFjaGlsZFskZ2xvYmFsRGF0YV0gJiYgdGhpc1skZ2xvYmFsRGF0YV0pIHsKICAgICAgY2hpbGRbJGdsb2JhbERhdGFdID0gdGhpc1skZ2xvYmFsRGF0YV07CiAgICB9CiAgfQogIFskaXNUcmFuc3BhcmVudF0oKSB7CiAgICByZXR1cm4gIXRoaXMubmFtZTsKICB9CiAgWyRsYXN0QXR0cmlidXRlXSgpIHsKICAgIHJldHVybiAiIjsKICB9CiAgWyR0ZXh0XSgpIHsKICAgIGlmICh0aGlzW19jaGlsZHJlbl0ubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiB0aGlzWyRjb250ZW50XTsKICAgIH0KICAgIHJldHVybiB0aGlzW19jaGlsZHJlbl0ubWFwKGMgPT4gY1skdGV4dF0oKSkuam9pbigiIik7CiAgfQogIGdldCBbX2F0dHJpYnV0ZU5hbWVzXSgpIHsKICAgIGNvbnN0IHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHRoaXMpOwogICAgaWYgKCFwcm90by5fYXR0cmlidXRlcykgewogICAgICBjb25zdCBhdHRyaWJ1dGVzID0gcHJvdG8uX2F0dHJpYnV0ZXMgPSBuZXcgU2V0KCk7CiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSkgewogICAgICAgIGlmICh0aGlzW25hbWVdID09PSBudWxsIHx8IHRoaXNbbmFtZV0gaW5zdGFuY2VvZiBYRkFPYmplY3QgfHwgdGhpc1tuYW1lXSBpbnN0YW5jZW9mIFhGQU9iamVjdEFycmF5KSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgYXR0cmlidXRlcy5hZGQobmFtZSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgX2F0dHJpYnV0ZU5hbWVzLCBwcm90by5fYXR0cmlidXRlcyk7CiAgfQogIFskaXNEZXNjZW5kZW50XShwYXJlbnQpIHsKICAgIGxldCBub2RlID0gdGhpczsKICAgIHdoaWxlIChub2RlKSB7CiAgICAgIGlmIChub2RlID09PSBwYXJlbnQpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBub2RlID0gbm9kZVskZ2V0UGFyZW50XSgpOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICBbJGdldFBhcmVudF0oKSB7CiAgICByZXR1cm4gdGhpc1tfcGFyZW50XTsKICB9CiAgWyRnZXRTdWJmb3JtUGFyZW50XSgpIHsKICAgIHJldHVybiB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgfQogIFskZ2V0Q2hpbGRyZW5dKG5hbWUgPSBudWxsKSB7CiAgICBpZiAoIW5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXTsKICAgIH0KICAgIHJldHVybiB0aGlzW25hbWVdOwogIH0KICBbJGR1bXBdKCkgewogICAgY29uc3QgZHVtcGVkID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGlmICh0aGlzWyRjb250ZW50XSkgewogICAgICBkdW1wZWQuJGNvbnRlbnQgPSB0aGlzWyRjb250ZW50XTsKICAgIH0KICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSkgewogICAgICBjb25zdCB2YWx1ZSA9IHRoaXNbbmFtZV07CiAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFhGQU9iamVjdCkgewogICAgICAgIGR1bXBlZFtuYW1lXSA9IHZhbHVlWyRkdW1wXSgpOwogICAgICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgWEZBT2JqZWN0QXJyYXkpIHsKICAgICAgICBpZiAoIXZhbHVlLmlzRW1wdHkoKSkgewogICAgICAgICAgZHVtcGVkW25hbWVdID0gdmFsdWUuZHVtcCgpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBkdW1wZWRbbmFtZV0gPSB2YWx1ZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGR1bXBlZDsKICB9CiAgWyR0b1N0eWxlXSgpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBbJHRvSFRNTF0oKSB7CiAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICB9CiAgKlskZ2V0Q29udGFpbmVkQ2hpbGRyZW5dKCkgewogICAgZm9yIChjb25zdCBub2RlIG9mIHRoaXNbJGdldENoaWxkcmVuXSgpKSB7CiAgICAgIHlpZWxkIG5vZGU7CiAgICB9CiAgfQogICpbX2ZpbHRlcmVkQ2hpbGRyZW5HZW5lcmF0b3JdKGZpbHRlciwgaW5jbHVkZSkgewogICAgZm9yIChjb25zdCBub2RlIG9mIHRoaXNbJGdldENvbnRhaW5lZENoaWxkcmVuXSgpKSB7CiAgICAgIGlmICghZmlsdGVyIHx8IGluY2x1ZGUgPT09IGZpbHRlci5oYXMobm9kZVskbm9kZU5hbWVdKSkgewogICAgICAgIGNvbnN0IGF2YWlsYWJsZVNwYWNlID0gdGhpc1skZ2V0QXZhaWxhYmxlU3BhY2VdKCk7CiAgICAgICAgY29uc3QgcmVzID0gbm9kZVskdG9IVE1MXShhdmFpbGFibGVTcGFjZSk7CiAgICAgICAgaWYgKCFyZXMuc3VjY2VzcykgewogICAgICAgICAgdGhpc1skZXh0cmFdLmZhaWxpbmdOb2RlID0gbm9kZTsKICAgICAgICB9CiAgICAgICAgeWllbGQgcmVzOwogICAgICB9CiAgICB9CiAgfQogIFskZmx1c2hIVE1MXSgpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBbJGFkZEhUTUxdKGh0bWwsIGJib3gpIHsKICAgIHRoaXNbJGV4dHJhXS5jaGlsZHJlbi5wdXNoKGh0bWwpOwogIH0KICBbJGdldEF2YWlsYWJsZVNwYWNlXSgpIHt9CiAgWyRjaGlsZHJlblRvSFRNTF0oewogICAgZmlsdGVyID0gbnVsbCwKICAgIGluY2x1ZGUgPSB0cnVlCiAgfSkgewogICAgaWYgKCF0aGlzWyRleHRyYV0uZ2VuZXJhdG9yKSB7CiAgICAgIHRoaXNbJGV4dHJhXS5nZW5lcmF0b3IgPSB0aGlzW19maWx0ZXJlZENoaWxkcmVuR2VuZXJhdG9yXShmaWx0ZXIsIGluY2x1ZGUpOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgYXZhaWxhYmxlU3BhY2UgPSB0aGlzWyRnZXRBdmFpbGFibGVTcGFjZV0oKTsKICAgICAgY29uc3QgcmVzID0gdGhpc1skZXh0cmFdLmZhaWxpbmdOb2RlWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKTsKICAgICAgaWYgKCFyZXMuc3VjY2VzcykgewogICAgICAgIHJldHVybiByZXM7CiAgICAgIH0KICAgICAgaWYgKHJlcy5odG1sKSB7CiAgICAgICAgdGhpc1skYWRkSFRNTF0ocmVzLmh0bWwsIHJlcy5iYm94KTsKICAgICAgfQogICAgICBkZWxldGUgdGhpc1skZXh0cmFdLmZhaWxpbmdOb2RlOwogICAgfQogICAgd2hpbGUgKHRydWUpIHsKICAgICAgY29uc3QgZ2VuID0gdGhpc1skZXh0cmFdLmdlbmVyYXRvci5uZXh0KCk7CiAgICAgIGlmIChnZW4uZG9uZSkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNvbnN0IHJlcyA9IGdlbi52YWx1ZTsKICAgICAgaWYgKCFyZXMuc3VjY2VzcykgewogICAgICAgIHJldHVybiByZXM7CiAgICAgIH0KICAgICAgaWYgKHJlcy5odG1sKSB7CiAgICAgICAgdGhpc1skYWRkSFRNTF0ocmVzLmh0bWwsIHJlcy5iYm94KTsKICAgICAgfQogICAgfQogICAgdGhpc1skZXh0cmFdLmdlbmVyYXRvciA9IG51bGw7CiAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICB9CiAgWyRzZXRTZXRBdHRyaWJ1dGVzXShhdHRyaWJ1dGVzKSB7CiAgICB0aGlzW19zZXRBdHRyaWJ1dGVzXSA9IG5ldyBTZXQoT2JqZWN0LmtleXMoYXR0cmlidXRlcykpOwogIH0KICBbX2dldFVuc2V0QXR0cmlidXRlc10ocHJvdG9BdHRyaWJ1dGVzKSB7CiAgICBjb25zdCBhbGxBdHRyID0gdGhpc1tfYXR0cmlidXRlTmFtZXNdOwogICAgY29uc3Qgc2V0QXR0ciA9IHRoaXNbX3NldEF0dHJpYnV0ZXNdOwogICAgcmV0dXJuIFsuLi5wcm90b0F0dHJpYnV0ZXNdLmZpbHRlcih4ID0+IGFsbEF0dHIuaGFzKHgpICYmICFzZXRBdHRyLmhhcyh4KSk7CiAgfQogIFskcmVzb2x2ZVByb3RvdHlwZXNdKGlkcywgYW5jZXN0b3JzID0gbmV3IFNldCgpKSB7CiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXNbX2NoaWxkcmVuXSkgewogICAgICBjaGlsZFtfcmVzb2x2ZVByb3RvdHlwZXNIZWxwZXJdKGlkcywgYW5jZXN0b3JzKTsKICAgIH0KICB9CiAgW19yZXNvbHZlUHJvdG90eXBlc0hlbHBlcl0oaWRzLCBhbmNlc3RvcnMpIHsKICAgIGNvbnN0IHByb3RvID0gdGhpc1tfZ2V0UHJvdG90eXBlXShpZHMsIGFuY2VzdG9ycyk7CiAgICBpZiAocHJvdG8pIHsKICAgICAgdGhpc1tfYXBwbHlQcm90b3R5cGVdKHByb3RvLCBpZHMsIGFuY2VzdG9ycyk7CiAgICB9IGVsc2UgewogICAgICB0aGlzWyRyZXNvbHZlUHJvdG90eXBlc10oaWRzLCBhbmNlc3RvcnMpOwogICAgfQogIH0KICBbX2dldFByb3RvdHlwZV0oaWRzLCBhbmNlc3RvcnMpIHsKICAgIGNvbnN0IHsKICAgICAgdXNlLAogICAgICB1c2VocmVmCiAgICB9ID0gdGhpczsKICAgIGlmICghdXNlICYmICF1c2VocmVmKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgbGV0IHByb3RvID0gbnVsbDsKICAgIGxldCBzb21FeHByZXNzaW9uID0gbnVsbDsKICAgIGxldCBpZCA9IG51bGw7CiAgICBsZXQgcmVmID0gdXNlOwogICAgaWYgKHVzZWhyZWYpIHsKICAgICAgcmVmID0gdXNlaHJlZjsKICAgICAgaWYgKHVzZWhyZWYuc3RhcnRzV2l0aCgiI3NvbSgiKSAmJiB1c2VocmVmLmVuZHNXaXRoKCIpIikpIHsKICAgICAgICBzb21FeHByZXNzaW9uID0gdXNlaHJlZi5zbGljZSgiI3NvbSgiLmxlbmd0aCwgLTEpOwogICAgICB9IGVsc2UgaWYgKHVzZWhyZWYuc3RhcnRzV2l0aCgiLiNzb20oIikgJiYgdXNlaHJlZi5lbmRzV2l0aCgiKSIpKSB7CiAgICAgICAgc29tRXhwcmVzc2lvbiA9IHVzZWhyZWYuc2xpY2UoIi4jc29tKCIubGVuZ3RoLCAtMSk7CiAgICAgIH0gZWxzZSBpZiAodXNlaHJlZi5zdGFydHNXaXRoKCIjIikpIHsKICAgICAgICBpZCA9IHVzZWhyZWYuc2xpY2UoMSk7CiAgICAgIH0gZWxzZSBpZiAodXNlaHJlZi5zdGFydHNXaXRoKCIuIyIpKSB7CiAgICAgICAgaWQgPSB1c2VocmVmLnNsaWNlKDIpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKHVzZS5zdGFydHNXaXRoKCIjIikpIHsKICAgICAgaWQgPSB1c2Uuc2xpY2UoMSk7CiAgICB9IGVsc2UgewogICAgICBzb21FeHByZXNzaW9uID0gdXNlOwogICAgfQogICAgdGhpcy51c2UgPSB0aGlzLnVzZWhyZWYgPSAiIjsKICAgIGlmIChpZCkgewogICAgICBwcm90byA9IGlkcy5nZXQoaWQpOwogICAgfSBlbHNlIHsKICAgICAgcHJvdG8gPSBzZWFyY2hOb2RlKGlkcy5nZXQoJHJvb3QpLCB0aGlzLCBzb21FeHByZXNzaW9uLCB0cnVlLCBmYWxzZSk7CiAgICAgIGlmIChwcm90bykgewogICAgICAgIHByb3RvID0gcHJvdG9bMF07CiAgICAgIH0KICAgIH0KICAgIGlmICghcHJvdG8pIHsKICAgICAgd2FybihgWEZBIC0gSW52YWxpZCBwcm90b3R5cGUgcmVmZXJlbmNlOiAke3JlZn0uYCk7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKHByb3RvWyRub2RlTmFtZV0gIT09IHRoaXNbJG5vZGVOYW1lXSkgewogICAgICB3YXJuKGBYRkEgLSBJbmNvbXBhdGlibGUgcHJvdG90eXBlOiAke3Byb3RvWyRub2RlTmFtZV19ICE9PSAke3RoaXNbJG5vZGVOYW1lXX0uYCk7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKGFuY2VzdG9ycy5oYXMocHJvdG8pKSB7CiAgICAgIHdhcm4oYFhGQSAtIEN5Y2xlIGRldGVjdGVkIGluIHByb3RvdHlwZXMgdXNlLmApOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGFuY2VzdG9ycy5hZGQocHJvdG8pOwogICAgY29uc3QgcHJvdG9Qcm90byA9IHByb3RvW19nZXRQcm90b3R5cGVdKGlkcywgYW5jZXN0b3JzKTsKICAgIGlmIChwcm90b1Byb3RvKSB7CiAgICAgIHByb3RvW19hcHBseVByb3RvdHlwZV0ocHJvdG9Qcm90bywgaWRzLCBhbmNlc3RvcnMpOwogICAgfQogICAgcHJvdG9bJHJlc29sdmVQcm90b3R5cGVzXShpZHMsIGFuY2VzdG9ycyk7CiAgICBhbmNlc3RvcnMuZGVsZXRlKHByb3RvKTsKICAgIHJldHVybiBwcm90bzsKICB9CiAgW19hcHBseVByb3RvdHlwZV0ocHJvdG8sIGlkcywgYW5jZXN0b3JzKSB7CiAgICBpZiAoYW5jZXN0b3JzLmhhcyhwcm90bykpIHsKICAgICAgd2FybihgWEZBIC0gQ3ljbGUgZGV0ZWN0ZWQgaW4gcHJvdG90eXBlcyB1c2UuYCk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICghdGhpc1skY29udGVudF0gJiYgcHJvdG9bJGNvbnRlbnRdKSB7CiAgICAgIHRoaXNbJGNvbnRlbnRdID0gcHJvdG9bJGNvbnRlbnRdOwogICAgfQogICAgY29uc3QgbmV3QW5jZXN0b3JzID0gbmV3IFNldChhbmNlc3RvcnMpOwogICAgbmV3QW5jZXN0b3JzLmFkZChwcm90byk7CiAgICBmb3IgKGNvbnN0IHVuc2V0QXR0ck5hbWUgb2YgdGhpc1tfZ2V0VW5zZXRBdHRyaWJ1dGVzXShwcm90b1tfc2V0QXR0cmlidXRlc10pKSB7CiAgICAgIHRoaXNbdW5zZXRBdHRyTmFtZV0gPSBwcm90b1t1bnNldEF0dHJOYW1lXTsKICAgICAgaWYgKHRoaXNbX3NldEF0dHJpYnV0ZXNdKSB7CiAgICAgICAgdGhpc1tfc2V0QXR0cmlidXRlc10uYWRkKHVuc2V0QXR0ck5hbWUpOwogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykpIHsKICAgICAgaWYgKHRoaXNbX2F0dHJpYnV0ZU5hbWVzXS5oYXMobmFtZSkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB2YWx1ZSA9IHRoaXNbbmFtZV07CiAgICAgIGNvbnN0IHByb3RvVmFsdWUgPSBwcm90b1tuYW1lXTsKICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgWEZBT2JqZWN0QXJyYXkpIHsKICAgICAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHZhbHVlW19jaGlsZHJlbl0pIHsKICAgICAgICAgIGNoaWxkW19yZXNvbHZlUHJvdG90eXBlc0hlbHBlcl0oaWRzLCBhbmNlc3RvcnMpOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gdmFsdWVbX2NoaWxkcmVuXS5sZW5ndGgsIGlpID0gcHJvdG9WYWx1ZVtfY2hpbGRyZW5dLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgIGNvbnN0IGNoaWxkID0gcHJvdG9bX2NoaWxkcmVuXVtpXVskY2xvbmVdKCk7CiAgICAgICAgICBpZiAodmFsdWUucHVzaChjaGlsZCkpIHsKICAgICAgICAgICAgY2hpbGRbX3BhcmVudF0gPSB0aGlzOwogICAgICAgICAgICB0aGlzW19jaGlsZHJlbl0ucHVzaChjaGlsZCk7CiAgICAgICAgICAgIGNoaWxkW19yZXNvbHZlUHJvdG90eXBlc0hlbHBlcl0oaWRzLCBhbmNlc3RvcnMpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICh2YWx1ZSAhPT0gbnVsbCkgewogICAgICAgIHZhbHVlWyRyZXNvbHZlUHJvdG90eXBlc10oaWRzLCBhbmNlc3RvcnMpOwogICAgICAgIGlmIChwcm90b1ZhbHVlKSB7CiAgICAgICAgICB2YWx1ZVtfYXBwbHlQcm90b3R5cGVdKHByb3RvVmFsdWUsIGlkcywgYW5jZXN0b3JzKTsKICAgICAgICB9CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKHByb3RvVmFsdWUgIT09IG51bGwpIHsKICAgICAgICBjb25zdCBjaGlsZCA9IHByb3RvVmFsdWVbJGNsb25lXSgpOwogICAgICAgIGNoaWxkW19wYXJlbnRdID0gdGhpczsKICAgICAgICB0aGlzW25hbWVdID0gY2hpbGQ7CiAgICAgICAgdGhpc1tfY2hpbGRyZW5dLnB1c2goY2hpbGQpOwogICAgICAgIGNoaWxkW19yZXNvbHZlUHJvdG90eXBlc0hlbHBlcl0oaWRzLCBhbmNlc3RvcnMpOwogICAgICB9CiAgICB9CiAgfQogIHN0YXRpYyBbX2Nsb25lQXR0cmlidXRlXShvYmopIHsKICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHsKICAgICAgcmV0dXJuIG9iai5tYXAoeCA9PiBYRkFPYmplY3RbX2Nsb25lQXR0cmlidXRlXSh4KSk7CiAgICB9CiAgICBpZiAodHlwZW9mIG9iaiA9PT0gIm9iamVjdCIgJiYgb2JqICE9PSBudWxsKSB7CiAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCBvYmopOwogICAgfQogICAgcmV0dXJuIG9iajsKICB9CiAgWyRjbG9uZV0oKSB7CiAgICBjb25zdCBjbG9uZSA9IE9iamVjdC5jcmVhdGUoT2JqZWN0LmdldFByb3RvdHlwZU9mKHRoaXMpKTsKICAgIGZvciAoY29uc3QgJHN5bWJvbCBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHRoaXMpKSB7CiAgICAgIHRyeSB7CiAgICAgICAgY2xvbmVbJHN5bWJvbF0gPSB0aGlzWyRzeW1ib2xdOwogICAgICB9IGNhdGNoIHsKICAgICAgICBzaGFkb3coY2xvbmUsICRzeW1ib2wsIHRoaXNbJHN5bWJvbF0pOwogICAgICB9CiAgICB9CiAgICBjbG9uZVskdWlkXSA9IGAke2Nsb25lWyRub2RlTmFtZV19JHt1aWQrK31gOwogICAgY2xvbmVbX2NoaWxkcmVuXSA9IFtdOwogICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKSB7CiAgICAgIGlmICh0aGlzW19hdHRyaWJ1dGVOYW1lc10uaGFzKG5hbWUpKSB7CiAgICAgICAgY2xvbmVbbmFtZV0gPSBYRkFPYmplY3RbX2Nsb25lQXR0cmlidXRlXSh0aGlzW25hbWVdKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB2YWx1ZSA9IHRoaXNbbmFtZV07CiAgICAgIGNsb25lW25hbWVdID0gdmFsdWUgaW5zdGFuY2VvZiBYRkFPYmplY3RBcnJheSA/IG5ldyBYRkFPYmplY3RBcnJheSh2YWx1ZVtfbWF4XSkgOiBudWxsOwogICAgfQogICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzW19jaGlsZHJlbl0pIHsKICAgICAgY29uc3QgbmFtZSA9IGNoaWxkWyRub2RlTmFtZV07CiAgICAgIGNvbnN0IGNsb25lZENoaWxkID0gY2hpbGRbJGNsb25lXSgpOwogICAgICBjbG9uZVtfY2hpbGRyZW5dLnB1c2goY2xvbmVkQ2hpbGQpOwogICAgICBjbG9uZWRDaGlsZFtfcGFyZW50XSA9IGNsb25lOwogICAgICBpZiAoY2xvbmVbbmFtZV0gPT09IG51bGwpIHsKICAgICAgICBjbG9uZVtuYW1lXSA9IGNsb25lZENoaWxkOwogICAgICB9IGVsc2UgewogICAgICAgIGNsb25lW25hbWVdW19jaGlsZHJlbl0ucHVzaChjbG9uZWRDaGlsZCk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBjbG9uZTsKICB9CiAgWyRnZXRDaGlsZHJlbl0obmFtZSA9IG51bGwpIHsKICAgIGlmICghbmFtZSkgewogICAgICByZXR1cm4gdGhpc1tfY2hpbGRyZW5dOwogICAgfQogICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXS5maWx0ZXIoYyA9PiBjWyRub2RlTmFtZV0gPT09IG5hbWUpOwogIH0KICBbJGdldENoaWxkcmVuQnlDbGFzc10obmFtZSkgewogICAgcmV0dXJuIHRoaXNbbmFtZV07CiAgfQogIFskZ2V0Q2hpbGRyZW5CeU5hbWVdKG5hbWUsIGFsbFRyYW5zcGFyZW50LCBmaXJzdCA9IHRydWUpIHsKICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXNbJGdldENoaWxkcmVuQnlOYW1lSXRdKG5hbWUsIGFsbFRyYW5zcGFyZW50LCBmaXJzdCkpOwogIH0KICAqWyRnZXRDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCBhbGxUcmFuc3BhcmVudCwgZmlyc3QgPSB0cnVlKSB7CiAgICBpZiAobmFtZSA9PT0gInBhcmVudCIpIHsKICAgICAgeWllbGQgdGhpc1tfcGFyZW50XTsKICAgICAgcmV0dXJuOwogICAgfQogICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzW19jaGlsZHJlbl0pIHsKICAgICAgaWYgKGNoaWxkWyRub2RlTmFtZV0gPT09IG5hbWUpIHsKICAgICAgICB5aWVsZCBjaGlsZDsKICAgICAgfQogICAgICBpZiAoY2hpbGQubmFtZSA9PT0gbmFtZSkgewogICAgICAgIHlpZWxkIGNoaWxkOwogICAgICB9CiAgICAgIGlmIChhbGxUcmFuc3BhcmVudCB8fCBjaGlsZFskaXNUcmFuc3BhcmVudF0oKSkgewogICAgICAgIHlpZWxkKiBjaGlsZFskZ2V0Q2hpbGRyZW5CeU5hbWVJdF0obmFtZSwgYWxsVHJhbnNwYXJlbnQsIGZhbHNlKTsKICAgICAgfQogICAgfQogICAgaWYgKGZpcnN0ICYmIHRoaXNbX2F0dHJpYnV0ZU5hbWVzXS5oYXMobmFtZSkpIHsKICAgICAgeWllbGQgbmV3IFhGQUF0dHJpYnV0ZSh0aGlzLCBuYW1lLCB0aGlzW25hbWVdKTsKICAgIH0KICB9Cn0KY2xhc3MgWEZBT2JqZWN0QXJyYXkgewogIGNvbnN0cnVjdG9yKG1heCA9IEluZmluaXR5KSB7CiAgICB0aGlzW19tYXhdID0gbWF4OwogICAgdGhpc1tfY2hpbGRyZW5dID0gW107CiAgfQogIGdldCBpc1hGQU9iamVjdCgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgZ2V0IGlzWEZBT2JqZWN0QXJyYXkoKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgcHVzaChjaGlsZCkgewogICAgY29uc3QgbGVuID0gdGhpc1tfY2hpbGRyZW5dLmxlbmd0aDsKICAgIGlmIChsZW4gPD0gdGhpc1tfbWF4XSkgewogICAgICB0aGlzW19jaGlsZHJlbl0ucHVzaChjaGlsZCk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgd2FybihgWEZBIC0gbm9kZSAiJHtjaGlsZFskbm9kZU5hbWVdfSIgYWNjZXB0cyBubyBtb3JlIHRoYW4gJHt0aGlzW19tYXhdfSBjaGlsZHJlbmApOwogICAgcmV0dXJuIGZhbHNlOwogIH0KICBpc0VtcHR5KCkgewogICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXS5sZW5ndGggPT09IDA7CiAgfQogIGR1bXAoKSB7CiAgICByZXR1cm4gdGhpc1tfY2hpbGRyZW5dLmxlbmd0aCA9PT0gMSA/IHRoaXNbX2NoaWxkcmVuXVswXVskZHVtcF0oKSA6IHRoaXNbX2NoaWxkcmVuXS5tYXAoeCA9PiB4WyRkdW1wXSgpKTsKICB9CiAgWyRjbG9uZV0oKSB7CiAgICBjb25zdCBjbG9uZSA9IG5ldyBYRkFPYmplY3RBcnJheSh0aGlzW19tYXhdKTsKICAgIGNsb25lW19jaGlsZHJlbl0gPSB0aGlzW19jaGlsZHJlbl0ubWFwKGMgPT4gY1skY2xvbmVdKCkpOwogICAgcmV0dXJuIGNsb25lOwogIH0KICBnZXQgY2hpbGRyZW4oKSB7CiAgICByZXR1cm4gdGhpc1tfY2hpbGRyZW5dOwogIH0KICBjbGVhcigpIHsKICAgIHRoaXNbX2NoaWxkcmVuXS5sZW5ndGggPSAwOwogIH0KfQpjbGFzcyBYRkFBdHRyaWJ1dGUgewogIGNvbnN0cnVjdG9yKG5vZGUsIG5hbWUsIHZhbHVlKSB7CiAgICB0aGlzW19wYXJlbnRdID0gbm9kZTsKICAgIHRoaXNbJG5vZGVOYW1lXSA9IG5hbWU7CiAgICB0aGlzWyRjb250ZW50XSA9IHZhbHVlOwogICAgdGhpc1skY29uc3VtZWRdID0gZmFsc2U7CiAgICB0aGlzWyR1aWRdID0gYGF0dHJpYnV0ZSR7dWlkKyt9YDsKICB9CiAgWyRnZXRQYXJlbnRdKCkgewogICAgcmV0dXJuIHRoaXNbX3BhcmVudF07CiAgfQogIFskaXNEYXRhVmFsdWVdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIFskZ2V0RGF0YVZhbHVlXSgpIHsKICAgIHJldHVybiB0aGlzWyRjb250ZW50XS50cmltKCk7CiAgfQogIFskc2V0VmFsdWVdKHZhbHVlKSB7CiAgICB2YWx1ZSA9IHZhbHVlLnZhbHVlIHx8ICIiOwogICAgdGhpc1skY29udGVudF0gPSB2YWx1ZS50b1N0cmluZygpOwogIH0KICBbJHRleHRdKCkgewogICAgcmV0dXJuIHRoaXNbJGNvbnRlbnRdOwogIH0KICBbJGlzRGVzY2VuZGVudF0ocGFyZW50KSB7CiAgICByZXR1cm4gdGhpc1tfcGFyZW50XSA9PT0gcGFyZW50IHx8IHRoaXNbX3BhcmVudF1bJGlzRGVzY2VuZGVudF0ocGFyZW50KTsKICB9Cn0KY2xhc3MgWG1sT2JqZWN0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3Rvcihuc0lkLCBuYW1lLCBhdHRyaWJ1dGVzID0ge30pIHsKICAgIHN1cGVyKG5zSWQsIG5hbWUpOwogICAgdGhpc1skY29udGVudF0gPSAiIjsKICAgIHRoaXNbX2RhdGFWYWx1ZV0gPSBudWxsOwogICAgaWYgKG5hbWUgIT09ICIjdGV4dCIpIHsKICAgICAgY29uc3QgbWFwID0gbmV3IE1hcCgpOwogICAgICB0aGlzW19hdHRyaWJ1dGVzXSA9IG1hcDsKICAgICAgZm9yIChjb25zdCBbYXR0ck5hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhhdHRyaWJ1dGVzKSkgewogICAgICAgIG1hcC5zZXQoYXR0ck5hbWUsIG5ldyBYRkFBdHRyaWJ1dGUodGhpcywgYXR0ck5hbWUsIHZhbHVlKSk7CiAgICAgIH0KICAgICAgaWYgKGF0dHJpYnV0ZXMuaGFzT3duUHJvcGVydHkoJG5zQXR0cmlidXRlcykpIHsKICAgICAgICBjb25zdCBkYXRhTm9kZSA9IGF0dHJpYnV0ZXNbJG5zQXR0cmlidXRlc10ueGZhLmRhdGFOb2RlOwogICAgICAgIGlmIChkYXRhTm9kZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBpZiAoZGF0YU5vZGUgPT09ICJkYXRhR3JvdXAiKSB7CiAgICAgICAgICAgIHRoaXNbX2RhdGFWYWx1ZV0gPSBmYWxzZTsKICAgICAgICAgIH0gZWxzZSBpZiAoZGF0YU5vZGUgPT09ICJkYXRhVmFsdWUiKSB7CiAgICAgICAgICAgIHRoaXNbX2RhdGFWYWx1ZV0gPSB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogICAgdGhpc1skY29uc3VtZWRdID0gZmFsc2U7CiAgfQogIFskdG9TdHJpbmddKGJ1ZikgewogICAgY29uc3QgdGFnTmFtZSA9IHRoaXNbJG5vZGVOYW1lXTsKICAgIGlmICh0YWdOYW1lID09PSAiI3RleHQiKSB7CiAgICAgIGJ1Zi5wdXNoKGVuY29kZVRvWG1sU3RyaW5nKHRoaXNbJGNvbnRlbnRdKSk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHV0ZjhUYWdOYW1lID0gdXRmOFN0cmluZ1RvU3RyaW5nKHRhZ05hbWUpOwogICAgY29uc3QgcHJlZml4ID0gdGhpc1skbmFtZXNwYWNlSWRdID09PSBOU19EQVRBU0VUUyA/ICJ4ZmE6IiA6ICIiOwogICAgYnVmLnB1c2goYDwke3ByZWZpeH0ke3V0ZjhUYWdOYW1lfWApOwogICAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIHRoaXNbX2F0dHJpYnV0ZXNdLmVudHJpZXMoKSkgewogICAgICBjb25zdCB1dGY4TmFtZSA9IHV0ZjhTdHJpbmdUb1N0cmluZyhuYW1lKTsKICAgICAgYnVmLnB1c2goYCAke3V0ZjhOYW1lfT0iJHtlbmNvZGVUb1htbFN0cmluZyh2YWx1ZVskY29udGVudF0pfSJgKTsKICAgIH0KICAgIGlmICh0aGlzW19kYXRhVmFsdWVdICE9PSBudWxsKSB7CiAgICAgIGlmICh0aGlzW19kYXRhVmFsdWVdKSB7CiAgICAgICAgYnVmLnB1c2goYCB4ZmE6ZGF0YU5vZGU9ImRhdGFWYWx1ZSJgKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBidWYucHVzaChgIHhmYTpkYXRhTm9kZT0iZGF0YUdyb3VwImApOwogICAgICB9CiAgICB9CiAgICBpZiAoIXRoaXNbJGNvbnRlbnRdICYmIHRoaXNbX2NoaWxkcmVuXS5sZW5ndGggPT09IDApIHsKICAgICAgYnVmLnB1c2goIi8+Iik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGJ1Zi5wdXNoKCI+Iik7CiAgICBpZiAodGhpc1skY29udGVudF0pIHsKICAgICAgaWYgKHR5cGVvZiB0aGlzWyRjb250ZW50XSA9PT0gInN0cmluZyIpIHsKICAgICAgICBidWYucHVzaChlbmNvZGVUb1htbFN0cmluZyh0aGlzWyRjb250ZW50XSkpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXNbJGNvbnRlbnRdWyR0b1N0cmluZ10oYnVmKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzW19jaGlsZHJlbl0pIHsKICAgICAgICBjaGlsZFskdG9TdHJpbmddKGJ1Zik7CiAgICAgIH0KICAgIH0KICAgIGJ1Zi5wdXNoKGA8LyR7cHJlZml4fSR7dXRmOFRhZ05hbWV9PmApOwogIH0KICBbJG9uQ2hpbGRdKGNoaWxkKSB7CiAgICBpZiAodGhpc1skY29udGVudF0pIHsKICAgICAgY29uc3Qgbm9kZSA9IG5ldyBYbWxPYmplY3QodGhpc1skbmFtZXNwYWNlSWRdLCAiI3RleHQiKTsKICAgICAgdGhpc1skYXBwZW5kQ2hpbGRdKG5vZGUpOwogICAgICBub2RlWyRjb250ZW50XSA9IHRoaXNbJGNvbnRlbnRdOwogICAgICB0aGlzWyRjb250ZW50XSA9ICIiOwogICAgfQogICAgdGhpc1skYXBwZW5kQ2hpbGRdKGNoaWxkKTsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJG9uVGV4dF0oc3RyKSB7CiAgICB0aGlzWyRjb250ZW50XSArPSBzdHI7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgaWYgKHRoaXNbJGNvbnRlbnRdICYmIHRoaXNbX2NoaWxkcmVuXS5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IG5vZGUgPSBuZXcgWG1sT2JqZWN0KHRoaXNbJG5hbWVzcGFjZUlkXSwgIiN0ZXh0Iik7CiAgICAgIHRoaXNbJGFwcGVuZENoaWxkXShub2RlKTsKICAgICAgbm9kZVskY29udGVudF0gPSB0aGlzWyRjb250ZW50XTsKICAgICAgZGVsZXRlIHRoaXNbJGNvbnRlbnRdOwogICAgfQogIH0KICBbJHRvSFRNTF0oKSB7CiAgICBpZiAodGhpc1skbm9kZU5hbWVdID09PSAiI3RleHQiKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICAgIG5hbWU6ICIjdGV4dCIsCiAgICAgICAgdmFsdWU6IHRoaXNbJGNvbnRlbnRdCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7CiAgfQogIFskZ2V0Q2hpbGRyZW5dKG5hbWUgPSBudWxsKSB7CiAgICBpZiAoIW5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXTsKICAgIH0KICAgIHJldHVybiB0aGlzW19jaGlsZHJlbl0uZmlsdGVyKGMgPT4gY1skbm9kZU5hbWVdID09PSBuYW1lKTsKICB9CiAgWyRnZXRBdHRyaWJ1dGVzXSgpIHsKICAgIHJldHVybiB0aGlzW19hdHRyaWJ1dGVzXTsKICB9CiAgWyRnZXRDaGlsZHJlbkJ5Q2xhc3NdKG5hbWUpIHsKICAgIGNvbnN0IHZhbHVlID0gdGhpc1tfYXR0cmlidXRlc10uZ2V0KG5hbWUpOwogICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQogICAgcmV0dXJuIHRoaXNbJGdldENoaWxkcmVuXShuYW1lKTsKICB9CiAgKlskZ2V0Q2hpbGRyZW5CeU5hbWVJdF0obmFtZSwgYWxsVHJhbnNwYXJlbnQpIHsKICAgIGNvbnN0IHZhbHVlID0gdGhpc1tfYXR0cmlidXRlc10uZ2V0KG5hbWUpOwogICAgaWYgKHZhbHVlKSB7CiAgICAgIHlpZWxkIHZhbHVlOwogICAgfQogICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzW19jaGlsZHJlbl0pIHsKICAgICAgaWYgKGNoaWxkWyRub2RlTmFtZV0gPT09IG5hbWUpIHsKICAgICAgICB5aWVsZCBjaGlsZDsKICAgICAgfQogICAgICBpZiAoYWxsVHJhbnNwYXJlbnQpIHsKICAgICAgICB5aWVsZCogY2hpbGRbJGdldENoaWxkcmVuQnlOYW1lSXRdKG5hbWUsIGFsbFRyYW5zcGFyZW50KTsKICAgICAgfQogICAgfQogIH0KICAqWyRnZXRBdHRyaWJ1dGVJdF0obmFtZSwgc2tpcENvbnN1bWVkKSB7CiAgICBjb25zdCB2YWx1ZSA9IHRoaXNbX2F0dHJpYnV0ZXNdLmdldChuYW1lKTsKICAgIGlmICh2YWx1ZSAmJiAoIXNraXBDb25zdW1lZCB8fCAhdmFsdWVbJGNvbnN1bWVkXSkpIHsKICAgICAgeWllbGQgdmFsdWU7CiAgICB9CiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXNbX2NoaWxkcmVuXSkgewogICAgICB5aWVsZCogY2hpbGRbJGdldEF0dHJpYnV0ZUl0XShuYW1lLCBza2lwQ29uc3VtZWQpOwogICAgfQogIH0KICAqWyRnZXRSZWFsQ2hpbGRyZW5CeU5hbWVJdF0obmFtZSwgYWxsVHJhbnNwYXJlbnQsIHNraXBDb25zdW1lZCkgewogICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzW19jaGlsZHJlbl0pIHsKICAgICAgaWYgKGNoaWxkWyRub2RlTmFtZV0gPT09IG5hbWUgJiYgKCFza2lwQ29uc3VtZWQgfHwgIWNoaWxkWyRjb25zdW1lZF0pKSB7CiAgICAgICAgeWllbGQgY2hpbGQ7CiAgICAgIH0KICAgICAgaWYgKGFsbFRyYW5zcGFyZW50KSB7CiAgICAgICAgeWllbGQqIGNoaWxkWyRnZXRSZWFsQ2hpbGRyZW5CeU5hbWVJdF0obmFtZSwgYWxsVHJhbnNwYXJlbnQsIHNraXBDb25zdW1lZCk7CiAgICAgIH0KICAgIH0KICB9CiAgWyRpc0RhdGFWYWx1ZV0oKSB7CiAgICBpZiAodGhpc1tfZGF0YVZhbHVlXSA9PT0gbnVsbCkgewogICAgICByZXR1cm4gdGhpc1tfY2hpbGRyZW5dLmxlbmd0aCA9PT0gMCB8fCB0aGlzW19jaGlsZHJlbl1bMF1bJG5hbWVzcGFjZUlkXSA9PT0gTmFtZXNwYWNlSWRzLnhodG1sLmlkOwogICAgfQogICAgcmV0dXJuIHRoaXNbX2RhdGFWYWx1ZV07CiAgfQogIFskZ2V0RGF0YVZhbHVlXSgpIHsKICAgIGlmICh0aGlzW19kYXRhVmFsdWVdID09PSBudWxsKSB7CiAgICAgIGlmICh0aGlzW19jaGlsZHJlbl0ubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIHRoaXNbJGNvbnRlbnRdLnRyaW0oKTsKICAgICAgfQogICAgICBpZiAodGhpc1tfY2hpbGRyZW5dWzBdWyRuYW1lc3BhY2VJZF0gPT09IE5hbWVzcGFjZUlkcy54aHRtbC5pZCkgewogICAgICAgIHJldHVybiB0aGlzW19jaGlsZHJlbl1bMF1bJHRleHRdKCkudHJpbSgpOwogICAgICB9CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcmV0dXJuIHRoaXNbJGNvbnRlbnRdLnRyaW0oKTsKICB9CiAgWyRzZXRWYWx1ZV0odmFsdWUpIHsKICAgIHZhbHVlID0gdmFsdWUudmFsdWUgfHwgIiI7CiAgICB0aGlzWyRjb250ZW50XSA9IHZhbHVlLnRvU3RyaW5nKCk7CiAgfQogIFskZHVtcF0oaGFzTlMgPSBmYWxzZSkgewogICAgY29uc3QgZHVtcGVkID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGlmIChoYXNOUykgewogICAgICBkdW1wZWQuJG5zID0gdGhpc1skbmFtZXNwYWNlSWRdOwogICAgfQogICAgaWYgKHRoaXNbJGNvbnRlbnRdKSB7CiAgICAgIGR1bXBlZC4kY29udGVudCA9IHRoaXNbJGNvbnRlbnRdOwogICAgfQogICAgZHVtcGVkLiRuYW1lID0gdGhpc1skbm9kZU5hbWVdOwogICAgZHVtcGVkLmNoaWxkcmVuID0gW107CiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXNbX2NoaWxkcmVuXSkgewogICAgICBkdW1wZWQuY2hpbGRyZW4ucHVzaChjaGlsZFskZHVtcF0oaGFzTlMpKTsKICAgIH0KICAgIGR1bXBlZC5hdHRyaWJ1dGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiB0aGlzW19hdHRyaWJ1dGVzXSkgewogICAgICBkdW1wZWQuYXR0cmlidXRlc1tuYW1lXSA9IHZhbHVlWyRjb250ZW50XTsKICAgIH0KICAgIHJldHVybiBkdW1wZWQ7CiAgfQp9CmNsYXNzIENvbnRlbnRPYmplY3QgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKG5zSWQsIG5hbWUpIHsKICAgIHN1cGVyKG5zSWQsIG5hbWUpOwogICAgdGhpc1skY29udGVudF0gPSAiIjsKICB9CiAgWyRvblRleHRdKHRleHQpIHsKICAgIHRoaXNbJGNvbnRlbnRdICs9IHRleHQ7CiAgfQogIFskZmluYWxpemVdKCkge30KfQpjbGFzcyBPcHRpb25PYmplY3QgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3Rvcihuc0lkLCBuYW1lLCBvcHRpb25zKSB7CiAgICBzdXBlcihuc0lkLCBuYW1lKTsKICAgIHRoaXNbX29wdGlvbnNdID0gb3B0aW9uczsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzWyRjb250ZW50XSA9IGdldEtleXdvcmQoewogICAgICBkYXRhOiB0aGlzWyRjb250ZW50XSwKICAgICAgZGVmYXVsdFZhbHVlOiB0aGlzW19vcHRpb25zXVswXSwKICAgICAgdmFsaWRhdGU6IGsgPT4gdGhpc1tfb3B0aW9uc10uaW5jbHVkZXMoaykKICAgIH0pOwogIH0KICBbJGNsZWFuXShidWlsZGVyKSB7CiAgICBzdXBlclskY2xlYW5dKGJ1aWxkZXIpOwogICAgZGVsZXRlIHRoaXNbX29wdGlvbnNdOwogIH0KfQpjbGFzcyBTdHJpbmdPYmplY3QgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBbJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbJGNvbnRlbnRdID0gdGhpc1skY29udGVudF0udHJpbSgpOwogIH0KfQpjbGFzcyBJbnRlZ2VyT2JqZWN0IGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IobnNJZCwgbmFtZSwgZGVmYXVsdFZhbHVlLCB2YWxpZGF0b3IpIHsKICAgIHN1cGVyKG5zSWQsIG5hbWUpOwogICAgdGhpc1tfZGVmYXVsdFZhbHVlXSA9IGRlZmF1bHRWYWx1ZTsKICAgIHRoaXNbX3ZhbGlkYXRvcl0gPSB2YWxpZGF0b3I7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgdGhpc1skY29udGVudF0gPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogdGhpc1skY29udGVudF0sCiAgICAgIGRlZmF1bHRWYWx1ZTogdGhpc1tfZGVmYXVsdFZhbHVlXSwKICAgICAgdmFsaWRhdGU6IHRoaXNbX3ZhbGlkYXRvcl0KICAgIH0pOwogIH0KICBbJGNsZWFuXShidWlsZGVyKSB7CiAgICBzdXBlclskY2xlYW5dKGJ1aWxkZXIpOwogICAgZGVsZXRlIHRoaXNbX2RlZmF1bHRWYWx1ZV07CiAgICBkZWxldGUgdGhpc1tfdmFsaWRhdG9yXTsKICB9Cn0KY2xhc3MgT3B0aW9uMDEgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3Rvcihuc0lkLCBuYW1lKSB7CiAgICBzdXBlcihuc0lkLCBuYW1lLCAwLCBuID0+IG4gPT09IDEpOwogIH0KfQpjbGFzcyBPcHRpb24xMCBleHRlbmRzIEludGVnZXJPYmplY3QgewogIGNvbnN0cnVjdG9yKG5zSWQsIG5hbWUpIHsKICAgIHN1cGVyKG5zSWQsIG5hbWUsIDEsIG4gPT4gbiA9PT0gMCk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvaHRtbF91dGlscy5qcwoKCgoKCgpmdW5jdGlvbiBtZWFzdXJlVG9TdHJpbmcobSkgewogIGlmICh0eXBlb2YgbSA9PT0gInN0cmluZyIpIHsKICAgIHJldHVybiAiMHB4IjsKICB9CiAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIobSkgPyBgJHttfXB4YCA6IGAke20udG9GaXhlZCgyKX1weGA7Cn0KY29uc3QgY29udmVydGVycyA9IHsKICBhbmNob3JUeXBlKG5vZGUsIHN0eWxlKSB7CiAgICBjb25zdCBwYXJlbnQgPSBub2RlWyRnZXRTdWJmb3JtUGFyZW50XSgpOwogICAgaWYgKCFwYXJlbnQgfHwgcGFyZW50LmxheW91dCAmJiBwYXJlbnQubGF5b3V0ICE9PSAicG9zaXRpb24iKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICghKCJ0cmFuc2Zvcm0iIGluIHN0eWxlKSkgewogICAgICBzdHlsZS50cmFuc2Zvcm0gPSAiIjsKICAgIH0KICAgIHN3aXRjaCAobm9kZS5hbmNob3JUeXBlKSB7CiAgICAgIGNhc2UgImJvdHRvbUNlbnRlciI6CiAgICAgICAgc3R5bGUudHJhbnNmb3JtICs9ICJ0cmFuc2xhdGUoLTUwJSwgLTEwMCUpIjsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiYm90dG9tTGVmdCI6CiAgICAgICAgc3R5bGUudHJhbnNmb3JtICs9ICJ0cmFuc2xhdGUoMCwtMTAwJSkiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJib3R0b21SaWdodCI6CiAgICAgICAgc3R5bGUudHJhbnNmb3JtICs9ICJ0cmFuc2xhdGUoLTEwMCUsLTEwMCUpIjsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAibWlkZGxlQ2VudGVyIjoKICAgICAgICBzdHlsZS50cmFuc2Zvcm0gKz0gInRyYW5zbGF0ZSgtNTAlLC01MCUpIjsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAibWlkZGxlTGVmdCI6CiAgICAgICAgc3R5bGUudHJhbnNmb3JtICs9ICJ0cmFuc2xhdGUoMCwtNTAlKSI7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIm1pZGRsZVJpZ2h0IjoKICAgICAgICBzdHlsZS50cmFuc2Zvcm0gKz0gInRyYW5zbGF0ZSgtMTAwJSwtNTAlKSI7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgInRvcENlbnRlciI6CiAgICAgICAgc3R5bGUudHJhbnNmb3JtICs9ICJ0cmFuc2xhdGUoLTUwJSwwKSI7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgInRvcFJpZ2h0IjoKICAgICAgICBzdHlsZS50cmFuc2Zvcm0gKz0gInRyYW5zbGF0ZSgtMTAwJSwwKSI7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfSwKICBkaW1lbnNpb25zKG5vZGUsIHN0eWxlKSB7CiAgICBjb25zdCBwYXJlbnQgPSBub2RlWyRnZXRTdWJmb3JtUGFyZW50XSgpOwogICAgbGV0IHdpZHRoID0gbm9kZS53OwogICAgY29uc3QgaGVpZ2h0ID0gbm9kZS5oOwogICAgaWYgKHBhcmVudC5sYXlvdXQ/LmluY2x1ZGVzKCJyb3ciKSkgewogICAgICBjb25zdCBleHRyYSA9IHBhcmVudFskZXh0cmFdOwogICAgICBjb25zdCBjb2xTcGFuID0gbm9kZS5jb2xTcGFuOwogICAgICBsZXQgdzsKICAgICAgaWYgKGNvbFNwYW4gPT09IC0xKSB7CiAgICAgICAgdyA9IE1hdGguc3VtUHJlY2lzZShleHRyYS5jb2x1bW5XaWR0aHMuc2xpY2UoZXh0cmEuY3VycmVudENvbHVtbikpOwogICAgICAgIGV4dHJhLmN1cnJlbnRDb2x1bW4gPSAwOwogICAgICB9IGVsc2UgewogICAgICAgIHcgPSBNYXRoLnN1bVByZWNpc2UoZXh0cmEuY29sdW1uV2lkdGhzLnNsaWNlKGV4dHJhLmN1cnJlbnRDb2x1bW4sIGV4dHJhLmN1cnJlbnRDb2x1bW4gKyBjb2xTcGFuKSk7CiAgICAgICAgZXh0cmEuY3VycmVudENvbHVtbiA9IChleHRyYS5jdXJyZW50Q29sdW1uICsgbm9kZS5jb2xTcGFuKSAlIGV4dHJhLmNvbHVtbldpZHRocy5sZW5ndGg7CiAgICAgIH0KICAgICAgaWYgKCFpc05hTih3KSkgewogICAgICAgIHdpZHRoID0gbm9kZS53ID0gdzsKICAgICAgfQogICAgfQogICAgc3R5bGUud2lkdGggPSB3aWR0aCAhPT0gIiIgPyBtZWFzdXJlVG9TdHJpbmcod2lkdGgpIDogImF1dG8iOwogICAgc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0ICE9PSAiIiA/IG1lYXN1cmVUb1N0cmluZyhoZWlnaHQpIDogImF1dG8iOwogIH0sCiAgcG9zaXRpb24obm9kZSwgc3R5bGUpIHsKICAgIGNvbnN0IHBhcmVudCA9IG5vZGVbJGdldFN1YmZvcm1QYXJlbnRdKCk7CiAgICBpZiAocGFyZW50Py5sYXlvdXQgJiYgcGFyZW50LmxheW91dCAhPT0gInBvc2l0aW9uIikgewogICAgICByZXR1cm47CiAgICB9CiAgICBzdHlsZS5wb3NpdGlvbiA9ICJhYnNvbHV0ZSI7CiAgICBzdHlsZS5sZWZ0ID0gbWVhc3VyZVRvU3RyaW5nKG5vZGUueCk7CiAgICBzdHlsZS50b3AgPSBtZWFzdXJlVG9TdHJpbmcobm9kZS55KTsKICB9LAogIHJvdGF0ZShub2RlLCBzdHlsZSkgewogICAgaWYgKG5vZGUucm90YXRlKSB7CiAgICAgIGlmICghKCJ0cmFuc2Zvcm0iIGluIHN0eWxlKSkgewogICAgICAgIHN0eWxlLnRyYW5zZm9ybSA9ICIiOwogICAgICB9CiAgICAgIHN0eWxlLnRyYW5zZm9ybSArPSBgcm90YXRlKC0ke25vZGUucm90YXRlfWRlZylgOwogICAgICBzdHlsZS50cmFuc2Zvcm1PcmlnaW4gPSAidG9wIGxlZnQiOwogICAgfQogIH0sCiAgcHJlc2VuY2Uobm9kZSwgc3R5bGUpIHsKICAgIHN3aXRjaCAobm9kZS5wcmVzZW5jZSkgewogICAgICBjYXNlICJpbnZpc2libGUiOgogICAgICAgIHN0eWxlLnZpc2liaWxpdHkgPSAiaGlkZGVuIjsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiaGlkZGVuIjoKICAgICAgY2FzZSAiaW5hY3RpdmUiOgogICAgICAgIHN0eWxlLmRpc3BsYXkgPSAibm9uZSI7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfSwKICBoQWxpZ24obm9kZSwgc3R5bGUpIHsKICAgIGlmIChub2RlWyRub2RlTmFtZV0gPT09ICJwYXJhIikgewogICAgICBzd2l0Y2ggKG5vZGUuaEFsaWduKSB7CiAgICAgICAgY2FzZSAianVzdGlmeUFsbCI6CiAgICAgICAgICBzdHlsZS50ZXh0QWxpZ24gPSAianVzdGlmeS1hbGwiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAicmFkaXgiOgogICAgICAgICAgc3R5bGUudGV4dEFsaWduID0gImxlZnQiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHN0eWxlLnRleHRBbGlnbiA9IG5vZGUuaEFsaWduOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBzd2l0Y2ggKG5vZGUuaEFsaWduKSB7CiAgICAgICAgY2FzZSAibGVmdCI6CiAgICAgICAgICBzdHlsZS5hbGlnblNlbGYgPSAic3RhcnQiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiY2VudGVyIjoKICAgICAgICAgIHN0eWxlLmFsaWduU2VsZiA9ICJjZW50ZXIiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAicmlnaHQiOgogICAgICAgICAgc3R5bGUuYWxpZ25TZWxmID0gImVuZCI7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogIH0sCiAgbWFyZ2luKG5vZGUsIHN0eWxlKSB7CiAgICBpZiAobm9kZS5tYXJnaW4pIHsKICAgICAgc3R5bGUubWFyZ2luID0gbm9kZS5tYXJnaW5bJHRvU3R5bGVdKCkubWFyZ2luOwogICAgfQogIH0KfTsKZnVuY3Rpb24gc2V0TWluTWF4RGltZW5zaW9ucyhub2RlLCBzdHlsZSkgewogIGNvbnN0IHBhcmVudCA9IG5vZGVbJGdldFN1YmZvcm1QYXJlbnRdKCk7CiAgaWYgKHBhcmVudC5sYXlvdXQgPT09ICJwb3NpdGlvbiIpIHsKICAgIGlmIChub2RlLm1pblcgPiAwKSB7CiAgICAgIHN0eWxlLm1pbldpZHRoID0gbWVhc3VyZVRvU3RyaW5nKG5vZGUubWluVyk7CiAgICB9CiAgICBpZiAobm9kZS5tYXhXID4gMCkgewogICAgICBzdHlsZS5tYXhXaWR0aCA9IG1lYXN1cmVUb1N0cmluZyhub2RlLm1heFcpOwogICAgfQogICAgaWYgKG5vZGUubWluSCA+IDApIHsKICAgICAgc3R5bGUubWluSGVpZ2h0ID0gbWVhc3VyZVRvU3RyaW5nKG5vZGUubWluSCk7CiAgICB9CiAgICBpZiAobm9kZS5tYXhIID4gMCkgewogICAgICBzdHlsZS5tYXhIZWlnaHQgPSBtZWFzdXJlVG9TdHJpbmcobm9kZS5tYXhIKTsKICAgIH0KICB9Cn0KZnVuY3Rpb24gbGF5b3V0VGV4dCh0ZXh0LCB4ZmFGb250LCBtYXJnaW4sIGxpbmVIZWlnaHQsIGZvbnRGaW5kZXIsIHdpZHRoKSB7CiAgY29uc3QgbWVhc3VyZSA9IG5ldyBUZXh0TWVhc3VyZSh4ZmFGb250LCBtYXJnaW4sIGxpbmVIZWlnaHQsIGZvbnRGaW5kZXIpOwogIGlmICh0eXBlb2YgdGV4dCA9PT0gInN0cmluZyIpIHsKICAgIG1lYXN1cmUuYWRkU3RyaW5nKHRleHQpOwogIH0gZWxzZSB7CiAgICB0ZXh0WyRwdXNoR2x5cGhzXShtZWFzdXJlKTsKICB9CiAgcmV0dXJuIG1lYXN1cmUuY29tcHV0ZSh3aWR0aCk7Cn0KZnVuY3Rpb24gbGF5b3V0Tm9kZShub2RlLCBhdmFpbGFibGVTcGFjZSkgewogIGxldCBoZWlnaHQgPSBudWxsOwogIGxldCB3aWR0aCA9IG51bGw7CiAgbGV0IGlzQnJva2VuID0gZmFsc2U7CiAgaWYgKCghbm9kZS53IHx8ICFub2RlLmgpICYmIG5vZGUudmFsdWUpIHsKICAgIGxldCBtYXJnaW5IID0gMDsKICAgIGxldCBtYXJnaW5WID0gMDsKICAgIGlmIChub2RlLm1hcmdpbikgewogICAgICBtYXJnaW5IID0gbm9kZS5tYXJnaW4ubGVmdEluc2V0ICsgbm9kZS5tYXJnaW4ucmlnaHRJbnNldDsKICAgICAgbWFyZ2luViA9IG5vZGUubWFyZ2luLnRvcEluc2V0ICsgbm9kZS5tYXJnaW4uYm90dG9tSW5zZXQ7CiAgICB9CiAgICBsZXQgbGluZUhlaWdodCA9IG51bGw7CiAgICBsZXQgbWFyZ2luID0gbnVsbDsKICAgIGlmIChub2RlLnBhcmEpIHsKICAgICAgbWFyZ2luID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgbGluZUhlaWdodCA9IG5vZGUucGFyYS5saW5lSGVpZ2h0ID09PSAiIiA/IG51bGwgOiBub2RlLnBhcmEubGluZUhlaWdodDsKICAgICAgbWFyZ2luLnRvcCA9IG5vZGUucGFyYS5zcGFjZUFib3ZlID09PSAiIiA/IDAgOiBub2RlLnBhcmEuc3BhY2VBYm92ZTsKICAgICAgbWFyZ2luLmJvdHRvbSA9IG5vZGUucGFyYS5zcGFjZUJlbG93ID09PSAiIiA/IDAgOiBub2RlLnBhcmEuc3BhY2VCZWxvdzsKICAgICAgbWFyZ2luLmxlZnQgPSBub2RlLnBhcmEubWFyZ2luTGVmdCA9PT0gIiIgPyAwIDogbm9kZS5wYXJhLm1hcmdpbkxlZnQ7CiAgICAgIG1hcmdpbi5yaWdodCA9IG5vZGUucGFyYS5tYXJnaW5SaWdodCA9PT0gIiIgPyAwIDogbm9kZS5wYXJhLm1hcmdpblJpZ2h0OwogICAgfQogICAgbGV0IGZvbnQgPSBub2RlLmZvbnQ7CiAgICBpZiAoIWZvbnQpIHsKICAgICAgY29uc3Qgcm9vdCA9IG5vZGVbJGdldFRlbXBsYXRlUm9vdF0oKTsKICAgICAgbGV0IHBhcmVudCA9IG5vZGVbJGdldFBhcmVudF0oKTsKICAgICAgd2hpbGUgKHBhcmVudCAmJiBwYXJlbnQgIT09IHJvb3QpIHsKICAgICAgICBpZiAocGFyZW50LmZvbnQpIHsKICAgICAgICAgIGZvbnQgPSBwYXJlbnQuZm9udDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBwYXJlbnQgPSBwYXJlbnRbJGdldFBhcmVudF0oKTsKICAgICAgfQogICAgfQogICAgY29uc3QgbWF4V2lkdGggPSAobm9kZS53IHx8IGF2YWlsYWJsZVNwYWNlLndpZHRoKSAtIG1hcmdpbkg7CiAgICBjb25zdCBmb250RmluZGVyID0gbm9kZVskZ2xvYmFsRGF0YV0uZm9udEZpbmRlcjsKICAgIGlmIChub2RlLnZhbHVlLmV4RGF0YSAmJiBub2RlLnZhbHVlLmV4RGF0YVskY29udGVudF0gJiYgbm9kZS52YWx1ZS5leERhdGEuY29udGVudFR5cGUgPT09ICJ0ZXh0L2h0bWwiKSB7CiAgICAgIGNvbnN0IHJlcyA9IGxheW91dFRleHQobm9kZS52YWx1ZS5leERhdGFbJGNvbnRlbnRdLCBmb250LCBtYXJnaW4sIGxpbmVIZWlnaHQsIGZvbnRGaW5kZXIsIG1heFdpZHRoKTsKICAgICAgd2lkdGggPSByZXMud2lkdGg7CiAgICAgIGhlaWdodCA9IHJlcy5oZWlnaHQ7CiAgICAgIGlzQnJva2VuID0gcmVzLmlzQnJva2VuOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgdGV4dCA9IG5vZGUudmFsdWVbJHRleHRdKCk7CiAgICAgIGlmICh0ZXh0KSB7CiAgICAgICAgY29uc3QgcmVzID0gbGF5b3V0VGV4dCh0ZXh0LCBmb250LCBtYXJnaW4sIGxpbmVIZWlnaHQsIGZvbnRGaW5kZXIsIG1heFdpZHRoKTsKICAgICAgICB3aWR0aCA9IHJlcy53aWR0aDsKICAgICAgICBoZWlnaHQgPSByZXMuaGVpZ2h0OwogICAgICAgIGlzQnJva2VuID0gcmVzLmlzQnJva2VuOwogICAgICB9CiAgICB9CiAgICBpZiAod2lkdGggIT09IG51bGwgJiYgIW5vZGUudykgewogICAgICB3aWR0aCArPSBtYXJnaW5IOwogICAgfQogICAgaWYgKGhlaWdodCAhPT0gbnVsbCAmJiAhbm9kZS5oKSB7CiAgICAgIGhlaWdodCArPSBtYXJnaW5WOwogICAgfQogIH0KICByZXR1cm4gewogICAgdzogd2lkdGgsCiAgICBoOiBoZWlnaHQsCiAgICBpc0Jyb2tlbgogIH07Cn0KZnVuY3Rpb24gY29tcHV0ZUJib3gobm9kZSwgaHRtbCwgYXZhaWxhYmxlU3BhY2UpIHsKICBsZXQgYmJveDsKICBpZiAobm9kZS53ICE9PSAiIiAmJiBub2RlLmggIT09ICIiKSB7CiAgICBiYm94ID0gW25vZGUueCwgbm9kZS55LCBub2RlLncsIG5vZGUuaF07CiAgfSBlbHNlIHsKICAgIGlmICghYXZhaWxhYmxlU3BhY2UpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBsZXQgd2lkdGggPSBub2RlLnc7CiAgICBpZiAod2lkdGggPT09ICIiKSB7CiAgICAgIGlmIChub2RlLm1heFcgPT09IDApIHsKICAgICAgICBjb25zdCBwYXJlbnQgPSBub2RlWyRnZXRTdWJmb3JtUGFyZW50XSgpOwogICAgICAgIHdpZHRoID0gcGFyZW50LmxheW91dCA9PT0gInBvc2l0aW9uIiAmJiBwYXJlbnQudyAhPT0gIiIgPyAwIDogbm9kZS5taW5XOwogICAgICB9IGVsc2UgewogICAgICAgIHdpZHRoID0gTWF0aC5taW4obm9kZS5tYXhXLCBhdmFpbGFibGVTcGFjZS53aWR0aCk7CiAgICAgIH0KICAgICAgaHRtbC5hdHRyaWJ1dGVzLnN0eWxlLndpZHRoID0gbWVhc3VyZVRvU3RyaW5nKHdpZHRoKTsKICAgIH0KICAgIGxldCBoZWlnaHQgPSBub2RlLmg7CiAgICBpZiAoaGVpZ2h0ID09PSAiIikgewogICAgICBpZiAobm9kZS5tYXhIID09PSAwKSB7CiAgICAgICAgY29uc3QgcGFyZW50ID0gbm9kZVskZ2V0U3ViZm9ybVBhcmVudF0oKTsKICAgICAgICBoZWlnaHQgPSBwYXJlbnQubGF5b3V0ID09PSAicG9zaXRpb24iICYmIHBhcmVudC5oICE9PSAiIiA/IDAgOiBub2RlLm1pbkg7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaGVpZ2h0ID0gTWF0aC5taW4obm9kZS5tYXhILCBhdmFpbGFibGVTcGFjZS5oZWlnaHQpOwogICAgICB9CiAgICAgIGh0bWwuYXR0cmlidXRlcy5zdHlsZS5oZWlnaHQgPSBtZWFzdXJlVG9TdHJpbmcoaGVpZ2h0KTsKICAgIH0KICAgIGJib3ggPSBbbm9kZS54LCBub2RlLnksIHdpZHRoLCBoZWlnaHRdOwogIH0KICByZXR1cm4gYmJveDsKfQpmdW5jdGlvbiBmaXhEaW1lbnNpb25zKG5vZGUpIHsKICBjb25zdCBwYXJlbnQgPSBub2RlWyRnZXRTdWJmb3JtUGFyZW50XSgpOwogIGlmIChwYXJlbnQubGF5b3V0Py5pbmNsdWRlcygicm93IikpIHsKICAgIGNvbnN0IGV4dHJhID0gcGFyZW50WyRleHRyYV07CiAgICBjb25zdCBjb2xTcGFuID0gbm9kZS5jb2xTcGFuOwogICAgbGV0IHdpZHRoOwogICAgaWYgKGNvbFNwYW4gPT09IC0xKSB7CiAgICAgIHdpZHRoID0gTWF0aC5zdW1QcmVjaXNlKGV4dHJhLmNvbHVtbldpZHRocy5zbGljZShleHRyYS5jdXJyZW50Q29sdW1uKSk7CiAgICB9IGVsc2UgewogICAgICB3aWR0aCA9IE1hdGguc3VtUHJlY2lzZShleHRyYS5jb2x1bW5XaWR0aHMuc2xpY2UoZXh0cmEuY3VycmVudENvbHVtbiwgZXh0cmEuY3VycmVudENvbHVtbiArIGNvbFNwYW4pKTsKICAgIH0KICAgIGlmICghaXNOYU4od2lkdGgpKSB7CiAgICAgIG5vZGUudyA9IHdpZHRoOwogICAgfQogIH0KICBpZiAocGFyZW50LmxheW91dCAmJiBwYXJlbnQubGF5b3V0ICE9PSAicG9zaXRpb24iKSB7CiAgICBub2RlLnggPSBub2RlLnkgPSAwOwogIH0KICBpZiAobm9kZS5sYXlvdXQgPT09ICJ0YWJsZSIpIHsKICAgIGlmIChub2RlLncgPT09ICIiICYmIEFycmF5LmlzQXJyYXkobm9kZS5jb2x1bW5XaWR0aHMpKSB7CiAgICAgIG5vZGUudyA9IE1hdGguc3VtUHJlY2lzZShub2RlLmNvbHVtbldpZHRocyk7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGxheW91dENsYXNzKG5vZGUpIHsKICBzd2l0Y2ggKG5vZGUubGF5b3V0KSB7CiAgICBjYXNlICJwb3NpdGlvbiI6CiAgICAgIHJldHVybiAieGZhUG9zaXRpb24iOwogICAgY2FzZSAibHItdGIiOgogICAgICByZXR1cm4gInhmYUxyVGIiOwogICAgY2FzZSAicmwtcm93IjoKICAgICAgcmV0dXJuICJ4ZmFSbFJvdyI7CiAgICBjYXNlICJybC10YiI6CiAgICAgIHJldHVybiAieGZhUmxUYiI7CiAgICBjYXNlICJyb3ciOgogICAgICByZXR1cm4gInhmYVJvdyI7CiAgICBjYXNlICJ0YWJsZSI6CiAgICAgIHJldHVybiAieGZhVGFibGUiOwogICAgY2FzZSAidGIiOgogICAgICByZXR1cm4gInhmYVRiIjsKICAgIGRlZmF1bHQ6CiAgICAgIHJldHVybiAieGZhUG9zaXRpb24iOwogIH0KfQpmdW5jdGlvbiB0b1N0eWxlKG5vZGUsIC4uLm5hbWVzKSB7CiAgY29uc3Qgc3R5bGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIGZvciAoY29uc3QgbmFtZSBvZiBuYW1lcykgewogICAgY29uc3QgdmFsdWUgPSBub2RlW25hbWVdOwogICAgaWYgKHZhbHVlID09PSBudWxsKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgaWYgKGNvbnZlcnRlcnMuaGFzT3duUHJvcGVydHkobmFtZSkpIHsKICAgICAgY29udmVydGVyc1tuYW1lXShub2RlLCBzdHlsZSk7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgWEZBT2JqZWN0KSB7CiAgICAgIGNvbnN0IG5ld1N0eWxlID0gdmFsdWVbJHRvU3R5bGVdKCk7CiAgICAgIGlmIChuZXdTdHlsZSkgewogICAgICAgIE9iamVjdC5hc3NpZ24oc3R5bGUsIG5ld1N0eWxlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB3YXJuKGAoREVCVUcpIC0gWEZBIC0gc3R5bGUgZm9yICR7bmFtZX0gbm90IGltcGxlbWVudGVkIHlldGApOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiBzdHlsZTsKfQpmdW5jdGlvbiBjcmVhdGVXcmFwcGVyKG5vZGUsIGh0bWwpIHsKICBjb25zdCB7CiAgICBhdHRyaWJ1dGVzCiAgfSA9IGh0bWw7CiAgY29uc3QgewogICAgc3R5bGUKICB9ID0gYXR0cmlidXRlczsKICBjb25zdCB3cmFwcGVyID0gewogICAgbmFtZTogImRpdiIsCiAgICBhdHRyaWJ1dGVzOiB7CiAgICAgIGNsYXNzOiBbInhmYVdyYXBwZXIiXSwKICAgICAgc3R5bGU6IE9iamVjdC5jcmVhdGUobnVsbCkKICAgIH0sCiAgICBjaGlsZHJlbjogW10KICB9OwogIGF0dHJpYnV0ZXMuY2xhc3MucHVzaCgieGZhV3JhcHBlZCIpOwogIGlmIChub2RlLmJvcmRlcikgewogICAgY29uc3QgewogICAgICB3aWR0aHMsCiAgICAgIGluc2V0cwogICAgfSA9IG5vZGUuYm9yZGVyWyRleHRyYV07CiAgICBsZXQgd2lkdGgsIGhlaWdodDsKICAgIGxldCB0b3AgPSBpbnNldHNbMF07CiAgICBsZXQgbGVmdCA9IGluc2V0c1szXTsKICAgIGNvbnN0IGluc2V0c0ggPSBpbnNldHNbMF0gKyBpbnNldHNbMl07CiAgICBjb25zdCBpbnNldHNXID0gaW5zZXRzWzFdICsgaW5zZXRzWzNdOwogICAgc3dpdGNoIChub2RlLmJvcmRlci5oYW5kKSB7CiAgICAgIGNhc2UgImV2ZW4iOgogICAgICAgIHRvcCAtPSB3aWR0aHNbMF0gLyAyOwogICAgICAgIGxlZnQgLT0gd2lkdGhzWzNdIC8gMjsKICAgICAgICB3aWR0aCA9IGBjYWxjKDEwMCUgKyAkeyh3aWR0aHNbMV0gKyB3aWR0aHNbM10pIC8gMiAtIGluc2V0c1d9cHgpYDsKICAgICAgICBoZWlnaHQgPSBgY2FsYygxMDAlICsgJHsod2lkdGhzWzBdICsgd2lkdGhzWzJdKSAvIDIgLSBpbnNldHNIfXB4KWA7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgImxlZnQiOgogICAgICAgIHRvcCAtPSB3aWR0aHNbMF07CiAgICAgICAgbGVmdCAtPSB3aWR0aHNbM107CiAgICAgICAgd2lkdGggPSBgY2FsYygxMDAlICsgJHt3aWR0aHNbMV0gKyB3aWR0aHNbM10gLSBpbnNldHNXfXB4KWA7CiAgICAgICAgaGVpZ2h0ID0gYGNhbGMoMTAwJSArICR7d2lkdGhzWzBdICsgd2lkdGhzWzJdIC0gaW5zZXRzSH1weClgOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJyaWdodCI6CiAgICAgICAgd2lkdGggPSBpbnNldHNXID8gYGNhbGMoMTAwJSAtICR7aW5zZXRzV31weClgIDogIjEwMCUiOwogICAgICAgIGhlaWdodCA9IGluc2V0c0ggPyBgY2FsYygxMDAlIC0gJHtpbnNldHNIfXB4KWAgOiAiMTAwJSI7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBjb25zdCBjbGFzc05hbWVzID0gWyJ4ZmFCb3JkZXIiXTsKICAgIGlmIChpc1ByaW50T25seShub2RlLmJvcmRlcikpIHsKICAgICAgY2xhc3NOYW1lcy5wdXNoKCJ4ZmFQcmludE9ubHkiKTsKICAgIH0KICAgIGNvbnN0IGJvcmRlciA9IHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBjbGFzczogY2xhc3NOYW1lcywKICAgICAgICBzdHlsZTogewogICAgICAgICAgdG9wOiBgJHt0b3B9cHhgLAogICAgICAgICAgbGVmdDogYCR7bGVmdH1weGAsCiAgICAgICAgICB3aWR0aCwKICAgICAgICAgIGhlaWdodAogICAgICAgIH0KICAgICAgfSwKICAgICAgY2hpbGRyZW46IFtdCiAgICB9OwogICAgZm9yIChjb25zdCBrZXkgb2YgWyJib3JkZXIiLCAiYm9yZGVyV2lkdGgiLCAiYm9yZGVyQ29sb3IiLCAiYm9yZGVyUmFkaXVzIiwgImJvcmRlclN0eWxlIl0pIHsKICAgICAgaWYgKHN0eWxlW2tleV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgIGJvcmRlci5hdHRyaWJ1dGVzLnN0eWxlW2tleV0gPSBzdHlsZVtrZXldOwogICAgICAgIGRlbGV0ZSBzdHlsZVtrZXldOwogICAgICB9CiAgICB9CiAgICB3cmFwcGVyLmNoaWxkcmVuLnB1c2goYm9yZGVyLCBodG1sKTsKICB9IGVsc2UgewogICAgd3JhcHBlci5jaGlsZHJlbi5wdXNoKGh0bWwpOwogIH0KICBmb3IgKGNvbnN0IGtleSBvZiBbImJhY2tncm91bmQiLCAiYmFja2dyb3VuZENsaXAiLCAidG9wIiwgImxlZnQiLCAid2lkdGgiLCAiaGVpZ2h0IiwgIm1pbldpZHRoIiwgIm1pbkhlaWdodCIsICJtYXhXaWR0aCIsICJtYXhIZWlnaHQiLCAidHJhbnNmb3JtIiwgInRyYW5zZm9ybU9yaWdpbiIsICJ2aXNpYmlsaXR5Il0pIHsKICAgIGlmIChzdHlsZVtrZXldICE9PSB1bmRlZmluZWQpIHsKICAgICAgd3JhcHBlci5hdHRyaWJ1dGVzLnN0eWxlW2tleV0gPSBzdHlsZVtrZXldOwogICAgICBkZWxldGUgc3R5bGVba2V5XTsKICAgIH0KICB9CiAgd3JhcHBlci5hdHRyaWJ1dGVzLnN0eWxlLnBvc2l0aW9uID0gc3R5bGUucG9zaXRpb24gPT09ICJhYnNvbHV0ZSIgPyAiYWJzb2x1dGUiIDogInJlbGF0aXZlIjsKICBkZWxldGUgc3R5bGUucG9zaXRpb247CiAgaWYgKHN0eWxlLmFsaWduU2VsZikgewogICAgd3JhcHBlci5hdHRyaWJ1dGVzLnN0eWxlLmFsaWduU2VsZiA9IHN0eWxlLmFsaWduU2VsZjsKICAgIGRlbGV0ZSBzdHlsZS5hbGlnblNlbGY7CiAgfQogIHJldHVybiB3cmFwcGVyOwp9CmZ1bmN0aW9uIGZpeFRleHRJbmRlbnQoc3R5bGVzKSB7CiAgY29uc3QgaW5kZW50ID0gZ2V0TWVhc3VyZW1lbnQoc3R5bGVzLnRleHRJbmRlbnQsICIwcHgiKTsKICBpZiAoaW5kZW50ID49IDApIHsKICAgIHJldHVybjsKICB9CiAgY29uc3QgYWxpZ24gPSBzdHlsZXMudGV4dEFsaWduID09PSAicmlnaHQiID8gInJpZ2h0IiA6ICJsZWZ0IjsKICBjb25zdCBuYW1lID0gInBhZGRpbmciICsgKGFsaWduID09PSAibGVmdCIgPyAiTGVmdCIgOiAiUmlnaHQiKTsKICBjb25zdCBwYWRkaW5nID0gZ2V0TWVhc3VyZW1lbnQoc3R5bGVzW25hbWVdLCAiMHB4Iik7CiAgc3R5bGVzW25hbWVdID0gYCR7cGFkZGluZyAtIGluZGVudH1weGA7Cn0KZnVuY3Rpb24gc2V0QWNjZXNzKG5vZGUsIGNsYXNzTmFtZXMpIHsKICBzd2l0Y2ggKG5vZGUuYWNjZXNzKSB7CiAgICBjYXNlICJub25JbnRlcmFjdGl2ZSI6CiAgICAgIGNsYXNzTmFtZXMucHVzaCgieGZhTm9uSW50ZXJhY3RpdmUiKTsKICAgICAgYnJlYWs7CiAgICBjYXNlICJyZWFkT25seSI6CiAgICAgIGNsYXNzTmFtZXMucHVzaCgieGZhUmVhZE9ubHkiKTsKICAgICAgYnJlYWs7CiAgICBjYXNlICJwcm90ZWN0ZWQiOgogICAgICBjbGFzc05hbWVzLnB1c2goInhmYURpc2FibGVkIik7CiAgICAgIGJyZWFrOwogIH0KfQpmdW5jdGlvbiBpc1ByaW50T25seShub2RlKSB7CiAgcmV0dXJuIG5vZGUucmVsZXZhbnQubGVuZ3RoID4gMCAmJiAhbm9kZS5yZWxldmFudFswXS5leGNsdWRlZCAmJiBub2RlLnJlbGV2YW50WzBdLnZpZXduYW1lID09PSAicHJpbnQiOwp9CmZ1bmN0aW9uIGdldEN1cnJlbnRQYXJhKG5vZGUpIHsKICBjb25zdCBzdGFjayA9IG5vZGVbJGdldFRlbXBsYXRlUm9vdF0oKVskZXh0cmFdLnBhcmFTdGFjazsKICByZXR1cm4gc3RhY2subGVuZ3RoID8gc3RhY2suYXQoLTEpIDogbnVsbDsKfQpmdW5jdGlvbiBzZXRQYXJhKG5vZGUsIG5vZGVTdHlsZSwgdmFsdWUpIHsKICBpZiAodmFsdWUuYXR0cmlidXRlcy5jbGFzcz8uaW5jbHVkZXMoInhmYVJpY2giKSkgewogICAgaWYgKG5vZGVTdHlsZSkgewogICAgICBpZiAobm9kZS5oID09PSAiIikgewogICAgICAgIG5vZGVTdHlsZS5oZWlnaHQgPSAiYXV0byI7CiAgICAgIH0KICAgICAgaWYgKG5vZGUudyA9PT0gIiIpIHsKICAgICAgICBub2RlU3R5bGUud2lkdGggPSAiYXV0byI7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHBhcmEgPSBnZXRDdXJyZW50UGFyYShub2RlKTsKICAgIGlmIChwYXJhKSB7CiAgICAgIGNvbnN0IHZhbHVlU3R5bGUgPSB2YWx1ZS5hdHRyaWJ1dGVzLnN0eWxlOwogICAgICB2YWx1ZVN0eWxlLmRpc3BsYXkgPSAiZmxleCI7CiAgICAgIHZhbHVlU3R5bGUuZmxleERpcmVjdGlvbiA9ICJjb2x1bW4iOwogICAgICBzd2l0Y2ggKHBhcmEudkFsaWduKSB7CiAgICAgICAgY2FzZSAidG9wIjoKICAgICAgICAgIHZhbHVlU3R5bGUuanVzdGlmeUNvbnRlbnQgPSAic3RhcnQiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiYm90dG9tIjoKICAgICAgICAgIHZhbHVlU3R5bGUuanVzdGlmeUNvbnRlbnQgPSAiZW5kIjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm1pZGRsZSI6CiAgICAgICAgICB2YWx1ZVN0eWxlLmp1c3RpZnlDb250ZW50ID0gImNlbnRlciI7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBjb25zdCBwYXJhU3R5bGUgPSBwYXJhWyR0b1N0eWxlXSgpOwogICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgT2JqZWN0LmVudHJpZXMocGFyYVN0eWxlKSkgewogICAgICAgIGlmICghKGtleSBpbiB2YWx1ZVN0eWxlKSkgewogICAgICAgICAgdmFsdWVTdHlsZVtrZXldID0gdmFsOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KfQpmdW5jdGlvbiBzZXRGb250RmFtaWx5KHhmYUZvbnQsIG5vZGUsIGZvbnRGaW5kZXIsIHN0eWxlKSB7CiAgaWYgKCFmb250RmluZGVyKSB7CiAgICBkZWxldGUgc3R5bGUuZm9udEZhbWlseTsKICAgIHJldHVybjsKICB9CiAgY29uc3QgbmFtZSA9IHN0cmlwUXVvdGVzKHhmYUZvbnQudHlwZWZhY2UpOwogIHN0eWxlLmZvbnRGYW1pbHkgPSBgIiR7bmFtZX0iYDsKICBjb25zdCB0eXBlZmFjZSA9IGZvbnRGaW5kZXIuZmluZChuYW1lKTsKICBpZiAodHlwZWZhY2UpIHsKICAgIGNvbnN0IHsKICAgICAgZm9udEZhbWlseQogICAgfSA9IHR5cGVmYWNlLnJlZ3VsYXIuY3NzRm9udEluZm87CiAgICBpZiAoZm9udEZhbWlseSAhPT0gbmFtZSkgewogICAgICBzdHlsZS5mb250RmFtaWx5ID0gYCIke2ZvbnRGYW1pbHl9ImA7CiAgICB9CiAgICBjb25zdCBwYXJhID0gZ2V0Q3VycmVudFBhcmEobm9kZSk7CiAgICBpZiAocGFyYSAmJiBwYXJhLmxpbmVIZWlnaHQgIT09ICIiKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChzdHlsZS5saW5lSGVpZ2h0KSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHBkZkZvbnQgPSBzZWxlY3RGb250KHhmYUZvbnQsIHR5cGVmYWNlKTsKICAgIGlmIChwZGZGb250KSB7CiAgICAgIHN0eWxlLmxpbmVIZWlnaHQgPSBNYXRoLm1heCgxLjIsIHBkZkZvbnQubGluZUhlaWdodCk7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGZpeFVSTChzdHIpIHsKICBjb25zdCBhYnNvbHV0ZVVybCA9IGNyZWF0ZVZhbGlkQWJzb2x1dGVVcmwoc3RyLCBudWxsLCB7CiAgICBhZGREZWZhdWx0UHJvdG9jb2w6IHRydWUsCiAgICB0cnlDb252ZXJ0RW5jb2Rpbmc6IHRydWUKICB9KTsKICByZXR1cm4gYWJzb2x1dGVVcmwgPyBhYnNvbHV0ZVVybC5ocmVmIDogbnVsbDsKfQoKOy8vIC4vc3JjL2NvcmUveGZhL2xheW91dC5qcwoKCgpmdW5jdGlvbiBjcmVhdGVMaW5lKG5vZGUsIGNoaWxkcmVuKSB7CiAgcmV0dXJuIHsKICAgIG5hbWU6ICJkaXYiLAogICAgYXR0cmlidXRlczogewogICAgICBjbGFzczogW25vZGUubGF5b3V0ID09PSAibHItdGIiID8gInhmYUxyIiA6ICJ4ZmFSbCJdCiAgICB9LAogICAgY2hpbGRyZW4KICB9Owp9CmZ1bmN0aW9uIGZsdXNoSFRNTChub2RlKSB7CiAgaWYgKCFub2RlWyRleHRyYV0pIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCBhdHRyaWJ1dGVzID0gbm9kZVskZXh0cmFdLmF0dHJpYnV0ZXM7CiAgY29uc3QgaHRtbCA9IHsKICAgIG5hbWU6ICJkaXYiLAogICAgYXR0cmlidXRlcywKICAgIGNoaWxkcmVuOiBub2RlWyRleHRyYV0uY2hpbGRyZW4KICB9OwogIGlmIChub2RlWyRleHRyYV0uZmFpbGluZ05vZGUpIHsKICAgIGNvbnN0IGh0bWxGcm9tRmFpbGluZyA9IG5vZGVbJGV4dHJhXS5mYWlsaW5nTm9kZVskZmx1c2hIVE1MXSgpOwogICAgaWYgKGh0bWxGcm9tRmFpbGluZykgewogICAgICBpZiAobm9kZS5sYXlvdXQuZW5kc1dpdGgoIi10YiIpKSB7CiAgICAgICAgaHRtbC5jaGlsZHJlbi5wdXNoKGNyZWF0ZUxpbmUobm9kZSwgW2h0bWxGcm9tRmFpbGluZ10pKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBodG1sLmNoaWxkcmVuLnB1c2goaHRtbEZyb21GYWlsaW5nKTsKICAgICAgfQogICAgfQogIH0KICBpZiAoaHRtbC5jaGlsZHJlbi5sZW5ndGggPT09IDApIHsKICAgIHJldHVybiBudWxsOwogIH0KICByZXR1cm4gaHRtbDsKfQpmdW5jdGlvbiBhZGRIVE1MKG5vZGUsIGh0bWwsIGJib3gpIHsKICBjb25zdCBleHRyYSA9IG5vZGVbJGV4dHJhXTsKICBjb25zdCBhdmFpbGFibGVTcGFjZSA9IGV4dHJhLmF2YWlsYWJsZVNwYWNlOwogIGNvbnN0IFt4LCB5LCB3LCBoXSA9IGJib3g7CiAgc3dpdGNoIChub2RlLmxheW91dCkgewogICAgY2FzZSAicG9zaXRpb24iOgogICAgICB7CiAgICAgICAgZXh0cmEud2lkdGggPSBNYXRoLm1heChleHRyYS53aWR0aCwgeCArIHcpOwogICAgICAgIGV4dHJhLmhlaWdodCA9IE1hdGgubWF4KGV4dHJhLmhlaWdodCwgeSArIGgpOwogICAgICAgIGV4dHJhLmNoaWxkcmVuLnB1c2goaHRtbCk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIGNhc2UgImxyLXRiIjoKICAgIGNhc2UgInJsLXRiIjoKICAgICAgaWYgKCFleHRyYS5saW5lIHx8IGV4dHJhLmF0dGVtcHQgPT09IDEpIHsKICAgICAgICBleHRyYS5saW5lID0gY3JlYXRlTGluZShub2RlLCBbXSk7CiAgICAgICAgZXh0cmEuY2hpbGRyZW4ucHVzaChleHRyYS5saW5lKTsKICAgICAgICBleHRyYS5udW1iZXJJbkxpbmUgPSAwOwogICAgICB9CiAgICAgIGV4dHJhLm51bWJlckluTGluZSArPSAxOwogICAgICBleHRyYS5saW5lLmNoaWxkcmVuLnB1c2goaHRtbCk7CiAgICAgIGlmIChleHRyYS5hdHRlbXB0ID09PSAwKSB7CiAgICAgICAgZXh0cmEuY3VycmVudFdpZHRoICs9IHc7CiAgICAgICAgZXh0cmEuaGVpZ2h0ID0gTWF0aC5tYXgoZXh0cmEuaGVpZ2h0LCBleHRyYS5wcmV2SGVpZ2h0ICsgaCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZXh0cmEuY3VycmVudFdpZHRoID0gdzsKICAgICAgICBleHRyYS5wcmV2SGVpZ2h0ID0gZXh0cmEuaGVpZ2h0OwogICAgICAgIGV4dHJhLmhlaWdodCArPSBoOwogICAgICAgIGV4dHJhLmF0dGVtcHQgPSAwOwogICAgICB9CiAgICAgIGV4dHJhLndpZHRoID0gTWF0aC5tYXgoZXh0cmEud2lkdGgsIGV4dHJhLmN1cnJlbnRXaWR0aCk7CiAgICAgIGJyZWFrOwogICAgY2FzZSAicmwtcm93IjoKICAgIGNhc2UgInJvdyI6CiAgICAgIHsKICAgICAgICBleHRyYS5jaGlsZHJlbi5wdXNoKGh0bWwpOwogICAgICAgIGV4dHJhLndpZHRoICs9IHc7CiAgICAgICAgZXh0cmEuaGVpZ2h0ID0gTWF0aC5tYXgoZXh0cmEuaGVpZ2h0LCBoKTsKICAgICAgICBjb25zdCBoZWlnaHQgPSBtZWFzdXJlVG9TdHJpbmcoZXh0cmEuaGVpZ2h0KTsKICAgICAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIGV4dHJhLmNoaWxkcmVuKSB7CiAgICAgICAgICBjaGlsZC5hdHRyaWJ1dGVzLnN0eWxlLmhlaWdodCA9IGhlaWdodDsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIGNhc2UgInRhYmxlIjoKICAgICAgewogICAgICAgIGV4dHJhLndpZHRoID0gTWF0aENsYW1wKHcsIGV4dHJhLndpZHRoLCBhdmFpbGFibGVTcGFjZS53aWR0aCk7CiAgICAgICAgZXh0cmEuaGVpZ2h0ICs9IGg7CiAgICAgICAgZXh0cmEuY2hpbGRyZW4ucHVzaChodG1sKTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgY2FzZSAidGIiOgogICAgICB7CiAgICAgICAgZXh0cmEud2lkdGggPSBNYXRoQ2xhbXAodywgZXh0cmEud2lkdGgsIGF2YWlsYWJsZVNwYWNlLndpZHRoKTsKICAgICAgICBleHRyYS5oZWlnaHQgKz0gaDsKICAgICAgICBleHRyYS5jaGlsZHJlbi5wdXNoKGh0bWwpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgfQp9CmZ1bmN0aW9uIGdldEF2YWlsYWJsZVNwYWNlKG5vZGUpIHsKICBjb25zdCBhdmFpbGFibGVTcGFjZSA9IG5vZGVbJGV4dHJhXS5hdmFpbGFibGVTcGFjZTsKICBjb25zdCBtYXJnaW5WID0gbm9kZS5tYXJnaW4gPyBub2RlLm1hcmdpbi50b3BJbnNldCArIG5vZGUubWFyZ2luLmJvdHRvbUluc2V0IDogMDsKICBjb25zdCBtYXJnaW5IID0gbm9kZS5tYXJnaW4gPyBub2RlLm1hcmdpbi5sZWZ0SW5zZXQgKyBub2RlLm1hcmdpbi5yaWdodEluc2V0IDogMDsKICBzd2l0Y2ggKG5vZGUubGF5b3V0KSB7CiAgICBjYXNlICJsci10YiI6CiAgICBjYXNlICJybC10YiI6CiAgICAgIGlmIChub2RlWyRleHRyYV0uYXR0ZW1wdCA9PT0gMCkgewogICAgICAgIHJldHVybiB7CiAgICAgICAgICB3aWR0aDogYXZhaWxhYmxlU3BhY2Uud2lkdGggLSBtYXJnaW5IIC0gbm9kZVskZXh0cmFdLmN1cnJlbnRXaWR0aCwKICAgICAgICAgIGhlaWdodDogYXZhaWxhYmxlU3BhY2UuaGVpZ2h0IC0gbWFyZ2luViAtIG5vZGVbJGV4dHJhXS5wcmV2SGVpZ2h0CiAgICAgICAgfTsKICAgICAgfQogICAgICByZXR1cm4gewogICAgICAgIHdpZHRoOiBhdmFpbGFibGVTcGFjZS53aWR0aCAtIG1hcmdpbkgsCiAgICAgICAgaGVpZ2h0OiBhdmFpbGFibGVTcGFjZS5oZWlnaHQgLSBtYXJnaW5WIC0gbm9kZVskZXh0cmFdLmhlaWdodAogICAgICB9OwogICAgY2FzZSAicmwtcm93IjoKICAgIGNhc2UgInJvdyI6CiAgICAgIGNvbnN0IHdpZHRoID0gTWF0aC5zdW1QcmVjaXNlKG5vZGVbJGV4dHJhXS5jb2x1bW5XaWR0aHMuc2xpY2Uobm9kZVskZXh0cmFdLmN1cnJlbnRDb2x1bW4pKTsKICAgICAgcmV0dXJuIHsKICAgICAgICB3aWR0aCwKICAgICAgICBoZWlnaHQ6IGF2YWlsYWJsZVNwYWNlLmhlaWdodCAtIG1hcmdpbkgKICAgICAgfTsKICAgIGNhc2UgInRhYmxlIjoKICAgIGNhc2UgInRiIjoKICAgICAgcmV0dXJuIHsKICAgICAgICB3aWR0aDogYXZhaWxhYmxlU3BhY2Uud2lkdGggLSBtYXJnaW5ILAogICAgICAgIGhlaWdodDogYXZhaWxhYmxlU3BhY2UuaGVpZ2h0IC0gbWFyZ2luViAtIG5vZGVbJGV4dHJhXS5oZWlnaHQKICAgICAgfTsKICAgIGNhc2UgInBvc2l0aW9uIjoKICAgIGRlZmF1bHQ6CiAgICAgIHJldHVybiBhdmFpbGFibGVTcGFjZTsKICB9Cn0KZnVuY3Rpb24gZ2V0VHJhbnNmb3JtZWRCQm94KG5vZGUpIHsKICBsZXQgdyA9IG5vZGUudyA9PT0gIiIgPyBOYU4gOiBub2RlLnc7CiAgbGV0IGggPSBub2RlLmggPT09ICIiID8gTmFOIDogbm9kZS5oOwogIGxldCBbY2VudGVyWCwgY2VudGVyWV0gPSBbMCwgMF07CiAgc3dpdGNoIChub2RlLmFuY2hvclR5cGUgfHwgIiIpIHsKICAgIGNhc2UgImJvdHRvbUNlbnRlciI6CiAgICAgIFtjZW50ZXJYLCBjZW50ZXJZXSA9IFt3IC8gMiwgaF07CiAgICAgIGJyZWFrOwogICAgY2FzZSAiYm90dG9tTGVmdCI6CiAgICAgIFtjZW50ZXJYLCBjZW50ZXJZXSA9IFswLCBoXTsKICAgICAgYnJlYWs7CiAgICBjYXNlICJib3R0b21SaWdodCI6CiAgICAgIFtjZW50ZXJYLCBjZW50ZXJZXSA9IFt3LCBoXTsKICAgICAgYnJlYWs7CiAgICBjYXNlICJtaWRkbGVDZW50ZXIiOgogICAgICBbY2VudGVyWCwgY2VudGVyWV0gPSBbdyAvIDIsIGggLyAyXTsKICAgICAgYnJlYWs7CiAgICBjYXNlICJtaWRkbGVMZWZ0IjoKICAgICAgW2NlbnRlclgsIGNlbnRlclldID0gWzAsIGggLyAyXTsKICAgICAgYnJlYWs7CiAgICBjYXNlICJtaWRkbGVSaWdodCI6CiAgICAgIFtjZW50ZXJYLCBjZW50ZXJZXSA9IFt3LCBoIC8gMl07CiAgICAgIGJyZWFrOwogICAgY2FzZSAidG9wQ2VudGVyIjoKICAgICAgW2NlbnRlclgsIGNlbnRlclldID0gW3cgLyAyLCAwXTsKICAgICAgYnJlYWs7CiAgICBjYXNlICJ0b3BSaWdodCI6CiAgICAgIFtjZW50ZXJYLCBjZW50ZXJZXSA9IFt3LCAwXTsKICAgICAgYnJlYWs7CiAgfQogIGxldCB4LCB5OwogIHN3aXRjaCAobm9kZS5yb3RhdGUgfHwgMCkgewogICAgY2FzZSAwOgogICAgICBbeCwgeV0gPSBbLWNlbnRlclgsIC1jZW50ZXJZXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDkwOgogICAgICBbeCwgeV0gPSBbLWNlbnRlclksIGNlbnRlclhdOwogICAgICBbdywgaF0gPSBbaCwgLXddOwogICAgICBicmVhazsKICAgIGNhc2UgMTgwOgogICAgICBbeCwgeV0gPSBbY2VudGVyWCwgY2VudGVyWV07CiAgICAgIFt3LCBoXSA9IFstdywgLWhdOwogICAgICBicmVhazsKICAgIGNhc2UgMjcwOgogICAgICBbeCwgeV0gPSBbY2VudGVyWSwgLWNlbnRlclhdOwogICAgICBbdywgaF0gPSBbLWgsIHddOwogICAgICBicmVhazsKICB9CiAgcmV0dXJuIFtub2RlLnggKyB4ICsgTWF0aC5taW4oMCwgdyksIG5vZGUueSArIHkgKyBNYXRoLm1pbigwLCBoKSwgTWF0aC5hYnModyksIE1hdGguYWJzKGgpXTsKfQpmdW5jdGlvbiBjaGVja0RpbWVuc2lvbnMobm9kZSwgc3BhY2UpIHsKICBpZiAobm9kZVskZ2V0VGVtcGxhdGVSb290XSgpWyRleHRyYV0uZmlyc3RVbnNwbGl0dGFibGUgPT09IG51bGwpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBpZiAobm9kZS53ID09PSAwIHx8IG5vZGUuaCA9PT0gMCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIGNvbnN0IEVSUk9SID0gMjsKICBjb25zdCBwYXJlbnQgPSBub2RlWyRnZXRTdWJmb3JtUGFyZW50XSgpOwogIGNvbnN0IGF0dGVtcHQgPSBwYXJlbnRbJGV4dHJhXT8uYXR0ZW1wdCB8fCAwOwogIGNvbnN0IFssIHksIHcsIGhdID0gZ2V0VHJhbnNmb3JtZWRCQm94KG5vZGUpOwogIHN3aXRjaCAocGFyZW50LmxheW91dCkgewogICAgY2FzZSAibHItdGIiOgogICAgY2FzZSAicmwtdGIiOgogICAgICBpZiAoYXR0ZW1wdCA9PT0gMCkgewogICAgICAgIGlmICghbm9kZVskZ2V0VGVtcGxhdGVSb290XSgpWyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlKSB7CiAgICAgICAgICBpZiAobm9kZS5oICE9PSAiIiAmJiBNYXRoLnJvdW5kKGggLSBzcGFjZS5oZWlnaHQpID4gRVJST1IpIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG5vZGUudyAhPT0gIiIpIHsKICAgICAgICAgICAgaWYgKE1hdGgucm91bmQodyAtIHNwYWNlLndpZHRoKSA8PSBFUlJPUikgewogICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChwYXJlbnRbJGV4dHJhXS5udW1iZXJJbkxpbmUgPT09IDApIHsKICAgICAgICAgICAgICByZXR1cm4gc3BhY2UuaGVpZ2h0ID4gRVJST1I7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHNwYWNlLndpZHRoID4gRVJST1I7CiAgICAgICAgfQogICAgICAgIGlmIChub2RlLncgIT09ICIiKSB7CiAgICAgICAgICByZXR1cm4gTWF0aC5yb3VuZCh3IC0gc3BhY2Uud2lkdGgpIDw9IEVSUk9SOwogICAgICAgIH0KICAgICAgICByZXR1cm4gc3BhY2Uud2lkdGggPiBFUlJPUjsKICAgICAgfQogICAgICBpZiAobm9kZVskZ2V0VGVtcGxhdGVSb290XSgpWyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKG5vZGUuaCAhPT0gIiIgJiYgTWF0aC5yb3VuZChoIC0gc3BhY2UuaGVpZ2h0KSA+IEVSUk9SKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChub2RlLncgPT09ICIiIHx8IE1hdGgucm91bmQodyAtIHNwYWNlLndpZHRoKSA8PSBFUlJPUikgewogICAgICAgIHJldHVybiBzcGFjZS5oZWlnaHQgPiBFUlJPUjsKICAgICAgfQogICAgICBpZiAocGFyZW50WyRpc1RoZXJlTW9yZVdpZHRoXSgpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIHJldHVybiBzcGFjZS5oZWlnaHQgPiBFUlJPUjsKICAgIGNhc2UgInRhYmxlIjoKICAgIGNhc2UgInRiIjoKICAgICAgaWYgKG5vZGVbJGdldFRlbXBsYXRlUm9vdF0oKVskZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmIChub2RlLmggIT09ICIiICYmICFub2RlWyRpc1NwbGl0dGFibGVdKCkpIHsKICAgICAgICByZXR1cm4gTWF0aC5yb3VuZChoIC0gc3BhY2UuaGVpZ2h0KSA8PSBFUlJPUjsKICAgICAgfQogICAgICBpZiAobm9kZS53ID09PSAiIiB8fCBNYXRoLnJvdW5kKHcgLSBzcGFjZS53aWR0aCkgPD0gRVJST1IpIHsKICAgICAgICByZXR1cm4gc3BhY2UuaGVpZ2h0ID4gRVJST1I7CiAgICAgIH0KICAgICAgaWYgKHBhcmVudFskaXNUaGVyZU1vcmVXaWR0aF0oKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICByZXR1cm4gc3BhY2UuaGVpZ2h0ID4gRVJST1I7CiAgICBjYXNlICJwb3NpdGlvbiI6CiAgICAgIGlmIChub2RlWyRnZXRUZW1wbGF0ZVJvb3RdKClbJGV4dHJhXS5ub0xheW91dEZhaWx1cmUpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAobm9kZS5oID09PSAiIiB8fCBNYXRoLnJvdW5kKGggKyB5IC0gc3BhY2UuaGVpZ2h0KSA8PSBFUlJPUikgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGNvbnN0IGFyZWEgPSBub2RlWyRnZXRUZW1wbGF0ZVJvb3RdKClbJGV4dHJhXS5jdXJyZW50Q29udGVudEFyZWE7CiAgICAgIHJldHVybiBoICsgeSA+IGFyZWEuaDsKICAgIGNhc2UgInJsLXJvdyI6CiAgICBjYXNlICJyb3ciOgogICAgICBpZiAobm9kZVskZ2V0VGVtcGxhdGVSb290XSgpWyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKG5vZGUuaCAhPT0gIiIpIHsKICAgICAgICByZXR1cm4gTWF0aC5yb3VuZChoIC0gc3BhY2UuaGVpZ2h0KSA8PSBFUlJPUjsKICAgICAgfQogICAgICByZXR1cm4gdHJ1ZTsKICAgIGRlZmF1bHQ6CiAgICAgIHJldHVybiB0cnVlOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL3RlbXBsYXRlLmpzCgoKCgoKCgoKCgpjb25zdCBURU1QTEFURV9OU19JRCA9IE5hbWVzcGFjZUlkcy50ZW1wbGF0ZS5pZDsKY29uc3QgU1ZHX05TID0gImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIjsKY29uc3QgTUFYX0FUVEVNUFRTX0ZPUl9MUlRCX0xBWU9VVCA9IDI7CmNvbnN0IE1BWF9FTVBUWV9QQUdFUyA9IDM7CmNvbnN0IERFRkFVTFRfVEFCX0lOREVYID0gNTAwMDsKY29uc3QgSEVBRElOR19QQVRURVJOID0gL15IKFxkKykkLzsKY29uc3QgTUlNRVMgPSBuZXcgU2V0KFsiaW1hZ2UvZ2lmIiwgImltYWdlL2pwZWciLCAiaW1hZ2UvanBnIiwgImltYWdlL3BqcGVnIiwgImltYWdlL3BuZyIsICJpbWFnZS9hcG5nIiwgImltYWdlL3gtcG5nIiwgImltYWdlL2JtcCIsICJpbWFnZS94LW1zLWJtcCIsICJpbWFnZS90aWZmIiwgImltYWdlL3RpZiIsICJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0iXSk7CmNvbnN0IElNQUdFU19IRUFERVJTID0gW1tbMHg0MiwgMHg0ZF0sICJpbWFnZS9ibXAiXSwgW1sweGZmLCAweGQ4LCAweGZmXSwgImltYWdlL2pwZWciXSwgW1sweDQ5LCAweDQ5LCAweDJhLCAweDAwXSwgImltYWdlL3RpZmYiXSwgW1sweDRkLCAweDRkLCAweDAwLCAweDJhXSwgImltYWdlL3RpZmYiXSwgW1sweDQ3LCAweDQ5LCAweDQ2LCAweDM4LCAweDM5LCAweDYxXSwgImltYWdlL2dpZiJdLCBbWzB4ODksIDB4NTAsIDB4NGUsIDB4NDcsIDB4MGQsIDB4MGEsIDB4MWEsIDB4MGFdLCAiaW1hZ2UvcG5nIl1dOwpmdW5jdGlvbiBnZXRCb3JkZXJEaW1zKG5vZGUpIHsKICBpZiAoIW5vZGUgfHwgIW5vZGUuYm9yZGVyKSB7CiAgICByZXR1cm4gewogICAgICB3OiAwLAogICAgICBoOiAwCiAgICB9OwogIH0KICBjb25zdCBib3JkZXJFeHRyYSA9IG5vZGUuYm9yZGVyWyRnZXRFeHRyYV0oKTsKICBpZiAoIWJvcmRlckV4dHJhKSB7CiAgICByZXR1cm4gewogICAgICB3OiAwLAogICAgICBoOiAwCiAgICB9OwogIH0KICByZXR1cm4gewogICAgdzogYm9yZGVyRXh0cmEud2lkdGhzWzBdICsgYm9yZGVyRXh0cmEud2lkdGhzWzJdICsgYm9yZGVyRXh0cmEuaW5zZXRzWzBdICsgYm9yZGVyRXh0cmEuaW5zZXRzWzJdLAogICAgaDogYm9yZGVyRXh0cmEud2lkdGhzWzFdICsgYm9yZGVyRXh0cmEud2lkdGhzWzNdICsgYm9yZGVyRXh0cmEuaW5zZXRzWzFdICsgYm9yZGVyRXh0cmEuaW5zZXRzWzNdCiAgfTsKfQpmdW5jdGlvbiBoYXNNYXJnaW4obm9kZSkgewogIHJldHVybiBub2RlLm1hcmdpbiAmJiAobm9kZS5tYXJnaW4udG9wSW5zZXQgfHwgbm9kZS5tYXJnaW4ucmlnaHRJbnNldCB8fCBub2RlLm1hcmdpbi5ib3R0b21JbnNldCB8fCBub2RlLm1hcmdpbi5sZWZ0SW5zZXQpOwp9CmZ1bmN0aW9uIF9zZXRWYWx1ZSh0ZW1wbGF0ZU5vZGUsIHZhbHVlKSB7CiAgaWYgKCF0ZW1wbGF0ZU5vZGUudmFsdWUpIHsKICAgIGNvbnN0IG5vZGVWYWx1ZSA9IG5ldyBWYWx1ZSh7fSk7CiAgICB0ZW1wbGF0ZU5vZGVbJGFwcGVuZENoaWxkXShub2RlVmFsdWUpOwogICAgdGVtcGxhdGVOb2RlLnZhbHVlID0gbm9kZVZhbHVlOwogIH0KICB0ZW1wbGF0ZU5vZGUudmFsdWVbJHNldFZhbHVlXSh2YWx1ZSk7Cn0KZnVuY3Rpb24qIGdldENvbnRhaW5lZENoaWxkcmVuKG5vZGUpIHsKICBmb3IgKGNvbnN0IGNoaWxkIG9mIG5vZGVbJGdldENoaWxkcmVuXSgpKSB7CiAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBTdWJmb3JtU2V0KSB7CiAgICAgIHlpZWxkKiBjaGlsZFskZ2V0Q29udGFpbmVkQ2hpbGRyZW5dKCk7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgeWllbGQgY2hpbGQ7CiAgfQp9CmZ1bmN0aW9uIGlzUmVxdWlyZWQobm9kZSkgewogIHJldHVybiBub2RlLnZhbGlkYXRlPy5udWxsVGVzdCA9PT0gImVycm9yIjsKfQpmdW5jdGlvbiBzZXRUYWJJbmRleChub2RlKSB7CiAgd2hpbGUgKG5vZGUpIHsKICAgIGlmICghbm9kZS50cmF2ZXJzYWwpIHsKICAgICAgbm9kZVskdGFiSW5kZXhdID0gbm9kZVskZ2V0UGFyZW50XSgpWyR0YWJJbmRleF07CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChub2RlWyR0YWJJbmRleF0pIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IG5leHQgPSBudWxsOwogICAgZm9yIChjb25zdCBjaGlsZCBvZiBub2RlLnRyYXZlcnNhbFskZ2V0Q2hpbGRyZW5dKCkpIHsKICAgICAgaWYgKGNoaWxkLm9wZXJhdGlvbiA9PT0gIm5leHQiKSB7CiAgICAgICAgbmV4dCA9IGNoaWxkOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBpZiAoIW5leHQgfHwgIW5leHQucmVmKSB7CiAgICAgIG5vZGVbJHRhYkluZGV4XSA9IG5vZGVbJGdldFBhcmVudF0oKVskdGFiSW5kZXhdOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCByb290ID0gbm9kZVskZ2V0VGVtcGxhdGVSb290XSgpOwogICAgbm9kZVskdGFiSW5kZXhdID0gKytyb290WyR0YWJJbmRleF07CiAgICBjb25zdCByZWYgPSByb290WyRzZWFyY2hOb2RlXShuZXh0LnJlZiwgbm9kZSk7CiAgICBpZiAoIXJlZikgewogICAgICByZXR1cm47CiAgICB9CiAgICBub2RlID0gcmVmWzBdOwogIH0KfQpmdW5jdGlvbiBhcHBseUFzc2lzdChvYmosIGF0dHJpYnV0ZXMpIHsKICBjb25zdCBhc3Npc3QgPSBvYmouYXNzaXN0OwogIGlmIChhc3Npc3QpIHsKICAgIGNvbnN0IGFzc2lzdFRpdGxlID0gYXNzaXN0WyR0b0hUTUxdKCk7CiAgICBpZiAoYXNzaXN0VGl0bGUpIHsKICAgICAgYXR0cmlidXRlcy50aXRsZSA9IGFzc2lzdFRpdGxlOwogICAgfQogICAgY29uc3Qgcm9sZSA9IGFzc2lzdC5yb2xlOwogICAgY29uc3QgbWF0Y2ggPSByb2xlLm1hdGNoKEhFQURJTkdfUEFUVEVSTik7CiAgICBpZiAobWF0Y2gpIHsKICAgICAgY29uc3QgYXJpYVJvbGUgPSAiaGVhZGluZyI7CiAgICAgIGNvbnN0IGFyaWFMZXZlbCA9IG1hdGNoWzFdOwogICAgICBhdHRyaWJ1dGVzLnJvbGUgPSBhcmlhUm9sZTsKICAgICAgYXR0cmlidXRlc1siYXJpYS1sZXZlbCJdID0gYXJpYUxldmVsOwogICAgfQogIH0KICBpZiAob2JqLmxheW91dCA9PT0gInRhYmxlIikgewogICAgYXR0cmlidXRlcy5yb2xlID0gInRhYmxlIjsKICB9IGVsc2UgaWYgKG9iai5sYXlvdXQgPT09ICJyb3ciKSB7CiAgICBhdHRyaWJ1dGVzLnJvbGUgPSAicm93IjsKICB9IGVsc2UgewogICAgY29uc3QgcGFyZW50ID0gb2JqWyRnZXRQYXJlbnRdKCk7CiAgICBpZiAocGFyZW50LmxheW91dCA9PT0gInJvdyIpIHsKICAgICAgYXR0cmlidXRlcy5yb2xlID0gcGFyZW50LmFzc2lzdD8ucm9sZSA9PT0gIlRIIiA/ICJjb2x1bW5oZWFkZXIiIDogImNlbGwiOwogICAgfQogIH0KfQpmdW5jdGlvbiBhcmlhTGFiZWwob2JqKSB7CiAgaWYgKCFvYmouYXNzaXN0KSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgY29uc3QgYXNzaXN0ID0gb2JqLmFzc2lzdDsKICBpZiAoYXNzaXN0LnNwZWFrICYmIGFzc2lzdC5zcGVha1skY29udGVudF0gIT09ICIiKSB7CiAgICByZXR1cm4gYXNzaXN0LnNwZWFrWyRjb250ZW50XTsKICB9CiAgaWYgKGFzc2lzdC50b29sVGlwKSB7CiAgICByZXR1cm4gYXNzaXN0LnRvb2xUaXBbJGNvbnRlbnRdOwogIH0KICByZXR1cm4gbnVsbDsKfQpmdW5jdGlvbiB2YWx1ZVRvSHRtbCh2YWx1ZSkgewogIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgbmFtZTogImRpdiIsCiAgICBhdHRyaWJ1dGVzOiB7CiAgICAgIGNsYXNzOiBbInhmYVJpY2giXSwKICAgICAgc3R5bGU6IE9iamVjdC5jcmVhdGUobnVsbCkKICAgIH0sCiAgICBjaGlsZHJlbjogW3sKICAgICAgbmFtZTogInNwYW4iLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgc3R5bGU6IE9iamVjdC5jcmVhdGUobnVsbCkKICAgICAgfSwKICAgICAgdmFsdWUKICAgIH1dCiAgfSk7Cn0KZnVuY3Rpb24gc2V0Rmlyc3RVbnNwbGl0dGFibGUobm9kZSkgewogIGNvbnN0IHJvb3QgPSBub2RlWyRnZXRUZW1wbGF0ZVJvb3RdKCk7CiAgaWYgKHJvb3RbJGV4dHJhXS5maXJzdFVuc3BsaXR0YWJsZSA9PT0gbnVsbCkgewogICAgcm9vdFskZXh0cmFdLmZpcnN0VW5zcGxpdHRhYmxlID0gbm9kZTsKICAgIHJvb3RbJGV4dHJhXS5ub0xheW91dEZhaWx1cmUgPSB0cnVlOwogIH0KfQpmdW5jdGlvbiB1bnNldEZpcnN0VW5zcGxpdHRhYmxlKG5vZGUpIHsKICBjb25zdCByb290ID0gbm9kZVskZ2V0VGVtcGxhdGVSb290XSgpOwogIGlmIChyb290WyRleHRyYV0uZmlyc3RVbnNwbGl0dGFibGUgPT09IG5vZGUpIHsKICAgIHJvb3RbJGV4dHJhXS5ub0xheW91dEZhaWx1cmUgPSBmYWxzZTsKICB9Cn0KZnVuY3Rpb24gaGFuZGxlQnJlYWsobm9kZSkgewogIGlmIChub2RlWyRleHRyYV0pIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgbm9kZVskZXh0cmFdID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBpZiAobm9kZS50YXJnZXRUeXBlID09PSAiYXV0byIpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgY29uc3Qgcm9vdCA9IG5vZGVbJGdldFRlbXBsYXRlUm9vdF0oKTsKICBsZXQgdGFyZ2V0ID0gbnVsbDsKICBpZiAobm9kZS50YXJnZXQpIHsKICAgIHRhcmdldCA9IHJvb3RbJHNlYXJjaE5vZGVdKG5vZGUudGFyZ2V0LCBub2RlWyRnZXRQYXJlbnRdKCkpOwogICAgaWYgKCF0YXJnZXQpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgdGFyZ2V0ID0gdGFyZ2V0WzBdOwogIH0KICBjb25zdCB7CiAgICBjdXJyZW50UGFnZUFyZWEsCiAgICBjdXJyZW50Q29udGVudEFyZWEKICB9ID0gcm9vdFskZXh0cmFdOwogIGlmIChub2RlLnRhcmdldFR5cGUgPT09ICJwYWdlQXJlYSIpIHsKICAgIGlmICghKHRhcmdldCBpbnN0YW5jZW9mIFBhZ2VBcmVhKSkgewogICAgICB0YXJnZXQgPSBudWxsOwogICAgfQogICAgaWYgKG5vZGUuc3RhcnROZXcpIHsKICAgICAgbm9kZVskZXh0cmFdLnRhcmdldCA9IHRhcmdldCB8fCBjdXJyZW50UGFnZUFyZWE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSBlbHNlIGlmICh0YXJnZXQgJiYgdGFyZ2V0ICE9PSBjdXJyZW50UGFnZUFyZWEpIHsKICAgICAgbm9kZVskZXh0cmFdLnRhcmdldCA9IHRhcmdldDsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGlmICghKHRhcmdldCBpbnN0YW5jZW9mIENvbnRlbnRBcmVhKSkgewogICAgdGFyZ2V0ID0gbnVsbDsKICB9CiAgY29uc3QgcGFnZUFyZWEgPSB0YXJnZXQgJiYgdGFyZ2V0WyRnZXRQYXJlbnRdKCk7CiAgbGV0IGluZGV4OwogIGxldCBuZXh0UGFnZUFyZWEgPSBwYWdlQXJlYTsKICBpZiAobm9kZS5zdGFydE5ldykgewogICAgaWYgKHRhcmdldCkgewogICAgICBjb25zdCBjb250ZW50QXJlYXMgPSBwYWdlQXJlYS5jb250ZW50QXJlYS5jaGlsZHJlbjsKICAgICAgY29uc3QgaW5kZXhGb3JDdXJyZW50ID0gY29udGVudEFyZWFzLmluZGV4T2YoY3VycmVudENvbnRlbnRBcmVhKTsKICAgICAgY29uc3QgaW5kZXhGb3JUYXJnZXQgPSBjb250ZW50QXJlYXMuaW5kZXhPZih0YXJnZXQpOwogICAgICBpZiAoaW5kZXhGb3JDdXJyZW50ICE9PSAtMSAmJiBpbmRleEZvckN1cnJlbnQgPCBpbmRleEZvclRhcmdldCkgewogICAgICAgIG5leHRQYWdlQXJlYSA9IG51bGw7CiAgICAgIH0KICAgICAgaW5kZXggPSBpbmRleEZvclRhcmdldCAtIDE7CiAgICB9IGVsc2UgewogICAgICBpbmRleCA9IGN1cnJlbnRQYWdlQXJlYS5jb250ZW50QXJlYS5jaGlsZHJlbi5pbmRleE9mKGN1cnJlbnRDb250ZW50QXJlYSk7CiAgICB9CiAgfSBlbHNlIGlmICh0YXJnZXQgJiYgdGFyZ2V0ICE9PSBjdXJyZW50Q29udGVudEFyZWEpIHsKICAgIGNvbnN0IGNvbnRlbnRBcmVhcyA9IHBhZ2VBcmVhLmNvbnRlbnRBcmVhLmNoaWxkcmVuOwogICAgaW5kZXggPSBjb250ZW50QXJlYXMuaW5kZXhPZih0YXJnZXQpIC0gMTsKICAgIG5leHRQYWdlQXJlYSA9IHBhZ2VBcmVhID09PSBjdXJyZW50UGFnZUFyZWEgPyBudWxsIDogcGFnZUFyZWE7CiAgfSBlbHNlIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgbm9kZVskZXh0cmFdLnRhcmdldCA9IG5leHRQYWdlQXJlYTsKICBub2RlWyRleHRyYV0uaW5kZXggPSBpbmRleDsKICByZXR1cm4gdHJ1ZTsKfQpmdW5jdGlvbiBoYW5kbGVPdmVyZmxvdyhub2RlLCBleHRyYU5vZGUsIHNwYWNlKSB7CiAgY29uc3Qgcm9vdCA9IG5vZGVbJGdldFRlbXBsYXRlUm9vdF0oKTsKICBjb25zdCBzYXZlZCA9IHJvb3RbJGV4dHJhXS5ub0xheW91dEZhaWx1cmU7CiAgY29uc3Qgc2F2ZWRNZXRob2QgPSBleHRyYU5vZGVbJGdldFN1YmZvcm1QYXJlbnRdOwogIGV4dHJhTm9kZVskZ2V0U3ViZm9ybVBhcmVudF0gPSAoKSA9PiBub2RlOwogIHJvb3RbJGV4dHJhXS5ub0xheW91dEZhaWx1cmUgPSB0cnVlOwogIGNvbnN0IHJlcyA9IGV4dHJhTm9kZVskdG9IVE1MXShzcGFjZSk7CiAgbm9kZVskYWRkSFRNTF0ocmVzLmh0bWwsIHJlcy5iYm94KTsKICByb290WyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlID0gc2F2ZWQ7CiAgZXh0cmFOb2RlWyRnZXRTdWJmb3JtUGFyZW50XSA9IHNhdmVkTWV0aG9kOwp9CmNsYXNzIEFwcGVhcmFuY2VGaWx0ZXIgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYXBwZWFyYW5jZUZpbHRlciIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgQXJjIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImFyYyIsIHRydWUpOwogICAgdGhpcy5jaXJjdWxhciA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmNpcmN1bGFyLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy5oYW5kID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuaGFuZCwgWyJldmVuIiwgImxlZnQiLCAicmlnaHQiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMuc3RhcnRBbmdsZSA9IGdldEZsb2F0KHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5zdGFydEFuZ2xlLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHRydWUKICAgIH0pOwogICAgdGhpcy5zd2VlcEFuZ2xlID0gZ2V0RmxvYXQoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnN3ZWVwQW5nbGUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMzYwLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmVkZ2UgPSBudWxsOwogICAgdGhpcy5maWxsID0gbnVsbDsKICB9CiAgWyR0b0hUTUxdKCkgewogICAgY29uc3QgZWRnZSA9IHRoaXMuZWRnZSB8fCBuZXcgRWRnZSh7fSk7CiAgICBjb25zdCBlZGdlU3R5bGUgPSBlZGdlWyR0b1N0eWxlXSgpOwogICAgY29uc3Qgc3R5bGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgaWYgKHRoaXMuZmlsbD8ucHJlc2VuY2UgPT09ICJ2aXNpYmxlIikgewogICAgICBPYmplY3QuYXNzaWduKHN0eWxlLCB0aGlzLmZpbGxbJHRvU3R5bGVdKCkpOwogICAgfSBlbHNlIHsKICAgICAgc3R5bGUuZmlsbCA9ICJ0cmFuc3BhcmVudCI7CiAgICB9CiAgICBzdHlsZS5zdHJva2VXaWR0aCA9IG1lYXN1cmVUb1N0cmluZyhlZGdlLnByZXNlbmNlID09PSAidmlzaWJsZSIgPyBlZGdlLnRoaWNrbmVzcyA6IDApOwogICAgc3R5bGUuc3Ryb2tlID0gZWRnZVN0eWxlLmNvbG9yOwogICAgbGV0IGFyYzsKICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSB7CiAgICAgIHhtbG5zOiBTVkdfTlMsCiAgICAgIHN0eWxlOiB7CiAgICAgICAgd2lkdGg6ICIxMDAlIiwKICAgICAgICBoZWlnaHQ6ICIxMDAlIiwKICAgICAgICBvdmVyZmxvdzogInZpc2libGUiCiAgICAgIH0KICAgIH07CiAgICBpZiAodGhpcy5zd2VlcEFuZ2xlID09PSAzNjApIHsKICAgICAgYXJjID0gewogICAgICAgIG5hbWU6ICJlbGxpcHNlIiwKICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICB4bWxuczogU1ZHX05TLAogICAgICAgICAgY3g6ICI1MCUiLAogICAgICAgICAgY3k6ICI1MCUiLAogICAgICAgICAgcng6ICI1MCUiLAogICAgICAgICAgcnk6ICI1MCUiLAogICAgICAgICAgc3R5bGUKICAgICAgICB9CiAgICAgIH07CiAgICB9IGVsc2UgewogICAgICBjb25zdCBzdGFydEFuZ2xlID0gdGhpcy5zdGFydEFuZ2xlICogTWF0aC5QSSAvIDE4MDsKICAgICAgY29uc3Qgc3dlZXBBbmdsZSA9IHRoaXMuc3dlZXBBbmdsZSAqIE1hdGguUEkgLyAxODA7CiAgICAgIGNvbnN0IGxhcmdlQXJjID0gdGhpcy5zd2VlcEFuZ2xlID4gMTgwID8gMSA6IDA7CiAgICAgIGNvbnN0IFt4MSwgeTEsIHgyLCB5Ml0gPSBbNTAgKiAoMSArIE1hdGguY29zKHN0YXJ0QW5nbGUpKSwgNTAgKiAoMSAtIE1hdGguc2luKHN0YXJ0QW5nbGUpKSwgNTAgKiAoMSArIE1hdGguY29zKHN0YXJ0QW5nbGUgKyBzd2VlcEFuZ2xlKSksIDUwICogKDEgLSBNYXRoLnNpbihzdGFydEFuZ2xlICsgc3dlZXBBbmdsZSkpXTsKICAgICAgYXJjID0gewogICAgICAgIG5hbWU6ICJwYXRoIiwKICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICB4bWxuczogU1ZHX05TLAogICAgICAgICAgZDogYE0gJHt4MX0gJHt5MX0gQSA1MCA1MCAwICR7bGFyZ2VBcmN9IDAgJHt4Mn0gJHt5Mn1gLAogICAgICAgICAgdmVjdG9yRWZmZWN0OiAibm9uLXNjYWxpbmctc3Ryb2tlIiwKICAgICAgICAgIHN0eWxlCiAgICAgICAgfQogICAgICB9OwogICAgICBPYmplY3QuYXNzaWduKGF0dHJpYnV0ZXMsIHsKICAgICAgICB2aWV3Qm94OiAiMCAwIDEwMCAxMDAiLAogICAgICAgIHByZXNlcnZlQXNwZWN0UmF0aW86ICJub25lIgogICAgICB9KTsKICAgIH0KICAgIGNvbnN0IHN2ZyA9IHsKICAgICAgbmFtZTogInN2ZyIsCiAgICAgIGNoaWxkcmVuOiBbYXJjXSwKICAgICAgYXR0cmlidXRlcwogICAgfTsKICAgIGNvbnN0IHBhcmVudCA9IHRoaXNbJGdldFBhcmVudF0oKVskZ2V0UGFyZW50XSgpOwogICAgaWYgKGhhc01hcmdpbihwYXJlbnQpKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICAgIG5hbWU6ICJkaXYiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIHN0eWxlOiB7CiAgICAgICAgICAgIGRpc3BsYXk6ICJpbmxpbmUiLAogICAgICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgICAgICBoZWlnaHQ6ICIxMDAlIgogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgY2hpbGRyZW46IFtzdmddCiAgICAgIH0pOwogICAgfQogICAgc3ZnLmF0dHJpYnV0ZXMuc3R5bGUucG9zaXRpb24gPSAiYWJzb2x1dGUiOwogICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhzdmcpOwogIH0KfQpjbGFzcyBBcmVhIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImFyZWEiLCB0cnVlKTsKICAgIHRoaXMuY29sU3BhbiA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmNvbFNwYW4sCiAgICAgIGRlZmF1bHRWYWx1ZTogMSwKICAgICAgdmFsaWRhdGU6IG4gPT4gbiA+PSAxIHx8IG4gPT09IC0xCiAgICB9KTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yZWxldmFudCA9IGdldFJlbGV2YW50KGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMueCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMueCwgIjBwdCIpOwogICAgdGhpcy55ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy55LCAiMHB0Iik7CiAgICB0aGlzLmRlc2MgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5hcmVhID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRyYXcgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXhPYmplY3QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXhjbEdyb3VwID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmZpZWxkID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1YmZvcm0gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViZm9ybVNldCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KICAqWyRnZXRDb250YWluZWRDaGlsZHJlbl0oKSB7CiAgICB5aWVsZCogZ2V0Q29udGFpbmVkQ2hpbGRyZW4odGhpcyk7CiAgfQogIFskaXNUcmFuc3BhcmVudF0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgWyRpc0JpbmRhYmxlXSgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJGFkZEhUTUxdKGh0bWwsIGJib3gpIHsKICAgIGNvbnN0IFt4LCB5LCB3LCBoXSA9IGJib3g7CiAgICB0aGlzWyRleHRyYV0ud2lkdGggPSBNYXRoLm1heCh0aGlzWyRleHRyYV0ud2lkdGgsIHggKyB3KTsKICAgIHRoaXNbJGV4dHJhXS5oZWlnaHQgPSBNYXRoLm1heCh0aGlzWyRleHRyYV0uaGVpZ2h0LCB5ICsgaCk7CiAgICB0aGlzWyRleHRyYV0uY2hpbGRyZW4ucHVzaChodG1sKTsKICB9CiAgWyRnZXRBdmFpbGFibGVTcGFjZV0oKSB7CiAgICByZXR1cm4gdGhpc1skZXh0cmFdLmF2YWlsYWJsZVNwYWNlOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAicG9zaXRpb24iKTsKICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSB7CiAgICAgIHN0eWxlLAogICAgICBpZDogdGhpc1skdWlkXSwKICAgICAgY2xhc3M6IFsieGZhQXJlYSJdCiAgICB9OwogICAgaWYgKGlzUHJpbnRPbmx5KHRoaXMpKSB7CiAgICAgIGF0dHJpYnV0ZXMuY2xhc3MucHVzaCgieGZhUHJpbnRPbmx5Iik7CiAgICB9CiAgICBpZiAodGhpcy5uYW1lKSB7CiAgICAgIGF0dHJpYnV0ZXMueGZhTmFtZSA9IHRoaXMubmFtZTsKICAgIH0KICAgIGNvbnN0IGNoaWxkcmVuID0gW107CiAgICB0aGlzWyRleHRyYV0gPSB7CiAgICAgIGNoaWxkcmVuLAogICAgICB3aWR0aDogMCwKICAgICAgaGVpZ2h0OiAwLAogICAgICBhdmFpbGFibGVTcGFjZQogICAgfTsKICAgIGNvbnN0IHJlc3VsdCA9IHRoaXNbJGNoaWxkcmVuVG9IVE1MXSh7CiAgICAgIGZpbHRlcjogbmV3IFNldChbImFyZWEiLCAiZHJhdyIsICJmaWVsZCIsICJleGNsR3JvdXAiLCAic3ViZm9ybSIsICJzdWJmb3JtU2V0Il0pLAogICAgICBpbmNsdWRlOiB0cnVlCiAgICB9KTsKICAgIGlmICghcmVzdWx0LnN1Y2Nlc3MpIHsKICAgICAgaWYgKHJlc3VsdC5pc0JyZWFrKCkpIHsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CiAgICAgIGRlbGV0ZSB0aGlzWyRleHRyYV07CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkZBSUxVUkU7CiAgICB9CiAgICBzdHlsZS53aWR0aCA9IG1lYXN1cmVUb1N0cmluZyh0aGlzWyRleHRyYV0ud2lkdGgpOwogICAgc3R5bGUuaGVpZ2h0ID0gbWVhc3VyZVRvU3RyaW5nKHRoaXNbJGV4dHJhXS5oZWlnaHQpOwogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGNoaWxkcmVuCiAgICB9OwogICAgY29uc3QgYmJveCA9IFt0aGlzLngsIHRoaXMueSwgdGhpc1skZXh0cmFdLndpZHRoLCB0aGlzWyRleHRyYV0uaGVpZ2h0XTsKICAgIGRlbGV0ZSB0aGlzWyRleHRyYV07CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKGh0bWwsIGJib3gpOwogIH0KfQpjbGFzcyBBc3Npc3QgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYXNzaXN0IiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMucm9sZSA9IGF0dHJpYnV0ZXMucm9sZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnNwZWFrID0gbnVsbDsKICAgIHRoaXMudG9vbFRpcCA9IG51bGw7CiAgfQogIFskdG9IVE1MXSgpIHsKICAgIHJldHVybiB0aGlzLnRvb2xUaXA/LlskY29udGVudF0gfHwgbnVsbDsKICB9Cn0KY2xhc3MgQmFyY29kZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJiYXJjb2RlIiwgdHJ1ZSk7CiAgICB0aGlzLmNoYXJFbmNvZGluZyA9IGdldEtleXdvcmQoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmNoYXJFbmNvZGluZyA/IGF0dHJpYnV0ZXMuY2hhckVuY29kaW5nLnRvTG93ZXJDYXNlKCkgOiAiIiwKICAgICAgZGVmYXVsdFZhbHVlOiAiIiwKICAgICAgdmFsaWRhdGU6IGsgPT4gWyJ1dGYtOCIsICJiaWctZml2ZSIsICJmb250c3BlY2lmaWMiLCAiZ2JrIiwgImdiLTE4MDMwIiwgImdiLTIzMTIiLCAia3NjLTU2MDEiLCAibm9uZSIsICJzaGlmdC1qaXMiLCAidWNzLTIiLCAidXRmLTE2Il0uaW5jbHVkZXMoaykgfHwgay5tYXRjaCgvaXNvLTg4NTktXGR7Mn0vKQogICAgfSk7CiAgICB0aGlzLmNoZWNrc3VtID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuY2hlY2tzdW0sIFsibm9uZSIsICIxbW9kMTAiLCAiMW1vZDEwXzFtb2QxMSIsICIybW9kMTAiLCAiYXV0byJdKTsKICAgIHRoaXMuZGF0YUNvbHVtbkNvdW50ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZGF0YUNvbHVtbkNvdW50LAogICAgICBkZWZhdWx0VmFsdWU6IC0xLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy5kYXRhTGVuZ3RoID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZGF0YUxlbmd0aCwKICAgICAgZGVmYXVsdFZhbHVlOiAtMSwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICAgIHRoaXMuZGF0YVByZXAgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5kYXRhUHJlcCwgWyJub25lIiwgImZsYXRlQ29tcHJlc3MiXSk7CiAgICB0aGlzLmRhdGFSb3dDb3VudCA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmRhdGFSb3dDb3VudCwKICAgICAgZGVmYXVsdFZhbHVlOiAtMSwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICAgIHRoaXMuZW5kQ2hhciA9IGF0dHJpYnV0ZXMuZW5kQ2hhciB8fCAiIjsKICAgIHRoaXMuZXJyb3JDb3JyZWN0aW9uTGV2ZWwgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5lcnJvckNvcnJlY3Rpb25MZXZlbCwKICAgICAgZGVmYXVsdFZhbHVlOiAtMSwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwICYmIHggPD0gOAogICAgfSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubW9kdWxlSGVpZ2h0ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5tb2R1bGVIZWlnaHQsICI1bW0iKTsKICAgIHRoaXMubW9kdWxlV2lkdGggPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1vZHVsZVdpZHRoLCAiMC4yNW1tIik7CiAgICB0aGlzLnByaW50Q2hlY2tEaWdpdCA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnByaW50Q2hlY2tEaWdpdCwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMucm93Q29sdW1uUmF0aW8gPSBnZXRSYXRpbyhhdHRyaWJ1dGVzLnJvd0NvbHVtblJhdGlvKTsKICAgIHRoaXMuc3RhcnRDaGFyID0gYXR0cmlidXRlcy5zdGFydENoYXIgfHwgIiI7CiAgICB0aGlzLnRleHRMb2NhdGlvbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnRleHRMb2NhdGlvbiwgWyJiZWxvdyIsICJhYm92ZSIsICJhYm92ZUVtYmVkZGVkIiwgImJlbG93RW1iZWRkZWQiLCAibm9uZSJdKTsKICAgIHRoaXMudHJ1bmNhdGUgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy50cnVuY2F0ZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMudHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnR5cGUgPyBhdHRyaWJ1dGVzLnR5cGUudG9Mb3dlckNhc2UoKSA6ICIiLCBbImF6dGVjIiwgImNvZGFiYXIiLCAiY29kZTJvZjVpbmR1c3RyaWFsIiwgImNvZGUyb2Y1aW50ZXJsZWF2ZWQiLCAiY29kZTJvZjVtYXRyaXgiLCAiY29kZTJvZjVzdGFuZGFyZCIsICJjb2RlM29mOSIsICJjb2RlM29mOWV4dGVuZGVkIiwgImNvZGUxMSIsICJjb2RlNDkiLCAiY29kZTkzIiwgImNvZGUxMjgiLCAiY29kZTEyOGEiLCAiY29kZTEyOGIiLCAiY29kZTEyOGMiLCAiY29kZTEyOHNzY2MiLCAiZGF0YW1hdHJpeCIsICJlYW44IiwgImVhbjhhZGQyIiwgImVhbjhhZGQ1IiwgImVhbjEzIiwgImVhbjEzYWRkMiIsICJlYW4xM2FkZDUiLCAiZWFuMTNwd2NkIiwgImZpbSIsICJsb2dtYXJzIiwgIm1heGljb2RlIiwgIm1zaSIsICJwZGY0MTciLCAicGRmNDE3bWFjcm8iLCAicGxlc3NleSIsICJwb3N0YXVzY3VzdDIiLCAicG9zdGF1c2N1c3QzIiwgInBvc3RhdXNyZXBseXBhaWQiLCAicG9zdGF1c3N0YW5kYXJkIiwgInBvc3R1a3JtNHNjYyIsICJwb3N0dXNkcGJjIiwgInBvc3R1c2ltYiIsICJwb3N0dXNzdGFuZGFyZCIsICJwb3N0dXM1emlwIiwgInFyY29kZSIsICJyZmlkIiwgInJzczE0IiwgInJzczE0ZXhwYW5kZWQiLCAicnNzMTRsaW1pdGVkIiwgInJzczE0c3RhY2tlZCIsICJyc3MxNHN0YWNrZWRvbW5pIiwgInJzczE0dHJ1bmNhdGVkIiwgInRlbGVwZW4iLCAidWNjMTI4IiwgInVjYzEyOHJhbmRvbSIsICJ1Y2MxMjhzc2NjIiwgInVwY2EiLCAidXBjYWFkZDIiLCAidXBjYWFkZDUiLCAidXBjYXB3Y2QiLCAidXBjZSIsICJ1cGNlYWRkMiIsICJ1cGNlYWRkNSIsICJ1cGNlYW4yIiwgInVwY2VhbjUiLCAidXBzbWF4aWNvZGUiXSk7CiAgICB0aGlzLnVwc01vZGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy51cHNNb2RlLCBbInVzQ2FycmllciIsICJpbnRlcm5hdGlvbmFsQ2FycmllciIsICJzZWN1cmVTeW1ib2wiLCAic3RhbmRhcmRTeW1ib2wiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy53aWRlTmFycm93UmF0aW8gPSBnZXRSYXRpbyhhdHRyaWJ1dGVzLndpZGVOYXJyb3dSYXRpbyk7CiAgICB0aGlzLmVuY3J5cHQgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KfQpjbGFzcyBCaW5kIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImJpbmQiLCB0cnVlKTsKICAgIHRoaXMubWF0Y2ggPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5tYXRjaCwgWyJvbmNlIiwgImRhdGFSZWYiLCAiZ2xvYmFsIiwgIm5vbmUiXSk7CiAgICB0aGlzLnJlZiA9IGF0dHJpYnV0ZXMucmVmIHx8ICIiOwogICAgdGhpcy5waWN0dXJlID0gbnVsbDsKICB9Cn0KY2xhc3MgQmluZEl0ZW1zIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImJpbmRJdGVtcyIpOwogICAgdGhpcy5jb25uZWN0aW9uID0gYXR0cmlidXRlcy5jb25uZWN0aW9uIHx8ICIiOwogICAgdGhpcy5sYWJlbFJlZiA9IGF0dHJpYnV0ZXMubGFiZWxSZWYgfHwgIiI7CiAgICB0aGlzLnJlZiA9IGF0dHJpYnV0ZXMucmVmIHx8ICIiOwogICAgdGhpcy52YWx1ZVJlZiA9IGF0dHJpYnV0ZXMudmFsdWVSZWYgfHwgIiI7CiAgfQp9CmNsYXNzIEJvb2tlbmQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYm9va2VuZCIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxlYWRlciA9IGF0dHJpYnV0ZXMubGVhZGVyIHx8ICIiOwogICAgdGhpcy50cmFpbGVyID0gYXR0cmlidXRlcy50cmFpbGVyIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgQm9vbGVhbkVsZW1lbnQgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJib29sZWFuIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgcmV0dXJuIHZhbHVlVG9IdG1sKHRoaXNbJGNvbnRlbnRdID09PSAxID8gIjEiIDogIjAiKTsKICB9Cn0KY2xhc3MgQm9yZGVyIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImJvcmRlciIsIHRydWUpOwogICAgdGhpcy5icmVhayA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmJyZWFrLCBbImNsb3NlIiwgIm9wZW4iXSk7CiAgICB0aGlzLmhhbmQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oYW5kLCBbImV2ZW4iLCAibGVmdCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5wcmVzZW5jZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnByZXNlbmNlLCBbInZpc2libGUiLCAiaGlkZGVuIiwgImluYWN0aXZlIiwgImludmlzaWJsZSJdKTsKICAgIHRoaXMucmVsZXZhbnQgPSBnZXRSZWxldmFudChhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNvcm5lciA9IG5ldyBYRkFPYmplY3RBcnJheSg0KTsKICAgIHRoaXMuZWRnZSA9IG5ldyBYRkFPYmplY3RBcnJheSg0KTsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuZmlsbCA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgfQogIFskZ2V0RXh0cmFdKCkgewogICAgaWYgKCF0aGlzWyRleHRyYV0pIHsKICAgICAgY29uc3QgZWRnZXMgPSB0aGlzLmVkZ2UuY2hpbGRyZW4uc2xpY2UoKTsKICAgICAgaWYgKGVkZ2VzLmxlbmd0aCA8IDQpIHsKICAgICAgICBjb25zdCBkZWZhdWx0RWRnZSA9IGVkZ2VzLmF0KC0xKSB8fCBuZXcgRWRnZSh7fSk7CiAgICAgICAgZm9yIChsZXQgaSA9IGVkZ2VzLmxlbmd0aDsgaSA8IDQ7IGkrKykgewogICAgICAgICAgZWRnZXMucHVzaChkZWZhdWx0RWRnZSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGNvbnN0IHdpZHRocyA9IGVkZ2VzLm1hcChlZGdlID0+IGVkZ2UudGhpY2tuZXNzKTsKICAgICAgY29uc3QgaW5zZXRzID0gWzAsIDAsIDAsIDBdOwogICAgICBpZiAodGhpcy5tYXJnaW4pIHsKICAgICAgICBpbnNldHNbMF0gPSB0aGlzLm1hcmdpbi50b3BJbnNldDsKICAgICAgICBpbnNldHNbMV0gPSB0aGlzLm1hcmdpbi5yaWdodEluc2V0OwogICAgICAgIGluc2V0c1syXSA9IHRoaXMubWFyZ2luLmJvdHRvbUluc2V0OwogICAgICAgIGluc2V0c1szXSA9IHRoaXMubWFyZ2luLmxlZnRJbnNldDsKICAgICAgfQogICAgICB0aGlzWyRleHRyYV0gPSB7CiAgICAgICAgd2lkdGhzLAogICAgICAgIGluc2V0cywKICAgICAgICBlZGdlcwogICAgICB9OwogICAgfQogICAgcmV0dXJuIHRoaXNbJGV4dHJhXTsKICB9CiAgWyR0b1N0eWxlXSgpIHsKICAgIGNvbnN0IHsKICAgICAgZWRnZXMKICAgIH0gPSB0aGlzWyRnZXRFeHRyYV0oKTsKICAgIGNvbnN0IGVkZ2VTdHlsZXMgPSBlZGdlcy5tYXAobm9kZSA9PiB7CiAgICAgIGNvbnN0IHN0eWxlID0gbm9kZVskdG9TdHlsZV0oKTsKICAgICAgc3R5bGUuY29sb3IgfHw9ICIjMDAwMDAwIjsKICAgICAgcmV0dXJuIHN0eWxlOwogICAgfSk7CiAgICBjb25zdCBzdHlsZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBpZiAodGhpcy5tYXJnaW4pIHsKICAgICAgT2JqZWN0LmFzc2lnbihzdHlsZSwgdGhpcy5tYXJnaW5bJHRvU3R5bGVdKCkpOwogICAgfQogICAgaWYgKHRoaXMuZmlsbD8ucHJlc2VuY2UgPT09ICJ2aXNpYmxlIikgewogICAgICBPYmplY3QuYXNzaWduKHN0eWxlLCB0aGlzLmZpbGxbJHRvU3R5bGVdKCkpOwogICAgfQogICAgaWYgKHRoaXMuY29ybmVyLmNoaWxkcmVuLnNvbWUobm9kZSA9PiBub2RlLnJhZGl1cyAhPT0gMCkpIHsKICAgICAgY29uc3QgY29ybmVyU3R5bGVzID0gdGhpcy5jb3JuZXIuY2hpbGRyZW4ubWFwKG5vZGUgPT4gbm9kZVskdG9TdHlsZV0oKSk7CiAgICAgIGlmIChjb3JuZXJTdHlsZXMubGVuZ3RoID09PSAyIHx8IGNvcm5lclN0eWxlcy5sZW5ndGggPT09IDMpIHsKICAgICAgICBjb25zdCBsYXN0ID0gY29ybmVyU3R5bGVzLmF0KC0xKTsKICAgICAgICBmb3IgKGxldCBpID0gY29ybmVyU3R5bGVzLmxlbmd0aDsgaSA8IDQ7IGkrKykgewogICAgICAgICAgY29ybmVyU3R5bGVzLnB1c2gobGFzdCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHN0eWxlLmJvcmRlclJhZGl1cyA9IGNvcm5lclN0eWxlcy5tYXAocyA9PiBzLnJhZGl1cykuam9pbigiICIpOwogICAgfQogICAgc3dpdGNoICh0aGlzLnByZXNlbmNlKSB7CiAgICAgIGNhc2UgImludmlzaWJsZSI6CiAgICAgIGNhc2UgImhpZGRlbiI6CiAgICAgICAgc3R5bGUuYm9yZGVyU3R5bGUgPSAiIjsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiaW5hY3RpdmUiOgogICAgICAgIHN0eWxlLmJvcmRlclN0eWxlID0gIm5vbmUiOwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHN0eWxlLmJvcmRlclN0eWxlID0gZWRnZVN0eWxlcy5tYXAocyA9PiBzLnN0eWxlKS5qb2luKCIgIik7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBzdHlsZS5ib3JkZXJXaWR0aCA9IGVkZ2VTdHlsZXMubWFwKHMgPT4gcy53aWR0aCkuam9pbigiICIpOwogICAgc3R5bGUuYm9yZGVyQ29sb3IgPSBlZGdlU3R5bGVzLm1hcChzID0+IHMuY29sb3IpLmpvaW4oIiAiKTsKICAgIHJldHVybiBzdHlsZTsKICB9Cn0KY2xhc3MgQnJlYWsgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYnJlYWsiLCB0cnVlKTsKICAgIHRoaXMuYWZ0ZXIgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5hZnRlciwgWyJhdXRvIiwgImNvbnRlbnRBcmVhIiwgInBhZ2VBcmVhIiwgInBhZ2VFdmVuIiwgInBhZ2VPZGQiXSk7CiAgICB0aGlzLmFmdGVyVGFyZ2V0ID0gYXR0cmlidXRlcy5hZnRlclRhcmdldCB8fCAiIjsKICAgIHRoaXMuYmVmb3JlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuYmVmb3JlLCBbImF1dG8iLCAiY29udGVudEFyZWEiLCAicGFnZUFyZWEiLCAicGFnZUV2ZW4iLCAicGFnZU9kZCJdKTsKICAgIHRoaXMuYmVmb3JlVGFyZ2V0ID0gYXR0cmlidXRlcy5iZWZvcmVUYXJnZXQgfHwgIiI7CiAgICB0aGlzLmJvb2tlbmRMZWFkZXIgPSBhdHRyaWJ1dGVzLmJvb2tlbmRMZWFkZXIgfHwgIiI7CiAgICB0aGlzLmJvb2tlbmRUcmFpbGVyID0gYXR0cmlidXRlcy5ib29rZW5kVHJhaWxlciB8fCAiIjsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5vdmVyZmxvd0xlYWRlciA9IGF0dHJpYnV0ZXMub3ZlcmZsb3dMZWFkZXIgfHwgIiI7CiAgICB0aGlzLm92ZXJmbG93VGFyZ2V0ID0gYXR0cmlidXRlcy5vdmVyZmxvd1RhcmdldCB8fCAiIjsKICAgIHRoaXMub3ZlcmZsb3dUcmFpbGVyID0gYXR0cmlidXRlcy5vdmVyZmxvd1RyYWlsZXIgfHwgIiI7CiAgICB0aGlzLnN0YXJ0TmV3ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuc3RhcnROZXcsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KfQpjbGFzcyBCcmVha0FmdGVyIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImJyZWFrQWZ0ZXIiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5sZWFkZXIgPSBhdHRyaWJ1dGVzLmxlYWRlciB8fCAiIjsKICAgIHRoaXMuc3RhcnROZXcgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5zdGFydE5ldywKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMudGFyZ2V0ID0gYXR0cmlidXRlcy50YXJnZXQgfHwgIiI7CiAgICB0aGlzLnRhcmdldFR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50YXJnZXRUeXBlLCBbImF1dG8iLCAiY29udGVudEFyZWEiLCAicGFnZUFyZWEiXSk7CiAgICB0aGlzLnRyYWlsZXIgPSBhdHRyaWJ1dGVzLnRyYWlsZXIgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5zY3JpcHQgPSBudWxsOwogIH0KfQpjbGFzcyBCcmVha0JlZm9yZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJicmVha0JlZm9yZSIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxlYWRlciA9IGF0dHJpYnV0ZXMubGVhZGVyIHx8ICIiOwogICAgdGhpcy5zdGFydE5ldyA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnN0YXJ0TmV3LAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy50YXJnZXQgPSBhdHRyaWJ1dGVzLnRhcmdldCB8fCAiIjsKICAgIHRoaXMudGFyZ2V0VHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnRhcmdldFR5cGUsIFsiYXV0byIsICJjb250ZW50QXJlYSIsICJwYWdlQXJlYSJdKTsKICAgIHRoaXMudHJhaWxlciA9IGF0dHJpYnV0ZXMudHJhaWxlciB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnNjcmlwdCA9IG51bGw7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgdGhpc1skZXh0cmFdID0ge307CiAgICByZXR1cm4gSFRNTFJlc3VsdC5GQUlMVVJFOwogIH0KfQpjbGFzcyBCdXR0b24gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYnV0dG9uIiwgdHJ1ZSk7CiAgICB0aGlzLmhpZ2hsaWdodCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmhpZ2hsaWdodCwgWyJpbnZlcnRlZCIsICJub25lIiwgIm91dGxpbmUiLCAicHVzaCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBncmFuZHBhID0gcGFyZW50WyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBodG1sQnV0dG9uID0gewogICAgICBuYW1lOiAiYnV0dG9uIiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGlkOiB0aGlzWyR1aWRdLAogICAgICAgIGNsYXNzOiBbInhmYUJ1dHRvbiJdLAogICAgICAgIHN0eWxlOiB7fQogICAgICB9LAogICAgICBjaGlsZHJlbjogW10KICAgIH07CiAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGdyYW5kcGEuZXZlbnQuY2hpbGRyZW4pIHsKICAgICAgaWYgKGV2ZW50LmFjdGl2aXR5ICE9PSAiY2xpY2siIHx8ICFldmVudC5zY3JpcHQpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBqc1VSTCA9IHJlY292ZXJKc1VSTChldmVudC5zY3JpcHRbJGNvbnRlbnRdKTsKICAgICAgaWYgKCFqc1VSTCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGhyZWYgPSBmaXhVUkwoanNVUkwudXJsKTsKICAgICAgaWYgKCFocmVmKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaHRtbEJ1dHRvbi5jaGlsZHJlbi5wdXNoKHsKICAgICAgICBuYW1lOiAiYSIsCiAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgaWQ6ICJsaW5rIiArIHRoaXNbJHVpZF0sCiAgICAgICAgICBocmVmLAogICAgICAgICAgbmV3V2luZG93OiBqc1VSTC5uZXdXaW5kb3csCiAgICAgICAgICBjbGFzczogWyJ4ZmFMaW5rIl0sCiAgICAgICAgICBzdHlsZToge30KICAgICAgICB9LAogICAgICAgIGNoaWxkcmVuOiBbXQogICAgICB9KTsKICAgIH0KICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoaHRtbEJ1dHRvbik7CiAgfQp9CmNsYXNzIENhbGN1bGF0ZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJjYWxjdWxhdGUiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5vdmVycmlkZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm92ZXJyaWRlLCBbImRpc2FibGVkIiwgImVycm9yIiwgImlnbm9yZSIsICJ3YXJuaW5nIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMubWVzc2FnZSA9IG51bGw7CiAgICB0aGlzLnNjcmlwdCA9IG51bGw7CiAgfQp9CmNsYXNzIENhcHRpb24gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiY2FwdGlvbiIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnBsYWNlbWVudCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnBsYWNlbWVudCwgWyJsZWZ0IiwgImJvdHRvbSIsICJpbmxpbmUiLCAicmlnaHQiLCAidG9wIl0pOwogICAgdGhpcy5wcmVzZW5jZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnByZXNlbmNlLCBbInZpc2libGUiLCAiaGlkZGVuIiwgImluYWN0aXZlIiwgImludmlzaWJsZSJdKTsKICAgIHRoaXMucmVzZXJ2ZSA9IE1hdGguY2VpbChnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnJlc2VydmUpKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmZvbnQgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogICAgdGhpcy5wYXJhID0gbnVsbDsKICAgIHRoaXMudmFsdWUgPSBudWxsOwogIH0KICBbJHNldFZhbHVlXSh2YWx1ZSkgewogICAgX3NldFZhbHVlKHRoaXMsIHZhbHVlKTsKICB9CiAgWyRnZXRFeHRyYV0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGlmICghdGhpc1skZXh0cmFdKSB7CiAgICAgIGxldCB7CiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0CiAgICAgIH0gPSBhdmFpbGFibGVTcGFjZTsKICAgICAgc3dpdGNoICh0aGlzLnBsYWNlbWVudCkgewogICAgICAgIGNhc2UgImxlZnQiOgogICAgICAgIGNhc2UgInJpZ2h0IjoKICAgICAgICBjYXNlICJpbmxpbmUiOgogICAgICAgICAgd2lkdGggPSB0aGlzLnJlc2VydmUgPD0gMCA/IHdpZHRoIDogdGhpcy5yZXNlcnZlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAidG9wIjoKICAgICAgICBjYXNlICJib3R0b20iOgogICAgICAgICAgaGVpZ2h0ID0gdGhpcy5yZXNlcnZlIDw9IDAgPyBoZWlnaHQgOiB0aGlzLnJlc2VydmU7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICB0aGlzWyRleHRyYV0gPSBsYXlvdXROb2RlKHRoaXMsIHsKICAgICAgICB3aWR0aCwKICAgICAgICBoZWlnaHQKICAgICAgfSk7CiAgICB9CiAgICByZXR1cm4gdGhpc1skZXh0cmFdOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGlmICghdGhpcy52YWx1ZSkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIHRoaXNbJHB1c2hQYXJhXSgpOwogICAgY29uc3QgdmFsdWUgPSB0aGlzLnZhbHVlWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKS5odG1sOwogICAgaWYgKCF2YWx1ZSkgewogICAgICB0aGlzWyRwb3BQYXJhXSgpOwogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGNvbnN0IHNhdmVkUmVzZXJ2ZSA9IHRoaXMucmVzZXJ2ZTsKICAgIGlmICh0aGlzLnJlc2VydmUgPD0gMCkgewogICAgICBjb25zdCB7CiAgICAgICAgdywKICAgICAgICBoCiAgICAgIH0gPSB0aGlzWyRnZXRFeHRyYV0oYXZhaWxhYmxlU3BhY2UpOwogICAgICBzd2l0Y2ggKHRoaXMucGxhY2VtZW50KSB7CiAgICAgICAgY2FzZSAibGVmdCI6CiAgICAgICAgY2FzZSAicmlnaHQiOgogICAgICAgIGNhc2UgImlubGluZSI6CiAgICAgICAgICB0aGlzLnJlc2VydmUgPSB3OwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAidG9wIjoKICAgICAgICBjYXNlICJib3R0b20iOgogICAgICAgICAgdGhpcy5yZXNlcnZlID0gaDsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gInN0cmluZyIpIHsKICAgICAgY2hpbGRyZW4ucHVzaCh7CiAgICAgICAgbmFtZTogIiN0ZXh0IiwKICAgICAgICB2YWx1ZQogICAgICB9KTsKICAgIH0gZWxzZSB7CiAgICAgIGNoaWxkcmVuLnB1c2godmFsdWUpOwogICAgfQogICAgY29uc3Qgc3R5bGUgPSB0b1N0eWxlKHRoaXMsICJmb250IiwgIm1hcmdpbiIsICJ2aXNpYmlsaXR5Iik7CiAgICBzd2l0Y2ggKHRoaXMucGxhY2VtZW50KSB7CiAgICAgIGNhc2UgImxlZnQiOgogICAgICBjYXNlICJyaWdodCI6CiAgICAgICAgaWYgKHRoaXMucmVzZXJ2ZSA+IDApIHsKICAgICAgICAgIHN0eWxlLndpZHRoID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMucmVzZXJ2ZSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJ0b3AiOgogICAgICBjYXNlICJib3R0b20iOgogICAgICAgIGlmICh0aGlzLnJlc2VydmUgPiAwKSB7CiAgICAgICAgICBzdHlsZS5oZWlnaHQgPSBtZWFzdXJlVG9TdHJpbmcodGhpcy5yZXNlcnZlKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBzZXRQYXJhKHRoaXMsIG51bGwsIHZhbHVlKTsKICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICB0aGlzLnJlc2VydmUgPSBzYXZlZFJlc2VydmU7CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBzdHlsZSwKICAgICAgICBjbGFzczogWyJ4ZmFDYXB0aW9uIl0KICAgICAgfSwKICAgICAgY2hpbGRyZW4KICAgIH0pOwogIH0KfQpjbGFzcyBDZXJ0aWZpY2F0ZSBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJjZXJ0aWZpY2F0ZSIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBDZXJ0aWZpY2F0ZXMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiY2VydGlmaWNhdGVzIiwgdHJ1ZSk7CiAgICB0aGlzLmNyZWRlbnRpYWxTZXJ2ZXJQb2xpY3kgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5jcmVkZW50aWFsU2VydmVyUG9saWN5LCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVybCA9IGF0dHJpYnV0ZXMudXJsIHx8ICIiOwogICAgdGhpcy51cmxQb2xpY3kgPSBhdHRyaWJ1dGVzLnVybFBvbGljeSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmVuY3J5cHRpb24gPSBudWxsOwogICAgdGhpcy5pc3N1ZXJzID0gbnVsbDsKICAgIHRoaXMua2V5VXNhZ2UgPSBudWxsOwogICAgdGhpcy5vaWRzID0gbnVsbDsKICAgIHRoaXMuc2lnbmluZyA9IG51bGw7CiAgICB0aGlzLnN1YmplY3RETnMgPSBudWxsOwogIH0KfQpjbGFzcyBDaGVja0J1dHRvbiBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJjaGVja0J1dHRvbiIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm1hcmsgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5tYXJrLCBbImRlZmF1bHQiLCAiY2hlY2siLCAiY2lyY2xlIiwgImNyb3NzIiwgImRpYW1vbmQiLCAic3F1YXJlIiwgInN0YXIiXSk7CiAgICB0aGlzLnNoYXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuc2hhcGUsIFsic3F1YXJlIiwgInJvdW5kIl0pOwogICAgdGhpcy5zaXplID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5zaXplLCAiMTBwdCIpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBzdHlsZSA9IHRvU3R5bGUodGhpcywgIm1hcmdpbiIpOwogICAgY29uc3Qgc2l6ZSA9IG1lYXN1cmVUb1N0cmluZyh0aGlzLnNpemUpOwogICAgc3R5bGUud2lkdGggPSBzdHlsZS5oZWlnaHQgPSBzaXplOwogICAgbGV0IHR5cGU7CiAgICBsZXQgY2xhc3NOYW1lOwogICAgbGV0IGdyb3VwSWQ7CiAgICBjb25zdCBmaWVsZCA9IHRoaXNbJGdldFBhcmVudF0oKVskZ2V0UGFyZW50XSgpOwogICAgY29uc3QgaXRlbXMgPSBmaWVsZC5pdGVtcy5jaGlsZHJlbi5sZW5ndGggJiYgZmllbGQuaXRlbXMuY2hpbGRyZW5bMF1bJHRvSFRNTF0oKS5odG1sIHx8IFtdOwogICAgY29uc3QgZXhwb3J0ZWRWYWx1ZSA9IHsKICAgICAgb246IChpdGVtc1swXSAhPT0gdW5kZWZpbmVkID8gaXRlbXNbMF0gOiAib24iKS50b1N0cmluZygpLAogICAgICBvZmY6IChpdGVtc1sxXSAhPT0gdW5kZWZpbmVkID8gaXRlbXNbMV0gOiAib2ZmIikudG9TdHJpbmcoKQogICAgfTsKICAgIGNvbnN0IHZhbHVlID0gZmllbGQudmFsdWU/LlskdGV4dF0oKSB8fCAib2ZmIjsKICAgIGNvbnN0IGNoZWNrZWQgPSB2YWx1ZSA9PT0gZXhwb3J0ZWRWYWx1ZS5vbiB8fCB1bmRlZmluZWQ7CiAgICBjb25zdCBjb250YWluZXIgPSBmaWVsZFskZ2V0U3ViZm9ybVBhcmVudF0oKTsKICAgIGNvbnN0IGZpZWxkSWQgPSBmaWVsZFskdWlkXTsKICAgIGxldCBkYXRhSWQ7CiAgICBpZiAoY29udGFpbmVyIGluc3RhbmNlb2YgRXhjbEdyb3VwKSB7CiAgICAgIGdyb3VwSWQgPSBjb250YWluZXJbJHVpZF07CiAgICAgIHR5cGUgPSAicmFkaW8iOwogICAgICBjbGFzc05hbWUgPSAieGZhUmFkaW8iOwogICAgICBkYXRhSWQgPSBjb250YWluZXJbJGRhdGFdPy5bJHVpZF0gfHwgY29udGFpbmVyWyR1aWRdOwogICAgfSBlbHNlIHsKICAgICAgdHlwZSA9ICJjaGVja2JveCI7CiAgICAgIGNsYXNzTmFtZSA9ICJ4ZmFDaGVja2JveCI7CiAgICAgIGRhdGFJZCA9IGZpZWxkWyRkYXRhXT8uWyR1aWRdIHx8IGZpZWxkWyR1aWRdOwogICAgfQogICAgY29uc3QgaW5wdXQgPSB7CiAgICAgIG5hbWU6ICJpbnB1dCIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBjbGFzczogW2NsYXNzTmFtZV0sCiAgICAgICAgc3R5bGUsCiAgICAgICAgZmllbGRJZCwKICAgICAgICBkYXRhSWQsCiAgICAgICAgdHlwZSwKICAgICAgICBjaGVja2VkLAogICAgICAgIHhmYU9uOiBleHBvcnRlZFZhbHVlLm9uLAogICAgICAgIHhmYU9mZjogZXhwb3J0ZWRWYWx1ZS5vZmYsCiAgICAgICAgImFyaWEtbGFiZWwiOiBhcmlhTGFiZWwoZmllbGQpLAogICAgICAgICJhcmlhLXJlcXVpcmVkIjogZmFsc2UKICAgICAgfQogICAgfTsKICAgIGlmIChncm91cElkKSB7CiAgICAgIGlucHV0LmF0dHJpYnV0ZXMubmFtZSA9IGdyb3VwSWQ7CiAgICB9CiAgICBpZiAoaXNSZXF1aXJlZChmaWVsZCkpIHsKICAgICAgaW5wdXQuYXR0cmlidXRlc1siYXJpYS1yZXF1aXJlZCJdID0gdHJ1ZTsKICAgICAgaW5wdXQuYXR0cmlidXRlcy5yZXF1aXJlZCA9IHRydWU7CiAgICB9CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImxhYmVsIiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBbInhmYUxhYmVsIl0KICAgICAgfSwKICAgICAgY2hpbGRyZW46IFtpbnB1dF0KICAgIH0pOwogIH0KfQpjbGFzcyBDaG9pY2VMaXN0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNob2ljZUxpc3QiLCB0cnVlKTsKICAgIHRoaXMuY29tbWl0T24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5jb21taXRPbiwgWyJzZWxlY3QiLCAiZXhpdCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5vcGVuID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMub3BlbiwgWyJ1c2VyQ29udHJvbCIsICJhbHdheXMiLCAibXVsdGlTZWxlY3QiLCAib25FbnRyeSJdKTsKICAgIHRoaXMudGV4dEVudHJ5ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMudGV4dEVudHJ5LAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBzdHlsZSA9IHRvU3R5bGUodGhpcywgImJvcmRlciIsICJtYXJnaW4iKTsKICAgIGNvbnN0IHVpID0gdGhpc1skZ2V0UGFyZW50XSgpOwogICAgY29uc3QgZmllbGQgPSB1aVskZ2V0UGFyZW50XSgpOwogICAgY29uc3QgZm9udFNpemUgPSBmaWVsZC5mb250Py5zaXplIHx8IDEwOwogICAgY29uc3Qgb3B0aW9uU3R5bGUgPSB7CiAgICAgIGZvbnRTaXplOiBgY2FsYygke2ZvbnRTaXplfXB4ICogdmFyKC0tdG90YWwtc2NhbGUtZmFjdG9yKSlgCiAgICB9OwogICAgY29uc3QgY2hpbGRyZW4gPSBbXTsKICAgIGlmIChmaWVsZC5pdGVtcy5jaGlsZHJlbi5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IGl0ZW1zID0gZmllbGQuaXRlbXM7CiAgICAgIGxldCBkaXNwbGF5ZWRJbmRleCA9IDA7CiAgICAgIGxldCBzYXZlSW5kZXggPSAwOwogICAgICBpZiAoaXRlbXMuY2hpbGRyZW4ubGVuZ3RoID09PSAyKSB7CiAgICAgICAgZGlzcGxheWVkSW5kZXggPSBpdGVtcy5jaGlsZHJlblswXS5zYXZlOwogICAgICAgIHNhdmVJbmRleCA9IDEgLSBkaXNwbGF5ZWRJbmRleDsKICAgICAgfQogICAgICBjb25zdCBkaXNwbGF5ZWQgPSBpdGVtcy5jaGlsZHJlbltkaXNwbGF5ZWRJbmRleF1bJHRvSFRNTF0oKS5odG1sOwogICAgICBjb25zdCB2YWx1ZXMgPSBpdGVtcy5jaGlsZHJlbltzYXZlSW5kZXhdWyR0b0hUTUxdKCkuaHRtbDsKICAgICAgbGV0IHNlbGVjdGVkID0gZmFsc2U7CiAgICAgIGNvbnN0IHZhbHVlID0gZmllbGQudmFsdWU/LlskdGV4dF0oKSB8fCAiIjsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZGlzcGxheWVkLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb25zdCBvcHRpb24gPSB7CiAgICAgICAgICBuYW1lOiAib3B0aW9uIiwKICAgICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgICAgdmFsdWU6IHZhbHVlc1tpXSB8fCBkaXNwbGF5ZWRbaV0sCiAgICAgICAgICAgIHN0eWxlOiBvcHRpb25TdHlsZQogICAgICAgICAgfSwKICAgICAgICAgIHZhbHVlOiBkaXNwbGF5ZWRbaV0KICAgICAgICB9OwogICAgICAgIGlmICh2YWx1ZXNbaV0gPT09IHZhbHVlKSB7CiAgICAgICAgICBvcHRpb24uYXR0cmlidXRlcy5zZWxlY3RlZCA9IHNlbGVjdGVkID0gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgY2hpbGRyZW4ucHVzaChvcHRpb24pOwogICAgICB9CiAgICAgIGlmICghc2VsZWN0ZWQpIHsKICAgICAgICBjaGlsZHJlbi5zcGxpY2UoMCwgMCwgewogICAgICAgICAgbmFtZTogIm9wdGlvbiIsCiAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgIGhpZGRlbjogdHJ1ZSwKICAgICAgICAgICAgc2VsZWN0ZWQ6IHRydWUKICAgICAgICAgIH0sCiAgICAgICAgICB2YWx1ZTogIiAiCiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHNlbGVjdEF0dHJpYnV0ZXMgPSB7CiAgICAgIGNsYXNzOiBbInhmYVNlbGVjdCJdLAogICAgICBmaWVsZElkOiBmaWVsZFskdWlkXSwKICAgICAgZGF0YUlkOiBmaWVsZFskZGF0YV0/LlskdWlkXSB8fCBmaWVsZFskdWlkXSwKICAgICAgc3R5bGUsCiAgICAgICJhcmlhLWxhYmVsIjogYXJpYUxhYmVsKGZpZWxkKSwKICAgICAgImFyaWEtcmVxdWlyZWQiOiBmYWxzZQogICAgfTsKICAgIGlmIChpc1JlcXVpcmVkKGZpZWxkKSkgewogICAgICBzZWxlY3RBdHRyaWJ1dGVzWyJhcmlhLXJlcXVpcmVkIl0gPSB0cnVlOwogICAgICBzZWxlY3RBdHRyaWJ1dGVzLnJlcXVpcmVkID0gdHJ1ZTsKICAgIH0KICAgIGlmICh0aGlzLm9wZW4gPT09ICJtdWx0aVNlbGVjdCIpIHsKICAgICAgc2VsZWN0QXR0cmlidXRlcy5tdWx0aXBsZSA9IHRydWU7CiAgICB9CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImxhYmVsIiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBbInhmYUxhYmVsIl0KICAgICAgfSwKICAgICAgY2hpbGRyZW46IFt7CiAgICAgICAgbmFtZTogInNlbGVjdCIsCiAgICAgICAgY2hpbGRyZW4sCiAgICAgICAgYXR0cmlidXRlczogc2VsZWN0QXR0cmlidXRlcwogICAgICB9XQogICAgfSk7CiAgfQp9CmNsYXNzIENvbG9yIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNvbG9yIiwgdHJ1ZSk7CiAgICB0aGlzLmNTcGFjZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmNTcGFjZSwgWyJTUkdCIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy52YWx1ZSA9IGF0dHJpYnV0ZXMudmFsdWUgPyBnZXRDb2xvcihhdHRyaWJ1dGVzLnZhbHVlKSA6ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbJGhhc1NldHRhYmxlVmFsdWVdKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBbJHRvU3R5bGVdKCkgewogICAgcmV0dXJuIHRoaXMudmFsdWUgPyBVdGlsLm1ha2VIZXhDb2xvcih0aGlzLnZhbHVlLnIsIHRoaXMudmFsdWUuZywgdGhpcy52YWx1ZS5iKSA6IG51bGw7CiAgfQp9CmNsYXNzIENvbWIgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiY29tYiIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm51bWJlck9mQ2VsbHMgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5udW1iZXJPZkNlbGxzLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMAogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBDb25uZWN0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNvbm5lY3QiLCB0cnVlKTsKICAgIHRoaXMuY29ubmVjdGlvbiA9IGF0dHJpYnV0ZXMuY29ubmVjdGlvbiB8fCAiIjsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5yZWYgPSBhdHRyaWJ1dGVzLnJlZiB8fCAiIjsKICAgIHRoaXMudXNhZ2UgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy51c2FnZSwgWyJleHBvcnRBbmRJbXBvcnQiLCAiZXhwb3J0T25seSIsICJpbXBvcnRPbmx5Il0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMucGljdHVyZSA9IG51bGw7CiAgfQp9CmNsYXNzIENvbnRlbnRBcmVhIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNvbnRlbnRBcmVhIiwgdHJ1ZSk7CiAgICB0aGlzLmggPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLmgpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnJlbGV2YW50ID0gZ2V0UmVsZXZhbnQoYXR0cmlidXRlcy5yZWxldmFudCk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy53ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy53KTsKICAgIHRoaXMueCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMueCwgIjBwdCIpOwogICAgdGhpcy55ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy55LCAiMHB0Iik7CiAgICB0aGlzLmRlc2MgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IGxlZnQgPSBtZWFzdXJlVG9TdHJpbmcodGhpcy54KTsKICAgIGNvbnN0IHRvcCA9IG1lYXN1cmVUb1N0cmluZyh0aGlzLnkpOwogICAgY29uc3Qgc3R5bGUgPSB7CiAgICAgIGxlZnQsCiAgICAgIHRvcCwKICAgICAgd2lkdGg6IG1lYXN1cmVUb1N0cmluZyh0aGlzLncpLAogICAgICBoZWlnaHQ6IG1lYXN1cmVUb1N0cmluZyh0aGlzLmgpCiAgICB9OwogICAgY29uc3QgY2xhc3NOYW1lcyA9IFsieGZhQ29udGVudGFyZWEiXTsKICAgIGlmIChpc1ByaW50T25seSh0aGlzKSkgewogICAgICBjbGFzc05hbWVzLnB1c2goInhmYVByaW50T25seSIpOwogICAgfQogICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6ICJkaXYiLAogICAgICBjaGlsZHJlbjogW10sCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBzdHlsZSwKICAgICAgICBjbGFzczogY2xhc3NOYW1lcywKICAgICAgICBpZDogdGhpc1skdWlkXQogICAgICB9CiAgICB9KTsKICB9Cn0KY2xhc3MgQ29ybmVyIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNvcm5lciIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmludmVydGVkID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuaW52ZXJ0ZWQsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmpvaW4gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5qb2luLCBbInNxdWFyZSIsICJyb3VuZCJdKTsKICAgIHRoaXMucHJlc2VuY2UgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5wcmVzZW5jZSwgWyJ2aXNpYmxlIiwgImhpZGRlbiIsICJpbmFjdGl2ZSIsICJpbnZpc2libGUiXSk7CiAgICB0aGlzLnJhZGl1cyA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMucmFkaXVzKTsKICAgIHRoaXMuc3Ryb2tlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuc3Ryb2tlLCBbInNvbGlkIiwgImRhc2hEb3QiLCAiZGFzaERvdERvdCIsICJkYXNoZWQiLCAiZG90dGVkIiwgImVtYm9zc2VkIiwgImV0Y2hlZCIsICJsb3dlcmVkIiwgInJhaXNlZCJdKTsKICAgIHRoaXMudGhpY2tuZXNzID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy50aGlja25lc3MsICIwLjVwdCIpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29sb3IgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbJHRvU3R5bGVdKCkgewogICAgY29uc3Qgc3R5bGUgPSB0b1N0eWxlKHRoaXMsICJ2aXNpYmlsaXR5Iik7CiAgICBzdHlsZS5yYWRpdXMgPSBtZWFzdXJlVG9TdHJpbmcodGhpcy5qb2luID09PSAic3F1YXJlIiA/IDAgOiB0aGlzLnJhZGl1cyk7CiAgICByZXR1cm4gc3R5bGU7CiAgfQp9CmNsYXNzIERhdGVFbGVtZW50IGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJkYXRlIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgY29uc3QgZGF0ZSA9IHRoaXNbJGNvbnRlbnRdLnRyaW0oKTsKICAgIHRoaXNbJGNvbnRlbnRdID0gZGF0ZSA/IG5ldyBEYXRlKGRhdGUpIDogbnVsbDsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gdmFsdWVUb0h0bWwodGhpc1skY29udGVudF0gPyB0aGlzWyRjb250ZW50XS50b1N0cmluZygpIDogIiIpOwogIH0KfQpjbGFzcyBEYXRlVGltZSBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZGF0ZVRpbWUiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICBjb25zdCBkYXRlID0gdGhpc1skY29udGVudF0udHJpbSgpOwogICAgdGhpc1skY29udGVudF0gPSBkYXRlID8gbmV3IERhdGUoZGF0ZSkgOiBudWxsOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIHJldHVybiB2YWx1ZVRvSHRtbCh0aGlzWyRjb250ZW50XSA/IHRoaXNbJGNvbnRlbnRdLnRvU3RyaW5nKCkgOiAiIik7CiAgfQp9CmNsYXNzIERhdGVUaW1lRWRpdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJkYXRlVGltZUVkaXQiLCB0cnVlKTsKICAgIHRoaXMuaFNjcm9sbFBvbGljeSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmhTY3JvbGxQb2xpY3ksIFsiYXV0byIsICJvZmYiLCAib24iXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMucGlja2VyID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucGlja2VyLCBbImhvc3QiLCAibm9uZSJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvcmRlciA9IG51bGw7CiAgICB0aGlzLmNvbWIgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAiYm9yZGVyIiwgImZvbnQiLCAibWFyZ2luIik7CiAgICBjb25zdCBmaWVsZCA9IHRoaXNbJGdldFBhcmVudF0oKVskZ2V0UGFyZW50XSgpOwogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImlucHV0IiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIHR5cGU6ICJ0ZXh0IiwKICAgICAgICBmaWVsZElkOiBmaWVsZFskdWlkXSwKICAgICAgICBkYXRhSWQ6IGZpZWxkWyRkYXRhXT8uWyR1aWRdIHx8IGZpZWxkWyR1aWRdLAogICAgICAgIGNsYXNzOiBbInhmYVRleHRmaWVsZCJdLAogICAgICAgIHN0eWxlLAogICAgICAgICJhcmlhLWxhYmVsIjogYXJpYUxhYmVsKGZpZWxkKSwKICAgICAgICAiYXJpYS1yZXF1aXJlZCI6IGZhbHNlCiAgICAgIH0KICAgIH07CiAgICBpZiAoaXNSZXF1aXJlZChmaWVsZCkpIHsKICAgICAgaHRtbC5hdHRyaWJ1dGVzWyJhcmlhLXJlcXVpcmVkIl0gPSB0cnVlOwogICAgICBodG1sLmF0dHJpYnV0ZXMucmVxdWlyZWQgPSB0cnVlOwogICAgfQogICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6ICJsYWJlbCIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBjbGFzczogWyJ4ZmFMYWJlbCJdCiAgICAgIH0sCiAgICAgIGNoaWxkcmVuOiBbaHRtbF0KICAgIH0pOwogIH0KfQpjbGFzcyBEZWNpbWFsIGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJkZWNpbWFsIik7CiAgICB0aGlzLmZyYWNEaWdpdHMgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5mcmFjRGlnaXRzLAogICAgICBkZWZhdWx0VmFsdWU6IDIsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHRydWUKICAgIH0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxlYWREaWdpdHMgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5sZWFkRGlnaXRzLAogICAgICBkZWZhdWx0VmFsdWU6IC0xLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgY29uc3QgbnVtYmVyID0gcGFyc2VGbG9hdCh0aGlzWyRjb250ZW50XS50cmltKCkpOwogICAgdGhpc1skY29udGVudF0gPSBpc05hTihudW1iZXIpID8gbnVsbCA6IG51bWJlcjsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gdmFsdWVUb0h0bWwodGhpc1skY29udGVudF0gIT09IG51bGwgPyB0aGlzWyRjb250ZW50XS50b1N0cmluZygpIDogIiIpOwogIH0KfQpjbGFzcyBEZWZhdWx0VWkgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZGVmYXVsdFVpIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQp9CmNsYXNzIERlc2MgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZGVzYyIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib29sZWFuID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZVRpbWUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGVjaW1hbCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leERhdGEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmxvYXQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaW1hZ2UgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaW50ZWdlciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50ZXh0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRpbWUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgRGlnZXN0TWV0aG9kIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImRpZ2VzdE1ldGhvZCIsIFsiIiwgIlNIQTEiLCAiU0hBMjU2IiwgIlNIQTUxMiIsICJSSVBFTUQxNjAiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIERpZ2VzdE1ldGhvZHMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZGlnZXN0TWV0aG9kcyIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZGlnZXN0TWV0aG9kID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIERyYXcgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZHJhdyIsIHRydWUpOwogICAgdGhpcy5hbmNob3JUeXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuYW5jaG9yVHlwZSwgWyJ0b3BMZWZ0IiwgImJvdHRvbUNlbnRlciIsICJib3R0b21MZWZ0IiwgImJvdHRvbVJpZ2h0IiwgIm1pZGRsZUNlbnRlciIsICJtaWRkbGVMZWZ0IiwgIm1pZGRsZVJpZ2h0IiwgInRvcENlbnRlciIsICJ0b3BSaWdodCJdKTsKICAgIHRoaXMuY29sU3BhbiA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmNvbFNwYW4sCiAgICAgIGRlZmF1bHRWYWx1ZTogMSwKICAgICAgdmFsaWRhdGU6IG4gPT4gbiA+PSAxIHx8IG4gPT09IC0xCiAgICB9KTsKICAgIHRoaXMuaCA9IGF0dHJpYnV0ZXMuaCA/IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMuaCkgOiAiIjsKICAgIHRoaXMuaEFsaWduID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuaEFsaWduLCBbImxlZnQiLCAiY2VudGVyIiwgImp1c3RpZnkiLCAianVzdGlmeUFsbCIsICJyYWRpeCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5sb2NhbGUgPSBhdHRyaWJ1dGVzLmxvY2FsZSB8fCAiIjsKICAgIHRoaXMubWF4SCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubWF4SCwgIjBwdCIpOwogICAgdGhpcy5tYXhXID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5tYXhXLCAiMHB0Iik7CiAgICB0aGlzLm1pbkggPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1pbkgsICIwcHQiKTsKICAgIHRoaXMubWluVyA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubWluVywgIjBwdCIpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5wcmVzZW5jZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnByZXNlbmNlLCBbInZpc2libGUiLCAiaGlkZGVuIiwgImluYWN0aXZlIiwgImludmlzaWJsZSJdKTsKICAgIHRoaXMucmVsZXZhbnQgPSBnZXRSZWxldmFudChhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMucm90YXRlID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMucm90YXRlLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggJSA5MCA9PT0gMAogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy53ID0gYXR0cmlidXRlcy53ID8gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy53KSA6ICIiOwogICAgdGhpcy54ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy54LCAiMHB0Iik7CiAgICB0aGlzLnkgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnksICIwcHQiKTsKICAgIHRoaXMuYXNzaXN0ID0gbnVsbDsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuY2FwdGlvbiA9IG51bGw7CiAgICB0aGlzLmRlc2MgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5mb250ID0gbnVsbDsKICAgIHRoaXMua2VlcCA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgICB0aGlzLnBhcmEgPSBudWxsOwogICAgdGhpcy50cmF2ZXJzYWwgPSBudWxsOwogICAgdGhpcy51aSA9IG51bGw7CiAgICB0aGlzLnZhbHVlID0gbnVsbDsKICAgIHRoaXMuc2V0UHJvcGVydHkgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9CiAgWyRzZXRWYWx1ZV0odmFsdWUpIHsKICAgIF9zZXRWYWx1ZSh0aGlzLCB2YWx1ZSk7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgc2V0VGFiSW5kZXgodGhpcyk7CiAgICBpZiAodGhpcy5wcmVzZW5jZSA9PT0gImhpZGRlbiIgfHwgdGhpcy5wcmVzZW5jZSA9PT0gImluYWN0aXZlIikgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGZpeERpbWVuc2lvbnModGhpcyk7CiAgICB0aGlzWyRwdXNoUGFyYV0oKTsKICAgIGNvbnN0IHNhdmVkVyA9IHRoaXMudzsKICAgIGNvbnN0IHNhdmVkSCA9IHRoaXMuaDsKICAgIGNvbnN0IHsKICAgICAgdywKICAgICAgaCwKICAgICAgaXNCcm9rZW4KICAgIH0gPSBsYXlvdXROb2RlKHRoaXMsIGF2YWlsYWJsZVNwYWNlKTsKICAgIGlmICh3ICYmIHRoaXMudyA9PT0gIiIpIHsKICAgICAgaWYgKGlzQnJva2VuICYmIHRoaXNbJGdldFN1YmZvcm1QYXJlbnRdKClbJGlzVGhlcmVNb3JlV2lkdGhdKCkpIHsKICAgICAgICB0aGlzWyRwb3BQYXJhXSgpOwogICAgICAgIHJldHVybiBIVE1MUmVzdWx0LkZBSUxVUkU7CiAgICAgIH0KICAgICAgdGhpcy53ID0gdzsKICAgIH0KICAgIGlmIChoICYmIHRoaXMuaCA9PT0gIiIpIHsKICAgICAgdGhpcy5oID0gaDsKICAgIH0KICAgIHNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgaWYgKCFjaGVja0RpbWVuc2lvbnModGhpcywgYXZhaWxhYmxlU3BhY2UpKSB7CiAgICAgIHRoaXMudyA9IHNhdmVkVzsKICAgICAgdGhpcy5oID0gc2F2ZWRIOwogICAgICB0aGlzWyRwb3BQYXJhXSgpOwogICAgICByZXR1cm4gSFRNTFJlc3VsdC5GQUlMVVJFOwogICAgfQogICAgdW5zZXRGaXJzdFVuc3BsaXR0YWJsZSh0aGlzKTsKICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAiZm9udCIsICJoQWxpZ24iLCAiZGltZW5zaW9ucyIsICJwb3NpdGlvbiIsICJwcmVzZW5jZSIsICJyb3RhdGUiLCAiYW5jaG9yVHlwZSIsICJib3JkZXIiLCAibWFyZ2luIik7CiAgICBzZXRNaW5NYXhEaW1lbnNpb25zKHRoaXMsIHN0eWxlKTsKICAgIGlmIChzdHlsZS5tYXJnaW4pIHsKICAgICAgc3R5bGUucGFkZGluZyA9IHN0eWxlLm1hcmdpbjsKICAgICAgZGVsZXRlIHN0eWxlLm1hcmdpbjsKICAgIH0KICAgIGNvbnN0IGNsYXNzTmFtZXMgPSBbInhmYURyYXciXTsKICAgIGlmICh0aGlzLmZvbnQpIHsKICAgICAgY2xhc3NOYW1lcy5wdXNoKCJ4ZmFGb250Iik7CiAgICB9CiAgICBpZiAoaXNQcmludE9ubHkodGhpcykpIHsKICAgICAgY2xhc3NOYW1lcy5wdXNoKCJ4ZmFQcmludE9ubHkiKTsKICAgIH0KICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSB7CiAgICAgIHN0eWxlLAogICAgICBpZDogdGhpc1skdWlkXSwKICAgICAgY2xhc3M6IGNsYXNzTmFtZXMKICAgIH07CiAgICBpZiAodGhpcy5uYW1lKSB7CiAgICAgIGF0dHJpYnV0ZXMueGZhTmFtZSA9IHRoaXMubmFtZTsKICAgIH0KICAgIGNvbnN0IGh0bWwgPSB7CiAgICAgIG5hbWU6ICJkaXYiLAogICAgICBhdHRyaWJ1dGVzLAogICAgICBjaGlsZHJlbjogW10KICAgIH07CiAgICBhcHBseUFzc2lzdCh0aGlzLCBhdHRyaWJ1dGVzKTsKICAgIGNvbnN0IGJib3ggPSBjb21wdXRlQmJveCh0aGlzLCBodG1sLCBhdmFpbGFibGVTcGFjZSk7CiAgICBjb25zdCB2YWx1ZSA9IHRoaXMudmFsdWUgPyB0aGlzLnZhbHVlWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKS5odG1sIDogbnVsbDsKICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkgewogICAgICB0aGlzLncgPSBzYXZlZFc7CiAgICAgIHRoaXMuaCA9IHNhdmVkSDsKICAgICAgdGhpc1skcG9wUGFyYV0oKTsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhjcmVhdGVXcmFwcGVyKHRoaXMsIGh0bWwpLCBiYm94KTsKICAgIH0KICAgIGh0bWwuY2hpbGRyZW4ucHVzaCh2YWx1ZSk7CiAgICBzZXRQYXJhKHRoaXMsIHN0eWxlLCB2YWx1ZSk7CiAgICB0aGlzLncgPSBzYXZlZFc7CiAgICB0aGlzLmggPSBzYXZlZEg7CiAgICB0aGlzWyRwb3BQYXJhXSgpOwogICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhjcmVhdGVXcmFwcGVyKHRoaXMsIGh0bWwpLCBiYm94KTsKICB9Cn0KY2xhc3MgRWRnZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJlZGdlIiwgdHJ1ZSk7CiAgICB0aGlzLmNhcCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmNhcCwgWyJzcXVhcmUiLCAiYnV0dCIsICJyb3VuZCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5wcmVzZW5jZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnByZXNlbmNlLCBbInZpc2libGUiLCAiaGlkZGVuIiwgImluYWN0aXZlIiwgImludmlzaWJsZSJdKTsKICAgIHRoaXMuc3Ryb2tlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuc3Ryb2tlLCBbInNvbGlkIiwgImRhc2hEb3QiLCAiZGFzaERvdERvdCIsICJkYXNoZWQiLCAiZG90dGVkIiwgImVtYm9zc2VkIiwgImV0Y2hlZCIsICJsb3dlcmVkIiwgInJhaXNlZCJdKTsKICAgIHRoaXMudGhpY2tuZXNzID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy50aGlja25lc3MsICIwLjVwdCIpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29sb3IgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbJHRvU3R5bGVdKCkgewogICAgY29uc3Qgc3R5bGUgPSB0b1N0eWxlKHRoaXMsICJ2aXNpYmlsaXR5Iik7CiAgICBPYmplY3QuYXNzaWduKHN0eWxlLCB7CiAgICAgIGxpbmVjYXA6IHRoaXMuY2FwLAogICAgICB3aWR0aDogbWVhc3VyZVRvU3RyaW5nKHRoaXMudGhpY2tuZXNzKSwKICAgICAgY29sb3I6IHRoaXMuY29sb3IgPyB0aGlzLmNvbG9yWyR0b1N0eWxlXSgpIDogIiMwMDAwMDAiLAogICAgICBzdHlsZTogIiIKICAgIH0pOwogICAgaWYgKHRoaXMucHJlc2VuY2UgIT09ICJ2aXNpYmxlIikgewogICAgICBzdHlsZS5zdHlsZSA9ICJub25lIjsKICAgIH0gZWxzZSB7CiAgICAgIHN3aXRjaCAodGhpcy5zdHJva2UpIHsKICAgICAgICBjYXNlICJzb2xpZCI6CiAgICAgICAgICBzdHlsZS5zdHlsZSA9ICJzb2xpZCI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJkYXNoRG90IjoKICAgICAgICAgIHN0eWxlLnN0eWxlID0gImRhc2hlZCI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJkYXNoRG90RG90IjoKICAgICAgICAgIHN0eWxlLnN0eWxlID0gImRhc2hlZCI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJkYXNoZWQiOgogICAgICAgICAgc3R5bGUuc3R5bGUgPSAiZGFzaGVkIjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImRvdHRlZCI6CiAgICAgICAgICBzdHlsZS5zdHlsZSA9ICJkb3R0ZWQiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZW1ib3NzZWQiOgogICAgICAgICAgc3R5bGUuc3R5bGUgPSAicmlkZ2UiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZXRjaGVkIjoKICAgICAgICAgIHN0eWxlLnN0eWxlID0gImdyb292ZSI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJsb3dlcmVkIjoKICAgICAgICAgIHN0eWxlLnN0eWxlID0gImluc2V0IjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInJhaXNlZCI6CiAgICAgICAgICBzdHlsZS5zdHlsZSA9ICJvdXRzZXQiOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzdHlsZTsKICB9Cn0KY2xhc3MgRW5jb2RpbmcgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZW5jb2RpbmciLCBbImFkYmUueDUwOS5yc2Ffc2hhMSIsICJhZGJlLnBrY3M3LmRldGFjaGVkIiwgImFkYmUucGtjczcuc2hhMSJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgRW5jb2RpbmdzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImVuY29kaW5ncyIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZW5jb2RpbmcgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgRW5jcnlwdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJlbmNyeXB0IiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNlcnRpZmljYXRlID0gbnVsbDsKICB9Cn0KY2xhc3MgRW5jcnlwdERhdGEgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZW5jcnlwdERhdGEiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5vcGVyYXRpb24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5vcGVyYXRpb24sIFsiZW5jcnlwdCIsICJkZWNyeXB0Il0pOwogICAgdGhpcy50YXJnZXQgPSBhdHRyaWJ1dGVzLnRhcmdldCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmZpbHRlciA9IG51bGw7CiAgICB0aGlzLm1hbmlmZXN0ID0gbnVsbDsKICB9Cn0KY2xhc3MgRW5jcnlwdGlvbiBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJlbmNyeXB0aW9uIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jZXJ0aWZpY2F0ZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBFbmNyeXB0aW9uTWV0aG9kIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImVuY3J5cHRpb25NZXRob2QiLCBbIiIsICJBRVMyNTYtQ0JDIiwgIlRSSVBMRURFUy1DQkMiLCAiQUVTMTI4LUNCQyIsICJBRVMxOTItQ0JDIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBFbmNyeXB0aW9uTWV0aG9kcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJlbmNyeXB0aW9uTWV0aG9kcyIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZW5jcnlwdGlvbk1ldGhvZCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBFdmVudCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJldmVudCIsIHRydWUpOwogICAgdGhpcy5hY3Rpdml0eSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmFjdGl2aXR5LCBbImNsaWNrIiwgImNoYW5nZSIsICJkb2NDbG9zZSIsICJkb2NSZWFkeSIsICJlbnRlciIsICJleGl0IiwgImZ1bGwiLCAiaW5kZXhDaGFuZ2UiLCAiaW5pdGlhbGl6ZSIsICJtb3VzZURvd24iLCAibW91c2VFbnRlciIsICJtb3VzZUV4aXQiLCAibW91c2VVcCIsICJwb3N0RXhlY3V0ZSIsICJwb3N0T3BlbiIsICJwb3N0UHJpbnQiLCAicG9zdFNhdmUiLCAicG9zdFNpZ24iLCAicG9zdFN1Ym1pdCIsICJwcmVFeGVjdXRlIiwgInByZU9wZW4iLCAicHJlUHJpbnQiLCAicHJlU2F2ZSIsICJwcmVTaWduIiwgInByZVN1Ym1pdCIsICJyZWFkeSIsICJ2YWxpZGF0aW9uU3RhdGUiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubGlzdGVuID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMubGlzdGVuLCBbInJlZk9ubHkiLCAicmVmQW5kRGVzY2VuZGVudHMiXSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnJlZiA9IGF0dHJpYnV0ZXMucmVmIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuZW5jcnlwdERhdGEgPSBudWxsOwogICAgdGhpcy5leGVjdXRlID0gbnVsbDsKICAgIHRoaXMuc2NyaXB0ID0gbnVsbDsKICAgIHRoaXMuc2lnbkRhdGEgPSBudWxsOwogICAgdGhpcy5zdWJtaXQgPSBudWxsOwogIH0KfQpjbGFzcyBFeERhdGEgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImV4RGF0YSIpOwogICAgdGhpcy5jb250ZW50VHlwZSA9IGF0dHJpYnV0ZXMuY29udGVudFR5cGUgfHwgIiI7CiAgICB0aGlzLmhyZWYgPSBhdHRyaWJ1dGVzLmhyZWYgfHwgIiI7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubWF4TGVuZ3RoID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMubWF4TGVuZ3RoLAogICAgICBkZWZhdWx0VmFsdWU6IC0xLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IC0xCiAgICB9KTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucmlkID0gYXR0cmlidXRlcy5yaWQgfHwgIiI7CiAgICB0aGlzLnRyYW5zZmVyRW5jb2RpbmcgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50cmFuc2ZlckVuY29kaW5nLCBbIm5vbmUiLCAiYmFzZTY0IiwgInBhY2thZ2UiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KICBbJGlzQ0RBVEFYbWxdKCkgewogICAgcmV0dXJuIHRoaXMuY29udGVudFR5cGUgPT09ICJ0ZXh0L2h0bWwiOwogIH0KICBbJG9uQ2hpbGRdKGNoaWxkKSB7CiAgICBpZiAodGhpcy5jb250ZW50VHlwZSA9PT0gInRleHQvaHRtbCIgJiYgY2hpbGRbJG5hbWVzcGFjZUlkXSA9PT0gTmFtZXNwYWNlSWRzLnhodG1sLmlkKSB7CiAgICAgIHRoaXNbJGNvbnRlbnRdID0gY2hpbGQ7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgaWYgKHRoaXMuY29udGVudFR5cGUgPT09ICJ0ZXh0L3htbCIpIHsKICAgICAgdGhpc1skY29udGVudF0gPSBjaGlsZDsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgaWYgKHRoaXMuY29udGVudFR5cGUgIT09ICJ0ZXh0L2h0bWwiIHx8ICF0aGlzWyRjb250ZW50XSkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIHJldHVybiB0aGlzWyRjb250ZW50XVskdG9IVE1MXShhdmFpbGFibGVTcGFjZSk7CiAgfQp9CmNsYXNzIEV4T2JqZWN0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImV4T2JqZWN0IiwgdHJ1ZSk7CiAgICB0aGlzLmFyY2hpdmUgPSBhdHRyaWJ1dGVzLmFyY2hpdmUgfHwgIiI7CiAgICB0aGlzLmNsYXNzSWQgPSBhdHRyaWJ1dGVzLmNsYXNzSWQgfHwgIiI7CiAgICB0aGlzLmNvZGVCYXNlID0gYXR0cmlidXRlcy5jb2RlQmFzZSB8fCAiIjsKICAgIHRoaXMuY29kZVR5cGUgPSBhdHRyaWJ1dGVzLmNvZGVUeXBlIHx8ICIiOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5ib29sZWFuID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZVRpbWUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGVjaW1hbCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leERhdGEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXhPYmplY3QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmxvYXQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaW1hZ2UgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaW50ZWdlciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50ZXh0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRpbWUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgRXhjbEdyb3VwIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImV4Y2xHcm91cCIsIHRydWUpOwogICAgdGhpcy5hY2Nlc3MgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5hY2Nlc3MsIFsib3BlbiIsICJub25JbnRlcmFjdGl2ZSIsICJwcm90ZWN0ZWQiLCAicmVhZE9ubHkiXSk7CiAgICB0aGlzLmFjY2Vzc0tleSA9IGF0dHJpYnV0ZXMuYWNjZXNzS2V5IHx8ICIiOwogICAgdGhpcy5hbmNob3JUeXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuYW5jaG9yVHlwZSwgWyJ0b3BMZWZ0IiwgImJvdHRvbUNlbnRlciIsICJib3R0b21MZWZ0IiwgImJvdHRvbVJpZ2h0IiwgIm1pZGRsZUNlbnRlciIsICJtaWRkbGVMZWZ0IiwgIm1pZGRsZVJpZ2h0IiwgInRvcENlbnRlciIsICJ0b3BSaWdodCJdKTsKICAgIHRoaXMuY29sU3BhbiA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmNvbFNwYW4sCiAgICAgIGRlZmF1bHRWYWx1ZTogMSwKICAgICAgdmFsaWRhdGU6IG4gPT4gbiA+PSAxIHx8IG4gPT09IC0xCiAgICB9KTsKICAgIHRoaXMuaCA9IGF0dHJpYnV0ZXMuaCA/IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMuaCkgOiAiIjsKICAgIHRoaXMuaEFsaWduID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuaEFsaWduLCBbImxlZnQiLCAiY2VudGVyIiwgImp1c3RpZnkiLCAianVzdGlmeUFsbCIsICJyYWRpeCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5sYXlvdXQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5sYXlvdXQsIFsicG9zaXRpb24iLCAibHItdGIiLCAicmwtcm93IiwgInJsLXRiIiwgInJvdyIsICJ0YWJsZSIsICJ0YiJdKTsKICAgIHRoaXMubWF4SCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubWF4SCwgIjBwdCIpOwogICAgdGhpcy5tYXhXID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5tYXhXLCAiMHB0Iik7CiAgICB0aGlzLm1pbkggPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1pbkgsICIwcHQiKTsKICAgIHRoaXMubWluVyA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubWluVywgIjBwdCIpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5wcmVzZW5jZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnByZXNlbmNlLCBbInZpc2libGUiLCAiaGlkZGVuIiwgImluYWN0aXZlIiwgImludmlzaWJsZSJdKTsKICAgIHRoaXMucmVsZXZhbnQgPSBnZXRSZWxldmFudChhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLncgPSBhdHRyaWJ1dGVzLncgPyBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLncpIDogIiI7CiAgICB0aGlzLnggPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLngsICIwcHQiKTsKICAgIHRoaXMueSA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMueSwgIjBwdCIpOwogICAgdGhpcy5hc3Npc3QgPSBudWxsOwogICAgdGhpcy5iaW5kID0gbnVsbDsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuY2FsY3VsYXRlID0gbnVsbDsKICAgIHRoaXMuY2FwdGlvbiA9IG51bGw7CiAgICB0aGlzLmRlc2MgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogICAgdGhpcy5wYXJhID0gbnVsbDsKICAgIHRoaXMudHJhdmVyc2FsID0gbnVsbDsKICAgIHRoaXMudmFsaWRhdGUgPSBudWxsOwogICAgdGhpcy5jb25uZWN0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV2ZW50ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmZpZWxkID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnNldFByb3BlcnR5ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQogIFskaXNCaW5kYWJsZV0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgWyRoYXNTZXR0YWJsZVZhbHVlXSgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJHNldFZhbHVlXSh2YWx1ZSkgewogICAgZm9yIChjb25zdCBmaWVsZCBvZiB0aGlzLmZpZWxkLmNoaWxkcmVuKSB7CiAgICAgIGlmICghZmllbGQudmFsdWUpIHsKICAgICAgICBjb25zdCBub2RlVmFsdWUgPSBuZXcgVmFsdWUoe30pOwogICAgICAgIGZpZWxkWyRhcHBlbmRDaGlsZF0obm9kZVZhbHVlKTsKICAgICAgICBmaWVsZC52YWx1ZSA9IG5vZGVWYWx1ZTsKICAgICAgfQogICAgICBmaWVsZC52YWx1ZVskc2V0VmFsdWVdKHZhbHVlKTsKICAgIH0KICB9CiAgWyRpc1RoZXJlTW9yZVdpZHRoXSgpIHsKICAgIHJldHVybiB0aGlzLmxheW91dC5lbmRzV2l0aCgiLXRiIikgJiYgdGhpc1skZXh0cmFdLmF0dGVtcHQgPT09IDAgJiYgdGhpc1skZXh0cmFdLm51bWJlckluTGluZSA+IDAgfHwgdGhpc1skZ2V0UGFyZW50XSgpWyRpc1RoZXJlTW9yZVdpZHRoXSgpOwogIH0KICBbJGlzU3BsaXR0YWJsZV0oKSB7CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRTdWJmb3JtUGFyZW50XSgpOwogICAgaWYgKCFwYXJlbnRbJGlzU3BsaXR0YWJsZV0oKSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpc1skZXh0cmFdLl9pc1NwbGl0dGFibGUgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gdGhpc1skZXh0cmFdLl9pc1NwbGl0dGFibGU7CiAgICB9CiAgICBpZiAodGhpcy5sYXlvdXQgPT09ICJwb3NpdGlvbiIgfHwgdGhpcy5sYXlvdXQuaW5jbHVkZXMoInJvdyIpKSB7CiAgICAgIHRoaXNbJGV4dHJhXS5faXNTcGxpdHRhYmxlID0gZmFsc2U7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmIChwYXJlbnQubGF5b3V0Py5lbmRzV2l0aCgiLXRiIikgJiYgcGFyZW50WyRleHRyYV0ubnVtYmVySW5MaW5lICE9PSAwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHRoaXNbJGV4dHJhXS5faXNTcGxpdHRhYmxlID0gdHJ1ZTsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJGZsdXNoSFRNTF0oKSB7CiAgICByZXR1cm4gZmx1c2hIVE1MKHRoaXMpOwogIH0KICBbJGFkZEhUTUxdKGh0bWwsIGJib3gpIHsKICAgIGFkZEhUTUwodGhpcywgaHRtbCwgYmJveCk7CiAgfQogIFskZ2V0QXZhaWxhYmxlU3BhY2VdKCkgewogICAgcmV0dXJuIGdldEF2YWlsYWJsZVNwYWNlKHRoaXMpOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIHNldFRhYkluZGV4KHRoaXMpOwogICAgaWYgKHRoaXMucHJlc2VuY2UgPT09ICJoaWRkZW4iIHx8IHRoaXMucHJlc2VuY2UgPT09ICJpbmFjdGl2ZSIgfHwgdGhpcy5oID09PSAwIHx8IHRoaXMudyA9PT0gMCkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGZpeERpbWVuc2lvbnModGhpcyk7CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgaWQ6IHRoaXNbJHVpZF0sCiAgICAgIGNsYXNzOiBbXQogICAgfTsKICAgIHNldEFjY2Vzcyh0aGlzLCBhdHRyaWJ1dGVzLmNsYXNzKTsKICAgIHRoaXNbJGV4dHJhXSB8fD0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIE9iamVjdC5hc3NpZ24odGhpc1skZXh0cmFdLCB7CiAgICAgIGNoaWxkcmVuLAogICAgICBhdHRyaWJ1dGVzLAogICAgICBhdHRlbXB0OiAwLAogICAgICBsaW5lOiBudWxsLAogICAgICBudW1iZXJJbkxpbmU6IDAsCiAgICAgIGF2YWlsYWJsZVNwYWNlOiB7CiAgICAgICAgd2lkdGg6IE1hdGgubWluKHRoaXMudyB8fCBJbmZpbml0eSwgYXZhaWxhYmxlU3BhY2Uud2lkdGgpLAogICAgICAgIGhlaWdodDogTWF0aC5taW4odGhpcy5oIHx8IEluZmluaXR5LCBhdmFpbGFibGVTcGFjZS5oZWlnaHQpCiAgICAgIH0sCiAgICAgIHdpZHRoOiAwLAogICAgICBoZWlnaHQ6IDAsCiAgICAgIHByZXZIZWlnaHQ6IDAsCiAgICAgIGN1cnJlbnRXaWR0aDogMAogICAgfSk7CiAgICBjb25zdCBpc1NwbGl0dGFibGUgPSB0aGlzWyRpc1NwbGl0dGFibGVdKCk7CiAgICBpZiAoIWlzU3BsaXR0YWJsZSkgewogICAgICBzZXRGaXJzdFVuc3BsaXR0YWJsZSh0aGlzKTsKICAgIH0KICAgIGlmICghY2hlY2tEaW1lbnNpb25zKHRoaXMsIGF2YWlsYWJsZVNwYWNlKSkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5GQUlMVVJFOwogICAgfQogICAgY29uc3QgZmlsdGVyID0gbmV3IFNldChbImZpZWxkIl0pOwogICAgaWYgKHRoaXMubGF5b3V0LmluY2x1ZGVzKCJyb3ciKSkgewogICAgICBjb25zdCBjb2x1bW5XaWR0aHMgPSB0aGlzWyRnZXRTdWJmb3JtUGFyZW50XSgpLmNvbHVtbldpZHRoczsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29sdW1uV2lkdGhzKSAmJiBjb2x1bW5XaWR0aHMubGVuZ3RoID4gMCkgewogICAgICAgIHRoaXNbJGV4dHJhXS5jb2x1bW5XaWR0aHMgPSBjb2x1bW5XaWR0aHM7CiAgICAgICAgdGhpc1skZXh0cmFdLmN1cnJlbnRDb2x1bW4gPSAwOwogICAgICB9CiAgICB9CiAgICBjb25zdCBzdHlsZSA9IHRvU3R5bGUodGhpcywgImFuY2hvclR5cGUiLCAiZGltZW5zaW9ucyIsICJwb3NpdGlvbiIsICJwcmVzZW5jZSIsICJib3JkZXIiLCAibWFyZ2luIiwgImhBbGlnbiIpOwogICAgY29uc3QgY2xhc3NOYW1lcyA9IFsieGZhRXhjbGdyb3VwIl07CiAgICBjb25zdCBjbCA9IGxheW91dENsYXNzKHRoaXMpOwogICAgaWYgKGNsKSB7CiAgICAgIGNsYXNzTmFtZXMucHVzaChjbCk7CiAgICB9CiAgICBpZiAoaXNQcmludE9ubHkodGhpcykpIHsKICAgICAgY2xhc3NOYW1lcy5wdXNoKCJ4ZmFQcmludE9ubHkiKTsKICAgIH0KICAgIGF0dHJpYnV0ZXMuc3R5bGUgPSBzdHlsZTsKICAgIGF0dHJpYnV0ZXMuY2xhc3MgPSBjbGFzc05hbWVzOwogICAgaWYgKHRoaXMubmFtZSkgewogICAgICBhdHRyaWJ1dGVzLnhmYU5hbWUgPSB0aGlzLm5hbWU7CiAgICB9CiAgICB0aGlzWyRwdXNoUGFyYV0oKTsKICAgIGNvbnN0IGlzTHJUYiA9IHRoaXMubGF5b3V0ID09PSAibHItdGIiIHx8IHRoaXMubGF5b3V0ID09PSAicmwtdGIiOwogICAgY29uc3QgbWF4UnVuID0gaXNMclRiID8gTUFYX0FUVEVNUFRTX0ZPUl9MUlRCX0xBWU9VVCA6IDE7CiAgICBmb3IgKDsgdGhpc1skZXh0cmFdLmF0dGVtcHQgPCBtYXhSdW47IHRoaXNbJGV4dHJhXS5hdHRlbXB0KyspIHsKICAgICAgaWYgKGlzTHJUYiAmJiB0aGlzWyRleHRyYV0uYXR0ZW1wdCA9PT0gTUFYX0FUVEVNUFRTX0ZPUl9MUlRCX0xBWU9VVCAtIDEpIHsKICAgICAgICB0aGlzWyRleHRyYV0ubnVtYmVySW5MaW5lID0gMDsKICAgICAgfQogICAgICBjb25zdCByZXN1bHQgPSB0aGlzWyRjaGlsZHJlblRvSFRNTF0oewogICAgICAgIGZpbHRlciwKICAgICAgICBpbmNsdWRlOiB0cnVlCiAgICAgIH0pOwogICAgICBpZiAocmVzdWx0LnN1Y2Nlc3MpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAocmVzdWx0LmlzQnJlYWsoKSkgewogICAgICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfQogICAgICBpZiAoaXNMclRiICYmIHRoaXNbJGV4dHJhXS5hdHRlbXB0ID09PSAwICYmIHRoaXNbJGV4dHJhXS5udW1iZXJJbkxpbmUgPT09IDAgJiYgIXRoaXNbJGdldFRlbXBsYXRlUm9vdF0oKVskZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSkgewogICAgICAgIHRoaXNbJGV4dHJhXS5hdHRlbXB0ID0gbWF4UnVuOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICB0aGlzWyRwb3BQYXJhXSgpOwogICAgaWYgKCFpc1NwbGl0dGFibGUpIHsKICAgICAgdW5zZXRGaXJzdFVuc3BsaXR0YWJsZSh0aGlzKTsKICAgIH0KICAgIGlmICh0aGlzWyRleHRyYV0uYXR0ZW1wdCA9PT0gbWF4UnVuKSB7CiAgICAgIGlmICghaXNTcGxpdHRhYmxlKSB7CiAgICAgICAgZGVsZXRlIHRoaXNbJGV4dHJhXTsKICAgICAgfQogICAgICByZXR1cm4gSFRNTFJlc3VsdC5GQUlMVVJFOwogICAgfQogICAgbGV0IG1hcmdpbkggPSAwOwogICAgbGV0IG1hcmdpblYgPSAwOwogICAgaWYgKHRoaXMubWFyZ2luKSB7CiAgICAgIG1hcmdpbkggPSB0aGlzLm1hcmdpbi5sZWZ0SW5zZXQgKyB0aGlzLm1hcmdpbi5yaWdodEluc2V0OwogICAgICBtYXJnaW5WID0gdGhpcy5tYXJnaW4udG9wSW5zZXQgKyB0aGlzLm1hcmdpbi5ib3R0b21JbnNldDsKICAgIH0KICAgIGNvbnN0IHdpZHRoID0gTWF0aC5tYXgodGhpc1skZXh0cmFdLndpZHRoICsgbWFyZ2luSCwgdGhpcy53IHx8IDApOwogICAgY29uc3QgaGVpZ2h0ID0gTWF0aC5tYXgodGhpc1skZXh0cmFdLmhlaWdodCArIG1hcmdpblYsIHRoaXMuaCB8fCAwKTsKICAgIGNvbnN0IGJib3ggPSBbdGhpcy54LCB0aGlzLnksIHdpZHRoLCBoZWlnaHRdOwogICAgaWYgKHRoaXMudyA9PT0gIiIpIHsKICAgICAgc3R5bGUud2lkdGggPSBtZWFzdXJlVG9TdHJpbmcod2lkdGgpOwogICAgfQogICAgaWYgKHRoaXMuaCA9PT0gIiIpIHsKICAgICAgc3R5bGUuaGVpZ2h0ID0gbWVhc3VyZVRvU3RyaW5nKGhlaWdodCk7CiAgICB9CiAgICBjb25zdCBodG1sID0gewogICAgICBuYW1lOiAiZGl2IiwKICAgICAgYXR0cmlidXRlcywKICAgICAgY2hpbGRyZW4KICAgIH07CiAgICBhcHBseUFzc2lzdCh0aGlzLCBhdHRyaWJ1dGVzKTsKICAgIGRlbGV0ZSB0aGlzWyRleHRyYV07CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKGNyZWF0ZVdyYXBwZXIodGhpcywgaHRtbCksIGJib3gpOwogIH0KfQpjbGFzcyBFeGVjdXRlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImV4ZWN1dGUiKTsKICAgIHRoaXMuY29ubmVjdGlvbiA9IGF0dHJpYnV0ZXMuY29ubmVjdGlvbiB8fCAiIjsKICAgIHRoaXMuZXhlY3V0ZVR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5leGVjdXRlVHlwZSwgWyJpbXBvcnQiLCAicmVtZXJnZSJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5ydW5BdCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnJ1bkF0LCBbImNsaWVudCIsICJib3RoIiwgInNlcnZlciJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIEV4dHJhcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJleHRyYXMiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9vbGVhbiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGVUaW1lID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRlY2ltYWwgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXhEYXRhID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4dHJhcyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5mbG9hdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbWFnZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbnRlZ2VyID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBGaWVsZCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJmaWVsZCIsIHRydWUpOwogICAgdGhpcy5hY2Nlc3MgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5hY2Nlc3MsIFsib3BlbiIsICJub25JbnRlcmFjdGl2ZSIsICJwcm90ZWN0ZWQiLCAicmVhZE9ubHkiXSk7CiAgICB0aGlzLmFjY2Vzc0tleSA9IGF0dHJpYnV0ZXMuYWNjZXNzS2V5IHx8ICIiOwogICAgdGhpcy5hbmNob3JUeXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuYW5jaG9yVHlwZSwgWyJ0b3BMZWZ0IiwgImJvdHRvbUNlbnRlciIsICJib3R0b21MZWZ0IiwgImJvdHRvbVJpZ2h0IiwgIm1pZGRsZUNlbnRlciIsICJtaWRkbGVMZWZ0IiwgIm1pZGRsZVJpZ2h0IiwgInRvcENlbnRlciIsICJ0b3BSaWdodCJdKTsKICAgIHRoaXMuY29sU3BhbiA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmNvbFNwYW4sCiAgICAgIGRlZmF1bHRWYWx1ZTogMSwKICAgICAgdmFsaWRhdGU6IG4gPT4gbiA+PSAxIHx8IG4gPT09IC0xCiAgICB9KTsKICAgIHRoaXMuaCA9IGF0dHJpYnV0ZXMuaCA/IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMuaCkgOiAiIjsKICAgIHRoaXMuaEFsaWduID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuaEFsaWduLCBbImxlZnQiLCAiY2VudGVyIiwgImp1c3RpZnkiLCAianVzdGlmeUFsbCIsICJyYWRpeCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5sb2NhbGUgPSBhdHRyaWJ1dGVzLmxvY2FsZSB8fCAiIjsKICAgIHRoaXMubWF4SCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubWF4SCwgIjBwdCIpOwogICAgdGhpcy5tYXhXID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5tYXhXLCAiMHB0Iik7CiAgICB0aGlzLm1pbkggPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1pbkgsICIwcHQiKTsKICAgIHRoaXMubWluVyA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubWluVywgIjBwdCIpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5wcmVzZW5jZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnByZXNlbmNlLCBbInZpc2libGUiLCAiaGlkZGVuIiwgImluYWN0aXZlIiwgImludmlzaWJsZSJdKTsKICAgIHRoaXMucmVsZXZhbnQgPSBnZXRSZWxldmFudChhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMucm90YXRlID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMucm90YXRlLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggJSA5MCA9PT0gMAogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy53ID0gYXR0cmlidXRlcy53ID8gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy53KSA6ICIiOwogICAgdGhpcy54ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy54LCAiMHB0Iik7CiAgICB0aGlzLnkgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnksICIwcHQiKTsKICAgIHRoaXMuYXNzaXN0ID0gbnVsbDsKICAgIHRoaXMuYmluZCA9IG51bGw7CiAgICB0aGlzLmJvcmRlciA9IG51bGw7CiAgICB0aGlzLmNhbGN1bGF0ZSA9IG51bGw7CiAgICB0aGlzLmNhcHRpb24gPSBudWxsOwogICAgdGhpcy5kZXNjID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuZm9udCA9IG51bGw7CiAgICB0aGlzLmZvcm1hdCA9IG51bGw7CiAgICB0aGlzLml0ZW1zID0gbmV3IFhGQU9iamVjdEFycmF5KDIpOwogICAgdGhpcy5rZWVwID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICAgIHRoaXMucGFyYSA9IG51bGw7CiAgICB0aGlzLnRyYXZlcnNhbCA9IG51bGw7CiAgICB0aGlzLnVpID0gbnVsbDsKICAgIHRoaXMudmFsaWRhdGUgPSBudWxsOwogICAgdGhpcy52YWx1ZSA9IG51bGw7CiAgICB0aGlzLmJpbmRJdGVtcyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5jb25uZWN0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV2ZW50ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnNldFByb3BlcnR5ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQogIFskaXNCaW5kYWJsZV0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgWyRzZXRWYWx1ZV0odmFsdWUpIHsKICAgIF9zZXRWYWx1ZSh0aGlzLCB2YWx1ZSk7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgc2V0VGFiSW5kZXgodGhpcyk7CiAgICBpZiAoIXRoaXMudWkpIHsKICAgICAgdGhpcy51aSA9IG5ldyBVaSh7fSk7CiAgICAgIHRoaXMudWlbJGdsb2JhbERhdGFdID0gdGhpc1skZ2xvYmFsRGF0YV07CiAgICAgIHRoaXNbJGFwcGVuZENoaWxkXSh0aGlzLnVpKTsKICAgICAgbGV0IG5vZGU7CiAgICAgIHN3aXRjaCAodGhpcy5pdGVtcy5jaGlsZHJlbi5sZW5ndGgpIHsKICAgICAgICBjYXNlIDA6CiAgICAgICAgICBub2RlID0gbmV3IFRleHRFZGl0KHt9KTsKICAgICAgICAgIHRoaXMudWkudGV4dEVkaXQgPSBub2RlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxOgogICAgICAgICAgbm9kZSA9IG5ldyBDaGVja0J1dHRvbih7fSk7CiAgICAgICAgICB0aGlzLnVpLmNoZWNrQnV0dG9uID0gbm9kZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjoKICAgICAgICAgIG5vZGUgPSBuZXcgQ2hvaWNlTGlzdCh7fSk7CiAgICAgICAgICB0aGlzLnVpLmNob2ljZUxpc3QgPSBub2RlOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgdGhpcy51aVskYXBwZW5kQ2hpbGRdKG5vZGUpOwogICAgfQogICAgaWYgKCF0aGlzLnVpIHx8IHRoaXMucHJlc2VuY2UgPT09ICJoaWRkZW4iIHx8IHRoaXMucHJlc2VuY2UgPT09ICJpbmFjdGl2ZSIgfHwgdGhpcy5oID09PSAwIHx8IHRoaXMudyA9PT0gMCkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGlmICh0aGlzLmNhcHRpb24pIHsKICAgICAgZGVsZXRlIHRoaXMuY2FwdGlvblskZXh0cmFdOwogICAgfQogICAgdGhpc1skcHVzaFBhcmFdKCk7CiAgICBjb25zdCBjYXB0aW9uID0gdGhpcy5jYXB0aW9uID8gdGhpcy5jYXB0aW9uWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKS5odG1sIDogbnVsbDsKICAgIGNvbnN0IHNhdmVkVyA9IHRoaXMudzsKICAgIGNvbnN0IHNhdmVkSCA9IHRoaXMuaDsKICAgIGxldCBtYXJnaW5IID0gMDsKICAgIGxldCBtYXJnaW5WID0gMDsKICAgIGlmICh0aGlzLm1hcmdpbikgewogICAgICBtYXJnaW5IID0gdGhpcy5tYXJnaW4ubGVmdEluc2V0ICsgdGhpcy5tYXJnaW4ucmlnaHRJbnNldDsKICAgICAgbWFyZ2luViA9IHRoaXMubWFyZ2luLnRvcEluc2V0ICsgdGhpcy5tYXJnaW4uYm90dG9tSW5zZXQ7CiAgICB9CiAgICBsZXQgYm9yZGVyRGltcyA9IG51bGw7CiAgICBpZiAodGhpcy53ID09PSAiIiB8fCB0aGlzLmggPT09ICIiKSB7CiAgICAgIGxldCB3aWR0aCA9IG51bGw7CiAgICAgIGxldCBoZWlnaHQgPSBudWxsOwogICAgICBsZXQgdWlXID0gMDsKICAgICAgbGV0IHVpSCA9IDA7CiAgICAgIGlmICh0aGlzLnVpLmNoZWNrQnV0dG9uKSB7CiAgICAgICAgdWlXID0gdWlIID0gdGhpcy51aS5jaGVja0J1dHRvbi5zaXplOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IHsKICAgICAgICAgIHcsCiAgICAgICAgICBoCiAgICAgICAgfSA9IGxheW91dE5vZGUodGhpcywgYXZhaWxhYmxlU3BhY2UpOwogICAgICAgIGlmICh3ICE9PSBudWxsKSB7CiAgICAgICAgICB1aVcgPSB3OwogICAgICAgICAgdWlIID0gaDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdWlIID0gZm9udHNfZ2V0TWV0cmljcyh0aGlzLmZvbnQsIHRydWUpLmxpbmVOb0dhcDsKICAgICAgICB9CiAgICAgIH0KICAgICAgYm9yZGVyRGltcyA9IGdldEJvcmRlckRpbXModGhpcy51aVskZ2V0RXh0cmFdKCkpOwogICAgICB1aVcgKz0gYm9yZGVyRGltcy53OwogICAgICB1aUggKz0gYm9yZGVyRGltcy5oOwogICAgICBpZiAodGhpcy5jYXB0aW9uKSB7CiAgICAgICAgY29uc3QgewogICAgICAgICAgdywKICAgICAgICAgIGgsCiAgICAgICAgICBpc0Jyb2tlbgogICAgICAgIH0gPSB0aGlzLmNhcHRpb25bJGdldEV4dHJhXShhdmFpbGFibGVTcGFjZSk7CiAgICAgICAgaWYgKGlzQnJva2VuICYmIHRoaXNbJGdldFN1YmZvcm1QYXJlbnRdKClbJGlzVGhlcmVNb3JlV2lkdGhdKCkpIHsKICAgICAgICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICAgICAgICByZXR1cm4gSFRNTFJlc3VsdC5GQUlMVVJFOwogICAgICAgIH0KICAgICAgICB3aWR0aCA9IHc7CiAgICAgICAgaGVpZ2h0ID0gaDsKICAgICAgICBzd2l0Y2ggKHRoaXMuY2FwdGlvbi5wbGFjZW1lbnQpIHsKICAgICAgICAgIGNhc2UgImxlZnQiOgogICAgICAgICAgY2FzZSAicmlnaHQiOgogICAgICAgICAgY2FzZSAiaW5saW5lIjoKICAgICAgICAgICAgd2lkdGggKz0gdWlXOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgInRvcCI6CiAgICAgICAgICBjYXNlICJib3R0b20iOgogICAgICAgICAgICBoZWlnaHQgKz0gdWlIOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgd2lkdGggPSB1aVc7CiAgICAgICAgaGVpZ2h0ID0gdWlIOwogICAgICB9CiAgICAgIGlmICh3aWR0aCAmJiB0aGlzLncgPT09ICIiKSB7CiAgICAgICAgd2lkdGggKz0gbWFyZ2luSDsKICAgICAgICB0aGlzLncgPSBNYXRoLm1pbih0aGlzLm1heFcgPD0gMCA/IEluZmluaXR5IDogdGhpcy5tYXhXLCB0aGlzLm1pblcgKyAxIDwgd2lkdGggPyB3aWR0aCA6IHRoaXMubWluVyk7CiAgICAgIH0KICAgICAgaWYgKGhlaWdodCAmJiB0aGlzLmggPT09ICIiKSB7CiAgICAgICAgaGVpZ2h0ICs9IG1hcmdpblY7CiAgICAgICAgdGhpcy5oID0gTWF0aC5taW4odGhpcy5tYXhIIDw9IDAgPyBJbmZpbml0eSA6IHRoaXMubWF4SCwgdGhpcy5taW5IICsgMSA8IGhlaWdodCA/IGhlaWdodCA6IHRoaXMubWluSCk7CiAgICAgIH0KICAgIH0KICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICBmaXhEaW1lbnNpb25zKHRoaXMpOwogICAgc2V0Rmlyc3RVbnNwbGl0dGFibGUodGhpcyk7CiAgICBpZiAoIWNoZWNrRGltZW5zaW9ucyh0aGlzLCBhdmFpbGFibGVTcGFjZSkpIHsKICAgICAgdGhpcy53ID0gc2F2ZWRXOwogICAgICB0aGlzLmggPSBzYXZlZEg7CiAgICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkZBSUxVUkU7CiAgICB9CiAgICB1bnNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgY29uc3Qgc3R5bGUgPSB0b1N0eWxlKHRoaXMsICJmb250IiwgImRpbWVuc2lvbnMiLCAicG9zaXRpb24iLCAicm90YXRlIiwgImFuY2hvclR5cGUiLCAicHJlc2VuY2UiLCAibWFyZ2luIiwgImhBbGlnbiIpOwogICAgc2V0TWluTWF4RGltZW5zaW9ucyh0aGlzLCBzdHlsZSk7CiAgICBjb25zdCBjbGFzc05hbWVzID0gWyJ4ZmFGaWVsZCJdOwogICAgaWYgKHRoaXMuZm9udCkgewogICAgICBjbGFzc05hbWVzLnB1c2goInhmYUZvbnQiKTsKICAgIH0KICAgIGlmIChpc1ByaW50T25seSh0aGlzKSkgewogICAgICBjbGFzc05hbWVzLnB1c2goInhmYVByaW50T25seSIpOwogICAgfQogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgc3R5bGUsCiAgICAgIGlkOiB0aGlzWyR1aWRdLAogICAgICBjbGFzczogY2xhc3NOYW1lcwogICAgfTsKICAgIGlmIChzdHlsZS5tYXJnaW4pIHsKICAgICAgc3R5bGUucGFkZGluZyA9IHN0eWxlLm1hcmdpbjsKICAgICAgZGVsZXRlIHN0eWxlLm1hcmdpbjsKICAgIH0KICAgIHNldEFjY2Vzcyh0aGlzLCBjbGFzc05hbWVzKTsKICAgIGlmICh0aGlzLm5hbWUpIHsKICAgICAgYXR0cmlidXRlcy54ZmFOYW1lID0gdGhpcy5uYW1lOwogICAgfQogICAgY29uc3QgY2hpbGRyZW4gPSBbXTsKICAgIGNvbnN0IGh0bWwgPSB7CiAgICAgIG5hbWU6ICJkaXYiLAogICAgICBhdHRyaWJ1dGVzLAogICAgICBjaGlsZHJlbgogICAgfTsKICAgIGFwcGx5QXNzaXN0KHRoaXMsIGF0dHJpYnV0ZXMpOwogICAgY29uc3QgYm9yZGVyU3R5bGUgPSB0aGlzLmJvcmRlciA/IHRoaXMuYm9yZGVyWyR0b1N0eWxlXSgpIDogbnVsbDsKICAgIGNvbnN0IGJib3ggPSBjb21wdXRlQmJveCh0aGlzLCBodG1sLCBhdmFpbGFibGVTcGFjZSk7CiAgICBjb25zdCB1aSA9IHRoaXMudWlbJHRvSFRNTF0oKS5odG1sOwogICAgaWYgKCF1aSkgewogICAgICBPYmplY3QuYXNzaWduKHN0eWxlLCBib3JkZXJTdHlsZSk7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoY3JlYXRlV3JhcHBlcih0aGlzLCBodG1sKSwgYmJveCk7CiAgICB9CiAgICBpZiAodGhpc1skdGFiSW5kZXhdKSB7CiAgICAgIGlmICh1aS5jaGlsZHJlbj8uWzBdKSB7CiAgICAgICAgdWkuY2hpbGRyZW5bMF0uYXR0cmlidXRlcy50YWJpbmRleCA9IHRoaXNbJHRhYkluZGV4XTsKICAgICAgfSBlbHNlIHsKICAgICAgICB1aS5hdHRyaWJ1dGVzLnRhYmluZGV4ID0gdGhpc1skdGFiSW5kZXhdOwogICAgICB9CiAgICB9CiAgICB1aS5hdHRyaWJ1dGVzLnN0eWxlIHx8PSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgbGV0IGFFbGVtZW50ID0gbnVsbDsKICAgIGlmICh0aGlzLnVpLmJ1dHRvbikgewogICAgICBpZiAodWkuY2hpbGRyZW4ubGVuZ3RoID09PSAxKSB7CiAgICAgICAgW2FFbGVtZW50XSA9IHVpLmNoaWxkcmVuLnNwbGljZSgwLCAxKTsKICAgICAgfQogICAgICBPYmplY3QuYXNzaWduKHVpLmF0dHJpYnV0ZXMuc3R5bGUsIGJvcmRlclN0eWxlKTsKICAgIH0gZWxzZSB7CiAgICAgIE9iamVjdC5hc3NpZ24oc3R5bGUsIGJvcmRlclN0eWxlKTsKICAgIH0KICAgIGNoaWxkcmVuLnB1c2godWkpOwogICAgaWYgKHRoaXMudmFsdWUpIHsKICAgICAgaWYgKHRoaXMudWkuaW1hZ2VFZGl0KSB7CiAgICAgICAgdWkuY2hpbGRyZW4ucHVzaCh0aGlzLnZhbHVlWyR0b0hUTUxdKCkuaHRtbCk7CiAgICAgIH0gZWxzZSBpZiAoIXRoaXMudWkuYnV0dG9uKSB7CiAgICAgICAgbGV0IHZhbHVlID0gIiI7CiAgICAgICAgaWYgKHRoaXMudmFsdWUuZXhEYXRhKSB7CiAgICAgICAgICB2YWx1ZSA9IHRoaXMudmFsdWUuZXhEYXRhWyR0ZXh0XSgpOwogICAgICAgIH0gZWxzZSBpZiAodGhpcy52YWx1ZS50ZXh0KSB7CiAgICAgICAgICB2YWx1ZSA9IHRoaXMudmFsdWUudGV4dFskZ2V0RXh0cmFdKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvbnN0IGh0bWxWYWx1ZSA9IHRoaXMudmFsdWVbJHRvSFRNTF0oKS5odG1sOwogICAgICAgICAgaWYgKGh0bWxWYWx1ZSAhPT0gbnVsbCkgewogICAgICAgICAgICB2YWx1ZSA9IGh0bWxWYWx1ZS5jaGlsZHJlblswXS52YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMudWkudGV4dEVkaXQgJiYgdGhpcy52YWx1ZS50ZXh0Py5tYXhDaGFycykgewogICAgICAgICAgdWkuY2hpbGRyZW5bMF0uYXR0cmlidXRlcy5tYXhMZW5ndGggPSB0aGlzLnZhbHVlLnRleHQubWF4Q2hhcnM7CiAgICAgICAgfQogICAgICAgIGlmICh2YWx1ZSkgewogICAgICAgICAgaWYgKHRoaXMudWkubnVtZXJpY0VkaXQpIHsKICAgICAgICAgICAgdmFsdWUgPSBwYXJzZUZsb2F0KHZhbHVlKTsKICAgICAgICAgICAgdmFsdWUgPSBpc05hTih2YWx1ZSkgPyAiIiA6IHZhbHVlLnRvU3RyaW5nKCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodWkuY2hpbGRyZW5bMF0ubmFtZSA9PT0gInRleHRhcmVhIikgewogICAgICAgICAgICB1aS5jaGlsZHJlblswXS5hdHRyaWJ1dGVzLnRleHRDb250ZW50ID0gdmFsdWU7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB1aS5jaGlsZHJlblswXS5hdHRyaWJ1dGVzLnZhbHVlID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAoIXRoaXMudWkuaW1hZ2VFZGl0ICYmIHVpLmNoaWxkcmVuPy5bMF0gJiYgdGhpcy5oKSB7CiAgICAgIGJvcmRlckRpbXMgPSBib3JkZXJEaW1zIHx8IGdldEJvcmRlckRpbXModGhpcy51aVskZ2V0RXh0cmFdKCkpOwogICAgICBsZXQgY2FwdGlvbkhlaWdodCA9IDA7CiAgICAgIGlmICh0aGlzLmNhcHRpb24gJiYgWyJ0b3AiLCAiYm90dG9tIl0uaW5jbHVkZXModGhpcy5jYXB0aW9uLnBsYWNlbWVudCkpIHsKICAgICAgICBjYXB0aW9uSGVpZ2h0ID0gdGhpcy5jYXB0aW9uLnJlc2VydmU7CiAgICAgICAgaWYgKGNhcHRpb25IZWlnaHQgPD0gMCkgewogICAgICAgICAgY2FwdGlvbkhlaWdodCA9IHRoaXMuY2FwdGlvblskZ2V0RXh0cmFdKGF2YWlsYWJsZVNwYWNlKS5oOwogICAgICAgIH0KICAgICAgICBjb25zdCBpbnB1dEhlaWdodCA9IHRoaXMuaCAtIGNhcHRpb25IZWlnaHQgLSBtYXJnaW5WIC0gYm9yZGVyRGltcy5oOwogICAgICAgIHVpLmNoaWxkcmVuWzBdLmF0dHJpYnV0ZXMuc3R5bGUuaGVpZ2h0ID0gbWVhc3VyZVRvU3RyaW5nKGlucHV0SGVpZ2h0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB1aS5jaGlsZHJlblswXS5hdHRyaWJ1dGVzLnN0eWxlLmhlaWdodCA9ICIxMDAlIjsKICAgICAgfQogICAgfQogICAgaWYgKGFFbGVtZW50KSB7CiAgICAgIHVpLmNoaWxkcmVuLnB1c2goYUVsZW1lbnQpOwogICAgfQogICAgaWYgKCFjYXB0aW9uKSB7CiAgICAgIGlmICh1aS5hdHRyaWJ1dGVzLmNsYXNzKSB7CiAgICAgICAgdWkuYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFMZWZ0Iik7CiAgICAgIH0KICAgICAgdGhpcy53ID0gc2F2ZWRXOwogICAgICB0aGlzLmggPSBzYXZlZEg7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoY3JlYXRlV3JhcHBlcih0aGlzLCBodG1sKSwgYmJveCk7CiAgICB9CiAgICBpZiAodGhpcy51aS5idXR0b24pIHsKICAgICAgaWYgKHN0eWxlLnBhZGRpbmcpIHsKICAgICAgICBkZWxldGUgc3R5bGUucGFkZGluZzsKICAgICAgfQogICAgICBpZiAoY2FwdGlvbi5uYW1lID09PSAiZGl2IikgewogICAgICAgIGNhcHRpb24ubmFtZSA9ICJzcGFuIjsKICAgICAgfQogICAgICB1aS5jaGlsZHJlbi5wdXNoKGNhcHRpb24pOwogICAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKGh0bWwsIGJib3gpOwogICAgfSBlbHNlIGlmICh0aGlzLnVpLmNoZWNrQnV0dG9uKSB7CiAgICAgIGNhcHRpb24uYXR0cmlidXRlcy5jbGFzc1swXSA9ICJ4ZmFDYXB0aW9uRm9yQ2hlY2tCdXR0b24iOwogICAgfQogICAgdWkuYXR0cmlidXRlcy5jbGFzcyB8fD0gW107CiAgICB1aS5jaGlsZHJlbi5zcGxpY2UoMCwgMCwgY2FwdGlvbik7CiAgICBzd2l0Y2ggKHRoaXMuY2FwdGlvbi5wbGFjZW1lbnQpIHsKICAgICAgY2FzZSAibGVmdCI6CiAgICAgICAgdWkuYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFMZWZ0Iik7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgInJpZ2h0IjoKICAgICAgICB1aS5hdHRyaWJ1dGVzLmNsYXNzLnB1c2goInhmYVJpZ2h0Iik7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgInRvcCI6CiAgICAgICAgdWkuYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFUb3AiKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiYm90dG9tIjoKICAgICAgICB1aS5hdHRyaWJ1dGVzLmNsYXNzLnB1c2goInhmYUJvdHRvbSIpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJpbmxpbmUiOgogICAgICAgIHVpLmF0dHJpYnV0ZXMuY2xhc3MucHVzaCgieGZhTGVmdCIpOwogICAgICAgIGJyZWFrOwogICAgfQogICAgdGhpcy53ID0gc2F2ZWRXOwogICAgdGhpcy5oID0gc2F2ZWRIOwogICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhjcmVhdGVXcmFwcGVyKHRoaXMsIGh0bWwpLCBiYm94KTsKICB9Cn0KY2xhc3MgRmlsbCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJmaWxsIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMucHJlc2VuY2UgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5wcmVzZW5jZSwgWyJ2aXNpYmxlIiwgImhpZGRlbiIsICJpbmFjdGl2ZSIsICJpbnZpc2libGUiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jb2xvciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmxpbmVhciA9IG51bGw7CiAgICB0aGlzLnBhdHRlcm4gPSBudWxsOwogICAgdGhpcy5yYWRpYWwgPSBudWxsOwogICAgdGhpcy5zb2xpZCA9IG51bGw7CiAgICB0aGlzLnN0aXBwbGUgPSBudWxsOwogIH0KICBbJHRvU3R5bGVdKCkgewogICAgY29uc3QgcGFyZW50ID0gdGhpc1skZ2V0UGFyZW50XSgpOwogICAgY29uc3QgZ3JhbmRwYSA9IHBhcmVudFskZ2V0UGFyZW50XSgpOwogICAgY29uc3QgZ2dyYW5kcGEgPSBncmFuZHBhWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBzdHlsZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBsZXQgcHJvcE5hbWUgPSAiY29sb3IiOwogICAgbGV0IGFsdFByb3BOYW1lID0gcHJvcE5hbWU7CiAgICBpZiAocGFyZW50IGluc3RhbmNlb2YgQm9yZGVyKSB7CiAgICAgIHByb3BOYW1lID0gImJhY2tncm91bmQtY29sb3IiOwogICAgICBhbHRQcm9wTmFtZSA9ICJiYWNrZ3JvdW5kIjsKICAgICAgaWYgKGdncmFuZHBhIGluc3RhbmNlb2YgVWkpIHsKICAgICAgICBzdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAid2hpdGUiOwogICAgICB9CiAgICB9CiAgICBpZiAocGFyZW50IGluc3RhbmNlb2YgUmVjdGFuZ2xlIHx8IHBhcmVudCBpbnN0YW5jZW9mIEFyYykgewogICAgICBwcm9wTmFtZSA9IGFsdFByb3BOYW1lID0gImZpbGwiOwogICAgICBzdHlsZS5maWxsID0gIndoaXRlIjsKICAgIH0KICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSkgewogICAgICBpZiAobmFtZSA9PT0gImV4dHJhcyIgfHwgbmFtZSA9PT0gImNvbG9yIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IG9iaiA9IHRoaXNbbmFtZV07CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIFhGQU9iamVjdCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBjb2xvciA9IG9ialskdG9TdHlsZV0odGhpcy5jb2xvcik7CiAgICAgIGlmIChjb2xvcikgewogICAgICAgIHN0eWxlW2NvbG9yLnN0YXJ0c1dpdGgoIiMiKSA/IHByb3BOYW1lIDogYWx0UHJvcE5hbWVdID0gY29sb3I7CiAgICAgIH0KICAgICAgcmV0dXJuIHN0eWxlOwogICAgfQogICAgaWYgKHRoaXMuY29sb3I/LnZhbHVlKSB7CiAgICAgIGNvbnN0IGNvbG9yID0gdGhpcy5jb2xvclskdG9TdHlsZV0oKTsKICAgICAgc3R5bGVbY29sb3Iuc3RhcnRzV2l0aCgiIyIpID8gcHJvcE5hbWUgOiBhbHRQcm9wTmFtZV0gPSBjb2xvcjsKICAgIH0KICAgIHJldHVybiBzdHlsZTsKICB9Cn0KY2xhc3MgRmlsdGVyIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImZpbHRlciIsIHRydWUpOwogICAgdGhpcy5hZGRSZXZvY2F0aW9uSW5mbyA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmFkZFJldm9jYXRpb25JbmZvLCBbIiIsICJyZXF1aXJlZCIsICJvcHRpb25hbCIsICJub25lIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy52ZXJzaW9uID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IHRoaXMudmVyc2lvbiwKICAgICAgZGVmYXVsdFZhbHVlOiA1LAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDEgJiYgeCA8PSA1CiAgICB9KTsKICAgIHRoaXMuYXBwZWFyYW5jZUZpbHRlciA9IG51bGw7CiAgICB0aGlzLmNlcnRpZmljYXRlcyA9IG51bGw7CiAgICB0aGlzLmRpZ2VzdE1ldGhvZHMgPSBudWxsOwogICAgdGhpcy5lbmNvZGluZ3MgPSBudWxsOwogICAgdGhpcy5lbmNyeXB0aW9uTWV0aG9kcyA9IG51bGw7CiAgICB0aGlzLmhhbmRsZXIgPSBudWxsOwogICAgdGhpcy5sb2NrRG9jdW1lbnQgPSBudWxsOwogICAgdGhpcy5tZHAgPSBudWxsOwogICAgdGhpcy5yZWFzb25zID0gbnVsbDsKICAgIHRoaXMudGltZVN0YW1wID0gbnVsbDsKICB9Cn0KY2xhc3MgRmxvYXQgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImZsb2F0Iik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgY29uc3QgbnVtYmVyID0gcGFyc2VGbG9hdCh0aGlzWyRjb250ZW50XS50cmltKCkpOwogICAgdGhpc1skY29udGVudF0gPSBpc05hTihudW1iZXIpID8gbnVsbCA6IG51bWJlcjsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gdmFsdWVUb0h0bWwodGhpc1skY29udGVudF0gIT09IG51bGwgPyB0aGlzWyRjb250ZW50XS50b1N0cmluZygpIDogIiIpOwogIH0KfQpjbGFzcyB0ZW1wbGF0ZV9Gb250IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImZvbnQiLCB0cnVlKTsKICAgIHRoaXMuYmFzZWxpbmVTaGlmdCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMuYmFzZWxpbmVTaGlmdCk7CiAgICB0aGlzLmZvbnRIb3Jpem9udGFsU2NhbGUgPSBnZXRGbG9hdCh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZm9udEhvcml6b250YWxTY2FsZSwKICAgICAgZGVmYXVsdFZhbHVlOiAxMDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMAogICAgfSk7CiAgICB0aGlzLmZvbnRWZXJ0aWNhbFNjYWxlID0gZ2V0RmxvYXQoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmZvbnRWZXJ0aWNhbFNjYWxlLAogICAgICBkZWZhdWx0VmFsdWU6IDEwMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5rZXJuaW5nTW9kZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmtlcm5pbmdNb2RlLCBbIm5vbmUiLCAicGFpciJdKTsKICAgIHRoaXMubGV0dGVyU3BhY2luZyA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubGV0dGVyU3BhY2luZywgIjAiKTsKICAgIHRoaXMubGluZVRocm91Z2ggPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5saW5lVGhyb3VnaCwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxIHx8IHggPT09IDIKICAgIH0pOwogICAgdGhpcy5saW5lVGhyb3VnaFBlcmlvZCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmxpbmVUaHJvdWdoUGVyaW9kLCBbImFsbCIsICJ3b3JkIl0pOwogICAgdGhpcy5vdmVybGluZSA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLm92ZXJsaW5lLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEgfHwgeCA9PT0gMgogICAgfSk7CiAgICB0aGlzLm92ZXJsaW5lUGVyaW9kID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMub3ZlcmxpbmVQZXJpb2QsIFsiYWxsIiwgIndvcmQiXSk7CiAgICB0aGlzLnBvc3R1cmUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5wb3N0dXJlLCBbIm5vcm1hbCIsICJpdGFsaWMiXSk7CiAgICB0aGlzLnNpemUgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnNpemUsICIxMHB0Iik7CiAgICB0aGlzLnR5cGVmYWNlID0gYXR0cmlidXRlcy50eXBlZmFjZSB8fCAiQ291cmllciI7CiAgICB0aGlzLnVuZGVybGluZSA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnVuZGVybGluZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxIHx8IHggPT09IDIKICAgIH0pOwogICAgdGhpcy51bmRlcmxpbmVQZXJpb2QgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy51bmRlcmxpbmVQZXJpb2QsIFsiYWxsIiwgIndvcmQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy53ZWlnaHQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy53ZWlnaHQsIFsibm9ybWFsIiwgImJvbGQiXSk7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmZpbGwgPSBudWxsOwogIH0KICBbJGNsZWFuXShidWlsZGVyKSB7CiAgICBzdXBlclskY2xlYW5dKGJ1aWxkZXIpOwogICAgdGhpc1skZ2xvYmFsRGF0YV0udXNlZFR5cGVmYWNlcy5hZGQodGhpcy50eXBlZmFjZSk7CiAgfQogIFskdG9TdHlsZV0oKSB7CiAgICBjb25zdCBzdHlsZSA9IHRvU3R5bGUodGhpcywgImZpbGwiKTsKICAgIGNvbnN0IGNvbG9yID0gc3R5bGUuY29sb3I7CiAgICBpZiAoY29sb3IpIHsKICAgICAgaWYgKGNvbG9yID09PSAiIzAwMDAwMCIpIHsKICAgICAgICBkZWxldGUgc3R5bGUuY29sb3I7CiAgICAgIH0gZWxzZSBpZiAoIWNvbG9yLnN0YXJ0c1dpdGgoIiMiKSkgewogICAgICAgIHN0eWxlLmJhY2tncm91bmQgPSBjb2xvcjsKICAgICAgICBzdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9ICJ0ZXh0IjsKICAgICAgICBzdHlsZS5jb2xvciA9ICJ0cmFuc3BhcmVudCI7CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzLmJhc2VsaW5lU2hpZnQpIHsKICAgICAgc3R5bGUudmVydGljYWxBbGlnbiA9IG1lYXN1cmVUb1N0cmluZyh0aGlzLmJhc2VsaW5lU2hpZnQpOwogICAgfQogICAgc3R5bGUuZm9udEtlcm5pbmcgPSB0aGlzLmtlcm5pbmdNb2RlID09PSAibm9uZSIgPyAibm9uZSIgOiAibm9ybWFsIjsKICAgIHN0eWxlLmxldHRlclNwYWNpbmcgPSBtZWFzdXJlVG9TdHJpbmcodGhpcy5sZXR0ZXJTcGFjaW5nKTsKICAgIGlmICh0aGlzLmxpbmVUaHJvdWdoICE9PSAwKSB7CiAgICAgIHN0eWxlLnRleHREZWNvcmF0aW9uID0gImxpbmUtdGhyb3VnaCI7CiAgICAgIGlmICh0aGlzLmxpbmVUaHJvdWdoID09PSAyKSB7CiAgICAgICAgc3R5bGUudGV4dERlY29yYXRpb25TdHlsZSA9ICJkb3VibGUiOwogICAgICB9CiAgICB9CiAgICBpZiAodGhpcy5vdmVybGluZSAhPT0gMCkgewogICAgICBzdHlsZS50ZXh0RGVjb3JhdGlvbiA9ICJvdmVybGluZSI7CiAgICAgIGlmICh0aGlzLm92ZXJsaW5lID09PSAyKSB7CiAgICAgICAgc3R5bGUudGV4dERlY29yYXRpb25TdHlsZSA9ICJkb3VibGUiOwogICAgICB9CiAgICB9CiAgICBzdHlsZS5mb250U3R5bGUgPSB0aGlzLnBvc3R1cmU7CiAgICBzdHlsZS5mb250U2l6ZSA9IG1lYXN1cmVUb1N0cmluZygwLjk5ICogdGhpcy5zaXplKTsKICAgIHNldEZvbnRGYW1pbHkodGhpcywgdGhpcywgdGhpc1skZ2xvYmFsRGF0YV0uZm9udEZpbmRlciwgc3R5bGUpOwogICAgaWYgKHRoaXMudW5kZXJsaW5lICE9PSAwKSB7CiAgICAgIHN0eWxlLnRleHREZWNvcmF0aW9uID0gInVuZGVybGluZSI7CiAgICAgIGlmICh0aGlzLnVuZGVybGluZSA9PT0gMikgewogICAgICAgIHN0eWxlLnRleHREZWNvcmF0aW9uU3R5bGUgPSAiZG91YmxlIjsKICAgICAgfQogICAgfQogICAgc3R5bGUuZm9udFdlaWdodCA9IHRoaXMud2VpZ2h0OwogICAgcmV0dXJuIHN0eWxlOwogIH0KfQpjbGFzcyBGb3JtYXQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZm9ybWF0IiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLnBpY3R1cmUgPSBudWxsOwogIH0KfQpjbGFzcyBIYW5kbGVyIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImhhbmRsZXIiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIEh5cGhlbmF0aW9uIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImh5cGhlbmF0aW9uIik7CiAgICB0aGlzLmV4Y2x1ZGVBbGxDYXBzID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZXhjbHVkZUFsbENhcHMsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmV4Y2x1ZGVJbml0aWFsQ2FwID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZXhjbHVkZUluaXRpYWxDYXAsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmh5cGhlbmF0ZSA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmh5cGhlbmF0ZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5wdXNoQ2hhcmFjdGVyQ291bnQgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5wdXNoQ2hhcmFjdGVyQ291bnQsCiAgICAgIGRlZmF1bHRWYWx1ZTogMywKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICAgIHRoaXMucmVtYWluQ2hhcmFjdGVyQ291bnQgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5yZW1haW5DaGFyYWN0ZXJDb3VudCwKICAgICAgZGVmYXVsdFZhbHVlOiAzLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMud29yZENoYXJhY3RlckNvdW50ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMud29yZENoYXJhY3RlckNvdW50LAogICAgICBkZWZhdWx0VmFsdWU6IDcsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMAogICAgfSk7CiAgfQp9CmNsYXNzIEltYWdlIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImltYWdlIik7CiAgICB0aGlzLmFzcGVjdCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmFzcGVjdCwgWyJmaXQiLCAiYWN0dWFsIiwgImhlaWdodCIsICJub25lIiwgIndpZHRoIl0pOwogICAgdGhpcy5jb250ZW50VHlwZSA9IGF0dHJpYnV0ZXMuY29udGVudFR5cGUgfHwgIiI7CiAgICB0aGlzLmhyZWYgPSBhdHRyaWJ1dGVzLmhyZWYgfHwgIiI7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudHJhbnNmZXJFbmNvZGluZyA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnRyYW5zZmVyRW5jb2RpbmcsIFsiYmFzZTY0IiwgIm5vbmUiLCAicGFja2FnZSJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFskdG9IVE1MXSgpIHsKICAgIGlmICh0aGlzLmNvbnRlbnRUeXBlICYmICFNSU1FUy5oYXModGhpcy5jb250ZW50VHlwZS50b0xvd2VyQ2FzZSgpKSkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGxldCBidWZmZXIgPSB0aGlzWyRnbG9iYWxEYXRhXS5pbWFnZXM/LmdldCh0aGlzLmhyZWYpOwogICAgaWYgKCFidWZmZXIgJiYgKHRoaXMuaHJlZiB8fCAhdGhpc1skY29udGVudF0pKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgaWYgKCFidWZmZXIgJiYgdGhpcy50cmFuc2ZlckVuY29kaW5nID09PSAiYmFzZTY0IikgewogICAgICBidWZmZXIgPSBVaW50OEFycmF5LmZyb21CYXNlNjQodGhpc1skY29udGVudF0pOwogICAgfQogICAgaWYgKCFidWZmZXIpIHsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7CiAgICB9CiAgICBpZiAoIXRoaXMuY29udGVudFR5cGUpIHsKICAgICAgZm9yIChjb25zdCBbaGVhZGVyLCB0eXBlXSBvZiBJTUFHRVNfSEVBREVSUykgewogICAgICAgIGlmIChidWZmZXIubGVuZ3RoID4gaGVhZGVyLmxlbmd0aCAmJiBoZWFkZXIuZXZlcnkoKHgsIGkpID0+IHggPT09IGJ1ZmZlcltpXSkpIHsKICAgICAgICAgIHRoaXMuY29udGVudFR5cGUgPSB0eXBlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICghdGhpcy5jb250ZW50VHlwZSkgewogICAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgICB9CiAgICB9CiAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW2J1ZmZlcl0sIHsKICAgICAgdHlwZTogdGhpcy5jb250ZW50VHlwZQogICAgfSk7CiAgICBsZXQgc3R5bGU7CiAgICBzd2l0Y2ggKHRoaXMuYXNwZWN0KSB7CiAgICAgIGNhc2UgImZpdCI6CiAgICAgIGNhc2UgImFjdHVhbCI6CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgImhlaWdodCI6CiAgICAgICAgc3R5bGUgPSB7CiAgICAgICAgICBoZWlnaHQ6ICIxMDAlIiwKICAgICAgICAgIG9iamVjdEZpdDogImZpbGwiCiAgICAgICAgfTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAibm9uZSI6CiAgICAgICAgc3R5bGUgPSB7CiAgICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgICAgaGVpZ2h0OiAiMTAwJSIsCiAgICAgICAgICBvYmplY3RGaXQ6ICJmaWxsIgogICAgICAgIH07CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIndpZHRoIjoKICAgICAgICBzdHlsZSA9IHsKICAgICAgICAgIHdpZHRoOiAiMTAwJSIsCiAgICAgICAgICBvYmplY3RGaXQ6ICJmaWxsIgogICAgICAgIH07CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImltZyIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBjbGFzczogWyJ4ZmFJbWFnZSJdLAogICAgICAgIHN0eWxlLAogICAgICAgIHNyYzogVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKSwKICAgICAgICBhbHQ6IHBhcmVudCA/IGFyaWFMYWJlbChwYXJlbnRbJGdldFBhcmVudF0oKSkgOiBudWxsCiAgICAgIH0KICAgIH0pOwogIH0KfQpjbGFzcyBJbWFnZUVkaXQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiaW1hZ2VFZGl0IiwgdHJ1ZSk7CiAgICB0aGlzLmRhdGEgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5kYXRhLCBbImxpbmsiLCAiZW1iZWQiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvcmRlciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgaWYgKHRoaXMuZGF0YSA9PT0gImVtYmVkIikgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgICBuYW1lOiAiZGl2IiwKICAgICAgICBjaGlsZHJlbjogW10sCiAgICAgICAgYXR0cmlidXRlczoge30KICAgICAgfSk7CiAgICB9CiAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICB9Cn0KY2xhc3MgSW50ZWdlciBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiaW50ZWdlciIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIGNvbnN0IG51bWJlciA9IHBhcnNlSW50KHRoaXNbJGNvbnRlbnRdLnRyaW0oKSwgMTApOwogICAgdGhpc1skY29udGVudF0gPSBpc05hTihudW1iZXIpID8gbnVsbCA6IG51bWJlcjsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gdmFsdWVUb0h0bWwodGhpc1skY29udGVudF0gIT09IG51bGwgPyB0aGlzWyRjb250ZW50XS50b1N0cmluZygpIDogIiIpOwogIH0KfQpjbGFzcyBJc3N1ZXJzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImlzc3VlcnMiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNlcnRpZmljYXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIEl0ZW1zIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgIml0ZW1zIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucHJlc2VuY2UgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5wcmVzZW5jZSwgWyJ2aXNpYmxlIiwgImhpZGRlbiIsICJpbmFjdGl2ZSIsICJpbnZpc2libGUiXSk7CiAgICB0aGlzLnJlZiA9IGF0dHJpYnV0ZXMucmVmIHx8ICIiOwogICAgdGhpcy5zYXZlID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuc2F2ZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvb2xlYW4gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlVGltZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWNpbWFsID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4RGF0YSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5mbG9hdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbWFnZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbnRlZ2VyID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KICBbJHRvSFRNTF0oKSB7CiAgICBjb25zdCBvdXRwdXQgPSBbXTsKICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpc1skZ2V0Q2hpbGRyZW5dKCkpIHsKICAgICAgb3V0cHV0LnB1c2goY2hpbGRbJHRleHRdKCkpOwogICAgfQogICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhvdXRwdXQpOwogIH0KfQpjbGFzcyBLZWVwIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImtlZXAiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgY29uc3Qgb3B0aW9ucyA9IFsibm9uZSIsICJjb250ZW50QXJlYSIsICJwYWdlQXJlYSJdOwogICAgdGhpcy5pbnRhY3QgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5pbnRhY3QsIG9wdGlvbnMpOwogICAgdGhpcy5uZXh0ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMubmV4dCwgb3B0aW9ucyk7CiAgICB0aGlzLnByZXZpb3VzID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucHJldmlvdXMsIG9wdGlvbnMpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9Cn0KY2xhc3MgS2V5VXNhZ2UgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAia2V5VXNhZ2UiKTsKICAgIGNvbnN0IG9wdGlvbnMgPSBbIiIsICJ5ZXMiLCAibm8iXTsKICAgIHRoaXMuY3JsU2lnbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmNybFNpZ24sIG9wdGlvbnMpOwogICAgdGhpcy5kYXRhRW5jaXBoZXJtZW50ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuZGF0YUVuY2lwaGVybWVudCwgb3B0aW9ucyk7CiAgICB0aGlzLmRlY2lwaGVyT25seSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmRlY2lwaGVyT25seSwgb3B0aW9ucyk7CiAgICB0aGlzLmRpZ2l0YWxTaWduYXR1cmUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5kaWdpdGFsU2lnbmF0dXJlLCBvcHRpb25zKTsKICAgIHRoaXMuZW5jaXBoZXJPbmx5ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuZW5jaXBoZXJPbmx5LCBvcHRpb25zKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5rZXlBZ3JlZW1lbnQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5rZXlBZ3JlZW1lbnQsIG9wdGlvbnMpOwogICAgdGhpcy5rZXlDZXJ0U2lnbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmtleUNlcnRTaWduLCBvcHRpb25zKTsKICAgIHRoaXMua2V5RW5jaXBoZXJtZW50ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMua2V5RW5jaXBoZXJtZW50LCBvcHRpb25zKTsKICAgIHRoaXMubm9uUmVwdWRpYXRpb24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5ub25SZXB1ZGlhdGlvbiwgb3B0aW9ucyk7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgTGluZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJsaW5lIiwgdHJ1ZSk7CiAgICB0aGlzLmhhbmQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oYW5kLCBbImV2ZW4iLCAibGVmdCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5zbG9wZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnNsb3BlLCBbIlxcIiwgIi8iXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5lZGdlID0gbnVsbDsKICB9CiAgWyR0b0hUTUxdKCkgewogICAgY29uc3QgcGFyZW50ID0gdGhpc1skZ2V0UGFyZW50XSgpWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBlZGdlID0gdGhpcy5lZGdlIHx8IG5ldyBFZGdlKHt9KTsKICAgIGNvbnN0IGVkZ2VTdHlsZSA9IGVkZ2VbJHRvU3R5bGVdKCk7CiAgICBjb25zdCBzdHlsZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBjb25zdCB0aGlja25lc3MgPSBlZGdlLnByZXNlbmNlID09PSAidmlzaWJsZSIgPyBlZGdlLnRoaWNrbmVzcyA6IDA7CiAgICBzdHlsZS5zdHJva2VXaWR0aCA9IG1lYXN1cmVUb1N0cmluZyh0aGlja25lc3MpOwogICAgc3R5bGUuc3Ryb2tlID0gZWRnZVN0eWxlLmNvbG9yOwogICAgbGV0IHgxLCB5MSwgeDIsIHkyOwogICAgbGV0IHdpZHRoID0gIjEwMCUiOwogICAgbGV0IGhlaWdodCA9ICIxMDAlIjsKICAgIGlmIChwYXJlbnQudyA8PSB0aGlja25lc3MpIHsKICAgICAgW3gxLCB5MSwgeDIsIHkyXSA9IFsiNTAlIiwgMCwgIjUwJSIsICIxMDAlIl07CiAgICAgIHdpZHRoID0gc3R5bGUuc3Ryb2tlV2lkdGg7CiAgICB9IGVsc2UgaWYgKHBhcmVudC5oIDw9IHRoaWNrbmVzcykgewogICAgICBbeDEsIHkxLCB4MiwgeTJdID0gWzAsICI1MCUiLCAiMTAwJSIsICI1MCUiXTsKICAgICAgaGVpZ2h0ID0gc3R5bGUuc3Ryb2tlV2lkdGg7CiAgICB9IGVsc2UgaWYgKHRoaXMuc2xvcGUgPT09ICJcXCIpIHsKICAgICAgW3gxLCB5MSwgeDIsIHkyXSA9IFswLCAwLCAiMTAwJSIsICIxMDAlIl07CiAgICB9IGVsc2UgewogICAgICBbeDEsIHkxLCB4MiwgeTJdID0gWzAsICIxMDAlIiwgIjEwMCUiLCAwXTsKICAgIH0KICAgIGNvbnN0IGxpbmUgPSB7CiAgICAgIG5hbWU6ICJsaW5lIiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIHhtbG5zOiBTVkdfTlMsCiAgICAgICAgeDEsCiAgICAgICAgeTEsCiAgICAgICAgeDIsCiAgICAgICAgeTIsCiAgICAgICAgc3R5bGUKICAgICAgfQogICAgfTsKICAgIGNvbnN0IHN2ZyA9IHsKICAgICAgbmFtZTogInN2ZyIsCiAgICAgIGNoaWxkcmVuOiBbbGluZV0sCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICB4bWxuczogU1ZHX05TLAogICAgICAgIHdpZHRoLAogICAgICAgIGhlaWdodCwKICAgICAgICBzdHlsZTogewogICAgICAgICAgb3ZlcmZsb3c6ICJ2aXNpYmxlIgogICAgICAgIH0KICAgICAgfQogICAgfTsKICAgIGlmIChoYXNNYXJnaW4ocGFyZW50KSkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgICBuYW1lOiAiZGl2IiwKICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICBzdHlsZTogewogICAgICAgICAgICBkaXNwbGF5OiAiaW5saW5lIiwKICAgICAgICAgICAgd2lkdGg6ICIxMDAlIiwKICAgICAgICAgICAgaGVpZ2h0OiAiMTAwJSIKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGNoaWxkcmVuOiBbc3ZnXQogICAgICB9KTsKICAgIH0KICAgIHN2Zy5hdHRyaWJ1dGVzLnN0eWxlLnBvc2l0aW9uID0gImFic29sdXRlIjsKICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3Moc3ZnKTsKICB9Cn0KY2xhc3MgTGluZWFyIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImxpbmVhciIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbInRvUmlnaHQiLCAidG9Cb3R0b20iLCAidG9MZWZ0IiwgInRvVG9wIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29sb3IgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbJHRvU3R5bGVdKHN0YXJ0Q29sb3IpIHsKICAgIHN0YXJ0Q29sb3IgPSBzdGFydENvbG9yID8gc3RhcnRDb2xvclskdG9TdHlsZV0oKSA6ICIjRkZGRkZGIjsKICAgIGNvbnN0IHRyYW5zZiA9IHRoaXMudHlwZS5yZXBsYWNlKC8oW1JCTFRdKS8sICIgJDEiKS50b0xvd2VyQ2FzZSgpOwogICAgY29uc3QgZW5kQ29sb3IgPSB0aGlzLmNvbG9yID8gdGhpcy5jb2xvclskdG9TdHlsZV0oKSA6ICIjMDAwMDAwIjsKICAgIHJldHVybiBgbGluZWFyLWdyYWRpZW50KCR7dHJhbnNmfSwgJHtzdGFydENvbG9yfSwgJHtlbmRDb2xvcn0pYDsKICB9Cn0KY2xhc3MgTG9ja0RvY3VtZW50IGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJsb2NrRG9jdW1lbnQiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgdGhpc1skY29udGVudF0gPSBnZXRTdHJpbmdPcHRpb24odGhpc1skY29udGVudF0sIFsiYXV0byIsICIwIiwgIjEiXSk7CiAgfQp9CmNsYXNzIE1hbmlmZXN0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgIm1hbmlmZXN0IiwgdHJ1ZSk7CiAgICB0aGlzLmFjdGlvbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmFjdGlvbiwgWyJpbmNsdWRlIiwgImFsbCIsICJleGNsdWRlIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5yZWYgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgTWFyZ2luIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgIm1hcmdpbiIsIHRydWUpOwogICAgdGhpcy5ib3R0b21JbnNldCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMuYm90dG9tSW5zZXQsICIwIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubGVmdEluc2V0ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5sZWZ0SW5zZXQsICIwIik7CiAgICB0aGlzLnJpZ2h0SW5zZXQgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnJpZ2h0SW5zZXQsICIwIik7CiAgICB0aGlzLnRvcEluc2V0ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy50b3BJbnNldCwgIjAiKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFskdG9TdHlsZV0oKSB7CiAgICByZXR1cm4gewogICAgICBtYXJnaW46IG1lYXN1cmVUb1N0cmluZyh0aGlzLnRvcEluc2V0KSArICIgIiArIG1lYXN1cmVUb1N0cmluZyh0aGlzLnJpZ2h0SW5zZXQpICsgIiAiICsgbWVhc3VyZVRvU3RyaW5nKHRoaXMuYm90dG9tSW5zZXQpICsgIiAiICsgbWVhc3VyZVRvU3RyaW5nKHRoaXMubGVmdEluc2V0KQogICAgfTsKICB9Cn0KY2xhc3MgTWRwIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgIm1kcCIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnBlcm1pc3Npb25zID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMucGVybWlzc2lvbnMsCiAgICAgIGRlZmF1bHRWYWx1ZTogMiwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMSB8fCB4ID09PSAzCiAgICB9KTsKICAgIHRoaXMuc2lnbmF0dXJlVHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnNpZ25hdHVyZVR5cGUsIFsiZmlsbGVyIiwgImF1dGhvciJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIE1lZGl1bSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJtZWRpdW0iKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5pbWFnaW5nQkJveCA9IGdldEJCb3goYXR0cmlidXRlcy5pbWFnaW5nQkJveCk7CiAgICB0aGlzLmxvbmcgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLmxvbmcpOwogICAgdGhpcy5vcmllbnRhdGlvbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm9yaWVudGF0aW9uLCBbInBvcnRyYWl0IiwgImxhbmRzY2FwZSJdKTsKICAgIHRoaXMuc2hvcnQgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnNob3J0KTsKICAgIHRoaXMuc3RvY2sgPSBhdHRyaWJ1dGVzLnN0b2NrIHx8ICIiOwogICAgdGhpcy50cmF5SW4gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50cmF5SW4sIFsiYXV0byIsICJkZWxlZ2F0ZSIsICJwYWdlRnJvbnQiXSk7CiAgICB0aGlzLnRyYXlPdXQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50cmF5T3V0LCBbImF1dG8iLCAiZGVsZWdhdGUiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBNZXNzYWdlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgIm1lc3NhZ2UiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMudGV4dCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBOdW1lcmljRWRpdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJudW1lcmljRWRpdCIsIHRydWUpOwogICAgdGhpcy5oU2Nyb2xsUG9saWN5ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuaFNjcm9sbFBvbGljeSwgWyJhdXRvIiwgIm9mZiIsICJvbiJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuY29tYiA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgY29uc3Qgc3R5bGUgPSB0b1N0eWxlKHRoaXMsICJib3JkZXIiLCAiZm9udCIsICJtYXJnaW4iKTsKICAgIGNvbnN0IGZpZWxkID0gdGhpc1skZ2V0UGFyZW50XSgpWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBodG1sID0gewogICAgICBuYW1lOiAiaW5wdXQiLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgdHlwZTogInRleHQiLAogICAgICAgIGZpZWxkSWQ6IGZpZWxkWyR1aWRdLAogICAgICAgIGRhdGFJZDogZmllbGRbJGRhdGFdPy5bJHVpZF0gfHwgZmllbGRbJHVpZF0sCiAgICAgICAgY2xhc3M6IFsieGZhVGV4dGZpZWxkIl0sCiAgICAgICAgc3R5bGUsCiAgICAgICAgImFyaWEtbGFiZWwiOiBhcmlhTGFiZWwoZmllbGQpLAogICAgICAgICJhcmlhLXJlcXVpcmVkIjogZmFsc2UKICAgICAgfQogICAgfTsKICAgIGlmIChpc1JlcXVpcmVkKGZpZWxkKSkgewogICAgICBodG1sLmF0dHJpYnV0ZXNbImFyaWEtcmVxdWlyZWQiXSA9IHRydWU7CiAgICAgIGh0bWwuYXR0cmlidXRlcy5yZXF1aXJlZCA9IHRydWU7CiAgICB9CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImxhYmVsIiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBbInhmYUxhYmVsIl0KICAgICAgfSwKICAgICAgY2hpbGRyZW46IFtodG1sXQogICAgfSk7CiAgfQp9CmNsYXNzIE9jY3VyIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgIm9jY3VyIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMuaW5pdGlhbCA9IGF0dHJpYnV0ZXMuaW5pdGlhbCAhPT0gIiIgPyBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5pbml0aWFsLAogICAgICBkZWZhdWx0VmFsdWU6ICIiLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KSA6ICIiOwogICAgdGhpcy5tYXggPSBhdHRyaWJ1dGVzLm1heCAhPT0gIiIgPyBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5tYXgsCiAgICAgIGRlZmF1bHRWYWx1ZTogLTEsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHRydWUKICAgIH0pIDogIiI7CiAgICB0aGlzLm1pbiA9IGF0dHJpYnV0ZXMubWluICE9PSAiIiA/IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLm1pbiwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KSA6ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9CiAgWyRjbGVhbl0oKSB7CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBvcmlnaW5hbE1pbiA9IHRoaXMubWluOwogICAgaWYgKHRoaXMubWluID09PSAiIikgewogICAgICB0aGlzLm1pbiA9IHBhcmVudCBpbnN0YW5jZW9mIFBhZ2VBcmVhIHx8IHBhcmVudCBpbnN0YW5jZW9mIFBhZ2VTZXQgPyAwIDogMTsKICAgIH0KICAgIGlmICh0aGlzLm1heCA9PT0gIiIpIHsKICAgICAgaWYgKG9yaWdpbmFsTWluID09PSAiIikgewogICAgICAgIHRoaXMubWF4ID0gcGFyZW50IGluc3RhbmNlb2YgUGFnZUFyZWEgfHwgcGFyZW50IGluc3RhbmNlb2YgUGFnZVNldCA/IC0xIDogMTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLm1heCA9IHRoaXMubWluOwogICAgICB9CiAgICB9CiAgICBpZiAodGhpcy5tYXggIT09IC0xICYmIHRoaXMubWF4IDwgdGhpcy5taW4pIHsKICAgICAgdGhpcy5tYXggPSB0aGlzLm1pbjsKICAgIH0KICAgIGlmICh0aGlzLmluaXRpYWwgPT09ICIiKSB7CiAgICAgIHRoaXMuaW5pdGlhbCA9IHBhcmVudCBpbnN0YW5jZW9mIFRlbXBsYXRlID8gMSA6IHRoaXMubWluOwogICAgfQogIH0KfQpjbGFzcyBPaWQgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAib2lkIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIE9pZHMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAib2lkcyIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMub2lkID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIE92ZXJmbG93IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgIm92ZXJmbG93Iik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubGVhZGVyID0gYXR0cmlidXRlcy5sZWFkZXIgfHwgIiI7CiAgICB0aGlzLnRhcmdldCA9IGF0dHJpYnV0ZXMudGFyZ2V0IHx8ICIiOwogICAgdGhpcy50cmFpbGVyID0gYXR0cmlidXRlcy50cmFpbGVyIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgWyRnZXRFeHRyYV0oKSB7CiAgICBpZiAoIXRoaXNbJGV4dHJhXSkgewogICAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICAgIGNvbnN0IHJvb3QgPSB0aGlzWyRnZXRUZW1wbGF0ZVJvb3RdKCk7CiAgICAgIGNvbnN0IHRhcmdldCA9IHJvb3RbJHNlYXJjaE5vZGVdKHRoaXMudGFyZ2V0LCBwYXJlbnQpOwogICAgICBjb25zdCBsZWFkZXIgPSByb290WyRzZWFyY2hOb2RlXSh0aGlzLmxlYWRlciwgcGFyZW50KTsKICAgICAgY29uc3QgdHJhaWxlciA9IHJvb3RbJHNlYXJjaE5vZGVdKHRoaXMudHJhaWxlciwgcGFyZW50KTsKICAgICAgdGhpc1skZXh0cmFdID0gewogICAgICAgIHRhcmdldDogdGFyZ2V0Py5bMF0gfHwgbnVsbCwKICAgICAgICBsZWFkZXI6IGxlYWRlcj8uWzBdIHx8IG51bGwsCiAgICAgICAgdHJhaWxlcjogdHJhaWxlcj8uWzBdIHx8IG51bGwsCiAgICAgICAgYWRkTGVhZGVyOiBmYWxzZSwKICAgICAgICBhZGRUcmFpbGVyOiBmYWxzZQogICAgICB9OwogICAgfQogICAgcmV0dXJuIHRoaXNbJGV4dHJhXTsKICB9Cn0KY2xhc3MgUGFnZUFyZWEgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAicGFnZUFyZWEiLCB0cnVlKTsKICAgIHRoaXMuYmxhbmtPck5vdEJsYW5rID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuYmxhbmtPck5vdEJsYW5rLCBbImFueSIsICJibGFuayIsICJub3RCbGFuayJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5pbml0aWFsTnVtYmVyID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuaW5pdGlhbE51bWJlciwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMubnVtYmVyZWQgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5udW1iZXJlZCwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KTsKICAgIHRoaXMub2RkT3JFdmVuID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMub2RkT3JFdmVuLCBbImFueSIsICJldmVuIiwgIm9kZCJdKTsKICAgIHRoaXMucGFnZVBvc2l0aW9uID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucGFnZVBvc2l0aW9uLCBbImFueSIsICJmaXJzdCIsICJsYXN0IiwgIm9ubHkiLCAicmVzdCJdKTsKICAgIHRoaXMucmVsZXZhbnQgPSBnZXRSZWxldmFudChhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmRlc2MgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tZWRpdW0gPSBudWxsOwogICAgdGhpcy5vY2N1ciA9IG51bGw7CiAgICB0aGlzLmFyZWEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY29udGVudEFyZWEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZHJhdyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leGNsR3JvdXAgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmllbGQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViZm9ybSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KICBbJGlzVXNhYmxlXSgpIHsKICAgIGlmICghdGhpc1skZXh0cmFdKSB7CiAgICAgIHRoaXNbJGV4dHJhXSA9IHsKICAgICAgICBudW1iZXJPZlVzZTogMAogICAgICB9OwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiAhdGhpcy5vY2N1ciB8fCB0aGlzLm9jY3VyLm1heCA9PT0gLTEgfHwgdGhpc1skZXh0cmFdLm51bWJlck9mVXNlIDwgdGhpcy5vY2N1ci5tYXg7CiAgfQogIFskY2xlYW5QYWdlXSgpIHsKICAgIGRlbGV0ZSB0aGlzWyRleHRyYV07CiAgfQogIFskZ2V0TmV4dFBhZ2VdKCkgewogICAgdGhpc1skZXh0cmFdIHx8PSB7CiAgICAgIG51bWJlck9mVXNlOiAwCiAgICB9OwogICAgY29uc3QgcGFyZW50ID0gdGhpc1skZ2V0UGFyZW50XSgpOwogICAgaWYgKHBhcmVudC5yZWxhdGlvbiA9PT0gIm9yZGVyZWRPY2N1cnJlbmNlIikgewogICAgICBpZiAodGhpc1skaXNVc2FibGVdKCkpIHsKICAgICAgICB0aGlzWyRleHRyYV0ubnVtYmVyT2ZVc2UgKz0gMTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHBhcmVudFskZ2V0TmV4dFBhZ2VdKCk7CiAgfQogIFskZ2V0QXZhaWxhYmxlU3BhY2VdKCkgewogICAgcmV0dXJuIHRoaXNbJGV4dHJhXS5zcGFjZSB8fCB7CiAgICAgIHdpZHRoOiAwLAogICAgICBoZWlnaHQ6IDAKICAgIH07CiAgfQogIFskdG9IVE1MXSgpIHsKICAgIHRoaXNbJGV4dHJhXSB8fD0gewogICAgICBudW1iZXJPZlVzZTogMQogICAgfTsKICAgIGNvbnN0IGNoaWxkcmVuID0gW107CiAgICB0aGlzWyRleHRyYV0uY2hpbGRyZW4gPSBjaGlsZHJlbjsKICAgIGNvbnN0IHN0eWxlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGlmICh0aGlzLm1lZGl1bSAmJiB0aGlzLm1lZGl1bS5zaG9ydCAmJiB0aGlzLm1lZGl1bS5sb25nKSB7CiAgICAgIHN0eWxlLndpZHRoID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMubWVkaXVtLnNob3J0KTsKICAgICAgc3R5bGUuaGVpZ2h0ID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMubWVkaXVtLmxvbmcpOwogICAgICB0aGlzWyRleHRyYV0uc3BhY2UgPSB7CiAgICAgICAgd2lkdGg6IHRoaXMubWVkaXVtLnNob3J0LAogICAgICAgIGhlaWdodDogdGhpcy5tZWRpdW0ubG9uZwogICAgICB9OwogICAgICBpZiAodGhpcy5tZWRpdW0ub3JpZW50YXRpb24gPT09ICJsYW5kc2NhcGUiKSB7CiAgICAgICAgY29uc3QgeCA9IHN0eWxlLndpZHRoOwogICAgICAgIHN0eWxlLndpZHRoID0gc3R5bGUuaGVpZ2h0OwogICAgICAgIHN0eWxlLmhlaWdodCA9IHg7CiAgICAgICAgdGhpc1skZXh0cmFdLnNwYWNlID0gewogICAgICAgICAgd2lkdGg6IHRoaXMubWVkaXVtLmxvbmcsCiAgICAgICAgICBoZWlnaHQ6IHRoaXMubWVkaXVtLnNob3J0CiAgICAgICAgfTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgd2FybigiWEZBIC0gTm8gbWVkaXVtIHNwZWNpZmllZCBpbiBwYWdlQXJlYTogcGxlYXNlIGZpbGUgYSBidWcuIik7CiAgICB9CiAgICB0aGlzWyRjaGlsZHJlblRvSFRNTF0oewogICAgICBmaWx0ZXI6IG5ldyBTZXQoWyJhcmVhIiwgImRyYXciLCAiZmllbGQiLCAic3ViZm9ybSJdKSwKICAgICAgaW5jbHVkZTogdHJ1ZQogICAgfSk7CiAgICB0aGlzWyRjaGlsZHJlblRvSFRNTF0oewogICAgICBmaWx0ZXI6IG5ldyBTZXQoWyJjb250ZW50QXJlYSJdKSwKICAgICAgaW5jbHVkZTogdHJ1ZQogICAgfSk7CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGNoaWxkcmVuLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgY2xhc3M6IFsieGZhUGFnZSJdLAogICAgICAgIGlkOiB0aGlzWyR1aWRdLAogICAgICAgIHN0eWxlLAogICAgICAgIHhmYU5hbWU6IHRoaXMubmFtZQogICAgICB9CiAgICB9KTsKICB9Cn0KY2xhc3MgUGFnZVNldCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJwYWdlU2V0IiwgdHJ1ZSk7CiAgICB0aGlzLmR1cGxleEltcG9zaXRpb24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5kdXBsZXhJbXBvc2l0aW9uLCBbImxvbmdFZGdlIiwgInNob3J0RWRnZSJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yZWxhdGlvbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnJlbGF0aW9uLCBbIm9yZGVyZWRPY2N1cnJlbmNlIiwgImR1cGxleFBhZ2luYXRlZCIsICJzaW1wbGV4UGFnaW5hdGVkIl0pOwogICAgdGhpcy5yZWxldmFudCA9IGdldFJlbGV2YW50KGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMub2NjdXIgPSBudWxsOwogICAgdGhpcy5wYWdlQXJlYSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wYWdlU2V0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQogIFskY2xlYW5QYWdlXSgpIHsKICAgIGZvciAoY29uc3QgcGFnZSBvZiB0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuKSB7CiAgICAgIHBhZ2VbJGNsZWFuUGFnZV0oKTsKICAgIH0KICAgIGZvciAoY29uc3QgcGFnZSBvZiB0aGlzLnBhZ2VTZXQuY2hpbGRyZW4pIHsKICAgICAgcGFnZVskY2xlYW5QYWdlXSgpOwogICAgfQogIH0KICBbJGlzVXNhYmxlXSgpIHsKICAgIHJldHVybiAhdGhpcy5vY2N1ciB8fCB0aGlzLm9jY3VyLm1heCA9PT0gLTEgfHwgdGhpc1skZXh0cmFdLm51bWJlck9mVXNlIDwgdGhpcy5vY2N1ci5tYXg7CiAgfQogIFskZ2V0TmV4dFBhZ2VdKCkgewogICAgdGhpc1skZXh0cmFdIHx8PSB7CiAgICAgIG51bWJlck9mVXNlOiAxLAogICAgICBwYWdlSW5kZXg6IC0xLAogICAgICBwYWdlU2V0SW5kZXg6IC0xCiAgICB9OwogICAgaWYgKHRoaXMucmVsYXRpb24gPT09ICJvcmRlcmVkT2NjdXJyZW5jZSIpIHsKICAgICAgaWYgKHRoaXNbJGV4dHJhXS5wYWdlSW5kZXggKyAxIDwgdGhpcy5wYWdlQXJlYS5jaGlsZHJlbi5sZW5ndGgpIHsKICAgICAgICB0aGlzWyRleHRyYV0ucGFnZUluZGV4ICs9IDE7CiAgICAgICAgY29uc3QgcGFnZUFyZWEgPSB0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuW3RoaXNbJGV4dHJhXS5wYWdlSW5kZXhdOwogICAgICAgIHJldHVybiBwYWdlQXJlYVskZ2V0TmV4dFBhZ2VdKCk7CiAgICAgIH0KICAgICAgaWYgKHRoaXNbJGV4dHJhXS5wYWdlU2V0SW5kZXggKyAxIDwgdGhpcy5wYWdlU2V0LmNoaWxkcmVuLmxlbmd0aCkgewogICAgICAgIHRoaXNbJGV4dHJhXS5wYWdlU2V0SW5kZXggKz0gMTsKICAgICAgICByZXR1cm4gdGhpcy5wYWdlU2V0LmNoaWxkcmVuW3RoaXNbJGV4dHJhXS5wYWdlU2V0SW5kZXhdWyRnZXROZXh0UGFnZV0oKTsKICAgICAgfQogICAgICBpZiAodGhpc1skaXNVc2FibGVdKCkpIHsKICAgICAgICB0aGlzWyRleHRyYV0ubnVtYmVyT2ZVc2UgKz0gMTsKICAgICAgICB0aGlzWyRleHRyYV0ucGFnZUluZGV4ID0gLTE7CiAgICAgICAgdGhpc1skZXh0cmFdLnBhZ2VTZXRJbmRleCA9IC0xOwogICAgICAgIHJldHVybiB0aGlzWyRnZXROZXh0UGFnZV0oKTsKICAgICAgfQogICAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICAgIGlmIChwYXJlbnQgaW5zdGFuY2VvZiBQYWdlU2V0KSB7CiAgICAgICAgcmV0dXJuIHBhcmVudFskZ2V0TmV4dFBhZ2VdKCk7CiAgICAgIH0KICAgICAgdGhpc1skY2xlYW5QYWdlXSgpOwogICAgICByZXR1cm4gdGhpc1skZ2V0TmV4dFBhZ2VdKCk7CiAgICB9CiAgICBjb25zdCBwYWdlTnVtYmVyID0gdGhpc1skZ2V0VGVtcGxhdGVSb290XSgpWyRleHRyYV0ucGFnZU51bWJlcjsKICAgIGNvbnN0IHBhcml0eSA9IHBhZ2VOdW1iZXIgJSAyID09PSAwID8gImV2ZW4iIDogIm9kZCI7CiAgICBjb25zdCBwb3NpdGlvbiA9IHBhZ2VOdW1iZXIgPT09IDAgPyAiZmlyc3QiIDogInJlc3QiOwogICAgbGV0IHBhZ2UgPSB0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuLmZpbmQocCA9PiBwLm9kZE9yRXZlbiA9PT0gcGFyaXR5ICYmIHAucGFnZVBvc2l0aW9uID09PSBwb3NpdGlvbik7CiAgICBpZiAocGFnZSkgewogICAgICByZXR1cm4gcGFnZTsKICAgIH0KICAgIHBhZ2UgPSB0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuLmZpbmQocCA9PiBwLm9kZE9yRXZlbiA9PT0gImFueSIgJiYgcC5wYWdlUG9zaXRpb24gPT09IHBvc2l0aW9uKTsKICAgIGlmIChwYWdlKSB7CiAgICAgIHJldHVybiBwYWdlOwogICAgfQogICAgcGFnZSA9IHRoaXMucGFnZUFyZWEuY2hpbGRyZW4uZmluZChwID0+IHAub2RkT3JFdmVuID09PSAiYW55IiAmJiBwLnBhZ2VQb3NpdGlvbiA9PT0gImFueSIpOwogICAgaWYgKHBhZ2UpIHsKICAgICAgcmV0dXJuIHBhZ2U7CiAgICB9CiAgICByZXR1cm4gdGhpcy5wYWdlQXJlYS5jaGlsZHJlblswXTsKICB9Cn0KY2xhc3MgUGFyYSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJwYXJhIiwgdHJ1ZSk7CiAgICB0aGlzLmhBbGlnbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmhBbGlnbiwgWyJsZWZ0IiwgImNlbnRlciIsICJqdXN0aWZ5IiwgImp1c3RpZnlBbGwiLCAicmFkaXgiLCAicmlnaHQiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubGluZUhlaWdodCA9IGF0dHJpYnV0ZXMubGluZUhlaWdodCA/IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubGluZUhlaWdodCwgIjBwdCIpIDogIiI7CiAgICB0aGlzLm1hcmdpbkxlZnQgPSBhdHRyaWJ1dGVzLm1hcmdpbkxlZnQgPyBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1hcmdpbkxlZnQsICIwcHQiKSA6ICIiOwogICAgdGhpcy5tYXJnaW5SaWdodCA9IGF0dHJpYnV0ZXMubWFyZ2luUmlnaHQgPyBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1hcmdpblJpZ2h0LCAiMHB0IikgOiAiIjsKICAgIHRoaXMub3JwaGFucyA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLm9ycGhhbnMsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICAgIHRoaXMucHJlc2VydmUgPSBhdHRyaWJ1dGVzLnByZXNlcnZlIHx8ICIiOwogICAgdGhpcy5yYWRpeE9mZnNldCA9IGF0dHJpYnV0ZXMucmFkaXhPZmZzZXQgPyBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnJhZGl4T2Zmc2V0LCAiMHB0IikgOiAiIjsKICAgIHRoaXMuc3BhY2VBYm92ZSA9IGF0dHJpYnV0ZXMuc3BhY2VBYm92ZSA/IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMuc3BhY2VBYm92ZSwgIjBwdCIpIDogIiI7CiAgICB0aGlzLnNwYWNlQmVsb3cgPSBhdHRyaWJ1dGVzLnNwYWNlQmVsb3cgPyBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnNwYWNlQmVsb3csICIwcHQiKSA6ICIiOwogICAgdGhpcy50YWJEZWZhdWx0ID0gYXR0cmlidXRlcy50YWJEZWZhdWx0ID8gZ2V0TWVhc3VyZW1lbnQodGhpcy50YWJEZWZhdWx0KSA6ICIiOwogICAgdGhpcy50YWJTdG9wcyA9IChhdHRyaWJ1dGVzLnRhYlN0b3BzIHx8ICIiKS50cmltKCkuc3BsaXQoL1xzKy8pLm1hcCgoeCwgaSkgPT4gaSAlIDIgPT09IDEgPyBnZXRNZWFzdXJlbWVudCh4KSA6IHgpOwogICAgdGhpcy50ZXh0SW5kZW50ID0gYXR0cmlidXRlcy50ZXh0SW5kZW50ID8gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy50ZXh0SW5kZW50LCAiMHB0IikgOiAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnZBbGlnbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnZBbGlnbiwgWyJ0b3AiLCAiYm90dG9tIiwgIm1pZGRsZSJdKTsKICAgIHRoaXMud2lkb3dzID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMud2lkb3dzLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMAogICAgfSk7CiAgICB0aGlzLmh5cGhlbmF0aW9uID0gbnVsbDsKICB9CiAgWyR0b1N0eWxlXSgpIHsKICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAiaEFsaWduIik7CiAgICBpZiAodGhpcy5tYXJnaW5MZWZ0ICE9PSAiIikgewogICAgICBzdHlsZS5wYWRkaW5nTGVmdCA9IG1lYXN1cmVUb1N0cmluZyh0aGlzLm1hcmdpbkxlZnQpOwogICAgfQogICAgaWYgKHRoaXMubWFyZ2luUmlnaHQgIT09ICIiKSB7CiAgICAgIHN0eWxlLnBhZGRpbmdSaWdodCA9IG1lYXN1cmVUb1N0cmluZyh0aGlzLm1hcmdpblJpZ2h0KTsKICAgIH0KICAgIGlmICh0aGlzLnNwYWNlQWJvdmUgIT09ICIiKSB7CiAgICAgIHN0eWxlLnBhZGRpbmdUb3AgPSBtZWFzdXJlVG9TdHJpbmcodGhpcy5zcGFjZUFib3ZlKTsKICAgIH0KICAgIGlmICh0aGlzLnNwYWNlQmVsb3cgIT09ICIiKSB7CiAgICAgIHN0eWxlLnBhZGRpbmdCb3R0b20gPSBtZWFzdXJlVG9TdHJpbmcodGhpcy5zcGFjZUJlbG93KTsKICAgIH0KICAgIGlmICh0aGlzLnRleHRJbmRlbnQgIT09ICIiKSB7CiAgICAgIHN0eWxlLnRleHRJbmRlbnQgPSBtZWFzdXJlVG9TdHJpbmcodGhpcy50ZXh0SW5kZW50KTsKICAgICAgZml4VGV4dEluZGVudChzdHlsZSk7CiAgICB9CiAgICBpZiAodGhpcy5saW5lSGVpZ2h0ID4gMCkgewogICAgICBzdHlsZS5saW5lSGVpZ2h0ID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMubGluZUhlaWdodCk7CiAgICB9CiAgICBpZiAodGhpcy50YWJEZWZhdWx0ICE9PSAiIikgewogICAgICBzdHlsZS50YWJTaXplID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMudGFiRGVmYXVsdCk7CiAgICB9CiAgICBpZiAodGhpcy50YWJTdG9wcy5sZW5ndGggPiAwKSB7fQogICAgaWYgKHRoaXMuaHlwaGVuYXRhdGlvbikgewogICAgICBPYmplY3QuYXNzaWduKHN0eWxlLCB0aGlzLmh5cGhlbmF0YXRpb25bJHRvU3R5bGVdKCkpOwogICAgfQogICAgcmV0dXJuIHN0eWxlOwogIH0KfQpjbGFzcyBQYXNzd29yZEVkaXQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAicGFzc3dvcmRFZGl0IiwgdHJ1ZSk7CiAgICB0aGlzLmhTY3JvbGxQb2xpY3kgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oU2Nyb2xsUG9saWN5LCBbImF1dG8iLCAib2ZmIiwgIm9uIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnBhc3N3b3JkQ2hhciA9IGF0dHJpYnV0ZXMucGFzc3dvcmRDaGFyIHx8ICIqIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvcmRlciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgfQp9CmNsYXNzIHRlbXBsYXRlX1BhdHRlcm4gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAicGF0dGVybiIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbImNyb3NzSGF0Y2giLCAiY3Jvc3NEaWFnb25hbCIsICJkaWFnb25hbExlZnQiLCAiZGlhZ29uYWxSaWdodCIsICJob3Jpem9udGFsIiwgInZlcnRpY2FsIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29sb3IgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbJHRvU3R5bGVdKHN0YXJ0Q29sb3IpIHsKICAgIHN0YXJ0Q29sb3IgPSBzdGFydENvbG9yID8gc3RhcnRDb2xvclskdG9TdHlsZV0oKSA6ICIjRkZGRkZGIjsKICAgIGNvbnN0IGVuZENvbG9yID0gdGhpcy5jb2xvciA/IHRoaXMuY29sb3JbJHRvU3R5bGVdKCkgOiAiIzAwMDAwMCI7CiAgICBjb25zdCB3aWR0aCA9IDU7CiAgICBjb25zdCBjbWQgPSAicmVwZWF0aW5nLWxpbmVhci1ncmFkaWVudCI7CiAgICBjb25zdCBjb2xvcnMgPSBgJHtzdGFydENvbG9yfSwke3N0YXJ0Q29sb3J9ICR7d2lkdGh9cHgsJHtlbmRDb2xvcn0gJHt3aWR0aH1weCwke2VuZENvbG9yfSAkezIgKiB3aWR0aH1weGA7CiAgICBzd2l0Y2ggKHRoaXMudHlwZSkgewogICAgICBjYXNlICJjcm9zc0hhdGNoIjoKICAgICAgICByZXR1cm4gYCR7Y21kfSh0byB0b3AsJHtjb2xvcnN9KSAke2NtZH0odG8gcmlnaHQsJHtjb2xvcnN9KWA7CiAgICAgIGNhc2UgImNyb3NzRGlhZ29uYWwiOgogICAgICAgIHJldHVybiBgJHtjbWR9KDQ1ZGVnLCR7Y29sb3JzfSkgJHtjbWR9KC00NWRlZywke2NvbG9yc30pYDsKICAgICAgY2FzZSAiZGlhZ29uYWxMZWZ0IjoKICAgICAgICByZXR1cm4gYCR7Y21kfSg0NWRlZywke2NvbG9yc30pYDsKICAgICAgY2FzZSAiZGlhZ29uYWxSaWdodCI6CiAgICAgICAgcmV0dXJuIGAke2NtZH0oLTQ1ZGVnLCR7Y29sb3JzfSlgOwogICAgICBjYXNlICJob3Jpem9udGFsIjoKICAgICAgICByZXR1cm4gYCR7Y21kfSh0byB0b3AsJHtjb2xvcnN9KWA7CiAgICAgIGNhc2UgInZlcnRpY2FsIjoKICAgICAgICByZXR1cm4gYCR7Y21kfSh0byByaWdodCwke2NvbG9yc30pYDsKICAgIH0KICAgIHJldHVybiAiIjsKICB9Cn0KY2xhc3MgUGljdHVyZSBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJwaWN0dXJlIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIFByb3RvIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInByb3RvIiwgdHJ1ZSk7CiAgICB0aGlzLmFwcGVhcmFuY2VGaWx0ZXIgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYXJjID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmFyZWEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYXNzaXN0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJhcmNvZGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYmluZEl0ZW1zID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJvb2tlbmQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYm9vbGVhbiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5ib3JkZXIgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYnJlYWsgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYnJlYWtBZnRlciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5icmVha0JlZm9yZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5idXR0b24gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY2FsY3VsYXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNhcHRpb24gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY2VydGlmaWNhdGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY2VydGlmaWNhdGVzID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNoZWNrQnV0dG9uID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNob2ljZUxpc3QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY29sb3IgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY29tYiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5jb25uZWN0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNvbnRlbnRBcmVhID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNvcm5lciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGVUaW1lID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGVUaW1lRWRpdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWNpbWFsID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRlZmF1bHRVaSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZXNjID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRpZ2VzdE1ldGhvZCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kaWdlc3RNZXRob2RzID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRyYXcgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZWRnZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lbmNvZGluZyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lbmNvZGluZ3MgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZW5jcnlwdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lbmNyeXB0RGF0YSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lbmNyeXB0aW9uID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmVuY3J5cHRpb25NZXRob2QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZW5jcnlwdGlvbk1ldGhvZHMgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXZlbnQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXhEYXRhID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4T2JqZWN0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4Y2xHcm91cCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leGVjdXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4dHJhcyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5maWVsZCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5maWxsID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmZpbHRlciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5mbG9hdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5mb250ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmZvcm1hdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5oYW5kbGVyID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmh5cGhlbmF0aW9uID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmltYWdlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmltYWdlRWRpdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbnRlZ2VyID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmlzc3VlcnMgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaXRlbXMgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMua2VlcCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5rZXlVc2FnZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5saW5lID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmxpbmVhciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5sb2NrRG9jdW1lbnQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubWFuaWZlc3QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubWFyZ2luID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLm1kcCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5tZWRpdW0gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubWVzc2FnZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5udW1lcmljRWRpdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5vY2N1ciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5vaWQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMub2lkcyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5vdmVyZmxvdyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wYWdlQXJlYSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wYWdlU2V0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnBhcmEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucGFzc3dvcmRFZGl0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnBhdHRlcm4gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucGljdHVyZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5yYWRpYWwgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucmVhc29uID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnJlYXNvbnMgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucmVjdGFuZ2xlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnJlZiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zY3JpcHQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2V0UHJvcGVydHkgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2lnbkRhdGEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2lnbmF0dXJlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnNpZ25pbmcgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc29saWQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3BlYWsgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3RpcHBsZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJmb3JtID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1YmZvcm1TZXQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViamVjdEROID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1YmplY3RETnMgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3VibWl0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGV4dEVkaXQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50aW1lU3RhbXAgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudG9vbFRpcCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50cmF2ZXJzYWwgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudHJhdmVyc2UgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudWkgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudmFsaWRhdGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudmFsdWUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudmFyaWFibGVzID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIFJhZGlhbCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJyYWRpYWwiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJ0b0VkZ2UiLCAidG9DZW50ZXIiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jb2xvciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFskdG9TdHlsZV0oc3RhcnRDb2xvcikgewogICAgc3RhcnRDb2xvciA9IHN0YXJ0Q29sb3IgPyBzdGFydENvbG9yWyR0b1N0eWxlXSgpIDogIiNGRkZGRkYiOwogICAgY29uc3QgZW5kQ29sb3IgPSB0aGlzLmNvbG9yID8gdGhpcy5jb2xvclskdG9TdHlsZV0oKSA6ICIjMDAwMDAwIjsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMudHlwZSA9PT0gInRvRWRnZSIgPyBgJHtzdGFydENvbG9yfSwke2VuZENvbG9yfWAgOiBgJHtlbmRDb2xvcn0sJHtzdGFydENvbG9yfWA7CiAgICByZXR1cm4gYHJhZGlhbC1ncmFkaWVudChjaXJjbGUgYXQgY2VudGVyLCAke2NvbG9yc30pYDsKICB9Cn0KY2xhc3MgUmVhc29uIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInJlYXNvbiIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBSZWFzb25zIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInJlYXNvbnMiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnJlYXNvbiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBSZWN0YW5nbGUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAicmVjdGFuZ2xlIiwgdHJ1ZSk7CiAgICB0aGlzLmhhbmQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oYW5kLCBbImV2ZW4iLCAibGVmdCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29ybmVyID0gbmV3IFhGQU9iamVjdEFycmF5KDQpOwogICAgdGhpcy5lZGdlID0gbmV3IFhGQU9iamVjdEFycmF5KDQpOwogICAgdGhpcy5maWxsID0gbnVsbDsKICB9CiAgWyR0b0hUTUxdKCkgewogICAgY29uc3QgZWRnZSA9IHRoaXMuZWRnZS5jaGlsZHJlbi5sZW5ndGggPyB0aGlzLmVkZ2UuY2hpbGRyZW5bMF0gOiBuZXcgRWRnZSh7fSk7CiAgICBjb25zdCBlZGdlU3R5bGUgPSBlZGdlWyR0b1N0eWxlXSgpOwogICAgY29uc3Qgc3R5bGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgaWYgKHRoaXMuZmlsbD8ucHJlc2VuY2UgPT09ICJ2aXNpYmxlIikgewogICAgICBPYmplY3QuYXNzaWduKHN0eWxlLCB0aGlzLmZpbGxbJHRvU3R5bGVdKCkpOwogICAgfSBlbHNlIHsKICAgICAgc3R5bGUuZmlsbCA9ICJ0cmFuc3BhcmVudCI7CiAgICB9CiAgICBzdHlsZS5zdHJva2VXaWR0aCA9IG1lYXN1cmVUb1N0cmluZyhlZGdlLnByZXNlbmNlID09PSAidmlzaWJsZSIgPyBlZGdlLnRoaWNrbmVzcyA6IDApOwogICAgc3R5bGUuc3Ryb2tlID0gZWRnZVN0eWxlLmNvbG9yOwogICAgY29uc3QgY29ybmVyID0gdGhpcy5jb3JuZXIuY2hpbGRyZW4ubGVuZ3RoID8gdGhpcy5jb3JuZXIuY2hpbGRyZW5bMF0gOiBuZXcgQ29ybmVyKHt9KTsKICAgIGNvbnN0IGNvcm5lclN0eWxlID0gY29ybmVyWyR0b1N0eWxlXSgpOwogICAgY29uc3QgcmVjdCA9IHsKICAgICAgbmFtZTogInJlY3QiLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgeG1sbnM6IFNWR19OUywKICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgIGhlaWdodDogIjEwMCUiLAogICAgICAgIHg6IDAsCiAgICAgICAgeTogMCwKICAgICAgICByeDogY29ybmVyU3R5bGUucmFkaXVzLAogICAgICAgIHJ5OiBjb3JuZXJTdHlsZS5yYWRpdXMsCiAgICAgICAgc3R5bGUKICAgICAgfQogICAgfTsKICAgIGNvbnN0IHN2ZyA9IHsKICAgICAgbmFtZTogInN2ZyIsCiAgICAgIGNoaWxkcmVuOiBbcmVjdF0sCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICB4bWxuczogU1ZHX05TLAogICAgICAgIHN0eWxlOiB7CiAgICAgICAgICBvdmVyZmxvdzogInZpc2libGUiCiAgICAgICAgfSwKICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgIGhlaWdodDogIjEwMCUiCiAgICAgIH0KICAgIH07CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKClbJGdldFBhcmVudF0oKTsKICAgIGlmIChoYXNNYXJnaW4ocGFyZW50KSkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgICBuYW1lOiAiZGl2IiwKICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICBzdHlsZTogewogICAgICAgICAgICBkaXNwbGF5OiAiaW5saW5lIiwKICAgICAgICAgICAgd2lkdGg6ICIxMDAlIiwKICAgICAgICAgICAgaGVpZ2h0OiAiMTAwJSIKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGNoaWxkcmVuOiBbc3ZnXQogICAgICB9KTsKICAgIH0KICAgIHN2Zy5hdHRyaWJ1dGVzLnN0eWxlLnBvc2l0aW9uID0gImFic29sdXRlIjsKICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3Moc3ZnKTsKICB9Cn0KY2xhc3MgUmVmRWxlbWVudCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJyZWYiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgU2NyaXB0IGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInNjcmlwdCIpOwogICAgdGhpcy5iaW5kaW5nID0gYXR0cmlidXRlcy5iaW5kaW5nIHx8ICIiOwogICAgdGhpcy5jb250ZW50VHlwZSA9IGF0dHJpYnV0ZXMuY29udGVudFR5cGUgfHwgIiI7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucnVuQXQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5ydW5BdCwgWyJjbGllbnQiLCAiYm90aCIsICJzZXJ2ZXIiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBTZXRQcm9wZXJ0eSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzZXRQcm9wZXJ0eSIpOwogICAgdGhpcy5jb25uZWN0aW9uID0gYXR0cmlidXRlcy5jb25uZWN0aW9uIHx8ICIiOwogICAgdGhpcy5yZWYgPSBhdHRyaWJ1dGVzLnJlZiB8fCAiIjsKICAgIHRoaXMudGFyZ2V0ID0gYXR0cmlidXRlcy50YXJnZXQgfHwgIiI7CiAgfQp9CmNsYXNzIFNpZ25EYXRhIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInNpZ25EYXRhIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMub3BlcmF0aW9uID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMub3BlcmF0aW9uLCBbInNpZ24iLCAiY2xlYXIiLCAidmVyaWZ5Il0pOwogICAgdGhpcy5yZWYgPSBhdHRyaWJ1dGVzLnJlZiB8fCAiIjsKICAgIHRoaXMudGFyZ2V0ID0gYXR0cmlidXRlcy50YXJnZXQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5maWx0ZXIgPSBudWxsOwogICAgdGhpcy5tYW5pZmVzdCA9IG51bGw7CiAgfQp9CmNsYXNzIFNpZ25hdHVyZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzaWduYXR1cmUiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJQREYxLjMiLCAiUERGMS42Il0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuZmlsdGVyID0gbnVsbDsKICAgIHRoaXMubWFuaWZlc3QgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KfQpjbGFzcyBTaWduaW5nIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInNpZ25pbmciLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNlcnRpZmljYXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIFNvbGlkIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInNvbGlkIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFskdG9TdHlsZV0oc3RhcnRDb2xvcikgewogICAgcmV0dXJuIHN0YXJ0Q29sb3IgPyBzdGFydENvbG9yWyR0b1N0eWxlXSgpIDogIiNGRkZGRkYiOwogIH0KfQpjbGFzcyBTcGVhayBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzcGVhayIpOwogICAgdGhpcy5kaXNhYmxlID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZGlzYWJsZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5wcmlvcml0eSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnByaW9yaXR5LCBbImN1c3RvbSIsICJjYXB0aW9uIiwgIm5hbWUiLCAidG9vbFRpcCJdKTsKICAgIHRoaXMucmlkID0gYXR0cmlidXRlcy5yaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBTdGlwcGxlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInN0aXBwbGUiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5yYXRlID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMucmF0ZSwKICAgICAgZGVmYXVsdFZhbHVlOiA1MCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwICYmIHggPD0gMTAwCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNvbG9yID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9CiAgWyR0b1N0eWxlXShiZ0NvbG9yKSB7CiAgICBjb25zdCBhbHBoYSA9IHRoaXMucmF0ZSAvIDEwMDsKICAgIHJldHVybiBVdGlsLm1ha2VIZXhDb2xvcihNYXRoLnJvdW5kKGJnQ29sb3IudmFsdWUuciAqICgxIC0gYWxwaGEpICsgdGhpcy52YWx1ZS5yICogYWxwaGEpLCBNYXRoLnJvdW5kKGJnQ29sb3IudmFsdWUuZyAqICgxIC0gYWxwaGEpICsgdGhpcy52YWx1ZS5nICogYWxwaGEpLCBNYXRoLnJvdW5kKGJnQ29sb3IudmFsdWUuYiAqICgxIC0gYWxwaGEpICsgdGhpcy52YWx1ZS5iICogYWxwaGEpKTsKICB9Cn0KY2xhc3MgU3ViZm9ybSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzdWJmb3JtIiwgdHJ1ZSk7CiAgICB0aGlzLmFjY2VzcyA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmFjY2VzcywgWyJvcGVuIiwgIm5vbkludGVyYWN0aXZlIiwgInByb3RlY3RlZCIsICJyZWFkT25seSJdKTsKICAgIHRoaXMuYWxsb3dNYWNybyA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmFsbG93TWFjcm8sCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmFuY2hvclR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5hbmNob3JUeXBlLCBbInRvcExlZnQiLCAiYm90dG9tQ2VudGVyIiwgImJvdHRvbUxlZnQiLCAiYm90dG9tUmlnaHQiLCAibWlkZGxlQ2VudGVyIiwgIm1pZGRsZUxlZnQiLCAibWlkZGxlUmlnaHQiLCAidG9wQ2VudGVyIiwgInRvcFJpZ2h0Il0pOwogICAgdGhpcy5jb2xTcGFuID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuY29sU3BhbiwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogbiA9PiBuID49IDEgfHwgbiA9PT0gLTEKICAgIH0pOwogICAgdGhpcy5jb2x1bW5XaWR0aHMgPSAoYXR0cmlidXRlcy5jb2x1bW5XaWR0aHMgfHwgIiIpLnRyaW0oKS5zcGxpdCgvXHMrLykubWFwKHggPT4geCA9PT0gIi0xIiA/IC0xIDogZ2V0TWVhc3VyZW1lbnQoeCkpOwogICAgdGhpcy5oID0gYXR0cmlidXRlcy5oID8gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5oKSA6ICIiOwogICAgdGhpcy5oQWxpZ24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oQWxpZ24sIFsibGVmdCIsICJjZW50ZXIiLCAianVzdGlmeSIsICJqdXN0aWZ5QWxsIiwgInJhZGl4IiwgInJpZ2h0Il0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxheW91dCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmxheW91dCwgWyJwb3NpdGlvbiIsICJsci10YiIsICJybC1yb3ciLCAicmwtdGIiLCAicm93IiwgInRhYmxlIiwgInRiIl0pOwogICAgdGhpcy5sb2NhbGUgPSBhdHRyaWJ1dGVzLmxvY2FsZSB8fCAiIjsKICAgIHRoaXMubWF4SCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubWF4SCwgIjBwdCIpOwogICAgdGhpcy5tYXhXID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5tYXhXLCAiMHB0Iik7CiAgICB0aGlzLm1lcmdlTW9kZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm1lcmdlTW9kZSwgWyJjb25zdW1lRGF0YSIsICJtYXRjaFRlbXBsYXRlIl0pOwogICAgdGhpcy5taW5IID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5taW5ILCAiMHB0Iik7CiAgICB0aGlzLm1pblcgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1pblcsICIwcHQiKTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucHJlc2VuY2UgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5wcmVzZW5jZSwgWyJ2aXNpYmxlIiwgImhpZGRlbiIsICJpbmFjdGl2ZSIsICJpbnZpc2libGUiXSk7CiAgICB0aGlzLnJlbGV2YW50ID0gZ2V0UmVsZXZhbnQoYXR0cmlidXRlcy5yZWxldmFudCk7CiAgICB0aGlzLnJlc3RvcmVTdGF0ZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnJlc3RvcmVTdGF0ZSwgWyJtYW51YWwiLCAiYXV0byJdKTsKICAgIHRoaXMuc2NvcGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5zY29wZSwgWyJuYW1lIiwgIm5vbmUiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy53ID0gYXR0cmlidXRlcy53ID8gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy53KSA6ICIiOwogICAgdGhpcy54ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy54LCAiMHB0Iik7CiAgICB0aGlzLnkgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnksICIwcHQiKTsKICAgIHRoaXMuYXNzaXN0ID0gbnVsbDsKICAgIHRoaXMuYmluZCA9IG51bGw7CiAgICB0aGlzLmJvb2tlbmQgPSBudWxsOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5icmVhayA9IG51bGw7CiAgICB0aGlzLmNhbGN1bGF0ZSA9IG51bGw7CiAgICB0aGlzLmRlc2MgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5rZWVwID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICAgIHRoaXMub2NjdXIgPSBudWxsOwogICAgdGhpcy5vdmVyZmxvdyA9IG51bGw7CiAgICB0aGlzLnBhZ2VTZXQgPSBudWxsOwogICAgdGhpcy5wYXJhID0gbnVsbDsKICAgIHRoaXMudHJhdmVyc2FsID0gbnVsbDsKICAgIHRoaXMudmFsaWRhdGUgPSBudWxsOwogICAgdGhpcy52YXJpYWJsZXMgPSBudWxsOwogICAgdGhpcy5hcmVhID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJyZWFrQWZ0ZXIgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYnJlYWtCZWZvcmUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY29ubmVjdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kcmF3ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV2ZW50ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4T2JqZWN0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4Y2xHcm91cCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5maWVsZCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wcm90byA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zZXRQcm9wZXJ0eSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJmb3JtID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1YmZvcm1TZXQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9CiAgWyRnZXRTdWJmb3JtUGFyZW50XSgpIHsKICAgIGNvbnN0IHBhcmVudCA9IHRoaXNbJGdldFBhcmVudF0oKTsKICAgIGlmIChwYXJlbnQgaW5zdGFuY2VvZiBTdWJmb3JtU2V0KSB7CiAgICAgIHJldHVybiBwYXJlbnRbJGdldFN1YmZvcm1QYXJlbnRdKCk7CiAgICB9CiAgICByZXR1cm4gcGFyZW50OwogIH0KICBbJGlzQmluZGFibGVdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIFskaXNUaGVyZU1vcmVXaWR0aF0oKSB7CiAgICByZXR1cm4gdGhpcy5sYXlvdXQuZW5kc1dpdGgoIi10YiIpICYmIHRoaXNbJGV4dHJhXS5hdHRlbXB0ID09PSAwICYmIHRoaXNbJGV4dHJhXS5udW1iZXJJbkxpbmUgPiAwIHx8IHRoaXNbJGdldFBhcmVudF0oKVskaXNUaGVyZU1vcmVXaWR0aF0oKTsKICB9CiAgKlskZ2V0Q29udGFpbmVkQ2hpbGRyZW5dKCkgewogICAgeWllbGQqIGdldENvbnRhaW5lZENoaWxkcmVuKHRoaXMpOwogIH0KICBbJGZsdXNoSFRNTF0oKSB7CiAgICByZXR1cm4gZmx1c2hIVE1MKHRoaXMpOwogIH0KICBbJGFkZEhUTUxdKGh0bWwsIGJib3gpIHsKICAgIGFkZEhUTUwodGhpcywgaHRtbCwgYmJveCk7CiAgfQogIFskZ2V0QXZhaWxhYmxlU3BhY2VdKCkgewogICAgcmV0dXJuIGdldEF2YWlsYWJsZVNwYWNlKHRoaXMpOwogIH0KICBbJGlzU3BsaXR0YWJsZV0oKSB7CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRTdWJmb3JtUGFyZW50XSgpOwogICAgaWYgKCFwYXJlbnRbJGlzU3BsaXR0YWJsZV0oKSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpc1skZXh0cmFdLl9pc1NwbGl0dGFibGUgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gdGhpc1skZXh0cmFdLl9pc1NwbGl0dGFibGU7CiAgICB9CiAgICBpZiAodGhpcy5sYXlvdXQgPT09ICJwb3NpdGlvbiIgfHwgdGhpcy5sYXlvdXQuaW5jbHVkZXMoInJvdyIpKSB7CiAgICAgIHRoaXNbJGV4dHJhXS5faXNTcGxpdHRhYmxlID0gZmFsc2U7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmICh0aGlzLmtlZXAgJiYgdGhpcy5rZWVwLmludGFjdCAhPT0gIm5vbmUiKSB7CiAgICAgIHRoaXNbJGV4dHJhXS5faXNTcGxpdHRhYmxlID0gZmFsc2U7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmIChwYXJlbnQubGF5b3V0Py5lbmRzV2l0aCgiLXRiIikgJiYgcGFyZW50WyRleHRyYV0ubnVtYmVySW5MaW5lICE9PSAwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHRoaXNbJGV4dHJhXS5faXNTcGxpdHRhYmxlID0gdHJ1ZTsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIHNldFRhYkluZGV4KHRoaXMpOwogICAgaWYgKHRoaXMuYnJlYWspIHsKICAgICAgaWYgKHRoaXMuYnJlYWsuYWZ0ZXIgIT09ICJhdXRvIiB8fCB0aGlzLmJyZWFrLmFmdGVyVGFyZ2V0ICE9PSAiIikgewogICAgICAgIGNvbnN0IG5vZGUgPSBuZXcgQnJlYWtBZnRlcih7CiAgICAgICAgICB0YXJnZXRUeXBlOiB0aGlzLmJyZWFrLmFmdGVyLAogICAgICAgICAgdGFyZ2V0OiB0aGlzLmJyZWFrLmFmdGVyVGFyZ2V0LAogICAgICAgICAgc3RhcnROZXc6IHRoaXMuYnJlYWsuc3RhcnROZXcudG9TdHJpbmcoKQogICAgICAgIH0pOwogICAgICAgIG5vZGVbJGdsb2JhbERhdGFdID0gdGhpc1skZ2xvYmFsRGF0YV07CiAgICAgICAgdGhpc1skYXBwZW5kQ2hpbGRdKG5vZGUpOwogICAgICAgIHRoaXMuYnJlYWtBZnRlci5wdXNoKG5vZGUpOwogICAgICB9CiAgICAgIGlmICh0aGlzLmJyZWFrLmJlZm9yZSAhPT0gImF1dG8iIHx8IHRoaXMuYnJlYWsuYmVmb3JlVGFyZ2V0ICE9PSAiIikgewogICAgICAgIGNvbnN0IG5vZGUgPSBuZXcgQnJlYWtCZWZvcmUoewogICAgICAgICAgdGFyZ2V0VHlwZTogdGhpcy5icmVhay5iZWZvcmUsCiAgICAgICAgICB0YXJnZXQ6IHRoaXMuYnJlYWsuYmVmb3JlVGFyZ2V0LAogICAgICAgICAgc3RhcnROZXc6IHRoaXMuYnJlYWsuc3RhcnROZXcudG9TdHJpbmcoKQogICAgICAgIH0pOwogICAgICAgIG5vZGVbJGdsb2JhbERhdGFdID0gdGhpc1skZ2xvYmFsRGF0YV07CiAgICAgICAgdGhpc1skYXBwZW5kQ2hpbGRdKG5vZGUpOwogICAgICAgIHRoaXMuYnJlYWtCZWZvcmUucHVzaChub2RlKTsKICAgICAgfQogICAgICBpZiAodGhpcy5icmVhay5vdmVyZmxvd1RhcmdldCAhPT0gIiIpIHsKICAgICAgICBjb25zdCBub2RlID0gbmV3IE92ZXJmbG93KHsKICAgICAgICAgIHRhcmdldDogdGhpcy5icmVhay5vdmVyZmxvd1RhcmdldCwKICAgICAgICAgIGxlYWRlcjogdGhpcy5icmVhay5vdmVyZmxvd0xlYWRlciwKICAgICAgICAgIHRyYWlsZXI6IHRoaXMuYnJlYWsub3ZlcmZsb3dUcmFpbGVyCiAgICAgICAgfSk7CiAgICAgICAgbm9kZVskZ2xvYmFsRGF0YV0gPSB0aGlzWyRnbG9iYWxEYXRhXTsKICAgICAgICB0aGlzWyRhcHBlbmRDaGlsZF0obm9kZSk7CiAgICAgICAgdGhpcy5vdmVyZmxvdy5wdXNoKG5vZGUpOwogICAgICB9CiAgICAgIHRoaXNbJHJlbW92ZUNoaWxkXSh0aGlzLmJyZWFrKTsKICAgICAgdGhpcy5icmVhayA9IG51bGw7CiAgICB9CiAgICBpZiAodGhpcy5wcmVzZW5jZSA9PT0gImhpZGRlbiIgfHwgdGhpcy5wcmVzZW5jZSA9PT0gImluYWN0aXZlIikgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGlmICh0aGlzLmJyZWFrQmVmb3JlLmNoaWxkcmVuLmxlbmd0aCA+IDEgfHwgdGhpcy5icmVha0FmdGVyLmNoaWxkcmVuLmxlbmd0aCA+IDEpIHsKICAgICAgd2FybigiWEZBIC0gU2V2ZXJhbCBicmVha0JlZm9yZSBvciBicmVha0FmdGVyIGluIHN1YmZvcm1zOiBwbGVhc2UgZmlsZSBhIGJ1Zy4iKTsKICAgIH0KICAgIGlmICh0aGlzLmJyZWFrQmVmb3JlLmNoaWxkcmVuLmxlbmd0aCA+PSAxKSB7CiAgICAgIGNvbnN0IGJyZWFrQmVmb3JlID0gdGhpcy5icmVha0JlZm9yZS5jaGlsZHJlblswXTsKICAgICAgaWYgKGhhbmRsZUJyZWFrKGJyZWFrQmVmb3JlKSkgewogICAgICAgIHJldHVybiBIVE1MUmVzdWx0LmJyZWFrTm9kZShicmVha0JlZm9yZSk7CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzWyRleHRyYV0/LmFmdGVyQnJlYWtBZnRlcikgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGZpeERpbWVuc2lvbnModGhpcyk7CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgaWQ6IHRoaXNbJHVpZF0sCiAgICAgIGNsYXNzOiBbXQogICAgfTsKICAgIHNldEFjY2Vzcyh0aGlzLCBhdHRyaWJ1dGVzLmNsYXNzKTsKICAgIHRoaXNbJGV4dHJhXSB8fD0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIE9iamVjdC5hc3NpZ24odGhpc1skZXh0cmFdLCB7CiAgICAgIGNoaWxkcmVuLAogICAgICBsaW5lOiBudWxsLAogICAgICBhdHRyaWJ1dGVzLAogICAgICBhdHRlbXB0OiAwLAogICAgICBudW1iZXJJbkxpbmU6IDAsCiAgICAgIGF2YWlsYWJsZVNwYWNlOiB7CiAgICAgICAgd2lkdGg6IE1hdGgubWluKHRoaXMudyB8fCBJbmZpbml0eSwgYXZhaWxhYmxlU3BhY2Uud2lkdGgpLAogICAgICAgIGhlaWdodDogTWF0aC5taW4odGhpcy5oIHx8IEluZmluaXR5LCBhdmFpbGFibGVTcGFjZS5oZWlnaHQpCiAgICAgIH0sCiAgICAgIHdpZHRoOiAwLAogICAgICBoZWlnaHQ6IDAsCiAgICAgIHByZXZIZWlnaHQ6IDAsCiAgICAgIGN1cnJlbnRXaWR0aDogMAogICAgfSk7CiAgICBjb25zdCByb290ID0gdGhpc1skZ2V0VGVtcGxhdGVSb290XSgpOwogICAgY29uc3Qgc2F2ZWROb0xheW91dEZhaWx1cmUgPSByb290WyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlOwogICAgY29uc3QgaXNTcGxpdHRhYmxlID0gdGhpc1skaXNTcGxpdHRhYmxlXSgpOwogICAgaWYgKCFpc1NwbGl0dGFibGUpIHsKICAgICAgc2V0Rmlyc3RVbnNwbGl0dGFibGUodGhpcyk7CiAgICB9CiAgICBpZiAoIWNoZWNrRGltZW5zaW9ucyh0aGlzLCBhdmFpbGFibGVTcGFjZSkpIHsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuRkFJTFVSRTsKICAgIH0KICAgIGNvbnN0IGZpbHRlciA9IG5ldyBTZXQoWyJhcmVhIiwgImRyYXciLCAiZXhjbEdyb3VwIiwgImZpZWxkIiwgInN1YmZvcm0iLCAic3ViZm9ybVNldCJdKTsKICAgIGlmICh0aGlzLmxheW91dC5pbmNsdWRlcygicm93IikpIHsKICAgICAgY29uc3QgY29sdW1uV2lkdGhzID0gdGhpc1skZ2V0U3ViZm9ybVBhcmVudF0oKS5jb2x1bW5XaWR0aHM7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvbHVtbldpZHRocykgJiYgY29sdW1uV2lkdGhzLmxlbmd0aCA+IDApIHsKICAgICAgICB0aGlzWyRleHRyYV0uY29sdW1uV2lkdGhzID0gY29sdW1uV2lkdGhzOwogICAgICAgIHRoaXNbJGV4dHJhXS5jdXJyZW50Q29sdW1uID0gMDsKICAgICAgfQogICAgfQogICAgY29uc3Qgc3R5bGUgPSB0b1N0eWxlKHRoaXMsICJhbmNob3JUeXBlIiwgImRpbWVuc2lvbnMiLCAicG9zaXRpb24iLCAicHJlc2VuY2UiLCAiYm9yZGVyIiwgIm1hcmdpbiIsICJoQWxpZ24iKTsKICAgIGNvbnN0IGNsYXNzTmFtZXMgPSBbInhmYVN1YmZvcm0iXTsKICAgIGNvbnN0IGNsID0gbGF5b3V0Q2xhc3ModGhpcyk7CiAgICBpZiAoY2wpIHsKICAgICAgY2xhc3NOYW1lcy5wdXNoKGNsKTsKICAgIH0KICAgIGF0dHJpYnV0ZXMuc3R5bGUgPSBzdHlsZTsKICAgIGF0dHJpYnV0ZXMuY2xhc3MgPSBjbGFzc05hbWVzOwogICAgaWYgKHRoaXMubmFtZSkgewogICAgICBhdHRyaWJ1dGVzLnhmYU5hbWUgPSB0aGlzLm5hbWU7CiAgICB9CiAgICBpZiAodGhpcy5vdmVyZmxvdykgewogICAgICBjb25zdCBvdmVyZmxvd0V4dHJhID0gdGhpcy5vdmVyZmxvd1skZ2V0RXh0cmFdKCk7CiAgICAgIGlmIChvdmVyZmxvd0V4dHJhLmFkZExlYWRlcikgewogICAgICAgIG92ZXJmbG93RXh0cmEuYWRkTGVhZGVyID0gZmFsc2U7CiAgICAgICAgaGFuZGxlT3ZlcmZsb3codGhpcywgb3ZlcmZsb3dFeHRyYS5sZWFkZXIsIGF2YWlsYWJsZVNwYWNlKTsKICAgICAgfQogICAgfQogICAgdGhpc1skcHVzaFBhcmFdKCk7CiAgICBjb25zdCBpc0xyVGIgPSB0aGlzLmxheW91dCA9PT0gImxyLXRiIiB8fCB0aGlzLmxheW91dCA9PT0gInJsLXRiIjsKICAgIGNvbnN0IG1heFJ1biA9IGlzTHJUYiA/IE1BWF9BVFRFTVBUU19GT1JfTFJUQl9MQVlPVVQgOiAxOwogICAgZm9yICg7IHRoaXNbJGV4dHJhXS5hdHRlbXB0IDwgbWF4UnVuOyB0aGlzWyRleHRyYV0uYXR0ZW1wdCsrKSB7CiAgICAgIGlmIChpc0xyVGIgJiYgdGhpc1skZXh0cmFdLmF0dGVtcHQgPT09IE1BWF9BVFRFTVBUU19GT1JfTFJUQl9MQVlPVVQgLSAxKSB7CiAgICAgICAgdGhpc1skZXh0cmFdLm51bWJlckluTGluZSA9IDA7CiAgICAgIH0KICAgICAgY29uc3QgcmVzdWx0ID0gdGhpc1skY2hpbGRyZW5Ub0hUTUxdKHsKICAgICAgICBmaWx0ZXIsCiAgICAgICAgaW5jbHVkZTogdHJ1ZQogICAgICB9KTsKICAgICAgaWYgKHJlc3VsdC5zdWNjZXNzKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKHJlc3VsdC5pc0JyZWFrKCkpIHsKICAgICAgICB0aGlzWyRwb3BQYXJhXSgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KICAgICAgaWYgKGlzTHJUYiAmJiB0aGlzWyRleHRyYV0uYXR0ZW1wdCA9PT0gMCAmJiB0aGlzWyRleHRyYV0ubnVtYmVySW5MaW5lID09PSAwICYmICFyb290WyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlKSB7CiAgICAgICAgdGhpc1skZXh0cmFdLmF0dGVtcHQgPSBtYXhSdW47CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICBpZiAoIWlzU3BsaXR0YWJsZSkgewogICAgICB1bnNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgfQogICAgcm9vdFskZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSA9IHNhdmVkTm9MYXlvdXRGYWlsdXJlOwogICAgaWYgKHRoaXNbJGV4dHJhXS5hdHRlbXB0ID09PSBtYXhSdW4pIHsKICAgICAgaWYgKHRoaXMub3ZlcmZsb3cpIHsKICAgICAgICB0aGlzWyRnZXRUZW1wbGF0ZVJvb3RdKClbJGV4dHJhXS5vdmVyZmxvd05vZGUgPSB0aGlzLm92ZXJmbG93OwogICAgICB9CiAgICAgIGlmICghaXNTcGxpdHRhYmxlKSB7CiAgICAgICAgZGVsZXRlIHRoaXNbJGV4dHJhXTsKICAgICAgfQogICAgICByZXR1cm4gSFRNTFJlc3VsdC5GQUlMVVJFOwogICAgfQogICAgaWYgKHRoaXMub3ZlcmZsb3cpIHsKICAgICAgY29uc3Qgb3ZlcmZsb3dFeHRyYSA9IHRoaXMub3ZlcmZsb3dbJGdldEV4dHJhXSgpOwogICAgICBpZiAob3ZlcmZsb3dFeHRyYS5hZGRUcmFpbGVyKSB7CiAgICAgICAgb3ZlcmZsb3dFeHRyYS5hZGRUcmFpbGVyID0gZmFsc2U7CiAgICAgICAgaGFuZGxlT3ZlcmZsb3codGhpcywgb3ZlcmZsb3dFeHRyYS50cmFpbGVyLCBhdmFpbGFibGVTcGFjZSk7CiAgICAgIH0KICAgIH0KICAgIGxldCBtYXJnaW5IID0gMDsKICAgIGxldCBtYXJnaW5WID0gMDsKICAgIGlmICh0aGlzLm1hcmdpbikgewogICAgICBtYXJnaW5IID0gdGhpcy5tYXJnaW4ubGVmdEluc2V0ICsgdGhpcy5tYXJnaW4ucmlnaHRJbnNldDsKICAgICAgbWFyZ2luViA9IHRoaXMubWFyZ2luLnRvcEluc2V0ICsgdGhpcy5tYXJnaW4uYm90dG9tSW5zZXQ7CiAgICB9CiAgICBjb25zdCB3aWR0aCA9IE1hdGgubWF4KHRoaXNbJGV4dHJhXS53aWR0aCArIG1hcmdpbkgsIHRoaXMudyB8fCAwKTsKICAgIGNvbnN0IGhlaWdodCA9IE1hdGgubWF4KHRoaXNbJGV4dHJhXS5oZWlnaHQgKyBtYXJnaW5WLCB0aGlzLmggfHwgMCk7CiAgICBjb25zdCBiYm94ID0gW3RoaXMueCwgdGhpcy55LCB3aWR0aCwgaGVpZ2h0XTsKICAgIGlmICh0aGlzLncgPT09ICIiKSB7CiAgICAgIHN0eWxlLndpZHRoID0gbWVhc3VyZVRvU3RyaW5nKHdpZHRoKTsKICAgIH0KICAgIGlmICh0aGlzLmggPT09ICIiKSB7CiAgICAgIHN0eWxlLmhlaWdodCA9IG1lYXN1cmVUb1N0cmluZyhoZWlnaHQpOwogICAgfQogICAgaWYgKChzdHlsZS53aWR0aCA9PT0gIjBweCIgfHwgc3R5bGUuaGVpZ2h0ID09PSAiMHB4IikgJiYgY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGNoaWxkcmVuCiAgICB9OwogICAgYXBwbHlBc3Npc3QodGhpcywgYXR0cmlidXRlcyk7CiAgICBjb25zdCByZXN1bHQgPSBIVE1MUmVzdWx0LnN1Y2Nlc3MoY3JlYXRlV3JhcHBlcih0aGlzLCBodG1sKSwgYmJveCk7CiAgICBpZiAodGhpcy5icmVha0FmdGVyLmNoaWxkcmVuLmxlbmd0aCA+PSAxKSB7CiAgICAgIGNvbnN0IGJyZWFrQWZ0ZXIgPSB0aGlzLmJyZWFrQWZ0ZXIuY2hpbGRyZW5bMF07CiAgICAgIGlmIChoYW5kbGVCcmVhayhicmVha0FmdGVyKSkgewogICAgICAgIHRoaXNbJGV4dHJhXS5hZnRlckJyZWFrQWZ0ZXIgPSByZXN1bHQ7CiAgICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuYnJlYWtOb2RlKGJyZWFrQWZ0ZXIpOwogICAgICB9CiAgICB9CiAgICBkZWxldGUgdGhpc1skZXh0cmFdOwogICAgcmV0dXJuIHJlc3VsdDsKICB9Cn0KY2xhc3MgU3ViZm9ybVNldCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzdWJmb3JtU2V0IiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucmVsYXRpb24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5yZWxhdGlvbiwgWyJvcmRlcmVkIiwgImNob2ljZSIsICJ1bm9yZGVyZWQiXSk7CiAgICB0aGlzLnJlbGV2YW50ID0gZ2V0UmVsZXZhbnQoYXR0cmlidXRlcy5yZWxldmFudCk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib29rZW5kID0gbnVsbDsKICAgIHRoaXMuYnJlYWsgPSBudWxsOwogICAgdGhpcy5kZXNjID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMub2NjdXIgPSBudWxsOwogICAgdGhpcy5vdmVyZmxvdyA9IG51bGw7CiAgICB0aGlzLmJyZWFrQWZ0ZXIgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYnJlYWtCZWZvcmUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViZm9ybSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJmb3JtU2V0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQogICpbJGdldENvbnRhaW5lZENoaWxkcmVuXSgpIHsKICAgIHlpZWxkKiBnZXRDb250YWluZWRDaGlsZHJlbih0aGlzKTsKICB9CiAgWyRnZXRTdWJmb3JtUGFyZW50XSgpIHsKICAgIGxldCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICB3aGlsZSAoIShwYXJlbnQgaW5zdGFuY2VvZiBTdWJmb3JtKSkgewogICAgICBwYXJlbnQgPSBwYXJlbnRbJGdldFBhcmVudF0oKTsKICAgIH0KICAgIHJldHVybiBwYXJlbnQ7CiAgfQogIFskaXNCaW5kYWJsZV0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KY2xhc3MgU3ViamVjdEROIGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzdWJqZWN0RE4iKTsKICAgIHRoaXMuZGVsaW1pdGVyID0gYXR0cmlidXRlcy5kZWxpbWl0ZXIgfHwgIiwiOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbJGNvbnRlbnRdID0gbmV3IE1hcCh0aGlzWyRjb250ZW50XS5zcGxpdCh0aGlzLmRlbGltaXRlcikubWFwKGt2ID0+IHsKICAgICAga3YgPSBrdi5zcGxpdCgiPSIsIDIpOwogICAgICBrdlswXSA9IGt2WzBdLnRyaW0oKTsKICAgICAgcmV0dXJuIGt2OwogICAgfSkpOwogIH0KfQpjbGFzcyBTdWJqZWN0RE5zIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInN1YmplY3RETnMiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnN1YmplY3RETiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBTdWJtaXQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAic3VibWl0IiwgdHJ1ZSk7CiAgICB0aGlzLmVtYmVkUERGID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZW1iZWRQREYsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmZvcm1hdCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmZvcm1hdCwgWyJ4ZHAiLCAiZm9ybWRhdGEiLCAicGRmIiwgInVybGVuY29kZWQiLCAieGZkIiwgInhtbCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50YXJnZXQgPSBhdHRyaWJ1dGVzLnRhcmdldCB8fCAiIjsKICAgIHRoaXMudGV4dEVuY29kaW5nID0gZ2V0S2V5d29yZCh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMudGV4dEVuY29kaW5nID8gYXR0cmlidXRlcy50ZXh0RW5jb2RpbmcudG9Mb3dlckNhc2UoKSA6ICIiLAogICAgICBkZWZhdWx0VmFsdWU6ICIiLAogICAgICB2YWxpZGF0ZTogayA9PiBbInV0Zi04IiwgImJpZy1maXZlIiwgImZvbnRzcGVjaWZpYyIsICJnYmsiLCAiZ2ItMTgwMzAiLCAiZ2ItMjMxMiIsICJrc2MtNTYwMSIsICJub25lIiwgInNoaWZ0LWppcyIsICJ1Y3MtMiIsICJ1dGYtMTYiXS5pbmNsdWRlcyhrKSB8fCBrLm1hdGNoKC9pc28tODg1OS1cZHsyfS8pCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnhkcENvbnRlbnQgPSBhdHRyaWJ1dGVzLnhkcENvbnRlbnQgfHwgIiI7CiAgICB0aGlzLmVuY3J5cHQgPSBudWxsOwogICAgdGhpcy5lbmNyeXB0RGF0YSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zaWduRGF0YSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBUZW1wbGF0ZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0ZW1wbGF0ZSIsIHRydWUpOwogICAgdGhpcy5iYXNlUHJvZmlsZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmJhc2VQcm9maWxlLCBbImZ1bGwiLCAiaW50ZXJhY3RpdmVGb3JtcyJdKTsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuc3ViZm9ybSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIGlmICh0aGlzLnN1YmZvcm0uY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7CiAgICAgIHdhcm4oIlhGQSAtIE5vIHN1YmZvcm1zIGluIHRlbXBsYXRlIG5vZGUuIik7CiAgICB9CiAgICBpZiAodGhpcy5zdWJmb3JtLmNoaWxkcmVuLmxlbmd0aCA+PSAyKSB7CiAgICAgIHdhcm4oIlhGQSAtIFNldmVyYWwgc3ViZm9ybXMgaW4gdGVtcGxhdGUgbm9kZTogcGxlYXNlIGZpbGUgYSBidWcuIik7CiAgICB9CiAgICB0aGlzWyR0YWJJbmRleF0gPSBERUZBVUxUX1RBQl9JTkRFWDsKICB9CiAgWyRpc1NwbGl0dGFibGVdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIFskc2VhcmNoTm9kZV0oZXhwciwgY29udGFpbmVyKSB7CiAgICBpZiAoZXhwci5zdGFydHNXaXRoKCIjIikpIHsKICAgICAgcmV0dXJuIFt0aGlzWyRpZHNdLmdldChleHByLnNsaWNlKDEpKV07CiAgICB9CiAgICByZXR1cm4gc2VhcmNoTm9kZSh0aGlzLCBjb250YWluZXIsIGV4cHIsIHRydWUsIHRydWUpOwogIH0KICAqWyR0b1BhZ2VzXSgpIHsKICAgIGlmICghdGhpcy5zdWJmb3JtLmNoaWxkcmVuLmxlbmd0aCkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgICBuYW1lOiAiZGl2IiwKICAgICAgICBjaGlsZHJlbjogW10KICAgICAgfSk7CiAgICB9CiAgICB0aGlzWyRleHRyYV0gPSB7CiAgICAgIG92ZXJmbG93Tm9kZTogbnVsbCwKICAgICAgZmlyc3RVbnNwbGl0dGFibGU6IG51bGwsCiAgICAgIGN1cnJlbnRDb250ZW50QXJlYTogbnVsbCwKICAgICAgY3VycmVudFBhZ2VBcmVhOiBudWxsLAogICAgICBub0xheW91dEZhaWx1cmU6IGZhbHNlLAogICAgICBwYWdlTnVtYmVyOiAxLAogICAgICBwYWdlUG9zaXRpb246ICJmaXJzdCIsCiAgICAgIG9kZE9yRXZlbjogIm9kZCIsCiAgICAgIGJsYW5rT3JOb3RCbGFuazogIm5vbkJsYW5rIiwKICAgICAgcGFyYVN0YWNrOiBbXQogICAgfTsKICAgIGNvbnN0IHJvb3QgPSB0aGlzLnN1YmZvcm0uY2hpbGRyZW5bMF07CiAgICByb290LnBhZ2VTZXRbJGNsZWFuUGFnZV0oKTsKICAgIGNvbnN0IHBhZ2VBcmVhcyA9IHJvb3QucGFnZVNldC5wYWdlQXJlYS5jaGlsZHJlbjsKICAgIGNvbnN0IG1haW5IdG1sID0gewogICAgICBuYW1lOiAiZGl2IiwKICAgICAgY2hpbGRyZW46IFtdCiAgICB9OwogICAgbGV0IHBhZ2VBcmVhID0gbnVsbDsKICAgIGxldCBicmVha0JlZm9yZSA9IG51bGw7CiAgICBsZXQgYnJlYWtCZWZvcmVUYXJnZXQgPSBudWxsOwogICAgaWYgKHJvb3QuYnJlYWtCZWZvcmUuY2hpbGRyZW4ubGVuZ3RoID49IDEpIHsKICAgICAgYnJlYWtCZWZvcmUgPSByb290LmJyZWFrQmVmb3JlLmNoaWxkcmVuWzBdOwogICAgICBicmVha0JlZm9yZVRhcmdldCA9IGJyZWFrQmVmb3JlLnRhcmdldDsKICAgIH0gZWxzZSBpZiAocm9vdC5zdWJmb3JtLmNoaWxkcmVuLmxlbmd0aCA+PSAxICYmIHJvb3Quc3ViZm9ybS5jaGlsZHJlblswXS5icmVha0JlZm9yZS5jaGlsZHJlbi5sZW5ndGggPj0gMSkgewogICAgICBicmVha0JlZm9yZSA9IHJvb3Quc3ViZm9ybS5jaGlsZHJlblswXS5icmVha0JlZm9yZS5jaGlsZHJlblswXTsKICAgICAgYnJlYWtCZWZvcmVUYXJnZXQgPSBicmVha0JlZm9yZS50YXJnZXQ7CiAgICB9IGVsc2UgaWYgKHJvb3QuYnJlYWs/LmJlZm9yZVRhcmdldCkgewogICAgICBicmVha0JlZm9yZSA9IHJvb3QuYnJlYWs7CiAgICAgIGJyZWFrQmVmb3JlVGFyZ2V0ID0gYnJlYWtCZWZvcmUuYmVmb3JlVGFyZ2V0OwogICAgfSBlbHNlIGlmIChyb290LnN1YmZvcm0uY2hpbGRyZW4ubGVuZ3RoID49IDEgJiYgcm9vdC5zdWJmb3JtLmNoaWxkcmVuWzBdLmJyZWFrPy5iZWZvcmVUYXJnZXQpIHsKICAgICAgYnJlYWtCZWZvcmUgPSByb290LnN1YmZvcm0uY2hpbGRyZW5bMF0uYnJlYWs7CiAgICAgIGJyZWFrQmVmb3JlVGFyZ2V0ID0gYnJlYWtCZWZvcmUuYmVmb3JlVGFyZ2V0OwogICAgfQogICAgaWYgKGJyZWFrQmVmb3JlKSB7CiAgICAgIGNvbnN0IHRhcmdldCA9IHRoaXNbJHNlYXJjaE5vZGVdKGJyZWFrQmVmb3JlVGFyZ2V0LCBicmVha0JlZm9yZVskZ2V0UGFyZW50XSgpKTsKICAgICAgaWYgKHRhcmdldCBpbnN0YW5jZW9mIFBhZ2VBcmVhKSB7CiAgICAgICAgcGFnZUFyZWEgPSB0YXJnZXQ7CiAgICAgICAgYnJlYWtCZWZvcmVbJGV4dHJhXSA9IHt9OwogICAgICB9CiAgICB9CiAgICBwYWdlQXJlYSB8fD0gcGFnZUFyZWFzWzBdOwogICAgcGFnZUFyZWFbJGV4dHJhXSA9IHsKICAgICAgbnVtYmVyT2ZVc2U6IDEKICAgIH07CiAgICBjb25zdCBwYWdlQXJlYVBhcmVudCA9IHBhZ2VBcmVhWyRnZXRQYXJlbnRdKCk7CiAgICBwYWdlQXJlYVBhcmVudFskZXh0cmFdID0gewogICAgICBudW1iZXJPZlVzZTogMSwKICAgICAgcGFnZUluZGV4OiBwYWdlQXJlYVBhcmVudC5wYWdlQXJlYS5jaGlsZHJlbi5pbmRleE9mKHBhZ2VBcmVhKSwKICAgICAgcGFnZVNldEluZGV4OiAwCiAgICB9OwogICAgbGV0IHRhcmdldFBhZ2VBcmVhOwogICAgbGV0IGxlYWRlciA9IG51bGw7CiAgICBsZXQgdHJhaWxlciA9IG51bGw7CiAgICBsZXQgaGFzU29tZXRoaW5nID0gdHJ1ZTsKICAgIGxldCBoYXNTb21ldGhpbmdDb3VudGVyID0gMDsKICAgIGxldCBzdGFydEluZGV4ID0gMDsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGlmICghaGFzU29tZXRoaW5nKSB7CiAgICAgICAgbWFpbkh0bWwuY2hpbGRyZW4ucG9wKCk7CiAgICAgICAgaWYgKCsraGFzU29tZXRoaW5nQ291bnRlciA9PT0gTUFYX0VNUFRZX1BBR0VTKSB7CiAgICAgICAgICB3YXJuKCJYRkEgLSBTb21ldGhpbmcgZ29lcyB3cm9uZzogcGxlYXNlIGZpbGUgYSBidWcuIik7CiAgICAgICAgICByZXR1cm4gbWFpbkh0bWw7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGhhc1NvbWV0aGluZ0NvdW50ZXIgPSAwOwogICAgICB9CiAgICAgIHRhcmdldFBhZ2VBcmVhID0gbnVsbDsKICAgICAgdGhpc1skZXh0cmFdLmN1cnJlbnRQYWdlQXJlYSA9IHBhZ2VBcmVhOwogICAgICBjb25zdCBwYWdlID0gcGFnZUFyZWFbJHRvSFRNTF0oKS5odG1sOwogICAgICBtYWluSHRtbC5jaGlsZHJlbi5wdXNoKHBhZ2UpOwogICAgICBpZiAobGVhZGVyKSB7CiAgICAgICAgdGhpc1skZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSA9IHRydWU7CiAgICAgICAgcGFnZS5jaGlsZHJlbi5wdXNoKGxlYWRlclskdG9IVE1MXShwYWdlQXJlYVskZXh0cmFdLnNwYWNlKS5odG1sKTsKICAgICAgICBsZWFkZXIgPSBudWxsOwogICAgICB9CiAgICAgIGlmICh0cmFpbGVyKSB7CiAgICAgICAgdGhpc1skZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSA9IHRydWU7CiAgICAgICAgcGFnZS5jaGlsZHJlbi5wdXNoKHRyYWlsZXJbJHRvSFRNTF0ocGFnZUFyZWFbJGV4dHJhXS5zcGFjZSkuaHRtbCk7CiAgICAgICAgdHJhaWxlciA9IG51bGw7CiAgICAgIH0KICAgICAgY29uc3QgY29udGVudEFyZWFzID0gcGFnZUFyZWEuY29udGVudEFyZWEuY2hpbGRyZW47CiAgICAgIGNvbnN0IGh0bWxDb250ZW50QXJlYXMgPSBwYWdlLmNoaWxkcmVuLmZpbHRlcihub2RlID0+IG5vZGUuYXR0cmlidXRlcy5jbGFzcy5pbmNsdWRlcygieGZhQ29udGVudGFyZWEiKSk7CiAgICAgIGhhc1NvbWV0aGluZyA9IGZhbHNlOwogICAgICB0aGlzWyRleHRyYV0uZmlyc3RVbnNwbGl0dGFibGUgPSBudWxsOwogICAgICB0aGlzWyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlID0gZmFsc2U7CiAgICAgIGNvbnN0IGZsdXNoID0gaW5kZXggPT4gewogICAgICAgIGNvbnN0IGh0bWwgPSByb290WyRmbHVzaEhUTUxdKCk7CiAgICAgICAgaWYgKGh0bWwpIHsKICAgICAgICAgIGhhc1NvbWV0aGluZyB8fD0gaHRtbC5jaGlsZHJlbj8ubGVuZ3RoID4gMDsKICAgICAgICAgIGh0bWxDb250ZW50QXJlYXNbaW5kZXhdLmNoaWxkcmVuLnB1c2goaHRtbCk7CiAgICAgICAgfQogICAgICB9OwogICAgICBmb3IgKGxldCBpID0gc3RhcnRJbmRleCwgaWkgPSBjb250ZW50QXJlYXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IGNvbnRlbnRBcmVhID0gdGhpc1skZXh0cmFdLmN1cnJlbnRDb250ZW50QXJlYSA9IGNvbnRlbnRBcmVhc1tpXTsKICAgICAgICBjb25zdCBzcGFjZSA9IHsKICAgICAgICAgIHdpZHRoOiBjb250ZW50QXJlYS53LAogICAgICAgICAgaGVpZ2h0OiBjb250ZW50QXJlYS5oCiAgICAgICAgfTsKICAgICAgICBzdGFydEluZGV4ID0gMDsKICAgICAgICBpZiAobGVhZGVyKSB7CiAgICAgICAgICBodG1sQ29udGVudEFyZWFzW2ldLmNoaWxkcmVuLnB1c2gobGVhZGVyWyR0b0hUTUxdKHNwYWNlKS5odG1sKTsKICAgICAgICAgIGxlYWRlciA9IG51bGw7CiAgICAgICAgfQogICAgICAgIGlmICh0cmFpbGVyKSB7CiAgICAgICAgICBodG1sQ29udGVudEFyZWFzW2ldLmNoaWxkcmVuLnB1c2godHJhaWxlclskdG9IVE1MXShzcGFjZSkuaHRtbCk7CiAgICAgICAgICB0cmFpbGVyID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgY29uc3QgaHRtbCA9IHJvb3RbJHRvSFRNTF0oc3BhY2UpOwogICAgICAgIGlmIChodG1sLnN1Y2Nlc3MpIHsKICAgICAgICAgIGlmIChodG1sLmh0bWwpIHsKICAgICAgICAgICAgaGFzU29tZXRoaW5nIHx8PSBodG1sLmh0bWwuY2hpbGRyZW4/Lmxlbmd0aCA+IDA7CiAgICAgICAgICAgIGh0bWxDb250ZW50QXJlYXNbaV0uY2hpbGRyZW4ucHVzaChodG1sLmh0bWwpOwogICAgICAgICAgfSBlbHNlIGlmICghaGFzU29tZXRoaW5nICYmIG1haW5IdG1sLmNoaWxkcmVuLmxlbmd0aCA+IDEpIHsKICAgICAgICAgICAgbWFpbkh0bWwuY2hpbGRyZW4ucG9wKCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gbWFpbkh0bWw7CiAgICAgICAgfQogICAgICAgIGlmIChodG1sLmlzQnJlYWsoKSkgewogICAgICAgICAgY29uc3Qgbm9kZSA9IGh0bWwuYnJlYWtOb2RlOwogICAgICAgICAgZmx1c2goaSk7CiAgICAgICAgICBpZiAobm9kZS50YXJnZXRUeXBlID09PSAiYXV0byIpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobm9kZS5sZWFkZXIpIHsKICAgICAgICAgICAgbGVhZGVyID0gdGhpc1skc2VhcmNoTm9kZV0obm9kZS5sZWFkZXIsIG5vZGVbJGdldFBhcmVudF0oKSk7CiAgICAgICAgICAgIGxlYWRlciA9IGxlYWRlciA/IGxlYWRlclswXSA6IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobm9kZS50cmFpbGVyKSB7CiAgICAgICAgICAgIHRyYWlsZXIgPSB0aGlzWyRzZWFyY2hOb2RlXShub2RlLnRyYWlsZXIsIG5vZGVbJGdldFBhcmVudF0oKSk7CiAgICAgICAgICAgIHRyYWlsZXIgPSB0cmFpbGVyID8gdHJhaWxlclswXSA6IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobm9kZS50YXJnZXRUeXBlID09PSAicGFnZUFyZWEiKSB7CiAgICAgICAgICAgIHRhcmdldFBhZ2VBcmVhID0gbm9kZVskZXh0cmFdLnRhcmdldDsKICAgICAgICAgICAgaSA9IEluZmluaXR5OwogICAgICAgICAgfSBlbHNlIGlmICghbm9kZVskZXh0cmFdLnRhcmdldCkgewogICAgICAgICAgICBpID0gbm9kZVskZXh0cmFdLmluZGV4OwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGFyZ2V0UGFnZUFyZWEgPSBub2RlWyRleHRyYV0udGFyZ2V0OwogICAgICAgICAgICBzdGFydEluZGV4ID0gbm9kZVskZXh0cmFdLmluZGV4ICsgMTsKICAgICAgICAgICAgaSA9IEluZmluaXR5OwogICAgICAgICAgfQogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICh0aGlzWyRleHRyYV0ub3ZlcmZsb3dOb2RlKSB7CiAgICAgICAgICBjb25zdCBub2RlID0gdGhpc1skZXh0cmFdLm92ZXJmbG93Tm9kZTsKICAgICAgICAgIHRoaXNbJGV4dHJhXS5vdmVyZmxvd05vZGUgPSBudWxsOwogICAgICAgICAgY29uc3Qgb3ZlcmZsb3dFeHRyYSA9IG5vZGVbJGdldEV4dHJhXSgpOwogICAgICAgICAgY29uc3QgdGFyZ2V0ID0gb3ZlcmZsb3dFeHRyYS50YXJnZXQ7CiAgICAgICAgICBvdmVyZmxvd0V4dHJhLmFkZExlYWRlciA9IG92ZXJmbG93RXh0cmEubGVhZGVyICE9PSBudWxsOwogICAgICAgICAgb3ZlcmZsb3dFeHRyYS5hZGRUcmFpbGVyID0gb3ZlcmZsb3dFeHRyYS50cmFpbGVyICE9PSBudWxsOwogICAgICAgICAgZmx1c2goaSk7CiAgICAgICAgICBjb25zdCBjdXJyZW50SW5kZXggPSBpOwogICAgICAgICAgaSA9IEluZmluaXR5OwogICAgICAgICAgaWYgKHRhcmdldCBpbnN0YW5jZW9mIFBhZ2VBcmVhKSB7CiAgICAgICAgICAgIHRhcmdldFBhZ2VBcmVhID0gdGFyZ2V0OwogICAgICAgICAgfSBlbHNlIGlmICh0YXJnZXQgaW5zdGFuY2VvZiBDb250ZW50QXJlYSkgewogICAgICAgICAgICBjb25zdCBpbmRleCA9IGNvbnRlbnRBcmVhcy5pbmRleE9mKHRhcmdldCk7CiAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgICAgICAgICBpZiAoaW5kZXggPiBjdXJyZW50SW5kZXgpIHsKICAgICAgICAgICAgICAgIGkgPSBpbmRleCAtIDE7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHN0YXJ0SW5kZXggPSBpbmRleDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdGFyZ2V0UGFnZUFyZWEgPSB0YXJnZXRbJGdldFBhcmVudF0oKTsKICAgICAgICAgICAgICBzdGFydEluZGV4ID0gdGFyZ2V0UGFnZUFyZWEuY29udGVudEFyZWEuY2hpbGRyZW4uaW5kZXhPZih0YXJnZXQpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgZmx1c2goaSk7CiAgICAgIH0KICAgICAgdGhpc1skZXh0cmFdLnBhZ2VOdW1iZXIgKz0gMTsKICAgICAgaWYgKHRhcmdldFBhZ2VBcmVhKSB7CiAgICAgICAgaWYgKHRhcmdldFBhZ2VBcmVhWyRpc1VzYWJsZV0oKSkgewogICAgICAgICAgdGFyZ2V0UGFnZUFyZWFbJGV4dHJhXS5udW1iZXJPZlVzZSArPSAxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0YXJnZXRQYWdlQXJlYSA9IG51bGw7CiAgICAgICAgfQogICAgICB9CiAgICAgIHBhZ2VBcmVhID0gdGFyZ2V0UGFnZUFyZWEgfHwgcGFnZUFyZWFbJGdldE5leHRQYWdlXSgpOwogICAgICB5aWVsZCBudWxsOwogICAgfQogIH0KfQpjbGFzcyBUZXh0IGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0ZXh0Iik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubWF4Q2hhcnMgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5tYXhDaGFycywKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yaWQgPSBhdHRyaWJ1dGVzLnJpZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFskYWNjZXB0V2hpdGVzcGFjZV0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgWyRvbkNoaWxkXShjaGlsZCkgewogICAgaWYgKGNoaWxkWyRuYW1lc3BhY2VJZF0gPT09IE5hbWVzcGFjZUlkcy54aHRtbC5pZCkgewogICAgICB0aGlzWyRjb250ZW50XSA9IGNoaWxkOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHdhcm4oYFhGQSAtIEludmFsaWQgY29udGVudCBpbiBUZXh0OiAke2NoaWxkWyRub2RlTmFtZV19LmApOwogICAgcmV0dXJuIGZhbHNlOwogIH0KICBbJG9uVGV4dF0oc3RyKSB7CiAgICBpZiAodGhpc1skY29udGVudF0gaW5zdGFuY2VvZiBYRkFPYmplY3QpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgc3VwZXJbJG9uVGV4dF0oc3RyKTsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICBpZiAodHlwZW9mIHRoaXNbJGNvbnRlbnRdID09PSAic3RyaW5nIikgewogICAgICB0aGlzWyRjb250ZW50XSA9IHRoaXNbJGNvbnRlbnRdLnJlcGxhY2VBbGwoIlxyXG4iLCAiXG4iKTsKICAgIH0KICB9CiAgWyRnZXRFeHRyYV0oKSB7CiAgICBpZiAodHlwZW9mIHRoaXNbJGNvbnRlbnRdID09PSAic3RyaW5nIikgewogICAgICByZXR1cm4gdGhpc1skY29udGVudF0uc3BsaXQoL1tcdTIwMjlcdTIwMjhcbl0vKS5maWx0ZXIobGluZSA9PiAhIWxpbmUpLmpvaW4oIlxuIik7CiAgICB9CiAgICByZXR1cm4gdGhpc1skY29udGVudF1bJHRleHRdKCk7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgaWYgKHR5cGVvZiB0aGlzWyRjb250ZW50XSA9PT0gInN0cmluZyIpIHsKICAgICAgY29uc3QgaHRtbCA9IHZhbHVlVG9IdG1sKHRoaXNbJGNvbnRlbnRdKS5odG1sOwogICAgICBpZiAodGhpc1skY29udGVudF0uaW5jbHVkZXMoIlx1MjAyOSIpKSB7CiAgICAgICAgaHRtbC5uYW1lID0gImRpdiI7CiAgICAgICAgaHRtbC5jaGlsZHJlbiA9IFtdOwogICAgICAgIHRoaXNbJGNvbnRlbnRdLnNwbGl0KCJcdTIwMjkiKS5tYXAocGFyYSA9PiBwYXJhLnNwbGl0KC9bXHUyMDI4XG5dLykuZmxhdE1hcChsaW5lID0+IFt7CiAgICAgICAgICBuYW1lOiAic3BhbiIsCiAgICAgICAgICB2YWx1ZTogbGluZQogICAgICAgIH0sIHsKICAgICAgICAgIG5hbWU6ICJiciIKICAgICAgICB9XSkpLmZvckVhY2gobGluZXMgPT4gewogICAgICAgICAgaHRtbC5jaGlsZHJlbi5wdXNoKHsKICAgICAgICAgICAgbmFtZTogInAiLAogICAgICAgICAgICBjaGlsZHJlbjogbGluZXMKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgaWYgKC9bXHUyMDI4XG5dLy50ZXN0KHRoaXNbJGNvbnRlbnRdKSkgewogICAgICAgIGh0bWwubmFtZSA9ICJkaXYiOwogICAgICAgIGh0bWwuY2hpbGRyZW4gPSBbXTsKICAgICAgICB0aGlzWyRjb250ZW50XS5zcGxpdCgvW1x1MjAyOFxuXS8pLmZvckVhY2gobGluZSA9PiB7CiAgICAgICAgICBodG1sLmNoaWxkcmVuLnB1c2goewogICAgICAgICAgICBuYW1lOiAic3BhbiIsCiAgICAgICAgICAgIHZhbHVlOiBsaW5lCiAgICAgICAgICB9LCB7CiAgICAgICAgICAgIG5hbWU6ICJiciIKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICB9CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoaHRtbCk7CiAgICB9CiAgICByZXR1cm4gdGhpc1skY29udGVudF1bJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpOwogIH0KfQpjbGFzcyBUZXh0RWRpdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0ZXh0RWRpdCIsIHRydWUpOwogICAgdGhpcy5hbGxvd1JpY2hUZXh0ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuYWxsb3dSaWNoVGV4dCwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMuaFNjcm9sbFBvbGljeSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmhTY3JvbGxQb2xpY3ksIFsiYXV0byIsICJvZmYiLCAib24iXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubXVsdGlMaW5lID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMubXVsdGlMaW5lLAogICAgICBkZWZhdWx0VmFsdWU6ICIiLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAwIHx8IHggPT09IDEKICAgIH0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMudlNjcm9sbFBvbGljeSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnZTY3JvbGxQb2xpY3ksIFsiYXV0byIsICJvZmYiLCAib24iXSk7CiAgICB0aGlzLmJvcmRlciA9IG51bGw7CiAgICB0aGlzLmNvbWIgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAiYm9yZGVyIiwgImZvbnQiLCAibWFyZ2luIik7CiAgICBsZXQgaHRtbDsKICAgIGNvbnN0IGZpZWxkID0gdGhpc1skZ2V0UGFyZW50XSgpWyRnZXRQYXJlbnRdKCk7CiAgICBpZiAodGhpcy5tdWx0aUxpbmUgPT09ICIiKSB7CiAgICAgIHRoaXMubXVsdGlMaW5lID0gZmllbGQgaW5zdGFuY2VvZiBEcmF3ID8gMSA6IDA7CiAgICB9CiAgICBpZiAodGhpcy5tdWx0aUxpbmUgPT09IDEpIHsKICAgICAgaHRtbCA9IHsKICAgICAgICBuYW1lOiAidGV4dGFyZWEiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIGRhdGFJZDogZmllbGRbJGRhdGFdPy5bJHVpZF0gfHwgZmllbGRbJHVpZF0sCiAgICAgICAgICBmaWVsZElkOiBmaWVsZFskdWlkXSwKICAgICAgICAgIGNsYXNzOiBbInhmYVRleHRmaWVsZCJdLAogICAgICAgICAgc3R5bGUsCiAgICAgICAgICAiYXJpYS1sYWJlbCI6IGFyaWFMYWJlbChmaWVsZCksCiAgICAgICAgICAiYXJpYS1yZXF1aXJlZCI6IGZhbHNlCiAgICAgICAgfQogICAgICB9OwogICAgfSBlbHNlIHsKICAgICAgaHRtbCA9IHsKICAgICAgICBuYW1lOiAiaW5wdXQiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIHR5cGU6ICJ0ZXh0IiwKICAgICAgICAgIGRhdGFJZDogZmllbGRbJGRhdGFdPy5bJHVpZF0gfHwgZmllbGRbJHVpZF0sCiAgICAgICAgICBmaWVsZElkOiBmaWVsZFskdWlkXSwKICAgICAgICAgIGNsYXNzOiBbInhmYVRleHRmaWVsZCJdLAogICAgICAgICAgc3R5bGUsCiAgICAgICAgICAiYXJpYS1sYWJlbCI6IGFyaWFMYWJlbChmaWVsZCksCiAgICAgICAgICAiYXJpYS1yZXF1aXJlZCI6IGZhbHNlCiAgICAgICAgfQogICAgICB9OwogICAgfQogICAgaWYgKGlzUmVxdWlyZWQoZmllbGQpKSB7CiAgICAgIGh0bWwuYXR0cmlidXRlc1siYXJpYS1yZXF1aXJlZCJdID0gdHJ1ZTsKICAgICAgaHRtbC5hdHRyaWJ1dGVzLnJlcXVpcmVkID0gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICBuYW1lOiAibGFiZWwiLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgY2xhc3M6IFsieGZhTGFiZWwiXQogICAgICB9LAogICAgICBjaGlsZHJlbjogW2h0bWxdCiAgICB9KTsKICB9Cn0KY2xhc3MgVGltZSBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0aW1lIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgY29uc3QgZGF0ZSA9IHRoaXNbJGNvbnRlbnRdLnRyaW0oKTsKICAgIHRoaXNbJGNvbnRlbnRdID0gZGF0ZSA/IG5ldyBEYXRlKGRhdGUpIDogbnVsbDsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gdmFsdWVUb0h0bWwodGhpc1skY29udGVudF0gPyB0aGlzWyRjb250ZW50XS50b1N0cmluZygpIDogIiIpOwogIH0KfQpjbGFzcyBUaW1lU3RhbXAgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAidGltZVN0YW1wIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMuc2VydmVyID0gYXR0cmlidXRlcy5zZXJ2ZXIgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgVG9vbFRpcCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0b29sVGlwIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMucmlkID0gYXR0cmlidXRlcy5yaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBUcmF2ZXJzYWwgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAidHJhdmVyc2FsIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLnRyYXZlcnNlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIFRyYXZlcnNlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInRyYXZlcnNlIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMub3BlcmF0aW9uID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMub3BlcmF0aW9uLCBbIm5leHQiLCAiYmFjayIsICJkb3duIiwgImZpcnN0IiwgImxlZnQiLCAicmlnaHQiLCAidXAiXSk7CiAgICB0aGlzLnJlZiA9IGF0dHJpYnV0ZXMucmVmIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuc2NyaXB0ID0gbnVsbDsKICB9CiAgZ2V0IG5hbWUoKSB7CiAgICByZXR1cm4gdGhpcy5vcGVyYXRpb247CiAgfQogIFskaXNUcmFuc3BhcmVudF0oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9CmNsYXNzIFVpIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInVpIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLnBpY3R1cmUgPSBudWxsOwogICAgdGhpcy5iYXJjb2RlID0gbnVsbDsKICAgIHRoaXMuYnV0dG9uID0gbnVsbDsKICAgIHRoaXMuY2hlY2tCdXR0b24gPSBudWxsOwogICAgdGhpcy5jaG9pY2VMaXN0ID0gbnVsbDsKICAgIHRoaXMuZGF0ZVRpbWVFZGl0ID0gbnVsbDsKICAgIHRoaXMuZGVmYXVsdFVpID0gbnVsbDsKICAgIHRoaXMuaW1hZ2VFZGl0ID0gbnVsbDsKICAgIHRoaXMubnVtZXJpY0VkaXQgPSBudWxsOwogICAgdGhpcy5wYXNzd29yZEVkaXQgPSBudWxsOwogICAgdGhpcy5zaWduYXR1cmUgPSBudWxsOwogICAgdGhpcy50ZXh0RWRpdCA9IG51bGw7CiAgfQogIFskZ2V0RXh0cmFdKCkgewogICAgaWYgKHRoaXNbJGV4dHJhXSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSkgewogICAgICAgIGlmIChuYW1lID09PSAiZXh0cmFzIiB8fCBuYW1lID09PSAicGljdHVyZSIpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBvYmogPSB0aGlzW25hbWVdOwogICAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIFhGQU9iamVjdCkpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICB0aGlzWyRleHRyYV0gPSBvYmo7CiAgICAgICAgcmV0dXJuIG9iajsKICAgICAgfQogICAgICB0aGlzWyRleHRyYV0gPSBudWxsOwogICAgfQogICAgcmV0dXJuIHRoaXNbJGV4dHJhXTsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBvYmogPSB0aGlzWyRnZXRFeHRyYV0oKTsKICAgIGlmIChvYmopIHsKICAgICAgcmV0dXJuIG9ialskdG9IVE1MXShhdmFpbGFibGVTcGFjZSk7CiAgICB9CiAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICB9Cn0KY2xhc3MgVmFsaWRhdGUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAidmFsaWRhdGUiLCB0cnVlKTsKICAgIHRoaXMuZm9ybWF0VGVzdCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmZvcm1hdFRlc3QsIFsid2FybmluZyIsICJkaXNhYmxlZCIsICJlcnJvciJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5udWxsVGVzdCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm51bGxUZXN0LCBbImRpc2FibGVkIiwgImVycm9yIiwgIndhcm5pbmciXSk7CiAgICB0aGlzLnNjcmlwdFRlc3QgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5zY3JpcHRUZXN0LCBbImVycm9yIiwgImRpc2FibGVkIiwgIndhcm5pbmciXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tZXNzYWdlID0gbnVsbDsKICAgIHRoaXMucGljdHVyZSA9IG51bGw7CiAgICB0aGlzLnNjcmlwdCA9IG51bGw7CiAgfQp9CmNsYXNzIFZhbHVlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInZhbHVlIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMub3ZlcnJpZGUgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5vdmVycmlkZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMucmVsZXZhbnQgPSBnZXRSZWxldmFudChhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmFyYyA9IG51bGw7CiAgICB0aGlzLmJvb2xlYW4gPSBudWxsOwogICAgdGhpcy5kYXRlID0gbnVsbDsKICAgIHRoaXMuZGF0ZVRpbWUgPSBudWxsOwogICAgdGhpcy5kZWNpbWFsID0gbnVsbDsKICAgIHRoaXMuZXhEYXRhID0gbnVsbDsKICAgIHRoaXMuZmxvYXQgPSBudWxsOwogICAgdGhpcy5pbWFnZSA9IG51bGw7CiAgICB0aGlzLmludGVnZXIgPSBudWxsOwogICAgdGhpcy5saW5lID0gbnVsbDsKICAgIHRoaXMucmVjdGFuZ2xlID0gbnVsbDsKICAgIHRoaXMudGV4dCA9IG51bGw7CiAgICB0aGlzLnRpbWUgPSBudWxsOwogIH0KICBbJHNldFZhbHVlXSh2YWx1ZSkgewogICAgY29uc3QgcGFyZW50ID0gdGhpc1skZ2V0UGFyZW50XSgpOwogICAgaWYgKHBhcmVudCBpbnN0YW5jZW9mIEZpZWxkKSB7CiAgICAgIGlmIChwYXJlbnQudWk/LmltYWdlRWRpdCkgewogICAgICAgIGlmICghdGhpcy5pbWFnZSkgewogICAgICAgICAgdGhpcy5pbWFnZSA9IG5ldyBJbWFnZSh7fSk7CiAgICAgICAgICB0aGlzWyRhcHBlbmRDaGlsZF0odGhpcy5pbWFnZSk7CiAgICAgICAgfQogICAgICAgIHRoaXMuaW1hZ2VbJGNvbnRlbnRdID0gdmFsdWVbJGNvbnRlbnRdOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgfQogICAgY29uc3QgdmFsdWVOYW1lID0gdmFsdWVbJG5vZGVOYW1lXTsKICAgIGlmICh0aGlzW3ZhbHVlTmFtZV0gIT09IG51bGwpIHsKICAgICAgdGhpc1t2YWx1ZU5hbWVdWyRjb250ZW50XSA9IHZhbHVlWyRjb250ZW50XTsKICAgICAgcmV0dXJuOwogICAgfQogICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKSB7CiAgICAgIGNvbnN0IG9iaiA9IHRoaXNbbmFtZV07CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBYRkFPYmplY3QpIHsKICAgICAgICB0aGlzW25hbWVdID0gbnVsbDsKICAgICAgICB0aGlzWyRyZW1vdmVDaGlsZF0ob2JqKTsKICAgICAgfQogICAgfQogICAgdGhpc1t2YWx1ZVskbm9kZU5hbWVdXSA9IHZhbHVlOwogICAgdGhpc1skYXBwZW5kQ2hpbGRdKHZhbHVlKTsKICB9CiAgWyR0ZXh0XSgpIHsKICAgIGlmICh0aGlzLmV4RGF0YSkgewogICAgICBpZiAodHlwZW9mIHRoaXMuZXhEYXRhWyRjb250ZW50XSA9PT0gInN0cmluZyIpIHsKICAgICAgICByZXR1cm4gdGhpcy5leERhdGFbJGNvbnRlbnRdLnRyaW0oKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5leERhdGFbJGNvbnRlbnRdWyR0ZXh0XSgpLnRyaW0oKTsKICAgIH0KICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSkgewogICAgICBpZiAobmFtZSA9PT0gImltYWdlIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IG9iaiA9IHRoaXNbbmFtZV07CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBYRkFPYmplY3QpIHsKICAgICAgICByZXR1cm4gKG9ialskY29udGVudF0gfHwgIiIpLnRvU3RyaW5nKCkudHJpbSgpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykpIHsKICAgICAgY29uc3Qgb2JqID0gdGhpc1tuYW1lXTsKICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgWEZBT2JqZWN0KSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHJldHVybiBvYmpbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpOwogICAgfQogICAgcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7CiAgfQp9CmNsYXNzIFZhcmlhYmxlcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ2YXJpYWJsZXMiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9vbGVhbiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGVUaW1lID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRlY2ltYWwgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXhEYXRhID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmZsb2F0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmltYWdlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmludGVnZXIgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubWFuaWZlc3QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2NyaXB0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KICBbJGlzVHJhbnNwYXJlbnRdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQp9CmNsYXNzIFRlbXBsYXRlTmFtZXNwYWNlIHsKICBzdGF0aWMgWyRidWlsZFhGQU9iamVjdF0obmFtZSwgYXR0cmlidXRlcykgewogICAgaWYgKFRlbXBsYXRlTmFtZXNwYWNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIGNvbnN0IG5vZGUgPSBUZW1wbGF0ZU5hbWVzcGFjZVtuYW1lXShhdHRyaWJ1dGVzKTsKICAgICAgbm9kZVskc2V0U2V0QXR0cmlidXRlc10oYXR0cmlidXRlcyk7CiAgICAgIHJldHVybiBub2RlOwogICAgfQogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9CiAgc3RhdGljIGFwcGVhcmFuY2VGaWx0ZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXBwZWFyYW5jZUZpbHRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBhcmMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXJjKGF0dHJzKTsKICB9CiAgc3RhdGljIGFyZWEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXJlYShhdHRycyk7CiAgfQogIHN0YXRpYyBhc3Npc3QoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXNzaXN0KGF0dHJzKTsKICB9CiAgc3RhdGljIGJhcmNvZGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQmFyY29kZShhdHRycyk7CiAgfQogIHN0YXRpYyBiaW5kKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJpbmQoYXR0cnMpOwogIH0KICBzdGF0aWMgYmluZEl0ZW1zKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJpbmRJdGVtcyhhdHRycyk7CiAgfQogIHN0YXRpYyBib29rZW5kKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJvb2tlbmQoYXR0cnMpOwogIH0KICBzdGF0aWMgYm9vbGVhbihhdHRycykgewogICAgcmV0dXJuIG5ldyBCb29sZWFuRWxlbWVudChhdHRycyk7CiAgfQogIHN0YXRpYyBib3JkZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQm9yZGVyKGF0dHJzKTsKICB9CiAgc3RhdGljIGJyZWFrKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJyZWFrKGF0dHJzKTsKICB9CiAgc3RhdGljIGJyZWFrQWZ0ZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQnJlYWtBZnRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBicmVha0JlZm9yZShhdHRycykgewogICAgcmV0dXJuIG5ldyBCcmVha0JlZm9yZShhdHRycyk7CiAgfQogIHN0YXRpYyBidXR0b24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQnV0dG9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGNhbGN1bGF0ZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDYWxjdWxhdGUoYXR0cnMpOwogIH0KICBzdGF0aWMgY2FwdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBDYXB0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGNlcnRpZmljYXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENlcnRpZmljYXRlKGF0dHJzKTsKICB9CiAgc3RhdGljIGNlcnRpZmljYXRlcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBDZXJ0aWZpY2F0ZXMoYXR0cnMpOwogIH0KICBzdGF0aWMgY2hlY2tCdXR0b24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ2hlY2tCdXR0b24oYXR0cnMpOwogIH0KICBzdGF0aWMgY2hvaWNlTGlzdChhdHRycykgewogICAgcmV0dXJuIG5ldyBDaG9pY2VMaXN0KGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbG9yKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbG9yKGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbWIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tYihhdHRycyk7CiAgfQogIHN0YXRpYyBjb25uZWN0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbm5lY3QoYXR0cnMpOwogIH0KICBzdGF0aWMgY29udGVudEFyZWEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29udGVudEFyZWEoYXR0cnMpOwogIH0KICBzdGF0aWMgY29ybmVyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvcm5lcihhdHRycyk7CiAgfQogIHN0YXRpYyBkYXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGVFbGVtZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIGRhdGVUaW1lKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGVUaW1lKGF0dHJzKTsKICB9CiAgc3RhdGljIGRhdGVUaW1lRWRpdChhdHRycykgewogICAgcmV0dXJuIG5ldyBEYXRlVGltZUVkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVjaW1hbChhdHRycykgewogICAgcmV0dXJuIG5ldyBEZWNpbWFsKGF0dHJzKTsKICB9CiAgc3RhdGljIGRlZmF1bHRVaShhdHRycykgewogICAgcmV0dXJuIG5ldyBEZWZhdWx0VWkoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVzYyhhdHRycykgewogICAgcmV0dXJuIG5ldyBEZXNjKGF0dHJzKTsKICB9CiAgc3RhdGljIGRpZ2VzdE1ldGhvZChhdHRycykgewogICAgcmV0dXJuIG5ldyBEaWdlc3RNZXRob2QoYXR0cnMpOwogIH0KICBzdGF0aWMgZGlnZXN0TWV0aG9kcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBEaWdlc3RNZXRob2RzKGF0dHJzKTsKICB9CiAgc3RhdGljIGRyYXcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRHJhdyhhdHRycyk7CiAgfQogIHN0YXRpYyBlZGdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVkZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jb2RpbmcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRW5jb2RpbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jb2RpbmdzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVuY29kaW5ncyhhdHRycyk7CiAgfQogIHN0YXRpYyBlbmNyeXB0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVuY3J5cHQoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jcnlwdERhdGEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRW5jcnlwdERhdGEoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jcnlwdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBFbmNyeXB0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGVuY3J5cHRpb25NZXRob2QoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRW5jcnlwdGlvbk1ldGhvZChhdHRycyk7CiAgfQogIHN0YXRpYyBlbmNyeXB0aW9uTWV0aG9kcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBFbmNyeXB0aW9uTWV0aG9kcyhhdHRycyk7CiAgfQogIHN0YXRpYyBldmVudChhdHRycykgewogICAgcmV0dXJuIG5ldyBFdmVudChhdHRycyk7CiAgfQogIHN0YXRpYyBleERhdGEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRXhEYXRhKGF0dHJzKTsKICB9CiAgc3RhdGljIGV4T2JqZWN0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEV4T2JqZWN0KGF0dHJzKTsKICB9CiAgc3RhdGljIGV4Y2xHcm91cChhdHRycykgewogICAgcmV0dXJuIG5ldyBFeGNsR3JvdXAoYXR0cnMpOwogIH0KICBzdGF0aWMgZXhlY3V0ZShhdHRycykgewogICAgcmV0dXJuIG5ldyBFeGVjdXRlKGF0dHJzKTsKICB9CiAgc3RhdGljIGV4dHJhcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBFeHRyYXMoYXR0cnMpOwogIH0KICBzdGF0aWMgZmllbGQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRmllbGQoYXR0cnMpOwogIH0KICBzdGF0aWMgZmlsbChhdHRycykgewogICAgcmV0dXJuIG5ldyBGaWxsKGF0dHJzKTsKICB9CiAgc3RhdGljIGZpbHRlcihhdHRycykgewogICAgcmV0dXJuIG5ldyBGaWx0ZXIoYXR0cnMpOwogIH0KICBzdGF0aWMgZmxvYXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRmxvYXQoYXR0cnMpOwogIH0KICBzdGF0aWMgZm9udChhdHRycykgewogICAgcmV0dXJuIG5ldyB0ZW1wbGF0ZV9Gb250KGF0dHJzKTsKICB9CiAgc3RhdGljIGZvcm1hdChhdHRycykgewogICAgcmV0dXJuIG5ldyBGb3JtYXQoYXR0cnMpOwogIH0KICBzdGF0aWMgaGFuZGxlcihhdHRycykgewogICAgcmV0dXJuIG5ldyBIYW5kbGVyKGF0dHJzKTsKICB9CiAgc3RhdGljIGh5cGhlbmF0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEh5cGhlbmF0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGltYWdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEltYWdlKGF0dHJzKTsKICB9CiAgc3RhdGljIGltYWdlRWRpdChhdHRycykgewogICAgcmV0dXJuIG5ldyBJbWFnZUVkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgaW50ZWdlcihhdHRycykgewogICAgcmV0dXJuIG5ldyBJbnRlZ2VyKGF0dHJzKTsKICB9CiAgc3RhdGljIGlzc3VlcnMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgSXNzdWVycyhhdHRycyk7CiAgfQogIHN0YXRpYyBpdGVtcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBJdGVtcyhhdHRycyk7CiAgfQogIHN0YXRpYyBrZWVwKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEtlZXAoYXR0cnMpOwogIH0KICBzdGF0aWMga2V5VXNhZ2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgS2V5VXNhZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgbGluZShhdHRycykgewogICAgcmV0dXJuIG5ldyBMaW5lKGF0dHJzKTsKICB9CiAgc3RhdGljIGxpbmVhcihhdHRycykgewogICAgcmV0dXJuIG5ldyBMaW5lYXIoYXR0cnMpOwogIH0KICBzdGF0aWMgbG9ja0RvY3VtZW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExvY2tEb2N1bWVudChhdHRycyk7CiAgfQogIHN0YXRpYyBtYW5pZmVzdChhdHRycykgewogICAgcmV0dXJuIG5ldyBNYW5pZmVzdChhdHRycyk7CiAgfQogIHN0YXRpYyBtYXJnaW4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTWFyZ2luKGF0dHJzKTsKICB9CiAgc3RhdGljIG1kcChhdHRycykgewogICAgcmV0dXJuIG5ldyBNZHAoYXR0cnMpOwogIH0KICBzdGF0aWMgbWVkaXVtKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1lZGl1bShhdHRycyk7CiAgfQogIHN0YXRpYyBtZXNzYWdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1lc3NhZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgbnVtZXJpY0VkaXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTnVtZXJpY0VkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgb2NjdXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT2NjdXIoYXR0cnMpOwogIH0KICBzdGF0aWMgb2lkKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE9pZChhdHRycyk7CiAgfQogIHN0YXRpYyBvaWRzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE9pZHMoYXR0cnMpOwogIH0KICBzdGF0aWMgb3ZlcmZsb3coYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT3ZlcmZsb3coYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnZUFyZWEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGFnZUFyZWEoYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnZVNldChhdHRycykgewogICAgcmV0dXJuIG5ldyBQYWdlU2V0KGF0dHJzKTsKICB9CiAgc3RhdGljIHBhcmEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGFyYShhdHRycyk7CiAgfQogIHN0YXRpYyBwYXNzd29yZEVkaXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGFzc3dvcmRFZGl0KGF0dHJzKTsKICB9CiAgc3RhdGljIHBhdHRlcm4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgdGVtcGxhdGVfUGF0dGVybihhdHRycyk7CiAgfQogIHN0YXRpYyBwaWN0dXJlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBpY3R1cmUoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJvdG8oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJvdG8oYXR0cnMpOwogIH0KICBzdGF0aWMgcmFkaWFsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFJhZGlhbChhdHRycyk7CiAgfQogIHN0YXRpYyByZWFzb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVhc29uKGF0dHJzKTsKICB9CiAgc3RhdGljIHJlYXNvbnMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVhc29ucyhhdHRycyk7CiAgfQogIHN0YXRpYyByZWN0YW5nbGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVjdGFuZ2xlKGF0dHJzKTsKICB9CiAgc3RhdGljIHJlZihhdHRycykgewogICAgcmV0dXJuIG5ldyBSZWZFbGVtZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHNjcmlwdChhdHRycykgewogICAgcmV0dXJuIG5ldyBTY3JpcHQoYXR0cnMpOwogIH0KICBzdGF0aWMgc2V0UHJvcGVydHkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU2V0UHJvcGVydHkoYXR0cnMpOwogIH0KICBzdGF0aWMgc2lnbkRhdGEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU2lnbkRhdGEoYXR0cnMpOwogIH0KICBzdGF0aWMgc2lnbmF0dXJlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNpZ25hdHVyZShhdHRycyk7CiAgfQogIHN0YXRpYyBzaWduaW5nKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNpZ25pbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgc29saWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU29saWQoYXR0cnMpOwogIH0KICBzdGF0aWMgc3BlYWsoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU3BlYWsoYXR0cnMpOwogIH0KICBzdGF0aWMgc3RpcHBsZShhdHRycykgewogICAgcmV0dXJuIG5ldyBTdGlwcGxlKGF0dHJzKTsKICB9CiAgc3RhdGljIHN1YmZvcm0oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU3ViZm9ybShhdHRycyk7CiAgfQogIHN0YXRpYyBzdWJmb3JtU2V0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1YmZvcm1TZXQoYXR0cnMpOwogIH0KICBzdGF0aWMgc3ViamVjdEROKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1YmplY3RETihhdHRycyk7CiAgfQogIHN0YXRpYyBzdWJqZWN0RE5zKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1YmplY3RETnMoYXR0cnMpOwogIH0KICBzdGF0aWMgc3VibWl0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1Ym1pdChhdHRycyk7CiAgfQogIHN0YXRpYyB0ZW1wbGF0ZShhdHRycykgewogICAgcmV0dXJuIG5ldyBUZW1wbGF0ZShhdHRycyk7CiAgfQogIHN0YXRpYyB0ZXh0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFRleHQoYXR0cnMpOwogIH0KICBzdGF0aWMgdGV4dEVkaXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVGV4dEVkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgdGltZShhdHRycykgewogICAgcmV0dXJuIG5ldyBUaW1lKGF0dHJzKTsKICB9CiAgc3RhdGljIHRpbWVTdGFtcChhdHRycykgewogICAgcmV0dXJuIG5ldyBUaW1lU3RhbXAoYXR0cnMpOwogIH0KICBzdGF0aWMgdG9vbFRpcChhdHRycykgewogICAgcmV0dXJuIG5ldyBUb29sVGlwKGF0dHJzKTsKICB9CiAgc3RhdGljIHRyYXZlcnNhbChhdHRycykgewogICAgcmV0dXJuIG5ldyBUcmF2ZXJzYWwoYXR0cnMpOwogIH0KICBzdGF0aWMgdHJhdmVyc2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVHJhdmVyc2UoYXR0cnMpOwogIH0KICBzdGF0aWMgdWkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVWkoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFsaWRhdGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVmFsaWRhdGUoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFsdWUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVmFsdWUoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFyaWFibGVzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFZhcmlhYmxlcyhhdHRycyk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvYmluZC5qcwoKCgoKCgpjb25zdCBiaW5kX05TX0RBVEFTRVRTID0gTmFtZXNwYWNlSWRzLmRhdGFzZXRzLmlkOwpmdW5jdGlvbiBjcmVhdGVUZXh0KGNvbnRlbnQpIHsKICBjb25zdCBub2RlID0gbmV3IFRleHQoe30pOwogIG5vZGVbJGNvbnRlbnRdID0gY29udGVudDsKICByZXR1cm4gbm9kZTsKfQpjbGFzcyBCaW5kZXIgewogIGNvbnN0cnVjdG9yKHJvb3QpIHsKICAgIHRoaXMucm9vdCA9IHJvb3Q7CiAgICB0aGlzLmRhdGFzZXRzID0gcm9vdC5kYXRhc2V0czsKICAgIHRoaXMuZGF0YSA9IHJvb3QuZGF0YXNldHM/LmRhdGEgfHwgbmV3IFhtbE9iamVjdChOYW1lc3BhY2VJZHMuZGF0YXNldHMuaWQsICJkYXRhIik7CiAgICB0aGlzLmVtcHR5TWVyZ2UgPSB0aGlzLmRhdGFbJGdldENoaWxkcmVuXSgpLmxlbmd0aCA9PT0gMDsKICAgIHRoaXMucm9vdC5mb3JtID0gdGhpcy5mb3JtID0gcm9vdC50ZW1wbGF0ZVskY2xvbmVdKCk7CiAgfQogIF9pc0NvbnN1bWVEYXRhKCkgewogICAgcmV0dXJuICF0aGlzLmVtcHR5TWVyZ2UgJiYgdGhpcy5fbWVyZ2VNb2RlOwogIH0KICBfaXNNYXRjaFRlbXBsYXRlKCkgewogICAgcmV0dXJuICF0aGlzLl9pc0NvbnN1bWVEYXRhKCk7CiAgfQogIGJpbmQoKSB7CiAgICB0aGlzLl9iaW5kRWxlbWVudCh0aGlzLmZvcm0sIHRoaXMuZGF0YSk7CiAgICByZXR1cm4gdGhpcy5mb3JtOwogIH0KICBnZXREYXRhKCkgewogICAgcmV0dXJuIHRoaXMuZGF0YTsKICB9CiAgX2JpbmRWYWx1ZShmb3JtTm9kZSwgZGF0YSwgcGljdHVyZSkgewogICAgZm9ybU5vZGVbJGRhdGFdID0gZGF0YTsKICAgIGlmIChmb3JtTm9kZVskaGFzU2V0dGFibGVWYWx1ZV0oKSkgewogICAgICBpZiAoZGF0YVskaXNEYXRhVmFsdWVdKCkpIHsKICAgICAgICBjb25zdCB2YWx1ZSA9IGRhdGFbJGdldERhdGFWYWx1ZV0oKTsKICAgICAgICBmb3JtTm9kZVskc2V0VmFsdWVdKGNyZWF0ZVRleHQodmFsdWUpKTsKICAgICAgfSBlbHNlIGlmIChmb3JtTm9kZSBpbnN0YW5jZW9mIEZpZWxkICYmIGZvcm1Ob2RlLnVpPy5jaG9pY2VMaXN0Py5vcGVuID09PSAibXVsdGlTZWxlY3QiKSB7CiAgICAgICAgY29uc3QgdmFsdWUgPSBkYXRhWyRnZXRDaGlsZHJlbl0oKS5tYXAoY2hpbGQgPT4gY2hpbGRbJGNvbnRlbnRdLnRyaW0oKSkuam9pbigiXG4iKTsKICAgICAgICBmb3JtTm9kZVskc2V0VmFsdWVdKGNyZWF0ZVRleHQodmFsdWUpKTsKICAgICAgfSBlbHNlIGlmICh0aGlzLl9pc0NvbnN1bWVEYXRhKCkpIHsKICAgICAgICB3YXJuKGBYRkEgLSBOb2RlcyBoYXZlbid0IHRoZSBzYW1lIHR5cGUuYCk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoIWRhdGFbJGlzRGF0YVZhbHVlXSgpIHx8IHRoaXMuX2lzTWF0Y2hUZW1wbGF0ZSgpKSB7CiAgICAgIHRoaXMuX2JpbmRFbGVtZW50KGZvcm1Ob2RlLCBkYXRhKTsKICAgIH0gZWxzZSB7CiAgICAgIHdhcm4oYFhGQSAtIE5vZGVzIGhhdmVuJ3QgdGhlIHNhbWUgdHlwZS5gKTsKICAgIH0KICB9CiAgX2ZpbmREYXRhQnlOYW1lVG9Db25zdW1lKG5hbWUsIGlzVmFsdWUsIGRhdGFOb2RlLCBnbG9iYWwpIHsKICAgIGlmICghbmFtZSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGxldCBnZW5lcmF0b3IsIG1hdGNoOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzOyBpKyspIHsKICAgICAgZ2VuZXJhdG9yID0gZGF0YU5vZGVbJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCBmYWxzZSwgdHJ1ZSk7CiAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgbWF0Y2ggPSBnZW5lcmF0b3IubmV4dCgpLnZhbHVlOwogICAgICAgIGlmICghbWF0Y2gpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAoaXNWYWx1ZSA9PT0gbWF0Y2hbJGlzRGF0YVZhbHVlXSgpKSB7CiAgICAgICAgICByZXR1cm4gbWF0Y2g7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChkYXRhTm9kZVskbmFtZXNwYWNlSWRdID09PSBOYW1lc3BhY2VJZHMuZGF0YXNldHMuaWQgJiYgZGF0YU5vZGVbJG5vZGVOYW1lXSA9PT0gImRhdGEiKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgZGF0YU5vZGUgPSBkYXRhTm9kZVskZ2V0UGFyZW50XSgpOwogICAgfQogICAgaWYgKCFnbG9iYWwpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBnZW5lcmF0b3IgPSB0aGlzLmRhdGFbJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCB0cnVlLCBmYWxzZSk7CiAgICBtYXRjaCA9IGdlbmVyYXRvci5uZXh0KCkudmFsdWU7CiAgICBpZiAobWF0Y2gpIHsKICAgICAgcmV0dXJuIG1hdGNoOwogICAgfQogICAgZ2VuZXJhdG9yID0gdGhpcy5kYXRhWyRnZXRBdHRyaWJ1dGVJdF0obmFtZSwgdHJ1ZSk7CiAgICBtYXRjaCA9IGdlbmVyYXRvci5uZXh0KCkudmFsdWU7CiAgICBpZiAobWF0Y2g/LlskaXNEYXRhVmFsdWVdKCkpIHsKICAgICAgcmV0dXJuIG1hdGNoOwogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogIF9zZXRQcm9wZXJ0aWVzKGZvcm1Ob2RlLCBkYXRhTm9kZSkgewogICAgaWYgKCFmb3JtTm9kZS5oYXNPd25Qcm9wZXJ0eSgic2V0UHJvcGVydHkiKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGNvbnN0IHsKICAgICAgcmVmLAogICAgICB0YXJnZXQsCiAgICAgIGNvbm5lY3Rpb24KICAgIH0gb2YgZm9ybU5vZGUuc2V0UHJvcGVydHkuY2hpbGRyZW4pIHsKICAgICAgaWYgKGNvbm5lY3Rpb24pIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIXJlZikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IG5vZGVzID0gc2VhcmNoTm9kZSh0aGlzLnJvb3QsIGRhdGFOb2RlLCByZWYsIGZhbHNlLCBmYWxzZSk7CiAgICAgIGlmICghbm9kZXMpIHsKICAgICAgICB3YXJuKGBYRkEgLSBJbnZhbGlkIHJlZmVyZW5jZTogJHtyZWZ9LmApOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IFtub2RlXSA9IG5vZGVzOwogICAgICBpZiAoIW5vZGVbJGlzRGVzY2VuZGVudF0odGhpcy5kYXRhKSkgewogICAgICAgIHdhcm4oYFhGQSAtIEludmFsaWQgbm9kZTogbXVzdCBiZSBhIGRhdGEgbm9kZS5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB0YXJnZXROb2RlcyA9IHNlYXJjaE5vZGUodGhpcy5yb290LCBmb3JtTm9kZSwgdGFyZ2V0LCBmYWxzZSwgZmFsc2UpOwogICAgICBpZiAoIXRhcmdldE5vZGVzKSB7CiAgICAgICAgd2FybihgWEZBIC0gSW52YWxpZCB0YXJnZXQ6ICR7dGFyZ2V0fS5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBbdGFyZ2V0Tm9kZV0gPSB0YXJnZXROb2RlczsKICAgICAgaWYgKCF0YXJnZXROb2RlWyRpc0Rlc2NlbmRlbnRdKGZvcm1Ob2RlKSkgewogICAgICAgIHdhcm4oYFhGQSAtIEludmFsaWQgdGFyZ2V0OiBtdXN0IGJlIGEgcHJvcGVydHkgb3Igc3VicHJvcGVydHkuYCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgdGFyZ2V0UGFyZW50ID0gdGFyZ2V0Tm9kZVskZ2V0UGFyZW50XSgpOwogICAgICBpZiAodGFyZ2V0Tm9kZSBpbnN0YW5jZW9mIFNldFByb3BlcnR5IHx8IHRhcmdldFBhcmVudCBpbnN0YW5jZW9mIFNldFByb3BlcnR5KSB7CiAgICAgICAgd2FybihgWEZBIC0gSW52YWxpZCB0YXJnZXQ6IGNhbm5vdCBiZSBhIHNldFByb3BlcnR5IG9yIG9uZSBvZiBpdHMgcHJvcGVydGllcy5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAodGFyZ2V0Tm9kZSBpbnN0YW5jZW9mIEJpbmRJdGVtcyB8fCB0YXJnZXRQYXJlbnQgaW5zdGFuY2VvZiBCaW5kSXRlbXMpIHsKICAgICAgICB3YXJuKGBYRkEgLSBJbnZhbGlkIHRhcmdldDogY2Fubm90IGJlIGEgYmluZEl0ZW1zIG9yIG9uZSBvZiBpdHMgcHJvcGVydGllcy5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBjb250ZW50ID0gbm9kZVskdGV4dF0oKTsKICAgICAgY29uc3QgbmFtZSA9IHRhcmdldE5vZGVbJG5vZGVOYW1lXTsKICAgICAgaWYgKHRhcmdldE5vZGUgaW5zdGFuY2VvZiBYRkFBdHRyaWJ1dGUpIHsKICAgICAgICBjb25zdCBhdHRycyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgYXR0cnNbbmFtZV0gPSBjb250ZW50OwogICAgICAgIGNvbnN0IG9iaiA9IFJlZmxlY3QuY29uc3RydWN0KE9iamVjdC5nZXRQcm90b3R5cGVPZih0YXJnZXRQYXJlbnQpLmNvbnN0cnVjdG9yLCBbYXR0cnNdKTsKICAgICAgICB0YXJnZXRQYXJlbnRbbmFtZV0gPSBvYmpbbmFtZV07CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKCF0YXJnZXROb2RlLmhhc093blByb3BlcnR5KCRjb250ZW50KSkgewogICAgICAgIHdhcm4oYFhGQSAtIEludmFsaWQgbm9kZSB0byB1c2UgaW4gc2V0UHJvcGVydHlgKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICB0YXJnZXROb2RlWyRkYXRhXSA9IG5vZGU7CiAgICAgIHRhcmdldE5vZGVbJGNvbnRlbnRdID0gY29udGVudDsKICAgICAgdGFyZ2V0Tm9kZVskZmluYWxpemVdKCk7CiAgICB9CiAgfQogIF9iaW5kSXRlbXMoZm9ybU5vZGUsIGRhdGFOb2RlKSB7CiAgICBpZiAoIWZvcm1Ob2RlLmhhc093blByb3BlcnR5KCJpdGVtcyIpIHx8ICFmb3JtTm9kZS5oYXNPd25Qcm9wZXJ0eSgiYmluZEl0ZW1zIikgfHwgZm9ybU5vZGUuYmluZEl0ZW1zLmlzRW1wdHkoKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgZm9ybU5vZGUuaXRlbXMuY2hpbGRyZW4pIHsKICAgICAgZm9ybU5vZGVbJHJlbW92ZUNoaWxkXShpdGVtKTsKICAgIH0KICAgIGZvcm1Ob2RlLml0ZW1zLmNsZWFyKCk7CiAgICBjb25zdCBsYWJlbHMgPSBuZXcgSXRlbXMoe30pOwogICAgY29uc3QgdmFsdWVzID0gbmV3IEl0ZW1zKHt9KTsKICAgIGZvcm1Ob2RlWyRhcHBlbmRDaGlsZF0obGFiZWxzKTsKICAgIGZvcm1Ob2RlLml0ZW1zLnB1c2gobGFiZWxzKTsKICAgIGZvcm1Ob2RlWyRhcHBlbmRDaGlsZF0odmFsdWVzKTsKICAgIGZvcm1Ob2RlLml0ZW1zLnB1c2godmFsdWVzKTsKICAgIGZvciAoY29uc3QgewogICAgICByZWYsCiAgICAgIGxhYmVsUmVmLAogICAgICB2YWx1ZVJlZiwKICAgICAgY29ubmVjdGlvbgogICAgfSBvZiBmb3JtTm9kZS5iaW5kSXRlbXMuY2hpbGRyZW4pIHsKICAgICAgaWYgKGNvbm5lY3Rpb24pIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIXJlZikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IG5vZGVzID0gc2VhcmNoTm9kZSh0aGlzLnJvb3QsIGRhdGFOb2RlLCByZWYsIGZhbHNlLCBmYWxzZSk7CiAgICAgIGlmICghbm9kZXMpIHsKICAgICAgICB3YXJuKGBYRkEgLSBJbnZhbGlkIHJlZmVyZW5jZTogJHtyZWZ9LmApOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBub2RlcykgewogICAgICAgIGlmICghbm9kZVskaXNEZXNjZW5kZW50XSh0aGlzLmRhdGFzZXRzKSkgewogICAgICAgICAgd2FybihgWEZBIC0gSW52YWxpZCByZWYgKCR7cmVmfSk6IG11c3QgYmUgYSBkYXRhc2V0cyBjaGlsZC5gKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBsYWJlbE5vZGVzID0gc2VhcmNoTm9kZSh0aGlzLnJvb3QsIG5vZGUsIGxhYmVsUmVmLCB0cnVlLCBmYWxzZSk7CiAgICAgICAgaWYgKCFsYWJlbE5vZGVzKSB7CiAgICAgICAgICB3YXJuKGBYRkEgLSBJbnZhbGlkIGxhYmVsOiAke2xhYmVsUmVmfS5gKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBbbGFiZWxOb2RlXSA9IGxhYmVsTm9kZXM7CiAgICAgICAgaWYgKCFsYWJlbE5vZGVbJGlzRGVzY2VuZGVudF0odGhpcy5kYXRhc2V0cykpIHsKICAgICAgICAgIHdhcm4oYFhGQSAtIEludmFsaWQgbGFiZWw6IG11c3QgYmUgYSBkYXRhc2V0cyBjaGlsZC5gKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCB2YWx1ZU5vZGVzID0gc2VhcmNoTm9kZSh0aGlzLnJvb3QsIG5vZGUsIHZhbHVlUmVmLCB0cnVlLCBmYWxzZSk7CiAgICAgICAgaWYgKCF2YWx1ZU5vZGVzKSB7CiAgICAgICAgICB3YXJuKGBYRkEgLSBJbnZhbGlkIHZhbHVlOiAke3ZhbHVlUmVmfS5gKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBbdmFsdWVOb2RlXSA9IHZhbHVlTm9kZXM7CiAgICAgICAgaWYgKCF2YWx1ZU5vZGVbJGlzRGVzY2VuZGVudF0odGhpcy5kYXRhc2V0cykpIHsKICAgICAgICAgIHdhcm4oYFhGQSAtIEludmFsaWQgdmFsdWU6IG11c3QgYmUgYSBkYXRhc2V0cyBjaGlsZC5gKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBsYWJlbCA9IGNyZWF0ZVRleHQobGFiZWxOb2RlWyR0ZXh0XSgpKTsKICAgICAgICBjb25zdCB2YWx1ZSA9IGNyZWF0ZVRleHQodmFsdWVOb2RlWyR0ZXh0XSgpKTsKICAgICAgICBsYWJlbHNbJGFwcGVuZENoaWxkXShsYWJlbCk7CiAgICAgICAgbGFiZWxzLnRleHQucHVzaChsYWJlbCk7CiAgICAgICAgdmFsdWVzWyRhcHBlbmRDaGlsZF0odmFsdWUpOwogICAgICAgIHZhbHVlcy50ZXh0LnB1c2godmFsdWUpOwogICAgICB9CiAgICB9CiAgfQogIF9iaW5kT2NjdXJyZW5jZXMoZm9ybU5vZGUsIG1hdGNoZXMsIHBpY3R1cmUpIHsKICAgIGxldCBiYXNlQ2xvbmU7CiAgICBpZiAobWF0Y2hlcy5sZW5ndGggPiAxKSB7CiAgICAgIGJhc2VDbG9uZSA9IGZvcm1Ob2RlWyRjbG9uZV0oKTsKICAgICAgYmFzZUNsb25lWyRyZW1vdmVDaGlsZF0oYmFzZUNsb25lLm9jY3VyKTsKICAgICAgYmFzZUNsb25lLm9jY3VyID0gbnVsbDsKICAgIH0KICAgIHRoaXMuX2JpbmRWYWx1ZShmb3JtTm9kZSwgbWF0Y2hlc1swXSwgcGljdHVyZSk7CiAgICB0aGlzLl9zZXRQcm9wZXJ0aWVzKGZvcm1Ob2RlLCBtYXRjaGVzWzBdKTsKICAgIHRoaXMuX2JpbmRJdGVtcyhmb3JtTm9kZSwgbWF0Y2hlc1swXSk7CiAgICBpZiAobWF0Y2hlcy5sZW5ndGggPT09IDEpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgcGFyZW50ID0gZm9ybU5vZGVbJGdldFBhcmVudF0oKTsKICAgIGNvbnN0IG5hbWUgPSBmb3JtTm9kZVskbm9kZU5hbWVdOwogICAgY29uc3QgcG9zID0gcGFyZW50WyRpbmRleE9mXShmb3JtTm9kZSk7CiAgICBmb3IgKGxldCBpID0gMSwgaWkgPSBtYXRjaGVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgbWF0Y2ggPSBtYXRjaGVzW2ldOwogICAgICBjb25zdCBjbG9uZSA9IGJhc2VDbG9uZVskY2xvbmVdKCk7CiAgICAgIHBhcmVudFtuYW1lXS5wdXNoKGNsb25lKTsKICAgICAgcGFyZW50WyRpbnNlcnRBdF0ocG9zICsgaSwgY2xvbmUpOwogICAgICB0aGlzLl9iaW5kVmFsdWUoY2xvbmUsIG1hdGNoLCBwaWN0dXJlKTsKICAgICAgdGhpcy5fc2V0UHJvcGVydGllcyhjbG9uZSwgbWF0Y2gpOwogICAgICB0aGlzLl9iaW5kSXRlbXMoY2xvbmUsIG1hdGNoKTsKICAgIH0KICB9CiAgX2NyZWF0ZU9jY3VycmVuY2VzKGZvcm1Ob2RlKSB7CiAgICBpZiAoIXRoaXMuZW1wdHlNZXJnZSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCB7CiAgICAgIG9jY3VyCiAgICB9ID0gZm9ybU5vZGU7CiAgICBpZiAoIW9jY3VyIHx8IG9jY3VyLmluaXRpYWwgPD0gMSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBwYXJlbnQgPSBmb3JtTm9kZVskZ2V0UGFyZW50XSgpOwogICAgY29uc3QgbmFtZSA9IGZvcm1Ob2RlWyRub2RlTmFtZV07CiAgICBpZiAoIShwYXJlbnRbbmFtZV0gaW5zdGFuY2VvZiBYRkFPYmplY3RBcnJheSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IGN1cnJlbnROdW1iZXI7CiAgICBpZiAoZm9ybU5vZGUubmFtZSkgewogICAgICBjdXJyZW50TnVtYmVyID0gcGFyZW50W25hbWVdLmNoaWxkcmVuLmZpbHRlcihlID0+IGUubmFtZSA9PT0gZm9ybU5vZGUubmFtZSkubGVuZ3RoOwogICAgfSBlbHNlIHsKICAgICAgY3VycmVudE51bWJlciA9IHBhcmVudFtuYW1lXS5jaGlsZHJlbi5sZW5ndGg7CiAgICB9CiAgICBjb25zdCBwb3MgPSBwYXJlbnRbJGluZGV4T2ZdKGZvcm1Ob2RlKSArIDE7CiAgICBjb25zdCBpaSA9IG9jY3VyLmluaXRpYWwgLSBjdXJyZW50TnVtYmVyOwogICAgaWYgKGlpKSB7CiAgICAgIGNvbnN0IG5vZGVDbG9uZSA9IGZvcm1Ob2RlWyRjbG9uZV0oKTsKICAgICAgbm9kZUNsb25lWyRyZW1vdmVDaGlsZF0obm9kZUNsb25lLm9jY3VyKTsKICAgICAgbm9kZUNsb25lLm9jY3VyID0gbnVsbDsKICAgICAgcGFyZW50W25hbWVdLnB1c2gobm9kZUNsb25lKTsKICAgICAgcGFyZW50WyRpbnNlcnRBdF0ocG9zLCBub2RlQ2xvbmUpOwogICAgICBmb3IgKGxldCBpID0gMTsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb25zdCBjbG9uZSA9IG5vZGVDbG9uZVskY2xvbmVdKCk7CiAgICAgICAgcGFyZW50W25hbWVdLnB1c2goY2xvbmUpOwogICAgICAgIHBhcmVudFskaW5zZXJ0QXRdKHBvcyArIGksIGNsb25lKTsKICAgICAgfQogICAgfQogIH0KICBfZ2V0T2NjdXJJbmZvKGZvcm1Ob2RlKSB7CiAgICBjb25zdCB7CiAgICAgIG5hbWUsCiAgICAgIG9jY3VyCiAgICB9ID0gZm9ybU5vZGU7CiAgICBpZiAoIW9jY3VyIHx8ICFuYW1lKSB7CiAgICAgIHJldHVybiBbMSwgMV07CiAgICB9CiAgICBjb25zdCBtYXggPSBvY2N1ci5tYXggPT09IC0xID8gSW5maW5pdHkgOiBvY2N1ci5tYXg7CiAgICByZXR1cm4gW29jY3VyLm1pbiwgbWF4XTsKICB9CiAgX3NldEFuZEJpbmQoZm9ybU5vZGUsIGRhdGFOb2RlKSB7CiAgICB0aGlzLl9zZXRQcm9wZXJ0aWVzKGZvcm1Ob2RlLCBkYXRhTm9kZSk7CiAgICB0aGlzLl9iaW5kSXRlbXMoZm9ybU5vZGUsIGRhdGFOb2RlKTsKICAgIHRoaXMuX2JpbmRFbGVtZW50KGZvcm1Ob2RlLCBkYXRhTm9kZSk7CiAgfQogIF9iaW5kRWxlbWVudChmb3JtTm9kZSwgZGF0YU5vZGUpIHsKICAgIGNvbnN0IHVzZWxlc3NOb2RlcyA9IFtdOwogICAgdGhpcy5fY3JlYXRlT2NjdXJyZW5jZXMoZm9ybU5vZGUpOwogICAgZm9yIChjb25zdCBjaGlsZCBvZiBmb3JtTm9kZVskZ2V0Q2hpbGRyZW5dKCkpIHsKICAgICAgaWYgKGNoaWxkWyRkYXRhXSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICh0aGlzLl9tZXJnZU1vZGUgPT09IHVuZGVmaW5lZCAmJiBjaGlsZFskbm9kZU5hbWVdID09PSAic3ViZm9ybSIpIHsKICAgICAgICB0aGlzLl9tZXJnZU1vZGUgPSBjaGlsZC5tZXJnZU1vZGUgPT09ICJjb25zdW1lRGF0YSI7CiAgICAgICAgY29uc3QgZGF0YUNoaWxkcmVuID0gZGF0YU5vZGVbJGdldENoaWxkcmVuXSgpOwogICAgICAgIGlmIChkYXRhQ2hpbGRyZW4ubGVuZ3RoID4gMCkgewogICAgICAgICAgdGhpcy5fYmluZE9jY3VycmVuY2VzKGNoaWxkLCBbZGF0YUNoaWxkcmVuWzBdXSwgbnVsbCk7CiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmVtcHR5TWVyZ2UpIHsKICAgICAgICAgIGNvbnN0IG5zSWQgPSBkYXRhTm9kZVskbmFtZXNwYWNlSWRdID09PSBiaW5kX05TX0RBVEFTRVRTID8gLTEgOiBkYXRhTm9kZVskbmFtZXNwYWNlSWRdOwogICAgICAgICAgY29uc3QgZGF0YUNoaWxkID0gY2hpbGRbJGRhdGFdID0gbmV3IFhtbE9iamVjdChuc0lkLCBjaGlsZC5uYW1lIHx8ICJyb290Iik7CiAgICAgICAgICBkYXRhTm9kZVskYXBwZW5kQ2hpbGRdKGRhdGFDaGlsZCk7CiAgICAgICAgICB0aGlzLl9iaW5kRWxlbWVudChjaGlsZCwgZGF0YUNoaWxkKTsKICAgICAgICB9CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKCFjaGlsZFskaXNCaW5kYWJsZV0oKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGxldCBnbG9iYWwgPSBmYWxzZTsKICAgICAgbGV0IHBpY3R1cmUgPSBudWxsOwogICAgICBsZXQgcmVmID0gbnVsbDsKICAgICAgbGV0IG1hdGNoID0gbnVsbDsKICAgICAgaWYgKGNoaWxkLmJpbmQpIHsKICAgICAgICBzd2l0Y2ggKGNoaWxkLmJpbmQubWF0Y2gpIHsKICAgICAgICAgIGNhc2UgIm5vbmUiOgogICAgICAgICAgICB0aGlzLl9zZXRBbmRCaW5kKGNoaWxkLCBkYXRhTm9kZSk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgY2FzZSAiZ2xvYmFsIjoKICAgICAgICAgICAgZ2xvYmFsID0gdHJ1ZTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICJkYXRhUmVmIjoKICAgICAgICAgICAgaWYgKCFjaGlsZC5iaW5kLnJlZikgewogICAgICAgICAgICAgIHdhcm4oYFhGQSAtIHJlZiBpcyBlbXB0eSBpbiBub2RlICR7Y2hpbGRbJG5vZGVOYW1lXX0uYCk7CiAgICAgICAgICAgICAgdGhpcy5fc2V0QW5kQmluZChjaGlsZCwgZGF0YU5vZGUpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJlZiA9IGNoaWxkLmJpbmQucmVmOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAoY2hpbGQuYmluZC5waWN0dXJlKSB7CiAgICAgICAgICBwaWN0dXJlID0gY2hpbGQuYmluZC5waWN0dXJlWyRjb250ZW50XTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgW21pbiwgbWF4XSA9IHRoaXMuX2dldE9jY3VySW5mbyhjaGlsZCk7CiAgICAgIGlmIChyZWYpIHsKICAgICAgICBtYXRjaCA9IHNlYXJjaE5vZGUodGhpcy5yb290LCBkYXRhTm9kZSwgcmVmLCB0cnVlLCBmYWxzZSk7CiAgICAgICAgaWYgKG1hdGNoID09PSBudWxsKSB7CiAgICAgICAgICBtYXRjaCA9IGNyZWF0ZURhdGFOb2RlKHRoaXMuZGF0YSwgZGF0YU5vZGUsIHJlZik7CiAgICAgICAgICBpZiAoIW1hdGNoKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHRoaXMuX2lzQ29uc3VtZURhdGEoKSkgewogICAgICAgICAgICBtYXRjaFskY29uc3VtZWRdID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuX3NldEFuZEJpbmQoY2hpbGQsIG1hdGNoKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAodGhpcy5faXNDb25zdW1lRGF0YSgpKSB7CiAgICAgICAgICAgIG1hdGNoID0gbWF0Y2guZmlsdGVyKG5vZGUgPT4gIW5vZGVbJGNvbnN1bWVkXSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gbWF4KSB7CiAgICAgICAgICAgIG1hdGNoID0gbWF0Y2guc2xpY2UoMCwgbWF4KTsKICAgICAgICAgIH0gZWxzZSBpZiAobWF0Y2gubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgIG1hdGNoID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChtYXRjaCAmJiB0aGlzLl9pc0NvbnN1bWVEYXRhKCkpIHsKICAgICAgICAgICAgbWF0Y2guZm9yRWFjaChub2RlID0+IHsKICAgICAgICAgICAgICBub2RlWyRjb25zdW1lZF0gPSB0cnVlOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaWYgKCFjaGlsZC5uYW1lKSB7CiAgICAgICAgICB0aGlzLl9zZXRBbmRCaW5kKGNoaWxkLCBkYXRhTm9kZSk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMuX2lzQ29uc3VtZURhdGEoKSkgewogICAgICAgICAgY29uc3QgbWF0Y2hlcyA9IFtdOwogICAgICAgICAgd2hpbGUgKG1hdGNoZXMubGVuZ3RoIDwgbWF4KSB7CiAgICAgICAgICAgIGNvbnN0IGZvdW5kID0gdGhpcy5fZmluZERhdGFCeU5hbWVUb0NvbnN1bWUoY2hpbGQubmFtZSwgY2hpbGRbJGhhc1NldHRhYmxlVmFsdWVdKCksIGRhdGFOb2RlLCBnbG9iYWwpOwogICAgICAgICAgICBpZiAoIWZvdW5kKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm91bmRbJGNvbnN1bWVkXSA9IHRydWU7CiAgICAgICAgICAgIG1hdGNoZXMucHVzaChmb3VuZCk7CiAgICAgICAgICB9CiAgICAgICAgICBtYXRjaCA9IG1hdGNoZXMubGVuZ3RoID4gMCA/IG1hdGNoZXMgOiBudWxsOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBtYXRjaCA9IGRhdGFOb2RlWyRnZXRSZWFsQ2hpbGRyZW5CeU5hbWVJdF0oY2hpbGQubmFtZSwgZmFsc2UsIHRoaXMuZW1wdHlNZXJnZSkubmV4dCgpLnZhbHVlOwogICAgICAgICAgaWYgKCFtYXRjaCkgewogICAgICAgICAgICBpZiAobWluID09PSAwKSB7CiAgICAgICAgICAgICAgdXNlbGVzc05vZGVzLnB1c2goY2hpbGQpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IG5zSWQgPSBkYXRhTm9kZVskbmFtZXNwYWNlSWRdID09PSBiaW5kX05TX0RBVEFTRVRTID8gLTEgOiBkYXRhTm9kZVskbmFtZXNwYWNlSWRdOwogICAgICAgICAgICBtYXRjaCA9IGNoaWxkWyRkYXRhXSA9IG5ldyBYbWxPYmplY3QobnNJZCwgY2hpbGQubmFtZSk7CiAgICAgICAgICAgIGlmICh0aGlzLmVtcHR5TWVyZ2UpIHsKICAgICAgICAgICAgICBtYXRjaFskY29uc3VtZWRdID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBkYXRhTm9kZVskYXBwZW5kQ2hpbGRdKG1hdGNoKTsKICAgICAgICAgICAgdGhpcy5fc2V0QW5kQmluZChjaGlsZCwgbWF0Y2gpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh0aGlzLmVtcHR5TWVyZ2UpIHsKICAgICAgICAgICAgbWF0Y2hbJGNvbnN1bWVkXSA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICBtYXRjaCA9IFttYXRjaF07CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChtYXRjaCkgewogICAgICAgIHRoaXMuX2JpbmRPY2N1cnJlbmNlcyhjaGlsZCwgbWF0Y2gsIHBpY3R1cmUpOwogICAgICB9IGVsc2UgaWYgKG1pbiA+IDApIHsKICAgICAgICB0aGlzLl9zZXRBbmRCaW5kKGNoaWxkLCBkYXRhTm9kZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdXNlbGVzc05vZGVzLnB1c2goY2hpbGQpOwogICAgICB9CiAgICB9CiAgICB1c2VsZXNzTm9kZXMuZm9yRWFjaChub2RlID0+IG5vZGVbJGdldFBhcmVudF0oKVskcmVtb3ZlQ2hpbGRdKG5vZGUpKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3hmYS9kYXRhLmpzCgpjbGFzcyBEYXRhSGFuZGxlciB7CiAgY29uc3RydWN0b3Iocm9vdCwgZGF0YSkgewogICAgdGhpcy5kYXRhID0gZGF0YTsKICAgIHRoaXMuZGF0YXNldCA9IHJvb3QuZGF0YXNldHMgfHwgbnVsbDsKICB9CiAgc2VyaWFsaXplKHN0b3JhZ2UpIHsKICAgIGNvbnN0IHN0YWNrID0gW1stMSwgdGhpcy5kYXRhWyRnZXRDaGlsZHJlbl0oKV1dOwogICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgbGFzdCA9IHN0YWNrLmF0KC0xKTsKICAgICAgY29uc3QgW2ksIGNoaWxkcmVuXSA9IGxhc3Q7CiAgICAgIGlmIChpICsgMSA9PT0gY2hpbGRyZW4ubGVuZ3RoKSB7CiAgICAgICAgc3RhY2sucG9wKCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgY2hpbGQgPSBjaGlsZHJlblsrK2xhc3RbMF1dOwogICAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBzdG9yYWdlLmdldChjaGlsZFskdWlkXSk7CiAgICAgIGlmIChzdG9yYWdlRW50cnkpIHsKICAgICAgICBjaGlsZFskc2V0VmFsdWVdKHN0b3JhZ2VFbnRyeSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IGNoaWxkWyRnZXRBdHRyaWJ1dGVzXSgpOwogICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgYXR0cmlidXRlcy52YWx1ZXMoKSkgewogICAgICAgICAgY29uc3QgZW50cnkgPSBzdG9yYWdlLmdldCh2YWx1ZVskdWlkXSk7CiAgICAgICAgICBpZiAoZW50cnkpIHsKICAgICAgICAgICAgdmFsdWVbJHNldFZhbHVlXShlbnRyeSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBub2RlcyA9IGNoaWxkWyRnZXRDaGlsZHJlbl0oKTsKICAgICAgaWYgKG5vZGVzLmxlbmd0aCA+IDApIHsKICAgICAgICBzdGFjay5wdXNoKFstMSwgbm9kZXNdKTsKICAgICAgfQogICAgfQogICAgY29uc3QgYnVmID0gW2A8eGZhOmRhdGFzZXRzIHhtbG5zOnhmYT0iaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtZGF0YS8xLjAvIj5gXTsKICAgIGlmICh0aGlzLmRhdGFzZXQpIHsKICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzLmRhdGFzZXRbJGdldENoaWxkcmVuXSgpKSB7CiAgICAgICAgaWYgKGNoaWxkWyRub2RlTmFtZV0gIT09ICJkYXRhIikgewogICAgICAgICAgY2hpbGRbJHRvU3RyaW5nXShidWYpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgdGhpcy5kYXRhWyR0b1N0cmluZ10oYnVmKTsKICAgIGJ1Zi5wdXNoKCI8L3hmYTpkYXRhc2V0cz4iKTsKICAgIHJldHVybiBidWYuam9pbigiIik7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvY29uZmlnLmpzCgoKCgoKY29uc3QgQ09ORklHX05TX0lEID0gTmFtZXNwYWNlSWRzLmNvbmZpZy5pZDsKY2xhc3MgQWNyb2JhdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYWNyb2JhdCIsIHRydWUpOwogICAgdGhpcy5hY3JvYmF0NyA9IG51bGw7CiAgICB0aGlzLmF1dG9TYXZlID0gbnVsbDsKICAgIHRoaXMuY29tbW9uID0gbnVsbDsKICAgIHRoaXMudmFsaWRhdGUgPSBudWxsOwogICAgdGhpcy52YWxpZGF0ZUFwcHJvdmFsU2lnbmF0dXJlcyA9IG51bGw7CiAgICB0aGlzLnN1Ym1pdFVybCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBBY3JvYmF0NyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYWNyb2JhdDciLCB0cnVlKTsKICAgIHRoaXMuZHluYW1pY1JlbmRlciA9IG51bGw7CiAgfQp9CmNsYXNzIEFEQkVfSlNDb25zb2xlIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJBREJFX0pTQ29uc29sZSIsIFsiZGVsZWdhdGUiLCAiRW5hYmxlIiwgIkRpc2FibGUiXSk7CiAgfQp9CmNsYXNzIEFEQkVfSlNEZWJ1Z2dlciBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiQURCRV9KU0RlYnVnZ2VyIiwgWyJkZWxlZ2F0ZSIsICJFbmFibGUiLCAiRGlzYWJsZSJdKTsKICB9Cn0KY2xhc3MgQWRkU2lsZW50UHJpbnQgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYWRkU2lsZW50UHJpbnQiKTsKICB9Cn0KY2xhc3MgQWRkVmlld2VyUHJlZmVyZW5jZXMgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYWRkVmlld2VyUHJlZmVyZW5jZXMiKTsKICB9Cn0KY2xhc3MgQWRqdXN0RGF0YSBleHRlbmRzIE9wdGlvbjEwIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhZGp1c3REYXRhIik7CiAgfQp9CmNsYXNzIEFkb2JlRXh0ZW5zaW9uTGV2ZWwgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhZG9iZUV4dGVuc2lvbkxldmVsIiwgMCwgbiA9PiBuID49IDEgJiYgbiA8PSA4KTsKICB9Cn0KY2xhc3MgQWdlbnQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImFnZW50IiwgdHJ1ZSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgPyBhdHRyaWJ1dGVzLm5hbWUudHJpbSgpIDogIiI7CiAgICB0aGlzLmNvbW1vbiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBBbHdheXNFbWJlZCBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImFsd2F5c0VtYmVkIik7CiAgfQp9CmNsYXNzIEFtZCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYW1kIik7CiAgfQp9CmNsYXNzIGNvbmZpZ19BcmVhIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhcmVhIik7CiAgICB0aGlzLmxldmVsID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMubGV2ZWwsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IG4gPT4gbiA+PSAxICYmIG4gPD0gMwogICAgfSk7CiAgICB0aGlzLm5hbWUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5uYW1lLCBbIiIsICJiYXJjb2RlIiwgImNvcmVpbml0IiwgImRldmljZURyaXZlciIsICJmb250IiwgImdlbmVyYWwiLCAibGF5b3V0IiwgIm1lcmdlIiwgInNjcmlwdCIsICJzaWduYXR1cmUiLCAic291cmNlU2V0IiwgInRlbXBsYXRlQ2FjaGUiXSk7CiAgfQp9CmNsYXNzIEF0dHJpYnV0ZXMgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImF0dHJpYnV0ZXMiLCBbInByZXNlcnZlIiwgImRlbGVnYXRlIiwgImlnbm9yZSJdKTsKICB9Cn0KY2xhc3MgQXV0b1NhdmUgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImF1dG9TYXZlIiwgWyJkaXNhYmxlZCIsICJlbmFibGVkIl0pOwogIH0KfQpjbGFzcyBCYXNlIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJiYXNlIik7CiAgfQp9CmNsYXNzIEJhdGNoT3V0cHV0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJiYXRjaE91dHB1dCIpOwogICAgdGhpcy5mb3JtYXQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5mb3JtYXQsIFsibm9uZSIsICJjb25jYXQiLCAiemlwIiwgInppcENvbXByZXNzIl0pOwogIH0KfQpjbGFzcyBCZWhhdmlvck92ZXJyaWRlIGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYmVoYXZpb3JPdmVycmlkZSIpOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbJGNvbnRlbnRdID0gbmV3IE1hcCh0aGlzWyRjb250ZW50XS50cmltKCkuc3BsaXQoL1xzKy8pLmZpbHRlcih4ID0+IHguaW5jbHVkZXMoIjoiKSkubWFwKHggPT4geC5zcGxpdCgiOiIsIDIpKSk7CiAgfQp9CmNsYXNzIENhY2hlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjYWNoZSIsIHRydWUpOwogICAgdGhpcy50ZW1wbGF0ZUNhY2hlID0gbnVsbDsKICB9Cn0KY2xhc3MgQ2hhbmdlIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImNoYW5nZSIpOwogIH0KfQpjbGFzcyBDb21tb24gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImNvbW1vbiIsIHRydWUpOwogICAgdGhpcy5kYXRhID0gbnVsbDsKICAgIHRoaXMubG9jYWxlID0gbnVsbDsKICAgIHRoaXMubG9jYWxlU2V0ID0gbnVsbDsKICAgIHRoaXMubWVzc2FnaW5nID0gbnVsbDsKICAgIHRoaXMuc3VwcHJlc3NCYW5uZXIgPSBudWxsOwogICAgdGhpcy50ZW1wbGF0ZSA9IG51bGw7CiAgICB0aGlzLnZhbGlkYXRpb25NZXNzYWdpbmcgPSBudWxsOwogICAgdGhpcy52ZXJzaW9uQ29udHJvbCA9IG51bGw7CiAgICB0aGlzLmxvZyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBDb21wcmVzcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiY29tcHJlc3MiKTsKICAgIHRoaXMuc2NvcGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5zY29wZSwgWyJpbWFnZU9ubHkiLCAiZG9jdW1lbnQiXSk7CiAgfQp9CmNsYXNzIENvbXByZXNzTG9naWNhbFN0cnVjdHVyZSBleHRlbmRzIE9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb21wcmVzc0xvZ2ljYWxTdHJ1Y3R1cmUiKTsKICB9Cn0KY2xhc3MgQ29tcHJlc3NPYmplY3RTdHJlYW0gZXh0ZW5kcyBPcHRpb24xMCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiY29tcHJlc3NPYmplY3RTdHJlYW0iKTsKICB9Cn0KY2xhc3MgQ29tcHJlc3Npb24gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImNvbXByZXNzaW9uIiwgdHJ1ZSk7CiAgICB0aGlzLmNvbXByZXNzTG9naWNhbFN0cnVjdHVyZSA9IG51bGw7CiAgICB0aGlzLmNvbXByZXNzT2JqZWN0U3RyZWFtID0gbnVsbDsKICAgIHRoaXMubGV2ZWwgPSBudWxsOwogICAgdGhpcy50eXBlID0gbnVsbDsKICB9Cn0KY2xhc3MgQ29uZmlnIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb25maWciLCB0cnVlKTsKICAgIHRoaXMuYWNyb2JhdCA9IG51bGw7CiAgICB0aGlzLnByZXNlbnQgPSBudWxsOwogICAgdGhpcy50cmFjZSA9IG51bGw7CiAgICB0aGlzLmFnZW50ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIENvbmZvcm1hbmNlIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb25mb3JtYW5jZSIsIFsiQSIsICJCIl0pOwogIH0KfQpjbGFzcyBDb250ZW50Q29weSBleHRlbmRzIE9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb250ZW50Q29weSIpOwogIH0KfQpjbGFzcyBDb3BpZXMgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb3BpZXMiLCAxLCBuID0+IG4gPj0gMSk7CiAgfQp9CmNsYXNzIENyZWF0b3IgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImNyZWF0b3IiKTsKICB9Cn0KY2xhc3MgQ3VycmVudFBhZ2UgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjdXJyZW50UGFnZSIsIDAsIG4gPT4gbiA+PSAwKTsKICB9Cn0KY2xhc3MgRGF0YSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZGF0YSIsIHRydWUpOwogICAgdGhpcy5hZGp1c3REYXRhID0gbnVsbDsKICAgIHRoaXMuYXR0cmlidXRlcyA9IG51bGw7CiAgICB0aGlzLmluY3JlbWVudGFsTG9hZCA9IG51bGw7CiAgICB0aGlzLm91dHB1dFhTTCA9IG51bGw7CiAgICB0aGlzLnJhbmdlID0gbnVsbDsKICAgIHRoaXMucmVjb3JkID0gbnVsbDsKICAgIHRoaXMuc3RhcnROb2RlID0gbnVsbDsKICAgIHRoaXMudXJpID0gbnVsbDsKICAgIHRoaXMud2luZG93ID0gbnVsbDsKICAgIHRoaXMueHNsID0gbnVsbDsKICAgIHRoaXMuZXhjbHVkZU5TID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRyYW5zZm9ybSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBEZWJ1ZyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZGVidWciLCB0cnVlKTsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgRGVmYXVsdFR5cGVmYWNlIGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZGVmYXVsdFR5cGVmYWNlIik7CiAgICB0aGlzLndyaXRpbmdTY3JpcHQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy53cml0aW5nU2NyaXB0LCBbIioiLCAiQXJhYmljIiwgIkN5cmlsbGljIiwgIkVhc3RFdXJvcGVhblJvbWFuIiwgIkdyZWVrIiwgIkhlYnJldyIsICJKYXBhbmVzZSIsICJLb3JlYW4iLCAiUm9tYW4iLCAiU2ltcGxpZmllZENoaW5lc2UiLCAiVGhhaSIsICJUcmFkaXRpb25hbENoaW5lc2UiLCAiVmlldG5hbWVzZSJdKTsKICB9Cn0KY2xhc3MgRGVzdGluYXRpb24gZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImRlc3RpbmF0aW9uIiwgWyJwZGYiLCAicGNsIiwgInBzIiwgIndlYkNsaWVudCIsICJ6cGwiXSk7CiAgfQp9CmNsYXNzIERvY3VtZW50QXNzZW1ibHkgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZG9jdW1lbnRBc3NlbWJseSIpOwogIH0KfQpjbGFzcyBEcml2ZXIgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImRyaXZlciIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lID8gYXR0cmlidXRlcy5uYW1lLnRyaW0oKSA6ICIiOwogICAgdGhpcy5mb250SW5mbyA9IG51bGw7CiAgICB0aGlzLnhkYyA9IG51bGw7CiAgfQp9CmNsYXNzIER1cGxleE9wdGlvbiBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZHVwbGV4T3B0aW9uIiwgWyJzaW1wbGV4IiwgImR1cGxleEZsaXBMb25nRWRnZSIsICJkdXBsZXhGbGlwU2hvcnRFZGdlIl0pOwogIH0KfQpjbGFzcyBEeW5hbWljUmVuZGVyIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJkeW5hbWljUmVuZGVyIiwgWyJmb3JiaWRkZW4iLCAicmVxdWlyZWQiXSk7CiAgfQp9CmNsYXNzIEVtYmVkIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImVtYmVkIik7CiAgfQp9CmNsYXNzIGNvbmZpZ19FbmNyeXB0IGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImVuY3J5cHQiKTsKICB9Cn0KY2xhc3MgY29uZmlnX0VuY3J5cHRpb24gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImVuY3J5cHRpb24iLCB0cnVlKTsKICAgIHRoaXMuZW5jcnlwdCA9IG51bGw7CiAgICB0aGlzLmVuY3J5cHRpb25MZXZlbCA9IG51bGw7CiAgICB0aGlzLnBlcm1pc3Npb25zID0gbnVsbDsKICB9Cn0KY2xhc3MgRW5jcnlwdGlvbkxldmVsIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJlbmNyeXB0aW9uTGV2ZWwiLCBbIjQwYml0IiwgIjEyOGJpdCJdKTsKICB9Cn0KY2xhc3MgRW5mb3JjZSBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZW5mb3JjZSIpOwogIH0KfQpjbGFzcyBFcXVhdGUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImVxdWF0ZSIpOwogICAgdGhpcy5mb3JjZSA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmZvcmNlLAogICAgICBkZWZhdWx0VmFsdWU6IDEsCiAgICAgIHZhbGlkYXRlOiBuID0+IG4gPT09IDAKICAgIH0pOwogICAgdGhpcy5mcm9tID0gYXR0cmlidXRlcy5mcm9tIHx8ICIiOwogICAgdGhpcy50byA9IGF0dHJpYnV0ZXMudG8gfHwgIiI7CiAgfQp9CmNsYXNzIEVxdWF0ZVJhbmdlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJlcXVhdGVSYW5nZSIpOwogICAgdGhpcy5mcm9tID0gYXR0cmlidXRlcy5mcm9tIHx8ICIiOwogICAgdGhpcy50byA9IGF0dHJpYnV0ZXMudG8gfHwgIiI7CiAgICB0aGlzLl91bmljb2RlUmFuZ2UgPSBhdHRyaWJ1dGVzLnVuaWNvZGVSYW5nZSB8fCAiIjsKICB9CiAgZ2V0IHVuaWNvZGVSYW5nZSgpIHsKICAgIGNvbnN0IHJhbmdlcyA9IFtdOwogICAgY29uc3QgdW5pY29kZVJlZ2V4ID0gL1VcKyhbMC05YS1mQS1GXSspLzsKICAgIGNvbnN0IHVuaWNvZGVSYW5nZSA9IHRoaXMuX3VuaWNvZGVSYW5nZTsKICAgIGZvciAobGV0IHJhbmdlIG9mIHVuaWNvZGVSYW5nZS5zcGxpdCgiLCIpLm1hcCh4ID0+IHgudHJpbSgpKS5maWx0ZXIoeCA9PiAhIXgpKSB7CiAgICAgIHJhbmdlID0gcmFuZ2Uuc3BsaXQoIi0iLCAyKS5tYXAoeCA9PiB7CiAgICAgICAgY29uc3QgZm91bmQgPSB4Lm1hdGNoKHVuaWNvZGVSZWdleCk7CiAgICAgICAgaWYgKCFmb3VuZCkgewogICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQogICAgICAgIHJldHVybiBwYXJzZUludChmb3VuZFsxXSwgMTYpOwogICAgICB9KTsKICAgICAgaWYgKHJhbmdlLmxlbmd0aCA9PT0gMSkgewogICAgICAgIHJhbmdlLnB1c2gocmFuZ2VbMF0pOwogICAgICB9CiAgICAgIHJhbmdlcy5wdXNoKHJhbmdlKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInVuaWNvZGVSYW5nZSIsIHJhbmdlcyk7CiAgfQp9CmNsYXNzIEV4Y2x1ZGUgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJleGNsdWRlIik7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgdGhpc1skY29udGVudF0gPSB0aGlzWyRjb250ZW50XS50cmltKCkuc3BsaXQoL1xzKy8pLmZpbHRlcih4ID0+IHggJiYgWyJjYWxjdWxhdGUiLCAiY2xvc2UiLCAiZW50ZXIiLCAiZXhpdCIsICJpbml0aWFsaXplIiwgInJlYWR5IiwgInZhbGlkYXRlIl0uaW5jbHVkZXMoeCkpOwogIH0KfQpjbGFzcyBFeGNsdWRlTlMgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImV4Y2x1ZGVOUyIpOwogIH0KfQpjbGFzcyBGbGlwTGFiZWwgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImZsaXBMYWJlbCIsIFsidXNlUHJpbnRlclNldHRpbmciLCAib24iLCAib2ZmIl0pOwogIH0KfQpjbGFzcyBjb25maWdfRm9udEluZm8gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImZvbnRJbmZvIiwgdHJ1ZSk7CiAgICB0aGlzLmVtYmVkID0gbnVsbDsKICAgIHRoaXMubWFwID0gbnVsbDsKICAgIHRoaXMuc3Vic2V0QmVsb3cgPSBudWxsOwogICAgdGhpcy5hbHdheXNFbWJlZCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWZhdWx0VHlwZWZhY2UgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubmV2ZXJFbWJlZCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBGb3JtRmllbGRGaWxsaW5nIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImZvcm1GaWVsZEZpbGxpbmciKTsKICB9Cn0KY2xhc3MgR3JvdXBQYXJlbnQgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImdyb3VwUGFyZW50Iik7CiAgfQp9CmNsYXNzIElmRW1wdHkgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImlmRW1wdHkiLCBbImRhdGFWYWx1ZSIsICJkYXRhR3JvdXAiLCAiaWdub3JlIiwgInJlbW92ZSJdKTsKICB9Cn0KY2xhc3MgSW5jbHVkZVhEUENvbnRlbnQgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImluY2x1ZGVYRFBDb250ZW50Iik7CiAgfQp9CmNsYXNzIEluY3JlbWVudGFsTG9hZCBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiaW5jcmVtZW50YWxMb2FkIiwgWyJub25lIiwgImZvcndhcmRPbmx5Il0pOwogIH0KfQpjbGFzcyBJbmNyZW1lbnRhbE1lcmdlIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImluY3JlbWVudGFsTWVyZ2UiKTsKICB9Cn0KY2xhc3MgSW50ZXJhY3RpdmUgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiaW50ZXJhY3RpdmUiKTsKICB9Cn0KY2xhc3MgSm9nIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJqb2ciLCBbInVzZVByaW50ZXJTZXR0aW5nIiwgIm5vbmUiLCAicGFnZVNldCJdKTsKICB9Cn0KY2xhc3MgTGFiZWxQcmludGVyIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsYWJlbFByaW50ZXIiLCB0cnVlKTsKICAgIHRoaXMubmFtZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm5hbWUsIFsienBsIiwgImRwbCIsICJpcGwiLCAidGNwbCJdKTsKICAgIHRoaXMuYmF0Y2hPdXRwdXQgPSBudWxsOwogICAgdGhpcy5mbGlwTGFiZWwgPSBudWxsOwogICAgdGhpcy5mb250SW5mbyA9IG51bGw7CiAgICB0aGlzLnhkYyA9IG51bGw7CiAgfQp9CmNsYXNzIExheW91dCBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAibGF5b3V0IiwgWyJwYWdpbmF0ZSIsICJwYW5lbCJdKTsKICB9Cn0KY2xhc3MgTGV2ZWwgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsZXZlbCIsIDAsIG4gPT4gbiA+IDApOwogIH0KfQpjbGFzcyBMaW5lYXJpemVkIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImxpbmVhcml6ZWQiKTsKICB9Cn0KY2xhc3MgTG9jYWxlIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsb2NhbGUiKTsKICB9Cn0KY2xhc3MgTG9jYWxlU2V0IGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsb2NhbGVTZXQiKTsKICB9Cn0KY2xhc3MgTG9nIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsb2ciLCB0cnVlKTsKICAgIHRoaXMubW9kZSA9IG51bGw7CiAgICB0aGlzLnRocmVzaG9sZCA9IG51bGw7CiAgICB0aGlzLnRvID0gbnVsbDsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgTWFwRWxlbWVudCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAibWFwIiwgdHJ1ZSk7CiAgICB0aGlzLmVxdWF0ZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lcXVhdGVSYW5nZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBNZWRpdW1JbmZvIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJtZWRpdW1JbmZvIiwgdHJ1ZSk7CiAgICB0aGlzLm1hcCA9IG51bGw7CiAgfQp9CmNsYXNzIGNvbmZpZ19NZXNzYWdlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJtZXNzYWdlIiwgdHJ1ZSk7CiAgICB0aGlzLm1zZ0lkID0gbnVsbDsKICAgIHRoaXMuc2V2ZXJpdHkgPSBudWxsOwogIH0KfQpjbGFzcyBNZXNzYWdpbmcgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm1lc3NhZ2luZyIsIHRydWUpOwogICAgdGhpcy5tZXNzYWdlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIE1vZGUgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm1vZGUiLCBbImFwcGVuZCIsICJvdmVyd3JpdGUiXSk7CiAgfQp9CmNsYXNzIE1vZGlmeUFubm90cyBleHRlbmRzIE9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJtb2RpZnlBbm5vdHMiKTsKICB9Cn0KY2xhc3MgTXNnSWQgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJtc2dJZCIsIDEsIG4gPT4gbiA+PSAxKTsKICB9Cn0KY2xhc3MgTmFtZUF0dHIgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm5hbWVBdHRyIik7CiAgfQp9CmNsYXNzIE5ldmVyRW1iZWQgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJuZXZlckVtYmVkIik7CiAgfQp9CmNsYXNzIE51bWJlck9mQ29waWVzIGV4dGVuZHMgSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAibnVtYmVyT2ZDb3BpZXMiLCBudWxsLCBuID0+IG4gPj0gMiAmJiBuIDw9IDUpOwogIH0KfQpjbGFzcyBPcGVuQWN0aW9uIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJvcGVuQWN0aW9uIiwgdHJ1ZSk7CiAgICB0aGlzLmRlc3RpbmF0aW9uID0gbnVsbDsKICB9Cn0KY2xhc3MgT3V0cHV0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJvdXRwdXQiLCB0cnVlKTsKICAgIHRoaXMudG8gPSBudWxsOwogICAgdGhpcy50eXBlID0gbnVsbDsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgT3V0cHV0QmluIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJvdXRwdXRCaW4iKTsKICB9Cn0KY2xhc3MgT3V0cHV0WFNMIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJvdXRwdXRYU0wiLCB0cnVlKTsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgT3ZlcnByaW50IGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJvdmVycHJpbnQiLCBbIm5vbmUiLCAiYm90aCIsICJkcmF3IiwgImZpZWxkIl0pOwogIH0KfQpjbGFzcyBQYWNrZXRzIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwYWNrZXRzIik7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgaWYgKHRoaXNbJGNvbnRlbnRdID09PSAiKiIpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpc1skY29udGVudF0gPSB0aGlzWyRjb250ZW50XS50cmltKCkuc3BsaXQoL1xzKy8pLmZpbHRlcih4ID0+IFsiY29uZmlnIiwgImRhdGFzZXRzIiwgInRlbXBsYXRlIiwgInhmZGYiLCAieHNsdCJdLmluY2x1ZGVzKHgpKTsKICB9Cn0KY2xhc3MgUGFnZU9mZnNldCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGFnZU9mZnNldCIpOwogICAgdGhpcy54ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMueCwKICAgICAgZGVmYXVsdFZhbHVlOiAidXNlWERDU2V0dGluZyIsCiAgICAgIHZhbGlkYXRlOiBuID0+IHRydWUKICAgIH0pOwogICAgdGhpcy55ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMueSwKICAgICAgZGVmYXVsdFZhbHVlOiAidXNlWERDU2V0dGluZyIsCiAgICAgIHZhbGlkYXRlOiBuID0+IHRydWUKICAgIH0pOwogIH0KfQpjbGFzcyBQYWdlUmFuZ2UgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBhZ2VSYW5nZSIpOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIGNvbnN0IG51bWJlcnMgPSB0aGlzWyRjb250ZW50XS50cmltKCkuc3BsaXQoL1xzKy8pLm1hcCh4ID0+IHBhcnNlSW50KHgsIDEwKSk7CiAgICBjb25zdCByYW5nZXMgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IG51bWJlcnMubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICByYW5nZXMucHVzaChudW1iZXJzLnNsaWNlKGksIGkgKyAyKSk7CiAgICB9CiAgICB0aGlzWyRjb250ZW50XSA9IHJhbmdlczsKICB9Cn0KY2xhc3MgUGFnaW5hdGlvbiBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGFnaW5hdGlvbiIsIFsic2ltcGxleCIsICJkdXBsZXhTaG9ydEVkZ2UiLCAiZHVwbGV4TG9uZ0VkZ2UiXSk7CiAgfQp9CmNsYXNzIFBhZ2luYXRpb25PdmVycmlkZSBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGFnaW5hdGlvbk92ZXJyaWRlIiwgWyJub25lIiwgImZvcmNlRHVwbGV4IiwgImZvcmNlRHVwbGV4TG9uZ0VkZ2UiLCAiZm9yY2VEdXBsZXhTaG9ydEVkZ2UiLCAiZm9yY2VTaW1wbGV4Il0pOwogIH0KfQpjbGFzcyBQYXJ0IGV4dGVuZHMgSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGFydCIsIDEsIG4gPT4gZmFsc2UpOwogIH0KfQpjbGFzcyBQY2wgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBjbCIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5iYXRjaE91dHB1dCA9IG51bGw7CiAgICB0aGlzLmZvbnRJbmZvID0gbnVsbDsKICAgIHRoaXMuam9nID0gbnVsbDsKICAgIHRoaXMubWVkaXVtSW5mbyA9IG51bGw7CiAgICB0aGlzLm91dHB1dEJpbiA9IG51bGw7CiAgICB0aGlzLnBhZ2VPZmZzZXQgPSBudWxsOwogICAgdGhpcy5zdGFwbGUgPSBudWxsOwogICAgdGhpcy54ZGMgPSBudWxsOwogIH0KfQpjbGFzcyBQZGYgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBkZiIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5hZG9iZUV4dGVuc2lvbkxldmVsID0gbnVsbDsKICAgIHRoaXMuYmF0Y2hPdXRwdXQgPSBudWxsOwogICAgdGhpcy5jb21wcmVzc2lvbiA9IG51bGw7CiAgICB0aGlzLmNyZWF0b3IgPSBudWxsOwogICAgdGhpcy5lbmNyeXB0aW9uID0gbnVsbDsKICAgIHRoaXMuZm9udEluZm8gPSBudWxsOwogICAgdGhpcy5pbnRlcmFjdGl2ZSA9IG51bGw7CiAgICB0aGlzLmxpbmVhcml6ZWQgPSBudWxsOwogICAgdGhpcy5vcGVuQWN0aW9uID0gbnVsbDsKICAgIHRoaXMucGRmYSA9IG51bGw7CiAgICB0aGlzLnByb2R1Y2VyID0gbnVsbDsKICAgIHRoaXMucmVuZGVyUG9saWN5ID0gbnVsbDsKICAgIHRoaXMuc2NyaXB0TW9kZWwgPSBudWxsOwogICAgdGhpcy5zaWxlbnRQcmludCA9IG51bGw7CiAgICB0aGlzLnN1Ym1pdEZvcm1hdCA9IG51bGw7CiAgICB0aGlzLnRhZ2dlZCA9IG51bGw7CiAgICB0aGlzLnZlcnNpb24gPSBudWxsOwogICAgdGhpcy52aWV3ZXJQcmVmZXJlbmNlcyA9IG51bGw7CiAgICB0aGlzLnhkYyA9IG51bGw7CiAgfQp9CmNsYXNzIFBkZmEgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBkZmEiLCB0cnVlKTsKICAgIHRoaXMuYW1kID0gbnVsbDsKICAgIHRoaXMuY29uZm9ybWFuY2UgPSBudWxsOwogICAgdGhpcy5pbmNsdWRlWERQQ29udGVudCA9IG51bGw7CiAgICB0aGlzLnBhcnQgPSBudWxsOwogIH0KfQpjbGFzcyBQZXJtaXNzaW9ucyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGVybWlzc2lvbnMiLCB0cnVlKTsKICAgIHRoaXMuYWNjZXNzaWJsZUNvbnRlbnQgPSBudWxsOwogICAgdGhpcy5jaGFuZ2UgPSBudWxsOwogICAgdGhpcy5jb250ZW50Q29weSA9IG51bGw7CiAgICB0aGlzLmRvY3VtZW50QXNzZW1ibHkgPSBudWxsOwogICAgdGhpcy5mb3JtRmllbGRGaWxsaW5nID0gbnVsbDsKICAgIHRoaXMubW9kaWZ5QW5ub3RzID0gbnVsbDsKICAgIHRoaXMucGxhaW50ZXh0TWV0YWRhdGEgPSBudWxsOwogICAgdGhpcy5wcmludCA9IG51bGw7CiAgICB0aGlzLnByaW50SGlnaFF1YWxpdHkgPSBudWxsOwogIH0KfQpjbGFzcyBQaWNrVHJheUJ5UERGU2l6ZSBleHRlbmRzIE9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwaWNrVHJheUJ5UERGU2l6ZSIpOwogIH0KfQpjbGFzcyBjb25maWdfUGljdHVyZSBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGljdHVyZSIpOwogIH0KfQpjbGFzcyBQbGFpbnRleHRNZXRhZGF0YSBleHRlbmRzIE9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwbGFpbnRleHRNZXRhZGF0YSIpOwogIH0KfQpjbGFzcyBQcmVzZW5jZSBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicHJlc2VuY2UiLCBbInByZXNlcnZlIiwgImRpc3NvbHZlIiwgImRpc3NvbHZlU3RydWN0dXJlIiwgImlnbm9yZSIsICJyZW1vdmUiXSk7CiAgfQp9CmNsYXNzIFByZXNlbnQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInByZXNlbnQiLCB0cnVlKTsKICAgIHRoaXMuYmVoYXZpb3JPdmVycmlkZSA9IG51bGw7CiAgICB0aGlzLmNhY2hlID0gbnVsbDsKICAgIHRoaXMuY29tbW9uID0gbnVsbDsKICAgIHRoaXMuY29waWVzID0gbnVsbDsKICAgIHRoaXMuZGVzdGluYXRpb24gPSBudWxsOwogICAgdGhpcy5pbmNyZW1lbnRhbE1lcmdlID0gbnVsbDsKICAgIHRoaXMubGF5b3V0ID0gbnVsbDsKICAgIHRoaXMub3V0cHV0ID0gbnVsbDsKICAgIHRoaXMub3ZlcnByaW50ID0gbnVsbDsKICAgIHRoaXMucGFnaW5hdGlvbiA9IG51bGw7CiAgICB0aGlzLnBhZ2luYXRpb25PdmVycmlkZSA9IG51bGw7CiAgICB0aGlzLnNjcmlwdCA9IG51bGw7CiAgICB0aGlzLnZhbGlkYXRlID0gbnVsbDsKICAgIHRoaXMueGRwID0gbnVsbDsKICAgIHRoaXMuZHJpdmVyID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmxhYmVsUHJpbnRlciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wY2wgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucGRmID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnBzID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1Ym1pdFVybCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy53ZWJDbGllbnQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuenBsID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIFByaW50IGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInByaW50Iik7CiAgfQp9CmNsYXNzIFByaW50SGlnaFF1YWxpdHkgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicHJpbnRIaWdoUXVhbGl0eSIpOwogIH0KfQpjbGFzcyBQcmludFNjYWxpbmcgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInByaW50U2NhbGluZyIsIFsiYXBwZGVmYXVsdCIsICJub1NjYWxpbmciXSk7CiAgfQp9CmNsYXNzIFByaW50ZXJOYW1lIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwcmludGVyTmFtZSIpOwogIH0KfQpjbGFzcyBQcm9kdWNlciBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicHJvZHVjZXIiKTsKICB9Cn0KY2xhc3MgUHMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBzIiwgdHJ1ZSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLmJhdGNoT3V0cHV0ID0gbnVsbDsKICAgIHRoaXMuZm9udEluZm8gPSBudWxsOwogICAgdGhpcy5qb2cgPSBudWxsOwogICAgdGhpcy5tZWRpdW1JbmZvID0gbnVsbDsKICAgIHRoaXMub3V0cHV0QmluID0gbnVsbDsKICAgIHRoaXMuc3RhcGxlID0gbnVsbDsKICAgIHRoaXMueGRjID0gbnVsbDsKICB9Cn0KY2xhc3MgUmFuZ2UgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJyYW5nZSIpOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbJGNvbnRlbnRdID0gdGhpc1skY29udGVudF0uc3BsaXQoIiwiLCAyKS5tYXAocmFuZ2UgPT4gcmFuZ2Uuc3BsaXQoIi0iKS5tYXAoeCA9PiBwYXJzZUludCh4LnRyaW0oKSwgMTApKSkuZmlsdGVyKHJhbmdlID0+IHJhbmdlLmV2ZXJ5KHggPT4gIWlzTmFOKHgpKSkubWFwKHJhbmdlID0+IHsKICAgICAgaWYgKHJhbmdlLmxlbmd0aCA9PT0gMSkgewogICAgICAgIHJhbmdlLnB1c2gocmFuZ2VbMF0pOwogICAgICB9CiAgICAgIHJldHVybiByYW5nZTsKICAgIH0pOwogIH0KfQpjbGFzcyBSZWNvcmQgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJyZWNvcmQiKTsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzWyRjb250ZW50XSA9IHRoaXNbJGNvbnRlbnRdLnRyaW0oKTsKICAgIGNvbnN0IG4gPSBwYXJzZUludCh0aGlzWyRjb250ZW50XSwgMTApOwogICAgaWYgKCFpc05hTihuKSAmJiBuID49IDApIHsKICAgICAgdGhpc1skY29udGVudF0gPSBuOwogICAgfQogIH0KfQpjbGFzcyBSZWxldmFudCBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInJlbGV2YW50Iik7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgdGhpc1skY29udGVudF0gPSB0aGlzWyRjb250ZW50XS50cmltKCkuc3BsaXQoL1xzKy8pOwogIH0KfQpjbGFzcyBSZW5hbWUgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJyZW5hbWUiKTsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzWyRjb250ZW50XSA9IHRoaXNbJGNvbnRlbnRdLnRyaW0oKTsKICAgIGlmICh0aGlzWyRjb250ZW50XS50b0xvd2VyQ2FzZSgpLnN0YXJ0c1dpdGgoInhtbCIpIHx8IG5ldyBSZWdFeHAoIltcXHB7TH1fXVtcXHB7TH1cXGQuX1xccHtNfS1dKiIsICJ1IikudGVzdCh0aGlzWyRjb250ZW50XSkpIHsKICAgICAgd2FybigiWEZBIC0gUmVuYW1lOiBpbnZhbGlkIFhGQSBuYW1lIik7CiAgICB9CiAgfQp9CmNsYXNzIFJlbmRlclBvbGljeSBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicmVuZGVyUG9saWN5IiwgWyJzZXJ2ZXIiLCAiY2xpZW50Il0pOwogIH0KfQpjbGFzcyBSdW5TY3JpcHRzIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJydW5TY3JpcHRzIiwgWyJib3RoIiwgImNsaWVudCIsICJub25lIiwgInNlcnZlciJdKTsKICB9Cn0KY2xhc3MgY29uZmlnX1NjcmlwdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2NyaXB0IiwgdHJ1ZSk7CiAgICB0aGlzLmN1cnJlbnRQYWdlID0gbnVsbDsKICAgIHRoaXMuZXhjbHVkZSA9IG51bGw7CiAgICB0aGlzLnJ1blNjcmlwdHMgPSBudWxsOwogIH0KfQpjbGFzcyBTY3JpcHRNb2RlbCBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2NyaXB0TW9kZWwiLCBbIlhGQSIsICJub25lIl0pOwogIH0KfQpjbGFzcyBTZXZlcml0eSBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2V2ZXJpdHkiLCBbImlnbm9yZSIsICJlcnJvciIsICJpbmZvcm1hdGlvbiIsICJ0cmFjZSIsICJ3YXJuaW5nIl0pOwogIH0KfQpjbGFzcyBTaWxlbnRQcmludCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2lsZW50UHJpbnQiLCB0cnVlKTsKICAgIHRoaXMuYWRkU2lsZW50UHJpbnQgPSBudWxsOwogICAgdGhpcy5wcmludGVyTmFtZSA9IG51bGw7CiAgfQp9CmNsYXNzIFN0YXBsZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3RhcGxlIik7CiAgICB0aGlzLm1vZGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5tb2RlLCBbInVzZVByaW50ZXJTZXR0aW5nIiwgIm9uIiwgIm9mZiJdKTsKICB9Cn0KY2xhc3MgU3RhcnROb2RlIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJzdGFydE5vZGUiKTsKICB9Cn0KY2xhc3MgU3RhcnRQYWdlIGV4dGVuZHMgSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3RhcnRQYWdlIiwgMCwgbiA9PiB0cnVlKTsKICB9Cn0KY2xhc3MgU3VibWl0Rm9ybWF0IGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJzdWJtaXRGb3JtYXQiLCBbImh0bWwiLCAiZGVsZWdhdGUiLCAiZmRmIiwgInhtbCIsICJwZGYiXSk7CiAgfQp9CmNsYXNzIFN1Ym1pdFVybCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3VibWl0VXJsIik7CiAgfQp9CmNsYXNzIFN1YnNldEJlbG93IGV4dGVuZHMgSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3Vic2V0QmVsb3ciLCAxMDAsIG4gPT4gbiA+PSAwICYmIG4gPD0gMTAwKTsKICB9Cn0KY2xhc3MgU3VwcHJlc3NCYW5uZXIgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3VwcHJlc3NCYW5uZXIiKTsKICB9Cn0KY2xhc3MgVGFnZ2VkIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInRhZ2dlZCIpOwogIH0KfQpjbGFzcyBjb25maWdfVGVtcGxhdGUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInRlbXBsYXRlIiwgdHJ1ZSk7CiAgICB0aGlzLmJhc2UgPSBudWxsOwogICAgdGhpcy5yZWxldmFudCA9IG51bGw7CiAgICB0aGlzLnN0YXJ0UGFnZSA9IG51bGw7CiAgICB0aGlzLnVyaSA9IG51bGw7CiAgICB0aGlzLnhzbCA9IG51bGw7CiAgfQp9CmNsYXNzIFRocmVzaG9sZCBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidGhyZXNob2xkIiwgWyJ0cmFjZSIsICJlcnJvciIsICJpbmZvcm1hdGlvbiIsICJ3YXJuaW5nIl0pOwogIH0KfQpjbGFzcyBUbyBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidG8iLCBbIm51bGwiLCAibWVtb3J5IiwgInN0ZGVyciIsICJzdGRvdXQiLCAic3lzdGVtIiwgInVyaSJdKTsKICB9Cn0KY2xhc3MgVGVtcGxhdGVDYWNoZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidGVtcGxhdGVDYWNoZSIpOwogICAgdGhpcy5tYXhFbnRyaWVzID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMubWF4RW50cmllcywKICAgICAgZGVmYXVsdFZhbHVlOiA1LAogICAgICB2YWxpZGF0ZTogbiA9PiBuID49IDAKICAgIH0pOwogIH0KfQpjbGFzcyBUcmFjZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidHJhY2UiLCB0cnVlKTsKICAgIHRoaXMuYXJlYSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBUcmFuc2Zvcm0gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInRyYW5zZm9ybSIsIHRydWUpOwogICAgdGhpcy5ncm91cFBhcmVudCA9IG51bGw7CiAgICB0aGlzLmlmRW1wdHkgPSBudWxsOwogICAgdGhpcy5uYW1lQXR0ciA9IG51bGw7CiAgICB0aGlzLnBpY3R1cmUgPSBudWxsOwogICAgdGhpcy5wcmVzZW5jZSA9IG51bGw7CiAgICB0aGlzLnJlbmFtZSA9IG51bGw7CiAgICB0aGlzLndoaXRlc3BhY2UgPSBudWxsOwogIH0KfQpjbGFzcyBUeXBlIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ0eXBlIiwgWyJub25lIiwgImFzY2lpODUiLCAiYXNjaWlIZXgiLCAiY2NpdHRmYXgiLCAiZmxhdGUiLCAibHp3IiwgInJ1bkxlbmd0aCIsICJuYXRpdmUiLCAieGRwIiwgIm1lcmdlZFhEUCJdKTsKICB9Cn0KY2xhc3MgVXJpIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ1cmkiKTsKICB9Cn0KY2xhc3MgY29uZmlnX1ZhbGlkYXRlIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ2YWxpZGF0ZSIsIFsicHJlU3VibWl0IiwgInByZVByaW50IiwgInByZUV4ZWN1dGUiLCAicHJlU2F2ZSJdKTsKICB9Cn0KY2xhc3MgVmFsaWRhdGVBcHByb3ZhbFNpZ25hdHVyZXMgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ2YWxpZGF0ZUFwcHJvdmFsU2lnbmF0dXJlcyIpOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbJGNvbnRlbnRdID0gdGhpc1skY29udGVudF0udHJpbSgpLnNwbGl0KC9ccysvKS5maWx0ZXIoeCA9PiBbImRvY1JlYWR5IiwgInBvc3RTaWduIl0uaW5jbHVkZXMoeCkpOwogIH0KfQpjbGFzcyBWYWxpZGF0aW9uTWVzc2FnaW5nIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ2YWxpZGF0aW9uTWVzc2FnaW5nIiwgWyJhbGxNZXNzYWdlc0luZGl2aWR1YWxseSIsICJhbGxNZXNzYWdlc1RvZ2V0aGVyIiwgImZpcnN0TWVzc2FnZU9ubHkiLCAibm9NZXNzYWdlcyJdKTsKICB9Cn0KY2xhc3MgVmVyc2lvbiBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidmVyc2lvbiIsIFsiMS43IiwgIjEuNiIsICIxLjUiLCAiMS40IiwgIjEuMyIsICIxLjIiXSk7CiAgfQp9CmNsYXNzIFZlcnNpb25Db250cm9sIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJWZXJzaW9uQ29udHJvbCIpOwogICAgdGhpcy5vdXRwdXRCZWxvdyA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm91dHB1dEJlbG93LCBbIndhcm4iLCAiZXJyb3IiLCAidXBkYXRlIl0pOwogICAgdGhpcy5zb3VyY2VBYm92ZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnNvdXJjZUFib3ZlLCBbIndhcm4iLCAiZXJyb3IiXSk7CiAgICB0aGlzLnNvdXJjZUJlbG93ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuc291cmNlQmVsb3csIFsidXBkYXRlIiwgIm1haW50YWluIl0pOwogIH0KfQpjbGFzcyBWaWV3ZXJQcmVmZXJlbmNlcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidmlld2VyUHJlZmVyZW5jZXMiLCB0cnVlKTsKICAgIHRoaXMuQURCRV9KU0NvbnNvbGUgPSBudWxsOwogICAgdGhpcy5BREJFX0pTRGVidWdnZXIgPSBudWxsOwogICAgdGhpcy5hZGRWaWV3ZXJQcmVmZXJlbmNlcyA9IG51bGw7CiAgICB0aGlzLmR1cGxleE9wdGlvbiA9IG51bGw7CiAgICB0aGlzLmVuZm9yY2UgPSBudWxsOwogICAgdGhpcy5udW1iZXJPZkNvcGllcyA9IG51bGw7CiAgICB0aGlzLnBhZ2VSYW5nZSA9IG51bGw7CiAgICB0aGlzLnBpY2tUcmF5QnlQREZTaXplID0gbnVsbDsKICAgIHRoaXMucHJpbnRTY2FsaW5nID0gbnVsbDsKICB9Cn0KY2xhc3MgV2ViQ2xpZW50IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ3ZWJDbGllbnQiLCB0cnVlKTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSA/IGF0dHJpYnV0ZXMubmFtZS50cmltKCkgOiAiIjsKICAgIHRoaXMuZm9udEluZm8gPSBudWxsOwogICAgdGhpcy54ZGMgPSBudWxsOwogIH0KfQpjbGFzcyBXaGl0ZXNwYWNlIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ3aGl0ZXNwYWNlIiwgWyJwcmVzZXJ2ZSIsICJsdHJpbSIsICJub3JtYWxpemUiLCAicnRyaW0iLCAidHJpbSJdKTsKICB9Cn0KY2xhc3MgV2luZG93IGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAid2luZG93Iik7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgY29uc3QgcGFpciA9IHRoaXNbJGNvbnRlbnRdLnNwbGl0KCIsIiwgMikubWFwKHggPT4gcGFyc2VJbnQoeC50cmltKCksIDEwKSk7CiAgICBpZiAocGFpci5zb21lKHggPT4gaXNOYU4oeCkpKSB7CiAgICAgIHRoaXNbJGNvbnRlbnRdID0gWzAsIDBdOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAocGFpci5sZW5ndGggPT09IDEpIHsKICAgICAgcGFpci5wdXNoKHBhaXJbMF0pOwogICAgfQogICAgdGhpc1skY29udGVudF0gPSBwYWlyOwogIH0KfQpjbGFzcyBYZGMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInhkYyIsIHRydWUpOwogICAgdGhpcy51cmkgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMueHNsID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIFhkcCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAieGRwIiwgdHJ1ZSk7CiAgICB0aGlzLnBhY2tldHMgPSBudWxsOwogIH0KfQpjbGFzcyBYc2wgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInhzbCIsIHRydWUpOwogICAgdGhpcy5kZWJ1ZyA9IG51bGw7CiAgICB0aGlzLnVyaSA9IG51bGw7CiAgfQp9CmNsYXNzIFpwbCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAienBsIiwgdHJ1ZSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgPyBhdHRyaWJ1dGVzLm5hbWUudHJpbSgpIDogIiI7CiAgICB0aGlzLmJhdGNoT3V0cHV0ID0gbnVsbDsKICAgIHRoaXMuZmxpcExhYmVsID0gbnVsbDsKICAgIHRoaXMuZm9udEluZm8gPSBudWxsOwogICAgdGhpcy54ZGMgPSBudWxsOwogIH0KfQpjbGFzcyBDb25maWdOYW1lc3BhY2UgewogIHN0YXRpYyBbJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoQ29uZmlnTmFtZXNwYWNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIHJldHVybiBDb25maWdOYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgYWNyb2JhdChhdHRycykgewogICAgcmV0dXJuIG5ldyBBY3JvYmF0KGF0dHJzKTsKICB9CiAgc3RhdGljIGFjcm9iYXQ3KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEFjcm9iYXQ3KGF0dHJzKTsKICB9CiAgc3RhdGljIEFEQkVfSlNDb25zb2xlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEFEQkVfSlNDb25zb2xlKGF0dHJzKTsKICB9CiAgc3RhdGljIEFEQkVfSlNEZWJ1Z2dlcihhdHRycykgewogICAgcmV0dXJuIG5ldyBBREJFX0pTRGVidWdnZXIoYXR0cnMpOwogIH0KICBzdGF0aWMgYWRkU2lsZW50UHJpbnQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQWRkU2lsZW50UHJpbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgYWRkVmlld2VyUHJlZmVyZW5jZXMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQWRkVmlld2VyUHJlZmVyZW5jZXMoYXR0cnMpOwogIH0KICBzdGF0aWMgYWRqdXN0RGF0YShhdHRycykgewogICAgcmV0dXJuIG5ldyBBZGp1c3REYXRhKGF0dHJzKTsKICB9CiAgc3RhdGljIGFkb2JlRXh0ZW5zaW9uTGV2ZWwoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQWRvYmVFeHRlbnNpb25MZXZlbChhdHRycyk7CiAgfQogIHN0YXRpYyBhZ2VudChhdHRycykgewogICAgcmV0dXJuIG5ldyBBZ2VudChhdHRycyk7CiAgfQogIHN0YXRpYyBhbHdheXNFbWJlZChhdHRycykgewogICAgcmV0dXJuIG5ldyBBbHdheXNFbWJlZChhdHRycyk7CiAgfQogIHN0YXRpYyBhbWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQW1kKGF0dHJzKTsKICB9CiAgc3RhdGljIGFyZWEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgY29uZmlnX0FyZWEoYXR0cnMpOwogIH0KICBzdGF0aWMgYXR0cmlidXRlcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBBdHRyaWJ1dGVzKGF0dHJzKTsKICB9CiAgc3RhdGljIGF1dG9TYXZlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEF1dG9TYXZlKGF0dHJzKTsKICB9CiAgc3RhdGljIGJhc2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQmFzZShhdHRycyk7CiAgfQogIHN0YXRpYyBiYXRjaE91dHB1dChhdHRycykgewogICAgcmV0dXJuIG5ldyBCYXRjaE91dHB1dChhdHRycyk7CiAgfQogIHN0YXRpYyBiZWhhdmlvck92ZXJyaWRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJlaGF2aW9yT3ZlcnJpZGUoYXR0cnMpOwogIH0KICBzdGF0aWMgY2FjaGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ2FjaGUoYXR0cnMpOwogIH0KICBzdGF0aWMgY2hhbmdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENoYW5nZShhdHRycyk7CiAgfQogIHN0YXRpYyBjb21tb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tbW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbXByZXNzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbXByZXNzKGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbXByZXNzTG9naWNhbFN0cnVjdHVyZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDb21wcmVzc0xvZ2ljYWxTdHJ1Y3R1cmUoYXR0cnMpOwogIH0KICBzdGF0aWMgY29tcHJlc3NPYmplY3RTdHJlYW0oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tcHJlc3NPYmplY3RTdHJlYW0oYXR0cnMpOwogIH0KICBzdGF0aWMgY29tcHJlc3Npb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tcHJlc3Npb24oYXR0cnMpOwogIH0KICBzdGF0aWMgY29uZmlnKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbmZpZyhhdHRycyk7CiAgfQogIHN0YXRpYyBjb25mb3JtYW5jZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDb25mb3JtYW5jZShhdHRycyk7CiAgfQogIHN0YXRpYyBjb250ZW50Q29weShhdHRycykgewogICAgcmV0dXJuIG5ldyBDb250ZW50Q29weShhdHRycyk7CiAgfQogIHN0YXRpYyBjb3BpZXMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29waWVzKGF0dHJzKTsKICB9CiAgc3RhdGljIGNyZWF0b3IoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ3JlYXRvcihhdHRycyk7CiAgfQogIHN0YXRpYyBjdXJyZW50UGFnZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDdXJyZW50UGFnZShhdHRycyk7CiAgfQogIHN0YXRpYyBkYXRhKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGEoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVidWcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRGVidWcoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVmYXVsdFR5cGVmYWNlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERlZmF1bHRUeXBlZmFjZShhdHRycyk7CiAgfQogIHN0YXRpYyBkZXN0aW5hdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBEZXN0aW5hdGlvbihhdHRycyk7CiAgfQogIHN0YXRpYyBkb2N1bWVudEFzc2VtYmx5KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERvY3VtZW50QXNzZW1ibHkoYXR0cnMpOwogIH0KICBzdGF0aWMgZHJpdmVyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERyaXZlcihhdHRycyk7CiAgfQogIHN0YXRpYyBkdXBsZXhPcHRpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRHVwbGV4T3B0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGR5bmFtaWNSZW5kZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRHluYW1pY1JlbmRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBlbWJlZChhdHRycykgewogICAgcmV0dXJuIG5ldyBFbWJlZChhdHRycyk7CiAgfQogIHN0YXRpYyBlbmNyeXB0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IGNvbmZpZ19FbmNyeXB0KGF0dHJzKTsKICB9CiAgc3RhdGljIGVuY3J5cHRpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgY29uZmlnX0VuY3J5cHRpb24oYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jcnlwdGlvbkxldmVsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVuY3J5cHRpb25MZXZlbChhdHRycyk7CiAgfQogIHN0YXRpYyBlbmZvcmNlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVuZm9yY2UoYXR0cnMpOwogIH0KICBzdGF0aWMgZXF1YXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVxdWF0ZShhdHRycyk7CiAgfQogIHN0YXRpYyBlcXVhdGVSYW5nZShhdHRycykgewogICAgcmV0dXJuIG5ldyBFcXVhdGVSYW5nZShhdHRycyk7CiAgfQogIHN0YXRpYyBleGNsdWRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEV4Y2x1ZGUoYXR0cnMpOwogIH0KICBzdGF0aWMgZXhjbHVkZU5TKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEV4Y2x1ZGVOUyhhdHRycyk7CiAgfQogIHN0YXRpYyBmbGlwTGFiZWwoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRmxpcExhYmVsKGF0dHJzKTsKICB9CiAgc3RhdGljIGZvbnRJbmZvKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IGNvbmZpZ19Gb250SW5mbyhhdHRycyk7CiAgfQogIHN0YXRpYyBmb3JtRmllbGRGaWxsaW5nKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEZvcm1GaWVsZEZpbGxpbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgZ3JvdXBQYXJlbnQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgR3JvdXBQYXJlbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgaWZFbXB0eShhdHRycykgewogICAgcmV0dXJuIG5ldyBJZkVtcHR5KGF0dHJzKTsKICB9CiAgc3RhdGljIGluY2x1ZGVYRFBDb250ZW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEluY2x1ZGVYRFBDb250ZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIGluY3JlbWVudGFsTG9hZChhdHRycykgewogICAgcmV0dXJuIG5ldyBJbmNyZW1lbnRhbExvYWQoYXR0cnMpOwogIH0KICBzdGF0aWMgaW5jcmVtZW50YWxNZXJnZShhdHRycykgewogICAgcmV0dXJuIG5ldyBJbmNyZW1lbnRhbE1lcmdlKGF0dHJzKTsKICB9CiAgc3RhdGljIGludGVyYWN0aXZlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEludGVyYWN0aXZlKGF0dHJzKTsKICB9CiAgc3RhdGljIGpvZyhhdHRycykgewogICAgcmV0dXJuIG5ldyBKb2coYXR0cnMpOwogIH0KICBzdGF0aWMgbGFiZWxQcmludGVyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExhYmVsUHJpbnRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBsYXlvdXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTGF5b3V0KGF0dHJzKTsKICB9CiAgc3RhdGljIGxldmVsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExldmVsKGF0dHJzKTsKICB9CiAgc3RhdGljIGxpbmVhcml6ZWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTGluZWFyaXplZChhdHRycyk7CiAgfQogIHN0YXRpYyBsb2NhbGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTG9jYWxlKGF0dHJzKTsKICB9CiAgc3RhdGljIGxvY2FsZVNldChhdHRycykgewogICAgcmV0dXJuIG5ldyBMb2NhbGVTZXQoYXR0cnMpOwogIH0KICBzdGF0aWMgbG9nKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExvZyhhdHRycyk7CiAgfQogIHN0YXRpYyBtYXAoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTWFwRWxlbWVudChhdHRycyk7CiAgfQogIHN0YXRpYyBtZWRpdW1JbmZvKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1lZGl1bUluZm8oYXR0cnMpOwogIH0KICBzdGF0aWMgbWVzc2FnZShhdHRycykgewogICAgcmV0dXJuIG5ldyBjb25maWdfTWVzc2FnZShhdHRycyk7CiAgfQogIHN0YXRpYyBtZXNzYWdpbmcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTWVzc2FnaW5nKGF0dHJzKTsKICB9CiAgc3RhdGljIG1vZGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTW9kZShhdHRycyk7CiAgfQogIHN0YXRpYyBtb2RpZnlBbm5vdHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTW9kaWZ5QW5ub3RzKGF0dHJzKTsKICB9CiAgc3RhdGljIG1zZ0lkKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1zZ0lkKGF0dHJzKTsKICB9CiAgc3RhdGljIG5hbWVBdHRyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE5hbWVBdHRyKGF0dHJzKTsKICB9CiAgc3RhdGljIG5ldmVyRW1iZWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTmV2ZXJFbWJlZChhdHRycyk7CiAgfQogIHN0YXRpYyBudW1iZXJPZkNvcGllcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBOdW1iZXJPZkNvcGllcyhhdHRycyk7CiAgfQogIHN0YXRpYyBvcGVuQWN0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE9wZW5BY3Rpb24oYXR0cnMpOwogIH0KICBzdGF0aWMgb3V0cHV0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE91dHB1dChhdHRycyk7CiAgfQogIHN0YXRpYyBvdXRwdXRCaW4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT3V0cHV0QmluKGF0dHJzKTsKICB9CiAgc3RhdGljIG91dHB1dFhTTChhdHRycykgewogICAgcmV0dXJuIG5ldyBPdXRwdXRYU0woYXR0cnMpOwogIH0KICBzdGF0aWMgb3ZlcnByaW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE92ZXJwcmludChhdHRycyk7CiAgfQogIHN0YXRpYyBwYWNrZXRzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBhY2tldHMoYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnZU9mZnNldChhdHRycykgewogICAgcmV0dXJuIG5ldyBQYWdlT2Zmc2V0KGF0dHJzKTsKICB9CiAgc3RhdGljIHBhZ2VSYW5nZShhdHRycykgewogICAgcmV0dXJuIG5ldyBQYWdlUmFuZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnaW5hdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBQYWdpbmF0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIHBhZ2luYXRpb25PdmVycmlkZShhdHRycykgewogICAgcmV0dXJuIG5ldyBQYWdpbmF0aW9uT3ZlcnJpZGUoYXR0cnMpOwogIH0KICBzdGF0aWMgcGFydChhdHRycykgewogICAgcmV0dXJuIG5ldyBQYXJ0KGF0dHJzKTsKICB9CiAgc3RhdGljIHBjbChhdHRycykgewogICAgcmV0dXJuIG5ldyBQY2woYXR0cnMpOwogIH0KICBzdGF0aWMgcGRmKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBkZihhdHRycyk7CiAgfQogIHN0YXRpYyBwZGZhKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBkZmEoYXR0cnMpOwogIH0KICBzdGF0aWMgcGVybWlzc2lvbnMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGVybWlzc2lvbnMoYXR0cnMpOwogIH0KICBzdGF0aWMgcGlja1RyYXlCeVBERlNpemUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGlja1RyYXlCeVBERlNpemUoYXR0cnMpOwogIH0KICBzdGF0aWMgcGljdHVyZShhdHRycykgewogICAgcmV0dXJuIG5ldyBjb25maWdfUGljdHVyZShhdHRycyk7CiAgfQogIHN0YXRpYyBwbGFpbnRleHRNZXRhZGF0YShhdHRycykgewogICAgcmV0dXJuIG5ldyBQbGFpbnRleHRNZXRhZGF0YShhdHRycyk7CiAgfQogIHN0YXRpYyBwcmVzZW5jZShhdHRycykgewogICAgcmV0dXJuIG5ldyBQcmVzZW5jZShhdHRycyk7CiAgfQogIHN0YXRpYyBwcmVzZW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFByZXNlbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJpbnQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJpbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJpbnRIaWdoUXVhbGl0eShhdHRycykgewogICAgcmV0dXJuIG5ldyBQcmludEhpZ2hRdWFsaXR5KGF0dHJzKTsKICB9CiAgc3RhdGljIHByaW50U2NhbGluZyhhdHRycykgewogICAgcmV0dXJuIG5ldyBQcmludFNjYWxpbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJpbnRlck5hbWUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJpbnRlck5hbWUoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJvZHVjZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJvZHVjZXIoYXR0cnMpOwogIH0KICBzdGF0aWMgcHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHMoYXR0cnMpOwogIH0KICBzdGF0aWMgcmFuZ2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmFuZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgcmVjb3JkKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFJlY29yZChhdHRycyk7CiAgfQogIHN0YXRpYyByZWxldmFudChhdHRycykgewogICAgcmV0dXJuIG5ldyBSZWxldmFudChhdHRycyk7CiAgfQogIHN0YXRpYyByZW5hbWUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVuYW1lKGF0dHJzKTsKICB9CiAgc3RhdGljIHJlbmRlclBvbGljeShhdHRycykgewogICAgcmV0dXJuIG5ldyBSZW5kZXJQb2xpY3koYXR0cnMpOwogIH0KICBzdGF0aWMgcnVuU2NyaXB0cyhhdHRycykgewogICAgcmV0dXJuIG5ldyBSdW5TY3JpcHRzKGF0dHJzKTsKICB9CiAgc3RhdGljIHNjcmlwdChhdHRycykgewogICAgcmV0dXJuIG5ldyBjb25maWdfU2NyaXB0KGF0dHJzKTsKICB9CiAgc3RhdGljIHNjcmlwdE1vZGVsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNjcmlwdE1vZGVsKGF0dHJzKTsKICB9CiAgc3RhdGljIHNldmVyaXR5KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNldmVyaXR5KGF0dHJzKTsKICB9CiAgc3RhdGljIHNpbGVudFByaW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNpbGVudFByaW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHN0YXBsZShhdHRycykgewogICAgcmV0dXJuIG5ldyBTdGFwbGUoYXR0cnMpOwogIH0KICBzdGF0aWMgc3RhcnROb2RlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN0YXJ0Tm9kZShhdHRycyk7CiAgfQogIHN0YXRpYyBzdGFydFBhZ2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU3RhcnRQYWdlKGF0dHJzKTsKICB9CiAgc3RhdGljIHN1Ym1pdEZvcm1hdChhdHRycykgewogICAgcmV0dXJuIG5ldyBTdWJtaXRGb3JtYXQoYXR0cnMpOwogIH0KICBzdGF0aWMgc3VibWl0VXJsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1Ym1pdFVybChhdHRycyk7CiAgfQogIHN0YXRpYyBzdWJzZXRCZWxvdyhhdHRycykgewogICAgcmV0dXJuIG5ldyBTdWJzZXRCZWxvdyhhdHRycyk7CiAgfQogIHN0YXRpYyBzdXBwcmVzc0Jhbm5lcihhdHRycykgewogICAgcmV0dXJuIG5ldyBTdXBwcmVzc0Jhbm5lcihhdHRycyk7CiAgfQogIHN0YXRpYyB0YWdnZWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVGFnZ2VkKGF0dHJzKTsKICB9CiAgc3RhdGljIHRlbXBsYXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IGNvbmZpZ19UZW1wbGF0ZShhdHRycyk7CiAgfQogIHN0YXRpYyB0ZW1wbGF0ZUNhY2hlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFRlbXBsYXRlQ2FjaGUoYXR0cnMpOwogIH0KICBzdGF0aWMgdGhyZXNob2xkKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFRocmVzaG9sZChhdHRycyk7CiAgfQogIHN0YXRpYyB0byhhdHRycykgewogICAgcmV0dXJuIG5ldyBUbyhhdHRycyk7CiAgfQogIHN0YXRpYyB0cmFjZShhdHRycykgewogICAgcmV0dXJuIG5ldyBUcmFjZShhdHRycyk7CiAgfQogIHN0YXRpYyB0cmFuc2Zvcm0oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVHJhbnNmb3JtKGF0dHJzKTsKICB9CiAgc3RhdGljIHR5cGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVHlwZShhdHRycyk7CiAgfQogIHN0YXRpYyB1cmkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVXJpKGF0dHJzKTsKICB9CiAgc3RhdGljIHZhbGlkYXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IGNvbmZpZ19WYWxpZGF0ZShhdHRycyk7CiAgfQogIHN0YXRpYyB2YWxpZGF0ZUFwcHJvdmFsU2lnbmF0dXJlcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBWYWxpZGF0ZUFwcHJvdmFsU2lnbmF0dXJlcyhhdHRycyk7CiAgfQogIHN0YXRpYyB2YWxpZGF0aW9uTWVzc2FnaW5nKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25NZXNzYWdpbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgdmVyc2lvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBWZXJzaW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIHZlcnNpb25Db250cm9sKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFZlcnNpb25Db250cm9sKGF0dHJzKTsKICB9CiAgc3RhdGljIHZpZXdlclByZWZlcmVuY2VzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFZpZXdlclByZWZlcmVuY2VzKGF0dHJzKTsKICB9CiAgc3RhdGljIHdlYkNsaWVudChhdHRycykgewogICAgcmV0dXJuIG5ldyBXZWJDbGllbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgd2hpdGVzcGFjZShhdHRycykgewogICAgcmV0dXJuIG5ldyBXaGl0ZXNwYWNlKGF0dHJzKTsKICB9CiAgc3RhdGljIHdpbmRvdyhhdHRycykgewogICAgcmV0dXJuIG5ldyBXaW5kb3coYXR0cnMpOwogIH0KICBzdGF0aWMgeGRjKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFhkYyhhdHRycyk7CiAgfQogIHN0YXRpYyB4ZHAoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgWGRwKGF0dHJzKTsKICB9CiAgc3RhdGljIHhzbChhdHRycykgewogICAgcmV0dXJuIG5ldyBYc2woYXR0cnMpOwogIH0KICBzdGF0aWMgenBsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFpwbChhdHRycyk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvY29ubmVjdGlvbl9zZXQuanMKCgpjb25zdCBDT05ORUNUSU9OX1NFVF9OU19JRCA9IE5hbWVzcGFjZUlkcy5jb25uZWN0aW9uU2V0LmlkOwpjbGFzcyBDb25uZWN0aW9uU2V0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgImNvbm5lY3Rpb25TZXQiLCB0cnVlKTsKICAgIHRoaXMud3NkbENvbm5lY3Rpb24gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMueG1sQ29ubmVjdGlvbiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy54c2RDb25uZWN0aW9uID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIEVmZmVjdGl2ZUlucHV0UG9saWN5IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgImVmZmVjdGl2ZUlucHV0UG9saWN5Iik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIEVmZmVjdGl2ZU91dHB1dFBvbGljeSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJlZmZlY3RpdmVPdXRwdXRQb2xpY3kiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgT3BlcmF0aW9uIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgIm9wZXJhdGlvbiIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmlucHV0ID0gYXR0cmlidXRlcy5pbnB1dCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMub3V0cHV0ID0gYXR0cmlidXRlcy5vdXRwdXQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBSb290RWxlbWVudCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJyb290RWxlbWVudCIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBTb2FwQWN0aW9uIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgInNvYXBBY3Rpb24iKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgU29hcEFkZHJlc3MgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTk5FQ1RJT05fU0VUX05TX0lELCAic29hcEFkZHJlc3MiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgY29ubmVjdGlvbl9zZXRfVXJpIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgInVyaSIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBXc2RsQWRkcmVzcyBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJ3c2RsQWRkcmVzcyIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBXc2RsQ29ubmVjdGlvbiBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJ3c2RsQ29ubmVjdGlvbiIsIHRydWUpOwogICAgdGhpcy5kYXRhRGVzY3JpcHRpb24gPSBhdHRyaWJ1dGVzLmRhdGFEZXNjcmlwdGlvbiB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMuZWZmZWN0aXZlSW5wdXRQb2xpY3kgPSBudWxsOwogICAgdGhpcy5lZmZlY3RpdmVPdXRwdXRQb2xpY3kgPSBudWxsOwogICAgdGhpcy5vcGVyYXRpb24gPSBudWxsOwogICAgdGhpcy5zb2FwQWN0aW9uID0gbnVsbDsKICAgIHRoaXMuc29hcEFkZHJlc3MgPSBudWxsOwogICAgdGhpcy53c2RsQWRkcmVzcyA9IG51bGw7CiAgfQp9CmNsYXNzIFhtbENvbm5lY3Rpb24gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTk5FQ1RJT05fU0VUX05TX0lELCAieG1sQ29ubmVjdGlvbiIsIHRydWUpOwogICAgdGhpcy5kYXRhRGVzY3JpcHRpb24gPSBhdHRyaWJ1dGVzLmRhdGFEZXNjcmlwdGlvbiB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgWHNkQ29ubmVjdGlvbiBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJ4c2RDb25uZWN0aW9uIiwgdHJ1ZSk7CiAgICB0aGlzLmRhdGFEZXNjcmlwdGlvbiA9IGF0dHJpYnV0ZXMuZGF0YURlc2NyaXB0aW9uIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yb290RWxlbWVudCA9IG51bGw7CiAgICB0aGlzLnVyaSA9IG51bGw7CiAgfQp9CmNsYXNzIENvbm5lY3Rpb25TZXROYW1lc3BhY2UgewogIHN0YXRpYyBbJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoQ29ubmVjdGlvblNldE5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICByZXR1cm4gQ29ubmVjdGlvblNldE5hbWVzcGFjZVtuYW1lXShhdHRyaWJ1dGVzKTsKICAgIH0KICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQogIHN0YXRpYyBjb25uZWN0aW9uU2V0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbm5lY3Rpb25TZXQoYXR0cnMpOwogIH0KICBzdGF0aWMgZWZmZWN0aXZlSW5wdXRQb2xpY3koYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRWZmZWN0aXZlSW5wdXRQb2xpY3koYXR0cnMpOwogIH0KICBzdGF0aWMgZWZmZWN0aXZlT3V0cHV0UG9saWN5KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVmZmVjdGl2ZU91dHB1dFBvbGljeShhdHRycyk7CiAgfQogIHN0YXRpYyBvcGVyYXRpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT3BlcmF0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIHJvb3RFbGVtZW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFJvb3RFbGVtZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHNvYXBBY3Rpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU29hcEFjdGlvbihhdHRycyk7CiAgfQogIHN0YXRpYyBzb2FwQWRkcmVzcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBTb2FwQWRkcmVzcyhhdHRycyk7CiAgfQogIHN0YXRpYyB1cmkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgY29ubmVjdGlvbl9zZXRfVXJpKGF0dHJzKTsKICB9CiAgc3RhdGljIHdzZGxBZGRyZXNzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFdzZGxBZGRyZXNzKGF0dHJzKTsKICB9CiAgc3RhdGljIHdzZGxDb25uZWN0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFdzZGxDb25uZWN0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIHhtbENvbm5lY3Rpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgWG1sQ29ubmVjdGlvbihhdHRycyk7CiAgfQogIHN0YXRpYyB4c2RDb25uZWN0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFhzZENvbm5lY3Rpb24oYXR0cnMpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL2RhdGFzZXRzLmpzCgoKCmNvbnN0IERBVEFTRVRTX05TX0lEID0gTmFtZXNwYWNlSWRzLmRhdGFzZXRzLmlkOwpjbGFzcyBkYXRhc2V0c19EYXRhIGV4dGVuZHMgWG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihEQVRBU0VUU19OU19JRCwgImRhdGEiLCBhdHRyaWJ1dGVzKTsKICB9CiAgWyRpc05zQWdub3N0aWNdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQp9CmNsYXNzIERhdGFzZXRzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihEQVRBU0VUU19OU19JRCwgImRhdGFzZXRzIiwgdHJ1ZSk7CiAgICB0aGlzLmRhdGEgPSBudWxsOwogICAgdGhpcy5TaWduYXR1cmUgPSBudWxsOwogIH0KICBbJG9uQ2hpbGRdKGNoaWxkKSB7CiAgICBjb25zdCBuYW1lID0gY2hpbGRbJG5vZGVOYW1lXTsKICAgIGlmIChuYW1lID09PSAiZGF0YSIgJiYgY2hpbGRbJG5hbWVzcGFjZUlkXSA9PT0gREFUQVNFVFNfTlNfSUQgfHwgbmFtZSA9PT0gIlNpZ25hdHVyZSIgJiYgY2hpbGRbJG5hbWVzcGFjZUlkXSA9PT0gTmFtZXNwYWNlSWRzLnNpZ25hdHVyZS5pZCkgewogICAgICB0aGlzW25hbWVdID0gY2hpbGQ7CiAgICB9CiAgICB0aGlzWyRhcHBlbmRDaGlsZF0oY2hpbGQpOwogIH0KfQpjbGFzcyBEYXRhc2V0c05hbWVzcGFjZSB7CiAgc3RhdGljIFskYnVpbGRYRkFPYmplY3RdKG5hbWUsIGF0dHJpYnV0ZXMpIHsKICAgIGlmIChEYXRhc2V0c05hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICByZXR1cm4gRGF0YXNldHNOYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgZGF0YXNldHMoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBEYXRhc2V0cyhhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIGRhdGEoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBkYXRhc2V0c19EYXRhKGF0dHJpYnV0ZXMpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL2xvY2FsZV9zZXQuanMKCgoKY29uc3QgTE9DQUxFX1NFVF9OU19JRCA9IE5hbWVzcGFjZUlkcy5sb2NhbGVTZXQuaWQ7CmNsYXNzIENhbGVuZGFyU3ltYm9scyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImNhbGVuZGFyU3ltYm9scyIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gImdyZWdvcmlhbiI7CiAgICB0aGlzLmRheU5hbWVzID0gbmV3IFhGQU9iamVjdEFycmF5KDIpOwogICAgdGhpcy5lcmFOYW1lcyA9IG51bGw7CiAgICB0aGlzLm1lcmlkaWVtTmFtZXMgPSBudWxsOwogICAgdGhpcy5tb250aE5hbWVzID0gbmV3IFhGQU9iamVjdEFycmF5KDIpOwogIH0KfQpjbGFzcyBDdXJyZW5jeVN5bWJvbCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImN1cnJlbmN5U3ltYm9sIik7CiAgICB0aGlzLm5hbWUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5uYW1lLCBbInN5bWJvbCIsICJpc29uYW1lIiwgImRlY2ltYWwiXSk7CiAgfQp9CmNsYXNzIEN1cnJlbmN5U3ltYm9scyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImN1cnJlbmN5U3ltYm9scyIsIHRydWUpOwogICAgdGhpcy5jdXJyZW5jeVN5bWJvbCA9IG5ldyBYRkFPYmplY3RBcnJheSgzKTsKICB9Cn0KY2xhc3MgRGF0ZVBhdHRlcm4gZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJkYXRlUGF0dGVybiIpOwogICAgdGhpcy5uYW1lID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMubmFtZSwgWyJmdWxsIiwgImxvbmciLCAibWVkIiwgInNob3J0Il0pOwogIH0KfQpjbGFzcyBEYXRlUGF0dGVybnMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJkYXRlUGF0dGVybnMiLCB0cnVlKTsKICAgIHRoaXMuZGF0ZVBhdHRlcm4gPSBuZXcgWEZBT2JqZWN0QXJyYXkoNCk7CiAgfQp9CmNsYXNzIERhdGVUaW1lU3ltYm9scyBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJkYXRlVGltZVN5bWJvbHMiKTsKICB9Cn0KY2xhc3MgRGF5IGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZGF5Iik7CiAgfQp9CmNsYXNzIERheU5hbWVzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZGF5TmFtZXMiLCB0cnVlKTsKICAgIHRoaXMuYWJiciA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmFiYnIsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmRheSA9IG5ldyBYRkFPYmplY3RBcnJheSg3KTsKICB9Cn0KY2xhc3MgRXJhIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZXJhIik7CiAgfQp9CmNsYXNzIEVyYU5hbWVzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZXJhTmFtZXMiLCB0cnVlKTsKICAgIHRoaXMuZXJhID0gbmV3IFhGQU9iamVjdEFycmF5KDIpOwogIH0KfQpjbGFzcyBsb2NhbGVfc2V0X0xvY2FsZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImxvY2FsZSIsIHRydWUpOwogICAgdGhpcy5kZXNjID0gYXR0cmlidXRlcy5kZXNjIHx8ICIiOwogICAgdGhpcy5uYW1lID0gImlzb25hbWUiOwogICAgdGhpcy5jYWxlbmRhclN5bWJvbHMgPSBudWxsOwogICAgdGhpcy5jdXJyZW5jeVN5bWJvbHMgPSBudWxsOwogICAgdGhpcy5kYXRlUGF0dGVybnMgPSBudWxsOwogICAgdGhpcy5kYXRlVGltZVN5bWJvbHMgPSBudWxsOwogICAgdGhpcy5udW1iZXJQYXR0ZXJucyA9IG51bGw7CiAgICB0aGlzLm51bWJlclN5bWJvbHMgPSBudWxsOwogICAgdGhpcy50aW1lUGF0dGVybnMgPSBudWxsOwogICAgdGhpcy50eXBlRmFjZXMgPSBudWxsOwogIH0KfQpjbGFzcyBsb2NhbGVfc2V0X0xvY2FsZVNldCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImxvY2FsZVNldCIsIHRydWUpOwogICAgdGhpcy5sb2NhbGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgTWVyaWRpZW0gZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJtZXJpZGllbSIpOwogIH0KfQpjbGFzcyBNZXJpZGllbU5hbWVzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAibWVyaWRpZW1OYW1lcyIsIHRydWUpOwogICAgdGhpcy5tZXJpZGllbSA9IG5ldyBYRkFPYmplY3RBcnJheSgyKTsKICB9Cn0KY2xhc3MgTW9udGggZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJtb250aCIpOwogIH0KfQpjbGFzcyBNb250aE5hbWVzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAibW9udGhOYW1lcyIsIHRydWUpOwogICAgdGhpcy5hYmJyID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuYWJiciwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMubW9udGggPSBuZXcgWEZBT2JqZWN0QXJyYXkoMTIpOwogIH0KfQpjbGFzcyBOdW1iZXJQYXR0ZXJuIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAibnVtYmVyUGF0dGVybiIpOwogICAgdGhpcy5uYW1lID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMubmFtZSwgWyJmdWxsIiwgImxvbmciLCAibWVkIiwgInNob3J0Il0pOwogIH0KfQpjbGFzcyBOdW1iZXJQYXR0ZXJucyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgIm51bWJlclBhdHRlcm5zIiwgdHJ1ZSk7CiAgICB0aGlzLm51bWJlclBhdHRlcm4gPSBuZXcgWEZBT2JqZWN0QXJyYXkoNCk7CiAgfQp9CmNsYXNzIE51bWJlclN5bWJvbCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgIm51bWJlclN5bWJvbCIpOwogICAgdGhpcy5uYW1lID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMubmFtZSwgWyJkZWNpbWFsIiwgImdyb3VwaW5nIiwgInBlcmNlbnQiLCAibWludXMiLCAiemVybyJdKTsKICB9Cn0KY2xhc3MgTnVtYmVyU3ltYm9scyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgIm51bWJlclN5bWJvbHMiLCB0cnVlKTsKICAgIHRoaXMubnVtYmVyU3ltYm9sID0gbmV3IFhGQU9iamVjdEFycmF5KDUpOwogIH0KfQpjbGFzcyBUaW1lUGF0dGVybiBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgInRpbWVQYXR0ZXJuIik7CiAgICB0aGlzLm5hbWUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5uYW1lLCBbImZ1bGwiLCAibG9uZyIsICJtZWQiLCAic2hvcnQiXSk7CiAgfQp9CmNsYXNzIFRpbWVQYXR0ZXJucyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgInRpbWVQYXR0ZXJucyIsIHRydWUpOwogICAgdGhpcy50aW1lUGF0dGVybiA9IG5ldyBYRkFPYmplY3RBcnJheSg0KTsKICB9Cn0KY2xhc3MgVHlwZUZhY2UgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJ0eXBlRmFjZSIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHwgIiI7CiAgfQp9CmNsYXNzIFR5cGVGYWNlcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgInR5cGVGYWNlcyIsIHRydWUpOwogICAgdGhpcy50eXBlRmFjZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBMb2NhbGVTZXROYW1lc3BhY2UgewogIHN0YXRpYyBbJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoTG9jYWxlU2V0TmFtZXNwYWNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIHJldHVybiBMb2NhbGVTZXROYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgY2FsZW5kYXJTeW1ib2xzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENhbGVuZGFyU3ltYm9scyhhdHRycyk7CiAgfQogIHN0YXRpYyBjdXJyZW5jeVN5bWJvbChhdHRycykgewogICAgcmV0dXJuIG5ldyBDdXJyZW5jeVN5bWJvbChhdHRycyk7CiAgfQogIHN0YXRpYyBjdXJyZW5jeVN5bWJvbHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ3VycmVuY3lTeW1ib2xzKGF0dHJzKTsKICB9CiAgc3RhdGljIGRhdGVQYXR0ZXJuKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGVQYXR0ZXJuKGF0dHJzKTsKICB9CiAgc3RhdGljIGRhdGVQYXR0ZXJucyhhdHRycykgewogICAgcmV0dXJuIG5ldyBEYXRlUGF0dGVybnMoYXR0cnMpOwogIH0KICBzdGF0aWMgZGF0ZVRpbWVTeW1ib2xzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGVUaW1lU3ltYm9scyhhdHRycyk7CiAgfQogIHN0YXRpYyBkYXkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRGF5KGF0dHJzKTsKICB9CiAgc3RhdGljIGRheU5hbWVzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERheU5hbWVzKGF0dHJzKTsKICB9CiAgc3RhdGljIGVyYShhdHRycykgewogICAgcmV0dXJuIG5ldyBFcmEoYXR0cnMpOwogIH0KICBzdGF0aWMgZXJhTmFtZXMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRXJhTmFtZXMoYXR0cnMpOwogIH0KICBzdGF0aWMgbG9jYWxlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IGxvY2FsZV9zZXRfTG9jYWxlKGF0dHJzKTsKICB9CiAgc3RhdGljIGxvY2FsZVNldChhdHRycykgewogICAgcmV0dXJuIG5ldyBsb2NhbGVfc2V0X0xvY2FsZVNldChhdHRycyk7CiAgfQogIHN0YXRpYyBtZXJpZGllbShhdHRycykgewogICAgcmV0dXJuIG5ldyBNZXJpZGllbShhdHRycyk7CiAgfQogIHN0YXRpYyBtZXJpZGllbU5hbWVzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1lcmlkaWVtTmFtZXMoYXR0cnMpOwogIH0KICBzdGF0aWMgbW9udGgoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTW9udGgoYXR0cnMpOwogIH0KICBzdGF0aWMgbW9udGhOYW1lcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBNb250aE5hbWVzKGF0dHJzKTsKICB9CiAgc3RhdGljIG51bWJlclBhdHRlcm4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTnVtYmVyUGF0dGVybihhdHRycyk7CiAgfQogIHN0YXRpYyBudW1iZXJQYXR0ZXJucyhhdHRycykgewogICAgcmV0dXJuIG5ldyBOdW1iZXJQYXR0ZXJucyhhdHRycyk7CiAgfQogIHN0YXRpYyBudW1iZXJTeW1ib2woYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTnVtYmVyU3ltYm9sKGF0dHJzKTsKICB9CiAgc3RhdGljIG51bWJlclN5bWJvbHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTnVtYmVyU3ltYm9scyhhdHRycyk7CiAgfQogIHN0YXRpYyB0aW1lUGF0dGVybihhdHRycykgewogICAgcmV0dXJuIG5ldyBUaW1lUGF0dGVybihhdHRycyk7CiAgfQogIHN0YXRpYyB0aW1lUGF0dGVybnMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVGltZVBhdHRlcm5zKGF0dHJzKTsKICB9CiAgc3RhdGljIHR5cGVGYWNlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFR5cGVGYWNlKGF0dHJzKTsKICB9CiAgc3RhdGljIHR5cGVGYWNlcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBUeXBlRmFjZXMoYXR0cnMpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL3NpZ25hdHVyZS5qcwoKCmNvbnN0IFNJR05BVFVSRV9OU19JRCA9IE5hbWVzcGFjZUlkcy5zaWduYXR1cmUuaWQ7CmNsYXNzIHNpZ25hdHVyZV9TaWduYXR1cmUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFNJR05BVFVSRV9OU19JRCwgInNpZ25hdHVyZSIsIHRydWUpOwogIH0KfQpjbGFzcyBTaWduYXR1cmVOYW1lc3BhY2UgewogIHN0YXRpYyBbJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoU2lnbmF0dXJlTmFtZXNwYWNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIHJldHVybiBTaWduYXR1cmVOYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgc2lnbmF0dXJlKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgc2lnbmF0dXJlX1NpZ25hdHVyZShhdHRyaWJ1dGVzKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3hmYS9zdHlsZXNoZWV0LmpzCgoKY29uc3QgU1RZTEVTSEVFVF9OU19JRCA9IE5hbWVzcGFjZUlkcy5zdHlsZXNoZWV0LmlkOwpjbGFzcyBTdHlsZXNoZWV0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihTVFlMRVNIRUVUX05TX0lELCAic3R5bGVzaGVldCIsIHRydWUpOwogIH0KfQpjbGFzcyBTdHlsZXNoZWV0TmFtZXNwYWNlIHsKICBzdGF0aWMgWyRidWlsZFhGQU9iamVjdF0obmFtZSwgYXR0cmlidXRlcykgewogICAgaWYgKFN0eWxlc2hlZXROYW1lc3BhY2UuaGFzT3duUHJvcGVydHkobmFtZSkpIHsKICAgICAgcmV0dXJuIFN0eWxlc2hlZXROYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgc3R5bGVzaGVldChhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IFN0eWxlc2hlZXQoYXR0cmlidXRlcyk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEveGRwLmpzCgoKCmNvbnN0IFhEUF9OU19JRCA9IE5hbWVzcGFjZUlkcy54ZHAuaWQ7CmNsYXNzIHhkcF9YZHAgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFhEUF9OU19JRCwgInhkcCIsIHRydWUpOwogICAgdGhpcy51dWlkID0gYXR0cmlidXRlcy51dWlkIHx8ICIiOwogICAgdGhpcy50aW1lU3RhbXAgPSBhdHRyaWJ1dGVzLnRpbWVTdGFtcCB8fCAiIjsKICAgIHRoaXMuY29uZmlnID0gbnVsbDsKICAgIHRoaXMuY29ubmVjdGlvblNldCA9IG51bGw7CiAgICB0aGlzLmRhdGFzZXRzID0gbnVsbDsKICAgIHRoaXMubG9jYWxlU2V0ID0gbnVsbDsKICAgIHRoaXMuc3R5bGVzaGVldCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50ZW1wbGF0ZSA9IG51bGw7CiAgfQogIFskb25DaGlsZENoZWNrXShjaGlsZCkgewogICAgY29uc3QgbnMgPSBOYW1lc3BhY2VJZHNbY2hpbGRbJG5vZGVOYW1lXV07CiAgICByZXR1cm4gbnMgJiYgY2hpbGRbJG5hbWVzcGFjZUlkXSA9PT0gbnMuaWQ7CiAgfQp9CmNsYXNzIFhkcE5hbWVzcGFjZSB7CiAgc3RhdGljIFskYnVpbGRYRkFPYmplY3RdKG5hbWUsIGF0dHJpYnV0ZXMpIHsKICAgIGlmIChYZHBOYW1lc3BhY2UuaGFzT3duUHJvcGVydHkobmFtZSkpIHsKICAgICAgcmV0dXJuIFhkcE5hbWVzcGFjZVtuYW1lXShhdHRyaWJ1dGVzKTsKICAgIH0KICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQogIHN0YXRpYyB4ZHAoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyB4ZHBfWGRwKGF0dHJpYnV0ZXMpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL3hodG1sLmpzCgoKCgoKY29uc3QgWEhUTUxfTlNfSUQgPSBOYW1lc3BhY2VJZHMueGh0bWwuaWQ7CmNvbnN0ICRyaWNoVGV4dCA9IFN5bWJvbCgpOwpjb25zdCBWQUxJRF9TVFlMRVMgPSBuZXcgU2V0KFsiY29sb3IiLCAiZm9udCIsICJmb250LWZhbWlseSIsICJmb250LXNpemUiLCAiZm9udC1zdHJldGNoIiwgImZvbnQtc3R5bGUiLCAiZm9udC13ZWlnaHQiLCAibWFyZ2luIiwgIm1hcmdpbi1ib3R0b20iLCAibWFyZ2luLWxlZnQiLCAibWFyZ2luLXJpZ2h0IiwgIm1hcmdpbi10b3AiLCAibGV0dGVyLXNwYWNpbmciLCAibGluZS1oZWlnaHQiLCAib3JwaGFucyIsICJwYWdlLWJyZWFrLWFmdGVyIiwgInBhZ2UtYnJlYWstYmVmb3JlIiwgInBhZ2UtYnJlYWstaW5zaWRlIiwgInRhYi1pbnRlcnZhbCIsICJ0YWItc3RvcCIsICJ0ZXh0LWFsaWduIiwgInRleHQtZGVjb3JhdGlvbiIsICJ0ZXh0LWluZGVudCIsICJ2ZXJ0aWNhbC1hbGlnbiIsICJ3aWRvd3MiLCAia2VybmluZy1tb2RlIiwgInhmYS1mb250LWhvcml6b250YWwtc2NhbGUiLCAieGZhLWZvbnQtdmVydGljYWwtc2NhbGUiLCAieGZhLXNwYWNlcnVuIiwgInhmYS10YWItc3RvcHMiXSk7CmNvbnN0IFN0eWxlTWFwcGluZyA9IG5ldyBNYXAoW1sicGFnZS1icmVhay1hZnRlciIsICJicmVha0FmdGVyIl0sIFsicGFnZS1icmVhay1iZWZvcmUiLCAiYnJlYWtCZWZvcmUiXSwgWyJwYWdlLWJyZWFrLWluc2lkZSIsICJicmVha0luc2lkZSJdLCBbImtlcm5pbmctbW9kZSIsIHZhbHVlID0+IHZhbHVlID09PSAibm9uZSIgPyAibm9uZSIgOiAibm9ybWFsIl0sIFsieGZhLWZvbnQtaG9yaXpvbnRhbC1zY2FsZSIsIHZhbHVlID0+IGBzY2FsZVgoJHtNYXRoLm1heCgwLCBwYXJzZUludCh2YWx1ZSkgLyAxMDApLnRvRml4ZWQoMil9KWBdLCBbInhmYS1mb250LXZlcnRpY2FsLXNjYWxlIiwgdmFsdWUgPT4gYHNjYWxlWSgke01hdGgubWF4KDAsIHBhcnNlSW50KHZhbHVlKSAvIDEwMCkudG9GaXhlZCgyKX0pYF0sIFsieGZhLXNwYWNlcnVuIiwgIiJdLCBbInhmYS10YWItc3RvcHMiLCAiIl0sIFsiZm9udC1zaXplIiwgKHZhbHVlLCBvcmlnaW5hbCkgPT4gewogIHZhbHVlID0gb3JpZ2luYWwuZm9udFNpemUgPSBNYXRoLmFicyhnZXRNZWFzdXJlbWVudCh2YWx1ZSkpOwogIHJldHVybiBtZWFzdXJlVG9TdHJpbmcoMC45OSAqIHZhbHVlKTsKfV0sIFsibGV0dGVyLXNwYWNpbmciLCB2YWx1ZSA9PiBtZWFzdXJlVG9TdHJpbmcoZ2V0TWVhc3VyZW1lbnQodmFsdWUpKV0sIFsibGluZS1oZWlnaHQiLCB2YWx1ZSA9PiBtZWFzdXJlVG9TdHJpbmcoZ2V0TWVhc3VyZW1lbnQodmFsdWUpKV0sIFsibWFyZ2luIiwgdmFsdWUgPT4gbWVhc3VyZVRvU3RyaW5nKGdldE1lYXN1cmVtZW50KHZhbHVlKSldLCBbIm1hcmdpbi1ib3R0b20iLCB2YWx1ZSA9PiBtZWFzdXJlVG9TdHJpbmcoZ2V0TWVhc3VyZW1lbnQodmFsdWUpKV0sIFsibWFyZ2luLWxlZnQiLCB2YWx1ZSA9PiBtZWFzdXJlVG9TdHJpbmcoZ2V0TWVhc3VyZW1lbnQodmFsdWUpKV0sIFsibWFyZ2luLXJpZ2h0IiwgdmFsdWUgPT4gbWVhc3VyZVRvU3RyaW5nKGdldE1lYXN1cmVtZW50KHZhbHVlKSldLCBbIm1hcmdpbi10b3AiLCB2YWx1ZSA9PiBtZWFzdXJlVG9TdHJpbmcoZ2V0TWVhc3VyZW1lbnQodmFsdWUpKV0sIFsidGV4dC1pbmRlbnQiLCB2YWx1ZSA9PiBtZWFzdXJlVG9TdHJpbmcoZ2V0TWVhc3VyZW1lbnQodmFsdWUpKV0sIFsiZm9udC1mYW1pbHkiLCB2YWx1ZSA9PiB2YWx1ZV0sIFsidmVydGljYWwtYWxpZ24iLCB2YWx1ZSA9PiBtZWFzdXJlVG9TdHJpbmcoZ2V0TWVhc3VyZW1lbnQodmFsdWUpKV1dKTsKY29uc3Qgc3BhY2VzUmVnRXhwID0gL1xzKy9nOwpjb25zdCBjcmxmUmVnRXhwID0gL1tcclxuXSsvZzsKY29uc3QgY3JsZkZvclJpY2hUZXh0UmVnRXhwID0gL1xyXG4/L2c7CmZ1bmN0aW9uIG1hcFN0eWxlKHN0eWxlU3RyLCBub2RlLCByaWNoVGV4dCkgewogIGNvbnN0IHN0eWxlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBpZiAoIXN0eWxlU3RyKSB7CiAgICByZXR1cm4gc3R5bGU7CiAgfQogIGNvbnN0IG9yaWdpbmFsID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBzdHlsZVN0ci5zcGxpdCgiOyIpLm1hcChzID0+IHMuc3BsaXQoIjoiLCAyKSkpIHsKICAgIGNvbnN0IG1hcHBpbmcgPSBTdHlsZU1hcHBpbmcuZ2V0KGtleSk7CiAgICBpZiAobWFwcGluZyA9PT0gIiIpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBsZXQgbmV3VmFsdWUgPSB2YWx1ZTsKICAgIGlmIChtYXBwaW5nKSB7CiAgICAgIG5ld1ZhbHVlID0gdHlwZW9mIG1hcHBpbmcgPT09ICJzdHJpbmciID8gbWFwcGluZyA6IG1hcHBpbmcodmFsdWUsIG9yaWdpbmFsKTsKICAgIH0KICAgIGlmIChrZXkuZW5kc1dpdGgoInNjYWxlIikpIHsKICAgICAgc3R5bGUudHJhbnNmb3JtID0gc3R5bGUudHJhbnNmb3JtID8gYCR7c3R5bGVba2V5XX0gJHtuZXdWYWx1ZX1gIDogbmV3VmFsdWU7CiAgICB9IGVsc2UgewogICAgICBzdHlsZVtrZXkucmVwbGFjZUFsbCgvLShbYS16QS1aXSkvZywgKF8sIHgpID0+IHgudG9VcHBlckNhc2UoKSldID0gbmV3VmFsdWU7CiAgICB9CiAgfQogIGlmIChzdHlsZS5mb250RmFtaWx5KSB7CiAgICBzZXRGb250RmFtaWx5KHsKICAgICAgdHlwZWZhY2U6IHN0eWxlLmZvbnRGYW1pbHksCiAgICAgIHdlaWdodDogc3R5bGUuZm9udFdlaWdodCB8fCAibm9ybWFsIiwKICAgICAgcG9zdHVyZTogc3R5bGUuZm9udFN0eWxlIHx8ICJub3JtYWwiLAogICAgICBzaXplOiBvcmlnaW5hbC5mb250U2l6ZSB8fCAwCiAgICB9LCBub2RlLCBub2RlWyRnbG9iYWxEYXRhXS5mb250RmluZGVyLCBzdHlsZSk7CiAgfQogIGlmIChyaWNoVGV4dCAmJiBzdHlsZS52ZXJ0aWNhbEFsaWduICYmIHN0eWxlLnZlcnRpY2FsQWxpZ24gIT09ICIwcHgiICYmIHN0eWxlLmZvbnRTaXplKSB7CiAgICBjb25zdCBTVUJfU1VQRVJfU0NSSVBUX0ZBQ1RPUiA9IDAuNTgzOwogICAgY29uc3QgVkVSVElDQUxfRkFDVE9SID0gMC4zMzM7CiAgICBjb25zdCBmb250U2l6ZSA9IGdldE1lYXN1cmVtZW50KHN0eWxlLmZvbnRTaXplKTsKICAgIHN0eWxlLmZvbnRTaXplID0gbWVhc3VyZVRvU3RyaW5nKGZvbnRTaXplICogU1VCX1NVUEVSX1NDUklQVF9GQUNUT1IpOwogICAgc3R5bGUudmVydGljYWxBbGlnbiA9IG1lYXN1cmVUb1N0cmluZyhNYXRoLnNpZ24oZ2V0TWVhc3VyZW1lbnQoc3R5bGUudmVydGljYWxBbGlnbikpICogZm9udFNpemUgKiBWRVJUSUNBTF9GQUNUT1IpOwogIH0KICBpZiAocmljaFRleHQgJiYgc3R5bGUuZm9udFNpemUpIHsKICAgIHN0eWxlLmZvbnRTaXplID0gYGNhbGMoJHtzdHlsZS5mb250U2l6ZX0gKiB2YXIoLS10b3RhbC1zY2FsZS1mYWN0b3IpKWA7CiAgfQogIGZpeFRleHRJbmRlbnQoc3R5bGUpOwogIHJldHVybiBzdHlsZTsKfQpmdW5jdGlvbiBjaGVja1N0eWxlKG5vZGUpIHsKICBpZiAoIW5vZGUuc3R5bGUpIHsKICAgIHJldHVybiAiIjsKICB9CiAgcmV0dXJuIG5vZGUuc3R5bGUuc3BsaXQoIjsiKS5maWx0ZXIocyA9PiAhIXMudHJpbSgpKS5tYXAocyA9PiBzLnNwbGl0KCI6IiwgMikubWFwKHQgPT4gdC50cmltKCkpKS5maWx0ZXIoKFtrZXksIHZhbHVlXSkgPT4gewogICAgaWYgKGtleSA9PT0gImZvbnQtZmFtaWx5IikgewogICAgICBub2RlWyRnbG9iYWxEYXRhXS51c2VkVHlwZWZhY2VzLmFkZCh2YWx1ZSk7CiAgICB9CiAgICByZXR1cm4gVkFMSURfU1RZTEVTLmhhcyhrZXkpOwogIH0pLm1hcChrdiA9PiBrdi5qb2luKCI6IikpLmpvaW4oIjsiKTsKfQpjb25zdCBOb1doaXRlcyA9IG5ldyBTZXQoWyJib2R5IiwgImh0bWwiXSk7CmNsYXNzIFhodG1sT2JqZWN0IGV4dGVuZHMgWG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzLCBuYW1lKSB7CiAgICBzdXBlcihYSFRNTF9OU19JRCwgbmFtZSk7CiAgICB0aGlzWyRyaWNoVGV4dF0gPSBmYWxzZTsKICAgIHRoaXMuc3R5bGUgPSBhdHRyaWJ1dGVzLnN0eWxlIHx8ICIiOwogIH0KICBbJGNsZWFuXShidWlsZGVyKSB7CiAgICBzdXBlclskY2xlYW5dKGJ1aWxkZXIpOwogICAgdGhpcy5zdHlsZSA9IGNoZWNrU3R5bGUodGhpcyk7CiAgfQogIFskYWNjZXB0V2hpdGVzcGFjZV0oKSB7CiAgICByZXR1cm4gIU5vV2hpdGVzLmhhcyh0aGlzWyRub2RlTmFtZV0pOwogIH0KICBbJG9uVGV4dF0oc3RyLCByaWNoVGV4dCA9IGZhbHNlKSB7CiAgICBpZiAoIXJpY2hUZXh0KSB7CiAgICAgIHN0ciA9IHN0ci5yZXBsYWNlQWxsKGNybGZSZWdFeHAsICIiKTsKICAgICAgaWYgKCF0aGlzLnN0eWxlLmluY2x1ZGVzKCJ4ZmEtc3BhY2VydW46eWVzIikpIHsKICAgICAgICBzdHIgPSBzdHIucmVwbGFjZUFsbChzcGFjZXNSZWdFeHAsICIgIik7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRoaXNbJHJpY2hUZXh0XSA9IHRydWU7CiAgICB9CiAgICBpZiAoc3RyKSB7CiAgICAgIHRoaXNbJGNvbnRlbnRdICs9IHN0cjsKICAgIH0KICB9CiAgWyRwdXNoR2x5cGhzXShtZWFzdXJlLCBtdXN0UG9wID0gdHJ1ZSkgewogICAgY29uc3QgeGZhRm9udCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBjb25zdCBtYXJnaW4gPSB7CiAgICAgIHRvcDogTmFOLAogICAgICBib3R0b206IE5hTiwKICAgICAgbGVmdDogTmFOLAogICAgICByaWdodDogTmFOCiAgICB9OwogICAgbGV0IGxpbmVIZWlnaHQgPSBudWxsOwogICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgdGhpcy5zdHlsZS5zcGxpdCgiOyIpLm1hcChzID0+IHMuc3BsaXQoIjoiLCAyKSkpIHsKICAgICAgc3dpdGNoIChrZXkpIHsKICAgICAgICBjYXNlICJmb250LWZhbWlseSI6CiAgICAgICAgICB4ZmFGb250LnR5cGVmYWNlID0gc3RyaXBRdW90ZXModmFsdWUpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZm9udC1zaXplIjoKICAgICAgICAgIHhmYUZvbnQuc2l6ZSA9IGdldE1lYXN1cmVtZW50KHZhbHVlKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImZvbnQtd2VpZ2h0IjoKICAgICAgICAgIHhmYUZvbnQud2VpZ2h0ID0gdmFsdWU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJmb250LXN0eWxlIjoKICAgICAgICAgIHhmYUZvbnQucG9zdHVyZSA9IHZhbHVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibGV0dGVyLXNwYWNpbmciOgogICAgICAgICAgeGZhRm9udC5sZXR0ZXJTcGFjaW5nID0gZ2V0TWVhc3VyZW1lbnQodmFsdWUpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibWFyZ2luIjoKICAgICAgICAgIGNvbnN0IHZhbHVlcyA9IHZhbHVlLnNwbGl0KC8gXHQvKS5tYXAoeCA9PiBnZXRNZWFzdXJlbWVudCh4KSk7CiAgICAgICAgICBzd2l0Y2ggKHZhbHVlcy5sZW5ndGgpIHsKICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgIG1hcmdpbi50b3AgPSBtYXJnaW4uYm90dG9tID0gbWFyZ2luLmxlZnQgPSBtYXJnaW4ucmlnaHQgPSB2YWx1ZXNbMF07CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgICBtYXJnaW4udG9wID0gbWFyZ2luLmJvdHRvbSA9IHZhbHVlc1swXTsKICAgICAgICAgICAgICBtYXJnaW4ubGVmdCA9IG1hcmdpbi5yaWdodCA9IHZhbHVlc1sxXTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICAgIG1hcmdpbi50b3AgPSB2YWx1ZXNbMF07CiAgICAgICAgICAgICAgbWFyZ2luLmJvdHRvbSA9IHZhbHVlc1syXTsKICAgICAgICAgICAgICBtYXJnaW4ubGVmdCA9IG1hcmdpbi5yaWdodCA9IHZhbHVlc1sxXTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICAgIG1hcmdpbi50b3AgPSB2YWx1ZXNbMF07CiAgICAgICAgICAgICAgbWFyZ2luLmxlZnQgPSB2YWx1ZXNbMV07CiAgICAgICAgICAgICAgbWFyZ2luLmJvdHRvbSA9IHZhbHVlc1syXTsKICAgICAgICAgICAgICBtYXJnaW4ucmlnaHQgPSB2YWx1ZXNbM107CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJtYXJnaW4tdG9wIjoKICAgICAgICAgIG1hcmdpbi50b3AgPSBnZXRNZWFzdXJlbWVudCh2YWx1ZSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJtYXJnaW4tYm90dG9tIjoKICAgICAgICAgIG1hcmdpbi5ib3R0b20gPSBnZXRNZWFzdXJlbWVudCh2YWx1ZSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJtYXJnaW4tbGVmdCI6CiAgICAgICAgICBtYXJnaW4ubGVmdCA9IGdldE1lYXN1cmVtZW50KHZhbHVlKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm1hcmdpbi1yaWdodCI6CiAgICAgICAgICBtYXJnaW4ucmlnaHQgPSBnZXRNZWFzdXJlbWVudCh2YWx1ZSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJsaW5lLWhlaWdodCI6CiAgICAgICAgICBsaW5lSGVpZ2h0ID0gZ2V0TWVhc3VyZW1lbnQodmFsdWUpOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIG1lYXN1cmUucHVzaERhdGEoeGZhRm9udCwgbWFyZ2luLCBsaW5lSGVpZ2h0KTsKICAgIGlmICh0aGlzWyRjb250ZW50XSkgewogICAgICBtZWFzdXJlLmFkZFN0cmluZyh0aGlzWyRjb250ZW50XSk7CiAgICB9IGVsc2UgewogICAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXNbJGdldENoaWxkcmVuXSgpKSB7CiAgICAgICAgaWYgKGNoaWxkWyRub2RlTmFtZV0gPT09ICIjdGV4dCIpIHsKICAgICAgICAgIG1lYXN1cmUuYWRkU3RyaW5nKGNoaWxkWyRjb250ZW50XSk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY2hpbGRbJHB1c2hHbHlwaHNdKG1lYXN1cmUpOwogICAgICB9CiAgICB9CiAgICBpZiAobXVzdFBvcCkgewogICAgICBtZWFzdXJlLnBvcEZvbnQoKTsKICAgIH0KICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgdGhpc1skZXh0cmFdID0gewogICAgICBjaGlsZHJlbgogICAgfTsKICAgIHRoaXNbJGNoaWxkcmVuVG9IVE1MXSh7fSk7CiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID09PSAwICYmICF0aGlzWyRjb250ZW50XSkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGxldCB2YWx1ZTsKICAgIGlmICh0aGlzWyRyaWNoVGV4dF0pIHsKICAgICAgdmFsdWUgPSB0aGlzWyRjb250ZW50XSA/IHRoaXNbJGNvbnRlbnRdLnJlcGxhY2VBbGwoY3JsZkZvclJpY2hUZXh0UmVnRXhwLCAiXG4iKSA6IHVuZGVmaW5lZDsKICAgIH0gZWxzZSB7CiAgICAgIHZhbHVlID0gdGhpc1skY29udGVudF0gfHwgdW5kZWZpbmVkOwogICAgfQogICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6IHRoaXNbJG5vZGVOYW1lXSwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGhyZWY6IHRoaXMuaHJlZiwKICAgICAgICBzdHlsZTogbWFwU3R5bGUodGhpcy5zdHlsZSwgdGhpcywgdGhpc1skcmljaFRleHRdKQogICAgICB9LAogICAgICBjaGlsZHJlbiwKICAgICAgdmFsdWUKICAgIH0pOwogIH0KfQpjbGFzcyBBIGV4dGVuZHMgWGh0bWxPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKGF0dHJpYnV0ZXMsICJhIik7CiAgICB0aGlzLmhyZWYgPSBmaXhVUkwoYXR0cmlidXRlcy5ocmVmKSB8fCAiIjsKICB9Cn0KY2xhc3MgQiBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAiYiIpOwogIH0KICBbJHB1c2hHbHlwaHNdKG1lYXN1cmUpIHsKICAgIG1lYXN1cmUucHVzaEZvbnQoewogICAgICB3ZWlnaHQ6ICJib2xkIgogICAgfSk7CiAgICBzdXBlclskcHVzaEdseXBoc10obWVhc3VyZSk7CiAgICBtZWFzdXJlLnBvcEZvbnQoKTsKICB9Cn0KY2xhc3MgQm9keSBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAiYm9keSIpOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IHJlcyA9IHN1cGVyWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKTsKICAgIGNvbnN0IHsKICAgICAgaHRtbAogICAgfSA9IHJlczsKICAgIGlmICghaHRtbCkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGh0bWwubmFtZSA9ICJkaXYiOwogICAgaHRtbC5hdHRyaWJ1dGVzLmNsYXNzID0gWyJ4ZmFSaWNoIl07CiAgICByZXR1cm4gcmVzOwogIH0KfQpjbGFzcyBCciBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAiYnIiKTsKICB9CiAgWyR0ZXh0XSgpIHsKICAgIHJldHVybiAiXG4iOwogIH0KICBbJHB1c2hHbHlwaHNdKG1lYXN1cmUpIHsKICAgIG1lYXN1cmUuYWRkU3RyaW5nKCJcbiIpOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICBuYW1lOiAiYnIiCiAgICB9KTsKICB9Cn0KY2xhc3MgSHRtbCBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAiaHRtbCIpOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IGNoaWxkcmVuID0gW107CiAgICB0aGlzWyRleHRyYV0gPSB7CiAgICAgIGNoaWxkcmVuCiAgICB9OwogICAgdGhpc1skY2hpbGRyZW5Ub0hUTUxdKHt9KTsKICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgICAgbmFtZTogImRpdiIsCiAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgY2xhc3M6IFsieGZhUmljaCJdLAogICAgICAgICAgc3R5bGU6IHt9CiAgICAgICAgfSwKICAgICAgICB2YWx1ZTogdGhpc1skY29udGVudF0gfHwgIiIKICAgICAgfSk7CiAgICB9CiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID09PSAxKSB7CiAgICAgIGNvbnN0IGNoaWxkID0gY2hpbGRyZW5bMF07CiAgICAgIGlmIChjaGlsZC5hdHRyaWJ1dGVzPy5jbGFzcy5pbmNsdWRlcygieGZhUmljaCIpKSB7CiAgICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhjaGlsZCk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICBuYW1lOiAiZGl2IiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBbInhmYVJpY2giXSwKICAgICAgICBzdHlsZToge30KICAgICAgfSwKICAgICAgY2hpbGRyZW4KICAgIH0pOwogIH0KfQpjbGFzcyBJIGV4dGVuZHMgWGh0bWxPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKGF0dHJpYnV0ZXMsICJpIik7CiAgfQogIFskcHVzaEdseXBoc10obWVhc3VyZSkgewogICAgbWVhc3VyZS5wdXNoRm9udCh7CiAgICAgIHBvc3R1cmU6ICJpdGFsaWMiCiAgICB9KTsKICAgIHN1cGVyWyRwdXNoR2x5cGhzXShtZWFzdXJlKTsKICAgIG1lYXN1cmUucG9wRm9udCgpOwogIH0KfQpjbGFzcyBMaSBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAibGkiKTsKICB9Cn0KY2xhc3MgT2wgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgIm9sIik7CiAgfQp9CmNsYXNzIFAgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgInAiKTsKICB9CiAgWyRwdXNoR2x5cGhzXShtZWFzdXJlKSB7CiAgICBzdXBlclskcHVzaEdseXBoc10obWVhc3VyZSwgZmFsc2UpOwogICAgbWVhc3VyZS5hZGRTdHJpbmcoIlxuIik7CiAgICBtZWFzdXJlLmFkZFBhcmEoKTsKICAgIG1lYXN1cmUucG9wRm9udCgpOwogIH0KICBbJHRleHRdKCkgewogICAgY29uc3Qgc2libGluZ3MgPSB0aGlzWyRnZXRQYXJlbnRdKClbJGdldENoaWxkcmVuXSgpOwogICAgaWYgKHNpYmxpbmdzLmF0KC0xKSA9PT0gdGhpcykgewogICAgICByZXR1cm4gc3VwZXJbJHRleHRdKCk7CiAgICB9CiAgICByZXR1cm4gc3VwZXJbJHRleHRdKCkgKyAiXG4iOwogIH0KfQpjbGFzcyBTcGFuIGV4dGVuZHMgWGh0bWxPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKGF0dHJpYnV0ZXMsICJzcGFuIik7CiAgfQp9CmNsYXNzIFN1YiBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAic3ViIik7CiAgfQp9CmNsYXNzIFN1cCBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAic3VwIik7CiAgfQp9CmNsYXNzIFVsIGV4dGVuZHMgWGh0bWxPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKGF0dHJpYnV0ZXMsICJ1bCIpOwogIH0KfQpjbGFzcyBYaHRtbE5hbWVzcGFjZSB7CiAgc3RhdGljIFskYnVpbGRYRkFPYmplY3RdKG5hbWUsIGF0dHJpYnV0ZXMpIHsKICAgIGlmIChYaHRtbE5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICByZXR1cm4gWGh0bWxOYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgYShhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IEEoYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBiKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgQihhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIGJvZHkoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBCb2R5KGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgYnIoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBCcihhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIGh0bWwoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBIdG1sKGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgaShhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IEkoYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBsaShhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IExpKGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgb2woYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBPbChhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIHAoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBQKGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgc3BhbihhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IFNwYW4oYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBzdWIoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBTdWIoYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBzdXAoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBTdXAoYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyB1bChhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IFVsKGF0dHJpYnV0ZXMpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL3NldHVwLmpzCgoKCgoKCgoKCmNvbnN0IE5hbWVzcGFjZVNldFVwID0gewogIGNvbmZpZzogQ29uZmlnTmFtZXNwYWNlLAogIGNvbm5lY3Rpb246IENvbm5lY3Rpb25TZXROYW1lc3BhY2UsCiAgZGF0YXNldHM6IERhdGFzZXRzTmFtZXNwYWNlLAogIGxvY2FsZVNldDogTG9jYWxlU2V0TmFtZXNwYWNlLAogIHNpZ25hdHVyZTogU2lnbmF0dXJlTmFtZXNwYWNlLAogIHN0eWxlc2hlZXQ6IFN0eWxlc2hlZXROYW1lc3BhY2UsCiAgdGVtcGxhdGU6IFRlbXBsYXRlTmFtZXNwYWNlLAogIHhkcDogWGRwTmFtZXNwYWNlLAogIHhodG1sOiBYaHRtbE5hbWVzcGFjZQp9OwoKOy8vIC4vc3JjL2NvcmUveGZhL3Vua25vd24uanMKCgpjbGFzcyBVbmtub3duTmFtZXNwYWNlIHsKICBjb25zdHJ1Y3Rvcihuc0lkKSB7CiAgICB0aGlzLm5hbWVzcGFjZUlkID0gbnNJZDsKICB9CiAgWyRidWlsZFhGQU9iamVjdF0obmFtZSwgYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBYbWxPYmplY3QodGhpcy5uYW1lc3BhY2VJZCwgbmFtZSwgYXR0cmlidXRlcyk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvYnVpbGRlci5qcwoKCgoKCgoKY2xhc3MgUm9vdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoaWRzKSB7CiAgICBzdXBlcigtMSwgInJvb3QiLCBPYmplY3QuY3JlYXRlKG51bGwpKTsKICAgIHRoaXMuZWxlbWVudCA9IG51bGw7CiAgICB0aGlzWyRpZHNdID0gaWRzOwogIH0KICBbJG9uQ2hpbGRdKGNoaWxkKSB7CiAgICB0aGlzLmVsZW1lbnQgPSBjaGlsZDsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIHN1cGVyWyRmaW5hbGl6ZV0oKTsKICAgIGlmICh0aGlzLmVsZW1lbnQudGVtcGxhdGUgaW5zdGFuY2VvZiBUZW1wbGF0ZSkgewogICAgICB0aGlzWyRpZHNdLnNldCgkcm9vdCwgdGhpcy5lbGVtZW50KTsKICAgICAgdGhpcy5lbGVtZW50LnRlbXBsYXRlWyRyZXNvbHZlUHJvdG90eXBlc10odGhpc1skaWRzXSk7CiAgICAgIHRoaXMuZWxlbWVudC50ZW1wbGF0ZVskaWRzXSA9IHRoaXNbJGlkc107CiAgICB9CiAgfQp9CmNsYXNzIEVtcHR5IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHN1cGVyKC0xLCAiIiwgT2JqZWN0LmNyZWF0ZShudWxsKSk7CiAgfQogIFskb25DaGlsZF0oXykgewogICAgcmV0dXJuIGZhbHNlOwogIH0KfQpjbGFzcyBCdWlsZGVyIHsKICBjb25zdHJ1Y3Rvcihyb290TmFtZVNwYWNlID0gbnVsbCkgewogICAgdGhpcy5fbmFtZXNwYWNlU3RhY2sgPSBbXTsKICAgIHRoaXMuX25zQWdub3N0aWNMZXZlbCA9IDA7CiAgICB0aGlzLl9uYW1lc3BhY2VQcmVmaXhlcyA9IG5ldyBNYXAoKTsKICAgIHRoaXMuX25hbWVzcGFjZXMgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9uZXh0TnNJZCA9IE1hdGgubWF4KC4uLk9iamVjdC52YWx1ZXMoTmFtZXNwYWNlSWRzKS5tYXAoKHsKICAgICAgaWQKICAgIH0pID0+IGlkKSk7CiAgICB0aGlzLl9jdXJyZW50TmFtZXNwYWNlID0gcm9vdE5hbWVTcGFjZSB8fCBuZXcgVW5rbm93bk5hbWVzcGFjZSgrK3RoaXMuX25leHROc0lkKTsKICB9CiAgYnVpbGRSb290KGlkcykgewogICAgcmV0dXJuIG5ldyBSb290KGlkcyk7CiAgfQogIGJ1aWxkKHsKICAgIG5zUHJlZml4LAogICAgbmFtZSwKICAgIGF0dHJpYnV0ZXMsCiAgICBuYW1lc3BhY2UsCiAgICBwcmVmaXhlcwogIH0pIHsKICAgIGNvbnN0IGhhc05hbWVzcGFjZURlZiA9IG5hbWVzcGFjZSAhPT0gbnVsbDsKICAgIGlmIChoYXNOYW1lc3BhY2VEZWYpIHsKICAgICAgdGhpcy5fbmFtZXNwYWNlU3RhY2sucHVzaCh0aGlzLl9jdXJyZW50TmFtZXNwYWNlKTsKICAgICAgdGhpcy5fY3VycmVudE5hbWVzcGFjZSA9IHRoaXMuX3NlYXJjaE5hbWVzcGFjZShuYW1lc3BhY2UpOwogICAgfQogICAgaWYgKHByZWZpeGVzKSB7CiAgICAgIHRoaXMuX2FkZE5hbWVzcGFjZVByZWZpeChwcmVmaXhlcyk7CiAgICB9CiAgICBpZiAoYXR0cmlidXRlcy5oYXNPd25Qcm9wZXJ0eSgkbnNBdHRyaWJ1dGVzKSkgewogICAgICBjb25zdCBkYXRhVGVtcGxhdGUgPSBOYW1lc3BhY2VTZXRVcC5kYXRhc2V0czsKICAgICAgY29uc3QgbnNBdHRycyA9IGF0dHJpYnV0ZXNbJG5zQXR0cmlidXRlc107CiAgICAgIGxldCB4ZmFBdHRycyA9IG51bGw7CiAgICAgIGZvciAoY29uc3QgW25zLCBhdHRyc10gb2YgT2JqZWN0LmVudHJpZXMobnNBdHRycykpIHsKICAgICAgICBjb25zdCBuc1RvVXNlID0gdGhpcy5fZ2V0TmFtZXNwYWNlVG9Vc2UobnMpOwogICAgICAgIGlmIChuc1RvVXNlID09PSBkYXRhVGVtcGxhdGUpIHsKICAgICAgICAgIHhmYUF0dHJzID0gewogICAgICAgICAgICB4ZmE6IGF0dHJzCiAgICAgICAgICB9OwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICh4ZmFBdHRycykgewogICAgICAgIGF0dHJpYnV0ZXNbJG5zQXR0cmlidXRlc10gPSB4ZmFBdHRyczsKICAgICAgfSBlbHNlIHsKICAgICAgICBkZWxldGUgYXR0cmlidXRlc1skbnNBdHRyaWJ1dGVzXTsKICAgICAgfQogICAgfQogICAgY29uc3QgbmFtZXNwYWNlVG9Vc2UgPSB0aGlzLl9nZXROYW1lc3BhY2VUb1VzZShuc1ByZWZpeCk7CiAgICBjb25zdCBub2RlID0gbmFtZXNwYWNlVG9Vc2U/LlskYnVpbGRYRkFPYmplY3RdKG5hbWUsIGF0dHJpYnV0ZXMpIHx8IG5ldyBFbXB0eSgpOwogICAgaWYgKG5vZGVbJGlzTnNBZ25vc3RpY10oKSkgewogICAgICB0aGlzLl9uc0Fnbm9zdGljTGV2ZWwrKzsKICAgIH0KICAgIGlmIChoYXNOYW1lc3BhY2VEZWYgfHwgcHJlZml4ZXMgfHwgbm9kZVskaXNOc0Fnbm9zdGljXSgpKSB7CiAgICAgIG5vZGVbJGNsZWFudXBdID0gewogICAgICAgIGhhc05hbWVzcGFjZTogaGFzTmFtZXNwYWNlRGVmLAogICAgICAgIHByZWZpeGVzLAogICAgICAgIG5zQWdub3N0aWM6IG5vZGVbJGlzTnNBZ25vc3RpY10oKQogICAgICB9OwogICAgfQogICAgcmV0dXJuIG5vZGU7CiAgfQogIGlzTnNBZ25vc3RpYygpIHsKICAgIHJldHVybiB0aGlzLl9uc0Fnbm9zdGljTGV2ZWwgPiAwOwogIH0KICBfc2VhcmNoTmFtZXNwYWNlKG5zTmFtZSkgewogICAgbGV0IG5zID0gdGhpcy5fbmFtZXNwYWNlcy5nZXQobnNOYW1lKTsKICAgIGlmIChucykgewogICAgICByZXR1cm4gbnM7CiAgICB9CiAgICBmb3IgKGNvbnN0IFtuYW1lLCB7CiAgICAgIGNoZWNrCiAgICB9XSBvZiBPYmplY3QuZW50cmllcyhOYW1lc3BhY2VJZHMpKSB7CiAgICAgIGlmIChjaGVjayhuc05hbWUpKSB7CiAgICAgICAgbnMgPSBOYW1lc3BhY2VTZXRVcFtuYW1lXTsKICAgICAgICBpZiAobnMpIHsKICAgICAgICAgIHRoaXMuX25hbWVzcGFjZXMuc2V0KG5zTmFtZSwgbnMpOwogICAgICAgICAgcmV0dXJuIG5zOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgbnMgPSBuZXcgVW5rbm93bk5hbWVzcGFjZSgrK3RoaXMuX25leHROc0lkKTsKICAgIHRoaXMuX25hbWVzcGFjZXMuc2V0KG5zTmFtZSwgbnMpOwogICAgcmV0dXJuIG5zOwogIH0KICBfYWRkTmFtZXNwYWNlUHJlZml4KHByZWZpeGVzKSB7CiAgICBmb3IgKGNvbnN0IHsKICAgICAgcHJlZml4LAogICAgICB2YWx1ZQogICAgfSBvZiBwcmVmaXhlcykgewogICAgICBjb25zdCBuYW1lc3BhY2UgPSB0aGlzLl9zZWFyY2hOYW1lc3BhY2UodmFsdWUpOwogICAgICBsZXQgcHJlZml4U3RhY2sgPSB0aGlzLl9uYW1lc3BhY2VQcmVmaXhlcy5nZXQocHJlZml4KTsKICAgICAgaWYgKCFwcmVmaXhTdGFjaykgewogICAgICAgIHByZWZpeFN0YWNrID0gW107CiAgICAgICAgdGhpcy5fbmFtZXNwYWNlUHJlZml4ZXMuc2V0KHByZWZpeCwgcHJlZml4U3RhY2spOwogICAgICB9CiAgICAgIHByZWZpeFN0YWNrLnB1c2gobmFtZXNwYWNlKTsKICAgIH0KICB9CiAgX2dldE5hbWVzcGFjZVRvVXNlKHByZWZpeCkgewogICAgaWYgKCFwcmVmaXgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2N1cnJlbnROYW1lc3BhY2U7CiAgICB9CiAgICBjb25zdCBwcmVmaXhTdGFjayA9IHRoaXMuX25hbWVzcGFjZVByZWZpeGVzLmdldChwcmVmaXgpOwogICAgaWYgKHByZWZpeFN0YWNrPy5sZW5ndGggPiAwKSB7CiAgICAgIHJldHVybiBwcmVmaXhTdGFjay5hdCgtMSk7CiAgICB9CiAgICB3YXJuKGBVbmtub3duIG5hbWVzcGFjZSBwcmVmaXg6ICR7cHJlZml4fS5gKTsKICAgIHJldHVybiBudWxsOwogIH0KICBjbGVhbihkYXRhKSB7CiAgICBjb25zdCB7CiAgICAgIGhhc05hbWVzcGFjZSwKICAgICAgcHJlZml4ZXMsCiAgICAgIG5zQWdub3N0aWMKICAgIH0gPSBkYXRhOwogICAgaWYgKGhhc05hbWVzcGFjZSkgewogICAgICB0aGlzLl9jdXJyZW50TmFtZXNwYWNlID0gdGhpcy5fbmFtZXNwYWNlU3RhY2sucG9wKCk7CiAgICB9CiAgICBpZiAocHJlZml4ZXMpIHsKICAgICAgcHJlZml4ZXMuZm9yRWFjaCgoewogICAgICAgIHByZWZpeAogICAgICB9KSA9PiB7CiAgICAgICAgdGhpcy5fbmFtZXNwYWNlUHJlZml4ZXMuZ2V0KHByZWZpeCkucG9wKCk7CiAgICAgIH0pOwogICAgfQogICAgaWYgKG5zQWdub3N0aWMpIHsKICAgICAgdGhpcy5fbnNBZ25vc3RpY0xldmVsLS07CiAgICB9CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvcGFyc2VyLmpzCgoKCgpjbGFzcyBYRkFQYXJzZXIgZXh0ZW5kcyBYTUxQYXJzZXJCYXNlIHsKICBjb25zdHJ1Y3Rvcihyb290TmFtZVNwYWNlID0gbnVsbCwgcmljaFRleHQgPSBmYWxzZSkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuX2J1aWxkZXIgPSBuZXcgQnVpbGRlcihyb290TmFtZVNwYWNlKTsKICAgIHRoaXMuX3N0YWNrID0gW107CiAgICB0aGlzLl9nbG9iYWxEYXRhID0gewogICAgICB1c2VkVHlwZWZhY2VzOiBuZXcgU2V0KCkKICAgIH07CiAgICB0aGlzLl9pZHMgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9jdXJyZW50ID0gdGhpcy5fYnVpbGRlci5idWlsZFJvb3QodGhpcy5faWRzKTsKICAgIHRoaXMuX2Vycm9yQ29kZSA9IFhNTFBhcnNlckVycm9yQ29kZS5Ob0Vycm9yOwogICAgdGhpcy5fd2hpdGVSZWdleCA9IC9eXHMrJC87CiAgICB0aGlzLl9uYnNwcyA9IC9ceGEwKy9nOwogICAgdGhpcy5fcmljaFRleHQgPSByaWNoVGV4dDsKICB9CiAgcGFyc2UoZGF0YSkgewogICAgdGhpcy5wYXJzZVhtbChkYXRhKTsKICAgIGlmICh0aGlzLl9lcnJvckNvZGUgIT09IFhNTFBhcnNlckVycm9yQ29kZS5Ob0Vycm9yKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICB0aGlzLl9jdXJyZW50WyRmaW5hbGl6ZV0oKTsKICAgIHJldHVybiB0aGlzLl9jdXJyZW50LmVsZW1lbnQ7CiAgfQogIG9uVGV4dCh0ZXh0KSB7CiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKHRoaXMuX25ic3BzLCBtYXRjaCA9PiBtYXRjaC5zbGljZSgxKSArICIgIik7CiAgICBpZiAodGhpcy5fcmljaFRleHQgfHwgdGhpcy5fY3VycmVudFskYWNjZXB0V2hpdGVzcGFjZV0oKSkgewogICAgICB0aGlzLl9jdXJyZW50WyRvblRleHRdKHRleHQsIHRoaXMuX3JpY2hUZXh0KTsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKHRoaXMuX3doaXRlUmVnZXgudGVzdCh0ZXh0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9jdXJyZW50WyRvblRleHRdKHRleHQudHJpbSgpKTsKICB9CiAgb25DZGF0YSh0ZXh0KSB7CiAgICB0aGlzLl9jdXJyZW50WyRvblRleHRdKHRleHQpOwogIH0KICBfbWtBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMsIHRhZ05hbWUpIHsKICAgIGxldCBuYW1lc3BhY2UgPSBudWxsOwogICAgbGV0IHByZWZpeGVzID0gbnVsbDsKICAgIGNvbnN0IGF0dHJpYnV0ZU9iaiA9IE9iamVjdC5jcmVhdGUoe30pOwogICAgZm9yIChjb25zdCB7CiAgICAgIG5hbWUsCiAgICAgIHZhbHVlCiAgICB9IG9mIGF0dHJpYnV0ZXMpIHsKICAgICAgaWYgKG5hbWUgPT09ICJ4bWxucyIpIHsKICAgICAgICBpZiAoIW5hbWVzcGFjZSkgewogICAgICAgICAgbmFtZXNwYWNlID0gdmFsdWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHdhcm4oYFhGQSAtIG11bHRpcGxlIG5hbWVzcGFjZSBkZWZpbml0aW9uIGluIDwke3RhZ05hbWV9PmApOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChuYW1lLnN0YXJ0c1dpdGgoInhtbG5zOiIpKSB7CiAgICAgICAgY29uc3QgcHJlZml4ID0gbmFtZS5zdWJzdHJpbmcoInhtbG5zOiIubGVuZ3RoKTsKICAgICAgICBwcmVmaXhlcyA/Pz0gW107CiAgICAgICAgcHJlZml4ZXMucHVzaCh7CiAgICAgICAgICBwcmVmaXgsCiAgICAgICAgICB2YWx1ZQogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGkgPSBuYW1lLmluZGV4T2YoIjoiKTsKICAgICAgICBpZiAoaSA9PT0gLTEpIHsKICAgICAgICAgIGF0dHJpYnV0ZU9ialtuYW1lXSA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb25zdCBuc0F0dHJzID0gYXR0cmlidXRlT2JqWyRuc0F0dHJpYnV0ZXNdID8/PSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgY29uc3QgW25zLCBhdHRyTmFtZV0gPSBbbmFtZS5zbGljZSgwLCBpKSwgbmFtZS5zbGljZShpICsgMSldOwogICAgICAgICAgY29uc3QgYXR0cnMgPSBuc0F0dHJzW25zXSB8fD0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgIGF0dHJzW2F0dHJOYW1lXSA9IHZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIFtuYW1lc3BhY2UsIHByZWZpeGVzLCBhdHRyaWJ1dGVPYmpdOwogIH0KICBfZ2V0TmFtZUFuZFByZWZpeChuYW1lLCBuc0Fnbm9zdGljKSB7CiAgICBjb25zdCBpID0gbmFtZS5pbmRleE9mKCI6Iik7CiAgICBpZiAoaSA9PT0gLTEpIHsKICAgICAgcmV0dXJuIFtuYW1lLCBudWxsXTsKICAgIH0KICAgIHJldHVybiBbbmFtZS5zdWJzdHJpbmcoaSArIDEpLCBuc0Fnbm9zdGljID8gIiIgOiBuYW1lLnN1YnN0cmluZygwLCBpKV07CiAgfQogIG9uQmVnaW5FbGVtZW50KHRhZ05hbWUsIGF0dHJpYnV0ZXMsIGlzRW1wdHkpIHsKICAgIGNvbnN0IFtuYW1lc3BhY2UsIHByZWZpeGVzLCBhdHRyaWJ1dGVzT2JqXSA9IHRoaXMuX21rQXR0cmlidXRlcyhhdHRyaWJ1dGVzLCB0YWdOYW1lKTsKICAgIGNvbnN0IFtuYW1lLCBuc1ByZWZpeF0gPSB0aGlzLl9nZXROYW1lQW5kUHJlZml4KHRhZ05hbWUsIHRoaXMuX2J1aWxkZXIuaXNOc0Fnbm9zdGljKCkpOwogICAgY29uc3Qgbm9kZSA9IHRoaXMuX2J1aWxkZXIuYnVpbGQoewogICAgICBuc1ByZWZpeCwKICAgICAgbmFtZSwKICAgICAgYXR0cmlidXRlczogYXR0cmlidXRlc09iaiwKICAgICAgbmFtZXNwYWNlLAogICAgICBwcmVmaXhlcwogICAgfSk7CiAgICBub2RlWyRnbG9iYWxEYXRhXSA9IHRoaXMuX2dsb2JhbERhdGE7CiAgICBpZiAoaXNFbXB0eSkgewogICAgICBub2RlWyRmaW5hbGl6ZV0oKTsKICAgICAgaWYgKHRoaXMuX2N1cnJlbnRbJG9uQ2hpbGRdKG5vZGUpKSB7CiAgICAgICAgbm9kZVskc2V0SWRdKHRoaXMuX2lkcyk7CiAgICAgIH0KICAgICAgbm9kZVskY2xlYW5dKHRoaXMuX2J1aWxkZXIpOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9zdGFjay5wdXNoKHRoaXMuX2N1cnJlbnQpOwogICAgdGhpcy5fY3VycmVudCA9IG5vZGU7CiAgfQogIG9uRW5kRWxlbWVudChuYW1lKSB7CiAgICBjb25zdCBub2RlID0gdGhpcy5fY3VycmVudDsKICAgIGlmIChub2RlWyRpc0NEQVRBWG1sXSgpICYmIHR5cGVvZiBub2RlWyRjb250ZW50XSA9PT0gInN0cmluZyIpIHsKICAgICAgY29uc3QgcGFyc2VyID0gbmV3IFhGQVBhcnNlcigpOwogICAgICBwYXJzZXIuX2dsb2JhbERhdGEgPSB0aGlzLl9nbG9iYWxEYXRhOwogICAgICBjb25zdCByb290ID0gcGFyc2VyLnBhcnNlKG5vZGVbJGNvbnRlbnRdKTsKICAgICAgbm9kZVskY29udGVudF0gPSBudWxsOwogICAgICBub2RlWyRvbkNoaWxkXShyb290KTsKICAgIH0KICAgIG5vZGVbJGZpbmFsaXplXSgpOwogICAgdGhpcy5fY3VycmVudCA9IHRoaXMuX3N0YWNrLnBvcCgpOwogICAgaWYgKHRoaXMuX2N1cnJlbnRbJG9uQ2hpbGRdKG5vZGUpKSB7CiAgICAgIG5vZGVbJHNldElkXSh0aGlzLl9pZHMpOwogICAgfQogICAgbm9kZVskY2xlYW5dKHRoaXMuX2J1aWxkZXIpOwogIH0KICBvbkVycm9yKGNvZGUpIHsKICAgIHRoaXMuX2Vycm9yQ29kZSA9IGNvZGU7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvZmFjdG9yeS5qcwoKCgoKCgoKCmNsYXNzIFhGQUZhY3RvcnkgewogIGNvbnN0cnVjdG9yKGRhdGEpIHsKICAgIHRyeSB7CiAgICAgIHRoaXMucm9vdCA9IG5ldyBYRkFQYXJzZXIoKS5wYXJzZShYRkFGYWN0b3J5Ll9jcmVhdGVEb2N1bWVudChkYXRhKSk7CiAgICAgIGNvbnN0IGJpbmRlciA9IG5ldyBCaW5kZXIodGhpcy5yb290KTsKICAgICAgdGhpcy5mb3JtID0gYmluZGVyLmJpbmQoKTsKICAgICAgdGhpcy5kYXRhSGFuZGxlciA9IG5ldyBEYXRhSGFuZGxlcih0aGlzLnJvb3QsIGJpbmRlci5nZXREYXRhKCkpOwogICAgICB0aGlzLmZvcm1bJGdsb2JhbERhdGFdLnRlbXBsYXRlID0gdGhpcy5mb3JtOwogICAgfSBjYXRjaCAoZSkgewogICAgICB3YXJuKGBYRkEgLSBhbiBlcnJvciBvY2N1cnJlZCBkdXJpbmcgcGFyc2luZyBhbmQgYmluZGluZzogJHtlfWApOwogICAgfQogIH0KICBpc1ZhbGlkKCkgewogICAgcmV0dXJuICEhKHRoaXMucm9vdCAmJiB0aGlzLmZvcm0pOwogIH0KICBfY3JlYXRlUGFnZXNIZWxwZXIoKSB7CiAgICBjb25zdCBpdGVyYXRvciA9IHRoaXMuZm9ybVskdG9QYWdlc10oKTsKICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAgIGNvbnN0IG5leHRJdGVyYXRpb24gPSAoKSA9PiB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gaXRlcmF0b3IubmV4dCgpOwogICAgICAgICAgaWYgKHZhbHVlLmRvbmUpIHsKICAgICAgICAgICAgcmVzb2x2ZSh2YWx1ZS52YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzZXRUaW1lb3V0KG5leHRJdGVyYXRpb24sIDApOwogICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIHJlamVjdChlKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIHNldFRpbWVvdXQobmV4dEl0ZXJhdGlvbiwgMCk7CiAgICB9KTsKICB9CiAgYXN5bmMgX2NyZWF0ZVBhZ2VzKCkgewogICAgdHJ5IHsKICAgICAgdGhpcy5wYWdlcyA9IGF3YWl0IHRoaXMuX2NyZWF0ZVBhZ2VzSGVscGVyKCk7CiAgICAgIHRoaXMuZGltcyA9IHRoaXMucGFnZXMuY2hpbGRyZW4ubWFwKGMgPT4gewogICAgICAgIGNvbnN0IHsKICAgICAgICAgIHdpZHRoLAogICAgICAgICAgaGVpZ2h0CiAgICAgICAgfSA9IGMuYXR0cmlidXRlcy5zdHlsZTsKICAgICAgICByZXR1cm4gWzAsIDAsIHBhcnNlSW50KHdpZHRoKSwgcGFyc2VJbnQoaGVpZ2h0KV07CiAgICAgIH0pOwogICAgfSBjYXRjaCAoZSkgewogICAgICB3YXJuKGBYRkEgLSBhbiBlcnJvciBvY2N1cnJlZCBkdXJpbmcgbGF5b3V0OiAke2V9YCk7CiAgICB9CiAgfQogIGdldEJvdW5kaW5nQm94KHBhZ2VJbmRleCkgewogICAgcmV0dXJuIHRoaXMuZGltc1twYWdlSW5kZXhdOwogIH0KICBhc3luYyBnZXROdW1QYWdlcygpIHsKICAgIGlmICghdGhpcy5wYWdlcykgewogICAgICBhd2FpdCB0aGlzLl9jcmVhdGVQYWdlcygpOwogICAgfQogICAgcmV0dXJuIHRoaXMuZGltcy5sZW5ndGg7CiAgfQogIHNldEltYWdlcyhpbWFnZXMpIHsKICAgIHRoaXMuZm9ybVskZ2xvYmFsRGF0YV0uaW1hZ2VzID0gaW1hZ2VzOwogIH0KICBzZXRGb250cyhmb250cykgewogICAgdGhpcy5mb3JtWyRnbG9iYWxEYXRhXS5mb250RmluZGVyID0gbmV3IEZvbnRGaW5kZXIoZm9udHMpOwogICAgY29uc3QgbWlzc2luZ0ZvbnRzID0gW107CiAgICBmb3IgKGxldCB0eXBlZmFjZSBvZiB0aGlzLmZvcm1bJGdsb2JhbERhdGFdLnVzZWRUeXBlZmFjZXMpIHsKICAgICAgdHlwZWZhY2UgPSBzdHJpcFF1b3Rlcyh0eXBlZmFjZSk7CiAgICAgIGNvbnN0IGZvbnQgPSB0aGlzLmZvcm1bJGdsb2JhbERhdGFdLmZvbnRGaW5kZXIuZmluZCh0eXBlZmFjZSk7CiAgICAgIGlmICghZm9udCkgewogICAgICAgIG1pc3NpbmdGb250cy5wdXNoKHR5cGVmYWNlKTsKICAgICAgfQogICAgfQogICAgaWYgKG1pc3NpbmdGb250cy5sZW5ndGggPiAwKSB7CiAgICAgIHJldHVybiBtaXNzaW5nRm9udHM7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgYXBwZW5kRm9udHMoZm9udHMsIHJlYWxseU1pc3NpbmdGb250cykgewogICAgdGhpcy5mb3JtWyRnbG9iYWxEYXRhXS5mb250RmluZGVyLmFkZChmb250cywgcmVhbGx5TWlzc2luZ0ZvbnRzKTsKICB9CiAgYXN5bmMgZ2V0UGFnZXMoKSB7CiAgICBpZiAoIXRoaXMucGFnZXMpIHsKICAgICAgYXdhaXQgdGhpcy5fY3JlYXRlUGFnZXMoKTsKICAgIH0KICAgIGNvbnN0IHBhZ2VzID0gdGhpcy5wYWdlczsKICAgIHRoaXMucGFnZXMgPSBudWxsOwogICAgcmV0dXJuIHBhZ2VzOwogIH0KICBzZXJpYWxpemVEYXRhKHN0b3JhZ2UpIHsKICAgIHJldHVybiB0aGlzLmRhdGFIYW5kbGVyLnNlcmlhbGl6ZShzdG9yYWdlKTsKICB9CiAgc3RhdGljIF9jcmVhdGVEb2N1bWVudChkYXRhKSB7CiAgICBpZiAoIWRhdGFbIi94ZHA6eGRwIl0pIHsKICAgICAgcmV0dXJuIGRhdGFbInhkcDp4ZHAiXTsKICAgIH0KICAgIHJldHVybiBPYmplY3QudmFsdWVzKGRhdGEpLmpvaW4oIiIpOwogIH0KICBzdGF0aWMgZ2V0UmljaFRleHRBc0h0bWwocmMpIHsKICAgIGlmICghcmMgfHwgdHlwZW9mIHJjICE9PSAic3RyaW5nIikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIHRyeSB7CiAgICAgIGxldCByb290ID0gbmV3IFhGQVBhcnNlcihYaHRtbE5hbWVzcGFjZSwgdHJ1ZSkucGFyc2UocmMpOwogICAgICBpZiAoIVsiYm9keSIsICJ4aHRtbCJdLmluY2x1ZGVzKHJvb3RbJG5vZGVOYW1lXSkpIHsKICAgICAgICBjb25zdCBuZXdSb290ID0gWGh0bWxOYW1lc3BhY2UuYm9keSh7fSk7CiAgICAgICAgbmV3Um9vdFskYXBwZW5kQ2hpbGRdKHJvb3QpOwogICAgICAgIHJvb3QgPSBuZXdSb290OwogICAgICB9CiAgICAgIGNvbnN0IHJlc3VsdCA9IHJvb3RbJHRvSFRNTF0oKTsKICAgICAgaWYgKCFyZXN1bHQuc3VjY2VzcykgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IHsKICAgICAgICBodG1sCiAgICAgIH0gPSByZXN1bHQ7CiAgICAgIGNvbnN0IHsKICAgICAgICBhdHRyaWJ1dGVzCiAgICAgIH0gPSBodG1sOwogICAgICBpZiAoYXR0cmlidXRlcykgewogICAgICAgIGlmIChhdHRyaWJ1dGVzLmNsYXNzKSB7CiAgICAgICAgICBhdHRyaWJ1dGVzLmNsYXNzID0gYXR0cmlidXRlcy5jbGFzcy5maWx0ZXIoYXR0ciA9PiAhYXR0ci5zdGFydHNXaXRoKCJ4ZmEiKSk7CiAgICAgICAgfQogICAgICAgIGF0dHJpYnV0ZXMuZGlyID0gImF1dG8iOwogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgaHRtbCwKICAgICAgICBzdHI6IHJvb3RbJHRleHRdKCkKICAgICAgfTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgd2FybihgWEZBIC0gYW4gZXJyb3Igb2NjdXJyZWQgZHVyaW5nIHBhcnNpbmcgb2YgcmljaCB0ZXh0OiAke2V9YCk7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2Fubm90YXRpb24uanMKCgoKCgoKCgoKCgoKCgoKY2xhc3MgQW5ub3RhdGlvbkZhY3RvcnkgewogIHN0YXRpYyBjcmVhdGVHbG9iYWxzKHBkZk1hbmFnZXIpIHsKICAgIHJldHVybiBQcm9taXNlLmFsbChbcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJhY3JvRm9ybSIpLCBwZGZNYW5hZ2VyLmVuc3VyZURvYygieGZhRGF0YXNldHMiKSwgcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJzdHJ1Y3RUcmVlUm9vdCIpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImJhc2VVcmwiKSwgcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJhdHRhY2htZW50cyIpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImdsb2JhbENvbG9yU3BhY2VDYWNoZSIpXSkudGhlbigoW2Fjcm9Gb3JtLCB4ZmFEYXRhc2V0cywgc3RydWN0VHJlZVJvb3QsIGJhc2VVcmwsIGF0dGFjaG1lbnRzLCBnbG9iYWxDb2xvclNwYWNlQ2FjaGVdKSA9PiAoewogICAgICBwZGZNYW5hZ2VyLAogICAgICBhY3JvRm9ybTogYWNyb0Zvcm0gaW5zdGFuY2VvZiBEaWN0ID8gYWNyb0Zvcm0gOiBEaWN0LmVtcHR5LAogICAgICB4ZmFEYXRhc2V0cywKICAgICAgc3RydWN0VHJlZVJvb3QsCiAgICAgIGJhc2VVcmwsCiAgICAgIGF0dGFjaG1lbnRzLAogICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGUKICAgIH0pLCByZWFzb24gPT4gewogICAgICB3YXJuKGBjcmVhdGVHbG9iYWxzOiAiJHtyZWFzb259Ii5gKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9KTsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZSh4cmVmLCByZWYsIGFubm90YXRpb25HbG9iYWxzLCBpZEZhY3RvcnksIGNvbGxlY3RGaWVsZHMsIG9ycGhhbkZpZWxkcywgY29sbGVjdEJ5VHlwZSwgcGFnZVJlZikgewogICAgY29uc3QgcGFnZUluZGV4ID0gY29sbGVjdEZpZWxkcyA/IGF3YWl0IHRoaXMuX2dldFBhZ2VJbmRleCh4cmVmLCByZWYsIGFubm90YXRpb25HbG9iYWxzLnBkZk1hbmFnZXIpIDogbnVsbDsKICAgIHJldHVybiBhbm5vdGF0aW9uR2xvYmFscy5wZGZNYW5hZ2VyLmVuc3VyZSh0aGlzLCAiX2NyZWF0ZSIsIFt4cmVmLCByZWYsIGFubm90YXRpb25HbG9iYWxzLCBpZEZhY3RvcnksIGNvbGxlY3RGaWVsZHMsIG9ycGhhbkZpZWxkcywgY29sbGVjdEJ5VHlwZSwgcGFnZUluZGV4LCBwYWdlUmVmXSk7CiAgfQogIHN0YXRpYyBfY3JlYXRlKHhyZWYsIHJlZiwgYW5ub3RhdGlvbkdsb2JhbHMsIGlkRmFjdG9yeSwgY29sbGVjdEZpZWxkcyA9IGZhbHNlLCBvcnBoYW5GaWVsZHMgPSBudWxsLCBjb2xsZWN0QnlUeXBlID0gbnVsbCwgcGFnZUluZGV4ID0gbnVsbCwgcGFnZVJlZiA9IG51bGwpIHsKICAgIGNvbnN0IGRpY3QgPSB4cmVmLmZldGNoSWZSZWYocmVmKTsKICAgIGlmICghKGRpY3QgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogICAgbGV0IHN1YnR5cGUgPSBkaWN0LmdldCgiU3VidHlwZSIpOwogICAgc3VidHlwZSA9IHN1YnR5cGUgaW5zdGFuY2VvZiBOYW1lID8gc3VidHlwZS5uYW1lIDogbnVsbDsKICAgIGlmIChjb2xsZWN0QnlUeXBlICYmICFjb2xsZWN0QnlUeXBlLmhhcyhBbm5vdGF0aW9uVHlwZVtzdWJ0eXBlLnRvVXBwZXJDYXNlKCldKSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgYWNyb0Zvcm0sCiAgICAgIHBkZk1hbmFnZXIKICAgIH0gPSBhbm5vdGF0aW9uR2xvYmFsczsKICAgIGNvbnN0IGlkID0gcmVmIGluc3RhbmNlb2YgUmVmID8gcmVmLnRvU3RyaW5nKCkgOiBgYW5ub3RfJHtpZEZhY3RvcnkuY3JlYXRlT2JqSWQoKX1gOwogICAgY29uc3QgcGFyYW1ldGVycyA9IHsKICAgICAgeHJlZiwKICAgICAgcmVmLAogICAgICBkaWN0LAogICAgICBzdWJ0eXBlLAogICAgICBpZCwKICAgICAgYW5ub3RhdGlvbkdsb2JhbHMsCiAgICAgIGNvbGxlY3RGaWVsZHMsCiAgICAgIG9ycGhhbkZpZWxkcywKICAgICAgbmVlZEFwcGVhcmFuY2VzOiAhY29sbGVjdEZpZWxkcyAmJiBhY3JvRm9ybS5nZXQoIk5lZWRBcHBlYXJhbmNlcyIpID09PSB0cnVlLAogICAgICBwYWdlSW5kZXgsCiAgICAgIGV2YWx1YXRvck9wdGlvbnM6IHBkZk1hbmFnZXIuZXZhbHVhdG9yT3B0aW9ucywKICAgICAgcGFnZVJlZgogICAgfTsKICAgIHN3aXRjaCAoc3VidHlwZSkgewogICAgICBjYXNlICJMaW5rIjoKICAgICAgICByZXR1cm4gbmV3IExpbmtBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJUZXh0IjoKICAgICAgICByZXR1cm4gbmV3IFRleHRBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJXaWRnZXQiOgogICAgICAgIGxldCBmaWVsZFR5cGUgPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5KHsKICAgICAgICAgIGRpY3QsCiAgICAgICAgICBrZXk6ICJGVCIKICAgICAgICB9KTsKICAgICAgICBmaWVsZFR5cGUgPSBmaWVsZFR5cGUgaW5zdGFuY2VvZiBOYW1lID8gZmllbGRUeXBlLm5hbWUgOiBudWxsOwogICAgICAgIHN3aXRjaCAoZmllbGRUeXBlKSB7CiAgICAgICAgICBjYXNlICJUeCI6CiAgICAgICAgICAgIHJldHVybiBuZXcgVGV4dFdpZGdldEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgICAgICBjYXNlICJCdG4iOgogICAgICAgICAgICByZXR1cm4gbmV3IEJ1dHRvbldpZGdldEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgICAgICBjYXNlICJDaCI6CiAgICAgICAgICAgIHJldHVybiBuZXcgQ2hvaWNlV2lkZ2V0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgICAgIGNhc2UgIlNpZyI6CiAgICAgICAgICAgIHJldHVybiBuZXcgU2lnbmF0dXJlV2lkZ2V0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgICB9CiAgICAgICAgd2FybihgVW5pbXBsZW1lbnRlZCB3aWRnZXQgZmllbGQgdHlwZSAiJHtmaWVsZFR5cGV9IiwgYCArICJmYWxsaW5nIGJhY2sgdG8gYmFzZSBmaWVsZCB0eXBlLiIpOwogICAgICAgIHJldHVybiBuZXcgV2lkZ2V0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiUG9wdXAiOgogICAgICAgIHJldHVybiBuZXcgUG9wdXBBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJGcmVlVGV4dCI6CiAgICAgICAgcmV0dXJuIG5ldyBGcmVlVGV4dEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIkxpbmUiOgogICAgICAgIHJldHVybiBuZXcgTGluZUFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIlNxdWFyZSI6CiAgICAgICAgcmV0dXJuIG5ldyBTcXVhcmVBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJDaXJjbGUiOgogICAgICAgIHJldHVybiBuZXcgQ2lyY2xlQW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiUG9seUxpbmUiOgogICAgICAgIHJldHVybiBuZXcgUG9seWxpbmVBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJQb2x5Z29uIjoKICAgICAgICByZXR1cm4gbmV3IFBvbHlnb25Bbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJDYXJldCI6CiAgICAgICAgcmV0dXJuIG5ldyBDYXJldEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIkluayI6CiAgICAgICAgcmV0dXJuIG5ldyBJbmtBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJIaWdobGlnaHQiOgogICAgICAgIHJldHVybiBuZXcgSGlnaGxpZ2h0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiVW5kZXJsaW5lIjoKICAgICAgICByZXR1cm4gbmV3IFVuZGVybGluZUFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIlNxdWlnZ2x5IjoKICAgICAgICByZXR1cm4gbmV3IFNxdWlnZ2x5QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiU3RyaWtlT3V0IjoKICAgICAgICByZXR1cm4gbmV3IFN0cmlrZU91dEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIlN0YW1wIjoKICAgICAgICByZXR1cm4gbmV3IFN0YW1wQW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiRmlsZUF0dGFjaG1lbnQiOgogICAgICAgIHJldHVybiBuZXcgRmlsZUF0dGFjaG1lbnRBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBkZWZhdWx0OgogICAgICAgIGlmICghY29sbGVjdEZpZWxkcykgewogICAgICAgICAgaWYgKCFzdWJ0eXBlKSB7CiAgICAgICAgICAgIHdhcm4oIkFubm90YXRpb24gaXMgbWlzc2luZyB0aGUgcmVxdWlyZWQgL1N1YnR5cGUuIik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB3YXJuKGBVbmltcGxlbWVudGVkIGFubm90YXRpb24gdHlwZSAiJHtzdWJ0eXBlfSIsIGAgKyAiZmFsbGluZyBiYWNrIHRvIGJhc2UgYW5ub3RhdGlvbi4iKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgfQogIH0KICBzdGF0aWMgYXN5bmMgX2dldFBhZ2VJbmRleCh4cmVmLCByZWYsIHBkZk1hbmFnZXIpIHsKICAgIHRyeSB7CiAgICAgIGNvbnN0IGFubm90RGljdCA9IGF3YWl0IHhyZWYuZmV0Y2hJZlJlZkFzeW5jKHJlZik7CiAgICAgIGlmICghKGFubm90RGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgcmV0dXJuIC0xOwogICAgICB9CiAgICAgIGNvbnN0IHBhZ2VSZWYgPSBhbm5vdERpY3QuZ2V0UmF3KCJQIik7CiAgICAgIGlmIChwYWdlUmVmIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGNvbnN0IHBhZ2VJbmRleCA9IGF3YWl0IHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiZ2V0UGFnZUluZGV4IiwgW3BhZ2VSZWZdKTsKICAgICAgICAgIHJldHVybiBwYWdlSW5kZXg7CiAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgIGluZm8oYF9nZXRQYWdlSW5kZXggLS0gbm90IGEgdmFsaWQgcGFnZSByZWZlcmVuY2U6ICIke2V4fSIuYCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChhbm5vdERpY3QuaGFzKCJLaWRzIikpIHsKICAgICAgICByZXR1cm4gLTE7CiAgICAgIH0KICAgICAgY29uc3QgbnVtUGFnZXMgPSBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZURvYygibnVtUGFnZXMiKTsKICAgICAgZm9yIChsZXQgcGFnZUluZGV4ID0gMDsgcGFnZUluZGV4IDwgbnVtUGFnZXM7IHBhZ2VJbmRleCsrKSB7CiAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IHBkZk1hbmFnZXIuZ2V0UGFnZShwYWdlSW5kZXgpOwogICAgICAgIGNvbnN0IGFubm90YXRpb25zID0gYXdhaXQgcGRmTWFuYWdlci5lbnN1cmUocGFnZSwgImFubm90YXRpb25zIik7CiAgICAgICAgZm9yIChjb25zdCBhbm5vdFJlZiBvZiBhbm5vdGF0aW9ucykgewogICAgICAgICAgaWYgKGFubm90UmVmIGluc3RhbmNlb2YgUmVmICYmIGlzUmVmc0VxdWFsKGFubm90UmVmLCByZWYpKSB7CiAgICAgICAgICAgIHJldHVybiBwYWdlSW5kZXg7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9IGNhdGNoIChleCkgewogICAgICB3YXJuKGBfZ2V0UGFnZUluZGV4OiAiJHtleH0iLmApOwogICAgfQogICAgcmV0dXJuIC0xOwogIH0KICBzdGF0aWMgZ2VuZXJhdGVJbWFnZXMoYW5ub3RhdGlvbnMsIHhyZWYsIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICBpZiAoIWlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICAgIHdhcm4oImdlbmVyYXRlSW1hZ2VzOiBPZmZzY3JlZW5DYW52YXMgaXMgbm90IHN1cHBvcnRlZCwgY2Fubm90IHNhdmUgb3IgcHJpbnQgc29tZSBhbm5vdGF0aW9ucyB3aXRoIGltYWdlcy4iKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBsZXQgaW1hZ2VQcm9taXNlczsKICAgIGZvciAoY29uc3QgewogICAgICBiaXRtYXBJZCwKICAgICAgYml0bWFwCiAgICB9IG9mIGFubm90YXRpb25zKSB7CiAgICAgIGlmICghYml0bWFwKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaW1hZ2VQcm9taXNlcyB8fD0gbmV3IE1hcCgpOwogICAgICBpbWFnZVByb21pc2VzLnNldChiaXRtYXBJZCwgU3RhbXBBbm5vdGF0aW9uLmNyZWF0ZUltYWdlKGJpdG1hcCwgeHJlZikpOwogICAgfQogICAgcmV0dXJuIGltYWdlUHJvbWlzZXM7CiAgfQogIHN0YXRpYyBhc3luYyBzYXZlTmV3QW5ub3RhdGlvbnMoZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9ucywgaW1hZ2VQcm9taXNlcywgY2hhbmdlcykgewogICAgY29uc3QgeHJlZiA9IGV2YWx1YXRvci54cmVmOwogICAgbGV0IGJhc2VGb250UmVmOwogICAgY29uc3QgcHJvbWlzZXMgPSBbXTsKICAgIGNvbnN0IHsKICAgICAgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQKICAgIH0gPSBldmFsdWF0b3Iub3B0aW9uczsKICAgIGZvciAoY29uc3QgYW5ub3RhdGlvbiBvZiBhbm5vdGF0aW9ucykgewogICAgICBpZiAoYW5ub3RhdGlvbi5kZWxldGVkKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgc3dpdGNoIChhbm5vdGF0aW9uLmFubm90YXRpb25UeXBlKSB7CiAgICAgICAgY2FzZSBBbm5vdGF0aW9uRWRpdG9yVHlwZS5GUkVFVEVYVDoKICAgICAgICAgIGlmICghYmFzZUZvbnRSZWYpIHsKICAgICAgICAgICAgY29uc3QgYmFzZUZvbnQgPSBuZXcgRGljdCh4cmVmKTsKICAgICAgICAgICAgYmFzZUZvbnQuc2V0SWZOYW1lKCJCYXNlRm9udCIsICJIZWx2ZXRpY2EiKTsKICAgICAgICAgICAgYmFzZUZvbnQuc2V0SWZOYW1lKCJUeXBlIiwgIkZvbnQiKTsKICAgICAgICAgICAgYmFzZUZvbnQuc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIlR5cGUxIik7CiAgICAgICAgICAgIGJhc2VGb250LnNldElmTmFtZSgiRW5jb2RpbmciLCAiV2luQW5zaUVuY29kaW5nIik7CiAgICAgICAgICAgIGJhc2VGb250UmVmID0geHJlZi5nZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgICAgICAgY2hhbmdlcy5wdXQoYmFzZUZvbnRSZWYsIHsKICAgICAgICAgICAgICBkYXRhOiBiYXNlRm9udAogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIHByb21pc2VzLnB1c2goRnJlZVRleHRBbm5vdGF0aW9uLmNyZWF0ZU5ld0Fubm90YXRpb24oeHJlZiwgYW5ub3RhdGlvbiwgY2hhbmdlcywgewogICAgICAgICAgICBldmFsdWF0b3IsCiAgICAgICAgICAgIHRhc2ssCiAgICAgICAgICAgIGJhc2VGb250UmVmCiAgICAgICAgICB9KSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIEFubm90YXRpb25FZGl0b3JUeXBlLkhJR0hMSUdIVDoKICAgICAgICAgIGlmIChhbm5vdGF0aW9uLnF1YWRQb2ludHMpIHsKICAgICAgICAgICAgcHJvbWlzZXMucHVzaChIaWdobGlnaHRBbm5vdGF0aW9uLmNyZWF0ZU5ld0Fubm90YXRpb24oeHJlZiwgYW5ub3RhdGlvbiwgY2hhbmdlcykpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcHJvbWlzZXMucHVzaChJbmtBbm5vdGF0aW9uLmNyZWF0ZU5ld0Fubm90YXRpb24oeHJlZiwgYW5ub3RhdGlvbiwgY2hhbmdlcykpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBBbm5vdGF0aW9uRWRpdG9yVHlwZS5JTks6CiAgICAgICAgICBwcm9taXNlcy5wdXNoKElua0Fubm90YXRpb24uY3JlYXRlTmV3QW5ub3RhdGlvbih4cmVmLCBhbm5vdGF0aW9uLCBjaGFuZ2VzKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIEFubm90YXRpb25FZGl0b3JUeXBlLlNUQU1QOgogICAgICAgICAgY29uc3QgaW1hZ2UgPSBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCA/IGF3YWl0IGltYWdlUHJvbWlzZXM/LmdldChhbm5vdGF0aW9uLmJpdG1hcElkKSA6IG51bGw7CiAgICAgICAgICBpZiAoaW1hZ2U/LmltYWdlU3RyZWFtKSB7CiAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICBpbWFnZVN0cmVhbSwKICAgICAgICAgICAgICBzbWFza1N0cmVhbQogICAgICAgICAgICB9ID0gaW1hZ2U7CiAgICAgICAgICAgIGlmIChzbWFza1N0cmVhbSkgewogICAgICAgICAgICAgIGNvbnN0IHNtYXNrUmVmID0geHJlZi5nZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgICAgICAgICBjaGFuZ2VzLnB1dChzbWFza1JlZiwgewogICAgICAgICAgICAgICAgZGF0YTogc21hc2tTdHJlYW0KICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICBpbWFnZVN0cmVhbS5kaWN0LnNldCgiU01hc2siLCBzbWFza1JlZik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgaW1hZ2VSZWYgPSBpbWFnZS5pbWFnZVJlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICAgICAgICAgIGNoYW5nZXMucHV0KGltYWdlUmVmLCB7CiAgICAgICAgICAgICAgZGF0YTogaW1hZ2VTdHJlYW0KICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGltYWdlLmltYWdlU3RyZWFtID0gaW1hZ2Uuc21hc2tTdHJlYW0gPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgcHJvbWlzZXMucHVzaChTdGFtcEFubm90YXRpb24uY3JlYXRlTmV3QW5ub3RhdGlvbih4cmVmLCBhbm5vdGF0aW9uLCBjaGFuZ2VzLCB7CiAgICAgICAgICAgIGltYWdlCiAgICAgICAgICB9KSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIEFubm90YXRpb25FZGl0b3JUeXBlLlNJR05BVFVSRToKICAgICAgICAgIHByb21pc2VzLnB1c2goU3RhbXBBbm5vdGF0aW9uLmNyZWF0ZU5ld0Fubm90YXRpb24oeHJlZiwgYW5ub3RhdGlvbiwgY2hhbmdlcywge30pKTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gewogICAgICBhbm5vdGF0aW9uczogKGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKSkuZmxhdCgpCiAgICB9OwogIH0KICBzdGF0aWMgYXN5bmMgcHJpbnROZXdBbm5vdGF0aW9ucyhhbm5vdGF0aW9uR2xvYmFscywgZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9ucywgaW1hZ2VQcm9taXNlcykgewogICAgaWYgKCFhbm5vdGF0aW9ucykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgb3B0aW9ucywKICAgICAgeHJlZgogICAgfSA9IGV2YWx1YXRvcjsKICAgIGNvbnN0IHByb21pc2VzID0gW107CiAgICBmb3IgKGNvbnN0IGFubm90YXRpb24gb2YgYW5ub3RhdGlvbnMpIHsKICAgICAgaWYgKGFubm90YXRpb24uZGVsZXRlZCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHN3aXRjaCAoYW5ub3RhdGlvbi5hbm5vdGF0aW9uVHlwZSkgewogICAgICAgIGNhc2UgQW5ub3RhdGlvbkVkaXRvclR5cGUuRlJFRVRFWFQ6CiAgICAgICAgICBwcm9taXNlcy5wdXNoKEZyZWVUZXh0QW5ub3RhdGlvbi5jcmVhdGVOZXdQcmludEFubm90YXRpb24oYW5ub3RhdGlvbkdsb2JhbHMsIHhyZWYsIGFubm90YXRpb24sIHsKICAgICAgICAgICAgZXZhbHVhdG9yLAogICAgICAgICAgICB0YXNrLAogICAgICAgICAgICBldmFsdWF0b3JPcHRpb25zOiBvcHRpb25zCiAgICAgICAgICB9KSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIEFubm90YXRpb25FZGl0b3JUeXBlLkhJR0hMSUdIVDoKICAgICAgICAgIGlmIChhbm5vdGF0aW9uLnF1YWRQb2ludHMpIHsKICAgICAgICAgICAgcHJvbWlzZXMucHVzaChIaWdobGlnaHRBbm5vdGF0aW9uLmNyZWF0ZU5ld1ByaW50QW5ub3RhdGlvbihhbm5vdGF0aW9uR2xvYmFscywgeHJlZiwgYW5ub3RhdGlvbiwgewogICAgICAgICAgICAgIGV2YWx1YXRvck9wdGlvbnM6IG9wdGlvbnMKICAgICAgICAgICAgfSkpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcHJvbWlzZXMucHVzaChJbmtBbm5vdGF0aW9uLmNyZWF0ZU5ld1ByaW50QW5ub3RhdGlvbihhbm5vdGF0aW9uR2xvYmFscywgeHJlZiwgYW5ub3RhdGlvbiwgewogICAgICAgICAgICAgIGV2YWx1YXRvck9wdGlvbnM6IG9wdGlvbnMKICAgICAgICAgICAgfSkpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBBbm5vdGF0aW9uRWRpdG9yVHlwZS5JTks6CiAgICAgICAgICBwcm9taXNlcy5wdXNoKElua0Fubm90YXRpb24uY3JlYXRlTmV3UHJpbnRBbm5vdGF0aW9uKGFubm90YXRpb25HbG9iYWxzLCB4cmVmLCBhbm5vdGF0aW9uLCB7CiAgICAgICAgICAgIGV2YWx1YXRvck9wdGlvbnM6IG9wdGlvbnMKICAgICAgICAgIH0pKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgQW5ub3RhdGlvbkVkaXRvclR5cGUuU1RBTVA6CiAgICAgICAgICBjb25zdCBpbWFnZSA9IG9wdGlvbnMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgPyBhd2FpdCBpbWFnZVByb21pc2VzPy5nZXQoYW5ub3RhdGlvbi5iaXRtYXBJZCkgOiBudWxsOwogICAgICAgICAgaWYgKGltYWdlPy5pbWFnZVN0cmVhbSkgewogICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgaW1hZ2VTdHJlYW0sCiAgICAgICAgICAgICAgc21hc2tTdHJlYW0KICAgICAgICAgICAgfSA9IGltYWdlOwogICAgICAgICAgICBpZiAoc21hc2tTdHJlYW0pIHsKICAgICAgICAgICAgICBpbWFnZVN0cmVhbS5kaWN0LnNldCgiU01hc2siLCBzbWFza1N0cmVhbSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaW1hZ2UuaW1hZ2VSZWYgPSBuZXcgSnBlZ1N0cmVhbShpbWFnZVN0cmVhbSwgaW1hZ2VTdHJlYW0ubGVuZ3RoKTsKICAgICAgICAgICAgaW1hZ2UuaW1hZ2VTdHJlYW0gPSBpbWFnZS5zbWFza1N0cmVhbSA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBwcm9taXNlcy5wdXNoKFN0YW1wQW5ub3RhdGlvbi5jcmVhdGVOZXdQcmludEFubm90YXRpb24oYW5ub3RhdGlvbkdsb2JhbHMsIHhyZWYsIGFubm90YXRpb24sIHsKICAgICAgICAgICAgaW1hZ2UsCiAgICAgICAgICAgIGV2YWx1YXRvck9wdGlvbnM6IG9wdGlvbnMKICAgICAgICAgIH0pKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgQW5ub3RhdGlvbkVkaXRvclR5cGUuU0lHTkFUVVJFOgogICAgICAgICAgcHJvbWlzZXMucHVzaChTdGFtcEFubm90YXRpb24uY3JlYXRlTmV3UHJpbnRBbm5vdGF0aW9uKGFubm90YXRpb25HbG9iYWxzLCB4cmVmLCBhbm5vdGF0aW9uLCB7CiAgICAgICAgICAgIGV2YWx1YXRvck9wdGlvbnM6IG9wdGlvbnMKICAgICAgICAgIH0pKTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpOwogIH0KfQpmdW5jdGlvbiBnZXRSZ2JDb2xvcihjb2xvciwgZGVmYXVsdENvbG9yID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDMpKSB7CiAgaWYgKCFBcnJheS5pc0FycmF5KGNvbG9yKSkgewogICAgcmV0dXJuIGRlZmF1bHRDb2xvcjsKICB9CiAgY29uc3QgcmdiQ29sb3IgPSBkZWZhdWx0Q29sb3IgfHwgbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDMpOwogIHN3aXRjaCAoY29sb3IubGVuZ3RoKSB7CiAgICBjYXNlIDA6CiAgICAgIHJldHVybiBudWxsOwogICAgY2FzZSAxOgogICAgICBDb2xvclNwYWNlVXRpbHMuZ3JheS5nZXRSZ2JJdGVtKGNvbG9yLCAwLCByZ2JDb2xvciwgMCk7CiAgICAgIHJldHVybiByZ2JDb2xvcjsKICAgIGNhc2UgMzoKICAgICAgQ29sb3JTcGFjZVV0aWxzLnJnYi5nZXRSZ2JJdGVtKGNvbG9yLCAwLCByZ2JDb2xvciwgMCk7CiAgICAgIHJldHVybiByZ2JDb2xvcjsKICAgIGNhc2UgNDoKICAgICAgQ29sb3JTcGFjZVV0aWxzLmNteWsuZ2V0UmdiSXRlbShjb2xvciwgMCwgcmdiQ29sb3IsIDApOwogICAgICByZXR1cm4gcmdiQ29sb3I7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gZGVmYXVsdENvbG9yOwogIH0KfQpmdW5jdGlvbiBnZXRQZGZDb2xvckFycmF5KGNvbG9yLCBkZWZhdWx0VmFsdWUgPSBudWxsKSB7CiAgcmV0dXJuIGNvbG9yICYmIEFycmF5LmZyb20oY29sb3IsIGMgPT4gYyAvIDI1NSkgfHwgZGVmYXVsdFZhbHVlOwp9CmZ1bmN0aW9uIGdldFF1YWRQb2ludHMoZGljdCwgcmVjdCkgewogIGNvbnN0IHF1YWRQb2ludHMgPSBkaWN0LmdldEFycmF5KCJRdWFkUG9pbnRzIik7CiAgaWYgKCFpc051bWJlckFycmF5KHF1YWRQb2ludHMsIG51bGwpIHx8IHF1YWRQb2ludHMubGVuZ3RoID09PSAwIHx8IHF1YWRQb2ludHMubGVuZ3RoICUgOCA+IDApIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCBuZXdRdWFkUG9pbnRzID0gbmV3IEZsb2F0MzJBcnJheShxdWFkUG9pbnRzLmxlbmd0aCk7CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gcXVhZFBvaW50cy5sZW5ndGg7IGkgPCBpaTsgaSArPSA4KSB7CiAgICBjb25zdCBbeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgeDQsIHk0XSA9IHF1YWRQb2ludHMuc2xpY2UoaSwgaSArIDgpOwogICAgY29uc3QgbWluWCA9IE1hdGgubWluKHgxLCB4MiwgeDMsIHg0KTsKICAgIGNvbnN0IG1heFggPSBNYXRoLm1heCh4MSwgeDIsIHgzLCB4NCk7CiAgICBjb25zdCBtaW5ZID0gTWF0aC5taW4oeTEsIHkyLCB5MywgeTQpOwogICAgY29uc3QgbWF4WSA9IE1hdGgubWF4KHkxLCB5MiwgeTMsIHk0KTsKICAgIGlmIChyZWN0ICE9PSBudWxsICYmIChtaW5YIDwgcmVjdFswXSB8fCBtYXhYID4gcmVjdFsyXSB8fCBtaW5ZIDwgcmVjdFsxXSB8fCBtYXhZID4gcmVjdFszXSkpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBuZXdRdWFkUG9pbnRzLnNldChbbWluWCwgbWF4WSwgbWF4WCwgbWF4WSwgbWluWCwgbWluWSwgbWF4WCwgbWluWV0sIGkpOwogIH0KICByZXR1cm4gbmV3UXVhZFBvaW50czsKfQpmdW5jdGlvbiBnZXRUcmFuc2Zvcm1NYXRyaXgocmVjdCwgYmJveCwgbWF0cml4KSB7CiAgY29uc3QgbWluTWF4ID0gbmV3IEZsb2F0MzJBcnJheShbSW5maW5pdHksIEluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV0pOwogIFV0aWwuYXhpYWxBbGlnbmVkQm91bmRpbmdCb3goYmJveCwgbWF0cml4LCBtaW5NYXgpOwogIGNvbnN0IFttaW5YLCBtaW5ZLCBtYXhYLCBtYXhZXSA9IG1pbk1heDsKICBpZiAobWluWCA9PT0gbWF4WCB8fCBtaW5ZID09PSBtYXhZKSB7CiAgICByZXR1cm4gWzEsIDAsIDAsIDEsIHJlY3RbMF0sIHJlY3RbMV1dOwogIH0KICBjb25zdCB4UmF0aW8gPSAocmVjdFsyXSAtIHJlY3RbMF0pIC8gKG1heFggLSBtaW5YKTsKICBjb25zdCB5UmF0aW8gPSAocmVjdFszXSAtIHJlY3RbMV0pIC8gKG1heFkgLSBtaW5ZKTsKICByZXR1cm4gW3hSYXRpbywgMCwgMCwgeVJhdGlvLCByZWN0WzBdIC0gbWluWCAqIHhSYXRpbywgcmVjdFsxXSAtIG1pblkgKiB5UmF0aW9dOwp9CmNsYXNzIEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmLAogICAgICBhbm5vdGF0aW9uR2xvYmFscywKICAgICAgcmVmLAogICAgICBvcnBoYW5GaWVsZHMKICAgIH0gPSBwYXJhbXM7CiAgICBjb25zdCBwYXJlbnRSZWYgPSBvcnBoYW5GaWVsZHM/LmdldChyZWYpOwogICAgaWYgKHBhcmVudFJlZikgewogICAgICBkaWN0LnNldCgiUGFyZW50IiwgcGFyZW50UmVmKTsKICAgIH0KICAgIHRoaXMuc2V0VGl0bGUoZGljdC5nZXQoIlQiKSk7CiAgICB0aGlzLnNldENvbnRlbnRzKGRpY3QuZ2V0KCJDb250ZW50cyIpKTsKICAgIHRoaXMuc2V0TW9kaWZpY2F0aW9uRGF0ZShkaWN0LmdldCgiTSIpKTsKICAgIHRoaXMuc2V0RmxhZ3MoZGljdC5nZXQoIkYiKSk7CiAgICB0aGlzLnNldFJlY3RhbmdsZShkaWN0LmdldEFycmF5KCJSZWN0IikpOwogICAgdGhpcy5zZXRDb2xvcihkaWN0LmdldEFycmF5KCJDIikpOwogICAgdGhpcy5zZXRCb3JkZXJTdHlsZShkaWN0KTsKICAgIHRoaXMuc2V0QXBwZWFyYW5jZShkaWN0KTsKICAgIHRoaXMuc2V0T3B0aW9uYWxDb250ZW50KGRpY3QpOwogICAgY29uc3QgTUsgPSBkaWN0LmdldCgiTUsiKTsKICAgIHRoaXMuc2V0Qm9yZGVyQW5kQmFja2dyb3VuZENvbG9ycyhNSyk7CiAgICB0aGlzLnNldFJvdGF0aW9uKE1LLCBkaWN0KTsKICAgIHRoaXMucmVmID0gcGFyYW1zLnJlZiBpbnN0YW5jZW9mIFJlZiA/IHBhcmFtcy5yZWYgOiBudWxsOwogICAgdGhpcy5fc3RyZWFtcyA9IFtdOwogICAgaWYgKHRoaXMuYXBwZWFyYW5jZSkgewogICAgICB0aGlzLl9zdHJlYW1zLnB1c2godGhpcy5hcHBlYXJhbmNlKTsKICAgIH0KICAgIGNvbnN0IGlzTG9ja2VkID0gISEodGhpcy5mbGFncyAmIEFubm90YXRpb25GbGFnLkxPQ0tFRCk7CiAgICBjb25zdCBpc0NvbnRlbnRMb2NrZWQgPSAhISh0aGlzLmZsYWdzICYgQW5ub3RhdGlvbkZsYWcuTE9DS0VEQ09OVEVOVFMpOwogICAgdGhpcy5kYXRhID0gewogICAgICBhbm5vdGF0aW9uRmxhZ3M6IHRoaXMuZmxhZ3MsCiAgICAgIGJvcmRlclN0eWxlOiB0aGlzLmJvcmRlclN0eWxlLAogICAgICBjb2xvcjogdGhpcy5jb2xvciwKICAgICAgYmFja2dyb3VuZENvbG9yOiB0aGlzLmJhY2tncm91bmRDb2xvciwKICAgICAgYm9yZGVyQ29sb3I6IHRoaXMuYm9yZGVyQ29sb3IsCiAgICAgIHJvdGF0aW9uOiB0aGlzLnJvdGF0aW9uLAogICAgICBjb250ZW50c09iajogdGhpcy5fY29udGVudHMsCiAgICAgIGhhc0FwcGVhcmFuY2U6ICEhdGhpcy5hcHBlYXJhbmNlLAogICAgICBpZDogcGFyYW1zLmlkLAogICAgICBtb2RpZmljYXRpb25EYXRlOiB0aGlzLm1vZGlmaWNhdGlvbkRhdGUsCiAgICAgIHJlY3Q6IHRoaXMucmVjdGFuZ2xlLAogICAgICBzdWJ0eXBlOiBwYXJhbXMuc3VidHlwZSwKICAgICAgaGFzT3duQ2FudmFzOiBmYWxzZSwKICAgICAgbm9Sb3RhdGU6ICEhKHRoaXMuZmxhZ3MgJiBBbm5vdGF0aW9uRmxhZy5OT1JPVEFURSksCiAgICAgIG5vSFRNTDogaXNMb2NrZWQgJiYgaXNDb250ZW50TG9ja2VkLAogICAgICBpc0VkaXRhYmxlOiBmYWxzZSwKICAgICAgc3RydWN0UGFyZW50OiAtMQogICAgfTsKICAgIGlmIChhbm5vdGF0aW9uR2xvYmFscy5zdHJ1Y3RUcmVlUm9vdCkgewogICAgICBsZXQgc3RydWN0UGFyZW50ID0gZGljdC5nZXQoIlN0cnVjdFBhcmVudCIpOwogICAgICB0aGlzLmRhdGEuc3RydWN0UGFyZW50ID0gc3RydWN0UGFyZW50ID0gTnVtYmVyLmlzSW50ZWdlcihzdHJ1Y3RQYXJlbnQpICYmIHN0cnVjdFBhcmVudCA+PSAwID8gc3RydWN0UGFyZW50IDogLTE7CiAgICAgIGFubm90YXRpb25HbG9iYWxzLnN0cnVjdFRyZWVSb290LmFkZEFubm90YXRpb25JZFRvUGFnZShwYXJhbXMucGFnZVJlZiwgc3RydWN0UGFyZW50KTsKICAgIH0KICAgIGlmIChwYXJhbXMuY29sbGVjdEZpZWxkcykgewogICAgICBjb25zdCBraWRzID0gZGljdC5nZXQoIktpZHMiKTsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkoa2lkcykpIHsKICAgICAgICBjb25zdCBraWRJZHMgPSBbXTsKICAgICAgICBmb3IgKGNvbnN0IGtpZCBvZiBraWRzKSB7CiAgICAgICAgICBpZiAoa2lkIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICAgIGtpZElkcy5wdXNoKGtpZC50b1N0cmluZygpKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGtpZElkcy5sZW5ndGggIT09IDApIHsKICAgICAgICAgIHRoaXMuZGF0YS5raWRJZHMgPSBraWRJZHM7CiAgICAgICAgfQogICAgICB9CiAgICAgIHRoaXMuZGF0YS5hY3Rpb25zID0gY29sbGVjdEFjdGlvbnMoeHJlZiwgZGljdCwgQW5ub3RhdGlvbkFjdGlvbkV2ZW50VHlwZSk7CiAgICAgIHRoaXMuZGF0YS5maWVsZE5hbWUgPSB0aGlzLl9jb25zdHJ1Y3RGaWVsZE5hbWUoZGljdCk7CiAgICAgIHRoaXMuZGF0YS5wYWdlSW5kZXggPSBwYXJhbXMucGFnZUluZGV4OwogICAgfQogICAgY29uc3QgaXQgPSBkaWN0LmdldCgiSVQiKTsKICAgIGlmIChpdCBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgdGhpcy5kYXRhLml0ID0gaXQubmFtZTsKICAgIH0KICAgIHRoaXMuX2lzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkID0gcGFyYW1zLmV2YWx1YXRvck9wdGlvbnMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQ7CiAgICB0aGlzLl9mYWxsYmFja0ZvbnREaWN0ID0gbnVsbDsKICAgIHRoaXMuX25lZWRBcHBlYXJhbmNlcyA9IGZhbHNlOwogIH0KICBfaGFzRmxhZyhmbGFncywgZmxhZykgewogICAgcmV0dXJuICEhKGZsYWdzICYgZmxhZyk7CiAgfQogIF9idWlsZEZsYWdzKG5vVmlldywgbm9QcmludCkgewogICAgbGV0IHsKICAgICAgZmxhZ3MKICAgIH0gPSB0aGlzOwogICAgaWYgKG5vVmlldyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmIChub1ByaW50ID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgICB9CiAgICAgIGlmIChub1ByaW50KSB7CiAgICAgICAgcmV0dXJuIGZsYWdzICYgfkFubm90YXRpb25GbGFnLlBSSU5UOwogICAgICB9CiAgICAgIHJldHVybiBmbGFncyAmIH5Bbm5vdGF0aW9uRmxhZy5ISURERU4gfCBBbm5vdGF0aW9uRmxhZy5QUklOVDsKICAgIH0KICAgIGlmIChub1ZpZXcpIHsKICAgICAgZmxhZ3MgfD0gQW5ub3RhdGlvbkZsYWcuUFJJTlQ7CiAgICAgIGlmIChub1ByaW50KSB7CiAgICAgICAgcmV0dXJuIGZsYWdzICYgfkFubm90YXRpb25GbGFnLk5PVklFVyB8IEFubm90YXRpb25GbGFnLkhJRERFTjsKICAgICAgfQogICAgICByZXR1cm4gZmxhZ3MgJiB+QW5ub3RhdGlvbkZsYWcuSElEREVOIHwgQW5ub3RhdGlvbkZsYWcuTk9WSUVXOwogICAgfQogICAgZmxhZ3MgJj0gfihBbm5vdGF0aW9uRmxhZy5ISURERU4gfCBBbm5vdGF0aW9uRmxhZy5OT1ZJRVcpOwogICAgaWYgKG5vUHJpbnQpIHsKICAgICAgcmV0dXJuIGZsYWdzICYgfkFubm90YXRpb25GbGFnLlBSSU5UOwogICAgfQogICAgcmV0dXJuIGZsYWdzIHwgQW5ub3RhdGlvbkZsYWcuUFJJTlQ7CiAgfQogIF9pc1ZpZXdhYmxlKGZsYWdzKSB7CiAgICByZXR1cm4gIXRoaXMuX2hhc0ZsYWcoZmxhZ3MsIEFubm90YXRpb25GbGFnLklOVklTSUJMRSkgJiYgIXRoaXMuX2hhc0ZsYWcoZmxhZ3MsIEFubm90YXRpb25GbGFnLk5PVklFVyk7CiAgfQogIF9pc1ByaW50YWJsZShmbGFncykgewogICAgcmV0dXJuIHRoaXMuX2hhc0ZsYWcoZmxhZ3MsIEFubm90YXRpb25GbGFnLlBSSU5UKSAmJiAhdGhpcy5faGFzRmxhZyhmbGFncywgQW5ub3RhdGlvbkZsYWcuSElEREVOKSAmJiAhdGhpcy5faGFzRmxhZyhmbGFncywgQW5ub3RhdGlvbkZsYWcuSU5WSVNJQkxFKTsKICB9CiAgbXVzdEJlVmlld2VkKGFubm90YXRpb25TdG9yYWdlLCBfcmVuZGVyRm9ybXMpIHsKICAgIGNvbnN0IG5vVmlldyA9IGFubm90YXRpb25TdG9yYWdlPy5nZXQodGhpcy5kYXRhLmlkKT8ubm9WaWV3OwogICAgaWYgKG5vVmlldyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiAhbm9WaWV3OwogICAgfQogICAgcmV0dXJuIHRoaXMudmlld2FibGUgJiYgIXRoaXMuX2hhc0ZsYWcodGhpcy5mbGFncywgQW5ub3RhdGlvbkZsYWcuSElEREVOKTsKICB9CiAgbXVzdEJlUHJpbnRlZChhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgY29uc3Qgbm9QcmludCA9IGFubm90YXRpb25TdG9yYWdlPy5nZXQodGhpcy5kYXRhLmlkKT8ubm9QcmludDsKICAgIGlmIChub1ByaW50ICE9PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuICFub1ByaW50OwogICAgfQogICAgcmV0dXJuIHRoaXMucHJpbnRhYmxlOwogIH0KICBtdXN0QmVWaWV3ZWRXaGVuRWRpdGluZyhpc0VkaXRpbmcsIG1vZGlmaWVkSWRzID0gbnVsbCkgewogICAgcmV0dXJuIGlzRWRpdGluZyA/ICF0aGlzLmRhdGEuaXNFZGl0YWJsZSA6ICFtb2RpZmllZElkcz8uaGFzKHRoaXMuZGF0YS5pZCk7CiAgfQogIGdldCB2aWV3YWJsZSgpIHsKICAgIGlmICh0aGlzLmRhdGEucXVhZFBvaW50cyA9PT0gbnVsbCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy5mbGFncyA9PT0gMCkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiB0aGlzLl9pc1ZpZXdhYmxlKHRoaXMuZmxhZ3MpOwogIH0KICBnZXQgcHJpbnRhYmxlKCkgewogICAgaWYgKHRoaXMuZGF0YS5xdWFkUG9pbnRzID09PSBudWxsKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmICh0aGlzLmZsYWdzID09PSAwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHJldHVybiB0aGlzLl9pc1ByaW50YWJsZSh0aGlzLmZsYWdzKTsKICB9CiAgX3BhcnNlU3RyaW5nSGVscGVyKGRhdGEpIHsKICAgIGNvbnN0IHN0ciA9IHR5cGVvZiBkYXRhID09PSAic3RyaW5nIiA/IHN0cmluZ1RvUERGU3RyaW5nKGRhdGEpIDogIiI7CiAgICBjb25zdCBkaXIgPSBzdHIgJiYgYmlkaShzdHIpLmRpciA9PT0gInJ0bCIgPyAicnRsIiA6ICJsdHIiOwogICAgcmV0dXJuIHsKICAgICAgc3RyLAogICAgICBkaXIKICAgIH07CiAgfQogIHNldERlZmF1bHRBcHBlYXJhbmNlKHBhcmFtcykgewogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICBhbm5vdGF0aW9uR2xvYmFscwogICAgfSA9IHBhcmFtczsKICAgIGNvbnN0IGRlZmF1bHRBcHBlYXJhbmNlID0gZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7CiAgICAgIGRpY3QsCiAgICAgIGtleTogIkRBIgogICAgfSkgfHwgYW5ub3RhdGlvbkdsb2JhbHMuYWNyb0Zvcm0uZ2V0KCJEQSIpOwogICAgdGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UgPSB0eXBlb2YgZGVmYXVsdEFwcGVhcmFuY2UgPT09ICJzdHJpbmciID8gZGVmYXVsdEFwcGVhcmFuY2UgOiAiIjsKICAgIHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEgPSBwYXJzZURlZmF1bHRBcHBlYXJhbmNlKHRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlKTsKICB9CiAgc2V0VGl0bGUodGl0bGUpIHsKICAgIHRoaXMuX3RpdGxlID0gdGhpcy5fcGFyc2VTdHJpbmdIZWxwZXIodGl0bGUpOwogIH0KICBzZXRDb250ZW50cyhjb250ZW50cykgewogICAgdGhpcy5fY29udGVudHMgPSB0aGlzLl9wYXJzZVN0cmluZ0hlbHBlcihjb250ZW50cyk7CiAgfQogIHNldE1vZGlmaWNhdGlvbkRhdGUobW9kaWZpY2F0aW9uRGF0ZSkgewogICAgdGhpcy5tb2RpZmljYXRpb25EYXRlID0gdHlwZW9mIG1vZGlmaWNhdGlvbkRhdGUgPT09ICJzdHJpbmciID8gbW9kaWZpY2F0aW9uRGF0ZSA6IG51bGw7CiAgfQogIHNldEZsYWdzKGZsYWdzKSB7CiAgICB0aGlzLmZsYWdzID0gTnVtYmVyLmlzSW50ZWdlcihmbGFncykgJiYgZmxhZ3MgPiAwID8gZmxhZ3MgOiAwOwogICAgaWYgKHRoaXMuZmxhZ3MgJiBBbm5vdGF0aW9uRmxhZy5JTlZJU0lCTEUgJiYgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lICE9PSAiQW5ub3RhdGlvbiIpIHsKICAgICAgdGhpcy5mbGFncyBePSBBbm5vdGF0aW9uRmxhZy5JTlZJU0lCTEU7CiAgICB9CiAgfQogIGhhc0ZsYWcoZmxhZykgewogICAgcmV0dXJuIHRoaXMuX2hhc0ZsYWcodGhpcy5mbGFncywgZmxhZyk7CiAgfQogIHNldFJlY3RhbmdsZShyZWN0YW5nbGUpIHsKICAgIHRoaXMucmVjdGFuZ2xlID0gbG9va3VwTm9ybWFsUmVjdChyZWN0YW5nbGUsIFswLCAwLCAwLCAwXSk7CiAgfQogIHNldENvbG9yKGNvbG9yKSB7CiAgICB0aGlzLmNvbG9yID0gZ2V0UmdiQ29sb3IoY29sb3IpOwogIH0KICBzZXRMaW5lRW5kaW5ncyhsaW5lRW5kaW5ncykgewogICAgdGhpcy5saW5lRW5kaW5ncyA9IFsiTm9uZSIsICJOb25lIl07CiAgICBpZiAoQXJyYXkuaXNBcnJheShsaW5lRW5kaW5ncykgJiYgbGluZUVuZGluZ3MubGVuZ3RoID09PSAyKSB7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMjsgaSsrKSB7CiAgICAgICAgY29uc3Qgb2JqID0gbGluZUVuZGluZ3NbaV07CiAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgIHN3aXRjaCAob2JqLm5hbWUpIHsKICAgICAgICAgICAgY2FzZSAiTm9uZSI6CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIGNhc2UgIlNxdWFyZSI6CiAgICAgICAgICAgIGNhc2UgIkNpcmNsZSI6CiAgICAgICAgICAgIGNhc2UgIkRpYW1vbmQiOgogICAgICAgICAgICBjYXNlICJPcGVuQXJyb3ciOgogICAgICAgICAgICBjYXNlICJDbG9zZWRBcnJvdyI6CiAgICAgICAgICAgIGNhc2UgIkJ1dHQiOgogICAgICAgICAgICBjYXNlICJST3BlbkFycm93IjoKICAgICAgICAgICAgY2FzZSAiUkNsb3NlZEFycm93IjoKICAgICAgICAgICAgY2FzZSAiU2xhc2giOgogICAgICAgICAgICAgIHRoaXMubGluZUVuZGluZ3NbaV0gPSBvYmoubmFtZTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgd2FybihgSWdub3JpbmcgaW52YWxpZCBsaW5lRW5kaW5nOiAke29ian1gKTsKICAgICAgfQogICAgfQogIH0KICBzZXRSb3RhdGlvbihtaywgZGljdCkgewogICAgdGhpcy5yb3RhdGlvbiA9IDA7CiAgICBsZXQgYW5nbGUgPSBtayBpbnN0YW5jZW9mIERpY3QgPyBtay5nZXQoIlIiKSB8fCAwIDogZGljdC5nZXQoIlJvdGF0ZSIpIHx8IDA7CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihhbmdsZSkgJiYgYW5nbGUgIT09IDApIHsKICAgICAgYW5nbGUgJT0gMzYwOwogICAgICBpZiAoYW5nbGUgPCAwKSB7CiAgICAgICAgYW5nbGUgKz0gMzYwOwogICAgICB9CiAgICAgIGlmIChhbmdsZSAlIDkwID09PSAwKSB7CiAgICAgICAgdGhpcy5yb3RhdGlvbiA9IGFuZ2xlOwogICAgICB9CiAgICB9CiAgfQogIHNldEJvcmRlckFuZEJhY2tncm91bmRDb2xvcnMobWspIHsKICAgIGlmIChtayBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgdGhpcy5ib3JkZXJDb2xvciA9IGdldFJnYkNvbG9yKG1rLmdldEFycmF5KCJCQyIpLCBudWxsKTsKICAgICAgdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBnZXRSZ2JDb2xvcihtay5nZXRBcnJheSgiQkciKSwgbnVsbCk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmJvcmRlckNvbG9yID0gdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBudWxsOwogICAgfQogIH0KICBzZXRCb3JkZXJTdHlsZShib3JkZXJTdHlsZSkgewogICAgdGhpcy5ib3JkZXJTdHlsZSA9IG5ldyBBbm5vdGF0aW9uQm9yZGVyU3R5bGUoKTsKICAgIGlmICghKGJvcmRlclN0eWxlIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKGJvcmRlclN0eWxlLmhhcygiQlMiKSkgewogICAgICBjb25zdCBkaWN0ID0gYm9yZGVyU3R5bGUuZ2V0KCJCUyIpOwogICAgICBpZiAoZGljdCBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICBjb25zdCBkaWN0VHlwZSA9IGRpY3QuZ2V0KCJUeXBlIik7CiAgICAgICAgaWYgKCFkaWN0VHlwZSB8fCBpc05hbWUoZGljdFR5cGUsICJCb3JkZXIiKSkgewogICAgICAgICAgdGhpcy5ib3JkZXJTdHlsZS5zZXRXaWR0aChkaWN0LmdldCgiVyIpLCB0aGlzLnJlY3RhbmdsZSk7CiAgICAgICAgICB0aGlzLmJvcmRlclN0eWxlLnNldFN0eWxlKGRpY3QuZ2V0KCJTIikpOwogICAgICAgICAgdGhpcy5ib3JkZXJTdHlsZS5zZXREYXNoQXJyYXkoZGljdC5nZXRBcnJheSgiRCIpKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoYm9yZGVyU3R5bGUuaGFzKCJCb3JkZXIiKSkgewogICAgICBjb25zdCBhcnJheSA9IGJvcmRlclN0eWxlLmdldEFycmF5KCJCb3JkZXIiKTsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYXJyYXkpICYmIGFycmF5Lmxlbmd0aCA+PSAzKSB7CiAgICAgICAgdGhpcy5ib3JkZXJTdHlsZS5zZXRIb3Jpem9udGFsQ29ybmVyUmFkaXVzKGFycmF5WzBdKTsKICAgICAgICB0aGlzLmJvcmRlclN0eWxlLnNldFZlcnRpY2FsQ29ybmVyUmFkaXVzKGFycmF5WzFdKTsKICAgICAgICB0aGlzLmJvcmRlclN0eWxlLnNldFdpZHRoKGFycmF5WzJdLCB0aGlzLnJlY3RhbmdsZSk7CiAgICAgICAgaWYgKGFycmF5Lmxlbmd0aCA9PT0gNCkgewogICAgICAgICAgdGhpcy5ib3JkZXJTdHlsZS5zZXREYXNoQXJyYXkoYXJyYXlbM10sIHRydWUpOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdGhpcy5ib3JkZXJTdHlsZS5zZXRXaWR0aCgwKTsKICAgIH0KICB9CiAgc2V0QXBwZWFyYW5jZShkaWN0KSB7CiAgICB0aGlzLmFwcGVhcmFuY2UgPSBudWxsOwogICAgY29uc3QgYXBwZWFyYW5jZVN0YXRlcyA9IGRpY3QuZ2V0KCJBUCIpOwogICAgaWYgKCEoYXBwZWFyYW5jZVN0YXRlcyBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG5vcm1hbEFwcGVhcmFuY2VTdGF0ZSA9IGFwcGVhcmFuY2VTdGF0ZXMuZ2V0KCJOIik7CiAgICBpZiAobm9ybWFsQXBwZWFyYW5jZVN0YXRlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICB0aGlzLmFwcGVhcmFuY2UgPSBub3JtYWxBcHBlYXJhbmNlU3RhdGU7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICghKG5vcm1hbEFwcGVhcmFuY2VTdGF0ZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGFzID0gZGljdC5nZXQoIkFTIik7CiAgICBpZiAoIShhcyBpbnN0YW5jZW9mIE5hbWUpIHx8ICFub3JtYWxBcHBlYXJhbmNlU3RhdGUuaGFzKGFzLm5hbWUpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGFwcGVhcmFuY2UgPSBub3JtYWxBcHBlYXJhbmNlU3RhdGUuZ2V0KGFzLm5hbWUpOwogICAgaWYgKGFwcGVhcmFuY2UgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgIHRoaXMuYXBwZWFyYW5jZSA9IGFwcGVhcmFuY2U7CiAgICB9CiAgfQogIHNldE9wdGlvbmFsQ29udGVudChkaWN0KSB7CiAgICB0aGlzLm9jID0gbnVsbDsKICAgIGNvbnN0IG9jID0gZGljdC5nZXQoIk9DIik7CiAgICBpZiAob2MgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgIHdhcm4oInNldE9wdGlvbmFsQ29udGVudDogU3VwcG9ydCBmb3IgL05hbWUtZW50cnkgaXMgbm90IGltcGxlbWVudGVkLiIpOwogICAgfSBlbHNlIGlmIChvYyBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgdGhpcy5vYyA9IG9jOwogICAgfQogIH0KICBhc3luYyBsb2FkUmVzb3VyY2VzKGtleXMsIGFwcGVhcmFuY2UpIHsKICAgIGNvbnN0IHJlc291cmNlcyA9IGF3YWl0IGFwcGVhcmFuY2UuZGljdC5nZXRBc3luYygiUmVzb3VyY2VzIik7CiAgICBpZiAocmVzb3VyY2VzKSB7CiAgICAgIGF3YWl0IE9iamVjdExvYWRlci5sb2FkKHJlc291cmNlcywga2V5cywgcmVzb3VyY2VzLnhyZWYpOwogICAgfQogICAgcmV0dXJuIHJlc291cmNlczsKICB9CiAgYXN5bmMgZ2V0T3BlcmF0b3JMaXN0KGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgY29uc3QgewogICAgICBoYXNPd25DYW52YXMsCiAgICAgIGlkLAogICAgICByZWN0CiAgICB9ID0gdGhpcy5kYXRhOwogICAgbGV0IGFwcGVhcmFuY2UgPSB0aGlzLmFwcGVhcmFuY2U7CiAgICBjb25zdCBpc1VzaW5nT3duQ2FudmFzID0gISEoaGFzT3duQ2FudmFzICYmIGludGVudCAmIFJlbmRlcmluZ0ludGVudEZsYWcuRElTUExBWSk7CiAgICBpZiAoaXNVc2luZ093bkNhbnZhcyAmJiAodGhpcy53aWR0aCA9PT0gMCB8fCB0aGlzLmhlaWdodCA9PT0gMCkpIHsKICAgICAgdGhpcy5kYXRhLmhhc093bkNhbnZhcyA9IGZhbHNlOwogICAgICByZXR1cm4gewogICAgICAgIG9wTGlzdDogbmV3IE9wZXJhdG9yTGlzdCgpLAogICAgICAgIHNlcGFyYXRlRm9ybTogZmFsc2UsCiAgICAgICAgc2VwYXJhdGVDYW52YXM6IGZhbHNlCiAgICAgIH07CiAgICB9CiAgICBpZiAoIWFwcGVhcmFuY2UpIHsKICAgICAgaWYgKCFpc1VzaW5nT3duQ2FudmFzKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIG9wTGlzdDogbmV3IE9wZXJhdG9yTGlzdCgpLAogICAgICAgICAgc2VwYXJhdGVGb3JtOiBmYWxzZSwKICAgICAgICAgIHNlcGFyYXRlQ2FudmFzOiBmYWxzZQogICAgICAgIH07CiAgICAgIH0KICAgICAgYXBwZWFyYW5jZSA9IG5ldyBTdHJpbmdTdHJlYW0oIiIpOwogICAgICBhcHBlYXJhbmNlLmRpY3QgPSBuZXcgRGljdCgpOwogICAgfQogICAgY29uc3QgYXBwZWFyYW5jZURpY3QgPSBhcHBlYXJhbmNlLmRpY3Q7CiAgICBjb25zdCByZXNvdXJjZXMgPSBhd2FpdCB0aGlzLmxvYWRSZXNvdXJjZXMoUkVTT1VSQ0VTX0tFWVNfT1BFUkFUT1JfTElTVCwgYXBwZWFyYW5jZSk7CiAgICBjb25zdCBiYm94ID0gbG9va3VwUmVjdChhcHBlYXJhbmNlRGljdC5nZXRBcnJheSgiQkJveCIpLCBbMCwgMCwgMSwgMV0pOwogICAgY29uc3QgbWF0cml4ID0gbG9va3VwTWF0cml4KGFwcGVhcmFuY2VEaWN0LmdldEFycmF5KCJNYXRyaXgiKSwgSURFTlRJVFlfTUFUUklYKTsKICAgIGNvbnN0IHRyYW5zZm9ybSA9IGdldFRyYW5zZm9ybU1hdHJpeChyZWN0LCBiYm94LCBtYXRyaXgpOwogICAgY29uc3Qgb3BMaXN0ID0gbmV3IE9wZXJhdG9yTGlzdCgpOwogICAgbGV0IG9wdGlvbmFsQ29udGVudDsKICAgIGlmICh0aGlzLm9jKSB7CiAgICAgIG9wdGlvbmFsQ29udGVudCA9IGF3YWl0IGV2YWx1YXRvci5wYXJzZU1hcmtlZENvbnRlbnRQcm9wcyh0aGlzLm9jLCBudWxsKTsKICAgIH0KICAgIGlmIChvcHRpb25hbENvbnRlbnQgIT09IHVuZGVmaW5lZCkgewogICAgICBvcExpc3QuYWRkT3AoT1BTLmJlZ2luTWFya2VkQ29udGVudFByb3BzLCBbIk9DIiwgb3B0aW9uYWxDb250ZW50XSk7CiAgICB9CiAgICBvcExpc3QuYWRkT3AoT1BTLmJlZ2luQW5ub3RhdGlvbiwgW2lkLCByZWN0LCB0cmFuc2Zvcm0sIG1hdHJpeCwgaXNVc2luZ093bkNhbnZhc10pOwogICAgYXdhaXQgZXZhbHVhdG9yLmdldE9wZXJhdG9yTGlzdCh7CiAgICAgIHN0cmVhbTogYXBwZWFyYW5jZSwKICAgICAgdGFzaywKICAgICAgcmVzb3VyY2VzLAogICAgICBvcGVyYXRvckxpc3Q6IG9wTGlzdCwKICAgICAgZmFsbGJhY2tGb250RGljdDogdGhpcy5fZmFsbGJhY2tGb250RGljdAogICAgfSk7CiAgICBvcExpc3QuYWRkT3AoT1BTLmVuZEFubm90YXRpb24sIFtdKTsKICAgIGlmIChvcHRpb25hbENvbnRlbnQgIT09IHVuZGVmaW5lZCkgewogICAgICBvcExpc3QuYWRkT3AoT1BTLmVuZE1hcmtlZENvbnRlbnQsIFtdKTsKICAgIH0KICAgIHRoaXMucmVzZXQoKTsKICAgIHJldHVybiB7CiAgICAgIG9wTGlzdCwKICAgICAgc2VwYXJhdGVGb3JtOiBmYWxzZSwKICAgICAgc2VwYXJhdGVDYW52YXM6IGlzVXNpbmdPd25DYW52YXMKICAgIH07CiAgfQogIGFzeW5jIHNhdmUoZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSwgY2hhbmdlcykgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGdldCBvdmVybGF5c1RleHRDb250ZW50KCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBnZXQgaGFzVGV4dENvbnRlbnQoKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGFzeW5jIGV4dHJhY3RUZXh0Q29udGVudChldmFsdWF0b3IsIHRhc2ssIHZpZXdCb3gpIHsKICAgIGlmICghdGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHJlc291cmNlcyA9IGF3YWl0IHRoaXMubG9hZFJlc291cmNlcyhSRVNPVVJDRVNfS0VZU19URVhUX0NPTlRFTlQsIHRoaXMuYXBwZWFyYW5jZSk7CiAgICBjb25zdCB0ZXh0ID0gW107CiAgICBjb25zdCBidWZmZXIgPSBbXTsKICAgIGxldCBmaXJzdFBvc2l0aW9uID0gbnVsbDsKICAgIGNvbnN0IHNpbmsgPSB7CiAgICAgIGRlc2lyZWRTaXplOiBNYXRoLkluZmluaXR5LAogICAgICByZWFkeTogdHJ1ZSwKICAgICAgZW5xdWV1ZShjaHVuaywgc2l6ZSkgewogICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBjaHVuay5pdGVtcykgewogICAgICAgICAgaWYgKGl0ZW0uc3RyID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBmaXJzdFBvc2l0aW9uIHx8PSBpdGVtLnRyYW5zZm9ybS5zbGljZSgtMik7CiAgICAgICAgICBidWZmZXIucHVzaChpdGVtLnN0cik7CiAgICAgICAgICBpZiAoaXRlbS5oYXNFT0wpIHsKICAgICAgICAgICAgdGV4dC5wdXNoKGJ1ZmZlci5qb2luKCIiKS50cmltRW5kKCkpOwogICAgICAgICAgICBidWZmZXIubGVuZ3RoID0gMDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH07CiAgICBhd2FpdCBldmFsdWF0b3IuZ2V0VGV4dENvbnRlbnQoewogICAgICBzdHJlYW06IHRoaXMuYXBwZWFyYW5jZSwKICAgICAgdGFzaywKICAgICAgcmVzb3VyY2VzLAogICAgICBpbmNsdWRlTWFya2VkQ29udGVudDogdHJ1ZSwKICAgICAga2VlcFdoaXRlU3BhY2U6IHRydWUsCiAgICAgIHNpbmssCiAgICAgIHZpZXdCb3gKICAgIH0pOwogICAgdGhpcy5yZXNldCgpOwogICAgaWYgKGJ1ZmZlci5sZW5ndGgpIHsKICAgICAgdGV4dC5wdXNoKGJ1ZmZlci5qb2luKCIiKS50cmltRW5kKCkpOwogICAgfQogICAgaWYgKHRleHQubGVuZ3RoID4gMSB8fCB0ZXh0WzBdKSB7CiAgICAgIGNvbnN0IGFwcGVhcmFuY2VEaWN0ID0gdGhpcy5hcHBlYXJhbmNlLmRpY3Q7CiAgICAgIGNvbnN0IGJib3ggPSBsb29rdXBSZWN0KGFwcGVhcmFuY2VEaWN0LmdldEFycmF5KCJCQm94IiksIG51bGwpOwogICAgICBjb25zdCBtYXRyaXggPSBsb29rdXBNYXRyaXgoYXBwZWFyYW5jZURpY3QuZ2V0QXJyYXkoIk1hdHJpeCIpLCBudWxsKTsKICAgICAgdGhpcy5kYXRhLnRleHRQb3NpdGlvbiA9IHRoaXMuX3RyYW5zZm9ybVBvaW50KGZpcnN0UG9zaXRpb24sIGJib3gsIG1hdHJpeCk7CiAgICAgIHRoaXMuZGF0YS50ZXh0Q29udGVudCA9IHRleHQ7CiAgICB9CiAgfQogIF90cmFuc2Zvcm1Qb2ludChjb29yZHMsIGJib3gsIG1hdHJpeCkgewogICAgY29uc3QgewogICAgICByZWN0CiAgICB9ID0gdGhpcy5kYXRhOwogICAgYmJveCB8fD0gWzAsIDAsIDEsIDFdOwogICAgbWF0cml4IHx8PSBbMSwgMCwgMCwgMSwgMCwgMF07CiAgICBjb25zdCB0cmFuc2Zvcm0gPSBnZXRUcmFuc2Zvcm1NYXRyaXgocmVjdCwgYmJveCwgbWF0cml4KTsKICAgIHRyYW5zZm9ybVs0XSAtPSByZWN0WzBdOwogICAgdHJhbnNmb3JtWzVdIC09IHJlY3RbMV07CiAgICBjb25zdCBwID0gY29vcmRzLnNsaWNlKCk7CiAgICBVdGlsLmFwcGx5VHJhbnNmb3JtKHAsIHRyYW5zZm9ybSk7CiAgICBVdGlsLmFwcGx5VHJhbnNmb3JtKHAsIG1hdHJpeCk7CiAgICByZXR1cm4gcDsKICB9CiAgZ2V0RmllbGRPYmplY3QoKSB7CiAgICBpZiAodGhpcy5kYXRhLmtpZElkcykgewogICAgICByZXR1cm4gewogICAgICAgIGlkOiB0aGlzLmRhdGEuaWQsCiAgICAgICAgYWN0aW9uczogdGhpcy5kYXRhLmFjdGlvbnMsCiAgICAgICAgbmFtZTogdGhpcy5kYXRhLmZpZWxkTmFtZSwKICAgICAgICBzdHJva2VDb2xvcjogdGhpcy5kYXRhLmJvcmRlckNvbG9yLAogICAgICAgIGZpbGxDb2xvcjogdGhpcy5kYXRhLmJhY2tncm91bmRDb2xvciwKICAgICAgICB0eXBlOiAiIiwKICAgICAgICBraWRJZHM6IHRoaXMuZGF0YS5raWRJZHMsCiAgICAgICAgcGFnZTogdGhpcy5kYXRhLnBhZ2VJbmRleCwKICAgICAgICByb3RhdGlvbjogdGhpcy5yb3RhdGlvbgogICAgICB9OwogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogIHJlc2V0KCkgewogICAgZm9yIChjb25zdCBzdHJlYW0gb2YgdGhpcy5fc3RyZWFtcykgewogICAgICBzdHJlYW0ucmVzZXQoKTsKICAgIH0KICB9CiAgX2NvbnN0cnVjdEZpZWxkTmFtZShkaWN0KSB7CiAgICBpZiAoIWRpY3QuaGFzKCJUIikgJiYgIWRpY3QuaGFzKCJQYXJlbnQiKSkgewogICAgICB3YXJuKCJVbmtub3duIGZpZWxkIG5hbWUsIGZhbGxpbmcgYmFjayB0byBlbXB0eSBmaWVsZCBuYW1lLiIpOwogICAgICByZXR1cm4gIiI7CiAgICB9CiAgICBpZiAoIWRpY3QuaGFzKCJQYXJlbnQiKSkgewogICAgICByZXR1cm4gc3RyaW5nVG9QREZTdHJpbmcoZGljdC5nZXQoIlQiKSk7CiAgICB9CiAgICBjb25zdCBmaWVsZE5hbWUgPSBbXTsKICAgIGlmIChkaWN0LmhhcygiVCIpKSB7CiAgICAgIGZpZWxkTmFtZS51bnNoaWZ0KHN0cmluZ1RvUERGU3RyaW5nKGRpY3QuZ2V0KCJUIikpKTsKICAgIH0KICAgIGxldCBsb29wRGljdCA9IGRpY3Q7CiAgICBjb25zdCB2aXNpdGVkID0gbmV3IFJlZlNldCgpOwogICAgaWYgKGRpY3Qub2JqSWQpIHsKICAgICAgdmlzaXRlZC5wdXQoZGljdC5vYmpJZCk7CiAgICB9CiAgICB3aGlsZSAobG9vcERpY3QuaGFzKCJQYXJlbnQiKSkgewogICAgICBsb29wRGljdCA9IGxvb3BEaWN0LmdldCgiUGFyZW50Iik7CiAgICAgIGlmICghKGxvb3BEaWN0IGluc3RhbmNlb2YgRGljdCkgfHwgbG9vcERpY3Qub2JqSWQgJiYgdmlzaXRlZC5oYXMobG9vcERpY3Qub2JqSWQpKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKGxvb3BEaWN0Lm9iaklkKSB7CiAgICAgICAgdmlzaXRlZC5wdXQobG9vcERpY3Qub2JqSWQpOwogICAgICB9CiAgICAgIGlmIChsb29wRGljdC5oYXMoIlQiKSkgewogICAgICAgIGZpZWxkTmFtZS51bnNoaWZ0KHN0cmluZ1RvUERGU3RyaW5nKGxvb3BEaWN0LmdldCgiVCIpKSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBmaWVsZE5hbWUuam9pbigiLiIpOwogIH0KICBnZXQgd2lkdGgoKSB7CiAgICByZXR1cm4gdGhpcy5kYXRhLnJlY3RbMl0gLSB0aGlzLmRhdGEucmVjdFswXTsKICB9CiAgZ2V0IGhlaWdodCgpIHsKICAgIHJldHVybiB0aGlzLmRhdGEucmVjdFszXSAtIHRoaXMuZGF0YS5yZWN0WzFdOwogIH0KfQpjbGFzcyBBbm5vdGF0aW9uQm9yZGVyU3R5bGUgewogIGNvbnN0cnVjdG9yKCkgewogICAgdGhpcy53aWR0aCA9IDE7CiAgICB0aGlzLnJhd1dpZHRoID0gMTsKICAgIHRoaXMuc3R5bGUgPSBBbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLlNPTElEOwogICAgdGhpcy5kYXNoQXJyYXkgPSBbM107CiAgICB0aGlzLmhvcml6b250YWxDb3JuZXJSYWRpdXMgPSAwOwogICAgdGhpcy52ZXJ0aWNhbENvcm5lclJhZGl1cyA9IDA7CiAgfQogIHNldFdpZHRoKHdpZHRoLCByZWN0ID0gWzAsIDAsIDAsIDBdKSB7CiAgICBpZiAod2lkdGggaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgIHRoaXMud2lkdGggPSAwOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAodHlwZW9mIHdpZHRoID09PSAibnVtYmVyIikgewogICAgICBpZiAod2lkdGggPiAwKSB7CiAgICAgICAgdGhpcy5yYXdXaWR0aCA9IHdpZHRoOwogICAgICAgIGNvbnN0IG1heFdpZHRoID0gKHJlY3RbMl0gLSByZWN0WzBdKSAvIDI7CiAgICAgICAgY29uc3QgbWF4SGVpZ2h0ID0gKHJlY3RbM10gLSByZWN0WzFdKSAvIDI7CiAgICAgICAgaWYgKG1heFdpZHRoID4gMCAmJiBtYXhIZWlnaHQgPiAwICYmICh3aWR0aCA+IG1heFdpZHRoIHx8IHdpZHRoID4gbWF4SGVpZ2h0KSkgewogICAgICAgICAgd2FybihgQW5ub3RhdGlvbkJvcmRlclN0eWxlLnNldFdpZHRoIC0gaWdub3Jpbmcgd2lkdGg6ICR7d2lkdGh9YCk7CiAgICAgICAgICB3aWR0aCA9IDE7CiAgICAgICAgfQogICAgICB9CiAgICAgIHRoaXMud2lkdGggPSB3aWR0aDsKICAgIH0KICB9CiAgc2V0U3R5bGUoc3R5bGUpIHsKICAgIGlmICghKHN0eWxlIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgc3dpdGNoIChzdHlsZS5uYW1lKSB7CiAgICAgIGNhc2UgIlMiOgogICAgICAgIHRoaXMuc3R5bGUgPSBBbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLlNPTElEOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJEIjoKICAgICAgICB0aGlzLnN0eWxlID0gQW5ub3RhdGlvbkJvcmRlclN0eWxlVHlwZS5EQVNIRUQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIkIiOgogICAgICAgIHRoaXMuc3R5bGUgPSBBbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLkJFVkVMRUQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIkkiOgogICAgICAgIHRoaXMuc3R5bGUgPSBBbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLklOU0VUOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJVIjoKICAgICAgICB0aGlzLnN0eWxlID0gQW5ub3RhdGlvbkJvcmRlclN0eWxlVHlwZS5VTkRFUkxJTkU7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfQogIHNldERhc2hBcnJheShkYXNoQXJyYXksIGZvcmNlU3R5bGUgPSBmYWxzZSkgewogICAgaWYgKEFycmF5LmlzQXJyYXkoZGFzaEFycmF5KSkgewogICAgICBsZXQgaXNWYWxpZCA9IHRydWU7CiAgICAgIGxldCBhbGxaZXJvcyA9IHRydWU7CiAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBkYXNoQXJyYXkpIHsKICAgICAgICBjb25zdCB2YWxpZE51bWJlciA9ICtlbGVtZW50ID49IDA7CiAgICAgICAgaWYgKCF2YWxpZE51bWJlcikgewogICAgICAgICAgaXNWYWxpZCA9IGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSBlbHNlIGlmIChlbGVtZW50ID4gMCkgewogICAgICAgICAgYWxsWmVyb3MgPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGRhc2hBcnJheS5sZW5ndGggPT09IDAgfHwgaXNWYWxpZCAmJiAhYWxsWmVyb3MpIHsKICAgICAgICB0aGlzLmRhc2hBcnJheSA9IGRhc2hBcnJheTsKICAgICAgICBpZiAoZm9yY2VTdHlsZSkgewogICAgICAgICAgdGhpcy5zZXRTdHlsZShOYW1lLmdldCgiRCIpKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy53aWR0aCA9IDA7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoZGFzaEFycmF5KSB7CiAgICAgIHRoaXMud2lkdGggPSAwOwogICAgfQogIH0KICBzZXRIb3Jpem9udGFsQ29ybmVyUmFkaXVzKHJhZGl1cykgewogICAgaWYgKE51bWJlci5pc0ludGVnZXIocmFkaXVzKSkgewogICAgICB0aGlzLmhvcml6b250YWxDb3JuZXJSYWRpdXMgPSByYWRpdXM7CiAgICB9CiAgfQogIHNldFZlcnRpY2FsQ29ybmVyUmFkaXVzKHJhZGl1cykgewogICAgaWYgKE51bWJlci5pc0ludGVnZXIocmFkaXVzKSkgewogICAgICB0aGlzLnZlcnRpY2FsQ29ybmVyUmFkaXVzID0gcmFkaXVzOwogICAgfQogIH0KfQpjbGFzcyBNYXJrdXBBbm5vdGF0aW9uIGV4dGVuZHMgQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0CiAgICB9ID0gcGFyYW1zOwogICAgaWYgKGRpY3QuaGFzKCJJUlQiKSkgewogICAgICBjb25zdCByYXdJUlQgPSBkaWN0LmdldFJhdygiSVJUIik7CiAgICAgIHRoaXMuZGF0YS5pblJlcGx5VG8gPSByYXdJUlQgaW5zdGFuY2VvZiBSZWYgPyByYXdJUlQudG9TdHJpbmcoKSA6IG51bGw7CiAgICAgIGNvbnN0IHJ0ID0gZGljdC5nZXQoIlJUIik7CiAgICAgIHRoaXMuZGF0YS5yZXBseVR5cGUgPSBydCBpbnN0YW5jZW9mIE5hbWUgPyBydC5uYW1lIDogQW5ub3RhdGlvblJlcGx5VHlwZS5SRVBMWTsKICAgIH0KICAgIGxldCBwb3B1cFJlZiA9IG51bGw7CiAgICBpZiAodGhpcy5kYXRhLnJlcGx5VHlwZSA9PT0gQW5ub3RhdGlvblJlcGx5VHlwZS5HUk9VUCkgewogICAgICBjb25zdCBwYXJlbnQgPSBkaWN0LmdldCgiSVJUIik7CiAgICAgIHRoaXMuc2V0VGl0bGUocGFyZW50LmdldCgiVCIpKTsKICAgICAgdGhpcy5kYXRhLnRpdGxlT2JqID0gdGhpcy5fdGl0bGU7CiAgICAgIHRoaXMuc2V0Q29udGVudHMocGFyZW50LmdldCgiQ29udGVudHMiKSk7CiAgICAgIHRoaXMuZGF0YS5jb250ZW50c09iaiA9IHRoaXMuX2NvbnRlbnRzOwogICAgICBpZiAoIXBhcmVudC5oYXMoIkNyZWF0aW9uRGF0ZSIpKSB7CiAgICAgICAgdGhpcy5kYXRhLmNyZWF0aW9uRGF0ZSA9IG51bGw7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5zZXRDcmVhdGlvbkRhdGUocGFyZW50LmdldCgiQ3JlYXRpb25EYXRlIikpOwogICAgICAgIHRoaXMuZGF0YS5jcmVhdGlvbkRhdGUgPSB0aGlzLmNyZWF0aW9uRGF0ZTsKICAgICAgfQogICAgICBpZiAoIXBhcmVudC5oYXMoIk0iKSkgewogICAgICAgIHRoaXMuZGF0YS5tb2RpZmljYXRpb25EYXRlID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnNldE1vZGlmaWNhdGlvbkRhdGUocGFyZW50LmdldCgiTSIpKTsKICAgICAgICB0aGlzLmRhdGEubW9kaWZpY2F0aW9uRGF0ZSA9IHRoaXMubW9kaWZpY2F0aW9uRGF0ZTsKICAgICAgfQogICAgICBwb3B1cFJlZiA9IHBhcmVudC5nZXRSYXcoIlBvcHVwIik7CiAgICAgIGlmICghcGFyZW50LmhhcygiQyIpKSB7CiAgICAgICAgdGhpcy5kYXRhLmNvbG9yID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnNldENvbG9yKHBhcmVudC5nZXRBcnJheSgiQyIpKTsKICAgICAgICB0aGlzLmRhdGEuY29sb3IgPSB0aGlzLmNvbG9yOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEudGl0bGVPYmogPSB0aGlzLl90aXRsZTsKICAgICAgdGhpcy5zZXRDcmVhdGlvbkRhdGUoZGljdC5nZXQoIkNyZWF0aW9uRGF0ZSIpKTsKICAgICAgdGhpcy5kYXRhLmNyZWF0aW9uRGF0ZSA9IHRoaXMuY3JlYXRpb25EYXRlOwogICAgICBwb3B1cFJlZiA9IGRpY3QuZ2V0UmF3KCJQb3B1cCIpOwogICAgICBpZiAoIWRpY3QuaGFzKCJDIikpIHsKICAgICAgICB0aGlzLmRhdGEuY29sb3IgPSBudWxsOwogICAgICB9CiAgICB9CiAgICB0aGlzLmRhdGEucG9wdXBSZWYgPSBwb3B1cFJlZiBpbnN0YW5jZW9mIFJlZiA/IHBvcHVwUmVmLnRvU3RyaW5nKCkgOiBudWxsOwogICAgaWYgKGRpY3QuaGFzKCJSQyIpKSB7CiAgICAgIHRoaXMuZGF0YS5yaWNoVGV4dCA9IFhGQUZhY3RvcnkuZ2V0UmljaFRleHRBc0h0bWwoZGljdC5nZXQoIlJDIikpOwogICAgfQogIH0KICBzZXRDcmVhdGlvbkRhdGUoY3JlYXRpb25EYXRlKSB7CiAgICB0aGlzLmNyZWF0aW9uRGF0ZSA9IHR5cGVvZiBjcmVhdGlvbkRhdGUgPT09ICJzdHJpbmciID8gY3JlYXRpb25EYXRlIDogbnVsbDsKICB9CiAgX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgIHhyZWYsCiAgICBleHRyYSwKICAgIHN0cm9rZUNvbG9yLAogICAgZmlsbENvbG9yLAogICAgYmxlbmRNb2RlLAogICAgc3Ryb2tlQWxwaGEsCiAgICBmaWxsQWxwaGEsCiAgICBwb2ludHNDYWxsYmFjawogIH0pIHsKICAgIGNvbnN0IGJib3ggPSB0aGlzLmRhdGEucmVjdCA9IFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XTsKICAgIGNvbnN0IGJ1ZmZlciA9IFsicSJdOwogICAgaWYgKGV4dHJhKSB7CiAgICAgIGJ1ZmZlci5wdXNoKGV4dHJhKTsKICAgIH0KICAgIGlmIChzdHJva2VDb2xvcikgewogICAgICBidWZmZXIucHVzaChgJHtzdHJva2VDb2xvclswXX0gJHtzdHJva2VDb2xvclsxXX0gJHtzdHJva2VDb2xvclsyXX0gUkdgKTsKICAgIH0KICAgIGlmIChmaWxsQ29sb3IpIHsKICAgICAgYnVmZmVyLnB1c2goYCR7ZmlsbENvbG9yWzBdfSAke2ZpbGxDb2xvclsxXX0gJHtmaWxsQ29sb3JbMl19IHJnYCk7CiAgICB9CiAgICBjb25zdCBwb2ludHNBcnJheSA9IHRoaXMuZGF0YS5xdWFkUG9pbnRzIHx8IEZsb2F0MzJBcnJheS5mcm9tKFt0aGlzLnJlY3RhbmdsZVswXSwgdGhpcy5yZWN0YW5nbGVbM10sIHRoaXMucmVjdGFuZ2xlWzJdLCB0aGlzLnJlY3RhbmdsZVszXSwgdGhpcy5yZWN0YW5nbGVbMF0sIHRoaXMucmVjdGFuZ2xlWzFdLCB0aGlzLnJlY3RhbmdsZVsyXSwgdGhpcy5yZWN0YW5nbGVbMV1dKTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHBvaW50c0FycmF5Lmxlbmd0aDsgaSA8IGlpOyBpICs9IDgpIHsKICAgICAgY29uc3QgcG9pbnRzID0gcG9pbnRzQ2FsbGJhY2soYnVmZmVyLCBwb2ludHNBcnJheS5zdWJhcnJheShpLCBpICsgOCkpOwogICAgICBVdGlsLnJlY3RCb3VuZGluZ0JveCguLi5wb2ludHMsIGJib3gpOwogICAgfQogICAgYnVmZmVyLnB1c2goIlEiKTsKICAgIGNvbnN0IGZvcm1EaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICBjb25zdCBhcHBlYXJhbmNlU3RyZWFtRGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIkZvcm0iKTsKICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW0gPSBuZXcgU3RyaW5nU3RyZWFtKGJ1ZmZlci5qb2luKCIgIikpOwogICAgYXBwZWFyYW5jZVN0cmVhbS5kaWN0ID0gYXBwZWFyYW5jZVN0cmVhbURpY3Q7CiAgICBmb3JtRGljdC5zZXQoIkZtMCIsIGFwcGVhcmFuY2VTdHJlYW0pOwogICAgY29uc3QgZ3NEaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICBpZiAoYmxlbmRNb2RlKSB7CiAgICAgIGdzRGljdC5zZXRJZk5hbWUoIkJNIiwgYmxlbmRNb2RlKTsKICAgIH0KICAgIGdzRGljdC5zZXRJZk51bWJlcigiQ0EiLCBzdHJva2VBbHBoYSk7CiAgICBnc0RpY3Quc2V0SWZOdW1iZXIoImNhIiwgZmlsbEFscGhhKTsKICAgIGNvbnN0IHN0YXRlRGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgc3RhdGVEaWN0LnNldCgiR1MwIiwgZ3NEaWN0KTsKICAgIGNvbnN0IHJlc291cmNlcyA9IG5ldyBEaWN0KHhyZWYpOwogICAgcmVzb3VyY2VzLnNldCgiRXh0R1N0YXRlIiwgc3RhdGVEaWN0KTsKICAgIHJlc291cmNlcy5zZXQoIlhPYmplY3QiLCBmb3JtRGljdCk7CiAgICBjb25zdCBhcHBlYXJhbmNlRGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgYXBwZWFyYW5jZURpY3Quc2V0KCJSZXNvdXJjZXMiLCByZXNvdXJjZXMpOwogICAgYXBwZWFyYW5jZURpY3Quc2V0KCJCQm94IiwgYmJveCk7CiAgICB0aGlzLmFwcGVhcmFuY2UgPSBuZXcgU3RyaW5nU3RyZWFtKCIvR1MwIGdzIC9GbTAgRG8iKTsKICAgIHRoaXMuYXBwZWFyYW5jZS5kaWN0ID0gYXBwZWFyYW5jZURpY3Q7CiAgICB0aGlzLl9zdHJlYW1zLnB1c2godGhpcy5hcHBlYXJhbmNlLCBhcHBlYXJhbmNlU3RyZWFtKTsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZU5ld0Fubm90YXRpb24oeHJlZiwgYW5ub3RhdGlvbiwgY2hhbmdlcywgcGFyYW1zKSB7CiAgICBjb25zdCBhbm5vdGF0aW9uUmVmID0gYW5ub3RhdGlvbi5yZWYgfHw9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICBjb25zdCBhcCA9IGF3YWl0IHRoaXMuY3JlYXRlTmV3QXBwZWFyYW5jZVN0cmVhbShhbm5vdGF0aW9uLCB4cmVmLCBwYXJhbXMpOwogICAgbGV0IGFubm90YXRpb25EaWN0OwogICAgaWYgKGFwKSB7CiAgICAgIGNvbnN0IGFwUmVmID0geHJlZi5nZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgYW5ub3RhdGlvbkRpY3QgPSB0aGlzLmNyZWF0ZU5ld0RpY3QoYW5ub3RhdGlvbiwgeHJlZiwgewogICAgICAgIGFwUmVmCiAgICAgIH0pOwogICAgICBjaGFuZ2VzLnB1dChhcFJlZiwgewogICAgICAgIGRhdGE6IGFwCiAgICAgIH0pOwogICAgfSBlbHNlIHsKICAgICAgYW5ub3RhdGlvbkRpY3QgPSB0aGlzLmNyZWF0ZU5ld0RpY3QoYW5ub3RhdGlvbiwgeHJlZiwge30pOwogICAgfQogICAgaWYgKE51bWJlci5pc0ludGVnZXIoYW5ub3RhdGlvbi5wYXJlbnRUcmVlSWQpKSB7CiAgICAgIGFubm90YXRpb25EaWN0LnNldCgiU3RydWN0UGFyZW50IiwgYW5ub3RhdGlvbi5wYXJlbnRUcmVlSWQpOwogICAgfQogICAgY2hhbmdlcy5wdXQoYW5ub3RhdGlvblJlZiwgewogICAgICBkYXRhOiBhbm5vdGF0aW9uRGljdAogICAgfSk7CiAgICBjb25zdCByZXRSZWYgPSB7CiAgICAgIHJlZjogYW5ub3RhdGlvblJlZgogICAgfTsKICAgIGNvbnN0IHsKICAgICAgcG9wdXAKICAgIH0gPSBhbm5vdGF0aW9uOwogICAgaWYgKHBvcHVwKSB7CiAgICAgIGlmIChwb3B1cC5kZWxldGVkKSB7CiAgICAgICAgYW5ub3RhdGlvbkRpY3QuZGVsZXRlKCJQb3B1cCIpOwogICAgICAgIGFubm90YXRpb25EaWN0LmRlbGV0ZSgiQ29udGVudHMiKTsKICAgICAgICBhbm5vdGF0aW9uRGljdC5kZWxldGUoIlJDIik7CiAgICAgICAgcmV0dXJuIHJldFJlZjsKICAgICAgfQogICAgICBjb25zdCBwb3B1cFJlZiA9IHBvcHVwLnJlZiB8fD0geHJlZi5nZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgcG9wdXAucGFyZW50ID0gYW5ub3RhdGlvblJlZjsKICAgICAgY29uc3QgcG9wdXBEaWN0ID0gUG9wdXBBbm5vdGF0aW9uLmNyZWF0ZU5ld0RpY3QocG9wdXAsIHhyZWYpOwogICAgICBjaGFuZ2VzLnB1dChwb3B1cFJlZiwgewogICAgICAgIGRhdGE6IHBvcHVwRGljdAogICAgICB9KTsKICAgICAgYW5ub3RhdGlvbkRpY3Quc2V0SWZEZWZpbmVkKCJDb250ZW50cyIsIHN0cmluZ1RvQXNjaWlPclVURjE2QkUocG9wdXAuY29udGVudHMpKTsKICAgICAgYW5ub3RhdGlvbkRpY3Quc2V0KCJQb3B1cCIsIHBvcHVwUmVmKTsKICAgICAgcmV0dXJuIFtyZXRSZWYsIHsKICAgICAgICByZWY6IHBvcHVwUmVmCiAgICAgIH1dOwogICAgfQogICAgcmV0dXJuIHJldFJlZjsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZU5ld1ByaW50QW5ub3RhdGlvbihhbm5vdGF0aW9uR2xvYmFscywgeHJlZiwgYW5ub3RhdGlvbiwgcGFyYW1zKSB7CiAgICBjb25zdCBhcCA9IGF3YWl0IHRoaXMuY3JlYXRlTmV3QXBwZWFyYW5jZVN0cmVhbShhbm5vdGF0aW9uLCB4cmVmLCBwYXJhbXMpOwogICAgY29uc3QgYW5ub3RhdGlvbkRpY3QgPSB0aGlzLmNyZWF0ZU5ld0RpY3QoYW5ub3RhdGlvbiwgeHJlZiwgYXAgPyB7CiAgICAgIGFwCiAgICB9IDoge30pOwogICAgY29uc3QgbmV3QW5ub3RhdGlvbiA9IG5ldyB0aGlzLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcih7CiAgICAgIGRpY3Q6IGFubm90YXRpb25EaWN0LAogICAgICB4cmVmLAogICAgICBhbm5vdGF0aW9uR2xvYmFscywKICAgICAgZXZhbHVhdG9yT3B0aW9uczogcGFyYW1zLmV2YWx1YXRvck9wdGlvbnMKICAgIH0pOwogICAgaWYgKGFubm90YXRpb24ucmVmKSB7CiAgICAgIG5ld0Fubm90YXRpb24ucmVmID0gbmV3QW5ub3RhdGlvbi5yZWZUb1JlcGxhY2UgPSBhbm5vdGF0aW9uLnJlZjsKICAgIH0KICAgIHJldHVybiBuZXdBbm5vdGF0aW9uOwogIH0KfQpjbGFzcyBXaWRnZXRBbm5vdGF0aW9uIGV4dGVuZHMgQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmLAogICAgICBhbm5vdGF0aW9uR2xvYmFscwogICAgfSA9IHBhcmFtczsKICAgIGNvbnN0IGRhdGEgPSB0aGlzLmRhdGE7CiAgICB0aGlzLl9uZWVkQXBwZWFyYW5jZXMgPSBwYXJhbXMubmVlZEFwcGVhcmFuY2VzOwogICAgZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLldJREdFVDsKICAgIGlmIChkYXRhLmZpZWxkTmFtZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGRhdGEuZmllbGROYW1lID0gdGhpcy5fY29uc3RydWN0RmllbGROYW1lKGRpY3QpOwogICAgfQogICAgaWYgKGRhdGEuYWN0aW9ucyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGRhdGEuYWN0aW9ucyA9IGNvbGxlY3RBY3Rpb25zKHhyZWYsIGRpY3QsIEFubm90YXRpb25BY3Rpb25FdmVudFR5cGUpOwogICAgfQogICAgbGV0IGZpZWxkVmFsdWUgPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5KHsKICAgICAgZGljdCwKICAgICAga2V5OiAiViIsCiAgICAgIGdldEFycmF5OiB0cnVlCiAgICB9KTsKICAgIGRhdGEuZmllbGRWYWx1ZSA9IHRoaXMuX2RlY29kZUZvcm1WYWx1ZShmaWVsZFZhbHVlKTsKICAgIGNvbnN0IGRlZmF1bHRGaWVsZFZhbHVlID0gZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7CiAgICAgIGRpY3QsCiAgICAgIGtleTogIkRWIiwKICAgICAgZ2V0QXJyYXk6IHRydWUKICAgIH0pOwogICAgZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSA9IHRoaXMuX2RlY29kZUZvcm1WYWx1ZShkZWZhdWx0RmllbGRWYWx1ZSk7CiAgICBpZiAoZmllbGRWYWx1ZSA9PT0gdW5kZWZpbmVkICYmIGFubm90YXRpb25HbG9iYWxzLnhmYURhdGFzZXRzKSB7CiAgICAgIGNvbnN0IHBhdGggPSB0aGlzLl90aXRsZS5zdHI7CiAgICAgIGlmIChwYXRoKSB7CiAgICAgICAgdGhpcy5faGFzVmFsdWVGcm9tWEZBID0gdHJ1ZTsKICAgICAgICBkYXRhLmZpZWxkVmFsdWUgPSBmaWVsZFZhbHVlID0gYW5ub3RhdGlvbkdsb2JhbHMueGZhRGF0YXNldHMuZ2V0VmFsdWUocGF0aCk7CiAgICAgIH0KICAgIH0KICAgIGlmIChmaWVsZFZhbHVlID09PSB1bmRlZmluZWQgJiYgZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSAhPT0gbnVsbCkgewogICAgICBkYXRhLmZpZWxkVmFsdWUgPSBkYXRhLmRlZmF1bHRGaWVsZFZhbHVlOwogICAgfQogICAgZGF0YS5hbHRlcm5hdGl2ZVRleHQgPSBzdHJpbmdUb1BERlN0cmluZyhkaWN0LmdldCgiVFUiKSB8fCAiIik7CiAgICB0aGlzLnNldERlZmF1bHRBcHBlYXJhbmNlKHBhcmFtcyk7CiAgICBkYXRhLmhhc0FwcGVhcmFuY2UgfHw9IHRoaXMuX25lZWRBcHBlYXJhbmNlcyAmJiBkYXRhLmZpZWxkVmFsdWUgIT09IHVuZGVmaW5lZCAmJiBkYXRhLmZpZWxkVmFsdWUgIT09IG51bGw7CiAgICBjb25zdCBmaWVsZFR5cGUgPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5KHsKICAgICAgZGljdCwKICAgICAga2V5OiAiRlQiCiAgICB9KTsKICAgIGRhdGEuZmllbGRUeXBlID0gZmllbGRUeXBlIGluc3RhbmNlb2YgTmFtZSA/IGZpZWxkVHlwZS5uYW1lIDogbnVsbDsKICAgIGNvbnN0IGxvY2FsUmVzb3VyY2VzID0gZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7CiAgICAgIGRpY3QsCiAgICAgIGtleTogIkRSIgogICAgfSk7CiAgICBjb25zdCBhY3JvRm9ybVJlc291cmNlcyA9IGFubm90YXRpb25HbG9iYWxzLmFjcm9Gb3JtLmdldCgiRFIiKTsKICAgIGNvbnN0IGFwcGVhcmFuY2VSZXNvdXJjZXMgPSB0aGlzLmFwcGVhcmFuY2U/LmRpY3QuZ2V0KCJSZXNvdXJjZXMiKTsKICAgIHRoaXMuX2ZpZWxkUmVzb3VyY2VzID0gewogICAgICBsb2NhbFJlc291cmNlcywKICAgICAgYWNyb0Zvcm1SZXNvdXJjZXMsCiAgICAgIGFwcGVhcmFuY2VSZXNvdXJjZXMsCiAgICAgIG1lcmdlZFJlc291cmNlczogRGljdC5tZXJnZSh7CiAgICAgICAgeHJlZiwKICAgICAgICBkaWN0QXJyYXk6IFtsb2NhbFJlc291cmNlcywgYXBwZWFyYW5jZVJlc291cmNlcywgYWNyb0Zvcm1SZXNvdXJjZXNdLAogICAgICAgIG1lcmdlU3ViRGljdHM6IHRydWUKICAgICAgfSkKICAgIH07CiAgICBkYXRhLmZpZWxkRmxhZ3MgPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5KHsKICAgICAgZGljdCwKICAgICAga2V5OiAiRmYiCiAgICB9KTsKICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihkYXRhLmZpZWxkRmxhZ3MpIHx8IGRhdGEuZmllbGRGbGFncyA8IDApIHsKICAgICAgZGF0YS5maWVsZEZsYWdzID0gMDsKICAgIH0KICAgIGRhdGEucGFzc3dvcmQgPSB0aGlzLmhhc0ZpZWxkRmxhZyhBbm5vdGF0aW9uRmllbGRGbGFnLlBBU1NXT1JEKTsKICAgIGRhdGEucmVhZE9ubHkgPSB0aGlzLmhhc0ZpZWxkRmxhZyhBbm5vdGF0aW9uRmllbGRGbGFnLlJFQURPTkxZKTsKICAgIGRhdGEucmVxdWlyZWQgPSB0aGlzLmhhc0ZpZWxkRmxhZyhBbm5vdGF0aW9uRmllbGRGbGFnLlJFUVVJUkVEKTsKICAgIGRhdGEuaGlkZGVuID0gdGhpcy5faGFzRmxhZyhkYXRhLmFubm90YXRpb25GbGFncywgQW5ub3RhdGlvbkZsYWcuSElEREVOKSB8fCB0aGlzLl9oYXNGbGFnKGRhdGEuYW5ub3RhdGlvbkZsYWdzLCBBbm5vdGF0aW9uRmxhZy5OT1ZJRVcpOwogIH0KICBfZGVjb2RlRm9ybVZhbHVlKGZvcm1WYWx1ZSkgewogICAgaWYgKEFycmF5LmlzQXJyYXkoZm9ybVZhbHVlKSkgewogICAgICByZXR1cm4gZm9ybVZhbHVlLmZpbHRlcihpdGVtID0+IHR5cGVvZiBpdGVtID09PSAic3RyaW5nIikubWFwKGl0ZW0gPT4gc3RyaW5nVG9QREZTdHJpbmcoaXRlbSkpOwogICAgfSBlbHNlIGlmIChmb3JtVmFsdWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgIHJldHVybiBzdHJpbmdUb1BERlN0cmluZyhmb3JtVmFsdWUubmFtZSk7CiAgICB9IGVsc2UgaWYgKHR5cGVvZiBmb3JtVmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgIHJldHVybiBzdHJpbmdUb1BERlN0cmluZyhmb3JtVmFsdWUpOwogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogIGhhc0ZpZWxkRmxhZyhmbGFnKSB7CiAgICByZXR1cm4gISEodGhpcy5kYXRhLmZpZWxkRmxhZ3MgJiBmbGFnKTsKICB9CiAgX2lzVmlld2FibGUoZmxhZ3MpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBtdXN0QmVWaWV3ZWQoYW5ub3RhdGlvblN0b3JhZ2UsIHJlbmRlckZvcm1zKSB7CiAgICBpZiAocmVuZGVyRm9ybXMpIHsKICAgICAgcmV0dXJuIHRoaXMudmlld2FibGU7CiAgICB9CiAgICByZXR1cm4gc3VwZXIubXVzdEJlVmlld2VkKGFubm90YXRpb25TdG9yYWdlLCByZW5kZXJGb3JtcykgJiYgIXRoaXMuX2hhc0ZsYWcodGhpcy5mbGFncywgQW5ub3RhdGlvbkZsYWcuTk9WSUVXKTsKICB9CiAgZ2V0Um90YXRpb25NYXRyaXgoYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIGxldCByb3RhdGlvbiA9IGFubm90YXRpb25TdG9yYWdlPy5nZXQodGhpcy5kYXRhLmlkKT8ucm90YXRpb247CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCkgewogICAgICByb3RhdGlvbiA9IHRoaXMucm90YXRpb247CiAgICB9CiAgICByZXR1cm4gcm90YXRpb24gPT09IDAgPyBJREVOVElUWV9NQVRSSVggOiBnZXRSb3RhdGlvbk1hdHJpeChyb3RhdGlvbiwgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHQpOwogIH0KICBnZXRCb3JkZXJBbmRCYWNrZ3JvdW5kQXBwZWFyYW5jZXMoYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIGxldCByb3RhdGlvbiA9IGFubm90YXRpb25TdG9yYWdlPy5nZXQodGhpcy5kYXRhLmlkKT8ucm90YXRpb247CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCkgewogICAgICByb3RhdGlvbiA9IHRoaXMucm90YXRpb247CiAgICB9CiAgICBpZiAoIXRoaXMuYmFja2dyb3VuZENvbG9yICYmICF0aGlzLmJvcmRlckNvbG9yKSB7CiAgICAgIHJldHVybiAiIjsKICAgIH0KICAgIGNvbnN0IHJlY3QgPSByb3RhdGlvbiA9PT0gMCB8fCByb3RhdGlvbiA9PT0gMTgwID8gYDAgMCAke3RoaXMud2lkdGh9ICR7dGhpcy5oZWlnaHR9IHJlYCA6IGAwIDAgJHt0aGlzLmhlaWdodH0gJHt0aGlzLndpZHRofSByZWA7CiAgICBsZXQgc3RyID0gIiI7CiAgICBpZiAodGhpcy5iYWNrZ3JvdW5kQ29sb3IpIHsKICAgICAgc3RyID0gYCR7Z2V0UGRmQ29sb3IodGhpcy5iYWNrZ3JvdW5kQ29sb3IsIHRydWUpfSAke3JlY3R9IGYgYDsKICAgIH0KICAgIGlmICh0aGlzLmJvcmRlckNvbG9yKSB7CiAgICAgIGNvbnN0IGJvcmRlcldpZHRoID0gdGhpcy5ib3JkZXJTdHlsZS53aWR0aCB8fCAxOwogICAgICBzdHIgKz0gYCR7Ym9yZGVyV2lkdGh9IHcgJHtnZXRQZGZDb2xvcih0aGlzLmJvcmRlckNvbG9yLCBmYWxzZSl9ICR7cmVjdH0gUyBgOwogICAgfQogICAgcmV0dXJuIHN0cjsKICB9CiAgYXN5bmMgZ2V0T3BlcmF0b3JMaXN0KGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgaWYgKGludGVudCAmIFJlbmRlcmluZ0ludGVudEZsYWcuQU5OT1RBVElPTlNfRk9STVMgJiYgISh0aGlzIGluc3RhbmNlb2YgU2lnbmF0dXJlV2lkZ2V0QW5ub3RhdGlvbikgJiYgIXRoaXMuZGF0YS5ub0hUTUwgJiYgIXRoaXMuZGF0YS5oYXNPd25DYW52YXMpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBvcExpc3Q6IG5ldyBPcGVyYXRvckxpc3QoKSwKICAgICAgICBzZXBhcmF0ZUZvcm06IHRydWUsCiAgICAgICAgc2VwYXJhdGVDYW52YXM6IGZhbHNlCiAgICAgIH07CiAgICB9CiAgICBpZiAoIXRoaXMuX2hhc1RleHQpIHsKICAgICAgcmV0dXJuIHN1cGVyLmdldE9wZXJhdG9yTGlzdChldmFsdWF0b3IsIHRhc2ssIGludGVudCwgYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgfQogICAgY29uc3QgY29udGVudCA9IGF3YWl0IHRoaXMuX2dldEFwcGVhcmFuY2UoZXZhbHVhdG9yLCB0YXNrLCBpbnRlbnQsIGFubm90YXRpb25TdG9yYWdlKTsKICAgIGlmICh0aGlzLmFwcGVhcmFuY2UgJiYgY29udGVudCA9PT0gbnVsbCkgewogICAgICByZXR1cm4gc3VwZXIuZ2V0T3BlcmF0b3JMaXN0KGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICB9CiAgICBjb25zdCBvcExpc3QgPSBuZXcgT3BlcmF0b3JMaXN0KCk7CiAgICBpZiAoIXRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlIHx8IGNvbnRlbnQgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBvcExpc3QsCiAgICAgICAgc2VwYXJhdGVGb3JtOiBmYWxzZSwKICAgICAgICBzZXBhcmF0ZUNhbnZhczogZmFsc2UKICAgICAgfTsKICAgIH0KICAgIGNvbnN0IGlzVXNpbmdPd25DYW52YXMgPSAhISh0aGlzLmRhdGEuaGFzT3duQ2FudmFzICYmIGludGVudCAmIFJlbmRlcmluZ0ludGVudEZsYWcuRElTUExBWSk7CiAgICBjb25zdCBtYXRyaXggPSBbMSwgMCwgMCwgMSwgMCwgMF07CiAgICBjb25zdCBiYm94ID0gWzAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0XTsKICAgIGNvbnN0IHRyYW5zZm9ybSA9IGdldFRyYW5zZm9ybU1hdHJpeCh0aGlzLmRhdGEucmVjdCwgYmJveCwgbWF0cml4KTsKICAgIGxldCBvcHRpb25hbENvbnRlbnQ7CiAgICBpZiAodGhpcy5vYykgewogICAgICBvcHRpb25hbENvbnRlbnQgPSBhd2FpdCBldmFsdWF0b3IucGFyc2VNYXJrZWRDb250ZW50UHJvcHModGhpcy5vYywgbnVsbCk7CiAgICB9CiAgICBpZiAob3B0aW9uYWxDb250ZW50ICE9PSB1bmRlZmluZWQpIHsKICAgICAgb3BMaXN0LmFkZE9wKE9QUy5iZWdpbk1hcmtlZENvbnRlbnRQcm9wcywgWyJPQyIsIG9wdGlvbmFsQ29udGVudF0pOwogICAgfQogICAgb3BMaXN0LmFkZE9wKE9QUy5iZWdpbkFubm90YXRpb24sIFt0aGlzLmRhdGEuaWQsIHRoaXMuZGF0YS5yZWN0LCB0cmFuc2Zvcm0sIHRoaXMuZ2V0Um90YXRpb25NYXRyaXgoYW5ub3RhdGlvblN0b3JhZ2UpLCBpc1VzaW5nT3duQ2FudmFzXSk7CiAgICBjb25zdCBzdHJlYW0gPSBuZXcgU3RyaW5nU3RyZWFtKGNvbnRlbnQpOwogICAgYXdhaXQgZXZhbHVhdG9yLmdldE9wZXJhdG9yTGlzdCh7CiAgICAgIHN0cmVhbSwKICAgICAgdGFzaywKICAgICAgcmVzb3VyY2VzOiB0aGlzLl9maWVsZFJlc291cmNlcy5tZXJnZWRSZXNvdXJjZXMsCiAgICAgIG9wZXJhdG9yTGlzdDogb3BMaXN0CiAgICB9KTsKICAgIG9wTGlzdC5hZGRPcChPUFMuZW5kQW5ub3RhdGlvbiwgW10pOwogICAgaWYgKG9wdGlvbmFsQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIG9wTGlzdC5hZGRPcChPUFMuZW5kTWFya2VkQ29udGVudCwgW10pOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgb3BMaXN0LAogICAgICBzZXBhcmF0ZUZvcm06IGZhbHNlLAogICAgICBzZXBhcmF0ZUNhbnZhczogaXNVc2luZ093bkNhbnZhcwogICAgfTsKICB9CiAgX2dldE1LRGljdChyb3RhdGlvbikgewogICAgY29uc3QgbWsgPSBuZXcgRGljdChudWxsKTsKICAgIGlmIChyb3RhdGlvbikgewogICAgICBtay5zZXQoIlIiLCByb3RhdGlvbik7CiAgICB9CiAgICBtay5zZXRJZkFycmF5KCJCQyIsIGdldFBkZkNvbG9yQXJyYXkodGhpcy5ib3JkZXJDb2xvcikpOwogICAgbWsuc2V0SWZBcnJheSgiQkciLCBnZXRQZGZDb2xvckFycmF5KHRoaXMuYmFja2dyb3VuZENvbG9yKSk7CiAgICByZXR1cm4gbWsuc2l6ZSA+IDAgPyBtayA6IG51bGw7CiAgfQogIGFtZW5kU2F2ZWREaWN0KGFubm90YXRpb25TdG9yYWdlLCBkaWN0KSB7fQogIHNldFZhbHVlKGRpY3QsIHZhbHVlLCB4cmVmLCBjaGFuZ2VzKSB7CiAgICBjb25zdCB7CiAgICAgIGRpY3Q6IHBhcmVudERpY3QsCiAgICAgIHJlZjogcGFyZW50UmVmCiAgICB9ID0gZ2V0UGFyZW50VG9VcGRhdGUoZGljdCwgdGhpcy5yZWYsIHhyZWYpOwogICAgaWYgKCFwYXJlbnREaWN0KSB7CiAgICAgIGRpY3Quc2V0KCJWIiwgdmFsdWUpOwogICAgfSBlbHNlIGlmICghY2hhbmdlcy5oYXMocGFyZW50UmVmKSkgewogICAgICBjb25zdCBuZXdQYXJlbnREaWN0ID0gcGFyZW50RGljdC5jbG9uZSgpOwogICAgICBuZXdQYXJlbnREaWN0LnNldCgiViIsIHZhbHVlKTsKICAgICAgY2hhbmdlcy5wdXQocGFyZW50UmVmLCB7CiAgICAgICAgZGF0YTogbmV3UGFyZW50RGljdAogICAgICB9KTsKICAgICAgcmV0dXJuIG5ld1BhcmVudERpY3Q7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgYXN5bmMgc2F2ZShldmFsdWF0b3IsIHRhc2ssIGFubm90YXRpb25TdG9yYWdlLCBjaGFuZ2VzKSB7CiAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBhbm5vdGF0aW9uU3RvcmFnZT8uZ2V0KHRoaXMuZGF0YS5pZCk7CiAgICBjb25zdCBmbGFncyA9IHRoaXMuX2J1aWxkRmxhZ3Moc3RvcmFnZUVudHJ5Py5ub1ZpZXcsIHN0b3JhZ2VFbnRyeT8ubm9QcmludCk7CiAgICBsZXQgdmFsdWUgPSBzdG9yYWdlRW50cnk/LnZhbHVlLAogICAgICByb3RhdGlvbiA9IHN0b3JhZ2VFbnRyeT8ucm90YXRpb247CiAgICBpZiAodmFsdWUgPT09IHRoaXMuZGF0YS5maWVsZFZhbHVlIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgaWYgKCF0aGlzLl9oYXNWYWx1ZUZyb21YRkEgJiYgcm90YXRpb24gPT09IHVuZGVmaW5lZCAmJiBmbGFncyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHZhbHVlIHx8PSB0aGlzLmRhdGEuZmllbGRWYWx1ZTsKICAgIH0KICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkICYmICF0aGlzLl9oYXNWYWx1ZUZyb21YRkEgJiYgQXJyYXkuaXNBcnJheSh2YWx1ZSkgJiYgQXJyYXkuaXNBcnJheSh0aGlzLmRhdGEuZmllbGRWYWx1ZSkgJiYgaXNBcnJheUVxdWFsKHZhbHVlLCB0aGlzLmRhdGEuZmllbGRWYWx1ZSkgJiYgZmxhZ3MgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCkgewogICAgICByb3RhdGlvbiA9IHRoaXMucm90YXRpb247CiAgICB9CiAgICBsZXQgYXBwZWFyYW5jZSA9IG51bGw7CiAgICBpZiAoIXRoaXMuX25lZWRBcHBlYXJhbmNlcykgewogICAgICBhcHBlYXJhbmNlID0gYXdhaXQgdGhpcy5fZ2V0QXBwZWFyYW5jZShldmFsdWF0b3IsIHRhc2ssIFJlbmRlcmluZ0ludGVudEZsYWcuU0FWRSwgYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgICBpZiAoYXBwZWFyYW5jZSA9PT0gbnVsbCAmJiBmbGFncyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICB9IGVsc2Uge30KICAgIGxldCBuZWVkQXBwZWFyYW5jZXMgPSBmYWxzZTsKICAgIGlmIChhcHBlYXJhbmNlPy5uZWVkQXBwZWFyYW5jZXMpIHsKICAgICAgbmVlZEFwcGVhcmFuY2VzID0gdHJ1ZTsKICAgICAgYXBwZWFyYW5jZSA9IG51bGw7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIHhyZWYKICAgIH0gPSBldmFsdWF0b3I7CiAgICBjb25zdCBvcmlnaW5hbERpY3QgPSB4cmVmLmZldGNoSWZSZWYodGhpcy5yZWYpOwogICAgaWYgKCEob3JpZ2luYWxEaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgZGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgZm9yIChjb25zdCBrZXkgb2Ygb3JpZ2luYWxEaWN0LmdldEtleXMoKSkgewogICAgICBpZiAoa2V5ICE9PSAiQVAiKSB7CiAgICAgICAgZGljdC5zZXQoa2V5LCBvcmlnaW5hbERpY3QuZ2V0UmF3KGtleSkpOwogICAgICB9CiAgICB9CiAgICBpZiAoZmxhZ3MgIT09IHVuZGVmaW5lZCkgewogICAgICBkaWN0LnNldCgiRiIsIGZsYWdzKTsKICAgICAgaWYgKGFwcGVhcmFuY2UgPT09IG51bGwgJiYgIW5lZWRBcHBlYXJhbmNlcykgewogICAgICAgIGNvbnN0IGFwID0gb3JpZ2luYWxEaWN0LmdldFJhdygiQVAiKTsKICAgICAgICBpZiAoYXApIHsKICAgICAgICAgIGRpY3Quc2V0KCJBUCIsIGFwKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHhmYSA9IHsKICAgICAgcGF0aDogdGhpcy5kYXRhLmZpZWxkTmFtZSwKICAgICAgdmFsdWUKICAgIH07CiAgICBjb25zdCBuZXdQYXJlbnREaWN0ID0gdGhpcy5zZXRWYWx1ZShkaWN0LCBBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlLm1hcChzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKSA6IHN0cmluZ1RvQXNjaWlPclVURjE2QkUodmFsdWUpLCB4cmVmLCBjaGFuZ2VzKTsKICAgIHRoaXMuYW1lbmRTYXZlZERpY3QoYW5ub3RhdGlvblN0b3JhZ2UsIG5ld1BhcmVudERpY3QgfHwgZGljdCk7CiAgICBjb25zdCBtYXliZU1LID0gdGhpcy5fZ2V0TUtEaWN0KHJvdGF0aW9uKTsKICAgIGlmIChtYXliZU1LKSB7CiAgICAgIGRpY3Quc2V0KCJNSyIsIG1heWJlTUspOwogICAgfQogICAgY2hhbmdlcy5wdXQodGhpcy5yZWYsIHsKICAgICAgZGF0YTogZGljdCwKICAgICAgeGZhLAogICAgICBuZWVkQXBwZWFyYW5jZXMKICAgIH0pOwogICAgaWYgKGFwcGVhcmFuY2UgIT09IG51bGwpIHsKICAgICAgY29uc3QgbmV3UmVmID0geHJlZi5nZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgY29uc3QgQVAgPSBuZXcgRGljdCh4cmVmKTsKICAgICAgZGljdC5zZXQoIkFQIiwgQVApOwogICAgICBBUC5zZXQoIk4iLCBuZXdSZWYpOwogICAgICBjb25zdCByZXNvdXJjZXMgPSB0aGlzLl9nZXRTYXZlRmllbGRSZXNvdXJjZXMoeHJlZik7CiAgICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW0gPSBuZXcgU3RyaW5nU3RyZWFtKGFwcGVhcmFuY2UpOwogICAgICBjb25zdCBhcHBlYXJhbmNlRGljdCA9IGFwcGVhcmFuY2VTdHJlYW0uZGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgICBhcHBlYXJhbmNlRGljdC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiRm9ybSIpOwogICAgICBhcHBlYXJhbmNlRGljdC5zZXQoIlJlc291cmNlcyIsIHJlc291cmNlcyk7CiAgICAgIGNvbnN0IGJib3ggPSByb3RhdGlvbiAlIDE4MCA9PT0gMCA/IFswLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodF0gOiBbMCwgMCwgdGhpcy5oZWlnaHQsIHRoaXMud2lkdGhdOwogICAgICBhcHBlYXJhbmNlRGljdC5zZXQoIkJCb3giLCBiYm94KTsKICAgICAgY29uc3Qgcm90YXRpb25NYXRyaXggPSB0aGlzLmdldFJvdGF0aW9uTWF0cml4KGFubm90YXRpb25TdG9yYWdlKTsKICAgICAgaWYgKHJvdGF0aW9uTWF0cml4ICE9PSBJREVOVElUWV9NQVRSSVgpIHsKICAgICAgICBhcHBlYXJhbmNlRGljdC5zZXQoIk1hdHJpeCIsIHJvdGF0aW9uTWF0cml4KTsKICAgICAgfQogICAgICBjaGFuZ2VzLnB1dChuZXdSZWYsIHsKICAgICAgICBkYXRhOiBhcHBlYXJhbmNlU3RyZWFtLAogICAgICAgIHhmYTogbnVsbCwKICAgICAgICBuZWVkQXBwZWFyYW5jZXM6IGZhbHNlCiAgICAgIH0pOwogICAgfQogICAgZGljdC5zZXQoIk0iLCBgRDoke2dldE1vZGlmaWNhdGlvbkRhdGUoKX1gKTsKICB9CiAgYXN5bmMgX2dldEFwcGVhcmFuY2UoZXZhbHVhdG9yLCB0YXNrLCBpbnRlbnQsIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBpZiAodGhpcy5kYXRhLnBhc3N3b3JkKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3Qgc3RvcmFnZUVudHJ5ID0gYW5ub3RhdGlvblN0b3JhZ2U/LmdldCh0aGlzLmRhdGEuaWQpOwogICAgbGV0IHZhbHVlLCByb3RhdGlvbjsKICAgIGlmIChzdG9yYWdlRW50cnkpIHsKICAgICAgdmFsdWUgPSBzdG9yYWdlRW50cnkuZm9ybWF0dGVkVmFsdWUgfHwgc3RvcmFnZUVudHJ5LnZhbHVlOwogICAgICByb3RhdGlvbiA9IHN0b3JhZ2VFbnRyeS5yb3RhdGlvbjsKICAgIH0KICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkICYmIHZhbHVlID09PSB1bmRlZmluZWQgJiYgIXRoaXMuX25lZWRBcHBlYXJhbmNlcykgewogICAgICBpZiAoIXRoaXMuX2hhc1ZhbHVlRnJvbVhGQSB8fCB0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQogICAgY29uc3QgY29sb3JzID0gdGhpcy5nZXRCb3JkZXJBbmRCYWNrZ3JvdW5kQXBwZWFyYW5jZXMoYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgdmFsdWUgPSB0aGlzLmRhdGEuZmllbGRWYWx1ZTsKICAgICAgaWYgKCF2YWx1ZSkgewogICAgICAgIHJldHVybiBgL1R4IEJNQyBxICR7Y29sb3JzfVEgRU1DYDsKICAgICAgfQogICAgfQogICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMSkgewogICAgICB2YWx1ZSA9IHZhbHVlWzBdOwogICAgfQogICAgYXNzZXJ0KHR5cGVvZiB2YWx1ZSA9PT0gInN0cmluZyIsICJFeHBlY3RlZCBgdmFsdWVgIHRvIGJlIGEgc3RyaW5nLiIpOwogICAgdmFsdWUgPSB2YWx1ZS50cmltRW5kKCk7CiAgICBpZiAodGhpcy5kYXRhLmNvbWJvKSB7CiAgICAgIGNvbnN0IG9wdGlvbiA9IHRoaXMuZGF0YS5vcHRpb25zLmZpbmQoKHsKICAgICAgICBleHBvcnRWYWx1ZQogICAgICB9KSA9PiB2YWx1ZSA9PT0gZXhwb3J0VmFsdWUpOwogICAgICB2YWx1ZSA9IG9wdGlvbj8uZGlzcGxheVZhbHVlIHx8IHZhbHVlOwogICAgfQogICAgaWYgKHZhbHVlID09PSAiIikgewogICAgICByZXR1cm4gYC9UeCBCTUMgcSAke2NvbG9yc31RIEVNQ2A7CiAgICB9CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCkgewogICAgICByb3RhdGlvbiA9IHRoaXMucm90YXRpb247CiAgICB9CiAgICBsZXQgbGluZUNvdW50ID0gLTE7CiAgICBsZXQgbGluZXM7CiAgICBpZiAodGhpcy5kYXRhLm11bHRpTGluZSkgewogICAgICBsaW5lcyA9IHZhbHVlLnNwbGl0KC9cclxuP3xcbi8pLm1hcChsaW5lID0+IGxpbmUubm9ybWFsaXplKCJORkMiKSk7CiAgICAgIGxpbmVDb3VudCA9IGxpbmVzLmxlbmd0aDsKICAgIH0gZWxzZSB7CiAgICAgIGxpbmVzID0gW3ZhbHVlLnJlcGxhY2UoL1xyXG4/fFxuLywgIiIpLm5vcm1hbGl6ZSgiTkZDIildOwogICAgfQogICAgY29uc3QgZGVmYXVsdFBhZGRpbmcgPSAxOwogICAgY29uc3QgZGVmYXVsdEhQYWRkaW5nID0gMjsKICAgIGxldCB7CiAgICAgIHdpZHRoOiB0b3RhbFdpZHRoLAogICAgICBoZWlnaHQ6IHRvdGFsSGVpZ2h0CiAgICB9ID0gdGhpczsKICAgIGlmIChyb3RhdGlvbiA9PT0gOTAgfHwgcm90YXRpb24gPT09IDI3MCkgewogICAgICBbdG90YWxXaWR0aCwgdG90YWxIZWlnaHRdID0gW3RvdGFsSGVpZ2h0LCB0b3RhbFdpZHRoXTsKICAgIH0KICAgIGlmICghdGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UpIHsKICAgICAgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YSA9IHBhcnNlRGVmYXVsdEFwcGVhcmFuY2UodGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UgPSAiL0hlbHZldGljYSAwIFRmIDAgZyIpOwogICAgfQogICAgbGV0IGZvbnQgPSBhd2FpdCBXaWRnZXRBbm5vdGF0aW9uLl9nZXRGb250RGF0YShldmFsdWF0b3IsIHRhc2ssIHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEsIHRoaXMuX2ZpZWxkUmVzb3VyY2VzLm1lcmdlZFJlc291cmNlcyk7CiAgICBsZXQgZGVmYXVsdEFwcGVhcmFuY2UsIGZvbnRTaXplLCBsaW5lSGVpZ2h0OwogICAgY29uc3QgZW5jb2RlZExpbmVzID0gW107CiAgICBsZXQgZW5jb2RpbmdFcnJvciA9IGZhbHNlOwogICAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7CiAgICAgIGNvbnN0IGVuY29kZWRTdHJpbmcgPSBmb250LmVuY29kZVN0cmluZyhsaW5lKTsKICAgICAgaWYgKGVuY29kZWRTdHJpbmcubGVuZ3RoID4gMSkgewogICAgICAgIGVuY29kaW5nRXJyb3IgPSB0cnVlOwogICAgICB9CiAgICAgIGVuY29kZWRMaW5lcy5wdXNoKGVuY29kZWRTdHJpbmcuam9pbigiIikpOwogICAgfQogICAgaWYgKGVuY29kaW5nRXJyb3IgJiYgaW50ZW50ICYgUmVuZGVyaW5nSW50ZW50RmxhZy5TQVZFKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgbmVlZEFwcGVhcmFuY2VzOiB0cnVlCiAgICAgIH07CiAgICB9CiAgICBpZiAoZW5jb2RpbmdFcnJvciAmJiB0aGlzLl9pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCkgewogICAgICBjb25zdCBmb250RmFtaWx5ID0gdGhpcy5kYXRhLmNvbWIgPyAibW9ub3NwYWNlIiA6ICJzYW5zLXNlcmlmIjsKICAgICAgY29uc3QgZmFrZVVuaWNvZGVGb250ID0gbmV3IEZha2VVbmljb2RlRm9udChldmFsdWF0b3IueHJlZiwgZm9udEZhbWlseSk7CiAgICAgIGNvbnN0IHJlc291cmNlcyA9IGZha2VVbmljb2RlRm9udC5jcmVhdGVGb250UmVzb3VyY2VzKGxpbmVzLmpvaW4oIiIpKTsKICAgICAgY29uc3QgbmV3Rm9udCA9IHJlc291cmNlcy5nZXRSYXcoIkZvbnQiKTsKICAgICAgaWYgKHRoaXMuX2ZpZWxkUmVzb3VyY2VzLm1lcmdlZFJlc291cmNlcy5oYXMoIkZvbnQiKSkgewogICAgICAgIGNvbnN0IG9sZEZvbnQgPSB0aGlzLl9maWVsZFJlc291cmNlcy5tZXJnZWRSZXNvdXJjZXMuZ2V0KCJGb250Iik7CiAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgbmV3Rm9udC5nZXRLZXlzKCkpIHsKICAgICAgICAgIG9sZEZvbnQuc2V0KGtleSwgbmV3Rm9udC5nZXRSYXcoa2V5KSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuX2ZpZWxkUmVzb3VyY2VzLm1lcmdlZFJlc291cmNlcy5zZXQoIkZvbnQiLCBuZXdGb250KTsKICAgICAgfQogICAgICBjb25zdCBmb250TmFtZSA9IGZha2VVbmljb2RlRm9udC5mb250TmFtZS5uYW1lOwogICAgICBmb250ID0gYXdhaXQgV2lkZ2V0QW5ub3RhdGlvbi5fZ2V0Rm9udERhdGEoZXZhbHVhdG9yLCB0YXNrLCB7CiAgICAgICAgZm9udE5hbWUsCiAgICAgICAgZm9udFNpemU6IDAKICAgICAgfSwgcmVzb3VyY2VzKTsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZW5jb2RlZExpbmVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBlbmNvZGVkTGluZXNbaV0gPSBzdHJpbmdUb1VURjE2U3RyaW5nKGxpbmVzW2ldKTsKICAgICAgfQogICAgICBjb25zdCBzYXZlZERlZmF1bHRBcHBlYXJhbmNlID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG51bGwpLCB0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhKTsKICAgICAgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YS5mb250U2l6ZSA9IDA7CiAgICAgIHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEuZm9udE5hbWUgPSBmb250TmFtZTsKICAgICAgW2RlZmF1bHRBcHBlYXJhbmNlLCBmb250U2l6ZSwgbGluZUhlaWdodF0gPSB0aGlzLl9jb21wdXRlRm9udFNpemUodG90YWxIZWlnaHQgLSAyICogZGVmYXVsdFBhZGRpbmcsIHRvdGFsV2lkdGggLSAyICogZGVmYXVsdEhQYWRkaW5nLCB2YWx1ZSwgZm9udCwgbGluZUNvdW50KTsKICAgICAgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YSA9IHNhdmVkRGVmYXVsdEFwcGVhcmFuY2U7CiAgICB9IGVsc2UgewogICAgICBpZiAoIXRoaXMuX2lzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICAgICAgd2FybigiX2dldEFwcGVhcmFuY2U6IE9mZnNjcmVlbkNhbnZhcyBpcyBub3Qgc3VwcG9ydGVkLCBhbm5vdGF0aW9uIG1heSBub3QgcmVuZGVyIGNvcnJlY3RseS4iKTsKICAgICAgfQogICAgICBbZGVmYXVsdEFwcGVhcmFuY2UsIGZvbnRTaXplLCBsaW5lSGVpZ2h0XSA9IHRoaXMuX2NvbXB1dGVGb250U2l6ZSh0b3RhbEhlaWdodCAtIDIgKiBkZWZhdWx0UGFkZGluZywgdG90YWxXaWR0aCAtIDIgKiBkZWZhdWx0SFBhZGRpbmcsIHZhbHVlLCBmb250LCBsaW5lQ291bnQpOwogICAgfQogICAgbGV0IGRlc2NlbnQgPSBmb250LmRlc2NlbnQ7CiAgICBpZiAoaXNOYU4oZGVzY2VudCkpIHsKICAgICAgZGVzY2VudCA9IEJBU0VMSU5FX0ZBQ1RPUiAqIGxpbmVIZWlnaHQ7CiAgICB9IGVsc2UgewogICAgICBkZXNjZW50ID0gTWF0aC5tYXgoQkFTRUxJTkVfRkFDVE9SICogbGluZUhlaWdodCwgTWF0aC5hYnMoZGVzY2VudCkgKiBmb250U2l6ZSk7CiAgICB9CiAgICBjb25zdCBkZWZhdWx0VlBhZGRpbmcgPSBNYXRoLm1pbihNYXRoLmZsb29yKCh0b3RhbEhlaWdodCAtIGZvbnRTaXplKSAvIDIpLCBkZWZhdWx0UGFkZGluZyk7CiAgICBjb25zdCBhbGlnbm1lbnQgPSB0aGlzLmRhdGEudGV4dEFsaWdubWVudDsKICAgIGlmICh0aGlzLmRhdGEubXVsdGlMaW5lKSB7CiAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aWxpbmVBcHBlYXJhbmNlKGRlZmF1bHRBcHBlYXJhbmNlLCBlbmNvZGVkTGluZXMsIGZvbnQsIGZvbnRTaXplLCB0b3RhbFdpZHRoLCB0b3RhbEhlaWdodCwgYWxpZ25tZW50LCBkZWZhdWx0SFBhZGRpbmcsIGRlZmF1bHRWUGFkZGluZywgZGVzY2VudCwgbGluZUhlaWdodCwgYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgfQogICAgaWYgKHRoaXMuZGF0YS5jb21iKSB7CiAgICAgIHJldHVybiB0aGlzLl9nZXRDb21iQXBwZWFyYW5jZShkZWZhdWx0QXBwZWFyYW5jZSwgZm9udCwgZW5jb2RlZExpbmVzWzBdLCBmb250U2l6ZSwgdG90YWxXaWR0aCwgdG90YWxIZWlnaHQsIGRlZmF1bHRIUGFkZGluZywgZGVmYXVsdFZQYWRkaW5nLCBkZXNjZW50LCBsaW5lSGVpZ2h0LCBhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICB9CiAgICBjb25zdCBib3R0b21QYWRkaW5nID0gZGVmYXVsdFZQYWRkaW5nICsgZGVzY2VudDsKICAgIGlmIChhbGlnbm1lbnQgPT09IDAgfHwgYWxpZ25tZW50ID4gMikgewogICAgICByZXR1cm4gYC9UeCBCTUMgcSAke2NvbG9yc31CVCBgICsgZGVmYXVsdEFwcGVhcmFuY2UgKyBgIDEgMCAwIDEgJHtudW1iZXJUb1N0cmluZyhkZWZhdWx0SFBhZGRpbmcpfSAke251bWJlclRvU3RyaW5nKGJvdHRvbVBhZGRpbmcpfSBUbSAoJHtlc2NhcGVTdHJpbmcoZW5jb2RlZExpbmVzWzBdKX0pIFRqYCArICIgRVQgUSBFTUMiOwogICAgfQogICAgY29uc3QgcHJldkluZm8gPSB7CiAgICAgIHNoaWZ0OiAwCiAgICB9OwogICAgY29uc3QgcmVuZGVyZWRUZXh0ID0gdGhpcy5fcmVuZGVyVGV4dChlbmNvZGVkTGluZXNbMF0sIGZvbnQsIGZvbnRTaXplLCB0b3RhbFdpZHRoLCBhbGlnbm1lbnQsIHByZXZJbmZvLCBkZWZhdWx0SFBhZGRpbmcsIGJvdHRvbVBhZGRpbmcpOwogICAgcmV0dXJuIGAvVHggQk1DIHEgJHtjb2xvcnN9QlQgYCArIGRlZmF1bHRBcHBlYXJhbmNlICsgYCAxIDAgMCAxIDAgMCBUbSAke3JlbmRlcmVkVGV4dH1gICsgIiBFVCBRIEVNQyI7CiAgfQogIHN0YXRpYyBhc3luYyBfZ2V0Rm9udERhdGEoZXZhbHVhdG9yLCB0YXNrLCBhcHBlYXJhbmNlRGF0YSwgcmVzb3VyY2VzKSB7CiAgICBjb25zdCBvcGVyYXRvckxpc3QgPSBuZXcgT3BlcmF0b3JMaXN0KCk7CiAgICBjb25zdCBpbml0aWFsU3RhdGUgPSB7CiAgICAgIGZvbnQ6IG51bGwsCiAgICAgIGNsb25lKCkgewogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICB9OwogICAgY29uc3QgewogICAgICBmb250TmFtZSwKICAgICAgZm9udFNpemUKICAgIH0gPSBhcHBlYXJhbmNlRGF0YTsKICAgIGF3YWl0IGV2YWx1YXRvci5oYW5kbGVTZXRGb250KHJlc291cmNlcywgW2ZvbnROYW1lICYmIE5hbWUuZ2V0KGZvbnROYW1lKSwgZm9udFNpemVdLCBudWxsLCBvcGVyYXRvckxpc3QsIHRhc2ssIGluaXRpYWxTdGF0ZSwgbnVsbCk7CiAgICByZXR1cm4gaW5pdGlhbFN0YXRlLmZvbnQ7CiAgfQogIF9nZXRUZXh0V2lkdGgodGV4dCwgZm9udCkgewogICAgcmV0dXJuIE1hdGguc3VtUHJlY2lzZShmb250LmNoYXJzVG9HbHlwaHModGV4dCkubWFwKGcgPT4gZy53aWR0aCkpIC8gMTAwMDsKICB9CiAgX2NvbXB1dGVGb250U2l6ZShoZWlnaHQsIHdpZHRoLCB0ZXh0LCBmb250LCBsaW5lQ291bnQpIHsKICAgIGxldCB7CiAgICAgIGZvbnRTaXplCiAgICB9ID0gdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YTsKICAgIGxldCBsaW5lSGVpZ2h0ID0gKGZvbnRTaXplIHx8IDEyKSAqIExJTkVfRkFDVE9SLAogICAgICBudW1iZXJPZkxpbmVzID0gTWF0aC5yb3VuZChoZWlnaHQgLyBsaW5lSGVpZ2h0KTsKICAgIGlmICghZm9udFNpemUpIHsKICAgICAgY29uc3Qgcm91bmRXaXRoVHdvRGlnaXRzID0geCA9PiBNYXRoLmZsb29yKHggKiAxMDApIC8gMTAwOwogICAgICBpZiAobGluZUNvdW50ID09PSAtMSkgewogICAgICAgIGNvbnN0IHRleHRXaWR0aCA9IHRoaXMuX2dldFRleHRXaWR0aCh0ZXh0LCBmb250KTsKICAgICAgICBmb250U2l6ZSA9IHJvdW5kV2l0aFR3b0RpZ2l0cyhNYXRoLm1pbihoZWlnaHQgLyBMSU5FX0ZBQ1RPUiwgd2lkdGggLyB0ZXh0V2lkdGgpKTsKICAgICAgICBudW1iZXJPZkxpbmVzID0gMTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBsaW5lcyA9IHRleHQuc3BsaXQoL1xyXG4/fFxuLyk7CiAgICAgICAgY29uc3QgY2FjaGVkTGluZXMgPSBbXTsKICAgICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgbGluZXMpIHsKICAgICAgICAgIGNvbnN0IGVuY29kZWQgPSBmb250LmVuY29kZVN0cmluZyhsaW5lKS5qb2luKCIiKTsKICAgICAgICAgIGNvbnN0IGdseXBocyA9IGZvbnQuY2hhcnNUb0dseXBocyhlbmNvZGVkKTsKICAgICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IGZvbnQuZ2V0Q2hhclBvc2l0aW9ucyhlbmNvZGVkKTsKICAgICAgICAgIGNhY2hlZExpbmVzLnB1c2goewogICAgICAgICAgICBsaW5lOiBlbmNvZGVkLAogICAgICAgICAgICBnbHlwaHMsCiAgICAgICAgICAgIHBvc2l0aW9ucwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGlzVG9vQmlnID0gZnNpemUgPT4gewogICAgICAgICAgbGV0IHRvdGFsSGVpZ2h0ID0gMDsKICAgICAgICAgIGZvciAoY29uc3QgY2FjaGUgb2YgY2FjaGVkTGluZXMpIHsKICAgICAgICAgICAgY29uc3QgY2h1bmtzID0gdGhpcy5fc3BsaXRMaW5lKG51bGwsIGZvbnQsIGZzaXplLCB3aWR0aCwgY2FjaGUpOwogICAgICAgICAgICB0b3RhbEhlaWdodCArPSBjaHVua3MubGVuZ3RoICogZnNpemU7CiAgICAgICAgICAgIGlmICh0b3RhbEhlaWdodCA+IGhlaWdodCkgewogICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfTsKICAgICAgICBudW1iZXJPZkxpbmVzID0gTWF0aC5tYXgobnVtYmVyT2ZMaW5lcywgbGluZUNvdW50KTsKICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgbGluZUhlaWdodCA9IGhlaWdodCAvIG51bWJlck9mTGluZXM7CiAgICAgICAgICBmb250U2l6ZSA9IHJvdW5kV2l0aFR3b0RpZ2l0cyhsaW5lSGVpZ2h0IC8gTElORV9GQUNUT1IpOwogICAgICAgICAgaWYgKGlzVG9vQmlnKGZvbnRTaXplKSkgewogICAgICAgICAgICBudW1iZXJPZkxpbmVzKys7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIGNvbnN0IHsKICAgICAgICBmb250TmFtZSwKICAgICAgICBmb250Q29sb3IKICAgICAgfSA9IHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGE7CiAgICAgIHRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlID0gY3JlYXRlRGVmYXVsdEFwcGVhcmFuY2UoewogICAgICAgIGZvbnRTaXplLAogICAgICAgIGZvbnROYW1lLAogICAgICAgIGZvbnRDb2xvcgogICAgICB9KTsKICAgIH0KICAgIHJldHVybiBbdGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UsIGZvbnRTaXplLCBoZWlnaHQgLyBudW1iZXJPZkxpbmVzXTsKICB9CiAgX3JlbmRlclRleHQodGV4dCwgZm9udCwgZm9udFNpemUsIHRvdGFsV2lkdGgsIGFsaWdubWVudCwgcHJldkluZm8sIGhQYWRkaW5nLCB2UGFkZGluZykgewogICAgbGV0IHNoaWZ0OwogICAgaWYgKGFsaWdubWVudCA9PT0gMSkgewogICAgICBjb25zdCB3aWR0aCA9IHRoaXMuX2dldFRleHRXaWR0aCh0ZXh0LCBmb250KSAqIGZvbnRTaXplOwogICAgICBzaGlmdCA9ICh0b3RhbFdpZHRoIC0gd2lkdGgpIC8gMjsKICAgIH0gZWxzZSBpZiAoYWxpZ25tZW50ID09PSAyKSB7CiAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5fZ2V0VGV4dFdpZHRoKHRleHQsIGZvbnQpICogZm9udFNpemU7CiAgICAgIHNoaWZ0ID0gdG90YWxXaWR0aCAtIHdpZHRoIC0gaFBhZGRpbmc7CiAgICB9IGVsc2UgewogICAgICBzaGlmdCA9IGhQYWRkaW5nOwogICAgfQogICAgY29uc3Qgc2hpZnRTdHIgPSBudW1iZXJUb1N0cmluZyhzaGlmdCAtIHByZXZJbmZvLnNoaWZ0KTsKICAgIHByZXZJbmZvLnNoaWZ0ID0gc2hpZnQ7CiAgICB2UGFkZGluZyA9IG51bWJlclRvU3RyaW5nKHZQYWRkaW5nKTsKICAgIHJldHVybiBgJHtzaGlmdFN0cn0gJHt2UGFkZGluZ30gVGQgKCR7ZXNjYXBlU3RyaW5nKHRleHQpfSkgVGpgOwogIH0KICBfZ2V0U2F2ZUZpZWxkUmVzb3VyY2VzKHhyZWYpIHsKICAgIGNvbnN0IHsKICAgICAgbG9jYWxSZXNvdXJjZXMsCiAgICAgIGFwcGVhcmFuY2VSZXNvdXJjZXMsCiAgICAgIGFjcm9Gb3JtUmVzb3VyY2VzCiAgICB9ID0gdGhpcy5fZmllbGRSZXNvdXJjZXM7CiAgICBjb25zdCBmb250TmFtZSA9IHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGE/LmZvbnROYW1lOwogICAgaWYgKCFmb250TmFtZSkgewogICAgICByZXR1cm4gbG9jYWxSZXNvdXJjZXMgfHwgRGljdC5lbXB0eTsKICAgIH0KICAgIGZvciAoY29uc3QgcmVzb3VyY2VzIG9mIFtsb2NhbFJlc291cmNlcywgYXBwZWFyYW5jZVJlc291cmNlc10pIHsKICAgICAgaWYgKHJlc291cmNlcyBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICBjb25zdCBsb2NhbEZvbnQgPSByZXNvdXJjZXMuZ2V0KCJGb250Iik7CiAgICAgICAgaWYgKGxvY2FsRm9udCBpbnN0YW5jZW9mIERpY3QgJiYgbG9jYWxGb250Lmhhcyhmb250TmFtZSkpIHsKICAgICAgICAgIHJldHVybiByZXNvdXJjZXM7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAoYWNyb0Zvcm1SZXNvdXJjZXMgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGNvbnN0IGFjcm9Gb3JtRm9udCA9IGFjcm9Gb3JtUmVzb3VyY2VzLmdldCgiRm9udCIpOwogICAgICBpZiAoYWNyb0Zvcm1Gb250IGluc3RhbmNlb2YgRGljdCAmJiBhY3JvRm9ybUZvbnQuaGFzKGZvbnROYW1lKSkgewogICAgICAgIGNvbnN0IHN1YkZvbnREaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICAgICAgc3ViRm9udERpY3Quc2V0KGZvbnROYW1lLCBhY3JvRm9ybUZvbnQuZ2V0UmF3KGZvbnROYW1lKSk7CiAgICAgICAgY29uc3Qgc3ViUmVzb3VyY2VzRGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgICAgIHN1YlJlc291cmNlc0RpY3Quc2V0KCJGb250Iiwgc3ViRm9udERpY3QpOwogICAgICAgIHJldHVybiBEaWN0Lm1lcmdlKHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBkaWN0QXJyYXk6IFtzdWJSZXNvdXJjZXNEaWN0LCBsb2NhbFJlc291cmNlc10sCiAgICAgICAgICBtZXJnZVN1YkRpY3RzOiB0cnVlCiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBsb2NhbFJlc291cmNlcyB8fCBEaWN0LmVtcHR5OwogIH0KICBnZXRGaWVsZE9iamVjdCgpIHsKICAgIHJldHVybiBudWxsOwogIH0KfQpjbGFzcyBUZXh0V2lkZ2V0QW5ub3RhdGlvbiBleHRlbmRzIFdpZGdldEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdAogICAgfSA9IHBhcmFtczsKICAgIGlmIChkaWN0LmhhcygiUE1EIikpIHsKICAgICAgdGhpcy5mbGFncyB8PSBBbm5vdGF0aW9uRmxhZy5ISURERU47CiAgICAgIHRoaXMuZGF0YS5oaWRkZW4gPSB0cnVlOwogICAgICB3YXJuKCJCYXJjb2RlcyBhcmUgbm90IHN1cHBvcnRlZCIpOwogICAgfQogICAgdGhpcy5kYXRhLmhhc093bkNhbnZhcyA9IHRoaXMuZGF0YS5yZWFkT25seSAmJiAhdGhpcy5kYXRhLm5vSFRNTDsKICAgIHRoaXMuX2hhc1RleHQgPSB0cnVlOwogICAgaWYgKHR5cGVvZiB0aGlzLmRhdGEuZmllbGRWYWx1ZSAhPT0gInN0cmluZyIpIHsKICAgICAgdGhpcy5kYXRhLmZpZWxkVmFsdWUgPSAiIjsKICAgIH0KICAgIGxldCBhbGlnbm1lbnQgPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5KHsKICAgICAgZGljdCwKICAgICAga2V5OiAiUSIKICAgIH0pOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGFsaWdubWVudCkgfHwgYWxpZ25tZW50IDwgMCB8fCBhbGlnbm1lbnQgPiAyKSB7CiAgICAgIGFsaWdubWVudCA9IG51bGw7CiAgICB9CiAgICB0aGlzLmRhdGEudGV4dEFsaWdubWVudCA9IGFsaWdubWVudDsKICAgIGxldCBtYXhpbXVtTGVuZ3RoID0gZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7CiAgICAgIGRpY3QsCiAgICAgIGtleTogIk1heExlbiIKICAgIH0pOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKG1heGltdW1MZW5ndGgpIHx8IG1heGltdW1MZW5ndGggPCAwKSB7CiAgICAgIG1heGltdW1MZW5ndGggPSAwOwogICAgfQogICAgdGhpcy5kYXRhLm1heExlbiA9IG1heGltdW1MZW5ndGg7CiAgICB0aGlzLmRhdGEubXVsdGlMaW5lID0gdGhpcy5oYXNGaWVsZEZsYWcoQW5ub3RhdGlvbkZpZWxkRmxhZy5NVUxUSUxJTkUpOwogICAgdGhpcy5kYXRhLmNvbWIgPSB0aGlzLmhhc0ZpZWxkRmxhZyhBbm5vdGF0aW9uRmllbGRGbGFnLkNPTUIpICYmICF0aGlzLmRhdGEubXVsdGlMaW5lICYmICF0aGlzLmRhdGEucGFzc3dvcmQgJiYgIXRoaXMuaGFzRmllbGRGbGFnKEFubm90YXRpb25GaWVsZEZsYWcuRklMRVNFTEVDVCkgJiYgdGhpcy5kYXRhLm1heExlbiAhPT0gMDsKICAgIHRoaXMuZGF0YS5kb05vdFNjcm9sbCA9IHRoaXMuaGFzRmllbGRGbGFnKEFubm90YXRpb25GaWVsZEZsYWcuRE9OT1RTQ1JPTEwpOwogICAgY29uc3QgewogICAgICBkYXRhOiB7CiAgICAgICAgYWN0aW9ucwogICAgICB9CiAgICB9ID0gdGhpczsKICAgIGlmICghYWN0aW9ucykgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBBRkRhdGVUaW1lID0gL15BRihEYXRlfFRpbWUpXyg/OktleXN0cm9rZXxGb3JtYXQpKD86RXgpP1woWyciXT8oW14nIl0rKVsnIl0/XCk7JC87CiAgICBsZXQgY2FuVXNlSFRNTERhdGVUaW1lID0gZmFsc2U7CiAgICBpZiAoYWN0aW9ucy5Gb3JtYXQ/Lmxlbmd0aCA9PT0gMSAmJiBhY3Rpb25zLktleXN0cm9rZT8ubGVuZ3RoID09PSAxICYmIEFGRGF0ZVRpbWUudGVzdChhY3Rpb25zLkZvcm1hdFswXSkgJiYgQUZEYXRlVGltZS50ZXN0KGFjdGlvbnMuS2V5c3Ryb2tlWzBdKSB8fCBhY3Rpb25zLkZvcm1hdD8ubGVuZ3RoID09PSAwICYmIGFjdGlvbnMuS2V5c3Ryb2tlPy5sZW5ndGggPT09IDEgJiYgQUZEYXRlVGltZS50ZXN0KGFjdGlvbnMuS2V5c3Ryb2tlWzBdKSB8fCBhY3Rpb25zLktleXN0cm9rZT8ubGVuZ3RoID09PSAwICYmIGFjdGlvbnMuRm9ybWF0Py5sZW5ndGggPT09IDEgJiYgQUZEYXRlVGltZS50ZXN0KGFjdGlvbnMuRm9ybWF0WzBdKSkgewogICAgICBjYW5Vc2VIVE1MRGF0ZVRpbWUgPSB0cnVlOwogICAgfQogICAgY29uc3QgYWN0aW9uc1RvVmlzaXQgPSBbXTsKICAgIGlmIChhY3Rpb25zLkZvcm1hdCkgewogICAgICBhY3Rpb25zVG9WaXNpdC5wdXNoKC4uLmFjdGlvbnMuRm9ybWF0KTsKICAgIH0KICAgIGlmIChhY3Rpb25zLktleXN0cm9rZSkgewogICAgICBhY3Rpb25zVG9WaXNpdC5wdXNoKC4uLmFjdGlvbnMuS2V5c3Ryb2tlKTsKICAgIH0KICAgIGlmIChjYW5Vc2VIVE1MRGF0ZVRpbWUpIHsKICAgICAgZGVsZXRlIGFjdGlvbnMuS2V5c3Ryb2tlOwogICAgICBhY3Rpb25zLkZvcm1hdCA9IGFjdGlvbnNUb1Zpc2l0OwogICAgfQogICAgZm9yIChjb25zdCBmb3JtYXRBY3Rpb24gb2YgYWN0aW9uc1RvVmlzaXQpIHsKICAgICAgY29uc3QgbSA9IGZvcm1hdEFjdGlvbi5tYXRjaChBRkRhdGVUaW1lKTsKICAgICAgaWYgKCFtKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgaXNEYXRlID0gbVsxXSA9PT0gIkRhdGUiOwogICAgICBsZXQgZm9ybWF0ID0gbVsyXTsKICAgICAgY29uc3QgbnVtID0gcGFyc2VJbnQoZm9ybWF0LCAxMCk7CiAgICAgIGlmICghaXNOYU4obnVtKSAmJiBNYXRoLmZsb29yKE1hdGgubG9nMTAobnVtKSkgKyAxID09PSBtWzJdLmxlbmd0aCkgewogICAgICAgIGZvcm1hdCA9IChpc0RhdGUgPyBEYXRlRm9ybWF0cyA6IFRpbWVGb3JtYXRzKVtudW1dID8/IGZvcm1hdDsKICAgICAgfQogICAgICB0aGlzLmRhdGEuZGF0ZXRpbWVGb3JtYXQgPSBmb3JtYXQ7CiAgICAgIGlmICghY2FuVXNlSFRNTERhdGVUaW1lKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKGlzRGF0ZSkgewogICAgICAgIGlmICgvSEh8TU18c3N8aC8udGVzdChmb3JtYXQpKSB7CiAgICAgICAgICB0aGlzLmRhdGEuZGF0ZXRpbWVUeXBlID0gImRhdGV0aW1lLWxvY2FsIjsKICAgICAgICAgIHRoaXMuZGF0YS50aW1lU3RlcCA9IC9zcy8udGVzdChmb3JtYXQpID8gMSA6IDYwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLmRhdGEuZGF0ZXRpbWVUeXBlID0gImRhdGUiOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgfQogICAgICB0aGlzLmRhdGEuZGF0ZXRpbWVUeXBlID0gInRpbWUiOwogICAgICB0aGlzLmRhdGEudGltZVN0ZXAgPSAvc3MvLnRlc3QoZm9ybWF0KSA/IDEgOiA2MDsKICAgICAgYnJlYWs7CiAgICB9CiAgfQogIGdldCBoYXNUZXh0Q29udGVudCgpIHsKICAgIHJldHVybiAhIXRoaXMuYXBwZWFyYW5jZSAmJiAhdGhpcy5fbmVlZEFwcGVhcmFuY2VzOwogIH0KICBfZ2V0Q29tYkFwcGVhcmFuY2UoZGVmYXVsdEFwcGVhcmFuY2UsIGZvbnQsIHRleHQsIGZvbnRTaXplLCB3aWR0aCwgaGVpZ2h0LCBoUGFkZGluZywgdlBhZGRpbmcsIGRlc2NlbnQsIGxpbmVIZWlnaHQsIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBjb25zdCBjb21iV2lkdGggPSB3aWR0aCAvIHRoaXMuZGF0YS5tYXhMZW47CiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLmdldEJvcmRlckFuZEJhY2tncm91bmRBcHBlYXJhbmNlcyhhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICBjb25zdCBidWYgPSBbXTsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IGZvbnQuZ2V0Q2hhclBvc2l0aW9ucyh0ZXh0KTsKICAgIGZvciAoY29uc3QgW3N0YXJ0LCBlbmRdIG9mIHBvc2l0aW9ucykgewogICAgICBidWYucHVzaChgKCR7ZXNjYXBlU3RyaW5nKHRleHQuc3Vic3RyaW5nKHN0YXJ0LCBlbmQpKX0pIFRqYCk7CiAgICB9CiAgICBjb25zdCByZW5kZXJlZENvbWIgPSBidWYuam9pbihgICR7bnVtYmVyVG9TdHJpbmcoY29tYldpZHRoKX0gMCBUZCBgKTsKICAgIHJldHVybiBgL1R4IEJNQyBxICR7Y29sb3JzfUJUIGAgKyBkZWZhdWx0QXBwZWFyYW5jZSArIGAgMSAwIDAgMSAke251bWJlclRvU3RyaW5nKGhQYWRkaW5nKX0gJHtudW1iZXJUb1N0cmluZyh2UGFkZGluZyArIGRlc2NlbnQpfSBUbSAke3JlbmRlcmVkQ29tYn1gICsgIiBFVCBRIEVNQyI7CiAgfQogIF9nZXRNdWx0aWxpbmVBcHBlYXJhbmNlKGRlZmF1bHRBcHBlYXJhbmNlLCBsaW5lcywgZm9udCwgZm9udFNpemUsIHdpZHRoLCBoZWlnaHQsIGFsaWdubWVudCwgaFBhZGRpbmcsIHZQYWRkaW5nLCBkZXNjZW50LCBsaW5lSGVpZ2h0LCBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgY29uc3QgYnVmID0gW107CiAgICBjb25zdCB0b3RhbFdpZHRoID0gd2lkdGggLSAyICogaFBhZGRpbmc7CiAgICBjb25zdCBwcmV2SW5mbyA9IHsKICAgICAgc2hpZnQ6IDAKICAgIH07CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBsaW5lcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IGxpbmUgPSBsaW5lc1tpXTsKICAgICAgY29uc3QgY2h1bmtzID0gdGhpcy5fc3BsaXRMaW5lKGxpbmUsIGZvbnQsIGZvbnRTaXplLCB0b3RhbFdpZHRoKTsKICAgICAgZm9yIChsZXQgaiA9IDAsIGpqID0gY2h1bmtzLmxlbmd0aDsgaiA8IGpqOyBqKyspIHsKICAgICAgICBjb25zdCBjaHVuayA9IGNodW5rc1tqXTsKICAgICAgICBjb25zdCB2U2hpZnQgPSBpID09PSAwICYmIGogPT09IDAgPyAtdlBhZGRpbmcgLSAobGluZUhlaWdodCAtIGRlc2NlbnQpIDogLWxpbmVIZWlnaHQ7CiAgICAgICAgYnVmLnB1c2godGhpcy5fcmVuZGVyVGV4dChjaHVuaywgZm9udCwgZm9udFNpemUsIHdpZHRoLCBhbGlnbm1lbnQsIHByZXZJbmZvLCBoUGFkZGluZywgdlNoaWZ0KSk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuZ2V0Qm9yZGVyQW5kQmFja2dyb3VuZEFwcGVhcmFuY2VzKGFubm90YXRpb25TdG9yYWdlKTsKICAgIGNvbnN0IHJlbmRlcmVkVGV4dCA9IGJ1Zi5qb2luKCJcbiIpOwogICAgcmV0dXJuIGAvVHggQk1DIHEgJHtjb2xvcnN9QlQgYCArIGRlZmF1bHRBcHBlYXJhbmNlICsgYCAxIDAgMCAxIDAgJHtudW1iZXJUb1N0cmluZyhoZWlnaHQpfSBUbSAke3JlbmRlcmVkVGV4dH1gICsgIiBFVCBRIEVNQyI7CiAgfQogIF9zcGxpdExpbmUobGluZSwgZm9udCwgZm9udFNpemUsIHdpZHRoLCBjYWNoZSA9IHt9KSB7CiAgICBsaW5lID0gY2FjaGUubGluZSB8fCBsaW5lOwogICAgY29uc3QgZ2x5cGhzID0gY2FjaGUuZ2x5cGhzIHx8IGZvbnQuY2hhcnNUb0dseXBocyhsaW5lKTsKICAgIGlmIChnbHlwaHMubGVuZ3RoIDw9IDEpIHsKICAgICAgcmV0dXJuIFtsaW5lXTsKICAgIH0KICAgIGNvbnN0IHBvc2l0aW9ucyA9IGNhY2hlLnBvc2l0aW9ucyB8fCBmb250LmdldENoYXJQb3NpdGlvbnMobGluZSk7CiAgICBjb25zdCBzY2FsZSA9IGZvbnRTaXplIC8gMTAwMDsKICAgIGNvbnN0IGNodW5rcyA9IFtdOwogICAgbGV0IGxhc3RTcGFjZVBvc0luU3RyaW5nU3RhcnQgPSAtMSwKICAgICAgbGFzdFNwYWNlUG9zSW5TdHJpbmdFbmQgPSAtMSwKICAgICAgbGFzdFNwYWNlUG9zID0gLTEsCiAgICAgIHN0YXJ0Q2h1bmsgPSAwLAogICAgICBjdXJyZW50V2lkdGggPSAwOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZ2x5cGhzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgW3N0YXJ0LCBlbmRdID0gcG9zaXRpb25zW2ldOwogICAgICBjb25zdCBnbHlwaCA9IGdseXBoc1tpXTsKICAgICAgY29uc3QgZ2x5cGhXaWR0aCA9IGdseXBoLndpZHRoICogc2NhbGU7CiAgICAgIGlmIChnbHlwaC51bmljb2RlID09PSAiICIpIHsKICAgICAgICBpZiAoY3VycmVudFdpZHRoICsgZ2x5cGhXaWR0aCA+IHdpZHRoKSB7CiAgICAgICAgICBjaHVua3MucHVzaChsaW5lLnN1YnN0cmluZyhzdGFydENodW5rLCBzdGFydCkpOwogICAgICAgICAgc3RhcnRDaHVuayA9IHN0YXJ0OwogICAgICAgICAgY3VycmVudFdpZHRoID0gZ2x5cGhXaWR0aDsKICAgICAgICAgIGxhc3RTcGFjZVBvc0luU3RyaW5nU3RhcnQgPSAtMTsKICAgICAgICAgIGxhc3RTcGFjZVBvcyA9IC0xOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjdXJyZW50V2lkdGggKz0gZ2x5cGhXaWR0aDsKICAgICAgICAgIGxhc3RTcGFjZVBvc0luU3RyaW5nU3RhcnQgPSBzdGFydDsKICAgICAgICAgIGxhc3RTcGFjZVBvc0luU3RyaW5nRW5kID0gZW5kOwogICAgICAgICAgbGFzdFNwYWNlUG9zID0gaTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFdpZHRoICsgZ2x5cGhXaWR0aCA+IHdpZHRoKSB7CiAgICAgICAgaWYgKGxhc3RTcGFjZVBvc0luU3RyaW5nU3RhcnQgIT09IC0xKSB7CiAgICAgICAgICBjaHVua3MucHVzaChsaW5lLnN1YnN0cmluZyhzdGFydENodW5rLCBsYXN0U3BhY2VQb3NJblN0cmluZ0VuZCkpOwogICAgICAgICAgc3RhcnRDaHVuayA9IGxhc3RTcGFjZVBvc0luU3RyaW5nRW5kOwogICAgICAgICAgaSA9IGxhc3RTcGFjZVBvcyArIDE7CiAgICAgICAgICBsYXN0U3BhY2VQb3NJblN0cmluZ1N0YXJ0ID0gLTE7CiAgICAgICAgICBjdXJyZW50V2lkdGggPSAwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjaHVua3MucHVzaChsaW5lLnN1YnN0cmluZyhzdGFydENodW5rLCBzdGFydCkpOwogICAgICAgICAgc3RhcnRDaHVuayA9IHN0YXJ0OwogICAgICAgICAgY3VycmVudFdpZHRoID0gZ2x5cGhXaWR0aDsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY3VycmVudFdpZHRoICs9IGdseXBoV2lkdGg7CiAgICAgIH0KICAgIH0KICAgIGlmIChzdGFydENodW5rIDwgbGluZS5sZW5ndGgpIHsKICAgICAgY2h1bmtzLnB1c2gobGluZS5zdWJzdHJpbmcoc3RhcnRDaHVuaywgbGluZS5sZW5ndGgpKTsKICAgIH0KICAgIHJldHVybiBjaHVua3M7CiAgfQogIGFzeW5jIGV4dHJhY3RUZXh0Q29udGVudChldmFsdWF0b3IsIHRhc2ssIHZpZXdCb3gpIHsKICAgIGF3YWl0IHN1cGVyLmV4dHJhY3RUZXh0Q29udGVudChldmFsdWF0b3IsIHRhc2ssIHZpZXdCb3gpOwogICAgY29uc3QgdGV4dCA9IHRoaXMuZGF0YS50ZXh0Q29udGVudDsKICAgIGlmICghdGV4dCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBhbGxUZXh0ID0gdGV4dC5qb2luKCJcbiIpOwogICAgaWYgKGFsbFRleHQgPT09IHRoaXMuZGF0YS5maWVsZFZhbHVlKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHJlZ2V4ID0gYWxsVGV4dC5yZXBsYWNlQWxsKC8oWy4qKz9eJHt9KCl8W1xdXFxdKXwoXHMrKS9nLCAoX20sIHAxKSA9PiBwMSA/IGBcXCR7cDF9YCA6ICJcXHMrIik7CiAgICBpZiAobmV3IFJlZ0V4cChgXlxccyoke3JlZ2V4fVxccyokYCkudGVzdCh0aGlzLmRhdGEuZmllbGRWYWx1ZSkpIHsKICAgICAgdGhpcy5kYXRhLnRleHRDb250ZW50ID0gdGhpcy5kYXRhLmZpZWxkVmFsdWUuc3BsaXQoIlxuIik7CiAgICB9CiAgfQogIGdldEZpZWxkT2JqZWN0KCkgewogICAgcmV0dXJuIHsKICAgICAgaWQ6IHRoaXMuZGF0YS5pZCwKICAgICAgdmFsdWU6IHRoaXMuZGF0YS5maWVsZFZhbHVlLAogICAgICBkZWZhdWx0VmFsdWU6IHRoaXMuZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSB8fCAiIiwKICAgICAgbXVsdGlsaW5lOiB0aGlzLmRhdGEubXVsdGlMaW5lLAogICAgICBwYXNzd29yZDogdGhpcy5kYXRhLnBhc3N3b3JkLAogICAgICBjaGFyTGltaXQ6IHRoaXMuZGF0YS5tYXhMZW4sCiAgICAgIGNvbWI6IHRoaXMuZGF0YS5jb21iLAogICAgICBlZGl0YWJsZTogIXRoaXMuZGF0YS5yZWFkT25seSwKICAgICAgaGlkZGVuOiB0aGlzLmRhdGEuaGlkZGVuLAogICAgICBuYW1lOiB0aGlzLmRhdGEuZmllbGROYW1lLAogICAgICByZWN0OiB0aGlzLmRhdGEucmVjdCwKICAgICAgYWN0aW9uczogdGhpcy5kYXRhLmFjdGlvbnMsCiAgICAgIHBhZ2U6IHRoaXMuZGF0YS5wYWdlSW5kZXgsCiAgICAgIHN0cm9rZUNvbG9yOiB0aGlzLmRhdGEuYm9yZGVyQ29sb3IsCiAgICAgIGZpbGxDb2xvcjogdGhpcy5kYXRhLmJhY2tncm91bmRDb2xvciwKICAgICAgcm90YXRpb246IHRoaXMucm90YXRpb24sCiAgICAgIGRhdGV0aW1lRm9ybWF0OiB0aGlzLmRhdGEuZGF0ZXRpbWVGb3JtYXQsCiAgICAgIGhhc0RhdGV0aW1lSFRNTDogISF0aGlzLmRhdGEuZGF0ZXRpbWVUeXBlLAogICAgICB0eXBlOiAidGV4dCIKICAgIH07CiAgfQp9CmNsYXNzIEJ1dHRvbldpZGdldEFubm90YXRpb24gZXh0ZW5kcyBXaWRnZXRBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICB0aGlzLmNoZWNrZWRBcHBlYXJhbmNlID0gbnVsbDsKICAgIHRoaXMudW5jaGVja2VkQXBwZWFyYW5jZSA9IG51bGw7CiAgICBjb25zdCBpc1JhZGlvID0gdGhpcy5oYXNGaWVsZEZsYWcoQW5ub3RhdGlvbkZpZWxkRmxhZy5SQURJTyksCiAgICAgIGlzUHVzaEJ1dHRvbiA9IHRoaXMuaGFzRmllbGRGbGFnKEFubm90YXRpb25GaWVsZEZsYWcuUFVTSEJVVFRPTik7CiAgICB0aGlzLmRhdGEuY2hlY2tCb3ggPSAhaXNSYWRpbyAmJiAhaXNQdXNoQnV0dG9uOwogICAgdGhpcy5kYXRhLnJhZGlvQnV0dG9uID0gaXNSYWRpbyAmJiAhaXNQdXNoQnV0dG9uOwogICAgdGhpcy5kYXRhLnB1c2hCdXR0b24gPSBpc1B1c2hCdXR0b247CiAgICB0aGlzLmRhdGEuaXNUb29sdGlwT25seSA9IGZhbHNlOwogICAgaWYgKHRoaXMuZGF0YS5jaGVja0JveCkgewogICAgICB0aGlzLl9wcm9jZXNzQ2hlY2tCb3gocGFyYW1zKTsKICAgIH0gZWxzZSBpZiAodGhpcy5kYXRhLnJhZGlvQnV0dG9uKSB7CiAgICAgIHRoaXMuX3Byb2Nlc3NSYWRpb0J1dHRvbihwYXJhbXMpOwogICAgfSBlbHNlIGlmICh0aGlzLmRhdGEucHVzaEJ1dHRvbikgewogICAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdHJ1ZTsKICAgICAgdGhpcy5kYXRhLm5vSFRNTCA9IGZhbHNlOwogICAgICB0aGlzLl9wcm9jZXNzUHVzaEJ1dHRvbihwYXJhbXMpOwogICAgfSBlbHNlIHsKICAgICAgd2FybigiSW52YWxpZCBmaWVsZCBmbGFncyBmb3IgYnV0dG9uIHdpZGdldCBhbm5vdGF0aW9uIik7CiAgICB9CiAgfQogIGFzeW5jIGdldE9wZXJhdG9yTGlzdChldmFsdWF0b3IsIHRhc2ssIGludGVudCwgYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIGlmICh0aGlzLmRhdGEucHVzaEJ1dHRvbikgewogICAgICByZXR1cm4gc3VwZXIuZ2V0T3BlcmF0b3JMaXN0KGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBmYWxzZSwgYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgfQogICAgbGV0IHZhbHVlID0gbnVsbDsKICAgIGxldCByb3RhdGlvbiA9IG51bGw7CiAgICBpZiAoYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgICAgY29uc3Qgc3RvcmFnZUVudHJ5ID0gYW5ub3RhdGlvblN0b3JhZ2UuZ2V0KHRoaXMuZGF0YS5pZCk7CiAgICAgIHZhbHVlID0gc3RvcmFnZUVudHJ5ID8gc3RvcmFnZUVudHJ5LnZhbHVlIDogbnVsbDsKICAgICAgcm90YXRpb24gPSBzdG9yYWdlRW50cnkgPyBzdG9yYWdlRW50cnkucm90YXRpb24gOiBudWxsOwogICAgfQogICAgaWYgKHZhbHVlID09PSBudWxsICYmIHRoaXMuYXBwZWFyYW5jZSkgewogICAgICByZXR1cm4gc3VwZXIuZ2V0T3BlcmF0b3JMaXN0KGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICB9CiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICB2YWx1ZSA9IHRoaXMuZGF0YS5jaGVja0JveCA/IHRoaXMuZGF0YS5maWVsZFZhbHVlID09PSB0aGlzLmRhdGEuZXhwb3J0VmFsdWUgOiB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9PT0gdGhpcy5kYXRhLmJ1dHRvblZhbHVlOwogICAgfQogICAgY29uc3QgYXBwZWFyYW5jZSA9IHZhbHVlID8gdGhpcy5jaGVja2VkQXBwZWFyYW5jZSA6IHRoaXMudW5jaGVja2VkQXBwZWFyYW5jZTsKICAgIGlmIChhcHBlYXJhbmNlKSB7CiAgICAgIGNvbnN0IHNhdmVkQXBwZWFyYW5jZSA9IHRoaXMuYXBwZWFyYW5jZTsKICAgICAgY29uc3Qgc2F2ZWRNYXRyaXggPSBsb29rdXBNYXRyaXgoYXBwZWFyYW5jZS5kaWN0LmdldEFycmF5KCJNYXRyaXgiKSwgSURFTlRJVFlfTUFUUklYKTsKICAgICAgaWYgKHJvdGF0aW9uKSB7CiAgICAgICAgYXBwZWFyYW5jZS5kaWN0LnNldCgiTWF0cml4IiwgdGhpcy5nZXRSb3RhdGlvbk1hdHJpeChhbm5vdGF0aW9uU3RvcmFnZSkpOwogICAgICB9CiAgICAgIHRoaXMuYXBwZWFyYW5jZSA9IGFwcGVhcmFuY2U7CiAgICAgIGNvbnN0IG9wZXJhdG9yTGlzdCA9IHN1cGVyLmdldE9wZXJhdG9yTGlzdChldmFsdWF0b3IsIHRhc2ssIGludGVudCwgYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgICB0aGlzLmFwcGVhcmFuY2UgPSBzYXZlZEFwcGVhcmFuY2U7CiAgICAgIGFwcGVhcmFuY2UuZGljdC5zZXQoIk1hdHJpeCIsIHNhdmVkTWF0cml4KTsKICAgICAgcmV0dXJuIG9wZXJhdG9yTGlzdDsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIG9wTGlzdDogbmV3IE9wZXJhdG9yTGlzdCgpLAogICAgICBzZXBhcmF0ZUZvcm06IGZhbHNlLAogICAgICBzZXBhcmF0ZUNhbnZhczogZmFsc2UKICAgIH07CiAgfQogIGFzeW5jIHNhdmUoZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSwgY2hhbmdlcykgewogICAgaWYgKHRoaXMuZGF0YS5jaGVja0JveCkgewogICAgICB0aGlzLl9zYXZlQ2hlY2tib3goZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSwgY2hhbmdlcyk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0aGlzLmRhdGEucmFkaW9CdXR0b24pIHsKICAgICAgdGhpcy5fc2F2ZVJhZGlvQnV0dG9uKGV2YWx1YXRvciwgdGFzaywgYW5ub3RhdGlvblN0b3JhZ2UsIGNoYW5nZXMpOwogICAgfQogIH0KICBhc3luYyBfc2F2ZUNoZWNrYm94KGV2YWx1YXRvciwgdGFzaywgYW5ub3RhdGlvblN0b3JhZ2UsIGNoYW5nZXMpIHsKICAgIGlmICghYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgc3RvcmFnZUVudHJ5ID0gYW5ub3RhdGlvblN0b3JhZ2UuZ2V0KHRoaXMuZGF0YS5pZCk7CiAgICBjb25zdCBmbGFncyA9IHRoaXMuX2J1aWxkRmxhZ3Moc3RvcmFnZUVudHJ5Py5ub1ZpZXcsIHN0b3JhZ2VFbnRyeT8ubm9QcmludCk7CiAgICBsZXQgcm90YXRpb24gPSBzdG9yYWdlRW50cnk/LnJvdGF0aW9uLAogICAgICB2YWx1ZSA9IHN0b3JhZ2VFbnRyeT8udmFsdWU7CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCAmJiBmbGFncyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IHRoaXMuZGF0YS5maWVsZFZhbHVlID09PSB0aGlzLmRhdGEuZXhwb3J0VmFsdWU7CiAgICAgIGlmIChkZWZhdWx0VmFsdWUgPT09IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICB9CiAgICBsZXQgZGljdCA9IGV2YWx1YXRvci54cmVmLmZldGNoSWZSZWYodGhpcy5yZWYpOwogICAgaWYgKCEoZGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGRpY3QgPSBkaWN0LmNsb25lKCk7CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCkgewogICAgICByb3RhdGlvbiA9IHRoaXMucm90YXRpb247CiAgICB9CiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICB2YWx1ZSA9IHRoaXMuZGF0YS5maWVsZFZhbHVlID09PSB0aGlzLmRhdGEuZXhwb3J0VmFsdWU7CiAgICB9CiAgICBjb25zdCB4ZmEgPSB7CiAgICAgIHBhdGg6IHRoaXMuZGF0YS5maWVsZE5hbWUsCiAgICAgIHZhbHVlOiB2YWx1ZSA/IHRoaXMuZGF0YS5leHBvcnRWYWx1ZSA6ICIiCiAgICB9OwogICAgY29uc3QgbmFtZSA9IE5hbWUuZ2V0KHZhbHVlID8gdGhpcy5kYXRhLmV4cG9ydFZhbHVlIDogIk9mZiIpOwogICAgdGhpcy5zZXRWYWx1ZShkaWN0LCBuYW1lLCBldmFsdWF0b3IueHJlZiwgY2hhbmdlcyk7CiAgICBkaWN0LnNldCgiQVMiLCBuYW1lKTsKICAgIGRpY3Quc2V0KCJNIiwgYEQ6JHtnZXRNb2RpZmljYXRpb25EYXRlKCl9YCk7CiAgICBpZiAoZmxhZ3MgIT09IHVuZGVmaW5lZCkgewogICAgICBkaWN0LnNldCgiRiIsIGZsYWdzKTsKICAgIH0KICAgIGNvbnN0IG1heWJlTUsgPSB0aGlzLl9nZXRNS0RpY3Qocm90YXRpb24pOwogICAgaWYgKG1heWJlTUspIHsKICAgICAgZGljdC5zZXQoIk1LIiwgbWF5YmVNSyk7CiAgICB9CiAgICBjaGFuZ2VzLnB1dCh0aGlzLnJlZiwgewogICAgICBkYXRhOiBkaWN0LAogICAgICB4ZmEsCiAgICAgIG5lZWRBcHBlYXJhbmNlczogZmFsc2UKICAgIH0pOwogIH0KICBhc3luYyBfc2F2ZVJhZGlvQnV0dG9uKGV2YWx1YXRvciwgdGFzaywgYW5ub3RhdGlvblN0b3JhZ2UsIGNoYW5nZXMpIHsKICAgIGlmICghYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgc3RvcmFnZUVudHJ5ID0gYW5ub3RhdGlvblN0b3JhZ2UuZ2V0KHRoaXMuZGF0YS5pZCk7CiAgICBjb25zdCBmbGFncyA9IHRoaXMuX2J1aWxkRmxhZ3Moc3RvcmFnZUVudHJ5Py5ub1ZpZXcsIHN0b3JhZ2VFbnRyeT8ubm9QcmludCk7CiAgICBsZXQgcm90YXRpb24gPSBzdG9yYWdlRW50cnk/LnJvdGF0aW9uLAogICAgICB2YWx1ZSA9IHN0b3JhZ2VFbnRyeT8udmFsdWU7CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCAmJiBmbGFncyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IHRoaXMuZGF0YS5maWVsZFZhbHVlID09PSB0aGlzLmRhdGEuYnV0dG9uVmFsdWU7CiAgICAgIGlmIChkZWZhdWx0VmFsdWUgPT09IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICB9CiAgICBsZXQgZGljdCA9IGV2YWx1YXRvci54cmVmLmZldGNoSWZSZWYodGhpcy5yZWYpOwogICAgaWYgKCEoZGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGRpY3QgPSBkaWN0LmNsb25lKCk7CiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICB2YWx1ZSA9IHRoaXMuZGF0YS5maWVsZFZhbHVlID09PSB0aGlzLmRhdGEuYnV0dG9uVmFsdWU7CiAgICB9CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCkgewogICAgICByb3RhdGlvbiA9IHRoaXMucm90YXRpb247CiAgICB9CiAgICBjb25zdCB4ZmEgPSB7CiAgICAgIHBhdGg6IHRoaXMuZGF0YS5maWVsZE5hbWUsCiAgICAgIHZhbHVlOiB2YWx1ZSA/IHRoaXMuZGF0YS5idXR0b25WYWx1ZSA6ICIiCiAgICB9OwogICAgY29uc3QgbmFtZSA9IE5hbWUuZ2V0KHZhbHVlID8gdGhpcy5kYXRhLmJ1dHRvblZhbHVlIDogIk9mZiIpOwogICAgaWYgKHZhbHVlKSB7CiAgICAgIHRoaXMuc2V0VmFsdWUoZGljdCwgbmFtZSwgZXZhbHVhdG9yLnhyZWYsIGNoYW5nZXMpOwogICAgfQogICAgZGljdC5zZXQoIkFTIiwgbmFtZSk7CiAgICBkaWN0LnNldCgiTSIsIGBEOiR7Z2V0TW9kaWZpY2F0aW9uRGF0ZSgpfWApOwogICAgaWYgKGZsYWdzICE9PSB1bmRlZmluZWQpIHsKICAgICAgZGljdC5zZXQoIkYiLCBmbGFncyk7CiAgICB9CiAgICBjb25zdCBtYXliZU1LID0gdGhpcy5fZ2V0TUtEaWN0KHJvdGF0aW9uKTsKICAgIGlmIChtYXliZU1LKSB7CiAgICAgIGRpY3Quc2V0KCJNSyIsIG1heWJlTUspOwogICAgfQogICAgY2hhbmdlcy5wdXQodGhpcy5yZWYsIHsKICAgICAgZGF0YTogZGljdCwKICAgICAgeGZhLAogICAgICBuZWVkQXBwZWFyYW5jZXM6IGZhbHNlCiAgICB9KTsKICB9CiAgX2dldERlZmF1bHRDaGVja2VkQXBwZWFyYW5jZShwYXJhbXMsIHR5cGUpIHsKICAgIGNvbnN0IHsKICAgICAgd2lkdGgsCiAgICAgIGhlaWdodAogICAgfSA9IHRoaXM7CiAgICBjb25zdCBiYm94ID0gWzAsIDAsIHdpZHRoLCBoZWlnaHRdOwogICAgY29uc3QgRk9OVF9SQVRJTyA9IDAuODsKICAgIGNvbnN0IGZvbnRTaXplID0gTWF0aC5taW4od2lkdGgsIGhlaWdodCkgKiBGT05UX1JBVElPOwogICAgbGV0IG1ldHJpY3MsIGNoYXI7CiAgICBpZiAodHlwZSA9PT0gImNoZWNrIikgewogICAgICBtZXRyaWNzID0gewogICAgICAgIHdpZHRoOiAwLjc1NSAqIGZvbnRTaXplLAogICAgICAgIGhlaWdodDogMC43MDUgKiBmb250U2l6ZQogICAgICB9OwogICAgICBjaGFyID0gIlx4MzMiOwogICAgfSBlbHNlIGlmICh0eXBlID09PSAiZGlzYyIpIHsKICAgICAgbWV0cmljcyA9IHsKICAgICAgICB3aWR0aDogMC43OTEgKiBmb250U2l6ZSwKICAgICAgICBoZWlnaHQ6IDAuNzA1ICogZm9udFNpemUKICAgICAgfTsKICAgICAgY2hhciA9ICJceDZDIjsKICAgIH0gZWxzZSB7CiAgICAgIHVucmVhY2hhYmxlKGBfZ2V0RGVmYXVsdENoZWNrZWRBcHBlYXJhbmNlIC0gdW5zdXBwb3J0ZWQgdHlwZTogJHt0eXBlfWApOwogICAgfQogICAgY29uc3QgeFNoaWZ0ID0gbnVtYmVyVG9TdHJpbmcoKHdpZHRoIC0gbWV0cmljcy53aWR0aCkgLyAyKTsKICAgIGNvbnN0IHlTaGlmdCA9IG51bWJlclRvU3RyaW5nKChoZWlnaHQgLSBtZXRyaWNzLmhlaWdodCkgLyAyKTsKICAgIGNvbnN0IGFwcGVhcmFuY2UgPSBgcSBCVCAvUGRmSnNaYURiICR7Zm9udFNpemV9IFRmIDAgZyAke3hTaGlmdH0gJHt5U2hpZnR9IFRkICgke2NoYXJ9KSBUaiBFVCBRYDsKICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW1EaWN0ID0gbmV3IERpY3QocGFyYW1zLnhyZWYpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJGb3JtVHlwZSIsIDEpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIkZvcm0iKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldElmTmFtZSgiVHlwZSIsICJYT2JqZWN0Iik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkJCb3giLCBiYm94KTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiTWF0cml4IiwgWzEsIDAsIDAsIDEsIDAsIDBdKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiTGVuZ3RoIiwgYXBwZWFyYW5jZS5sZW5ndGgpOwogICAgY29uc3QgcmVzb3VyY2VzID0gbmV3IERpY3QocGFyYW1zLnhyZWYpOwogICAgY29uc3QgZm9udCA9IG5ldyBEaWN0KHBhcmFtcy54cmVmKTsKICAgIGZvbnQuc2V0KCJQZGZKc1phRGIiLCB0aGlzLmZhbGxiYWNrRm9udERpY3QpOwogICAgcmVzb3VyY2VzLnNldCgiRm9udCIsIGZvbnQpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJSZXNvdXJjZXMiLCByZXNvdXJjZXMpOwogICAgdGhpcy5jaGVja2VkQXBwZWFyYW5jZSA9IG5ldyBTdHJpbmdTdHJlYW0oYXBwZWFyYW5jZSk7CiAgICB0aGlzLmNoZWNrZWRBcHBlYXJhbmNlLmRpY3QgPSBhcHBlYXJhbmNlU3RyZWFtRGljdDsKICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmNoZWNrZWRBcHBlYXJhbmNlKTsKICB9CiAgX3Byb2Nlc3NDaGVja0JveChwYXJhbXMpIHsKICAgIGNvbnN0IGN1c3RvbUFwcGVhcmFuY2UgPSBwYXJhbXMuZGljdC5nZXQoIkFQIik7CiAgICBpZiAoIShjdXN0b21BcHBlYXJhbmNlIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgbm9ybWFsQXBwZWFyYW5jZSA9IGN1c3RvbUFwcGVhcmFuY2UuZ2V0KCJOIik7CiAgICBpZiAoIShub3JtYWxBcHBlYXJhbmNlIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgYXNWYWx1ZSA9IHRoaXMuX2RlY29kZUZvcm1WYWx1ZShwYXJhbXMuZGljdC5nZXQoIkFTIikpOwogICAgaWYgKHR5cGVvZiBhc1ZhbHVlID09PSAic3RyaW5nIikgewogICAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9IGFzVmFsdWU7CiAgICB9CiAgICBjb25zdCB5ZXMgPSB0aGlzLmRhdGEuZmllbGRWYWx1ZSAhPT0gbnVsbCAmJiB0aGlzLmRhdGEuZmllbGRWYWx1ZSAhPT0gIk9mZiIgPyB0aGlzLmRhdGEuZmllbGRWYWx1ZSA6ICJZZXMiOwogICAgY29uc3QgZXhwb3J0VmFsdWVzID0gdGhpcy5fZGVjb2RlRm9ybVZhbHVlKG5vcm1hbEFwcGVhcmFuY2UuZ2V0S2V5cygpKTsKICAgIGlmIChleHBvcnRWYWx1ZXMubGVuZ3RoID09PSAwKSB7CiAgICAgIGV4cG9ydFZhbHVlcy5wdXNoKCJPZmYiLCB5ZXMpOwogICAgfSBlbHNlIGlmIChleHBvcnRWYWx1ZXMubGVuZ3RoID09PSAxKSB7CiAgICAgIGlmIChleHBvcnRWYWx1ZXNbMF0gPT09ICJPZmYiKSB7CiAgICAgICAgZXhwb3J0VmFsdWVzLnB1c2goeWVzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBleHBvcnRWYWx1ZXMudW5zaGlmdCgiT2ZmIik7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoZXhwb3J0VmFsdWVzLmluY2x1ZGVzKHllcykpIHsKICAgICAgZXhwb3J0VmFsdWVzLmxlbmd0aCA9IDA7CiAgICAgIGV4cG9ydFZhbHVlcy5wdXNoKCJPZmYiLCB5ZXMpOwogICAgfSBlbHNlIHsKICAgICAgY29uc3Qgb3RoZXJZZXMgPSBleHBvcnRWYWx1ZXMuZmluZCh2ID0+IHYgIT09ICJPZmYiKTsKICAgICAgZXhwb3J0VmFsdWVzLmxlbmd0aCA9IDA7CiAgICAgIGV4cG9ydFZhbHVlcy5wdXNoKCJPZmYiLCBvdGhlclllcyk7CiAgICB9CiAgICBpZiAoIWV4cG9ydFZhbHVlcy5pbmNsdWRlcyh0aGlzLmRhdGEuZmllbGRWYWx1ZSkpIHsKICAgICAgdGhpcy5kYXRhLmZpZWxkVmFsdWUgPSAiT2ZmIjsKICAgIH0KICAgIHRoaXMuZGF0YS5leHBvcnRWYWx1ZSA9IGV4cG9ydFZhbHVlc1sxXTsKICAgIGNvbnN0IGNoZWNrZWRBcHBlYXJhbmNlID0gbm9ybWFsQXBwZWFyYW5jZS5nZXQodGhpcy5kYXRhLmV4cG9ydFZhbHVlKTsKICAgIHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UgPSBjaGVja2VkQXBwZWFyYW5jZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0gPyBjaGVja2VkQXBwZWFyYW5jZSA6IG51bGw7CiAgICBjb25zdCB1bmNoZWNrZWRBcHBlYXJhbmNlID0gbm9ybWFsQXBwZWFyYW5jZS5nZXQoIk9mZiIpOwogICAgdGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlID0gdW5jaGVja2VkQXBwZWFyYW5jZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0gPyB1bmNoZWNrZWRBcHBlYXJhbmNlIDogbnVsbDsKICAgIGlmICh0aGlzLmNoZWNrZWRBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmNoZWNrZWRBcHBlYXJhbmNlKTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuX2dldERlZmF1bHRDaGVja2VkQXBwZWFyYW5jZShwYXJhbXMsICJjaGVjayIpOwogICAgfQogICAgaWYgKHRoaXMudW5jaGVja2VkQXBwZWFyYW5jZSkgewogICAgICB0aGlzLl9zdHJlYW1zLnB1c2godGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlKTsKICAgIH0KICAgIHRoaXMuX2ZhbGxiYWNrRm9udERpY3QgPSB0aGlzLmZhbGxiYWNrRm9udERpY3Q7CiAgICBpZiAodGhpcy5kYXRhLmRlZmF1bHRGaWVsZFZhbHVlID09PSBudWxsKSB7CiAgICAgIHRoaXMuZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSA9ICJPZmYiOwogICAgfQogIH0KICBfcHJvY2Vzc1JhZGlvQnV0dG9uKHBhcmFtcykgewogICAgdGhpcy5kYXRhLmJ1dHRvblZhbHVlID0gbnVsbDsKICAgIGNvbnN0IGZpZWxkUGFyZW50ID0gcGFyYW1zLmRpY3QuZ2V0KCJQYXJlbnQiKTsKICAgIGlmIChmaWVsZFBhcmVudCBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgdGhpcy5wYXJlbnQgPSBwYXJhbXMuZGljdC5nZXRSYXcoIlBhcmVudCIpOwogICAgICBjb25zdCBmaWVsZFBhcmVudFZhbHVlID0gZmllbGRQYXJlbnQuZ2V0KCJWIik7CiAgICAgIGlmIChmaWVsZFBhcmVudFZhbHVlIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgIHRoaXMuZGF0YS5maWVsZFZhbHVlID0gdGhpcy5fZGVjb2RlRm9ybVZhbHVlKGZpZWxkUGFyZW50VmFsdWUpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBhcHBlYXJhbmNlU3RhdGVzID0gcGFyYW1zLmRpY3QuZ2V0KCJBUCIpOwogICAgaWYgKCEoYXBwZWFyYW5jZVN0YXRlcyBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG5vcm1hbEFwcGVhcmFuY2UgPSBhcHBlYXJhbmNlU3RhdGVzLmdldCgiTiIpOwogICAgaWYgKCEobm9ybWFsQXBwZWFyYW5jZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGZvciAoY29uc3Qga2V5IG9mIG5vcm1hbEFwcGVhcmFuY2UuZ2V0S2V5cygpKSB7CiAgICAgIGlmIChrZXkgIT09ICJPZmYiKSB7CiAgICAgICAgdGhpcy5kYXRhLmJ1dHRvblZhbHVlID0gdGhpcy5fZGVjb2RlRm9ybVZhbHVlKGtleSk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGNoZWNrZWRBcHBlYXJhbmNlID0gbm9ybWFsQXBwZWFyYW5jZS5nZXQodGhpcy5kYXRhLmJ1dHRvblZhbHVlKTsKICAgIHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UgPSBjaGVja2VkQXBwZWFyYW5jZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0gPyBjaGVja2VkQXBwZWFyYW5jZSA6IG51bGw7CiAgICBjb25zdCB1bmNoZWNrZWRBcHBlYXJhbmNlID0gbm9ybWFsQXBwZWFyYW5jZS5nZXQoIk9mZiIpOwogICAgdGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlID0gdW5jaGVja2VkQXBwZWFyYW5jZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0gPyB1bmNoZWNrZWRBcHBlYXJhbmNlIDogbnVsbDsKICAgIGlmICh0aGlzLmNoZWNrZWRBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmNoZWNrZWRBcHBlYXJhbmNlKTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuX2dldERlZmF1bHRDaGVja2VkQXBwZWFyYW5jZShwYXJhbXMsICJkaXNjIik7CiAgICB9CiAgICBpZiAodGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2UpOwogICAgfQogICAgdGhpcy5fZmFsbGJhY2tGb250RGljdCA9IHRoaXMuZmFsbGJhY2tGb250RGljdDsKICAgIGlmICh0aGlzLmRhdGEuZGVmYXVsdEZpZWxkVmFsdWUgPT09IG51bGwpIHsKICAgICAgdGhpcy5kYXRhLmRlZmF1bHRGaWVsZFZhbHVlID0gIk9mZiI7CiAgICB9CiAgfQogIF9wcm9jZXNzUHVzaEJ1dHRvbihwYXJhbXMpIHsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgYW5ub3RhdGlvbkdsb2JhbHMKICAgIH0gPSBwYXJhbXM7CiAgICBpZiAoIWRpY3QuaGFzKCJBIikgJiYgIWRpY3QuaGFzKCJBQSIpICYmICF0aGlzLmRhdGEuYWx0ZXJuYXRpdmVUZXh0KSB7CiAgICAgIHdhcm4oIlB1c2ggYnV0dG9ucyB3aXRob3V0IGFjdGlvbiBkaWN0aW9uYXJpZXMgYXJlIG5vdCBzdXBwb3J0ZWQiKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5kYXRhLmlzVG9vbHRpcE9ubHkgPSAhZGljdC5oYXMoIkEiKSAmJiAhZGljdC5oYXMoIkFBIik7CiAgICBDYXRhbG9nLnBhcnNlRGVzdERpY3Rpb25hcnkoewogICAgICBkZXN0RGljdDogZGljdCwKICAgICAgcmVzdWx0T2JqOiB0aGlzLmRhdGEsCiAgICAgIGRvY0Jhc2VVcmw6IGFubm90YXRpb25HbG9iYWxzLmJhc2VVcmwsCiAgICAgIGRvY0F0dGFjaG1lbnRzOiBhbm5vdGF0aW9uR2xvYmFscy5hdHRhY2htZW50cwogICAgfSk7CiAgfQogIGdldEZpZWxkT2JqZWN0KCkgewogICAgbGV0IHR5cGUgPSAiYnV0dG9uIjsKICAgIGxldCBleHBvcnRWYWx1ZXM7CiAgICBpZiAodGhpcy5kYXRhLmNoZWNrQm94KSB7CiAgICAgIHR5cGUgPSAiY2hlY2tib3giOwogICAgICBleHBvcnRWYWx1ZXMgPSB0aGlzLmRhdGEuZXhwb3J0VmFsdWU7CiAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YS5yYWRpb0J1dHRvbikgewogICAgICB0eXBlID0gInJhZGlvYnV0dG9uIjsKICAgICAgZXhwb3J0VmFsdWVzID0gdGhpcy5kYXRhLmJ1dHRvblZhbHVlOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgaWQ6IHRoaXMuZGF0YS5pZCwKICAgICAgdmFsdWU6IHRoaXMuZGF0YS5maWVsZFZhbHVlIHx8ICJPZmYiLAogICAgICBkZWZhdWx0VmFsdWU6IHRoaXMuZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSwKICAgICAgZXhwb3J0VmFsdWVzLAogICAgICBlZGl0YWJsZTogIXRoaXMuZGF0YS5yZWFkT25seSwKICAgICAgbmFtZTogdGhpcy5kYXRhLmZpZWxkTmFtZSwKICAgICAgcmVjdDogdGhpcy5kYXRhLnJlY3QsCiAgICAgIGhpZGRlbjogdGhpcy5kYXRhLmhpZGRlbiwKICAgICAgYWN0aW9uczogdGhpcy5kYXRhLmFjdGlvbnMsCiAgICAgIHBhZ2U6IHRoaXMuZGF0YS5wYWdlSW5kZXgsCiAgICAgIHN0cm9rZUNvbG9yOiB0aGlzLmRhdGEuYm9yZGVyQ29sb3IsCiAgICAgIGZpbGxDb2xvcjogdGhpcy5kYXRhLmJhY2tncm91bmRDb2xvciwKICAgICAgcm90YXRpb246IHRoaXMucm90YXRpb24sCiAgICAgIHR5cGUKICAgIH07CiAgfQogIGdldCBmYWxsYmFja0ZvbnREaWN0KCkgewogICAgY29uc3QgZGljdCA9IG5ldyBEaWN0KCk7CiAgICBkaWN0LnNldElmTmFtZSgiQmFzZUZvbnQiLCAiWmFwZkRpbmdiYXRzIik7CiAgICBkaWN0LnNldElmTmFtZSgiVHlwZSIsICJGYWxsYmFja1R5cGUiKTsKICAgIGRpY3Quc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIkZhbGxiYWNrVHlwZSIpOwogICAgZGljdC5zZXRJZk5hbWUoIkVuY29kaW5nIiwgIlphcGZEaW5nYmF0c0VuY29kaW5nIik7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJmYWxsYmFja0ZvbnREaWN0IiwgZGljdCk7CiAgfQp9CmNsYXNzIENob2ljZVdpZGdldEFubm90YXRpb24gZXh0ZW5kcyBXaWRnZXRBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIHhyZWYKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmluZGljZXMgPSBkaWN0LmdldEFycmF5KCJJIik7CiAgICB0aGlzLmhhc0luZGljZXMgPSBBcnJheS5pc0FycmF5KHRoaXMuaW5kaWNlcykgJiYgdGhpcy5pbmRpY2VzLmxlbmd0aCA+IDA7CiAgICB0aGlzLmRhdGEub3B0aW9ucyA9IFtdOwogICAgY29uc3Qgb3B0aW9ucyA9IGdldEluaGVyaXRhYmxlUHJvcGVydHkoewogICAgICBkaWN0LAogICAgICBrZXk6ICJPcHQiCiAgICB9KTsKICAgIGlmIChBcnJheS5pc0FycmF5KG9wdGlvbnMpKSB7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IG9wdGlvbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IG9wdGlvbiA9IHhyZWYuZmV0Y2hJZlJlZihvcHRpb25zW2ldKTsKICAgICAgICBjb25zdCBpc09wdGlvbkFycmF5ID0gQXJyYXkuaXNBcnJheShvcHRpb24pOwogICAgICAgIHRoaXMuZGF0YS5vcHRpb25zW2ldID0gewogICAgICAgICAgZXhwb3J0VmFsdWU6IHRoaXMuX2RlY29kZUZvcm1WYWx1ZShpc09wdGlvbkFycmF5ID8geHJlZi5mZXRjaElmUmVmKG9wdGlvblswXSkgOiBvcHRpb24pLAogICAgICAgICAgZGlzcGxheVZhbHVlOiB0aGlzLl9kZWNvZGVGb3JtVmFsdWUoaXNPcHRpb25BcnJheSA/IHhyZWYuZmV0Y2hJZlJlZihvcHRpb25bMV0pIDogb3B0aW9uKQogICAgICAgIH07CiAgICAgIH0KICAgIH0KICAgIGlmICghdGhpcy5oYXNJbmRpY2VzKSB7CiAgICAgIGlmICh0eXBlb2YgdGhpcy5kYXRhLmZpZWxkVmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgICAgdGhpcy5kYXRhLmZpZWxkVmFsdWUgPSBbdGhpcy5kYXRhLmZpZWxkVmFsdWVdOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuZGF0YS5maWVsZFZhbHVlIHx8PSBbXTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdGhpcy5kYXRhLmZpZWxkVmFsdWUgPSBbXTsKICAgICAgY29uc3QgaWkgPSB0aGlzLmRhdGEub3B0aW9ucy5sZW5ndGg7CiAgICAgIGZvciAoY29uc3QgaSBvZiB0aGlzLmluZGljZXMpIHsKICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihpKSAmJiBpID49IDAgJiYgaSA8IGlpKSB7CiAgICAgICAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZS5wdXNoKHRoaXMuZGF0YS5vcHRpb25zW2ldLmV4cG9ydFZhbHVlKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzLmRhdGEub3B0aW9ucy5sZW5ndGggPT09IDAgJiYgdGhpcy5kYXRhLmZpZWxkVmFsdWUubGVuZ3RoID4gMCkgewogICAgICB0aGlzLmRhdGEub3B0aW9ucyA9IHRoaXMuZGF0YS5maWVsZFZhbHVlLm1hcCh2YWx1ZSA9PiAoewogICAgICAgIGV4cG9ydFZhbHVlOiB2YWx1ZSwKICAgICAgICBkaXNwbGF5VmFsdWU6IHZhbHVlCiAgICAgIH0pKTsKICAgIH0KICAgIHRoaXMuZGF0YS5jb21ibyA9IHRoaXMuaGFzRmllbGRGbGFnKEFubm90YXRpb25GaWVsZEZsYWcuQ09NQk8pOwogICAgdGhpcy5kYXRhLm11bHRpU2VsZWN0ID0gdGhpcy5oYXNGaWVsZEZsYWcoQW5ub3RhdGlvbkZpZWxkRmxhZy5NVUxUSVNFTEVDVCk7CiAgICB0aGlzLl9oYXNUZXh0ID0gdHJ1ZTsKICB9CiAgZ2V0RmllbGRPYmplY3QoKSB7CiAgICBjb25zdCB0eXBlID0gdGhpcy5kYXRhLmNvbWJvID8gImNvbWJvYm94IiA6ICJsaXN0Ym94IjsKICAgIGNvbnN0IHZhbHVlID0gdGhpcy5kYXRhLmZpZWxkVmFsdWUubGVuZ3RoID4gMCA/IHRoaXMuZGF0YS5maWVsZFZhbHVlWzBdIDogbnVsbDsKICAgIHJldHVybiB7CiAgICAgIGlkOiB0aGlzLmRhdGEuaWQsCiAgICAgIHZhbHVlLAogICAgICBkZWZhdWx0VmFsdWU6IHRoaXMuZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSwKICAgICAgZWRpdGFibGU6ICF0aGlzLmRhdGEucmVhZE9ubHksCiAgICAgIG5hbWU6IHRoaXMuZGF0YS5maWVsZE5hbWUsCiAgICAgIHJlY3Q6IHRoaXMuZGF0YS5yZWN0LAogICAgICBudW1JdGVtczogdGhpcy5kYXRhLmZpZWxkVmFsdWUubGVuZ3RoLAogICAgICBtdWx0aXBsZVNlbGVjdGlvbjogdGhpcy5kYXRhLm11bHRpU2VsZWN0LAogICAgICBoaWRkZW46IHRoaXMuZGF0YS5oaWRkZW4sCiAgICAgIGFjdGlvbnM6IHRoaXMuZGF0YS5hY3Rpb25zLAogICAgICBpdGVtczogdGhpcy5kYXRhLm9wdGlvbnMsCiAgICAgIHBhZ2U6IHRoaXMuZGF0YS5wYWdlSW5kZXgsCiAgICAgIHN0cm9rZUNvbG9yOiB0aGlzLmRhdGEuYm9yZGVyQ29sb3IsCiAgICAgIGZpbGxDb2xvcjogdGhpcy5kYXRhLmJhY2tncm91bmRDb2xvciwKICAgICAgcm90YXRpb246IHRoaXMucm90YXRpb24sCiAgICAgIHR5cGUKICAgIH07CiAgfQogIGFtZW5kU2F2ZWREaWN0KGFubm90YXRpb25TdG9yYWdlLCBkaWN0KSB7CiAgICBpZiAoIXRoaXMuaGFzSW5kaWNlcykgewogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgdmFsdWVzID0gYW5ub3RhdGlvblN0b3JhZ2U/LmdldCh0aGlzLmRhdGEuaWQpPy52YWx1ZTsKICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZXMpKSB7CiAgICAgIHZhbHVlcyA9IFt2YWx1ZXNdOwogICAgfQogICAgY29uc3QgaW5kaWNlcyA9IFtdOwogICAgY29uc3QgewogICAgICBvcHRpb25zCiAgICB9ID0gdGhpcy5kYXRhOwogICAgZm9yIChsZXQgaSA9IDAsIGogPSAwLCBpaSA9IG9wdGlvbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBpZiAob3B0aW9uc1tpXS5leHBvcnRWYWx1ZSA9PT0gdmFsdWVzW2pdKSB7CiAgICAgICAgaW5kaWNlcy5wdXNoKGkpOwogICAgICAgIGogKz0gMTsKICAgICAgfQogICAgfQogICAgZGljdC5zZXQoIkkiLCBpbmRpY2VzKTsKICB9CiAgYXN5bmMgX2dldEFwcGVhcmFuY2UoZXZhbHVhdG9yLCB0YXNrLCBpbnRlbnQsIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBpZiAodGhpcy5kYXRhLmNvbWJvKSB7CiAgICAgIHJldHVybiBzdXBlci5fZ2V0QXBwZWFyYW5jZShldmFsdWF0b3IsIHRhc2ssIGludGVudCwgYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgfQogICAgbGV0IGV4cG9ydGVkVmFsdWUsIHJvdGF0aW9uOwogICAgY29uc3Qgc3RvcmFnZUVudHJ5ID0gYW5ub3RhdGlvblN0b3JhZ2U/LmdldCh0aGlzLmRhdGEuaWQpOwogICAgaWYgKHN0b3JhZ2VFbnRyeSkgewogICAgICByb3RhdGlvbiA9IHN0b3JhZ2VFbnRyeS5yb3RhdGlvbjsKICAgICAgZXhwb3J0ZWRWYWx1ZSA9IHN0b3JhZ2VFbnRyeS52YWx1ZTsKICAgIH0KICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkICYmIGV4cG9ydGVkVmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhdGhpcy5fbmVlZEFwcGVhcmFuY2VzKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKGV4cG9ydGVkVmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICBleHBvcnRlZFZhbHVlID0gdGhpcy5kYXRhLmZpZWxkVmFsdWU7CiAgICB9IGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KGV4cG9ydGVkVmFsdWUpKSB7CiAgICAgIGV4cG9ydGVkVmFsdWUgPSBbZXhwb3J0ZWRWYWx1ZV07CiAgICB9CiAgICBjb25zdCBkZWZhdWx0UGFkZGluZyA9IDE7CiAgICBjb25zdCBkZWZhdWx0SFBhZGRpbmcgPSAyOwogICAgbGV0IHsKICAgICAgd2lkdGg6IHRvdGFsV2lkdGgsCiAgICAgIGhlaWdodDogdG90YWxIZWlnaHQKICAgIH0gPSB0aGlzOwogICAgaWYgKHJvdGF0aW9uID09PSA5MCB8fCByb3RhdGlvbiA9PT0gMjcwKSB7CiAgICAgIFt0b3RhbFdpZHRoLCB0b3RhbEhlaWdodF0gPSBbdG90YWxIZWlnaHQsIHRvdGFsV2lkdGhdOwogICAgfQogICAgY29uc3QgbGluZUNvdW50ID0gdGhpcy5kYXRhLm9wdGlvbnMubGVuZ3RoOwogICAgY29uc3QgdmFsdWVJbmRpY2VzID0gW107CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVDb3VudDsgaSsrKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBleHBvcnRWYWx1ZQogICAgICB9ID0gdGhpcy5kYXRhLm9wdGlvbnNbaV07CiAgICAgIGlmIChleHBvcnRlZFZhbHVlLmluY2x1ZGVzKGV4cG9ydFZhbHVlKSkgewogICAgICAgIHZhbHVlSW5kaWNlcy5wdXNoKGkpOwogICAgICB9CiAgICB9CiAgICBpZiAoIXRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEgPSBwYXJzZURlZmF1bHRBcHBlYXJhbmNlKHRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlID0gIi9IZWx2ZXRpY2EgMCBUZiAwIGciKTsKICAgIH0KICAgIGNvbnN0IGZvbnQgPSBhd2FpdCBXaWRnZXRBbm5vdGF0aW9uLl9nZXRGb250RGF0YShldmFsdWF0b3IsIHRhc2ssIHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEsIHRoaXMuX2ZpZWxkUmVzb3VyY2VzLm1lcmdlZFJlc291cmNlcyk7CiAgICBsZXQgZGVmYXVsdEFwcGVhcmFuY2U7CiAgICBsZXQgewogICAgICBmb250U2l6ZQogICAgfSA9IHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGE7CiAgICBpZiAoIWZvbnRTaXplKSB7CiAgICAgIGNvbnN0IGxpbmVIZWlnaHQgPSAodG90YWxIZWlnaHQgLSBkZWZhdWx0UGFkZGluZykgLyBsaW5lQ291bnQ7CiAgICAgIGxldCBsaW5lV2lkdGggPSAtMTsKICAgICAgbGV0IHZhbHVlOwogICAgICBmb3IgKGNvbnN0IHsKICAgICAgICBkaXNwbGF5VmFsdWUKICAgICAgfSBvZiB0aGlzLmRhdGEub3B0aW9ucykgewogICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5fZ2V0VGV4dFdpZHRoKGRpc3BsYXlWYWx1ZSwgZm9udCk7CiAgICAgICAgaWYgKHdpZHRoID4gbGluZVdpZHRoKSB7CiAgICAgICAgICBsaW5lV2lkdGggPSB3aWR0aDsKICAgICAgICAgIHZhbHVlID0gZGlzcGxheVZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICBbZGVmYXVsdEFwcGVhcmFuY2UsIGZvbnRTaXplXSA9IHRoaXMuX2NvbXB1dGVGb250U2l6ZShsaW5lSGVpZ2h0LCB0b3RhbFdpZHRoIC0gMiAqIGRlZmF1bHRIUGFkZGluZywgdmFsdWUsIGZvbnQsIC0xKTsKICAgIH0gZWxzZSB7CiAgICAgIGRlZmF1bHRBcHBlYXJhbmNlID0gdGhpcy5fZGVmYXVsdEFwcGVhcmFuY2U7CiAgICB9CiAgICBjb25zdCBsaW5lSGVpZ2h0ID0gZm9udFNpemUgKiBMSU5FX0ZBQ1RPUjsKICAgIGNvbnN0IHZQYWRkaW5nID0gKGxpbmVIZWlnaHQgLSBmb250U2l6ZSkgLyAyOwogICAgY29uc3QgbnVtYmVyT2ZWaXNpYmxlTGluZXMgPSBNYXRoLmZsb29yKHRvdGFsSGVpZ2h0IC8gbGluZUhlaWdodCk7CiAgICBsZXQgZmlyc3RJbmRleCA9IDA7CiAgICBpZiAodmFsdWVJbmRpY2VzLmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgbWluSW5kZXggPSBNYXRoLm1pbiguLi52YWx1ZUluZGljZXMpOwogICAgICBjb25zdCBtYXhJbmRleCA9IE1hdGgubWF4KC4uLnZhbHVlSW5kaWNlcyk7CiAgICAgIGZpcnN0SW5kZXggPSBNYXRoLm1heCgwLCBtYXhJbmRleCAtIG51bWJlck9mVmlzaWJsZUxpbmVzICsgMSk7CiAgICAgIGlmIChmaXJzdEluZGV4ID4gbWluSW5kZXgpIHsKICAgICAgICBmaXJzdEluZGV4ID0gbWluSW5kZXg7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGVuZCA9IE1hdGgubWluKGZpcnN0SW5kZXggKyBudW1iZXJPZlZpc2libGVMaW5lcyArIDEsIGxpbmVDb3VudCk7CiAgICBjb25zdCBidWYgPSBbIi9UeCBCTUMgcSIsIGAxIDEgJHt0b3RhbFdpZHRofSAke3RvdGFsSGVpZ2h0fSByZSBXIG5gXTsKICAgIGlmICh2YWx1ZUluZGljZXMubGVuZ3RoKSB7CiAgICAgIGJ1Zi5wdXNoKCIwLjYwMDAwNiAwLjc1Njg2NiAwLjg1NDkwNCByZyIpOwogICAgICBmb3IgKGNvbnN0IGluZGV4IG9mIHZhbHVlSW5kaWNlcykgewogICAgICAgIGlmIChmaXJzdEluZGV4IDw9IGluZGV4ICYmIGluZGV4IDwgZW5kKSB7CiAgICAgICAgICBidWYucHVzaChgMSAke3RvdGFsSGVpZ2h0IC0gKGluZGV4IC0gZmlyc3RJbmRleCArIDEpICogbGluZUhlaWdodH0gJHt0b3RhbFdpZHRofSAke2xpbmVIZWlnaHR9IHJlIGZgKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGJ1Zi5wdXNoKCJCVCIsIGRlZmF1bHRBcHBlYXJhbmNlLCBgMSAwIDAgMSAwICR7dG90YWxIZWlnaHR9IFRtYCk7CiAgICBjb25zdCBwcmV2SW5mbyA9IHsKICAgICAgc2hpZnQ6IDAKICAgIH07CiAgICBmb3IgKGxldCBpID0gZmlyc3RJbmRleDsgaSA8IGVuZDsgaSsrKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBkaXNwbGF5VmFsdWUKICAgICAgfSA9IHRoaXMuZGF0YS5vcHRpb25zW2ldOwogICAgICBjb25zdCB2cGFkZGluZyA9IGkgPT09IGZpcnN0SW5kZXggPyB2UGFkZGluZyA6IDA7CiAgICAgIGJ1Zi5wdXNoKHRoaXMuX3JlbmRlclRleHQoZGlzcGxheVZhbHVlLCBmb250LCBmb250U2l6ZSwgdG90YWxXaWR0aCwgMCwgcHJldkluZm8sIGRlZmF1bHRIUGFkZGluZywgLWxpbmVIZWlnaHQgKyB2cGFkZGluZykpOwogICAgfQogICAgYnVmLnB1c2goIkVUIFEgRU1DIik7CiAgICByZXR1cm4gYnVmLmpvaW4oIlxuIik7CiAgfQp9CmNsYXNzIFNpZ25hdHVyZVdpZGdldEFubm90YXRpb24gZXh0ZW5kcyBXaWRnZXRBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9IG51bGw7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogICAgdGhpcy5kYXRhLm5vSFRNTCA9ICF0aGlzLmRhdGEuaGFzT3duQ2FudmFzOwogIH0KICBnZXRGaWVsZE9iamVjdCgpIHsKICAgIHJldHVybiB7CiAgICAgIGlkOiB0aGlzLmRhdGEuaWQsCiAgICAgIHZhbHVlOiBudWxsLAogICAgICBwYWdlOiB0aGlzLmRhdGEucGFnZUluZGV4LAogICAgICB0eXBlOiAic2lnbmF0dXJlIgogICAgfTsKICB9Cn0KY2xhc3MgVGV4dEFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIGNvbnN0IERFRkFVTFRfSUNPTl9TSVpFID0gMjI7CiAgICBzdXBlcihwYXJhbXMpOwogICAgdGhpcy5kYXRhLm5vUm90YXRlID0gdHJ1ZTsKICAgIHRoaXMuZGF0YS5oYXNPd25DYW52YXMgPSB0aGlzLmRhdGEubm9Sb3RhdGU7CiAgICB0aGlzLmRhdGEubm9IVE1MID0gZmFsc2U7CiAgICBjb25zdCB7CiAgICAgIGRpY3QKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBBbm5vdGF0aW9uVHlwZS5URVhUOwogICAgaWYgKHRoaXMuZGF0YS5oYXNBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuZGF0YS5uYW1lID0gIk5vSWNvbiI7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEucmVjdFsxXSA9IHRoaXMuZGF0YS5yZWN0WzNdIC0gREVGQVVMVF9JQ09OX1NJWkU7CiAgICAgIHRoaXMuZGF0YS5yZWN0WzJdID0gdGhpcy5kYXRhLnJlY3RbMF0gKyBERUZBVUxUX0lDT05fU0laRTsKICAgICAgdGhpcy5kYXRhLm5hbWUgPSBkaWN0LmhhcygiTmFtZSIpID8gZGljdC5nZXQoIk5hbWUiKS5uYW1lIDogIk5vdGUiOwogICAgfQogICAgaWYgKGRpY3QuaGFzKCJTdGF0ZSIpKSB7CiAgICAgIHRoaXMuZGF0YS5zdGF0ZSA9IGRpY3QuZ2V0KCJTdGF0ZSIpIHx8IG51bGw7CiAgICAgIHRoaXMuZGF0YS5zdGF0ZU1vZGVsID0gZGljdC5nZXQoIlN0YXRlTW9kZWwiKSB8fCBudWxsOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5kYXRhLnN0YXRlID0gbnVsbDsKICAgICAgdGhpcy5kYXRhLnN0YXRlTW9kZWwgPSBudWxsOwogICAgfQogIH0KfQpjbGFzcyBMaW5rQW5ub3RhdGlvbiBleHRlbmRzIEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgYW5ub3RhdGlvbkdsb2JhbHMKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBBbm5vdGF0aW9uVHlwZS5MSU5LOwogICAgdGhpcy5kYXRhLm5vSFRNTCA9IGZhbHNlOwogICAgY29uc3QgcXVhZFBvaW50cyA9IGdldFF1YWRQb2ludHMoZGljdCwgdGhpcy5yZWN0YW5nbGUpOwogICAgaWYgKHF1YWRQb2ludHMpIHsKICAgICAgdGhpcy5kYXRhLnF1YWRQb2ludHMgPSBxdWFkUG9pbnRzOwogICAgfQogICAgdGhpcy5kYXRhLmJvcmRlckNvbG9yIHx8PSB0aGlzLmRhdGEuY29sb3I7CiAgICBDYXRhbG9nLnBhcnNlRGVzdERpY3Rpb25hcnkoewogICAgICBkZXN0RGljdDogZGljdCwKICAgICAgcmVzdWx0T2JqOiB0aGlzLmRhdGEsCiAgICAgIGRvY0Jhc2VVcmw6IGFubm90YXRpb25HbG9iYWxzLmJhc2VVcmwsCiAgICAgIGRvY0F0dGFjaG1lbnRzOiBhbm5vdGF0aW9uR2xvYmFscy5hdHRhY2htZW50cwogICAgfSk7CiAgfQogIGdldCBvdmVybGF5c1RleHRDb250ZW50KCkgewogICAgcmV0dXJuIHRydWU7CiAgfQp9CmNsYXNzIFBvcHVwQW5ub3RhdGlvbiBleHRlbmRzIEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdAogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLlBPUFVQOwogICAgdGhpcy5kYXRhLm5vSFRNTCA9IGZhbHNlOwogICAgaWYgKHRoaXMud2lkdGggPT09IDAgfHwgdGhpcy5oZWlnaHQgPT09IDApIHsKICAgICAgdGhpcy5kYXRhLnJlY3QgPSBudWxsOwogICAgfQogICAgbGV0IHBhcmVudEl0ZW0gPSBkaWN0LmdldCgiUGFyZW50Iik7CiAgICBpZiAoIXBhcmVudEl0ZW0pIHsKICAgICAgd2FybigiUG9wdXAgYW5ub3RhdGlvbiBoYXMgYSBtaXNzaW5nIG9yIGludmFsaWQgcGFyZW50IGFubm90YXRpb24uIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuZGF0YS5wYXJlbnRSZWN0ID0gbG9va3VwTm9ybWFsUmVjdChwYXJlbnRJdGVtLmdldEFycmF5KCJSZWN0IiksIG51bGwpOwogICAgdGhpcy5kYXRhLmNyZWF0aW9uRGF0ZSA9IHBhcmVudEl0ZW0uZ2V0KCJDcmVhdGlvbkRhdGUiKSB8fCAiIjsKICAgIGNvbnN0IHJ0ID0gcGFyZW50SXRlbS5nZXQoIlJUIik7CiAgICBpZiAoaXNOYW1lKHJ0LCBBbm5vdGF0aW9uUmVwbHlUeXBlLkdST1VQKSkgewogICAgICBwYXJlbnRJdGVtID0gcGFyZW50SXRlbS5nZXQoIklSVCIpOwogICAgfQogICAgaWYgKCFwYXJlbnRJdGVtLmhhcygiTSIpKSB7CiAgICAgIHRoaXMuZGF0YS5tb2RpZmljYXRpb25EYXRlID0gbnVsbDsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuc2V0TW9kaWZpY2F0aW9uRGF0ZShwYXJlbnRJdGVtLmdldCgiTSIpKTsKICAgICAgdGhpcy5kYXRhLm1vZGlmaWNhdGlvbkRhdGUgPSB0aGlzLm1vZGlmaWNhdGlvbkRhdGU7CiAgICB9CiAgICBpZiAoIXBhcmVudEl0ZW0uaGFzKCJDIikpIHsKICAgICAgdGhpcy5kYXRhLmNvbG9yID0gbnVsbDsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuc2V0Q29sb3IocGFyZW50SXRlbS5nZXRBcnJheSgiQyIpKTsKICAgICAgdGhpcy5kYXRhLmNvbG9yID0gdGhpcy5jb2xvcjsKICAgIH0KICAgIGlmICghdGhpcy52aWV3YWJsZSkgewogICAgICBjb25zdCBwYXJlbnRGbGFncyA9IHBhcmVudEl0ZW0uZ2V0KCJGIik7CiAgICAgIGlmICh0aGlzLl9pc1ZpZXdhYmxlKHBhcmVudEZsYWdzKSkgewogICAgICAgIHRoaXMuc2V0RmxhZ3MocGFyZW50RmxhZ3MpOwogICAgICB9CiAgICB9CiAgICB0aGlzLnNldFRpdGxlKHBhcmVudEl0ZW0uZ2V0KCJUIikpOwogICAgdGhpcy5kYXRhLnRpdGxlT2JqID0gdGhpcy5fdGl0bGU7CiAgICB0aGlzLnNldENvbnRlbnRzKHBhcmVudEl0ZW0uZ2V0KCJDb250ZW50cyIpKTsKICAgIHRoaXMuZGF0YS5jb250ZW50c09iaiA9IHRoaXMuX2NvbnRlbnRzOwogICAgaWYgKHBhcmVudEl0ZW0uaGFzKCJSQyIpKSB7CiAgICAgIHRoaXMuZGF0YS5yaWNoVGV4dCA9IFhGQUZhY3RvcnkuZ2V0UmljaFRleHRBc0h0bWwocGFyZW50SXRlbS5nZXQoIlJDIikpOwogICAgfQogICAgdGhpcy5kYXRhLm9wZW4gPSAhIWRpY3QuZ2V0KCJPcGVuIik7CiAgfQogIHN0YXRpYyBjcmVhdGVOZXdEaWN0KGFubm90YXRpb24sIHhyZWYsIF9wYXJhbXMpIHsKICAgIGNvbnN0IHsKICAgICAgb2xkQW5ub3RhdGlvbiwKICAgICAgcmVjdCwKICAgICAgcGFyZW50CiAgICB9ID0gYW5ub3RhdGlvbjsKICAgIGNvbnN0IHBvcHVwID0gb2xkQW5ub3RhdGlvbiB8fCBuZXcgRGljdCh4cmVmKTsKICAgIHBvcHVwLnNldElmTm90RXhpc3RzKCJUeXBlIiwgTmFtZS5nZXQoIkFubm90IikpOwogICAgcG9wdXAuc2V0SWZOb3RFeGlzdHMoIlN1YnR5cGUiLCBOYW1lLmdldCgiUG9wdXAiKSk7CiAgICBwb3B1cC5zZXRJZk5vdEV4aXN0cygiT3BlbiIsIGZhbHNlKTsKICAgIHBvcHVwLnNldElmQXJyYXkoIlJlY3QiLCByZWN0KTsKICAgIHBvcHVwLnNldCgiUGFyZW50IiwgcGFyZW50KTsKICAgIHJldHVybiBwb3B1cDsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZU5ld0FwcGVhcmFuY2VTdHJlYW0oYW5ub3RhdGlvbiwgeHJlZiwgcGFyYW1zKSB7CiAgICByZXR1cm4gbnVsbDsKICB9Cn0KY2xhc3MgRnJlZVRleHRBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgdGhpcy5kYXRhLmhhc093bkNhbnZhcyA9IHRoaXMuZGF0YS5ub1JvdGF0ZTsKICAgIHRoaXMuZGF0YS5pc0VkaXRhYmxlID0gIXRoaXMuZGF0YS5ub0hUTUw7CiAgICB0aGlzLmRhdGEubm9IVE1MID0gZmFsc2U7CiAgICBjb25zdCB7CiAgICAgIGFubm90YXRpb25HbG9iYWxzLAogICAgICBldmFsdWF0b3JPcHRpb25zLAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuRlJFRVRFWFQ7CiAgICB0aGlzLnNldERlZmF1bHRBcHBlYXJhbmNlKHBhcmFtcyk7CiAgICB0aGlzLl9oYXNBcHBlYXJhbmNlID0gISF0aGlzLmFwcGVhcmFuY2U7CiAgICBpZiAodGhpcy5faGFzQXBwZWFyYW5jZSkgewogICAgICBjb25zdCB7CiAgICAgICAgZm9udENvbG9yLAogICAgICAgIGZvbnRTaXplCiAgICAgIH0gPSBwYXJzZUFwcGVhcmFuY2VTdHJlYW0odGhpcy5hcHBlYXJhbmNlLCBldmFsdWF0b3JPcHRpb25zLCB4cmVmLCBhbm5vdGF0aW9uR2xvYmFscy5nbG9iYWxDb2xvclNwYWNlQ2FjaGUpOwogICAgICB0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhLmZvbnRDb2xvciA9IGZvbnRDb2xvcjsKICAgICAgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YS5mb250U2l6ZSA9IGZvbnRTaXplIHx8IDEwOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YS5mb250U2l6ZSB8fD0gMTA7CiAgICAgIGNvbnN0IHsKICAgICAgICBmb250Q29sb3IsCiAgICAgICAgZm9udFNpemUKICAgICAgfSA9IHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGE7CiAgICAgIGlmICh0aGlzLl9jb250ZW50cy5zdHIpIHsKICAgICAgICB0aGlzLmRhdGEudGV4dENvbnRlbnQgPSB0aGlzLl9jb250ZW50cy5zdHIuc3BsaXQoL1xyXG4/fFxuLykubWFwKGxpbmUgPT4gbGluZS50cmltRW5kKCkpOwogICAgICAgIGNvbnN0IHsKICAgICAgICAgIGNvb3JkcywKICAgICAgICAgIGJib3gsCiAgICAgICAgICBtYXRyaXgKICAgICAgICB9ID0gRmFrZVVuaWNvZGVGb250LmdldEZpcnN0UG9zaXRpb25JbmZvKHRoaXMucmVjdGFuZ2xlLCB0aGlzLnJvdGF0aW9uLCBmb250U2l6ZSk7CiAgICAgICAgdGhpcy5kYXRhLnRleHRQb3NpdGlvbiA9IHRoaXMuX3RyYW5zZm9ybVBvaW50KGNvb3JkcywgYmJveCwgbWF0cml4KTsKICAgICAgfQogICAgICBpZiAodGhpcy5faXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpIHsKICAgICAgICBjb25zdCBzdHJva2VBbHBoYSA9IHBhcmFtcy5kaWN0LmdldCgiQ0EiKTsKICAgICAgICBjb25zdCBmYWtlVW5pY29kZUZvbnQgPSBuZXcgRmFrZVVuaWNvZGVGb250KHhyZWYsICJzYW5zLXNlcmlmIik7CiAgICAgICAgdGhpcy5hcHBlYXJhbmNlID0gZmFrZVVuaWNvZGVGb250LmNyZWF0ZUFwcGVhcmFuY2UodGhpcy5fY29udGVudHMuc3RyLCB0aGlzLnJlY3RhbmdsZSwgdGhpcy5yb3RhdGlvbiwgZm9udFNpemUsIGZvbnRDb2xvciwgc3Ryb2tlQWxwaGEpOwogICAgICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmFwcGVhcmFuY2UpOwogICAgICB9IGVsc2UgewogICAgICAgIHdhcm4oIkZyZWVUZXh0QW5ub3RhdGlvbjogT2Zmc2NyZWVuQ2FudmFzIGlzIG5vdCBzdXBwb3J0ZWQsIGFubm90YXRpb24gbWF5IG5vdCByZW5kZXIgY29ycmVjdGx5LiIpOwogICAgICB9CiAgICB9CiAgfQogIGdldCBoYXNUZXh0Q29udGVudCgpIHsKICAgIHJldHVybiB0aGlzLl9oYXNBcHBlYXJhbmNlOwogIH0KICBzdGF0aWMgY3JlYXRlTmV3RGljdChhbm5vdGF0aW9uLCB4cmVmLCB7CiAgICBhcFJlZiwKICAgIGFwCiAgfSkgewogICAgY29uc3QgewogICAgICBjb2xvciwKICAgICAgZGF0ZSwKICAgICAgZm9udFNpemUsCiAgICAgIG9sZEFubm90YXRpb24sCiAgICAgIHJlY3QsCiAgICAgIHJvdGF0aW9uLAogICAgICB1c2VyLAogICAgICB2YWx1ZQogICAgfSA9IGFubm90YXRpb247CiAgICBjb25zdCBmcmVldGV4dCA9IG9sZEFubm90YXRpb24gfHwgbmV3IERpY3QoeHJlZik7CiAgICBmcmVldGV4dC5zZXRJZk5vdEV4aXN0cygiVHlwZSIsIE5hbWUuZ2V0KCJBbm5vdCIpKTsKICAgIGZyZWV0ZXh0LnNldElmTm90RXhpc3RzKCJTdWJ0eXBlIiwgTmFtZS5nZXQoIkZyZWVUZXh0IikpOwogICAgZnJlZXRleHQuc2V0KG9sZEFubm90YXRpb24gPyAiTSIgOiAiQ3JlYXRpb25EYXRlIiwgYEQ6JHtnZXRNb2RpZmljYXRpb25EYXRlKGRhdGUpfWApOwogICAgaWYgKG9sZEFubm90YXRpb24pIHsKICAgICAgZnJlZXRleHQuZGVsZXRlKCJSQyIpOwogICAgfQogICAgZnJlZXRleHQuc2V0SWZBcnJheSgiUmVjdCIsIHJlY3QpOwogICAgY29uc3QgZGEgPSBgL0hlbHYgJHtmb250U2l6ZX0gVGYgJHtnZXRQZGZDb2xvcihjb2xvciwgdHJ1ZSl9YDsKICAgIGZyZWV0ZXh0LnNldCgiREEiLCBkYSk7CiAgICBmcmVldGV4dC5zZXRJZkRlZmluZWQoIkNvbnRlbnRzIiwgc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRSh2YWx1ZSkpOwogICAgZnJlZXRleHQuc2V0SWZOb3RFeGlzdHMoIkYiLCA0KTsKICAgIGZyZWV0ZXh0LnNldElmTm90RXhpc3RzKCJCb3JkZXIiLCBbMCwgMCwgMF0pOwogICAgZnJlZXRleHQuc2V0SWZOdW1iZXIoIlJvdGF0ZSIsIHJvdGF0aW9uKTsKICAgIGZyZWV0ZXh0LnNldElmRGVmaW5lZCgiVCIsIHN0cmluZ1RvQXNjaWlPclVURjE2QkUodXNlcikpOwogICAgaWYgKGFwUmVmIHx8IGFwKSB7CiAgICAgIGNvbnN0IG4gPSBuZXcgRGljdCh4cmVmKTsKICAgICAgZnJlZXRleHQuc2V0KCJBUCIsIG4pOwogICAgICBuLnNldCgiTiIsIGFwUmVmIHx8IGFwKTsKICAgIH0KICAgIHJldHVybiBmcmVldGV4dDsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZU5ld0FwcGVhcmFuY2VTdHJlYW0oYW5ub3RhdGlvbiwgeHJlZiwgcGFyYW1zKSB7CiAgICBjb25zdCB7CiAgICAgIGJhc2VGb250UmVmLAogICAgICBldmFsdWF0b3IsCiAgICAgIHRhc2sKICAgIH0gPSBwYXJhbXM7CiAgICBjb25zdCB7CiAgICAgIGNvbG9yLAogICAgICBmb250U2l6ZSwKICAgICAgcmVjdCwKICAgICAgcm90YXRpb24sCiAgICAgIHZhbHVlCiAgICB9ID0gYW5ub3RhdGlvbjsKICAgIGlmICghY29sb3IpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCByZXNvdXJjZXMgPSBuZXcgRGljdCh4cmVmKTsKICAgIGNvbnN0IGZvbnQgPSBuZXcgRGljdCh4cmVmKTsKICAgIGlmIChiYXNlRm9udFJlZikgewogICAgICBmb250LnNldCgiSGVsdiIsIGJhc2VGb250UmVmKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGJhc2VGb250ID0gbmV3IERpY3QoeHJlZik7CiAgICAgIGJhc2VGb250LnNldElmTmFtZSgiQmFzZUZvbnQiLCAiSGVsdmV0aWNhIik7CiAgICAgIGJhc2VGb250LnNldElmTmFtZSgiVHlwZSIsICJGb250Iik7CiAgICAgIGJhc2VGb250LnNldElmTmFtZSgiU3VidHlwZSIsICJUeXBlMSIpOwogICAgICBiYXNlRm9udC5zZXRJZk5hbWUoIkVuY29kaW5nIiwgIldpbkFuc2lFbmNvZGluZyIpOwogICAgICBmb250LnNldCgiSGVsdiIsIGJhc2VGb250KTsKICAgIH0KICAgIHJlc291cmNlcy5zZXQoIkZvbnQiLCBmb250KTsKICAgIGNvbnN0IGhlbHYgPSBhd2FpdCBXaWRnZXRBbm5vdGF0aW9uLl9nZXRGb250RGF0YShldmFsdWF0b3IsIHRhc2ssIHsKICAgICAgZm9udE5hbWU6ICJIZWx2IiwKICAgICAgZm9udFNpemUKICAgIH0sIHJlc291cmNlcyk7CiAgICBjb25zdCBbeDEsIHkxLCB4MiwgeTJdID0gcmVjdDsKICAgIGxldCB3ID0geDIgLSB4MTsKICAgIGxldCBoID0geTIgLSB5MTsKICAgIGlmIChyb3RhdGlvbiAlIDE4MCAhPT0gMCkgewogICAgICBbdywgaF0gPSBbaCwgd107CiAgICB9CiAgICBjb25zdCBsaW5lcyA9IHZhbHVlLnNwbGl0KCJcbiIpOwogICAgY29uc3Qgc2NhbGUgPSBmb250U2l6ZSAvIDEwMDA7CiAgICBsZXQgdG90YWxXaWR0aCA9IC1JbmZpbml0eTsKICAgIGNvbnN0IGVuY29kZWRMaW5lcyA9IFtdOwogICAgZm9yIChsZXQgbGluZSBvZiBsaW5lcykgewogICAgICBjb25zdCBlbmNvZGVkID0gaGVsdi5lbmNvZGVTdHJpbmcobGluZSk7CiAgICAgIGlmIChlbmNvZGVkLmxlbmd0aCA+IDEpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBsaW5lID0gZW5jb2RlZC5qb2luKCIiKTsKICAgICAgZW5jb2RlZExpbmVzLnB1c2gobGluZSk7CiAgICAgIGxldCBsaW5lV2lkdGggPSAwOwogICAgICBjb25zdCBnbHlwaHMgPSBoZWx2LmNoYXJzVG9HbHlwaHMobGluZSk7CiAgICAgIGZvciAoY29uc3QgZ2x5cGggb2YgZ2x5cGhzKSB7CiAgICAgICAgbGluZVdpZHRoICs9IGdseXBoLndpZHRoICogc2NhbGU7CiAgICAgIH0KICAgICAgdG90YWxXaWR0aCA9IE1hdGgubWF4KHRvdGFsV2lkdGgsIGxpbmVXaWR0aCk7CiAgICB9CiAgICBsZXQgaHNjYWxlID0gMTsKICAgIGlmICh0b3RhbFdpZHRoID4gdykgewogICAgICBoc2NhbGUgPSB3IC8gdG90YWxXaWR0aDsKICAgIH0KICAgIGxldCB2c2NhbGUgPSAxOwogICAgY29uc3QgbGluZUhlaWdodCA9IExJTkVfRkFDVE9SICogZm9udFNpemU7CiAgICBjb25zdCBsaW5lQXNjZW50ID0gKExJTkVfRkFDVE9SIC0gTElORV9ERVNDRU5UX0ZBQ1RPUikgKiBmb250U2l6ZTsKICAgIGNvbnN0IHRvdGFsSGVpZ2h0ID0gbGluZUhlaWdodCAqIGxpbmVzLmxlbmd0aDsKICAgIGlmICh0b3RhbEhlaWdodCA+IGgpIHsKICAgICAgdnNjYWxlID0gaCAvIHRvdGFsSGVpZ2h0OwogICAgfQogICAgY29uc3QgZnNjYWxlID0gTWF0aC5taW4oaHNjYWxlLCB2c2NhbGUpOwogICAgY29uc3QgbmV3Rm9udFNpemUgPSBmb250U2l6ZSAqIGZzY2FsZTsKICAgIGxldCBmaXJzdFBvaW50LCBjbGlwQm94LCBtYXRyaXg7CiAgICBzd2l0Y2ggKHJvdGF0aW9uKSB7CiAgICAgIGNhc2UgMDoKICAgICAgICBtYXRyaXggPSBbMSwgMCwgMCwgMV07CiAgICAgICAgY2xpcEJveCA9IFtyZWN0WzBdLCByZWN0WzFdLCB3LCBoXTsKICAgICAgICBmaXJzdFBvaW50ID0gW3JlY3RbMF0sIHJlY3RbM10gLSBsaW5lQXNjZW50XTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSA5MDoKICAgICAgICBtYXRyaXggPSBbMCwgMSwgLTEsIDBdOwogICAgICAgIGNsaXBCb3ggPSBbcmVjdFsxXSwgLXJlY3RbMl0sIHcsIGhdOwogICAgICAgIGZpcnN0UG9pbnQgPSBbcmVjdFsxXSwgLXJlY3RbMF0gLSBsaW5lQXNjZW50XTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAxODA6CiAgICAgICAgbWF0cml4ID0gWy0xLCAwLCAwLCAtMV07CiAgICAgICAgY2xpcEJveCA9IFstcmVjdFsyXSwgLXJlY3RbM10sIHcsIGhdOwogICAgICAgIGZpcnN0UG9pbnQgPSBbLXJlY3RbMl0sIC1yZWN0WzFdIC0gbGluZUFzY2VudF07CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMjcwOgogICAgICAgIG1hdHJpeCA9IFswLCAtMSwgMSwgMF07CiAgICAgICAgY2xpcEJveCA9IFstcmVjdFszXSwgcmVjdFswXSwgdywgaF07CiAgICAgICAgZmlyc3RQb2ludCA9IFstcmVjdFszXSwgcmVjdFsyXSAtIGxpbmVBc2NlbnRdOwogICAgICAgIGJyZWFrOwogICAgfQogICAgY29uc3QgYnVmZmVyID0gWyJxIiwgYCR7bWF0cml4LmpvaW4oIiAiKX0gMCAwIGNtYCwgYCR7Y2xpcEJveC5qb2luKCIgIil9IHJlIFcgbmAsIGBCVGAsIGAke2dldFBkZkNvbG9yKGNvbG9yLCB0cnVlKX1gLCBgMCBUYyAvSGVsdiAke251bWJlclRvU3RyaW5nKG5ld0ZvbnRTaXplKX0gVGZgXTsKICAgIGJ1ZmZlci5wdXNoKGAke2ZpcnN0UG9pbnQuam9pbigiICIpfSBUZCAoJHtlc2NhcGVTdHJpbmcoZW5jb2RlZExpbmVzWzBdKX0pIFRqYCk7CiAgICBjb25zdCB2U2hpZnQgPSBudW1iZXJUb1N0cmluZyhsaW5lSGVpZ2h0KTsKICAgIGZvciAobGV0IGkgPSAxLCBpaSA9IGVuY29kZWRMaW5lcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IGxpbmUgPSBlbmNvZGVkTGluZXNbaV07CiAgICAgIGJ1ZmZlci5wdXNoKGAwIC0ke3ZTaGlmdH0gVGQgKCR7ZXNjYXBlU3RyaW5nKGxpbmUpfSkgVGpgKTsKICAgIH0KICAgIGJ1ZmZlci5wdXNoKCJFVCIsICJRIik7CiAgICBjb25zdCBhcHBlYXJhbmNlID0gYnVmZmVyLmpvaW4oIlxuIik7CiAgICBjb25zdCBhcHBlYXJhbmNlU3RyZWFtRGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJGb3JtVHlwZSIsIDEpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIkZvcm0iKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldElmTmFtZSgiVHlwZSIsICJYT2JqZWN0Iik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkJCb3giLCByZWN0KTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiUmVzb3VyY2VzIiwgcmVzb3VyY2VzKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiTWF0cml4IiwgWzEsIDAsIDAsIDEsIC1yZWN0WzBdLCAtcmVjdFsxXV0pOwogICAgY29uc3QgYXAgPSBuZXcgU3RyaW5nU3RyZWFtKGFwcGVhcmFuY2UpOwogICAgYXAuZGljdCA9IGFwcGVhcmFuY2VTdHJlYW1EaWN0OwogICAgcmV0dXJuIGFwOwogIH0KfQpjbGFzcyBMaW5lQW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLkxJTkU7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogICAgdGhpcy5kYXRhLm5vSFRNTCA9IGZhbHNlOwogICAgY29uc3QgbGluZUNvb3JkaW5hdGVzID0gbG9va3VwUmVjdChkaWN0LmdldEFycmF5KCJMIiksIFswLCAwLCAwLCAwXSk7CiAgICB0aGlzLmRhdGEubGluZUNvb3JkaW5hdGVzID0gVXRpbC5ub3JtYWxpemVSZWN0KGxpbmVDb29yZGluYXRlcyk7CiAgICB0aGlzLnNldExpbmVFbmRpbmdzKGRpY3QuZ2V0QXJyYXkoIkxFIikpOwogICAgdGhpcy5kYXRhLmxpbmVFbmRpbmdzID0gdGhpcy5saW5lRW5kaW5nczsKICAgIGlmICghdGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgIGNvbnN0IHN0cm9rZUNvbG9yID0gZ2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yLCBbMCwgMCwgMF0pOwogICAgICBjb25zdCBzdHJva2VBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICBjb25zdCBpbnRlcmlvckNvbG9yID0gZ2V0UmdiQ29sb3IoZGljdC5nZXRBcnJheSgiSUMiKSwgbnVsbCk7CiAgICAgIGNvbnN0IGZpbGxDb2xvciA9IGdldFBkZkNvbG9yQXJyYXkoaW50ZXJpb3JDb2xvcik7CiAgICAgIGNvbnN0IGZpbGxBbHBoYSA9IGZpbGxDb2xvciA/IHN0cm9rZUFscGhhIDogbnVsbDsKICAgICAgY29uc3QgYm9yZGVyV2lkdGggPSB0aGlzLmJvcmRlclN0eWxlLndpZHRoIHx8IDEsCiAgICAgICAgYm9yZGVyQWRqdXN0ID0gMiAqIGJvcmRlcldpZHRoOwogICAgICBjb25zdCBiYm94ID0gW3RoaXMuZGF0YS5saW5lQ29vcmRpbmF0ZXNbMF0gLSBib3JkZXJBZGp1c3QsIHRoaXMuZGF0YS5saW5lQ29vcmRpbmF0ZXNbMV0gLSBib3JkZXJBZGp1c3QsIHRoaXMuZGF0YS5saW5lQ29vcmRpbmF0ZXNbMl0gKyBib3JkZXJBZGp1c3QsIHRoaXMuZGF0YS5saW5lQ29vcmRpbmF0ZXNbM10gKyBib3JkZXJBZGp1c3RdOwogICAgICBpZiAoIVV0aWwuaW50ZXJzZWN0KHRoaXMucmVjdGFuZ2xlLCBiYm94KSkgewogICAgICAgIHRoaXMucmVjdGFuZ2xlID0gYmJveDsKICAgICAgfQogICAgICB0aGlzLl9zZXREZWZhdWx0QXBwZWFyYW5jZSh7CiAgICAgICAgeHJlZiwKICAgICAgICBleHRyYTogYCR7Ym9yZGVyV2lkdGh9IHdgLAogICAgICAgIHN0cm9rZUNvbG9yLAogICAgICAgIGZpbGxDb2xvciwKICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICBmaWxsQWxwaGEsCiAgICAgICAgcG9pbnRzQ2FsbGJhY2s6IChidWZmZXIsIHBvaW50cykgPT4gewogICAgICAgICAgYnVmZmVyLnB1c2goYCR7bGluZUNvb3JkaW5hdGVzWzBdfSAke2xpbmVDb29yZGluYXRlc1sxXX0gbWAsIGAke2xpbmVDb29yZGluYXRlc1syXX0gJHtsaW5lQ29vcmRpbmF0ZXNbM119IGxgLCAiUyIpOwogICAgICAgICAgcmV0dXJuIFtwb2ludHNbMF0gLSBib3JkZXJXaWR0aCwgcG9pbnRzWzddIC0gYm9yZGVyV2lkdGgsIHBvaW50c1syXSArIGJvcmRlcldpZHRoLCBwb2ludHNbM10gKyBib3JkZXJXaWR0aF07CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICB9Cn0KY2xhc3MgU3F1YXJlQW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLlNRVUFSRTsKICAgIHRoaXMuZGF0YS5oYXNPd25DYW52YXMgPSB0aGlzLmRhdGEubm9Sb3RhdGU7CiAgICB0aGlzLmRhdGEubm9IVE1MID0gZmFsc2U7CiAgICBpZiAoIXRoaXMuYXBwZWFyYW5jZSkgewogICAgICBjb25zdCBzdHJva2VDb2xvciA9IGdldFBkZkNvbG9yQXJyYXkodGhpcy5jb2xvciwgWzAsIDAsIDBdKTsKICAgICAgY29uc3Qgc3Ryb2tlQWxwaGEgPSBkaWN0LmdldCgiQ0EiKTsKICAgICAgY29uc3QgaW50ZXJpb3JDb2xvciA9IGdldFJnYkNvbG9yKGRpY3QuZ2V0QXJyYXkoIklDIiksIG51bGwpOwogICAgICBjb25zdCBmaWxsQ29sb3IgPSBnZXRQZGZDb2xvckFycmF5KGludGVyaW9yQ29sb3IpOwogICAgICBjb25zdCBmaWxsQWxwaGEgPSBmaWxsQ29sb3IgPyBzdHJva2VBbHBoYSA6IG51bGw7CiAgICAgIGlmICh0aGlzLmJvcmRlclN0eWxlLndpZHRoID09PSAwICYmICFmaWxsQ29sb3IpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2UoewogICAgICAgIHhyZWYsCiAgICAgICAgZXh0cmE6IGAke3RoaXMuYm9yZGVyU3R5bGUud2lkdGh9IHdgLAogICAgICAgIHN0cm9rZUNvbG9yLAogICAgICAgIGZpbGxDb2xvciwKICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICBmaWxsQWxwaGEsCiAgICAgICAgcG9pbnRzQ2FsbGJhY2s6IChidWZmZXIsIHBvaW50cykgPT4gewogICAgICAgICAgY29uc3QgeCA9IHBvaW50c1s0XSArIHRoaXMuYm9yZGVyU3R5bGUud2lkdGggLyAyOwogICAgICAgICAgY29uc3QgeSA9IHBvaW50c1s1XSArIHRoaXMuYm9yZGVyU3R5bGUud2lkdGggLyAyOwogICAgICAgICAgY29uc3Qgd2lkdGggPSBwb2ludHNbNl0gLSBwb2ludHNbNF0gLSB0aGlzLmJvcmRlclN0eWxlLndpZHRoOwogICAgICAgICAgY29uc3QgaGVpZ2h0ID0gcG9pbnRzWzNdIC0gcG9pbnRzWzddIC0gdGhpcy5ib3JkZXJTdHlsZS53aWR0aDsKICAgICAgICAgIGJ1ZmZlci5wdXNoKGAke3h9ICR7eX0gJHt3aWR0aH0gJHtoZWlnaHR9IHJlYCk7CiAgICAgICAgICBpZiAoZmlsbENvbG9yKSB7CiAgICAgICAgICAgIGJ1ZmZlci5wdXNoKCJCIik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBidWZmZXIucHVzaCgiUyIpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIFtwb2ludHNbMF0sIHBvaW50c1s3XSwgcG9pbnRzWzJdLCBwb2ludHNbM11dOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CiAgfQp9CmNsYXNzIENpcmNsZUFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIHhyZWYKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBBbm5vdGF0aW9uVHlwZS5DSVJDTEU7CiAgICBpZiAoIXRoaXMuYXBwZWFyYW5jZSkgewogICAgICBjb25zdCBzdHJva2VDb2xvciA9IGdldFBkZkNvbG9yQXJyYXkodGhpcy5jb2xvciwgWzAsIDAsIDBdKTsKICAgICAgY29uc3Qgc3Ryb2tlQWxwaGEgPSBkaWN0LmdldCgiQ0EiKTsKICAgICAgY29uc3QgaW50ZXJpb3JDb2xvciA9IGdldFJnYkNvbG9yKGRpY3QuZ2V0QXJyYXkoIklDIiksIG51bGwpOwogICAgICBjb25zdCBmaWxsQ29sb3IgPSBnZXRQZGZDb2xvckFycmF5KGludGVyaW9yQ29sb3IpOwogICAgICBjb25zdCBmaWxsQWxwaGEgPSBmaWxsQ29sb3IgPyBzdHJva2VBbHBoYSA6IG51bGw7CiAgICAgIGlmICh0aGlzLmJvcmRlclN0eWxlLndpZHRoID09PSAwICYmICFmaWxsQ29sb3IpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29uc3QgY29udHJvbFBvaW50c0Rpc3RhbmNlID0gNCAvIDMgKiBNYXRoLnRhbihNYXRoLlBJIC8gKDIgKiA0KSk7CiAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICB4cmVmLAogICAgICAgIGV4dHJhOiBgJHt0aGlzLmJvcmRlclN0eWxlLndpZHRofSB3YCwKICAgICAgICBzdHJva2VDb2xvciwKICAgICAgICBmaWxsQ29sb3IsCiAgICAgICAgc3Ryb2tlQWxwaGEsCiAgICAgICAgZmlsbEFscGhhLAogICAgICAgIHBvaW50c0NhbGxiYWNrOiAoYnVmZmVyLCBwb2ludHMpID0+IHsKICAgICAgICAgIGNvbnN0IHgwID0gcG9pbnRzWzBdICsgdGhpcy5ib3JkZXJTdHlsZS53aWR0aCAvIDI7CiAgICAgICAgICBjb25zdCB5MCA9IHBvaW50c1sxXSAtIHRoaXMuYm9yZGVyU3R5bGUud2lkdGggLyAyOwogICAgICAgICAgY29uc3QgeDEgPSBwb2ludHNbNl0gLSB0aGlzLmJvcmRlclN0eWxlLndpZHRoIC8gMjsKICAgICAgICAgIGNvbnN0IHkxID0gcG9pbnRzWzddICsgdGhpcy5ib3JkZXJTdHlsZS53aWR0aCAvIDI7CiAgICAgICAgICBjb25zdCB4TWlkID0geDAgKyAoeDEgLSB4MCkgLyAyOwogICAgICAgICAgY29uc3QgeU1pZCA9IHkwICsgKHkxIC0geTApIC8gMjsKICAgICAgICAgIGNvbnN0IHhPZmZzZXQgPSAoeDEgLSB4MCkgLyAyICogY29udHJvbFBvaW50c0Rpc3RhbmNlOwogICAgICAgICAgY29uc3QgeU9mZnNldCA9ICh5MSAtIHkwKSAvIDIgKiBjb250cm9sUG9pbnRzRGlzdGFuY2U7CiAgICAgICAgICBidWZmZXIucHVzaChgJHt4TWlkfSAke3kxfSBtYCwgYCR7eE1pZCArIHhPZmZzZXR9ICR7eTF9ICR7eDF9ICR7eU1pZCArIHlPZmZzZXR9ICR7eDF9ICR7eU1pZH0gY2AsIGAke3gxfSAke3lNaWQgLSB5T2Zmc2V0fSAke3hNaWQgKyB4T2Zmc2V0fSAke3kwfSAke3hNaWR9ICR7eTB9IGNgLCBgJHt4TWlkIC0geE9mZnNldH0gJHt5MH0gJHt4MH0gJHt5TWlkIC0geU9mZnNldH0gJHt4MH0gJHt5TWlkfSBjYCwgYCR7eDB9ICR7eU1pZCArIHlPZmZzZXR9ICR7eE1pZCAtIHhPZmZzZXR9ICR7eTF9ICR7eE1pZH0gJHt5MX0gY2AsICJoIik7CiAgICAgICAgICBpZiAoZmlsbENvbG9yKSB7CiAgICAgICAgICAgIGJ1ZmZlci5wdXNoKCJCIik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBidWZmZXIucHVzaCgiUyIpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIFtwb2ludHNbMF0sIHBvaW50c1s3XSwgcG9pbnRzWzJdLCBwb2ludHNbM11dOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CiAgfQp9CmNsYXNzIFBvbHlsaW5lQW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLlBPTFlMSU5FOwogICAgdGhpcy5kYXRhLmhhc093bkNhbnZhcyA9IHRoaXMuZGF0YS5ub1JvdGF0ZTsKICAgIHRoaXMuZGF0YS5ub0hUTUwgPSBmYWxzZTsKICAgIHRoaXMuZGF0YS52ZXJ0aWNlcyA9IG51bGw7CiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUG9seWdvbkFubm90YXRpb24pKSB7CiAgICAgIHRoaXMuc2V0TGluZUVuZGluZ3MoZGljdC5nZXRBcnJheSgiTEUiKSk7CiAgICAgIHRoaXMuZGF0YS5saW5lRW5kaW5ncyA9IHRoaXMubGluZUVuZGluZ3M7CiAgICB9CiAgICBjb25zdCByYXdWZXJ0aWNlcyA9IGRpY3QuZ2V0QXJyYXkoIlZlcnRpY2VzIik7CiAgICBpZiAoIWlzTnVtYmVyQXJyYXkocmF3VmVydGljZXMsIG51bGwpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHZlcnRpY2VzID0gdGhpcy5kYXRhLnZlcnRpY2VzID0gRmxvYXQzMkFycmF5LmZyb20ocmF3VmVydGljZXMpOwogICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgY29uc3Qgc3Ryb2tlQ29sb3IgPSBnZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IsIFswLCAwLCAwXSk7CiAgICAgIGNvbnN0IHN0cm9rZUFscGhhID0gZGljdC5nZXQoIkNBIik7CiAgICAgIGxldCBmaWxsQ29sb3IgPSBnZXRSZ2JDb2xvcihkaWN0LmdldEFycmF5KCJJQyIpLCBudWxsKTsKICAgICAgaWYgKGZpbGxDb2xvcikgewogICAgICAgIGZpbGxDb2xvciA9IGdldFBkZkNvbG9yQXJyYXkoZmlsbENvbG9yKTsKICAgICAgfQogICAgICBsZXQgb3BlcmF0b3I7CiAgICAgIGlmIChmaWxsQ29sb3IpIHsKICAgICAgICBpZiAodGhpcy5jb2xvcikgewogICAgICAgICAgb3BlcmF0b3IgPSBmaWxsQ29sb3IuZXZlcnkoKGMsIGkpID0+IGMgPT09IHN0cm9rZUNvbG9yW2ldKSA/ICJmIiA6ICJCIjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb3BlcmF0b3IgPSAiZiI7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIG9wZXJhdG9yID0gIlMiOwogICAgICB9CiAgICAgIGNvbnN0IGJvcmRlcldpZHRoID0gdGhpcy5ib3JkZXJTdHlsZS53aWR0aCB8fCAxLAogICAgICAgIGJvcmRlckFkanVzdCA9IDIgKiBib3JkZXJXaWR0aDsKICAgICAgY29uc3QgYmJveCA9IFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XTsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdmVydGljZXMubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgIFV0aWwucmVjdEJvdW5kaW5nQm94KHZlcnRpY2VzW2ldIC0gYm9yZGVyQWRqdXN0LCB2ZXJ0aWNlc1tpICsgMV0gLSBib3JkZXJBZGp1c3QsIHZlcnRpY2VzW2ldICsgYm9yZGVyQWRqdXN0LCB2ZXJ0aWNlc1tpICsgMV0gKyBib3JkZXJBZGp1c3QsIGJib3gpOwogICAgICB9CiAgICAgIGlmICghVXRpbC5pbnRlcnNlY3QodGhpcy5yZWN0YW5nbGUsIGJib3gpKSB7CiAgICAgICAgdGhpcy5yZWN0YW5nbGUgPSBiYm94OwogICAgICB9CiAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICB4cmVmLAogICAgICAgIGV4dHJhOiBgJHtib3JkZXJXaWR0aH0gd2AsCiAgICAgICAgc3Ryb2tlQ29sb3IsCiAgICAgICAgc3Ryb2tlQWxwaGEsCiAgICAgICAgZmlsbENvbG9yLAogICAgICAgIGZpbGxBbHBoYTogZmlsbENvbG9yID8gc3Ryb2tlQWxwaGEgOiBudWxsLAogICAgICAgIHBvaW50c0NhbGxiYWNrOiAoYnVmZmVyLCBwb2ludHMpID0+IHsKICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHZlcnRpY2VzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgICAgICAgYnVmZmVyLnB1c2goYCR7dmVydGljZXNbaV19ICR7dmVydGljZXNbaSArIDFdfSAke2kgPT09IDAgPyAibSIgOiAibCJ9YCk7CiAgICAgICAgICB9CiAgICAgICAgICBidWZmZXIucHVzaChvcGVyYXRvcik7CiAgICAgICAgICByZXR1cm4gW3BvaW50c1swXSwgcG9pbnRzWzddLCBwb2ludHNbMl0sIHBvaW50c1szXV07CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICB9Cn0KY2xhc3MgUG9seWdvbkFubm90YXRpb24gZXh0ZW5kcyBQb2x5bGluZUFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLlBPTFlHT047CiAgfQp9CmNsYXNzIENhcmV0QW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLkNBUkVUOwogIH0KfQpjbGFzcyBJbmtBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgdGhpcy5kYXRhLmhhc093bkNhbnZhcyA9IHRoaXMuZGF0YS5ub1JvdGF0ZTsKICAgIHRoaXMuZGF0YS5ub0hUTUwgPSBmYWxzZTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLklOSzsKICAgIHRoaXMuZGF0YS5pbmtMaXN0cyA9IFtdOwogICAgdGhpcy5kYXRhLmlzRWRpdGFibGUgPSAhdGhpcy5kYXRhLm5vSFRNTDsKICAgIHRoaXMuZGF0YS5ub0hUTUwgPSBmYWxzZTsKICAgIHRoaXMuZGF0YS5vcGFjaXR5ID0gZGljdC5nZXQoIkNBIikgfHwgMTsKICAgIGNvbnN0IHJhd0lua0xpc3RzID0gZGljdC5nZXRBcnJheSgiSW5rTGlzdCIpOwogICAgaWYgKCFBcnJheS5pc0FycmF5KHJhd0lua0xpc3RzKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSByYXdJbmtMaXN0cy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICAgIGlmICghQXJyYXkuaXNBcnJheShyYXdJbmtMaXN0c1tpXSkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBpbmtMaXN0ID0gbmV3IEZsb2F0MzJBcnJheShyYXdJbmtMaXN0c1tpXS5sZW5ndGgpOwogICAgICB0aGlzLmRhdGEuaW5rTGlzdHMucHVzaChpbmtMaXN0KTsKICAgICAgZm9yIChsZXQgaiA9IDAsIGpqID0gcmF3SW5rTGlzdHNbaV0ubGVuZ3RoOyBqIDwgamo7IGogKz0gMikgewogICAgICAgIGNvbnN0IHggPSB4cmVmLmZldGNoSWZSZWYocmF3SW5rTGlzdHNbaV1bal0pLAogICAgICAgICAgeSA9IHhyZWYuZmV0Y2hJZlJlZihyYXdJbmtMaXN0c1tpXVtqICsgMV0pOwogICAgICAgIGlmICh0eXBlb2YgeCA9PT0gIm51bWJlciIgJiYgdHlwZW9mIHkgPT09ICJudW1iZXIiKSB7CiAgICAgICAgICBpbmtMaXN0W2pdID0geDsKICAgICAgICAgIGlua0xpc3RbaiArIDFdID0geTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmICghdGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgIGNvbnN0IHN0cm9rZUNvbG9yID0gZ2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yLCBbMCwgMCwgMF0pOwogICAgICBjb25zdCBzdHJva2VBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICBjb25zdCBib3JkZXJXaWR0aCA9IHRoaXMuYm9yZGVyU3R5bGUud2lkdGggfHwgMSwKICAgICAgICBib3JkZXJBZGp1c3QgPSAyICogYm9yZGVyV2lkdGg7CiAgICAgIGNvbnN0IGJib3ggPSBbSW5maW5pdHksIEluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV07CiAgICAgIGZvciAoY29uc3QgaW5rTGlzdCBvZiB0aGlzLmRhdGEuaW5rTGlzdHMpIHsKICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBpbmtMaXN0Lmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgICAgIFV0aWwucmVjdEJvdW5kaW5nQm94KGlua0xpc3RbaV0gLSBib3JkZXJBZGp1c3QsIGlua0xpc3RbaSArIDFdIC0gYm9yZGVyQWRqdXN0LCBpbmtMaXN0W2ldICsgYm9yZGVyQWRqdXN0LCBpbmtMaXN0W2kgKyAxXSArIGJvcmRlckFkanVzdCwgYmJveCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICghVXRpbC5pbnRlcnNlY3QodGhpcy5yZWN0YW5nbGUsIGJib3gpKSB7CiAgICAgICAgdGhpcy5yZWN0YW5nbGUgPSBiYm94OwogICAgICB9CiAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICB4cmVmLAogICAgICAgIGV4dHJhOiBgJHtib3JkZXJXaWR0aH0gd2AsCiAgICAgICAgc3Ryb2tlQ29sb3IsCiAgICAgICAgc3Ryb2tlQWxwaGEsCiAgICAgICAgcG9pbnRzQ2FsbGJhY2s6IChidWZmZXIsIHBvaW50cykgPT4gewogICAgICAgICAgZm9yIChjb25zdCBpbmtMaXN0IG9mIHRoaXMuZGF0YS5pbmtMaXN0cykgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBpbmtMaXN0Lmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgICAgICAgICBidWZmZXIucHVzaChgJHtpbmtMaXN0W2ldfSAke2lua0xpc3RbaSArIDFdfSAke2kgPT09IDAgPyAibSIgOiAibCJ9YCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnVmZmVyLnB1c2goIlMiKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBbcG9pbnRzWzBdLCBwb2ludHNbN10sIHBvaW50c1syXSwgcG9pbnRzWzNdXTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogIH0KICBzdGF0aWMgY3JlYXRlTmV3RGljdChhbm5vdGF0aW9uLCB4cmVmLCB7CiAgICBhcFJlZiwKICAgIGFwCiAgfSkgewogICAgY29uc3QgewogICAgICBvbGRBbm5vdGF0aW9uLAogICAgICBjb2xvciwKICAgICAgZGF0ZSwKICAgICAgb3BhY2l0eSwKICAgICAgcGF0aHMsCiAgICAgIG91dGxpbmVzLAogICAgICByZWN0LAogICAgICByb3RhdGlvbiwKICAgICAgdGhpY2tuZXNzLAogICAgICB1c2VyCiAgICB9ID0gYW5ub3RhdGlvbjsKICAgIGNvbnN0IGluayA9IG9sZEFubm90YXRpb24gfHwgbmV3IERpY3QoeHJlZik7CiAgICBpbmsuc2V0SWZOb3RFeGlzdHMoIlR5cGUiLCBOYW1lLmdldCgiQW5ub3QiKSk7CiAgICBpbmsuc2V0SWZOb3RFeGlzdHMoIlN1YnR5cGUiLCBOYW1lLmdldCgiSW5rIikpOwogICAgaW5rLnNldChvbGRBbm5vdGF0aW9uID8gIk0iIDogIkNyZWF0aW9uRGF0ZSIsIGBEOiR7Z2V0TW9kaWZpY2F0aW9uRGF0ZShkYXRlKX1gKTsKICAgIGluay5zZXRJZkFycmF5KCJSZWN0IiwgcmVjdCk7CiAgICBpbmsuc2V0SWZBcnJheSgiSW5rTGlzdCIsIG91dGxpbmVzPy5wb2ludHMgfHwgcGF0aHM/LnBvaW50cyk7CiAgICBpbmsuc2V0SWZOb3RFeGlzdHMoIkYiLCA0KTsKICAgIGluay5zZXRJZk51bWJlcigiUm90YXRlIiwgcm90YXRpb24pOwogICAgaW5rLnNldElmRGVmaW5lZCgiVCIsIHN0cmluZ1RvQXNjaWlPclVURjE2QkUodXNlcikpOwogICAgaWYgKG91dGxpbmVzKSB7CiAgICAgIGluay5zZXRJZk5hbWUoIklUIiwgIklua0hpZ2hsaWdodCIpOwogICAgfQogICAgaWYgKHRoaWNrbmVzcyA+IDApIHsKICAgICAgY29uc3QgYnMgPSBuZXcgRGljdCh4cmVmKTsKICAgICAgaW5rLnNldCgiQlMiLCBicyk7CiAgICAgIGJzLnNldCgiVyIsIHRoaWNrbmVzcyk7CiAgICB9CiAgICBpbmsuc2V0SWZBcnJheSgiQyIsIGdldFBkZkNvbG9yQXJyYXkoY29sb3IpKTsKICAgIGluay5zZXRJZk51bWJlcigiQ0EiLCBvcGFjaXR5KTsKICAgIGlmIChhcCB8fCBhcFJlZikgewogICAgICBjb25zdCBuID0gbmV3IERpY3QoeHJlZik7CiAgICAgIGluay5zZXQoIkFQIiwgbik7CiAgICAgIG4uc2V0KCJOIiwgYXBSZWYgfHwgYXApOwogICAgfQogICAgcmV0dXJuIGluazsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZU5ld0FwcGVhcmFuY2VTdHJlYW0oYW5ub3RhdGlvbiwgeHJlZiwgcGFyYW1zKSB7CiAgICBpZiAoYW5ub3RhdGlvbi5vdXRsaW5lcykgewogICAgICByZXR1cm4gdGhpcy5jcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtRm9ySGlnaGxpZ2h0KGFubm90YXRpb24sIHhyZWYsIHBhcmFtcyk7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIGNvbG9yLAogICAgICByZWN0LAogICAgICBwYXRocywKICAgICAgdGhpY2tuZXNzLAogICAgICBvcGFjaXR5CiAgICB9ID0gYW5ub3RhdGlvbjsKICAgIGlmICghY29sb3IpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBhcHBlYXJhbmNlQnVmZmVyID0gW2Ake3RoaWNrbmVzc30gdyAxIEogMSBqYCwgYCR7Z2V0UGRmQ29sb3IoY29sb3IsIGZhbHNlKX1gXTsKICAgIGlmIChvcGFjaXR5ICE9PSAxKSB7CiAgICAgIGFwcGVhcmFuY2VCdWZmZXIucHVzaCgiL1IwIGdzIik7CiAgICB9CiAgICBmb3IgKGNvbnN0IG91dGxpbmUgb2YgcGF0aHMubGluZXMpIHsKICAgICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKGAke251bWJlclRvU3RyaW5nKG91dGxpbmVbNF0pfSAke251bWJlclRvU3RyaW5nKG91dGxpbmVbNV0pfSBtYCk7CiAgICAgIGZvciAobGV0IGkgPSA2LCBpaSA9IG91dGxpbmUubGVuZ3RoOyBpIDwgaWk7IGkgKz0gNikgewogICAgICAgIGlmIChpc05hTihvdXRsaW5lW2ldKSkgewogICAgICAgICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKGAke251bWJlclRvU3RyaW5nKG91dGxpbmVbaSArIDRdKX0gJHtudW1iZXJUb1N0cmluZyhvdXRsaW5lW2kgKyA1XSl9IGxgKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgW2MxeCwgYzF5LCBjMngsIGMyeSwgeCwgeV0gPSBvdXRsaW5lLnNsaWNlKGksIGkgKyA2KTsKICAgICAgICAgIGFwcGVhcmFuY2VCdWZmZXIucHVzaChbYzF4LCBjMXksIGMyeCwgYzJ5LCB4LCB5XS5tYXAobnVtYmVyVG9TdHJpbmcpLmpvaW4oIiAiKSArICIgYyIpOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAob3V0bGluZS5sZW5ndGggPT09IDYpIHsKICAgICAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goYCR7bnVtYmVyVG9TdHJpbmcob3V0bGluZVs0XSl9ICR7bnVtYmVyVG9TdHJpbmcob3V0bGluZVs1XSl9IGxgKTsKICAgICAgfQogICAgfQogICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKCJTIik7CiAgICBjb25zdCBhcHBlYXJhbmNlID0gYXBwZWFyYW5jZUJ1ZmZlci5qb2luKCJcbiIpOwogICAgY29uc3QgYXBwZWFyYW5jZVN0cmVhbURpY3QgPSBuZXcgRGljdCh4cmVmKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiRm9ybVR5cGUiLCAxKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldElmTmFtZSgiU3VidHlwZSIsICJGb3JtIik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXRJZk5hbWUoIlR5cGUiLCAiWE9iamVjdCIpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJCQm94IiwgcmVjdCk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkxlbmd0aCIsIGFwcGVhcmFuY2UubGVuZ3RoKTsKICAgIGlmIChvcGFjaXR5ICE9PSAxKSB7CiAgICAgIGNvbnN0IHJlc291cmNlcyA9IG5ldyBEaWN0KHhyZWYpOwogICAgICBjb25zdCBleHRHU3RhdGUgPSBuZXcgRGljdCh4cmVmKTsKICAgICAgY29uc3QgcjAgPSBuZXcgRGljdCh4cmVmKTsKICAgICAgcjAuc2V0KCJDQSIsIG9wYWNpdHkpOwogICAgICByMC5zZXRJZk5hbWUoIlR5cGUiLCAiRXh0R1N0YXRlIik7CiAgICAgIGV4dEdTdGF0ZS5zZXQoIlIwIiwgcjApOwogICAgICByZXNvdXJjZXMuc2V0KCJFeHRHU3RhdGUiLCBleHRHU3RhdGUpOwogICAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlJlc291cmNlcyIsIHJlc291cmNlcyk7CiAgICB9CiAgICBjb25zdCBhcCA9IG5ldyBTdHJpbmdTdHJlYW0oYXBwZWFyYW5jZSk7CiAgICBhcC5kaWN0ID0gYXBwZWFyYW5jZVN0cmVhbURpY3Q7CiAgICByZXR1cm4gYXA7CiAgfQogIHN0YXRpYyBhc3luYyBjcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtRm9ySGlnaGxpZ2h0KGFubm90YXRpb24sIHhyZWYsIHBhcmFtcykgewogICAgY29uc3QgewogICAgICBjb2xvciwKICAgICAgcmVjdCwKICAgICAgb3V0bGluZXM6IHsKICAgICAgICBvdXRsaW5lCiAgICAgIH0sCiAgICAgIG9wYWNpdHkKICAgIH0gPSBhbm5vdGF0aW9uOwogICAgaWYgKCFjb2xvcikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGFwcGVhcmFuY2VCdWZmZXIgPSBbYCR7Z2V0UGRmQ29sb3IoY29sb3IsIHRydWUpfWAsICIvUjAgZ3MiXTsKICAgIGFwcGVhcmFuY2VCdWZmZXIucHVzaChgJHtudW1iZXJUb1N0cmluZyhvdXRsaW5lWzRdKX0gJHtudW1iZXJUb1N0cmluZyhvdXRsaW5lWzVdKX0gbWApOwogICAgZm9yIChsZXQgaSA9IDYsIGlpID0gb3V0bGluZS5sZW5ndGg7IGkgPCBpaTsgaSArPSA2KSB7CiAgICAgIGlmIChpc05hTihvdXRsaW5lW2ldKSkgewogICAgICAgIGFwcGVhcmFuY2VCdWZmZXIucHVzaChgJHtudW1iZXJUb1N0cmluZyhvdXRsaW5lW2kgKyA0XSl9ICR7bnVtYmVyVG9TdHJpbmcob3V0bGluZVtpICsgNV0pfSBsYCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgW2MxeCwgYzF5LCBjMngsIGMyeSwgeCwgeV0gPSBvdXRsaW5lLnNsaWNlKGksIGkgKyA2KTsKICAgICAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goW2MxeCwgYzF5LCBjMngsIGMyeSwgeCwgeV0ubWFwKG51bWJlclRvU3RyaW5nKS5qb2luKCIgIikgKyAiIGMiKTsKICAgICAgfQogICAgfQogICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKCJoIGYiKTsKICAgIGNvbnN0IGFwcGVhcmFuY2UgPSBhcHBlYXJhbmNlQnVmZmVyLmpvaW4oIlxuIik7CiAgICBjb25zdCBhcHBlYXJhbmNlU3RyZWFtRGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJGb3JtVHlwZSIsIDEpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIkZvcm0iKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldElmTmFtZSgiVHlwZSIsICJYT2JqZWN0Iik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkJCb3giLCByZWN0KTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiTGVuZ3RoIiwgYXBwZWFyYW5jZS5sZW5ndGgpOwogICAgY29uc3QgcmVzb3VyY2VzID0gbmV3IERpY3QoeHJlZik7CiAgICBjb25zdCBleHRHU3RhdGUgPSBuZXcgRGljdCh4cmVmKTsKICAgIHJlc291cmNlcy5zZXQoIkV4dEdTdGF0ZSIsIGV4dEdTdGF0ZSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlJlc291cmNlcyIsIHJlc291cmNlcyk7CiAgICBjb25zdCByMCA9IG5ldyBEaWN0KHhyZWYpOwogICAgZXh0R1N0YXRlLnNldCgiUjAiLCByMCk7CiAgICByMC5zZXRJZk5hbWUoIkJNIiwgIk11bHRpcGx5Iik7CiAgICBpZiAob3BhY2l0eSAhPT0gMSkgewogICAgICByMC5zZXQoImNhIiwgb3BhY2l0eSk7CiAgICAgIHIwLnNldElmTmFtZSgiVHlwZSIsICJFeHRHU3RhdGUiKTsKICAgIH0KICAgIGNvbnN0IGFwID0gbmV3IFN0cmluZ1N0cmVhbShhcHBlYXJhbmNlKTsKICAgIGFwLmRpY3QgPSBhcHBlYXJhbmNlU3RyZWFtRGljdDsKICAgIHJldHVybiBhcDsKICB9Cn0KY2xhc3MgSGlnaGxpZ2h0QW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLkhJR0hMSUdIVDsKICAgIHRoaXMuZGF0YS5pc0VkaXRhYmxlID0gIXRoaXMuZGF0YS5ub0hUTUw7CiAgICB0aGlzLmRhdGEubm9IVE1MID0gZmFsc2U7CiAgICB0aGlzLmRhdGEub3BhY2l0eSA9IGRpY3QuZ2V0KCJDQSIpIHx8IDE7CiAgICBjb25zdCBxdWFkUG9pbnRzID0gdGhpcy5kYXRhLnF1YWRQb2ludHMgPSBnZXRRdWFkUG9pbnRzKGRpY3QsIG51bGwpOwogICAgaWYgKHF1YWRQb2ludHMpIHsKICAgICAgY29uc3QgcmVzb3VyY2VzID0gdGhpcy5hcHBlYXJhbmNlPy5kaWN0LmdldCgiUmVzb3VyY2VzIik7CiAgICAgIGlmICghdGhpcy5hcHBlYXJhbmNlIHx8ICFyZXNvdXJjZXM/LmhhcygiRXh0R1N0YXRlIikpIHsKICAgICAgICBpZiAodGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgICAgICB3YXJuKCJIaWdobGlnaHRBbm5vdGF0aW9uIC0gaWdub3JpbmcgYnVpbHQtaW4gYXBwZWFyYW5jZSBzdHJlYW0uIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGZpbGxDb2xvciA9IGdldFBkZkNvbG9yQXJyYXkodGhpcy5jb2xvciwgWzEsIDEsIDBdKTsKICAgICAgICBjb25zdCBmaWxsQWxwaGEgPSBkaWN0LmdldCgiQ0EiKTsKICAgICAgICB0aGlzLl9zZXREZWZhdWx0QXBwZWFyYW5jZSh7CiAgICAgICAgICB4cmVmLAogICAgICAgICAgZmlsbENvbG9yLAogICAgICAgICAgYmxlbmRNb2RlOiAiTXVsdGlwbHkiLAogICAgICAgICAgZmlsbEFscGhhLAogICAgICAgICAgcG9pbnRzQ2FsbGJhY2s6IChidWZmZXIsIHBvaW50cykgPT4gewogICAgICAgICAgICBidWZmZXIucHVzaChgJHtwb2ludHNbMF19ICR7cG9pbnRzWzFdfSBtYCwgYCR7cG9pbnRzWzJdfSAke3BvaW50c1szXX0gbGAsIGAke3BvaW50c1s2XX0gJHtwb2ludHNbN119IGxgLCBgJHtwb2ludHNbNF19ICR7cG9pbnRzWzVdfSBsYCwgImYiKTsKICAgICAgICAgICAgcmV0dXJuIFtwb2ludHNbMF0sIHBvaW50c1s3XSwgcG9pbnRzWzJdLCBwb2ludHNbM11dOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEucG9wdXBSZWYgPSBudWxsOwogICAgfQogIH0KICBnZXQgb3ZlcmxheXNUZXh0Q29udGVudCgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBzdGF0aWMgY3JlYXRlTmV3RGljdChhbm5vdGF0aW9uLCB4cmVmLCB7CiAgICBhcFJlZiwKICAgIGFwCiAgfSkgewogICAgY29uc3QgewogICAgICBjb2xvciwKICAgICAgZGF0ZSwKICAgICAgb2xkQW5ub3RhdGlvbiwKICAgICAgb3BhY2l0eSwKICAgICAgcmVjdCwKICAgICAgcm90YXRpb24sCiAgICAgIHVzZXIsCiAgICAgIHF1YWRQb2ludHMKICAgIH0gPSBhbm5vdGF0aW9uOwogICAgY29uc3QgaGlnaGxpZ2h0ID0gb2xkQW5ub3RhdGlvbiB8fCBuZXcgRGljdCh4cmVmKTsKICAgIGhpZ2hsaWdodC5zZXRJZk5vdEV4aXN0cygiVHlwZSIsIE5hbWUuZ2V0KCJBbm5vdCIpKTsKICAgIGhpZ2hsaWdodC5zZXRJZk5vdEV4aXN0cygiU3VidHlwZSIsIE5hbWUuZ2V0KCJIaWdobGlnaHQiKSk7CiAgICBoaWdobGlnaHQuc2V0KG9sZEFubm90YXRpb24gPyAiTSIgOiAiQ3JlYXRpb25EYXRlIiwgYEQ6JHtnZXRNb2RpZmljYXRpb25EYXRlKGRhdGUpfWApOwogICAgaGlnaGxpZ2h0LnNldElmQXJyYXkoIlJlY3QiLCByZWN0KTsKICAgIGhpZ2hsaWdodC5zZXRJZk5vdEV4aXN0cygiRiIsIDQpOwogICAgaGlnaGxpZ2h0LnNldElmTm90RXhpc3RzKCJCb3JkZXIiLCBbMCwgMCwgMF0pOwogICAgaGlnaGxpZ2h0LnNldElmTnVtYmVyKCJSb3RhdGUiLCByb3RhdGlvbik7CiAgICBoaWdobGlnaHQuc2V0SWZBcnJheSgiUXVhZFBvaW50cyIsIHF1YWRQb2ludHMpOwogICAgaGlnaGxpZ2h0LnNldElmQXJyYXkoIkMiLCBnZXRQZGZDb2xvckFycmF5KGNvbG9yKSk7CiAgICBoaWdobGlnaHQuc2V0SWZOdW1iZXIoIkNBIiwgb3BhY2l0eSk7CiAgICBoaWdobGlnaHQuc2V0SWZEZWZpbmVkKCJUIiwgc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRSh1c2VyKSk7CiAgICBpZiAoYXBSZWYgfHwgYXApIHsKICAgICAgY29uc3QgbiA9IG5ldyBEaWN0KHhyZWYpOwogICAgICBoaWdobGlnaHQuc2V0KCJBUCIsIG4pOwogICAgICBuLnNldCgiTiIsIGFwUmVmIHx8IGFwKTsKICAgIH0KICAgIHJldHVybiBoaWdobGlnaHQ7CiAgfQogIHN0YXRpYyBhc3luYyBjcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtKGFubm90YXRpb24sIHhyZWYsIHBhcmFtcykgewogICAgY29uc3QgewogICAgICBjb2xvciwKICAgICAgcmVjdCwKICAgICAgb3V0bGluZXMsCiAgICAgIG9wYWNpdHkKICAgIH0gPSBhbm5vdGF0aW9uOwogICAgaWYgKCFjb2xvcikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGFwcGVhcmFuY2VCdWZmZXIgPSBbYCR7Z2V0UGRmQ29sb3IoY29sb3IsIHRydWUpfWAsICIvUjAgZ3MiXTsKICAgIGNvbnN0IGJ1ZmZlciA9IFtdOwogICAgZm9yIChjb25zdCBvdXRsaW5lIG9mIG91dGxpbmVzKSB7CiAgICAgIGJ1ZmZlci5sZW5ndGggPSAwOwogICAgICBidWZmZXIucHVzaChgJHtudW1iZXJUb1N0cmluZyhvdXRsaW5lWzBdKX0gJHtudW1iZXJUb1N0cmluZyhvdXRsaW5lWzFdKX0gbWApOwogICAgICBmb3IgKGxldCBpID0gMiwgaWkgPSBvdXRsaW5lLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgICBidWZmZXIucHVzaChgJHtudW1iZXJUb1N0cmluZyhvdXRsaW5lW2ldKX0gJHtudW1iZXJUb1N0cmluZyhvdXRsaW5lW2kgKyAxXSl9IGxgKTsKICAgICAgfQogICAgICBidWZmZXIucHVzaCgiaCIpOwogICAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goYnVmZmVyLmpvaW4oIlxuIikpOwogICAgfQogICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKCJmKiIpOwogICAgY29uc3QgYXBwZWFyYW5jZSA9IGFwcGVhcmFuY2VCdWZmZXIuam9pbigiXG4iKTsKICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW1EaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkZvcm1UeXBlIiwgMSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiRm9ybSIpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJUeXBlIiwgIlhPYmplY3QiKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiQkJveCIsIHJlY3QpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJMZW5ndGgiLCBhcHBlYXJhbmNlLmxlbmd0aCk7CiAgICBjb25zdCByZXNvdXJjZXMgPSBuZXcgRGljdCh4cmVmKTsKICAgIGNvbnN0IGV4dEdTdGF0ZSA9IG5ldyBEaWN0KHhyZWYpOwogICAgcmVzb3VyY2VzLnNldCgiRXh0R1N0YXRlIiwgZXh0R1N0YXRlKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiUmVzb3VyY2VzIiwgcmVzb3VyY2VzKTsKICAgIGNvbnN0IHIwID0gbmV3IERpY3QoeHJlZik7CiAgICBleHRHU3RhdGUuc2V0KCJSMCIsIHIwKTsKICAgIHIwLnNldElmTmFtZSgiQk0iLCAiTXVsdGlwbHkiKTsKICAgIGlmIChvcGFjaXR5ICE9PSAxKSB7CiAgICAgIHIwLnNldCgiY2EiLCBvcGFjaXR5KTsKICAgICAgcjAuc2V0SWZOYW1lKCJUeXBlIiwgIkV4dEdTdGF0ZSIpOwogICAgfQogICAgY29uc3QgYXAgPSBuZXcgU3RyaW5nU3RyZWFtKGFwcGVhcmFuY2UpOwogICAgYXAuZGljdCA9IGFwcGVhcmFuY2VTdHJlYW1EaWN0OwogICAgcmV0dXJuIGFwOwogIH0KfQpjbGFzcyBVbmRlcmxpbmVBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuVU5ERVJMSU5FOwogICAgY29uc3QgcXVhZFBvaW50cyA9IHRoaXMuZGF0YS5xdWFkUG9pbnRzID0gZ2V0UXVhZFBvaW50cyhkaWN0LCBudWxsKTsKICAgIGlmIChxdWFkUG9pbnRzKSB7CiAgICAgIGlmICghdGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgICAgY29uc3Qgc3Ryb2tlQ29sb3IgPSBnZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IsIFswLCAwLCAwXSk7CiAgICAgICAgY29uc3Qgc3Ryb2tlQWxwaGEgPSBkaWN0LmdldCgiQ0EiKTsKICAgICAgICB0aGlzLl9zZXREZWZhdWx0QXBwZWFyYW5jZSh7CiAgICAgICAgICB4cmVmLAogICAgICAgICAgZXh0cmE6ICJbXSAwIGQgMC41NzEgdyIsCiAgICAgICAgICBzdHJva2VDb2xvciwKICAgICAgICAgIHN0cm9rZUFscGhhLAogICAgICAgICAgcG9pbnRzQ2FsbGJhY2s6IChidWZmZXIsIHBvaW50cykgPT4gewogICAgICAgICAgICBidWZmZXIucHVzaChgJHtwb2ludHNbNF19ICR7cG9pbnRzWzVdICsgMS4zfSBtYCwgYCR7cG9pbnRzWzZdfSAke3BvaW50c1s3XSArIDEuM30gbGAsICJTIik7CiAgICAgICAgICAgIHJldHVybiBbcG9pbnRzWzBdLCBwb2ludHNbN10sIHBvaW50c1syXSwgcG9pbnRzWzNdXTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdGhpcy5kYXRhLnBvcHVwUmVmID0gbnVsbDsKICAgIH0KICB9CiAgZ2V0IG92ZXJsYXlzVGV4dENvbnRlbnQoKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KY2xhc3MgU3F1aWdnbHlBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuU1FVSUdHTFk7CiAgICBjb25zdCBxdWFkUG9pbnRzID0gdGhpcy5kYXRhLnF1YWRQb2ludHMgPSBnZXRRdWFkUG9pbnRzKGRpY3QsIG51bGwpOwogICAgaWYgKHF1YWRQb2ludHMpIHsKICAgICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgICBjb25zdCBzdHJva2VDb2xvciA9IGdldFBkZkNvbG9yQXJyYXkodGhpcy5jb2xvciwgWzAsIDAsIDBdKTsKICAgICAgICBjb25zdCBzdHJva2VBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBleHRyYTogIltdIDAgZCAxIHciLAogICAgICAgICAgc3Ryb2tlQ29sb3IsCiAgICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICAgIHBvaW50c0NhbGxiYWNrOiAoYnVmZmVyLCBwb2ludHMpID0+IHsKICAgICAgICAgICAgY29uc3QgZHkgPSAocG9pbnRzWzFdIC0gcG9pbnRzWzVdKSAvIDY7CiAgICAgICAgICAgIGxldCBzaGlmdCA9IGR5OwogICAgICAgICAgICBsZXQgeCA9IHBvaW50c1s0XTsKICAgICAgICAgICAgY29uc3QgeSA9IHBvaW50c1s1XTsKICAgICAgICAgICAgY29uc3QgeEVuZCA9IHBvaW50c1s2XTsKICAgICAgICAgICAgYnVmZmVyLnB1c2goYCR7eH0gJHt5ICsgc2hpZnR9IG1gKTsKICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgIHggKz0gMjsKICAgICAgICAgICAgICBzaGlmdCA9IHNoaWZ0ID09PSAwID8gZHkgOiAwOwogICAgICAgICAgICAgIGJ1ZmZlci5wdXNoKGAke3h9ICR7eSArIHNoaWZ0fSBsYCk7CiAgICAgICAgICAgIH0gd2hpbGUgKHggPCB4RW5kKTsKICAgICAgICAgICAgYnVmZmVyLnB1c2goIlMiKTsKICAgICAgICAgICAgcmV0dXJuIFtwb2ludHNbNF0sIHkgLSAyICogZHksIHhFbmQsIHkgKyAyICogZHldOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEucG9wdXBSZWYgPSBudWxsOwogICAgfQogIH0KICBnZXQgb3ZlcmxheXNUZXh0Q29udGVudCgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KfQpjbGFzcyBTdHJpa2VPdXRBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuU1RSSUtFT1VUOwogICAgY29uc3QgcXVhZFBvaW50cyA9IHRoaXMuZGF0YS5xdWFkUG9pbnRzID0gZ2V0UXVhZFBvaW50cyhkaWN0LCBudWxsKTsKICAgIGlmIChxdWFkUG9pbnRzKSB7CiAgICAgIGlmICghdGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgICAgY29uc3Qgc3Ryb2tlQ29sb3IgPSBnZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IsIFswLCAwLCAwXSk7CiAgICAgICAgY29uc3Qgc3Ryb2tlQWxwaGEgPSBkaWN0LmdldCgiQ0EiKTsKICAgICAgICB0aGlzLl9zZXREZWZhdWx0QXBwZWFyYW5jZSh7CiAgICAgICAgICB4cmVmLAogICAgICAgICAgZXh0cmE6ICJbXSAwIGQgMSB3IiwKICAgICAgICAgIHN0cm9rZUNvbG9yLAogICAgICAgICAgc3Ryb2tlQWxwaGEsCiAgICAgICAgICBwb2ludHNDYWxsYmFjazogKGJ1ZmZlciwgcG9pbnRzKSA9PiB7CiAgICAgICAgICAgIGJ1ZmZlci5wdXNoKGAkeyhwb2ludHNbMF0gKyBwb2ludHNbNF0pIC8gMn0gYCArIGAkeyhwb2ludHNbMV0gKyBwb2ludHNbNV0pIC8gMn0gbWAsIGAkeyhwb2ludHNbMl0gKyBwb2ludHNbNl0pIC8gMn0gYCArIGAkeyhwb2ludHNbM10gKyBwb2ludHNbN10pIC8gMn0gbGAsICJTIik7CiAgICAgICAgICAgIHJldHVybiBbcG9pbnRzWzBdLCBwb2ludHNbN10sIHBvaW50c1syXSwgcG9pbnRzWzNdXTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdGhpcy5kYXRhLnBvcHVwUmVmID0gbnVsbDsKICAgIH0KICB9CiAgZ2V0IG92ZXJsYXlzVGV4dENvbnRlbnQoKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KY2xhc3MgU3RhbXBBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgI3NhdmVkSGFzT3duQ2FudmFzID0gbnVsbDsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBBbm5vdGF0aW9uVHlwZS5TVEFNUDsKICAgIHRoaXMuZGF0YS5oYXNPd25DYW52YXMgPSB0aGlzLmRhdGEubm9Sb3RhdGU7CiAgICB0aGlzLmRhdGEuaXNFZGl0YWJsZSA9ICF0aGlzLmRhdGEubm9IVE1MOwogICAgdGhpcy5kYXRhLm5vSFRNTCA9IGZhbHNlOwogIH0KICBtdXN0QmVWaWV3ZWRXaGVuRWRpdGluZyhpc0VkaXRpbmcsIG1vZGlmaWVkSWRzID0gbnVsbCkgewogICAgaWYgKGlzRWRpdGluZykgewogICAgICBpZiAoIXRoaXMuZGF0YS5pc0VkaXRhYmxlKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgdGhpcy4jc2F2ZWRIYXNPd25DYW52YXMgPz89IHRoaXMuZGF0YS5oYXNPd25DYW52YXM7CiAgICAgIHRoaXMuZGF0YS5oYXNPd25DYW52YXMgPSB0cnVlOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmICh0aGlzLiNzYXZlZEhhc093bkNhbnZhcyAhPT0gbnVsbCkgewogICAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy4jc2F2ZWRIYXNPd25DYW52YXM7CiAgICAgIHRoaXMuI3NhdmVkSGFzT3duQ2FudmFzID0gbnVsbDsKICAgIH0KICAgIHJldHVybiAhbW9kaWZpZWRJZHM/Lmhhcyh0aGlzLmRhdGEuaWQpOwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlSW1hZ2UoYml0bWFwLCB4cmVmKSB7CiAgICBjb25zdCB7CiAgICAgIHdpZHRoLAogICAgICBoZWlnaHQKICAgIH0gPSBiaXRtYXA7CiAgICBjb25zdCBjYW52YXMgPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKHdpZHRoLCBoZWlnaHQpOwogICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIiwgewogICAgICBhbHBoYTogdHJ1ZQogICAgfSk7CiAgICBjdHguZHJhd0ltYWdlKGJpdG1hcCwgMCwgMCk7CiAgICBjb25zdCBkYXRhID0gY3R4LmdldEltYWdlRGF0YSgwLCAwLCB3aWR0aCwgaGVpZ2h0KS5kYXRhOwogICAgY29uc3QgYnVmMzIgPSBuZXcgVWludDMyQXJyYXkoZGF0YS5idWZmZXIpOwogICAgY29uc3QgaGFzQWxwaGEgPSBidWYzMi5zb21lKEZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuID8geCA9PiB4ID4+PiAyNCAhPT0gMHhmZiA6IHggPT4gKHggJiAweGZmKSAhPT0gMHhmZik7CiAgICBpZiAoaGFzQWxwaGEpIHsKICAgICAgY3R4LmZpbGxTdHlsZSA9ICJ3aGl0ZSI7CiAgICAgIGN0eC5maWxsUmVjdCgwLCAwLCB3aWR0aCwgaGVpZ2h0KTsKICAgICAgY3R4LmRyYXdJbWFnZShiaXRtYXAsIDAsIDApOwogICAgfQogICAgY29uc3QganBlZ0J1ZmZlclByb21pc2UgPSBjYW52YXMuY29udmVydFRvQmxvYih7CiAgICAgIHR5cGU6ICJpbWFnZS9qcGVnIiwKICAgICAgcXVhbGl0eTogMQogICAgfSkudGhlbihibG9iID0+IGJsb2IuYXJyYXlCdWZmZXIoKSk7CiAgICBjb25zdCB4b2JqZWN0TmFtZSA9IE5hbWUuZ2V0KCJYT2JqZWN0Iik7CiAgICBjb25zdCBpbWFnZU5hbWUgPSBOYW1lLmdldCgiSW1hZ2UiKTsKICAgIGNvbnN0IGltYWdlID0gbmV3IERpY3QoeHJlZik7CiAgICBpbWFnZS5zZXQoIlR5cGUiLCB4b2JqZWN0TmFtZSk7CiAgICBpbWFnZS5zZXQoIlN1YnR5cGUiLCBpbWFnZU5hbWUpOwogICAgaW1hZ2Uuc2V0KCJCaXRzUGVyQ29tcG9uZW50IiwgOCk7CiAgICBpbWFnZS5zZXRJZk5hbWUoIkNvbG9yU3BhY2UiLCAiRGV2aWNlUkdCIik7CiAgICBpbWFnZS5zZXRJZk5hbWUoIkZpbHRlciIsICJEQ1REZWNvZGUiKTsKICAgIGltYWdlLnNldCgiQkJveCIsIFswLCAwLCB3aWR0aCwgaGVpZ2h0XSk7CiAgICBpbWFnZS5zZXQoIldpZHRoIiwgd2lkdGgpOwogICAgaW1hZ2Uuc2V0KCJIZWlnaHQiLCBoZWlnaHQpOwogICAgbGV0IHNtYXNrU3RyZWFtID0gbnVsbDsKICAgIGlmIChoYXNBbHBoYSkgewogICAgICBjb25zdCBhbHBoYUJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KGJ1ZjMyLmxlbmd0aCk7CiAgICAgIGlmIChGZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbikgewogICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGJ1ZjMyLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgIGFscGhhQnVmZmVyW2ldID0gYnVmMzJbaV0gPj4+IDI0OwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBidWYzMi5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICBhbHBoYUJ1ZmZlcltpXSA9IGJ1ZjMyW2ldICYgMHhmZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3Qgc21hc2sgPSBuZXcgRGljdCh4cmVmKTsKICAgICAgc21hc2suc2V0KCJUeXBlIiwgeG9iamVjdE5hbWUpOwogICAgICBzbWFzay5zZXQoIlN1YnR5cGUiLCBpbWFnZU5hbWUpOwogICAgICBzbWFzay5zZXQoIkJpdHNQZXJDb21wb25lbnQiLCA4KTsKICAgICAgc21hc2suc2V0SWZOYW1lKCJDb2xvclNwYWNlIiwgIkRldmljZUdyYXkiKTsKICAgICAgc21hc2suc2V0KCJXaWR0aCIsIHdpZHRoKTsKICAgICAgc21hc2suc2V0KCJIZWlnaHQiLCBoZWlnaHQpOwogICAgICBzbWFza1N0cmVhbSA9IG5ldyBTdHJlYW0oYWxwaGFCdWZmZXIsIDAsIDAsIHNtYXNrKTsKICAgIH0KICAgIGNvbnN0IGltYWdlU3RyZWFtID0gbmV3IFN0cmVhbShhd2FpdCBqcGVnQnVmZmVyUHJvbWlzZSwgMCwgMCwgaW1hZ2UpOwogICAgcmV0dXJuIHsKICAgICAgaW1hZ2VTdHJlYW0sCiAgICAgIHNtYXNrU3RyZWFtLAogICAgICB3aWR0aCwKICAgICAgaGVpZ2h0CiAgICB9OwogIH0KICBzdGF0aWMgY3JlYXRlTmV3RGljdChhbm5vdGF0aW9uLCB4cmVmLCB7CiAgICBhcFJlZiwKICAgIGFwCiAgfSkgewogICAgY29uc3QgewogICAgICBkYXRlLAogICAgICBvbGRBbm5vdGF0aW9uLAogICAgICByZWN0LAogICAgICByb3RhdGlvbiwKICAgICAgdXNlcgogICAgfSA9IGFubm90YXRpb247CiAgICBjb25zdCBzdGFtcCA9IG9sZEFubm90YXRpb24gfHwgbmV3IERpY3QoeHJlZik7CiAgICBzdGFtcC5zZXRJZk5vdEV4aXN0cygiVHlwZSIsIE5hbWUuZ2V0KCJBbm5vdCIpKTsKICAgIHN0YW1wLnNldElmTm90RXhpc3RzKCJTdWJ0eXBlIiwgTmFtZS5nZXQoIlN0YW1wIikpOwogICAgc3RhbXAuc2V0KG9sZEFubm90YXRpb24gPyAiTSIgOiAiQ3JlYXRpb25EYXRlIiwgYEQ6JHtnZXRNb2RpZmljYXRpb25EYXRlKGRhdGUpfWApOwogICAgc3RhbXAuc2V0SWZBcnJheSgiUmVjdCIsIHJlY3QpOwogICAgc3RhbXAuc2V0SWZOb3RFeGlzdHMoIkYiLCA0KTsKICAgIHN0YW1wLnNldElmTm90RXhpc3RzKCJCb3JkZXIiLCBbMCwgMCwgMF0pOwogICAgc3RhbXAuc2V0SWZOdW1iZXIoIlJvdGF0ZSIsIHJvdGF0aW9uKTsKICAgIHN0YW1wLnNldElmRGVmaW5lZCgiVCIsIHN0cmluZ1RvQXNjaWlPclVURjE2QkUodXNlcikpOwogICAgaWYgKGFwUmVmIHx8IGFwKSB7CiAgICAgIGNvbnN0IG4gPSBuZXcgRGljdCh4cmVmKTsKICAgICAgc3RhbXAuc2V0KCJBUCIsIG4pOwogICAgICBuLnNldCgiTiIsIGFwUmVmIHx8IGFwKTsKICAgIH0KICAgIHJldHVybiBzdGFtcDsKICB9CiAgc3RhdGljIGFzeW5jICNjcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtRm9yRHJhd2luZyhhbm5vdGF0aW9uLCB4cmVmKSB7CiAgICBjb25zdCB7CiAgICAgIGFyZUNvbnRvdXJzLAogICAgICBjb2xvciwKICAgICAgcmVjdCwKICAgICAgbGluZXMsCiAgICAgIHRoaWNrbmVzcwogICAgfSA9IGFubm90YXRpb247CiAgICBpZiAoIWNvbG9yKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgYXBwZWFyYW5jZUJ1ZmZlciA9IFtgJHt0aGlja25lc3N9IHcgMSBKIDEgamAsIGAke2dldFBkZkNvbG9yKGNvbG9yLCBhcmVDb250b3Vycyl9YF07CiAgICBmb3IgKGNvbnN0IGxpbmUgb2YgbGluZXMpIHsKICAgICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKGAke251bWJlclRvU3RyaW5nKGxpbmVbNF0pfSAke251bWJlclRvU3RyaW5nKGxpbmVbNV0pfSBtYCk7CiAgICAgIGZvciAobGV0IGkgPSA2LCBpaSA9IGxpbmUubGVuZ3RoOyBpIDwgaWk7IGkgKz0gNikgewogICAgICAgIGlmIChpc05hTihsaW5lW2ldKSkgewogICAgICAgICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKGAke251bWJlclRvU3RyaW5nKGxpbmVbaSArIDRdKX0gJHtudW1iZXJUb1N0cmluZyhsaW5lW2kgKyA1XSl9IGxgKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgW2MxeCwgYzF5LCBjMngsIGMyeSwgeCwgeV0gPSBsaW5lLnNsaWNlKGksIGkgKyA2KTsKICAgICAgICAgIGFwcGVhcmFuY2VCdWZmZXIucHVzaChbYzF4LCBjMXksIGMyeCwgYzJ5LCB4LCB5XS5tYXAobnVtYmVyVG9TdHJpbmcpLmpvaW4oIiAiKSArICIgYyIpOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAobGluZS5sZW5ndGggPT09IDYpIHsKICAgICAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goYCR7bnVtYmVyVG9TdHJpbmcobGluZVs0XSl9ICR7bnVtYmVyVG9TdHJpbmcobGluZVs1XSl9IGxgKTsKICAgICAgfQogICAgfQogICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKGFyZUNvbnRvdXJzID8gIkYiIDogIlMiKTsKICAgIGNvbnN0IGFwcGVhcmFuY2UgPSBhcHBlYXJhbmNlQnVmZmVyLmpvaW4oIlxuIik7CiAgICBjb25zdCBhcHBlYXJhbmNlU3RyZWFtRGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJGb3JtVHlwZSIsIDEpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIkZvcm0iKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldElmTmFtZSgiVHlwZSIsICJYT2JqZWN0Iik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkJCb3giLCByZWN0KTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiTGVuZ3RoIiwgYXBwZWFyYW5jZS5sZW5ndGgpOwogICAgY29uc3QgYXAgPSBuZXcgU3RyaW5nU3RyZWFtKGFwcGVhcmFuY2UpOwogICAgYXAuZGljdCA9IGFwcGVhcmFuY2VTdHJlYW1EaWN0OwogICAgcmV0dXJuIGFwOwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlTmV3QXBwZWFyYW5jZVN0cmVhbShhbm5vdGF0aW9uLCB4cmVmLCBwYXJhbXMpIHsKICAgIGlmIChhbm5vdGF0aW9uLm9sZEFubm90YXRpb24pIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBpZiAoYW5ub3RhdGlvbi5pc1NpZ25hdHVyZSkgewogICAgICByZXR1cm4gdGhpcy4jY3JlYXRlTmV3QXBwZWFyYW5jZVN0cmVhbUZvckRyYXdpbmcoYW5ub3RhdGlvbiwgeHJlZik7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIHJvdGF0aW9uCiAgICB9ID0gYW5ub3RhdGlvbjsKICAgIGNvbnN0IHsKICAgICAgaW1hZ2VSZWYsCiAgICAgIHdpZHRoLAogICAgICBoZWlnaHQKICAgIH0gPSBwYXJhbXMuaW1hZ2U7CiAgICBjb25zdCByZXNvdXJjZXMgPSBuZXcgRGljdCh4cmVmKTsKICAgIGNvbnN0IHhvYmplY3QgPSBuZXcgRGljdCh4cmVmKTsKICAgIHJlc291cmNlcy5zZXQoIlhPYmplY3QiLCB4b2JqZWN0KTsKICAgIHhvYmplY3Quc2V0KCJJbTAiLCBpbWFnZVJlZik7CiAgICBjb25zdCBhcHBlYXJhbmNlID0gYHEgJHt3aWR0aH0gMCAwICR7aGVpZ2h0fSAwIDAgY20gL0ltMCBEbyBRYDsKICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW1EaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkZvcm1UeXBlIiwgMSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiRm9ybSIpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJUeXBlIiwgIlhPYmplY3QiKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiQkJveCIsIFswLCAwLCB3aWR0aCwgaGVpZ2h0XSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlJlc291cmNlcyIsIHJlc291cmNlcyk7CiAgICBpZiAocm90YXRpb24pIHsKICAgICAgY29uc3QgbWF0cml4ID0gZ2V0Um90YXRpb25NYXRyaXgocm90YXRpb24sIHdpZHRoLCBoZWlnaHQpOwogICAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIk1hdHJpeCIsIG1hdHJpeCk7CiAgICB9CiAgICBjb25zdCBhcCA9IG5ldyBTdHJpbmdTdHJlYW0oYXBwZWFyYW5jZSk7CiAgICBhcC5kaWN0ID0gYXBwZWFyYW5jZVN0cmVhbURpY3Q7CiAgICByZXR1cm4gYXA7CiAgfQp9CmNsYXNzIEZpbGVBdHRhY2htZW50QW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdAogICAgfSA9IHBhcmFtczsKICAgIGNvbnN0IGZpbGUgPSBuZXcgRmlsZVNwZWMoZGljdC5nZXQoIkZTIikpOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuRklMRUFUVEFDSE1FTlQ7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogICAgdGhpcy5kYXRhLm5vSFRNTCA9IGZhbHNlOwogICAgdGhpcy5kYXRhLmZpbGUgPSBmaWxlLnNlcmlhbGl6YWJsZTsKICAgIGNvbnN0IG5hbWUgPSBkaWN0LmdldCgiTmFtZSIpOwogICAgdGhpcy5kYXRhLm5hbWUgPSBuYW1lIGluc3RhbmNlb2YgTmFtZSA/IHN0cmluZ1RvUERGU3RyaW5nKG5hbWUubmFtZSkgOiAiUHVzaFBpbiI7CiAgICBjb25zdCBmaWxsQWxwaGEgPSBkaWN0LmdldCgiY2EiKTsKICAgIHRoaXMuZGF0YS5maWxsQWxwaGEgPSB0eXBlb2YgZmlsbEFscGhhID09PSAibnVtYmVyIiAmJiBmaWxsQWxwaGEgPj0gMCAmJiBmaWxsQWxwaGEgPD0gMSA/IGZpbGxBbHBoYSA6IG51bGw7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9jYWxjdWxhdGVfbWQ1LmpzCgpjb25zdCBQQVJBTVMgPSB7CiAgZ2V0IHIoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJyIiwgbmV3IFVpbnQ4QXJyYXkoWzcsIDEyLCAxNywgMjIsIDcsIDEyLCAxNywgMjIsIDcsIDEyLCAxNywgMjIsIDcsIDEyLCAxNywgMjIsIDUsIDksIDE0LCAyMCwgNSwgOSwgMTQsIDIwLCA1LCA5LCAxNCwgMjAsIDUsIDksIDE0LCAyMCwgNCwgMTEsIDE2LCAyMywgNCwgMTEsIDE2LCAyMywgNCwgMTEsIDE2LCAyMywgNCwgMTEsIDE2LCAyMywgNiwgMTAsIDE1LCAyMSwgNiwgMTAsIDE1LCAyMSwgNiwgMTAsIDE1LCAyMSwgNiwgMTAsIDE1LCAyMV0pKTsKICB9LAogIGdldCBrKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiayIsIG5ldyBJbnQzMkFycmF5KFstNjgwODc2OTM2LCAtMzg5NTY0NTg2LCA2MDYxMDU4MTksIC0xMDQ0NTI1MzMwLCAtMTc2NDE4ODk3LCAxMjAwMDgwNDI2LCAtMTQ3MzIzMTM0MSwgLTQ1NzA1OTgzLCAxNzcwMDM1NDE2LCAtMTk1ODQxNDQxNywgLTQyMDYzLCAtMTk5MDQwNDE2MiwgMTgwNDYwMzY4MiwgLTQwMzQxMTAxLCAtMTUwMjAwMjI5MCwgMTIzNjUzNTMyOSwgLTE2NTc5NjUxMCwgLTEwNjk1MDE2MzIsIDY0MzcxNzcxMywgLTM3Mzg5NzMwMiwgLTcwMTU1ODY5MSwgMzgwMTYwODMsIC02NjA0NzgzMzUsIC00MDU1Mzc4NDgsIDU2ODQ0NjQzOCwgLTEwMTk4MDM2OTAsIC0xODczNjM5NjEsIDExNjM1MzE1MDEsIC0xNDQ0NjgxNDY3LCAtNTE0MDM3ODQsIDE3MzUzMjg0NzMsIC0xOTI2NjA3NzM0LCAtMzc4NTU4LCAtMjAyMjU3NDQ2MywgMTgzOTAzMDU2MiwgLTM1MzA5NTU2LCAtMTUzMDk5MjA2MCwgMTI3Mjg5MzM1MywgLTE1NTQ5NzYzMiwgLTEwOTQ3MzA2NDAsIDY4MTI3OTE3NCwgLTM1ODUzNzIyMiwgLTcyMjUyMTk3OSwgNzYwMjkxODksIC02NDAzNjQ0ODcsIC00MjE4MTU4MzUsIDUzMDc0MjUyMCwgLTk5NTMzODY1MSwgLTE5ODYzMDg0NCwgMTEyNjg5MTQxNSwgLTE0MTYzNTQ5MDUsIC01NzQzNDA1NSwgMTcwMDQ4NTU3MSwgLTE4OTQ5ODY2MDYsIC0xMDUxNTIzLCAtMjA1NDkyMjc5OSwgMTg3MzMxMzM1OSwgLTMwNjExNzQ0LCAtMTU2MDE5ODM4MCwgMTMwOTE1MTY0OSwgLTE0NTUyMzA3MCwgLTExMjAyMTAzNzksIDcxODc4NzI1OSwgLTM0MzQ4NTU1MV0pKTsKICB9Cn07CmZ1bmN0aW9uIGNhbGN1bGF0ZU1ENShkYXRhLCBvZmZzZXQsIGxlbmd0aCkgewogIGxldCBoMCA9IDE3MzI1ODQxOTMsCiAgICBoMSA9IC0yNzE3MzM4NzksCiAgICBoMiA9IC0xNzMyNTg0MTk0LAogICAgaDMgPSAyNzE3MzM4Nzg7CiAgY29uc3QgcGFkZGVkTGVuZ3RoID0gbGVuZ3RoICsgNzIgJiB+NjM7CiAgY29uc3QgcGFkZGVkID0gbmV3IFVpbnQ4QXJyYXkocGFkZGVkTGVuZ3RoKTsKICBsZXQgaSwgajsKICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgIHBhZGRlZFtpXSA9IGRhdGFbb2Zmc2V0KytdOwogIH0KICBwYWRkZWRbaSsrXSA9IDB4ODA7CiAgY29uc3QgbiA9IHBhZGRlZExlbmd0aCAtIDg7CiAgaWYgKGkgPCBuKSB7CiAgICBpID0gbjsKICB9CiAgcGFkZGVkW2krK10gPSBsZW5ndGggPDwgMyAmIDB4ZmY7CiAgcGFkZGVkW2krK10gPSBsZW5ndGggPj4gNSAmIDB4ZmY7CiAgcGFkZGVkW2krK10gPSBsZW5ndGggPj4gMTMgJiAweGZmOwogIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+IDIxICYgMHhmZjsKICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+Pj4gMjkgJiAweGZmOwogIGkgKz0gMzsKICBjb25zdCB3ID0gbmV3IEludDMyQXJyYXkoMTYpOwogIGNvbnN0IHsKICAgIGssCiAgICByCiAgfSA9IFBBUkFNUzsKICBmb3IgKGkgPSAwOyBpIDwgcGFkZGVkTGVuZ3RoOykgewogICAgZm9yIChqID0gMDsgaiA8IDE2OyArK2osIGkgKz0gNCkgewogICAgICB3W2pdID0gcGFkZGVkW2ldIHwgcGFkZGVkW2kgKyAxXSA8PCA4IHwgcGFkZGVkW2kgKyAyXSA8PCAxNiB8IHBhZGRlZFtpICsgM10gPDwgMjQ7CiAgICB9CiAgICBsZXQgYSA9IGgwLAogICAgICBiID0gaDEsCiAgICAgIGMgPSBoMiwKICAgICAgZCA9IGgzLAogICAgICBmLAogICAgICBnOwogICAgZm9yIChqID0gMDsgaiA8IDY0OyArK2opIHsKICAgICAgaWYgKGogPCAxNikgewogICAgICAgIGYgPSBiICYgYyB8IH5iICYgZDsKICAgICAgICBnID0gajsKICAgICAgfSBlbHNlIGlmIChqIDwgMzIpIHsKICAgICAgICBmID0gZCAmIGIgfCB+ZCAmIGM7CiAgICAgICAgZyA9IDUgKiBqICsgMSAmIDE1OwogICAgICB9IGVsc2UgaWYgKGogPCA0OCkgewogICAgICAgIGYgPSBiIF4gYyBeIGQ7CiAgICAgICAgZyA9IDMgKiBqICsgNSAmIDE1OwogICAgICB9IGVsc2UgewogICAgICAgIGYgPSBjIF4gKGIgfCB+ZCk7CiAgICAgICAgZyA9IDcgKiBqICYgMTU7CiAgICAgIH0KICAgICAgY29uc3QgdG1wID0gZCwKICAgICAgICByb3RhdGVBcmcgPSBhICsgZiArIGtbal0gKyB3W2ddIHwgMCwKICAgICAgICByb3RhdGUgPSByW2pdOwogICAgICBkID0gYzsKICAgICAgYyA9IGI7CiAgICAgIGIgPSBiICsgKHJvdGF0ZUFyZyA8PCByb3RhdGUgfCByb3RhdGVBcmcgPj4+IDMyIC0gcm90YXRlKSB8IDA7CiAgICAgIGEgPSB0bXA7CiAgICB9CiAgICBoMCA9IGgwICsgYSB8IDA7CiAgICBoMSA9IGgxICsgYiB8IDA7CiAgICBoMiA9IGgyICsgYyB8IDA7CiAgICBoMyA9IGgzICsgZCB8IDA7CiAgfQogIHJldHVybiBuZXcgVWludDhBcnJheShbaDAgJiAweEZGLCBoMCA+PiA4ICYgMHhGRiwgaDAgPj4gMTYgJiAweEZGLCBoMCA+Pj4gMjQgJiAweEZGLCBoMSAmIDB4RkYsIGgxID4+IDggJiAweEZGLCBoMSA+PiAxNiAmIDB4RkYsIGgxID4+PiAyNCAmIDB4RkYsIGgyICYgMHhGRiwgaDIgPj4gOCAmIDB4RkYsIGgyID4+IDE2ICYgMHhGRiwgaDIgPj4+IDI0ICYgMHhGRiwgaDMgJiAweEZGLCBoMyA+PiA4ICYgMHhGRiwgaDMgPj4gMTYgJiAweEZGLCBoMyA+Pj4gMjQgJiAweEZGXSk7Cn0KCjsvLyAuL3NyYy9jb3JlL2RhdGFzZXRfcmVhZGVyLmpzCgoKCmZ1bmN0aW9uIGRlY29kZVN0cmluZyhzdHIpIHsKICB0cnkgewogICAgcmV0dXJuIHN0cmluZ1RvVVRGOFN0cmluZyhzdHIpOwogIH0gY2F0Y2ggKGV4KSB7CiAgICB3YXJuKGBVVEYtOCBkZWNvZGluZyBmYWlsZWQ6ICIke2V4fSIuYCk7CiAgICByZXR1cm4gc3RyOwogIH0KfQpjbGFzcyBEYXRhc2V0WE1MUGFyc2VyIGV4dGVuZHMgU2ltcGxlWE1MUGFyc2VyIHsKICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICBzdXBlcihvcHRpb25zKTsKICAgIHRoaXMubm9kZSA9IG51bGw7CiAgfQogIG9uRW5kRWxlbWVudChuYW1lKSB7CiAgICBjb25zdCBub2RlID0gc3VwZXIub25FbmRFbGVtZW50KG5hbWUpOwogICAgaWYgKG5vZGUgJiYgbmFtZSA9PT0gInhmYTpkYXRhc2V0cyIpIHsKICAgICAgdGhpcy5ub2RlID0gbm9kZTsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJBYm9ydGluZyBEYXRhc2V0WE1MUGFyc2VyLiIpOwogICAgfQogIH0KfQpjbGFzcyBEYXRhc2V0UmVhZGVyIHsKICBjb25zdHJ1Y3RvcihkYXRhKSB7CiAgICBpZiAoZGF0YS5kYXRhc2V0cykgewogICAgICB0aGlzLm5vZGUgPSBuZXcgU2ltcGxlWE1MUGFyc2VyKHsKICAgICAgICBoYXNBdHRyaWJ1dGVzOiB0cnVlCiAgICAgIH0pLnBhcnNlRnJvbVN0cmluZyhkYXRhLmRhdGFzZXRzKS5kb2N1bWVudEVsZW1lbnQ7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBwYXJzZXIgPSBuZXcgRGF0YXNldFhNTFBhcnNlcih7CiAgICAgICAgaGFzQXR0cmlidXRlczogdHJ1ZQogICAgICB9KTsKICAgICAgdHJ5IHsKICAgICAgICBwYXJzZXIucGFyc2VGcm9tU3RyaW5nKGRhdGFbInhkcDp4ZHAiXSk7CiAgICAgIH0gY2F0Y2gge30KICAgICAgdGhpcy5ub2RlID0gcGFyc2VyLm5vZGU7CiAgICB9CiAgfQogIGdldFZhbHVlKHBhdGgpIHsKICAgIGlmICghdGhpcy5ub2RlIHx8ICFwYXRoKSB7CiAgICAgIHJldHVybiAiIjsKICAgIH0KICAgIGNvbnN0IG5vZGUgPSB0aGlzLm5vZGUuc2VhcmNoTm9kZShwYXJzZVhGQVBhdGgocGF0aCksIDApOwogICAgaWYgKCFub2RlKSB7CiAgICAgIHJldHVybiAiIjsKICAgIH0KICAgIGNvbnN0IGZpcnN0ID0gbm9kZS5maXJzdENoaWxkOwogICAgaWYgKGZpcnN0Py5ub2RlTmFtZSA9PT0gInZhbHVlIikgewogICAgICByZXR1cm4gbm9kZS5jaGlsZHJlbi5tYXAoY2hpbGQgPT4gZGVjb2RlU3RyaW5nKGNoaWxkLnRleHRDb250ZW50KSk7CiAgICB9CiAgICByZXR1cm4gZGVjb2RlU3RyaW5nKG5vZGUudGV4dENvbnRlbnQpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvaW50ZXJzZWN0b3IuanMKY2xhc3MgU2luZ2xlSW50ZXJzZWN0b3IgewogICNhbm5vdGF0aW9uOwogIG1pblggPSBJbmZpbml0eTsKICBtaW5ZID0gSW5maW5pdHk7CiAgbWF4WCA9IC1JbmZpbml0eTsKICBtYXhZID0gLUluZmluaXR5OwogICNxdWFkUG9pbnRzID0gbnVsbDsKICAjdGV4dCA9IFtdOwogICNleHRyYUNoYXJzID0gW107CiAgI2xhc3RJbnRlcnNlY3RpbmdRdWFkSW5kZXggPSAtMTsKICAjY2FuVGFrZUV4dHJhQ2hhcnMgPSBmYWxzZTsKICBjb25zdHJ1Y3Rvcihhbm5vdGF0aW9uKSB7CiAgICB0aGlzLiNhbm5vdGF0aW9uID0gYW5ub3RhdGlvbjsKICAgIGNvbnN0IHF1YWRQb2ludHMgPSBhbm5vdGF0aW9uLmRhdGEucXVhZFBvaW50czsKICAgIGlmICghcXVhZFBvaW50cykgewogICAgICBbdGhpcy5taW5YLCB0aGlzLm1pblksIHRoaXMubWF4WCwgdGhpcy5tYXhZXSA9IGFubm90YXRpb24uZGF0YS5yZWN0OwogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBxdWFkUG9pbnRzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDgpIHsKICAgICAgdGhpcy5taW5YID0gTWF0aC5taW4odGhpcy5taW5YLCBxdWFkUG9pbnRzW2ldKTsKICAgICAgdGhpcy5tYXhYID0gTWF0aC5tYXgodGhpcy5tYXhYLCBxdWFkUG9pbnRzW2kgKyAyXSk7CiAgICAgIHRoaXMubWluWSA9IE1hdGgubWluKHRoaXMubWluWSwgcXVhZFBvaW50c1tpICsgNV0pOwogICAgICB0aGlzLm1heFkgPSBNYXRoLm1heCh0aGlzLm1heFksIHF1YWRQb2ludHNbaSArIDFdKTsKICAgIH0KICAgIGlmIChxdWFkUG9pbnRzLmxlbmd0aCA+IDgpIHsKICAgICAgdGhpcy4jcXVhZFBvaW50cyA9IHF1YWRQb2ludHM7CiAgICB9CiAgfQogICNpbnRlcnNlY3RzKHgsIHkpIHsKICAgIGlmICh0aGlzLm1pblggPj0geCB8fCB0aGlzLm1heFggPD0geCB8fCB0aGlzLm1pblkgPj0geSB8fCB0aGlzLm1heFkgPD0geSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBjb25zdCBxdWFkUG9pbnRzID0gdGhpcy4jcXVhZFBvaW50czsKICAgIGlmICghcXVhZFBvaW50cykgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmICh0aGlzLiNsYXN0SW50ZXJzZWN0aW5nUXVhZEluZGV4ID49IDApIHsKICAgICAgY29uc3QgaSA9IHRoaXMuI2xhc3RJbnRlcnNlY3RpbmdRdWFkSW5kZXg7CiAgICAgIGlmICghKHF1YWRQb2ludHNbaV0gPj0geCB8fCBxdWFkUG9pbnRzW2kgKyAyXSA8PSB4IHx8IHF1YWRQb2ludHNbaSArIDVdID49IHkgfHwgcXVhZFBvaW50c1tpICsgMV0gPD0geSkpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICB0aGlzLiNsYXN0SW50ZXJzZWN0aW5nUXVhZEluZGV4ID0gLTE7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBxdWFkUG9pbnRzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDgpIHsKICAgICAgaWYgKCEocXVhZFBvaW50c1tpXSA+PSB4IHx8IHF1YWRQb2ludHNbaSArIDJdIDw9IHggfHwgcXVhZFBvaW50c1tpICsgNV0gPj0geSB8fCBxdWFkUG9pbnRzW2kgKyAxXSA8PSB5KSkgewogICAgICAgIHRoaXMuI2xhc3RJbnRlcnNlY3RpbmdRdWFkSW5kZXggPSBpOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGFkZEdseXBoKHgsIHksIGdseXBoKSB7CiAgICBpZiAoIXRoaXMuI2ludGVyc2VjdHMoeCwgeSkpIHsKICAgICAgdGhpcy5kaXNhYmxlRXh0cmFDaGFycygpOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy4jZXh0cmFDaGFycy5sZW5ndGggPiAwKSB7CiAgICAgIHRoaXMuI3RleHQucHVzaCh0aGlzLiNleHRyYUNoYXJzLmpvaW4oIiIpKTsKICAgICAgdGhpcy4jZXh0cmFDaGFycy5sZW5ndGggPSAwOwogICAgfQogICAgdGhpcy4jdGV4dC5wdXNoKGdseXBoKTsKICAgIHRoaXMuI2NhblRha2VFeHRyYUNoYXJzID0gdHJ1ZTsKICAgIHJldHVybiB0cnVlOwogIH0KICBhZGRFeHRyYUNoYXIoY2hhcikgewogICAgaWYgKHRoaXMuI2NhblRha2VFeHRyYUNoYXJzKSB7CiAgICAgIHRoaXMuI2V4dHJhQ2hhcnMucHVzaChjaGFyKTsKICAgIH0KICB9CiAgZGlzYWJsZUV4dHJhQ2hhcnMoKSB7CiAgICBpZiAoIXRoaXMuI2NhblRha2VFeHRyYUNoYXJzKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuI2NhblRha2VFeHRyYUNoYXJzID0gZmFsc2U7CiAgICB0aGlzLiNleHRyYUNoYXJzLmxlbmd0aCA9IDA7CiAgfQogIHNldFRleHQoKSB7CiAgICB0aGlzLiNhbm5vdGF0aW9uLmRhdGEub3ZlcmxhaWRUZXh0ID0gdGhpcy4jdGV4dC5qb2luKCIiKTsKICB9Cn0KY29uc3QgU1RFUFMgPSA2NDsKY2xhc3MgSW50ZXJzZWN0b3IgewogICNpbnRlcnNlY3RvcnMgPSBbXTsKICAjZ3JpZCA9IFtdOwogICNtaW5YOwogICNtYXhYOwogICNtaW5ZOwogICNtYXhZOwogICNpbnZYUmF0aW87CiAgI2ludllSYXRpbzsKICBjb25zdHJ1Y3Rvcihhbm5vdGF0aW9ucykgewogICAgbGV0IG1pblggPSBJbmZpbml0eTsKICAgIGxldCBtaW5ZID0gSW5maW5pdHk7CiAgICBsZXQgbWF4WCA9IC1JbmZpbml0eTsKICAgIGxldCBtYXhZID0gLUluZmluaXR5OwogICAgY29uc3QgaW50ZXJzZWN0b3JzID0gdGhpcy4jaW50ZXJzZWN0b3JzOwogICAgZm9yIChjb25zdCBhbm5vdGF0aW9uIG9mIGFubm90YXRpb25zKSB7CiAgICAgIGlmICghYW5ub3RhdGlvbi5kYXRhLnF1YWRQb2ludHMgJiYgIWFubm90YXRpb24uZGF0YS5yZWN0KSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgaW50ZXJzZWN0b3IgPSBuZXcgU2luZ2xlSW50ZXJzZWN0b3IoYW5ub3RhdGlvbik7CiAgICAgIGludGVyc2VjdG9ycy5wdXNoKGludGVyc2VjdG9yKTsKICAgICAgbWluWCA9IE1hdGgubWluKG1pblgsIGludGVyc2VjdG9yLm1pblgpOwogICAgICBtaW5ZID0gTWF0aC5taW4obWluWSwgaW50ZXJzZWN0b3IubWluWSk7CiAgICAgIG1heFggPSBNYXRoLm1heChtYXhYLCBpbnRlcnNlY3Rvci5tYXhYKTsKICAgICAgbWF4WSA9IE1hdGgubWF4KG1heFksIGludGVyc2VjdG9yLm1heFkpOwogICAgfQogICAgdGhpcy4jbWluWCA9IG1pblg7CiAgICB0aGlzLiNtaW5ZID0gbWluWTsKICAgIHRoaXMuI21heFggPSBtYXhYOwogICAgdGhpcy4jbWF4WSA9IG1heFk7CiAgICB0aGlzLiNpbnZYUmF0aW8gPSAoU1RFUFMgLSAxKSAvIChtYXhYIC0gbWluWCk7CiAgICB0aGlzLiNpbnZZUmF0aW8gPSAoU1RFUFMgLSAxKSAvIChtYXhZIC0gbWluWSk7CiAgICBmb3IgKGNvbnN0IGludGVyc2VjdG9yIG9mIGludGVyc2VjdG9ycykgewogICAgICBjb25zdCBpTWluID0gdGhpcy4jZ2V0R3JpZEluZGV4KGludGVyc2VjdG9yLm1pblgsIGludGVyc2VjdG9yLm1pblkpOwogICAgICBjb25zdCBpTWF4ID0gdGhpcy4jZ2V0R3JpZEluZGV4KGludGVyc2VjdG9yLm1heFgsIGludGVyc2VjdG9yLm1heFkpOwogICAgICBjb25zdCB3ID0gKGlNYXggLSBpTWluKSAlIFNURVBTOwogICAgICBjb25zdCBoID0gTWF0aC5mbG9vcigoaU1heCAtIGlNaW4pIC8gU1RFUFMpOwogICAgICBmb3IgKGxldCBpID0gaU1pbjsgaSA8PSBpTWluICsgaCAqIFNURVBTOyBpICs9IFNURVBTKSB7CiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPD0gdzsgaisrKSB7CiAgICAgICAgICBsZXQgZXhpc3RpbmcgPSB0aGlzLiNncmlkW2kgKyBqXTsKICAgICAgICAgIGlmICghZXhpc3RpbmcpIHsKICAgICAgICAgICAgdGhpcy4jZ3JpZFtpICsgal0gPSBleGlzdGluZyA9IFtdOwogICAgICAgICAgfQogICAgICAgICAgZXhpc3RpbmcucHVzaChpbnRlcnNlY3Rvcik7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQogICNnZXRHcmlkSW5kZXgoeCwgeSkgewogICAgY29uc3QgaSA9IE1hdGguZmxvb3IoKHggLSB0aGlzLiNtaW5YKSAqIHRoaXMuI2ludlhSYXRpbyk7CiAgICBjb25zdCBqID0gTWF0aC5mbG9vcigoeSAtIHRoaXMuI21pblkpICogdGhpcy4jaW52WVJhdGlvKTsKICAgIHJldHVybiBpICsgaiAqIFNURVBTOwogIH0KICBhZGRHbHlwaCh0cmFuc2Zvcm0sIHdpZHRoLCBoZWlnaHQsIGdseXBoKSB7CiAgICBjb25zdCB4ID0gdHJhbnNmb3JtWzRdICsgd2lkdGggLyAyOwogICAgY29uc3QgeSA9IHRyYW5zZm9ybVs1XSArIGhlaWdodCAvIDI7CiAgICBpZiAoeCA8IHRoaXMuI21pblggfHwgeSA8IHRoaXMuI21pblkgfHwgeCA+IHRoaXMuI21heFggfHwgeSA+IHRoaXMuI21heFkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgaW50ZXJzZWN0b3JzID0gdGhpcy4jZ3JpZFt0aGlzLiNnZXRHcmlkSW5kZXgoeCwgeSldOwogICAgaWYgKCFpbnRlcnNlY3RvcnMpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgZm9yIChjb25zdCBpbnRlcnNlY3RvciBvZiBpbnRlcnNlY3RvcnMpIHsKICAgICAgaW50ZXJzZWN0b3IuYWRkR2x5cGgoeCwgeSwgZ2x5cGgpOwogICAgfQogIH0KICBhZGRFeHRyYUNoYXIoY2hhcikgewogICAgZm9yIChjb25zdCBpbnRlcnNlY3RvciBvZiB0aGlzLiNpbnRlcnNlY3RvcnMpIHsKICAgICAgaW50ZXJzZWN0b3IuYWRkRXh0cmFDaGFyKGNoYXIpOwogICAgfQogIH0KICBzZXRUZXh0KCkgewogICAgZm9yIChjb25zdCBpbnRlcnNlY3RvciBvZiB0aGlzLiNpbnRlcnNlY3RvcnMpIHsKICAgICAgaW50ZXJzZWN0b3Iuc2V0VGV4dCgpOwogICAgfQogIH0KfQoKOy8vIC4vc3JjL2NvcmUvY2FsY3VsYXRlX3NoYV9vdGhlci5qcwoKY2xhc3MgV29yZDY0IHsKICBjb25zdHJ1Y3RvcihoaWdoSW50ZWdlciwgbG93SW50ZWdlcikgewogICAgdGhpcy5oaWdoID0gaGlnaEludGVnZXIgfCAwOwogICAgdGhpcy5sb3cgPSBsb3dJbnRlZ2VyIHwgMDsKICB9CiAgYW5kKHdvcmQpIHsKICAgIHRoaXMuaGlnaCAmPSB3b3JkLmhpZ2g7CiAgICB0aGlzLmxvdyAmPSB3b3JkLmxvdzsKICB9CiAgeG9yKHdvcmQpIHsKICAgIHRoaXMuaGlnaCBePSB3b3JkLmhpZ2g7CiAgICB0aGlzLmxvdyBePSB3b3JkLmxvdzsKICB9CiAgc2hpZnRSaWdodChwbGFjZXMpIHsKICAgIGlmIChwbGFjZXMgPj0gMzIpIHsKICAgICAgdGhpcy5sb3cgPSB0aGlzLmhpZ2ggPj4+IHBsYWNlcyAtIDMyIHwgMDsKICAgICAgdGhpcy5oaWdoID0gMDsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMubG93ID0gdGhpcy5sb3cgPj4+IHBsYWNlcyB8IHRoaXMuaGlnaCA8PCAzMiAtIHBsYWNlczsKICAgICAgdGhpcy5oaWdoID0gdGhpcy5oaWdoID4+PiBwbGFjZXMgfCAwOwogICAgfQogIH0KICByb3RhdGVSaWdodChwbGFjZXMpIHsKICAgIGxldCBsb3csIGhpZ2g7CiAgICBpZiAocGxhY2VzICYgMzIpIHsKICAgICAgaGlnaCA9IHRoaXMubG93OwogICAgICBsb3cgPSB0aGlzLmhpZ2g7CiAgICB9IGVsc2UgewogICAgICBsb3cgPSB0aGlzLmxvdzsKICAgICAgaGlnaCA9IHRoaXMuaGlnaDsKICAgIH0KICAgIHBsYWNlcyAmPSAzMTsKICAgIHRoaXMubG93ID0gbG93ID4+PiBwbGFjZXMgfCBoaWdoIDw8IDMyIC0gcGxhY2VzOwogICAgdGhpcy5oaWdoID0gaGlnaCA+Pj4gcGxhY2VzIHwgbG93IDw8IDMyIC0gcGxhY2VzOwogIH0KICBub3QoKSB7CiAgICB0aGlzLmhpZ2ggPSB+dGhpcy5oaWdoOwogICAgdGhpcy5sb3cgPSB+dGhpcy5sb3c7CiAgfQogIGFkZCh3b3JkKSB7CiAgICBjb25zdCBsb3dBZGQgPSAodGhpcy5sb3cgPj4+IDApICsgKHdvcmQubG93ID4+PiAwKTsKICAgIGxldCBoaWdoQWRkID0gKHRoaXMuaGlnaCA+Pj4gMCkgKyAod29yZC5oaWdoID4+PiAwKTsKICAgIGlmIChsb3dBZGQgPiAweGZmZmZmZmZmKSB7CiAgICAgIGhpZ2hBZGQgKz0gMTsKICAgIH0KICAgIHRoaXMubG93ID0gbG93QWRkIHwgMDsKICAgIHRoaXMuaGlnaCA9IGhpZ2hBZGQgfCAwOwogIH0KICBjb3B5VG8oYnl0ZXMsIG9mZnNldCkgewogICAgYnl0ZXNbb2Zmc2V0XSA9IHRoaXMuaGlnaCA+Pj4gMjQgJiAweGZmOwogICAgYnl0ZXNbb2Zmc2V0ICsgMV0gPSB0aGlzLmhpZ2ggPj4gMTYgJiAweGZmOwogICAgYnl0ZXNbb2Zmc2V0ICsgMl0gPSB0aGlzLmhpZ2ggPj4gOCAmIDB4ZmY7CiAgICBieXRlc1tvZmZzZXQgKyAzXSA9IHRoaXMuaGlnaCAmIDB4ZmY7CiAgICBieXRlc1tvZmZzZXQgKyA0XSA9IHRoaXMubG93ID4+PiAyNCAmIDB4ZmY7CiAgICBieXRlc1tvZmZzZXQgKyA1XSA9IHRoaXMubG93ID4+IDE2ICYgMHhmZjsKICAgIGJ5dGVzW29mZnNldCArIDZdID0gdGhpcy5sb3cgPj4gOCAmIDB4ZmY7CiAgICBieXRlc1tvZmZzZXQgKyA3XSA9IHRoaXMubG93ICYgMHhmZjsKICB9CiAgYXNzaWduKHdvcmQpIHsKICAgIHRoaXMuaGlnaCA9IHdvcmQuaGlnaDsKICAgIHRoaXMubG93ID0gd29yZC5sb3c7CiAgfQp9CmNvbnN0IGNhbGN1bGF0ZV9zaGFfb3RoZXJfUEFSQU1TID0gewogIGdldCBrKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiayIsIFtuZXcgV29yZDY0KDB4NDI4YTJmOTgsIDB4ZDcyOGFlMjIpLCBuZXcgV29yZDY0KDB4NzEzNzQ0OTEsIDB4MjNlZjY1Y2QpLCBuZXcgV29yZDY0KDB4YjVjMGZiY2YsIDB4ZWM0ZDNiMmYpLCBuZXcgV29yZDY0KDB4ZTliNWRiYTUsIDB4ODE4OWRiYmMpLCBuZXcgV29yZDY0KDB4Mzk1NmMyNWIsIDB4ZjM0OGI1MzgpLCBuZXcgV29yZDY0KDB4NTlmMTExZjEsIDB4YjYwNWQwMTkpLCBuZXcgV29yZDY0KDB4OTIzZjgyYTQsIDB4YWYxOTRmOWIpLCBuZXcgV29yZDY0KDB4YWIxYzVlZDUsIDB4ZGE2ZDgxMTgpLCBuZXcgV29yZDY0KDB4ZDgwN2FhOTgsIDB4YTMwMzAyNDIpLCBuZXcgV29yZDY0KDB4MTI4MzViMDEsIDB4NDU3MDZmYmUpLCBuZXcgV29yZDY0KDB4MjQzMTg1YmUsIDB4NGVlNGIyOGMpLCBuZXcgV29yZDY0KDB4NTUwYzdkYzMsIDB4ZDVmZmI0ZTIpLCBuZXcgV29yZDY0KDB4NzJiZTVkNzQsIDB4ZjI3Yjg5NmYpLCBuZXcgV29yZDY0KDB4ODBkZWIxZmUsIDB4M2IxNjk2YjEpLCBuZXcgV29yZDY0KDB4OWJkYzA2YTcsIDB4MjVjNzEyMzUpLCBuZXcgV29yZDY0KDB4YzE5YmYxNzQsIDB4Y2Y2OTI2OTQpLCBuZXcgV29yZDY0KDB4ZTQ5YjY5YzEsIDB4OWVmMTRhZDIpLCBuZXcgV29yZDY0KDB4ZWZiZTQ3ODYsIDB4Mzg0ZjI1ZTMpLCBuZXcgV29yZDY0KDB4MGZjMTlkYzYsIDB4OGI4Y2Q1YjUpLCBuZXcgV29yZDY0KDB4MjQwY2ExY2MsIDB4NzdhYzljNjUpLCBuZXcgV29yZDY0KDB4MmRlOTJjNmYsIDB4NTkyYjAyNzUpLCBuZXcgV29yZDY0KDB4NGE3NDg0YWEsIDB4NmVhNmU0ODMpLCBuZXcgV29yZDY0KDB4NWNiMGE5ZGMsIDB4YmQ0MWZiZDQpLCBuZXcgV29yZDY0KDB4NzZmOTg4ZGEsIDB4ODMxMTUzYjUpLCBuZXcgV29yZDY0KDB4OTgzZTUxNTIsIDB4ZWU2NmRmYWIpLCBuZXcgV29yZDY0KDB4YTgzMWM2NmQsIDB4MmRiNDMyMTApLCBuZXcgV29yZDY0KDB4YjAwMzI3YzgsIDB4OThmYjIxM2YpLCBuZXcgV29yZDY0KDB4YmY1OTdmYzcsIDB4YmVlZjBlZTQpLCBuZXcgV29yZDY0KDB4YzZlMDBiZjMsIDB4M2RhODhmYzIpLCBuZXcgV29yZDY0KDB4ZDVhNzkxNDcsIDB4OTMwYWE3MjUpLCBuZXcgV29yZDY0KDB4MDZjYTYzNTEsIDB4ZTAwMzgyNmYpLCBuZXcgV29yZDY0KDB4MTQyOTI5NjcsIDB4MGEwZTZlNzApLCBuZXcgV29yZDY0KDB4MjdiNzBhODUsIDB4NDZkMjJmZmMpLCBuZXcgV29yZDY0KDB4MmUxYjIxMzgsIDB4NWMyNmM5MjYpLCBuZXcgV29yZDY0KDB4NGQyYzZkZmMsIDB4NWFjNDJhZWQpLCBuZXcgV29yZDY0KDB4NTMzODBkMTMsIDB4OWQ5NWIzZGYpLCBuZXcgV29yZDY0KDB4NjUwYTczNTQsIDB4OGJhZjYzZGUpLCBuZXcgV29yZDY0KDB4NzY2YTBhYmIsIDB4M2M3N2IyYTgpLCBuZXcgV29yZDY0KDB4ODFjMmM5MmUsIDB4NDdlZGFlZTYpLCBuZXcgV29yZDY0KDB4OTI3MjJjODUsIDB4MTQ4MjM1M2IpLCBuZXcgV29yZDY0KDB4YTJiZmU4YTEsIDB4NGNmMTAzNjQpLCBuZXcgV29yZDY0KDB4YTgxYTY2NGIsIDB4YmM0MjMwMDEpLCBuZXcgV29yZDY0KDB4YzI0YjhiNzAsIDB4ZDBmODk3OTEpLCBuZXcgV29yZDY0KDB4Yzc2YzUxYTMsIDB4MDY1NGJlMzApLCBuZXcgV29yZDY0KDB4ZDE5MmU4MTksIDB4ZDZlZjUyMTgpLCBuZXcgV29yZDY0KDB4ZDY5OTA2MjQsIDB4NTU2NWE5MTApLCBuZXcgV29yZDY0KDB4ZjQwZTM1ODUsIDB4NTc3MTIwMmEpLCBuZXcgV29yZDY0KDB4MTA2YWEwNzAsIDB4MzJiYmQxYjgpLCBuZXcgV29yZDY0KDB4MTlhNGMxMTYsIDB4YjhkMmQwYzgpLCBuZXcgV29yZDY0KDB4MWUzNzZjMDgsIDB4NTE0MWFiNTMpLCBuZXcgV29yZDY0KDB4Mjc0ODc3NGMsIDB4ZGY4ZWViOTkpLCBuZXcgV29yZDY0KDB4MzRiMGJjYjUsIDB4ZTE5YjQ4YTgpLCBuZXcgV29yZDY0KDB4MzkxYzBjYjMsIDB4YzVjOTVhNjMpLCBuZXcgV29yZDY0KDB4NGVkOGFhNGEsIDB4ZTM0MThhY2IpLCBuZXcgV29yZDY0KDB4NWI5Y2NhNGYsIDB4Nzc2M2UzNzMpLCBuZXcgV29yZDY0KDB4NjgyZTZmZjMsIDB4ZDZiMmI4YTMpLCBuZXcgV29yZDY0KDB4NzQ4ZjgyZWUsIDB4NWRlZmIyZmMpLCBuZXcgV29yZDY0KDB4NzhhNTYzNmYsIDB4NDMxNzJmNjApLCBuZXcgV29yZDY0KDB4ODRjODc4MTQsIDB4YTFmMGFiNzIpLCBuZXcgV29yZDY0KDB4OGNjNzAyMDgsIDB4MWE2NDM5ZWMpLCBuZXcgV29yZDY0KDB4OTBiZWZmZmEsIDB4MjM2MzFlMjgpLCBuZXcgV29yZDY0KDB4YTQ1MDZjZWIsIDB4ZGU4MmJkZTkpLCBuZXcgV29yZDY0KDB4YmVmOWEzZjcsIDB4YjJjNjc5MTUpLCBuZXcgV29yZDY0KDB4YzY3MTc4ZjIsIDB4ZTM3MjUzMmIpLCBuZXcgV29yZDY0KDB4Y2EyNzNlY2UsIDB4ZWEyNjYxOWMpLCBuZXcgV29yZDY0KDB4ZDE4NmI4YzcsIDB4MjFjMGMyMDcpLCBuZXcgV29yZDY0KDB4ZWFkYTdkZDYsIDB4Y2RlMGViMWUpLCBuZXcgV29yZDY0KDB4ZjU3ZDRmN2YsIDB4ZWU2ZWQxNzgpLCBuZXcgV29yZDY0KDB4MDZmMDY3YWEsIDB4NzIxNzZmYmEpLCBuZXcgV29yZDY0KDB4MGE2MzdkYzUsIDB4YTJjODk4YTYpLCBuZXcgV29yZDY0KDB4MTEzZjk4MDQsIDB4YmVmOTBkYWUpLCBuZXcgV29yZDY0KDB4MWI3MTBiMzUsIDB4MTMxYzQ3MWIpLCBuZXcgV29yZDY0KDB4MjhkYjc3ZjUsIDB4MjMwNDdkODQpLCBuZXcgV29yZDY0KDB4MzJjYWFiN2IsIDB4NDBjNzI0OTMpLCBuZXcgV29yZDY0KDB4M2M5ZWJlMGEsIDB4MTVjOWJlYmMpLCBuZXcgV29yZDY0KDB4NDMxZDY3YzQsIDB4OWMxMDBkNGMpLCBuZXcgV29yZDY0KDB4NGNjNWQ0YmUsIDB4Y2IzZTQyYjYpLCBuZXcgV29yZDY0KDB4NTk3ZjI5OWMsIDB4ZmM2NTdlMmEpLCBuZXcgV29yZDY0KDB4NWZjYjZmYWIsIDB4M2FkNmZhZWMpLCBuZXcgV29yZDY0KDB4NmM0NDE5OGMsIDB4NGE0NzU4MTcpXSk7CiAgfQp9OwpmdW5jdGlvbiBjaChyZXN1bHQsIHgsIHksIHosIHRtcCkgewogIHJlc3VsdC5hc3NpZ24oeCk7CiAgcmVzdWx0LmFuZCh5KTsKICB0bXAuYXNzaWduKHgpOwogIHRtcC5ub3QoKTsKICB0bXAuYW5kKHopOwogIHJlc3VsdC54b3IodG1wKTsKfQpmdW5jdGlvbiBtYWoocmVzdWx0LCB4LCB5LCB6LCB0bXApIHsKICByZXN1bHQuYXNzaWduKHgpOwogIHJlc3VsdC5hbmQoeSk7CiAgdG1wLmFzc2lnbih4KTsKICB0bXAuYW5kKHopOwogIHJlc3VsdC54b3IodG1wKTsKICB0bXAuYXNzaWduKHkpOwogIHRtcC5hbmQoeik7CiAgcmVzdWx0Lnhvcih0bXApOwp9CmZ1bmN0aW9uIHNpZ21hKHJlc3VsdCwgeCwgdG1wKSB7CiAgcmVzdWx0LmFzc2lnbih4KTsKICByZXN1bHQucm90YXRlUmlnaHQoMjgpOwogIHRtcC5hc3NpZ24oeCk7CiAgdG1wLnJvdGF0ZVJpZ2h0KDM0KTsKICByZXN1bHQueG9yKHRtcCk7CiAgdG1wLmFzc2lnbih4KTsKICB0bXAucm90YXRlUmlnaHQoMzkpOwogIHJlc3VsdC54b3IodG1wKTsKfQpmdW5jdGlvbiBzaWdtYVByaW1lKHJlc3VsdCwgeCwgdG1wKSB7CiAgcmVzdWx0LmFzc2lnbih4KTsKICByZXN1bHQucm90YXRlUmlnaHQoMTQpOwogIHRtcC5hc3NpZ24oeCk7CiAgdG1wLnJvdGF0ZVJpZ2h0KDE4KTsKICByZXN1bHQueG9yKHRtcCk7CiAgdG1wLmFzc2lnbih4KTsKICB0bXAucm90YXRlUmlnaHQoNDEpOwogIHJlc3VsdC54b3IodG1wKTsKfQpmdW5jdGlvbiBsaXR0bGVTaWdtYShyZXN1bHQsIHgsIHRtcCkgewogIHJlc3VsdC5hc3NpZ24oeCk7CiAgcmVzdWx0LnJvdGF0ZVJpZ2h0KDEpOwogIHRtcC5hc3NpZ24oeCk7CiAgdG1wLnJvdGF0ZVJpZ2h0KDgpOwogIHJlc3VsdC54b3IodG1wKTsKICB0bXAuYXNzaWduKHgpOwogIHRtcC5zaGlmdFJpZ2h0KDcpOwogIHJlc3VsdC54b3IodG1wKTsKfQpmdW5jdGlvbiBsaXR0bGVTaWdtYVByaW1lKHJlc3VsdCwgeCwgdG1wKSB7CiAgcmVzdWx0LmFzc2lnbih4KTsKICByZXN1bHQucm90YXRlUmlnaHQoMTkpOwogIHRtcC5hc3NpZ24oeCk7CiAgdG1wLnJvdGF0ZVJpZ2h0KDYxKTsKICByZXN1bHQueG9yKHRtcCk7CiAgdG1wLmFzc2lnbih4KTsKICB0bXAuc2hpZnRSaWdodCg2KTsKICByZXN1bHQueG9yKHRtcCk7Cn0KZnVuY3Rpb24gY2FsY3VsYXRlU0hBNTEyKGRhdGEsIG9mZnNldCwgbGVuZ3RoLCBtb2RlMzg0ID0gZmFsc2UpIHsKICBsZXQgaDAsIGgxLCBoMiwgaDMsIGg0LCBoNSwgaDYsIGg3OwogIGlmICghbW9kZTM4NCkgewogICAgaDAgPSBuZXcgV29yZDY0KDB4NmEwOWU2NjcsIDB4ZjNiY2M5MDgpOwogICAgaDEgPSBuZXcgV29yZDY0KDB4YmI2N2FlODUsIDB4ODRjYWE3M2IpOwogICAgaDIgPSBuZXcgV29yZDY0KDB4M2M2ZWYzNzIsIDB4ZmU5NGY4MmIpOwogICAgaDMgPSBuZXcgV29yZDY0KDB4YTU0ZmY1M2EsIDB4NWYxZDM2ZjEpOwogICAgaDQgPSBuZXcgV29yZDY0KDB4NTEwZTUyN2YsIDB4YWRlNjgyZDEpOwogICAgaDUgPSBuZXcgV29yZDY0KDB4OWIwNTY4OGMsIDB4MmIzZTZjMWYpOwogICAgaDYgPSBuZXcgV29yZDY0KDB4MWY4M2Q5YWIsIDB4ZmI0MWJkNmIpOwogICAgaDcgPSBuZXcgV29yZDY0KDB4NWJlMGNkMTksIDB4MTM3ZTIxNzkpOwogIH0gZWxzZSB7CiAgICBoMCA9IG5ldyBXb3JkNjQoMHhjYmJiOWQ1ZCwgMHhjMTA1OWVkOCk7CiAgICBoMSA9IG5ldyBXb3JkNjQoMHg2MjlhMjkyYSwgMHgzNjdjZDUwNyk7CiAgICBoMiA9IG5ldyBXb3JkNjQoMHg5MTU5MDE1YSwgMHgzMDcwZGQxNyk7CiAgICBoMyA9IG5ldyBXb3JkNjQoMHgxNTJmZWNkOCwgMHhmNzBlNTkzOSk7CiAgICBoNCA9IG5ldyBXb3JkNjQoMHg2NzMzMjY2NywgMHhmZmMwMGIzMSk7CiAgICBoNSA9IG5ldyBXb3JkNjQoMHg4ZWI0NGE4NywgMHg2ODU4MTUxMSk7CiAgICBoNiA9IG5ldyBXb3JkNjQoMHhkYjBjMmUwZCwgMHg2NGY5OGZhNyk7CiAgICBoNyA9IG5ldyBXb3JkNjQoMHg0N2I1NDgxZCwgMHhiZWZhNGZhNCk7CiAgfQogIGNvbnN0IHBhZGRlZExlbmd0aCA9IE1hdGguY2VpbCgobGVuZ3RoICsgMTcpIC8gMTI4KSAqIDEyODsKICBjb25zdCBwYWRkZWQgPSBuZXcgVWludDhBcnJheShwYWRkZWRMZW5ndGgpOwogIGxldCBpLCBqOwogIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgcGFkZGVkW2ldID0gZGF0YVtvZmZzZXQrK107CiAgfQogIHBhZGRlZFtpKytdID0gMHg4MDsKICBjb25zdCBuID0gcGFkZGVkTGVuZ3RoIC0gMTY7CiAgaWYgKGkgPCBuKSB7CiAgICBpID0gbjsKICB9CiAgaSArPSAxMTsKICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+Pj4gMjkgJiAweGZmOwogIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+IDIxICYgMHhmZjsKICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+PiAxMyAmIDB4ZmY7CiAgcGFkZGVkW2krK10gPSBsZW5ndGggPj4gNSAmIDB4ZmY7CiAgcGFkZGVkW2krK10gPSBsZW5ndGggPDwgMyAmIDB4ZmY7CiAgY29uc3QgdyA9IG5ldyBBcnJheSg4MCk7CiAgZm9yIChpID0gMDsgaSA8IDgwOyBpKyspIHsKICAgIHdbaV0gPSBuZXcgV29yZDY0KDAsIDApOwogIH0KICBjb25zdCB7CiAgICBrCiAgfSA9IGNhbGN1bGF0ZV9zaGFfb3RoZXJfUEFSQU1TOwogIGxldCBhID0gbmV3IFdvcmQ2NCgwLCAwKSwKICAgIGIgPSBuZXcgV29yZDY0KDAsIDApLAogICAgYyA9IG5ldyBXb3JkNjQoMCwgMCk7CiAgbGV0IGQgPSBuZXcgV29yZDY0KDAsIDApLAogICAgZSA9IG5ldyBXb3JkNjQoMCwgMCksCiAgICBmID0gbmV3IFdvcmQ2NCgwLCAwKTsKICBsZXQgZyA9IG5ldyBXb3JkNjQoMCwgMCksCiAgICBoID0gbmV3IFdvcmQ2NCgwLCAwKTsKICBjb25zdCB0MSA9IG5ldyBXb3JkNjQoMCwgMCksCiAgICB0MiA9IG5ldyBXb3JkNjQoMCwgMCk7CiAgY29uc3QgdG1wMSA9IG5ldyBXb3JkNjQoMCwgMCksCiAgICB0bXAyID0gbmV3IFdvcmQ2NCgwLCAwKTsKICBsZXQgdG1wMzsKICBmb3IgKGkgPSAwOyBpIDwgcGFkZGVkTGVuZ3RoOykgewogICAgZm9yIChqID0gMDsgaiA8IDE2OyArK2opIHsKICAgICAgd1tqXS5oaWdoID0gcGFkZGVkW2ldIDw8IDI0IHwgcGFkZGVkW2kgKyAxXSA8PCAxNiB8IHBhZGRlZFtpICsgMl0gPDwgOCB8IHBhZGRlZFtpICsgM107CiAgICAgIHdbal0ubG93ID0gcGFkZGVkW2kgKyA0XSA8PCAyNCB8IHBhZGRlZFtpICsgNV0gPDwgMTYgfCBwYWRkZWRbaSArIDZdIDw8IDggfCBwYWRkZWRbaSArIDddOwogICAgICBpICs9IDg7CiAgICB9CiAgICBmb3IgKGogPSAxNjsgaiA8IDgwOyArK2opIHsKICAgICAgdG1wMyA9IHdbal07CiAgICAgIGxpdHRsZVNpZ21hUHJpbWUodG1wMywgd1tqIC0gMl0sIHRtcDIpOwogICAgICB0bXAzLmFkZCh3W2ogLSA3XSk7CiAgICAgIGxpdHRsZVNpZ21hKHRtcDEsIHdbaiAtIDE1XSwgdG1wMik7CiAgICAgIHRtcDMuYWRkKHRtcDEpOwogICAgICB0bXAzLmFkZCh3W2ogLSAxNl0pOwogICAgfQogICAgYS5hc3NpZ24oaDApOwogICAgYi5hc3NpZ24oaDEpOwogICAgYy5hc3NpZ24oaDIpOwogICAgZC5hc3NpZ24oaDMpOwogICAgZS5hc3NpZ24oaDQpOwogICAgZi5hc3NpZ24oaDUpOwogICAgZy5hc3NpZ24oaDYpOwogICAgaC5hc3NpZ24oaDcpOwogICAgZm9yIChqID0gMDsgaiA8IDgwOyArK2opIHsKICAgICAgdDEuYXNzaWduKGgpOwogICAgICBzaWdtYVByaW1lKHRtcDEsIGUsIHRtcDIpOwogICAgICB0MS5hZGQodG1wMSk7CiAgICAgIGNoKHRtcDEsIGUsIGYsIGcsIHRtcDIpOwogICAgICB0MS5hZGQodG1wMSk7CiAgICAgIHQxLmFkZChrW2pdKTsKICAgICAgdDEuYWRkKHdbal0pOwogICAgICBzaWdtYSh0MiwgYSwgdG1wMik7CiAgICAgIG1haih0bXAxLCBhLCBiLCBjLCB0bXAyKTsKICAgICAgdDIuYWRkKHRtcDEpOwogICAgICB0bXAzID0gaDsKICAgICAgaCA9IGc7CiAgICAgIGcgPSBmOwogICAgICBmID0gZTsKICAgICAgZC5hZGQodDEpOwogICAgICBlID0gZDsKICAgICAgZCA9IGM7CiAgICAgIGMgPSBiOwogICAgICBiID0gYTsKICAgICAgdG1wMy5hc3NpZ24odDEpOwogICAgICB0bXAzLmFkZCh0Mik7CiAgICAgIGEgPSB0bXAzOwogICAgfQogICAgaDAuYWRkKGEpOwogICAgaDEuYWRkKGIpOwogICAgaDIuYWRkKGMpOwogICAgaDMuYWRkKGQpOwogICAgaDQuYWRkKGUpOwogICAgaDUuYWRkKGYpOwogICAgaDYuYWRkKGcpOwogICAgaDcuYWRkKGgpOwogIH0KICBsZXQgcmVzdWx0OwogIGlmICghbW9kZTM4NCkgewogICAgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkoNjQpOwogICAgaDAuY29weVRvKHJlc3VsdCwgMCk7CiAgICBoMS5jb3B5VG8ocmVzdWx0LCA4KTsKICAgIGgyLmNvcHlUbyhyZXN1bHQsIDE2KTsKICAgIGgzLmNvcHlUbyhyZXN1bHQsIDI0KTsKICAgIGg0LmNvcHlUbyhyZXN1bHQsIDMyKTsKICAgIGg1LmNvcHlUbyhyZXN1bHQsIDQwKTsKICAgIGg2LmNvcHlUbyhyZXN1bHQsIDQ4KTsKICAgIGg3LmNvcHlUbyhyZXN1bHQsIDU2KTsKICB9IGVsc2UgewogICAgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkoNDgpOwogICAgaDAuY29weVRvKHJlc3VsdCwgMCk7CiAgICBoMS5jb3B5VG8ocmVzdWx0LCA4KTsKICAgIGgyLmNvcHlUbyhyZXN1bHQsIDE2KTsKICAgIGgzLmNvcHlUbyhyZXN1bHQsIDI0KTsKICAgIGg0LmNvcHlUbyhyZXN1bHQsIDMyKTsKICAgIGg1LmNvcHlUbyhyZXN1bHQsIDQwKTsKICB9CiAgcmV0dXJuIHJlc3VsdDsKfQpmdW5jdGlvbiBjYWxjdWxhdGVTSEEzODQoZGF0YSwgb2Zmc2V0LCBsZW5ndGgpIHsKICByZXR1cm4gY2FsY3VsYXRlU0hBNTEyKGRhdGEsIG9mZnNldCwgbGVuZ3RoLCB0cnVlKTsKfQoKOy8vIC4vc3JjL2NvcmUvY2FsY3VsYXRlX3NoYTI1Ni5qcwoKY29uc3QgY2FsY3VsYXRlX3NoYTI1Nl9QQVJBTVMgPSB7CiAgZ2V0IGsoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJrIiwgWzB4NDI4YTJmOTgsIDB4NzEzNzQ0OTEsIDB4YjVjMGZiY2YsIDB4ZTliNWRiYTUsIDB4Mzk1NmMyNWIsIDB4NTlmMTExZjEsIDB4OTIzZjgyYTQsIDB4YWIxYzVlZDUsIDB4ZDgwN2FhOTgsIDB4MTI4MzViMDEsIDB4MjQzMTg1YmUsIDB4NTUwYzdkYzMsIDB4NzJiZTVkNzQsIDB4ODBkZWIxZmUsIDB4OWJkYzA2YTcsIDB4YzE5YmYxNzQsIDB4ZTQ5YjY5YzEsIDB4ZWZiZTQ3ODYsIDB4MGZjMTlkYzYsIDB4MjQwY2ExY2MsIDB4MmRlOTJjNmYsIDB4NGE3NDg0YWEsIDB4NWNiMGE5ZGMsIDB4NzZmOTg4ZGEsIDB4OTgzZTUxNTIsIDB4YTgzMWM2NmQsIDB4YjAwMzI3YzgsIDB4YmY1OTdmYzcsIDB4YzZlMDBiZjMsIDB4ZDVhNzkxNDcsIDB4MDZjYTYzNTEsIDB4MTQyOTI5NjcsIDB4MjdiNzBhODUsIDB4MmUxYjIxMzgsIDB4NGQyYzZkZmMsIDB4NTMzODBkMTMsIDB4NjUwYTczNTQsIDB4NzY2YTBhYmIsIDB4ODFjMmM5MmUsIDB4OTI3MjJjODUsIDB4YTJiZmU4YTEsIDB4YTgxYTY2NGIsIDB4YzI0YjhiNzAsIDB4Yzc2YzUxYTMsIDB4ZDE5MmU4MTksIDB4ZDY5OTA2MjQsIDB4ZjQwZTM1ODUsIDB4MTA2YWEwNzAsIDB4MTlhNGMxMTYsIDB4MWUzNzZjMDgsIDB4Mjc0ODc3NGMsIDB4MzRiMGJjYjUsIDB4MzkxYzBjYjMsIDB4NGVkOGFhNGEsIDB4NWI5Y2NhNGYsIDB4NjgyZTZmZjMsIDB4NzQ4ZjgyZWUsIDB4NzhhNTYzNmYsIDB4ODRjODc4MTQsIDB4OGNjNzAyMDgsIDB4OTBiZWZmZmEsIDB4YTQ1MDZjZWIsIDB4YmVmOWEzZjcsIDB4YzY3MTc4ZjJdKTsKICB9Cn07CmZ1bmN0aW9uIHJvdHIoeCwgbikgewogIHJldHVybiB4ID4+PiBuIHwgeCA8PCAzMiAtIG47Cn0KZnVuY3Rpb24gY2FsY3VsYXRlX3NoYTI1Nl9jaCh4LCB5LCB6KSB7CiAgcmV0dXJuIHggJiB5IF4gfnggJiB6Owp9CmZ1bmN0aW9uIGNhbGN1bGF0ZV9zaGEyNTZfbWFqKHgsIHksIHopIHsKICByZXR1cm4geCAmIHkgXiB4ICYgeiBeIHkgJiB6Owp9CmZ1bmN0aW9uIGNhbGN1bGF0ZV9zaGEyNTZfc2lnbWEoeCkgewogIHJldHVybiByb3RyKHgsIDIpIF4gcm90cih4LCAxMykgXiByb3RyKHgsIDIyKTsKfQpmdW5jdGlvbiBjYWxjdWxhdGVfc2hhMjU2X3NpZ21hUHJpbWUoeCkgewogIHJldHVybiByb3RyKHgsIDYpIF4gcm90cih4LCAxMSkgXiByb3RyKHgsIDI1KTsKfQpmdW5jdGlvbiBjYWxjdWxhdGVfc2hhMjU2X2xpdHRsZVNpZ21hKHgpIHsKICByZXR1cm4gcm90cih4LCA3KSBeIHJvdHIoeCwgMTgpIF4geCA+Pj4gMzsKfQpmdW5jdGlvbiBjYWxjdWxhdGVfc2hhMjU2X2xpdHRsZVNpZ21hUHJpbWUoeCkgewogIHJldHVybiByb3RyKHgsIDE3KSBeIHJvdHIoeCwgMTkpIF4geCA+Pj4gMTA7Cn0KZnVuY3Rpb24gY2FsY3VsYXRlU0hBMjU2KGRhdGEsIG9mZnNldCwgbGVuZ3RoKSB7CiAgbGV0IGgwID0gMHg2YTA5ZTY2NywKICAgIGgxID0gMHhiYjY3YWU4NSwKICAgIGgyID0gMHgzYzZlZjM3MiwKICAgIGgzID0gMHhhNTRmZjUzYSwKICAgIGg0ID0gMHg1MTBlNTI3ZiwKICAgIGg1ID0gMHg5YjA1Njg4YywKICAgIGg2ID0gMHgxZjgzZDlhYiwKICAgIGg3ID0gMHg1YmUwY2QxOTsKICBjb25zdCBwYWRkZWRMZW5ndGggPSBNYXRoLmNlaWwoKGxlbmd0aCArIDkpIC8gNjQpICogNjQ7CiAgY29uc3QgcGFkZGVkID0gbmV3IFVpbnQ4QXJyYXkocGFkZGVkTGVuZ3RoKTsKICBsZXQgaSwgajsKICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgIHBhZGRlZFtpXSA9IGRhdGFbb2Zmc2V0KytdOwogIH0KICBwYWRkZWRbaSsrXSA9IDB4ODA7CiAgY29uc3QgbiA9IHBhZGRlZExlbmd0aCAtIDg7CiAgaWYgKGkgPCBuKSB7CiAgICBpID0gbjsKICB9CiAgaSArPSAzOwogIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+PiAyOSAmIDB4ZmY7CiAgcGFkZGVkW2krK10gPSBsZW5ndGggPj4gMjEgJiAweGZmOwogIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+IDEzICYgMHhmZjsKICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+PiA1ICYgMHhmZjsKICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA8PCAzICYgMHhmZjsKICBjb25zdCB3ID0gbmV3IFVpbnQzMkFycmF5KDY0KTsKICBjb25zdCB7CiAgICBrCiAgfSA9IGNhbGN1bGF0ZV9zaGEyNTZfUEFSQU1TOwogIGZvciAoaSA9IDA7IGkgPCBwYWRkZWRMZW5ndGg7KSB7CiAgICBmb3IgKGogPSAwOyBqIDwgMTY7ICsraikgewogICAgICB3W2pdID0gcGFkZGVkW2ldIDw8IDI0IHwgcGFkZGVkW2kgKyAxXSA8PCAxNiB8IHBhZGRlZFtpICsgMl0gPDwgOCB8IHBhZGRlZFtpICsgM107CiAgICAgIGkgKz0gNDsKICAgIH0KICAgIGZvciAoaiA9IDE2OyBqIDwgNjQ7ICsraikgewogICAgICB3W2pdID0gY2FsY3VsYXRlX3NoYTI1Nl9saXR0bGVTaWdtYVByaW1lKHdbaiAtIDJdKSArIHdbaiAtIDddICsgY2FsY3VsYXRlX3NoYTI1Nl9saXR0bGVTaWdtYSh3W2ogLSAxNV0pICsgd1tqIC0gMTZdIHwgMDsKICAgIH0KICAgIGxldCBhID0gaDAsCiAgICAgIGIgPSBoMSwKICAgICAgYyA9IGgyLAogICAgICBkID0gaDMsCiAgICAgIGUgPSBoNCwKICAgICAgZiA9IGg1LAogICAgICBnID0gaDYsCiAgICAgIGggPSBoNywKICAgICAgdDEsCiAgICAgIHQyOwogICAgZm9yIChqID0gMDsgaiA8IDY0OyArK2opIHsKICAgICAgdDEgPSBoICsgY2FsY3VsYXRlX3NoYTI1Nl9zaWdtYVByaW1lKGUpICsgY2FsY3VsYXRlX3NoYTI1Nl9jaChlLCBmLCBnKSArIGtbal0gKyB3W2pdOwogICAgICB0MiA9IGNhbGN1bGF0ZV9zaGEyNTZfc2lnbWEoYSkgKyBjYWxjdWxhdGVfc2hhMjU2X21haihhLCBiLCBjKTsKICAgICAgaCA9IGc7CiAgICAgIGcgPSBmOwogICAgICBmID0gZTsKICAgICAgZSA9IGQgKyB0MSB8IDA7CiAgICAgIGQgPSBjOwogICAgICBjID0gYjsKICAgICAgYiA9IGE7CiAgICAgIGEgPSB0MSArIHQyIHwgMDsKICAgIH0KICAgIGgwID0gaDAgKyBhIHwgMDsKICAgIGgxID0gaDEgKyBiIHwgMDsKICAgIGgyID0gaDIgKyBjIHwgMDsKICAgIGgzID0gaDMgKyBkIHwgMDsKICAgIGg0ID0gaDQgKyBlIHwgMDsKICAgIGg1ID0gaDUgKyBmIHwgMDsKICAgIGg2ID0gaDYgKyBnIHwgMDsKICAgIGg3ID0gaDcgKyBoIHwgMDsKICB9CiAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFtoMCA+PiAyNCAmIDB4RkYsIGgwID4+IDE2ICYgMHhGRiwgaDAgPj4gOCAmIDB4RkYsIGgwICYgMHhGRiwgaDEgPj4gMjQgJiAweEZGLCBoMSA+PiAxNiAmIDB4RkYsIGgxID4+IDggJiAweEZGLCBoMSAmIDB4RkYsIGgyID4+IDI0ICYgMHhGRiwgaDIgPj4gMTYgJiAweEZGLCBoMiA+PiA4ICYgMHhGRiwgaDIgJiAweEZGLCBoMyA+PiAyNCAmIDB4RkYsIGgzID4+IDE2ICYgMHhGRiwgaDMgPj4gOCAmIDB4RkYsIGgzICYgMHhGRiwgaDQgPj4gMjQgJiAweEZGLCBoNCA+PiAxNiAmIDB4RkYsIGg0ID4+IDggJiAweEZGLCBoNCAmIDB4RkYsIGg1ID4+IDI0ICYgMHhGRiwgaDUgPj4gMTYgJiAweEZGLCBoNSA+PiA4ICYgMHhGRiwgaDUgJiAweEZGLCBoNiA+PiAyNCAmIDB4RkYsIGg2ID4+IDE2ICYgMHhGRiwgaDYgPj4gOCAmIDB4RkYsIGg2ICYgMHhGRiwgaDcgPj4gMjQgJiAweEZGLCBoNyA+PiAxNiAmIDB4RkYsIGg3ID4+IDggJiAweEZGLCBoNyAmIDB4RkZdKTsKfQoKOy8vIC4vc3JjL2NvcmUvZGVjcnlwdF9zdHJlYW0uanMKCmNvbnN0IGNodW5rU2l6ZSA9IDUxMjsKY2xhc3MgRGVjcnlwdFN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyLCBtYXliZUxlbmd0aCwgZGVjcnlwdCkgewogICAgc3VwZXIobWF5YmVMZW5ndGgpOwogICAgdGhpcy5zdHJlYW0gPSBzdHI7CiAgICB0aGlzLmRpY3QgPSBzdHIuZGljdDsKICAgIHRoaXMuZGVjcnlwdCA9IGRlY3J5cHQ7CiAgICB0aGlzLm5leHRDaHVuayA9IG51bGw7CiAgICB0aGlzLmluaXRpYWxpemVkID0gZmFsc2U7CiAgfQogIHJlYWRCbG9jaygpIHsKICAgIGxldCBjaHVuazsKICAgIGlmICh0aGlzLmluaXRpYWxpemVkKSB7CiAgICAgIGNodW5rID0gdGhpcy5uZXh0Q2h1bms7CiAgICB9IGVsc2UgewogICAgICBjaHVuayA9IHRoaXMuc3RyZWFtLmdldEJ5dGVzKGNodW5rU2l6ZSk7CiAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlOwogICAgfQogICAgaWYgKCFjaHVuaz8ubGVuZ3RoKSB7CiAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5uZXh0Q2h1bmsgPSB0aGlzLnN0cmVhbS5nZXRCeXRlcyhjaHVua1NpemUpOwogICAgY29uc3QgaGFzTW9yZURhdGEgPSB0aGlzLm5leHRDaHVuaz8ubGVuZ3RoID4gMDsKICAgIGNvbnN0IGRlY3J5cHQgPSB0aGlzLmRlY3J5cHQ7CiAgICBjaHVuayA9IGRlY3J5cHQoY2h1bmssICFoYXNNb3JlRGF0YSk7CiAgICBjb25zdCBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlckxlbmd0aCwKICAgICAgbmV3TGVuZ3RoID0gYnVmZmVyTGVuZ3RoICsgY2h1bmsubGVuZ3RoLAogICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihuZXdMZW5ndGgpOwogICAgYnVmZmVyLnNldChjaHVuaywgYnVmZmVyTGVuZ3RoKTsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gbmV3TGVuZ3RoOwogIH0KICBnZXRPcmlnaW5hbFN0cmVhbSgpIHsKICAgIHJldHVybiB0aGlzOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvY3J5cHRvLmpzCgoKCgoKCmNsYXNzIEFSQ0ZvdXJDaXBoZXIgewogIGNvbnN0cnVjdG9yKGtleSkgewogICAgdGhpcy5hID0gMDsKICAgIHRoaXMuYiA9IDA7CiAgICBjb25zdCBzID0gbmV3IFVpbnQ4QXJyYXkoMjU2KTsKICAgIGNvbnN0IGtleUxlbmd0aCA9IGtleS5sZW5ndGg7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgKytpKSB7CiAgICAgIHNbaV0gPSBpOwogICAgfQogICAgZm9yIChsZXQgaSA9IDAsIGogPSAwOyBpIDwgMjU2OyArK2kpIHsKICAgICAgY29uc3QgdG1wID0gc1tpXTsKICAgICAgaiA9IGogKyB0bXAgKyBrZXlbaSAlIGtleUxlbmd0aF0gJiAweGZmOwogICAgICBzW2ldID0gc1tqXTsKICAgICAgc1tqXSA9IHRtcDsKICAgIH0KICAgIHRoaXMucyA9IHM7CiAgfQogIGVuY3J5cHRCbG9jayhkYXRhKSB7CiAgICBsZXQgYSA9IHRoaXMuYSwKICAgICAgYiA9IHRoaXMuYjsKICAgIGNvbnN0IHMgPSB0aGlzLnM7CiAgICBjb25zdCBuID0gZGF0YS5sZW5ndGg7CiAgICBjb25zdCBvdXRwdXQgPSBuZXcgVWludDhBcnJheShuKTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgKytpKSB7CiAgICAgIGEgPSBhICsgMSAmIDB4ZmY7CiAgICAgIGNvbnN0IHRtcCA9IHNbYV07CiAgICAgIGIgPSBiICsgdG1wICYgMHhmZjsKICAgICAgY29uc3QgdG1wMiA9IHNbYl07CiAgICAgIHNbYV0gPSB0bXAyOwogICAgICBzW2JdID0gdG1wOwogICAgICBvdXRwdXRbaV0gPSBkYXRhW2ldIF4gc1t0bXAgKyB0bXAyICYgMHhmZl07CiAgICB9CiAgICB0aGlzLmEgPSBhOwogICAgdGhpcy5iID0gYjsKICAgIHJldHVybiBvdXRwdXQ7CiAgfQogIGRlY3J5cHRCbG9jayhkYXRhKSB7CiAgICByZXR1cm4gdGhpcy5lbmNyeXB0QmxvY2soZGF0YSk7CiAgfQogIGVuY3J5cHQoZGF0YSkgewogICAgcmV0dXJuIHRoaXMuZW5jcnlwdEJsb2NrKGRhdGEpOwogIH0KfQpjbGFzcyBOdWxsQ2lwaGVyIHsKICBkZWNyeXB0QmxvY2soZGF0YSkgewogICAgcmV0dXJuIGRhdGE7CiAgfQogIGVuY3J5cHQoZGF0YSkgewogICAgcmV0dXJuIGRhdGE7CiAgfQp9CmNsYXNzIEFFU0Jhc2VDaXBoZXIgewogIF9zID0gbmV3IFVpbnQ4QXJyYXkoWzB4NjMsIDB4N2MsIDB4NzcsIDB4N2IsIDB4ZjIsIDB4NmIsIDB4NmYsIDB4YzUsIDB4MzAsIDB4MDEsIDB4NjcsIDB4MmIsIDB4ZmUsIDB4ZDcsIDB4YWIsIDB4NzYsIDB4Y2EsIDB4ODIsIDB4YzksIDB4N2QsIDB4ZmEsIDB4NTksIDB4NDcsIDB4ZjAsIDB4YWQsIDB4ZDQsIDB4YTIsIDB4YWYsIDB4OWMsIDB4YTQsIDB4NzIsIDB4YzAsIDB4YjcsIDB4ZmQsIDB4OTMsIDB4MjYsIDB4MzYsIDB4M2YsIDB4ZjcsIDB4Y2MsIDB4MzQsIDB4YTUsIDB4ZTUsIDB4ZjEsIDB4NzEsIDB4ZDgsIDB4MzEsIDB4MTUsIDB4MDQsIDB4YzcsIDB4MjMsIDB4YzMsIDB4MTgsIDB4OTYsIDB4MDUsIDB4OWEsIDB4MDcsIDB4MTIsIDB4ODAsIDB4ZTIsIDB4ZWIsIDB4MjcsIDB4YjIsIDB4NzUsIDB4MDksIDB4ODMsIDB4MmMsIDB4MWEsIDB4MWIsIDB4NmUsIDB4NWEsIDB4YTAsIDB4NTIsIDB4M2IsIDB4ZDYsIDB4YjMsIDB4MjksIDB4ZTMsIDB4MmYsIDB4ODQsIDB4NTMsIDB4ZDEsIDB4MDAsIDB4ZWQsIDB4MjAsIDB4ZmMsIDB4YjEsIDB4NWIsIDB4NmEsIDB4Y2IsIDB4YmUsIDB4MzksIDB4NGEsIDB4NGMsIDB4NTgsIDB4Y2YsIDB4ZDAsIDB4ZWYsIDB4YWEsIDB4ZmIsIDB4NDMsIDB4NGQsIDB4MzMsIDB4ODUsIDB4NDUsIDB4ZjksIDB4MDIsIDB4N2YsIDB4NTAsIDB4M2MsIDB4OWYsIDB4YTgsIDB4NTEsIDB4YTMsIDB4NDAsIDB4OGYsIDB4OTIsIDB4OWQsIDB4MzgsIDB4ZjUsIDB4YmMsIDB4YjYsIDB4ZGEsIDB4MjEsIDB4MTAsIDB4ZmYsIDB4ZjMsIDB4ZDIsIDB4Y2QsIDB4MGMsIDB4MTMsIDB4ZWMsIDB4NWYsIDB4OTcsIDB4NDQsIDB4MTcsIDB4YzQsIDB4YTcsIDB4N2UsIDB4M2QsIDB4NjQsIDB4NWQsIDB4MTksIDB4NzMsIDB4NjAsIDB4ODEsIDB4NGYsIDB4ZGMsIDB4MjIsIDB4MmEsIDB4OTAsIDB4ODgsIDB4NDYsIDB4ZWUsIDB4YjgsIDB4MTQsIDB4ZGUsIDB4NWUsIDB4MGIsIDB4ZGIsIDB4ZTAsIDB4MzIsIDB4M2EsIDB4MGEsIDB4NDksIDB4MDYsIDB4MjQsIDB4NWMsIDB4YzIsIDB4ZDMsIDB4YWMsIDB4NjIsIDB4OTEsIDB4OTUsIDB4ZTQsIDB4NzksIDB4ZTcsIDB4YzgsIDB4MzcsIDB4NmQsIDB4OGQsIDB4ZDUsIDB4NGUsIDB4YTksIDB4NmMsIDB4NTYsIDB4ZjQsIDB4ZWEsIDB4NjUsIDB4N2EsIDB4YWUsIDB4MDgsIDB4YmEsIDB4NzgsIDB4MjUsIDB4MmUsIDB4MWMsIDB4YTYsIDB4YjQsIDB4YzYsIDB4ZTgsIDB4ZGQsIDB4NzQsIDB4MWYsIDB4NGIsIDB4YmQsIDB4OGIsIDB4OGEsIDB4NzAsIDB4M2UsIDB4YjUsIDB4NjYsIDB4NDgsIDB4MDMsIDB4ZjYsIDB4MGUsIDB4NjEsIDB4MzUsIDB4NTcsIDB4YjksIDB4ODYsIDB4YzEsIDB4MWQsIDB4OWUsIDB4ZTEsIDB4ZjgsIDB4OTgsIDB4MTEsIDB4NjksIDB4ZDksIDB4OGUsIDB4OTQsIDB4OWIsIDB4MWUsIDB4ODcsIDB4ZTksIDB4Y2UsIDB4NTUsIDB4MjgsIDB4ZGYsIDB4OGMsIDB4YTEsIDB4ODksIDB4MGQsIDB4YmYsIDB4ZTYsIDB4NDIsIDB4NjgsIDB4NDEsIDB4OTksIDB4MmQsIDB4MGYsIDB4YjAsIDB4NTQsIDB4YmIsIDB4MTZdKTsKICBfaW52X3MgPSBuZXcgVWludDhBcnJheShbMHg1MiwgMHgwOSwgMHg2YSwgMHhkNSwgMHgzMCwgMHgzNiwgMHhhNSwgMHgzOCwgMHhiZiwgMHg0MCwgMHhhMywgMHg5ZSwgMHg4MSwgMHhmMywgMHhkNywgMHhmYiwgMHg3YywgMHhlMywgMHgzOSwgMHg4MiwgMHg5YiwgMHgyZiwgMHhmZiwgMHg4NywgMHgzNCwgMHg4ZSwgMHg0MywgMHg0NCwgMHhjNCwgMHhkZSwgMHhlOSwgMHhjYiwgMHg1NCwgMHg3YiwgMHg5NCwgMHgzMiwgMHhhNiwgMHhjMiwgMHgyMywgMHgzZCwgMHhlZSwgMHg0YywgMHg5NSwgMHgwYiwgMHg0MiwgMHhmYSwgMHhjMywgMHg0ZSwgMHgwOCwgMHgyZSwgMHhhMSwgMHg2NiwgMHgyOCwgMHhkOSwgMHgyNCwgMHhiMiwgMHg3NiwgMHg1YiwgMHhhMiwgMHg0OSwgMHg2ZCwgMHg4YiwgMHhkMSwgMHgyNSwgMHg3MiwgMHhmOCwgMHhmNiwgMHg2NCwgMHg4NiwgMHg2OCwgMHg5OCwgMHgxNiwgMHhkNCwgMHhhNCwgMHg1YywgMHhjYywgMHg1ZCwgMHg2NSwgMHhiNiwgMHg5MiwgMHg2YywgMHg3MCwgMHg0OCwgMHg1MCwgMHhmZCwgMHhlZCwgMHhiOSwgMHhkYSwgMHg1ZSwgMHgxNSwgMHg0NiwgMHg1NywgMHhhNywgMHg4ZCwgMHg5ZCwgMHg4NCwgMHg5MCwgMHhkOCwgMHhhYiwgMHgwMCwgMHg4YywgMHhiYywgMHhkMywgMHgwYSwgMHhmNywgMHhlNCwgMHg1OCwgMHgwNSwgMHhiOCwgMHhiMywgMHg0NSwgMHgwNiwgMHhkMCwgMHgyYywgMHgxZSwgMHg4ZiwgMHhjYSwgMHgzZiwgMHgwZiwgMHgwMiwgMHhjMSwgMHhhZiwgMHhiZCwgMHgwMywgMHgwMSwgMHgxMywgMHg4YSwgMHg2YiwgMHgzYSwgMHg5MSwgMHgxMSwgMHg0MSwgMHg0ZiwgMHg2NywgMHhkYywgMHhlYSwgMHg5NywgMHhmMiwgMHhjZiwgMHhjZSwgMHhmMCwgMHhiNCwgMHhlNiwgMHg3MywgMHg5NiwgMHhhYywgMHg3NCwgMHgyMiwgMHhlNywgMHhhZCwgMHgzNSwgMHg4NSwgMHhlMiwgMHhmOSwgMHgzNywgMHhlOCwgMHgxYywgMHg3NSwgMHhkZiwgMHg2ZSwgMHg0NywgMHhmMSwgMHgxYSwgMHg3MSwgMHgxZCwgMHgyOSwgMHhjNSwgMHg4OSwgMHg2ZiwgMHhiNywgMHg2MiwgMHgwZSwgMHhhYSwgMHgxOCwgMHhiZSwgMHgxYiwgMHhmYywgMHg1NiwgMHgzZSwgMHg0YiwgMHhjNiwgMHhkMiwgMHg3OSwgMHgyMCwgMHg5YSwgMHhkYiwgMHhjMCwgMHhmZSwgMHg3OCwgMHhjZCwgMHg1YSwgMHhmNCwgMHgxZiwgMHhkZCwgMHhhOCwgMHgzMywgMHg4OCwgMHgwNywgMHhjNywgMHgzMSwgMHhiMSwgMHgxMiwgMHgxMCwgMHg1OSwgMHgyNywgMHg4MCwgMHhlYywgMHg1ZiwgMHg2MCwgMHg1MSwgMHg3ZiwgMHhhOSwgMHgxOSwgMHhiNSwgMHg0YSwgMHgwZCwgMHgyZCwgMHhlNSwgMHg3YSwgMHg5ZiwgMHg5MywgMHhjOSwgMHg5YywgMHhlZiwgMHhhMCwgMHhlMCwgMHgzYiwgMHg0ZCwgMHhhZSwgMHgyYSwgMHhmNSwgMHhiMCwgMHhjOCwgMHhlYiwgMHhiYiwgMHgzYywgMHg4MywgMHg1MywgMHg5OSwgMHg2MSwgMHgxNywgMHgyYiwgMHgwNCwgMHg3ZSwgMHhiYSwgMHg3NywgMHhkNiwgMHgyNiwgMHhlMSwgMHg2OSwgMHgxNCwgMHg2MywgMHg1NSwgMHgyMSwgMHgwYywgMHg3ZF0pOwogIF9taXggPSBuZXcgVWludDMyQXJyYXkoWzB4MDAwMDAwMDAsIDB4MGUwOTBkMGIsIDB4MWMxMjFhMTYsIDB4MTIxYjE3MWQsIDB4MzgyNDM0MmMsIDB4MzYyZDM5MjcsIDB4MjQzNjJlM2EsIDB4MmEzZjIzMzEsIDB4NzA0ODY4NTgsIDB4N2U0MTY1NTMsIDB4NmM1YTcyNGUsIDB4NjI1MzdmNDUsIDB4NDg2YzVjNzQsIDB4NDY2NTUxN2YsIDB4NTQ3ZTQ2NjIsIDB4NWE3NzRiNjksIDB4ZTA5MGQwYjAsIDB4ZWU5OWRkYmIsIDB4ZmM4MmNhYTYsIDB4ZjI4YmM3YWQsIDB4ZDhiNGU0OWMsIDB4ZDZiZGU5OTcsIDB4YzRhNmZlOGEsIDB4Y2FhZmYzODEsIDB4OTBkOGI4ZTgsIDB4OWVkMWI1ZTMsIDB4OGNjYWEyZmUsIDB4ODJjM2FmZjUsIDB4YThmYzhjYzQsIDB4YTZmNTgxY2YsIDB4YjRlZTk2ZDIsIDB4YmFlNzliZDksIDB4ZGIzYmJiN2IsIDB4ZDUzMmI2NzAsIDB4YzcyOWExNmQsIDB4YzkyMGFjNjYsIDB4ZTMxZjhmNTcsIDB4ZWQxNjgyNWMsIDB4ZmYwZDk1NDEsIDB4ZjEwNDk4NGEsIDB4YWI3M2QzMjMsIDB4YTU3YWRlMjgsIDB4Yjc2MWM5MzUsIDB4Yjk2OGM0M2UsIDB4OTM1N2U3MGYsIDB4OWQ1ZWVhMDQsIDB4OGY0NWZkMTksIDB4ODE0Y2YwMTIsIDB4M2JhYjZiY2IsIDB4MzVhMjY2YzAsIDB4MjdiOTcxZGQsIDB4MjliMDdjZDYsIDB4MDM4ZjVmZTcsIDB4MGQ4NjUyZWMsIDB4MWY5ZDQ1ZjEsIDB4MTE5NDQ4ZmEsIDB4NGJlMzAzOTMsIDB4NDVlYTBlOTgsIDB4NTdmMTE5ODUsIDB4NTlmODE0OGUsIDB4NzNjNzM3YmYsIDB4N2RjZTNhYjQsIDB4NmZkNTJkYTksIDB4NjFkYzIwYTIsIDB4YWQ3NjZkZjYsIDB4YTM3ZjYwZmQsIDB4YjE2NDc3ZTAsIDB4YmY2ZDdhZWIsIDB4OTU1MjU5ZGEsIDB4OWI1YjU0ZDEsIDB4ODk0MDQzY2MsIDB4ODc0OTRlYzcsIDB4ZGQzZTA1YWUsIDB4ZDMzNzA4YTUsIDB4YzEyYzFmYjgsIDB4Y2YyNTEyYjMsIDB4ZTUxYTMxODIsIDB4ZWIxMzNjODksIDB4ZjkwODJiOTQsIDB4ZjcwMTI2OWYsIDB4NGRlNmJkNDYsIDB4NDNlZmIwNGQsIDB4NTFmNGE3NTAsIDB4NWZmZGFhNWIsIDB4NzVjMjg5NmEsIDB4N2JjYjg0NjEsIDB4NjlkMDkzN2MsIDB4NjdkOTllNzcsIDB4M2RhZWQ1MWUsIDB4MzNhN2Q4MTUsIDB4MjFiY2NmMDgsIDB4MmZiNWMyMDMsIDB4MDU4YWUxMzIsIDB4MGI4M2VjMzksIDB4MTk5OGZiMjQsIDB4MTc5MWY2MmYsIDB4NzY0ZGQ2OGQsIDB4Nzg0NGRiODYsIDB4NmE1ZmNjOWIsIDB4NjQ1NmMxOTAsIDB4NGU2OWUyYTEsIDB4NDA2MGVmYWEsIDB4NTI3YmY4YjcsIDB4NWM3MmY1YmMsIDB4MDYwNWJlZDUsIDB4MDgwY2IzZGUsIDB4MWExN2E0YzMsIDB4MTQxZWE5YzgsIDB4M2UyMThhZjksIDB4MzAyODg3ZjIsIDB4MjIzMzkwZWYsIDB4MmMzYTlkZTQsIDB4OTZkZDA2M2QsIDB4OThkNDBiMzYsIDB4OGFjZjFjMmIsIDB4ODRjNjExMjAsIDB4YWVmOTMyMTEsIDB4YTBmMDNmMWEsIDB4YjJlYjI4MDcsIDB4YmNlMjI1MGMsIDB4ZTY5NTZlNjUsIDB4ZTg5YzYzNmUsIDB4ZmE4Nzc0NzMsIDB4ZjQ4ZTc5NzgsIDB4ZGViMTVhNDksIDB4ZDBiODU3NDIsIDB4YzJhMzQwNWYsIDB4Y2NhYTRkNTQsIDB4NDFlY2RhZjcsIDB4NGZlNWQ3ZmMsIDB4NWRmZWMwZTEsIDB4NTNmN2NkZWEsIDB4NzljOGVlZGIsIDB4NzdjMWUzZDAsIDB4NjVkYWY0Y2QsIDB4NmJkM2Y5YzYsIDB4MzFhNGIyYWYsIDB4M2ZhZGJmYTQsIDB4MmRiNmE4YjksIDB4MjNiZmE1YjIsIDB4MDk4MDg2ODMsIDB4MDc4OThiODgsIDB4MTU5MjljOTUsIDB4MWI5YjkxOWUsIDB4YTE3YzBhNDcsIDB4YWY3NTA3NGMsIDB4YmQ2ZTEwNTEsIDB4YjM2NzFkNWEsIDB4OTk1ODNlNmIsIDB4OTc1MTMzNjAsIDB4ODU0YTI0N2QsIDB4OGI0MzI5NzYsIDB4ZDEzNDYyMWYsIDB4ZGYzZDZmMTQsIDB4Y2QyNjc4MDksIDB4YzMyZjc1MDIsIDB4ZTkxMDU2MzMsIDB4ZTcxOTViMzgsIDB4ZjUwMjRjMjUsIDB4ZmIwYjQxMmUsIDB4OWFkNzYxOGMsIDB4OTRkZTZjODcsIDB4ODZjNTdiOWEsIDB4ODhjYzc2OTEsIDB4YTJmMzU1YTAsIDB4YWNmYTU4YWIsIDB4YmVlMTRmYjYsIDB4YjBlODQyYmQsIDB4ZWE5ZjA5ZDQsIDB4ZTQ5NjA0ZGYsIDB4ZjY4ZDEzYzIsIDB4Zjg4NDFlYzksIDB4ZDJiYjNkZjgsIDB4ZGNiMjMwZjMsIDB4Y2VhOTI3ZWUsIDB4YzBhMDJhZTUsIDB4N2E0N2IxM2MsIDB4NzQ0ZWJjMzcsIDB4NjY1NWFiMmEsIDB4Njg1Y2E2MjEsIDB4NDI2Mzg1MTAsIDB4NGM2YTg4MWIsIDB4NWU3MTlmMDYsIDB4NTA3ODkyMGQsIDB4MGEwZmQ5NjQsIDB4MDQwNmQ0NmYsIDB4MTYxZGMzNzIsIDB4MTgxNGNlNzksIDB4MzIyYmVkNDgsIDB4M2MyMmUwNDMsIDB4MmUzOWY3NWUsIDB4MjAzMGZhNTUsIDB4ZWM5YWI3MDEsIDB4ZTI5M2JhMGEsIDB4ZjA4OGFkMTcsIDB4ZmU4MWEwMWMsIDB4ZDRiZTgzMmQsIDB4ZGFiNzhlMjYsIDB4YzhhYzk5M2IsIDB4YzZhNTk0MzAsIDB4OWNkMmRmNTksIDB4OTJkYmQyNTIsIDB4ODBjMGM1NGYsIDB4OGVjOWM4NDQsIDB4YTRmNmViNzUsIDB4YWFmZmU2N2UsIDB4YjhlNGYxNjMsIDB4YjZlZGZjNjgsIDB4MGMwYTY3YjEsIDB4MDIwMzZhYmEsIDB4MTAxODdkYTcsIDB4MWUxMTcwYWMsIDB4MzQyZTUzOWQsIDB4M2EyNzVlOTYsIDB4MjgzYzQ5OGIsIDB4MjYzNTQ0ODAsIDB4N2M0MjBmZTksIDB4NzI0YjAyZTIsIDB4NjA1MDE1ZmYsIDB4NmU1OTE4ZjQsIDB4NDQ2NjNiYzUsIDB4NGE2ZjM2Y2UsIDB4NTg3NDIxZDMsIDB4NTY3ZDJjZDgsIDB4MzdhMTBjN2EsIDB4MzlhODAxNzEsIDB4MmJiMzE2NmMsIDB4MjViYTFiNjcsIDB4MGY4NTM4NTYsIDB4MDE4YzM1NWQsIDB4MTM5NzIyNDAsIDB4MWQ5ZTJmNGIsIDB4NDdlOTY0MjIsIDB4NDllMDY5MjksIDB4NWJmYjdlMzQsIDB4NTVmMjczM2YsIDB4N2ZjZDUwMGUsIDB4NzFjNDVkMDUsIDB4NjNkZjRhMTgsIDB4NmRkNjQ3MTMsIDB4ZDczMWRjY2EsIDB4ZDkzOGQxYzEsIDB4Y2IyM2M2ZGMsIDB4YzUyYWNiZDcsIDB4ZWYxNWU4ZTYsIDB4ZTExY2U1ZWQsIDB4ZjMwN2YyZjAsIDB4ZmQwZWZmZmIsIDB4YTc3OWI0OTIsIDB4YTk3MGI5OTksIDB4YmI2YmFlODQsIDB4YjU2MmEzOGYsIDB4OWY1ZDgwYmUsIDB4OTE1NDhkYjUsIDB4ODM0ZjlhYTgsIDB4OGQ0Njk3YTNdKTsKICBfbWl4Q29sID0gbmV3IFVpbnQ4QXJyYXkoMjU2KS5tYXAoKF8sIGkpID0+IGkgPCAxMjggPyBpIDw8IDEgOiBpIDw8IDEgXiAweDFiKTsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMuYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgdGhpcy5idWZmZXJQb3NpdGlvbiA9IDA7CiAgfQogIF9leHBhbmRLZXkoY2lwaGVyS2V5KSB7CiAgICB1bnJlYWNoYWJsZSgiQ2Fubm90IGNhbGwgYF9leHBhbmRLZXlgIG9uIHRoZSBiYXNlIGNsYXNzIik7CiAgfQogIF9kZWNyeXB0KGlucHV0LCBrZXkpIHsKICAgIGxldCB0LCB1LCB2OwogICAgY29uc3Qgc3RhdGUgPSBuZXcgVWludDhBcnJheSgxNik7CiAgICBzdGF0ZS5zZXQoaW5wdXQpOwogICAgZm9yIChsZXQgaiA9IDAsIGsgPSB0aGlzLl9rZXlTaXplOyBqIDwgMTY7ICsraiwgKytrKSB7CiAgICAgIHN0YXRlW2pdIF49IGtleVtrXTsKICAgIH0KICAgIGZvciAobGV0IGkgPSB0aGlzLl9jeWNsZXNPZlJlcGV0aXRpb24gLSAxOyBpID49IDE7IC0taSkgewogICAgICB0ID0gc3RhdGVbMTNdOwogICAgICBzdGF0ZVsxM10gPSBzdGF0ZVs5XTsKICAgICAgc3RhdGVbOV0gPSBzdGF0ZVs1XTsKICAgICAgc3RhdGVbNV0gPSBzdGF0ZVsxXTsKICAgICAgc3RhdGVbMV0gPSB0OwogICAgICB0ID0gc3RhdGVbMTRdOwogICAgICB1ID0gc3RhdGVbMTBdOwogICAgICBzdGF0ZVsxNF0gPSBzdGF0ZVs2XTsKICAgICAgc3RhdGVbMTBdID0gc3RhdGVbMl07CiAgICAgIHN0YXRlWzZdID0gdDsKICAgICAgc3RhdGVbMl0gPSB1OwogICAgICB0ID0gc3RhdGVbMTVdOwogICAgICB1ID0gc3RhdGVbMTFdOwogICAgICB2ID0gc3RhdGVbN107CiAgICAgIHN0YXRlWzE1XSA9IHN0YXRlWzNdOwogICAgICBzdGF0ZVsxMV0gPSB0OwogICAgICBzdGF0ZVs3XSA9IHU7CiAgICAgIHN0YXRlWzNdID0gdjsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCAxNjsgKytqKSB7CiAgICAgICAgc3RhdGVbal0gPSB0aGlzLl9pbnZfc1tzdGF0ZVtqXV07CiAgICAgIH0KICAgICAgZm9yIChsZXQgaiA9IDAsIGsgPSBpICogMTY7IGogPCAxNjsgKytqLCArK2spIHsKICAgICAgICBzdGF0ZVtqXSBePSBrZXlba107CiAgICAgIH0KICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCAxNjsgaiArPSA0KSB7CiAgICAgICAgY29uc3QgczAgPSB0aGlzLl9taXhbc3RhdGVbal1dOwogICAgICAgIGNvbnN0IHMxID0gdGhpcy5fbWl4W3N0YXRlW2ogKyAxXV07CiAgICAgICAgY29uc3QgczIgPSB0aGlzLl9taXhbc3RhdGVbaiArIDJdXTsKICAgICAgICBjb25zdCBzMyA9IHRoaXMuX21peFtzdGF0ZVtqICsgM11dOwogICAgICAgIHQgPSBzMCBeIHMxID4+PiA4IF4gczEgPDwgMjQgXiBzMiA+Pj4gMTYgXiBzMiA8PCAxNiBeIHMzID4+PiAyNCBeIHMzIDw8IDg7CiAgICAgICAgc3RhdGVbal0gPSB0ID4+PiAyNCAmIDB4ZmY7CiAgICAgICAgc3RhdGVbaiArIDFdID0gdCA+PiAxNiAmIDB4ZmY7CiAgICAgICAgc3RhdGVbaiArIDJdID0gdCA+PiA4ICYgMHhmZjsKICAgICAgICBzdGF0ZVtqICsgM10gPSB0ICYgMHhmZjsKICAgICAgfQogICAgfQogICAgdCA9IHN0YXRlWzEzXTsKICAgIHN0YXRlWzEzXSA9IHN0YXRlWzldOwogICAgc3RhdGVbOV0gPSBzdGF0ZVs1XTsKICAgIHN0YXRlWzVdID0gc3RhdGVbMV07CiAgICBzdGF0ZVsxXSA9IHQ7CiAgICB0ID0gc3RhdGVbMTRdOwogICAgdSA9IHN0YXRlWzEwXTsKICAgIHN0YXRlWzE0XSA9IHN0YXRlWzZdOwogICAgc3RhdGVbMTBdID0gc3RhdGVbMl07CiAgICBzdGF0ZVs2XSA9IHQ7CiAgICBzdGF0ZVsyXSA9IHU7CiAgICB0ID0gc3RhdGVbMTVdOwogICAgdSA9IHN0YXRlWzExXTsKICAgIHYgPSBzdGF0ZVs3XTsKICAgIHN0YXRlWzE1XSA9IHN0YXRlWzNdOwogICAgc3RhdGVbMTFdID0gdDsKICAgIHN0YXRlWzddID0gdTsKICAgIHN0YXRlWzNdID0gdjsKICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7ICsraikgewogICAgICBzdGF0ZVtqXSA9IHRoaXMuX2ludl9zW3N0YXRlW2pdXTsKICAgICAgc3RhdGVbal0gXj0ga2V5W2pdOwogICAgfQogICAgcmV0dXJuIHN0YXRlOwogIH0KICBfZW5jcnlwdChpbnB1dCwga2V5KSB7CiAgICBjb25zdCBzID0gdGhpcy5fczsKICAgIGxldCB0LCB1LCB2OwogICAgY29uc3Qgc3RhdGUgPSBuZXcgVWludDhBcnJheSgxNik7CiAgICBzdGF0ZS5zZXQoaW5wdXQpOwogICAgZm9yIChsZXQgaiA9IDA7IGogPCAxNjsgKytqKSB7CiAgICAgIHN0YXRlW2pdIF49IGtleVtqXTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAxOyBpIDwgdGhpcy5fY3ljbGVzT2ZSZXBldGl0aW9uOyBpKyspIHsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCAxNjsgKytqKSB7CiAgICAgICAgc3RhdGVbal0gPSBzW3N0YXRlW2pdXTsKICAgICAgfQogICAgICB2ID0gc3RhdGVbMV07CiAgICAgIHN0YXRlWzFdID0gc3RhdGVbNV07CiAgICAgIHN0YXRlWzVdID0gc3RhdGVbOV07CiAgICAgIHN0YXRlWzldID0gc3RhdGVbMTNdOwogICAgICBzdGF0ZVsxM10gPSB2OwogICAgICB2ID0gc3RhdGVbMl07CiAgICAgIHUgPSBzdGF0ZVs2XTsKICAgICAgc3RhdGVbMl0gPSBzdGF0ZVsxMF07CiAgICAgIHN0YXRlWzZdID0gc3RhdGVbMTRdOwogICAgICBzdGF0ZVsxMF0gPSB2OwogICAgICBzdGF0ZVsxNF0gPSB1OwogICAgICB2ID0gc3RhdGVbM107CiAgICAgIHUgPSBzdGF0ZVs3XTsKICAgICAgdCA9IHN0YXRlWzExXTsKICAgICAgc3RhdGVbM10gPSBzdGF0ZVsxNV07CiAgICAgIHN0YXRlWzddID0gdjsKICAgICAgc3RhdGVbMTFdID0gdTsKICAgICAgc3RhdGVbMTVdID0gdDsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCAxNjsgaiArPSA0KSB7CiAgICAgICAgY29uc3QgczAgPSBzdGF0ZVtqXTsKICAgICAgICBjb25zdCBzMSA9IHN0YXRlW2ogKyAxXTsKICAgICAgICBjb25zdCBzMiA9IHN0YXRlW2ogKyAyXTsKICAgICAgICBjb25zdCBzMyA9IHN0YXRlW2ogKyAzXTsKICAgICAgICB0ID0gczAgXiBzMSBeIHMyIF4gczM7CiAgICAgICAgc3RhdGVbal0gXj0gdCBeIHRoaXMuX21peENvbFtzMCBeIHMxXTsKICAgICAgICBzdGF0ZVtqICsgMV0gXj0gdCBeIHRoaXMuX21peENvbFtzMSBeIHMyXTsKICAgICAgICBzdGF0ZVtqICsgMl0gXj0gdCBeIHRoaXMuX21peENvbFtzMiBeIHMzXTsKICAgICAgICBzdGF0ZVtqICsgM10gXj0gdCBeIHRoaXMuX21peENvbFtzMyBeIHMwXTsKICAgICAgfQogICAgICBmb3IgKGxldCBqID0gMCwgayA9IGkgKiAxNjsgaiA8IDE2OyArK2osICsraykgewogICAgICAgIHN0YXRlW2pdIF49IGtleVtrXTsKICAgICAgfQogICAgfQogICAgZm9yIChsZXQgaiA9IDA7IGogPCAxNjsgKytqKSB7CiAgICAgIHN0YXRlW2pdID0gc1tzdGF0ZVtqXV07CiAgICB9CiAgICB2ID0gc3RhdGVbMV07CiAgICBzdGF0ZVsxXSA9IHN0YXRlWzVdOwogICAgc3RhdGVbNV0gPSBzdGF0ZVs5XTsKICAgIHN0YXRlWzldID0gc3RhdGVbMTNdOwogICAgc3RhdGVbMTNdID0gdjsKICAgIHYgPSBzdGF0ZVsyXTsKICAgIHUgPSBzdGF0ZVs2XTsKICAgIHN0YXRlWzJdID0gc3RhdGVbMTBdOwogICAgc3RhdGVbNl0gPSBzdGF0ZVsxNF07CiAgICBzdGF0ZVsxMF0gPSB2OwogICAgc3RhdGVbMTRdID0gdTsKICAgIHYgPSBzdGF0ZVszXTsKICAgIHUgPSBzdGF0ZVs3XTsKICAgIHQgPSBzdGF0ZVsxMV07CiAgICBzdGF0ZVszXSA9IHN0YXRlWzE1XTsKICAgIHN0YXRlWzddID0gdjsKICAgIHN0YXRlWzExXSA9IHU7CiAgICBzdGF0ZVsxNV0gPSB0OwogICAgZm9yIChsZXQgaiA9IDAsIGsgPSB0aGlzLl9rZXlTaXplOyBqIDwgMTY7ICsraiwgKytrKSB7CiAgICAgIHN0YXRlW2pdIF49IGtleVtrXTsKICAgIH0KICAgIHJldHVybiBzdGF0ZTsKICB9CiAgX2RlY3J5cHRCbG9jazIoZGF0YSwgZmluYWxpemUpIHsKICAgIGNvbnN0IHNvdXJjZUxlbmd0aCA9IGRhdGEubGVuZ3RoOwogICAgbGV0IGJ1ZmZlciA9IHRoaXMuYnVmZmVyLAogICAgICBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlclBvc2l0aW9uOwogICAgY29uc3QgcmVzdWx0ID0gW107CiAgICBsZXQgaXYgPSB0aGlzLml2OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzb3VyY2VMZW5ndGg7ICsraSkgewogICAgICBidWZmZXJbYnVmZmVyTGVuZ3RoXSA9IGRhdGFbaV07CiAgICAgICsrYnVmZmVyTGVuZ3RoOwogICAgICBpZiAoYnVmZmVyTGVuZ3RoIDwgMTYpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBwbGFpbiA9IHRoaXMuX2RlY3J5cHQoYnVmZmVyLCB0aGlzLl9rZXkpOwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IDE2OyArK2opIHsKICAgICAgICBwbGFpbltqXSBePSBpdltqXTsKICAgICAgfQogICAgICBpdiA9IGJ1ZmZlcjsKICAgICAgcmVzdWx0LnB1c2gocGxhaW4pOwogICAgICBidWZmZXIgPSBuZXcgVWludDhBcnJheSgxNik7CiAgICAgIGJ1ZmZlckxlbmd0aCA9IDA7CiAgICB9CiAgICB0aGlzLmJ1ZmZlciA9IGJ1ZmZlcjsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gYnVmZmVyTGVuZ3RoOwogICAgdGhpcy5pdiA9IGl2OwogICAgaWYgKHJlc3VsdC5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KDApOwogICAgfQogICAgbGV0IG91dHB1dExlbmd0aCA9IDE2ICogcmVzdWx0Lmxlbmd0aDsKICAgIGlmIChmaW5hbGl6ZSkgewogICAgICBjb25zdCBsYXN0QmxvY2sgPSByZXN1bHQuYXQoLTEpOwogICAgICBsZXQgcHNMZW4gPSBsYXN0QmxvY2tbMTVdOwogICAgICBpZiAocHNMZW4gPD0gMTYpIHsKICAgICAgICBmb3IgKGxldCBpID0gMTUsIGlpID0gMTYgLSBwc0xlbjsgaSA+PSBpaTsgLS1pKSB7CiAgICAgICAgICBpZiAobGFzdEJsb2NrW2ldICE9PSBwc0xlbikgewogICAgICAgICAgICBwc0xlbiA9IDA7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBvdXRwdXRMZW5ndGggLT0gcHNMZW47CiAgICAgICAgcmVzdWx0W3Jlc3VsdC5sZW5ndGggLSAxXSA9IGxhc3RCbG9jay5zdWJhcnJheSgwLCAxNiAtIHBzTGVuKTsKICAgICAgfQogICAgfQogICAgY29uc3Qgb3V0cHV0ID0gbmV3IFVpbnQ4QXJyYXkob3V0cHV0TGVuZ3RoKTsKICAgIGZvciAobGV0IGkgPSAwLCBqID0gMCwgaWkgPSByZXN1bHQubGVuZ3RoOyBpIDwgaWk7ICsraSwgaiArPSAxNikgewogICAgICBvdXRwdXQuc2V0KHJlc3VsdFtpXSwgaik7CiAgICB9CiAgICByZXR1cm4gb3V0cHV0OwogIH0KICBkZWNyeXB0QmxvY2soZGF0YSwgZmluYWxpemUsIGl2ID0gbnVsbCkgewogICAgY29uc3Qgc291cmNlTGVuZ3RoID0gZGF0YS5sZW5ndGg7CiAgICBjb25zdCBidWZmZXIgPSB0aGlzLmJ1ZmZlcjsKICAgIGxldCBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlclBvc2l0aW9uOwogICAgaWYgKGl2KSB7CiAgICAgIHRoaXMuaXYgPSBpdjsKICAgIH0gZWxzZSB7CiAgICAgIGZvciAobGV0IGkgPSAwOyBidWZmZXJMZW5ndGggPCAxNiAmJiBpIDwgc291cmNlTGVuZ3RoOyArK2ksICsrYnVmZmVyTGVuZ3RoKSB7CiAgICAgICAgYnVmZmVyW2J1ZmZlckxlbmd0aF0gPSBkYXRhW2ldOwogICAgICB9CiAgICAgIGlmIChidWZmZXJMZW5ndGggPCAxNikgewogICAgICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gYnVmZmVyTGVuZ3RoOwogICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheSgwKTsKICAgICAgfQogICAgICB0aGlzLml2ID0gYnVmZmVyOwogICAgICBkYXRhID0gZGF0YS5zdWJhcnJheSgxNik7CiAgICB9CiAgICB0aGlzLmJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KDE2KTsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gMDsKICAgIHRoaXMuZGVjcnlwdEJsb2NrID0gdGhpcy5fZGVjcnlwdEJsb2NrMjsKICAgIHJldHVybiB0aGlzLmRlY3J5cHRCbG9jayhkYXRhLCBmaW5hbGl6ZSk7CiAgfQogIGVuY3J5cHQoZGF0YSwgaXYpIHsKICAgIGNvbnN0IHNvdXJjZUxlbmd0aCA9IGRhdGEubGVuZ3RoOwogICAgbGV0IGJ1ZmZlciA9IHRoaXMuYnVmZmVyLAogICAgICBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlclBvc2l0aW9uOwogICAgY29uc3QgcmVzdWx0ID0gW107CiAgICBpdiB8fD0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzb3VyY2VMZW5ndGg7ICsraSkgewogICAgICBidWZmZXJbYnVmZmVyTGVuZ3RoXSA9IGRhdGFbaV07CiAgICAgICsrYnVmZmVyTGVuZ3RoOwogICAgICBpZiAoYnVmZmVyTGVuZ3RoIDwgMTYpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IDE2OyArK2opIHsKICAgICAgICBidWZmZXJbal0gXj0gaXZbal07CiAgICAgIH0KICAgICAgY29uc3QgY2lwaGVyID0gdGhpcy5fZW5jcnlwdChidWZmZXIsIHRoaXMuX2tleSk7CiAgICAgIGl2ID0gY2lwaGVyOwogICAgICByZXN1bHQucHVzaChjaXBoZXIpOwogICAgICBidWZmZXIgPSBuZXcgVWludDhBcnJheSgxNik7CiAgICAgIGJ1ZmZlckxlbmd0aCA9IDA7CiAgICB9CiAgICB0aGlzLmJ1ZmZlciA9IGJ1ZmZlcjsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gYnVmZmVyTGVuZ3RoOwogICAgdGhpcy5pdiA9IGl2OwogICAgaWYgKHJlc3VsdC5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KDApOwogICAgfQogICAgY29uc3Qgb3V0cHV0TGVuZ3RoID0gMTYgKiByZXN1bHQubGVuZ3RoOwogICAgY29uc3Qgb3V0cHV0ID0gbmV3IFVpbnQ4QXJyYXkob3V0cHV0TGVuZ3RoKTsKICAgIGZvciAobGV0IGkgPSAwLCBqID0gMCwgaWkgPSByZXN1bHQubGVuZ3RoOyBpIDwgaWk7ICsraSwgaiArPSAxNikgewogICAgICBvdXRwdXQuc2V0KHJlc3VsdFtpXSwgaik7CiAgICB9CiAgICByZXR1cm4gb3V0cHV0OwogIH0KfQpjbGFzcyBBRVMxMjhDaXBoZXIgZXh0ZW5kcyBBRVNCYXNlQ2lwaGVyIHsKICBfcmNvbiA9IG5ldyBVaW50OEFycmF5KFsweDhkLCAweDAxLCAweDAyLCAweDA0LCAweDA4LCAweDEwLCAweDIwLCAweDQwLCAweDgwLCAweDFiLCAweDM2LCAweDZjLCAweGQ4LCAweGFiLCAweDRkLCAweDlhLCAweDJmLCAweDVlLCAweGJjLCAweDYzLCAweGM2LCAweDk3LCAweDM1LCAweDZhLCAweGQ0LCAweGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxLCAweDM5LCAweDcyLCAweGU0LCAweGQzLCAweGJkLCAweDYxLCAweGMyLCAweDlmLCAweDI1LCAweDRhLCAweDk0LCAweDMzLCAweDY2LCAweGNjLCAweDgzLCAweDFkLCAweDNhLCAweDc0LCAweGU4LCAweGNiLCAweDhkLCAweDAxLCAweDAyLCAweDA0LCAweDA4LCAweDEwLCAweDIwLCAweDQwLCAweDgwLCAweDFiLCAweDM2LCAweDZjLCAweGQ4LCAweGFiLCAweDRkLCAweDlhLCAweDJmLCAweDVlLCAweGJjLCAweDYzLCAweGM2LCAweDk3LCAweDM1LCAweDZhLCAweGQ0LCAweGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxLCAweDM5LCAweDcyLCAweGU0LCAweGQzLCAweGJkLCAweDYxLCAweGMyLCAweDlmLCAweDI1LCAweDRhLCAweDk0LCAweDMzLCAweDY2LCAweGNjLCAweDgzLCAweDFkLCAweDNhLCAweDc0LCAweGU4LCAweGNiLCAweDhkLCAweDAxLCAweDAyLCAweDA0LCAweDA4LCAweDEwLCAweDIwLCAweDQwLCAweDgwLCAweDFiLCAweDM2LCAweDZjLCAweGQ4LCAweGFiLCAweDRkLCAweDlhLCAweDJmLCAweDVlLCAweGJjLCAweDYzLCAweGM2LCAweDk3LCAweDM1LCAweDZhLCAweGQ0LCAweGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxLCAweDM5LCAweDcyLCAweGU0LCAweGQzLCAweGJkLCAweDYxLCAweGMyLCAweDlmLCAweDI1LCAweDRhLCAweDk0LCAweDMzLCAweDY2LCAweGNjLCAweDgzLCAweDFkLCAweDNhLCAweDc0LCAweGU4LCAweGNiLCAweDhkLCAweDAxLCAweDAyLCAweDA0LCAweDA4LCAweDEwLCAweDIwLCAweDQwLCAweDgwLCAweDFiLCAweDM2LCAweDZjLCAweGQ4LCAweGFiLCAweDRkLCAweDlhLCAweDJmLCAweDVlLCAweGJjLCAweDYzLCAweGM2LCAweDk3LCAweDM1LCAweDZhLCAweGQ0LCAweGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxLCAweDM5LCAweDcyLCAweGU0LCAweGQzLCAweGJkLCAweDYxLCAweGMyLCAweDlmLCAweDI1LCAweDRhLCAweDk0LCAweDMzLCAweDY2LCAweGNjLCAweDgzLCAweDFkLCAweDNhLCAweDc0LCAweGU4LCAweGNiLCAweDhkLCAweDAxLCAweDAyLCAweDA0LCAweDA4LCAweDEwLCAweDIwLCAweDQwLCAweDgwLCAweDFiLCAweDM2LCAweDZjLCAweGQ4LCAweGFiLCAweDRkLCAweDlhLCAweDJmLCAweDVlLCAweGJjLCAweDYzLCAweGM2LCAweDk3LCAweDM1LCAweDZhLCAweGQ0LCAweGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxLCAweDM5LCAweDcyLCAweGU0LCAweGQzLCAweGJkLCAweDYxLCAweGMyLCAweDlmLCAweDI1LCAweDRhLCAweDk0LCAweDMzLCAweDY2LCAweGNjLCAweDgzLCAweDFkLCAweDNhLCAweDc0LCAweGU4LCAweGNiLCAweDhkXSk7CiAgY29uc3RydWN0b3Ioa2V5KSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5fY3ljbGVzT2ZSZXBldGl0aW9uID0gMTA7CiAgICB0aGlzLl9rZXlTaXplID0gMTYwOwogICAgdGhpcy5fa2V5ID0gdGhpcy5fZXhwYW5kS2V5KGtleSk7CiAgfQogIF9leHBhbmRLZXkoY2lwaGVyS2V5KSB7CiAgICBjb25zdCBiID0gMTc2OwogICAgY29uc3QgcyA9IHRoaXMuX3M7CiAgICBjb25zdCByY29uID0gdGhpcy5fcmNvbjsKICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBVaW50OEFycmF5KGIpOwogICAgcmVzdWx0LnNldChjaXBoZXJLZXkpOwogICAgZm9yIChsZXQgaiA9IDE2LCBpID0gMTsgaiA8IGI7ICsraSkgewogICAgICBsZXQgdDEgPSByZXN1bHRbaiAtIDNdOwogICAgICBsZXQgdDIgPSByZXN1bHRbaiAtIDJdOwogICAgICBsZXQgdDMgPSByZXN1bHRbaiAtIDFdOwogICAgICBsZXQgdDQgPSByZXN1bHRbaiAtIDRdOwogICAgICB0MSA9IHNbdDFdOwogICAgICB0MiA9IHNbdDJdOwogICAgICB0MyA9IHNbdDNdOwogICAgICB0NCA9IHNbdDRdOwogICAgICB0MSBePSByY29uW2ldOwogICAgICBmb3IgKGxldCBuID0gMDsgbiA8IDQ7ICsrbikgewogICAgICAgIHJlc3VsdFtqXSA9IHQxIF49IHJlc3VsdFtqIC0gMTZdOwogICAgICAgIGorKzsKICAgICAgICByZXN1bHRbal0gPSB0MiBePSByZXN1bHRbaiAtIDE2XTsKICAgICAgICBqKys7CiAgICAgICAgcmVzdWx0W2pdID0gdDMgXj0gcmVzdWx0W2ogLSAxNl07CiAgICAgICAgaisrOwogICAgICAgIHJlc3VsdFtqXSA9IHQ0IF49IHJlc3VsdFtqIC0gMTZdOwogICAgICAgIGorKzsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9Cn0KY2xhc3MgQUVTMjU2Q2lwaGVyIGV4dGVuZHMgQUVTQmFzZUNpcGhlciB7CiAgY29uc3RydWN0b3Ioa2V5KSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5fY3ljbGVzT2ZSZXBldGl0aW9uID0gMTQ7CiAgICB0aGlzLl9rZXlTaXplID0gMjI0OwogICAgdGhpcy5fa2V5ID0gdGhpcy5fZXhwYW5kS2V5KGtleSk7CiAgfQogIF9leHBhbmRLZXkoY2lwaGVyS2V5KSB7CiAgICBjb25zdCBiID0gMjQwOwogICAgY29uc3QgcyA9IHRoaXMuX3M7CiAgICBjb25zdCByZXN1bHQgPSBuZXcgVWludDhBcnJheShiKTsKICAgIHJlc3VsdC5zZXQoY2lwaGVyS2V5KTsKICAgIGxldCByID0gMTsKICAgIGxldCB0MSwgdDIsIHQzLCB0NDsKICAgIGZvciAobGV0IGogPSAzMiwgaSA9IDE7IGogPCBiOyArK2kpIHsKICAgICAgaWYgKGogJSAzMiA9PT0gMTYpIHsKICAgICAgICB0MSA9IHNbdDFdOwogICAgICAgIHQyID0gc1t0Ml07CiAgICAgICAgdDMgPSBzW3QzXTsKICAgICAgICB0NCA9IHNbdDRdOwogICAgICB9IGVsc2UgaWYgKGogJSAzMiA9PT0gMCkgewogICAgICAgIHQxID0gcmVzdWx0W2ogLSAzXTsKICAgICAgICB0MiA9IHJlc3VsdFtqIC0gMl07CiAgICAgICAgdDMgPSByZXN1bHRbaiAtIDFdOwogICAgICAgIHQ0ID0gcmVzdWx0W2ogLSA0XTsKICAgICAgICB0MSA9IHNbdDFdOwogICAgICAgIHQyID0gc1t0Ml07CiAgICAgICAgdDMgPSBzW3QzXTsKICAgICAgICB0NCA9IHNbdDRdOwogICAgICAgIHQxIF49IHI7CiAgICAgICAgaWYgKChyIDw8PSAxKSA+PSAyNTYpIHsKICAgICAgICAgIHIgPSAociBeIDB4MWIpICYgMHhmZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgZm9yIChsZXQgbiA9IDA7IG4gPCA0OyArK24pIHsKICAgICAgICByZXN1bHRbal0gPSB0MSBePSByZXN1bHRbaiAtIDMyXTsKICAgICAgICBqKys7CiAgICAgICAgcmVzdWx0W2pdID0gdDIgXj0gcmVzdWx0W2ogLSAzMl07CiAgICAgICAgaisrOwogICAgICAgIHJlc3VsdFtqXSA9IHQzIF49IHJlc3VsdFtqIC0gMzJdOwogICAgICAgIGorKzsKICAgICAgICByZXN1bHRbal0gPSB0NCBePSByZXN1bHRbaiAtIDMyXTsKICAgICAgICBqKys7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQp9CmNsYXNzIFBERkJhc2UgewogIF9oYXNoKHBhc3N3b3JkLCBpbnB1dCwgdXNlckJ5dGVzKSB7CiAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGBfaGFzaGAgY2FsbGVkIik7CiAgfQogIGNoZWNrT3duZXJQYXNzd29yZChwYXNzd29yZCwgb3duZXJWYWxpZGF0aW9uU2FsdCwgdXNlckJ5dGVzLCBvd25lclBhc3N3b3JkKSB7CiAgICBjb25zdCBoYXNoRGF0YSA9IG5ldyBVaW50OEFycmF5KHBhc3N3b3JkLmxlbmd0aCArIDU2KTsKICAgIGhhc2hEYXRhLnNldChwYXNzd29yZCwgMCk7CiAgICBoYXNoRGF0YS5zZXQob3duZXJWYWxpZGF0aW9uU2FsdCwgcGFzc3dvcmQubGVuZ3RoKTsKICAgIGhhc2hEYXRhLnNldCh1c2VyQnl0ZXMsIHBhc3N3b3JkLmxlbmd0aCArIG93bmVyVmFsaWRhdGlvblNhbHQubGVuZ3RoKTsKICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX2hhc2gocGFzc3dvcmQsIGhhc2hEYXRhLCB1c2VyQnl0ZXMpOwogICAgcmV0dXJuIGlzQXJyYXlFcXVhbChyZXN1bHQsIG93bmVyUGFzc3dvcmQpOwogIH0KICBjaGVja1VzZXJQYXNzd29yZChwYXNzd29yZCwgdXNlclZhbGlkYXRpb25TYWx0LCB1c2VyUGFzc3dvcmQpIHsKICAgIGNvbnN0IGhhc2hEYXRhID0gbmV3IFVpbnQ4QXJyYXkocGFzc3dvcmQubGVuZ3RoICsgOCk7CiAgICBoYXNoRGF0YS5zZXQocGFzc3dvcmQsIDApOwogICAgaGFzaERhdGEuc2V0KHVzZXJWYWxpZGF0aW9uU2FsdCwgcGFzc3dvcmQubGVuZ3RoKTsKICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX2hhc2gocGFzc3dvcmQsIGhhc2hEYXRhLCBbXSk7CiAgICByZXR1cm4gaXNBcnJheUVxdWFsKHJlc3VsdCwgdXNlclBhc3N3b3JkKTsKICB9CiAgZ2V0T3duZXJLZXkocGFzc3dvcmQsIG93bmVyS2V5U2FsdCwgdXNlckJ5dGVzLCBvd25lckVuY3J5cHRpb24pIHsKICAgIGNvbnN0IGhhc2hEYXRhID0gbmV3IFVpbnQ4QXJyYXkocGFzc3dvcmQubGVuZ3RoICsgNTYpOwogICAgaGFzaERhdGEuc2V0KHBhc3N3b3JkLCAwKTsKICAgIGhhc2hEYXRhLnNldChvd25lcktleVNhbHQsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICBoYXNoRGF0YS5zZXQodXNlckJ5dGVzLCBwYXNzd29yZC5sZW5ndGggKyBvd25lcktleVNhbHQubGVuZ3RoKTsKICAgIGNvbnN0IGtleSA9IHRoaXMuX2hhc2gocGFzc3dvcmQsIGhhc2hEYXRhLCB1c2VyQnl0ZXMpOwogICAgY29uc3QgY2lwaGVyID0gbmV3IEFFUzI1NkNpcGhlcihrZXkpOwogICAgcmV0dXJuIGNpcGhlci5kZWNyeXB0QmxvY2sob3duZXJFbmNyeXB0aW9uLCBmYWxzZSwgbmV3IFVpbnQ4QXJyYXkoMTYpKTsKICB9CiAgZ2V0VXNlcktleShwYXNzd29yZCwgdXNlcktleVNhbHQsIHVzZXJFbmNyeXB0aW9uKSB7CiAgICBjb25zdCBoYXNoRGF0YSA9IG5ldyBVaW50OEFycmF5KHBhc3N3b3JkLmxlbmd0aCArIDgpOwogICAgaGFzaERhdGEuc2V0KHBhc3N3b3JkLCAwKTsKICAgIGhhc2hEYXRhLnNldCh1c2VyS2V5U2FsdCwgcGFzc3dvcmQubGVuZ3RoKTsKICAgIGNvbnN0IGtleSA9IHRoaXMuX2hhc2gocGFzc3dvcmQsIGhhc2hEYXRhLCBbXSk7CiAgICBjb25zdCBjaXBoZXIgPSBuZXcgQUVTMjU2Q2lwaGVyKGtleSk7CiAgICByZXR1cm4gY2lwaGVyLmRlY3J5cHRCbG9jayh1c2VyRW5jcnlwdGlvbiwgZmFsc2UsIG5ldyBVaW50OEFycmF5KDE2KSk7CiAgfQp9CmNsYXNzIFBERjE3IGV4dGVuZHMgUERGQmFzZSB7CiAgX2hhc2gocGFzc3dvcmQsIGlucHV0LCB1c2VyQnl0ZXMpIHsKICAgIHJldHVybiBjYWxjdWxhdGVTSEEyNTYoaW5wdXQsIDAsIGlucHV0Lmxlbmd0aCk7CiAgfQp9CmNsYXNzIFBERjIwIGV4dGVuZHMgUERGQmFzZSB7CiAgX2hhc2gocGFzc3dvcmQsIGlucHV0LCB1c2VyQnl0ZXMpIHsKICAgIGxldCBrID0gY2FsY3VsYXRlU0hBMjU2KGlucHV0LCAwLCBpbnB1dC5sZW5ndGgpLnN1YmFycmF5KDAsIDMyKTsKICAgIGxldCBlID0gWzBdOwogICAgbGV0IGkgPSAwOwogICAgd2hpbGUgKGkgPCA2NCB8fCBlLmF0KC0xKSA+IGkgLSAzMikgewogICAgICBjb25zdCBjb21iaW5lZExlbmd0aCA9IHBhc3N3b3JkLmxlbmd0aCArIGsubGVuZ3RoICsgdXNlckJ5dGVzLmxlbmd0aCwKICAgICAgICBjb21iaW5lZEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoY29tYmluZWRMZW5ndGgpOwogICAgICBsZXQgd3JpdGVPZmZzZXQgPSAwOwogICAgICBjb21iaW5lZEFycmF5LnNldChwYXNzd29yZCwgd3JpdGVPZmZzZXQpOwogICAgICB3cml0ZU9mZnNldCArPSBwYXNzd29yZC5sZW5ndGg7CiAgICAgIGNvbWJpbmVkQXJyYXkuc2V0KGssIHdyaXRlT2Zmc2V0KTsKICAgICAgd3JpdGVPZmZzZXQgKz0gay5sZW5ndGg7CiAgICAgIGNvbWJpbmVkQXJyYXkuc2V0KHVzZXJCeXRlcywgd3JpdGVPZmZzZXQpOwogICAgICBjb25zdCBrMSA9IG5ldyBVaW50OEFycmF5KGNvbWJpbmVkTGVuZ3RoICogNjQpOwogICAgICBmb3IgKGxldCBqID0gMCwgcG9zID0gMDsgaiA8IDY0OyBqKyssIHBvcyArPSBjb21iaW5lZExlbmd0aCkgewogICAgICAgIGsxLnNldChjb21iaW5lZEFycmF5LCBwb3MpOwogICAgICB9CiAgICAgIGNvbnN0IGNpcGhlciA9IG5ldyBBRVMxMjhDaXBoZXIoay5zdWJhcnJheSgwLCAxNikpOwogICAgICBlID0gY2lwaGVyLmVuY3J5cHQoazEsIGsuc3ViYXJyYXkoMTYsIDMyKSk7CiAgICAgIGNvbnN0IHJlbWFpbmRlciA9IE1hdGguc3VtUHJlY2lzZShlLnNsaWNlKDAsIDE2KSkgJSAzOwogICAgICBpZiAocmVtYWluZGVyID09PSAwKSB7CiAgICAgICAgayA9IGNhbGN1bGF0ZVNIQTI1NihlLCAwLCBlLmxlbmd0aCk7CiAgICAgIH0gZWxzZSBpZiAocmVtYWluZGVyID09PSAxKSB7CiAgICAgICAgayA9IGNhbGN1bGF0ZVNIQTM4NChlLCAwLCBlLmxlbmd0aCk7CiAgICAgIH0gZWxzZSBpZiAocmVtYWluZGVyID09PSAyKSB7CiAgICAgICAgayA9IGNhbGN1bGF0ZVNIQTUxMihlLCAwLCBlLmxlbmd0aCk7CiAgICAgIH0KICAgICAgaSsrOwogICAgfQogICAgcmV0dXJuIGsuc3ViYXJyYXkoMCwgMzIpOwogIH0KfQpjbGFzcyBDaXBoZXJUcmFuc2Zvcm0gewogIGNvbnN0cnVjdG9yKHN0cmluZ0NpcGhlckNvbnN0cnVjdG9yLCBzdHJlYW1DaXBoZXJDb25zdHJ1Y3RvcikgewogICAgdGhpcy5TdHJpbmdDaXBoZXJDb25zdHJ1Y3RvciA9IHN0cmluZ0NpcGhlckNvbnN0cnVjdG9yOwogICAgdGhpcy5TdHJlYW1DaXBoZXJDb25zdHJ1Y3RvciA9IHN0cmVhbUNpcGhlckNvbnN0cnVjdG9yOwogIH0KICBjcmVhdGVTdHJlYW0oc3RyZWFtLCBsZW5ndGgpIHsKICAgIGNvbnN0IGNpcGhlciA9IG5ldyB0aGlzLlN0cmVhbUNpcGhlckNvbnN0cnVjdG9yKCk7CiAgICByZXR1cm4gbmV3IERlY3J5cHRTdHJlYW0oc3RyZWFtLCBsZW5ndGgsIGZ1bmN0aW9uIGNpcGhlclRyYW5zZm9ybURlY3J5cHRTdHJlYW0oZGF0YSwgZmluYWxpemUpIHsKICAgICAgcmV0dXJuIGNpcGhlci5kZWNyeXB0QmxvY2soZGF0YSwgZmluYWxpemUpOwogICAgfSk7CiAgfQogIGRlY3J5cHRTdHJpbmcocykgewogICAgY29uc3QgY2lwaGVyID0gbmV3IHRoaXMuU3RyaW5nQ2lwaGVyQ29uc3RydWN0b3IoKTsKICAgIGxldCBkYXRhID0gc3RyaW5nVG9CeXRlcyhzKTsKICAgIGRhdGEgPSBjaXBoZXIuZGVjcnlwdEJsb2NrKGRhdGEsIHRydWUpOwogICAgcmV0dXJuIGJ5dGVzVG9TdHJpbmcoZGF0YSk7CiAgfQogIGVuY3J5cHRTdHJpbmcocykgewogICAgY29uc3QgY2lwaGVyID0gbmV3IHRoaXMuU3RyaW5nQ2lwaGVyQ29uc3RydWN0b3IoKTsKICAgIGlmIChjaXBoZXIgaW5zdGFuY2VvZiBBRVNCYXNlQ2lwaGVyKSB7CiAgICAgIGNvbnN0IHN0ckxlbiA9IHMubGVuZ3RoOwogICAgICBjb25zdCBwYWQgPSAxNiAtIHN0ckxlbiAlIDE2OwogICAgICBzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUocGFkKS5yZXBlYXQocGFkKTsKICAgICAgY29uc3QgaXYgPSBuZXcgVWludDhBcnJheSgxNik7CiAgICAgIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMoaXYpOwogICAgICBsZXQgZGF0YSA9IHN0cmluZ1RvQnl0ZXMocyk7CiAgICAgIGRhdGEgPSBjaXBoZXIuZW5jcnlwdChkYXRhLCBpdik7CiAgICAgIGNvbnN0IGJ1ZiA9IG5ldyBVaW50OEFycmF5KDE2ICsgZGF0YS5sZW5ndGgpOwogICAgICBidWYuc2V0KGl2KTsKICAgICAgYnVmLnNldChkYXRhLCAxNik7CiAgICAgIHJldHVybiBieXRlc1RvU3RyaW5nKGJ1Zik7CiAgICB9CiAgICBsZXQgZGF0YSA9IHN0cmluZ1RvQnl0ZXMocyk7CiAgICBkYXRhID0gY2lwaGVyLmVuY3J5cHQoZGF0YSk7CiAgICByZXR1cm4gYnl0ZXNUb1N0cmluZyhkYXRhKTsKICB9Cn0KY2xhc3MgQ2lwaGVyVHJhbnNmb3JtRmFjdG9yeSB7CiAgc3RhdGljIGdldCBfZGVmYXVsdFBhc3N3b3JkQnl0ZXMoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJfZGVmYXVsdFBhc3N3b3JkQnl0ZXMiLCBuZXcgVWludDhBcnJheShbMHgyOCwgMHhiZiwgMHg0ZSwgMHg1ZSwgMHg0ZSwgMHg3NSwgMHg4YSwgMHg0MSwgMHg2NCwgMHgwMCwgMHg0ZSwgMHg1NiwgMHhmZiwgMHhmYSwgMHgwMSwgMHgwOCwgMHgyZSwgMHgyZSwgMHgwMCwgMHhiNiwgMHhkMCwgMHg2OCwgMHgzZSwgMHg4MCwgMHgyZiwgMHgwYywgMHhhOSwgMHhmZSwgMHg2NCwgMHg1MywgMHg2OSwgMHg3YV0pKTsKICB9CiAgI2NyZWF0ZUVuY3J5cHRpb25LZXkyMChyZXZpc2lvbiwgcGFzc3dvcmQsIG93bmVyUGFzc3dvcmQsIG93bmVyVmFsaWRhdGlvblNhbHQsIG93bmVyS2V5U2FsdCwgdUJ5dGVzLCB1c2VyUGFzc3dvcmQsIHVzZXJWYWxpZGF0aW9uU2FsdCwgdXNlcktleVNhbHQsIG93bmVyRW5jcnlwdGlvbiwgdXNlckVuY3J5cHRpb24sIHBlcm1zKSB7CiAgICBpZiAocGFzc3dvcmQpIHsKICAgICAgY29uc3QgcGFzc3dvcmRMZW5ndGggPSBNYXRoLm1pbigxMjcsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICAgIHBhc3N3b3JkID0gcGFzc3dvcmQuc3ViYXJyYXkoMCwgcGFzc3dvcmRMZW5ndGgpOwogICAgfSBlbHNlIHsKICAgICAgcGFzc3dvcmQgPSBbXTsKICAgIH0KICAgIGNvbnN0IHBkZkFsZ29yaXRobSA9IHJldmlzaW9uID09PSA2ID8gbmV3IFBERjIwKCkgOiBuZXcgUERGMTcoKTsKICAgIGlmIChwZGZBbGdvcml0aG0uY2hlY2tVc2VyUGFzc3dvcmQocGFzc3dvcmQsIHVzZXJWYWxpZGF0aW9uU2FsdCwgdXNlclBhc3N3b3JkKSkgewogICAgICByZXR1cm4gcGRmQWxnb3JpdGhtLmdldFVzZXJLZXkocGFzc3dvcmQsIHVzZXJLZXlTYWx0LCB1c2VyRW5jcnlwdGlvbik7CiAgICB9IGVsc2UgaWYgKHBhc3N3b3JkLmxlbmd0aCAmJiBwZGZBbGdvcml0aG0uY2hlY2tPd25lclBhc3N3b3JkKHBhc3N3b3JkLCBvd25lclZhbGlkYXRpb25TYWx0LCB1Qnl0ZXMsIG93bmVyUGFzc3dvcmQpKSB7CiAgICAgIHJldHVybiBwZGZBbGdvcml0aG0uZ2V0T3duZXJLZXkocGFzc3dvcmQsIG93bmVyS2V5U2FsdCwgdUJ5dGVzLCBvd25lckVuY3J5cHRpb24pOwogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogICNwcmVwYXJlS2V5RGF0YShmaWxlSWQsIHBhc3N3b3JkLCBvd25lclBhc3N3b3JkLCB1c2VyUGFzc3dvcmQsIGZsYWdzLCByZXZpc2lvbiwga2V5TGVuZ3RoLCBlbmNyeXB0TWV0YWRhdGEpIHsKICAgIGNvbnN0IGhhc2hEYXRhU2l6ZSA9IDQwICsgb3duZXJQYXNzd29yZC5sZW5ndGggKyBmaWxlSWQubGVuZ3RoOwogICAgY29uc3QgaGFzaERhdGEgPSBuZXcgVWludDhBcnJheShoYXNoRGF0YVNpemUpOwogICAgbGV0IGkgPSAwLAogICAgICBqLAogICAgICBuOwogICAgaWYgKHBhc3N3b3JkKSB7CiAgICAgIG4gPSBNYXRoLm1pbigzMiwgcGFzc3dvcmQubGVuZ3RoKTsKICAgICAgZm9yICg7IGkgPCBuOyArK2kpIHsKICAgICAgICBoYXNoRGF0YVtpXSA9IHBhc3N3b3JkW2ldOwogICAgICB9CiAgICB9CiAgICBqID0gMDsKICAgIHdoaWxlIChpIDwgMzIpIHsKICAgICAgaGFzaERhdGFbaSsrXSA9IENpcGhlclRyYW5zZm9ybUZhY3RvcnkuX2RlZmF1bHRQYXNzd29yZEJ5dGVzW2orK107CiAgICB9CiAgICBoYXNoRGF0YS5zZXQob3duZXJQYXNzd29yZCwgaSk7CiAgICBpICs9IG93bmVyUGFzc3dvcmQubGVuZ3RoOwogICAgaGFzaERhdGFbaSsrXSA9IGZsYWdzICYgMHhmZjsKICAgIGhhc2hEYXRhW2krK10gPSBmbGFncyA+PiA4ICYgMHhmZjsKICAgIGhhc2hEYXRhW2krK10gPSBmbGFncyA+PiAxNiAmIDB4ZmY7CiAgICBoYXNoRGF0YVtpKytdID0gZmxhZ3MgPj4+IDI0ICYgMHhmZjsKICAgIGhhc2hEYXRhLnNldChmaWxlSWQsIGkpOwogICAgaSArPSBmaWxlSWQubGVuZ3RoOwogICAgaWYgKHJldmlzaW9uID49IDQgJiYgIWVuY3J5cHRNZXRhZGF0YSkgewogICAgICBoYXNoRGF0YS5maWxsKDB4ZmYsIGksIGkgKyA0KTsKICAgICAgaSArPSA0OwogICAgfQogICAgbGV0IGhhc2ggPSBjYWxjdWxhdGVNRDUoaGFzaERhdGEsIDAsIGkpOwogICAgY29uc3Qga2V5TGVuZ3RoSW5CeXRlcyA9IGtleUxlbmd0aCA+PiAzOwogICAgaWYgKHJldmlzaW9uID49IDMpIHsKICAgICAgZm9yIChqID0gMDsgaiA8IDUwOyArK2opIHsKICAgICAgICBoYXNoID0gY2FsY3VsYXRlTUQ1KGhhc2gsIDAsIGtleUxlbmd0aEluQnl0ZXMpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gaGFzaC5zdWJhcnJheSgwLCBrZXlMZW5ndGhJbkJ5dGVzKTsKICAgIGxldCBjaXBoZXIsIGNoZWNrRGF0YTsKICAgIGlmIChyZXZpc2lvbiA+PSAzKSB7CiAgICAgIGkgPSAwOwogICAgICBoYXNoRGF0YS5zZXQoQ2lwaGVyVHJhbnNmb3JtRmFjdG9yeS5fZGVmYXVsdFBhc3N3b3JkQnl0ZXMsIGkpOwogICAgICBpICs9IDMyOwogICAgICBoYXNoRGF0YS5zZXQoZmlsZUlkLCBpKTsKICAgICAgaSArPSBmaWxlSWQubGVuZ3RoOwogICAgICBjaXBoZXIgPSBuZXcgQVJDRm91ckNpcGhlcihlbmNyeXB0aW9uS2V5KTsKICAgICAgY2hlY2tEYXRhID0gY2lwaGVyLmVuY3J5cHRCbG9jayhjYWxjdWxhdGVNRDUoaGFzaERhdGEsIDAsIGkpKTsKICAgICAgbiA9IGVuY3J5cHRpb25LZXkubGVuZ3RoOwogICAgICBjb25zdCBkZXJpdmVkS2V5ID0gbmV3IFVpbnQ4QXJyYXkobik7CiAgICAgIGZvciAoaiA9IDE7IGogPD0gMTk7ICsraikgewogICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgbjsgKytrKSB7CiAgICAgICAgICBkZXJpdmVkS2V5W2tdID0gZW5jcnlwdGlvbktleVtrXSBeIGo7CiAgICAgICAgfQogICAgICAgIGNpcGhlciA9IG5ldyBBUkNGb3VyQ2lwaGVyKGRlcml2ZWRLZXkpOwogICAgICAgIGNoZWNrRGF0YSA9IGNpcGhlci5lbmNyeXB0QmxvY2soY2hlY2tEYXRhKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgY2lwaGVyID0gbmV3IEFSQ0ZvdXJDaXBoZXIoZW5jcnlwdGlvbktleSk7CiAgICAgIGNoZWNrRGF0YSA9IGNpcGhlci5lbmNyeXB0QmxvY2soQ2lwaGVyVHJhbnNmb3JtRmFjdG9yeS5fZGVmYXVsdFBhc3N3b3JkQnl0ZXMpOwogICAgfQogICAgcmV0dXJuIGNoZWNrRGF0YS5ldmVyeSgoZGF0YSwgaykgPT4gdXNlclBhc3N3b3JkW2tdID09PSBkYXRhKSA/IGVuY3J5cHRpb25LZXkgOiBudWxsOwogIH0KICAjZGVjb2RlVXNlclBhc3N3b3JkKHBhc3N3b3JkLCBvd25lclBhc3N3b3JkLCByZXZpc2lvbiwga2V5TGVuZ3RoKSB7CiAgICBjb25zdCBoYXNoRGF0YSA9IG5ldyBVaW50OEFycmF5KDMyKTsKICAgIGxldCBpID0gMDsKICAgIGNvbnN0IG4gPSBNYXRoLm1pbigzMiwgcGFzc3dvcmQubGVuZ3RoKTsKICAgIGZvciAoOyBpIDwgbjsgKytpKSB7CiAgICAgIGhhc2hEYXRhW2ldID0gcGFzc3dvcmRbaV07CiAgICB9CiAgICBsZXQgaiA9IDA7CiAgICB3aGlsZSAoaSA8IDMyKSB7CiAgICAgIGhhc2hEYXRhW2krK10gPSBDaXBoZXJUcmFuc2Zvcm1GYWN0b3J5Ll9kZWZhdWx0UGFzc3dvcmRCeXRlc1tqKytdOwogICAgfQogICAgbGV0IGhhc2ggPSBjYWxjdWxhdGVNRDUoaGFzaERhdGEsIDAsIGkpOwogICAgY29uc3Qga2V5TGVuZ3RoSW5CeXRlcyA9IGtleUxlbmd0aCA+PiAzOwogICAgaWYgKHJldmlzaW9uID49IDMpIHsKICAgICAgZm9yIChqID0gMDsgaiA8IDUwOyArK2opIHsKICAgICAgICBoYXNoID0gY2FsY3VsYXRlTUQ1KGhhc2gsIDAsIGhhc2gubGVuZ3RoKTsKICAgICAgfQogICAgfQogICAgbGV0IGNpcGhlciwgdXNlclBhc3N3b3JkOwogICAgaWYgKHJldmlzaW9uID49IDMpIHsKICAgICAgdXNlclBhc3N3b3JkID0gb3duZXJQYXNzd29yZDsKICAgICAgY29uc3QgZGVyaXZlZEtleSA9IG5ldyBVaW50OEFycmF5KGtleUxlbmd0aEluQnl0ZXMpOwogICAgICBmb3IgKGogPSAxOTsgaiA+PSAwOyBqLS0pIHsKICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IGtleUxlbmd0aEluQnl0ZXM7ICsraykgewogICAgICAgICAgZGVyaXZlZEtleVtrXSA9IGhhc2hba10gXiBqOwogICAgICAgIH0KICAgICAgICBjaXBoZXIgPSBuZXcgQVJDRm91ckNpcGhlcihkZXJpdmVkS2V5KTsKICAgICAgICB1c2VyUGFzc3dvcmQgPSBjaXBoZXIuZW5jcnlwdEJsb2NrKHVzZXJQYXNzd29yZCk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGNpcGhlciA9IG5ldyBBUkNGb3VyQ2lwaGVyKGhhc2guc3ViYXJyYXkoMCwga2V5TGVuZ3RoSW5CeXRlcykpOwogICAgICB1c2VyUGFzc3dvcmQgPSBjaXBoZXIuZW5jcnlwdEJsb2NrKG93bmVyUGFzc3dvcmQpOwogICAgfQogICAgcmV0dXJuIHVzZXJQYXNzd29yZDsKICB9CiAgI2J1aWxkT2JqZWN0S2V5KG51bSwgZ2VuLCBlbmNyeXB0aW9uS2V5LCBpc0FlcyA9IGZhbHNlKSB7CiAgICBjb25zdCBuID0gZW5jcnlwdGlvbktleS5sZW5ndGg7CiAgICBjb25zdCBrZXkgPSBuZXcgVWludDhBcnJheShuICsgOSk7CiAgICBrZXkuc2V0KGVuY3J5cHRpb25LZXkpOwogICAgbGV0IGkgPSBuOwogICAga2V5W2krK10gPSBudW0gJiAweGZmOwogICAga2V5W2krK10gPSBudW0gPj4gOCAmIDB4ZmY7CiAgICBrZXlbaSsrXSA9IG51bSA+PiAxNiAmIDB4ZmY7CiAgICBrZXlbaSsrXSA9IGdlbiAmIDB4ZmY7CiAgICBrZXlbaSsrXSA9IGdlbiA+PiA4ICYgMHhmZjsKICAgIGlmIChpc0FlcykgewogICAgICBrZXlbaSsrXSA9IDB4NzM7CiAgICAgIGtleVtpKytdID0gMHg0MTsKICAgICAga2V5W2krK10gPSAweDZjOwogICAgICBrZXlbaSsrXSA9IDB4NTQ7CiAgICB9CiAgICBjb25zdCBoYXNoID0gY2FsY3VsYXRlTUQ1KGtleSwgMCwgaSk7CiAgICByZXR1cm4gaGFzaC5zdWJhcnJheSgwLCBNYXRoLm1pbihuICsgNSwgMTYpKTsKICB9CiAgI2J1aWxkQ2lwaGVyQ29uc3RydWN0b3IoY2YsIG5hbWUsIG51bSwgZ2VuLCBrZXkpIHsKICAgIGlmICghKG5hbWUgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgY3J5cHQgZmlsdGVyIG5hbWUuIik7CiAgICB9CiAgICBjb25zdCBzZWxmID0gdGhpczsKICAgIGNvbnN0IGNyeXB0RmlsdGVyID0gY2YuZ2V0KG5hbWUubmFtZSk7CiAgICBjb25zdCBjZm0gPSBjcnlwdEZpbHRlcj8uZ2V0KCJDRk0iKTsKICAgIGlmICghY2ZtIHx8IGNmbS5uYW1lID09PSAiTm9uZSIpIHsKICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gbmV3IE51bGxDaXBoZXIoKTsKICAgICAgfTsKICAgIH0KICAgIGlmIChjZm0ubmFtZSA9PT0gIlYyIikgewogICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBuZXcgQVJDRm91ckNpcGhlcihzZWxmLiNidWlsZE9iamVjdEtleShudW0sIGdlbiwga2V5LCBmYWxzZSkpOwogICAgICB9OwogICAgfQogICAgaWYgKGNmbS5uYW1lID09PSAiQUVTVjIiKSB7CiAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIG5ldyBBRVMxMjhDaXBoZXIoc2VsZi4jYnVpbGRPYmplY3RLZXkobnVtLCBnZW4sIGtleSwgdHJ1ZSkpOwogICAgICB9OwogICAgfQogICAgaWYgKGNmbS5uYW1lID09PSAiQUVTVjMiKSB7CiAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIG5ldyBBRVMyNTZDaXBoZXIoa2V5KTsKICAgICAgfTsKICAgIH0KICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiVW5rbm93biBjcnlwdG8gbWV0aG9kIik7CiAgfQogIGNvbnN0cnVjdG9yKGRpY3QsIGZpbGVJZCwgcGFzc3dvcmQpIHsKICAgIGNvbnN0IGZpbHRlciA9IGRpY3QuZ2V0KCJGaWx0ZXIiKTsKICAgIGlmICghaXNOYW1lKGZpbHRlciwgIlN0YW5kYXJkIikpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJ1bmtub3duIGVuY3J5cHRpb24gbWV0aG9kIik7CiAgICB9CiAgICB0aGlzLmZpbHRlck5hbWUgPSBmaWx0ZXIubmFtZTsKICAgIHRoaXMuZGljdCA9IGRpY3Q7CiAgICBjb25zdCBhbGdvcml0aG0gPSBkaWN0LmdldCgiViIpOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGFsZ29yaXRobSkgfHwgYWxnb3JpdGhtICE9PSAxICYmIGFsZ29yaXRobSAhPT0gMiAmJiBhbGdvcml0aG0gIT09IDQgJiYgYWxnb3JpdGhtICE9PSA1KSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigidW5zdXBwb3J0ZWQgZW5jcnlwdGlvbiBhbGdvcml0aG0iKTsKICAgIH0KICAgIHRoaXMuYWxnb3JpdGhtID0gYWxnb3JpdGhtOwogICAgbGV0IGtleUxlbmd0aCA9IGRpY3QuZ2V0KCJMZW5ndGgiKTsKICAgIGlmICgha2V5TGVuZ3RoKSB7CiAgICAgIGlmIChhbGdvcml0aG0gPD0gMykgewogICAgICAgIGtleUxlbmd0aCA9IDQwOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGNmRGljdCA9IGRpY3QuZ2V0KCJDRiIpOwogICAgICAgIGNvbnN0IHN0cmVhbUNyeXB0b05hbWUgPSBkaWN0LmdldCgiU3RtRiIpOwogICAgICAgIGlmIChjZkRpY3QgaW5zdGFuY2VvZiBEaWN0ICYmIHN0cmVhbUNyeXB0b05hbWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICBjZkRpY3Quc3VwcHJlc3NFbmNyeXB0aW9uID0gdHJ1ZTsKICAgICAgICAgIGNvbnN0IGhhbmRsZXJEaWN0ID0gY2ZEaWN0LmdldChzdHJlYW1DcnlwdG9OYW1lLm5hbWUpOwogICAgICAgICAga2V5TGVuZ3RoID0gaGFuZGxlckRpY3Q/LmdldCgiTGVuZ3RoIikgfHwgMTI4OwogICAgICAgICAgaWYgKGtleUxlbmd0aCA8IDQwKSB7CiAgICAgICAgICAgIGtleUxlbmd0aCA8PD0gMzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihrZXlMZW5ndGgpIHx8IGtleUxlbmd0aCA8IDQwIHx8IGtleUxlbmd0aCAlIDggIT09IDApIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJpbnZhbGlkIGtleSBsZW5ndGgiKTsKICAgIH0KICAgIGNvbnN0IG93bmVyQnl0ZXMgPSBzdHJpbmdUb0J5dGVzKGRpY3QuZ2V0KCJPIikpLAogICAgICB1c2VyQnl0ZXMgPSBzdHJpbmdUb0J5dGVzKGRpY3QuZ2V0KCJVIikpOwogICAgY29uc3Qgb3duZXJQYXNzd29yZCA9IG93bmVyQnl0ZXMuc3ViYXJyYXkoMCwgMzIpOwogICAgY29uc3QgdXNlclBhc3N3b3JkID0gdXNlckJ5dGVzLnN1YmFycmF5KDAsIDMyKTsKICAgIGNvbnN0IGZsYWdzID0gZGljdC5nZXQoIlAiKTsKICAgIGNvbnN0IHJldmlzaW9uID0gZGljdC5nZXQoIlIiKTsKICAgIGNvbnN0IGVuY3J5cHRNZXRhZGF0YSA9IChhbGdvcml0aG0gPT09IDQgfHwgYWxnb3JpdGhtID09PSA1KSAmJiBkaWN0LmdldCgiRW5jcnlwdE1ldGFkYXRhIikgIT09IGZhbHNlOwogICAgdGhpcy5lbmNyeXB0TWV0YWRhdGEgPSBlbmNyeXB0TWV0YWRhdGE7CiAgICBjb25zdCBmaWxlSWRCeXRlcyA9IHN0cmluZ1RvQnl0ZXMoZmlsZUlkKTsKICAgIGxldCBwYXNzd29yZEJ5dGVzOwogICAgaWYgKHBhc3N3b3JkKSB7CiAgICAgIGlmIChyZXZpc2lvbiA9PT0gNikgewogICAgICAgIHRyeSB7CiAgICAgICAgICBwYXNzd29yZCA9IHV0ZjhTdHJpbmdUb1N0cmluZyhwYXNzd29yZCk7CiAgICAgICAgfSBjYXRjaCB7CiAgICAgICAgICB3YXJuKCJDaXBoZXJUcmFuc2Zvcm1GYWN0b3J5OiBVbmFibGUgdG8gY29udmVydCBVVEY4IGVuY29kZWQgcGFzc3dvcmQuIik7CiAgICAgICAgfQogICAgICB9CiAgICAgIHBhc3N3b3JkQnl0ZXMgPSBzdHJpbmdUb0J5dGVzKHBhc3N3b3JkKTsKICAgIH0KICAgIGxldCBlbmNyeXB0aW9uS2V5OwogICAgaWYgKGFsZ29yaXRobSAhPT0gNSkgewogICAgICBlbmNyeXB0aW9uS2V5ID0gdGhpcy4jcHJlcGFyZUtleURhdGEoZmlsZUlkQnl0ZXMsIHBhc3N3b3JkQnl0ZXMsIG93bmVyUGFzc3dvcmQsIHVzZXJQYXNzd29yZCwgZmxhZ3MsIHJldmlzaW9uLCBrZXlMZW5ndGgsIGVuY3J5cHRNZXRhZGF0YSk7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBvd25lclZhbGlkYXRpb25TYWx0ID0gb3duZXJCeXRlcy5zdWJhcnJheSgzMiwgNDApOwogICAgICBjb25zdCBvd25lcktleVNhbHQgPSBvd25lckJ5dGVzLnN1YmFycmF5KDQwLCA0OCk7CiAgICAgIGNvbnN0IHVCeXRlcyA9IHVzZXJCeXRlcy5zdWJhcnJheSgwLCA0OCk7CiAgICAgIGNvbnN0IHVzZXJWYWxpZGF0aW9uU2FsdCA9IHVzZXJCeXRlcy5zdWJhcnJheSgzMiwgNDApOwogICAgICBjb25zdCB1c2VyS2V5U2FsdCA9IHVzZXJCeXRlcy5zdWJhcnJheSg0MCwgNDgpOwogICAgICBjb25zdCBvd25lckVuY3J5cHRpb24gPSBzdHJpbmdUb0J5dGVzKGRpY3QuZ2V0KCJPRSIpKTsKICAgICAgY29uc3QgdXNlckVuY3J5cHRpb24gPSBzdHJpbmdUb0J5dGVzKGRpY3QuZ2V0KCJVRSIpKTsKICAgICAgY29uc3QgcGVybXMgPSBzdHJpbmdUb0J5dGVzKGRpY3QuZ2V0KCJQZXJtcyIpKTsKICAgICAgZW5jcnlwdGlvbktleSA9IHRoaXMuI2NyZWF0ZUVuY3J5cHRpb25LZXkyMChyZXZpc2lvbiwgcGFzc3dvcmRCeXRlcywgb3duZXJQYXNzd29yZCwgb3duZXJWYWxpZGF0aW9uU2FsdCwgb3duZXJLZXlTYWx0LCB1Qnl0ZXMsIHVzZXJQYXNzd29yZCwgdXNlclZhbGlkYXRpb25TYWx0LCB1c2VyS2V5U2FsdCwgb3duZXJFbmNyeXB0aW9uLCB1c2VyRW5jcnlwdGlvbiwgcGVybXMpOwogICAgfQogICAgaWYgKCFlbmNyeXB0aW9uS2V5KSB7CiAgICAgIGlmICghcGFzc3dvcmQpIHsKICAgICAgICB0aHJvdyBuZXcgUGFzc3dvcmRFeGNlcHRpb24oIk5vIHBhc3N3b3JkIGdpdmVuIiwgUGFzc3dvcmRSZXNwb25zZXMuTkVFRF9QQVNTV09SRCk7CiAgICAgIH0KICAgICAgY29uc3QgZGVjb2RlZFBhc3N3b3JkID0gdGhpcy4jZGVjb2RlVXNlclBhc3N3b3JkKHBhc3N3b3JkQnl0ZXMsIG93bmVyUGFzc3dvcmQsIHJldmlzaW9uLCBrZXlMZW5ndGgpOwogICAgICBlbmNyeXB0aW9uS2V5ID0gdGhpcy4jcHJlcGFyZUtleURhdGEoZmlsZUlkQnl0ZXMsIGRlY29kZWRQYXNzd29yZCwgb3duZXJQYXNzd29yZCwgdXNlclBhc3N3b3JkLCBmbGFncywgcmV2aXNpb24sIGtleUxlbmd0aCwgZW5jcnlwdE1ldGFkYXRhKTsKICAgIH0KICAgIGlmICghZW5jcnlwdGlvbktleSkgewogICAgICB0aHJvdyBuZXcgUGFzc3dvcmRFeGNlcHRpb24oIkluY29ycmVjdCBQYXNzd29yZCIsIFBhc3N3b3JkUmVzcG9uc2VzLklOQ09SUkVDVF9QQVNTV09SRCk7CiAgICB9CiAgICBpZiAoYWxnb3JpdGhtID09PSA0ICYmIGVuY3J5cHRpb25LZXkubGVuZ3RoIDwgMTYpIHsKICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5ID0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgICB0aGlzLmVuY3J5cHRpb25LZXkuc2V0KGVuY3J5cHRpb25LZXkpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5ID0gZW5jcnlwdGlvbktleTsKICAgIH0KICAgIGlmIChhbGdvcml0aG0gPj0gNCkgewogICAgICBjb25zdCBjZiA9IGRpY3QuZ2V0KCJDRiIpOwogICAgICBpZiAoY2YgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgICAgY2Yuc3VwcHJlc3NFbmNyeXB0aW9uID0gdHJ1ZTsKICAgICAgfQogICAgICB0aGlzLmNmID0gY2Y7CiAgICAgIHRoaXMuc3RtZiA9IGRpY3QuZ2V0KCJTdG1GIikgfHwgTmFtZS5nZXQoIklkZW50aXR5Iik7CiAgICAgIHRoaXMuc3RyZiA9IGRpY3QuZ2V0KCJTdHJGIikgfHwgTmFtZS5nZXQoIklkZW50aXR5Iik7CiAgICAgIHRoaXMuZWZmID0gZGljdC5nZXQoIkVGRiIpIHx8IHRoaXMuc3RtZjsKICAgIH0KICB9CiAgY3JlYXRlQ2lwaGVyVHJhbnNmb3JtKG51bSwgZ2VuKSB7CiAgICBpZiAodGhpcy5hbGdvcml0aG0gPT09IDQgfHwgdGhpcy5hbGdvcml0aG0gPT09IDUpIHsKICAgICAgcmV0dXJuIG5ldyBDaXBoZXJUcmFuc2Zvcm0odGhpcy4jYnVpbGRDaXBoZXJDb25zdHJ1Y3Rvcih0aGlzLmNmLCB0aGlzLnN0cmYsIG51bSwgZ2VuLCB0aGlzLmVuY3J5cHRpb25LZXkpLCB0aGlzLiNidWlsZENpcGhlckNvbnN0cnVjdG9yKHRoaXMuY2YsIHRoaXMuc3RtZiwgbnVtLCBnZW4sIHRoaXMuZW5jcnlwdGlvbktleSkpOwogICAgfQogICAgY29uc3Qga2V5ID0gdGhpcy4jYnVpbGRPYmplY3RLZXkobnVtLCBnZW4sIHRoaXMuZW5jcnlwdGlvbktleSwgZmFsc2UpOwogICAgY29uc3QgY2lwaGVyQ29uc3RydWN0b3IgPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBuZXcgQVJDRm91ckNpcGhlcihrZXkpOwogICAgfTsKICAgIHJldHVybiBuZXcgQ2lwaGVyVHJhbnNmb3JtKGNpcGhlckNvbnN0cnVjdG9yLCBjaXBoZXJDb25zdHJ1Y3Rvcik7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94cmVmLmpzCgoKCgoKCmNsYXNzIFhSZWYgewogIGNvbnN0cnVjdG9yKHN0cmVhbSwgcGRmTWFuYWdlcikgewogICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07CiAgICB0aGlzLnBkZk1hbmFnZXIgPSBwZGZNYW5hZ2VyOwogICAgdGhpcy5lbnRyaWVzID0gW107CiAgICB0aGlzLl94cmVmU3RtcyA9IG5ldyBTZXQoKTsKICAgIHRoaXMuX2NhY2hlTWFwID0gbmV3IE1hcCgpOwogICAgdGhpcy5fcGVuZGluZ1JlZnMgPSBuZXcgUmVmU2V0KCk7CiAgICB0aGlzLl9uZXdQZXJzaXN0ZW50UmVmTnVtID0gbnVsbDsKICAgIHRoaXMuX25ld1RlbXBvcmFyeVJlZk51bSA9IG51bGw7CiAgICB0aGlzLl9wZXJzaXN0ZW50UmVmc0NhY2hlID0gbnVsbDsKICB9CiAgZ2V0TmV3UGVyc2lzdGVudFJlZihvYmopIHsKICAgIGlmICh0aGlzLl9uZXdQZXJzaXN0ZW50UmVmTnVtID09PSBudWxsKSB7CiAgICAgIHRoaXMuX25ld1BlcnNpc3RlbnRSZWZOdW0gPSB0aGlzLmVudHJpZXMubGVuZ3RoIHx8IDE7CiAgICB9CiAgICBjb25zdCBudW0gPSB0aGlzLl9uZXdQZXJzaXN0ZW50UmVmTnVtKys7CiAgICB0aGlzLl9jYWNoZU1hcC5zZXQobnVtLCBvYmopOwogICAgcmV0dXJuIFJlZi5nZXQobnVtLCAwKTsKICB9CiAgZ2V0TmV3VGVtcG9yYXJ5UmVmKCkgewogICAgaWYgKHRoaXMuX25ld1RlbXBvcmFyeVJlZk51bSA9PT0gbnVsbCkgewogICAgICB0aGlzLl9uZXdUZW1wb3JhcnlSZWZOdW0gPSB0aGlzLmVudHJpZXMubGVuZ3RoIHx8IDE7CiAgICAgIGlmICh0aGlzLl9uZXdQZXJzaXN0ZW50UmVmTnVtKSB7CiAgICAgICAgdGhpcy5fcGVyc2lzdGVudFJlZnNDYWNoZSA9IG5ldyBNYXAoKTsKICAgICAgICBmb3IgKGxldCBpID0gdGhpcy5fbmV3VGVtcG9yYXJ5UmVmTnVtOyBpIDwgdGhpcy5fbmV3UGVyc2lzdGVudFJlZk51bTsgaSsrKSB7CiAgICAgICAgICB0aGlzLl9wZXJzaXN0ZW50UmVmc0NhY2hlLnNldChpLCB0aGlzLl9jYWNoZU1hcC5nZXQoaSkpOwogICAgICAgICAgdGhpcy5fY2FjaGVNYXAuZGVsZXRlKGkpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIFJlZi5nZXQodGhpcy5fbmV3VGVtcG9yYXJ5UmVmTnVtKyssIDApOwogIH0KICByZXNldE5ld1RlbXBvcmFyeVJlZigpIHsKICAgIHRoaXMuX25ld1RlbXBvcmFyeVJlZk51bSA9IG51bGw7CiAgICBpZiAodGhpcy5fcGVyc2lzdGVudFJlZnNDYWNoZSkgewogICAgICBmb3IgKGNvbnN0IFtudW0sIG9ial0gb2YgdGhpcy5fcGVyc2lzdGVudFJlZnNDYWNoZSkgewogICAgICAgIHRoaXMuX2NhY2hlTWFwLnNldChudW0sIG9iaik7CiAgICAgIH0KICAgIH0KICAgIHRoaXMuX3BlcnNpc3RlbnRSZWZzQ2FjaGUgPSBudWxsOwogIH0KICBzZXRTdGFydFhSZWYoc3RhcnRYUmVmKSB7CiAgICB0aGlzLnN0YXJ0WFJlZlF1ZXVlID0gW3N0YXJ0WFJlZl07CiAgfQogIHBhcnNlKHJlY292ZXJ5TW9kZSA9IGZhbHNlKSB7CiAgICBsZXQgdHJhaWxlckRpY3Q7CiAgICBpZiAoIXJlY292ZXJ5TW9kZSkgewogICAgICB0cmFpbGVyRGljdCA9IHRoaXMucmVhZFhSZWYoKTsKICAgIH0gZWxzZSB7CiAgICAgIHdhcm4oIkluZGV4aW5nIGFsbCBQREYgb2JqZWN0cyIpOwogICAgICB0cmFpbGVyRGljdCA9IHRoaXMuaW5kZXhPYmplY3RzKCk7CiAgICB9CiAgICB0cmFpbGVyRGljdC5hc3NpZ25YcmVmKHRoaXMpOwogICAgdGhpcy50cmFpbGVyID0gdHJhaWxlckRpY3Q7CiAgICBsZXQgZW5jcnlwdDsKICAgIHRyeSB7CiAgICAgIGVuY3J5cHQgPSB0cmFpbGVyRGljdC5nZXQoIkVuY3J5cHQiKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgd2FybihgWFJlZi5wYXJzZSAtIEludmFsaWQgIkVuY3J5cHQiIHJlZmVyZW5jZTogIiR7ZXh9Ii5gKTsKICAgIH0KICAgIGlmIChlbmNyeXB0IGluc3RhbmNlb2YgRGljdCkgewogICAgICBjb25zdCBpZHMgPSB0cmFpbGVyRGljdC5nZXQoIklEIik7CiAgICAgIGNvbnN0IGZpbGVJZCA9IGlkcz8ubGVuZ3RoID8gaWRzWzBdIDogIiI7CiAgICAgIGVuY3J5cHQuc3VwcHJlc3NFbmNyeXB0aW9uID0gdHJ1ZTsKICAgICAgdGhpcy5lbmNyeXB0ID0gbmV3IENpcGhlclRyYW5zZm9ybUZhY3RvcnkoZW5jcnlwdCwgZmlsZUlkLCB0aGlzLnBkZk1hbmFnZXIucGFzc3dvcmQpOwogICAgfQogICAgbGV0IHJvb3Q7CiAgICB0cnkgewogICAgICByb290ID0gdHJhaWxlckRpY3QuZ2V0KCJSb290Iik7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIHdhcm4oYFhSZWYucGFyc2UgLSBJbnZhbGlkICJSb290IiByZWZlcmVuY2U6ICIke2V4fSIuYCk7CiAgICB9CiAgICBpZiAocm9vdCBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgdHJ5IHsKICAgICAgICBjb25zdCBwYWdlcyA9IHJvb3QuZ2V0KCJQYWdlcyIpOwogICAgICAgIGlmIChwYWdlcyBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICAgIHRoaXMucm9vdCA9IHJvb3Q7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICB9IGNhdGNoIChleCkgewogICAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgICB0aHJvdyBleDsKICAgICAgICB9CiAgICAgICAgd2FybihgWFJlZi5wYXJzZSAtIEludmFsaWQgIlBhZ2VzIiByZWZlcmVuY2U6ICIke2V4fSIuYCk7CiAgICAgIH0KICAgIH0KICAgIGlmICghcmVjb3ZlcnlNb2RlKSB7CiAgICAgIHRocm93IG5ldyBYUmVmUGFyc2VFeGNlcHRpb24oKTsKICAgIH0KICAgIHRocm93IG5ldyBJbnZhbGlkUERGRXhjZXB0aW9uKCJJbnZhbGlkIFJvb3QgcmVmZXJlbmNlLiIpOwogIH0KICBwcm9jZXNzWFJlZlRhYmxlKHBhcnNlcikgewogICAgaWYgKCEoInRhYmxlU3RhdGUiIGluIHRoaXMpKSB7CiAgICAgIHRoaXMudGFibGVTdGF0ZSA9IHsKICAgICAgICBlbnRyeU51bTogMCwKICAgICAgICBzdHJlYW1Qb3M6IHBhcnNlci5sZXhlci5zdHJlYW0ucG9zLAogICAgICAgIHBhcnNlckJ1ZjE6IHBhcnNlci5idWYxLAogICAgICAgIHBhcnNlckJ1ZjI6IHBhcnNlci5idWYyCiAgICAgIH07CiAgICB9CiAgICBjb25zdCBvYmogPSB0aGlzLnJlYWRYUmVmVGFibGUocGFyc2VyKTsKICAgIGlmICghaXNDbWQob2JqLCAidHJhaWxlciIpKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIHRhYmxlOiBjb3VsZCBub3QgZmluZCB0cmFpbGVyIGRpY3Rpb25hcnkiKTsKICAgIH0KICAgIGxldCBkaWN0ID0gcGFyc2VyLmdldE9iaigpOwogICAgaWYgKCEoZGljdCBpbnN0YW5jZW9mIERpY3QpICYmIGRpY3QuZGljdCkgewogICAgICBkaWN0ID0gZGljdC5kaWN0OwogICAgfQogICAgaWYgKCEoZGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIHRhYmxlOiBjb3VsZCBub3QgcGFyc2UgdHJhaWxlciBkaWN0aW9uYXJ5Iik7CiAgICB9CiAgICBkZWxldGUgdGhpcy50YWJsZVN0YXRlOwogICAgcmV0dXJuIGRpY3Q7CiAgfQogIHJlYWRYUmVmVGFibGUocGFyc2VyKSB7CiAgICBjb25zdCBzdHJlYW0gPSBwYXJzZXIubGV4ZXIuc3RyZWFtOwogICAgY29uc3QgdGFibGVTdGF0ZSA9IHRoaXMudGFibGVTdGF0ZTsKICAgIHN0cmVhbS5wb3MgPSB0YWJsZVN0YXRlLnN0cmVhbVBvczsKICAgIHBhcnNlci5idWYxID0gdGFibGVTdGF0ZS5wYXJzZXJCdWYxOwogICAgcGFyc2VyLmJ1ZjIgPSB0YWJsZVN0YXRlLnBhcnNlckJ1ZjI7CiAgICBsZXQgb2JqOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgaWYgKCEoImZpcnN0RW50cnlOdW0iIGluIHRhYmxlU3RhdGUpIHx8ICEoImVudHJ5Q291bnQiIGluIHRhYmxlU3RhdGUpKSB7CiAgICAgICAgaWYgKGlzQ21kKG9iaiA9IHBhcnNlci5nZXRPYmooKSwgInRyYWlsZXIiKSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHRhYmxlU3RhdGUuZmlyc3RFbnRyeU51bSA9IG9iajsKICAgICAgICB0YWJsZVN0YXRlLmVudHJ5Q291bnQgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgIH0KICAgICAgbGV0IGZpcnN0ID0gdGFibGVTdGF0ZS5maXJzdEVudHJ5TnVtOwogICAgICBjb25zdCBjb3VudCA9IHRhYmxlU3RhdGUuZW50cnlDb3VudDsKICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGZpcnN0KSB8fCAhTnVtYmVyLmlzSW50ZWdlcihjb3VudCkpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgWFJlZiB0YWJsZTogd3JvbmcgdHlwZXMgaW4gc3Vic2VjdGlvbiBoZWFkZXIiKTsKICAgICAgfQogICAgICBmb3IgKGxldCBpID0gdGFibGVTdGF0ZS5lbnRyeU51bTsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgICB0YWJsZVN0YXRlLnN0cmVhbVBvcyA9IHN0cmVhbS5wb3M7CiAgICAgICAgdGFibGVTdGF0ZS5lbnRyeU51bSA9IGk7CiAgICAgICAgdGFibGVTdGF0ZS5wYXJzZXJCdWYxID0gcGFyc2VyLmJ1ZjE7CiAgICAgICAgdGFibGVTdGF0ZS5wYXJzZXJCdWYyID0gcGFyc2VyLmJ1ZjI7CiAgICAgICAgY29uc3QgZW50cnkgPSB7fTsKICAgICAgICBlbnRyeS5vZmZzZXQgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgICAgZW50cnkuZ2VuID0gcGFyc2VyLmdldE9iaigpOwogICAgICAgIGNvbnN0IHR5cGUgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgICAgaWYgKHR5cGUgaW5zdGFuY2VvZiBDbWQpIHsKICAgICAgICAgIHN3aXRjaCAodHlwZS5jbWQpIHsKICAgICAgICAgICAgY2FzZSAiZiI6CiAgICAgICAgICAgICAgZW50cnkuZnJlZSA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgIm4iOgogICAgICAgICAgICAgIGVudHJ5LnVuY29tcHJlc3NlZCA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihlbnRyeS5vZmZzZXQpIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKGVudHJ5LmdlbikgfHwgIShlbnRyeS5mcmVlIHx8IGVudHJ5LnVuY29tcHJlc3NlZCkpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBlbnRyeSBpbiBYUmVmIHN1YnNlY3Rpb246ICR7Zmlyc3R9LCAke2NvdW50fWApOwogICAgICAgIH0KICAgICAgICBpZiAoaSA9PT0gMCAmJiBlbnRyeS5mcmVlICYmIGZpcnN0ID09PSAxKSB7CiAgICAgICAgICBmaXJzdCA9IDA7CiAgICAgICAgfQogICAgICAgIGlmICghdGhpcy5lbnRyaWVzW2kgKyBmaXJzdF0pIHsKICAgICAgICAgIHRoaXMuZW50cmllc1tpICsgZmlyc3RdID0gZW50cnk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHRhYmxlU3RhdGUuZW50cnlOdW0gPSAwOwogICAgICB0YWJsZVN0YXRlLnN0cmVhbVBvcyA9IHN0cmVhbS5wb3M7CiAgICAgIHRhYmxlU3RhdGUucGFyc2VyQnVmMSA9IHBhcnNlci5idWYxOwogICAgICB0YWJsZVN0YXRlLnBhcnNlckJ1ZjIgPSBwYXJzZXIuYnVmMjsKICAgICAgZGVsZXRlIHRhYmxlU3RhdGUuZmlyc3RFbnRyeU51bTsKICAgICAgZGVsZXRlIHRhYmxlU3RhdGUuZW50cnlDb3VudDsKICAgIH0KICAgIGlmICh0aGlzLmVudHJpZXNbMF0gJiYgIXRoaXMuZW50cmllc1swXS5mcmVlKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIHRhYmxlOiB1bmV4cGVjdGVkIGZpcnN0IG9iamVjdCIpOwogICAgfQogICAgcmV0dXJuIG9iajsKICB9CiAgcHJvY2Vzc1hSZWZTdHJlYW0oc3RyZWFtKSB7CiAgICBpZiAoISgic3RyZWFtU3RhdGUiIGluIHRoaXMpKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBkaWN0LAogICAgICAgIHBvcwogICAgICB9ID0gc3RyZWFtOwogICAgICBjb25zdCBieXRlV2lkdGhzID0gZGljdC5nZXQoIlciKTsKICAgICAgY29uc3QgcmFuZ2UgPSBkaWN0LmdldCgiSW5kZXgiKSB8fCBbMCwgZGljdC5nZXQoIlNpemUiKV07CiAgICAgIHRoaXMuc3RyZWFtU3RhdGUgPSB7CiAgICAgICAgZW50cnlSYW5nZXM6IHJhbmdlLAogICAgICAgIGJ5dGVXaWR0aHMsCiAgICAgICAgZW50cnlOdW06IDAsCiAgICAgICAgc3RyZWFtUG9zOiBwb3MKICAgICAgfTsKICAgIH0KICAgIHRoaXMucmVhZFhSZWZTdHJlYW0oc3RyZWFtKTsKICAgIGRlbGV0ZSB0aGlzLnN0cmVhbVN0YXRlOwogICAgcmV0dXJuIHN0cmVhbS5kaWN0OwogIH0KICByZWFkWFJlZlN0cmVhbShzdHJlYW0pIHsKICAgIGNvbnN0IHN0cmVhbVN0YXRlID0gdGhpcy5zdHJlYW1TdGF0ZTsKICAgIHN0cmVhbS5wb3MgPSBzdHJlYW1TdGF0ZS5zdHJlYW1Qb3M7CiAgICBjb25zdCBbdHlwZUZpZWxkV2lkdGgsIG9mZnNldEZpZWxkV2lkdGgsIGdlbmVyYXRpb25GaWVsZFdpZHRoXSA9IHN0cmVhbVN0YXRlLmJ5dGVXaWR0aHM7CiAgICBjb25zdCBlbnRyeVJhbmdlcyA9IHN0cmVhbVN0YXRlLmVudHJ5UmFuZ2VzOwogICAgd2hpbGUgKGVudHJ5UmFuZ2VzLmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgW2ZpcnN0LCBuXSA9IGVudHJ5UmFuZ2VzOwogICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoZmlyc3QpIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG4pKSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIFhSZWYgcmFuZ2UgZmllbGRzOiAke2ZpcnN0fSwgJHtufWApOwogICAgICB9CiAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcih0eXBlRmllbGRXaWR0aCkgfHwgIU51bWJlci5pc0ludGVnZXIob2Zmc2V0RmllbGRXaWR0aCkgfHwgIU51bWJlci5pc0ludGVnZXIoZ2VuZXJhdGlvbkZpZWxkV2lkdGgpKSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIFhSZWYgZW50cnkgZmllbGRzIGxlbmd0aDogJHtmaXJzdH0sICR7bn1gKTsKICAgICAgfQogICAgICBmb3IgKGxldCBpID0gc3RyZWFtU3RhdGUuZW50cnlOdW07IGkgPCBuOyArK2kpIHsKICAgICAgICBzdHJlYW1TdGF0ZS5lbnRyeU51bSA9IGk7CiAgICAgICAgc3RyZWFtU3RhdGUuc3RyZWFtUG9zID0gc3RyZWFtLnBvczsKICAgICAgICBsZXQgdHlwZSA9IDAsCiAgICAgICAgICBvZmZzZXQgPSAwLAogICAgICAgICAgZ2VuZXJhdGlvbiA9IDA7CiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0eXBlRmllbGRXaWR0aDsgKytqKSB7CiAgICAgICAgICBjb25zdCB0eXBlQnl0ZSA9IHN0cmVhbS5nZXRCeXRlKCk7CiAgICAgICAgICBpZiAodHlwZUJ5dGUgPT09IC0xKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIGJ5dGVXaWR0aHMgJ3R5cGUnLiIpOwogICAgICAgICAgfQogICAgICAgICAgdHlwZSA9IHR5cGUgPDwgOCB8IHR5cGVCeXRlOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZUZpZWxkV2lkdGggPT09IDApIHsKICAgICAgICAgIHR5cGUgPSAxOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG9mZnNldEZpZWxkV2lkdGg7ICsraikgewogICAgICAgICAgY29uc3Qgb2Zmc2V0Qnl0ZSA9IHN0cmVhbS5nZXRCeXRlKCk7CiAgICAgICAgICBpZiAob2Zmc2V0Qnl0ZSA9PT0gLTEpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgYnl0ZVdpZHRocyAnb2Zmc2V0Jy4iKTsKICAgICAgICAgIH0KICAgICAgICAgIG9mZnNldCA9IG9mZnNldCA8PCA4IHwgb2Zmc2V0Qnl0ZTsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBnZW5lcmF0aW9uRmllbGRXaWR0aDsgKytqKSB7CiAgICAgICAgICBjb25zdCBnZW5lcmF0aW9uQnl0ZSA9IHN0cmVhbS5nZXRCeXRlKCk7CiAgICAgICAgICBpZiAoZ2VuZXJhdGlvbkJ5dGUgPT09IC0xKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIGJ5dGVXaWR0aHMgJ2dlbmVyYXRpb24nLiIpOwogICAgICAgICAgfQogICAgICAgICAgZ2VuZXJhdGlvbiA9IGdlbmVyYXRpb24gPDwgOCB8IGdlbmVyYXRpb25CeXRlOwogICAgICAgIH0KICAgICAgICBjb25zdCBlbnRyeSA9IHt9OwogICAgICAgIGVudHJ5Lm9mZnNldCA9IG9mZnNldDsKICAgICAgICBlbnRyeS5nZW4gPSBnZW5lcmF0aW9uOwogICAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICBlbnRyeS5mcmVlID0gdHJ1ZTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIGVudHJ5LnVuY29tcHJlc3NlZCA9IHRydWU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBYUmVmIGVudHJ5IHR5cGU6ICR7dHlwZX1gKTsKICAgICAgICB9CiAgICAgICAgaWYgKCF0aGlzLmVudHJpZXNbZmlyc3QgKyBpXSkgewogICAgICAgICAgdGhpcy5lbnRyaWVzW2ZpcnN0ICsgaV0gPSBlbnRyeTsKICAgICAgICB9CiAgICAgIH0KICAgICAgc3RyZWFtU3RhdGUuZW50cnlOdW0gPSAwOwogICAgICBzdHJlYW1TdGF0ZS5zdHJlYW1Qb3MgPSBzdHJlYW0ucG9zOwogICAgICBlbnRyeVJhbmdlcy5zcGxpY2UoMCwgMik7CiAgICB9CiAgfQogIGluZGV4T2JqZWN0cygpIHsKICAgIGNvbnN0IFRBQiA9IDB4OSwKICAgICAgTEYgPSAweGEsCiAgICAgIENSID0gMHhkLAogICAgICBTUEFDRSA9IDB4MjA7CiAgICBjb25zdCBQRVJDRU5UID0gMHgyNSwKICAgICAgTFQgPSAweDNjOwogICAgZnVuY3Rpb24gcmVhZFRva2VuKGRhdGEsIG9mZnNldCkgewogICAgICBsZXQgdG9rZW4gPSAiIiwKICAgICAgICBjaCA9IGRhdGFbb2Zmc2V0XTsKICAgICAgd2hpbGUgKGNoICE9PSBMRiAmJiBjaCAhPT0gQ1IgJiYgY2ggIT09IExUKSB7CiAgICAgICAgaWYgKCsrb2Zmc2V0ID49IGRhdGEubGVuZ3RoKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdG9rZW4gKz0gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICAgICAgY2ggPSBkYXRhW29mZnNldF07CiAgICAgIH0KICAgICAgcmV0dXJuIHRva2VuOwogICAgfQogICAgZnVuY3Rpb24gc2tpcFVudGlsKGRhdGEsIG9mZnNldCwgd2hhdCkgewogICAgICBjb25zdCBsZW5ndGggPSB3aGF0Lmxlbmd0aCwKICAgICAgICBkYXRhTGVuZ3RoID0gZGF0YS5sZW5ndGg7CiAgICAgIGxldCBza2lwcGVkID0gMDsKICAgICAgd2hpbGUgKG9mZnNldCA8IGRhdGFMZW5ndGgpIHsKICAgICAgICBsZXQgaSA9IDA7CiAgICAgICAgd2hpbGUgKGkgPCBsZW5ndGggJiYgZGF0YVtvZmZzZXQgKyBpXSA9PT0gd2hhdFtpXSkgewogICAgICAgICAgKytpOwogICAgICAgIH0KICAgICAgICBpZiAoaSA+PSBsZW5ndGgpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBvZmZzZXQrKzsKICAgICAgICBza2lwcGVkKys7CiAgICAgIH0KICAgICAgcmV0dXJuIHNraXBwZWQ7CiAgICB9CiAgICBjb25zdCBnRW5kb2JqUmVnRXhwID0gL1xiKGVuZG9ianxcZCtccytcZCtccytvYmp8eHJlZnx0cmFpbGVyXHMqPDwpXGIvZzsKICAgIGNvbnN0IGdTdGFydHhyZWZSZWdFeHAgPSAvXGIoc3RhcnR4cmVmfFxkK1xzK1xkK1xzK29iailcYi9nOwogICAgY29uc3Qgb2JqUmVnRXhwID0gL14oXGQrKVxzKyhcZCspXHMrb2JqXGIvOwogICAgY29uc3QgdHJhaWxlckJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoWzExNiwgMTE0LCA5NywgMTA1LCAxMDgsIDEwMSwgMTE0XSk7CiAgICBjb25zdCBzdGFydHhyZWZCeXRlcyA9IG5ldyBVaW50OEFycmF5KFsxMTUsIDExNiwgOTcsIDExNCwgMTE2LCAxMjAsIDExNCwgMTAxLCAxMDJdKTsKICAgIGNvbnN0IHhyZWZCeXRlcyA9IG5ldyBVaW50OEFycmF5KFs0NywgODgsIDgyLCAxMDEsIDEwMl0pOwogICAgdGhpcy5lbnRyaWVzLmxlbmd0aCA9IDA7CiAgICB0aGlzLl9jYWNoZU1hcC5jbGVhcigpOwogICAgY29uc3Qgc3RyZWFtID0gdGhpcy5zdHJlYW07CiAgICBzdHJlYW0ucG9zID0gMDsKICAgIGNvbnN0IGJ1ZmZlciA9IHN0cmVhbS5nZXRCeXRlcygpLAogICAgICBidWZmZXJTdHIgPSBieXRlc1RvU3RyaW5nKGJ1ZmZlciksCiAgICAgIGxlbmd0aCA9IGJ1ZmZlci5sZW5ndGg7CiAgICBsZXQgcG9zaXRpb24gPSBzdHJlYW0uc3RhcnQ7CiAgICBjb25zdCB0cmFpbGVycyA9IFtdLAogICAgICB4cmVmU3RtcyA9IFtdOwogICAgd2hpbGUgKHBvc2l0aW9uIDwgbGVuZ3RoKSB7CiAgICAgIGxldCBjaCA9IGJ1ZmZlcltwb3NpdGlvbl07CiAgICAgIGlmIChjaCA9PT0gVEFCIHx8IGNoID09PSBMRiB8fCBjaCA9PT0gQ1IgfHwgY2ggPT09IFNQQUNFKSB7CiAgICAgICAgKytwb3NpdGlvbjsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoY2ggPT09IFBFUkNFTlQpIHsKICAgICAgICBkbyB7CiAgICAgICAgICArK3Bvc2l0aW9uOwogICAgICAgICAgaWYgKHBvc2l0aW9uID49IGxlbmd0aCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNoID0gYnVmZmVyW3Bvc2l0aW9uXTsKICAgICAgICB9IHdoaWxlIChjaCAhPT0gTEYgJiYgY2ggIT09IENSKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB0b2tlbiA9IHJlYWRUb2tlbihidWZmZXIsIHBvc2l0aW9uKTsKICAgICAgbGV0IG07CiAgICAgIGlmICh0b2tlbi5zdGFydHNXaXRoKCJ4cmVmIikgJiYgKHRva2VuLmxlbmd0aCA9PT0gNCB8fCAvXHMvLnRlc3QodG9rZW5bNF0pKSkgewogICAgICAgIHBvc2l0aW9uICs9IHNraXBVbnRpbChidWZmZXIsIHBvc2l0aW9uLCB0cmFpbGVyQnl0ZXMpOwogICAgICAgIHRyYWlsZXJzLnB1c2gocG9zaXRpb24pOwogICAgICAgIHBvc2l0aW9uICs9IHNraXBVbnRpbChidWZmZXIsIHBvc2l0aW9uLCBzdGFydHhyZWZCeXRlcyk7CiAgICAgIH0gZWxzZSBpZiAobSA9IG9ialJlZ0V4cC5leGVjKHRva2VuKSkgewogICAgICAgIGNvbnN0IG51bSA9IG1bMV0gfCAwLAogICAgICAgICAgZ2VuID0gbVsyXSB8IDA7CiAgICAgICAgY29uc3Qgc3RhcnRQb3MgPSBwb3NpdGlvbiArIHRva2VuLmxlbmd0aDsKICAgICAgICBsZXQgY29udGVudExlbmd0aCwKICAgICAgICAgIHVwZGF0ZUVudHJpZXMgPSBmYWxzZTsKICAgICAgICBpZiAoIXRoaXMuZW50cmllc1tudW1dKSB7CiAgICAgICAgICB1cGRhdGVFbnRyaWVzID0gdHJ1ZTsKICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZW50cmllc1tudW1dLmdlbiA9PT0gZ2VuKSB7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBjb25zdCBwYXJzZXIgPSBuZXcgUGFyc2VyKHsKICAgICAgICAgICAgICBsZXhlcjogbmV3IExleGVyKHN0cmVhbS5tYWtlU3ViU3RyZWFtKHN0YXJ0UG9zKSkKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHBhcnNlci5nZXRPYmooKTsKICAgICAgICAgICAgdXBkYXRlRW50cmllcyA9IHRydWU7CiAgICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXJzZXJFT0ZFeGNlcHRpb24pIHsKICAgICAgICAgICAgICB3YXJuKGBpbmRleE9iamVjdHMgLS0gY2hlY2tpbmcgb2JqZWN0ICgke3Rva2VufSk6ICIke2V4fSIuYCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdXBkYXRlRW50cmllcyA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHVwZGF0ZUVudHJpZXMpIHsKICAgICAgICAgIHRoaXMuZW50cmllc1tudW1dID0gewogICAgICAgICAgICBvZmZzZXQ6IHBvc2l0aW9uIC0gc3RyZWFtLnN0YXJ0LAogICAgICAgICAgICBnZW4sCiAgICAgICAgICAgIHVuY29tcHJlc3NlZDogdHJ1ZQogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgZ0VuZG9ialJlZ0V4cC5sYXN0SW5kZXggPSBzdGFydFBvczsKICAgICAgICBjb25zdCBtYXRjaCA9IGdFbmRvYmpSZWdFeHAuZXhlYyhidWZmZXJTdHIpOwogICAgICAgIGlmIChtYXRjaCkgewogICAgICAgICAgY29uc3QgZW5kUG9zID0gZ0VuZG9ialJlZ0V4cC5sYXN0SW5kZXggKyAxOwogICAgICAgICAgY29udGVudExlbmd0aCA9IGVuZFBvcyAtIHBvc2l0aW9uOwogICAgICAgICAgaWYgKG1hdGNoWzFdICE9PSAiZW5kb2JqIikgewogICAgICAgICAgICB3YXJuKGBpbmRleE9iamVjdHM6IEZvdW5kICIke21hdGNoWzFdfSIgaW5zaWRlIG9mIGFub3RoZXIgIm9iaiIsIGAgKyAnY2F1c2VkIGJ5IG1pc3NpbmcgImVuZG9iaiIgLS0gdHJ5aW5nIHRvIHJlY292ZXIuJyk7CiAgICAgICAgICAgIGNvbnRlbnRMZW5ndGggLT0gbWF0Y2hbMV0ubGVuZ3RoICsgMTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29udGVudExlbmd0aCA9IGxlbmd0aCAtIHBvc2l0aW9uOwogICAgICAgIH0KICAgICAgICBjb25zdCBjb250ZW50ID0gYnVmZmVyLnN1YmFycmF5KHBvc2l0aW9uLCBwb3NpdGlvbiArIGNvbnRlbnRMZW5ndGgpOwogICAgICAgIGNvbnN0IHhyZWZUYWdPZmZzZXQgPSBza2lwVW50aWwoY29udGVudCwgMCwgeHJlZkJ5dGVzKTsKICAgICAgICBpZiAoeHJlZlRhZ09mZnNldCA8IGNvbnRlbnRMZW5ndGggJiYgY29udGVudFt4cmVmVGFnT2Zmc2V0ICsgNV0gPCA2NCkgewogICAgICAgICAgeHJlZlN0bXMucHVzaChwb3NpdGlvbiAtIHN0cmVhbS5zdGFydCk7CiAgICAgICAgICB0aGlzLl94cmVmU3Rtcy5hZGQocG9zaXRpb24gLSBzdHJlYW0uc3RhcnQpOwogICAgICAgIH0KICAgICAgICBwb3NpdGlvbiArPSBjb250ZW50TGVuZ3RoOwogICAgICB9IGVsc2UgaWYgKHRva2VuLnN0YXJ0c1dpdGgoInRyYWlsZXIiKSAmJiAodG9rZW4ubGVuZ3RoID09PSA3IHx8IC9ccy8udGVzdCh0b2tlbls3XSkpKSB7CiAgICAgICAgdHJhaWxlcnMucHVzaChwb3NpdGlvbik7CiAgICAgICAgY29uc3Qgc3RhcnRQb3MgPSBwb3NpdGlvbiArIHRva2VuLmxlbmd0aDsKICAgICAgICBsZXQgY29udGVudExlbmd0aDsKICAgICAgICBnU3RhcnR4cmVmUmVnRXhwLmxhc3RJbmRleCA9IHN0YXJ0UG9zOwogICAgICAgIGNvbnN0IG1hdGNoID0gZ1N0YXJ0eHJlZlJlZ0V4cC5leGVjKGJ1ZmZlclN0cik7CiAgICAgICAgaWYgKG1hdGNoKSB7CiAgICAgICAgICBjb25zdCBlbmRQb3MgPSBnU3RhcnR4cmVmUmVnRXhwLmxhc3RJbmRleCArIDE7CiAgICAgICAgICBjb250ZW50TGVuZ3RoID0gZW5kUG9zIC0gcG9zaXRpb247CiAgICAgICAgICBpZiAobWF0Y2hbMV0gIT09ICJzdGFydHhyZWYiKSB7CiAgICAgICAgICAgIHdhcm4oYGluZGV4T2JqZWN0czogRm91bmQgIiR7bWF0Y2hbMV19IiBhZnRlciAidHJhaWxlciIsIGAgKyAnY2F1c2VkIGJ5IG1pc3NpbmcgInN0YXJ0eHJlZiIgLS0gdHJ5aW5nIHRvIHJlY292ZXIuJyk7CiAgICAgICAgICAgIGNvbnRlbnRMZW5ndGggLT0gbWF0Y2hbMV0ubGVuZ3RoICsgMTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29udGVudExlbmd0aCA9IGxlbmd0aCAtIHBvc2l0aW9uOwogICAgICAgIH0KICAgICAgICBwb3NpdGlvbiArPSBjb250ZW50TGVuZ3RoOwogICAgICB9IGVsc2UgewogICAgICAgIHBvc2l0aW9uICs9IHRva2VuLmxlbmd0aCArIDE7CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgeHJlZlN0bSBvZiB4cmVmU3RtcykgewogICAgICB0aGlzLnN0YXJ0WFJlZlF1ZXVlLnB1c2goeHJlZlN0bSk7CiAgICAgIHRoaXMucmVhZFhSZWYodHJ1ZSk7CiAgICB9CiAgICBjb25zdCB0cmFpbGVyRGljdHMgPSBbXTsKICAgIGxldCBpc0VuY3J5cHRlZCA9IGZhbHNlOwogICAgZm9yIChjb25zdCB0cmFpbGVyIG9mIHRyYWlsZXJzKSB7CiAgICAgIHN0cmVhbS5wb3MgPSB0cmFpbGVyOwogICAgICBjb25zdCBwYXJzZXIgPSBuZXcgUGFyc2VyKHsKICAgICAgICBsZXhlcjogbmV3IExleGVyKHN0cmVhbSksCiAgICAgICAgeHJlZjogdGhpcywKICAgICAgICBhbGxvd1N0cmVhbXM6IHRydWUsCiAgICAgICAgcmVjb3ZlcnlNb2RlOiB0cnVlCiAgICAgIH0pOwogICAgICBjb25zdCBvYmogPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgIGlmICghaXNDbWQob2JqLCAidHJhaWxlciIpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgZGljdCA9IHBhcnNlci5nZXRPYmooKTsKICAgICAgaWYgKCEoZGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgdHJhaWxlckRpY3RzLnB1c2goZGljdCk7CiAgICAgIGlmIChkaWN0LmhhcygiRW5jcnlwdCIpKSB7CiAgICAgICAgaXNFbmNyeXB0ZWQgPSB0cnVlOwogICAgICB9CiAgICB9CiAgICBsZXQgdHJhaWxlckRpY3QsIHRyYWlsZXJFcnJvcjsKICAgIGZvciAoY29uc3QgZGljdCBvZiBbLi4udHJhaWxlckRpY3RzLCAiZ2VuRmFsbGJhY2siLCAuLi50cmFpbGVyRGljdHNdKSB7CiAgICAgIGlmIChkaWN0ID09PSAiZ2VuRmFsbGJhY2siKSB7CiAgICAgICAgaWYgKCF0cmFpbGVyRXJyb3IpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICB0aGlzLl9nZW5lcmF0aW9uRmFsbGJhY2sgPSB0cnVlOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGxldCB2YWxpZFBhZ2VzRGljdCA9IGZhbHNlOwogICAgICB0cnkgewogICAgICAgIGNvbnN0IHJvb3REaWN0ID0gZGljdC5nZXQoIlJvb3QiKTsKICAgICAgICBpZiAoIShyb290RGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcGFnZXNEaWN0ID0gcm9vdERpY3QuZ2V0KCJQYWdlcyIpOwogICAgICAgIGlmICghKHBhZ2VzRGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcGFnZXNDb3VudCA9IHBhZ2VzRGljdC5nZXQoIkNvdW50Iik7CiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIocGFnZXNDb3VudCkpIHsKICAgICAgICAgIHZhbGlkUGFnZXNEaWN0ID0gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgdHJhaWxlckVycm9yID0gZXg7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKHZhbGlkUGFnZXNEaWN0ICYmICghaXNFbmNyeXB0ZWQgfHwgZGljdC5oYXMoIkVuY3J5cHQiKSkgJiYgZGljdC5oYXMoIklEIikpIHsKICAgICAgICByZXR1cm4gZGljdDsKICAgICAgfQogICAgICB0cmFpbGVyRGljdCA9IGRpY3Q7CiAgICB9CiAgICBpZiAodHJhaWxlckRpY3QpIHsKICAgICAgcmV0dXJuIHRyYWlsZXJEaWN0OwogICAgfQogICAgaWYgKHRoaXMudG9wRGljdCkgewogICAgICByZXR1cm4gdGhpcy50b3BEaWN0OwogICAgfQogICAgaWYgKCF0cmFpbGVyRGljdHMubGVuZ3RoKSB7CiAgICAgIGZvciAoY29uc3QgbnVtIGluIHRoaXMuZW50cmllcykgewogICAgICAgIGlmICghT2JqZWN0Lmhhc093bih0aGlzLmVudHJpZXMsIG51bSkpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBlbnRyeSA9IHRoaXMuZW50cmllc1tudW1dOwogICAgICAgIGNvbnN0IHJlZiA9IFJlZi5nZXQocGFyc2VJbnQobnVtKSwgZW50cnkuZ2VuKTsKICAgICAgICBsZXQgb2JqOwogICAgICAgIHRyeSB7CiAgICAgICAgICBvYmogPSB0aGlzLmZldGNoKHJlZik7CiAgICAgICAgfSBjYXRjaCB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgICAgIG9iaiA9IG9iai5kaWN0OwogICAgICAgIH0KICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgRGljdCAmJiBvYmouaGFzKCJSb290IikpIHsKICAgICAgICAgIHJldHVybiBvYmo7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICB0aHJvdyBuZXcgSW52YWxpZFBERkV4Y2VwdGlvbigiSW52YWxpZCBQREYgc3RydWN0dXJlLiIpOwogIH0KICByZWFkWFJlZihyZWNvdmVyeU1vZGUgPSBmYWxzZSkgewogICAgY29uc3Qgc3RyZWFtID0gdGhpcy5zdHJlYW07CiAgICBjb25zdCBzdGFydFhSZWZQYXJzZWRDYWNoZSA9IG5ldyBTZXQoKTsKICAgIHdoaWxlICh0aGlzLnN0YXJ0WFJlZlF1ZXVlLmxlbmd0aCkgewogICAgICB0cnkgewogICAgICAgIGNvbnN0IHN0YXJ0WFJlZiA9IHRoaXMuc3RhcnRYUmVmUXVldWVbMF07CiAgICAgICAgaWYgKHN0YXJ0WFJlZlBhcnNlZENhY2hlLmhhcyhzdGFydFhSZWYpKSB7CiAgICAgICAgICB3YXJuKCJyZWFkWFJlZiAtIHNraXBwaW5nIFhSZWYgdGFibGUgc2luY2UgaXQgd2FzIGFscmVhZHkgcGFyc2VkLiIpOwogICAgICAgICAgdGhpcy5zdGFydFhSZWZRdWV1ZS5zaGlmdCgpOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIHN0YXJ0WFJlZlBhcnNlZENhY2hlLmFkZChzdGFydFhSZWYpOwogICAgICAgIHN0cmVhbS5wb3MgPSBzdGFydFhSZWYgKyBzdHJlYW0uc3RhcnQ7CiAgICAgICAgY29uc3QgcGFyc2VyID0gbmV3IFBhcnNlcih7CiAgICAgICAgICBsZXhlcjogbmV3IExleGVyKHN0cmVhbSksCiAgICAgICAgICB4cmVmOiB0aGlzLAogICAgICAgICAgYWxsb3dTdHJlYW1zOiB0cnVlCiAgICAgICAgfSk7CiAgICAgICAgbGV0IG9iaiA9IHBhcnNlci5nZXRPYmooKTsKICAgICAgICBsZXQgZGljdDsKICAgICAgICBpZiAoaXNDbWQob2JqLCAieHJlZiIpKSB7CiAgICAgICAgICBkaWN0ID0gdGhpcy5wcm9jZXNzWFJlZlRhYmxlKHBhcnNlcik7CiAgICAgICAgICBpZiAoIXRoaXMudG9wRGljdCkgewogICAgICAgICAgICB0aGlzLnRvcERpY3QgPSBkaWN0OwogICAgICAgICAgfQogICAgICAgICAgb2JqID0gZGljdC5nZXQoIlhSZWZTdG0iKTsKICAgICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKG9iaikgJiYgIXRoaXMuX3hyZWZTdG1zLmhhcyhvYmopKSB7CiAgICAgICAgICAgIHRoaXMuX3hyZWZTdG1zLmFkZChvYmopOwogICAgICAgICAgICB0aGlzLnN0YXJ0WFJlZlF1ZXVlLnB1c2gob2JqKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKE51bWJlci5pc0ludGVnZXIob2JqKSkgewogICAgICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHBhcnNlci5nZXRPYmooKSkgfHwgIWlzQ21kKHBhcnNlci5nZXRPYmooKSwgIm9iaiIpIHx8ICEoKG9iaiA9IHBhcnNlci5nZXRPYmooKSkgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgWFJlZiBzdHJlYW0iKTsKICAgICAgICAgIH0KICAgICAgICAgIGRpY3QgPSB0aGlzLnByb2Nlc3NYUmVmU3RyZWFtKG9iaik7CiAgICAgICAgICBpZiAoIXRoaXMudG9wRGljdCkgewogICAgICAgICAgICB0aGlzLnRvcERpY3QgPSBkaWN0OwogICAgICAgICAgfQogICAgICAgICAgaWYgKCFkaWN0KSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiRmFpbGVkIHRvIHJlYWQgWFJlZiBzdHJlYW0iKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgc3RyZWFtIGhlYWRlciIpOwogICAgICAgIH0KICAgICAgICBvYmogPSBkaWN0LmdldCgiUHJldiIpOwogICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKG9iaikpIHsKICAgICAgICAgIHRoaXMuc3RhcnRYUmVmUXVldWUucHVzaChvYmopOwogICAgICAgIH0gZWxzZSBpZiAob2JqIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICB0aGlzLnN0YXJ0WFJlZlF1ZXVlLnB1c2gob2JqLm51bSk7CiAgICAgICAgfQogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgICAgdGhyb3cgZTsKICAgICAgICB9CiAgICAgICAgaW5mbygiKHdoaWxlIHJlYWRpbmcgWFJlZik6ICIgKyBlKTsKICAgICAgfQogICAgICB0aGlzLnN0YXJ0WFJlZlF1ZXVlLnNoaWZ0KCk7CiAgICB9CiAgICBpZiAodGhpcy50b3BEaWN0KSB7CiAgICAgIHJldHVybiB0aGlzLnRvcERpY3Q7CiAgICB9CiAgICBpZiAocmVjb3ZlcnlNb2RlKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICB0aHJvdyBuZXcgWFJlZlBhcnNlRXhjZXB0aW9uKCk7CiAgfQogIGdldEVudHJ5KGkpIHsKICAgIGNvbnN0IHhyZWZFbnRyeSA9IHRoaXMuZW50cmllc1tpXTsKICAgIGlmICh4cmVmRW50cnkgJiYgIXhyZWZFbnRyeS5mcmVlICYmIHhyZWZFbnRyeS5vZmZzZXQpIHsKICAgICAgcmV0dXJuIHhyZWZFbnRyeTsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICBmZXRjaElmUmVmKG9iaiwgc3VwcHJlc3NFbmNyeXB0aW9uID0gZmFsc2UpIHsKICAgIGlmIChvYmogaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgcmV0dXJuIHRoaXMuZmV0Y2gob2JqLCBzdXBwcmVzc0VuY3J5cHRpb24pOwogICAgfQogICAgcmV0dXJuIG9iajsKICB9CiAgZmV0Y2gocmVmLCBzdXBwcmVzc0VuY3J5cHRpb24gPSBmYWxzZSkgewogICAgaWYgKCEocmVmIGluc3RhbmNlb2YgUmVmKSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoInJlZiBvYmplY3QgaXMgbm90IGEgcmVmZXJlbmNlIik7CiAgICB9CiAgICBjb25zdCBudW0gPSByZWYubnVtOwogICAgY29uc3QgY2FjaGVFbnRyeSA9IHRoaXMuX2NhY2hlTWFwLmdldChudW0pOwogICAgaWYgKGNhY2hlRW50cnkgIT09IHVuZGVmaW5lZCkgewogICAgICBpZiAoY2FjaGVFbnRyeSBpbnN0YW5jZW9mIERpY3QgJiYgIWNhY2hlRW50cnkub2JqSWQpIHsKICAgICAgICBjYWNoZUVudHJ5Lm9iaklkID0gcmVmLnRvU3RyaW5nKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIGNhY2hlRW50cnk7CiAgICB9CiAgICBsZXQgeHJlZkVudHJ5ID0gdGhpcy5nZXRFbnRyeShudW0pOwogICAgaWYgKHhyZWZFbnRyeSA9PT0gbnVsbCkgewogICAgICByZXR1cm4geHJlZkVudHJ5OwogICAgfQogICAgaWYgKHRoaXMuX3BlbmRpbmdSZWZzLmhhcyhyZWYpKSB7CiAgICAgIHRoaXMuX3BlbmRpbmdSZWZzLnJlbW92ZShyZWYpOwogICAgICB3YXJuKGBJZ25vcmluZyBjaXJjdWxhciByZWZlcmVuY2U6ICR7cmVmfS5gKTsKICAgICAgcmV0dXJuIENJUkNVTEFSX1JFRjsKICAgIH0KICAgIHRoaXMuX3BlbmRpbmdSZWZzLnB1dChyZWYpOwogICAgdHJ5IHsKICAgICAgeHJlZkVudHJ5ID0geHJlZkVudHJ5LnVuY29tcHJlc3NlZCA/IHRoaXMuZmV0Y2hVbmNvbXByZXNzZWQocmVmLCB4cmVmRW50cnksIHN1cHByZXNzRW5jcnlwdGlvbikgOiB0aGlzLmZldGNoQ29tcHJlc3NlZChyZWYsIHhyZWZFbnRyeSwgc3VwcHJlc3NFbmNyeXB0aW9uKTsKICAgICAgdGhpcy5fcGVuZGluZ1JlZnMucmVtb3ZlKHJlZik7CiAgICB9IGNhdGNoIChleCkgewogICAgICB0aGlzLl9wZW5kaW5nUmVmcy5yZW1vdmUocmVmKTsKICAgICAgdGhyb3cgZXg7CiAgICB9CiAgICBpZiAoeHJlZkVudHJ5IGluc3RhbmNlb2YgRGljdCkgewogICAgICB4cmVmRW50cnkub2JqSWQgPSByZWYudG9TdHJpbmcoKTsKICAgIH0gZWxzZSBpZiAoeHJlZkVudHJ5IGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICB4cmVmRW50cnkuZGljdC5vYmpJZCA9IHJlZi50b1N0cmluZygpOwogICAgfQogICAgcmV0dXJuIHhyZWZFbnRyeTsKICB9CiAgZmV0Y2hVbmNvbXByZXNzZWQocmVmLCB4cmVmRW50cnksIHN1cHByZXNzRW5jcnlwdGlvbiA9IGZhbHNlKSB7CiAgICBjb25zdCBnZW4gPSByZWYuZ2VuOwogICAgbGV0IG51bSA9IHJlZi5udW07CiAgICBpZiAoeHJlZkVudHJ5LmdlbiAhPT0gZ2VuKSB7CiAgICAgIGNvbnN0IG1zZyA9IGBJbmNvbnNpc3RlbnQgZ2VuZXJhdGlvbiBpbiBYUmVmOiAke3JlZn1gOwogICAgICBpZiAodGhpcy5fZ2VuZXJhdGlvbkZhbGxiYWNrICYmIHhyZWZFbnRyeS5nZW4gPCBnZW4pIHsKICAgICAgICB3YXJuKG1zZyk7CiAgICAgICAgcmV0dXJuIHRoaXMuZmV0Y2hVbmNvbXByZXNzZWQoUmVmLmdldChudW0sIHhyZWZFbnRyeS5nZW4pLCB4cmVmRW50cnksIHN1cHByZXNzRW5jcnlwdGlvbik7CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IFhSZWZFbnRyeUV4Y2VwdGlvbihtc2cpOwogICAgfQogICAgY29uc3Qgc3RyZWFtID0gdGhpcy5zdHJlYW0ubWFrZVN1YlN0cmVhbSh4cmVmRW50cnkub2Zmc2V0ICsgdGhpcy5zdHJlYW0uc3RhcnQpOwogICAgY29uc3QgcGFyc2VyID0gbmV3IFBhcnNlcih7CiAgICAgIGxleGVyOiBuZXcgTGV4ZXIoc3RyZWFtKSwKICAgICAgeHJlZjogdGhpcywKICAgICAgYWxsb3dTdHJlYW1zOiB0cnVlCiAgICB9KTsKICAgIGNvbnN0IG9iajEgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICBjb25zdCBvYmoyID0gcGFyc2VyLmdldE9iaigpOwogICAgY29uc3Qgb2JqMyA9IHBhcnNlci5nZXRPYmooKTsKICAgIGlmIChvYmoxICE9PSBudW0gfHwgb2JqMiAhPT0gZ2VuIHx8ICEob2JqMyBpbnN0YW5jZW9mIENtZCkpIHsKICAgICAgdGhyb3cgbmV3IFhSZWZFbnRyeUV4Y2VwdGlvbihgQmFkICh1bmNvbXByZXNzZWQpIFhSZWYgZW50cnk6ICR7cmVmfWApOwogICAgfQogICAgaWYgKG9iajMuY21kICE9PSAib2JqIikgewogICAgICBpZiAob2JqMy5jbWQuc3RhcnRzV2l0aCgib2JqIikpIHsKICAgICAgICBudW0gPSBwYXJzZUludChvYmozLmNtZC5zdWJzdHJpbmcoMyksIDEwKTsKICAgICAgICBpZiAoIU51bWJlci5pc05hTihudW0pKSB7CiAgICAgICAgICByZXR1cm4gbnVtOwogICAgICAgIH0KICAgICAgfQogICAgICB0aHJvdyBuZXcgWFJlZkVudHJ5RXhjZXB0aW9uKGBCYWQgKHVuY29tcHJlc3NlZCkgWFJlZiBlbnRyeTogJHtyZWZ9YCk7CiAgICB9CiAgICB4cmVmRW50cnkgPSB0aGlzLmVuY3J5cHQgJiYgIXN1cHByZXNzRW5jcnlwdGlvbiA/IHBhcnNlci5nZXRPYmoodGhpcy5lbmNyeXB0LmNyZWF0ZUNpcGhlclRyYW5zZm9ybShudW0sIGdlbikpIDogcGFyc2VyLmdldE9iaigpOwogICAgaWYgKCEoeHJlZkVudHJ5IGluc3RhbmNlb2YgQmFzZVN0cmVhbSkpIHsKICAgICAgdGhpcy5fY2FjaGVNYXAuc2V0KG51bSwgeHJlZkVudHJ5KTsKICAgIH0KICAgIHJldHVybiB4cmVmRW50cnk7CiAgfQogIGZldGNoQ29tcHJlc3NlZChyZWYsIHhyZWZFbnRyeSwgc3VwcHJlc3NFbmNyeXB0aW9uID0gZmFsc2UpIHsKICAgIGNvbnN0IHRhYmxlT2Zmc2V0ID0geHJlZkVudHJ5Lm9mZnNldDsKICAgIGNvbnN0IHN0cmVhbSA9IHRoaXMuZmV0Y2goUmVmLmdldCh0YWJsZU9mZnNldCwgMCkpOwogICAgaWYgKCEoc3RyZWFtIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJiYWQgT2JqU3RtIHN0cmVhbSIpOwogICAgfQogICAgY29uc3QgZmlyc3QgPSBzdHJlYW0uZGljdC5nZXQoIkZpcnN0Iik7CiAgICBjb25zdCBuID0gc3RyZWFtLmRpY3QuZ2V0KCJOIik7CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoZmlyc3QpIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG4pKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiaW52YWxpZCBmaXJzdCBhbmQgbiBwYXJhbWV0ZXJzIGZvciBPYmpTdG0gc3RyZWFtIik7CiAgICB9CiAgICBsZXQgcGFyc2VyID0gbmV3IFBhcnNlcih7CiAgICAgIGxleGVyOiBuZXcgTGV4ZXIoc3RyZWFtKSwKICAgICAgeHJlZjogdGhpcywKICAgICAgYWxsb3dTdHJlYW1zOiB0cnVlCiAgICB9KTsKICAgIGNvbnN0IG51bXMgPSBuZXcgQXJyYXkobik7CiAgICBjb25zdCBvZmZzZXRzID0gbmV3IEFycmF5KG4pOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyArK2kpIHsKICAgICAgY29uc3QgbnVtID0gcGFyc2VyLmdldE9iaigpOwogICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIobnVtKSkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgaW52YWxpZCBvYmplY3QgbnVtYmVyIGluIHRoZSBPYmpTdG0gc3RyZWFtOiAke251bX1gKTsKICAgICAgfQogICAgICBjb25zdCBvZmZzZXQgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihvZmZzZXQpKSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBpbnZhbGlkIG9iamVjdCBvZmZzZXQgaW4gdGhlIE9ialN0bSBzdHJlYW06ICR7b2Zmc2V0fWApOwogICAgICB9CiAgICAgIG51bXNbaV0gPSBudW07CiAgICAgIGNvbnN0IGVudHJ5ID0gdGhpcy5nZXRFbnRyeShudW0pOwogICAgICBpZiAoZW50cnk/Lm9mZnNldCA9PT0gdGFibGVPZmZzZXQgJiYgZW50cnkuZ2VuICE9PSBpKSB7CiAgICAgICAgZW50cnkuZ2VuID0gaTsKICAgICAgfQogICAgICBvZmZzZXRzW2ldID0gb2Zmc2V0OwogICAgfQogICAgY29uc3Qgc3RhcnQgPSAoc3RyZWFtLnN0YXJ0IHx8IDApICsgZmlyc3Q7CiAgICBjb25zdCBlbnRyaWVzID0gbmV3IEFycmF5KG4pOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyArK2kpIHsKICAgICAgY29uc3QgbGVuZ3RoID0gaSA8IG4gLSAxID8gb2Zmc2V0c1tpICsgMV0gLSBvZmZzZXRzW2ldIDogdW5kZWZpbmVkOwogICAgICBpZiAobGVuZ3RoIDwgMCkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBvZmZzZXQgaW4gdGhlIE9ialN0bSBzdHJlYW0uIik7CiAgICAgIH0KICAgICAgcGFyc2VyID0gbmV3IFBhcnNlcih7CiAgICAgICAgbGV4ZXI6IG5ldyBMZXhlcihzdHJlYW0ubWFrZVN1YlN0cmVhbShzdGFydCArIG9mZnNldHNbaV0sIGxlbmd0aCwgc3RyZWFtLmRpY3QpKSwKICAgICAgICB4cmVmOiB0aGlzLAogICAgICAgIGFsbG93U3RyZWFtczogdHJ1ZQogICAgICB9KTsKICAgICAgY29uc3Qgb2JqID0gcGFyc2VyLmdldE9iaigpOwogICAgICBlbnRyaWVzW2ldID0gb2JqOwogICAgICBpZiAob2JqIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IG51bSA9IG51bXNbaV0sCiAgICAgICAgZW50cnkgPSB0aGlzLmVudHJpZXNbbnVtXTsKICAgICAgaWYgKGVudHJ5ICYmIGVudHJ5Lm9mZnNldCA9PT0gdGFibGVPZmZzZXQgJiYgZW50cnkuZ2VuID09PSBpKSB7CiAgICAgICAgdGhpcy5fY2FjaGVNYXAuc2V0KG51bSwgb2JqKTsKICAgICAgfQogICAgfQogICAgeHJlZkVudHJ5ID0gZW50cmllc1t4cmVmRW50cnkuZ2VuXTsKICAgIGlmICh4cmVmRW50cnkgPT09IHVuZGVmaW5lZCkgewogICAgICB0aHJvdyBuZXcgWFJlZkVudHJ5RXhjZXB0aW9uKGBCYWQgKGNvbXByZXNzZWQpIFhSZWYgZW50cnk6ICR7cmVmfWApOwogICAgfQogICAgcmV0dXJuIHhyZWZFbnRyeTsKICB9CiAgYXN5bmMgZmV0Y2hJZlJlZkFzeW5jKG9iaiwgc3VwcHJlc3NFbmNyeXB0aW9uKSB7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgIHJldHVybiB0aGlzLmZldGNoQXN5bmMob2JqLCBzdXBwcmVzc0VuY3J5cHRpb24pOwogICAgfQogICAgcmV0dXJuIG9iajsKICB9CiAgYXN5bmMgZmV0Y2hBc3luYyhyZWYsIHN1cHByZXNzRW5jcnlwdGlvbikgewogICAgdHJ5IHsKICAgICAgcmV0dXJuIHRoaXMuZmV0Y2gocmVmLCBzdXBwcmVzc0VuY3J5cHRpb24pOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKCEoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikpIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICBhd2FpdCB0aGlzLnBkZk1hbmFnZXIucmVxdWVzdFJhbmdlKGV4LmJlZ2luLCBleC5lbmQpOwogICAgICByZXR1cm4gdGhpcy5mZXRjaEFzeW5jKHJlZiwgc3VwcHJlc3NFbmNyeXB0aW9uKTsKICAgIH0KICB9CiAgZ2V0Q2F0YWxvZ09iaigpIHsKICAgIHJldHVybiB0aGlzLnJvb3Q7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9kb2N1bWVudC5qcwoKCgoKCgoKCgoKCgoKCgoKCgoKCmNvbnN0IExFVFRFUl9TSVpFX01FRElBQk9YID0gWzAsIDAsIDYxMiwgNzkyXTsKY2xhc3MgUGFnZSB7CiAgI2FyZUFubm90YXRpb25zQ2FjaGVkID0gZmFsc2U7CiAgI3Jlc291cmNlc1Byb21pc2UgPSBudWxsOwogIGNvbnN0cnVjdG9yKHsKICAgIHBkZk1hbmFnZXIsCiAgICB4cmVmLAogICAgcGFnZUluZGV4LAogICAgcGFnZURpY3QsCiAgICByZWYsCiAgICBnbG9iYWxJZEZhY3RvcnksCiAgICBmb250Q2FjaGUsCiAgICBidWlsdEluQ01hcENhY2hlLAogICAgc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgZ2xvYmFsSW1hZ2VDYWNoZSwKICAgIHN5c3RlbUZvbnRDYWNoZSwKICAgIG5vbkJsZW5kTW9kZXNTZXQsCiAgICB4ZmFGYWN0b3J5CiAgfSkgewogICAgdGhpcy5wZGZNYW5hZ2VyID0gcGRmTWFuYWdlcjsKICAgIHRoaXMucGFnZUluZGV4ID0gcGFnZUluZGV4OwogICAgdGhpcy5wYWdlRGljdCA9IHBhZ2VEaWN0OwogICAgdGhpcy54cmVmID0geHJlZjsKICAgIHRoaXMucmVmID0gcmVmOwogICAgdGhpcy5mb250Q2FjaGUgPSBmb250Q2FjaGU7CiAgICB0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUgPSBidWlsdEluQ01hcENhY2hlOwogICAgdGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUgPSBzdGFuZGFyZEZvbnREYXRhQ2FjaGU7CiAgICB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSA9IGdsb2JhbENvbG9yU3BhY2VDYWNoZTsKICAgIHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZSA9IGdsb2JhbEltYWdlQ2FjaGU7CiAgICB0aGlzLnN5c3RlbUZvbnRDYWNoZSA9IHN5c3RlbUZvbnRDYWNoZTsKICAgIHRoaXMubm9uQmxlbmRNb2Rlc1NldCA9IG5vbkJsZW5kTW9kZXNTZXQ7CiAgICB0aGlzLmV2YWx1YXRvck9wdGlvbnMgPSBwZGZNYW5hZ2VyLmV2YWx1YXRvck9wdGlvbnM7CiAgICB0aGlzLnhmYUZhY3RvcnkgPSB4ZmFGYWN0b3J5OwogICAgY29uc3QgaWRDb3VudGVycyA9IHsKICAgICAgb2JqOiAwCiAgICB9OwogICAgdGhpcy5fbG9jYWxJZEZhY3RvcnkgPSBjbGFzcyBleHRlbmRzIGdsb2JhbElkRmFjdG9yeSB7CiAgICAgIHN0YXRpYyBjcmVhdGVPYmpJZCgpIHsKICAgICAgICByZXR1cm4gYHAke3BhZ2VJbmRleH1fJHsrK2lkQ291bnRlcnMub2JqfWA7CiAgICAgIH0KICAgICAgc3RhdGljIGdldFBhZ2VPYmpJZCgpIHsKICAgICAgICByZXR1cm4gYHAke3JlZi50b1N0cmluZygpfWA7CiAgICAgIH0KICAgIH07CiAgfQogICNjcmVhdGVQYXJ0aWFsRXZhbHVhdG9yKGhhbmRsZXIpIHsKICAgIHJldHVybiBuZXcgUGFydGlhbEV2YWx1YXRvcih7CiAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgaGFuZGxlciwKICAgICAgcGFnZUluZGV4OiB0aGlzLnBhZ2VJbmRleCwKICAgICAgaWRGYWN0b3J5OiB0aGlzLl9sb2NhbElkRmFjdG9yeSwKICAgICAgZm9udENhY2hlOiB0aGlzLmZvbnRDYWNoZSwKICAgICAgYnVpbHRJbkNNYXBDYWNoZTogdGhpcy5idWlsdEluQ01hcENhY2hlLAogICAgICBzdGFuZGFyZEZvbnREYXRhQ2FjaGU6IHRoaXMuc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGU6IHRoaXMuZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICBnbG9iYWxJbWFnZUNhY2hlOiB0aGlzLmdsb2JhbEltYWdlQ2FjaGUsCiAgICAgIHN5c3RlbUZvbnRDYWNoZTogdGhpcy5zeXN0ZW1Gb250Q2FjaGUsCiAgICAgIG9wdGlvbnM6IHRoaXMuZXZhbHVhdG9yT3B0aW9ucwogICAgfSk7CiAgfQogICNnZXRJbmhlcml0YWJsZVByb3BlcnR5KGtleSwgZ2V0QXJyYXkgPSBmYWxzZSkgewogICAgY29uc3QgdmFsdWUgPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5KHsKICAgICAgZGljdDogdGhpcy5wYWdlRGljdCwKICAgICAga2V5LAogICAgICBnZXRBcnJheSwKICAgICAgc3RvcFdoZW5Gb3VuZDogZmFsc2UKICAgIH0pOwogICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSkgewogICAgICByZXR1cm4gdmFsdWU7CiAgICB9CiAgICBpZiAodmFsdWUubGVuZ3RoID09PSAxIHx8ICEodmFsdWVbMF0gaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm4gdmFsdWVbMF07CiAgICB9CiAgICByZXR1cm4gRGljdC5tZXJnZSh7CiAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgZGljdEFycmF5OiB2YWx1ZQogICAgfSk7CiAgfQogIGdldCBjb250ZW50KCkgewogICAgcmV0dXJuIHRoaXMucGFnZURpY3QuZ2V0QXJyYXkoIkNvbnRlbnRzIik7CiAgfQogIGdldCByZXNvdXJjZXMoKSB7CiAgICBjb25zdCByZXNvdXJjZXMgPSB0aGlzLiNnZXRJbmhlcml0YWJsZVByb3BlcnR5KCJSZXNvdXJjZXMiKTsKICAgIHJldHVybiBzaGFkb3codGhpcywgInJlc291cmNlcyIsIHJlc291cmNlcyBpbnN0YW5jZW9mIERpY3QgPyByZXNvdXJjZXMgOiBEaWN0LmVtcHR5KTsKICB9CiAgZ2V0Qm91bmRpbmdCb3gobmFtZSkgewogICAgaWYgKHRoaXMueGZhRGF0YSkgewogICAgICByZXR1cm4gdGhpcy54ZmFEYXRhLmJib3g7CiAgICB9CiAgICBjb25zdCBib3ggPSBsb29rdXBOb3JtYWxSZWN0KHRoaXMuI2dldEluaGVyaXRhYmxlUHJvcGVydHkobmFtZSwgdHJ1ZSksIG51bGwpOwogICAgaWYgKGJveCkgewogICAgICBpZiAoYm94WzJdIC0gYm94WzBdID4gMCAmJiBib3hbM10gLSBib3hbMV0gPiAwKSB7CiAgICAgICAgcmV0dXJuIGJveDsKICAgICAgfQogICAgICB3YXJuKGBFbXB0eSwgb3IgaW52YWxpZCwgLyR7bmFtZX0gZW50cnkuYCk7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgZ2V0IG1lZGlhQm94KCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAibWVkaWFCb3giLCB0aGlzLmdldEJvdW5kaW5nQm94KCJNZWRpYUJveCIpIHx8IExFVFRFUl9TSVpFX01FRElBQk9YKTsKICB9CiAgZ2V0IGNyb3BCb3goKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJjcm9wQm94IiwgdGhpcy5nZXRCb3VuZGluZ0JveCgiQ3JvcEJveCIpIHx8IHRoaXMubWVkaWFCb3gpOwogIH0KICBnZXQgdXNlclVuaXQoKSB7CiAgICBjb25zdCBvYmogPSB0aGlzLnBhZ2VEaWN0LmdldCgiVXNlclVuaXQiKTsKICAgIHJldHVybiBzaGFkb3codGhpcywgInVzZXJVbml0IiwgdHlwZW9mIG9iaiA9PT0gIm51bWJlciIgJiYgb2JqID4gMCA/IG9iaiA6IDEuMCk7CiAgfQogIGdldCB2aWV3KCkgewogICAgY29uc3QgewogICAgICBjcm9wQm94LAogICAgICBtZWRpYUJveAogICAgfSA9IHRoaXM7CiAgICBpZiAoY3JvcEJveCAhPT0gbWVkaWFCb3ggJiYgIWlzQXJyYXlFcXVhbChjcm9wQm94LCBtZWRpYUJveCkpIHsKICAgICAgY29uc3QgYm94ID0gVXRpbC5pbnRlcnNlY3QoY3JvcEJveCwgbWVkaWFCb3gpOwogICAgICBpZiAoYm94ICYmIGJveFsyXSAtIGJveFswXSA+IDAgJiYgYm94WzNdIC0gYm94WzFdID4gMCkgewogICAgICAgIHJldHVybiBzaGFkb3codGhpcywgInZpZXciLCBib3gpOwogICAgICB9CiAgICAgIHdhcm4oIkVtcHR5IC9Dcm9wQm94IGFuZCAvTWVkaWFCb3ggaW50ZXJzZWN0aW9uLiIpOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAidmlldyIsIG1lZGlhQm94KTsKICB9CiAgZ2V0IHJvdGF0ZSgpIHsKICAgIGxldCByb3RhdGUgPSB0aGlzLiNnZXRJbmhlcml0YWJsZVByb3BlcnR5KCJSb3RhdGUiKSB8fCAwOwogICAgaWYgKHJvdGF0ZSAlIDkwICE9PSAwKSB7CiAgICAgIHJvdGF0ZSA9IDA7CiAgICB9IGVsc2UgaWYgKHJvdGF0ZSA+PSAzNjApIHsKICAgICAgcm90YXRlICU9IDM2MDsKICAgIH0gZWxzZSBpZiAocm90YXRlIDwgMCkgewogICAgICByb3RhdGUgPSAocm90YXRlICUgMzYwICsgMzYwKSAlIDM2MDsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInJvdGF0ZSIsIHJvdGF0ZSk7CiAgfQogICNvblN1YlN0cmVhbUVycm9yKHJlYXNvbiwgb2JqSWQpIHsKICAgIGlmICh0aGlzLmV2YWx1YXRvck9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgIHdhcm4oYGdldENvbnRlbnRTdHJlYW0gLSBpZ25vcmluZyBzdWItc3RyZWFtICgke29iaklkfSk6ICIke3JlYXNvbn0iLmApOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aHJvdyByZWFzb247CiAgfQogIGFzeW5jIGdldENvbnRlbnRTdHJlYW0oKSB7CiAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZSh0aGlzLCAiY29udGVudCIpOwogICAgaWYgKGNvbnRlbnQgaW5zdGFuY2VvZiBCYXNlU3RyZWFtICYmICFjb250ZW50LmlzSW1hZ2VTdHJlYW0pIHsKICAgICAgaWYgKGNvbnRlbnQuaXNBc3luYykgewogICAgICAgIGNvbnN0IGJ5dGVzID0gYXdhaXQgY29udGVudC5hc3luY0dldEJ5dGVzKCk7CiAgICAgICAgaWYgKGJ5dGVzKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFN0cmVhbShieXRlcywgMCwgYnl0ZXMubGVuZ3RoLCBjb250ZW50LmRpY3QpOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gY29udGVudDsKICAgIH0KICAgIGlmIChBcnJheS5pc0FycmF5KGNvbnRlbnQpKSB7CiAgICAgIGNvbnN0IHByb21pc2VzID0gW107CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGNvbnRlbnQubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IGl0ZW0gPSBjb250ZW50W2ldOwogICAgICAgIGlmIChpdGVtIGluc3RhbmNlb2YgQmFzZVN0cmVhbSAmJiBpdGVtLmlzQXN5bmMpIHsKICAgICAgICAgIHByb21pc2VzLnB1c2goaXRlbS5hc3luY0dldEJ5dGVzKCkudGhlbihieXRlcyA9PiB7CiAgICAgICAgICAgIGlmIChieXRlcykgewogICAgICAgICAgICAgIGNvbnRlbnRbaV0gPSBuZXcgU3RyZWFtKGJ5dGVzLCAwLCBieXRlcy5sZW5ndGgsIGl0ZW0uZGljdCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHByb21pc2VzLmxlbmd0aCA+IDApIHsKICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7CiAgICAgIH0KICAgICAgcmV0dXJuIG5ldyBTdHJlYW1zU2VxdWVuY2VTdHJlYW0oY29udGVudCwgdGhpcy4jb25TdWJTdHJlYW1FcnJvci5iaW5kKHRoaXMpKTsKICAgIH0KICAgIHJldHVybiBuZXcgTnVsbFN0cmVhbSgpOwogIH0KICBnZXQgeGZhRGF0YSgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgInhmYURhdGEiLCB0aGlzLnhmYUZhY3RvcnkgPyB7CiAgICAgIGJib3g6IHRoaXMueGZhRmFjdG9yeS5nZXRCb3VuZGluZ0JveCh0aGlzLnBhZ2VJbmRleCkKICAgIH0gOiBudWxsKTsKICB9CiAgYXN5bmMgI3JlcGxhY2VJZEJ5UmVmKGFubm90YXRpb25zLCBkZWxldGVkQW5ub3RhdGlvbnMsIGV4aXN0aW5nQW5ub3RhdGlvbnMpIHsKICAgIGNvbnN0IHByb21pc2VzID0gW107CiAgICBmb3IgKGNvbnN0IGFubm90YXRpb24gb2YgYW5ub3RhdGlvbnMpIHsKICAgICAgaWYgKGFubm90YXRpb24uaWQpIHsKICAgICAgICBjb25zdCByZWYgPSBSZWYuZnJvbVN0cmluZyhhbm5vdGF0aW9uLmlkKTsKICAgICAgICBpZiAoIXJlZikgewogICAgICAgICAgd2FybihgQSBub24tbGlua2VkIGFubm90YXRpb24gY2Fubm90IGJlIG1vZGlmaWVkOiAke2Fubm90YXRpb24uaWR9YCk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKGFubm90YXRpb24uZGVsZXRlZCkgewogICAgICAgICAgZGVsZXRlZEFubm90YXRpb25zLnB1dChyZWYsIHJlZik7CiAgICAgICAgICBpZiAoYW5ub3RhdGlvbi5wb3B1cFJlZikgewogICAgICAgICAgICBjb25zdCBwb3B1cFJlZiA9IFJlZi5mcm9tU3RyaW5nKGFubm90YXRpb24ucG9wdXBSZWYpOwogICAgICAgICAgICBpZiAocG9wdXBSZWYpIHsKICAgICAgICAgICAgICBkZWxldGVkQW5ub3RhdGlvbnMucHV0KHBvcHVwUmVmLCBwb3B1cFJlZik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZiAoYW5ub3RhdGlvbi5wb3B1cD8uZGVsZXRlZCkgewogICAgICAgICAgY29uc3QgcG9wdXBSZWYgPSBSZWYuZnJvbVN0cmluZyhhbm5vdGF0aW9uLnBvcHVwUmVmKTsKICAgICAgICAgIGlmIChwb3B1cFJlZikgewogICAgICAgICAgICBkZWxldGVkQW5ub3RhdGlvbnMucHV0KHBvcHVwUmVmLCBwb3B1cFJlZik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGV4aXN0aW5nQW5ub3RhdGlvbnM/LnB1dChyZWYpOwogICAgICAgIGFubm90YXRpb24ucmVmID0gcmVmOwogICAgICAgIHByb21pc2VzLnB1c2godGhpcy54cmVmLmZldGNoQXN5bmMocmVmKS50aGVuKG9iaiA9PiB7CiAgICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgICAgICBhbm5vdGF0aW9uLm9sZEFubm90YXRpb24gPSBvYmouY2xvbmUoKTsKICAgICAgICAgIH0KICAgICAgICB9LCAoKSA9PiB7CiAgICAgICAgICB3YXJuKGBDYW5ub3QgZmV0Y2ggXGBvbGRBbm5vdGF0aW9uXGAgZm9yOiAke3JlZn0uYCk7CiAgICAgICAgfSkpOwogICAgICAgIGRlbGV0ZSBhbm5vdGF0aW9uLmlkOwogICAgICB9CiAgICB9CiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7CiAgfQogIGFzeW5jIHNhdmVOZXdBbm5vdGF0aW9ucyhoYW5kbGVyLCB0YXNrLCBhbm5vdGF0aW9ucywgaW1hZ2VQcm9taXNlcywgY2hhbmdlcykgewogICAgaWYgKHRoaXMueGZhRmFjdG9yeSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIlhGQTogQ2Fubm90IHNhdmUgbmV3IGFubm90YXRpb25zLiIpOwogICAgfQogICAgY29uc3QgcGFydGlhbEV2YWx1YXRvciA9IHRoaXMuI2NyZWF0ZVBhcnRpYWxFdmFsdWF0b3IoaGFuZGxlcik7CiAgICBjb25zdCBkZWxldGVkQW5ub3RhdGlvbnMgPSBuZXcgUmVmU2V0Q2FjaGUoKTsKICAgIGNvbnN0IGV4aXN0aW5nQW5ub3RhdGlvbnMgPSBuZXcgUmVmU2V0KCk7CiAgICBhd2FpdCB0aGlzLiNyZXBsYWNlSWRCeVJlZihhbm5vdGF0aW9ucywgZGVsZXRlZEFubm90YXRpb25zLCBleGlzdGluZ0Fubm90YXRpb25zKTsKICAgIGNvbnN0IHBhZ2VEaWN0ID0gdGhpcy5wYWdlRGljdDsKICAgIGNvbnN0IGFubm90YXRpb25zQXJyYXkgPSB0aGlzLmFubm90YXRpb25zLmZpbHRlcihhID0+ICEoYSBpbnN0YW5jZW9mIFJlZiAmJiBkZWxldGVkQW5ub3RhdGlvbnMuaGFzKGEpKSk7CiAgICBjb25zdCBuZXdEYXRhID0gYXdhaXQgQW5ub3RhdGlvbkZhY3Rvcnkuc2F2ZU5ld0Fubm90YXRpb25zKHBhcnRpYWxFdmFsdWF0b3IsIHRhc2ssIGFubm90YXRpb25zLCBpbWFnZVByb21pc2VzLCBjaGFuZ2VzKTsKICAgIGZvciAoY29uc3QgewogICAgICByZWYKICAgIH0gb2YgbmV3RGF0YS5hbm5vdGF0aW9ucykgewogICAgICBpZiAocmVmIGluc3RhbmNlb2YgUmVmICYmICFleGlzdGluZ0Fubm90YXRpb25zLmhhcyhyZWYpKSB7CiAgICAgICAgYW5ub3RhdGlvbnNBcnJheS5wdXNoKHJlZik7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGRpY3QgPSBwYWdlRGljdC5jbG9uZSgpOwogICAgZGljdC5zZXQoIkFubm90cyIsIGFubm90YXRpb25zQXJyYXkpOwogICAgY2hhbmdlcy5wdXQodGhpcy5yZWYsIHsKICAgICAgZGF0YTogZGljdAogICAgfSk7CiAgICBmb3IgKGNvbnN0IGRlbGV0ZWRSZWYgb2YgZGVsZXRlZEFubm90YXRpb25zKSB7CiAgICAgIGNoYW5nZXMucHV0KGRlbGV0ZWRSZWYsIHsKICAgICAgICBkYXRhOiBudWxsCiAgICAgIH0pOwogICAgfQogIH0KICBhc3luYyBzYXZlKGhhbmRsZXIsIHRhc2ssIGFubm90YXRpb25TdG9yYWdlLCBjaGFuZ2VzKSB7CiAgICBjb25zdCBwYXJ0aWFsRXZhbHVhdG9yID0gdGhpcy4jY3JlYXRlUGFydGlhbEV2YWx1YXRvcihoYW5kbGVyKTsKICAgIGNvbnN0IGFubm90YXRpb25zID0gYXdhaXQgdGhpcy5fcGFyc2VkQW5ub3RhdGlvbnM7CiAgICBjb25zdCBwcm9taXNlcyA9IFtdOwogICAgZm9yIChjb25zdCBhbm5vdGF0aW9uIG9mIGFubm90YXRpb25zKSB7CiAgICAgIHByb21pc2VzLnB1c2goYW5ub3RhdGlvbi5zYXZlKHBhcnRpYWxFdmFsdWF0b3IsIHRhc2ssIGFubm90YXRpb25TdG9yYWdlLCBjaGFuZ2VzKS5jYXRjaChmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgd2Fybigic2F2ZSAtIGlnbm9yaW5nIGFubm90YXRpb24gZGF0YSBkdXJpbmcgIiArIGAiJHt0YXNrLm5hbWV9IiB0YXNrOiAiJHtyZWFzb259Ii5gKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfSkpOwogICAgfQogICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTsKICB9CiAgYXN5bmMgbG9hZFJlc291cmNlcyhrZXlzKSB7CiAgICBhd2FpdCAodGhpcy4jcmVzb3VyY2VzUHJvbWlzZSA/Pz0gdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZSh0aGlzLCAicmVzb3VyY2VzIikpOwogICAgYXdhaXQgT2JqZWN0TG9hZGVyLmxvYWQodGhpcy5yZXNvdXJjZXMsIGtleXMsIHRoaXMueHJlZik7CiAgfQogIGFzeW5jICNnZXRNZXJnZWRSZXNvdXJjZXMoc3RyZWFtRGljdCwga2V5cykgewogICAgY29uc3QgbG9jYWxSZXNvdXJjZXMgPSBzdHJlYW1EaWN0Py5nZXQoIlJlc291cmNlcyIpOwogICAgaWYgKCEobG9jYWxSZXNvdXJjZXMgaW5zdGFuY2VvZiBEaWN0ICYmIGxvY2FsUmVzb3VyY2VzLnNpemUpKSB7CiAgICAgIHJldHVybiB0aGlzLnJlc291cmNlczsKICAgIH0KICAgIGF3YWl0IE9iamVjdExvYWRlci5sb2FkKGxvY2FsUmVzb3VyY2VzLCBrZXlzLCB0aGlzLnhyZWYpOwogICAgcmV0dXJuIERpY3QubWVyZ2UoewogICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgIGRpY3RBcnJheTogW2xvY2FsUmVzb3VyY2VzLCB0aGlzLnJlc291cmNlc10sCiAgICAgIG1lcmdlU3ViRGljdHM6IHRydWUKICAgIH0pOwogIH0KICBhc3luYyBnZXRPcGVyYXRvckxpc3QoewogICAgaGFuZGxlciwKICAgIHNpbmssCiAgICB0YXNrLAogICAgaW50ZW50LAogICAgY2FjaGVLZXksCiAgICBwYWdlSWQgPSB0aGlzLnBhZ2VJbmRleCwKICAgIHBhZ2VJbmRleCA9IHRoaXMucGFnZUluZGV4LAogICAgYW5ub3RhdGlvblN0b3JhZ2UgPSBudWxsLAogICAgbW9kaWZpZWRJZHMgPSBudWxsCiAgfSkgewogICAgY29uc3QgY29udGVudFN0cmVhbVByb21pc2UgPSB0aGlzLmdldENvbnRlbnRTdHJlYW0oKTsKICAgIGNvbnN0IHJlc291cmNlc1Byb21pc2UgPSB0aGlzLmxvYWRSZXNvdXJjZXMoUkVTT1VSQ0VTX0tFWVNfT1BFUkFUT1JfTElTVCk7CiAgICBjb25zdCBwYXJ0aWFsRXZhbHVhdG9yID0gdGhpcy4jY3JlYXRlUGFydGlhbEV2YWx1YXRvcihoYW5kbGVyKTsKICAgIGNvbnN0IG5ld0Fubm90c0J5UGFnZSA9ICF0aGlzLnhmYUZhY3RvcnkgPyBnZXROZXdBbm5vdGF0aW9uc01hcChhbm5vdGF0aW9uU3RvcmFnZSkgOiBudWxsOwogICAgY29uc3QgbmV3QW5ub3RzID0gbmV3QW5ub3RzQnlQYWdlPy5nZXQodGhpcy5wYWdlSW5kZXgpOwogICAgbGV0IG5ld0Fubm90YXRpb25zUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShudWxsKTsKICAgIGxldCBkZWxldGVkQW5ub3RhdGlvbnMgPSBudWxsOwogICAgaWYgKG5ld0Fubm90cykgewogICAgICBjb25zdCBhbm5vdGF0aW9uR2xvYmFsc1Byb21pc2UgPSB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlRG9jKCJhbm5vdGF0aW9uR2xvYmFscyIpOwogICAgICBsZXQgaW1hZ2VQcm9taXNlczsKICAgICAgY29uc3QgbWlzc2luZ0JpdG1hcHMgPSBuZXcgU2V0KCk7CiAgICAgIGZvciAoY29uc3QgewogICAgICAgIGJpdG1hcElkLAogICAgICAgIGJpdG1hcAogICAgICB9IG9mIG5ld0Fubm90cykgewogICAgICAgIGlmIChiaXRtYXBJZCAmJiAhYml0bWFwICYmICFtaXNzaW5nQml0bWFwcy5oYXMoYml0bWFwSWQpKSB7CiAgICAgICAgICBtaXNzaW5nQml0bWFwcy5hZGQoYml0bWFwSWQpOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCB7CiAgICAgICAgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQKICAgICAgfSA9IHRoaXMuZXZhbHVhdG9yT3B0aW9uczsKICAgICAgaWYgKG1pc3NpbmdCaXRtYXBzLnNpemUgPiAwKSB7CiAgICAgICAgY29uc3QgYW5ub3RhdGlvbldpdGhCaXRtYXBzID0gbmV3QW5ub3RzLnNsaWNlKCk7CiAgICAgICAgZm9yIChjb25zdCBba2V5LCBhbm5vdGF0aW9uXSBvZiBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgICAgICAgaWYgKCFrZXkuc3RhcnRzV2l0aChBbm5vdGF0aW9uRWRpdG9yUHJlZml4KSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChhbm5vdGF0aW9uLmJpdG1hcCAmJiBtaXNzaW5nQml0bWFwcy5oYXMoYW5ub3RhdGlvbi5iaXRtYXBJZCkpIHsKICAgICAgICAgICAgYW5ub3RhdGlvbldpdGhCaXRtYXBzLnB1c2goYW5ub3RhdGlvbik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGltYWdlUHJvbWlzZXMgPSBBbm5vdGF0aW9uRmFjdG9yeS5nZW5lcmF0ZUltYWdlcyhhbm5vdGF0aW9uV2l0aEJpdG1hcHMsIHRoaXMueHJlZiwgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpOwogICAgICB9IGVsc2UgewogICAgICAgIGltYWdlUHJvbWlzZXMgPSBBbm5vdGF0aW9uRmFjdG9yeS5nZW5lcmF0ZUltYWdlcyhuZXdBbm5vdHMsIHRoaXMueHJlZiwgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpOwogICAgICB9CiAgICAgIGRlbGV0ZWRBbm5vdGF0aW9ucyA9IG5ldyBSZWZTZXQoKTsKICAgICAgbmV3QW5ub3RhdGlvbnNQcm9taXNlID0gUHJvbWlzZS5hbGwoW2Fubm90YXRpb25HbG9iYWxzUHJvbWlzZSwgdGhpcy4jcmVwbGFjZUlkQnlSZWYobmV3QW5ub3RzLCBkZWxldGVkQW5ub3RhdGlvbnMsIG51bGwpXSkudGhlbigoW2Fubm90YXRpb25HbG9iYWxzXSkgPT4gewogICAgICAgIGlmICghYW5ub3RhdGlvbkdsb2JhbHMpIHsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gQW5ub3RhdGlvbkZhY3RvcnkucHJpbnROZXdBbm5vdGF0aW9ucyhhbm5vdGF0aW9uR2xvYmFscywgcGFydGlhbEV2YWx1YXRvciwgdGFzaywgbmV3QW5ub3RzLCBpbWFnZVByb21pc2VzKTsKICAgICAgfSk7CiAgICB9CiAgICBjb25zdCBwYWdlTGlzdFByb21pc2UgPSBQcm9taXNlLmFsbChbY29udGVudFN0cmVhbVByb21pc2UsIHJlc291cmNlc1Byb21pc2VdKS50aGVuKGFzeW5jIChbY29udGVudFN0cmVhbV0pID0+IHsKICAgICAgY29uc3QgcmVzb3VyY2VzID0gYXdhaXQgdGhpcy4jZ2V0TWVyZ2VkUmVzb3VyY2VzKGNvbnRlbnRTdHJlYW0uZGljdCwgUkVTT1VSQ0VTX0tFWVNfT1BFUkFUT1JfTElTVCk7CiAgICAgIGNvbnN0IG9wTGlzdCA9IG5ldyBPcGVyYXRvckxpc3QoaW50ZW50LCBzaW5rKTsKICAgICAgaGFuZGxlci5zZW5kKCJTdGFydFJlbmRlclBhZ2UiLCB7CiAgICAgICAgdHJhbnNwYXJlbmN5OiBwYXJ0aWFsRXZhbHVhdG9yLmhhc0JsZW5kTW9kZXMocmVzb3VyY2VzLCB0aGlzLm5vbkJsZW5kTW9kZXNTZXQpLAogICAgICAgIHBhZ2VJbmRleCwKICAgICAgICBjYWNoZUtleQogICAgICB9KTsKICAgICAgYXdhaXQgcGFydGlhbEV2YWx1YXRvci5nZXRPcGVyYXRvckxpc3QoewogICAgICAgIHN0cmVhbTogY29udGVudFN0cmVhbSwKICAgICAgICB0YXNrLAogICAgICAgIHJlc291cmNlcywKICAgICAgICBvcGVyYXRvckxpc3Q6IG9wTGlzdAogICAgICB9KTsKICAgICAgcmV0dXJuIG9wTGlzdDsKICAgIH0pOwogICAgbGV0IFtwYWdlT3BMaXN0LCBhbm5vdGF0aW9ucywgbmV3QW5ub3RhdGlvbnNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW3BhZ2VMaXN0UHJvbWlzZSwgdGhpcy5fcGFyc2VkQW5ub3RhdGlvbnMsIG5ld0Fubm90YXRpb25zUHJvbWlzZV0pOwogICAgaWYgKG5ld0Fubm90YXRpb25zKSB7CiAgICAgIGFubm90YXRpb25zID0gYW5ub3RhdGlvbnMuZmlsdGVyKGEgPT4gIShhLnJlZiAmJiBkZWxldGVkQW5ub3RhdGlvbnMuaGFzKGEucmVmKSkpOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBuZXdBbm5vdGF0aW9ucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3QgbmV3QW5ub3RhdGlvbiA9IG5ld0Fubm90YXRpb25zW2ldOwogICAgICAgIGlmIChuZXdBbm5vdGF0aW9uLnJlZlRvUmVwbGFjZSkgewogICAgICAgICAgY29uc3QgaiA9IGFubm90YXRpb25zLmZpbmRJbmRleChhID0+IGEucmVmICYmIGlzUmVmc0VxdWFsKGEucmVmLCBuZXdBbm5vdGF0aW9uLnJlZlRvUmVwbGFjZSkpOwogICAgICAgICAgaWYgKGogPj0gMCkgewogICAgICAgICAgICBhbm5vdGF0aW9ucy5zcGxpY2UoaiwgMSwgbmV3QW5ub3RhdGlvbik7CiAgICAgICAgICAgIG5ld0Fubm90YXRpb25zLnNwbGljZShpLS0sIDEpOwogICAgICAgICAgICBpaS0tOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBhbm5vdGF0aW9ucyA9IGFubm90YXRpb25zLmNvbmNhdChuZXdBbm5vdGF0aW9ucyk7CiAgICB9CiAgICBpZiAoYW5ub3RhdGlvbnMubGVuZ3RoID09PSAwIHx8IGludGVudCAmIFJlbmRlcmluZ0ludGVudEZsYWcuQU5OT1RBVElPTlNfRElTQUJMRSkgewogICAgICBwYWdlT3BMaXN0LmZsdXNoKHRydWUpOwogICAgICByZXR1cm4gewogICAgICAgIGxlbmd0aDogcGFnZU9wTGlzdC50b3RhbExlbmd0aAogICAgICB9OwogICAgfQogICAgY29uc3QgcmVuZGVyRm9ybXMgPSAhIShpbnRlbnQgJiBSZW5kZXJpbmdJbnRlbnRGbGFnLkFOTk9UQVRJT05TX0ZPUk1TKSwKICAgICAgaXNFZGl0aW5nID0gISEoaW50ZW50ICYgUmVuZGVyaW5nSW50ZW50RmxhZy5JU19FRElUSU5HKSwKICAgICAgaW50ZW50QW55ID0gISEoaW50ZW50ICYgUmVuZGVyaW5nSW50ZW50RmxhZy5BTlkpLAogICAgICBpbnRlbnREaXNwbGF5ID0gISEoaW50ZW50ICYgUmVuZGVyaW5nSW50ZW50RmxhZy5ESVNQTEFZKSwKICAgICAgaW50ZW50UHJpbnQgPSAhIShpbnRlbnQgJiBSZW5kZXJpbmdJbnRlbnRGbGFnLlBSSU5UKTsKICAgIGNvbnN0IG9wTGlzdFByb21pc2VzID0gW107CiAgICBmb3IgKGNvbnN0IGFubm90YXRpb24gb2YgYW5ub3RhdGlvbnMpIHsKICAgICAgaWYgKGludGVudEFueSB8fCBpbnRlbnREaXNwbGF5ICYmIGFubm90YXRpb24ubXVzdEJlVmlld2VkKGFubm90YXRpb25TdG9yYWdlLCByZW5kZXJGb3JtcykgJiYgYW5ub3RhdGlvbi5tdXN0QmVWaWV3ZWRXaGVuRWRpdGluZyhpc0VkaXRpbmcsIG1vZGlmaWVkSWRzKSB8fCBpbnRlbnRQcmludCAmJiBhbm5vdGF0aW9uLm11c3RCZVByaW50ZWQoYW5ub3RhdGlvblN0b3JhZ2UpKSB7CiAgICAgICAgb3BMaXN0UHJvbWlzZXMucHVzaChhbm5vdGF0aW9uLmdldE9wZXJhdG9yTGlzdChwYXJ0aWFsRXZhbHVhdG9yLCB0YXNrLCBpbnRlbnQsIGFubm90YXRpb25TdG9yYWdlKS5jYXRjaChmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICB3YXJuKCJnZXRPcGVyYXRvckxpc3QgLSBpZ25vcmluZyBhbm5vdGF0aW9uIGRhdGEgZHVyaW5nICIgKyBgIiR7dGFzay5uYW1lfSIgdGFzazogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBvcExpc3Q6IG51bGwsCiAgICAgICAgICAgIHNlcGFyYXRlRm9ybTogZmFsc2UsCiAgICAgICAgICAgIHNlcGFyYXRlQ2FudmFzOiBmYWxzZQogICAgICAgICAgfTsKICAgICAgICB9KSk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IG9wTGlzdHMgPSBhd2FpdCBQcm9taXNlLmFsbChvcExpc3RQcm9taXNlcyk7CiAgICBsZXQgZm9ybSA9IGZhbHNlLAogICAgICBjYW52YXMgPSBmYWxzZTsKICAgIGZvciAoY29uc3QgewogICAgICBvcExpc3QsCiAgICAgIHNlcGFyYXRlRm9ybSwKICAgICAgc2VwYXJhdGVDYW52YXMKICAgIH0gb2Ygb3BMaXN0cykgewogICAgICBwYWdlT3BMaXN0LmFkZE9wTGlzdChvcExpc3QpOwogICAgICBmb3JtIHx8PSBzZXBhcmF0ZUZvcm07CiAgICAgIGNhbnZhcyB8fD0gc2VwYXJhdGVDYW52YXM7CiAgICB9CiAgICBwYWdlT3BMaXN0LmZsdXNoKHRydWUsIHsKICAgICAgZm9ybSwKICAgICAgY2FudmFzCiAgICB9KTsKICAgIHJldHVybiB7CiAgICAgIGxlbmd0aDogcGFnZU9wTGlzdC50b3RhbExlbmd0aAogICAgfTsKICB9CiAgYXN5bmMgZXh0cmFjdFRleHRDb250ZW50KHsKICAgIGhhbmRsZXIsCiAgICB0YXNrLAogICAgaW5jbHVkZU1hcmtlZENvbnRlbnQsCiAgICBkaXNhYmxlTm9ybWFsaXphdGlvbiwKICAgIHNpbmssCiAgICBpbnRlcnNlY3RvciA9IG51bGwKICB9KSB7CiAgICBjb25zdCBjb250ZW50U3RyZWFtUHJvbWlzZSA9IHRoaXMuZ2V0Q29udGVudFN0cmVhbSgpOwogICAgY29uc3QgcmVzb3VyY2VzUHJvbWlzZSA9IHRoaXMubG9hZFJlc291cmNlcyhSRVNPVVJDRVNfS0VZU19URVhUX0NPTlRFTlQpOwogICAgY29uc3QgbGFuZ1Byb21pc2UgPSB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygibGFuZyIpOwogICAgY29uc3QgW2NvbnRlbnRTdHJlYW0sLCBsYW5nXSA9IGF3YWl0IFByb21pc2UuYWxsKFtjb250ZW50U3RyZWFtUHJvbWlzZSwgcmVzb3VyY2VzUHJvbWlzZSwgbGFuZ1Byb21pc2VdKTsKICAgIGNvbnN0IHJlc291cmNlcyA9IGF3YWl0IHRoaXMuI2dldE1lcmdlZFJlc291cmNlcyhjb250ZW50U3RyZWFtLmRpY3QsIFJFU09VUkNFU19LRVlTX1RFWFRfQ09OVEVOVCk7CiAgICBjb25zdCBwYXJ0aWFsRXZhbHVhdG9yID0gdGhpcy4jY3JlYXRlUGFydGlhbEV2YWx1YXRvcihoYW5kbGVyKTsKICAgIHJldHVybiBwYXJ0aWFsRXZhbHVhdG9yLmdldFRleHRDb250ZW50KHsKICAgICAgc3RyZWFtOiBjb250ZW50U3RyZWFtLAogICAgICB0YXNrLAogICAgICByZXNvdXJjZXMsCiAgICAgIGluY2x1ZGVNYXJrZWRDb250ZW50LAogICAgICBkaXNhYmxlTm9ybWFsaXphdGlvbiwKICAgICAgc2luaywKICAgICAgdmlld0JveDogdGhpcy52aWV3LAogICAgICBsYW5nLAogICAgICBpbnRlcnNlY3RvcgogICAgfSk7CiAgfQogIGFzeW5jIGdldFN0cnVjdFRyZWUoKSB7CiAgICBjb25zdCBzdHJ1Y3RUcmVlUm9vdCA9IGF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJzdHJ1Y3RUcmVlUm9vdCIpOwogICAgaWYgKCFzdHJ1Y3RUcmVlUm9vdCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGF3YWl0IHRoaXMuX3BhcnNlZEFubm90YXRpb25zOwogICAgdHJ5IHsKICAgICAgY29uc3Qgc3RydWN0VHJlZSA9IGF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmUodGhpcywgIl9wYXJzZVN0cnVjdFRyZWUiLCBbc3RydWN0VHJlZVJvb3RdKTsKICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmUoc3RydWN0VHJlZSwgInNlcmlhbGl6YWJsZSIpOwogICAgICByZXR1cm4gZGF0YTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIHdhcm4oYGdldFN0cnVjdFRyZWU6ICIke2V4fSIuYCk7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogIH0KICBfcGFyc2VTdHJ1Y3RUcmVlKHN0cnVjdFRyZWVSb290KSB7CiAgICBjb25zdCB0cmVlID0gbmV3IFN0cnVjdFRyZWVQYWdlKHN0cnVjdFRyZWVSb290LCB0aGlzLnBhZ2VEaWN0KTsKICAgIHRyZWUucGFyc2UodGhpcy5yZWYpOwogICAgcmV0dXJuIHRyZWU7CiAgfQogIGFzeW5jIGdldEFubm90YXRpb25zRGF0YShoYW5kbGVyLCB0YXNrLCBpbnRlbnQpIHsKICAgIGNvbnN0IGFubm90YXRpb25zID0gYXdhaXQgdGhpcy5fcGFyc2VkQW5ub3RhdGlvbnM7CiAgICBpZiAoYW5ub3RhdGlvbnMubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBhbm5vdGF0aW9uczsKICAgIH0KICAgIGNvbnN0IGFubm90YXRpb25zRGF0YSA9IFtdLAogICAgICB0ZXh0Q29udGVudFByb21pc2VzID0gW107CiAgICBsZXQgcGFydGlhbEV2YWx1YXRvcjsKICAgIGNvbnN0IGludGVudEFueSA9ICEhKGludGVudCAmIFJlbmRlcmluZ0ludGVudEZsYWcuQU5ZKSwKICAgICAgaW50ZW50RGlzcGxheSA9ICEhKGludGVudCAmIFJlbmRlcmluZ0ludGVudEZsYWcuRElTUExBWSksCiAgICAgIGludGVudFByaW50ID0gISEoaW50ZW50ICYgUmVuZGVyaW5nSW50ZW50RmxhZy5QUklOVCk7CiAgICBjb25zdCBoaWdobGlnaHRlZEFubm90YXRpb25zID0gW107CiAgICBmb3IgKGNvbnN0IGFubm90YXRpb24gb2YgYW5ub3RhdGlvbnMpIHsKICAgICAgY29uc3QgaXNWaXNpYmxlID0gaW50ZW50QW55IHx8IGludGVudERpc3BsYXkgJiYgYW5ub3RhdGlvbi52aWV3YWJsZTsKICAgICAgaWYgKGlzVmlzaWJsZSB8fCBpbnRlbnRQcmludCAmJiBhbm5vdGF0aW9uLnByaW50YWJsZSkgewogICAgICAgIGFubm90YXRpb25zRGF0YS5wdXNoKGFubm90YXRpb24uZGF0YSk7CiAgICAgIH0KICAgICAgaWYgKGFubm90YXRpb24uaGFzVGV4dENvbnRlbnQgJiYgaXNWaXNpYmxlKSB7CiAgICAgICAgcGFydGlhbEV2YWx1YXRvciA/Pz0gdGhpcy4jY3JlYXRlUGFydGlhbEV2YWx1YXRvcihoYW5kbGVyKTsKICAgICAgICB0ZXh0Q29udGVudFByb21pc2VzLnB1c2goYW5ub3RhdGlvbi5leHRyYWN0VGV4dENvbnRlbnQocGFydGlhbEV2YWx1YXRvciwgdGFzaywgWy1JbmZpbml0eSwgLUluZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldKS5jYXRjaChmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICB3YXJuKGBnZXRBbm5vdGF0aW9uc0RhdGEgLSBpZ25vcmluZyB0ZXh0Q29udGVudCBkdXJpbmcgIiR7dGFzay5uYW1lfSIgdGFzazogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgfSkpOwogICAgICB9IGVsc2UgaWYgKGFubm90YXRpb24ub3ZlcmxheXNUZXh0Q29udGVudCAmJiBpc1Zpc2libGUpIHsKICAgICAgICBoaWdobGlnaHRlZEFubm90YXRpb25zLnB1c2goYW5ub3RhdGlvbik7CiAgICAgIH0KICAgIH0KICAgIGlmIChoaWdobGlnaHRlZEFubm90YXRpb25zLmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgaW50ZXJzZWN0b3IgPSBuZXcgSW50ZXJzZWN0b3IoaGlnaGxpZ2h0ZWRBbm5vdGF0aW9ucyk7CiAgICAgIHRleHRDb250ZW50UHJvbWlzZXMucHVzaCh0aGlzLmV4dHJhY3RUZXh0Q29udGVudCh7CiAgICAgICAgaGFuZGxlciwKICAgICAgICB0YXNrLAogICAgICAgIGluY2x1ZGVNYXJrZWRDb250ZW50OiBmYWxzZSwKICAgICAgICBkaXNhYmxlTm9ybWFsaXphdGlvbjogZmFsc2UsCiAgICAgICAgc2luazogbnVsbCwKICAgICAgICB2aWV3Qm94OiB0aGlzLnZpZXcsCiAgICAgICAgbGFuZzogbnVsbCwKICAgICAgICBpbnRlcnNlY3RvcgogICAgICB9KS50aGVuKCgpID0+IHsKICAgICAgICBpbnRlcnNlY3Rvci5zZXRUZXh0KCk7CiAgICAgIH0pKTsKICAgIH0KICAgIGF3YWl0IFByb21pc2UuYWxsKHRleHRDb250ZW50UHJvbWlzZXMpOwogICAgcmV0dXJuIGFubm90YXRpb25zRGF0YTsKICB9CiAgZ2V0IGFubm90YXRpb25zKCkgewogICAgY29uc3QgYW5ub3RzID0gdGhpcy4jZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSgiQW5ub3RzIik7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJhbm5vdGF0aW9ucyIsIEFycmF5LmlzQXJyYXkoYW5ub3RzKSA/IGFubm90cyA6IFtdKTsKICB9CiAgZ2V0IF9wYXJzZWRBbm5vdGF0aW9ucygpIHsKICAgIGNvbnN0IHByb21pc2UgPSB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlKHRoaXMsICJhbm5vdGF0aW9ucyIpLnRoZW4oYXN5bmMgYW5ub3RzID0+IHsKICAgICAgaWYgKGFubm90cy5sZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gYW5ub3RzOwogICAgICB9CiAgICAgIGNvbnN0IFthbm5vdGF0aW9uR2xvYmFscywgZmllbGRPYmplY3RzXSA9IGF3YWl0IFByb21pc2UuYWxsKFt0aGlzLnBkZk1hbmFnZXIuZW5zdXJlRG9jKCJhbm5vdGF0aW9uR2xvYmFscyIpLCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlRG9jKCJmaWVsZE9iamVjdHMiKV0pOwogICAgICBpZiAoIWFubm90YXRpb25HbG9iYWxzKSB7CiAgICAgICAgcmV0dXJuIFtdOwogICAgICB9CiAgICAgIGNvbnN0IG9ycGhhbkZpZWxkcyA9IGZpZWxkT2JqZWN0cz8ub3JwaGFuRmllbGRzOwogICAgICBjb25zdCBhbm5vdGF0aW9uUHJvbWlzZXMgPSBbXTsKICAgICAgZm9yIChjb25zdCBhbm5vdGF0aW9uUmVmIG9mIGFubm90cykgewogICAgICAgIGFubm90YXRpb25Qcm9taXNlcy5wdXNoKEFubm90YXRpb25GYWN0b3J5LmNyZWF0ZSh0aGlzLnhyZWYsIGFubm90YXRpb25SZWYsIGFubm90YXRpb25HbG9iYWxzLCB0aGlzLl9sb2NhbElkRmFjdG9yeSwgZmFsc2UsIG9ycGhhbkZpZWxkcywgbnVsbCwgdGhpcy5yZWYpLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgIHdhcm4oYF9wYXJzZWRBbm5vdGF0aW9uczogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9KSk7CiAgICAgIH0KICAgICAgY29uc3Qgc29ydGVkQW5ub3RhdGlvbnMgPSBbXTsKICAgICAgbGV0IHBvcHVwQW5ub3RhdGlvbnMsIHdpZGdldEFubm90YXRpb25zOwogICAgICBmb3IgKGNvbnN0IGFubm90YXRpb24gb2YgYXdhaXQgUHJvbWlzZS5hbGwoYW5ub3RhdGlvblByb21pc2VzKSkgewogICAgICAgIGlmICghYW5ub3RhdGlvbikgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmIChhbm5vdGF0aW9uIGluc3RhbmNlb2YgV2lkZ2V0QW5ub3RhdGlvbikgewogICAgICAgICAgKHdpZGdldEFubm90YXRpb25zIHx8PSBbXSkucHVzaChhbm5vdGF0aW9uKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZiAoYW5ub3RhdGlvbiBpbnN0YW5jZW9mIFBvcHVwQW5ub3RhdGlvbikgewogICAgICAgICAgKHBvcHVwQW5ub3RhdGlvbnMgfHw9IFtdKS5wdXNoKGFubm90YXRpb24pOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIHNvcnRlZEFubm90YXRpb25zLnB1c2goYW5ub3RhdGlvbik7CiAgICAgIH0KICAgICAgaWYgKHdpZGdldEFubm90YXRpb25zKSB7CiAgICAgICAgc29ydGVkQW5ub3RhdGlvbnMucHVzaCguLi53aWRnZXRBbm5vdGF0aW9ucyk7CiAgICAgIH0KICAgICAgaWYgKHBvcHVwQW5ub3RhdGlvbnMpIHsKICAgICAgICBzb3J0ZWRBbm5vdGF0aW9ucy5wdXNoKC4uLnBvcHVwQW5ub3RhdGlvbnMpOwogICAgICB9CiAgICAgIHJldHVybiBzb3J0ZWRBbm5vdGF0aW9uczsKICAgIH0pOwogICAgdGhpcy4jYXJlQW5ub3RhdGlvbnNDYWNoZWQgPSB0cnVlOwogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiX3BhcnNlZEFubm90YXRpb25zIiwgcHJvbWlzZSk7CiAgfQogIGdldCBqc0FjdGlvbnMoKSB7CiAgICBjb25zdCBhY3Rpb25zID0gY29sbGVjdEFjdGlvbnModGhpcy54cmVmLCB0aGlzLnBhZ2VEaWN0LCBQYWdlQWN0aW9uRXZlbnRUeXBlKTsKICAgIHJldHVybiBzaGFkb3codGhpcywgImpzQWN0aW9ucyIsIGFjdGlvbnMpOwogIH0KICBhc3luYyBjb2xsZWN0QW5ub3RhdGlvbnNCeVR5cGUoaGFuZGxlciwgdGFzaywgdHlwZXMsIHByb21pc2VzLCBhbm5vdGF0aW9uR2xvYmFscykgewogICAgY29uc3QgewogICAgICBwYWdlSW5kZXgKICAgIH0gPSB0aGlzOwogICAgaWYgKHRoaXMuI2FyZUFubm90YXRpb25zQ2FjaGVkKSB7CiAgICAgIGNvbnN0IGNhY2hlZEFubm90YXRpb25zID0gYXdhaXQgdGhpcy5fcGFyc2VkQW5ub3RhdGlvbnM7CiAgICAgIGZvciAoY29uc3QgewogICAgICAgIGRhdGEKICAgICAgfSBvZiBjYWNoZWRBbm5vdGF0aW9ucykgewogICAgICAgIGlmICghdHlwZXMgfHwgdHlwZXMuaGFzKGRhdGEuYW5ub3RhdGlvblR5cGUpKSB7CiAgICAgICAgICBkYXRhLnBhZ2VJbmRleCA9IHBhZ2VJbmRleDsKICAgICAgICAgIHByb21pc2VzLnB1c2goUHJvbWlzZS5yZXNvbHZlKGRhdGEpKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgYW5ub3RzID0gYXdhaXQgdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZSh0aGlzLCAiYW5ub3RhdGlvbnMiKTsKICAgIGZvciAoY29uc3QgYW5ub3RhdGlvblJlZiBvZiBhbm5vdHMpIHsKICAgICAgcHJvbWlzZXMucHVzaChBbm5vdGF0aW9uRmFjdG9yeS5jcmVhdGUodGhpcy54cmVmLCBhbm5vdGF0aW9uUmVmLCBhbm5vdGF0aW9uR2xvYmFscywgdGhpcy5fbG9jYWxJZEZhY3RvcnksIGZhbHNlLCBudWxsLCB0eXBlcywgdGhpcy5yZWYpLnRoZW4oYXN5bmMgYW5ub3RhdGlvbiA9PiB7CiAgICAgICAgaWYgKCFhbm5vdGF0aW9uKSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgICAgYW5ub3RhdGlvbi5kYXRhLnBhZ2VJbmRleCA9IHBhZ2VJbmRleDsKICAgICAgICBpZiAoYW5ub3RhdGlvbi5oYXNUZXh0Q29udGVudCAmJiBhbm5vdGF0aW9uLnZpZXdhYmxlKSB7CiAgICAgICAgICBjb25zdCBwYXJ0aWFsRXZhbHVhdG9yID0gdGhpcy4jY3JlYXRlUGFydGlhbEV2YWx1YXRvcihoYW5kbGVyKTsKICAgICAgICAgIGF3YWl0IGFubm90YXRpb24uZXh0cmFjdFRleHRDb250ZW50KHBhcnRpYWxFdmFsdWF0b3IsIHRhc2ssIFstSW5maW5pdHksIC1JbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBhbm5vdGF0aW9uLmRhdGE7CiAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICB3YXJuKGBjb2xsZWN0QW5ub3RhdGlvbnNCeVR5cGU6ICIke3JlYXNvbn0iLmApOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9KSk7CiAgICB9CiAgfQp9CmNvbnN0IFBERl9IRUFERVJfU0lHTkFUVVJFID0gbmV3IFVpbnQ4QXJyYXkoWzB4MjUsIDB4NTAsIDB4NDQsIDB4NDYsIDB4MmRdKTsKY29uc3QgU1RBUlRYUkVGX1NJR05BVFVSRSA9IG5ldyBVaW50OEFycmF5KFsweDczLCAweDc0LCAweDYxLCAweDcyLCAweDc0LCAweDc4LCAweDcyLCAweDY1LCAweDY2XSk7CmNvbnN0IEVORE9CSl9TSUdOQVRVUkUgPSBuZXcgVWludDhBcnJheShbMHg2NSwgMHg2ZSwgMHg2NCwgMHg2ZiwgMHg2MiwgMHg2YV0pOwpmdW5jdGlvbiBmaW5kKHN0cmVhbSwgc2lnbmF0dXJlLCBsaW1pdCA9IDEwMjQsIGJhY2t3YXJkcyA9IGZhbHNlKSB7CiAgY29uc3Qgc2lnbmF0dXJlTGVuZ3RoID0gc2lnbmF0dXJlLmxlbmd0aDsKICBjb25zdCBzY2FuQnl0ZXMgPSBzdHJlYW0ucGVla0J5dGVzKGxpbWl0KTsKICBjb25zdCBzY2FuTGVuZ3RoID0gc2NhbkJ5dGVzLmxlbmd0aCAtIHNpZ25hdHVyZUxlbmd0aDsKICBpZiAoc2Nhbkxlbmd0aCA8PSAwKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGlmIChiYWNrd2FyZHMpIHsKICAgIGNvbnN0IHNpZ25hdHVyZUVuZCA9IHNpZ25hdHVyZUxlbmd0aCAtIDE7CiAgICBsZXQgcG9zID0gc2NhbkJ5dGVzLmxlbmd0aCAtIDE7CiAgICB3aGlsZSAocG9zID49IHNpZ25hdHVyZUVuZCkgewogICAgICBsZXQgaiA9IDA7CiAgICAgIHdoaWxlIChqIDwgc2lnbmF0dXJlTGVuZ3RoICYmIHNjYW5CeXRlc1twb3MgLSBqXSA9PT0gc2lnbmF0dXJlW3NpZ25hdHVyZUVuZCAtIGpdKSB7CiAgICAgICAgaisrOwogICAgICB9CiAgICAgIGlmIChqID49IHNpZ25hdHVyZUxlbmd0aCkgewogICAgICAgIHN0cmVhbS5wb3MgKz0gcG9zIC0gc2lnbmF0dXJlRW5kOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIHBvcy0tOwogICAgfQogIH0gZWxzZSB7CiAgICBsZXQgcG9zID0gMDsKICAgIHdoaWxlIChwb3MgPD0gc2Nhbkxlbmd0aCkgewogICAgICBsZXQgaiA9IDA7CiAgICAgIHdoaWxlIChqIDwgc2lnbmF0dXJlTGVuZ3RoICYmIHNjYW5CeXRlc1twb3MgKyBqXSA9PT0gc2lnbmF0dXJlW2pdKSB7CiAgICAgICAgaisrOwogICAgICB9CiAgICAgIGlmIChqID49IHNpZ25hdHVyZUxlbmd0aCkgewogICAgICAgIHN0cmVhbS5wb3MgKz0gcG9zOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIHBvcysrOwogICAgfQogIH0KICByZXR1cm4gZmFsc2U7Cn0KY2xhc3MgUERGRG9jdW1lbnQgewogICNwYWdlUHJvbWlzZXMgPSBuZXcgTWFwKCk7CiAgI3ZlcnNpb24gPSBudWxsOwogIGNvbnN0cnVjdG9yKHBkZk1hbmFnZXIsIHN0cmVhbSkgewogICAgaWYgKHN0cmVhbS5sZW5ndGggPD0gMCkgewogICAgICB0aHJvdyBuZXcgSW52YWxpZFBERkV4Y2VwdGlvbigiVGhlIFBERiBmaWxlIGlzIGVtcHR5LCBpLmUuIGl0cyBzaXplIGlzIHplcm8gYnl0ZXMuIik7CiAgICB9CiAgICB0aGlzLnBkZk1hbmFnZXIgPSBwZGZNYW5hZ2VyOwogICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07CiAgICB0aGlzLnhyZWYgPSBuZXcgWFJlZihzdHJlYW0sIHBkZk1hbmFnZXIpOwogICAgY29uc3QgaWRDb3VudGVycyA9IHsKICAgICAgZm9udDogMAogICAgfTsKICAgIHRoaXMuX2dsb2JhbElkRmFjdG9yeSA9IGNsYXNzIHsKICAgICAgc3RhdGljIGdldERvY0lkKCkgewogICAgICAgIHJldHVybiBgZ18ke3BkZk1hbmFnZXIuZG9jSWR9YDsKICAgICAgfQogICAgICBzdGF0aWMgY3JlYXRlRm9udElkKCkgewogICAgICAgIHJldHVybiBgZiR7KytpZENvdW50ZXJzLmZvbnR9YDsKICAgICAgfQogICAgICBzdGF0aWMgY3JlYXRlT2JqSWQoKSB7CiAgICAgICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgY3JlYXRlT2JqSWRgIGNhbGxlZC4iKTsKICAgICAgfQogICAgICBzdGF0aWMgZ2V0UGFnZU9iaklkKCkgewogICAgICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYGdldFBhZ2VPYmpJZGAgY2FsbGVkLiIpOwogICAgICB9CiAgICB9OwogIH0KICBwYXJzZShyZWNvdmVyeU1vZGUpIHsKICAgIHRoaXMueHJlZi5wYXJzZShyZWNvdmVyeU1vZGUpOwogICAgdGhpcy5jYXRhbG9nID0gbmV3IENhdGFsb2codGhpcy5wZGZNYW5hZ2VyLCB0aGlzLnhyZWYpOwogIH0KICBnZXQgbGluZWFyaXphdGlvbigpIHsKICAgIGxldCBsaW5lYXJpemF0aW9uID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIGxpbmVhcml6YXRpb24gPSBMaW5lYXJpemF0aW9uLmNyZWF0ZSh0aGlzLnN0cmVhbSk7CiAgICB9IGNhdGNoIChlcnIpIHsKICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXJyOwogICAgICB9CiAgICAgIGluZm8oZXJyKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImxpbmVhcml6YXRpb24iLCBsaW5lYXJpemF0aW9uKTsKICB9CiAgZ2V0IHN0YXJ0WFJlZigpIHsKICAgIGNvbnN0IHN0cmVhbSA9IHRoaXMuc3RyZWFtOwogICAgbGV0IHN0YXJ0WFJlZiA9IDA7CiAgICBpZiAodGhpcy5saW5lYXJpemF0aW9uKSB7CiAgICAgIHN0cmVhbS5yZXNldCgpOwogICAgICBpZiAoZmluZChzdHJlYW0sIEVORE9CSl9TSUdOQVRVUkUpKSB7CiAgICAgICAgc3RyZWFtLnNraXAoNik7CiAgICAgICAgbGV0IGNoID0gc3RyZWFtLnBlZWtCeXRlKCk7CiAgICAgICAgd2hpbGUgKGlzV2hpdGVTcGFjZShjaCkpIHsKICAgICAgICAgIHN0cmVhbS5wb3MrKzsKICAgICAgICAgIGNoID0gc3RyZWFtLnBlZWtCeXRlKCk7CiAgICAgICAgfQogICAgICAgIHN0YXJ0WFJlZiA9IHN0cmVhbS5wb3MgLSBzdHJlYW0uc3RhcnQ7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IHN0ZXAgPSAxMDI0OwogICAgICBjb25zdCBzdGFydFhSZWZMZW5ndGggPSBTVEFSVFhSRUZfU0lHTkFUVVJFLmxlbmd0aDsKICAgICAgbGV0IGZvdW5kID0gZmFsc2UsCiAgICAgICAgcG9zID0gc3RyZWFtLmVuZDsKICAgICAgd2hpbGUgKCFmb3VuZCAmJiBwb3MgPiAwKSB7CiAgICAgICAgcG9zIC09IHN0ZXAgLSBzdGFydFhSZWZMZW5ndGg7CiAgICAgICAgaWYgKHBvcyA8IDApIHsKICAgICAgICAgIHBvcyA9IDA7CiAgICAgICAgfQogICAgICAgIHN0cmVhbS5wb3MgPSBwb3M7CiAgICAgICAgZm91bmQgPSBmaW5kKHN0cmVhbSwgU1RBUlRYUkVGX1NJR05BVFVSRSwgc3RlcCwgdHJ1ZSk7CiAgICAgIH0KICAgICAgaWYgKGZvdW5kKSB7CiAgICAgICAgc3RyZWFtLnNraXAoOSk7CiAgICAgICAgbGV0IGNoOwogICAgICAgIGRvIHsKICAgICAgICAgIGNoID0gc3RyZWFtLmdldEJ5dGUoKTsKICAgICAgICB9IHdoaWxlIChpc1doaXRlU3BhY2UoY2gpKTsKICAgICAgICBsZXQgc3RyID0gIiI7CiAgICAgICAgd2hpbGUgKGNoID49IDB4MjAgJiYgY2ggPD0gMHgzOSkgewogICAgICAgICAgc3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpOwogICAgICAgICAgY2ggPSBzdHJlYW0uZ2V0Qnl0ZSgpOwogICAgICAgIH0KICAgICAgICBzdGFydFhSZWYgPSBwYXJzZUludChzdHIsIDEwKTsKICAgICAgICBpZiAoaXNOYU4oc3RhcnRYUmVmKSkgewogICAgICAgICAgc3RhcnRYUmVmID0gMDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInN0YXJ0WFJlZiIsIHN0YXJ0WFJlZik7CiAgfQogIGNoZWNrSGVhZGVyKCkgewogICAgY29uc3Qgc3RyZWFtID0gdGhpcy5zdHJlYW07CiAgICBzdHJlYW0ucmVzZXQoKTsKICAgIGlmICghZmluZChzdHJlYW0sIFBERl9IRUFERVJfU0lHTkFUVVJFKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBzdHJlYW0ubW92ZVN0YXJ0KCk7CiAgICBzdHJlYW0uc2tpcChQREZfSEVBREVSX1NJR05BVFVSRS5sZW5ndGgpOwogICAgbGV0IHZlcnNpb24gPSAiIiwKICAgICAgY2g7CiAgICB3aGlsZSAoKGNoID0gc3RyZWFtLmdldEJ5dGUoKSkgPiAweDIwICYmIHZlcnNpb24ubGVuZ3RoIDwgNykgewogICAgICB2ZXJzaW9uICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpOwogICAgfQogICAgaWYgKFBERl9WRVJTSU9OX1JFR0VYUC50ZXN0KHZlcnNpb24pKSB7CiAgICAgIHRoaXMuI3ZlcnNpb24gPSB2ZXJzaW9uOwogICAgfSBlbHNlIHsKICAgICAgd2FybihgSW52YWxpZCBQREYgaGVhZGVyIHZlcnNpb246ICR7dmVyc2lvbn1gKTsKICAgIH0KICB9CiAgcGFyc2VTdGFydFhSZWYoKSB7CiAgICB0aGlzLnhyZWYuc2V0U3RhcnRYUmVmKHRoaXMuc3RhcnRYUmVmKTsKICB9CiAgZ2V0IG51bVBhZ2VzKCkgewogICAgbGV0IG51bSA9IDA7CiAgICBpZiAodGhpcy5jYXRhbG9nLmhhc0FjdHVhbE51bVBhZ2VzKSB7CiAgICAgIG51bSA9IHRoaXMuY2F0YWxvZy5udW1QYWdlczsKICAgIH0gZWxzZSBpZiAodGhpcy54ZmFGYWN0b3J5KSB7CiAgICAgIG51bSA9IHRoaXMueGZhRmFjdG9yeS5nZXROdW1QYWdlcygpOwogICAgfSBlbHNlIGlmICh0aGlzLmxpbmVhcml6YXRpb24pIHsKICAgICAgbnVtID0gdGhpcy5saW5lYXJpemF0aW9uLm51bVBhZ2VzOwogICAgfSBlbHNlIHsKICAgICAgbnVtID0gdGhpcy5jYXRhbG9nLm51bVBhZ2VzOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAibnVtUGFnZXMiLCBudW0pOwogIH0KICAjaGFzT25seURvY3VtZW50U2lnbmF0dXJlcyhmaWVsZHMsIHJlY3Vyc2lvbkRlcHRoID0gMCkgewogICAgY29uc3QgUkVDVVJTSU9OX0xJTUlUID0gMTA7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZmllbGRzKSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICByZXR1cm4gZmllbGRzLmV2ZXJ5KGZpZWxkID0+IHsKICAgICAgZmllbGQgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihmaWVsZCk7CiAgICAgIGlmICghKGZpZWxkIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaWYgKGZpZWxkLmhhcygiS2lkcyIpKSB7CiAgICAgICAgaWYgKCsrcmVjdXJzaW9uRGVwdGggPiBSRUNVUlNJT05fTElNSVQpIHsKICAgICAgICAgIHdhcm4oIiNoYXNPbmx5RG9jdW1lbnRTaWduYXR1cmVzOiBtYXhpbXVtIHJlY3Vyc2lvbiBkZXB0aCByZWFjaGVkIik7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzLiNoYXNPbmx5RG9jdW1lbnRTaWduYXR1cmVzKGZpZWxkLmdldCgiS2lkcyIpLCByZWN1cnNpb25EZXB0aCk7CiAgICAgIH0KICAgICAgY29uc3QgaXNTaWduYXR1cmUgPSBpc05hbWUoZmllbGQuZ2V0KCJGVCIpLCAiU2lnIik7CiAgICAgIGNvbnN0IHJlY3RhbmdsZSA9IGZpZWxkLmdldCgiUmVjdCIpOwogICAgICBjb25zdCBpc0ludmlzaWJsZSA9IEFycmF5LmlzQXJyYXkocmVjdGFuZ2xlKSAmJiByZWN0YW5nbGUuZXZlcnkodmFsdWUgPT4gdmFsdWUgPT09IDApOwogICAgICByZXR1cm4gaXNTaWduYXR1cmUgJiYgaXNJbnZpc2libGU7CiAgICB9KTsKICB9CiAgZ2V0IF94ZmFTdHJlYW1zKCkgewogICAgY29uc3QgewogICAgICBhY3JvRm9ybQogICAgfSA9IHRoaXMuY2F0YWxvZzsKICAgIGlmICghYWNyb0Zvcm0pIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCB4ZmEgPSBhY3JvRm9ybS5nZXQoIlhGQSIpOwogICAgY29uc3QgZW50cmllcyA9IG5ldyBNYXAoWyJ4ZHA6eGRwIiwgInRlbXBsYXRlIiwgImRhdGFzZXRzIiwgImNvbmZpZyIsICJjb25uZWN0aW9uU2V0IiwgImxvY2FsZVNldCIsICJzdHlsZXNoZWV0IiwgIi94ZHA6eGRwIl0ubWFwKGUgPT4gW2UsIG51bGxdKSk7CiAgICBpZiAoeGZhIGluc3RhbmNlb2YgQmFzZVN0cmVhbSAmJiAheGZhLmlzRW1wdHkpIHsKICAgICAgZW50cmllcy5zZXQoInhkcDp4ZHAiLCB4ZmEpOwogICAgICByZXR1cm4gZW50cmllczsKICAgIH0KICAgIGlmICghQXJyYXkuaXNBcnJheSh4ZmEpIHx8IHhmYS5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB4ZmEubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICBsZXQgbmFtZTsKICAgICAgaWYgKGkgPT09IDApIHsKICAgICAgICBuYW1lID0gInhkcDp4ZHAiOwogICAgICB9IGVsc2UgaWYgKGkgPT09IGlpIC0gMikgewogICAgICAgIG5hbWUgPSAiL3hkcDp4ZHAiOwogICAgICB9IGVsc2UgewogICAgICAgIG5hbWUgPSB4ZmFbaV07CiAgICAgIH0KICAgICAgaWYgKCFlbnRyaWVzLmhhcyhuYW1lKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZih4ZmFbaSArIDFdKTsKICAgICAgaWYgKCEoZGF0YSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHx8IGRhdGEuaXNFbXB0eSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGVudHJpZXMuc2V0KG5hbWUsIGRhdGEpOwogICAgfQogICAgcmV0dXJuIGVudHJpZXM7CiAgfQogIGdldCB4ZmFEYXRhc2V0cygpIHsKICAgIGNvbnN0IHN0cmVhbXMgPSB0aGlzLl94ZmFTdHJlYW1zOwogICAgaWYgKCFzdHJlYW1zKSB7CiAgICAgIHJldHVybiBzaGFkb3codGhpcywgInhmYURhdGFzZXRzIiwgbnVsbCk7CiAgICB9CiAgICBmb3IgKGNvbnN0IGtleSBvZiBbImRhdGFzZXRzIiwgInhkcDp4ZHAiXSkgewogICAgICBjb25zdCBzdHJlYW0gPSBzdHJlYW1zLmdldChrZXkpOwogICAgICBpZiAoIXN0cmVhbSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3Qgc3RyID0gc3RyaW5nVG9VVEY4U3RyaW5nKHN0cmVhbS5nZXRTdHJpbmcoKSk7CiAgICAgICAgY29uc3QgZGF0YSA9IHsKICAgICAgICAgIFtrZXldOiBzdHIKICAgICAgICB9OwogICAgICAgIHJldHVybiBzaGFkb3codGhpcywgInhmYURhdGFzZXRzIiwgbmV3IERhdGFzZXRSZWFkZXIoZGF0YSkpOwogICAgICB9IGNhdGNoIHsKICAgICAgICB3YXJuKCJYRkEgLSBJbnZhbGlkIHV0Zi04IHN0cmluZy4iKTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAieGZhRGF0YXNldHMiLCBudWxsKTsKICB9CiAgZ2V0IHhmYURhdGEoKSB7CiAgICBjb25zdCBzdHJlYW1zID0gdGhpcy5feGZhU3RyZWFtczsKICAgIGlmICghc3RyZWFtcykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGRhdGEgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgZm9yIChjb25zdCBba2V5LCBzdHJlYW1dIG9mIHN0cmVhbXMpIHsKICAgICAgaWYgKCFzdHJlYW0pIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICB0cnkgewogICAgICAgIGRhdGFba2V5XSA9IHN0cmluZ1RvVVRGOFN0cmluZyhzdHJlYW0uZ2V0U3RyaW5nKCkpOwogICAgICB9IGNhdGNoIHsKICAgICAgICB3YXJuKCJYRkEgLSBJbnZhbGlkIHV0Zi04IHN0cmluZy4iKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGRhdGE7CiAgfQogIGdldCB4ZmFGYWN0b3J5KCkgewogICAgbGV0IGRhdGE7CiAgICBpZiAodGhpcy5wZGZNYW5hZ2VyLmVuYWJsZVhmYSAmJiB0aGlzLmNhdGFsb2cubmVlZHNSZW5kZXJpbmcgJiYgdGhpcy5mb3JtSW5mby5oYXNYZmEgJiYgIXRoaXMuZm9ybUluZm8uaGFzQWNyb0Zvcm0pIHsKICAgICAgZGF0YSA9IHRoaXMueGZhRGF0YTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInhmYUZhY3RvcnkiLCBkYXRhID8gbmV3IFhGQUZhY3RvcnkoZGF0YSkgOiBudWxsKTsKICB9CiAgZ2V0IGlzUHVyZVhmYSgpIHsKICAgIHJldHVybiB0aGlzLnhmYUZhY3RvcnkgPyB0aGlzLnhmYUZhY3RvcnkuaXNWYWxpZCgpIDogZmFsc2U7CiAgfQogIGdldCBodG1sRm9yWGZhKCkgewogICAgcmV0dXJuIHRoaXMueGZhRmFjdG9yeSA/IHRoaXMueGZhRmFjdG9yeS5nZXRQYWdlcygpIDogbnVsbDsKICB9CiAgYXN5bmMgI2xvYWRYZmFJbWFnZXMoKSB7CiAgICBjb25zdCB4ZmFJbWFnZXMgPSBhd2FpdCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygieGZhSW1hZ2VzIik7CiAgICBpZiAoIXhmYUltYWdlcykgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLnhmYUZhY3Rvcnkuc2V0SW1hZ2VzKHhmYUltYWdlcyk7CiAgfQogIGFzeW5jICNsb2FkWGZhRm9udHMoaGFuZGxlciwgdGFzaykgewogICAgY29uc3QgYWNyb0Zvcm0gPSBhd2FpdCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiYWNyb0Zvcm0iKTsKICAgIGlmICghYWNyb0Zvcm0pIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgcmVzb3VyY2VzID0gYXdhaXQgYWNyb0Zvcm0uZ2V0QXN5bmMoIkRSIik7CiAgICBpZiAoIShyZXNvdXJjZXMgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBhd2FpdCBPYmplY3RMb2FkZXIubG9hZChyZXNvdXJjZXMsIFsiRm9udCJdLCB0aGlzLnhyZWYpOwogICAgY29uc3QgZm9udFJlcyA9IHJlc291cmNlcy5nZXQoIkZvbnQiKTsKICAgIGlmICghKGZvbnRSZXMgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG51bGwpLCB0aGlzLnBkZk1hbmFnZXIuZXZhbHVhdG9yT3B0aW9ucywgewogICAgICB1c2VTeXN0ZW1Gb250czogZmFsc2UKICAgIH0pOwogICAgY29uc3QgewogICAgICBidWlsdEluQ01hcENhY2hlLAogICAgICBmb250Q2FjaGUsCiAgICAgIHN0YW5kYXJkRm9udERhdGFDYWNoZQogICAgfSA9IHRoaXMuY2F0YWxvZzsKICAgIGNvbnN0IHBhcnRpYWxFdmFsdWF0b3IgPSBuZXcgUGFydGlhbEV2YWx1YXRvcih7CiAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgaGFuZGxlciwKICAgICAgcGFnZUluZGV4OiAtMSwKICAgICAgaWRGYWN0b3J5OiB0aGlzLl9nbG9iYWxJZEZhY3RvcnksCiAgICAgIGZvbnRDYWNoZSwKICAgICAgYnVpbHRJbkNNYXBDYWNoZSwKICAgICAgc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgICBvcHRpb25zCiAgICB9KTsKICAgIGNvbnN0IG9wZXJhdG9yTGlzdCA9IG5ldyBPcGVyYXRvckxpc3QoKTsKICAgIGNvbnN0IHBkZkZvbnRzID0gW107CiAgICBjb25zdCBpbml0aWFsU3RhdGUgPSB7CiAgICAgIGdldCBmb250KCkgewogICAgICAgIHJldHVybiBwZGZGb250cy5hdCgtMSk7CiAgICAgIH0sCiAgICAgIHNldCBmb250KGZvbnQpIHsKICAgICAgICBwZGZGb250cy5wdXNoKGZvbnQpOwogICAgICB9LAogICAgICBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgfTsKICAgIGNvbnN0IHBhcnNlRm9udCA9IChmb250TmFtZSwgZmFsbGJhY2tGb250RGljdCwgY3NzRm9udEluZm8pID0+IHBhcnRpYWxFdmFsdWF0b3IuaGFuZGxlU2V0Rm9udChyZXNvdXJjZXMsIFtOYW1lLmdldChmb250TmFtZSksIDFdLCBudWxsLCBvcGVyYXRvckxpc3QsIHRhc2ssIGluaXRpYWxTdGF0ZSwgZmFsbGJhY2tGb250RGljdCwgY3NzRm9udEluZm8pLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgIHdhcm4oYGxvYWRYZmFGb250czogIiR7cmVhc29ufSIuYCk7CiAgICAgIHJldHVybiBudWxsOwogICAgfSk7CiAgICBjb25zdCBwcm9taXNlcyA9IFtdOwogICAgZm9yIChjb25zdCBbZm9udE5hbWUsIGZvbnRdIG9mIGZvbnRSZXMpIHsKICAgICAgY29uc3QgZGVzY3JpcHRvciA9IGZvbnQuZ2V0KCJGb250RGVzY3JpcHRvciIpOwogICAgICBpZiAoIShkZXNjcmlwdG9yIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBsZXQgZm9udEZhbWlseSA9IGRlc2NyaXB0b3IuZ2V0KCJGb250RmFtaWx5Iik7CiAgICAgIGZvbnRGYW1pbHkgPSBmb250RmFtaWx5LnJlcGxhY2VBbGwoL1sgXSsoXGQpL2csICIkMSIpOwogICAgICBjb25zdCBmb250V2VpZ2h0ID0gZGVzY3JpcHRvci5nZXQoIkZvbnRXZWlnaHQiKTsKICAgICAgY29uc3QgaXRhbGljQW5nbGUgPSAtZGVzY3JpcHRvci5nZXQoIkl0YWxpY0FuZ2xlIik7CiAgICAgIGNvbnN0IGNzc0ZvbnRJbmZvID0gewogICAgICAgIGZvbnRGYW1pbHksCiAgICAgICAgZm9udFdlaWdodCwKICAgICAgICBpdGFsaWNBbmdsZQogICAgICB9OwogICAgICBpZiAoIXZhbGlkYXRlQ1NTRm9udChjc3NGb250SW5mbykpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBwcm9taXNlcy5wdXNoKHBhcnNlRm9udChmb250TmFtZSwgbnVsbCwgY3NzRm9udEluZm8pKTsKICAgIH0KICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTsKICAgIGNvbnN0IG1pc3NpbmdGb250cyA9IHRoaXMueGZhRmFjdG9yeS5zZXRGb250cyhwZGZGb250cyk7CiAgICBpZiAoIW1pc3NpbmdGb250cykgewogICAgICByZXR1cm47CiAgICB9CiAgICBvcHRpb25zLmlnbm9yZUVycm9ycyA9IHRydWU7CiAgICBwcm9taXNlcy5sZW5ndGggPSAwOwogICAgcGRmRm9udHMubGVuZ3RoID0gMDsKICAgIGNvbnN0IHJlYWxseU1pc3NpbmdGb250cyA9IG5ldyBTZXQoKTsKICAgIGZvciAoY29uc3QgbWlzc2luZyBvZiBtaXNzaW5nRm9udHMpIHsKICAgICAgaWYgKCFnZXRYZmFGb250TmFtZShgJHttaXNzaW5nfS1SZWd1bGFyYCkpIHsKICAgICAgICByZWFsbHlNaXNzaW5nRm9udHMuYWRkKG1pc3NpbmcpOwogICAgICB9CiAgICB9CiAgICBpZiAocmVhbGx5TWlzc2luZ0ZvbnRzLnNpemUpIHsKICAgICAgbWlzc2luZ0ZvbnRzLnB1c2goIlBkZkpTLUZhbGxiYWNrIik7CiAgICB9CiAgICBmb3IgKGNvbnN0IG1pc3Npbmcgb2YgbWlzc2luZ0ZvbnRzKSB7CiAgICAgIGlmIChyZWFsbHlNaXNzaW5nRm9udHMuaGFzKG1pc3NpbmcpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBmb250SW5mbyBvZiBbewogICAgICAgIG5hbWU6ICJSZWd1bGFyIiwKICAgICAgICBmb250V2VpZ2h0OiA0MDAsCiAgICAgICAgaXRhbGljQW5nbGU6IDAKICAgICAgfSwgewogICAgICAgIG5hbWU6ICJCb2xkIiwKICAgICAgICBmb250V2VpZ2h0OiA3MDAsCiAgICAgICAgaXRhbGljQW5nbGU6IDAKICAgICAgfSwgewogICAgICAgIG5hbWU6ICJJdGFsaWMiLAogICAgICAgIGZvbnRXZWlnaHQ6IDQwMCwKICAgICAgICBpdGFsaWNBbmdsZTogMTIKICAgICAgfSwgewogICAgICAgIG5hbWU6ICJCb2xkSXRhbGljIiwKICAgICAgICBmb250V2VpZ2h0OiA3MDAsCiAgICAgICAgaXRhbGljQW5nbGU6IDEyCiAgICAgIH1dKSB7CiAgICAgICAgY29uc3QgbmFtZSA9IGAke21pc3Npbmd9LSR7Zm9udEluZm8ubmFtZX1gOwogICAgICAgIHByb21pc2VzLnB1c2gocGFyc2VGb250KG5hbWUsIGdldFhmYUZvbnREaWN0KG5hbWUpLCB7CiAgICAgICAgICBmb250RmFtaWx5OiBtaXNzaW5nLAogICAgICAgICAgZm9udFdlaWdodDogZm9udEluZm8uZm9udFdlaWdodCwKICAgICAgICAgIGl0YWxpY0FuZ2xlOiBmb250SW5mby5pdGFsaWNBbmdsZQogICAgICAgIH0pKTsKICAgICAgfQogICAgfQogICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpOwogICAgdGhpcy54ZmFGYWN0b3J5LmFwcGVuZEZvbnRzKHBkZkZvbnRzLCByZWFsbHlNaXNzaW5nRm9udHMpOwogIH0KICBsb2FkWGZhUmVzb3VyY2VzKGhhbmRsZXIsIHRhc2spIHsKICAgIHJldHVybiBQcm9taXNlLmFsbChbdGhpcy4jbG9hZFhmYUZvbnRzKGhhbmRsZXIsIHRhc2spLmNhdGNoKCgpID0+IHt9KSwgdGhpcy4jbG9hZFhmYUltYWdlcygpXSk7CiAgfQogIHNlcmlhbGl6ZVhmYURhdGEoYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIHJldHVybiB0aGlzLnhmYUZhY3RvcnkgPyB0aGlzLnhmYUZhY3Rvcnkuc2VyaWFsaXplRGF0YShhbm5vdGF0aW9uU3RvcmFnZSkgOiBudWxsOwogIH0KICBnZXQgdmVyc2lvbigpIHsKICAgIHJldHVybiB0aGlzLmNhdGFsb2cudmVyc2lvbiB8fCB0aGlzLiN2ZXJzaW9uOwogIH0KICBnZXQgZm9ybUluZm8oKSB7CiAgICBjb25zdCBmb3JtSW5mbyA9IHsKICAgICAgaGFzRmllbGRzOiBmYWxzZSwKICAgICAgaGFzQWNyb0Zvcm06IGZhbHNlLAogICAgICBoYXNYZmE6IGZhbHNlLAogICAgICBoYXNTaWduYXR1cmVzOiBmYWxzZQogICAgfTsKICAgIGNvbnN0IHsKICAgICAgYWNyb0Zvcm0KICAgIH0gPSB0aGlzLmNhdGFsb2c7CiAgICBpZiAoIWFjcm9Gb3JtKSB7CiAgICAgIHJldHVybiBzaGFkb3codGhpcywgImZvcm1JbmZvIiwgZm9ybUluZm8pOwogICAgfQogICAgdHJ5IHsKICAgICAgY29uc3QgZmllbGRzID0gYWNyb0Zvcm0uZ2V0KCJGaWVsZHMiKTsKICAgICAgY29uc3QgaGFzRmllbGRzID0gQXJyYXkuaXNBcnJheShmaWVsZHMpICYmIGZpZWxkcy5sZW5ndGggPiAwOwogICAgICBmb3JtSW5mby5oYXNGaWVsZHMgPSBoYXNGaWVsZHM7CiAgICAgIGNvbnN0IHhmYSA9IGFjcm9Gb3JtLmdldCgiWEZBIik7CiAgICAgIGZvcm1JbmZvLmhhc1hmYSA9IEFycmF5LmlzQXJyYXkoeGZhKSAmJiB4ZmEubGVuZ3RoID4gMCB8fCB4ZmEgaW5zdGFuY2VvZiBCYXNlU3RyZWFtICYmICF4ZmEuaXNFbXB0eTsKICAgICAgY29uc3Qgc2lnRmxhZ3MgPSBhY3JvRm9ybS5nZXQoIlNpZ0ZsYWdzIik7CiAgICAgIGNvbnN0IGhhc1NpZ25hdHVyZXMgPSAhIShzaWdGbGFncyAmIDB4MSk7CiAgICAgIGNvbnN0IGhhc09ubHlEb2N1bWVudFNpZ25hdHVyZXMgPSBoYXNTaWduYXR1cmVzICYmIHRoaXMuI2hhc09ubHlEb2N1bWVudFNpZ25hdHVyZXMoZmllbGRzKTsKICAgICAgZm9ybUluZm8uaGFzQWNyb0Zvcm0gPSBoYXNGaWVsZHMgJiYgIWhhc09ubHlEb2N1bWVudFNpZ25hdHVyZXM7CiAgICAgIGZvcm1JbmZvLmhhc1NpZ25hdHVyZXMgPSBoYXNTaWduYXR1cmVzOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICB3YXJuKGBDYW5ub3QgZmV0Y2ggZm9ybSBpbmZvcm1hdGlvbjogIiR7ZXh9Ii5gKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImZvcm1JbmZvIiwgZm9ybUluZm8pOwogIH0KICBnZXQgZG9jdW1lbnRJbmZvKCkgewogICAgY29uc3QgewogICAgICBjYXRhbG9nLAogICAgICBmb3JtSW5mbywKICAgICAgeHJlZgogICAgfSA9IHRoaXM7CiAgICBjb25zdCBkb2NJbmZvID0gewogICAgICBQREZGb3JtYXRWZXJzaW9uOiB0aGlzLnZlcnNpb24sCiAgICAgIExhbmd1YWdlOiBjYXRhbG9nLmxhbmcsCiAgICAgIEVuY3J5cHRGaWx0ZXJOYW1lOiB4cmVmLmVuY3J5cHQ/LmZpbHRlck5hbWUgPz8gbnVsbCwKICAgICAgSXNMaW5lYXJpemVkOiAhIXRoaXMubGluZWFyaXphdGlvbiwKICAgICAgSXNBY3JvRm9ybVByZXNlbnQ6IGZvcm1JbmZvLmhhc0Fjcm9Gb3JtLAogICAgICBJc1hGQVByZXNlbnQ6IGZvcm1JbmZvLmhhc1hmYSwKICAgICAgSXNDb2xsZWN0aW9uUHJlc2VudDogISFjYXRhbG9nLmNvbGxlY3Rpb24sCiAgICAgIElzU2lnbmF0dXJlc1ByZXNlbnQ6IGZvcm1JbmZvLmhhc1NpZ25hdHVyZXMKICAgIH07CiAgICBsZXQgaW5mb0RpY3Q7CiAgICB0cnkgewogICAgICBpbmZvRGljdCA9IHhyZWYudHJhaWxlci5nZXQoIkluZm8iKTsKICAgIH0gY2F0Y2ggKGVycikgewogICAgICBpZiAoZXJyIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBlcnI7CiAgICAgIH0KICAgICAgaW5mbygiVGhlIGRvY3VtZW50IGluZm9ybWF0aW9uIGRpY3Rpb25hcnkgaXMgaW52YWxpZC4iKTsKICAgIH0KICAgIGlmICghKGluZm9EaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiZG9jdW1lbnRJbmZvIiwgZG9jSW5mbyk7CiAgICB9CiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBpbmZvRGljdCkgewogICAgICBzd2l0Y2ggKGtleSkgewogICAgICAgIGNhc2UgIlRpdGxlIjoKICAgICAgICBjYXNlICJBdXRob3IiOgogICAgICAgIGNhc2UgIlN1YmplY3QiOgogICAgICAgIGNhc2UgIktleXdvcmRzIjoKICAgICAgICBjYXNlICJDcmVhdG9yIjoKICAgICAgICBjYXNlICJQcm9kdWNlciI6CiAgICAgICAgY2FzZSAiQ3JlYXRpb25EYXRlIjoKICAgICAgICBjYXNlICJNb2REYXRlIjoKICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgIGRvY0luZm9ba2V5XSA9IHN0cmluZ1RvUERGU3RyaW5nKHZhbHVlKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJUcmFwcGVkIjoKICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgICAgZG9jSW5mb1trZXldID0gdmFsdWU7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIGxldCBjdXN0b21WYWx1ZTsKICAgICAgICAgIHN3aXRjaCAodHlwZW9mIHZhbHVlKSB7CiAgICAgICAgICAgIGNhc2UgInN0cmluZyI6CiAgICAgICAgICAgICAgY3VzdG9tVmFsdWUgPSBzdHJpbmdUb1BERlN0cmluZyh2YWx1ZSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgIm51bWJlciI6CiAgICAgICAgICAgIGNhc2UgImJvb2xlYW4iOgogICAgICAgICAgICAgIGN1c3RvbVZhbHVlID0gdmFsdWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgICAgICAgY3VzdG9tVmFsdWUgPSB2YWx1ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoY3VzdG9tVmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICB3YXJuKGBCYWQgdmFsdWUsIGZvciBjdXN0b20ga2V5ICIke2tleX0iLCBpbiBJbmZvOiAke3ZhbHVlfS5gKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBkb2NJbmZvLkN1c3RvbSA/Pz0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgIGRvY0luZm8uQ3VzdG9tW2tleV0gPSBjdXN0b21WYWx1ZTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHdhcm4oYEJhZCB2YWx1ZSwgZm9yIGtleSAiJHtrZXl9IiwgaW4gSW5mbzogJHt2YWx1ZX0uYCk7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJkb2N1bWVudEluZm8iLCBkb2NJbmZvKTsKICB9CiAgZ2V0IGZpbmdlcnByaW50cygpIHsKICAgIGNvbnN0IEZJTkdFUlBSSU5UX0ZJUlNUX0JZVEVTID0gMTAyNDsKICAgIGNvbnN0IEVNUFRZX0ZJTkdFUlBSSU5UID0gIlx4MDAiLnJlcGVhdCgxNik7CiAgICBmdW5jdGlvbiB2YWxpZGF0ZShkYXRhKSB7CiAgICAgIHJldHVybiB0eXBlb2YgZGF0YSA9PT0gInN0cmluZyIgJiYgZGF0YS5sZW5ndGggPT09IDE2ICYmIGRhdGEgIT09IEVNUFRZX0ZJTkdFUlBSSU5UOwogICAgfQogICAgY29uc3QgaWQgPSB0aGlzLnhyZWYudHJhaWxlci5nZXQoIklEIik7CiAgICBsZXQgaGFzaE9yaWdpbmFsLCBoYXNoTW9kaWZpZWQ7CiAgICBpZiAoQXJyYXkuaXNBcnJheShpZCkgJiYgdmFsaWRhdGUoaWRbMF0pKSB7CiAgICAgIGhhc2hPcmlnaW5hbCA9IHN0cmluZ1RvQnl0ZXMoaWRbMF0pOwogICAgICBpZiAoaWRbMV0gIT09IGlkWzBdICYmIHZhbGlkYXRlKGlkWzFdKSkgewogICAgICAgIGhhc2hNb2RpZmllZCA9IHN0cmluZ1RvQnl0ZXMoaWRbMV0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBoYXNoT3JpZ2luYWwgPSBjYWxjdWxhdGVNRDUodGhpcy5zdHJlYW0uZ2V0Qnl0ZVJhbmdlKDAsIEZJTkdFUlBSSU5UX0ZJUlNUX0JZVEVTKSwgMCwgRklOR0VSUFJJTlRfRklSU1RfQllURVMpOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiZmluZ2VycHJpbnRzIiwgW2hhc2hPcmlnaW5hbC50b0hleCgpLCBoYXNoTW9kaWZpZWQ/LnRvSGV4KCkgPz8gbnVsbF0pOwogIH0KICBhc3luYyAjZ2V0TGluZWFyaXphdGlvblBhZ2UocGFnZUluZGV4KSB7CiAgICBjb25zdCB7CiAgICAgIGNhdGFsb2csCiAgICAgIGxpbmVhcml6YXRpb24sCiAgICAgIHhyZWYKICAgIH0gPSB0aGlzOwogICAgY29uc3QgcmVmID0gUmVmLmdldChsaW5lYXJpemF0aW9uLm9iamVjdE51bWJlckZpcnN0LCAwKTsKICAgIHRyeSB7CiAgICAgIGNvbnN0IG9iaiA9IGF3YWl0IHhyZWYuZmV0Y2hBc3luYyhyZWYpOwogICAgICBpZiAob2JqIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIGxldCB0eXBlID0gb2JqLmdldFJhdygiVHlwZSIpOwogICAgICAgIGlmICh0eXBlIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICB0eXBlID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKHR5cGUpOwogICAgICAgIH0KICAgICAgICBpZiAoaXNOYW1lKHR5cGUsICJQYWdlIikgfHwgIW9iai5oYXMoIlR5cGUiKSAmJiAhb2JqLmhhcygiS2lkcyIpICYmIG9iai5oYXMoIkNvbnRlbnRzIikpIHsKICAgICAgICAgIGlmICghY2F0YWxvZy5wYWdlS2lkc0NvdW50Q2FjaGUuaGFzKHJlZikpIHsKICAgICAgICAgICAgY2F0YWxvZy5wYWdlS2lkc0NvdW50Q2FjaGUucHV0KHJlZiwgMSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIWNhdGFsb2cucGFnZUluZGV4Q2FjaGUuaGFzKHJlZikpIHsKICAgICAgICAgICAgY2F0YWxvZy5wYWdlSW5kZXhDYWNoZS5wdXQocmVmLCAwKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBbb2JqLCByZWZdOwogICAgICAgIH0KICAgICAgfQogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlRoZSBMaW5lYXJpemF0aW9uIGRpY3Rpb25hcnkgZG9lc24ndCBwb2ludCB0byBhIHZhbGlkIFBhZ2UgZGljdGlvbmFyeS4iKTsKICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICB3YXJuKGBfZ2V0TGluZWFyaXphdGlvblBhZ2U6ICIke3JlYXNvbi5tZXNzYWdlfSIuYCk7CiAgICAgIHJldHVybiBjYXRhbG9nLmdldFBhZ2VEaWN0KHBhZ2VJbmRleCk7CiAgICB9CiAgfQogIGdldFBhZ2UocGFnZUluZGV4KSB7CiAgICBjb25zdCBjYWNoZWRQcm9taXNlID0gdGhpcy4jcGFnZVByb21pc2VzLmdldChwYWdlSW5kZXgpOwogICAgaWYgKGNhY2hlZFByb21pc2UpIHsKICAgICAgcmV0dXJuIGNhY2hlZFByb21pc2U7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIGNhdGFsb2csCiAgICAgIGxpbmVhcml6YXRpb24sCiAgICAgIHhmYUZhY3RvcnkKICAgIH0gPSB0aGlzOwogICAgbGV0IHByb21pc2U7CiAgICBpZiAoeGZhRmFjdG9yeSkgewogICAgICBwcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKFtEaWN0LmVtcHR5LCBudWxsXSk7CiAgICB9IGVsc2UgaWYgKGxpbmVhcml6YXRpb24/LnBhZ2VGaXJzdCA9PT0gcGFnZUluZGV4KSB7CiAgICAgIHByb21pc2UgPSB0aGlzLiNnZXRMaW5lYXJpemF0aW9uUGFnZShwYWdlSW5kZXgpOwogICAgfSBlbHNlIHsKICAgICAgcHJvbWlzZSA9IGNhdGFsb2cuZ2V0UGFnZURpY3QocGFnZUluZGV4KTsKICAgIH0KICAgIHByb21pc2UgPSBwcm9taXNlLnRoZW4oKFtwYWdlRGljdCwgcmVmXSkgPT4gbmV3IFBhZ2UoewogICAgICBwZGZNYW5hZ2VyOiB0aGlzLnBkZk1hbmFnZXIsCiAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgcGFnZUluZGV4LAogICAgICBwYWdlRGljdCwKICAgICAgcmVmLAogICAgICBnbG9iYWxJZEZhY3Rvcnk6IHRoaXMuX2dsb2JhbElkRmFjdG9yeSwKICAgICAgZm9udENhY2hlOiBjYXRhbG9nLmZvbnRDYWNoZSwKICAgICAgYnVpbHRJbkNNYXBDYWNoZTogY2F0YWxvZy5idWlsdEluQ01hcENhY2hlLAogICAgICBzdGFuZGFyZEZvbnREYXRhQ2FjaGU6IGNhdGFsb2cuc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGU6IGNhdGFsb2cuZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICBnbG9iYWxJbWFnZUNhY2hlOiBjYXRhbG9nLmdsb2JhbEltYWdlQ2FjaGUsCiAgICAgIHN5c3RlbUZvbnRDYWNoZTogY2F0YWxvZy5zeXN0ZW1Gb250Q2FjaGUsCiAgICAgIG5vbkJsZW5kTW9kZXNTZXQ6IGNhdGFsb2cubm9uQmxlbmRNb2Rlc1NldCwKICAgICAgeGZhRmFjdG9yeQogICAgfSkpOwogICAgdGhpcy4jcGFnZVByb21pc2VzLnNldChwYWdlSW5kZXgsIHByb21pc2UpOwogICAgcmV0dXJuIHByb21pc2U7CiAgfQogIGFzeW5jIGNoZWNrRmlyc3RQYWdlKHJlY292ZXJ5TW9kZSA9IGZhbHNlKSB7CiAgICBpZiAocmVjb3ZlcnlNb2RlKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRyeSB7CiAgICAgIGF3YWl0IHRoaXMuZ2V0UGFnZSgwKTsKICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgWFJlZkVudHJ5RXhjZXB0aW9uKSB7CiAgICAgICAgdGhpcy4jcGFnZVByb21pc2VzLmRlbGV0ZSgwKTsKICAgICAgICBhd2FpdCB0aGlzLmNsZWFudXAoKTsKICAgICAgICB0aHJvdyBuZXcgWFJlZlBhcnNlRXhjZXB0aW9uKCk7CiAgICAgIH0KICAgIH0KICB9CiAgYXN5bmMgY2hlY2tMYXN0UGFnZShyZWNvdmVyeU1vZGUgPSBmYWxzZSkgewogICAgY29uc3QgewogICAgICBjYXRhbG9nLAogICAgICBwZGZNYW5hZ2VyCiAgICB9ID0gdGhpczsKICAgIGNhdGFsb2cuc2V0QWN0dWFsTnVtUGFnZXMoKTsKICAgIGxldCBudW1QYWdlczsKICAgIHRyeSB7CiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtwZGZNYW5hZ2VyLmVuc3VyZURvYygieGZhRmFjdG9yeSIpLCBwZGZNYW5hZ2VyLmVuc3VyZURvYygibGluZWFyaXphdGlvbiIpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coIm51bVBhZ2VzIildKTsKICAgICAgaWYgKHRoaXMueGZhRmFjdG9yeSkgewogICAgICAgIHJldHVybjsKICAgICAgfSBlbHNlIGlmICh0aGlzLmxpbmVhcml6YXRpb24pIHsKICAgICAgICBudW1QYWdlcyA9IHRoaXMubGluZWFyaXphdGlvbi5udW1QYWdlczsKICAgICAgfSBlbHNlIHsKICAgICAgICBudW1QYWdlcyA9IGNhdGFsb2cubnVtUGFnZXM7CiAgICAgIH0KICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKG51bVBhZ2VzKSkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiUGFnZSBjb3VudCBpcyBub3QgYW4gaW50ZWdlci4iKTsKICAgICAgfSBlbHNlIGlmIChudW1QYWdlcyA8PSAxKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGF3YWl0IHRoaXMuZ2V0UGFnZShudW1QYWdlcyAtIDEpOwogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIHRoaXMuI3BhZ2VQcm9taXNlcy5kZWxldGUobnVtUGFnZXMgLSAxKTsKICAgICAgYXdhaXQgdGhpcy5jbGVhbnVwKCk7CiAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBYUmVmRW50cnlFeGNlcHRpb24gJiYgIXJlY292ZXJ5TW9kZSkgewogICAgICAgIHRocm93IG5ldyBYUmVmUGFyc2VFeGNlcHRpb24oKTsKICAgICAgfQogICAgICB3YXJuKGBjaGVja0xhc3RQYWdlIC0gaW52YWxpZCAvUGFnZXMgdHJlZSAvQ291bnQ6ICR7bnVtUGFnZXN9LmApOwogICAgICBsZXQgcGFnZXNUcmVlOwogICAgICB0cnkgewogICAgICAgIHBhZ2VzVHJlZSA9IGF3YWl0IGNhdGFsb2cuZ2V0QWxsUGFnZURpY3RzKHJlY292ZXJ5TW9kZSk7CiAgICAgIH0gY2F0Y2ggKHJlYXNvbkFsbCkgewogICAgICAgIGlmIChyZWFzb25BbGwgaW5zdGFuY2VvZiBYUmVmRW50cnlFeGNlcHRpb24gJiYgIXJlY292ZXJ5TW9kZSkgewogICAgICAgICAgdGhyb3cgbmV3IFhSZWZQYXJzZUV4Y2VwdGlvbigpOwogICAgICAgIH0KICAgICAgICBjYXRhbG9nLnNldEFjdHVhbE51bVBhZ2VzKDEpOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBmb3IgKGNvbnN0IFtwYWdlSW5kZXgsIFtwYWdlRGljdCwgcmVmXV0gb2YgcGFnZXNUcmVlKSB7CiAgICAgICAgbGV0IHByb21pc2U7CiAgICAgICAgaWYgKHBhZ2VEaWN0IGluc3RhbmNlb2YgRXJyb3IpIHsKICAgICAgICAgIHByb21pc2UgPSBQcm9taXNlLnJlamVjdChwYWdlRGljdCk7CiAgICAgICAgICBwcm9taXNlLmNhdGNoKCgpID0+IHt9KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShuZXcgUGFnZSh7CiAgICAgICAgICAgIHBkZk1hbmFnZXIsCiAgICAgICAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgICAgICAgcGFnZUluZGV4LAogICAgICAgICAgICBwYWdlRGljdCwKICAgICAgICAgICAgcmVmLAogICAgICAgICAgICBnbG9iYWxJZEZhY3Rvcnk6IHRoaXMuX2dsb2JhbElkRmFjdG9yeSwKICAgICAgICAgICAgZm9udENhY2hlOiBjYXRhbG9nLmZvbnRDYWNoZSwKICAgICAgICAgICAgYnVpbHRJbkNNYXBDYWNoZTogY2F0YWxvZy5idWlsdEluQ01hcENhY2hlLAogICAgICAgICAgICBzdGFuZGFyZEZvbnREYXRhQ2FjaGU6IGNhdGFsb2cuc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgICAgICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGU6IHRoaXMuZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICAgICAgICBnbG9iYWxJbWFnZUNhY2hlOiBjYXRhbG9nLmdsb2JhbEltYWdlQ2FjaGUsCiAgICAgICAgICAgIHN5c3RlbUZvbnRDYWNoZTogY2F0YWxvZy5zeXN0ZW1Gb250Q2FjaGUsCiAgICAgICAgICAgIG5vbkJsZW5kTW9kZXNTZXQ6IGNhdGFsb2cubm9uQmxlbmRNb2Rlc1NldCwKICAgICAgICAgICAgeGZhRmFjdG9yeTogbnVsbAogICAgICAgICAgfSkpOwogICAgICAgIH0KICAgICAgICB0aGlzLiNwYWdlUHJvbWlzZXMuc2V0KHBhZ2VJbmRleCwgcHJvbWlzZSk7CiAgICAgIH0KICAgICAgY2F0YWxvZy5zZXRBY3R1YWxOdW1QYWdlcyhwYWdlc1RyZWUuc2l6ZSk7CiAgICB9CiAgfQogIGFzeW5jIGZvbnRGYWxsYmFjayhpZCwgaGFuZGxlcikgewogICAgY29uc3QgewogICAgICBjYXRhbG9nLAogICAgICBwZGZNYW5hZ2VyCiAgICB9ID0gdGhpczsKICAgIGZvciAoY29uc3QgdHJhbnNsYXRlZEZvbnQgb2YgYXdhaXQgUHJvbWlzZS5hbGwoY2F0YWxvZy5mb250Q2FjaGUpKSB7CiAgICAgIGlmICh0cmFuc2xhdGVkRm9udC5sb2FkZWROYW1lID09PSBpZCkgewogICAgICAgIHRyYW5zbGF0ZWRGb250LmZhbGxiYWNrKGhhbmRsZXIsIHBkZk1hbmFnZXIuZXZhbHVhdG9yT3B0aW9ucyk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICB9CiAgfQogIGFzeW5jIGNsZWFudXAobWFudWFsbHlUcmlnZ2VyZWQgPSBmYWxzZSkgewogICAgcmV0dXJuIHRoaXMuY2F0YWxvZyA/IHRoaXMuY2F0YWxvZy5jbGVhbnVwKG1hbnVhbGx5VHJpZ2dlcmVkKSA6IGNsZWFyR2xvYmFsQ2FjaGVzKCk7CiAgfQogIGFzeW5jICNjb2xsZWN0RmllbGRPYmplY3RzKG5hbWUsIHBhcmVudFJlZiwgZmllbGRSZWYsIHByb21pc2VzLCBhbm5vdGF0aW9uR2xvYmFscywgdmlzaXRlZFJlZnMsIG9ycGhhbkZpZWxkcykgewogICAgY29uc3QgewogICAgICB4cmVmCiAgICB9ID0gdGhpczsKICAgIGlmICghKGZpZWxkUmVmIGluc3RhbmNlb2YgUmVmKSB8fCB2aXNpdGVkUmVmcy5oYXMoZmllbGRSZWYpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHZpc2l0ZWRSZWZzLnB1dChmaWVsZFJlZik7CiAgICBjb25zdCBmaWVsZCA9IGF3YWl0IHhyZWYuZmV0Y2hBc3luYyhmaWVsZFJlZik7CiAgICBpZiAoIShmaWVsZCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCBzdWJ0eXBlID0gYXdhaXQgZmllbGQuZ2V0QXN5bmMoIlN1YnR5cGUiKTsKICAgIHN1YnR5cGUgPSBzdWJ0eXBlIGluc3RhbmNlb2YgTmFtZSA/IHN1YnR5cGUubmFtZSA6IG51bGw7CiAgICBzd2l0Y2ggKHN1YnR5cGUpIHsKICAgICAgY2FzZSAiTGluayI6CiAgICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKGZpZWxkLmhhcygiVCIpKSB7CiAgICAgIGNvbnN0IHBhcnROYW1lID0gc3RyaW5nVG9QREZTdHJpbmcoYXdhaXQgZmllbGQuZ2V0QXN5bmMoIlQiKSk7CiAgICAgIG5hbWUgPSBuYW1lID09PSAiIiA/IHBhcnROYW1lIDogYCR7bmFtZX0uJHtwYXJ0TmFtZX1gOwogICAgfSBlbHNlIHsKICAgICAgbGV0IG9iaiA9IGZpZWxkOwogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgIG9iaiA9IG9iai5nZXRSYXcoIlBhcmVudCIpIHx8IHBhcmVudFJlZjsKICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICBpZiAodmlzaXRlZFJlZnMuaGFzKG9iaikpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBvYmogPSBhd2FpdCB4cmVmLmZldGNoQXN5bmMob2JqKTsKICAgICAgICB9CiAgICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAob2JqLmhhcygiVCIpKSB7CiAgICAgICAgICBjb25zdCBwYXJ0TmFtZSA9IHN0cmluZ1RvUERGU3RyaW5nKGF3YWl0IG9iai5nZXRBc3luYygiVCIpKTsKICAgICAgICAgIG5hbWUgPSBuYW1lID09PSAiIiA/IHBhcnROYW1lIDogYCR7bmFtZX0uJHtwYXJ0TmFtZX1gOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAocGFyZW50UmVmICYmICFmaWVsZC5oYXMoIlBhcmVudCIpICYmIGlzTmFtZShmaWVsZC5nZXQoIlN1YnR5cGUiKSwgIldpZGdldCIpKSB7CiAgICAgIG9ycGhhbkZpZWxkcy5wdXQoZmllbGRSZWYsIHBhcmVudFJlZik7CiAgICB9CiAgICBpZiAoIXByb21pc2VzLmhhcyhuYW1lKSkgewogICAgICBwcm9taXNlcy5zZXQobmFtZSwgW10pOwogICAgfQogICAgcHJvbWlzZXMuZ2V0KG5hbWUpLnB1c2goQW5ub3RhdGlvbkZhY3RvcnkuY3JlYXRlKHhyZWYsIGZpZWxkUmVmLCBhbm5vdGF0aW9uR2xvYmFscywgbnVsbCwgdHJ1ZSwgb3JwaGFuRmllbGRzLCBudWxsLCBudWxsKS50aGVuKGFubm90YXRpb24gPT4gYW5ub3RhdGlvbj8uZ2V0RmllbGRPYmplY3QoKSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICB3YXJuKGAjY29sbGVjdEZpZWxkT2JqZWN0czogIiR7cmVhc29ufSIuYCk7CiAgICAgIHJldHVybiBudWxsOwogICAgfSkpOwogICAgaWYgKCFmaWVsZC5oYXMoIktpZHMiKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBraWRzID0gYXdhaXQgZmllbGQuZ2V0QXN5bmMoIktpZHMiKTsKICAgIGlmIChBcnJheS5pc0FycmF5KGtpZHMpKSB7CiAgICAgIGZvciAoY29uc3Qga2lkIG9mIGtpZHMpIHsKICAgICAgICBhd2FpdCB0aGlzLiNjb2xsZWN0RmllbGRPYmplY3RzKG5hbWUsIGZpZWxkUmVmLCBraWQsIHByb21pc2VzLCBhbm5vdGF0aW9uR2xvYmFscywgdmlzaXRlZFJlZnMsIG9ycGhhbkZpZWxkcyk7CiAgICAgIH0KICAgIH0KICB9CiAgZ2V0IGZpZWxkT2JqZWN0cygpIHsKICAgIGNvbnN0IHByb21pc2UgPSB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlRG9jKCJmb3JtSW5mbyIpLnRoZW4oYXN5bmMgZm9ybUluZm8gPT4gewogICAgICBpZiAoIWZvcm1JbmZvLmhhc0ZpZWxkcykgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IGFubm90YXRpb25HbG9iYWxzID0gYXdhaXQgdGhpcy5hbm5vdGF0aW9uR2xvYmFsczsKICAgICAgaWYgKCFhbm5vdGF0aW9uR2xvYmFscykgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IHsKICAgICAgICBhY3JvRm9ybQogICAgICB9ID0gYW5ub3RhdGlvbkdsb2JhbHM7CiAgICAgIGNvbnN0IHZpc2l0ZWRSZWZzID0gbmV3IFJlZlNldCgpOwogICAgICBjb25zdCBhbGxGaWVsZHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBjb25zdCBmaWVsZFByb21pc2VzID0gbmV3IE1hcCgpOwogICAgICBjb25zdCBvcnBoYW5GaWVsZHMgPSBuZXcgUmVmU2V0Q2FjaGUoKTsKICAgICAgZm9yIChjb25zdCBmaWVsZFJlZiBvZiBhY3JvRm9ybS5nZXQoIkZpZWxkcyIpKSB7CiAgICAgICAgYXdhaXQgdGhpcy4jY29sbGVjdEZpZWxkT2JqZWN0cygiIiwgbnVsbCwgZmllbGRSZWYsIGZpZWxkUHJvbWlzZXMsIGFubm90YXRpb25HbG9iYWxzLCB2aXNpdGVkUmVmcywgb3JwaGFuRmllbGRzKTsKICAgICAgfQogICAgICBjb25zdCBhbGxQcm9taXNlcyA9IFtdOwogICAgICBmb3IgKGNvbnN0IFtuYW1lLCBwcm9taXNlc10gb2YgZmllbGRQcm9taXNlcykgewogICAgICAgIGFsbFByb21pc2VzLnB1c2goUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oZmllbGRzID0+IHsKICAgICAgICAgIGZpZWxkcyA9IGZpZWxkcy5maWx0ZXIoZmllbGQgPT4gISFmaWVsZCk7CiAgICAgICAgICBpZiAoZmllbGRzLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgYWxsRmllbGRzW25hbWVdID0gZmllbGRzOwogICAgICAgICAgfQogICAgICAgIH0pKTsKICAgICAgfQogICAgICBhd2FpdCBQcm9taXNlLmFsbChhbGxQcm9taXNlcyk7CiAgICAgIHJldHVybiB7CiAgICAgICAgYWxsRmllbGRzOiBvYmplY3RTaXplKGFsbEZpZWxkcykgPiAwID8gYWxsRmllbGRzIDogbnVsbCwKICAgICAgICBvcnBoYW5GaWVsZHMKICAgICAgfTsKICAgIH0pOwogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiZmllbGRPYmplY3RzIiwgcHJvbWlzZSk7CiAgfQogIGdldCBoYXNKU0FjdGlvbnMoKSB7CiAgICBjb25zdCBwcm9taXNlID0gdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZURvYygiX3BhcnNlSGFzSlNBY3Rpb25zIik7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJoYXNKU0FjdGlvbnMiLCBwcm9taXNlKTsKICB9CiAgYXN5bmMgX3BhcnNlSGFzSlNBY3Rpb25zKCkgewogICAgY29uc3QgW2NhdGFsb2dKc0FjdGlvbnMsIGZpZWxkT2JqZWN0c10gPSBhd2FpdCBQcm9taXNlLmFsbChbdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImpzQWN0aW9ucyIpLCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlRG9jKCJmaWVsZE9iamVjdHMiKV0pOwogICAgaWYgKGNhdGFsb2dKc0FjdGlvbnMpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBpZiAoZmllbGRPYmplY3RzPy5hbGxGaWVsZHMpIHsKICAgICAgcmV0dXJuIE9iamVjdC52YWx1ZXMoZmllbGRPYmplY3RzLmFsbEZpZWxkcykuc29tZShmaWVsZE9iamVjdCA9PiBmaWVsZE9iamVjdC5zb21lKG9iamVjdCA9PiBvYmplY3QuYWN0aW9ucyAhPT0gbnVsbCkpOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICBnZXQgY2FsY3VsYXRpb25PcmRlcklkcygpIHsKICAgIGNvbnN0IGNhbGN1bGF0aW9uT3JkZXIgPSB0aGlzLmNhdGFsb2cuYWNyb0Zvcm0/LmdldCgiQ08iKTsKICAgIGlmICghQXJyYXkuaXNBcnJheShjYWxjdWxhdGlvbk9yZGVyKSB8fCBjYWxjdWxhdGlvbk9yZGVyLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gc2hhZG93KHRoaXMsICJjYWxjdWxhdGlvbk9yZGVySWRzIiwgbnVsbCk7CiAgICB9CiAgICBjb25zdCBpZHMgPSBbXTsKICAgIGZvciAoY29uc3QgaWQgb2YgY2FsY3VsYXRpb25PcmRlcikgewogICAgICBpZiAoaWQgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICBpZHMucHVzaChpZC50b1N0cmluZygpKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiY2FsY3VsYXRpb25PcmRlcklkcyIsIGlkcy5sZW5ndGggPyBpZHMgOiBudWxsKTsKICB9CiAgZ2V0IGFubm90YXRpb25HbG9iYWxzKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiYW5ub3RhdGlvbkdsb2JhbHMiLCBBbm5vdGF0aW9uRmFjdG9yeS5jcmVhdGVHbG9iYWxzKHRoaXMucGRmTWFuYWdlcikpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvcGRmX21hbmFnZXIuanMKCgoKCgoKCgoKCgpmdW5jdGlvbiBwYXJzZURvY0Jhc2VVcmwodXJsKSB7CiAgaWYgKHVybCkgewogICAgY29uc3QgYWJzb2x1dGVVcmwgPSBjcmVhdGVWYWxpZEFic29sdXRlVXJsKHVybCk7CiAgICBpZiAoYWJzb2x1dGVVcmwpIHsKICAgICAgcmV0dXJuIGFic29sdXRlVXJsLmhyZWY7CiAgICB9CiAgICB3YXJuKGBJbnZhbGlkIGFic29sdXRlIGRvY0Jhc2VVcmw6ICIke3VybH0iLmApOwogIH0KICByZXR1cm4gbnVsbDsKfQpjbGFzcyBCYXNlUGRmTWFuYWdlciB7CiAgY29uc3RydWN0b3IoewogICAgZG9jQmFzZVVybCwKICAgIGRvY0lkLAogICAgZW5hYmxlWGZhLAogICAgZXZhbHVhdG9yT3B0aW9ucywKICAgIGhhbmRsZXIsCiAgICBwYXNzd29yZAogIH0pIHsKICAgIHRoaXMuX2RvY0Jhc2VVcmwgPSBwYXJzZURvY0Jhc2VVcmwoZG9jQmFzZVVybCk7CiAgICB0aGlzLl9kb2NJZCA9IGRvY0lkOwogICAgdGhpcy5fcGFzc3dvcmQgPSBwYXNzd29yZDsKICAgIHRoaXMuZW5hYmxlWGZhID0gZW5hYmxlWGZhOwogICAgZXZhbHVhdG9yT3B0aW9ucy5pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCAmJj0gRmVhdHVyZVRlc3QuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQ7CiAgICBldmFsdWF0b3JPcHRpb25zLmlzSW1hZ2VEZWNvZGVyU3VwcG9ydGVkICYmPSBGZWF0dXJlVGVzdC5pc0ltYWdlRGVjb2RlclN1cHBvcnRlZDsKICAgIHRoaXMuZXZhbHVhdG9yT3B0aW9ucyA9IE9iamVjdC5mcmVlemUoZXZhbHVhdG9yT3B0aW9ucyk7CiAgICBJbWFnZVJlc2l6ZXIuc2V0T3B0aW9ucyhldmFsdWF0b3JPcHRpb25zKTsKICAgIEpwZWdTdHJlYW0uc2V0T3B0aW9ucyhldmFsdWF0b3JPcHRpb25zKTsKICAgIE9wZXJhdG9yTGlzdC5zZXRPcHRpb25zKGV2YWx1YXRvck9wdGlvbnMpOwogICAgY29uc3Qgb3B0aW9ucyA9IHsKICAgICAgLi4uZXZhbHVhdG9yT3B0aW9ucywKICAgICAgaGFuZGxlcgogICAgfTsKICAgIEpweEltYWdlLnNldE9wdGlvbnMob3B0aW9ucyk7CiAgICBJY2NDb2xvclNwYWNlLnNldE9wdGlvbnMob3B0aW9ucyk7CiAgICBDbXlrSUNDQmFzZWRDUy5zZXRPcHRpb25zKG9wdGlvbnMpOwogICAgSkJpZzJXYXNtSW1hZ2Uuc2V0T3B0aW9ucyhvcHRpb25zKTsKICB9CiAgZ2V0IGRvY0lkKCkgewogICAgcmV0dXJuIHRoaXMuX2RvY0lkOwogIH0KICBnZXQgcGFzc3dvcmQoKSB7CiAgICByZXR1cm4gdGhpcy5fcGFzc3dvcmQ7CiAgfQogIGdldCBkb2NCYXNlVXJsKCkgewogICAgcmV0dXJuIHRoaXMuX2RvY0Jhc2VVcmw7CiAgfQogIGVuc3VyZURvYyhwcm9wLCBhcmdzKSB7CiAgICByZXR1cm4gdGhpcy5lbnN1cmUodGhpcy5wZGZEb2N1bWVudCwgcHJvcCwgYXJncyk7CiAgfQogIGVuc3VyZVhSZWYocHJvcCwgYXJncykgewogICAgcmV0dXJuIHRoaXMuZW5zdXJlKHRoaXMucGRmRG9jdW1lbnQueHJlZiwgcHJvcCwgYXJncyk7CiAgfQogIGVuc3VyZUNhdGFsb2cocHJvcCwgYXJncykgewogICAgcmV0dXJuIHRoaXMuZW5zdXJlKHRoaXMucGRmRG9jdW1lbnQuY2F0YWxvZywgcHJvcCwgYXJncyk7CiAgfQogIGdldFBhZ2UocGFnZUluZGV4KSB7CiAgICByZXR1cm4gdGhpcy5wZGZEb2N1bWVudC5nZXRQYWdlKHBhZ2VJbmRleCk7CiAgfQogIGZvbnRGYWxsYmFjayhpZCwgaGFuZGxlcikgewogICAgcmV0dXJuIHRoaXMucGRmRG9jdW1lbnQuZm9udEZhbGxiYWNrKGlkLCBoYW5kbGVyKTsKICB9CiAgY2xlYW51cChtYW51YWxseVRyaWdnZXJlZCA9IGZhbHNlKSB7CiAgICByZXR1cm4gdGhpcy5wZGZEb2N1bWVudC5jbGVhbnVwKG1hbnVhbGx5VHJpZ2dlcmVkKTsKICB9CiAgYXN5bmMgZW5zdXJlKG9iaiwgcHJvcCwgYXJncykgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgZW5zdXJlYCBjYWxsZWQiKTsKICB9CiAgcmVxdWVzdFJhbmdlKGJlZ2luLCBlbmQpIHsKICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYHJlcXVlc3RSYW5nZWAgY2FsbGVkIik7CiAgfQogIHJlcXVlc3RMb2FkZWRTdHJlYW0obm9GZXRjaCA9IGZhbHNlKSB7CiAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGByZXF1ZXN0TG9hZGVkU3RyZWFtYCBjYWxsZWQiKTsKICB9CiAgc2VuZFByb2dyZXNzaXZlRGF0YShjaHVuaykgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgc2VuZFByb2dyZXNzaXZlRGF0YWAgY2FsbGVkIik7CiAgfQogIHVwZGF0ZVBhc3N3b3JkKHBhc3N3b3JkKSB7CiAgICB0aGlzLl9wYXNzd29yZCA9IHBhc3N3b3JkOwogIH0KICB0ZXJtaW5hdGUocmVhc29uKSB7CiAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGB0ZXJtaW5hdGVgIGNhbGxlZCIpOwogIH0KfQpjbGFzcyBMb2NhbFBkZk1hbmFnZXIgZXh0ZW5kcyBCYXNlUGRmTWFuYWdlciB7CiAgY29uc3RydWN0b3IoYXJncykgewogICAgc3VwZXIoYXJncyk7CiAgICBjb25zdCBzdHJlYW0gPSBuZXcgU3RyZWFtKGFyZ3Muc291cmNlKTsKICAgIHRoaXMucGRmRG9jdW1lbnQgPSBuZXcgUERGRG9jdW1lbnQodGhpcywgc3RyZWFtKTsKICAgIHRoaXMuX2xvYWRlZFN0cmVhbVByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoc3RyZWFtKTsKICB9CiAgYXN5bmMgZW5zdXJlKG9iaiwgcHJvcCwgYXJncykgewogICAgY29uc3QgdmFsdWUgPSBvYmpbcHJvcF07CiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAiZnVuY3Rpb24iKSB7CiAgICAgIHJldHVybiB2YWx1ZS5hcHBseShvYmosIGFyZ3MpOwogICAgfQogICAgcmV0dXJuIHZhbHVlOwogIH0KICByZXF1ZXN0UmFuZ2UoYmVnaW4sIGVuZCkgewogICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpOwogIH0KICByZXF1ZXN0TG9hZGVkU3RyZWFtKG5vRmV0Y2ggPSBmYWxzZSkgewogICAgcmV0dXJuIHRoaXMuX2xvYWRlZFN0cmVhbVByb21pc2U7CiAgfQogIHRlcm1pbmF0ZShyZWFzb24pIHt9Cn0KY2xhc3MgTmV0d29ya1BkZk1hbmFnZXIgZXh0ZW5kcyBCYXNlUGRmTWFuYWdlciB7CiAgY29uc3RydWN0b3IoYXJncykgewogICAgc3VwZXIoYXJncyk7CiAgICB0aGlzLnN0cmVhbU1hbmFnZXIgPSBuZXcgQ2h1bmtlZFN0cmVhbU1hbmFnZXIoYXJncy5zb3VyY2UsIHsKICAgICAgbXNnSGFuZGxlcjogYXJncy5oYW5kbGVyLAogICAgICBsZW5ndGg6IGFyZ3MubGVuZ3RoLAogICAgICBkaXNhYmxlQXV0b0ZldGNoOiBhcmdzLmRpc2FibGVBdXRvRmV0Y2gsCiAgICAgIHJhbmdlQ2h1bmtTaXplOiBhcmdzLnJhbmdlQ2h1bmtTaXplCiAgICB9KTsKICAgIHRoaXMucGRmRG9jdW1lbnQgPSBuZXcgUERGRG9jdW1lbnQodGhpcywgdGhpcy5zdHJlYW1NYW5hZ2VyLmdldFN0cmVhbSgpKTsKICB9CiAgYXN5bmMgZW5zdXJlKG9iaiwgcHJvcCwgYXJncykgewogICAgdHJ5IHsKICAgICAgY29uc3QgdmFsdWUgPSBvYmpbcHJvcF07CiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICByZXR1cm4gdmFsdWUuYXBwbHkob2JqLCBhcmdzKTsKICAgICAgfQogICAgICByZXR1cm4gdmFsdWU7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoIShleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSkgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIGF3YWl0IHRoaXMucmVxdWVzdFJhbmdlKGV4LmJlZ2luLCBleC5lbmQpOwogICAgICByZXR1cm4gdGhpcy5lbnN1cmUob2JqLCBwcm9wLCBhcmdzKTsKICAgIH0KICB9CiAgcmVxdWVzdFJhbmdlKGJlZ2luLCBlbmQpIHsKICAgIHJldHVybiB0aGlzLnN0cmVhbU1hbmFnZXIucmVxdWVzdFJhbmdlKGJlZ2luLCBlbmQpOwogIH0KICByZXF1ZXN0TG9hZGVkU3RyZWFtKG5vRmV0Y2ggPSBmYWxzZSkgewogICAgcmV0dXJuIHRoaXMuc3RyZWFtTWFuYWdlci5yZXF1ZXN0QWxsQ2h1bmtzKG5vRmV0Y2gpOwogIH0KICBzZW5kUHJvZ3Jlc3NpdmVEYXRhKGNodW5rKSB7CiAgICB0aGlzLnN0cmVhbU1hbmFnZXIub25SZWNlaXZlRGF0YSh7CiAgICAgIGNodW5rCiAgICB9KTsKICB9CiAgdGVybWluYXRlKHJlYXNvbikgewogICAgdGhpcy5zdHJlYW1NYW5hZ2VyLmFib3J0KHJlYXNvbik7CiAgfQp9Cgo7Ly8gLi9zcmMvc2hhcmVkL21lc3NhZ2VfaGFuZGxlci5qcwoKY29uc3QgQ2FsbGJhY2tLaW5kID0gewogIERBVEE6IDEsCiAgRVJST1I6IDIKfTsKY29uc3QgU3RyZWFtS2luZCA9IHsKICBDQU5DRUw6IDEsCiAgQ0FOQ0VMX0NPTVBMRVRFOiAyLAogIENMT1NFOiAzLAogIEVOUVVFVUU6IDQsCiAgRVJST1I6IDUsCiAgUFVMTDogNiwKICBQVUxMX0NPTVBMRVRFOiA3LAogIFNUQVJUX0NPTVBMRVRFOiA4Cn07CmZ1bmN0aW9uIG9uRm4oKSB7fQpmdW5jdGlvbiB3cmFwUmVhc29uKGV4KSB7CiAgaWYgKGV4IGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24gfHwgZXggaW5zdGFuY2VvZiBJbnZhbGlkUERGRXhjZXB0aW9uIHx8IGV4IGluc3RhbmNlb2YgUGFzc3dvcmRFeGNlcHRpb24gfHwgZXggaW5zdGFuY2VvZiBSZXNwb25zZUV4Y2VwdGlvbiB8fCBleCBpbnN0YW5jZW9mIFVua25vd25FcnJvckV4Y2VwdGlvbikgewogICAgcmV0dXJuIGV4OwogIH0KICBpZiAoIShleCBpbnN0YW5jZW9mIEVycm9yIHx8IHR5cGVvZiBleCA9PT0gIm9iamVjdCIgJiYgZXggIT09IG51bGwpKSB7CiAgICB1bnJlYWNoYWJsZSgnd3JhcFJlYXNvbjogRXhwZWN0ZWQgInJlYXNvbiIgdG8gYmUgYSAocG9zc2libHkgY2xvbmVkKSBFcnJvci4nKTsKICB9CiAgc3dpdGNoIChleC5uYW1lKSB7CiAgICBjYXNlICJBYm9ydEV4Y2VwdGlvbiI6CiAgICAgIHJldHVybiBuZXcgQWJvcnRFeGNlcHRpb24oZXgubWVzc2FnZSk7CiAgICBjYXNlICJJbnZhbGlkUERGRXhjZXB0aW9uIjoKICAgICAgcmV0dXJuIG5ldyBJbnZhbGlkUERGRXhjZXB0aW9uKGV4Lm1lc3NhZ2UpOwogICAgY2FzZSAiUGFzc3dvcmRFeGNlcHRpb24iOgogICAgICByZXR1cm4gbmV3IFBhc3N3b3JkRXhjZXB0aW9uKGV4Lm1lc3NhZ2UsIGV4LmNvZGUpOwogICAgY2FzZSAiUmVzcG9uc2VFeGNlcHRpb24iOgogICAgICByZXR1cm4gbmV3IFJlc3BvbnNlRXhjZXB0aW9uKGV4Lm1lc3NhZ2UsIGV4LnN0YXR1cywgZXgubWlzc2luZyk7CiAgICBjYXNlICJVbmtub3duRXJyb3JFeGNlcHRpb24iOgogICAgICByZXR1cm4gbmV3IFVua25vd25FcnJvckV4Y2VwdGlvbihleC5tZXNzYWdlLCBleC5kZXRhaWxzKTsKICB9CiAgcmV0dXJuIG5ldyBVbmtub3duRXJyb3JFeGNlcHRpb24oZXgubWVzc2FnZSwgZXgudG9TdHJpbmcoKSk7Cn0KY2xhc3MgTWVzc2FnZUhhbmRsZXIgewogICNtZXNzYWdlQUMgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7CiAgY29uc3RydWN0b3Ioc291cmNlTmFtZSwgdGFyZ2V0TmFtZSwgY29tT2JqKSB7CiAgICB0aGlzLnNvdXJjZU5hbWUgPSBzb3VyY2VOYW1lOwogICAgdGhpcy50YXJnZXROYW1lID0gdGFyZ2V0TmFtZTsKICAgIHRoaXMuY29tT2JqID0gY29tT2JqOwogICAgdGhpcy5jYWxsYmFja0lkID0gMTsKICAgIHRoaXMuc3RyZWFtSWQgPSAxOwogICAgdGhpcy5zdHJlYW1TaW5rcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB0aGlzLnN0cmVhbUNvbnRyb2xsZXJzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHRoaXMuY2FsbGJhY2tDYXBhYmlsaXRpZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgdGhpcy5hY3Rpb25IYW5kbGVyID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGNvbU9iai5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwgdGhpcy4jb25NZXNzYWdlLmJpbmQodGhpcyksIHsKICAgICAgc2lnbmFsOiB0aGlzLiNtZXNzYWdlQUMuc2lnbmFsCiAgICB9KTsKICB9CiAgI29uTWVzc2FnZSh7CiAgICBkYXRhCiAgfSkgewogICAgaWYgKGRhdGEudGFyZ2V0TmFtZSAhPT0gdGhpcy5zb3VyY2VOYW1lKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChkYXRhLnN0cmVhbSkgewogICAgICB0aGlzLiNwcm9jZXNzU3RyZWFtTWVzc2FnZShkYXRhKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKGRhdGEuY2FsbGJhY2spIHsKICAgICAgY29uc3QgY2FsbGJhY2tJZCA9IGRhdGEuY2FsbGJhY2tJZDsKICAgICAgY29uc3QgY2FwYWJpbGl0eSA9IHRoaXMuY2FsbGJhY2tDYXBhYmlsaXRpZXNbY2FsbGJhY2tJZF07CiAgICAgIGlmICghY2FwYWJpbGl0eSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlc29sdmUgY2FsbGJhY2sgJHtjYWxsYmFja0lkfWApOwogICAgICB9CiAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzW2NhbGxiYWNrSWRdOwogICAgICBpZiAoZGF0YS5jYWxsYmFjayA9PT0gQ2FsbGJhY2tLaW5kLkRBVEEpIHsKICAgICAgICBjYXBhYmlsaXR5LnJlc29sdmUoZGF0YS5kYXRhKTsKICAgICAgfSBlbHNlIGlmIChkYXRhLmNhbGxiYWNrID09PSBDYWxsYmFja0tpbmQuRVJST1IpIHsKICAgICAgICBjYXBhYmlsaXR5LnJlamVjdCh3cmFwUmVhc29uKGRhdGEucmVhc29uKSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJVbmV4cGVjdGVkIGNhbGxiYWNrIGNhc2UiKTsKICAgICAgfQogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBhY3Rpb24gPSB0aGlzLmFjdGlvbkhhbmRsZXJbZGF0YS5hY3Rpb25dOwogICAgaWYgKCFhY3Rpb24pIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGFjdGlvbiBmcm9tIHdvcmtlcjogJHtkYXRhLmFjdGlvbn1gKTsKICAgIH0KICAgIGlmIChkYXRhLmNhbGxiYWNrSWQpIHsKICAgICAgY29uc3Qgc291cmNlTmFtZSA9IHRoaXMuc291cmNlTmFtZSwKICAgICAgICB0YXJnZXROYW1lID0gZGF0YS5zb3VyY2VOYW1lLAogICAgICAgIGNvbU9iaiA9IHRoaXMuY29tT2JqOwogICAgICBQcm9taXNlLnRyeShhY3Rpb24sIGRhdGEuZGF0YSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7CiAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgY2FsbGJhY2s6IENhbGxiYWNrS2luZC5EQVRBLAogICAgICAgICAgY2FsbGJhY2tJZDogZGF0YS5jYWxsYmFja0lkLAogICAgICAgICAgZGF0YTogcmVzdWx0CiAgICAgICAgfSk7CiAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICBjYWxsYmFjazogQ2FsbGJhY2tLaW5kLkVSUk9SLAogICAgICAgICAgY2FsbGJhY2tJZDogZGF0YS5jYWxsYmFja0lkLAogICAgICAgICAgcmVhc29uOiB3cmFwUmVhc29uKHJlYXNvbikKICAgICAgICB9KTsKICAgICAgfSk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChkYXRhLnN0cmVhbUlkKSB7CiAgICAgIHRoaXMuI2NyZWF0ZVN0cmVhbVNpbmsoZGF0YSk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGFjdGlvbihkYXRhLmRhdGEpOwogIH0KICBvbihhY3Rpb25OYW1lLCBoYW5kbGVyKSB7CiAgICBjb25zdCBhaCA9IHRoaXMuYWN0aW9uSGFuZGxlcjsKICAgIGlmIChhaFthY3Rpb25OYW1lXSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZXJlIGlzIGFscmVhZHkgYW4gYWN0aW9uTmFtZSBjYWxsZWQgIiR7YWN0aW9uTmFtZX0iYCk7CiAgICB9CiAgICBhaFthY3Rpb25OYW1lXSA9IGhhbmRsZXI7CiAgfQogIHNlbmQoYWN0aW9uTmFtZSwgZGF0YSwgdHJhbnNmZXJzKSB7CiAgICB0aGlzLmNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgIHNvdXJjZU5hbWU6IHRoaXMuc291cmNlTmFtZSwKICAgICAgdGFyZ2V0TmFtZTogdGhpcy50YXJnZXROYW1lLAogICAgICBhY3Rpb246IGFjdGlvbk5hbWUsCiAgICAgIGRhdGEKICAgIH0sIHRyYW5zZmVycyk7CiAgfQogIHNlbmRXaXRoUHJvbWlzZShhY3Rpb25OYW1lLCBkYXRhLCB0cmFuc2ZlcnMpIHsKICAgIGNvbnN0IGNhbGxiYWNrSWQgPSB0aGlzLmNhbGxiYWNrSWQrKzsKICAgIGNvbnN0IGNhcGFiaWxpdHkgPSBQcm9taXNlLndpdGhSZXNvbHZlcnMoKTsKICAgIHRoaXMuY2FsbGJhY2tDYXBhYmlsaXRpZXNbY2FsbGJhY2tJZF0gPSBjYXBhYmlsaXR5OwogICAgdHJ5IHsKICAgICAgdGhpcy5jb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgIHNvdXJjZU5hbWU6IHRoaXMuc291cmNlTmFtZSwKICAgICAgICB0YXJnZXROYW1lOiB0aGlzLnRhcmdldE5hbWUsCiAgICAgICAgYWN0aW9uOiBhY3Rpb25OYW1lLAogICAgICAgIGNhbGxiYWNrSWQsCiAgICAgICAgZGF0YQogICAgICB9LCB0cmFuc2ZlcnMpOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgY2FwYWJpbGl0eS5yZWplY3QoZXgpOwogICAgfQogICAgcmV0dXJuIGNhcGFiaWxpdHkucHJvbWlzZTsKICB9CiAgc2VuZFdpdGhTdHJlYW0oYWN0aW9uTmFtZSwgZGF0YSwgcXVldWVpbmdTdHJhdGVneSwgdHJhbnNmZXJzKSB7CiAgICBjb25zdCBzdHJlYW1JZCA9IHRoaXMuc3RyZWFtSWQrKywKICAgICAgc291cmNlTmFtZSA9IHRoaXMuc291cmNlTmFtZSwKICAgICAgdGFyZ2V0TmFtZSA9IHRoaXMudGFyZ2V0TmFtZSwKICAgICAgY29tT2JqID0gdGhpcy5jb21PYmo7CiAgICByZXR1cm4gbmV3IFJlYWRhYmxlU3RyZWFtKHsKICAgICAgc3RhcnQ6IGNvbnRyb2xsZXIgPT4gewogICAgICAgIGNvbnN0IHN0YXJ0Q2FwYWJpbGl0eSA9IFByb21pc2Uud2l0aFJlc29sdmVycygpOwogICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdID0gewogICAgICAgICAgY29udHJvbGxlciwKICAgICAgICAgIHN0YXJ0Q2FsbDogc3RhcnRDYXBhYmlsaXR5LAogICAgICAgICAgcHVsbENhbGw6IG51bGwsCiAgICAgICAgICBjYW5jZWxDYWxsOiBudWxsLAogICAgICAgICAgaXNDbG9zZWQ6IGZhbHNlCiAgICAgICAgfTsKICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICBhY3Rpb246IGFjdGlvbk5hbWUsCiAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgIGRhdGEsCiAgICAgICAgICBkZXNpcmVkU2l6ZTogY29udHJvbGxlci5kZXNpcmVkU2l6ZQogICAgICAgIH0sIHRyYW5zZmVycyk7CiAgICAgICAgcmV0dXJuIHN0YXJ0Q2FwYWJpbGl0eS5wcm9taXNlOwogICAgICB9LAogICAgICBwdWxsOiBjb250cm9sbGVyID0+IHsKICAgICAgICBjb25zdCBwdWxsQ2FwYWJpbGl0eSA9IFByb21pc2Uud2l0aFJlc29sdmVycygpOwogICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdLnB1bGxDYWxsID0gcHVsbENhcGFiaWxpdHk7CiAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLlBVTEwsCiAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgIGRlc2lyZWRTaXplOiBjb250cm9sbGVyLmRlc2lyZWRTaXplCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIHB1bGxDYXBhYmlsaXR5LnByb21pc2U7CiAgICAgIH0sCiAgICAgIGNhbmNlbDogcmVhc29uID0+IHsKICAgICAgICBhc3NlcnQocmVhc29uIGluc3RhbmNlb2YgRXJyb3IsICJjYW5jZWwgbXVzdCBoYXZlIGEgdmFsaWQgcmVhc29uIik7CiAgICAgICAgY29uc3QgY2FuY2VsQ2FwYWJpbGl0eSA9IFByb21pc2Uud2l0aFJlc29sdmVycygpOwogICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdLmNhbmNlbENhbGwgPSBjYW5jZWxDYXBhYmlsaXR5OwogICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdLmlzQ2xvc2VkID0gdHJ1ZTsKICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuQ0FOQ0VMLAogICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICByZWFzb246IHdyYXBSZWFzb24ocmVhc29uKQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBjYW5jZWxDYXBhYmlsaXR5LnByb21pc2U7CiAgICAgIH0KICAgIH0sIHF1ZXVlaW5nU3RyYXRlZ3kpOwogIH0KICAjY3JlYXRlU3RyZWFtU2luayhkYXRhKSB7CiAgICBjb25zdCBzdHJlYW1JZCA9IGRhdGEuc3RyZWFtSWQsCiAgICAgIHNvdXJjZU5hbWUgPSB0aGlzLnNvdXJjZU5hbWUsCiAgICAgIHRhcmdldE5hbWUgPSBkYXRhLnNvdXJjZU5hbWUsCiAgICAgIGNvbU9iaiA9IHRoaXMuY29tT2JqOwogICAgY29uc3Qgc2VsZiA9IHRoaXMsCiAgICAgIGFjdGlvbiA9IHRoaXMuYWN0aW9uSGFuZGxlcltkYXRhLmFjdGlvbl07CiAgICBjb25zdCBzdHJlYW1TaW5rID0gewogICAgICBlbnF1ZXVlKGNodW5rLCBzaXplID0gMSwgdHJhbnNmZXJzKSB7CiAgICAgICAgaWYgKHRoaXMuaXNDYW5jZWxsZWQpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgY29uc3QgbGFzdERlc2lyZWRTaXplID0gdGhpcy5kZXNpcmVkU2l6ZTsKICAgICAgICB0aGlzLmRlc2lyZWRTaXplIC09IHNpemU7CiAgICAgICAgaWYgKGxhc3REZXNpcmVkU2l6ZSA+IDAgJiYgdGhpcy5kZXNpcmVkU2l6ZSA8PSAwKSB7CiAgICAgICAgICB0aGlzLnNpbmtDYXBhYmlsaXR5ID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7CiAgICAgICAgICB0aGlzLnJlYWR5ID0gdGhpcy5zaW5rQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgICAgIH0KICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuRU5RVUVVRSwKICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgY2h1bmsKICAgICAgICB9LCB0cmFuc2ZlcnMpOwogICAgICB9LAogICAgICBjbG9zZSgpIHsKICAgICAgICBpZiAodGhpcy5pc0NhbmNlbGxlZCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICB0aGlzLmlzQ2FuY2VsbGVkID0gdHJ1ZTsKICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuQ0xPU0UsCiAgICAgICAgICBzdHJlYW1JZAogICAgICAgIH0pOwogICAgICAgIGRlbGV0ZSBzZWxmLnN0cmVhbVNpbmtzW3N0cmVhbUlkXTsKICAgICAgfSwKICAgICAgZXJyb3IocmVhc29uKSB7CiAgICAgICAgYXNzZXJ0KHJlYXNvbiBpbnN0YW5jZW9mIEVycm9yLCAiZXJyb3IgbXVzdCBoYXZlIGEgdmFsaWQgcmVhc29uIik7CiAgICAgICAgaWYgKHRoaXMuaXNDYW5jZWxsZWQpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgdGhpcy5pc0NhbmNlbGxlZCA9IHRydWU7CiAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLkVSUk9SLAogICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICByZWFzb246IHdyYXBSZWFzb24ocmVhc29uKQogICAgICAgIH0pOwogICAgICB9LAogICAgICBzaW5rQ2FwYWJpbGl0eTogUHJvbWlzZS53aXRoUmVzb2x2ZXJzKCksCiAgICAgIG9uUHVsbDogbnVsbCwKICAgICAgb25DYW5jZWw6IG51bGwsCiAgICAgIGlzQ2FuY2VsbGVkOiBmYWxzZSwKICAgICAgZGVzaXJlZFNpemU6IGRhdGEuZGVzaXJlZFNpemUsCiAgICAgIHJlYWR5OiBudWxsCiAgICB9OwogICAgc3RyZWFtU2luay5zaW5rQ2FwYWJpbGl0eS5yZXNvbHZlKCk7CiAgICBzdHJlYW1TaW5rLnJlYWR5ID0gc3RyZWFtU2luay5zaW5rQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgdGhpcy5zdHJlYW1TaW5rc1tzdHJlYW1JZF0gPSBzdHJlYW1TaW5rOwogICAgUHJvbWlzZS50cnkoYWN0aW9uLCBkYXRhLmRhdGEsIHN0cmVhbVNpbmspLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuU1RBUlRfQ09NUExFVEUsCiAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgc3VjY2VzczogdHJ1ZQogICAgICB9KTsKICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLlNUQVJUX0NPTVBMRVRFLAogICAgICAgIHN0cmVhbUlkLAogICAgICAgIHJlYXNvbjogd3JhcFJlYXNvbihyZWFzb24pCiAgICAgIH0pOwogICAgfSk7CiAgfQogICNwcm9jZXNzU3RyZWFtTWVzc2FnZShkYXRhKSB7CiAgICBjb25zdCBzdHJlYW1JZCA9IGRhdGEuc3RyZWFtSWQsCiAgICAgIHNvdXJjZU5hbWUgPSB0aGlzLnNvdXJjZU5hbWUsCiAgICAgIHRhcmdldE5hbWUgPSBkYXRhLnNvdXJjZU5hbWUsCiAgICAgIGNvbU9iaiA9IHRoaXMuY29tT2JqOwogICAgY29uc3Qgc3RyZWFtQ29udHJvbGxlciA9IHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdLAogICAgICBzdHJlYW1TaW5rID0gdGhpcy5zdHJlYW1TaW5rc1tzdHJlYW1JZF07CiAgICBzd2l0Y2ggKGRhdGEuc3RyZWFtKSB7CiAgICAgIGNhc2UgU3RyZWFtS2luZC5TVEFSVF9DT01QTEVURToKICAgICAgICBpZiAoZGF0YS5zdWNjZXNzKSB7CiAgICAgICAgICBzdHJlYW1Db250cm9sbGVyLnN0YXJ0Q2FsbC5yZXNvbHZlKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN0cmVhbUNvbnRyb2xsZXIuc3RhcnRDYWxsLnJlamVjdCh3cmFwUmVhc29uKGRhdGEucmVhc29uKSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFN0cmVhbUtpbmQuUFVMTF9DT01QTEVURToKICAgICAgICBpZiAoZGF0YS5zdWNjZXNzKSB7CiAgICAgICAgICBzdHJlYW1Db250cm9sbGVyLnB1bGxDYWxsLnJlc29sdmUoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3RyZWFtQ29udHJvbGxlci5wdWxsQ2FsbC5yZWplY3Qod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSBTdHJlYW1LaW5kLlBVTEw6CiAgICAgICAgaWYgKCFzdHJlYW1TaW5rKSB7CiAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuUFVMTF9DT01QTEVURSwKICAgICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUKICAgICAgICAgIH0pOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmIChzdHJlYW1TaW5rLmRlc2lyZWRTaXplIDw9IDAgJiYgZGF0YS5kZXNpcmVkU2l6ZSA+IDApIHsKICAgICAgICAgIHN0cmVhbVNpbmsuc2lua0NhcGFiaWxpdHkucmVzb2x2ZSgpOwogICAgICAgIH0KICAgICAgICBzdHJlYW1TaW5rLmRlc2lyZWRTaXplID0gZGF0YS5kZXNpcmVkU2l6ZTsKICAgICAgICBQcm9taXNlLnRyeShzdHJlYW1TaW5rLm9uUHVsbCB8fCBvbkZuKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5QVUxMX0NPTVBMRVRFLAogICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgc3VjY2VzczogdHJ1ZQogICAgICAgICAgfSk7CiAgICAgICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLlBVTExfQ09NUExFVEUsCiAgICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgICByZWFzb246IHdyYXBSZWFzb24ocmVhc29uKQogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgU3RyZWFtS2luZC5FTlFVRVVFOgogICAgICAgIGFzc2VydChzdHJlYW1Db250cm9sbGVyLCAiZW5xdWV1ZSBzaG91bGQgaGF2ZSBzdHJlYW0gY29udHJvbGxlciIpOwogICAgICAgIGlmIChzdHJlYW1Db250cm9sbGVyLmlzQ2xvc2VkKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgc3RyZWFtQ29udHJvbGxlci5jb250cm9sbGVyLmVucXVldWUoZGF0YS5jaHVuayk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgU3RyZWFtS2luZC5DTE9TRToKICAgICAgICBhc3NlcnQoc3RyZWFtQ29udHJvbGxlciwgImNsb3NlIHNob3VsZCBoYXZlIHN0cmVhbSBjb250cm9sbGVyIik7CiAgICAgICAgaWYgKHN0cmVhbUNvbnRyb2xsZXIuaXNDbG9zZWQpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBzdHJlYW1Db250cm9sbGVyLmlzQ2xvc2VkID0gdHJ1ZTsKICAgICAgICBzdHJlYW1Db250cm9sbGVyLmNvbnRyb2xsZXIuY2xvc2UoKTsKICAgICAgICB0aGlzLiNkZWxldGVTdHJlYW1Db250cm9sbGVyKHN0cmVhbUNvbnRyb2xsZXIsIHN0cmVhbUlkKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBTdHJlYW1LaW5kLkVSUk9SOgogICAgICAgIGFzc2VydChzdHJlYW1Db250cm9sbGVyLCAiZXJyb3Igc2hvdWxkIGhhdmUgc3RyZWFtIGNvbnRyb2xsZXIiKTsKICAgICAgICBzdHJlYW1Db250cm9sbGVyLmNvbnRyb2xsZXIuZXJyb3Iod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpOwogICAgICAgIHRoaXMuI2RlbGV0ZVN0cmVhbUNvbnRyb2xsZXIoc3RyZWFtQ29udHJvbGxlciwgc3RyZWFtSWQpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFN0cmVhbUtpbmQuQ0FOQ0VMX0NPTVBMRVRFOgogICAgICAgIGlmIChkYXRhLnN1Y2Nlc3MpIHsKICAgICAgICAgIHN0cmVhbUNvbnRyb2xsZXIuY2FuY2VsQ2FsbC5yZXNvbHZlKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN0cmVhbUNvbnRyb2xsZXIuY2FuY2VsQ2FsbC5yZWplY3Qod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpOwogICAgICAgIH0KICAgICAgICB0aGlzLiNkZWxldGVTdHJlYW1Db250cm9sbGVyKHN0cmVhbUNvbnRyb2xsZXIsIHN0cmVhbUlkKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBTdHJlYW1LaW5kLkNBTkNFTDoKICAgICAgICBpZiAoIXN0cmVhbVNpbmspIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjb25zdCBkYXRhUmVhc29uID0gd3JhcFJlYXNvbihkYXRhLnJlYXNvbik7CiAgICAgICAgUHJvbWlzZS50cnkoc3RyZWFtU2luay5vbkNhbmNlbCB8fCBvbkZuLCBkYXRhUmVhc29uKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5DQU5DRUxfQ09NUExFVEUsCiAgICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgICBzdWNjZXNzOiB0cnVlCiAgICAgICAgICB9KTsKICAgICAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuQ0FOQ0VMX0NPTVBMRVRFLAogICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgcmVhc29uOiB3cmFwUmVhc29uKHJlYXNvbikKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICAgIHN0cmVhbVNpbmsuc2lua0NhcGFiaWxpdHkucmVqZWN0KGRhdGFSZWFzb24pOwogICAgICAgIHN0cmVhbVNpbmsuaXNDYW5jZWxsZWQgPSB0cnVlOwogICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbVNpbmtzW3N0cmVhbUlkXTsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlVuZXhwZWN0ZWQgc3RyZWFtIGNhc2UiKTsKICAgIH0KICB9CiAgYXN5bmMgI2RlbGV0ZVN0cmVhbUNvbnRyb2xsZXIoc3RyZWFtQ29udHJvbGxlciwgc3RyZWFtSWQpIHsKICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbc3RyZWFtQ29udHJvbGxlci5zdGFydENhbGw/LnByb21pc2UsIHN0cmVhbUNvbnRyb2xsZXIucHVsbENhbGw/LnByb21pc2UsIHN0cmVhbUNvbnRyb2xsZXIuY2FuY2VsQ2FsbD8ucHJvbWlzZV0pOwogICAgZGVsZXRlIHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdOwogIH0KICBkZXN0cm95KCkgewogICAgdGhpcy4jbWVzc2FnZUFDPy5hYm9ydCgpOwogICAgdGhpcy4jbWVzc2FnZUFDID0gbnVsbDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3dyaXRlci5qcwoKCgoKCgoKYXN5bmMgZnVuY3Rpb24gd3JpdGVPYmplY3QocmVmLCBvYmosIGJ1ZmZlciwgewogIGVuY3J5cHQgPSBudWxsLAogIGVuY3J5cHRSZWYgPSBudWxsCn0pIHsKICBjb25zdCB0cmFuc2Zvcm0gPSBlbmNyeXB0ICYmIGVuY3J5cHRSZWYgIT09IHJlZiA/IGVuY3J5cHQuY3JlYXRlQ2lwaGVyVHJhbnNmb3JtKHJlZi5udW0sIHJlZi5nZW4pIDogbnVsbDsKICBidWZmZXIucHVzaChgJHtyZWYubnVtfSAke3JlZi5nZW59IG9ialxuYCk7CiAgYXdhaXQgd3JpdGVWYWx1ZShvYmosIGJ1ZmZlciwgdHJhbnNmb3JtKTsKICBidWZmZXIucHVzaCgiXG5lbmRvYmpcbiIpOwp9CmFzeW5jIGZ1bmN0aW9uIHdyaXRlRGljdChkaWN0LCBidWZmZXIsIHRyYW5zZm9ybSkgewogIGJ1ZmZlci5wdXNoKCI8PCIpOwogIGZvciAoY29uc3QgW2tleSwgcmF3T2JqXSBvZiBkaWN0LmdldFJhd0VudHJpZXMoKSkgewogICAgYnVmZmVyLnB1c2goYCAvJHtlc2NhcGVQREZOYW1lKGtleSl9IGApOwogICAgYXdhaXQgd3JpdGVWYWx1ZShyYXdPYmosIGJ1ZmZlciwgdHJhbnNmb3JtKTsKICB9CiAgYnVmZmVyLnB1c2goIj4+Iik7Cn0KYXN5bmMgZnVuY3Rpb24gd3JpdGVTdHJlYW0oc3RyZWFtLCBidWZmZXIsIHRyYW5zZm9ybSkgewogIHN0cmVhbSA9IHN0cmVhbS5nZXRPcmlnaW5hbFN0cmVhbSgpOwogIHN0cmVhbS5yZXNldCgpOwogIGxldCBieXRlcyA9IHN0cmVhbS5nZXRCeXRlcygpOwogIGNvbnN0IHsKICAgIGRpY3QKICB9ID0gc3RyZWFtOwogIGNvbnN0IFtmaWx0ZXIsIHBhcmFtc10gPSBhd2FpdCBQcm9taXNlLmFsbChbZGljdC5nZXRBc3luYygiRmlsdGVyIiksIGRpY3QuZ2V0QXN5bmMoIkRlY29kZVBhcm1zIildKTsKICBjb25zdCBmaWx0ZXJaZXJvID0gQXJyYXkuaXNBcnJheShmaWx0ZXIpID8gYXdhaXQgZGljdC54cmVmLmZldGNoSWZSZWZBc3luYyhmaWx0ZXJbMF0pIDogZmlsdGVyOwogIGNvbnN0IGlzRmlsdGVyWmVyb0ZsYXRlRGVjb2RlID0gaXNOYW1lKGZpbHRlclplcm8sICJGbGF0ZURlY29kZSIpOwogIGNvbnN0IE1JTl9MRU5HVEhfRk9SX0NPTVBSRVNTSU5HID0gMjU2OwogIGlmIChieXRlcy5sZW5ndGggPj0gTUlOX0xFTkdUSF9GT1JfQ09NUFJFU1NJTkcgJiYgIWlzRmlsdGVyWmVyb0ZsYXRlRGVjb2RlKSB7CiAgICB0cnkgewogICAgICBjb25zdCBjcyA9IG5ldyBDb21wcmVzc2lvblN0cmVhbSgiZGVmbGF0ZSIpOwogICAgICBjb25zdCB3cml0ZXIgPSBjcy53cml0YWJsZS5nZXRXcml0ZXIoKTsKICAgICAgYXdhaXQgd3JpdGVyLnJlYWR5OwogICAgICB3cml0ZXIud3JpdGUoYnl0ZXMpLnRoZW4oYXN5bmMgKCkgPT4gewogICAgICAgIGF3YWl0IHdyaXRlci5yZWFkeTsKICAgICAgICBhd2FpdCB3cml0ZXIuY2xvc2UoKTsKICAgICAgfSkuY2F0Y2goKCkgPT4ge30pOwogICAgICBjb25zdCBidWYgPSBhd2FpdCBuZXcgUmVzcG9uc2UoY3MucmVhZGFibGUpLmFycmF5QnVmZmVyKCk7CiAgICAgIGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoYnVmKTsKICAgICAgbGV0IG5ld0ZpbHRlciwgbmV3UGFyYW1zOwogICAgICBpZiAoIWZpbHRlcikgewogICAgICAgIG5ld0ZpbHRlciA9IE5hbWUuZ2V0KCJGbGF0ZURlY29kZSIpOwogICAgICB9IGVsc2UgaWYgKCFpc0ZpbHRlclplcm9GbGF0ZURlY29kZSkgewogICAgICAgIG5ld0ZpbHRlciA9IEFycmF5LmlzQXJyYXkoZmlsdGVyKSA/IFtOYW1lLmdldCgiRmxhdGVEZWNvZGUiKSwgLi4uZmlsdGVyXSA6IFtOYW1lLmdldCgiRmxhdGVEZWNvZGUiKSwgZmlsdGVyXTsKICAgICAgICBpZiAocGFyYW1zKSB7CiAgICAgICAgICBuZXdQYXJhbXMgPSBBcnJheS5pc0FycmF5KHBhcmFtcykgPyBbbnVsbCwgLi4ucGFyYW1zXSA6IFtudWxsLCBwYXJhbXNdOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAobmV3RmlsdGVyKSB7CiAgICAgICAgZGljdC5zZXQoIkZpbHRlciIsIG5ld0ZpbHRlcik7CiAgICAgIH0KICAgICAgaWYgKG5ld1BhcmFtcykgewogICAgICAgIGRpY3Quc2V0KCJEZWNvZGVQYXJtcyIsIG5ld1BhcmFtcyk7CiAgICAgIH0KICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGluZm8oYHdyaXRlU3RyZWFtIC0gY2Fubm90IGNvbXByZXNzIGRhdGE6ICIke2V4fSIuYCk7CiAgICB9CiAgfQogIGxldCBzdHJpbmcgPSBieXRlc1RvU3RyaW5nKGJ5dGVzKTsKICBpZiAodHJhbnNmb3JtKSB7CiAgICBzdHJpbmcgPSB0cmFuc2Zvcm0uZW5jcnlwdFN0cmluZyhzdHJpbmcpOwogIH0KICBkaWN0LnNldCgiTGVuZ3RoIiwgc3RyaW5nLmxlbmd0aCk7CiAgYXdhaXQgd3JpdGVEaWN0KGRpY3QsIGJ1ZmZlciwgdHJhbnNmb3JtKTsKICBidWZmZXIucHVzaCgiIHN0cmVhbVxuIiwgc3RyaW5nLCAiXG5lbmRzdHJlYW0iKTsKfQphc3luYyBmdW5jdGlvbiB3cml0ZUFycmF5KGFycmF5LCBidWZmZXIsIHRyYW5zZm9ybSkgewogIGJ1ZmZlci5wdXNoKCJbIik7CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gYXJyYXkubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgYXdhaXQgd3JpdGVWYWx1ZShhcnJheVtpXSwgYnVmZmVyLCB0cmFuc2Zvcm0pOwogICAgaWYgKGkgPCBpaSAtIDEpIHsKICAgICAgYnVmZmVyLnB1c2goIiAiKTsKICAgIH0KICB9CiAgYnVmZmVyLnB1c2goIl0iKTsKfQphc3luYyBmdW5jdGlvbiB3cml0ZVZhbHVlKHZhbHVlLCBidWZmZXIsIHRyYW5zZm9ybSkgewogIGlmICh2YWx1ZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgIGJ1ZmZlci5wdXNoKGAvJHtlc2NhcGVQREZOYW1lKHZhbHVlLm5hbWUpfWApOwogIH0gZWxzZSBpZiAodmFsdWUgaW5zdGFuY2VvZiBSZWYpIHsKICAgIGJ1ZmZlci5wdXNoKGAke3ZhbHVlLm51bX0gJHt2YWx1ZS5nZW59IFJgKTsKICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpIHx8IEFycmF5QnVmZmVyLmlzVmlldyh2YWx1ZSkpIHsKICAgIGF3YWl0IHdyaXRlQXJyYXkodmFsdWUsIGJ1ZmZlciwgdHJhbnNmb3JtKTsKICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gInN0cmluZyIpIHsKICAgIGlmICh0cmFuc2Zvcm0pIHsKICAgICAgdmFsdWUgPSB0cmFuc2Zvcm0uZW5jcnlwdFN0cmluZyh2YWx1ZSk7CiAgICB9CiAgICBidWZmZXIucHVzaChgKCR7ZXNjYXBlU3RyaW5nKHZhbHVlKX0pYCk7CiAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICJudW1iZXIiKSB7CiAgICBidWZmZXIucHVzaCh2YWx1ZS50b1N0cmluZygpKTsKICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gImJvb2xlYW4iKSB7CiAgICBidWZmZXIucHVzaCh2YWx1ZS50b1N0cmluZygpKTsKICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGljdCkgewogICAgYXdhaXQgd3JpdGVEaWN0KHZhbHVlLCBidWZmZXIsIHRyYW5zZm9ybSk7CiAgfSBlbHNlIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgIGF3YWl0IHdyaXRlU3RyZWFtKHZhbHVlLCBidWZmZXIsIHRyYW5zZm9ybSk7CiAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gbnVsbCkgewogICAgYnVmZmVyLnB1c2goIm51bGwiKTsKICB9IGVsc2UgewogICAgd2FybihgVW5oYW5kbGVkIHZhbHVlIGluIHdyaXRlcjogJHt0eXBlb2YgdmFsdWV9LCBwbGVhc2UgZmlsZSBhIGJ1Zy5gKTsKICB9Cn0KZnVuY3Rpb24gd3JpdGVJbnQobnVtYmVyLCBzaXplLCBvZmZzZXQsIGJ1ZmZlcikgewogIGZvciAobGV0IGkgPSBzaXplICsgb2Zmc2V0IC0gMTsgaSA+IG9mZnNldCAtIDE7IGktLSkgewogICAgYnVmZmVyW2ldID0gbnVtYmVyICYgMHhmZjsKICAgIG51bWJlciA+Pj0gODsKICB9CiAgcmV0dXJuIG9mZnNldCArIHNpemU7Cn0KZnVuY3Rpb24gd3JpdGVTdHJpbmcoc3RyaW5nLCBvZmZzZXQsIGJ1ZmZlcikgewogIGNvbnN0IGlpID0gc3RyaW5nLmxlbmd0aDsKICBmb3IgKGxldCBpID0gMDsgaSA8IGlpOyBpKyspIHsKICAgIGJ1ZmZlcltvZmZzZXQgKyBpXSA9IHN0cmluZy5jaGFyQ29kZUF0KGkpICYgMHhmZjsKICB9CiAgcmV0dXJuIG9mZnNldCArIGlpOwp9CmZ1bmN0aW9uIGNvbXB1dGVNRDUoZmlsZXNpemUsIHhyZWZJbmZvKSB7CiAgY29uc3QgdGltZSA9IE1hdGguZmxvb3IoRGF0ZS5ub3coKSAvIDEwMDApOwogIGNvbnN0IGZpbGVuYW1lID0geHJlZkluZm8uZmlsZW5hbWUgfHwgIiI7CiAgY29uc3QgbWQ1QnVmZmVyID0gW3RpbWUudG9TdHJpbmcoKSwgZmlsZW5hbWUsIGZpbGVzaXplLnRvU3RyaW5nKCksIC4uLnhyZWZJbmZvLmluZm9NYXAudmFsdWVzKCldOwogIGNvbnN0IG1kNUJ1ZmZlckxlbiA9IE1hdGguc3VtUHJlY2lzZShtZDVCdWZmZXIubWFwKHN0ciA9PiBzdHIubGVuZ3RoKSk7CiAgY29uc3QgYXJyYXkgPSBuZXcgVWludDhBcnJheShtZDVCdWZmZXJMZW4pOwogIGxldCBvZmZzZXQgPSAwOwogIGZvciAoY29uc3Qgc3RyIG9mIG1kNUJ1ZmZlcikgewogICAgb2Zmc2V0ID0gd3JpdGVTdHJpbmcoc3RyLCBvZmZzZXQsIGFycmF5KTsKICB9CiAgcmV0dXJuIGJ5dGVzVG9TdHJpbmcoY2FsY3VsYXRlTUQ1KGFycmF5LCAwLCBhcnJheS5sZW5ndGgpKTsKfQpmdW5jdGlvbiB3cml0ZVhGQURhdGFGb3JBY3JvZm9ybShzdHIsIGNoYW5nZXMpIHsKICBjb25zdCB4bWwgPSBuZXcgU2ltcGxlWE1MUGFyc2VyKHsKICAgIGhhc0F0dHJpYnV0ZXM6IHRydWUKICB9KS5wYXJzZUZyb21TdHJpbmcoc3RyKTsKICBmb3IgKGNvbnN0IHsKICAgIHhmYQogIH0gb2YgY2hhbmdlcykgewogICAgaWYgKCF4ZmEpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIHBhdGgsCiAgICAgIHZhbHVlCiAgICB9ID0geGZhOwogICAgaWYgKCFwYXRoKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgY29uc3Qgbm9kZVBhdGggPSBwYXJzZVhGQVBhdGgocGF0aCk7CiAgICBsZXQgbm9kZSA9IHhtbC5kb2N1bWVudEVsZW1lbnQuc2VhcmNoTm9kZShub2RlUGF0aCwgMCk7CiAgICBpZiAoIW5vZGUgJiYgbm9kZVBhdGgubGVuZ3RoID4gMSkgewogICAgICBub2RlID0geG1sLmRvY3VtZW50RWxlbWVudC5zZWFyY2hOb2RlKFtub2RlUGF0aC5hdCgtMSldLCAwKTsKICAgIH0KICAgIGlmIChub2RlKSB7CiAgICAgIG5vZGUuY2hpbGROb2RlcyA9IEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUubWFwKHZhbCA9PiBuZXcgU2ltcGxlRE9NTm9kZSgidmFsdWUiLCB2YWwpKSA6IFtuZXcgU2ltcGxlRE9NTm9kZSgiI3RleHQiLCB2YWx1ZSldOwogICAgfSBlbHNlIHsKICAgICAgd2FybihgTm9kZSBub3QgZm91bmQgZm9yIHBhdGg6ICR7cGF0aH1gKTsKICAgIH0KICB9CiAgY29uc3QgYnVmZmVyID0gW107CiAgeG1sLmRvY3VtZW50RWxlbWVudC5kdW1wKGJ1ZmZlcik7CiAgcmV0dXJuIGJ1ZmZlci5qb2luKCIiKTsKfQphc3luYyBmdW5jdGlvbiB1cGRhdGVBY3JvZm9ybSh7CiAgeHJlZiwKICBhY3JvRm9ybSwKICBhY3JvRm9ybVJlZiwKICBoYXNYZmEsCiAgaGFzWGZhRGF0YXNldHNFbnRyeSwKICB4ZmFEYXRhc2V0c1JlZiwKICBuZWVkQXBwZWFyYW5jZXMsCiAgY2hhbmdlcwp9KSB7CiAgaWYgKGhhc1hmYSAmJiAhaGFzWGZhRGF0YXNldHNFbnRyeSAmJiAheGZhRGF0YXNldHNSZWYpIHsKICAgIHdhcm4oIlhGQSAtIENhbm5vdCBzYXZlIGl0Iik7CiAgfQogIGlmICghbmVlZEFwcGVhcmFuY2VzICYmICghaGFzWGZhIHx8ICF4ZmFEYXRhc2V0c1JlZiB8fCBoYXNYZmFEYXRhc2V0c0VudHJ5KSkgewogICAgcmV0dXJuOwogIH0KICBjb25zdCBkaWN0ID0gYWNyb0Zvcm0uY2xvbmUoKTsKICBpZiAoaGFzWGZhICYmICFoYXNYZmFEYXRhc2V0c0VudHJ5KSB7CiAgICBjb25zdCBuZXdYZmEgPSBhY3JvRm9ybS5nZXQoIlhGQSIpLnNsaWNlKCk7CiAgICBuZXdYZmEuc3BsaWNlKDIsIDAsICJkYXRhc2V0cyIpOwogICAgbmV3WGZhLnNwbGljZSgzLCAwLCB4ZmFEYXRhc2V0c1JlZik7CiAgICBkaWN0LnNldCgiWEZBIiwgbmV3WGZhKTsKICB9CiAgaWYgKG5lZWRBcHBlYXJhbmNlcykgewogICAgZGljdC5zZXQoIk5lZWRBcHBlYXJhbmNlcyIsIHRydWUpOwogIH0KICBjaGFuZ2VzLnB1dChhY3JvRm9ybVJlZiwgewogICAgZGF0YTogZGljdAogIH0pOwp9CmZ1bmN0aW9uIHVwZGF0ZVhGQSh7CiAgeGZhRGF0YSwKICB4ZmFEYXRhc2V0c1JlZiwKICBjaGFuZ2VzLAogIHhyZWYKfSkgewogIGlmICh4ZmFEYXRhID09PSBudWxsKSB7CiAgICBjb25zdCBkYXRhc2V0cyA9IHhyZWYuZmV0Y2hJZlJlZih4ZmFEYXRhc2V0c1JlZik7CiAgICB4ZmFEYXRhID0gd3JpdGVYRkFEYXRhRm9yQWNyb2Zvcm0oZGF0YXNldHMuZ2V0U3RyaW5nKCksIGNoYW5nZXMpOwogIH0KICBjb25zdCB4ZmFEYXRhU3RyZWFtID0gbmV3IFN0cmluZ1N0cmVhbSh4ZmFEYXRhKTsKICB4ZmFEYXRhU3RyZWFtLmRpY3QgPSBuZXcgRGljdCh4cmVmKTsKICB4ZmFEYXRhU3RyZWFtLmRpY3Quc2V0SWZOYW1lKCJUeXBlIiwgIkVtYmVkZGVkRmlsZSIpOwogIGNoYW5nZXMucHV0KHhmYURhdGFzZXRzUmVmLCB7CiAgICBkYXRhOiB4ZmFEYXRhU3RyZWFtCiAgfSk7Cn0KYXN5bmMgZnVuY3Rpb24gZ2V0WFJlZlRhYmxlKHhyZWZJbmZvLCBiYXNlT2Zmc2V0LCBuZXdSZWZzLCBuZXdYcmVmLCBidWZmZXIpIHsKICBidWZmZXIucHVzaCgieHJlZlxuIik7CiAgY29uc3QgaW5kZXhlcyA9IGdldEluZGV4ZXMobmV3UmVmcyk7CiAgbGV0IGluZGV4ZXNQb3NpdGlvbiA9IDA7CiAgZm9yIChjb25zdCB7CiAgICByZWYsCiAgICBkYXRhCiAgfSBvZiBuZXdSZWZzKSB7CiAgICBpZiAocmVmLm51bSA9PT0gaW5kZXhlc1tpbmRleGVzUG9zaXRpb25dKSB7CiAgICAgIGJ1ZmZlci5wdXNoKGAke2luZGV4ZXNbaW5kZXhlc1Bvc2l0aW9uXX0gJHtpbmRleGVzW2luZGV4ZXNQb3NpdGlvbiArIDFdfVxuYCk7CiAgICAgIGluZGV4ZXNQb3NpdGlvbiArPSAyOwogICAgfQogICAgaWYgKGRhdGEgIT09IG51bGwpIHsKICAgICAgYnVmZmVyLnB1c2goYCR7YmFzZU9mZnNldC50b1N0cmluZygpLnBhZFN0YXJ0KDEwLCAiMCIpfSAke01hdGgubWluKHJlZi5nZW4sIDB4ZmZmZikudG9TdHJpbmcoKS5wYWRTdGFydCg1LCAiMCIpfSBuXHJcbmApOwogICAgICBiYXNlT2Zmc2V0ICs9IGRhdGEubGVuZ3RoOwogICAgfSBlbHNlIHsKICAgICAgYnVmZmVyLnB1c2goYDAwMDAwMDAwMDAgJHtNYXRoLm1pbihyZWYuZ2VuICsgMSwgMHhmZmZmKS50b1N0cmluZygpLnBhZFN0YXJ0KDUsICIwIil9IGZcclxuYCk7CiAgICB9CiAgfQogIGNvbXB1dGVJRHMoYmFzZU9mZnNldCwgeHJlZkluZm8sIG5ld1hyZWYpOwogIGJ1ZmZlci5wdXNoKCJ0cmFpbGVyXG4iKTsKICBhd2FpdCB3cml0ZURpY3QobmV3WHJlZiwgYnVmZmVyLCBudWxsKTsKICBidWZmZXIucHVzaCgiXG5zdGFydHhyZWZcbiIsIGJhc2VPZmZzZXQudG9TdHJpbmcoKSwgIlxuJSVFT0ZcbiIpOwp9CmZ1bmN0aW9uIGdldEluZGV4ZXMobmV3UmVmcykgewogIGNvbnN0IGluZGV4ZXMgPSBbXTsKICBmb3IgKGNvbnN0IHsKICAgIHJlZgogIH0gb2YgbmV3UmVmcykgewogICAgaWYgKHJlZi5udW0gPT09IGluZGV4ZXMuYXQoLTIpICsgaW5kZXhlcy5hdCgtMSkpIHsKICAgICAgaW5kZXhlc1tpbmRleGVzLmxlbmd0aCAtIDFdICs9IDE7CiAgICB9IGVsc2UgewogICAgICBpbmRleGVzLnB1c2gocmVmLm51bSwgMSk7CiAgICB9CiAgfQogIHJldHVybiBpbmRleGVzOwp9CmFzeW5jIGZ1bmN0aW9uIGdldFhSZWZTdHJlYW1UYWJsZSh4cmVmSW5mbywgYmFzZU9mZnNldCwgbmV3UmVmcywgbmV3WHJlZiwgYnVmZmVyKSB7CiAgY29uc3QgeHJlZlRhYmxlRGF0YSA9IFtdOwogIGxldCBtYXhPZmZzZXQgPSAwOwogIGxldCBtYXhHZW4gPSAwOwogIGZvciAoY29uc3QgewogICAgcmVmLAogICAgZGF0YSwKICAgIG9ialN0cmVhbVJlZiwKICAgIGluZGV4CiAgfSBvZiBuZXdSZWZzKSB7CiAgICBsZXQgZ2VuOwogICAgbWF4T2Zmc2V0ID0gTWF0aC5tYXgobWF4T2Zmc2V0LCBiYXNlT2Zmc2V0KTsKICAgIGlmIChvYmpTdHJlYW1SZWYpIHsKICAgICAgZ2VuID0gaW5kZXg7CiAgICAgIHhyZWZUYWJsZURhdGEucHVzaChbMiwgb2JqU3RyZWFtUmVmLm51bSwgZ2VuXSk7CiAgICB9IGVsc2UgaWYgKGRhdGEgIT09IG51bGwpIHsKICAgICAgZ2VuID0gTWF0aC5taW4ocmVmLmdlbiwgMHhmZmZmKTsKICAgICAgeHJlZlRhYmxlRGF0YS5wdXNoKFsxLCBiYXNlT2Zmc2V0LCBnZW5dKTsKICAgICAgYmFzZU9mZnNldCArPSBkYXRhLmxlbmd0aDsKICAgIH0gZWxzZSB7CiAgICAgIGdlbiA9IE1hdGgubWluKHJlZi5nZW4gKyAxLCAweGZmZmYpOwogICAgICB4cmVmVGFibGVEYXRhLnB1c2goWzAsIDAsIGdlbl0pOwogICAgfQogICAgbWF4R2VuID0gTWF0aC5tYXgobWF4R2VuLCBnZW4pOwogIH0KICBuZXdYcmVmLnNldCgiSW5kZXgiLCBnZXRJbmRleGVzKG5ld1JlZnMpKTsKICBjb25zdCBvZmZzZXRTaXplID0gZ2V0U2l6ZUluQnl0ZXMobWF4T2Zmc2V0KTsKICBjb25zdCBtYXhHZW5TaXplID0gZ2V0U2l6ZUluQnl0ZXMobWF4R2VuKTsKICBjb25zdCBzaXplcyA9IFsxLCBvZmZzZXRTaXplLCBtYXhHZW5TaXplXTsKICBuZXdYcmVmLnNldCgiVyIsIHNpemVzKTsKICBjb21wdXRlSURzKGJhc2VPZmZzZXQsIHhyZWZJbmZvLCBuZXdYcmVmKTsKICBjb25zdCBzdHJ1Y3RTaXplID0gTWF0aC5zdW1QcmVjaXNlKHNpemVzKTsKICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4QXJyYXkoc3RydWN0U2l6ZSAqIHhyZWZUYWJsZURhdGEubGVuZ3RoKTsKICBjb25zdCBzdHJlYW0gPSBuZXcgU3RyZWFtKGRhdGEpOwogIHN0cmVhbS5kaWN0ID0gbmV3WHJlZjsKICBsZXQgb2Zmc2V0ID0gMDsKICBmb3IgKGNvbnN0IFt0eXBlLCBvYmpPZmZzZXQsIGdlbl0gb2YgeHJlZlRhYmxlRGF0YSkgewogICAgb2Zmc2V0ID0gd3JpdGVJbnQodHlwZSwgc2l6ZXNbMF0sIG9mZnNldCwgZGF0YSk7CiAgICBvZmZzZXQgPSB3cml0ZUludChvYmpPZmZzZXQsIHNpemVzWzFdLCBvZmZzZXQsIGRhdGEpOwogICAgb2Zmc2V0ID0gd3JpdGVJbnQoZ2VuLCBzaXplc1syXSwgb2Zmc2V0LCBkYXRhKTsKICB9CiAgYXdhaXQgd3JpdGVPYmplY3QoeHJlZkluZm8ubmV3UmVmLCBzdHJlYW0sIGJ1ZmZlciwge30pOwogIGJ1ZmZlci5wdXNoKCJzdGFydHhyZWZcbiIsIGJhc2VPZmZzZXQudG9TdHJpbmcoKSwgIlxuJSVFT0ZcbiIpOwp9CmZ1bmN0aW9uIGNvbXB1dGVJRHMoYmFzZU9mZnNldCwgeHJlZkluZm8sIG5ld1hyZWYpIHsKICBpZiAoQXJyYXkuaXNBcnJheSh4cmVmSW5mby5maWxlSWRzKSAmJiB4cmVmSW5mby5maWxlSWRzLmxlbmd0aCA+IDApIHsKICAgIGNvbnN0IG1kNSA9IGNvbXB1dGVNRDUoYmFzZU9mZnNldCwgeHJlZkluZm8pOwogICAgbmV3WHJlZi5zZXQoIklEIiwgW3hyZWZJbmZvLmZpbGVJZHNbMF0gfHwgbWQ1LCBtZDVdKTsKICB9Cn0KZnVuY3Rpb24gZ2V0VHJhaWxlckRpY3QoeHJlZkluZm8sIGNoYW5nZXMsIHVzZVhyZWZTdHJlYW0pIHsKICBjb25zdCBuZXdYcmVmID0gbmV3IERpY3QobnVsbCk7CiAgbmV3WHJlZi5zZXRJZkRlZmluZWQoIlByZXYiLCB4cmVmSW5mbz8uc3RhcnRYUmVmKTsKICBjb25zdCByZWZGb3JYcmVmVGFibGUgPSB4cmVmSW5mby5uZXdSZWY7CiAgaWYgKHVzZVhyZWZTdHJlYW0pIHsKICAgIGNoYW5nZXMucHV0KHJlZkZvclhyZWZUYWJsZSwgewogICAgICBkYXRhOiAiIgogICAgfSk7CiAgICBuZXdYcmVmLnNldCgiU2l6ZSIsIHJlZkZvclhyZWZUYWJsZS5udW0gKyAxKTsKICAgIG5ld1hyZWYuc2V0SWZOYW1lKCJUeXBlIiwgIlhSZWYiKTsKICB9IGVsc2UgewogICAgbmV3WHJlZi5zZXQoIlNpemUiLCByZWZGb3JYcmVmVGFibGUubnVtKTsKICB9CiAgbmV3WHJlZi5zZXRJZkRlZmluZWQoIlJvb3QiLCB4cmVmSW5mbz8ucm9vdFJlZik7CiAgbmV3WHJlZi5zZXRJZkRlZmluZWQoIkluZm8iLCB4cmVmSW5mbz8uaW5mb1JlZik7CiAgbmV3WHJlZi5zZXRJZkRlZmluZWQoIkVuY3J5cHQiLCB4cmVmSW5mbz8uZW5jcnlwdFJlZik7CiAgcmV0dXJuIG5ld1hyZWY7Cn0KYXN5bmMgZnVuY3Rpb24gd3JpdGVDaGFuZ2VzKGNoYW5nZXMsIHhyZWYsIGJ1ZmZlciA9IFtdKSB7CiAgY29uc3QgbmV3UmVmcyA9IFtdOwogIGZvciAoY29uc3QgW3JlZiwgewogICAgZGF0YSwKICAgIG9ialN0cmVhbVJlZiwKICAgIGluZGV4CiAgfV0gb2YgY2hhbmdlcy5pdGVtcygpKSB7CiAgICBpZiAob2JqU3RyZWFtUmVmKSB7CiAgICAgIG5ld1JlZnMucHVzaCh7CiAgICAgICAgcmVmLAogICAgICAgIGRhdGEsCiAgICAgICAgb2JqU3RyZWFtUmVmLAogICAgICAgIGluZGV4CiAgICAgIH0pOwogICAgICBjb250aW51ZTsKICAgIH0KICAgIGlmIChkYXRhID09PSBudWxsIHx8IHR5cGVvZiBkYXRhID09PSAic3RyaW5nIikgewogICAgICBuZXdSZWZzLnB1c2goewogICAgICAgIHJlZiwKICAgICAgICBkYXRhCiAgICAgIH0pOwogICAgICBjb250aW51ZTsKICAgIH0KICAgIGF3YWl0IHdyaXRlT2JqZWN0KHJlZiwgZGF0YSwgYnVmZmVyLCB4cmVmKTsKICAgIG5ld1JlZnMucHVzaCh7CiAgICAgIHJlZiwKICAgICAgZGF0YTogYnVmZmVyLmpvaW4oIiIpCiAgICB9KTsKICAgIGJ1ZmZlci5sZW5ndGggPSAwOwogIH0KICByZXR1cm4gbmV3UmVmcy5zb3J0KChhLCBiKSA9PiBhLnJlZi5udW0gLSBiLnJlZi5udW0pOwp9CmFzeW5jIGZ1bmN0aW9uIGluY3JlbWVudGFsVXBkYXRlKHsKICBvcmlnaW5hbERhdGEsCiAgeHJlZkluZm8sCiAgY2hhbmdlcywKICB4cmVmID0gbnVsbCwKICBoYXNYZmEgPSBmYWxzZSwKICB4ZmFEYXRhc2V0c1JlZiA9IG51bGwsCiAgaGFzWGZhRGF0YXNldHNFbnRyeSA9IGZhbHNlLAogIG5lZWRBcHBlYXJhbmNlcywKICBhY3JvRm9ybVJlZiA9IG51bGwsCiAgYWNyb0Zvcm0gPSBudWxsLAogIHhmYURhdGEgPSBudWxsLAogIHVzZVhyZWZTdHJlYW0gPSBmYWxzZQp9KSB7CiAgYXdhaXQgdXBkYXRlQWNyb2Zvcm0oewogICAgeHJlZiwKICAgIGFjcm9Gb3JtLAogICAgYWNyb0Zvcm1SZWYsCiAgICBoYXNYZmEsCiAgICBoYXNYZmFEYXRhc2V0c0VudHJ5LAogICAgeGZhRGF0YXNldHNSZWYsCiAgICBuZWVkQXBwZWFyYW5jZXMsCiAgICBjaGFuZ2VzCiAgfSk7CiAgaWYgKGhhc1hmYSkgewogICAgdXBkYXRlWEZBKHsKICAgICAgeGZhRGF0YSwKICAgICAgeGZhRGF0YXNldHNSZWYsCiAgICAgIGNoYW5nZXMsCiAgICAgIHhyZWYKICAgIH0pOwogIH0KICBjb25zdCBuZXdYcmVmID0gZ2V0VHJhaWxlckRpY3QoeHJlZkluZm8sIGNoYW5nZXMsIHVzZVhyZWZTdHJlYW0pOwogIGNvbnN0IGJ1ZmZlciA9IFtdOwogIGNvbnN0IG5ld1JlZnMgPSBhd2FpdCB3cml0ZUNoYW5nZXMoY2hhbmdlcywgeHJlZiwgYnVmZmVyKTsKICBsZXQgYmFzZU9mZnNldCA9IG9yaWdpbmFsRGF0YS5sZW5ndGg7CiAgY29uc3QgbGFzdEJ5dGUgPSBvcmlnaW5hbERhdGEuYXQoLTEpOwogIGlmIChsYXN0Qnl0ZSAhPT0gMHgwYSAmJiBsYXN0Qnl0ZSAhPT0gMHgwZCkgewogICAgYnVmZmVyLnB1c2goIlxuIik7CiAgICBiYXNlT2Zmc2V0ICs9IDE7CiAgfQogIGZvciAoY29uc3QgewogICAgZGF0YQogIH0gb2YgbmV3UmVmcykgewogICAgaWYgKGRhdGEgIT09IG51bGwpIHsKICAgICAgYnVmZmVyLnB1c2goZGF0YSk7CiAgICB9CiAgfQogIGF3YWl0ICh1c2VYcmVmU3RyZWFtID8gZ2V0WFJlZlN0cmVhbVRhYmxlKHhyZWZJbmZvLCBiYXNlT2Zmc2V0LCBuZXdSZWZzLCBuZXdYcmVmLCBidWZmZXIpIDogZ2V0WFJlZlRhYmxlKHhyZWZJbmZvLCBiYXNlT2Zmc2V0LCBuZXdSZWZzLCBuZXdYcmVmLCBidWZmZXIpKTsKICBjb25zdCB0b3RhbExlbmd0aCA9IG9yaWdpbmFsRGF0YS5sZW5ndGggKyBNYXRoLnN1bVByZWNpc2UoYnVmZmVyLm1hcChzdHIgPT4gc3RyLmxlbmd0aCkpOwogIGNvbnN0IGFycmF5ID0gbmV3IFVpbnQ4QXJyYXkodG90YWxMZW5ndGgpOwogIGFycmF5LnNldChvcmlnaW5hbERhdGEpOwogIGxldCBvZmZzZXQgPSBvcmlnaW5hbERhdGEubGVuZ3RoOwogIGZvciAoY29uc3Qgc3RyIG9mIGJ1ZmZlcikgewogICAgb2Zmc2V0ID0gd3JpdGVTdHJpbmcoc3RyLCBvZmZzZXQsIGFycmF5KTsKICB9CiAgcmV0dXJuIGFycmF5Owp9Cgo7Ly8gLi9zcmMvY29yZS9lZGl0b3IvcGRmX2VkaXRvci5qcwoKCgoKCgoKY29uc3QgTUFYX0xFQVZFU19QRVJfUEFHRVNfTk9ERSA9IDE2Owpjb25zdCBNQVhfSU5fTkFNRV9UUkVFX05PREUgPSA2NDsKY2xhc3MgUGFnZURhdGEgewogIGNvbnN0cnVjdG9yKHBhZ2UsIGRvY3VtZW50RGF0YSkgewogICAgdGhpcy5wYWdlID0gcGFnZTsKICAgIHRoaXMuZG9jdW1lbnREYXRhID0gZG9jdW1lbnREYXRhOwogICAgdGhpcy5hbm5vdGF0aW9ucyA9IG51bGw7CiAgICB0aGlzLnBvaW50aW5nTmFtZWREZXN0aW5hdGlvbnMgPSBudWxsOwogICAgZG9jdW1lbnREYXRhLnBhZ2VzTWFwLnB1dChwYWdlLnJlZiwgdGhpcyk7CiAgfQp9CmNsYXNzIERvY3VtZW50RGF0YSB7CiAgY29uc3RydWN0b3IoZG9jdW1lbnQpIHsKICAgIHRoaXMuZG9jdW1lbnQgPSBkb2N1bWVudDsKICAgIHRoaXMuZGVzdGluYXRpb25zID0gbnVsbDsKICAgIHRoaXMucGFnZUxhYmVscyA9IG51bGw7CiAgICB0aGlzLnBhZ2VzTWFwID0gbmV3IFJlZlNldENhY2hlKCk7CiAgICB0aGlzLm9sZFJlZk1hcHBpbmcgPSBuZXcgUmVmU2V0Q2FjaGUoKTsKICAgIHRoaXMuZGVkdXBOYW1lZERlc3RpbmF0aW9ucyA9IG5ldyBNYXAoKTsKICAgIHRoaXMudXNlZE5hbWVkRGVzdGluYXRpb25zID0gbmV3IFNldCgpOwogICAgdGhpcy5wb3N0cG9uZWRSZWZDb3BpZXMgPSBuZXcgUmVmU2V0Q2FjaGUoKTsKICAgIHRoaXMudXNlZFN0cnVjdFBhcmVudHMgPSBuZXcgU2V0KCk7CiAgICB0aGlzLm9sZFN0cnVjdFBhcmVudE1hcHBpbmcgPSBuZXcgTWFwKCk7CiAgICB0aGlzLnN0cnVjdFRyZWVSb290ID0gbnVsbDsKICAgIHRoaXMucGFyZW50VHJlZSA9IG51bGw7CiAgICB0aGlzLmlkVHJlZSA9IG51bGw7CiAgICB0aGlzLnJvbGVNYXAgPSBudWxsOwogICAgdGhpcy5jbGFzc01hcCA9IG51bGw7CiAgICB0aGlzLm5hbWVzcGFjZXMgPSBudWxsOwogICAgdGhpcy5zdHJ1Y3RUcmVlQUYgPSBudWxsOwogICAgdGhpcy5zdHJ1Y3RUcmVlUHJvbnVuY2lhdGlvbkxleGljb24gPSBbXTsKICB9Cn0KY2xhc3MgWFJlZldyYXBwZXIgewogIGNvbnN0cnVjdG9yKGVudHJpZXMpIHsKICAgIHRoaXMuZW50cmllcyA9IGVudHJpZXM7CiAgfQogIGZldGNoKHJlZikgewogICAgcmV0dXJuIHJlZiBpbnN0YW5jZW9mIFJlZiA/IHRoaXMuZW50cmllc1tyZWYubnVtXSA6IHJlZjsKICB9Cn0KY2xhc3MgUERGRWRpdG9yIHsKICBjb25zdHJ1Y3Rvcih7CiAgICB1c2VPYmplY3RTdHJlYW1zID0gdHJ1ZSwKICAgIHRpdGxlID0gIiIsCiAgICBhdXRob3IgPSAiIgogIH0gPSB7fSkgewogICAgdGhpcy5oYXNTaW5nbGVGaWxlID0gZmFsc2U7CiAgICB0aGlzLmN1cnJlbnREb2N1bWVudCA9IG51bGw7CiAgICB0aGlzLm9sZFBhZ2VzID0gW107CiAgICB0aGlzLm5ld1BhZ2VzID0gW107CiAgICB0aGlzLnhyZWYgPSBbbnVsbF07CiAgICB0aGlzLnhyZWZXcmFwcGVyID0gbmV3IFhSZWZXcmFwcGVyKHRoaXMueHJlZik7CiAgICB0aGlzLm5ld1JlZkNvdW50ID0gMTsKICAgIFt0aGlzLnJvb3RSZWYsIHRoaXMucm9vdERpY3RdID0gdGhpcy5uZXdEaWN0OwogICAgW3RoaXMuaW5mb1JlZiwgdGhpcy5pbmZvRGljdF0gPSB0aGlzLm5ld0RpY3Q7CiAgICBbdGhpcy5wYWdlc1JlZiwgdGhpcy5wYWdlc0RpY3RdID0gdGhpcy5uZXdEaWN0OwogICAgdGhpcy5uYW1lc0RpY3QgPSBudWxsOwogICAgdGhpcy51c2VPYmplY3RTdHJlYW1zID0gdXNlT2JqZWN0U3RyZWFtczsKICAgIHRoaXMub2JqU3RyZWFtUmVmcyA9IHVzZU9iamVjdFN0cmVhbXMgPyBuZXcgU2V0KCkgOiBudWxsOwogICAgdGhpcy52ZXJzaW9uID0gIjEuNyI7CiAgICB0aGlzLnRpdGxlID0gdGl0bGU7CiAgICB0aGlzLmF1dGhvciA9IGF1dGhvcjsKICAgIHRoaXMucGFnZUxhYmVscyA9IG51bGw7CiAgICB0aGlzLm5hbWVkRGVzdGluYXRpb25zID0gbmV3IE1hcCgpOwogICAgdGhpcy5wYXJlbnRUcmVlID0gbmV3IE1hcCgpOwogICAgdGhpcy5zdHJ1Y3RUcmVlS2lkcyA9IFtdOwogICAgdGhpcy5pZFRyZWUgPSBuZXcgTWFwKCk7CiAgICB0aGlzLmNsYXNzTWFwID0gbmV3IERpY3QoKTsKICAgIHRoaXMucm9sZU1hcCA9IG5ldyBEaWN0KCk7CiAgICB0aGlzLm5hbWVzcGFjZXMgPSBuZXcgTWFwKCk7CiAgICB0aGlzLnN0cnVjdFRyZWVBRiA9IFtdOwogICAgdGhpcy5zdHJ1Y3RUcmVlUHJvbnVuY2lhdGlvbkxleGljb24gPSBbXTsKICB9CiAgZ2V0IG5ld1JlZigpIHsKICAgIGNvbnN0IHJlZiA9IFJlZi5nZXQodGhpcy5uZXdSZWZDb3VudCsrLCAwKTsKICAgIHJldHVybiByZWY7CiAgfQogIGdldCBuZXdEaWN0KCkgewogICAgY29uc3QgcmVmID0gdGhpcy5uZXdSZWY7CiAgICBjb25zdCBkaWN0ID0gdGhpcy54cmVmW3JlZi5udW1dID0gbmV3IERpY3QoKTsKICAgIHJldHVybiBbcmVmLCBkaWN0XTsKICB9CiAgYXN5bmMgI2Nsb25lT2JqZWN0KG9iaiwgeHJlZikgewogICAgY29uc3QgcmVmID0gdGhpcy5uZXdSZWY7CiAgICB0aGlzLnhyZWZbcmVmLm51bV0gPSBhd2FpdCB0aGlzLiNjb2xsZWN0RGVwZW5kZW5jaWVzKG9iaiwgdHJ1ZSwgeHJlZik7CiAgICByZXR1cm4gcmVmOwogIH0KICBjbG9uZURpY3QoZGljdCkgewogICAgY29uc3QgbmV3RGljdCA9IGRpY3QuY2xvbmUoKTsKICAgIG5ld0RpY3QueHJlZiA9IHRoaXMueHJlZldyYXBwZXI7CiAgICByZXR1cm4gbmV3RGljdDsKICB9CiAgYXN5bmMgI2NvbGxlY3REZXBlbmRlbmNpZXMob2JqLCBtdXN0Q2xvbmUsIHhyZWYpIHsKICAgIGlmIChvYmogaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgY29uc3QgewogICAgICAgIGN1cnJlbnREb2N1bWVudDogewogICAgICAgICAgb2xkUmVmTWFwcGluZwogICAgICAgIH0KICAgICAgfSA9IHRoaXM7CiAgICAgIGxldCBuZXdSZWYgPSBvbGRSZWZNYXBwaW5nLmdldChvYmopOwogICAgICBpZiAobmV3UmVmKSB7CiAgICAgICAgcmV0dXJuIG5ld1JlZjsKICAgICAgfQogICAgICBjb25zdCBvbGRSZWYgPSBvYmo7CiAgICAgIG9iaiA9IGF3YWl0IHhyZWYuZmV0Y2hBc3luYyhvbGRSZWYpOwogICAgICBpZiAodHlwZW9mIG9iaiA9PT0gIm51bWJlciIpIHsKICAgICAgICByZXR1cm4gb2JqOwogICAgICB9CiAgICAgIG5ld1JlZiA9IHRoaXMubmV3UmVmOwogICAgICBvbGRSZWZNYXBwaW5nLnB1dChvbGRSZWYsIG5ld1JlZik7CiAgICAgIHRoaXMueHJlZltuZXdSZWYubnVtXSA9IGF3YWl0IHRoaXMuI2NvbGxlY3REZXBlbmRlbmNpZXMob2JqLCB0cnVlLCB4cmVmKTsKICAgICAgcmV0dXJuIG5ld1JlZjsKICAgIH0KICAgIGNvbnN0IHByb21pc2VzID0gW107CiAgICBjb25zdCB7CiAgICAgIGN1cnJlbnREb2N1bWVudDogewogICAgICAgIHBvc3Rwb25lZFJlZkNvcGllcwogICAgICB9CiAgICB9ID0gdGhpczsKICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHsKICAgICAgaWYgKG11c3RDbG9uZSkgewogICAgICAgIG9iaiA9IG9iai5zbGljZSgpOwogICAgICB9CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IG9iai5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3QgcG9zdHBvbmVkQWN0aW9ucyA9IHBvc3Rwb25lZFJlZkNvcGllcy5nZXQob2JqW2ldKTsKICAgICAgICBpZiAocG9zdHBvbmVkQWN0aW9ucykgewogICAgICAgICAgcG9zdHBvbmVkQWN0aW9ucy5wdXNoKHJlZiA9PiBvYmpbaV0gPSByZWYpOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIHByb21pc2VzLnB1c2godGhpcy4jY29sbGVjdERlcGVuZGVuY2llcyhvYmpbaV0sIHRydWUsIHhyZWYpLnRoZW4obmV3T2JqID0+IG9ialtpXSA9IG5ld09iaikpOwogICAgICB9CiAgICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTsKICAgICAgcmV0dXJuIG9iajsKICAgIH0KICAgIGxldCBkaWN0OwogICAgaWYgKG9iaiBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgKHsKICAgICAgICBkaWN0CiAgICAgIH0gPSBvYmogPSBvYmouZ2V0T3JpZ2luYWxTdHJlYW0oKS5jbG9uZSgpKTsKICAgICAgZGljdC54cmVmID0gdGhpcy54cmVmV3JhcHBlcjsKICAgIH0gZWxzZSBpZiAob2JqIGluc3RhbmNlb2YgRGljdCkgewogICAgICBpZiAobXVzdENsb25lKSB7CiAgICAgICAgb2JqID0gb2JqLmNsb25lKCk7CiAgICAgICAgb2JqLnhyZWYgPSB0aGlzLnhyZWZXcmFwcGVyOwogICAgICB9CiAgICAgIGRpY3QgPSBvYmo7CiAgICB9CiAgICBpZiAoZGljdCkgewogICAgICBmb3IgKGNvbnN0IFtrZXksIHJhd09ial0gb2YgZGljdC5nZXRSYXdFbnRyaWVzKCkpIHsKICAgICAgICBjb25zdCBwb3N0cG9uZWRBY3Rpb25zID0gcG9zdHBvbmVkUmVmQ29waWVzLmdldChyYXdPYmopOwogICAgICAgIGlmIChwb3N0cG9uZWRBY3Rpb25zKSB7CiAgICAgICAgICBwb3N0cG9uZWRBY3Rpb25zLnB1c2gocmVmID0+IGRpY3Quc2V0KGtleSwgcmVmKSk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLiNjb2xsZWN0RGVwZW5kZW5jaWVzKHJhd09iaiwgdHJ1ZSwgeHJlZikudGhlbihuZXdPYmogPT4gZGljdC5zZXQoa2V5LCBuZXdPYmopKSk7CiAgICAgIH0KICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpOwogICAgfQogICAgcmV0dXJuIG9iajsKICB9CiAgYXN5bmMgI2Nsb25lU3RydWN0VHJlZU5vZGUocGFyZW50U3RydWN0UmVmLCBub2RlLCB4cmVmLCByZW1vdmVkU3RydWN0RWxlbWVudHMsIGRlZHVwSURzLCBkZWR1cENsYXNzZXMsIGRlZHVwUm9sZXMsIHZpc2l0ZWQgPSBuZXcgUmVmU2V0KCkpIHsKICAgIGNvbnN0IHsKICAgICAgY3VycmVudERvY3VtZW50OiB7CiAgICAgICAgcGFnZXNNYXAsCiAgICAgICAgb2xkUmVmTWFwcGluZwogICAgICB9CiAgICB9ID0gdGhpczsKICAgIGNvbnN0IHBnID0gbm9kZS5nZXRSYXcoIlBnIik7CiAgICBpZiAocGcgaW5zdGFuY2VvZiBSZWYgJiYgIXBhZ2VzTWFwLmhhcyhwZykpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBsZXQga2lkczsKICAgIGNvbnN0IGsgPSBraWRzID0gbm9kZS5nZXRSYXcoIksiKTsKICAgIGlmIChrIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgIGlmICh2aXNpdGVkLmhhcyhrKSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGtpZHMgPSBhd2FpdCB4cmVmLmZldGNoQXN5bmMoayk7CiAgICAgIGlmICghQXJyYXkuaXNBcnJheShraWRzKSkgewogICAgICAgIGtpZHMgPSBba107CiAgICAgIH0KICAgIH0KICAgIGtpZHMgPSBBcnJheS5pc0FycmF5KGtpZHMpID8ga2lkcyA6IFtraWRzXTsKICAgIGNvbnN0IG5ld0tpZHMgPSBbXTsKICAgIGNvbnN0IHN0cnVjdEVsZW1JbmRpY2VzID0gW107CiAgICBmb3IgKGxldCBraWQgb2Yga2lkcykgewogICAgICBjb25zdCBraWRSZWYgPSBraWQgaW5zdGFuY2VvZiBSZWYgPyBraWQgOiBudWxsOwogICAgICBpZiAoa2lkUmVmKSB7CiAgICAgICAgaWYgKHZpc2l0ZWQuaGFzKGtpZFJlZikpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICB2aXNpdGVkLnB1dChraWRSZWYpOwogICAgICAgIGtpZCA9IGF3YWl0IHhyZWYuZmV0Y2hBc3luYyhraWRSZWYpOwogICAgICB9CiAgICAgIGlmICh0eXBlb2Yga2lkID09PSAibnVtYmVyIikgewogICAgICAgIG5ld0tpZHMucHVzaChraWQpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICghKGtpZCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgcGdSZWYgPSBraWQuZ2V0UmF3KCJQZyIpOwogICAgICBpZiAocGdSZWYgaW5zdGFuY2VvZiBSZWYgJiYgIXBhZ2VzTWFwLmhhcyhwZ1JlZikpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB0eXBlID0ga2lkLmdldCgiVHlwZSIpOwogICAgICBpZiAoIXR5cGUgfHwgaXNOYW1lKHR5cGUsICJTdHJ1Y3RFbGVtIikpIHsKICAgICAgICBsZXQgc2V0QXNTcGFuID0gZmFsc2U7CiAgICAgICAgaWYgKGtpZFJlZiAmJiByZW1vdmVkU3RydWN0RWxlbWVudHMuaGFzKGtpZFJlZikpIHsKICAgICAgICAgIGlmICghaXNOYW1lKGtpZC5nZXQoIlMiKSwgIkxpbmsiKSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIHNldEFzU3BhbiA9IHRydWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG5ld0tpZFJlZiA9IGF3YWl0IHRoaXMuI2Nsb25lU3RydWN0VHJlZU5vZGUoa2lkUmVmLCBraWQsIHhyZWYsIHJlbW92ZWRTdHJ1Y3RFbGVtZW50cywgZGVkdXBJRHMsIGRlZHVwQ2xhc3NlcywgZGVkdXBSb2xlcywgdmlzaXRlZCk7CiAgICAgICAgaWYgKG5ld0tpZFJlZikgewogICAgICAgICAgc3RydWN0RWxlbUluZGljZXMucHVzaChuZXdLaWRzLmxlbmd0aCk7CiAgICAgICAgICBuZXdLaWRzLnB1c2gobmV3S2lkUmVmKTsKICAgICAgICAgIGlmIChraWRSZWYpIHsKICAgICAgICAgICAgb2xkUmVmTWFwcGluZy5wdXQoa2lkUmVmLCBuZXdLaWRSZWYpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHNldEFzU3BhbikgewogICAgICAgICAgICB0aGlzLnhyZWZbbmV3S2lkUmVmLm51bV0uc2V0SWZOYW1lKCJTIiwgIlNwYW4iKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGlzTmFtZSh0eXBlLCAiT0JKUiIpKSB7CiAgICAgICAgaWYgKCFraWRSZWYpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBuZXdLaWRSZWYgPSBvbGRSZWZNYXBwaW5nLmdldChraWRSZWYpOwogICAgICAgIGlmICghbmV3S2lkUmVmKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbmV3S2lkID0gdGhpcy54cmVmW25ld0tpZFJlZi5udW1dOwogICAgICAgIGNvbnN0IG9ialJlZiA9IG5ld0tpZC5nZXRSYXcoIk9iaiIpOwogICAgICAgIGlmIChvYmpSZWYgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgIGNvbnN0IG9iaiA9IHRoaXMueHJlZltvYmpSZWYubnVtXTsKICAgICAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBEaWN0ICYmICFvYmouaGFzKCJTdHJ1Y3RQYXJlbnQiKSAmJiBwYXJlbnRTdHJ1Y3RSZWYpIHsKICAgICAgICAgICAgY29uc3Qgc3RydWN0UGFyZW50ID0gdGhpcy5wYXJlbnRUcmVlLnNpemU7CiAgICAgICAgICAgIHRoaXMucGFyZW50VHJlZS5zZXQoc3RydWN0UGFyZW50LCBbb2xkUmVmTWFwcGluZywgcGFyZW50U3RydWN0UmVmXSk7CiAgICAgICAgICAgIG9iai5zZXQoIlN0cnVjdFBhcmVudCIsIHN0cnVjdFBhcmVudCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG5ld0tpZHMucHVzaChuZXdLaWRSZWYpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChpc05hbWUodHlwZSwgIk1DUiIpKSB7CiAgICAgICAgY29uc3QgbmV3S2lkID0gYXdhaXQgdGhpcy4jY29sbGVjdERlcGVuZGVuY2llcyhraWRSZWYgfHwga2lkLCB0cnVlLCB4cmVmKTsKICAgICAgICBuZXdLaWRzLnB1c2gobmV3S2lkKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoa2lkUmVmKSB7CiAgICAgICAgY29uc3QgbmV3S2lkUmVmID0gYXdhaXQgdGhpcy4jY29sbGVjdERlcGVuZGVuY2llcyhraWRSZWYsIHRydWUsIHhyZWYpOwogICAgICAgIG5ld0tpZHMucHVzaChuZXdLaWRSZWYpOwogICAgICB9CiAgICB9CiAgICBpZiAoa2lkcy5sZW5ndGggIT09IDAgJiYgbmV3S2lkcy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBuZXdOb2RlUmVmID0gdGhpcy5uZXdSZWY7CiAgICBjb25zdCBuZXdOb2RlID0gdGhpcy54cmVmW25ld05vZGVSZWYubnVtXSA9IHRoaXMuY2xvbmVEaWN0KG5vZGUpOwogICAgbmV3Tm9kZS5kZWxldGUoIklEIik7CiAgICBuZXdOb2RlLmRlbGV0ZSgiQyIpOwogICAgbmV3Tm9kZS5kZWxldGUoIksiKTsKICAgIG5ld05vZGUuZGVsZXRlKCJQIik7CiAgICBuZXdOb2RlLmRlbGV0ZSgiUyIpOwogICAgYXdhaXQgdGhpcy4jY29sbGVjdERlcGVuZGVuY2llcyhuZXdOb2RlLCBmYWxzZSwgeHJlZik7CiAgICBjb25zdCBjbGFzc05hbWVzID0gbm9kZS5nZXQoIkMiKTsKICAgIGlmIChjbGFzc05hbWVzIGluc3RhbmNlb2YgTmFtZSkgewogICAgICBjb25zdCBuZXdDbGFzc05hbWUgPSBkZWR1cENsYXNzZXMuZ2V0KGNsYXNzTmFtZXMubmFtZSk7CiAgICAgIGlmIChuZXdDbGFzc05hbWUpIHsKICAgICAgICBuZXdOb2RlLnNldCgiQyIsIE5hbWUuZ2V0KG5ld0NsYXNzTmFtZSkpOwogICAgICB9IGVsc2UgewogICAgICAgIG5ld05vZGUuc2V0KCJDIiwgY2xhc3NOYW1lcyk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShjbGFzc05hbWVzKSkgewogICAgICBjb25zdCBuZXdDbGFzc05hbWVzID0gW107CiAgICAgIGZvciAoY29uc3QgY2xhc3NOYW1lIG9mIGNsYXNzTmFtZXMpIHsKICAgICAgICBpZiAoY2xhc3NOYW1lIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgY29uc3QgbmV3Q2xhc3NOYW1lID0gZGVkdXBDbGFzc2VzLmdldChjbGFzc05hbWUubmFtZSk7CiAgICAgICAgICBpZiAobmV3Q2xhc3NOYW1lKSB7CiAgICAgICAgICAgIG5ld0NsYXNzTmFtZXMucHVzaChOYW1lLmdldChuZXdDbGFzc05hbWUpKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG5ld0NsYXNzTmFtZXMucHVzaChjbGFzc05hbWUpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBuZXdOb2RlLnNldCgiQyIsIG5ld0NsYXNzTmFtZXMpOwogICAgfQogICAgY29uc3Qgcm9sZU5hbWUgPSBub2RlLmdldCgiUyIpOwogICAgaWYgKHJvbGVOYW1lIGluc3RhbmNlb2YgTmFtZSkgewogICAgICBjb25zdCBuZXdSb2xlTmFtZSA9IGRlZHVwUm9sZXMuZ2V0KHJvbGVOYW1lLm5hbWUpOwogICAgICBpZiAobmV3Um9sZU5hbWUpIHsKICAgICAgICBuZXdOb2RlLnNldCgiUyIsIE5hbWUuZ2V0KG5ld1JvbGVOYW1lKSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmV3Tm9kZS5zZXQoIlMiLCByb2xlTmFtZSk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGlkID0gbm9kZS5nZXQoIklEIik7CiAgICBpZiAodHlwZW9mIGlkID09PSAic3RyaW5nIikgewogICAgICBjb25zdCBzdHJpbmdJZCA9IHN0cmluZ1RvUERGU3RyaW5nKGlkLCBmYWxzZSk7CiAgICAgIGNvbnN0IG5ld0lkID0gZGVkdXBJRHMuZ2V0KHN0cmluZ0lkKTsKICAgICAgaWYgKG5ld0lkKSB7CiAgICAgICAgbmV3Tm9kZS5zZXQoIklEIiwgc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRShuZXdJZCkpOwogICAgICB9IGVsc2UgewogICAgICAgIG5ld05vZGUuc2V0KCJJRCIsIGlkKTsKICAgICAgfQogICAgfQogICAgbGV0IGF0dHJpYnV0ZXMgPSBuZXdOb2RlLmdldCgiQSIpOwogICAgaWYgKGF0dHJpYnV0ZXMpIHsKICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGF0dHJpYnV0ZXMpKSB7CiAgICAgICAgYXR0cmlidXRlcyA9IFthdHRyaWJ1dGVzXTsKICAgICAgfQogICAgICBmb3IgKGxldCBhdHRyIG9mIGF0dHJpYnV0ZXMpIHsKICAgICAgICBhdHRyID0gdGhpcy54cmVmV3JhcHBlci5mZXRjaChhdHRyKTsKICAgICAgICBpZiAoaXNOYW1lKGF0dHIuZ2V0KCJPIiksICJUYWJsZSIpICYmIGF0dHIuaGFzKCJIZWFkZXJzIikpIHsKICAgICAgICAgIGNvbnN0IGhlYWRlcnMgPSB0aGlzLnhyZWZXcmFwcGVyLmZldGNoKGF0dHIuZ2V0UmF3KCJIZWFkZXJzIikpOwogICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoaGVhZGVycykpIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gaGVhZGVycy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICAgICAgY29uc3QgbmV3SWQgPSBkZWR1cElEcy5nZXQoc3RyaW5nVG9QREZTdHJpbmcoaGVhZGVyc1tpXSwgZmFsc2UpKTsKICAgICAgICAgICAgICBpZiAobmV3SWQpIHsKICAgICAgICAgICAgICAgIGhlYWRlcnNbaV0gPSBuZXdJZDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgaW5kZXggb2Ygc3RydWN0RWxlbUluZGljZXMpIHsKICAgICAgY29uc3Qgc3RydWN0RWxlbVJlZiA9IG5ld0tpZHNbaW5kZXhdOwogICAgICBjb25zdCBzdHJ1Y3RFbGVtID0gdGhpcy54cmVmW3N0cnVjdEVsZW1SZWYubnVtXTsKICAgICAgc3RydWN0RWxlbS5zZXQoIlAiLCBuZXdOb2RlUmVmKTsKICAgIH0KICAgIGlmIChuZXdLaWRzLmxlbmd0aCA9PT0gMSkgewogICAgICBuZXdOb2RlLnNldCgiSyIsIG5ld0tpZHNbMF0pOwogICAgfSBlbHNlIGlmIChuZXdLaWRzLmxlbmd0aCA+IDEpIHsKICAgICAgbmV3Tm9kZS5zZXQoIksiLCBuZXdLaWRzKTsKICAgIH0KICAgIHJldHVybiBuZXdOb2RlUmVmOwogIH0KICBhc3luYyBleHRyYWN0UGFnZXMocGFnZUluZm9zKSB7CiAgICBjb25zdCBwcm9taXNlcyA9IFtdOwogICAgbGV0IG5ld0luZGV4ID0gMDsKICAgIHRoaXMuaGFzU2luZ2xlRmlsZSA9IHBhZ2VJbmZvcy5sZW5ndGggPT09IDE7CiAgICBjb25zdCBhbGxEb2N1bWVudERhdGEgPSBbXTsKICAgIGZvciAoY29uc3QgewogICAgICBkb2N1bWVudCwKICAgICAgaW5jbHVkZVBhZ2VzLAogICAgICBleGNsdWRlUGFnZXMsCiAgICAgIHBhZ2VJbmRpY2VzCiAgICB9IG9mIHBhZ2VJbmZvcykgewogICAgICBpZiAoIWRvY3VtZW50KSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKHBhZ2VJbmRpY2VzKSB7CiAgICAgICAgbmV3SW5kZXggPSAtMTsKICAgICAgfQogICAgICBjb25zdCBkb2N1bWVudERhdGEgPSBuZXcgRG9jdW1lbnREYXRhKGRvY3VtZW50KTsKICAgICAgYWxsRG9jdW1lbnREYXRhLnB1c2goZG9jdW1lbnREYXRhKTsKICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLiNjb2xsZWN0RG9jdW1lbnREYXRhKGRvY3VtZW50RGF0YSkpOwogICAgICBsZXQga2VwdEluZGljZXMsIGtlcHRSYW5nZXMsIGRlbGV0ZWRJbmRpY2VzLCBkZWxldGVkUmFuZ2VzOwogICAgICBmb3IgKGNvbnN0IHBhZ2Ugb2YgaW5jbHVkZVBhZ2VzIHx8IFtdKSB7CiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocGFnZSkpIHsKICAgICAgICAgIChrZXB0UmFuZ2VzIHx8PSBbXSkucHVzaChwYWdlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgKGtlcHRJbmRpY2VzIHx8PSBuZXcgU2V0KCkpLmFkZChwYWdlKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBwYWdlIG9mIGV4Y2x1ZGVQYWdlcyB8fCBbXSkgewogICAgICAgIGlmIChBcnJheS5pc0FycmF5KHBhZ2UpKSB7CiAgICAgICAgICAoZGVsZXRlZFJhbmdlcyB8fD0gW10pLnB1c2gocGFnZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIChkZWxldGVkSW5kaWNlcyB8fD0gbmV3IFNldCgpKS5hZGQocGFnZSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGxldCBwYWdlSW5kZXggPSAwOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBkb2N1bWVudC5udW1QYWdlczsgaSA8IGlpOyBpKyspIHsKICAgICAgICBpZiAoZGVsZXRlZEluZGljZXM/LmhhcyhpKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmIChkZWxldGVkUmFuZ2VzKSB7CiAgICAgICAgICBsZXQgaXNEZWxldGVkID0gZmFsc2U7CiAgICAgICAgICBmb3IgKGNvbnN0IFtzdGFydCwgZW5kXSBvZiBkZWxldGVkUmFuZ2VzKSB7CiAgICAgICAgICAgIGlmIChpID49IHN0YXJ0ICYmIGkgPD0gZW5kKSB7CiAgICAgICAgICAgICAgaXNEZWxldGVkID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGlzRGVsZXRlZCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbGV0IHRha2VQYWdlID0gZmFsc2U7CiAgICAgICAgaWYgKGtlcHRJbmRpY2VzKSB7CiAgICAgICAgICB0YWtlUGFnZSA9IGtlcHRJbmRpY2VzLmhhcyhpKTsKICAgICAgICB9CiAgICAgICAgaWYgKCF0YWtlUGFnZSAmJiBrZXB0UmFuZ2VzKSB7CiAgICAgICAgICBmb3IgKGNvbnN0IFtzdGFydCwgZW5kXSBvZiBrZXB0UmFuZ2VzKSB7CiAgICAgICAgICAgIGlmIChpID49IHN0YXJ0ICYmIGkgPD0gZW5kKSB7CiAgICAgICAgICAgICAgdGFrZVBhZ2UgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICghdGFrZVBhZ2UgJiYgIWtlcHRJbmRpY2VzICYmICFrZXB0UmFuZ2VzKSB7CiAgICAgICAgICB0YWtlUGFnZSA9IHRydWU7CiAgICAgICAgfQogICAgICAgIGlmICghdGFrZVBhZ2UpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBsZXQgbmV3UGFnZUluZGV4OwogICAgICAgIGlmIChwYWdlSW5kaWNlcykgewogICAgICAgICAgbmV3UGFnZUluZGV4ID0gcGFnZUluZGljZXNbcGFnZUluZGV4KytdOwogICAgICAgIH0KICAgICAgICBpZiAobmV3UGFnZUluZGV4ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGlmIChuZXdJbmRleCAhPT0gLTEpIHsKICAgICAgICAgICAgbmV3UGFnZUluZGV4ID0gbmV3SW5kZXgrKzsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZvciAobmV3UGFnZUluZGV4ID0gMDsgdGhpcy5vbGRQYWdlc1tuZXdQYWdlSW5kZXhdID09PSB1bmRlZmluZWQ7IG5ld1BhZ2VJbmRleCsrKSB7fQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBwcm9taXNlcy5wdXNoKGRvY3VtZW50LmdldFBhZ2UoaSkudGhlbihwYWdlID0+IHsKICAgICAgICAgIHRoaXMub2xkUGFnZXNbbmV3UGFnZUluZGV4XSA9IG5ldyBQYWdlRGF0YShwYWdlLCBkb2N1bWVudERhdGEpOwogICAgICAgIH0pKTsKICAgICAgfQogICAgfQogICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpOwogICAgcHJvbWlzZXMubGVuZ3RoID0gMDsKICAgIHRoaXMuI2NvbGxlY3RWYWxpZERlc3RpbmF0aW9ucyhhbGxEb2N1bWVudERhdGEpOwogICAgdGhpcy4jY29sbGVjdFBhZ2VMYWJlbHMoKTsKICAgIGZvciAoY29uc3QgcGFnZSBvZiB0aGlzLm9sZFBhZ2VzKSB7CiAgICAgIHByb21pc2VzLnB1c2godGhpcy4jcG9zdENvbGxlY3RQYWdlRGF0YShwYWdlKSk7CiAgICB9CiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7CiAgICB0aGlzLiNmaW5kRHVwbGljYXRlTmFtZWREZXN0aW5hdGlvbnMoKTsKICAgIHRoaXMuI3NldFBvc3Rwb25lZFJlZkNvcGllcyhhbGxEb2N1bWVudERhdGEpOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdGhpcy5vbGRQYWdlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIHRoaXMubmV3UGFnZXNbaV0gPSBhd2FpdCB0aGlzLiNtYWtlUGFnZUNvcHkoaSwgbnVsbCk7CiAgICB9CiAgICB0aGlzLiNmaXhQb3N0cG9uZWRSZWZDb3BpZXMoYWxsRG9jdW1lbnREYXRhKTsKICAgIGF3YWl0IHRoaXMuI21lcmdlU3RydWN0VHJlZXMoYWxsRG9jdW1lbnREYXRhKTsKICAgIHJldHVybiB0aGlzLndyaXRlUERGKCk7CiAgfQogIGFzeW5jICNjb2xsZWN0RG9jdW1lbnREYXRhKGRvY3VtZW50RGF0YSkgewogICAgY29uc3QgewogICAgICBkb2N1bWVudDogewogICAgICAgIHBkZk1hbmFnZXIsCiAgICAgICAgeHJlZgogICAgICB9CiAgICB9ID0gZG9jdW1lbnREYXRhOwogICAgYXdhaXQgUHJvbWlzZS5hbGwoW3BkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiZGVzdGluYXRpb25zIikudGhlbihkZXN0aW5hdGlvbnMgPT4gZG9jdW1lbnREYXRhLmRlc3RpbmF0aW9ucyA9IGRlc3RpbmF0aW9ucyksIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygicmF3UGFnZUxhYmVscyIpLnRoZW4ocGFnZUxhYmVscyA9PiBkb2N1bWVudERhdGEucGFnZUxhYmVscyA9IHBhZ2VMYWJlbHMpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coInN0cnVjdFRyZWVSb290IikudGhlbihzdHJ1Y3RUcmVlUm9vdCA9PiBkb2N1bWVudERhdGEuc3RydWN0VHJlZVJvb3QgPSBzdHJ1Y3RUcmVlUm9vdCldKTsKICAgIGNvbnN0IHN0cnVjdFRyZWVSb290ID0gZG9jdW1lbnREYXRhLnN0cnVjdFRyZWVSb290OwogICAgaWYgKHN0cnVjdFRyZWVSb290KSB7CiAgICAgIGNvbnN0IHJvb3REaWN0ID0gc3RydWN0VHJlZVJvb3QuZGljdDsKICAgICAgY29uc3QgcGFyZW50VHJlZSA9IHJvb3REaWN0LmdldCgiUGFyZW50VHJlZSIpOwogICAgICBpZiAocGFyZW50VHJlZSkgewogICAgICAgIGNvbnN0IG51bWJlclRyZWUgPSBuZXcgTnVtYmVyVHJlZShwYXJlbnRUcmVlLCB4cmVmKTsKICAgICAgICBkb2N1bWVudERhdGEucGFyZW50VHJlZSA9IG51bWJlclRyZWUuZ2V0QWxsKHRydWUpOwogICAgICB9CiAgICAgIGNvbnN0IGlkVHJlZSA9IHJvb3REaWN0LmdldCgiSURUcmVlIik7CiAgICAgIGlmIChpZFRyZWUpIHsKICAgICAgICBjb25zdCBuYW1lVHJlZSA9IG5ldyBOYW1lVHJlZShpZFRyZWUsIHhyZWYpOwogICAgICAgIGRvY3VtZW50RGF0YS5pZFRyZWUgPSBuYW1lVHJlZS5nZXRBbGwodHJ1ZSk7CiAgICAgIH0KICAgICAgZG9jdW1lbnREYXRhLnJvbGVNYXAgPSByb290RGljdC5nZXQoIlJvbGVNYXAiKSB8fCBudWxsOwogICAgICBkb2N1bWVudERhdGEuY2xhc3NNYXAgPSByb290RGljdC5nZXQoIkNsYXNzTWFwIikgfHwgbnVsbDsKICAgICAgbGV0IG5hbWVzcGFjZXMgPSByb290RGljdC5nZXQoIk5hbWVzcGFjZXMiKSB8fCBudWxsOwogICAgICBpZiAobmFtZXNwYWNlcyAmJiAhQXJyYXkuaXNBcnJheShuYW1lc3BhY2VzKSkgewogICAgICAgIG5hbWVzcGFjZXMgPSBbbmFtZXNwYWNlc107CiAgICAgIH0KICAgICAgZG9jdW1lbnREYXRhLm5hbWVzcGFjZXMgPSBuYW1lc3BhY2VzOwogICAgICBkb2N1bWVudERhdGEuc3RydWN0VHJlZUFGID0gcm9vdERpY3QuZ2V0KCJBRiIpIHx8IG51bGw7CiAgICAgIGRvY3VtZW50RGF0YS5zdHJ1Y3RUcmVlUHJvbnVuY2lhdGlvbkxleGljb24gPSByb290RGljdC5nZXQoIlByb251bmNpYXRpb25MZXhpY29uIikgfHwgbnVsbDsKICAgIH0KICB9CiAgYXN5bmMgI3Bvc3RDb2xsZWN0UGFnZURhdGEocGFnZURhdGEpIHsKICAgIGNvbnN0IHsKICAgICAgcGFnZTogewogICAgICAgIHhyZWYsCiAgICAgICAgYW5ub3RhdGlvbnMKICAgICAgfSwKICAgICAgZG9jdW1lbnREYXRhOiB7CiAgICAgICAgcGFnZXNNYXAsCiAgICAgICAgZGVzdGluYXRpb25zLAogICAgICAgIHVzZWROYW1lZERlc3RpbmF0aW9ucwogICAgICB9CiAgICB9ID0gcGFnZURhdGE7CiAgICBpZiAoIWFubm90YXRpb25zKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHByb21pc2VzID0gW107CiAgICBsZXQgbmV3QW5ub3RhdGlvbnMgPSBbXTsKICAgIGxldCBuZXdJbmRleCA9IDA7CiAgICBmb3IgKGNvbnN0IGFubm90YXRpb25SZWYgb2YgYW5ub3RhdGlvbnMpIHsKICAgICAgY29uc3QgbmV3QW5ub3RhdGlvbkluZGV4ID0gbmV3SW5kZXgrKzsKICAgICAgcHJvbWlzZXMucHVzaCh4cmVmLmZldGNoSWZSZWZBc3luYyhhbm5vdGF0aW9uUmVmKS50aGVuKGFzeW5jIGFubm90YXRpb25EaWN0ID0+IHsKICAgICAgICBpZiAoIWlzTmFtZShhbm5vdGF0aW9uRGljdC5nZXQoIlN1YnR5cGUiKSwgIkxpbmsiKSkgewogICAgICAgICAgbmV3QW5ub3RhdGlvbnNbbmV3QW5ub3RhdGlvbkluZGV4XSA9IGFubm90YXRpb25SZWY7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IGFjdGlvbiA9IGFubm90YXRpb25EaWN0LmdldCgiQSIpOwogICAgICAgIGNvbnN0IGRlc3QgPSBhY3Rpb24gaW5zdGFuY2VvZiBEaWN0ID8gYWN0aW9uLmdldCgiRCIpIDogYW5ub3RhdGlvbkRpY3QuZ2V0KCJEZXN0Iik7CiAgICAgICAgaWYgKCFkZXN0IHx8IEFycmF5LmlzQXJyYXkoZGVzdCkgJiYgKCEoZGVzdFswXSBpbnN0YW5jZW9mIFJlZikgfHwgcGFnZXNNYXAuaGFzKGRlc3RbMF0pKSkgewogICAgICAgICAgbmV3QW5ub3RhdGlvbnNbbmV3QW5ub3RhdGlvbkluZGV4XSA9IGFubm90YXRpb25SZWY7CiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZGVzdCA9PT0gInN0cmluZyIpIHsKICAgICAgICAgIGNvbnN0IGRlc3RTdHJpbmcgPSBzdHJpbmdUb1BERlN0cmluZyhkZXN0LCB0cnVlKTsKICAgICAgICAgIGlmIChkZXN0aW5hdGlvbnMuaGFzKGRlc3RTdHJpbmcpKSB7CiAgICAgICAgICAgIG5ld0Fubm90YXRpb25zW25ld0Fubm90YXRpb25JbmRleF0gPSBhbm5vdGF0aW9uUmVmOwogICAgICAgICAgICB1c2VkTmFtZWREZXN0aW5hdGlvbnMuYWRkKGRlc3RTdHJpbmcpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSkpOwogICAgfQogICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpOwogICAgbmV3QW5ub3RhdGlvbnMgPSBuZXdBbm5vdGF0aW9ucy5maWx0ZXIoYW5ub3QgPT4gISFhbm5vdCk7CiAgICBwYWdlRGF0YS5hbm5vdGF0aW9ucyA9IG5ld0Fubm90YXRpb25zLmxlbmd0aCA+IDAgPyBuZXdBbm5vdGF0aW9ucyA6IG51bGw7CiAgfQogICNzZXRQb3N0cG9uZWRSZWZDb3BpZXMoYWxsRG9jdW1lbnREYXRhKSB7CiAgICBmb3IgKGNvbnN0IHsKICAgICAgcG9zdHBvbmVkUmVmQ29waWVzLAogICAgICBwYWdlc01hcAogICAgfSBvZiBhbGxEb2N1bWVudERhdGEpIHsKICAgICAgZm9yIChjb25zdCBvbGRQYWdlUmVmIG9mIHBhZ2VzTWFwLmtleXMoKSkgewogICAgICAgIHBvc3Rwb25lZFJlZkNvcGllcy5wdXQob2xkUGFnZVJlZiwgW10pOwogICAgICB9CiAgICB9CiAgfQogICNmaXhQb3N0cG9uZWRSZWZDb3BpZXMoYWxsRG9jdW1lbnREYXRhKSB7CiAgICBmb3IgKGNvbnN0IHsKICAgICAgcG9zdHBvbmVkUmVmQ29waWVzLAogICAgICBvbGRSZWZNYXBwaW5nCiAgICB9IG9mIGFsbERvY3VtZW50RGF0YSkgewogICAgICBmb3IgKGNvbnN0IFtvbGRSZWYsIGFjdGlvbnNdIG9mIHBvc3Rwb25lZFJlZkNvcGllcy5pdGVtcygpKSB7CiAgICAgICAgY29uc3QgbmV3UmVmID0gb2xkUmVmTWFwcGluZy5nZXQob2xkUmVmKTsKICAgICAgICBmb3IgKGNvbnN0IGFjdGlvbiBvZiBhY3Rpb25zKSB7CiAgICAgICAgICBhY3Rpb24obmV3UmVmKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcG9zdHBvbmVkUmVmQ29waWVzLmNsZWFyKCk7CiAgICB9CiAgfQogICN2aXNpdE9iamVjdChvYmosIGNhbGxiYWNrLCB2aXNpdGVkID0gbmV3IFJlZlNldCgpKSB7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgIGlmICghdmlzaXRlZC5oYXMob2JqKSkgewogICAgICAgIHZpc2l0ZWQucHV0KG9iaik7CiAgICAgICAgdGhpcy4jdmlzaXRPYmplY3QodGhpcy54cmVmW29iai5udW1dLCBjYWxsYmFjaywgdmlzaXRlZCk7CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkgewogICAgICBmb3IgKGNvbnN0IGl0ZW0gb2Ygb2JqKSB7CiAgICAgICAgdGhpcy4jdmlzaXRPYmplY3QoaXRlbSwgY2FsbGJhY2ssIHZpc2l0ZWQpOwogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCBkaWN0OwogICAgaWYgKG9iaiBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgKHsKICAgICAgICBkaWN0CiAgICAgIH0gPSBvYmopOwogICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGRpY3QgPSBvYmo7CiAgICB9CiAgICBpZiAoZGljdCkgewogICAgICBjYWxsYmFjayhkaWN0KTsKICAgICAgZm9yIChjb25zdCB2YWx1ZSBvZiBkaWN0LmdldFJhd1ZhbHVlcygpKSB7CiAgICAgICAgdGhpcy4jdmlzaXRPYmplY3QodmFsdWUsIGNhbGxiYWNrLCB2aXNpdGVkKTsKICAgICAgfQogICAgfQogIH0KICBhc3luYyAjbWVyZ2VTdHJ1Y3RUcmVlcyhhbGxEb2N1bWVudERhdGEpIHsKICAgIGxldCBuZXdTdHJ1Y3RQYXJlbnRJZCA9IDA7CiAgICBjb25zdCB7CiAgICAgIHBhcmVudFRyZWU6IG5ld1BhcmVudFRyZWUKICAgIH0gPSB0aGlzOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdGhpcy5uZXdQYWdlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBkb2N1bWVudERhdGE6IHsKICAgICAgICAgIHBhcmVudFRyZWUsCiAgICAgICAgICBvbGRSZWZNYXBwaW5nLAogICAgICAgICAgb2xkU3RydWN0UGFyZW50TWFwcGluZywKICAgICAgICAgIHVzZWRTdHJ1Y3RQYXJlbnRzLAogICAgICAgICAgZG9jdW1lbnQ6IHsKICAgICAgICAgICAgeHJlZgogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSA9IHRoaXMub2xkUGFnZXNbaV07CiAgICAgIGlmICghcGFyZW50VHJlZSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IHBhZ2VSZWYgPSB0aGlzLm5ld1BhZ2VzW2ldOwogICAgICBjb25zdCBwYWdlRGljdCA9IHRoaXMueHJlZltwYWdlUmVmLm51bV07CiAgICAgIHRoaXMuI3Zpc2l0T2JqZWN0KHBhZ2VEaWN0LCBkaWN0ID0+IHsKICAgICAgICBjb25zdCBzdHJ1Y3RQYXJlbnQgPSBkaWN0LmdldCgiU3RydWN0UGFyZW50IikgPz8gZGljdC5nZXQoIlN0cnVjdFBhcmVudHMiKTsKICAgICAgICBpZiAodHlwZW9mIHN0cnVjdFBhcmVudCAhPT0gIm51bWJlciIpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgdXNlZFN0cnVjdFBhcmVudHMuYWRkKHN0cnVjdFBhcmVudCk7CiAgICAgICAgbGV0IHBhcmVudCA9IHBhcmVudFRyZWUuZ2V0KHN0cnVjdFBhcmVudCk7CiAgICAgICAgY29uc3QgcGFyZW50UmVmID0gcGFyZW50IGluc3RhbmNlb2YgUmVmID8gcGFyZW50IDogbnVsbDsKICAgICAgICBpZiAocGFyZW50UmVmKSB7CiAgICAgICAgICBjb25zdCBhcnJheSA9IHhyZWYuZmV0Y2gocGFyZW50UmVmKTsKICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGFycmF5KSkgewogICAgICAgICAgICBwYXJlbnQgPSBhcnJheTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocGFyZW50KSAmJiBwYXJlbnQuZXZlcnkocmVmID0+IHJlZiA9PT0gbnVsbCkpIHsKICAgICAgICAgIHBhcmVudCA9IG51bGw7CiAgICAgICAgfQogICAgICAgIGlmICghcGFyZW50KSB7CiAgICAgICAgICBpZiAoZGljdC5oYXMoIlN0cnVjdFBhcmVudCIpKSB7CiAgICAgICAgICAgIGRpY3QuZGVsZXRlKCJTdHJ1Y3RQYXJlbnQiKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGRpY3QuZGVsZXRlKCJTdHJ1Y3RQYXJlbnRzIik7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGxldCBuZXdTdHJ1Y3RQYXJlbnQgPSBvbGRTdHJ1Y3RQYXJlbnRNYXBwaW5nLmdldChzdHJ1Y3RQYXJlbnQpOwogICAgICAgIGlmIChuZXdTdHJ1Y3RQYXJlbnQgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgbmV3U3RydWN0UGFyZW50ID0gbmV3U3RydWN0UGFyZW50SWQrKzsKICAgICAgICAgIG9sZFN0cnVjdFBhcmVudE1hcHBpbmcuc2V0KHN0cnVjdFBhcmVudCwgbmV3U3RydWN0UGFyZW50KTsKICAgICAgICAgIG5ld1BhcmVudFRyZWUuc2V0KG5ld1N0cnVjdFBhcmVudCwgW29sZFJlZk1hcHBpbmcsIHBhcmVudF0pOwogICAgICAgIH0KICAgICAgICBpZiAoZGljdC5oYXMoIlN0cnVjdFBhcmVudCIpKSB7CiAgICAgICAgICBkaWN0LnNldCgiU3RydWN0UGFyZW50IiwgbmV3U3RydWN0UGFyZW50KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZGljdC5zZXQoIlN0cnVjdFBhcmVudHMiLCBuZXdTdHJ1Y3RQYXJlbnQpOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIHN0cnVjdFRyZWVLaWRzLAogICAgICBpZFRyZWU6IG5ld0lkVHJlZSwKICAgICAgY2xhc3NNYXA6IG5ld0NsYXNzTWFwLAogICAgICByb2xlTWFwOiBuZXdSb2xlTWFwLAogICAgICBuYW1lc3BhY2VzOiBuZXdOYW1lc3BhY2VzLAogICAgICBzdHJ1Y3RUcmVlQUY6IG5ld1N0cnVjdFRyZWVBRiwKICAgICAgc3RydWN0VHJlZVByb251bmNpYXRpb25MZXhpY29uOiBuZXdTdHJ1Y3RUcmVlUHJvbnVuY2lhdGlvbkxleGljb24KICAgIH0gPSB0aGlzOwogICAgZm9yIChjb25zdCBkb2N1bWVudERhdGEgb2YgYWxsRG9jdW1lbnREYXRhKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBkb2N1bWVudDogewogICAgICAgICAgeHJlZgogICAgICAgIH0sCiAgICAgICAgb2xkUmVmTWFwcGluZywKICAgICAgICBwYXJlbnRUcmVlLAogICAgICAgIHVzZWRTdHJ1Y3RQYXJlbnRzLAogICAgICAgIHN0cnVjdFRyZWVSb290LAogICAgICAgIGlkVHJlZSwKICAgICAgICBjbGFzc01hcCwKICAgICAgICByb2xlTWFwLAogICAgICAgIG5hbWVzcGFjZXMsCiAgICAgICAgc3RydWN0VHJlZUFGLAogICAgICAgIHN0cnVjdFRyZWVQcm9udW5jaWF0aW9uTGV4aWNvbgogICAgICB9ID0gZG9jdW1lbnREYXRhOwogICAgICBpZiAoIXN0cnVjdFRyZWVSb290KSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgdGhpcy5jdXJyZW50RG9jdW1lbnQgPSBkb2N1bWVudERhdGE7CiAgICAgIGNvbnN0IHJlbW92ZWRTdHJ1Y3RFbGVtZW50cyA9IG5ldyBSZWZTZXQoKTsKICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgcGFyZW50VHJlZSB8fCBbXSkgewogICAgICAgIGlmICghdXNlZFN0cnVjdFBhcmVudHMuaGFzKGtleSkgJiYgdmFsdWUgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgIHJlbW92ZWRTdHJ1Y3RFbGVtZW50cy5wdXQodmFsdWUpOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBkZWR1cElEcyA9IG5ldyBNYXAoKTsKICAgICAgZm9yIChjb25zdCBbaWQsIG5vZGVSZWZdIG9mIGlkVHJlZSB8fCBbXSkgewogICAgICAgIGxldCBfaWQgPSBpZDsKICAgICAgICBpZiAobmV3SWRUcmVlLmhhcyhpZCkpIHsKICAgICAgICAgIGZvciAobGV0IGkgPSAxOzsgaSsrKSB7CiAgICAgICAgICAgIGNvbnN0IG5ld0lkID0gYCR7aWR9XyR7aX1gOwogICAgICAgICAgICBpZiAoIW5ld0lkVHJlZS5oYXMobmV3SWQpKSB7CiAgICAgICAgICAgICAgZGVkdXBJRHMuc2V0KGlkLCBuZXdJZCk7CiAgICAgICAgICAgICAgX2lkID0gbmV3SWQ7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbmV3SWRUcmVlLnNldChfaWQsIG5vZGVSZWYpOwogICAgICB9CiAgICAgIGNvbnN0IGRlZHVwQ2xhc3NlcyA9IG5ldyBNYXAoKTsKICAgICAgaWYgKGNsYXNzTWFwPy5zaXplID4gMCkgewogICAgICAgIGZvciAobGV0IFtjbGFzc05hbWUsIGNsYXNzRGljdF0gb2YgY2xhc3NNYXApIHsKICAgICAgICAgIGNsYXNzRGljdCA9IGF3YWl0IHRoaXMuI2NvbGxlY3REZXBlbmRlbmNpZXMoY2xhc3NEaWN0LCB0cnVlLCB4cmVmKTsKICAgICAgICAgIGlmIChuZXdDbGFzc01hcC5oYXMoY2xhc3NOYW1lKSkgewogICAgICAgICAgICBmb3IgKGxldCBpID0gMTs7IGkrKykgewogICAgICAgICAgICAgIGNvbnN0IG5ld0NsYXNzTmFtZSA9IGAke2NsYXNzTmFtZX1fJHtpfWA7CiAgICAgICAgICAgICAgaWYgKCFuZXdDbGFzc01hcC5oYXMobmV3Q2xhc3NOYW1lKSkgewogICAgICAgICAgICAgICAgZGVkdXBDbGFzc2VzLnNldChjbGFzc05hbWUsIG5ld0NsYXNzTmFtZSk7CiAgICAgICAgICAgICAgICBjbGFzc05hbWUgPSBuZXdDbGFzc05hbWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIG5ld0NsYXNzTWFwLnNldChjbGFzc05hbWUsIGNsYXNzRGljdCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGNvbnN0IGRlZHVwUm9sZXMgPSBuZXcgTWFwKCk7CiAgICAgIGlmIChyb2xlTWFwPy5zaXplID4gMCkgewogICAgICAgIGZvciAoY29uc3QgW3JvbGVOYW1lLCBtYXBwZWROYW1lXSBvZiByb2xlTWFwKSB7CiAgICAgICAgICBjb25zdCBuZXdNYXBwZWROYW1lID0gbmV3Um9sZU1hcC5nZXQocm9sZU5hbWUpOwogICAgICAgICAgaWYgKCFuZXdNYXBwZWROYW1lKSB7CiAgICAgICAgICAgIG5ld1JvbGVNYXAuc2V0KHJvbGVOYW1lLCBtYXBwZWROYW1lKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobmV3TWFwcGVkTmFtZSA9PT0gbWFwcGVkTmFtZSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAobGV0IGkgPSAxOzsgaSsrKSB7CiAgICAgICAgICAgIGNvbnN0IG5ld1JvbGVOYW1lID0gYCR7cm9sZU5hbWV9XyR7aX1gOwogICAgICAgICAgICBpZiAoIW5ld1JvbGVNYXAuaGFzKG5ld1JvbGVOYW1lKSkgewogICAgICAgICAgICAgIGRlZHVwUm9sZXMuc2V0KHJvbGVOYW1lLCBuZXdSb2xlTmFtZSk7CiAgICAgICAgICAgICAgbmV3Um9sZU1hcC5zZXQobmV3Um9sZU5hbWUsIG1hcHBlZE5hbWUpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChuYW1lc3BhY2VzPy5sZW5ndGggPiAwKSB7CiAgICAgICAgZm9yIChjb25zdCBuYW1lc3BhY2VSZWYgb2YgbmFtZXNwYWNlcykgewogICAgICAgICAgY29uc3QgbmFtZXNwYWNlID0gYXdhaXQgeHJlZi5mZXRjaElmUmVmQXN5bmMobmFtZXNwYWNlUmVmKTsKICAgICAgICAgIGxldCBucyA9IG5hbWVzcGFjZS5nZXQoIk5TIik7CiAgICAgICAgICBpZiAoIW5zIHx8IG5ld05hbWVzcGFjZXMuaGFzKG5zKSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIG5zID0gc3RyaW5nVG9QREZTdHJpbmcobnMsIGZhbHNlKTsKICAgICAgICAgIGNvbnN0IG5ld05hbWVzcGFjZSA9IGF3YWl0IHRoaXMuI2NvbGxlY3REZXBlbmRlbmNpZXMobmFtZXNwYWNlLCB0cnVlLCB4cmVmKTsKICAgICAgICAgIG5ld05hbWVzcGFjZXMuc2V0KG5zLCBuZXdOYW1lc3BhY2UpOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoc3RydWN0VHJlZUFGKSB7CiAgICAgICAgZm9yIChjb25zdCBhZlJlZiBvZiBzdHJ1Y3RUcmVlQUYpIHsKICAgICAgICAgIG5ld1N0cnVjdFRyZWVBRi5wdXNoKGF3YWl0IHRoaXMuI2NvbGxlY3REZXBlbmRlbmNpZXMoYWZSZWYsIHRydWUsIHhyZWYpKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHN0cnVjdFRyZWVQcm9udW5jaWF0aW9uTGV4aWNvbikgewogICAgICAgIGZvciAoY29uc3QgbGV4aWNvblJlZiBvZiBzdHJ1Y3RUcmVlUHJvbnVuY2lhdGlvbkxleGljb24pIHsKICAgICAgICAgIG5ld1N0cnVjdFRyZWVQcm9udW5jaWF0aW9uTGV4aWNvbi5wdXNoKGF3YWl0IHRoaXMuI2NvbGxlY3REZXBlbmRlbmNpZXMobGV4aWNvblJlZiwgdHJ1ZSwgeHJlZikpOwogICAgICAgIH0KICAgICAgfQogICAgICBsZXQga2lkcyA9IHN0cnVjdFRyZWVSb290LmRpY3QuZ2V0KCJLIik7CiAgICAgIGlmICgha2lkcykgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGtpZHMgPSBBcnJheS5pc0FycmF5KGtpZHMpID8ga2lkcyA6IFtraWRzXTsKICAgICAgZm9yIChsZXQga2lkIG9mIGtpZHMpIHsKICAgICAgICBjb25zdCBraWRSZWYgPSBraWQgaW5zdGFuY2VvZiBSZWYgPyBraWQgOiBudWxsOwogICAgICAgIGlmIChraWRSZWYgJiYgcmVtb3ZlZFN0cnVjdEVsZW1lbnRzLmhhcyhraWRSZWYpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAga2lkID0gYXdhaXQgeHJlZi5mZXRjaElmUmVmQXN5bmMoa2lkKTsKICAgICAgICBjb25zdCBuZXdLaWRSZWYgPSBhd2FpdCB0aGlzLiNjbG9uZVN0cnVjdFRyZWVOb2RlKGtpZFJlZiwga2lkLCB4cmVmLCByZW1vdmVkU3RydWN0RWxlbWVudHMsIGRlZHVwSURzLCBkZWR1cENsYXNzZXMsIGRlZHVwUm9sZXMpOwogICAgICAgIGlmIChuZXdLaWRSZWYpIHsKICAgICAgICAgIHN0cnVjdFRyZWVLaWRzLnB1c2gobmV3S2lkUmVmKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBbaWQsIG5vZGVSZWZdIG9mIGlkVHJlZSB8fCBbXSkgewogICAgICAgIGNvbnN0IG5ld05vZGVSZWYgPSBvbGRSZWZNYXBwaW5nLmdldChub2RlUmVmKTsKICAgICAgICBjb25zdCBuZXdJZCA9IGRlZHVwSURzLmdldChpZCkgfHwgaWQ7CiAgICAgICAgaWYgKG5ld05vZGVSZWYpIHsKICAgICAgICAgIG5ld0lkVHJlZS5zZXQobmV3SWQsIG5ld05vZGVSZWYpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBuZXdJZFRyZWUuZGVsZXRlKG5ld0lkKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgW2tleSwgW29sZFJlZk1hcHBpbmcsIHBhcmVudF1dIG9mIG5ld1BhcmVudFRyZWUpIHsKICAgICAgaWYgKCFwYXJlbnQpIHsKICAgICAgICBuZXdQYXJlbnRUcmVlLmRlbGV0ZShrZXkpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICghQXJyYXkuaXNBcnJheShwYXJlbnQpKSB7CiAgICAgICAgY29uc3QgbmV3UGFyZW50ID0gb2xkUmVmTWFwcGluZy5nZXQocGFyZW50KTsKICAgICAgICBpZiAobmV3UGFyZW50ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIG5ld1BhcmVudFRyZWUuZGVsZXRlKGtleSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG5ld1BhcmVudFRyZWUuc2V0KGtleSwgbmV3UGFyZW50KTsKICAgICAgICB9CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgbmV3UGFyZW50cyA9IHBhcmVudC5tYXAocmVmID0+IHJlZiBpbnN0YW5jZW9mIFJlZiAmJiBvbGRSZWZNYXBwaW5nLmdldChyZWYpIHx8IG51bGwpOwogICAgICBpZiAobmV3UGFyZW50cy5sZW5ndGggPT09IDAgfHwgbmV3UGFyZW50cy5ldmVyeShyZWYgPT4gcmVmID09PSBudWxsKSkgewogICAgICAgIG5ld1BhcmVudFRyZWUuZGVsZXRlKGtleSk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbmV3UGFyZW50VHJlZS5zZXQoa2V5LCBuZXdQYXJlbnRzKTsKICAgIH0KICAgIHRoaXMuY3VycmVudERvY3VtZW50ID0gbnVsbDsKICB9CiAgI2NvbGxlY3RWYWxpZERlc3RpbmF0aW9ucyhhbGxEb2N1bWVudERhdGEpIHsKICAgIGZvciAoY29uc3QgZG9jdW1lbnREYXRhIG9mIGFsbERvY3VtZW50RGF0YSkgewogICAgICBpZiAoIWRvY3VtZW50RGF0YS5kZXN0aW5hdGlvbnMpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB7CiAgICAgICAgZGVzdGluYXRpb25zLAogICAgICAgIHBhZ2VzTWFwCiAgICAgIH0gPSBkb2N1bWVudERhdGE7CiAgICAgIGNvbnN0IG5ld0Rlc3RpbmF0aW9ucyA9IGRvY3VtZW50RGF0YS5kZXN0aW5hdGlvbnMgPSBuZXcgTWFwKCk7CiAgICAgIGZvciAoY29uc3QgW2tleSwgZGVzdF0gb2YgT2JqZWN0LmVudHJpZXMoZGVzdGluYXRpb25zKSkgewogICAgICAgIGNvbnN0IHBhZ2VSZWYgPSBkZXN0WzBdOwogICAgICAgIGNvbnN0IHBhZ2VEYXRhID0gcGFnZXNNYXAuZ2V0KHBhZ2VSZWYpOwogICAgICAgIGlmICghcGFnZURhdGEpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICAocGFnZURhdGEucG9pbnRpbmdOYW1lZERlc3RpbmF0aW9ucyB8fD0gbmV3IFNldCgpKS5hZGQoa2V5KTsKICAgICAgICBuZXdEZXN0aW5hdGlvbnMuc2V0KGtleSwgZGVzdCk7CiAgICAgIH0KICAgIH0KICB9CiAgI2ZpbmREdXBsaWNhdGVOYW1lZERlc3RpbmF0aW9ucygpIHsKICAgIGNvbnN0IHsKICAgICAgbmFtZWREZXN0aW5hdGlvbnMKICAgIH0gPSB0aGlzOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdGhpcy5vbGRQYWdlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IHBhZ2UgPSB0aGlzLm9sZFBhZ2VzW2ldOwogICAgICBjb25zdCB7CiAgICAgICAgZG9jdW1lbnREYXRhOiB7CiAgICAgICAgICBkZXN0aW5hdGlvbnMsCiAgICAgICAgICBkZWR1cE5hbWVkRGVzdGluYXRpb25zLAogICAgICAgICAgdXNlZE5hbWVkRGVzdGluYXRpb25zCiAgICAgICAgfQogICAgICB9ID0gcGFnZTsKICAgICAgbGV0IHsKICAgICAgICBwb2ludGluZ05hbWVkRGVzdGluYXRpb25zCiAgICAgIH0gPSBwYWdlOwogICAgICBpZiAoIXBvaW50aW5nTmFtZWREZXN0aW5hdGlvbnMpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBwYWdlLnBvaW50aW5nTmFtZWREZXN0aW5hdGlvbnMgPSBwb2ludGluZ05hbWVkRGVzdGluYXRpb25zID0gcG9pbnRpbmdOYW1lZERlc3RpbmF0aW9ucy5pbnRlcnNlY3Rpb24odXNlZE5hbWVkRGVzdGluYXRpb25zKTsKICAgICAgZm9yIChjb25zdCBwb2ludGluZ0Rlc3Qgb2YgcG9pbnRpbmdOYW1lZERlc3RpbmF0aW9ucykgewogICAgICAgIGlmICghdXNlZE5hbWVkRGVzdGluYXRpb25zLmhhcyhwb2ludGluZ0Rlc3QpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZGVzdCA9IGRlc3RpbmF0aW9ucy5nZXQocG9pbnRpbmdEZXN0KS5zbGljZSgpOwogICAgICAgIGlmICghbmFtZWREZXN0aW5hdGlvbnMuaGFzKHBvaW50aW5nRGVzdCkpIHsKICAgICAgICAgIG5hbWVkRGVzdGluYXRpb25zLnNldChwb2ludGluZ0Rlc3QsIGRlc3QpOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG5ld05hbWUgPSBgJHtwb2ludGluZ0Rlc3R9X3Ake2kgKyAxfWA7CiAgICAgICAgZGVkdXBOYW1lZERlc3RpbmF0aW9ucy5zZXQocG9pbnRpbmdEZXN0LCBuZXdOYW1lKTsKICAgICAgICBuYW1lZERlc3RpbmF0aW9ucy5zZXQobmV3TmFtZSwgZGVzdCk7CiAgICAgIH0KICAgIH0KICB9CiAgI2ZpeE5hbWVkRGVzdGluYXRpb25zKGFubm90YXRpb25zLCBkZWR1cE5hbWVkRGVzdGluYXRpb25zKSB7CiAgICBpZiAoZGVkdXBOYW1lZERlc3RpbmF0aW9ucy5zaXplID09PSAwKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGZpeERlc3RpbmF0aW9uID0gKGRpY3QsIGtleSwgZGVzdCkgPT4gewogICAgICBpZiAodHlwZW9mIGRlc3QgPT09ICJzdHJpbmciKSB7CiAgICAgICAgZGljdC5zZXQoa2V5LCBkZWR1cE5hbWVkRGVzdGluYXRpb25zLmdldChzdHJpbmdUb1BERlN0cmluZyhkZXN0LCB0cnVlKSkgfHwgZGVzdCk7CiAgICAgIH0KICAgIH07CiAgICBmb3IgKGNvbnN0IGFubm90UmVmIG9mIGFubm90YXRpb25zKSB7CiAgICAgIGNvbnN0IGFubm90RGljdCA9IHRoaXMueHJlZlthbm5vdFJlZi5udW1dOwogICAgICBpZiAoIWlzTmFtZShhbm5vdERpY3QuZ2V0KCJTdWJ0eXBlIiksICJMaW5rIikpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBhY3Rpb24gPSBhbm5vdERpY3QuZ2V0KCJBIik7CiAgICAgIGlmIChhY3Rpb24gaW5zdGFuY2VvZiBEaWN0ICYmIGFjdGlvbi5oYXMoIkQiKSkgewogICAgICAgIGNvbnN0IGRlc3QgPSBhY3Rpb24uZ2V0KCJEIik7CiAgICAgICAgZml4RGVzdGluYXRpb24oYWN0aW9uLCAiRCIsIGRlc3QpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGRlc3QgPSBhbm5vdERpY3QuZ2V0KCJEZXN0Iik7CiAgICAgIGZpeERlc3RpbmF0aW9uKGFubm90RGljdCwgIkRlc3QiLCBkZXN0KTsKICAgIH0KICB9CiAgYXN5bmMgI2NvbGxlY3RQYWdlTGFiZWxzKCkgewogICAgaWYgKCF0aGlzLmhhc1NpbmdsZUZpbGUpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgewogICAgICBkb2N1bWVudERhdGE6IHsKICAgICAgICBkb2N1bWVudCwKICAgICAgICBwYWdlTGFiZWxzCiAgICAgIH0KICAgIH0gPSB0aGlzLm9sZFBhZ2VzWzBdOwogICAgaWYgKCFwYWdlTGFiZWxzKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG51bVBhZ2VzID0gZG9jdW1lbnQubnVtUGFnZXM7CiAgICBjb25zdCBvbGRQYWdlTGFiZWxzID0gW107CiAgICBjb25zdCBvbGRQYWdlSW5kaWNlcyA9IG5ldyBTZXQodGhpcy5vbGRQYWdlcy5tYXAoKHsKICAgICAgcGFnZTogewogICAgICAgIHBhZ2VJbmRleAogICAgICB9CiAgICB9KSA9PiBwYWdlSW5kZXgpKTsKICAgIGxldCBjdXJyZW50TGFiZWwgPSBudWxsOwogICAgbGV0IHN0Rmlyc3RJbmRleCA9IC0xOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1QYWdlczsgaSsrKSB7CiAgICAgIGNvbnN0IG5ld0xhYmVsID0gcGFnZUxhYmVscy5nZXQoaSk7CiAgICAgIGlmIChuZXdMYWJlbCkgewogICAgICAgIGN1cnJlbnRMYWJlbCA9IG5ld0xhYmVsOwogICAgICAgIHN0Rmlyc3RJbmRleCA9IGN1cnJlbnRMYWJlbC5oYXMoIlN0IikgPyBpIDogLTE7CiAgICAgIH0KICAgICAgaWYgKCFvbGRQYWdlSW5kaWNlcy5oYXMoaSkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoc3RGaXJzdEluZGV4ICE9PSAtMSkgewogICAgICAgIGNvbnN0IHN0ID0gY3VycmVudExhYmVsLmdldCgiU3QiKTsKICAgICAgICBjdXJyZW50TGFiZWwgPSB0aGlzLmNsb25lRGljdChjdXJyZW50TGFiZWwpOwogICAgICAgIGN1cnJlbnRMYWJlbC5zZXQoIlN0Iiwgc3QgKyAoaSAtIHN0Rmlyc3RJbmRleCkpOwogICAgICAgIHN0Rmlyc3RJbmRleCA9IC0xOwogICAgICB9CiAgICAgIG9sZFBhZ2VMYWJlbHMucHVzaChjdXJyZW50TGFiZWwpOwogICAgfQogICAgY3VycmVudExhYmVsID0gb2xkUGFnZUxhYmVsc1swXTsKICAgIGxldCBjdXJyZW50SW5kZXggPSAwOwogICAgY29uc3QgbmV3UGFnZUxhYmVscyA9IHRoaXMucGFnZUxhYmVscyA9IFtbMCwgY3VycmVudExhYmVsXV07CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBvbGRQYWdlTGFiZWxzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgbGFiZWwgPSBvbGRQYWdlTGFiZWxzW2ldOwogICAgICBpZiAobGFiZWwgPT09IGN1cnJlbnRMYWJlbCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGN1cnJlbnRJbmRleCA9IGk7CiAgICAgIGN1cnJlbnRMYWJlbCA9IGxhYmVsOwogICAgICBuZXdQYWdlTGFiZWxzLnB1c2goW2N1cnJlbnRJbmRleCwgY3VycmVudExhYmVsXSk7CiAgICB9CiAgfQogIGFzeW5jICNtYWtlUGFnZUNvcHkocGFnZUluZGV4KSB7CiAgICBjb25zdCB7CiAgICAgIHBhZ2UsCiAgICAgIGRvY3VtZW50RGF0YSwKICAgICAgYW5ub3RhdGlvbnMsCiAgICAgIHBvaW50aW5nTmFtZWREZXN0aW5hdGlvbnMKICAgIH0gPSB0aGlzLm9sZFBhZ2VzW3BhZ2VJbmRleF07CiAgICB0aGlzLmN1cnJlbnREb2N1bWVudCA9IGRvY3VtZW50RGF0YTsKICAgIGNvbnN0IHsKICAgICAgZGVkdXBOYW1lZERlc3RpbmF0aW9ucywKICAgICAgb2xkUmVmTWFwcGluZwogICAgfSA9IGRvY3VtZW50RGF0YTsKICAgIGNvbnN0IHsKICAgICAgeHJlZiwKICAgICAgcm90YXRlLAogICAgICBtZWRpYUJveCwKICAgICAgcmVzb3VyY2VzLAogICAgICByZWY6IG9sZFBhZ2VSZWYKICAgIH0gPSBwYWdlOwogICAgY29uc3QgcGFnZVJlZiA9IHRoaXMubmV3UmVmOwogICAgY29uc3QgcGFnZURpY3QgPSB0aGlzLnhyZWZbcGFnZVJlZi5udW1dID0gdGhpcy5jbG9uZURpY3QocGFnZS5wYWdlRGljdCk7CiAgICBvbGRSZWZNYXBwaW5nLnB1dChvbGRQYWdlUmVmLCBwYWdlUmVmKTsKICAgIGlmIChwb2ludGluZ05hbWVkRGVzdGluYXRpb25zKSB7CiAgICAgIGZvciAoY29uc3QgcG9pbnRpbmdEZXN0IG9mIHBvaW50aW5nTmFtZWREZXN0aW5hdGlvbnMpIHsKICAgICAgICBjb25zdCBuYW1lID0gZGVkdXBOYW1lZERlc3RpbmF0aW9ucy5nZXQocG9pbnRpbmdEZXN0KSB8fCBwb2ludGluZ0Rlc3Q7CiAgICAgICAgY29uc3QgZGVzdCA9IHRoaXMubmFtZWREZXN0aW5hdGlvbnMuZ2V0KG5hbWUpOwogICAgICAgIGRlc3RbMF0gPSBwYWdlUmVmOwogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IGtleSBvZiBbIlJvdGF0ZSIsICJNZWRpYUJveCIsICJDcm9wQm94IiwgIkJsZWVkQm94IiwgIlRyaW1Cb3giLCAiQXJ0Qm94IiwgIlJlc291cmNlcyIsICJBbm5vdHMiLCAiUGFyZW50IiwgIlVzZXJVbml0Il0pIHsKICAgICAgcGFnZURpY3QuZGVsZXRlKGtleSk7CiAgICB9CiAgICBjb25zdCBsYXN0UmVmID0gdGhpcy5uZXdSZWZDb3VudDsKICAgIGF3YWl0IHRoaXMuI2NvbGxlY3REZXBlbmRlbmNpZXMocGFnZURpY3QsIGZhbHNlLCB4cmVmKTsKICAgIHBhZ2VEaWN0LnNldCgiUm90YXRlIiwgcm90YXRlKTsKICAgIHBhZ2VEaWN0LnNldCgiTWVkaWFCb3giLCBtZWRpYUJveCk7CiAgICBmb3IgKGNvbnN0IGJveE5hbWUgb2YgWyJDcm9wQm94IiwgIkJsZWVkQm94IiwgIlRyaW1Cb3giLCAiQXJ0Qm94Il0pIHsKICAgICAgY29uc3QgYm94ID0gcGFnZS5nZXRCb3VuZGluZ0JveChib3hOYW1lKTsKICAgICAgaWYgKGJveD8uc29tZSgodmFsdWUsIGluZGV4KSA9PiB2YWx1ZSAhPT0gbWVkaWFCb3hbaW5kZXhdKSkgewogICAgICAgIHBhZ2VEaWN0LnNldChib3hOYW1lLCBib3gpOwogICAgICB9CiAgICB9CiAgICBjb25zdCB1c2VyVW5pdCA9IHBhZ2UudXNlclVuaXQ7CiAgICBpZiAodXNlclVuaXQgIT09IDEpIHsKICAgICAgcGFnZURpY3Quc2V0KCJVc2VyVW5pdCIsIHVzZXJVbml0KTsKICAgIH0KICAgIHBhZ2VEaWN0LnNldElmRGljdCgiUmVzb3VyY2VzIiwgYXdhaXQgdGhpcy4jY29sbGVjdERlcGVuZGVuY2llcyhyZXNvdXJjZXMsIHRydWUsIHhyZWYpKTsKICAgIGlmIChhbm5vdGF0aW9ucykgewogICAgICBjb25zdCBuZXdBbm5vdGF0aW9ucyA9IGF3YWl0IHRoaXMuI2NvbGxlY3REZXBlbmRlbmNpZXMoYW5ub3RhdGlvbnMsIHRydWUsIHhyZWYpOwogICAgICB0aGlzLiNmaXhOYW1lZERlc3RpbmF0aW9ucyhuZXdBbm5vdGF0aW9ucywgZGVkdXBOYW1lZERlc3RpbmF0aW9ucyk7CiAgICAgIHBhZ2VEaWN0LnNldElmQXJyYXkoIkFubm90cyIsIG5ld0Fubm90YXRpb25zKTsKICAgIH0KICAgIGlmICh0aGlzLnVzZU9iamVjdFN0cmVhbXMpIHsKICAgICAgY29uc3QgbmV3TGFzdFJlZiA9IHRoaXMubmV3UmVmQ291bnQ7CiAgICAgIGNvbnN0IHBhZ2VPYmplY3RSZWZzID0gW107CiAgICAgIGZvciAobGV0IGkgPSBsYXN0UmVmOyBpIDwgbmV3TGFzdFJlZjsgaSsrKSB7CiAgICAgICAgY29uc3Qgb2JqID0gdGhpcy54cmVmW2ldOwogICAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgcGFnZU9iamVjdFJlZnMucHVzaChSZWYuZ2V0KGksIDApKTsKICAgICAgfQogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhZ2VPYmplY3RSZWZzLmxlbmd0aDsgaSArPSAweGZmZmYpIHsKICAgICAgICBjb25zdCBvYmpTdHJlYW1SZWYgPSB0aGlzLm5ld1JlZjsKICAgICAgICB0aGlzLm9ialN0cmVhbVJlZnMuYWRkKG9ialN0cmVhbVJlZi5udW0pOwogICAgICAgIHRoaXMueHJlZltvYmpTdHJlYW1SZWYubnVtXSA9IHBhZ2VPYmplY3RSZWZzLnNsaWNlKGksIGkgKyAweGZmZmYpOwogICAgICB9CiAgICB9CiAgICB0aGlzLmN1cnJlbnREb2N1bWVudCA9IG51bGw7CiAgICByZXR1cm4gcGFnZVJlZjsKICB9CiAgI21ha2VQYWdlVHJlZSgpIHsKICAgIGNvbnN0IHsKICAgICAgbmV3UGFnZXM6IHBhZ2VzLAogICAgICByb290RGljdCwKICAgICAgcGFnZXNSZWYsCiAgICAgIHBhZ2VzRGljdAogICAgfSA9IHRoaXM7CiAgICByb290RGljdC5zZXQoIlBhZ2VzIiwgcGFnZXNSZWYpOwogICAgcGFnZXNEaWN0LnNldElmTmFtZSgiVHlwZSIsICJQYWdlcyIpOwogICAgcGFnZXNEaWN0LnNldCgiQ291bnQiLCBwYWdlcy5sZW5ndGgpOwogICAgY29uc3QgbWF4TGVhdmVzID0gTUFYX0xFQVZFU19QRVJfUEFHRVNfTk9ERSA8PSAxID8gcGFnZXMubGVuZ3RoIDogTUFYX0xFQVZFU19QRVJfUEFHRVNfTk9ERTsKICAgIGNvbnN0IHN0YWNrID0gW3sKICAgICAgZGljdDogcGFnZXNEaWN0LAogICAgICBraWRzOiBwYWdlcywKICAgICAgcGFyZW50UmVmOiBwYWdlc1JlZgogICAgfV07CiAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICBjb25zdCB7CiAgICAgICAgZGljdCwKICAgICAgICBraWRzLAogICAgICAgIHBhcmVudFJlZgogICAgICB9ID0gc3RhY2sucG9wKCk7CiAgICAgIGlmIChraWRzLmxlbmd0aCA8PSBtYXhMZWF2ZXMpIHsKICAgICAgICBkaWN0LnNldCgiS2lkcyIsIGtpZHMpOwogICAgICAgIGZvciAoY29uc3QgcmVmIG9mIGtpZHMpIHsKICAgICAgICAgIHRoaXMueHJlZltyZWYubnVtXS5zZXQoIlBhcmVudCIsIHBhcmVudFJlZik7CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IE1hdGgubWF4KG1heExlYXZlcywgTWF0aC5jZWlsKGtpZHMubGVuZ3RoIC8gbWF4TGVhdmVzKSk7CiAgICAgIGNvbnN0IGtpZHNDaHVua3MgPSBbXTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBraWRzLmxlbmd0aDsgaSArPSBjaHVua1NpemUpIHsKICAgICAgICBraWRzQ2h1bmtzLnB1c2goa2lkcy5zbGljZShpLCBpICsgY2h1bmtTaXplKSk7CiAgICAgIH0KICAgICAgY29uc3Qga2lkc1JlZnMgPSBbXTsKICAgICAgZGljdC5zZXQoIktpZHMiLCBraWRzUmVmcyk7CiAgICAgIGZvciAoY29uc3QgY2h1bmsgb2Yga2lkc0NodW5rcykgewogICAgICAgIGNvbnN0IFtraWRSZWYsIGtpZERpY3RdID0gdGhpcy5uZXdEaWN0OwogICAgICAgIGtpZHNSZWZzLnB1c2goa2lkUmVmKTsKICAgICAgICBraWREaWN0LnNldElmTmFtZSgiVHlwZSIsICJQYWdlcyIpOwogICAgICAgIGtpZERpY3Quc2V0KCJQYXJlbnQiLCBwYXJlbnRSZWYpOwogICAgICAgIGtpZERpY3Quc2V0KCJDb3VudCIsIGNodW5rLmxlbmd0aCk7CiAgICAgICAgc3RhY2sucHVzaCh7CiAgICAgICAgICBkaWN0OiBraWREaWN0LAogICAgICAgICAga2lkczogY2h1bmssCiAgICAgICAgICBwYXJlbnRSZWY6IGtpZFJlZgogICAgICAgIH0pOwogICAgICB9CiAgICB9CiAgfQogICNtYWtlTmFtZU51bVRyZWUobWFwLCBhcmVOYW1lcykgewogICAgY29uc3QgYWxsRW50cmllcyA9IG1hcC5zb3J0KGFyZU5hbWVzID8gKFtrZXlBXSwgW2tleUJdKSA9PiBrZXlBLmxvY2FsZUNvbXBhcmUoa2V5QikgOiAoW2tleUFdLCBba2V5Ql0pID0+IGtleUEgLSBrZXlCKTsKICAgIGNvbnN0IG1heExlYXZlcyA9IE1BWF9JTl9OQU1FX1RSRUVfTk9ERSA8PSAxID8gYWxsRW50cmllcy5sZW5ndGggOiBNQVhfSU5fTkFNRV9UUkVFX05PREU7CiAgICBjb25zdCBbdHJlZVJlZiwgdHJlZURpY3RdID0gdGhpcy5uZXdEaWN0OwogICAgY29uc3Qgc3RhY2sgPSBbewogICAgICBkaWN0OiB0cmVlRGljdCwKICAgICAgZW50cmllczogYWxsRW50cmllcwogICAgfV07CiAgICBjb25zdCB2YWx1ZVR5cGUgPSBhcmVOYW1lcyA/ICJOYW1lcyIgOiAiTnVtcyI7CiAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICBjb25zdCB7CiAgICAgICAgZGljdCwKICAgICAgICBlbnRyaWVzCiAgICAgIH0gPSBzdGFjay5wb3AoKTsKICAgICAgaWYgKGVudHJpZXMubGVuZ3RoIDw9IG1heExlYXZlcykgewogICAgICAgIGRpY3Quc2V0KCJMaW1pdHMiLCBbZW50cmllc1swXVswXSwgZW50cmllcy5hdCgtMSlbMF1dKTsKICAgICAgICBkaWN0LnNldCh2YWx1ZVR5cGUsIGVudHJpZXMuZmxhdCgpKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBlbnRyaWVzQ2h1bmtzID0gW107CiAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IE1hdGgubWF4KG1heExlYXZlcywgTWF0aC5jZWlsKGVudHJpZXMubGVuZ3RoIC8gbWF4TGVhdmVzKSk7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZW50cmllcy5sZW5ndGg7IGkgKz0gY2h1bmtTaXplKSB7CiAgICAgICAgZW50cmllc0NodW5rcy5wdXNoKGVudHJpZXMuc2xpY2UoaSwgaSArIGNodW5rU2l6ZSkpOwogICAgICB9CiAgICAgIGNvbnN0IGVudHJpZXNSZWZzID0gW107CiAgICAgIGRpY3Quc2V0KCJLaWRzIiwgZW50cmllc1JlZnMpOwogICAgICBmb3IgKGNvbnN0IGNodW5rIG9mIGVudHJpZXNDaHVua3MpIHsKICAgICAgICBjb25zdCBbZW50cmllc1JlZiwgZW50cmllc0RpY3RdID0gdGhpcy5uZXdEaWN0OwogICAgICAgIGVudHJpZXNSZWZzLnB1c2goZW50cmllc1JlZik7CiAgICAgICAgZW50cmllc0RpY3Quc2V0KCJMaW1pdHMiLCBbY2h1bmtbMF1bMF0sIGNodW5rLmF0KC0xKVswXV0pOwogICAgICAgIHN0YWNrLnB1c2goewogICAgICAgICAgZGljdDogZW50cmllc0RpY3QsCiAgICAgICAgICBlbnRyaWVzOiBjaHVuawogICAgICAgIH0pOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJlZVJlZjsKICB9CiAgI21ha2VQYWdlTGFiZWxzVHJlZSgpIHsKICAgIGNvbnN0IHsKICAgICAgcGFnZUxhYmVscwogICAgfSA9IHRoaXM7CiAgICBpZiAoIXBhZ2VMYWJlbHMgfHwgcGFnZUxhYmVscy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgewogICAgICByb290RGljdAogICAgfSA9IHRoaXM7CiAgICBjb25zdCBwYWdlTGFiZWxzUmVmID0gdGhpcy4jbWFrZU5hbWVOdW1UcmVlKHRoaXMucGFnZUxhYmVscywgZmFsc2UpOwogICAgcm9vdERpY3Quc2V0KCJQYWdlTGFiZWxzIiwgcGFnZUxhYmVsc1JlZik7CiAgfQogICNtYWtlRGVzdGluYXRpb25zVHJlZSgpIHsKICAgIGNvbnN0IHsKICAgICAgbmFtZWREZXN0aW5hdGlvbnMKICAgIH0gPSB0aGlzOwogICAgaWYgKG5hbWVkRGVzdGluYXRpb25zLnNpemUgPT09IDApIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKCF0aGlzLm5hbWVzRGljdCkgewogICAgICBbdGhpcy5uYW1lc1JlZiwgdGhpcy5uYW1lc0RpY3RdID0gdGhpcy5uZXdEaWN0OwogICAgICB0aGlzLnJvb3REaWN0LnNldCgiTmFtZXMiLCB0aGlzLm5hbWVzUmVmKTsKICAgIH0KICAgIHRoaXMubmFtZXNEaWN0LnNldCgiRGVzdHMiLCB0aGlzLiNtYWtlTmFtZU51bVRyZWUoQXJyYXkuZnJvbShuYW1lZERlc3RpbmF0aW9ucy5lbnRyaWVzKCkpLCB0cnVlKSk7CiAgfQogICNtYWtlU3RydWN0VHJlZSgpIHsKICAgIGNvbnN0IHsKICAgICAgc3RydWN0VHJlZUtpZHMKICAgIH0gPSB0aGlzOwogICAgaWYgKCFzdHJ1Y3RUcmVlS2lkcyB8fCBzdHJ1Y3RUcmVlS2lkcy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgewogICAgICByb290RGljdAogICAgfSA9IHRoaXM7CiAgICBjb25zdCBzdHJ1Y3RUcmVlUmVmID0gdGhpcy5uZXdSZWY7CiAgICBjb25zdCBzdHJ1Y3RUcmVlID0gdGhpcy54cmVmW3N0cnVjdFRyZWVSZWYubnVtXSA9IG5ldyBEaWN0KCk7CiAgICBzdHJ1Y3RUcmVlLnNldElmTmFtZSgiVHlwZSIsICJTdHJ1Y3RUcmVlUm9vdCIpOwogICAgc3RydWN0VHJlZS5zZXRJZkFycmF5KCJLIiwgc3RydWN0VHJlZUtpZHMpOwogICAgZm9yIChjb25zdCBraWRSZWYgb2Ygc3RydWN0VHJlZUtpZHMpIHsKICAgICAgY29uc3Qga2lkID0gdGhpcy54cmVmW2tpZFJlZi5udW1dOwogICAgICBjb25zdCB0eXBlID0ga2lkLmdldCgiVHlwZSIpOwogICAgICBpZiAoIXR5cGUgfHwgaXNOYW1lKHR5cGUsICJTdHJ1Y3RFbGVtIikpIHsKICAgICAgICBraWQuc2V0KCJQIiwgc3RydWN0VHJlZVJlZik7CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzLnBhcmVudFRyZWUuc2l6ZSA+IDApIHsKICAgICAgY29uc3QgcGFyZW50VHJlZVJlZiA9IHRoaXMuI21ha2VOYW1lTnVtVHJlZShBcnJheS5mcm9tKHRoaXMucGFyZW50VHJlZS5lbnRyaWVzKCkpLCBmYWxzZSk7CiAgICAgIGNvbnN0IHBhcmVudFRyZWUgPSB0aGlzLnhyZWZbcGFyZW50VHJlZVJlZi5udW1dOwogICAgICBwYXJlbnRUcmVlLnNldElmTmFtZSgiVHlwZSIsICJQYXJlbnRUcmVlIik7CiAgICAgIHN0cnVjdFRyZWUuc2V0KCJQYXJlbnRUcmVlIiwgcGFyZW50VHJlZVJlZik7CiAgICAgIHN0cnVjdFRyZWUuc2V0KCJQYXJlbnRUcmVlTmV4dEtleSIsIHRoaXMucGFyZW50VHJlZS5zaXplKTsKICAgIH0KICAgIGlmICh0aGlzLmlkVHJlZS5zaXplID4gMCkgewogICAgICBjb25zdCBpZFRyZWVSZWYgPSB0aGlzLiNtYWtlTmFtZU51bVRyZWUoQXJyYXkuZnJvbSh0aGlzLmlkVHJlZS5lbnRyaWVzKCkpLCB0cnVlKTsKICAgICAgY29uc3QgaWRUcmVlID0gdGhpcy54cmVmW2lkVHJlZVJlZi5udW1dOwogICAgICBpZFRyZWUuc2V0SWZOYW1lKCJUeXBlIiwgIklEVHJlZSIpOwogICAgICBzdHJ1Y3RUcmVlLnNldCgiSURUcmVlIiwgaWRUcmVlUmVmKTsKICAgIH0KICAgIGlmICh0aGlzLmNsYXNzTWFwLnNpemUgPiAwKSB7CiAgICAgIGNvbnN0IGNsYXNzTWFwUmVmID0gdGhpcy5uZXdSZWY7CiAgICAgIHRoaXMueHJlZltjbGFzc01hcFJlZi5udW1dID0gdGhpcy5jbGFzc01hcDsKICAgICAgc3RydWN0VHJlZS5zZXQoIkNsYXNzTWFwIiwgY2xhc3NNYXBSZWYpOwogICAgfQogICAgaWYgKHRoaXMucm9sZU1hcC5zaXplID4gMCkgewogICAgICBjb25zdCByb2xlTWFwUmVmID0gdGhpcy5uZXdSZWY7CiAgICAgIHRoaXMueHJlZltyb2xlTWFwUmVmLm51bV0gPSB0aGlzLnJvbGVNYXA7CiAgICAgIHN0cnVjdFRyZWUuc2V0KCJSb2xlTWFwIiwgcm9sZU1hcFJlZik7CiAgICB9CiAgICBpZiAodGhpcy5uYW1lc3BhY2VzLnNpemUgPiAwKSB7CiAgICAgIGNvbnN0IG5hbWVzcGFjZXNSZWYgPSB0aGlzLm5ld1JlZjsKICAgICAgdGhpcy54cmVmW25hbWVzcGFjZXNSZWYubnVtXSA9IEFycmF5LmZyb20odGhpcy5uYW1lc3BhY2VzLnZhbHVlcygpKTsKICAgICAgc3RydWN0VHJlZS5zZXQoIk5hbWVzcGFjZXMiLCBuYW1lc3BhY2VzUmVmKTsKICAgIH0KICAgIGlmICh0aGlzLnN0cnVjdFRyZWVBRi5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IHN0cnVjdFRyZWVBRlJlZiA9IHRoaXMubmV3UmVmOwogICAgICB0aGlzLnhyZWZbc3RydWN0VHJlZUFGUmVmLm51bV0gPSB0aGlzLnN0cnVjdFRyZWVBRjsKICAgICAgc3RydWN0VHJlZS5zZXQoIkFGIiwgc3RydWN0VHJlZUFGUmVmKTsKICAgIH0KICAgIGlmICh0aGlzLnN0cnVjdFRyZWVQcm9udW5jaWF0aW9uTGV4aWNvbi5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IHN0cnVjdFRyZWVQcm9udW5jaWF0aW9uTGV4aWNvblJlZiA9IHRoaXMubmV3UmVmOwogICAgICB0aGlzLnhyZWZbc3RydWN0VHJlZVByb251bmNpYXRpb25MZXhpY29uUmVmLm51bV0gPSB0aGlzLnN0cnVjdFRyZWVQcm9udW5jaWF0aW9uTGV4aWNvbjsKICAgICAgc3RydWN0VHJlZS5zZXQoIlByb251bmNpYXRpb25MZXhpY29uIiwgc3RydWN0VHJlZVByb251bmNpYXRpb25MZXhpY29uUmVmKTsKICAgIH0KICAgIHJvb3REaWN0LnNldCgiU3RydWN0VHJlZVJvb3QiLCBzdHJ1Y3RUcmVlUmVmKTsKICB9CiAgYXN5bmMgI21ha2VSb290KCkgewogICAgY29uc3QgewogICAgICByb290RGljdAogICAgfSA9IHRoaXM7CiAgICByb290RGljdC5zZXRJZk5hbWUoIlR5cGUiLCAiQ2F0YWxvZyIpOwogICAgcm9vdERpY3Quc2V0SWZOYW1lKCJWZXJzaW9uIiwgdGhpcy52ZXJzaW9uKTsKICAgIHRoaXMuI21ha2VQYWdlVHJlZSgpOwogICAgdGhpcy4jbWFrZVBhZ2VMYWJlbHNUcmVlKCk7CiAgICB0aGlzLiNtYWtlRGVzdGluYXRpb25zVHJlZSgpOwogICAgdGhpcy4jbWFrZVN0cnVjdFRyZWUoKTsKICB9CiAgI21ha2VJbmZvKCkgewogICAgY29uc3QgaW5mb01hcCA9IG5ldyBNYXAoKTsKICAgIGlmICh0aGlzLmhhc1NpbmdsZUZpbGUpIHsKICAgICAgY29uc3QgewogICAgICAgIHhyZWY6IHsKICAgICAgICAgIHRyYWlsZXIKICAgICAgICB9CiAgICAgIH0gPSB0aGlzLm9sZFBhZ2VzWzBdLmRvY3VtZW50RGF0YS5kb2N1bWVudDsKICAgICAgY29uc3Qgb2xkSW5mb0RpY3QgPSB0cmFpbGVyLmdldCgiSW5mbyIpOwogICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBvbGRJbmZvRGljdCB8fCBbXSkgewogICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICBpbmZvTWFwLnNldChrZXksIHN0cmluZ1RvUERGU3RyaW5nKHZhbHVlKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpbmZvTWFwLmRlbGV0ZSgiTW9kRGF0ZSIpOwogICAgaW5mb01hcC5zZXQoIkNyZWF0aW9uRGF0ZSIsIGdldE1vZGlmaWNhdGlvbkRhdGUoKSk7CiAgICBpbmZvTWFwLnNldCgiQ3JlYXRvciIsICJQREYuanMiKTsKICAgIGluZm9NYXAuc2V0KCJQcm9kdWNlciIsICJGaXJlZm94Iik7CiAgICBpZiAodGhpcy5hdXRob3IpIHsKICAgICAgaW5mb01hcC5zZXQoIkF1dGhvciIsIHRoaXMuYXV0aG9yKTsKICAgIH0KICAgIGlmICh0aGlzLnRpdGxlKSB7CiAgICAgIGluZm9NYXAuc2V0KCJUaXRsZSIsIHRoaXMudGl0bGUpOwogICAgfQogICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgaW5mb01hcCkgewogICAgICB0aGlzLmluZm9EaWN0LnNldChrZXksIHN0cmluZ1RvQXNjaWlPclVURjE2QkUodmFsdWUpKTsKICAgIH0KICAgIHJldHVybiBpbmZvTWFwOwogIH0KICBhc3luYyAjbWFrZUVuY3J5cHQoKSB7CiAgICBpZiAoIXRoaXMuaGFzU2luZ2xlRmlsZSkgewogICAgICByZXR1cm4gW251bGwsIG51bGwsIG51bGxdOwogICAgfQogICAgY29uc3QgewogICAgICBkb2N1bWVudERhdGEKICAgIH0gPSB0aGlzLm9sZFBhZ2VzWzBdOwogICAgY29uc3QgewogICAgICBkb2N1bWVudDogewogICAgICAgIHhyZWY6IHsKICAgICAgICAgIHRyYWlsZXIsCiAgICAgICAgICBlbmNyeXB0CiAgICAgICAgfQogICAgICB9CiAgICB9ID0gZG9jdW1lbnREYXRhOwogICAgaWYgKCF0cmFpbGVyLmhhcygiRW5jcnlwdCIpKSB7CiAgICAgIHJldHVybiBbbnVsbCwgbnVsbCwgbnVsbF07CiAgICB9CiAgICBjb25zdCBlbmNyeXB0RGljdCA9IHRyYWlsZXIuZ2V0KCJFbmNyeXB0Iik7CiAgICBpZiAoIShlbmNyeXB0RGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybiBbbnVsbCwgbnVsbCwgbnVsbF07CiAgICB9CiAgICB0aGlzLmN1cnJlbnREb2N1bWVudCA9IGRvY3VtZW50RGF0YTsKICAgIGNvbnN0IHJlc3VsdCA9IFthd2FpdCB0aGlzLiNjbG9uZU9iamVjdChlbmNyeXB0RGljdCwgdHJhaWxlci54cmVmKSwgZW5jcnlwdCwgdHJhaWxlci5nZXQoIklEIildOwogICAgdGhpcy5jdXJyZW50RG9jdW1lbnQgPSBudWxsOwogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgYXN5bmMgI2NyZWF0ZUNoYW5nZXMoKSB7CiAgICBjb25zdCBjaGFuZ2VzID0gbmV3IFJlZlNldENhY2hlKCk7CiAgICBjaGFuZ2VzLnB1dChSZWYuZ2V0KDAsIDB4ZmZmZiksIHsKICAgICAgZGF0YTogbnVsbAogICAgfSk7CiAgICBmb3IgKGxldCBpID0gMSwgaWkgPSB0aGlzLnhyZWYubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBpZiAodGhpcy5vYmpTdHJlYW1SZWZzPy5oYXMoaSkpIHsKICAgICAgICBhd2FpdCB0aGlzLiNjcmVhdGVPYmplY3RTdHJlYW0oUmVmLmdldChpLCAwKSwgdGhpcy54cmVmW2ldLCBjaGFuZ2VzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjaGFuZ2VzLnB1dChSZWYuZ2V0KGksIDApLCB7CiAgICAgICAgICBkYXRhOiB0aGlzLnhyZWZbaV0KICAgICAgICB9KTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIFtjaGFuZ2VzLCB0aGlzLm5ld1JlZl07CiAgfQogIGFzeW5jICNjcmVhdGVPYmplY3RTdHJlYW0ob2JqU3RyZWFtUmVmLCBvYmpSZWZzLCBjaGFuZ2VzKSB7CiAgICBjb25zdCBzdHJlYW1CdWZmZXIgPSBbIiJdOwogICAgY29uc3Qgb2JqT2Zmc2V0cyA9IFtdOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICBjb25zdCBidWZmZXIgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IG9ialJlZnMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBvYmpSZWYgPSBvYmpSZWZzW2ldOwogICAgICBjaGFuZ2VzLnB1dChvYmpSZWYsIHsKICAgICAgICBkYXRhOiBudWxsLAogICAgICAgIG9ialN0cmVhbVJlZiwKICAgICAgICBpbmRleDogaQogICAgICB9KTsKICAgICAgb2JqT2Zmc2V0cy5wdXNoKGAke29ialJlZi5udW19ICR7b2Zmc2V0fWApOwogICAgICBjb25zdCBkYXRhID0gdGhpcy54cmVmW29ialJlZi5udW1dOwogICAgICBhd2FpdCB3cml0ZVZhbHVlKGRhdGEsIGJ1ZmZlciwgbnVsbCk7CiAgICAgIGNvbnN0IG9iaiA9IGJ1ZmZlci5qb2luKCIiKTsKICAgICAgYnVmZmVyLmxlbmd0aCA9IDA7CiAgICAgIHN0cmVhbUJ1ZmZlci5wdXNoKG9iaik7CiAgICAgIG9mZnNldCArPSBvYmoubGVuZ3RoICsgMTsKICAgIH0KICAgIHN0cmVhbUJ1ZmZlclswXSA9IG9iak9mZnNldHMuam9pbigiXG4iKTsKICAgIGNvbnN0IG9ialN0cmVhbSA9IG5ldyBTdHJpbmdTdHJlYW0oc3RyZWFtQnVmZmVyLmpvaW4oIlxuIikpOwogICAgY29uc3Qgb2JqU3RyZWFtRGljdCA9IG9ialN0cmVhbS5kaWN0ID0gbmV3IERpY3QoKTsKICAgIG9ialN0cmVhbURpY3Quc2V0SWZOYW1lKCJUeXBlIiwgIk9ialN0bSIpOwogICAgb2JqU3RyZWFtRGljdC5zZXQoIk4iLCBvYmpSZWZzLmxlbmd0aCk7CiAgICBvYmpTdHJlYW1EaWN0LnNldCgiRmlyc3QiLCBzdHJlYW1CdWZmZXJbMF0ubGVuZ3RoICsgMSk7CiAgICBjaGFuZ2VzLnB1dChvYmpTdHJlYW1SZWYsIHsKICAgICAgZGF0YTogb2JqU3RyZWFtCiAgICB9KTsKICB9CiAgYXN5bmMgd3JpdGVQREYoKSB7CiAgICBhd2FpdCB0aGlzLiNtYWtlUm9vdCgpOwogICAgY29uc3QgaW5mb01hcCA9IHRoaXMuI21ha2VJbmZvKCk7CiAgICBjb25zdCBbZW5jcnlwdFJlZiwgZW5jcnlwdCwgZmlsZUlkc10gPSBhd2FpdCB0aGlzLiNtYWtlRW5jcnlwdCgpOwogICAgY29uc3QgW2NoYW5nZXMsIHhyZWZUYWJsZVJlZl0gPSBhd2FpdCB0aGlzLiNjcmVhdGVDaGFuZ2VzKCk7CiAgICBjb25zdCBoZWFkZXIgPSBbLi4uYCVQREYtJHt0aGlzLnZlcnNpb259XG4lYC5zcGxpdCgiIikubWFwKGMgPT4gYy5jaGFyQ29kZUF0KDApKSwgMHhmYSwgMHhkZSwgMHhmYSwgMHhjZV07CiAgICByZXR1cm4gaW5jcmVtZW50YWxVcGRhdGUoewogICAgICBvcmlnaW5hbERhdGE6IG5ldyBVaW50OEFycmF5KGhlYWRlciksCiAgICAgIGNoYW5nZXMsCiAgICAgIHhyZWZJbmZvOiB7CiAgICAgICAgc3RhcnRYUmVmOiBudWxsLAogICAgICAgIHJvb3RSZWY6IHRoaXMucm9vdFJlZiwKICAgICAgICBpbmZvUmVmOiB0aGlzLmluZm9SZWYsCiAgICAgICAgZW5jcnlwdFJlZiwKICAgICAgICBuZXdSZWY6IHhyZWZUYWJsZVJlZiwKICAgICAgICBmaWxlSWRzOiBmaWxlSWRzIHx8IFtudWxsLCBudWxsXSwKICAgICAgICBpbmZvTWFwCiAgICAgIH0sCiAgICAgIHVzZVhyZWZTdHJlYW06IHRoaXMudXNlT2JqZWN0U3RyZWFtcywKICAgICAgeHJlZjogewogICAgICAgIGVuY3J5cHQsCiAgICAgICAgZW5jcnlwdFJlZgogICAgICB9CiAgICB9KTsKICB9Cn0KCjsvLyAuL3NyYy9zaGFyZWQvYmFzZV9wZGZfc3RyZWFtLmpzCgpjbGFzcyBCYXNlUERGU3RyZWFtIHsKICAjUERGU3RyZWFtUmVhZGVyID0gbnVsbDsKICAjUERGU3RyZWFtUmFuZ2VSZWFkZXIgPSBudWxsOwogIF9mdWxsUmVhZGVyID0gbnVsbDsKICBfcmFuZ2VSZWFkZXJzID0gbmV3IFNldCgpOwogIF9zb3VyY2UgPSBudWxsOwogIGNvbnN0cnVjdG9yKHNvdXJjZSwgUERGU3RyZWFtUmVhZGVyLCBQREZTdHJlYW1SYW5nZVJlYWRlcikgewogICAgdGhpcy5fc291cmNlID0gc291cmNlOwogICAgdGhpcy4jUERGU3RyZWFtUmVhZGVyID0gUERGU3RyZWFtUmVhZGVyOwogICAgdGhpcy4jUERGU3RyZWFtUmFuZ2VSZWFkZXIgPSBQREZTdHJlYW1SYW5nZVJlYWRlcjsKICB9CiAgZ2V0IF9wcm9ncmVzc2l2ZURhdGFMZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5fZnVsbFJlYWRlcj8uX2xvYWRlZCA/PyAwOwogIH0KICBnZXRGdWxsUmVhZGVyKCkgewogICAgYXNzZXJ0KCF0aGlzLl9mdWxsUmVhZGVyLCAiQmFzZVBERlN0cmVhbS5nZXRGdWxsUmVhZGVyIGNhbiBvbmx5IGJlIGNhbGxlZCBvbmNlLiIpOwogICAgcmV0dXJuIHRoaXMuX2Z1bGxSZWFkZXIgPSBuZXcgdGhpcy4jUERGU3RyZWFtUmVhZGVyKHRoaXMpOwogIH0KICBnZXRSYW5nZVJlYWRlcihiZWdpbiwgZW5kKSB7CiAgICBpZiAoZW5kIDw9IHRoaXMuX3Byb2dyZXNzaXZlRGF0YUxlbmd0aCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHJlYWRlciA9IG5ldyB0aGlzLiNQREZTdHJlYW1SYW5nZVJlYWRlcih0aGlzLCBiZWdpbiwgZW5kKTsKICAgIHRoaXMuX3JhbmdlUmVhZGVycy5hZGQocmVhZGVyKTsKICAgIHJldHVybiByZWFkZXI7CiAgfQogIGNhbmNlbEFsbFJlcXVlc3RzKHJlYXNvbikgewogICAgdGhpcy5fZnVsbFJlYWRlcj8uY2FuY2VsKHJlYXNvbik7CiAgICBmb3IgKGNvbnN0IHJlYWRlciBvZiBuZXcgU2V0KHRoaXMuX3JhbmdlUmVhZGVycykpIHsKICAgICAgcmVhZGVyLmNhbmNlbChyZWFzb24pOwogICAgfQogIH0KfQpjbGFzcyBCYXNlUERGU3RyZWFtUmVhZGVyIHsKICBvblByb2dyZXNzID0gbnVsbDsKICBfY29udGVudExlbmd0aCA9IDA7CiAgX2ZpbGVuYW1lID0gbnVsbDsKICBfaGVhZGVyc0NhcGFiaWxpdHkgPSBQcm9taXNlLndpdGhSZXNvbHZlcnMoKTsKICBfaXNSYW5nZVN1cHBvcnRlZCA9IGZhbHNlOwogIF9pc1N0cmVhbWluZ1N1cHBvcnRlZCA9IGZhbHNlOwogIF9sb2FkZWQgPSAwOwogIF9zdHJlYW0gPSBudWxsOwogIGNvbnN0cnVjdG9yKHN0cmVhbSkgewogICAgdGhpcy5fc3RyZWFtID0gc3RyZWFtOwogIH0KICBnZXQgaGVhZGVyc1JlYWR5KCkgewogICAgcmV0dXJuIHRoaXMuX2hlYWRlcnNDYXBhYmlsaXR5LnByb21pc2U7CiAgfQogIGdldCBmaWxlbmFtZSgpIHsKICAgIHJldHVybiB0aGlzLl9maWxlbmFtZTsKICB9CiAgZ2V0IGNvbnRlbnRMZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5fY29udGVudExlbmd0aDsKICB9CiAgZ2V0IGlzUmFuZ2VTdXBwb3J0ZWQoKSB7CiAgICByZXR1cm4gdGhpcy5faXNSYW5nZVN1cHBvcnRlZDsKICB9CiAgZ2V0IGlzU3RyZWFtaW5nU3VwcG9ydGVkKCkgewogICAgcmV0dXJuIHRoaXMuX2lzU3RyZWFtaW5nU3VwcG9ydGVkOwogIH0KICBhc3luYyByZWFkKCkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgcmVhZGAgY2FsbGVkIik7CiAgfQogIGNhbmNlbChyZWFzb24pIHsKICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYGNhbmNlbGAgY2FsbGVkIik7CiAgfQp9CmNsYXNzIEJhc2VQREZTdHJlYW1SYW5nZVJlYWRlciB7CiAgX3N0cmVhbSA9IG51bGw7CiAgY29uc3RydWN0b3Ioc3RyZWFtLCBiZWdpbiwgZW5kKSB7CiAgICB0aGlzLl9zdHJlYW0gPSBzdHJlYW07CiAgfQogIGFzeW5jIHJlYWQoKSB7CiAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGByZWFkYCBjYWxsZWQiKTsKICB9CiAgY2FuY2VsKHJlYXNvbikgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgY2FuY2VsYCBjYWxsZWQiKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3dvcmtlcl9zdHJlYW0uanMKCmNsYXNzIFBERldvcmtlclN0cmVhbSBleHRlbmRzIEJhc2VQREZTdHJlYW0gewogIGNvbnN0cnVjdG9yKHNvdXJjZSkgewogICAgc3VwZXIoc291cmNlLCBQREZXb3JrZXJTdHJlYW1SZWFkZXIsIFBERldvcmtlclN0cmVhbVJhbmdlUmVhZGVyKTsKICB9Cn0KY2xhc3MgUERGV29ya2VyU3RyZWFtUmVhZGVyIGV4dGVuZHMgQmFzZVBERlN0cmVhbVJlYWRlciB7CiAgX3JlYWRlciA9IG51bGw7CiAgY29uc3RydWN0b3Ioc3RyZWFtKSB7CiAgICBzdXBlcihzdHJlYW0pOwogICAgY29uc3QgewogICAgICBtc2dIYW5kbGVyCiAgICB9ID0gc3RyZWFtLl9zb3VyY2U7CiAgICBjb25zdCByZWFkYWJsZVN0cmVhbSA9IG1zZ0hhbmRsZXIuc2VuZFdpdGhTdHJlYW0oIkdldFJlYWRlciIpOwogICAgdGhpcy5fcmVhZGVyID0gcmVhZGFibGVTdHJlYW0uZ2V0UmVhZGVyKCk7CiAgICBtc2dIYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiUmVhZGVySGVhZGVyc1JlYWR5IikudGhlbihkYXRhID0+IHsKICAgICAgdGhpcy5fY29udGVudExlbmd0aCA9IGRhdGEuY29udGVudExlbmd0aDsKICAgICAgdGhpcy5faXNTdHJlYW1pbmdTdXBwb3J0ZWQgPSBkYXRhLmlzU3RyZWFtaW5nU3VwcG9ydGVkOwogICAgICB0aGlzLl9pc1JhbmdlU3VwcG9ydGVkID0gZGF0YS5pc1JhbmdlU3VwcG9ydGVkOwogICAgICB0aGlzLl9oZWFkZXJzQ2FwYWJpbGl0eS5yZXNvbHZlKCk7CiAgICB9LCB0aGlzLl9oZWFkZXJzQ2FwYWJpbGl0eS5yZWplY3QpOwogIH0KICBhc3luYyByZWFkKCkgewogICAgY29uc3QgewogICAgICB2YWx1ZSwKICAgICAgZG9uZQogICAgfSA9IGF3YWl0IHRoaXMuX3JlYWRlci5yZWFkKCk7CiAgICBpZiAoZG9uZSkgewogICAgICByZXR1cm4gewogICAgICAgIHZhbHVlOiB1bmRlZmluZWQsCiAgICAgICAgZG9uZTogdHJ1ZQogICAgICB9OwogICAgfQogICAgcmV0dXJuIHsKICAgICAgdmFsdWU6IHZhbHVlLmJ1ZmZlciwKICAgICAgZG9uZTogZmFsc2UKICAgIH07CiAgfQogIGNhbmNlbChyZWFzb24pIHsKICAgIHRoaXMuX3JlYWRlci5jYW5jZWwocmVhc29uKTsKICB9Cn0KY2xhc3MgUERGV29ya2VyU3RyZWFtUmFuZ2VSZWFkZXIgZXh0ZW5kcyBCYXNlUERGU3RyZWFtUmFuZ2VSZWFkZXIgewogIF9yZWFkZXIgPSBudWxsOwogIGNvbnN0cnVjdG9yKHN0cmVhbSwgYmVnaW4sIGVuZCkgewogICAgc3VwZXIoc3RyZWFtLCBiZWdpbiwgZW5kKTsKICAgIGNvbnN0IHsKICAgICAgbXNnSGFuZGxlcgogICAgfSA9IHN0cmVhbS5fc291cmNlOwogICAgY29uc3QgcmVhZGFibGVTdHJlYW0gPSBtc2dIYW5kbGVyLnNlbmRXaXRoU3RyZWFtKCJHZXRSYW5nZVJlYWRlciIsIHsKICAgICAgYmVnaW4sCiAgICAgIGVuZAogICAgfSk7CiAgICB0aGlzLl9yZWFkZXIgPSByZWFkYWJsZVN0cmVhbS5nZXRSZWFkZXIoKTsKICB9CiAgYXN5bmMgcmVhZCgpIHsKICAgIGNvbnN0IHsKICAgICAgdmFsdWUsCiAgICAgIGRvbmUKICAgIH0gPSBhd2FpdCB0aGlzLl9yZWFkZXIucmVhZCgpOwogICAgaWYgKGRvbmUpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICB2YWx1ZTogdW5kZWZpbmVkLAogICAgICAgIGRvbmU6IHRydWUKICAgICAgfTsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIHZhbHVlOiB2YWx1ZS5idWZmZXIsCiAgICAgIGRvbmU6IGZhbHNlCiAgICB9OwogIH0KICBjYW5jZWwocmVhc29uKSB7CiAgICB0aGlzLl9yZWFkZXIuY2FuY2VsKHJlYXNvbik7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS93b3JrZXIuanMKCgoKCgoKCgoKCgpjbGFzcyBXb3JrZXJUYXNrIHsKICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICB0aGlzLm5hbWUgPSBuYW1lOwogICAgdGhpcy50ZXJtaW5hdGVkID0gZmFsc2U7CiAgICB0aGlzLl9jYXBhYmlsaXR5ID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7CiAgfQogIGdldCBmaW5pc2hlZCgpIHsKICAgIHJldHVybiB0aGlzLl9jYXBhYmlsaXR5LnByb21pc2U7CiAgfQogIGZpbmlzaCgpIHsKICAgIHRoaXMuX2NhcGFiaWxpdHkucmVzb2x2ZSgpOwogIH0KICB0ZXJtaW5hdGUoKSB7CiAgICB0aGlzLnRlcm1pbmF0ZWQgPSB0cnVlOwogIH0KICBlbnN1cmVOb3RUZXJtaW5hdGVkKCkgewogICAgaWYgKHRoaXMudGVybWluYXRlZCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIldvcmtlciB0YXNrIHdhcyB0ZXJtaW5hdGVkIik7CiAgICB9CiAgfQp9CmNsYXNzIFdvcmtlck1lc3NhZ2VIYW5kbGVyIHsKICBzdGF0aWMgewogICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICJ1bmRlZmluZWQiICYmICFpc05vZGVKUyAmJiB0eXBlb2Ygc2VsZiAhPT0gInVuZGVmaW5lZCIgJiYgdHlwZW9mIHNlbGYucG9zdE1lc3NhZ2UgPT09ICJmdW5jdGlvbiIgJiYgIm9ubWVzc2FnZSIgaW4gc2VsZikgewogICAgICB0aGlzLmluaXRpYWxpemVGcm9tUG9ydChzZWxmKTsKICAgIH0KICB9CiAgc3RhdGljIHNldHVwKGhhbmRsZXIsIHBvcnQpIHsKICAgIGxldCB0ZXN0TWVzc2FnZVByb2Nlc3NlZCA9IGZhbHNlOwogICAgaGFuZGxlci5vbigidGVzdCIsIGRhdGEgPT4gewogICAgICBpZiAodGVzdE1lc3NhZ2VQcm9jZXNzZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGVzdE1lc3NhZ2VQcm9jZXNzZWQgPSB0cnVlOwogICAgICBoYW5kbGVyLnNlbmQoInRlc3QiLCBkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oImNvbmZpZ3VyZSIsIGRhdGEgPT4gewogICAgICBzZXRWZXJib3NpdHlMZXZlbChkYXRhLnZlcmJvc2l0eSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldERvY1JlcXVlc3QiLCBkYXRhID0+IHRoaXMuY3JlYXRlRG9jdW1lbnRIYW5kbGVyKGRhdGEsIHBvcnQpKTsKICB9CiAgc3RhdGljIGNyZWF0ZURvY3VtZW50SGFuZGxlcihkb2NQYXJhbXMsIHBvcnQpIHsKICAgIGxldCBwZGZNYW5hZ2VyOwogICAgbGV0IHRlcm1pbmF0ZWQgPSBmYWxzZTsKICAgIGxldCBjYW5jZWxYSFJzID0gbnVsbDsKICAgIGNvbnN0IFdvcmtlclRhc2tzID0gbmV3IFNldCgpOwogICAgY29uc3QgdmVyYm9zaXR5ID0gZ2V0VmVyYm9zaXR5TGV2ZWwoKTsKICAgIGNvbnN0IHsKICAgICAgZG9jSWQsCiAgICAgIGFwaVZlcnNpb24KICAgIH0gPSBkb2NQYXJhbXM7CiAgICBjb25zdCB3b3JrZXJWZXJzaW9uID0gIjUuNC42MjQiOwogICAgaWYgKGFwaVZlcnNpb24gIT09IHdvcmtlclZlcnNpb24pIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgQVBJIHZlcnNpb24gIiR7YXBpVmVyc2lvbn0iIGRvZXMgbm90IG1hdGNoIGAgKyBgdGhlIFdvcmtlciB2ZXJzaW9uICIke3dvcmtlclZlcnNpb259Ii5gKTsKICAgIH0KICAgIGNvbnN0IGJ1aWxkTXNnID0gKHR5cGUsIHByb3ApID0+IGBUaGUgXGAke3R5cGV9LnByb3RvdHlwZVxgIGNvbnRhaW5zIHVuZXhwZWN0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0eSBgICsgYCIke3Byb3B9IiwgdGh1cyBicmVha2luZyBlLmcuIFxgZm9yLi4uaW5cYCBpdGVyYXRpb24gb2YgJHt0eXBlfXMuYDsKICAgIGZvciAoY29uc3QgcHJvcCBpbiB7fSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYnVpbGRNc2coIk9iamVjdCIsIHByb3ApKTsKICAgIH0KICAgIGZvciAoY29uc3QgcHJvcCBpbiBbXSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYnVpbGRNc2coIkFycmF5IiwgcHJvcCkpOwogICAgfQogICAgY29uc3Qgd29ya2VySGFuZGxlck5hbWUgPSBkb2NJZCArICJfd29ya2VyIjsKICAgIGxldCBoYW5kbGVyID0gbmV3IE1lc3NhZ2VIYW5kbGVyKHdvcmtlckhhbmRsZXJOYW1lLCBkb2NJZCwgcG9ydCk7CiAgICBmdW5jdGlvbiBlbnN1cmVOb3RUZXJtaW5hdGVkKCkgewogICAgICBpZiAodGVybWluYXRlZCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiV29ya2VyIHdhcyB0ZXJtaW5hdGVkIik7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIHN0YXJ0V29ya2VyVGFzayh0YXNrKSB7CiAgICAgIFdvcmtlclRhc2tzLmFkZCh0YXNrKTsKICAgIH0KICAgIGZ1bmN0aW9uIGZpbmlzaFdvcmtlclRhc2sodGFzaykgewogICAgICB0YXNrLmZpbmlzaCgpOwogICAgICBXb3JrZXJUYXNrcy5kZWxldGUodGFzayk7CiAgICB9CiAgICBhc3luYyBmdW5jdGlvbiBsb2FkRG9jdW1lbnQocmVjb3ZlcnlNb2RlKSB7CiAgICAgIGF3YWl0IHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJjaGVja0hlYWRlciIpOwogICAgICBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZURvYygicGFyc2VTdGFydFhSZWYiKTsKICAgICAgYXdhaXQgcGRmTWFuYWdlci5lbnN1cmVEb2MoInBhcnNlIiwgW3JlY292ZXJ5TW9kZV0pOwogICAgICBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZURvYygiY2hlY2tGaXJzdFBhZ2UiLCBbcmVjb3ZlcnlNb2RlXSk7CiAgICAgIGF3YWl0IHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJjaGVja0xhc3RQYWdlIiwgW3JlY292ZXJ5TW9kZV0pOwogICAgICBjb25zdCBpc1B1cmVYZmEgPSBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZURvYygiaXNQdXJlWGZhIik7CiAgICAgIGlmIChpc1B1cmVYZmEpIHsKICAgICAgICBjb25zdCB0YXNrID0gbmV3IFdvcmtlclRhc2soImxvYWRYZmFSZXNvdXJjZXMiKTsKICAgICAgICBzdGFydFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgYXdhaXQgcGRmTWFuYWdlci5lbnN1cmVEb2MoImxvYWRYZmFSZXNvdXJjZXMiLCBbaGFuZGxlciwgdGFza10pOwogICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgIH0KICAgICAgY29uc3QgW251bVBhZ2VzLCBmaW5nZXJwcmludHNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW3BkZk1hbmFnZXIuZW5zdXJlRG9jKCJudW1QYWdlcyIpLCBwZGZNYW5hZ2VyLmVuc3VyZURvYygiZmluZ2VycHJpbnRzIildKTsKICAgICAgY29uc3QgaHRtbEZvclhmYSA9IGlzUHVyZVhmYSA/IGF3YWl0IHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJodG1sRm9yWGZhIikgOiBudWxsOwogICAgICByZXR1cm4gewogICAgICAgIG51bVBhZ2VzLAogICAgICAgIGZpbmdlcnByaW50cywKICAgICAgICBodG1sRm9yWGZhCiAgICAgIH07CiAgICB9CiAgICBhc3luYyBmdW5jdGlvbiBnZXRQZGZNYW5hZ2VyKHsKICAgICAgZGF0YSwKICAgICAgcGFzc3dvcmQsCiAgICAgIGRpc2FibGVBdXRvRmV0Y2gsCiAgICAgIHJhbmdlQ2h1bmtTaXplLAogICAgICBsZW5ndGgsCiAgICAgIGRvY0Jhc2VVcmwsCiAgICAgIGVuYWJsZVhmYSwKICAgICAgZXZhbHVhdG9yT3B0aW9ucwogICAgfSkgewogICAgICBjb25zdCBwZGZNYW5hZ2VyQXJncyA9IHsKICAgICAgICBzb3VyY2U6IG51bGwsCiAgICAgICAgZGlzYWJsZUF1dG9GZXRjaCwKICAgICAgICBkb2NCYXNlVXJsLAogICAgICAgIGRvY0lkLAogICAgICAgIGVuYWJsZVhmYSwKICAgICAgICBldmFsdWF0b3JPcHRpb25zLAogICAgICAgIGhhbmRsZXIsCiAgICAgICAgbGVuZ3RoLAogICAgICAgIHBhc3N3b3JkLAogICAgICAgIHJhbmdlQ2h1bmtTaXplCiAgICAgIH07CiAgICAgIGlmIChkYXRhKSB7CiAgICAgICAgcGRmTWFuYWdlckFyZ3Muc291cmNlID0gZGF0YTsKICAgICAgICByZXR1cm4gbmV3IExvY2FsUGRmTWFuYWdlcihwZGZNYW5hZ2VyQXJncyk7CiAgICAgIH0KICAgICAgY29uc3QgcGRmU3RyZWFtID0gbmV3IFBERldvcmtlclN0cmVhbSh7CiAgICAgICAgICBtc2dIYW5kbGVyOiBoYW5kbGVyCiAgICAgICAgfSksCiAgICAgICAgZnVsbFJlYWRlciA9IHBkZlN0cmVhbS5nZXRGdWxsUmVhZGVyKCk7CiAgICAgIGNvbnN0IHBkZk1hbmFnZXJDYXBhYmlsaXR5ID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7CiAgICAgIGxldCBuZXdQZGZNYW5hZ2VyLAogICAgICAgIGNhY2hlZENodW5rcyA9IFtdLAogICAgICAgIGxvYWRlZCA9IDA7CiAgICAgIGZ1bGxSZWFkZXIuaGVhZGVyc1JlYWR5LnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIGlmICghZnVsbFJlYWRlci5pc1JhbmdlU3VwcG9ydGVkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIHBkZk1hbmFnZXJBcmdzLnNvdXJjZSA9IHBkZlN0cmVhbTsKICAgICAgICBwZGZNYW5hZ2VyQXJncy5sZW5ndGggPSBmdWxsUmVhZGVyLmNvbnRlbnRMZW5ndGg7CiAgICAgICAgcGRmTWFuYWdlckFyZ3MuZGlzYWJsZUF1dG9GZXRjaCB8fD0gZnVsbFJlYWRlci5pc1N0cmVhbWluZ1N1cHBvcnRlZDsKICAgICAgICBuZXdQZGZNYW5hZ2VyID0gbmV3IE5ldHdvcmtQZGZNYW5hZ2VyKHBkZk1hbmFnZXJBcmdzKTsKICAgICAgICBmb3IgKGNvbnN0IGNodW5rIG9mIGNhY2hlZENodW5rcykgewogICAgICAgICAgbmV3UGRmTWFuYWdlci5zZW5kUHJvZ3Jlc3NpdmVEYXRhKGNodW5rKTsKICAgICAgICB9CiAgICAgICAgY2FjaGVkQ2h1bmtzID0gW107CiAgICAgICAgcGRmTWFuYWdlckNhcGFiaWxpdHkucmVzb2x2ZShuZXdQZGZNYW5hZ2VyKTsKICAgICAgICBjYW5jZWxYSFJzID0gbnVsbDsKICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgIHBkZk1hbmFnZXJDYXBhYmlsaXR5LnJlamVjdChyZWFzb24pOwogICAgICAgIGNhbmNlbFhIUnMgPSBudWxsOwogICAgICB9KTsKICAgICAgbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgIGNvbnN0IHJlYWRDaHVuayA9IGZ1bmN0aW9uICh7CiAgICAgICAgICB2YWx1ZSwKICAgICAgICAgIGRvbmUKICAgICAgICB9KSB7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBlbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgICAgICAgIGlmIChkb25lKSB7CiAgICAgICAgICAgICAgaWYgKCFuZXdQZGZNYW5hZ2VyKSB7CiAgICAgICAgICAgICAgICBjb25zdCBwZGZGaWxlID0gYXJyYXlCdWZmZXJzVG9CeXRlcyhjYWNoZWRDaHVua3MpOwogICAgICAgICAgICAgICAgY2FjaGVkQ2h1bmtzID0gW107CiAgICAgICAgICAgICAgICBpZiAobGVuZ3RoICYmIHBkZkZpbGUubGVuZ3RoICE9PSBsZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgd2FybigicmVwb3J0ZWQgSFRUUCBsZW5ndGggaXMgZGlmZmVyZW50IGZyb20gYWN0dWFsIik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBwZGZNYW5hZ2VyQXJncy5zb3VyY2UgPSBwZGZGaWxlOwogICAgICAgICAgICAgICAgbmV3UGRmTWFuYWdlciA9IG5ldyBMb2NhbFBkZk1hbmFnZXIocGRmTWFuYWdlckFyZ3MpOwogICAgICAgICAgICAgICAgcGRmTWFuYWdlckNhcGFiaWxpdHkucmVzb2x2ZShuZXdQZGZNYW5hZ2VyKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY2FuY2VsWEhScyA9IG51bGw7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxvYWRlZCArPSB2YWx1ZS5ieXRlTGVuZ3RoOwogICAgICAgICAgICBpZiAoIWZ1bGxSZWFkZXIuaXNTdHJlYW1pbmdTdXBwb3J0ZWQpIHsKICAgICAgICAgICAgICBoYW5kbGVyLnNlbmQoIkRvY1Byb2dyZXNzIiwgewogICAgICAgICAgICAgICAgbG9hZGVkLAogICAgICAgICAgICAgICAgdG90YWw6IE1hdGgubWF4KGxvYWRlZCwgZnVsbFJlYWRlci5jb250ZW50TGVuZ3RoIHx8IDApCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKG5ld1BkZk1hbmFnZXIpIHsKICAgICAgICAgICAgICBuZXdQZGZNYW5hZ2VyLnNlbmRQcm9ncmVzc2l2ZURhdGEodmFsdWUpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGNhY2hlZENodW5rcy5wdXNoKHZhbHVlKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmdWxsUmVhZGVyLnJlYWQoKS50aGVuKHJlYWRDaHVuaywgcmVqZWN0KTsKICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgcmVqZWN0KGUpOwogICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgZnVsbFJlYWRlci5yZWFkKCkudGhlbihyZWFkQ2h1bmssIHJlamVjdCk7CiAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlKSB7CiAgICAgICAgcGRmTWFuYWdlckNhcGFiaWxpdHkucmVqZWN0KGUpOwogICAgICAgIGNhbmNlbFhIUnMgPSBudWxsOwogICAgICB9KTsKICAgICAgY2FuY2VsWEhScyA9IHJlYXNvbiA9PiB7CiAgICAgICAgcGRmU3RyZWFtLmNhbmNlbEFsbFJlcXVlc3RzKHJlYXNvbik7CiAgICAgIH07CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgfQogICAgZnVuY3Rpb24gc2V0dXBEb2MoZGF0YSkgewogICAgICBmdW5jdGlvbiBvblN1Y2Nlc3MoZG9jKSB7CiAgICAgICAgZW5zdXJlTm90VGVybWluYXRlZCgpOwogICAgICAgIGhhbmRsZXIuc2VuZCgiR2V0RG9jIiwgewogICAgICAgICAgcGRmSW5mbzogZG9jCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgZnVuY3Rpb24gb25GYWlsdXJlKGV4KSB7CiAgICAgICAgZW5zdXJlTm90VGVybWluYXRlZCgpOwogICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhc3N3b3JkRXhjZXB0aW9uKSB7CiAgICAgICAgICBjb25zdCB0YXNrID0gbmV3IFdvcmtlclRhc2soYFBhc3N3b3JkRXhjZXB0aW9uOiByZXNwb25zZSAke2V4LmNvZGV9YCk7CiAgICAgICAgICBzdGFydFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICBoYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiUGFzc3dvcmRSZXF1ZXN0IiwgZXgpLnRoZW4oZnVuY3Rpb24gKHsKICAgICAgICAgICAgcGFzc3dvcmQKICAgICAgICAgIH0pIHsKICAgICAgICAgICAgZmluaXNoV29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgICAgcGRmTWFuYWdlci51cGRhdGVQYXNzd29yZChwYXNzd29yZCk7CiAgICAgICAgICAgIHBkZk1hbmFnZXJSZWFkeSgpOwogICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKCkgewogICAgICAgICAgICBmaW5pc2hXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgICBoYW5kbGVyLnNlbmQoIkRvY0V4Y2VwdGlvbiIsIGV4KTsKICAgICAgICAgIH0pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBoYW5kbGVyLnNlbmQoIkRvY0V4Y2VwdGlvbiIsIHdyYXBSZWFzb24oZXgpKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgZnVuY3Rpb24gcGRmTWFuYWdlclJlYWR5KCkgewogICAgICAgIGVuc3VyZU5vdFRlcm1pbmF0ZWQoKTsKICAgICAgICBsb2FkRG9jdW1lbnQoZmFsc2UpLnRoZW4ob25TdWNjZXNzLCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICBlbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgICAgICBpZiAoIShyZWFzb24gaW5zdGFuY2VvZiBYUmVmUGFyc2VFeGNlcHRpb24pKSB7CiAgICAgICAgICAgIG9uRmFpbHVyZShyZWFzb24pOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CiAgICAgICAgICBwZGZNYW5hZ2VyLnJlcXVlc3RMb2FkZWRTdHJlYW0oKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgZW5zdXJlTm90VGVybWluYXRlZCgpOwogICAgICAgICAgICBsb2FkRG9jdW1lbnQodHJ1ZSkudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7CiAgICAgICAgICB9KTsKICAgICAgICB9KTsKICAgICAgfQogICAgICBlbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgIGdldFBkZk1hbmFnZXIoZGF0YSkudGhlbihmdW5jdGlvbiAobmV3UGRmTWFuYWdlcikgewogICAgICAgIGlmICh0ZXJtaW5hdGVkKSB7CiAgICAgICAgICBuZXdQZGZNYW5hZ2VyLnRlcm1pbmF0ZShuZXcgQWJvcnRFeGNlcHRpb24oIldvcmtlciB3YXMgdGVybWluYXRlZC4iKSk7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIldvcmtlciB3YXMgdGVybWluYXRlZCIpOwogICAgICAgIH0KICAgICAgICBwZGZNYW5hZ2VyID0gbmV3UGRmTWFuYWdlcjsKICAgICAgICBwZGZNYW5hZ2VyLnJlcXVlc3RMb2FkZWRTdHJlYW0odHJ1ZSkudGhlbihzdHJlYW0gPT4gewogICAgICAgICAgaGFuZGxlci5zZW5kKCJEYXRhTG9hZGVkIiwgewogICAgICAgICAgICBsZW5ndGg6IHN0cmVhbS5ieXRlcy5ieXRlTGVuZ3RoCiAgICAgICAgICB9KTsKICAgICAgICB9KTsKICAgICAgfSkudGhlbihwZGZNYW5hZ2VyUmVhZHksIG9uRmFpbHVyZSk7CiAgICB9CiAgICBoYW5kbGVyLm9uKCJHZXRQYWdlIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZ2V0UGFnZShkYXRhLnBhZ2VJbmRleCkudGhlbihmdW5jdGlvbiAocGFnZSkgewogICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbcGRmTWFuYWdlci5lbnN1cmUocGFnZSwgInJvdGF0ZSIpLCBwZGZNYW5hZ2VyLmVuc3VyZShwYWdlLCAicmVmIiksIHBkZk1hbmFnZXIuZW5zdXJlKHBhZ2UsICJ1c2VyVW5pdCIpLCBwZGZNYW5hZ2VyLmVuc3VyZShwYWdlLCAidmlldyIpXSkudGhlbihmdW5jdGlvbiAoW3JvdGF0ZSwgcmVmLCB1c2VyVW5pdCwgdmlld10pIHsKICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIHJvdGF0ZSwKICAgICAgICAgICAgcmVmLAogICAgICAgICAgICByZWZTdHI6IHJlZj8udG9TdHJpbmcoKSA/PyBudWxsLAogICAgICAgICAgICB1c2VyVW5pdCwKICAgICAgICAgICAgdmlldwogICAgICAgICAgfTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldFBhZ2VJbmRleCIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIGNvbnN0IHBhZ2VSZWYgPSBSZWYuZ2V0KGRhdGEubnVtLCBkYXRhLmdlbik7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImdldFBhZ2VJbmRleCIsIFtwYWdlUmVmXSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldERlc3RpbmF0aW9ucyIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImRlc3RpbmF0aW9ucyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXREZXN0aW5hdGlvbiIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImdldERlc3RpbmF0aW9uIiwgW2RhdGEuaWRdKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0UGFnZUxhYmVscyIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coInBhZ2VMYWJlbHMiKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0UGFnZUxheW91dCIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coInBhZ2VMYXlvdXQiKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0UGFnZU1vZGUiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJwYWdlTW9kZSIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRWaWV3ZXJQcmVmZXJlbmNlcyIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coInZpZXdlclByZWZlcmVuY2VzIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldE9wZW5BY3Rpb24iLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJvcGVuQWN0aW9uIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldEF0dGFjaG1lbnRzIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiYXR0YWNobWVudHMiKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0RG9jSlNBY3Rpb25zIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygianNBY3Rpb25zIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldFBhZ2VKU0FjdGlvbnMiLCBmdW5jdGlvbiAoewogICAgICBwYWdlSW5kZXgKICAgIH0pIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZ2V0UGFnZShwYWdlSW5kZXgpLnRoZW4ocGFnZSA9PiBwZGZNYW5hZ2VyLmVuc3VyZShwYWdlLCAianNBY3Rpb25zIikpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRBbm5vdGF0aW9uc0J5VHlwZSIsIGFzeW5jIGZ1bmN0aW9uICh7CiAgICAgIHR5cGVzLAogICAgICBwYWdlSW5kZXhlc1RvU2tpcAogICAgfSkgewogICAgICBjb25zdCBbbnVtUGFnZXMsIGFubm90YXRpb25HbG9iYWxzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtwZGZNYW5hZ2VyLmVuc3VyZURvYygibnVtUGFnZXMiKSwgcGRmTWFuYWdlci5lbnN1cmVEb2MoImFubm90YXRpb25HbG9iYWxzIildKTsKICAgICAgaWYgKCFhbm5vdGF0aW9uR2xvYmFscykgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IHBhZ2VQcm9taXNlcyA9IFtdOwogICAgICBjb25zdCBhbm5vdGF0aW9uUHJvbWlzZXMgPSBbXTsKICAgICAgbGV0IHRhc2sgPSBudWxsOwogICAgICB0cnkgewogICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IG51bVBhZ2VzOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgaWYgKHBhZ2VJbmRleGVzVG9Ta2lwPy5oYXMoaSkpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIXRhc2spIHsKICAgICAgICAgICAgdGFzayA9IG5ldyBXb3JrZXJUYXNrKCJHZXRBbm5vdGF0aW9uc0J5VHlwZSIpOwogICAgICAgICAgICBzdGFydFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICB9CiAgICAgICAgICBwYWdlUHJvbWlzZXMucHVzaChwZGZNYW5hZ2VyLmdldFBhZ2UoaSkudGhlbihhc3luYyBwYWdlID0+IHsKICAgICAgICAgICAgaWYgKCFwYWdlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIFtdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBwYWdlLmNvbGxlY3RBbm5vdGF0aW9uc0J5VHlwZShoYW5kbGVyLCB0YXNrLCB0eXBlcywgYW5ub3RhdGlvblByb21pc2VzLCBhbm5vdGF0aW9uR2xvYmFscykgfHwgW107CiAgICAgICAgICB9KSk7CiAgICAgICAgfQogICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHBhZ2VQcm9taXNlcyk7CiAgICAgICAgY29uc3QgYW5ub3RhdGlvbnMgPSBhd2FpdCBQcm9taXNlLmFsbChhbm5vdGF0aW9uUHJvbWlzZXMpOwogICAgICAgIHJldHVybiBhbm5vdGF0aW9ucy5maWx0ZXIoYSA9PiAhIWEpOwogICAgICB9IGZpbmFsbHkgewogICAgICAgIGlmICh0YXNrKSB7CiAgICAgICAgICBmaW5pc2hXb3JrZXJUYXNrKHRhc2spOwogICAgICAgIH0KICAgICAgfQogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRPdXRsaW5lIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiZG9jdW1lbnRPdXRsaW5lIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldE9wdGlvbmFsQ29udGVudENvbmZpZyIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coIm9wdGlvbmFsQ29udGVudENvbmZpZyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRQZXJtaXNzaW9ucyIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coInBlcm1pc3Npb25zIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldE1ldGFkYXRhIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtwZGZNYW5hZ2VyLmVuc3VyZURvYygiZG9jdW1lbnRJbmZvIiksIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygibWV0YWRhdGEiKSwgcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJoYXNTdHJ1Y3RUcmVlIildKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0TWFya0luZm8iLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJtYXJrSW5mbyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXREYXRhIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIucmVxdWVzdExvYWRlZFN0cmVhbSgpLnRoZW4oc3RyZWFtID0+IHN0cmVhbS5ieXRlcyk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldEFubm90YXRpb25zIiwgZnVuY3Rpb24gKHsKICAgICAgcGFnZUluZGV4LAogICAgICBpbnRlbnQKICAgIH0pIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZ2V0UGFnZShwYWdlSW5kZXgpLnRoZW4oZnVuY3Rpb24gKHBhZ2UpIHsKICAgICAgICBjb25zdCB0YXNrID0gbmV3IFdvcmtlclRhc2soYEdldEFubm90YXRpb25zOiBwYWdlICR7cGFnZUluZGV4fWApOwogICAgICAgIHN0YXJ0V29ya2VyVGFzayh0YXNrKTsKICAgICAgICByZXR1cm4gcGFnZS5nZXRBbm5vdGF0aW9uc0RhdGEoaGFuZGxlciwgdGFzaywgaW50ZW50KS50aGVuKGRhdGEgPT4gewogICAgICAgICAgZmluaXNoV29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgIHJldHVybiBkYXRhOwogICAgICAgIH0sIHJlYXNvbiA9PiB7CiAgICAgICAgICBmaW5pc2hXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgdGhyb3cgcmVhc29uOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0RmllbGRPYmplY3RzIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJmaWVsZE9iamVjdHMiKS50aGVuKGZpZWxkT2JqZWN0cyA9PiBmaWVsZE9iamVjdHM/LmFsbEZpZWxkcyB8fCBudWxsKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiSGFzSlNBY3Rpb25zIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJoYXNKU0FjdGlvbnMiKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0Q2FsY3VsYXRpb25PcmRlcklkcyIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZURvYygiY2FsY3VsYXRpb25PcmRlcklkcyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJFeHRyYWN0UGFnZXMiLCBhc3luYyBmdW5jdGlvbiAoewogICAgICBwYWdlSW5mb3MKICAgIH0pIHsKICAgICAgaWYgKCFwYWdlSW5mb3MpIHsKICAgICAgICB3YXJuKCJleHRyYWN0UGFnZXM6IG5vdGhpbmcgdG8gZXh0cmFjdC4iKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBpZiAoIUFycmF5LmlzQXJyYXkocGFnZUluZm9zKSkgewogICAgICAgIHBhZ2VJbmZvcyA9IFtwYWdlSW5mb3NdOwogICAgICB9CiAgICAgIGxldCBuZXdEb2N1bWVudElkID0gMDsKICAgICAgZm9yIChjb25zdCBwYWdlSW5mbyBvZiBwYWdlSW5mb3MpIHsKICAgICAgICBpZiAocGFnZUluZm8uZG9jdW1lbnQgPT09IG51bGwpIHsKICAgICAgICAgIHBhZ2VJbmZvLmRvY3VtZW50ID0gcGRmTWFuYWdlci5wZGZEb2N1bWVudDsKICAgICAgICB9IGVsc2UgaWYgKEFycmF5QnVmZmVyLmlzVmlldyhwYWdlSW5mby5kb2N1bWVudCkpIHsKICAgICAgICAgIGNvbnN0IG1hbmFnZXIgPSBuZXcgTG9jYWxQZGZNYW5hZ2VyKHsKICAgICAgICAgICAgc291cmNlOiBwYWdlSW5mby5kb2N1bWVudCwKICAgICAgICAgICAgZG9jSWQ6IGAke2RvY0lkfV9leHRyYWN0UGFnZXNfJHtuZXdEb2N1bWVudElkKyt9YCwKICAgICAgICAgICAgaGFuZGxlciwKICAgICAgICAgICAgcGFzc3dvcmQ6IHBhZ2VJbmZvLnBhc3N3b3JkID8/IG51bGwsCiAgICAgICAgICAgIGV2YWx1YXRvck9wdGlvbnM6IE9iamVjdC5hc3NpZ24oe30sIHBkZk1hbmFnZXIuZXZhbHVhdG9yT3B0aW9ucykKICAgICAgICAgIH0pOwogICAgICAgICAgbGV0IHJlY292ZXJ5TW9kZSA9IGZhbHNlOwogICAgICAgICAgbGV0IGlzVmFsaWQgPSB0cnVlOwogICAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBhd2FpdCBtYW5hZ2VyLnJlcXVlc3RMb2FkZWRTdHJlYW0oKTsKICAgICAgICAgICAgICBhd2FpdCBtYW5hZ2VyLmVuc3VyZURvYygiY2hlY2tIZWFkZXIiKTsKICAgICAgICAgICAgICBhd2FpdCBtYW5hZ2VyLmVuc3VyZURvYygicGFyc2VTdGFydFhSZWYiKTsKICAgICAgICAgICAgICBhd2FpdCBtYW5hZ2VyLmVuc3VyZURvYygicGFyc2UiLCBbcmVjb3ZlcnlNb2RlXSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFhSZWZQYXJzZUV4Y2VwdGlvbikgewogICAgICAgICAgICAgICAgaWYgKHJlY292ZXJ5TW9kZSA9PT0gZmFsc2UpIHsKICAgICAgICAgICAgICAgICAgcmVjb3ZlcnlNb2RlID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBpc1ZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgIHdhcm4oImV4dHJhY3RQYWdlczogWFJlZlBhcnNlRXhjZXB0aW9uLiIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0gZWxzZSBpZiAoZSBpbnN0YW5jZW9mIFBhc3N3b3JkRXhjZXB0aW9uKSB7CiAgICAgICAgICAgICAgICBjb25zdCB0YXNrID0gbmV3IFdvcmtlclRhc2soYFBhc3N3b3JkRXhjZXB0aW9uOiByZXNwb25zZSAke2UuY29kZX1gKTsKICAgICAgICAgICAgICAgIHN0YXJ0V29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICBwYXNzd29yZAogICAgICAgICAgICAgICAgICB9ID0gYXdhaXQgaGFuZGxlci5zZW5kV2l0aFByb21pc2UoIlBhc3N3b3JkUmVxdWVzdCIsIGUpOwogICAgICAgICAgICAgICAgICBtYW5hZ2VyLnVwZGF0ZVBhc3N3b3JkKHBhc3N3b3JkKTsKICAgICAgICAgICAgICAgIH0gY2F0Y2ggewogICAgICAgICAgICAgICAgICBpc1ZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgIHdhcm4oImV4dHJhY3RQYWdlczogaW52YWxpZCBwYXNzd29yZC4iKTsKICAgICAgICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGlzVmFsaWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgIHdhcm4oImV4dHJhY3RQYWdlczogaW52YWxpZCBkb2N1bWVudC4iKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKCFpc1ZhbGlkKSB7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmICghaXNWYWxpZCkgewogICAgICAgICAgICBwYWdlSW5mby5kb2N1bWVudCA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBpc1B1cmVYZmEgPSBhd2FpdCBtYW5hZ2VyLmVuc3VyZURvYygiaXNQdXJlWGZhIik7CiAgICAgICAgICBpZiAoaXNQdXJlWGZhKSB7CiAgICAgICAgICAgIHBhZ2VJbmZvLmRvY3VtZW50ID0gbnVsbDsKICAgICAgICAgICAgd2FybigiZXh0cmFjdFBhZ2VzIGRvZXMgbm90IHN1cHBvcnQgcHVyZSBYRkEgZG9jdW1lbnRzLiIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcGFnZUluZm8uZG9jdW1lbnQgPSBtYW5hZ2VyLnBkZkRvY3VtZW50OwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB3YXJuKCJleHRyYWN0UGFnZXM6IGludmFsaWQgZG9jdW1lbnQuIik7CiAgICAgICAgfQogICAgICB9CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3QgcGRmRWRpdG9yID0gbmV3IFBERkVkaXRvcigpOwogICAgICAgIGNvbnN0IGJ1ZmZlciA9IGF3YWl0IHBkZkVkaXRvci5leHRyYWN0UGFnZXMocGFnZUluZm9zKTsKICAgICAgICByZXR1cm4gYnVmZmVyOwogICAgICB9IGNhdGNoIChyZWFzb24pIHsKICAgICAgICBjb25zb2xlLmVycm9yKHJlYXNvbik7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH0pOwogICAgaGFuZGxlci5vbigiU2F2ZURvY3VtZW50IiwgYXN5bmMgZnVuY3Rpb24gKHsKICAgICAgaXNQdXJlWGZhLAogICAgICBudW1QYWdlcywKICAgICAgYW5ub3RhdGlvblN0b3JhZ2UsCiAgICAgIGZpbGVuYW1lCiAgICB9KSB7CiAgICAgIGNvbnN0IGdsb2JhbFByb21pc2VzID0gW3BkZk1hbmFnZXIucmVxdWVzdExvYWRlZFN0cmVhbSgpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImFjcm9Gb3JtIiksIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiYWNyb0Zvcm1SZWYiKSwgcGRmTWFuYWdlci5lbnN1cmVEb2MoInN0YXJ0WFJlZiIpLCBwZGZNYW5hZ2VyLmVuc3VyZURvYygieHJlZiIpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coInN0cnVjdFRyZWVSb290IildOwogICAgICBjb25zdCBjaGFuZ2VzID0gbmV3IFJlZlNldENhY2hlKCk7CiAgICAgIGNvbnN0IHByb21pc2VzID0gW107CiAgICAgIGNvbnN0IG5ld0Fubm90YXRpb25zQnlQYWdlID0gIWlzUHVyZVhmYSA/IGdldE5ld0Fubm90YXRpb25zTWFwKGFubm90YXRpb25TdG9yYWdlKSA6IG51bGw7CiAgICAgIGNvbnN0IFtzdHJlYW0sIGFjcm9Gb3JtLCBhY3JvRm9ybVJlZiwgc3RhcnRYUmVmLCB4cmVmLCBfc3RydWN0VHJlZVJvb3RdID0gYXdhaXQgUHJvbWlzZS5hbGwoZ2xvYmFsUHJvbWlzZXMpOwogICAgICBjb25zdCBjYXRhbG9nUmVmID0geHJlZi50cmFpbGVyLmdldFJhdygiUm9vdCIpIHx8IG51bGw7CiAgICAgIGxldCBzdHJ1Y3RUcmVlUm9vdDsKICAgICAgaWYgKG5ld0Fubm90YXRpb25zQnlQYWdlKSB7CiAgICAgICAgaWYgKCFfc3RydWN0VHJlZVJvb3QpIHsKICAgICAgICAgIGlmIChhd2FpdCBTdHJ1Y3RUcmVlUm9vdC5jYW5DcmVhdGVTdHJ1Y3R1cmVUcmVlKHsKICAgICAgICAgICAgY2F0YWxvZ1JlZiwKICAgICAgICAgICAgcGRmTWFuYWdlciwKICAgICAgICAgICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UKICAgICAgICAgIH0pKSB7CiAgICAgICAgICAgIHN0cnVjdFRyZWVSb290ID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGF3YWl0IF9zdHJ1Y3RUcmVlUm9vdC5jYW5VcGRhdGVTdHJ1Y3RUcmVlKHsKICAgICAgICAgIHBkZk1hbmFnZXIsCiAgICAgICAgICBuZXdBbm5vdGF0aW9uc0J5UGFnZQogICAgICAgIH0pKSB7CiAgICAgICAgICBzdHJ1Y3RUcmVlUm9vdCA9IF9zdHJ1Y3RUcmVlUm9vdDsKICAgICAgICB9CiAgICAgICAgY29uc3QgaW1hZ2VQcm9taXNlcyA9IEFubm90YXRpb25GYWN0b3J5LmdlbmVyYXRlSW1hZ2VzKGFubm90YXRpb25TdG9yYWdlLnZhbHVlcygpLCB4cmVmLCBwZGZNYW5hZ2VyLmV2YWx1YXRvck9wdGlvbnMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpOwogICAgICAgIGNvbnN0IG5ld0Fubm90YXRpb25Qcm9taXNlcyA9IHN0cnVjdFRyZWVSb290ID09PSB1bmRlZmluZWQgPyBwcm9taXNlcyA6IFtdOwogICAgICAgIGZvciAoY29uc3QgW3BhZ2VJbmRleCwgYW5ub3RhdGlvbnNdIG9mIG5ld0Fubm90YXRpb25zQnlQYWdlKSB7CiAgICAgICAgICBuZXdBbm5vdGF0aW9uUHJvbWlzZXMucHVzaChwZGZNYW5hZ2VyLmdldFBhZ2UocGFnZUluZGV4KS50aGVuKHBhZ2UgPT4gewogICAgICAgICAgICBjb25zdCB0YXNrID0gbmV3IFdvcmtlclRhc2soYFNhdmUgKGVkaXRvcik6IHBhZ2UgJHtwYWdlSW5kZXh9YCk7CiAgICAgICAgICAgIHN0YXJ0V29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgICAgcmV0dXJuIHBhZ2Uuc2F2ZU5ld0Fubm90YXRpb25zKGhhbmRsZXIsIHRhc2ssIGFubm90YXRpb25zLCBpbWFnZVByb21pc2VzLCBjaGFuZ2VzKS5maW5hbGx5KGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICBmaW5pc2hXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pKTsKICAgICAgICB9CiAgICAgICAgaWYgKHN0cnVjdFRyZWVSb290ID09PSBudWxsKSB7CiAgICAgICAgICBwcm9taXNlcy5wdXNoKFByb21pc2UuYWxsKG5ld0Fubm90YXRpb25Qcm9taXNlcykudGhlbihhc3luYyAoKSA9PiB7CiAgICAgICAgICAgIGF3YWl0IFN0cnVjdFRyZWVSb290LmNyZWF0ZVN0cnVjdHVyZVRyZWUoewogICAgICAgICAgICAgIG5ld0Fubm90YXRpb25zQnlQYWdlLAogICAgICAgICAgICAgIHhyZWYsCiAgICAgICAgICAgICAgY2F0YWxvZ1JlZiwKICAgICAgICAgICAgICBwZGZNYW5hZ2VyLAogICAgICAgICAgICAgIGNoYW5nZXMKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KSk7CiAgICAgICAgfSBlbHNlIGlmIChzdHJ1Y3RUcmVlUm9vdCkgewogICAgICAgICAgcHJvbWlzZXMucHVzaChQcm9taXNlLmFsbChuZXdBbm5vdGF0aW9uUHJvbWlzZXMpLnRoZW4oYXN5bmMgKCkgPT4gewogICAgICAgICAgICBhd2FpdCBzdHJ1Y3RUcmVlUm9vdC51cGRhdGVTdHJ1Y3R1cmVUcmVlKHsKICAgICAgICAgICAgICBuZXdBbm5vdGF0aW9uc0J5UGFnZSwKICAgICAgICAgICAgICBwZGZNYW5hZ2VyLAogICAgICAgICAgICAgIGNoYW5nZXMKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChpc1B1cmVYZmEpIHsKICAgICAgICBwcm9taXNlcy5wdXNoKHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJzZXJpYWxpemVYZmFEYXRhIiwgW2Fubm90YXRpb25TdG9yYWdlXSkpOwogICAgICB9IGVsc2UgewogICAgICAgIGZvciAobGV0IHBhZ2VJbmRleCA9IDA7IHBhZ2VJbmRleCA8IG51bVBhZ2VzOyBwYWdlSW5kZXgrKykgewogICAgICAgICAgcHJvbWlzZXMucHVzaChwZGZNYW5hZ2VyLmdldFBhZ2UocGFnZUluZGV4KS50aGVuKGZ1bmN0aW9uIChwYWdlKSB7CiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgV29ya2VyVGFzayhgU2F2ZTogcGFnZSAke3BhZ2VJbmRleH1gKTsKICAgICAgICAgICAgc3RhcnRXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgICByZXR1cm4gcGFnZS5zYXZlKGhhbmRsZXIsIHRhc2ssIGFubm90YXRpb25TdG9yYWdlLCBjaGFuZ2VzKS5maW5hbGx5KGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICBmaW5pc2hXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgcmVmcyA9IGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTsKICAgICAgbGV0IHhmYURhdGEgPSBudWxsOwogICAgICBpZiAoaXNQdXJlWGZhKSB7CiAgICAgICAgeGZhRGF0YSA9IHJlZnNbMF07CiAgICAgICAgaWYgKCF4ZmFEYXRhKSB7CiAgICAgICAgICByZXR1cm4gc3RyZWFtLmJ5dGVzOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChjaGFuZ2VzLnNpemUgPT09IDApIHsKICAgICAgICByZXR1cm4gc3RyZWFtLmJ5dGVzOwogICAgICB9CiAgICAgIGNvbnN0IG5lZWRBcHBlYXJhbmNlcyA9IGFjcm9Gb3JtUmVmICYmIGFjcm9Gb3JtIGluc3RhbmNlb2YgRGljdCAmJiBjaGFuZ2VzLnZhbHVlcygpLnNvbWUocmVmID0+IHJlZi5uZWVkQXBwZWFyYW5jZXMpOwogICAgICBjb25zdCB4ZmEgPSBhY3JvRm9ybSBpbnN0YW5jZW9mIERpY3QgJiYgYWNyb0Zvcm0uZ2V0KCJYRkEiKSB8fCBudWxsOwogICAgICBsZXQgeGZhRGF0YXNldHNSZWYgPSBudWxsOwogICAgICBsZXQgaGFzWGZhRGF0YXNldHNFbnRyeSA9IGZhbHNlOwogICAgICBpZiAoQXJyYXkuaXNBcnJheSh4ZmEpKSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0geGZhLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgICAgIGlmICh4ZmFbaV0gPT09ICJkYXRhc2V0cyIpIHsKICAgICAgICAgICAgeGZhRGF0YXNldHNSZWYgPSB4ZmFbaSArIDFdOwogICAgICAgICAgICBoYXNYZmFEYXRhc2V0c0VudHJ5ID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHhmYURhdGFzZXRzUmVmID09PSBudWxsKSB7CiAgICAgICAgICB4ZmFEYXRhc2V0c1JlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKHhmYSkgewogICAgICAgIHdhcm4oIlVuc3VwcG9ydGVkIFhGQSB0eXBlLiIpOwogICAgICB9CiAgICAgIGxldCBuZXdYcmVmSW5mbyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIGlmICh4cmVmLnRyYWlsZXIpIHsKICAgICAgICBjb25zdCBpbmZvTWFwID0gbmV3IE1hcCgpOwogICAgICAgIGNvbnN0IHhyZWZJbmZvID0geHJlZi50cmFpbGVyLmdldCgiSW5mbyIpIHx8IG51bGw7CiAgICAgICAgaWYgKHhyZWZJbmZvIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgeHJlZkluZm8pIHsKICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICBpbmZvTWFwLnNldChrZXksIHN0cmluZ1RvUERGU3RyaW5nKHZhbHVlKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbmV3WHJlZkluZm8gPSB7CiAgICAgICAgICByb290UmVmOiBjYXRhbG9nUmVmLAogICAgICAgICAgZW5jcnlwdFJlZjogeHJlZi50cmFpbGVyLmdldFJhdygiRW5jcnlwdCIpIHx8IG51bGwsCiAgICAgICAgICBuZXdSZWY6IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCksCiAgICAgICAgICBpbmZvUmVmOiB4cmVmLnRyYWlsZXIuZ2V0UmF3KCJJbmZvIikgfHwgbnVsbCwKICAgICAgICAgIGluZm9NYXAsCiAgICAgICAgICBmaWxlSWRzOiB4cmVmLnRyYWlsZXIuZ2V0KCJJRCIpIHx8IG51bGwsCiAgICAgICAgICBzdGFydFhSZWYsCiAgICAgICAgICBmaWxlbmFtZQogICAgICAgIH07CiAgICAgIH0KICAgICAgcmV0dXJuIGluY3JlbWVudGFsVXBkYXRlKHsKICAgICAgICBvcmlnaW5hbERhdGE6IHN0cmVhbS5ieXRlcywKICAgICAgICB4cmVmSW5mbzogbmV3WHJlZkluZm8sCiAgICAgICAgY2hhbmdlcywKICAgICAgICB4cmVmLAogICAgICAgIGhhc1hmYTogISF4ZmEsCiAgICAgICAgeGZhRGF0YXNldHNSZWYsCiAgICAgICAgaGFzWGZhRGF0YXNldHNFbnRyeSwKICAgICAgICBuZWVkQXBwZWFyYW5jZXMsCiAgICAgICAgYWNyb0Zvcm1SZWYsCiAgICAgICAgYWNyb0Zvcm0sCiAgICAgICAgeGZhRGF0YSwKICAgICAgICB1c2VYcmVmU3RyZWFtOiBpc0RpY3QoeHJlZi50b3BEaWN0LCAiWFJlZiIpCiAgICAgIH0pLmZpbmFsbHkoKCkgPT4gewogICAgICAgIHhyZWYucmVzZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgfSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldE9wZXJhdG9yTGlzdCIsIGZ1bmN0aW9uIChkYXRhLCBzaW5rKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBwYWdlSWQsCiAgICAgICAgcGFnZUluZGV4CiAgICAgIH0gPSBkYXRhOwogICAgICBwZGZNYW5hZ2VyLmdldFBhZ2UocGFnZUlkKS50aGVuKGZ1bmN0aW9uIChwYWdlKSB7CiAgICAgICAgY29uc3QgdGFzayA9IG5ldyBXb3JrZXJUYXNrKGBHZXRPcGVyYXRvckxpc3Q6IHBhZ2UgJHtwYWdlSW5kZXh9YCk7CiAgICAgICAgc3RhcnRXb3JrZXJUYXNrKHRhc2spOwogICAgICAgIGNvbnN0IHN0YXJ0ID0gdmVyYm9zaXR5ID49IFZlcmJvc2l0eUxldmVsLklORk9TID8gRGF0ZS5ub3coKSA6IDA7CiAgICAgICAgcGFnZS5nZXRPcGVyYXRvckxpc3QoewogICAgICAgICAgaGFuZGxlciwKICAgICAgICAgIHNpbmssCiAgICAgICAgICB0YXNrLAogICAgICAgICAgaW50ZW50OiBkYXRhLmludGVudCwKICAgICAgICAgIGNhY2hlS2V5OiBkYXRhLmNhY2hlS2V5LAogICAgICAgICAgYW5ub3RhdGlvblN0b3JhZ2U6IGRhdGEuYW5ub3RhdGlvblN0b3JhZ2UsCiAgICAgICAgICBtb2RpZmllZElkczogZGF0YS5tb2RpZmllZElkcywKICAgICAgICAgIHBhZ2VJbmRleAogICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKG9wZXJhdG9yTGlzdEluZm8pIHsKICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICBpZiAoc3RhcnQpIHsKICAgICAgICAgICAgaW5mbyhgcGFnZT0ke3BhZ2VJbmRleCArIDF9IC0gZ2V0T3BlcmF0b3JMaXN0OiB0aW1lPWAgKyBgJHtEYXRlLm5vdygpIC0gc3RhcnR9bXMsIGxlbj0ke29wZXJhdG9yTGlzdEluZm8ubGVuZ3RofWApOwogICAgICAgICAgfQogICAgICAgICAgc2luay5jbG9zZSgpOwogICAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICBpZiAodGFzay50ZXJtaW5hdGVkKSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIHNpbmsuZXJyb3IocmVhc29uKTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldFRleHRDb250ZW50IiwgZnVuY3Rpb24gKGRhdGEsIHNpbmspIHsKICAgICAgY29uc3QgewogICAgICAgIHBhZ2VJZCwKICAgICAgICBwYWdlSW5kZXgsCiAgICAgICAgaW5jbHVkZU1hcmtlZENvbnRlbnQsCiAgICAgICAgZGlzYWJsZU5vcm1hbGl6YXRpb24KICAgICAgfSA9IGRhdGE7CiAgICAgIHBkZk1hbmFnZXIuZ2V0UGFnZShwYWdlSWQpLnRoZW4oZnVuY3Rpb24gKHBhZ2UpIHsKICAgICAgICBjb25zdCB0YXNrID0gbmV3IFdvcmtlclRhc2soIkdldFRleHRDb250ZW50OiBwYWdlICIgKyBwYWdlSW5kZXgpOwogICAgICAgIHN0YXJ0V29ya2VyVGFzayh0YXNrKTsKICAgICAgICBjb25zdCBzdGFydCA9IHZlcmJvc2l0eSA+PSBWZXJib3NpdHlMZXZlbC5JTkZPUyA/IERhdGUubm93KCkgOiAwOwogICAgICAgIHBhZ2UuZXh0cmFjdFRleHRDb250ZW50KHsKICAgICAgICAgIGhhbmRsZXIsCiAgICAgICAgICB0YXNrLAogICAgICAgICAgc2luaywKICAgICAgICAgIGluY2x1ZGVNYXJrZWRDb250ZW50LAogICAgICAgICAgZGlzYWJsZU5vcm1hbGl6YXRpb24KICAgICAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICBpZiAoc3RhcnQpIHsKICAgICAgICAgICAgaW5mbyhgcGFnZT0ke3BhZ2VJbmRleCArIDF9IC0gZ2V0VGV4dENvbnRlbnQ6IHRpbWU9YCArIGAke0RhdGUubm93KCkgLSBzdGFydH1tc2ApOwogICAgICAgICAgfQogICAgICAgICAgc2luay5jbG9zZSgpOwogICAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICBpZiAodGFzay50ZXJtaW5hdGVkKSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIHNpbmsuZXJyb3IocmVhc29uKTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldFN0cnVjdFRyZWUiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5nZXRQYWdlKGRhdGEucGFnZUluZGV4KS50aGVuKHBhZ2UgPT4gcGRmTWFuYWdlci5lbnN1cmUocGFnZSwgImdldFN0cnVjdFRyZWUiKSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkZvbnRGYWxsYmFjayIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmZvbnRGYWxsYmFjayhkYXRhLmlkLCBoYW5kbGVyKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiQ2xlYW51cCIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmNsZWFudXAodHJ1ZSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIlRlcm1pbmF0ZSIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHRlcm1pbmF0ZWQgPSB0cnVlOwogICAgICBjb25zdCB3YWl0T24gPSBbXTsKICAgICAgaWYgKHBkZk1hbmFnZXIpIHsKICAgICAgICBwZGZNYW5hZ2VyLnRlcm1pbmF0ZShuZXcgQWJvcnRFeGNlcHRpb24oIldvcmtlciB3YXMgdGVybWluYXRlZC4iKSk7CiAgICAgICAgY29uc3QgY2xlYW51cFByb21pc2UgPSBwZGZNYW5hZ2VyLmNsZWFudXAoKTsKICAgICAgICB3YWl0T24ucHVzaChjbGVhbnVwUHJvbWlzZSk7CiAgICAgICAgcGRmTWFuYWdlciA9IG51bGw7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY2xlYXJHbG9iYWxDYWNoZXMoKTsKICAgICAgfQogICAgICBjYW5jZWxYSFJzPy4obmV3IEFib3J0RXhjZXB0aW9uKCJXb3JrZXIgd2FzIHRlcm1pbmF0ZWQuIikpOwogICAgICBmb3IgKGNvbnN0IHRhc2sgb2YgV29ya2VyVGFza3MpIHsKICAgICAgICB3YWl0T24ucHVzaCh0YXNrLmZpbmlzaGVkKTsKICAgICAgICB0YXNrLnRlcm1pbmF0ZSgpOwogICAgICB9CiAgICAgIHJldHVybiBQcm9taXNlLmFsbCh3YWl0T24pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIGhhbmRsZXIuZGVzdHJveSgpOwogICAgICAgIGhhbmRsZXIgPSBudWxsOwogICAgICB9KTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiUmVhZHkiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICBzZXR1cERvYyhkb2NQYXJhbXMpOwogICAgICBkb2NQYXJhbXMgPSBudWxsOwogICAgfSk7CiAgICByZXR1cm4gd29ya2VySGFuZGxlck5hbWU7CiAgfQogIHN0YXRpYyBpbml0aWFsaXplRnJvbVBvcnQocG9ydCkgewogICAgY29uc3QgaGFuZGxlciA9IG5ldyBNZXNzYWdlSGFuZGxlcigid29ya2VyIiwgIm1haW4iLCBwb3J0KTsKICAgIHRoaXMuc2V0dXAoaGFuZGxlciwgcG9ydCk7CiAgICBoYW5kbGVyLnNlbmQoInJlYWR5IiwgbnVsbCk7CiAgfQp9Cgo7Ly8gLi9zcmMvcGRmLndvcmtlci5qcwoKZ2xvYmFsVGhpcy5wZGZqc1dvcmtlciA9IHsKICBXb3JrZXJNZXNzYWdlSGFuZGxlcjogV29ya2VyTWVzc2FnZUhhbmRsZXIKfTsKCmV4cG9ydCB7IFdvcmtlck1lc3NhZ2VIYW5kbGVyIH07CgovLyMgc291cmNlTWFwcGluZ1VSTD1wZGYud29ya2VyLm1qcy5tYXA=\""],"names":["useAnnouncer","target","timeout","arguments","length","undefined","assertiveElement","ref","announcement","clearText","setTimeout","value","innerText","watch","val","console","warn","document","createElement","classList","add","setAttribute","appendChild","useDebounce","debounce","callback","time","clearTimeout","_typeof","o","toPrimitive","t","r","e","i","toPropertyKey","_defineProperty","useElementObserver","_ref","type","_ref$options","options","targetElement","computed","_target$value","$el","observer","initObserver","ResizeObserver","MutationObserver","IntersectionObserver","entries","forEach","entry","triggerCallbackWhenInViewport","isIntersecting","stopObservingWhenInViewport","disconnect","concat","observe","onMounted","onBeforeUnmount","useEventListener","event","_ref$setDebounce","setDebounce","_ref$callOnMounted","callOnMounted","listenerContainer","listenerCallback","_useDebounce","window","addEventListener","container","once","removeEventListener","useElementFadeOut","direction","className","_ref$direction","_ref$className","scrollContainer","directionIsVertical","preElementName","postElementName","boxFadeOut","calcFadeOut","scrollPosition","Math","ceil","scrollTop","scrollLeft","scrollMax","scrollHeight","clientHeight","scrollWidth","clientWidth","remove","elementIsScrollable","useExtractAttrs","filterAttrs","attrs","useAttrs","rootAttrs","newAttrs","attr","forwardAttrs","_objectSpread","useHasSlotContent","slot","slotHasContent","vNodeHasContent","vnodes","some","node","Comment","Text","children","trim","Fragment","_arrayLikeToArray","a","n","_arrayWithoutHoles","arrayLikeToArray","_iterableToArray","_unsupportedIterableToArray","_nonIterableSpread","_toConsumableArray","arrayWithoutHoles","iterableToArray","unsupportedIterableToArray","nonIterableSpread","useHorizontalDragScroll","scrollingClassNames","scrollableClassNames","_ref$scrollingClassNa","_ref$scrollableClassN","_useElementFadeOut","isScrolling","pos","top","left","x","y","clickModificationsSet","state","_target$value$classLi","apply","_target$value$classLi2","_target$value$classLi3","_target$value$classLi4","pointerDownHandler","pointerType","pointerMoveHandler","pointerUpHandler","_event$clientX","_event$touches$","_event$clientY","_event$touches$2","clientX","touches","clientY","_event$clientX2","_event$touches$3","preventDefault","setPointerCapture","pointerId","overlay","id","style","position","height","width","backgroundColor","zIndex","body","eventXPosition","dx","releasePointerCapture","getElementById","removeChild","useI18n","language","app","getCurrentInstance","appContext","i18n","te","langInt","hasI18n","_app$config","i18nEnabled","Boolean","config","globalProperties","$i18n","$t","$te","getI18nTerm","key","count","variables","termPath","split","pop","setLangLabels","locales","reduce","prev","curr","getLangLabel","useAny","langToUse","locale","availableLang","Object","keys","find","_arrayWithHoles","_iterableToArrayLimit","l","u","f","_nonIterableRest","_slicedToArray","arrayWithHoles","iterableToArrayLimit","nonIterableRest","capitalizeString","string","newString2","map","partialString","slice","toUpperCase","join","createId","random","toString","extractNestedPropertyValue","object","b","getNameSortValue","compareString","compareStringSansNumbers","replace","includes","compareArray","splice","compArray","sort","list","objectProp","sortByName","valueFunction","compareValueA","compareValueB","secondaryCompareValueA","secondaryCompareValueB","_getNameSortValue","_getNameSortValue2","_getNameSortValue3","_getNameSortValue4","toLowerCase","hasData","fieldValues","hasContent","values","objectKeys","delay","timer","_len","args","Array","_key","_this","highlightText","word","queryString","_ref$highlightTags","highlightTags","check","RegExp","highlightTagsStart","highlightTagsEnd","matchedText","ATTR_KEY","useId","_instance$vnode$el","_instance$vnode$el2","_instance$vnode$el3","_el$getAttribute","instance","el","vnode","nodeType","nextElementSibling","getAttribute","call","useListNavigation","isWithinArrayLimit","isArrowDown","newIndex","listLimit","operators","operator","navigate","currentIndex","loop","allowNegativeIndex","numberToAdd","B","it","T","R","at","st","j","rt","lt","ct","ut","m","g","ft","ot","v","dt","Q","X","h","D","S","s","p","L","G","W","A","k","d","C","P","N","F","U","q","z","J","I","K","$","M","O","_","Y","V","w","Z","tt","et","nt","H","E","gt","pt","yt","ht","useNotifications","_useNotification","useNotification","notify","arr","arr2","hasPassiveEvents","passiveTestOptions","isIosDevice","locks","documentListenerAdded","initialClientY","previousBodyOverflowSetting","previousBodyPosition","previousBodyPaddingRight","allowTouchMove","lock","rawEvent","setOverflowHidden","_reserveScrollBarGap","scrollBarGap","computedBodyPaddingRight","restoreOverflowSetting","setPositionFixed","_window","scrollY","scrollX","innerHeight","bottomBarHeight","restorePositionSetting","isTargetElementTotallyScrolled","handleScroll","disableBodyScroll","clearAllBodyScrollLocks","enableBodyScroll","usePopUpLock","showElement","toggleScrollLock","reserveScrollBarGap","onUpdated","useTabKeyHandler","focusableElements","disable","focusableHTMLTags","disableHandler","_document","querySelector","_document2","getFocusableElements","elements","from","querySelectorAll","filter","element","checkVisibility","setFocus","currentFocus","nextFocus","index","matches","focus","tabKeyHandler","shiftKey","watchEffect","useWindowResize","_ref$mobileMaxSize","mobileMaxSize","_ref$tabletMaxSize","tabletMaxSize","windowInnerWidth","isMobile","isTablet","resize","innerWidth","_sfc_main","defineAsyncComponent","props","emit","internalId","idInt","inputComponent","useTemplateRef","inputElement","_a","inputElements","search","_openBlock","_createElementBlock","_mergeProps","$setup","_createBlock","_resolveDynamicComponent","$options","$event","$data","$props","_renderSlot","_ctx","_createElementVNode","_normalizeClass","_component_BaseIcon","aria","_hoisted_2","_hoisted_3","slots","useSlots","buttonHasTextElement","_component_BaseBoxTooltip","_cache","tryOnScopeDispose","fn","getCurrentScope","onScopeDispose","isClient","isObject","noop","isIOS","getIsIOS","_b","toRef","toRef$1","readonly","customRef","toArray","watchImmediate","source","cb","defaultWindow","unrefElement","elRef","plain","toValue","cleanups","cleanup","register","listener","firstParamTargets","test","stopWatch","unref","raw_targets","raw_events","raw_listeners","raw_options","optionsClone","stop","_iOSWorkaround","onClickOutside","handler","ignore","capture","detectIframe","controls","listenerOptions","shouldListen","shouldIgnore","target2","hasMultipleRoots","vm","checkMultipleRoots","child","isProcessingClick","BaseIcon","prop","internalValidationMessage","labelLocalized","errorMessageInt","showLabelRow","inputInt","inputMode","showRemoveIcon","input","tempElement","inputFrame","isActiveInt","setFieldState","clickedInside","handleInputTab","parsedValue","validatedValue","ctrlKey","allowedKeys","allowedKeysRegex","updatedString","decimalSeparator","bannedChars","decimals","eMinus","pattern","ds","chunks","char","c","text","_hoisted_1","_hoisted_4","_createVNode","_component_BaseLoader","_hoisted_6","_hoisted_7","_toDisplayString","BaseInput","vueDraggablePlus","generatedId","baseInput","isChipsEditable","chipsInputField","tempList","option","isIndexUp","activeChip","optionLabel","duplicate","setIndex","newEntry","newString","newSelectedListInt","selected","matchingOption","opt","dataTransfer","dragEl","img","elem","_component_BaseInput","_component_VueDraggable","_TransitionGroup","_Fragment","_renderList","_component_BaseChip","textString","_component_BaseInsertTextAsHtml","__props","emits","__emit","dropDownContainer","dropDownList","cleanedOptions","arrayIds","item","hasDuplicates","isDuplicate","langLabel","reducedArrItem","selectedOption","originalOption","scrollContainerElement","scrollContainerHeight","activeOptionIndex","activeOptionInt","activeOptionElement","subOptionElement","totalOffsetTop","elementOffsetTop","highlight","showNoOptions","dropDownOption","optionIndex","_withKeys","_withModifiers","_createTextVNode","BaseButton","BaseDropDownList","BaseChip","BaseChipsInputField","BaseSearch","advancedSearchRow","baseSearch","setFilterValues","newFilter","previousFilter","previousFilterValues","freetextAllowed","_c","internalRowId","filterSlotName","resizeActions","searchElement","searchElementWidth","searchRowElementWidth","searchInputElement","isActive","currentFilterType","filterChangeObserverAction","handleDropDownOnTabKey","searchInputArray","eventInputIndex","filterBox","filterFade","currentFilter","resultsToDisplay","section","selectedOptionIds","selectedFilter","previousInput","category","collectionId","selectedOptionCollection","newValue","oldFilterValues","newTextArray","resultsNumber","previousActiveCollection","currentCollectionIndex","currentCollectionArray","currentEntryIndex","isWithinListLimit","newItemIndex","collectionLabel","data","_hoisted_5","_hoisted_11","_hoisted_13","_hoisted_14","_component_BaseSearch","_component_BaseChipsInputField","_withCtx","_component_BaseDropDownList","_hoisted_9","_hoisted_10","_hoisted_12","autocompleteOption","singleFilter","_hoisted_8","chip","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_component_BaseButton","labelId","_hoisted_24","mainSearch","searchContainer","fieldProps","updatedFormFieldProps","renderProp","displayed","lastFilterIndex","key1","key2","formFilterData","isRepeatableField","repeatableEntry","filterId","groupMatch","filterData","filterValues","previousValues","fieldsToSetTrue","mainFilterHasData","originalMainFilterHasData","filtersWithoutDefault","filterValuesNoMain","resizeObserver","alwaysTrigger","modeFilterList","searchFilterList","filterKey","filterValue","minMainFilter","newFilterValues","triggerSearch","fieldInformation","fieldXAttrs","labelProp","idProp","chipsFormFieldValue","fieldLabel","params","newFilterValueList","fieldData","fieldId","parentFields","fieldType","formattedLabel","chipValue","additionalProperties","fieldKey","fieldValue","currentType","storageDate","minus","year","month","day","collapsedValues","objectProperties","valueObject","formFieldInfo","subFields","keyProps","propertyName","propertyValue","overwritePreviousValues","previousFieldProps","renderPropKey","renderPropValues","prevObject","field","_component_BaseAdvancedSearchRow","_component_BaseForm","fieldName","groupNames","arrayEntry","_component_BaseCollapsedFilterRow","optionsIsListOfStrings","listInt","previousOptionValue","label","optionId","filteredListInt","activeOption","onArrowKey","onKeydown","onEnter","selectOption","autocompleteInput","__expose","_unref","clicked","BaseBox","baseBox","baseBoxSubtext","showSubtext","calcShowSubtext","subtextBottomPosition","boxHeight","_component_BaseBox","cleanDomNodes","binding","childNodes","_binding$value","Node","TEXT_NODE","textContent","ELEMENT_NODE","recursive","showTooltip","closeTooltip","scrollResizeHandler","isRouterAvailable","obj","router","_withDirectives","_component_BaseTooltipBox","BaseLink","route","showLabel","icon","_component_BaseLink","iconSlotHasContent","footerRightSlotHasContent","footerLeftSlotHasContent","titleRightSlotHasContent","headerBox","boxText","boxTextInner","boxTextStyle","calcTextHeight","headerHeight","elemInnerHeight","boxMargin","lineElement","lineHeight","textBoxHeight","lines","_component_BaseImage","_component_BaseImageGrid","_Transition","_component_BaseCheckmark","BaseImageBox","imageSrc","Swiper","A11y","index$1","Autoplay","Keyboard","Navigation","Pagination","defaultSwiperOptions","_component_BaseImageBox","createdId","chipsInput","newProps","defaultValue","newSelected","BaseChipsInput","chipsBelow","renderListCopy","providedId","matchingLabelsList","updatedSelectedList","newChipText","modifiedEntry","updatedList","isValidChipsInput","error","_component_BaseChipsInput","stopClickOutsideMap","vOnClickOutside","resolveElement","checkOverflowScroll","ele","parent","_target","elInitialOverflow","useScrollLock","initialState","isLocked","shallowRef","stopTouchMoveListener","initialOverflow","unlock","onScrollLock","isMounted","labelKeys","lang","newLang","__variableDynamicImportRuntime2__","dateFormatInt","isFromTimeField","isToTimeField","isInputTypeString","inputProperties","inputFrom","parseToDateDisplay","oldValue","newDate","parseToDateStorage","emitData","inputTo","getInputData","dateString","isNegativeYear","isNegativeStorageDate","positiveDateString","removeYearMinusFromStorageDate","addYearMinusToDateDisplay","isNegativeDisplayDate","date","format","formatToCheck","isNegative","addYearMinusToDateStorage","removeYearMinusFromDisplayDate","isSwitchableFormat","labelRowSlotsHaveData","pickerState","onClickOutsideHandler","onInputBlur","origin","relatedTargetInput","_d","baseDateInput","labelElement","labelAdditions","nativeInputElements","baseIcon","iconWidth","wrapLabelRow","showIcons","fadeOut","onElementResize","onLabelAdditionsResize","calcLabelAdditionsWidth","observableWidth","labelMargin","labelWidth","spacingLeft","inputFields","iconElement","iconMargin","maxTextWidth","span","toWidth","inputWidth","nextTick","textWidth","invalidFrom","invalidTo","errorMessageFrom","errorMessageTo","requiredFrom","requiredTo","disabledFrom","disabledTo","old","dateKey","__variableDynamicImportRuntime3__","currentInputString","isTimeField","allowedFieldKey","allowMinus","disallowedKeysOnLengthRegex","formatLength","modifiedValue","charToAdd","positiveDate","separator","numberFormatParts","hours","minutes","currentYear","century","newTime","tempDate","uppercaseOrigin","oldFormat","dateValue","dateToConvert","useStorageDate","isNegativeTempStorageDate","isNegativeNewDateValue","positiveTempStorageDate","date1","date2","convertedDate1","convertedDate2","monthDate1","monthDate2","yearDate1","yearDate2","_component_BaseSwitchButton","_component_DatePicker","timeType","_e","_f","BaseBoxButton","evt","originalEvent","div","draggedElementId","_component_BaseBoxButton","dropDown","dropArea","dropDownPosition","dropDownTransformation","calculateDropDownPosition","windowWidth","dropElement","dropAreaPosition","dropAreaStart","dropAreaEnd","dropAreaTop","dropAreaBottom","moveToLeft","debounceCalc","button","actionType","baseDropDown","dropDownButton","headText","showFadeOut","setOverflow","headerWidth","showDropDown","maxDropDownHeight","dropDownTopPosition","maxHeight","newY","newHeight","keySelectedIndex","_normalizeStyle","loader","setLoaderAnnouncement","BaseLoader","titleLine","requiredProp","bodyEl","headHasShadow","bottomHasShadow","scroll","firstFocusableListElement","announcementTextKey","entriesIds","number","_component_BaseOptions","_component_BaseDropDown","_component_BaseSelectOptions","_component_BaseMenuList","isSelected","_component_BasePagination","headerSlotHasContent","footerSlotHasContent","content","contentInner","mutationObserver","contentInnerTemp","contentInnerTempHeight","dragHandle","scrollable","currentState","rows","row","elementHeight","items","_component_BaseExpandListRow","dataNextLevel","_component_BaseToggle","BaseExpandListRow","draggableIsLoaded","Draggable","component","rowData","to","visibilityText","currentSupportString","_vShow","_Suspense","BaseCheckmark","hasDefaultSlot","hasIconSlot","isSelectedInternal","isExpandedInternal","isExpandable","dropDownLists","openAPIFieldType","numberFieldType","numberFieldFormat","textObject","multilineText","autocompleteInformation","parentFieldsArary","localesWithContent","tab","_component_BaseDateInput","INDIVIDUAL_REPEATABLE_FIELDPROPS","BaseFormFieldCreator","fieldFormat","order","hidden","lastArrayElementIndex","groupTitleField","inputs","newValueList","name","xAttrs","properties","xAttrsFieldType","initObj","newFieldValues","fieldGroupValues","errors","refName","hasErrors","groupIndex","valueIndex","singleFieldProps","fieldRepeatable","repeatableFieldProps","existingIndividualFieldProps","comboIndex","errorMessagesObjectExtract","schema","subSchema","fieldLists","rowId","rowType","rowIndex","_component_BaseFormFieldCreator","rowField","BaseForm","groupsId","formFieldsGrouped","groupedFormFields","noGroupFields","formValuesGrouped","group","formsMounted","formMounted","allFormsMounted","updateFormValues","mountedVal","formGroup","fieldIndex","isLoading","hls","playButton","video","HlsLight","Hls","last","size","lazysizes","BaseImage","image","useIconElement","useHeaderElement","bottomSlotHasContent","useBottomElement","action","paragraph","iconPosition","disabled","markerClass","markerClusterClass","mapElement","activePopUp","boundsPadding","highlightedMarker","markerCluster","popupOptions","scrollWheelZoom","cssProps","markerFiltered","getLatLng","before","resetAllMarker","layer","marker","markerClusterActive","activateMarker","emitMarkerState","resetMarker","init","ResponsivePopup","MarkerClusterGroup","mapTmp","mapConfig","iconOptions","markerIcon","cluster","classSize","popup","markerOptions","bounds","_component_BaseTextList","arrayItem","listIndex","objectItem","objectIndex","BaseTextList","_component_BaseMap","location","footer","footerHeight","setFooterHeight","docType","match","_hoisted_16","_component_BaseHlsVideo","_component_BaseRangeSlider","_component_BasePdfViewer","textline","_hoisted_15","BaseMediaCarouselItem","mediaCarousel","showInt","swiperId","Zoom","additionalOptions","slide","pdfViewer","swiper","scale","media","focusable","focusableBySlide","currentSlide","itemIndex","elemIndex","_component_BaseMediaCarouselItem","isSelectActive","thumbnailsSlotHasContent","rightSideSlotHasContent","thumbnailCount","BaseMenuEntry","isDraggable","entryKeys","entryPropsKey","entryIcon","pic","_component_BaseMenuEntry","textarea","propName","_vModelText","navOpen","currentRoute","navElements","activeElement","activeElementIdInt","mobileViewNavigation","desktopNavigation","menuButton","resizeTriggered","showShortLabel","mobileDropDownElements","mobileRightElements","mobileLeftElements","showSeparator","rightElementsLength","leftElementsLength","calcTextWidth","cloneRef","clonedNavigation","navigationWidth","menuButtonWidth","activeLinkElement","activeTextElement","activeLinkPadding","li","linkElement","textElement","linkPadding","requiredProps","optionProps","optionsRow","rowWidth","beforeSlotHasData","afterSlotHasData","beforeOptions","afterOptions","afterOptionsBelow","optionsButton","remainingOptionsWidth","beforeOptionsWidth","afterOptionsWidth","optionsButtonWidth","optionsWidth","fontSizeChangeDetector","optionsInitialized","calcFixedElementWidth","afterOptionsElement","getElementWidth","useOptionsButton","elementToClone","elementWidth","calcOptionsWidth","isMobileInt","showOptionsInt","optionsFittingRowWidth","displayOptions","showOptionsInline","active","pagination","subsetNumber","maxNumbers","start","end","setStartEnd","debounceCalculations","elementMounted","subsetStart","page","canvasContainer","mounted","pdfDoc","renderVersion","lastRenderedPage","renderPagesAllowed","allPagesRendered","loadPdf","src","pdfjsLib","pdfjsWorker","pdf_worker$1","getScaleForPage","naturalWidth","renderPages","startPage","newVersion","fragment","canvas","pageNum","naturalViewport","viewport","context","task","renderPdf","err","stopRendering","resumeRendering","onUnmounted","newSrc","popUpBody","progressBar","fileName","currentValue","countDecimals","str","stepper","stepSize","point","pointValue","actionProps","elementId","resultBoxSection","resultBoxesArea","itemsPerRow","initialBoxCalcDone","calcBoxNumber","resultBoxesElement","totalWidth","boxBreakpointsCopy","nodeId","oldVal","availableSpaces","html","actionsVisible","selectAll","visibleEntryIds","visibleEntry","entryId","boxId","selectedEntry","shiftDown","newArray","localizationArguments","idList","tooltipBox","tooltipInner","bodyInner","calcPosition","isClickOutsideActive","close","escEventHandler","css","thresholdX","thresholdY","spacing","thresholdTopInt","thresholdTopCssVar","computedTop","thresholdTopAsNumber","attachToRect","boxWidth","triangleHeight","triangleWidth","directionOption","isPopUpLockEnabled","onMutation","prevActiveElement","focusInitialElement","focusElement","BasePopUp","BaseProgressBar","bytes","si","newBytes","thresh","units","file","message","_component_BasePopUp","_component_BaseProgressBar","notificationTitle","_component_Notifications","BaseNotificationsPlugin","install","use","Notifications","BaseNotification","an","Pe","wt","bt","fe","$e","Ht","mn","vn","St","bn","yn","Dt","_t","wn","En","Tt","Ke","Sn","Dn","_n","Tn","Ct","Cn","On","Ot","ne","In","Ye","ie","An","xn","Nn","re","ae","xe","It","Te","Lt","Wt","Gt","We","Pn","At","ye","jt","xt","ce","we","Nt","Mn","Fn","Je","Ce","zt","Rn","Ut","Vt","Xn","Bn","ge","Ze","Ne","kn","Hn","pe","Be","ue","Se","be","Oe","se","Zt","Qt","Me","ve","Ge","je","de","Qe","Pt","Mt","me","Ie","Ae","Fe","ke","ze","Ve","Re","Ft","Ln","qt","Kt","Wn","Gn","Jt","he","jn","Zn","He","ee","Ee","vt","rn","Xe","$n","Vn","oe","le","qn","Un","zn","Jn","De","Ue","Qn","Rt","Le","en","eo","sn","no","un","kt","tn","nn","Xt","oo","Yt","on","qe","mt","ln","ro","lo","cn","Et","dn","hn","pn","requiredFilterValueProps","filterProps","filterValueProps","propMissing","groupFilterValueProps","nestedFilterValue","property","filterIndex","filterLabel","concatValuesArray","groupFilterValues","valueId","filterPropertyName","subFormList","groupValue","_component_BaseCollapsedFilterItem","extend","noExtend","ssrDocument","getDocument","doc","ssrWindow","getWindow","win","classesToTokens","classes","getComputedStyle","getTranslate","axis","matrix","curTransform","transformMatrix","curStyle","elementChildren","selector","tag","elementOffset","box","clientTop","clientLeft","elementIndex","elementParents","parents","elementOuterSize","includeMargins","makeElementsArray","setInnerHTML","extendParams","handle","rtl","kc","pageUpDown","isPageUp","isPageDown","isArrowLeft","isArrowRight","isArrowUp","inView","swiperWidth","swiperHeight","windowHeight","swiperOffset","swiperCoord","speed","enable","createElementIfNotDefined","originalParams","checkProps","arrowSvg","getEl","res","toggleEl","subEl","update","nextEl","prevEl","onPrevClick","onNextClick","initButton","dir","tempEl","destroy","destroyButton","_s","targetEl","targetIsButton","path","pathEl","isHidden","classesToSelector","pfx","bulletSize","dynamicBulletIndex","isPaginationDisabled","setSideBullets","bulletEl","bulletActiveClass","getMoveDirection","prevIndex","nextIndex","onBulletClick","moveDirection","current","previousIndex","slidesLength","total","bullets","firstIndex","lastIndex","midIndex","classesToRemove","suffix","bullet","bulletIndex","firstDisplayedBullet","lastDisplayedBullet","dynamicBulletsLength","bulletsOffset","offsetProp","subElIndex","fractionEl","totalEl","progressbarDirection","scaleX","scaleY","progressEl","render","paginationHTML","numberOfBullets","currentScale","isScaling","isPanningWithMouse","mousePanStart","mousePanSensitivity","fakeGestureTouched","fakeGestureMoved","evCache","gesture","velocity","imageEl","slideEl","getDistanceBetweenTouches","x1","y1","x2","y2","getMaxRatio","maxRatio","imageMaxRatio","getScaleOrigin","getSlideSelector","eventWithinSlide","slideSelector","eventWithinZoomContainer","containerEl","onGestureStart","originX","originY","onGestureChange","zoom","pointerIndex","cachedEv","onGestureEnd","allowTouchMoveTimeout","preventTouchMove","onTouchStart","device","onTouchMove","isMousePan","onMouseMove","scaledWidth","scaledHeight","scaleRatio","onTouchEnd","momentumDurationX","momentumDurationY","momentumDistanceX","newPositionX","momentumDistanceY","newPositionY","momentumDuration","onTransitionEnd","currentTransform","deltaX","deltaY","slideWidth","slideHeight","minX","maxX","minY","maxY","newX","zoomIn","touchX","touchY","offsetX","offsetY","diffX","diffY","translateX","translateY","imageWidth","imageHeight","translateMinX","translateMinY","translateMaxX","translateMaxY","prevScale","forceZoomRatio","zoomOut","zoomToggle","getListeners","passiveListener","activeListenerWithCapture","eventName","liveRegion","preventFocusHandler","focusTargetSlideEl","visibilityChangedTimestamp","notification","getRandomNumber","randomChar","makeElFocusable","makeElNotFocusable","addElRole","role","addElRoleDescription","description","addElLabel","addElId","addElLive","live","disableEl","enableEl","onEnterOrSpaceKey","prevEls","updateNavigation","hasPagination","hasClickablePagination","updatePagination","initNavEl","wrapperId","handlePointerDown","handlePointerUp","onVisibilityChange","handleFocus","isVirtual","isVisible","initSlides","slideIndex","ariaLabelMessage","wrapperEl","raf","autoplayDelayTotal","autoplayDelayCurrent","autoplayTimeLeft","autoplayStartTime","wasPaused","isTouched","pausedByTouch","touchStartTimeout","pausedByInteraction","pausedByPointerEnter","resume","calcTimeLeft","timeLeft","getSlideDelay","activeSlideEl","getTotalDelay","totalDelay","currentSlideDelay","run","delayForce","proceed","pause","internal","reset","onPointerEnter","onPointerLeave","attachMouseEvents","detachMouseEvents","attachDocumentEvents","detachDocumentEvents","isDate","toDate","isValidDate","startOfWeek","firstDayOfWeek","diff","startOfWeekYear","_ref$firstDayOfWeek","_ref$firstWeekContain","firstWeekContainsDate","firstDateOfFirstWeek","getWeek","_ref2","_ref2$firstDayOfWeek","_ref2$firstWeekContai","firstDateOfThisWeek","REGEX_FORMAT","pad","len","output","sign","getOffset","formatTimezone","offset","delimeter","absOffset","meridiem","isLowercase","formatFlags","meridiemFunc","formatStr","defaultLocale","p1","iter","ownKeys","enumerableOnly","symbols","sym","_arr","_i","formattingTokens","match1","match2","match3","match4","match1to2","matchShortOffset","matchSigned","matchTimestamp","YEAR","MONTH","DAY","HOUR","MINUTE","SECOND","MILLISECOND","parseFlags","addParseFlag","token","regex","tokens","func","escapeStringRegExp","matchWordRegExp","localeKey","array","matchWordCallback","cent","matchMeridiem","defaultIsPM","isPM","offsetFromString","_ref8","_ref9","symbol","hour","minute","to24hour","getFullInputArray","backupDate","result","backupArr","useBackup","createDate","ms","createUTCDate","makeParser","mark","parseTo","parser","parse","_options$locale","_locale","_options$backupDate","parseResult","second","millisecond","weekday","week","inputArray","firstDate","parsedDate","__defProp","__defProps","__getOwnPropDescs","__getOwnPropSymbols","__hasOwnProp","__propIsEnum","__defNormalProp","__spreadValues","__spreadProps","__objRest","exclude","isLocal","getLocale","chunk","isPlainObject","pick","mergeDeep","targetValue","padNumber","num","camelcase","camelizeRE","localeContextKey","prefixClassKey","getWeekKey","useLocale","inject","provideLocale","lang2","locale2","provide","providePrefixClass","usePrefixClass","provideGetWeek","useGetWeek","getPopupElementSize","originalDisplay","originalVisibility","styles","getRelativePosition","targetWidth","targetHeight","fixed","relativeRect","dw","dh","getScrollParent","until","scrollBarWidth","getScrollbarWidth","outer","inner","mousedownEvent","rafThrottle","isRunning","defineVueComponent","setup","withDefault","defaultProps","resolveProps","booleanKeys2","camelizeKey","Popup","originalProps","prefixClass","displayPopup","relativeElement","onInvalidate","scrollElement","handleMove","handleClickOutside","createVNode","Teleport","Transition","popupProps","Popup$1","_hoisted_1$2","_hoisted_3$2","createElementVNode","render$2","openBlock","createElementBlock","_hoisted_1$1","_hoisted_3$1","render$1","h2","isValidRangeDate","dates","isValidDates","getValidDate","rest","startOfYear","startOfMonth","startOfDay","getCalendar","calendar","lastDayInLastMonth","firstDayInLastMonth","lastDayInCurrentMonth","nextMonthLength","setMonth","dirtyDate","dirtyMonth","daysInMonth","setYear","dirtyYear","diffCalendarMonths","dirtyDateLeft","dirtyDateRight","dateRight","dateLeft","yearDiff","monthDiff","assignTime","PickerInput","userInput","innerSeparator","isValidValue","isDisabledValue","handleClear","handleChange","text2","handleInput","handleKeydown","keyCode","showClearIcon","inputProps","pickerInputBaseProps","pickerInputProps","PickerInput$1","Picker","getContainer","defaultOpen","popupVisible","openPopup","_a2","closePopup","formatDate","fmt","parseDate","value2date","date2value","innerValue","emitValue","handleSelect","handleConfirm","disabledDateTime","renderSidebar","slotProps","_a3","confirm","range","popupClass","popupStyle","appendToBody","header","sidedar","pickerProps","Picker$1","ButtonIcon","TableHeader","onUpdateCalendar","lastMonth","nextMonth","lastYear","nextYear","lastDecade","nextDecade","TableDate","isWeekMode","showWeekNumber","titleFormat","getWeekActive","getCellClasses","onSelect","onUpdatePanel","onDateMouseEnter","onDateMouseLeave","getWeekNumber","yearFormat","monthBeforeYear","monthFormat","formatLocale","days","handlePanelChange","panel","getCellDate","index2","col","handleCellClick","handleMouseEnter","handleMouseLeave","yearLabel","monthLabel","cell","TableMonth","months","getDate","handleClick","getDefaultYears","firstYear","years","TableYear","getYearPanel","Calendar","innerCalendar","calendarDate","handleCalendarChange","panels","handelPanelChange","oldPanel","isDisabled","emitDate","nextDates","handleSelectDate","handleSelectYear","handleSelectMonth","cellDate","getDateClasses","notCurrentMonth","getMonthClasses","getYearClasses","calendarProps","Calendar$1","inRange","min","max","CalendarRange","defaultValues","handlePick","startValue","endValue","defaultCalendars","calendars","calendarMinDiff","updateCalendars","gap","anotherIndex","updateCalendarStart","updateCalendarEnd","hoveredValue","getRangeClasses","currentDates","classnames","outerClasses","calendarRange","calendarProps2","calendarRangeProps","CalendarRange$1","ScrollbarVertical","defineComponent","wrapper","thumbHeight","thumbTop","getThumbHeight","heightPercentage","scrollbarWidth","draggable","prevY","handleDragstart","offsetTop","handleDraging","handleDragend","Columns","getClasses","currentTarget","_isSlot","isVNode","FixedList","_slot","generateList","step","getColumnOptions","showHour","showMinute","showSecond","use12h","format2","columns","parseOption","getFixedOptions","startMinutes","endMinutes","stepMinutes","timeMinutes","scrollTo","duration","tick","TimePanel","isDisabledTimes","isDisabledHour","isDisabledMinute","isDisabledAMPM","minHour","maxHour","scrollToSelected","timePanelProps","TimePanel$1","TimeRange","emitChange","handleSelectStart","handleSelectEnd","disabledStartTime","disabledEndTime","timeRangeProps","TimeRange$1","useTimePanelVisible","defaultTimeVisible","closeTimePanel","openTimePanel","DateTime","timeVisible","datetime","calendarProp","timeProps","datetimeBaseProps","datetimeProps","DateTime$1","DateTimeRange","datetimes","datetimeRangeProps","DateTimeRange$1","booleanKeys","formatMap","DatePicker","Content","factory","lazySizes","module","Date","lazySizesCfg","lazySizesDefaults","docElem","supportPicture","_addEventListener","_getAttribute","requestAnimationFrame","requestIdleCallback","regPicture","loadEvents","regClassCache","hasClass","cls","addClass","removeClass","reg","addRemoveLoadEvents","dom","triggerEvent","detail","noBubbles","noCancelable","updatePolyfill","full","polyfill","getCSS","getWidth","rAF","running","waiting","firstFns","secondFns","fns","runFns","rafBatch","queue","rAFIt","simple","that","throttle","lastTime","gDelay","rICTimeout","idleCallback","isPriority","timestamp","wait","later","preloadElems","isCompleted","resetPreloadingTimer","loadMode","started","eLvW","elvH","eLtop","eLleft","eLright","eLbottom","isBodyHidden","regImg","regIframe","supportScroll","shrinkExpand","currentExpand","lowRuns","resetPreloading","isNestedVisible","elemExpand","outerRect","visible","checkElements","eLlen","rect","autoLoadElem","loadedSomething","elemNegativeExpand","elemExpandVal","beforeExpandVal","defaultExpand","preloadExpand","hFac","lazyloadElems","unveilElement","throttledCheckElements","switchLoadingClass","rafSwitchLoadingClass","rafedSwitchLoadingClass","changeIframeSrc","handleSources","customMedia","sourceSrcset","lazyUnveil","isAuto","sizes","isImg","srcset","isPicture","firesLoad","isLoaded","autoSizer","afterScroll","altLoadmodeScrollListner","onload","loadingElements","autosizesElems","sizeElement","sources","getSizeElement","dataAttr","updateElementsSizes","debouncedUpdateElementsSizes"],"mappings":"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","x_google_ignoreList":[2,3,4,5,11,12,13,14,15,16,19,20,21,22,26,28,35,36,55,98,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176]}