@genspectrum/dashboard-components 0.10.1 → 0.10.2
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.
- package/custom-elements.json +23 -23
- package/dist/assets/{mutationOverTimeWorker-CvZg52rf.js.map → mutationOverTimeWorker-Di6yP1e6.js.map} +1 -1
- package/dist/components.d.ts +50 -48
- package/dist/components.js +151 -62
- package/dist/components.js.map +1 -1
- package/dist/{utilEntrypoint-g4DsyhU7.js → dateRangeOption-du8H7LWu.js} +33 -2
- package/dist/dateRangeOption-du8H7LWu.js.map +1 -0
- package/dist/util.d.ts +101 -59
- package/dist/util.js +3 -2
- package/package.json +1 -1
- package/src/preact/components/color-scale-selector.tsx +7 -3
- package/src/preact/components/error-boundary.tsx +39 -5
- package/src/preact/components/error-display.tsx +40 -5
- package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +8 -2
- package/src/preact/dateRangeSelector/computeInitialValues.ts +6 -0
- package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +16 -2
- package/src/preact/dateRangeSelector/date-range-selector.tsx +20 -15
- package/src/preact/dateRangeSelector/dateRangeOption.ts +10 -5
- package/src/preact/lineageFilter/lineage-filter.stories.tsx +18 -4
- package/src/preact/lineageFilter/lineage-filter.tsx +15 -10
- package/src/preact/locationFilter/location-filter.stories.tsx +14 -0
- package/src/preact/locationFilter/location-filter.tsx +15 -10
- package/src/preact/mutationComparison/mutation-comparison-venn.tsx +17 -18
- package/src/preact/mutationComparison/mutation-comparison.tsx +18 -12
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay.ts +1326 -9341
- package/src/preact/mutationsOverTime/__mockData__/byWeek.ts +615 -4920
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData.ts +2203 -17624
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +16 -8
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +1 -3
- package/src/preact/shared/stories/expectInvalidAttributesErrorMessage.ts +13 -0
- package/src/preact/webWorkers/useWebWorker.ts +8 -4
- package/src/query/queryMutationsOverTime.spec.ts +12 -27
- package/src/query/queryMutationsOverTime.ts +2 -6
- package/src/types.ts +19 -6
- package/src/utilEntrypoint.ts +8 -0
- package/src/utils/map2d.spec.ts +10 -10
- package/src/utils/map2d.ts +10 -10
- package/src/web-components/input/gs-date-range-selector.stories.ts +2 -2
- package/src/web-components/input/gs-date-range-selector.tsx +3 -3
- package/src/web-components/input/gs-lineage-filter.tsx +1 -1
- package/src/web-components/input/gs-location-filter.tsx +2 -2
- package/src/web-components/visualization/gs-aggregate.tsx +2 -2
- package/standalone-bundle/assets/{mutationOverTimeWorker-CypX_PYM.js.map → mutationOverTimeWorker-cIyshfj_.js.map} +1 -1
- package/standalone-bundle/dashboard-components.js +6668 -6580
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/utilEntrypoint-g4DsyhU7.js.map +0 -1
package/dist/components.js
CHANGED
|
@@ -6,11 +6,11 @@ import { options, createContext as createContext$1, Fragment, render } from "pre
|
|
|
6
6
|
import { Grid } from "gridjs";
|
|
7
7
|
import { Chart, registerables, Scale } from "chart.js";
|
|
8
8
|
import { VennDiagramController, ArcSlice, extractSets } from "chartjs-chart-venn";
|
|
9
|
+
import { n as namedLapisFilterSchema, s as sequenceTypeSchema, m as mutationComparisonViewSchema, a as dateRangeOptionSchema, t as toYYYYMMDD, D as DateRangeOptionChangedEvent } from "./dateRangeOption-du8H7LWu.js";
|
|
9
10
|
import { autoUpdate, computePosition, offset, shift, flip } from "@floating-ui/dom";
|
|
10
11
|
import { ReactiveElement } from "@lit/reactive-element";
|
|
11
12
|
import { BarWithErrorBarsController, BarWithErrorBar } from "chartjs-chart-error-bars";
|
|
12
13
|
import flatpickr from "flatpickr";
|
|
13
|
-
import { t as toYYYYMMDD, D as DateRangeOptionChangedEvent } from "./utilEntrypoint-g4DsyhU7.js";
|
|
14
14
|
/**
|
|
15
15
|
* @license
|
|
16
16
|
* Copyright 2017 Google LLC
|
|
@@ -1021,8 +1021,6 @@ const MutationComparisonVenn = ({
|
|
|
1021
1021
|
data,
|
|
1022
1022
|
proportionInterval
|
|
1023
1023
|
}) => {
|
|
1024
|
-
const divRef = A(null);
|
|
1025
|
-
const noElementSelectedMessage = "You have no elements selected. Click in the venn diagram to select.";
|
|
1026
1024
|
const [selectedDatasetIndex, setSelectedDatasetIndex] = h(null);
|
|
1027
1025
|
const sets = T(
|
|
1028
1026
|
() => extractSets(
|
|
@@ -1040,18 +1038,6 @@ const MutationComparisonVenn = ({
|
|
|
1040
1038
|
),
|
|
1041
1039
|
[data, proportionInterval]
|
|
1042
1040
|
);
|
|
1043
|
-
y(() => {
|
|
1044
|
-
if (divRef.current === null) {
|
|
1045
|
-
return;
|
|
1046
|
-
}
|
|
1047
|
-
if (selectedDatasetIndex === null) {
|
|
1048
|
-
divRef.current.innerText = noElementSelectedMessage;
|
|
1049
|
-
return;
|
|
1050
|
-
}
|
|
1051
|
-
const values = sets.datasets[0].data[selectedDatasetIndex].values;
|
|
1052
|
-
const label = sets.datasets[0].data[selectedDatasetIndex].label;
|
|
1053
|
-
divRef.current.innerText = `${label}: ${values.join(", ")}` || "";
|
|
1054
|
-
}, [divRef, selectedDatasetIndex, sets]);
|
|
1055
1041
|
const config = T(
|
|
1056
1042
|
() => ({
|
|
1057
1043
|
type: "venn",
|
|
@@ -1107,9 +1093,18 @@ const MutationComparisonVenn = ({
|
|
|
1107
1093
|
}
|
|
1108
1094
|
return /* @__PURE__ */ u$1("div", { className: "h-full flex flex-col", children: [
|
|
1109
1095
|
/* @__PURE__ */ u$1("div", { className: "flex-1", children: /* @__PURE__ */ u$1(GsChart, { configuration: config }) }),
|
|
1110
|
-
/* @__PURE__ */ u$1("
|
|
1096
|
+
/* @__PURE__ */ u$1("p", { class: "flex flex-wrap break-words m-2", children: getSelectedMutationsDescription(selectedDatasetIndex, sets) })
|
|
1111
1097
|
] });
|
|
1112
1098
|
};
|
|
1099
|
+
const noElementSelectedMessage = "You have no elements selected. Click in the venn diagram to select.";
|
|
1100
|
+
function getSelectedMutationsDescription(selectedDatasetIndex, sets) {
|
|
1101
|
+
if (selectedDatasetIndex === null) {
|
|
1102
|
+
return noElementSelectedMessage;
|
|
1103
|
+
}
|
|
1104
|
+
const values = sets.datasets[0].data[selectedDatasetIndex].values;
|
|
1105
|
+
const label = sets.datasets[0].data[selectedDatasetIndex].label;
|
|
1106
|
+
return `${label}: ${values.join(", ")}` || "";
|
|
1107
|
+
}
|
|
1113
1108
|
class FetchSubstitutionsOrDeletionsOperator {
|
|
1114
1109
|
constructor(filter, sequenceType, minProportion) {
|
|
1115
1110
|
this.filter = filter;
|
|
@@ -1254,6 +1249,14 @@ class UserFacingError extends Error {
|
|
|
1254
1249
|
this.name = "UserFacingError";
|
|
1255
1250
|
}
|
|
1256
1251
|
}
|
|
1252
|
+
class InvalidPropsError extends Error {
|
|
1253
|
+
constructor(zodError, componentProps) {
|
|
1254
|
+
super(zodError.message);
|
|
1255
|
+
this.zodError = zodError;
|
|
1256
|
+
this.componentProps = componentProps;
|
|
1257
|
+
this.name = "InvalidPropsError";
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1257
1260
|
const ErrorDisplay = ({ error, resetError, layout }) => {
|
|
1258
1261
|
console.error(error);
|
|
1259
1262
|
const containerRef = A(null);
|
|
@@ -1290,7 +1293,7 @@ const ErrorDisplay = ({ error, resetError, layout }) => {
|
|
|
1290
1293
|
] })
|
|
1291
1294
|
] })
|
|
1292
1295
|
] }),
|
|
1293
|
-
/* @__PURE__ */ u$1("button", { onClick: resetError, className: "btn btn-sm flex items-center m-4", children: [
|
|
1296
|
+
resetError !== void 0 && /* @__PURE__ */ u$1("button", { onClick: resetError, className: "btn btn-sm flex items-center m-4", children: [
|
|
1294
1297
|
/* @__PURE__ */ u$1("span", { className: "iconify mdi--reload text-lg" }),
|
|
1295
1298
|
"Try again"
|
|
1296
1299
|
] })
|
|
@@ -1326,18 +1329,54 @@ function getDisplayedErrorMessage(error) {
|
|
|
1326
1329
|
}
|
|
1327
1330
|
};
|
|
1328
1331
|
}
|
|
1332
|
+
if (error instanceof InvalidPropsError) {
|
|
1333
|
+
const firstError = error.zodError.errors[0];
|
|
1334
|
+
let message = error.zodError.issues.map((issue) => {
|
|
1335
|
+
const actual = issue.path[0] in error.componentProps ? ` '${JSON.stringify(error.componentProps[issue.path[0]])}'` : "";
|
|
1336
|
+
return `Unexpected value${actual} for "${issue.path.join(".")}": ${issue.message}`;
|
|
1337
|
+
}).join(" - ");
|
|
1338
|
+
if (firstError.code === "invalid_type" && firstError.received === "null") {
|
|
1339
|
+
message = `Is the "${firstError.path[0]}" attribute in the HTML of the correct type? ${message}`;
|
|
1340
|
+
}
|
|
1341
|
+
return {
|
|
1342
|
+
headline: "Error - Invalid component attributes",
|
|
1343
|
+
details: { headline: "Invalid component attributes", message }
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1329
1346
|
return { headline: "Error", details: void 0 };
|
|
1330
1347
|
}
|
|
1331
1348
|
const ResizeContainer = ({ children, size }) => {
|
|
1332
1349
|
return /* @__PURE__ */ u$1("div", { style: size, className: "bg-white", children });
|
|
1333
1350
|
};
|
|
1334
|
-
const ErrorBoundary = ({
|
|
1351
|
+
const ErrorBoundary = ({
|
|
1352
|
+
size,
|
|
1353
|
+
layout,
|
|
1354
|
+
componentProps,
|
|
1355
|
+
schema,
|
|
1356
|
+
children
|
|
1357
|
+
}) => {
|
|
1335
1358
|
const [internalError, resetError] = b2();
|
|
1359
|
+
const componentPropsParseError = useCheckComponentProps(schema, componentProps);
|
|
1336
1360
|
if (internalError) {
|
|
1337
1361
|
return /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(ErrorDisplay, { error: internalError, resetError, layout }) });
|
|
1338
1362
|
}
|
|
1363
|
+
if (componentPropsParseError !== void 0) {
|
|
1364
|
+
return /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(ErrorDisplay, { error: componentPropsParseError, layout }) });
|
|
1365
|
+
}
|
|
1339
1366
|
return /* @__PURE__ */ u$1(Fragment, { children });
|
|
1340
1367
|
};
|
|
1368
|
+
function useCheckComponentProps(schema, componentProps) {
|
|
1369
|
+
return T(() => {
|
|
1370
|
+
if (schema === void 0 || componentProps === void 0) {
|
|
1371
|
+
return void 0;
|
|
1372
|
+
}
|
|
1373
|
+
const parseResult = schema.safeParse(componentProps);
|
|
1374
|
+
if (parseResult.success) {
|
|
1375
|
+
return void 0;
|
|
1376
|
+
}
|
|
1377
|
+
return new InvalidPropsError(parseResult.error, componentProps);
|
|
1378
|
+
}, [componentProps, schema]);
|
|
1379
|
+
}
|
|
1341
1380
|
const Fullscreen = () => {
|
|
1342
1381
|
const element = A(null);
|
|
1343
1382
|
const isFullscreen = useFullscreenStatus();
|
|
@@ -1958,10 +1997,18 @@ function useQuery(fetchDataCallback, dependencies) {
|
|
|
1958
1997
|
}, [JSON.stringify(dependencies)]);
|
|
1959
1998
|
return { data, error, isLoading };
|
|
1960
1999
|
}
|
|
2000
|
+
const mutationComparisonPropsSchema = z$1.object({
|
|
2001
|
+
width: z$1.string(),
|
|
2002
|
+
height: z$1.string(),
|
|
2003
|
+
lapisFilters: z$1.array(namedLapisFilterSchema).min(1),
|
|
2004
|
+
sequenceType: sequenceTypeSchema,
|
|
2005
|
+
views: z$1.array(mutationComparisonViewSchema),
|
|
2006
|
+
pageSize: z$1.union([z$1.boolean(), z$1.number()])
|
|
2007
|
+
});
|
|
1961
2008
|
const MutationComparison = (componentProps) => {
|
|
1962
2009
|
const { width, height } = componentProps;
|
|
1963
2010
|
const size = { height, width };
|
|
1964
|
-
return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(MutationComparisonInner, { ...componentProps }) }) });
|
|
2011
|
+
return /* @__PURE__ */ u$1(ErrorBoundary, { size, componentProps, schema: mutationComparisonPropsSchema, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(MutationComparisonInner, { ...componentProps }) }) });
|
|
1965
2012
|
};
|
|
1966
2013
|
const MutationComparisonInner = (componentProps) => {
|
|
1967
2014
|
const { lapisFilters, sequenceType } = componentProps;
|
|
@@ -8606,7 +8653,7 @@ __decorateClass$7([
|
|
|
8606
8653
|
NumberSequencesOverTimeComponent = __decorateClass$7([
|
|
8607
8654
|
t$2("gs-number-sequences-over-time")
|
|
8608
8655
|
], NumberSequencesOverTimeComponent);
|
|
8609
|
-
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+IG51bWJlclR5cGUoKS5vcHRpb25hbCgpOwogIGNvbnN0IG9ib29sZWFuID0gKCkgPT4gYm9vbGVhblR5cGUoKS5vcHRpb25hbCgpOwogIGNvbnN0IGNvZXJjZSA9IHsKICAgIHN0cmluZzogKGFyZykgPT4gWm9kU3RyaW5nLmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pLAogICAgbnVtYmVyOiAoYXJnKSA9PiBab2ROdW1iZXIuY3JlYXRlKHsgLi4uYXJnLCBjb2VyY2U6IHRydWUgfSksCiAgICBib29sZWFuOiAoYXJnKSA9PiBab2RCb29sZWFuLmNyZWF0ZSh7CiAgICAgIC4uLmFyZywKICAgICAgY29lcmNlOiB0cnVlCiAgICB9KSwKICAgIGJpZ2ludDogKGFyZykgPT4gWm9kQmlnSW50LmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pLAogICAgZGF0ZTogKGFyZykgPT4gWm9kRGF0ZS5jcmVhdGUoeyAuLi5hcmcsIGNvZXJjZTogdHJ1ZSB9KQogIH07CiAgY29uc3QgTkVWRVIgPSBJTlZBTElEOwogIHZhciB6JDEgPSAvKiBAX19QVVJFX18gKi8gT2JqZWN0LmZyZWV6ZSh7CiAgICBfX3Byb3RvX186IG51bGwsCiAgICBkZWZhdWx0RXJyb3JNYXA6IGVycm9yTWFwLAogICAgc2V0RXJyb3JNYXAsCiAgICBnZXRFcnJvck1hcCwKICAgIG1ha2VJc3N1ZSwKICAgIEVNUFRZX1BBVEgsCiAgICBhZGRJc3N1ZVRvQ29udGV4dCwKICAgIFBhcnNlU3RhdHVzLAogICAgSU5WQUxJRCwKICAgIERJUlRZLAogICAgT0ssCiAgICBpc0Fib3J0ZWQsCiAgICBpc0RpcnR5LAogICAgaXNWYWxpZCwKICAgIGlzQXN5bmMsCiAgICBnZXQgdXRpbCgpIHsKICAgICAgcmV0dXJuIHV0aWw7CiAgICB9LAogICAgZ2V0IG9iamVjdFV0aWwoKSB7CiAgICAgIHJldHVybiBvYmplY3RVdGlsOwogICAgfSwKICAgIFpvZFBhcnNlZFR5cGUsCiAgICBnZXRQYXJzZWRUeXBlLAogICAgWm9kVHlwZSwKICAgIGRhdGV0aW1lUmVnZXgsCiAgICBab2RTdHJpbmcsCiAgICBab2ROdW1iZXIsCiAgICBab2RCaWdJbnQsCiAgICBab2RCb29sZWFuLAogICAgWm9kRGF0ZSwKICAgIFpvZFN5bWJvbCwKICAgIFpvZFVuZGVmaW5lZCwKICAgIFpvZE51bGwsCiAgICBab2RBbnksCiAgICBab2RVbmtub3duLAogICAgWm9kTmV2ZXIsCiAgICBab2RWb2lkLAogICAgWm9kQXJyYXksCiAgICBab2RPYmplY3QsCiAgICBab2RVbmlvbiwKICAgIFpvZERpc2NyaW1pbmF0ZWRVbmlvbiwKICAgIFpvZEludGVyc2VjdGlvbiwKICAgIFpvZFR1cGxlLAogICAgWm9kUmVjb3JkLAogICAgWm9kTWFwLAogICAgWm9kU2V0LAogICAgWm9kRnVuY3Rpb24sCiAgICBab2RMYXp5LAogICAgWm9kTGl0ZXJhbCwKICAgIFpvZEVudW0sCiAgICBab2ROYXRpdmVFbnVtLAogICAgWm9kUHJvbWlzZSwKICAgIFpvZEVmZmVjdHMsCiAgICBab2RUcmFuc2Zvcm1lcjogWm9kRWZmZWN0cywKICAgIFpvZE9wdGlvbmFsLAogICAgWm9kTnVsbGFibGUsCiAgICBab2REZWZhdWx0LAogICAgWm9kQ2F0Y2gsCiAgICBab2ROYU4sCiAgICBCUkFORCwKICAgIFpvZEJyYW5kZWQsCiAgICBab2RQaXBlbGluZSwKICAgIFpvZFJlYWRvbmx5LAogICAgY3VzdG9tLAogICAgU2NoZW1hOiBab2RUeXBlLAogICAgWm9kU2NoZW1hOiBab2RUeXBlLAogICAgbGF0ZSwKICAgIGdldCBab2RGaXJzdFBhcnR5VHlwZUtpbmQoKSB7CiAgICAgIHJldHVybiBab2RGaXJzdFBhcnR5VHlwZUtpbmQ7CiAgICB9LAogICAgY29lcmNlLAogICAgYW55OiBhbnlUeXBlLAogICAgYXJyYXk6IGFycmF5VHlwZSwKICAgIGJpZ2ludDogYmlnSW50VHlwZSwKICAgIGJvb2xlYW46IGJvb2xlYW5UeXBlLAogICAgZGF0ZTogZGF0ZVR5cGUsCiAgICBkaXNjcmltaW5hdGVkVW5pb246IGRpc2NyaW1pbmF0ZWRVbmlvblR5cGUsCiAgICBlZmZlY3Q6IGVmZmVjdHNUeXBlLAogICAgImVudW0iOiBlbnVtVHlwZSwKICAgICJmdW5jdGlvbiI6IGZ1bmN0aW9uVHlwZSwKICAgICJpbnN0YW5jZW9mIjogaW5zdGFuY2VPZlR5cGUsCiAgICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvblR5cGUsCiAgICBsYXp5OiBsYXp5VHlwZSwKICAgIGxpdGVyYWw6IGxpdGVyYWxUeXBlLAogICAgbWFwOiBtYXBUeXBlLAogICAgbmFuOiBuYW5UeXBlLAogICAgbmF0aXZlRW51bTogbmF0aXZlRW51bVR5cGUsCiAgICBuZXZlcjogbmV2ZXJUeXBlLAogICAgIm51bGwiOiBudWxsVHlwZSwKICAgIG51bGxhYmxlOiBudWxsYWJsZVR5cGUsCiAgICBudW1iZXI6IG51bWJlclR5cGUsCiAgICBvYmplY3Q6IG9iamVjdFR5cGUsCiAgICBvYm9vbGVhbiwKICAgIG9udW1iZXIsCiAgICBvcHRpb25hbDogb3B0aW9uYWxUeXBlLAogICAgb3N0cmluZywKICAgIHBpcGVsaW5lOiBwaXBlbGluZVR5cGUsCiAgICBwcmVwcm9jZXNzOiBwcmVwcm9jZXNzVHlwZSwKICAgIHByb21pc2U6IHByb21pc2VUeXBlLAogICAgcmVjb3JkOiByZWNvcmRUeXBlLAogICAgc2V0OiBzZXRUeXBlLAogICAgc3RyaWN0T2JqZWN0OiBzdHJpY3RPYmplY3RUeXBlLAogICAgc3RyaW5nOiBzdHJpbmdUeXBlLAogICAgc3ltYm9sOiBzeW1ib2xUeXBlLAogICAgdHJhbnNmb3JtZXI6IGVmZmVjdHNUeXBlLAogICAgdHVwbGU6IHR1cGxlVHlwZSwKICAgICJ1bmRlZmluZWQiOiB1bmRlZmluZWRUeXBlLAogICAgdW5pb246IHVuaW9uVHlwZSwKICAgIHVua25vd246IHVua25vd25UeXBlLAogICAgInZvaWQiOiB2b2lkVHlwZSwKICAgIE5FVkVSLAogICAgWm9kSXNzdWVDb2RlLAogICAgcXVvdGVsZXNzSnNvbiwKICAgIFpvZEVycm9yCiAgfSk7CiAgeiQxLm9iamVjdCh7CiAgICBudWNsZW90aWRlU2VxdWVuY2VzOiB6JDEuYXJyYXkoCiAgICAgIHokMS5vYmplY3QoewogICAgICAgIG5hbWU6IHokMS5zdHJpbmcoKSwKICAgICAgICBzZXF1ZW5jZTogeiQxLnN0cmluZygpCiAgICAgIH0pCiAgICApLAogICAgZ2VuZXM6IHokMS5hcnJheSgKICAgICAgeiQxLm9iamVjdCh7CiAgICAgICAgbmFtZTogeiQxLnN0cmluZygpLAogICAgICAgIHNlcXVlbmNlOiB6JDEuc3RyaW5nKCkKICAgICAgfSkKICAgICkKICB9KTsKICBjb25zdCBvcmRlckJ5VHlwZSA9IHokMS5lbnVtKFsiYXNjZW5kaW5nIiwgImRlc2NlbmRpbmciXSk7CiAgY29uc3Qgb3JkZXJCeSA9IHokMS5vYmplY3QoewogICAgZmllbGQ6IHokMS5zdHJpbmcoKSwKICAgIHR5cGU6IG9yZGVyQnlUeXBlCiAgfSk7CiAgY29uc3QgbGFwaXNCYXNlUmVxdWVzdCA9IHokMS5vYmplY3QoewogICAgbGltaXQ6IHokMS5udW1iZXIoKS5vcHRpb25hbCgpLAogICAgb2Zmc2V0OiB6JDEubnVtYmVyKCkub3B0aW9uYWwoKSwKICAgIGZpZWxkczogeiQxLmFycmF5KHokMS5zdHJpbmcoKSkub3B0aW9uYWwoKSwKICAgIG9yZGVyQnk6IHokMS5hcnJheShvcmRlckJ5KS5vcHRpb25hbCgpCiAgfSkuY2F0Y2hhbGwoeiQxLnVuaW9uKFt6JDEuYm9vbGVhbigpLCB6JDEudW5kZWZpbmVkKCksIHokMS5zdHJpbmcoKSwgeiQxLm51bWJlcigpLCB6JDEubnVsbCgpLCB6JDEuYXJyYXkoeiQxLnN0cmluZygpKV0pKTsKICBsYXBpc0Jhc2VSZXF1ZXN0LmV4dGVuZCh7IG1pblByb3BvcnRpb246IHokMS5udW1iZXIoKS5vcHRpb25hbCgpIH0pOwogIGNvbnN0IG11dGF0aW9uUHJvcG9ydGlvbkNvdW50ID0geiQxLm9iamVjdCh7CiAgICBtdXRhdGlvbjogeiQxLnN0cmluZygpLAogICAgcHJvcG9ydGlvbjogeiQxLm51bWJlcigpLAogICAgY291bnQ6IHokMS5udW1iZXIoKSwKICAgIHNlcXVlbmNlTmFtZTogeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udWxsKCldKSwKICAgIG11dGF0aW9uRnJvbTogeiQxLnN0cmluZygpLAogICAgbXV0YXRpb25UbzogeiQxLnN0cmluZygpLAogICAgcG9zaXRpb246IHokMS5udW1iZXIoKQogIH0pOwogIGNvbnN0IG11dGF0aW9uc1Jlc3BvbnNlID0gbWFrZUxhcGlzUmVzcG9uc2UoeiQxLmFycmF5KG11dGF0aW9uUHJvcG9ydGlvbkNvdW50KSk7CiAgY29uc3QgaW5zZXJ0aW9uQ291bnQgPSB6JDEub2JqZWN0KHsKICAgIGluc2VydGlvbjogeiQxLnN0cmluZygpLAogICAgY291bnQ6IHokMS5udW1iZXIoKSwKICAgIGluc2VydGVkU3ltYm9sczogeiQxLnN0cmluZygpLAogICAgcG9zaXRpb246IHokMS5udW1iZXIoKSwKICAgIHNlcXVlbmNlTmFtZTogeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udWxsKCldKQogIH0pOwogIG1ha2VMYXBpc1Jlc3BvbnNlKHokMS5hcnJheShpbnNlcnRpb25Db3VudCkpOwogIGNvbnN0IGFnZ3JlZ2F0ZWRJdGVtID0geiQxLm9iamVjdCh7IGNvdW50OiB6JDEubnVtYmVyKCkgfSkuY2F0Y2hhbGwoeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udW1iZXIoKSwgeiQxLm51bGwoKV0pKTsKICBjb25zdCBhZ2dyZWdhdGVkUmVzcG9uc2UgPSBtYWtlTGFwaXNSZXNwb25zZSh6JDEuYXJyYXkoYWdncmVnYXRlZEl0ZW0pKTsKICBmdW5jdGlvbiBtYWtlTGFwaXNSZXNwb25zZShkYXRhKSB7CiAgICByZXR1cm4geiQxLm9iamVjdCh7CiAgICAgIGRhdGEKICAgIH0pOwogIH0KICBjb25zdCBwcm9ibGVtRGV0YWlsID0geiQxLm9iamVjdCh7CiAgICB0aXRsZTogeiQxLnN0cmluZygpLm9wdGlvbmFsKCksCiAgICBzdGF0dXM6IHokMS5udW1iZXIoKSwKICAgIGRldGFpbDogeiQxLnN0cmluZygpLm9wdGlvbmFsKCksCiAgICB0eXBlOiB6JDEuc3RyaW5nKCksCiAgICBpbnN0YW5jZTogeiQxLnN0cmluZygpLm9wdGlvbmFsKCkKICB9KTsKICBjb25zdCBsYXBpc0Vycm9yID0geiQxLm9iamVjdCh7CiAgICBlcnJvcjogcHJvYmxlbURldGFpbAogIH0pOwogIGNsYXNzIFVua25vd25MYXBpc0Vycm9yIGV4dGVuZHMgRXJyb3IgewogICAgY29uc3RydWN0b3IobWVzc2FnZSwgc3RhdHVzLCByZXF1ZXN0ZWREYXRhKSB7CiAgICAgIHN1cGVyKG1lc3NhZ2UpOwogICAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgICAgdGhpcy5yZXF1ZXN0ZWREYXRhID0gcmVxdWVzdGVkRGF0YTsKICAgICAgdGhpcy5uYW1lID0gIlVua25vd25MYXBpc0Vycm9yIjsKICAgIH0KICB9CiAgY2xhc3MgTGFwaXNFcnJvciBleHRlbmRzIEVycm9yIHsKICAgIGNvbnN0cnVjdG9yKG1lc3NhZ2UsIHN0YXR1cywgcHJvYmxlbURldGFpbDIsIHJlcXVlc3RlZERhdGEpIHsKICAgICAgc3VwZXIobWVzc2FnZSk7CiAgICAgIHRoaXMuc3RhdHVzID0gc3RhdHVzOwogICAgICB0aGlzLnByb2JsZW1EZXRhaWwgPSBwcm9ibGVtRGV0YWlsMjsKICAgICAgdGhpcy5yZXF1ZXN0ZWREYXRhID0gcmVxdWVzdGVkRGF0YTsKICAgICAgdGhpcy5uYW1lID0gIkxhcGlzRXJyb3IiOwogICAgfQogIH0KICBhc3luYyBmdW5jdGlvbiBmZXRjaEFnZ3JlZ2F0ZWQobGFwaXNVcmwsIGJvZHksIHNpZ25hbCkgewogICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjYWxsTGFwaXMoCiAgICAgIGFnZ3JlZ2F0ZWRFbmRwb2ludChsYXBpc1VybCksCiAgICAgIHsKICAgICAgICBtZXRob2Q6ICJQT1NUIiwKICAgICAgICBoZWFkZXJzOiB7CiAgICAgICAgICAiQ29udGVudC1UeXBlIjogImFwcGxpY2F0aW9uL2pzb24iCiAgICAgICAgfSwKICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShib2R5KSwKICAgICAgICBzaWduYWwKICAgICAgfSwKICAgICAgImFnZ3JlZ2F0ZWQgZGF0YSIKICAgICk7CiAgICByZXR1cm4gYWdncmVnYXRlZFJlc3BvbnNlLnBhcnNlKGF3YWl0IHJlc3BvbnNlLmpzb24oKSk7CiAgfQogIGFzeW5jIGZ1bmN0aW9uIGZldGNoU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zKGxhcGlzVXJsLCBib2R5LCBzZXF1ZW5jZVR5cGUsIHNpZ25hbCkgewogICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjYWxsTGFwaXMoCiAgICAgIHN1YnN0aXR1dGlvbnNPckRlbGV0aW9uc0VuZHBvaW50KGxhcGlzVXJsLCBzZXF1ZW5jZVR5cGUpLAogICAgICB7CiAgICAgICAgbWV0aG9kOiAiUE9TVCIsCiAgICAgICAgaGVhZGVyczogewogICAgICAgICAgIkNvbnRlbnQtVHlwZSI6ICJhcHBsaWNhdGlvbi9qc29uIgogICAgICAgIH0sCiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoYm9keSksCiAgICAgICAgc2lnbmFsCiAgICAgIH0sCiAgICAgIGAke3NlcXVlbmNlVHlwZX0gbXV0YXRpb25zYAogICAgKTsKICAgIHJldHVybiBtdXRhdGlvbnNSZXNwb25zZS5wYXJzZShhd2FpdCByZXNwb25zZS5qc29uKCkpOwogIH0KICBhc3luYyBmdW5jdGlvbiBjYWxsTGFwaXMoaW5wdXQsIGluaXQsIHJlcXVlc3RlZERhdGFOYW1lKSB7CiAgICB0cnkgewogICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGlucHV0LCBpbml0KTsKICAgICAgYXdhaXQgaGFuZGxlRXJyb3JzKHJlc3BvbnNlLCByZXF1ZXN0ZWREYXRhTmFtZSk7CiAgICAgIHJldHVybiByZXNwb25zZTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IGAke2Vycm9yfWA7CiAgICAgIHRocm93IG5ldyBVbmtub3duTGFwaXNFcnJvcihgRmFpbGVkIHRvIGNvbm5lY3QgdG8gTEFQSVM6ICR7bWVzc2FnZX1gLCA1MDAsIHJlcXVlc3RlZERhdGFOYW1lKTsKICAgIH0KICB9CiAgY29uc3QgaGFuZGxlRXJyb3JzID0gYXN5bmMgKHJlc3BvbnNlLCByZXF1ZXN0ZWREYXRhKSA9PiB7CiAgICBpZiAoIXJlc3BvbnNlLm9rKSB7CiAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgPj0gNDAwICYmIHJlc3BvbnNlLnN0YXR1cyA8IDUwMCkgewogICAgICAgIGNvbnN0IGpzb24gPSBhd2FpdCByZXNwb25zZS5qc29uKCk7CiAgICAgICAgY29uc3QgbGFwaXNFcnJvclJlc3VsdCA9IGxhcGlzRXJyb3Iuc2FmZVBhcnNlKGpzb24pOwogICAgICAgIGlmIChsYXBpc0Vycm9yUmVzdWx0LnN1Y2Nlc3MpIHsKICAgICAgICAgIHRocm93IG5ldyBMYXBpc0Vycm9yKAogICAgICAgICAgICByZXNwb25zZS5zdGF0dXNUZXh0ICsgbGFwaXNFcnJvclJlc3VsdC5kYXRhLmVycm9yLmRldGFpbCwKICAgICAgICAgICAgcmVzcG9uc2Uuc3RhdHVzLAogICAgICAgICAgICBsYXBpc0Vycm9yUmVzdWx0LmRhdGEuZXJyb3IsCiAgICAgICAgICAgIHJlcXVlc3RlZERhdGEKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHByb2JsZW1EZXRhaWxSZXN1bHQgPSBwcm9ibGVtRGV0YWlsLnNhZmVQYXJzZShqc29uKTsKICAgICAgICBpZiAocHJvYmxlbURldGFpbFJlc3VsdC5zdWNjZXNzKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTGFwaXNFcnJvcigKICAgICAgICAgICAgcmVzcG9uc2Uuc3RhdHVzVGV4dCArIHByb2JsZW1EZXRhaWxSZXN1bHQuZGF0YS5kZXRhaWwsCiAgICAgICAgICAgIHJlc3BvbnNlLnN0YXR1cywKICAgICAgICAgICAgcHJvYmxlbURldGFpbFJlc3VsdC5kYXRhLAogICAgICAgICAgICByZXF1ZXN0ZWREYXRhCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICB0aHJvdyBuZXcgVW5rbm93bkxhcGlzRXJyb3IoCiAgICAgICAgICBgJHtyZXNwb25zZS5zdGF0dXNUZXh0fTogJHtKU09OLnN0cmluZ2lmeShqc29uKX1gLAogICAgICAgICAgcmVzcG9uc2Uuc3RhdHVzLAogICAgICAgICAgcmVxdWVzdGVkRGF0YQogICAgICAgICk7CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IFVua25vd25MYXBpc0Vycm9yKGAke3Jlc3BvbnNlLnN0YXR1c1RleHR9OiAke3Jlc3BvbnNlLnN0YXR1c31gLCByZXNwb25zZS5zdGF0dXMsIHJlcXVlc3RlZERhdGEpOwogICAgfQogIH07CiAgY29uc3QgYWdncmVnYXRlZEVuZHBvaW50ID0gKGxhcGlzVXJsKSA9PiBgJHtsYXBpc1VybH0vc2FtcGxlL2FnZ3JlZ2F0ZWRgOwogIGNvbnN0IHN1YnN0aXR1dGlvbnNPckRlbGV0aW9uc0VuZHBvaW50ID0gKGxhcGlzVXJsLCBzZXF1ZW5jZVR5cGUpID0+IHsKICAgIHJldHVybiBzZXF1ZW5jZVR5cGUgPT09ICJhbWlubyBhY2lkIiA/IGAke2xhcGlzVXJsfS9zYW1wbGUvYW1pbm9BY2lkTXV0YXRpb25zYCA6IGAke2xhcGlzVXJsfS9zYW1wbGUvbnVjbGVvdGlkZU11dGF0aW9uc2A7CiAgfTsKICBjbGFzcyBGZXRjaEFnZ3JlZ2F0ZWRPcGVyYXRvciB7CiAgICBjb25zdHJ1Y3RvcihmaWx0ZXIsIGZpZWxkcyA9IFtdKSB7CiAgICAgIHRoaXMuZmlsdGVyID0gZmlsdGVyOwogICAgICB0aGlzLmZpZWxkcyA9IGZpZWxkczsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzVXJsLCBzaWduYWwpIHsKICAgICAgY29uc3QgYWdncmVnYXRlZFJlc3BvbnNlMiA9IChhd2FpdCBmZXRjaEFnZ3JlZ2F0ZWQoCiAgICAgICAgbGFwaXNVcmwsCiAgICAgICAgewogICAgICAgICAgLi4udGhpcy5maWx0ZXIsCiAgICAgICAgICBmaWVsZHM6IHRoaXMuZmllbGRzCiAgICAgICAgfSwKICAgICAgICBzaWduYWwKICAgICAgKSkuZGF0YTsKICAgICAgaWYgKGlzRmllbGRzQXJyYXlXaXRoQ291bnQoYWdncmVnYXRlZFJlc3BvbnNlMikpIHsKICAgICAgICByZXR1cm4gewogICAgICAgICAgY29udGVudDogYWdncmVnYXRlZFJlc3BvbnNlMgogICAgICAgIH07CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IEVycm9yKCJBZ2dyZWdhdGVkIHJlc3BvbnNlIGRvZXMgbm90IGhhdmUgY291bnQiKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gaXNGaWVsZHNBcnJheVdpdGhDb3VudChkYXRhKSB7CiAgICByZXR1cm4gZGF0YS5ldmVyeSgoaXRlbSkgPT4gdHlwZW9mIGl0ZW0gPT09ICJvYmplY3QiICYmICJjb3VudCIgaW4gaXRlbSAmJiB0eXBlb2YgaXRlbS5jb3VudCA9PT0gIm51bWJlciIpOwogIH0KICBjbGFzcyBHcm91cEJ5T3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoY2hpbGQsIGZpZWxkLCBhZ2dyZWdhdGUpIHsKICAgICAgdGhpcy5jaGlsZCA9IGNoaWxkOwogICAgICB0aGlzLmZpZWxkID0gZmllbGQ7CiAgICAgIHRoaXMuYWdncmVnYXRlID0gYWdncmVnYXRlOwogICAgfQogICAgYXN5bmMgZXZhbHVhdGUobGFwaXMsIHNpZ25hbCkgewogICAgICBjb25zdCBjaGlsZEV2YWx1YXRlZCA9IGF3YWl0IHRoaXMuY2hpbGQuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgICAgIGNvbnN0IGdyb3VwZWQgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICBmb3IgKGNvbnN0IHJvdyBvZiBjaGlsZEV2YWx1YXRlZC5jb250ZW50KSB7CiAgICAgICAgY29uc3Qga2V5ID0gcm93W3RoaXMuZmllbGRdOwogICAgICAgIGlmICghZ3JvdXBlZC5oYXMoa2V5KSkgewogICAgICAgICAgZ3JvdXBlZC5zZXQoa2V5LCBbXSk7CiAgICAgICAgfQogICAgICAgIGdyb3VwZWQuZ2V0KGtleSkucHVzaChyb3cpOwogICAgICB9CiAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBBcnJheSgpOwogICAgICBmb3IgKGNvbnN0IFssIHZhbHVlc10gb2YgZ3JvdXBlZCkgewogICAgICAgIHJlc3VsdC5wdXNoKHRoaXMuYWdncmVnYXRlKHZhbHVlcykpOwogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgY29udGVudDogcmVzdWx0CiAgICAgIH07CiAgICB9CiAgfQogIGNsYXNzIEdyb3VwQnlBbmRTdW1PcGVyYXRvciBleHRlbmRzIEdyb3VwQnlPcGVyYXRvciB7CiAgICBjb25zdHJ1Y3RvcihjaGlsZCwgZ3JvdXBCeUZpZWxkLCBzdW1GaWVsZCkgewogICAgICBzdXBlcihjaGlsZCwgZ3JvdXBCeUZpZWxkLCAodmFsdWVzKSA9PiB7CiAgICAgICAgbGV0IG4gPSAwOwogICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgdmFsdWVzKSB7CiAgICAgICAgICBuICs9IHZhbHVlW3N1bUZpZWxkXTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIFtncm91cEJ5RmllbGRdOiB2YWx1ZXNbMF1bZ3JvdXBCeUZpZWxkXSwKICAgICAgICAgIFtzdW1GaWVsZF06IG4KICAgICAgICB9OwogICAgICB9KTsKICAgIH0KICB9CiAgY2xhc3MgTWFwT3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoY2hpbGQsIGZ1bmMpIHsKICAgICAgdGhpcy5jaGlsZCA9IGNoaWxkOwogICAgICB0aGlzLmZ1bmMgPSBmdW5jOwogICAgfQogICAgYXN5bmMgZXZhbHVhdGUobGFwaXMsIHNpZ25hbCkgewogICAgICBjb25zdCBjaGlsZEV2YWx1YXRlZCA9IGF3YWl0IHRoaXMuY2hpbGQuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgY29udGVudDogY2hpbGRFdmFsdWF0ZWQuY29udGVudC5tYXAodGhpcy5mdW5jKQogICAgICB9OwogICAgfQogIH0KICBjbGFzcyBSZW5hbWVGaWVsZE9wZXJhdG9yIGV4dGVuZHMgTWFwT3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoY2hpbGQsIG9sZEZpZWxkTmFtZSwgbmV3RmllbGROYW1lKSB7CiAgICAgIHN1cGVyKAogICAgICAgIGNoaWxkLAogICAgICAgICh2YWx1ZSkgPT4gKHsKICAgICAgICAgIC4uLnZhbHVlLAogICAgICAgICAgW25ld0ZpZWxkTmFtZV06IHZhbHVlW29sZEZpZWxkTmFtZV0KICAgICAgICB9KQogICAgICApOwogICAgfQogIH0KICBjbGFzcyBTb3J0T3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoY2hpbGQsIGNvbXBhcmVGbikgewogICAgICB0aGlzLmNoaWxkID0gY2hpbGQ7CiAgICAgIHRoaXMuY29tcGFyZUZuID0gY29tcGFyZUZuOwogICAgfQogICAgYXN5bmMgZXZhbHVhdGUobGFwaXMsIHNpZ25hbCkgewogICAgICBjb25zdCBjaGlsZEV2YWx1YXRlZCA9IGF3YWl0IHRoaXMuY2hpbGQuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgY29udGVudDogY2hpbGRFdmFsdWF0ZWQuY29udGVudC5zb3J0KHRoaXMuY29tcGFyZUZuKQogICAgICB9OwogICAgfQogIH0KICB2YXIgU0VDT05EU19BX01JTlVURSA9IDYwOwogIHZhciBTRUNPTkRTX0FfSE9VUiA9IFNFQ09ORFNfQV9NSU5VVEUgKiA2MDsKICB2YXIgU0VDT05EU19BX0RBWSA9IFNFQ09ORFNfQV9IT1VSICogMjQ7CiAgdmFyIFNFQ09ORFNfQV9XRUVLID0gU0VDT05EU19BX0RBWSAqIDc7CiAgdmFyIE1JTExJU0VDT05EU19BX1NFQ09ORCA9IDFlMzsKICB2YXIgTUlMTElTRUNPTkRTX0FfTUlOVVRFID0gU0VDT05EU19BX01JTlVURSAqIE1JTExJU0VDT05EU19BX1NFQ09ORDsKICB2YXIgTUlMTElTRUNPTkRTX0FfSE9VUiA9IFNFQ09ORFNfQV9IT1VSICogTUlMTElTRUNPTkRTX0FfU0VDT05EOwogIHZhciBNSUxMSVNFQ09ORFNfQV9EQVkgPSBTRUNPTkRTX0FfREFZICogTUlMTElTRUNPTkRTX0FfU0VDT05EOwogIHZhciBNSUxMSVNFQ09ORFNfQV9XRUVLID0gU0VDT05EU19BX1dFRUsgKiBNSUxMSVNFQ09ORFNfQV9TRUNPTkQ7CiAgdmFyIE1TID0gIm1pbGxpc2Vjb25kIjsKICB2YXIgUyA9ICJzZWNvbmQiOwogIHZhciBNSU4gPSAibWludXRlIjsKICB2YXIgSCA9ICJob3VyIjsKICB2YXIgRCA9ICJkYXkiOwogIHZhciBXID0gIndlZWsiOwogIHZhciBNID0gIm1vbnRoIjsKICB2YXIgUSA9ICJxdWFydGVyIjsKICB2YXIgWSA9ICJ5ZWFyIjsKICB2YXIgREFURSA9ICJkYXRlIjsKICB2YXIgRk9STUFUX0RFRkFVTFQgPSAiWVlZWS1NTS1ERFRISDptbTpzc1oiOwogIHZhciBJTlZBTElEX0RBVEVfU1RSSU5HID0gIkludmFsaWQgRGF0ZSI7CiAgdmFyIFJFR0VYX1BBUlNFID0gL14oXGR7NH0pWy0vXT8oXGR7MSwyfSk/Wy0vXT8oXGR7MCwyfSlbVHRcc10qKFxkezEsMn0pPzo/KFxkezEsMn0pPzo/KFxkezEsMn0pP1suOl0/KFxkKyk/JC87CiAgdmFyIFJFR0VYX0ZPUk1BVCA9IC9cWyhbXlxdXSspXXxZezEsNH18TXsxLDR9fER7MSwyfXxkezEsNH18SHsxLDJ9fGh7MSwyfXxhfEF8bXsxLDJ9fHN7MSwyfXxaezEsMn18U1NTL2c7CiAgdmFyIGVuID0gewogICAgbmFtZTogImVuIiwKICAgIHdlZWtkYXlzOiAiU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXkiLnNwbGl0KCJfIiksCiAgICBtb250aHM6ICJKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyIi5zcGxpdCgiXyIpLAogICAgb3JkaW5hbDogZnVuY3Rpb24gb3JkaW5hbChuKSB7CiAgICAgIHZhciBzMiA9IFsidGgiLCAic3QiLCAibmQiLCAicmQiXTsKICAgICAgdmFyIHYyID0gbiAlIDEwMDsKICAgICAgcmV0dXJuICJbIiArIG4gKyAoczJbKHYyIC0gMjApICUgMTBdIHx8IHMyW3YyXSB8fCBzMlswXSkgKyAiXSI7CiAgICB9CiAgfTsKICB2YXIgcGFkU3RhcnQgPSBmdW5jdGlvbiBwYWRTdGFydDIoc3RyaW5nLCBsZW5ndGgsIHBhZCkgewogICAgdmFyIHMyID0gU3RyaW5nKHN0cmluZyk7CiAgICBpZiAoIXMyIHx8IHMyLmxlbmd0aCA+PSBsZW5ndGgpIHJldHVybiBzdHJpbmc7CiAgICByZXR1cm4gIiIgKyBBcnJheShsZW5ndGggKyAxIC0gczIubGVuZ3RoKS5qb2luKHBhZCkgKyBzdHJpbmc7CiAgfTsKICB2YXIgcGFkWm9uZVN0ciA9IGZ1bmN0aW9uIHBhZFpvbmVTdHIyKGluc3RhbmNlKSB7CiAgICB2YXIgbmVnTWludXRlcyA9IC1pbnN0YW5jZS51dGNPZmZzZXQoKTsKICAgIHZhciBtaW51dGVzID0gTWF0aC5hYnMobmVnTWludXRlcyk7CiAgICB2YXIgaG91ck9mZnNldCA9IE1hdGguZmxvb3IobWludXRlcyAvIDYwKTsKICAgIHZhciBtaW51dGVPZmZzZXQgPSBtaW51dGVzICUgNjA7CiAgICByZXR1cm4gKG5lZ01pbnV0ZXMgPD0gMCA/ICIrIiA6ICItIikgKyBwYWRTdGFydChob3VyT2Zmc2V0LCAyLCAiMCIpICsgIjoiICsgcGFkU3RhcnQobWludXRlT2Zmc2V0LCAyLCAiMCIpOwogIH07CiAgdmFyIG1vbnRoRGlmZiA9IGZ1bmN0aW9uIG1vbnRoRGlmZjIoYTIsIGIpIHsKICAgIGlmIChhMi5kYXRlKCkgPCBiLmRhdGUoKSkgcmV0dXJuIC1tb250aERpZmYyKGIsIGEyKTsKICAgIHZhciB3aG9sZU1vbnRoRGlmZiA9IChiLnllYXIoKSAtIGEyLnllYXIoKSkgKiAxMiArIChiLm1vbnRoKCkgLSBhMi5tb250aCgpKTsKICAgIHZhciBhbmNob3IgPSBhMi5jbG9uZSgpLmFkZCh3aG9sZU1vbnRoRGlmZiwgTSk7CiAgICB2YXIgYzIgPSBiIC0gYW5jaG9yIDwgMDsKICAgIHZhciBhbmNob3IyID0gYTIuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYgKyAoYzIgPyAtMSA6IDEpLCBNKTsKICAgIHJldHVybiArKC0od2hvbGVNb250aERpZmYgKyAoYiAtIGFuY2hvcikgLyAoYzIgPyBhbmNob3IgLSBhbmNob3IyIDogYW5jaG9yMiAtIGFuY2hvcikpIHx8IDApOwogIH07CiAgdmFyIGFic0Zsb29yID0gZnVuY3Rpb24gYWJzRmxvb3IyKG4pIHsKICAgIHJldHVybiBuIDwgMCA/IE1hdGguY2VpbChuKSB8fCAwIDogTWF0aC5mbG9vcihuKTsKICB9OwogIHZhciBwcmV0dHlVbml0ID0gZnVuY3Rpb24gcHJldHR5VW5pdDIodTIpIHsKICAgIHZhciBzcGVjaWFsID0gewogICAgICBNLAogICAgICB5OiBZLAogICAgICB3OiBXLAogICAgICBkOiBELAogICAgICBEOiBEQVRFLAogICAgICBoOiBILAogICAgICBtOiBNSU4sCiAgICAgIHM6IFMsCiAgICAgIG1zOiBNUywKICAgICAgUQogICAgfTsKICAgIHJldHVybiBzcGVjaWFsW3UyXSB8fCBTdHJpbmcodTIgfHwgIiIpLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvcyQvLCAiIik7CiAgfTsKICB2YXIgaXNVbmRlZmluZWQgPSBmdW5jdGlvbiBpc1VuZGVmaW5lZDIoczIpIHsKICAgIHJldHVybiBzMiA9PT0gdm9pZCAwOwogIH07CiAgdmFyIFUgPSB7CiAgICBzOiBwYWRTdGFydCwKICAgIHo6IHBhZFpvbmVTdHIsCiAgICBtOiBtb250aERpZmYsCiAgICBhOiBhYnNGbG9vciwKICAgIHA6IHByZXR0eVVuaXQsCiAgICB1OiBpc1VuZGVmaW5lZAogIH07CiAgdmFyIEwgPSAiZW4iOwogIHZhciBMcyA9IHt9OwogIExzW0xdID0gZW47CiAgdmFyIElTX0RBWUpTID0gIiRpc0RheWpzT2JqZWN0IjsKICB2YXIgaXNEYXlqcyA9IGZ1bmN0aW9uIGlzRGF5anMyKGQpIHsKICAgIHJldHVybiBkIGluc3RhbmNlb2YgRGF5anMgfHwgISEoZCAmJiBkW0lTX0RBWUpTXSk7CiAgfTsKICB2YXIgcGFyc2VMb2NhbGUgPSBmdW5jdGlvbiBwYXJzZUxvY2FsZTIocHJlc2V0LCBvYmplY3QsIGlzTG9jYWwpIHsKICAgIHZhciBsMjsKICAgIGlmICghcHJlc2V0KSByZXR1cm4gTDsKICAgIGlmICh0eXBlb2YgcHJlc2V0ID09PSAic3RyaW5nIikgewogICAgICB2YXIgcHJlc2V0TG93ZXIgPSBwcmVzZXQudG9Mb3dlckNhc2UoKTsKICAgICAgaWYgKExzW3ByZXNldExvd2VyXSkgewogICAgICAgIGwyID0gcHJlc2V0TG93ZXI7CiAgICAgIH0KICAgICAgaWYgKG9iamVjdCkgewogICAgICAgIExzW3ByZXNldExvd2VyXSA9IG9iamVjdDsKICAgICAgICBsMiA9IHByZXNldExvd2VyOwogICAgICB9CiAgICAgIHZhciBwcmVzZXRTcGxpdCA9IHByZXNldC5zcGxpdCgiLSIpOwogICAgICBpZiAoIWwyICYmIHByZXNldFNwbGl0Lmxlbmd0aCA+IDEpIHsKICAgICAgICByZXR1cm4gcGFyc2VMb2NhbGUyKHByZXNldFNwbGl0WzBdKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdmFyIG5hbWUgPSBwcmVzZXQubmFtZTsKICAgICAgTHNbbmFtZV0gPSBwcmVzZXQ7CiAgICAgIGwyID0gbmFtZTsKICAgIH0KICAgIGlmICghaXNMb2NhbCAmJiBsMikgTCA9IGwyOwogICAgcmV0dXJuIGwyIHx8ICFpc0xvY2FsICYmIEw7CiAgfTsKICB2YXIgZGF5anMgPSBmdW5jdGlvbiBkYXlqczIoZGF0ZSwgYzIpIHsKICAgIGlmIChpc0RheWpzKGRhdGUpKSB7CiAgICAgIHJldHVybiBkYXRlLmNsb25lKCk7CiAgICB9CiAgICB2YXIgY2ZnID0gdHlwZW9mIGMyID09PSAib2JqZWN0IiA/IGMyIDoge307CiAgICBjZmcuZGF0ZSA9IGRhdGU7CiAgICBjZmcuYXJncyA9IGFyZ3VtZW50czsKICAgIHJldHVybiBuZXcgRGF5anMoY2ZnKTsKICB9OwogIHZhciB3cmFwcGVyID0gZnVuY3Rpb24gd3JhcHBlcjIoZGF0ZSwgaW5zdGFuY2UpIHsKICAgIHJldHVybiBkYXlqcyhkYXRlLCB7CiAgICAgIGxvY2FsZTogaW5zdGFuY2UuJEwsCiAgICAgIHV0YzogaW5zdGFuY2UuJHUsCiAgICAgIHg6IGluc3RhbmNlLiR4LAogICAgICAkb2Zmc2V0OiBpbnN0YW5jZS4kb2Zmc2V0CiAgICAgIC8vIHRvZG86IHJlZmFjdG9yOyBkbyBub3QgdXNlIHRoaXMuJG9mZnNldCBpbiB5b3UgY29kZQogICAgfSk7CiAgfTsKICB2YXIgVXRpbHMgPSBVOwogIFV0aWxzLmwgPSBwYXJzZUxvY2FsZTsKICBVdGlscy5pID0gaXNEYXlqczsKICBVdGlscy53ID0gd3JhcHBlcjsKICB2YXIgcGFyc2VEYXRlID0gZnVuY3Rpb24gcGFyc2VEYXRlMihjZmcpIHsKICAgIHZhciBkYXRlID0gY2ZnLmRhdGUsIHV0YyA9IGNmZy51dGM7CiAgICBpZiAoZGF0ZSA9PT0gbnVsbCkgcmV0dXJuIC8qIEBfX1BVUkVfXyAqLyBuZXcgRGF0ZShOYU4pOwogICAgaWYgKFV0aWxzLnUoZGF0ZSkpIHJldHVybiAvKiBAX19QVVJFX18gKi8gbmV3IERhdGUoKTsKICAgIGlmIChkYXRlIGluc3RhbmNlb2YgRGF0ZSkgcmV0dXJuIG5ldyBEYXRlKGRhdGUpOwogICAgaWYgKHR5cGVvZiBkYXRlID09PSAic3RyaW5nIiAmJiAhL1okL2kudGVzdChkYXRlKSkgewogICAgICB2YXIgZCA9IGRhdGUubWF0Y2goUkVHRVhfUEFSU0UpOwogICAgICBpZiAoZCkgewogICAgICAgIHZhciBtMiA9IGRbMl0gLSAxIHx8IDA7CiAgICAgICAgdmFyIG1zID0gKGRbN10gfHwgIjAiKS5zdWJzdHJpbmcoMCwgMyk7CiAgICAgICAgaWYgKHV0YykgewogICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKERhdGUuVVRDKGRbMV0sIG0yLCBkWzNdIHx8IDEsIGRbNF0gfHwgMCwgZFs1XSB8fCAwLCBkWzZdIHx8IDAsIG1zKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgRGF0ZShkWzFdLCBtMiwgZFszXSB8fCAxLCBkWzRdIHx8IDAsIGRbNV0gfHwgMCwgZFs2XSB8fCAwLCBtcyk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBuZXcgRGF0ZShkYXRlKTsKICB9OwogIHZhciBEYXlqcyA9IC8qIEBfX1BVUkVfXyAqLyBmdW5jdGlvbigpIHsKICAgIGZ1bmN0aW9uIERheWpzMihjZmcpIHsKICAgICAgdGhpcy4kTCA9IHBhcnNlTG9jYWxlKGNmZy5sb2NhbGUsIG51bGwsIHRydWUpOwogICAgICB0aGlzLnBhcnNlKGNmZyk7CiAgICAgIHRoaXMuJHggPSB0aGlzLiR4IHx8IGNmZy54IHx8IHt9OwogICAgICB0aGlzW0lTX0RBWUpTXSA9IHRydWU7CiAgICB9CiAgICB2YXIgX3Byb3RvID0gRGF5anMyLnByb3RvdHlwZTsKICAgIF9wcm90by5wYXJzZSA9IGZ1bmN0aW9uIHBhcnNlKGNmZykgewogICAgICB0aGlzLiRkID0gcGFyc2VEYXRlKGNmZyk7CiAgICAgIHRoaXMuaW5pdCgpOwogICAgfTsKICAgIF9wcm90by5pbml0ID0gZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgdmFyICRkID0gdGhpcy4kZDsKICAgICAgdGhpcy4keSA9ICRkLmdldEZ1bGxZZWFyKCk7CiAgICAgIHRoaXMuJE0gPSAkZC5nZXRNb250aCgpOwogICAgICB0aGlzLiREID0gJGQuZ2V0RGF0ZSgpOwogICAgICB0aGlzLiRXID0gJGQuZ2V0RGF5KCk7CiAgICAgIHRoaXMuJEggPSAkZC5nZXRIb3VycygpOwogICAgICB0aGlzLiRtID0gJGQuZ2V0TWludXRlcygpOwogICAgICB0aGlzLiRzID0gJGQuZ2V0U2Vjb25kcygpOwogICAgICB0aGlzLiRtcyA9ICRkLmdldE1pbGxpc2Vjb25kcygpOwogICAgfTsKICAgIF9wcm90by4kdXRpbHMgPSBmdW5jdGlvbiAkdXRpbHMoKSB7CiAgICAgIHJldHVybiBVdGlsczsKICAgIH07CiAgICBfcHJvdG8uaXNWYWxpZCA9IGZ1bmN0aW9uIGlzVmFsaWQyKCkgewogICAgICByZXR1cm4gISh0aGlzLiRkLnRvU3RyaW5nKCkgPT09IElOVkFMSURfREFURV9TVFJJTkcpOwogICAgfTsKICAgIF9wcm90by5pc1NhbWUgPSBmdW5jdGlvbiBpc1NhbWUodGhhdCwgdW5pdHMpIHsKICAgICAgdmFyIG90aGVyID0gZGF5anModGhhdCk7CiAgICAgIHJldHVybiB0aGlzLnN0YXJ0T2YodW5pdHMpIDw9IG90aGVyICYmIG90aGVyIDw9IHRoaXMuZW5kT2YodW5pdHMpOwogICAgfTsKICAgIF9wcm90by5pc0FmdGVyID0gZnVuY3Rpb24gaXNBZnRlcih0aGF0LCB1bml0cykgewogICAgICByZXR1cm4gZGF5anModGhhdCkgPCB0aGlzLnN0YXJ0T2YodW5pdHMpOwogICAgfTsKICAgIF9wcm90by5pc0JlZm9yZSA9IGZ1bmN0aW9uIGlzQmVmb3JlKHRoYXQsIHVuaXRzKSB7CiAgICAgIHJldHVybiB0aGlzLmVuZE9mKHVuaXRzKSA8IGRheWpzKHRoYXQpOwogICAgfTsKICAgIF9wcm90by4kZyA9IGZ1bmN0aW9uICRnKGlucHV0LCBnZXQsIHNldCkgewogICAgICBpZiAoVXRpbHMudShpbnB1dCkpIHJldHVybiB0aGlzW2dldF07CiAgICAgIHJldHVybiB0aGlzLnNldChzZXQsIGlucHV0KTsKICAgIH07CiAgICBfcHJvdG8udW5peCA9IGZ1bmN0aW9uIHVuaXgoKSB7CiAgICAgIHJldHVybiBNYXRoLmZsb29yKHRoaXMudmFsdWVPZigpIC8gMWUzKTsKICAgIH07CiAgICBfcHJvdG8udmFsdWVPZiA9IGZ1bmN0aW9uIHZhbHVlT2YoKSB7CiAgICAgIHJldHVybiB0aGlzLiRkLmdldFRpbWUoKTsKICAgIH07CiAgICBfcHJvdG8uc3RhcnRPZiA9IGZ1bmN0aW9uIHN0YXJ0T2YodW5pdHMsIF9zdGFydE9mKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CiAgICAgIHZhciBpc1N0YXJ0T2YgPSAhVXRpbHMudShfc3RhcnRPZikgPyBfc3RhcnRPZiA6IHRydWU7CiAgICAgIHZhciB1bml0ID0gVXRpbHMucCh1bml0cyk7CiAgICAgIHZhciBpbnN0YW5jZUZhY3RvcnkgPSBmdW5jdGlvbiBpbnN0YW5jZUZhY3RvcnkyKGQsIG0yKSB7CiAgICAgICAgdmFyIGlucyA9IFV0aWxzLncoX3RoaXMuJHUgPyBEYXRlLlVUQyhfdGhpcy4keSwgbTIsIGQpIDogbmV3IERhdGUoX3RoaXMuJHksIG0yLCBkKSwgX3RoaXMpOwogICAgICAgIHJldHVybiBpc1N0YXJ0T2YgPyBpbnMgOiBpbnMuZW5kT2YoRCk7CiAgICAgIH07CiAgICAgIHZhciBpbnN0YW5jZUZhY3RvcnlTZXQgPSBmdW5jdGlvbiBpbnN0YW5jZUZhY3RvcnlTZXQyKG1ldGhvZCwgc2xpY2UpIHsKICAgICAgICB2YXIgYXJndW1lbnRTdGFydCA9IFswLCAwLCAwLCAwXTsKICAgICAgICB2YXIgYXJndW1lbnRFbmQgPSBbMjMsIDU5LCA1OSwgOTk5XTsKICAgICAgICByZXR1cm4gVXRpbHMudyhfdGhpcy50b0RhdGUoKVttZXRob2RdLmFwcGx5KAogICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBwcmVmZXItc3ByZWFkCiAgICAgICAgICBfdGhpcy50b0RhdGUoInMiKSwKICAgICAgICAgIChpc1N0YXJ0T2YgPyBhcmd1bWVudFN0YXJ0IDogYXJndW1lbnRFbmQpLnNsaWNlKHNsaWNlKQogICAgICAgICksIF90aGlzKTsKICAgICAgfTsKICAgICAgdmFyICRXID0gdGhpcy4kVywgJE0gPSB0aGlzLiRNLCAkRCA9IHRoaXMuJEQ7CiAgICAgIHZhciB1dGNQYWQgPSAic2V0IiArICh0aGlzLiR1ID8gIlVUQyIgOiAiIik7CiAgICAgIHN3aXRjaCAodW5pdCkgewogICAgICAgIGNhc2UgWToKICAgICAgICAgIHJldHVybiBpc1N0YXJ0T2YgPyBpbnN0YW5jZUZhY3RvcnkoMSwgMCkgOiBpbnN0YW5jZUZhY3RvcnkoMzEsIDExKTsKICAgICAgICBjYXNlIE06CiAgICAgICAgICByZXR1cm4gaXNTdGFydE9mID8gaW5zdGFuY2VGYWN0b3J5KDEsICRNKSA6IGluc3RhbmNlRmFjdG9yeSgwLCAkTSArIDEpOwogICAgICAgIGNhc2UgVzogewogICAgICAgICAgdmFyIHdlZWtTdGFydCA9IHRoaXMuJGxvY2FsZSgpLndlZWtTdGFydCB8fCAwOwogICAgICAgICAgdmFyIGdhcCA9ICgkVyA8IHdlZWtTdGFydCA/ICRXICsgNyA6ICRXKSAtIHdlZWtTdGFydDsKICAgICAgICAgIHJldHVybiBpbnN0YW5jZUZhY3RvcnkoaXNTdGFydE9mID8gJEQgLSBnYXAgOiAkRCArICg2IC0gZ2FwKSwgJE0pOwogICAgICAgIH0KICAgICAgICBjYXNlIEQ6CiAgICAgICAgY2FzZSBEQVRFOgogICAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCh1dGNQYWQgKyAiSG91cnMiLCAwKTsKICAgICAgICBjYXNlIEg6CiAgICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5U2V0KHV0Y1BhZCArICJNaW51dGVzIiwgMSk7CiAgICAgICAgY2FzZSBNSU46CiAgICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5U2V0KHV0Y1BhZCArICJTZWNvbmRzIiwgMik7CiAgICAgICAgY2FzZSBTOgogICAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCh1dGNQYWQgKyAiTWlsbGlzZWNvbmRzIiwgMyk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHJldHVybiB0aGlzLmNsb25lKCk7CiAgICAgIH0KICAgIH07CiAgICBfcHJvdG8uZW5kT2YgPSBmdW5jdGlvbiBlbmRPZihhcmcpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RhcnRPZihhcmcsIGZhbHNlKTsKICAgIH07CiAgICBfcHJvdG8uJHNldCA9IGZ1bmN0aW9uICRzZXQodW5pdHMsIF9pbnQpIHsKICAgICAgdmFyIF9DJEQkQyREQVRFJEMkTSRDJFkkQzsKICAgICAgdmFyIHVuaXQgPSBVdGlscy5wKHVuaXRzKTsKICAgICAgdmFyIHV0Y1BhZCA9ICJzZXQiICsgKHRoaXMuJHUgPyAiVVRDIiA6ICIiKTsKICAgICAgdmFyIG5hbWUgPSAoX0MkRCRDJERBVEUkQyRNJEMkWSRDID0ge30sIF9DJEQkQyREQVRFJEMkTSRDJFkkQ1tEXSA9IHV0Y1BhZCArICJEYXRlIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW0RBVEVdID0gdXRjUGFkICsgIkRhdGUiLCBfQyREJEMkREFURSRDJE0kQyRZJENbTV0gPSB1dGNQYWQgKyAiTW9udGgiLCBfQyREJEMkREFURSRDJE0kQyRZJENbWV0gPSB1dGNQYWQgKyAiRnVsbFllYXIiLCBfQyREJEMkREFURSRDJE0kQyRZJENbSF0gPSB1dGNQYWQgKyAiSG91cnMiLCBfQyREJEMkREFURSRDJE0kQyRZJENbTUlOXSA9IHV0Y1BhZCArICJNaW51dGVzIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW1NdID0gdXRjUGFkICsgIlNlY29uZHMiLCBfQyREJEMkREFURSRDJE0kQyRZJENbTVNdID0gdXRjUGFkICsgIk1pbGxpc2Vjb25kcyIsIF9DJEQkQyREQVRFJEMkTSRDJFkkQylbdW5pdF07CiAgICAgIHZhciBhcmcgPSB1bml0ID09PSBEID8gdGhpcy4kRCArIChfaW50IC0gdGhpcy4kVykgOiBfaW50OwogICAgICBpZiAodW5pdCA9PT0gTSB8fCB1bml0ID09PSBZKSB7CiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLmNsb25lKCkuc2V0KERBVEUsIDEpOwogICAgICAgIGRhdGUuJGRbbmFtZV0oYXJnKTsKICAgICAgICBkYXRlLmluaXQoKTsKICAgICAgICB0aGlzLiRkID0gZGF0ZS5zZXQoREFURSwgTWF0aC5taW4odGhpcy4kRCwgZGF0ZS5kYXlzSW5Nb250aCgpKSkuJGQ7CiAgICAgIH0gZWxzZSBpZiAobmFtZSkgdGhpcy4kZFtuYW1lXShhcmcpOwogICAgICB0aGlzLmluaXQoKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9OwogICAgX3Byb3RvLnNldCA9IGZ1bmN0aW9uIHNldChzdHJpbmcsIF9pbnQyKSB7CiAgICAgIHJldHVybiB0aGlzLmNsb25lKCkuJHNldChzdHJpbmcsIF9pbnQyKTsKICAgIH07CiAgICBfcHJvdG8uZ2V0ID0gZnVuY3Rpb24gZ2V0KHVuaXQpIHsKICAgICAgcmV0dXJuIHRoaXNbVXRpbHMucCh1bml0KV0oKTsKICAgIH07CiAgICBfcHJvdG8uYWRkID0gZnVuY3Rpb24gYWRkKG51bWJlciwgdW5pdHMpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXMsIF9DJE1JTiRDJEgkQyRTJHVuaXQ7CiAgICAgIG51bWJlciA9IE51bWJlcihudW1iZXIpOwogICAgICB2YXIgdW5pdCA9IFV0aWxzLnAodW5pdHMpOwogICAgICB2YXIgaW5zdGFuY2VGYWN0b3J5U2V0ID0gZnVuY3Rpb24gaW5zdGFuY2VGYWN0b3J5U2V0MihuKSB7CiAgICAgICAgdmFyIGQgPSBkYXlqcyhfdGhpczIpOwogICAgICAgIHJldHVybiBVdGlscy53KGQuZGF0ZShkLmRhdGUoKSArIE1hdGgucm91bmQobiAqIG51bWJlcikpLCBfdGhpczIpOwogICAgICB9OwogICAgICBpZiAodW5pdCA9PT0gTSkgewogICAgICAgIHJldHVybiB0aGlzLnNldChNLCB0aGlzLiRNICsgbnVtYmVyKTsKICAgICAgfQogICAgICBpZiAodW5pdCA9PT0gWSkgewogICAgICAgIHJldHVybiB0aGlzLnNldChZLCB0aGlzLiR5ICsgbnVtYmVyKTsKICAgICAgfQogICAgICBpZiAodW5pdCA9PT0gRCkgewogICAgICAgIHJldHVybiBpbnN0YW5jZUZhY3RvcnlTZXQoMSk7CiAgICAgIH0KICAgICAgaWYgKHVuaXQgPT09IFcpIHsKICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5U2V0KDcpOwogICAgICB9CiAgICAgIHZhciBzdGVwID0gKF9DJE1JTiRDJEgkQyRTJHVuaXQgPSB7fSwgX0MkTUlOJEMkSCRDJFMkdW5pdFtNSU5dID0gTUlMTElTRUNPTkRTX0FfTUlOVVRFLCBfQyRNSU4kQyRIJEMkUyR1bml0W0hdID0gTUlMTElTRUNPTkRTX0FfSE9VUiwgX0MkTUlOJEMkSCRDJFMkdW5pdFtTXSA9IE1JTExJU0VDT05EU19BX1NFQ09ORCwgX0MkTUlOJEMkSCRDJFMkdW5pdClbdW5pdF0gfHwgMTsKICAgICAgdmFyIG5leHRUaW1lU3RhbXAgPSB0aGlzLiRkLmdldFRpbWUoKSArIG51bWJlciAqIHN0ZXA7CiAgICAgIHJldHVybiBVdGlscy53KG5leHRUaW1lU3RhbXAsIHRoaXMpOwogICAgfTsKICAgIF9wcm90by5zdWJ0cmFjdCA9IGZ1bmN0aW9uIHN1YnRyYWN0KG51bWJlciwgc3RyaW5nKSB7CiAgICAgIHJldHVybiB0aGlzLmFkZChudW1iZXIgKiAtMSwgc3RyaW5nKTsKICAgIH07CiAgICBfcHJvdG8uZm9ybWF0ID0gZnVuY3Rpb24gZm9ybWF0KGZvcm1hdFN0cikgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKICAgICAgdmFyIGxvY2FsZSA9IHRoaXMuJGxvY2FsZSgpOwogICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSByZXR1cm4gbG9jYWxlLmludmFsaWREYXRlIHx8IElOVkFMSURfREFURV9TVFJJTkc7CiAgICAgIHZhciBzdHIgPSBmb3JtYXRTdHIgfHwgRk9STUFUX0RFRkFVTFQ7CiAgICAgIHZhciB6b25lU3RyID0gVXRpbHMueih0aGlzKTsKICAgICAgdmFyICRIID0gdGhpcy4kSCwgJG0gPSB0aGlzLiRtLCAkTSA9IHRoaXMuJE07CiAgICAgIHZhciB3ZWVrZGF5cyA9IGxvY2FsZS53ZWVrZGF5cywgbW9udGhzID0gbG9jYWxlLm1vbnRocywgbWVyaWRpZW0gPSBsb2NhbGUubWVyaWRpZW07CiAgICAgIHZhciBnZXRTaG9ydCA9IGZ1bmN0aW9uIGdldFNob3J0MihhcnIsIGluZGV4LCBmdWxsLCBsZW5ndGgpIHsKICAgICAgICByZXR1cm4gYXJyICYmIChhcnJbaW5kZXhdIHx8IGFycihfdGhpczMsIHN0cikpIHx8IGZ1bGxbaW5kZXhdLnNsaWNlKDAsIGxlbmd0aCk7CiAgICAgIH07CiAgICAgIHZhciBnZXQkSCA9IGZ1bmN0aW9uIGdldCRIMihudW0pIHsKICAgICAgICByZXR1cm4gVXRpbHMucygkSCAlIDEyIHx8IDEyLCBudW0sICIwIik7CiAgICAgIH07CiAgICAgIHZhciBtZXJpZGllbUZ1bmMgPSBtZXJpZGllbSB8fCBmdW5jdGlvbihob3VyLCBtaW51dGUsIGlzTG93ZXJjYXNlKSB7CiAgICAgICAgdmFyIG0yID0gaG91ciA8IDEyID8gIkFNIiA6ICJQTSI7CiAgICAgICAgcmV0dXJuIGlzTG93ZXJjYXNlID8gbTIudG9Mb3dlckNhc2UoKSA6IG0yOwogICAgICB9OwogICAgICB2YXIgbWF0Y2hlcyA9IGZ1bmN0aW9uIG1hdGNoZXMyKG1hdGNoKSB7CiAgICAgICAgc3dpdGNoIChtYXRjaCkgewogICAgICAgICAgY2FzZSAiWVkiOgogICAgICAgICAgICByZXR1cm4gU3RyaW5nKF90aGlzMy4keSkuc2xpY2UoLTIpOwogICAgICAgICAgY2FzZSAiWVlZWSI6CiAgICAgICAgICAgIHJldHVybiBVdGlscy5zKF90aGlzMy4keSwgNCwgIjAiKTsKICAgICAgICAgIGNhc2UgIk0iOgogICAgICAgICAgICByZXR1cm4gJE0gKyAxOwogICAgICAgICAgY2FzZSAiTU0iOgogICAgICAgICAgICByZXR1cm4gVXRpbHMucygkTSArIDEsIDIsICIwIik7CiAgICAgICAgICBjYXNlICJNTU0iOgogICAgICAgICAgICByZXR1cm4gZ2V0U2hvcnQobG9jYWxlLm1vbnRoc1Nob3J0LCAkTSwgbW9udGhzLCAzKTsKICAgICAgICAgIGNhc2UgIk1NTU0iOgogICAgICAgICAgICByZXR1cm4gZ2V0U2hvcnQobW9udGhzLCAkTSk7CiAgICAgICAgICBjYXNlICJEIjoKICAgICAgICAgICAgcmV0dXJuIF90aGlzMy4kRDsKICAgICAgICAgIGNhc2UgIkREIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoX3RoaXMzLiRELCAyLCAiMCIpOwogICAgICAgICAgY2FzZSAiZCI6CiAgICAgICAgICAgIHJldHVybiBTdHJpbmcoX3RoaXMzLiRXKTsKICAgICAgICAgIGNhc2UgImRkIjoKICAgICAgICAgICAgcmV0dXJuIGdldFNob3J0KGxvY2FsZS53ZWVrZGF5c01pbiwgX3RoaXMzLiRXLCB3ZWVrZGF5cywgMik7CiAgICAgICAgICBjYXNlICJkZGQiOgogICAgICAgICAgICByZXR1cm4gZ2V0U2hvcnQobG9jYWxlLndlZWtkYXlzU2hvcnQsIF90aGlzMy4kVywgd2Vla2RheXMsIDMpOwogICAgICAgICAgY2FzZSAiZGRkZCI6CiAgICAgICAgICAgIHJldHVybiB3ZWVrZGF5c1tfdGhpczMuJFddOwogICAgICAgICAgY2FzZSAiSCI6CiAgICAgICAgICAgIHJldHVybiBTdHJpbmcoJEgpOwogICAgICAgICAgY2FzZSAiSEgiOgogICAgICAgICAgICByZXR1cm4gVXRpbHMucygkSCwgMiwgIjAiKTsKICAgICAgICAgIGNhc2UgImgiOgogICAgICAgICAgICByZXR1cm4gZ2V0JEgoMSk7CiAgICAgICAgICBjYXNlICJoaCI6CiAgICAgICAgICAgIHJldHVybiBnZXQkSCgyKTsKICAgICAgICAgIGNhc2UgImEiOgogICAgICAgICAgICByZXR1cm4gbWVyaWRpZW1GdW5jKCRILCAkbSwgdHJ1ZSk7CiAgICAgICAgICBjYXNlICJBIjoKICAgICAgICAgICAgcmV0dXJuIG1lcmlkaWVtRnVuYygkSCwgJG0sIGZhbHNlKTsKICAgICAgICAgIGNhc2UgIm0iOgogICAgICAgICAgICByZXR1cm4gU3RyaW5nKCRtKTsKICAgICAgICAgIGNhc2UgIm1tIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoJG0sIDIsICIwIik7CiAgICAgICAgICBjYXNlICJzIjoKICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhfdGhpczMuJHMpOwogICAgICAgICAgY2FzZSAic3MiOgogICAgICAgICAgICByZXR1cm4gVXRpbHMucyhfdGhpczMuJHMsIDIsICIwIik7CiAgICAgICAgICBjYXNlICJTU1MiOgogICAgICAgICAgICByZXR1cm4gVXRpbHMucyhfdGhpczMuJG1zLCAzLCAiMCIpOwogICAgICAgICAgY2FzZSAiWiI6CiAgICAgICAgICAgIHJldHVybiB6b25lU3RyOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfTsKICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKFJFR0VYX0ZPUk1BVCwgZnVuY3Rpb24obWF0Y2gsICQxKSB7CiAgICAgICAgcmV0dXJuICQxIHx8IG1hdGNoZXMobWF0Y2gpIHx8IHpvbmVTdHIucmVwbGFjZSgiOiIsICIiKTsKICAgICAgfSk7CiAgICB9OwogICAgX3Byb3RvLnV0Y09mZnNldCA9IGZ1bmN0aW9uIHV0Y09mZnNldCgpIHsKICAgICAgcmV0dXJuIC1NYXRoLnJvdW5kKHRoaXMuJGQuZ2V0VGltZXpvbmVPZmZzZXQoKSAvIDE1KSAqIDE1OwogICAgfTsKICAgIF9wcm90by5kaWZmID0gZnVuY3Rpb24gZGlmZihpbnB1dCwgdW5pdHMsIF9mbG9hdCkgewogICAgICB2YXIgX3RoaXM0ID0gdGhpczsKICAgICAgdmFyIHVuaXQgPSBVdGlscy5wKHVuaXRzKTsKICAgICAgdmFyIHRoYXQgPSBkYXlqcyhpbnB1dCk7CiAgICAgIHZhciB6b25lRGVsdGEgPSAodGhhdC51dGNPZmZzZXQoKSAtIHRoaXMudXRjT2Zmc2V0KCkpICogTUlMTElTRUNPTkRTX0FfTUlOVVRFOwogICAgICB2YXIgZGlmZjIgPSB0aGlzIC0gdGhhdDsKICAgICAgdmFyIGdldE1vbnRoID0gZnVuY3Rpb24gZ2V0TW9udGgyKCkgewogICAgICAgIHJldHVybiBVdGlscy5tKF90aGlzNCwgdGhhdCk7CiAgICAgIH07CiAgICAgIHZhciByZXN1bHQ7CiAgICAgIHN3aXRjaCAodW5pdCkgewogICAgICAgIGNhc2UgWToKICAgICAgICAgIHJlc3VsdCA9IGdldE1vbnRoKCkgLyAxMjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgTToKICAgICAgICAgIHJlc3VsdCA9IGdldE1vbnRoKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFE6CiAgICAgICAgICByZXN1bHQgPSBnZXRNb250aCgpIC8gMzsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgVzoKICAgICAgICAgIHJlc3VsdCA9IChkaWZmMiAtIHpvbmVEZWx0YSkgLyBNSUxMSVNFQ09ORFNfQV9XRUVLOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBEOgogICAgICAgICAgcmVzdWx0ID0gKGRpZmYyIC0gem9uZURlbHRhKSAvIE1JTExJU0VDT05EU19BX0RBWTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgSDoKICAgICAgICAgIHJlc3VsdCA9IGRpZmYyIC8gTUlMTElTRUNPTkRTX0FfSE9VUjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgTUlOOgogICAgICAgICAgcmVzdWx0ID0gZGlmZjIgLyBNSUxMSVNFQ09ORFNfQV9NSU5VVEU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFM6CiAgICAgICAgICByZXN1bHQgPSBkaWZmMiAvIE1JTExJU0VDT05EU19BX1NFQ09ORDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXN1bHQgPSBkaWZmMjsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHJldHVybiBfZmxvYXQgPyByZXN1bHQgOiBVdGlscy5hKHJlc3VsdCk7CiAgICB9OwogICAgX3Byb3RvLmRheXNJbk1vbnRoID0gZnVuY3Rpb24gZGF5c0luTW9udGgoKSB7CiAgICAgIHJldHVybiB0aGlzLmVuZE9mKE0pLiREOwogICAgfTsKICAgIF9wcm90by4kbG9jYWxlID0gZnVuY3Rpb24gJGxvY2FsZSgpIHsKICAgICAgcmV0dXJuIExzW3RoaXMuJExdOwogICAgfTsKICAgIF9wcm90by5sb2NhbGUgPSBmdW5jdGlvbiBsb2NhbGUocHJlc2V0LCBvYmplY3QpIHsKICAgICAgaWYgKCFwcmVzZXQpIHJldHVybiB0aGlzLiRMOwogICAgICB2YXIgdGhhdCA9IHRoaXMuY2xvbmUoKTsKICAgICAgdmFyIG5leHRMb2NhbGVOYW1lID0gcGFyc2VMb2NhbGUocHJlc2V0LCBvYmplY3QsIHRydWUpOwogICAgICBpZiAobmV4dExvY2FsZU5hbWUpIHRoYXQuJEwgPSBuZXh0TG9jYWxlTmFtZTsKICAgICAgcmV0dXJuIHRoYXQ7CiAgICB9OwogICAgX3Byb3RvLmNsb25lID0gZnVuY3Rpb24gY2xvbmUoKSB7CiAgICAgIHJldHVybiBVdGlscy53KHRoaXMuJGQsIHRoaXMpOwogICAgfTsKICAgIF9wcm90by50b0RhdGUgPSBmdW5jdGlvbiB0b0RhdGUoKSB7CiAgICAgIHJldHVybiBuZXcgRGF0ZSh0aGlzLnZhbHVlT2YoKSk7CiAgICB9OwogICAgX3Byb3RvLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTigpIHsKICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZCgpID8gdGhpcy50b0lTT1N0cmluZygpIDogbnVsbDsKICAgIH07CiAgICBfcHJvdG8udG9JU09TdHJpbmcgPSBmdW5jdGlvbiB0b0lTT1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMuJGQudG9JU09TdHJpbmcoKTsKICAgIH07CiAgICBfcHJvdG8udG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMuJGQudG9VVENTdHJpbmcoKTsKICAgIH07CiAgICByZXR1cm4gRGF5anMyOwogIH0oKTsKICB2YXIgcHJvdG8gPSBEYXlqcy5wcm90b3R5cGU7CiAgZGF5anMucHJvdG90eXBlID0gcHJvdG87CiAgW1siJG1zIiwgTVNdLCBbIiRzIiwgU10sIFsiJG0iLCBNSU5dLCBbIiRIIiwgSF0sIFsiJFciLCBEXSwgWyIkTSIsIE1dLCBbIiR5IiwgWV0sIFsiJEQiLCBEQVRFXV0uZm9yRWFjaChmdW5jdGlvbihnKSB7CiAgICBwcm90b1tnWzFdXSA9IGZ1bmN0aW9uKGlucHV0KSB7CiAgICAgIHJldHVybiB0aGlzLiRnKGlucHV0LCBnWzBdLCBnWzFdKTsKICAgIH07CiAgfSk7CiAgZGF5anMuZXh0ZW5kID0gZnVuY3Rpb24ocGx1Z2luLCBvcHRpb24pIHsKICAgIGlmICghcGx1Z2luLiRpKSB7CiAgICAgIHBsdWdpbihvcHRpb24sIERheWpzLCBkYXlqcyk7CiAgICAgIHBsdWdpbi4kaSA9IHRydWU7CiAgICB9CiAgICByZXR1cm4gZGF5anM7CiAgfTsKICBkYXlqcy5sb2NhbGUgPSBwYXJzZUxvY2FsZTsKICBkYXlqcy5pc0RheWpzID0gaXNEYXlqczsKICBkYXlqcy51bml4ID0gZnVuY3Rpb24odGltZXN0YW1wKSB7CiAgICByZXR1cm4gZGF5anModGltZXN0YW1wICogMWUzKTsKICB9OwogIGRheWpzLmVuID0gTHNbTF07CiAgZGF5anMuTHMgPSBMczsKICBkYXlqcy5wID0ge307CiAgdmFyIGFkdmFuY2VkRm9ybWF0ID0gZnVuY3Rpb24obywgYzIpIHsKICAgIHZhciBwcm90bzIgPSBjMi5wcm90b3R5cGU7CiAgICB2YXIgb2xkRm9ybWF0ID0gcHJvdG8yLmZvcm1hdDsKICAgIHByb3RvMi5mb3JtYXQgPSBmdW5jdGlvbihmb3JtYXRTdHIpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKICAgICAgdmFyIGxvY2FsZSA9IHRoaXMuJGxvY2FsZSgpOwogICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7CiAgICAgICAgcmV0dXJuIG9sZEZvcm1hdC5iaW5kKHRoaXMpKGZvcm1hdFN0cik7CiAgICAgIH0KICAgICAgdmFyIHV0aWxzID0gdGhpcy4kdXRpbHMoKTsKICAgICAgdmFyIHN0ciA9IGZvcm1hdFN0ciB8fCBGT1JNQVRfREVGQVVMVDsKICAgICAgdmFyIHJlc3VsdCA9IHN0ci5yZXBsYWNlKC9cWyhbXlxdXSspXXxRfHdvfHd3fHd8V1d8V3x6enp8enxnZ2dnfEdHR0d8RG98WHx4fGt7MSwyfXxTL2csIGZ1bmN0aW9uKG1hdGNoKSB7CiAgICAgICAgc3dpdGNoIChtYXRjaCkgewogICAgICAgICAgY2FzZSAiUSI6CiAgICAgICAgICAgIHJldHVybiBNYXRoLmNlaWwoKF90aGlzLiRNICsgMSkgLyAzKTsKICAgICAgICAgIGNhc2UgIkRvIjoKICAgICAgICAgICAgcmV0dXJuIGxvY2FsZS5vcmRpbmFsKF90aGlzLiREKTsKICAgICAgICAgIGNhc2UgImdnZ2ciOgogICAgICAgICAgICByZXR1cm4gX3RoaXMud2Vla1llYXIoKTsKICAgICAgICAgIGNhc2UgIkdHR0ciOgogICAgICAgICAgICByZXR1cm4gX3RoaXMuaXNvV2Vla1llYXIoKTsKICAgICAgICAgIGNhc2UgIndvIjoKICAgICAgICAgICAgcmV0dXJuIGxvY2FsZS5vcmRpbmFsKF90aGlzLndlZWsoKSwgIlciKTsKICAgICAgICAgIGNhc2UgInciOgogICAgICAgICAgY2FzZSAid3ciOgogICAgICAgICAgICByZXR1cm4gdXRpbHMucyhfdGhpcy53ZWVrKCksIG1hdGNoID09PSAidyIgPyAxIDogMiwgIjAiKTsKICAgICAgICAgIGNhc2UgIlciOgogICAgICAgICAgY2FzZSAiV1ciOgogICAgICAgICAgICByZXR1cm4gdXRpbHMucyhfdGhpcy5pc29XZWVrKCksIG1hdGNoID09PSAiVyIgPyAxIDogMiwgIjAiKTsKICAgICAgICAgIGNhc2UgImsiOgogICAgICAgICAgY2FzZSAia2siOgogICAgICAgICAgICByZXR1cm4gdXRpbHMucyhTdHJpbmcoX3RoaXMuJEggPT09IDAgPyAyNCA6IF90aGlzLiRIKSwgbWF0Y2ggPT09ICJrIiA/IDEgOiAyLCAiMCIpOwogICAgICAgICAgY2FzZSAiWCI6CiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKF90aGlzLiRkLmdldFRpbWUoKSAvIDFlMyk7CiAgICAgICAgICBjYXNlICJ4IjoKICAgICAgICAgICAgcmV0dXJuIF90aGlzLiRkLmdldFRpbWUoKTsKICAgICAgICAgIGNhc2UgInoiOgogICAgICAgICAgICByZXR1cm4gIlsiICsgX3RoaXMub2Zmc2V0TmFtZSgpICsgIl0iOwogICAgICAgICAgY2FzZSAienp6IjoKICAgICAgICAgICAgcmV0dXJuICJbIiArIF90aGlzLm9mZnNldE5hbWUoImxvbmciKSArICJdIjsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHJldHVybiBtYXRjaDsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gb2xkRm9ybWF0LmJpbmQodGhpcykocmVzdWx0KTsKICAgIH07CiAgfTsKICB2YXIgaXNvV2Vla1ByZXR0eVVuaXQgPSAiaXNvd2VlayI7CiAgdmFyIGlzb1dlZWsgPSBmdW5jdGlvbihvLCBjMiwgZCkgewogICAgdmFyIGdldFllYXJGaXJzdFRodXJzZGF5ID0gZnVuY3Rpb24gZ2V0WWVhckZpcnN0VGh1cnNkYXkyKHllYXIsIGlzVXRjKSB7CiAgICAgIHZhciB5ZWFyRmlyc3REYXkgPSAoaXNVdGMgPyBkLnV0YyA6IGQpKCkueWVhcih5ZWFyKS5zdGFydE9mKFkpOwogICAgICB2YXIgYWRkRGlmZkRheXMgPSA0IC0geWVhckZpcnN0RGF5Lmlzb1dlZWtkYXkoKTsKICAgICAgaWYgKHllYXJGaXJzdERheS5pc29XZWVrZGF5KCkgPiA0KSB7CiAgICAgICAgYWRkRGlmZkRheXMgKz0gNzsKICAgICAgfQogICAgICByZXR1cm4geWVhckZpcnN0RGF5LmFkZChhZGREaWZmRGF5cywgRCk7CiAgICB9OwogICAgdmFyIGdldEN1cnJlbnRXZWVrVGh1cnNkYXkgPSBmdW5jdGlvbiBnZXRDdXJyZW50V2Vla1RodXJzZGF5MihpbnMpIHsKICAgICAgcmV0dXJuIGlucy5hZGQoNCAtIGlucy5pc29XZWVrZGF5KCksIEQpOwogICAgfTsKICAgIHZhciBwcm90bzIgPSBjMi5wcm90b3R5cGU7CiAgICBwcm90bzIuaXNvV2Vla1llYXIgPSBmdW5jdGlvbigpIHsKICAgICAgdmFyIG5vd1dlZWtUaHVyc2RheSA9IGdldEN1cnJlbnRXZWVrVGh1cnNkYXkodGhpcyk7CiAgICAgIHJldHVybiBub3dXZWVrVGh1cnNkYXkueWVhcigpOwogICAgfTsKICAgIHByb3RvMi5pc29XZWVrID0gZnVuY3Rpb24od2VlaykgewogICAgICBpZiAoIXRoaXMuJHV0aWxzKCkudSh3ZWVrKSkgewogICAgICAgIHJldHVybiB0aGlzLmFkZCgod2VlayAtIHRoaXMuaXNvV2VlaygpKSAqIDcsIEQpOwogICAgICB9CiAgICAgIHZhciBub3dXZWVrVGh1cnNkYXkgPSBnZXRDdXJyZW50V2Vla1RodXJzZGF5KHRoaXMpOwogICAgICB2YXIgZGlmZldlZWtUaHVyc2RheSA9IGdldFllYXJGaXJzdFRodXJzZGF5KHRoaXMuaXNvV2Vla1llYXIoKSwgdGhpcy4kdSk7CiAgICAgIHJldHVybiBub3dXZWVrVGh1cnNkYXkuZGlmZihkaWZmV2Vla1RodXJzZGF5LCBXKSArIDE7CiAgICB9OwogICAgcHJvdG8yLmlzb1dlZWtkYXkgPSBmdW5jdGlvbih3ZWVrKSB7CiAgICAgIGlmICghdGhpcy4kdXRpbHMoKS51KHdlZWspKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZGF5KHRoaXMuZGF5KCkgJSA3ID8gd2VlayA6IHdlZWsgLSA3KTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5kYXkoKSB8fCA3OwogICAgfTsKICAgIHZhciBvbGRTdGFydE9mID0gcHJvdG8yLnN0YXJ0T2Y7CiAgICBwcm90bzIuc3RhcnRPZiA9IGZ1bmN0aW9uKHVuaXRzLCBzdGFydE9mKSB7CiAgICAgIHZhciB1dGlscyA9IHRoaXMuJHV0aWxzKCk7CiAgICAgIHZhciBpc1N0YXJ0T2YgPSAhdXRpbHMudShzdGFydE9mKSA/IHN0YXJ0T2YgOiB0cnVlOwogICAgICB2YXIgdW5pdCA9IHV0aWxzLnAodW5pdHMpOwogICAgICBpZiAodW5pdCA9PT0gaXNvV2Vla1ByZXR0eVVuaXQpIHsKICAgICAgICByZXR1cm4gaXNTdGFydE9mID8gdGhpcy5kYXRlKHRoaXMuZGF0ZSgpIC0gKHRoaXMuaXNvV2Vla2RheSgpIC0gMSkpLnN0YXJ0T2YoImRheSIpIDogdGhpcy5kYXRlKHRoaXMuZGF0ZSgpIC0gMSAtICh0aGlzLmlzb1dlZWtkYXkoKSAtIDEpICsgNykuZW5kT2YoImRheSIpOwogICAgICB9CiAgICAgIHJldHVybiBvbGRTdGFydE9mLmJpbmQodGhpcykodW5pdHMsIHN0YXJ0T2YpOwogICAgfTsKICB9OwogIGRheWpzLmV4dGVuZChpc29XZWVrKTsKICBkYXlqcy5leHRlbmQoYWR2YW5jZWRGb3JtYXQpOwogIGNvbnN0IEZPUk1BVF9JU09fV0VFS19ZRUFSX1dFRUsgPSAiR0dHRy1bV11XVyI7CiAgY29uc3QgX1RlbXBvcmFsQ2FjaGUgPSBjbGFzcyBfVGVtcG9yYWxDYWNoZSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgdGhpcy55ZWFyTW9udGhEYXlDYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgIHRoaXMueWVhcldlZWtDYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgIHRoaXMueWVhck1vbnRoQ2FjaGUgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLnllYXJDYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICB9CiAgICBnZXRZZWFyTW9udGhEYXkoczIpIHsKICAgICAgaWYgKCF0aGlzLnllYXJNb250aERheUNhY2hlLmhhcyhzMikpIHsKICAgICAgICB0aGlzLnllYXJNb250aERheUNhY2hlLnNldChzMiwgWWVhck1vbnRoRGF5Q2xhc3MucGFyc2UoczIsIHRoaXMpKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy55ZWFyTW9udGhEYXlDYWNoZS5nZXQoczIpOwogICAgfQogICAgZ2V0WWVhck1vbnRoKHMyKSB7CiAgICAgIGlmICghdGhpcy55ZWFyTW9udGhDYWNoZS5oYXMoczIpKSB7CiAgICAgICAgdGhpcy55ZWFyTW9udGhDYWNoZS5zZXQoczIsIFllYXJNb250aENsYXNzLnBhcnNlKHMyLCB0aGlzKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMueWVhck1vbnRoQ2FjaGUuZ2V0KHMyKTsKICAgIH0KICAgIGdldFllYXJXZWVrKHMyKSB7CiAgICAgIGlmICghdGhpcy55ZWFyV2Vla0NhY2hlLmhhcyhzMikpIHsKICAgICAgICB0aGlzLnllYXJXZWVrQ2FjaGUuc2V0KHMyLCBZZWFyV2Vla0NsYXNzLnBhcnNlKHMyLCB0aGlzKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMueWVhcldlZWtDYWNoZS5nZXQoczIpOwogICAgfQogICAgZ2V0WWVhcihzMikgewogICAgICBpZiAoIXRoaXMueWVhckNhY2hlLmhhcyhzMikpIHsKICAgICAgICB0aGlzLnllYXJDYWNoZS5zZXQoczIsIFllYXJDbGFzcy5wYXJzZShzMiwgdGhpcykpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnllYXJDYWNoZS5nZXQoczIpOwogICAgfQogICAgc3RhdGljIGdldEluc3RhbmNlKCkgewogICAgICByZXR1cm4gdGhpcy5pbnN0YW5jZTsKICAgIH0KICB9OwogIF9UZW1wb3JhbENhY2hlLmluc3RhbmNlID0gbmV3IF9UZW1wb3JhbENhY2hlKCk7CiAgbGV0IFRlbXBvcmFsQ2FjaGUgPSBfVGVtcG9yYWxDYWNoZTsKICBjbGFzcyBZZWFyTW9udGhEYXlDbGFzcyB7CiAgICBjb25zdHJ1Y3Rvcih5ZWFyTnVtYmVyLCBtb250aE51bWJlciwgZGF5TnVtYmVyLCBjYWNoZSkgewogICAgICB0aGlzLnllYXJOdW1iZXIgPSB5ZWFyTnVtYmVyOwogICAgICB0aGlzLm1vbnRoTnVtYmVyID0gbW9udGhOdW1iZXI7CiAgICAgIHRoaXMuZGF5TnVtYmVyID0gZGF5TnVtYmVyOwogICAgICB0aGlzLmNhY2hlID0gY2FjaGU7CiAgICAgIHRoaXMudHlwZSA9ICJZZWFyTW9udGhEYXkiOwogICAgICB0aGlzLmRhdGUgPSBuZXcgRGF0ZSh0aGlzLnllYXJOdW1iZXIsIHRoaXMubW9udGhOdW1iZXIgLSAxLCB0aGlzLmRheU51bWJlcik7CiAgICAgIHRoaXMuZGF5anMgPSBkYXlqcyh0aGlzLmRhdGUpOwogICAgICB0aGlzLmRhdGVTdHJpbmcgPSB0aGlzLnRvU3RyaW5nKCk7CiAgICB9CiAgICBnZXQgdGV4dCgpIHsKICAgICAgcmV0dXJuIHRoaXMuZGF5anMuZm9ybWF0KCJZWVlZLU1NLUREIik7CiAgICB9CiAgICB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMudGV4dDsKICAgIH0KICAgIGVuZ2xpc2hOYW1lKCkgewogICAgICByZXR1cm4gdGhpcy5kYXlqcy5mb3JtYXQoImRkZGQsIE1NTU0gRCwgWVlZWSIpOwogICAgfQogICAgZ2V0IGZpcnN0RGF5KCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH0KICAgIGdldCBsYXN0RGF5KCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH0KICAgIGdldCB5ZWFyKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyKGAke3RoaXMueWVhck51bWJlcn1gKTsKICAgIH0KICAgIGdldCBtb250aCgpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoKHRoaXMuZGF5anMuZm9ybWF0KCJZWVlZLU1NIikpOwogICAgfQogICAgZ2V0IHdlZWsoKSB7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJXZWVrKHRoaXMuZGF5anMuZm9ybWF0KEZPUk1BVF9JU09fV0VFS19ZRUFSX1dFRUspKTsKICAgIH0KICAgIGFkZERheXMoZGF5cykgewogICAgICBjb25zdCBkYXRlID0gdGhpcy5kYXlqcy5hZGQoZGF5cywgImRheSIpOwogICAgICBjb25zdCBzMiA9IGRhdGUuZm9ybWF0KCJZWVlZLU1NLUREIik7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aERheShzMik7CiAgICB9CiAgICBtaW51cyhvdGhlcikgewogICAgICByZXR1cm4gdGhpcy5kYXlqcy5kaWZmKG90aGVyLmRheWpzLCAiZGF5Iik7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UoczIsIGNhY2hlKSB7CiAgICAgIGNvbnN0IFt5ZWFyLCBtb250aCwgZGF5XSA9IHMyLnNwbGl0KCItIikubWFwKChzMjIpID0+IHBhcnNlSW50KHMyMiwgMTApKTsKICAgICAgcmV0dXJuIG5ldyBZZWFyTW9udGhEYXlDbGFzcyh5ZWFyLCBtb250aCwgZGF5LCBjYWNoZSk7CiAgICB9CiAgfQogIGNsYXNzIFllYXJXZWVrQ2xhc3MgewogICAgY29uc3RydWN0b3IoaXNvWWVhck51bWJlciwgaXNvV2Vla051bWJlciwgY2FjaGUpIHsKICAgICAgdGhpcy5pc29ZZWFyTnVtYmVyID0gaXNvWWVhck51bWJlcjsKICAgICAgdGhpcy5pc29XZWVrTnVtYmVyID0gaXNvV2Vla051bWJlcjsKICAgICAgdGhpcy5jYWNoZSA9IGNhY2hlOwogICAgICB0aGlzLnR5cGUgPSAiWWVhcldlZWsiOwogICAgICB0aGlzLmRhdGVTdHJpbmcgPSB0aGlzLnRvU3RyaW5nKCk7CiAgICB9CiAgICBnZXQgdGV4dCgpIHsKICAgICAgcmV0dXJuIHRoaXMuZmlyc3REYXkuZGF5anMuZm9ybWF0KEZPUk1BVF9JU09fV0VFS19ZRUFSX1dFRUspOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLnRleHQ7CiAgICB9CiAgICBlbmdsaXNoTmFtZSgpIHsKICAgICAgcmV0dXJuIGBXZWVrICR7dGhpcy5pc29XZWVrTnVtYmVyfSwgJHt0aGlzLmlzb1llYXJOdW1iZXJ9YDsKICAgIH0KICAgIGdldCBmaXJzdERheSgpIHsKICAgICAgY29uc3QgZmlyc3REYXkgPSBkYXlqcygpLnllYXIodGhpcy5pc29ZZWFyTnVtYmVyKS5tb250aCgxKS5kYXRlKDQpLmlzb1dlZWsodGhpcy5pc29XZWVrTnVtYmVyKS5zdGFydE9mKCJpc29XZWVrIik7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aERheShmaXJzdERheS5mb3JtYXQoIllZWVktTU0tREQiKSk7CiAgICB9CiAgICBnZXQgbGFzdERheSgpIHsKICAgICAgY29uc3QgZmlyc3REYXkgPSBkYXlqcygpLnllYXIodGhpcy5pc29ZZWFyTnVtYmVyKS5zdGFydE9mKCJ5ZWFyIikuYWRkKCh0aGlzLmlzb1dlZWtOdW1iZXIgLSAxKSAqIDcsICJkYXkiKS5zdGFydE9mKCJ3ZWVrIikuYWRkKDEsICJkYXkiKTsKICAgICAgY29uc3QgbGFzdERheSA9IGZpcnN0RGF5LmFkZCg2LCAiZGF5Iik7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aERheShsYXN0RGF5LmZvcm1hdCgiWVlZWS1NTS1ERCIpKTsKICAgIH0KICAgIGdldCB5ZWFyKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyKGAke3RoaXMuaXNvWWVhck51bWJlcn1gKTsKICAgIH0KICAgIGFkZFdlZWtzKHdlZWtzKSB7CiAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLmZpcnN0RGF5LmRheWpzLmFkZCh3ZWVrcywgIndlZWsiKTsKICAgICAgY29uc3QgczIgPSBkYXRlLmZvcm1hdChGT1JNQVRfSVNPX1dFRUtfWUVBUl9XRUVLKTsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhcldlZWsoczIpOwogICAgfQogICAgbWludXMob3RoZXIpIHsKICAgICAgcmV0dXJuIHRoaXMuZmlyc3REYXkuZGF5anMuZGlmZihvdGhlci5maXJzdERheS5kYXlqcywgIndlZWsiKTsKICAgIH0KICAgIHN0YXRpYyBwYXJzZShzMiwgY2FjaGUpIHsKICAgICAgY29uc3QgW3llYXIsIHdlZWtdID0gczIuc3BsaXQoIi1XIikubWFwKChzMjIpID0+IHBhcnNlSW50KHMyMiwgMTApKTsKICAgICAgcmV0dXJuIG5ldyBZZWFyV2Vla0NsYXNzKHllYXIsIHdlZWssIGNhY2hlKTsKICAgIH0KICB9CiAgY2xhc3MgWWVhck1vbnRoQ2xhc3MgewogICAgY29uc3RydWN0b3IoeWVhck51bWJlciwgbW9udGhOdW1iZXIsIGNhY2hlKSB7CiAgICAgIHRoaXMueWVhck51bWJlciA9IHllYXJOdW1iZXI7CiAgICAgIHRoaXMubW9udGhOdW1iZXIgPSBtb250aE51bWJlcjsKICAgICAgdGhpcy5jYWNoZSA9IGNhY2hlOwogICAgICB0aGlzLnR5cGUgPSAiWWVhck1vbnRoIjsKICAgICAgdGhpcy5kYXRlU3RyaW5nID0gdGhpcy50b1N0cmluZygpOwogICAgfQogICAgZ2V0IHRleHQoKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmZvcm1hdCgiWVlZWS1NTSIpOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLnRleHQ7CiAgICB9CiAgICBlbmdsaXNoTmFtZSgpIHsKICAgICAgcmV0dXJuIGAke21vbnRoTmFtZSh0aGlzLm1vbnRoTnVtYmVyKX0gJHt0aGlzLnllYXJOdW1iZXJ9YDsKICAgIH0KICAgIGdldCBmaXJzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoRGF5KGRheWpzKGAke3RoaXMueWVhck51bWJlcn0tJHt0aGlzLm1vbnRoTnVtYmVyfS0wMWApLmZvcm1hdCgiWVlZWS1NTS1ERCIpKTsKICAgIH0KICAgIGdldCBsYXN0RGF5KCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGhEYXkoCiAgICAgICAgZGF5anMoYCR7dGhpcy55ZWFyTnVtYmVyfS0ke3RoaXMubW9udGhOdW1iZXJ9LTAxYCkuZW5kT2YoIm1vbnRoIikuZm9ybWF0KCJZWVlZLU1NLUREIikKICAgICAgKTsKICAgIH0KICAgIGdldCB5ZWFyKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyKGAke3RoaXMueWVhck51bWJlcn1gKTsKICAgIH0KICAgIGFkZE1vbnRocyhtb250aHMpIHsKICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuZmlyc3REYXkuZGF5anMuYWRkKG1vbnRocywgIm1vbnRoIik7CiAgICAgIGNvbnN0IHMyID0gZGF0ZS5mb3JtYXQoIllZWVktTU0iKTsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoKHMyKTsKICAgIH0KICAgIG1pbnVzKG90aGVyKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmRpZmYob3RoZXIuZmlyc3REYXkuZGF5anMsICJtb250aCIpOwogICAgfQogICAgc3RhdGljIHBhcnNlKHMyLCBjYWNoZSkgewogICAgICBjb25zdCBbeWVhciwgbW9udGhdID0gczIuc3BsaXQoIi0iKS5tYXAoKHMyMikgPT4gcGFyc2VJbnQoczIyLCAxMCkpOwogICAgICByZXR1cm4gbmV3IFllYXJNb250aENsYXNzKHllYXIsIG1vbnRoLCBjYWNoZSk7CiAgICB9CiAgfQogIGNsYXNzIFllYXJDbGFzcyB7CiAgICBjb25zdHJ1Y3Rvcih5ZWFyLCBjYWNoZSkgewogICAgICB0aGlzLnllYXIgPSB5ZWFyOwogICAgICB0aGlzLmNhY2hlID0gY2FjaGU7CiAgICAgIHRoaXMudHlwZSA9ICJZZWFyIjsKICAgICAgdGhpcy5kYXRlU3RyaW5nID0gdGhpcy50b1N0cmluZygpOwogICAgfQogICAgZ2V0IHRleHQoKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmZvcm1hdCgiWVlZWSIpOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLnRleHQ7CiAgICB9CiAgICBlbmdsaXNoTmFtZSgpIHsKICAgICAgcmV0dXJuIHRoaXMueWVhci50b1N0cmluZygpOwogICAgfQogICAgZ2V0IGZpcnN0TW9udGgoKSB7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aChgJHt0aGlzLnllYXJ9LTAxYCk7CiAgICB9CiAgICBnZXQgbGFzdE1vbnRoKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGgoYCR7dGhpcy55ZWFyfS0xMmApOwogICAgfQogICAgZ2V0IGZpcnN0RGF5KCkgewogICAgICByZXR1cm4gdGhpcy5maXJzdE1vbnRoLmZpcnN0RGF5OwogICAgfQogICAgZ2V0IGxhc3REYXkoKSB7CiAgICAgIHJldHVybiB0aGlzLmxhc3RNb250aC5sYXN0RGF5OwogICAgfQogICAgYWRkWWVhcnMoeWVhcnMpIHsKICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuZmlyc3REYXkuZGF5anMuYWRkKHllYXJzLCAieWVhciIpOwogICAgICBjb25zdCBzMiA9IGRhdGUuZm9ybWF0KCJZWVlZIik7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXIoczIpOwogICAgfQogICAgbWludXMob3RoZXIpIHsKICAgICAgcmV0dXJuIHRoaXMuZmlyc3REYXkuZGF5anMuZGlmZihvdGhlci5maXJzdERheS5kYXlqcywgInllYXIiKTsKICAgIH0KICAgIHN0YXRpYyBwYXJzZShzMiwgY2FjaGUpIHsKICAgICAgY29uc3QgeWVhciA9IHBhcnNlSW50KHMyLCAxMCk7CiAgICAgIHJldHVybiBuZXcgWWVhckNsYXNzKHllYXIsIGNhY2hlKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gbW9udGhOYW1lKG1vbnRoKSB7CiAgICByZXR1cm4gZGF5anMoKS5tb250aChtb250aCAtIDEpLmZvcm1hdCgiTU1NTSIpOwogIH0KICBmdW5jdGlvbiB0b1RlbXBvcmFsKHRlbXBvcmFsQ2xhc3MpIHsKICAgIHN3aXRjaCAodGVtcG9yYWxDbGFzcy50eXBlKSB7CiAgICAgIGNhc2UgIlllYXJNb250aERheSI6CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHR5cGU6ICJZZWFyTW9udGhEYXkiLAogICAgICAgICAgeWVhck51bWJlcjogdGVtcG9yYWxDbGFzcy55ZWFyTnVtYmVyLAogICAgICAgICAgbW9udGhOdW1iZXI6IHRlbXBvcmFsQ2xhc3MubW9udGhOdW1iZXIsCiAgICAgICAgICBkYXlOdW1iZXI6IHRlbXBvcmFsQ2xhc3MuZGF5TnVtYmVyLAogICAgICAgICAgZGF0ZVN0cmluZzogdGVtcG9yYWxDbGFzcy5kYXRlU3RyaW5nCiAgICAgICAgfTsKICAgICAgY2FzZSAiWWVhcldlZWsiOgogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiAiWWVhcldlZWsiLAogICAgICAgICAgaXNvWWVhck51bWJlcjogdGVtcG9yYWxDbGFzcy5pc29ZZWFyTnVtYmVyLAogICAgICAgICAgaXNvV2Vla051bWJlcjogdGVtcG9yYWxDbGFzcy5pc29XZWVrTnVtYmVyLAogICAgICAgICAgZGF0ZVN0cmluZzogdGVtcG9yYWxDbGFzcy5kYXRlU3RyaW5nCiAgICAgICAgfTsKICAgICAgY2FzZSAiWWVhck1vbnRoIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogIlllYXJNb250aCIsCiAgICAgICAgICB5ZWFyTnVtYmVyOiB0ZW1wb3JhbENsYXNzLnllYXJOdW1iZXIsCiAgICAgICAgICBtb250aE51bWJlcjogdGVtcG9yYWxDbGFzcy5tb250aE51bWJlciwKICAgICAgICAgIGRhdGVTdHJpbmc6IHRlbXBvcmFsQ2xhc3MuZGF0ZVN0cmluZwogICAgICAgIH07CiAgICAgIGNhc2UgIlllYXIiOgogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiAiWWVhciIsCiAgICAgICAgICB5ZWFyOiB0ZW1wb3JhbENsYXNzLnllYXIsCiAgICAgICAgICBkYXRlU3RyaW5nOiB0ZW1wb3JhbENsYXNzLmRhdGVTdHJpbmcKICAgICAgICB9OwogICAgfQogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZUFsbERheXNJblJhbmdlKHN0YXJ0LCBlbmQpIHsKICAgIGNvbnN0IGRheXMgPSBbXTsKICAgIGNvbnN0IGRheXNJbkJldHdlZW4gPSBlbmQubWludXMoc3RhcnQpOwogICAgZm9yIChsZXQgaTIgPSAwOyBpMiA8PSBkYXlzSW5CZXR3ZWVuOyBpMisrKSB7CiAgICAgIGRheXMucHVzaChzdGFydC5hZGREYXlzKGkyKSk7CiAgICB9CiAgICByZXR1cm4gZGF5czsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVBbGxXZWVrc0luUmFuZ2Uoc3RhcnQsIGVuZCkgewogICAgY29uc3Qgd2Vla3MgPSBbXTsKICAgIGNvbnN0IHdlZWtzSW5CZXR3ZWVuID0gZW5kLm1pbnVzKHN0YXJ0KTsKICAgIGZvciAobGV0IGkyID0gMDsgaTIgPD0gd2Vla3NJbkJldHdlZW47IGkyKyspIHsKICAgICAgd2Vla3MucHVzaChzdGFydC5hZGRXZWVrcyhpMikpOwogICAgfQogICAgcmV0dXJuIHdlZWtzOwogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZUFsbE1vbnRoc0luUmFuZ2Uoc3RhcnQsIGVuZCkgewogICAgY29uc3QgbW9udGhzID0gW107CiAgICBjb25zdCBtb250aHNJbkJldHdlZW4gPSBlbmQubWludXMoc3RhcnQpOwogICAgZm9yIChsZXQgaTIgPSAwOyBpMiA8PSBtb250aHNJbkJldHdlZW47IGkyKyspIHsKICAgICAgbW9udGhzLnB1c2goc3RhcnQuYWRkTW9udGhzKGkyKSk7CiAgICB9CiAgICByZXR1cm4gbW9udGhzOwogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZUFsbFllYXJzSW5SYW5nZShzdGFydCwgZW5kKSB7CiAgICBjb25zdCB5ZWFycyA9IFtdOwogICAgY29uc3QgeWVhcnNJbkJldHdlZW4gPSBlbmQubWludXMoc3RhcnQpOwogICAgZm9yIChsZXQgaTIgPSAwOyBpMiA8PSB5ZWFyc0luQmV0d2VlbjsgaTIrKykgewogICAgICB5ZWFycy5wdXNoKHN0YXJ0LmFkZFllYXJzKGkyKSk7CiAgICB9CiAgICByZXR1cm4geWVhcnM7CiAgfQogIGZ1bmN0aW9uIGdlbmVyYXRlQWxsSW5SYW5nZShzdGFydCwgZW5kKSB7CiAgICBpZiAoc3RhcnQgPT09IG51bGwgfHwgZW5kID09PSBudWxsKSB7CiAgICAgIHJldHVybiBbXTsKICAgIH0KICAgIGlmIChzdGFydCBpbnN0YW5jZW9mIFllYXJNb250aERheUNsYXNzICYmIGVuZCBpbnN0YW5jZW9mIFllYXJNb250aERheUNsYXNzKSB7CiAgICAgIHJldHVybiBnZW5lcmF0ZUFsbERheXNJblJhbmdlKHN0YXJ0LCBlbmQpOwogICAgfQogICAgaWYgKHN0YXJ0IGluc3RhbmNlb2YgWWVhcldlZWtDbGFzcyAmJiBlbmQgaW5zdGFuY2VvZiBZZWFyV2Vla0NsYXNzKSB7CiAgICAgIHJldHVybiBnZW5lcmF0ZUFsbFdlZWtzSW5SYW5nZShzdGFydCwgZW5kKTsKICAgIH0KICAgIGlmIChzdGFydCBpbnN0YW5jZW9mIFllYXJNb250aENsYXNzICYmIGVuZCBpbnN0YW5jZW9mIFllYXJNb250aENsYXNzKSB7CiAgICAgIHJldHVybiBnZW5lcmF0ZUFsbE1vbnRoc0luUmFuZ2Uoc3RhcnQsIGVuZCk7CiAgICB9CiAgICBpZiAoc3RhcnQgaW5zdGFuY2VvZiBZZWFyQ2xhc3MgJiYgZW5kIGluc3RhbmNlb2YgWWVhckNsYXNzKSB7CiAgICAgIHJldHVybiBnZW5lcmF0ZUFsbFllYXJzSW5SYW5nZShzdGFydCwgZW5kKTsKICAgIH0KICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBhcmd1bWVudHM6IHN0YXJ0IGFuZCBlbmQgbXVzdCBiZSBvZiB0aGUgc2FtZSB0eXBlOiAke3N0YXJ0fSwgJHtlbmR9YCk7CiAgfQogIGZ1bmN0aW9uIG1pbnVzVGVtcG9yYWwoYTIsIGIpIHsKICAgIGlmIChhMiBpbnN0YW5jZW9mIFllYXJNb250aERheUNsYXNzICYmIGIgaW5zdGFuY2VvZiBZZWFyTW9udGhEYXlDbGFzcykgewogICAgICByZXR1cm4gYTIubWludXMoYik7CiAgICB9CiAgICBpZiAoYTIgaW5zdGFuY2VvZiBZZWFyV2Vla0NsYXNzICYmIGIgaW5zdGFuY2VvZiBZZWFyV2Vla0NsYXNzKSB7CiAgICAgIHJldHVybiBhMi5taW51cyhiKTsKICAgIH0KICAgIGlmIChhMiBpbnN0YW5jZW9mIFllYXJNb250aENsYXNzICYmIGIgaW5zdGFuY2VvZiBZZWFyTW9udGhDbGFzcykgewogICAgICByZXR1cm4gYTIubWludXMoYik7CiAgICB9CiAgICBpZiAoYTIgaW5zdGFuY2VvZiBZZWFyQ2xhc3MgJiYgYiBpbnN0YW5jZW9mIFllYXJDbGFzcykgewogICAgICByZXR1cm4gYTIubWludXMoYik7CiAgICB9CiAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBjb21wYXJlICR7YTJ9IGFuZCAke2J9YCk7CiAgfQogIGZ1bmN0aW9uIGNvbXBhcmVUZW1wb3JhbChhMiwgYikgewogICAgaWYgKGEyID09PSBudWxsKSB7CiAgICAgIHJldHVybiAxOwogICAgfQogICAgaWYgKGIgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgY29uc3QgZGlmZiA9IG1pbnVzVGVtcG9yYWwoYTIsIGIpOwogICAgaWYgKGRpZmYgPCAwKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGlmIChkaWZmID4gMCkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIHJldHVybiAwOwogIH0KICBmdW5jdGlvbiBnZXRNaW5NYXhUZW1wb3JhbCh2YWx1ZXMpIHsKICAgIGxldCBtaW4gPSBudWxsOwogICAgbGV0IG1heCA9IG51bGw7CiAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIHZhbHVlcykgewogICAgICBpZiAodmFsdWUgPT09IG51bGwpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAobWluID09PSBudWxsIHx8IGNvbXBhcmVUZW1wb3JhbCh2YWx1ZSwgbWluKSA8IDApIHsKICAgICAgICBtaW4gPSB2YWx1ZTsKICAgICAgfQogICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNvbXBhcmVUZW1wb3JhbCh2YWx1ZSwgbWF4KSA+IDApIHsKICAgICAgICBtYXggPSB2YWx1ZTsKICAgICAgfQogICAgfQogICAgaWYgKG1pbiA9PT0gbnVsbCB8fCBtYXggPT09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgbWluOiBudWxsLCBtYXg6IG51bGwgfTsKICAgIH0KICAgIHJldHVybiB7IG1pbiwgbWF4IH07CiAgfQogIGZ1bmN0aW9uIHBhcnNlRGF0ZVN0cmluZ1RvVGVtcG9yYWwoZGF0ZSwgZ3JhbnVsYXJpdHkpIHsKICAgIGNvbnN0IGNhY2hlID0gVGVtcG9yYWxDYWNoZS5nZXRJbnN0YW5jZSgpOwogICAgY29uc3QgZGF5ID0gY2FjaGUuZ2V0WWVhck1vbnRoRGF5KGRhdGUpOwogICAgc3dpdGNoIChncmFudWxhcml0eSkgewogICAgICBjYXNlICJkYXkiOgogICAgICAgIHJldHVybiBkYXk7CiAgICAgIGNhc2UgIndlZWsiOgogICAgICAgIHJldHVybiBkYXkud2VlazsKICAgICAgY2FzZSAibW9udGgiOgogICAgICAgIHJldHVybiBkYXkubW9udGg7CiAgICAgIGNhc2UgInllYXIiOgogICAgICAgIHJldHVybiBkYXkueWVhcjsKICAgIH0KICB9CiAgZnVuY3Rpb24gZGF0ZVJhbmdlQ29tcGFyZShhMiwgYikgewogICAgaWYgKGEyLmRhdGVSYW5nZSA9PT0gbnVsbCkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIGlmIChiLmRhdGVSYW5nZSA9PT0gbnVsbCkgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICByZXR1cm4gY29tcGFyZVRlbXBvcmFsKGEyLmRhdGVSYW5nZSwgYi5kYXRlUmFuZ2UpOwogIH0KICBmdW5jdGlvbiBtYXBEYXRlVG9HcmFudWxhcml0eVJhbmdlKGRhdGEsIGdyYW51bGFyaXR5KSB7CiAgICByZXR1cm4gewogICAgICBkYXRlUmFuZ2U6IGRhdGEuZGF0ZSA9PT0gbnVsbCA/IG51bGwgOiBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKGRhdGEuZGF0ZSwgZ3JhbnVsYXJpdHkpLAogICAgICBjb3VudDogZGF0YS5jb3VudAogICAgfTsKICB9CiAgY29uc3Qgc3Vic3RpdHV0aW9uUmVnZXggPSAvXigoPzxzZWdtZW50PltBLVowLTlfLV0rKSg/PTopOik/KD88dmFsdWVBdFJlZmVyZW5jZT5bQS1aXSk/KD88cG9zaXRpb24+XGQrKSg/PHN1YnN0aXR1dGlvblZhbHVlPltBLVouXSk/JC9pOwogIGNsYXNzIFN1YnN0aXR1dGlvbkNsYXNzIHsKICAgIGNvbnN0cnVjdG9yKHNlZ21lbnQsIHZhbHVlQXRSZWZlcmVuY2UsIHN1YnN0aXR1dGlvblZhbHVlLCBwb3NpdGlvbikgewogICAgICB0aGlzLnNlZ21lbnQgPSBzZWdtZW50OwogICAgICB0aGlzLnZhbHVlQXRSZWZlcmVuY2UgPSB2YWx1ZUF0UmVmZXJlbmNlOwogICAgICB0aGlzLnN1YnN0aXR1dGlvblZhbHVlID0gc3Vic3RpdHV0aW9uVmFsdWU7CiAgICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjsKICAgICAgdGhpcy50eXBlID0gInN1YnN0aXR1dGlvbiI7CiAgICAgIGNvbnN0IHNlZ21lbnRTdHJpbmcgPSB0aGlzLnNlZ21lbnQgPyBgJHt0aGlzLnNlZ21lbnR9OmAgOiAiIjsKICAgICAgY29uc3QgdmFsdWVBdFJlZmVyZW5jZVN0cmluZyA9IHRoaXMudmFsdWVBdFJlZmVyZW5jZSA/IGAke3RoaXMudmFsdWVBdFJlZmVyZW5jZX1gIDogIiI7CiAgICAgIGNvbnN0IHN1YnN0aXR1dGlvblZhbHVlU3RyaW5nID0gdGhpcy5zdWJzdGl0dXRpb25WYWx1ZSA/IGAke3RoaXMuc3Vic3RpdHV0aW9uVmFsdWV9YCA6ICIiOwogICAgICB0aGlzLmNvZGUgPSBgJHtzZWdtZW50U3RyaW5nfSR7dmFsdWVBdFJlZmVyZW5jZVN0cmluZ30ke3RoaXMucG9zaXRpb259JHtzdWJzdGl0dXRpb25WYWx1ZVN0cmluZ31gOwogICAgfQogICAgZXF1YWxzKG90aGVyKSB7CiAgICAgIGlmICghKG90aGVyIGluc3RhbmNlb2YgU3Vic3RpdHV0aW9uQ2xhc3MpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnNlZ21lbnQgPT09IG90aGVyLnNlZ21lbnQgJiYgdGhpcy52YWx1ZUF0UmVmZXJlbmNlID09PSBvdGhlci52YWx1ZUF0UmVmZXJlbmNlICYmIHRoaXMuc3Vic3RpdHV0aW9uVmFsdWUgPT09IG90aGVyLnN1YnN0aXR1dGlvblZhbHVlICYmIHRoaXMucG9zaXRpb24gPT09IG90aGVyLnBvc2l0aW9uOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLmNvZGU7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UobXV0YXRpb25TdHIpIHsKICAgICAgY29uc3QgbWF0Y2ggPSBtdXRhdGlvblN0ci5tYXRjaChzdWJzdGl0dXRpb25SZWdleCk7CiAgICAgIGlmIChtYXRjaCA9PT0gbnVsbCB8fCBtYXRjaC5ncm91cHMgPT09IHZvaWQgMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHJldHVybiBuZXcgU3Vic3RpdHV0aW9uQ2xhc3MoCiAgICAgICAgbWF0Y2guZ3JvdXBzLnNlZ21lbnQsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnZhbHVlQXRSZWZlcmVuY2UsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnN1YnN0aXR1dGlvblZhbHVlLAogICAgICAgIHBhcnNlSW50KG1hdGNoLmdyb3Vwcy5wb3NpdGlvbiwgMTApCiAgICAgICk7CiAgICB9CiAgfQogIGNvbnN0IGRlbGV0aW9uUmVnZXggPSAvXigoPzxzZWdtZW50PltBLVowLTlfLV0rKSg/PTopOik/KD88dmFsdWVBdFJlZmVyZW5jZT5bQS1aXSk/KD88cG9zaXRpb24+XGQrKSgtKSQvaTsKICBjbGFzcyBEZWxldGlvbkNsYXNzIHsKICAgIGNvbnN0cnVjdG9yKHNlZ21lbnQsIHZhbHVlQXRSZWZlcmVuY2UsIHBvc2l0aW9uKSB7CiAgICAgIHRoaXMuc2VnbWVudCA9IHNlZ21lbnQ7CiAgICAgIHRoaXMudmFsdWVBdFJlZmVyZW5jZSA9IHZhbHVlQXRSZWZlcmVuY2U7CiAgICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjsKICAgICAgdGhpcy50eXBlID0gImRlbGV0aW9uIjsKICAgICAgY29uc3Qgc2VnbWVudFN0cmluZyA9IHRoaXMuc2VnbWVudCA/IGAke3RoaXMuc2VnbWVudH06YCA6ICIiOwogICAgICBjb25zdCB2YWx1ZUF0UmVmZXJlbmNlU3RyaW5nID0gdGhpcy52YWx1ZUF0UmVmZXJlbmNlID8gYCR7dGhpcy52YWx1ZUF0UmVmZXJlbmNlfWAgOiAiIjsKICAgICAgdGhpcy5jb2RlID0gYCR7c2VnbWVudFN0cmluZ30ke3ZhbHVlQXRSZWZlcmVuY2VTdHJpbmd9JHt0aGlzLnBvc2l0aW9ufS1gOwogICAgfQogICAgZXF1YWxzKG90aGVyKSB7CiAgICAgIGlmICghKG90aGVyIGluc3RhbmNlb2YgRGVsZXRpb25DbGFzcykpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuc2VnbWVudCA9PT0gb3RoZXIuc2VnbWVudCAmJiB0aGlzLnZhbHVlQXRSZWZlcmVuY2UgPT09IG90aGVyLnZhbHVlQXRSZWZlcmVuY2UgJiYgdGhpcy5wb3NpdGlvbiA9PT0gb3RoZXIucG9zaXRpb247CiAgICB9CiAgICB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMuY29kZTsKICAgIH0KICAgIHN0YXRpYyBwYXJzZShtdXRhdGlvblN0cikgewogICAgICBjb25zdCBtYXRjaCA9IG11dGF0aW9uU3RyLm1hdGNoKGRlbGV0aW9uUmVnZXgpOwogICAgICBpZiAobWF0Y2ggPT09IG51bGwgfHwgbWF0Y2guZ3JvdXBzID09PSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICByZXR1cm4gbmV3IERlbGV0aW9uQ2xhc3MoCiAgICAgICAgbWF0Y2guZ3JvdXBzLnNlZ21lbnQsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnZhbHVlQXRSZWZlcmVuY2UsCiAgICAgICAgcGFyc2VJbnQobWF0Y2guZ3JvdXBzLnBvc2l0aW9uLCAxMCkKICAgICAgKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gdG9TdWJzdGl0dXRpb25PckRlbGV0aW9uKG11dGF0aW9uKSB7CiAgICBzd2l0Y2ggKG11dGF0aW9uLnR5cGUpIHsKICAgICAgY2FzZSAic3Vic3RpdHV0aW9uIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogInN1YnN0aXR1dGlvbiIsCiAgICAgICAgICBjb2RlOiBtdXRhdGlvbi5jb2RlLAogICAgICAgICAgc2VnbWVudDogbXV0YXRpb24uc2VnbWVudCwKICAgICAgICAgIHBvc2l0aW9uOiBtdXRhdGlvbi5wb3NpdGlvbiwKICAgICAgICAgIHZhbHVlQXRSZWZlcmVuY2U6IG11dGF0aW9uLnZhbHVlQXRSZWZlcmVuY2UsCiAgICAgICAgICBzdWJzdGl0dXRpb25WYWx1ZTogbXV0YXRpb24uc3Vic3RpdHV0aW9uVmFsdWUKICAgICAgICB9OwogICAgICBjYXNlICJkZWxldGlvbiI6CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHR5cGU6ICJkZWxldGlvbiIsCiAgICAgICAgICBjb2RlOiBtdXRhdGlvbi5jb2RlLAogICAgICAgICAgc2VnbWVudDogbXV0YXRpb24uc2VnbWVudCwKICAgICAgICAgIHBvc2l0aW9uOiBtdXRhdGlvbi5wb3NpdGlvbiwKICAgICAgICAgIHZhbHVlQXRSZWZlcmVuY2U6IG11dGF0aW9uLnZhbHVlQXRSZWZlcmVuY2UKICAgICAgICB9OwogICAgfQogIH0KICBjbGFzcyBGZXRjaFN1YnN0aXR1dGlvbnNPckRlbGV0aW9uc09wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGZpbHRlciwgc2VxdWVuY2VUeXBlLCBtaW5Qcm9wb3J0aW9uKSB7CiAgICAgIHRoaXMuZmlsdGVyID0gZmlsdGVyOwogICAgICB0aGlzLnNlcXVlbmNlVHlwZSA9IHNlcXVlbmNlVHlwZTsKICAgICAgdGhpcy5taW5Qcm9wb3J0aW9uID0gbWluUHJvcG9ydGlvbjsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzLCBzaWduYWwpIHsKICAgICAgY29uc3QgbXV0YXRpb25zID0gYXdhaXQgdGhpcy5mZXRjaE11dGF0aW9ucyhsYXBpcywgc2lnbmFsKTsKICAgICAgY29uc3QgY29udGVudCA9IG11dGF0aW9ucy5tYXAoCiAgICAgICAgKHsgY291bnQsIHByb3BvcnRpb24sIG11dGF0aW9uRnJvbSwgbXV0YXRpb25UbywgcG9zaXRpb24sIHNlcXVlbmNlTmFtZSB9KSA9PiB7CiAgICAgICAgICBpZiAobXV0YXRpb25UbyA9PT0gIi0iKSB7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgdHlwZTogImRlbGV0aW9uIiwKICAgICAgICAgICAgICBtdXRhdGlvbjogbmV3IERlbGV0aW9uQ2xhc3Moc2VxdWVuY2VOYW1lID8/IHZvaWQgMCwgbXV0YXRpb25Gcm9tLCBwb3NpdGlvbiksCiAgICAgICAgICAgICAgY291bnQsCiAgICAgICAgICAgICAgcHJvcG9ydGlvbgogICAgICAgICAgICB9OwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgdHlwZTogInN1YnN0aXR1dGlvbiIsCiAgICAgICAgICAgIG11dGF0aW9uOiBuZXcgU3Vic3RpdHV0aW9uQ2xhc3Moc2VxdWVuY2VOYW1lID8/IHZvaWQgMCwgbXV0YXRpb25Gcm9tLCBtdXRhdGlvblRvLCBwb3NpdGlvbiksCiAgICAgICAgICAgIGNvdW50LAogICAgICAgICAgICBwcm9wb3J0aW9uCiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgKTsKICAgICAgcmV0dXJuIHsgY29udGVudCB9OwogICAgfQogICAgYXN5bmMgZmV0Y2hNdXRhdGlvbnMobGFwaXMsIHNpZ25hbCkgewogICAgICBjb25zdCBmaWx0ZXIgPSB7CiAgICAgICAgLi4udGhpcy5maWx0ZXIsCiAgICAgICAgbWluUHJvcG9ydGlvbjogdGhpcy5taW5Qcm9wb3J0aW9uCiAgICAgIH07CiAgICAgIHJldHVybiBmZXRjaFN1YnN0aXR1dGlvbnNPckRlbGV0aW9ucyhsYXBpcywgZmlsdGVyLCB0aGlzLnNlcXVlbmNlVHlwZSwgc2lnbmFsKS50aGVuKAogICAgICAgIChyZXNwb25zZSkgPT4gcmVzcG9uc2UuZGF0YQogICAgICApOwogICAgfQogIH0KICB2YXIgbCQxOwogIGwkMSA9IHsgX19lOiBmdW5jdGlvbihuLCBsMiwgdTIsIHQpIHsKICAgIGZvciAodmFyIGkyLCBvLCByMjsgbDIgPSBsMi5fXzsgKSBpZiAoKGkyID0gbDIuX19jKSAmJiAhaTIuX18pIHRyeSB7CiAgICAgIGlmICgobyA9IGkyLmNvbnN0cnVjdG9yKSAmJiBudWxsICE9IG8uZ2V0RGVyaXZlZFN0YXRlRnJvbUVycm9yICYmIChpMi5zZXRTdGF0ZShvLmdldERlcml2ZWRTdGF0ZUZyb21FcnJvcihuKSksIHIyID0gaTIuX19kKSwgbnVsbCAhPSBpMi5jb21wb25lbnREaWRDYXRjaCAmJiAoaTIuY29tcG9uZW50RGlkQ2F0Y2gobiwgdCB8fCB7fSksIHIyID0gaTIuX19kKSwgcjIpIHJldHVybiBpMi5fX0UgPSBpMjsKICAgIH0gY2F0Y2ggKGwzKSB7CiAgICAgIG4gPSBsMzsKICAgIH0KICAgIHRocm93IG47CiAgfSB9LCAiZnVuY3Rpb24iID09IHR5cGVvZiBQcm9taXNlID8gUHJvbWlzZS5wcm90b3R5cGUudGhlbi5iaW5kKFByb21pc2UucmVzb2x2ZSgpKSA6IHNldFRpbWVvdXQ7CiAgdmFyIHIsIHUsIGksIGYgPSBbXSwgYyA9IGwkMSwgZSA9IGMuX19iLCBhID0gYy5fX3IsIHYgPSBjLmRpZmZlZCwgbCA9IGMuX19jLCBtID0gYy51bm1vdW50LCBzID0gYy5fXzsKICBmdW5jdGlvbiBqKCkgewogICAgZm9yICh2YXIgbjsgbiA9IGYuc2hpZnQoKTsgKSBpZiAobi5fX1AgJiYgbi5fX0gpIHRyeSB7CiAgICAgIG4uX19ILl9faC5mb3JFYWNoKHopLCBuLl9fSC5fX2guZm9yRWFjaChCKSwgbi5fX0guX19oID0gW107CiAgICB9IGNhdGNoICh0KSB7CiAgICAgIG4uX19ILl9faCA9IFtdLCBjLl9fZSh0LCBuLl9fdik7CiAgICB9CiAgfQogIGMuX19iID0gZnVuY3Rpb24obikgewogICAgciA9IG51bGwsIGUgJiYgZShuKTsKICB9LCBjLl9fID0gZnVuY3Rpb24obiwgdCkgewogICAgbiAmJiB0Ll9fayAmJiB0Ll9fay5fX20gJiYgKG4uX19tID0gdC5fX2suX19tKSwgcyAmJiBzKG4sIHQpOwogIH0sIGMuX19yID0gZnVuY3Rpb24obikgewogICAgYSAmJiBhKG4pOwogICAgdmFyIGkyID0gKHIgPSBuLl9fYykuX19IOwogICAgaTIgJiYgKHUgPT09IHIgPyAoaTIuX19oID0gW10sIHIuX19oID0gW10sIGkyLl9fLmZvckVhY2goZnVuY3Rpb24objIpIHsKICAgICAgbjIuX19OICYmIChuMi5fXyA9IG4yLl9fTiksIG4yLmkgPSBuMi5fX04gPSB2b2lkIDA7CiAgICB9KSkgOiAoaTIuX19oLmZvckVhY2goeiksIGkyLl9faC5mb3JFYWNoKEIpLCBpMi5fX2ggPSBbXSwgMCkpLCB1ID0gcjsKICB9LCBjLmRpZmZlZCA9IGZ1bmN0aW9uKG4pIHsKICAgIHYgJiYgdihuKTsKICAgIHZhciB0ID0gbi5fX2M7CiAgICB0ICYmIHQuX19IICYmICh0Ll9fSC5fX2gubGVuZ3RoICYmICgxICE9PSBmLnB1c2godCkgJiYgaSA9PT0gYy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHwgKChpID0gYy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUpIHx8IHcpKGopKSwgdC5fX0guX18uZm9yRWFjaChmdW5jdGlvbihuMikgewogICAgICBuMi5pICYmIChuMi5fX0ggPSBuMi5pKSwgbjIuaSA9IHZvaWQgMDsKICAgIH0pKSwgdSA9IHIgPSBudWxsOwogIH0sIGMuX19jID0gZnVuY3Rpb24obiwgdCkgewogICAgdC5zb21lKGZ1bmN0aW9uKG4yKSB7CiAgICAgIHRyeSB7CiAgICAgICAgbjIuX19oLmZvckVhY2goeiksIG4yLl9faCA9IG4yLl9faC5maWx0ZXIoZnVuY3Rpb24objMpIHsKICAgICAgICAgIHJldHVybiAhbjMuX18gfHwgQihuMyk7CiAgICAgICAgfSk7CiAgICAgIH0gY2F0Y2ggKHIyKSB7CiAgICAgICAgdC5zb21lKGZ1bmN0aW9uKG4zKSB7CiAgICAgICAgICBuMy5fX2ggJiYgKG4zLl9faCA9IFtdKTsKICAgICAgICB9KSwgdCA9IFtdLCBjLl9fZShyMiwgbjIuX192KTsKICAgICAgfQogICAgfSksIGwgJiYgbChuLCB0KTsKICB9LCBjLnVubW91bnQgPSBmdW5jdGlvbihuKSB7CiAgICBtICYmIG0obik7CiAgICB2YXIgdCwgcjIgPSBuLl9fYzsKICAgIHIyICYmIHIyLl9fSCAmJiAocjIuX19ILl9fLmZvckVhY2goZnVuY3Rpb24objIpIHsKICAgICAgdHJ5IHsKICAgICAgICB6KG4yKTsKICAgICAgfSBjYXRjaCAobjMpIHsKICAgICAgICB0ID0gbjM7CiAgICAgIH0KICAgIH0pLCByMi5fX0ggPSB2b2lkIDAsIHQgJiYgYy5fX2UodCwgcjIuX192KSk7CiAgfTsKICB2YXIgayA9ICJmdW5jdGlvbiIgPT0gdHlwZW9mIHJlcXVlc3RBbmltYXRpb25GcmFtZTsKICBmdW5jdGlvbiB3KG4pIHsKICAgIHZhciB0LCByMiA9IGZ1bmN0aW9uKCkgewogICAgICBjbGVhclRpbWVvdXQodTIpLCBrICYmIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHQpLCBzZXRUaW1lb3V0KG4pOwogICAgfSwgdTIgPSBzZXRUaW1lb3V0KHIyLCAxMDApOwogICAgayAmJiAodCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZShyMikpOwogIH0KICBmdW5jdGlvbiB6KG4pIHsKICAgIHZhciB0ID0gciwgdTIgPSBuLl9fYzsKICAgICJmdW5jdGlvbiIgPT0gdHlwZW9mIHUyICYmIChuLl9fYyA9IHZvaWQgMCwgdTIoKSksIHIgPSB0OwogIH0KICBmdW5jdGlvbiBCKG4pIHsKICAgIHZhciB0ID0gcjsKICAgIG4uX19jID0gbi5fXygpLCByID0gdDsKICB9CiAgY2xhc3MgVXNlckZhY2luZ0Vycm9yIGV4dGVuZHMgRXJyb3IgewogICAgY29uc3RydWN0b3IoaGVhZGxpbmUsIG1lc3NhZ2UpIHsKICAgICAgc3VwZXIobWVzc2FnZSk7CiAgICAgIHRoaXMuaGVhZGxpbmUgPSBoZWFkbGluZTsKICAgICAgdGhpcy5uYW1lID0gIlVzZXJGYWNpbmdFcnJvciI7CiAgICB9CiAgfQogIGNsYXNzIE1hcDJkQmFzZSB7CiAgICBjb25zdHJ1Y3RvcihzZXJpYWxpemVGaXJzdEF4aXMsIHNlcmlhbGl6ZVNlY29uZEF4aXMsIGluaXRpYWxDb250ZW50KSB7CiAgICAgIHRoaXMuc2VyaWFsaXplRmlyc3RBeGlzID0gc2VyaWFsaXplRmlyc3RBeGlzOwogICAgICB0aGlzLnNlcmlhbGl6ZVNlY29uZEF4aXMgPSBzZXJpYWxpemVTZWNvbmRBeGlzOwogICAgICB0aGlzLmRhdGEgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLmtleXNGaXJzdEF4aXMgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLmtleXNTZWNvbmRBeGlzID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgaWYgKGluaXRpYWxDb250ZW50KSB7CiAgICAgICAgdGhpcy5rZXlzRmlyc3RBeGlzID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5rZXlzRmlyc3RBeGlzKTsKICAgICAgICB0aGlzLmtleXNTZWNvbmRBeGlzID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5rZXlzU2Vjb25kQXhpcyk7CiAgICAgICAgdGhpcy5kYXRhID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5kYXRhKTsKICAgICAgfQogICAgfQogICAgZ2V0KGtleUZpcnN0QXhpcywga2V5U2Vjb25kQXhpcykgewogICAgICB2YXIgX2E7CiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMgPSB0aGlzLnNlcmlhbGl6ZUZpcnN0QXhpcyhrZXlGaXJzdEF4aXMpOwogICAgICBjb25zdCBzZXJpYWxpemVkS2V5U2Vjb25kQXhpcyA9IHRoaXMuc2VyaWFsaXplU2Vjb25kQXhpcyhrZXlTZWNvbmRBeGlzKTsKICAgICAgcmV0dXJuIChfYSA9IHRoaXMuZGF0YS5nZXQoc2VyaWFsaXplZEtleUZpcnN0QXhpcykpID09IG51bGwgPyB2b2lkIDAgOiBfYS5nZXQoc2VyaWFsaXplZEtleVNlY29uZEF4aXMpOwogICAgfQogICAgZ2V0Um93KGtleSwgZmlsbEVtcHR5V2l0aCkgewogICAgICBjb25zdCBzZXJpYWxpemVkS2V5Rmlyc3RBeGlzID0gdGhpcy5zZXJpYWxpemVGaXJzdEF4aXMoa2V5KTsKICAgICAgY29uc3Qgcm93ID0gdGhpcy5kYXRhLmdldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKTsKICAgICAgaWYgKHJvdyA9PT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIFtdOwogICAgICB9CiAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMua2V5c1NlY29uZEF4aXMua2V5cygpKS5tYXAoKGtleTIpID0+IHJvdy5nZXQoa2V5MikgPz8gZmlsbEVtcHR5V2l0aCk7CiAgICB9CiAgICBzZXQoa2V5Rmlyc3RBeGlzLCBrZXlTZWNvbmRBeGlzLCB2YWx1ZSkgewogICAgICBjb25zdCBzZXJpYWxpemVkS2V5Rmlyc3RBeGlzID0gdGhpcy5zZXJpYWxpemVGaXJzdEF4aXMoa2V5Rmlyc3RBeGlzKTsKICAgICAgY29uc3Qgc2VyaWFsaXplZEtleVNlY29uZEF4aXMgPSB0aGlzLnNlcmlhbGl6ZVNlY29uZEF4aXMoa2V5U2Vjb25kQXhpcyk7CiAgICAgIGlmICghdGhpcy5kYXRhLmhhcyhzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKSkgewogICAgICAgIHRoaXMuZGF0YS5zZXQoc2VyaWFsaXplZEtleUZpcnN0QXhpcywgLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKSk7CiAgICAgIH0KICAgICAgdGhpcy5kYXRhLmdldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKS5zZXQoc2VyaWFsaXplZEtleVNlY29uZEF4aXMsIHZhbHVlKTsKICAgICAgdGhpcy5rZXlzRmlyc3RBeGlzLnNldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzLCBrZXlGaXJzdEF4aXMpOwogICAgICB0aGlzLmtleXNTZWNvbmRBeGlzLnNldChzZXJpYWxpemVkS2V5U2Vjb25kQXhpcywga2V5U2Vjb25kQXhpcyk7CiAgICB9CiAgICBkZWxldGVSb3coa2V5KSB7CiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMgPSB0aGlzLnNlcmlhbGl6ZUZpcnN0QXhpcyhrZXkpOwogICAgICB0aGlzLmRhdGEuZGVsZXRlKHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMpOwogICAgICB0aGlzLmtleXNGaXJzdEF4aXMuZGVsZXRlKHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMpOwogICAgfQogICAgZ2V0Rmlyc3RBeGlzS2V5cygpIHsKICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5rZXlzRmlyc3RBeGlzLnZhbHVlcygpKTsKICAgIH0KICAgIGdldFNlY29uZEF4aXNLZXlzKCkgewogICAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLmtleXNTZWNvbmRBeGlzLnZhbHVlcygpKTsKICAgIH0KICAgIGdldEFzQXJyYXkoZmlsbEVtcHR5V2l0aCkgewogICAgICByZXR1cm4gdGhpcy5nZXRGaXJzdEF4aXNLZXlzKCkubWFwKChmaXJzdEF4aXNLZXkpID0+IHsKICAgICAgICByZXR1cm4gdGhpcy5nZXRTZWNvbmRBeGlzS2V5cygpLm1hcCgoc2Vjb25kQXhpc0tleSkgPT4gewogICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KGZpcnN0QXhpc0tleSwgc2Vjb25kQXhpc0tleSkgPz8gZmlsbEVtcHR5V2l0aDsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9CiAgICBnZXRDb250ZW50cygpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBrZXlzRmlyc3RBeGlzOiB0aGlzLmtleXNGaXJzdEF4aXMsCiAgICAgICAga2V5c1NlY29uZEF4aXM6IHRoaXMua2V5c1NlY29uZEF4aXMsCiAgICAgICAgZGF0YTogdGhpcy5kYXRhCiAgICAgIH07CiAgICB9CiAgfQogIGNsYXNzIEJhc2VNdXRhdGlvbk92ZXJUaW1lRGF0YU1hcCBleHRlbmRzIE1hcDJkQmFzZSB7CiAgICBjb25zdHJ1Y3Rvcihpbml0aWFsQ29udGVudCkgewogICAgICBzdXBlcihzZXJpYWxpemVTdWJzdGl0dXRpb25PckRlbGV0aW9uLCBzZXJpYWxpemVUZW1wb3JhbCwgaW5pdGlhbENvbnRlbnQpOwogICAgfQogIH0KICBjb25zdCBzb3J0U3Vic3RpdHV0aW9uc0FuZERlbGV0aW9ucyA9IChhMiwgYikgPT4gewogICAgaWYgKGEyLnNlZ21lbnQgIT09IGIuc2VnbWVudCkgewogICAgICByZXR1cm4gY29tcGFyZVNlZ21lbnRzKGEyLnNlZ21lbnQsIGIuc2VnbWVudCk7CiAgICB9CiAgICBpZiAoYTIucG9zaXRpb24gIT09IGIucG9zaXRpb24pIHsKICAgICAgcmV0dXJuIGNvbXBhcmVQb3NpdGlvbnMoYTIucG9zaXRpb24sIGIucG9zaXRpb24pOwogICAgfQogICAgY29uc3QgYUlzRGVsZXRpb24gPSBhMiBpbnN0YW5jZW9mIERlbGV0aW9uQ2xhc3M7CiAgICBjb25zdCBiSXNEZWxldGlvbiA9IGIgaW5zdGFuY2VvZiBEZWxldGlvbkNsYXNzOwogICAgaWYgKGFJc0RlbGV0aW9uICE9PSBiSXNEZWxldGlvbikgewogICAgICByZXR1cm4gYUlzRGVsZXRpb24gPyAxIDogLTE7CiAgICB9CiAgICBpZiAoIWFJc0RlbGV0aW9uICYmICFiSXNEZWxldGlvbikgewogICAgICBpZiAoYTIuc3Vic3RpdHV0aW9uVmFsdWUgIT09IGIuc3Vic3RpdHV0aW9uVmFsdWUpIHsKICAgICAgICByZXR1cm4gY29tcGFyZVN1YnN0aXR1dGlvblZhbHVlcyhhMi5zdWJzdGl0dXRpb25WYWx1ZSwgYi5zdWJzdGl0dXRpb25WYWx1ZSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiAwOwogIH07CiAgY29uc3QgY29tcGFyZVNlZ21lbnRzID0gKGEyLCBiKSA9PiB7CiAgICBpZiAoYTIgPT09IHZvaWQgMCkgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICBpZiAoYiA9PT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiAxOwogICAgfQogICAgcmV0dXJuIGEyLmxvY2FsZUNvbXBhcmUoYik7CiAgfTsKICBjb25zdCBjb21wYXJlUG9zaXRpb25zID0gKGEyLCBiKSA9PiB7CiAgICByZXR1cm4gYTIgLSBiOwogIH07CiAgY29uc3QgY29tcGFyZVN1YnN0aXR1dGlvblZhbHVlcyA9IChhMiwgYikgPT4gewogICAgaWYgKGEyID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgaWYgKGIgPT09IHZvaWQgMCkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIHJldHVybiBhMi5sb2NhbGVDb21wYXJlKGIpOwogIH07CiAgY29uc3QgTUFYX05VTUJFUl9PRl9HUklEX0NPTFVNTlMgPSAyMDA7CiAgYXN5bmMgZnVuY3Rpb24gcXVlcnlPdmVyYWxsTXV0YXRpb25EYXRhKHsKICAgIGxhcGlzRmlsdGVyLAogICAgc2VxdWVuY2VUeXBlLAogICAgbGFwaXMsCiAgICBncmFudWxhcml0eSwKICAgIGxhcGlzRGF0ZUZpZWxkLAogICAgc2lnbmFsCiAgfSkgewogICAgY29uc3QgYWxsRGF0ZXMgPSBhd2FpdCBnZXREYXRlc0luRGF0YXNldChsYXBpc0ZpbHRlciwgbGFwaXMsIGdyYW51bGFyaXR5LCBsYXBpc0RhdGVGaWVsZCwgc2lnbmFsKTsKICAgIGlmIChhbGxEYXRlcy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBjb250ZW50OiBbXQogICAgICB9OwogICAgfQogICAgY29uc3QgZmlsdGVyID0gewogICAgICAuLi5sYXBpc0ZpbHRlciwKICAgICAgW2Ake2xhcGlzRGF0ZUZpZWxkfUZyb21gXTogYWxsRGF0ZXNbMF0uZmlyc3REYXkudG9TdHJpbmcoKSwKICAgICAgW2Ake2xhcGlzRGF0ZUZpZWxkfVRvYF06IGFsbERhdGVzW2FsbERhdGVzLmxlbmd0aCAtIDFdLmxhc3REYXkudG9TdHJpbmcoKQogICAgfTsKICAgIHJldHVybiBmZXRjaEFuZFByZXBhcmVTdWJzdGl0dXRpb25zT3JEZWxldGlvbnMoZmlsdGVyLCBzZXF1ZW5jZVR5cGUpLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogIH0KICBhc3luYyBmdW5jdGlvbiBxdWVyeU11dGF0aW9uc092ZXJUaW1lRGF0YSh7CiAgICBsYXBpc0ZpbHRlciwKICAgIHNlcXVlbmNlVHlwZSwKICAgIGxhcGlzLAogICAgbGFwaXNEYXRlRmllbGQsCiAgICBncmFudWxhcml0eSwKICAgIHNpZ25hbAogIH0pIHsKICAgIGNvbnN0IGFsbERhdGVzID0gYXdhaXQgZ2V0RGF0ZXNJbkRhdGFzZXQobGFwaXNGaWx0ZXIsIGxhcGlzLCBncmFudWxhcml0eSwgbGFwaXNEYXRlRmllbGQsIHNpZ25hbCk7CiAgICBpZiAoYWxsRGF0ZXMubGVuZ3RoID4gTUFYX05VTUJFUl9PRl9HUklEX0NPTFVNTlMpIHsKICAgICAgdGhyb3cgbmV3IFVzZXJGYWNpbmdFcnJvcigKICAgICAgICAiVG9vIG1hbnkgZGF0ZXMiLAogICAgICAgIGBUaGUgZGF0YXNldCB3b3VsZCBjb250YWluICR7YWxsRGF0ZXMubGVuZ3RofSBkYXRlIGludGVydmFscy4gUGxlYXNlIHJlZHVjZSB0aGUgbnVtYmVyIHRvIGJlbG93ICR7TUFYX05VTUJFUl9PRl9HUklEX0NPTFVNTlN9IHRvIGRpc3BsYXkgdGhlIGRhdGEuIFlvdSBjYW4gYWNoaWV2ZSB0aGlzIGJ5IGVpdGhlciBuYXJyb3dpbmcgdGhlIGRhdGUgcmFuZ2UgaW4gdGhlIHByb3ZpZGVkIExBUElTIGZpbHRlciBvciBieSBzZWxlY3RpbmcgYSBsYXJnZXIgZ3JhbnVsYXJpdHkuYAogICAgICApOwogICAgfQogICAgY29uc3Qgc3ViUXVlcmllcyA9IGFsbERhdGVzLm1hcChhc3luYyAoZGF0ZSkgPT4gewogICAgICBjb25zdCBkYXRlRnJvbSA9IGRhdGUuZmlyc3REYXkudG9TdHJpbmcoKTsKICAgICAgY29uc3QgZGF0ZVRvID0gZGF0ZS5sYXN0RGF5LnRvU3RyaW5nKCk7CiAgICAgIGNvbnN0IGZpbHRlciA9IHsKICAgICAgICAuLi5sYXBpc0ZpbHRlciwKICAgICAgICBbYCR7bGFwaXNEYXRlRmllbGR9RnJvbWBdOiBkYXRlRnJvbSwKICAgICAgICBbYCR7bGFwaXNEYXRlRmllbGR9VG9gXTogZGF0ZVRvCiAgICAgIH07CiAgICAgIGNvbnN0IGRhdGEyID0gYXdhaXQgZmV0Y2hBbmRQcmVwYXJlU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zKGZpbHRlciwgc2VxdWVuY2VUeXBlKS5ldmFsdWF0ZShsYXBpcywgc2lnbmFsKTsKICAgICAgY29uc3QgdG90YWxDb3VudFF1ZXJ5ID0gYXdhaXQgZ2V0VG90YWxOdW1iZXJPZlNlcXVlbmNlc0luRGF0ZVJhbmdlKGZpbHRlcikuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgZGF0ZSwKICAgICAgICBtdXRhdGlvbnM6IGRhdGEyLmNvbnRlbnQsCiAgICAgICAgdG90YWxDb3VudDogdG90YWxDb3VudFF1ZXJ5LmNvbnRlbnRbMF0uY291bnQKICAgICAgfTsKICAgIH0pOwogICAgY29uc3QgZGF0YSA9IGF3YWl0IFByb21pc2UuYWxsKHN1YlF1ZXJpZXMpOwogICAgY29uc3Qgb3ZlcmFsbE11dGF0aW9uc0RhdGEgPSAoYXdhaXQgcXVlcnlPdmVyYWxsTXV0YXRpb25EYXRhKHsKICAgICAgbGFwaXNGaWx0ZXIsCiAgICAgIHNlcXVlbmNlVHlwZSwKICAgICAgbGFwaXMsCiAgICAgIGxhcGlzRGF0ZUZpZWxkLAogICAgICBncmFudWxhcml0eQogICAgfSkpLmNvbnRlbnQ7CiAgICByZXR1cm4gewogICAgICBtdXRhdGlvbk92ZXJUaW1lRGF0YTogZ3JvdXBCeU11dGF0aW9uKGRhdGEsIG92ZXJhbGxNdXRhdGlvbnNEYXRhKSwKICAgICAgb3ZlcmFsbE11dGF0aW9uRGF0YTogb3ZlcmFsbE11dGF0aW9uc0RhdGEKICAgIH07CiAgfQogIGFzeW5jIGZ1bmN0aW9uIGdldERhdGVzSW5EYXRhc2V0KGxhcGlzRmlsdGVyLCBsYXBpcywgZ3JhbnVsYXJpdHksIGxhcGlzRGF0ZUZpZWxkLCBzaWduYWwpIHsKICAgIGNvbnN0IHsgY29udGVudDogYXZhaWxhYmxlRGF0ZXMgfSA9IGF3YWl0IHF1ZXJ5QXZhaWxhYmxlRGF0ZXMoCiAgICAgIGxhcGlzRmlsdGVyLAogICAgICBsYXBpcywKICAgICAgZ3JhbnVsYXJpdHksCiAgICAgIGxhcGlzRGF0ZUZpZWxkLAogICAgICBzaWduYWwKICAgICk7CiAgICBjb25zdCB7IGRhdGVGcm9tLCBkYXRlVG8gfSA9IGdldERhdGVSYW5nZUZyb21GaWx0ZXIobGFwaXNGaWx0ZXIsIGxhcGlzRGF0ZUZpZWxkLCBncmFudWxhcml0eSk7CiAgICBjb25zdCB7IG1pbiwgbWF4IH0gPSBnZXRNaW5NYXhUZW1wb3JhbChhdmFpbGFibGVEYXRlcyk7CiAgICByZXR1cm4gZ2VuZXJhdGVBbGxJblJhbmdlKGRhdGVGcm9tID8/IG1pbiwgZGF0ZVRvID8/IG1heCk7CiAgfQogIGZ1bmN0aW9uIGdldERhdGVSYW5nZUZyb21GaWx0ZXIobGFwaXNGaWx0ZXIsIGxhcGlzRGF0ZUZpZWxkLCBncmFudWxhcml0eSkgewogICAgY29uc3QgdmFsdWVGcm9tRmlsdGVyID0gbGFwaXNGaWx0ZXJbbGFwaXNEYXRlRmllbGRdOwogICAgaWYgKHZhbHVlRnJvbUZpbHRlcikgewogICAgICByZXR1cm4gewogICAgICAgIGRhdGVGcm9tOiBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKHZhbHVlRnJvbUZpbHRlciwgZ3JhbnVsYXJpdHkpLAogICAgICAgIGRhdGVUbzogcGFyc2VEYXRlU3RyaW5nVG9UZW1wb3JhbCh2YWx1ZUZyb21GaWx0ZXIsIGdyYW51bGFyaXR5KQogICAgICB9OwogICAgfQogICAgY29uc3QgbWluRnJvbUZpbHRlciA9IGxhcGlzRmlsdGVyW2Ake2xhcGlzRGF0ZUZpZWxkfUZyb21gXTsKICAgIGNvbnN0IG1heEZyb21GaWx0ZXIgPSBsYXBpc0ZpbHRlcltgJHtsYXBpc0RhdGVGaWVsZH1Ub2BdOwogICAgcmV0dXJuIHsKICAgICAgZGF0ZUZyb206IG1pbkZyb21GaWx0ZXIgPyBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKG1pbkZyb21GaWx0ZXIsIGdyYW51bGFyaXR5KSA6IG51bGwsCiAgICAgIGRhdGVUbzogbWF4RnJvbUZpbHRlciA/IHBhcnNlRGF0ZVN0cmluZ1RvVGVtcG9yYWwobWF4RnJvbUZpbHRlciwgZ3JhbnVsYXJpdHkpIDogbnVsbAogICAgfTsKICB9CiAgZnVuY3Rpb24gcXVlcnlBdmFpbGFibGVEYXRlcyhsYXBpc0ZpbHRlciwgbGFwaXMsIGdyYW51bGFyaXR5LCBsYXBpc0RhdGVGaWVsZCwgc2lnbmFsKSB7CiAgICByZXR1cm4gZmV0Y2hBbmRQcmVwYXJlRGF0ZXMobGFwaXNGaWx0ZXIsIGdyYW51bGFyaXR5LCBsYXBpc0RhdGVGaWVsZCkuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgfQogIGZ1bmN0aW9uIGZldGNoQW5kUHJlcGFyZURhdGVzKGZpbHRlciwgZ3JhbnVsYXJpdHksIGxhcGlzRGF0ZUZpZWxkKSB7CiAgICBjb25zdCBmZXRjaERhdGEgPSBuZXcgRmV0Y2hBZ2dyZWdhdGVkT3BlcmF0b3IoZmlsdGVyLCBbbGFwaXNEYXRlRmllbGRdKTsKICAgIGNvbnN0IGRhdGFXaXRoRml4ZWREYXRlS2V5ID0gbmV3IFJlbmFtZUZpZWxkT3BlcmF0b3IoZmV0Y2hEYXRhLCBsYXBpc0RhdGVGaWVsZCwgImRhdGUiKTsKICAgIGNvbnN0IG1hcERhdGEgPSBuZXcgTWFwT3BlcmF0b3IoZGF0YVdpdGhGaXhlZERhdGVLZXksIChkYXRhKSA9PiBtYXBEYXRlVG9HcmFudWxhcml0eVJhbmdlKGRhdGEsIGdyYW51bGFyaXR5KSk7CiAgICBjb25zdCBncm91cEJ5RGF0YSA9IG5ldyBHcm91cEJ5QW5kU3VtT3BlcmF0b3IobWFwRGF0YSwgImRhdGVSYW5nZSIsICJjb3VudCIpOwogICAgY29uc3Qgc29ydERhdGEgPSBuZXcgU29ydE9wZXJhdG9yKGdyb3VwQnlEYXRhLCBkYXRlUmFuZ2VDb21wYXJlKTsKICAgIHJldHVybiBuZXcgTWFwT3BlcmF0b3Ioc29ydERhdGEsIChkYXRhKSA9PiBkYXRhLmRhdGVSYW5nZSk7CiAgfQogIGZ1bmN0aW9uIGZldGNoQW5kUHJlcGFyZVN1YnN0aXR1dGlvbnNPckRlbGV0aW9ucyhmaWx0ZXIsIHNlcXVlbmNlVHlwZSkgewogICAgcmV0dXJuIG5ldyBGZXRjaFN1YnN0aXR1dGlvbnNPckRlbGV0aW9uc09wZXJhdG9yKGZpbHRlciwgc2VxdWVuY2VUeXBlLCAxZS0zKTsKICB9CiAgZnVuY3Rpb24gc2VyaWFsaXplU3Vic3RpdHV0aW9uT3JEZWxldGlvbihtdXRhdGlvbikgewogICAgcmV0dXJuIG11dGF0aW9uLmNvZGU7CiAgfQogIGZ1bmN0aW9uIHNlcmlhbGl6ZVRlbXBvcmFsKGRhdGUpIHsKICAgIHJldHVybiBkYXRlLmRhdGVTdHJpbmc7CiAgfQogIGZ1bmN0aW9uIGdyb3VwQnlNdXRhdGlvbihkYXRhLCBvdmVyYWxsTXV0YXRpb25EYXRhKSB7CiAgICBjb25zdCBkYXRhQXJyYXkgPSBuZXcgQmFzZU11dGF0aW9uT3ZlclRpbWVEYXRhTWFwKCk7CiAgICBjb25zdCBhbGxEYXRlcyA9IGRhdGEubWFwKChtdXRhdGlvbkRhdGEpID0+IG11dGF0aW9uRGF0YS5kYXRlKTsKICAgIGNvbnN0IHNvcnRlZE92ZXJhbGxNdXRhdGlvbkRhdGEgPSBvdmVyYWxsTXV0YXRpb25EYXRhLnNvcnQoKGEyLCBiKSA9PiBzb3J0U3Vic3RpdHV0aW9uc0FuZERlbGV0aW9ucyhhMi5tdXRhdGlvbiwgYi5tdXRhdGlvbikpLm1hcCgoZW50cnkpID0+IHsKICAgICAgcmV0dXJuIHRvU3Vic3RpdHV0aW9uT3JEZWxldGlvbihlbnRyeS5tdXRhdGlvbik7CiAgICB9KTsKICAgIGNvbnN0IHNvcnRlZERhdGVzID0gYWxsRGF0ZXMuc29ydCgoYTIsIGIpID0+IGNvbXBhcmVUZW1wb3JhbChhMiwgYikpLm1hcCgoZGF0ZSkgPT4gdG9UZW1wb3JhbChkYXRlKSk7CiAgICBzb3J0ZWRPdmVyYWxsTXV0YXRpb25EYXRhLmZvckVhY2goKG11dGF0aW9uRGF0YSkgPT4gewogICAgICBzb3J0ZWREYXRlcy5mb3JFYWNoKChkYXRlKSA9PiB7CiAgICAgICAgZGF0YUFycmF5LnNldChtdXRhdGlvbkRhdGEsIGRhdGUsIHsKICAgICAgICAgIGNvdW50OiAwLAogICAgICAgICAgcHJvcG9ydGlvbjogMCwKICAgICAgICAgIHRvdGFsQ291bnQ6IDAKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9KTsKICAgIGRhdGEuZm9yRWFjaCgobXV0YXRpb25EYXRhKSA9PiB7CiAgICAgIG11dGF0aW9uRGF0YS5tdXRhdGlvbnMuZm9yRWFjaCgobXV0YXRpb25FbnRyeSkgPT4gewogICAgICAgIGNvbnN0IG11dGF0aW9uID0gdG9TdWJzdGl0dXRpb25PckRlbGV0aW9uKG11dGF0aW9uRW50cnkubXV0YXRpb24pOwogICAgICAgIGNvbnN0IGRhdGUgPSB0b1RlbXBvcmFsKG11dGF0aW9uRGF0YS5kYXRlKTsKICAgICAgICBpZiAoZGF0YUFycmF5LmdldChtdXRhdGlvbiwgZGF0ZSkgIT09IHZvaWQgMCkgewogICAgICAgICAgZGF0YUFycmF5LnNldChtdXRhdGlvbiwgZGF0ZSwgewogICAgICAgICAgICBjb3VudDogbXV0YXRpb25FbnRyeS5jb3VudCwKICAgICAgICAgICAgcHJvcG9ydGlvbjogbXV0YXRpb25FbnRyeS5wcm9wb3J0aW9uLAogICAgICAgICAgICB0b3RhbENvdW50OiBtdXRhdGlvbkRhdGEudG90YWxDb3VudAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0pOwogICAgcmV0dXJuIGRhdGFBcnJheTsKICB9CiAgZnVuY3Rpb24gZ2V0VG90YWxOdW1iZXJPZlNlcXVlbmNlc0luRGF0ZVJhbmdlKGZpbHRlcikgewogICAgcmV0dXJuIG5ldyBGZXRjaEFnZ3JlZ2F0ZWRPcGVyYXRvcihmaWx0ZXIpOwogIH0KICBhc3luYyBmdW5jdGlvbiB3b3JrZXJGdW5jdGlvbihxdWVyeUZ1bmN0aW9uKSB7CiAgICB0cnkgewogICAgICBwb3N0TWVzc2FnZSh7IHN0YXR1czogImxvYWRpbmciIH0pOwogICAgICBjb25zdCB3b3JrZXJSZXNwb25zZSA9IGF3YWl0IHF1ZXJ5RnVuY3Rpb24oKTsKICAgICAgcG9zdE1lc3NhZ2UoewogICAgICAgIHN0YXR1czogInN1Y2Nlc3MiLAogICAgICAgIGRhdGE6IHdvcmtlclJlc3BvbnNlCiAgICAgIH0pOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgcG9zdE1lc3NhZ2UoCiAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBVc2VyRmFjaW5nRXJyb3IgPyB7CiAgICAgICAgICBzdGF0dXM6ICJlcnJvciIsCiAgICAgICAgICB1c2VyRmFjaW5nOiB0cnVlLAogICAgICAgICAgaGVhZGxpbmU6IGVycm9yLmhlYWRsaW5lLAogICAgICAgICAgZXJyb3IKICAgICAgICB9IDogewogICAgICAgICAgc3RhdHVzOiAiZXJyb3IiLAogICAgICAgICAgdXNlckZhY2luZzogZmFsc2UsCiAgICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKGAke2Vycm9yfWApCiAgICAgICAgfQogICAgICApOwogICAgfQogIH0KICBhc3luYyBmdW5jdGlvbiBnZXRNdXRhdGlvbk92ZXJUaW1lV29ya2VyRnVuY3Rpb24oZXZlbnQpIHsKICAgIGNvbnN0IG11dGF0aW9uT3ZlclRpbWVEYXRhID0gYXdhaXQgcXVlcnlNdXRhdGlvbnNPdmVyVGltZURhdGEoZXZlbnQuZGF0YSk7CiAgICBjb25zdCB3b3JrZXJSZXNwb25zZSA9IHsKICAgICAgb3ZlcmFsbE11dGF0aW9uRGF0YTogbXV0YXRpb25PdmVyVGltZURhdGEub3ZlcmFsbE11dGF0aW9uRGF0YSwKICAgICAgbXV0YXRpb25PdmVyVGltZVNlcmlhbGl6ZWQ6IG11dGF0aW9uT3ZlclRpbWVEYXRhLm11dGF0aW9uT3ZlclRpbWVEYXRhLmdldENvbnRlbnRzKCkKICAgIH07CiAgICByZXR1cm4gd29ya2VyUmVzcG9uc2U7CiAgfQogIHNlbGYub25tZXNzYWdlID0gYXN5bmMgZnVuY3Rpb24oZXZlbnQpIHsKICAgIGF3YWl0IHdvcmtlckZ1bmN0aW9uKCgpID0+IGdldE11dGF0aW9uT3ZlclRpbWVXb3JrZXJGdW5jdGlvbihldmVudCkpOwogIH07Cn0pKCk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPW11dGF0aW9uT3ZlclRpbWVXb3JrZXItQ3ZaZzUycmYuanMubWFwCg==";
|
|
8656
|
+
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+IG51bWJlclR5cGUoKS5vcHRpb25hbCgpOwogIGNvbnN0IG9ib29sZWFuID0gKCkgPT4gYm9vbGVhblR5cGUoKS5vcHRpb25hbCgpOwogIGNvbnN0IGNvZXJjZSA9IHsKICAgIHN0cmluZzogKGFyZykgPT4gWm9kU3RyaW5nLmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pLAogICAgbnVtYmVyOiAoYXJnKSA9PiBab2ROdW1iZXIuY3JlYXRlKHsgLi4uYXJnLCBjb2VyY2U6IHRydWUgfSksCiAgICBib29sZWFuOiAoYXJnKSA9PiBab2RCb29sZWFuLmNyZWF0ZSh7CiAgICAgIC4uLmFyZywKICAgICAgY29lcmNlOiB0cnVlCiAgICB9KSwKICAgIGJpZ2ludDogKGFyZykgPT4gWm9kQmlnSW50LmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pLAogICAgZGF0ZTogKGFyZykgPT4gWm9kRGF0ZS5jcmVhdGUoeyAuLi5hcmcsIGNvZXJjZTogdHJ1ZSB9KQogIH07CiAgY29uc3QgTkVWRVIgPSBJTlZBTElEOwogIHZhciB6JDEgPSAvKiBAX19QVVJFX18gKi8gT2JqZWN0LmZyZWV6ZSh7CiAgICBfX3Byb3RvX186IG51bGwsCiAgICBkZWZhdWx0RXJyb3JNYXA6IGVycm9yTWFwLAogICAgc2V0RXJyb3JNYXAsCiAgICBnZXRFcnJvck1hcCwKICAgIG1ha2VJc3N1ZSwKICAgIEVNUFRZX1BBVEgsCiAgICBhZGRJc3N1ZVRvQ29udGV4dCwKICAgIFBhcnNlU3RhdHVzLAogICAgSU5WQUxJRCwKICAgIERJUlRZLAogICAgT0ssCiAgICBpc0Fib3J0ZWQsCiAgICBpc0RpcnR5LAogICAgaXNWYWxpZCwKICAgIGlzQXN5bmMsCiAgICBnZXQgdXRpbCgpIHsKICAgICAgcmV0dXJuIHV0aWw7CiAgICB9LAogICAgZ2V0IG9iamVjdFV0aWwoKSB7CiAgICAgIHJldHVybiBvYmplY3RVdGlsOwogICAgfSwKICAgIFpvZFBhcnNlZFR5cGUsCiAgICBnZXRQYXJzZWRUeXBlLAogICAgWm9kVHlwZSwKICAgIGRhdGV0aW1lUmVnZXgsCiAgICBab2RTdHJpbmcsCiAgICBab2ROdW1iZXIsCiAgICBab2RCaWdJbnQsCiAgICBab2RCb29sZWFuLAogICAgWm9kRGF0ZSwKICAgIFpvZFN5bWJvbCwKICAgIFpvZFVuZGVmaW5lZCwKICAgIFpvZE51bGwsCiAgICBab2RBbnksCiAgICBab2RVbmtub3duLAogICAgWm9kTmV2ZXIsCiAgICBab2RWb2lkLAogICAgWm9kQXJyYXksCiAgICBab2RPYmplY3QsCiAgICBab2RVbmlvbiwKICAgIFpvZERpc2NyaW1pbmF0ZWRVbmlvbiwKICAgIFpvZEludGVyc2VjdGlvbiwKICAgIFpvZFR1cGxlLAogICAgWm9kUmVjb3JkLAogICAgWm9kTWFwLAogICAgWm9kU2V0LAogICAgWm9kRnVuY3Rpb24sCiAgICBab2RMYXp5LAogICAgWm9kTGl0ZXJhbCwKICAgIFpvZEVudW0sCiAgICBab2ROYXRpdmVFbnVtLAogICAgWm9kUHJvbWlzZSwKICAgIFpvZEVmZmVjdHMsCiAgICBab2RUcmFuc2Zvcm1lcjogWm9kRWZmZWN0cywKICAgIFpvZE9wdGlvbmFsLAogICAgWm9kTnVsbGFibGUsCiAgICBab2REZWZhdWx0LAogICAgWm9kQ2F0Y2gsCiAgICBab2ROYU4sCiAgICBCUkFORCwKICAgIFpvZEJyYW5kZWQsCiAgICBab2RQaXBlbGluZSwKICAgIFpvZFJlYWRvbmx5LAogICAgY3VzdG9tLAogICAgU2NoZW1hOiBab2RUeXBlLAogICAgWm9kU2NoZW1hOiBab2RUeXBlLAogICAgbGF0ZSwKICAgIGdldCBab2RGaXJzdFBhcnR5VHlwZUtpbmQoKSB7CiAgICAgIHJldHVybiBab2RGaXJzdFBhcnR5VHlwZUtpbmQ7CiAgICB9LAogICAgY29lcmNlLAogICAgYW55OiBhbnlUeXBlLAogICAgYXJyYXk6IGFycmF5VHlwZSwKICAgIGJpZ2ludDogYmlnSW50VHlwZSwKICAgIGJvb2xlYW46IGJvb2xlYW5UeXBlLAogICAgZGF0ZTogZGF0ZVR5cGUsCiAgICBkaXNjcmltaW5hdGVkVW5pb246IGRpc2NyaW1pbmF0ZWRVbmlvblR5cGUsCiAgICBlZmZlY3Q6IGVmZmVjdHNUeXBlLAogICAgImVudW0iOiBlbnVtVHlwZSwKICAgICJmdW5jdGlvbiI6IGZ1bmN0aW9uVHlwZSwKICAgICJpbnN0YW5jZW9mIjogaW5zdGFuY2VPZlR5cGUsCiAgICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvblR5cGUsCiAgICBsYXp5OiBsYXp5VHlwZSwKICAgIGxpdGVyYWw6IGxpdGVyYWxUeXBlLAogICAgbWFwOiBtYXBUeXBlLAogICAgbmFuOiBuYW5UeXBlLAogICAgbmF0aXZlRW51bTogbmF0aXZlRW51bVR5cGUsCiAgICBuZXZlcjogbmV2ZXJUeXBlLAogICAgIm51bGwiOiBudWxsVHlwZSwKICAgIG51bGxhYmxlOiBudWxsYWJsZVR5cGUsCiAgICBudW1iZXI6IG51bWJlclR5cGUsCiAgICBvYmplY3Q6IG9iamVjdFR5cGUsCiAgICBvYm9vbGVhbiwKICAgIG9udW1iZXIsCiAgICBvcHRpb25hbDogb3B0aW9uYWxUeXBlLAogICAgb3N0cmluZywKICAgIHBpcGVsaW5lOiBwaXBlbGluZVR5cGUsCiAgICBwcmVwcm9jZXNzOiBwcmVwcm9jZXNzVHlwZSwKICAgIHByb21pc2U6IHByb21pc2VUeXBlLAogICAgcmVjb3JkOiByZWNvcmRUeXBlLAogICAgc2V0OiBzZXRUeXBlLAogICAgc3RyaWN0T2JqZWN0OiBzdHJpY3RPYmplY3RUeXBlLAogICAgc3RyaW5nOiBzdHJpbmdUeXBlLAogICAgc3ltYm9sOiBzeW1ib2xUeXBlLAogICAgdHJhbnNmb3JtZXI6IGVmZmVjdHNUeXBlLAogICAgdHVwbGU6IHR1cGxlVHlwZSwKICAgICJ1bmRlZmluZWQiOiB1bmRlZmluZWRUeXBlLAogICAgdW5pb246IHVuaW9uVHlwZSwKICAgIHVua25vd246IHVua25vd25UeXBlLAogICAgInZvaWQiOiB2b2lkVHlwZSwKICAgIE5FVkVSLAogICAgWm9kSXNzdWVDb2RlLAogICAgcXVvdGVsZXNzSnNvbiwKICAgIFpvZEVycm9yCiAgfSk7CiAgeiQxLm9iamVjdCh7CiAgICBudWNsZW90aWRlU2VxdWVuY2VzOiB6JDEuYXJyYXkoCiAgICAgIHokMS5vYmplY3QoewogICAgICAgIG5hbWU6IHokMS5zdHJpbmcoKSwKICAgICAgICBzZXF1ZW5jZTogeiQxLnN0cmluZygpCiAgICAgIH0pCiAgICApLAogICAgZ2VuZXM6IHokMS5hcnJheSgKICAgICAgeiQxLm9iamVjdCh7CiAgICAgICAgbmFtZTogeiQxLnN0cmluZygpLAogICAgICAgIHNlcXVlbmNlOiB6JDEuc3RyaW5nKCkKICAgICAgfSkKICAgICkKICB9KTsKICBjb25zdCBvcmRlckJ5VHlwZSA9IHokMS5lbnVtKFsiYXNjZW5kaW5nIiwgImRlc2NlbmRpbmciXSk7CiAgY29uc3Qgb3JkZXJCeSA9IHokMS5vYmplY3QoewogICAgZmllbGQ6IHokMS5zdHJpbmcoKSwKICAgIHR5cGU6IG9yZGVyQnlUeXBlCiAgfSk7CiAgY29uc3QgbGFwaXNCYXNlUmVxdWVzdCA9IHokMS5vYmplY3QoewogICAgbGltaXQ6IHokMS5udW1iZXIoKS5vcHRpb25hbCgpLAogICAgb2Zmc2V0OiB6JDEubnVtYmVyKCkub3B0aW9uYWwoKSwKICAgIGZpZWxkczogeiQxLmFycmF5KHokMS5zdHJpbmcoKSkub3B0aW9uYWwoKSwKICAgIG9yZGVyQnk6IHokMS5hcnJheShvcmRlckJ5KS5vcHRpb25hbCgpCiAgfSkuY2F0Y2hhbGwoeiQxLnVuaW9uKFt6JDEuYm9vbGVhbigpLCB6JDEudW5kZWZpbmVkKCksIHokMS5zdHJpbmcoKSwgeiQxLm51bWJlcigpLCB6JDEubnVsbCgpLCB6JDEuYXJyYXkoeiQxLnN0cmluZygpKV0pKTsKICBsYXBpc0Jhc2VSZXF1ZXN0LmV4dGVuZCh7IG1pblByb3BvcnRpb246IHokMS5udW1iZXIoKS5vcHRpb25hbCgpIH0pOwogIGNvbnN0IG11dGF0aW9uUHJvcG9ydGlvbkNvdW50ID0geiQxLm9iamVjdCh7CiAgICBtdXRhdGlvbjogeiQxLnN0cmluZygpLAogICAgcHJvcG9ydGlvbjogeiQxLm51bWJlcigpLAogICAgY291bnQ6IHokMS5udW1iZXIoKSwKICAgIHNlcXVlbmNlTmFtZTogeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udWxsKCldKSwKICAgIG11dGF0aW9uRnJvbTogeiQxLnN0cmluZygpLAogICAgbXV0YXRpb25UbzogeiQxLnN0cmluZygpLAogICAgcG9zaXRpb246IHokMS5udW1iZXIoKQogIH0pOwogIGNvbnN0IG11dGF0aW9uc1Jlc3BvbnNlID0gbWFrZUxhcGlzUmVzcG9uc2UoeiQxLmFycmF5KG11dGF0aW9uUHJvcG9ydGlvbkNvdW50KSk7CiAgY29uc3QgaW5zZXJ0aW9uQ291bnQgPSB6JDEub2JqZWN0KHsKICAgIGluc2VydGlvbjogeiQxLnN0cmluZygpLAogICAgY291bnQ6IHokMS5udW1iZXIoKSwKICAgIGluc2VydGVkU3ltYm9sczogeiQxLnN0cmluZygpLAogICAgcG9zaXRpb246IHokMS5udW1iZXIoKSwKICAgIHNlcXVlbmNlTmFtZTogeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udWxsKCldKQogIH0pOwogIG1ha2VMYXBpc1Jlc3BvbnNlKHokMS5hcnJheShpbnNlcnRpb25Db3VudCkpOwogIGNvbnN0IGFnZ3JlZ2F0ZWRJdGVtID0geiQxLm9iamVjdCh7IGNvdW50OiB6JDEubnVtYmVyKCkgfSkuY2F0Y2hhbGwoeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udW1iZXIoKSwgeiQxLm51bGwoKV0pKTsKICBjb25zdCBhZ2dyZWdhdGVkUmVzcG9uc2UgPSBtYWtlTGFwaXNSZXNwb25zZSh6JDEuYXJyYXkoYWdncmVnYXRlZEl0ZW0pKTsKICBmdW5jdGlvbiBtYWtlTGFwaXNSZXNwb25zZShkYXRhKSB7CiAgICByZXR1cm4geiQxLm9iamVjdCh7CiAgICAgIGRhdGEKICAgIH0pOwogIH0KICBjb25zdCBwcm9ibGVtRGV0YWlsID0geiQxLm9iamVjdCh7CiAgICB0aXRsZTogeiQxLnN0cmluZygpLm9wdGlvbmFsKCksCiAgICBzdGF0dXM6IHokMS5udW1iZXIoKSwKICAgIGRldGFpbDogeiQxLnN0cmluZygpLm9wdGlvbmFsKCksCiAgICB0eXBlOiB6JDEuc3RyaW5nKCksCiAgICBpbnN0YW5jZTogeiQxLnN0cmluZygpLm9wdGlvbmFsKCkKICB9KTsKICBjb25zdCBsYXBpc0Vycm9yID0geiQxLm9iamVjdCh7CiAgICBlcnJvcjogcHJvYmxlbURldGFpbAogIH0pOwogIGNsYXNzIFVua25vd25MYXBpc0Vycm9yIGV4dGVuZHMgRXJyb3IgewogICAgY29uc3RydWN0b3IobWVzc2FnZSwgc3RhdHVzLCByZXF1ZXN0ZWREYXRhKSB7CiAgICAgIHN1cGVyKG1lc3NhZ2UpOwogICAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgICAgdGhpcy5yZXF1ZXN0ZWREYXRhID0gcmVxdWVzdGVkRGF0YTsKICAgICAgdGhpcy5uYW1lID0gIlVua25vd25MYXBpc0Vycm9yIjsKICAgIH0KICB9CiAgY2xhc3MgTGFwaXNFcnJvciBleHRlbmRzIEVycm9yIHsKICAgIGNvbnN0cnVjdG9yKG1lc3NhZ2UsIHN0YXR1cywgcHJvYmxlbURldGFpbDIsIHJlcXVlc3RlZERhdGEpIHsKICAgICAgc3VwZXIobWVzc2FnZSk7CiAgICAgIHRoaXMuc3RhdHVzID0gc3RhdHVzOwogICAgICB0aGlzLnByb2JsZW1EZXRhaWwgPSBwcm9ibGVtRGV0YWlsMjsKICAgICAgdGhpcy5yZXF1ZXN0ZWREYXRhID0gcmVxdWVzdGVkRGF0YTsKICAgICAgdGhpcy5uYW1lID0gIkxhcGlzRXJyb3IiOwogICAgfQogIH0KICBhc3luYyBmdW5jdGlvbiBmZXRjaEFnZ3JlZ2F0ZWQobGFwaXNVcmwsIGJvZHksIHNpZ25hbCkgewogICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjYWxsTGFwaXMoCiAgICAgIGFnZ3JlZ2F0ZWRFbmRwb2ludChsYXBpc1VybCksCiAgICAgIHsKICAgICAgICBtZXRob2Q6ICJQT1NUIiwKICAgICAgICBoZWFkZXJzOiB7CiAgICAgICAgICAiQ29udGVudC1UeXBlIjogImFwcGxpY2F0aW9uL2pzb24iCiAgICAgICAgfSwKICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShib2R5KSwKICAgICAgICBzaWduYWwKICAgICAgfSwKICAgICAgImFnZ3JlZ2F0ZWQgZGF0YSIKICAgICk7CiAgICByZXR1cm4gYWdncmVnYXRlZFJlc3BvbnNlLnBhcnNlKGF3YWl0IHJlc3BvbnNlLmpzb24oKSk7CiAgfQogIGFzeW5jIGZ1bmN0aW9uIGZldGNoU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zKGxhcGlzVXJsLCBib2R5LCBzZXF1ZW5jZVR5cGUsIHNpZ25hbCkgewogICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjYWxsTGFwaXMoCiAgICAgIHN1YnN0aXR1dGlvbnNPckRlbGV0aW9uc0VuZHBvaW50KGxhcGlzVXJsLCBzZXF1ZW5jZVR5cGUpLAogICAgICB7CiAgICAgICAgbWV0aG9kOiAiUE9TVCIsCiAgICAgICAgaGVhZGVyczogewogICAgICAgICAgIkNvbnRlbnQtVHlwZSI6ICJhcHBsaWNhdGlvbi9qc29uIgogICAgICAgIH0sCiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoYm9keSksCiAgICAgICAgc2lnbmFsCiAgICAgIH0sCiAgICAgIGAke3NlcXVlbmNlVHlwZX0gbXV0YXRpb25zYAogICAgKTsKICAgIHJldHVybiBtdXRhdGlvbnNSZXNwb25zZS5wYXJzZShhd2FpdCByZXNwb25zZS5qc29uKCkpOwogIH0KICBhc3luYyBmdW5jdGlvbiBjYWxsTGFwaXMoaW5wdXQsIGluaXQsIHJlcXVlc3RlZERhdGFOYW1lKSB7CiAgICB0cnkgewogICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGlucHV0LCBpbml0KTsKICAgICAgYXdhaXQgaGFuZGxlRXJyb3JzKHJlc3BvbnNlLCByZXF1ZXN0ZWREYXRhTmFtZSk7CiAgICAgIHJldHVybiByZXNwb25zZTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IGAke2Vycm9yfWA7CiAgICAgIHRocm93IG5ldyBVbmtub3duTGFwaXNFcnJvcihgRmFpbGVkIHRvIGNvbm5lY3QgdG8gTEFQSVM6ICR7bWVzc2FnZX1gLCA1MDAsIHJlcXVlc3RlZERhdGFOYW1lKTsKICAgIH0KICB9CiAgY29uc3QgaGFuZGxlRXJyb3JzID0gYXN5bmMgKHJlc3BvbnNlLCByZXF1ZXN0ZWREYXRhKSA9PiB7CiAgICBpZiAoIXJlc3BvbnNlLm9rKSB7CiAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgPj0gNDAwICYmIHJlc3BvbnNlLnN0YXR1cyA8IDUwMCkgewogICAgICAgIGNvbnN0IGpzb24gPSBhd2FpdCByZXNwb25zZS5qc29uKCk7CiAgICAgICAgY29uc3QgbGFwaXNFcnJvclJlc3VsdCA9IGxhcGlzRXJyb3Iuc2FmZVBhcnNlKGpzb24pOwogICAgICAgIGlmIChsYXBpc0Vycm9yUmVzdWx0LnN1Y2Nlc3MpIHsKICAgICAgICAgIHRocm93IG5ldyBMYXBpc0Vycm9yKAogICAgICAgICAgICByZXNwb25zZS5zdGF0dXNUZXh0ICsgbGFwaXNFcnJvclJlc3VsdC5kYXRhLmVycm9yLmRldGFpbCwKICAgICAgICAgICAgcmVzcG9uc2Uuc3RhdHVzLAogICAgICAgICAgICBsYXBpc0Vycm9yUmVzdWx0LmRhdGEuZXJyb3IsCiAgICAgICAgICAgIHJlcXVlc3RlZERhdGEKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHByb2JsZW1EZXRhaWxSZXN1bHQgPSBwcm9ibGVtRGV0YWlsLnNhZmVQYXJzZShqc29uKTsKICAgICAgICBpZiAocHJvYmxlbURldGFpbFJlc3VsdC5zdWNjZXNzKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTGFwaXNFcnJvcigKICAgICAgICAgICAgcmVzcG9uc2Uuc3RhdHVzVGV4dCArIHByb2JsZW1EZXRhaWxSZXN1bHQuZGF0YS5kZXRhaWwsCiAgICAgICAgICAgIHJlc3BvbnNlLnN0YXR1cywKICAgICAgICAgICAgcHJvYmxlbURldGFpbFJlc3VsdC5kYXRhLAogICAgICAgICAgICByZXF1ZXN0ZWREYXRhCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICB0aHJvdyBuZXcgVW5rbm93bkxhcGlzRXJyb3IoCiAgICAgICAgICBgJHtyZXNwb25zZS5zdGF0dXNUZXh0fTogJHtKU09OLnN0cmluZ2lmeShqc29uKX1gLAogICAgICAgICAgcmVzcG9uc2Uuc3RhdHVzLAogICAgICAgICAgcmVxdWVzdGVkRGF0YQogICAgICAgICk7CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IFVua25vd25MYXBpc0Vycm9yKGAke3Jlc3BvbnNlLnN0YXR1c1RleHR9OiAke3Jlc3BvbnNlLnN0YXR1c31gLCByZXNwb25zZS5zdGF0dXMsIHJlcXVlc3RlZERhdGEpOwogICAgfQogIH07CiAgY29uc3QgYWdncmVnYXRlZEVuZHBvaW50ID0gKGxhcGlzVXJsKSA9PiBgJHtsYXBpc1VybH0vc2FtcGxlL2FnZ3JlZ2F0ZWRgOwogIGNvbnN0IHN1YnN0aXR1dGlvbnNPckRlbGV0aW9uc0VuZHBvaW50ID0gKGxhcGlzVXJsLCBzZXF1ZW5jZVR5cGUpID0+IHsKICAgIHJldHVybiBzZXF1ZW5jZVR5cGUgPT09ICJhbWlubyBhY2lkIiA/IGAke2xhcGlzVXJsfS9zYW1wbGUvYW1pbm9BY2lkTXV0YXRpb25zYCA6IGAke2xhcGlzVXJsfS9zYW1wbGUvbnVjbGVvdGlkZU11dGF0aW9uc2A7CiAgfTsKICBjbGFzcyBGZXRjaEFnZ3JlZ2F0ZWRPcGVyYXRvciB7CiAgICBjb25zdHJ1Y3RvcihmaWx0ZXIsIGZpZWxkcyA9IFtdKSB7CiAgICAgIHRoaXMuZmlsdGVyID0gZmlsdGVyOwogICAgICB0aGlzLmZpZWxkcyA9IGZpZWxkczsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzVXJsLCBzaWduYWwpIHsKICAgICAgY29uc3QgYWdncmVnYXRlZFJlc3BvbnNlMiA9IChhd2FpdCBmZXRjaEFnZ3JlZ2F0ZWQoCiAgICAgICAgbGFwaXNVcmwsCiAgICAgICAgewogICAgICAgICAgLi4udGhpcy5maWx0ZXIsCiAgICAgICAgICBmaWVsZHM6IHRoaXMuZmllbGRzCiAgICAgICAgfSwKICAgICAgICBzaWduYWwKICAgICAgKSkuZGF0YTsKICAgICAgaWYgKGlzRmllbGRzQXJyYXlXaXRoQ291bnQoYWdncmVnYXRlZFJlc3BvbnNlMikpIHsKICAgICAgICByZXR1cm4gewogICAgICAgICAgY29udGVudDogYWdncmVnYXRlZFJlc3BvbnNlMgogICAgICAgIH07CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IEVycm9yKCJBZ2dyZWdhdGVkIHJlc3BvbnNlIGRvZXMgbm90IGhhdmUgY291bnQiKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gaXNGaWVsZHNBcnJheVdpdGhDb3VudChkYXRhKSB7CiAgICByZXR1cm4gZGF0YS5ldmVyeSgoaXRlbSkgPT4gdHlwZW9mIGl0ZW0gPT09ICJvYmplY3QiICYmICJjb3VudCIgaW4gaXRlbSAmJiB0eXBlb2YgaXRlbS5jb3VudCA9PT0gIm51bWJlciIpOwogIH0KICBjbGFzcyBHcm91cEJ5T3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoY2hpbGQsIGZpZWxkLCBhZ2dyZWdhdGUpIHsKICAgICAgdGhpcy5jaGlsZCA9IGNoaWxkOwogICAgICB0aGlzLmZpZWxkID0gZmllbGQ7CiAgICAgIHRoaXMuYWdncmVnYXRlID0gYWdncmVnYXRlOwogICAgfQogICAgYXN5bmMgZXZhbHVhdGUobGFwaXMsIHNpZ25hbCkgewogICAgICBjb25zdCBjaGlsZEV2YWx1YXRlZCA9IGF3YWl0IHRoaXMuY2hpbGQuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgICAgIGNvbnN0IGdyb3VwZWQgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICBmb3IgKGNvbnN0IHJvdyBvZiBjaGlsZEV2YWx1YXRlZC5jb250ZW50KSB7CiAgICAgICAgY29uc3Qga2V5ID0gcm93W3RoaXMuZmllbGRdOwogICAgICAgIGlmICghZ3JvdXBlZC5oYXMoa2V5KSkgewogICAgICAgICAgZ3JvdXBlZC5zZXQoa2V5LCBbXSk7CiAgICAgICAgfQogICAgICAgIGdyb3VwZWQuZ2V0KGtleSkucHVzaChyb3cpOwogICAgICB9CiAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBBcnJheSgpOwogICAgICBmb3IgKGNvbnN0IFssIHZhbHVlc10gb2YgZ3JvdXBlZCkgewogICAgICAgIHJlc3VsdC5wdXNoKHRoaXMuYWdncmVnYXRlKHZhbHVlcykpOwogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgY29udGVudDogcmVzdWx0CiAgICAgIH07CiAgICB9CiAgfQogIGNsYXNzIEdyb3VwQnlBbmRTdW1PcGVyYXRvciBleHRlbmRzIEdyb3VwQnlPcGVyYXRvciB7CiAgICBjb25zdHJ1Y3RvcihjaGlsZCwgZ3JvdXBCeUZpZWxkLCBzdW1GaWVsZCkgewogICAgICBzdXBlcihjaGlsZCwgZ3JvdXBCeUZpZWxkLCAodmFsdWVzKSA9PiB7CiAgICAgICAgbGV0IG4gPSAwOwogICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgdmFsdWVzKSB7CiAgICAgICAgICBuICs9IHZhbHVlW3N1bUZpZWxkXTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIFtncm91cEJ5RmllbGRdOiB2YWx1ZXNbMF1bZ3JvdXBCeUZpZWxkXSwKICAgICAgICAgIFtzdW1GaWVsZF06IG4KICAgICAgICB9OwogICAgICB9KTsKICAgIH0KICB9CiAgY2xhc3MgTWFwT3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoY2hpbGQsIGZ1bmMpIHsKICAgICAgdGhpcy5jaGlsZCA9IGNoaWxkOwogICAgICB0aGlzLmZ1bmMgPSBmdW5jOwogICAgfQogICAgYXN5bmMgZXZhbHVhdGUobGFwaXMsIHNpZ25hbCkgewogICAgICBjb25zdCBjaGlsZEV2YWx1YXRlZCA9IGF3YWl0IHRoaXMuY2hpbGQuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgY29udGVudDogY2hpbGRFdmFsdWF0ZWQuY29udGVudC5tYXAodGhpcy5mdW5jKQogICAgICB9OwogICAgfQogIH0KICBjbGFzcyBSZW5hbWVGaWVsZE9wZXJhdG9yIGV4dGVuZHMgTWFwT3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoY2hpbGQsIG9sZEZpZWxkTmFtZSwgbmV3RmllbGROYW1lKSB7CiAgICAgIHN1cGVyKAogICAgICAgIGNoaWxkLAogICAgICAgICh2YWx1ZSkgPT4gKHsKICAgICAgICAgIC4uLnZhbHVlLAogICAgICAgICAgW25ld0ZpZWxkTmFtZV06IHZhbHVlW29sZEZpZWxkTmFtZV0KICAgICAgICB9KQogICAgICApOwogICAgfQogIH0KICBjbGFzcyBTb3J0T3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoY2hpbGQsIGNvbXBhcmVGbikgewogICAgICB0aGlzLmNoaWxkID0gY2hpbGQ7CiAgICAgIHRoaXMuY29tcGFyZUZuID0gY29tcGFyZUZuOwogICAgfQogICAgYXN5bmMgZXZhbHVhdGUobGFwaXMsIHNpZ25hbCkgewogICAgICBjb25zdCBjaGlsZEV2YWx1YXRlZCA9IGF3YWl0IHRoaXMuY2hpbGQuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgY29udGVudDogY2hpbGRFdmFsdWF0ZWQuY29udGVudC5zb3J0KHRoaXMuY29tcGFyZUZuKQogICAgICB9OwogICAgfQogIH0KICB2YXIgU0VDT05EU19BX01JTlVURSA9IDYwOwogIHZhciBTRUNPTkRTX0FfSE9VUiA9IFNFQ09ORFNfQV9NSU5VVEUgKiA2MDsKICB2YXIgU0VDT05EU19BX0RBWSA9IFNFQ09ORFNfQV9IT1VSICogMjQ7CiAgdmFyIFNFQ09ORFNfQV9XRUVLID0gU0VDT05EU19BX0RBWSAqIDc7CiAgdmFyIE1JTExJU0VDT05EU19BX1NFQ09ORCA9IDFlMzsKICB2YXIgTUlMTElTRUNPTkRTX0FfTUlOVVRFID0gU0VDT05EU19BX01JTlVURSAqIE1JTExJU0VDT05EU19BX1NFQ09ORDsKICB2YXIgTUlMTElTRUNPTkRTX0FfSE9VUiA9IFNFQ09ORFNfQV9IT1VSICogTUlMTElTRUNPTkRTX0FfU0VDT05EOwogIHZhciBNSUxMSVNFQ09ORFNfQV9EQVkgPSBTRUNPTkRTX0FfREFZICogTUlMTElTRUNPTkRTX0FfU0VDT05EOwogIHZhciBNSUxMSVNFQ09ORFNfQV9XRUVLID0gU0VDT05EU19BX1dFRUsgKiBNSUxMSVNFQ09ORFNfQV9TRUNPTkQ7CiAgdmFyIE1TID0gIm1pbGxpc2Vjb25kIjsKICB2YXIgUyA9ICJzZWNvbmQiOwogIHZhciBNSU4gPSAibWludXRlIjsKICB2YXIgSCA9ICJob3VyIjsKICB2YXIgRCA9ICJkYXkiOwogIHZhciBXID0gIndlZWsiOwogIHZhciBNID0gIm1vbnRoIjsKICB2YXIgUSA9ICJxdWFydGVyIjsKICB2YXIgWSA9ICJ5ZWFyIjsKICB2YXIgREFURSA9ICJkYXRlIjsKICB2YXIgRk9STUFUX0RFRkFVTFQgPSAiWVlZWS1NTS1ERFRISDptbTpzc1oiOwogIHZhciBJTlZBTElEX0RBVEVfU1RSSU5HID0gIkludmFsaWQgRGF0ZSI7CiAgdmFyIFJFR0VYX1BBUlNFID0gL14oXGR7NH0pWy0vXT8oXGR7MSwyfSk/Wy0vXT8oXGR7MCwyfSlbVHRcc10qKFxkezEsMn0pPzo/KFxkezEsMn0pPzo/KFxkezEsMn0pP1suOl0/KFxkKyk/JC87CiAgdmFyIFJFR0VYX0ZPUk1BVCA9IC9cWyhbXlxdXSspXXxZezEsNH18TXsxLDR9fER7MSwyfXxkezEsNH18SHsxLDJ9fGh7MSwyfXxhfEF8bXsxLDJ9fHN7MSwyfXxaezEsMn18U1NTL2c7CiAgdmFyIGVuID0gewogICAgbmFtZTogImVuIiwKICAgIHdlZWtkYXlzOiAiU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXkiLnNwbGl0KCJfIiksCiAgICBtb250aHM6ICJKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyIi5zcGxpdCgiXyIpLAogICAgb3JkaW5hbDogZnVuY3Rpb24gb3JkaW5hbChuKSB7CiAgICAgIHZhciBzMiA9IFsidGgiLCAic3QiLCAibmQiLCAicmQiXTsKICAgICAgdmFyIHYyID0gbiAlIDEwMDsKICAgICAgcmV0dXJuICJbIiArIG4gKyAoczJbKHYyIC0gMjApICUgMTBdIHx8IHMyW3YyXSB8fCBzMlswXSkgKyAiXSI7CiAgICB9CiAgfTsKICB2YXIgcGFkU3RhcnQgPSBmdW5jdGlvbiBwYWRTdGFydDIoc3RyaW5nLCBsZW5ndGgsIHBhZCkgewogICAgdmFyIHMyID0gU3RyaW5nKHN0cmluZyk7CiAgICBpZiAoIXMyIHx8IHMyLmxlbmd0aCA+PSBsZW5ndGgpIHJldHVybiBzdHJpbmc7CiAgICByZXR1cm4gIiIgKyBBcnJheShsZW5ndGggKyAxIC0gczIubGVuZ3RoKS5qb2luKHBhZCkgKyBzdHJpbmc7CiAgfTsKICB2YXIgcGFkWm9uZVN0ciA9IGZ1bmN0aW9uIHBhZFpvbmVTdHIyKGluc3RhbmNlKSB7CiAgICB2YXIgbmVnTWludXRlcyA9IC1pbnN0YW5jZS51dGNPZmZzZXQoKTsKICAgIHZhciBtaW51dGVzID0gTWF0aC5hYnMobmVnTWludXRlcyk7CiAgICB2YXIgaG91ck9mZnNldCA9IE1hdGguZmxvb3IobWludXRlcyAvIDYwKTsKICAgIHZhciBtaW51dGVPZmZzZXQgPSBtaW51dGVzICUgNjA7CiAgICByZXR1cm4gKG5lZ01pbnV0ZXMgPD0gMCA/ICIrIiA6ICItIikgKyBwYWRTdGFydChob3VyT2Zmc2V0LCAyLCAiMCIpICsgIjoiICsgcGFkU3RhcnQobWludXRlT2Zmc2V0LCAyLCAiMCIpOwogIH07CiAgdmFyIG1vbnRoRGlmZiA9IGZ1bmN0aW9uIG1vbnRoRGlmZjIoYTIsIGIpIHsKICAgIGlmIChhMi5kYXRlKCkgPCBiLmRhdGUoKSkgcmV0dXJuIC1tb250aERpZmYyKGIsIGEyKTsKICAgIHZhciB3aG9sZU1vbnRoRGlmZiA9IChiLnllYXIoKSAtIGEyLnllYXIoKSkgKiAxMiArIChiLm1vbnRoKCkgLSBhMi5tb250aCgpKTsKICAgIHZhciBhbmNob3IgPSBhMi5jbG9uZSgpLmFkZCh3aG9sZU1vbnRoRGlmZiwgTSk7CiAgICB2YXIgYzIgPSBiIC0gYW5jaG9yIDwgMDsKICAgIHZhciBhbmNob3IyID0gYTIuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYgKyAoYzIgPyAtMSA6IDEpLCBNKTsKICAgIHJldHVybiArKC0od2hvbGVNb250aERpZmYgKyAoYiAtIGFuY2hvcikgLyAoYzIgPyBhbmNob3IgLSBhbmNob3IyIDogYW5jaG9yMiAtIGFuY2hvcikpIHx8IDApOwogIH07CiAgdmFyIGFic0Zsb29yID0gZnVuY3Rpb24gYWJzRmxvb3IyKG4pIHsKICAgIHJldHVybiBuIDwgMCA/IE1hdGguY2VpbChuKSB8fCAwIDogTWF0aC5mbG9vcihuKTsKICB9OwogIHZhciBwcmV0dHlVbml0ID0gZnVuY3Rpb24gcHJldHR5VW5pdDIodTIpIHsKICAgIHZhciBzcGVjaWFsID0gewogICAgICBNLAogICAgICB5OiBZLAogICAgICB3OiBXLAogICAgICBkOiBELAogICAgICBEOiBEQVRFLAogICAgICBoOiBILAogICAgICBtOiBNSU4sCiAgICAgIHM6IFMsCiAgICAgIG1zOiBNUywKICAgICAgUQogICAgfTsKICAgIHJldHVybiBzcGVjaWFsW3UyXSB8fCBTdHJpbmcodTIgfHwgIiIpLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvcyQvLCAiIik7CiAgfTsKICB2YXIgaXNVbmRlZmluZWQgPSBmdW5jdGlvbiBpc1VuZGVmaW5lZDIoczIpIHsKICAgIHJldHVybiBzMiA9PT0gdm9pZCAwOwogIH07CiAgdmFyIFUgPSB7CiAgICBzOiBwYWRTdGFydCwKICAgIHo6IHBhZFpvbmVTdHIsCiAgICBtOiBtb250aERpZmYsCiAgICBhOiBhYnNGbG9vciwKICAgIHA6IHByZXR0eVVuaXQsCiAgICB1OiBpc1VuZGVmaW5lZAogIH07CiAgdmFyIEwgPSAiZW4iOwogIHZhciBMcyA9IHt9OwogIExzW0xdID0gZW47CiAgdmFyIElTX0RBWUpTID0gIiRpc0RheWpzT2JqZWN0IjsKICB2YXIgaXNEYXlqcyA9IGZ1bmN0aW9uIGlzRGF5anMyKGQpIHsKICAgIHJldHVybiBkIGluc3RhbmNlb2YgRGF5anMgfHwgISEoZCAmJiBkW0lTX0RBWUpTXSk7CiAgfTsKICB2YXIgcGFyc2VMb2NhbGUgPSBmdW5jdGlvbiBwYXJzZUxvY2FsZTIocHJlc2V0LCBvYmplY3QsIGlzTG9jYWwpIHsKICAgIHZhciBsMjsKICAgIGlmICghcHJlc2V0KSByZXR1cm4gTDsKICAgIGlmICh0eXBlb2YgcHJlc2V0ID09PSAic3RyaW5nIikgewogICAgICB2YXIgcHJlc2V0TG93ZXIgPSBwcmVzZXQudG9Mb3dlckNhc2UoKTsKICAgICAgaWYgKExzW3ByZXNldExvd2VyXSkgewogICAgICAgIGwyID0gcHJlc2V0TG93ZXI7CiAgICAgIH0KICAgICAgaWYgKG9iamVjdCkgewogICAgICAgIExzW3ByZXNldExvd2VyXSA9IG9iamVjdDsKICAgICAgICBsMiA9IHByZXNldExvd2VyOwogICAgICB9CiAgICAgIHZhciBwcmVzZXRTcGxpdCA9IHByZXNldC5zcGxpdCgiLSIpOwogICAgICBpZiAoIWwyICYmIHByZXNldFNwbGl0Lmxlbmd0aCA+IDEpIHsKICAgICAgICByZXR1cm4gcGFyc2VMb2NhbGUyKHByZXNldFNwbGl0WzBdKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdmFyIG5hbWUgPSBwcmVzZXQubmFtZTsKICAgICAgTHNbbmFtZV0gPSBwcmVzZXQ7CiAgICAgIGwyID0gbmFtZTsKICAgIH0KICAgIGlmICghaXNMb2NhbCAmJiBsMikgTCA9IGwyOwogICAgcmV0dXJuIGwyIHx8ICFpc0xvY2FsICYmIEw7CiAgfTsKICB2YXIgZGF5anMgPSBmdW5jdGlvbiBkYXlqczIoZGF0ZSwgYzIpIHsKICAgIGlmIChpc0RheWpzKGRhdGUpKSB7CiAgICAgIHJldHVybiBkYXRlLmNsb25lKCk7CiAgICB9CiAgICB2YXIgY2ZnID0gdHlwZW9mIGMyID09PSAib2JqZWN0IiA/IGMyIDoge307CiAgICBjZmcuZGF0ZSA9IGRhdGU7CiAgICBjZmcuYXJncyA9IGFyZ3VtZW50czsKICAgIHJldHVybiBuZXcgRGF5anMoY2ZnKTsKICB9OwogIHZhciB3cmFwcGVyID0gZnVuY3Rpb24gd3JhcHBlcjIoZGF0ZSwgaW5zdGFuY2UpIHsKICAgIHJldHVybiBkYXlqcyhkYXRlLCB7CiAgICAgIGxvY2FsZTogaW5zdGFuY2UuJEwsCiAgICAgIHV0YzogaW5zdGFuY2UuJHUsCiAgICAgIHg6IGluc3RhbmNlLiR4LAogICAgICAkb2Zmc2V0OiBpbnN0YW5jZS4kb2Zmc2V0CiAgICAgIC8vIHRvZG86IHJlZmFjdG9yOyBkbyBub3QgdXNlIHRoaXMuJG9mZnNldCBpbiB5b3UgY29kZQogICAgfSk7CiAgfTsKICB2YXIgVXRpbHMgPSBVOwogIFV0aWxzLmwgPSBwYXJzZUxvY2FsZTsKICBVdGlscy5pID0gaXNEYXlqczsKICBVdGlscy53ID0gd3JhcHBlcjsKICB2YXIgcGFyc2VEYXRlID0gZnVuY3Rpb24gcGFyc2VEYXRlMihjZmcpIHsKICAgIHZhciBkYXRlID0gY2ZnLmRhdGUsIHV0YyA9IGNmZy51dGM7CiAgICBpZiAoZGF0ZSA9PT0gbnVsbCkgcmV0dXJuIC8qIEBfX1BVUkVfXyAqLyBuZXcgRGF0ZShOYU4pOwogICAgaWYgKFV0aWxzLnUoZGF0ZSkpIHJldHVybiAvKiBAX19QVVJFX18gKi8gbmV3IERhdGUoKTsKICAgIGlmIChkYXRlIGluc3RhbmNlb2YgRGF0ZSkgcmV0dXJuIG5ldyBEYXRlKGRhdGUpOwogICAgaWYgKHR5cGVvZiBkYXRlID09PSAic3RyaW5nIiAmJiAhL1okL2kudGVzdChkYXRlKSkgewogICAgICB2YXIgZCA9IGRhdGUubWF0Y2goUkVHRVhfUEFSU0UpOwogICAgICBpZiAoZCkgewogICAgICAgIHZhciBtMiA9IGRbMl0gLSAxIHx8IDA7CiAgICAgICAgdmFyIG1zID0gKGRbN10gfHwgIjAiKS5zdWJzdHJpbmcoMCwgMyk7CiAgICAgICAgaWYgKHV0YykgewogICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKERhdGUuVVRDKGRbMV0sIG0yLCBkWzNdIHx8IDEsIGRbNF0gfHwgMCwgZFs1XSB8fCAwLCBkWzZdIHx8IDAsIG1zKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgRGF0ZShkWzFdLCBtMiwgZFszXSB8fCAxLCBkWzRdIHx8IDAsIGRbNV0gfHwgMCwgZFs2XSB8fCAwLCBtcyk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBuZXcgRGF0ZShkYXRlKTsKICB9OwogIHZhciBEYXlqcyA9IC8qIEBfX1BVUkVfXyAqLyBmdW5jdGlvbigpIHsKICAgIGZ1bmN0aW9uIERheWpzMihjZmcpIHsKICAgICAgdGhpcy4kTCA9IHBhcnNlTG9jYWxlKGNmZy5sb2NhbGUsIG51bGwsIHRydWUpOwogICAgICB0aGlzLnBhcnNlKGNmZyk7CiAgICAgIHRoaXMuJHggPSB0aGlzLiR4IHx8IGNmZy54IHx8IHt9OwogICAgICB0aGlzW0lTX0RBWUpTXSA9IHRydWU7CiAgICB9CiAgICB2YXIgX3Byb3RvID0gRGF5anMyLnByb3RvdHlwZTsKICAgIF9wcm90by5wYXJzZSA9IGZ1bmN0aW9uIHBhcnNlKGNmZykgewogICAgICB0aGlzLiRkID0gcGFyc2VEYXRlKGNmZyk7CiAgICAgIHRoaXMuaW5pdCgpOwogICAgfTsKICAgIF9wcm90by5pbml0ID0gZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgdmFyICRkID0gdGhpcy4kZDsKICAgICAgdGhpcy4keSA9ICRkLmdldEZ1bGxZZWFyKCk7CiAgICAgIHRoaXMuJE0gPSAkZC5nZXRNb250aCgpOwogICAgICB0aGlzLiREID0gJGQuZ2V0RGF0ZSgpOwogICAgICB0aGlzLiRXID0gJGQuZ2V0RGF5KCk7CiAgICAgIHRoaXMuJEggPSAkZC5nZXRIb3VycygpOwogICAgICB0aGlzLiRtID0gJGQuZ2V0TWludXRlcygpOwogICAgICB0aGlzLiRzID0gJGQuZ2V0U2Vjb25kcygpOwogICAgICB0aGlzLiRtcyA9ICRkLmdldE1pbGxpc2Vjb25kcygpOwogICAgfTsKICAgIF9wcm90by4kdXRpbHMgPSBmdW5jdGlvbiAkdXRpbHMoKSB7CiAgICAgIHJldHVybiBVdGlsczsKICAgIH07CiAgICBfcHJvdG8uaXNWYWxpZCA9IGZ1bmN0aW9uIGlzVmFsaWQyKCkgewogICAgICByZXR1cm4gISh0aGlzLiRkLnRvU3RyaW5nKCkgPT09IElOVkFMSURfREFURV9TVFJJTkcpOwogICAgfTsKICAgIF9wcm90by5pc1NhbWUgPSBmdW5jdGlvbiBpc1NhbWUodGhhdCwgdW5pdHMpIHsKICAgICAgdmFyIG90aGVyID0gZGF5anModGhhdCk7CiAgICAgIHJldHVybiB0aGlzLnN0YXJ0T2YodW5pdHMpIDw9IG90aGVyICYmIG90aGVyIDw9IHRoaXMuZW5kT2YodW5pdHMpOwogICAgfTsKICAgIF9wcm90by5pc0FmdGVyID0gZnVuY3Rpb24gaXNBZnRlcih0aGF0LCB1bml0cykgewogICAgICByZXR1cm4gZGF5anModGhhdCkgPCB0aGlzLnN0YXJ0T2YodW5pdHMpOwogICAgfTsKICAgIF9wcm90by5pc0JlZm9yZSA9IGZ1bmN0aW9uIGlzQmVmb3JlKHRoYXQsIHVuaXRzKSB7CiAgICAgIHJldHVybiB0aGlzLmVuZE9mKHVuaXRzKSA8IGRheWpzKHRoYXQpOwogICAgfTsKICAgIF9wcm90by4kZyA9IGZ1bmN0aW9uICRnKGlucHV0LCBnZXQsIHNldCkgewogICAgICBpZiAoVXRpbHMudShpbnB1dCkpIHJldHVybiB0aGlzW2dldF07CiAgICAgIHJldHVybiB0aGlzLnNldChzZXQsIGlucHV0KTsKICAgIH07CiAgICBfcHJvdG8udW5peCA9IGZ1bmN0aW9uIHVuaXgoKSB7CiAgICAgIHJldHVybiBNYXRoLmZsb29yKHRoaXMudmFsdWVPZigpIC8gMWUzKTsKICAgIH07CiAgICBfcHJvdG8udmFsdWVPZiA9IGZ1bmN0aW9uIHZhbHVlT2YoKSB7CiAgICAgIHJldHVybiB0aGlzLiRkLmdldFRpbWUoKTsKICAgIH07CiAgICBfcHJvdG8uc3RhcnRPZiA9IGZ1bmN0aW9uIHN0YXJ0T2YodW5pdHMsIF9zdGFydE9mKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CiAgICAgIHZhciBpc1N0YXJ0T2YgPSAhVXRpbHMudShfc3RhcnRPZikgPyBfc3RhcnRPZiA6IHRydWU7CiAgICAgIHZhciB1bml0ID0gVXRpbHMucCh1bml0cyk7CiAgICAgIHZhciBpbnN0YW5jZUZhY3RvcnkgPSBmdW5jdGlvbiBpbnN0YW5jZUZhY3RvcnkyKGQsIG0yKSB7CiAgICAgICAgdmFyIGlucyA9IFV0aWxzLncoX3RoaXMuJHUgPyBEYXRlLlVUQyhfdGhpcy4keSwgbTIsIGQpIDogbmV3IERhdGUoX3RoaXMuJHksIG0yLCBkKSwgX3RoaXMpOwogICAgICAgIHJldHVybiBpc1N0YXJ0T2YgPyBpbnMgOiBpbnMuZW5kT2YoRCk7CiAgICAgIH07CiAgICAgIHZhciBpbnN0YW5jZUZhY3RvcnlTZXQgPSBmdW5jdGlvbiBpbnN0YW5jZUZhY3RvcnlTZXQyKG1ldGhvZCwgc2xpY2UpIHsKICAgICAgICB2YXIgYXJndW1lbnRTdGFydCA9IFswLCAwLCAwLCAwXTsKICAgICAgICB2YXIgYXJndW1lbnRFbmQgPSBbMjMsIDU5LCA1OSwgOTk5XTsKICAgICAgICByZXR1cm4gVXRpbHMudyhfdGhpcy50b0RhdGUoKVttZXRob2RdLmFwcGx5KAogICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBwcmVmZXItc3ByZWFkCiAgICAgICAgICBfdGhpcy50b0RhdGUoInMiKSwKICAgICAgICAgIChpc1N0YXJ0T2YgPyBhcmd1bWVudFN0YXJ0IDogYXJndW1lbnRFbmQpLnNsaWNlKHNsaWNlKQogICAgICAgICksIF90aGlzKTsKICAgICAgfTsKICAgICAgdmFyICRXID0gdGhpcy4kVywgJE0gPSB0aGlzLiRNLCAkRCA9IHRoaXMuJEQ7CiAgICAgIHZhciB1dGNQYWQgPSAic2V0IiArICh0aGlzLiR1ID8gIlVUQyIgOiAiIik7CiAgICAgIHN3aXRjaCAodW5pdCkgewogICAgICAgIGNhc2UgWToKICAgICAgICAgIHJldHVybiBpc1N0YXJ0T2YgPyBpbnN0YW5jZUZhY3RvcnkoMSwgMCkgOiBpbnN0YW5jZUZhY3RvcnkoMzEsIDExKTsKICAgICAgICBjYXNlIE06CiAgICAgICAgICByZXR1cm4gaXNTdGFydE9mID8gaW5zdGFuY2VGYWN0b3J5KDEsICRNKSA6IGluc3RhbmNlRmFjdG9yeSgwLCAkTSArIDEpOwogICAgICAgIGNhc2UgVzogewogICAgICAgICAgdmFyIHdlZWtTdGFydCA9IHRoaXMuJGxvY2FsZSgpLndlZWtTdGFydCB8fCAwOwogICAgICAgICAgdmFyIGdhcCA9ICgkVyA8IHdlZWtTdGFydCA/ICRXICsgNyA6ICRXKSAtIHdlZWtTdGFydDsKICAgICAgICAgIHJldHVybiBpbnN0YW5jZUZhY3RvcnkoaXNTdGFydE9mID8gJEQgLSBnYXAgOiAkRCArICg2IC0gZ2FwKSwgJE0pOwogICAgICAgIH0KICAgICAgICBjYXNlIEQ6CiAgICAgICAgY2FzZSBEQVRFOgogICAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCh1dGNQYWQgKyAiSG91cnMiLCAwKTsKICAgICAgICBjYXNlIEg6CiAgICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5U2V0KHV0Y1BhZCArICJNaW51dGVzIiwgMSk7CiAgICAgICAgY2FzZSBNSU46CiAgICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5U2V0KHV0Y1BhZCArICJTZWNvbmRzIiwgMik7CiAgICAgICAgY2FzZSBTOgogICAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCh1dGNQYWQgKyAiTWlsbGlzZWNvbmRzIiwgMyk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHJldHVybiB0aGlzLmNsb25lKCk7CiAgICAgIH0KICAgIH07CiAgICBfcHJvdG8uZW5kT2YgPSBmdW5jdGlvbiBlbmRPZihhcmcpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RhcnRPZihhcmcsIGZhbHNlKTsKICAgIH07CiAgICBfcHJvdG8uJHNldCA9IGZ1bmN0aW9uICRzZXQodW5pdHMsIF9pbnQpIHsKICAgICAgdmFyIF9DJEQkQyREQVRFJEMkTSRDJFkkQzsKICAgICAgdmFyIHVuaXQgPSBVdGlscy5wKHVuaXRzKTsKICAgICAgdmFyIHV0Y1BhZCA9ICJzZXQiICsgKHRoaXMuJHUgPyAiVVRDIiA6ICIiKTsKICAgICAgdmFyIG5hbWUgPSAoX0MkRCRDJERBVEUkQyRNJEMkWSRDID0ge30sIF9DJEQkQyREQVRFJEMkTSRDJFkkQ1tEXSA9IHV0Y1BhZCArICJEYXRlIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW0RBVEVdID0gdXRjUGFkICsgIkRhdGUiLCBfQyREJEMkREFURSRDJE0kQyRZJENbTV0gPSB1dGNQYWQgKyAiTW9udGgiLCBfQyREJEMkREFURSRDJE0kQyRZJENbWV0gPSB1dGNQYWQgKyAiRnVsbFllYXIiLCBfQyREJEMkREFURSRDJE0kQyRZJENbSF0gPSB1dGNQYWQgKyAiSG91cnMiLCBfQyREJEMkREFURSRDJE0kQyRZJENbTUlOXSA9IHV0Y1BhZCArICJNaW51dGVzIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW1NdID0gdXRjUGFkICsgIlNlY29uZHMiLCBfQyREJEMkREFURSRDJE0kQyRZJENbTVNdID0gdXRjUGFkICsgIk1pbGxpc2Vjb25kcyIsIF9DJEQkQyREQVRFJEMkTSRDJFkkQylbdW5pdF07CiAgICAgIHZhciBhcmcgPSB1bml0ID09PSBEID8gdGhpcy4kRCArIChfaW50IC0gdGhpcy4kVykgOiBfaW50OwogICAgICBpZiAodW5pdCA9PT0gTSB8fCB1bml0ID09PSBZKSB7CiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLmNsb25lKCkuc2V0KERBVEUsIDEpOwogICAgICAgIGRhdGUuJGRbbmFtZV0oYXJnKTsKICAgICAgICBkYXRlLmluaXQoKTsKICAgICAgICB0aGlzLiRkID0gZGF0ZS5zZXQoREFURSwgTWF0aC5taW4odGhpcy4kRCwgZGF0ZS5kYXlzSW5Nb250aCgpKSkuJGQ7CiAgICAgIH0gZWxzZSBpZiAobmFtZSkgdGhpcy4kZFtuYW1lXShhcmcpOwogICAgICB0aGlzLmluaXQoKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9OwogICAgX3Byb3RvLnNldCA9IGZ1bmN0aW9uIHNldChzdHJpbmcsIF9pbnQyKSB7CiAgICAgIHJldHVybiB0aGlzLmNsb25lKCkuJHNldChzdHJpbmcsIF9pbnQyKTsKICAgIH07CiAgICBfcHJvdG8uZ2V0ID0gZnVuY3Rpb24gZ2V0KHVuaXQpIHsKICAgICAgcmV0dXJuIHRoaXNbVXRpbHMucCh1bml0KV0oKTsKICAgIH07CiAgICBfcHJvdG8uYWRkID0gZnVuY3Rpb24gYWRkKG51bWJlciwgdW5pdHMpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXMsIF9DJE1JTiRDJEgkQyRTJHVuaXQ7CiAgICAgIG51bWJlciA9IE51bWJlcihudW1iZXIpOwogICAgICB2YXIgdW5pdCA9IFV0aWxzLnAodW5pdHMpOwogICAgICB2YXIgaW5zdGFuY2VGYWN0b3J5U2V0ID0gZnVuY3Rpb24gaW5zdGFuY2VGYWN0b3J5U2V0MihuKSB7CiAgICAgICAgdmFyIGQgPSBkYXlqcyhfdGhpczIpOwogICAgICAgIHJldHVybiBVdGlscy53KGQuZGF0ZShkLmRhdGUoKSArIE1hdGgucm91bmQobiAqIG51bWJlcikpLCBfdGhpczIpOwogICAgICB9OwogICAgICBpZiAodW5pdCA9PT0gTSkgewogICAgICAgIHJldHVybiB0aGlzLnNldChNLCB0aGlzLiRNICsgbnVtYmVyKTsKICAgICAgfQogICAgICBpZiAodW5pdCA9PT0gWSkgewogICAgICAgIHJldHVybiB0aGlzLnNldChZLCB0aGlzLiR5ICsgbnVtYmVyKTsKICAgICAgfQogICAgICBpZiAodW5pdCA9PT0gRCkgewogICAgICAgIHJldHVybiBpbnN0YW5jZUZhY3RvcnlTZXQoMSk7CiAgICAgIH0KICAgICAgaWYgKHVuaXQgPT09IFcpIHsKICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5U2V0KDcpOwogICAgICB9CiAgICAgIHZhciBzdGVwID0gKF9DJE1JTiRDJEgkQyRTJHVuaXQgPSB7fSwgX0MkTUlOJEMkSCRDJFMkdW5pdFtNSU5dID0gTUlMTElTRUNPTkRTX0FfTUlOVVRFLCBfQyRNSU4kQyRIJEMkUyR1bml0W0hdID0gTUlMTElTRUNPTkRTX0FfSE9VUiwgX0MkTUlOJEMkSCRDJFMkdW5pdFtTXSA9IE1JTExJU0VDT05EU19BX1NFQ09ORCwgX0MkTUlOJEMkSCRDJFMkdW5pdClbdW5pdF0gfHwgMTsKICAgICAgdmFyIG5leHRUaW1lU3RhbXAgPSB0aGlzLiRkLmdldFRpbWUoKSArIG51bWJlciAqIHN0ZXA7CiAgICAgIHJldHVybiBVdGlscy53KG5leHRUaW1lU3RhbXAsIHRoaXMpOwogICAgfTsKICAgIF9wcm90by5zdWJ0cmFjdCA9IGZ1bmN0aW9uIHN1YnRyYWN0KG51bWJlciwgc3RyaW5nKSB7CiAgICAgIHJldHVybiB0aGlzLmFkZChudW1iZXIgKiAtMSwgc3RyaW5nKTsKICAgIH07CiAgICBfcHJvdG8uZm9ybWF0ID0gZnVuY3Rpb24gZm9ybWF0KGZvcm1hdFN0cikgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKICAgICAgdmFyIGxvY2FsZSA9IHRoaXMuJGxvY2FsZSgpOwogICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSByZXR1cm4gbG9jYWxlLmludmFsaWREYXRlIHx8IElOVkFMSURfREFURV9TVFJJTkc7CiAgICAgIHZhciBzdHIgPSBmb3JtYXRTdHIgfHwgRk9STUFUX0RFRkFVTFQ7CiAgICAgIHZhciB6b25lU3RyID0gVXRpbHMueih0aGlzKTsKICAgICAgdmFyICRIID0gdGhpcy4kSCwgJG0gPSB0aGlzLiRtLCAkTSA9IHRoaXMuJE07CiAgICAgIHZhciB3ZWVrZGF5cyA9IGxvY2FsZS53ZWVrZGF5cywgbW9udGhzID0gbG9jYWxlLm1vbnRocywgbWVyaWRpZW0gPSBsb2NhbGUubWVyaWRpZW07CiAgICAgIHZhciBnZXRTaG9ydCA9IGZ1bmN0aW9uIGdldFNob3J0MihhcnIsIGluZGV4LCBmdWxsLCBsZW5ndGgpIHsKICAgICAgICByZXR1cm4gYXJyICYmIChhcnJbaW5kZXhdIHx8IGFycihfdGhpczMsIHN0cikpIHx8IGZ1bGxbaW5kZXhdLnNsaWNlKDAsIGxlbmd0aCk7CiAgICAgIH07CiAgICAgIHZhciBnZXQkSCA9IGZ1bmN0aW9uIGdldCRIMihudW0pIHsKICAgICAgICByZXR1cm4gVXRpbHMucygkSCAlIDEyIHx8IDEyLCBudW0sICIwIik7CiAgICAgIH07CiAgICAgIHZhciBtZXJpZGllbUZ1bmMgPSBtZXJpZGllbSB8fCBmdW5jdGlvbihob3VyLCBtaW51dGUsIGlzTG93ZXJjYXNlKSB7CiAgICAgICAgdmFyIG0yID0gaG91ciA8IDEyID8gIkFNIiA6ICJQTSI7CiAgICAgICAgcmV0dXJuIGlzTG93ZXJjYXNlID8gbTIudG9Mb3dlckNhc2UoKSA6IG0yOwogICAgICB9OwogICAgICB2YXIgbWF0Y2hlcyA9IGZ1bmN0aW9uIG1hdGNoZXMyKG1hdGNoKSB7CiAgICAgICAgc3dpdGNoIChtYXRjaCkgewogICAgICAgICAgY2FzZSAiWVkiOgogICAgICAgICAgICByZXR1cm4gU3RyaW5nKF90aGlzMy4keSkuc2xpY2UoLTIpOwogICAgICAgICAgY2FzZSAiWVlZWSI6CiAgICAgICAgICAgIHJldHVybiBVdGlscy5zKF90aGlzMy4keSwgNCwgIjAiKTsKICAgICAgICAgIGNhc2UgIk0iOgogICAgICAgICAgICByZXR1cm4gJE0gKyAxOwogICAgICAgICAgY2FzZSAiTU0iOgogICAgICAgICAgICByZXR1cm4gVXRpbHMucygkTSArIDEsIDIsICIwIik7CiAgICAgICAgICBjYXNlICJNTU0iOgogICAgICAgICAgICByZXR1cm4gZ2V0U2hvcnQobG9jYWxlLm1vbnRoc1Nob3J0LCAkTSwgbW9udGhzLCAzKTsKICAgICAgICAgIGNhc2UgIk1NTU0iOgogICAgICAgICAgICByZXR1cm4gZ2V0U2hvcnQobW9udGhzLCAkTSk7CiAgICAgICAgICBjYXNlICJEIjoKICAgICAgICAgICAgcmV0dXJuIF90aGlzMy4kRDsKICAgICAgICAgIGNhc2UgIkREIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoX3RoaXMzLiRELCAyLCAiMCIpOwogICAgICAgICAgY2FzZSAiZCI6CiAgICAgICAgICAgIHJldHVybiBTdHJpbmcoX3RoaXMzLiRXKTsKICAgICAgICAgIGNhc2UgImRkIjoKICAgICAgICAgICAgcmV0dXJuIGdldFNob3J0KGxvY2FsZS53ZWVrZGF5c01pbiwgX3RoaXMzLiRXLCB3ZWVrZGF5cywgMik7CiAgICAgICAgICBjYXNlICJkZGQiOgogICAgICAgICAgICByZXR1cm4gZ2V0U2hvcnQobG9jYWxlLndlZWtkYXlzU2hvcnQsIF90aGlzMy4kVywgd2Vla2RheXMsIDMpOwogICAgICAgICAgY2FzZSAiZGRkZCI6CiAgICAgICAgICAgIHJldHVybiB3ZWVrZGF5c1tfdGhpczMuJFddOwogICAgICAgICAgY2FzZSAiSCI6CiAgICAgICAgICAgIHJldHVybiBTdHJpbmcoJEgpOwogICAgICAgICAgY2FzZSAiSEgiOgogICAgICAgICAgICByZXR1cm4gVXRpbHMucygkSCwgMiwgIjAiKTsKICAgICAgICAgIGNhc2UgImgiOgogICAgICAgICAgICByZXR1cm4gZ2V0JEgoMSk7CiAgICAgICAgICBjYXNlICJoaCI6CiAgICAgICAgICAgIHJldHVybiBnZXQkSCgyKTsKICAgICAgICAgIGNhc2UgImEiOgogICAgICAgICAgICByZXR1cm4gbWVyaWRpZW1GdW5jKCRILCAkbSwgdHJ1ZSk7CiAgICAgICAgICBjYXNlICJBIjoKICAgICAgICAgICAgcmV0dXJuIG1lcmlkaWVtRnVuYygkSCwgJG0sIGZhbHNlKTsKICAgICAgICAgIGNhc2UgIm0iOgogICAgICAgICAgICByZXR1cm4gU3RyaW5nKCRtKTsKICAgICAgICAgIGNhc2UgIm1tIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoJG0sIDIsICIwIik7CiAgICAgICAgICBjYXNlICJzIjoKICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhfdGhpczMuJHMpOwogICAgICAgICAgY2FzZSAic3MiOgogICAgICAgICAgICByZXR1cm4gVXRpbHMucyhfdGhpczMuJHMsIDIsICIwIik7CiAgICAgICAgICBjYXNlICJTU1MiOgogICAgICAgICAgICByZXR1cm4gVXRpbHMucyhfdGhpczMuJG1zLCAzLCAiMCIpOwogICAgICAgICAgY2FzZSAiWiI6CiAgICAgICAgICAgIHJldHVybiB6b25lU3RyOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfTsKICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKFJFR0VYX0ZPUk1BVCwgZnVuY3Rpb24obWF0Y2gsICQxKSB7CiAgICAgICAgcmV0dXJuICQxIHx8IG1hdGNoZXMobWF0Y2gpIHx8IHpvbmVTdHIucmVwbGFjZSgiOiIsICIiKTsKICAgICAgfSk7CiAgICB9OwogICAgX3Byb3RvLnV0Y09mZnNldCA9IGZ1bmN0aW9uIHV0Y09mZnNldCgpIHsKICAgICAgcmV0dXJuIC1NYXRoLnJvdW5kKHRoaXMuJGQuZ2V0VGltZXpvbmVPZmZzZXQoKSAvIDE1KSAqIDE1OwogICAgfTsKICAgIF9wcm90by5kaWZmID0gZnVuY3Rpb24gZGlmZihpbnB1dCwgdW5pdHMsIF9mbG9hdCkgewogICAgICB2YXIgX3RoaXM0ID0gdGhpczsKICAgICAgdmFyIHVuaXQgPSBVdGlscy5wKHVuaXRzKTsKICAgICAgdmFyIHRoYXQgPSBkYXlqcyhpbnB1dCk7CiAgICAgIHZhciB6b25lRGVsdGEgPSAodGhhdC51dGNPZmZzZXQoKSAtIHRoaXMudXRjT2Zmc2V0KCkpICogTUlMTElTRUNPTkRTX0FfTUlOVVRFOwogICAgICB2YXIgZGlmZjIgPSB0aGlzIC0gdGhhdDsKICAgICAgdmFyIGdldE1vbnRoID0gZnVuY3Rpb24gZ2V0TW9udGgyKCkgewogICAgICAgIHJldHVybiBVdGlscy5tKF90aGlzNCwgdGhhdCk7CiAgICAgIH07CiAgICAgIHZhciByZXN1bHQ7CiAgICAgIHN3aXRjaCAodW5pdCkgewogICAgICAgIGNhc2UgWToKICAgICAgICAgIHJlc3VsdCA9IGdldE1vbnRoKCkgLyAxMjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgTToKICAgICAgICAgIHJlc3VsdCA9IGdldE1vbnRoKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFE6CiAgICAgICAgICByZXN1bHQgPSBnZXRNb250aCgpIC8gMzsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgVzoKICAgICAgICAgIHJlc3VsdCA9IChkaWZmMiAtIHpvbmVEZWx0YSkgLyBNSUxMSVNFQ09ORFNfQV9XRUVLOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBEOgogICAgICAgICAgcmVzdWx0ID0gKGRpZmYyIC0gem9uZURlbHRhKSAvIE1JTExJU0VDT05EU19BX0RBWTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgSDoKICAgICAgICAgIHJlc3VsdCA9IGRpZmYyIC8gTUlMTElTRUNPTkRTX0FfSE9VUjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgTUlOOgogICAgICAgICAgcmVzdWx0ID0gZGlmZjIgLyBNSUxMSVNFQ09ORFNfQV9NSU5VVEU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFM6CiAgICAgICAgICByZXN1bHQgPSBkaWZmMiAvIE1JTExJU0VDT05EU19BX1NFQ09ORDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXN1bHQgPSBkaWZmMjsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHJldHVybiBfZmxvYXQgPyByZXN1bHQgOiBVdGlscy5hKHJlc3VsdCk7CiAgICB9OwogICAgX3Byb3RvLmRheXNJbk1vbnRoID0gZnVuY3Rpb24gZGF5c0luTW9udGgoKSB7CiAgICAgIHJldHVybiB0aGlzLmVuZE9mKE0pLiREOwogICAgfTsKICAgIF9wcm90by4kbG9jYWxlID0gZnVuY3Rpb24gJGxvY2FsZSgpIHsKICAgICAgcmV0dXJuIExzW3RoaXMuJExdOwogICAgfTsKICAgIF9wcm90by5sb2NhbGUgPSBmdW5jdGlvbiBsb2NhbGUocHJlc2V0LCBvYmplY3QpIHsKICAgICAgaWYgKCFwcmVzZXQpIHJldHVybiB0aGlzLiRMOwogICAgICB2YXIgdGhhdCA9IHRoaXMuY2xvbmUoKTsKICAgICAgdmFyIG5leHRMb2NhbGVOYW1lID0gcGFyc2VMb2NhbGUocHJlc2V0LCBvYmplY3QsIHRydWUpOwogICAgICBpZiAobmV4dExvY2FsZU5hbWUpIHRoYXQuJEwgPSBuZXh0TG9jYWxlTmFtZTsKICAgICAgcmV0dXJuIHRoYXQ7CiAgICB9OwogICAgX3Byb3RvLmNsb25lID0gZnVuY3Rpb24gY2xvbmUoKSB7CiAgICAgIHJldHVybiBVdGlscy53KHRoaXMuJGQsIHRoaXMpOwogICAgfTsKICAgIF9wcm90by50b0RhdGUgPSBmdW5jdGlvbiB0b0RhdGUoKSB7CiAgICAgIHJldHVybiBuZXcgRGF0ZSh0aGlzLnZhbHVlT2YoKSk7CiAgICB9OwogICAgX3Byb3RvLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTigpIHsKICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZCgpID8gdGhpcy50b0lTT1N0cmluZygpIDogbnVsbDsKICAgIH07CiAgICBfcHJvdG8udG9JU09TdHJpbmcgPSBmdW5jdGlvbiB0b0lTT1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMuJGQudG9JU09TdHJpbmcoKTsKICAgIH07CiAgICBfcHJvdG8udG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMuJGQudG9VVENTdHJpbmcoKTsKICAgIH07CiAgICByZXR1cm4gRGF5anMyOwogIH0oKTsKICB2YXIgcHJvdG8gPSBEYXlqcy5wcm90b3R5cGU7CiAgZGF5anMucHJvdG90eXBlID0gcHJvdG87CiAgW1siJG1zIiwgTVNdLCBbIiRzIiwgU10sIFsiJG0iLCBNSU5dLCBbIiRIIiwgSF0sIFsiJFciLCBEXSwgWyIkTSIsIE1dLCBbIiR5IiwgWV0sIFsiJEQiLCBEQVRFXV0uZm9yRWFjaChmdW5jdGlvbihnKSB7CiAgICBwcm90b1tnWzFdXSA9IGZ1bmN0aW9uKGlucHV0KSB7CiAgICAgIHJldHVybiB0aGlzLiRnKGlucHV0LCBnWzBdLCBnWzFdKTsKICAgIH07CiAgfSk7CiAgZGF5anMuZXh0ZW5kID0gZnVuY3Rpb24ocGx1Z2luLCBvcHRpb24pIHsKICAgIGlmICghcGx1Z2luLiRpKSB7CiAgICAgIHBsdWdpbihvcHRpb24sIERheWpzLCBkYXlqcyk7CiAgICAgIHBsdWdpbi4kaSA9IHRydWU7CiAgICB9CiAgICByZXR1cm4gZGF5anM7CiAgfTsKICBkYXlqcy5sb2NhbGUgPSBwYXJzZUxvY2FsZTsKICBkYXlqcy5pc0RheWpzID0gaXNEYXlqczsKICBkYXlqcy51bml4ID0gZnVuY3Rpb24odGltZXN0YW1wKSB7CiAgICByZXR1cm4gZGF5anModGltZXN0YW1wICogMWUzKTsKICB9OwogIGRheWpzLmVuID0gTHNbTF07CiAgZGF5anMuTHMgPSBMczsKICBkYXlqcy5wID0ge307CiAgdmFyIGFkdmFuY2VkRm9ybWF0ID0gZnVuY3Rpb24obywgYzIpIHsKICAgIHZhciBwcm90bzIgPSBjMi5wcm90b3R5cGU7CiAgICB2YXIgb2xkRm9ybWF0ID0gcHJvdG8yLmZvcm1hdDsKICAgIHByb3RvMi5mb3JtYXQgPSBmdW5jdGlvbihmb3JtYXRTdHIpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKICAgICAgdmFyIGxvY2FsZSA9IHRoaXMuJGxvY2FsZSgpOwogICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7CiAgICAgICAgcmV0dXJuIG9sZEZvcm1hdC5iaW5kKHRoaXMpKGZvcm1hdFN0cik7CiAgICAgIH0KICAgICAgdmFyIHV0aWxzID0gdGhpcy4kdXRpbHMoKTsKICAgICAgdmFyIHN0ciA9IGZvcm1hdFN0ciB8fCBGT1JNQVRfREVGQVVMVDsKICAgICAgdmFyIHJlc3VsdCA9IHN0ci5yZXBsYWNlKC9cWyhbXlxdXSspXXxRfHdvfHd3fHd8V1d8V3x6enp8enxnZ2dnfEdHR0d8RG98WHx4fGt7MSwyfXxTL2csIGZ1bmN0aW9uKG1hdGNoKSB7CiAgICAgICAgc3dpdGNoIChtYXRjaCkgewogICAgICAgICAgY2FzZSAiUSI6CiAgICAgICAgICAgIHJldHVybiBNYXRoLmNlaWwoKF90aGlzLiRNICsgMSkgLyAzKTsKICAgICAgICAgIGNhc2UgIkRvIjoKICAgICAgICAgICAgcmV0dXJuIGxvY2FsZS5vcmRpbmFsKF90aGlzLiREKTsKICAgICAgICAgIGNhc2UgImdnZ2ciOgogICAgICAgICAgICByZXR1cm4gX3RoaXMud2Vla1llYXIoKTsKICAgICAgICAgIGNhc2UgIkdHR0ciOgogICAgICAgICAgICByZXR1cm4gX3RoaXMuaXNvV2Vla1llYXIoKTsKICAgICAgICAgIGNhc2UgIndvIjoKICAgICAgICAgICAgcmV0dXJuIGxvY2FsZS5vcmRpbmFsKF90aGlzLndlZWsoKSwgIlciKTsKICAgICAgICAgIGNhc2UgInciOgogICAgICAgICAgY2FzZSAid3ciOgogICAgICAgICAgICByZXR1cm4gdXRpbHMucyhfdGhpcy53ZWVrKCksIG1hdGNoID09PSAidyIgPyAxIDogMiwgIjAiKTsKICAgICAgICAgIGNhc2UgIlciOgogICAgICAgICAgY2FzZSAiV1ciOgogICAgICAgICAgICByZXR1cm4gdXRpbHMucyhfdGhpcy5pc29XZWVrKCksIG1hdGNoID09PSAiVyIgPyAxIDogMiwgIjAiKTsKICAgICAgICAgIGNhc2UgImsiOgogICAgICAgICAgY2FzZSAia2siOgogICAgICAgICAgICByZXR1cm4gdXRpbHMucyhTdHJpbmcoX3RoaXMuJEggPT09IDAgPyAyNCA6IF90aGlzLiRIKSwgbWF0Y2ggPT09ICJrIiA/IDEgOiAyLCAiMCIpOwogICAgICAgICAgY2FzZSAiWCI6CiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKF90aGlzLiRkLmdldFRpbWUoKSAvIDFlMyk7CiAgICAgICAgICBjYXNlICJ4IjoKICAgICAgICAgICAgcmV0dXJuIF90aGlzLiRkLmdldFRpbWUoKTsKICAgICAgICAgIGNhc2UgInoiOgogICAgICAgICAgICByZXR1cm4gIlsiICsgX3RoaXMub2Zmc2V0TmFtZSgpICsgIl0iOwogICAgICAgICAgY2FzZSAienp6IjoKICAgICAgICAgICAgcmV0dXJuICJbIiArIF90aGlzLm9mZnNldE5hbWUoImxvbmciKSArICJdIjsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHJldHVybiBtYXRjaDsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gb2xkRm9ybWF0LmJpbmQodGhpcykocmVzdWx0KTsKICAgIH07CiAgfTsKICB2YXIgaXNvV2Vla1ByZXR0eVVuaXQgPSAiaXNvd2VlayI7CiAgdmFyIGlzb1dlZWsgPSBmdW5jdGlvbihvLCBjMiwgZCkgewogICAgdmFyIGdldFllYXJGaXJzdFRodXJzZGF5ID0gZnVuY3Rpb24gZ2V0WWVhckZpcnN0VGh1cnNkYXkyKHllYXIsIGlzVXRjKSB7CiAgICAgIHZhciB5ZWFyRmlyc3REYXkgPSAoaXNVdGMgPyBkLnV0YyA6IGQpKCkueWVhcih5ZWFyKS5zdGFydE9mKFkpOwogICAgICB2YXIgYWRkRGlmZkRheXMgPSA0IC0geWVhckZpcnN0RGF5Lmlzb1dlZWtkYXkoKTsKICAgICAgaWYgKHllYXJGaXJzdERheS5pc29XZWVrZGF5KCkgPiA0KSB7CiAgICAgICAgYWRkRGlmZkRheXMgKz0gNzsKICAgICAgfQogICAgICByZXR1cm4geWVhckZpcnN0RGF5LmFkZChhZGREaWZmRGF5cywgRCk7CiAgICB9OwogICAgdmFyIGdldEN1cnJlbnRXZWVrVGh1cnNkYXkgPSBmdW5jdGlvbiBnZXRDdXJyZW50V2Vla1RodXJzZGF5MihpbnMpIHsKICAgICAgcmV0dXJuIGlucy5hZGQoNCAtIGlucy5pc29XZWVrZGF5KCksIEQpOwogICAgfTsKICAgIHZhciBwcm90bzIgPSBjMi5wcm90b3R5cGU7CiAgICBwcm90bzIuaXNvV2Vla1llYXIgPSBmdW5jdGlvbigpIHsKICAgICAgdmFyIG5vd1dlZWtUaHVyc2RheSA9IGdldEN1cnJlbnRXZWVrVGh1cnNkYXkodGhpcyk7CiAgICAgIHJldHVybiBub3dXZWVrVGh1cnNkYXkueWVhcigpOwogICAgfTsKICAgIHByb3RvMi5pc29XZWVrID0gZnVuY3Rpb24od2VlaykgewogICAgICBpZiAoIXRoaXMuJHV0aWxzKCkudSh3ZWVrKSkgewogICAgICAgIHJldHVybiB0aGlzLmFkZCgod2VlayAtIHRoaXMuaXNvV2VlaygpKSAqIDcsIEQpOwogICAgICB9CiAgICAgIHZhciBub3dXZWVrVGh1cnNkYXkgPSBnZXRDdXJyZW50V2Vla1RodXJzZGF5KHRoaXMpOwogICAgICB2YXIgZGlmZldlZWtUaHVyc2RheSA9IGdldFllYXJGaXJzdFRodXJzZGF5KHRoaXMuaXNvV2Vla1llYXIoKSwgdGhpcy4kdSk7CiAgICAgIHJldHVybiBub3dXZWVrVGh1cnNkYXkuZGlmZihkaWZmV2Vla1RodXJzZGF5LCBXKSArIDE7CiAgICB9OwogICAgcHJvdG8yLmlzb1dlZWtkYXkgPSBmdW5jdGlvbih3ZWVrKSB7CiAgICAgIGlmICghdGhpcy4kdXRpbHMoKS51KHdlZWspKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZGF5KHRoaXMuZGF5KCkgJSA3ID8gd2VlayA6IHdlZWsgLSA3KTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5kYXkoKSB8fCA3OwogICAgfTsKICAgIHZhciBvbGRTdGFydE9mID0gcHJvdG8yLnN0YXJ0T2Y7CiAgICBwcm90bzIuc3RhcnRPZiA9IGZ1bmN0aW9uKHVuaXRzLCBzdGFydE9mKSB7CiAgICAgIHZhciB1dGlscyA9IHRoaXMuJHV0aWxzKCk7CiAgICAgIHZhciBpc1N0YXJ0T2YgPSAhdXRpbHMudShzdGFydE9mKSA/IHN0YXJ0T2YgOiB0cnVlOwogICAgICB2YXIgdW5pdCA9IHV0aWxzLnAodW5pdHMpOwogICAgICBpZiAodW5pdCA9PT0gaXNvV2Vla1ByZXR0eVVuaXQpIHsKICAgICAgICByZXR1cm4gaXNTdGFydE9mID8gdGhpcy5kYXRlKHRoaXMuZGF0ZSgpIC0gKHRoaXMuaXNvV2Vla2RheSgpIC0gMSkpLnN0YXJ0T2YoImRheSIpIDogdGhpcy5kYXRlKHRoaXMuZGF0ZSgpIC0gMSAtICh0aGlzLmlzb1dlZWtkYXkoKSAtIDEpICsgNykuZW5kT2YoImRheSIpOwogICAgICB9CiAgICAgIHJldHVybiBvbGRTdGFydE9mLmJpbmQodGhpcykodW5pdHMsIHN0YXJ0T2YpOwogICAgfTsKICB9OwogIGRheWpzLmV4dGVuZChpc29XZWVrKTsKICBkYXlqcy5leHRlbmQoYWR2YW5jZWRGb3JtYXQpOwogIGNvbnN0IEZPUk1BVF9JU09fV0VFS19ZRUFSX1dFRUsgPSAiR0dHRy1bV11XVyI7CiAgY29uc3QgX1RlbXBvcmFsQ2FjaGUgPSBjbGFzcyBfVGVtcG9yYWxDYWNoZSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgdGhpcy55ZWFyTW9udGhEYXlDYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgIHRoaXMueWVhcldlZWtDYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgIHRoaXMueWVhck1vbnRoQ2FjaGUgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLnllYXJDYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICB9CiAgICBnZXRZZWFyTW9udGhEYXkoczIpIHsKICAgICAgaWYgKCF0aGlzLnllYXJNb250aERheUNhY2hlLmhhcyhzMikpIHsKICAgICAgICB0aGlzLnllYXJNb250aERheUNhY2hlLnNldChzMiwgWWVhck1vbnRoRGF5Q2xhc3MucGFyc2UoczIsIHRoaXMpKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy55ZWFyTW9udGhEYXlDYWNoZS5nZXQoczIpOwogICAgfQogICAgZ2V0WWVhck1vbnRoKHMyKSB7CiAgICAgIGlmICghdGhpcy55ZWFyTW9udGhDYWNoZS5oYXMoczIpKSB7CiAgICAgICAgdGhpcy55ZWFyTW9udGhDYWNoZS5zZXQoczIsIFllYXJNb250aENsYXNzLnBhcnNlKHMyLCB0aGlzKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMueWVhck1vbnRoQ2FjaGUuZ2V0KHMyKTsKICAgIH0KICAgIGdldFllYXJXZWVrKHMyKSB7CiAgICAgIGlmICghdGhpcy55ZWFyV2Vla0NhY2hlLmhhcyhzMikpIHsKICAgICAgICB0aGlzLnllYXJXZWVrQ2FjaGUuc2V0KHMyLCBZZWFyV2Vla0NsYXNzLnBhcnNlKHMyLCB0aGlzKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMueWVhcldlZWtDYWNoZS5nZXQoczIpOwogICAgfQogICAgZ2V0WWVhcihzMikgewogICAgICBpZiAoIXRoaXMueWVhckNhY2hlLmhhcyhzMikpIHsKICAgICAgICB0aGlzLnllYXJDYWNoZS5zZXQoczIsIFllYXJDbGFzcy5wYXJzZShzMiwgdGhpcykpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnllYXJDYWNoZS5nZXQoczIpOwogICAgfQogICAgc3RhdGljIGdldEluc3RhbmNlKCkgewogICAgICByZXR1cm4gdGhpcy5pbnN0YW5jZTsKICAgIH0KICB9OwogIF9UZW1wb3JhbENhY2hlLmluc3RhbmNlID0gbmV3IF9UZW1wb3JhbENhY2hlKCk7CiAgbGV0IFRlbXBvcmFsQ2FjaGUgPSBfVGVtcG9yYWxDYWNoZTsKICBjbGFzcyBZZWFyTW9udGhEYXlDbGFzcyB7CiAgICBjb25zdHJ1Y3Rvcih5ZWFyTnVtYmVyLCBtb250aE51bWJlciwgZGF5TnVtYmVyLCBjYWNoZSkgewogICAgICB0aGlzLnllYXJOdW1iZXIgPSB5ZWFyTnVtYmVyOwogICAgICB0aGlzLm1vbnRoTnVtYmVyID0gbW9udGhOdW1iZXI7CiAgICAgIHRoaXMuZGF5TnVtYmVyID0gZGF5TnVtYmVyOwogICAgICB0aGlzLmNhY2hlID0gY2FjaGU7CiAgICAgIHRoaXMudHlwZSA9ICJZZWFyTW9udGhEYXkiOwogICAgICB0aGlzLmRhdGUgPSBuZXcgRGF0ZSh0aGlzLnllYXJOdW1iZXIsIHRoaXMubW9udGhOdW1iZXIgLSAxLCB0aGlzLmRheU51bWJlcik7CiAgICAgIHRoaXMuZGF5anMgPSBkYXlqcyh0aGlzLmRhdGUpOwogICAgICB0aGlzLmRhdGVTdHJpbmcgPSB0aGlzLnRvU3RyaW5nKCk7CiAgICB9CiAgICBnZXQgdGV4dCgpIHsKICAgICAgcmV0dXJuIHRoaXMuZGF5anMuZm9ybWF0KCJZWVlZLU1NLUREIik7CiAgICB9CiAgICB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMudGV4dDsKICAgIH0KICAgIGVuZ2xpc2hOYW1lKCkgewogICAgICByZXR1cm4gdGhpcy5kYXlqcy5mb3JtYXQoImRkZGQsIE1NTU0gRCwgWVlZWSIpOwogICAgfQogICAgZ2V0IGZpcnN0RGF5KCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH0KICAgIGdldCBsYXN0RGF5KCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH0KICAgIGdldCB5ZWFyKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyKGAke3RoaXMueWVhck51bWJlcn1gKTsKICAgIH0KICAgIGdldCBtb250aCgpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoKHRoaXMuZGF5anMuZm9ybWF0KCJZWVlZLU1NIikpOwogICAgfQogICAgZ2V0IHdlZWsoKSB7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJXZWVrKHRoaXMuZGF5anMuZm9ybWF0KEZPUk1BVF9JU09fV0VFS19ZRUFSX1dFRUspKTsKICAgIH0KICAgIGFkZERheXMoZGF5cykgewogICAgICBjb25zdCBkYXRlID0gdGhpcy5kYXlqcy5hZGQoZGF5cywgImRheSIpOwogICAgICBjb25zdCBzMiA9IGRhdGUuZm9ybWF0KCJZWVlZLU1NLUREIik7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aERheShzMik7CiAgICB9CiAgICBtaW51cyhvdGhlcikgewogICAgICByZXR1cm4gdGhpcy5kYXlqcy5kaWZmKG90aGVyLmRheWpzLCAiZGF5Iik7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UoczIsIGNhY2hlKSB7CiAgICAgIGNvbnN0IFt5ZWFyLCBtb250aCwgZGF5XSA9IHMyLnNwbGl0KCItIikubWFwKChzMjIpID0+IHBhcnNlSW50KHMyMiwgMTApKTsKICAgICAgcmV0dXJuIG5ldyBZZWFyTW9udGhEYXlDbGFzcyh5ZWFyLCBtb250aCwgZGF5LCBjYWNoZSk7CiAgICB9CiAgfQogIGNsYXNzIFllYXJXZWVrQ2xhc3MgewogICAgY29uc3RydWN0b3IoaXNvWWVhck51bWJlciwgaXNvV2Vla051bWJlciwgY2FjaGUpIHsKICAgICAgdGhpcy5pc29ZZWFyTnVtYmVyID0gaXNvWWVhck51bWJlcjsKICAgICAgdGhpcy5pc29XZWVrTnVtYmVyID0gaXNvV2Vla051bWJlcjsKICAgICAgdGhpcy5jYWNoZSA9IGNhY2hlOwogICAgICB0aGlzLnR5cGUgPSAiWWVhcldlZWsiOwogICAgICB0aGlzLmRhdGVTdHJpbmcgPSB0aGlzLnRvU3RyaW5nKCk7CiAgICB9CiAgICBnZXQgdGV4dCgpIHsKICAgICAgcmV0dXJuIHRoaXMuZmlyc3REYXkuZGF5anMuZm9ybWF0KEZPUk1BVF9JU09fV0VFS19ZRUFSX1dFRUspOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLnRleHQ7CiAgICB9CiAgICBlbmdsaXNoTmFtZSgpIHsKICAgICAgcmV0dXJuIGBXZWVrICR7dGhpcy5pc29XZWVrTnVtYmVyfSwgJHt0aGlzLmlzb1llYXJOdW1iZXJ9YDsKICAgIH0KICAgIGdldCBmaXJzdERheSgpIHsKICAgICAgY29uc3QgZmlyc3REYXkgPSBkYXlqcygpLnllYXIodGhpcy5pc29ZZWFyTnVtYmVyKS5tb250aCgxKS5kYXRlKDQpLmlzb1dlZWsodGhpcy5pc29XZWVrTnVtYmVyKS5zdGFydE9mKCJpc29XZWVrIik7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aERheShmaXJzdERheS5mb3JtYXQoIllZWVktTU0tREQiKSk7CiAgICB9CiAgICBnZXQgbGFzdERheSgpIHsKICAgICAgY29uc3QgZmlyc3REYXkgPSBkYXlqcygpLnllYXIodGhpcy5pc29ZZWFyTnVtYmVyKS5zdGFydE9mKCJ5ZWFyIikuYWRkKCh0aGlzLmlzb1dlZWtOdW1iZXIgLSAxKSAqIDcsICJkYXkiKS5zdGFydE9mKCJ3ZWVrIikuYWRkKDEsICJkYXkiKTsKICAgICAgY29uc3QgbGFzdERheSA9IGZpcnN0RGF5LmFkZCg2LCAiZGF5Iik7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aERheShsYXN0RGF5LmZvcm1hdCgiWVlZWS1NTS1ERCIpKTsKICAgIH0KICAgIGdldCB5ZWFyKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyKGAke3RoaXMuaXNvWWVhck51bWJlcn1gKTsKICAgIH0KICAgIGFkZFdlZWtzKHdlZWtzKSB7CiAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLmZpcnN0RGF5LmRheWpzLmFkZCh3ZWVrcywgIndlZWsiKTsKICAgICAgY29uc3QgczIgPSBkYXRlLmZvcm1hdChGT1JNQVRfSVNPX1dFRUtfWUVBUl9XRUVLKTsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhcldlZWsoczIpOwogICAgfQogICAgbWludXMob3RoZXIpIHsKICAgICAgcmV0dXJuIHRoaXMuZmlyc3REYXkuZGF5anMuZGlmZihvdGhlci5maXJzdERheS5kYXlqcywgIndlZWsiKTsKICAgIH0KICAgIHN0YXRpYyBwYXJzZShzMiwgY2FjaGUpIHsKICAgICAgY29uc3QgW3llYXIsIHdlZWtdID0gczIuc3BsaXQoIi1XIikubWFwKChzMjIpID0+IHBhcnNlSW50KHMyMiwgMTApKTsKICAgICAgcmV0dXJuIG5ldyBZZWFyV2Vla0NsYXNzKHllYXIsIHdlZWssIGNhY2hlKTsKICAgIH0KICB9CiAgY2xhc3MgWWVhck1vbnRoQ2xhc3MgewogICAgY29uc3RydWN0b3IoeWVhck51bWJlciwgbW9udGhOdW1iZXIsIGNhY2hlKSB7CiAgICAgIHRoaXMueWVhck51bWJlciA9IHllYXJOdW1iZXI7CiAgICAgIHRoaXMubW9udGhOdW1iZXIgPSBtb250aE51bWJlcjsKICAgICAgdGhpcy5jYWNoZSA9IGNhY2hlOwogICAgICB0aGlzLnR5cGUgPSAiWWVhck1vbnRoIjsKICAgICAgdGhpcy5kYXRlU3RyaW5nID0gdGhpcy50b1N0cmluZygpOwogICAgfQogICAgZ2V0IHRleHQoKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmZvcm1hdCgiWVlZWS1NTSIpOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLnRleHQ7CiAgICB9CiAgICBlbmdsaXNoTmFtZSgpIHsKICAgICAgcmV0dXJuIGAke21vbnRoTmFtZSh0aGlzLm1vbnRoTnVtYmVyKX0gJHt0aGlzLnllYXJOdW1iZXJ9YDsKICAgIH0KICAgIGdldCBmaXJzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoRGF5KGRheWpzKGAke3RoaXMueWVhck51bWJlcn0tJHt0aGlzLm1vbnRoTnVtYmVyfS0wMWApLmZvcm1hdCgiWVlZWS1NTS1ERCIpKTsKICAgIH0KICAgIGdldCBsYXN0RGF5KCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGhEYXkoCiAgICAgICAgZGF5anMoYCR7dGhpcy55ZWFyTnVtYmVyfS0ke3RoaXMubW9udGhOdW1iZXJ9LTAxYCkuZW5kT2YoIm1vbnRoIikuZm9ybWF0KCJZWVlZLU1NLUREIikKICAgICAgKTsKICAgIH0KICAgIGdldCB5ZWFyKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyKGAke3RoaXMueWVhck51bWJlcn1gKTsKICAgIH0KICAgIGFkZE1vbnRocyhtb250aHMpIHsKICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuZmlyc3REYXkuZGF5anMuYWRkKG1vbnRocywgIm1vbnRoIik7CiAgICAgIGNvbnN0IHMyID0gZGF0ZS5mb3JtYXQoIllZWVktTU0iKTsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoKHMyKTsKICAgIH0KICAgIG1pbnVzKG90aGVyKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmRpZmYob3RoZXIuZmlyc3REYXkuZGF5anMsICJtb250aCIpOwogICAgfQogICAgc3RhdGljIHBhcnNlKHMyLCBjYWNoZSkgewogICAgICBjb25zdCBbeWVhciwgbW9udGhdID0gczIuc3BsaXQoIi0iKS5tYXAoKHMyMikgPT4gcGFyc2VJbnQoczIyLCAxMCkpOwogICAgICByZXR1cm4gbmV3IFllYXJNb250aENsYXNzKHllYXIsIG1vbnRoLCBjYWNoZSk7CiAgICB9CiAgfQogIGNsYXNzIFllYXJDbGFzcyB7CiAgICBjb25zdHJ1Y3Rvcih5ZWFyLCBjYWNoZSkgewogICAgICB0aGlzLnllYXIgPSB5ZWFyOwogICAgICB0aGlzLmNhY2hlID0gY2FjaGU7CiAgICAgIHRoaXMudHlwZSA9ICJZZWFyIjsKICAgICAgdGhpcy5kYXRlU3RyaW5nID0gdGhpcy50b1N0cmluZygpOwogICAgfQogICAgZ2V0IHRleHQoKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmZvcm1hdCgiWVlZWSIpOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLnRleHQ7CiAgICB9CiAgICBlbmdsaXNoTmFtZSgpIHsKICAgICAgcmV0dXJuIHRoaXMueWVhci50b1N0cmluZygpOwogICAgfQogICAgZ2V0IGZpcnN0TW9udGgoKSB7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aChgJHt0aGlzLnllYXJ9LTAxYCk7CiAgICB9CiAgICBnZXQgbGFzdE1vbnRoKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGgoYCR7dGhpcy55ZWFyfS0xMmApOwogICAgfQogICAgZ2V0IGZpcnN0RGF5KCkgewogICAgICByZXR1cm4gdGhpcy5maXJzdE1vbnRoLmZpcnN0RGF5OwogICAgfQogICAgZ2V0IGxhc3REYXkoKSB7CiAgICAgIHJldHVybiB0aGlzLmxhc3RNb250aC5sYXN0RGF5OwogICAgfQogICAgYWRkWWVhcnMoeWVhcnMpIHsKICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuZmlyc3REYXkuZGF5anMuYWRkKHllYXJzLCAieWVhciIpOwogICAgICBjb25zdCBzMiA9IGRhdGUuZm9ybWF0KCJZWVlZIik7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXIoczIpOwogICAgfQogICAgbWludXMob3RoZXIpIHsKICAgICAgcmV0dXJuIHRoaXMuZmlyc3REYXkuZGF5anMuZGlmZihvdGhlci5maXJzdERheS5kYXlqcywgInllYXIiKTsKICAgIH0KICAgIHN0YXRpYyBwYXJzZShzMiwgY2FjaGUpIHsKICAgICAgY29uc3QgeWVhciA9IHBhcnNlSW50KHMyLCAxMCk7CiAgICAgIHJldHVybiBuZXcgWWVhckNsYXNzKHllYXIsIGNhY2hlKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gbW9udGhOYW1lKG1vbnRoKSB7CiAgICByZXR1cm4gZGF5anMoKS5tb250aChtb250aCAtIDEpLmZvcm1hdCgiTU1NTSIpOwogIH0KICBmdW5jdGlvbiB0b1RlbXBvcmFsKHRlbXBvcmFsQ2xhc3MpIHsKICAgIHN3aXRjaCAodGVtcG9yYWxDbGFzcy50eXBlKSB7CiAgICAgIGNhc2UgIlllYXJNb250aERheSI6CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHR5cGU6ICJZZWFyTW9udGhEYXkiLAogICAgICAgICAgeWVhck51bWJlcjogdGVtcG9yYWxDbGFzcy55ZWFyTnVtYmVyLAogICAgICAgICAgbW9udGhOdW1iZXI6IHRlbXBvcmFsQ2xhc3MubW9udGhOdW1iZXIsCiAgICAgICAgICBkYXlOdW1iZXI6IHRlbXBvcmFsQ2xhc3MuZGF5TnVtYmVyLAogICAgICAgICAgZGF0ZVN0cmluZzogdGVtcG9yYWxDbGFzcy5kYXRlU3RyaW5nCiAgICAgICAgfTsKICAgICAgY2FzZSAiWWVhcldlZWsiOgogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiAiWWVhcldlZWsiLAogICAgICAgICAgaXNvWWVhck51bWJlcjogdGVtcG9yYWxDbGFzcy5pc29ZZWFyTnVtYmVyLAogICAgICAgICAgaXNvV2Vla051bWJlcjogdGVtcG9yYWxDbGFzcy5pc29XZWVrTnVtYmVyLAogICAgICAgICAgZGF0ZVN0cmluZzogdGVtcG9yYWxDbGFzcy5kYXRlU3RyaW5nCiAgICAgICAgfTsKICAgICAgY2FzZSAiWWVhck1vbnRoIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogIlllYXJNb250aCIsCiAgICAgICAgICB5ZWFyTnVtYmVyOiB0ZW1wb3JhbENsYXNzLnllYXJOdW1iZXIsCiAgICAgICAgICBtb250aE51bWJlcjogdGVtcG9yYWxDbGFzcy5tb250aE51bWJlciwKICAgICAgICAgIGRhdGVTdHJpbmc6IHRlbXBvcmFsQ2xhc3MuZGF0ZVN0cmluZwogICAgICAgIH07CiAgICAgIGNhc2UgIlllYXIiOgogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiAiWWVhciIsCiAgICAgICAgICB5ZWFyOiB0ZW1wb3JhbENsYXNzLnllYXIsCiAgICAgICAgICBkYXRlU3RyaW5nOiB0ZW1wb3JhbENsYXNzLmRhdGVTdHJpbmcKICAgICAgICB9OwogICAgfQogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZUFsbERheXNJblJhbmdlKHN0YXJ0LCBlbmQpIHsKICAgIGNvbnN0IGRheXMgPSBbXTsKICAgIGNvbnN0IGRheXNJbkJldHdlZW4gPSBlbmQubWludXMoc3RhcnQpOwogICAgZm9yIChsZXQgaTIgPSAwOyBpMiA8PSBkYXlzSW5CZXR3ZWVuOyBpMisrKSB7CiAgICAgIGRheXMucHVzaChzdGFydC5hZGREYXlzKGkyKSk7CiAgICB9CiAgICByZXR1cm4gZGF5czsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVBbGxXZWVrc0luUmFuZ2Uoc3RhcnQsIGVuZCkgewogICAgY29uc3Qgd2Vla3MgPSBbXTsKICAgIGNvbnN0IHdlZWtzSW5CZXR3ZWVuID0gZW5kLm1pbnVzKHN0YXJ0KTsKICAgIGZvciAobGV0IGkyID0gMDsgaTIgPD0gd2Vla3NJbkJldHdlZW47IGkyKyspIHsKICAgICAgd2Vla3MucHVzaChzdGFydC5hZGRXZWVrcyhpMikpOwogICAgfQogICAgcmV0dXJuIHdlZWtzOwogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZUFsbE1vbnRoc0luUmFuZ2Uoc3RhcnQsIGVuZCkgewogICAgY29uc3QgbW9udGhzID0gW107CiAgICBjb25zdCBtb250aHNJbkJldHdlZW4gPSBlbmQubWludXMoc3RhcnQpOwogICAgZm9yIChsZXQgaTIgPSAwOyBpMiA8PSBtb250aHNJbkJldHdlZW47IGkyKyspIHsKICAgICAgbW9udGhzLnB1c2goc3RhcnQuYWRkTW9udGhzKGkyKSk7CiAgICB9CiAgICByZXR1cm4gbW9udGhzOwogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZUFsbFllYXJzSW5SYW5nZShzdGFydCwgZW5kKSB7CiAgICBjb25zdCB5ZWFycyA9IFtdOwogICAgY29uc3QgeWVhcnNJbkJldHdlZW4gPSBlbmQubWludXMoc3RhcnQpOwogICAgZm9yIChsZXQgaTIgPSAwOyBpMiA8PSB5ZWFyc0luQmV0d2VlbjsgaTIrKykgewogICAgICB5ZWFycy5wdXNoKHN0YXJ0LmFkZFllYXJzKGkyKSk7CiAgICB9CiAgICByZXR1cm4geWVhcnM7CiAgfQogIGZ1bmN0aW9uIGdlbmVyYXRlQWxsSW5SYW5nZShzdGFydCwgZW5kKSB7CiAgICBpZiAoc3RhcnQgPT09IG51bGwgfHwgZW5kID09PSBudWxsKSB7CiAgICAgIHJldHVybiBbXTsKICAgIH0KICAgIGlmIChzdGFydCBpbnN0YW5jZW9mIFllYXJNb250aERheUNsYXNzICYmIGVuZCBpbnN0YW5jZW9mIFllYXJNb250aERheUNsYXNzKSB7CiAgICAgIHJldHVybiBnZW5lcmF0ZUFsbERheXNJblJhbmdlKHN0YXJ0LCBlbmQpOwogICAgfQogICAgaWYgKHN0YXJ0IGluc3RhbmNlb2YgWWVhcldlZWtDbGFzcyAmJiBlbmQgaW5zdGFuY2VvZiBZZWFyV2Vla0NsYXNzKSB7CiAgICAgIHJldHVybiBnZW5lcmF0ZUFsbFdlZWtzSW5SYW5nZShzdGFydCwgZW5kKTsKICAgIH0KICAgIGlmIChzdGFydCBpbnN0YW5jZW9mIFllYXJNb250aENsYXNzICYmIGVuZCBpbnN0YW5jZW9mIFllYXJNb250aENsYXNzKSB7CiAgICAgIHJldHVybiBnZW5lcmF0ZUFsbE1vbnRoc0luUmFuZ2Uoc3RhcnQsIGVuZCk7CiAgICB9CiAgICBpZiAoc3RhcnQgaW5zdGFuY2VvZiBZZWFyQ2xhc3MgJiYgZW5kIGluc3RhbmNlb2YgWWVhckNsYXNzKSB7CiAgICAgIHJldHVybiBnZW5lcmF0ZUFsbFllYXJzSW5SYW5nZShzdGFydCwgZW5kKTsKICAgIH0KICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBhcmd1bWVudHM6IHN0YXJ0IGFuZCBlbmQgbXVzdCBiZSBvZiB0aGUgc2FtZSB0eXBlOiAke3N0YXJ0fSwgJHtlbmR9YCk7CiAgfQogIGZ1bmN0aW9uIG1pbnVzVGVtcG9yYWwoYTIsIGIpIHsKICAgIGlmIChhMiBpbnN0YW5jZW9mIFllYXJNb250aERheUNsYXNzICYmIGIgaW5zdGFuY2VvZiBZZWFyTW9udGhEYXlDbGFzcykgewogICAgICByZXR1cm4gYTIubWludXMoYik7CiAgICB9CiAgICBpZiAoYTIgaW5zdGFuY2VvZiBZZWFyV2Vla0NsYXNzICYmIGIgaW5zdGFuY2VvZiBZZWFyV2Vla0NsYXNzKSB7CiAgICAgIHJldHVybiBhMi5taW51cyhiKTsKICAgIH0KICAgIGlmIChhMiBpbnN0YW5jZW9mIFllYXJNb250aENsYXNzICYmIGIgaW5zdGFuY2VvZiBZZWFyTW9udGhDbGFzcykgewogICAgICByZXR1cm4gYTIubWludXMoYik7CiAgICB9CiAgICBpZiAoYTIgaW5zdGFuY2VvZiBZZWFyQ2xhc3MgJiYgYiBpbnN0YW5jZW9mIFllYXJDbGFzcykgewogICAgICByZXR1cm4gYTIubWludXMoYik7CiAgICB9CiAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBjb21wYXJlICR7YTJ9IGFuZCAke2J9YCk7CiAgfQogIGZ1bmN0aW9uIGNvbXBhcmVUZW1wb3JhbChhMiwgYikgewogICAgaWYgKGEyID09PSBudWxsKSB7CiAgICAgIHJldHVybiAxOwogICAgfQogICAgaWYgKGIgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgY29uc3QgZGlmZiA9IG1pbnVzVGVtcG9yYWwoYTIsIGIpOwogICAgaWYgKGRpZmYgPCAwKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGlmIChkaWZmID4gMCkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIHJldHVybiAwOwogIH0KICBmdW5jdGlvbiBnZXRNaW5NYXhUZW1wb3JhbCh2YWx1ZXMpIHsKICAgIGxldCBtaW4gPSBudWxsOwogICAgbGV0IG1heCA9IG51bGw7CiAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIHZhbHVlcykgewogICAgICBpZiAodmFsdWUgPT09IG51bGwpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAobWluID09PSBudWxsIHx8IGNvbXBhcmVUZW1wb3JhbCh2YWx1ZSwgbWluKSA8IDApIHsKICAgICAgICBtaW4gPSB2YWx1ZTsKICAgICAgfQogICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNvbXBhcmVUZW1wb3JhbCh2YWx1ZSwgbWF4KSA+IDApIHsKICAgICAgICBtYXggPSB2YWx1ZTsKICAgICAgfQogICAgfQogICAgaWYgKG1pbiA9PT0gbnVsbCB8fCBtYXggPT09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgbWluOiBudWxsLCBtYXg6IG51bGwgfTsKICAgIH0KICAgIHJldHVybiB7IG1pbiwgbWF4IH07CiAgfQogIGZ1bmN0aW9uIHBhcnNlRGF0ZVN0cmluZ1RvVGVtcG9yYWwoZGF0ZSwgZ3JhbnVsYXJpdHkpIHsKICAgIGNvbnN0IGNhY2hlID0gVGVtcG9yYWxDYWNoZS5nZXRJbnN0YW5jZSgpOwogICAgY29uc3QgZGF5ID0gY2FjaGUuZ2V0WWVhck1vbnRoRGF5KGRhdGUpOwogICAgc3dpdGNoIChncmFudWxhcml0eSkgewogICAgICBjYXNlICJkYXkiOgogICAgICAgIHJldHVybiBkYXk7CiAgICAgIGNhc2UgIndlZWsiOgogICAgICAgIHJldHVybiBkYXkud2VlazsKICAgICAgY2FzZSAibW9udGgiOgogICAgICAgIHJldHVybiBkYXkubW9udGg7CiAgICAgIGNhc2UgInllYXIiOgogICAgICAgIHJldHVybiBkYXkueWVhcjsKICAgIH0KICB9CiAgZnVuY3Rpb24gZGF0ZVJhbmdlQ29tcGFyZShhMiwgYikgewogICAgaWYgKGEyLmRhdGVSYW5nZSA9PT0gbnVsbCkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIGlmIChiLmRhdGVSYW5nZSA9PT0gbnVsbCkgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICByZXR1cm4gY29tcGFyZVRlbXBvcmFsKGEyLmRhdGVSYW5nZSwgYi5kYXRlUmFuZ2UpOwogIH0KICBmdW5jdGlvbiBtYXBEYXRlVG9HcmFudWxhcml0eVJhbmdlKGRhdGEsIGdyYW51bGFyaXR5KSB7CiAgICByZXR1cm4gewogICAgICBkYXRlUmFuZ2U6IGRhdGEuZGF0ZSA9PT0gbnVsbCA/IG51bGwgOiBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKGRhdGEuZGF0ZSwgZ3JhbnVsYXJpdHkpLAogICAgICBjb3VudDogZGF0YS5jb3VudAogICAgfTsKICB9CiAgY29uc3Qgc3Vic3RpdHV0aW9uUmVnZXggPSAvXigoPzxzZWdtZW50PltBLVowLTlfLV0rKSg/PTopOik/KD88dmFsdWVBdFJlZmVyZW5jZT5bQS1aXSk/KD88cG9zaXRpb24+XGQrKSg/PHN1YnN0aXR1dGlvblZhbHVlPltBLVouXSk/JC9pOwogIGNsYXNzIFN1YnN0aXR1dGlvbkNsYXNzIHsKICAgIGNvbnN0cnVjdG9yKHNlZ21lbnQsIHZhbHVlQXRSZWZlcmVuY2UsIHN1YnN0aXR1dGlvblZhbHVlLCBwb3NpdGlvbikgewogICAgICB0aGlzLnNlZ21lbnQgPSBzZWdtZW50OwogICAgICB0aGlzLnZhbHVlQXRSZWZlcmVuY2UgPSB2YWx1ZUF0UmVmZXJlbmNlOwogICAgICB0aGlzLnN1YnN0aXR1dGlvblZhbHVlID0gc3Vic3RpdHV0aW9uVmFsdWU7CiAgICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjsKICAgICAgdGhpcy50eXBlID0gInN1YnN0aXR1dGlvbiI7CiAgICAgIGNvbnN0IHNlZ21lbnRTdHJpbmcgPSB0aGlzLnNlZ21lbnQgPyBgJHt0aGlzLnNlZ21lbnR9OmAgOiAiIjsKICAgICAgY29uc3QgdmFsdWVBdFJlZmVyZW5jZVN0cmluZyA9IHRoaXMudmFsdWVBdFJlZmVyZW5jZSA/IGAke3RoaXMudmFsdWVBdFJlZmVyZW5jZX1gIDogIiI7CiAgICAgIGNvbnN0IHN1YnN0aXR1dGlvblZhbHVlU3RyaW5nID0gdGhpcy5zdWJzdGl0dXRpb25WYWx1ZSA/IGAke3RoaXMuc3Vic3RpdHV0aW9uVmFsdWV9YCA6ICIiOwogICAgICB0aGlzLmNvZGUgPSBgJHtzZWdtZW50U3RyaW5nfSR7dmFsdWVBdFJlZmVyZW5jZVN0cmluZ30ke3RoaXMucG9zaXRpb259JHtzdWJzdGl0dXRpb25WYWx1ZVN0cmluZ31gOwogICAgfQogICAgZXF1YWxzKG90aGVyKSB7CiAgICAgIGlmICghKG90aGVyIGluc3RhbmNlb2YgU3Vic3RpdHV0aW9uQ2xhc3MpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnNlZ21lbnQgPT09IG90aGVyLnNlZ21lbnQgJiYgdGhpcy52YWx1ZUF0UmVmZXJlbmNlID09PSBvdGhlci52YWx1ZUF0UmVmZXJlbmNlICYmIHRoaXMuc3Vic3RpdHV0aW9uVmFsdWUgPT09IG90aGVyLnN1YnN0aXR1dGlvblZhbHVlICYmIHRoaXMucG9zaXRpb24gPT09IG90aGVyLnBvc2l0aW9uOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLmNvZGU7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UobXV0YXRpb25TdHIpIHsKICAgICAgY29uc3QgbWF0Y2ggPSBtdXRhdGlvblN0ci5tYXRjaChzdWJzdGl0dXRpb25SZWdleCk7CiAgICAgIGlmIChtYXRjaCA9PT0gbnVsbCB8fCBtYXRjaC5ncm91cHMgPT09IHZvaWQgMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHJldHVybiBuZXcgU3Vic3RpdHV0aW9uQ2xhc3MoCiAgICAgICAgbWF0Y2guZ3JvdXBzLnNlZ21lbnQsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnZhbHVlQXRSZWZlcmVuY2UsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnN1YnN0aXR1dGlvblZhbHVlLAogICAgICAgIHBhcnNlSW50KG1hdGNoLmdyb3Vwcy5wb3NpdGlvbiwgMTApCiAgICAgICk7CiAgICB9CiAgfQogIGNvbnN0IGRlbGV0aW9uUmVnZXggPSAvXigoPzxzZWdtZW50PltBLVowLTlfLV0rKSg/PTopOik/KD88dmFsdWVBdFJlZmVyZW5jZT5bQS1aXSk/KD88cG9zaXRpb24+XGQrKSgtKSQvaTsKICBjbGFzcyBEZWxldGlvbkNsYXNzIHsKICAgIGNvbnN0cnVjdG9yKHNlZ21lbnQsIHZhbHVlQXRSZWZlcmVuY2UsIHBvc2l0aW9uKSB7CiAgICAgIHRoaXMuc2VnbWVudCA9IHNlZ21lbnQ7CiAgICAgIHRoaXMudmFsdWVBdFJlZmVyZW5jZSA9IHZhbHVlQXRSZWZlcmVuY2U7CiAgICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjsKICAgICAgdGhpcy50eXBlID0gImRlbGV0aW9uIjsKICAgICAgY29uc3Qgc2VnbWVudFN0cmluZyA9IHRoaXMuc2VnbWVudCA/IGAke3RoaXMuc2VnbWVudH06YCA6ICIiOwogICAgICBjb25zdCB2YWx1ZUF0UmVmZXJlbmNlU3RyaW5nID0gdGhpcy52YWx1ZUF0UmVmZXJlbmNlID8gYCR7dGhpcy52YWx1ZUF0UmVmZXJlbmNlfWAgOiAiIjsKICAgICAgdGhpcy5jb2RlID0gYCR7c2VnbWVudFN0cmluZ30ke3ZhbHVlQXRSZWZlcmVuY2VTdHJpbmd9JHt0aGlzLnBvc2l0aW9ufS1gOwogICAgfQogICAgZXF1YWxzKG90aGVyKSB7CiAgICAgIGlmICghKG90aGVyIGluc3RhbmNlb2YgRGVsZXRpb25DbGFzcykpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuc2VnbWVudCA9PT0gb3RoZXIuc2VnbWVudCAmJiB0aGlzLnZhbHVlQXRSZWZlcmVuY2UgPT09IG90aGVyLnZhbHVlQXRSZWZlcmVuY2UgJiYgdGhpcy5wb3NpdGlvbiA9PT0gb3RoZXIucG9zaXRpb247CiAgICB9CiAgICB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMuY29kZTsKICAgIH0KICAgIHN0YXRpYyBwYXJzZShtdXRhdGlvblN0cikgewogICAgICBjb25zdCBtYXRjaCA9IG11dGF0aW9uU3RyLm1hdGNoKGRlbGV0aW9uUmVnZXgpOwogICAgICBpZiAobWF0Y2ggPT09IG51bGwgfHwgbWF0Y2guZ3JvdXBzID09PSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICByZXR1cm4gbmV3IERlbGV0aW9uQ2xhc3MoCiAgICAgICAgbWF0Y2guZ3JvdXBzLnNlZ21lbnQsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnZhbHVlQXRSZWZlcmVuY2UsCiAgICAgICAgcGFyc2VJbnQobWF0Y2guZ3JvdXBzLnBvc2l0aW9uLCAxMCkKICAgICAgKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gdG9TdWJzdGl0dXRpb25PckRlbGV0aW9uKG11dGF0aW9uKSB7CiAgICBzd2l0Y2ggKG11dGF0aW9uLnR5cGUpIHsKICAgICAgY2FzZSAic3Vic3RpdHV0aW9uIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogInN1YnN0aXR1dGlvbiIsCiAgICAgICAgICBjb2RlOiBtdXRhdGlvbi5jb2RlLAogICAgICAgICAgc2VnbWVudDogbXV0YXRpb24uc2VnbWVudCwKICAgICAgICAgIHBvc2l0aW9uOiBtdXRhdGlvbi5wb3NpdGlvbiwKICAgICAgICAgIHZhbHVlQXRSZWZlcmVuY2U6IG11dGF0aW9uLnZhbHVlQXRSZWZlcmVuY2UsCiAgICAgICAgICBzdWJzdGl0dXRpb25WYWx1ZTogbXV0YXRpb24uc3Vic3RpdHV0aW9uVmFsdWUKICAgICAgICB9OwogICAgICBjYXNlICJkZWxldGlvbiI6CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHR5cGU6ICJkZWxldGlvbiIsCiAgICAgICAgICBjb2RlOiBtdXRhdGlvbi5jb2RlLAogICAgICAgICAgc2VnbWVudDogbXV0YXRpb24uc2VnbWVudCwKICAgICAgICAgIHBvc2l0aW9uOiBtdXRhdGlvbi5wb3NpdGlvbiwKICAgICAgICAgIHZhbHVlQXRSZWZlcmVuY2U6IG11dGF0aW9uLnZhbHVlQXRSZWZlcmVuY2UKICAgICAgICB9OwogICAgfQogIH0KICBjbGFzcyBGZXRjaFN1YnN0aXR1dGlvbnNPckRlbGV0aW9uc09wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGZpbHRlciwgc2VxdWVuY2VUeXBlLCBtaW5Qcm9wb3J0aW9uKSB7CiAgICAgIHRoaXMuZmlsdGVyID0gZmlsdGVyOwogICAgICB0aGlzLnNlcXVlbmNlVHlwZSA9IHNlcXVlbmNlVHlwZTsKICAgICAgdGhpcy5taW5Qcm9wb3J0aW9uID0gbWluUHJvcG9ydGlvbjsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzLCBzaWduYWwpIHsKICAgICAgY29uc3QgbXV0YXRpb25zID0gYXdhaXQgdGhpcy5mZXRjaE11dGF0aW9ucyhsYXBpcywgc2lnbmFsKTsKICAgICAgY29uc3QgY29udGVudCA9IG11dGF0aW9ucy5tYXAoCiAgICAgICAgKHsgY291bnQsIHByb3BvcnRpb24sIG11dGF0aW9uRnJvbSwgbXV0YXRpb25UbywgcG9zaXRpb24sIHNlcXVlbmNlTmFtZSB9KSA9PiB7CiAgICAgICAgICBpZiAobXV0YXRpb25UbyA9PT0gIi0iKSB7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgdHlwZTogImRlbGV0aW9uIiwKICAgICAgICAgICAgICBtdXRhdGlvbjogbmV3IERlbGV0aW9uQ2xhc3Moc2VxdWVuY2VOYW1lID8/IHZvaWQgMCwgbXV0YXRpb25Gcm9tLCBwb3NpdGlvbiksCiAgICAgICAgICAgICAgY291bnQsCiAgICAgICAgICAgICAgcHJvcG9ydGlvbgogICAgICAgICAgICB9OwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgdHlwZTogInN1YnN0aXR1dGlvbiIsCiAgICAgICAgICAgIG11dGF0aW9uOiBuZXcgU3Vic3RpdHV0aW9uQ2xhc3Moc2VxdWVuY2VOYW1lID8/IHZvaWQgMCwgbXV0YXRpb25Gcm9tLCBtdXRhdGlvblRvLCBwb3NpdGlvbiksCiAgICAgICAgICAgIGNvdW50LAogICAgICAgICAgICBwcm9wb3J0aW9uCiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgKTsKICAgICAgcmV0dXJuIHsgY29udGVudCB9OwogICAgfQogICAgYXN5bmMgZmV0Y2hNdXRhdGlvbnMobGFwaXMsIHNpZ25hbCkgewogICAgICBjb25zdCBmaWx0ZXIgPSB7CiAgICAgICAgLi4udGhpcy5maWx0ZXIsCiAgICAgICAgbWluUHJvcG9ydGlvbjogdGhpcy5taW5Qcm9wb3J0aW9uCiAgICAgIH07CiAgICAgIHJldHVybiBmZXRjaFN1YnN0aXR1dGlvbnNPckRlbGV0aW9ucyhsYXBpcywgZmlsdGVyLCB0aGlzLnNlcXVlbmNlVHlwZSwgc2lnbmFsKS50aGVuKAogICAgICAgIChyZXNwb25zZSkgPT4gcmVzcG9uc2UuZGF0YQogICAgICApOwogICAgfQogIH0KICB2YXIgbCQxOwogIGwkMSA9IHsgX19lOiBmdW5jdGlvbihuLCBsMiwgdTIsIHQpIHsKICAgIGZvciAodmFyIGkyLCBvLCByMjsgbDIgPSBsMi5fXzsgKSBpZiAoKGkyID0gbDIuX19jKSAmJiAhaTIuX18pIHRyeSB7CiAgICAgIGlmICgobyA9IGkyLmNvbnN0cnVjdG9yKSAmJiBudWxsICE9IG8uZ2V0RGVyaXZlZFN0YXRlRnJvbUVycm9yICYmIChpMi5zZXRTdGF0ZShvLmdldERlcml2ZWRTdGF0ZUZyb21FcnJvcihuKSksIHIyID0gaTIuX19kKSwgbnVsbCAhPSBpMi5jb21wb25lbnREaWRDYXRjaCAmJiAoaTIuY29tcG9uZW50RGlkQ2F0Y2gobiwgdCB8fCB7fSksIHIyID0gaTIuX19kKSwgcjIpIHJldHVybiBpMi5fX0UgPSBpMjsKICAgIH0gY2F0Y2ggKGwzKSB7CiAgICAgIG4gPSBsMzsKICAgIH0KICAgIHRocm93IG47CiAgfSB9LCAiZnVuY3Rpb24iID09IHR5cGVvZiBQcm9taXNlID8gUHJvbWlzZS5wcm90b3R5cGUudGhlbi5iaW5kKFByb21pc2UucmVzb2x2ZSgpKSA6IHNldFRpbWVvdXQ7CiAgdmFyIHIsIHUsIGksIGYgPSBbXSwgYyA9IGwkMSwgZSA9IGMuX19iLCBhID0gYy5fX3IsIHYgPSBjLmRpZmZlZCwgbCA9IGMuX19jLCBtID0gYy51bm1vdW50LCBzID0gYy5fXzsKICBmdW5jdGlvbiBqKCkgewogICAgZm9yICh2YXIgbjsgbiA9IGYuc2hpZnQoKTsgKSBpZiAobi5fX1AgJiYgbi5fX0gpIHRyeSB7CiAgICAgIG4uX19ILl9faC5mb3JFYWNoKHopLCBuLl9fSC5fX2guZm9yRWFjaChCKSwgbi5fX0guX19oID0gW107CiAgICB9IGNhdGNoICh0KSB7CiAgICAgIG4uX19ILl9faCA9IFtdLCBjLl9fZSh0LCBuLl9fdik7CiAgICB9CiAgfQogIGMuX19iID0gZnVuY3Rpb24obikgewogICAgciA9IG51bGwsIGUgJiYgZShuKTsKICB9LCBjLl9fID0gZnVuY3Rpb24obiwgdCkgewogICAgbiAmJiB0Ll9fayAmJiB0Ll9fay5fX20gJiYgKG4uX19tID0gdC5fX2suX19tKSwgcyAmJiBzKG4sIHQpOwogIH0sIGMuX19yID0gZnVuY3Rpb24obikgewogICAgYSAmJiBhKG4pOwogICAgdmFyIGkyID0gKHIgPSBuLl9fYykuX19IOwogICAgaTIgJiYgKHUgPT09IHIgPyAoaTIuX19oID0gW10sIHIuX19oID0gW10sIGkyLl9fLmZvckVhY2goZnVuY3Rpb24objIpIHsKICAgICAgbjIuX19OICYmIChuMi5fXyA9IG4yLl9fTiksIG4yLmkgPSBuMi5fX04gPSB2b2lkIDA7CiAgICB9KSkgOiAoaTIuX19oLmZvckVhY2goeiksIGkyLl9faC5mb3JFYWNoKEIpLCBpMi5fX2ggPSBbXSwgMCkpLCB1ID0gcjsKICB9LCBjLmRpZmZlZCA9IGZ1bmN0aW9uKG4pIHsKICAgIHYgJiYgdihuKTsKICAgIHZhciB0ID0gbi5fX2M7CiAgICB0ICYmIHQuX19IICYmICh0Ll9fSC5fX2gubGVuZ3RoICYmICgxICE9PSBmLnB1c2godCkgJiYgaSA9PT0gYy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHwgKChpID0gYy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUpIHx8IHcpKGopKSwgdC5fX0guX18uZm9yRWFjaChmdW5jdGlvbihuMikgewogICAgICBuMi5pICYmIChuMi5fX0ggPSBuMi5pKSwgbjIuaSA9IHZvaWQgMDsKICAgIH0pKSwgdSA9IHIgPSBudWxsOwogIH0sIGMuX19jID0gZnVuY3Rpb24obiwgdCkgewogICAgdC5zb21lKGZ1bmN0aW9uKG4yKSB7CiAgICAgIHRyeSB7CiAgICAgICAgbjIuX19oLmZvckVhY2goeiksIG4yLl9faCA9IG4yLl9faC5maWx0ZXIoZnVuY3Rpb24objMpIHsKICAgICAgICAgIHJldHVybiAhbjMuX18gfHwgQihuMyk7CiAgICAgICAgfSk7CiAgICAgIH0gY2F0Y2ggKHIyKSB7CiAgICAgICAgdC5zb21lKGZ1bmN0aW9uKG4zKSB7CiAgICAgICAgICBuMy5fX2ggJiYgKG4zLl9faCA9IFtdKTsKICAgICAgICB9KSwgdCA9IFtdLCBjLl9fZShyMiwgbjIuX192KTsKICAgICAgfQogICAgfSksIGwgJiYgbChuLCB0KTsKICB9LCBjLnVubW91bnQgPSBmdW5jdGlvbihuKSB7CiAgICBtICYmIG0obik7CiAgICB2YXIgdCwgcjIgPSBuLl9fYzsKICAgIHIyICYmIHIyLl9fSCAmJiAocjIuX19ILl9fLmZvckVhY2goZnVuY3Rpb24objIpIHsKICAgICAgdHJ5IHsKICAgICAgICB6KG4yKTsKICAgICAgfSBjYXRjaCAobjMpIHsKICAgICAgICB0ID0gbjM7CiAgICAgIH0KICAgIH0pLCByMi5fX0ggPSB2b2lkIDAsIHQgJiYgYy5fX2UodCwgcjIuX192KSk7CiAgfTsKICB2YXIgayA9ICJmdW5jdGlvbiIgPT0gdHlwZW9mIHJlcXVlc3RBbmltYXRpb25GcmFtZTsKICBmdW5jdGlvbiB3KG4pIHsKICAgIHZhciB0LCByMiA9IGZ1bmN0aW9uKCkgewogICAgICBjbGVhclRpbWVvdXQodTIpLCBrICYmIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHQpLCBzZXRUaW1lb3V0KG4pOwogICAgfSwgdTIgPSBzZXRUaW1lb3V0KHIyLCAxMDApOwogICAgayAmJiAodCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZShyMikpOwogIH0KICBmdW5jdGlvbiB6KG4pIHsKICAgIHZhciB0ID0gciwgdTIgPSBuLl9fYzsKICAgICJmdW5jdGlvbiIgPT0gdHlwZW9mIHUyICYmIChuLl9fYyA9IHZvaWQgMCwgdTIoKSksIHIgPSB0OwogIH0KICBmdW5jdGlvbiBCKG4pIHsKICAgIHZhciB0ID0gcjsKICAgIG4uX19jID0gbi5fXygpLCByID0gdDsKICB9CiAgY2xhc3MgVXNlckZhY2luZ0Vycm9yIGV4dGVuZHMgRXJyb3IgewogICAgY29uc3RydWN0b3IoaGVhZGxpbmUsIG1lc3NhZ2UpIHsKICAgICAgc3VwZXIobWVzc2FnZSk7CiAgICAgIHRoaXMuaGVhZGxpbmUgPSBoZWFkbGluZTsKICAgICAgdGhpcy5uYW1lID0gIlVzZXJGYWNpbmdFcnJvciI7CiAgICB9CiAgfQogIGNsYXNzIE1hcDJkQmFzZSB7CiAgICBjb25zdHJ1Y3RvcihzZXJpYWxpemVGaXJzdEF4aXMsIHNlcmlhbGl6ZVNlY29uZEF4aXMsIGluaXRpYWxDb250ZW50KSB7CiAgICAgIHRoaXMuc2VyaWFsaXplRmlyc3RBeGlzID0gc2VyaWFsaXplRmlyc3RBeGlzOwogICAgICB0aGlzLnNlcmlhbGl6ZVNlY29uZEF4aXMgPSBzZXJpYWxpemVTZWNvbmRBeGlzOwogICAgICB0aGlzLmRhdGEgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLmtleXNGaXJzdEF4aXMgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLmtleXNTZWNvbmRBeGlzID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgaWYgKGluaXRpYWxDb250ZW50KSB7CiAgICAgICAgdGhpcy5rZXlzRmlyc3RBeGlzID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5rZXlzRmlyc3RBeGlzKTsKICAgICAgICB0aGlzLmtleXNTZWNvbmRBeGlzID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5rZXlzU2Vjb25kQXhpcyk7CiAgICAgICAgdGhpcy5kYXRhID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5kYXRhKTsKICAgICAgfQogICAgfQogICAgZ2V0KGtleUZpcnN0QXhpcywga2V5U2Vjb25kQXhpcykgewogICAgICB2YXIgX2E7CiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMgPSB0aGlzLnNlcmlhbGl6ZUZpcnN0QXhpcyhrZXlGaXJzdEF4aXMpOwogICAgICBjb25zdCBzZXJpYWxpemVkS2V5U2Vjb25kQXhpcyA9IHRoaXMuc2VyaWFsaXplU2Vjb25kQXhpcyhrZXlTZWNvbmRBeGlzKTsKICAgICAgcmV0dXJuIChfYSA9IHRoaXMuZGF0YS5nZXQoc2VyaWFsaXplZEtleUZpcnN0QXhpcykpID09IG51bGwgPyB2b2lkIDAgOiBfYS5nZXQoc2VyaWFsaXplZEtleVNlY29uZEF4aXMpOwogICAgfQogICAgZ2V0Um93KGtleSkgewogICAgICBjb25zdCBzZXJpYWxpemVkS2V5Rmlyc3RBeGlzID0gdGhpcy5zZXJpYWxpemVGaXJzdEF4aXMoa2V5KTsKICAgICAgY29uc3Qgcm93ID0gdGhpcy5kYXRhLmdldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKTsKICAgICAgaWYgKHJvdyA9PT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIFtdOwogICAgICB9CiAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMua2V5c1NlY29uZEF4aXMua2V5cygpKS5tYXAoKGtleTIpID0+IHJvdy5nZXQoa2V5MikpOwogICAgfQogICAgc2V0KGtleUZpcnN0QXhpcywga2V5U2Vjb25kQXhpcywgdmFsdWUpIHsKICAgICAgY29uc3Qgc2VyaWFsaXplZEtleUZpcnN0QXhpcyA9IHRoaXMuc2VyaWFsaXplRmlyc3RBeGlzKGtleUZpcnN0QXhpcyk7CiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRLZXlTZWNvbmRBeGlzID0gdGhpcy5zZXJpYWxpemVTZWNvbmRBeGlzKGtleVNlY29uZEF4aXMpOwogICAgICBpZiAoIXRoaXMuZGF0YS5oYXMoc2VyaWFsaXplZEtleUZpcnN0QXhpcykpIHsKICAgICAgICB0aGlzLmRhdGEuc2V0KHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMsIC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCkpOwogICAgICB9CiAgICAgIHRoaXMuZGF0YS5nZXQoc2VyaWFsaXplZEtleUZpcnN0QXhpcykuc2V0KHNlcmlhbGl6ZWRLZXlTZWNvbmRBeGlzLCB2YWx1ZSk7CiAgICAgIHRoaXMua2V5c0ZpcnN0QXhpcy5zZXQoc2VyaWFsaXplZEtleUZpcnN0QXhpcywga2V5Rmlyc3RBeGlzKTsKICAgICAgdGhpcy5rZXlzU2Vjb25kQXhpcy5zZXQoc2VyaWFsaXplZEtleVNlY29uZEF4aXMsIGtleVNlY29uZEF4aXMpOwogICAgfQogICAgZGVsZXRlUm93KGtleSkgewogICAgICBjb25zdCBzZXJpYWxpemVkS2V5Rmlyc3RBeGlzID0gdGhpcy5zZXJpYWxpemVGaXJzdEF4aXMoa2V5KTsKICAgICAgdGhpcy5kYXRhLmRlbGV0ZShzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKTsKICAgICAgdGhpcy5rZXlzRmlyc3RBeGlzLmRlbGV0ZShzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKTsKICAgIH0KICAgIGdldEZpcnN0QXhpc0tleXMoKSB7CiAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMua2V5c0ZpcnN0QXhpcy52YWx1ZXMoKSk7CiAgICB9CiAgICBnZXRTZWNvbmRBeGlzS2V5cygpIHsKICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5rZXlzU2Vjb25kQXhpcy52YWx1ZXMoKSk7CiAgICB9CiAgICBnZXRBc0FycmF5KCkgewogICAgICByZXR1cm4gdGhpcy5nZXRGaXJzdEF4aXNLZXlzKCkubWFwKChmaXJzdEF4aXNLZXkpID0+IHsKICAgICAgICByZXR1cm4gdGhpcy5nZXRTZWNvbmRBeGlzS2V5cygpLm1hcCgoc2Vjb25kQXhpc0tleSkgPT4gewogICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KGZpcnN0QXhpc0tleSwgc2Vjb25kQXhpc0tleSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfQogICAgZ2V0Q29udGVudHMoKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAga2V5c0ZpcnN0QXhpczogdGhpcy5rZXlzRmlyc3RBeGlzLAogICAgICAgIGtleXNTZWNvbmRBeGlzOiB0aGlzLmtleXNTZWNvbmRBeGlzLAogICAgICAgIGRhdGE6IHRoaXMuZGF0YQogICAgICB9OwogICAgfQogIH0KICBjbGFzcyBCYXNlTXV0YXRpb25PdmVyVGltZURhdGFNYXAgZXh0ZW5kcyBNYXAyZEJhc2UgewogICAgY29uc3RydWN0b3IoaW5pdGlhbENvbnRlbnQpIHsKICAgICAgc3VwZXIoc2VyaWFsaXplU3Vic3RpdHV0aW9uT3JEZWxldGlvbiwgc2VyaWFsaXplVGVtcG9yYWwsIGluaXRpYWxDb250ZW50KTsKICAgIH0KICB9CiAgY29uc3Qgc29ydFN1YnN0aXR1dGlvbnNBbmREZWxldGlvbnMgPSAoYTIsIGIpID0+IHsKICAgIGlmIChhMi5zZWdtZW50ICE9PSBiLnNlZ21lbnQpIHsKICAgICAgcmV0dXJuIGNvbXBhcmVTZWdtZW50cyhhMi5zZWdtZW50LCBiLnNlZ21lbnQpOwogICAgfQogICAgaWYgKGEyLnBvc2l0aW9uICE9PSBiLnBvc2l0aW9uKSB7CiAgICAgIHJldHVybiBjb21wYXJlUG9zaXRpb25zKGEyLnBvc2l0aW9uLCBiLnBvc2l0aW9uKTsKICAgIH0KICAgIGNvbnN0IGFJc0RlbGV0aW9uID0gYTIgaW5zdGFuY2VvZiBEZWxldGlvbkNsYXNzOwogICAgY29uc3QgYklzRGVsZXRpb24gPSBiIGluc3RhbmNlb2YgRGVsZXRpb25DbGFzczsKICAgIGlmIChhSXNEZWxldGlvbiAhPT0gYklzRGVsZXRpb24pIHsKICAgICAgcmV0dXJuIGFJc0RlbGV0aW9uID8gMSA6IC0xOwogICAgfQogICAgaWYgKCFhSXNEZWxldGlvbiAmJiAhYklzRGVsZXRpb24pIHsKICAgICAgaWYgKGEyLnN1YnN0aXR1dGlvblZhbHVlICE9PSBiLnN1YnN0aXR1dGlvblZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGNvbXBhcmVTdWJzdGl0dXRpb25WYWx1ZXMoYTIuc3Vic3RpdHV0aW9uVmFsdWUsIGIuc3Vic3RpdHV0aW9uVmFsdWUpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gMDsKICB9OwogIGNvbnN0IGNvbXBhcmVTZWdtZW50cyA9IChhMiwgYikgPT4gewogICAgaWYgKGEyID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgaWYgKGIgPT09IHZvaWQgMCkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIHJldHVybiBhMi5sb2NhbGVDb21wYXJlKGIpOwogIH07CiAgY29uc3QgY29tcGFyZVBvc2l0aW9ucyA9IChhMiwgYikgPT4gewogICAgcmV0dXJuIGEyIC0gYjsKICB9OwogIGNvbnN0IGNvbXBhcmVTdWJzdGl0dXRpb25WYWx1ZXMgPSAoYTIsIGIpID0+IHsKICAgIGlmIChhMiA9PT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGlmIChiID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICByZXR1cm4gYTIubG9jYWxlQ29tcGFyZShiKTsKICB9OwogIGNvbnN0IE1BWF9OVU1CRVJfT0ZfR1JJRF9DT0xVTU5TID0gMjAwOwogIGFzeW5jIGZ1bmN0aW9uIHF1ZXJ5T3ZlcmFsbE11dGF0aW9uRGF0YSh7CiAgICBsYXBpc0ZpbHRlciwKICAgIHNlcXVlbmNlVHlwZSwKICAgIGxhcGlzLAogICAgZ3JhbnVsYXJpdHksCiAgICBsYXBpc0RhdGVGaWVsZCwKICAgIHNpZ25hbAogIH0pIHsKICAgIGNvbnN0IGFsbERhdGVzID0gYXdhaXQgZ2V0RGF0ZXNJbkRhdGFzZXQobGFwaXNGaWx0ZXIsIGxhcGlzLCBncmFudWxhcml0eSwgbGFwaXNEYXRlRmllbGQsIHNpZ25hbCk7CiAgICBpZiAoYWxsRGF0ZXMubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgY29udGVudDogW10KICAgICAgfTsKICAgIH0KICAgIGNvbnN0IGZpbHRlciA9IHsKICAgICAgLi4ubGFwaXNGaWx0ZXIsCiAgICAgIFtgJHtsYXBpc0RhdGVGaWVsZH1Gcm9tYF06IGFsbERhdGVzWzBdLmZpcnN0RGF5LnRvU3RyaW5nKCksCiAgICAgIFtgJHtsYXBpc0RhdGVGaWVsZH1Ub2BdOiBhbGxEYXRlc1thbGxEYXRlcy5sZW5ndGggLSAxXS5sYXN0RGF5LnRvU3RyaW5nKCkKICAgIH07CiAgICByZXR1cm4gZmV0Y2hBbmRQcmVwYXJlU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zKGZpbHRlciwgc2VxdWVuY2VUeXBlKS5ldmFsdWF0ZShsYXBpcywgc2lnbmFsKTsKICB9CiAgYXN5bmMgZnVuY3Rpb24gcXVlcnlNdXRhdGlvbnNPdmVyVGltZURhdGEoewogICAgbGFwaXNGaWx0ZXIsCiAgICBzZXF1ZW5jZVR5cGUsCiAgICBsYXBpcywKICAgIGxhcGlzRGF0ZUZpZWxkLAogICAgZ3JhbnVsYXJpdHksCiAgICBzaWduYWwKICB9KSB7CiAgICBjb25zdCBhbGxEYXRlcyA9IGF3YWl0IGdldERhdGVzSW5EYXRhc2V0KGxhcGlzRmlsdGVyLCBsYXBpcywgZ3JhbnVsYXJpdHksIGxhcGlzRGF0ZUZpZWxkLCBzaWduYWwpOwogICAgaWYgKGFsbERhdGVzLmxlbmd0aCA+IE1BWF9OVU1CRVJfT0ZfR1JJRF9DT0xVTU5TKSB7CiAgICAgIHRocm93IG5ldyBVc2VyRmFjaW5nRXJyb3IoCiAgICAgICAgIlRvbyBtYW55IGRhdGVzIiwKICAgICAgICBgVGhlIGRhdGFzZXQgd291bGQgY29udGFpbiAke2FsbERhdGVzLmxlbmd0aH0gZGF0ZSBpbnRlcnZhbHMuIFBsZWFzZSByZWR1Y2UgdGhlIG51bWJlciB0byBiZWxvdyAke01BWF9OVU1CRVJfT0ZfR1JJRF9DT0xVTU5TfSB0byBkaXNwbGF5IHRoZSBkYXRhLiBZb3UgY2FuIGFjaGlldmUgdGhpcyBieSBlaXRoZXIgbmFycm93aW5nIHRoZSBkYXRlIHJhbmdlIGluIHRoZSBwcm92aWRlZCBMQVBJUyBmaWx0ZXIgb3IgYnkgc2VsZWN0aW5nIGEgbGFyZ2VyIGdyYW51bGFyaXR5LmAKICAgICAgKTsKICAgIH0KICAgIGNvbnN0IHN1YlF1ZXJpZXMgPSBhbGxEYXRlcy5tYXAoYXN5bmMgKGRhdGUpID0+IHsKICAgICAgY29uc3QgZGF0ZUZyb20gPSBkYXRlLmZpcnN0RGF5LnRvU3RyaW5nKCk7CiAgICAgIGNvbnN0IGRhdGVUbyA9IGRhdGUubGFzdERheS50b1N0cmluZygpOwogICAgICBjb25zdCBmaWx0ZXIgPSB7CiAgICAgICAgLi4ubGFwaXNGaWx0ZXIsCiAgICAgICAgW2Ake2xhcGlzRGF0ZUZpZWxkfUZyb21gXTogZGF0ZUZyb20sCiAgICAgICAgW2Ake2xhcGlzRGF0ZUZpZWxkfVRvYF06IGRhdGVUbwogICAgICB9OwogICAgICBjb25zdCBkYXRhMiA9IGF3YWl0IGZldGNoQW5kUHJlcGFyZVN1YnN0aXR1dGlvbnNPckRlbGV0aW9ucyhmaWx0ZXIsIHNlcXVlbmNlVHlwZSkuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgICAgIGNvbnN0IHRvdGFsQ291bnRRdWVyeSA9IGF3YWl0IGdldFRvdGFsTnVtYmVyT2ZTZXF1ZW5jZXNJbkRhdGVSYW5nZShmaWx0ZXIpLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICByZXR1cm4gewogICAgICAgIGRhdGUsCiAgICAgICAgbXV0YXRpb25zOiBkYXRhMi5jb250ZW50LAogICAgICAgIHRvdGFsQ291bnQ6IHRvdGFsQ291bnRRdWVyeS5jb250ZW50WzBdLmNvdW50CiAgICAgIH07CiAgICB9KTsKICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBQcm9taXNlLmFsbChzdWJRdWVyaWVzKTsKICAgIGNvbnN0IG92ZXJhbGxNdXRhdGlvbnNEYXRhID0gKGF3YWl0IHF1ZXJ5T3ZlcmFsbE11dGF0aW9uRGF0YSh7CiAgICAgIGxhcGlzRmlsdGVyLAogICAgICBzZXF1ZW5jZVR5cGUsCiAgICAgIGxhcGlzLAogICAgICBsYXBpc0RhdGVGaWVsZCwKICAgICAgZ3JhbnVsYXJpdHkKICAgIH0pKS5jb250ZW50OwogICAgcmV0dXJuIHsKICAgICAgbXV0YXRpb25PdmVyVGltZURhdGE6IGdyb3VwQnlNdXRhdGlvbihkYXRhLCBvdmVyYWxsTXV0YXRpb25zRGF0YSksCiAgICAgIG92ZXJhbGxNdXRhdGlvbkRhdGE6IG92ZXJhbGxNdXRhdGlvbnNEYXRhCiAgICB9OwogIH0KICBhc3luYyBmdW5jdGlvbiBnZXREYXRlc0luRGF0YXNldChsYXBpc0ZpbHRlciwgbGFwaXMsIGdyYW51bGFyaXR5LCBsYXBpc0RhdGVGaWVsZCwgc2lnbmFsKSB7CiAgICBjb25zdCB7IGNvbnRlbnQ6IGF2YWlsYWJsZURhdGVzIH0gPSBhd2FpdCBxdWVyeUF2YWlsYWJsZURhdGVzKAogICAgICBsYXBpc0ZpbHRlciwKICAgICAgbGFwaXMsCiAgICAgIGdyYW51bGFyaXR5LAogICAgICBsYXBpc0RhdGVGaWVsZCwKICAgICAgc2lnbmFsCiAgICApOwogICAgY29uc3QgeyBkYXRlRnJvbSwgZGF0ZVRvIH0gPSBnZXREYXRlUmFuZ2VGcm9tRmlsdGVyKGxhcGlzRmlsdGVyLCBsYXBpc0RhdGVGaWVsZCwgZ3JhbnVsYXJpdHkpOwogICAgY29uc3QgeyBtaW4sIG1heCB9ID0gZ2V0TWluTWF4VGVtcG9yYWwoYXZhaWxhYmxlRGF0ZXMpOwogICAgcmV0dXJuIGdlbmVyYXRlQWxsSW5SYW5nZShkYXRlRnJvbSA/PyBtaW4sIGRhdGVUbyA/PyBtYXgpOwogIH0KICBmdW5jdGlvbiBnZXREYXRlUmFuZ2VGcm9tRmlsdGVyKGxhcGlzRmlsdGVyLCBsYXBpc0RhdGVGaWVsZCwgZ3JhbnVsYXJpdHkpIHsKICAgIGNvbnN0IHZhbHVlRnJvbUZpbHRlciA9IGxhcGlzRmlsdGVyW2xhcGlzRGF0ZUZpZWxkXTsKICAgIGlmICh2YWx1ZUZyb21GaWx0ZXIpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBkYXRlRnJvbTogcGFyc2VEYXRlU3RyaW5nVG9UZW1wb3JhbCh2YWx1ZUZyb21GaWx0ZXIsIGdyYW51bGFyaXR5KSwKICAgICAgICBkYXRlVG86IHBhcnNlRGF0ZVN0cmluZ1RvVGVtcG9yYWwodmFsdWVGcm9tRmlsdGVyLCBncmFudWxhcml0eSkKICAgICAgfTsKICAgIH0KICAgIGNvbnN0IG1pbkZyb21GaWx0ZXIgPSBsYXBpc0ZpbHRlcltgJHtsYXBpc0RhdGVGaWVsZH1Gcm9tYF07CiAgICBjb25zdCBtYXhGcm9tRmlsdGVyID0gbGFwaXNGaWx0ZXJbYCR7bGFwaXNEYXRlRmllbGR9VG9gXTsKICAgIHJldHVybiB7CiAgICAgIGRhdGVGcm9tOiBtaW5Gcm9tRmlsdGVyID8gcGFyc2VEYXRlU3RyaW5nVG9UZW1wb3JhbChtaW5Gcm9tRmlsdGVyLCBncmFudWxhcml0eSkgOiBudWxsLAogICAgICBkYXRlVG86IG1heEZyb21GaWx0ZXIgPyBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKG1heEZyb21GaWx0ZXIsIGdyYW51bGFyaXR5KSA6IG51bGwKICAgIH07CiAgfQogIGZ1bmN0aW9uIHF1ZXJ5QXZhaWxhYmxlRGF0ZXMobGFwaXNGaWx0ZXIsIGxhcGlzLCBncmFudWxhcml0eSwgbGFwaXNEYXRlRmllbGQsIHNpZ25hbCkgewogICAgcmV0dXJuIGZldGNoQW5kUHJlcGFyZURhdGVzKGxhcGlzRmlsdGVyLCBncmFudWxhcml0eSwgbGFwaXNEYXRlRmllbGQpLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogIH0KICBmdW5jdGlvbiBmZXRjaEFuZFByZXBhcmVEYXRlcyhmaWx0ZXIsIGdyYW51bGFyaXR5LCBsYXBpc0RhdGVGaWVsZCkgewogICAgY29uc3QgZmV0Y2hEYXRhID0gbmV3IEZldGNoQWdncmVnYXRlZE9wZXJhdG9yKGZpbHRlciwgW2xhcGlzRGF0ZUZpZWxkXSk7CiAgICBjb25zdCBkYXRhV2l0aEZpeGVkRGF0ZUtleSA9IG5ldyBSZW5hbWVGaWVsZE9wZXJhdG9yKGZldGNoRGF0YSwgbGFwaXNEYXRlRmllbGQsICJkYXRlIik7CiAgICBjb25zdCBtYXBEYXRhID0gbmV3IE1hcE9wZXJhdG9yKGRhdGFXaXRoRml4ZWREYXRlS2V5LCAoZGF0YSkgPT4gbWFwRGF0ZVRvR3JhbnVsYXJpdHlSYW5nZShkYXRhLCBncmFudWxhcml0eSkpOwogICAgY29uc3QgZ3JvdXBCeURhdGEgPSBuZXcgR3JvdXBCeUFuZFN1bU9wZXJhdG9yKG1hcERhdGEsICJkYXRlUmFuZ2UiLCAiY291bnQiKTsKICAgIGNvbnN0IHNvcnREYXRhID0gbmV3IFNvcnRPcGVyYXRvcihncm91cEJ5RGF0YSwgZGF0ZVJhbmdlQ29tcGFyZSk7CiAgICByZXR1cm4gbmV3IE1hcE9wZXJhdG9yKHNvcnREYXRhLCAoZGF0YSkgPT4gZGF0YS5kYXRlUmFuZ2UpOwogIH0KICBmdW5jdGlvbiBmZXRjaEFuZFByZXBhcmVTdWJzdGl0dXRpb25zT3JEZWxldGlvbnMoZmlsdGVyLCBzZXF1ZW5jZVR5cGUpIHsKICAgIHJldHVybiBuZXcgRmV0Y2hTdWJzdGl0dXRpb25zT3JEZWxldGlvbnNPcGVyYXRvcihmaWx0ZXIsIHNlcXVlbmNlVHlwZSwgMWUtMyk7CiAgfQogIGZ1bmN0aW9uIHNlcmlhbGl6ZVN1YnN0aXR1dGlvbk9yRGVsZXRpb24obXV0YXRpb24pIHsKICAgIHJldHVybiBtdXRhdGlvbi5jb2RlOwogIH0KICBmdW5jdGlvbiBzZXJpYWxpemVUZW1wb3JhbChkYXRlKSB7CiAgICByZXR1cm4gZGF0ZS5kYXRlU3RyaW5nOwogIH0KICBmdW5jdGlvbiBncm91cEJ5TXV0YXRpb24oZGF0YSwgb3ZlcmFsbE11dGF0aW9uRGF0YSkgewogICAgY29uc3QgZGF0YUFycmF5ID0gbmV3IEJhc2VNdXRhdGlvbk92ZXJUaW1lRGF0YU1hcCgpOwogICAgY29uc3QgYWxsRGF0ZXMgPSBkYXRhLm1hcCgobXV0YXRpb25EYXRhKSA9PiBtdXRhdGlvbkRhdGEuZGF0ZSk7CiAgICBjb25zdCBzb3J0ZWRPdmVyYWxsTXV0YXRpb25EYXRhID0gb3ZlcmFsbE11dGF0aW9uRGF0YS5zb3J0KChhMiwgYikgPT4gc29ydFN1YnN0aXR1dGlvbnNBbmREZWxldGlvbnMoYTIubXV0YXRpb24sIGIubXV0YXRpb24pKS5tYXAoKGVudHJ5KSA9PiB7CiAgICAgIHJldHVybiB0b1N1YnN0aXR1dGlvbk9yRGVsZXRpb24oZW50cnkubXV0YXRpb24pOwogICAgfSk7CiAgICBjb25zdCBzb3J0ZWREYXRlcyA9IGFsbERhdGVzLnNvcnQoKGEyLCBiKSA9PiBjb21wYXJlVGVtcG9yYWwoYTIsIGIpKS5tYXAoKGRhdGUpID0+IHRvVGVtcG9yYWwoZGF0ZSkpOwogICAgc29ydGVkT3ZlcmFsbE11dGF0aW9uRGF0YS5mb3JFYWNoKChtdXRhdGlvbkRhdGEpID0+IHsKICAgICAgc29ydGVkRGF0ZXMuZm9yRWFjaCgoZGF0ZSkgPT4gewogICAgICAgIGRhdGFBcnJheS5zZXQobXV0YXRpb25EYXRhLCBkYXRlLCBudWxsKTsKICAgICAgfSk7CiAgICB9KTsKICAgIGRhdGEuZm9yRWFjaCgobXV0YXRpb25EYXRhKSA9PiB7CiAgICAgIG11dGF0aW9uRGF0YS5tdXRhdGlvbnMuZm9yRWFjaCgobXV0YXRpb25FbnRyeSkgPT4gewogICAgICAgIGNvbnN0IG11dGF0aW9uID0gdG9TdWJzdGl0dXRpb25PckRlbGV0aW9uKG11dGF0aW9uRW50cnkubXV0YXRpb24pOwogICAgICAgIGNvbnN0IGRhdGUgPSB0b1RlbXBvcmFsKG11dGF0aW9uRGF0YS5kYXRlKTsKICAgICAgICBpZiAoZGF0YUFycmF5LmdldChtdXRhdGlvbiwgZGF0ZSkgIT09IHZvaWQgMCkgewogICAgICAgICAgZGF0YUFycmF5LnNldChtdXRhdGlvbiwgZGF0ZSwgewogICAgICAgICAgICBjb3VudDogbXV0YXRpb25FbnRyeS5jb3VudCwKICAgICAgICAgICAgcHJvcG9ydGlvbjogbXV0YXRpb25FbnRyeS5wcm9wb3J0aW9uLAogICAgICAgICAgICB0b3RhbENvdW50OiBtdXRhdGlvbkRhdGEudG90YWxDb3VudAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0pOwogICAgcmV0dXJuIGRhdGFBcnJheTsKICB9CiAgZnVuY3Rpb24gZ2V0VG90YWxOdW1iZXJPZlNlcXVlbmNlc0luRGF0ZVJhbmdlKGZpbHRlcikgewogICAgcmV0dXJuIG5ldyBGZXRjaEFnZ3JlZ2F0ZWRPcGVyYXRvcihmaWx0ZXIpOwogIH0KICBhc3luYyBmdW5jdGlvbiB3b3JrZXJGdW5jdGlvbihxdWVyeUZ1bmN0aW9uKSB7CiAgICB0cnkgewogICAgICBwb3N0TWVzc2FnZSh7IHN0YXR1czogImxvYWRpbmciIH0pOwogICAgICBjb25zdCB3b3JrZXJSZXNwb25zZSA9IGF3YWl0IHF1ZXJ5RnVuY3Rpb24oKTsKICAgICAgcG9zdE1lc3NhZ2UoewogICAgICAgIHN0YXR1czogInN1Y2Nlc3MiLAogICAgICAgIGRhdGE6IHdvcmtlclJlc3BvbnNlCiAgICAgIH0pOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgcG9zdE1lc3NhZ2UoCiAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBVc2VyRmFjaW5nRXJyb3IgPyB7CiAgICAgICAgICBzdGF0dXM6ICJlcnJvciIsCiAgICAgICAgICB1c2VyRmFjaW5nOiB0cnVlLAogICAgICAgICAgaGVhZGxpbmU6IGVycm9yLmhlYWRsaW5lLAogICAgICAgICAgZXJyb3IKICAgICAgICB9IDogewogICAgICAgICAgc3RhdHVzOiAiZXJyb3IiLAogICAgICAgICAgdXNlckZhY2luZzogZmFsc2UsCiAgICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKGAke2Vycm9yfWApCiAgICAgICAgfQogICAgICApOwogICAgfQogIH0KICBhc3luYyBmdW5jdGlvbiBnZXRNdXRhdGlvbk92ZXJUaW1lV29ya2VyRnVuY3Rpb24oZXZlbnQpIHsKICAgIGNvbnN0IG11dGF0aW9uT3ZlclRpbWVEYXRhID0gYXdhaXQgcXVlcnlNdXRhdGlvbnNPdmVyVGltZURhdGEoZXZlbnQuZGF0YSk7CiAgICBjb25zdCB3b3JrZXJSZXNwb25zZSA9IHsKICAgICAgb3ZlcmFsbE11dGF0aW9uRGF0YTogbXV0YXRpb25PdmVyVGltZURhdGEub3ZlcmFsbE11dGF0aW9uRGF0YSwKICAgICAgbXV0YXRpb25PdmVyVGltZVNlcmlhbGl6ZWQ6IG11dGF0aW9uT3ZlclRpbWVEYXRhLm11dGF0aW9uT3ZlclRpbWVEYXRhLmdldENvbnRlbnRzKCkKICAgIH07CiAgICByZXR1cm4gd29ya2VyUmVzcG9uc2U7CiAgfQogIHNlbGYub25tZXNzYWdlID0gYXN5bmMgZnVuY3Rpb24oZXZlbnQpIHsKICAgIGF3YWl0IHdvcmtlckZ1bmN0aW9uKCgpID0+IGdldE11dGF0aW9uT3ZlclRpbWVXb3JrZXJGdW5jdGlvbihldmVudCkpOwogIH07Cn0pKCk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPW11dGF0aW9uT3ZlclRpbWVXb3JrZXItRGk2eVAxZTYuanMubWFwCg==";
|
|
8610
8657
|
const decodeBase64 = (base64) => Uint8Array.from(atob(base64), (c2) => c2.charCodeAt(0));
|
|
8611
8658
|
const blob = typeof self !== "undefined" && self.Blob && new Blob([decodeBase64(encodedJs)], { type: "text/javascript;charset=utf-8" });
|
|
8612
8659
|
function WorkerWrapper(options2) {
|
|
@@ -8657,13 +8704,13 @@ class Map2dBase {
|
|
|
8657
8704
|
const serializedKeySecondAxis = this.serializeSecondAxis(keySecondAxis);
|
|
8658
8705
|
return (_a = this.data.get(serializedKeyFirstAxis)) == null ? void 0 : _a.get(serializedKeySecondAxis);
|
|
8659
8706
|
}
|
|
8660
|
-
getRow(key
|
|
8707
|
+
getRow(key) {
|
|
8661
8708
|
const serializedKeyFirstAxis = this.serializeFirstAxis(key);
|
|
8662
8709
|
const row = this.data.get(serializedKeyFirstAxis);
|
|
8663
8710
|
if (row === void 0) {
|
|
8664
8711
|
return [];
|
|
8665
8712
|
}
|
|
8666
|
-
return Array.from(this.keysSecondAxis.keys()).map((key2) => row.get(key2)
|
|
8713
|
+
return Array.from(this.keysSecondAxis.keys()).map((key2) => row.get(key2));
|
|
8667
8714
|
}
|
|
8668
8715
|
set(keyFirstAxis, keySecondAxis, value) {
|
|
8669
8716
|
const serializedKeyFirstAxis = this.serializeFirstAxis(keyFirstAxis);
|
|
@@ -8686,10 +8733,10 @@ class Map2dBase {
|
|
|
8686
8733
|
getSecondAxisKeys() {
|
|
8687
8734
|
return Array.from(this.keysSecondAxis.values());
|
|
8688
8735
|
}
|
|
8689
|
-
getAsArray(
|
|
8736
|
+
getAsArray() {
|
|
8690
8737
|
return this.getFirstAxisKeys().map((firstAxisKey) => {
|
|
8691
8738
|
return this.getSecondAxisKeys().map((secondAxisKey) => {
|
|
8692
|
-
return this.get(firstAxisKey, secondAxisKey)
|
|
8739
|
+
return this.get(firstAxisKey, secondAxisKey);
|
|
8693
8740
|
});
|
|
8694
8741
|
});
|
|
8695
8742
|
}
|
|
@@ -8736,19 +8783,19 @@ class Map2dView {
|
|
|
8736
8783
|
getSecondAxisKeys() {
|
|
8737
8784
|
return Array.from(this.keysSecondAxis.values());
|
|
8738
8785
|
}
|
|
8739
|
-
getAsArray(
|
|
8786
|
+
getAsArray() {
|
|
8740
8787
|
return this.getFirstAxisKeys().map((firstAxisKey) => {
|
|
8741
8788
|
return this.getSecondAxisKeys().map((secondAxisKey) => {
|
|
8742
|
-
return this.baseMap.get(firstAxisKey, secondAxisKey)
|
|
8789
|
+
return this.baseMap.get(firstAxisKey, secondAxisKey);
|
|
8743
8790
|
});
|
|
8744
8791
|
});
|
|
8745
8792
|
}
|
|
8746
|
-
getRow(key
|
|
8793
|
+
getRow(key) {
|
|
8747
8794
|
const serializedKeyFirstAxis = this.serializeFirstAxis(key);
|
|
8748
8795
|
if (!this.keysFirstAxis.has(serializedKeyFirstAxis)) {
|
|
8749
8796
|
return [];
|
|
8750
8797
|
}
|
|
8751
|
-
return this.baseMap.getRow(key
|
|
8798
|
+
return this.baseMap.getRow(key);
|
|
8752
8799
|
}
|
|
8753
8800
|
}
|
|
8754
8801
|
class BaseMutationOverTimeDataMap extends Map2dBase {
|
|
@@ -8815,6 +8862,9 @@ const ColorScaleSelector = ({ colorScale, setColorScale }) => {
|
|
|
8815
8862
|
] });
|
|
8816
8863
|
};
|
|
8817
8864
|
const getColorWithingScale = (value, colorScale) => {
|
|
8865
|
+
if (value === void 0) {
|
|
8866
|
+
return "lightgrey";
|
|
8867
|
+
}
|
|
8818
8868
|
if (colorScale.min === colorScale.max) {
|
|
8819
8869
|
return singleGraphColorRGBByName(colorScale.color, 0);
|
|
8820
8870
|
}
|
|
@@ -8823,7 +8873,7 @@ const getColorWithingScale = (value, colorScale) => {
|
|
|
8823
8873
|
return singleGraphColorRGBByName(colorScale.color, alpha);
|
|
8824
8874
|
};
|
|
8825
8875
|
const getTextColorForScale = (value, colorScale) => {
|
|
8826
|
-
if (colorScale.min === colorScale.max) {
|
|
8876
|
+
if (value === void 0 || colorScale.min === colorScale.max) {
|
|
8827
8877
|
return "black";
|
|
8828
8878
|
}
|
|
8829
8879
|
const colorRange = colorScale.max - colorScale.min;
|
|
@@ -8900,7 +8950,7 @@ const MutationsOverTimeGrid = ({ data, colorScale }) => {
|
|
|
8900
8950
|
`mutation-${mutation.toString()}`
|
|
8901
8951
|
),
|
|
8902
8952
|
dates.map((date, columnIndex) => {
|
|
8903
|
-
const value = data.get(mutation, date) ??
|
|
8953
|
+
const value = data.get(mutation, date) ?? null;
|
|
8904
8954
|
const tooltipPosition = getTooltipPosition(
|
|
8905
8955
|
rowIndex,
|
|
8906
8956
|
shownMutations.length,
|
|
@@ -8946,27 +8996,29 @@ const ProportionCell = ({ value, mutation, date, tooltipPosition, colorScale })
|
|
|
8946
8996
|
")"
|
|
8947
8997
|
] }),
|
|
8948
8998
|
/* @__PURE__ */ u$1("p", { children: mutation.code }),
|
|
8949
|
-
/* @__PURE__ */ u$1("p", { children: [
|
|
8950
|
-
"
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
"
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8999
|
+
value === null ? /* @__PURE__ */ u$1("p", { children: "No data" }) : /* @__PURE__ */ u$1(Fragment, { children: [
|
|
9000
|
+
/* @__PURE__ */ u$1("p", { children: [
|
|
9001
|
+
"Proportion: ",
|
|
9002
|
+
formatProportion(value.proportion)
|
|
9003
|
+
] }),
|
|
9004
|
+
/* @__PURE__ */ u$1("p", { children: [
|
|
9005
|
+
"Count: ",
|
|
9006
|
+
value.count,
|
|
9007
|
+
" / ",
|
|
9008
|
+
value.totalCount,
|
|
9009
|
+
" total"
|
|
9010
|
+
] })
|
|
8959
9011
|
] })
|
|
8960
9012
|
] });
|
|
8961
9013
|
return /* @__PURE__ */ u$1("div", { className: "py-1 w-full h-full", children: /* @__PURE__ */ u$1(Tooltip, { content: tooltipContent, position: tooltipPosition, children: /* @__PURE__ */ u$1(
|
|
8962
9014
|
"div",
|
|
8963
9015
|
{
|
|
8964
9016
|
style: {
|
|
8965
|
-
backgroundColor: getColorWithingScale(value.proportion, colorScale),
|
|
8966
|
-
color: getTextColorForScale(value.proportion, colorScale)
|
|
9017
|
+
backgroundColor: getColorWithingScale(value == null ? void 0 : value.proportion, colorScale),
|
|
9018
|
+
color: getTextColorForScale(value == null ? void 0 : value.proportion, colorScale)
|
|
8967
9019
|
},
|
|
8968
9020
|
className: `w-full h-full text-center hover:font-bold text-xs group @container`,
|
|
8969
|
-
children: /* @__PURE__ */ u$1("span", { className: "invisible @[2rem]:visible", children: formatProportion(value.proportion, 0) })
|
|
9021
|
+
children: /* @__PURE__ */ u$1("span", { className: "invisible @[2rem]:visible", children: value === null ? "" : formatProportion(value.proportion, 0) })
|
|
8970
9022
|
}
|
|
8971
9023
|
) }) });
|
|
8972
9024
|
};
|
|
@@ -8985,12 +9037,13 @@ const ColorScaleSelectorDropdown = ({
|
|
|
8985
9037
|
}) => {
|
|
8986
9038
|
return /* @__PURE__ */ u$1("div", { className: "w-20", children: /* @__PURE__ */ u$1(Dropdown, { buttonTitle: `Color scale`, placement: "bottom-start", children: /* @__PURE__ */ u$1(ColorScaleSelector, { colorScale, setColorScale }) }) });
|
|
8987
9039
|
};
|
|
8988
|
-
function useWebWorker(messageToWorker,
|
|
9040
|
+
function useWebWorker(messageToWorker, WorkerConstructor) {
|
|
8989
9041
|
const [data, setData] = h(void 0);
|
|
8990
9042
|
const [error, setError] = h(void 0);
|
|
8991
9043
|
const [isLoading, setIsLoading] = h(true);
|
|
8992
|
-
|
|
8993
|
-
|
|
9044
|
+
const worker = T(() => {
|
|
9045
|
+
const worker2 = new WorkerConstructor();
|
|
9046
|
+
worker2.onmessage = (event) => {
|
|
8994
9047
|
const eventData = event.data;
|
|
8995
9048
|
const status = eventData.status;
|
|
8996
9049
|
switch (status) {
|
|
@@ -9012,11 +9065,12 @@ function useWebWorker(messageToWorker, worker) {
|
|
|
9012
9065
|
throw new Error(`Unknown status: ${status}`);
|
|
9013
9066
|
}
|
|
9014
9067
|
};
|
|
9015
|
-
|
|
9068
|
+
worker2.onmessageerror = (event) => {
|
|
9016
9069
|
setError(new Error(`Worker received a message that it cannot deserialize: ${event.data}`));
|
|
9017
9070
|
setIsLoading(false);
|
|
9018
9071
|
};
|
|
9019
|
-
|
|
9072
|
+
return worker2;
|
|
9073
|
+
}, [WorkerConstructor]);
|
|
9020
9074
|
y(() => {
|
|
9021
9075
|
worker.postMessage(messageToWorker);
|
|
9022
9076
|
}, [messageToWorker, worker]);
|
|
@@ -9039,10 +9093,9 @@ const MutationsOverTimeInner = (componentProps) => {
|
|
|
9039
9093
|
lapis
|
|
9040
9094
|
};
|
|
9041
9095
|
}, [granularity, lapis, lapisDateField, lapisFilter, sequenceType]);
|
|
9042
|
-
const worker = T(() => new WorkerWrapper(), []);
|
|
9043
9096
|
const { data, error, isLoading } = useWebWorker(
|
|
9044
9097
|
messageToWorker,
|
|
9045
|
-
|
|
9098
|
+
WorkerWrapper
|
|
9046
9099
|
);
|
|
9047
9100
|
if (isLoading) {
|
|
9048
9101
|
return /* @__PURE__ */ u$1(LoadingDisplay, {});
|
|
@@ -9370,6 +9423,12 @@ function computeInitialValues(initialValue, initialDateFrom, initialDateTo, earl
|
|
|
9370
9423
|
const selectableOptions = getSelectableOptions(dateRangeOptions);
|
|
9371
9424
|
const initialSelectedDateRange = (_a = selectableOptions.find((option) => option.value === initialValue)) == null ? void 0 : _a.value;
|
|
9372
9425
|
if (initialValue !== void 0 && initialSelectedDateRange === void 0) {
|
|
9426
|
+
if (selectableOptions.length === 0) {
|
|
9427
|
+
throw new UserFacingError(
|
|
9428
|
+
"Invalid initialValue",
|
|
9429
|
+
"There are no selectable options, but initialValue is set."
|
|
9430
|
+
);
|
|
9431
|
+
}
|
|
9373
9432
|
throw new UserFacingError(
|
|
9374
9433
|
"Invalid initialValue",
|
|
9375
9434
|
`Invalid initialValue "${initialValue}", It must be one of ${selectableOptions.map((option) => `'${option.value}'`).join(", ")}`
|
|
@@ -9409,9 +9468,21 @@ function isUndefinedOrEmpty(value) {
|
|
|
9409
9468
|
return value === void 0 || value === "";
|
|
9410
9469
|
}
|
|
9411
9470
|
const customOption = "Custom";
|
|
9412
|
-
const
|
|
9471
|
+
const dateRangeSelectorInnerPropsSchema = z$1.object({
|
|
9472
|
+
dateRangeOptions: z$1.array(dateRangeOptionSchema),
|
|
9473
|
+
earliestDate: z$1.string().date(),
|
|
9474
|
+
initialValue: z$1.string().optional(),
|
|
9475
|
+
initialDateFrom: z$1.string().date().optional(),
|
|
9476
|
+
initialDateTo: z$1.string().date().optional(),
|
|
9477
|
+
dateColumn: z$1.string().min(1)
|
|
9478
|
+
});
|
|
9479
|
+
const dateRangeSelectorPropsSchema = dateRangeSelectorInnerPropsSchema.extend({
|
|
9480
|
+
width: z$1.string()
|
|
9481
|
+
});
|
|
9482
|
+
const DateRangeSelector = (props) => {
|
|
9483
|
+
const { width, ...innerProps } = props;
|
|
9413
9484
|
const size = { width, height: "3rem" };
|
|
9414
|
-
return /* @__PURE__ */ u$1(ErrorBoundary, { size, layout: "horizontal", children: /* @__PURE__ */ u$1("div", { style: { width }, children: /* @__PURE__ */ u$1(DateRangeSelectorInner, { ...innerProps }) }) });
|
|
9485
|
+
return /* @__PURE__ */ u$1(ErrorBoundary, { size, layout: "horizontal", componentProps: props, schema: dateRangeSelectorPropsSchema, children: /* @__PURE__ */ u$1("div", { style: { width }, children: /* @__PURE__ */ u$1(DateRangeSelectorInner, { ...innerProps }) }) });
|
|
9415
9486
|
};
|
|
9416
9487
|
const DateRangeSelectorInner = ({
|
|
9417
9488
|
dateRangeOptions,
|
|
@@ -9590,10 +9661,10 @@ let DateRangeSelectorComponent = class extends PreactLitAdapter {
|
|
|
9590
9661
|
this.dateRangeOptions = [];
|
|
9591
9662
|
this.earliestDate = "1900-01-01";
|
|
9592
9663
|
this.initialValue = void 0;
|
|
9593
|
-
this.initialDateFrom =
|
|
9594
|
-
this.initialDateTo =
|
|
9664
|
+
this.initialDateFrom = void 0;
|
|
9665
|
+
this.initialDateTo = void 0;
|
|
9595
9666
|
this.width = "100%";
|
|
9596
|
-
this.dateColumn = "
|
|
9667
|
+
this.dateColumn = "";
|
|
9597
9668
|
}
|
|
9598
9669
|
render() {
|
|
9599
9670
|
return /* @__PURE__ */ u$1(
|
|
@@ -9666,9 +9737,18 @@ function compareLocationEntries(fields) {
|
|
|
9666
9737
|
return 0;
|
|
9667
9738
|
};
|
|
9668
9739
|
}
|
|
9669
|
-
const
|
|
9740
|
+
const lineageFilterInnerPropsSchema$1 = z$1.object({
|
|
9741
|
+
initialValue: z$1.string().optional(),
|
|
9742
|
+
placeholderText: z$1.string().optional(),
|
|
9743
|
+
fields: z$1.array(z$1.string()).min(1)
|
|
9744
|
+
});
|
|
9745
|
+
const lineageFilterPropsSchema$1 = lineageFilterInnerPropsSchema$1.extend({
|
|
9746
|
+
width: z$1.string()
|
|
9747
|
+
});
|
|
9748
|
+
const LocationFilter = (props) => {
|
|
9749
|
+
const { width, ...innerProps } = props;
|
|
9670
9750
|
const size = { width, height: "3rem" };
|
|
9671
|
-
return /* @__PURE__ */ u$1(ErrorBoundary, { size, layout: "horizontal", children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(LocationFilterInner, { ...innerProps }) }) });
|
|
9751
|
+
return /* @__PURE__ */ u$1(ErrorBoundary, { size, layout: "horizontal", componentProps: props, schema: lineageFilterPropsSchema$1, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(LocationFilterInner, { ...innerProps }) }) });
|
|
9672
9752
|
};
|
|
9673
9753
|
const LocationFilterInner = ({ initialValue, fields, placeholderText }) => {
|
|
9674
9754
|
const lapis = x(LapisUrlContext);
|
|
@@ -9749,10 +9829,10 @@ var __decorateClass$3 = (decorators, target, key, kind) => {
|
|
|
9749
9829
|
let LocationFilterComponent = class extends PreactLitAdapter {
|
|
9750
9830
|
constructor() {
|
|
9751
9831
|
super(...arguments);
|
|
9752
|
-
this.initialValue =
|
|
9832
|
+
this.initialValue = void 0;
|
|
9753
9833
|
this.fields = [];
|
|
9754
9834
|
this.width = "100%";
|
|
9755
|
-
this.placeholderText =
|
|
9835
|
+
this.placeholderText = void 0;
|
|
9756
9836
|
}
|
|
9757
9837
|
render() {
|
|
9758
9838
|
return /* @__PURE__ */ u$1(
|
|
@@ -10439,9 +10519,18 @@ async function fetchLineageAutocompleteList(lapis, field, signal) {
|
|
|
10439
10519
|
const data = (await fetchAggregatedOperator.evaluate(lapis, signal)).content;
|
|
10440
10520
|
return data.flatMap((item) => [item[field], `${item[field]}*`]).sort();
|
|
10441
10521
|
}
|
|
10442
|
-
const
|
|
10522
|
+
const lineageFilterInnerPropsSchema = z$1.object({
|
|
10523
|
+
lapisField: z$1.string().min(1),
|
|
10524
|
+
placeholderText: z$1.string().optional(),
|
|
10525
|
+
initialValue: z$1.string()
|
|
10526
|
+
});
|
|
10527
|
+
const lineageFilterPropsSchema = lineageFilterInnerPropsSchema.extend({
|
|
10528
|
+
width: z$1.string()
|
|
10529
|
+
});
|
|
10530
|
+
const LineageFilter = (props) => {
|
|
10531
|
+
const { width, ...innerProps } = props;
|
|
10443
10532
|
const size = { width, height: "3rem" };
|
|
10444
|
-
return /* @__PURE__ */ u$1(ErrorBoundary, { size, layout: "horizontal", children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(LineageFilterInner, { ...innerProps }) }) });
|
|
10533
|
+
return /* @__PURE__ */ u$1(ErrorBoundary, { size, layout: "horizontal", componentProps: props, schema: lineageFilterPropsSchema, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(LineageFilterInner, { ...innerProps }) }) });
|
|
10445
10534
|
};
|
|
10446
10535
|
const LineageFilterInner = ({
|
|
10447
10536
|
lapisField,
|
|
@@ -10513,7 +10602,7 @@ let LineageFilterComponent = class extends PreactLitAdapter {
|
|
|
10513
10602
|
super(...arguments);
|
|
10514
10603
|
this.initialValue = "";
|
|
10515
10604
|
this.lapisField = "";
|
|
10516
|
-
this.placeholderText =
|
|
10605
|
+
this.placeholderText = void 0;
|
|
10517
10606
|
this.width = "100%";
|
|
10518
10607
|
}
|
|
10519
10608
|
render() {
|