@genspectrum/dashboard-components 0.6.19 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/custom-elements.json +18 -18
  2. package/dist/assets/mutationOverTimeWorker-BOCXtKzd.js.map +1 -0
  3. package/dist/dashboard-components.js +296 -302
  4. package/dist/dashboard-components.js.map +1 -1
  5. package/dist/genspectrum-components.d.ts +98 -48
  6. package/package.json +1 -3
  7. package/src/index.ts +1 -0
  8. package/src/preact/aggregatedData/aggregate.tsx +41 -33
  9. package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +53 -38
  10. package/src/preact/dateRangeSelector/computeInitialValues.ts +17 -23
  11. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +46 -32
  12. package/src/preact/dateRangeSelector/date-range-selector.tsx +24 -26
  13. package/src/preact/dateRangeSelector/dateRangeOption.ts +65 -0
  14. package/src/preact/dateRangeSelector/selectableOptions.ts +17 -66
  15. package/src/preact/mutationComparison/mutation-comparison.tsx +32 -34
  16. package/src/preact/mutations/mutations.tsx +63 -56
  17. package/src/preact/mutationsOverTime/MutationOverTimeData.ts +20 -0
  18. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +2 -3
  19. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +2 -2
  20. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +3 -3
  21. package/src/preact/mutationsOverTime/mutations-over-time.tsx +40 -43
  22. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +46 -64
  23. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +29 -36
  24. package/src/query/queryMutationsOverTime.ts +3 -5
  25. package/src/utils/map2d.spec.ts +52 -13
  26. package/src/utils/map2d.ts +3 -4
  27. package/src/web-components/input/gs-date-range-selector.stories.ts +16 -28
  28. package/src/web-components/input/gs-date-range-selector.tsx +17 -32
  29. package/standalone-bundle/dashboard-components.js +14322 -15115
  30. package/standalone-bundle/dashboard-components.js.map +1 -1
  31. package/dist/assets/mutationOverTimeWorker-BdzqDqvO.js.map +0 -1
@@ -9,7 +9,6 @@ import { VennDiagramController, ArcSlice, extractSets } from "chartjs-chart-venn
9
9
  import { autoUpdate, computePosition, offset, shift, flip } from "@floating-ui/dom";
10
10
  import { ReactiveElement } from "@lit/reactive-element";
11
11
  import { BarWithErrorBarsController, BarWithErrorBar } from "chartjs-chart-error-bars";
12
- import hash from "object-hash";
13
12
  import flatpickr from "flatpickr";
14
13
  /**
15
14
  * @license
@@ -1931,16 +1930,13 @@ function useQuery(fetchDataCallback, dependencies) {
1931
1930
  }, [JSON.stringify(dependencies)]);
1932
1931
  return { data, error, isLoading };
1933
1932
  }
1934
- const MutationComparison = ({ width, height, ...innerProps }) => {
1933
+ const MutationComparison = (componentProps) => {
1934
+ const { width, height } = componentProps;
1935
1935
  const size = { height, width };
1936
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(MutationComparisonInner, { ...innerProps }) }) });
1936
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(MutationComparisonInner, { ...componentProps }) }) });
1937
1937
  };
1938
- const MutationComparisonInner = ({
1939
- lapisFilters,
1940
- sequenceType,
1941
- views,
1942
- pageSize
1943
- }) => {
1938
+ const MutationComparisonInner = (componentProps) => {
1939
+ const { lapisFilters, sequenceType } = componentProps;
1944
1940
  const lapis = x(LapisUrlContext);
1945
1941
  const { data, error, isLoading } = useQuery(async () => {
1946
1942
  return queryMutationData(lapisFilters, sequenceType, lapis);
@@ -1954,28 +1950,15 @@ const MutationComparisonInner = ({
1954
1950
  if (data === null) {
1955
1951
  return /* @__PURE__ */ u$1(NoDataDisplay, {});
1956
1952
  }
1957
- return /* @__PURE__ */ u$1(
1958
- MutationComparisonTabs,
1959
- {
1960
- data: data.mutationData,
1961
- sequenceType,
1962
- views,
1963
- pageSize
1964
- }
1965
- );
1953
+ return /* @__PURE__ */ u$1(MutationComparisonTabs, { data: data.mutationData, originalComponentProps: componentProps });
1966
1954
  };
1967
- const MutationComparisonTabs = ({
1968
- data,
1969
- views,
1970
- sequenceType,
1971
- pageSize
1972
- }) => {
1955
+ const MutationComparisonTabs = ({ data, originalComponentProps }) => {
1973
1956
  const [proportionInterval, setProportionInterval] = h({ min: 0.5, max: 1 });
1974
1957
  const [displayedMutationTypes, setDisplayedMutationTypes] = h([
1975
1958
  { label: "Substitutions", checked: true, type: "substitution" },
1976
1959
  { label: "Deletions", checked: true, type: "deletion" }
1977
1960
  ]);
1978
- const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(sequenceType);
1961
+ const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(originalComponentProps.sequenceType);
1979
1962
  const filteredData = T(
1980
1963
  () => filterMutationData(data, displayedSegments, displayedMutationTypes),
1981
1964
  [data, displayedSegments, displayedMutationTypes]
@@ -1990,7 +1973,7 @@ const MutationComparisonTabs = ({
1990
1973
  {
1991
1974
  data: { content: filteredData },
1992
1975
  proportionInterval,
1993
- pageSize
1976
+ pageSize: originalComponentProps.pageSize
1994
1977
  }
1995
1978
  )
1996
1979
  };
@@ -2007,7 +1990,7 @@ const MutationComparisonTabs = ({
2007
1990
  };
2008
1991
  }
2009
1992
  };
2010
- const tabs = views.map((view) => getTab(view));
1993
+ const tabs = originalComponentProps.views.map((view) => getTab(view));
2011
1994
  return /* @__PURE__ */ u$1(
2012
1995
  Tabs,
2013
1996
  {
@@ -2021,7 +2004,8 @@ const MutationComparisonTabs = ({
2021
2004
  setDisplayedMutationTypes,
2022
2005
  filteredData,
2023
2006
  proportionInterval,
2024
- setProportionInterval
2007
+ setProportionInterval,
2008
+ originalComponentProps
2025
2009
  }
2026
2010
  )
2027
2011
  }
@@ -2034,7 +2018,8 @@ const Toolbar$5 = ({
2034
2018
  setDisplayedMutationTypes,
2035
2019
  filteredData,
2036
2020
  proportionInterval,
2037
- setProportionInterval
2021
+ setProportionInterval,
2022
+ originalComponentProps
2038
2023
  }) => {
2039
2024
  return /* @__PURE__ */ u$1(Fragment, { children: [
2040
2025
  /* @__PURE__ */ u$1(
@@ -2061,10 +2046,18 @@ const Toolbar$5 = ({
2061
2046
  filename: "mutation_comparison.csv"
2062
2047
  }
2063
2048
  ),
2064
- /* @__PURE__ */ u$1(Info, { children: "Info for mutation comparison" }),
2049
+ /* @__PURE__ */ u$1(MutationComparisonInfo, { originalComponentProps }),
2065
2050
  /* @__PURE__ */ u$1(Fullscreen, {})
2066
2051
  ] });
2067
2052
  };
2053
+ const MutationComparisonInfo = ({ originalComponentProps }) => {
2054
+ const lapis = x(LapisUrlContext);
2055
+ return /* @__PURE__ */ u$1(Info, { children: [
2056
+ /* @__PURE__ */ u$1(InfoHeadline1, { children: "Info for mutation comparison" }),
2057
+ /* @__PURE__ */ u$1(InfoParagraph, { children: "TODO: https://github.com/GenSpectrum/dashboard-components/issues/465" }),
2058
+ /* @__PURE__ */ u$1(InfoComponentCode, { componentName: "mutation-comparison", params: originalComponentProps, lapisUrl: lapis })
2059
+ ] });
2060
+ };
2068
2061
  const gridJsStyle = '.gridjs-head button, .gridjs-footer button {\n cursor: pointer;\n background-color: transparent;\n background-image: none;\n padding: 0;\n margin: 0;\n border: none;\n outline: none;\n}\n\n.gridjs-temp {\n position: relative;\n}\n\n.gridjs-head {\n width: 100%;\n margin-bottom: 5px;\n padding: 5px 1px;\n}\n.gridjs-head::after {\n content: "";\n display: block;\n clear: both;\n}\n.gridjs-head:empty {\n padding: 0;\n border: none;\n}\n\n.gridjs-container {\n overflow: hidden;\n display: inline-block;\n padding: 2px;\n color: #000;\n position: relative;\n z-index: 0;\n}\n\n.gridjs-footer {\n display: block;\n position: relative;\n width: 100%;\n z-index: 5;\n padding: 12px 24px;\n border-top: 1px solid #e5e7eb;\n background-color: #fff;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.26);\n border-radius: 0 0 8px 8px;\n border-bottom-width: 1px;\n border-color: #e5e7eb;\n}\n.gridjs-footer:empty {\n padding: 0;\n border: none;\n}\n\ninput.gridjs-input {\n outline: none;\n background-color: #fff;\n border: 1px solid #d2d6dc;\n border-radius: 5px;\n padding: 10px 13px;\n font-size: 14px;\n line-height: 1.45;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\ninput.gridjs-input:focus {\n box-shadow: 0 0 0 3px rgba(149, 189, 243, 0.5);\n border-color: #9bc2f7;\n}\n\n.gridjs-pagination {\n color: #3d4044;\n}\n.gridjs-pagination::after {\n content: "";\n display: block;\n clear: both;\n}\n.gridjs-pagination .gridjs-summary {\n float: left;\n margin-top: 5px;\n}\n.gridjs-pagination .gridjs-pages {\n float: right;\n}\n.gridjs-pagination .gridjs-pages button {\n padding: 5px 14px;\n border: 1px solid #d2d6dc;\n background-color: #fff;\n border-right: none;\n outline: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n}\n.gridjs-pagination .gridjs-pages button:focus {\n box-shadow: 0 0 0 2px rgba(149, 189, 243, 0.5);\n position: relative;\n margin-right: -1px;\n border-right: 1px solid #d2d6dc;\n}\n.gridjs-pagination .gridjs-pages button:hover {\n background-color: #f7f7f7;\n color: rgb(60, 66, 87);\n outline: none;\n}\n.gridjs-pagination .gridjs-pages button:disabled,\n.gridjs-pagination .gridjs-pages button[disabled],\n.gridjs-pagination .gridjs-pages button:hover:disabled {\n cursor: default;\n background-color: #fff;\n color: #6b7280;\n}\n.gridjs-pagination .gridjs-pages button.gridjs-spread {\n cursor: default;\n box-shadow: none;\n background-color: #fff;\n}\n.gridjs-pagination .gridjs-pages button.gridjs-currentPage {\n background-color: #f7f7f7;\n font-weight: bold;\n}\n.gridjs-pagination .gridjs-pages button:last-child {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n border-right: 1px solid #d2d6dc;\n}\n.gridjs-pagination .gridjs-pages button:first-child {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.gridjs-pagination .gridjs-pages button:last-child:focus {\n margin-right: 0;\n}\n\nbutton.gridjs-sort {\n float: right;\n height: 24px;\n width: 13px;\n background-color: transparent;\n background-repeat: no-repeat;\n background-position-x: center;\n cursor: pointer;\n padding: 0;\n margin: 0;\n border: none;\n outline: none;\n background-size: contain;\n}\nbutton.gridjs-sort-neutral {\n opacity: 0.3;\n background-image: url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHdpZHRoPSI0MDEuOTk4cHgiIGhlaWdodD0iNDAxLjk5OHB4IiB2aWV3Qm94PSIwIDAgNDAxLjk5OCA0MDEuOTk4IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA0MDEuOTk4IDQwMS45OTg7IgoJIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxnPgoJCTxwYXRoIGQ9Ik03My4wOTIsMTY0LjQ1MmgyNTUuODEzYzQuOTQ5LDAsOS4yMzMtMS44MDcsMTIuODQ4LTUuNDI0YzMuNjEzLTMuNjE2LDUuNDI3LTcuODk4LDUuNDI3LTEyLjg0NwoJCQljMC00Ljk0OS0xLjgxMy05LjIyOS01LjQyNy0xMi44NUwyMTMuODQ2LDUuNDI0QzIxMC4yMzIsMS44MTIsMjA1Ljk1MSwwLDIwMC45OTksMHMtOS4yMzMsMS44MTItMTIuODUsNS40MjRMNjAuMjQyLDEzMy4zMzEKCQkJYy0zLjYxNywzLjYxNy01LjQyNCw3LjkwMS01LjQyNCwxMi44NWMwLDQuOTQ4LDEuODA3LDkuMjMxLDUuNDI0LDEyLjg0N0M2My44NjMsMTYyLjY0NSw2OC4xNDQsMTY0LjQ1Miw3My4wOTIsMTY0LjQ1MnoiLz4KCQk8cGF0aCBkPSJNMzI4LjkwNSwyMzcuNTQ5SDczLjA5MmMtNC45NTIsMC05LjIzMywxLjgwOC0xMi44NSw1LjQyMWMtMy42MTcsMy42MTctNS40MjQsNy44OTgtNS40MjQsMTIuODQ3CgkJCWMwLDQuOTQ5LDEuODA3LDkuMjMzLDUuNDI0LDEyLjg0OEwxODguMTQ5LDM5Ni41N2MzLjYyMSwzLjYxNyw3LjkwMiw1LjQyOCwxMi44NSw1LjQyOHM5LjIzMy0xLjgxMSwxMi44NDctNS40MjhsMTI3LjkwNy0xMjcuOTA2CgkJCWMzLjYxMy0zLjYxNCw1LjQyNy03Ljg5OCw1LjQyNy0xMi44NDhjMC00Ljk0OC0xLjgxMy05LjIyOS01LjQyNy0xMi44NDdDMzM4LjEzOSwyMzkuMzUzLDMzMy44NTQsMjM3LjU0OSwzMjguOTA1LDIzNy41NDl6Ii8+Cgk8L2c+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+");\n background-position-y: center;\n}\nbutton.gridjs-sort-asc {\n background-image: url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHdpZHRoPSIyOTIuMzYycHgiIGhlaWdodD0iMjkyLjM2MXB4IiB2aWV3Qm94PSIwIDAgMjkyLjM2MiAyOTIuMzYxIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyOTIuMzYyIDI5Mi4zNjE7IgoJIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxwYXRoIGQ9Ik0yODYuOTM1LDE5Ny4yODdMMTU5LjAyOCw2OS4zODFjLTMuNjEzLTMuNjE3LTcuODk1LTUuNDI0LTEyLjg0Ny01LjQyNHMtOS4yMzMsMS44MDctMTIuODUsNS40MjRMNS40MjQsMTk3LjI4NwoJCUMxLjgwNywyMDAuOTA0LDAsMjA1LjE4NiwwLDIxMC4xMzRzMS44MDcsOS4yMzMsNS40MjQsMTIuODQ3YzMuNjIxLDMuNjE3LDcuOTAyLDUuNDI1LDEyLjg1LDUuNDI1aDI1NS44MTMKCQljNC45NDksMCw5LjIzMy0xLjgwOCwxMi44NDgtNS40MjVjMy42MTMtMy42MTMsNS40MjctNy44OTgsNS40MjctMTIuODQ3UzI5MC41NDgsMjAwLjkwNCwyODYuOTM1LDE5Ny4yODd6Ii8+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+");\n background-position-y: 35%;\n background-size: 10px;\n}\nbutton.gridjs-sort-desc {\n background-image: url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHdpZHRoPSIyOTIuMzYycHgiIGhlaWdodD0iMjkyLjM2MnB4IiB2aWV3Qm94PSIwIDAgMjkyLjM2MiAyOTIuMzYyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyOTIuMzYyIDI5Mi4zNjI7IgoJIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxwYXRoIGQ9Ik0yODYuOTM1LDY5LjM3N2MtMy42MTQtMy42MTctNy44OTgtNS40MjQtMTIuODQ4LTUuNDI0SDE4LjI3NGMtNC45NTIsMC05LjIzMywxLjgwNy0xMi44NSw1LjQyNAoJCUMxLjgwNyw3Mi45OTgsMCw3Ny4yNzksMCw4Mi4yMjhjMCw0Ljk0OCwxLjgwNyw5LjIyOSw1LjQyNCwxMi44NDdsMTI3LjkwNywxMjcuOTA3YzMuNjIxLDMuNjE3LDcuOTAyLDUuNDI4LDEyLjg1LDUuNDI4CgkJczkuMjMzLTEuODExLDEyLjg0Ny01LjQyOEwyODYuOTM1LDk1LjA3NGMzLjYxMy0zLjYxNyw1LjQyNy03Ljg5OCw1LjQyNy0xMi44NDdDMjkyLjM2Miw3Ny4yNzksMjkwLjU0OCw3Mi45OTgsMjg2LjkzNSw2OS4zNzd6Ii8+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+");\n background-position-y: 65%;\n background-size: 10px;\n}\nbutton.gridjs-sort:focus {\n outline: none;\n}\n\ntable.gridjs-table {\n width: 100%;\n max-width: 100%;\n border-collapse: collapse;\n text-align: left;\n display: table;\n margin: 0;\n padding: 0;\n overflow: auto;\n table-layout: fixed;\n}\n\n.gridjs-tbody {\n background-color: #fff;\n}\n\ntd.gridjs-td {\n border: 1px solid #e5e7eb;\n padding: 12px 24px;\n background-color: #fff;\n box-sizing: content-box;\n}\ntd.gridjs-td:first-child {\n border-left: none;\n}\ntd.gridjs-td:last-child {\n border-right: none;\n}\ntd.gridjs-message {\n text-align: center;\n}\n\nth.gridjs-th {\n position: relative;\n color: #6b7280;\n background-color: #f9fafb;\n border: 1px solid #e5e7eb;\n border-top: none;\n padding: 14px 24px;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n box-sizing: border-box;\n white-space: nowrap;\n outline: none;\n vertical-align: middle;\n}\nth.gridjs-th .gridjs-th-content {\n text-overflow: ellipsis;\n overflow: hidden;\n width: 100%;\n float: left;\n}\nth.gridjs-th-sort {\n cursor: pointer;\n}\nth.gridjs-th-sort .gridjs-th-content {\n width: calc(100% - 15px);\n}\nth.gridjs-th-sort:hover {\n background-color: #e5e7eb;\n}\nth.gridjs-th-sort:focus {\n background-color: #e5e7eb;\n}\nth.gridjs-th-fixed {\n position: sticky;\n box-shadow: 0 1px 0 0 #e5e7eb;\n}\n@supports (-moz-appearance: none) {\n th.gridjs-th-fixed {\n box-shadow: 0 0 0 1px #e5e7eb;\n }\n}\nth.gridjs-th:first-child {\n border-left: none;\n}\nth.gridjs-th:last-child {\n border-right: none;\n}\n\n.gridjs-tr {\n border: none;\n}\n.gridjs-tr-selected td {\n background-color: #ebf5ff;\n}\n.gridjs-tr:last-child td {\n border-bottom: 0;\n}\n\n.gridjs *,\n.gridjs :after,\n.gridjs :before {\n box-sizing: border-box;\n}\n\n.gridjs-wrapper {\n position: relative;\n z-index: 1;\n overflow: auto;\n width: 100%;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.26);\n border-radius: 8px 8px 0 0;\n display: block;\n border-top-width: 1px;\n border-color: #e5e7eb;\n}\n.gridjs-wrapper:nth-last-of-type(2) {\n border-radius: 8px;\n border-bottom-width: 1px;\n}\n\n.gridjs-search {\n float: left;\n}\n.gridjs-search-input {\n width: 250px;\n}\n\n.gridjs-loading-bar {\n z-index: 10;\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n background-color: #fff;\n opacity: 0.5;\n}\n.gridjs-loading-bar::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n transform: translateX(-100%);\n background-image: linear-gradient(90deg, rgba(204, 204, 204, 0) 0, rgba(204, 204, 204, 0.2) 20%, rgba(204, 204, 204, 0.5) 60%, rgba(204, 204, 204, 0));\n animation: shimmer 2s infinite;\n content: "";\n}\n@keyframes shimmer {\n 100% {\n transform: translateX(100%);\n }\n}\n\n.gridjs-td .gridjs-checkbox {\n display: block;\n margin: auto;\n cursor: pointer;\n}\n\n.gridjs-resizable {\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n width: 5px;\n}\n.gridjs-resizable:hover {\n cursor: ew-resize;\n background-color: #9bc2f7;\n}\n/*# sourceMappingURL=mermaid.css?inline.map */';
2069
2062
  const minMaxPercentSliderCss = 'input[type=range]::-webkit-slider-thumb {\n -webkit-appearance: none;\n pointer-events: all;\n width: 24px;\n height: 24px;\n background-color: #fff;\n border-radius: 50%;\n box-shadow: 0 0 0 1px #C6C6C6;\n cursor: pointer;\n}\n\ninput[type=range]::-moz-range-thumb {\n -webkit-appearance: none;\n pointer-events: all;\n width: 24px;\n height: 24px;\n background-color: #fff;\n border-radius: 50%;\n box-shadow: 0 0 0 1px #C6C6C6;\n cursor: pointer;\n}\n\ninput[type=range]::-webkit-slider-thumb:hover {\n background: #f7f7f7;\n}\n\ninput[type=range]::-webkit-slider-thumb:active {\n box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;\n -webkit-box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;\n}\n\ninput[type="range"] {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n height: 2px;\n width: 100%;\n position: absolute;\n background-color: #C6C6C6;\n pointer-events: none;\n}';
2070
2063
  const tailwindStyle = `*, ::before, ::after {
@@ -5446,17 +5439,14 @@ function filterMutationsData(data, displayedSegments, displayedMutationTypes) {
5446
5439
  gridData: filteredSubstitutionsOrDeletions
5447
5440
  };
5448
5441
  }
5449
- const Mutations = ({ width, height, ...innerProps }) => {
5442
+ const Mutations = (componentProps) => {
5443
+ const { width, height } = componentProps;
5450
5444
  const size = { height, width };
5451
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(MutationsInner, { ...innerProps }) }) });
5445
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(MutationsInner, { ...componentProps }) }) });
5452
5446
  };
5453
- const MutationsInner = ({
5454
- lapisFilter,
5455
- sequenceType,
5456
- views,
5457
- pageSize
5458
- }) => {
5447
+ const MutationsInner = (componentProps) => {
5459
5448
  const lapis = x(LapisUrlContext);
5449
+ const { lapisFilter, sequenceType } = componentProps;
5460
5450
  const { data, error, isLoading } = useQuery(async () => {
5461
5451
  return queryMutationsData(lapisFilter, sequenceType, lapis);
5462
5452
  }, [lapisFilter, sequenceType, lapis]);
@@ -5469,11 +5459,11 @@ const MutationsInner = ({
5469
5459
  if (data === null) {
5470
5460
  return /* @__PURE__ */ u$1(NoDataDisplay, {});
5471
5461
  }
5472
- return /* @__PURE__ */ u$1(MutationsTabs, { mutationsData: data, sequenceType, views, pageSize });
5462
+ return /* @__PURE__ */ u$1(MutationsTabs, { mutationsData: data, originalComponentProps: componentProps });
5473
5463
  };
5474
- const MutationsTabs = ({ mutationsData, sequenceType, views, pageSize }) => {
5464
+ const MutationsTabs = ({ mutationsData, originalComponentProps }) => {
5475
5465
  const [proportionInterval, setProportionInterval] = h({ min: 0.05, max: 1 });
5476
- const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(sequenceType);
5466
+ const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(originalComponentProps.sequenceType);
5477
5467
  const [displayedMutationTypes, setDisplayedMutationTypes] = h([
5478
5468
  { label: "Substitutions", checked: true, type: "substitution" },
5479
5469
  { label: "Deletions", checked: true, type: "deletion" }
@@ -5489,7 +5479,7 @@ const MutationsTabs = ({ mutationsData, sequenceType, views, pageSize }) => {
5489
5479
  {
5490
5480
  data: filteredData.tableData,
5491
5481
  proportionInterval,
5492
- pageSize
5482
+ pageSize: originalComponentProps.pageSize
5493
5483
  }
5494
5484
  )
5495
5485
  };
@@ -5500,20 +5490,20 @@ const MutationsTabs = ({ mutationsData, sequenceType, views, pageSize }) => {
5500
5490
  MutationsGrid,
5501
5491
  {
5502
5492
  data: filteredData.gridData,
5503
- sequenceType,
5493
+ sequenceType: originalComponentProps.sequenceType,
5504
5494
  proportionInterval,
5505
- pageSize
5495
+ pageSize: originalComponentProps.pageSize
5506
5496
  }
5507
5497
  )
5508
5498
  };
5509
5499
  case "insertions":
5510
5500
  return {
5511
5501
  title: "Insertions",
5512
- content: /* @__PURE__ */ u$1(InsertionsTable, { data: filteredData.insertions, pageSize })
5502
+ content: /* @__PURE__ */ u$1(InsertionsTable, { data: filteredData.insertions, pageSize: originalComponentProps.pageSize })
5513
5503
  };
5514
5504
  }
5515
5505
  };
5516
- const tabs = views.map((view) => getTab(view));
5506
+ const tabs = originalComponentProps.views.map((view) => getTab(view));
5517
5507
  const toolbar = (activeTab) => /* @__PURE__ */ u$1(
5518
5508
  Toolbar$4,
5519
5509
  {
@@ -5524,7 +5514,8 @@ const MutationsTabs = ({ mutationsData, sequenceType, views, pageSize }) => {
5524
5514
  setDisplayedMutationTypes,
5525
5515
  filteredData,
5526
5516
  proportionInterval,
5527
- setProportionInterval
5517
+ setProportionInterval,
5518
+ originalComponentProps
5528
5519
  }
5529
5520
  );
5530
5521
  return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar });
@@ -5537,7 +5528,8 @@ const Toolbar$4 = ({
5537
5528
  setDisplayedMutationTypes,
5538
5529
  filteredData,
5539
5530
  proportionInterval,
5540
- setProportionInterval
5531
+ setProportionInterval,
5532
+ originalComponentProps
5541
5533
  }) => {
5542
5534
  return /* @__PURE__ */ u$1(Fragment, { children: [
5543
5535
  /* @__PURE__ */ u$1(SegmentSelector, { displayedSegments, setDisplayedSegments }),
@@ -5579,39 +5571,43 @@ const Toolbar$4 = ({
5579
5571
  filename: "insertions.csv"
5580
5572
  }
5581
5573
  ),
5582
- /* @__PURE__ */ u$1(MutationsInfo, {}),
5574
+ /* @__PURE__ */ u$1(MutationsInfo, { originalComponentProps }),
5583
5575
  /* @__PURE__ */ u$1(Fullscreen, {})
5584
5576
  ] });
5585
5577
  };
5586
- const MutationsInfo = () => /* @__PURE__ */ u$1(Info, { children: [
5587
- /* @__PURE__ */ u$1(InfoHeadline1, { children: "Mutations" }),
5588
- /* @__PURE__ */ u$1(InfoParagraph, { children: [
5589
- "This shows mutations of a variant. There are three types of mutations:",
5590
- " ",
5591
- /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Substitution", children: "substitutions" }),
5592
- ",",
5593
- " ",
5594
- /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Deletion", children: "deletions" }),
5595
- " and",
5596
- " ",
5597
- /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Insertion", children: "insertions" }),
5598
- "."
5599
- ] }),
5600
- /* @__PURE__ */ u$1(InfoHeadline2, { children: "Proportion calculation" }),
5601
- /* @__PURE__ */ u$1(InfoParagraph, { children: "The proportion of a mutation is calculated by dividing the number of sequences with the mutation by the total number of sequences with a non-ambiguous symbol at the position." }),
5602
- /* @__PURE__ */ u$1(InfoParagraph, { children: [
5603
- /* @__PURE__ */ u$1("b", { children: "Example:" }),
5604
- " Assume we look at nucleotide mutations at position 5 where the reference has a T and assume there are 10 sequences in total:",
5605
- /* @__PURE__ */ u$1("ul", { className: "list-disc list-inside ml-2", children: [
5606
- /* @__PURE__ */ u$1("li", { children: "3 sequences have a C," }),
5607
- /* @__PURE__ */ u$1("li", { children: "2 sequences have a T," }),
5608
- /* @__PURE__ */ u$1("li", { children: "1 sequence has a G," }),
5609
- /* @__PURE__ */ u$1("li", { children: "3 sequences have an N," }),
5610
- /* @__PURE__ */ u$1("li", { children: "1 sequence has a Y (which means T or C)," })
5578
+ const MutationsInfo = ({ originalComponentProps }) => {
5579
+ const lapis = x(LapisUrlContext);
5580
+ return /* @__PURE__ */ u$1(Info, { children: [
5581
+ /* @__PURE__ */ u$1(InfoHeadline1, { children: "Mutations" }),
5582
+ /* @__PURE__ */ u$1(InfoParagraph, { children: [
5583
+ "This shows mutations of a variant. There are three types of mutations:",
5584
+ " ",
5585
+ /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Substitution", children: "substitutions" }),
5586
+ ",",
5587
+ " ",
5588
+ /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Deletion", children: "deletions" }),
5589
+ " and",
5590
+ " ",
5591
+ /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Insertion", children: "insertions" }),
5592
+ "."
5593
+ ] }),
5594
+ /* @__PURE__ */ u$1(InfoHeadline2, { children: "Proportion calculation" }),
5595
+ /* @__PURE__ */ u$1(InfoParagraph, { children: "The proportion of a mutation is calculated by dividing the number of sequences with the mutation by the total number of sequences with a non-ambiguous symbol at the position." }),
5596
+ /* @__PURE__ */ u$1(InfoParagraph, { children: [
5597
+ /* @__PURE__ */ u$1("b", { children: "Example:" }),
5598
+ " Assume we look at nucleotide mutations at position 5 where the reference has a T and assume there are 10 sequences in total:",
5599
+ /* @__PURE__ */ u$1("ul", { className: "list-disc list-inside ml-2", children: [
5600
+ /* @__PURE__ */ u$1("li", { children: "3 sequences have a C," }),
5601
+ /* @__PURE__ */ u$1("li", { children: "2 sequences have a T," }),
5602
+ /* @__PURE__ */ u$1("li", { children: "1 sequence has a G," }),
5603
+ /* @__PURE__ */ u$1("li", { children: "3 sequences have an N," }),
5604
+ /* @__PURE__ */ u$1("li", { children: "1 sequence has a Y (which means T or C)," })
5605
+ ] }),
5606
+ "then the proportion of the T5C mutation is 50%. The 4 sequences that have an N or Y are excluded from the calculation."
5611
5607
  ] }),
5612
- "then the proportion of the T5C mutation is 50%. The 4 sequences that have an N or Y are excluded from the calculation."
5613
- ] })
5614
- ] });
5608
+ /* @__PURE__ */ u$1(InfoComponentCode, { componentName: "mutations", params: originalComponentProps, lapisUrl: lapis })
5609
+ ] });
5610
+ };
5615
5611
  var __defProp$a = Object.defineProperty;
5616
5612
  var __getOwnPropDesc$a = Object.getOwnPropertyDescriptor;
5617
5613
  var __decorateClass$a = (decorators, target, key, kind) => {
@@ -7769,27 +7765,18 @@ function toYearMonthDay(d2) {
7769
7765
  count: d2.count
7770
7766
  };
7771
7767
  }
7772
- const RelativeGrowthAdvantage = ({
7773
- width,
7774
- height,
7775
- ...innerProps
7776
- }) => {
7768
+ const RelativeGrowthAdvantage = (componentProps) => {
7769
+ const { width, height } = componentProps;
7777
7770
  const size = { height, width };
7778
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(RelativeGrowthAdvantageInner, { ...innerProps }) }) });
7779
- };
7780
- const RelativeGrowthAdvantageInner = ({
7781
- numeratorFilter,
7782
- denominatorFilter,
7783
- generationTime,
7784
- views,
7785
- lapisDateField,
7786
- yAxisMaxConfig
7787
- }) => {
7771
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(RelativeGrowthAdvantageInner, { ...componentProps }) }) });
7772
+ };
7773
+ const RelativeGrowthAdvantageInner = (componentProps) => {
7788
7774
  const lapis = x(LapisUrlContext);
7775
+ const { numeratorFilter, denominatorFilter, generationTime, lapisDateField } = componentProps;
7789
7776
  const [yAxisScaleType, setYAxisScaleType] = h("linear");
7790
7777
  const { data, error, isLoading } = useQuery(
7791
7778
  () => queryRelativeGrowthAdvantage(numeratorFilter, denominatorFilter, generationTime, lapis, lapisDateField),
7792
- [lapis, numeratorFilter, denominatorFilter, generationTime, views, lapisDateField]
7779
+ [lapis, numeratorFilter, denominatorFilter, generationTime, lapisDateField]
7793
7780
  );
7794
7781
  if (isLoading) {
7795
7782
  return /* @__PURE__ */ u$1(LoadingDisplay, {});
@@ -7806,9 +7793,7 @@ const RelativeGrowthAdvantageInner = ({
7806
7793
  data,
7807
7794
  yAxisScaleType,
7808
7795
  setYAxisScaleType,
7809
- views,
7810
- generationTime,
7811
- yAxisMaxConfig
7796
+ originalComponentProps: componentProps
7812
7797
  }
7813
7798
  );
7814
7799
  };
@@ -7816,9 +7801,7 @@ const RelativeGrowthAdvantageTabs = ({
7816
7801
  data,
7817
7802
  yAxisScaleType,
7818
7803
  setYAxisScaleType,
7819
- views,
7820
- generationTime,
7821
- yAxisMaxConfig
7804
+ originalComponentProps
7822
7805
  }) => {
7823
7806
  const getTab = (view) => {
7824
7807
  switch (view) {
@@ -7834,17 +7817,17 @@ const RelativeGrowthAdvantageTabs = ({
7834
7817
  params: data.params
7835
7818
  },
7836
7819
  yAxisScaleType,
7837
- yAxisMaxConfig
7820
+ yAxisMaxConfig: originalComponentProps.yAxisMaxConfig
7838
7821
  }
7839
7822
  )
7840
7823
  };
7841
7824
  }
7842
7825
  };
7843
- const tabs = views.map((view) => getTab(view));
7826
+ const tabs = originalComponentProps.views.map((view) => getTab(view));
7844
7827
  const toolbar = () => /* @__PURE__ */ u$1(
7845
7828
  RelativeGrowthAdvantageToolbar,
7846
7829
  {
7847
- generationTime,
7830
+ originalComponentProps,
7848
7831
  yAxisScaleType,
7849
7832
  setYAxisScaleType
7850
7833
  }
@@ -7854,15 +7837,19 @@ const RelativeGrowthAdvantageTabs = ({
7854
7837
  const RelativeGrowthAdvantageToolbar = ({
7855
7838
  yAxisScaleType,
7856
7839
  setYAxisScaleType,
7857
- generationTime
7840
+ originalComponentProps
7858
7841
  }) => {
7859
7842
  return /* @__PURE__ */ u$1(Fragment, { children: [
7860
7843
  /* @__PURE__ */ u$1(ScalingSelector, { yAxisScaleType, setYAxisScaleType }),
7861
- /* @__PURE__ */ u$1(RelativeGrowthAdvantageInfo, { generationTime }),
7844
+ /* @__PURE__ */ u$1(RelativeGrowthAdvantageInfo, { originalComponentProps }),
7862
7845
  /* @__PURE__ */ u$1(Fullscreen, {})
7863
7846
  ] });
7864
7847
  };
7865
- const RelativeGrowthAdvantageInfo = ({ generationTime }) => {
7848
+ const RelativeGrowthAdvantageInfo = ({
7849
+ originalComponentProps
7850
+ }) => {
7851
+ const lapis = x(LapisUrlContext);
7852
+ const generationTime = originalComponentProps.generationTime;
7866
7853
  return /* @__PURE__ */ u$1(Info, { children: [
7867
7854
  /* @__PURE__ */ u$1(InfoHeadline1, { children: "Relative growth advantage" }),
7868
7855
  /* @__PURE__ */ u$1(InfoParagraph, { children: [
@@ -7880,7 +7867,15 @@ const RelativeGrowthAdvantageInfo = ({ generationTime }) => {
7880
7867
  'Chen, Chaoran, et al. "Quantification of the spread of SARS-CoV-2 variant B.1.1.7 in Switzerland." Epidemics (2021); doi:',
7881
7868
  " ",
7882
7869
  /* @__PURE__ */ u$1(InfoLink, { href: "https://www.sciencedirect.com/science/article/pii/S1755436521000335?via=ihub", children: "10.1016/j.epidem.2021.100480" })
7883
- ] })
7870
+ ] }),
7871
+ /* @__PURE__ */ u$1(
7872
+ InfoComponentCode,
7873
+ {
7874
+ componentName: "relative-growth-advantage",
7875
+ params: originalComponentProps,
7876
+ lapisUrl: lapis
7877
+ }
7878
+ )
7884
7879
  ] });
7885
7880
  };
7886
7881
  var __defProp$8 = Object.defineProperty;
@@ -8003,18 +7998,13 @@ const AggregateTable = ({ data, fields, pageSize }) => {
8003
7998
  ];
8004
7999
  return /* @__PURE__ */ u$1(Table, { data, columns: headers, pageSize });
8005
8000
  };
8006
- const Aggregate = ({ width, height, ...innerProps }) => {
8001
+ const Aggregate = (componentProps) => {
8002
+ const { width, height } = componentProps;
8007
8003
  const size = { height, width };
8008
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(AggregateInner, { ...innerProps }) }) });
8009
- };
8010
- const AggregateInner = ({
8011
- fields,
8012
- views,
8013
- filter,
8014
- initialSortField,
8015
- initialSortDirection,
8016
- pageSize
8017
- }) => {
8004
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(AggregateInner, { ...componentProps }) }) });
8005
+ };
8006
+ const AggregateInner = (componentProps) => {
8007
+ const { fields, filter, initialSortField, initialSortDirection } = componentProps;
8018
8008
  const lapis = x(LapisUrlContext);
8019
8009
  const { data, error, isLoading } = useQuery(async () => {
8020
8010
  return queryAggregateData(filter, fields, lapis, { field: initialSortField, direction: initialSortDirection });
@@ -8028,36 +8018,48 @@ const AggregateInner = ({
8028
8018
  if (data === null) {
8029
8019
  return /* @__PURE__ */ u$1(NoDataDisplay, {});
8030
8020
  }
8031
- return /* @__PURE__ */ u$1(AggregatedDataTabs, { data, views, fields, pageSize });
8021
+ return /* @__PURE__ */ u$1(AggregatedDataTabs, { data, originalComponentProps: componentProps });
8032
8022
  };
8033
- const AggregatedDataTabs = ({ data, views, fields, pageSize }) => {
8023
+ const AggregatedDataTabs = ({ data, originalComponentProps }) => {
8034
8024
  const getTab = (view) => {
8035
8025
  switch (view) {
8036
8026
  case "table":
8037
8027
  return {
8038
8028
  title: "Table",
8039
- content: /* @__PURE__ */ u$1(AggregateTable, { data, fields, pageSize })
8029
+ content: /* @__PURE__ */ u$1(
8030
+ AggregateTable,
8031
+ {
8032
+ data,
8033
+ fields: originalComponentProps.fields,
8034
+ pageSize: originalComponentProps.pageSize
8035
+ }
8036
+ )
8040
8037
  };
8041
8038
  }
8042
8039
  };
8043
- const tabs = views.map((view) => getTab(view));
8044
- return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar: /* @__PURE__ */ u$1(Toolbar$2, { data, fields }) });
8040
+ const tabs = originalComponentProps.views.map((view) => getTab(view));
8041
+ return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar: /* @__PURE__ */ u$1(Toolbar$2, { data, originalComponentProps }) });
8045
8042
  };
8046
- const Toolbar$2 = ({ data, fields }) => {
8043
+ const Toolbar$2 = ({ data, originalComponentProps }) => {
8047
8044
  return /* @__PURE__ */ u$1("div", { class: "flex flex-row", children: [
8048
8045
  /* @__PURE__ */ u$1(CsvDownloadButton, { className: "mx-1 btn btn-xs", getData: () => data, filename: "aggregate.csv" }),
8049
- /* @__PURE__ */ u$1(Info, { children: [
8050
- /* @__PURE__ */ u$1(InfoHeadline1, { children: "Aggregated data" }),
8051
- /* @__PURE__ */ u$1(InfoParagraph, { children: [
8052
- "This table shows the number and proportion of sequences stratified by the following fields:",
8053
- " ",
8054
- fields.join(", "),
8055
- ". The proportion is calculated with respect to the total count within the filtered dataset."
8056
- ] })
8057
- ] }),
8046
+ /* @__PURE__ */ u$1(AggregateInfo, { originalComponentProps }),
8058
8047
  /* @__PURE__ */ u$1(Fullscreen, {})
8059
8048
  ] });
8060
8049
  };
8050
+ const AggregateInfo = ({ originalComponentProps }) => {
8051
+ const lapis = x(LapisUrlContext);
8052
+ return /* @__PURE__ */ u$1(Info, { children: [
8053
+ /* @__PURE__ */ u$1(InfoHeadline1, { children: "Aggregated data" }),
8054
+ /* @__PURE__ */ u$1(InfoParagraph, { children: [
8055
+ "This table shows the number and proportion of sequences stratified by the following fields:",
8056
+ " ",
8057
+ originalComponentProps.fields.join(", "),
8058
+ ". The proportion is calculated with respect to the total count within the filtered dataset."
8059
+ ] }),
8060
+ /* @__PURE__ */ u$1(InfoComponentCode, { componentName: "aggregate", params: originalComponentProps, lapisUrl: lapis })
8061
+ ] });
8062
+ };
8061
8063
  var __defProp$7 = Object.defineProperty;
8062
8064
  var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
8063
8065
  var __decorateClass$7 = (decorators, target, key, kind) => {
@@ -8279,18 +8281,13 @@ async function queryNumberOfSequencesOverTime(lapis, lapisFilter, lapisDateField
8279
8281
  });
8280
8282
  return Promise.all(queries);
8281
8283
  }
8282
- const NumberSequencesOverTime = ({ width, height, ...innerProps }) => {
8284
+ const NumberSequencesOverTime = (componentProps) => {
8285
+ const { width, height } = componentProps;
8283
8286
  const size = { height, width };
8284
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(NumberSequencesOverTimeInner, { ...innerProps }) }) });
8285
- };
8286
- const NumberSequencesOverTimeInner = ({
8287
- lapisFilter,
8288
- granularity,
8289
- smoothingWindow,
8290
- lapisDateField,
8291
- views,
8292
- pageSize
8293
- }) => {
8287
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(NumberSequencesOverTimeInner, { ...componentProps }) }) });
8288
+ };
8289
+ const NumberSequencesOverTimeInner = (componentProps) => {
8290
+ const { lapisFilter, lapisDateField, granularity, smoothingWindow } = componentProps;
8294
8291
  const lapis = x(LapisUrlContext);
8295
8292
  const { data, error, isLoading } = useQuery(
8296
8293
  () => queryNumberOfSequencesOverTime(lapis, lapisFilter, lapisDateField, granularity, smoothingWindow),
@@ -8305,24 +8302,9 @@ const NumberSequencesOverTimeInner = ({
8305
8302
  if (data === null) {
8306
8303
  return /* @__PURE__ */ u$1(NoDataDisplay, {});
8307
8304
  }
8308
- return /* @__PURE__ */ u$1(
8309
- NumberSequencesOverTimeTabs,
8310
- {
8311
- views,
8312
- data,
8313
- granularity,
8314
- smoothingWindow,
8315
- pageSize
8316
- }
8317
- );
8305
+ return /* @__PURE__ */ u$1(NumberSequencesOverTimeTabs, { data, originalComponentProps: componentProps });
8318
8306
  };
8319
- const NumberSequencesOverTimeTabs = ({
8320
- views,
8321
- data,
8322
- granularity,
8323
- smoothingWindow,
8324
- pageSize
8325
- }) => {
8307
+ const NumberSequencesOverTimeTabs = ({ data, originalComponentProps }) => {
8326
8308
  const [yAxisScaleType, setYAxisScaleType] = h("linear");
8327
8309
  const getTab = (view) => {
8328
8310
  switch (view) {
@@ -8339,7 +8321,14 @@ const NumberSequencesOverTimeTabs = ({
8339
8321
  case "table":
8340
8322
  return {
8341
8323
  title: "Table",
8342
- content: /* @__PURE__ */ u$1(NumberSequencesOverTimeTable, { data, granularity, pageSize })
8324
+ content: /* @__PURE__ */ u$1(
8325
+ NumberSequencesOverTimeTable,
8326
+ {
8327
+ data,
8328
+ granularity: originalComponentProps.granularity,
8329
+ pageSize: originalComponentProps.pageSize
8330
+ }
8331
+ )
8343
8332
  };
8344
8333
  default:
8345
8334
  throw new Error(`Unknown view: ${view}`);
@@ -8348,29 +8337,21 @@ const NumberSequencesOverTimeTabs = ({
8348
8337
  return /* @__PURE__ */ u$1(
8349
8338
  Tabs,
8350
8339
  {
8351
- tabs: views.map((view) => getTab(view)),
8340
+ tabs: originalComponentProps.views.map((view) => getTab(view)),
8352
8341
  toolbar: (activeTab) => /* @__PURE__ */ u$1(
8353
8342
  Toolbar$1,
8354
8343
  {
8355
8344
  activeTab,
8356
8345
  data,
8357
- granularity,
8358
- smoothingWindow,
8359
8346
  yAxisScaleType,
8360
- setYAxisScaleType
8347
+ setYAxisScaleType,
8348
+ originalComponentProps
8361
8349
  }
8362
8350
  )
8363
8351
  }
8364
8352
  );
8365
8353
  };
8366
- const Toolbar$1 = ({
8367
- activeTab,
8368
- data,
8369
- granularity,
8370
- yAxisScaleType,
8371
- setYAxisScaleType,
8372
- smoothingWindow
8373
- }) => {
8354
+ const Toolbar$1 = ({ activeTab, data, yAxisScaleType, setYAxisScaleType, originalComponentProps }) => {
8374
8355
  return /* @__PURE__ */ u$1(Fragment, { children: [
8375
8356
  activeTab !== "Table" && /* @__PURE__ */ u$1(
8376
8357
  ScalingSelector,
@@ -8384,26 +8365,37 @@ const Toolbar$1 = ({
8384
8365
  CsvDownloadButton,
8385
8366
  {
8386
8367
  className: "mx-1 btn btn-xs",
8387
- getData: () => getNumberOfSequencesOverTimeTableData(data, granularity),
8368
+ getData: () => getNumberOfSequencesOverTimeTableData(data, originalComponentProps.granularity),
8388
8369
  filename: "number_of_sequences_over_time.csv"
8389
8370
  }
8390
8371
  ),
8391
- /* @__PURE__ */ u$1(NumberSequencesOverTimeInfo, { granularity, smoothingWindow }),
8372
+ /* @__PURE__ */ u$1(NumberSequencesOverTimeInfo, { originalComponentProps }),
8392
8373
  /* @__PURE__ */ u$1(Fullscreen, {})
8393
8374
  ] });
8394
8375
  };
8395
8376
  const NumberSequencesOverTimeInfo = ({
8396
- granularity,
8397
- smoothingWindow
8398
- }) => /* @__PURE__ */ u$1(Info, { children: [
8399
- /* @__PURE__ */ u$1(InfoHeadline1, { children: "Number of sequences over time" }),
8400
- /* @__PURE__ */ u$1(InfoParagraph, { children: [
8401
- "This presents the number of available sequences of a variant per ",
8402
- /* @__PURE__ */ u$1("b", { children: granularity }),
8403
- smoothingWindow > 0 && `, smoothed using a ${smoothingWindow}-${granularity} sliding window`,
8404
- "."
8405
- ] })
8406
- ] });
8377
+ originalComponentProps
8378
+ }) => {
8379
+ const lapis = x(LapisUrlContext);
8380
+ return /* @__PURE__ */ u$1(Info, { children: [
8381
+ /* @__PURE__ */ u$1(InfoHeadline1, { children: "Number of sequences over time" }),
8382
+ /* @__PURE__ */ u$1(InfoParagraph, { children: [
8383
+ "This presents the number of available sequences of a variant per",
8384
+ " ",
8385
+ /* @__PURE__ */ u$1("b", { children: originalComponentProps.granularity }),
8386
+ originalComponentProps.smoothingWindow > 0 && `, smoothed using a ${originalComponentProps.smoothingWindow}-${originalComponentProps.granularity} sliding window`,
8387
+ "."
8388
+ ] }),
8389
+ /* @__PURE__ */ u$1(
8390
+ InfoComponentCode,
8391
+ {
8392
+ componentName: "number-sequences-over-time",
8393
+ params: originalComponentProps,
8394
+ lapisUrl: lapis
8395
+ }
8396
+ )
8397
+ ] });
8398
+ };
8407
8399
  var __defProp$6 = Object.defineProperty;
8408
8400
  var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
8409
8401
  var __decorateClass$6 = (decorators, target, key, kind) => {
@@ -8469,7 +8461,7 @@ __decorateClass$6([
8469
8461
  NumberSequencesOverTimeComponent = __decorateClass$6([
8470
8462
  t$2("gs-number-sequences-over-time")
8471
8463
  ], NumberSequencesOverTimeComponent);
8472
- const encodedJs = "KGZ1bmN0aW9uKCkgewogICJ1c2Ugc3RyaWN0IjsKICB2YXIgdXRpbDsKICAoZnVuY3Rpb24odXRpbDIpIHsKICAgIHV0aWwyLmFzc2VydEVxdWFsID0gKHZhbCkgPT4gdmFsOwogICAgZnVuY3Rpb24gYXNzZXJ0SXMoX2FyZykgewogICAgfQogICAgdXRpbDIuYXNzZXJ0SXMgPSBhc3NlcnRJczsKICAgIGZ1bmN0aW9uIGFzc2VydE5ldmVyKF94KSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgfQogICAgdXRpbDIuYXNzZXJ0TmV2ZXIgPSBhc3NlcnROZXZlcjsKICAgIHV0aWwyLmFycmF5VG9FbnVtID0gKGl0ZW1zKSA9PiB7CiAgICAgIGNvbnN0IG9iaiA9IHt9OwogICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHsKICAgICAgICBvYmpbaXRlbV0gPSBpdGVtOwogICAgICB9CiAgICAgIHJldHVybiBvYmo7CiAgICB9OwogICAgdXRpbDIuZ2V0VmFsaWRFbnVtVmFsdWVzID0gKG9iaikgPT4gewogICAgICBjb25zdCB2YWxpZEtleXMgPSB1dGlsMi5vYmplY3RLZXlzKG9iaikuZmlsdGVyKChrMikgPT4gdHlwZW9mIG9ialtvYmpbazJdXSAhPT0gIm51bWJlciIpOwogICAgICBjb25zdCBmaWx0ZXJlZCA9IHt9OwogICAgICBmb3IgKGNvbnN0IGsyIG9mIHZhbGlkS2V5cykgewogICAgICAgIGZpbHRlcmVkW2syXSA9IG9ialtrMl07CiAgICAgIH0KICAgICAgcmV0dXJuIHV0aWwyLm9iamVjdFZhbHVlcyhmaWx0ZXJlZCk7CiAgICB9OwogICAgdXRpbDIub2JqZWN0VmFsdWVzID0gKG9iaikgPT4gewogICAgICByZXR1cm4gdXRpbDIub2JqZWN0S2V5cyhvYmopLm1hcChmdW5jdGlvbihlMikgewogICAgICAgIHJldHVybiBvYmpbZTJdOwogICAgICB9KTsKICAgIH07CiAgICB1dGlsMi5vYmplY3RLZXlzID0gdHlwZW9mIE9iamVjdC5rZXlzID09PSAiZnVuY3Rpb24iID8gKG9iaikgPT4gT2JqZWN0LmtleXMob2JqKSA6IChvYmplY3QpID0+IHsKICAgICAgY29uc3Qga2V5cyA9IFtdOwogICAgICBmb3IgKGNvbnN0IGtleSBpbiBvYmplY3QpIHsKICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkgewogICAgICAgICAga2V5cy5wdXNoKGtleSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBrZXlzOwogICAgfTsKICAgIHV0aWwyLmZpbmQgPSAoYXJyLCBjaGVja2VyKSA9PiB7CiAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBhcnIpIHsKICAgICAgICBpZiAoY2hlY2tlcihpdGVtKSkKICAgICAgICAgIHJldHVybiBpdGVtOwogICAgICB9CiAgICAgIHJldHVybiB2b2lkIDA7CiAgICB9OwogICAgdXRpbDIuaXNJbnRlZ2VyID0gdHlwZW9mIE51bWJlci5pc0ludGVnZXIgPT09ICJmdW5jdGlvbiIgPyAodmFsKSA9PiBOdW1iZXIuaXNJbnRlZ2VyKHZhbCkgOiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAibnVtYmVyIiAmJiBpc0Zpbml0ZSh2YWwpICYmIE1hdGguZmxvb3IodmFsKSA9PT0gdmFsOwogICAgZnVuY3Rpb24gam9pblZhbHVlcyhhcnJheSwgc2VwYXJhdG9yID0gIiB8ICIpIHsKICAgICAgcmV0dXJuIGFycmF5Lm1hcCgodmFsKSA9PiB0eXBlb2YgdmFsID09PSAic3RyaW5nIiA/IGAnJHt2YWx9J2AgOiB2YWwpLmpvaW4oc2VwYXJhdG9yKTsKICAgIH0KICAgIHV0aWwyLmpvaW5WYWx1ZXMgPSBqb2luVmFsdWVzOwogICAgdXRpbDIuanNvblN0cmluZ2lmeVJlcGxhY2VyID0gKF8sIHZhbHVlKSA9PiB7CiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJiaWdpbnQiKSB7CiAgICAgICAgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIHZhbHVlOwogICAgfTsKICB9KSh1dGlsIHx8ICh1dGlsID0ge30pKTsKICB2YXIgb2JqZWN0VXRpbDsKICAoZnVuY3Rpb24ob2JqZWN0VXRpbDIpIHsKICAgIG9iamVjdFV0aWwyLm1lcmdlU2hhcGVzID0gKGZpcnN0LCBzZWNvbmQpID0+IHsKICAgICAgcmV0dXJuIHsKICAgICAgICAuLi5maXJzdCwKICAgICAgICAuLi5zZWNvbmQKICAgICAgICAvLyBzZWNvbmQgb3ZlcndyaXRlcyBmaXJzdAogICAgICB9OwogICAgfTsKICB9KShvYmplY3RVdGlsIHx8IChvYmplY3RVdGlsID0ge30pKTsKICBjb25zdCBab2RQYXJzZWRUeXBlID0gdXRpbC5hcnJheVRvRW51bShbCiAgICAic3RyaW5nIiwKICAgICJuYW4iLAogICAgIm51bWJlciIsCiAgICAiaW50ZWdlciIsCiAgICAiZmxvYXQiLAogICAgImJvb2xlYW4iLAogICAgImRhdGUiLAogICAgImJpZ2ludCIsCiAgICAic3ltYm9sIiwKICAgICJmdW5jdGlvbiIsCiAgICAidW5kZWZpbmVkIiwKICAgICJudWxsIiwKICAgICJhcnJheSIsCiAgICAib2JqZWN0IiwKICAgICJ1bmtub3duIiwKICAgICJwcm9taXNlIiwKICAgICJ2b2lkIiwKICAgICJuZXZlciIsCiAgICAibWFwIiwKICAgICJzZXQiCiAgXSk7CiAgY29uc3QgZ2V0UGFyc2VkVHlwZSA9IChkYXRhKSA9PiB7CiAgICBjb25zdCB0ID0gdHlwZW9mIGRhdGE7CiAgICBzd2l0Y2ggKHQpIHsKICAgICAgY2FzZSAidW5kZWZpbmVkIjoKICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS51bmRlZmluZWQ7CiAgICAgIGNhc2UgInN0cmluZyI6CiAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc3RyaW5nOwogICAgICBjYXNlICJudW1iZXIiOgogICAgICAgIHJldHVybiBpc05hTihkYXRhKSA/IFpvZFBhcnNlZFR5cGUubmFuIDogWm9kUGFyc2VkVHlwZS5udW1iZXI7CiAgICAgIGNhc2UgImJvb2xlYW4iOgogICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLmJvb2xlYW47CiAgICAgIGNhc2UgImZ1bmN0aW9uIjoKICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5mdW5jdGlvbjsKICAgICAgY2FzZSAiYmlnaW50IjoKICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5iaWdpbnQ7CiAgICAgIGNhc2UgInN5bWJvbCI6CiAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc3ltYm9sOwogICAgICBjYXNlICJvYmplY3QiOgogICAgICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7CiAgICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5hcnJheTsKICAgICAgICB9CiAgICAgICAgaWYgKGRhdGEgPT09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLm51bGw7CiAgICAgICAgfQogICAgICAgIGlmIChkYXRhLnRoZW4gJiYgdHlwZW9mIGRhdGEudGhlbiA9PT0gImZ1bmN0aW9uIiAmJiBkYXRhLmNhdGNoICYmIHR5cGVvZiBkYXRhLmNhdGNoID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5wcm9taXNlOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIE1hcCAhPT0gInVuZGVmaW5lZCIgJiYgZGF0YSBpbnN0YW5jZW9mIE1hcCkgewogICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUubWFwOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIFNldCAhPT0gInVuZGVmaW5lZCIgJiYgZGF0YSBpbnN0YW5jZW9mIFNldCkgewogICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc2V0OwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIERhdGUgIT09ICJ1bmRlZmluZWQiICYmIGRhdGEgaW5zdGFuY2VvZiBEYXRlKSB7CiAgICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5kYXRlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5vYmplY3Q7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUudW5rbm93bjsKICAgIH0KICB9OwogIGNvbnN0IFpvZElzc3VlQ29kZSA9IHV0aWwuYXJyYXlUb0VudW0oWwogICAgImludmFsaWRfdHlwZSIsCiAgICAiaW52YWxpZF9saXRlcmFsIiwKICAgICJjdXN0b20iLAogICAgImludmFsaWRfdW5pb24iLAogICAgImludmFsaWRfdW5pb25fZGlzY3JpbWluYXRvciIsCiAgICAiaW52YWxpZF9lbnVtX3ZhbHVlIiwKICAgICJ1bnJlY29nbml6ZWRfa2V5cyIsCiAgICAiaW52YWxpZF9hcmd1bWVudHMiLAogICAgImludmFsaWRfcmV0dXJuX3R5cGUiLAogICAgImludmFsaWRfZGF0ZSIsCiAgICAiaW52YWxpZF9zdHJpbmciLAogICAgInRvb19zbWFsbCIsCiAgICAidG9vX2JpZyIsCiAgICAiaW52YWxpZF9pbnRlcnNlY3Rpb25fdHlwZXMiLAogICAgIm5vdF9tdWx0aXBsZV9vZiIsCiAgICAibm90X2Zpbml0ZSIKICBdKTsKICBjb25zdCBxdW90ZWxlc3NKc29uID0gKG9iaikgPT4gewogICAgY29uc3QganNvbiA9IEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgMik7CiAgICByZXR1cm4ganNvbi5yZXBsYWNlKC8iKFteIl0rKSI6L2csICIkMToiKTsKICB9OwogIGNsYXNzIFpvZEVycm9yIGV4dGVuZHMgRXJyb3IgewogICAgY29uc3RydWN0b3IoaXNzdWVzKSB7CiAgICAgIHN1cGVyKCk7CiAgICAgIHRoaXMuaXNzdWVzID0gW107CiAgICAgIHRoaXMuYWRkSXNzdWUgPSAoc3ViKSA9PiB7CiAgICAgICAgdGhpcy5pc3N1ZXMgPSBbLi4udGhpcy5pc3N1ZXMsIHN1Yl07CiAgICAgIH07CiAgICAgIHRoaXMuYWRkSXNzdWVzID0gKHN1YnMgPSBbXSkgPT4gewogICAgICAgIHRoaXMuaXNzdWVzID0gWy4uLnRoaXMuaXNzdWVzLCAuLi5zdWJzXTsKICAgICAgfTsKICAgICAgY29uc3QgYWN0dWFsUHJvdG8gPSBuZXcudGFyZ2V0LnByb3RvdHlwZTsKICAgICAgaWYgKE9iamVjdC5zZXRQcm90b3R5cGVPZikgewogICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBhY3R1YWxQcm90byk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fX3Byb3RvX18gPSBhY3R1YWxQcm90bzsKICAgICAgfQogICAgICB0aGlzLm5hbWUgPSAiWm9kRXJyb3IiOwogICAgICB0aGlzLmlzc3VlcyA9IGlzc3VlczsKICAgIH0KICAgIGdldCBlcnJvcnMoKSB7CiAgICAgIHJldHVybiB0aGlzLmlzc3VlczsKICAgIH0KICAgIGZvcm1hdChfbWFwcGVyKSB7CiAgICAgIGNvbnN0IG1hcHBlciA9IF9tYXBwZXIgfHwgZnVuY3Rpb24oaXNzdWUpIHsKICAgICAgICByZXR1cm4gaXNzdWUubWVzc2FnZTsKICAgICAgfTsKICAgICAgY29uc3QgZmllbGRFcnJvcnMgPSB7IF9lcnJvcnM6IFtdIH07CiAgICAgIGNvbnN0IHByb2Nlc3NFcnJvciA9IChlcnJvcikgPT4gewogICAgICAgIGZvciAoY29uc3QgaXNzdWUgb2YgZXJyb3IuaXNzdWVzKSB7CiAgICAgICAgICBpZiAoaXNzdWUuY29kZSA9PT0gImludmFsaWRfdW5pb24iKSB7CiAgICAgICAgICAgIGlzc3VlLnVuaW9uRXJyb3JzLm1hcChwcm9jZXNzRXJyb3IpOwogICAgICAgICAgfSBlbHNlIGlmIChpc3N1ZS5jb2RlID09PSAiaW52YWxpZF9yZXR1cm5fdHlwZSIpIHsKICAgICAgICAgICAgcHJvY2Vzc0Vycm9yKGlzc3VlLnJldHVyblR5cGVFcnJvcik7CiAgICAgICAgICB9IGVsc2UgaWYgKGlzc3VlLmNvZGUgPT09ICJpbnZhbGlkX2FyZ3VtZW50cyIpIHsKICAgICAgICAgICAgcHJvY2Vzc0Vycm9yKGlzc3VlLmFyZ3VtZW50c0Vycm9yKTsKICAgICAgICAgIH0gZWxzZSBpZiAoaXNzdWUucGF0aC5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgZmllbGRFcnJvcnMuX2Vycm9ycy5wdXNoKG1hcHBlcihpc3N1ZSkpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgbGV0IGN1cnIgPSBmaWVsZEVycm9yczsKICAgICAgICAgICAgbGV0IGkyID0gMDsKICAgICAgICAgICAgd2hpbGUgKGkyIDwgaXNzdWUucGF0aC5sZW5ndGgpIHsKICAgICAgICAgICAgICBjb25zdCBlbCA9IGlzc3VlLnBhdGhbaTJdOwogICAgICAgICAgICAgIGNvbnN0IHRlcm1pbmFsID0gaTIgPT09IGlzc3VlLnBhdGgubGVuZ3RoIC0gMTsKICAgICAgICAgICAgICBpZiAoIXRlcm1pbmFsKSB7CiAgICAgICAgICAgICAgICBjdXJyW2VsXSA9IGN1cnJbZWxdIHx8IHsgX2Vycm9yczogW10gfTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgY3VycltlbF0gPSBjdXJyW2VsXSB8fCB7IF9lcnJvcnM6IFtdIH07CiAgICAgICAgICAgICAgICBjdXJyW2VsXS5fZXJyb3JzLnB1c2gobWFwcGVyKGlzc3VlKSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGN1cnIgPSBjdXJyW2VsXTsKICAgICAgICAgICAgICBpMisrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9OwogICAgICBwcm9jZXNzRXJyb3IodGhpcyk7CiAgICAgIHJldHVybiBmaWVsZEVycm9yczsKICAgIH0KICAgIHN0YXRpYyBhc3NlcnQodmFsdWUpIHsKICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBab2RFcnJvcikpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vdCBhIFpvZEVycm9yOiAke3ZhbHVlfWApOwogICAgICB9CiAgICB9CiAgICB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZTsKICAgIH0KICAgIGdldCBtZXNzYWdlKCkgewogICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy5pc3N1ZXMsIHV0aWwuanNvblN0cmluZ2lmeVJlcGxhY2VyLCAyKTsKICAgIH0KICAgIGdldCBpc0VtcHR5KCkgewogICAgICByZXR1cm4gdGhpcy5pc3N1ZXMubGVuZ3RoID09PSAwOwogICAgfQogICAgZmxhdHRlbihtYXBwZXIgPSAoaXNzdWUpID0+IGlzc3VlLm1lc3NhZ2UpIHsKICAgICAgY29uc3QgZmllbGRFcnJvcnMgPSB7fTsKICAgICAgY29uc3QgZm9ybUVycm9ycyA9IFtdOwogICAgICBmb3IgKGNvbnN0IHN1YiBvZiB0aGlzLmlzc3VlcykgewogICAgICAgIGlmIChzdWIucGF0aC5sZW5ndGggPiAwKSB7CiAgICAgICAgICBmaWVsZEVycm9yc1tzdWIucGF0aFswXV0gPSBmaWVsZEVycm9yc1tzdWIucGF0aFswXV0gfHwgW107CiAgICAgICAgICBmaWVsZEVycm9yc1tzdWIucGF0aFswXV0ucHVzaChtYXBwZXIoc3ViKSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGZvcm1FcnJvcnMucHVzaChtYXBwZXIoc3ViKSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiB7IGZvcm1FcnJvcnMsIGZpZWxkRXJyb3JzIH07CiAgICB9CiAgICBnZXQgZm9ybUVycm9ycygpIHsKICAgICAgcmV0dXJuIHRoaXMuZmxhdHRlbigpOwogICAgfQogIH0KICBab2RFcnJvci5jcmVhdGUgPSAoaXNzdWVzKSA9PiB7CiAgICBjb25zdCBlcnJvciA9IG5ldyBab2RFcnJvcihpc3N1ZXMpOwogICAgcmV0dXJuIGVycm9yOwogIH07CiAgY29uc3QgZXJyb3JNYXAgPSAoaXNzdWUsIF9jdHgpID0+IHsKICAgIGxldCBtZXNzYWdlOwogICAgc3dpdGNoIChpc3N1ZS5jb2RlKSB7CiAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZToKICAgICAgICBpZiAoaXNzdWUucmVjZWl2ZWQgPT09IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkKSB7CiAgICAgICAgICBtZXNzYWdlID0gIlJlcXVpcmVkIjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbWVzc2FnZSA9IGBFeHBlY3RlZCAke2lzc3VlLmV4cGVjdGVkfSwgcmVjZWl2ZWQgJHtpc3N1ZS5yZWNlaXZlZH1gOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9saXRlcmFsOgogICAgICAgIG1lc3NhZ2UgPSBgSW52YWxpZCBsaXRlcmFsIHZhbHVlLCBleHBlY3RlZCAke0pTT04uc3RyaW5naWZ5KGlzc3VlLmV4cGVjdGVkLCB1dGlsLmpzb25TdHJpbmdpZnlSZXBsYWNlcil9YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUudW5yZWNvZ25pemVkX2tleXM6CiAgICAgICAgbWVzc2FnZSA9IGBVbnJlY29nbml6ZWQga2V5KHMpIGluIG9iamVjdDogJHt1dGlsLmpvaW5WYWx1ZXMoaXNzdWUua2V5cywgIiwgIil9YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF91bmlvbjoKICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgaW5wdXRgOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFpvZElzc3VlQ29kZS5pbnZhbGlkX3VuaW9uX2Rpc2NyaW1pbmF0b3I6CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGRpc2NyaW1pbmF0b3IgdmFsdWUuIEV4cGVjdGVkICR7dXRpbC5qb2luVmFsdWVzKGlzc3VlLm9wdGlvbnMpfWA7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfZW51bV92YWx1ZToKICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgZW51bSB2YWx1ZS4gRXhwZWN0ZWQgJHt1dGlsLmpvaW5WYWx1ZXMoaXNzdWUub3B0aW9ucyl9LCByZWNlaXZlZCAnJHtpc3N1ZS5yZWNlaXZlZH0nYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9hcmd1bWVudHM6CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGZ1bmN0aW9uIGFyZ3VtZW50c2A7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfcmV0dXJuX3R5cGU6CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGZ1bmN0aW9uIHJldHVybiB0eXBlYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9kYXRlOgogICAgICAgIG1lc3NhZ2UgPSBgSW52YWxpZCBkYXRlYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmc6CiAgICAgICAgaWYgKHR5cGVvZiBpc3N1ZS52YWxpZGF0aW9uID09PSAib2JqZWN0IikgewogICAgICAgICAgaWYgKCJpbmNsdWRlcyIgaW4gaXNzdWUudmFsaWRhdGlvbikgewogICAgICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgaW5wdXQ6IG11c3QgaW5jbHVkZSAiJHtpc3N1ZS52YWxpZGF0aW9uLmluY2x1ZGVzfSJgOwogICAgICAgICAgICBpZiAodHlwZW9mIGlzc3VlLnZhbGlkYXRpb24ucG9zaXRpb24gPT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgICAgbWVzc2FnZSA9IGAke21lc3NhZ2V9IGF0IG9uZSBvciBtb3JlIHBvc2l0aW9ucyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gJHtpc3N1ZS52YWxpZGF0aW9uLnBvc2l0aW9ufWA7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSBpZiAoInN0YXJ0c1dpdGgiIGluIGlzc3VlLnZhbGlkYXRpb24pIHsKICAgICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGlucHV0OiBtdXN0IHN0YXJ0IHdpdGggIiR7aXNzdWUudmFsaWRhdGlvbi5zdGFydHNXaXRofSJgOwogICAgICAgICAgfSBlbHNlIGlmICgiZW5kc1dpdGgiIGluIGlzc3VlLnZhbGlkYXRpb24pIHsKICAgICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGlucHV0OiBtdXN0IGVuZCB3aXRoICIke2lzc3VlLnZhbGlkYXRpb24uZW5kc1dpdGh9ImA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB1dGlsLmFzc2VydE5ldmVyKGlzc3VlLnZhbGlkYXRpb24pOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoaXNzdWUudmFsaWRhdGlvbiAhPT0gInJlZ2V4IikgewogICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkICR7aXNzdWUudmFsaWRhdGlvbn1gOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBtZXNzYWdlID0gIkludmFsaWQiOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUudG9vX3NtYWxsOgogICAgICAgIGlmIChpc3N1ZS50eXBlID09PSAiYXJyYXkiKQogICAgICAgICAgbWVzc2FnZSA9IGBBcnJheSBtdXN0IGNvbnRhaW4gJHtpc3N1ZS5leGFjdCA/ICJleGFjdGx5IiA6IGlzc3VlLmluY2x1c2l2ZSA/IGBhdCBsZWFzdGAgOiBgbW9yZSB0aGFuYH0gJHtpc3N1ZS5taW5pbXVtfSBlbGVtZW50KHMpYDsKICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSAic3RyaW5nIikKICAgICAgICAgIG1lc3NhZ2UgPSBgU3RyaW5nIG11c3QgY29udGFpbiAke2lzc3VlLmV4YWN0ID8gImV4YWN0bHkiIDogaXNzdWUuaW5jbHVzaXZlID8gYGF0IGxlYXN0YCA6IGBvdmVyYH0gJHtpc3N1ZS5taW5pbXVtfSBjaGFyYWN0ZXIocylgOwogICAgICAgIGVsc2UgaWYgKGlzc3VlLnR5cGUgPT09ICJudW1iZXIiKQogICAgICAgICAgbWVzc2FnZSA9IGBOdW1iZXIgbXVzdCBiZSAke2lzc3VlLmV4YWN0ID8gYGV4YWN0bHkgZXF1YWwgdG8gYCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYCA6IGBncmVhdGVyIHRoYW4gYH0ke2lzc3VlLm1pbmltdW19YDsKICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSAiZGF0ZSIpCiAgICAgICAgICBtZXNzYWdlID0gYERhdGUgbXVzdCBiZSAke2lzc3VlLmV4YWN0ID8gYGV4YWN0bHkgZXF1YWwgdG8gYCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYCA6IGBncmVhdGVyIHRoYW4gYH0ke25ldyBEYXRlKE51bWJlcihpc3N1ZS5taW5pbXVtKSl9YDsKICAgICAgICBlbHNlCiAgICAgICAgICBtZXNzYWdlID0gIkludmFsaWQgaW5wdXQiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFpvZElzc3VlQ29kZS50b29fYmlnOgogICAgICAgIGlmIChpc3N1ZS50eXBlID09PSAiYXJyYXkiKQogICAgICAgICAgbWVzc2FnZSA9IGBBcnJheSBtdXN0IGNvbnRhaW4gJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5YCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBhdCBtb3N0YCA6IGBsZXNzIHRoYW5gfSAke2lzc3VlLm1heGltdW19IGVsZW1lbnQocylgOwogICAgICAgIGVsc2UgaWYgKGlzc3VlLnR5cGUgPT09ICJzdHJpbmciKQogICAgICAgICAgbWVzc2FnZSA9IGBTdHJpbmcgbXVzdCBjb250YWluICR7aXNzdWUuZXhhY3QgPyBgZXhhY3RseWAgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgYXQgbW9zdGAgOiBgdW5kZXJgfSAke2lzc3VlLm1heGltdW19IGNoYXJhY3RlcihzKWA7CiAgICAgICAgZWxzZSBpZiAoaXNzdWUudHlwZSA9PT0gIm51bWJlciIpCiAgICAgICAgICBtZXNzYWdlID0gYE51bWJlciBtdXN0IGJlICR7aXNzdWUuZXhhY3QgPyBgZXhhY3RseWAgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgbGVzcyB0aGFuIG9yIGVxdWFsIHRvYCA6IGBsZXNzIHRoYW5gfSAke2lzc3VlLm1heGltdW19YDsKICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSAiYmlnaW50IikKICAgICAgICAgIG1lc3NhZ2UgPSBgQmlnSW50IG11c3QgYmUgJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5YCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBsZXNzIHRoYW4gb3IgZXF1YWwgdG9gIDogYGxlc3MgdGhhbmB9ICR7aXNzdWUubWF4aW11bX1gOwogICAgICAgIGVsc2UgaWYgKGlzc3VlLnR5cGUgPT09ICJkYXRlIikKICAgICAgICAgIG1lc3NhZ2UgPSBgRGF0ZSBtdXN0IGJlICR7aXNzdWUuZXhhY3QgPyBgZXhhY3RseWAgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgc21hbGxlciB0aGFuIG9yIGVxdWFsIHRvYCA6IGBzbWFsbGVyIHRoYW5gfSAke25ldyBEYXRlKE51bWJlcihpc3N1ZS5tYXhpbXVtKSl9YDsKICAgICAgICBlbHNlCiAgICAgICAgICBtZXNzYWdlID0gIkludmFsaWQgaW5wdXQiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFpvZElzc3VlQ29kZS5jdXN0b206CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGlucHV0YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9pbnRlcnNlY3Rpb25fdHlwZXM6CiAgICAgICAgbWVzc2FnZSA9IGBJbnRlcnNlY3Rpb24gcmVzdWx0cyBjb3VsZCBub3QgYmUgbWVyZ2VkYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUubm90X211bHRpcGxlX29mOgogICAgICAgIG1lc3NhZ2UgPSBgTnVtYmVyIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAke2lzc3VlLm11bHRpcGxlT2Z9YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUubm90X2Zpbml0ZToKICAgICAgICBtZXNzYWdlID0gIk51bWJlciBtdXN0IGJlIGZpbml0ZSI7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgbWVzc2FnZSA9IF9jdHguZGVmYXVsdEVycm9yOwogICAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoaXNzdWUpOwogICAgfQogICAgcmV0dXJuIHsgbWVzc2FnZSB9OwogIH07CiAgbGV0IG92ZXJyaWRlRXJyb3JNYXAgPSBlcnJvck1hcDsKICBmdW5jdGlvbiBzZXRFcnJvck1hcChtYXApIHsKICAgIG92ZXJyaWRlRXJyb3JNYXAgPSBtYXA7CiAgfQogIGZ1bmN0aW9uIGdldEVycm9yTWFwKCkgewogICAgcmV0dXJuIG92ZXJyaWRlRXJyb3JNYXA7CiAgfQogIGNvbnN0IG1ha2VJc3N1ZSA9IChwYXJhbXMpID0+IHsKICAgIGNvbnN0IHsgZGF0YSwgcGF0aCwgZXJyb3JNYXBzLCBpc3N1ZURhdGEgfSA9IHBhcmFtczsKICAgIGNvbnN0IGZ1bGxQYXRoID0gWy4uLnBhdGgsIC4uLmlzc3VlRGF0YS5wYXRoIHx8IFtdXTsKICAgIGNvbnN0IGZ1bGxJc3N1ZSA9IHsKICAgICAgLi4uaXNzdWVEYXRhLAogICAgICBwYXRoOiBmdWxsUGF0aAogICAgfTsKICAgIGlmIChpc3N1ZURhdGEubWVzc2FnZSAhPT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgLi4uaXNzdWVEYXRhLAogICAgICAgIHBhdGg6IGZ1bGxQYXRoLAogICAgICAgIG1lc3NhZ2U6IGlzc3VlRGF0YS5tZXNzYWdlCiAgICAgIH07CiAgICB9CiAgICBsZXQgZXJyb3JNZXNzYWdlID0gIiI7CiAgICBjb25zdCBtYXBzID0gZXJyb3JNYXBzLmZpbHRlcigobTIpID0+ICEhbTIpLnNsaWNlKCkucmV2ZXJzZSgpOwogICAgZm9yIChjb25zdCBtYXAgb2YgbWFwcykgewogICAgICBlcnJvck1lc3NhZ2UgPSBtYXAoZnVsbElzc3VlLCB7IGRhdGEsIGRlZmF1bHRFcnJvcjogZXJyb3JNZXNzYWdlIH0pLm1lc3NhZ2U7CiAgICB9CiAgICByZXR1cm4gewogICAgICAuLi5pc3N1ZURhdGEsCiAgICAgIHBhdGg6IGZ1bGxQYXRoLAogICAgICBtZXNzYWdlOiBlcnJvck1lc3NhZ2UKICAgIH07CiAgfTsKICBjb25zdCBFTVBUWV9QQVRIID0gW107CiAgZnVuY3Rpb24gYWRkSXNzdWVUb0NvbnRleHQoY3R4LCBpc3N1ZURhdGEpIHsKICAgIGNvbnN0IG92ZXJyaWRlTWFwID0gZ2V0RXJyb3JNYXAoKTsKICAgIGNvbnN0IGlzc3VlID0gbWFrZUlzc3VlKHsKICAgICAgaXNzdWVEYXRhLAogICAgICBkYXRhOiBjdHguZGF0YSwKICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgIGVycm9yTWFwczogWwogICAgICAgIGN0eC5jb21tb24uY29udGV4dHVhbEVycm9yTWFwLAogICAgICAgIGN0eC5zY2hlbWFFcnJvck1hcCwKICAgICAgICBvdmVycmlkZU1hcCwKICAgICAgICBvdmVycmlkZU1hcCA9PT0gZXJyb3JNYXAgPyB2b2lkIDAgOiBlcnJvck1hcAogICAgICAgIC8vIHRoZW4gZ2xvYmFsIGRlZmF1bHQgbWFwCiAgICAgIF0uZmlsdGVyKCh4KSA9PiAhIXgpCiAgICB9KTsKICAgIGN0eC5jb21tb24uaXNzdWVzLnB1c2goaXNzdWUpOwogIH0KICBjbGFzcyBQYXJzZVN0YXR1cyB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgdGhpcy52YWx1ZSA9ICJ2YWxpZCI7CiAgICB9CiAgICBkaXJ0eSgpIHsKICAgICAgaWYgKHRoaXMudmFsdWUgPT09ICJ2YWxpZCIpCiAgICAgICAgdGhpcy52YWx1ZSA9ICJkaXJ0eSI7CiAgICB9CiAgICBhYm9ydCgpIHsKICAgICAgaWYgKHRoaXMudmFsdWUgIT09ICJhYm9ydGVkIikKICAgICAgICB0aGlzLnZhbHVlID0gImFib3J0ZWQiOwogICAgfQogICAgc3RhdGljIG1lcmdlQXJyYXkoc3RhdHVzLCByZXN1bHRzKSB7CiAgICAgIGNvbnN0IGFycmF5VmFsdWUgPSBbXTsKICAgICAgZm9yIChjb25zdCBzMiBvZiByZXN1bHRzKSB7CiAgICAgICAgaWYgKHMyLnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgaWYgKHMyLnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgIGFycmF5VmFsdWUucHVzaChzMi52YWx1ZSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBhcnJheVZhbHVlIH07CiAgICB9CiAgICBzdGF0aWMgYXN5bmMgbWVyZ2VPYmplY3RBc3luYyhzdGF0dXMsIHBhaXJzKSB7CiAgICAgIGNvbnN0IHN5bmNQYWlycyA9IFtdOwogICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHsKICAgICAgICBjb25zdCBrZXkgPSBhd2FpdCBwYWlyLmtleTsKICAgICAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IHBhaXIudmFsdWU7CiAgICAgICAgc3luY1BhaXJzLnB1c2goewogICAgICAgICAga2V5LAogICAgICAgICAgdmFsdWUKICAgICAgICB9KTsKICAgICAgfQogICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VPYmplY3RTeW5jKHN0YXR1cywgc3luY1BhaXJzKTsKICAgIH0KICAgIHN0YXRpYyBtZXJnZU9iamVjdFN5bmMoc3RhdHVzLCBwYWlycykgewogICAgICBjb25zdCBmaW5hbE9iamVjdCA9IHt9OwogICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHsKICAgICAgICBjb25zdCB7IGtleSwgdmFsdWUgfSA9IHBhaXI7CiAgICAgICAgaWYgKGtleS5zdGF0dXMgPT09ICJhYm9ydGVkIikKICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgIGlmICh2YWx1ZS5zdGF0dXMgPT09ICJhYm9ydGVkIikKICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgIGlmIChrZXkuc3RhdHVzID09PSAiZGlydHkiKQogICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgaWYgKHZhbHVlLnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgIGlmIChrZXkudmFsdWUgIT09ICJfX3Byb3RvX18iICYmICh0eXBlb2YgdmFsdWUudmFsdWUgIT09ICJ1bmRlZmluZWQiIHx8IHBhaXIuYWx3YXlzU2V0KSkgewogICAgICAgICAgZmluYWxPYmplY3Rba2V5LnZhbHVlXSA9IHZhbHVlLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGZpbmFsT2JqZWN0IH07CiAgICB9CiAgfQogIGNvbnN0IElOVkFMSUQgPSBPYmplY3QuZnJlZXplKHsKICAgIHN0YXR1czogImFib3J0ZWQiCiAgfSk7CiAgY29uc3QgRElSVFkgPSAodmFsdWUpID0+ICh7IHN0YXR1czogImRpcnR5IiwgdmFsdWUgfSk7CiAgY29uc3QgT0sgPSAodmFsdWUpID0+ICh7IHN0YXR1czogInZhbGlkIiwgdmFsdWUgfSk7CiAgY29uc3QgaXNBYm9ydGVkID0gKHgpID0+IHguc3RhdHVzID09PSAiYWJvcnRlZCI7CiAgY29uc3QgaXNEaXJ0eSA9ICh4KSA9PiB4LnN0YXR1cyA9PT0gImRpcnR5IjsKICBjb25zdCBpc1ZhbGlkID0gKHgpID0+IHguc3RhdHVzID09PSAidmFsaWQiOwogIGNvbnN0IGlzQXN5bmMgPSAoeCkgPT4gdHlwZW9mIFByb21pc2UgIT09ICJ1bmRlZmluZWQiICYmIHggaW5zdGFuY2VvZiBQcm9taXNlOwogIGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRHZXQocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmMikgewogICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gImZ1bmN0aW9uIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZjIgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0Iik7CiAgICByZXR1cm4gc3RhdGUuZ2V0KHJlY2VpdmVyKTsKICB9CiAgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZFNldChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmMikgewogICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gImZ1bmN0aW9uIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZjIgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXQiKTsKICAgIHJldHVybiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSwgdmFsdWU7CiAgfQogIHR5cGVvZiBTdXBwcmVzc2VkRXJyb3IgPT09ICJmdW5jdGlvbiIgPyBTdXBwcmVzc2VkRXJyb3IgOiBmdW5jdGlvbihlcnJvciwgc3VwcHJlc3NlZCwgbWVzc2FnZSkgewogICAgdmFyIGUyID0gbmV3IEVycm9yKG1lc3NhZ2UpOwogICAgcmV0dXJuIGUyLm5hbWUgPSAiU3VwcHJlc3NlZEVycm9yIiwgZTIuZXJyb3IgPSBlcnJvciwgZTIuc3VwcHJlc3NlZCA9IHN1cHByZXNzZWQsIGUyOwogIH07CiAgdmFyIGVycm9yVXRpbDsKICAoZnVuY3Rpb24oZXJyb3JVdGlsMikgewogICAgZXJyb3JVdGlsMi5lcnJUb09iaiA9IChtZXNzYWdlKSA9PiB0eXBlb2YgbWVzc2FnZSA9PT0gInN0cmluZyIgPyB7IG1lc3NhZ2UgfSA6IG1lc3NhZ2UgfHwge307CiAgICBlcnJvclV0aWwyLnRvU3RyaW5nID0gKG1lc3NhZ2UpID0+IHR5cGVvZiBtZXNzYWdlID09PSAic3RyaW5nIiA/IG1lc3NhZ2UgOiBtZXNzYWdlID09PSBudWxsIHx8IG1lc3NhZ2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG1lc3NhZ2UubWVzc2FnZTsKICB9KShlcnJvclV0aWwgfHwgKGVycm9yVXRpbCA9IHt9KSk7CiAgdmFyIF9ab2RFbnVtX2NhY2hlLCBfWm9kTmF0aXZlRW51bV9jYWNoZTsKICBjbGFzcyBQYXJzZUlucHV0TGF6eVBhdGggewogICAgY29uc3RydWN0b3IocGFyZW50LCB2YWx1ZSwgcGF0aCwga2V5KSB7CiAgICAgIHRoaXMuX2NhY2hlZFBhdGggPSBbXTsKICAgICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7CiAgICAgIHRoaXMuZGF0YSA9IHZhbHVlOwogICAgICB0aGlzLl9wYXRoID0gcGF0aDsKICAgICAgdGhpcy5fa2V5ID0ga2V5OwogICAgfQogICAgZ2V0IHBhdGgoKSB7CiAgICAgIGlmICghdGhpcy5fY2FjaGVkUGF0aC5sZW5ndGgpIHsKICAgICAgICBpZiAodGhpcy5fa2V5IGluc3RhbmNlb2YgQXJyYXkpIHsKICAgICAgICAgIHRoaXMuX2NhY2hlZFBhdGgucHVzaCguLi50aGlzLl9wYXRoLCAuLi50aGlzLl9rZXkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9jYWNoZWRQYXRoLnB1c2goLi4udGhpcy5fcGF0aCwgdGhpcy5fa2V5KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlZFBhdGg7CiAgICB9CiAgfQogIGNvbnN0IGhhbmRsZVJlc3VsdCA9IChjdHgsIHJlc3VsdCkgPT4gewogICAgaWYgKGlzVmFsaWQocmVzdWx0KSkgewogICAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBkYXRhOiByZXN1bHQudmFsdWUgfTsKICAgIH0gZWxzZSB7CiAgICAgIGlmICghY3R4LmNvbW1vbi5pc3N1ZXMubGVuZ3RoKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJWYWxpZGF0aW9uIGZhaWxlZCBidXQgbm8gaXNzdWVzIGRldGVjdGVkLiIpOwogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgc3VjY2VzczogZmFsc2UsCiAgICAgICAgZ2V0IGVycm9yKCkgewogICAgICAgICAgaWYgKHRoaXMuX2Vycm9yKQogICAgICAgICAgICByZXR1cm4gdGhpcy5fZXJyb3I7CiAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBab2RFcnJvcihjdHguY29tbW9uLmlzc3Vlcyk7CiAgICAgICAgICB0aGlzLl9lcnJvciA9IGVycm9yOwogICAgICAgICAgcmV0dXJuIHRoaXMuX2Vycm9yOwogICAgICAgIH0KICAgICAgfTsKICAgIH0KICB9OwogIGZ1bmN0aW9uIHByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSB7CiAgICBpZiAoIXBhcmFtcykKICAgICAgcmV0dXJuIHt9OwogICAgY29uc3QgeyBlcnJvck1hcDogZXJyb3JNYXAyLCBpbnZhbGlkX3R5cGVfZXJyb3IsIHJlcXVpcmVkX2Vycm9yLCBkZXNjcmlwdGlvbiB9ID0gcGFyYW1zOwogICAgaWYgKGVycm9yTWFwMiAmJiAoaW52YWxpZF90eXBlX2Vycm9yIHx8IHJlcXVpcmVkX2Vycm9yKSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IHVzZSAiaW52YWxpZF90eXBlX2Vycm9yIiBvciAicmVxdWlyZWRfZXJyb3IiIGluIGNvbmp1bmN0aW9uIHdpdGggY3VzdG9tIGVycm9yIG1hcC5gKTsKICAgIH0KICAgIGlmIChlcnJvck1hcDIpCiAgICAgIHJldHVybiB7IGVycm9yTWFwOiBlcnJvck1hcDIsIGRlc2NyaXB0aW9uIH07CiAgICBjb25zdCBjdXN0b21NYXAgPSAoaXNzLCBjdHgpID0+IHsKICAgICAgdmFyIF9hLCBfYjsKICAgICAgY29uc3QgeyBtZXNzYWdlIH0gPSBwYXJhbXM7CiAgICAgIGlmIChpc3MuY29kZSA9PT0gImludmFsaWRfZW51bV92YWx1ZSIpIHsKICAgICAgICByZXR1cm4geyBtZXNzYWdlOiBtZXNzYWdlICE9PSBudWxsICYmIG1lc3NhZ2UgIT09IHZvaWQgMCA/IG1lc3NhZ2UgOiBjdHguZGVmYXVsdEVycm9yIH07CiAgICAgIH0KICAgICAgaWYgKHR5cGVvZiBjdHguZGF0YSA9PT0gInVuZGVmaW5lZCIpIHsKICAgICAgICByZXR1cm4geyBtZXNzYWdlOiAoX2EgPSBtZXNzYWdlICE9PSBudWxsICYmIG1lc3NhZ2UgIT09IHZvaWQgMCA/IG1lc3NhZ2UgOiByZXF1aXJlZF9lcnJvcikgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogY3R4LmRlZmF1bHRFcnJvciB9OwogICAgICB9CiAgICAgIGlmIChpc3MuY29kZSAhPT0gImludmFsaWRfdHlwZSIpCiAgICAgICAgcmV0dXJuIHsgbWVzc2FnZTogY3R4LmRlZmF1bHRFcnJvciB9OwogICAgICByZXR1cm4geyBtZXNzYWdlOiAoX2IgPSBtZXNzYWdlICE9PSBudWxsICYmIG1lc3NhZ2UgIT09IHZvaWQgMCA/IG1lc3NhZ2UgOiBpbnZhbGlkX3R5cGVfZXJyb3IpICE9PSBudWxsICYmIF9iICE9PSB2b2lkIDAgPyBfYiA6IGN0eC5kZWZhdWx0RXJyb3IgfTsKICAgIH07CiAgICByZXR1cm4geyBlcnJvck1hcDogY3VzdG9tTWFwLCBkZXNjcmlwdGlvbiB9OwogIH0KICBjbGFzcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKGRlZikgewogICAgICB0aGlzLnNwYSA9IHRoaXMuc2FmZVBhcnNlQXN5bmM7CiAgICAgIHRoaXMuX2RlZiA9IGRlZjsKICAgICAgdGhpcy5wYXJzZSA9IHRoaXMucGFyc2UuYmluZCh0aGlzKTsKICAgICAgdGhpcy5zYWZlUGFyc2UgPSB0aGlzLnNhZmVQYXJzZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLnBhcnNlQXN5bmMgPSB0aGlzLnBhcnNlQXN5bmMuYmluZCh0aGlzKTsKICAgICAgdGhpcy5zYWZlUGFyc2VBc3luYyA9IHRoaXMuc2FmZVBhcnNlQXN5bmMuYmluZCh0aGlzKTsKICAgICAgdGhpcy5zcGEgPSB0aGlzLnNwYS5iaW5kKHRoaXMpOwogICAgICB0aGlzLnJlZmluZSA9IHRoaXMucmVmaW5lLmJpbmQodGhpcyk7CiAgICAgIHRoaXMucmVmaW5lbWVudCA9IHRoaXMucmVmaW5lbWVudC5iaW5kKHRoaXMpOwogICAgICB0aGlzLnN1cGVyUmVmaW5lID0gdGhpcy5zdXBlclJlZmluZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLm9wdGlvbmFsID0gdGhpcy5vcHRpb25hbC5iaW5kKHRoaXMpOwogICAgICB0aGlzLm51bGxhYmxlID0gdGhpcy5udWxsYWJsZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLm51bGxpc2ggPSB0aGlzLm51bGxpc2guYmluZCh0aGlzKTsKICAgICAgdGhpcy5hcnJheSA9IHRoaXMuYXJyYXkuYmluZCh0aGlzKTsKICAgICAgdGhpcy5wcm9taXNlID0gdGhpcy5wcm9taXNlLmJpbmQodGhpcyk7CiAgICAgIHRoaXMub3IgPSB0aGlzLm9yLmJpbmQodGhpcyk7CiAgICAgIHRoaXMuYW5kID0gdGhpcy5hbmQuYmluZCh0aGlzKTsKICAgICAgdGhpcy50cmFuc2Zvcm0gPSB0aGlzLnRyYW5zZm9ybS5iaW5kKHRoaXMpOwogICAgICB0aGlzLmJyYW5kID0gdGhpcy5icmFuZC5iaW5kKHRoaXMpOwogICAgICB0aGlzLmRlZmF1bHQgPSB0aGlzLmRlZmF1bHQuYmluZCh0aGlzKTsKICAgICAgdGhpcy5jYXRjaCA9IHRoaXMuY2F0Y2guYmluZCh0aGlzKTsKICAgICAgdGhpcy5kZXNjcmliZSA9IHRoaXMuZGVzY3JpYmUuYmluZCh0aGlzKTsKICAgICAgdGhpcy5waXBlID0gdGhpcy5waXBlLmJpbmQodGhpcyk7CiAgICAgIHRoaXMucmVhZG9ubHkgPSB0aGlzLnJlYWRvbmx5LmJpbmQodGhpcyk7CiAgICAgIHRoaXMuaXNOdWxsYWJsZSA9IHRoaXMuaXNOdWxsYWJsZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLmlzT3B0aW9uYWwgPSB0aGlzLmlzT3B0aW9uYWwuYmluZCh0aGlzKTsKICAgIH0KICAgIGdldCBkZXNjcmlwdGlvbigpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5kZXNjcmlwdGlvbjsKICAgIH0KICAgIF9nZXRUeXBlKGlucHV0KSB7CiAgICAgIHJldHVybiBnZXRQYXJzZWRUeXBlKGlucHV0LmRhdGEpOwogICAgfQogICAgX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpIHsKICAgICAgcmV0dXJuIGN0eCB8fCB7CiAgICAgICAgY29tbW9uOiBpbnB1dC5wYXJlbnQuY29tbW9uLAogICAgICAgIGRhdGE6IGlucHV0LmRhdGEsCiAgICAgICAgcGFyc2VkVHlwZTogZ2V0UGFyc2VkVHlwZShpbnB1dC5kYXRhKSwKICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLAogICAgICAgIHBhdGg6IGlucHV0LnBhdGgsCiAgICAgICAgcGFyZW50OiBpbnB1dC5wYXJlbnQKICAgICAgfTsKICAgIH0KICAgIF9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBzdGF0dXM6IG5ldyBQYXJzZVN0YXR1cygpLAogICAgICAgIGN0eDogewogICAgICAgICAgY29tbW9uOiBpbnB1dC5wYXJlbnQuY29tbW9uLAogICAgICAgICAgZGF0YTogaW5wdXQuZGF0YSwKICAgICAgICAgIHBhcnNlZFR5cGU6IGdldFBhcnNlZFR5cGUoaW5wdXQuZGF0YSksCiAgICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLAogICAgICAgICAgcGF0aDogaW5wdXQucGF0aCwKICAgICAgICAgIHBhcmVudDogaW5wdXQucGFyZW50CiAgICAgICAgfQogICAgICB9OwogICAgfQogICAgX3BhcnNlU3luYyhpbnB1dCkgewogICAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9wYXJzZShpbnB1dCk7CiAgICAgIGlmIChpc0FzeW5jKHJlc3VsdCkpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlN5bmNocm9ub3VzIHBhcnNlIGVuY291bnRlcmVkIHByb21pc2UuIik7CiAgICAgIH0KICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIF9wYXJzZUFzeW5jKGlucHV0KSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX3BhcnNlKGlucHV0KTsKICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHQpOwogICAgfQogICAgcGFyc2UoZGF0YSwgcGFyYW1zKSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuc2FmZVBhcnNlKGRhdGEsIHBhcmFtcyk7CiAgICAgIGlmIChyZXN1bHQuc3VjY2VzcykKICAgICAgICByZXR1cm4gcmVzdWx0LmRhdGE7CiAgICAgIHRocm93IHJlc3VsdC5lcnJvcjsKICAgIH0KICAgIHNhZmVQYXJzZShkYXRhLCBwYXJhbXMpIHsKICAgICAgdmFyIF9hOwogICAgICBjb25zdCBjdHggPSB7CiAgICAgICAgY29tbW9uOiB7CiAgICAgICAgICBpc3N1ZXM6IFtdLAogICAgICAgICAgYXN5bmM6IChfYSA9IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5hc3luYykgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogZmFsc2UsCiAgICAgICAgICBjb250ZXh0dWFsRXJyb3JNYXA6IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5lcnJvck1hcAogICAgICAgIH0sCiAgICAgICAgcGF0aDogKHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5wYXRoKSB8fCBbXSwKICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLAogICAgICAgIHBhcmVudDogbnVsbCwKICAgICAgICBkYXRhLAogICAgICAgIHBhcnNlZFR5cGU6IGdldFBhcnNlZFR5cGUoZGF0YSkKICAgICAgfTsKICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fcGFyc2VTeW5jKHsgZGF0YSwgcGF0aDogY3R4LnBhdGgsIHBhcmVudDogY3R4IH0pOwogICAgICByZXR1cm4gaGFuZGxlUmVzdWx0KGN0eCwgcmVzdWx0KTsKICAgIH0KICAgIGFzeW5jIHBhcnNlQXN5bmMoZGF0YSwgcGFyYW1zKSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuc2FmZVBhcnNlQXN5bmMoZGF0YSwgcGFyYW1zKTsKICAgICAgaWYgKHJlc3VsdC5zdWNjZXNzKQogICAgICAgIHJldHVybiByZXN1bHQuZGF0YTsKICAgICAgdGhyb3cgcmVzdWx0LmVycm9yOwogICAgfQogICAgYXN5bmMgc2FmZVBhcnNlQXN5bmMoZGF0YSwgcGFyYW1zKSB7CiAgICAgIGNvbnN0IGN0eCA9IHsKICAgICAgICBjb21tb246IHsKICAgICAgICAgIGlzc3VlczogW10sCiAgICAgICAgICBjb250ZXh0dWFsRXJyb3JNYXA6IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5lcnJvck1hcCwKICAgICAgICAgIGFzeW5jOiB0cnVlCiAgICAgICAgfSwKICAgICAgICBwYXRoOiAocGFyYW1zID09PSBudWxsIHx8IHBhcmFtcyA9PT0gdm9pZCAwID8gdm9pZCAwIDogcGFyYW1zLnBhdGgpIHx8IFtdLAogICAgICAgIHNjaGVtYUVycm9yTWFwOiB0aGlzLl9kZWYuZXJyb3JNYXAsCiAgICAgICAgcGFyZW50OiBudWxsLAogICAgICAgIGRhdGEsCiAgICAgICAgcGFyc2VkVHlwZTogZ2V0UGFyc2VkVHlwZShkYXRhKQogICAgICB9OwogICAgICBjb25zdCBtYXliZUFzeW5jUmVzdWx0ID0gdGhpcy5fcGFyc2UoeyBkYXRhLCBwYXRoOiBjdHgucGF0aCwgcGFyZW50OiBjdHggfSk7CiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IChpc0FzeW5jKG1heWJlQXN5bmNSZXN1bHQpID8gbWF5YmVBc3luY1Jlc3VsdCA6IFByb21pc2UucmVzb2x2ZShtYXliZUFzeW5jUmVzdWx0KSk7CiAgICAgIHJldHVybiBoYW5kbGVSZXN1bHQoY3R4LCByZXN1bHQpOwogICAgfQogICAgcmVmaW5lKGNoZWNrLCBtZXNzYWdlKSB7CiAgICAgIGNvbnN0IGdldElzc3VlUHJvcGVydGllcyA9ICh2YWwpID0+IHsKICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgPT09ICJzdHJpbmciIHx8IHR5cGVvZiBtZXNzYWdlID09PSAidW5kZWZpbmVkIikgewogICAgICAgICAgcmV0dXJuIHsgbWVzc2FnZSB9OwogICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG1lc3NhZ2UgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgIHJldHVybiBtZXNzYWdlKHZhbCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBtZXNzYWdlOwogICAgICAgIH0KICAgICAgfTsKICAgICAgcmV0dXJuIHRoaXMuX3JlZmluZW1lbnQoKHZhbCwgY3R4KSA9PiB7CiAgICAgICAgY29uc3QgcmVzdWx0ID0gY2hlY2sodmFsKTsKICAgICAgICBjb25zdCBzZXRFcnJvciA9ICgpID0+IGN0eC5hZGRJc3N1ZSh7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuY3VzdG9tLAogICAgICAgICAgLi4uZ2V0SXNzdWVQcm9wZXJ0aWVzKHZhbCkKICAgICAgICB9KTsKICAgICAgICBpZiAodHlwZW9mIFByb21pc2UgIT09ICJ1bmRlZmluZWQiICYmIHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UpIHsKICAgICAgICAgIHJldHVybiByZXN1bHQudGhlbigoZGF0YSkgPT4gewogICAgICAgICAgICBpZiAoIWRhdGEpIHsKICAgICAgICAgICAgICBzZXRFcnJvcigpOwogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGlmICghcmVzdWx0KSB7CiAgICAgICAgICBzZXRFcnJvcigpOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogICAgcmVmaW5lbWVudChjaGVjaywgcmVmaW5lbWVudERhdGEpIHsKICAgICAgcmV0dXJuIHRoaXMuX3JlZmluZW1lbnQoKHZhbCwgY3R4KSA9PiB7CiAgICAgICAgaWYgKCFjaGVjayh2YWwpKSB7CiAgICAgICAgICBjdHguYWRkSXNzdWUodHlwZW9mIHJlZmluZW1lbnREYXRhID09PSAiZnVuY3Rpb24iID8gcmVmaW5lbWVudERhdGEodmFsLCBjdHgpIDogcmVmaW5lbWVudERhdGEpOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogICAgX3JlZmluZW1lbnQocmVmaW5lbWVudCkgewogICAgICByZXR1cm4gbmV3IFpvZEVmZmVjdHMoewogICAgICAgIHNjaGVtYTogdGhpcywKICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMsCiAgICAgICAgZWZmZWN0OiB7IHR5cGU6ICJyZWZpbmVtZW50IiwgcmVmaW5lbWVudCB9CiAgICAgIH0pOwogICAgfQogICAgc3VwZXJSZWZpbmUocmVmaW5lbWVudCkgewogICAgICByZXR1cm4gdGhpcy5fcmVmaW5lbWVudChyZWZpbmVtZW50KTsKICAgIH0KICAgIG9wdGlvbmFsKCkgewogICAgICByZXR1cm4gWm9kT3B0aW9uYWwuY3JlYXRlKHRoaXMsIHRoaXMuX2RlZik7CiAgICB9CiAgICBudWxsYWJsZSgpIHsKICAgICAgcmV0dXJuIFpvZE51bGxhYmxlLmNyZWF0ZSh0aGlzLCB0aGlzLl9kZWYpOwogICAgfQogICAgbnVsbGlzaCgpIHsKICAgICAgcmV0dXJuIHRoaXMubnVsbGFibGUoKS5vcHRpb25hbCgpOwogICAgfQogICAgYXJyYXkoKSB7CiAgICAgIHJldHVybiBab2RBcnJheS5jcmVhdGUodGhpcywgdGhpcy5fZGVmKTsKICAgIH0KICAgIHByb21pc2UoKSB7CiAgICAgIHJldHVybiBab2RQcm9taXNlLmNyZWF0ZSh0aGlzLCB0aGlzLl9kZWYpOwogICAgfQogICAgb3Iob3B0aW9uKSB7CiAgICAgIHJldHVybiBab2RVbmlvbi5jcmVhdGUoW3RoaXMsIG9wdGlvbl0sIHRoaXMuX2RlZik7CiAgICB9CiAgICBhbmQoaW5jb21pbmcpIHsKICAgICAgcmV0dXJuIFpvZEludGVyc2VjdGlvbi5jcmVhdGUodGhpcywgaW5jb21pbmcsIHRoaXMuX2RlZik7CiAgICB9CiAgICB0cmFuc2Zvcm0odHJhbnNmb3JtKSB7CiAgICAgIHJldHVybiBuZXcgWm9kRWZmZWN0cyh7CiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyh0aGlzLl9kZWYpLAogICAgICAgIHNjaGVtYTogdGhpcywKICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMsCiAgICAgICAgZWZmZWN0OiB7IHR5cGU6ICJ0cmFuc2Zvcm0iLCB0cmFuc2Zvcm0gfQogICAgICB9KTsKICAgIH0KICAgIGRlZmF1bHQoZGVmKSB7CiAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZUZ1bmMgPSB0eXBlb2YgZGVmID09PSAiZnVuY3Rpb24iID8gZGVmIDogKCkgPT4gZGVmOwogICAgICByZXR1cm4gbmV3IFpvZERlZmF1bHQoewogICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXModGhpcy5fZGVmKSwKICAgICAgICBpbm5lclR5cGU6IHRoaXMsCiAgICAgICAgZGVmYXVsdFZhbHVlOiBkZWZhdWx0VmFsdWVGdW5jLAogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRGVmYXVsdAogICAgICB9KTsKICAgIH0KICAgIGJyYW5kKCkgewogICAgICByZXR1cm4gbmV3IFpvZEJyYW5kZWQoewogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kQnJhbmRlZCwKICAgICAgICB0eXBlOiB0aGlzLAogICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXModGhpcy5fZGVmKQogICAgICB9KTsKICAgIH0KICAgIGNhdGNoKGRlZikgewogICAgICBjb25zdCBjYXRjaFZhbHVlRnVuYyA9IHR5cGVvZiBkZWYgPT09ICJmdW5jdGlvbiIgPyBkZWYgOiAoKSA9PiBkZWY7CiAgICAgIHJldHVybiBuZXcgWm9kQ2F0Y2goewogICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXModGhpcy5fZGVmKSwKICAgICAgICBpbm5lclR5cGU6IHRoaXMsCiAgICAgICAgY2F0Y2hWYWx1ZTogY2F0Y2hWYWx1ZUZ1bmMsCiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RDYXRjaAogICAgICB9KTsKICAgIH0KICAgIGRlc2NyaWJlKGRlc2NyaXB0aW9uKSB7CiAgICAgIGNvbnN0IFRoaXMgPSB0aGlzLmNvbnN0cnVjdG9yOwogICAgICByZXR1cm4gbmV3IFRoaXMoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBkZXNjcmlwdGlvbgogICAgICB9KTsKICAgIH0KICAgIHBpcGUodGFyZ2V0KSB7CiAgICAgIHJldHVybiBab2RQaXBlbGluZS5jcmVhdGUodGhpcywgdGFyZ2V0KTsKICAgIH0KICAgIHJlYWRvbmx5KCkgewogICAgICByZXR1cm4gWm9kUmVhZG9ubHkuY3JlYXRlKHRoaXMpOwogICAgfQogICAgaXNPcHRpb25hbCgpIHsKICAgICAgcmV0dXJuIHRoaXMuc2FmZVBhcnNlKHZvaWQgMCkuc3VjY2VzczsKICAgIH0KICAgIGlzTnVsbGFibGUoKSB7CiAgICAgIHJldHVybiB0aGlzLnNhZmVQYXJzZShudWxsKS5zdWNjZXNzOwogICAgfQogIH0KICBjb25zdCBjdWlkUmVnZXggPSAvXmNbXlxzLV17OCx9JC9pOwogIGNvbnN0IGN1aWQyUmVnZXggPSAvXlswLTlhLXpdKyQvOwogIGNvbnN0IHVsaWRSZWdleCA9IC9eWzAtOUEtSEpLTU5QLVRWLVpdezI2fSQvOwogIGNvbnN0IHV1aWRSZWdleCA9IC9eWzAtOWEtZkEtRl17OH1cYi1bMC05YS1mQS1GXXs0fVxiLVswLTlhLWZBLUZdezR9XGItWzAtOWEtZkEtRl17NH1cYi1bMC05YS1mQS1GXXsxMn0kL2k7CiAgY29uc3QgbmFub2lkUmVnZXggPSAvXlthLXowLTlfLV17MjF9JC9pOwogIGNvbnN0IGR1cmF0aW9uUmVnZXggPSAvXlstK10/UCg/ISQpKD86KD86Wy0rXT9cZCtZKXwoPzpbLStdP1xkK1suLF1cZCtZJCkpPyg/Oig/OlstK10/XGQrTSl8KD86Wy0rXT9cZCtbLixdXGQrTSQpKT8oPzooPzpbLStdP1xkK1cpfCg/OlstK10/XGQrWy4sXVxkK1ckKSk/KD86KD86Wy0rXT9cZCtEKXwoPzpbLStdP1xkK1suLF1cZCtEJCkpPyg/OlQoPz1bXGQrLV0pKD86KD86Wy0rXT9cZCtIKXwoPzpbLStdP1xkK1suLF1cZCtIJCkpPyg/Oig/OlstK10/XGQrTSl8KD86Wy0rXT9cZCtbLixdXGQrTSQpKT8oPzpbLStdP1xkKyg/OlsuLF1cZCspP1MpPyk/PyQvOwogIGNvbnN0IGVtYWlsUmVnZXggPSAvXig/IVwuKSg/IS4qXC5cLikoW0EtWjAtOV8nK1wtXC5dKilbQS1aMC05XystXUAoW0EtWjAtOV1bQS1aMC05XC1dKlwuKStbQS1aXXsyLH0kL2k7CiAgY29uc3QgX2Vtb2ppUmVnZXggPSBgXihcXHB7RXh0ZW5kZWRfUGljdG9ncmFwaGljfXxcXHB7RW1vamlfQ29tcG9uZW50fSkrJGA7CiAgbGV0IGVtb2ppUmVnZXg7CiAgY29uc3QgaXB2NFJlZ2V4ID0gL14oPzooPzoyNVswLTVdfDJbMC00XVswLTldfDFbMC05XVswLTldfFsxLTldWzAtOV18WzAtOV0pXC4pezN9KD86MjVbMC01XXwyWzAtNF1bMC05XXwxWzAtOV1bMC05XXxbMS05XVswLTldfFswLTldKSQvOwogIGNvbnN0IGlwdjZSZWdleCA9IC9eKChbYS1mMC05XXsxLDR9Oil7N318OjooW2EtZjAtOV17MSw0fTopezAsNn18KFthLWYwLTldezEsNH06KXsxfTooW2EtZjAtOV17MSw0fTopezAsNX18KFthLWYwLTldezEsNH06KXsyfTooW2EtZjAtOV17MSw0fTopezAsNH18KFthLWYwLTldezEsNH06KXszfTooW2EtZjAtOV17MSw0fTopezAsM318KFthLWYwLTldezEsNH06KXs0fTooW2EtZjAtOV17MSw0fTopezAsMn18KFthLWYwLTldezEsNH06KXs1fTooW2EtZjAtOV17MSw0fTopezAsMX0pKFthLWYwLTldezEsNH18KCgoMjVbMC01XSl8KDJbMC00XVswLTldKXwoMVswLTldezJ9KXwoWzAtOV17MSwyfSkpXC4pezN9KCgyNVswLTVdKXwoMlswLTRdWzAtOV0pfCgxWzAtOV17Mn0pfChbMC05XXsxLDJ9KSkpJC87CiAgY29uc3QgYmFzZTY0UmVnZXggPSAvXihbMC05YS16QS1aKy9dezR9KSooKFswLTlhLXpBLVorL117Mn09PSl8KFswLTlhLXpBLVorL117M309KSk/JC87CiAgY29uc3QgZGF0ZVJlZ2V4U291cmNlID0gYCgoXFxkXFxkWzI0NjhdWzA0OF18XFxkXFxkWzEzNTc5XVsyNl18XFxkXFxkMFs0OF18WzAyNDY4XVswNDhdMDB8WzEzNTc5XVsyNl0wMCktMDItMjl8XFxkezR9LSgoMFsxMzU3OF18MVswMl0pLSgwWzEtOV18WzEyXVxcZHwzWzAxXSl8KDBbNDY5XXwxMSktKDBbMS05XXxbMTJdXFxkfDMwKXwoMDIpLSgwWzEtOV18MVxcZHwyWzAtOF0pKSlgOwogIGNvbnN0IGRhdGVSZWdleCA9IG5ldyBSZWdFeHAoYF4ke2RhdGVSZWdleFNvdXJjZX0kYCk7CiAgZnVuY3Rpb24gdGltZVJlZ2V4U291cmNlKGFyZ3MpIHsKICAgIGxldCByZWdleCA9IGAoWzAxXVxcZHwyWzAtM10pOlswLTVdXFxkOlswLTVdXFxkYDsKICAgIGlmIChhcmdzLnByZWNpc2lvbikgewogICAgICByZWdleCA9IGAke3JlZ2V4fVxcLlxcZHske2FyZ3MucHJlY2lzaW9ufX1gOwogICAgfSBlbHNlIGlmIChhcmdzLnByZWNpc2lvbiA9PSBudWxsKSB7CiAgICAgIHJlZ2V4ID0gYCR7cmVnZXh9KFxcLlxcZCspP2A7CiAgICB9CiAgICByZXR1cm4gcmVnZXg7CiAgfQogIGZ1bmN0aW9uIHRpbWVSZWdleChhcmdzKSB7CiAgICByZXR1cm4gbmV3IFJlZ0V4cChgXiR7dGltZVJlZ2V4U291cmNlKGFyZ3MpfSRgKTsKICB9CiAgZnVuY3Rpb24gZGF0ZXRpbWVSZWdleChhcmdzKSB7CiAgICBsZXQgcmVnZXggPSBgJHtkYXRlUmVnZXhTb3VyY2V9VCR7dGltZVJlZ2V4U291cmNlKGFyZ3MpfWA7CiAgICBjb25zdCBvcHRzID0gW107CiAgICBvcHRzLnB1c2goYXJncy5sb2NhbCA/IGBaP2AgOiBgWmApOwogICAgaWYgKGFyZ3Mub2Zmc2V0KQogICAgICBvcHRzLnB1c2goYChbKy1dXFxkezJ9Oj9cXGR7Mn0pYCk7CiAgICByZWdleCA9IGAke3JlZ2V4fSgke29wdHMuam9pbigifCIpfSlgOwogICAgcmV0dXJuIG5ldyBSZWdFeHAoYF4ke3JlZ2V4fSRgKTsKICB9CiAgZnVuY3Rpb24gaXNWYWxpZElQKGlwLCB2ZXJzaW9uKSB7CiAgICBpZiAoKHZlcnNpb24gPT09ICJ2NCIgfHwgIXZlcnNpb24pICYmIGlwdjRSZWdleC50ZXN0KGlwKSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmICgodmVyc2lvbiA9PT0gInY2IiB8fCAhdmVyc2lvbikgJiYgaXB2NlJlZ2V4LnRlc3QoaXApKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICBjbGFzcyBab2RTdHJpbmcgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBpZiAodGhpcy5fZGVmLmNvZXJjZSkgewogICAgICAgIGlucHV0LmRhdGEgPSBTdHJpbmcoaW5wdXQuZGF0YSk7CiAgICAgIH0KICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5zdHJpbmcpIHsKICAgICAgICBjb25zdCBjdHgyID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eDIsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5zdHJpbmcsCiAgICAgICAgICByZWNlaXZlZDogY3R4Mi5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgY29uc3Qgc3RhdHVzID0gbmV3IFBhcnNlU3RhdHVzKCk7CiAgICAgIGxldCBjdHggPSB2b2lkIDA7CiAgICAgIGZvciAoY29uc3QgY2hlY2sgb2YgdGhpcy5fZGVmLmNoZWNrcykgewogICAgICAgIGlmIChjaGVjay5raW5kID09PSAibWluIikgewogICAgICAgICAgaWYgKGlucHV0LmRhdGEubGVuZ3RoIDwgY2hlY2sudmFsdWUpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgICAgbWluaW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogInN0cmluZyIsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAoaW5wdXQuZGF0YS5sZW5ndGggPiBjaGVjay52YWx1ZSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsCiAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogInN0cmluZyIsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJsZW5ndGgiKSB7CiAgICAgICAgICBjb25zdCB0b29CaWcgPSBpbnB1dC5kYXRhLmxlbmd0aCA+IGNoZWNrLnZhbHVlOwogICAgICAgICAgY29uc3QgdG9vU21hbGwgPSBpbnB1dC5kYXRhLmxlbmd0aCA8IGNoZWNrLnZhbHVlOwogICAgICAgICAgaWYgKHRvb0JpZyB8fCB0b29TbWFsbCkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgaWYgKHRvb0JpZykgewogICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsCiAgICAgICAgICAgICAgICBtYXhpbXVtOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICAgIHR5cGU6ICJzdHJpbmciLAogICAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgICAgZXhhY3Q6IHRydWUsCiAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAodG9vU21hbGwpIHsKICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgICAgICBtaW5pbXVtOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICAgIHR5cGU6ICJzdHJpbmciLAogICAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgICAgZXhhY3Q6IHRydWUsCiAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiZW1haWwiKSB7CiAgICAgICAgICBpZiAoIWVtYWlsUmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImVtYWlsIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiZW1vamkiKSB7CiAgICAgICAgICBpZiAoIWVtb2ppUmVnZXgpIHsKICAgICAgICAgICAgZW1vamlSZWdleCA9IG5ldyBSZWdFeHAoX2Vtb2ppUmVnZXgsICJ1Iik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIWVtb2ppUmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImVtb2ppIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidXVpZCIpIHsKICAgICAgICAgIGlmICghdXVpZFJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJ1dWlkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAibmFub2lkIikgewogICAgICAgICAgaWYgKCFuYW5vaWRSZWdleC50ZXN0KGlucHV0LmRhdGEpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiAibmFub2lkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiY3VpZCIpIHsKICAgICAgICAgIGlmICghY3VpZFJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJjdWlkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiY3VpZDIiKSB7CiAgICAgICAgICBpZiAoIWN1aWQyUmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImN1aWQyIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidWxpZCIpIHsKICAgICAgICAgIGlmICghdWxpZFJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJ1bGlkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidXJsIikgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgbmV3IFVSTChpbnB1dC5kYXRhKTsKICAgICAgICAgIH0gY2F0Y2ggKF9hKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiAidXJsIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAicmVnZXgiKSB7CiAgICAgICAgICBjaGVjay5yZWdleC5sYXN0SW5kZXggPSAwOwogICAgICAgICAgY29uc3QgdGVzdFJlc3VsdCA9IGNoZWNrLnJlZ2V4LnRlc3QoaW5wdXQuZGF0YSk7CiAgICAgICAgICBpZiAoIXRlc3RSZXN1bHQpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJyZWdleCIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gInRyaW0iKSB7CiAgICAgICAgICBpbnB1dC5kYXRhID0gaW5wdXQuZGF0YS50cmltKCk7CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiaW5jbHVkZXMiKSB7CiAgICAgICAgICBpZiAoIWlucHV0LmRhdGEuaW5jbHVkZXMoY2hlY2sudmFsdWUsIGNoZWNrLnBvc2l0aW9uKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIHZhbGlkYXRpb246IHsgaW5jbHVkZXM6IGNoZWNrLnZhbHVlLCBwb3NpdGlvbjogY2hlY2sucG9zaXRpb24gfSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJ0b0xvd2VyQ2FzZSIpIHsKICAgICAgICAgIGlucHV0LmRhdGEgPSBpbnB1dC5kYXRhLnRvTG93ZXJDYXNlKCk7CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidG9VcHBlckNhc2UiKSB7CiAgICAgICAgICBpbnB1dC5kYXRhID0gaW5wdXQuZGF0YS50b1VwcGVyQ2FzZSgpOwogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gInN0YXJ0c1dpdGgiKSB7CiAgICAgICAgICBpZiAoIWlucHV0LmRhdGEuc3RhcnRzV2l0aChjaGVjay52YWx1ZSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZywKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiB7IHN0YXJ0c1dpdGg6IGNoZWNrLnZhbHVlIH0sCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiZW5kc1dpdGgiKSB7CiAgICAgICAgICBpZiAoIWlucHV0LmRhdGEuZW5kc1dpdGgoY2hlY2sudmFsdWUpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogeyBlbmRzV2l0aDogY2hlY2sudmFsdWUgfSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJkYXRldGltZSIpIHsKICAgICAgICAgIGNvbnN0IHJlZ2V4ID0gZGF0ZXRpbWVSZWdleChjaGVjayk7CiAgICAgICAgICBpZiAoIXJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZywKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiAiZGF0ZXRpbWUiLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImRhdGUiKSB7CiAgICAgICAgICBjb25zdCByZWdleCA9IGRhdGVSZWdleDsKICAgICAgICAgIGlmICghcmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJkYXRlIiwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJ0aW1lIikgewogICAgICAgICAgY29uc3QgcmVnZXggPSB0aW1lUmVnZXgoY2hlY2spOwogICAgICAgICAgaWYgKCFyZWdleC50ZXN0KGlucHV0LmRhdGEpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogInRpbWUiLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImR1cmF0aW9uIikgewogICAgICAgICAgaWYgKCFkdXJhdGlvblJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJkdXJhdGlvbiIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImlwIikgewogICAgICAgICAgaWYgKCFpc1ZhbGlkSVAoaW5wdXQuZGF0YSwgY2hlY2sudmVyc2lvbikpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJpcCIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImJhc2U2NCIpIHsKICAgICAgICAgIGlmICghYmFzZTY0UmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImJhc2U2NCIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB1dGlsLmFzc2VydE5ldmVyKGNoZWNrKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBpbnB1dC5kYXRhIH07CiAgICB9CiAgICBfcmVnZXgocmVnZXgsIHZhbGlkYXRpb24sIG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMucmVmaW5lbWVudCgoZGF0YSkgPT4gcmVnZXgudGVzdChkYXRhKSwgewogICAgICAgIHZhbGlkYXRpb24sCiAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIF9hZGRDaGVjayhjaGVjaykgewogICAgICByZXR1cm4gbmV3IFpvZFN0cmluZyh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIGNoZWNrczogWy4uLnRoaXMuX2RlZi5jaGVja3MsIGNoZWNrXQogICAgICB9KTsKICAgIH0KICAgIGVtYWlsKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImVtYWlsIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgdXJsKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogInVybCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGVtb2ppKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImVtb2ppIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgdXVpZChtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6ICJ1dWlkIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgbmFub2lkKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogIm5hbm9pZCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGN1aWQobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soeyBraW5kOiAiY3VpZCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGN1aWQyKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImN1aWQyIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgdWxpZChtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6ICJ1bGlkIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgYmFzZTY0KG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImJhc2U2NCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGlwKG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImlwIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG9wdGlvbnMpIH0pOwogICAgfQogICAgZGF0ZXRpbWUob3B0aW9ucykgewogICAgICB2YXIgX2EsIF9iOwogICAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICJzdHJpbmciKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICAgIGtpbmQ6ICJkYXRldGltZSIsCiAgICAgICAgICBwcmVjaXNpb246IG51bGwsCiAgICAgICAgICBvZmZzZXQ6IGZhbHNlLAogICAgICAgICAgbG9jYWw6IGZhbHNlLAogICAgICAgICAgbWVzc2FnZTogb3B0aW9ucwogICAgICAgIH0pOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImRhdGV0aW1lIiwKICAgICAgICBwcmVjaXNpb246IHR5cGVvZiAob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLnByZWNpc2lvbikgPT09ICJ1bmRlZmluZWQiID8gbnVsbCA6IG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5wcmVjaXNpb24sCiAgICAgICAgb2Zmc2V0OiAoX2EgPSBvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMub2Zmc2V0KSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiBmYWxzZSwKICAgICAgICBsb2NhbDogKF9iID0gb3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLmxvY2FsKSAhPT0gbnVsbCAmJiBfYiAhPT0gdm9pZCAwID8gX2IgOiBmYWxzZSwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLm1lc3NhZ2UpCiAgICAgIH0pOwogICAgfQogICAgZGF0ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6ICJkYXRlIiwgbWVzc2FnZSB9KTsKICAgIH0KICAgIHRpbWUob3B0aW9ucykgewogICAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICJzdHJpbmciKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICAgIGtpbmQ6ICJ0aW1lIiwKICAgICAgICAgIHByZWNpc2lvbjogbnVsbCwKICAgICAgICAgIG1lc3NhZ2U6IG9wdGlvbnMKICAgICAgICB9KTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJ0aW1lIiwKICAgICAgICBwcmVjaXNpb246IHR5cGVvZiAob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLnByZWNpc2lvbikgPT09ICJ1bmRlZmluZWQiID8gbnVsbCA6IG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5wcmVjaXNpb24sCiAgICAgICAgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5tZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGR1cmF0aW9uKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImR1cmF0aW9uIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgcmVnZXgocmVnZXgsIG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAicmVnZXgiLAogICAgICAgIHJlZ2V4LAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGluY2x1ZGVzKHZhbHVlLCBvcHRpb25zKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImluY2x1ZGVzIiwKICAgICAgICB2YWx1ZSwKICAgICAgICBwb3NpdGlvbjogb3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLnBvc2l0aW9uLAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMubWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBzdGFydHNXaXRoKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogInN0YXJ0c1dpdGgiLAogICAgICAgIHZhbHVlLAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGVuZHNXaXRoKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImVuZHNXaXRoIiwKICAgICAgICB2YWx1ZSwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBtaW4obWluTGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IG1pbkxlbmd0aCwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBtYXgobWF4TGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IG1heExlbmd0aCwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBsZW5ndGgobGVuLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImxlbmd0aCIsCiAgICAgICAgdmFsdWU6IGxlbiwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICAvKioKICAgICAqIEBkZXByZWNhdGVkIFVzZSB6LnN0cmluZygpLm1pbigxKSBpbnN0ZWFkLgogICAgICogQHNlZSB7QGxpbmsgWm9kU3RyaW5nLm1pbn0KICAgICAqLwogICAgbm9uZW1wdHkobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5taW4oMSwgZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpKTsKICAgIH0KICAgIHRyaW0oKSB7CiAgICAgIHJldHVybiBuZXcgWm9kU3RyaW5nKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgeyBraW5kOiAidHJpbSIgfV0KICAgICAgfSk7CiAgICB9CiAgICB0b0xvd2VyQ2FzZSgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RTdHJpbmcoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBjaGVja3M6IFsuLi50aGlzLl9kZWYuY2hlY2tzLCB7IGtpbmQ6ICJ0b0xvd2VyQ2FzZSIgfV0KICAgICAgfSk7CiAgICB9CiAgICB0b1VwcGVyQ2FzZSgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RTdHJpbmcoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBjaGVja3M6IFsuLi50aGlzLl9kZWYuY2hlY2tzLCB7IGtpbmQ6ICJ0b1VwcGVyQ2FzZSIgfV0KICAgICAgfSk7CiAgICB9CiAgICBnZXQgaXNEYXRldGltZSgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImRhdGV0aW1lIik7CiAgICB9CiAgICBnZXQgaXNEYXRlKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiZGF0ZSIpOwogICAgfQogICAgZ2V0IGlzVGltZSgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gInRpbWUiKTsKICAgIH0KICAgIGdldCBpc0R1cmF0aW9uKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiZHVyYXRpb24iKTsKICAgIH0KICAgIGdldCBpc0VtYWlsKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiZW1haWwiKTsKICAgIH0KICAgIGdldCBpc1VSTCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gInVybCIpOwogICAgfQogICAgZ2V0IGlzRW1vamkoKSB7CiAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09ICJlbW9qaSIpOwogICAgfQogICAgZ2V0IGlzVVVJRCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gInV1aWQiKTsKICAgIH0KICAgIGdldCBpc05BTk9JRCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gIm5hbm9pZCIpOwogICAgfQogICAgZ2V0IGlzQ1VJRCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImN1aWQiKTsKICAgIH0KICAgIGdldCBpc0NVSUQyKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiY3VpZDIiKTsKICAgIH0KICAgIGdldCBpc1VMSUQoKSB7CiAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09ICJ1bGlkIik7CiAgICB9CiAgICBnZXQgaXNJUCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImlwIik7CiAgICB9CiAgICBnZXQgaXNCYXNlNjQoKSB7CiAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09ICJiYXNlNjQiKTsKICAgIH0KICAgIGdldCBtaW5MZW5ndGgoKSB7CiAgICAgIGxldCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChtaW4gPT09IG51bGwgfHwgY2gudmFsdWUgPiBtaW4pCiAgICAgICAgICAgIG1pbiA9IGNoLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbWluOwogICAgfQogICAgZ2V0IG1heExlbmd0aCgpIHsKICAgICAgbGV0IG1heCA9IG51bGw7CiAgICAgIGZvciAoY29uc3QgY2ggb2YgdGhpcy5fZGVmLmNoZWNrcykgewogICAgICAgIGlmIChjaC5raW5kID09PSAibWF4IikgewogICAgICAgICAgaWYgKG1heCA9PT0gbnVsbCB8fCBjaC52YWx1ZSA8IG1heCkKICAgICAgICAgICAgbWF4ID0gY2gudmFsdWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBtYXg7CiAgICB9CiAgfQogIFpvZFN0cmluZy5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICB2YXIgX2E7CiAgICByZXR1cm4gbmV3IFpvZFN0cmluZyh7CiAgICAgIGNoZWNrczogW10sCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kU3RyaW5nLAogICAgICBjb2VyY2U6IChfYSA9IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5jb2VyY2UpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IGZhbHNlLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgZnVuY3Rpb24gZmxvYXRTYWZlUmVtYWluZGVyKHZhbCwgc3RlcCkgewogICAgY29uc3QgdmFsRGVjQ291bnQgPSAodmFsLnRvU3RyaW5nKCkuc3BsaXQoIi4iKVsxXSB8fCAiIikubGVuZ3RoOwogICAgY29uc3Qgc3RlcERlY0NvdW50ID0gKHN0ZXAudG9TdHJpbmcoKS5zcGxpdCgiLiIpWzFdIHx8ICIiKS5sZW5ndGg7CiAgICBjb25zdCBkZWNDb3VudCA9IHZhbERlY0NvdW50ID4gc3RlcERlY0NvdW50ID8gdmFsRGVjQ291bnQgOiBzdGVwRGVjQ291bnQ7CiAgICBjb25zdCB2YWxJbnQgPSBwYXJzZUludCh2YWwudG9GaXhlZChkZWNDb3VudCkucmVwbGFjZSgiLiIsICIiKSk7CiAgICBjb25zdCBzdGVwSW50ID0gcGFyc2VJbnQoc3RlcC50b0ZpeGVkKGRlY0NvdW50KS5yZXBsYWNlKCIuIiwgIiIpKTsKICAgIHJldHVybiB2YWxJbnQgJSBzdGVwSW50IC8gTWF0aC5wb3coMTAsIGRlY0NvdW50KTsKICB9CiAgY2xhc3MgWm9kTnVtYmVyIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgdGhpcy5taW4gPSB0aGlzLmd0ZTsKICAgICAgdGhpcy5tYXggPSB0aGlzLmx0ZTsKICAgICAgdGhpcy5zdGVwID0gdGhpcy5tdWx0aXBsZU9mOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGlmICh0aGlzLl9kZWYuY29lcmNlKSB7CiAgICAgICAgaW5wdXQuZGF0YSA9IE51bWJlcihpbnB1dC5kYXRhKTsKICAgICAgfQogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm51bWJlcikgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm51bWJlciwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgyLnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBsZXQgY3R4ID0gdm9pZCAwOwogICAgICBjb25zdCBzdGF0dXMgPSBuZXcgUGFyc2VTdGF0dXMoKTsKICAgICAgZm9yIChjb25zdCBjaGVjayBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoZWNrLmtpbmQgPT09ICJpbnQiKSB7CiAgICAgICAgICBpZiAoIXV0aWwuaXNJbnRlZ2VyKGlucHV0LmRhdGEpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgICAgIGV4cGVjdGVkOiAiaW50ZWdlciIsCiAgICAgICAgICAgICAgcmVjZWl2ZWQ6ICJmbG9hdCIsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAibWluIikgewogICAgICAgICAgY29uc3QgdG9vU21hbGwgPSBjaGVjay5pbmNsdXNpdmUgPyBpbnB1dC5kYXRhIDwgY2hlY2sudmFsdWUgOiBpbnB1dC5kYXRhIDw9IGNoZWNrLnZhbHVlOwogICAgICAgICAgaWYgKHRvb1NtYWxsKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgICAgIG1pbmltdW06IGNoZWNrLnZhbHVlLAogICAgICAgICAgICAgIHR5cGU6ICJudW1iZXIiLAogICAgICAgICAgICAgIGluY2x1c2l2ZTogY2hlY2suaW5jbHVzaXZlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBjb25zdCB0b29CaWcgPSBjaGVjay5pbmNsdXNpdmUgPyBpbnB1dC5kYXRhID4gY2hlY2sudmFsdWUgOiBpbnB1dC5kYXRhID49IGNoZWNrLnZhbHVlOwogICAgICAgICAgaWYgKHRvb0JpZykgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsCiAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogIm51bWJlciIsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiBjaGVjay5pbmNsdXNpdmUsCiAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gIm11bHRpcGxlT2YiKSB7CiAgICAgICAgICBpZiAoZmxvYXRTYWZlUmVtYWluZGVyKGlucHV0LmRhdGEsIGNoZWNrLnZhbHVlKSAhPT0gMCkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLm5vdF9tdWx0aXBsZV9vZiwKICAgICAgICAgICAgICBtdWx0aXBsZU9mOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJmaW5pdGUiKSB7CiAgICAgICAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLm5vdF9maW5pdGUsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoY2hlY2spOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGlucHV0LmRhdGEgfTsKICAgIH0KICAgIGd0ZSh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIHRydWUsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBndCh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIGZhbHNlLCBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkpOwogICAgfQogICAgbHRlKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgdHJ1ZSwgZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpKTsKICAgIH0KICAgIGx0KHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgZmFsc2UsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBzZXRMaW1pdChraW5kLCB2YWx1ZSwgaW5jbHVzaXZlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kTnVtYmVyKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbCiAgICAgICAgICAuLi50aGlzLl9kZWYuY2hlY2tzLAogICAgICAgICAgewogICAgICAgICAgICBraW5kLAogICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgaW5jbHVzaXZlLAogICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgICAgIH0KICAgICAgICBdCiAgICAgIH0pOwogICAgfQogICAgX2FkZENoZWNrKGNoZWNrKSB7CiAgICAgIHJldHVybiBuZXcgWm9kTnVtYmVyKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgY2hlY2tdCiAgICAgIH0pOwogICAgfQogICAgaW50KG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAiaW50IiwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBwb3NpdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IDAsCiAgICAgICAgaW5jbHVzaXZlOiBmYWxzZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBuZWdhdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IDAsCiAgICAgICAgaW5jbHVzaXZlOiBmYWxzZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBub25wb3NpdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IDAsCiAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIG5vbm5lZ2F0aXZlKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAibWluIiwKICAgICAgICB2YWx1ZTogMCwKICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpCiAgICAgIH0pOwogICAgfQogICAgbXVsdGlwbGVPZih2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtdWx0aXBsZU9mIiwKICAgICAgICB2YWx1ZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBmaW5pdGUobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJmaW5pdGUiLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIHNhZmUobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtaW4iLAogICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICB2YWx1ZTogTnVtYmVyLk1JTl9TQUZFX0lOVEVHRVIsCiAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpCiAgICAgIH0pLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgIHZhbHVlOiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBnZXQgbWluVmFsdWUoKSB7CiAgICAgIGxldCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChtaW4gPT09IG51bGwgfHwgY2gudmFsdWUgPiBtaW4pCiAgICAgICAgICAgIG1pbiA9IGNoLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbWluOwogICAgfQogICAgZ2V0IG1heFZhbHVlKCkgewogICAgICBsZXQgbWF4ID0gbnVsbDsKICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNoLnZhbHVlIDwgbWF4KQogICAgICAgICAgICBtYXggPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG1heDsKICAgIH0KICAgIGdldCBpc0ludCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImludCIgfHwgY2gua2luZCA9PT0gIm11bHRpcGxlT2YiICYmIHV0aWwuaXNJbnRlZ2VyKGNoLnZhbHVlKSk7CiAgICB9CiAgICBnZXQgaXNGaW5pdGUoKSB7CiAgICAgIGxldCBtYXggPSBudWxsLCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gImZpbml0ZSIgfHwgY2gua2luZCA9PT0gImludCIgfHwgY2gua2luZCA9PT0gIm11bHRpcGxlT2YiKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9IGVsc2UgaWYgKGNoLmtpbmQgPT09ICJtaW4iKSB7CiAgICAgICAgICBpZiAobWluID09PSBudWxsIHx8IGNoLnZhbHVlID4gbWluKQogICAgICAgICAgICBtaW4gPSBjaC52YWx1ZTsKICAgICAgICB9IGVsc2UgaWYgKGNoLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNoLnZhbHVlIDwgbWF4KQogICAgICAgICAgICBtYXggPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShtaW4pICYmIE51bWJlci5pc0Zpbml0ZShtYXgpOwogICAgfQogIH0KICBab2ROdW1iZXIuY3JlYXRlID0gKHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2ROdW1iZXIoewogICAgICBjaGVja3M6IFtdLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE51bWJlciwKICAgICAgY29lcmNlOiAocGFyYW1zID09PSBudWxsIHx8IHBhcmFtcyA9PT0gdm9pZCAwID8gdm9pZCAwIDogcGFyYW1zLmNvZXJjZSkgfHwgZmFsc2UsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RCaWdJbnQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICB0aGlzLm1pbiA9IHRoaXMuZ3RlOwogICAgICB0aGlzLm1heCA9IHRoaXMubHRlOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGlmICh0aGlzLl9kZWYuY29lcmNlKSB7CiAgICAgICAgaW5wdXQuZGF0YSA9IEJpZ0ludChpbnB1dC5kYXRhKTsKICAgICAgfQogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLmJpZ2ludCkgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmJpZ2ludCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgyLnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBsZXQgY3R4ID0gdm9pZCAwOwogICAgICBjb25zdCBzdGF0dXMgPSBuZXcgUGFyc2VTdGF0dXMoKTsKICAgICAgZm9yIChjb25zdCBjaGVjayBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoZWNrLmtpbmQgPT09ICJtaW4iKSB7CiAgICAgICAgICBjb25zdCB0b29TbWFsbCA9IGNoZWNrLmluY2x1c2l2ZSA/IGlucHV0LmRhdGEgPCBjaGVjay52YWx1ZSA6IGlucHV0LmRhdGEgPD0gY2hlY2sudmFsdWU7CiAgICAgICAgICBpZiAodG9vU21hbGwpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgICAgdHlwZTogImJpZ2ludCIsCiAgICAgICAgICAgICAgbWluaW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiBjaGVjay5pbmNsdXNpdmUsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAibWF4IikgewogICAgICAgICAgY29uc3QgdG9vQmlnID0gY2hlY2suaW5jbHVzaXZlID8gaW5wdXQuZGF0YSA+IGNoZWNrLnZhbHVlIDogaW5wdXQuZGF0YSA+PSBjaGVjay52YWx1ZTsKICAgICAgICAgIGlmICh0b29CaWcpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fYmlnLAogICAgICAgICAgICAgIHR5cGU6ICJiaWdpbnQiLAogICAgICAgICAgICAgIG1heGltdW06IGNoZWNrLnZhbHVlLAogICAgICAgICAgICAgIGluY2x1c2l2ZTogY2hlY2suaW5jbHVzaXZlLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gIm11bHRpcGxlT2YiKSB7CiAgICAgICAgICBpZiAoaW5wdXQuZGF0YSAlIGNoZWNrLnZhbHVlICE9PSBCaWdJbnQoMCkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5ub3RfbXVsdGlwbGVfb2YsCiAgICAgICAgICAgICAgbXVsdGlwbGVPZjogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoY2hlY2spOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGlucHV0LmRhdGEgfTsKICAgIH0KICAgIGd0ZSh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIHRydWUsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBndCh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIGZhbHNlLCBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkpOwogICAgfQogICAgbHRlKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgdHJ1ZSwgZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpKTsKICAgIH0KICAgIGx0KHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgZmFsc2UsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBzZXRMaW1pdChraW5kLCB2YWx1ZSwgaW5jbHVzaXZlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQmlnSW50KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbCiAgICAgICAgICAuLi50aGlzLl9kZWYuY2hlY2tzLAogICAgICAgICAgewogICAgICAgICAgICBraW5kLAogICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgaW5jbHVzaXZlLAogICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgICAgIH0KICAgICAgICBdCiAgICAgIH0pOwogICAgfQogICAgX2FkZENoZWNrKGNoZWNrKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQmlnSW50KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgY2hlY2tdCiAgICAgIH0pOwogICAgfQogICAgcG9zaXRpdmUobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtaW4iLAogICAgICAgIHZhbHVlOiBCaWdJbnQoMCksCiAgICAgICAgaW5jbHVzaXZlOiBmYWxzZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBuZWdhdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IEJpZ0ludCgwKSwKICAgICAgICBpbmNsdXNpdmU6IGZhbHNlLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIG5vbnBvc2l0aXZlKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAibWF4IiwKICAgICAgICB2YWx1ZTogQmlnSW50KDApLAogICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBub25uZWdhdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IEJpZ0ludCgwKSwKICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpCiAgICAgIH0pOwogICAgfQogICAgbXVsdGlwbGVPZih2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtdWx0aXBsZU9mIiwKICAgICAgICB2YWx1ZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBnZXQgbWluVmFsdWUoKSB7CiAgICAgIGxldCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChtaW4gPT09IG51bGwgfHwgY2gudmFsdWUgPiBtaW4pCiAgICAgICAgICAgIG1pbiA9IGNoLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbWluOwogICAgfQogICAgZ2V0IG1heFZhbHVlKCkgewogICAgICBsZXQgbWF4ID0gbnVsbDsKICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNoLnZhbHVlIDwgbWF4KQogICAgICAgICAgICBtYXggPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG1heDsKICAgIH0KICB9CiAgWm9kQmlnSW50LmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHZhciBfYTsKICAgIHJldHVybiBuZXcgWm9kQmlnSW50KHsKICAgICAgY2hlY2tzOiBbXSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RCaWdJbnQsCiAgICAgIGNvZXJjZTogKF9hID0gcGFyYW1zID09PSBudWxsIHx8IHBhcmFtcyA9PT0gdm9pZCAwID8gdm9pZCAwIDogcGFyYW1zLmNvZXJjZSkgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogZmFsc2UsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RCb29sZWFuIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgaWYgKHRoaXMuX2RlZi5jb2VyY2UpIHsKICAgICAgICBpbnB1dC5kYXRhID0gQm9vbGVhbihpbnB1dC5kYXRhKTsKICAgICAgfQogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLmJvb2xlYW4pIHsKICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUuYm9vbGVhbiwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTsKICAgIH0KICB9CiAgWm9kQm9vbGVhbi5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZEJvb2xlYW4oewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEJvb2xlYW4sCiAgICAgIGNvZXJjZTogKHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5jb2VyY2UpIHx8IGZhbHNlLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kRGF0ZSBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGlmICh0aGlzLl9kZWYuY29lcmNlKSB7CiAgICAgICAgaW5wdXQuZGF0YSA9IG5ldyBEYXRlKGlucHV0LmRhdGEpOwogICAgICB9CiAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTsKICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuZGF0ZSkgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmRhdGUsCiAgICAgICAgICByZWNlaXZlZDogY3R4Mi5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgaWYgKGlzTmFOKGlucHV0LmRhdGEuZ2V0VGltZSgpKSkgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfZGF0ZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IHN0YXR1cyA9IG5ldyBQYXJzZVN0YXR1cygpOwogICAgICBsZXQgY3R4ID0gdm9pZCAwOwogICAgICBmb3IgKGNvbnN0IGNoZWNrIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2hlY2sua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChpbnB1dC5kYXRhLmdldFRpbWUoKSA8IGNoZWNrLnZhbHVlKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtaW5pbXVtOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICB0eXBlOiAiZGF0ZSIKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gIm1heCIpIHsKICAgICAgICAgIGlmIChpbnB1dC5kYXRhLmdldFRpbWUoKSA+IGNoZWNrLnZhbHVlKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX2JpZywKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLAogICAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgICAgICBleGFjdDogZmFsc2UsCiAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogImRhdGUiCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgdXRpbC5hc3NlcnROZXZlcihjaGVjayk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgc3RhdHVzOiBzdGF0dXMudmFsdWUsCiAgICAgICAgdmFsdWU6IG5ldyBEYXRlKGlucHV0LmRhdGEuZ2V0VGltZSgpKQogICAgICB9OwogICAgfQogICAgX2FkZENoZWNrKGNoZWNrKSB7CiAgICAgIHJldHVybiBuZXcgWm9kRGF0ZSh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIGNoZWNrczogWy4uLnRoaXMuX2RlZi5jaGVja3MsIGNoZWNrXQogICAgICB9KTsKICAgIH0KICAgIG1pbihtaW5EYXRlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IG1pbkRhdGUuZ2V0VGltZSgpLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIG1heChtYXhEYXRlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IG1heERhdGUuZ2V0VGltZSgpLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGdldCBtaW5EYXRlKCkgewogICAgICBsZXQgbWluID0gbnVsbDsKICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoLmtpbmQgPT09ICJtaW4iKSB7CiAgICAgICAgICBpZiAobWluID09PSBudWxsIHx8IGNoLnZhbHVlID4gbWluKQogICAgICAgICAgICBtaW4gPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG1pbiAhPSBudWxsID8gbmV3IERhdGUobWluKSA6IG51bGw7CiAgICB9CiAgICBnZXQgbWF4RGF0ZSgpIHsKICAgICAgbGV0IG1heCA9IG51bGw7CiAgICAgIGZvciAoY29uc3QgY2ggb2YgdGhpcy5fZGVmLmNoZWNrcykgewogICAgICAgIGlmIChjaC5raW5kID09PSAibWF4IikgewogICAgICAgICAgaWYgKG1heCA9PT0gbnVsbCB8fCBjaC52YWx1ZSA8IG1heCkKICAgICAgICAgICAgbWF4ID0gY2gudmFsdWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBtYXggIT0gbnVsbCA/IG5ldyBEYXRlKG1heCkgOiBudWxsOwogICAgfQogIH0KICBab2REYXRlLmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kRGF0ZSh7CiAgICAgIGNoZWNrczogW10sCiAgICAgIGNvZXJjZTogKHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5jb2VyY2UpIHx8IGZhbHNlLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZERhdGUsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RTeW1ib2wgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLnN5bWJvbCkgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5zeW1ib2wsCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7CiAgICB9CiAgfQogIFpvZFN5bWJvbC5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZFN5bWJvbCh7CiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kU3ltYm9sLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kVW5kZWZpbmVkIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS51bmRlZmluZWQpIHsKICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgcmV0dXJuIE9LKGlucHV0LmRhdGEpOwogICAgfQogIH0KICBab2RVbmRlZmluZWQuY3JlYXRlID0gKHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RVbmRlZmluZWQoewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZFVuZGVmaW5lZCwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE51bGwgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm51bGwpIHsKICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUubnVsbCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTsKICAgIH0KICB9CiAgWm9kTnVsbC5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE51bGwoewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE51bGwsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RBbnkgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICB0aGlzLl9hbnkgPSB0cnVlOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTsKICAgIH0KICB9CiAgWm9kQW55LmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kQW55KHsKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RBbnksCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RVbmtub3duIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgdGhpcy5fdW5rbm93biA9IHRydWU7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgcmV0dXJuIE9LKGlucHV0LmRhdGEpOwogICAgfQogIH0KICBab2RVbmtub3duLmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kVW5rbm93bih7CiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kVW5rbm93biwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE5ldmVyIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm5ldmVyLAogICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICB9KTsKICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICB9CiAgfQogIFpvZE5ldmVyLmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kTmV2ZXIoewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE5ldmVyLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kVm9pZCBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTsKICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkKSB7CiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLnZvaWQsCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7CiAgICB9CiAgfQogIFpvZFZvaWQuY3JlYXRlID0gKHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RWb2lkKHsKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RWb2lkLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kQXJyYXkgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCwgc3RhdHVzIH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBkZWYgPSB0aGlzLl9kZWY7CiAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5hcnJheSkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmFycmF5LAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgaWYgKGRlZi5leGFjdExlbmd0aCAhPT0gbnVsbCkgewogICAgICAgIGNvbnN0IHRvb0JpZyA9IGN0eC5kYXRhLmxlbmd0aCA+IGRlZi5leGFjdExlbmd0aC52YWx1ZTsKICAgICAgICBjb25zdCB0b29TbWFsbCA9IGN0eC5kYXRhLmxlbmd0aCA8IGRlZi5leGFjdExlbmd0aC52YWx1ZTsKICAgICAgICBpZiAodG9vQmlnIHx8IHRvb1NtYWxsKSB7CiAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgY29kZTogdG9vQmlnID8gWm9kSXNzdWVDb2RlLnRvb19iaWcgOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgICBtaW5pbXVtOiB0b29TbWFsbCA/IGRlZi5leGFjdExlbmd0aC52YWx1ZSA6IHZvaWQgMCwKICAgICAgICAgICAgbWF4aW11bTogdG9vQmlnID8gZGVmLmV4YWN0TGVuZ3RoLnZhbHVlIDogdm9pZCAwLAogICAgICAgICAgICB0eXBlOiAiYXJyYXkiLAogICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgICAgIGV4YWN0OiB0cnVlLAogICAgICAgICAgICBtZXNzYWdlOiBkZWYuZXhhY3RMZW5ndGgubWVzc2FnZQogICAgICAgICAgfSk7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGRlZi5taW5MZW5ndGggIT09IG51bGwpIHsKICAgICAgICBpZiAoY3R4LmRhdGEubGVuZ3RoIDwgZGVmLm1pbkxlbmd0aC52YWx1ZSkgewogICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgIG1pbmltdW06IGRlZi5taW5MZW5ndGgudmFsdWUsCiAgICAgICAgICAgIHR5cGU6ICJhcnJheSIsCiAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLAogICAgICAgICAgICBtZXNzYWdlOiBkZWYubWluTGVuZ3RoLm1lc3NhZ2UKICAgICAgICAgIH0pOwogICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChkZWYubWF4TGVuZ3RoICE9PSBudWxsKSB7CiAgICAgICAgaWYgKGN0eC5kYXRhLmxlbmd0aCA+IGRlZi5tYXhMZW5ndGgudmFsdWUpIHsKICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX2JpZywKICAgICAgICAgICAgbWF4aW11bTogZGVmLm1heExlbmd0aC52YWx1ZSwKICAgICAgICAgICAgdHlwZTogImFycmF5IiwKICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICBleGFjdDogZmFsc2UsCiAgICAgICAgICAgIG1lc3NhZ2U6IGRlZi5tYXhMZW5ndGgubWVzc2FnZQogICAgICAgICAgfSk7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoWy4uLmN0eC5kYXRhXS5tYXAoKGl0ZW0sIGkyKSA9PiB7CiAgICAgICAgICByZXR1cm4gZGVmLnR5cGUuX3BhcnNlQXN5bmMobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGl0ZW0sIGN0eC5wYXRoLCBpMikpOwogICAgICAgIH0pKS50aGVuKChyZXN1bHQyKSA9PiB7CiAgICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VBcnJheShzdGF0dXMsIHJlc3VsdDIpOwogICAgICAgIH0pOwogICAgICB9CiAgICAgIGNvbnN0IHJlc3VsdCA9IFsuLi5jdHguZGF0YV0ubWFwKChpdGVtLCBpMikgPT4gewogICAgICAgIHJldHVybiBkZWYudHlwZS5fcGFyc2VTeW5jKG5ldyBQYXJzZUlucHV0TGF6eVBhdGgoY3R4LCBpdGVtLCBjdHgucGF0aCwgaTIpKTsKICAgICAgfSk7CiAgICAgIHJldHVybiBQYXJzZVN0YXR1cy5tZXJnZUFycmF5KHN0YXR1cywgcmVzdWx0KTsKICAgIH0KICAgIGdldCBlbGVtZW50KCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnR5cGU7CiAgICB9CiAgICBtaW4obWluTGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBtaW5MZW5ndGg6IHsgdmFsdWU6IG1pbkxlbmd0aCwgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpIH0KICAgICAgfSk7CiAgICB9CiAgICBtYXgobWF4TGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBtYXhMZW5ndGg6IHsgdmFsdWU6IG1heExlbmd0aCwgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpIH0KICAgICAgfSk7CiAgICB9CiAgICBsZW5ndGgobGVuLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBleGFjdExlbmd0aDogeyB2YWx1ZTogbGVuLCBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkgfQogICAgICB9KTsKICAgIH0KICAgIG5vbmVtcHR5KG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMubWluKDEsIG1lc3NhZ2UpOwogICAgfQogIH0KICBab2RBcnJheS5jcmVhdGUgPSAoc2NoZW1hLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICB0eXBlOiBzY2hlbWEsCiAgICAgIG1pbkxlbmd0aDogbnVsbCwKICAgICAgbWF4TGVuZ3RoOiBudWxsLAogICAgICBleGFjdExlbmd0aDogbnVsbCwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RBcnJheSwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGZ1bmN0aW9uIGRlZXBQYXJ0aWFsaWZ5KHNjaGVtYSkgewogICAgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZE9iamVjdCkgewogICAgICBjb25zdCBuZXdTaGFwZSA9IHt9OwogICAgICBmb3IgKGNvbnN0IGtleSBpbiBzY2hlbWEuc2hhcGUpIHsKICAgICAgICBjb25zdCBmaWVsZFNjaGVtYSA9IHNjaGVtYS5zaGFwZVtrZXldOwogICAgICAgIG5ld1NoYXBlW2tleV0gPSBab2RPcHRpb25hbC5jcmVhdGUoZGVlcFBhcnRpYWxpZnkoZmllbGRTY2hlbWEpKTsKICAgICAgfQogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4uc2NoZW1hLl9kZWYsCiAgICAgICAgc2hhcGU6ICgpID0+IG5ld1NoYXBlCiAgICAgIH0pOwogICAgfSBlbHNlIGlmIChzY2hlbWEgaW5zdGFuY2VvZiBab2RBcnJheSkgewogICAgICByZXR1cm4gbmV3IFpvZEFycmF5KHsKICAgICAgICAuLi5zY2hlbWEuX2RlZiwKICAgICAgICB0eXBlOiBkZWVwUGFydGlhbGlmeShzY2hlbWEuZWxlbWVudCkKICAgICAgfSk7CiAgICB9IGVsc2UgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZE9wdGlvbmFsKSB7CiAgICAgIHJldHVybiBab2RPcHRpb25hbC5jcmVhdGUoZGVlcFBhcnRpYWxpZnkoc2NoZW1hLnVud3JhcCgpKSk7CiAgICB9IGVsc2UgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZE51bGxhYmxlKSB7CiAgICAgIHJldHVybiBab2ROdWxsYWJsZS5jcmVhdGUoZGVlcFBhcnRpYWxpZnkoc2NoZW1hLnVud3JhcCgpKSk7CiAgICB9IGVsc2UgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZFR1cGxlKSB7CiAgICAgIHJldHVybiBab2RUdXBsZS5jcmVhdGUoc2NoZW1hLml0ZW1zLm1hcCgoaXRlbSkgPT4gZGVlcFBhcnRpYWxpZnkoaXRlbSkpKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBzY2hlbWE7CiAgICB9CiAgfQogIGNsYXNzIFpvZE9iamVjdCBleHRlbmRzIFpvZFR5cGUgewogICAgY29uc3RydWN0b3IoKSB7CiAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7CiAgICAgIHRoaXMuX2NhY2hlZCA9IG51bGw7CiAgICAgIHRoaXMubm9uc3RyaWN0ID0gdGhpcy5wYXNzdGhyb3VnaDsKICAgICAgdGhpcy5hdWdtZW50ID0gdGhpcy5leHRlbmQ7CiAgICB9CiAgICBfZ2V0Q2FjaGVkKCkgewogICAgICBpZiAodGhpcy5fY2FjaGVkICE9PSBudWxsKQogICAgICAgIHJldHVybiB0aGlzLl9jYWNoZWQ7CiAgICAgIGNvbnN0IHNoYXBlID0gdGhpcy5fZGVmLnNoYXBlKCk7CiAgICAgIGNvbnN0IGtleXMgPSB1dGlsLm9iamVjdEtleXMoc2hhcGUpOwogICAgICByZXR1cm4gdGhpcy5fY2FjaGVkID0geyBzaGFwZSwga2V5cyB9OwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTsKICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUub2JqZWN0KSB7CiAgICAgICAgY29uc3QgY3R4MiA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgyLCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUub2JqZWN0LAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eDIucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IHsgc3RhdHVzLCBjdHggfSA9IHRoaXMuX3Byb2Nlc3NJbnB1dFBhcmFtcyhpbnB1dCk7CiAgICAgIGNvbnN0IHsgc2hhcGUsIGtleXM6IHNoYXBlS2V5cyB9ID0gdGhpcy5fZ2V0Q2FjaGVkKCk7CiAgICAgIGNvbnN0IGV4dHJhS2V5cyA9IFtdOwogICAgICBpZiAoISh0aGlzLl9kZWYuY2F0Y2hhbGwgaW5zdGFuY2VvZiBab2ROZXZlciAmJiB0aGlzLl9kZWYudW5rbm93bktleXMgPT09ICJzdHJpcCIpKSB7CiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gY3R4LmRhdGEpIHsKICAgICAgICAgIGlmICghc2hhcGVLZXlzLmluY2x1ZGVzKGtleSkpIHsKICAgICAgICAgICAgZXh0cmFLZXlzLnB1c2goa2V5KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgcGFpcnMgPSBbXTsKICAgICAgZm9yIChjb25zdCBrZXkgb2Ygc2hhcGVLZXlzKSB7CiAgICAgICAgY29uc3Qga2V5VmFsaWRhdG9yID0gc2hhcGVba2V5XTsKICAgICAgICBjb25zdCB2YWx1ZSA9IGN0eC5kYXRhW2tleV07CiAgICAgICAgcGFpcnMucHVzaCh7CiAgICAgICAgICBrZXk6IHsgc3RhdHVzOiAidmFsaWQiLCB2YWx1ZToga2V5IH0sCiAgICAgICAgICB2YWx1ZToga2V5VmFsaWRhdG9yLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwgdmFsdWUsIGN0eC5wYXRoLCBrZXkpKSwKICAgICAgICAgIGFsd2F5c1NldDoga2V5IGluIGN0eC5kYXRhCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuX2RlZi5jYXRjaGFsbCBpbnN0YW5jZW9mIFpvZE5ldmVyKSB7CiAgICAgICAgY29uc3QgdW5rbm93bktleXMgPSB0aGlzLl9kZWYudW5rbm93bktleXM7CiAgICAgICAgaWYgKHVua25vd25LZXlzID09PSAicGFzc3Rocm91Z2giKSB7CiAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBleHRyYUtleXMpIHsKICAgICAgICAgICAgcGFpcnMucHVzaCh7CiAgICAgICAgICAgICAga2V5OiB7IHN0YXR1czogInZhbGlkIiwgdmFsdWU6IGtleSB9LAogICAgICAgICAgICAgIHZhbHVlOiB7IHN0YXR1czogInZhbGlkIiwgdmFsdWU6IGN0eC5kYXRhW2tleV0gfQogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKHVua25vd25LZXlzID09PSAic3RyaWN0IikgewogICAgICAgICAgaWYgKGV4dHJhS2V5cy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS51bnJlY29nbml6ZWRfa2V5cywKICAgICAgICAgICAgICBrZXlzOiBleHRyYUtleXMKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAodW5rbm93bktleXMgPT09ICJzdHJpcCIpIDsKICAgICAgICBlbHNlIHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW50ZXJuYWwgWm9kT2JqZWN0IGVycm9yOiBpbnZhbGlkIHVua25vd25LZXlzIHZhbHVlLmApOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBjYXRjaGFsbCA9IHRoaXMuX2RlZi5jYXRjaGFsbDsKICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBleHRyYUtleXMpIHsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gY3R4LmRhdGFba2V5XTsKICAgICAgICAgIHBhaXJzLnB1c2goewogICAgICAgICAgICBrZXk6IHsgc3RhdHVzOiAidmFsaWQiLCB2YWx1ZToga2V5IH0sCiAgICAgICAgICAgIHZhbHVlOiBjYXRjaGFsbC5fcGFyc2UoCiAgICAgICAgICAgICAgbmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIHZhbHVlLCBjdHgucGF0aCwga2V5KQogICAgICAgICAgICAgIC8vLCBjdHguY2hpbGQoa2V5KSwgdmFsdWUsIGdldFBhcnNlZFR5cGUodmFsdWUpCiAgICAgICAgICAgICksCiAgICAgICAgICAgIGFsd2F5c1NldDoga2V5IGluIGN0eC5kYXRhCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihhc3luYyAoKSA9PiB7CiAgICAgICAgICBjb25zdCBzeW5jUGFpcnMgPSBbXTsKICAgICAgICAgIGZvciAoY29uc3QgcGFpciBvZiBwYWlycykgewogICAgICAgICAgICBjb25zdCBrZXkgPSBhd2FpdCBwYWlyLmtleTsKICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCBwYWlyLnZhbHVlOwogICAgICAgICAgICBzeW5jUGFpcnMucHVzaCh7CiAgICAgICAgICAgICAga2V5LAogICAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICAgIGFsd2F5c1NldDogcGFpci5hbHdheXNTZXQKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gc3luY1BhaXJzOwogICAgICAgIH0pLnRoZW4oKHN5bmNQYWlycykgPT4gewogICAgICAgICAgcmV0dXJuIFBhcnNlU3RhdHVzLm1lcmdlT2JqZWN0U3luYyhzdGF0dXMsIHN5bmNQYWlycyk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIFBhcnNlU3RhdHVzLm1lcmdlT2JqZWN0U3luYyhzdGF0dXMsIHBhaXJzKTsKICAgICAgfQogICAgfQogICAgZ2V0IHNoYXBlKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnNoYXBlKCk7CiAgICB9CiAgICBzdHJpY3QobWVzc2FnZSkgewogICAgICBlcnJvclV0aWwuZXJyVG9PYmo7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgdW5rbm93bktleXM6ICJzdHJpY3QiLAogICAgICAgIC4uLm1lc3NhZ2UgIT09IHZvaWQgMCA/IHsKICAgICAgICAgIGVycm9yTWFwOiAoaXNzdWUsIGN0eCkgPT4gewogICAgICAgICAgICB2YXIgX2EsIF9iLCBfYywgX2Q7CiAgICAgICAgICAgIGNvbnN0IGRlZmF1bHRFcnJvciA9IChfYyA9IChfYiA9IChfYSA9IHRoaXMuX2RlZikuZXJyb3JNYXApID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5jYWxsKF9hLCBpc3N1ZSwgY3R4KS5tZXNzYWdlKSAhPT0gbnVsbCAmJiBfYyAhPT0gdm9pZCAwID8gX2MgOiBjdHguZGVmYXVsdEVycm9yOwogICAgICAgICAgICBpZiAoaXNzdWUuY29kZSA9PT0gInVucmVjb2duaXplZF9rZXlzIikKICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgbWVzc2FnZTogKF9kID0gZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpLm1lc3NhZ2UpICE9PSBudWxsICYmIF9kICE9PSB2b2lkIDAgPyBfZCA6IGRlZmF1bHRFcnJvcgogICAgICAgICAgICAgIH07CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgbWVzc2FnZTogZGVmYXVsdEVycm9yCiAgICAgICAgICAgIH07CiAgICAgICAgICB9CiAgICAgICAgfSA6IHt9CiAgICAgIH0pOwogICAgfQogICAgc3RyaXAoKSB7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgdW5rbm93bktleXM6ICJzdHJpcCIKICAgICAgfSk7CiAgICB9CiAgICBwYXNzdGhyb3VnaCgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICB1bmtub3duS2V5czogInBhc3N0aHJvdWdoIgogICAgICB9KTsKICAgIH0KICAgIC8vIGNvbnN0IEF1Z21lbnRGYWN0b3J5ID0KICAgIC8vICAgPERlZiBleHRlbmRzIFpvZE9iamVjdERlZj4oZGVmOiBEZWYpID0+CiAgICAvLyAgIDxBdWdtZW50YXRpb24gZXh0ZW5kcyBab2RSYXdTaGFwZT4oCiAgICAvLyAgICAgYXVnbWVudGF0aW9uOiBBdWdtZW50YXRpb24KICAgIC8vICAgKTogWm9kT2JqZWN0PAogICAgLy8gICAgIGV4dGVuZFNoYXBlPFJldHVyblR5cGU8RGVmWyJzaGFwZSJdPiwgQXVnbWVudGF0aW9uPiwKICAgIC8vICAgICBEZWZbInVua25vd25LZXlzIl0sCiAgICAvLyAgICAgRGVmWyJjYXRjaGFsbCJdCiAgICAvLyAgID4gPT4gewogICAgLy8gICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgIC8vICAgICAgIC4uLmRlZiwKICAgIC8vICAgICAgIHNoYXBlOiAoKSA9PiAoewogICAgLy8gICAgICAgICAuLi5kZWYuc2hhcGUoKSwKICAgIC8vICAgICAgICAgLi4uYXVnbWVudGF0aW9uLAogICAgLy8gICAgICAgfSksCiAgICAvLyAgICAgfSkgYXMgYW55OwogICAgLy8gICB9OwogICAgZXh0ZW5kKGF1Z21lbnRhdGlvbikgewogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHNoYXBlOiAoKSA9PiAoewogICAgICAgICAgLi4udGhpcy5fZGVmLnNoYXBlKCksCiAgICAgICAgICAuLi5hdWdtZW50YXRpb24KICAgICAgICB9KQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICogUHJpb3IgdG8gem9kQDEuMC4xMiB0aGVyZSB3YXMgYSBidWcgaW4gdGhlCiAgICAgKiBpbmZlcnJlZCB0eXBlIG9mIG1lcmdlZCBvYmplY3RzLiBQbGVhc2UKICAgICAqIHVwZ3JhZGUgaWYgeW91IGFyZSBleHBlcmllbmNpbmcgaXNzdWVzLgogICAgICovCiAgICBtZXJnZShtZXJnaW5nKSB7CiAgICAgIGNvbnN0IG1lcmdlZCA9IG5ldyBab2RPYmplY3QoewogICAgICAgIHVua25vd25LZXlzOiBtZXJnaW5nLl9kZWYudW5rbm93bktleXMsCiAgICAgICAgY2F0Y2hhbGw6IG1lcmdpbmcuX2RlZi5jYXRjaGFsbCwKICAgICAgICBzaGFwZTogKCkgPT4gKHsKICAgICAgICAgIC4uLnRoaXMuX2RlZi5zaGFwZSgpLAogICAgICAgICAgLi4ubWVyZ2luZy5fZGVmLnNoYXBlKCkKICAgICAgICB9KSwKICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE9iamVjdAogICAgICB9KTsKICAgICAgcmV0dXJuIG1lcmdlZDsKICAgIH0KICAgIC8vIG1lcmdlPAogICAgLy8gICBJbmNvbWluZyBleHRlbmRzIEFueVpvZE9iamVjdCwKICAgIC8vICAgQXVnbWVudGF0aW9uIGV4dGVuZHMgSW5jb21pbmdbInNoYXBlIl0sCiAgICAvLyAgIE5ld091dHB1dCBleHRlbmRzIHsKICAgIC8vICAgICBbayBpbiBrZXlvZiBBdWdtZW50YXRpb24gfCBrZXlvZiBPdXRwdXRdOiBrIGV4dGVuZHMga2V5b2YgQXVnbWVudGF0aW9uCiAgICAvLyAgICAgICA/IEF1Z21lbnRhdGlvbltrXVsiX291dHB1dCJdCiAgICAvLyAgICAgICA6IGsgZXh0ZW5kcyBrZXlvZiBPdXRwdXQKICAgIC8vICAgICAgID8gT3V0cHV0W2tdCiAgICAvLyAgICAgICA6IG5ldmVyOwogICAgLy8gICB9LAogICAgLy8gICBOZXdJbnB1dCBleHRlbmRzIHsKICAgIC8vICAgICBbayBpbiBrZXlvZiBBdWdtZW50YXRpb24gfCBrZXlvZiBJbnB1dF06IGsgZXh0ZW5kcyBrZXlvZiBBdWdtZW50YXRpb24KICAgIC8vICAgICAgID8gQXVnbWVudGF0aW9uW2tdWyJfaW5wdXQiXQogICAgLy8gICAgICAgOiBrIGV4dGVuZHMga2V5b2YgSW5wdXQKICAgIC8vICAgICAgID8gSW5wdXRba10KICAgIC8vICAgICAgIDogbmV2ZXI7CiAgICAvLyAgIH0KICAgIC8vID4oCiAgICAvLyAgIG1lcmdpbmc6IEluY29taW5nCiAgICAvLyApOiBab2RPYmplY3Q8CiAgICAvLyAgIGV4dGVuZFNoYXBlPFQsIFJldHVyblR5cGU8SW5jb21pbmdbIl9kZWYiXVsic2hhcGUiXT4+LAogICAgLy8gICBJbmNvbWluZ1siX2RlZiJdWyJ1bmtub3duS2V5cyJdLAogICAgLy8gICBJbmNvbWluZ1siX2RlZiJdWyJjYXRjaGFsbCJdLAogICAgLy8gICBOZXdPdXRwdXQsCiAgICAvLyAgIE5ld0lucHV0CiAgICAvLyA+IHsKICAgIC8vICAgY29uc3QgbWVyZ2VkOiBhbnkgPSBuZXcgWm9kT2JqZWN0KHsKICAgIC8vICAgICB1bmtub3duS2V5czogbWVyZ2luZy5fZGVmLnVua25vd25LZXlzLAogICAgLy8gICAgIGNhdGNoYWxsOiBtZXJnaW5nLl9kZWYuY2F0Y2hhbGwsCiAgICAvLyAgICAgc2hhcGU6ICgpID0+CiAgICAvLyAgICAgICBvYmplY3RVdGlsLm1lcmdlU2hhcGVzKHRoaXMuX2RlZi5zaGFwZSgpLCBtZXJnaW5nLl9kZWYuc2hhcGUoKSksCiAgICAvLyAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPYmplY3QsCiAgICAvLyAgIH0pIGFzIGFueTsKICAgIC8vICAgcmV0dXJuIG1lcmdlZDsKICAgIC8vIH0KICAgIHNldEtleShrZXksIHNjaGVtYSkgewogICAgICByZXR1cm4gdGhpcy5hdWdtZW50KHsgW2tleV06IHNjaGVtYSB9KTsKICAgIH0KICAgIC8vIG1lcmdlPEluY29taW5nIGV4dGVuZHMgQW55Wm9kT2JqZWN0PigKICAgIC8vICAgbWVyZ2luZzogSW5jb21pbmcKICAgIC8vICk6IC8vWm9kT2JqZWN0PFQgJiBJbmNvbWluZ1siX3NoYXBlIl0sIFVua25vd25LZXlzLCBDYXRjaGFsbD4gPSAobWVyZ2luZykgPT4gewogICAgLy8gWm9kT2JqZWN0PAogICAgLy8gICBleHRlbmRTaGFwZTxULCBSZXR1cm5UeXBlPEluY29taW5nWyJfZGVmIl1bInNoYXBlIl0+PiwKICAgIC8vICAgSW5jb21pbmdbIl9kZWYiXVsidW5rbm93bktleXMiXSwKICAgIC8vICAgSW5jb21pbmdbIl9kZWYiXVsiY2F0Y2hhbGwiXQogICAgLy8gPiB7CiAgICAvLyAgIC8vIGNvbnN0IG1lcmdlZFNoYXBlID0gb2JqZWN0VXRpbC5tZXJnZVNoYXBlcygKICAgIC8vICAgLy8gICB0aGlzLl9kZWYuc2hhcGUoKSwKICAgIC8vICAgLy8gICBtZXJnaW5nLl9kZWYuc2hhcGUoKQogICAgLy8gICAvLyApOwogICAgLy8gICBjb25zdCBtZXJnZWQ6IGFueSA9IG5ldyBab2RPYmplY3QoewogICAgLy8gICAgIHVua25vd25LZXlzOiBtZXJnaW5nLl9kZWYudW5rbm93bktleXMsCiAgICAvLyAgICAgY2F0Y2hhbGw6IG1lcmdpbmcuX2RlZi5jYXRjaGFsbCwKICAgIC8vICAgICBzaGFwZTogKCkgPT4KICAgIC8vICAgICAgIG9iamVjdFV0aWwubWVyZ2VTaGFwZXModGhpcy5fZGVmLnNoYXBlKCksIG1lcmdpbmcuX2RlZi5zaGFwZSgpKSwKICAgIC8vICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE9iamVjdCwKICAgIC8vICAgfSkgYXMgYW55OwogICAgLy8gICByZXR1cm4gbWVyZ2VkOwogICAgLy8gfQogICAgY2F0Y2hhbGwoaW5kZXgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBjYXRjaGFsbDogaW5kZXgKICAgICAgfSk7CiAgICB9CiAgICBwaWNrKG1hc2spIHsKICAgICAgY29uc3Qgc2hhcGUgPSB7fTsKICAgICAgdXRpbC5vYmplY3RLZXlzKG1hc2spLmZvckVhY2goKGtleSkgPT4gewogICAgICAgIGlmIChtYXNrW2tleV0gJiYgdGhpcy5zaGFwZVtrZXldKSB7CiAgICAgICAgICBzaGFwZVtrZXldID0gdGhpcy5zaGFwZVtrZXldOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgc2hhcGU6ICgpID0+IHNoYXBlCiAgICAgIH0pOwogICAgfQogICAgb21pdChtYXNrKSB7CiAgICAgIGNvbnN0IHNoYXBlID0ge307CiAgICAgIHV0aWwub2JqZWN0S2V5cyh0aGlzLnNoYXBlKS5mb3JFYWNoKChrZXkpID0+IHsKICAgICAgICBpZiAoIW1hc2tba2V5XSkgewogICAgICAgICAgc2hhcGVba2V5XSA9IHRoaXMuc2hhcGVba2V5XTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHNoYXBlOiAoKSA9PiBzaGFwZQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICogQGRlcHJlY2F0ZWQKICAgICAqLwogICAgZGVlcFBhcnRpYWwoKSB7CiAgICAgIHJldHVybiBkZWVwUGFydGlhbGlmeSh0aGlzKTsKICAgIH0KICAgIHBhcnRpYWwobWFzaykgewogICAgICBjb25zdCBuZXdTaGFwZSA9IHt9OwogICAgICB1dGlsLm9iamVjdEtleXModGhpcy5zaGFwZSkuZm9yRWFjaCgoa2V5KSA9PiB7CiAgICAgICAgY29uc3QgZmllbGRTY2hlbWEgPSB0aGlzLnNoYXBlW2tleV07CiAgICAgICAgaWYgKG1hc2sgJiYgIW1hc2tba2V5XSkgewogICAgICAgICAgbmV3U2hhcGVba2V5XSA9IGZpZWxkU2NoZW1hOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBuZXdTaGFwZVtrZXldID0gZmllbGRTY2hlbWEub3B0aW9uYWwoKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHNoYXBlOiAoKSA9PiBuZXdTaGFwZQogICAgICB9KTsKICAgIH0KICAgIHJlcXVpcmVkKG1hc2spIHsKICAgICAgY29uc3QgbmV3U2hhcGUgPSB7fTsKICAgICAgdXRpbC5vYmplY3RLZXlzKHRoaXMuc2hhcGUpLmZvckVhY2goKGtleSkgPT4gewogICAgICAgIGlmIChtYXNrICYmICFtYXNrW2tleV0pIHsKICAgICAgICAgIG5ld1NoYXBlW2tleV0gPSB0aGlzLnNoYXBlW2tleV07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvbnN0IGZpZWxkU2NoZW1hID0gdGhpcy5zaGFwZVtrZXldOwogICAgICAgICAgbGV0IG5ld0ZpZWxkID0gZmllbGRTY2hlbWE7CiAgICAgICAgICB3aGlsZSAobmV3RmllbGQgaW5zdGFuY2VvZiBab2RPcHRpb25hbCkgewogICAgICAgICAgICBuZXdGaWVsZCA9IG5ld0ZpZWxkLl9kZWYuaW5uZXJUeXBlOwogICAgICAgICAgfQogICAgICAgICAgbmV3U2hhcGVba2V5XSA9IG5ld0ZpZWxkOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgc2hhcGU6ICgpID0+IG5ld1NoYXBlCiAgICAgIH0pOwogICAgfQogICAga2V5b2YoKSB7CiAgICAgIHJldHVybiBjcmVhdGVab2RFbnVtKHV0aWwub2JqZWN0S2V5cyh0aGlzLnNoYXBlKSk7CiAgICB9CiAgfQogIFpvZE9iamVjdC5jcmVhdGUgPSAoc2hhcGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICBzaGFwZTogKCkgPT4gc2hhcGUsCiAgICAgIHVua25vd25LZXlzOiAic3RyaXAiLAogICAgICBjYXRjaGFsbDogWm9kTmV2ZXIuY3JlYXRlKCksCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kT2JqZWN0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgWm9kT2JqZWN0LnN0cmljdENyZWF0ZSA9IChzaGFwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgIHNoYXBlOiAoKSA9PiBzaGFwZSwKICAgICAgdW5rbm93bktleXM6ICJzdHJpY3QiLAogICAgICBjYXRjaGFsbDogWm9kTmV2ZXIuY3JlYXRlKCksCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kT2JqZWN0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgWm9kT2JqZWN0LmxhenljcmVhdGUgPSAoc2hhcGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICBzaGFwZSwKICAgICAgdW5rbm93bktleXM6ICJzdHJpcCIsCiAgICAgIGNhdGNoYWxsOiBab2ROZXZlci5jcmVhdGUoKSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPYmplY3QsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RVbmlvbiBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5fZGVmLm9wdGlvbnM7CiAgICAgIGZ1bmN0aW9uIGhhbmRsZVJlc3VsdHMocmVzdWx0cykgewogICAgICAgIGZvciAoY29uc3QgcmVzdWx0IG9mIHJlc3VsdHMpIHsKICAgICAgICAgIGlmIChyZXN1bHQucmVzdWx0LnN0YXR1cyA9PT0gInZhbGlkIikgewogICAgICAgICAgICByZXR1cm4gcmVzdWx0LnJlc3VsdDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZm9yIChjb25zdCByZXN1bHQgb2YgcmVzdWx0cykgewogICAgICAgICAgaWYgKHJlc3VsdC5yZXN1bHQuc3RhdHVzID09PSAiZGlydHkiKSB7CiAgICAgICAgICAgIGN0eC5jb21tb24uaXNzdWVzLnB1c2goLi4ucmVzdWx0LmN0eC5jb21tb24uaXNzdWVzKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5yZXN1bHQ7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IHVuaW9uRXJyb3JzID0gcmVzdWx0cy5tYXAoKHJlc3VsdCkgPT4gbmV3IFpvZEVycm9yKHJlc3VsdC5jdHguY29tbW9uLmlzc3VlcykpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdW5pb24sCiAgICAgICAgICB1bmlvbkVycm9ycwogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKG9wdGlvbnMubWFwKGFzeW5jIChvcHRpb24pID0+IHsKICAgICAgICAgIGNvbnN0IGNoaWxkQ3R4ID0gewogICAgICAgICAgICAuLi5jdHgsCiAgICAgICAgICAgIGNvbW1vbjogewogICAgICAgICAgICAgIC4uLmN0eC5jb21tb24sCiAgICAgICAgICAgICAgaXNzdWVzOiBbXQogICAgICAgICAgICB9LAogICAgICAgICAgICBwYXJlbnQ6IG51bGwKICAgICAgICAgIH07CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICByZXN1bHQ6IGF3YWl0IG9wdGlvbi5fcGFyc2VBc3luYyh7CiAgICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgICAgICAgcGFyZW50OiBjaGlsZEN0eAogICAgICAgICAgICB9KSwKICAgICAgICAgICAgY3R4OiBjaGlsZEN0eAogICAgICAgICAgfTsKICAgICAgICB9KSkudGhlbihoYW5kbGVSZXN1bHRzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBsZXQgZGlydHkgPSB2b2lkIDA7CiAgICAgICAgY29uc3QgaXNzdWVzID0gW107CiAgICAgICAgZm9yIChjb25zdCBvcHRpb24gb2Ygb3B0aW9ucykgewogICAgICAgICAgY29uc3QgY2hpbGRDdHggPSB7CiAgICAgICAgICAgIC4uLmN0eCwKICAgICAgICAgICAgY29tbW9uOiB7CiAgICAgICAgICAgICAgLi4uY3R4LmNvbW1vbiwKICAgICAgICAgICAgICBpc3N1ZXM6IFtdCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHBhcmVudDogbnVsbAogICAgICAgICAgfTsKICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG9wdGlvbi5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGNoaWxkQ3R4CiAgICAgICAgICB9KTsKICAgICAgICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSAidmFsaWQiKSB7CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICB9IGVsc2UgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICJkaXJ0eSIgJiYgIWRpcnR5KSB7CiAgICAgICAgICAgIGRpcnR5ID0geyByZXN1bHQsIGN0eDogY2hpbGRDdHggfTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChjaGlsZEN0eC5jb21tb24uaXNzdWVzLmxlbmd0aCkgewogICAgICAgICAgICBpc3N1ZXMucHVzaChjaGlsZEN0eC5jb21tb24uaXNzdWVzKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGRpcnR5KSB7CiAgICAgICAgICBjdHguY29tbW9uLmlzc3Vlcy5wdXNoKC4uLmRpcnR5LmN0eC5jb21tb24uaXNzdWVzKTsKICAgICAgICAgIHJldHVybiBkaXJ0eS5yZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHVuaW9uRXJyb3JzID0gaXNzdWVzLm1hcCgoaXNzdWVzMikgPT4gbmV3IFpvZEVycm9yKGlzc3VlczIpKTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3VuaW9uLAogICAgICAgICAgdW5pb25FcnJvcnMKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgfQogICAgZ2V0IG9wdGlvbnMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYub3B0aW9uczsKICAgIH0KICB9CiAgWm9kVW5pb24uY3JlYXRlID0gKHR5cGVzLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kVW5pb24oewogICAgICBvcHRpb25zOiB0eXBlcywKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RVbmlvbiwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNvbnN0IGdldERpc2NyaW1pbmF0b3IgPSAodHlwZSkgPT4gewogICAgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RMYXp5KSB7CiAgICAgIHJldHVybiBnZXREaXNjcmltaW5hdG9yKHR5cGUuc2NoZW1hKTsKICAgIH0gZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZEVmZmVjdHMpIHsKICAgICAgcmV0dXJuIGdldERpc2NyaW1pbmF0b3IodHlwZS5pbm5lclR5cGUoKSk7CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RMaXRlcmFsKSB7CiAgICAgIHJldHVybiBbdHlwZS52YWx1ZV07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RFbnVtKSB7CiAgICAgIHJldHVybiB0eXBlLm9wdGlvbnM7CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2ROYXRpdmVFbnVtKSB7CiAgICAgIHJldHVybiB1dGlsLm9iamVjdFZhbHVlcyh0eXBlLmVudW0pOwogICAgfSBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kRGVmYXVsdCkgewogICAgICByZXR1cm4gZ2V0RGlzY3JpbWluYXRvcih0eXBlLl9kZWYuaW5uZXJUeXBlKTsKICAgIH0gZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZFVuZGVmaW5lZCkgewogICAgICByZXR1cm4gW3ZvaWQgMF07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2ROdWxsKSB7CiAgICAgIHJldHVybiBbbnVsbF07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RPcHRpb25hbCkgewogICAgICByZXR1cm4gW3ZvaWQgMCwgLi4uZ2V0RGlzY3JpbWluYXRvcih0eXBlLnVud3JhcCgpKV07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2ROdWxsYWJsZSkgewogICAgICByZXR1cm4gW251bGwsIC4uLmdldERpc2NyaW1pbmF0b3IodHlwZS51bndyYXAoKSldOwogICAgfSBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kQnJhbmRlZCkgewogICAgICByZXR1cm4gZ2V0RGlzY3JpbWluYXRvcih0eXBlLnVud3JhcCgpKTsKICAgIH0gZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZFJlYWRvbmx5KSB7CiAgICAgIHJldHVybiBnZXREaXNjcmltaW5hdG9yKHR5cGUudW53cmFwKCkpOwogICAgfSBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kQ2F0Y2gpIHsKICAgICAgcmV0dXJuIGdldERpc2NyaW1pbmF0b3IodHlwZS5fZGVmLmlubmVyVHlwZSk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gW107CiAgICB9CiAgfTsKICBjbGFzcyBab2REaXNjcmltaW5hdGVkVW5pb24gZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm9iamVjdCkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm9iamVjdCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IGRpc2NyaW1pbmF0b3IgPSB0aGlzLmRpc2NyaW1pbmF0b3I7CiAgICAgIGNvbnN0IGRpc2NyaW1pbmF0b3JWYWx1ZSA9IGN0eC5kYXRhW2Rpc2NyaW1pbmF0b3JdOwogICAgICBjb25zdCBvcHRpb24gPSB0aGlzLm9wdGlvbnNNYXAuZ2V0KGRpc2NyaW1pbmF0b3JWYWx1ZSk7CiAgICAgIGlmICghb3B0aW9uKSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF91bmlvbl9kaXNjcmltaW5hdG9yLAogICAgICAgICAgb3B0aW9uczogQXJyYXkuZnJvbSh0aGlzLm9wdGlvbnNNYXAua2V5cygpKSwKICAgICAgICAgIHBhdGg6IFtkaXNjcmltaW5hdG9yXQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbi5fcGFyc2VBc3luYyh7CiAgICAgICAgICBkYXRhOiBjdHguZGF0YSwKICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gb3B0aW9uLl9wYXJzZVN5bmMoewogICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIGdldCBkaXNjcmltaW5hdG9yKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmRpc2NyaW1pbmF0b3I7CiAgICB9CiAgICBnZXQgb3B0aW9ucygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5vcHRpb25zOwogICAgfQogICAgZ2V0IG9wdGlvbnNNYXAoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYub3B0aW9uc01hcDsKICAgIH0KICAgIC8qKgogICAgICogVGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBkaXNjcmltaW5hdGVkIHVuaW9uIHNjaGVtYS4gSXRzIGJlaGF2aW91ciBpcyB2ZXJ5IHNpbWlsYXIgdG8gdGhhdCBvZiB0aGUgbm9ybWFsIHoudW5pb24oKSBjb25zdHJ1Y3Rvci4KICAgICAqIEhvd2V2ZXIsIGl0IG9ubHkgYWxsb3dzIGEgdW5pb24gb2Ygb2JqZWN0cywgYWxsIG9mIHdoaWNoIG5lZWQgdG8gc2hhcmUgYSBkaXNjcmltaW5hdG9yIHByb3BlcnR5LiBUaGlzIHByb3BlcnR5IG11c3QKICAgICAqIGhhdmUgYSBkaWZmZXJlbnQgdmFsdWUgZm9yIGVhY2ggb2JqZWN0IGluIHRoZSB1bmlvbi4KICAgICAqIEBwYXJhbSBkaXNjcmltaW5hdG9yIHRoZSBuYW1lIG9mIHRoZSBkaXNjcmltaW5hdG9yIHByb3BlcnR5CiAgICAgKiBAcGFyYW0gdHlwZXMgYW4gYXJyYXkgb2Ygb2JqZWN0IHNjaGVtYXMKICAgICAqIEBwYXJhbSBwYXJhbXMKICAgICAqLwogICAgc3RhdGljIGNyZWF0ZShkaXNjcmltaW5hdG9yLCBvcHRpb25zLCBwYXJhbXMpIHsKICAgICAgY29uc3Qgb3B0aW9uc01hcCA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgIGZvciAoY29uc3QgdHlwZSBvZiBvcHRpb25zKSB7CiAgICAgICAgY29uc3QgZGlzY3JpbWluYXRvclZhbHVlcyA9IGdldERpc2NyaW1pbmF0b3IodHlwZS5zaGFwZVtkaXNjcmltaW5hdG9yXSk7CiAgICAgICAgaWYgKCFkaXNjcmltaW5hdG9yVmFsdWVzLmxlbmd0aCkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBBIGRpc2NyaW1pbmF0b3IgdmFsdWUgZm9yIGtleSBcYCR7ZGlzY3JpbWluYXRvcn1cYCBjb3VsZCBub3QgYmUgZXh0cmFjdGVkIGZyb20gYWxsIHNjaGVtYSBvcHRpb25zYCk7CiAgICAgICAgfQogICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgZGlzY3JpbWluYXRvclZhbHVlcykgewogICAgICAgICAgaWYgKG9wdGlvbnNNYXAuaGFzKHZhbHVlKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERpc2NyaW1pbmF0b3IgcHJvcGVydHkgJHtTdHJpbmcoZGlzY3JpbWluYXRvcil9IGhhcyBkdXBsaWNhdGUgdmFsdWUgJHtTdHJpbmcodmFsdWUpfWApOwogICAgICAgICAgfQogICAgICAgICAgb3B0aW9uc01hcC5zZXQodmFsdWUsIHR5cGUpOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbmV3IFpvZERpc2NyaW1pbmF0ZWRVbmlvbih7CiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2REaXNjcmltaW5hdGVkVW5pb24sCiAgICAgICAgZGlzY3JpbWluYXRvciwKICAgICAgICBvcHRpb25zLAogICAgICAgIG9wdGlvbnNNYXAsCiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICAgIH0pOwogICAgfQogIH0KICBmdW5jdGlvbiBtZXJnZVZhbHVlcyhhMiwgYikgewogICAgY29uc3QgYVR5cGUgPSBnZXRQYXJzZWRUeXBlKGEyKTsKICAgIGNvbnN0IGJUeXBlID0gZ2V0UGFyc2VkVHlwZShiKTsKICAgIGlmIChhMiA9PT0gYikgewogICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZGF0YTogYTIgfTsKICAgIH0gZWxzZSBpZiAoYVR5cGUgPT09IFpvZFBhcnNlZFR5cGUub2JqZWN0ICYmIGJUeXBlID09PSBab2RQYXJzZWRUeXBlLm9iamVjdCkgewogICAgICBjb25zdCBiS2V5cyA9IHV0aWwub2JqZWN0S2V5cyhiKTsKICAgICAgY29uc3Qgc2hhcmVkS2V5cyA9IHV0aWwub2JqZWN0S2V5cyhhMikuZmlsdGVyKChrZXkpID0+IGJLZXlzLmluZGV4T2Yoa2V5KSAhPT0gLTEpOwogICAgICBjb25zdCBuZXdPYmogPSB7IC4uLmEyLCAuLi5iIH07CiAgICAgIGZvciAoY29uc3Qga2V5IG9mIHNoYXJlZEtleXMpIHsKICAgICAgICBjb25zdCBzaGFyZWRWYWx1ZSA9IG1lcmdlVmFsdWVzKGEyW2tleV0sIGJba2V5XSk7CiAgICAgICAgaWYgKCFzaGFyZWRWYWx1ZS52YWxpZCkgewogICAgICAgICAgcmV0dXJuIHsgdmFsaWQ6IGZhbHNlIH07CiAgICAgICAgfQogICAgICAgIG5ld09ialtrZXldID0gc2hhcmVkVmFsdWUuZGF0YTsKICAgICAgfQogICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZGF0YTogbmV3T2JqIH07CiAgICB9IGVsc2UgaWYgKGFUeXBlID09PSBab2RQYXJzZWRUeXBlLmFycmF5ICYmIGJUeXBlID09PSBab2RQYXJzZWRUeXBlLmFycmF5KSB7CiAgICAgIGlmIChhMi5sZW5ndGggIT09IGIubGVuZ3RoKSB7CiAgICAgICAgcmV0dXJuIHsgdmFsaWQ6IGZhbHNlIH07CiAgICAgIH0KICAgICAgY29uc3QgbmV3QXJyYXkgPSBbXTsKICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGEyLmxlbmd0aDsgaW5kZXgrKykgewogICAgICAgIGNvbnN0IGl0ZW1BID0gYTJbaW5kZXhdOwogICAgICAgIGNvbnN0IGl0ZW1CID0gYltpbmRleF07CiAgICAgICAgY29uc3Qgc2hhcmVkVmFsdWUgPSBtZXJnZVZhbHVlcyhpdGVtQSwgaXRlbUIpOwogICAgICAgIGlmICghc2hhcmVkVmFsdWUudmFsaWQpIHsKICAgICAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSB9OwogICAgICAgIH0KICAgICAgICBuZXdBcnJheS5wdXNoKHNoYXJlZFZhbHVlLmRhdGEpOwogICAgICB9CiAgICAgIHJldHVybiB7IHZhbGlkOiB0cnVlLCBkYXRhOiBuZXdBcnJheSB9OwogICAgfSBlbHNlIGlmIChhVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS5kYXRlICYmIGJUeXBlID09PSBab2RQYXJzZWRUeXBlLmRhdGUgJiYgK2EyID09PSArYikgewogICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZGF0YTogYTIgfTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSB9OwogICAgfQogIH0KICBjbGFzcyBab2RJbnRlcnNlY3Rpb24gZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IHN0YXR1cywgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBoYW5kbGVQYXJzZWQgPSAocGFyc2VkTGVmdCwgcGFyc2VkUmlnaHQpID0+IHsKICAgICAgICBpZiAoaXNBYm9ydGVkKHBhcnNlZExlZnQpIHx8IGlzQWJvcnRlZChwYXJzZWRSaWdodCkpIHsKICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgIH0KICAgICAgICBjb25zdCBtZXJnZWQgPSBtZXJnZVZhbHVlcyhwYXJzZWRMZWZ0LnZhbHVlLCBwYXJzZWRSaWdodC52YWx1ZSk7CiAgICAgICAgaWYgKCFtZXJnZWQudmFsaWQpIHsKICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9pbnRlcnNlY3Rpb25fdHlwZXMKICAgICAgICAgIH0pOwogICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgfQogICAgICAgIGlmIChpc0RpcnR5KHBhcnNlZExlZnQpIHx8IGlzRGlydHkocGFyc2VkUmlnaHQpKSB7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBtZXJnZWQuZGF0YSB9OwogICAgICB9OwogICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYykgewogICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbCiAgICAgICAgICB0aGlzLl9kZWYubGVmdC5fcGFyc2VBc3luYyh7CiAgICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLAogICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICAgIH0pLAogICAgICAgICAgdGhpcy5fZGVmLnJpZ2h0Ll9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSkKICAgICAgICBdKS50aGVuKChbbGVmdCwgcmlnaHRdKSA9PiBoYW5kbGVQYXJzZWQobGVmdCwgcmlnaHQpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gaGFuZGxlUGFyc2VkKHRoaXMuX2RlZi5sZWZ0Ll9wYXJzZVN5bmMoewogICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgfSksIHRoaXMuX2RlZi5yaWdodC5fcGFyc2VTeW5jKHsKICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLAogICAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgIH0pKTsKICAgICAgfQogICAgfQogIH0KICBab2RJbnRlcnNlY3Rpb24uY3JlYXRlID0gKGxlZnQsIHJpZ2h0LCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kSW50ZXJzZWN0aW9uKHsKICAgICAgbGVmdCwKICAgICAgcmlnaHQsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kSW50ZXJzZWN0aW9uLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kVHVwbGUgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IHN0YXR1cywgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuYXJyYXkpIHsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5hcnJheSwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmIChjdHguZGF0YS5sZW5ndGggPCB0aGlzLl9kZWYuaXRlbXMubGVuZ3RoKSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgbWluaW11bTogdGhpcy5fZGVmLml0ZW1zLmxlbmd0aCwKICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgIHR5cGU6ICJhcnJheSIKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBjb25zdCByZXN0ID0gdGhpcy5fZGVmLnJlc3Q7CiAgICAgIGlmICghcmVzdCAmJiBjdHguZGF0YS5sZW5ndGggPiB0aGlzLl9kZWYuaXRlbXMubGVuZ3RoKSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX2JpZywKICAgICAgICAgIG1heGltdW06IHRoaXMuX2RlZi5pdGVtcy5sZW5ndGgsCiAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgICBleGFjdDogZmFsc2UsCiAgICAgICAgICB0eXBlOiAiYXJyYXkiCiAgICAgICAgfSk7CiAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgIH0KICAgICAgY29uc3QgaXRlbXMgPSBbLi4uY3R4LmRhdGFdLm1hcCgoaXRlbSwgaXRlbUluZGV4KSA9PiB7CiAgICAgICAgY29uc3Qgc2NoZW1hID0gdGhpcy5fZGVmLml0ZW1zW2l0ZW1JbmRleF0gfHwgdGhpcy5fZGVmLnJlc3Q7CiAgICAgICAgaWYgKCFzY2hlbWEpCiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICByZXR1cm4gc2NoZW1hLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwgaXRlbSwgY3R4LnBhdGgsIGl0ZW1JbmRleCkpOwogICAgICB9KS5maWx0ZXIoKHgpID0+ICEheCk7CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKGl0ZW1zKS50aGVuKChyZXN1bHRzKSA9PiB7CiAgICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VBcnJheShzdGF0dXMsIHJlc3VsdHMpOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBQYXJzZVN0YXR1cy5tZXJnZUFycmF5KHN0YXR1cywgaXRlbXMpOwogICAgICB9CiAgICB9CiAgICBnZXQgaXRlbXMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYuaXRlbXM7CiAgICB9CiAgICByZXN0KHJlc3QpIHsKICAgICAgcmV0dXJuIG5ldyBab2RUdXBsZSh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHJlc3QKICAgICAgfSk7CiAgICB9CiAgfQogIFpvZFR1cGxlLmNyZWF0ZSA9IChzY2hlbWFzLCBwYXJhbXMpID0+IHsKICAgIGlmICghQXJyYXkuaXNBcnJheShzY2hlbWFzKSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIllvdSBtdXN0IHBhc3MgYW4gYXJyYXkgb2Ygc2NoZW1hcyB0byB6LnR1cGxlKFsgLi4uIF0pIik7CiAgICB9CiAgICByZXR1cm4gbmV3IFpvZFR1cGxlKHsKICAgICAgaXRlbXM6IHNjaGVtYXMsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kVHVwbGUsCiAgICAgIHJlc3Q6IG51bGwsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RSZWNvcmQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGdldCBrZXlTY2hlbWEoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYua2V5VHlwZTsKICAgIH0KICAgIGdldCB2YWx1ZVNjaGVtYSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZVR5cGU7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm9iamVjdCkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm9iamVjdCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IHBhaXJzID0gW107CiAgICAgIGNvbnN0IGtleVR5cGUgPSB0aGlzLl9kZWYua2V5VHlwZTsKICAgICAgY29uc3QgdmFsdWVUeXBlID0gdGhpcy5fZGVmLnZhbHVlVHlwZTsKICAgICAgZm9yIChjb25zdCBrZXkgaW4gY3R4LmRhdGEpIHsKICAgICAgICBwYWlycy5wdXNoKHsKICAgICAgICAgIGtleToga2V5VHlwZS5fcGFyc2UobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGtleSwgY3R4LnBhdGgsIGtleSkpLAogICAgICAgICAgdmFsdWU6IHZhbHVlVHlwZS5fcGFyc2UobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGN0eC5kYXRhW2tleV0sIGN0eC5wYXRoLCBrZXkpKSwKICAgICAgICAgIGFsd2F5c1NldDoga2V5IGluIGN0eC5kYXRhCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VPYmplY3RBc3luYyhzdGF0dXMsIHBhaXJzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VPYmplY3RTeW5jKHN0YXR1cywgcGFpcnMpOwogICAgICB9CiAgICB9CiAgICBnZXQgZWxlbWVudCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZVR5cGU7CiAgICB9CiAgICBzdGF0aWMgY3JlYXRlKGZpcnN0LCBzZWNvbmQsIHRoaXJkKSB7CiAgICAgIGlmIChzZWNvbmQgaW5zdGFuY2VvZiBab2RUeXBlKSB7CiAgICAgICAgcmV0dXJuIG5ldyBab2RSZWNvcmQoewogICAgICAgICAga2V5VHlwZTogZmlyc3QsCiAgICAgICAgICB2YWx1ZVR5cGU6IHNlY29uZCwKICAgICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kUmVjb3JkLAogICAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyh0aGlyZCkKICAgICAgICB9KTsKICAgICAgfQogICAgICByZXR1cm4gbmV3IFpvZFJlY29yZCh7CiAgICAgICAga2V5VHlwZTogWm9kU3RyaW5nLmNyZWF0ZSgpLAogICAgICAgIHZhbHVlVHlwZTogZmlyc3QsCiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RSZWNvcmQsCiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhzZWNvbmQpCiAgICAgIH0pOwogICAgfQogIH0KICBjbGFzcyBab2RNYXAgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGdldCBrZXlTY2hlbWEoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYua2V5VHlwZTsKICAgIH0KICAgIGdldCB2YWx1ZVNjaGVtYSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZVR5cGU7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm1hcCkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm1hcCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IGtleVR5cGUgPSB0aGlzLl9kZWYua2V5VHlwZTsKICAgICAgY29uc3QgdmFsdWVUeXBlID0gdGhpcy5fZGVmLnZhbHVlVHlwZTsKICAgICAgY29uc3QgcGFpcnMgPSBbLi4uY3R4LmRhdGEuZW50cmllcygpXS5tYXAoKFtrZXksIHZhbHVlXSwgaW5kZXgpID0+IHsKICAgICAgICByZXR1cm4gewogICAgICAgICAga2V5OiBrZXlUeXBlLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwga2V5LCBjdHgucGF0aCwgW2luZGV4LCAia2V5Il0pKSwKICAgICAgICAgIHZhbHVlOiB2YWx1ZVR5cGUuX3BhcnNlKG5ldyBQYXJzZUlucHV0TGF6eVBhdGgoY3R4LCB2YWx1ZSwgY3R4LnBhdGgsIFtpbmRleCwgInZhbHVlIl0pKQogICAgICAgIH07CiAgICAgIH0pOwogICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYykgewogICAgICAgIGNvbnN0IGZpbmFsTWFwID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihhc3luYyAoKSA9PiB7CiAgICAgICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHsKICAgICAgICAgICAgY29uc3Qga2V5ID0gYXdhaXQgcGFpci5rZXk7CiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgcGFpci52YWx1ZTsKICAgICAgICAgICAgaWYgKGtleS5zdGF0dXMgPT09ICJhYm9ydGVkIiB8fCB2YWx1ZS5zdGF0dXMgPT09ICJhYm9ydGVkIikgewogICAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChrZXkuc3RhdHVzID09PSAiZGlydHkiIHx8IHZhbHVlLnN0YXR1cyA9PT0gImRpcnR5IikgewogICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZpbmFsTWFwLnNldChrZXkudmFsdWUsIHZhbHVlLnZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogZmluYWxNYXAgfTsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBmaW5hbE1hcCA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgICAgZm9yIChjb25zdCBwYWlyIG9mIHBhaXJzKSB7CiAgICAgICAgICBjb25zdCBrZXkgPSBwYWlyLmtleTsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gcGFpci52YWx1ZTsKICAgICAgICAgIGlmIChrZXkuc3RhdHVzID09PSAiYWJvcnRlZCIgfHwgdmFsdWUuc3RhdHVzID09PSAiYWJvcnRlZCIpIHsKICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoa2V5LnN0YXR1cyA9PT0gImRpcnR5IiB8fCB2YWx1ZS5zdGF0dXMgPT09ICJkaXJ0eSIpIHsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgICBmaW5hbE1hcC5zZXQoa2V5LnZhbHVlLCB2YWx1ZS52YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogZmluYWxNYXAgfTsKICAgICAgfQogICAgfQogIH0KICBab2RNYXAuY3JlYXRlID0gKGtleVR5cGUsIHZhbHVlVHlwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE1hcCh7CiAgICAgIHZhbHVlVHlwZSwKICAgICAga2V5VHlwZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RNYXAsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RTZXQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IHN0YXR1cywgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuc2V0KSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUuc2V0LAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgY29uc3QgZGVmID0gdGhpcy5fZGVmOwogICAgICBpZiAoZGVmLm1pblNpemUgIT09IG51bGwpIHsKICAgICAgICBpZiAoY3R4LmRhdGEuc2l6ZSA8IGRlZi5taW5TaXplLnZhbHVlKSB7CiAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19zbWFsbCwKICAgICAgICAgICAgbWluaW11bTogZGVmLm1pblNpemUudmFsdWUsCiAgICAgICAgICAgIHR5cGU6ICJzZXQiLAogICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgbWVzc2FnZTogZGVmLm1pblNpemUubWVzc2FnZQogICAgICAgICAgfSk7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGRlZi5tYXhTaXplICE9PSBudWxsKSB7CiAgICAgICAgaWYgKGN0eC5kYXRhLnNpemUgPiBkZWYubWF4U2l6ZS52YWx1ZSkgewogICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fYmlnLAogICAgICAgICAgICBtYXhpbXVtOiBkZWYubWF4U2l6ZS52YWx1ZSwKICAgICAgICAgICAgdHlwZTogInNldCIsCiAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLAogICAgICAgICAgICBtZXNzYWdlOiBkZWYubWF4U2l6ZS5tZXNzYWdlCiAgICAgICAgICB9KTsKICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCB2YWx1ZVR5cGUgPSB0aGlzLl9kZWYudmFsdWVUeXBlOwogICAgICBmdW5jdGlvbiBmaW5hbGl6ZVNldChlbGVtZW50czIpIHsKICAgICAgICBjb25zdCBwYXJzZWRTZXQgPSAvKiBAX19QVVJFX18gKi8gbmV3IFNldCgpOwogICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbGVtZW50czIpIHsKICAgICAgICAgIGlmIChlbGVtZW50LnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgICAgIGlmIChlbGVtZW50LnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICBwYXJzZWRTZXQuYWRkKGVsZW1lbnQudmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IHBhcnNlZFNldCB9OwogICAgICB9CiAgICAgIGNvbnN0IGVsZW1lbnRzID0gWy4uLmN0eC5kYXRhLnZhbHVlcygpXS5tYXAoKGl0ZW0sIGkyKSA9PiB2YWx1ZVR5cGUuX3BhcnNlKG5ldyBQYXJzZUlucHV0TGF6eVBhdGgoY3R4LCBpdGVtLCBjdHgucGF0aCwgaTIpKSk7CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKGVsZW1lbnRzKS50aGVuKChlbGVtZW50czIpID0+IGZpbmFsaXplU2V0KGVsZW1lbnRzMikpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBmaW5hbGl6ZVNldChlbGVtZW50cyk7CiAgICAgIH0KICAgIH0KICAgIG1pbihtaW5TaXplLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kU2V0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgbWluU2l6ZTogeyB2YWx1ZTogbWluU2l6ZSwgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpIH0KICAgICAgfSk7CiAgICB9CiAgICBtYXgobWF4U2l6ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gbmV3IFpvZFNldCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIG1heFNpemU6IHsgdmFsdWU6IG1heFNpemUsIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSB9CiAgICAgIH0pOwogICAgfQogICAgc2l6ZShzaXplLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLm1pbihzaXplLCBtZXNzYWdlKS5tYXgoc2l6ZSwgbWVzc2FnZSk7CiAgICB9CiAgICBub25lbXB0eShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLm1pbigxLCBtZXNzYWdlKTsKICAgIH0KICB9CiAgWm9kU2V0LmNyZWF0ZSA9ICh2YWx1ZVR5cGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RTZXQoewogICAgICB2YWx1ZVR5cGUsCiAgICAgIG1pblNpemU6IG51bGwsCiAgICAgIG1heFNpemU6IG51bGwsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kU2V0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kRnVuY3Rpb24gZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICB0aGlzLnZhbGlkYXRlID0gdGhpcy5pbXBsZW1lbnQ7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBjdHggfSA9IHRoaXMuX3Byb2Nlc3NJbnB1dFBhcmFtcyhpbnB1dCk7CiAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5mdW5jdGlvbikgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmZ1bmN0aW9uLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgZnVuY3Rpb24gbWFrZUFyZ3NJc3N1ZShhcmdzLCBlcnJvcikgewogICAgICAgIHJldHVybiBtYWtlSXNzdWUoewogICAgICAgICAgZGF0YTogYXJncywKICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgZXJyb3JNYXBzOiBbCiAgICAgICAgICAgIGN0eC5jb21tb24uY29udGV4dHVhbEVycm9yTWFwLAogICAgICAgICAgICBjdHguc2NoZW1hRXJyb3JNYXAsCiAgICAgICAgICAgIGdldEVycm9yTWFwKCksCiAgICAgICAgICAgIGVycm9yTWFwCiAgICAgICAgICBdLmZpbHRlcigoeCkgPT4gISF4KSwKICAgICAgICAgIGlzc3VlRGF0YTogewogICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9hcmd1bWVudHMsCiAgICAgICAgICAgIGFyZ3VtZW50c0Vycm9yOiBlcnJvcgogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CiAgICAgIGZ1bmN0aW9uIG1ha2VSZXR1cm5zSXNzdWUocmV0dXJucywgZXJyb3IpIHsKICAgICAgICByZXR1cm4gbWFrZUlzc3VlKHsKICAgICAgICAgIGRhdGE6IHJldHVybnMsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIGVycm9yTWFwczogWwogICAgICAgICAgICBjdHguY29tbW9uLmNvbnRleHR1YWxFcnJvck1hcCwKICAgICAgICAgICAgY3R4LnNjaGVtYUVycm9yTWFwLAogICAgICAgICAgICBnZXRFcnJvck1hcCgpLAogICAgICAgICAgICBlcnJvck1hcAogICAgICAgICAgXS5maWx0ZXIoKHgpID0+ICEheCksCiAgICAgICAgICBpc3N1ZURhdGE6IHsKICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfcmV0dXJuX3R5cGUsCiAgICAgICAgICAgIHJldHVyblR5cGVFcnJvcjogZXJyb3IKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQogICAgICBjb25zdCBwYXJhbXMgPSB7IGVycm9yTWFwOiBjdHguY29tbW9uLmNvbnRleHR1YWxFcnJvck1hcCB9OwogICAgICBjb25zdCBmbiA9IGN0eC5kYXRhOwogICAgICBpZiAodGhpcy5fZGVmLnJldHVybnMgaW5zdGFuY2VvZiBab2RQcm9taXNlKSB7CiAgICAgICAgY29uc3QgbWUgPSB0aGlzOwogICAgICAgIHJldHVybiBPSyhhc3luYyBmdW5jdGlvbiguLi5hcmdzKSB7CiAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBab2RFcnJvcihbXSk7CiAgICAgICAgICBjb25zdCBwYXJzZWRBcmdzID0gYXdhaXQgbWUuX2RlZi5hcmdzLnBhcnNlQXN5bmMoYXJncywgcGFyYW1zKS5jYXRjaCgoZTIpID0+IHsKICAgICAgICAgICAgZXJyb3IuYWRkSXNzdWUobWFrZUFyZ3NJc3N1ZShhcmdzLCBlMikpOwogICAgICAgICAgICB0aHJvdyBlcnJvcjsKICAgICAgICAgIH0pOwogICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgUmVmbGVjdC5hcHBseShmbiwgdGhpcywgcGFyc2VkQXJncyk7CiAgICAgICAgICBjb25zdCBwYXJzZWRSZXR1cm5zID0gYXdhaXQgbWUuX2RlZi5yZXR1cm5zLl9kZWYudHlwZS5wYXJzZUFzeW5jKHJlc3VsdCwgcGFyYW1zKS5jYXRjaCgoZTIpID0+IHsKICAgICAgICAgICAgZXJyb3IuYWRkSXNzdWUobWFrZVJldHVybnNJc3N1ZShyZXN1bHQsIGUyKSk7CiAgICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgICAgfSk7CiAgICAgICAgICByZXR1cm4gcGFyc2VkUmV0dXJuczsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBtZSA9IHRoaXM7CiAgICAgICAgcmV0dXJuIE9LKGZ1bmN0aW9uKC4uLmFyZ3MpIHsKICAgICAgICAgIGNvbnN0IHBhcnNlZEFyZ3MgPSBtZS5fZGVmLmFyZ3Muc2FmZVBhcnNlKGFyZ3MsIHBhcmFtcyk7CiAgICAgICAgICBpZiAoIXBhcnNlZEFyZ3Muc3VjY2VzcykgewogICAgICAgICAgICB0aHJvdyBuZXcgWm9kRXJyb3IoW21ha2VBcmdzSXNzdWUoYXJncywgcGFyc2VkQXJncy5lcnJvcildKTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IFJlZmxlY3QuYXBwbHkoZm4sIHRoaXMsIHBhcnNlZEFyZ3MuZGF0YSk7CiAgICAgICAgICBjb25zdCBwYXJzZWRSZXR1cm5zID0gbWUuX2RlZi5yZXR1cm5zLnNhZmVQYXJzZShyZXN1bHQsIHBhcmFtcyk7CiAgICAgICAgICBpZiAoIXBhcnNlZFJldHVybnMuc3VjY2VzcykgewogICAgICAgICAgICB0aHJvdyBuZXcgWm9kRXJyb3IoW21ha2VSZXR1cm5zSXNzdWUocmVzdWx0LCBwYXJzZWRSZXR1cm5zLmVycm9yKV0pOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHBhcnNlZFJldHVybnMuZGF0YTsKICAgICAgICB9KTsKICAgICAgfQogICAgfQogICAgcGFyYW1ldGVycygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5hcmdzOwogICAgfQogICAgcmV0dXJuVHlwZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5yZXR1cm5zOwogICAgfQogICAgYXJncyguLi5pdGVtcykgewogICAgICByZXR1cm4gbmV3IFpvZEZ1bmN0aW9uKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgYXJnczogWm9kVHVwbGUuY3JlYXRlKGl0ZW1zKS5yZXN0KFpvZFVua25vd24uY3JlYXRlKCkpCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJucyhyZXR1cm5UeXBlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kRnVuY3Rpb24oewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICByZXR1cm5zOiByZXR1cm5UeXBlCiAgICAgIH0pOwogICAgfQogICAgaW1wbGVtZW50KGZ1bmMpIHsKICAgICAgY29uc3QgdmFsaWRhdGVkRnVuYyA9IHRoaXMucGFyc2UoZnVuYyk7CiAgICAgIHJldHVybiB2YWxpZGF0ZWRGdW5jOwogICAgfQogICAgc3RyaWN0SW1wbGVtZW50KGZ1bmMpIHsKICAgICAgY29uc3QgdmFsaWRhdGVkRnVuYyA9IHRoaXMucGFyc2UoZnVuYyk7CiAgICAgIHJldHVybiB2YWxpZGF0ZWRGdW5jOwogICAgfQogICAgc3RhdGljIGNyZWF0ZShhcmdzLCByZXR1cm5zLCBwYXJhbXMpIHsKICAgICAgcmV0dXJuIG5ldyBab2RGdW5jdGlvbih7CiAgICAgICAgYXJnczogYXJncyA/IGFyZ3MgOiBab2RUdXBsZS5jcmVhdGUoW10pLnJlc3QoWm9kVW5rbm93bi5jcmVhdGUoKSksCiAgICAgICAgcmV0dXJuczogcmV0dXJucyB8fCBab2RVbmtub3duLmNyZWF0ZSgpLAogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRnVuY3Rpb24sCiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICAgIH0pOwogICAgfQogIH0KICBjbGFzcyBab2RMYXp5IGV4dGVuZHMgWm9kVHlwZSB7CiAgICBnZXQgc2NoZW1hKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmdldHRlcigpOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBsYXp5U2NoZW1hID0gdGhpcy5fZGVmLmdldHRlcigpOwogICAgICByZXR1cm4gbGF6eVNjaGVtYS5fcGFyc2UoeyBkYXRhOiBjdHguZGF0YSwgcGF0aDogY3R4LnBhdGgsIHBhcmVudDogY3R4IH0pOwogICAgfQogIH0KICBab2RMYXp5LmNyZWF0ZSA9IChnZXR0ZXIsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RMYXp5KHsKICAgICAgZ2V0dGVyLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZExhenksCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RMaXRlcmFsIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgaWYgKGlucHV0LmRhdGEgIT09IHRoaXMuX2RlZi52YWx1ZSkgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIHJlY2VpdmVkOiBjdHguZGF0YSwKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX2xpdGVyYWwsCiAgICAgICAgICBleHBlY3RlZDogdGhpcy5fZGVmLnZhbHVlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgcmV0dXJuIHsgc3RhdHVzOiAidmFsaWQiLCB2YWx1ZTogaW5wdXQuZGF0YSB9OwogICAgfQogICAgZ2V0IHZhbHVlKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnZhbHVlOwogICAgfQogIH0KICBab2RMaXRlcmFsLmNyZWF0ZSA9ICh2YWx1ZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZExpdGVyYWwoewogICAgICB2YWx1ZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RMaXRlcmFsLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgZnVuY3Rpb24gY3JlYXRlWm9kRW51bSh2YWx1ZXMsIHBhcmFtcykgewogICAgcmV0dXJuIG5ldyBab2RFbnVtKHsKICAgICAgdmFsdWVzLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVudW0sCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfQogIGNsYXNzIFpvZEVudW0gZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICBfWm9kRW51bV9jYWNoZS5zZXQodGhpcywgdm9pZCAwKTsKICAgIH0KICAgIF9wYXJzZShpbnB1dCkgewogICAgICBpZiAodHlwZW9mIGlucHV0LmRhdGEgIT09ICJzdHJpbmciKSB7CiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICAgIGNvbnN0IGV4cGVjdGVkVmFsdWVzID0gdGhpcy5fZGVmLnZhbHVlczsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGV4cGVjdGVkOiB1dGlsLmpvaW5WYWx1ZXMoZXhwZWN0ZWRWYWx1ZXMpLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLAogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmICghX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfWm9kRW51bV9jYWNoZSkpIHsKICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9ab2RFbnVtX2NhY2hlLCBuZXcgU2V0KHRoaXMuX2RlZi52YWx1ZXMpKTsKICAgICAgfQogICAgICBpZiAoIV9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1pvZEVudW1fY2FjaGUpLmhhcyhpbnB1dC5kYXRhKSkgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBjb25zdCBleHBlY3RlZFZhbHVlcyA9IHRoaXMuX2RlZi52YWx1ZXM7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICByZWNlaXZlZDogY3R4LmRhdGEsCiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9lbnVtX3ZhbHVlLAogICAgICAgICAgb3B0aW9uczogZXhwZWN0ZWRWYWx1ZXMKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7CiAgICB9CiAgICBnZXQgb3B0aW9ucygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZXM7CiAgICB9CiAgICBnZXQgZW51bSgpIHsKICAgICAgY29uc3QgZW51bVZhbHVlcyA9IHt9OwogICAgICBmb3IgKGNvbnN0IHZhbCBvZiB0aGlzLl9kZWYudmFsdWVzKSB7CiAgICAgICAgZW51bVZhbHVlc1t2YWxdID0gdmFsOwogICAgICB9CiAgICAgIHJldHVybiBlbnVtVmFsdWVzOwogICAgfQogICAgZ2V0IFZhbHVlcygpIHsKICAgICAgY29uc3QgZW51bVZhbHVlcyA9IHt9OwogICAgICBmb3IgKGNvbnN0IHZhbCBvZiB0aGlzLl9kZWYudmFsdWVzKSB7CiAgICAgICAgZW51bVZhbHVlc1t2YWxdID0gdmFsOwogICAgICB9CiAgICAgIHJldHVybiBlbnVtVmFsdWVzOwogICAgfQogICAgZ2V0IEVudW0oKSB7CiAgICAgIGNvbnN0IGVudW1WYWx1ZXMgPSB7fTsKICAgICAgZm9yIChjb25zdCB2YWwgb2YgdGhpcy5fZGVmLnZhbHVlcykgewogICAgICAgIGVudW1WYWx1ZXNbdmFsXSA9IHZhbDsKICAgICAgfQogICAgICByZXR1cm4gZW51bVZhbHVlczsKICAgIH0KICAgIGV4dHJhY3QodmFsdWVzLCBuZXdEZWYgPSB0aGlzLl9kZWYpIHsKICAgICAgcmV0dXJuIFpvZEVudW0uY3JlYXRlKHZhbHVlcywgewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICAuLi5uZXdEZWYKICAgICAgfSk7CiAgICB9CiAgICBleGNsdWRlKHZhbHVlcywgbmV3RGVmID0gdGhpcy5fZGVmKSB7CiAgICAgIHJldHVybiBab2RFbnVtLmNyZWF0ZSh0aGlzLm9wdGlvbnMuZmlsdGVyKChvcHQpID0+ICF2YWx1ZXMuaW5jbHVkZXMob3B0KSksIHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgLi4ubmV3RGVmCiAgICAgIH0pOwogICAgfQogIH0KICBfWm9kRW51bV9jYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgV2Vha01hcCgpOwogIFpvZEVudW0uY3JlYXRlID0gY3JlYXRlWm9kRW51bTsKICBjbGFzcyBab2ROYXRpdmVFbnVtIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgX1pvZE5hdGl2ZUVudW1fY2FjaGUuc2V0KHRoaXMsIHZvaWQgMCk7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgbmF0aXZlRW51bVZhbHVlcyA9IHV0aWwuZ2V0VmFsaWRFbnVtVmFsdWVzKHRoaXMuX2RlZi52YWx1ZXMpOwogICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5zdHJpbmcgJiYgY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUubnVtYmVyKSB7CiAgICAgICAgY29uc3QgZXhwZWN0ZWRWYWx1ZXMgPSB1dGlsLm9iamVjdFZhbHVlcyhuYXRpdmVFbnVtVmFsdWVzKTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGV4cGVjdGVkOiB1dGlsLmpvaW5WYWx1ZXMoZXhwZWN0ZWRWYWx1ZXMpLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLAogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmICghX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfWm9kTmF0aXZlRW51bV9jYWNoZSkpIHsKICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9ab2ROYXRpdmVFbnVtX2NhY2hlLCBuZXcgU2V0KHV0aWwuZ2V0VmFsaWRFbnVtVmFsdWVzKHRoaXMuX2RlZi52YWx1ZXMpKSk7CiAgICAgIH0KICAgICAgaWYgKCFfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ab2ROYXRpdmVFbnVtX2NhY2hlKS5oYXMoaW5wdXQuZGF0YSkpIHsKICAgICAgICBjb25zdCBleHBlY3RlZFZhbHVlcyA9IHV0aWwub2JqZWN0VmFsdWVzKG5hdGl2ZUVudW1WYWx1ZXMpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5kYXRhLAogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfZW51bV92YWx1ZSwKICAgICAgICAgIG9wdGlvbnM6IGV4cGVjdGVkVmFsdWVzCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgcmV0dXJuIE9LKGlucHV0LmRhdGEpOwogICAgfQogICAgZ2V0IGVudW0oKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYudmFsdWVzOwogICAgfQogIH0KICBfWm9kTmF0aXZlRW51bV9jYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgV2Vha01hcCgpOwogIFpvZE5hdGl2ZUVudW0uY3JlYXRlID0gKHZhbHVlcywgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE5hdGl2ZUVudW0oewogICAgICB2YWx1ZXMsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kTmF0aXZlRW51bSwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZFByb21pc2UgZXh0ZW5kcyBab2RUeXBlIHsKICAgIHVud3JhcCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi50eXBlOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUucHJvbWlzZSAmJiBjdHguY29tbW9uLmFzeW5jID09PSBmYWxzZSkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLnByb21pc2UsCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBjb25zdCBwcm9taXNpZmllZCA9IGN0eC5wYXJzZWRUeXBlID09PSBab2RQYXJzZWRUeXBlLnByb21pc2UgPyBjdHguZGF0YSA6IFByb21pc2UucmVzb2x2ZShjdHguZGF0YSk7CiAgICAgIHJldHVybiBPSyhwcm9taXNpZmllZC50aGVuKChkYXRhKSA9PiB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi50eXBlLnBhcnNlQXN5bmMoZGF0YSwgewogICAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgICBlcnJvck1hcDogY3R4LmNvbW1vbi5jb250ZXh0dWFsRXJyb3JNYXAKICAgICAgICB9KTsKICAgICAgfSkpOwogICAgfQogIH0KICBab2RQcm9taXNlLmNyZWF0ZSA9IChzY2hlbWEsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RQcm9taXNlKHsKICAgICAgdHlwZTogc2NoZW1hLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZFByb21pc2UsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RFZmZlY3RzIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBpbm5lclR5cGUoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYuc2NoZW1hOwogICAgfQogICAgc291cmNlVHlwZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5zY2hlbWEuX2RlZi50eXBlTmFtZSA9PT0gWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMgPyB0aGlzLl9kZWYuc2NoZW1hLnNvdXJjZVR5cGUoKSA6IHRoaXMuX2RlZi5zY2hlbWE7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgY29uc3QgZWZmZWN0ID0gdGhpcy5fZGVmLmVmZmVjdCB8fCBudWxsOwogICAgICBjb25zdCBjaGVja0N0eCA9IHsKICAgICAgICBhZGRJc3N1ZTogKGFyZykgPT4gewogICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCBhcmcpOwogICAgICAgICAgaWYgKGFyZy5mYXRhbCkgewogICAgICAgICAgICBzdGF0dXMuYWJvcnQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgZ2V0IHBhdGgoKSB7CiAgICAgICAgICByZXR1cm4gY3R4LnBhdGg7CiAgICAgICAgfQogICAgICB9OwogICAgICBjaGVja0N0eC5hZGRJc3N1ZSA9IGNoZWNrQ3R4LmFkZElzc3VlLmJpbmQoY2hlY2tDdHgpOwogICAgICBpZiAoZWZmZWN0LnR5cGUgPT09ICJwcmVwcm9jZXNzIikgewogICAgICAgIGNvbnN0IHByb2Nlc3NlZCA9IGVmZmVjdC50cmFuc2Zvcm0oY3R4LmRhdGEsIGNoZWNrQ3R4KTsKICAgICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYykgewogICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwcm9jZXNzZWQpLnRoZW4oYXN5bmMgKHByb2Nlc3NlZDIpID0+IHsKICAgICAgICAgICAgaWYgKHN0YXR1cy52YWx1ZSA9PT0gImFib3J0ZWQiKQogICAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLl9kZWYuc2NoZW1hLl9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgICBkYXRhOiBwcm9jZXNzZWQyLAogICAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgICByZXR1cm4gRElSVFkocmVzdWx0LnZhbHVlKTsKICAgICAgICAgICAgaWYgKHN0YXR1cy52YWx1ZSA9PT0gImRpcnR5IikKICAgICAgICAgICAgICByZXR1cm4gRElSVFkocmVzdWx0LnZhbHVlKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgIH0pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoc3RhdHVzLnZhbHVlID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogcHJvY2Vzc2VkLAogICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICAgIH0pOwogICAgICAgICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICJhYm9ydGVkIikKICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgcmV0dXJuIERJUlRZKHJlc3VsdC52YWx1ZSk7CiAgICAgICAgICBpZiAoc3RhdHVzLnZhbHVlID09PSAiZGlydHkiKQogICAgICAgICAgICByZXR1cm4gRElSVFkocmVzdWx0LnZhbHVlKTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChlZmZlY3QudHlwZSA9PT0gInJlZmluZW1lbnQiKSB7CiAgICAgICAgY29uc3QgZXhlY3V0ZVJlZmluZW1lbnQgPSAoYWNjKSA9PiB7CiAgICAgICAgICBjb25zdCByZXN1bHQgPSBlZmZlY3QucmVmaW5lbWVudChhY2MsIGNoZWNrQ3R4KTsKICAgICAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiQXN5bmMgcmVmaW5lbWVudCBlbmNvdW50ZXJlZCBkdXJpbmcgc3luY2hyb25vdXMgcGFyc2Ugb3BlcmF0aW9uLiBVc2UgLnBhcnNlQXN5bmMgaW5zdGVhZC4iKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBhY2M7CiAgICAgICAgfTsKICAgICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYyA9PT0gZmFsc2UpIHsKICAgICAgICAgIGNvbnN0IGlubmVyID0gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAoaW5uZXIuc3RhdHVzID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgaWYgKGlubmVyLnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICBleGVjdXRlUmVmaW5lbWVudChpbm5lci52YWx1ZSk7CiAgICAgICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGlubmVyLnZhbHVlIH07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9kZWYuc2NoZW1hLl9wYXJzZUFzeW5jKHsgZGF0YTogY3R4LmRhdGEsIHBhdGg6IGN0eC5wYXRoLCBwYXJlbnQ6IGN0eCB9KS50aGVuKChpbm5lcikgPT4gewogICAgICAgICAgICBpZiAoaW5uZXIuc3RhdHVzID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgICAgIGlmIChpbm5lci5zdGF0dXMgPT09ICJkaXJ0eSIpCiAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICAgIHJldHVybiBleGVjdXRlUmVmaW5lbWVudChpbm5lci52YWx1ZSkudGhlbigoKSA9PiB7CiAgICAgICAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBpbm5lci52YWx1ZSB9OwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoZWZmZWN0LnR5cGUgPT09ICJ0cmFuc2Zvcm0iKSB7CiAgICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMgPT09IGZhbHNlKSB7CiAgICAgICAgICBjb25zdCBiYXNlID0gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAoIWlzVmFsaWQoYmFzZSkpCiAgICAgICAgICAgIHJldHVybiBiYXNlOwogICAgICAgICAgY29uc3QgcmVzdWx0ID0gZWZmZWN0LnRyYW5zZm9ybShiYXNlLnZhbHVlLCBjaGVja0N0eCk7CiAgICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgUHJvbWlzZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFzeW5jaHJvbm91cyB0cmFuc2Zvcm0gZW5jb3VudGVyZWQgZHVyaW5nIHN5bmNocm9ub3VzIHBhcnNlIG9wZXJhdGlvbi4gVXNlIC5wYXJzZUFzeW5jIGluc3RlYWQuYCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IHJlc3VsdCB9OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VBc3luYyh7IGRhdGE6IGN0eC5kYXRhLCBwYXRoOiBjdHgucGF0aCwgcGFyZW50OiBjdHggfSkudGhlbigoYmFzZSkgPT4gewogICAgICAgICAgICBpZiAoIWlzVmFsaWQoYmFzZSkpCiAgICAgICAgICAgICAgcmV0dXJuIGJhc2U7CiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZWZmZWN0LnRyYW5zZm9ybShiYXNlLnZhbHVlLCBjaGVja0N0eCkpLnRoZW4oKHJlc3VsdCkgPT4gKHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiByZXN1bHQgfSkpOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoZWZmZWN0KTsKICAgIH0KICB9CiAgWm9kRWZmZWN0cy5jcmVhdGUgPSAoc2NoZW1hLCBlZmZlY3QsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RFZmZlY3RzKHsKICAgICAgc2NoZW1hLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMsCiAgICAgIGVmZmVjdCwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIFpvZEVmZmVjdHMuY3JlYXRlV2l0aFByZXByb2Nlc3MgPSAocHJlcHJvY2Vzcywgc2NoZW1hLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kRWZmZWN0cyh7CiAgICAgIHNjaGVtYSwKICAgICAgZWZmZWN0OiB7IHR5cGU6ICJwcmVwcm9jZXNzIiwgdHJhbnNmb3JtOiBwcmVwcm9jZXNzIH0sCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRWZmZWN0cywKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE9wdGlvbmFsIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS51bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gT0sodm9pZCAwKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZS5fcGFyc2UoaW5wdXQpOwogICAgfQogICAgdW53cmFwKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZTsKICAgIH0KICB9CiAgWm9kT3B0aW9uYWwuY3JlYXRlID0gKHR5cGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RPcHRpb25hbCh7CiAgICAgIGlubmVyVHlwZTogdHlwZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPcHRpb25hbCwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE51bGxhYmxlIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS5udWxsKSB7CiAgICAgICAgcmV0dXJuIE9LKG51bGwpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLl9kZWYuaW5uZXJUeXBlLl9wYXJzZShpbnB1dCk7CiAgICB9CiAgICB1bndyYXAoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYuaW5uZXJUeXBlOwogICAgfQogIH0KICBab2ROdWxsYWJsZS5jcmVhdGUgPSAodHlwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE51bGxhYmxlKHsKICAgICAgaW5uZXJUeXBlOiB0eXBlLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE51bGxhYmxlLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kRGVmYXVsdCBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBsZXQgZGF0YSA9IGN0eC5kYXRhOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgPT09IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkKSB7CiAgICAgICAgZGF0YSA9IHRoaXMuX2RlZi5kZWZhdWx0VmFsdWUoKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZS5fcGFyc2UoewogICAgICAgIGRhdGEsCiAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgcGFyZW50OiBjdHgKICAgICAgfSk7CiAgICB9CiAgICByZW1vdmVEZWZhdWx0KCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZTsKICAgIH0KICB9CiAgWm9kRGVmYXVsdC5jcmVhdGUgPSAodHlwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZERlZmF1bHQoewogICAgICBpbm5lclR5cGU6IHR5cGUsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRGVmYXVsdCwKICAgICAgZGVmYXVsdFZhbHVlOiB0eXBlb2YgcGFyYW1zLmRlZmF1bHQgPT09ICJmdW5jdGlvbiIgPyBwYXJhbXMuZGVmYXVsdCA6ICgpID0+IHBhcmFtcy5kZWZhdWx0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kQ2F0Y2ggZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgY29uc3QgbmV3Q3R4ID0gewogICAgICAgIC4uLmN0eCwKICAgICAgICBjb21tb246IHsKICAgICAgICAgIC4uLmN0eC5jb21tb24sCiAgICAgICAgICBpc3N1ZXM6IFtdCiAgICAgICAgfQogICAgICB9OwogICAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9kZWYuaW5uZXJUeXBlLl9wYXJzZSh7CiAgICAgICAgZGF0YTogbmV3Q3R4LmRhdGEsCiAgICAgICAgcGF0aDogbmV3Q3R4LnBhdGgsCiAgICAgICAgcGFyZW50OiB7CiAgICAgICAgICAuLi5uZXdDdHgKICAgICAgICB9CiAgICAgIH0pOwogICAgICBpZiAoaXNBc3luYyhyZXN1bHQpKSB7CiAgICAgICAgcmV0dXJuIHJlc3VsdC50aGVuKChyZXN1bHQyKSA9PiB7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBzdGF0dXM6ICJ2YWxpZCIsCiAgICAgICAgICAgIHZhbHVlOiByZXN1bHQyLnN0YXR1cyA9PT0gInZhbGlkIiA/IHJlc3VsdDIudmFsdWUgOiB0aGlzLl9kZWYuY2F0Y2hWYWx1ZSh7CiAgICAgICAgICAgICAgZ2V0IGVycm9yKCkgewogICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBab2RFcnJvcihuZXdDdHguY29tbW9uLmlzc3Vlcyk7CiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICBpbnB1dDogbmV3Q3R4LmRhdGEKICAgICAgICAgICAgfSkKICAgICAgICAgIH07CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHN0YXR1czogInZhbGlkIiwKICAgICAgICAgIHZhbHVlOiByZXN1bHQuc3RhdHVzID09PSAidmFsaWQiID8gcmVzdWx0LnZhbHVlIDogdGhpcy5fZGVmLmNhdGNoVmFsdWUoewogICAgICAgICAgICBnZXQgZXJyb3IoKSB7CiAgICAgICAgICAgICAgcmV0dXJuIG5ldyBab2RFcnJvcihuZXdDdHguY29tbW9uLmlzc3Vlcyk7CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGlucHV0OiBuZXdDdHguZGF0YQogICAgICAgICAgfSkKICAgICAgICB9OwogICAgICB9CiAgICB9CiAgICByZW1vdmVDYXRjaCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5pbm5lclR5cGU7CiAgICB9CiAgfQogIFpvZENhdGNoLmNyZWF0ZSA9ICh0eXBlLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kQ2F0Y2goewogICAgICBpbm5lclR5cGU6IHR5cGUsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kQ2F0Y2gsCiAgICAgIGNhdGNoVmFsdWU6IHR5cGVvZiBwYXJhbXMuY2F0Y2ggPT09ICJmdW5jdGlvbiIgPyBwYXJhbXMuY2F0Y2ggOiAoKSA9PiBwYXJhbXMuY2F0Y2gsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2ROYU4gZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm5hbikgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5uYW4sCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6ICJ2YWxpZCIsIHZhbHVlOiBpbnB1dC5kYXRhIH07CiAgICB9CiAgfQogIFpvZE5hTi5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE5hTih7CiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kTmFOLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY29uc3QgQlJBTkQgPSBTeW1ib2woInpvZF9icmFuZCIpOwogIGNsYXNzIFpvZEJyYW5kZWQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgY29uc3QgZGF0YSA9IGN0eC5kYXRhOwogICAgICByZXR1cm4gdGhpcy5fZGVmLnR5cGUuX3BhcnNlKHsKICAgICAgICBkYXRhLAogICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgIHBhcmVudDogY3R4CiAgICAgIH0pOwogICAgfQogICAgdW53cmFwKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnR5cGU7CiAgICB9CiAgfQogIGNsYXNzIFpvZFBpcGVsaW5lIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICBjb25zdCBoYW5kbGVBc3luYyA9IGFzeW5jICgpID0+IHsKICAgICAgICAgIGNvbnN0IGluUmVzdWx0ID0gYXdhaXQgdGhpcy5fZGVmLmluLl9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAoaW5SZXN1bHQuc3RhdHVzID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgaWYgKGluUmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikgewogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgICAgcmV0dXJuIERJUlRZKGluUmVzdWx0LnZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kZWYub3V0Ll9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgICBkYXRhOiBpblJlc3VsdC52YWx1ZSwKICAgICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHJldHVybiBoYW5kbGVBc3luYygpOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGluUmVzdWx0ID0gdGhpcy5fZGVmLmluLl9wYXJzZVN5bmMoewogICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgfSk7CiAgICAgICAgaWYgKGluUmVzdWx0LnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgaWYgKGluUmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikgewogICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBzdGF0dXM6ICJkaXJ0eSIsCiAgICAgICAgICAgIHZhbHVlOiBpblJlc3VsdC52YWx1ZQogICAgICAgICAgfTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi5vdXQuX3BhcnNlU3luYyh7CiAgICAgICAgICAgIGRhdGE6IGluUmVzdWx0LnZhbHVlLAogICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgc3RhdGljIGNyZWF0ZShhMiwgYikgewogICAgICByZXR1cm4gbmV3IFpvZFBpcGVsaW5lKHsKICAgICAgICBpbjogYTIsCiAgICAgICAgb3V0OiBiLAogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kUGlwZWxpbmUKICAgICAgfSk7CiAgICB9CiAgfQogIGNsYXNzIFpvZFJlYWRvbmx5IGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fZGVmLmlubmVyVHlwZS5fcGFyc2UoaW5wdXQpOwogICAgICBjb25zdCBmcmVlemUgPSAoZGF0YSkgPT4gewogICAgICAgIGlmIChpc1ZhbGlkKGRhdGEpKSB7CiAgICAgICAgICBkYXRhLnZhbHVlID0gT2JqZWN0LmZyZWV6ZShkYXRhLnZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGRhdGE7CiAgICAgIH07CiAgICAgIHJldHVybiBpc0FzeW5jKHJlc3VsdCkgPyByZXN1bHQudGhlbigoZGF0YSkgPT4gZnJlZXplKGRhdGEpKSA6IGZyZWV6ZShyZXN1bHQpOwogICAgfQogICAgdW53cmFwKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZTsKICAgIH0KICB9CiAgWm9kUmVhZG9ubHkuY3JlYXRlID0gKHR5cGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RSZWFkb25seSh7CiAgICAgIGlubmVyVHlwZTogdHlwZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RSZWFkb25seSwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGZ1bmN0aW9uIGN1c3RvbShjaGVjaywgcGFyYW1zID0ge30sIGZhdGFsKSB7CiAgICBpZiAoY2hlY2spCiAgICAgIHJldHVybiBab2RBbnkuY3JlYXRlKCkuc3VwZXJSZWZpbmUoKGRhdGEsIGN0eCkgPT4gewogICAgICAgIHZhciBfYSwgX2I7CiAgICAgICAgaWYgKCFjaGVjayhkYXRhKSkgewogICAgICAgICAgY29uc3QgcCA9IHR5cGVvZiBwYXJhbXMgPT09ICJmdW5jdGlvbiIgPyBwYXJhbXMoZGF0YSkgOiB0eXBlb2YgcGFyYW1zID09PSAic3RyaW5nIiA/IHsgbWVzc2FnZTogcGFyYW1zIH0gOiBwYXJhbXM7CiAgICAgICAgICBjb25zdCBfZmF0YWwgPSAoX2IgPSAoX2EgPSBwLmZhdGFsKSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiBmYXRhbCkgIT09IG51bGwgJiYgX2IgIT09IHZvaWQgMCA/IF9iIDogdHJ1ZTsKICAgICAgICAgIGNvbnN0IHAyID0gdHlwZW9mIHAgPT09ICJzdHJpbmciID8geyBtZXNzYWdlOiBwIH0gOiBwOwogICAgICAgICAgY3R4LmFkZElzc3VlKHsgY29kZTogImN1c3RvbSIsIC4uLnAyLCBmYXRhbDogX2ZhdGFsIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICByZXR1cm4gWm9kQW55LmNyZWF0ZSgpOwogIH0KICBjb25zdCBsYXRlID0gewogICAgb2JqZWN0OiBab2RPYmplY3QubGF6eWNyZWF0ZQogIH07CiAgdmFyIFpvZEZpcnN0UGFydHlUeXBlS2luZDsKICAoZnVuY3Rpb24oWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMikgewogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kU3RyaW5nIl0gPSAiWm9kU3RyaW5nIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE51bWJlciJdID0gIlpvZE51bWJlciI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2ROYU4iXSA9ICJab2ROYU4iOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQmlnSW50Il0gPSAiWm9kQmlnSW50IjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZEJvb2xlYW4iXSA9ICJab2RCb29sZWFuIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZERhdGUiXSA9ICJab2REYXRlIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFN5bWJvbCJdID0gIlpvZFN5bWJvbCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RVbmRlZmluZWQiXSA9ICJab2RVbmRlZmluZWQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kTnVsbCJdID0gIlpvZE51bGwiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQW55Il0gPSAiWm9kQW55IjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFVua25vd24iXSA9ICJab2RVbmtub3duIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE5ldmVyIl0gPSAiWm9kTmV2ZXIiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kVm9pZCJdID0gIlpvZFZvaWQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQXJyYXkiXSA9ICJab2RBcnJheSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RPYmplY3QiXSA9ICJab2RPYmplY3QiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kVW5pb24iXSA9ICJab2RVbmlvbiI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2REaXNjcmltaW5hdGVkVW5pb24iXSA9ICJab2REaXNjcmltaW5hdGVkVW5pb24iOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kSW50ZXJzZWN0aW9uIl0gPSAiWm9kSW50ZXJzZWN0aW9uIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFR1cGxlIl0gPSAiWm9kVHVwbGUiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kUmVjb3JkIl0gPSAiWm9kUmVjb3JkIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE1hcCJdID0gIlpvZE1hcCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RTZXQiXSA9ICJab2RTZXQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kRnVuY3Rpb24iXSA9ICJab2RGdW5jdGlvbiI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RMYXp5Il0gPSAiWm9kTGF6eSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RMaXRlcmFsIl0gPSAiWm9kTGl0ZXJhbCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RFbnVtIl0gPSAiWm9kRW51bSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RFZmZlY3RzIl0gPSAiWm9kRWZmZWN0cyI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2ROYXRpdmVFbnVtIl0gPSAiWm9kTmF0aXZlRW51bSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RPcHRpb25hbCJdID0gIlpvZE9wdGlvbmFsIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE51bGxhYmxlIl0gPSAiWm9kTnVsbGFibGUiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kRGVmYXVsdCJdID0gIlpvZERlZmF1bHQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQ2F0Y2giXSA9ICJab2RDYXRjaCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RQcm9taXNlIl0gPSAiWm9kUHJvbWlzZSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RCcmFuZGVkIl0gPSAiWm9kQnJhbmRlZCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RQaXBlbGluZSJdID0gIlpvZFBpcGVsaW5lIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFJlYWRvbmx5Il0gPSAiWm9kUmVhZG9ubHkiOwogIH0pKFpvZEZpcnN0UGFydHlUeXBlS2luZCB8fCAoWm9kRmlyc3RQYXJ0eVR5cGVLaW5kID0ge30pKTsKICBjb25zdCBpbnN0YW5jZU9mVHlwZSA9IChjbHMsIHBhcmFtcyA9IHsKICAgIG1lc3NhZ2U6IGBJbnB1dCBub3QgaW5zdGFuY2Ugb2YgJHtjbHMubmFtZX1gCiAgfSkgPT4gY3VzdG9tKChkYXRhKSA9PiBkYXRhIGluc3RhbmNlb2YgY2xzLCBwYXJhbXMpOwogIGNvbnN0IHN0cmluZ1R5cGUgPSBab2RTdHJpbmcuY3JlYXRlOwogIGNvbnN0IG51bWJlclR5cGUgPSBab2ROdW1iZXIuY3JlYXRlOwogIGNvbnN0IG5hblR5cGUgPSBab2ROYU4uY3JlYXRlOwogIGNvbnN0IGJpZ0ludFR5cGUgPSBab2RCaWdJbnQuY3JlYXRlOwogIGNvbnN0IGJvb2xlYW5UeXBlID0gWm9kQm9vbGVhbi5jcmVhdGU7CiAgY29uc3QgZGF0ZVR5cGUgPSBab2REYXRlLmNyZWF0ZTsKICBjb25zdCBzeW1ib2xUeXBlID0gWm9kU3ltYm9sLmNyZWF0ZTsKICBjb25zdCB1bmRlZmluZWRUeXBlID0gWm9kVW5kZWZpbmVkLmNyZWF0ZTsKICBjb25zdCBudWxsVHlwZSA9IFpvZE51bGwuY3JlYXRlOwogIGNvbnN0IGFueVR5cGUgPSBab2RBbnkuY3JlYXRlOwogIGNvbnN0IHVua25vd25UeXBlID0gWm9kVW5rbm93bi5jcmVhdGU7CiAgY29uc3QgbmV2ZXJUeXBlID0gWm9kTmV2ZXIuY3JlYXRlOwogIGNvbnN0IHZvaWRUeXBlID0gWm9kVm9pZC5jcmVhdGU7CiAgY29uc3QgYXJyYXlUeXBlID0gWm9kQXJyYXkuY3JlYXRlOwogIGNvbnN0IG9iamVjdFR5cGUgPSBab2RPYmplY3QuY3JlYXRlOwogIGNvbnN0IHN0cmljdE9iamVjdFR5cGUgPSBab2RPYmplY3Quc3RyaWN0Q3JlYXRlOwogIGNvbnN0IHVuaW9uVHlwZSA9IFpvZFVuaW9uLmNyZWF0ZTsKICBjb25zdCBkaXNjcmltaW5hdGVkVW5pb25UeXBlID0gWm9kRGlzY3JpbWluYXRlZFVuaW9uLmNyZWF0ZTsKICBjb25zdCBpbnRlcnNlY3Rpb25UeXBlID0gWm9kSW50ZXJzZWN0aW9uLmNyZWF0ZTsKICBjb25zdCB0dXBsZVR5cGUgPSBab2RUdXBsZS5jcmVhdGU7CiAgY29uc3QgcmVjb3JkVHlwZSA9IFpvZFJlY29yZC5jcmVhdGU7CiAgY29uc3QgbWFwVHlwZSA9IFpvZE1hcC5jcmVhdGU7CiAgY29uc3Qgc2V0VHlwZSA9IFpvZFNldC5jcmVhdGU7CiAgY29uc3QgZnVuY3Rpb25UeXBlID0gWm9kRnVuY3Rpb24uY3JlYXRlOwogIGNvbnN0IGxhenlUeXBlID0gWm9kTGF6eS5jcmVhdGU7CiAgY29uc3QgbGl0ZXJhbFR5cGUgPSBab2RMaXRlcmFsLmNyZWF0ZTsKICBjb25zdCBlbnVtVHlwZSA9IFpvZEVudW0uY3JlYXRlOwogIGNvbnN0IG5hdGl2ZUVudW1UeXBlID0gWm9kTmF0aXZlRW51bS5jcmVhdGU7CiAgY29uc3QgcHJvbWlzZVR5cGUgPSBab2RQcm9taXNlLmNyZWF0ZTsKICBjb25zdCBlZmZlY3RzVHlwZSA9IFpvZEVmZmVjdHMuY3JlYXRlOwogIGNvbnN0IG9wdGlvbmFsVHlwZSA9IFpvZE9wdGlvbmFsLmNyZWF0ZTsKICBjb25zdCBudWxsYWJsZVR5cGUgPSBab2ROdWxsYWJsZS5jcmVhdGU7CiAgY29uc3QgcHJlcHJvY2Vzc1R5cGUgPSBab2RFZmZlY3RzLmNyZWF0ZVdpdGhQcmVwcm9jZXNzOwogIGNvbnN0IHBpcGVsaW5lVHlwZSA9IFpvZFBpcGVsaW5lLmNyZWF0ZTsKICBjb25zdCBvc3RyaW5nID0gKCkgPT4gc3RyaW5nVHlwZSgpLm9wdGlvbmFsKCk7CiAgY29uc3Qgb251bWJlciA9ICgpID0+IG51bWJlclR5cGUoKS5vcHRpb25hbCgpOwogIGNvbnN0IG9ib29sZWFuID0gKCkgPT4gYm9vbGVhblR5cGUoKS5vcHRpb25hbCgpOwogIGNvbnN0IGNvZXJjZSA9IHsKICAgIHN0cmluZzogKGFyZykgPT4gWm9kU3RyaW5nLmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pLAogICAgbnVtYmVyOiAoYXJnKSA9PiBab2ROdW1iZXIuY3JlYXRlKHsgLi4uYXJnLCBjb2VyY2U6IHRydWUgfSksCiAgICBib29sZWFuOiAoYXJnKSA9PiBab2RCb29sZWFuLmNyZWF0ZSh7CiAgICAgIC4uLmFyZywKICAgICAgY29lcmNlOiB0cnVlCiAgICB9KSwKICAgIGJpZ2ludDogKGFyZykgPT4gWm9kQmlnSW50LmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pLAogICAgZGF0ZTogKGFyZykgPT4gWm9kRGF0ZS5jcmVhdGUoeyAuLi5hcmcsIGNvZXJjZTogdHJ1ZSB9KQogIH07CiAgY29uc3QgTkVWRVIgPSBJTlZBTElEOwogIHZhciB6JDEgPSAvKiBAX19QVVJFX18gKi8gT2JqZWN0LmZyZWV6ZSh7CiAgICBfX3Byb3RvX186IG51bGwsCiAgICBkZWZhdWx0RXJyb3JNYXA6IGVycm9yTWFwLAogICAgc2V0RXJyb3JNYXAsCiAgICBnZXRFcnJvck1hcCwKICAgIG1ha2VJc3N1ZSwKICAgIEVNUFRZX1BBVEgsCiAgICBhZGRJc3N1ZVRvQ29udGV4dCwKICAgIFBhcnNlU3RhdHVzLAogICAgSU5WQUxJRCwKICAgIERJUlRZLAogICAgT0ssCiAgICBpc0Fib3J0ZWQsCiAgICBpc0RpcnR5LAogICAgaXNWYWxpZCwKICAgIGlzQXN5bmMsCiAgICBnZXQgdXRpbCgpIHsKICAgICAgcmV0dXJuIHV0aWw7CiAgICB9LAogICAgZ2V0IG9iamVjdFV0aWwoKSB7CiAgICAgIHJldHVybiBvYmplY3RVdGlsOwogICAgfSwKICAgIFpvZFBhcnNlZFR5cGUsCiAgICBnZXRQYXJzZWRUeXBlLAogICAgWm9kVHlwZSwKICAgIGRhdGV0aW1lUmVnZXgsCiAgICBab2RTdHJpbmcsCiAgICBab2ROdW1iZXIsCiAgICBab2RCaWdJbnQsCiAgICBab2RCb29sZWFuLAogICAgWm9kRGF0ZSwKICAgIFpvZFN5bWJvbCwKICAgIFpvZFVuZGVmaW5lZCwKICAgIFpvZE51bGwsCiAgICBab2RBbnksCiAgICBab2RVbmtub3duLAogICAgWm9kTmV2ZXIsCiAgICBab2RWb2lkLAogICAgWm9kQXJyYXksCiAgICBab2RPYmplY3QsCiAgICBab2RVbmlvbiwKICAgIFpvZERpc2NyaW1pbmF0ZWRVbmlvbiwKICAgIFpvZEludGVyc2VjdGlvbiwKICAgIFpvZFR1cGxlLAogICAgWm9kUmVjb3JkLAogICAgWm9kTWFwLAogICAgWm9kU2V0LAogICAgWm9kRnVuY3Rpb24sCiAgICBab2RMYXp5LAogICAgWm9kTGl0ZXJhbCwKICAgIFpvZEVudW0sCiAgICBab2ROYXRpdmVFbnVtLAogICAgWm9kUHJvbWlzZSwKICAgIFpvZEVmZmVjdHMsCiAgICBab2RUcmFuc2Zvcm1lcjogWm9kRWZmZWN0cywKICAgIFpvZE9wdGlvbmFsLAogICAgWm9kTnVsbGFibGUsCiAgICBab2REZWZhdWx0LAogICAgWm9kQ2F0Y2gsCiAgICBab2ROYU4sCiAgICBCUkFORCwKICAgIFpvZEJyYW5kZWQsCiAgICBab2RQaXBlbGluZSwKICAgIFpvZFJlYWRvbmx5LAogICAgY3VzdG9tLAogICAgU2NoZW1hOiBab2RUeXBlLAogICAgWm9kU2NoZW1hOiBab2RUeXBlLAogICAgbGF0ZSwKICAgIGdldCBab2RGaXJzdFBhcnR5VHlwZUtpbmQoKSB7CiAgICAgIHJldHVybiBab2RGaXJzdFBhcnR5VHlwZUtpbmQ7CiAgICB9LAogICAgY29lcmNlLAogICAgYW55OiBhbnlUeXBlLAogICAgYXJyYXk6IGFycmF5VHlwZSwKICAgIGJpZ2ludDogYmlnSW50VHlwZSwKICAgIGJvb2xlYW46IGJvb2xlYW5UeXBlLAogICAgZGF0ZTogZGF0ZVR5cGUsCiAgICBkaXNjcmltaW5hdGVkVW5pb246IGRpc2NyaW1pbmF0ZWRVbmlvblR5cGUsCiAgICBlZmZlY3Q6IGVmZmVjdHNUeXBlLAogICAgImVudW0iOiBlbnVtVHlwZSwKICAgICJmdW5jdGlvbiI6IGZ1bmN0aW9uVHlwZSwKICAgICJpbnN0YW5jZW9mIjogaW5zdGFuY2VPZlR5cGUsCiAgICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvblR5cGUsCiAgICBsYXp5OiBsYXp5VHlwZSwKICAgIGxpdGVyYWw6IGxpdGVyYWxUeXBlLAogICAgbWFwOiBtYXBUeXBlLAogICAgbmFuOiBuYW5UeXBlLAogICAgbmF0aXZlRW51bTogbmF0aXZlRW51bVR5cGUsCiAgICBuZXZlcjogbmV2ZXJUeXBlLAogICAgIm51bGwiOiBudWxsVHlwZSwKICAgIG51bGxhYmxlOiBudWxsYWJsZVR5cGUsCiAgICBudW1iZXI6IG51bWJlclR5cGUsCiAgICBvYmplY3Q6IG9iamVjdFR5cGUsCiAgICBvYm9vbGVhbiwKICAgIG9udW1iZXIsCiAgICBvcHRpb25hbDogb3B0aW9uYWxUeXBlLAogICAgb3N0cmluZywKICAgIHBpcGVsaW5lOiBwaXBlbGluZVR5cGUsCiAgICBwcmVwcm9jZXNzOiBwcmVwcm9jZXNzVHlwZSwKICAgIHByb21pc2U6IHByb21pc2VUeXBlLAogICAgcmVjb3JkOiByZWNvcmRUeXBlLAogICAgc2V0OiBzZXRUeXBlLAogICAgc3RyaWN0T2JqZWN0OiBzdHJpY3RPYmplY3RUeXBlLAogICAgc3RyaW5nOiBzdHJpbmdUeXBlLAogICAgc3ltYm9sOiBzeW1ib2xUeXBlLAogICAgdHJhbnNmb3JtZXI6IGVmZmVjdHNUeXBlLAogICAgdHVwbGU6IHR1cGxlVHlwZSwKICAgICJ1bmRlZmluZWQiOiB1bmRlZmluZWRUeXBlLAogICAgdW5pb246IHVuaW9uVHlwZSwKICAgIHVua25vd246IHVua25vd25UeXBlLAogICAgInZvaWQiOiB2b2lkVHlwZSwKICAgIE5FVkVSLAogICAgWm9kSXNzdWVDb2RlLAogICAgcXVvdGVsZXNzSnNvbiwKICAgIFpvZEVycm9yCiAgfSk7CiAgeiQxLm9iamVjdCh7CiAgICBudWNsZW90aWRlU2VxdWVuY2VzOiB6JDEuYXJyYXkoCiAgICAgIHokMS5vYmplY3QoewogICAgICAgIG5hbWU6IHokMS5zdHJpbmcoKSwKICAgICAgICBzZXF1ZW5jZTogeiQxLnN0cmluZygpCiAgICAgIH0pCiAgICApLAogICAgZ2VuZXM6IHokMS5hcnJheSgKICAgICAgeiQxLm9iamVjdCh7CiAgICAgICAgbmFtZTogeiQxLnN0cmluZygpLAogICAgICAgIHNlcXVlbmNlOiB6JDEuc3RyaW5nKCkKICAgICAgfSkKICAgICkKICB9KTsKICBjb25zdCBvcmRlckJ5VHlwZSA9IHokMS5lbnVtKFsiYXNjZW5kaW5nIiwgImRlc2NlbmRpbmciXSk7CiAgY29uc3Qgb3JkZXJCeSA9IHokMS5vYmplY3QoewogICAgZmllbGQ6IHokMS5zdHJpbmcoKSwKICAgIHR5cGU6IG9yZGVyQnlUeXBlCiAgfSk7CiAgY29uc3QgbGFwaXNCYXNlUmVxdWVzdCA9IHokMS5vYmplY3QoewogICAgbGltaXQ6IHokMS5udW1iZXIoKS5vcHRpb25hbCgpLAogICAgb2Zmc2V0OiB6JDEubnVtYmVyKCkub3B0aW9uYWwoKSwKICAgIGZpZWxkczogeiQxLmFycmF5KHokMS5zdHJpbmcoKSkub3B0aW9uYWwoKSwKICAgIG9yZGVyQnk6IHokMS5hcnJheShvcmRlckJ5KS5vcHRpb25hbCgpCiAgfSkuY2F0Y2hhbGwoeiQxLnVuaW9uKFt6JDEuYm9vbGVhbigpLCB6JDEudW5kZWZpbmVkKCksIHokMS5zdHJpbmcoKSwgeiQxLm51bWJlcigpLCB6JDEubnVsbCgpLCB6JDEuYXJyYXkoeiQxLnN0cmluZygpKV0pKTsKICBsYXBpc0Jhc2VSZXF1ZXN0LmV4dGVuZCh7IG1pblByb3BvcnRpb246IHokMS5udW1iZXIoKS5vcHRpb25hbCgpIH0pOwogIGNvbnN0IG11dGF0aW9uUHJvcG9ydGlvbkNvdW50ID0geiQxLm9iamVjdCh7CiAgICBtdXRhdGlvbjogeiQxLnN0cmluZygpLAogICAgcHJvcG9ydGlvbjogeiQxLm51bWJlcigpLAogICAgY291bnQ6IHokMS5udW1iZXIoKSwKICAgIHNlcXVlbmNlTmFtZTogeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udWxsKCldKSwKICAgIG11dGF0aW9uRnJvbTogeiQxLnN0cmluZygpLAogICAgbXV0YXRpb25UbzogeiQxLnN0cmluZygpLAogICAgcG9zaXRpb246IHokMS5udW1iZXIoKQogIH0pOwogIGNvbnN0IG11dGF0aW9uc1Jlc3BvbnNlID0gbWFrZUxhcGlzUmVzcG9uc2UoeiQxLmFycmF5KG11dGF0aW9uUHJvcG9ydGlvbkNvdW50KSk7CiAgY29uc3QgaW5zZXJ0aW9uQ291bnQgPSB6JDEub2JqZWN0KHsKICAgIGluc2VydGlvbjogeiQxLnN0cmluZygpLAogICAgY291bnQ6IHokMS5udW1iZXIoKSwKICAgIGluc2VydGVkU3ltYm9sczogeiQxLnN0cmluZygpLAogICAgcG9zaXRpb246IHokMS5udW1iZXIoKSwKICAgIHNlcXVlbmNlTmFtZTogeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udWxsKCldKQogIH0pOwogIG1ha2VMYXBpc1Jlc3BvbnNlKHokMS5hcnJheShpbnNlcnRpb25Db3VudCkpOwogIGNvbnN0IGFnZ3JlZ2F0ZWRJdGVtID0geiQxLm9iamVjdCh7IGNvdW50OiB6JDEubnVtYmVyKCkgfSkuY2F0Y2hhbGwoeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udW1iZXIoKSwgeiQxLm51bGwoKV0pKTsKICBjb25zdCBhZ2dyZWdhdGVkUmVzcG9uc2UgPSBtYWtlTGFwaXNSZXNwb25zZSh6JDEuYXJyYXkoYWdncmVnYXRlZEl0ZW0pKTsKICBmdW5jdGlvbiBtYWtlTGFwaXNSZXNwb25zZShkYXRhKSB7CiAgICByZXR1cm4geiQxLm9iamVjdCh7CiAgICAgIGRhdGEKICAgIH0pOwogIH0KICBjb25zdCBwcm9ibGVtRGV0YWlsID0geiQxLm9iamVjdCh7CiAgICB0aXRsZTogeiQxLnN0cmluZygpLm9wdGlvbmFsKCksCiAgICBzdGF0dXM6IHokMS5udW1iZXIoKSwKICAgIGRldGFpbDogeiQxLnN0cmluZygpLm9wdGlvbmFsKCksCiAgICB0eXBlOiB6JDEuc3RyaW5nKCksCiAgICBpbnN0YW5jZTogeiQxLnN0cmluZygpLm9wdGlvbmFsKCkKICB9KTsKICBjb25zdCBsYXBpc0Vycm9yID0geiQxLm9iamVjdCh7CiAgICBlcnJvcjogcHJvYmxlbURldGFpbAogIH0pOwogIGNsYXNzIFVua25vd25MYXBpc0Vycm9yIGV4dGVuZHMgRXJyb3IgewogICAgY29uc3RydWN0b3IobWVzc2FnZSwgc3RhdHVzLCByZXF1ZXN0ZWREYXRhKSB7CiAgICAgIHN1cGVyKG1lc3NhZ2UpOwogICAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgICAgdGhpcy5yZXF1ZXN0ZWREYXRhID0gcmVxdWVzdGVkRGF0YTsKICAgICAgdGhpcy5uYW1lID0gIlVua25vd25MYXBpc0Vycm9yIjsKICAgIH0KICB9CiAgY2xhc3MgTGFwaXNFcnJvciBleHRlbmRzIEVycm9yIHsKICAgIGNvbnN0cnVjdG9yKG1lc3NhZ2UsIHN0YXR1cywgcHJvYmxlbURldGFpbDIsIHJlcXVlc3RlZERhdGEpIHsKICAgICAgc3VwZXIobWVzc2FnZSk7CiAgICAgIHRoaXMuc3RhdHVzID0gc3RhdHVzOwogICAgICB0aGlzLnByb2JsZW1EZXRhaWwgPSBwcm9ibGVtRGV0YWlsMjsKICAgICAgdGhpcy5yZXF1ZXN0ZWREYXRhID0gcmVxdWVzdGVkRGF0YTsKICAgICAgdGhpcy5uYW1lID0gIkxhcGlzRXJyb3IiOwogICAgfQogIH0KICBhc3luYyBmdW5jdGlvbiBmZXRjaEFnZ3JlZ2F0ZWQobGFwaXNVcmwsIGJvZHksIHNpZ25hbCkgewogICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChhZ2dyZWdhdGVkRW5kcG9pbnQobGFwaXNVcmwpLCB7CiAgICAgIG1ldGhvZDogIlBPU1QiLAogICAgICBoZWFkZXJzOiB7CiAgICAgICAgIkNvbnRlbnQtVHlwZSI6ICJhcHBsaWNhdGlvbi9qc29uIgogICAgICB9LAogICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShib2R5KSwKICAgICAgc2lnbmFsCiAgICB9KTsKICAgIGF3YWl0IGhhbmRsZUVycm9ycyhyZXNwb25zZSwgImFnZ3JlZ2F0ZWQgZGF0YSIpOwogICAgcmV0dXJuIGFnZ3JlZ2F0ZWRSZXNwb25zZS5wYXJzZShhd2FpdCByZXNwb25zZS5qc29uKCkpOwogIH0KICBhc3luYyBmdW5jdGlvbiBmZXRjaFN1YnN0aXR1dGlvbnNPckRlbGV0aW9ucyhsYXBpc1VybCwgYm9keSwgc2VxdWVuY2VUeXBlLCBzaWduYWwpIHsKICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goc3Vic3RpdHV0aW9uc09yRGVsZXRpb25zRW5kcG9pbnQobGFwaXNVcmwsIHNlcXVlbmNlVHlwZSksIHsKICAgICAgbWV0aG9kOiAiUE9TVCIsCiAgICAgIGhlYWRlcnM6IHsKICAgICAgICAiQ29udGVudC1UeXBlIjogImFwcGxpY2F0aW9uL2pzb24iCiAgICAgIH0sCiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KGJvZHkpLAogICAgICBzaWduYWwKICAgIH0pOwogICAgYXdhaXQgaGFuZGxlRXJyb3JzKHJlc3BvbnNlLCBgJHtzZXF1ZW5jZVR5cGV9IG11dGF0aW9uc2ApOwogICAgcmV0dXJuIG11dGF0aW9uc1Jlc3BvbnNlLnBhcnNlKGF3YWl0IHJlc3BvbnNlLmpzb24oKSk7CiAgfQogIGNvbnN0IGhhbmRsZUVycm9ycyA9IGFzeW5jIChyZXNwb25zZSwgcmVxdWVzdGVkRGF0YSkgPT4gewogICAgaWYgKCFyZXNwb25zZS5vaykgewogICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID49IDQwMCAmJiByZXNwb25zZS5zdGF0dXMgPCA1MDApIHsKICAgICAgICBjb25zdCBqc29uID0gYXdhaXQgcmVzcG9uc2UuanNvbigpOwogICAgICAgIGNvbnN0IGxhcGlzRXJyb3JSZXN1bHQgPSBsYXBpc0Vycm9yLnNhZmVQYXJzZShqc29uKTsKICAgICAgICBpZiAobGFwaXNFcnJvclJlc3VsdC5zdWNjZXNzKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTGFwaXNFcnJvcigKICAgICAgICAgICAgcmVzcG9uc2Uuc3RhdHVzVGV4dCArIGxhcGlzRXJyb3JSZXN1bHQuZGF0YS5lcnJvci5kZXRhaWwsCiAgICAgICAgICAgIHJlc3BvbnNlLnN0YXR1cywKICAgICAgICAgICAgbGFwaXNFcnJvclJlc3VsdC5kYXRhLmVycm9yLAogICAgICAgICAgICByZXF1ZXN0ZWREYXRhCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBwcm9ibGVtRGV0YWlsUmVzdWx0ID0gcHJvYmxlbURldGFpbC5zYWZlUGFyc2UoanNvbik7CiAgICAgICAgaWYgKHByb2JsZW1EZXRhaWxSZXN1bHQuc3VjY2VzcykgewogICAgICAgICAgdGhyb3cgbmV3IExhcGlzRXJyb3IoCiAgICAgICAgICAgIHJlc3BvbnNlLnN0YXR1c1RleHQgKyBwcm9ibGVtRGV0YWlsUmVzdWx0LmRhdGEuZGV0YWlsLAogICAgICAgICAgICByZXNwb25zZS5zdGF0dXMsCiAgICAgICAgICAgIHByb2JsZW1EZXRhaWxSZXN1bHQuZGF0YSwKICAgICAgICAgICAgcmVxdWVzdGVkRGF0YQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgdGhyb3cgbmV3IFVua25vd25MYXBpc0Vycm9yKAogICAgICAgICAgYCR7cmVzcG9uc2Uuc3RhdHVzVGV4dH06ICR7SlNPTi5zdHJpbmdpZnkoanNvbil9YCwKICAgICAgICAgIHJlc3BvbnNlLnN0YXR1cywKICAgICAgICAgIHJlcXVlc3RlZERhdGEKICAgICAgICApOwogICAgICB9CiAgICAgIHRocm93IG5ldyBVbmtub3duTGFwaXNFcnJvcihgJHtyZXNwb25zZS5zdGF0dXNUZXh0fTogJHtyZXNwb25zZS5zdGF0dXN9YCwgcmVzcG9uc2Uuc3RhdHVzLCByZXF1ZXN0ZWREYXRhKTsKICAgIH0KICB9OwogIGNvbnN0IGFnZ3JlZ2F0ZWRFbmRwb2ludCA9IChsYXBpc1VybCkgPT4gYCR7bGFwaXNVcmx9L3NhbXBsZS9hZ2dyZWdhdGVkYDsKICBjb25zdCBzdWJzdGl0dXRpb25zT3JEZWxldGlvbnNFbmRwb2ludCA9IChsYXBpc1VybCwgc2VxdWVuY2VUeXBlKSA9PiB7CiAgICByZXR1cm4gc2VxdWVuY2VUeXBlID09PSAiYW1pbm8gYWNpZCIgPyBgJHtsYXBpc1VybH0vc2FtcGxlL2FtaW5vQWNpZE11dGF0aW9uc2AgOiBgJHtsYXBpc1VybH0vc2FtcGxlL251Y2xlb3RpZGVNdXRhdGlvbnNgOwogIH07CiAgY2xhc3MgRmV0Y2hBZ2dyZWdhdGVkT3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoZmlsdGVyLCBmaWVsZHMgPSBbXSkgewogICAgICB0aGlzLmZpbHRlciA9IGZpbHRlcjsKICAgICAgdGhpcy5maWVsZHMgPSBmaWVsZHM7CiAgICB9CiAgICBhc3luYyBldmFsdWF0ZShsYXBpc1VybCwgc2lnbmFsKSB7CiAgICAgIGNvbnN0IGFnZ3JlZ2F0ZWRSZXNwb25zZTIgPSAoYXdhaXQgZmV0Y2hBZ2dyZWdhdGVkKAogICAgICAgIGxhcGlzVXJsLAogICAgICAgIHsKICAgICAgICAgIC4uLnRoaXMuZmlsdGVyLAogICAgICAgICAgZmllbGRzOiB0aGlzLmZpZWxkcwogICAgICAgIH0sCiAgICAgICAgc2lnbmFsCiAgICAgICkpLmRhdGE7CiAgICAgIGlmIChpc0ZpZWxkc0FycmF5V2l0aENvdW50KGFnZ3JlZ2F0ZWRSZXNwb25zZTIpKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGNvbnRlbnQ6IGFnZ3JlZ2F0ZWRSZXNwb25zZTIKICAgICAgICB9OwogICAgICB9CiAgICAgIHRocm93IG5ldyBFcnJvcigiQWdncmVnYXRlZCByZXNwb25zZSBkb2VzIG5vdCBoYXZlIGNvdW50Iik7CiAgICB9CiAgfQogIGZ1bmN0aW9uIGlzRmllbGRzQXJyYXlXaXRoQ291bnQoZGF0YSkgewogICAgcmV0dXJuIGRhdGEuZXZlcnkoKGl0ZW0pID0+IHR5cGVvZiBpdGVtID09PSAib2JqZWN0IiAmJiAiY291bnQiIGluIGl0ZW0gJiYgdHlwZW9mIGl0ZW0uY291bnQgPT09ICJudW1iZXIiKTsKICB9CiAgY2xhc3MgR3JvdXBCeU9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBmaWVsZCwgYWdncmVnYXRlKSB7CiAgICAgIHRoaXMuY2hpbGQgPSBjaGlsZDsKICAgICAgdGhpcy5maWVsZCA9IGZpZWxkOwogICAgICB0aGlzLmFnZ3JlZ2F0ZSA9IGFnZ3JlZ2F0ZTsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzLCBzaWduYWwpIHsKICAgICAgY29uc3QgY2hpbGRFdmFsdWF0ZWQgPSBhd2FpdCB0aGlzLmNoaWxkLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICBjb25zdCBncm91cGVkID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgZm9yIChjb25zdCByb3cgb2YgY2hpbGRFdmFsdWF0ZWQuY29udGVudCkgewogICAgICAgIGNvbnN0IGtleSA9IHJvd1t0aGlzLmZpZWxkXTsKICAgICAgICBpZiAoIWdyb3VwZWQuaGFzKGtleSkpIHsKICAgICAgICAgIGdyb3VwZWQuc2V0KGtleSwgW10pOwogICAgICAgIH0KICAgICAgICBncm91cGVkLmdldChrZXkpLnB1c2gocm93KTsKICAgICAgfQogICAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXkoKTsKICAgICAgZm9yIChjb25zdCBbLCB2YWx1ZXNdIG9mIGdyb3VwZWQpIHsKICAgICAgICByZXN1bHQucHVzaCh0aGlzLmFnZ3JlZ2F0ZSh2YWx1ZXMpKTsKICAgICAgfQogICAgICByZXR1cm4gewogICAgICAgIGNvbnRlbnQ6IHJlc3VsdAogICAgICB9OwogICAgfQogIH0KICBjbGFzcyBHcm91cEJ5QW5kU3VtT3BlcmF0b3IgZXh0ZW5kcyBHcm91cEJ5T3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoY2hpbGQsIGdyb3VwQnlGaWVsZCwgc3VtRmllbGQpIHsKICAgICAgc3VwZXIoY2hpbGQsIGdyb3VwQnlGaWVsZCwgKHZhbHVlcykgPT4gewogICAgICAgIGxldCBuID0gMDsKICAgICAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIHZhbHVlcykgewogICAgICAgICAgbiArPSB2YWx1ZVtzdW1GaWVsZF07CiAgICAgICAgfQogICAgICAgIHJldHVybiB7CiAgICAgICAgICBbZ3JvdXBCeUZpZWxkXTogdmFsdWVzWzBdW2dyb3VwQnlGaWVsZF0sCiAgICAgICAgICBbc3VtRmllbGRdOiBuCiAgICAgICAgfTsKICAgICAgfSk7CiAgICB9CiAgfQogIGNsYXNzIE1hcE9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBmdW5jKSB7CiAgICAgIHRoaXMuY2hpbGQgPSBjaGlsZDsKICAgICAgdGhpcy5mdW5jID0gZnVuYzsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzLCBzaWduYWwpIHsKICAgICAgY29uc3QgY2hpbGRFdmFsdWF0ZWQgPSBhd2FpdCB0aGlzLmNoaWxkLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICByZXR1cm4gewogICAgICAgIGNvbnRlbnQ6IGNoaWxkRXZhbHVhdGVkLmNvbnRlbnQubWFwKHRoaXMuZnVuYykKICAgICAgfTsKICAgIH0KICB9CiAgY2xhc3MgUmVuYW1lRmllbGRPcGVyYXRvciBleHRlbmRzIE1hcE9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBvbGRGaWVsZE5hbWUsIG5ld0ZpZWxkTmFtZSkgewogICAgICBzdXBlcigKICAgICAgICBjaGlsZCwKICAgICAgICAodmFsdWUpID0+ICh7CiAgICAgICAgICAuLi52YWx1ZSwKICAgICAgICAgIFtuZXdGaWVsZE5hbWVdOiB2YWx1ZVtvbGRGaWVsZE5hbWVdCiAgICAgICAgfSkKICAgICAgKTsKICAgIH0KICB9CiAgY2xhc3MgU29ydE9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBjb21wYXJlRm4pIHsKICAgICAgdGhpcy5jaGlsZCA9IGNoaWxkOwogICAgICB0aGlzLmNvbXBhcmVGbiA9IGNvbXBhcmVGbjsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzLCBzaWduYWwpIHsKICAgICAgY29uc3QgY2hpbGRFdmFsdWF0ZWQgPSBhd2FpdCB0aGlzLmNoaWxkLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICByZXR1cm4gewogICAgICAgIGNvbnRlbnQ6IGNoaWxkRXZhbHVhdGVkLmNvbnRlbnQuc29ydCh0aGlzLmNvbXBhcmVGbikKICAgICAgfTsKICAgIH0KICB9CiAgdmFyIFNFQ09ORFNfQV9NSU5VVEUgPSA2MDsKICB2YXIgU0VDT05EU19BX0hPVVIgPSBTRUNPTkRTX0FfTUlOVVRFICogNjA7CiAgdmFyIFNFQ09ORFNfQV9EQVkgPSBTRUNPTkRTX0FfSE9VUiAqIDI0OwogIHZhciBTRUNPTkRTX0FfV0VFSyA9IFNFQ09ORFNfQV9EQVkgKiA3OwogIHZhciBNSUxMSVNFQ09ORFNfQV9TRUNPTkQgPSAxZTM7CiAgdmFyIE1JTExJU0VDT05EU19BX01JTlVURSA9IFNFQ09ORFNfQV9NSU5VVEUgKiBNSUxMSVNFQ09ORFNfQV9TRUNPTkQ7CiAgdmFyIE1JTExJU0VDT05EU19BX0hPVVIgPSBTRUNPTkRTX0FfSE9VUiAqIE1JTExJU0VDT05EU19BX1NFQ09ORDsKICB2YXIgTUlMTElTRUNPTkRTX0FfREFZID0gU0VDT05EU19BX0RBWSAqIE1JTExJU0VDT05EU19BX1NFQ09ORDsKICB2YXIgTUlMTElTRUNPTkRTX0FfV0VFSyA9IFNFQ09ORFNfQV9XRUVLICogTUlMTElTRUNPTkRTX0FfU0VDT05EOwogIHZhciBNUyA9ICJtaWxsaXNlY29uZCI7CiAgdmFyIFMgPSAic2Vjb25kIjsKICB2YXIgTUlOID0gIm1pbnV0ZSI7CiAgdmFyIEggPSAiaG91ciI7CiAgdmFyIEQgPSAiZGF5IjsKICB2YXIgVyA9ICJ3ZWVrIjsKICB2YXIgTSA9ICJtb250aCI7CiAgdmFyIFEgPSAicXVhcnRlciI7CiAgdmFyIFkgPSAieWVhciI7CiAgdmFyIERBVEUgPSAiZGF0ZSI7CiAgdmFyIEZPUk1BVF9ERUZBVUxUID0gIllZWVktTU0tRERUSEg6bW06c3NaIjsKICB2YXIgSU5WQUxJRF9EQVRFX1NUUklORyA9ICJJbnZhbGlkIERhdGUiOwogIHZhciBSRUdFWF9QQVJTRSA9IC9eKFxkezR9KVstL10/KFxkezEsMn0pP1stL10/KFxkezAsMn0pW1R0XHNdKihcZHsxLDJ9KT86PyhcZHsxLDJ9KT86PyhcZHsxLDJ9KT9bLjpdPyhcZCspPyQvOwogIHZhciBSRUdFWF9GT1JNQVQgPSAvXFsoW15cXV0rKV18WXsxLDR9fE17MSw0fXxEezEsMn18ZHsxLDR9fEh7MSwyfXxoezEsMn18YXxBfG17MSwyfXxzezEsMn18WnsxLDJ9fFNTUy9nOwogIHZhciBlbiA9IHsKICAgIG5hbWU6ICJlbiIsCiAgICB3ZWVrZGF5czogIlN1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Ii5zcGxpdCgiXyIpLAogICAgbW9udGhzOiAiSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlciIuc3BsaXQoIl8iKSwKICAgIG9yZGluYWw6IGZ1bmN0aW9uIG9yZGluYWwobikgewogICAgICB2YXIgczIgPSBbInRoIiwgInN0IiwgIm5kIiwgInJkIl07CiAgICAgIHZhciB2MiA9IG4gJSAxMDA7CiAgICAgIHJldHVybiAiWyIgKyBuICsgKHMyWyh2MiAtIDIwKSAlIDEwXSB8fCBzMlt2Ml0gfHwgczJbMF0pICsgIl0iOwogICAgfQogIH07CiAgdmFyIHBhZFN0YXJ0ID0gZnVuY3Rpb24gcGFkU3RhcnQyKHN0cmluZywgbGVuZ3RoLCBwYWQpIHsKICAgIHZhciBzMiA9IFN0cmluZyhzdHJpbmcpOwogICAgaWYgKCFzMiB8fCBzMi5sZW5ndGggPj0gbGVuZ3RoKSByZXR1cm4gc3RyaW5nOwogICAgcmV0dXJuICIiICsgQXJyYXkobGVuZ3RoICsgMSAtIHMyLmxlbmd0aCkuam9pbihwYWQpICsgc3RyaW5nOwogIH07CiAgdmFyIHBhZFpvbmVTdHIgPSBmdW5jdGlvbiBwYWRab25lU3RyMihpbnN0YW5jZSkgewogICAgdmFyIG5lZ01pbnV0ZXMgPSAtaW5zdGFuY2UudXRjT2Zmc2V0KCk7CiAgICB2YXIgbWludXRlcyA9IE1hdGguYWJzKG5lZ01pbnV0ZXMpOwogICAgdmFyIGhvdXJPZmZzZXQgPSBNYXRoLmZsb29yKG1pbnV0ZXMgLyA2MCk7CiAgICB2YXIgbWludXRlT2Zmc2V0ID0gbWludXRlcyAlIDYwOwogICAgcmV0dXJuIChuZWdNaW51dGVzIDw9IDAgPyAiKyIgOiAiLSIpICsgcGFkU3RhcnQoaG91ck9mZnNldCwgMiwgIjAiKSArICI6IiArIHBhZFN0YXJ0KG1pbnV0ZU9mZnNldCwgMiwgIjAiKTsKICB9OwogIHZhciBtb250aERpZmYgPSBmdW5jdGlvbiBtb250aERpZmYyKGEyLCBiKSB7CiAgICBpZiAoYTIuZGF0ZSgpIDwgYi5kYXRlKCkpIHJldHVybiAtbW9udGhEaWZmMihiLCBhMik7CiAgICB2YXIgd2hvbGVNb250aERpZmYgPSAoYi55ZWFyKCkgLSBhMi55ZWFyKCkpICogMTIgKyAoYi5tb250aCgpIC0gYTIubW9udGgoKSk7CiAgICB2YXIgYW5jaG9yID0gYTIuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYsIE0pOwogICAgdmFyIGMyID0gYiAtIGFuY2hvciA8IDA7CiAgICB2YXIgYW5jaG9yMiA9IGEyLmNsb25lKCkuYWRkKHdob2xlTW9udGhEaWZmICsgKGMyID8gLTEgOiAxKSwgTSk7CiAgICByZXR1cm4gKygtKHdob2xlTW9udGhEaWZmICsgKGIgLSBhbmNob3IpIC8gKGMyID8gYW5jaG9yIC0gYW5jaG9yMiA6IGFuY2hvcjIgLSBhbmNob3IpKSB8fCAwKTsKICB9OwogIHZhciBhYnNGbG9vciA9IGZ1bmN0aW9uIGFic0Zsb29yMihuKSB7CiAgICByZXR1cm4gbiA8IDAgPyBNYXRoLmNlaWwobikgfHwgMCA6IE1hdGguZmxvb3Iobik7CiAgfTsKICB2YXIgcHJldHR5VW5pdCA9IGZ1bmN0aW9uIHByZXR0eVVuaXQyKHUyKSB7CiAgICB2YXIgc3BlY2lhbCA9IHsKICAgICAgTSwKICAgICAgeTogWSwKICAgICAgdzogVywKICAgICAgZDogRCwKICAgICAgRDogREFURSwKICAgICAgaDogSCwKICAgICAgbTogTUlOLAogICAgICBzOiBTLAogICAgICBtczogTVMsCiAgICAgIFEKICAgIH07CiAgICByZXR1cm4gc3BlY2lhbFt1Ml0gfHwgU3RyaW5nKHUyIHx8ICIiKS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL3MkLywgIiIpOwogIH07CiAgdmFyIGlzVW5kZWZpbmVkID0gZnVuY3Rpb24gaXNVbmRlZmluZWQyKHMyKSB7CiAgICByZXR1cm4gczIgPT09IHZvaWQgMDsKICB9OwogIHZhciBVID0gewogICAgczogcGFkU3RhcnQsCiAgICB6OiBwYWRab25lU3RyLAogICAgbTogbW9udGhEaWZmLAogICAgYTogYWJzRmxvb3IsCiAgICBwOiBwcmV0dHlVbml0LAogICAgdTogaXNVbmRlZmluZWQKICB9OwogIHZhciBMID0gImVuIjsKICB2YXIgTHMgPSB7fTsKICBMc1tMXSA9IGVuOwogIHZhciBJU19EQVlKUyA9ICIkaXNEYXlqc09iamVjdCI7CiAgdmFyIGlzRGF5anMgPSBmdW5jdGlvbiBpc0RheWpzMihkKSB7CiAgICByZXR1cm4gZCBpbnN0YW5jZW9mIERheWpzIHx8ICEhKGQgJiYgZFtJU19EQVlKU10pOwogIH07CiAgdmFyIHBhcnNlTG9jYWxlID0gZnVuY3Rpb24gcGFyc2VMb2NhbGUyKHByZXNldCwgb2JqZWN0LCBpc0xvY2FsKSB7CiAgICB2YXIgbDI7CiAgICBpZiAoIXByZXNldCkgcmV0dXJuIEw7CiAgICBpZiAodHlwZW9mIHByZXNldCA9PT0gInN0cmluZyIpIHsKICAgICAgdmFyIHByZXNldExvd2VyID0gcHJlc2V0LnRvTG93ZXJDYXNlKCk7CiAgICAgIGlmIChMc1twcmVzZXRMb3dlcl0pIHsKICAgICAgICBsMiA9IHByZXNldExvd2VyOwogICAgICB9CiAgICAgIGlmIChvYmplY3QpIHsKICAgICAgICBMc1twcmVzZXRMb3dlcl0gPSBvYmplY3Q7CiAgICAgICAgbDIgPSBwcmVzZXRMb3dlcjsKICAgICAgfQogICAgICB2YXIgcHJlc2V0U3BsaXQgPSBwcmVzZXQuc3BsaXQoIi0iKTsKICAgICAgaWYgKCFsMiAmJiBwcmVzZXRTcGxpdC5sZW5ndGggPiAxKSB7CiAgICAgICAgcmV0dXJuIHBhcnNlTG9jYWxlMihwcmVzZXRTcGxpdFswXSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhciBuYW1lID0gcHJlc2V0Lm5hbWU7CiAgICAgIExzW25hbWVdID0gcHJlc2V0OwogICAgICBsMiA9IG5hbWU7CiAgICB9CiAgICBpZiAoIWlzTG9jYWwgJiYgbDIpIEwgPSBsMjsKICAgIHJldHVybiBsMiB8fCAhaXNMb2NhbCAmJiBMOwogIH07CiAgdmFyIGRheWpzID0gZnVuY3Rpb24gZGF5anMyKGRhdGUsIGMyKSB7CiAgICBpZiAoaXNEYXlqcyhkYXRlKSkgewogICAgICByZXR1cm4gZGF0ZS5jbG9uZSgpOwogICAgfQogICAgdmFyIGNmZyA9IHR5cGVvZiBjMiA9PT0gIm9iamVjdCIgPyBjMiA6IHt9OwogICAgY2ZnLmRhdGUgPSBkYXRlOwogICAgY2ZnLmFyZ3MgPSBhcmd1bWVudHM7CiAgICByZXR1cm4gbmV3IERheWpzKGNmZyk7CiAgfTsKICB2YXIgd3JhcHBlciA9IGZ1bmN0aW9uIHdyYXBwZXIyKGRhdGUsIGluc3RhbmNlKSB7CiAgICByZXR1cm4gZGF5anMoZGF0ZSwgewogICAgICBsb2NhbGU6IGluc3RhbmNlLiRMLAogICAgICB1dGM6IGluc3RhbmNlLiR1LAogICAgICB4OiBpbnN0YW5jZS4keCwKICAgICAgJG9mZnNldDogaW5zdGFuY2UuJG9mZnNldAogICAgICAvLyB0b2RvOiByZWZhY3RvcjsgZG8gbm90IHVzZSB0aGlzLiRvZmZzZXQgaW4geW91IGNvZGUKICAgIH0pOwogIH07CiAgdmFyIFV0aWxzID0gVTsKICBVdGlscy5sID0gcGFyc2VMb2NhbGU7CiAgVXRpbHMuaSA9IGlzRGF5anM7CiAgVXRpbHMudyA9IHdyYXBwZXI7CiAgdmFyIHBhcnNlRGF0ZSA9IGZ1bmN0aW9uIHBhcnNlRGF0ZTIoY2ZnKSB7CiAgICB2YXIgZGF0ZSA9IGNmZy5kYXRlLCB1dGMgPSBjZmcudXRjOwogICAgaWYgKGRhdGUgPT09IG51bGwpIHJldHVybiAvKiBAX19QVVJFX18gKi8gbmV3IERhdGUoTmFOKTsKICAgIGlmIChVdGlscy51KGRhdGUpKSByZXR1cm4gLyogQF9fUFVSRV9fICovIG5ldyBEYXRlKCk7CiAgICBpZiAoZGF0ZSBpbnN0YW5jZW9mIERhdGUpIHJldHVybiBuZXcgRGF0ZShkYXRlKTsKICAgIGlmICh0eXBlb2YgZGF0ZSA9PT0gInN0cmluZyIgJiYgIS9aJC9pLnRlc3QoZGF0ZSkpIHsKICAgICAgdmFyIGQgPSBkYXRlLm1hdGNoKFJFR0VYX1BBUlNFKTsKICAgICAgaWYgKGQpIHsKICAgICAgICB2YXIgbTIgPSBkWzJdIC0gMSB8fCAwOwogICAgICAgIHZhciBtcyA9IChkWzddIHx8ICIwIikuc3Vic3RyaW5nKDAsIDMpOwogICAgICAgIGlmICh1dGMpIHsKICAgICAgICAgIHJldHVybiBuZXcgRGF0ZShEYXRlLlVUQyhkWzFdLCBtMiwgZFszXSB8fCAxLCBkWzRdIHx8IDAsIGRbNV0gfHwgMCwgZFs2XSB8fCAwLCBtcykpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IERhdGUoZFsxXSwgbTIsIGRbM10gfHwgMSwgZFs0XSB8fCAwLCBkWzVdIHx8IDAsIGRbNl0gfHwgMCwgbXMpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbmV3IERhdGUoZGF0ZSk7CiAgfTsKICB2YXIgRGF5anMgPSAvKiBAX19QVVJFX18gKi8gZnVuY3Rpb24oKSB7CiAgICBmdW5jdGlvbiBEYXlqczIoY2ZnKSB7CiAgICAgIHRoaXMuJEwgPSBwYXJzZUxvY2FsZShjZmcubG9jYWxlLCBudWxsLCB0cnVlKTsKICAgICAgdGhpcy5wYXJzZShjZmcpOwogICAgICB0aGlzLiR4ID0gdGhpcy4keCB8fCBjZmcueCB8fCB7fTsKICAgICAgdGhpc1tJU19EQVlKU10gPSB0cnVlOwogICAgfQogICAgdmFyIF9wcm90byA9IERheWpzMi5wcm90b3R5cGU7CiAgICBfcHJvdG8ucGFyc2UgPSBmdW5jdGlvbiBwYXJzZShjZmcpIHsKICAgICAgdGhpcy4kZCA9IHBhcnNlRGF0ZShjZmcpOwogICAgICB0aGlzLmluaXQoKTsKICAgIH07CiAgICBfcHJvdG8uaW5pdCA9IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHZhciAkZCA9IHRoaXMuJGQ7CiAgICAgIHRoaXMuJHkgPSAkZC5nZXRGdWxsWWVhcigpOwogICAgICB0aGlzLiRNID0gJGQuZ2V0TW9udGgoKTsKICAgICAgdGhpcy4kRCA9ICRkLmdldERhdGUoKTsKICAgICAgdGhpcy4kVyA9ICRkLmdldERheSgpOwogICAgICB0aGlzLiRIID0gJGQuZ2V0SG91cnMoKTsKICAgICAgdGhpcy4kbSA9ICRkLmdldE1pbnV0ZXMoKTsKICAgICAgdGhpcy4kcyA9ICRkLmdldFNlY29uZHMoKTsKICAgICAgdGhpcy4kbXMgPSAkZC5nZXRNaWxsaXNlY29uZHMoKTsKICAgIH07CiAgICBfcHJvdG8uJHV0aWxzID0gZnVuY3Rpb24gJHV0aWxzKCkgewogICAgICByZXR1cm4gVXRpbHM7CiAgICB9OwogICAgX3Byb3RvLmlzVmFsaWQgPSBmdW5jdGlvbiBpc1ZhbGlkMigpIHsKICAgICAgcmV0dXJuICEodGhpcy4kZC50b1N0cmluZygpID09PSBJTlZBTElEX0RBVEVfU1RSSU5HKTsKICAgIH07CiAgICBfcHJvdG8uaXNTYW1lID0gZnVuY3Rpb24gaXNTYW1lKHRoYXQsIHVuaXRzKSB7CiAgICAgIHZhciBvdGhlciA9IGRheWpzKHRoYXQpOwogICAgICByZXR1cm4gdGhpcy5zdGFydE9mKHVuaXRzKSA8PSBvdGhlciAmJiBvdGhlciA8PSB0aGlzLmVuZE9mKHVuaXRzKTsKICAgIH07CiAgICBfcHJvdG8uaXNBZnRlciA9IGZ1bmN0aW9uIGlzQWZ0ZXIodGhhdCwgdW5pdHMpIHsKICAgICAgcmV0dXJuIGRheWpzKHRoYXQpIDwgdGhpcy5zdGFydE9mKHVuaXRzKTsKICAgIH07CiAgICBfcHJvdG8uaXNCZWZvcmUgPSBmdW5jdGlvbiBpc0JlZm9yZSh0aGF0LCB1bml0cykgewogICAgICByZXR1cm4gdGhpcy5lbmRPZih1bml0cykgPCBkYXlqcyh0aGF0KTsKICAgIH07CiAgICBfcHJvdG8uJGcgPSBmdW5jdGlvbiAkZyhpbnB1dCwgZ2V0LCBzZXQpIHsKICAgICAgaWYgKFV0aWxzLnUoaW5wdXQpKSByZXR1cm4gdGhpc1tnZXRdOwogICAgICByZXR1cm4gdGhpcy5zZXQoc2V0LCBpbnB1dCk7CiAgICB9OwogICAgX3Byb3RvLnVuaXggPSBmdW5jdGlvbiB1bml4KCkgewogICAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLnZhbHVlT2YoKSAvIDFlMyk7CiAgICB9OwogICAgX3Byb3RvLnZhbHVlT2YgPSBmdW5jdGlvbiB2YWx1ZU9mKCkgewogICAgICByZXR1cm4gdGhpcy4kZC5nZXRUaW1lKCk7CiAgICB9OwogICAgX3Byb3RvLnN0YXJ0T2YgPSBmdW5jdGlvbiBzdGFydE9mKHVuaXRzLCBfc3RhcnRPZikgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwogICAgICB2YXIgaXNTdGFydE9mID0gIVV0aWxzLnUoX3N0YXJ0T2YpID8gX3N0YXJ0T2YgOiB0cnVlOwogICAgICB2YXIgdW5pdCA9IFV0aWxzLnAodW5pdHMpOwogICAgICB2YXIgaW5zdGFuY2VGYWN0b3J5ID0gZnVuY3Rpb24gaW5zdGFuY2VGYWN0b3J5MihkLCBtMikgewogICAgICAgIHZhciBpbnMgPSBVdGlscy53KF90aGlzLiR1ID8gRGF0ZS5VVEMoX3RoaXMuJHksIG0yLCBkKSA6IG5ldyBEYXRlKF90aGlzLiR5LCBtMiwgZCksIF90aGlzKTsKICAgICAgICByZXR1cm4gaXNTdGFydE9mID8gaW5zIDogaW5zLmVuZE9mKEQpOwogICAgICB9OwogICAgICB2YXIgaW5zdGFuY2VGYWN0b3J5U2V0ID0gZnVuY3Rpb24gaW5zdGFuY2VGYWN0b3J5U2V0MihtZXRob2QsIHNsaWNlKSB7CiAgICAgICAgdmFyIGFyZ3VtZW50U3RhcnQgPSBbMCwgMCwgMCwgMF07CiAgICAgICAgdmFyIGFyZ3VtZW50RW5kID0gWzIzLCA1OSwgNTksIDk5OV07CiAgICAgICAgcmV0dXJuIFV0aWxzLncoX3RoaXMudG9EYXRlKClbbWV0aG9kXS5hcHBseSgKICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcHJlZmVyLXNwcmVhZAogICAgICAgICAgX3RoaXMudG9EYXRlKCJzIiksCiAgICAgICAgICAoaXNTdGFydE9mID8gYXJndW1lbnRTdGFydCA6IGFyZ3VtZW50RW5kKS5zbGljZShzbGljZSkKICAgICAgICApLCBfdGhpcyk7CiAgICAgIH07CiAgICAgIHZhciAkVyA9IHRoaXMuJFcsICRNID0gdGhpcy4kTSwgJEQgPSB0aGlzLiREOwogICAgICB2YXIgdXRjUGFkID0gInNldCIgKyAodGhpcy4kdSA/ICJVVEMiIDogIiIpOwogICAgICBzd2l0Y2ggKHVuaXQpIHsKICAgICAgICBjYXNlIFk6CiAgICAgICAgICByZXR1cm4gaXNTdGFydE9mID8gaW5zdGFuY2VGYWN0b3J5KDEsIDApIDogaW5zdGFuY2VGYWN0b3J5KDMxLCAxMSk7CiAgICAgICAgY2FzZSBNOgogICAgICAgICAgcmV0dXJuIGlzU3RhcnRPZiA/IGluc3RhbmNlRmFjdG9yeSgxLCAkTSkgOiBpbnN0YW5jZUZhY3RvcnkoMCwgJE0gKyAxKTsKICAgICAgICBjYXNlIFc6IHsKICAgICAgICAgIHZhciB3ZWVrU3RhcnQgPSB0aGlzLiRsb2NhbGUoKS53ZWVrU3RhcnQgfHwgMDsKICAgICAgICAgIHZhciBnYXAgPSAoJFcgPCB3ZWVrU3RhcnQgPyAkVyArIDcgOiAkVykgLSB3ZWVrU3RhcnQ7CiAgICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5KGlzU3RhcnRPZiA/ICREIC0gZ2FwIDogJEQgKyAoNiAtIGdhcCksICRNKTsKICAgICAgICB9CiAgICAgICAgY2FzZSBEOgogICAgICAgIGNhc2UgREFURToKICAgICAgICAgIHJldHVybiBpbnN0YW5jZUZhY3RvcnlTZXQodXRjUGFkICsgIkhvdXJzIiwgMCk7CiAgICAgICAgY2FzZSBIOgogICAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCh1dGNQYWQgKyAiTWludXRlcyIsIDEpOwogICAgICAgIGNhc2UgTUlOOgogICAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCh1dGNQYWQgKyAiU2Vjb25kcyIsIDIpOwogICAgICAgIGNhc2UgUzoKICAgICAgICAgIHJldHVybiBpbnN0YW5jZUZhY3RvcnlTZXQodXRjUGFkICsgIk1pbGxpc2Vjb25kcyIsIDMpOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gdGhpcy5jbG9uZSgpOwogICAgICB9CiAgICB9OwogICAgX3Byb3RvLmVuZE9mID0gZnVuY3Rpb24gZW5kT2YoYXJnKSB7CiAgICAgIHJldHVybiB0aGlzLnN0YXJ0T2YoYXJnLCBmYWxzZSk7CiAgICB9OwogICAgX3Byb3RvLiRzZXQgPSBmdW5jdGlvbiAkc2V0KHVuaXRzLCBfaW50KSB7CiAgICAgIHZhciBfQyREJEMkREFURSRDJE0kQyRZJEM7CiAgICAgIHZhciB1bml0ID0gVXRpbHMucCh1bml0cyk7CiAgICAgIHZhciB1dGNQYWQgPSAic2V0IiArICh0aGlzLiR1ID8gIlVUQyIgOiAiIik7CiAgICAgIHZhciBuYW1lID0gKF9DJEQkQyREQVRFJEMkTSRDJFkkQyA9IHt9LCBfQyREJEMkREFURSRDJE0kQyRZJENbRF0gPSB1dGNQYWQgKyAiRGF0ZSIsIF9DJEQkQyREQVRFJEMkTSRDJFkkQ1tEQVRFXSA9IHV0Y1BhZCArICJEYXRlIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW01dID0gdXRjUGFkICsgIk1vbnRoIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW1ldID0gdXRjUGFkICsgIkZ1bGxZZWFyIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW0hdID0gdXRjUGFkICsgIkhvdXJzIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW01JTl0gPSB1dGNQYWQgKyAiTWludXRlcyIsIF9DJEQkQyREQVRFJEMkTSRDJFkkQ1tTXSA9IHV0Y1BhZCArICJTZWNvbmRzIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW01TXSA9IHV0Y1BhZCArICJNaWxsaXNlY29uZHMiLCBfQyREJEMkREFURSRDJE0kQyRZJEMpW3VuaXRdOwogICAgICB2YXIgYXJnID0gdW5pdCA9PT0gRCA/IHRoaXMuJEQgKyAoX2ludCAtIHRoaXMuJFcpIDogX2ludDsKICAgICAgaWYgKHVuaXQgPT09IE0gfHwgdW5pdCA9PT0gWSkgewogICAgICAgIHZhciBkYXRlID0gdGhpcy5jbG9uZSgpLnNldChEQVRFLCAxKTsKICAgICAgICBkYXRlLiRkW25hbWVdKGFyZyk7CiAgICAgICAgZGF0ZS5pbml0KCk7CiAgICAgICAgdGhpcy4kZCA9IGRhdGUuc2V0KERBVEUsIE1hdGgubWluKHRoaXMuJEQsIGRhdGUuZGF5c0luTW9udGgoKSkpLiRkOwogICAgICB9IGVsc2UgaWYgKG5hbWUpIHRoaXMuJGRbbmFtZV0oYXJnKTsKICAgICAgdGhpcy5pbml0KCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKICAgIF9wcm90by5zZXQgPSBmdW5jdGlvbiBzZXQoc3RyaW5nLCBfaW50MikgewogICAgICByZXR1cm4gdGhpcy5jbG9uZSgpLiRzZXQoc3RyaW5nLCBfaW50Mik7CiAgICB9OwogICAgX3Byb3RvLmdldCA9IGZ1bmN0aW9uIGdldCh1bml0KSB7CiAgICAgIHJldHVybiB0aGlzW1V0aWxzLnAodW5pdCldKCk7CiAgICB9OwogICAgX3Byb3RvLmFkZCA9IGZ1bmN0aW9uIGFkZChudW1iZXIsIHVuaXRzKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzLCBfQyRNSU4kQyRIJEMkUyR1bml0OwogICAgICBudW1iZXIgPSBOdW1iZXIobnVtYmVyKTsKICAgICAgdmFyIHVuaXQgPSBVdGlscy5wKHVuaXRzKTsKICAgICAgdmFyIGluc3RhbmNlRmFjdG9yeVNldCA9IGZ1bmN0aW9uIGluc3RhbmNlRmFjdG9yeVNldDIobikgewogICAgICAgIHZhciBkID0gZGF5anMoX3RoaXMyKTsKICAgICAgICByZXR1cm4gVXRpbHMudyhkLmRhdGUoZC5kYXRlKCkgKyBNYXRoLnJvdW5kKG4gKiBudW1iZXIpKSwgX3RoaXMyKTsKICAgICAgfTsKICAgICAgaWYgKHVuaXQgPT09IE0pIHsKICAgICAgICByZXR1cm4gdGhpcy5zZXQoTSwgdGhpcy4kTSArIG51bWJlcik7CiAgICAgIH0KICAgICAgaWYgKHVuaXQgPT09IFkpIHsKICAgICAgICByZXR1cm4gdGhpcy5zZXQoWSwgdGhpcy4keSArIG51bWJlcik7CiAgICAgIH0KICAgICAgaWYgKHVuaXQgPT09IEQpIHsKICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5U2V0KDEpOwogICAgICB9CiAgICAgIGlmICh1bml0ID09PSBXKSB7CiAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCg3KTsKICAgICAgfQogICAgICB2YXIgc3RlcCA9IChfQyRNSU4kQyRIJEMkUyR1bml0ID0ge30sIF9DJE1JTiRDJEgkQyRTJHVuaXRbTUlOXSA9IE1JTExJU0VDT05EU19BX01JTlVURSwgX0MkTUlOJEMkSCRDJFMkdW5pdFtIXSA9IE1JTExJU0VDT05EU19BX0hPVVIsIF9DJE1JTiRDJEgkQyRTJHVuaXRbU10gPSBNSUxMSVNFQ09ORFNfQV9TRUNPTkQsIF9DJE1JTiRDJEgkQyRTJHVuaXQpW3VuaXRdIHx8IDE7CiAgICAgIHZhciBuZXh0VGltZVN0YW1wID0gdGhpcy4kZC5nZXRUaW1lKCkgKyBudW1iZXIgKiBzdGVwOwogICAgICByZXR1cm4gVXRpbHMudyhuZXh0VGltZVN0YW1wLCB0aGlzKTsKICAgIH07CiAgICBfcHJvdG8uc3VidHJhY3QgPSBmdW5jdGlvbiBzdWJ0cmFjdChudW1iZXIsIHN0cmluZykgewogICAgICByZXR1cm4gdGhpcy5hZGQobnVtYmVyICogLTEsIHN0cmluZyk7CiAgICB9OwogICAgX3Byb3RvLmZvcm1hdCA9IGZ1bmN0aW9uIGZvcm1hdChmb3JtYXRTdHIpIHsKICAgICAgdmFyIF90aGlzMyA9IHRoaXM7CiAgICAgIHZhciBsb2NhbGUgPSB0aGlzLiRsb2NhbGUoKTsKICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkgcmV0dXJuIGxvY2FsZS5pbnZhbGlkRGF0ZSB8fCBJTlZBTElEX0RBVEVfU1RSSU5HOwogICAgICB2YXIgc3RyID0gZm9ybWF0U3RyIHx8IEZPUk1BVF9ERUZBVUxUOwogICAgICB2YXIgem9uZVN0ciA9IFV0aWxzLnoodGhpcyk7CiAgICAgIHZhciAkSCA9IHRoaXMuJEgsICRtID0gdGhpcy4kbSwgJE0gPSB0aGlzLiRNOwogICAgICB2YXIgd2Vla2RheXMgPSBsb2NhbGUud2Vla2RheXMsIG1vbnRocyA9IGxvY2FsZS5tb250aHMsIG1lcmlkaWVtID0gbG9jYWxlLm1lcmlkaWVtOwogICAgICB2YXIgZ2V0U2hvcnQgPSBmdW5jdGlvbiBnZXRTaG9ydDIoYXJyLCBpbmRleCwgZnVsbCwgbGVuZ3RoKSB7CiAgICAgICAgcmV0dXJuIGFyciAmJiAoYXJyW2luZGV4XSB8fCBhcnIoX3RoaXMzLCBzdHIpKSB8fCBmdWxsW2luZGV4XS5zbGljZSgwLCBsZW5ndGgpOwogICAgICB9OwogICAgICB2YXIgZ2V0JEggPSBmdW5jdGlvbiBnZXQkSDIobnVtKSB7CiAgICAgICAgcmV0dXJuIFV0aWxzLnMoJEggJSAxMiB8fCAxMiwgbnVtLCAiMCIpOwogICAgICB9OwogICAgICB2YXIgbWVyaWRpZW1GdW5jID0gbWVyaWRpZW0gfHwgZnVuY3Rpb24oaG91ciwgbWludXRlLCBpc0xvd2VyY2FzZSkgewogICAgICAgIHZhciBtMiA9IGhvdXIgPCAxMiA/ICJBTSIgOiAiUE0iOwogICAgICAgIHJldHVybiBpc0xvd2VyY2FzZSA/IG0yLnRvTG93ZXJDYXNlKCkgOiBtMjsKICAgICAgfTsKICAgICAgdmFyIG1hdGNoZXMgPSBmdW5jdGlvbiBtYXRjaGVzMihtYXRjaCkgewogICAgICAgIHN3aXRjaCAobWF0Y2gpIHsKICAgICAgICAgIGNhc2UgIllZIjoKICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhfdGhpczMuJHkpLnNsaWNlKC0yKTsKICAgICAgICAgIGNhc2UgIllZWVkiOgogICAgICAgICAgICByZXR1cm4gVXRpbHMucyhfdGhpczMuJHksIDQsICIwIik7CiAgICAgICAgICBjYXNlICJNIjoKICAgICAgICAgICAgcmV0dXJuICRNICsgMTsKICAgICAgICAgIGNhc2UgIk1NIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoJE0gKyAxLCAyLCAiMCIpOwogICAgICAgICAgY2FzZSAiTU1NIjoKICAgICAgICAgICAgcmV0dXJuIGdldFNob3J0KGxvY2FsZS5tb250aHNTaG9ydCwgJE0sIG1vbnRocywgMyk7CiAgICAgICAgICBjYXNlICJNTU1NIjoKICAgICAgICAgICAgcmV0dXJuIGdldFNob3J0KG1vbnRocywgJE0pOwogICAgICAgICAgY2FzZSAiRCI6CiAgICAgICAgICAgIHJldHVybiBfdGhpczMuJEQ7CiAgICAgICAgICBjYXNlICJERCI6CiAgICAgICAgICAgIHJldHVybiBVdGlscy5zKF90aGlzMy4kRCwgMiwgIjAiKTsKICAgICAgICAgIGNhc2UgImQiOgogICAgICAgICAgICByZXR1cm4gU3RyaW5nKF90aGlzMy4kVyk7CiAgICAgICAgICBjYXNlICJkZCI6CiAgICAgICAgICAgIHJldHVybiBnZXRTaG9ydChsb2NhbGUud2Vla2RheXNNaW4sIF90aGlzMy4kVywgd2Vla2RheXMsIDIpOwogICAgICAgICAgY2FzZSAiZGRkIjoKICAgICAgICAgICAgcmV0dXJuIGdldFNob3J0KGxvY2FsZS53ZWVrZGF5c1Nob3J0LCBfdGhpczMuJFcsIHdlZWtkYXlzLCAzKTsKICAgICAgICAgIGNhc2UgImRkZGQiOgogICAgICAgICAgICByZXR1cm4gd2Vla2RheXNbX3RoaXMzLiRXXTsKICAgICAgICAgIGNhc2UgIkgiOgogICAgICAgICAgICByZXR1cm4gU3RyaW5nKCRIKTsKICAgICAgICAgIGNhc2UgIkhIIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoJEgsIDIsICIwIik7CiAgICAgICAgICBjYXNlICJoIjoKICAgICAgICAgICAgcmV0dXJuIGdldCRIKDEpOwogICAgICAgICAgY2FzZSAiaGgiOgogICAgICAgICAgICByZXR1cm4gZ2V0JEgoMik7CiAgICAgICAgICBjYXNlICJhIjoKICAgICAgICAgICAgcmV0dXJuIG1lcmlkaWVtRnVuYygkSCwgJG0sIHRydWUpOwogICAgICAgICAgY2FzZSAiQSI6CiAgICAgICAgICAgIHJldHVybiBtZXJpZGllbUZ1bmMoJEgsICRtLCBmYWxzZSk7CiAgICAgICAgICBjYXNlICJtIjoKICAgICAgICAgICAgcmV0dXJuIFN0cmluZygkbSk7CiAgICAgICAgICBjYXNlICJtbSI6CiAgICAgICAgICAgIHJldHVybiBVdGlscy5zKCRtLCAyLCAiMCIpOwogICAgICAgICAgY2FzZSAicyI6CiAgICAgICAgICAgIHJldHVybiBTdHJpbmcoX3RoaXMzLiRzKTsKICAgICAgICAgIGNhc2UgInNzIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoX3RoaXMzLiRzLCAyLCAiMCIpOwogICAgICAgICAgY2FzZSAiU1NTIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoX3RoaXMzLiRtcywgMywgIjAiKTsKICAgICAgICAgIGNhc2UgIloiOgogICAgICAgICAgICByZXR1cm4gem9uZVN0cjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH07CiAgICAgIHJldHVybiBzdHIucmVwbGFjZShSRUdFWF9GT1JNQVQsIGZ1bmN0aW9uKG1hdGNoLCAkMSkgewogICAgICAgIHJldHVybiAkMSB8fCBtYXRjaGVzKG1hdGNoKSB8fCB6b25lU3RyLnJlcGxhY2UoIjoiLCAiIik7CiAgICAgIH0pOwogICAgfTsKICAgIF9wcm90by51dGNPZmZzZXQgPSBmdW5jdGlvbiB1dGNPZmZzZXQoKSB7CiAgICAgIHJldHVybiAtTWF0aC5yb3VuZCh0aGlzLiRkLmdldFRpbWV6b25lT2Zmc2V0KCkgLyAxNSkgKiAxNTsKICAgIH07CiAgICBfcHJvdG8uZGlmZiA9IGZ1bmN0aW9uIGRpZmYoaW5wdXQsIHVuaXRzLCBfZmxvYXQpIHsKICAgICAgdmFyIF90aGlzNCA9IHRoaXM7CiAgICAgIHZhciB1bml0ID0gVXRpbHMucCh1bml0cyk7CiAgICAgIHZhciB0aGF0ID0gZGF5anMoaW5wdXQpOwogICAgICB2YXIgem9uZURlbHRhID0gKHRoYXQudXRjT2Zmc2V0KCkgLSB0aGlzLnV0Y09mZnNldCgpKSAqIE1JTExJU0VDT05EU19BX01JTlVURTsKICAgICAgdmFyIGRpZmYyID0gdGhpcyAtIHRoYXQ7CiAgICAgIHZhciBnZXRNb250aCA9IGZ1bmN0aW9uIGdldE1vbnRoMigpIHsKICAgICAgICByZXR1cm4gVXRpbHMubShfdGhpczQsIHRoYXQpOwogICAgICB9OwogICAgICB2YXIgcmVzdWx0OwogICAgICBzd2l0Y2ggKHVuaXQpIHsKICAgICAgICBjYXNlIFk6CiAgICAgICAgICByZXN1bHQgPSBnZXRNb250aCgpIC8gMTI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIE06CiAgICAgICAgICByZXN1bHQgPSBnZXRNb250aCgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBROgogICAgICAgICAgcmVzdWx0ID0gZ2V0TW9udGgoKSAvIDM7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFc6CiAgICAgICAgICByZXN1bHQgPSAoZGlmZjIgLSB6b25lRGVsdGEpIC8gTUlMTElTRUNPTkRTX0FfV0VFSzsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgRDoKICAgICAgICAgIHJlc3VsdCA9IChkaWZmMiAtIHpvbmVEZWx0YSkgLyBNSUxMSVNFQ09ORFNfQV9EQVk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIEg6CiAgICAgICAgICByZXN1bHQgPSBkaWZmMiAvIE1JTExJU0VDT05EU19BX0hPVVI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIE1JTjoKICAgICAgICAgIHJlc3VsdCA9IGRpZmYyIC8gTUlMTElTRUNPTkRTX0FfTUlOVVRFOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTOgogICAgICAgICAgcmVzdWx0ID0gZGlmZjIgLyBNSUxMSVNFQ09ORFNfQV9TRUNPTkQ7CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgcmVzdWx0ID0gZGlmZjI7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICByZXR1cm4gX2Zsb2F0ID8gcmVzdWx0IDogVXRpbHMuYShyZXN1bHQpOwogICAgfTsKICAgIF9wcm90by5kYXlzSW5Nb250aCA9IGZ1bmN0aW9uIGRheXNJbk1vbnRoKCkgewogICAgICByZXR1cm4gdGhpcy5lbmRPZihNKS4kRDsKICAgIH07CiAgICBfcHJvdG8uJGxvY2FsZSA9IGZ1bmN0aW9uICRsb2NhbGUoKSB7CiAgICAgIHJldHVybiBMc1t0aGlzLiRMXTsKICAgIH07CiAgICBfcHJvdG8ubG9jYWxlID0gZnVuY3Rpb24gbG9jYWxlKHByZXNldCwgb2JqZWN0KSB7CiAgICAgIGlmICghcHJlc2V0KSByZXR1cm4gdGhpcy4kTDsKICAgICAgdmFyIHRoYXQgPSB0aGlzLmNsb25lKCk7CiAgICAgIHZhciBuZXh0TG9jYWxlTmFtZSA9IHBhcnNlTG9jYWxlKHByZXNldCwgb2JqZWN0LCB0cnVlKTsKICAgICAgaWYgKG5leHRMb2NhbGVOYW1lKSB0aGF0LiRMID0gbmV4dExvY2FsZU5hbWU7CiAgICAgIHJldHVybiB0aGF0OwogICAgfTsKICAgIF9wcm90by5jbG9uZSA9IGZ1bmN0aW9uIGNsb25lKCkgewogICAgICByZXR1cm4gVXRpbHMudyh0aGlzLiRkLCB0aGlzKTsKICAgIH07CiAgICBfcHJvdG8udG9EYXRlID0gZnVuY3Rpb24gdG9EYXRlKCkgewogICAgICByZXR1cm4gbmV3IERhdGUodGhpcy52YWx1ZU9mKCkpOwogICAgfTsKICAgIF9wcm90by50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7CiAgICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMudG9JU09TdHJpbmcoKSA6IG51bGw7CiAgICB9OwogICAgX3Byb3RvLnRvSVNPU3RyaW5nID0gZnVuY3Rpb24gdG9JU09TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLiRkLnRvSVNPU3RyaW5nKCk7CiAgICB9OwogICAgX3Byb3RvLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLiRkLnRvVVRDU3RyaW5nKCk7CiAgICB9OwogICAgcmV0dXJuIERheWpzMjsKICB9KCk7CiAgdmFyIHByb3RvID0gRGF5anMucHJvdG90eXBlOwogIGRheWpzLnByb3RvdHlwZSA9IHByb3RvOwogIFtbIiRtcyIsIE1TXSwgWyIkcyIsIFNdLCBbIiRtIiwgTUlOXSwgWyIkSCIsIEhdLCBbIiRXIiwgRF0sIFsiJE0iLCBNXSwgWyIkeSIsIFldLCBbIiREIiwgREFURV1dLmZvckVhY2goZnVuY3Rpb24oZykgewogICAgcHJvdG9bZ1sxXV0gPSBmdW5jdGlvbihpbnB1dCkgewogICAgICByZXR1cm4gdGhpcy4kZyhpbnB1dCwgZ1swXSwgZ1sxXSk7CiAgICB9OwogIH0pOwogIGRheWpzLmV4dGVuZCA9IGZ1bmN0aW9uKHBsdWdpbiwgb3B0aW9uKSB7CiAgICBpZiAoIXBsdWdpbi4kaSkgewogICAgICBwbHVnaW4ob3B0aW9uLCBEYXlqcywgZGF5anMpOwogICAgICBwbHVnaW4uJGkgPSB0cnVlOwogICAgfQogICAgcmV0dXJuIGRheWpzOwogIH07CiAgZGF5anMubG9jYWxlID0gcGFyc2VMb2NhbGU7CiAgZGF5anMuaXNEYXlqcyA9IGlzRGF5anM7CiAgZGF5anMudW5peCA9IGZ1bmN0aW9uKHRpbWVzdGFtcCkgewogICAgcmV0dXJuIGRheWpzKHRpbWVzdGFtcCAqIDFlMyk7CiAgfTsKICBkYXlqcy5lbiA9IExzW0xdOwogIGRheWpzLkxzID0gTHM7CiAgZGF5anMucCA9IHt9OwogIHZhciBhZHZhbmNlZEZvcm1hdCA9IGZ1bmN0aW9uKG8sIGMyKSB7CiAgICB2YXIgcHJvdG8yID0gYzIucHJvdG90eXBlOwogICAgdmFyIG9sZEZvcm1hdCA9IHByb3RvMi5mb3JtYXQ7CiAgICBwcm90bzIuZm9ybWF0ID0gZnVuY3Rpb24oZm9ybWF0U3RyKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CiAgICAgIHZhciBsb2NhbGUgPSB0aGlzLiRsb2NhbGUoKTsKICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkgewogICAgICAgIHJldHVybiBvbGRGb3JtYXQuYmluZCh0aGlzKShmb3JtYXRTdHIpOwogICAgICB9CiAgICAgIHZhciB1dGlscyA9IHRoaXMuJHV0aWxzKCk7CiAgICAgIHZhciBzdHIgPSBmb3JtYXRTdHIgfHwgRk9STUFUX0RFRkFVTFQ7CiAgICAgIHZhciByZXN1bHQgPSBzdHIucmVwbGFjZSgvXFsoW15cXV0rKV18UXx3b3x3d3x3fFdXfFd8enp6fHp8Z2dnZ3xHR0dHfERvfFh8eHxrezEsMn18Uy9nLCBmdW5jdGlvbihtYXRjaCkgewogICAgICAgIHN3aXRjaCAobWF0Y2gpIHsKICAgICAgICAgIGNhc2UgIlEiOgogICAgICAgICAgICByZXR1cm4gTWF0aC5jZWlsKChfdGhpcy4kTSArIDEpIC8gMyk7CiAgICAgICAgICBjYXNlICJEbyI6CiAgICAgICAgICAgIHJldHVybiBsb2NhbGUub3JkaW5hbChfdGhpcy4kRCk7CiAgICAgICAgICBjYXNlICJnZ2dnIjoKICAgICAgICAgICAgcmV0dXJuIF90aGlzLndlZWtZZWFyKCk7CiAgICAgICAgICBjYXNlICJHR0dHIjoKICAgICAgICAgICAgcmV0dXJuIF90aGlzLmlzb1dlZWtZZWFyKCk7CiAgICAgICAgICBjYXNlICJ3byI6CiAgICAgICAgICAgIHJldHVybiBsb2NhbGUub3JkaW5hbChfdGhpcy53ZWVrKCksICJXIik7CiAgICAgICAgICBjYXNlICJ3IjoKICAgICAgICAgIGNhc2UgInd3IjoKICAgICAgICAgICAgcmV0dXJuIHV0aWxzLnMoX3RoaXMud2VlaygpLCBtYXRjaCA9PT0gInciID8gMSA6IDIsICIwIik7CiAgICAgICAgICBjYXNlICJXIjoKICAgICAgICAgIGNhc2UgIldXIjoKICAgICAgICAgICAgcmV0dXJuIHV0aWxzLnMoX3RoaXMuaXNvV2VlaygpLCBtYXRjaCA9PT0gIlciID8gMSA6IDIsICIwIik7CiAgICAgICAgICBjYXNlICJrIjoKICAgICAgICAgIGNhc2UgImtrIjoKICAgICAgICAgICAgcmV0dXJuIHV0aWxzLnMoU3RyaW5nKF90aGlzLiRIID09PSAwID8gMjQgOiBfdGhpcy4kSCksIG1hdGNoID09PSAiayIgPyAxIDogMiwgIjAiKTsKICAgICAgICAgIGNhc2UgIlgiOgogICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihfdGhpcy4kZC5nZXRUaW1lKCkgLyAxZTMpOwogICAgICAgICAgY2FzZSAieCI6CiAgICAgICAgICAgIHJldHVybiBfdGhpcy4kZC5nZXRUaW1lKCk7CiAgICAgICAgICBjYXNlICJ6IjoKICAgICAgICAgICAgcmV0dXJuICJbIiArIF90aGlzLm9mZnNldE5hbWUoKSArICJdIjsKICAgICAgICAgIGNhc2UgInp6eiI6CiAgICAgICAgICAgIHJldHVybiAiWyIgKyBfdGhpcy5vZmZzZXROYW1lKCJsb25nIikgKyAiXSI7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICByZXR1cm4gbWF0Y2g7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIG9sZEZvcm1hdC5iaW5kKHRoaXMpKHJlc3VsdCk7CiAgICB9OwogIH07CiAgdmFyIGlzb1dlZWtQcmV0dHlVbml0ID0gImlzb3dlZWsiOwogIHZhciBpc29XZWVrID0gZnVuY3Rpb24obywgYzIsIGQpIHsKICAgIHZhciBnZXRZZWFyRmlyc3RUaHVyc2RheSA9IGZ1bmN0aW9uIGdldFllYXJGaXJzdFRodXJzZGF5Mih5ZWFyLCBpc1V0YykgewogICAgICB2YXIgeWVhckZpcnN0RGF5ID0gKGlzVXRjID8gZC51dGMgOiBkKSgpLnllYXIoeWVhcikuc3RhcnRPZihZKTsKICAgICAgdmFyIGFkZERpZmZEYXlzID0gNCAtIHllYXJGaXJzdERheS5pc29XZWVrZGF5KCk7CiAgICAgIGlmICh5ZWFyRmlyc3REYXkuaXNvV2Vla2RheSgpID4gNCkgewogICAgICAgIGFkZERpZmZEYXlzICs9IDc7CiAgICAgIH0KICAgICAgcmV0dXJuIHllYXJGaXJzdERheS5hZGQoYWRkRGlmZkRheXMsIEQpOwogICAgfTsKICAgIHZhciBnZXRDdXJyZW50V2Vla1RodXJzZGF5ID0gZnVuY3Rpb24gZ2V0Q3VycmVudFdlZWtUaHVyc2RheTIoaW5zKSB7CiAgICAgIHJldHVybiBpbnMuYWRkKDQgLSBpbnMuaXNvV2Vla2RheSgpLCBEKTsKICAgIH07CiAgICB2YXIgcHJvdG8yID0gYzIucHJvdG90eXBlOwogICAgcHJvdG8yLmlzb1dlZWtZZWFyID0gZnVuY3Rpb24oKSB7CiAgICAgIHZhciBub3dXZWVrVGh1cnNkYXkgPSBnZXRDdXJyZW50V2Vla1RodXJzZGF5KHRoaXMpOwogICAgICByZXR1cm4gbm93V2Vla1RodXJzZGF5LnllYXIoKTsKICAgIH07CiAgICBwcm90bzIuaXNvV2VlayA9IGZ1bmN0aW9uKHdlZWspIHsKICAgICAgaWYgKCF0aGlzLiR1dGlscygpLnUod2VlaykpIHsKICAgICAgICByZXR1cm4gdGhpcy5hZGQoKHdlZWsgLSB0aGlzLmlzb1dlZWsoKSkgKiA3LCBEKTsKICAgICAgfQogICAgICB2YXIgbm93V2Vla1RodXJzZGF5ID0gZ2V0Q3VycmVudFdlZWtUaHVyc2RheSh0aGlzKTsKICAgICAgdmFyIGRpZmZXZWVrVGh1cnNkYXkgPSBnZXRZZWFyRmlyc3RUaHVyc2RheSh0aGlzLmlzb1dlZWtZZWFyKCksIHRoaXMuJHUpOwogICAgICByZXR1cm4gbm93V2Vla1RodXJzZGF5LmRpZmYoZGlmZldlZWtUaHVyc2RheSwgVykgKyAxOwogICAgfTsKICAgIHByb3RvMi5pc29XZWVrZGF5ID0gZnVuY3Rpb24od2VlaykgewogICAgICBpZiAoIXRoaXMuJHV0aWxzKCkudSh3ZWVrKSkgewogICAgICAgIHJldHVybiB0aGlzLmRheSh0aGlzLmRheSgpICUgNyA/IHdlZWsgOiB3ZWVrIC0gNyk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuZGF5KCkgfHwgNzsKICAgIH07CiAgICB2YXIgb2xkU3RhcnRPZiA9IHByb3RvMi5zdGFydE9mOwogICAgcHJvdG8yLnN0YXJ0T2YgPSBmdW5jdGlvbih1bml0cywgc3RhcnRPZikgewogICAgICB2YXIgdXRpbHMgPSB0aGlzLiR1dGlscygpOwogICAgICB2YXIgaXNTdGFydE9mID0gIXV0aWxzLnUoc3RhcnRPZikgPyBzdGFydE9mIDogdHJ1ZTsKICAgICAgdmFyIHVuaXQgPSB1dGlscy5wKHVuaXRzKTsKICAgICAgaWYgKHVuaXQgPT09IGlzb1dlZWtQcmV0dHlVbml0KSB7CiAgICAgICAgcmV0dXJuIGlzU3RhcnRPZiA/IHRoaXMuZGF0ZSh0aGlzLmRhdGUoKSAtICh0aGlzLmlzb1dlZWtkYXkoKSAtIDEpKS5zdGFydE9mKCJkYXkiKSA6IHRoaXMuZGF0ZSh0aGlzLmRhdGUoKSAtIDEgLSAodGhpcy5pc29XZWVrZGF5KCkgLSAxKSArIDcpLmVuZE9mKCJkYXkiKTsKICAgICAgfQogICAgICByZXR1cm4gb2xkU3RhcnRPZi5iaW5kKHRoaXMpKHVuaXRzLCBzdGFydE9mKTsKICAgIH07CiAgfTsKICBkYXlqcy5leHRlbmQoaXNvV2Vlayk7CiAgZGF5anMuZXh0ZW5kKGFkdmFuY2VkRm9ybWF0KTsKICBjb25zdCBGT1JNQVRfSVNPX1dFRUtfWUVBUl9XRUVLID0gIkdHR0ctW1ddV1ciOwogIGNvbnN0IF9UZW1wb3JhbENhY2hlID0gY2xhc3MgX1RlbXBvcmFsQ2FjaGUgewogICAgY29uc3RydWN0b3IoKSB7CiAgICAgIHRoaXMueWVhck1vbnRoRGF5Q2FjaGUgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLnllYXJXZWVrQ2FjaGUgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLnllYXJNb250aENhY2hlID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgdGhpcy55ZWFyQ2FjaGUgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgfQogICAgZ2V0WWVhck1vbnRoRGF5KHMyKSB7CiAgICAgIGlmICghdGhpcy55ZWFyTW9udGhEYXlDYWNoZS5oYXMoczIpKSB7CiAgICAgICAgdGhpcy55ZWFyTW9udGhEYXlDYWNoZS5zZXQoczIsIFllYXJNb250aERheUNsYXNzLnBhcnNlKHMyLCB0aGlzKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMueWVhck1vbnRoRGF5Q2FjaGUuZ2V0KHMyKTsKICAgIH0KICAgIGdldFllYXJNb250aChzMikgewogICAgICBpZiAoIXRoaXMueWVhck1vbnRoQ2FjaGUuaGFzKHMyKSkgewogICAgICAgIHRoaXMueWVhck1vbnRoQ2FjaGUuc2V0KHMyLCBZZWFyTW9udGhDbGFzcy5wYXJzZShzMiwgdGhpcykpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnllYXJNb250aENhY2hlLmdldChzMik7CiAgICB9CiAgICBnZXRZZWFyV2VlayhzMikgewogICAgICBpZiAoIXRoaXMueWVhcldlZWtDYWNoZS5oYXMoczIpKSB7CiAgICAgICAgdGhpcy55ZWFyV2Vla0NhY2hlLnNldChzMiwgWWVhcldlZWtDbGFzcy5wYXJzZShzMiwgdGhpcykpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnllYXJXZWVrQ2FjaGUuZ2V0KHMyKTsKICAgIH0KICAgIGdldFllYXIoczIpIHsKICAgICAgaWYgKCF0aGlzLnllYXJDYWNoZS5oYXMoczIpKSB7CiAgICAgICAgdGhpcy55ZWFyQ2FjaGUuc2V0KHMyLCBZZWFyQ2xhc3MucGFyc2UoczIsIHRoaXMpKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy55ZWFyQ2FjaGUuZ2V0KHMyKTsKICAgIH0KICAgIHN0YXRpYyBnZXRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuaW5zdGFuY2U7CiAgICB9CiAgfTsKICBfVGVtcG9yYWxDYWNoZS5pbnN0YW5jZSA9IG5ldyBfVGVtcG9yYWxDYWNoZSgpOwogIGxldCBUZW1wb3JhbENhY2hlID0gX1RlbXBvcmFsQ2FjaGU7CiAgY2xhc3MgWWVhck1vbnRoRGF5Q2xhc3MgewogICAgY29uc3RydWN0b3IoeWVhck51bWJlciwgbW9udGhOdW1iZXIsIGRheU51bWJlciwgY2FjaGUpIHsKICAgICAgdGhpcy55ZWFyTnVtYmVyID0geWVhck51bWJlcjsKICAgICAgdGhpcy5tb250aE51bWJlciA9IG1vbnRoTnVtYmVyOwogICAgICB0aGlzLmRheU51bWJlciA9IGRheU51bWJlcjsKICAgICAgdGhpcy5jYWNoZSA9IGNhY2hlOwogICAgICB0aGlzLnR5cGUgPSAiWWVhck1vbnRoRGF5IjsKICAgICAgdGhpcy5kYXRlID0gbmV3IERhdGUodGhpcy55ZWFyTnVtYmVyLCB0aGlzLm1vbnRoTnVtYmVyIC0gMSwgdGhpcy5kYXlOdW1iZXIpOwogICAgICB0aGlzLmRheWpzID0gZGF5anModGhpcy5kYXRlKTsKICAgICAgdGhpcy5kYXRlU3RyaW5nID0gdGhpcy50b1N0cmluZygpOwogICAgfQogICAgZ2V0IHRleHQoKSB7CiAgICAgIHJldHVybiB0aGlzLmRheWpzLmZvcm1hdCgiWVlZWS1NTS1ERCIpOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLnRleHQ7CiAgICB9CiAgICBlbmdsaXNoTmFtZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZGF5anMuZm9ybWF0KCJkZGRkLCBNTU1NIEQsIFlZWVkiKTsKICAgIH0KICAgIGdldCBmaXJzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICBnZXQgbGFzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICBnZXQgeWVhcigpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhcihgJHt0aGlzLnllYXJOdW1iZXJ9YCk7CiAgICB9CiAgICBnZXQgbW9udGgoKSB7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aCh0aGlzLmRheWpzLmZvcm1hdCgiWVlZWS1NTSIpKTsKICAgIH0KICAgIGdldCB3ZWVrKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyV2Vlayh0aGlzLmRheWpzLmZvcm1hdChGT1JNQVRfSVNPX1dFRUtfWUVBUl9XRUVLKSk7CiAgICB9CiAgICBhZGREYXlzKGRheXMpIHsKICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuZGF5anMuYWRkKGRheXMsICJkYXkiKTsKICAgICAgY29uc3QgczIgPSBkYXRlLmZvcm1hdCgiWVlZWS1NTS1ERCIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGhEYXkoczIpOwogICAgfQogICAgbWludXMob3RoZXIpIHsKICAgICAgcmV0dXJuIHRoaXMuZGF5anMuZGlmZihvdGhlci5kYXlqcywgImRheSIpOwogICAgfQogICAgc3RhdGljIHBhcnNlKHMyLCBjYWNoZSkgewogICAgICBjb25zdCBbeWVhciwgbW9udGgsIGRheV0gPSBzMi5zcGxpdCgiLSIpLm1hcCgoczIyKSA9PiBwYXJzZUludChzMjIsIDEwKSk7CiAgICAgIHJldHVybiBuZXcgWWVhck1vbnRoRGF5Q2xhc3MoeWVhciwgbW9udGgsIGRheSwgY2FjaGUpOwogICAgfQogIH0KICBjbGFzcyBZZWFyV2Vla0NsYXNzIHsKICAgIGNvbnN0cnVjdG9yKGlzb1llYXJOdW1iZXIsIGlzb1dlZWtOdW1iZXIsIGNhY2hlKSB7CiAgICAgIHRoaXMuaXNvWWVhck51bWJlciA9IGlzb1llYXJOdW1iZXI7CiAgICAgIHRoaXMuaXNvV2Vla051bWJlciA9IGlzb1dlZWtOdW1iZXI7CiAgICAgIHRoaXMuY2FjaGUgPSBjYWNoZTsKICAgICAgdGhpcy50eXBlID0gIlllYXJXZWVrIjsKICAgICAgdGhpcy5kYXRlU3RyaW5nID0gdGhpcy50b1N0cmluZygpOwogICAgfQogICAgZ2V0IHRleHQoKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmZvcm1hdChGT1JNQVRfSVNPX1dFRUtfWUVBUl9XRUVLKTsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy50ZXh0OwogICAgfQogICAgZW5nbGlzaE5hbWUoKSB7CiAgICAgIHJldHVybiBgV2VlayAke3RoaXMuaXNvV2Vla051bWJlcn0sICR7dGhpcy5pc29ZZWFyTnVtYmVyfWA7CiAgICB9CiAgICBnZXQgZmlyc3REYXkoKSB7CiAgICAgIGNvbnN0IGZpcnN0RGF5ID0gZGF5anMoKS55ZWFyKHRoaXMuaXNvWWVhck51bWJlcikubW9udGgoMSkuZGF0ZSg0KS5pc29XZWVrKHRoaXMuaXNvV2Vla051bWJlcikuc3RhcnRPZigiaXNvV2VlayIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGhEYXkoZmlyc3REYXkuZm9ybWF0KCJZWVlZLU1NLUREIikpOwogICAgfQogICAgZ2V0IGxhc3REYXkoKSB7CiAgICAgIGNvbnN0IGZpcnN0RGF5ID0gZGF5anMoKS55ZWFyKHRoaXMuaXNvWWVhck51bWJlcikuc3RhcnRPZigieWVhciIpLmFkZCgodGhpcy5pc29XZWVrTnVtYmVyIC0gMSkgKiA3LCAiZGF5Iikuc3RhcnRPZigid2VlayIpLmFkZCgxLCAiZGF5Iik7CiAgICAgIGNvbnN0IGxhc3REYXkgPSBmaXJzdERheS5hZGQoNiwgImRheSIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGhEYXkobGFzdERheS5mb3JtYXQoIllZWVktTU0tREQiKSk7CiAgICB9CiAgICBnZXQgeWVhcigpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhcihgJHt0aGlzLmlzb1llYXJOdW1iZXJ9YCk7CiAgICB9CiAgICBhZGRXZWVrcyh3ZWVrcykgewogICAgICBjb25zdCBkYXRlID0gdGhpcy5maXJzdERheS5kYXlqcy5hZGQod2Vla3MsICJ3ZWVrIik7CiAgICAgIGNvbnN0IHMyID0gZGF0ZS5mb3JtYXQoRk9STUFUX0lTT19XRUVLX1lFQVJfV0VFSyk7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJXZWVrKHMyKTsKICAgIH0KICAgIG1pbnVzKG90aGVyKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmRpZmYob3RoZXIuZmlyc3REYXkuZGF5anMsICJ3ZWVrIik7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UoczIsIGNhY2hlKSB7CiAgICAgIGNvbnN0IFt5ZWFyLCB3ZWVrXSA9IHMyLnNwbGl0KCItVyIpLm1hcCgoczIyKSA9PiBwYXJzZUludChzMjIsIDEwKSk7CiAgICAgIHJldHVybiBuZXcgWWVhcldlZWtDbGFzcyh5ZWFyLCB3ZWVrLCBjYWNoZSk7CiAgICB9CiAgfQogIGNsYXNzIFllYXJNb250aENsYXNzIHsKICAgIGNvbnN0cnVjdG9yKHllYXJOdW1iZXIsIG1vbnRoTnVtYmVyLCBjYWNoZSkgewogICAgICB0aGlzLnllYXJOdW1iZXIgPSB5ZWFyTnVtYmVyOwogICAgICB0aGlzLm1vbnRoTnVtYmVyID0gbW9udGhOdW1iZXI7CiAgICAgIHRoaXMuY2FjaGUgPSBjYWNoZTsKICAgICAgdGhpcy50eXBlID0gIlllYXJNb250aCI7CiAgICAgIHRoaXMuZGF0ZVN0cmluZyA9IHRoaXMudG9TdHJpbmcoKTsKICAgIH0KICAgIGdldCB0ZXh0KCkgewogICAgICByZXR1cm4gdGhpcy5maXJzdERheS5kYXlqcy5mb3JtYXQoIllZWVktTU0iKTsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy50ZXh0OwogICAgfQogICAgZW5nbGlzaE5hbWUoKSB7CiAgICAgIHJldHVybiBgJHttb250aE5hbWUodGhpcy5tb250aE51bWJlcil9ICR7dGhpcy55ZWFyTnVtYmVyfWA7CiAgICB9CiAgICBnZXQgZmlyc3REYXkoKSB7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aERheShkYXlqcyhgJHt0aGlzLnllYXJOdW1iZXJ9LSR7dGhpcy5tb250aE51bWJlcn0tMDFgKS5mb3JtYXQoIllZWVktTU0tREQiKSk7CiAgICB9CiAgICBnZXQgbGFzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoRGF5KAogICAgICAgIGRheWpzKGAke3RoaXMueWVhck51bWJlcn0tJHt0aGlzLm1vbnRoTnVtYmVyfS0wMWApLmVuZE9mKCJtb250aCIpLmZvcm1hdCgiWVlZWS1NTS1ERCIpCiAgICAgICk7CiAgICB9CiAgICBnZXQgeWVhcigpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhcihgJHt0aGlzLnllYXJOdW1iZXJ9YCk7CiAgICB9CiAgICBhZGRNb250aHMobW9udGhzKSB7CiAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLmZpcnN0RGF5LmRheWpzLmFkZChtb250aHMsICJtb250aCIpOwogICAgICBjb25zdCBzMiA9IGRhdGUuZm9ybWF0KCJZWVlZLU1NIik7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aChzMik7CiAgICB9CiAgICBtaW51cyhvdGhlcikgewogICAgICByZXR1cm4gdGhpcy5maXJzdERheS5kYXlqcy5kaWZmKG90aGVyLmZpcnN0RGF5LmRheWpzLCAibW9udGgiKTsKICAgIH0KICAgIHN0YXRpYyBwYXJzZShzMiwgY2FjaGUpIHsKICAgICAgY29uc3QgW3llYXIsIG1vbnRoXSA9IHMyLnNwbGl0KCItIikubWFwKChzMjIpID0+IHBhcnNlSW50KHMyMiwgMTApKTsKICAgICAgcmV0dXJuIG5ldyBZZWFyTW9udGhDbGFzcyh5ZWFyLCBtb250aCwgY2FjaGUpOwogICAgfQogIH0KICBjbGFzcyBZZWFyQ2xhc3MgewogICAgY29uc3RydWN0b3IoeWVhciwgY2FjaGUpIHsKICAgICAgdGhpcy55ZWFyID0geWVhcjsKICAgICAgdGhpcy5jYWNoZSA9IGNhY2hlOwogICAgICB0aGlzLnR5cGUgPSAiWWVhciI7CiAgICAgIHRoaXMuZGF0ZVN0cmluZyA9IHRoaXMudG9TdHJpbmcoKTsKICAgIH0KICAgIGdldCB0ZXh0KCkgewogICAgICByZXR1cm4gdGhpcy5maXJzdERheS5kYXlqcy5mb3JtYXQoIllZWVkiKTsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy50ZXh0OwogICAgfQogICAgZW5nbGlzaE5hbWUoKSB7CiAgICAgIHJldHVybiB0aGlzLnllYXIudG9TdHJpbmcoKTsKICAgIH0KICAgIGdldCBmaXJzdE1vbnRoKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGgoYCR7dGhpcy55ZWFyfS0wMWApOwogICAgfQogICAgZ2V0IGxhc3RNb250aCgpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoKGAke3RoaXMueWVhcn0tMTJgKTsKICAgIH0KICAgIGdldCBmaXJzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZmlyc3RNb250aC5maXJzdERheTsKICAgIH0KICAgIGdldCBsYXN0RGF5KCkgewogICAgICByZXR1cm4gdGhpcy5sYXN0TW9udGgubGFzdERheTsKICAgIH0KICAgIGFkZFllYXJzKHllYXJzKSB7CiAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLmZpcnN0RGF5LmRheWpzLmFkZCh5ZWFycywgInllYXIiKTsKICAgICAgY29uc3QgczIgPSBkYXRlLmZvcm1hdCgiWVlZWSIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyKHMyKTsKICAgIH0KICAgIG1pbnVzKG90aGVyKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmRpZmYob3RoZXIuZmlyc3REYXkuZGF5anMsICJ5ZWFyIik7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UoczIsIGNhY2hlKSB7CiAgICAgIGNvbnN0IHllYXIgPSBwYXJzZUludChzMiwgMTApOwogICAgICByZXR1cm4gbmV3IFllYXJDbGFzcyh5ZWFyLCBjYWNoZSk7CiAgICB9CiAgfQogIGZ1bmN0aW9uIG1vbnRoTmFtZShtb250aCkgewogICAgcmV0dXJuIGRheWpzKCkubW9udGgobW9udGggLSAxKS5mb3JtYXQoIk1NTU0iKTsKICB9CiAgZnVuY3Rpb24gdG9UZW1wb3JhbCh0ZW1wb3JhbENsYXNzKSB7CiAgICBzd2l0Y2ggKHRlbXBvcmFsQ2xhc3MudHlwZSkgewogICAgICBjYXNlICJZZWFyTW9udGhEYXkiOgogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiAiWWVhck1vbnRoRGF5IiwKICAgICAgICAgIHllYXJOdW1iZXI6IHRlbXBvcmFsQ2xhc3MueWVhck51bWJlciwKICAgICAgICAgIG1vbnRoTnVtYmVyOiB0ZW1wb3JhbENsYXNzLm1vbnRoTnVtYmVyLAogICAgICAgICAgZGF5TnVtYmVyOiB0ZW1wb3JhbENsYXNzLmRheU51bWJlciwKICAgICAgICAgIGRhdGVTdHJpbmc6IHRlbXBvcmFsQ2xhc3MuZGF0ZVN0cmluZwogICAgICAgIH07CiAgICAgIGNhc2UgIlllYXJXZWVrIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogIlllYXJXZWVrIiwKICAgICAgICAgIGlzb1llYXJOdW1iZXI6IHRlbXBvcmFsQ2xhc3MuaXNvWWVhck51bWJlciwKICAgICAgICAgIGlzb1dlZWtOdW1iZXI6IHRlbXBvcmFsQ2xhc3MuaXNvV2Vla051bWJlciwKICAgICAgICAgIGRhdGVTdHJpbmc6IHRlbXBvcmFsQ2xhc3MuZGF0ZVN0cmluZwogICAgICAgIH07CiAgICAgIGNhc2UgIlllYXJNb250aCI6CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHR5cGU6ICJZZWFyTW9udGgiLAogICAgICAgICAgeWVhck51bWJlcjogdGVtcG9yYWxDbGFzcy55ZWFyTnVtYmVyLAogICAgICAgICAgbW9udGhOdW1iZXI6IHRlbXBvcmFsQ2xhc3MubW9udGhOdW1iZXIsCiAgICAgICAgICBkYXRlU3RyaW5nOiB0ZW1wb3JhbENsYXNzLmRhdGVTdHJpbmcKICAgICAgICB9OwogICAgICBjYXNlICJZZWFyIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogIlllYXIiLAogICAgICAgICAgeWVhcjogdGVtcG9yYWxDbGFzcy55ZWFyLAogICAgICAgICAgZGF0ZVN0cmluZzogdGVtcG9yYWxDbGFzcy5kYXRlU3RyaW5nCiAgICAgICAgfTsKICAgIH0KICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVBbGxEYXlzSW5SYW5nZShzdGFydCwgZW5kKSB7CiAgICBjb25zdCBkYXlzID0gW107CiAgICBjb25zdCBkYXlzSW5CZXR3ZWVuID0gZW5kLm1pbnVzKHN0YXJ0KTsKICAgIGZvciAobGV0IGkyID0gMDsgaTIgPD0gZGF5c0luQmV0d2VlbjsgaTIrKykgewogICAgICBkYXlzLnB1c2goc3RhcnQuYWRkRGF5cyhpMikpOwogICAgfQogICAgcmV0dXJuIGRheXM7CiAgfQogIGZ1bmN0aW9uIGdlbmVyYXRlQWxsV2Vla3NJblJhbmdlKHN0YXJ0LCBlbmQpIHsKICAgIGNvbnN0IHdlZWtzID0gW107CiAgICBjb25zdCB3ZWVrc0luQmV0d2VlbiA9IGVuZC5taW51cyhzdGFydCk7CiAgICBmb3IgKGxldCBpMiA9IDA7IGkyIDw9IHdlZWtzSW5CZXR3ZWVuOyBpMisrKSB7CiAgICAgIHdlZWtzLnB1c2goc3RhcnQuYWRkV2Vla3MoaTIpKTsKICAgIH0KICAgIHJldHVybiB3ZWVrczsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVBbGxNb250aHNJblJhbmdlKHN0YXJ0LCBlbmQpIHsKICAgIGNvbnN0IG1vbnRocyA9IFtdOwogICAgY29uc3QgbW9udGhzSW5CZXR3ZWVuID0gZW5kLm1pbnVzKHN0YXJ0KTsKICAgIGZvciAobGV0IGkyID0gMDsgaTIgPD0gbW9udGhzSW5CZXR3ZWVuOyBpMisrKSB7CiAgICAgIG1vbnRocy5wdXNoKHN0YXJ0LmFkZE1vbnRocyhpMikpOwogICAgfQogICAgcmV0dXJuIG1vbnRoczsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVBbGxZZWFyc0luUmFuZ2Uoc3RhcnQsIGVuZCkgewogICAgY29uc3QgeWVhcnMgPSBbXTsKICAgIGNvbnN0IHllYXJzSW5CZXR3ZWVuID0gZW5kLm1pbnVzKHN0YXJ0KTsKICAgIGZvciAobGV0IGkyID0gMDsgaTIgPD0geWVhcnNJbkJldHdlZW47IGkyKyspIHsKICAgICAgeWVhcnMucHVzaChzdGFydC5hZGRZZWFycyhpMikpOwogICAgfQogICAgcmV0dXJuIHllYXJzOwogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZUFsbEluUmFuZ2Uoc3RhcnQsIGVuZCkgewogICAgaWYgKHN0YXJ0ID09PSBudWxsIHx8IGVuZCA9PT0gbnVsbCkgewogICAgICByZXR1cm4gW107CiAgICB9CiAgICBpZiAoc3RhcnQgaW5zdGFuY2VvZiBZZWFyTW9udGhEYXlDbGFzcyAmJiBlbmQgaW5zdGFuY2VvZiBZZWFyTW9udGhEYXlDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxEYXlzSW5SYW5nZShzdGFydCwgZW5kKTsKICAgIH0KICAgIGlmIChzdGFydCBpbnN0YW5jZW9mIFllYXJXZWVrQ2xhc3MgJiYgZW5kIGluc3RhbmNlb2YgWWVhcldlZWtDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxXZWVrc0luUmFuZ2Uoc3RhcnQsIGVuZCk7CiAgICB9CiAgICBpZiAoc3RhcnQgaW5zdGFuY2VvZiBZZWFyTW9udGhDbGFzcyAmJiBlbmQgaW5zdGFuY2VvZiBZZWFyTW9udGhDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxNb250aHNJblJhbmdlKHN0YXJ0LCBlbmQpOwogICAgfQogICAgaWYgKHN0YXJ0IGluc3RhbmNlb2YgWWVhckNsYXNzICYmIGVuZCBpbnN0YW5jZW9mIFllYXJDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxZZWFyc0luUmFuZ2Uoc3RhcnQsIGVuZCk7CiAgICB9CiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgYXJndW1lbnRzOiBzdGFydCBhbmQgZW5kIG11c3QgYmUgb2YgdGhlIHNhbWUgdHlwZTogJHtzdGFydH0sICR7ZW5kfWApOwogIH0KICBmdW5jdGlvbiBtaW51c1RlbXBvcmFsKGEyLCBiKSB7CiAgICBpZiAoYTIgaW5zdGFuY2VvZiBZZWFyTW9udGhEYXlDbGFzcyAmJiBiIGluc3RhbmNlb2YgWWVhck1vbnRoRGF5Q2xhc3MpIHsKICAgICAgcmV0dXJuIGEyLm1pbnVzKGIpOwogICAgfQogICAgaWYgKGEyIGluc3RhbmNlb2YgWWVhcldlZWtDbGFzcyAmJiBiIGluc3RhbmNlb2YgWWVhcldlZWtDbGFzcykgewogICAgICByZXR1cm4gYTIubWludXMoYik7CiAgICB9CiAgICBpZiAoYTIgaW5zdGFuY2VvZiBZZWFyTW9udGhDbGFzcyAmJiBiIGluc3RhbmNlb2YgWWVhck1vbnRoQ2xhc3MpIHsKICAgICAgcmV0dXJuIGEyLm1pbnVzKGIpOwogICAgfQogICAgaWYgKGEyIGluc3RhbmNlb2YgWWVhckNsYXNzICYmIGIgaW5zdGFuY2VvZiBZZWFyQ2xhc3MpIHsKICAgICAgcmV0dXJuIGEyLm1pbnVzKGIpOwogICAgfQogICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgY29tcGFyZSAke2EyfSBhbmQgJHtifWApOwogIH0KICBmdW5jdGlvbiBjb21wYXJlVGVtcG9yYWwoYTIsIGIpIHsKICAgIGlmIChhMiA9PT0gbnVsbCkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIGlmIChiID09PSBudWxsKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGNvbnN0IGRpZmYgPSBtaW51c1RlbXBvcmFsKGEyLCBiKTsKICAgIGlmIChkaWZmIDwgMCkgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICBpZiAoZGlmZiA+IDApIHsKICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICByZXR1cm4gMDsKICB9CiAgZnVuY3Rpb24gZ2V0TWluTWF4VGVtcG9yYWwodmFsdWVzKSB7CiAgICBsZXQgbWluID0gbnVsbDsKICAgIGxldCBtYXggPSBudWxsOwogICAgZm9yIChjb25zdCB2YWx1ZSBvZiB2YWx1ZXMpIHsKICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKG1pbiA9PT0gbnVsbCB8fCBjb21wYXJlVGVtcG9yYWwodmFsdWUsIG1pbikgPCAwKSB7CiAgICAgICAgbWluID0gdmFsdWU7CiAgICAgIH0KICAgICAgaWYgKG1heCA9PT0gbnVsbCB8fCBjb21wYXJlVGVtcG9yYWwodmFsdWUsIG1heCkgPiAwKSB7CiAgICAgICAgbWF4ID0gdmFsdWU7CiAgICAgIH0KICAgIH0KICAgIGlmIChtaW4gPT09IG51bGwgfHwgbWF4ID09PSBudWxsKSB7CiAgICAgIHJldHVybiB7IG1pbjogbnVsbCwgbWF4OiBudWxsIH07CiAgICB9CiAgICByZXR1cm4geyBtaW4sIG1heCB9OwogIH0KICBmdW5jdGlvbiBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKGRhdGUsIGdyYW51bGFyaXR5KSB7CiAgICBjb25zdCBjYWNoZSA9IFRlbXBvcmFsQ2FjaGUuZ2V0SW5zdGFuY2UoKTsKICAgIGNvbnN0IGRheSA9IGNhY2hlLmdldFllYXJNb250aERheShkYXRlKTsKICAgIHN3aXRjaCAoZ3JhbnVsYXJpdHkpIHsKICAgICAgY2FzZSAiZGF5IjoKICAgICAgICByZXR1cm4gZGF5OwogICAgICBjYXNlICJ3ZWVrIjoKICAgICAgICByZXR1cm4gZGF5LndlZWs7CiAgICAgIGNhc2UgIm1vbnRoIjoKICAgICAgICByZXR1cm4gZGF5Lm1vbnRoOwogICAgICBjYXNlICJ5ZWFyIjoKICAgICAgICByZXR1cm4gZGF5LnllYXI7CiAgICB9CiAgfQogIGZ1bmN0aW9uIGRhdGVSYW5nZUNvbXBhcmUoYTIsIGIpIHsKICAgIGlmIChhMi5kYXRlUmFuZ2UgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICBpZiAoYi5kYXRlUmFuZ2UgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgcmV0dXJuIGNvbXBhcmVUZW1wb3JhbChhMi5kYXRlUmFuZ2UsIGIuZGF0ZVJhbmdlKTsKICB9CiAgZnVuY3Rpb24gbWFwRGF0ZVRvR3JhbnVsYXJpdHlSYW5nZShkYXRhLCBncmFudWxhcml0eSkgewogICAgcmV0dXJuIHsKICAgICAgZGF0ZVJhbmdlOiBkYXRhLmRhdGUgPT09IG51bGwgPyBudWxsIDogcGFyc2VEYXRlU3RyaW5nVG9UZW1wb3JhbChkYXRhLmRhdGUsIGdyYW51bGFyaXR5KSwKICAgICAgY291bnQ6IGRhdGEuY291bnQKICAgIH07CiAgfQogIGNvbnN0IHN1YnN0aXR1dGlvblJlZ2V4ID0gL14oKD88c2VnbWVudD5bQS1aYS16MC05Xy1dKykoPz06KTopPyg/PHZhbHVlQXRSZWZlcmVuY2U+W0EtWmEtel0pPyg/PHBvc2l0aW9uPlxkKykoPzxzdWJzdGl0dXRpb25WYWx1ZT5bQS1aYS16Ll0pPyQvOwogIGNsYXNzIFN1YnN0aXR1dGlvbkNsYXNzIHsKICAgIGNvbnN0cnVjdG9yKHNlZ21lbnQsIHZhbHVlQXRSZWZlcmVuY2UsIHN1YnN0aXR1dGlvblZhbHVlLCBwb3NpdGlvbikgewogICAgICB0aGlzLnNlZ21lbnQgPSBzZWdtZW50OwogICAgICB0aGlzLnZhbHVlQXRSZWZlcmVuY2UgPSB2YWx1ZUF0UmVmZXJlbmNlOwogICAgICB0aGlzLnN1YnN0aXR1dGlvblZhbHVlID0gc3Vic3RpdHV0aW9uVmFsdWU7CiAgICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjsKICAgICAgdGhpcy50eXBlID0gInN1YnN0aXR1dGlvbiI7CiAgICAgIGNvbnN0IHNlZ21lbnRTdHJpbmcgPSB0aGlzLnNlZ21lbnQgPyBgJHt0aGlzLnNlZ21lbnR9OmAgOiAiIjsKICAgICAgY29uc3QgdmFsdWVBdFJlZmVyZW5jZVN0cmluZyA9IHRoaXMudmFsdWVBdFJlZmVyZW5jZSA/IGAke3RoaXMudmFsdWVBdFJlZmVyZW5jZX1gIDogIiI7CiAgICAgIGNvbnN0IHN1YnN0aXR1dGlvblZhbHVlU3RyaW5nID0gdGhpcy5zdWJzdGl0dXRpb25WYWx1ZSA/IGAke3RoaXMuc3Vic3RpdHV0aW9uVmFsdWV9YCA6ICIiOwogICAgICB0aGlzLmNvZGUgPSBgJHtzZWdtZW50U3RyaW5nfSR7dmFsdWVBdFJlZmVyZW5jZVN0cmluZ30ke3RoaXMucG9zaXRpb259JHtzdWJzdGl0dXRpb25WYWx1ZVN0cmluZ31gOwogICAgfQogICAgZXF1YWxzKG90aGVyKSB7CiAgICAgIGlmICghKG90aGVyIGluc3RhbmNlb2YgU3Vic3RpdHV0aW9uQ2xhc3MpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnNlZ21lbnQgPT09IG90aGVyLnNlZ21lbnQgJiYgdGhpcy52YWx1ZUF0UmVmZXJlbmNlID09PSBvdGhlci52YWx1ZUF0UmVmZXJlbmNlICYmIHRoaXMuc3Vic3RpdHV0aW9uVmFsdWUgPT09IG90aGVyLnN1YnN0aXR1dGlvblZhbHVlICYmIHRoaXMucG9zaXRpb24gPT09IG90aGVyLnBvc2l0aW9uOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLmNvZGU7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UobXV0YXRpb25TdHIpIHsKICAgICAgY29uc3QgbWF0Y2ggPSBtdXRhdGlvblN0ci5tYXRjaChzdWJzdGl0dXRpb25SZWdleCk7CiAgICAgIGlmIChtYXRjaCA9PT0gbnVsbCB8fCBtYXRjaC5ncm91cHMgPT09IHZvaWQgMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHJldHVybiBuZXcgU3Vic3RpdHV0aW9uQ2xhc3MoCiAgICAgICAgbWF0Y2guZ3JvdXBzLnNlZ21lbnQsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnZhbHVlQXRSZWZlcmVuY2UsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnN1YnN0aXR1dGlvblZhbHVlLAogICAgICAgIHBhcnNlSW50KG1hdGNoLmdyb3Vwcy5wb3NpdGlvbiwgMTApCiAgICAgICk7CiAgICB9CiAgfQogIGNvbnN0IGRlbGV0aW9uUmVnZXggPSAvXigoPzxzZWdtZW50PltBLVphLXowLTlfLV0rKSg/PTopOik/KD88dmFsdWVBdFJlZmVyZW5jZT5bQS1aYS16XSk/KD88cG9zaXRpb24+XGQrKSgtKSQvOwogIGNsYXNzIERlbGV0aW9uQ2xhc3MgewogICAgY29uc3RydWN0b3Ioc2VnbWVudCwgdmFsdWVBdFJlZmVyZW5jZSwgcG9zaXRpb24pIHsKICAgICAgdGhpcy5zZWdtZW50ID0gc2VnbWVudDsKICAgICAgdGhpcy52YWx1ZUF0UmVmZXJlbmNlID0gdmFsdWVBdFJlZmVyZW5jZTsKICAgICAgdGhpcy5wb3NpdGlvbiA9IHBvc2l0aW9uOwogICAgICB0aGlzLnR5cGUgPSAiZGVsZXRpb24iOwogICAgICBjb25zdCBzZWdtZW50U3RyaW5nID0gdGhpcy5zZWdtZW50ID8gYCR7dGhpcy5zZWdtZW50fTpgIDogIiI7CiAgICAgIGNvbnN0IHZhbHVlQXRSZWZlcmVuY2VTdHJpbmcgPSB0aGlzLnZhbHVlQXRSZWZlcmVuY2UgPyBgJHt0aGlzLnZhbHVlQXRSZWZlcmVuY2V9YCA6ICIiOwogICAgICB0aGlzLmNvZGUgPSBgJHtzZWdtZW50U3RyaW5nfSR7dmFsdWVBdFJlZmVyZW5jZVN0cmluZ30ke3RoaXMucG9zaXRpb259LWA7CiAgICB9CiAgICBlcXVhbHMob3RoZXIpIHsKICAgICAgaWYgKCEob3RoZXIgaW5zdGFuY2VvZiBEZWxldGlvbkNsYXNzKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5zZWdtZW50ID09PSBvdGhlci5zZWdtZW50ICYmIHRoaXMudmFsdWVBdFJlZmVyZW5jZSA9PT0gb3RoZXIudmFsdWVBdFJlZmVyZW5jZSAmJiB0aGlzLnBvc2l0aW9uID09PSBvdGhlci5wb3NpdGlvbjsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy5jb2RlOwogICAgfQogICAgc3RhdGljIHBhcnNlKG11dGF0aW9uU3RyKSB7CiAgICAgIGNvbnN0IG1hdGNoID0gbXV0YXRpb25TdHIubWF0Y2goZGVsZXRpb25SZWdleCk7CiAgICAgIGlmIChtYXRjaCA9PT0gbnVsbCB8fCBtYXRjaC5ncm91cHMgPT09IHZvaWQgMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHJldHVybiBuZXcgRGVsZXRpb25DbGFzcygKICAgICAgICBtYXRjaC5ncm91cHMuc2VnbWVudCwKICAgICAgICBtYXRjaC5ncm91cHMudmFsdWVBdFJlZmVyZW5jZSwKICAgICAgICBwYXJzZUludChtYXRjaC5ncm91cHMucG9zaXRpb24sIDEwKQogICAgICApOwogICAgfQogIH0KICBmdW5jdGlvbiB0b1N1YnN0aXR1dGlvbk9yRGVsZXRpb24obXV0YXRpb24pIHsKICAgIHN3aXRjaCAobXV0YXRpb24udHlwZSkgewogICAgICBjYXNlICJzdWJzdGl0dXRpb24iOgogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiAic3Vic3RpdHV0aW9uIiwKICAgICAgICAgIGNvZGU6IG11dGF0aW9uLmNvZGUsCiAgICAgICAgICBzZWdtZW50OiBtdXRhdGlvbi5zZWdtZW50LAogICAgICAgICAgcG9zaXRpb246IG11dGF0aW9uLnBvc2l0aW9uLAogICAgICAgICAgdmFsdWVBdFJlZmVyZW5jZTogbXV0YXRpb24udmFsdWVBdFJlZmVyZW5jZSwKICAgICAgICAgIHN1YnN0aXR1dGlvblZhbHVlOiBtdXRhdGlvbi5zdWJzdGl0dXRpb25WYWx1ZQogICAgICAgIH07CiAgICAgIGNhc2UgImRlbGV0aW9uIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogImRlbGV0aW9uIiwKICAgICAgICAgIGNvZGU6IG11dGF0aW9uLmNvZGUsCiAgICAgICAgICBzZWdtZW50OiBtdXRhdGlvbi5zZWdtZW50LAogICAgICAgICAgcG9zaXRpb246IG11dGF0aW9uLnBvc2l0aW9uLAogICAgICAgICAgdmFsdWVBdFJlZmVyZW5jZTogbXV0YXRpb24udmFsdWVBdFJlZmVyZW5jZQogICAgICAgIH07CiAgICB9CiAgfQogIGNsYXNzIEZldGNoU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zT3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoZmlsdGVyLCBzZXF1ZW5jZVR5cGUsIG1pblByb3BvcnRpb24pIHsKICAgICAgdGhpcy5maWx0ZXIgPSBmaWx0ZXI7CiAgICAgIHRoaXMuc2VxdWVuY2VUeXBlID0gc2VxdWVuY2VUeXBlOwogICAgICB0aGlzLm1pblByb3BvcnRpb24gPSBtaW5Qcm9wb3J0aW9uOwogICAgfQogICAgYXN5bmMgZXZhbHVhdGUobGFwaXMsIHNpZ25hbCkgewogICAgICBjb25zdCBtdXRhdGlvbnMgPSBhd2FpdCB0aGlzLmZldGNoTXV0YXRpb25zKGxhcGlzLCBzaWduYWwpOwogICAgICBjb25zdCBjb250ZW50ID0gbXV0YXRpb25zLm1hcCgKICAgICAgICAoeyBjb3VudCwgcHJvcG9ydGlvbiwgbXV0YXRpb25Gcm9tLCBtdXRhdGlvblRvLCBwb3NpdGlvbiwgc2VxdWVuY2VOYW1lIH0pID0+IHsKICAgICAgICAgIGlmIChtdXRhdGlvblRvID09PSAiLSIpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICB0eXBlOiAiZGVsZXRpb24iLAogICAgICAgICAgICAgIG11dGF0aW9uOiBuZXcgRGVsZXRpb25DbGFzcyhzZXF1ZW5jZU5hbWUgPz8gdm9pZCAwLCBtdXRhdGlvbkZyb20sIHBvc2l0aW9uKSwKICAgICAgICAgICAgICBjb3VudCwKICAgICAgICAgICAgICBwcm9wb3J0aW9uCiAgICAgICAgICAgIH07CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICB0eXBlOiAic3Vic3RpdHV0aW9uIiwKICAgICAgICAgICAgbXV0YXRpb246IG5ldyBTdWJzdGl0dXRpb25DbGFzcyhzZXF1ZW5jZU5hbWUgPz8gdm9pZCAwLCBtdXRhdGlvbkZyb20sIG11dGF0aW9uVG8sIHBvc2l0aW9uKSwKICAgICAgICAgICAgY291bnQsCiAgICAgICAgICAgIHByb3BvcnRpb24KICAgICAgICAgIH07CiAgICAgICAgfQogICAgICApOwogICAgICByZXR1cm4geyBjb250ZW50IH07CiAgICB9CiAgICBhc3luYyBmZXRjaE11dGF0aW9ucyhsYXBpcywgc2lnbmFsKSB7CiAgICAgIGNvbnN0IGZpbHRlciA9IHsKICAgICAgICAuLi50aGlzLmZpbHRlciwKICAgICAgICBtaW5Qcm9wb3J0aW9uOiB0aGlzLm1pblByb3BvcnRpb24KICAgICAgfTsKICAgICAgcmV0dXJuIGZldGNoU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zKGxhcGlzLCBmaWx0ZXIsIHRoaXMuc2VxdWVuY2VUeXBlLCBzaWduYWwpLnRoZW4oCiAgICAgICAgKHJlc3BvbnNlKSA9PiByZXNwb25zZS5kYXRhCiAgICAgICk7CiAgICB9CiAgfQogIHZhciBsJDE7CiAgbCQxID0geyBfX2U6IGZ1bmN0aW9uKG4sIGwyLCB1MiwgdCkgewogICAgZm9yICh2YXIgaTIsIG8sIHIyOyBsMiA9IGwyLl9fOyApIGlmICgoaTIgPSBsMi5fX2MpICYmICFpMi5fXykgdHJ5IHsKICAgICAgaWYgKChvID0gaTIuY29uc3RydWN0b3IpICYmIG51bGwgIT0gby5nZXREZXJpdmVkU3RhdGVGcm9tRXJyb3IgJiYgKGkyLnNldFN0YXRlKG8uZ2V0RGVyaXZlZFN0YXRlRnJvbUVycm9yKG4pKSwgcjIgPSBpMi5fX2QpLCBudWxsICE9IGkyLmNvbXBvbmVudERpZENhdGNoICYmIChpMi5jb21wb25lbnREaWRDYXRjaChuLCB0IHx8IHt9KSwgcjIgPSBpMi5fX2QpLCByMikgcmV0dXJuIGkyLl9fRSA9IGkyOwogICAgfSBjYXRjaCAobDMpIHsKICAgICAgbiA9IGwzOwogICAgfQogICAgdGhyb3cgbjsKICB9IH0sICJmdW5jdGlvbiIgPT0gdHlwZW9mIFByb21pc2UgPyBQcm9taXNlLnByb3RvdHlwZS50aGVuLmJpbmQoUHJvbWlzZS5yZXNvbHZlKCkpIDogc2V0VGltZW91dDsKICB2YXIgciwgdSwgaSwgZiA9IFtdLCBjID0gbCQxLCBlID0gYy5fX2IsIGEgPSBjLl9fciwgdiA9IGMuZGlmZmVkLCBsID0gYy5fX2MsIG0gPSBjLnVubW91bnQsIHMgPSBjLl9fOwogIGZ1bmN0aW9uIGooKSB7CiAgICBmb3IgKHZhciBuOyBuID0gZi5zaGlmdCgpOyApIGlmIChuLl9fUCAmJiBuLl9fSCkgdHJ5IHsKICAgICAgbi5fX0guX19oLmZvckVhY2goeiksIG4uX19ILl9faC5mb3JFYWNoKEIpLCBuLl9fSC5fX2ggPSBbXTsKICAgIH0gY2F0Y2ggKHQpIHsKICAgICAgbi5fX0guX19oID0gW10sIGMuX19lKHQsIG4uX192KTsKICAgIH0KICB9CiAgYy5fX2IgPSBmdW5jdGlvbihuKSB7CiAgICByID0gbnVsbCwgZSAmJiBlKG4pOwogIH0sIGMuX18gPSBmdW5jdGlvbihuLCB0KSB7CiAgICBuICYmIHQuX19rICYmIHQuX19rLl9fbSAmJiAobi5fX20gPSB0Ll9fay5fX20pLCBzICYmIHMobiwgdCk7CiAgfSwgYy5fX3IgPSBmdW5jdGlvbihuKSB7CiAgICBhICYmIGEobik7CiAgICB2YXIgaTIgPSAociA9IG4uX19jKS5fX0g7CiAgICBpMiAmJiAodSA9PT0gciA/IChpMi5fX2ggPSBbXSwgci5fX2ggPSBbXSwgaTIuX18uZm9yRWFjaChmdW5jdGlvbihuMikgewogICAgICBuMi5fX04gJiYgKG4yLl9fID0gbjIuX19OKSwgbjIuaSA9IG4yLl9fTiA9IHZvaWQgMDsKICAgIH0pKSA6IChpMi5fX2guZm9yRWFjaCh6KSwgaTIuX19oLmZvckVhY2goQiksIGkyLl9faCA9IFtdLCAwKSksIHUgPSByOwogIH0sIGMuZGlmZmVkID0gZnVuY3Rpb24obikgewogICAgdiAmJiB2KG4pOwogICAgdmFyIHQgPSBuLl9fYzsKICAgIHQgJiYgdC5fX0ggJiYgKHQuX19ILl9faC5sZW5ndGggJiYgKDEgIT09IGYucHVzaCh0KSAmJiBpID09PSBjLnJlcXVlc3RBbmltYXRpb25GcmFtZSB8fCAoKGkgPSBjLnJlcXVlc3RBbmltYXRpb25GcmFtZSkgfHwgdykoaikpLCB0Ll9fSC5fXy5mb3JFYWNoKGZ1bmN0aW9uKG4yKSB7CiAgICAgIG4yLmkgJiYgKG4yLl9fSCA9IG4yLmkpLCBuMi5pID0gdm9pZCAwOwogICAgfSkpLCB1ID0gciA9IG51bGw7CiAgfSwgYy5fX2MgPSBmdW5jdGlvbihuLCB0KSB7CiAgICB0LnNvbWUoZnVuY3Rpb24objIpIHsKICAgICAgdHJ5IHsKICAgICAgICBuMi5fX2guZm9yRWFjaCh6KSwgbjIuX19oID0gbjIuX19oLmZpbHRlcihmdW5jdGlvbihuMykgewogICAgICAgICAgcmV0dXJuICFuMy5fXyB8fCBCKG4zKTsKICAgICAgICB9KTsKICAgICAgfSBjYXRjaCAocjIpIHsKICAgICAgICB0LnNvbWUoZnVuY3Rpb24objMpIHsKICAgICAgICAgIG4zLl9faCAmJiAobjMuX19oID0gW10pOwogICAgICAgIH0pLCB0ID0gW10sIGMuX19lKHIyLCBuMi5fX3YpOwogICAgICB9CiAgICB9KSwgbCAmJiBsKG4sIHQpOwogIH0sIGMudW5tb3VudCA9IGZ1bmN0aW9uKG4pIHsKICAgIG0gJiYgbShuKTsKICAgIHZhciB0LCByMiA9IG4uX19jOwogICAgcjIgJiYgcjIuX19IICYmIChyMi5fX0guX18uZm9yRWFjaChmdW5jdGlvbihuMikgewogICAgICB0cnkgewogICAgICAgIHoobjIpOwogICAgICB9IGNhdGNoIChuMykgewogICAgICAgIHQgPSBuMzsKICAgICAgfQogICAgfSksIHIyLl9fSCA9IHZvaWQgMCwgdCAmJiBjLl9fZSh0LCByMi5fX3YpKTsKICB9OwogIHZhciBrID0gImZ1bmN0aW9uIiA9PSB0eXBlb2YgcmVxdWVzdEFuaW1hdGlvbkZyYW1lOwogIGZ1bmN0aW9uIHcobikgewogICAgdmFyIHQsIHIyID0gZnVuY3Rpb24oKSB7CiAgICAgIGNsZWFyVGltZW91dCh1MiksIGsgJiYgY2FuY2VsQW5pbWF0aW9uRnJhbWUodCksIHNldFRpbWVvdXQobik7CiAgICB9LCB1MiA9IHNldFRpbWVvdXQocjIsIDEwMCk7CiAgICBrICYmICh0ID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHIyKSk7CiAgfQogIGZ1bmN0aW9uIHoobikgewogICAgdmFyIHQgPSByLCB1MiA9IG4uX19jOwogICAgImZ1bmN0aW9uIiA9PSB0eXBlb2YgdTIgJiYgKG4uX19jID0gdm9pZCAwLCB1MigpKSwgciA9IHQ7CiAgfQogIGZ1bmN0aW9uIEIobikgewogICAgdmFyIHQgPSByOwogICAgbi5fX2MgPSBuLl9fKCksIHIgPSB0OwogIH0KICBjbGFzcyBVc2VyRmFjaW5nRXJyb3IgZXh0ZW5kcyBFcnJvciB7CiAgICBjb25zdHJ1Y3RvcihoZWFkbGluZSwgbWVzc2FnZSkgewogICAgICBzdXBlcihtZXNzYWdlKTsKICAgICAgdGhpcy5oZWFkbGluZSA9IGhlYWRsaW5lOwogICAgICB0aGlzLm5hbWUgPSAiVXNlckZhY2luZ0Vycm9yIjsKICAgIH0KICB9CiAgY29uc3Qgc29ydFN1YnN0aXR1dGlvbnNBbmREZWxldGlvbnMgPSAoYTIsIGIpID0+IHsKICAgIGlmIChhMi5zZWdtZW50ICE9PSBiLnNlZ21lbnQpIHsKICAgICAgcmV0dXJuIGNvbXBhcmVTZWdtZW50cyhhMi5zZWdtZW50LCBiLnNlZ21lbnQpOwogICAgfQogICAgaWYgKGEyLnBvc2l0aW9uICE9PSBiLnBvc2l0aW9uKSB7CiAgICAgIHJldHVybiBjb21wYXJlUG9zaXRpb25zKGEyLnBvc2l0aW9uLCBiLnBvc2l0aW9uKTsKICAgIH0KICAgIGNvbnN0IGFJc0RlbGV0aW9uID0gYTIgaW5zdGFuY2VvZiBEZWxldGlvbkNsYXNzOwogICAgY29uc3QgYklzRGVsZXRpb24gPSBiIGluc3RhbmNlb2YgRGVsZXRpb25DbGFzczsKICAgIGlmIChhSXNEZWxldGlvbiAhPT0gYklzRGVsZXRpb24pIHsKICAgICAgcmV0dXJuIGFJc0RlbGV0aW9uID8gMSA6IC0xOwogICAgfQogICAgaWYgKCFhSXNEZWxldGlvbiAmJiAhYklzRGVsZXRpb24pIHsKICAgICAgaWYgKGEyLnN1YnN0aXR1dGlvblZhbHVlICE9PSBiLnN1YnN0aXR1dGlvblZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGNvbXBhcmVTdWJzdGl0dXRpb25WYWx1ZXMoYTIuc3Vic3RpdHV0aW9uVmFsdWUsIGIuc3Vic3RpdHV0aW9uVmFsdWUpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gMDsKICB9OwogIGNvbnN0IGNvbXBhcmVTZWdtZW50cyA9IChhMiwgYikgPT4gewogICAgaWYgKGEyID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgaWYgKGIgPT09IHZvaWQgMCkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIHJldHVybiBhMi5sb2NhbGVDb21wYXJlKGIpOwogIH07CiAgY29uc3QgY29tcGFyZVBvc2l0aW9ucyA9IChhMiwgYikgPT4gewogICAgcmV0dXJuIGEyIC0gYjsKICB9OwogIGNvbnN0IGNvbXBhcmVTdWJzdGl0dXRpb25WYWx1ZXMgPSAoYTIsIGIpID0+IHsKICAgIGlmIChhMiA9PT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGlmIChiID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICByZXR1cm4gYTIubG9jYWxlQ29tcGFyZShiKTsKICB9OwogIGZ1bmN0aW9uIGdldERlZmF1bHRFeHBvcnRGcm9tQ2pzKHgpIHsKICAgIHJldHVybiB4ICYmIHguX19lc01vZHVsZSAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoeCwgImRlZmF1bHQiKSA/IHhbImRlZmF1bHQiXSA6IHg7CiAgfQogIGZ1bmN0aW9uIGNvbW1vbmpzUmVxdWlyZShwYXRoKSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCBkeW5hbWljYWxseSByZXF1aXJlICInICsgcGF0aCArICciLiBQbGVhc2UgY29uZmlndXJlIHRoZSBkeW5hbWljUmVxdWlyZVRhcmdldHMgb3IvYW5kIGlnbm9yZUR5bmFtaWNSZXF1aXJlcyBvcHRpb24gb2YgQHJvbGx1cC9wbHVnaW4tY29tbW9uanMgYXBwcm9wcmlhdGVseSBmb3IgdGhpcyByZXF1aXJlIGNhbGwgdG8gd29yay4nKTsKICB9CiAgdmFyIG9iamVjdF9oYXNoID0geyBleHBvcnRzOiB7fSB9OwogIChmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMpIHsKICAgICFmdW5jdGlvbihlMikgewogICAgICBtb2R1bGUuZXhwb3J0cyA9IGUyKCk7CiAgICB9KGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gZnVuY3Rpb24gcjIobywgaTIsIHUyKSB7CiAgICAgICAgZnVuY3Rpb24gczIobiwgZTMpIHsKICAgICAgICAgIGlmICghaTJbbl0pIHsKICAgICAgICAgICAgaWYgKCFvW25dKSB7CiAgICAgICAgICAgICAgdmFyIHQgPSAiZnVuY3Rpb24iID09IHR5cGVvZiBjb21tb25qc1JlcXVpcmUgJiYgY29tbW9uanNSZXF1aXJlOwogICAgICAgICAgICAgIGlmICghZTMgJiYgdCkgcmV0dXJuIHQobiwgdHJ1ZSk7CiAgICAgICAgICAgICAgaWYgKGEyKSByZXR1cm4gYTIobiwgdHJ1ZSk7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDYW5ub3QgZmluZCBtb2R1bGUgJyIgKyBuICsgIiciKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlMyA9IGkyW25dID0geyBleHBvcnRzOiB7fSB9OwogICAgICAgICAgICBvW25dWzBdLmNhbGwoZTMuZXhwb3J0cywgZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgICB2YXIgdDIgPSBvW25dWzFdW2U0XTsKICAgICAgICAgICAgICByZXR1cm4gczIodDIgfHwgZTQpOwogICAgICAgICAgICB9LCBlMywgZTMuZXhwb3J0cywgcjIsIG8sIGkyLCB1Mik7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gaTJbbl0uZXhwb3J0czsKICAgICAgICB9CiAgICAgICAgZm9yICh2YXIgYTIgPSAiZnVuY3Rpb24iID09IHR5cGVvZiBjb21tb25qc1JlcXVpcmUgJiYgY29tbW9uanNSZXF1aXJlLCBlMiA9IDA7IGUyIDwgdTIubGVuZ3RoOyBlMisrKSBzMih1MltlMl0pOwogICAgICAgIHJldHVybiBzMjsKICAgICAgfSh7IDE6IFtmdW5jdGlvbih3MiwgYiwgbTIpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUyLCBuLCBzMiwgYzIsIGQsIGgsIHAsIGcsIHkpIHsKICAgICAgICAgIHZhciByMiA9IHcyKCJjcnlwdG8iKTsKICAgICAgICAgIGZ1bmN0aW9uIHQoZTMsIHQyKSB7CiAgICAgICAgICAgIHQyID0gdTIoZTMsIHQyKTsKICAgICAgICAgICAgdmFyIG4yOwogICAgICAgICAgICByZXR1cm4gdm9pZCAwID09PSAobjIgPSAicGFzc3Rocm91Z2giICE9PSB0Mi5hbGdvcml0aG0gPyByMi5jcmVhdGVIYXNoKHQyLmFsZ29yaXRobSkgOiBuZXcgbDIoKSkud3JpdGUgJiYgKG4yLndyaXRlID0gbjIudXBkYXRlLCBuMi5lbmQgPSBuMi51cGRhdGUpLCBmMih0MiwgbjIpLmRpc3BhdGNoKGUzKSwgbjIudXBkYXRlIHx8IG4yLmVuZCgiIiksIG4yLmRpZ2VzdCA/IG4yLmRpZ2VzdCgiYnVmZmVyIiA9PT0gdDIuZW5jb2RpbmcgPyB2b2lkIDAgOiB0Mi5lbmNvZGluZykgOiAoZTMgPSBuMi5yZWFkKCksICJidWZmZXIiICE9PSB0Mi5lbmNvZGluZyA/IGUzLnRvU3RyaW5nKHQyLmVuY29kaW5nKSA6IGUzKTsKICAgICAgICAgIH0KICAgICAgICAgIChtMiA9IGIuZXhwb3J0cyA9IHQpLnNoYTEgPSBmdW5jdGlvbihlMykgewogICAgICAgICAgICByZXR1cm4gdChlMyk7CiAgICAgICAgICB9LCBtMi5rZXlzID0gZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgcmV0dXJuIHQoZTMsIHsgZXhjbHVkZVZhbHVlczogdHJ1ZSwgYWxnb3JpdGhtOiAic2hhMSIsIGVuY29kaW5nOiAiaGV4IiB9KTsKICAgICAgICAgIH0sIG0yLk1ENSA9IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIHJldHVybiB0KGUzLCB7IGFsZ29yaXRobTogIm1kNSIsIGVuY29kaW5nOiAiaGV4IiB9KTsKICAgICAgICAgIH0sIG0yLmtleXNNRDUgPSBmdW5jdGlvbihlMykgewogICAgICAgICAgICByZXR1cm4gdChlMywgeyBhbGdvcml0aG06ICJtZDUiLCBlbmNvZGluZzogImhleCIsIGV4Y2x1ZGVWYWx1ZXM6IHRydWUgfSk7CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIG8gPSByMi5nZXRIYXNoZXMgPyByMi5nZXRIYXNoZXMoKS5zbGljZSgpIDogWyJzaGExIiwgIm1kNSJdLCBpMiA9IChvLnB1c2goInBhc3N0aHJvdWdoIiksIFsiYnVmZmVyIiwgImhleCIsICJiaW5hcnkiLCAiYmFzZTY0Il0pOwogICAgICAgICAgZnVuY3Rpb24gdTIoZTMsIHQyKSB7CiAgICAgICAgICAgIHZhciBuMiA9IHt9OwogICAgICAgICAgICBpZiAobjIuYWxnb3JpdGhtID0gKHQyID0gdDIgfHwge30pLmFsZ29yaXRobSB8fCAic2hhMSIsIG4yLmVuY29kaW5nID0gdDIuZW5jb2RpbmcgfHwgImhleCIsIG4yLmV4Y2x1ZGVWYWx1ZXMgPSAhIXQyLmV4Y2x1ZGVWYWx1ZXMsIG4yLmFsZ29yaXRobSA9IG4yLmFsZ29yaXRobS50b0xvd2VyQ2FzZSgpLCBuMi5lbmNvZGluZyA9IG4yLmVuY29kaW5nLnRvTG93ZXJDYXNlKCksIG4yLmlnbm9yZVVua25vd24gPSB0cnVlID09PSB0Mi5pZ25vcmVVbmtub3duLCBuMi5yZXNwZWN0VHlwZSA9IGZhbHNlICE9PSB0Mi5yZXNwZWN0VHlwZSwgbjIucmVzcGVjdEZ1bmN0aW9uTmFtZXMgPSBmYWxzZSAhPT0gdDIucmVzcGVjdEZ1bmN0aW9uTmFtZXMsIG4yLnJlc3BlY3RGdW5jdGlvblByb3BlcnRpZXMgPSBmYWxzZSAhPT0gdDIucmVzcGVjdEZ1bmN0aW9uUHJvcGVydGllcywgbjIudW5vcmRlcmVkQXJyYXlzID0gdHJ1ZSA9PT0gdDIudW5vcmRlcmVkQXJyYXlzLCBuMi51bm9yZGVyZWRTZXRzID0gZmFsc2UgIT09IHQyLnVub3JkZXJlZFNldHMsIG4yLnVub3JkZXJlZE9iamVjdHMgPSBmYWxzZSAhPT0gdDIudW5vcmRlcmVkT2JqZWN0cywgbjIucmVwbGFjZXIgPSB0Mi5yZXBsYWNlciB8fCB2b2lkIDAsIG4yLmV4Y2x1ZGVLZXlzID0gdDIuZXhjbHVkZUtleXMgfHwgdm9pZCAwLCB2b2lkIDAgPT09IGUzKSB0aHJvdyBuZXcgRXJyb3IoIk9iamVjdCBhcmd1bWVudCByZXF1aXJlZC4iKTsKICAgICAgICAgICAgZm9yICh2YXIgcjMgPSAwOyByMyA8IG8ubGVuZ3RoOyArK3IzKSBvW3IzXS50b0xvd2VyQ2FzZSgpID09PSBuMi5hbGdvcml0aG0udG9Mb3dlckNhc2UoKSAmJiAobjIuYWxnb3JpdGhtID0gb1tyM10pOwogICAgICAgICAgICBpZiAoLTEgPT09IG8uaW5kZXhPZihuMi5hbGdvcml0aG0pKSB0aHJvdyBuZXcgRXJyb3IoJ0FsZ29yaXRobSAiJyArIG4yLmFsZ29yaXRobSArICciICBub3Qgc3VwcG9ydGVkLiBzdXBwb3J0ZWQgdmFsdWVzOiAnICsgby5qb2luKCIsICIpKTsKICAgICAgICAgICAgaWYgKC0xID09PSBpMi5pbmRleE9mKG4yLmVuY29kaW5nKSAmJiAicGFzc3Rocm91Z2giICE9PSBuMi5hbGdvcml0aG0pIHRocm93IG5ldyBFcnJvcignRW5jb2RpbmcgIicgKyBuMi5lbmNvZGluZyArICciICBub3Qgc3VwcG9ydGVkLiBzdXBwb3J0ZWQgdmFsdWVzOiAnICsgaTIuam9pbigiLCAiKSk7CiAgICAgICAgICAgIHJldHVybiBuMjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGEyKGUzKSB7CiAgICAgICAgICAgIGlmICgiZnVuY3Rpb24iID09IHR5cGVvZiBlMykgcmV0dXJuIG51bGwgIT0gL15mdW5jdGlvblxzK1x3KlxzKlwoXHMqXClccyp7XHMrXFtuYXRpdmUgY29kZVxdXHMrfSQvaS5leGVjKEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGUzKSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBmMihvMiwgdDIsIGkzKSB7CiAgICAgICAgICAgIGkzID0gaTMgfHwgW107CiAgICAgICAgICAgIGZ1bmN0aW9uIHUzKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHQyLnVwZGF0ZSA/IHQyLnVwZGF0ZShlMywgInV0ZjgiKSA6IHQyLndyaXRlKGUzLCAidXRmOCIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB7IGRpc3BhdGNoOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB0aGlzWyJfIiArIChudWxsID09PSAoZTMgPSBvMi5yZXBsYWNlciA/IG8yLnJlcGxhY2VyKGUzKSA6IGUzKSA/ICJudWxsIiA6IHR5cGVvZiBlMyldKGUzKTsKICAgICAgICAgICAgfSwgX29iamVjdDogZnVuY3Rpb24odDMpIHsKICAgICAgICAgICAgICB2YXIgbjIsIGUzID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHQzKSwgcjMgPSAvXFtvYmplY3QgKC4qKVxdL2kuZXhlYyhlMyk7CiAgICAgICAgICAgICAgcjMgPSAocjMgPSByMyA/IHIzWzFdIDogInVua25vd246WyIgKyBlMyArICJdIikudG9Mb3dlckNhc2UoKTsKICAgICAgICAgICAgICBpZiAoMCA8PSAoZTMgPSBpMy5pbmRleE9mKHQzKSkpIHJldHVybiB0aGlzLmRpc3BhdGNoKCJbQ0lSQ1VMQVI6IiArIGUzICsgIl0iKTsKICAgICAgICAgICAgICBpZiAoaTMucHVzaCh0MyksIHZvaWQgMCAhPT0gczIgJiYgczIuaXNCdWZmZXIgJiYgczIuaXNCdWZmZXIodDMpKSByZXR1cm4gdTMoImJ1ZmZlcjoiKSwgdTModDMpOwogICAgICAgICAgICAgIGlmICgib2JqZWN0IiA9PT0gcjMgfHwgImZ1bmN0aW9uIiA9PT0gcjMgfHwgImFzeW5jZnVuY3Rpb24iID09PSByMykgcmV0dXJuIGUzID0gT2JqZWN0LmtleXModDMpLCBvMi51bm9yZGVyZWRPYmplY3RzICYmIChlMyA9IGUzLnNvcnQoKSksIGZhbHNlID09PSBvMi5yZXNwZWN0VHlwZSB8fCBhMih0MykgfHwgZTMuc3BsaWNlKDAsIDAsICJwcm90b3R5cGUiLCAiX19wcm90b19fIiwgImNvbnN0cnVjdG9yIiksIG8yLmV4Y2x1ZGVLZXlzICYmIChlMyA9IGUzLmZpbHRlcihmdW5jdGlvbihlNCkgewogICAgICAgICAgICAgICAgcmV0dXJuICFvMi5leGNsdWRlS2V5cyhlNCk7CiAgICAgICAgICAgICAgfSkpLCB1Mygib2JqZWN0OiIgKyBlMy5sZW5ndGggKyAiOiIpLCBuMiA9IHRoaXMsIGUzLmZvckVhY2goZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgICAgIG4yLmRpc3BhdGNoKGU0KSwgdTMoIjoiKSwgbzIuZXhjbHVkZVZhbHVlcyB8fCBuMi5kaXNwYXRjaCh0M1tlNF0pLCB1MygiLCIpOwogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIGlmICghdGhpc1siXyIgKyByM10pIHsKICAgICAgICAgICAgICAgIGlmIChvMi5pZ25vcmVVbmtub3duKSByZXR1cm4gdTMoIlsiICsgcjMgKyAiXSIpOwogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIG9iamVjdCB0eXBlICInICsgcjMgKyAnIicpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0aGlzWyJfIiArIHIzXSh0Myk7CiAgICAgICAgICAgIH0sIF9hcnJheTogZnVuY3Rpb24oZTMsIHQzKSB7CiAgICAgICAgICAgICAgdDMgPSB2b2lkIDAgIT09IHQzID8gdDMgOiBmYWxzZSAhPT0gbzIudW5vcmRlcmVkQXJyYXlzOwogICAgICAgICAgICAgIHZhciBuMiA9IHRoaXM7CiAgICAgICAgICAgICAgaWYgKHUzKCJhcnJheToiICsgZTMubGVuZ3RoICsgIjoiKSwgIXQzIHx8IGUzLmxlbmd0aCA8PSAxKSByZXR1cm4gZTMuZm9yRWFjaChmdW5jdGlvbihlNCkgewogICAgICAgICAgICAgICAgcmV0dXJuIG4yLmRpc3BhdGNoKGU0KTsKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICB2YXIgcjMgPSBbXSwgdDMgPSBlMy5tYXAoZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgICAgIHZhciB0NCA9IG5ldyBsMigpLCBuMyA9IGkzLnNsaWNlKCk7CiAgICAgICAgICAgICAgICByZXR1cm4gZjIobzIsIHQ0LCBuMykuZGlzcGF0Y2goZTQpLCByMyA9IHIzLmNvbmNhdChuMy5zbGljZShpMy5sZW5ndGgpKSwgdDQucmVhZCgpLnRvU3RyaW5nKCk7CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgcmV0dXJuIGkzID0gaTMuY29uY2F0KHIzKSwgdDMuc29ydCgpLCB0aGlzLl9hcnJheSh0MywgZmFsc2UpOwogICAgICAgICAgICB9LCBfZGF0ZTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImRhdGU6IiArIGUzLnRvSlNPTigpKTsKICAgICAgICAgICAgfSwgX3N5bWJvbDogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInN5bWJvbDoiICsgZTMudG9TdHJpbmcoKSk7CiAgICAgICAgICAgIH0sIF9lcnJvcjogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImVycm9yOiIgKyBlMy50b1N0cmluZygpKTsKICAgICAgICAgICAgfSwgX2Jvb2xlYW46IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJib29sOiIgKyBlMy50b1N0cmluZygpKTsKICAgICAgICAgICAgfSwgX3N0cmluZzogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICB1Mygic3RyaW5nOiIgKyBlMy5sZW5ndGggKyAiOiIpLCB1MyhlMy50b1N0cmluZygpKTsKICAgICAgICAgICAgfSwgX2Z1bmN0aW9uOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHUzKCJmbjoiKSwgYTIoZTMpID8gdGhpcy5kaXNwYXRjaCgiW25hdGl2ZV0iKSA6IHRoaXMuZGlzcGF0Y2goZTMudG9TdHJpbmcoKSksIGZhbHNlICE9PSBvMi5yZXNwZWN0RnVuY3Rpb25OYW1lcyAmJiB0aGlzLmRpc3BhdGNoKCJmdW5jdGlvbi1uYW1lOiIgKyBTdHJpbmcoZTMubmFtZSkpLCBvMi5yZXNwZWN0RnVuY3Rpb25Qcm9wZXJ0aWVzICYmIHRoaXMuX29iamVjdChlMyk7CiAgICAgICAgICAgIH0sIF9udW1iZXI6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJudW1iZXI6IiArIGUzLnRvU3RyaW5nKCkpOwogICAgICAgICAgICB9LCBfeG1sOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB1MygieG1sOiIgKyBlMy50b1N0cmluZygpKTsKICAgICAgICAgICAgfSwgX251bGw6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiB1MygiTnVsbCIpOwogICAgICAgICAgICB9LCBfdW5kZWZpbmVkOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoIlVuZGVmaW5lZCIpOwogICAgICAgICAgICB9LCBfcmVnZXhwOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB1MygicmVnZXg6IiArIGUzLnRvU3RyaW5nKCkpOwogICAgICAgICAgICB9LCBfdWludDhhcnJheTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInVpbnQ4YXJyYXk6IiksIHRoaXMuZGlzcGF0Y2goQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZTMpKTsKICAgICAgICAgICAgfSwgX3VpbnQ4Y2xhbXBlZGFycmF5OiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB1MygidWludDhjbGFtcGVkYXJyYXk6IiksIHRoaXMuZGlzcGF0Y2goQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZTMpKTsKICAgICAgICAgICAgfSwgX2ludDhhcnJheTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImludDhhcnJheToiKSwgdGhpcy5kaXNwYXRjaChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChlMykpOwogICAgICAgICAgICB9LCBfdWludDE2YXJyYXk6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJ1aW50MTZhcnJheToiKSwgdGhpcy5kaXNwYXRjaChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChlMykpOwogICAgICAgICAgICB9LCBfaW50MTZhcnJheTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImludDE2YXJyYXk6IiksIHRoaXMuZGlzcGF0Y2goQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZTMpKTsKICAgICAgICAgICAgfSwgX3VpbnQzMmFycmF5OiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB1MygidWludDMyYXJyYXk6IiksIHRoaXMuZGlzcGF0Y2goQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZTMpKTsKICAgICAgICAgICAgfSwgX2ludDMyYXJyYXk6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJpbnQzMmFycmF5OiIpLCB0aGlzLmRpc3BhdGNoKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGUzKSk7CiAgICAgICAgICAgIH0sIF9mbG9hdDMyYXJyYXk6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJmbG9hdDMyYXJyYXk6IiksIHRoaXMuZGlzcGF0Y2goQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZTMpKTsKICAgICAgICAgICAgfSwgX2Zsb2F0NjRhcnJheTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImZsb2F0NjRhcnJheToiKSwgdGhpcy5kaXNwYXRjaChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChlMykpOwogICAgICAgICAgICB9LCBfYXJyYXlidWZmZXI6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJhcnJheWJ1ZmZlcjoiKSwgdGhpcy5kaXNwYXRjaChuZXcgVWludDhBcnJheShlMykpOwogICAgICAgICAgICB9LCBfdXJsOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB1MygidXJsOiIgKyBlMy50b1N0cmluZygpKTsKICAgICAgICAgICAgfSwgX21hcDogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICB1MygibWFwOiIpOwogICAgICAgICAgICAgIGUzID0gQXJyYXkuZnJvbShlMyk7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2FycmF5KGUzLCBmYWxzZSAhPT0gbzIudW5vcmRlcmVkU2V0cyk7CiAgICAgICAgICAgIH0sIF9zZXQ6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgdTMoInNldDoiKTsKICAgICAgICAgICAgICBlMyA9IEFycmF5LmZyb20oZTMpOwogICAgICAgICAgICAgIHJldHVybiB0aGlzLl9hcnJheShlMywgZmFsc2UgIT09IG8yLnVub3JkZXJlZFNldHMpOwogICAgICAgICAgICB9LCBfZmlsZTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImZpbGU6IiksIHRoaXMuZGlzcGF0Y2goW2UzLm5hbWUsIGUzLnNpemUsIGUzLnR5cGUsIGUzLmxhc3RNb2RmaWVkXSk7CiAgICAgICAgICAgIH0sIF9ibG9iOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICBpZiAobzIuaWdub3JlVW5rbm93bikgcmV0dXJuIHUzKCJbYmxvYl0iKTsKICAgICAgICAgICAgICB0aHJvdyBFcnJvcignSGFzaGluZyBCbG9iIG9iamVjdHMgaXMgY3VycmVudGx5IG5vdCBzdXBwb3J0ZWRcbihzZWUgaHR0cHM6Ly9naXRodWIuY29tL3B1bGVvcy9vYmplY3QtaGFzaC9pc3N1ZXMvMjYpXG5Vc2UgIm9wdGlvbnMucmVwbGFjZXIiIG9yICJvcHRpb25zLmlnbm9yZVVua25vd24iXG4nKTsKICAgICAgICAgICAgfSwgX2RvbXdpbmRvdzogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJkb213aW5kb3ciKTsKICAgICAgICAgICAgfSwgX2JpZ2ludDogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImJpZ2ludDoiICsgZTMudG9TdHJpbmcoKSk7CiAgICAgICAgICAgIH0sIF9wcm9jZXNzOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInByb2Nlc3MiKTsKICAgICAgICAgICAgfSwgX3RpbWVyOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInRpbWVyIik7CiAgICAgICAgICAgIH0sIF9waXBlOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInBpcGUiKTsKICAgICAgICAgICAgfSwgX3RjcDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJ0Y3AiKTsKICAgICAgICAgICAgfSwgX3VkcDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJ1ZHAiKTsKICAgICAgICAgICAgfSwgX3R0eTogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJ0dHkiKTsKICAgICAgICAgICAgfSwgX3N0YXR3YXRjaGVyOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInN0YXR3YXRjaGVyIik7CiAgICAgICAgICAgIH0sIF9zZWN1cmVjb250ZXh0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInNlY3VyZWNvbnRleHQiKTsKICAgICAgICAgICAgfSwgX2Nvbm5lY3Rpb246IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiB1MygiY29ubmVjdGlvbiIpOwogICAgICAgICAgICB9LCBfemxpYjogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJ6bGliIik7CiAgICAgICAgICAgIH0sIF9jb250ZXh0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImNvbnRleHQiKTsKICAgICAgICAgICAgfSwgX25vZGVzY3JpcHQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiB1Mygibm9kZXNjcmlwdCIpOwogICAgICAgICAgICB9LCBfaHR0cHBhcnNlcjogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJodHRwcGFyc2VyIik7CiAgICAgICAgICAgIH0sIF9kYXRhdmlldzogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJkYXRhdmlldyIpOwogICAgICAgICAgICB9LCBfc2lnbmFsOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInNpZ25hbCIpOwogICAgICAgICAgICB9LCBfZnNldmVudDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJmc2V2ZW50Iik7CiAgICAgICAgICAgIH0sIF90bHN3cmFwOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInRsc3dyYXAiKTsKICAgICAgICAgICAgfSB9OwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gbDIoKSB7CiAgICAgICAgICAgIHJldHVybiB7IGJ1ZjogIiIsIHdyaXRlOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHRoaXMuYnVmICs9IGUzOwogICAgICAgICAgICB9LCBlbmQ6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgdGhpcy5idWYgKz0gZTM7CiAgICAgICAgICAgIH0sIHJlYWQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiB0aGlzLmJ1ZjsKICAgICAgICAgICAgfSB9OwogICAgICAgICAgfQogICAgICAgICAgbTIud3JpdGVUb1N0cmVhbSA9IGZ1bmN0aW9uKGUzLCB0MiwgbjIpIHsKICAgICAgICAgICAgcmV0dXJuIHZvaWQgMCA9PT0gbjIgJiYgKG4yID0gdDIsIHQyID0ge30pLCBmMih0MiA9IHUyKGUzLCB0MiksIG4yKS5kaXNwYXRjaChlMyk7CiAgICAgICAgICB9OwogICAgICAgIH0pLmNhbGwodGhpcywgdzIoImxZcG9JMiIpLCAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygc2VsZiA/IHNlbGYgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDoge30sIHcyKCJidWZmZXIiKS5CdWZmZXIsIGFyZ3VtZW50c1szXSwgYXJndW1lbnRzWzRdLCBhcmd1bWVudHNbNV0sIGFyZ3VtZW50c1s2XSwgIi9mYWtlXzlhNWFhNDlkLmpzIiwgIi8iKTsKICAgICAgfSwgeyBidWZmZXI6IDMsIGNyeXB0bzogNSwgbFlwb0kyOiAxMSB9XSwgMjogW2Z1bmN0aW9uKGUyLCB0LCBmMikgewogICAgICAgICEoZnVuY3Rpb24oZTMsIHQyLCBuLCByMiwgbywgaTIsIHUyLCBzMiwgYTIpIHsKICAgICAgICAgICFmdW5jdGlvbihlNCkgewogICAgICAgICAgICB2YXIgYTMgPSAidW5kZWZpbmVkIiAhPSB0eXBlb2YgVWludDhBcnJheSA/IFVpbnQ4QXJyYXkgOiBBcnJheSwgdDMgPSAiKyIuY2hhckNvZGVBdCgwKSwgbjIgPSAiLyIuY2hhckNvZGVBdCgwKSwgcjMgPSAiMCIuY2hhckNvZGVBdCgwKSwgbzIgPSAiYSIuY2hhckNvZGVBdCgwKSwgaTMgPSAiQSIuY2hhckNvZGVBdCgwKSwgdTMgPSAiLSIuY2hhckNvZGVBdCgwKSwgczMgPSAiXyIuY2hhckNvZGVBdCgwKTsKICAgICAgICAgICAgZnVuY3Rpb24gZjMoZTUpIHsKICAgICAgICAgICAgICBlNSA9IGU1LmNoYXJDb2RlQXQoMCk7CiAgICAgICAgICAgICAgcmV0dXJuIGU1ID09PSB0MyB8fCBlNSA9PT0gdTMgPyA2MiA6IGU1ID09PSBuMiB8fCBlNSA9PT0gczMgPyA2MyA6IGU1IDwgcjMgPyAtMSA6IGU1IDwgcjMgKyAxMCA/IGU1IC0gcjMgKyAyNiArIDI2IDogZTUgPCBpMyArIDI2ID8gZTUgLSBpMyA6IGU1IDwgbzIgKyAyNiA/IGU1IC0gbzIgKyAyNiA6IHZvaWQgMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBlNC50b0J5dGVBcnJheSA9IGZ1bmN0aW9uKGU1KSB7CiAgICAgICAgICAgICAgdmFyIHQ0LCBuMzsKICAgICAgICAgICAgICBpZiAoMCA8IGU1Lmxlbmd0aCAlIDQpIHRocm93IG5ldyBFcnJvcigiSW52YWxpZCBzdHJpbmcuIExlbmd0aCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNCIpOwogICAgICAgICAgICAgIHZhciByNCA9IGU1Lmxlbmd0aCwgcjQgPSAiPSIgPT09IGU1LmNoYXJBdChyNCAtIDIpID8gMiA6ICI9IiA9PT0gZTUuY2hhckF0KHI0IC0gMSkgPyAxIDogMCwgbzMgPSBuZXcgYTMoMyAqIGU1Lmxlbmd0aCAvIDQgLSByNCksIGk0ID0gMCA8IHI0ID8gZTUubGVuZ3RoIC0gNCA6IGU1Lmxlbmd0aCwgdTQgPSAwOwogICAgICAgICAgICAgIGZ1bmN0aW9uIHM0KGU2KSB7CiAgICAgICAgICAgICAgICBvM1t1NCsrXSA9IGU2OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBmb3IgKHQ0ID0gMDsgdDQgPCBpNDsgdDQgKz0gNCwgMCkgczQoKDE2NzExNjgwICYgKG4zID0gZjMoZTUuY2hhckF0KHQ0KSkgPDwgMTggfCBmMyhlNS5jaGFyQXQodDQgKyAxKSkgPDwgMTIgfCBmMyhlNS5jaGFyQXQodDQgKyAyKSkgPDwgNiB8IGYzKGU1LmNoYXJBdCh0NCArIDMpKSkpID4+IDE2KSwgczQoKDY1MjgwICYgbjMpID4+IDgpLCBzNCgyNTUgJiBuMyk7CiAgICAgICAgICAgICAgcmV0dXJuIDIgPT0gcjQgPyBzNCgyNTUgJiAobjMgPSBmMyhlNS5jaGFyQXQodDQpKSA8PCAyIHwgZjMoZTUuY2hhckF0KHQ0ICsgMSkpID4+IDQpKSA6IDEgPT0gcjQgJiYgKHM0KChuMyA9IGYzKGU1LmNoYXJBdCh0NCkpIDw8IDEwIHwgZjMoZTUuY2hhckF0KHQ0ICsgMSkpIDw8IDQgfCBmMyhlNS5jaGFyQXQodDQgKyAyKSkgPj4gMikgPj4gOCAmIDI1NSksIHM0KDI1NSAmIG4zKSksIG8zOwogICAgICAgICAgICB9LCBlNC5mcm9tQnl0ZUFycmF5ID0gZnVuY3Rpb24oZTUpIHsKICAgICAgICAgICAgICB2YXIgdDQsIG4zLCByNCwgbzMsIGk0ID0gZTUubGVuZ3RoICUgMywgdTQgPSAiIjsKICAgICAgICAgICAgICBmdW5jdGlvbiBzNChlNikgewogICAgICAgICAgICAgICAgcmV0dXJuICJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvIi5jaGFyQXQoZTYpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBmb3IgKHQ0ID0gMCwgcjQgPSBlNS5sZW5ndGggLSBpNDsgdDQgPCByNDsgdDQgKz0gMykgbjMgPSAoZTVbdDRdIDw8IDE2KSArIChlNVt0NCArIDFdIDw8IDgpICsgZTVbdDQgKyAyXSwgdTQgKz0gczQoKG8zID0gbjMpID4+IDE4ICYgNjMpICsgczQobzMgPj4gMTIgJiA2MykgKyBzNChvMyA+PiA2ICYgNjMpICsgczQoNjMgJiBvMyk7CiAgICAgICAgICAgICAgc3dpdGNoIChpNCkgewogICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICB1NCA9ICh1NCArPSBzNCgobjMgPSBlNVtlNS5sZW5ndGggLSAxXSkgPj4gMikpICsgczQobjMgPDwgNCAmIDYzKSArICI9PSI7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgICB1NCA9ICh1NCA9ICh1NCArPSBzNCgobjMgPSAoZTVbZTUubGVuZ3RoIC0gMl0gPDwgOCkgKyBlNVtlNS5sZW5ndGggLSAxXSkgPj4gMTApKSArIHM0KG4zID4+IDQgJiA2MykpICsgczQobjMgPDwgMiAmIDYzKSArICI9IjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIHU0OwogICAgICAgICAgICB9OwogICAgICAgICAgfSh2b2lkIDAgPT09IGYyID8gdGhpcy5iYXNlNjRqcyA9IHt9IDogZjIpOwogICAgICAgIH0pLmNhbGwodGhpcywgZTIoImxZcG9JMiIpLCAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygc2VsZiA/IHNlbGYgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDoge30sIGUyKCJidWZmZXIiKS5CdWZmZXIsIGFyZ3VtZW50c1szXSwgYXJndW1lbnRzWzRdLCBhcmd1bWVudHNbNV0sIGFyZ3VtZW50c1s2XSwgIi9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9iYXNlNjQtanMvbGliL2I2NC5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYmFzZTY0LWpzL2xpYiIpOwogICAgICB9LCB7IGJ1ZmZlcjogMywgbFlwb0kyOiAxMSB9XSwgMzogW2Z1bmN0aW9uKE8sIGUyLCBIMikgewogICAgICAgICEoZnVuY3Rpb24oZTMsIG4sIGYyLCByMiwgaCwgcCwgZywgeSwgdzIpIHsKICAgICAgICAgIHZhciBhMiA9IE8oImJhc2U2NC1qcyIpLCBpMiA9IE8oImllZWU3NTQiKTsKICAgICAgICAgIGZ1bmN0aW9uIGYyKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIGYyKSkgcmV0dXJuIG5ldyBmMihlNCwgdDIsIG4yKTsKICAgICAgICAgICAgdmFyIHIzLCBvMiwgaTMsIHUzLCBzMyA9IHR5cGVvZiBlNDsKICAgICAgICAgICAgaWYgKCJiYXNlNjQiID09PSB0MiAmJiAic3RyaW5nIiA9PSBzMykgZm9yIChlNCA9ICh1MyA9IGU0KS50cmltID8gdTMudHJpbSgpIDogdTMucmVwbGFjZSgvXlxzK3xccyskL2csICIiKTsgZTQubGVuZ3RoICUgNCAhPSAwOyApIGU0ICs9ICI9IjsKICAgICAgICAgICAgaWYgKCJudW1iZXIiID09IHMzKSByMyA9IGoyKGU0KTsKICAgICAgICAgICAgZWxzZSBpZiAoInN0cmluZyIgPT0gczMpIHIzID0gZjIuYnl0ZUxlbmd0aChlNCwgdDIpOwogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICBpZiAoIm9iamVjdCIgIT0gczMpIHRocm93IG5ldyBFcnJvcigiRmlyc3QgYXJndW1lbnQgbmVlZHMgdG8gYmUgYSBudW1iZXIsIGFycmF5IG9yIHN0cmluZy4iKTsKICAgICAgICAgICAgICByMyA9IGoyKGU0Lmxlbmd0aCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGYyLl91c2VUeXBlZEFycmF5cyA/IG8yID0gZjIuX2F1Z21lbnQobmV3IFVpbnQ4QXJyYXkocjMpKSA6ICgobzIgPSB0aGlzKS5sZW5ndGggPSByMywgbzIuX2lzQnVmZmVyID0gdHJ1ZSksIGYyLl91c2VUeXBlZEFycmF5cyAmJiAibnVtYmVyIiA9PSB0eXBlb2YgZTQuYnl0ZUxlbmd0aCkgbzIuX3NldChlNCk7CiAgICAgICAgICAgIGVsc2UgaWYgKEModTMgPSBlNCkgfHwgZjIuaXNCdWZmZXIodTMpIHx8IHUzICYmICJvYmplY3QiID09IHR5cGVvZiB1MyAmJiAibnVtYmVyIiA9PSB0eXBlb2YgdTMubGVuZ3RoKSBmb3IgKGkzID0gMDsgaTMgPCByMzsgaTMrKykgZjIuaXNCdWZmZXIoZTQpID8gbzJbaTNdID0gZTQucmVhZFVJbnQ4KGkzKSA6IG8yW2kzXSA9IGU0W2kzXTsKICAgICAgICAgICAgZWxzZSBpZiAoInN0cmluZyIgPT0gczMpIG8yLndyaXRlKGU0LCAwLCB0Mik7CiAgICAgICAgICAgIGVsc2UgaWYgKCJudW1iZXIiID09IHMzICYmICFmMi5fdXNlVHlwZWRBcnJheXMgJiYgIW4yKSBmb3IgKGkzID0gMDsgaTMgPCByMzsgaTMrKykgbzJbaTNdID0gMDsKICAgICAgICAgICAgcmV0dXJuIG8yOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gYihlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICByZXR1cm4gZjIuX2NoYXJzV3JpdHRlbiA9IGMyKGZ1bmN0aW9uKGU1KSB7CiAgICAgICAgICAgICAgZm9yICh2YXIgdDMgPSBbXSwgbjMgPSAwOyBuMyA8IGU1Lmxlbmd0aDsgbjMrKykgdDMucHVzaCgyNTUgJiBlNS5jaGFyQ29kZUF0KG4zKSk7CiAgICAgICAgICAgICAgcmV0dXJuIHQzOwogICAgICAgICAgICB9KHQyKSwgZTQsIG4yLCByMyk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBtMihlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICByZXR1cm4gZjIuX2NoYXJzV3JpdHRlbiA9IGMyKGZ1bmN0aW9uKGU1KSB7CiAgICAgICAgICAgICAgZm9yICh2YXIgdDMsIG4zLCByNCA9IFtdLCBvMiA9IDA7IG8yIDwgZTUubGVuZ3RoOyBvMisrKSBuMyA9IGU1LmNoYXJDb2RlQXQobzIpLCB0MyA9IG4zID4+IDgsIG4zID0gbjMgJSAyNTYsIHI0LnB1c2gobjMpLCByNC5wdXNoKHQzKTsKICAgICAgICAgICAgICByZXR1cm4gcjQ7CiAgICAgICAgICAgIH0odDIpLCBlNCwgbjIsIHIzKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHYyKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgdmFyIHIzID0gIiI7CiAgICAgICAgICAgIG4yID0gTWF0aC5taW4oZTQubGVuZ3RoLCBuMik7CiAgICAgICAgICAgIGZvciAodmFyIG8yID0gdDI7IG8yIDwgbjI7IG8yKyspIHIzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZTRbbzJdKTsKICAgICAgICAgICAgcmV0dXJuIHIzOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gbyhlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICByMyB8fCAoZCgiYm9vbGVhbiIgPT0gdHlwZW9mIG4yLCAibWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbiIpLCBkKG51bGwgIT0gdDIsICJtaXNzaW5nIG9mZnNldCIpLCBkKHQyICsgMSA8IGU0Lmxlbmd0aCwgIlRyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoIikpOwogICAgICAgICAgICB2YXIgbzIsIHIzID0gZTQubGVuZ3RoOwogICAgICAgICAgICBpZiAoIShyMyA8PSB0MikpIHJldHVybiBuMiA/IChvMiA9IGU0W3QyXSwgdDIgKyAxIDwgcjMgJiYgKG8yIHw9IGU0W3QyICsgMV0gPDwgOCkpIDogKG8yID0gZTRbdDJdIDw8IDgsIHQyICsgMSA8IHIzICYmIChvMiB8PSBlNFt0MiArIDFdKSksIG8yOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gdTIoZTQsIHQyLCBuMiwgcjMpIHsKICAgICAgICAgICAgcjMgfHwgKGQoImJvb2xlYW4iID09IHR5cGVvZiBuMiwgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZChudWxsICE9IHQyLCAibWlzc2luZyBvZmZzZXQiKSwgZCh0MiArIDMgPCBlNC5sZW5ndGgsICJUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCIpKTsKICAgICAgICAgICAgdmFyIG8yLCByMyA9IGU0Lmxlbmd0aDsKICAgICAgICAgICAgaWYgKCEocjMgPD0gdDIpKSByZXR1cm4gbjIgPyAodDIgKyAyIDwgcjMgJiYgKG8yID0gZTRbdDIgKyAyXSA8PCAxNiksIHQyICsgMSA8IHIzICYmIChvMiB8PSBlNFt0MiArIDFdIDw8IDgpLCBvMiB8PSBlNFt0Ml0sIHQyICsgMyA8IHIzICYmIChvMiArPSBlNFt0MiArIDNdIDw8IDI0ID4+PiAwKSkgOiAodDIgKyAxIDwgcjMgJiYgKG8yID0gZTRbdDIgKyAxXSA8PCAxNiksIHQyICsgMiA8IHIzICYmIChvMiB8PSBlNFt0MiArIDJdIDw8IDgpLCB0MiArIDMgPCByMyAmJiAobzIgfD0gZTRbdDIgKyAzXSksIG8yICs9IGU0W3QyXSA8PCAyNCA+Pj4gMCksIG8yOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gXyhlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICBpZiAocjMgfHwgKGQoImJvb2xlYW4iID09IHR5cGVvZiBuMiwgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZChudWxsICE9IHQyLCAibWlzc2luZyBvZmZzZXQiKSwgZCh0MiArIDEgPCBlNC5sZW5ndGgsICJUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCIpKSwgIShlNC5sZW5ndGggPD0gdDIpKSByZXR1cm4gcjMgPSBvKGU0LCB0MiwgbjIsIHRydWUpLCAzMjc2OCAmIHIzID8gLTEgKiAoNjU1MzUgLSByMyArIDEpIDogcjM7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBFKGU0LCB0MiwgbjIsIHIzKSB7CiAgICAgICAgICAgIGlmIChyMyB8fCAoZCgiYm9vbGVhbiIgPT0gdHlwZW9mIG4yLCAibWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbiIpLCBkKG51bGwgIT0gdDIsICJtaXNzaW5nIG9mZnNldCIpLCBkKHQyICsgMyA8IGU0Lmxlbmd0aCwgIlRyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoIikpLCAhKGU0Lmxlbmd0aCA8PSB0MikpIHJldHVybiByMyA9IHUyKGU0LCB0MiwgbjIsIHRydWUpLCAyMTQ3NDgzNjQ4ICYgcjMgPyAtMSAqICg0Mjk0OTY3Mjk1IC0gcjMgKyAxKSA6IHIzOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gSShlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICByZXR1cm4gcjMgfHwgKGQoImJvb2xlYW4iID09IHR5cGVvZiBuMiwgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZCh0MiArIDMgPCBlNC5sZW5ndGgsICJUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCIpKSwgaTIucmVhZChlNCwgdDIsIG4yLCAyMywgNCk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBBKGU0LCB0MiwgbjIsIHIzKSB7CiAgICAgICAgICAgIHJldHVybiByMyB8fCAoZCgiYm9vbGVhbiIgPT0gdHlwZW9mIG4yLCAibWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbiIpLCBkKHQyICsgNyA8IGU0Lmxlbmd0aCwgIlRyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoIikpLCBpMi5yZWFkKGU0LCB0MiwgbjIsIDUyLCA4KTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHMyKGU0LCB0MiwgbjIsIHIzLCBvMikgewogICAgICAgICAgICBvMiB8fCAoZChudWxsICE9IHQyLCAibWlzc2luZyB2YWx1ZSIpLCBkKCJib29sZWFuIiA9PSB0eXBlb2YgcjMsICJtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuIiksIGQobnVsbCAhPSBuMiwgIm1pc3Npbmcgb2Zmc2V0IiksIGQobjIgKyAxIDwgZTQubGVuZ3RoLCAidHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoIiksIFkyKHQyLCA2NTUzNSkpOwogICAgICAgICAgICBvMiA9IGU0Lmxlbmd0aDsKICAgICAgICAgICAgaWYgKCEobzIgPD0gbjIpKSBmb3IgKHZhciBpMyA9IDAsIHUzID0gTWF0aC5taW4obzIgLSBuMiwgMik7IGkzIDwgdTM7IGkzKyspIGU0W24yICsgaTNdID0gKHQyICYgMjU1IDw8IDggKiAocjMgPyBpMyA6IDEgLSBpMykpID4+PiA4ICogKHIzID8gaTMgOiAxIC0gaTMpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gbDIoZTQsIHQyLCBuMiwgcjMsIG8yKSB7CiAgICAgICAgICAgIG8yIHx8IChkKG51bGwgIT0gdDIsICJtaXNzaW5nIHZhbHVlIiksIGQoImJvb2xlYW4iID09IHR5cGVvZiByMywgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZChudWxsICE9IG4yLCAibWlzc2luZyBvZmZzZXQiKSwgZChuMiArIDMgPCBlNC5sZW5ndGgsICJ0cnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgiKSwgWTIodDIsIDQyOTQ5NjcyOTUpKTsKICAgICAgICAgICAgbzIgPSBlNC5sZW5ndGg7CiAgICAgICAgICAgIGlmICghKG8yIDw9IG4yKSkgZm9yICh2YXIgaTMgPSAwLCB1MyA9IE1hdGgubWluKG8yIC0gbjIsIDQpOyBpMyA8IHUzOyBpMysrKSBlNFtuMiArIGkzXSA9IHQyID4+PiA4ICogKHIzID8gaTMgOiAzIC0gaTMpICYgMjU1OwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gQjIoZTQsIHQyLCBuMiwgcjMsIG8yKSB7CiAgICAgICAgICAgIG8yIHx8IChkKG51bGwgIT0gdDIsICJtaXNzaW5nIHZhbHVlIiksIGQoImJvb2xlYW4iID09IHR5cGVvZiByMywgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZChudWxsICE9IG4yLCAibWlzc2luZyBvZmZzZXQiKSwgZChuMiArIDEgPCBlNC5sZW5ndGgsICJUcnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgiKSwgRih0MiwgMzI3NjcsIC0zMjc2OCkpLCBlNC5sZW5ndGggPD0gbjIgfHwgczIoZTQsIDAgPD0gdDIgPyB0MiA6IDY1NTM1ICsgdDIgKyAxLCBuMiwgcjMsIG8yKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEwyKGU0LCB0MiwgbjIsIHIzLCBvMikgewogICAgICAgICAgICBvMiB8fCAoZChudWxsICE9IHQyLCAibWlzc2luZyB2YWx1ZSIpLCBkKCJib29sZWFuIiA9PSB0eXBlb2YgcjMsICJtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuIiksIGQobnVsbCAhPSBuMiwgIm1pc3Npbmcgb2Zmc2V0IiksIGQobjIgKyAzIDwgZTQubGVuZ3RoLCAiVHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoIiksIEYodDIsIDIxNDc0ODM2NDcsIC0yMTQ3NDgzNjQ4KSksIGU0Lmxlbmd0aCA8PSBuMiB8fCBsMihlNCwgMCA8PSB0MiA/IHQyIDogNDI5NDk2NzI5NSArIHQyICsgMSwgbjIsIHIzLCBvMik7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBVMihlNCwgdDIsIG4yLCByMywgbzIpIHsKICAgICAgICAgICAgbzIgfHwgKGQobnVsbCAhPSB0MiwgIm1pc3NpbmcgdmFsdWUiKSwgZCgiYm9vbGVhbiIgPT0gdHlwZW9mIHIzLCAibWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbiIpLCBkKG51bGwgIT0gbjIsICJtaXNzaW5nIG9mZnNldCIpLCBkKG4yICsgMyA8IGU0Lmxlbmd0aCwgIlRyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCIpLCBEMih0MiwgMzQwMjgyMzQ2NjM4NTI4ODZlMjIsIC0zNDAyODIzNDY2Mzg1Mjg4NmUyMikpLCBlNC5sZW5ndGggPD0gbjIgfHwgaTIud3JpdGUoZTQsIHQyLCBuMiwgcjMsIDIzLCA0KTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHgoZTQsIHQyLCBuMiwgcjMsIG8yKSB7CiAgICAgICAgICAgIG8yIHx8IChkKG51bGwgIT0gdDIsICJtaXNzaW5nIHZhbHVlIiksIGQoImJvb2xlYW4iID09IHR5cGVvZiByMywgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZChudWxsICE9IG4yLCAibWlzc2luZyBvZmZzZXQiKSwgZChuMiArIDcgPCBlNC5sZW5ndGgsICJUcnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgiKSwgRDIodDIsIDE3OTc2OTMxMzQ4NjIzMTU3ZTI5MiwgLTE3OTc2OTMxMzQ4NjIzMTU3ZTI5MikpLCBlNC5sZW5ndGggPD0gbjIgfHwgaTIud3JpdGUoZTQsIHQyLCBuMiwgcjMsIDUyLCA4KTsKICAgICAgICAgIH0KICAgICAgICAgIEgyLkJ1ZmZlciA9IGYyLCBIMi5TbG93QnVmZmVyID0gZjIsIEgyLklOU1BFQ1RfTUFYX0JZVEVTID0gNTAsIGYyLnBvb2xTaXplID0gODE5MiwgZjIuX3VzZVR5cGVkQXJyYXlzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgdmFyIGU0ID0gbmV3IEFycmF5QnVmZmVyKDApLCB0MiA9IG5ldyBVaW50OEFycmF5KGU0KTsKICAgICAgICAgICAgICByZXR1cm4gdDIuZm9vID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gNDI7CiAgICAgICAgICAgICAgfSwgNDIgPT09IHQyLmZvbygpICYmICJmdW5jdGlvbiIgPT0gdHlwZW9mIHQyLnN1YmFycmF5OwogICAgICAgICAgICB9IGNhdGNoIChlNSkgewogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgICAgfSgpLCBmMi5pc0VuY29kaW5nID0gZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgc3dpdGNoIChTdHJpbmcoZTQpLnRvTG93ZXJDYXNlKCkpIHsKICAgICAgICAgICAgICBjYXNlICJoZXgiOgogICAgICAgICAgICAgIGNhc2UgInV0ZjgiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi04IjoKICAgICAgICAgICAgICBjYXNlICJhc2NpaSI6CiAgICAgICAgICAgICAgY2FzZSAiYmluYXJ5IjoKICAgICAgICAgICAgICBjYXNlICJiYXNlNjQiOgogICAgICAgICAgICAgIGNhc2UgInJhdyI6CiAgICAgICAgICAgICAgY2FzZSAidWNzMiI6CiAgICAgICAgICAgICAgY2FzZSAidWNzLTIiOgogICAgICAgICAgICAgIGNhc2UgInV0ZjE2bGUiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi0xNmxlIjoKICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0sIGYyLmlzQnVmZmVyID0gZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgcmV0dXJuICEobnVsbCA9PSBlNCB8fCAhZTQuX2lzQnVmZmVyKTsKICAgICAgICAgIH0sIGYyLmJ5dGVMZW5ndGggPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgdmFyIG4yOwogICAgICAgICAgICBzd2l0Y2ggKGU0ICs9ICIiLCB0MiB8fCAidXRmOCIpIHsKICAgICAgICAgICAgICBjYXNlICJoZXgiOgogICAgICAgICAgICAgICAgbjIgPSBlNC5sZW5ndGggLyAyOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAidXRmOCI6CiAgICAgICAgICAgICAgY2FzZSAidXRmLTgiOgogICAgICAgICAgICAgICAgbjIgPSBUKGU0KS5sZW5ndGg7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlICJhc2NpaSI6CiAgICAgICAgICAgICAgY2FzZSAiYmluYXJ5IjoKICAgICAgICAgICAgICBjYXNlICJyYXciOgogICAgICAgICAgICAgICAgbjIgPSBlNC5sZW5ndGg7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlICJiYXNlNjQiOgogICAgICAgICAgICAgICAgbjIgPSBNMihlNCkubGVuZ3RoOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAidWNzMiI6CiAgICAgICAgICAgICAgY2FzZSAidWNzLTIiOgogICAgICAgICAgICAgIGNhc2UgInV0ZjE2bGUiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi0xNmxlIjoKICAgICAgICAgICAgICAgIG4yID0gMiAqIGU0Lmxlbmd0aDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlVua25vd24gZW5jb2RpbmciKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbjI7CiAgICAgICAgICB9LCBmMi5jb25jYXQgPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgaWYgKGQoQyhlNCksICJVc2FnZTogQnVmZmVyLmNvbmNhdChsaXN0LCBbdG90YWxMZW5ndGhdKVxubGlzdCBzaG91bGQgYmUgYW4gQXJyYXkuIiksIDAgPT09IGU0Lmxlbmd0aCkgcmV0dXJuIG5ldyBmMigwKTsKICAgICAgICAgICAgaWYgKDEgPT09IGU0Lmxlbmd0aCkgcmV0dXJuIGU0WzBdOwogICAgICAgICAgICBpZiAoIm51bWJlciIgIT0gdHlwZW9mIHQyKSBmb3IgKG8yID0gdDIgPSAwOyBvMiA8IGU0Lmxlbmd0aDsgbzIrKykgdDIgKz0gZTRbbzJdLmxlbmd0aDsKICAgICAgICAgICAgZm9yICh2YXIgbjIgPSBuZXcgZjIodDIpLCByMyA9IDAsIG8yID0gMDsgbzIgPCBlNC5sZW5ndGg7IG8yKyspIHsKICAgICAgICAgICAgICB2YXIgaTMgPSBlNFtvMl07CiAgICAgICAgICAgICAgaTMuY29weShuMiwgcjMpLCByMyArPSBpMy5sZW5ndGg7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIG4yOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24oZTQsIHQyLCBuMiwgcjMpIHsKICAgICAgICAgICAgaXNGaW5pdGUodDIpID8gaXNGaW5pdGUobjIpIHx8IChyMyA9IG4yLCBuMiA9IHZvaWQgMCkgOiAoYTMgPSByMywgcjMgPSB0MiwgdDIgPSBuMiwgbjIgPSBhMyksIHQyID0gTnVtYmVyKHQyKSB8fCAwOwogICAgICAgICAgICB2YXIgbzIsIGkzLCB1MywgczMsIGEzID0gdGhpcy5sZW5ndGggLSB0MjsKICAgICAgICAgICAgc3dpdGNoICgoIW4yIHx8IGEzIDwgKG4yID0gTnVtYmVyKG4yKSkpICYmIChuMiA9IGEzKSwgcjMgPSBTdHJpbmcocjMgfHwgInV0ZjgiKS50b0xvd2VyQ2FzZSgpKSB7CiAgICAgICAgICAgICAgY2FzZSAiaGV4IjoKICAgICAgICAgICAgICAgIG8yID0gZnVuY3Rpb24oZTUsIHQzLCBuMywgcjQpIHsKICAgICAgICAgICAgICAgICAgbjMgPSBOdW1iZXIobjMpIHx8IDA7CiAgICAgICAgICAgICAgICAgIHZhciBvMyA9IGU1Lmxlbmd0aCAtIG4zOwogICAgICAgICAgICAgICAgICAoIXI0IHx8IG8zIDwgKHI0ID0gTnVtYmVyKHI0KSkpICYmIChyNCA9IG8zKSwgZCgobzMgPSB0My5sZW5ndGgpICUgMiA9PSAwLCAiSW52YWxpZCBoZXggc3RyaW5nIiksIG8zIC8gMiA8IHI0ICYmIChyNCA9IG8zIC8gMik7CiAgICAgICAgICAgICAgICAgIGZvciAodmFyIGk0ID0gMDsgaTQgPCByNDsgaTQrKykgewogICAgICAgICAgICAgICAgICAgIHZhciB1NCA9IHBhcnNlSW50KHQzLnN1YnN0cigyICogaTQsIDIpLCAxNik7CiAgICAgICAgICAgICAgICAgICAgZCghaXNOYU4odTQpLCAiSW52YWxpZCBoZXggc3RyaW5nIiksIGU1W24zICsgaTRdID0gdTQ7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgcmV0dXJuIGYyLl9jaGFyc1dyaXR0ZW4gPSAyICogaTQsIGk0OwogICAgICAgICAgICAgICAgfSh0aGlzLCBlNCwgdDIsIG4yKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgInV0ZjgiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi04IjoKICAgICAgICAgICAgICAgIGkzID0gdGhpcywgdTMgPSB0MiwgczMgPSBuMiwgbzIgPSBmMi5fY2hhcnNXcml0dGVuID0gYzIoVChlNCksIGkzLCB1MywgczMpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAiYXNjaWkiOgogICAgICAgICAgICAgIGNhc2UgImJpbmFyeSI6CiAgICAgICAgICAgICAgICBvMiA9IGIodGhpcywgZTQsIHQyLCBuMik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlICJiYXNlNjQiOgogICAgICAgICAgICAgICAgaTMgPSB0aGlzLCB1MyA9IHQyLCBzMyA9IG4yLCBvMiA9IGYyLl9jaGFyc1dyaXR0ZW4gPSBjMihNMihlNCksIGkzLCB1MywgczMpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAidWNzMiI6CiAgICAgICAgICAgICAgY2FzZSAidWNzLTIiOgogICAgICAgICAgICAgIGNhc2UgInV0ZjE2bGUiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi0xNmxlIjoKICAgICAgICAgICAgICAgIG8yID0gbTIodGhpcywgZTQsIHQyLCBuMik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJVbmtub3duIGVuY29kaW5nIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIG8yOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oZTQsIHQyLCBuMikgewogICAgICAgICAgICB2YXIgcjMsIG8yLCBpMywgdTMsIHMzID0gdGhpczsKICAgICAgICAgICAgaWYgKGU0ID0gU3RyaW5nKGU0IHx8ICJ1dGY4IikudG9Mb3dlckNhc2UoKSwgdDIgPSBOdW1iZXIodDIpIHx8IDAsIChuMiA9IHZvaWQgMCAhPT0gbjIgPyBOdW1iZXIobjIpIDogczMubGVuZ3RoKSA9PT0gdDIpIHJldHVybiAiIjsKICAgICAgICAgICAgc3dpdGNoIChlNCkgewogICAgICAgICAgICAgIGNhc2UgImhleCI6CiAgICAgICAgICAgICAgICByMyA9IGZ1bmN0aW9uKGU1LCB0MywgbjMpIHsKICAgICAgICAgICAgICAgICAgdmFyIHI0ID0gZTUubGVuZ3RoOwogICAgICAgICAgICAgICAgICAoIXQzIHx8IHQzIDwgMCkgJiYgKHQzID0gMCk7CiAgICAgICAgICAgICAgICAgICghbjMgfHwgbjMgPCAwIHx8IHI0IDwgbjMpICYmIChuMyA9IHI0KTsKICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbzMgPSAiIiwgaTQgPSB0MzsgaTQgPCBuMzsgaTQrKykgbzMgKz0gazIoZTVbaTRdKTsKICAgICAgICAgICAgICAgICAgcmV0dXJuIG8zOwogICAgICAgICAgICAgICAgfShzMywgdDIsIG4yKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgInV0ZjgiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi04IjoKICAgICAgICAgICAgICAgIHIzID0gZnVuY3Rpb24oZTUsIHQzLCBuMykgewogICAgICAgICAgICAgICAgICB2YXIgcjQgPSAiIiwgbzMgPSAiIjsKICAgICAgICAgICAgICAgICAgbjMgPSBNYXRoLm1pbihlNS5sZW5ndGgsIG4zKTsKICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaTQgPSB0MzsgaTQgPCBuMzsgaTQrKykgZTVbaTRdIDw9IDEyNyA/IChyNCArPSBOKG8zKSArIFN0cmluZy5mcm9tQ2hhckNvZGUoZTVbaTRdKSwgbzMgPSAiIikgOiBvMyArPSAiJSIgKyBlNVtpNF0udG9TdHJpbmcoMTYpOwogICAgICAgICAgICAgICAgICByZXR1cm4gcjQgKyBOKG8zKTsKICAgICAgICAgICAgICAgIH0oczMsIHQyLCBuMik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlICJhc2NpaSI6CiAgICAgICAgICAgICAgY2FzZSAiYmluYXJ5IjoKICAgICAgICAgICAgICAgIHIzID0gdjIoczMsIHQyLCBuMik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlICJiYXNlNjQiOgogICAgICAgICAgICAgICAgbzIgPSBzMywgdTMgPSBuMiwgcjMgPSAwID09PSAoaTMgPSB0MikgJiYgdTMgPT09IG8yLmxlbmd0aCA/IGEyLmZyb21CeXRlQXJyYXkobzIpIDogYTIuZnJvbUJ5dGVBcnJheShvMi5zbGljZShpMywgdTMpKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgInVjczIiOgogICAgICAgICAgICAgIGNhc2UgInVjcy0yIjoKICAgICAgICAgICAgICBjYXNlICJ1dGYxNmxlIjoKICAgICAgICAgICAgICBjYXNlICJ1dGYtMTZsZSI6CiAgICAgICAgICAgICAgICByMyA9IGZ1bmN0aW9uKGU1LCB0MywgbjMpIHsKICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcjQgPSBlNS5zbGljZSh0MywgbjMpLCBvMyA9ICIiLCBpNCA9IDA7IGk0IDwgcjQubGVuZ3RoOyBpNCArPSAyKSBvMyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHI0W2k0XSArIDI1NiAqIHI0W2k0ICsgMV0pOwogICAgICAgICAgICAgICAgICByZXR1cm4gbzM7CiAgICAgICAgICAgICAgICB9KHMzLCB0MiwgbjIpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiVW5rbm93biBlbmNvZGluZyIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiByMzsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogIkJ1ZmZlciIsIGRhdGE6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHRoaXMuX2FyciB8fCB0aGlzLCAwKSB9OwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbihlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICBpZiAodDIgPSB0MiB8fCAwLCAocjMgPSByMyB8fCAwID09PSByMyA/IHIzIDogdGhpcy5sZW5ndGgpICE9PSAobjIgPSBuMiB8fCAwKSAmJiAwICE9PSBlNC5sZW5ndGggJiYgMCAhPT0gdGhpcy5sZW5ndGgpIHsKICAgICAgICAgICAgICBkKG4yIDw9IHIzLCAic291cmNlRW5kIDwgc291cmNlU3RhcnQiKSwgZCgwIDw9IHQyICYmIHQyIDwgZTQubGVuZ3RoLCAidGFyZ2V0U3RhcnQgb3V0IG9mIGJvdW5kcyIpLCBkKDAgPD0gbjIgJiYgbjIgPCB0aGlzLmxlbmd0aCwgInNvdXJjZVN0YXJ0IG91dCBvZiBib3VuZHMiKSwgZCgwIDw9IHIzICYmIHIzIDw9IHRoaXMubGVuZ3RoLCAic291cmNlRW5kIG91dCBvZiBib3VuZHMiKSwgcjMgPiB0aGlzLmxlbmd0aCAmJiAocjMgPSB0aGlzLmxlbmd0aCk7CiAgICAgICAgICAgICAgdmFyIG8yID0gKHIzID0gZTQubGVuZ3RoIC0gdDIgPCByMyAtIG4yID8gZTQubGVuZ3RoIC0gdDIgKyBuMiA6IHIzKSAtIG4yOwogICAgICAgICAgICAgIGlmIChvMiA8IDEwMCB8fCAhZjIuX3VzZVR5cGVkQXJyYXlzKSBmb3IgKHZhciBpMyA9IDA7IGkzIDwgbzI7IGkzKyspIGU0W2kzICsgdDJdID0gdGhpc1tpMyArIG4yXTsKICAgICAgICAgICAgICBlbHNlIGU0Ll9zZXQodGhpcy5zdWJhcnJheShuMiwgbjIgKyBvMiksIHQyKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24oZTQsIHQyKSB7CiAgICAgICAgICAgIHZhciBuMiA9IHRoaXMubGVuZ3RoOwogICAgICAgICAgICBpZiAoZTQgPSBTMihlNCwgbjIsIDApLCB0MiA9IFMyKHQyLCBuMiwgbjIpLCBmMi5fdXNlVHlwZWRBcnJheXMpIHJldHVybiBmMi5fYXVnbWVudCh0aGlzLnN1YmFycmF5KGU0LCB0MikpOwogICAgICAgICAgICBmb3IgKHZhciByMyA9IHQyIC0gZTQsIG8yID0gbmV3IGYyKHIzLCB2b2lkIDAsIHRydWUpLCBpMyA9IDA7IGkzIDwgcjM7IGkzKyspIG8yW2kzXSA9IHRoaXNbaTMgKyBlNF07CiAgICAgICAgICAgIHJldHVybiBvMjsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbihlNCkgewogICAgICAgICAgICByZXR1cm4gY29uc29sZS5sb2coIi5nZXQoKSBpcyBkZXByZWNhdGVkLiBBY2Nlc3MgdXNpbmcgYXJyYXkgaW5kZXhlcyBpbnN0ZWFkLiIpLCB0aGlzLnJlYWRVSW50OChlNCk7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24oZTQsIHQyKSB7CiAgICAgICAgICAgIHJldHVybiBjb25zb2xlLmxvZygiLnNldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuIiksIHRoaXMud3JpdGVVSW50OChlNCwgdDIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWRVSW50OCA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICBpZiAodDIgfHwgKGQobnVsbCAhPSBlNCwgIm1pc3Npbmcgb2Zmc2V0IiksIGQoZTQgPCB0aGlzLmxlbmd0aCwgIlRyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoIikpLCAhKGU0ID49IHRoaXMubGVuZ3RoKSkgcmV0dXJuIHRoaXNbZTRdOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWRVSW50MTZMRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gbyh0aGlzLCBlNCwgdHJ1ZSwgdDIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWRVSW50MTZCRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gbyh0aGlzLCBlNCwgZmFsc2UsIHQyKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS5yZWFkVUludDMyTEUgPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgcmV0dXJuIHUyKHRoaXMsIGU0LCB0cnVlLCB0Mik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUucmVhZFVJbnQzMkJFID0gZnVuY3Rpb24oZTQsIHQyKSB7CiAgICAgICAgICAgIHJldHVybiB1Mih0aGlzLCBlNCwgZmFsc2UsIHQyKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS5yZWFkSW50OCA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICBpZiAodDIgfHwgKGQobnVsbCAhPSBlNCwgIm1pc3Npbmcgb2Zmc2V0IiksIGQoZTQgPCB0aGlzLmxlbmd0aCwgIlRyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoIikpLCAhKGU0ID49IHRoaXMubGVuZ3RoKSkgcmV0dXJuIDEyOCAmIHRoaXNbZTRdID8gLTEgKiAoMjU1IC0gdGhpc1tlNF0gKyAxKSA6IHRoaXNbZTRdOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWRJbnQxNkxFID0gZnVuY3Rpb24oZTQsIHQyKSB7CiAgICAgICAgICAgIHJldHVybiBfKHRoaXMsIGU0LCB0cnVlLCB0Mik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUucmVhZEludDE2QkUgPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgcmV0dXJuIF8odGhpcywgZTQsIGZhbHNlLCB0Mik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUucmVhZEludDMyTEUgPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgcmV0dXJuIEUodGhpcywgZTQsIHRydWUsIHQyKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS5yZWFkSW50MzJCRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gRSh0aGlzLCBlNCwgZmFsc2UsIHQyKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS5yZWFkRmxvYXRMRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gSSh0aGlzLCBlNCwgdHJ1ZSwgdDIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWRGbG9hdEJFID0gZnVuY3Rpb24oZTQsIHQyKSB7CiAgICAgICAgICAgIHJldHVybiBJKHRoaXMsIGU0LCBmYWxzZSwgdDIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWREb3VibGVMRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gQSh0aGlzLCBlNCwgdHJ1ZSwgdDIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWREb3VibGVCRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gQSh0aGlzLCBlNCwgZmFsc2UsIHQyKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS53cml0ZVVJbnQ4ID0gZnVuY3Rpb24oZTQsIHQyLCBuMikgewogICAgICAgICAgICBuMiB8fCAoZChudWxsICE9IGU0LCAibWlzc2luZyB2YWx1ZSIpLCBkKG51bGwgIT0gdDIsICJtaXNzaW5nIG9mZnNldCIpLCBkKHQyIDwgdGhpcy5sZW5ndGgsICJ0cnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgiKSwgWTIoZTQsIDI1NSkpLCB0MiA+PSB0aGlzLmxlbmd0aCB8fCAodGhpc1t0Ml0gPSBlNCk7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUud3JpdGVVSW50MTZMRSA9IGZ1bmN0aW9uKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgczIodGhpcywgZTQsIHQyLCB0cnVlLCBuMik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUud3JpdGVVSW50MTZCRSA9IGZ1bmN0aW9uKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgczIodGhpcywgZTQsIHQyLCBmYWxzZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlVUludDMyTEUgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIGwyKHRoaXMsIGU0LCB0MiwgdHJ1ZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlVUludDMyQkUgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIGwyKHRoaXMsIGU0LCB0MiwgZmFsc2UsIG4yKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIG4yIHx8IChkKG51bGwgIT0gZTQsICJtaXNzaW5nIHZhbHVlIiksIGQobnVsbCAhPSB0MiwgIm1pc3Npbmcgb2Zmc2V0IiksIGQodDIgPCB0aGlzLmxlbmd0aCwgIlRyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCIpLCBGKGU0LCAxMjcsIC0xMjgpKSwgdDIgPj0gdGhpcy5sZW5ndGggfHwgKDAgPD0gZTQgPyB0aGlzLndyaXRlVUludDgoZTQsIHQyLCBuMikgOiB0aGlzLndyaXRlVUludDgoMjU1ICsgZTQgKyAxLCB0MiwgbjIpKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS53cml0ZUludDE2TEUgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIEIyKHRoaXMsIGU0LCB0MiwgdHJ1ZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlSW50MTZCRSA9IGZ1bmN0aW9uKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgQjIodGhpcywgZTQsIHQyLCBmYWxzZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlSW50MzJMRSA9IGZ1bmN0aW9uKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgTDIodGhpcywgZTQsIHQyLCB0cnVlLCBuMik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUud3JpdGVJbnQzMkJFID0gZnVuY3Rpb24oZTQsIHQyLCBuMikgewogICAgICAgICAgICBMMih0aGlzLCBlNCwgdDIsIGZhbHNlLCBuMik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUud3JpdGVGbG9hdExFID0gZnVuY3Rpb24oZTQsIHQyLCBuMikgewogICAgICAgICAgICBVMih0aGlzLCBlNCwgdDIsIHRydWUsIG4yKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS53cml0ZUZsb2F0QkUgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIFUyKHRoaXMsIGU0LCB0MiwgZmFsc2UsIG4yKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS53cml0ZURvdWJsZUxFID0gZnVuY3Rpb24oZTQsIHQyLCBuMikgewogICAgICAgICAgICB4KHRoaXMsIGU0LCB0MiwgdHJ1ZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIHgodGhpcywgZTQsIHQyLCBmYWxzZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLmZpbGwgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIGlmICh0MiA9IHQyIHx8IDAsIG4yID0gbjIgfHwgdGhpcy5sZW5ndGgsIGQoIm51bWJlciIgPT0gdHlwZW9mIChlNCA9ICJzdHJpbmciID09IHR5cGVvZiAoZTQgPSBlNCB8fCAwKSA/IGU0LmNoYXJDb2RlQXQoMCkgOiBlNCkgJiYgIWlzTmFOKGU0KSwgInZhbHVlIGlzIG5vdCBhIG51bWJlciIpLCBkKHQyIDw9IG4yLCAiZW5kIDwgc3RhcnQiKSwgbjIgIT09IHQyICYmIDAgIT09IHRoaXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgZCgwIDw9IHQyICYmIHQyIDwgdGhpcy5sZW5ndGgsICJzdGFydCBvdXQgb2YgYm91bmRzIiksIGQoMCA8PSBuMiAmJiBuMiA8PSB0aGlzLmxlbmd0aCwgImVuZCBvdXQgb2YgYm91bmRzIik7CiAgICAgICAgICAgICAgZm9yICh2YXIgcjMgPSB0MjsgcjMgPCBuMjsgcjMrKykgdGhpc1tyM10gPSBlNDsKICAgICAgICAgICAgfQogICAgICAgICAgfSwgZjIucHJvdG90eXBlLmluc3BlY3QgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgZm9yICh2YXIgZTQgPSBbXSwgdDIgPSB0aGlzLmxlbmd0aCwgbjIgPSAwOyBuMiA8IHQyOyBuMisrKSBpZiAoZTRbbjJdID0gazIodGhpc1tuMl0pLCBuMiA9PT0gSDIuSU5TUEVDVF9NQVhfQllURVMpIHsKICAgICAgICAgICAgICBlNFtuMiArIDFdID0gIi4uLiI7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuICI8QnVmZmVyICIgKyBlNC5qb2luKCIgIikgKyAiPiI7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUudG9BcnJheUJ1ZmZlciA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBpZiAoInVuZGVmaW5lZCIgPT0gdHlwZW9mIFVpbnQ4QXJyYXkpIHRocm93IG5ldyBFcnJvcigiQnVmZmVyLnRvQXJyYXlCdWZmZXIgbm90IHN1cHBvcnRlZCBpbiB0aGlzIGJyb3dzZXIiKTsKICAgICAgICAgICAgaWYgKGYyLl91c2VUeXBlZEFycmF5cykgcmV0dXJuIG5ldyBmMih0aGlzKS5idWZmZXI7CiAgICAgICAgICAgIGZvciAodmFyIGU0ID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5sZW5ndGgpLCB0MiA9IDAsIG4yID0gZTQubGVuZ3RoOyB0MiA8IG4yOyB0MiArPSAxKSBlNFt0Ml0gPSB0aGlzW3QyXTsKICAgICAgICAgICAgcmV0dXJuIGU0LmJ1ZmZlcjsKICAgICAgICAgIH07CiAgICAgICAgICB2YXIgdCA9IGYyLnByb3RvdHlwZTsKICAgICAgICAgIGZ1bmN0aW9uIFMyKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgcmV0dXJuICJudW1iZXIiICE9IHR5cGVvZiBlNCA/IG4yIDogdDIgPD0gKGU0ID0gfn5lNCkgPyB0MiA6IDAgPD0gZTQgfHwgMCA8PSAoZTQgKz0gdDIpID8gZTQgOiAwOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gajIoZTQpIHsKICAgICAgICAgICAgcmV0dXJuIChlNCA9IH5+TWF0aC5jZWlsKCtlNCkpIDwgMCA/IDAgOiBlNDsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEMoZTQpIHsKICAgICAgICAgICAgcmV0dXJuIChBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uKGU1KSB7CiAgICAgICAgICAgICAgcmV0dXJuICJbb2JqZWN0IEFycmF5XSIgPT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChlNSk7CiAgICAgICAgICAgIH0pKGU0KTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGsyKGU0KSB7CiAgICAgICAgICAgIHJldHVybiBlNCA8IDE2ID8gIjAiICsgZTQudG9TdHJpbmcoMTYpIDogZTQudG9TdHJpbmcoMTYpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gVChlNCkgewogICAgICAgICAgICBmb3IgKHZhciB0MiA9IFtdLCBuMiA9IDA7IG4yIDwgZTQubGVuZ3RoOyBuMisrKSB7CiAgICAgICAgICAgICAgdmFyIHIzID0gZTQuY2hhckNvZGVBdChuMik7CiAgICAgICAgICAgICAgaWYgKHIzIDw9IDEyNykgdDIucHVzaChlNC5jaGFyQ29kZUF0KG4yKSk7CiAgICAgICAgICAgICAgZWxzZSBmb3IgKHZhciBvMiA9IG4yLCBpMyA9ICg1NTI5NiA8PSByMyAmJiByMyA8PSA1NzM0MyAmJiBuMisrLCBlbmNvZGVVUklDb21wb25lbnQoZTQuc2xpY2UobzIsIG4yICsgMSkpLnN1YnN0cigxKS5zcGxpdCgiJSIpKSwgdTMgPSAwOyB1MyA8IGkzLmxlbmd0aDsgdTMrKykgdDIucHVzaChwYXJzZUludChpM1t1M10sIDE2KSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHQyOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gTTIoZTQpIHsKICAgICAgICAgICAgcmV0dXJuIGEyLnRvQnl0ZUFycmF5KGU0KTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGMyKGU0LCB0MiwgbjIsIHIzKSB7CiAgICAgICAgICAgIGZvciAodmFyIG8yID0gMDsgbzIgPCByMyAmJiAhKG8yICsgbjIgPj0gdDIubGVuZ3RoIHx8IG8yID49IGU0Lmxlbmd0aCk7IG8yKyspIHQyW28yICsgbjJdID0gZTRbbzJdOwogICAgICAgICAgICByZXR1cm4gbzI7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBOKGU0KSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChlNCk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGU1KSB7CiAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoNjU1MzMpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBZMihlNCwgdDIpIHsKICAgICAgICAgICAgZCgibnVtYmVyIiA9PSB0eXBlb2YgZTQsICJjYW5ub3Qgd3JpdGUgYSBub24tbnVtYmVyIGFzIGEgbnVtYmVyIiksIGQoMCA8PSBlNCwgInNwZWNpZmllZCBhIG5lZ2F0aXZlIHZhbHVlIGZvciB3cml0aW5nIGFuIHVuc2lnbmVkIHZhbHVlIiksIGQoZTQgPD0gdDIsICJ2YWx1ZSBpcyBsYXJnZXIgdGhhbiBtYXhpbXVtIHZhbHVlIGZvciB0eXBlIiksIGQoTWF0aC5mbG9vcihlNCkgPT09IGU0LCAidmFsdWUgaGFzIGEgZnJhY3Rpb25hbCBjb21wb25lbnQiKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEYoZTQsIHQyLCBuMikgewogICAgICAgICAgICBkKCJudW1iZXIiID09IHR5cGVvZiBlNCwgImNhbm5vdCB3cml0ZSBhIG5vbi1udW1iZXIgYXMgYSBudW1iZXIiKSwgZChlNCA8PSB0MiwgInZhbHVlIGxhcmdlciB0aGFuIG1heGltdW0gYWxsb3dlZCB2YWx1ZSIpLCBkKG4yIDw9IGU0LCAidmFsdWUgc21hbGxlciB0aGFuIG1pbmltdW0gYWxsb3dlZCB2YWx1ZSIpLCBkKE1hdGguZmxvb3IoZTQpID09PSBlNCwgInZhbHVlIGhhcyBhIGZyYWN0aW9uYWwgY29tcG9uZW50Iik7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBEMihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIGQoIm51bWJlciIgPT0gdHlwZW9mIGU0LCAiY2Fubm90IHdyaXRlIGEgbm9uLW51bWJlciBhcyBhIG51bWJlciIpLCBkKGU0IDw9IHQyLCAidmFsdWUgbGFyZ2VyIHRoYW4gbWF4aW11bSBhbGxvd2VkIHZhbHVlIiksIGQobjIgPD0gZTQsICJ2YWx1ZSBzbWFsbGVyIHRoYW4gbWluaW11bSBhbGxvd2VkIHZhbHVlIik7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBkKGU0LCB0MikgewogICAgICAgICAgICBpZiAoIWU0KSB0aHJvdyBuZXcgRXJyb3IodDIgfHwgIkZhaWxlZCBhc3NlcnRpb24iKTsKICAgICAgICAgIH0KICAgICAgICAgIGYyLl9hdWdtZW50ID0gZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgcmV0dXJuIGU0Ll9pc0J1ZmZlciA9IHRydWUsIGU0Ll9nZXQgPSBlNC5nZXQsIGU0Ll9zZXQgPSBlNC5zZXQsIGU0LmdldCA9IHQuZ2V0LCBlNC5zZXQgPSB0LnNldCwgZTQud3JpdGUgPSB0LndyaXRlLCBlNC50b1N0cmluZyA9IHQudG9TdHJpbmcsIGU0LnRvTG9jYWxlU3RyaW5nID0gdC50b1N0cmluZywgZTQudG9KU09OID0gdC50b0pTT04sIGU0LmNvcHkgPSB0LmNvcHksIGU0LnNsaWNlID0gdC5zbGljZSwgZTQucmVhZFVJbnQ4ID0gdC5yZWFkVUludDgsIGU0LnJlYWRVSW50MTZMRSA9IHQucmVhZFVJbnQxNkxFLCBlNC5yZWFkVUludDE2QkUgPSB0LnJlYWRVSW50MTZCRSwgZTQucmVhZFVJbnQzMkxFID0gdC5yZWFkVUludDMyTEUsIGU0LnJlYWRVSW50MzJCRSA9IHQucmVhZFVJbnQzMkJFLCBlNC5yZWFkSW50OCA9IHQucmVhZEludDgsIGU0LnJlYWRJbnQxNkxFID0gdC5yZWFkSW50MTZMRSwgZTQucmVhZEludDE2QkUgPSB0LnJlYWRJbnQxNkJFLCBlNC5yZWFkSW50MzJMRSA9IHQucmVhZEludDMyTEUsIGU0LnJlYWRJbnQzMkJFID0gdC5yZWFkSW50MzJCRSwgZTQucmVhZEZsb2F0TEUgPSB0LnJlYWRGbG9hdExFLCBlNC5yZWFkRmxvYXRCRSA9IHQucmVhZEZsb2F0QkUsIGU0LnJlYWREb3VibGVMRSA9IHQucmVhZERvdWJsZUxFLCBlNC5yZWFkRG91YmxlQkUgPSB0LnJlYWREb3VibGVCRSwgZTQud3JpdGVVSW50OCA9IHQud3JpdGVVSW50OCwgZTQud3JpdGVVSW50MTZMRSA9IHQud3JpdGVVSW50MTZMRSwgZTQud3JpdGVVSW50MTZCRSA9IHQud3JpdGVVSW50MTZCRSwgZTQud3JpdGVVSW50MzJMRSA9IHQud3JpdGVVSW50MzJMRSwgZTQud3JpdGVVSW50MzJCRSA9IHQud3JpdGVVSW50MzJCRSwgZTQud3JpdGVJbnQ4ID0gdC53cml0ZUludDgsIGU0LndyaXRlSW50MTZMRSA9IHQud3JpdGVJbnQxNkxFLCBlNC53cml0ZUludDE2QkUgPSB0LndyaXRlSW50MTZCRSwgZTQud3JpdGVJbnQzMkxFID0gdC53cml0ZUludDMyTEUsIGU0LndyaXRlSW50MzJCRSA9IHQud3JpdGVJbnQzMkJFLCBlNC53cml0ZUZsb2F0TEUgPSB0LndyaXRlRmxvYXRMRSwgZTQud3JpdGVGbG9hdEJFID0gdC53cml0ZUZsb2F0QkUsIGU0LndyaXRlRG91YmxlTEUgPSB0LndyaXRlRG91YmxlTEUsIGU0LndyaXRlRG91YmxlQkUgPSB0LndyaXRlRG91YmxlQkUsIGU0LmZpbGwgPSB0LmZpbGwsIGU0Lmluc3BlY3QgPSB0Lmluc3BlY3QsIGU0LnRvQXJyYXlCdWZmZXIgPSB0LnRvQXJyYXlCdWZmZXIsIGU0OwogICAgICAgICAgfTsKICAgICAgICB9KS5jYWxsKHRoaXMsIE8oImxZcG9JMiIpLCAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygc2VsZiA/IHNlbGYgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDoge30sIE8oImJ1ZmZlciIpLkJ1ZmZlciwgYXJndW1lbnRzWzNdLCBhcmd1bWVudHNbNF0sIGFyZ3VtZW50c1s1XSwgYXJndW1lbnRzWzZdLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9pbmRleC5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnVmZmVyIik7CiAgICAgIH0sIHsgImJhc2U2NC1qcyI6IDIsIGJ1ZmZlcjogMywgaWVlZTc1NDogMTAsIGxZcG9JMjogMTEgfV0sIDQ6IFtmdW5jdGlvbihjMiwgZCwgZTIpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUzLCB0LCBhMiwgbiwgcjIsIG8sIGkyLCB1MiwgczIpIHsKICAgICAgICAgIHZhciBhMiA9IGMyKCJidWZmZXIiKS5CdWZmZXIsIGYyID0gNCwgbDIgPSBuZXcgYTIoZjIpOwogICAgICAgICAgbDIuZmlsbCgwKTsKICAgICAgICAgIGQuZXhwb3J0cyA9IHsgaGFzaDogZnVuY3Rpb24oZTQsIHQyLCBuMiwgcjMpIHsKICAgICAgICAgICAgZm9yICh2YXIgbzIgPSB0MihmdW5jdGlvbihlNSwgdDMpIHsKICAgICAgICAgICAgICBlNS5sZW5ndGggJSBmMiAhPSAwICYmIChuMyA9IGU1Lmxlbmd0aCArIChmMiAtIGU1Lmxlbmd0aCAlIGYyKSwgZTUgPSBhMi5jb25jYXQoW2U1LCBsMl0sIG4zKSk7CiAgICAgICAgICAgICAgZm9yICh2YXIgbjMsIHI0ID0gW10sIG8zID0gdDMgPyBlNS5yZWFkSW50MzJCRSA6IGU1LnJlYWRJbnQzMkxFLCBpNCA9IDA7IGk0IDwgZTUubGVuZ3RoOyBpNCArPSBmMikgcjQucHVzaChvMy5jYWxsKGU1LCBpNCkpOwogICAgICAgICAgICAgIHJldHVybiByNDsKICAgICAgICAgICAgfShlNCA9IGEyLmlzQnVmZmVyKGU0KSA/IGU0IDogbmV3IGEyKGU0KSwgcjMpLCA4ICogZTQubGVuZ3RoKSwgdDIgPSByMywgaTMgPSBuZXcgYTIobjIpLCB1MyA9IHQyID8gaTMud3JpdGVJbnQzMkJFIDogaTMud3JpdGVJbnQzMkxFLCBzMyA9IDA7IHMzIDwgbzIubGVuZ3RoOyBzMysrKSB1My5jYWxsKGkzLCBvMltzM10sIDQgKiBzMywgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiBpMzsKICAgICAgICAgIH0gfTsKICAgICAgICB9KS5jYWxsKHRoaXMsIGMyKCJsWXBvSTIiKSwgInVuZGVmaW5lZCIgIT0gdHlwZW9mIHNlbGYgPyBzZWxmIDogInVuZGVmaW5lZCIgIT0gdHlwZW9mIHdpbmRvdyA/IHdpbmRvdyA6IHt9LCBjMigiYnVmZmVyIikuQnVmZmVyLCBhcmd1bWVudHNbM10sIGFyZ3VtZW50c1s0XSwgYXJndW1lbnRzWzVdLCBhcmd1bWVudHNbNl0sICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkvaGVscGVycy5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkiKTsKICAgICAgfSwgeyBidWZmZXI6IDMsIGxZcG9JMjogMTEgfV0sIDU6IFtmdW5jdGlvbih2MiwgZTIsIF8pIHsKICAgICAgICAhKGZ1bmN0aW9uKGwyLCBjMiwgdTIsIGQsIGgsIHAsIGcsIHksIHcyKSB7CiAgICAgICAgICB2YXIgdTIgPSB2MigiYnVmZmVyIikuQnVmZmVyLCBlMyA9IHYyKCIuL3NoYSIpLCB0ID0gdjIoIi4vc2hhMjU2IiksIG4gPSB2MigiLi9ybmciKSwgYiA9IHsgc2hhMTogZTMsIHNoYTI1NjogdCwgbWQ1OiB2MigiLi9tZDUiKSB9LCBzMiA9IDY0LCBhMiA9IG5ldyB1MihzMik7CiAgICAgICAgICBmdW5jdGlvbiByMihlNCwgbjIpIHsKICAgICAgICAgICAgdmFyIHIzID0gYltlNCA9IGU0IHx8ICJzaGExIl0sIG8yID0gW107CiAgICAgICAgICAgIHJldHVybiByMyB8fCBpMigiYWxnb3JpdGhtOiIsIGU0LCAiaXMgbm90IHlldCBzdXBwb3J0ZWQiKSwgeyB1cGRhdGU6IGZ1bmN0aW9uKGU1KSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUyLmlzQnVmZmVyKGU1KSB8fCAoZTUgPSBuZXcgdTIoZTUpKSwgbzIucHVzaChlNSksIGU1Lmxlbmd0aCwgdGhpczsKICAgICAgICAgICAgfSwgZGlnZXN0OiBmdW5jdGlvbihlNSkgewogICAgICAgICAgICAgIHZhciB0MiA9IHUyLmNvbmNhdChvMiksIHQyID0gbjIgPyBmdW5jdGlvbihlNiwgdDMsIG4zKSB7CiAgICAgICAgICAgICAgICB1Mi5pc0J1ZmZlcih0MykgfHwgKHQzID0gbmV3IHUyKHQzKSksIHUyLmlzQnVmZmVyKG4zKSB8fCAobjMgPSBuZXcgdTIobjMpKSwgdDMubGVuZ3RoID4gczIgPyB0MyA9IGU2KHQzKSA6IHQzLmxlbmd0aCA8IHMyICYmICh0MyA9IHUyLmNvbmNhdChbdDMsIGEyXSwgczIpKTsKICAgICAgICAgICAgICAgIGZvciAodmFyIHI0ID0gbmV3IHUyKHMyKSwgbzMgPSBuZXcgdTIoczIpLCBpMyA9IDA7IGkzIDwgczI7IGkzKyspIHI0W2kzXSA9IDU0IF4gdDNbaTNdLCBvM1tpM10gPSA5MiBeIHQzW2kzXTsKICAgICAgICAgICAgICAgIHJldHVybiBuMyA9IGU2KHUyLmNvbmNhdChbcjQsIG4zXSkpLCBlNih1Mi5jb25jYXQoW28zLCBuM10pKTsKICAgICAgICAgICAgICB9KHIzLCBuMiwgdDIpIDogcjModDIpOwogICAgICAgICAgICAgIHJldHVybiBvMiA9IG51bGwsIGU1ID8gdDIudG9TdHJpbmcoZTUpIDogdDI7CiAgICAgICAgICAgIH0gfTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGkyKCkgewogICAgICAgICAgICB2YXIgZTQgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cykuam9pbigiICIpOwogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoW2U0LCAid2UgYWNjZXB0IHB1bGwgcmVxdWVzdHMiLCAiaHR0cDovL2dpdGh1Yi5jb20vZG9taW5pY3RhcnIvY3J5cHRvLWJyb3dzZXJpZnkiXS5qb2luKCJcbiIpKTsKICAgICAgICAgIH0KICAgICAgICAgIGEyLmZpbGwoMCksIF8uY3JlYXRlSGFzaCA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIHJldHVybiByMihlNCk7CiAgICAgICAgICB9LCBfLmNyZWF0ZUhtYWMgPSByMiwgXy5yYW5kb21CeXRlcyA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICBpZiAoIXQyIHx8ICF0Mi5jYWxsKSByZXR1cm4gbmV3IHUyKG4oZTQpKTsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICB0Mi5jYWxsKHRoaXMsIHZvaWQgMCwgbmV3IHUyKG4oZTQpKSk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGU1KSB7CiAgICAgICAgICAgICAgdDIoZTUpOwogICAgICAgICAgICB9CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIG8sIGYyID0gWyJjcmVhdGVDcmVkZW50aWFscyIsICJjcmVhdGVDaXBoZXIiLCAiY3JlYXRlQ2lwaGVyaXYiLCAiY3JlYXRlRGVjaXBoZXIiLCAiY3JlYXRlRGVjaXBoZXJpdiIsICJjcmVhdGVTaWduIiwgImNyZWF0ZVZlcmlmeSIsICJjcmVhdGVEaWZmaWVIZWxsbWFuIiwgInBia2RmMiJdLCBtMiA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIF9bZTRdID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgaTIoInNvcnJ5LCIsIGU0LCAiaXMgbm90IGltcGxlbWVudGVkIHlldCIpOwogICAgICAgICAgICB9OwogICAgICAgICAgfTsKICAgICAgICAgIGZvciAobyBpbiBmMikgbTIoZjJbb10pOwogICAgICAgIH0pLmNhbGwodGhpcywgdjIoImxZcG9JMiIpLCAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygc2VsZiA/IHNlbGYgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDoge30sIHYyKCJidWZmZXIiKS5CdWZmZXIsIGFyZ3VtZW50c1szXSwgYXJndW1lbnRzWzRdLCBhcmd1bWVudHNbNV0sIGFyZ3VtZW50c1s2XSwgIi9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9jcnlwdG8tYnJvd3NlcmlmeS9pbmRleC5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkiKTsKICAgICAgfSwgeyAiLi9tZDUiOiA2LCAiLi9ybmciOiA3LCAiLi9zaGEiOiA4LCAiLi9zaGEyNTYiOiA5LCBidWZmZXI6IDMsIGxZcG9JMjogMTEgfV0sIDY6IFtmdW5jdGlvbih3MiwgYiwgZTIpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUzLCByMiwgbywgaTIsIHUyLCBhMiwgZjIsIGwyLCB5KSB7CiAgICAgICAgICB2YXIgdCA9IHcyKCIuL2hlbHBlcnMiKTsKICAgICAgICAgIGZ1bmN0aW9uIG4oZTQsIHQyKSB7CiAgICAgICAgICAgIGU0W3QyID4+IDVdIHw9IDEyOCA8PCB0MiAlIDMyLCBlNFsxNCArICh0MiArIDY0ID4+PiA5IDw8IDQpXSA9IHQyOwogICAgICAgICAgICBmb3IgKHZhciBuMiA9IDE3MzI1ODQxOTMsIHIzID0gLTI3MTczMzg3OSwgbzIgPSAtMTczMjU4NDE5NCwgaTMgPSAyNzE3MzM4NzgsIHUzID0gMDsgdTMgPCBlNC5sZW5ndGg7IHUzICs9IDE2KSB7CiAgICAgICAgICAgICAgdmFyIHMzID0gbjIsIGEzID0gcjMsIGYzID0gbzIsIGwzID0gaTMsIG4yID0gYzIobjIsIHIzLCBvMiwgaTMsIGU0W3UzICsgMF0sIDcsIC02ODA4NzY5MzYpLCBpMyA9IGMyKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDFdLCAxMiwgLTM4OTU2NDU4NiksIG8yID0gYzIobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgMl0sIDE3LCA2MDYxMDU4MTkpLCByMyA9IGMyKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDNdLCAyMiwgLTEwNDQ1MjUzMzApOwogICAgICAgICAgICAgIG4yID0gYzIobjIsIHIzLCBvMiwgaTMsIGU0W3UzICsgNF0sIDcsIC0xNzY0MTg4OTcpLCBpMyA9IGMyKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDVdLCAxMiwgMTIwMDA4MDQyNiksIG8yID0gYzIobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgNl0sIDE3LCAtMTQ3MzIzMTM0MSksIHIzID0gYzIocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgN10sIDIyLCAtNDU3MDU5ODMpLCBuMiA9IGMyKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDhdLCA3LCAxNzcwMDM1NDE2KSwgaTMgPSBjMihpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyA5XSwgMTIsIC0xOTU4NDE0NDE3KSwgbzIgPSBjMihvMiwgaTMsIG4yLCByMywgZTRbdTMgKyAxMF0sIDE3LCAtNDIwNjMpLCByMyA9IGMyKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDExXSwgMjIsIC0xOTkwNDA0MTYyKSwgbjIgPSBjMihuMiwgcjMsIG8yLCBpMywgZTRbdTMgKyAxMl0sIDcsIDE4MDQ2MDM2ODIpLCBpMyA9IGMyKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDEzXSwgMTIsIC00MDM0MTEwMSksIG8yID0gYzIobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgMTRdLCAxNywgLTE1MDIwMDIyOTApLCBuMiA9IGQobjIsIHIzID0gYzIocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgMTVdLCAyMiwgMTIzNjUzNTMyOSksIG8yLCBpMywgZTRbdTMgKyAxXSwgNSwgLTE2NTc5NjUxMCksIGkzID0gZChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyA2XSwgOSwgLTEwNjk1MDE2MzIpLCBvMiA9IGQobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgMTFdLCAxNCwgNjQzNzE3NzEzKSwgcjMgPSBkKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDBdLCAyMCwgLTM3Mzg5NzMwMiksIG4yID0gZChuMiwgcjMsIG8yLCBpMywgZTRbdTMgKyA1XSwgNSwgLTcwMTU1ODY5MSksIGkzID0gZChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyAxMF0sIDksIDM4MDE2MDgzKSwgbzIgPSBkKG8yLCBpMywgbjIsIHIzLCBlNFt1MyArIDE1XSwgMTQsIC02NjA0NzgzMzUpLCByMyA9IGQocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgNF0sIDIwLCAtNDA1NTM3ODQ4KSwgbjIgPSBkKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDldLCA1LCA1Njg0NDY0MzgpLCBpMyA9IGQoaTMsIG4yLCByMywgbzIsIGU0W3UzICsgMTRdLCA5LCAtMTAxOTgwMzY5MCksIG8yID0gZChvMiwgaTMsIG4yLCByMywgZTRbdTMgKyAzXSwgMTQsIC0xODczNjM5NjEpLCByMyA9IGQocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgOF0sIDIwLCAxMTYzNTMxNTAxKSwgbjIgPSBkKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDEzXSwgNSwgLTE0NDQ2ODE0NjcpLCBpMyA9IGQoaTMsIG4yLCByMywgbzIsIGU0W3UzICsgMl0sIDksIC01MTQwMzc4NCksIG8yID0gZChvMiwgaTMsIG4yLCByMywgZTRbdTMgKyA3XSwgMTQsIDE3MzUzMjg0NzMpLCBuMiA9IGgobjIsIHIzID0gZChyMywgbzIsIGkzLCBuMiwgZTRbdTMgKyAxMl0sIDIwLCAtMTkyNjYwNzczNCksIG8yLCBpMywgZTRbdTMgKyA1XSwgNCwgLTM3ODU1OCksIGkzID0gaChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyA4XSwgMTEsIC0yMDIyNTc0NDYzKSwgbzIgPSBoKG8yLCBpMywgbjIsIHIzLCBlNFt1MyArIDExXSwgMTYsIDE4MzkwMzA1NjIpLCByMyA9IGgocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgMTRdLCAyMywgLTM1MzA5NTU2KSwgbjIgPSBoKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDFdLCA0LCAtMTUzMDk5MjA2MCksIGkzID0gaChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyA0XSwgMTEsIDEyNzI4OTMzNTMpLCBvMiA9IGgobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgN10sIDE2LCAtMTU1NDk3NjMyKSwgcjMgPSBoKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDEwXSwgMjMsIC0xMDk0NzMwNjQwKSwgbjIgPSBoKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDEzXSwgNCwgNjgxMjc5MTc0KSwgaTMgPSBoKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDBdLCAxMSwgLTM1ODUzNzIyMiksIG8yID0gaChvMiwgaTMsIG4yLCByMywgZTRbdTMgKyAzXSwgMTYsIC03MjI1MjE5NzkpLCByMyA9IGgocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgNl0sIDIzLCA3NjAyOTE4OSksIG4yID0gaChuMiwgcjMsIG8yLCBpMywgZTRbdTMgKyA5XSwgNCwgLTY0MDM2NDQ4NyksIGkzID0gaChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyAxMl0sIDExLCAtNDIxODE1ODM1KSwgbzIgPSBoKG8yLCBpMywgbjIsIHIzLCBlNFt1MyArIDE1XSwgMTYsIDUzMDc0MjUyMCksIG4yID0gcChuMiwgcjMgPSBoKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDJdLCAyMywgLTk5NTMzODY1MSksIG8yLCBpMywgZTRbdTMgKyAwXSwgNiwgLTE5ODYzMDg0NCksIGkzID0gcChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyA3XSwgMTAsIDExMjY4OTE0MTUpLCBvMiA9IHAobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgMTRdLCAxNSwgLTE0MTYzNTQ5MDUpLCByMyA9IHAocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgNV0sIDIxLCAtNTc0MzQwNTUpLCBuMiA9IHAobjIsIHIzLCBvMiwgaTMsIGU0W3UzICsgMTJdLCA2LCAxNzAwNDg1NTcxKSwgaTMgPSBwKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDNdLCAxMCwgLTE4OTQ5ODY2MDYpLCBvMiA9IHAobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgMTBdLCAxNSwgLTEwNTE1MjMpLCByMyA9IHAocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgMV0sIDIxLCAtMjA1NDkyMjc5OSksIG4yID0gcChuMiwgcjMsIG8yLCBpMywgZTRbdTMgKyA4XSwgNiwgMTg3MzMxMzM1OSksIGkzID0gcChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyAxNV0sIDEwLCAtMzA2MTE3NDQpLCBvMiA9IHAobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgNl0sIDE1LCAtMTU2MDE5ODM4MCksIHIzID0gcChyMywgbzIsIGkzLCBuMiwgZTRbdTMgKyAxM10sIDIxLCAxMzA5MTUxNjQ5KSwgbjIgPSBwKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDRdLCA2LCAtMTQ1NTIzMDcwKSwgaTMgPSBwKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDExXSwgMTAsIC0xMTIwMjEwMzc5KSwgbzIgPSBwKG8yLCBpMywgbjIsIHIzLCBlNFt1MyArIDJdLCAxNSwgNzE4Nzg3MjU5KSwgcjMgPSBwKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDldLCAyMSwgLTM0MzQ4NTU1MSksIG4yID0gZyhuMiwgczMpLCByMyA9IGcocjMsIGEzKSwgbzIgPSBnKG8yLCBmMyksIGkzID0gZyhpMywgbDMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBBcnJheShuMiwgcjMsIG8yLCBpMyk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBzMihlNCwgdDIsIG4yLCByMywgbzIsIGkzKSB7CiAgICAgICAgICAgIHJldHVybiBnKCh0MiA9IGcoZyh0MiwgZTQpLCBnKHIzLCBpMykpKSA8PCBvMiB8IHQyID4+PiAzMiAtIG8yLCBuMik7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBjMihlNCwgdDIsIG4yLCByMywgbzIsIGkzLCB1MykgewogICAgICAgICAgICByZXR1cm4gczIodDIgJiBuMiB8IH50MiAmIHIzLCBlNCwgdDIsIG8yLCBpMywgdTMpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZChlNCwgdDIsIG4yLCByMywgbzIsIGkzLCB1MykgewogICAgICAgICAgICByZXR1cm4gczIodDIgJiByMyB8IG4yICYgfnIzLCBlNCwgdDIsIG8yLCBpMywgdTMpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gaChlNCwgdDIsIG4yLCByMywgbzIsIGkzLCB1MykgewogICAgICAgICAgICByZXR1cm4gczIodDIgXiBuMiBeIHIzLCBlNCwgdDIsIG8yLCBpMywgdTMpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gcChlNCwgdDIsIG4yLCByMywgbzIsIGkzLCB1MykgewogICAgICAgICAgICByZXR1cm4gczIobjIgXiAodDIgfCB+cjMpLCBlNCwgdDIsIG8yLCBpMywgdTMpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZyhlNCwgdDIpIHsKICAgICAgICAgICAgdmFyIG4yID0gKDY1NTM1ICYgZTQpICsgKDY1NTM1ICYgdDIpOwogICAgICAgICAgICByZXR1cm4gKGU0ID4+IDE2KSArICh0MiA+PiAxNikgKyAobjIgPj4gMTYpIDw8IDE2IHwgNjU1MzUgJiBuMjsKICAgICAgICAgIH0KICAgICAgICAgIGIuZXhwb3J0cyA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIHJldHVybiB0Lmhhc2goZTQsIG4sIDE2KTsKICAgICAgICAgIH07CiAgICAgICAgfSkuY2FsbCh0aGlzLCB3MigibFlwb0kyIiksICJ1bmRlZmluZWQiICE9IHR5cGVvZiBzZWxmID8gc2VsZiA6ICJ1bmRlZmluZWQiICE9IHR5cGVvZiB3aW5kb3cgPyB3aW5kb3cgOiB7fSwgdzIoImJ1ZmZlciIpLkJ1ZmZlciwgYXJndW1lbnRzWzNdLCBhcmd1bWVudHNbNF0sIGFyZ3VtZW50c1s1XSwgYXJndW1lbnRzWzZdLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2NyeXB0by1icm93c2VyaWZ5L21kNS5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkiKTsKICAgICAgfSwgeyAiLi9oZWxwZXJzIjogNCwgYnVmZmVyOiAzLCBsWXBvSTI6IDExIH1dLCA3OiBbZnVuY3Rpb24oZTIsIGwyLCB0KSB7CiAgICAgICAgIShmdW5jdGlvbihlMywgdDIsIG4sIHIyLCBvLCBpMiwgdTIsIHMyLCBmMikgewogICAgICAgICAgbDIuZXhwb3J0cyA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIGZvciAodmFyIHQzLCBuMiA9IG5ldyBBcnJheShlNCksIHIzID0gMDsgcjMgPCBlNDsgcjMrKykgMCA9PSAoMyAmIHIzKSAmJiAodDMgPSA0Mjk0OTY3Mjk2ICogTWF0aC5yYW5kb20oKSksIG4yW3IzXSA9IHQzID4+PiAoKDMgJiByMykgPDwgMykgJiAyNTU7CiAgICAgICAgICAgIHJldHVybiBuMjsKICAgICAgICAgIH07CiAgICAgICAgfSkuY2FsbCh0aGlzLCBlMigibFlwb0kyIiksICJ1bmRlZmluZWQiICE9IHR5cGVvZiBzZWxmID8gc2VsZiA6ICJ1bmRlZmluZWQiICE9IHR5cGVvZiB3aW5kb3cgPyB3aW5kb3cgOiB7fSwgZTIoImJ1ZmZlciIpLkJ1ZmZlciwgYXJndW1lbnRzWzNdLCBhcmd1bWVudHNbNF0sIGFyZ3VtZW50c1s1XSwgYXJndW1lbnRzWzZdLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2NyeXB0by1icm93c2VyaWZ5L3JuZy5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkiKTsKICAgICAgfSwgeyBidWZmZXI6IDMsIGxZcG9JMjogMTEgfV0sIDg6IFtmdW5jdGlvbihjMiwgZCwgZTIpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUzLCB0LCBuLCByMiwgbywgczIsIGEyLCBmMiwgbDIpIHsKICAgICAgICAgIHZhciBpMiA9IGMyKCIuL2hlbHBlcnMiKTsKICAgICAgICAgIGZ1bmN0aW9uIHUyKGwzLCBjMykgewogICAgICAgICAgICBsM1tjMyA+PiA1XSB8PSAxMjggPDwgMjQgLSBjMyAlIDMyLCBsM1sxNSArIChjMyArIDY0ID4+IDkgPDwgNCldID0gYzM7CiAgICAgICAgICAgIGZvciAodmFyIGU0LCB0MiwgbjIsIHIzID0gQXJyYXkoODApLCBvMiA9IDE3MzI1ODQxOTMsIGkzID0gLTI3MTczMzg3OSwgdTMgPSAtMTczMjU4NDE5NCwgczMgPSAyNzE3MzM4NzgsIGQyID0gLTEwMDk1ODk3NzYsIGggPSAwOyBoIDwgbDMubGVuZ3RoOyBoICs9IDE2KSB7CiAgICAgICAgICAgICAgZm9yICh2YXIgcCA9IG8yLCBnID0gaTMsIHkgPSB1MywgdzIgPSBzMywgYiA9IGQyLCBhMyA9IDA7IGEzIDwgODA7IGEzKyspIHsKICAgICAgICAgICAgICAgIHIzW2EzXSA9IGEzIDwgMTYgPyBsM1toICsgYTNdIDogdjIocjNbYTMgLSAzXSBeIHIzW2EzIC0gOF0gXiByM1thMyAtIDE0XSBeIHIzW2EzIC0gMTZdLCAxKTsKICAgICAgICAgICAgICAgIHZhciBmMyA9IG0yKG0yKHYyKG8yLCA1KSwgKGYzID0gaTMsIHQyID0gdTMsIG4yID0gczMsIChlNCA9IGEzKSA8IDIwID8gZjMgJiB0MiB8IH5mMyAmIG4yIDogIShlNCA8IDQwKSAmJiBlNCA8IDYwID8gZjMgJiB0MiB8IGYzICYgbjIgfCB0MiAmIG4yIDogZjMgXiB0MiBeIG4yKSksIG0yKG0yKGQyLCByM1thM10pLCAoZTQgPSBhMykgPCAyMCA/IDE1MTg1MDAyNDkgOiBlNCA8IDQwID8gMTg1OTc3NTM5MyA6IGU0IDwgNjAgPyAtMTg5NDAwNzU4OCA6IC04OTk0OTc1MTQpKSwgZDIgPSBzMywgczMgPSB1MywgdTMgPSB2MihpMywgMzApLCBpMyA9IG8yLCBvMiA9IGYzOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBvMiA9IG0yKG8yLCBwKSwgaTMgPSBtMihpMywgZyksIHUzID0gbTIodTMsIHkpLCBzMyA9IG0yKHMzLCB3MiksIGQyID0gbTIoZDIsIGIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBBcnJheShvMiwgaTMsIHUzLCBzMywgZDIpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gbTIoZTQsIHQyKSB7CiAgICAgICAgICAgIHZhciBuMiA9ICg2NTUzNSAmIGU0KSArICg2NTUzNSAmIHQyKTsKICAgICAgICAgICAgcmV0dXJuIChlNCA+PiAxNikgKyAodDIgPj4gMTYpICsgKG4yID4+IDE2KSA8PCAxNiB8IDY1NTM1ICYgbjI7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiB2MihlNCwgdDIpIHsKICAgICAgICAgICAgcmV0dXJuIGU0IDw8IHQyIHwgZTQgPj4+IDMyIC0gdDI7CiAgICAgICAgICB9CiAgICAgICAgICBkLmV4cG9ydHMgPSBmdW5jdGlvbihlNCkgewogICAgICAgICAgICByZXR1cm4gaTIuaGFzaChlNCwgdTIsIDIwLCB0cnVlKTsKICAgICAgICAgIH07CiAgICAgICAgfSkuY2FsbCh0aGlzLCBjMigibFlwb0kyIiksICJ1bmRlZmluZWQiICE9IHR5cGVvZiBzZWxmID8gc2VsZiA6ICJ1bmRlZmluZWQiICE9IHR5cGVvZiB3aW5kb3cgPyB3aW5kb3cgOiB7fSwgYzIoImJ1ZmZlciIpLkJ1ZmZlciwgYXJndW1lbnRzWzNdLCBhcmd1bWVudHNbNF0sIGFyZ3VtZW50c1s1XSwgYXJndW1lbnRzWzZdLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2NyeXB0by1icm93c2VyaWZ5L3NoYS5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkiKTsKICAgICAgfSwgeyAiLi9oZWxwZXJzIjogNCwgYnVmZmVyOiAzLCBsWXBvSTI6IDExIH1dLCA5OiBbZnVuY3Rpb24oYzIsIGQsIGUyKSB7CiAgICAgICAgIShmdW5jdGlvbihlMywgdCwgbiwgcjIsIHUyLCBzMiwgYTIsIGYyLCBsMikgewogICAgICAgICAgZnVuY3Rpb24gYihlNCwgdDIpIHsKICAgICAgICAgICAgdmFyIG4yID0gKDY1NTM1ICYgZTQpICsgKDY1NTM1ICYgdDIpOwogICAgICAgICAgICByZXR1cm4gKGU0ID4+IDE2KSArICh0MiA+PiAxNikgKyAobjIgPj4gMTYpIDw8IDE2IHwgNjU1MzUgJiBuMjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIG8oZTQsIGwzKSB7CiAgICAgICAgICAgIHZhciBjMywgZDIgPSBuZXcgQXJyYXkoMTExNjM1MjQwOCwgMTg5OTQ0NzQ0MSwgMzA0OTMyMzQ3MSwgMzkyMTAwOTU3MywgOTYxOTg3MTYzLCAxNTA4OTcwOTkzLCAyNDUzNjM1NzQ4LCAyODcwNzYzMjIxLCAzNjI0MzgxMDgwLCAzMTA1OTg0MDEsIDYwNzIyNTI3OCwgMTQyNjg4MTk4NywgMTkyNTA3ODM4OCwgMjE2MjA3ODIwNiwgMjYxNDg4ODEwMywgMzI0ODIyMjU4MCwgMzgzNTM5MDQwMSwgNDAyMjIyNDc3NCwgMjY0MzQ3MDc4LCA2MDQ4MDc2MjgsIDc3MDI1NTk4MywgMTI0OTE1MDEyMiwgMTU1NTA4MTY5MiwgMTk5NjA2NDk4NiwgMjU1NDIyMDg4MiwgMjgyMTgzNDM0OSwgMjk1Mjk5NjgwOCwgMzIxMDMxMzY3MSwgMzMzNjU3MTg5MSwgMzU4NDUyODcxMSwgMTEzOTI2OTkzLCAzMzgyNDE4OTUsIDY2NjMwNzIwNSwgNzczNTI5OTEyLCAxMjk0NzU3MzcyLCAxMzk2MTgyMjkxLCAxNjk1MTgzNzAwLCAxOTg2NjYxMDUxLCAyMTc3MDI2MzUwLCAyNDU2OTU2MDM3LCAyNzMwNDg1OTIxLCAyODIwMzAyNDExLCAzMjU5NzMwODAwLCAzMzQ1NzY0NzcxLCAzNTE2MDY1ODE3LCAzNjAwMzUyODA0LCA0MDk0NTcxOTA5LCAyNzU0MjMzNDQsIDQzMDIyNzczNCwgNTA2OTQ4NjE2LCA2NTkwNjA1NTYsIDg4Mzk5Nzg3NywgOTU4MTM5NTcxLCAxMzIyODIyMjE4LCAxNTM3MDAyMDYzLCAxNzQ3ODczNzc5LCAxOTU1NTYyMjIyLCAyMDI0MTA0ODE1LCAyMjI3NzMwNDUyLCAyMzYxODUyNDI0LCAyNDI4NDM2NDc0LCAyNzU2NzM0MTg3LCAzMjA0MDMxNDc5LCAzMzI5MzI1Mjk4KSwgdDIgPSBuZXcgQXJyYXkoMTc3OTAzMzcwMywgMzE0NDEzNDI3NywgMTAxMzkwNDI0MiwgMjc3MzQ4MDc2MiwgMTM1OTg5MzExOSwgMjYwMDgyMjkyNCwgNTI4NzM0NjM1LCAxNTQxNDU5MjI1KSwgbjIgPSBuZXcgQXJyYXkoNjQpOwogICAgICAgICAgICBlNFtsMyA+PiA1XSB8PSAxMjggPDwgMjQgLSBsMyAlIDMyLCBlNFsxNSArIChsMyArIDY0ID4+IDkgPDwgNCldID0gbDM7CiAgICAgICAgICAgIGZvciAodmFyIHIzLCBvMiwgaCA9IDA7IGggPCBlNC5sZW5ndGg7IGggKz0gMTYpIHsKICAgICAgICAgICAgICBmb3IgKHZhciBpMyA9IHQyWzBdLCB1MyA9IHQyWzFdLCBzMyA9IHQyWzJdLCBwID0gdDJbM10sIGEzID0gdDJbNF0sIGcgPSB0Mls1XSwgeSA9IHQyWzZdLCB3MiA9IHQyWzddLCBmMyA9IDA7IGYzIDwgNjQ7IGYzKyspIG4yW2YzXSA9IGYzIDwgMTYgPyBlNFtmMyArIGhdIDogYihiKGIoKG8yID0gbjJbZjMgLSAyXSwgbTIobzIsIDE3KSBeIG0yKG8yLCAxOSkgXiB2MihvMiwgMTApKSwgbjJbZjMgLSA3XSksIChvMiA9IG4yW2YzIC0gMTVdLCBtMihvMiwgNykgXiBtMihvMiwgMTgpIF4gdjIobzIsIDMpKSksIG4yW2YzIC0gMTZdKSwgYzMgPSBiKGIoYihiKHcyLCBtMihvMiA9IGEzLCA2KSBeIG0yKG8yLCAxMSkgXiBtMihvMiwgMjUpKSwgYTMgJiBnIF4gfmEzICYgeSksIGQyW2YzXSksIG4yW2YzXSksIHIzID0gYihtMihyMyA9IGkzLCAyKSBeIG0yKHIzLCAxMykgXiBtMihyMywgMjIpLCBpMyAmIHUzIF4gaTMgJiBzMyBeIHUzICYgczMpLCB3MiA9IHksIHkgPSBnLCBnID0gYTMsIGEzID0gYihwLCBjMyksIHAgPSBzMywgczMgPSB1MywgdTMgPSBpMywgaTMgPSBiKGMzLCByMyk7CiAgICAgICAgICAgICAgdDJbMF0gPSBiKGkzLCB0MlswXSksIHQyWzFdID0gYih1MywgdDJbMV0pLCB0MlsyXSA9IGIoczMsIHQyWzJdKSwgdDJbM10gPSBiKHAsIHQyWzNdKSwgdDJbNF0gPSBiKGEzLCB0Mls0XSksIHQyWzVdID0gYihnLCB0Mls1XSksIHQyWzZdID0gYih5LCB0Mls2XSksIHQyWzddID0gYih3MiwgdDJbN10pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0MjsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBpMiA9IGMyKCIuL2hlbHBlcnMiKSwgbTIgPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgcmV0dXJuIGU0ID4+PiB0MiB8IGU0IDw8IDMyIC0gdDI7CiAgICAgICAgICB9LCB2MiA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gZTQgPj4+IHQyOwogICAgICAgICAgfTsKICAgICAgICAgIGQuZXhwb3J0cyA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIHJldHVybiBpMi5oYXNoKGU0LCBvLCAzMiwgdHJ1ZSk7CiAgICAgICAgICB9OwogICAgICAgIH0pLmNhbGwodGhpcywgYzIoImxZcG9JMiIpLCAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygc2VsZiA/IHNlbGYgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDoge30sIGMyKCJidWZmZXIiKS5CdWZmZXIsIGFyZ3VtZW50c1szXSwgYXJndW1lbnRzWzRdLCBhcmd1bWVudHNbNV0sIGFyZ3VtZW50c1s2XSwgIi9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9jcnlwdG8tYnJvd3NlcmlmeS9zaGEyNTYuanMiLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2NyeXB0by1icm93c2VyaWZ5Iik7CiAgICAgIH0sIHsgIi4vaGVscGVycyI6IDQsIGJ1ZmZlcjogMywgbFlwb0kyOiAxMSB9XSwgMTA6IFtmdW5jdGlvbihlMiwgdCwgZjIpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUzLCB0MiwgbiwgcjIsIG8sIGkyLCB1MiwgczIsIGEyKSB7CiAgICAgICAgICBmMi5yZWFkID0gZnVuY3Rpb24oZTQsIHQzLCBuMiwgcjMsIG8yKSB7CiAgICAgICAgICAgIHZhciBpMywgdTMsIGwyID0gOCAqIG8yIC0gcjMgLSAxLCBjMiA9ICgxIDw8IGwyKSAtIDEsIGQgPSBjMiA+PiAxLCBzMyA9IC03LCBhMyA9IG4yID8gbzIgLSAxIDogMCwgZjMgPSBuMiA/IC0xIDogMSwgbzIgPSBlNFt0MyArIGEzXTsKICAgICAgICAgICAgZm9yIChhMyArPSBmMywgaTMgPSBvMiAmICgxIDw8IC1zMykgLSAxLCBvMiA+Pj0gLXMzLCBzMyArPSBsMjsgMCA8IHMzOyBpMyA9IDI1NiAqIGkzICsgZTRbdDMgKyBhM10sIGEzICs9IGYzLCBzMyAtPSA4KSA7CiAgICAgICAgICAgIGZvciAodTMgPSBpMyAmICgxIDw8IC1zMykgLSAxLCBpMyA+Pj0gLXMzLCBzMyArPSByMzsgMCA8IHMzOyB1MyA9IDI1NiAqIHUzICsgZTRbdDMgKyBhM10sIGEzICs9IGYzLCBzMyAtPSA4KSA7CiAgICAgICAgICAgIGlmICgwID09PSBpMykgaTMgPSAxIC0gZDsKICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgaWYgKGkzID09PSBjMikgcmV0dXJuIHUzID8gTmFOIDogMSAvIDAgKiAobzIgPyAtMSA6IDEpOwogICAgICAgICAgICAgIHUzICs9IE1hdGgucG93KDIsIHIzKSwgaTMgLT0gZDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gKG8yID8gLTEgOiAxKSAqIHUzICogTWF0aC5wb3coMiwgaTMgLSByMyk7CiAgICAgICAgICB9LCBmMi53cml0ZSA9IGZ1bmN0aW9uKGU0LCB0MywgbDIsIG4yLCByMywgYzIpIHsKICAgICAgICAgICAgdmFyIG8yLCBpMywgdTMgPSA4ICogYzIgLSByMyAtIDEsIHMzID0gKDEgPDwgdTMpIC0gMSwgYTMgPSBzMyA+PiAxLCBkID0gMjMgPT09IHIzID8gTWF0aC5wb3coMiwgLTI0KSAtIE1hdGgucG93KDIsIC03NykgOiAwLCBmMyA9IG4yID8gMCA6IGMyIC0gMSwgaCA9IG4yID8gMSA6IC0xLCBjMiA9IHQzIDwgMCB8fCAwID09PSB0MyAmJiAxIC8gdDMgPCAwID8gMSA6IDA7CiAgICAgICAgICAgIGZvciAodDMgPSBNYXRoLmFicyh0MyksIGlzTmFOKHQzKSB8fCB0MyA9PT0gMSAvIDAgPyAoaTMgPSBpc05hTih0MykgPyAxIDogMCwgbzIgPSBzMykgOiAobzIgPSBNYXRoLmZsb29yKE1hdGgubG9nKHQzKSAvIE1hdGguTE4yKSwgdDMgKiAobjIgPSBNYXRoLnBvdygyLCAtbzIpKSA8IDEgJiYgKG8yLS0sIG4yICo9IDIpLCAyIDw9ICh0MyArPSAxIDw9IG8yICsgYTMgPyBkIC8gbjIgOiBkICogTWF0aC5wb3coMiwgMSAtIGEzKSkgKiBuMiAmJiAobzIrKywgbjIgLz0gMiksIHMzIDw9IG8yICsgYTMgPyAoaTMgPSAwLCBvMiA9IHMzKSA6IDEgPD0gbzIgKyBhMyA/IChpMyA9ICh0MyAqIG4yIC0gMSkgKiBNYXRoLnBvdygyLCByMyksIG8yICs9IGEzKSA6IChpMyA9IHQzICogTWF0aC5wb3coMiwgYTMgLSAxKSAqIE1hdGgucG93KDIsIHIzKSwgbzIgPSAwKSk7IDggPD0gcjM7IGU0W2wyICsgZjNdID0gMjU1ICYgaTMsIGYzICs9IGgsIGkzIC89IDI1NiwgcjMgLT0gOCkgOwogICAgICAgICAgICBmb3IgKG8yID0gbzIgPDwgcjMgfCBpMywgdTMgKz0gcjM7IDAgPCB1MzsgZTRbbDIgKyBmM10gPSAyNTUgJiBvMiwgZjMgKz0gaCwgbzIgLz0gMjU2LCB1MyAtPSA4KSA7CiAgICAgICAgICAgIGU0W2wyICsgZjMgLSBoXSB8PSAxMjggKiBjMjsKICAgICAgICAgIH07CiAgICAgICAgfSkuY2FsbCh0aGlzLCBlMigibFlwb0kyIiksICJ1bmRlZmluZWQiICE9IHR5cGVvZiBzZWxmID8gc2VsZiA6ICJ1bmRlZmluZWQiICE9IHR5cGVvZiB3aW5kb3cgPyB3aW5kb3cgOiB7fSwgZTIoImJ1ZmZlciIpLkJ1ZmZlciwgYXJndW1lbnRzWzNdLCBhcmd1bWVudHNbNF0sIGFyZ3VtZW50c1s1XSwgYXJndW1lbnRzWzZdLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2llZWU3NTQiKTsKICAgICAgfSwgeyBidWZmZXI6IDMsIGxZcG9JMjogMTEgfV0sIDExOiBbZnVuY3Rpb24oZTIsIGgsIHQpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUzLCB0MiwgbiwgcjIsIG8sIGYyLCBsMiwgYzIsIGQpIHsKICAgICAgICAgIHZhciBpMiwgdTIsIHMyOwogICAgICAgICAgZnVuY3Rpb24gYTIoKSB7CiAgICAgICAgICB9CiAgICAgICAgICAoZTMgPSBoLmV4cG9ydHMgPSB7fSkubmV4dFRpY2sgPSAodTIgPSAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ICYmIHdpbmRvdy5zZXRJbW1lZGlhdGUsIHMyID0gInVuZGVmaW5lZCIgIT0gdHlwZW9mIHdpbmRvdyAmJiB3aW5kb3cucG9zdE1lc3NhZ2UgJiYgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIsIHUyID8gZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5zZXRJbW1lZGlhdGUoZTQpOwogICAgICAgICAgfSA6IHMyID8gKGkyID0gW10sIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwgZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgdmFyIHQzID0gZTQuc291cmNlOwogICAgICAgICAgICB0MyAhPT0gd2luZG93ICYmIG51bGwgIT09IHQzIHx8ICJwcm9jZXNzLXRpY2siICE9PSBlNC5kYXRhIHx8IChlNC5zdG9wUHJvcGFnYXRpb24oKSwgMCA8IGkyLmxlbmd0aCAmJiBpMi5zaGlmdCgpKCkpOwogICAgICAgICAgfSwgdHJ1ZSksIGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIGkyLnB1c2goZTQpLCB3aW5kb3cucG9zdE1lc3NhZ2UoInByb2Nlc3MtdGljayIsICIqIik7CiAgICAgICAgICB9KSA6IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIHNldFRpbWVvdXQoZTQsIDApOwogICAgICAgICAgfSksIGUzLnRpdGxlID0gImJyb3dzZXIiLCBlMy5icm93c2VyID0gdHJ1ZSwgZTMuZW52ID0ge30sIGUzLmFyZ3YgPSBbXSwgZTMub24gPSBhMiwgZTMuYWRkTGlzdGVuZXIgPSBhMiwgZTMub25jZSA9IGEyLCBlMy5vZmYgPSBhMiwgZTMucmVtb3ZlTGlzdGVuZXIgPSBhMiwgZTMucmVtb3ZlQWxsTGlzdGVuZXJzID0gYTIsIGUzLmVtaXQgPSBhMiwgZTMuYmluZGluZyA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigicHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQiKTsKICAgICAgICAgIH0sIGUzLmN3ZCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gIi8iOwogICAgICAgICAgfSwgZTMuY2hkaXIgPSBmdW5jdGlvbihlNCkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoInByb2Nlc3MuY2hkaXIgaXMgbm90IHN1cHBvcnRlZCIpOwogICAgICAgICAgfTsKICAgICAgICB9KS5jYWxsKHRoaXMsIGUyKCJsWXBvSTIiKSwgInVuZGVmaW5lZCIgIT0gdHlwZW9mIHNlbGYgPyBzZWxmIDogInVuZGVmaW5lZCIgIT0gdHlwZW9mIHdpbmRvdyA/IHdpbmRvdyA6IHt9LCBlMigiYnVmZmVyIikuQnVmZmVyLCBhcmd1bWVudHNbM10sIGFyZ3VtZW50c1s0XSwgYXJndW1lbnRzWzVdLCBhcmd1bWVudHNbNl0sICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwgIi9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9wcm9jZXNzIik7CiAgICAgIH0sIHsgYnVmZmVyOiAzLCBsWXBvSTI6IDExIH1dIH0sIHt9LCBbMV0pKDEpOwogICAgfSk7CiAgfSkob2JqZWN0X2hhc2gpOwogIHZhciBvYmplY3RfaGFzaEV4cG9ydHMgPSBvYmplY3RfaGFzaC5leHBvcnRzOwogIHZhciBoYXNoID0gLyogQF9fUFVSRV9fICovIGdldERlZmF1bHRFeHBvcnRGcm9tQ2pzKG9iamVjdF9oYXNoRXhwb3J0cyk7CiAgY2xhc3MgTWFwMmRCYXNlIHsKICAgIGNvbnN0cnVjdG9yKHNlcmlhbGl6ZUZpcnN0QXhpcyA9IChrZXkpID0+IHR5cGVvZiBrZXkgPT09ICJzdHJpbmciID8ga2V5IDogaGFzaChrZXkpLCBzZXJpYWxpemVTZWNvbmRBeGlzID0gKGtleSkgPT4gdHlwZW9mIGtleSA9PT0gInN0cmluZyIgPyBrZXkgOiBoYXNoKGtleSksIGluaXRpYWxDb250ZW50KSB7CiAgICAgIHRoaXMuc2VyaWFsaXplRmlyc3RBeGlzID0gc2VyaWFsaXplRmlyc3RBeGlzOwogICAgICB0aGlzLnNlcmlhbGl6ZVNlY29uZEF4aXMgPSBzZXJpYWxpemVTZWNvbmRBeGlzOwogICAgICB0aGlzLmRhdGEgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLmtleXNGaXJzdEF4aXMgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLmtleXNTZWNvbmRBeGlzID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgaWYgKGluaXRpYWxDb250ZW50KSB7CiAgICAgICAgdGhpcy5rZXlzRmlyc3RBeGlzID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5rZXlzRmlyc3RBeGlzKTsKICAgICAgICB0aGlzLmtleXNTZWNvbmRBeGlzID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5rZXlzU2Vjb25kQXhpcyk7CiAgICAgICAgdGhpcy5kYXRhID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5kYXRhKTsKICAgICAgfQogICAgfQogICAgZ2V0KGtleUZpcnN0QXhpcywga2V5U2Vjb25kQXhpcykgewogICAgICB2YXIgX2E7CiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMgPSB0aGlzLnNlcmlhbGl6ZUZpcnN0QXhpcyhrZXlGaXJzdEF4aXMpOwogICAgICBjb25zdCBzZXJpYWxpemVkS2V5U2Vjb25kQXhpcyA9IHRoaXMuc2VyaWFsaXplU2Vjb25kQXhpcyhrZXlTZWNvbmRBeGlzKTsKICAgICAgcmV0dXJuIChfYSA9IHRoaXMuZGF0YS5nZXQoc2VyaWFsaXplZEtleUZpcnN0QXhpcykpID09IG51bGwgPyB2b2lkIDAgOiBfYS5nZXQoc2VyaWFsaXplZEtleVNlY29uZEF4aXMpOwogICAgfQogICAgZ2V0Um93KGtleSwgZmlsbEVtcHR5V2l0aCkgewogICAgICBjb25zdCBzZXJpYWxpemVkS2V5Rmlyc3RBeGlzID0gdGhpcy5zZXJpYWxpemVGaXJzdEF4aXMoa2V5KTsKICAgICAgY29uc3Qgcm93ID0gdGhpcy5kYXRhLmdldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKTsKICAgICAgaWYgKHJvdyA9PT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIFtdOwogICAgICB9CiAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMua2V5c1NlY29uZEF4aXMua2V5cygpKS5tYXAoKGtleTIpID0+IHJvdy5nZXQoa2V5MikgPz8gZmlsbEVtcHR5V2l0aCk7CiAgICB9CiAgICBzZXQoa2V5Rmlyc3RBeGlzLCBrZXlTZWNvbmRBeGlzLCB2YWx1ZSkgewogICAgICBjb25zdCBzZXJpYWxpemVkS2V5Rmlyc3RBeGlzID0gdGhpcy5zZXJpYWxpemVGaXJzdEF4aXMoa2V5Rmlyc3RBeGlzKTsKICAgICAgY29uc3Qgc2VyaWFsaXplZEtleVNlY29uZEF4aXMgPSB0aGlzLnNlcmlhbGl6ZVNlY29uZEF4aXMoa2V5U2Vjb25kQXhpcyk7CiAgICAgIGlmICghdGhpcy5kYXRhLmhhcyhzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKSkgewogICAgICAgIHRoaXMuZGF0YS5zZXQoc2VyaWFsaXplZEtleUZpcnN0QXhpcywgLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKSk7CiAgICAgIH0KICAgICAgdGhpcy5kYXRhLmdldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKS5zZXQoc2VyaWFsaXplZEtleVNlY29uZEF4aXMsIHZhbHVlKTsKICAgICAgdGhpcy5rZXlzRmlyc3RBeGlzLnNldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzLCBrZXlGaXJzdEF4aXMpOwogICAgICB0aGlzLmtleXNTZWNvbmRBeGlzLnNldChzZXJpYWxpemVkS2V5U2Vjb25kQXhpcywga2V5U2Vjb25kQXhpcyk7CiAgICB9CiAgICBkZWxldGVSb3coa2V5KSB7CiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMgPSB0aGlzLnNlcmlhbGl6ZUZpcnN0QXhpcyhrZXkpOwogICAgICB0aGlzLmRhdGEuZGVsZXRlKHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMpOwogICAgICB0aGlzLmtleXNGaXJzdEF4aXMuZGVsZXRlKHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMpOwogICAgfQogICAgZ2V0Rmlyc3RBeGlzS2V5cygpIHsKICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5rZXlzRmlyc3RBeGlzLnZhbHVlcygpKTsKICAgIH0KICAgIGdldFNlY29uZEF4aXNLZXlzKCkgewogICAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLmtleXNTZWNvbmRBeGlzLnZhbHVlcygpKTsKICAgIH0KICAgIGdldEFzQXJyYXkoZmlsbEVtcHR5V2l0aCkgewogICAgICByZXR1cm4gdGhpcy5nZXRGaXJzdEF4aXNLZXlzKCkubWFwKChmaXJzdEF4aXNLZXkpID0+IHsKICAgICAgICByZXR1cm4gdGhpcy5nZXRTZWNvbmRBeGlzS2V5cygpLm1hcCgoc2Vjb25kQXhpc0tleSkgPT4gewogICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KGZpcnN0QXhpc0tleSwgc2Vjb25kQXhpc0tleSkgPz8gZmlsbEVtcHR5V2l0aDsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9CiAgICBnZXRDb250ZW50cygpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBrZXlzRmlyc3RBeGlzOiB0aGlzLmtleXNGaXJzdEF4aXMsCiAgICAgICAga2V5c1NlY29uZEF4aXM6IHRoaXMua2V5c1NlY29uZEF4aXMsCiAgICAgICAgZGF0YTogdGhpcy5kYXRhCiAgICAgIH07CiAgICB9CiAgfQogIGNvbnN0IE1BWF9OVU1CRVJfT0ZfR1JJRF9DT0xVTU5TID0gMjAwOwogIGFzeW5jIGZ1bmN0aW9uIHF1ZXJ5T3ZlcmFsbE11dGF0aW9uRGF0YSh7CiAgICBsYXBpc0ZpbHRlciwKICAgIHNlcXVlbmNlVHlwZSwKICAgIGxhcGlzLAogICAgZ3JhbnVsYXJpdHksCiAgICBsYXBpc0RhdGVGaWVsZCwKICAgIHNpZ25hbAogIH0pIHsKICAgIGNvbnN0IGFsbERhdGVzID0gYXdhaXQgZ2V0RGF0ZXNJbkRhdGFzZXQobGFwaXNGaWx0ZXIsIGxhcGlzLCBncmFudWxhcml0eSwgbGFwaXNEYXRlRmllbGQsIHNpZ25hbCk7CiAgICBjb25zdCBmaWx0ZXIgPSB7CiAgICAgIC4uLmxhcGlzRmlsdGVyLAogICAgICBbYCR7bGFwaXNEYXRlRmllbGR9RnJvbWBdOiBhbGxEYXRlc1swXS5maXJzdERheS50b1N0cmluZygpLAogICAgICBbYCR7bGFwaXNEYXRlRmllbGR9VG9gXTogYWxsRGF0ZXNbYWxsRGF0ZXMubGVuZ3RoIC0gMV0ubGFzdERheS50b1N0cmluZygpCiAgICB9OwogICAgcmV0dXJuIGZldGNoQW5kUHJlcGFyZVN1YnN0aXR1dGlvbnNPckRlbGV0aW9ucyhmaWx0ZXIsIHNlcXVlbmNlVHlwZSkuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgfQogIGFzeW5jIGZ1bmN0aW9uIHF1ZXJ5TXV0YXRpb25zT3ZlclRpbWVEYXRhKHsKICAgIGxhcGlzRmlsdGVyLAogICAgc2VxdWVuY2VUeXBlLAogICAgbGFwaXMsCiAgICBsYXBpc0RhdGVGaWVsZCwKICAgIGdyYW51bGFyaXR5LAogICAgc2lnbmFsCiAgfSkgewogICAgY29uc3QgYWxsRGF0ZXMgPSBhd2FpdCBnZXREYXRlc0luRGF0YXNldChsYXBpc0ZpbHRlciwgbGFwaXMsIGdyYW51bGFyaXR5LCBsYXBpc0RhdGVGaWVsZCwgc2lnbmFsKTsKICAgIGlmIChhbGxEYXRlcy5sZW5ndGggPiBNQVhfTlVNQkVSX09GX0dSSURfQ09MVU1OUykgewogICAgICB0aHJvdyBuZXcgVXNlckZhY2luZ0Vycm9yKAogICAgICAgICJUb28gbWFueSBkYXRlcyIsCiAgICAgICAgYFRoZSBkYXRhc2V0IHdvdWxkIGNvbnRhaW4gJHthbGxEYXRlcy5sZW5ndGh9IGRhdGUgaW50ZXJ2YWxzLiBQbGVhc2UgcmVkdWNlIHRoZSBudW1iZXIgdG8gYmVsb3cgJHtNQVhfTlVNQkVSX09GX0dSSURfQ09MVU1OU30gdG8gZGlzcGxheSB0aGUgZGF0YS4gWW91IGNhbiBhY2hpZXZlIHRoaXMgYnkgZWl0aGVyIG5hcnJvd2luZyB0aGUgZGF0ZSByYW5nZSBpbiB0aGUgcHJvdmlkZWQgTEFQSVMgZmlsdGVyIG9yIGJ5IHNlbGVjdGluZyBhIGxhcmdlciBncmFudWxhcml0eS5gCiAgICAgICk7CiAgICB9CiAgICBjb25zdCBzdWJRdWVyaWVzID0gYWxsRGF0ZXMubWFwKGFzeW5jIChkYXRlKSA9PiB7CiAgICAgIGNvbnN0IGRhdGVGcm9tID0gZGF0ZS5maXJzdERheS50b1N0cmluZygpOwogICAgICBjb25zdCBkYXRlVG8gPSBkYXRlLmxhc3REYXkudG9TdHJpbmcoKTsKICAgICAgY29uc3QgZmlsdGVyID0gewogICAgICAgIC4uLmxhcGlzRmlsdGVyLAogICAgICAgIFtgJHtsYXBpc0RhdGVGaWVsZH1Gcm9tYF06IGRhdGVGcm9tLAogICAgICAgIFtgJHtsYXBpc0RhdGVGaWVsZH1Ub2BdOiBkYXRlVG8KICAgICAgfTsKICAgICAgY29uc3QgZGF0YTIgPSBhd2FpdCBmZXRjaEFuZFByZXBhcmVTdWJzdGl0dXRpb25zT3JEZWxldGlvbnMoZmlsdGVyLCBzZXF1ZW5jZVR5cGUpLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICBjb25zdCB0b3RhbENvdW50UXVlcnkgPSBhd2FpdCBnZXRUb3RhbE51bWJlck9mU2VxdWVuY2VzSW5EYXRlUmFuZ2UoZmlsdGVyKS5ldmFsdWF0ZShsYXBpcywgc2lnbmFsKTsKICAgICAgcmV0dXJuIHsKICAgICAgICBkYXRlLAogICAgICAgIG11dGF0aW9uczogZGF0YTIuY29udGVudCwKICAgICAgICB0b3RhbENvdW50OiB0b3RhbENvdW50UXVlcnkuY29udGVudFswXS5jb3VudAogICAgICB9OwogICAgfSk7CiAgICBjb25zdCBkYXRhID0gYXdhaXQgUHJvbWlzZS5hbGwoc3ViUXVlcmllcyk7CiAgICBjb25zdCBvdmVyYWxsTXV0YXRpb25zRGF0YSA9IChhd2FpdCBxdWVyeU92ZXJhbGxNdXRhdGlvbkRhdGEoewogICAgICBsYXBpc0ZpbHRlciwKICAgICAgc2VxdWVuY2VUeXBlLAogICAgICBsYXBpcywKICAgICAgbGFwaXNEYXRlRmllbGQsCiAgICAgIGdyYW51bGFyaXR5CiAgICB9KSkuY29udGVudDsKICAgIHJldHVybiB7CiAgICAgIG11dGF0aW9uT3ZlclRpbWVEYXRhOiBncm91cEJ5TXV0YXRpb24oZGF0YSwgb3ZlcmFsbE11dGF0aW9uc0RhdGEpLAogICAgICBvdmVyYWxsTXV0YXRpb25EYXRhOiBvdmVyYWxsTXV0YXRpb25zRGF0YQogICAgfTsKICB9CiAgYXN5bmMgZnVuY3Rpb24gZ2V0RGF0ZXNJbkRhdGFzZXQobGFwaXNGaWx0ZXIsIGxhcGlzLCBncmFudWxhcml0eSwgbGFwaXNEYXRlRmllbGQsIHNpZ25hbCkgewogICAgY29uc3QgeyBjb250ZW50OiBhdmFpbGFibGVEYXRlcyB9ID0gYXdhaXQgcXVlcnlBdmFpbGFibGVEYXRlcygKICAgICAgbGFwaXNGaWx0ZXIsCiAgICAgIGxhcGlzLAogICAgICBncmFudWxhcml0eSwKICAgICAgbGFwaXNEYXRlRmllbGQsCiAgICAgIHNpZ25hbAogICAgKTsKICAgIGNvbnN0IHsgZGF0ZUZyb20sIGRhdGVUbyB9ID0gZ2V0RGF0ZVJhbmdlRnJvbUZpbHRlcihsYXBpc0ZpbHRlciwgbGFwaXNEYXRlRmllbGQsIGdyYW51bGFyaXR5KTsKICAgIGNvbnN0IHsgbWluLCBtYXggfSA9IGdldE1pbk1heFRlbXBvcmFsKGF2YWlsYWJsZURhdGVzKTsKICAgIHJldHVybiBnZW5lcmF0ZUFsbEluUmFuZ2UoZGF0ZUZyb20gPz8gbWluLCBkYXRlVG8gPz8gbWF4KTsKICB9CiAgZnVuY3Rpb24gZ2V0RGF0ZVJhbmdlRnJvbUZpbHRlcihsYXBpc0ZpbHRlciwgbGFwaXNEYXRlRmllbGQsIGdyYW51bGFyaXR5KSB7CiAgICBjb25zdCB2YWx1ZUZyb21GaWx0ZXIgPSBsYXBpc0ZpbHRlcltsYXBpc0RhdGVGaWVsZF07CiAgICBpZiAodmFsdWVGcm9tRmlsdGVyKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgZGF0ZUZyb206IHBhcnNlRGF0ZVN0cmluZ1RvVGVtcG9yYWwodmFsdWVGcm9tRmlsdGVyLCBncmFudWxhcml0eSksCiAgICAgICAgZGF0ZVRvOiBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKHZhbHVlRnJvbUZpbHRlciwgZ3JhbnVsYXJpdHkpCiAgICAgIH07CiAgICB9CiAgICBjb25zdCBtaW5Gcm9tRmlsdGVyID0gbGFwaXNGaWx0ZXJbYCR7bGFwaXNEYXRlRmllbGR9RnJvbWBdOwogICAgY29uc3QgbWF4RnJvbUZpbHRlciA9IGxhcGlzRmlsdGVyW2Ake2xhcGlzRGF0ZUZpZWxkfVRvYF07CiAgICByZXR1cm4gewogICAgICBkYXRlRnJvbTogbWluRnJvbUZpbHRlciA/IHBhcnNlRGF0ZVN0cmluZ1RvVGVtcG9yYWwobWluRnJvbUZpbHRlciwgZ3JhbnVsYXJpdHkpIDogbnVsbCwKICAgICAgZGF0ZVRvOiBtYXhGcm9tRmlsdGVyID8gcGFyc2VEYXRlU3RyaW5nVG9UZW1wb3JhbChtYXhGcm9tRmlsdGVyLCBncmFudWxhcml0eSkgOiBudWxsCiAgICB9OwogIH0KICBmdW5jdGlvbiBxdWVyeUF2YWlsYWJsZURhdGVzKGxhcGlzRmlsdGVyLCBsYXBpcywgZ3JhbnVsYXJpdHksIGxhcGlzRGF0ZUZpZWxkLCBzaWduYWwpIHsKICAgIHJldHVybiBmZXRjaEFuZFByZXBhcmVEYXRlcyhsYXBpc0ZpbHRlciwgZ3JhbnVsYXJpdHksIGxhcGlzRGF0ZUZpZWxkKS5ldmFsdWF0ZShsYXBpcywgc2lnbmFsKTsKICB9CiAgZnVuY3Rpb24gZmV0Y2hBbmRQcmVwYXJlRGF0ZXMoZmlsdGVyLCBncmFudWxhcml0eSwgbGFwaXNEYXRlRmllbGQpIHsKICAgIGNvbnN0IGZldGNoRGF0YSA9IG5ldyBGZXRjaEFnZ3JlZ2F0ZWRPcGVyYXRvcihmaWx0ZXIsIFtsYXBpc0RhdGVGaWVsZF0pOwogICAgY29uc3QgZGF0YVdpdGhGaXhlZERhdGVLZXkgPSBuZXcgUmVuYW1lRmllbGRPcGVyYXRvcihmZXRjaERhdGEsIGxhcGlzRGF0ZUZpZWxkLCAiZGF0ZSIpOwogICAgY29uc3QgbWFwRGF0YSA9IG5ldyBNYXBPcGVyYXRvcihkYXRhV2l0aEZpeGVkRGF0ZUtleSwgKGRhdGEpID0+IG1hcERhdGVUb0dyYW51bGFyaXR5UmFuZ2UoZGF0YSwgZ3JhbnVsYXJpdHkpKTsKICAgIGNvbnN0IGdyb3VwQnlEYXRhID0gbmV3IEdyb3VwQnlBbmRTdW1PcGVyYXRvcihtYXBEYXRhLCAiZGF0ZVJhbmdlIiwgImNvdW50Iik7CiAgICBjb25zdCBzb3J0RGF0YSA9IG5ldyBTb3J0T3BlcmF0b3IoZ3JvdXBCeURhdGEsIGRhdGVSYW5nZUNvbXBhcmUpOwogICAgcmV0dXJuIG5ldyBNYXBPcGVyYXRvcihzb3J0RGF0YSwgKGRhdGEpID0+IGRhdGEuZGF0ZVJhbmdlKTsKICB9CiAgZnVuY3Rpb24gZmV0Y2hBbmRQcmVwYXJlU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zKGZpbHRlciwgc2VxdWVuY2VUeXBlKSB7CiAgICByZXR1cm4gbmV3IEZldGNoU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zT3BlcmF0b3IoZmlsdGVyLCBzZXF1ZW5jZVR5cGUsIDFlLTMpOwogIH0KICBmdW5jdGlvbiBzZXJpYWxpemVTdWJzdGl0dXRpb25PckRlbGV0aW9uKG11dGF0aW9uKSB7CiAgICByZXR1cm4gbXV0YXRpb24uY29kZTsKICB9CiAgZnVuY3Rpb24gc2VyaWFsaXplVGVtcG9yYWwoZGF0ZSkgewogICAgcmV0dXJuIGRhdGUuZGF0ZVN0cmluZzsKICB9CiAgZnVuY3Rpb24gZ3JvdXBCeU11dGF0aW9uKGRhdGEsIG92ZXJhbGxNdXRhdGlvbkRhdGEpIHsKICAgIGNvbnN0IGRhdGFBcnJheSA9IG5ldyBNYXAyZEJhc2UoCiAgICAgIHNlcmlhbGl6ZVN1YnN0aXR1dGlvbk9yRGVsZXRpb24sCiAgICAgIHNlcmlhbGl6ZVRlbXBvcmFsCiAgICApOwogICAgY29uc3QgYWxsRGF0ZXMgPSBkYXRhLm1hcCgobXV0YXRpb25EYXRhKSA9PiBtdXRhdGlvbkRhdGEuZGF0ZSk7CiAgICBjb25zdCBzb3J0ZWRPdmVyYWxsTXV0YXRpb25EYXRhID0gb3ZlcmFsbE11dGF0aW9uRGF0YS5zb3J0KChhMiwgYikgPT4gc29ydFN1YnN0aXR1dGlvbnNBbmREZWxldGlvbnMoYTIubXV0YXRpb24sIGIubXV0YXRpb24pKS5tYXAoKGVudHJ5KSA9PiB7CiAgICAgIHJldHVybiB0b1N1YnN0aXR1dGlvbk9yRGVsZXRpb24oZW50cnkubXV0YXRpb24pOwogICAgfSk7CiAgICBjb25zdCBzb3J0ZWREYXRlcyA9IGFsbERhdGVzLnNvcnQoKGEyLCBiKSA9PiBjb21wYXJlVGVtcG9yYWwoYTIsIGIpKS5tYXAoKGRhdGUpID0+IHRvVGVtcG9yYWwoZGF0ZSkpOwogICAgc29ydGVkT3ZlcmFsbE11dGF0aW9uRGF0YS5mb3JFYWNoKChtdXRhdGlvbkRhdGEpID0+IHsKICAgICAgc29ydGVkRGF0ZXMuZm9yRWFjaCgoZGF0ZSkgPT4gewogICAgICAgIGRhdGFBcnJheS5zZXQobXV0YXRpb25EYXRhLCBkYXRlLCB7CiAgICAgICAgICBjb3VudDogMCwKICAgICAgICAgIHByb3BvcnRpb246IDAsCiAgICAgICAgICB0b3RhbENvdW50OiAwCiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfSk7CiAgICBkYXRhLmZvckVhY2goKG11dGF0aW9uRGF0YSkgPT4gewogICAgICBtdXRhdGlvbkRhdGEubXV0YXRpb25zLmZvckVhY2goKG11dGF0aW9uRW50cnkpID0+IHsKICAgICAgICBjb25zdCBtdXRhdGlvbiA9IHRvU3Vic3RpdHV0aW9uT3JEZWxldGlvbihtdXRhdGlvbkVudHJ5Lm11dGF0aW9uKTsKICAgICAgICBjb25zdCBkYXRlID0gdG9UZW1wb3JhbChtdXRhdGlvbkRhdGEuZGF0ZSk7CiAgICAgICAgaWYgKGRhdGFBcnJheS5nZXQobXV0YXRpb24sIGRhdGUpICE9PSB2b2lkIDApIHsKICAgICAgICAgIGRhdGFBcnJheS5zZXQobXV0YXRpb24sIGRhdGUsIHsKICAgICAgICAgICAgY291bnQ6IG11dGF0aW9uRW50cnkuY291bnQsCiAgICAgICAgICAgIHByb3BvcnRpb246IG11dGF0aW9uRW50cnkucHJvcG9ydGlvbiwKICAgICAgICAgICAgdG90YWxDb3VudDogbXV0YXRpb25EYXRhLnRvdGFsQ291bnQKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9KTsKICAgIHJldHVybiBkYXRhQXJyYXk7CiAgfQogIGZ1bmN0aW9uIGdldFRvdGFsTnVtYmVyT2ZTZXF1ZW5jZXNJbkRhdGVSYW5nZShmaWx0ZXIpIHsKICAgIHJldHVybiBuZXcgRmV0Y2hBZ2dyZWdhdGVkT3BlcmF0b3IoZmlsdGVyKTsKICB9CiAgYXN5bmMgZnVuY3Rpb24gd29ya2VyRnVuY3Rpb24ocXVlcnlGdW5jdGlvbikgewogICAgdHJ5IHsKICAgICAgcG9zdE1lc3NhZ2UoeyBzdGF0dXM6ICJsb2FkaW5nIiB9KTsKICAgICAgY29uc3Qgd29ya2VyUmVzcG9uc2UgPSBhd2FpdCBxdWVyeUZ1bmN0aW9uKCk7CiAgICAgIHBvc3RNZXNzYWdlKHsKICAgICAgICBzdGF0dXM6ICJzdWNjZXNzIiwKICAgICAgICBkYXRhOiB3b3JrZXJSZXNwb25zZQogICAgICB9KTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIHBvc3RNZXNzYWdlKHsgc3RhdHVzOiAiZXJyb3IiLCBlcnJvciB9KTsKICAgIH0KICB9CiAgYXN5bmMgZnVuY3Rpb24gZ2V0TXV0YXRpb25PdmVyVGltZVdvcmtlckZ1bmN0aW9uKGV2ZW50KSB7CiAgICBjb25zdCBtdXRhdGlvbk92ZXJUaW1lRGF0YSA9IGF3YWl0IHF1ZXJ5TXV0YXRpb25zT3ZlclRpbWVEYXRhKGV2ZW50LmRhdGEpOwogICAgY29uc3Qgd29ya2VyUmVzcG9uc2UgPSB7CiAgICAgIG92ZXJhbGxNdXRhdGlvbkRhdGE6IG11dGF0aW9uT3ZlclRpbWVEYXRhLm92ZXJhbGxNdXRhdGlvbkRhdGEsCiAgICAgIG11dGF0aW9uT3ZlclRpbWVTZXJpYWxpemVkOiBtdXRhdGlvbk92ZXJUaW1lRGF0YS5tdXRhdGlvbk92ZXJUaW1lRGF0YS5nZXRDb250ZW50cygpCiAgICB9OwogICAgcmV0dXJuIHdvcmtlclJlc3BvbnNlOwogIH0KICBzZWxmLm9ubWVzc2FnZSA9IGFzeW5jIGZ1bmN0aW9uKGV2ZW50KSB7CiAgICBhd2FpdCB3b3JrZXJGdW5jdGlvbigoKSA9PiBnZXRNdXRhdGlvbk92ZXJUaW1lV29ya2VyRnVuY3Rpb24oZXZlbnQpKTsKICB9Owp9KSgpOwovLyMgc291cmNlTWFwcGluZ1VSTD1tdXRhdGlvbk92ZXJUaW1lV29ya2VyLUJkenFEcXZPLmpzLm1hcAo=";
8464
+ const encodedJs = "KGZ1bmN0aW9uKCkgewogICJ1c2Ugc3RyaWN0IjsKICB2YXIgdXRpbDsKICAoZnVuY3Rpb24odXRpbDIpIHsKICAgIHV0aWwyLmFzc2VydEVxdWFsID0gKHZhbCkgPT4gdmFsOwogICAgZnVuY3Rpb24gYXNzZXJ0SXMoX2FyZykgewogICAgfQogICAgdXRpbDIuYXNzZXJ0SXMgPSBhc3NlcnRJczsKICAgIGZ1bmN0aW9uIGFzc2VydE5ldmVyKF94KSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgfQogICAgdXRpbDIuYXNzZXJ0TmV2ZXIgPSBhc3NlcnROZXZlcjsKICAgIHV0aWwyLmFycmF5VG9FbnVtID0gKGl0ZW1zKSA9PiB7CiAgICAgIGNvbnN0IG9iaiA9IHt9OwogICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHsKICAgICAgICBvYmpbaXRlbV0gPSBpdGVtOwogICAgICB9CiAgICAgIHJldHVybiBvYmo7CiAgICB9OwogICAgdXRpbDIuZ2V0VmFsaWRFbnVtVmFsdWVzID0gKG9iaikgPT4gewogICAgICBjb25zdCB2YWxpZEtleXMgPSB1dGlsMi5vYmplY3RLZXlzKG9iaikuZmlsdGVyKChrMikgPT4gdHlwZW9mIG9ialtvYmpbazJdXSAhPT0gIm51bWJlciIpOwogICAgICBjb25zdCBmaWx0ZXJlZCA9IHt9OwogICAgICBmb3IgKGNvbnN0IGsyIG9mIHZhbGlkS2V5cykgewogICAgICAgIGZpbHRlcmVkW2syXSA9IG9ialtrMl07CiAgICAgIH0KICAgICAgcmV0dXJuIHV0aWwyLm9iamVjdFZhbHVlcyhmaWx0ZXJlZCk7CiAgICB9OwogICAgdXRpbDIub2JqZWN0VmFsdWVzID0gKG9iaikgPT4gewogICAgICByZXR1cm4gdXRpbDIub2JqZWN0S2V5cyhvYmopLm1hcChmdW5jdGlvbihlMikgewogICAgICAgIHJldHVybiBvYmpbZTJdOwogICAgICB9KTsKICAgIH07CiAgICB1dGlsMi5vYmplY3RLZXlzID0gdHlwZW9mIE9iamVjdC5rZXlzID09PSAiZnVuY3Rpb24iID8gKG9iaikgPT4gT2JqZWN0LmtleXMob2JqKSA6IChvYmplY3QpID0+IHsKICAgICAgY29uc3Qga2V5cyA9IFtdOwogICAgICBmb3IgKGNvbnN0IGtleSBpbiBvYmplY3QpIHsKICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkgewogICAgICAgICAga2V5cy5wdXNoKGtleSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBrZXlzOwogICAgfTsKICAgIHV0aWwyLmZpbmQgPSAoYXJyLCBjaGVja2VyKSA9PiB7CiAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBhcnIpIHsKICAgICAgICBpZiAoY2hlY2tlcihpdGVtKSkKICAgICAgICAgIHJldHVybiBpdGVtOwogICAgICB9CiAgICAgIHJldHVybiB2b2lkIDA7CiAgICB9OwogICAgdXRpbDIuaXNJbnRlZ2VyID0gdHlwZW9mIE51bWJlci5pc0ludGVnZXIgPT09ICJmdW5jdGlvbiIgPyAodmFsKSA9PiBOdW1iZXIuaXNJbnRlZ2VyKHZhbCkgOiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAibnVtYmVyIiAmJiBpc0Zpbml0ZSh2YWwpICYmIE1hdGguZmxvb3IodmFsKSA9PT0gdmFsOwogICAgZnVuY3Rpb24gam9pblZhbHVlcyhhcnJheSwgc2VwYXJhdG9yID0gIiB8ICIpIHsKICAgICAgcmV0dXJuIGFycmF5Lm1hcCgodmFsKSA9PiB0eXBlb2YgdmFsID09PSAic3RyaW5nIiA/IGAnJHt2YWx9J2AgOiB2YWwpLmpvaW4oc2VwYXJhdG9yKTsKICAgIH0KICAgIHV0aWwyLmpvaW5WYWx1ZXMgPSBqb2luVmFsdWVzOwogICAgdXRpbDIuanNvblN0cmluZ2lmeVJlcGxhY2VyID0gKF8sIHZhbHVlKSA9PiB7CiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJiaWdpbnQiKSB7CiAgICAgICAgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIHZhbHVlOwogICAgfTsKICB9KSh1dGlsIHx8ICh1dGlsID0ge30pKTsKICB2YXIgb2JqZWN0VXRpbDsKICAoZnVuY3Rpb24ob2JqZWN0VXRpbDIpIHsKICAgIG9iamVjdFV0aWwyLm1lcmdlU2hhcGVzID0gKGZpcnN0LCBzZWNvbmQpID0+IHsKICAgICAgcmV0dXJuIHsKICAgICAgICAuLi5maXJzdCwKICAgICAgICAuLi5zZWNvbmQKICAgICAgICAvLyBzZWNvbmQgb3ZlcndyaXRlcyBmaXJzdAogICAgICB9OwogICAgfTsKICB9KShvYmplY3RVdGlsIHx8IChvYmplY3RVdGlsID0ge30pKTsKICBjb25zdCBab2RQYXJzZWRUeXBlID0gdXRpbC5hcnJheVRvRW51bShbCiAgICAic3RyaW5nIiwKICAgICJuYW4iLAogICAgIm51bWJlciIsCiAgICAiaW50ZWdlciIsCiAgICAiZmxvYXQiLAogICAgImJvb2xlYW4iLAogICAgImRhdGUiLAogICAgImJpZ2ludCIsCiAgICAic3ltYm9sIiwKICAgICJmdW5jdGlvbiIsCiAgICAidW5kZWZpbmVkIiwKICAgICJudWxsIiwKICAgICJhcnJheSIsCiAgICAib2JqZWN0IiwKICAgICJ1bmtub3duIiwKICAgICJwcm9taXNlIiwKICAgICJ2b2lkIiwKICAgICJuZXZlciIsCiAgICAibWFwIiwKICAgICJzZXQiCiAgXSk7CiAgY29uc3QgZ2V0UGFyc2VkVHlwZSA9IChkYXRhKSA9PiB7CiAgICBjb25zdCB0ID0gdHlwZW9mIGRhdGE7CiAgICBzd2l0Y2ggKHQpIHsKICAgICAgY2FzZSAidW5kZWZpbmVkIjoKICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS51bmRlZmluZWQ7CiAgICAgIGNhc2UgInN0cmluZyI6CiAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc3RyaW5nOwogICAgICBjYXNlICJudW1iZXIiOgogICAgICAgIHJldHVybiBpc05hTihkYXRhKSA/IFpvZFBhcnNlZFR5cGUubmFuIDogWm9kUGFyc2VkVHlwZS5udW1iZXI7CiAgICAgIGNhc2UgImJvb2xlYW4iOgogICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLmJvb2xlYW47CiAgICAgIGNhc2UgImZ1bmN0aW9uIjoKICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5mdW5jdGlvbjsKICAgICAgY2FzZSAiYmlnaW50IjoKICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5iaWdpbnQ7CiAgICAgIGNhc2UgInN5bWJvbCI6CiAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc3ltYm9sOwogICAgICBjYXNlICJvYmplY3QiOgogICAgICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7CiAgICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5hcnJheTsKICAgICAgICB9CiAgICAgICAgaWYgKGRhdGEgPT09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLm51bGw7CiAgICAgICAgfQogICAgICAgIGlmIChkYXRhLnRoZW4gJiYgdHlwZW9mIGRhdGEudGhlbiA9PT0gImZ1bmN0aW9uIiAmJiBkYXRhLmNhdGNoICYmIHR5cGVvZiBkYXRhLmNhdGNoID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5wcm9taXNlOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIE1hcCAhPT0gInVuZGVmaW5lZCIgJiYgZGF0YSBpbnN0YW5jZW9mIE1hcCkgewogICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUubWFwOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIFNldCAhPT0gInVuZGVmaW5lZCIgJiYgZGF0YSBpbnN0YW5jZW9mIFNldCkgewogICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc2V0OwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIERhdGUgIT09ICJ1bmRlZmluZWQiICYmIGRhdGEgaW5zdGFuY2VvZiBEYXRlKSB7CiAgICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5kYXRlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5vYmplY3Q7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUudW5rbm93bjsKICAgIH0KICB9OwogIGNvbnN0IFpvZElzc3VlQ29kZSA9IHV0aWwuYXJyYXlUb0VudW0oWwogICAgImludmFsaWRfdHlwZSIsCiAgICAiaW52YWxpZF9saXRlcmFsIiwKICAgICJjdXN0b20iLAogICAgImludmFsaWRfdW5pb24iLAogICAgImludmFsaWRfdW5pb25fZGlzY3JpbWluYXRvciIsCiAgICAiaW52YWxpZF9lbnVtX3ZhbHVlIiwKICAgICJ1bnJlY29nbml6ZWRfa2V5cyIsCiAgICAiaW52YWxpZF9hcmd1bWVudHMiLAogICAgImludmFsaWRfcmV0dXJuX3R5cGUiLAogICAgImludmFsaWRfZGF0ZSIsCiAgICAiaW52YWxpZF9zdHJpbmciLAogICAgInRvb19zbWFsbCIsCiAgICAidG9vX2JpZyIsCiAgICAiaW52YWxpZF9pbnRlcnNlY3Rpb25fdHlwZXMiLAogICAgIm5vdF9tdWx0aXBsZV9vZiIsCiAgICAibm90X2Zpbml0ZSIKICBdKTsKICBjb25zdCBxdW90ZWxlc3NKc29uID0gKG9iaikgPT4gewogICAgY29uc3QganNvbiA9IEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgMik7CiAgICByZXR1cm4ganNvbi5yZXBsYWNlKC8iKFteIl0rKSI6L2csICIkMToiKTsKICB9OwogIGNsYXNzIFpvZEVycm9yIGV4dGVuZHMgRXJyb3IgewogICAgY29uc3RydWN0b3IoaXNzdWVzKSB7CiAgICAgIHN1cGVyKCk7CiAgICAgIHRoaXMuaXNzdWVzID0gW107CiAgICAgIHRoaXMuYWRkSXNzdWUgPSAoc3ViKSA9PiB7CiAgICAgICAgdGhpcy5pc3N1ZXMgPSBbLi4udGhpcy5pc3N1ZXMsIHN1Yl07CiAgICAgIH07CiAgICAgIHRoaXMuYWRkSXNzdWVzID0gKHN1YnMgPSBbXSkgPT4gewogICAgICAgIHRoaXMuaXNzdWVzID0gWy4uLnRoaXMuaXNzdWVzLCAuLi5zdWJzXTsKICAgICAgfTsKICAgICAgY29uc3QgYWN0dWFsUHJvdG8gPSBuZXcudGFyZ2V0LnByb3RvdHlwZTsKICAgICAgaWYgKE9iamVjdC5zZXRQcm90b3R5cGVPZikgewogICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBhY3R1YWxQcm90byk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fX3Byb3RvX18gPSBhY3R1YWxQcm90bzsKICAgICAgfQogICAgICB0aGlzLm5hbWUgPSAiWm9kRXJyb3IiOwogICAgICB0aGlzLmlzc3VlcyA9IGlzc3VlczsKICAgIH0KICAgIGdldCBlcnJvcnMoKSB7CiAgICAgIHJldHVybiB0aGlzLmlzc3VlczsKICAgIH0KICAgIGZvcm1hdChfbWFwcGVyKSB7CiAgICAgIGNvbnN0IG1hcHBlciA9IF9tYXBwZXIgfHwgZnVuY3Rpb24oaXNzdWUpIHsKICAgICAgICByZXR1cm4gaXNzdWUubWVzc2FnZTsKICAgICAgfTsKICAgICAgY29uc3QgZmllbGRFcnJvcnMgPSB7IF9lcnJvcnM6IFtdIH07CiAgICAgIGNvbnN0IHByb2Nlc3NFcnJvciA9IChlcnJvcikgPT4gewogICAgICAgIGZvciAoY29uc3QgaXNzdWUgb2YgZXJyb3IuaXNzdWVzKSB7CiAgICAgICAgICBpZiAoaXNzdWUuY29kZSA9PT0gImludmFsaWRfdW5pb24iKSB7CiAgICAgICAgICAgIGlzc3VlLnVuaW9uRXJyb3JzLm1hcChwcm9jZXNzRXJyb3IpOwogICAgICAgICAgfSBlbHNlIGlmIChpc3N1ZS5jb2RlID09PSAiaW52YWxpZF9yZXR1cm5fdHlwZSIpIHsKICAgICAgICAgICAgcHJvY2Vzc0Vycm9yKGlzc3VlLnJldHVyblR5cGVFcnJvcik7CiAgICAgICAgICB9IGVsc2UgaWYgKGlzc3VlLmNvZGUgPT09ICJpbnZhbGlkX2FyZ3VtZW50cyIpIHsKICAgICAgICAgICAgcHJvY2Vzc0Vycm9yKGlzc3VlLmFyZ3VtZW50c0Vycm9yKTsKICAgICAgICAgIH0gZWxzZSBpZiAoaXNzdWUucGF0aC5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgZmllbGRFcnJvcnMuX2Vycm9ycy5wdXNoKG1hcHBlcihpc3N1ZSkpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgbGV0IGN1cnIgPSBmaWVsZEVycm9yczsKICAgICAgICAgICAgbGV0IGkyID0gMDsKICAgICAgICAgICAgd2hpbGUgKGkyIDwgaXNzdWUucGF0aC5sZW5ndGgpIHsKICAgICAgICAgICAgICBjb25zdCBlbCA9IGlzc3VlLnBhdGhbaTJdOwogICAgICAgICAgICAgIGNvbnN0IHRlcm1pbmFsID0gaTIgPT09IGlzc3VlLnBhdGgubGVuZ3RoIC0gMTsKICAgICAgICAgICAgICBpZiAoIXRlcm1pbmFsKSB7CiAgICAgICAgICAgICAgICBjdXJyW2VsXSA9IGN1cnJbZWxdIHx8IHsgX2Vycm9yczogW10gfTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgY3VycltlbF0gPSBjdXJyW2VsXSB8fCB7IF9lcnJvcnM6IFtdIH07CiAgICAgICAgICAgICAgICBjdXJyW2VsXS5fZXJyb3JzLnB1c2gobWFwcGVyKGlzc3VlKSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGN1cnIgPSBjdXJyW2VsXTsKICAgICAgICAgICAgICBpMisrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9OwogICAgICBwcm9jZXNzRXJyb3IodGhpcyk7CiAgICAgIHJldHVybiBmaWVsZEVycm9yczsKICAgIH0KICAgIHN0YXRpYyBhc3NlcnQodmFsdWUpIHsKICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBab2RFcnJvcikpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vdCBhIFpvZEVycm9yOiAke3ZhbHVlfWApOwogICAgICB9CiAgICB9CiAgICB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZTsKICAgIH0KICAgIGdldCBtZXNzYWdlKCkgewogICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy5pc3N1ZXMsIHV0aWwuanNvblN0cmluZ2lmeVJlcGxhY2VyLCAyKTsKICAgIH0KICAgIGdldCBpc0VtcHR5KCkgewogICAgICByZXR1cm4gdGhpcy5pc3N1ZXMubGVuZ3RoID09PSAwOwogICAgfQogICAgZmxhdHRlbihtYXBwZXIgPSAoaXNzdWUpID0+IGlzc3VlLm1lc3NhZ2UpIHsKICAgICAgY29uc3QgZmllbGRFcnJvcnMgPSB7fTsKICAgICAgY29uc3QgZm9ybUVycm9ycyA9IFtdOwogICAgICBmb3IgKGNvbnN0IHN1YiBvZiB0aGlzLmlzc3VlcykgewogICAgICAgIGlmIChzdWIucGF0aC5sZW5ndGggPiAwKSB7CiAgICAgICAgICBmaWVsZEVycm9yc1tzdWIucGF0aFswXV0gPSBmaWVsZEVycm9yc1tzdWIucGF0aFswXV0gfHwgW107CiAgICAgICAgICBmaWVsZEVycm9yc1tzdWIucGF0aFswXV0ucHVzaChtYXBwZXIoc3ViKSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGZvcm1FcnJvcnMucHVzaChtYXBwZXIoc3ViKSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiB7IGZvcm1FcnJvcnMsIGZpZWxkRXJyb3JzIH07CiAgICB9CiAgICBnZXQgZm9ybUVycm9ycygpIHsKICAgICAgcmV0dXJuIHRoaXMuZmxhdHRlbigpOwogICAgfQogIH0KICBab2RFcnJvci5jcmVhdGUgPSAoaXNzdWVzKSA9PiB7CiAgICBjb25zdCBlcnJvciA9IG5ldyBab2RFcnJvcihpc3N1ZXMpOwogICAgcmV0dXJuIGVycm9yOwogIH07CiAgY29uc3QgZXJyb3JNYXAgPSAoaXNzdWUsIF9jdHgpID0+IHsKICAgIGxldCBtZXNzYWdlOwogICAgc3dpdGNoIChpc3N1ZS5jb2RlKSB7CiAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZToKICAgICAgICBpZiAoaXNzdWUucmVjZWl2ZWQgPT09IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkKSB7CiAgICAgICAgICBtZXNzYWdlID0gIlJlcXVpcmVkIjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbWVzc2FnZSA9IGBFeHBlY3RlZCAke2lzc3VlLmV4cGVjdGVkfSwgcmVjZWl2ZWQgJHtpc3N1ZS5yZWNlaXZlZH1gOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9saXRlcmFsOgogICAgICAgIG1lc3NhZ2UgPSBgSW52YWxpZCBsaXRlcmFsIHZhbHVlLCBleHBlY3RlZCAke0pTT04uc3RyaW5naWZ5KGlzc3VlLmV4cGVjdGVkLCB1dGlsLmpzb25TdHJpbmdpZnlSZXBsYWNlcil9YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUudW5yZWNvZ25pemVkX2tleXM6CiAgICAgICAgbWVzc2FnZSA9IGBVbnJlY29nbml6ZWQga2V5KHMpIGluIG9iamVjdDogJHt1dGlsLmpvaW5WYWx1ZXMoaXNzdWUua2V5cywgIiwgIil9YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF91bmlvbjoKICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgaW5wdXRgOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFpvZElzc3VlQ29kZS5pbnZhbGlkX3VuaW9uX2Rpc2NyaW1pbmF0b3I6CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGRpc2NyaW1pbmF0b3IgdmFsdWUuIEV4cGVjdGVkICR7dXRpbC5qb2luVmFsdWVzKGlzc3VlLm9wdGlvbnMpfWA7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfZW51bV92YWx1ZToKICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgZW51bSB2YWx1ZS4gRXhwZWN0ZWQgJHt1dGlsLmpvaW5WYWx1ZXMoaXNzdWUub3B0aW9ucyl9LCByZWNlaXZlZCAnJHtpc3N1ZS5yZWNlaXZlZH0nYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9hcmd1bWVudHM6CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGZ1bmN0aW9uIGFyZ3VtZW50c2A7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfcmV0dXJuX3R5cGU6CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGZ1bmN0aW9uIHJldHVybiB0eXBlYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9kYXRlOgogICAgICAgIG1lc3NhZ2UgPSBgSW52YWxpZCBkYXRlYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmc6CiAgICAgICAgaWYgKHR5cGVvZiBpc3N1ZS52YWxpZGF0aW9uID09PSAib2JqZWN0IikgewogICAgICAgICAgaWYgKCJpbmNsdWRlcyIgaW4gaXNzdWUudmFsaWRhdGlvbikgewogICAgICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgaW5wdXQ6IG11c3QgaW5jbHVkZSAiJHtpc3N1ZS52YWxpZGF0aW9uLmluY2x1ZGVzfSJgOwogICAgICAgICAgICBpZiAodHlwZW9mIGlzc3VlLnZhbGlkYXRpb24ucG9zaXRpb24gPT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgICAgbWVzc2FnZSA9IGAke21lc3NhZ2V9IGF0IG9uZSBvciBtb3JlIHBvc2l0aW9ucyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gJHtpc3N1ZS52YWxpZGF0aW9uLnBvc2l0aW9ufWA7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSBpZiAoInN0YXJ0c1dpdGgiIGluIGlzc3VlLnZhbGlkYXRpb24pIHsKICAgICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGlucHV0OiBtdXN0IHN0YXJ0IHdpdGggIiR7aXNzdWUudmFsaWRhdGlvbi5zdGFydHNXaXRofSJgOwogICAgICAgICAgfSBlbHNlIGlmICgiZW5kc1dpdGgiIGluIGlzc3VlLnZhbGlkYXRpb24pIHsKICAgICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGlucHV0OiBtdXN0IGVuZCB3aXRoICIke2lzc3VlLnZhbGlkYXRpb24uZW5kc1dpdGh9ImA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB1dGlsLmFzc2VydE5ldmVyKGlzc3VlLnZhbGlkYXRpb24pOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoaXNzdWUudmFsaWRhdGlvbiAhPT0gInJlZ2V4IikgewogICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkICR7aXNzdWUudmFsaWRhdGlvbn1gOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBtZXNzYWdlID0gIkludmFsaWQiOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUudG9vX3NtYWxsOgogICAgICAgIGlmIChpc3N1ZS50eXBlID09PSAiYXJyYXkiKQogICAgICAgICAgbWVzc2FnZSA9IGBBcnJheSBtdXN0IGNvbnRhaW4gJHtpc3N1ZS5leGFjdCA/ICJleGFjdGx5IiA6IGlzc3VlLmluY2x1c2l2ZSA/IGBhdCBsZWFzdGAgOiBgbW9yZSB0aGFuYH0gJHtpc3N1ZS5taW5pbXVtfSBlbGVtZW50KHMpYDsKICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSAic3RyaW5nIikKICAgICAgICAgIG1lc3NhZ2UgPSBgU3RyaW5nIG11c3QgY29udGFpbiAke2lzc3VlLmV4YWN0ID8gImV4YWN0bHkiIDogaXNzdWUuaW5jbHVzaXZlID8gYGF0IGxlYXN0YCA6IGBvdmVyYH0gJHtpc3N1ZS5taW5pbXVtfSBjaGFyYWN0ZXIocylgOwogICAgICAgIGVsc2UgaWYgKGlzc3VlLnR5cGUgPT09ICJudW1iZXIiKQogICAgICAgICAgbWVzc2FnZSA9IGBOdW1iZXIgbXVzdCBiZSAke2lzc3VlLmV4YWN0ID8gYGV4YWN0bHkgZXF1YWwgdG8gYCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYCA6IGBncmVhdGVyIHRoYW4gYH0ke2lzc3VlLm1pbmltdW19YDsKICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSAiZGF0ZSIpCiAgICAgICAgICBtZXNzYWdlID0gYERhdGUgbXVzdCBiZSAke2lzc3VlLmV4YWN0ID8gYGV4YWN0bHkgZXF1YWwgdG8gYCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYCA6IGBncmVhdGVyIHRoYW4gYH0ke25ldyBEYXRlKE51bWJlcihpc3N1ZS5taW5pbXVtKSl9YDsKICAgICAgICBlbHNlCiAgICAgICAgICBtZXNzYWdlID0gIkludmFsaWQgaW5wdXQiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFpvZElzc3VlQ29kZS50b29fYmlnOgogICAgICAgIGlmIChpc3N1ZS50eXBlID09PSAiYXJyYXkiKQogICAgICAgICAgbWVzc2FnZSA9IGBBcnJheSBtdXN0IGNvbnRhaW4gJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5YCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBhdCBtb3N0YCA6IGBsZXNzIHRoYW5gfSAke2lzc3VlLm1heGltdW19IGVsZW1lbnQocylgOwogICAgICAgIGVsc2UgaWYgKGlzc3VlLnR5cGUgPT09ICJzdHJpbmciKQogICAgICAgICAgbWVzc2FnZSA9IGBTdHJpbmcgbXVzdCBjb250YWluICR7aXNzdWUuZXhhY3QgPyBgZXhhY3RseWAgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgYXQgbW9zdGAgOiBgdW5kZXJgfSAke2lzc3VlLm1heGltdW19IGNoYXJhY3RlcihzKWA7CiAgICAgICAgZWxzZSBpZiAoaXNzdWUudHlwZSA9PT0gIm51bWJlciIpCiAgICAgICAgICBtZXNzYWdlID0gYE51bWJlciBtdXN0IGJlICR7aXNzdWUuZXhhY3QgPyBgZXhhY3RseWAgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgbGVzcyB0aGFuIG9yIGVxdWFsIHRvYCA6IGBsZXNzIHRoYW5gfSAke2lzc3VlLm1heGltdW19YDsKICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSAiYmlnaW50IikKICAgICAgICAgIG1lc3NhZ2UgPSBgQmlnSW50IG11c3QgYmUgJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5YCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBsZXNzIHRoYW4gb3IgZXF1YWwgdG9gIDogYGxlc3MgdGhhbmB9ICR7aXNzdWUubWF4aW11bX1gOwogICAgICAgIGVsc2UgaWYgKGlzc3VlLnR5cGUgPT09ICJkYXRlIikKICAgICAgICAgIG1lc3NhZ2UgPSBgRGF0ZSBtdXN0IGJlICR7aXNzdWUuZXhhY3QgPyBgZXhhY3RseWAgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgc21hbGxlciB0aGFuIG9yIGVxdWFsIHRvYCA6IGBzbWFsbGVyIHRoYW5gfSAke25ldyBEYXRlKE51bWJlcihpc3N1ZS5tYXhpbXVtKSl9YDsKICAgICAgICBlbHNlCiAgICAgICAgICBtZXNzYWdlID0gIkludmFsaWQgaW5wdXQiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFpvZElzc3VlQ29kZS5jdXN0b206CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGlucHV0YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9pbnRlcnNlY3Rpb25fdHlwZXM6CiAgICAgICAgbWVzc2FnZSA9IGBJbnRlcnNlY3Rpb24gcmVzdWx0cyBjb3VsZCBub3QgYmUgbWVyZ2VkYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUubm90X211bHRpcGxlX29mOgogICAgICAgIG1lc3NhZ2UgPSBgTnVtYmVyIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAke2lzc3VlLm11bHRpcGxlT2Z9YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUubm90X2Zpbml0ZToKICAgICAgICBtZXNzYWdlID0gIk51bWJlciBtdXN0IGJlIGZpbml0ZSI7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgbWVzc2FnZSA9IF9jdHguZGVmYXVsdEVycm9yOwogICAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoaXNzdWUpOwogICAgfQogICAgcmV0dXJuIHsgbWVzc2FnZSB9OwogIH07CiAgbGV0IG92ZXJyaWRlRXJyb3JNYXAgPSBlcnJvck1hcDsKICBmdW5jdGlvbiBzZXRFcnJvck1hcChtYXApIHsKICAgIG92ZXJyaWRlRXJyb3JNYXAgPSBtYXA7CiAgfQogIGZ1bmN0aW9uIGdldEVycm9yTWFwKCkgewogICAgcmV0dXJuIG92ZXJyaWRlRXJyb3JNYXA7CiAgfQogIGNvbnN0IG1ha2VJc3N1ZSA9IChwYXJhbXMpID0+IHsKICAgIGNvbnN0IHsgZGF0YSwgcGF0aCwgZXJyb3JNYXBzLCBpc3N1ZURhdGEgfSA9IHBhcmFtczsKICAgIGNvbnN0IGZ1bGxQYXRoID0gWy4uLnBhdGgsIC4uLmlzc3VlRGF0YS5wYXRoIHx8IFtdXTsKICAgIGNvbnN0IGZ1bGxJc3N1ZSA9IHsKICAgICAgLi4uaXNzdWVEYXRhLAogICAgICBwYXRoOiBmdWxsUGF0aAogICAgfTsKICAgIGlmIChpc3N1ZURhdGEubWVzc2FnZSAhPT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgLi4uaXNzdWVEYXRhLAogICAgICAgIHBhdGg6IGZ1bGxQYXRoLAogICAgICAgIG1lc3NhZ2U6IGlzc3VlRGF0YS5tZXNzYWdlCiAgICAgIH07CiAgICB9CiAgICBsZXQgZXJyb3JNZXNzYWdlID0gIiI7CiAgICBjb25zdCBtYXBzID0gZXJyb3JNYXBzLmZpbHRlcigobTIpID0+ICEhbTIpLnNsaWNlKCkucmV2ZXJzZSgpOwogICAgZm9yIChjb25zdCBtYXAgb2YgbWFwcykgewogICAgICBlcnJvck1lc3NhZ2UgPSBtYXAoZnVsbElzc3VlLCB7IGRhdGEsIGRlZmF1bHRFcnJvcjogZXJyb3JNZXNzYWdlIH0pLm1lc3NhZ2U7CiAgICB9CiAgICByZXR1cm4gewogICAgICAuLi5pc3N1ZURhdGEsCiAgICAgIHBhdGg6IGZ1bGxQYXRoLAogICAgICBtZXNzYWdlOiBlcnJvck1lc3NhZ2UKICAgIH07CiAgfTsKICBjb25zdCBFTVBUWV9QQVRIID0gW107CiAgZnVuY3Rpb24gYWRkSXNzdWVUb0NvbnRleHQoY3R4LCBpc3N1ZURhdGEpIHsKICAgIGNvbnN0IG92ZXJyaWRlTWFwID0gZ2V0RXJyb3JNYXAoKTsKICAgIGNvbnN0IGlzc3VlID0gbWFrZUlzc3VlKHsKICAgICAgaXNzdWVEYXRhLAogICAgICBkYXRhOiBjdHguZGF0YSwKICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgIGVycm9yTWFwczogWwogICAgICAgIGN0eC5jb21tb24uY29udGV4dHVhbEVycm9yTWFwLAogICAgICAgIGN0eC5zY2hlbWFFcnJvck1hcCwKICAgICAgICBvdmVycmlkZU1hcCwKICAgICAgICBvdmVycmlkZU1hcCA9PT0gZXJyb3JNYXAgPyB2b2lkIDAgOiBlcnJvck1hcAogICAgICAgIC8vIHRoZW4gZ2xvYmFsIGRlZmF1bHQgbWFwCiAgICAgIF0uZmlsdGVyKCh4KSA9PiAhIXgpCiAgICB9KTsKICAgIGN0eC5jb21tb24uaXNzdWVzLnB1c2goaXNzdWUpOwogIH0KICBjbGFzcyBQYXJzZVN0YXR1cyB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgdGhpcy52YWx1ZSA9ICJ2YWxpZCI7CiAgICB9CiAgICBkaXJ0eSgpIHsKICAgICAgaWYgKHRoaXMudmFsdWUgPT09ICJ2YWxpZCIpCiAgICAgICAgdGhpcy52YWx1ZSA9ICJkaXJ0eSI7CiAgICB9CiAgICBhYm9ydCgpIHsKICAgICAgaWYgKHRoaXMudmFsdWUgIT09ICJhYm9ydGVkIikKICAgICAgICB0aGlzLnZhbHVlID0gImFib3J0ZWQiOwogICAgfQogICAgc3RhdGljIG1lcmdlQXJyYXkoc3RhdHVzLCByZXN1bHRzKSB7CiAgICAgIGNvbnN0IGFycmF5VmFsdWUgPSBbXTsKICAgICAgZm9yIChjb25zdCBzMiBvZiByZXN1bHRzKSB7CiAgICAgICAgaWYgKHMyLnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgaWYgKHMyLnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgIGFycmF5VmFsdWUucHVzaChzMi52YWx1ZSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBhcnJheVZhbHVlIH07CiAgICB9CiAgICBzdGF0aWMgYXN5bmMgbWVyZ2VPYmplY3RBc3luYyhzdGF0dXMsIHBhaXJzKSB7CiAgICAgIGNvbnN0IHN5bmNQYWlycyA9IFtdOwogICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHsKICAgICAgICBjb25zdCBrZXkgPSBhd2FpdCBwYWlyLmtleTsKICAgICAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IHBhaXIudmFsdWU7CiAgICAgICAgc3luY1BhaXJzLnB1c2goewogICAgICAgICAga2V5LAogICAgICAgICAgdmFsdWUKICAgICAgICB9KTsKICAgICAgfQogICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VPYmplY3RTeW5jKHN0YXR1cywgc3luY1BhaXJzKTsKICAgIH0KICAgIHN0YXRpYyBtZXJnZU9iamVjdFN5bmMoc3RhdHVzLCBwYWlycykgewogICAgICBjb25zdCBmaW5hbE9iamVjdCA9IHt9OwogICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHsKICAgICAgICBjb25zdCB7IGtleSwgdmFsdWUgfSA9IHBhaXI7CiAgICAgICAgaWYgKGtleS5zdGF0dXMgPT09ICJhYm9ydGVkIikKICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgIGlmICh2YWx1ZS5zdGF0dXMgPT09ICJhYm9ydGVkIikKICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgIGlmIChrZXkuc3RhdHVzID09PSAiZGlydHkiKQogICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgaWYgKHZhbHVlLnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgIGlmIChrZXkudmFsdWUgIT09ICJfX3Byb3RvX18iICYmICh0eXBlb2YgdmFsdWUudmFsdWUgIT09ICJ1bmRlZmluZWQiIHx8IHBhaXIuYWx3YXlzU2V0KSkgewogICAgICAgICAgZmluYWxPYmplY3Rba2V5LnZhbHVlXSA9IHZhbHVlLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGZpbmFsT2JqZWN0IH07CiAgICB9CiAgfQogIGNvbnN0IElOVkFMSUQgPSBPYmplY3QuZnJlZXplKHsKICAgIHN0YXR1czogImFib3J0ZWQiCiAgfSk7CiAgY29uc3QgRElSVFkgPSAodmFsdWUpID0+ICh7IHN0YXR1czogImRpcnR5IiwgdmFsdWUgfSk7CiAgY29uc3QgT0sgPSAodmFsdWUpID0+ICh7IHN0YXR1czogInZhbGlkIiwgdmFsdWUgfSk7CiAgY29uc3QgaXNBYm9ydGVkID0gKHgpID0+IHguc3RhdHVzID09PSAiYWJvcnRlZCI7CiAgY29uc3QgaXNEaXJ0eSA9ICh4KSA9PiB4LnN0YXR1cyA9PT0gImRpcnR5IjsKICBjb25zdCBpc1ZhbGlkID0gKHgpID0+IHguc3RhdHVzID09PSAidmFsaWQiOwogIGNvbnN0IGlzQXN5bmMgPSAoeCkgPT4gdHlwZW9mIFByb21pc2UgIT09ICJ1bmRlZmluZWQiICYmIHggaW5zdGFuY2VvZiBQcm9taXNlOwogIGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRHZXQocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmMikgewogICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gImZ1bmN0aW9uIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZjIgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0Iik7CiAgICByZXR1cm4gc3RhdGUuZ2V0KHJlY2VpdmVyKTsKICB9CiAgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZFNldChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmMikgewogICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gImZ1bmN0aW9uIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZjIgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXQiKTsKICAgIHJldHVybiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSwgdmFsdWU7CiAgfQogIHR5cGVvZiBTdXBwcmVzc2VkRXJyb3IgPT09ICJmdW5jdGlvbiIgPyBTdXBwcmVzc2VkRXJyb3IgOiBmdW5jdGlvbihlcnJvciwgc3VwcHJlc3NlZCwgbWVzc2FnZSkgewogICAgdmFyIGUyID0gbmV3IEVycm9yKG1lc3NhZ2UpOwogICAgcmV0dXJuIGUyLm5hbWUgPSAiU3VwcHJlc3NlZEVycm9yIiwgZTIuZXJyb3IgPSBlcnJvciwgZTIuc3VwcHJlc3NlZCA9IHN1cHByZXNzZWQsIGUyOwogIH07CiAgdmFyIGVycm9yVXRpbDsKICAoZnVuY3Rpb24oZXJyb3JVdGlsMikgewogICAgZXJyb3JVdGlsMi5lcnJUb09iaiA9IChtZXNzYWdlKSA9PiB0eXBlb2YgbWVzc2FnZSA9PT0gInN0cmluZyIgPyB7IG1lc3NhZ2UgfSA6IG1lc3NhZ2UgfHwge307CiAgICBlcnJvclV0aWwyLnRvU3RyaW5nID0gKG1lc3NhZ2UpID0+IHR5cGVvZiBtZXNzYWdlID09PSAic3RyaW5nIiA/IG1lc3NhZ2UgOiBtZXNzYWdlID09PSBudWxsIHx8IG1lc3NhZ2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG1lc3NhZ2UubWVzc2FnZTsKICB9KShlcnJvclV0aWwgfHwgKGVycm9yVXRpbCA9IHt9KSk7CiAgdmFyIF9ab2RFbnVtX2NhY2hlLCBfWm9kTmF0aXZlRW51bV9jYWNoZTsKICBjbGFzcyBQYXJzZUlucHV0TGF6eVBhdGggewogICAgY29uc3RydWN0b3IocGFyZW50LCB2YWx1ZSwgcGF0aCwga2V5KSB7CiAgICAgIHRoaXMuX2NhY2hlZFBhdGggPSBbXTsKICAgICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7CiAgICAgIHRoaXMuZGF0YSA9IHZhbHVlOwogICAgICB0aGlzLl9wYXRoID0gcGF0aDsKICAgICAgdGhpcy5fa2V5ID0ga2V5OwogICAgfQogICAgZ2V0IHBhdGgoKSB7CiAgICAgIGlmICghdGhpcy5fY2FjaGVkUGF0aC5sZW5ndGgpIHsKICAgICAgICBpZiAodGhpcy5fa2V5IGluc3RhbmNlb2YgQXJyYXkpIHsKICAgICAgICAgIHRoaXMuX2NhY2hlZFBhdGgucHVzaCguLi50aGlzLl9wYXRoLCAuLi50aGlzLl9rZXkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9jYWNoZWRQYXRoLnB1c2goLi4udGhpcy5fcGF0aCwgdGhpcy5fa2V5KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlZFBhdGg7CiAgICB9CiAgfQogIGNvbnN0IGhhbmRsZVJlc3VsdCA9IChjdHgsIHJlc3VsdCkgPT4gewogICAgaWYgKGlzVmFsaWQocmVzdWx0KSkgewogICAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBkYXRhOiByZXN1bHQudmFsdWUgfTsKICAgIH0gZWxzZSB7CiAgICAgIGlmICghY3R4LmNvbW1vbi5pc3N1ZXMubGVuZ3RoKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJWYWxpZGF0aW9uIGZhaWxlZCBidXQgbm8gaXNzdWVzIGRldGVjdGVkLiIpOwogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgc3VjY2VzczogZmFsc2UsCiAgICAgICAgZ2V0IGVycm9yKCkgewogICAgICAgICAgaWYgKHRoaXMuX2Vycm9yKQogICAgICAgICAgICByZXR1cm4gdGhpcy5fZXJyb3I7CiAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBab2RFcnJvcihjdHguY29tbW9uLmlzc3Vlcyk7CiAgICAgICAgICB0aGlzLl9lcnJvciA9IGVycm9yOwogICAgICAgICAgcmV0dXJuIHRoaXMuX2Vycm9yOwogICAgICAgIH0KICAgICAgfTsKICAgIH0KICB9OwogIGZ1bmN0aW9uIHByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSB7CiAgICBpZiAoIXBhcmFtcykKICAgICAgcmV0dXJuIHt9OwogICAgY29uc3QgeyBlcnJvck1hcDogZXJyb3JNYXAyLCBpbnZhbGlkX3R5cGVfZXJyb3IsIHJlcXVpcmVkX2Vycm9yLCBkZXNjcmlwdGlvbiB9ID0gcGFyYW1zOwogICAgaWYgKGVycm9yTWFwMiAmJiAoaW52YWxpZF90eXBlX2Vycm9yIHx8IHJlcXVpcmVkX2Vycm9yKSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IHVzZSAiaW52YWxpZF90eXBlX2Vycm9yIiBvciAicmVxdWlyZWRfZXJyb3IiIGluIGNvbmp1bmN0aW9uIHdpdGggY3VzdG9tIGVycm9yIG1hcC5gKTsKICAgIH0KICAgIGlmIChlcnJvck1hcDIpCiAgICAgIHJldHVybiB7IGVycm9yTWFwOiBlcnJvck1hcDIsIGRlc2NyaXB0aW9uIH07CiAgICBjb25zdCBjdXN0b21NYXAgPSAoaXNzLCBjdHgpID0+IHsKICAgICAgdmFyIF9hLCBfYjsKICAgICAgY29uc3QgeyBtZXNzYWdlIH0gPSBwYXJhbXM7CiAgICAgIGlmIChpc3MuY29kZSA9PT0gImludmFsaWRfZW51bV92YWx1ZSIpIHsKICAgICAgICByZXR1cm4geyBtZXNzYWdlOiBtZXNzYWdlICE9PSBudWxsICYmIG1lc3NhZ2UgIT09IHZvaWQgMCA/IG1lc3NhZ2UgOiBjdHguZGVmYXVsdEVycm9yIH07CiAgICAgIH0KICAgICAgaWYgKHR5cGVvZiBjdHguZGF0YSA9PT0gInVuZGVmaW5lZCIpIHsKICAgICAgICByZXR1cm4geyBtZXNzYWdlOiAoX2EgPSBtZXNzYWdlICE9PSBudWxsICYmIG1lc3NhZ2UgIT09IHZvaWQgMCA/IG1lc3NhZ2UgOiByZXF1aXJlZF9lcnJvcikgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogY3R4LmRlZmF1bHRFcnJvciB9OwogICAgICB9CiAgICAgIGlmIChpc3MuY29kZSAhPT0gImludmFsaWRfdHlwZSIpCiAgICAgICAgcmV0dXJuIHsgbWVzc2FnZTogY3R4LmRlZmF1bHRFcnJvciB9OwogICAgICByZXR1cm4geyBtZXNzYWdlOiAoX2IgPSBtZXNzYWdlICE9PSBudWxsICYmIG1lc3NhZ2UgIT09IHZvaWQgMCA/IG1lc3NhZ2UgOiBpbnZhbGlkX3R5cGVfZXJyb3IpICE9PSBudWxsICYmIF9iICE9PSB2b2lkIDAgPyBfYiA6IGN0eC5kZWZhdWx0RXJyb3IgfTsKICAgIH07CiAgICByZXR1cm4geyBlcnJvck1hcDogY3VzdG9tTWFwLCBkZXNjcmlwdGlvbiB9OwogIH0KICBjbGFzcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKGRlZikgewogICAgICB0aGlzLnNwYSA9IHRoaXMuc2FmZVBhcnNlQXN5bmM7CiAgICAgIHRoaXMuX2RlZiA9IGRlZjsKICAgICAgdGhpcy5wYXJzZSA9IHRoaXMucGFyc2UuYmluZCh0aGlzKTsKICAgICAgdGhpcy5zYWZlUGFyc2UgPSB0aGlzLnNhZmVQYXJzZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLnBhcnNlQXN5bmMgPSB0aGlzLnBhcnNlQXN5bmMuYmluZCh0aGlzKTsKICAgICAgdGhpcy5zYWZlUGFyc2VBc3luYyA9IHRoaXMuc2FmZVBhcnNlQXN5bmMuYmluZCh0aGlzKTsKICAgICAgdGhpcy5zcGEgPSB0aGlzLnNwYS5iaW5kKHRoaXMpOwogICAgICB0aGlzLnJlZmluZSA9IHRoaXMucmVmaW5lLmJpbmQodGhpcyk7CiAgICAgIHRoaXMucmVmaW5lbWVudCA9IHRoaXMucmVmaW5lbWVudC5iaW5kKHRoaXMpOwogICAgICB0aGlzLnN1cGVyUmVmaW5lID0gdGhpcy5zdXBlclJlZmluZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLm9wdGlvbmFsID0gdGhpcy5vcHRpb25hbC5iaW5kKHRoaXMpOwogICAgICB0aGlzLm51bGxhYmxlID0gdGhpcy5udWxsYWJsZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLm51bGxpc2ggPSB0aGlzLm51bGxpc2guYmluZCh0aGlzKTsKICAgICAgdGhpcy5hcnJheSA9IHRoaXMuYXJyYXkuYmluZCh0aGlzKTsKICAgICAgdGhpcy5wcm9taXNlID0gdGhpcy5wcm9taXNlLmJpbmQodGhpcyk7CiAgICAgIHRoaXMub3IgPSB0aGlzLm9yLmJpbmQodGhpcyk7CiAgICAgIHRoaXMuYW5kID0gdGhpcy5hbmQuYmluZCh0aGlzKTsKICAgICAgdGhpcy50cmFuc2Zvcm0gPSB0aGlzLnRyYW5zZm9ybS5iaW5kKHRoaXMpOwogICAgICB0aGlzLmJyYW5kID0gdGhpcy5icmFuZC5iaW5kKHRoaXMpOwogICAgICB0aGlzLmRlZmF1bHQgPSB0aGlzLmRlZmF1bHQuYmluZCh0aGlzKTsKICAgICAgdGhpcy5jYXRjaCA9IHRoaXMuY2F0Y2guYmluZCh0aGlzKTsKICAgICAgdGhpcy5kZXNjcmliZSA9IHRoaXMuZGVzY3JpYmUuYmluZCh0aGlzKTsKICAgICAgdGhpcy5waXBlID0gdGhpcy5waXBlLmJpbmQodGhpcyk7CiAgICAgIHRoaXMucmVhZG9ubHkgPSB0aGlzLnJlYWRvbmx5LmJpbmQodGhpcyk7CiAgICAgIHRoaXMuaXNOdWxsYWJsZSA9IHRoaXMuaXNOdWxsYWJsZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLmlzT3B0aW9uYWwgPSB0aGlzLmlzT3B0aW9uYWwuYmluZCh0aGlzKTsKICAgIH0KICAgIGdldCBkZXNjcmlwdGlvbigpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5kZXNjcmlwdGlvbjsKICAgIH0KICAgIF9nZXRUeXBlKGlucHV0KSB7CiAgICAgIHJldHVybiBnZXRQYXJzZWRUeXBlKGlucHV0LmRhdGEpOwogICAgfQogICAgX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpIHsKICAgICAgcmV0dXJuIGN0eCB8fCB7CiAgICAgICAgY29tbW9uOiBpbnB1dC5wYXJlbnQuY29tbW9uLAogICAgICAgIGRhdGE6IGlucHV0LmRhdGEsCiAgICAgICAgcGFyc2VkVHlwZTogZ2V0UGFyc2VkVHlwZShpbnB1dC5kYXRhKSwKICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLAogICAgICAgIHBhdGg6IGlucHV0LnBhdGgsCiAgICAgICAgcGFyZW50OiBpbnB1dC5wYXJlbnQKICAgICAgfTsKICAgIH0KICAgIF9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBzdGF0dXM6IG5ldyBQYXJzZVN0YXR1cygpLAogICAgICAgIGN0eDogewogICAgICAgICAgY29tbW9uOiBpbnB1dC5wYXJlbnQuY29tbW9uLAogICAgICAgICAgZGF0YTogaW5wdXQuZGF0YSwKICAgICAgICAgIHBhcnNlZFR5cGU6IGdldFBhcnNlZFR5cGUoaW5wdXQuZGF0YSksCiAgICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLAogICAgICAgICAgcGF0aDogaW5wdXQucGF0aCwKICAgICAgICAgIHBhcmVudDogaW5wdXQucGFyZW50CiAgICAgICAgfQogICAgICB9OwogICAgfQogICAgX3BhcnNlU3luYyhpbnB1dCkgewogICAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9wYXJzZShpbnB1dCk7CiAgICAgIGlmIChpc0FzeW5jKHJlc3VsdCkpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlN5bmNocm9ub3VzIHBhcnNlIGVuY291bnRlcmVkIHByb21pc2UuIik7CiAgICAgIH0KICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIF9wYXJzZUFzeW5jKGlucHV0KSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX3BhcnNlKGlucHV0KTsKICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHQpOwogICAgfQogICAgcGFyc2UoZGF0YSwgcGFyYW1zKSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuc2FmZVBhcnNlKGRhdGEsIHBhcmFtcyk7CiAgICAgIGlmIChyZXN1bHQuc3VjY2VzcykKICAgICAgICByZXR1cm4gcmVzdWx0LmRhdGE7CiAgICAgIHRocm93IHJlc3VsdC5lcnJvcjsKICAgIH0KICAgIHNhZmVQYXJzZShkYXRhLCBwYXJhbXMpIHsKICAgICAgdmFyIF9hOwogICAgICBjb25zdCBjdHggPSB7CiAgICAgICAgY29tbW9uOiB7CiAgICAgICAgICBpc3N1ZXM6IFtdLAogICAgICAgICAgYXN5bmM6IChfYSA9IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5hc3luYykgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogZmFsc2UsCiAgICAgICAgICBjb250ZXh0dWFsRXJyb3JNYXA6IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5lcnJvck1hcAogICAgICAgIH0sCiAgICAgICAgcGF0aDogKHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5wYXRoKSB8fCBbXSwKICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLAogICAgICAgIHBhcmVudDogbnVsbCwKICAgICAgICBkYXRhLAogICAgICAgIHBhcnNlZFR5cGU6IGdldFBhcnNlZFR5cGUoZGF0YSkKICAgICAgfTsKICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fcGFyc2VTeW5jKHsgZGF0YSwgcGF0aDogY3R4LnBhdGgsIHBhcmVudDogY3R4IH0pOwogICAgICByZXR1cm4gaGFuZGxlUmVzdWx0KGN0eCwgcmVzdWx0KTsKICAgIH0KICAgIGFzeW5jIHBhcnNlQXN5bmMoZGF0YSwgcGFyYW1zKSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuc2FmZVBhcnNlQXN5bmMoZGF0YSwgcGFyYW1zKTsKICAgICAgaWYgKHJlc3VsdC5zdWNjZXNzKQogICAgICAgIHJldHVybiByZXN1bHQuZGF0YTsKICAgICAgdGhyb3cgcmVzdWx0LmVycm9yOwogICAgfQogICAgYXN5bmMgc2FmZVBhcnNlQXN5bmMoZGF0YSwgcGFyYW1zKSB7CiAgICAgIGNvbnN0IGN0eCA9IHsKICAgICAgICBjb21tb246IHsKICAgICAgICAgIGlzc3VlczogW10sCiAgICAgICAgICBjb250ZXh0dWFsRXJyb3JNYXA6IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5lcnJvck1hcCwKICAgICAgICAgIGFzeW5jOiB0cnVlCiAgICAgICAgfSwKICAgICAgICBwYXRoOiAocGFyYW1zID09PSBudWxsIHx8IHBhcmFtcyA9PT0gdm9pZCAwID8gdm9pZCAwIDogcGFyYW1zLnBhdGgpIHx8IFtdLAogICAgICAgIHNjaGVtYUVycm9yTWFwOiB0aGlzLl9kZWYuZXJyb3JNYXAsCiAgICAgICAgcGFyZW50OiBudWxsLAogICAgICAgIGRhdGEsCiAgICAgICAgcGFyc2VkVHlwZTogZ2V0UGFyc2VkVHlwZShkYXRhKQogICAgICB9OwogICAgICBjb25zdCBtYXliZUFzeW5jUmVzdWx0ID0gdGhpcy5fcGFyc2UoeyBkYXRhLCBwYXRoOiBjdHgucGF0aCwgcGFyZW50OiBjdHggfSk7CiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IChpc0FzeW5jKG1heWJlQXN5bmNSZXN1bHQpID8gbWF5YmVBc3luY1Jlc3VsdCA6IFByb21pc2UucmVzb2x2ZShtYXliZUFzeW5jUmVzdWx0KSk7CiAgICAgIHJldHVybiBoYW5kbGVSZXN1bHQoY3R4LCByZXN1bHQpOwogICAgfQogICAgcmVmaW5lKGNoZWNrLCBtZXNzYWdlKSB7CiAgICAgIGNvbnN0IGdldElzc3VlUHJvcGVydGllcyA9ICh2YWwpID0+IHsKICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgPT09ICJzdHJpbmciIHx8IHR5cGVvZiBtZXNzYWdlID09PSAidW5kZWZpbmVkIikgewogICAgICAgICAgcmV0dXJuIHsgbWVzc2FnZSB9OwogICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG1lc3NhZ2UgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgIHJldHVybiBtZXNzYWdlKHZhbCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBtZXNzYWdlOwogICAgICAgIH0KICAgICAgfTsKICAgICAgcmV0dXJuIHRoaXMuX3JlZmluZW1lbnQoKHZhbCwgY3R4KSA9PiB7CiAgICAgICAgY29uc3QgcmVzdWx0ID0gY2hlY2sodmFsKTsKICAgICAgICBjb25zdCBzZXRFcnJvciA9ICgpID0+IGN0eC5hZGRJc3N1ZSh7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuY3VzdG9tLAogICAgICAgICAgLi4uZ2V0SXNzdWVQcm9wZXJ0aWVzKHZhbCkKICAgICAgICB9KTsKICAgICAgICBpZiAodHlwZW9mIFByb21pc2UgIT09ICJ1bmRlZmluZWQiICYmIHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UpIHsKICAgICAgICAgIHJldHVybiByZXN1bHQudGhlbigoZGF0YSkgPT4gewogICAgICAgICAgICBpZiAoIWRhdGEpIHsKICAgICAgICAgICAgICBzZXRFcnJvcigpOwogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGlmICghcmVzdWx0KSB7CiAgICAgICAgICBzZXRFcnJvcigpOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogICAgcmVmaW5lbWVudChjaGVjaywgcmVmaW5lbWVudERhdGEpIHsKICAgICAgcmV0dXJuIHRoaXMuX3JlZmluZW1lbnQoKHZhbCwgY3R4KSA9PiB7CiAgICAgICAgaWYgKCFjaGVjayh2YWwpKSB7CiAgICAgICAgICBjdHguYWRkSXNzdWUodHlwZW9mIHJlZmluZW1lbnREYXRhID09PSAiZnVuY3Rpb24iID8gcmVmaW5lbWVudERhdGEodmFsLCBjdHgpIDogcmVmaW5lbWVudERhdGEpOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogICAgX3JlZmluZW1lbnQocmVmaW5lbWVudCkgewogICAgICByZXR1cm4gbmV3IFpvZEVmZmVjdHMoewogICAgICAgIHNjaGVtYTogdGhpcywKICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMsCiAgICAgICAgZWZmZWN0OiB7IHR5cGU6ICJyZWZpbmVtZW50IiwgcmVmaW5lbWVudCB9CiAgICAgIH0pOwogICAgfQogICAgc3VwZXJSZWZpbmUocmVmaW5lbWVudCkgewogICAgICByZXR1cm4gdGhpcy5fcmVmaW5lbWVudChyZWZpbmVtZW50KTsKICAgIH0KICAgIG9wdGlvbmFsKCkgewogICAgICByZXR1cm4gWm9kT3B0aW9uYWwuY3JlYXRlKHRoaXMsIHRoaXMuX2RlZik7CiAgICB9CiAgICBudWxsYWJsZSgpIHsKICAgICAgcmV0dXJuIFpvZE51bGxhYmxlLmNyZWF0ZSh0aGlzLCB0aGlzLl9kZWYpOwogICAgfQogICAgbnVsbGlzaCgpIHsKICAgICAgcmV0dXJuIHRoaXMubnVsbGFibGUoKS5vcHRpb25hbCgpOwogICAgfQogICAgYXJyYXkoKSB7CiAgICAgIHJldHVybiBab2RBcnJheS5jcmVhdGUodGhpcywgdGhpcy5fZGVmKTsKICAgIH0KICAgIHByb21pc2UoKSB7CiAgICAgIHJldHVybiBab2RQcm9taXNlLmNyZWF0ZSh0aGlzLCB0aGlzLl9kZWYpOwogICAgfQogICAgb3Iob3B0aW9uKSB7CiAgICAgIHJldHVybiBab2RVbmlvbi5jcmVhdGUoW3RoaXMsIG9wdGlvbl0sIHRoaXMuX2RlZik7CiAgICB9CiAgICBhbmQoaW5jb21pbmcpIHsKICAgICAgcmV0dXJuIFpvZEludGVyc2VjdGlvbi5jcmVhdGUodGhpcywgaW5jb21pbmcsIHRoaXMuX2RlZik7CiAgICB9CiAgICB0cmFuc2Zvcm0odHJhbnNmb3JtKSB7CiAgICAgIHJldHVybiBuZXcgWm9kRWZmZWN0cyh7CiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyh0aGlzLl9kZWYpLAogICAgICAgIHNjaGVtYTogdGhpcywKICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMsCiAgICAgICAgZWZmZWN0OiB7IHR5cGU6ICJ0cmFuc2Zvcm0iLCB0cmFuc2Zvcm0gfQogICAgICB9KTsKICAgIH0KICAgIGRlZmF1bHQoZGVmKSB7CiAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZUZ1bmMgPSB0eXBlb2YgZGVmID09PSAiZnVuY3Rpb24iID8gZGVmIDogKCkgPT4gZGVmOwogICAgICByZXR1cm4gbmV3IFpvZERlZmF1bHQoewogICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXModGhpcy5fZGVmKSwKICAgICAgICBpbm5lclR5cGU6IHRoaXMsCiAgICAgICAgZGVmYXVsdFZhbHVlOiBkZWZhdWx0VmFsdWVGdW5jLAogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRGVmYXVsdAogICAgICB9KTsKICAgIH0KICAgIGJyYW5kKCkgewogICAgICByZXR1cm4gbmV3IFpvZEJyYW5kZWQoewogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kQnJhbmRlZCwKICAgICAgICB0eXBlOiB0aGlzLAogICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXModGhpcy5fZGVmKQogICAgICB9KTsKICAgIH0KICAgIGNhdGNoKGRlZikgewogICAgICBjb25zdCBjYXRjaFZhbHVlRnVuYyA9IHR5cGVvZiBkZWYgPT09ICJmdW5jdGlvbiIgPyBkZWYgOiAoKSA9PiBkZWY7CiAgICAgIHJldHVybiBuZXcgWm9kQ2F0Y2goewogICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXModGhpcy5fZGVmKSwKICAgICAgICBpbm5lclR5cGU6IHRoaXMsCiAgICAgICAgY2F0Y2hWYWx1ZTogY2F0Y2hWYWx1ZUZ1bmMsCiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RDYXRjaAogICAgICB9KTsKICAgIH0KICAgIGRlc2NyaWJlKGRlc2NyaXB0aW9uKSB7CiAgICAgIGNvbnN0IFRoaXMgPSB0aGlzLmNvbnN0cnVjdG9yOwogICAgICByZXR1cm4gbmV3IFRoaXMoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBkZXNjcmlwdGlvbgogICAgICB9KTsKICAgIH0KICAgIHBpcGUodGFyZ2V0KSB7CiAgICAgIHJldHVybiBab2RQaXBlbGluZS5jcmVhdGUodGhpcywgdGFyZ2V0KTsKICAgIH0KICAgIHJlYWRvbmx5KCkgewogICAgICByZXR1cm4gWm9kUmVhZG9ubHkuY3JlYXRlKHRoaXMpOwogICAgfQogICAgaXNPcHRpb25hbCgpIHsKICAgICAgcmV0dXJuIHRoaXMuc2FmZVBhcnNlKHZvaWQgMCkuc3VjY2VzczsKICAgIH0KICAgIGlzTnVsbGFibGUoKSB7CiAgICAgIHJldHVybiB0aGlzLnNhZmVQYXJzZShudWxsKS5zdWNjZXNzOwogICAgfQogIH0KICBjb25zdCBjdWlkUmVnZXggPSAvXmNbXlxzLV17OCx9JC9pOwogIGNvbnN0IGN1aWQyUmVnZXggPSAvXlswLTlhLXpdKyQvOwogIGNvbnN0IHVsaWRSZWdleCA9IC9eWzAtOUEtSEpLTU5QLVRWLVpdezI2fSQvOwogIGNvbnN0IHV1aWRSZWdleCA9IC9eWzAtOWEtZkEtRl17OH1cYi1bMC05YS1mQS1GXXs0fVxiLVswLTlhLWZBLUZdezR9XGItWzAtOWEtZkEtRl17NH1cYi1bMC05YS1mQS1GXXsxMn0kL2k7CiAgY29uc3QgbmFub2lkUmVnZXggPSAvXlthLXowLTlfLV17MjF9JC9pOwogIGNvbnN0IGR1cmF0aW9uUmVnZXggPSAvXlstK10/UCg/ISQpKD86KD86Wy0rXT9cZCtZKXwoPzpbLStdP1xkK1suLF1cZCtZJCkpPyg/Oig/OlstK10/XGQrTSl8KD86Wy0rXT9cZCtbLixdXGQrTSQpKT8oPzooPzpbLStdP1xkK1cpfCg/OlstK10/XGQrWy4sXVxkK1ckKSk/KD86KD86Wy0rXT9cZCtEKXwoPzpbLStdP1xkK1suLF1cZCtEJCkpPyg/OlQoPz1bXGQrLV0pKD86KD86Wy0rXT9cZCtIKXwoPzpbLStdP1xkK1suLF1cZCtIJCkpPyg/Oig/OlstK10/XGQrTSl8KD86Wy0rXT9cZCtbLixdXGQrTSQpKT8oPzpbLStdP1xkKyg/OlsuLF1cZCspP1MpPyk/PyQvOwogIGNvbnN0IGVtYWlsUmVnZXggPSAvXig/IVwuKSg/IS4qXC5cLikoW0EtWjAtOV8nK1wtXC5dKilbQS1aMC05XystXUAoW0EtWjAtOV1bQS1aMC05XC1dKlwuKStbQS1aXXsyLH0kL2k7CiAgY29uc3QgX2Vtb2ppUmVnZXggPSBgXihcXHB7RXh0ZW5kZWRfUGljdG9ncmFwaGljfXxcXHB7RW1vamlfQ29tcG9uZW50fSkrJGA7CiAgbGV0IGVtb2ppUmVnZXg7CiAgY29uc3QgaXB2NFJlZ2V4ID0gL14oPzooPzoyNVswLTVdfDJbMC00XVswLTldfDFbMC05XVswLTldfFsxLTldWzAtOV18WzAtOV0pXC4pezN9KD86MjVbMC01XXwyWzAtNF1bMC05XXwxWzAtOV1bMC05XXxbMS05XVswLTldfFswLTldKSQvOwogIGNvbnN0IGlwdjZSZWdleCA9IC9eKChbYS1mMC05XXsxLDR9Oil7N318OjooW2EtZjAtOV17MSw0fTopezAsNn18KFthLWYwLTldezEsNH06KXsxfTooW2EtZjAtOV17MSw0fTopezAsNX18KFthLWYwLTldezEsNH06KXsyfTooW2EtZjAtOV17MSw0fTopezAsNH18KFthLWYwLTldezEsNH06KXszfTooW2EtZjAtOV17MSw0fTopezAsM318KFthLWYwLTldezEsNH06KXs0fTooW2EtZjAtOV17MSw0fTopezAsMn18KFthLWYwLTldezEsNH06KXs1fTooW2EtZjAtOV17MSw0fTopezAsMX0pKFthLWYwLTldezEsNH18KCgoMjVbMC01XSl8KDJbMC00XVswLTldKXwoMVswLTldezJ9KXwoWzAtOV17MSwyfSkpXC4pezN9KCgyNVswLTVdKXwoMlswLTRdWzAtOV0pfCgxWzAtOV17Mn0pfChbMC05XXsxLDJ9KSkpJC87CiAgY29uc3QgYmFzZTY0UmVnZXggPSAvXihbMC05YS16QS1aKy9dezR9KSooKFswLTlhLXpBLVorL117Mn09PSl8KFswLTlhLXpBLVorL117M309KSk/JC87CiAgY29uc3QgZGF0ZVJlZ2V4U291cmNlID0gYCgoXFxkXFxkWzI0NjhdWzA0OF18XFxkXFxkWzEzNTc5XVsyNl18XFxkXFxkMFs0OF18WzAyNDY4XVswNDhdMDB8WzEzNTc5XVsyNl0wMCktMDItMjl8XFxkezR9LSgoMFsxMzU3OF18MVswMl0pLSgwWzEtOV18WzEyXVxcZHwzWzAxXSl8KDBbNDY5XXwxMSktKDBbMS05XXxbMTJdXFxkfDMwKXwoMDIpLSgwWzEtOV18MVxcZHwyWzAtOF0pKSlgOwogIGNvbnN0IGRhdGVSZWdleCA9IG5ldyBSZWdFeHAoYF4ke2RhdGVSZWdleFNvdXJjZX0kYCk7CiAgZnVuY3Rpb24gdGltZVJlZ2V4U291cmNlKGFyZ3MpIHsKICAgIGxldCByZWdleCA9IGAoWzAxXVxcZHwyWzAtM10pOlswLTVdXFxkOlswLTVdXFxkYDsKICAgIGlmIChhcmdzLnByZWNpc2lvbikgewogICAgICByZWdleCA9IGAke3JlZ2V4fVxcLlxcZHske2FyZ3MucHJlY2lzaW9ufX1gOwogICAgfSBlbHNlIGlmIChhcmdzLnByZWNpc2lvbiA9PSBudWxsKSB7CiAgICAgIHJlZ2V4ID0gYCR7cmVnZXh9KFxcLlxcZCspP2A7CiAgICB9CiAgICByZXR1cm4gcmVnZXg7CiAgfQogIGZ1bmN0aW9uIHRpbWVSZWdleChhcmdzKSB7CiAgICByZXR1cm4gbmV3IFJlZ0V4cChgXiR7dGltZVJlZ2V4U291cmNlKGFyZ3MpfSRgKTsKICB9CiAgZnVuY3Rpb24gZGF0ZXRpbWVSZWdleChhcmdzKSB7CiAgICBsZXQgcmVnZXggPSBgJHtkYXRlUmVnZXhTb3VyY2V9VCR7dGltZVJlZ2V4U291cmNlKGFyZ3MpfWA7CiAgICBjb25zdCBvcHRzID0gW107CiAgICBvcHRzLnB1c2goYXJncy5sb2NhbCA/IGBaP2AgOiBgWmApOwogICAgaWYgKGFyZ3Mub2Zmc2V0KQogICAgICBvcHRzLnB1c2goYChbKy1dXFxkezJ9Oj9cXGR7Mn0pYCk7CiAgICByZWdleCA9IGAke3JlZ2V4fSgke29wdHMuam9pbigifCIpfSlgOwogICAgcmV0dXJuIG5ldyBSZWdFeHAoYF4ke3JlZ2V4fSRgKTsKICB9CiAgZnVuY3Rpb24gaXNWYWxpZElQKGlwLCB2ZXJzaW9uKSB7CiAgICBpZiAoKHZlcnNpb24gPT09ICJ2NCIgfHwgIXZlcnNpb24pICYmIGlwdjRSZWdleC50ZXN0KGlwKSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmICgodmVyc2lvbiA9PT0gInY2IiB8fCAhdmVyc2lvbikgJiYgaXB2NlJlZ2V4LnRlc3QoaXApKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICBjbGFzcyBab2RTdHJpbmcgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBpZiAodGhpcy5fZGVmLmNvZXJjZSkgewogICAgICAgIGlucHV0LmRhdGEgPSBTdHJpbmcoaW5wdXQuZGF0YSk7CiAgICAgIH0KICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5zdHJpbmcpIHsKICAgICAgICBjb25zdCBjdHgyID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eDIsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5zdHJpbmcsCiAgICAgICAgICByZWNlaXZlZDogY3R4Mi5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgY29uc3Qgc3RhdHVzID0gbmV3IFBhcnNlU3RhdHVzKCk7CiAgICAgIGxldCBjdHggPSB2b2lkIDA7CiAgICAgIGZvciAoY29uc3QgY2hlY2sgb2YgdGhpcy5fZGVmLmNoZWNrcykgewogICAgICAgIGlmIChjaGVjay5raW5kID09PSAibWluIikgewogICAgICAgICAgaWYgKGlucHV0LmRhdGEubGVuZ3RoIDwgY2hlY2sudmFsdWUpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgICAgbWluaW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogInN0cmluZyIsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAoaW5wdXQuZGF0YS5sZW5ndGggPiBjaGVjay52YWx1ZSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsCiAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogInN0cmluZyIsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJsZW5ndGgiKSB7CiAgICAgICAgICBjb25zdCB0b29CaWcgPSBpbnB1dC5kYXRhLmxlbmd0aCA+IGNoZWNrLnZhbHVlOwogICAgICAgICAgY29uc3QgdG9vU21hbGwgPSBpbnB1dC5kYXRhLmxlbmd0aCA8IGNoZWNrLnZhbHVlOwogICAgICAgICAgaWYgKHRvb0JpZyB8fCB0b29TbWFsbCkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgaWYgKHRvb0JpZykgewogICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsCiAgICAgICAgICAgICAgICBtYXhpbXVtOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICAgIHR5cGU6ICJzdHJpbmciLAogICAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgICAgZXhhY3Q6IHRydWUsCiAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAodG9vU21hbGwpIHsKICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgICAgICBtaW5pbXVtOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICAgIHR5cGU6ICJzdHJpbmciLAogICAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgICAgZXhhY3Q6IHRydWUsCiAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiZW1haWwiKSB7CiAgICAgICAgICBpZiAoIWVtYWlsUmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImVtYWlsIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiZW1vamkiKSB7CiAgICAgICAgICBpZiAoIWVtb2ppUmVnZXgpIHsKICAgICAgICAgICAgZW1vamlSZWdleCA9IG5ldyBSZWdFeHAoX2Vtb2ppUmVnZXgsICJ1Iik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIWVtb2ppUmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImVtb2ppIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidXVpZCIpIHsKICAgICAgICAgIGlmICghdXVpZFJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJ1dWlkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAibmFub2lkIikgewogICAgICAgICAgaWYgKCFuYW5vaWRSZWdleC50ZXN0KGlucHV0LmRhdGEpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiAibmFub2lkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiY3VpZCIpIHsKICAgICAgICAgIGlmICghY3VpZFJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJjdWlkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiY3VpZDIiKSB7CiAgICAgICAgICBpZiAoIWN1aWQyUmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImN1aWQyIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidWxpZCIpIHsKICAgICAgICAgIGlmICghdWxpZFJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJ1bGlkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidXJsIikgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgbmV3IFVSTChpbnB1dC5kYXRhKTsKICAgICAgICAgIH0gY2F0Y2ggKF9hKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiAidXJsIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAicmVnZXgiKSB7CiAgICAgICAgICBjaGVjay5yZWdleC5sYXN0SW5kZXggPSAwOwogICAgICAgICAgY29uc3QgdGVzdFJlc3VsdCA9IGNoZWNrLnJlZ2V4LnRlc3QoaW5wdXQuZGF0YSk7CiAgICAgICAgICBpZiAoIXRlc3RSZXN1bHQpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJyZWdleCIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gInRyaW0iKSB7CiAgICAgICAgICBpbnB1dC5kYXRhID0gaW5wdXQuZGF0YS50cmltKCk7CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiaW5jbHVkZXMiKSB7CiAgICAgICAgICBpZiAoIWlucHV0LmRhdGEuaW5jbHVkZXMoY2hlY2sudmFsdWUsIGNoZWNrLnBvc2l0aW9uKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIHZhbGlkYXRpb246IHsgaW5jbHVkZXM6IGNoZWNrLnZhbHVlLCBwb3NpdGlvbjogY2hlY2sucG9zaXRpb24gfSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJ0b0xvd2VyQ2FzZSIpIHsKICAgICAgICAgIGlucHV0LmRhdGEgPSBpbnB1dC5kYXRhLnRvTG93ZXJDYXNlKCk7CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidG9VcHBlckNhc2UiKSB7CiAgICAgICAgICBpbnB1dC5kYXRhID0gaW5wdXQuZGF0YS50b1VwcGVyQ2FzZSgpOwogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gInN0YXJ0c1dpdGgiKSB7CiAgICAgICAgICBpZiAoIWlucHV0LmRhdGEuc3RhcnRzV2l0aChjaGVjay52YWx1ZSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZywKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiB7IHN0YXJ0c1dpdGg6IGNoZWNrLnZhbHVlIH0sCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiZW5kc1dpdGgiKSB7CiAgICAgICAgICBpZiAoIWlucHV0LmRhdGEuZW5kc1dpdGgoY2hlY2sudmFsdWUpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogeyBlbmRzV2l0aDogY2hlY2sudmFsdWUgfSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJkYXRldGltZSIpIHsKICAgICAgICAgIGNvbnN0IHJlZ2V4ID0gZGF0ZXRpbWVSZWdleChjaGVjayk7CiAgICAgICAgICBpZiAoIXJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZywKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiAiZGF0ZXRpbWUiLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImRhdGUiKSB7CiAgICAgICAgICBjb25zdCByZWdleCA9IGRhdGVSZWdleDsKICAgICAgICAgIGlmICghcmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJkYXRlIiwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJ0aW1lIikgewogICAgICAgICAgY29uc3QgcmVnZXggPSB0aW1lUmVnZXgoY2hlY2spOwogICAgICAgICAgaWYgKCFyZWdleC50ZXN0KGlucHV0LmRhdGEpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogInRpbWUiLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImR1cmF0aW9uIikgewogICAgICAgICAgaWYgKCFkdXJhdGlvblJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJkdXJhdGlvbiIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImlwIikgewogICAgICAgICAgaWYgKCFpc1ZhbGlkSVAoaW5wdXQuZGF0YSwgY2hlY2sudmVyc2lvbikpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJpcCIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImJhc2U2NCIpIHsKICAgICAgICAgIGlmICghYmFzZTY0UmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImJhc2U2NCIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB1dGlsLmFzc2VydE5ldmVyKGNoZWNrKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBpbnB1dC5kYXRhIH07CiAgICB9CiAgICBfcmVnZXgocmVnZXgsIHZhbGlkYXRpb24sIG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMucmVmaW5lbWVudCgoZGF0YSkgPT4gcmVnZXgudGVzdChkYXRhKSwgewogICAgICAgIHZhbGlkYXRpb24sCiAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIF9hZGRDaGVjayhjaGVjaykgewogICAgICByZXR1cm4gbmV3IFpvZFN0cmluZyh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIGNoZWNrczogWy4uLnRoaXMuX2RlZi5jaGVja3MsIGNoZWNrXQogICAgICB9KTsKICAgIH0KICAgIGVtYWlsKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImVtYWlsIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgdXJsKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogInVybCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGVtb2ppKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImVtb2ppIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgdXVpZChtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6ICJ1dWlkIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgbmFub2lkKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogIm5hbm9pZCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGN1aWQobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soeyBraW5kOiAiY3VpZCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGN1aWQyKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImN1aWQyIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgdWxpZChtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6ICJ1bGlkIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgYmFzZTY0KG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImJhc2U2NCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGlwKG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImlwIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG9wdGlvbnMpIH0pOwogICAgfQogICAgZGF0ZXRpbWUob3B0aW9ucykgewogICAgICB2YXIgX2EsIF9iOwogICAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICJzdHJpbmciKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICAgIGtpbmQ6ICJkYXRldGltZSIsCiAgICAgICAgICBwcmVjaXNpb246IG51bGwsCiAgICAgICAgICBvZmZzZXQ6IGZhbHNlLAogICAgICAgICAgbG9jYWw6IGZhbHNlLAogICAgICAgICAgbWVzc2FnZTogb3B0aW9ucwogICAgICAgIH0pOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImRhdGV0aW1lIiwKICAgICAgICBwcmVjaXNpb246IHR5cGVvZiAob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLnByZWNpc2lvbikgPT09ICJ1bmRlZmluZWQiID8gbnVsbCA6IG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5wcmVjaXNpb24sCiAgICAgICAgb2Zmc2V0OiAoX2EgPSBvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMub2Zmc2V0KSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiBmYWxzZSwKICAgICAgICBsb2NhbDogKF9iID0gb3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLmxvY2FsKSAhPT0gbnVsbCAmJiBfYiAhPT0gdm9pZCAwID8gX2IgOiBmYWxzZSwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLm1lc3NhZ2UpCiAgICAgIH0pOwogICAgfQogICAgZGF0ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6ICJkYXRlIiwgbWVzc2FnZSB9KTsKICAgIH0KICAgIHRpbWUob3B0aW9ucykgewogICAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICJzdHJpbmciKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICAgIGtpbmQ6ICJ0aW1lIiwKICAgICAgICAgIHByZWNpc2lvbjogbnVsbCwKICAgICAgICAgIG1lc3NhZ2U6IG9wdGlvbnMKICAgICAgICB9KTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJ0aW1lIiwKICAgICAgICBwcmVjaXNpb246IHR5cGVvZiAob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLnByZWNpc2lvbikgPT09ICJ1bmRlZmluZWQiID8gbnVsbCA6IG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5wcmVjaXNpb24sCiAgICAgICAgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5tZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGR1cmF0aW9uKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImR1cmF0aW9uIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgcmVnZXgocmVnZXgsIG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAicmVnZXgiLAogICAgICAgIHJlZ2V4LAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGluY2x1ZGVzKHZhbHVlLCBvcHRpb25zKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImluY2x1ZGVzIiwKICAgICAgICB2YWx1ZSwKICAgICAgICBwb3NpdGlvbjogb3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLnBvc2l0aW9uLAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMubWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBzdGFydHNXaXRoKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogInN0YXJ0c1dpdGgiLAogICAgICAgIHZhbHVlLAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGVuZHNXaXRoKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImVuZHNXaXRoIiwKICAgICAgICB2YWx1ZSwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBtaW4obWluTGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IG1pbkxlbmd0aCwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBtYXgobWF4TGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IG1heExlbmd0aCwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBsZW5ndGgobGVuLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImxlbmd0aCIsCiAgICAgICAgdmFsdWU6IGxlbiwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICAvKioKICAgICAqIEBkZXByZWNhdGVkIFVzZSB6LnN0cmluZygpLm1pbigxKSBpbnN0ZWFkLgogICAgICogQHNlZSB7QGxpbmsgWm9kU3RyaW5nLm1pbn0KICAgICAqLwogICAgbm9uZW1wdHkobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5taW4oMSwgZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpKTsKICAgIH0KICAgIHRyaW0oKSB7CiAgICAgIHJldHVybiBuZXcgWm9kU3RyaW5nKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgeyBraW5kOiAidHJpbSIgfV0KICAgICAgfSk7CiAgICB9CiAgICB0b0xvd2VyQ2FzZSgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RTdHJpbmcoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBjaGVja3M6IFsuLi50aGlzLl9kZWYuY2hlY2tzLCB7IGtpbmQ6ICJ0b0xvd2VyQ2FzZSIgfV0KICAgICAgfSk7CiAgICB9CiAgICB0b1VwcGVyQ2FzZSgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RTdHJpbmcoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBjaGVja3M6IFsuLi50aGlzLl9kZWYuY2hlY2tzLCB7IGtpbmQ6ICJ0b1VwcGVyQ2FzZSIgfV0KICAgICAgfSk7CiAgICB9CiAgICBnZXQgaXNEYXRldGltZSgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImRhdGV0aW1lIik7CiAgICB9CiAgICBnZXQgaXNEYXRlKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiZGF0ZSIpOwogICAgfQogICAgZ2V0IGlzVGltZSgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gInRpbWUiKTsKICAgIH0KICAgIGdldCBpc0R1cmF0aW9uKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiZHVyYXRpb24iKTsKICAgIH0KICAgIGdldCBpc0VtYWlsKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiZW1haWwiKTsKICAgIH0KICAgIGdldCBpc1VSTCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gInVybCIpOwogICAgfQogICAgZ2V0IGlzRW1vamkoKSB7CiAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09ICJlbW9qaSIpOwogICAgfQogICAgZ2V0IGlzVVVJRCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gInV1aWQiKTsKICAgIH0KICAgIGdldCBpc05BTk9JRCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gIm5hbm9pZCIpOwogICAgfQogICAgZ2V0IGlzQ1VJRCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImN1aWQiKTsKICAgIH0KICAgIGdldCBpc0NVSUQyKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiY3VpZDIiKTsKICAgIH0KICAgIGdldCBpc1VMSUQoKSB7CiAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09ICJ1bGlkIik7CiAgICB9CiAgICBnZXQgaXNJUCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImlwIik7CiAgICB9CiAgICBnZXQgaXNCYXNlNjQoKSB7CiAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09ICJiYXNlNjQiKTsKICAgIH0KICAgIGdldCBtaW5MZW5ndGgoKSB7CiAgICAgIGxldCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChtaW4gPT09IG51bGwgfHwgY2gudmFsdWUgPiBtaW4pCiAgICAgICAgICAgIG1pbiA9IGNoLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbWluOwogICAgfQogICAgZ2V0IG1heExlbmd0aCgpIHsKICAgICAgbGV0IG1heCA9IG51bGw7CiAgICAgIGZvciAoY29uc3QgY2ggb2YgdGhpcy5fZGVmLmNoZWNrcykgewogICAgICAgIGlmIChjaC5raW5kID09PSAibWF4IikgewogICAgICAgICAgaWYgKG1heCA9PT0gbnVsbCB8fCBjaC52YWx1ZSA8IG1heCkKICAgICAgICAgICAgbWF4ID0gY2gudmFsdWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBtYXg7CiAgICB9CiAgfQogIFpvZFN0cmluZy5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICB2YXIgX2E7CiAgICByZXR1cm4gbmV3IFpvZFN0cmluZyh7CiAgICAgIGNoZWNrczogW10sCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kU3RyaW5nLAogICAgICBjb2VyY2U6IChfYSA9IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5jb2VyY2UpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IGZhbHNlLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgZnVuY3Rpb24gZmxvYXRTYWZlUmVtYWluZGVyKHZhbCwgc3RlcCkgewogICAgY29uc3QgdmFsRGVjQ291bnQgPSAodmFsLnRvU3RyaW5nKCkuc3BsaXQoIi4iKVsxXSB8fCAiIikubGVuZ3RoOwogICAgY29uc3Qgc3RlcERlY0NvdW50ID0gKHN0ZXAudG9TdHJpbmcoKS5zcGxpdCgiLiIpWzFdIHx8ICIiKS5sZW5ndGg7CiAgICBjb25zdCBkZWNDb3VudCA9IHZhbERlY0NvdW50ID4gc3RlcERlY0NvdW50ID8gdmFsRGVjQ291bnQgOiBzdGVwRGVjQ291bnQ7CiAgICBjb25zdCB2YWxJbnQgPSBwYXJzZUludCh2YWwudG9GaXhlZChkZWNDb3VudCkucmVwbGFjZSgiLiIsICIiKSk7CiAgICBjb25zdCBzdGVwSW50ID0gcGFyc2VJbnQoc3RlcC50b0ZpeGVkKGRlY0NvdW50KS5yZXBsYWNlKCIuIiwgIiIpKTsKICAgIHJldHVybiB2YWxJbnQgJSBzdGVwSW50IC8gTWF0aC5wb3coMTAsIGRlY0NvdW50KTsKICB9CiAgY2xhc3MgWm9kTnVtYmVyIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgdGhpcy5taW4gPSB0aGlzLmd0ZTsKICAgICAgdGhpcy5tYXggPSB0aGlzLmx0ZTsKICAgICAgdGhpcy5zdGVwID0gdGhpcy5tdWx0aXBsZU9mOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGlmICh0aGlzLl9kZWYuY29lcmNlKSB7CiAgICAgICAgaW5wdXQuZGF0YSA9IE51bWJlcihpbnB1dC5kYXRhKTsKICAgICAgfQogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm51bWJlcikgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm51bWJlciwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgyLnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBsZXQgY3R4ID0gdm9pZCAwOwogICAgICBjb25zdCBzdGF0dXMgPSBuZXcgUGFyc2VTdGF0dXMoKTsKICAgICAgZm9yIChjb25zdCBjaGVjayBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoZWNrLmtpbmQgPT09ICJpbnQiKSB7CiAgICAgICAgICBpZiAoIXV0aWwuaXNJbnRlZ2VyKGlucHV0LmRhdGEpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgICAgIGV4cGVjdGVkOiAiaW50ZWdlciIsCiAgICAgICAgICAgICAgcmVjZWl2ZWQ6ICJmbG9hdCIsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAibWluIikgewogICAgICAgICAgY29uc3QgdG9vU21hbGwgPSBjaGVjay5pbmNsdXNpdmUgPyBpbnB1dC5kYXRhIDwgY2hlY2sudmFsdWUgOiBpbnB1dC5kYXRhIDw9IGNoZWNrLnZhbHVlOwogICAgICAgICAgaWYgKHRvb1NtYWxsKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgICAgIG1pbmltdW06IGNoZWNrLnZhbHVlLAogICAgICAgICAgICAgIHR5cGU6ICJudW1iZXIiLAogICAgICAgICAgICAgIGluY2x1c2l2ZTogY2hlY2suaW5jbHVzaXZlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBjb25zdCB0b29CaWcgPSBjaGVjay5pbmNsdXNpdmUgPyBpbnB1dC5kYXRhID4gY2hlY2sudmFsdWUgOiBpbnB1dC5kYXRhID49IGNoZWNrLnZhbHVlOwogICAgICAgICAgaWYgKHRvb0JpZykgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsCiAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogIm51bWJlciIsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiBjaGVjay5pbmNsdXNpdmUsCiAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gIm11bHRpcGxlT2YiKSB7CiAgICAgICAgICBpZiAoZmxvYXRTYWZlUmVtYWluZGVyKGlucHV0LmRhdGEsIGNoZWNrLnZhbHVlKSAhPT0gMCkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLm5vdF9tdWx0aXBsZV9vZiwKICAgICAgICAgICAgICBtdWx0aXBsZU9mOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJmaW5pdGUiKSB7CiAgICAgICAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLm5vdF9maW5pdGUsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoY2hlY2spOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGlucHV0LmRhdGEgfTsKICAgIH0KICAgIGd0ZSh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIHRydWUsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBndCh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIGZhbHNlLCBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkpOwogICAgfQogICAgbHRlKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgdHJ1ZSwgZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpKTsKICAgIH0KICAgIGx0KHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgZmFsc2UsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBzZXRMaW1pdChraW5kLCB2YWx1ZSwgaW5jbHVzaXZlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kTnVtYmVyKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbCiAgICAgICAgICAuLi50aGlzLl9kZWYuY2hlY2tzLAogICAgICAgICAgewogICAgICAgICAgICBraW5kLAogICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgaW5jbHVzaXZlLAogICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgICAgIH0KICAgICAgICBdCiAgICAgIH0pOwogICAgfQogICAgX2FkZENoZWNrKGNoZWNrKSB7CiAgICAgIHJldHVybiBuZXcgWm9kTnVtYmVyKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgY2hlY2tdCiAgICAgIH0pOwogICAgfQogICAgaW50KG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAiaW50IiwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBwb3NpdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IDAsCiAgICAgICAgaW5jbHVzaXZlOiBmYWxzZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBuZWdhdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IDAsCiAgICAgICAgaW5jbHVzaXZlOiBmYWxzZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBub25wb3NpdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IDAsCiAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIG5vbm5lZ2F0aXZlKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAibWluIiwKICAgICAgICB2YWx1ZTogMCwKICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpCiAgICAgIH0pOwogICAgfQogICAgbXVsdGlwbGVPZih2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtdWx0aXBsZU9mIiwKICAgICAgICB2YWx1ZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBmaW5pdGUobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJmaW5pdGUiLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIHNhZmUobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtaW4iLAogICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICB2YWx1ZTogTnVtYmVyLk1JTl9TQUZFX0lOVEVHRVIsCiAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpCiAgICAgIH0pLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgIHZhbHVlOiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBnZXQgbWluVmFsdWUoKSB7CiAgICAgIGxldCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChtaW4gPT09IG51bGwgfHwgY2gudmFsdWUgPiBtaW4pCiAgICAgICAgICAgIG1pbiA9IGNoLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbWluOwogICAgfQogICAgZ2V0IG1heFZhbHVlKCkgewogICAgICBsZXQgbWF4ID0gbnVsbDsKICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNoLnZhbHVlIDwgbWF4KQogICAgICAgICAgICBtYXggPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG1heDsKICAgIH0KICAgIGdldCBpc0ludCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImludCIgfHwgY2gua2luZCA9PT0gIm11bHRpcGxlT2YiICYmIHV0aWwuaXNJbnRlZ2VyKGNoLnZhbHVlKSk7CiAgICB9CiAgICBnZXQgaXNGaW5pdGUoKSB7CiAgICAgIGxldCBtYXggPSBudWxsLCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gImZpbml0ZSIgfHwgY2gua2luZCA9PT0gImludCIgfHwgY2gua2luZCA9PT0gIm11bHRpcGxlT2YiKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9IGVsc2UgaWYgKGNoLmtpbmQgPT09ICJtaW4iKSB7CiAgICAgICAgICBpZiAobWluID09PSBudWxsIHx8IGNoLnZhbHVlID4gbWluKQogICAgICAgICAgICBtaW4gPSBjaC52YWx1ZTsKICAgICAgICB9IGVsc2UgaWYgKGNoLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNoLnZhbHVlIDwgbWF4KQogICAgICAgICAgICBtYXggPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShtaW4pICYmIE51bWJlci5pc0Zpbml0ZShtYXgpOwogICAgfQogIH0KICBab2ROdW1iZXIuY3JlYXRlID0gKHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2ROdW1iZXIoewogICAgICBjaGVja3M6IFtdLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE51bWJlciwKICAgICAgY29lcmNlOiAocGFyYW1zID09PSBudWxsIHx8IHBhcmFtcyA9PT0gdm9pZCAwID8gdm9pZCAwIDogcGFyYW1zLmNvZXJjZSkgfHwgZmFsc2UsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RCaWdJbnQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICB0aGlzLm1pbiA9IHRoaXMuZ3RlOwogICAgICB0aGlzLm1heCA9IHRoaXMubHRlOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGlmICh0aGlzLl9kZWYuY29lcmNlKSB7CiAgICAgICAgaW5wdXQuZGF0YSA9IEJpZ0ludChpbnB1dC5kYXRhKTsKICAgICAgfQogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLmJpZ2ludCkgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmJpZ2ludCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgyLnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBsZXQgY3R4ID0gdm9pZCAwOwogICAgICBjb25zdCBzdGF0dXMgPSBuZXcgUGFyc2VTdGF0dXMoKTsKICAgICAgZm9yIChjb25zdCBjaGVjayBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoZWNrLmtpbmQgPT09ICJtaW4iKSB7CiAgICAgICAgICBjb25zdCB0b29TbWFsbCA9IGNoZWNrLmluY2x1c2l2ZSA/IGlucHV0LmRhdGEgPCBjaGVjay52YWx1ZSA6IGlucHV0LmRhdGEgPD0gY2hlY2sudmFsdWU7CiAgICAgICAgICBpZiAodG9vU21hbGwpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgICAgdHlwZTogImJpZ2ludCIsCiAgICAgICAgICAgICAgbWluaW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiBjaGVjay5pbmNsdXNpdmUsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAibWF4IikgewogICAgICAgICAgY29uc3QgdG9vQmlnID0gY2hlY2suaW5jbHVzaXZlID8gaW5wdXQuZGF0YSA+IGNoZWNrLnZhbHVlIDogaW5wdXQuZGF0YSA+PSBjaGVjay52YWx1ZTsKICAgICAgICAgIGlmICh0b29CaWcpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fYmlnLAogICAgICAgICAgICAgIHR5cGU6ICJiaWdpbnQiLAogICAgICAgICAgICAgIG1heGltdW06IGNoZWNrLnZhbHVlLAogICAgICAgICAgICAgIGluY2x1c2l2ZTogY2hlY2suaW5jbHVzaXZlLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gIm11bHRpcGxlT2YiKSB7CiAgICAgICAgICBpZiAoaW5wdXQuZGF0YSAlIGNoZWNrLnZhbHVlICE9PSBCaWdJbnQoMCkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5ub3RfbXVsdGlwbGVfb2YsCiAgICAgICAgICAgICAgbXVsdGlwbGVPZjogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoY2hlY2spOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGlucHV0LmRhdGEgfTsKICAgIH0KICAgIGd0ZSh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIHRydWUsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBndCh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIGZhbHNlLCBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkpOwogICAgfQogICAgbHRlKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgdHJ1ZSwgZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpKTsKICAgIH0KICAgIGx0KHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgZmFsc2UsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBzZXRMaW1pdChraW5kLCB2YWx1ZSwgaW5jbHVzaXZlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQmlnSW50KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbCiAgICAgICAgICAuLi50aGlzLl9kZWYuY2hlY2tzLAogICAgICAgICAgewogICAgICAgICAgICBraW5kLAogICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgaW5jbHVzaXZlLAogICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgICAgIH0KICAgICAgICBdCiAgICAgIH0pOwogICAgfQogICAgX2FkZENoZWNrKGNoZWNrKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQmlnSW50KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgY2hlY2tdCiAgICAgIH0pOwogICAgfQogICAgcG9zaXRpdmUobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtaW4iLAogICAgICAgIHZhbHVlOiBCaWdJbnQoMCksCiAgICAgICAgaW5jbHVzaXZlOiBmYWxzZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBuZWdhdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IEJpZ0ludCgwKSwKICAgICAgICBpbmNsdXNpdmU6IGZhbHNlLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIG5vbnBvc2l0aXZlKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAibWF4IiwKICAgICAgICB2YWx1ZTogQmlnSW50KDApLAogICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBub25uZWdhdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IEJpZ0ludCgwKSwKICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpCiAgICAgIH0pOwogICAgfQogICAgbXVsdGlwbGVPZih2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtdWx0aXBsZU9mIiwKICAgICAgICB2YWx1ZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBnZXQgbWluVmFsdWUoKSB7CiAgICAgIGxldCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChtaW4gPT09IG51bGwgfHwgY2gudmFsdWUgPiBtaW4pCiAgICAgICAgICAgIG1pbiA9IGNoLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbWluOwogICAgfQogICAgZ2V0IG1heFZhbHVlKCkgewogICAgICBsZXQgbWF4ID0gbnVsbDsKICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNoLnZhbHVlIDwgbWF4KQogICAgICAgICAgICBtYXggPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG1heDsKICAgIH0KICB9CiAgWm9kQmlnSW50LmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHZhciBfYTsKICAgIHJldHVybiBuZXcgWm9kQmlnSW50KHsKICAgICAgY2hlY2tzOiBbXSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RCaWdJbnQsCiAgICAgIGNvZXJjZTogKF9hID0gcGFyYW1zID09PSBudWxsIHx8IHBhcmFtcyA9PT0gdm9pZCAwID8gdm9pZCAwIDogcGFyYW1zLmNvZXJjZSkgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogZmFsc2UsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RCb29sZWFuIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgaWYgKHRoaXMuX2RlZi5jb2VyY2UpIHsKICAgICAgICBpbnB1dC5kYXRhID0gQm9vbGVhbihpbnB1dC5kYXRhKTsKICAgICAgfQogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLmJvb2xlYW4pIHsKICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUuYm9vbGVhbiwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTsKICAgIH0KICB9CiAgWm9kQm9vbGVhbi5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZEJvb2xlYW4oewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEJvb2xlYW4sCiAgICAgIGNvZXJjZTogKHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5jb2VyY2UpIHx8IGZhbHNlLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kRGF0ZSBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGlmICh0aGlzLl9kZWYuY29lcmNlKSB7CiAgICAgICAgaW5wdXQuZGF0YSA9IG5ldyBEYXRlKGlucHV0LmRhdGEpOwogICAgICB9CiAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTsKICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuZGF0ZSkgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmRhdGUsCiAgICAgICAgICByZWNlaXZlZDogY3R4Mi5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgaWYgKGlzTmFOKGlucHV0LmRhdGEuZ2V0VGltZSgpKSkgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfZGF0ZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IHN0YXR1cyA9IG5ldyBQYXJzZVN0YXR1cygpOwogICAgICBsZXQgY3R4ID0gdm9pZCAwOwogICAgICBmb3IgKGNvbnN0IGNoZWNrIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2hlY2sua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChpbnB1dC5kYXRhLmdldFRpbWUoKSA8IGNoZWNrLnZhbHVlKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtaW5pbXVtOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICB0eXBlOiAiZGF0ZSIKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gIm1heCIpIHsKICAgICAgICAgIGlmIChpbnB1dC5kYXRhLmdldFRpbWUoKSA+IGNoZWNrLnZhbHVlKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX2JpZywKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLAogICAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgICAgICBleGFjdDogZmFsc2UsCiAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogImRhdGUiCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgdXRpbC5hc3NlcnROZXZlcihjaGVjayk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgc3RhdHVzOiBzdGF0dXMudmFsdWUsCiAgICAgICAgdmFsdWU6IG5ldyBEYXRlKGlucHV0LmRhdGEuZ2V0VGltZSgpKQogICAgICB9OwogICAgfQogICAgX2FkZENoZWNrKGNoZWNrKSB7CiAgICAgIHJldHVybiBuZXcgWm9kRGF0ZSh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIGNoZWNrczogWy4uLnRoaXMuX2RlZi5jaGVja3MsIGNoZWNrXQogICAgICB9KTsKICAgIH0KICAgIG1pbihtaW5EYXRlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IG1pbkRhdGUuZ2V0VGltZSgpLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIG1heChtYXhEYXRlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IG1heERhdGUuZ2V0VGltZSgpLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGdldCBtaW5EYXRlKCkgewogICAgICBsZXQgbWluID0gbnVsbDsKICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoLmtpbmQgPT09ICJtaW4iKSB7CiAgICAgICAgICBpZiAobWluID09PSBudWxsIHx8IGNoLnZhbHVlID4gbWluKQogICAgICAgICAgICBtaW4gPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG1pbiAhPSBudWxsID8gbmV3IERhdGUobWluKSA6IG51bGw7CiAgICB9CiAgICBnZXQgbWF4RGF0ZSgpIHsKICAgICAgbGV0IG1heCA9IG51bGw7CiAgICAgIGZvciAoY29uc3QgY2ggb2YgdGhpcy5fZGVmLmNoZWNrcykgewogICAgICAgIGlmIChjaC5raW5kID09PSAibWF4IikgewogICAgICAgICAgaWYgKG1heCA9PT0gbnVsbCB8fCBjaC52YWx1ZSA8IG1heCkKICAgICAgICAgICAgbWF4ID0gY2gudmFsdWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBtYXggIT0gbnVsbCA/IG5ldyBEYXRlKG1heCkgOiBudWxsOwogICAgfQogIH0KICBab2REYXRlLmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kRGF0ZSh7CiAgICAgIGNoZWNrczogW10sCiAgICAgIGNvZXJjZTogKHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5jb2VyY2UpIHx8IGZhbHNlLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZERhdGUsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RTeW1ib2wgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLnN5bWJvbCkgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5zeW1ib2wsCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7CiAgICB9CiAgfQogIFpvZFN5bWJvbC5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZFN5bWJvbCh7CiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kU3ltYm9sLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kVW5kZWZpbmVkIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS51bmRlZmluZWQpIHsKICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgcmV0dXJuIE9LKGlucHV0LmRhdGEpOwogICAgfQogIH0KICBab2RVbmRlZmluZWQuY3JlYXRlID0gKHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RVbmRlZmluZWQoewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZFVuZGVmaW5lZCwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE51bGwgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm51bGwpIHsKICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUubnVsbCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTsKICAgIH0KICB9CiAgWm9kTnVsbC5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE51bGwoewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE51bGwsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RBbnkgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICB0aGlzLl9hbnkgPSB0cnVlOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTsKICAgIH0KICB9CiAgWm9kQW55LmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kQW55KHsKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RBbnksCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RVbmtub3duIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgdGhpcy5fdW5rbm93biA9IHRydWU7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgcmV0dXJuIE9LKGlucHV0LmRhdGEpOwogICAgfQogIH0KICBab2RVbmtub3duLmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kVW5rbm93bih7CiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kVW5rbm93biwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE5ldmVyIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm5ldmVyLAogICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICB9KTsKICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICB9CiAgfQogIFpvZE5ldmVyLmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kTmV2ZXIoewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE5ldmVyLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kVm9pZCBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTsKICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkKSB7CiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLnZvaWQsCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7CiAgICB9CiAgfQogIFpvZFZvaWQuY3JlYXRlID0gKHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RWb2lkKHsKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RWb2lkLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kQXJyYXkgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCwgc3RhdHVzIH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBkZWYgPSB0aGlzLl9kZWY7CiAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5hcnJheSkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmFycmF5LAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgaWYgKGRlZi5leGFjdExlbmd0aCAhPT0gbnVsbCkgewogICAgICAgIGNvbnN0IHRvb0JpZyA9IGN0eC5kYXRhLmxlbmd0aCA+IGRlZi5leGFjdExlbmd0aC52YWx1ZTsKICAgICAgICBjb25zdCB0b29TbWFsbCA9IGN0eC5kYXRhLmxlbmd0aCA8IGRlZi5leGFjdExlbmd0aC52YWx1ZTsKICAgICAgICBpZiAodG9vQmlnIHx8IHRvb1NtYWxsKSB7CiAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgY29kZTogdG9vQmlnID8gWm9kSXNzdWVDb2RlLnRvb19iaWcgOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgICBtaW5pbXVtOiB0b29TbWFsbCA/IGRlZi5leGFjdExlbmd0aC52YWx1ZSA6IHZvaWQgMCwKICAgICAgICAgICAgbWF4aW11bTogdG9vQmlnID8gZGVmLmV4YWN0TGVuZ3RoLnZhbHVlIDogdm9pZCAwLAogICAgICAgICAgICB0eXBlOiAiYXJyYXkiLAogICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgICAgIGV4YWN0OiB0cnVlLAogICAgICAgICAgICBtZXNzYWdlOiBkZWYuZXhhY3RMZW5ndGgubWVzc2FnZQogICAgICAgICAgfSk7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGRlZi5taW5MZW5ndGggIT09IG51bGwpIHsKICAgICAgICBpZiAoY3R4LmRhdGEubGVuZ3RoIDwgZGVmLm1pbkxlbmd0aC52YWx1ZSkgewogICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgIG1pbmltdW06IGRlZi5taW5MZW5ndGgudmFsdWUsCiAgICAgICAgICAgIHR5cGU6ICJhcnJheSIsCiAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLAogICAgICAgICAgICBtZXNzYWdlOiBkZWYubWluTGVuZ3RoLm1lc3NhZ2UKICAgICAgICAgIH0pOwogICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChkZWYubWF4TGVuZ3RoICE9PSBudWxsKSB7CiAgICAgICAgaWYgKGN0eC5kYXRhLmxlbmd0aCA+IGRlZi5tYXhMZW5ndGgudmFsdWUpIHsKICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX2JpZywKICAgICAgICAgICAgbWF4aW11bTogZGVmLm1heExlbmd0aC52YWx1ZSwKICAgICAgICAgICAgdHlwZTogImFycmF5IiwKICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICBleGFjdDogZmFsc2UsCiAgICAgICAgICAgIG1lc3NhZ2U6IGRlZi5tYXhMZW5ndGgubWVzc2FnZQogICAgICAgICAgfSk7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoWy4uLmN0eC5kYXRhXS5tYXAoKGl0ZW0sIGkyKSA9PiB7CiAgICAgICAgICByZXR1cm4gZGVmLnR5cGUuX3BhcnNlQXN5bmMobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGl0ZW0sIGN0eC5wYXRoLCBpMikpOwogICAgICAgIH0pKS50aGVuKChyZXN1bHQyKSA9PiB7CiAgICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VBcnJheShzdGF0dXMsIHJlc3VsdDIpOwogICAgICAgIH0pOwogICAgICB9CiAgICAgIGNvbnN0IHJlc3VsdCA9IFsuLi5jdHguZGF0YV0ubWFwKChpdGVtLCBpMikgPT4gewogICAgICAgIHJldHVybiBkZWYudHlwZS5fcGFyc2VTeW5jKG5ldyBQYXJzZUlucHV0TGF6eVBhdGgoY3R4LCBpdGVtLCBjdHgucGF0aCwgaTIpKTsKICAgICAgfSk7CiAgICAgIHJldHVybiBQYXJzZVN0YXR1cy5tZXJnZUFycmF5KHN0YXR1cywgcmVzdWx0KTsKICAgIH0KICAgIGdldCBlbGVtZW50KCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnR5cGU7CiAgICB9CiAgICBtaW4obWluTGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBtaW5MZW5ndGg6IHsgdmFsdWU6IG1pbkxlbmd0aCwgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpIH0KICAgICAgfSk7CiAgICB9CiAgICBtYXgobWF4TGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBtYXhMZW5ndGg6IHsgdmFsdWU6IG1heExlbmd0aCwgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpIH0KICAgICAgfSk7CiAgICB9CiAgICBsZW5ndGgobGVuLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBleGFjdExlbmd0aDogeyB2YWx1ZTogbGVuLCBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkgfQogICAgICB9KTsKICAgIH0KICAgIG5vbmVtcHR5KG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMubWluKDEsIG1lc3NhZ2UpOwogICAgfQogIH0KICBab2RBcnJheS5jcmVhdGUgPSAoc2NoZW1hLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICB0eXBlOiBzY2hlbWEsCiAgICAgIG1pbkxlbmd0aDogbnVsbCwKICAgICAgbWF4TGVuZ3RoOiBudWxsLAogICAgICBleGFjdExlbmd0aDogbnVsbCwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RBcnJheSwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGZ1bmN0aW9uIGRlZXBQYXJ0aWFsaWZ5KHNjaGVtYSkgewogICAgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZE9iamVjdCkgewogICAgICBjb25zdCBuZXdTaGFwZSA9IHt9OwogICAgICBmb3IgKGNvbnN0IGtleSBpbiBzY2hlbWEuc2hhcGUpIHsKICAgICAgICBjb25zdCBmaWVsZFNjaGVtYSA9IHNjaGVtYS5zaGFwZVtrZXldOwogICAgICAgIG5ld1NoYXBlW2tleV0gPSBab2RPcHRpb25hbC5jcmVhdGUoZGVlcFBhcnRpYWxpZnkoZmllbGRTY2hlbWEpKTsKICAgICAgfQogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4uc2NoZW1hLl9kZWYsCiAgICAgICAgc2hhcGU6ICgpID0+IG5ld1NoYXBlCiAgICAgIH0pOwogICAgfSBlbHNlIGlmIChzY2hlbWEgaW5zdGFuY2VvZiBab2RBcnJheSkgewogICAgICByZXR1cm4gbmV3IFpvZEFycmF5KHsKICAgICAgICAuLi5zY2hlbWEuX2RlZiwKICAgICAgICB0eXBlOiBkZWVwUGFydGlhbGlmeShzY2hlbWEuZWxlbWVudCkKICAgICAgfSk7CiAgICB9IGVsc2UgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZE9wdGlvbmFsKSB7CiAgICAgIHJldHVybiBab2RPcHRpb25hbC5jcmVhdGUoZGVlcFBhcnRpYWxpZnkoc2NoZW1hLnVud3JhcCgpKSk7CiAgICB9IGVsc2UgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZE51bGxhYmxlKSB7CiAgICAgIHJldHVybiBab2ROdWxsYWJsZS5jcmVhdGUoZGVlcFBhcnRpYWxpZnkoc2NoZW1hLnVud3JhcCgpKSk7CiAgICB9IGVsc2UgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZFR1cGxlKSB7CiAgICAgIHJldHVybiBab2RUdXBsZS5jcmVhdGUoc2NoZW1hLml0ZW1zLm1hcCgoaXRlbSkgPT4gZGVlcFBhcnRpYWxpZnkoaXRlbSkpKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBzY2hlbWE7CiAgICB9CiAgfQogIGNsYXNzIFpvZE9iamVjdCBleHRlbmRzIFpvZFR5cGUgewogICAgY29uc3RydWN0b3IoKSB7CiAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7CiAgICAgIHRoaXMuX2NhY2hlZCA9IG51bGw7CiAgICAgIHRoaXMubm9uc3RyaWN0ID0gdGhpcy5wYXNzdGhyb3VnaDsKICAgICAgdGhpcy5hdWdtZW50ID0gdGhpcy5leHRlbmQ7CiAgICB9CiAgICBfZ2V0Q2FjaGVkKCkgewogICAgICBpZiAodGhpcy5fY2FjaGVkICE9PSBudWxsKQogICAgICAgIHJldHVybiB0aGlzLl9jYWNoZWQ7CiAgICAgIGNvbnN0IHNoYXBlID0gdGhpcy5fZGVmLnNoYXBlKCk7CiAgICAgIGNvbnN0IGtleXMgPSB1dGlsLm9iamVjdEtleXMoc2hhcGUpOwogICAgICByZXR1cm4gdGhpcy5fY2FjaGVkID0geyBzaGFwZSwga2V5cyB9OwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTsKICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUub2JqZWN0KSB7CiAgICAgICAgY29uc3QgY3R4MiA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgyLCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUub2JqZWN0LAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eDIucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IHsgc3RhdHVzLCBjdHggfSA9IHRoaXMuX3Byb2Nlc3NJbnB1dFBhcmFtcyhpbnB1dCk7CiAgICAgIGNvbnN0IHsgc2hhcGUsIGtleXM6IHNoYXBlS2V5cyB9ID0gdGhpcy5fZ2V0Q2FjaGVkKCk7CiAgICAgIGNvbnN0IGV4dHJhS2V5cyA9IFtdOwogICAgICBpZiAoISh0aGlzLl9kZWYuY2F0Y2hhbGwgaW5zdGFuY2VvZiBab2ROZXZlciAmJiB0aGlzLl9kZWYudW5rbm93bktleXMgPT09ICJzdHJpcCIpKSB7CiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gY3R4LmRhdGEpIHsKICAgICAgICAgIGlmICghc2hhcGVLZXlzLmluY2x1ZGVzKGtleSkpIHsKICAgICAgICAgICAgZXh0cmFLZXlzLnB1c2goa2V5KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgcGFpcnMgPSBbXTsKICAgICAgZm9yIChjb25zdCBrZXkgb2Ygc2hhcGVLZXlzKSB7CiAgICAgICAgY29uc3Qga2V5VmFsaWRhdG9yID0gc2hhcGVba2V5XTsKICAgICAgICBjb25zdCB2YWx1ZSA9IGN0eC5kYXRhW2tleV07CiAgICAgICAgcGFpcnMucHVzaCh7CiAgICAgICAgICBrZXk6IHsgc3RhdHVzOiAidmFsaWQiLCB2YWx1ZToga2V5IH0sCiAgICAgICAgICB2YWx1ZToga2V5VmFsaWRhdG9yLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwgdmFsdWUsIGN0eC5wYXRoLCBrZXkpKSwKICAgICAgICAgIGFsd2F5c1NldDoga2V5IGluIGN0eC5kYXRhCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuX2RlZi5jYXRjaGFsbCBpbnN0YW5jZW9mIFpvZE5ldmVyKSB7CiAgICAgICAgY29uc3QgdW5rbm93bktleXMgPSB0aGlzLl9kZWYudW5rbm93bktleXM7CiAgICAgICAgaWYgKHVua25vd25LZXlzID09PSAicGFzc3Rocm91Z2giKSB7CiAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBleHRyYUtleXMpIHsKICAgICAgICAgICAgcGFpcnMucHVzaCh7CiAgICAgICAgICAgICAga2V5OiB7IHN0YXR1czogInZhbGlkIiwgdmFsdWU6IGtleSB9LAogICAgICAgICAgICAgIHZhbHVlOiB7IHN0YXR1czogInZhbGlkIiwgdmFsdWU6IGN0eC5kYXRhW2tleV0gfQogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKHVua25vd25LZXlzID09PSAic3RyaWN0IikgewogICAgICAgICAgaWYgKGV4dHJhS2V5cy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS51bnJlY29nbml6ZWRfa2V5cywKICAgICAgICAgICAgICBrZXlzOiBleHRyYUtleXMKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAodW5rbm93bktleXMgPT09ICJzdHJpcCIpIDsKICAgICAgICBlbHNlIHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW50ZXJuYWwgWm9kT2JqZWN0IGVycm9yOiBpbnZhbGlkIHVua25vd25LZXlzIHZhbHVlLmApOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBjYXRjaGFsbCA9IHRoaXMuX2RlZi5jYXRjaGFsbDsKICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBleHRyYUtleXMpIHsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gY3R4LmRhdGFba2V5XTsKICAgICAgICAgIHBhaXJzLnB1c2goewogICAgICAgICAgICBrZXk6IHsgc3RhdHVzOiAidmFsaWQiLCB2YWx1ZToga2V5IH0sCiAgICAgICAgICAgIHZhbHVlOiBjYXRjaGFsbC5fcGFyc2UoCiAgICAgICAgICAgICAgbmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIHZhbHVlLCBjdHgucGF0aCwga2V5KQogICAgICAgICAgICAgIC8vLCBjdHguY2hpbGQoa2V5KSwgdmFsdWUsIGdldFBhcnNlZFR5cGUodmFsdWUpCiAgICAgICAgICAgICksCiAgICAgICAgICAgIGFsd2F5c1NldDoga2V5IGluIGN0eC5kYXRhCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihhc3luYyAoKSA9PiB7CiAgICAgICAgICBjb25zdCBzeW5jUGFpcnMgPSBbXTsKICAgICAgICAgIGZvciAoY29uc3QgcGFpciBvZiBwYWlycykgewogICAgICAgICAgICBjb25zdCBrZXkgPSBhd2FpdCBwYWlyLmtleTsKICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCBwYWlyLnZhbHVlOwogICAgICAgICAgICBzeW5jUGFpcnMucHVzaCh7CiAgICAgICAgICAgICAga2V5LAogICAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICAgIGFsd2F5c1NldDogcGFpci5hbHdheXNTZXQKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gc3luY1BhaXJzOwogICAgICAgIH0pLnRoZW4oKHN5bmNQYWlycykgPT4gewogICAgICAgICAgcmV0dXJuIFBhcnNlU3RhdHVzLm1lcmdlT2JqZWN0U3luYyhzdGF0dXMsIHN5bmNQYWlycyk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIFBhcnNlU3RhdHVzLm1lcmdlT2JqZWN0U3luYyhzdGF0dXMsIHBhaXJzKTsKICAgICAgfQogICAgfQogICAgZ2V0IHNoYXBlKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnNoYXBlKCk7CiAgICB9CiAgICBzdHJpY3QobWVzc2FnZSkgewogICAgICBlcnJvclV0aWwuZXJyVG9PYmo7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgdW5rbm93bktleXM6ICJzdHJpY3QiLAogICAgICAgIC4uLm1lc3NhZ2UgIT09IHZvaWQgMCA/IHsKICAgICAgICAgIGVycm9yTWFwOiAoaXNzdWUsIGN0eCkgPT4gewogICAgICAgICAgICB2YXIgX2EsIF9iLCBfYywgX2Q7CiAgICAgICAgICAgIGNvbnN0IGRlZmF1bHRFcnJvciA9IChfYyA9IChfYiA9IChfYSA9IHRoaXMuX2RlZikuZXJyb3JNYXApID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5jYWxsKF9hLCBpc3N1ZSwgY3R4KS5tZXNzYWdlKSAhPT0gbnVsbCAmJiBfYyAhPT0gdm9pZCAwID8gX2MgOiBjdHguZGVmYXVsdEVycm9yOwogICAgICAgICAgICBpZiAoaXNzdWUuY29kZSA9PT0gInVucmVjb2duaXplZF9rZXlzIikKICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgbWVzc2FnZTogKF9kID0gZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpLm1lc3NhZ2UpICE9PSBudWxsICYmIF9kICE9PSB2b2lkIDAgPyBfZCA6IGRlZmF1bHRFcnJvcgogICAgICAgICAgICAgIH07CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgbWVzc2FnZTogZGVmYXVsdEVycm9yCiAgICAgICAgICAgIH07CiAgICAgICAgICB9CiAgICAgICAgfSA6IHt9CiAgICAgIH0pOwogICAgfQogICAgc3RyaXAoKSB7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgdW5rbm93bktleXM6ICJzdHJpcCIKICAgICAgfSk7CiAgICB9CiAgICBwYXNzdGhyb3VnaCgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICB1bmtub3duS2V5czogInBhc3N0aHJvdWdoIgogICAgICB9KTsKICAgIH0KICAgIC8vIGNvbnN0IEF1Z21lbnRGYWN0b3J5ID0KICAgIC8vICAgPERlZiBleHRlbmRzIFpvZE9iamVjdERlZj4oZGVmOiBEZWYpID0+CiAgICAvLyAgIDxBdWdtZW50YXRpb24gZXh0ZW5kcyBab2RSYXdTaGFwZT4oCiAgICAvLyAgICAgYXVnbWVudGF0aW9uOiBBdWdtZW50YXRpb24KICAgIC8vICAgKTogWm9kT2JqZWN0PAogICAgLy8gICAgIGV4dGVuZFNoYXBlPFJldHVyblR5cGU8RGVmWyJzaGFwZSJdPiwgQXVnbWVudGF0aW9uPiwKICAgIC8vICAgICBEZWZbInVua25vd25LZXlzIl0sCiAgICAvLyAgICAgRGVmWyJjYXRjaGFsbCJdCiAgICAvLyAgID4gPT4gewogICAgLy8gICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgIC8vICAgICAgIC4uLmRlZiwKICAgIC8vICAgICAgIHNoYXBlOiAoKSA9PiAoewogICAgLy8gICAgICAgICAuLi5kZWYuc2hhcGUoKSwKICAgIC8vICAgICAgICAgLi4uYXVnbWVudGF0aW9uLAogICAgLy8gICAgICAgfSksCiAgICAvLyAgICAgfSkgYXMgYW55OwogICAgLy8gICB9OwogICAgZXh0ZW5kKGF1Z21lbnRhdGlvbikgewogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHNoYXBlOiAoKSA9PiAoewogICAgICAgICAgLi4udGhpcy5fZGVmLnNoYXBlKCksCiAgICAgICAgICAuLi5hdWdtZW50YXRpb24KICAgICAgICB9KQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICogUHJpb3IgdG8gem9kQDEuMC4xMiB0aGVyZSB3YXMgYSBidWcgaW4gdGhlCiAgICAgKiBpbmZlcnJlZCB0eXBlIG9mIG1lcmdlZCBvYmplY3RzLiBQbGVhc2UKICAgICAqIHVwZ3JhZGUgaWYgeW91IGFyZSBleHBlcmllbmNpbmcgaXNzdWVzLgogICAgICovCiAgICBtZXJnZShtZXJnaW5nKSB7CiAgICAgIGNvbnN0IG1lcmdlZCA9IG5ldyBab2RPYmplY3QoewogICAgICAgIHVua25vd25LZXlzOiBtZXJnaW5nLl9kZWYudW5rbm93bktleXMsCiAgICAgICAgY2F0Y2hhbGw6IG1lcmdpbmcuX2RlZi5jYXRjaGFsbCwKICAgICAgICBzaGFwZTogKCkgPT4gKHsKICAgICAgICAgIC4uLnRoaXMuX2RlZi5zaGFwZSgpLAogICAgICAgICAgLi4ubWVyZ2luZy5fZGVmLnNoYXBlKCkKICAgICAgICB9KSwKICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE9iamVjdAogICAgICB9KTsKICAgICAgcmV0dXJuIG1lcmdlZDsKICAgIH0KICAgIC8vIG1lcmdlPAogICAgLy8gICBJbmNvbWluZyBleHRlbmRzIEFueVpvZE9iamVjdCwKICAgIC8vICAgQXVnbWVudGF0aW9uIGV4dGVuZHMgSW5jb21pbmdbInNoYXBlIl0sCiAgICAvLyAgIE5ld091dHB1dCBleHRlbmRzIHsKICAgIC8vICAgICBbayBpbiBrZXlvZiBBdWdtZW50YXRpb24gfCBrZXlvZiBPdXRwdXRdOiBrIGV4dGVuZHMga2V5b2YgQXVnbWVudGF0aW9uCiAgICAvLyAgICAgICA/IEF1Z21lbnRhdGlvbltrXVsiX291dHB1dCJdCiAgICAvLyAgICAgICA6IGsgZXh0ZW5kcyBrZXlvZiBPdXRwdXQKICAgIC8vICAgICAgID8gT3V0cHV0W2tdCiAgICAvLyAgICAgICA6IG5ldmVyOwogICAgLy8gICB9LAogICAgLy8gICBOZXdJbnB1dCBleHRlbmRzIHsKICAgIC8vICAgICBbayBpbiBrZXlvZiBBdWdtZW50YXRpb24gfCBrZXlvZiBJbnB1dF06IGsgZXh0ZW5kcyBrZXlvZiBBdWdtZW50YXRpb24KICAgIC8vICAgICAgID8gQXVnbWVudGF0aW9uW2tdWyJfaW5wdXQiXQogICAgLy8gICAgICAgOiBrIGV4dGVuZHMga2V5b2YgSW5wdXQKICAgIC8vICAgICAgID8gSW5wdXRba10KICAgIC8vICAgICAgIDogbmV2ZXI7CiAgICAvLyAgIH0KICAgIC8vID4oCiAgICAvLyAgIG1lcmdpbmc6IEluY29taW5nCiAgICAvLyApOiBab2RPYmplY3Q8CiAgICAvLyAgIGV4dGVuZFNoYXBlPFQsIFJldHVyblR5cGU8SW5jb21pbmdbIl9kZWYiXVsic2hhcGUiXT4+LAogICAgLy8gICBJbmNvbWluZ1siX2RlZiJdWyJ1bmtub3duS2V5cyJdLAogICAgLy8gICBJbmNvbWluZ1siX2RlZiJdWyJjYXRjaGFsbCJdLAogICAgLy8gICBOZXdPdXRwdXQsCiAgICAvLyAgIE5ld0lucHV0CiAgICAvLyA+IHsKICAgIC8vICAgY29uc3QgbWVyZ2VkOiBhbnkgPSBuZXcgWm9kT2JqZWN0KHsKICAgIC8vICAgICB1bmtub3duS2V5czogbWVyZ2luZy5fZGVmLnVua25vd25LZXlzLAogICAgLy8gICAgIGNhdGNoYWxsOiBtZXJnaW5nLl9kZWYuY2F0Y2hhbGwsCiAgICAvLyAgICAgc2hhcGU6ICgpID0+CiAgICAvLyAgICAgICBvYmplY3RVdGlsLm1lcmdlU2hhcGVzKHRoaXMuX2RlZi5zaGFwZSgpLCBtZXJnaW5nLl9kZWYuc2hhcGUoKSksCiAgICAvLyAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPYmplY3QsCiAgICAvLyAgIH0pIGFzIGFueTsKICAgIC8vICAgcmV0dXJuIG1lcmdlZDsKICAgIC8vIH0KICAgIHNldEtleShrZXksIHNjaGVtYSkgewogICAgICByZXR1cm4gdGhpcy5hdWdtZW50KHsgW2tleV06IHNjaGVtYSB9KTsKICAgIH0KICAgIC8vIG1lcmdlPEluY29taW5nIGV4dGVuZHMgQW55Wm9kT2JqZWN0PigKICAgIC8vICAgbWVyZ2luZzogSW5jb21pbmcKICAgIC8vICk6IC8vWm9kT2JqZWN0PFQgJiBJbmNvbWluZ1siX3NoYXBlIl0sIFVua25vd25LZXlzLCBDYXRjaGFsbD4gPSAobWVyZ2luZykgPT4gewogICAgLy8gWm9kT2JqZWN0PAogICAgLy8gICBleHRlbmRTaGFwZTxULCBSZXR1cm5UeXBlPEluY29taW5nWyJfZGVmIl1bInNoYXBlIl0+PiwKICAgIC8vICAgSW5jb21pbmdbIl9kZWYiXVsidW5rbm93bktleXMiXSwKICAgIC8vICAgSW5jb21pbmdbIl9kZWYiXVsiY2F0Y2hhbGwiXQogICAgLy8gPiB7CiAgICAvLyAgIC8vIGNvbnN0IG1lcmdlZFNoYXBlID0gb2JqZWN0VXRpbC5tZXJnZVNoYXBlcygKICAgIC8vICAgLy8gICB0aGlzLl9kZWYuc2hhcGUoKSwKICAgIC8vICAgLy8gICBtZXJnaW5nLl9kZWYuc2hhcGUoKQogICAgLy8gICAvLyApOwogICAgLy8gICBjb25zdCBtZXJnZWQ6IGFueSA9IG5ldyBab2RPYmplY3QoewogICAgLy8gICAgIHVua25vd25LZXlzOiBtZXJnaW5nLl9kZWYudW5rbm93bktleXMsCiAgICAvLyAgICAgY2F0Y2hhbGw6IG1lcmdpbmcuX2RlZi5jYXRjaGFsbCwKICAgIC8vICAgICBzaGFwZTogKCkgPT4KICAgIC8vICAgICAgIG9iamVjdFV0aWwubWVyZ2VTaGFwZXModGhpcy5fZGVmLnNoYXBlKCksIG1lcmdpbmcuX2RlZi5zaGFwZSgpKSwKICAgIC8vICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE9iamVjdCwKICAgIC8vICAgfSkgYXMgYW55OwogICAgLy8gICByZXR1cm4gbWVyZ2VkOwogICAgLy8gfQogICAgY2F0Y2hhbGwoaW5kZXgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBjYXRjaGFsbDogaW5kZXgKICAgICAgfSk7CiAgICB9CiAgICBwaWNrKG1hc2spIHsKICAgICAgY29uc3Qgc2hhcGUgPSB7fTsKICAgICAgdXRpbC5vYmplY3RLZXlzKG1hc2spLmZvckVhY2goKGtleSkgPT4gewogICAgICAgIGlmIChtYXNrW2tleV0gJiYgdGhpcy5zaGFwZVtrZXldKSB7CiAgICAgICAgICBzaGFwZVtrZXldID0gdGhpcy5zaGFwZVtrZXldOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgc2hhcGU6ICgpID0+IHNoYXBlCiAgICAgIH0pOwogICAgfQogICAgb21pdChtYXNrKSB7CiAgICAgIGNvbnN0IHNoYXBlID0ge307CiAgICAgIHV0aWwub2JqZWN0S2V5cyh0aGlzLnNoYXBlKS5mb3JFYWNoKChrZXkpID0+IHsKICAgICAgICBpZiAoIW1hc2tba2V5XSkgewogICAgICAgICAgc2hhcGVba2V5XSA9IHRoaXMuc2hhcGVba2V5XTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHNoYXBlOiAoKSA9PiBzaGFwZQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICogQGRlcHJlY2F0ZWQKICAgICAqLwogICAgZGVlcFBhcnRpYWwoKSB7CiAgICAgIHJldHVybiBkZWVwUGFydGlhbGlmeSh0aGlzKTsKICAgIH0KICAgIHBhcnRpYWwobWFzaykgewogICAgICBjb25zdCBuZXdTaGFwZSA9IHt9OwogICAgICB1dGlsLm9iamVjdEtleXModGhpcy5zaGFwZSkuZm9yRWFjaCgoa2V5KSA9PiB7CiAgICAgICAgY29uc3QgZmllbGRTY2hlbWEgPSB0aGlzLnNoYXBlW2tleV07CiAgICAgICAgaWYgKG1hc2sgJiYgIW1hc2tba2V5XSkgewogICAgICAgICAgbmV3U2hhcGVba2V5XSA9IGZpZWxkU2NoZW1hOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBuZXdTaGFwZVtrZXldID0gZmllbGRTY2hlbWEub3B0aW9uYWwoKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHNoYXBlOiAoKSA9PiBuZXdTaGFwZQogICAgICB9KTsKICAgIH0KICAgIHJlcXVpcmVkKG1hc2spIHsKICAgICAgY29uc3QgbmV3U2hhcGUgPSB7fTsKICAgICAgdXRpbC5vYmplY3RLZXlzKHRoaXMuc2hhcGUpLmZvckVhY2goKGtleSkgPT4gewogICAgICAgIGlmIChtYXNrICYmICFtYXNrW2tleV0pIHsKICAgICAgICAgIG5ld1NoYXBlW2tleV0gPSB0aGlzLnNoYXBlW2tleV07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvbnN0IGZpZWxkU2NoZW1hID0gdGhpcy5zaGFwZVtrZXldOwogICAgICAgICAgbGV0IG5ld0ZpZWxkID0gZmllbGRTY2hlbWE7CiAgICAgICAgICB3aGlsZSAobmV3RmllbGQgaW5zdGFuY2VvZiBab2RPcHRpb25hbCkgewogICAgICAgICAgICBuZXdGaWVsZCA9IG5ld0ZpZWxkLl9kZWYuaW5uZXJUeXBlOwogICAgICAgICAgfQogICAgICAgICAgbmV3U2hhcGVba2V5XSA9IG5ld0ZpZWxkOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgc2hhcGU6ICgpID0+IG5ld1NoYXBlCiAgICAgIH0pOwogICAgfQogICAga2V5b2YoKSB7CiAgICAgIHJldHVybiBjcmVhdGVab2RFbnVtKHV0aWwub2JqZWN0S2V5cyh0aGlzLnNoYXBlKSk7CiAgICB9CiAgfQogIFpvZE9iamVjdC5jcmVhdGUgPSAoc2hhcGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICBzaGFwZTogKCkgPT4gc2hhcGUsCiAgICAgIHVua25vd25LZXlzOiAic3RyaXAiLAogICAgICBjYXRjaGFsbDogWm9kTmV2ZXIuY3JlYXRlKCksCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kT2JqZWN0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgWm9kT2JqZWN0LnN0cmljdENyZWF0ZSA9IChzaGFwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgIHNoYXBlOiAoKSA9PiBzaGFwZSwKICAgICAgdW5rbm93bktleXM6ICJzdHJpY3QiLAogICAgICBjYXRjaGFsbDogWm9kTmV2ZXIuY3JlYXRlKCksCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kT2JqZWN0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgWm9kT2JqZWN0LmxhenljcmVhdGUgPSAoc2hhcGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICBzaGFwZSwKICAgICAgdW5rbm93bktleXM6ICJzdHJpcCIsCiAgICAgIGNhdGNoYWxsOiBab2ROZXZlci5jcmVhdGUoKSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPYmplY3QsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RVbmlvbiBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5fZGVmLm9wdGlvbnM7CiAgICAgIGZ1bmN0aW9uIGhhbmRsZVJlc3VsdHMocmVzdWx0cykgewogICAgICAgIGZvciAoY29uc3QgcmVzdWx0IG9mIHJlc3VsdHMpIHsKICAgICAgICAgIGlmIChyZXN1bHQucmVzdWx0LnN0YXR1cyA9PT0gInZhbGlkIikgewogICAgICAgICAgICByZXR1cm4gcmVzdWx0LnJlc3VsdDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZm9yIChjb25zdCByZXN1bHQgb2YgcmVzdWx0cykgewogICAgICAgICAgaWYgKHJlc3VsdC5yZXN1bHQuc3RhdHVzID09PSAiZGlydHkiKSB7CiAgICAgICAgICAgIGN0eC5jb21tb24uaXNzdWVzLnB1c2goLi4ucmVzdWx0LmN0eC5jb21tb24uaXNzdWVzKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5yZXN1bHQ7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IHVuaW9uRXJyb3JzID0gcmVzdWx0cy5tYXAoKHJlc3VsdCkgPT4gbmV3IFpvZEVycm9yKHJlc3VsdC5jdHguY29tbW9uLmlzc3VlcykpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdW5pb24sCiAgICAgICAgICB1bmlvbkVycm9ycwogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKG9wdGlvbnMubWFwKGFzeW5jIChvcHRpb24pID0+IHsKICAgICAgICAgIGNvbnN0IGNoaWxkQ3R4ID0gewogICAgICAgICAgICAuLi5jdHgsCiAgICAgICAgICAgIGNvbW1vbjogewogICAgICAgICAgICAgIC4uLmN0eC5jb21tb24sCiAgICAgICAgICAgICAgaXNzdWVzOiBbXQogICAgICAgICAgICB9LAogICAgICAgICAgICBwYXJlbnQ6IG51bGwKICAgICAgICAgIH07CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICByZXN1bHQ6IGF3YWl0IG9wdGlvbi5fcGFyc2VBc3luYyh7CiAgICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgICAgICAgcGFyZW50OiBjaGlsZEN0eAogICAgICAgICAgICB9KSwKICAgICAgICAgICAgY3R4OiBjaGlsZEN0eAogICAgICAgICAgfTsKICAgICAgICB9KSkudGhlbihoYW5kbGVSZXN1bHRzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBsZXQgZGlydHkgPSB2b2lkIDA7CiAgICAgICAgY29uc3QgaXNzdWVzID0gW107CiAgICAgICAgZm9yIChjb25zdCBvcHRpb24gb2Ygb3B0aW9ucykgewogICAgICAgICAgY29uc3QgY2hpbGRDdHggPSB7CiAgICAgICAgICAgIC4uLmN0eCwKICAgICAgICAgICAgY29tbW9uOiB7CiAgICAgICAgICAgICAgLi4uY3R4LmNvbW1vbiwKICAgICAgICAgICAgICBpc3N1ZXM6IFtdCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHBhcmVudDogbnVsbAogICAgICAgICAgfTsKICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG9wdGlvbi5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGNoaWxkQ3R4CiAgICAgICAgICB9KTsKICAgICAgICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSAidmFsaWQiKSB7CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICB9IGVsc2UgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICJkaXJ0eSIgJiYgIWRpcnR5KSB7CiAgICAgICAgICAgIGRpcnR5ID0geyByZXN1bHQsIGN0eDogY2hpbGRDdHggfTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChjaGlsZEN0eC5jb21tb24uaXNzdWVzLmxlbmd0aCkgewogICAgICAgICAgICBpc3N1ZXMucHVzaChjaGlsZEN0eC5jb21tb24uaXNzdWVzKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGRpcnR5KSB7CiAgICAgICAgICBjdHguY29tbW9uLmlzc3Vlcy5wdXNoKC4uLmRpcnR5LmN0eC5jb21tb24uaXNzdWVzKTsKICAgICAgICAgIHJldHVybiBkaXJ0eS5yZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHVuaW9uRXJyb3JzID0gaXNzdWVzLm1hcCgoaXNzdWVzMikgPT4gbmV3IFpvZEVycm9yKGlzc3VlczIpKTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3VuaW9uLAogICAgICAgICAgdW5pb25FcnJvcnMKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgfQogICAgZ2V0IG9wdGlvbnMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYub3B0aW9uczsKICAgIH0KICB9CiAgWm9kVW5pb24uY3JlYXRlID0gKHR5cGVzLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kVW5pb24oewogICAgICBvcHRpb25zOiB0eXBlcywKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RVbmlvbiwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNvbnN0IGdldERpc2NyaW1pbmF0b3IgPSAodHlwZSkgPT4gewogICAgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RMYXp5KSB7CiAgICAgIHJldHVybiBnZXREaXNjcmltaW5hdG9yKHR5cGUuc2NoZW1hKTsKICAgIH0gZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZEVmZmVjdHMpIHsKICAgICAgcmV0dXJuIGdldERpc2NyaW1pbmF0b3IodHlwZS5pbm5lclR5cGUoKSk7CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RMaXRlcmFsKSB7CiAgICAgIHJldHVybiBbdHlwZS52YWx1ZV07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RFbnVtKSB7CiAgICAgIHJldHVybiB0eXBlLm9wdGlvbnM7CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2ROYXRpdmVFbnVtKSB7CiAgICAgIHJldHVybiB1dGlsLm9iamVjdFZhbHVlcyh0eXBlLmVudW0pOwogICAgfSBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kRGVmYXVsdCkgewogICAgICByZXR1cm4gZ2V0RGlzY3JpbWluYXRvcih0eXBlLl9kZWYuaW5uZXJUeXBlKTsKICAgIH0gZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZFVuZGVmaW5lZCkgewogICAgICByZXR1cm4gW3ZvaWQgMF07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2ROdWxsKSB7CiAgICAgIHJldHVybiBbbnVsbF07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RPcHRpb25hbCkgewogICAgICByZXR1cm4gW3ZvaWQgMCwgLi4uZ2V0RGlzY3JpbWluYXRvcih0eXBlLnVud3JhcCgpKV07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2ROdWxsYWJsZSkgewogICAgICByZXR1cm4gW251bGwsIC4uLmdldERpc2NyaW1pbmF0b3IodHlwZS51bndyYXAoKSldOwogICAgfSBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kQnJhbmRlZCkgewogICAgICByZXR1cm4gZ2V0RGlzY3JpbWluYXRvcih0eXBlLnVud3JhcCgpKTsKICAgIH0gZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZFJlYWRvbmx5KSB7CiAgICAgIHJldHVybiBnZXREaXNjcmltaW5hdG9yKHR5cGUudW53cmFwKCkpOwogICAgfSBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kQ2F0Y2gpIHsKICAgICAgcmV0dXJuIGdldERpc2NyaW1pbmF0b3IodHlwZS5fZGVmLmlubmVyVHlwZSk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gW107CiAgICB9CiAgfTsKICBjbGFzcyBab2REaXNjcmltaW5hdGVkVW5pb24gZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm9iamVjdCkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm9iamVjdCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IGRpc2NyaW1pbmF0b3IgPSB0aGlzLmRpc2NyaW1pbmF0b3I7CiAgICAgIGNvbnN0IGRpc2NyaW1pbmF0b3JWYWx1ZSA9IGN0eC5kYXRhW2Rpc2NyaW1pbmF0b3JdOwogICAgICBjb25zdCBvcHRpb24gPSB0aGlzLm9wdGlvbnNNYXAuZ2V0KGRpc2NyaW1pbmF0b3JWYWx1ZSk7CiAgICAgIGlmICghb3B0aW9uKSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF91bmlvbl9kaXNjcmltaW5hdG9yLAogICAgICAgICAgb3B0aW9uczogQXJyYXkuZnJvbSh0aGlzLm9wdGlvbnNNYXAua2V5cygpKSwKICAgICAgICAgIHBhdGg6IFtkaXNjcmltaW5hdG9yXQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbi5fcGFyc2VBc3luYyh7CiAgICAgICAgICBkYXRhOiBjdHguZGF0YSwKICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gb3B0aW9uLl9wYXJzZVN5bmMoewogICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIGdldCBkaXNjcmltaW5hdG9yKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmRpc2NyaW1pbmF0b3I7CiAgICB9CiAgICBnZXQgb3B0aW9ucygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5vcHRpb25zOwogICAgfQogICAgZ2V0IG9wdGlvbnNNYXAoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYub3B0aW9uc01hcDsKICAgIH0KICAgIC8qKgogICAgICogVGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBkaXNjcmltaW5hdGVkIHVuaW9uIHNjaGVtYS4gSXRzIGJlaGF2aW91ciBpcyB2ZXJ5IHNpbWlsYXIgdG8gdGhhdCBvZiB0aGUgbm9ybWFsIHoudW5pb24oKSBjb25zdHJ1Y3Rvci4KICAgICAqIEhvd2V2ZXIsIGl0IG9ubHkgYWxsb3dzIGEgdW5pb24gb2Ygb2JqZWN0cywgYWxsIG9mIHdoaWNoIG5lZWQgdG8gc2hhcmUgYSBkaXNjcmltaW5hdG9yIHByb3BlcnR5LiBUaGlzIHByb3BlcnR5IG11c3QKICAgICAqIGhhdmUgYSBkaWZmZXJlbnQgdmFsdWUgZm9yIGVhY2ggb2JqZWN0IGluIHRoZSB1bmlvbi4KICAgICAqIEBwYXJhbSBkaXNjcmltaW5hdG9yIHRoZSBuYW1lIG9mIHRoZSBkaXNjcmltaW5hdG9yIHByb3BlcnR5CiAgICAgKiBAcGFyYW0gdHlwZXMgYW4gYXJyYXkgb2Ygb2JqZWN0IHNjaGVtYXMKICAgICAqIEBwYXJhbSBwYXJhbXMKICAgICAqLwogICAgc3RhdGljIGNyZWF0ZShkaXNjcmltaW5hdG9yLCBvcHRpb25zLCBwYXJhbXMpIHsKICAgICAgY29uc3Qgb3B0aW9uc01hcCA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgIGZvciAoY29uc3QgdHlwZSBvZiBvcHRpb25zKSB7CiAgICAgICAgY29uc3QgZGlzY3JpbWluYXRvclZhbHVlcyA9IGdldERpc2NyaW1pbmF0b3IodHlwZS5zaGFwZVtkaXNjcmltaW5hdG9yXSk7CiAgICAgICAgaWYgKCFkaXNjcmltaW5hdG9yVmFsdWVzLmxlbmd0aCkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBBIGRpc2NyaW1pbmF0b3IgdmFsdWUgZm9yIGtleSBcYCR7ZGlzY3JpbWluYXRvcn1cYCBjb3VsZCBub3QgYmUgZXh0cmFjdGVkIGZyb20gYWxsIHNjaGVtYSBvcHRpb25zYCk7CiAgICAgICAgfQogICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgZGlzY3JpbWluYXRvclZhbHVlcykgewogICAgICAgICAgaWYgKG9wdGlvbnNNYXAuaGFzKHZhbHVlKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERpc2NyaW1pbmF0b3IgcHJvcGVydHkgJHtTdHJpbmcoZGlzY3JpbWluYXRvcil9IGhhcyBkdXBsaWNhdGUgdmFsdWUgJHtTdHJpbmcodmFsdWUpfWApOwogICAgICAgICAgfQogICAgICAgICAgb3B0aW9uc01hcC5zZXQodmFsdWUsIHR5cGUpOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbmV3IFpvZERpc2NyaW1pbmF0ZWRVbmlvbih7CiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2REaXNjcmltaW5hdGVkVW5pb24sCiAgICAgICAgZGlzY3JpbWluYXRvciwKICAgICAgICBvcHRpb25zLAogICAgICAgIG9wdGlvbnNNYXAsCiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICAgIH0pOwogICAgfQogIH0KICBmdW5jdGlvbiBtZXJnZVZhbHVlcyhhMiwgYikgewogICAgY29uc3QgYVR5cGUgPSBnZXRQYXJzZWRUeXBlKGEyKTsKICAgIGNvbnN0IGJUeXBlID0gZ2V0UGFyc2VkVHlwZShiKTsKICAgIGlmIChhMiA9PT0gYikgewogICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZGF0YTogYTIgfTsKICAgIH0gZWxzZSBpZiAoYVR5cGUgPT09IFpvZFBhcnNlZFR5cGUub2JqZWN0ICYmIGJUeXBlID09PSBab2RQYXJzZWRUeXBlLm9iamVjdCkgewogICAgICBjb25zdCBiS2V5cyA9IHV0aWwub2JqZWN0S2V5cyhiKTsKICAgICAgY29uc3Qgc2hhcmVkS2V5cyA9IHV0aWwub2JqZWN0S2V5cyhhMikuZmlsdGVyKChrZXkpID0+IGJLZXlzLmluZGV4T2Yoa2V5KSAhPT0gLTEpOwogICAgICBjb25zdCBuZXdPYmogPSB7IC4uLmEyLCAuLi5iIH07CiAgICAgIGZvciAoY29uc3Qga2V5IG9mIHNoYXJlZEtleXMpIHsKICAgICAgICBjb25zdCBzaGFyZWRWYWx1ZSA9IG1lcmdlVmFsdWVzKGEyW2tleV0sIGJba2V5XSk7CiAgICAgICAgaWYgKCFzaGFyZWRWYWx1ZS52YWxpZCkgewogICAgICAgICAgcmV0dXJuIHsgdmFsaWQ6IGZhbHNlIH07CiAgICAgICAgfQogICAgICAgIG5ld09ialtrZXldID0gc2hhcmVkVmFsdWUuZGF0YTsKICAgICAgfQogICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZGF0YTogbmV3T2JqIH07CiAgICB9IGVsc2UgaWYgKGFUeXBlID09PSBab2RQYXJzZWRUeXBlLmFycmF5ICYmIGJUeXBlID09PSBab2RQYXJzZWRUeXBlLmFycmF5KSB7CiAgICAgIGlmIChhMi5sZW5ndGggIT09IGIubGVuZ3RoKSB7CiAgICAgICAgcmV0dXJuIHsgdmFsaWQ6IGZhbHNlIH07CiAgICAgIH0KICAgICAgY29uc3QgbmV3QXJyYXkgPSBbXTsKICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGEyLmxlbmd0aDsgaW5kZXgrKykgewogICAgICAgIGNvbnN0IGl0ZW1BID0gYTJbaW5kZXhdOwogICAgICAgIGNvbnN0IGl0ZW1CID0gYltpbmRleF07CiAgICAgICAgY29uc3Qgc2hhcmVkVmFsdWUgPSBtZXJnZVZhbHVlcyhpdGVtQSwgaXRlbUIpOwogICAgICAgIGlmICghc2hhcmVkVmFsdWUudmFsaWQpIHsKICAgICAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSB9OwogICAgICAgIH0KICAgICAgICBuZXdBcnJheS5wdXNoKHNoYXJlZFZhbHVlLmRhdGEpOwogICAgICB9CiAgICAgIHJldHVybiB7IHZhbGlkOiB0cnVlLCBkYXRhOiBuZXdBcnJheSB9OwogICAgfSBlbHNlIGlmIChhVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS5kYXRlICYmIGJUeXBlID09PSBab2RQYXJzZWRUeXBlLmRhdGUgJiYgK2EyID09PSArYikgewogICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZGF0YTogYTIgfTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSB9OwogICAgfQogIH0KICBjbGFzcyBab2RJbnRlcnNlY3Rpb24gZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IHN0YXR1cywgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBoYW5kbGVQYXJzZWQgPSAocGFyc2VkTGVmdCwgcGFyc2VkUmlnaHQpID0+IHsKICAgICAgICBpZiAoaXNBYm9ydGVkKHBhcnNlZExlZnQpIHx8IGlzQWJvcnRlZChwYXJzZWRSaWdodCkpIHsKICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgIH0KICAgICAgICBjb25zdCBtZXJnZWQgPSBtZXJnZVZhbHVlcyhwYXJzZWRMZWZ0LnZhbHVlLCBwYXJzZWRSaWdodC52YWx1ZSk7CiAgICAgICAgaWYgKCFtZXJnZWQudmFsaWQpIHsKICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9pbnRlcnNlY3Rpb25fdHlwZXMKICAgICAgICAgIH0pOwogICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgfQogICAgICAgIGlmIChpc0RpcnR5KHBhcnNlZExlZnQpIHx8IGlzRGlydHkocGFyc2VkUmlnaHQpKSB7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBtZXJnZWQuZGF0YSB9OwogICAgICB9OwogICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYykgewogICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbCiAgICAgICAgICB0aGlzLl9kZWYubGVmdC5fcGFyc2VBc3luYyh7CiAgICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLAogICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICAgIH0pLAogICAgICAgICAgdGhpcy5fZGVmLnJpZ2h0Ll9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSkKICAgICAgICBdKS50aGVuKChbbGVmdCwgcmlnaHRdKSA9PiBoYW5kbGVQYXJzZWQobGVmdCwgcmlnaHQpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gaGFuZGxlUGFyc2VkKHRoaXMuX2RlZi5sZWZ0Ll9wYXJzZVN5bmMoewogICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgfSksIHRoaXMuX2RlZi5yaWdodC5fcGFyc2VTeW5jKHsKICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLAogICAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgIH0pKTsKICAgICAgfQogICAgfQogIH0KICBab2RJbnRlcnNlY3Rpb24uY3JlYXRlID0gKGxlZnQsIHJpZ2h0LCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kSW50ZXJzZWN0aW9uKHsKICAgICAgbGVmdCwKICAgICAgcmlnaHQsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kSW50ZXJzZWN0aW9uLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kVHVwbGUgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IHN0YXR1cywgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuYXJyYXkpIHsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5hcnJheSwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmIChjdHguZGF0YS5sZW5ndGggPCB0aGlzLl9kZWYuaXRlbXMubGVuZ3RoKSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgbWluaW11bTogdGhpcy5fZGVmLml0ZW1zLmxlbmd0aCwKICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgIHR5cGU6ICJhcnJheSIKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBjb25zdCByZXN0ID0gdGhpcy5fZGVmLnJlc3Q7CiAgICAgIGlmICghcmVzdCAmJiBjdHguZGF0YS5sZW5ndGggPiB0aGlzLl9kZWYuaXRlbXMubGVuZ3RoKSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX2JpZywKICAgICAgICAgIG1heGltdW06IHRoaXMuX2RlZi5pdGVtcy5sZW5ndGgsCiAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgICBleGFjdDogZmFsc2UsCiAgICAgICAgICB0eXBlOiAiYXJyYXkiCiAgICAgICAgfSk7CiAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgIH0KICAgICAgY29uc3QgaXRlbXMgPSBbLi4uY3R4LmRhdGFdLm1hcCgoaXRlbSwgaXRlbUluZGV4KSA9PiB7CiAgICAgICAgY29uc3Qgc2NoZW1hID0gdGhpcy5fZGVmLml0ZW1zW2l0ZW1JbmRleF0gfHwgdGhpcy5fZGVmLnJlc3Q7CiAgICAgICAgaWYgKCFzY2hlbWEpCiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICByZXR1cm4gc2NoZW1hLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwgaXRlbSwgY3R4LnBhdGgsIGl0ZW1JbmRleCkpOwogICAgICB9KS5maWx0ZXIoKHgpID0+ICEheCk7CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKGl0ZW1zKS50aGVuKChyZXN1bHRzKSA9PiB7CiAgICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VBcnJheShzdGF0dXMsIHJlc3VsdHMpOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBQYXJzZVN0YXR1cy5tZXJnZUFycmF5KHN0YXR1cywgaXRlbXMpOwogICAgICB9CiAgICB9CiAgICBnZXQgaXRlbXMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYuaXRlbXM7CiAgICB9CiAgICByZXN0KHJlc3QpIHsKICAgICAgcmV0dXJuIG5ldyBab2RUdXBsZSh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHJlc3QKICAgICAgfSk7CiAgICB9CiAgfQogIFpvZFR1cGxlLmNyZWF0ZSA9IChzY2hlbWFzLCBwYXJhbXMpID0+IHsKICAgIGlmICghQXJyYXkuaXNBcnJheShzY2hlbWFzKSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIllvdSBtdXN0IHBhc3MgYW4gYXJyYXkgb2Ygc2NoZW1hcyB0byB6LnR1cGxlKFsgLi4uIF0pIik7CiAgICB9CiAgICByZXR1cm4gbmV3IFpvZFR1cGxlKHsKICAgICAgaXRlbXM6IHNjaGVtYXMsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kVHVwbGUsCiAgICAgIHJlc3Q6IG51bGwsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RSZWNvcmQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGdldCBrZXlTY2hlbWEoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYua2V5VHlwZTsKICAgIH0KICAgIGdldCB2YWx1ZVNjaGVtYSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZVR5cGU7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm9iamVjdCkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm9iamVjdCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IHBhaXJzID0gW107CiAgICAgIGNvbnN0IGtleVR5cGUgPSB0aGlzLl9kZWYua2V5VHlwZTsKICAgICAgY29uc3QgdmFsdWVUeXBlID0gdGhpcy5fZGVmLnZhbHVlVHlwZTsKICAgICAgZm9yIChjb25zdCBrZXkgaW4gY3R4LmRhdGEpIHsKICAgICAgICBwYWlycy5wdXNoKHsKICAgICAgICAgIGtleToga2V5VHlwZS5fcGFyc2UobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGtleSwgY3R4LnBhdGgsIGtleSkpLAogICAgICAgICAgdmFsdWU6IHZhbHVlVHlwZS5fcGFyc2UobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGN0eC5kYXRhW2tleV0sIGN0eC5wYXRoLCBrZXkpKSwKICAgICAgICAgIGFsd2F5c1NldDoga2V5IGluIGN0eC5kYXRhCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VPYmplY3RBc3luYyhzdGF0dXMsIHBhaXJzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VPYmplY3RTeW5jKHN0YXR1cywgcGFpcnMpOwogICAgICB9CiAgICB9CiAgICBnZXQgZWxlbWVudCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZVR5cGU7CiAgICB9CiAgICBzdGF0aWMgY3JlYXRlKGZpcnN0LCBzZWNvbmQsIHRoaXJkKSB7CiAgICAgIGlmIChzZWNvbmQgaW5zdGFuY2VvZiBab2RUeXBlKSB7CiAgICAgICAgcmV0dXJuIG5ldyBab2RSZWNvcmQoewogICAgICAgICAga2V5VHlwZTogZmlyc3QsCiAgICAgICAgICB2YWx1ZVR5cGU6IHNlY29uZCwKICAgICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kUmVjb3JkLAogICAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyh0aGlyZCkKICAgICAgICB9KTsKICAgICAgfQogICAgICByZXR1cm4gbmV3IFpvZFJlY29yZCh7CiAgICAgICAga2V5VHlwZTogWm9kU3RyaW5nLmNyZWF0ZSgpLAogICAgICAgIHZhbHVlVHlwZTogZmlyc3QsCiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RSZWNvcmQsCiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhzZWNvbmQpCiAgICAgIH0pOwogICAgfQogIH0KICBjbGFzcyBab2RNYXAgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGdldCBrZXlTY2hlbWEoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYua2V5VHlwZTsKICAgIH0KICAgIGdldCB2YWx1ZVNjaGVtYSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZVR5cGU7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm1hcCkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm1hcCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IGtleVR5cGUgPSB0aGlzLl9kZWYua2V5VHlwZTsKICAgICAgY29uc3QgdmFsdWVUeXBlID0gdGhpcy5fZGVmLnZhbHVlVHlwZTsKICAgICAgY29uc3QgcGFpcnMgPSBbLi4uY3R4LmRhdGEuZW50cmllcygpXS5tYXAoKFtrZXksIHZhbHVlXSwgaW5kZXgpID0+IHsKICAgICAgICByZXR1cm4gewogICAgICAgICAga2V5OiBrZXlUeXBlLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwga2V5LCBjdHgucGF0aCwgW2luZGV4LCAia2V5Il0pKSwKICAgICAgICAgIHZhbHVlOiB2YWx1ZVR5cGUuX3BhcnNlKG5ldyBQYXJzZUlucHV0TGF6eVBhdGgoY3R4LCB2YWx1ZSwgY3R4LnBhdGgsIFtpbmRleCwgInZhbHVlIl0pKQogICAgICAgIH07CiAgICAgIH0pOwogICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYykgewogICAgICAgIGNvbnN0IGZpbmFsTWFwID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihhc3luYyAoKSA9PiB7CiAgICAgICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHsKICAgICAgICAgICAgY29uc3Qga2V5ID0gYXdhaXQgcGFpci5rZXk7CiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgcGFpci52YWx1ZTsKICAgICAgICAgICAgaWYgKGtleS5zdGF0dXMgPT09ICJhYm9ydGVkIiB8fCB2YWx1ZS5zdGF0dXMgPT09ICJhYm9ydGVkIikgewogICAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChrZXkuc3RhdHVzID09PSAiZGlydHkiIHx8IHZhbHVlLnN0YXR1cyA9PT0gImRpcnR5IikgewogICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZpbmFsTWFwLnNldChrZXkudmFsdWUsIHZhbHVlLnZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogZmluYWxNYXAgfTsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBmaW5hbE1hcCA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgICAgZm9yIChjb25zdCBwYWlyIG9mIHBhaXJzKSB7CiAgICAgICAgICBjb25zdCBrZXkgPSBwYWlyLmtleTsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gcGFpci52YWx1ZTsKICAgICAgICAgIGlmIChrZXkuc3RhdHVzID09PSAiYWJvcnRlZCIgfHwgdmFsdWUuc3RhdHVzID09PSAiYWJvcnRlZCIpIHsKICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoa2V5LnN0YXR1cyA9PT0gImRpcnR5IiB8fCB2YWx1ZS5zdGF0dXMgPT09ICJkaXJ0eSIpIHsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgICBmaW5hbE1hcC5zZXQoa2V5LnZhbHVlLCB2YWx1ZS52YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogZmluYWxNYXAgfTsKICAgICAgfQogICAgfQogIH0KICBab2RNYXAuY3JlYXRlID0gKGtleVR5cGUsIHZhbHVlVHlwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE1hcCh7CiAgICAgIHZhbHVlVHlwZSwKICAgICAga2V5VHlwZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RNYXAsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RTZXQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IHN0YXR1cywgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuc2V0KSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUuc2V0LAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgY29uc3QgZGVmID0gdGhpcy5fZGVmOwogICAgICBpZiAoZGVmLm1pblNpemUgIT09IG51bGwpIHsKICAgICAgICBpZiAoY3R4LmRhdGEuc2l6ZSA8IGRlZi5taW5TaXplLnZhbHVlKSB7CiAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19zbWFsbCwKICAgICAgICAgICAgbWluaW11bTogZGVmLm1pblNpemUudmFsdWUsCiAgICAgICAgICAgIHR5cGU6ICJzZXQiLAogICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgbWVzc2FnZTogZGVmLm1pblNpemUubWVzc2FnZQogICAgICAgICAgfSk7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGRlZi5tYXhTaXplICE9PSBudWxsKSB7CiAgICAgICAgaWYgKGN0eC5kYXRhLnNpemUgPiBkZWYubWF4U2l6ZS52YWx1ZSkgewogICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fYmlnLAogICAgICAgICAgICBtYXhpbXVtOiBkZWYubWF4U2l6ZS52YWx1ZSwKICAgICAgICAgICAgdHlwZTogInNldCIsCiAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLAogICAgICAgICAgICBtZXNzYWdlOiBkZWYubWF4U2l6ZS5tZXNzYWdlCiAgICAgICAgICB9KTsKICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCB2YWx1ZVR5cGUgPSB0aGlzLl9kZWYudmFsdWVUeXBlOwogICAgICBmdW5jdGlvbiBmaW5hbGl6ZVNldChlbGVtZW50czIpIHsKICAgICAgICBjb25zdCBwYXJzZWRTZXQgPSAvKiBAX19QVVJFX18gKi8gbmV3IFNldCgpOwogICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbGVtZW50czIpIHsKICAgICAgICAgIGlmIChlbGVtZW50LnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgICAgIGlmIChlbGVtZW50LnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICBwYXJzZWRTZXQuYWRkKGVsZW1lbnQudmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IHBhcnNlZFNldCB9OwogICAgICB9CiAgICAgIGNvbnN0IGVsZW1lbnRzID0gWy4uLmN0eC5kYXRhLnZhbHVlcygpXS5tYXAoKGl0ZW0sIGkyKSA9PiB2YWx1ZVR5cGUuX3BhcnNlKG5ldyBQYXJzZUlucHV0TGF6eVBhdGgoY3R4LCBpdGVtLCBjdHgucGF0aCwgaTIpKSk7CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKGVsZW1lbnRzKS50aGVuKChlbGVtZW50czIpID0+IGZpbmFsaXplU2V0KGVsZW1lbnRzMikpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBmaW5hbGl6ZVNldChlbGVtZW50cyk7CiAgICAgIH0KICAgIH0KICAgIG1pbihtaW5TaXplLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kU2V0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgbWluU2l6ZTogeyB2YWx1ZTogbWluU2l6ZSwgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpIH0KICAgICAgfSk7CiAgICB9CiAgICBtYXgobWF4U2l6ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gbmV3IFpvZFNldCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIG1heFNpemU6IHsgdmFsdWU6IG1heFNpemUsIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSB9CiAgICAgIH0pOwogICAgfQogICAgc2l6ZShzaXplLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLm1pbihzaXplLCBtZXNzYWdlKS5tYXgoc2l6ZSwgbWVzc2FnZSk7CiAgICB9CiAgICBub25lbXB0eShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLm1pbigxLCBtZXNzYWdlKTsKICAgIH0KICB9CiAgWm9kU2V0LmNyZWF0ZSA9ICh2YWx1ZVR5cGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RTZXQoewogICAgICB2YWx1ZVR5cGUsCiAgICAgIG1pblNpemU6IG51bGwsCiAgICAgIG1heFNpemU6IG51bGwsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kU2V0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kRnVuY3Rpb24gZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICB0aGlzLnZhbGlkYXRlID0gdGhpcy5pbXBsZW1lbnQ7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBjdHggfSA9IHRoaXMuX3Byb2Nlc3NJbnB1dFBhcmFtcyhpbnB1dCk7CiAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5mdW5jdGlvbikgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmZ1bmN0aW9uLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgZnVuY3Rpb24gbWFrZUFyZ3NJc3N1ZShhcmdzLCBlcnJvcikgewogICAgICAgIHJldHVybiBtYWtlSXNzdWUoewogICAgICAgICAgZGF0YTogYXJncywKICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgZXJyb3JNYXBzOiBbCiAgICAgICAgICAgIGN0eC5jb21tb24uY29udGV4dHVhbEVycm9yTWFwLAogICAgICAgICAgICBjdHguc2NoZW1hRXJyb3JNYXAsCiAgICAgICAgICAgIGdldEVycm9yTWFwKCksCiAgICAgICAgICAgIGVycm9yTWFwCiAgICAgICAgICBdLmZpbHRlcigoeCkgPT4gISF4KSwKICAgICAgICAgIGlzc3VlRGF0YTogewogICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9hcmd1bWVudHMsCiAgICAgICAgICAgIGFyZ3VtZW50c0Vycm9yOiBlcnJvcgogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CiAgICAgIGZ1bmN0aW9uIG1ha2VSZXR1cm5zSXNzdWUocmV0dXJucywgZXJyb3IpIHsKICAgICAgICByZXR1cm4gbWFrZUlzc3VlKHsKICAgICAgICAgIGRhdGE6IHJldHVybnMsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIGVycm9yTWFwczogWwogICAgICAgICAgICBjdHguY29tbW9uLmNvbnRleHR1YWxFcnJvck1hcCwKICAgICAgICAgICAgY3R4LnNjaGVtYUVycm9yTWFwLAogICAgICAgICAgICBnZXRFcnJvck1hcCgpLAogICAgICAgICAgICBlcnJvck1hcAogICAgICAgICAgXS5maWx0ZXIoKHgpID0+ICEheCksCiAgICAgICAgICBpc3N1ZURhdGE6IHsKICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfcmV0dXJuX3R5cGUsCiAgICAgICAgICAgIHJldHVyblR5cGVFcnJvcjogZXJyb3IKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQogICAgICBjb25zdCBwYXJhbXMgPSB7IGVycm9yTWFwOiBjdHguY29tbW9uLmNvbnRleHR1YWxFcnJvck1hcCB9OwogICAgICBjb25zdCBmbiA9IGN0eC5kYXRhOwogICAgICBpZiAodGhpcy5fZGVmLnJldHVybnMgaW5zdGFuY2VvZiBab2RQcm9taXNlKSB7CiAgICAgICAgY29uc3QgbWUgPSB0aGlzOwogICAgICAgIHJldHVybiBPSyhhc3luYyBmdW5jdGlvbiguLi5hcmdzKSB7CiAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBab2RFcnJvcihbXSk7CiAgICAgICAgICBjb25zdCBwYXJzZWRBcmdzID0gYXdhaXQgbWUuX2RlZi5hcmdzLnBhcnNlQXN5bmMoYXJncywgcGFyYW1zKS5jYXRjaCgoZTIpID0+IHsKICAgICAgICAgICAgZXJyb3IuYWRkSXNzdWUobWFrZUFyZ3NJc3N1ZShhcmdzLCBlMikpOwogICAgICAgICAgICB0aHJvdyBlcnJvcjsKICAgICAgICAgIH0pOwogICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgUmVmbGVjdC5hcHBseShmbiwgdGhpcywgcGFyc2VkQXJncyk7CiAgICAgICAgICBjb25zdCBwYXJzZWRSZXR1cm5zID0gYXdhaXQgbWUuX2RlZi5yZXR1cm5zLl9kZWYudHlwZS5wYXJzZUFzeW5jKHJlc3VsdCwgcGFyYW1zKS5jYXRjaCgoZTIpID0+IHsKICAgICAgICAgICAgZXJyb3IuYWRkSXNzdWUobWFrZVJldHVybnNJc3N1ZShyZXN1bHQsIGUyKSk7CiAgICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgICAgfSk7CiAgICAgICAgICByZXR1cm4gcGFyc2VkUmV0dXJuczsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBtZSA9IHRoaXM7CiAgICAgICAgcmV0dXJuIE9LKGZ1bmN0aW9uKC4uLmFyZ3MpIHsKICAgICAgICAgIGNvbnN0IHBhcnNlZEFyZ3MgPSBtZS5fZGVmLmFyZ3Muc2FmZVBhcnNlKGFyZ3MsIHBhcmFtcyk7CiAgICAgICAgICBpZiAoIXBhcnNlZEFyZ3Muc3VjY2VzcykgewogICAgICAgICAgICB0aHJvdyBuZXcgWm9kRXJyb3IoW21ha2VBcmdzSXNzdWUoYXJncywgcGFyc2VkQXJncy5lcnJvcildKTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IFJlZmxlY3QuYXBwbHkoZm4sIHRoaXMsIHBhcnNlZEFyZ3MuZGF0YSk7CiAgICAgICAgICBjb25zdCBwYXJzZWRSZXR1cm5zID0gbWUuX2RlZi5yZXR1cm5zLnNhZmVQYXJzZShyZXN1bHQsIHBhcmFtcyk7CiAgICAgICAgICBpZiAoIXBhcnNlZFJldHVybnMuc3VjY2VzcykgewogICAgICAgICAgICB0aHJvdyBuZXcgWm9kRXJyb3IoW21ha2VSZXR1cm5zSXNzdWUocmVzdWx0LCBwYXJzZWRSZXR1cm5zLmVycm9yKV0pOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHBhcnNlZFJldHVybnMuZGF0YTsKICAgICAgICB9KTsKICAgICAgfQogICAgfQogICAgcGFyYW1ldGVycygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5hcmdzOwogICAgfQogICAgcmV0dXJuVHlwZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5yZXR1cm5zOwogICAgfQogICAgYXJncyguLi5pdGVtcykgewogICAgICByZXR1cm4gbmV3IFpvZEZ1bmN0aW9uKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgYXJnczogWm9kVHVwbGUuY3JlYXRlKGl0ZW1zKS5yZXN0KFpvZFVua25vd24uY3JlYXRlKCkpCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJucyhyZXR1cm5UeXBlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kRnVuY3Rpb24oewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICByZXR1cm5zOiByZXR1cm5UeXBlCiAgICAgIH0pOwogICAgfQogICAgaW1wbGVtZW50KGZ1bmMpIHsKICAgICAgY29uc3QgdmFsaWRhdGVkRnVuYyA9IHRoaXMucGFyc2UoZnVuYyk7CiAgICAgIHJldHVybiB2YWxpZGF0ZWRGdW5jOwogICAgfQogICAgc3RyaWN0SW1wbGVtZW50KGZ1bmMpIHsKICAgICAgY29uc3QgdmFsaWRhdGVkRnVuYyA9IHRoaXMucGFyc2UoZnVuYyk7CiAgICAgIHJldHVybiB2YWxpZGF0ZWRGdW5jOwogICAgfQogICAgc3RhdGljIGNyZWF0ZShhcmdzLCByZXR1cm5zLCBwYXJhbXMpIHsKICAgICAgcmV0dXJuIG5ldyBab2RGdW5jdGlvbih7CiAgICAgICAgYXJnczogYXJncyA/IGFyZ3MgOiBab2RUdXBsZS5jcmVhdGUoW10pLnJlc3QoWm9kVW5rbm93bi5jcmVhdGUoKSksCiAgICAgICAgcmV0dXJuczogcmV0dXJucyB8fCBab2RVbmtub3duLmNyZWF0ZSgpLAogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRnVuY3Rpb24sCiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICAgIH0pOwogICAgfQogIH0KICBjbGFzcyBab2RMYXp5IGV4dGVuZHMgWm9kVHlwZSB7CiAgICBnZXQgc2NoZW1hKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmdldHRlcigpOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBsYXp5U2NoZW1hID0gdGhpcy5fZGVmLmdldHRlcigpOwogICAgICByZXR1cm4gbGF6eVNjaGVtYS5fcGFyc2UoeyBkYXRhOiBjdHguZGF0YSwgcGF0aDogY3R4LnBhdGgsIHBhcmVudDogY3R4IH0pOwogICAgfQogIH0KICBab2RMYXp5LmNyZWF0ZSA9IChnZXR0ZXIsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RMYXp5KHsKICAgICAgZ2V0dGVyLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZExhenksCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RMaXRlcmFsIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgaWYgKGlucHV0LmRhdGEgIT09IHRoaXMuX2RlZi52YWx1ZSkgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIHJlY2VpdmVkOiBjdHguZGF0YSwKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX2xpdGVyYWwsCiAgICAgICAgICBleHBlY3RlZDogdGhpcy5fZGVmLnZhbHVlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgcmV0dXJuIHsgc3RhdHVzOiAidmFsaWQiLCB2YWx1ZTogaW5wdXQuZGF0YSB9OwogICAgfQogICAgZ2V0IHZhbHVlKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnZhbHVlOwogICAgfQogIH0KICBab2RMaXRlcmFsLmNyZWF0ZSA9ICh2YWx1ZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZExpdGVyYWwoewogICAgICB2YWx1ZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RMaXRlcmFsLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgZnVuY3Rpb24gY3JlYXRlWm9kRW51bSh2YWx1ZXMsIHBhcmFtcykgewogICAgcmV0dXJuIG5ldyBab2RFbnVtKHsKICAgICAgdmFsdWVzLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVudW0sCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfQogIGNsYXNzIFpvZEVudW0gZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICBfWm9kRW51bV9jYWNoZS5zZXQodGhpcywgdm9pZCAwKTsKICAgIH0KICAgIF9wYXJzZShpbnB1dCkgewogICAgICBpZiAodHlwZW9mIGlucHV0LmRhdGEgIT09ICJzdHJpbmciKSB7CiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICAgIGNvbnN0IGV4cGVjdGVkVmFsdWVzID0gdGhpcy5fZGVmLnZhbHVlczsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGV4cGVjdGVkOiB1dGlsLmpvaW5WYWx1ZXMoZXhwZWN0ZWRWYWx1ZXMpLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLAogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmICghX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfWm9kRW51bV9jYWNoZSkpIHsKICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9ab2RFbnVtX2NhY2hlLCBuZXcgU2V0KHRoaXMuX2RlZi52YWx1ZXMpKTsKICAgICAgfQogICAgICBpZiAoIV9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1pvZEVudW1fY2FjaGUpLmhhcyhpbnB1dC5kYXRhKSkgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBjb25zdCBleHBlY3RlZFZhbHVlcyA9IHRoaXMuX2RlZi52YWx1ZXM7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICByZWNlaXZlZDogY3R4LmRhdGEsCiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9lbnVtX3ZhbHVlLAogICAgICAgICAgb3B0aW9uczogZXhwZWN0ZWRWYWx1ZXMKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7CiAgICB9CiAgICBnZXQgb3B0aW9ucygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZXM7CiAgICB9CiAgICBnZXQgZW51bSgpIHsKICAgICAgY29uc3QgZW51bVZhbHVlcyA9IHt9OwogICAgICBmb3IgKGNvbnN0IHZhbCBvZiB0aGlzLl9kZWYudmFsdWVzKSB7CiAgICAgICAgZW51bVZhbHVlc1t2YWxdID0gdmFsOwogICAgICB9CiAgICAgIHJldHVybiBlbnVtVmFsdWVzOwogICAgfQogICAgZ2V0IFZhbHVlcygpIHsKICAgICAgY29uc3QgZW51bVZhbHVlcyA9IHt9OwogICAgICBmb3IgKGNvbnN0IHZhbCBvZiB0aGlzLl9kZWYudmFsdWVzKSB7CiAgICAgICAgZW51bVZhbHVlc1t2YWxdID0gdmFsOwogICAgICB9CiAgICAgIHJldHVybiBlbnVtVmFsdWVzOwogICAgfQogICAgZ2V0IEVudW0oKSB7CiAgICAgIGNvbnN0IGVudW1WYWx1ZXMgPSB7fTsKICAgICAgZm9yIChjb25zdCB2YWwgb2YgdGhpcy5fZGVmLnZhbHVlcykgewogICAgICAgIGVudW1WYWx1ZXNbdmFsXSA9IHZhbDsKICAgICAgfQogICAgICByZXR1cm4gZW51bVZhbHVlczsKICAgIH0KICAgIGV4dHJhY3QodmFsdWVzLCBuZXdEZWYgPSB0aGlzLl9kZWYpIHsKICAgICAgcmV0dXJuIFpvZEVudW0uY3JlYXRlKHZhbHVlcywgewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICAuLi5uZXdEZWYKICAgICAgfSk7CiAgICB9CiAgICBleGNsdWRlKHZhbHVlcywgbmV3RGVmID0gdGhpcy5fZGVmKSB7CiAgICAgIHJldHVybiBab2RFbnVtLmNyZWF0ZSh0aGlzLm9wdGlvbnMuZmlsdGVyKChvcHQpID0+ICF2YWx1ZXMuaW5jbHVkZXMob3B0KSksIHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgLi4ubmV3RGVmCiAgICAgIH0pOwogICAgfQogIH0KICBfWm9kRW51bV9jYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgV2Vha01hcCgpOwogIFpvZEVudW0uY3JlYXRlID0gY3JlYXRlWm9kRW51bTsKICBjbGFzcyBab2ROYXRpdmVFbnVtIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgX1pvZE5hdGl2ZUVudW1fY2FjaGUuc2V0KHRoaXMsIHZvaWQgMCk7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgbmF0aXZlRW51bVZhbHVlcyA9IHV0aWwuZ2V0VmFsaWRFbnVtVmFsdWVzKHRoaXMuX2RlZi52YWx1ZXMpOwogICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5zdHJpbmcgJiYgY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUubnVtYmVyKSB7CiAgICAgICAgY29uc3QgZXhwZWN0ZWRWYWx1ZXMgPSB1dGlsLm9iamVjdFZhbHVlcyhuYXRpdmVFbnVtVmFsdWVzKTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGV4cGVjdGVkOiB1dGlsLmpvaW5WYWx1ZXMoZXhwZWN0ZWRWYWx1ZXMpLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLAogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmICghX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfWm9kTmF0aXZlRW51bV9jYWNoZSkpIHsKICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9ab2ROYXRpdmVFbnVtX2NhY2hlLCBuZXcgU2V0KHV0aWwuZ2V0VmFsaWRFbnVtVmFsdWVzKHRoaXMuX2RlZi52YWx1ZXMpKSk7CiAgICAgIH0KICAgICAgaWYgKCFfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ab2ROYXRpdmVFbnVtX2NhY2hlKS5oYXMoaW5wdXQuZGF0YSkpIHsKICAgICAgICBjb25zdCBleHBlY3RlZFZhbHVlcyA9IHV0aWwub2JqZWN0VmFsdWVzKG5hdGl2ZUVudW1WYWx1ZXMpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5kYXRhLAogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfZW51bV92YWx1ZSwKICAgICAgICAgIG9wdGlvbnM6IGV4cGVjdGVkVmFsdWVzCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgcmV0dXJuIE9LKGlucHV0LmRhdGEpOwogICAgfQogICAgZ2V0IGVudW0oKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYudmFsdWVzOwogICAgfQogIH0KICBfWm9kTmF0aXZlRW51bV9jYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgV2Vha01hcCgpOwogIFpvZE5hdGl2ZUVudW0uY3JlYXRlID0gKHZhbHVlcywgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE5hdGl2ZUVudW0oewogICAgICB2YWx1ZXMsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kTmF0aXZlRW51bSwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZFByb21pc2UgZXh0ZW5kcyBab2RUeXBlIHsKICAgIHVud3JhcCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi50eXBlOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUucHJvbWlzZSAmJiBjdHguY29tbW9uLmFzeW5jID09PSBmYWxzZSkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLnByb21pc2UsCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBjb25zdCBwcm9taXNpZmllZCA9IGN0eC5wYXJzZWRUeXBlID09PSBab2RQYXJzZWRUeXBlLnByb21pc2UgPyBjdHguZGF0YSA6IFByb21pc2UucmVzb2x2ZShjdHguZGF0YSk7CiAgICAgIHJldHVybiBPSyhwcm9taXNpZmllZC50aGVuKChkYXRhKSA9PiB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi50eXBlLnBhcnNlQXN5bmMoZGF0YSwgewogICAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgICBlcnJvck1hcDogY3R4LmNvbW1vbi5jb250ZXh0dWFsRXJyb3JNYXAKICAgICAgICB9KTsKICAgICAgfSkpOwogICAgfQogIH0KICBab2RQcm9taXNlLmNyZWF0ZSA9IChzY2hlbWEsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RQcm9taXNlKHsKICAgICAgdHlwZTogc2NoZW1hLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZFByb21pc2UsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RFZmZlY3RzIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBpbm5lclR5cGUoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYuc2NoZW1hOwogICAgfQogICAgc291cmNlVHlwZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5zY2hlbWEuX2RlZi50eXBlTmFtZSA9PT0gWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMgPyB0aGlzLl9kZWYuc2NoZW1hLnNvdXJjZVR5cGUoKSA6IHRoaXMuX2RlZi5zY2hlbWE7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgY29uc3QgZWZmZWN0ID0gdGhpcy5fZGVmLmVmZmVjdCB8fCBudWxsOwogICAgICBjb25zdCBjaGVja0N0eCA9IHsKICAgICAgICBhZGRJc3N1ZTogKGFyZykgPT4gewogICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCBhcmcpOwogICAgICAgICAgaWYgKGFyZy5mYXRhbCkgewogICAgICAgICAgICBzdGF0dXMuYWJvcnQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgZ2V0IHBhdGgoKSB7CiAgICAgICAgICByZXR1cm4gY3R4LnBhdGg7CiAgICAgICAgfQogICAgICB9OwogICAgICBjaGVja0N0eC5hZGRJc3N1ZSA9IGNoZWNrQ3R4LmFkZElzc3VlLmJpbmQoY2hlY2tDdHgpOwogICAgICBpZiAoZWZmZWN0LnR5cGUgPT09ICJwcmVwcm9jZXNzIikgewogICAgICAgIGNvbnN0IHByb2Nlc3NlZCA9IGVmZmVjdC50cmFuc2Zvcm0oY3R4LmRhdGEsIGNoZWNrQ3R4KTsKICAgICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYykgewogICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwcm9jZXNzZWQpLnRoZW4oYXN5bmMgKHByb2Nlc3NlZDIpID0+IHsKICAgICAgICAgICAgaWYgKHN0YXR1cy52YWx1ZSA9PT0gImFib3J0ZWQiKQogICAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLl9kZWYuc2NoZW1hLl9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgICBkYXRhOiBwcm9jZXNzZWQyLAogICAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgICByZXR1cm4gRElSVFkocmVzdWx0LnZhbHVlKTsKICAgICAgICAgICAgaWYgKHN0YXR1cy52YWx1ZSA9PT0gImRpcnR5IikKICAgICAgICAgICAgICByZXR1cm4gRElSVFkocmVzdWx0LnZhbHVlKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgIH0pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoc3RhdHVzLnZhbHVlID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogcHJvY2Vzc2VkLAogICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICAgIH0pOwogICAgICAgICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICJhYm9ydGVkIikKICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgcmV0dXJuIERJUlRZKHJlc3VsdC52YWx1ZSk7CiAgICAgICAgICBpZiAoc3RhdHVzLnZhbHVlID09PSAiZGlydHkiKQogICAgICAgICAgICByZXR1cm4gRElSVFkocmVzdWx0LnZhbHVlKTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChlZmZlY3QudHlwZSA9PT0gInJlZmluZW1lbnQiKSB7CiAgICAgICAgY29uc3QgZXhlY3V0ZVJlZmluZW1lbnQgPSAoYWNjKSA9PiB7CiAgICAgICAgICBjb25zdCByZXN1bHQgPSBlZmZlY3QucmVmaW5lbWVudChhY2MsIGNoZWNrQ3R4KTsKICAgICAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiQXN5bmMgcmVmaW5lbWVudCBlbmNvdW50ZXJlZCBkdXJpbmcgc3luY2hyb25vdXMgcGFyc2Ugb3BlcmF0aW9uLiBVc2UgLnBhcnNlQXN5bmMgaW5zdGVhZC4iKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBhY2M7CiAgICAgICAgfTsKICAgICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYyA9PT0gZmFsc2UpIHsKICAgICAgICAgIGNvbnN0IGlubmVyID0gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAoaW5uZXIuc3RhdHVzID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgaWYgKGlubmVyLnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICBleGVjdXRlUmVmaW5lbWVudChpbm5lci52YWx1ZSk7CiAgICAgICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGlubmVyLnZhbHVlIH07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9kZWYuc2NoZW1hLl9wYXJzZUFzeW5jKHsgZGF0YTogY3R4LmRhdGEsIHBhdGg6IGN0eC5wYXRoLCBwYXJlbnQ6IGN0eCB9KS50aGVuKChpbm5lcikgPT4gewogICAgICAgICAgICBpZiAoaW5uZXIuc3RhdHVzID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgICAgIGlmIChpbm5lci5zdGF0dXMgPT09ICJkaXJ0eSIpCiAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICAgIHJldHVybiBleGVjdXRlUmVmaW5lbWVudChpbm5lci52YWx1ZSkudGhlbigoKSA9PiB7CiAgICAgICAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBpbm5lci52YWx1ZSB9OwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoZWZmZWN0LnR5cGUgPT09ICJ0cmFuc2Zvcm0iKSB7CiAgICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMgPT09IGZhbHNlKSB7CiAgICAgICAgICBjb25zdCBiYXNlID0gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAoIWlzVmFsaWQoYmFzZSkpCiAgICAgICAgICAgIHJldHVybiBiYXNlOwogICAgICAgICAgY29uc3QgcmVzdWx0ID0gZWZmZWN0LnRyYW5zZm9ybShiYXNlLnZhbHVlLCBjaGVja0N0eCk7CiAgICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgUHJvbWlzZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFzeW5jaHJvbm91cyB0cmFuc2Zvcm0gZW5jb3VudGVyZWQgZHVyaW5nIHN5bmNocm9ub3VzIHBhcnNlIG9wZXJhdGlvbi4gVXNlIC5wYXJzZUFzeW5jIGluc3RlYWQuYCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IHJlc3VsdCB9OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VBc3luYyh7IGRhdGE6IGN0eC5kYXRhLCBwYXRoOiBjdHgucGF0aCwgcGFyZW50OiBjdHggfSkudGhlbigoYmFzZSkgPT4gewogICAgICAgICAgICBpZiAoIWlzVmFsaWQoYmFzZSkpCiAgICAgICAgICAgICAgcmV0dXJuIGJhc2U7CiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZWZmZWN0LnRyYW5zZm9ybShiYXNlLnZhbHVlLCBjaGVja0N0eCkpLnRoZW4oKHJlc3VsdCkgPT4gKHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiByZXN1bHQgfSkpOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoZWZmZWN0KTsKICAgIH0KICB9CiAgWm9kRWZmZWN0cy5jcmVhdGUgPSAoc2NoZW1hLCBlZmZlY3QsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RFZmZlY3RzKHsKICAgICAgc2NoZW1hLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMsCiAgICAgIGVmZmVjdCwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIFpvZEVmZmVjdHMuY3JlYXRlV2l0aFByZXByb2Nlc3MgPSAocHJlcHJvY2Vzcywgc2NoZW1hLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kRWZmZWN0cyh7CiAgICAgIHNjaGVtYSwKICAgICAgZWZmZWN0OiB7IHR5cGU6ICJwcmVwcm9jZXNzIiwgdHJhbnNmb3JtOiBwcmVwcm9jZXNzIH0sCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRWZmZWN0cywKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE9wdGlvbmFsIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS51bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gT0sodm9pZCAwKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZS5fcGFyc2UoaW5wdXQpOwogICAgfQogICAgdW53cmFwKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZTsKICAgIH0KICB9CiAgWm9kT3B0aW9uYWwuY3JlYXRlID0gKHR5cGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RPcHRpb25hbCh7CiAgICAgIGlubmVyVHlwZTogdHlwZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPcHRpb25hbCwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE51bGxhYmxlIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS5udWxsKSB7CiAgICAgICAgcmV0dXJuIE9LKG51bGwpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLl9kZWYuaW5uZXJUeXBlLl9wYXJzZShpbnB1dCk7CiAgICB9CiAgICB1bndyYXAoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYuaW5uZXJUeXBlOwogICAgfQogIH0KICBab2ROdWxsYWJsZS5jcmVhdGUgPSAodHlwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE51bGxhYmxlKHsKICAgICAgaW5uZXJUeXBlOiB0eXBlLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE51bGxhYmxlLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kRGVmYXVsdCBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBsZXQgZGF0YSA9IGN0eC5kYXRhOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgPT09IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkKSB7CiAgICAgICAgZGF0YSA9IHRoaXMuX2RlZi5kZWZhdWx0VmFsdWUoKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZS5fcGFyc2UoewogICAgICAgIGRhdGEsCiAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgcGFyZW50OiBjdHgKICAgICAgfSk7CiAgICB9CiAgICByZW1vdmVEZWZhdWx0KCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZTsKICAgIH0KICB9CiAgWm9kRGVmYXVsdC5jcmVhdGUgPSAodHlwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZERlZmF1bHQoewogICAgICBpbm5lclR5cGU6IHR5cGUsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRGVmYXVsdCwKICAgICAgZGVmYXVsdFZhbHVlOiB0eXBlb2YgcGFyYW1zLmRlZmF1bHQgPT09ICJmdW5jdGlvbiIgPyBwYXJhbXMuZGVmYXVsdCA6ICgpID0+IHBhcmFtcy5kZWZhdWx0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kQ2F0Y2ggZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgY29uc3QgbmV3Q3R4ID0gewogICAgICAgIC4uLmN0eCwKICAgICAgICBjb21tb246IHsKICAgICAgICAgIC4uLmN0eC5jb21tb24sCiAgICAgICAgICBpc3N1ZXM6IFtdCiAgICAgICAgfQogICAgICB9OwogICAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9kZWYuaW5uZXJUeXBlLl9wYXJzZSh7CiAgICAgICAgZGF0YTogbmV3Q3R4LmRhdGEsCiAgICAgICAgcGF0aDogbmV3Q3R4LnBhdGgsCiAgICAgICAgcGFyZW50OiB7CiAgICAgICAgICAuLi5uZXdDdHgKICAgICAgICB9CiAgICAgIH0pOwogICAgICBpZiAoaXNBc3luYyhyZXN1bHQpKSB7CiAgICAgICAgcmV0dXJuIHJlc3VsdC50aGVuKChyZXN1bHQyKSA9PiB7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBzdGF0dXM6ICJ2YWxpZCIsCiAgICAgICAgICAgIHZhbHVlOiByZXN1bHQyLnN0YXR1cyA9PT0gInZhbGlkIiA/IHJlc3VsdDIudmFsdWUgOiB0aGlzLl9kZWYuY2F0Y2hWYWx1ZSh7CiAgICAgICAgICAgICAgZ2V0IGVycm9yKCkgewogICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBab2RFcnJvcihuZXdDdHguY29tbW9uLmlzc3Vlcyk7CiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICBpbnB1dDogbmV3Q3R4LmRhdGEKICAgICAgICAgICAgfSkKICAgICAgICAgIH07CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHN0YXR1czogInZhbGlkIiwKICAgICAgICAgIHZhbHVlOiByZXN1bHQuc3RhdHVzID09PSAidmFsaWQiID8gcmVzdWx0LnZhbHVlIDogdGhpcy5fZGVmLmNhdGNoVmFsdWUoewogICAgICAgICAgICBnZXQgZXJyb3IoKSB7CiAgICAgICAgICAgICAgcmV0dXJuIG5ldyBab2RFcnJvcihuZXdDdHguY29tbW9uLmlzc3Vlcyk7CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGlucHV0OiBuZXdDdHguZGF0YQogICAgICAgICAgfSkKICAgICAgICB9OwogICAgICB9CiAgICB9CiAgICByZW1vdmVDYXRjaCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5pbm5lclR5cGU7CiAgICB9CiAgfQogIFpvZENhdGNoLmNyZWF0ZSA9ICh0eXBlLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kQ2F0Y2goewogICAgICBpbm5lclR5cGU6IHR5cGUsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kQ2F0Y2gsCiAgICAgIGNhdGNoVmFsdWU6IHR5cGVvZiBwYXJhbXMuY2F0Y2ggPT09ICJmdW5jdGlvbiIgPyBwYXJhbXMuY2F0Y2ggOiAoKSA9PiBwYXJhbXMuY2F0Y2gsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2ROYU4gZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm5hbikgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5uYW4sCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6ICJ2YWxpZCIsIHZhbHVlOiBpbnB1dC5kYXRhIH07CiAgICB9CiAgfQogIFpvZE5hTi5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE5hTih7CiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kTmFOLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY29uc3QgQlJBTkQgPSBTeW1ib2woInpvZF9icmFuZCIpOwogIGNsYXNzIFpvZEJyYW5kZWQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgY29uc3QgZGF0YSA9IGN0eC5kYXRhOwogICAgICByZXR1cm4gdGhpcy5fZGVmLnR5cGUuX3BhcnNlKHsKICAgICAgICBkYXRhLAogICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgIHBhcmVudDogY3R4CiAgICAgIH0pOwogICAgfQogICAgdW53cmFwKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnR5cGU7CiAgICB9CiAgfQogIGNsYXNzIFpvZFBpcGVsaW5lIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICBjb25zdCBoYW5kbGVBc3luYyA9IGFzeW5jICgpID0+IHsKICAgICAgICAgIGNvbnN0IGluUmVzdWx0ID0gYXdhaXQgdGhpcy5fZGVmLmluLl9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAoaW5SZXN1bHQuc3RhdHVzID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgaWYgKGluUmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikgewogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgICAgcmV0dXJuIERJUlRZKGluUmVzdWx0LnZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kZWYub3V0Ll9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgICBkYXRhOiBpblJlc3VsdC52YWx1ZSwKICAgICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHJldHVybiBoYW5kbGVBc3luYygpOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGluUmVzdWx0ID0gdGhpcy5fZGVmLmluLl9wYXJzZVN5bmMoewogICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgfSk7CiAgICAgICAgaWYgKGluUmVzdWx0LnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgaWYgKGluUmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikgewogICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBzdGF0dXM6ICJkaXJ0eSIsCiAgICAgICAgICAgIHZhbHVlOiBpblJlc3VsdC52YWx1ZQogICAgICAgICAgfTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi5vdXQuX3BhcnNlU3luYyh7CiAgICAgICAgICAgIGRhdGE6IGluUmVzdWx0LnZhbHVlLAogICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgc3RhdGljIGNyZWF0ZShhMiwgYikgewogICAgICByZXR1cm4gbmV3IFpvZFBpcGVsaW5lKHsKICAgICAgICBpbjogYTIsCiAgICAgICAgb3V0OiBiLAogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kUGlwZWxpbmUKICAgICAgfSk7CiAgICB9CiAgfQogIGNsYXNzIFpvZFJlYWRvbmx5IGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fZGVmLmlubmVyVHlwZS5fcGFyc2UoaW5wdXQpOwogICAgICBjb25zdCBmcmVlemUgPSAoZGF0YSkgPT4gewogICAgICAgIGlmIChpc1ZhbGlkKGRhdGEpKSB7CiAgICAgICAgICBkYXRhLnZhbHVlID0gT2JqZWN0LmZyZWV6ZShkYXRhLnZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGRhdGE7CiAgICAgIH07CiAgICAgIHJldHVybiBpc0FzeW5jKHJlc3VsdCkgPyByZXN1bHQudGhlbigoZGF0YSkgPT4gZnJlZXplKGRhdGEpKSA6IGZyZWV6ZShyZXN1bHQpOwogICAgfQogICAgdW53cmFwKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZTsKICAgIH0KICB9CiAgWm9kUmVhZG9ubHkuY3JlYXRlID0gKHR5cGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RSZWFkb25seSh7CiAgICAgIGlubmVyVHlwZTogdHlwZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RSZWFkb25seSwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGZ1bmN0aW9uIGN1c3RvbShjaGVjaywgcGFyYW1zID0ge30sIGZhdGFsKSB7CiAgICBpZiAoY2hlY2spCiAgICAgIHJldHVybiBab2RBbnkuY3JlYXRlKCkuc3VwZXJSZWZpbmUoKGRhdGEsIGN0eCkgPT4gewogICAgICAgIHZhciBfYSwgX2I7CiAgICAgICAgaWYgKCFjaGVjayhkYXRhKSkgewogICAgICAgICAgY29uc3QgcCA9IHR5cGVvZiBwYXJhbXMgPT09ICJmdW5jdGlvbiIgPyBwYXJhbXMoZGF0YSkgOiB0eXBlb2YgcGFyYW1zID09PSAic3RyaW5nIiA/IHsgbWVzc2FnZTogcGFyYW1zIH0gOiBwYXJhbXM7CiAgICAgICAgICBjb25zdCBfZmF0YWwgPSAoX2IgPSAoX2EgPSBwLmZhdGFsKSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiBmYXRhbCkgIT09IG51bGwgJiYgX2IgIT09IHZvaWQgMCA/IF9iIDogdHJ1ZTsKICAgICAgICAgIGNvbnN0IHAyID0gdHlwZW9mIHAgPT09ICJzdHJpbmciID8geyBtZXNzYWdlOiBwIH0gOiBwOwogICAgICAgICAgY3R4LmFkZElzc3VlKHsgY29kZTogImN1c3RvbSIsIC4uLnAyLCBmYXRhbDogX2ZhdGFsIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICByZXR1cm4gWm9kQW55LmNyZWF0ZSgpOwogIH0KICBjb25zdCBsYXRlID0gewogICAgb2JqZWN0OiBab2RPYmplY3QubGF6eWNyZWF0ZQogIH07CiAgdmFyIFpvZEZpcnN0UGFydHlUeXBlS2luZDsKICAoZnVuY3Rpb24oWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMikgewogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kU3RyaW5nIl0gPSAiWm9kU3RyaW5nIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE51bWJlciJdID0gIlpvZE51bWJlciI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2ROYU4iXSA9ICJab2ROYU4iOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQmlnSW50Il0gPSAiWm9kQmlnSW50IjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZEJvb2xlYW4iXSA9ICJab2RCb29sZWFuIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZERhdGUiXSA9ICJab2REYXRlIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFN5bWJvbCJdID0gIlpvZFN5bWJvbCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RVbmRlZmluZWQiXSA9ICJab2RVbmRlZmluZWQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kTnVsbCJdID0gIlpvZE51bGwiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQW55Il0gPSAiWm9kQW55IjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFVua25vd24iXSA9ICJab2RVbmtub3duIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE5ldmVyIl0gPSAiWm9kTmV2ZXIiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kVm9pZCJdID0gIlpvZFZvaWQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQXJyYXkiXSA9ICJab2RBcnJheSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RPYmplY3QiXSA9ICJab2RPYmplY3QiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kVW5pb24iXSA9ICJab2RVbmlvbiI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2REaXNjcmltaW5hdGVkVW5pb24iXSA9ICJab2REaXNjcmltaW5hdGVkVW5pb24iOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kSW50ZXJzZWN0aW9uIl0gPSAiWm9kSW50ZXJzZWN0aW9uIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFR1cGxlIl0gPSAiWm9kVHVwbGUiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kUmVjb3JkIl0gPSAiWm9kUmVjb3JkIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE1hcCJdID0gIlpvZE1hcCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RTZXQiXSA9ICJab2RTZXQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kRnVuY3Rpb24iXSA9ICJab2RGdW5jdGlvbiI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RMYXp5Il0gPSAiWm9kTGF6eSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RMaXRlcmFsIl0gPSAiWm9kTGl0ZXJhbCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RFbnVtIl0gPSAiWm9kRW51bSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RFZmZlY3RzIl0gPSAiWm9kRWZmZWN0cyI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2ROYXRpdmVFbnVtIl0gPSAiWm9kTmF0aXZlRW51bSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RPcHRpb25hbCJdID0gIlpvZE9wdGlvbmFsIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE51bGxhYmxlIl0gPSAiWm9kTnVsbGFibGUiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kRGVmYXVsdCJdID0gIlpvZERlZmF1bHQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQ2F0Y2giXSA9ICJab2RDYXRjaCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RQcm9taXNlIl0gPSAiWm9kUHJvbWlzZSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RCcmFuZGVkIl0gPSAiWm9kQnJhbmRlZCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RQaXBlbGluZSJdID0gIlpvZFBpcGVsaW5lIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFJlYWRvbmx5Il0gPSAiWm9kUmVhZG9ubHkiOwogIH0pKFpvZEZpcnN0UGFydHlUeXBlS2luZCB8fCAoWm9kRmlyc3RQYXJ0eVR5cGVLaW5kID0ge30pKTsKICBjb25zdCBpbnN0YW5jZU9mVHlwZSA9IChjbHMsIHBhcmFtcyA9IHsKICAgIG1lc3NhZ2U6IGBJbnB1dCBub3QgaW5zdGFuY2Ugb2YgJHtjbHMubmFtZX1gCiAgfSkgPT4gY3VzdG9tKChkYXRhKSA9PiBkYXRhIGluc3RhbmNlb2YgY2xzLCBwYXJhbXMpOwogIGNvbnN0IHN0cmluZ1R5cGUgPSBab2RTdHJpbmcuY3JlYXRlOwogIGNvbnN0IG51bWJlclR5cGUgPSBab2ROdW1iZXIuY3JlYXRlOwogIGNvbnN0IG5hblR5cGUgPSBab2ROYU4uY3JlYXRlOwogIGNvbnN0IGJpZ0ludFR5cGUgPSBab2RCaWdJbnQuY3JlYXRlOwogIGNvbnN0IGJvb2xlYW5UeXBlID0gWm9kQm9vbGVhbi5jcmVhdGU7CiAgY29uc3QgZGF0ZVR5cGUgPSBab2REYXRlLmNyZWF0ZTsKICBjb25zdCBzeW1ib2xUeXBlID0gWm9kU3ltYm9sLmNyZWF0ZTsKICBjb25zdCB1bmRlZmluZWRUeXBlID0gWm9kVW5kZWZpbmVkLmNyZWF0ZTsKICBjb25zdCBudWxsVHlwZSA9IFpvZE51bGwuY3JlYXRlOwogIGNvbnN0IGFueVR5cGUgPSBab2RBbnkuY3JlYXRlOwogIGNvbnN0IHVua25vd25UeXBlID0gWm9kVW5rbm93bi5jcmVhdGU7CiAgY29uc3QgbmV2ZXJUeXBlID0gWm9kTmV2ZXIuY3JlYXRlOwogIGNvbnN0IHZvaWRUeXBlID0gWm9kVm9pZC5jcmVhdGU7CiAgY29uc3QgYXJyYXlUeXBlID0gWm9kQXJyYXkuY3JlYXRlOwogIGNvbnN0IG9iamVjdFR5cGUgPSBab2RPYmplY3QuY3JlYXRlOwogIGNvbnN0IHN0cmljdE9iamVjdFR5cGUgPSBab2RPYmplY3Quc3RyaWN0Q3JlYXRlOwogIGNvbnN0IHVuaW9uVHlwZSA9IFpvZFVuaW9uLmNyZWF0ZTsKICBjb25zdCBkaXNjcmltaW5hdGVkVW5pb25UeXBlID0gWm9kRGlzY3JpbWluYXRlZFVuaW9uLmNyZWF0ZTsKICBjb25zdCBpbnRlcnNlY3Rpb25UeXBlID0gWm9kSW50ZXJzZWN0aW9uLmNyZWF0ZTsKICBjb25zdCB0dXBsZVR5cGUgPSBab2RUdXBsZS5jcmVhdGU7CiAgY29uc3QgcmVjb3JkVHlwZSA9IFpvZFJlY29yZC5jcmVhdGU7CiAgY29uc3QgbWFwVHlwZSA9IFpvZE1hcC5jcmVhdGU7CiAgY29uc3Qgc2V0VHlwZSA9IFpvZFNldC5jcmVhdGU7CiAgY29uc3QgZnVuY3Rpb25UeXBlID0gWm9kRnVuY3Rpb24uY3JlYXRlOwogIGNvbnN0IGxhenlUeXBlID0gWm9kTGF6eS5jcmVhdGU7CiAgY29uc3QgbGl0ZXJhbFR5cGUgPSBab2RMaXRlcmFsLmNyZWF0ZTsKICBjb25zdCBlbnVtVHlwZSA9IFpvZEVudW0uY3JlYXRlOwogIGNvbnN0IG5hdGl2ZUVudW1UeXBlID0gWm9kTmF0aXZlRW51bS5jcmVhdGU7CiAgY29uc3QgcHJvbWlzZVR5cGUgPSBab2RQcm9taXNlLmNyZWF0ZTsKICBjb25zdCBlZmZlY3RzVHlwZSA9IFpvZEVmZmVjdHMuY3JlYXRlOwogIGNvbnN0IG9wdGlvbmFsVHlwZSA9IFpvZE9wdGlvbmFsLmNyZWF0ZTsKICBjb25zdCBudWxsYWJsZVR5cGUgPSBab2ROdWxsYWJsZS5jcmVhdGU7CiAgY29uc3QgcHJlcHJvY2Vzc1R5cGUgPSBab2RFZmZlY3RzLmNyZWF0ZVdpdGhQcmVwcm9jZXNzOwogIGNvbnN0IHBpcGVsaW5lVHlwZSA9IFpvZFBpcGVsaW5lLmNyZWF0ZTsKICBjb25zdCBvc3RyaW5nID0gKCkgPT4gc3RyaW5nVHlwZSgpLm9wdGlvbmFsKCk7CiAgY29uc3Qgb251bWJlciA9ICgpID0+IG51bWJlclR5cGUoKS5vcHRpb25hbCgpOwogIGNvbnN0IG9ib29sZWFuID0gKCkgPT4gYm9vbGVhblR5cGUoKS5vcHRpb25hbCgpOwogIGNvbnN0IGNvZXJjZSA9IHsKICAgIHN0cmluZzogKGFyZykgPT4gWm9kU3RyaW5nLmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pLAogICAgbnVtYmVyOiAoYXJnKSA9PiBab2ROdW1iZXIuY3JlYXRlKHsgLi4uYXJnLCBjb2VyY2U6IHRydWUgfSksCiAgICBib29sZWFuOiAoYXJnKSA9PiBab2RCb29sZWFuLmNyZWF0ZSh7CiAgICAgIC4uLmFyZywKICAgICAgY29lcmNlOiB0cnVlCiAgICB9KSwKICAgIGJpZ2ludDogKGFyZykgPT4gWm9kQmlnSW50LmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pLAogICAgZGF0ZTogKGFyZykgPT4gWm9kRGF0ZS5jcmVhdGUoeyAuLi5hcmcsIGNvZXJjZTogdHJ1ZSB9KQogIH07CiAgY29uc3QgTkVWRVIgPSBJTlZBTElEOwogIHZhciB6JDEgPSAvKiBAX19QVVJFX18gKi8gT2JqZWN0LmZyZWV6ZSh7CiAgICBfX3Byb3RvX186IG51bGwsCiAgICBkZWZhdWx0RXJyb3JNYXA6IGVycm9yTWFwLAogICAgc2V0RXJyb3JNYXAsCiAgICBnZXRFcnJvck1hcCwKICAgIG1ha2VJc3N1ZSwKICAgIEVNUFRZX1BBVEgsCiAgICBhZGRJc3N1ZVRvQ29udGV4dCwKICAgIFBhcnNlU3RhdHVzLAogICAgSU5WQUxJRCwKICAgIERJUlRZLAogICAgT0ssCiAgICBpc0Fib3J0ZWQsCiAgICBpc0RpcnR5LAogICAgaXNWYWxpZCwKICAgIGlzQXN5bmMsCiAgICBnZXQgdXRpbCgpIHsKICAgICAgcmV0dXJuIHV0aWw7CiAgICB9LAogICAgZ2V0IG9iamVjdFV0aWwoKSB7CiAgICAgIHJldHVybiBvYmplY3RVdGlsOwogICAgfSwKICAgIFpvZFBhcnNlZFR5cGUsCiAgICBnZXRQYXJzZWRUeXBlLAogICAgWm9kVHlwZSwKICAgIGRhdGV0aW1lUmVnZXgsCiAgICBab2RTdHJpbmcsCiAgICBab2ROdW1iZXIsCiAgICBab2RCaWdJbnQsCiAgICBab2RCb29sZWFuLAogICAgWm9kRGF0ZSwKICAgIFpvZFN5bWJvbCwKICAgIFpvZFVuZGVmaW5lZCwKICAgIFpvZE51bGwsCiAgICBab2RBbnksCiAgICBab2RVbmtub3duLAogICAgWm9kTmV2ZXIsCiAgICBab2RWb2lkLAogICAgWm9kQXJyYXksCiAgICBab2RPYmplY3QsCiAgICBab2RVbmlvbiwKICAgIFpvZERpc2NyaW1pbmF0ZWRVbmlvbiwKICAgIFpvZEludGVyc2VjdGlvbiwKICAgIFpvZFR1cGxlLAogICAgWm9kUmVjb3JkLAogICAgWm9kTWFwLAogICAgWm9kU2V0LAogICAgWm9kRnVuY3Rpb24sCiAgICBab2RMYXp5LAogICAgWm9kTGl0ZXJhbCwKICAgIFpvZEVudW0sCiAgICBab2ROYXRpdmVFbnVtLAogICAgWm9kUHJvbWlzZSwKICAgIFpvZEVmZmVjdHMsCiAgICBab2RUcmFuc2Zvcm1lcjogWm9kRWZmZWN0cywKICAgIFpvZE9wdGlvbmFsLAogICAgWm9kTnVsbGFibGUsCiAgICBab2REZWZhdWx0LAogICAgWm9kQ2F0Y2gsCiAgICBab2ROYU4sCiAgICBCUkFORCwKICAgIFpvZEJyYW5kZWQsCiAgICBab2RQaXBlbGluZSwKICAgIFpvZFJlYWRvbmx5LAogICAgY3VzdG9tLAogICAgU2NoZW1hOiBab2RUeXBlLAogICAgWm9kU2NoZW1hOiBab2RUeXBlLAogICAgbGF0ZSwKICAgIGdldCBab2RGaXJzdFBhcnR5VHlwZUtpbmQoKSB7CiAgICAgIHJldHVybiBab2RGaXJzdFBhcnR5VHlwZUtpbmQ7CiAgICB9LAogICAgY29lcmNlLAogICAgYW55OiBhbnlUeXBlLAogICAgYXJyYXk6IGFycmF5VHlwZSwKICAgIGJpZ2ludDogYmlnSW50VHlwZSwKICAgIGJvb2xlYW46IGJvb2xlYW5UeXBlLAogICAgZGF0ZTogZGF0ZVR5cGUsCiAgICBkaXNjcmltaW5hdGVkVW5pb246IGRpc2NyaW1pbmF0ZWRVbmlvblR5cGUsCiAgICBlZmZlY3Q6IGVmZmVjdHNUeXBlLAogICAgImVudW0iOiBlbnVtVHlwZSwKICAgICJmdW5jdGlvbiI6IGZ1bmN0aW9uVHlwZSwKICAgICJpbnN0YW5jZW9mIjogaW5zdGFuY2VPZlR5cGUsCiAgICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvblR5cGUsCiAgICBsYXp5OiBsYXp5VHlwZSwKICAgIGxpdGVyYWw6IGxpdGVyYWxUeXBlLAogICAgbWFwOiBtYXBUeXBlLAogICAgbmFuOiBuYW5UeXBlLAogICAgbmF0aXZlRW51bTogbmF0aXZlRW51bVR5cGUsCiAgICBuZXZlcjogbmV2ZXJUeXBlLAogICAgIm51bGwiOiBudWxsVHlwZSwKICAgIG51bGxhYmxlOiBudWxsYWJsZVR5cGUsCiAgICBudW1iZXI6IG51bWJlclR5cGUsCiAgICBvYmplY3Q6IG9iamVjdFR5cGUsCiAgICBvYm9vbGVhbiwKICAgIG9udW1iZXIsCiAgICBvcHRpb25hbDogb3B0aW9uYWxUeXBlLAogICAgb3N0cmluZywKICAgIHBpcGVsaW5lOiBwaXBlbGluZVR5cGUsCiAgICBwcmVwcm9jZXNzOiBwcmVwcm9jZXNzVHlwZSwKICAgIHByb21pc2U6IHByb21pc2VUeXBlLAogICAgcmVjb3JkOiByZWNvcmRUeXBlLAogICAgc2V0OiBzZXRUeXBlLAogICAgc3RyaWN0T2JqZWN0OiBzdHJpY3RPYmplY3RUeXBlLAogICAgc3RyaW5nOiBzdHJpbmdUeXBlLAogICAgc3ltYm9sOiBzeW1ib2xUeXBlLAogICAgdHJhbnNmb3JtZXI6IGVmZmVjdHNUeXBlLAogICAgdHVwbGU6IHR1cGxlVHlwZSwKICAgICJ1bmRlZmluZWQiOiB1bmRlZmluZWRUeXBlLAogICAgdW5pb246IHVuaW9uVHlwZSwKICAgIHVua25vd246IHVua25vd25UeXBlLAogICAgInZvaWQiOiB2b2lkVHlwZSwKICAgIE5FVkVSLAogICAgWm9kSXNzdWVDb2RlLAogICAgcXVvdGVsZXNzSnNvbiwKICAgIFpvZEVycm9yCiAgfSk7CiAgeiQxLm9iamVjdCh7CiAgICBudWNsZW90aWRlU2VxdWVuY2VzOiB6JDEuYXJyYXkoCiAgICAgIHokMS5vYmplY3QoewogICAgICAgIG5hbWU6IHokMS5zdHJpbmcoKSwKICAgICAgICBzZXF1ZW5jZTogeiQxLnN0cmluZygpCiAgICAgIH0pCiAgICApLAogICAgZ2VuZXM6IHokMS5hcnJheSgKICAgICAgeiQxLm9iamVjdCh7CiAgICAgICAgbmFtZTogeiQxLnN0cmluZygpLAogICAgICAgIHNlcXVlbmNlOiB6JDEuc3RyaW5nKCkKICAgICAgfSkKICAgICkKICB9KTsKICBjb25zdCBvcmRlckJ5VHlwZSA9IHokMS5lbnVtKFsiYXNjZW5kaW5nIiwgImRlc2NlbmRpbmciXSk7CiAgY29uc3Qgb3JkZXJCeSA9IHokMS5vYmplY3QoewogICAgZmllbGQ6IHokMS5zdHJpbmcoKSwKICAgIHR5cGU6IG9yZGVyQnlUeXBlCiAgfSk7CiAgY29uc3QgbGFwaXNCYXNlUmVxdWVzdCA9IHokMS5vYmplY3QoewogICAgbGltaXQ6IHokMS5udW1iZXIoKS5vcHRpb25hbCgpLAogICAgb2Zmc2V0OiB6JDEubnVtYmVyKCkub3B0aW9uYWwoKSwKICAgIGZpZWxkczogeiQxLmFycmF5KHokMS5zdHJpbmcoKSkub3B0aW9uYWwoKSwKICAgIG9yZGVyQnk6IHokMS5hcnJheShvcmRlckJ5KS5vcHRpb25hbCgpCiAgfSkuY2F0Y2hhbGwoeiQxLnVuaW9uKFt6JDEuYm9vbGVhbigpLCB6JDEudW5kZWZpbmVkKCksIHokMS5zdHJpbmcoKSwgeiQxLm51bWJlcigpLCB6JDEubnVsbCgpLCB6JDEuYXJyYXkoeiQxLnN0cmluZygpKV0pKTsKICBsYXBpc0Jhc2VSZXF1ZXN0LmV4dGVuZCh7IG1pblByb3BvcnRpb246IHokMS5udW1iZXIoKS5vcHRpb25hbCgpIH0pOwogIGNvbnN0IG11dGF0aW9uUHJvcG9ydGlvbkNvdW50ID0geiQxLm9iamVjdCh7CiAgICBtdXRhdGlvbjogeiQxLnN0cmluZygpLAogICAgcHJvcG9ydGlvbjogeiQxLm51bWJlcigpLAogICAgY291bnQ6IHokMS5udW1iZXIoKSwKICAgIHNlcXVlbmNlTmFtZTogeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udWxsKCldKSwKICAgIG11dGF0aW9uRnJvbTogeiQxLnN0cmluZygpLAogICAgbXV0YXRpb25UbzogeiQxLnN0cmluZygpLAogICAgcG9zaXRpb246IHokMS5udW1iZXIoKQogIH0pOwogIGNvbnN0IG11dGF0aW9uc1Jlc3BvbnNlID0gbWFrZUxhcGlzUmVzcG9uc2UoeiQxLmFycmF5KG11dGF0aW9uUHJvcG9ydGlvbkNvdW50KSk7CiAgY29uc3QgaW5zZXJ0aW9uQ291bnQgPSB6JDEub2JqZWN0KHsKICAgIGluc2VydGlvbjogeiQxLnN0cmluZygpLAogICAgY291bnQ6IHokMS5udW1iZXIoKSwKICAgIGluc2VydGVkU3ltYm9sczogeiQxLnN0cmluZygpLAogICAgcG9zaXRpb246IHokMS5udW1iZXIoKSwKICAgIHNlcXVlbmNlTmFtZTogeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udWxsKCldKQogIH0pOwogIG1ha2VMYXBpc1Jlc3BvbnNlKHokMS5hcnJheShpbnNlcnRpb25Db3VudCkpOwogIGNvbnN0IGFnZ3JlZ2F0ZWRJdGVtID0geiQxLm9iamVjdCh7IGNvdW50OiB6JDEubnVtYmVyKCkgfSkuY2F0Y2hhbGwoeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udW1iZXIoKSwgeiQxLm51bGwoKV0pKTsKICBjb25zdCBhZ2dyZWdhdGVkUmVzcG9uc2UgPSBtYWtlTGFwaXNSZXNwb25zZSh6JDEuYXJyYXkoYWdncmVnYXRlZEl0ZW0pKTsKICBmdW5jdGlvbiBtYWtlTGFwaXNSZXNwb25zZShkYXRhKSB7CiAgICByZXR1cm4geiQxLm9iamVjdCh7CiAgICAgIGRhdGEKICAgIH0pOwogIH0KICBjb25zdCBwcm9ibGVtRGV0YWlsID0geiQxLm9iamVjdCh7CiAgICB0aXRsZTogeiQxLnN0cmluZygpLm9wdGlvbmFsKCksCiAgICBzdGF0dXM6IHokMS5udW1iZXIoKSwKICAgIGRldGFpbDogeiQxLnN0cmluZygpLm9wdGlvbmFsKCksCiAgICB0eXBlOiB6JDEuc3RyaW5nKCksCiAgICBpbnN0YW5jZTogeiQxLnN0cmluZygpLm9wdGlvbmFsKCkKICB9KTsKICBjb25zdCBsYXBpc0Vycm9yID0geiQxLm9iamVjdCh7CiAgICBlcnJvcjogcHJvYmxlbURldGFpbAogIH0pOwogIGNsYXNzIFVua25vd25MYXBpc0Vycm9yIGV4dGVuZHMgRXJyb3IgewogICAgY29uc3RydWN0b3IobWVzc2FnZSwgc3RhdHVzLCByZXF1ZXN0ZWREYXRhKSB7CiAgICAgIHN1cGVyKG1lc3NhZ2UpOwogICAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgICAgdGhpcy5yZXF1ZXN0ZWREYXRhID0gcmVxdWVzdGVkRGF0YTsKICAgICAgdGhpcy5uYW1lID0gIlVua25vd25MYXBpc0Vycm9yIjsKICAgIH0KICB9CiAgY2xhc3MgTGFwaXNFcnJvciBleHRlbmRzIEVycm9yIHsKICAgIGNvbnN0cnVjdG9yKG1lc3NhZ2UsIHN0YXR1cywgcHJvYmxlbURldGFpbDIsIHJlcXVlc3RlZERhdGEpIHsKICAgICAgc3VwZXIobWVzc2FnZSk7CiAgICAgIHRoaXMuc3RhdHVzID0gc3RhdHVzOwogICAgICB0aGlzLnByb2JsZW1EZXRhaWwgPSBwcm9ibGVtRGV0YWlsMjsKICAgICAgdGhpcy5yZXF1ZXN0ZWREYXRhID0gcmVxdWVzdGVkRGF0YTsKICAgICAgdGhpcy5uYW1lID0gIkxhcGlzRXJyb3IiOwogICAgfQogIH0KICBhc3luYyBmdW5jdGlvbiBmZXRjaEFnZ3JlZ2F0ZWQobGFwaXNVcmwsIGJvZHksIHNpZ25hbCkgewogICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChhZ2dyZWdhdGVkRW5kcG9pbnQobGFwaXNVcmwpLCB7CiAgICAgIG1ldGhvZDogIlBPU1QiLAogICAgICBoZWFkZXJzOiB7CiAgICAgICAgIkNvbnRlbnQtVHlwZSI6ICJhcHBsaWNhdGlvbi9qc29uIgogICAgICB9LAogICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShib2R5KSwKICAgICAgc2lnbmFsCiAgICB9KTsKICAgIGF3YWl0IGhhbmRsZUVycm9ycyhyZXNwb25zZSwgImFnZ3JlZ2F0ZWQgZGF0YSIpOwogICAgcmV0dXJuIGFnZ3JlZ2F0ZWRSZXNwb25zZS5wYXJzZShhd2FpdCByZXNwb25zZS5qc29uKCkpOwogIH0KICBhc3luYyBmdW5jdGlvbiBmZXRjaFN1YnN0aXR1dGlvbnNPckRlbGV0aW9ucyhsYXBpc1VybCwgYm9keSwgc2VxdWVuY2VUeXBlLCBzaWduYWwpIHsKICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goc3Vic3RpdHV0aW9uc09yRGVsZXRpb25zRW5kcG9pbnQobGFwaXNVcmwsIHNlcXVlbmNlVHlwZSksIHsKICAgICAgbWV0aG9kOiAiUE9TVCIsCiAgICAgIGhlYWRlcnM6IHsKICAgICAgICAiQ29udGVudC1UeXBlIjogImFwcGxpY2F0aW9uL2pzb24iCiAgICAgIH0sCiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KGJvZHkpLAogICAgICBzaWduYWwKICAgIH0pOwogICAgYXdhaXQgaGFuZGxlRXJyb3JzKHJlc3BvbnNlLCBgJHtzZXF1ZW5jZVR5cGV9IG11dGF0aW9uc2ApOwogICAgcmV0dXJuIG11dGF0aW9uc1Jlc3BvbnNlLnBhcnNlKGF3YWl0IHJlc3BvbnNlLmpzb24oKSk7CiAgfQogIGNvbnN0IGhhbmRsZUVycm9ycyA9IGFzeW5jIChyZXNwb25zZSwgcmVxdWVzdGVkRGF0YSkgPT4gewogICAgaWYgKCFyZXNwb25zZS5vaykgewogICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID49IDQwMCAmJiByZXNwb25zZS5zdGF0dXMgPCA1MDApIHsKICAgICAgICBjb25zdCBqc29uID0gYXdhaXQgcmVzcG9uc2UuanNvbigpOwogICAgICAgIGNvbnN0IGxhcGlzRXJyb3JSZXN1bHQgPSBsYXBpc0Vycm9yLnNhZmVQYXJzZShqc29uKTsKICAgICAgICBpZiAobGFwaXNFcnJvclJlc3VsdC5zdWNjZXNzKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTGFwaXNFcnJvcigKICAgICAgICAgICAgcmVzcG9uc2Uuc3RhdHVzVGV4dCArIGxhcGlzRXJyb3JSZXN1bHQuZGF0YS5lcnJvci5kZXRhaWwsCiAgICAgICAgICAgIHJlc3BvbnNlLnN0YXR1cywKICAgICAgICAgICAgbGFwaXNFcnJvclJlc3VsdC5kYXRhLmVycm9yLAogICAgICAgICAgICByZXF1ZXN0ZWREYXRhCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBwcm9ibGVtRGV0YWlsUmVzdWx0ID0gcHJvYmxlbURldGFpbC5zYWZlUGFyc2UoanNvbik7CiAgICAgICAgaWYgKHByb2JsZW1EZXRhaWxSZXN1bHQuc3VjY2VzcykgewogICAgICAgICAgdGhyb3cgbmV3IExhcGlzRXJyb3IoCiAgICAgICAgICAgIHJlc3BvbnNlLnN0YXR1c1RleHQgKyBwcm9ibGVtRGV0YWlsUmVzdWx0LmRhdGEuZGV0YWlsLAogICAgICAgICAgICByZXNwb25zZS5zdGF0dXMsCiAgICAgICAgICAgIHByb2JsZW1EZXRhaWxSZXN1bHQuZGF0YSwKICAgICAgICAgICAgcmVxdWVzdGVkRGF0YQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgdGhyb3cgbmV3IFVua25vd25MYXBpc0Vycm9yKAogICAgICAgICAgYCR7cmVzcG9uc2Uuc3RhdHVzVGV4dH06ICR7SlNPTi5zdHJpbmdpZnkoanNvbil9YCwKICAgICAgICAgIHJlc3BvbnNlLnN0YXR1cywKICAgICAgICAgIHJlcXVlc3RlZERhdGEKICAgICAgICApOwogICAgICB9CiAgICAgIHRocm93IG5ldyBVbmtub3duTGFwaXNFcnJvcihgJHtyZXNwb25zZS5zdGF0dXNUZXh0fTogJHtyZXNwb25zZS5zdGF0dXN9YCwgcmVzcG9uc2Uuc3RhdHVzLCByZXF1ZXN0ZWREYXRhKTsKICAgIH0KICB9OwogIGNvbnN0IGFnZ3JlZ2F0ZWRFbmRwb2ludCA9IChsYXBpc1VybCkgPT4gYCR7bGFwaXNVcmx9L3NhbXBsZS9hZ2dyZWdhdGVkYDsKICBjb25zdCBzdWJzdGl0dXRpb25zT3JEZWxldGlvbnNFbmRwb2ludCA9IChsYXBpc1VybCwgc2VxdWVuY2VUeXBlKSA9PiB7CiAgICByZXR1cm4gc2VxdWVuY2VUeXBlID09PSAiYW1pbm8gYWNpZCIgPyBgJHtsYXBpc1VybH0vc2FtcGxlL2FtaW5vQWNpZE11dGF0aW9uc2AgOiBgJHtsYXBpc1VybH0vc2FtcGxlL251Y2xlb3RpZGVNdXRhdGlvbnNgOwogIH07CiAgY2xhc3MgRmV0Y2hBZ2dyZWdhdGVkT3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoZmlsdGVyLCBmaWVsZHMgPSBbXSkgewogICAgICB0aGlzLmZpbHRlciA9IGZpbHRlcjsKICAgICAgdGhpcy5maWVsZHMgPSBmaWVsZHM7CiAgICB9CiAgICBhc3luYyBldmFsdWF0ZShsYXBpc1VybCwgc2lnbmFsKSB7CiAgICAgIGNvbnN0IGFnZ3JlZ2F0ZWRSZXNwb25zZTIgPSAoYXdhaXQgZmV0Y2hBZ2dyZWdhdGVkKAogICAgICAgIGxhcGlzVXJsLAogICAgICAgIHsKICAgICAgICAgIC4uLnRoaXMuZmlsdGVyLAogICAgICAgICAgZmllbGRzOiB0aGlzLmZpZWxkcwogICAgICAgIH0sCiAgICAgICAgc2lnbmFsCiAgICAgICkpLmRhdGE7CiAgICAgIGlmIChpc0ZpZWxkc0FycmF5V2l0aENvdW50KGFnZ3JlZ2F0ZWRSZXNwb25zZTIpKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGNvbnRlbnQ6IGFnZ3JlZ2F0ZWRSZXNwb25zZTIKICAgICAgICB9OwogICAgICB9CiAgICAgIHRocm93IG5ldyBFcnJvcigiQWdncmVnYXRlZCByZXNwb25zZSBkb2VzIG5vdCBoYXZlIGNvdW50Iik7CiAgICB9CiAgfQogIGZ1bmN0aW9uIGlzRmllbGRzQXJyYXlXaXRoQ291bnQoZGF0YSkgewogICAgcmV0dXJuIGRhdGEuZXZlcnkoKGl0ZW0pID0+IHR5cGVvZiBpdGVtID09PSAib2JqZWN0IiAmJiAiY291bnQiIGluIGl0ZW0gJiYgdHlwZW9mIGl0ZW0uY291bnQgPT09ICJudW1iZXIiKTsKICB9CiAgY2xhc3MgR3JvdXBCeU9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBmaWVsZCwgYWdncmVnYXRlKSB7CiAgICAgIHRoaXMuY2hpbGQgPSBjaGlsZDsKICAgICAgdGhpcy5maWVsZCA9IGZpZWxkOwogICAgICB0aGlzLmFnZ3JlZ2F0ZSA9IGFnZ3JlZ2F0ZTsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzLCBzaWduYWwpIHsKICAgICAgY29uc3QgY2hpbGRFdmFsdWF0ZWQgPSBhd2FpdCB0aGlzLmNoaWxkLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICBjb25zdCBncm91cGVkID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgZm9yIChjb25zdCByb3cgb2YgY2hpbGRFdmFsdWF0ZWQuY29udGVudCkgewogICAgICAgIGNvbnN0IGtleSA9IHJvd1t0aGlzLmZpZWxkXTsKICAgICAgICBpZiAoIWdyb3VwZWQuaGFzKGtleSkpIHsKICAgICAgICAgIGdyb3VwZWQuc2V0KGtleSwgW10pOwogICAgICAgIH0KICAgICAgICBncm91cGVkLmdldChrZXkpLnB1c2gocm93KTsKICAgICAgfQogICAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXkoKTsKICAgICAgZm9yIChjb25zdCBbLCB2YWx1ZXNdIG9mIGdyb3VwZWQpIHsKICAgICAgICByZXN1bHQucHVzaCh0aGlzLmFnZ3JlZ2F0ZSh2YWx1ZXMpKTsKICAgICAgfQogICAgICByZXR1cm4gewogICAgICAgIGNvbnRlbnQ6IHJlc3VsdAogICAgICB9OwogICAgfQogIH0KICBjbGFzcyBHcm91cEJ5QW5kU3VtT3BlcmF0b3IgZXh0ZW5kcyBHcm91cEJ5T3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoY2hpbGQsIGdyb3VwQnlGaWVsZCwgc3VtRmllbGQpIHsKICAgICAgc3VwZXIoY2hpbGQsIGdyb3VwQnlGaWVsZCwgKHZhbHVlcykgPT4gewogICAgICAgIGxldCBuID0gMDsKICAgICAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIHZhbHVlcykgewogICAgICAgICAgbiArPSB2YWx1ZVtzdW1GaWVsZF07CiAgICAgICAgfQogICAgICAgIHJldHVybiB7CiAgICAgICAgICBbZ3JvdXBCeUZpZWxkXTogdmFsdWVzWzBdW2dyb3VwQnlGaWVsZF0sCiAgICAgICAgICBbc3VtRmllbGRdOiBuCiAgICAgICAgfTsKICAgICAgfSk7CiAgICB9CiAgfQogIGNsYXNzIE1hcE9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBmdW5jKSB7CiAgICAgIHRoaXMuY2hpbGQgPSBjaGlsZDsKICAgICAgdGhpcy5mdW5jID0gZnVuYzsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzLCBzaWduYWwpIHsKICAgICAgY29uc3QgY2hpbGRFdmFsdWF0ZWQgPSBhd2FpdCB0aGlzLmNoaWxkLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICByZXR1cm4gewogICAgICAgIGNvbnRlbnQ6IGNoaWxkRXZhbHVhdGVkLmNvbnRlbnQubWFwKHRoaXMuZnVuYykKICAgICAgfTsKICAgIH0KICB9CiAgY2xhc3MgUmVuYW1lRmllbGRPcGVyYXRvciBleHRlbmRzIE1hcE9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBvbGRGaWVsZE5hbWUsIG5ld0ZpZWxkTmFtZSkgewogICAgICBzdXBlcigKICAgICAgICBjaGlsZCwKICAgICAgICAodmFsdWUpID0+ICh7CiAgICAgICAgICAuLi52YWx1ZSwKICAgICAgICAgIFtuZXdGaWVsZE5hbWVdOiB2YWx1ZVtvbGRGaWVsZE5hbWVdCiAgICAgICAgfSkKICAgICAgKTsKICAgIH0KICB9CiAgY2xhc3MgU29ydE9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBjb21wYXJlRm4pIHsKICAgICAgdGhpcy5jaGlsZCA9IGNoaWxkOwogICAgICB0aGlzLmNvbXBhcmVGbiA9IGNvbXBhcmVGbjsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzLCBzaWduYWwpIHsKICAgICAgY29uc3QgY2hpbGRFdmFsdWF0ZWQgPSBhd2FpdCB0aGlzLmNoaWxkLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICByZXR1cm4gewogICAgICAgIGNvbnRlbnQ6IGNoaWxkRXZhbHVhdGVkLmNvbnRlbnQuc29ydCh0aGlzLmNvbXBhcmVGbikKICAgICAgfTsKICAgIH0KICB9CiAgdmFyIFNFQ09ORFNfQV9NSU5VVEUgPSA2MDsKICB2YXIgU0VDT05EU19BX0hPVVIgPSBTRUNPTkRTX0FfTUlOVVRFICogNjA7CiAgdmFyIFNFQ09ORFNfQV9EQVkgPSBTRUNPTkRTX0FfSE9VUiAqIDI0OwogIHZhciBTRUNPTkRTX0FfV0VFSyA9IFNFQ09ORFNfQV9EQVkgKiA3OwogIHZhciBNSUxMSVNFQ09ORFNfQV9TRUNPTkQgPSAxZTM7CiAgdmFyIE1JTExJU0VDT05EU19BX01JTlVURSA9IFNFQ09ORFNfQV9NSU5VVEUgKiBNSUxMSVNFQ09ORFNfQV9TRUNPTkQ7CiAgdmFyIE1JTExJU0VDT05EU19BX0hPVVIgPSBTRUNPTkRTX0FfSE9VUiAqIE1JTExJU0VDT05EU19BX1NFQ09ORDsKICB2YXIgTUlMTElTRUNPTkRTX0FfREFZID0gU0VDT05EU19BX0RBWSAqIE1JTExJU0VDT05EU19BX1NFQ09ORDsKICB2YXIgTUlMTElTRUNPTkRTX0FfV0VFSyA9IFNFQ09ORFNfQV9XRUVLICogTUlMTElTRUNPTkRTX0FfU0VDT05EOwogIHZhciBNUyA9ICJtaWxsaXNlY29uZCI7CiAgdmFyIFMgPSAic2Vjb25kIjsKICB2YXIgTUlOID0gIm1pbnV0ZSI7CiAgdmFyIEggPSAiaG91ciI7CiAgdmFyIEQgPSAiZGF5IjsKICB2YXIgVyA9ICJ3ZWVrIjsKICB2YXIgTSA9ICJtb250aCI7CiAgdmFyIFEgPSAicXVhcnRlciI7CiAgdmFyIFkgPSAieWVhciI7CiAgdmFyIERBVEUgPSAiZGF0ZSI7CiAgdmFyIEZPUk1BVF9ERUZBVUxUID0gIllZWVktTU0tRERUSEg6bW06c3NaIjsKICB2YXIgSU5WQUxJRF9EQVRFX1NUUklORyA9ICJJbnZhbGlkIERhdGUiOwogIHZhciBSRUdFWF9QQVJTRSA9IC9eKFxkezR9KVstL10/KFxkezEsMn0pP1stL10/KFxkezAsMn0pW1R0XHNdKihcZHsxLDJ9KT86PyhcZHsxLDJ9KT86PyhcZHsxLDJ9KT9bLjpdPyhcZCspPyQvOwogIHZhciBSRUdFWF9GT1JNQVQgPSAvXFsoW15cXV0rKV18WXsxLDR9fE17MSw0fXxEezEsMn18ZHsxLDR9fEh7MSwyfXxoezEsMn18YXxBfG17MSwyfXxzezEsMn18WnsxLDJ9fFNTUy9nOwogIHZhciBlbiA9IHsKICAgIG5hbWU6ICJlbiIsCiAgICB3ZWVrZGF5czogIlN1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Ii5zcGxpdCgiXyIpLAogICAgbW9udGhzOiAiSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlciIuc3BsaXQoIl8iKSwKICAgIG9yZGluYWw6IGZ1bmN0aW9uIG9yZGluYWwobikgewogICAgICB2YXIgczIgPSBbInRoIiwgInN0IiwgIm5kIiwgInJkIl07CiAgICAgIHZhciB2MiA9IG4gJSAxMDA7CiAgICAgIHJldHVybiAiWyIgKyBuICsgKHMyWyh2MiAtIDIwKSAlIDEwXSB8fCBzMlt2Ml0gfHwgczJbMF0pICsgIl0iOwogICAgfQogIH07CiAgdmFyIHBhZFN0YXJ0ID0gZnVuY3Rpb24gcGFkU3RhcnQyKHN0cmluZywgbGVuZ3RoLCBwYWQpIHsKICAgIHZhciBzMiA9IFN0cmluZyhzdHJpbmcpOwogICAgaWYgKCFzMiB8fCBzMi5sZW5ndGggPj0gbGVuZ3RoKSByZXR1cm4gc3RyaW5nOwogICAgcmV0dXJuICIiICsgQXJyYXkobGVuZ3RoICsgMSAtIHMyLmxlbmd0aCkuam9pbihwYWQpICsgc3RyaW5nOwogIH07CiAgdmFyIHBhZFpvbmVTdHIgPSBmdW5jdGlvbiBwYWRab25lU3RyMihpbnN0YW5jZSkgewogICAgdmFyIG5lZ01pbnV0ZXMgPSAtaW5zdGFuY2UudXRjT2Zmc2V0KCk7CiAgICB2YXIgbWludXRlcyA9IE1hdGguYWJzKG5lZ01pbnV0ZXMpOwogICAgdmFyIGhvdXJPZmZzZXQgPSBNYXRoLmZsb29yKG1pbnV0ZXMgLyA2MCk7CiAgICB2YXIgbWludXRlT2Zmc2V0ID0gbWludXRlcyAlIDYwOwogICAgcmV0dXJuIChuZWdNaW51dGVzIDw9IDAgPyAiKyIgOiAiLSIpICsgcGFkU3RhcnQoaG91ck9mZnNldCwgMiwgIjAiKSArICI6IiArIHBhZFN0YXJ0KG1pbnV0ZU9mZnNldCwgMiwgIjAiKTsKICB9OwogIHZhciBtb250aERpZmYgPSBmdW5jdGlvbiBtb250aERpZmYyKGEyLCBiKSB7CiAgICBpZiAoYTIuZGF0ZSgpIDwgYi5kYXRlKCkpIHJldHVybiAtbW9udGhEaWZmMihiLCBhMik7CiAgICB2YXIgd2hvbGVNb250aERpZmYgPSAoYi55ZWFyKCkgLSBhMi55ZWFyKCkpICogMTIgKyAoYi5tb250aCgpIC0gYTIubW9udGgoKSk7CiAgICB2YXIgYW5jaG9yID0gYTIuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYsIE0pOwogICAgdmFyIGMyID0gYiAtIGFuY2hvciA8IDA7CiAgICB2YXIgYW5jaG9yMiA9IGEyLmNsb25lKCkuYWRkKHdob2xlTW9udGhEaWZmICsgKGMyID8gLTEgOiAxKSwgTSk7CiAgICByZXR1cm4gKygtKHdob2xlTW9udGhEaWZmICsgKGIgLSBhbmNob3IpIC8gKGMyID8gYW5jaG9yIC0gYW5jaG9yMiA6IGFuY2hvcjIgLSBhbmNob3IpKSB8fCAwKTsKICB9OwogIHZhciBhYnNGbG9vciA9IGZ1bmN0aW9uIGFic0Zsb29yMihuKSB7CiAgICByZXR1cm4gbiA8IDAgPyBNYXRoLmNlaWwobikgfHwgMCA6IE1hdGguZmxvb3Iobik7CiAgfTsKICB2YXIgcHJldHR5VW5pdCA9IGZ1bmN0aW9uIHByZXR0eVVuaXQyKHUyKSB7CiAgICB2YXIgc3BlY2lhbCA9IHsKICAgICAgTSwKICAgICAgeTogWSwKICAgICAgdzogVywKICAgICAgZDogRCwKICAgICAgRDogREFURSwKICAgICAgaDogSCwKICAgICAgbTogTUlOLAogICAgICBzOiBTLAogICAgICBtczogTVMsCiAgICAgIFEKICAgIH07CiAgICByZXR1cm4gc3BlY2lhbFt1Ml0gfHwgU3RyaW5nKHUyIHx8ICIiKS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL3MkLywgIiIpOwogIH07CiAgdmFyIGlzVW5kZWZpbmVkID0gZnVuY3Rpb24gaXNVbmRlZmluZWQyKHMyKSB7CiAgICByZXR1cm4gczIgPT09IHZvaWQgMDsKICB9OwogIHZhciBVID0gewogICAgczogcGFkU3RhcnQsCiAgICB6OiBwYWRab25lU3RyLAogICAgbTogbW9udGhEaWZmLAogICAgYTogYWJzRmxvb3IsCiAgICBwOiBwcmV0dHlVbml0LAogICAgdTogaXNVbmRlZmluZWQKICB9OwogIHZhciBMID0gImVuIjsKICB2YXIgTHMgPSB7fTsKICBMc1tMXSA9IGVuOwogIHZhciBJU19EQVlKUyA9ICIkaXNEYXlqc09iamVjdCI7CiAgdmFyIGlzRGF5anMgPSBmdW5jdGlvbiBpc0RheWpzMihkKSB7CiAgICByZXR1cm4gZCBpbnN0YW5jZW9mIERheWpzIHx8ICEhKGQgJiYgZFtJU19EQVlKU10pOwogIH07CiAgdmFyIHBhcnNlTG9jYWxlID0gZnVuY3Rpb24gcGFyc2VMb2NhbGUyKHByZXNldCwgb2JqZWN0LCBpc0xvY2FsKSB7CiAgICB2YXIgbDI7CiAgICBpZiAoIXByZXNldCkgcmV0dXJuIEw7CiAgICBpZiAodHlwZW9mIHByZXNldCA9PT0gInN0cmluZyIpIHsKICAgICAgdmFyIHByZXNldExvd2VyID0gcHJlc2V0LnRvTG93ZXJDYXNlKCk7CiAgICAgIGlmIChMc1twcmVzZXRMb3dlcl0pIHsKICAgICAgICBsMiA9IHByZXNldExvd2VyOwogICAgICB9CiAgICAgIGlmIChvYmplY3QpIHsKICAgICAgICBMc1twcmVzZXRMb3dlcl0gPSBvYmplY3Q7CiAgICAgICAgbDIgPSBwcmVzZXRMb3dlcjsKICAgICAgfQogICAgICB2YXIgcHJlc2V0U3BsaXQgPSBwcmVzZXQuc3BsaXQoIi0iKTsKICAgICAgaWYgKCFsMiAmJiBwcmVzZXRTcGxpdC5sZW5ndGggPiAxKSB7CiAgICAgICAgcmV0dXJuIHBhcnNlTG9jYWxlMihwcmVzZXRTcGxpdFswXSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhciBuYW1lID0gcHJlc2V0Lm5hbWU7CiAgICAgIExzW25hbWVdID0gcHJlc2V0OwogICAgICBsMiA9IG5hbWU7CiAgICB9CiAgICBpZiAoIWlzTG9jYWwgJiYgbDIpIEwgPSBsMjsKICAgIHJldHVybiBsMiB8fCAhaXNMb2NhbCAmJiBMOwogIH07CiAgdmFyIGRheWpzID0gZnVuY3Rpb24gZGF5anMyKGRhdGUsIGMyKSB7CiAgICBpZiAoaXNEYXlqcyhkYXRlKSkgewogICAgICByZXR1cm4gZGF0ZS5jbG9uZSgpOwogICAgfQogICAgdmFyIGNmZyA9IHR5cGVvZiBjMiA9PT0gIm9iamVjdCIgPyBjMiA6IHt9OwogICAgY2ZnLmRhdGUgPSBkYXRlOwogICAgY2ZnLmFyZ3MgPSBhcmd1bWVudHM7CiAgICByZXR1cm4gbmV3IERheWpzKGNmZyk7CiAgfTsKICB2YXIgd3JhcHBlciA9IGZ1bmN0aW9uIHdyYXBwZXIyKGRhdGUsIGluc3RhbmNlKSB7CiAgICByZXR1cm4gZGF5anMoZGF0ZSwgewogICAgICBsb2NhbGU6IGluc3RhbmNlLiRMLAogICAgICB1dGM6IGluc3RhbmNlLiR1LAogICAgICB4OiBpbnN0YW5jZS4keCwKICAgICAgJG9mZnNldDogaW5zdGFuY2UuJG9mZnNldAogICAgICAvLyB0b2RvOiByZWZhY3RvcjsgZG8gbm90IHVzZSB0aGlzLiRvZmZzZXQgaW4geW91IGNvZGUKICAgIH0pOwogIH07CiAgdmFyIFV0aWxzID0gVTsKICBVdGlscy5sID0gcGFyc2VMb2NhbGU7CiAgVXRpbHMuaSA9IGlzRGF5anM7CiAgVXRpbHMudyA9IHdyYXBwZXI7CiAgdmFyIHBhcnNlRGF0ZSA9IGZ1bmN0aW9uIHBhcnNlRGF0ZTIoY2ZnKSB7CiAgICB2YXIgZGF0ZSA9IGNmZy5kYXRlLCB1dGMgPSBjZmcudXRjOwogICAgaWYgKGRhdGUgPT09IG51bGwpIHJldHVybiAvKiBAX19QVVJFX18gKi8gbmV3IERhdGUoTmFOKTsKICAgIGlmIChVdGlscy51KGRhdGUpKSByZXR1cm4gLyogQF9fUFVSRV9fICovIG5ldyBEYXRlKCk7CiAgICBpZiAoZGF0ZSBpbnN0YW5jZW9mIERhdGUpIHJldHVybiBuZXcgRGF0ZShkYXRlKTsKICAgIGlmICh0eXBlb2YgZGF0ZSA9PT0gInN0cmluZyIgJiYgIS9aJC9pLnRlc3QoZGF0ZSkpIHsKICAgICAgdmFyIGQgPSBkYXRlLm1hdGNoKFJFR0VYX1BBUlNFKTsKICAgICAgaWYgKGQpIHsKICAgICAgICB2YXIgbTIgPSBkWzJdIC0gMSB8fCAwOwogICAgICAgIHZhciBtcyA9IChkWzddIHx8ICIwIikuc3Vic3RyaW5nKDAsIDMpOwogICAgICAgIGlmICh1dGMpIHsKICAgICAgICAgIHJldHVybiBuZXcgRGF0ZShEYXRlLlVUQyhkWzFdLCBtMiwgZFszXSB8fCAxLCBkWzRdIHx8IDAsIGRbNV0gfHwgMCwgZFs2XSB8fCAwLCBtcykpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IERhdGUoZFsxXSwgbTIsIGRbM10gfHwgMSwgZFs0XSB8fCAwLCBkWzVdIHx8IDAsIGRbNl0gfHwgMCwgbXMpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbmV3IERhdGUoZGF0ZSk7CiAgfTsKICB2YXIgRGF5anMgPSAvKiBAX19QVVJFX18gKi8gZnVuY3Rpb24oKSB7CiAgICBmdW5jdGlvbiBEYXlqczIoY2ZnKSB7CiAgICAgIHRoaXMuJEwgPSBwYXJzZUxvY2FsZShjZmcubG9jYWxlLCBudWxsLCB0cnVlKTsKICAgICAgdGhpcy5wYXJzZShjZmcpOwogICAgICB0aGlzLiR4ID0gdGhpcy4keCB8fCBjZmcueCB8fCB7fTsKICAgICAgdGhpc1tJU19EQVlKU10gPSB0cnVlOwogICAgfQogICAgdmFyIF9wcm90byA9IERheWpzMi5wcm90b3R5cGU7CiAgICBfcHJvdG8ucGFyc2UgPSBmdW5jdGlvbiBwYXJzZShjZmcpIHsKICAgICAgdGhpcy4kZCA9IHBhcnNlRGF0ZShjZmcpOwogICAgICB0aGlzLmluaXQoKTsKICAgIH07CiAgICBfcHJvdG8uaW5pdCA9IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHZhciAkZCA9IHRoaXMuJGQ7CiAgICAgIHRoaXMuJHkgPSAkZC5nZXRGdWxsWWVhcigpOwogICAgICB0aGlzLiRNID0gJGQuZ2V0TW9udGgoKTsKICAgICAgdGhpcy4kRCA9ICRkLmdldERhdGUoKTsKICAgICAgdGhpcy4kVyA9ICRkLmdldERheSgpOwogICAgICB0aGlzLiRIID0gJGQuZ2V0SG91cnMoKTsKICAgICAgdGhpcy4kbSA9ICRkLmdldE1pbnV0ZXMoKTsKICAgICAgdGhpcy4kcyA9ICRkLmdldFNlY29uZHMoKTsKICAgICAgdGhpcy4kbXMgPSAkZC5nZXRNaWxsaXNlY29uZHMoKTsKICAgIH07CiAgICBfcHJvdG8uJHV0aWxzID0gZnVuY3Rpb24gJHV0aWxzKCkgewogICAgICByZXR1cm4gVXRpbHM7CiAgICB9OwogICAgX3Byb3RvLmlzVmFsaWQgPSBmdW5jdGlvbiBpc1ZhbGlkMigpIHsKICAgICAgcmV0dXJuICEodGhpcy4kZC50b1N0cmluZygpID09PSBJTlZBTElEX0RBVEVfU1RSSU5HKTsKICAgIH07CiAgICBfcHJvdG8uaXNTYW1lID0gZnVuY3Rpb24gaXNTYW1lKHRoYXQsIHVuaXRzKSB7CiAgICAgIHZhciBvdGhlciA9IGRheWpzKHRoYXQpOwogICAgICByZXR1cm4gdGhpcy5zdGFydE9mKHVuaXRzKSA8PSBvdGhlciAmJiBvdGhlciA8PSB0aGlzLmVuZE9mKHVuaXRzKTsKICAgIH07CiAgICBfcHJvdG8uaXNBZnRlciA9IGZ1bmN0aW9uIGlzQWZ0ZXIodGhhdCwgdW5pdHMpIHsKICAgICAgcmV0dXJuIGRheWpzKHRoYXQpIDwgdGhpcy5zdGFydE9mKHVuaXRzKTsKICAgIH07CiAgICBfcHJvdG8uaXNCZWZvcmUgPSBmdW5jdGlvbiBpc0JlZm9yZSh0aGF0LCB1bml0cykgewogICAgICByZXR1cm4gdGhpcy5lbmRPZih1bml0cykgPCBkYXlqcyh0aGF0KTsKICAgIH07CiAgICBfcHJvdG8uJGcgPSBmdW5jdGlvbiAkZyhpbnB1dCwgZ2V0LCBzZXQpIHsKICAgICAgaWYgKFV0aWxzLnUoaW5wdXQpKSByZXR1cm4gdGhpc1tnZXRdOwogICAgICByZXR1cm4gdGhpcy5zZXQoc2V0LCBpbnB1dCk7CiAgICB9OwogICAgX3Byb3RvLnVuaXggPSBmdW5jdGlvbiB1bml4KCkgewogICAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLnZhbHVlT2YoKSAvIDFlMyk7CiAgICB9OwogICAgX3Byb3RvLnZhbHVlT2YgPSBmdW5jdGlvbiB2YWx1ZU9mKCkgewogICAgICByZXR1cm4gdGhpcy4kZC5nZXRUaW1lKCk7CiAgICB9OwogICAgX3Byb3RvLnN0YXJ0T2YgPSBmdW5jdGlvbiBzdGFydE9mKHVuaXRzLCBfc3RhcnRPZikgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwogICAgICB2YXIgaXNTdGFydE9mID0gIVV0aWxzLnUoX3N0YXJ0T2YpID8gX3N0YXJ0T2YgOiB0cnVlOwogICAgICB2YXIgdW5pdCA9IFV0aWxzLnAodW5pdHMpOwogICAgICB2YXIgaW5zdGFuY2VGYWN0b3J5ID0gZnVuY3Rpb24gaW5zdGFuY2VGYWN0b3J5MihkLCBtMikgewogICAgICAgIHZhciBpbnMgPSBVdGlscy53KF90aGlzLiR1ID8gRGF0ZS5VVEMoX3RoaXMuJHksIG0yLCBkKSA6IG5ldyBEYXRlKF90aGlzLiR5LCBtMiwgZCksIF90aGlzKTsKICAgICAgICByZXR1cm4gaXNTdGFydE9mID8gaW5zIDogaW5zLmVuZE9mKEQpOwogICAgICB9OwogICAgICB2YXIgaW5zdGFuY2VGYWN0b3J5U2V0ID0gZnVuY3Rpb24gaW5zdGFuY2VGYWN0b3J5U2V0MihtZXRob2QsIHNsaWNlKSB7CiAgICAgICAgdmFyIGFyZ3VtZW50U3RhcnQgPSBbMCwgMCwgMCwgMF07CiAgICAgICAgdmFyIGFyZ3VtZW50RW5kID0gWzIzLCA1OSwgNTksIDk5OV07CiAgICAgICAgcmV0dXJuIFV0aWxzLncoX3RoaXMudG9EYXRlKClbbWV0aG9kXS5hcHBseSgKICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcHJlZmVyLXNwcmVhZAogICAgICAgICAgX3RoaXMudG9EYXRlKCJzIiksCiAgICAgICAgICAoaXNTdGFydE9mID8gYXJndW1lbnRTdGFydCA6IGFyZ3VtZW50RW5kKS5zbGljZShzbGljZSkKICAgICAgICApLCBfdGhpcyk7CiAgICAgIH07CiAgICAgIHZhciAkVyA9IHRoaXMuJFcsICRNID0gdGhpcy4kTSwgJEQgPSB0aGlzLiREOwogICAgICB2YXIgdXRjUGFkID0gInNldCIgKyAodGhpcy4kdSA/ICJVVEMiIDogIiIpOwogICAgICBzd2l0Y2ggKHVuaXQpIHsKICAgICAgICBjYXNlIFk6CiAgICAgICAgICByZXR1cm4gaXNTdGFydE9mID8gaW5zdGFuY2VGYWN0b3J5KDEsIDApIDogaW5zdGFuY2VGYWN0b3J5KDMxLCAxMSk7CiAgICAgICAgY2FzZSBNOgogICAgICAgICAgcmV0dXJuIGlzU3RhcnRPZiA/IGluc3RhbmNlRmFjdG9yeSgxLCAkTSkgOiBpbnN0YW5jZUZhY3RvcnkoMCwgJE0gKyAxKTsKICAgICAgICBjYXNlIFc6IHsKICAgICAgICAgIHZhciB3ZWVrU3RhcnQgPSB0aGlzLiRsb2NhbGUoKS53ZWVrU3RhcnQgfHwgMDsKICAgICAgICAgIHZhciBnYXAgPSAoJFcgPCB3ZWVrU3RhcnQgPyAkVyArIDcgOiAkVykgLSB3ZWVrU3RhcnQ7CiAgICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5KGlzU3RhcnRPZiA/ICREIC0gZ2FwIDogJEQgKyAoNiAtIGdhcCksICRNKTsKICAgICAgICB9CiAgICAgICAgY2FzZSBEOgogICAgICAgIGNhc2UgREFURToKICAgICAgICAgIHJldHVybiBpbnN0YW5jZUZhY3RvcnlTZXQodXRjUGFkICsgIkhvdXJzIiwgMCk7CiAgICAgICAgY2FzZSBIOgogICAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCh1dGNQYWQgKyAiTWludXRlcyIsIDEpOwogICAgICAgIGNhc2UgTUlOOgogICAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCh1dGNQYWQgKyAiU2Vjb25kcyIsIDIpOwogICAgICAgIGNhc2UgUzoKICAgICAgICAgIHJldHVybiBpbnN0YW5jZUZhY3RvcnlTZXQodXRjUGFkICsgIk1pbGxpc2Vjb25kcyIsIDMpOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gdGhpcy5jbG9uZSgpOwogICAgICB9CiAgICB9OwogICAgX3Byb3RvLmVuZE9mID0gZnVuY3Rpb24gZW5kT2YoYXJnKSB7CiAgICAgIHJldHVybiB0aGlzLnN0YXJ0T2YoYXJnLCBmYWxzZSk7CiAgICB9OwogICAgX3Byb3RvLiRzZXQgPSBmdW5jdGlvbiAkc2V0KHVuaXRzLCBfaW50KSB7CiAgICAgIHZhciBfQyREJEMkREFURSRDJE0kQyRZJEM7CiAgICAgIHZhciB1bml0ID0gVXRpbHMucCh1bml0cyk7CiAgICAgIHZhciB1dGNQYWQgPSAic2V0IiArICh0aGlzLiR1ID8gIlVUQyIgOiAiIik7CiAgICAgIHZhciBuYW1lID0gKF9DJEQkQyREQVRFJEMkTSRDJFkkQyA9IHt9LCBfQyREJEMkREFURSRDJE0kQyRZJENbRF0gPSB1dGNQYWQgKyAiRGF0ZSIsIF9DJEQkQyREQVRFJEMkTSRDJFkkQ1tEQVRFXSA9IHV0Y1BhZCArICJEYXRlIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW01dID0gdXRjUGFkICsgIk1vbnRoIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW1ldID0gdXRjUGFkICsgIkZ1bGxZZWFyIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW0hdID0gdXRjUGFkICsgIkhvdXJzIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW01JTl0gPSB1dGNQYWQgKyAiTWludXRlcyIsIF9DJEQkQyREQVRFJEMkTSRDJFkkQ1tTXSA9IHV0Y1BhZCArICJTZWNvbmRzIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW01TXSA9IHV0Y1BhZCArICJNaWxsaXNlY29uZHMiLCBfQyREJEMkREFURSRDJE0kQyRZJEMpW3VuaXRdOwogICAgICB2YXIgYXJnID0gdW5pdCA9PT0gRCA/IHRoaXMuJEQgKyAoX2ludCAtIHRoaXMuJFcpIDogX2ludDsKICAgICAgaWYgKHVuaXQgPT09IE0gfHwgdW5pdCA9PT0gWSkgewogICAgICAgIHZhciBkYXRlID0gdGhpcy5jbG9uZSgpLnNldChEQVRFLCAxKTsKICAgICAgICBkYXRlLiRkW25hbWVdKGFyZyk7CiAgICAgICAgZGF0ZS5pbml0KCk7CiAgICAgICAgdGhpcy4kZCA9IGRhdGUuc2V0KERBVEUsIE1hdGgubWluKHRoaXMuJEQsIGRhdGUuZGF5c0luTW9udGgoKSkpLiRkOwogICAgICB9IGVsc2UgaWYgKG5hbWUpIHRoaXMuJGRbbmFtZV0oYXJnKTsKICAgICAgdGhpcy5pbml0KCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKICAgIF9wcm90by5zZXQgPSBmdW5jdGlvbiBzZXQoc3RyaW5nLCBfaW50MikgewogICAgICByZXR1cm4gdGhpcy5jbG9uZSgpLiRzZXQoc3RyaW5nLCBfaW50Mik7CiAgICB9OwogICAgX3Byb3RvLmdldCA9IGZ1bmN0aW9uIGdldCh1bml0KSB7CiAgICAgIHJldHVybiB0aGlzW1V0aWxzLnAodW5pdCldKCk7CiAgICB9OwogICAgX3Byb3RvLmFkZCA9IGZ1bmN0aW9uIGFkZChudW1iZXIsIHVuaXRzKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzLCBfQyRNSU4kQyRIJEMkUyR1bml0OwogICAgICBudW1iZXIgPSBOdW1iZXIobnVtYmVyKTsKICAgICAgdmFyIHVuaXQgPSBVdGlscy5wKHVuaXRzKTsKICAgICAgdmFyIGluc3RhbmNlRmFjdG9yeVNldCA9IGZ1bmN0aW9uIGluc3RhbmNlRmFjdG9yeVNldDIobikgewogICAgICAgIHZhciBkID0gZGF5anMoX3RoaXMyKTsKICAgICAgICByZXR1cm4gVXRpbHMudyhkLmRhdGUoZC5kYXRlKCkgKyBNYXRoLnJvdW5kKG4gKiBudW1iZXIpKSwgX3RoaXMyKTsKICAgICAgfTsKICAgICAgaWYgKHVuaXQgPT09IE0pIHsKICAgICAgICByZXR1cm4gdGhpcy5zZXQoTSwgdGhpcy4kTSArIG51bWJlcik7CiAgICAgIH0KICAgICAgaWYgKHVuaXQgPT09IFkpIHsKICAgICAgICByZXR1cm4gdGhpcy5zZXQoWSwgdGhpcy4keSArIG51bWJlcik7CiAgICAgIH0KICAgICAgaWYgKHVuaXQgPT09IEQpIHsKICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5U2V0KDEpOwogICAgICB9CiAgICAgIGlmICh1bml0ID09PSBXKSB7CiAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCg3KTsKICAgICAgfQogICAgICB2YXIgc3RlcCA9IChfQyRNSU4kQyRIJEMkUyR1bml0ID0ge30sIF9DJE1JTiRDJEgkQyRTJHVuaXRbTUlOXSA9IE1JTExJU0VDT05EU19BX01JTlVURSwgX0MkTUlOJEMkSCRDJFMkdW5pdFtIXSA9IE1JTExJU0VDT05EU19BX0hPVVIsIF9DJE1JTiRDJEgkQyRTJHVuaXRbU10gPSBNSUxMSVNFQ09ORFNfQV9TRUNPTkQsIF9DJE1JTiRDJEgkQyRTJHVuaXQpW3VuaXRdIHx8IDE7CiAgICAgIHZhciBuZXh0VGltZVN0YW1wID0gdGhpcy4kZC5nZXRUaW1lKCkgKyBudW1iZXIgKiBzdGVwOwogICAgICByZXR1cm4gVXRpbHMudyhuZXh0VGltZVN0YW1wLCB0aGlzKTsKICAgIH07CiAgICBfcHJvdG8uc3VidHJhY3QgPSBmdW5jdGlvbiBzdWJ0cmFjdChudW1iZXIsIHN0cmluZykgewogICAgICByZXR1cm4gdGhpcy5hZGQobnVtYmVyICogLTEsIHN0cmluZyk7CiAgICB9OwogICAgX3Byb3RvLmZvcm1hdCA9IGZ1bmN0aW9uIGZvcm1hdChmb3JtYXRTdHIpIHsKICAgICAgdmFyIF90aGlzMyA9IHRoaXM7CiAgICAgIHZhciBsb2NhbGUgPSB0aGlzLiRsb2NhbGUoKTsKICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkgcmV0dXJuIGxvY2FsZS5pbnZhbGlkRGF0ZSB8fCBJTlZBTElEX0RBVEVfU1RSSU5HOwogICAgICB2YXIgc3RyID0gZm9ybWF0U3RyIHx8IEZPUk1BVF9ERUZBVUxUOwogICAgICB2YXIgem9uZVN0ciA9IFV0aWxzLnoodGhpcyk7CiAgICAgIHZhciAkSCA9IHRoaXMuJEgsICRtID0gdGhpcy4kbSwgJE0gPSB0aGlzLiRNOwogICAgICB2YXIgd2Vla2RheXMgPSBsb2NhbGUud2Vla2RheXMsIG1vbnRocyA9IGxvY2FsZS5tb250aHMsIG1lcmlkaWVtID0gbG9jYWxlLm1lcmlkaWVtOwogICAgICB2YXIgZ2V0U2hvcnQgPSBmdW5jdGlvbiBnZXRTaG9ydDIoYXJyLCBpbmRleCwgZnVsbCwgbGVuZ3RoKSB7CiAgICAgICAgcmV0dXJuIGFyciAmJiAoYXJyW2luZGV4XSB8fCBhcnIoX3RoaXMzLCBzdHIpKSB8fCBmdWxsW2luZGV4XS5zbGljZSgwLCBsZW5ndGgpOwogICAgICB9OwogICAgICB2YXIgZ2V0JEggPSBmdW5jdGlvbiBnZXQkSDIobnVtKSB7CiAgICAgICAgcmV0dXJuIFV0aWxzLnMoJEggJSAxMiB8fCAxMiwgbnVtLCAiMCIpOwogICAgICB9OwogICAgICB2YXIgbWVyaWRpZW1GdW5jID0gbWVyaWRpZW0gfHwgZnVuY3Rpb24oaG91ciwgbWludXRlLCBpc0xvd2VyY2FzZSkgewogICAgICAgIHZhciBtMiA9IGhvdXIgPCAxMiA/ICJBTSIgOiAiUE0iOwogICAgICAgIHJldHVybiBpc0xvd2VyY2FzZSA/IG0yLnRvTG93ZXJDYXNlKCkgOiBtMjsKICAgICAgfTsKICAgICAgdmFyIG1hdGNoZXMgPSBmdW5jdGlvbiBtYXRjaGVzMihtYXRjaCkgewogICAgICAgIHN3aXRjaCAobWF0Y2gpIHsKICAgICAgICAgIGNhc2UgIllZIjoKICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhfdGhpczMuJHkpLnNsaWNlKC0yKTsKICAgICAgICAgIGNhc2UgIllZWVkiOgogICAgICAgICAgICByZXR1cm4gVXRpbHMucyhfdGhpczMuJHksIDQsICIwIik7CiAgICAgICAgICBjYXNlICJNIjoKICAgICAgICAgICAgcmV0dXJuICRNICsgMTsKICAgICAgICAgIGNhc2UgIk1NIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoJE0gKyAxLCAyLCAiMCIpOwogICAgICAgICAgY2FzZSAiTU1NIjoKICAgICAgICAgICAgcmV0dXJuIGdldFNob3J0KGxvY2FsZS5tb250aHNTaG9ydCwgJE0sIG1vbnRocywgMyk7CiAgICAgICAgICBjYXNlICJNTU1NIjoKICAgICAgICAgICAgcmV0dXJuIGdldFNob3J0KG1vbnRocywgJE0pOwogICAgICAgICAgY2FzZSAiRCI6CiAgICAgICAgICAgIHJldHVybiBfdGhpczMuJEQ7CiAgICAgICAgICBjYXNlICJERCI6CiAgICAgICAgICAgIHJldHVybiBVdGlscy5zKF90aGlzMy4kRCwgMiwgIjAiKTsKICAgICAgICAgIGNhc2UgImQiOgogICAgICAgICAgICByZXR1cm4gU3RyaW5nKF90aGlzMy4kVyk7CiAgICAgICAgICBjYXNlICJkZCI6CiAgICAgICAgICAgIHJldHVybiBnZXRTaG9ydChsb2NhbGUud2Vla2RheXNNaW4sIF90aGlzMy4kVywgd2Vla2RheXMsIDIpOwogICAgICAgICAgY2FzZSAiZGRkIjoKICAgICAgICAgICAgcmV0dXJuIGdldFNob3J0KGxvY2FsZS53ZWVrZGF5c1Nob3J0LCBfdGhpczMuJFcsIHdlZWtkYXlzLCAzKTsKICAgICAgICAgIGNhc2UgImRkZGQiOgogICAgICAgICAgICByZXR1cm4gd2Vla2RheXNbX3RoaXMzLiRXXTsKICAgICAgICAgIGNhc2UgIkgiOgogICAgICAgICAgICByZXR1cm4gU3RyaW5nKCRIKTsKICAgICAgICAgIGNhc2UgIkhIIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoJEgsIDIsICIwIik7CiAgICAgICAgICBjYXNlICJoIjoKICAgICAgICAgICAgcmV0dXJuIGdldCRIKDEpOwogICAgICAgICAgY2FzZSAiaGgiOgogICAgICAgICAgICByZXR1cm4gZ2V0JEgoMik7CiAgICAgICAgICBjYXNlICJhIjoKICAgICAgICAgICAgcmV0dXJuIG1lcmlkaWVtRnVuYygkSCwgJG0sIHRydWUpOwogICAgICAgICAgY2FzZSAiQSI6CiAgICAgICAgICAgIHJldHVybiBtZXJpZGllbUZ1bmMoJEgsICRtLCBmYWxzZSk7CiAgICAgICAgICBjYXNlICJtIjoKICAgICAgICAgICAgcmV0dXJuIFN0cmluZygkbSk7CiAgICAgICAgICBjYXNlICJtbSI6CiAgICAgICAgICAgIHJldHVybiBVdGlscy5zKCRtLCAyLCAiMCIpOwogICAgICAgICAgY2FzZSAicyI6CiAgICAgICAgICAgIHJldHVybiBTdHJpbmcoX3RoaXMzLiRzKTsKICAgICAgICAgIGNhc2UgInNzIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoX3RoaXMzLiRzLCAyLCAiMCIpOwogICAgICAgICAgY2FzZSAiU1NTIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoX3RoaXMzLiRtcywgMywgIjAiKTsKICAgICAgICAgIGNhc2UgIloiOgogICAgICAgICAgICByZXR1cm4gem9uZVN0cjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH07CiAgICAgIHJldHVybiBzdHIucmVwbGFjZShSRUdFWF9GT1JNQVQsIGZ1bmN0aW9uKG1hdGNoLCAkMSkgewogICAgICAgIHJldHVybiAkMSB8fCBtYXRjaGVzKG1hdGNoKSB8fCB6b25lU3RyLnJlcGxhY2UoIjoiLCAiIik7CiAgICAgIH0pOwogICAgfTsKICAgIF9wcm90by51dGNPZmZzZXQgPSBmdW5jdGlvbiB1dGNPZmZzZXQoKSB7CiAgICAgIHJldHVybiAtTWF0aC5yb3VuZCh0aGlzLiRkLmdldFRpbWV6b25lT2Zmc2V0KCkgLyAxNSkgKiAxNTsKICAgIH07CiAgICBfcHJvdG8uZGlmZiA9IGZ1bmN0aW9uIGRpZmYoaW5wdXQsIHVuaXRzLCBfZmxvYXQpIHsKICAgICAgdmFyIF90aGlzNCA9IHRoaXM7CiAgICAgIHZhciB1bml0ID0gVXRpbHMucCh1bml0cyk7CiAgICAgIHZhciB0aGF0ID0gZGF5anMoaW5wdXQpOwogICAgICB2YXIgem9uZURlbHRhID0gKHRoYXQudXRjT2Zmc2V0KCkgLSB0aGlzLnV0Y09mZnNldCgpKSAqIE1JTExJU0VDT05EU19BX01JTlVURTsKICAgICAgdmFyIGRpZmYyID0gdGhpcyAtIHRoYXQ7CiAgICAgIHZhciBnZXRNb250aCA9IGZ1bmN0aW9uIGdldE1vbnRoMigpIHsKICAgICAgICByZXR1cm4gVXRpbHMubShfdGhpczQsIHRoYXQpOwogICAgICB9OwogICAgICB2YXIgcmVzdWx0OwogICAgICBzd2l0Y2ggKHVuaXQpIHsKICAgICAgICBjYXNlIFk6CiAgICAgICAgICByZXN1bHQgPSBnZXRNb250aCgpIC8gMTI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIE06CiAgICAgICAgICByZXN1bHQgPSBnZXRNb250aCgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBROgogICAgICAgICAgcmVzdWx0ID0gZ2V0TW9udGgoKSAvIDM7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFc6CiAgICAgICAgICByZXN1bHQgPSAoZGlmZjIgLSB6b25lRGVsdGEpIC8gTUlMTElTRUNPTkRTX0FfV0VFSzsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgRDoKICAgICAgICAgIHJlc3VsdCA9IChkaWZmMiAtIHpvbmVEZWx0YSkgLyBNSUxMSVNFQ09ORFNfQV9EQVk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIEg6CiAgICAgICAgICByZXN1bHQgPSBkaWZmMiAvIE1JTExJU0VDT05EU19BX0hPVVI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIE1JTjoKICAgICAgICAgIHJlc3VsdCA9IGRpZmYyIC8gTUlMTElTRUNPTkRTX0FfTUlOVVRFOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTOgogICAgICAgICAgcmVzdWx0ID0gZGlmZjIgLyBNSUxMSVNFQ09ORFNfQV9TRUNPTkQ7CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgcmVzdWx0ID0gZGlmZjI7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICByZXR1cm4gX2Zsb2F0ID8gcmVzdWx0IDogVXRpbHMuYShyZXN1bHQpOwogICAgfTsKICAgIF9wcm90by5kYXlzSW5Nb250aCA9IGZ1bmN0aW9uIGRheXNJbk1vbnRoKCkgewogICAgICByZXR1cm4gdGhpcy5lbmRPZihNKS4kRDsKICAgIH07CiAgICBfcHJvdG8uJGxvY2FsZSA9IGZ1bmN0aW9uICRsb2NhbGUoKSB7CiAgICAgIHJldHVybiBMc1t0aGlzLiRMXTsKICAgIH07CiAgICBfcHJvdG8ubG9jYWxlID0gZnVuY3Rpb24gbG9jYWxlKHByZXNldCwgb2JqZWN0KSB7CiAgICAgIGlmICghcHJlc2V0KSByZXR1cm4gdGhpcy4kTDsKICAgICAgdmFyIHRoYXQgPSB0aGlzLmNsb25lKCk7CiAgICAgIHZhciBuZXh0TG9jYWxlTmFtZSA9IHBhcnNlTG9jYWxlKHByZXNldCwgb2JqZWN0LCB0cnVlKTsKICAgICAgaWYgKG5leHRMb2NhbGVOYW1lKSB0aGF0LiRMID0gbmV4dExvY2FsZU5hbWU7CiAgICAgIHJldHVybiB0aGF0OwogICAgfTsKICAgIF9wcm90by5jbG9uZSA9IGZ1bmN0aW9uIGNsb25lKCkgewogICAgICByZXR1cm4gVXRpbHMudyh0aGlzLiRkLCB0aGlzKTsKICAgIH07CiAgICBfcHJvdG8udG9EYXRlID0gZnVuY3Rpb24gdG9EYXRlKCkgewogICAgICByZXR1cm4gbmV3IERhdGUodGhpcy52YWx1ZU9mKCkpOwogICAgfTsKICAgIF9wcm90by50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7CiAgICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMudG9JU09TdHJpbmcoKSA6IG51bGw7CiAgICB9OwogICAgX3Byb3RvLnRvSVNPU3RyaW5nID0gZnVuY3Rpb24gdG9JU09TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLiRkLnRvSVNPU3RyaW5nKCk7CiAgICB9OwogICAgX3Byb3RvLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLiRkLnRvVVRDU3RyaW5nKCk7CiAgICB9OwogICAgcmV0dXJuIERheWpzMjsKICB9KCk7CiAgdmFyIHByb3RvID0gRGF5anMucHJvdG90eXBlOwogIGRheWpzLnByb3RvdHlwZSA9IHByb3RvOwogIFtbIiRtcyIsIE1TXSwgWyIkcyIsIFNdLCBbIiRtIiwgTUlOXSwgWyIkSCIsIEhdLCBbIiRXIiwgRF0sIFsiJE0iLCBNXSwgWyIkeSIsIFldLCBbIiREIiwgREFURV1dLmZvckVhY2goZnVuY3Rpb24oZykgewogICAgcHJvdG9bZ1sxXV0gPSBmdW5jdGlvbihpbnB1dCkgewogICAgICByZXR1cm4gdGhpcy4kZyhpbnB1dCwgZ1swXSwgZ1sxXSk7CiAgICB9OwogIH0pOwogIGRheWpzLmV4dGVuZCA9IGZ1bmN0aW9uKHBsdWdpbiwgb3B0aW9uKSB7CiAgICBpZiAoIXBsdWdpbi4kaSkgewogICAgICBwbHVnaW4ob3B0aW9uLCBEYXlqcywgZGF5anMpOwogICAgICBwbHVnaW4uJGkgPSB0cnVlOwogICAgfQogICAgcmV0dXJuIGRheWpzOwogIH07CiAgZGF5anMubG9jYWxlID0gcGFyc2VMb2NhbGU7CiAgZGF5anMuaXNEYXlqcyA9IGlzRGF5anM7CiAgZGF5anMudW5peCA9IGZ1bmN0aW9uKHRpbWVzdGFtcCkgewogICAgcmV0dXJuIGRheWpzKHRpbWVzdGFtcCAqIDFlMyk7CiAgfTsKICBkYXlqcy5lbiA9IExzW0xdOwogIGRheWpzLkxzID0gTHM7CiAgZGF5anMucCA9IHt9OwogIHZhciBhZHZhbmNlZEZvcm1hdCA9IGZ1bmN0aW9uKG8sIGMyKSB7CiAgICB2YXIgcHJvdG8yID0gYzIucHJvdG90eXBlOwogICAgdmFyIG9sZEZvcm1hdCA9IHByb3RvMi5mb3JtYXQ7CiAgICBwcm90bzIuZm9ybWF0ID0gZnVuY3Rpb24oZm9ybWF0U3RyKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CiAgICAgIHZhciBsb2NhbGUgPSB0aGlzLiRsb2NhbGUoKTsKICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkgewogICAgICAgIHJldHVybiBvbGRGb3JtYXQuYmluZCh0aGlzKShmb3JtYXRTdHIpOwogICAgICB9CiAgICAgIHZhciB1dGlscyA9IHRoaXMuJHV0aWxzKCk7CiAgICAgIHZhciBzdHIgPSBmb3JtYXRTdHIgfHwgRk9STUFUX0RFRkFVTFQ7CiAgICAgIHZhciByZXN1bHQgPSBzdHIucmVwbGFjZSgvXFsoW15cXV0rKV18UXx3b3x3d3x3fFdXfFd8enp6fHp8Z2dnZ3xHR0dHfERvfFh8eHxrezEsMn18Uy9nLCBmdW5jdGlvbihtYXRjaCkgewogICAgICAgIHN3aXRjaCAobWF0Y2gpIHsKICAgICAgICAgIGNhc2UgIlEiOgogICAgICAgICAgICByZXR1cm4gTWF0aC5jZWlsKChfdGhpcy4kTSArIDEpIC8gMyk7CiAgICAgICAgICBjYXNlICJEbyI6CiAgICAgICAgICAgIHJldHVybiBsb2NhbGUub3JkaW5hbChfdGhpcy4kRCk7CiAgICAgICAgICBjYXNlICJnZ2dnIjoKICAgICAgICAgICAgcmV0dXJuIF90aGlzLndlZWtZZWFyKCk7CiAgICAgICAgICBjYXNlICJHR0dHIjoKICAgICAgICAgICAgcmV0dXJuIF90aGlzLmlzb1dlZWtZZWFyKCk7CiAgICAgICAgICBjYXNlICJ3byI6CiAgICAgICAgICAgIHJldHVybiBsb2NhbGUub3JkaW5hbChfdGhpcy53ZWVrKCksICJXIik7CiAgICAgICAgICBjYXNlICJ3IjoKICAgICAgICAgIGNhc2UgInd3IjoKICAgICAgICAgICAgcmV0dXJuIHV0aWxzLnMoX3RoaXMud2VlaygpLCBtYXRjaCA9PT0gInciID8gMSA6IDIsICIwIik7CiAgICAgICAgICBjYXNlICJXIjoKICAgICAgICAgIGNhc2UgIldXIjoKICAgICAgICAgICAgcmV0dXJuIHV0aWxzLnMoX3RoaXMuaXNvV2VlaygpLCBtYXRjaCA9PT0gIlciID8gMSA6IDIsICIwIik7CiAgICAgICAgICBjYXNlICJrIjoKICAgICAgICAgIGNhc2UgImtrIjoKICAgICAgICAgICAgcmV0dXJuIHV0aWxzLnMoU3RyaW5nKF90aGlzLiRIID09PSAwID8gMjQgOiBfdGhpcy4kSCksIG1hdGNoID09PSAiayIgPyAxIDogMiwgIjAiKTsKICAgICAgICAgIGNhc2UgIlgiOgogICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihfdGhpcy4kZC5nZXRUaW1lKCkgLyAxZTMpOwogICAgICAgICAgY2FzZSAieCI6CiAgICAgICAgICAgIHJldHVybiBfdGhpcy4kZC5nZXRUaW1lKCk7CiAgICAgICAgICBjYXNlICJ6IjoKICAgICAgICAgICAgcmV0dXJuICJbIiArIF90aGlzLm9mZnNldE5hbWUoKSArICJdIjsKICAgICAgICAgIGNhc2UgInp6eiI6CiAgICAgICAgICAgIHJldHVybiAiWyIgKyBfdGhpcy5vZmZzZXROYW1lKCJsb25nIikgKyAiXSI7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICByZXR1cm4gbWF0Y2g7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIG9sZEZvcm1hdC5iaW5kKHRoaXMpKHJlc3VsdCk7CiAgICB9OwogIH07CiAgdmFyIGlzb1dlZWtQcmV0dHlVbml0ID0gImlzb3dlZWsiOwogIHZhciBpc29XZWVrID0gZnVuY3Rpb24obywgYzIsIGQpIHsKICAgIHZhciBnZXRZZWFyRmlyc3RUaHVyc2RheSA9IGZ1bmN0aW9uIGdldFllYXJGaXJzdFRodXJzZGF5Mih5ZWFyLCBpc1V0YykgewogICAgICB2YXIgeWVhckZpcnN0RGF5ID0gKGlzVXRjID8gZC51dGMgOiBkKSgpLnllYXIoeWVhcikuc3RhcnRPZihZKTsKICAgICAgdmFyIGFkZERpZmZEYXlzID0gNCAtIHllYXJGaXJzdERheS5pc29XZWVrZGF5KCk7CiAgICAgIGlmICh5ZWFyRmlyc3REYXkuaXNvV2Vla2RheSgpID4gNCkgewogICAgICAgIGFkZERpZmZEYXlzICs9IDc7CiAgICAgIH0KICAgICAgcmV0dXJuIHllYXJGaXJzdERheS5hZGQoYWRkRGlmZkRheXMsIEQpOwogICAgfTsKICAgIHZhciBnZXRDdXJyZW50V2Vla1RodXJzZGF5ID0gZnVuY3Rpb24gZ2V0Q3VycmVudFdlZWtUaHVyc2RheTIoaW5zKSB7CiAgICAgIHJldHVybiBpbnMuYWRkKDQgLSBpbnMuaXNvV2Vla2RheSgpLCBEKTsKICAgIH07CiAgICB2YXIgcHJvdG8yID0gYzIucHJvdG90eXBlOwogICAgcHJvdG8yLmlzb1dlZWtZZWFyID0gZnVuY3Rpb24oKSB7CiAgICAgIHZhciBub3dXZWVrVGh1cnNkYXkgPSBnZXRDdXJyZW50V2Vla1RodXJzZGF5KHRoaXMpOwogICAgICByZXR1cm4gbm93V2Vla1RodXJzZGF5LnllYXIoKTsKICAgIH07CiAgICBwcm90bzIuaXNvV2VlayA9IGZ1bmN0aW9uKHdlZWspIHsKICAgICAgaWYgKCF0aGlzLiR1dGlscygpLnUod2VlaykpIHsKICAgICAgICByZXR1cm4gdGhpcy5hZGQoKHdlZWsgLSB0aGlzLmlzb1dlZWsoKSkgKiA3LCBEKTsKICAgICAgfQogICAgICB2YXIgbm93V2Vla1RodXJzZGF5ID0gZ2V0Q3VycmVudFdlZWtUaHVyc2RheSh0aGlzKTsKICAgICAgdmFyIGRpZmZXZWVrVGh1cnNkYXkgPSBnZXRZZWFyRmlyc3RUaHVyc2RheSh0aGlzLmlzb1dlZWtZZWFyKCksIHRoaXMuJHUpOwogICAgICByZXR1cm4gbm93V2Vla1RodXJzZGF5LmRpZmYoZGlmZldlZWtUaHVyc2RheSwgVykgKyAxOwogICAgfTsKICAgIHByb3RvMi5pc29XZWVrZGF5ID0gZnVuY3Rpb24od2VlaykgewogICAgICBpZiAoIXRoaXMuJHV0aWxzKCkudSh3ZWVrKSkgewogICAgICAgIHJldHVybiB0aGlzLmRheSh0aGlzLmRheSgpICUgNyA/IHdlZWsgOiB3ZWVrIC0gNyk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuZGF5KCkgfHwgNzsKICAgIH07CiAgICB2YXIgb2xkU3RhcnRPZiA9IHByb3RvMi5zdGFydE9mOwogICAgcHJvdG8yLnN0YXJ0T2YgPSBmdW5jdGlvbih1bml0cywgc3RhcnRPZikgewogICAgICB2YXIgdXRpbHMgPSB0aGlzLiR1dGlscygpOwogICAgICB2YXIgaXNTdGFydE9mID0gIXV0aWxzLnUoc3RhcnRPZikgPyBzdGFydE9mIDogdHJ1ZTsKICAgICAgdmFyIHVuaXQgPSB1dGlscy5wKHVuaXRzKTsKICAgICAgaWYgKHVuaXQgPT09IGlzb1dlZWtQcmV0dHlVbml0KSB7CiAgICAgICAgcmV0dXJuIGlzU3RhcnRPZiA/IHRoaXMuZGF0ZSh0aGlzLmRhdGUoKSAtICh0aGlzLmlzb1dlZWtkYXkoKSAtIDEpKS5zdGFydE9mKCJkYXkiKSA6IHRoaXMuZGF0ZSh0aGlzLmRhdGUoKSAtIDEgLSAodGhpcy5pc29XZWVrZGF5KCkgLSAxKSArIDcpLmVuZE9mKCJkYXkiKTsKICAgICAgfQogICAgICByZXR1cm4gb2xkU3RhcnRPZi5iaW5kKHRoaXMpKHVuaXRzLCBzdGFydE9mKTsKICAgIH07CiAgfTsKICBkYXlqcy5leHRlbmQoaXNvV2Vlayk7CiAgZGF5anMuZXh0ZW5kKGFkdmFuY2VkRm9ybWF0KTsKICBjb25zdCBGT1JNQVRfSVNPX1dFRUtfWUVBUl9XRUVLID0gIkdHR0ctW1ddV1ciOwogIGNvbnN0IF9UZW1wb3JhbENhY2hlID0gY2xhc3MgX1RlbXBvcmFsQ2FjaGUgewogICAgY29uc3RydWN0b3IoKSB7CiAgICAgIHRoaXMueWVhck1vbnRoRGF5Q2FjaGUgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLnllYXJXZWVrQ2FjaGUgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLnllYXJNb250aENhY2hlID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgdGhpcy55ZWFyQ2FjaGUgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgfQogICAgZ2V0WWVhck1vbnRoRGF5KHMyKSB7CiAgICAgIGlmICghdGhpcy55ZWFyTW9udGhEYXlDYWNoZS5oYXMoczIpKSB7CiAgICAgICAgdGhpcy55ZWFyTW9udGhEYXlDYWNoZS5zZXQoczIsIFllYXJNb250aERheUNsYXNzLnBhcnNlKHMyLCB0aGlzKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMueWVhck1vbnRoRGF5Q2FjaGUuZ2V0KHMyKTsKICAgIH0KICAgIGdldFllYXJNb250aChzMikgewogICAgICBpZiAoIXRoaXMueWVhck1vbnRoQ2FjaGUuaGFzKHMyKSkgewogICAgICAgIHRoaXMueWVhck1vbnRoQ2FjaGUuc2V0KHMyLCBZZWFyTW9udGhDbGFzcy5wYXJzZShzMiwgdGhpcykpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnllYXJNb250aENhY2hlLmdldChzMik7CiAgICB9CiAgICBnZXRZZWFyV2VlayhzMikgewogICAgICBpZiAoIXRoaXMueWVhcldlZWtDYWNoZS5oYXMoczIpKSB7CiAgICAgICAgdGhpcy55ZWFyV2Vla0NhY2hlLnNldChzMiwgWWVhcldlZWtDbGFzcy5wYXJzZShzMiwgdGhpcykpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnllYXJXZWVrQ2FjaGUuZ2V0KHMyKTsKICAgIH0KICAgIGdldFllYXIoczIpIHsKICAgICAgaWYgKCF0aGlzLnllYXJDYWNoZS5oYXMoczIpKSB7CiAgICAgICAgdGhpcy55ZWFyQ2FjaGUuc2V0KHMyLCBZZWFyQ2xhc3MucGFyc2UoczIsIHRoaXMpKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy55ZWFyQ2FjaGUuZ2V0KHMyKTsKICAgIH0KICAgIHN0YXRpYyBnZXRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuaW5zdGFuY2U7CiAgICB9CiAgfTsKICBfVGVtcG9yYWxDYWNoZS5pbnN0YW5jZSA9IG5ldyBfVGVtcG9yYWxDYWNoZSgpOwogIGxldCBUZW1wb3JhbENhY2hlID0gX1RlbXBvcmFsQ2FjaGU7CiAgY2xhc3MgWWVhck1vbnRoRGF5Q2xhc3MgewogICAgY29uc3RydWN0b3IoeWVhck51bWJlciwgbW9udGhOdW1iZXIsIGRheU51bWJlciwgY2FjaGUpIHsKICAgICAgdGhpcy55ZWFyTnVtYmVyID0geWVhck51bWJlcjsKICAgICAgdGhpcy5tb250aE51bWJlciA9IG1vbnRoTnVtYmVyOwogICAgICB0aGlzLmRheU51bWJlciA9IGRheU51bWJlcjsKICAgICAgdGhpcy5jYWNoZSA9IGNhY2hlOwogICAgICB0aGlzLnR5cGUgPSAiWWVhck1vbnRoRGF5IjsKICAgICAgdGhpcy5kYXRlID0gbmV3IERhdGUodGhpcy55ZWFyTnVtYmVyLCB0aGlzLm1vbnRoTnVtYmVyIC0gMSwgdGhpcy5kYXlOdW1iZXIpOwogICAgICB0aGlzLmRheWpzID0gZGF5anModGhpcy5kYXRlKTsKICAgICAgdGhpcy5kYXRlU3RyaW5nID0gdGhpcy50b1N0cmluZygpOwogICAgfQogICAgZ2V0IHRleHQoKSB7CiAgICAgIHJldHVybiB0aGlzLmRheWpzLmZvcm1hdCgiWVlZWS1NTS1ERCIpOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLnRleHQ7CiAgICB9CiAgICBlbmdsaXNoTmFtZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZGF5anMuZm9ybWF0KCJkZGRkLCBNTU1NIEQsIFlZWVkiKTsKICAgIH0KICAgIGdldCBmaXJzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICBnZXQgbGFzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICBnZXQgeWVhcigpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhcihgJHt0aGlzLnllYXJOdW1iZXJ9YCk7CiAgICB9CiAgICBnZXQgbW9udGgoKSB7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aCh0aGlzLmRheWpzLmZvcm1hdCgiWVlZWS1NTSIpKTsKICAgIH0KICAgIGdldCB3ZWVrKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyV2Vlayh0aGlzLmRheWpzLmZvcm1hdChGT1JNQVRfSVNPX1dFRUtfWUVBUl9XRUVLKSk7CiAgICB9CiAgICBhZGREYXlzKGRheXMpIHsKICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuZGF5anMuYWRkKGRheXMsICJkYXkiKTsKICAgICAgY29uc3QgczIgPSBkYXRlLmZvcm1hdCgiWVlZWS1NTS1ERCIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGhEYXkoczIpOwogICAgfQogICAgbWludXMob3RoZXIpIHsKICAgICAgcmV0dXJuIHRoaXMuZGF5anMuZGlmZihvdGhlci5kYXlqcywgImRheSIpOwogICAgfQogICAgc3RhdGljIHBhcnNlKHMyLCBjYWNoZSkgewogICAgICBjb25zdCBbeWVhciwgbW9udGgsIGRheV0gPSBzMi5zcGxpdCgiLSIpLm1hcCgoczIyKSA9PiBwYXJzZUludChzMjIsIDEwKSk7CiAgICAgIHJldHVybiBuZXcgWWVhck1vbnRoRGF5Q2xhc3MoeWVhciwgbW9udGgsIGRheSwgY2FjaGUpOwogICAgfQogIH0KICBjbGFzcyBZZWFyV2Vla0NsYXNzIHsKICAgIGNvbnN0cnVjdG9yKGlzb1llYXJOdW1iZXIsIGlzb1dlZWtOdW1iZXIsIGNhY2hlKSB7CiAgICAgIHRoaXMuaXNvWWVhck51bWJlciA9IGlzb1llYXJOdW1iZXI7CiAgICAgIHRoaXMuaXNvV2Vla051bWJlciA9IGlzb1dlZWtOdW1iZXI7CiAgICAgIHRoaXMuY2FjaGUgPSBjYWNoZTsKICAgICAgdGhpcy50eXBlID0gIlllYXJXZWVrIjsKICAgICAgdGhpcy5kYXRlU3RyaW5nID0gdGhpcy50b1N0cmluZygpOwogICAgfQogICAgZ2V0IHRleHQoKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmZvcm1hdChGT1JNQVRfSVNPX1dFRUtfWUVBUl9XRUVLKTsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy50ZXh0OwogICAgfQogICAgZW5nbGlzaE5hbWUoKSB7CiAgICAgIHJldHVybiBgV2VlayAke3RoaXMuaXNvV2Vla051bWJlcn0sICR7dGhpcy5pc29ZZWFyTnVtYmVyfWA7CiAgICB9CiAgICBnZXQgZmlyc3REYXkoKSB7CiAgICAgIGNvbnN0IGZpcnN0RGF5ID0gZGF5anMoKS55ZWFyKHRoaXMuaXNvWWVhck51bWJlcikubW9udGgoMSkuZGF0ZSg0KS5pc29XZWVrKHRoaXMuaXNvV2Vla051bWJlcikuc3RhcnRPZigiaXNvV2VlayIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGhEYXkoZmlyc3REYXkuZm9ybWF0KCJZWVlZLU1NLUREIikpOwogICAgfQogICAgZ2V0IGxhc3REYXkoKSB7CiAgICAgIGNvbnN0IGZpcnN0RGF5ID0gZGF5anMoKS55ZWFyKHRoaXMuaXNvWWVhck51bWJlcikuc3RhcnRPZigieWVhciIpLmFkZCgodGhpcy5pc29XZWVrTnVtYmVyIC0gMSkgKiA3LCAiZGF5Iikuc3RhcnRPZigid2VlayIpLmFkZCgxLCAiZGF5Iik7CiAgICAgIGNvbnN0IGxhc3REYXkgPSBmaXJzdERheS5hZGQoNiwgImRheSIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGhEYXkobGFzdERheS5mb3JtYXQoIllZWVktTU0tREQiKSk7CiAgICB9CiAgICBnZXQgeWVhcigpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhcihgJHt0aGlzLmlzb1llYXJOdW1iZXJ9YCk7CiAgICB9CiAgICBhZGRXZWVrcyh3ZWVrcykgewogICAgICBjb25zdCBkYXRlID0gdGhpcy5maXJzdERheS5kYXlqcy5hZGQod2Vla3MsICJ3ZWVrIik7CiAgICAgIGNvbnN0IHMyID0gZGF0ZS5mb3JtYXQoRk9STUFUX0lTT19XRUVLX1lFQVJfV0VFSyk7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJXZWVrKHMyKTsKICAgIH0KICAgIG1pbnVzKG90aGVyKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmRpZmYob3RoZXIuZmlyc3REYXkuZGF5anMsICJ3ZWVrIik7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UoczIsIGNhY2hlKSB7CiAgICAgIGNvbnN0IFt5ZWFyLCB3ZWVrXSA9IHMyLnNwbGl0KCItVyIpLm1hcCgoczIyKSA9PiBwYXJzZUludChzMjIsIDEwKSk7CiAgICAgIHJldHVybiBuZXcgWWVhcldlZWtDbGFzcyh5ZWFyLCB3ZWVrLCBjYWNoZSk7CiAgICB9CiAgfQogIGNsYXNzIFllYXJNb250aENsYXNzIHsKICAgIGNvbnN0cnVjdG9yKHllYXJOdW1iZXIsIG1vbnRoTnVtYmVyLCBjYWNoZSkgewogICAgICB0aGlzLnllYXJOdW1iZXIgPSB5ZWFyTnVtYmVyOwogICAgICB0aGlzLm1vbnRoTnVtYmVyID0gbW9udGhOdW1iZXI7CiAgICAgIHRoaXMuY2FjaGUgPSBjYWNoZTsKICAgICAgdGhpcy50eXBlID0gIlllYXJNb250aCI7CiAgICAgIHRoaXMuZGF0ZVN0cmluZyA9IHRoaXMudG9TdHJpbmcoKTsKICAgIH0KICAgIGdldCB0ZXh0KCkgewogICAgICByZXR1cm4gdGhpcy5maXJzdERheS5kYXlqcy5mb3JtYXQoIllZWVktTU0iKTsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy50ZXh0OwogICAgfQogICAgZW5nbGlzaE5hbWUoKSB7CiAgICAgIHJldHVybiBgJHttb250aE5hbWUodGhpcy5tb250aE51bWJlcil9ICR7dGhpcy55ZWFyTnVtYmVyfWA7CiAgICB9CiAgICBnZXQgZmlyc3REYXkoKSB7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aERheShkYXlqcyhgJHt0aGlzLnllYXJOdW1iZXJ9LSR7dGhpcy5tb250aE51bWJlcn0tMDFgKS5mb3JtYXQoIllZWVktTU0tREQiKSk7CiAgICB9CiAgICBnZXQgbGFzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoRGF5KAogICAgICAgIGRheWpzKGAke3RoaXMueWVhck51bWJlcn0tJHt0aGlzLm1vbnRoTnVtYmVyfS0wMWApLmVuZE9mKCJtb250aCIpLmZvcm1hdCgiWVlZWS1NTS1ERCIpCiAgICAgICk7CiAgICB9CiAgICBnZXQgeWVhcigpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhcihgJHt0aGlzLnllYXJOdW1iZXJ9YCk7CiAgICB9CiAgICBhZGRNb250aHMobW9udGhzKSB7CiAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLmZpcnN0RGF5LmRheWpzLmFkZChtb250aHMsICJtb250aCIpOwogICAgICBjb25zdCBzMiA9IGRhdGUuZm9ybWF0KCJZWVlZLU1NIik7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aChzMik7CiAgICB9CiAgICBtaW51cyhvdGhlcikgewogICAgICByZXR1cm4gdGhpcy5maXJzdERheS5kYXlqcy5kaWZmKG90aGVyLmZpcnN0RGF5LmRheWpzLCAibW9udGgiKTsKICAgIH0KICAgIHN0YXRpYyBwYXJzZShzMiwgY2FjaGUpIHsKICAgICAgY29uc3QgW3llYXIsIG1vbnRoXSA9IHMyLnNwbGl0KCItIikubWFwKChzMjIpID0+IHBhcnNlSW50KHMyMiwgMTApKTsKICAgICAgcmV0dXJuIG5ldyBZZWFyTW9udGhDbGFzcyh5ZWFyLCBtb250aCwgY2FjaGUpOwogICAgfQogIH0KICBjbGFzcyBZZWFyQ2xhc3MgewogICAgY29uc3RydWN0b3IoeWVhciwgY2FjaGUpIHsKICAgICAgdGhpcy55ZWFyID0geWVhcjsKICAgICAgdGhpcy5jYWNoZSA9IGNhY2hlOwogICAgICB0aGlzLnR5cGUgPSAiWWVhciI7CiAgICAgIHRoaXMuZGF0ZVN0cmluZyA9IHRoaXMudG9TdHJpbmcoKTsKICAgIH0KICAgIGdldCB0ZXh0KCkgewogICAgICByZXR1cm4gdGhpcy5maXJzdERheS5kYXlqcy5mb3JtYXQoIllZWVkiKTsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy50ZXh0OwogICAgfQogICAgZW5nbGlzaE5hbWUoKSB7CiAgICAgIHJldHVybiB0aGlzLnllYXIudG9TdHJpbmcoKTsKICAgIH0KICAgIGdldCBmaXJzdE1vbnRoKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGgoYCR7dGhpcy55ZWFyfS0wMWApOwogICAgfQogICAgZ2V0IGxhc3RNb250aCgpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoKGAke3RoaXMueWVhcn0tMTJgKTsKICAgIH0KICAgIGdldCBmaXJzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZmlyc3RNb250aC5maXJzdERheTsKICAgIH0KICAgIGdldCBsYXN0RGF5KCkgewogICAgICByZXR1cm4gdGhpcy5sYXN0TW9udGgubGFzdERheTsKICAgIH0KICAgIGFkZFllYXJzKHllYXJzKSB7CiAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLmZpcnN0RGF5LmRheWpzLmFkZCh5ZWFycywgInllYXIiKTsKICAgICAgY29uc3QgczIgPSBkYXRlLmZvcm1hdCgiWVlZWSIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyKHMyKTsKICAgIH0KICAgIG1pbnVzKG90aGVyKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmRpZmYob3RoZXIuZmlyc3REYXkuZGF5anMsICJ5ZWFyIik7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UoczIsIGNhY2hlKSB7CiAgICAgIGNvbnN0IHllYXIgPSBwYXJzZUludChzMiwgMTApOwogICAgICByZXR1cm4gbmV3IFllYXJDbGFzcyh5ZWFyLCBjYWNoZSk7CiAgICB9CiAgfQogIGZ1bmN0aW9uIG1vbnRoTmFtZShtb250aCkgewogICAgcmV0dXJuIGRheWpzKCkubW9udGgobW9udGggLSAxKS5mb3JtYXQoIk1NTU0iKTsKICB9CiAgZnVuY3Rpb24gdG9UZW1wb3JhbCh0ZW1wb3JhbENsYXNzKSB7CiAgICBzd2l0Y2ggKHRlbXBvcmFsQ2xhc3MudHlwZSkgewogICAgICBjYXNlICJZZWFyTW9udGhEYXkiOgogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiAiWWVhck1vbnRoRGF5IiwKICAgICAgICAgIHllYXJOdW1iZXI6IHRlbXBvcmFsQ2xhc3MueWVhck51bWJlciwKICAgICAgICAgIG1vbnRoTnVtYmVyOiB0ZW1wb3JhbENsYXNzLm1vbnRoTnVtYmVyLAogICAgICAgICAgZGF5TnVtYmVyOiB0ZW1wb3JhbENsYXNzLmRheU51bWJlciwKICAgICAgICAgIGRhdGVTdHJpbmc6IHRlbXBvcmFsQ2xhc3MuZGF0ZVN0cmluZwogICAgICAgIH07CiAgICAgIGNhc2UgIlllYXJXZWVrIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogIlllYXJXZWVrIiwKICAgICAgICAgIGlzb1llYXJOdW1iZXI6IHRlbXBvcmFsQ2xhc3MuaXNvWWVhck51bWJlciwKICAgICAgICAgIGlzb1dlZWtOdW1iZXI6IHRlbXBvcmFsQ2xhc3MuaXNvV2Vla051bWJlciwKICAgICAgICAgIGRhdGVTdHJpbmc6IHRlbXBvcmFsQ2xhc3MuZGF0ZVN0cmluZwogICAgICAgIH07CiAgICAgIGNhc2UgIlllYXJNb250aCI6CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHR5cGU6ICJZZWFyTW9udGgiLAogICAgICAgICAgeWVhck51bWJlcjogdGVtcG9yYWxDbGFzcy55ZWFyTnVtYmVyLAogICAgICAgICAgbW9udGhOdW1iZXI6IHRlbXBvcmFsQ2xhc3MubW9udGhOdW1iZXIsCiAgICAgICAgICBkYXRlU3RyaW5nOiB0ZW1wb3JhbENsYXNzLmRhdGVTdHJpbmcKICAgICAgICB9OwogICAgICBjYXNlICJZZWFyIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogIlllYXIiLAogICAgICAgICAgeWVhcjogdGVtcG9yYWxDbGFzcy55ZWFyLAogICAgICAgICAgZGF0ZVN0cmluZzogdGVtcG9yYWxDbGFzcy5kYXRlU3RyaW5nCiAgICAgICAgfTsKICAgIH0KICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVBbGxEYXlzSW5SYW5nZShzdGFydCwgZW5kKSB7CiAgICBjb25zdCBkYXlzID0gW107CiAgICBjb25zdCBkYXlzSW5CZXR3ZWVuID0gZW5kLm1pbnVzKHN0YXJ0KTsKICAgIGZvciAobGV0IGkyID0gMDsgaTIgPD0gZGF5c0luQmV0d2VlbjsgaTIrKykgewogICAgICBkYXlzLnB1c2goc3RhcnQuYWRkRGF5cyhpMikpOwogICAgfQogICAgcmV0dXJuIGRheXM7CiAgfQogIGZ1bmN0aW9uIGdlbmVyYXRlQWxsV2Vla3NJblJhbmdlKHN0YXJ0LCBlbmQpIHsKICAgIGNvbnN0IHdlZWtzID0gW107CiAgICBjb25zdCB3ZWVrc0luQmV0d2VlbiA9IGVuZC5taW51cyhzdGFydCk7CiAgICBmb3IgKGxldCBpMiA9IDA7IGkyIDw9IHdlZWtzSW5CZXR3ZWVuOyBpMisrKSB7CiAgICAgIHdlZWtzLnB1c2goc3RhcnQuYWRkV2Vla3MoaTIpKTsKICAgIH0KICAgIHJldHVybiB3ZWVrczsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVBbGxNb250aHNJblJhbmdlKHN0YXJ0LCBlbmQpIHsKICAgIGNvbnN0IG1vbnRocyA9IFtdOwogICAgY29uc3QgbW9udGhzSW5CZXR3ZWVuID0gZW5kLm1pbnVzKHN0YXJ0KTsKICAgIGZvciAobGV0IGkyID0gMDsgaTIgPD0gbW9udGhzSW5CZXR3ZWVuOyBpMisrKSB7CiAgICAgIG1vbnRocy5wdXNoKHN0YXJ0LmFkZE1vbnRocyhpMikpOwogICAgfQogICAgcmV0dXJuIG1vbnRoczsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVBbGxZZWFyc0luUmFuZ2Uoc3RhcnQsIGVuZCkgewogICAgY29uc3QgeWVhcnMgPSBbXTsKICAgIGNvbnN0IHllYXJzSW5CZXR3ZWVuID0gZW5kLm1pbnVzKHN0YXJ0KTsKICAgIGZvciAobGV0IGkyID0gMDsgaTIgPD0geWVhcnNJbkJldHdlZW47IGkyKyspIHsKICAgICAgeWVhcnMucHVzaChzdGFydC5hZGRZZWFycyhpMikpOwogICAgfQogICAgcmV0dXJuIHllYXJzOwogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZUFsbEluUmFuZ2Uoc3RhcnQsIGVuZCkgewogICAgaWYgKHN0YXJ0ID09PSBudWxsIHx8IGVuZCA9PT0gbnVsbCkgewogICAgICByZXR1cm4gW107CiAgICB9CiAgICBpZiAoc3RhcnQgaW5zdGFuY2VvZiBZZWFyTW9udGhEYXlDbGFzcyAmJiBlbmQgaW5zdGFuY2VvZiBZZWFyTW9udGhEYXlDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxEYXlzSW5SYW5nZShzdGFydCwgZW5kKTsKICAgIH0KICAgIGlmIChzdGFydCBpbnN0YW5jZW9mIFllYXJXZWVrQ2xhc3MgJiYgZW5kIGluc3RhbmNlb2YgWWVhcldlZWtDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxXZWVrc0luUmFuZ2Uoc3RhcnQsIGVuZCk7CiAgICB9CiAgICBpZiAoc3RhcnQgaW5zdGFuY2VvZiBZZWFyTW9udGhDbGFzcyAmJiBlbmQgaW5zdGFuY2VvZiBZZWFyTW9udGhDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxNb250aHNJblJhbmdlKHN0YXJ0LCBlbmQpOwogICAgfQogICAgaWYgKHN0YXJ0IGluc3RhbmNlb2YgWWVhckNsYXNzICYmIGVuZCBpbnN0YW5jZW9mIFllYXJDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxZZWFyc0luUmFuZ2Uoc3RhcnQsIGVuZCk7CiAgICB9CiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgYXJndW1lbnRzOiBzdGFydCBhbmQgZW5kIG11c3QgYmUgb2YgdGhlIHNhbWUgdHlwZTogJHtzdGFydH0sICR7ZW5kfWApOwogIH0KICBmdW5jdGlvbiBtaW51c1RlbXBvcmFsKGEyLCBiKSB7CiAgICBpZiAoYTIgaW5zdGFuY2VvZiBZZWFyTW9udGhEYXlDbGFzcyAmJiBiIGluc3RhbmNlb2YgWWVhck1vbnRoRGF5Q2xhc3MpIHsKICAgICAgcmV0dXJuIGEyLm1pbnVzKGIpOwogICAgfQogICAgaWYgKGEyIGluc3RhbmNlb2YgWWVhcldlZWtDbGFzcyAmJiBiIGluc3RhbmNlb2YgWWVhcldlZWtDbGFzcykgewogICAgICByZXR1cm4gYTIubWludXMoYik7CiAgICB9CiAgICBpZiAoYTIgaW5zdGFuY2VvZiBZZWFyTW9udGhDbGFzcyAmJiBiIGluc3RhbmNlb2YgWWVhck1vbnRoQ2xhc3MpIHsKICAgICAgcmV0dXJuIGEyLm1pbnVzKGIpOwogICAgfQogICAgaWYgKGEyIGluc3RhbmNlb2YgWWVhckNsYXNzICYmIGIgaW5zdGFuY2VvZiBZZWFyQ2xhc3MpIHsKICAgICAgcmV0dXJuIGEyLm1pbnVzKGIpOwogICAgfQogICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgY29tcGFyZSAke2EyfSBhbmQgJHtifWApOwogIH0KICBmdW5jdGlvbiBjb21wYXJlVGVtcG9yYWwoYTIsIGIpIHsKICAgIGlmIChhMiA9PT0gbnVsbCkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIGlmIChiID09PSBudWxsKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGNvbnN0IGRpZmYgPSBtaW51c1RlbXBvcmFsKGEyLCBiKTsKICAgIGlmIChkaWZmIDwgMCkgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICBpZiAoZGlmZiA+IDApIHsKICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICByZXR1cm4gMDsKICB9CiAgZnVuY3Rpb24gZ2V0TWluTWF4VGVtcG9yYWwodmFsdWVzKSB7CiAgICBsZXQgbWluID0gbnVsbDsKICAgIGxldCBtYXggPSBudWxsOwogICAgZm9yIChjb25zdCB2YWx1ZSBvZiB2YWx1ZXMpIHsKICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKG1pbiA9PT0gbnVsbCB8fCBjb21wYXJlVGVtcG9yYWwodmFsdWUsIG1pbikgPCAwKSB7CiAgICAgICAgbWluID0gdmFsdWU7CiAgICAgIH0KICAgICAgaWYgKG1heCA9PT0gbnVsbCB8fCBjb21wYXJlVGVtcG9yYWwodmFsdWUsIG1heCkgPiAwKSB7CiAgICAgICAgbWF4ID0gdmFsdWU7CiAgICAgIH0KICAgIH0KICAgIGlmIChtaW4gPT09IG51bGwgfHwgbWF4ID09PSBudWxsKSB7CiAgICAgIHJldHVybiB7IG1pbjogbnVsbCwgbWF4OiBudWxsIH07CiAgICB9CiAgICByZXR1cm4geyBtaW4sIG1heCB9OwogIH0KICBmdW5jdGlvbiBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKGRhdGUsIGdyYW51bGFyaXR5KSB7CiAgICBjb25zdCBjYWNoZSA9IFRlbXBvcmFsQ2FjaGUuZ2V0SW5zdGFuY2UoKTsKICAgIGNvbnN0IGRheSA9IGNhY2hlLmdldFllYXJNb250aERheShkYXRlKTsKICAgIHN3aXRjaCAoZ3JhbnVsYXJpdHkpIHsKICAgICAgY2FzZSAiZGF5IjoKICAgICAgICByZXR1cm4gZGF5OwogICAgICBjYXNlICJ3ZWVrIjoKICAgICAgICByZXR1cm4gZGF5LndlZWs7CiAgICAgIGNhc2UgIm1vbnRoIjoKICAgICAgICByZXR1cm4gZGF5Lm1vbnRoOwogICAgICBjYXNlICJ5ZWFyIjoKICAgICAgICByZXR1cm4gZGF5LnllYXI7CiAgICB9CiAgfQogIGZ1bmN0aW9uIGRhdGVSYW5nZUNvbXBhcmUoYTIsIGIpIHsKICAgIGlmIChhMi5kYXRlUmFuZ2UgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICBpZiAoYi5kYXRlUmFuZ2UgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgcmV0dXJuIGNvbXBhcmVUZW1wb3JhbChhMi5kYXRlUmFuZ2UsIGIuZGF0ZVJhbmdlKTsKICB9CiAgZnVuY3Rpb24gbWFwRGF0ZVRvR3JhbnVsYXJpdHlSYW5nZShkYXRhLCBncmFudWxhcml0eSkgewogICAgcmV0dXJuIHsKICAgICAgZGF0ZVJhbmdlOiBkYXRhLmRhdGUgPT09IG51bGwgPyBudWxsIDogcGFyc2VEYXRlU3RyaW5nVG9UZW1wb3JhbChkYXRhLmRhdGUsIGdyYW51bGFyaXR5KSwKICAgICAgY291bnQ6IGRhdGEuY291bnQKICAgIH07CiAgfQogIGNvbnN0IHN1YnN0aXR1dGlvblJlZ2V4ID0gL14oKD88c2VnbWVudD5bQS1aYS16MC05Xy1dKykoPz06KTopPyg/PHZhbHVlQXRSZWZlcmVuY2U+W0EtWmEtel0pPyg/PHBvc2l0aW9uPlxkKykoPzxzdWJzdGl0dXRpb25WYWx1ZT5bQS1aYS16Ll0pPyQvOwogIGNsYXNzIFN1YnN0aXR1dGlvbkNsYXNzIHsKICAgIGNvbnN0cnVjdG9yKHNlZ21lbnQsIHZhbHVlQXRSZWZlcmVuY2UsIHN1YnN0aXR1dGlvblZhbHVlLCBwb3NpdGlvbikgewogICAgICB0aGlzLnNlZ21lbnQgPSBzZWdtZW50OwogICAgICB0aGlzLnZhbHVlQXRSZWZlcmVuY2UgPSB2YWx1ZUF0UmVmZXJlbmNlOwogICAgICB0aGlzLnN1YnN0aXR1dGlvblZhbHVlID0gc3Vic3RpdHV0aW9uVmFsdWU7CiAgICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjsKICAgICAgdGhpcy50eXBlID0gInN1YnN0aXR1dGlvbiI7CiAgICAgIGNvbnN0IHNlZ21lbnRTdHJpbmcgPSB0aGlzLnNlZ21lbnQgPyBgJHt0aGlzLnNlZ21lbnR9OmAgOiAiIjsKICAgICAgY29uc3QgdmFsdWVBdFJlZmVyZW5jZVN0cmluZyA9IHRoaXMudmFsdWVBdFJlZmVyZW5jZSA/IGAke3RoaXMudmFsdWVBdFJlZmVyZW5jZX1gIDogIiI7CiAgICAgIGNvbnN0IHN1YnN0aXR1dGlvblZhbHVlU3RyaW5nID0gdGhpcy5zdWJzdGl0dXRpb25WYWx1ZSA/IGAke3RoaXMuc3Vic3RpdHV0aW9uVmFsdWV9YCA6ICIiOwogICAgICB0aGlzLmNvZGUgPSBgJHtzZWdtZW50U3RyaW5nfSR7dmFsdWVBdFJlZmVyZW5jZVN0cmluZ30ke3RoaXMucG9zaXRpb259JHtzdWJzdGl0dXRpb25WYWx1ZVN0cmluZ31gOwogICAgfQogICAgZXF1YWxzKG90aGVyKSB7CiAgICAgIGlmICghKG90aGVyIGluc3RhbmNlb2YgU3Vic3RpdHV0aW9uQ2xhc3MpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnNlZ21lbnQgPT09IG90aGVyLnNlZ21lbnQgJiYgdGhpcy52YWx1ZUF0UmVmZXJlbmNlID09PSBvdGhlci52YWx1ZUF0UmVmZXJlbmNlICYmIHRoaXMuc3Vic3RpdHV0aW9uVmFsdWUgPT09IG90aGVyLnN1YnN0aXR1dGlvblZhbHVlICYmIHRoaXMucG9zaXRpb24gPT09IG90aGVyLnBvc2l0aW9uOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLmNvZGU7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UobXV0YXRpb25TdHIpIHsKICAgICAgY29uc3QgbWF0Y2ggPSBtdXRhdGlvblN0ci5tYXRjaChzdWJzdGl0dXRpb25SZWdleCk7CiAgICAgIGlmIChtYXRjaCA9PT0gbnVsbCB8fCBtYXRjaC5ncm91cHMgPT09IHZvaWQgMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHJldHVybiBuZXcgU3Vic3RpdHV0aW9uQ2xhc3MoCiAgICAgICAgbWF0Y2guZ3JvdXBzLnNlZ21lbnQsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnZhbHVlQXRSZWZlcmVuY2UsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnN1YnN0aXR1dGlvblZhbHVlLAogICAgICAgIHBhcnNlSW50KG1hdGNoLmdyb3Vwcy5wb3NpdGlvbiwgMTApCiAgICAgICk7CiAgICB9CiAgfQogIGNvbnN0IGRlbGV0aW9uUmVnZXggPSAvXigoPzxzZWdtZW50PltBLVphLXowLTlfLV0rKSg/PTopOik/KD88dmFsdWVBdFJlZmVyZW5jZT5bQS1aYS16XSk/KD88cG9zaXRpb24+XGQrKSgtKSQvOwogIGNsYXNzIERlbGV0aW9uQ2xhc3MgewogICAgY29uc3RydWN0b3Ioc2VnbWVudCwgdmFsdWVBdFJlZmVyZW5jZSwgcG9zaXRpb24pIHsKICAgICAgdGhpcy5zZWdtZW50ID0gc2VnbWVudDsKICAgICAgdGhpcy52YWx1ZUF0UmVmZXJlbmNlID0gdmFsdWVBdFJlZmVyZW5jZTsKICAgICAgdGhpcy5wb3NpdGlvbiA9IHBvc2l0aW9uOwogICAgICB0aGlzLnR5cGUgPSAiZGVsZXRpb24iOwogICAgICBjb25zdCBzZWdtZW50U3RyaW5nID0gdGhpcy5zZWdtZW50ID8gYCR7dGhpcy5zZWdtZW50fTpgIDogIiI7CiAgICAgIGNvbnN0IHZhbHVlQXRSZWZlcmVuY2VTdHJpbmcgPSB0aGlzLnZhbHVlQXRSZWZlcmVuY2UgPyBgJHt0aGlzLnZhbHVlQXRSZWZlcmVuY2V9YCA6ICIiOwogICAgICB0aGlzLmNvZGUgPSBgJHtzZWdtZW50U3RyaW5nfSR7dmFsdWVBdFJlZmVyZW5jZVN0cmluZ30ke3RoaXMucG9zaXRpb259LWA7CiAgICB9CiAgICBlcXVhbHMob3RoZXIpIHsKICAgICAgaWYgKCEob3RoZXIgaW5zdGFuY2VvZiBEZWxldGlvbkNsYXNzKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5zZWdtZW50ID09PSBvdGhlci5zZWdtZW50ICYmIHRoaXMudmFsdWVBdFJlZmVyZW5jZSA9PT0gb3RoZXIudmFsdWVBdFJlZmVyZW5jZSAmJiB0aGlzLnBvc2l0aW9uID09PSBvdGhlci5wb3NpdGlvbjsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy5jb2RlOwogICAgfQogICAgc3RhdGljIHBhcnNlKG11dGF0aW9uU3RyKSB7CiAgICAgIGNvbnN0IG1hdGNoID0gbXV0YXRpb25TdHIubWF0Y2goZGVsZXRpb25SZWdleCk7CiAgICAgIGlmIChtYXRjaCA9PT0gbnVsbCB8fCBtYXRjaC5ncm91cHMgPT09IHZvaWQgMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHJldHVybiBuZXcgRGVsZXRpb25DbGFzcygKICAgICAgICBtYXRjaC5ncm91cHMuc2VnbWVudCwKICAgICAgICBtYXRjaC5ncm91cHMudmFsdWVBdFJlZmVyZW5jZSwKICAgICAgICBwYXJzZUludChtYXRjaC5ncm91cHMucG9zaXRpb24sIDEwKQogICAgICApOwogICAgfQogIH0KICBmdW5jdGlvbiB0b1N1YnN0aXR1dGlvbk9yRGVsZXRpb24obXV0YXRpb24pIHsKICAgIHN3aXRjaCAobXV0YXRpb24udHlwZSkgewogICAgICBjYXNlICJzdWJzdGl0dXRpb24iOgogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiAic3Vic3RpdHV0aW9uIiwKICAgICAgICAgIGNvZGU6IG11dGF0aW9uLmNvZGUsCiAgICAgICAgICBzZWdtZW50OiBtdXRhdGlvbi5zZWdtZW50LAogICAgICAgICAgcG9zaXRpb246IG11dGF0aW9uLnBvc2l0aW9uLAogICAgICAgICAgdmFsdWVBdFJlZmVyZW5jZTogbXV0YXRpb24udmFsdWVBdFJlZmVyZW5jZSwKICAgICAgICAgIHN1YnN0aXR1dGlvblZhbHVlOiBtdXRhdGlvbi5zdWJzdGl0dXRpb25WYWx1ZQogICAgICAgIH07CiAgICAgIGNhc2UgImRlbGV0aW9uIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogImRlbGV0aW9uIiwKICAgICAgICAgIGNvZGU6IG11dGF0aW9uLmNvZGUsCiAgICAgICAgICBzZWdtZW50OiBtdXRhdGlvbi5zZWdtZW50LAogICAgICAgICAgcG9zaXRpb246IG11dGF0aW9uLnBvc2l0aW9uLAogICAgICAgICAgdmFsdWVBdFJlZmVyZW5jZTogbXV0YXRpb24udmFsdWVBdFJlZmVyZW5jZQogICAgICAgIH07CiAgICB9CiAgfQogIGNsYXNzIEZldGNoU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zT3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoZmlsdGVyLCBzZXF1ZW5jZVR5cGUsIG1pblByb3BvcnRpb24pIHsKICAgICAgdGhpcy5maWx0ZXIgPSBmaWx0ZXI7CiAgICAgIHRoaXMuc2VxdWVuY2VUeXBlID0gc2VxdWVuY2VUeXBlOwogICAgICB0aGlzLm1pblByb3BvcnRpb24gPSBtaW5Qcm9wb3J0aW9uOwogICAgfQogICAgYXN5bmMgZXZhbHVhdGUobGFwaXMsIHNpZ25hbCkgewogICAgICBjb25zdCBtdXRhdGlvbnMgPSBhd2FpdCB0aGlzLmZldGNoTXV0YXRpb25zKGxhcGlzLCBzaWduYWwpOwogICAgICBjb25zdCBjb250ZW50ID0gbXV0YXRpb25zLm1hcCgKICAgICAgICAoeyBjb3VudCwgcHJvcG9ydGlvbiwgbXV0YXRpb25Gcm9tLCBtdXRhdGlvblRvLCBwb3NpdGlvbiwgc2VxdWVuY2VOYW1lIH0pID0+IHsKICAgICAgICAgIGlmIChtdXRhdGlvblRvID09PSAiLSIpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICB0eXBlOiAiZGVsZXRpb24iLAogICAgICAgICAgICAgIG11dGF0aW9uOiBuZXcgRGVsZXRpb25DbGFzcyhzZXF1ZW5jZU5hbWUgPz8gdm9pZCAwLCBtdXRhdGlvbkZyb20sIHBvc2l0aW9uKSwKICAgICAgICAgICAgICBjb3VudCwKICAgICAgICAgICAgICBwcm9wb3J0aW9uCiAgICAgICAgICAgIH07CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICB0eXBlOiAic3Vic3RpdHV0aW9uIiwKICAgICAgICAgICAgbXV0YXRpb246IG5ldyBTdWJzdGl0dXRpb25DbGFzcyhzZXF1ZW5jZU5hbWUgPz8gdm9pZCAwLCBtdXRhdGlvbkZyb20sIG11dGF0aW9uVG8sIHBvc2l0aW9uKSwKICAgICAgICAgICAgY291bnQsCiAgICAgICAgICAgIHByb3BvcnRpb24KICAgICAgICAgIH07CiAgICAgICAgfQogICAgICApOwogICAgICByZXR1cm4geyBjb250ZW50IH07CiAgICB9CiAgICBhc3luYyBmZXRjaE11dGF0aW9ucyhsYXBpcywgc2lnbmFsKSB7CiAgICAgIGNvbnN0IGZpbHRlciA9IHsKICAgICAgICAuLi50aGlzLmZpbHRlciwKICAgICAgICBtaW5Qcm9wb3J0aW9uOiB0aGlzLm1pblByb3BvcnRpb24KICAgICAgfTsKICAgICAgcmV0dXJuIGZldGNoU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zKGxhcGlzLCBmaWx0ZXIsIHRoaXMuc2VxdWVuY2VUeXBlLCBzaWduYWwpLnRoZW4oCiAgICAgICAgKHJlc3BvbnNlKSA9PiByZXNwb25zZS5kYXRhCiAgICAgICk7CiAgICB9CiAgfQogIHZhciBsJDE7CiAgbCQxID0geyBfX2U6IGZ1bmN0aW9uKG4sIGwyLCB1MiwgdCkgewogICAgZm9yICh2YXIgaTIsIG8sIHIyOyBsMiA9IGwyLl9fOyApIGlmICgoaTIgPSBsMi5fX2MpICYmICFpMi5fXykgdHJ5IHsKICAgICAgaWYgKChvID0gaTIuY29uc3RydWN0b3IpICYmIG51bGwgIT0gby5nZXREZXJpdmVkU3RhdGVGcm9tRXJyb3IgJiYgKGkyLnNldFN0YXRlKG8uZ2V0RGVyaXZlZFN0YXRlRnJvbUVycm9yKG4pKSwgcjIgPSBpMi5fX2QpLCBudWxsICE9IGkyLmNvbXBvbmVudERpZENhdGNoICYmIChpMi5jb21wb25lbnREaWRDYXRjaChuLCB0IHx8IHt9KSwgcjIgPSBpMi5fX2QpLCByMikgcmV0dXJuIGkyLl9fRSA9IGkyOwogICAgfSBjYXRjaCAobDMpIHsKICAgICAgbiA9IGwzOwogICAgfQogICAgdGhyb3cgbjsKICB9IH0sICJmdW5jdGlvbiIgPT0gdHlwZW9mIFByb21pc2UgPyBQcm9taXNlLnByb3RvdHlwZS50aGVuLmJpbmQoUHJvbWlzZS5yZXNvbHZlKCkpIDogc2V0VGltZW91dDsKICB2YXIgciwgdSwgaSwgZiA9IFtdLCBjID0gbCQxLCBlID0gYy5fX2IsIGEgPSBjLl9fciwgdiA9IGMuZGlmZmVkLCBsID0gYy5fX2MsIG0gPSBjLnVubW91bnQsIHMgPSBjLl9fOwogIGZ1bmN0aW9uIGooKSB7CiAgICBmb3IgKHZhciBuOyBuID0gZi5zaGlmdCgpOyApIGlmIChuLl9fUCAmJiBuLl9fSCkgdHJ5IHsKICAgICAgbi5fX0guX19oLmZvckVhY2goeiksIG4uX19ILl9faC5mb3JFYWNoKEIpLCBuLl9fSC5fX2ggPSBbXTsKICAgIH0gY2F0Y2ggKHQpIHsKICAgICAgbi5fX0guX19oID0gW10sIGMuX19lKHQsIG4uX192KTsKICAgIH0KICB9CiAgYy5fX2IgPSBmdW5jdGlvbihuKSB7CiAgICByID0gbnVsbCwgZSAmJiBlKG4pOwogIH0sIGMuX18gPSBmdW5jdGlvbihuLCB0KSB7CiAgICBuICYmIHQuX19rICYmIHQuX19rLl9fbSAmJiAobi5fX20gPSB0Ll9fay5fX20pLCBzICYmIHMobiwgdCk7CiAgfSwgYy5fX3IgPSBmdW5jdGlvbihuKSB7CiAgICBhICYmIGEobik7CiAgICB2YXIgaTIgPSAociA9IG4uX19jKS5fX0g7CiAgICBpMiAmJiAodSA9PT0gciA/IChpMi5fX2ggPSBbXSwgci5fX2ggPSBbXSwgaTIuX18uZm9yRWFjaChmdW5jdGlvbihuMikgewogICAgICBuMi5fX04gJiYgKG4yLl9fID0gbjIuX19OKSwgbjIuaSA9IG4yLl9fTiA9IHZvaWQgMDsKICAgIH0pKSA6IChpMi5fX2guZm9yRWFjaCh6KSwgaTIuX19oLmZvckVhY2goQiksIGkyLl9faCA9IFtdLCAwKSksIHUgPSByOwogIH0sIGMuZGlmZmVkID0gZnVuY3Rpb24obikgewogICAgdiAmJiB2KG4pOwogICAgdmFyIHQgPSBuLl9fYzsKICAgIHQgJiYgdC5fX0ggJiYgKHQuX19ILl9faC5sZW5ndGggJiYgKDEgIT09IGYucHVzaCh0KSAmJiBpID09PSBjLnJlcXVlc3RBbmltYXRpb25GcmFtZSB8fCAoKGkgPSBjLnJlcXVlc3RBbmltYXRpb25GcmFtZSkgfHwgdykoaikpLCB0Ll9fSC5fXy5mb3JFYWNoKGZ1bmN0aW9uKG4yKSB7CiAgICAgIG4yLmkgJiYgKG4yLl9fSCA9IG4yLmkpLCBuMi5pID0gdm9pZCAwOwogICAgfSkpLCB1ID0gciA9IG51bGw7CiAgfSwgYy5fX2MgPSBmdW5jdGlvbihuLCB0KSB7CiAgICB0LnNvbWUoZnVuY3Rpb24objIpIHsKICAgICAgdHJ5IHsKICAgICAgICBuMi5fX2guZm9yRWFjaCh6KSwgbjIuX19oID0gbjIuX19oLmZpbHRlcihmdW5jdGlvbihuMykgewogICAgICAgICAgcmV0dXJuICFuMy5fXyB8fCBCKG4zKTsKICAgICAgICB9KTsKICAgICAgfSBjYXRjaCAocjIpIHsKICAgICAgICB0LnNvbWUoZnVuY3Rpb24objMpIHsKICAgICAgICAgIG4zLl9faCAmJiAobjMuX19oID0gW10pOwogICAgICAgIH0pLCB0ID0gW10sIGMuX19lKHIyLCBuMi5fX3YpOwogICAgICB9CiAgICB9KSwgbCAmJiBsKG4sIHQpOwogIH0sIGMudW5tb3VudCA9IGZ1bmN0aW9uKG4pIHsKICAgIG0gJiYgbShuKTsKICAgIHZhciB0LCByMiA9IG4uX19jOwogICAgcjIgJiYgcjIuX19IICYmIChyMi5fX0guX18uZm9yRWFjaChmdW5jdGlvbihuMikgewogICAgICB0cnkgewogICAgICAgIHoobjIpOwogICAgICB9IGNhdGNoIChuMykgewogICAgICAgIHQgPSBuMzsKICAgICAgfQogICAgfSksIHIyLl9fSCA9IHZvaWQgMCwgdCAmJiBjLl9fZSh0LCByMi5fX3YpKTsKICB9OwogIHZhciBrID0gImZ1bmN0aW9uIiA9PSB0eXBlb2YgcmVxdWVzdEFuaW1hdGlvbkZyYW1lOwogIGZ1bmN0aW9uIHcobikgewogICAgdmFyIHQsIHIyID0gZnVuY3Rpb24oKSB7CiAgICAgIGNsZWFyVGltZW91dCh1MiksIGsgJiYgY2FuY2VsQW5pbWF0aW9uRnJhbWUodCksIHNldFRpbWVvdXQobik7CiAgICB9LCB1MiA9IHNldFRpbWVvdXQocjIsIDEwMCk7CiAgICBrICYmICh0ID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHIyKSk7CiAgfQogIGZ1bmN0aW9uIHoobikgewogICAgdmFyIHQgPSByLCB1MiA9IG4uX19jOwogICAgImZ1bmN0aW9uIiA9PSB0eXBlb2YgdTIgJiYgKG4uX19jID0gdm9pZCAwLCB1MigpKSwgciA9IHQ7CiAgfQogIGZ1bmN0aW9uIEIobikgewogICAgdmFyIHQgPSByOwogICAgbi5fX2MgPSBuLl9fKCksIHIgPSB0OwogIH0KICBjbGFzcyBVc2VyRmFjaW5nRXJyb3IgZXh0ZW5kcyBFcnJvciB7CiAgICBjb25zdHJ1Y3RvcihoZWFkbGluZSwgbWVzc2FnZSkgewogICAgICBzdXBlcihtZXNzYWdlKTsKICAgICAgdGhpcy5oZWFkbGluZSA9IGhlYWRsaW5lOwogICAgICB0aGlzLm5hbWUgPSAiVXNlckZhY2luZ0Vycm9yIjsKICAgIH0KICB9CiAgY2xhc3MgTWFwMmRCYXNlIHsKICAgIGNvbnN0cnVjdG9yKHNlcmlhbGl6ZUZpcnN0QXhpcywgc2VyaWFsaXplU2Vjb25kQXhpcywgaW5pdGlhbENvbnRlbnQpIHsKICAgICAgdGhpcy5zZXJpYWxpemVGaXJzdEF4aXMgPSBzZXJpYWxpemVGaXJzdEF4aXM7CiAgICAgIHRoaXMuc2VyaWFsaXplU2Vjb25kQXhpcyA9IHNlcmlhbGl6ZVNlY29uZEF4aXM7CiAgICAgIHRoaXMuZGF0YSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgIHRoaXMua2V5c0ZpcnN0QXhpcyA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgIHRoaXMua2V5c1NlY29uZEF4aXMgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICBpZiAoaW5pdGlhbENvbnRlbnQpIHsKICAgICAgICB0aGlzLmtleXNGaXJzdEF4aXMgPSBuZXcgTWFwKGluaXRpYWxDb250ZW50LmtleXNGaXJzdEF4aXMpOwogICAgICAgIHRoaXMua2V5c1NlY29uZEF4aXMgPSBuZXcgTWFwKGluaXRpYWxDb250ZW50LmtleXNTZWNvbmRBeGlzKTsKICAgICAgICB0aGlzLmRhdGEgPSBuZXcgTWFwKGluaXRpYWxDb250ZW50LmRhdGEpOwogICAgICB9CiAgICB9CiAgICBnZXQoa2V5Rmlyc3RBeGlzLCBrZXlTZWNvbmRBeGlzKSB7CiAgICAgIHZhciBfYTsKICAgICAgY29uc3Qgc2VyaWFsaXplZEtleUZpcnN0QXhpcyA9IHRoaXMuc2VyaWFsaXplRmlyc3RBeGlzKGtleUZpcnN0QXhpcyk7CiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRLZXlTZWNvbmRBeGlzID0gdGhpcy5zZXJpYWxpemVTZWNvbmRBeGlzKGtleVNlY29uZEF4aXMpOwogICAgICByZXR1cm4gKF9hID0gdGhpcy5kYXRhLmdldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKSkgPT0gbnVsbCA/IHZvaWQgMCA6IF9hLmdldChzZXJpYWxpemVkS2V5U2Vjb25kQXhpcyk7CiAgICB9CiAgICBnZXRSb3coa2V5LCBmaWxsRW1wdHlXaXRoKSB7CiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMgPSB0aGlzLnNlcmlhbGl6ZUZpcnN0QXhpcyhrZXkpOwogICAgICBjb25zdCByb3cgPSB0aGlzLmRhdGEuZ2V0KHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMpOwogICAgICBpZiAocm93ID09PSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gW107CiAgICAgIH0KICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5rZXlzU2Vjb25kQXhpcy5rZXlzKCkpLm1hcCgoa2V5MikgPT4gcm93LmdldChrZXkyKSA/PyBmaWxsRW1wdHlXaXRoKTsKICAgIH0KICAgIHNldChrZXlGaXJzdEF4aXMsIGtleVNlY29uZEF4aXMsIHZhbHVlKSB7CiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMgPSB0aGlzLnNlcmlhbGl6ZUZpcnN0QXhpcyhrZXlGaXJzdEF4aXMpOwogICAgICBjb25zdCBzZXJpYWxpemVkS2V5U2Vjb25kQXhpcyA9IHRoaXMuc2VyaWFsaXplU2Vjb25kQXhpcyhrZXlTZWNvbmRBeGlzKTsKICAgICAgaWYgKCF0aGlzLmRhdGEuaGFzKHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMpKSB7CiAgICAgICAgdGhpcy5kYXRhLnNldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzLCAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpKTsKICAgICAgfQogICAgICB0aGlzLmRhdGEuZ2V0KHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMpLnNldChzZXJpYWxpemVkS2V5U2Vjb25kQXhpcywgdmFsdWUpOwogICAgICB0aGlzLmtleXNGaXJzdEF4aXMuc2V0KHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMsIGtleUZpcnN0QXhpcyk7CiAgICAgIHRoaXMua2V5c1NlY29uZEF4aXMuc2V0KHNlcmlhbGl6ZWRLZXlTZWNvbmRBeGlzLCBrZXlTZWNvbmRBeGlzKTsKICAgIH0KICAgIGRlbGV0ZVJvdyhrZXkpIHsKICAgICAgY29uc3Qgc2VyaWFsaXplZEtleUZpcnN0QXhpcyA9IHRoaXMuc2VyaWFsaXplRmlyc3RBeGlzKGtleSk7CiAgICAgIHRoaXMuZGF0YS5kZWxldGUoc2VyaWFsaXplZEtleUZpcnN0QXhpcyk7CiAgICAgIHRoaXMua2V5c0ZpcnN0QXhpcy5kZWxldGUoc2VyaWFsaXplZEtleUZpcnN0QXhpcyk7CiAgICB9CiAgICBnZXRGaXJzdEF4aXNLZXlzKCkgewogICAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLmtleXNGaXJzdEF4aXMudmFsdWVzKCkpOwogICAgfQogICAgZ2V0U2Vjb25kQXhpc0tleXMoKSB7CiAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMua2V5c1NlY29uZEF4aXMudmFsdWVzKCkpOwogICAgfQogICAgZ2V0QXNBcnJheShmaWxsRW1wdHlXaXRoKSB7CiAgICAgIHJldHVybiB0aGlzLmdldEZpcnN0QXhpc0tleXMoKS5tYXAoKGZpcnN0QXhpc0tleSkgPT4gewogICAgICAgIHJldHVybiB0aGlzLmdldFNlY29uZEF4aXNLZXlzKCkubWFwKChzZWNvbmRBeGlzS2V5KSA9PiB7CiAgICAgICAgICByZXR1cm4gdGhpcy5nZXQoZmlyc3RBeGlzS2V5LCBzZWNvbmRBeGlzS2V5KSA/PyBmaWxsRW1wdHlXaXRoOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0KICAgIGdldENvbnRlbnRzKCkgewogICAgICByZXR1cm4gewogICAgICAgIGtleXNGaXJzdEF4aXM6IHRoaXMua2V5c0ZpcnN0QXhpcywKICAgICAgICBrZXlzU2Vjb25kQXhpczogdGhpcy5rZXlzU2Vjb25kQXhpcywKICAgICAgICBkYXRhOiB0aGlzLmRhdGEKICAgICAgfTsKICAgIH0KICB9CiAgY2xhc3MgQmFzZU11dGF0aW9uT3ZlclRpbWVEYXRhTWFwIGV4dGVuZHMgTWFwMmRCYXNlIHsKICAgIGNvbnN0cnVjdG9yKGluaXRpYWxDb250ZW50KSB7CiAgICAgIHN1cGVyKHNlcmlhbGl6ZVN1YnN0aXR1dGlvbk9yRGVsZXRpb24sIHNlcmlhbGl6ZVRlbXBvcmFsLCBpbml0aWFsQ29udGVudCk7CiAgICB9CiAgfQogIGNvbnN0IHNvcnRTdWJzdGl0dXRpb25zQW5kRGVsZXRpb25zID0gKGEyLCBiKSA9PiB7CiAgICBpZiAoYTIuc2VnbWVudCAhPT0gYi5zZWdtZW50KSB7CiAgICAgIHJldHVybiBjb21wYXJlU2VnbWVudHMoYTIuc2VnbWVudCwgYi5zZWdtZW50KTsKICAgIH0KICAgIGlmIChhMi5wb3NpdGlvbiAhPT0gYi5wb3NpdGlvbikgewogICAgICByZXR1cm4gY29tcGFyZVBvc2l0aW9ucyhhMi5wb3NpdGlvbiwgYi5wb3NpdGlvbik7CiAgICB9CiAgICBjb25zdCBhSXNEZWxldGlvbiA9IGEyIGluc3RhbmNlb2YgRGVsZXRpb25DbGFzczsKICAgIGNvbnN0IGJJc0RlbGV0aW9uID0gYiBpbnN0YW5jZW9mIERlbGV0aW9uQ2xhc3M7CiAgICBpZiAoYUlzRGVsZXRpb24gIT09IGJJc0RlbGV0aW9uKSB7CiAgICAgIHJldHVybiBhSXNEZWxldGlvbiA/IDEgOiAtMTsKICAgIH0KICAgIGlmICghYUlzRGVsZXRpb24gJiYgIWJJc0RlbGV0aW9uKSB7CiAgICAgIGlmIChhMi5zdWJzdGl0dXRpb25WYWx1ZSAhPT0gYi5zdWJzdGl0dXRpb25WYWx1ZSkgewogICAgICAgIHJldHVybiBjb21wYXJlU3Vic3RpdHV0aW9uVmFsdWVzKGEyLnN1YnN0aXR1dGlvblZhbHVlLCBiLnN1YnN0aXR1dGlvblZhbHVlKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIDA7CiAgfTsKICBjb25zdCBjb21wYXJlU2VnbWVudHMgPSAoYTIsIGIpID0+IHsKICAgIGlmIChhMiA9PT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGlmIChiID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICByZXR1cm4gYTIubG9jYWxlQ29tcGFyZShiKTsKICB9OwogIGNvbnN0IGNvbXBhcmVQb3NpdGlvbnMgPSAoYTIsIGIpID0+IHsKICAgIHJldHVybiBhMiAtIGI7CiAgfTsKICBjb25zdCBjb21wYXJlU3Vic3RpdHV0aW9uVmFsdWVzID0gKGEyLCBiKSA9PiB7CiAgICBpZiAoYTIgPT09IHZvaWQgMCkgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICBpZiAoYiA9PT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiAxOwogICAgfQogICAgcmV0dXJuIGEyLmxvY2FsZUNvbXBhcmUoYik7CiAgfTsKICBjb25zdCBNQVhfTlVNQkVSX09GX0dSSURfQ09MVU1OUyA9IDIwMDsKICBhc3luYyBmdW5jdGlvbiBxdWVyeU92ZXJhbGxNdXRhdGlvbkRhdGEoewogICAgbGFwaXNGaWx0ZXIsCiAgICBzZXF1ZW5jZVR5cGUsCiAgICBsYXBpcywKICAgIGdyYW51bGFyaXR5LAogICAgbGFwaXNEYXRlRmllbGQsCiAgICBzaWduYWwKICB9KSB7CiAgICBjb25zdCBhbGxEYXRlcyA9IGF3YWl0IGdldERhdGVzSW5EYXRhc2V0KGxhcGlzRmlsdGVyLCBsYXBpcywgZ3JhbnVsYXJpdHksIGxhcGlzRGF0ZUZpZWxkLCBzaWduYWwpOwogICAgY29uc3QgZmlsdGVyID0gewogICAgICAuLi5sYXBpc0ZpbHRlciwKICAgICAgW2Ake2xhcGlzRGF0ZUZpZWxkfUZyb21gXTogYWxsRGF0ZXNbMF0uZmlyc3REYXkudG9TdHJpbmcoKSwKICAgICAgW2Ake2xhcGlzRGF0ZUZpZWxkfVRvYF06IGFsbERhdGVzW2FsbERhdGVzLmxlbmd0aCAtIDFdLmxhc3REYXkudG9TdHJpbmcoKQogICAgfTsKICAgIHJldHVybiBmZXRjaEFuZFByZXBhcmVTdWJzdGl0dXRpb25zT3JEZWxldGlvbnMoZmlsdGVyLCBzZXF1ZW5jZVR5cGUpLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogIH0KICBhc3luYyBmdW5jdGlvbiBxdWVyeU11dGF0aW9uc092ZXJUaW1lRGF0YSh7CiAgICBsYXBpc0ZpbHRlciwKICAgIHNlcXVlbmNlVHlwZSwKICAgIGxhcGlzLAogICAgbGFwaXNEYXRlRmllbGQsCiAgICBncmFudWxhcml0eSwKICAgIHNpZ25hbAogIH0pIHsKICAgIGNvbnN0IGFsbERhdGVzID0gYXdhaXQgZ2V0RGF0ZXNJbkRhdGFzZXQobGFwaXNGaWx0ZXIsIGxhcGlzLCBncmFudWxhcml0eSwgbGFwaXNEYXRlRmllbGQsIHNpZ25hbCk7CiAgICBpZiAoYWxsRGF0ZXMubGVuZ3RoID4gTUFYX05VTUJFUl9PRl9HUklEX0NPTFVNTlMpIHsKICAgICAgdGhyb3cgbmV3IFVzZXJGYWNpbmdFcnJvcigKICAgICAgICAiVG9vIG1hbnkgZGF0ZXMiLAogICAgICAgIGBUaGUgZGF0YXNldCB3b3VsZCBjb250YWluICR7YWxsRGF0ZXMubGVuZ3RofSBkYXRlIGludGVydmFscy4gUGxlYXNlIHJlZHVjZSB0aGUgbnVtYmVyIHRvIGJlbG93ICR7TUFYX05VTUJFUl9PRl9HUklEX0NPTFVNTlN9IHRvIGRpc3BsYXkgdGhlIGRhdGEuIFlvdSBjYW4gYWNoaWV2ZSB0aGlzIGJ5IGVpdGhlciBuYXJyb3dpbmcgdGhlIGRhdGUgcmFuZ2UgaW4gdGhlIHByb3ZpZGVkIExBUElTIGZpbHRlciBvciBieSBzZWxlY3RpbmcgYSBsYXJnZXIgZ3JhbnVsYXJpdHkuYAogICAgICApOwogICAgfQogICAgY29uc3Qgc3ViUXVlcmllcyA9IGFsbERhdGVzLm1hcChhc3luYyAoZGF0ZSkgPT4gewogICAgICBjb25zdCBkYXRlRnJvbSA9IGRhdGUuZmlyc3REYXkudG9TdHJpbmcoKTsKICAgICAgY29uc3QgZGF0ZVRvID0gZGF0ZS5sYXN0RGF5LnRvU3RyaW5nKCk7CiAgICAgIGNvbnN0IGZpbHRlciA9IHsKICAgICAgICAuLi5sYXBpc0ZpbHRlciwKICAgICAgICBbYCR7bGFwaXNEYXRlRmllbGR9RnJvbWBdOiBkYXRlRnJvbSwKICAgICAgICBbYCR7bGFwaXNEYXRlRmllbGR9VG9gXTogZGF0ZVRvCiAgICAgIH07CiAgICAgIGNvbnN0IGRhdGEyID0gYXdhaXQgZmV0Y2hBbmRQcmVwYXJlU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zKGZpbHRlciwgc2VxdWVuY2VUeXBlKS5ldmFsdWF0ZShsYXBpcywgc2lnbmFsKTsKICAgICAgY29uc3QgdG90YWxDb3VudFF1ZXJ5ID0gYXdhaXQgZ2V0VG90YWxOdW1iZXJPZlNlcXVlbmNlc0luRGF0ZVJhbmdlKGZpbHRlcikuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgZGF0ZSwKICAgICAgICBtdXRhdGlvbnM6IGRhdGEyLmNvbnRlbnQsCiAgICAgICAgdG90YWxDb3VudDogdG90YWxDb3VudFF1ZXJ5LmNvbnRlbnRbMF0uY291bnQKICAgICAgfTsKICAgIH0pOwogICAgY29uc3QgZGF0YSA9IGF3YWl0IFByb21pc2UuYWxsKHN1YlF1ZXJpZXMpOwogICAgY29uc3Qgb3ZlcmFsbE11dGF0aW9uc0RhdGEgPSAoYXdhaXQgcXVlcnlPdmVyYWxsTXV0YXRpb25EYXRhKHsKICAgICAgbGFwaXNGaWx0ZXIsCiAgICAgIHNlcXVlbmNlVHlwZSwKICAgICAgbGFwaXMsCiAgICAgIGxhcGlzRGF0ZUZpZWxkLAogICAgICBncmFudWxhcml0eQogICAgfSkpLmNvbnRlbnQ7CiAgICByZXR1cm4gewogICAgICBtdXRhdGlvbk92ZXJUaW1lRGF0YTogZ3JvdXBCeU11dGF0aW9uKGRhdGEsIG92ZXJhbGxNdXRhdGlvbnNEYXRhKSwKICAgICAgb3ZlcmFsbE11dGF0aW9uRGF0YTogb3ZlcmFsbE11dGF0aW9uc0RhdGEKICAgIH07CiAgfQogIGFzeW5jIGZ1bmN0aW9uIGdldERhdGVzSW5EYXRhc2V0KGxhcGlzRmlsdGVyLCBsYXBpcywgZ3JhbnVsYXJpdHksIGxhcGlzRGF0ZUZpZWxkLCBzaWduYWwpIHsKICAgIGNvbnN0IHsgY29udGVudDogYXZhaWxhYmxlRGF0ZXMgfSA9IGF3YWl0IHF1ZXJ5QXZhaWxhYmxlRGF0ZXMoCiAgICAgIGxhcGlzRmlsdGVyLAogICAgICBsYXBpcywKICAgICAgZ3JhbnVsYXJpdHksCiAgICAgIGxhcGlzRGF0ZUZpZWxkLAogICAgICBzaWduYWwKICAgICk7CiAgICBjb25zdCB7IGRhdGVGcm9tLCBkYXRlVG8gfSA9IGdldERhdGVSYW5nZUZyb21GaWx0ZXIobGFwaXNGaWx0ZXIsIGxhcGlzRGF0ZUZpZWxkLCBncmFudWxhcml0eSk7CiAgICBjb25zdCB7IG1pbiwgbWF4IH0gPSBnZXRNaW5NYXhUZW1wb3JhbChhdmFpbGFibGVEYXRlcyk7CiAgICByZXR1cm4gZ2VuZXJhdGVBbGxJblJhbmdlKGRhdGVGcm9tID8/IG1pbiwgZGF0ZVRvID8/IG1heCk7CiAgfQogIGZ1bmN0aW9uIGdldERhdGVSYW5nZUZyb21GaWx0ZXIobGFwaXNGaWx0ZXIsIGxhcGlzRGF0ZUZpZWxkLCBncmFudWxhcml0eSkgewogICAgY29uc3QgdmFsdWVGcm9tRmlsdGVyID0gbGFwaXNGaWx0ZXJbbGFwaXNEYXRlRmllbGRdOwogICAgaWYgKHZhbHVlRnJvbUZpbHRlcikgewogICAgICByZXR1cm4gewogICAgICAgIGRhdGVGcm9tOiBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKHZhbHVlRnJvbUZpbHRlciwgZ3JhbnVsYXJpdHkpLAogICAgICAgIGRhdGVUbzogcGFyc2VEYXRlU3RyaW5nVG9UZW1wb3JhbCh2YWx1ZUZyb21GaWx0ZXIsIGdyYW51bGFyaXR5KQogICAgICB9OwogICAgfQogICAgY29uc3QgbWluRnJvbUZpbHRlciA9IGxhcGlzRmlsdGVyW2Ake2xhcGlzRGF0ZUZpZWxkfUZyb21gXTsKICAgIGNvbnN0IG1heEZyb21GaWx0ZXIgPSBsYXBpc0ZpbHRlcltgJHtsYXBpc0RhdGVGaWVsZH1Ub2BdOwogICAgcmV0dXJuIHsKICAgICAgZGF0ZUZyb206IG1pbkZyb21GaWx0ZXIgPyBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKG1pbkZyb21GaWx0ZXIsIGdyYW51bGFyaXR5KSA6IG51bGwsCiAgICAgIGRhdGVUbzogbWF4RnJvbUZpbHRlciA/IHBhcnNlRGF0ZVN0cmluZ1RvVGVtcG9yYWwobWF4RnJvbUZpbHRlciwgZ3JhbnVsYXJpdHkpIDogbnVsbAogICAgfTsKICB9CiAgZnVuY3Rpb24gcXVlcnlBdmFpbGFibGVEYXRlcyhsYXBpc0ZpbHRlciwgbGFwaXMsIGdyYW51bGFyaXR5LCBsYXBpc0RhdGVGaWVsZCwgc2lnbmFsKSB7CiAgICByZXR1cm4gZmV0Y2hBbmRQcmVwYXJlRGF0ZXMobGFwaXNGaWx0ZXIsIGdyYW51bGFyaXR5LCBsYXBpc0RhdGVGaWVsZCkuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgfQogIGZ1bmN0aW9uIGZldGNoQW5kUHJlcGFyZURhdGVzKGZpbHRlciwgZ3JhbnVsYXJpdHksIGxhcGlzRGF0ZUZpZWxkKSB7CiAgICBjb25zdCBmZXRjaERhdGEgPSBuZXcgRmV0Y2hBZ2dyZWdhdGVkT3BlcmF0b3IoZmlsdGVyLCBbbGFwaXNEYXRlRmllbGRdKTsKICAgIGNvbnN0IGRhdGFXaXRoRml4ZWREYXRlS2V5ID0gbmV3IFJlbmFtZUZpZWxkT3BlcmF0b3IoZmV0Y2hEYXRhLCBsYXBpc0RhdGVGaWVsZCwgImRhdGUiKTsKICAgIGNvbnN0IG1hcERhdGEgPSBuZXcgTWFwT3BlcmF0b3IoZGF0YVdpdGhGaXhlZERhdGVLZXksIChkYXRhKSA9PiBtYXBEYXRlVG9HcmFudWxhcml0eVJhbmdlKGRhdGEsIGdyYW51bGFyaXR5KSk7CiAgICBjb25zdCBncm91cEJ5RGF0YSA9IG5ldyBHcm91cEJ5QW5kU3VtT3BlcmF0b3IobWFwRGF0YSwgImRhdGVSYW5nZSIsICJjb3VudCIpOwogICAgY29uc3Qgc29ydERhdGEgPSBuZXcgU29ydE9wZXJhdG9yKGdyb3VwQnlEYXRhLCBkYXRlUmFuZ2VDb21wYXJlKTsKICAgIHJldHVybiBuZXcgTWFwT3BlcmF0b3Ioc29ydERhdGEsIChkYXRhKSA9PiBkYXRhLmRhdGVSYW5nZSk7CiAgfQogIGZ1bmN0aW9uIGZldGNoQW5kUHJlcGFyZVN1YnN0aXR1dGlvbnNPckRlbGV0aW9ucyhmaWx0ZXIsIHNlcXVlbmNlVHlwZSkgewogICAgcmV0dXJuIG5ldyBGZXRjaFN1YnN0aXR1dGlvbnNPckRlbGV0aW9uc09wZXJhdG9yKGZpbHRlciwgc2VxdWVuY2VUeXBlLCAxZS0zKTsKICB9CiAgZnVuY3Rpb24gc2VyaWFsaXplU3Vic3RpdHV0aW9uT3JEZWxldGlvbihtdXRhdGlvbikgewogICAgcmV0dXJuIG11dGF0aW9uLmNvZGU7CiAgfQogIGZ1bmN0aW9uIHNlcmlhbGl6ZVRlbXBvcmFsKGRhdGUpIHsKICAgIHJldHVybiBkYXRlLmRhdGVTdHJpbmc7CiAgfQogIGZ1bmN0aW9uIGdyb3VwQnlNdXRhdGlvbihkYXRhLCBvdmVyYWxsTXV0YXRpb25EYXRhKSB7CiAgICBjb25zdCBkYXRhQXJyYXkgPSBuZXcgQmFzZU11dGF0aW9uT3ZlclRpbWVEYXRhTWFwKCk7CiAgICBjb25zdCBhbGxEYXRlcyA9IGRhdGEubWFwKChtdXRhdGlvbkRhdGEpID0+IG11dGF0aW9uRGF0YS5kYXRlKTsKICAgIGNvbnN0IHNvcnRlZE92ZXJhbGxNdXRhdGlvbkRhdGEgPSBvdmVyYWxsTXV0YXRpb25EYXRhLnNvcnQoKGEyLCBiKSA9PiBzb3J0U3Vic3RpdHV0aW9uc0FuZERlbGV0aW9ucyhhMi5tdXRhdGlvbiwgYi5tdXRhdGlvbikpLm1hcCgoZW50cnkpID0+IHsKICAgICAgcmV0dXJuIHRvU3Vic3RpdHV0aW9uT3JEZWxldGlvbihlbnRyeS5tdXRhdGlvbik7CiAgICB9KTsKICAgIGNvbnN0IHNvcnRlZERhdGVzID0gYWxsRGF0ZXMuc29ydCgoYTIsIGIpID0+IGNvbXBhcmVUZW1wb3JhbChhMiwgYikpLm1hcCgoZGF0ZSkgPT4gdG9UZW1wb3JhbChkYXRlKSk7CiAgICBzb3J0ZWRPdmVyYWxsTXV0YXRpb25EYXRhLmZvckVhY2goKG11dGF0aW9uRGF0YSkgPT4gewogICAgICBzb3J0ZWREYXRlcy5mb3JFYWNoKChkYXRlKSA9PiB7CiAgICAgICAgZGF0YUFycmF5LnNldChtdXRhdGlvbkRhdGEsIGRhdGUsIHsKICAgICAgICAgIGNvdW50OiAwLAogICAgICAgICAgcHJvcG9ydGlvbjogMCwKICAgICAgICAgIHRvdGFsQ291bnQ6IDAKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9KTsKICAgIGRhdGEuZm9yRWFjaCgobXV0YXRpb25EYXRhKSA9PiB7CiAgICAgIG11dGF0aW9uRGF0YS5tdXRhdGlvbnMuZm9yRWFjaCgobXV0YXRpb25FbnRyeSkgPT4gewogICAgICAgIGNvbnN0IG11dGF0aW9uID0gdG9TdWJzdGl0dXRpb25PckRlbGV0aW9uKG11dGF0aW9uRW50cnkubXV0YXRpb24pOwogICAgICAgIGNvbnN0IGRhdGUgPSB0b1RlbXBvcmFsKG11dGF0aW9uRGF0YS5kYXRlKTsKICAgICAgICBpZiAoZGF0YUFycmF5LmdldChtdXRhdGlvbiwgZGF0ZSkgIT09IHZvaWQgMCkgewogICAgICAgICAgZGF0YUFycmF5LnNldChtdXRhdGlvbiwgZGF0ZSwgewogICAgICAgICAgICBjb3VudDogbXV0YXRpb25FbnRyeS5jb3VudCwKICAgICAgICAgICAgcHJvcG9ydGlvbjogbXV0YXRpb25FbnRyeS5wcm9wb3J0aW9uLAogICAgICAgICAgICB0b3RhbENvdW50OiBtdXRhdGlvbkRhdGEudG90YWxDb3VudAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0pOwogICAgcmV0dXJuIGRhdGFBcnJheTsKICB9CiAgZnVuY3Rpb24gZ2V0VG90YWxOdW1iZXJPZlNlcXVlbmNlc0luRGF0ZVJhbmdlKGZpbHRlcikgewogICAgcmV0dXJuIG5ldyBGZXRjaEFnZ3JlZ2F0ZWRPcGVyYXRvcihmaWx0ZXIpOwogIH0KICBhc3luYyBmdW5jdGlvbiB3b3JrZXJGdW5jdGlvbihxdWVyeUZ1bmN0aW9uKSB7CiAgICB0cnkgewogICAgICBwb3N0TWVzc2FnZSh7IHN0YXR1czogImxvYWRpbmciIH0pOwogICAgICBjb25zdCB3b3JrZXJSZXNwb25zZSA9IGF3YWl0IHF1ZXJ5RnVuY3Rpb24oKTsKICAgICAgcG9zdE1lc3NhZ2UoewogICAgICAgIHN0YXR1czogInN1Y2Nlc3MiLAogICAgICAgIGRhdGE6IHdvcmtlclJlc3BvbnNlCiAgICAgIH0pOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgcG9zdE1lc3NhZ2UoeyBzdGF0dXM6ICJlcnJvciIsIGVycm9yIH0pOwogICAgfQogIH0KICBhc3luYyBmdW5jdGlvbiBnZXRNdXRhdGlvbk92ZXJUaW1lV29ya2VyRnVuY3Rpb24oZXZlbnQpIHsKICAgIGNvbnN0IG11dGF0aW9uT3ZlclRpbWVEYXRhID0gYXdhaXQgcXVlcnlNdXRhdGlvbnNPdmVyVGltZURhdGEoZXZlbnQuZGF0YSk7CiAgICBjb25zdCB3b3JrZXJSZXNwb25zZSA9IHsKICAgICAgb3ZlcmFsbE11dGF0aW9uRGF0YTogbXV0YXRpb25PdmVyVGltZURhdGEub3ZlcmFsbE11dGF0aW9uRGF0YSwKICAgICAgbXV0YXRpb25PdmVyVGltZVNlcmlhbGl6ZWQ6IG11dGF0aW9uT3ZlclRpbWVEYXRhLm11dGF0aW9uT3ZlclRpbWVEYXRhLmdldENvbnRlbnRzKCkKICAgIH07CiAgICByZXR1cm4gd29ya2VyUmVzcG9uc2U7CiAgfQogIHNlbGYub25tZXNzYWdlID0gYXN5bmMgZnVuY3Rpb24oZXZlbnQpIHsKICAgIGF3YWl0IHdvcmtlckZ1bmN0aW9uKCgpID0+IGdldE11dGF0aW9uT3ZlclRpbWVXb3JrZXJGdW5jdGlvbihldmVudCkpOwogIH07Cn0pKCk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPW11dGF0aW9uT3ZlclRpbWVXb3JrZXItQk9DWHRLemQuanMubWFwCg==";
8473
8465
  const decodeBase64 = (base64) => Uint8Array.from(atob(base64), (c2) => c2.charCodeAt(0));
8474
8466
  const blob = typeof self !== "undefined" && self.Blob && new Blob([decodeBase64(encodedJs)], { type: "text/javascript;charset=utf-8" });
8475
8467
  function WorkerWrapper(options2) {
@@ -8495,8 +8487,14 @@ function WorkerWrapper(options2) {
8495
8487
  objURL && (self.URL || self.webkitURL).revokeObjectURL(objURL);
8496
8488
  }
8497
8489
  }
8490
+ function serializeSubstitutionOrDeletion(mutation) {
8491
+ return mutation.code;
8492
+ }
8493
+ function serializeTemporal(date) {
8494
+ return date.dateString;
8495
+ }
8498
8496
  class Map2dBase {
8499
- constructor(serializeFirstAxis = (key) => typeof key === "string" ? key : hash(key), serializeSecondAxis = (key) => typeof key === "string" ? key : hash(key), initialContent) {
8497
+ constructor(serializeFirstAxis, serializeSecondAxis, initialContent) {
8500
8498
  this.serializeFirstAxis = serializeFirstAxis;
8501
8499
  this.serializeSecondAxis = serializeSecondAxis;
8502
8500
  this.data = /* @__PURE__ */ new Map();
@@ -8608,6 +8606,11 @@ class Map2dView {
8608
8606
  return this.baseMap.getRow(key, fillEmptyWith);
8609
8607
  }
8610
8608
  }
8609
+ class BaseMutationOverTimeDataMap extends Map2dBase {
8610
+ constructor(initialContent) {
8611
+ super(serializeSubstitutionOrDeletion, serializeTemporal, initialContent);
8612
+ }
8613
+ }
8611
8614
  function getFilteredMutationOverTimeData(data, overallMutationData, displayedSegments, displayedMutationTypes, proportionInterval) {
8612
8615
  const filteredData = new Map2dView(data);
8613
8616
  const mutationsToFilterOut = overallMutationData.filter((entry) => {
@@ -8851,12 +8854,6 @@ const timeIntervalDisplay = (date) => {
8851
8854
  const MutationCell = ({ mutation }) => {
8852
8855
  return /* @__PURE__ */ u$1("div", { className: "text-center", children: mutation.code });
8853
8856
  };
8854
- function serializeSubstitutionOrDeletion(mutation) {
8855
- return mutation.code;
8856
- }
8857
- function serializeTemporal(date) {
8858
- return date.dateString;
8859
- }
8860
8857
  const ColorScaleSelectorDropdown = ({
8861
8858
  colorScale,
8862
8859
  setColorScale
@@ -8900,18 +8897,14 @@ function useWebWorker(messageToWorker, worker) {
8900
8897
  }, [messageToWorker]);
8901
8898
  return { data, error, isLoading };
8902
8899
  }
8903
- const MutationsOverTime = ({ width, height, ...innerProps }) => {
8900
+ const MutationsOverTime = (componentProps) => {
8901
+ const { width, height } = componentProps;
8904
8902
  const size = { height, width };
8905
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(MutationsOverTimeInner, { ...innerProps }) }) });
8903
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(MutationsOverTimeInner, { ...componentProps }) }) });
8906
8904
  };
8907
- const MutationsOverTimeInner = ({
8908
- lapisFilter,
8909
- sequenceType,
8910
- views,
8911
- granularity,
8912
- lapisDateField
8913
- }) => {
8905
+ const MutationsOverTimeInner = (componentProps) => {
8914
8906
  const lapis = x(LapisUrlContext);
8907
+ const { lapisFilter, sequenceType, granularity, lapisDateField } = componentProps;
8915
8908
  const { data, error, isLoading } = useWebWorker(
8916
8909
  {
8917
8910
  lapisFilter,
@@ -8932,30 +8925,24 @@ const MutationsOverTimeInner = ({
8932
8925
  return /* @__PURE__ */ u$1(NoDataDisplay, {});
8933
8926
  }
8934
8927
  const { overallMutationData, mutationOverTimeSerialized } = data;
8935
- const mutationOverTimeData = new Map2dBase(
8936
- serializeSubstitutionOrDeletion,
8937
- serializeTemporal,
8938
- mutationOverTimeSerialized
8939
- );
8928
+ const mutationOverTimeData = new BaseMutationOverTimeDataMap(mutationOverTimeSerialized);
8940
8929
  return /* @__PURE__ */ u$1(
8941
8930
  MutationsOverTimeTabs,
8942
8931
  {
8943
8932
  overallMutationData,
8944
8933
  mutationOverTimeData,
8945
- sequenceType,
8946
- views
8934
+ originalComponentProps: componentProps
8947
8935
  }
8948
8936
  );
8949
8937
  };
8950
8938
  const MutationsOverTimeTabs = ({
8951
8939
  mutationOverTimeData,
8952
- sequenceType,
8953
- views,
8940
+ originalComponentProps,
8954
8941
  overallMutationData
8955
8942
  }) => {
8956
8943
  const [proportionInterval, setProportionInterval] = h({ min: 0.05, max: 0.9 });
8957
8944
  const [colorScale, setColorScale] = h({ min: 0, max: 1, color: "indigo" });
8958
- const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(sequenceType);
8945
+ const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(originalComponentProps.sequenceType);
8959
8946
  const [displayedMutationTypes, setDisplayedMutationTypes] = h([
8960
8947
  { label: "Substitutions", checked: true, type: "substitution" },
8961
8948
  { label: "Deletions", checked: true, type: "deletion" }
@@ -8984,7 +8971,7 @@ const MutationsOverTimeTabs = ({
8984
8971
  };
8985
8972
  }
8986
8973
  };
8987
- const tabs = views.map((view) => getTab(view));
8974
+ const tabs = originalComponentProps.views.map((view) => getTab(view));
8988
8975
  const toolbar = (activeTab) => /* @__PURE__ */ u$1(
8989
8976
  Toolbar,
8990
8977
  {
@@ -8997,7 +8984,8 @@ const MutationsOverTimeTabs = ({
8997
8984
  setProportionInterval,
8998
8985
  filteredData,
8999
8986
  colorScale,
9000
- setColorScale
8987
+ setColorScale,
8988
+ originalComponentProps
9001
8989
  }
9002
8990
  );
9003
8991
  return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar });
@@ -9012,7 +9000,8 @@ const Toolbar = ({
9012
9000
  setProportionInterval,
9013
9001
  filteredData,
9014
9002
  colorScale,
9015
- setColorScale
9003
+ setColorScale,
9004
+ originalComponentProps
9016
9005
  }) => {
9017
9006
  return /* @__PURE__ */ u$1(Fragment, { children: [
9018
9007
  activeTab === "Grid" && /* @__PURE__ */ u$1(ColorScaleSelectorDropdown, { colorScale, setColorScale }),
@@ -9041,10 +9030,18 @@ const Toolbar = ({
9041
9030
  filename: "mutations_over_time.csv"
9042
9031
  }
9043
9032
  ),
9044
- /* @__PURE__ */ u$1(Info, { children: "Info for mutations over time" }),
9033
+ /* @__PURE__ */ u$1(MutationsOverTimeInfo, { originalComponentProps }),
9045
9034
  /* @__PURE__ */ u$1(Fullscreen, {})
9046
9035
  ] });
9047
9036
  };
9037
+ const MutationsOverTimeInfo = ({ originalComponentProps }) => {
9038
+ const lapis = x(LapisUrlContext);
9039
+ return /* @__PURE__ */ u$1(Info, { children: [
9040
+ /* @__PURE__ */ u$1(InfoHeadline1, { children: "Info for mutations over time" }),
9041
+ /* @__PURE__ */ u$1(InfoParagraph, { children: "TODO: https://github.com/GenSpectrum/dashboard-components/issues/441" }),
9042
+ /* @__PURE__ */ u$1(InfoComponentCode, { componentName: "mutations-over-time", params: originalComponentProps, lapisUrl: lapis })
9043
+ ] });
9044
+ };
9048
9045
  function getDownloadData(filteredData) {
9049
9046
  const dates = filteredData.getSecondAxisKeys().map((date) => toTemporalClass(date));
9050
9047
  return filteredData.getFirstAxisKeys().map((mutation) => {
@@ -9121,79 +9118,38 @@ __decorateClass$5([
9121
9118
  MutationsOverTimeComponent = __decorateClass$5([
9122
9119
  t$2("gs-mutations-over-time")
9123
9120
  ], MutationsOverTimeComponent);
9124
- const PRESET_VALUE_CUSTOM = "custom";
9125
- const PRESET_VALUE_ALL_TIMES = "allTimes";
9126
- const PRESET_VALUE_LAST_2_WEEKS = "last2Weeks";
9127
- const PRESET_VALUE_LAST_MONTH = "lastMonth";
9128
- const PRESET_VALUE_LAST_2_MONTHS = "last2Months";
9129
- const PRESET_VALUE_LAST_3_MONTHS = "last3Months";
9130
- const PRESET_VALUE_LAST_6_MONTHS = "last6Months";
9131
- const presets = {
9132
- [PRESET_VALUE_CUSTOM]: { label: "Custom" },
9133
- [PRESET_VALUE_ALL_TIMES]: { label: "All times" },
9134
- [PRESET_VALUE_LAST_2_WEEKS]: { label: "Last 2 weeks" },
9135
- [PRESET_VALUE_LAST_MONTH]: { label: "Last month" },
9136
- [PRESET_VALUE_LAST_2_MONTHS]: { label: "Last 2 months" },
9137
- [PRESET_VALUE_LAST_3_MONTHS]: { label: "Last 3 months" },
9138
- [PRESET_VALUE_LAST_6_MONTHS]: { label: "Last 6 months" }
9139
- };
9140
- const getSelectableOptions = (customSelectOptions) => {
9141
- const presetOptions = Object.entries(presets).map(([key, value]) => {
9142
- return { label: value.label, value: key };
9143
- });
9144
- const customOptions = customSelectOptions.map((customSelectOption) => {
9121
+ const getSelectableOptions = (dateRangeOptions) => {
9122
+ return dateRangeOptions.map((customSelectOption) => {
9145
9123
  return { label: customSelectOption.label, value: customSelectOption.label };
9146
9124
  });
9147
- return [...presetOptions, ...customOptions];
9148
- };
9149
- const getDatesForSelectorValue = (selectorValue, customSelectOptions, earliestDate) => {
9150
- const today = /* @__PURE__ */ new Date();
9151
- const customSelectOption = customSelectOptions.find((option) => option.label === selectorValue);
9152
- if (customSelectOption) {
9153
- return { dateFrom: new Date(customSelectOption.dateFrom), dateTo: new Date(customSelectOption.dateTo) };
9154
- }
9155
- switch (selectorValue) {
9156
- case PRESET_VALUE_LAST_2_WEEKS: {
9157
- const twoWeeksAgo = new Date(today);
9158
- twoWeeksAgo.setDate(today.getDate() - 14);
9159
- return { dateFrom: twoWeeksAgo, dateTo: today };
9160
- }
9161
- case PRESET_VALUE_LAST_MONTH: {
9162
- const lastMonth = new Date(today);
9163
- lastMonth.setMonth(today.getMonth() - 1);
9164
- return { dateFrom: lastMonth, dateTo: today };
9165
- }
9166
- case PRESET_VALUE_LAST_2_MONTHS: {
9167
- const twoMonthsAgo = new Date(today);
9168
- twoMonthsAgo.setMonth(today.getMonth() - 2);
9169
- return { dateFrom: twoMonthsAgo, dateTo: today };
9170
- }
9171
- case PRESET_VALUE_LAST_3_MONTHS: {
9172
- const threeMonthsAgo = new Date(today);
9173
- threeMonthsAgo.setMonth(today.getMonth() - 3);
9174
- return { dateFrom: threeMonthsAgo, dateTo: today };
9175
- }
9176
- case PRESET_VALUE_LAST_6_MONTHS: {
9177
- const sixMonthsAgo = new Date(today);
9178
- sixMonthsAgo.setMonth(today.getMonth() - 6);
9179
- return { dateFrom: sixMonthsAgo, dateTo: today };
9180
- }
9181
- case PRESET_VALUE_ALL_TIMES: {
9182
- return { dateFrom: new Date(earliestDate), dateTo: today };
9183
- }
9184
- default:
9185
- return { dateFrom: today, dateTo: today };
9125
+ };
9126
+ const getDatesForSelectorValue = (initialSelectedDateRange, dateRangeOptions, earliestDate) => {
9127
+ const today2 = /* @__PURE__ */ new Date();
9128
+ const defaultDates = { dateFrom: new Date(earliestDate), dateTo: today2 };
9129
+ if (initialSelectedDateRange === void 0) {
9130
+ return defaultDates;
9131
+ }
9132
+ const dateRangeOption = dateRangeOptions.find((option) => option.label === initialSelectedDateRange);
9133
+ if (dateRangeOption) {
9134
+ return {
9135
+ dateFrom: new Date(dateRangeOption.dateFrom ?? earliestDate),
9136
+ dateTo: new Date(dateRangeOption.dateTo ?? today2)
9137
+ };
9186
9138
  }
9139
+ return defaultDates;
9187
9140
  };
9188
- function computeInitialValues(initialValue, initialDateFrom, initialDateTo, earliestDate, customSelectOptions) {
9141
+ function computeInitialValues(initialValue, initialDateFrom, initialDateTo, earliestDate, dateRangeOptions) {
9142
+ var _a;
9189
9143
  if (isUndefinedOrEmpty(initialDateFrom) && isUndefinedOrEmpty(initialDateTo)) {
9190
- const selectableOptions = getSelectableOptions(customSelectOptions);
9191
- const initialSelectedDateRange = initialValue !== void 0 && selectableOptions.some((option) => option.value === initialValue) ? initialValue : PRESET_VALUE_LAST_6_MONTHS;
9192
- const { dateFrom, dateTo } = getDatesForSelectorValue(
9193
- initialSelectedDateRange,
9194
- customSelectOptions,
9195
- earliestDate
9196
- );
9144
+ const selectableOptions = getSelectableOptions(dateRangeOptions);
9145
+ const initialSelectedDateRange = (_a = selectableOptions.find((option) => option.value === initialValue)) == null ? void 0 : _a.value;
9146
+ if (initialValue !== void 0 && initialSelectedDateRange === void 0) {
9147
+ throw new UserFacingError(
9148
+ "Invalid initialValue",
9149
+ `Invalid initialValue "${initialValue}", It must be one of ${selectableOptions.map((option) => `'${option.value}'`).join(", ")}`
9150
+ );
9151
+ }
9152
+ const { dateFrom, dateTo } = getDatesForSelectorValue(initialSelectedDateRange, dateRangeOptions, earliestDate);
9197
9153
  return {
9198
9154
  initialSelectedDateRange,
9199
9155
  initialSelectedDateFrom: dateFrom,
@@ -9218,7 +9174,7 @@ function computeInitialValues(initialValue, initialDateFrom, initialDateTo, earl
9218
9174
  initialSelectedDateTo = initialSelectedDateFrom;
9219
9175
  }
9220
9176
  return {
9221
- initialSelectedDateRange: PRESET_VALUE_CUSTOM,
9177
+ initialSelectedDateRange: void 0,
9222
9178
  initialSelectedDateFrom,
9223
9179
  initialSelectedDateTo
9224
9180
  };
@@ -9233,15 +9189,13 @@ const toYYYYMMDD = (date) => {
9233
9189
  const options2 = { year: "numeric", month: "2-digit", day: "2-digit" };
9234
9190
  return date.toLocaleDateString("en-CA", options2);
9235
9191
  };
9236
- const DateRangeSelector = ({
9237
- width,
9238
- ...innerProps
9239
- }) => {
9192
+ const customOption = "Custom";
9193
+ const DateRangeSelector = ({ width, ...innerProps }) => {
9240
9194
  const size = { width, height: "3rem" };
9241
9195
  return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1("div", { style: { width }, children: /* @__PURE__ */ u$1(DateRangeSelectorInner, { ...innerProps }) }) });
9242
9196
  };
9243
9197
  const DateRangeSelectorInner = ({
9244
- customSelectOptions,
9198
+ dateRangeOptions,
9245
9199
  earliestDate = "1900-01-01",
9246
9200
  initialValue,
9247
9201
  dateColumn,
@@ -9253,7 +9207,7 @@ const DateRangeSelectorInner = ({
9253
9207
  initialDateFrom,
9254
9208
  initialDateTo,
9255
9209
  earliestDate,
9256
- customSelectOptions
9210
+ dateRangeOptions
9257
9211
  );
9258
9212
  const fromDatePickerRef = A(null);
9259
9213
  const toDatePickerRef = A(null);
@@ -9295,7 +9249,7 @@ const DateRangeSelectorInner = ({
9295
9249
  }, [fromDatePickerRef, toDatePickerRef]);
9296
9250
  const onSelectChange = (value) => {
9297
9251
  setSelectedDateRange(value);
9298
- const dateRange = getDatesForSelectorValue(value, customSelectOptions, earliestDate);
9252
+ const dateRange = getDatesForSelectorValue(value, dateRangeOptions, earliestDate);
9299
9253
  dateToPicker == null ? void 0 : dateToPicker.set("minDate", dateRange.dateFrom);
9300
9254
  dateFromPicker == null ? void 0 : dateFromPicker.set("maxDate", dateRange.dateTo);
9301
9255
  dateFromPicker == null ? void 0 : dateFromPicker.setDate(dateRange.dateFrom);
@@ -9312,7 +9266,7 @@ const DateRangeSelectorInner = ({
9312
9266
  }
9313
9267
  selectedDates.dateFrom = (dateFromPicker == null ? void 0 : dateFromPicker.selectedDates[0]) || /* @__PURE__ */ new Date();
9314
9268
  dateToPicker == null ? void 0 : dateToPicker.set("minDate", dateFromPicker == null ? void 0 : dateFromPicker.selectedDates[0]);
9315
- setSelectedDateRange("custom");
9269
+ setSelectedDateRange(customOption);
9316
9270
  submit();
9317
9271
  };
9318
9272
  const onChangeDateTo = () => {
@@ -9321,7 +9275,7 @@ const DateRangeSelectorInner = ({
9321
9275
  }
9322
9276
  selectedDates.dateTo = (dateToPicker == null ? void 0 : dateToPicker.selectedDates[0]) || /* @__PURE__ */ new Date();
9323
9277
  dateFromPicker == null ? void 0 : dateFromPicker.set("maxDate", dateToPicker == null ? void 0 : dateToPicker.selectedDates[0]);
9324
- setSelectedDateRange("custom");
9278
+ setSelectedDateRange(customOption);
9325
9279
  submit();
9326
9280
  };
9327
9281
  const submit = () => {
@@ -9344,8 +9298,11 @@ const DateRangeSelectorInner = ({
9344
9298
  /* @__PURE__ */ u$1(
9345
9299
  Select,
9346
9300
  {
9347
- items: getSelectableOptions(customSelectOptions),
9348
- selected: selectedDateRange,
9301
+ items: [
9302
+ ...getSelectableOptions(dateRangeOptions),
9303
+ { label: customOption, value: customOption, disabled: true }
9304
+ ],
9305
+ selected: selectedDateRange ?? customOption,
9349
9306
  selectStyle: "select-bordered rounded-none flex-grow min-w-[7.5rem]",
9350
9307
  onChange: (event) => {
9351
9308
  event.preventDefault();
@@ -9394,9 +9351,9 @@ var __decorateClass$4 = (decorators, target, key, kind) => {
9394
9351
  let DateRangeSelectorComponent = class extends PreactLitAdapter {
9395
9352
  constructor() {
9396
9353
  super(...arguments);
9397
- this.customSelectOptions = [];
9354
+ this.dateRangeOptions = [];
9398
9355
  this.earliestDate = "1900-01-01";
9399
- this.initialValue = "last6Months";
9356
+ this.initialValue = void 0;
9400
9357
  this.initialDateFrom = "";
9401
9358
  this.initialDateTo = "";
9402
9359
  this.width = "100%";
@@ -9406,7 +9363,7 @@ let DateRangeSelectorComponent = class extends PreactLitAdapter {
9406
9363
  return /* @__PURE__ */ u$1(
9407
9364
  DateRangeSelector,
9408
9365
  {
9409
- customSelectOptions: this.customSelectOptions,
9366
+ dateRangeOptions: this.dateRangeOptions,
9410
9367
  earliestDate: this.earliestDate,
9411
9368
  initialValue: this.initialValue,
9412
9369
  initialDateFrom: this.initialDateFrom,
@@ -9419,7 +9376,7 @@ let DateRangeSelectorComponent = class extends PreactLitAdapter {
9419
9376
  };
9420
9377
  __decorateClass$4([
9421
9378
  n2({ type: Array })
9422
- ], DateRangeSelectorComponent.prototype, "customSelectOptions", 2);
9379
+ ], DateRangeSelectorComponent.prototype, "dateRangeOptions", 2);
9423
9380
  __decorateClass$4([
9424
9381
  n2({ type: String })
9425
9382
  ], DateRangeSelectorComponent.prototype, "earliestDate", 2);
@@ -10346,6 +10303,42 @@ __decorateClass([
10346
10303
  LineageFilterComponent = __decorateClass([
10347
10304
  t$2("gs-lineage-filter")
10348
10305
  ], LineageFilterComponent);
10306
+ const today = /* @__PURE__ */ new Date();
10307
+ const twoWeeksAgo = /* @__PURE__ */ new Date();
10308
+ twoWeeksAgo.setDate(today.getDate() - 14);
10309
+ const lastMonth = new Date(today);
10310
+ lastMonth.setMonth(today.getMonth() - 1);
10311
+ const last2Months = new Date(today);
10312
+ last2Months.setMonth(today.getMonth() - 2);
10313
+ const last3Months = new Date(today);
10314
+ last3Months.setMonth(today.getMonth() - 3);
10315
+ const last6Months = new Date(today);
10316
+ last6Months.setMonth(today.getMonth() - 6);
10317
+ const dateRangeOptionPresets = {
10318
+ last2Weeks: {
10319
+ label: "Last 2 weeks",
10320
+ dateFrom: toYYYYMMDD(twoWeeksAgo)
10321
+ },
10322
+ lastMonth: {
10323
+ label: "Last month",
10324
+ dateFrom: toYYYYMMDD(lastMonth)
10325
+ },
10326
+ last2Months: {
10327
+ label: "Last 2 months",
10328
+ dateFrom: toYYYYMMDD(last2Months)
10329
+ },
10330
+ last3Months: {
10331
+ label: "Last 3 months",
10332
+ dateFrom: toYYYYMMDD(last3Months)
10333
+ },
10334
+ last6Months: {
10335
+ label: "Last 6 months",
10336
+ dateFrom: toYYYYMMDD(last6Months)
10337
+ },
10338
+ allTimes: {
10339
+ label: "All times"
10340
+ }
10341
+ };
10349
10342
  export {
10350
10343
  AggregateComponent,
10351
10344
  App,
@@ -10360,6 +10353,7 @@ export {
10360
10353
  PrevalenceOverTimeComponent,
10361
10354
  RelativeGrowthAdvantageComponent,
10362
10355
  TextInputComponent,
10363
- UserFacingError
10356
+ UserFacingError,
10357
+ dateRangeOptionPresets
10364
10358
  };
10365
10359
  //# sourceMappingURL=dashboard-components.js.map