@genspectrum/dashboard-components 0.6.18 → 0.6.19
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/README.md +5 -12
- package/custom-elements.json +4 -4
- package/dist/assets/mutationOverTimeWorker-BdzqDqvO.js.map +1 -0
- package/dist/dashboard-components.js +216 -214
- package/dist/dashboard-components.js.map +1 -1
- package/dist/genspectrum-components.d.ts +40 -40
- package/dist/style.css +3 -2
- package/package.json +13 -2
- package/src/operator/FetchInsertionsOperator.ts +2 -2
- package/src/operator/FetchSubstitutionsOrDeletionsOperator.ts +3 -3
- package/src/preact/mutationComparison/fetchMutationData.spec.ts +3 -3
- package/src/preact/mutationComparison/getMutationComparisonTableData.spec.ts +11 -11
- package/src/preact/mutationComparison/getMutationComparisonTableData.ts +4 -4
- package/src/preact/mutationComparison/mutation-comparison-table.tsx +2 -2
- package/src/preact/mutationFilter/mutation-filter.tsx +27 -18
- package/src/preact/mutationFilter/parseAndValidateMutation.ts +4 -4
- package/src/preact/mutationFilter/parseMutation.spec.ts +17 -17
- package/src/preact/mutations/getInsertionsTableData.spec.ts +3 -3
- package/src/preact/mutations/getMutationsGridData.spec.ts +9 -9
- package/src/preact/mutations/getMutationsTableData.spec.ts +7 -7
- package/src/preact/mutations/mutations-insertions-table.tsx +3 -3
- package/src/preact/mutations/mutations-table.tsx +3 -3
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay.ts +45686 -0
- package/src/preact/mutationsOverTime/__mockData__/byWeek.ts +58989 -0
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData.ts +103991 -0
- package/src/preact/mutationsOverTime/__mockData__/mockConversion.ts +54 -0
- package/src/preact/mutationsOverTime/__mockData__/showsMessageWhenTooManyMutations.ts +63690 -0
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +176 -159
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +17 -59
- package/src/preact/mutationsOverTime/mutationOverTimeWorker.mock.ts +27 -0
- package/src/preact/mutationsOverTime/mutationOverTimeWorker.ts +29 -0
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +13 -14
- package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +9 -334
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +68 -52
- package/src/preact/numberSequencesOverTime/getNumberOfSequencesOverTimeTableData.ts +3 -3
- package/src/preact/prevalenceOverTime/getPrevalenceOverTimeTableData.spec.ts +5 -5
- package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +1 -1
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage-chart.tsx +2 -2
- package/src/preact/shared/sort/sortInsertions.spec.ts +11 -11
- package/src/preact/shared/sort/sortInsertions.ts +2 -2
- package/src/preact/shared/sort/sortSubstitutionsAndDeletions.spec.ts +13 -13
- package/src/preact/shared/sort/sortSubstitutionsAndDeletions.ts +7 -4
- package/src/preact/webWorkers/useWebWorker.ts +51 -0
- package/src/preact/webWorkers/workerFunction.ts +14 -0
- package/src/query/queryAggregatedDataOverTime.ts +3 -3
- package/src/query/queryMutationsOverTime.spec.ts +272 -51
- package/src/query/queryMutationsOverTime.ts +114 -45
- package/src/query/queryPrevalenceOverTime.ts +2 -2
- package/src/query/queryRelativeGrowthAdvantage.ts +3 -3
- package/src/types.ts +25 -5
- package/src/utils/map2d.spec.ts +29 -1
- package/src/utils/map2d.ts +22 -1
- package/src/utils/mutations.spec.ts +20 -20
- package/src/utils/mutations.ts +80 -17
- package/src/utils/sort.ts +5 -2
- package/src/utils/temporal.spec.ts +27 -24
- package/src/utils/{temporal.ts → temporalClass.ts} +170 -72
- package/src/utils/temporalTestHelpers.ts +3 -3
- package/src/web-components/introduction.mdx +46 -0
- package/src/web-components/visualization/gs-mutations-over-time.stories.ts +6 -699
- package/src/web-components/visualization/gs-mutations-over-time.tsx +2 -2
- package/standalone-bundle/dashboard-components.js +13763 -13754
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_01.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_02.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_03.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_04.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_05.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_06.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_07.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_20_01_2024.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_21_01_2024.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_22_01_2024.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_23_01_2024.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_24_01_2024.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_25_01_2024.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_26_01_2024.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_byDay.json +0 -38
- package/src/preact/mutationsOverTime/__mockData__/aggregated_byWeek.json +0 -122
- package/src/preact/mutationsOverTime/__mockData__/aggregated_date.json +0 -642
- package/src/preact/mutationsOverTime/__mockData__/aggregated_tooManyMutations.json +0 -1470
- package/src/preact/mutationsOverTime/__mockData__/aggregated_tooManyMutations_total.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_week3_2024.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_week4_2024.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_week5_2024.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aggregated_week6_2024.json +0 -13
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_20_01_2024.json +0 -6778
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_21_01_2024.json +0 -7129
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_22_01_2024.json +0 -4681
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_23_01_2024.json +0 -10738
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_24_01_2024.json +0 -11710
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_25_01_2024.json +0 -11557
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_26_01_2024.json +0 -8596
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_byDayOverall.json +0 -4726
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_01.json +0 -1747
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_02.json +0 -1774
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_03.json +0 -1819
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_04.json +0 -1864
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_05.json +0 -1927
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_06.json +0 -1864
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_07.json +0 -9
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_byMonthOverall.json +0 -11143
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_byWeekOverall.json +0 -9154
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_tooManyMutations.json +0 -16453
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week3_2024.json +0 -8812
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week4_2024.json +0 -9730
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week5_2024.json +0 -9865
- package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week6_2024.json +0 -11314
|
@@ -550,11 +550,11 @@ App = __decorateClass$d([
|
|
|
550
550
|
var f$1 = 0;
|
|
551
551
|
function u$1(e2, t2, n3, o2, i2, u2) {
|
|
552
552
|
t2 || (t2 = {});
|
|
553
|
-
var a2, c2,
|
|
554
|
-
|
|
555
|
-
var
|
|
556
|
-
if ("function" == typeof e2 && (a2 = e2.defaultProps)) for (c2 in a2) void 0 ===
|
|
557
|
-
return options.vnode && options.vnode(
|
|
553
|
+
var a2, c2, l2 = t2;
|
|
554
|
+
"ref" in t2 && (a2 = t2.ref, delete t2.ref);
|
|
555
|
+
var p2 = { type: e2, props: l2, key: n3, ref: a2, __k: null, __: null, __b: 0, __e: null, __d: void 0, __c: null, constructor: void 0, __v: --f$1, __i: -1, __u: 0, __source: i2, __self: u2 };
|
|
556
|
+
if ("function" == typeof e2 && (a2 = e2.defaultProps)) for (c2 in a2) void 0 === l2[c2] && (l2[c2] = a2[c2]);
|
|
557
|
+
return options.vnode && options.vnode(p2), p2;
|
|
558
558
|
}
|
|
559
559
|
var t, r, u, i, o = 0, f = [], c = options, e = c.__b, a = c.__r, v = c.diffed, l = c.__c, m = c.unmount, s = c.__;
|
|
560
560
|
function d(n3, t2) {
|
|
@@ -776,7 +776,7 @@ const Table = ({ data, columns, pageSize }) => {
|
|
|
776
776
|
return /* @__PURE__ */ u$1("div", { ref: wrapper3 });
|
|
777
777
|
};
|
|
778
778
|
const substitutionRegex = /^((?<segment>[A-Za-z0-9_-]+)(?=:):)?(?<valueAtReference>[A-Za-z])?(?<position>\d+)(?<substitutionValue>[A-Za-z.])?$/;
|
|
779
|
-
class
|
|
779
|
+
class SubstitutionClass {
|
|
780
780
|
constructor(segment, valueAtReference, substitutionValue, position) {
|
|
781
781
|
this.segment = segment;
|
|
782
782
|
this.valueAtReference = valueAtReference;
|
|
@@ -789,7 +789,7 @@ class Substitution {
|
|
|
789
789
|
this.code = `${segmentString}${valueAtReferenceString}${this.position}${substitutionValueString}`;
|
|
790
790
|
}
|
|
791
791
|
equals(other) {
|
|
792
|
-
if (!(other instanceof
|
|
792
|
+
if (!(other instanceof SubstitutionClass)) {
|
|
793
793
|
return false;
|
|
794
794
|
}
|
|
795
795
|
return this.segment === other.segment && this.valueAtReference === other.valueAtReference && this.substitutionValue === other.substitutionValue && this.position === other.position;
|
|
@@ -802,7 +802,7 @@ class Substitution {
|
|
|
802
802
|
if (match === null || match.groups === void 0) {
|
|
803
803
|
return null;
|
|
804
804
|
}
|
|
805
|
-
return new
|
|
805
|
+
return new SubstitutionClass(
|
|
806
806
|
match.groups.segment,
|
|
807
807
|
match.groups.valueAtReference,
|
|
808
808
|
match.groups.substitutionValue,
|
|
@@ -811,7 +811,7 @@ class Substitution {
|
|
|
811
811
|
}
|
|
812
812
|
}
|
|
813
813
|
const deletionRegex = /^((?<segment>[A-Za-z0-9_-]+)(?=:):)?(?<valueAtReference>[A-Za-z])?(?<position>\d+)(-)$/;
|
|
814
|
-
class
|
|
814
|
+
class DeletionClass {
|
|
815
815
|
constructor(segment, valueAtReference, position) {
|
|
816
816
|
this.segment = segment;
|
|
817
817
|
this.valueAtReference = valueAtReference;
|
|
@@ -822,7 +822,7 @@ class Deletion {
|
|
|
822
822
|
this.code = `${segmentString}${valueAtReferenceString}${this.position}-`;
|
|
823
823
|
}
|
|
824
824
|
equals(other) {
|
|
825
|
-
if (!(other instanceof
|
|
825
|
+
if (!(other instanceof DeletionClass)) {
|
|
826
826
|
return false;
|
|
827
827
|
}
|
|
828
828
|
return this.segment === other.segment && this.valueAtReference === other.valueAtReference && this.position === other.position;
|
|
@@ -835,11 +835,15 @@ class Deletion {
|
|
|
835
835
|
if (match === null || match.groups === void 0) {
|
|
836
836
|
return null;
|
|
837
837
|
}
|
|
838
|
-
return new
|
|
838
|
+
return new DeletionClass(
|
|
839
|
+
match.groups.segment,
|
|
840
|
+
match.groups.valueAtReference,
|
|
841
|
+
parseInt(match.groups.position, 10)
|
|
842
|
+
);
|
|
839
843
|
}
|
|
840
844
|
}
|
|
841
845
|
const insertionRegexp = /^ins_((?<segment>[A-Za-z0-9_-]+)(?=:):)?(?<position>\d+):(?<insertedSymbols>(([A-Za-z?]|(\.\*))+))$/i;
|
|
842
|
-
class
|
|
846
|
+
class InsertionClass {
|
|
843
847
|
constructor(segment, position, insertedSymbols) {
|
|
844
848
|
this.segment = segment;
|
|
845
849
|
this.position = position;
|
|
@@ -848,7 +852,7 @@ class Insertion {
|
|
|
848
852
|
this.code = `ins_${this.segment ? `${this.segment}:` : ""}${this.position}:${this.insertedSymbols}`;
|
|
849
853
|
}
|
|
850
854
|
equals(other) {
|
|
851
|
-
if (!(other instanceof
|
|
855
|
+
if (!(other instanceof InsertionClass)) {
|
|
852
856
|
return false;
|
|
853
857
|
}
|
|
854
858
|
return this.segment === other.segment && this.insertedSymbols === other.insertedSymbols && this.position === other.position;
|
|
@@ -861,7 +865,11 @@ class Insertion {
|
|
|
861
865
|
if (match === null || match.groups === void 0) {
|
|
862
866
|
return null;
|
|
863
867
|
}
|
|
864
|
-
return new
|
|
868
|
+
return new InsertionClass(
|
|
869
|
+
match.groups.segment,
|
|
870
|
+
parseInt(match.groups.position, 10),
|
|
871
|
+
match.groups.insertedSymbols
|
|
872
|
+
);
|
|
865
873
|
}
|
|
866
874
|
}
|
|
867
875
|
const bases = {
|
|
@@ -897,8 +905,8 @@ const sortSubstitutionsAndDeletions = (a2, b3) => {
|
|
|
897
905
|
if (a2.position !== b3.position) {
|
|
898
906
|
return comparePositions(a2.position, b3.position);
|
|
899
907
|
}
|
|
900
|
-
const aIsDeletion = a2 instanceof
|
|
901
|
-
const bIsDeletion = b3 instanceof
|
|
908
|
+
const aIsDeletion = a2 instanceof DeletionClass;
|
|
909
|
+
const bIsDeletion = b3 instanceof DeletionClass;
|
|
902
910
|
if (aIsDeletion !== bIsDeletion) {
|
|
903
911
|
return aIsDeletion ? 1 : -1;
|
|
904
912
|
}
|
|
@@ -1094,14 +1102,14 @@ class FetchSubstitutionsOrDeletionsOperator {
|
|
|
1094
1102
|
if (mutationTo === "-") {
|
|
1095
1103
|
return {
|
|
1096
1104
|
type: "deletion",
|
|
1097
|
-
mutation: new
|
|
1105
|
+
mutation: new DeletionClass(sequenceName ?? void 0, mutationFrom, position),
|
|
1098
1106
|
count,
|
|
1099
1107
|
proportion
|
|
1100
1108
|
};
|
|
1101
1109
|
}
|
|
1102
1110
|
return {
|
|
1103
1111
|
type: "substitution",
|
|
1104
|
-
mutation: new
|
|
1112
|
+
mutation: new SubstitutionClass(sequenceName ?? void 0, mutationFrom, mutationTo, position),
|
|
1105
1113
|
count,
|
|
1106
1114
|
proportion
|
|
1107
1115
|
};
|
|
@@ -1183,8 +1191,8 @@ const CsvDownloadButton = ({
|
|
|
1183
1191
|
}) => {
|
|
1184
1192
|
const download = () => {
|
|
1185
1193
|
const content = getDownloadContent();
|
|
1186
|
-
const
|
|
1187
|
-
const url = URL.createObjectURL(
|
|
1194
|
+
const blob2 = new Blob([content], { type: "text/csv" });
|
|
1195
|
+
const url = URL.createObjectURL(blob2);
|
|
1188
1196
|
const a2 = document.createElement("a");
|
|
1189
1197
|
a2.href = url;
|
|
1190
1198
|
a2.download = filename;
|
|
@@ -2166,7 +2174,7 @@ const tailwindStyle = `*, ::before, ::after {
|
|
|
2166
2174
|
--tw-contain-paint: ;
|
|
2167
2175
|
--tw-contain-style: ;
|
|
2168
2176
|
}/*
|
|
2169
|
-
! tailwindcss v3.4.
|
|
2177
|
+
! tailwindcss v3.4.14 | MIT License | https://tailwindcss.com
|
|
2170
2178
|
*//*
|
|
2171
2179
|
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
|
|
2172
2180
|
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
|
|
@@ -2557,7 +2565,7 @@ video {
|
|
|
2557
2565
|
}
|
|
2558
2566
|
|
|
2559
2567
|
/* Make elements with the HTML hidden attribute stay hidden by default */
|
|
2560
|
-
[hidden] {
|
|
2568
|
+
[hidden]:where(:not([hidden="until-found"])) {
|
|
2561
2569
|
display: none;
|
|
2562
2570
|
}
|
|
2563
2571
|
|
|
@@ -4391,6 +4399,7 @@ input.tab:checked + .tab-content,
|
|
|
4391
4399
|
}
|
|
4392
4400
|
.join.join-horizontal > :where(*:not(:first-child)):is(.btn) {
|
|
4393
4401
|
margin-inline-start: calc(var(--border-btn) * -1);
|
|
4402
|
+
margin-top: 0px;
|
|
4394
4403
|
}
|
|
4395
4404
|
.modal-top :where(.modal-box) {
|
|
4396
4405
|
width: 100%;
|
|
@@ -5392,7 +5401,7 @@ class FetchInsertionsOperator {
|
|
|
5392
5401
|
const insertions = (await fetchInsertions(lapisUrl, this.filter, this.sequenceType, signal)).data;
|
|
5393
5402
|
const content = insertions.map(({ count, insertedSymbols, sequenceName, position }) => ({
|
|
5394
5403
|
type: "insertion",
|
|
5395
|
-
mutation: new
|
|
5404
|
+
mutation: new InsertionClass(sequenceName ?? void 0, position, insertedSymbols),
|
|
5396
5405
|
count
|
|
5397
5406
|
}));
|
|
5398
5407
|
return { content };
|
|
@@ -6420,25 +6429,25 @@ const _TemporalCache = class _TemporalCache {
|
|
|
6420
6429
|
}
|
|
6421
6430
|
getYearMonthDay(s2) {
|
|
6422
6431
|
if (!this.yearMonthDayCache.has(s2)) {
|
|
6423
|
-
this.yearMonthDayCache.set(s2,
|
|
6432
|
+
this.yearMonthDayCache.set(s2, YearMonthDayClass.parse(s2, this));
|
|
6424
6433
|
}
|
|
6425
6434
|
return this.yearMonthDayCache.get(s2);
|
|
6426
6435
|
}
|
|
6427
6436
|
getYearMonth(s2) {
|
|
6428
6437
|
if (!this.yearMonthCache.has(s2)) {
|
|
6429
|
-
this.yearMonthCache.set(s2,
|
|
6438
|
+
this.yearMonthCache.set(s2, YearMonthClass.parse(s2, this));
|
|
6430
6439
|
}
|
|
6431
6440
|
return this.yearMonthCache.get(s2);
|
|
6432
6441
|
}
|
|
6433
6442
|
getYearWeek(s2) {
|
|
6434
6443
|
if (!this.yearWeekCache.has(s2)) {
|
|
6435
|
-
this.yearWeekCache.set(s2,
|
|
6444
|
+
this.yearWeekCache.set(s2, YearWeekClass.parse(s2, this));
|
|
6436
6445
|
}
|
|
6437
6446
|
return this.yearWeekCache.get(s2);
|
|
6438
6447
|
}
|
|
6439
6448
|
getYear(s2) {
|
|
6440
6449
|
if (!this.yearCache.has(s2)) {
|
|
6441
|
-
this.yearCache.set(s2,
|
|
6450
|
+
this.yearCache.set(s2, YearClass.parse(s2, this));
|
|
6442
6451
|
}
|
|
6443
6452
|
return this.yearCache.get(s2);
|
|
6444
6453
|
}
|
|
@@ -6448,14 +6457,16 @@ const _TemporalCache = class _TemporalCache {
|
|
|
6448
6457
|
};
|
|
6449
6458
|
_TemporalCache.instance = new _TemporalCache();
|
|
6450
6459
|
let TemporalCache = _TemporalCache;
|
|
6451
|
-
class
|
|
6460
|
+
class YearMonthDayClass {
|
|
6452
6461
|
constructor(yearNumber, monthNumber, dayNumber, cache) {
|
|
6453
6462
|
this.yearNumber = yearNumber;
|
|
6454
6463
|
this.monthNumber = monthNumber;
|
|
6455
6464
|
this.dayNumber = dayNumber;
|
|
6456
6465
|
this.cache = cache;
|
|
6466
|
+
this.type = "YearMonthDay";
|
|
6457
6467
|
this.date = new Date(this.yearNumber, this.monthNumber - 1, this.dayNumber);
|
|
6458
6468
|
this.dayjs = dayjs(this.date);
|
|
6469
|
+
this.dateString = this.toString();
|
|
6459
6470
|
}
|
|
6460
6471
|
get text() {
|
|
6461
6472
|
return this.dayjs.format("YYYY-MM-DD");
|
|
@@ -6491,14 +6502,16 @@ class YearMonthDay {
|
|
|
6491
6502
|
}
|
|
6492
6503
|
static parse(s2, cache) {
|
|
6493
6504
|
const [year, month, day] = s2.split("-").map((s22) => parseInt(s22, 10));
|
|
6494
|
-
return new
|
|
6505
|
+
return new YearMonthDayClass(year, month, day, cache);
|
|
6495
6506
|
}
|
|
6496
6507
|
}
|
|
6497
|
-
class
|
|
6508
|
+
class YearWeekClass {
|
|
6498
6509
|
constructor(isoYearNumber, isoWeekNumber, cache) {
|
|
6499
6510
|
this.isoYearNumber = isoYearNumber;
|
|
6500
6511
|
this.isoWeekNumber = isoWeekNumber;
|
|
6501
6512
|
this.cache = cache;
|
|
6513
|
+
this.type = "YearWeek";
|
|
6514
|
+
this.dateString = this.toString();
|
|
6502
6515
|
}
|
|
6503
6516
|
get text() {
|
|
6504
6517
|
return this.firstDay.dayjs.format(FORMAT_ISO_WEEK_YEAR_WEEK);
|
|
@@ -6531,14 +6544,16 @@ class YearWeek {
|
|
|
6531
6544
|
}
|
|
6532
6545
|
static parse(s2, cache) {
|
|
6533
6546
|
const [year, week] = s2.split("-W").map((s22) => parseInt(s22, 10));
|
|
6534
|
-
return new
|
|
6547
|
+
return new YearWeekClass(year, week, cache);
|
|
6535
6548
|
}
|
|
6536
6549
|
}
|
|
6537
|
-
class
|
|
6550
|
+
class YearMonthClass {
|
|
6538
6551
|
constructor(yearNumber, monthNumber, cache) {
|
|
6539
6552
|
this.yearNumber = yearNumber;
|
|
6540
6553
|
this.monthNumber = monthNumber;
|
|
6541
6554
|
this.cache = cache;
|
|
6555
|
+
this.type = "YearMonth";
|
|
6556
|
+
this.dateString = this.toString();
|
|
6542
6557
|
}
|
|
6543
6558
|
get text() {
|
|
6544
6559
|
return this.firstDay.dayjs.format("YYYY-MM");
|
|
@@ -6570,13 +6585,15 @@ class YearMonth {
|
|
|
6570
6585
|
}
|
|
6571
6586
|
static parse(s2, cache) {
|
|
6572
6587
|
const [year, month] = s2.split("-").map((s22) => parseInt(s22, 10));
|
|
6573
|
-
return new
|
|
6588
|
+
return new YearMonthClass(year, month, cache);
|
|
6574
6589
|
}
|
|
6575
6590
|
}
|
|
6576
|
-
class
|
|
6591
|
+
class YearClass {
|
|
6577
6592
|
constructor(year, cache) {
|
|
6578
6593
|
this.year = year;
|
|
6579
6594
|
this.cache = cache;
|
|
6595
|
+
this.type = "Year";
|
|
6596
|
+
this.dateString = this.toString();
|
|
6580
6597
|
}
|
|
6581
6598
|
get text() {
|
|
6582
6599
|
return this.firstDay.dayjs.format("YYYY");
|
|
@@ -6609,12 +6626,29 @@ class Year {
|
|
|
6609
6626
|
}
|
|
6610
6627
|
static parse(s2, cache) {
|
|
6611
6628
|
const year = parseInt(s2, 10);
|
|
6612
|
-
return new
|
|
6629
|
+
return new YearClass(year, cache);
|
|
6613
6630
|
}
|
|
6614
6631
|
}
|
|
6615
6632
|
function monthName(month) {
|
|
6616
6633
|
return dayjs().month(month - 1).format("MMMM");
|
|
6617
6634
|
}
|
|
6635
|
+
function toTemporalClass(temporal) {
|
|
6636
|
+
switch (temporal.type) {
|
|
6637
|
+
case "YearMonthDay":
|
|
6638
|
+
return new YearMonthDayClass(
|
|
6639
|
+
temporal.yearNumber,
|
|
6640
|
+
temporal.monthNumber,
|
|
6641
|
+
temporal.dayNumber,
|
|
6642
|
+
TemporalCache.getInstance()
|
|
6643
|
+
);
|
|
6644
|
+
case "YearWeek":
|
|
6645
|
+
return new YearWeekClass(temporal.isoYearNumber, temporal.isoWeekNumber, TemporalCache.getInstance());
|
|
6646
|
+
case "YearMonth":
|
|
6647
|
+
return new YearMonthClass(temporal.yearNumber, temporal.monthNumber, TemporalCache.getInstance());
|
|
6648
|
+
case "Year":
|
|
6649
|
+
return new YearClass(temporal.year, TemporalCache.getInstance());
|
|
6650
|
+
}
|
|
6651
|
+
}
|
|
6618
6652
|
function generateAllDaysInRange(start, end) {
|
|
6619
6653
|
const days = [];
|
|
6620
6654
|
const daysInBetween = end.minus(start);
|
|
@@ -6651,31 +6685,31 @@ function generateAllInRange(start, end) {
|
|
|
6651
6685
|
if (start === null || end === null) {
|
|
6652
6686
|
return [];
|
|
6653
6687
|
}
|
|
6654
|
-
if (start instanceof
|
|
6688
|
+
if (start instanceof YearMonthDayClass && end instanceof YearMonthDayClass) {
|
|
6655
6689
|
return generateAllDaysInRange(start, end);
|
|
6656
6690
|
}
|
|
6657
|
-
if (start instanceof
|
|
6691
|
+
if (start instanceof YearWeekClass && end instanceof YearWeekClass) {
|
|
6658
6692
|
return generateAllWeeksInRange(start, end);
|
|
6659
6693
|
}
|
|
6660
|
-
if (start instanceof
|
|
6694
|
+
if (start instanceof YearMonthClass && end instanceof YearMonthClass) {
|
|
6661
6695
|
return generateAllMonthsInRange(start, end);
|
|
6662
6696
|
}
|
|
6663
|
-
if (start instanceof
|
|
6697
|
+
if (start instanceof YearClass && end instanceof YearClass) {
|
|
6664
6698
|
return generateAllYearsInRange(start, end);
|
|
6665
6699
|
}
|
|
6666
6700
|
throw new Error(`Invalid arguments: start and end must be of the same type: ${start}, ${end}`);
|
|
6667
6701
|
}
|
|
6668
6702
|
function minusTemporal(a2, b3) {
|
|
6669
|
-
if (a2 instanceof
|
|
6703
|
+
if (a2 instanceof YearMonthDayClass && b3 instanceof YearMonthDayClass) {
|
|
6670
6704
|
return a2.minus(b3);
|
|
6671
6705
|
}
|
|
6672
|
-
if (a2 instanceof
|
|
6706
|
+
if (a2 instanceof YearWeekClass && b3 instanceof YearWeekClass) {
|
|
6673
6707
|
return a2.minus(b3);
|
|
6674
6708
|
}
|
|
6675
|
-
if (a2 instanceof
|
|
6709
|
+
if (a2 instanceof YearMonthClass && b3 instanceof YearMonthClass) {
|
|
6676
6710
|
return a2.minus(b3);
|
|
6677
6711
|
}
|
|
6678
|
-
if (a2 instanceof
|
|
6712
|
+
if (a2 instanceof YearClass && b3 instanceof YearClass) {
|
|
6679
6713
|
return a2.minus(b3);
|
|
6680
6714
|
}
|
|
6681
6715
|
throw new Error(`Cannot compare ${a2} and ${b3}`);
|
|
@@ -6716,16 +6750,16 @@ function getMinMaxTemporal(values) {
|
|
|
6716
6750
|
return { min, max };
|
|
6717
6751
|
}
|
|
6718
6752
|
function addUnit(temporal, amount) {
|
|
6719
|
-
if (temporal instanceof
|
|
6753
|
+
if (temporal instanceof YearMonthDayClass) {
|
|
6720
6754
|
return temporal.addDays(amount);
|
|
6721
6755
|
}
|
|
6722
|
-
if (temporal instanceof
|
|
6756
|
+
if (temporal instanceof YearWeekClass) {
|
|
6723
6757
|
return temporal.addWeeks(amount);
|
|
6724
6758
|
}
|
|
6725
|
-
if (temporal instanceof
|
|
6759
|
+
if (temporal instanceof YearMonthClass) {
|
|
6726
6760
|
return temporal.addMonths(amount);
|
|
6727
6761
|
}
|
|
6728
|
-
if (temporal instanceof
|
|
6762
|
+
if (temporal instanceof YearClass) {
|
|
6729
6763
|
return temporal.addYears(amount);
|
|
6730
6764
|
}
|
|
6731
6765
|
throw new Error(`Invalid argument: ${temporal}`);
|
|
@@ -8435,13 +8469,44 @@ __decorateClass$6([
|
|
|
8435
8469
|
NumberSequencesOverTimeComponent = __decorateClass$6([
|
|
8436
8470
|
t$2("gs-number-sequences-over-time")
|
|
8437
8471
|
], NumberSequencesOverTimeComponent);
|
|
8472
|
+
const encodedJs = "KGZ1bmN0aW9uKCkgewogICJ1c2Ugc3RyaWN0IjsKICB2YXIgdXRpbDsKICAoZnVuY3Rpb24odXRpbDIpIHsKICAgIHV0aWwyLmFzc2VydEVxdWFsID0gKHZhbCkgPT4gdmFsOwogICAgZnVuY3Rpb24gYXNzZXJ0SXMoX2FyZykgewogICAgfQogICAgdXRpbDIuYXNzZXJ0SXMgPSBhc3NlcnRJczsKICAgIGZ1bmN0aW9uIGFzc2VydE5ldmVyKF94KSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigpOwogICAgfQogICAgdXRpbDIuYXNzZXJ0TmV2ZXIgPSBhc3NlcnROZXZlcjsKICAgIHV0aWwyLmFycmF5VG9FbnVtID0gKGl0ZW1zKSA9PiB7CiAgICAgIGNvbnN0IG9iaiA9IHt9OwogICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHsKICAgICAgICBvYmpbaXRlbV0gPSBpdGVtOwogICAgICB9CiAgICAgIHJldHVybiBvYmo7CiAgICB9OwogICAgdXRpbDIuZ2V0VmFsaWRFbnVtVmFsdWVzID0gKG9iaikgPT4gewogICAgICBjb25zdCB2YWxpZEtleXMgPSB1dGlsMi5vYmplY3RLZXlzKG9iaikuZmlsdGVyKChrMikgPT4gdHlwZW9mIG9ialtvYmpbazJdXSAhPT0gIm51bWJlciIpOwogICAgICBjb25zdCBmaWx0ZXJlZCA9IHt9OwogICAgICBmb3IgKGNvbnN0IGsyIG9mIHZhbGlkS2V5cykgewogICAgICAgIGZpbHRlcmVkW2syXSA9IG9ialtrMl07CiAgICAgIH0KICAgICAgcmV0dXJuIHV0aWwyLm9iamVjdFZhbHVlcyhmaWx0ZXJlZCk7CiAgICB9OwogICAgdXRpbDIub2JqZWN0VmFsdWVzID0gKG9iaikgPT4gewogICAgICByZXR1cm4gdXRpbDIub2JqZWN0S2V5cyhvYmopLm1hcChmdW5jdGlvbihlMikgewogICAgICAgIHJldHVybiBvYmpbZTJdOwogICAgICB9KTsKICAgIH07CiAgICB1dGlsMi5vYmplY3RLZXlzID0gdHlwZW9mIE9iamVjdC5rZXlzID09PSAiZnVuY3Rpb24iID8gKG9iaikgPT4gT2JqZWN0LmtleXMob2JqKSA6IChvYmplY3QpID0+IHsKICAgICAgY29uc3Qga2V5cyA9IFtdOwogICAgICBmb3IgKGNvbnN0IGtleSBpbiBvYmplY3QpIHsKICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkgewogICAgICAgICAga2V5cy5wdXNoKGtleSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBrZXlzOwogICAgfTsKICAgIHV0aWwyLmZpbmQgPSAoYXJyLCBjaGVja2VyKSA9PiB7CiAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBhcnIpIHsKICAgICAgICBpZiAoY2hlY2tlcihpdGVtKSkKICAgICAgICAgIHJldHVybiBpdGVtOwogICAgICB9CiAgICAgIHJldHVybiB2b2lkIDA7CiAgICB9OwogICAgdXRpbDIuaXNJbnRlZ2VyID0gdHlwZW9mIE51bWJlci5pc0ludGVnZXIgPT09ICJmdW5jdGlvbiIgPyAodmFsKSA9PiBOdW1iZXIuaXNJbnRlZ2VyKHZhbCkgOiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAibnVtYmVyIiAmJiBpc0Zpbml0ZSh2YWwpICYmIE1hdGguZmxvb3IodmFsKSA9PT0gdmFsOwogICAgZnVuY3Rpb24gam9pblZhbHVlcyhhcnJheSwgc2VwYXJhdG9yID0gIiB8ICIpIHsKICAgICAgcmV0dXJuIGFycmF5Lm1hcCgodmFsKSA9PiB0eXBlb2YgdmFsID09PSAic3RyaW5nIiA/IGAnJHt2YWx9J2AgOiB2YWwpLmpvaW4oc2VwYXJhdG9yKTsKICAgIH0KICAgIHV0aWwyLmpvaW5WYWx1ZXMgPSBqb2luVmFsdWVzOwogICAgdXRpbDIuanNvblN0cmluZ2lmeVJlcGxhY2VyID0gKF8sIHZhbHVlKSA9PiB7CiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJiaWdpbnQiKSB7CiAgICAgICAgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIHZhbHVlOwogICAgfTsKICB9KSh1dGlsIHx8ICh1dGlsID0ge30pKTsKICB2YXIgb2JqZWN0VXRpbDsKICAoZnVuY3Rpb24ob2JqZWN0VXRpbDIpIHsKICAgIG9iamVjdFV0aWwyLm1lcmdlU2hhcGVzID0gKGZpcnN0LCBzZWNvbmQpID0+IHsKICAgICAgcmV0dXJuIHsKICAgICAgICAuLi5maXJzdCwKICAgICAgICAuLi5zZWNvbmQKICAgICAgICAvLyBzZWNvbmQgb3ZlcndyaXRlcyBmaXJzdAogICAgICB9OwogICAgfTsKICB9KShvYmplY3RVdGlsIHx8IChvYmplY3RVdGlsID0ge30pKTsKICBjb25zdCBab2RQYXJzZWRUeXBlID0gdXRpbC5hcnJheVRvRW51bShbCiAgICAic3RyaW5nIiwKICAgICJuYW4iLAogICAgIm51bWJlciIsCiAgICAiaW50ZWdlciIsCiAgICAiZmxvYXQiLAogICAgImJvb2xlYW4iLAogICAgImRhdGUiLAogICAgImJpZ2ludCIsCiAgICAic3ltYm9sIiwKICAgICJmdW5jdGlvbiIsCiAgICAidW5kZWZpbmVkIiwKICAgICJudWxsIiwKICAgICJhcnJheSIsCiAgICAib2JqZWN0IiwKICAgICJ1bmtub3duIiwKICAgICJwcm9taXNlIiwKICAgICJ2b2lkIiwKICAgICJuZXZlciIsCiAgICAibWFwIiwKICAgICJzZXQiCiAgXSk7CiAgY29uc3QgZ2V0UGFyc2VkVHlwZSA9IChkYXRhKSA9PiB7CiAgICBjb25zdCB0ID0gdHlwZW9mIGRhdGE7CiAgICBzd2l0Y2ggKHQpIHsKICAgICAgY2FzZSAidW5kZWZpbmVkIjoKICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS51bmRlZmluZWQ7CiAgICAgIGNhc2UgInN0cmluZyI6CiAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc3RyaW5nOwogICAgICBjYXNlICJudW1iZXIiOgogICAgICAgIHJldHVybiBpc05hTihkYXRhKSA/IFpvZFBhcnNlZFR5cGUubmFuIDogWm9kUGFyc2VkVHlwZS5udW1iZXI7CiAgICAgIGNhc2UgImJvb2xlYW4iOgogICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLmJvb2xlYW47CiAgICAgIGNhc2UgImZ1bmN0aW9uIjoKICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5mdW5jdGlvbjsKICAgICAgY2FzZSAiYmlnaW50IjoKICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5iaWdpbnQ7CiAgICAgIGNhc2UgInN5bWJvbCI6CiAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc3ltYm9sOwogICAgICBjYXNlICJvYmplY3QiOgogICAgICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7CiAgICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5hcnJheTsKICAgICAgICB9CiAgICAgICAgaWYgKGRhdGEgPT09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBab2RQYXJzZWRUeXBlLm51bGw7CiAgICAgICAgfQogICAgICAgIGlmIChkYXRhLnRoZW4gJiYgdHlwZW9mIGRhdGEudGhlbiA9PT0gImZ1bmN0aW9uIiAmJiBkYXRhLmNhdGNoICYmIHR5cGVvZiBkYXRhLmNhdGNoID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5wcm9taXNlOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIE1hcCAhPT0gInVuZGVmaW5lZCIgJiYgZGF0YSBpbnN0YW5jZW9mIE1hcCkgewogICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUubWFwOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIFNldCAhPT0gInVuZGVmaW5lZCIgJiYgZGF0YSBpbnN0YW5jZW9mIFNldCkgewogICAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUuc2V0OwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIERhdGUgIT09ICJ1bmRlZmluZWQiICYmIGRhdGEgaW5zdGFuY2VvZiBEYXRlKSB7CiAgICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5kYXRlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gWm9kUGFyc2VkVHlwZS5vYmplY3Q7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuIFpvZFBhcnNlZFR5cGUudW5rbm93bjsKICAgIH0KICB9OwogIGNvbnN0IFpvZElzc3VlQ29kZSA9IHV0aWwuYXJyYXlUb0VudW0oWwogICAgImludmFsaWRfdHlwZSIsCiAgICAiaW52YWxpZF9saXRlcmFsIiwKICAgICJjdXN0b20iLAogICAgImludmFsaWRfdW5pb24iLAogICAgImludmFsaWRfdW5pb25fZGlzY3JpbWluYXRvciIsCiAgICAiaW52YWxpZF9lbnVtX3ZhbHVlIiwKICAgICJ1bnJlY29nbml6ZWRfa2V5cyIsCiAgICAiaW52YWxpZF9hcmd1bWVudHMiLAogICAgImludmFsaWRfcmV0dXJuX3R5cGUiLAogICAgImludmFsaWRfZGF0ZSIsCiAgICAiaW52YWxpZF9zdHJpbmciLAogICAgInRvb19zbWFsbCIsCiAgICAidG9vX2JpZyIsCiAgICAiaW52YWxpZF9pbnRlcnNlY3Rpb25fdHlwZXMiLAogICAgIm5vdF9tdWx0aXBsZV9vZiIsCiAgICAibm90X2Zpbml0ZSIKICBdKTsKICBjb25zdCBxdW90ZWxlc3NKc29uID0gKG9iaikgPT4gewogICAgY29uc3QganNvbiA9IEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgMik7CiAgICByZXR1cm4ganNvbi5yZXBsYWNlKC8iKFteIl0rKSI6L2csICIkMToiKTsKICB9OwogIGNsYXNzIFpvZEVycm9yIGV4dGVuZHMgRXJyb3IgewogICAgY29uc3RydWN0b3IoaXNzdWVzKSB7CiAgICAgIHN1cGVyKCk7CiAgICAgIHRoaXMuaXNzdWVzID0gW107CiAgICAgIHRoaXMuYWRkSXNzdWUgPSAoc3ViKSA9PiB7CiAgICAgICAgdGhpcy5pc3N1ZXMgPSBbLi4udGhpcy5pc3N1ZXMsIHN1Yl07CiAgICAgIH07CiAgICAgIHRoaXMuYWRkSXNzdWVzID0gKHN1YnMgPSBbXSkgPT4gewogICAgICAgIHRoaXMuaXNzdWVzID0gWy4uLnRoaXMuaXNzdWVzLCAuLi5zdWJzXTsKICAgICAgfTsKICAgICAgY29uc3QgYWN0dWFsUHJvdG8gPSBuZXcudGFyZ2V0LnByb3RvdHlwZTsKICAgICAgaWYgKE9iamVjdC5zZXRQcm90b3R5cGVPZikgewogICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBhY3R1YWxQcm90byk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fX3Byb3RvX18gPSBhY3R1YWxQcm90bzsKICAgICAgfQogICAgICB0aGlzLm5hbWUgPSAiWm9kRXJyb3IiOwogICAgICB0aGlzLmlzc3VlcyA9IGlzc3VlczsKICAgIH0KICAgIGdldCBlcnJvcnMoKSB7CiAgICAgIHJldHVybiB0aGlzLmlzc3VlczsKICAgIH0KICAgIGZvcm1hdChfbWFwcGVyKSB7CiAgICAgIGNvbnN0IG1hcHBlciA9IF9tYXBwZXIgfHwgZnVuY3Rpb24oaXNzdWUpIHsKICAgICAgICByZXR1cm4gaXNzdWUubWVzc2FnZTsKICAgICAgfTsKICAgICAgY29uc3QgZmllbGRFcnJvcnMgPSB7IF9lcnJvcnM6IFtdIH07CiAgICAgIGNvbnN0IHByb2Nlc3NFcnJvciA9IChlcnJvcikgPT4gewogICAgICAgIGZvciAoY29uc3QgaXNzdWUgb2YgZXJyb3IuaXNzdWVzKSB7CiAgICAgICAgICBpZiAoaXNzdWUuY29kZSA9PT0gImludmFsaWRfdW5pb24iKSB7CiAgICAgICAgICAgIGlzc3VlLnVuaW9uRXJyb3JzLm1hcChwcm9jZXNzRXJyb3IpOwogICAgICAgICAgfSBlbHNlIGlmIChpc3N1ZS5jb2RlID09PSAiaW52YWxpZF9yZXR1cm5fdHlwZSIpIHsKICAgICAgICAgICAgcHJvY2Vzc0Vycm9yKGlzc3VlLnJldHVyblR5cGVFcnJvcik7CiAgICAgICAgICB9IGVsc2UgaWYgKGlzc3VlLmNvZGUgPT09ICJpbnZhbGlkX2FyZ3VtZW50cyIpIHsKICAgICAgICAgICAgcHJvY2Vzc0Vycm9yKGlzc3VlLmFyZ3VtZW50c0Vycm9yKTsKICAgICAgICAgIH0gZWxzZSBpZiAoaXNzdWUucGF0aC5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgZmllbGRFcnJvcnMuX2Vycm9ycy5wdXNoKG1hcHBlcihpc3N1ZSkpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgbGV0IGN1cnIgPSBmaWVsZEVycm9yczsKICAgICAgICAgICAgbGV0IGkyID0gMDsKICAgICAgICAgICAgd2hpbGUgKGkyIDwgaXNzdWUucGF0aC5sZW5ndGgpIHsKICAgICAgICAgICAgICBjb25zdCBlbCA9IGlzc3VlLnBhdGhbaTJdOwogICAgICAgICAgICAgIGNvbnN0IHRlcm1pbmFsID0gaTIgPT09IGlzc3VlLnBhdGgubGVuZ3RoIC0gMTsKICAgICAgICAgICAgICBpZiAoIXRlcm1pbmFsKSB7CiAgICAgICAgICAgICAgICBjdXJyW2VsXSA9IGN1cnJbZWxdIHx8IHsgX2Vycm9yczogW10gfTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgY3VycltlbF0gPSBjdXJyW2VsXSB8fCB7IF9lcnJvcnM6IFtdIH07CiAgICAgICAgICAgICAgICBjdXJyW2VsXS5fZXJyb3JzLnB1c2gobWFwcGVyKGlzc3VlKSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGN1cnIgPSBjdXJyW2VsXTsKICAgICAgICAgICAgICBpMisrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9OwogICAgICBwcm9jZXNzRXJyb3IodGhpcyk7CiAgICAgIHJldHVybiBmaWVsZEVycm9yczsKICAgIH0KICAgIHN0YXRpYyBhc3NlcnQodmFsdWUpIHsKICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBab2RFcnJvcikpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vdCBhIFpvZEVycm9yOiAke3ZhbHVlfWApOwogICAgICB9CiAgICB9CiAgICB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZTsKICAgIH0KICAgIGdldCBtZXNzYWdlKCkgewogICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy5pc3N1ZXMsIHV0aWwuanNvblN0cmluZ2lmeVJlcGxhY2VyLCAyKTsKICAgIH0KICAgIGdldCBpc0VtcHR5KCkgewogICAgICByZXR1cm4gdGhpcy5pc3N1ZXMubGVuZ3RoID09PSAwOwogICAgfQogICAgZmxhdHRlbihtYXBwZXIgPSAoaXNzdWUpID0+IGlzc3VlLm1lc3NhZ2UpIHsKICAgICAgY29uc3QgZmllbGRFcnJvcnMgPSB7fTsKICAgICAgY29uc3QgZm9ybUVycm9ycyA9IFtdOwogICAgICBmb3IgKGNvbnN0IHN1YiBvZiB0aGlzLmlzc3VlcykgewogICAgICAgIGlmIChzdWIucGF0aC5sZW5ndGggPiAwKSB7CiAgICAgICAgICBmaWVsZEVycm9yc1tzdWIucGF0aFswXV0gPSBmaWVsZEVycm9yc1tzdWIucGF0aFswXV0gfHwgW107CiAgICAgICAgICBmaWVsZEVycm9yc1tzdWIucGF0aFswXV0ucHVzaChtYXBwZXIoc3ViKSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGZvcm1FcnJvcnMucHVzaChtYXBwZXIoc3ViKSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiB7IGZvcm1FcnJvcnMsIGZpZWxkRXJyb3JzIH07CiAgICB9CiAgICBnZXQgZm9ybUVycm9ycygpIHsKICAgICAgcmV0dXJuIHRoaXMuZmxhdHRlbigpOwogICAgfQogIH0KICBab2RFcnJvci5jcmVhdGUgPSAoaXNzdWVzKSA9PiB7CiAgICBjb25zdCBlcnJvciA9IG5ldyBab2RFcnJvcihpc3N1ZXMpOwogICAgcmV0dXJuIGVycm9yOwogIH07CiAgY29uc3QgZXJyb3JNYXAgPSAoaXNzdWUsIF9jdHgpID0+IHsKICAgIGxldCBtZXNzYWdlOwogICAgc3dpdGNoIChpc3N1ZS5jb2RlKSB7CiAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZToKICAgICAgICBpZiAoaXNzdWUucmVjZWl2ZWQgPT09IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkKSB7CiAgICAgICAgICBtZXNzYWdlID0gIlJlcXVpcmVkIjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbWVzc2FnZSA9IGBFeHBlY3RlZCAke2lzc3VlLmV4cGVjdGVkfSwgcmVjZWl2ZWQgJHtpc3N1ZS5yZWNlaXZlZH1gOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9saXRlcmFsOgogICAgICAgIG1lc3NhZ2UgPSBgSW52YWxpZCBsaXRlcmFsIHZhbHVlLCBleHBlY3RlZCAke0pTT04uc3RyaW5naWZ5KGlzc3VlLmV4cGVjdGVkLCB1dGlsLmpzb25TdHJpbmdpZnlSZXBsYWNlcil9YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUudW5yZWNvZ25pemVkX2tleXM6CiAgICAgICAgbWVzc2FnZSA9IGBVbnJlY29nbml6ZWQga2V5KHMpIGluIG9iamVjdDogJHt1dGlsLmpvaW5WYWx1ZXMoaXNzdWUua2V5cywgIiwgIil9YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF91bmlvbjoKICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgaW5wdXRgOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFpvZElzc3VlQ29kZS5pbnZhbGlkX3VuaW9uX2Rpc2NyaW1pbmF0b3I6CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGRpc2NyaW1pbmF0b3IgdmFsdWUuIEV4cGVjdGVkICR7dXRpbC5qb2luVmFsdWVzKGlzc3VlLm9wdGlvbnMpfWA7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfZW51bV92YWx1ZToKICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgZW51bSB2YWx1ZS4gRXhwZWN0ZWQgJHt1dGlsLmpvaW5WYWx1ZXMoaXNzdWUub3B0aW9ucyl9LCByZWNlaXZlZCAnJHtpc3N1ZS5yZWNlaXZlZH0nYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9hcmd1bWVudHM6CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGZ1bmN0aW9uIGFyZ3VtZW50c2A7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgWm9kSXNzdWVDb2RlLmludmFsaWRfcmV0dXJuX3R5cGU6CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGZ1bmN0aW9uIHJldHVybiB0eXBlYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9kYXRlOgogICAgICAgIG1lc3NhZ2UgPSBgSW52YWxpZCBkYXRlYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmc6CiAgICAgICAgaWYgKHR5cGVvZiBpc3N1ZS52YWxpZGF0aW9uID09PSAib2JqZWN0IikgewogICAgICAgICAgaWYgKCJpbmNsdWRlcyIgaW4gaXNzdWUudmFsaWRhdGlvbikgewogICAgICAgICAgICBtZXNzYWdlID0gYEludmFsaWQgaW5wdXQ6IG11c3QgaW5jbHVkZSAiJHtpc3N1ZS52YWxpZGF0aW9uLmluY2x1ZGVzfSJgOwogICAgICAgICAgICBpZiAodHlwZW9mIGlzc3VlLnZhbGlkYXRpb24ucG9zaXRpb24gPT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgICAgbWVzc2FnZSA9IGAke21lc3NhZ2V9IGF0IG9uZSBvciBtb3JlIHBvc2l0aW9ucyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gJHtpc3N1ZS52YWxpZGF0aW9uLnBvc2l0aW9ufWA7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSBpZiAoInN0YXJ0c1dpdGgiIGluIGlzc3VlLnZhbGlkYXRpb24pIHsKICAgICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGlucHV0OiBtdXN0IHN0YXJ0IHdpdGggIiR7aXNzdWUudmFsaWRhdGlvbi5zdGFydHNXaXRofSJgOwogICAgICAgICAgfSBlbHNlIGlmICgiZW5kc1dpdGgiIGluIGlzc3VlLnZhbGlkYXRpb24pIHsKICAgICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGlucHV0OiBtdXN0IGVuZCB3aXRoICIke2lzc3VlLnZhbGlkYXRpb24uZW5kc1dpdGh9ImA7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB1dGlsLmFzc2VydE5ldmVyKGlzc3VlLnZhbGlkYXRpb24pOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoaXNzdWUudmFsaWRhdGlvbiAhPT0gInJlZ2V4IikgewogICAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkICR7aXNzdWUudmFsaWRhdGlvbn1gOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBtZXNzYWdlID0gIkludmFsaWQiOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUudG9vX3NtYWxsOgogICAgICAgIGlmIChpc3N1ZS50eXBlID09PSAiYXJyYXkiKQogICAgICAgICAgbWVzc2FnZSA9IGBBcnJheSBtdXN0IGNvbnRhaW4gJHtpc3N1ZS5leGFjdCA/ICJleGFjdGx5IiA6IGlzc3VlLmluY2x1c2l2ZSA/IGBhdCBsZWFzdGAgOiBgbW9yZSB0aGFuYH0gJHtpc3N1ZS5taW5pbXVtfSBlbGVtZW50KHMpYDsKICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSAic3RyaW5nIikKICAgICAgICAgIG1lc3NhZ2UgPSBgU3RyaW5nIG11c3QgY29udGFpbiAke2lzc3VlLmV4YWN0ID8gImV4YWN0bHkiIDogaXNzdWUuaW5jbHVzaXZlID8gYGF0IGxlYXN0YCA6IGBvdmVyYH0gJHtpc3N1ZS5taW5pbXVtfSBjaGFyYWN0ZXIocylgOwogICAgICAgIGVsc2UgaWYgKGlzc3VlLnR5cGUgPT09ICJudW1iZXIiKQogICAgICAgICAgbWVzc2FnZSA9IGBOdW1iZXIgbXVzdCBiZSAke2lzc3VlLmV4YWN0ID8gYGV4YWN0bHkgZXF1YWwgdG8gYCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYCA6IGBncmVhdGVyIHRoYW4gYH0ke2lzc3VlLm1pbmltdW19YDsKICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSAiZGF0ZSIpCiAgICAgICAgICBtZXNzYWdlID0gYERhdGUgbXVzdCBiZSAke2lzc3VlLmV4YWN0ID8gYGV4YWN0bHkgZXF1YWwgdG8gYCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYCA6IGBncmVhdGVyIHRoYW4gYH0ke25ldyBEYXRlKE51bWJlcihpc3N1ZS5taW5pbXVtKSl9YDsKICAgICAgICBlbHNlCiAgICAgICAgICBtZXNzYWdlID0gIkludmFsaWQgaW5wdXQiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFpvZElzc3VlQ29kZS50b29fYmlnOgogICAgICAgIGlmIChpc3N1ZS50eXBlID09PSAiYXJyYXkiKQogICAgICAgICAgbWVzc2FnZSA9IGBBcnJheSBtdXN0IGNvbnRhaW4gJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5YCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBhdCBtb3N0YCA6IGBsZXNzIHRoYW5gfSAke2lzc3VlLm1heGltdW19IGVsZW1lbnQocylgOwogICAgICAgIGVsc2UgaWYgKGlzc3VlLnR5cGUgPT09ICJzdHJpbmciKQogICAgICAgICAgbWVzc2FnZSA9IGBTdHJpbmcgbXVzdCBjb250YWluICR7aXNzdWUuZXhhY3QgPyBgZXhhY3RseWAgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgYXQgbW9zdGAgOiBgdW5kZXJgfSAke2lzc3VlLm1heGltdW19IGNoYXJhY3RlcihzKWA7CiAgICAgICAgZWxzZSBpZiAoaXNzdWUudHlwZSA9PT0gIm51bWJlciIpCiAgICAgICAgICBtZXNzYWdlID0gYE51bWJlciBtdXN0IGJlICR7aXNzdWUuZXhhY3QgPyBgZXhhY3RseWAgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgbGVzcyB0aGFuIG9yIGVxdWFsIHRvYCA6IGBsZXNzIHRoYW5gfSAke2lzc3VlLm1heGltdW19YDsKICAgICAgICBlbHNlIGlmIChpc3N1ZS50eXBlID09PSAiYmlnaW50IikKICAgICAgICAgIG1lc3NhZ2UgPSBgQmlnSW50IG11c3QgYmUgJHtpc3N1ZS5leGFjdCA/IGBleGFjdGx5YCA6IGlzc3VlLmluY2x1c2l2ZSA/IGBsZXNzIHRoYW4gb3IgZXF1YWwgdG9gIDogYGxlc3MgdGhhbmB9ICR7aXNzdWUubWF4aW11bX1gOwogICAgICAgIGVsc2UgaWYgKGlzc3VlLnR5cGUgPT09ICJkYXRlIikKICAgICAgICAgIG1lc3NhZ2UgPSBgRGF0ZSBtdXN0IGJlICR7aXNzdWUuZXhhY3QgPyBgZXhhY3RseWAgOiBpc3N1ZS5pbmNsdXNpdmUgPyBgc21hbGxlciB0aGFuIG9yIGVxdWFsIHRvYCA6IGBzbWFsbGVyIHRoYW5gfSAke25ldyBEYXRlKE51bWJlcihpc3N1ZS5tYXhpbXVtKSl9YDsKICAgICAgICBlbHNlCiAgICAgICAgICBtZXNzYWdlID0gIkludmFsaWQgaW5wdXQiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFpvZElzc3VlQ29kZS5jdXN0b206CiAgICAgICAgbWVzc2FnZSA9IGBJbnZhbGlkIGlucHV0YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUuaW52YWxpZF9pbnRlcnNlY3Rpb25fdHlwZXM6CiAgICAgICAgbWVzc2FnZSA9IGBJbnRlcnNlY3Rpb24gcmVzdWx0cyBjb3VsZCBub3QgYmUgbWVyZ2VkYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUubm90X211bHRpcGxlX29mOgogICAgICAgIG1lc3NhZ2UgPSBgTnVtYmVyIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAke2lzc3VlLm11bHRpcGxlT2Z9YDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBab2RJc3N1ZUNvZGUubm90X2Zpbml0ZToKICAgICAgICBtZXNzYWdlID0gIk51bWJlciBtdXN0IGJlIGZpbml0ZSI7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgbWVzc2FnZSA9IF9jdHguZGVmYXVsdEVycm9yOwogICAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoaXNzdWUpOwogICAgfQogICAgcmV0dXJuIHsgbWVzc2FnZSB9OwogIH07CiAgbGV0IG92ZXJyaWRlRXJyb3JNYXAgPSBlcnJvck1hcDsKICBmdW5jdGlvbiBzZXRFcnJvck1hcChtYXApIHsKICAgIG92ZXJyaWRlRXJyb3JNYXAgPSBtYXA7CiAgfQogIGZ1bmN0aW9uIGdldEVycm9yTWFwKCkgewogICAgcmV0dXJuIG92ZXJyaWRlRXJyb3JNYXA7CiAgfQogIGNvbnN0IG1ha2VJc3N1ZSA9IChwYXJhbXMpID0+IHsKICAgIGNvbnN0IHsgZGF0YSwgcGF0aCwgZXJyb3JNYXBzLCBpc3N1ZURhdGEgfSA9IHBhcmFtczsKICAgIGNvbnN0IGZ1bGxQYXRoID0gWy4uLnBhdGgsIC4uLmlzc3VlRGF0YS5wYXRoIHx8IFtdXTsKICAgIGNvbnN0IGZ1bGxJc3N1ZSA9IHsKICAgICAgLi4uaXNzdWVEYXRhLAogICAgICBwYXRoOiBmdWxsUGF0aAogICAgfTsKICAgIGlmIChpc3N1ZURhdGEubWVzc2FnZSAhPT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgLi4uaXNzdWVEYXRhLAogICAgICAgIHBhdGg6IGZ1bGxQYXRoLAogICAgICAgIG1lc3NhZ2U6IGlzc3VlRGF0YS5tZXNzYWdlCiAgICAgIH07CiAgICB9CiAgICBsZXQgZXJyb3JNZXNzYWdlID0gIiI7CiAgICBjb25zdCBtYXBzID0gZXJyb3JNYXBzLmZpbHRlcigobTIpID0+ICEhbTIpLnNsaWNlKCkucmV2ZXJzZSgpOwogICAgZm9yIChjb25zdCBtYXAgb2YgbWFwcykgewogICAgICBlcnJvck1lc3NhZ2UgPSBtYXAoZnVsbElzc3VlLCB7IGRhdGEsIGRlZmF1bHRFcnJvcjogZXJyb3JNZXNzYWdlIH0pLm1lc3NhZ2U7CiAgICB9CiAgICByZXR1cm4gewogICAgICAuLi5pc3N1ZURhdGEsCiAgICAgIHBhdGg6IGZ1bGxQYXRoLAogICAgICBtZXNzYWdlOiBlcnJvck1lc3NhZ2UKICAgIH07CiAgfTsKICBjb25zdCBFTVBUWV9QQVRIID0gW107CiAgZnVuY3Rpb24gYWRkSXNzdWVUb0NvbnRleHQoY3R4LCBpc3N1ZURhdGEpIHsKICAgIGNvbnN0IG92ZXJyaWRlTWFwID0gZ2V0RXJyb3JNYXAoKTsKICAgIGNvbnN0IGlzc3VlID0gbWFrZUlzc3VlKHsKICAgICAgaXNzdWVEYXRhLAogICAgICBkYXRhOiBjdHguZGF0YSwKICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgIGVycm9yTWFwczogWwogICAgICAgIGN0eC5jb21tb24uY29udGV4dHVhbEVycm9yTWFwLAogICAgICAgIGN0eC5zY2hlbWFFcnJvck1hcCwKICAgICAgICBvdmVycmlkZU1hcCwKICAgICAgICBvdmVycmlkZU1hcCA9PT0gZXJyb3JNYXAgPyB2b2lkIDAgOiBlcnJvck1hcAogICAgICAgIC8vIHRoZW4gZ2xvYmFsIGRlZmF1bHQgbWFwCiAgICAgIF0uZmlsdGVyKCh4KSA9PiAhIXgpCiAgICB9KTsKICAgIGN0eC5jb21tb24uaXNzdWVzLnB1c2goaXNzdWUpOwogIH0KICBjbGFzcyBQYXJzZVN0YXR1cyB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgdGhpcy52YWx1ZSA9ICJ2YWxpZCI7CiAgICB9CiAgICBkaXJ0eSgpIHsKICAgICAgaWYgKHRoaXMudmFsdWUgPT09ICJ2YWxpZCIpCiAgICAgICAgdGhpcy52YWx1ZSA9ICJkaXJ0eSI7CiAgICB9CiAgICBhYm9ydCgpIHsKICAgICAgaWYgKHRoaXMudmFsdWUgIT09ICJhYm9ydGVkIikKICAgICAgICB0aGlzLnZhbHVlID0gImFib3J0ZWQiOwogICAgfQogICAgc3RhdGljIG1lcmdlQXJyYXkoc3RhdHVzLCByZXN1bHRzKSB7CiAgICAgIGNvbnN0IGFycmF5VmFsdWUgPSBbXTsKICAgICAgZm9yIChjb25zdCBzMiBvZiByZXN1bHRzKSB7CiAgICAgICAgaWYgKHMyLnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgaWYgKHMyLnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgIGFycmF5VmFsdWUucHVzaChzMi52YWx1ZSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBhcnJheVZhbHVlIH07CiAgICB9CiAgICBzdGF0aWMgYXN5bmMgbWVyZ2VPYmplY3RBc3luYyhzdGF0dXMsIHBhaXJzKSB7CiAgICAgIGNvbnN0IHN5bmNQYWlycyA9IFtdOwogICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHsKICAgICAgICBjb25zdCBrZXkgPSBhd2FpdCBwYWlyLmtleTsKICAgICAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IHBhaXIudmFsdWU7CiAgICAgICAgc3luY1BhaXJzLnB1c2goewogICAgICAgICAga2V5LAogICAgICAgICAgdmFsdWUKICAgICAgICB9KTsKICAgICAgfQogICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VPYmplY3RTeW5jKHN0YXR1cywgc3luY1BhaXJzKTsKICAgIH0KICAgIHN0YXRpYyBtZXJnZU9iamVjdFN5bmMoc3RhdHVzLCBwYWlycykgewogICAgICBjb25zdCBmaW5hbE9iamVjdCA9IHt9OwogICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHsKICAgICAgICBjb25zdCB7IGtleSwgdmFsdWUgfSA9IHBhaXI7CiAgICAgICAgaWYgKGtleS5zdGF0dXMgPT09ICJhYm9ydGVkIikKICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgIGlmICh2YWx1ZS5zdGF0dXMgPT09ICJhYm9ydGVkIikKICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgIGlmIChrZXkuc3RhdHVzID09PSAiZGlydHkiKQogICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgaWYgKHZhbHVlLnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgIGlmIChrZXkudmFsdWUgIT09ICJfX3Byb3RvX18iICYmICh0eXBlb2YgdmFsdWUudmFsdWUgIT09ICJ1bmRlZmluZWQiIHx8IHBhaXIuYWx3YXlzU2V0KSkgewogICAgICAgICAgZmluYWxPYmplY3Rba2V5LnZhbHVlXSA9IHZhbHVlLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGZpbmFsT2JqZWN0IH07CiAgICB9CiAgfQogIGNvbnN0IElOVkFMSUQgPSBPYmplY3QuZnJlZXplKHsKICAgIHN0YXR1czogImFib3J0ZWQiCiAgfSk7CiAgY29uc3QgRElSVFkgPSAodmFsdWUpID0+ICh7IHN0YXR1czogImRpcnR5IiwgdmFsdWUgfSk7CiAgY29uc3QgT0sgPSAodmFsdWUpID0+ICh7IHN0YXR1czogInZhbGlkIiwgdmFsdWUgfSk7CiAgY29uc3QgaXNBYm9ydGVkID0gKHgpID0+IHguc3RhdHVzID09PSAiYWJvcnRlZCI7CiAgY29uc3QgaXNEaXJ0eSA9ICh4KSA9PiB4LnN0YXR1cyA9PT0gImRpcnR5IjsKICBjb25zdCBpc1ZhbGlkID0gKHgpID0+IHguc3RhdHVzID09PSAidmFsaWQiOwogIGNvbnN0IGlzQXN5bmMgPSAoeCkgPT4gdHlwZW9mIFByb21pc2UgIT09ICJ1bmRlZmluZWQiICYmIHggaW5zdGFuY2VvZiBQcm9taXNlOwogIGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRHZXQocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmMikgewogICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gImZ1bmN0aW9uIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZjIgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0Iik7CiAgICByZXR1cm4gc3RhdGUuZ2V0KHJlY2VpdmVyKTsKICB9CiAgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZFNldChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmMikgewogICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gImZ1bmN0aW9uIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZjIgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXQiKTsKICAgIHJldHVybiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSwgdmFsdWU7CiAgfQogIHR5cGVvZiBTdXBwcmVzc2VkRXJyb3IgPT09ICJmdW5jdGlvbiIgPyBTdXBwcmVzc2VkRXJyb3IgOiBmdW5jdGlvbihlcnJvciwgc3VwcHJlc3NlZCwgbWVzc2FnZSkgewogICAgdmFyIGUyID0gbmV3IEVycm9yKG1lc3NhZ2UpOwogICAgcmV0dXJuIGUyLm5hbWUgPSAiU3VwcHJlc3NlZEVycm9yIiwgZTIuZXJyb3IgPSBlcnJvciwgZTIuc3VwcHJlc3NlZCA9IHN1cHByZXNzZWQsIGUyOwogIH07CiAgdmFyIGVycm9yVXRpbDsKICAoZnVuY3Rpb24oZXJyb3JVdGlsMikgewogICAgZXJyb3JVdGlsMi5lcnJUb09iaiA9IChtZXNzYWdlKSA9PiB0eXBlb2YgbWVzc2FnZSA9PT0gInN0cmluZyIgPyB7IG1lc3NhZ2UgfSA6IG1lc3NhZ2UgfHwge307CiAgICBlcnJvclV0aWwyLnRvU3RyaW5nID0gKG1lc3NhZ2UpID0+IHR5cGVvZiBtZXNzYWdlID09PSAic3RyaW5nIiA/IG1lc3NhZ2UgOiBtZXNzYWdlID09PSBudWxsIHx8IG1lc3NhZ2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG1lc3NhZ2UubWVzc2FnZTsKICB9KShlcnJvclV0aWwgfHwgKGVycm9yVXRpbCA9IHt9KSk7CiAgdmFyIF9ab2RFbnVtX2NhY2hlLCBfWm9kTmF0aXZlRW51bV9jYWNoZTsKICBjbGFzcyBQYXJzZUlucHV0TGF6eVBhdGggewogICAgY29uc3RydWN0b3IocGFyZW50LCB2YWx1ZSwgcGF0aCwga2V5KSB7CiAgICAgIHRoaXMuX2NhY2hlZFBhdGggPSBbXTsKICAgICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7CiAgICAgIHRoaXMuZGF0YSA9IHZhbHVlOwogICAgICB0aGlzLl9wYXRoID0gcGF0aDsKICAgICAgdGhpcy5fa2V5ID0ga2V5OwogICAgfQogICAgZ2V0IHBhdGgoKSB7CiAgICAgIGlmICghdGhpcy5fY2FjaGVkUGF0aC5sZW5ndGgpIHsKICAgICAgICBpZiAodGhpcy5fa2V5IGluc3RhbmNlb2YgQXJyYXkpIHsKICAgICAgICAgIHRoaXMuX2NhY2hlZFBhdGgucHVzaCguLi50aGlzLl9wYXRoLCAuLi50aGlzLl9rZXkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9jYWNoZWRQYXRoLnB1c2goLi4udGhpcy5fcGF0aCwgdGhpcy5fa2V5KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlZFBhdGg7CiAgICB9CiAgfQogIGNvbnN0IGhhbmRsZVJlc3VsdCA9IChjdHgsIHJlc3VsdCkgPT4gewogICAgaWYgKGlzVmFsaWQocmVzdWx0KSkgewogICAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBkYXRhOiByZXN1bHQudmFsdWUgfTsKICAgIH0gZWxzZSB7CiAgICAgIGlmICghY3R4LmNvbW1vbi5pc3N1ZXMubGVuZ3RoKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJWYWxpZGF0aW9uIGZhaWxlZCBidXQgbm8gaXNzdWVzIGRldGVjdGVkLiIpOwogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgc3VjY2VzczogZmFsc2UsCiAgICAgICAgZ2V0IGVycm9yKCkgewogICAgICAgICAgaWYgKHRoaXMuX2Vycm9yKQogICAgICAgICAgICByZXR1cm4gdGhpcy5fZXJyb3I7CiAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBab2RFcnJvcihjdHguY29tbW9uLmlzc3Vlcyk7CiAgICAgICAgICB0aGlzLl9lcnJvciA9IGVycm9yOwogICAgICAgICAgcmV0dXJuIHRoaXMuX2Vycm9yOwogICAgICAgIH0KICAgICAgfTsKICAgIH0KICB9OwogIGZ1bmN0aW9uIHByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKSB7CiAgICBpZiAoIXBhcmFtcykKICAgICAgcmV0dXJuIHt9OwogICAgY29uc3QgeyBlcnJvck1hcDogZXJyb3JNYXAyLCBpbnZhbGlkX3R5cGVfZXJyb3IsIHJlcXVpcmVkX2Vycm9yLCBkZXNjcmlwdGlvbiB9ID0gcGFyYW1zOwogICAgaWYgKGVycm9yTWFwMiAmJiAoaW52YWxpZF90eXBlX2Vycm9yIHx8IHJlcXVpcmVkX2Vycm9yKSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IHVzZSAiaW52YWxpZF90eXBlX2Vycm9yIiBvciAicmVxdWlyZWRfZXJyb3IiIGluIGNvbmp1bmN0aW9uIHdpdGggY3VzdG9tIGVycm9yIG1hcC5gKTsKICAgIH0KICAgIGlmIChlcnJvck1hcDIpCiAgICAgIHJldHVybiB7IGVycm9yTWFwOiBlcnJvck1hcDIsIGRlc2NyaXB0aW9uIH07CiAgICBjb25zdCBjdXN0b21NYXAgPSAoaXNzLCBjdHgpID0+IHsKICAgICAgdmFyIF9hLCBfYjsKICAgICAgY29uc3QgeyBtZXNzYWdlIH0gPSBwYXJhbXM7CiAgICAgIGlmIChpc3MuY29kZSA9PT0gImludmFsaWRfZW51bV92YWx1ZSIpIHsKICAgICAgICByZXR1cm4geyBtZXNzYWdlOiBtZXNzYWdlICE9PSBudWxsICYmIG1lc3NhZ2UgIT09IHZvaWQgMCA/IG1lc3NhZ2UgOiBjdHguZGVmYXVsdEVycm9yIH07CiAgICAgIH0KICAgICAgaWYgKHR5cGVvZiBjdHguZGF0YSA9PT0gInVuZGVmaW5lZCIpIHsKICAgICAgICByZXR1cm4geyBtZXNzYWdlOiAoX2EgPSBtZXNzYWdlICE9PSBudWxsICYmIG1lc3NhZ2UgIT09IHZvaWQgMCA/IG1lc3NhZ2UgOiByZXF1aXJlZF9lcnJvcikgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogY3R4LmRlZmF1bHRFcnJvciB9OwogICAgICB9CiAgICAgIGlmIChpc3MuY29kZSAhPT0gImludmFsaWRfdHlwZSIpCiAgICAgICAgcmV0dXJuIHsgbWVzc2FnZTogY3R4LmRlZmF1bHRFcnJvciB9OwogICAgICByZXR1cm4geyBtZXNzYWdlOiAoX2IgPSBtZXNzYWdlICE9PSBudWxsICYmIG1lc3NhZ2UgIT09IHZvaWQgMCA/IG1lc3NhZ2UgOiBpbnZhbGlkX3R5cGVfZXJyb3IpICE9PSBudWxsICYmIF9iICE9PSB2b2lkIDAgPyBfYiA6IGN0eC5kZWZhdWx0RXJyb3IgfTsKICAgIH07CiAgICByZXR1cm4geyBlcnJvck1hcDogY3VzdG9tTWFwLCBkZXNjcmlwdGlvbiB9OwogIH0KICBjbGFzcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKGRlZikgewogICAgICB0aGlzLnNwYSA9IHRoaXMuc2FmZVBhcnNlQXN5bmM7CiAgICAgIHRoaXMuX2RlZiA9IGRlZjsKICAgICAgdGhpcy5wYXJzZSA9IHRoaXMucGFyc2UuYmluZCh0aGlzKTsKICAgICAgdGhpcy5zYWZlUGFyc2UgPSB0aGlzLnNhZmVQYXJzZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLnBhcnNlQXN5bmMgPSB0aGlzLnBhcnNlQXN5bmMuYmluZCh0aGlzKTsKICAgICAgdGhpcy5zYWZlUGFyc2VBc3luYyA9IHRoaXMuc2FmZVBhcnNlQXN5bmMuYmluZCh0aGlzKTsKICAgICAgdGhpcy5zcGEgPSB0aGlzLnNwYS5iaW5kKHRoaXMpOwogICAgICB0aGlzLnJlZmluZSA9IHRoaXMucmVmaW5lLmJpbmQodGhpcyk7CiAgICAgIHRoaXMucmVmaW5lbWVudCA9IHRoaXMucmVmaW5lbWVudC5iaW5kKHRoaXMpOwogICAgICB0aGlzLnN1cGVyUmVmaW5lID0gdGhpcy5zdXBlclJlZmluZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLm9wdGlvbmFsID0gdGhpcy5vcHRpb25hbC5iaW5kKHRoaXMpOwogICAgICB0aGlzLm51bGxhYmxlID0gdGhpcy5udWxsYWJsZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLm51bGxpc2ggPSB0aGlzLm51bGxpc2guYmluZCh0aGlzKTsKICAgICAgdGhpcy5hcnJheSA9IHRoaXMuYXJyYXkuYmluZCh0aGlzKTsKICAgICAgdGhpcy5wcm9taXNlID0gdGhpcy5wcm9taXNlLmJpbmQodGhpcyk7CiAgICAgIHRoaXMub3IgPSB0aGlzLm9yLmJpbmQodGhpcyk7CiAgICAgIHRoaXMuYW5kID0gdGhpcy5hbmQuYmluZCh0aGlzKTsKICAgICAgdGhpcy50cmFuc2Zvcm0gPSB0aGlzLnRyYW5zZm9ybS5iaW5kKHRoaXMpOwogICAgICB0aGlzLmJyYW5kID0gdGhpcy5icmFuZC5iaW5kKHRoaXMpOwogICAgICB0aGlzLmRlZmF1bHQgPSB0aGlzLmRlZmF1bHQuYmluZCh0aGlzKTsKICAgICAgdGhpcy5jYXRjaCA9IHRoaXMuY2F0Y2guYmluZCh0aGlzKTsKICAgICAgdGhpcy5kZXNjcmliZSA9IHRoaXMuZGVzY3JpYmUuYmluZCh0aGlzKTsKICAgICAgdGhpcy5waXBlID0gdGhpcy5waXBlLmJpbmQodGhpcyk7CiAgICAgIHRoaXMucmVhZG9ubHkgPSB0aGlzLnJlYWRvbmx5LmJpbmQodGhpcyk7CiAgICAgIHRoaXMuaXNOdWxsYWJsZSA9IHRoaXMuaXNOdWxsYWJsZS5iaW5kKHRoaXMpOwogICAgICB0aGlzLmlzT3B0aW9uYWwgPSB0aGlzLmlzT3B0aW9uYWwuYmluZCh0aGlzKTsKICAgIH0KICAgIGdldCBkZXNjcmlwdGlvbigpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5kZXNjcmlwdGlvbjsKICAgIH0KICAgIF9nZXRUeXBlKGlucHV0KSB7CiAgICAgIHJldHVybiBnZXRQYXJzZWRUeXBlKGlucHV0LmRhdGEpOwogICAgfQogICAgX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpIHsKICAgICAgcmV0dXJuIGN0eCB8fCB7CiAgICAgICAgY29tbW9uOiBpbnB1dC5wYXJlbnQuY29tbW9uLAogICAgICAgIGRhdGE6IGlucHV0LmRhdGEsCiAgICAgICAgcGFyc2VkVHlwZTogZ2V0UGFyc2VkVHlwZShpbnB1dC5kYXRhKSwKICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLAogICAgICAgIHBhdGg6IGlucHV0LnBhdGgsCiAgICAgICAgcGFyZW50OiBpbnB1dC5wYXJlbnQKICAgICAgfTsKICAgIH0KICAgIF9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBzdGF0dXM6IG5ldyBQYXJzZVN0YXR1cygpLAogICAgICAgIGN0eDogewogICAgICAgICAgY29tbW9uOiBpbnB1dC5wYXJlbnQuY29tbW9uLAogICAgICAgICAgZGF0YTogaW5wdXQuZGF0YSwKICAgICAgICAgIHBhcnNlZFR5cGU6IGdldFBhcnNlZFR5cGUoaW5wdXQuZGF0YSksCiAgICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLAogICAgICAgICAgcGF0aDogaW5wdXQucGF0aCwKICAgICAgICAgIHBhcmVudDogaW5wdXQucGFyZW50CiAgICAgICAgfQogICAgICB9OwogICAgfQogICAgX3BhcnNlU3luYyhpbnB1dCkgewogICAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9wYXJzZShpbnB1dCk7CiAgICAgIGlmIChpc0FzeW5jKHJlc3VsdCkpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlN5bmNocm9ub3VzIHBhcnNlIGVuY291bnRlcmVkIHByb21pc2UuIik7CiAgICAgIH0KICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIF9wYXJzZUFzeW5jKGlucHV0KSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX3BhcnNlKGlucHV0KTsKICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHQpOwogICAgfQogICAgcGFyc2UoZGF0YSwgcGFyYW1zKSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuc2FmZVBhcnNlKGRhdGEsIHBhcmFtcyk7CiAgICAgIGlmIChyZXN1bHQuc3VjY2VzcykKICAgICAgICByZXR1cm4gcmVzdWx0LmRhdGE7CiAgICAgIHRocm93IHJlc3VsdC5lcnJvcjsKICAgIH0KICAgIHNhZmVQYXJzZShkYXRhLCBwYXJhbXMpIHsKICAgICAgdmFyIF9hOwogICAgICBjb25zdCBjdHggPSB7CiAgICAgICAgY29tbW9uOiB7CiAgICAgICAgICBpc3N1ZXM6IFtdLAogICAgICAgICAgYXN5bmM6IChfYSA9IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5hc3luYykgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogZmFsc2UsCiAgICAgICAgICBjb250ZXh0dWFsRXJyb3JNYXA6IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5lcnJvck1hcAogICAgICAgIH0sCiAgICAgICAgcGF0aDogKHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5wYXRoKSB8fCBbXSwKICAgICAgICBzY2hlbWFFcnJvck1hcDogdGhpcy5fZGVmLmVycm9yTWFwLAogICAgICAgIHBhcmVudDogbnVsbCwKICAgICAgICBkYXRhLAogICAgICAgIHBhcnNlZFR5cGU6IGdldFBhcnNlZFR5cGUoZGF0YSkKICAgICAgfTsKICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fcGFyc2VTeW5jKHsgZGF0YSwgcGF0aDogY3R4LnBhdGgsIHBhcmVudDogY3R4IH0pOwogICAgICByZXR1cm4gaGFuZGxlUmVzdWx0KGN0eCwgcmVzdWx0KTsKICAgIH0KICAgIGFzeW5jIHBhcnNlQXN5bmMoZGF0YSwgcGFyYW1zKSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuc2FmZVBhcnNlQXN5bmMoZGF0YSwgcGFyYW1zKTsKICAgICAgaWYgKHJlc3VsdC5zdWNjZXNzKQogICAgICAgIHJldHVybiByZXN1bHQuZGF0YTsKICAgICAgdGhyb3cgcmVzdWx0LmVycm9yOwogICAgfQogICAgYXN5bmMgc2FmZVBhcnNlQXN5bmMoZGF0YSwgcGFyYW1zKSB7CiAgICAgIGNvbnN0IGN0eCA9IHsKICAgICAgICBjb21tb246IHsKICAgICAgICAgIGlzc3VlczogW10sCiAgICAgICAgICBjb250ZXh0dWFsRXJyb3JNYXA6IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5lcnJvck1hcCwKICAgICAgICAgIGFzeW5jOiB0cnVlCiAgICAgICAgfSwKICAgICAgICBwYXRoOiAocGFyYW1zID09PSBudWxsIHx8IHBhcmFtcyA9PT0gdm9pZCAwID8gdm9pZCAwIDogcGFyYW1zLnBhdGgpIHx8IFtdLAogICAgICAgIHNjaGVtYUVycm9yTWFwOiB0aGlzLl9kZWYuZXJyb3JNYXAsCiAgICAgICAgcGFyZW50OiBudWxsLAogICAgICAgIGRhdGEsCiAgICAgICAgcGFyc2VkVHlwZTogZ2V0UGFyc2VkVHlwZShkYXRhKQogICAgICB9OwogICAgICBjb25zdCBtYXliZUFzeW5jUmVzdWx0ID0gdGhpcy5fcGFyc2UoeyBkYXRhLCBwYXRoOiBjdHgucGF0aCwgcGFyZW50OiBjdHggfSk7CiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IChpc0FzeW5jKG1heWJlQXN5bmNSZXN1bHQpID8gbWF5YmVBc3luY1Jlc3VsdCA6IFByb21pc2UucmVzb2x2ZShtYXliZUFzeW5jUmVzdWx0KSk7CiAgICAgIHJldHVybiBoYW5kbGVSZXN1bHQoY3R4LCByZXN1bHQpOwogICAgfQogICAgcmVmaW5lKGNoZWNrLCBtZXNzYWdlKSB7CiAgICAgIGNvbnN0IGdldElzc3VlUHJvcGVydGllcyA9ICh2YWwpID0+IHsKICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgPT09ICJzdHJpbmciIHx8IHR5cGVvZiBtZXNzYWdlID09PSAidW5kZWZpbmVkIikgewogICAgICAgICAgcmV0dXJuIHsgbWVzc2FnZSB9OwogICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG1lc3NhZ2UgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgIHJldHVybiBtZXNzYWdlKHZhbCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBtZXNzYWdlOwogICAgICAgIH0KICAgICAgfTsKICAgICAgcmV0dXJuIHRoaXMuX3JlZmluZW1lbnQoKHZhbCwgY3R4KSA9PiB7CiAgICAgICAgY29uc3QgcmVzdWx0ID0gY2hlY2sodmFsKTsKICAgICAgICBjb25zdCBzZXRFcnJvciA9ICgpID0+IGN0eC5hZGRJc3N1ZSh7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuY3VzdG9tLAogICAgICAgICAgLi4uZ2V0SXNzdWVQcm9wZXJ0aWVzKHZhbCkKICAgICAgICB9KTsKICAgICAgICBpZiAodHlwZW9mIFByb21pc2UgIT09ICJ1bmRlZmluZWQiICYmIHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UpIHsKICAgICAgICAgIHJldHVybiByZXN1bHQudGhlbigoZGF0YSkgPT4gewogICAgICAgICAgICBpZiAoIWRhdGEpIHsKICAgICAgICAgICAgICBzZXRFcnJvcigpOwogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGlmICghcmVzdWx0KSB7CiAgICAgICAgICBzZXRFcnJvcigpOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogICAgcmVmaW5lbWVudChjaGVjaywgcmVmaW5lbWVudERhdGEpIHsKICAgICAgcmV0dXJuIHRoaXMuX3JlZmluZW1lbnQoKHZhbCwgY3R4KSA9PiB7CiAgICAgICAgaWYgKCFjaGVjayh2YWwpKSB7CiAgICAgICAgICBjdHguYWRkSXNzdWUodHlwZW9mIHJlZmluZW1lbnREYXRhID09PSAiZnVuY3Rpb24iID8gcmVmaW5lbWVudERhdGEodmFsLCBjdHgpIDogcmVmaW5lbWVudERhdGEpOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogICAgX3JlZmluZW1lbnQocmVmaW5lbWVudCkgewogICAgICByZXR1cm4gbmV3IFpvZEVmZmVjdHMoewogICAgICAgIHNjaGVtYTogdGhpcywKICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMsCiAgICAgICAgZWZmZWN0OiB7IHR5cGU6ICJyZWZpbmVtZW50IiwgcmVmaW5lbWVudCB9CiAgICAgIH0pOwogICAgfQogICAgc3VwZXJSZWZpbmUocmVmaW5lbWVudCkgewogICAgICByZXR1cm4gdGhpcy5fcmVmaW5lbWVudChyZWZpbmVtZW50KTsKICAgIH0KICAgIG9wdGlvbmFsKCkgewogICAgICByZXR1cm4gWm9kT3B0aW9uYWwuY3JlYXRlKHRoaXMsIHRoaXMuX2RlZik7CiAgICB9CiAgICBudWxsYWJsZSgpIHsKICAgICAgcmV0dXJuIFpvZE51bGxhYmxlLmNyZWF0ZSh0aGlzLCB0aGlzLl9kZWYpOwogICAgfQogICAgbnVsbGlzaCgpIHsKICAgICAgcmV0dXJuIHRoaXMubnVsbGFibGUoKS5vcHRpb25hbCgpOwogICAgfQogICAgYXJyYXkoKSB7CiAgICAgIHJldHVybiBab2RBcnJheS5jcmVhdGUodGhpcywgdGhpcy5fZGVmKTsKICAgIH0KICAgIHByb21pc2UoKSB7CiAgICAgIHJldHVybiBab2RQcm9taXNlLmNyZWF0ZSh0aGlzLCB0aGlzLl9kZWYpOwogICAgfQogICAgb3Iob3B0aW9uKSB7CiAgICAgIHJldHVybiBab2RVbmlvbi5jcmVhdGUoW3RoaXMsIG9wdGlvbl0sIHRoaXMuX2RlZik7CiAgICB9CiAgICBhbmQoaW5jb21pbmcpIHsKICAgICAgcmV0dXJuIFpvZEludGVyc2VjdGlvbi5jcmVhdGUodGhpcywgaW5jb21pbmcsIHRoaXMuX2RlZik7CiAgICB9CiAgICB0cmFuc2Zvcm0odHJhbnNmb3JtKSB7CiAgICAgIHJldHVybiBuZXcgWm9kRWZmZWN0cyh7CiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyh0aGlzLl9kZWYpLAogICAgICAgIHNjaGVtYTogdGhpcywKICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMsCiAgICAgICAgZWZmZWN0OiB7IHR5cGU6ICJ0cmFuc2Zvcm0iLCB0cmFuc2Zvcm0gfQogICAgICB9KTsKICAgIH0KICAgIGRlZmF1bHQoZGVmKSB7CiAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZUZ1bmMgPSB0eXBlb2YgZGVmID09PSAiZnVuY3Rpb24iID8gZGVmIDogKCkgPT4gZGVmOwogICAgICByZXR1cm4gbmV3IFpvZERlZmF1bHQoewogICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXModGhpcy5fZGVmKSwKICAgICAgICBpbm5lclR5cGU6IHRoaXMsCiAgICAgICAgZGVmYXVsdFZhbHVlOiBkZWZhdWx0VmFsdWVGdW5jLAogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRGVmYXVsdAogICAgICB9KTsKICAgIH0KICAgIGJyYW5kKCkgewogICAgICByZXR1cm4gbmV3IFpvZEJyYW5kZWQoewogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kQnJhbmRlZCwKICAgICAgICB0eXBlOiB0aGlzLAogICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXModGhpcy5fZGVmKQogICAgICB9KTsKICAgIH0KICAgIGNhdGNoKGRlZikgewogICAgICBjb25zdCBjYXRjaFZhbHVlRnVuYyA9IHR5cGVvZiBkZWYgPT09ICJmdW5jdGlvbiIgPyBkZWYgOiAoKSA9PiBkZWY7CiAgICAgIHJldHVybiBuZXcgWm9kQ2F0Y2goewogICAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXModGhpcy5fZGVmKSwKICAgICAgICBpbm5lclR5cGU6IHRoaXMsCiAgICAgICAgY2F0Y2hWYWx1ZTogY2F0Y2hWYWx1ZUZ1bmMsCiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RDYXRjaAogICAgICB9KTsKICAgIH0KICAgIGRlc2NyaWJlKGRlc2NyaXB0aW9uKSB7CiAgICAgIGNvbnN0IFRoaXMgPSB0aGlzLmNvbnN0cnVjdG9yOwogICAgICByZXR1cm4gbmV3IFRoaXMoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBkZXNjcmlwdGlvbgogICAgICB9KTsKICAgIH0KICAgIHBpcGUodGFyZ2V0KSB7CiAgICAgIHJldHVybiBab2RQaXBlbGluZS5jcmVhdGUodGhpcywgdGFyZ2V0KTsKICAgIH0KICAgIHJlYWRvbmx5KCkgewogICAgICByZXR1cm4gWm9kUmVhZG9ubHkuY3JlYXRlKHRoaXMpOwogICAgfQogICAgaXNPcHRpb25hbCgpIHsKICAgICAgcmV0dXJuIHRoaXMuc2FmZVBhcnNlKHZvaWQgMCkuc3VjY2VzczsKICAgIH0KICAgIGlzTnVsbGFibGUoKSB7CiAgICAgIHJldHVybiB0aGlzLnNhZmVQYXJzZShudWxsKS5zdWNjZXNzOwogICAgfQogIH0KICBjb25zdCBjdWlkUmVnZXggPSAvXmNbXlxzLV17OCx9JC9pOwogIGNvbnN0IGN1aWQyUmVnZXggPSAvXlswLTlhLXpdKyQvOwogIGNvbnN0IHVsaWRSZWdleCA9IC9eWzAtOUEtSEpLTU5QLVRWLVpdezI2fSQvOwogIGNvbnN0IHV1aWRSZWdleCA9IC9eWzAtOWEtZkEtRl17OH1cYi1bMC05YS1mQS1GXXs0fVxiLVswLTlhLWZBLUZdezR9XGItWzAtOWEtZkEtRl17NH1cYi1bMC05YS1mQS1GXXsxMn0kL2k7CiAgY29uc3QgbmFub2lkUmVnZXggPSAvXlthLXowLTlfLV17MjF9JC9pOwogIGNvbnN0IGR1cmF0aW9uUmVnZXggPSAvXlstK10/UCg/ISQpKD86KD86Wy0rXT9cZCtZKXwoPzpbLStdP1xkK1suLF1cZCtZJCkpPyg/Oig/OlstK10/XGQrTSl8KD86Wy0rXT9cZCtbLixdXGQrTSQpKT8oPzooPzpbLStdP1xkK1cpfCg/OlstK10/XGQrWy4sXVxkK1ckKSk/KD86KD86Wy0rXT9cZCtEKXwoPzpbLStdP1xkK1suLF1cZCtEJCkpPyg/OlQoPz1bXGQrLV0pKD86KD86Wy0rXT9cZCtIKXwoPzpbLStdP1xkK1suLF1cZCtIJCkpPyg/Oig/OlstK10/XGQrTSl8KD86Wy0rXT9cZCtbLixdXGQrTSQpKT8oPzpbLStdP1xkKyg/OlsuLF1cZCspP1MpPyk/PyQvOwogIGNvbnN0IGVtYWlsUmVnZXggPSAvXig/IVwuKSg/IS4qXC5cLikoW0EtWjAtOV8nK1wtXC5dKilbQS1aMC05XystXUAoW0EtWjAtOV1bQS1aMC05XC1dKlwuKStbQS1aXXsyLH0kL2k7CiAgY29uc3QgX2Vtb2ppUmVnZXggPSBgXihcXHB7RXh0ZW5kZWRfUGljdG9ncmFwaGljfXxcXHB7RW1vamlfQ29tcG9uZW50fSkrJGA7CiAgbGV0IGVtb2ppUmVnZXg7CiAgY29uc3QgaXB2NFJlZ2V4ID0gL14oPzooPzoyNVswLTVdfDJbMC00XVswLTldfDFbMC05XVswLTldfFsxLTldWzAtOV18WzAtOV0pXC4pezN9KD86MjVbMC01XXwyWzAtNF1bMC05XXwxWzAtOV1bMC05XXxbMS05XVswLTldfFswLTldKSQvOwogIGNvbnN0IGlwdjZSZWdleCA9IC9eKChbYS1mMC05XXsxLDR9Oil7N318OjooW2EtZjAtOV17MSw0fTopezAsNn18KFthLWYwLTldezEsNH06KXsxfTooW2EtZjAtOV17MSw0fTopezAsNX18KFthLWYwLTldezEsNH06KXsyfTooW2EtZjAtOV17MSw0fTopezAsNH18KFthLWYwLTldezEsNH06KXszfTooW2EtZjAtOV17MSw0fTopezAsM318KFthLWYwLTldezEsNH06KXs0fTooW2EtZjAtOV17MSw0fTopezAsMn18KFthLWYwLTldezEsNH06KXs1fTooW2EtZjAtOV17MSw0fTopezAsMX0pKFthLWYwLTldezEsNH18KCgoMjVbMC01XSl8KDJbMC00XVswLTldKXwoMVswLTldezJ9KXwoWzAtOV17MSwyfSkpXC4pezN9KCgyNVswLTVdKXwoMlswLTRdWzAtOV0pfCgxWzAtOV17Mn0pfChbMC05XXsxLDJ9KSkpJC87CiAgY29uc3QgYmFzZTY0UmVnZXggPSAvXihbMC05YS16QS1aKy9dezR9KSooKFswLTlhLXpBLVorL117Mn09PSl8KFswLTlhLXpBLVorL117M309KSk/JC87CiAgY29uc3QgZGF0ZVJlZ2V4U291cmNlID0gYCgoXFxkXFxkWzI0NjhdWzA0OF18XFxkXFxkWzEzNTc5XVsyNl18XFxkXFxkMFs0OF18WzAyNDY4XVswNDhdMDB8WzEzNTc5XVsyNl0wMCktMDItMjl8XFxkezR9LSgoMFsxMzU3OF18MVswMl0pLSgwWzEtOV18WzEyXVxcZHwzWzAxXSl8KDBbNDY5XXwxMSktKDBbMS05XXxbMTJdXFxkfDMwKXwoMDIpLSgwWzEtOV18MVxcZHwyWzAtOF0pKSlgOwogIGNvbnN0IGRhdGVSZWdleCA9IG5ldyBSZWdFeHAoYF4ke2RhdGVSZWdleFNvdXJjZX0kYCk7CiAgZnVuY3Rpb24gdGltZVJlZ2V4U291cmNlKGFyZ3MpIHsKICAgIGxldCByZWdleCA9IGAoWzAxXVxcZHwyWzAtM10pOlswLTVdXFxkOlswLTVdXFxkYDsKICAgIGlmIChhcmdzLnByZWNpc2lvbikgewogICAgICByZWdleCA9IGAke3JlZ2V4fVxcLlxcZHske2FyZ3MucHJlY2lzaW9ufX1gOwogICAgfSBlbHNlIGlmIChhcmdzLnByZWNpc2lvbiA9PSBudWxsKSB7CiAgICAgIHJlZ2V4ID0gYCR7cmVnZXh9KFxcLlxcZCspP2A7CiAgICB9CiAgICByZXR1cm4gcmVnZXg7CiAgfQogIGZ1bmN0aW9uIHRpbWVSZWdleChhcmdzKSB7CiAgICByZXR1cm4gbmV3IFJlZ0V4cChgXiR7dGltZVJlZ2V4U291cmNlKGFyZ3MpfSRgKTsKICB9CiAgZnVuY3Rpb24gZGF0ZXRpbWVSZWdleChhcmdzKSB7CiAgICBsZXQgcmVnZXggPSBgJHtkYXRlUmVnZXhTb3VyY2V9VCR7dGltZVJlZ2V4U291cmNlKGFyZ3MpfWA7CiAgICBjb25zdCBvcHRzID0gW107CiAgICBvcHRzLnB1c2goYXJncy5sb2NhbCA/IGBaP2AgOiBgWmApOwogICAgaWYgKGFyZ3Mub2Zmc2V0KQogICAgICBvcHRzLnB1c2goYChbKy1dXFxkezJ9Oj9cXGR7Mn0pYCk7CiAgICByZWdleCA9IGAke3JlZ2V4fSgke29wdHMuam9pbigifCIpfSlgOwogICAgcmV0dXJuIG5ldyBSZWdFeHAoYF4ke3JlZ2V4fSRgKTsKICB9CiAgZnVuY3Rpb24gaXNWYWxpZElQKGlwLCB2ZXJzaW9uKSB7CiAgICBpZiAoKHZlcnNpb24gPT09ICJ2NCIgfHwgIXZlcnNpb24pICYmIGlwdjRSZWdleC50ZXN0KGlwKSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmICgodmVyc2lvbiA9PT0gInY2IiB8fCAhdmVyc2lvbikgJiYgaXB2NlJlZ2V4LnRlc3QoaXApKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICBjbGFzcyBab2RTdHJpbmcgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBpZiAodGhpcy5fZGVmLmNvZXJjZSkgewogICAgICAgIGlucHV0LmRhdGEgPSBTdHJpbmcoaW5wdXQuZGF0YSk7CiAgICAgIH0KICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5zdHJpbmcpIHsKICAgICAgICBjb25zdCBjdHgyID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eDIsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5zdHJpbmcsCiAgICAgICAgICByZWNlaXZlZDogY3R4Mi5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgY29uc3Qgc3RhdHVzID0gbmV3IFBhcnNlU3RhdHVzKCk7CiAgICAgIGxldCBjdHggPSB2b2lkIDA7CiAgICAgIGZvciAoY29uc3QgY2hlY2sgb2YgdGhpcy5fZGVmLmNoZWNrcykgewogICAgICAgIGlmIChjaGVjay5raW5kID09PSAibWluIikgewogICAgICAgICAgaWYgKGlucHV0LmRhdGEubGVuZ3RoIDwgY2hlY2sudmFsdWUpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgICAgbWluaW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogInN0cmluZyIsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAoaW5wdXQuZGF0YS5sZW5ndGggPiBjaGVjay52YWx1ZSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsCiAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogInN0cmluZyIsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJsZW5ndGgiKSB7CiAgICAgICAgICBjb25zdCB0b29CaWcgPSBpbnB1dC5kYXRhLmxlbmd0aCA+IGNoZWNrLnZhbHVlOwogICAgICAgICAgY29uc3QgdG9vU21hbGwgPSBpbnB1dC5kYXRhLmxlbmd0aCA8IGNoZWNrLnZhbHVlOwogICAgICAgICAgaWYgKHRvb0JpZyB8fCB0b29TbWFsbCkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgaWYgKHRvb0JpZykgewogICAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsCiAgICAgICAgICAgICAgICBtYXhpbXVtOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICAgIHR5cGU6ICJzdHJpbmciLAogICAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgICAgZXhhY3Q6IHRydWUsCiAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAodG9vU21hbGwpIHsKICAgICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgICAgICBtaW5pbXVtOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICAgIHR5cGU6ICJzdHJpbmciLAogICAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgICAgZXhhY3Q6IHRydWUsCiAgICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiZW1haWwiKSB7CiAgICAgICAgICBpZiAoIWVtYWlsUmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImVtYWlsIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiZW1vamkiKSB7CiAgICAgICAgICBpZiAoIWVtb2ppUmVnZXgpIHsKICAgICAgICAgICAgZW1vamlSZWdleCA9IG5ldyBSZWdFeHAoX2Vtb2ppUmVnZXgsICJ1Iik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIWVtb2ppUmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImVtb2ppIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidXVpZCIpIHsKICAgICAgICAgIGlmICghdXVpZFJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJ1dWlkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAibmFub2lkIikgewogICAgICAgICAgaWYgKCFuYW5vaWRSZWdleC50ZXN0KGlucHV0LmRhdGEpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiAibmFub2lkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiY3VpZCIpIHsKICAgICAgICAgIGlmICghY3VpZFJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJjdWlkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiY3VpZDIiKSB7CiAgICAgICAgICBpZiAoIWN1aWQyUmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImN1aWQyIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidWxpZCIpIHsKICAgICAgICAgIGlmICghdWxpZFJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJ1bGlkIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidXJsIikgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgbmV3IFVSTChpbnB1dC5kYXRhKTsKICAgICAgICAgIH0gY2F0Y2ggKF9hKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiAidXJsIiwKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAicmVnZXgiKSB7CiAgICAgICAgICBjaGVjay5yZWdleC5sYXN0SW5kZXggPSAwOwogICAgICAgICAgY29uc3QgdGVzdFJlc3VsdCA9IGNoZWNrLnJlZ2V4LnRlc3QoaW5wdXQuZGF0YSk7CiAgICAgICAgICBpZiAoIXRlc3RSZXN1bHQpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJyZWdleCIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gInRyaW0iKSB7CiAgICAgICAgICBpbnB1dC5kYXRhID0gaW5wdXQuZGF0YS50cmltKCk7CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiaW5jbHVkZXMiKSB7CiAgICAgICAgICBpZiAoIWlucHV0LmRhdGEuaW5jbHVkZXMoY2hlY2sudmFsdWUsIGNoZWNrLnBvc2l0aW9uKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIHZhbGlkYXRpb246IHsgaW5jbHVkZXM6IGNoZWNrLnZhbHVlLCBwb3NpdGlvbjogY2hlY2sucG9zaXRpb24gfSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJ0b0xvd2VyQ2FzZSIpIHsKICAgICAgICAgIGlucHV0LmRhdGEgPSBpbnB1dC5kYXRhLnRvTG93ZXJDYXNlKCk7CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAidG9VcHBlckNhc2UiKSB7CiAgICAgICAgICBpbnB1dC5kYXRhID0gaW5wdXQuZGF0YS50b1VwcGVyQ2FzZSgpOwogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gInN0YXJ0c1dpdGgiKSB7CiAgICAgICAgICBpZiAoIWlucHV0LmRhdGEuc3RhcnRzV2l0aChjaGVjay52YWx1ZSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZywKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiB7IHN0YXJ0c1dpdGg6IGNoZWNrLnZhbHVlIH0sCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAiZW5kc1dpdGgiKSB7CiAgICAgICAgICBpZiAoIWlucHV0LmRhdGEuZW5kc1dpdGgoY2hlY2sudmFsdWUpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogeyBlbmRzV2l0aDogY2hlY2sudmFsdWUgfSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJkYXRldGltZSIpIHsKICAgICAgICAgIGNvbnN0IHJlZ2V4ID0gZGF0ZXRpbWVSZWdleChjaGVjayk7CiAgICAgICAgICBpZiAoIXJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3N0cmluZywKICAgICAgICAgICAgICB2YWxpZGF0aW9uOiAiZGF0ZXRpbWUiLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImRhdGUiKSB7CiAgICAgICAgICBjb25zdCByZWdleCA9IGRhdGVSZWdleDsKICAgICAgICAgIGlmICghcmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJkYXRlIiwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJ0aW1lIikgewogICAgICAgICAgY29uc3QgcmVnZXggPSB0aW1lUmVnZXgoY2hlY2spOwogICAgICAgICAgaWYgKCFyZWdleC50ZXN0KGlucHV0LmRhdGEpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9zdHJpbmcsCiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogInRpbWUiLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImR1cmF0aW9uIikgewogICAgICAgICAgaWYgKCFkdXJhdGlvblJlZ2V4LnRlc3QoaW5wdXQuZGF0YSkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJkdXJhdGlvbiIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImlwIikgewogICAgICAgICAgaWYgKCFpc1ZhbGlkSVAoaW5wdXQuZGF0YSwgY2hlY2sudmVyc2lvbikpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIHZhbGlkYXRpb246ICJpcCIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gImJhc2U2NCIpIHsKICAgICAgICAgIGlmICghYmFzZTY0UmVnZXgudGVzdChpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgdmFsaWRhdGlvbjogImJhc2U2NCIsCiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB1dGlsLmFzc2VydE5ldmVyKGNoZWNrKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBpbnB1dC5kYXRhIH07CiAgICB9CiAgICBfcmVnZXgocmVnZXgsIHZhbGlkYXRpb24sIG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMucmVmaW5lbWVudCgoZGF0YSkgPT4gcmVnZXgudGVzdChkYXRhKSwgewogICAgICAgIHZhbGlkYXRpb24sCiAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfc3RyaW5nLAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIF9hZGRDaGVjayhjaGVjaykgewogICAgICByZXR1cm4gbmV3IFpvZFN0cmluZyh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIGNoZWNrczogWy4uLnRoaXMuX2RlZi5jaGVja3MsIGNoZWNrXQogICAgICB9KTsKICAgIH0KICAgIGVtYWlsKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImVtYWlsIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgdXJsKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogInVybCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGVtb2ppKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImVtb2ppIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgdXVpZChtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6ICJ1dWlkIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgbmFub2lkKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogIm5hbm9pZCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGN1aWQobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soeyBraW5kOiAiY3VpZCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGN1aWQyKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImN1aWQyIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgdWxpZChtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6ICJ1bGlkIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgYmFzZTY0KG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImJhc2U2NCIsIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKSB9KTsKICAgIH0KICAgIGlwKG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImlwIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG9wdGlvbnMpIH0pOwogICAgfQogICAgZGF0ZXRpbWUob3B0aW9ucykgewogICAgICB2YXIgX2EsIF9iOwogICAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICJzdHJpbmciKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICAgIGtpbmQ6ICJkYXRldGltZSIsCiAgICAgICAgICBwcmVjaXNpb246IG51bGwsCiAgICAgICAgICBvZmZzZXQ6IGZhbHNlLAogICAgICAgICAgbG9jYWw6IGZhbHNlLAogICAgICAgICAgbWVzc2FnZTogb3B0aW9ucwogICAgICAgIH0pOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImRhdGV0aW1lIiwKICAgICAgICBwcmVjaXNpb246IHR5cGVvZiAob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLnByZWNpc2lvbikgPT09ICJ1bmRlZmluZWQiID8gbnVsbCA6IG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5wcmVjaXNpb24sCiAgICAgICAgb2Zmc2V0OiAoX2EgPSBvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMub2Zmc2V0KSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiBmYWxzZSwKICAgICAgICBsb2NhbDogKF9iID0gb3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLmxvY2FsKSAhPT0gbnVsbCAmJiBfYiAhPT0gdm9pZCAwID8gX2IgOiBmYWxzZSwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLm1lc3NhZ2UpCiAgICAgIH0pOwogICAgfQogICAgZGF0ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7IGtpbmQ6ICJkYXRlIiwgbWVzc2FnZSB9KTsKICAgIH0KICAgIHRpbWUob3B0aW9ucykgewogICAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICJzdHJpbmciKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICAgIGtpbmQ6ICJ0aW1lIiwKICAgICAgICAgIHByZWNpc2lvbjogbnVsbCwKICAgICAgICAgIG1lc3NhZ2U6IG9wdGlvbnMKICAgICAgICB9KTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJ0aW1lIiwKICAgICAgICBwcmVjaXNpb246IHR5cGVvZiAob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLnByZWNpc2lvbikgPT09ICJ1bmRlZmluZWQiID8gbnVsbCA6IG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5wcmVjaXNpb24sCiAgICAgICAgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5tZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGR1cmF0aW9uKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsga2luZDogImR1cmF0aW9uIiwgLi4uZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpIH0pOwogICAgfQogICAgcmVnZXgocmVnZXgsIG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAicmVnZXgiLAogICAgICAgIHJlZ2V4LAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGluY2x1ZGVzKHZhbHVlLCBvcHRpb25zKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImluY2x1ZGVzIiwKICAgICAgICB2YWx1ZSwKICAgICAgICBwb3NpdGlvbjogb3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLnBvc2l0aW9uLAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMubWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBzdGFydHNXaXRoKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogInN0YXJ0c1dpdGgiLAogICAgICAgIHZhbHVlLAogICAgICAgIC4uLmVycm9yVXRpbC5lcnJUb09iaihtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGVuZHNXaXRoKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImVuZHNXaXRoIiwKICAgICAgICB2YWx1ZSwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBtaW4obWluTGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IG1pbkxlbmd0aCwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBtYXgobWF4TGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IG1heExlbmd0aCwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBsZW5ndGgobGVuLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogImxlbmd0aCIsCiAgICAgICAgdmFsdWU6IGxlbiwKICAgICAgICAuLi5lcnJvclV0aWwuZXJyVG9PYmoobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICAvKioKICAgICAqIEBkZXByZWNhdGVkIFVzZSB6LnN0cmluZygpLm1pbigxKSBpbnN0ZWFkLgogICAgICogQHNlZSB7QGxpbmsgWm9kU3RyaW5nLm1pbn0KICAgICAqLwogICAgbm9uZW1wdHkobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5taW4oMSwgZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpKTsKICAgIH0KICAgIHRyaW0oKSB7CiAgICAgIHJldHVybiBuZXcgWm9kU3RyaW5nKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgeyBraW5kOiAidHJpbSIgfV0KICAgICAgfSk7CiAgICB9CiAgICB0b0xvd2VyQ2FzZSgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RTdHJpbmcoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBjaGVja3M6IFsuLi50aGlzLl9kZWYuY2hlY2tzLCB7IGtpbmQ6ICJ0b0xvd2VyQ2FzZSIgfV0KICAgICAgfSk7CiAgICB9CiAgICB0b1VwcGVyQ2FzZSgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RTdHJpbmcoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBjaGVja3M6IFsuLi50aGlzLl9kZWYuY2hlY2tzLCB7IGtpbmQ6ICJ0b1VwcGVyQ2FzZSIgfV0KICAgICAgfSk7CiAgICB9CiAgICBnZXQgaXNEYXRldGltZSgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImRhdGV0aW1lIik7CiAgICB9CiAgICBnZXQgaXNEYXRlKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiZGF0ZSIpOwogICAgfQogICAgZ2V0IGlzVGltZSgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gInRpbWUiKTsKICAgIH0KICAgIGdldCBpc0R1cmF0aW9uKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiZHVyYXRpb24iKTsKICAgIH0KICAgIGdldCBpc0VtYWlsKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiZW1haWwiKTsKICAgIH0KICAgIGdldCBpc1VSTCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gInVybCIpOwogICAgfQogICAgZ2V0IGlzRW1vamkoKSB7CiAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09ICJlbW9qaSIpOwogICAgfQogICAgZ2V0IGlzVVVJRCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gInV1aWQiKTsKICAgIH0KICAgIGdldCBpc05BTk9JRCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gIm5hbm9pZCIpOwogICAgfQogICAgZ2V0IGlzQ1VJRCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImN1aWQiKTsKICAgIH0KICAgIGdldCBpc0NVSUQyKCkgewogICAgICByZXR1cm4gISF0aGlzLl9kZWYuY2hlY2tzLmZpbmQoKGNoKSA9PiBjaC5raW5kID09PSAiY3VpZDIiKTsKICAgIH0KICAgIGdldCBpc1VMSUQoKSB7CiAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09ICJ1bGlkIik7CiAgICB9CiAgICBnZXQgaXNJUCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImlwIik7CiAgICB9CiAgICBnZXQgaXNCYXNlNjQoKSB7CiAgICAgIHJldHVybiAhIXRoaXMuX2RlZi5jaGVja3MuZmluZCgoY2gpID0+IGNoLmtpbmQgPT09ICJiYXNlNjQiKTsKICAgIH0KICAgIGdldCBtaW5MZW5ndGgoKSB7CiAgICAgIGxldCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChtaW4gPT09IG51bGwgfHwgY2gudmFsdWUgPiBtaW4pCiAgICAgICAgICAgIG1pbiA9IGNoLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbWluOwogICAgfQogICAgZ2V0IG1heExlbmd0aCgpIHsKICAgICAgbGV0IG1heCA9IG51bGw7CiAgICAgIGZvciAoY29uc3QgY2ggb2YgdGhpcy5fZGVmLmNoZWNrcykgewogICAgICAgIGlmIChjaC5raW5kID09PSAibWF4IikgewogICAgICAgICAgaWYgKG1heCA9PT0gbnVsbCB8fCBjaC52YWx1ZSA8IG1heCkKICAgICAgICAgICAgbWF4ID0gY2gudmFsdWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBtYXg7CiAgICB9CiAgfQogIFpvZFN0cmluZy5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICB2YXIgX2E7CiAgICByZXR1cm4gbmV3IFpvZFN0cmluZyh7CiAgICAgIGNoZWNrczogW10sCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kU3RyaW5nLAogICAgICBjb2VyY2U6IChfYSA9IHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5jb2VyY2UpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IGZhbHNlLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgZnVuY3Rpb24gZmxvYXRTYWZlUmVtYWluZGVyKHZhbCwgc3RlcCkgewogICAgY29uc3QgdmFsRGVjQ291bnQgPSAodmFsLnRvU3RyaW5nKCkuc3BsaXQoIi4iKVsxXSB8fCAiIikubGVuZ3RoOwogICAgY29uc3Qgc3RlcERlY0NvdW50ID0gKHN0ZXAudG9TdHJpbmcoKS5zcGxpdCgiLiIpWzFdIHx8ICIiKS5sZW5ndGg7CiAgICBjb25zdCBkZWNDb3VudCA9IHZhbERlY0NvdW50ID4gc3RlcERlY0NvdW50ID8gdmFsRGVjQ291bnQgOiBzdGVwRGVjQ291bnQ7CiAgICBjb25zdCB2YWxJbnQgPSBwYXJzZUludCh2YWwudG9GaXhlZChkZWNDb3VudCkucmVwbGFjZSgiLiIsICIiKSk7CiAgICBjb25zdCBzdGVwSW50ID0gcGFyc2VJbnQoc3RlcC50b0ZpeGVkKGRlY0NvdW50KS5yZXBsYWNlKCIuIiwgIiIpKTsKICAgIHJldHVybiB2YWxJbnQgJSBzdGVwSW50IC8gTWF0aC5wb3coMTAsIGRlY0NvdW50KTsKICB9CiAgY2xhc3MgWm9kTnVtYmVyIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgdGhpcy5taW4gPSB0aGlzLmd0ZTsKICAgICAgdGhpcy5tYXggPSB0aGlzLmx0ZTsKICAgICAgdGhpcy5zdGVwID0gdGhpcy5tdWx0aXBsZU9mOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGlmICh0aGlzLl9kZWYuY29lcmNlKSB7CiAgICAgICAgaW5wdXQuZGF0YSA9IE51bWJlcihpbnB1dC5kYXRhKTsKICAgICAgfQogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm51bWJlcikgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm51bWJlciwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgyLnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBsZXQgY3R4ID0gdm9pZCAwOwogICAgICBjb25zdCBzdGF0dXMgPSBuZXcgUGFyc2VTdGF0dXMoKTsKICAgICAgZm9yIChjb25zdCBjaGVjayBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoZWNrLmtpbmQgPT09ICJpbnQiKSB7CiAgICAgICAgICBpZiAoIXV0aWwuaXNJbnRlZ2VyKGlucHV0LmRhdGEpKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgICAgIGV4cGVjdGVkOiAiaW50ZWdlciIsCiAgICAgICAgICAgICAgcmVjZWl2ZWQ6ICJmbG9hdCIsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAibWluIikgewogICAgICAgICAgY29uc3QgdG9vU21hbGwgPSBjaGVjay5pbmNsdXNpdmUgPyBpbnB1dC5kYXRhIDwgY2hlY2sudmFsdWUgOiBpbnB1dC5kYXRhIDw9IGNoZWNrLnZhbHVlOwogICAgICAgICAgaWYgKHRvb1NtYWxsKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgICAgIG1pbmltdW06IGNoZWNrLnZhbHVlLAogICAgICAgICAgICAgIHR5cGU6ICJudW1iZXIiLAogICAgICAgICAgICAgIGluY2x1c2l2ZTogY2hlY2suaW5jbHVzaXZlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBjb25zdCB0b29CaWcgPSBjaGVjay5pbmNsdXNpdmUgPyBpbnB1dC5kYXRhID4gY2hlY2sudmFsdWUgOiBpbnB1dC5kYXRhID49IGNoZWNrLnZhbHVlOwogICAgICAgICAgaWYgKHRvb0JpZykgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19iaWcsCiAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogIm51bWJlciIsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiBjaGVjay5pbmNsdXNpdmUsCiAgICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gIm11bHRpcGxlT2YiKSB7CiAgICAgICAgICBpZiAoZmxvYXRTYWZlUmVtYWluZGVyKGlucHV0LmRhdGEsIGNoZWNrLnZhbHVlKSAhPT0gMCkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLm5vdF9tdWx0aXBsZV9vZiwKICAgICAgICAgICAgICBtdWx0aXBsZU9mOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGNoZWNrLmtpbmQgPT09ICJmaW5pdGUiKSB7CiAgICAgICAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShpbnB1dC5kYXRhKSkgewogICAgICAgICAgICBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCwgY3R4KTsKICAgICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLm5vdF9maW5pdGUsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoY2hlY2spOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGlucHV0LmRhdGEgfTsKICAgIH0KICAgIGd0ZSh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIHRydWUsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBndCh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIGZhbHNlLCBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkpOwogICAgfQogICAgbHRlKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgdHJ1ZSwgZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpKTsKICAgIH0KICAgIGx0KHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgZmFsc2UsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBzZXRMaW1pdChraW5kLCB2YWx1ZSwgaW5jbHVzaXZlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kTnVtYmVyKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbCiAgICAgICAgICAuLi50aGlzLl9kZWYuY2hlY2tzLAogICAgICAgICAgewogICAgICAgICAgICBraW5kLAogICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgaW5jbHVzaXZlLAogICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgICAgIH0KICAgICAgICBdCiAgICAgIH0pOwogICAgfQogICAgX2FkZENoZWNrKGNoZWNrKSB7CiAgICAgIHJldHVybiBuZXcgWm9kTnVtYmVyKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgY2hlY2tdCiAgICAgIH0pOwogICAgfQogICAgaW50KG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAiaW50IiwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBwb3NpdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IDAsCiAgICAgICAgaW5jbHVzaXZlOiBmYWxzZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBuZWdhdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IDAsCiAgICAgICAgaW5jbHVzaXZlOiBmYWxzZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBub25wb3NpdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IDAsCiAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIG5vbm5lZ2F0aXZlKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAibWluIiwKICAgICAgICB2YWx1ZTogMCwKICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpCiAgICAgIH0pOwogICAgfQogICAgbXVsdGlwbGVPZih2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtdWx0aXBsZU9mIiwKICAgICAgICB2YWx1ZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBmaW5pdGUobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJmaW5pdGUiLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIHNhZmUobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtaW4iLAogICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICB2YWx1ZTogTnVtYmVyLk1JTl9TQUZFX0lOVEVHRVIsCiAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpCiAgICAgIH0pLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgIHZhbHVlOiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBnZXQgbWluVmFsdWUoKSB7CiAgICAgIGxldCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChtaW4gPT09IG51bGwgfHwgY2gudmFsdWUgPiBtaW4pCiAgICAgICAgICAgIG1pbiA9IGNoLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbWluOwogICAgfQogICAgZ2V0IG1heFZhbHVlKCkgewogICAgICBsZXQgbWF4ID0gbnVsbDsKICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNoLnZhbHVlIDwgbWF4KQogICAgICAgICAgICBtYXggPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG1heDsKICAgIH0KICAgIGdldCBpc0ludCgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fZGVmLmNoZWNrcy5maW5kKChjaCkgPT4gY2gua2luZCA9PT0gImludCIgfHwgY2gua2luZCA9PT0gIm11bHRpcGxlT2YiICYmIHV0aWwuaXNJbnRlZ2VyKGNoLnZhbHVlKSk7CiAgICB9CiAgICBnZXQgaXNGaW5pdGUoKSB7CiAgICAgIGxldCBtYXggPSBudWxsLCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gImZpbml0ZSIgfHwgY2gua2luZCA9PT0gImludCIgfHwgY2gua2luZCA9PT0gIm11bHRpcGxlT2YiKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9IGVsc2UgaWYgKGNoLmtpbmQgPT09ICJtaW4iKSB7CiAgICAgICAgICBpZiAobWluID09PSBudWxsIHx8IGNoLnZhbHVlID4gbWluKQogICAgICAgICAgICBtaW4gPSBjaC52YWx1ZTsKICAgICAgICB9IGVsc2UgaWYgKGNoLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNoLnZhbHVlIDwgbWF4KQogICAgICAgICAgICBtYXggPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShtaW4pICYmIE51bWJlci5pc0Zpbml0ZShtYXgpOwogICAgfQogIH0KICBab2ROdW1iZXIuY3JlYXRlID0gKHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2ROdW1iZXIoewogICAgICBjaGVja3M6IFtdLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE51bWJlciwKICAgICAgY29lcmNlOiAocGFyYW1zID09PSBudWxsIHx8IHBhcmFtcyA9PT0gdm9pZCAwID8gdm9pZCAwIDogcGFyYW1zLmNvZXJjZSkgfHwgZmFsc2UsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RCaWdJbnQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICB0aGlzLm1pbiA9IHRoaXMuZ3RlOwogICAgICB0aGlzLm1heCA9IHRoaXMubHRlOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGlmICh0aGlzLl9kZWYuY29lcmNlKSB7CiAgICAgICAgaW5wdXQuZGF0YSA9IEJpZ0ludChpbnB1dC5kYXRhKTsKICAgICAgfQogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLmJpZ2ludCkgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmJpZ2ludCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgyLnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBsZXQgY3R4ID0gdm9pZCAwOwogICAgICBjb25zdCBzdGF0dXMgPSBuZXcgUGFyc2VTdGF0dXMoKTsKICAgICAgZm9yIChjb25zdCBjaGVjayBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoZWNrLmtpbmQgPT09ICJtaW4iKSB7CiAgICAgICAgICBjb25zdCB0b29TbWFsbCA9IGNoZWNrLmluY2x1c2l2ZSA/IGlucHV0LmRhdGEgPCBjaGVjay52YWx1ZSA6IGlucHV0LmRhdGEgPD0gY2hlY2sudmFsdWU7CiAgICAgICAgICBpZiAodG9vU21hbGwpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgICAgdHlwZTogImJpZ2ludCIsCiAgICAgICAgICAgICAgbWluaW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiBjaGVjay5pbmNsdXNpdmUsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjaGVjay5raW5kID09PSAibWF4IikgewogICAgICAgICAgY29uc3QgdG9vQmlnID0gY2hlY2suaW5jbHVzaXZlID8gaW5wdXQuZGF0YSA+IGNoZWNrLnZhbHVlIDogaW5wdXQuZGF0YSA+PSBjaGVjay52YWx1ZTsKICAgICAgICAgIGlmICh0b29CaWcpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fYmlnLAogICAgICAgICAgICAgIHR5cGU6ICJiaWdpbnQiLAogICAgICAgICAgICAgIG1heGltdW06IGNoZWNrLnZhbHVlLAogICAgICAgICAgICAgIGluY2x1c2l2ZTogY2hlY2suaW5jbHVzaXZlLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gIm11bHRpcGxlT2YiKSB7CiAgICAgICAgICBpZiAoaW5wdXQuZGF0YSAlIGNoZWNrLnZhbHVlICE9PSBCaWdJbnQoMCkpIHsKICAgICAgICAgICAgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQsIGN0eCk7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5ub3RfbXVsdGlwbGVfb2YsCiAgICAgICAgICAgICAgbXVsdGlwbGVPZjogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgbWVzc2FnZTogY2hlY2subWVzc2FnZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoY2hlY2spOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGlucHV0LmRhdGEgfTsKICAgIH0KICAgIGd0ZSh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIHRydWUsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBndCh2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5zZXRMaW1pdCgibWluIiwgdmFsdWUsIGZhbHNlLCBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkpOwogICAgfQogICAgbHRlKHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgdHJ1ZSwgZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpKTsKICAgIH0KICAgIGx0KHZhbHVlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLnNldExpbWl0KCJtYXgiLCB2YWx1ZSwgZmFsc2UsIGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSk7CiAgICB9CiAgICBzZXRMaW1pdChraW5kLCB2YWx1ZSwgaW5jbHVzaXZlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQmlnSW50KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbCiAgICAgICAgICAuLi50aGlzLl9kZWYuY2hlY2tzLAogICAgICAgICAgewogICAgICAgICAgICBraW5kLAogICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgaW5jbHVzaXZlLAogICAgICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgICAgIH0KICAgICAgICBdCiAgICAgIH0pOwogICAgfQogICAgX2FkZENoZWNrKGNoZWNrKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQmlnSW50KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgY2hlY2tzOiBbLi4udGhpcy5fZGVmLmNoZWNrcywgY2hlY2tdCiAgICAgIH0pOwogICAgfQogICAgcG9zaXRpdmUobWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtaW4iLAogICAgICAgIHZhbHVlOiBCaWdJbnQoMCksCiAgICAgICAgaW5jbHVzaXZlOiBmYWxzZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBuZWdhdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IEJpZ0ludCgwKSwKICAgICAgICBpbmNsdXNpdmU6IGZhbHNlLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIG5vbnBvc2l0aXZlKG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FkZENoZWNrKHsKICAgICAgICBraW5kOiAibWF4IiwKICAgICAgICB2YWx1ZTogQmlnSW50KDApLAogICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBub25uZWdhdGl2ZShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IEJpZ0ludCgwKSwKICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpCiAgICAgIH0pOwogICAgfQogICAgbXVsdGlwbGVPZih2YWx1ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gdGhpcy5fYWRkQ2hlY2soewogICAgICAgIGtpbmQ6ICJtdWx0aXBsZU9mIiwKICAgICAgICB2YWx1ZSwKICAgICAgICBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkKICAgICAgfSk7CiAgICB9CiAgICBnZXQgbWluVmFsdWUoKSB7CiAgICAgIGxldCBtaW4gPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2gua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChtaW4gPT09IG51bGwgfHwgY2gudmFsdWUgPiBtaW4pCiAgICAgICAgICAgIG1pbiA9IGNoLnZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbWluOwogICAgfQogICAgZ2V0IG1heFZhbHVlKCkgewogICAgICBsZXQgbWF4ID0gbnVsbDsKICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoLmtpbmQgPT09ICJtYXgiKSB7CiAgICAgICAgICBpZiAobWF4ID09PSBudWxsIHx8IGNoLnZhbHVlIDwgbWF4KQogICAgICAgICAgICBtYXggPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG1heDsKICAgIH0KICB9CiAgWm9kQmlnSW50LmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHZhciBfYTsKICAgIHJldHVybiBuZXcgWm9kQmlnSW50KHsKICAgICAgY2hlY2tzOiBbXSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RCaWdJbnQsCiAgICAgIGNvZXJjZTogKF9hID0gcGFyYW1zID09PSBudWxsIHx8IHBhcmFtcyA9PT0gdm9pZCAwID8gdm9pZCAwIDogcGFyYW1zLmNvZXJjZSkgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogZmFsc2UsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RCb29sZWFuIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgaWYgKHRoaXMuX2RlZi5jb2VyY2UpIHsKICAgICAgICBpbnB1dC5kYXRhID0gQm9vbGVhbihpbnB1dC5kYXRhKTsKICAgICAgfQogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLmJvb2xlYW4pIHsKICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUuYm9vbGVhbiwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTsKICAgIH0KICB9CiAgWm9kQm9vbGVhbi5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZEJvb2xlYW4oewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEJvb2xlYW4sCiAgICAgIGNvZXJjZTogKHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5jb2VyY2UpIHx8IGZhbHNlLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kRGF0ZSBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGlmICh0aGlzLl9kZWYuY29lcmNlKSB7CiAgICAgICAgaW5wdXQuZGF0YSA9IG5ldyBEYXRlKGlucHV0LmRhdGEpOwogICAgICB9CiAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTsKICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuZGF0ZSkgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmRhdGUsCiAgICAgICAgICByZWNlaXZlZDogY3R4Mi5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgaWYgKGlzTmFOKGlucHV0LmRhdGEuZ2V0VGltZSgpKSkgewogICAgICAgIGNvbnN0IGN0eDIgPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4MiwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfZGF0ZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IHN0YXR1cyA9IG5ldyBQYXJzZVN0YXR1cygpOwogICAgICBsZXQgY3R4ID0gdm9pZCAwOwogICAgICBmb3IgKGNvbnN0IGNoZWNrIG9mIHRoaXMuX2RlZi5jaGVja3MpIHsKICAgICAgICBpZiAoY2hlY2sua2luZCA9PT0gIm1pbiIpIHsKICAgICAgICAgIGlmIChpbnB1dC5kYXRhLmdldFRpbWUoKSA8IGNoZWNrLnZhbHVlKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgICAgIG1lc3NhZ2U6IGNoZWNrLm1lc3NhZ2UsCiAgICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgICBtaW5pbXVtOiBjaGVjay52YWx1ZSwKICAgICAgICAgICAgICB0eXBlOiAiZGF0ZSIKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoY2hlY2sua2luZCA9PT0gIm1heCIpIHsKICAgICAgICAgIGlmIChpbnB1dC5kYXRhLmdldFRpbWUoKSA+IGNoZWNrLnZhbHVlKSB7CiAgICAgICAgICAgIGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0LCBjdHgpOwogICAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX2JpZywKICAgICAgICAgICAgICBtZXNzYWdlOiBjaGVjay5tZXNzYWdlLAogICAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgICAgICBleGFjdDogZmFsc2UsCiAgICAgICAgICAgICAgbWF4aW11bTogY2hlY2sudmFsdWUsCiAgICAgICAgICAgICAgdHlwZTogImRhdGUiCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgdXRpbC5hc3NlcnROZXZlcihjaGVjayk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgc3RhdHVzOiBzdGF0dXMudmFsdWUsCiAgICAgICAgdmFsdWU6IG5ldyBEYXRlKGlucHV0LmRhdGEuZ2V0VGltZSgpKQogICAgICB9OwogICAgfQogICAgX2FkZENoZWNrKGNoZWNrKSB7CiAgICAgIHJldHVybiBuZXcgWm9kRGF0ZSh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIGNoZWNrczogWy4uLnRoaXMuX2RlZi5jaGVja3MsIGNoZWNrXQogICAgICB9KTsKICAgIH0KICAgIG1pbihtaW5EYXRlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1pbiIsCiAgICAgICAgdmFsdWU6IG1pbkRhdGUuZ2V0VGltZSgpLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIG1heChtYXhEYXRlLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLl9hZGRDaGVjayh7CiAgICAgICAga2luZDogIm1heCIsCiAgICAgICAgdmFsdWU6IG1heERhdGUuZ2V0VGltZSgpLAogICAgICAgIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKQogICAgICB9KTsKICAgIH0KICAgIGdldCBtaW5EYXRlKCkgewogICAgICBsZXQgbWluID0gbnVsbDsKICAgICAgZm9yIChjb25zdCBjaCBvZiB0aGlzLl9kZWYuY2hlY2tzKSB7CiAgICAgICAgaWYgKGNoLmtpbmQgPT09ICJtaW4iKSB7CiAgICAgICAgICBpZiAobWluID09PSBudWxsIHx8IGNoLnZhbHVlID4gbWluKQogICAgICAgICAgICBtaW4gPSBjaC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG1pbiAhPSBudWxsID8gbmV3IERhdGUobWluKSA6IG51bGw7CiAgICB9CiAgICBnZXQgbWF4RGF0ZSgpIHsKICAgICAgbGV0IG1heCA9IG51bGw7CiAgICAgIGZvciAoY29uc3QgY2ggb2YgdGhpcy5fZGVmLmNoZWNrcykgewogICAgICAgIGlmIChjaC5raW5kID09PSAibWF4IikgewogICAgICAgICAgaWYgKG1heCA9PT0gbnVsbCB8fCBjaC52YWx1ZSA8IG1heCkKICAgICAgICAgICAgbWF4ID0gY2gudmFsdWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBtYXggIT0gbnVsbCA/IG5ldyBEYXRlKG1heCkgOiBudWxsOwogICAgfQogIH0KICBab2REYXRlLmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kRGF0ZSh7CiAgICAgIGNoZWNrczogW10sCiAgICAgIGNvZXJjZTogKHBhcmFtcyA9PT0gbnVsbCB8fCBwYXJhbXMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHBhcmFtcy5jb2VyY2UpIHx8IGZhbHNlLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZERhdGUsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RTeW1ib2wgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLnN5bWJvbCkgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5zeW1ib2wsCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7CiAgICB9CiAgfQogIFpvZFN5bWJvbC5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZFN5bWJvbCh7CiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kU3ltYm9sLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kVW5kZWZpbmVkIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS51bmRlZmluZWQpIHsKICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgcmV0dXJuIE9LKGlucHV0LmRhdGEpOwogICAgfQogIH0KICBab2RVbmRlZmluZWQuY3JlYXRlID0gKHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RVbmRlZmluZWQoewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZFVuZGVmaW5lZCwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE51bGwgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm51bGwpIHsKICAgICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUubnVsbCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTsKICAgIH0KICB9CiAgWm9kTnVsbC5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE51bGwoewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE51bGwsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RBbnkgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICB0aGlzLl9hbnkgPSB0cnVlOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIHJldHVybiBPSyhpbnB1dC5kYXRhKTsKICAgIH0KICB9CiAgWm9kQW55LmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kQW55KHsKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RBbnksCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RVbmtub3duIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgdGhpcy5fdW5rbm93biA9IHRydWU7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgcmV0dXJuIE9LKGlucHV0LmRhdGEpOwogICAgfQogIH0KICBab2RVbmtub3duLmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kVW5rbm93bih7CiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kVW5rbm93biwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE5ldmVyIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm5ldmVyLAogICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICB9KTsKICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICB9CiAgfQogIFpvZE5ldmVyLmNyZWF0ZSA9IChwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kTmV2ZXIoewogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE5ldmVyLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kVm9pZCBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTsKICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkKSB7CiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLnZvaWQsCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7CiAgICB9CiAgfQogIFpvZFZvaWQuY3JlYXRlID0gKHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RWb2lkKHsKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RWb2lkLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kQXJyYXkgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCwgc3RhdHVzIH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBkZWYgPSB0aGlzLl9kZWY7CiAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5hcnJheSkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmFycmF5LAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgaWYgKGRlZi5leGFjdExlbmd0aCAhPT0gbnVsbCkgewogICAgICAgIGNvbnN0IHRvb0JpZyA9IGN0eC5kYXRhLmxlbmd0aCA+IGRlZi5leGFjdExlbmd0aC52YWx1ZTsKICAgICAgICBjb25zdCB0b29TbWFsbCA9IGN0eC5kYXRhLmxlbmd0aCA8IGRlZi5leGFjdExlbmd0aC52YWx1ZTsKICAgICAgICBpZiAodG9vQmlnIHx8IHRvb1NtYWxsKSB7CiAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgY29kZTogdG9vQmlnID8gWm9kSXNzdWVDb2RlLnRvb19iaWcgOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgICBtaW5pbXVtOiB0b29TbWFsbCA/IGRlZi5leGFjdExlbmd0aC52YWx1ZSA6IHZvaWQgMCwKICAgICAgICAgICAgbWF4aW11bTogdG9vQmlnID8gZGVmLmV4YWN0TGVuZ3RoLnZhbHVlIDogdm9pZCAwLAogICAgICAgICAgICB0eXBlOiAiYXJyYXkiLAogICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgICAgIGV4YWN0OiB0cnVlLAogICAgICAgICAgICBtZXNzYWdlOiBkZWYuZXhhY3RMZW5ndGgubWVzc2FnZQogICAgICAgICAgfSk7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGRlZi5taW5MZW5ndGggIT09IG51bGwpIHsKICAgICAgICBpZiAoY3R4LmRhdGEubGVuZ3RoIDwgZGVmLm1pbkxlbmd0aC52YWx1ZSkgewogICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fc21hbGwsCiAgICAgICAgICAgIG1pbmltdW06IGRlZi5taW5MZW5ndGgudmFsdWUsCiAgICAgICAgICAgIHR5cGU6ICJhcnJheSIsCiAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLAogICAgICAgICAgICBtZXNzYWdlOiBkZWYubWluTGVuZ3RoLm1lc3NhZ2UKICAgICAgICAgIH0pOwogICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChkZWYubWF4TGVuZ3RoICE9PSBudWxsKSB7CiAgICAgICAgaWYgKGN0eC5kYXRhLmxlbmd0aCA+IGRlZi5tYXhMZW5ndGgudmFsdWUpIHsKICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX2JpZywKICAgICAgICAgICAgbWF4aW11bTogZGVmLm1heExlbmd0aC52YWx1ZSwKICAgICAgICAgICAgdHlwZTogImFycmF5IiwKICAgICAgICAgICAgaW5jbHVzaXZlOiB0cnVlLAogICAgICAgICAgICBleGFjdDogZmFsc2UsCiAgICAgICAgICAgIG1lc3NhZ2U6IGRlZi5tYXhMZW5ndGgubWVzc2FnZQogICAgICAgICAgfSk7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoWy4uLmN0eC5kYXRhXS5tYXAoKGl0ZW0sIGkyKSA9PiB7CiAgICAgICAgICByZXR1cm4gZGVmLnR5cGUuX3BhcnNlQXN5bmMobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGl0ZW0sIGN0eC5wYXRoLCBpMikpOwogICAgICAgIH0pKS50aGVuKChyZXN1bHQyKSA9PiB7CiAgICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VBcnJheShzdGF0dXMsIHJlc3VsdDIpOwogICAgICAgIH0pOwogICAgICB9CiAgICAgIGNvbnN0IHJlc3VsdCA9IFsuLi5jdHguZGF0YV0ubWFwKChpdGVtLCBpMikgPT4gewogICAgICAgIHJldHVybiBkZWYudHlwZS5fcGFyc2VTeW5jKG5ldyBQYXJzZUlucHV0TGF6eVBhdGgoY3R4LCBpdGVtLCBjdHgucGF0aCwgaTIpKTsKICAgICAgfSk7CiAgICAgIHJldHVybiBQYXJzZVN0YXR1cy5tZXJnZUFycmF5KHN0YXR1cywgcmVzdWx0KTsKICAgIH0KICAgIGdldCBlbGVtZW50KCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnR5cGU7CiAgICB9CiAgICBtaW4obWluTGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBtaW5MZW5ndGg6IHsgdmFsdWU6IG1pbkxlbmd0aCwgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpIH0KICAgICAgfSk7CiAgICB9CiAgICBtYXgobWF4TGVuZ3RoLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBtYXhMZW5ndGg6IHsgdmFsdWU6IG1heExlbmd0aCwgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpIH0KICAgICAgfSk7CiAgICB9CiAgICBsZW5ndGgobGVuLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBleGFjdExlbmd0aDogeyB2YWx1ZTogbGVuLCBtZXNzYWdlOiBlcnJvclV0aWwudG9TdHJpbmcobWVzc2FnZSkgfQogICAgICB9KTsKICAgIH0KICAgIG5vbmVtcHR5KG1lc3NhZ2UpIHsKICAgICAgcmV0dXJuIHRoaXMubWluKDEsIG1lc3NhZ2UpOwogICAgfQogIH0KICBab2RBcnJheS5jcmVhdGUgPSAoc2NoZW1hLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kQXJyYXkoewogICAgICB0eXBlOiBzY2hlbWEsCiAgICAgIG1pbkxlbmd0aDogbnVsbCwKICAgICAgbWF4TGVuZ3RoOiBudWxsLAogICAgICBleGFjdExlbmd0aDogbnVsbCwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RBcnJheSwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGZ1bmN0aW9uIGRlZXBQYXJ0aWFsaWZ5KHNjaGVtYSkgewogICAgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZE9iamVjdCkgewogICAgICBjb25zdCBuZXdTaGFwZSA9IHt9OwogICAgICBmb3IgKGNvbnN0IGtleSBpbiBzY2hlbWEuc2hhcGUpIHsKICAgICAgICBjb25zdCBmaWVsZFNjaGVtYSA9IHNjaGVtYS5zaGFwZVtrZXldOwogICAgICAgIG5ld1NoYXBlW2tleV0gPSBab2RPcHRpb25hbC5jcmVhdGUoZGVlcFBhcnRpYWxpZnkoZmllbGRTY2hlbWEpKTsKICAgICAgfQogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4uc2NoZW1hLl9kZWYsCiAgICAgICAgc2hhcGU6ICgpID0+IG5ld1NoYXBlCiAgICAgIH0pOwogICAgfSBlbHNlIGlmIChzY2hlbWEgaW5zdGFuY2VvZiBab2RBcnJheSkgewogICAgICByZXR1cm4gbmV3IFpvZEFycmF5KHsKICAgICAgICAuLi5zY2hlbWEuX2RlZiwKICAgICAgICB0eXBlOiBkZWVwUGFydGlhbGlmeShzY2hlbWEuZWxlbWVudCkKICAgICAgfSk7CiAgICB9IGVsc2UgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZE9wdGlvbmFsKSB7CiAgICAgIHJldHVybiBab2RPcHRpb25hbC5jcmVhdGUoZGVlcFBhcnRpYWxpZnkoc2NoZW1hLnVud3JhcCgpKSk7CiAgICB9IGVsc2UgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZE51bGxhYmxlKSB7CiAgICAgIHJldHVybiBab2ROdWxsYWJsZS5jcmVhdGUoZGVlcFBhcnRpYWxpZnkoc2NoZW1hLnVud3JhcCgpKSk7CiAgICB9IGVsc2UgaWYgKHNjaGVtYSBpbnN0YW5jZW9mIFpvZFR1cGxlKSB7CiAgICAgIHJldHVybiBab2RUdXBsZS5jcmVhdGUoc2NoZW1hLml0ZW1zLm1hcCgoaXRlbSkgPT4gZGVlcFBhcnRpYWxpZnkoaXRlbSkpKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBzY2hlbWE7CiAgICB9CiAgfQogIGNsYXNzIFpvZE9iamVjdCBleHRlbmRzIFpvZFR5cGUgewogICAgY29uc3RydWN0b3IoKSB7CiAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7CiAgICAgIHRoaXMuX2NhY2hlZCA9IG51bGw7CiAgICAgIHRoaXMubm9uc3RyaWN0ID0gdGhpcy5wYXNzdGhyb3VnaDsKICAgICAgdGhpcy5hdWdtZW50ID0gdGhpcy5leHRlbmQ7CiAgICB9CiAgICBfZ2V0Q2FjaGVkKCkgewogICAgICBpZiAodGhpcy5fY2FjaGVkICE9PSBudWxsKQogICAgICAgIHJldHVybiB0aGlzLl9jYWNoZWQ7CiAgICAgIGNvbnN0IHNoYXBlID0gdGhpcy5fZGVmLnNoYXBlKCk7CiAgICAgIGNvbnN0IGtleXMgPSB1dGlsLm9iamVjdEtleXMoc2hhcGUpOwogICAgICByZXR1cm4gdGhpcy5fY2FjaGVkID0geyBzaGFwZSwga2V5cyB9OwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHBhcnNlZFR5cGUgPSB0aGlzLl9nZXRUeXBlKGlucHV0KTsKICAgICAgaWYgKHBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUub2JqZWN0KSB7CiAgICAgICAgY29uc3QgY3R4MiA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgyLCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUub2JqZWN0LAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eDIucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IHsgc3RhdHVzLCBjdHggfSA9IHRoaXMuX3Byb2Nlc3NJbnB1dFBhcmFtcyhpbnB1dCk7CiAgICAgIGNvbnN0IHsgc2hhcGUsIGtleXM6IHNoYXBlS2V5cyB9ID0gdGhpcy5fZ2V0Q2FjaGVkKCk7CiAgICAgIGNvbnN0IGV4dHJhS2V5cyA9IFtdOwogICAgICBpZiAoISh0aGlzLl9kZWYuY2F0Y2hhbGwgaW5zdGFuY2VvZiBab2ROZXZlciAmJiB0aGlzLl9kZWYudW5rbm93bktleXMgPT09ICJzdHJpcCIpKSB7CiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gY3R4LmRhdGEpIHsKICAgICAgICAgIGlmICghc2hhcGVLZXlzLmluY2x1ZGVzKGtleSkpIHsKICAgICAgICAgICAgZXh0cmFLZXlzLnB1c2goa2V5KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgcGFpcnMgPSBbXTsKICAgICAgZm9yIChjb25zdCBrZXkgb2Ygc2hhcGVLZXlzKSB7CiAgICAgICAgY29uc3Qga2V5VmFsaWRhdG9yID0gc2hhcGVba2V5XTsKICAgICAgICBjb25zdCB2YWx1ZSA9IGN0eC5kYXRhW2tleV07CiAgICAgICAgcGFpcnMucHVzaCh7CiAgICAgICAgICBrZXk6IHsgc3RhdHVzOiAidmFsaWQiLCB2YWx1ZToga2V5IH0sCiAgICAgICAgICB2YWx1ZToga2V5VmFsaWRhdG9yLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwgdmFsdWUsIGN0eC5wYXRoLCBrZXkpKSwKICAgICAgICAgIGFsd2F5c1NldDoga2V5IGluIGN0eC5kYXRhCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuX2RlZi5jYXRjaGFsbCBpbnN0YW5jZW9mIFpvZE5ldmVyKSB7CiAgICAgICAgY29uc3QgdW5rbm93bktleXMgPSB0aGlzLl9kZWYudW5rbm93bktleXM7CiAgICAgICAgaWYgKHVua25vd25LZXlzID09PSAicGFzc3Rocm91Z2giKSB7CiAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBleHRyYUtleXMpIHsKICAgICAgICAgICAgcGFpcnMucHVzaCh7CiAgICAgICAgICAgICAga2V5OiB7IHN0YXR1czogInZhbGlkIiwgdmFsdWU6IGtleSB9LAogICAgICAgICAgICAgIHZhbHVlOiB7IHN0YXR1czogInZhbGlkIiwgdmFsdWU6IGN0eC5kYXRhW2tleV0gfQogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKHVua25vd25LZXlzID09PSAic3RyaWN0IikgewogICAgICAgICAgaWYgKGV4dHJhS2V5cy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS51bnJlY29nbml6ZWRfa2V5cywKICAgICAgICAgICAgICBrZXlzOiBleHRyYUtleXMKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAodW5rbm93bktleXMgPT09ICJzdHJpcCIpIDsKICAgICAgICBlbHNlIHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW50ZXJuYWwgWm9kT2JqZWN0IGVycm9yOiBpbnZhbGlkIHVua25vd25LZXlzIHZhbHVlLmApOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBjYXRjaGFsbCA9IHRoaXMuX2RlZi5jYXRjaGFsbDsKICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBleHRyYUtleXMpIHsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gY3R4LmRhdGFba2V5XTsKICAgICAgICAgIHBhaXJzLnB1c2goewogICAgICAgICAgICBrZXk6IHsgc3RhdHVzOiAidmFsaWQiLCB2YWx1ZToga2V5IH0sCiAgICAgICAgICAgIHZhbHVlOiBjYXRjaGFsbC5fcGFyc2UoCiAgICAgICAgICAgICAgbmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIHZhbHVlLCBjdHgucGF0aCwga2V5KQogICAgICAgICAgICAgIC8vLCBjdHguY2hpbGQoa2V5KSwgdmFsdWUsIGdldFBhcnNlZFR5cGUodmFsdWUpCiAgICAgICAgICAgICksCiAgICAgICAgICAgIGFsd2F5c1NldDoga2V5IGluIGN0eC5kYXRhCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihhc3luYyAoKSA9PiB7CiAgICAgICAgICBjb25zdCBzeW5jUGFpcnMgPSBbXTsKICAgICAgICAgIGZvciAoY29uc3QgcGFpciBvZiBwYWlycykgewogICAgICAgICAgICBjb25zdCBrZXkgPSBhd2FpdCBwYWlyLmtleTsKICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCBwYWlyLnZhbHVlOwogICAgICAgICAgICBzeW5jUGFpcnMucHVzaCh7CiAgICAgICAgICAgICAga2V5LAogICAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICAgIGFsd2F5c1NldDogcGFpci5hbHdheXNTZXQKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gc3luY1BhaXJzOwogICAgICAgIH0pLnRoZW4oKHN5bmNQYWlycykgPT4gewogICAgICAgICAgcmV0dXJuIFBhcnNlU3RhdHVzLm1lcmdlT2JqZWN0U3luYyhzdGF0dXMsIHN5bmNQYWlycyk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIFBhcnNlU3RhdHVzLm1lcmdlT2JqZWN0U3luYyhzdGF0dXMsIHBhaXJzKTsKICAgICAgfQogICAgfQogICAgZ2V0IHNoYXBlKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnNoYXBlKCk7CiAgICB9CiAgICBzdHJpY3QobWVzc2FnZSkgewogICAgICBlcnJvclV0aWwuZXJyVG9PYmo7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgdW5rbm93bktleXM6ICJzdHJpY3QiLAogICAgICAgIC4uLm1lc3NhZ2UgIT09IHZvaWQgMCA/IHsKICAgICAgICAgIGVycm9yTWFwOiAoaXNzdWUsIGN0eCkgPT4gewogICAgICAgICAgICB2YXIgX2EsIF9iLCBfYywgX2Q7CiAgICAgICAgICAgIGNvbnN0IGRlZmF1bHRFcnJvciA9IChfYyA9IChfYiA9IChfYSA9IHRoaXMuX2RlZikuZXJyb3JNYXApID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5jYWxsKF9hLCBpc3N1ZSwgY3R4KS5tZXNzYWdlKSAhPT0gbnVsbCAmJiBfYyAhPT0gdm9pZCAwID8gX2MgOiBjdHguZGVmYXVsdEVycm9yOwogICAgICAgICAgICBpZiAoaXNzdWUuY29kZSA9PT0gInVucmVjb2duaXplZF9rZXlzIikKICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgbWVzc2FnZTogKF9kID0gZXJyb3JVdGlsLmVyclRvT2JqKG1lc3NhZ2UpLm1lc3NhZ2UpICE9PSBudWxsICYmIF9kICE9PSB2b2lkIDAgPyBfZCA6IGRlZmF1bHRFcnJvcgogICAgICAgICAgICAgIH07CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgbWVzc2FnZTogZGVmYXVsdEVycm9yCiAgICAgICAgICAgIH07CiAgICAgICAgICB9CiAgICAgICAgfSA6IHt9CiAgICAgIH0pOwogICAgfQogICAgc3RyaXAoKSB7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgdW5rbm93bktleXM6ICJzdHJpcCIKICAgICAgfSk7CiAgICB9CiAgICBwYXNzdGhyb3VnaCgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICB1bmtub3duS2V5czogInBhc3N0aHJvdWdoIgogICAgICB9KTsKICAgIH0KICAgIC8vIGNvbnN0IEF1Z21lbnRGYWN0b3J5ID0KICAgIC8vICAgPERlZiBleHRlbmRzIFpvZE9iamVjdERlZj4oZGVmOiBEZWYpID0+CiAgICAvLyAgIDxBdWdtZW50YXRpb24gZXh0ZW5kcyBab2RSYXdTaGFwZT4oCiAgICAvLyAgICAgYXVnbWVudGF0aW9uOiBBdWdtZW50YXRpb24KICAgIC8vICAgKTogWm9kT2JqZWN0PAogICAgLy8gICAgIGV4dGVuZFNoYXBlPFJldHVyblR5cGU8RGVmWyJzaGFwZSJdPiwgQXVnbWVudGF0aW9uPiwKICAgIC8vICAgICBEZWZbInVua25vd25LZXlzIl0sCiAgICAvLyAgICAgRGVmWyJjYXRjaGFsbCJdCiAgICAvLyAgID4gPT4gewogICAgLy8gICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgIC8vICAgICAgIC4uLmRlZiwKICAgIC8vICAgICAgIHNoYXBlOiAoKSA9PiAoewogICAgLy8gICAgICAgICAuLi5kZWYuc2hhcGUoKSwKICAgIC8vICAgICAgICAgLi4uYXVnbWVudGF0aW9uLAogICAgLy8gICAgICAgfSksCiAgICAvLyAgICAgfSkgYXMgYW55OwogICAgLy8gICB9OwogICAgZXh0ZW5kKGF1Z21lbnRhdGlvbikgewogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHNoYXBlOiAoKSA9PiAoewogICAgICAgICAgLi4udGhpcy5fZGVmLnNoYXBlKCksCiAgICAgICAgICAuLi5hdWdtZW50YXRpb24KICAgICAgICB9KQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICogUHJpb3IgdG8gem9kQDEuMC4xMiB0aGVyZSB3YXMgYSBidWcgaW4gdGhlCiAgICAgKiBpbmZlcnJlZCB0eXBlIG9mIG1lcmdlZCBvYmplY3RzLiBQbGVhc2UKICAgICAqIHVwZ3JhZGUgaWYgeW91IGFyZSBleHBlcmllbmNpbmcgaXNzdWVzLgogICAgICovCiAgICBtZXJnZShtZXJnaW5nKSB7CiAgICAgIGNvbnN0IG1lcmdlZCA9IG5ldyBab2RPYmplY3QoewogICAgICAgIHVua25vd25LZXlzOiBtZXJnaW5nLl9kZWYudW5rbm93bktleXMsCiAgICAgICAgY2F0Y2hhbGw6IG1lcmdpbmcuX2RlZi5jYXRjaGFsbCwKICAgICAgICBzaGFwZTogKCkgPT4gKHsKICAgICAgICAgIC4uLnRoaXMuX2RlZi5zaGFwZSgpLAogICAgICAgICAgLi4ubWVyZ2luZy5fZGVmLnNoYXBlKCkKICAgICAgICB9KSwKICAgICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE9iamVjdAogICAgICB9KTsKICAgICAgcmV0dXJuIG1lcmdlZDsKICAgIH0KICAgIC8vIG1lcmdlPAogICAgLy8gICBJbmNvbWluZyBleHRlbmRzIEFueVpvZE9iamVjdCwKICAgIC8vICAgQXVnbWVudGF0aW9uIGV4dGVuZHMgSW5jb21pbmdbInNoYXBlIl0sCiAgICAvLyAgIE5ld091dHB1dCBleHRlbmRzIHsKICAgIC8vICAgICBbayBpbiBrZXlvZiBBdWdtZW50YXRpb24gfCBrZXlvZiBPdXRwdXRdOiBrIGV4dGVuZHMga2V5b2YgQXVnbWVudGF0aW9uCiAgICAvLyAgICAgICA/IEF1Z21lbnRhdGlvbltrXVsiX291dHB1dCJdCiAgICAvLyAgICAgICA6IGsgZXh0ZW5kcyBrZXlvZiBPdXRwdXQKICAgIC8vICAgICAgID8gT3V0cHV0W2tdCiAgICAvLyAgICAgICA6IG5ldmVyOwogICAgLy8gICB9LAogICAgLy8gICBOZXdJbnB1dCBleHRlbmRzIHsKICAgIC8vICAgICBbayBpbiBrZXlvZiBBdWdtZW50YXRpb24gfCBrZXlvZiBJbnB1dF06IGsgZXh0ZW5kcyBrZXlvZiBBdWdtZW50YXRpb24KICAgIC8vICAgICAgID8gQXVnbWVudGF0aW9uW2tdWyJfaW5wdXQiXQogICAgLy8gICAgICAgOiBrIGV4dGVuZHMga2V5b2YgSW5wdXQKICAgIC8vICAgICAgID8gSW5wdXRba10KICAgIC8vICAgICAgIDogbmV2ZXI7CiAgICAvLyAgIH0KICAgIC8vID4oCiAgICAvLyAgIG1lcmdpbmc6IEluY29taW5nCiAgICAvLyApOiBab2RPYmplY3Q8CiAgICAvLyAgIGV4dGVuZFNoYXBlPFQsIFJldHVyblR5cGU8SW5jb21pbmdbIl9kZWYiXVsic2hhcGUiXT4+LAogICAgLy8gICBJbmNvbWluZ1siX2RlZiJdWyJ1bmtub3duS2V5cyJdLAogICAgLy8gICBJbmNvbWluZ1siX2RlZiJdWyJjYXRjaGFsbCJdLAogICAgLy8gICBOZXdPdXRwdXQsCiAgICAvLyAgIE5ld0lucHV0CiAgICAvLyA+IHsKICAgIC8vICAgY29uc3QgbWVyZ2VkOiBhbnkgPSBuZXcgWm9kT2JqZWN0KHsKICAgIC8vICAgICB1bmtub3duS2V5czogbWVyZ2luZy5fZGVmLnVua25vd25LZXlzLAogICAgLy8gICAgIGNhdGNoYWxsOiBtZXJnaW5nLl9kZWYuY2F0Y2hhbGwsCiAgICAvLyAgICAgc2hhcGU6ICgpID0+CiAgICAvLyAgICAgICBvYmplY3RVdGlsLm1lcmdlU2hhcGVzKHRoaXMuX2RlZi5zaGFwZSgpLCBtZXJnaW5nLl9kZWYuc2hhcGUoKSksCiAgICAvLyAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPYmplY3QsCiAgICAvLyAgIH0pIGFzIGFueTsKICAgIC8vICAgcmV0dXJuIG1lcmdlZDsKICAgIC8vIH0KICAgIHNldEtleShrZXksIHNjaGVtYSkgewogICAgICByZXR1cm4gdGhpcy5hdWdtZW50KHsgW2tleV06IHNjaGVtYSB9KTsKICAgIH0KICAgIC8vIG1lcmdlPEluY29taW5nIGV4dGVuZHMgQW55Wm9kT2JqZWN0PigKICAgIC8vICAgbWVyZ2luZzogSW5jb21pbmcKICAgIC8vICk6IC8vWm9kT2JqZWN0PFQgJiBJbmNvbWluZ1siX3NoYXBlIl0sIFVua25vd25LZXlzLCBDYXRjaGFsbD4gPSAobWVyZ2luZykgPT4gewogICAgLy8gWm9kT2JqZWN0PAogICAgLy8gICBleHRlbmRTaGFwZTxULCBSZXR1cm5UeXBlPEluY29taW5nWyJfZGVmIl1bInNoYXBlIl0+PiwKICAgIC8vICAgSW5jb21pbmdbIl9kZWYiXVsidW5rbm93bktleXMiXSwKICAgIC8vICAgSW5jb21pbmdbIl9kZWYiXVsiY2F0Y2hhbGwiXQogICAgLy8gPiB7CiAgICAvLyAgIC8vIGNvbnN0IG1lcmdlZFNoYXBlID0gb2JqZWN0VXRpbC5tZXJnZVNoYXBlcygKICAgIC8vICAgLy8gICB0aGlzLl9kZWYuc2hhcGUoKSwKICAgIC8vICAgLy8gICBtZXJnaW5nLl9kZWYuc2hhcGUoKQogICAgLy8gICAvLyApOwogICAgLy8gICBjb25zdCBtZXJnZWQ6IGFueSA9IG5ldyBab2RPYmplY3QoewogICAgLy8gICAgIHVua25vd25LZXlzOiBtZXJnaW5nLl9kZWYudW5rbm93bktleXMsCiAgICAvLyAgICAgY2F0Y2hhbGw6IG1lcmdpbmcuX2RlZi5jYXRjaGFsbCwKICAgIC8vICAgICBzaGFwZTogKCkgPT4KICAgIC8vICAgICAgIG9iamVjdFV0aWwubWVyZ2VTaGFwZXModGhpcy5fZGVmLnNoYXBlKCksIG1lcmdpbmcuX2RlZi5zaGFwZSgpKSwKICAgIC8vICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE9iamVjdCwKICAgIC8vICAgfSkgYXMgYW55OwogICAgLy8gICByZXR1cm4gbWVyZ2VkOwogICAgLy8gfQogICAgY2F0Y2hhbGwoaW5kZXgpIHsKICAgICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICBjYXRjaGFsbDogaW5kZXgKICAgICAgfSk7CiAgICB9CiAgICBwaWNrKG1hc2spIHsKICAgICAgY29uc3Qgc2hhcGUgPSB7fTsKICAgICAgdXRpbC5vYmplY3RLZXlzKG1hc2spLmZvckVhY2goKGtleSkgPT4gewogICAgICAgIGlmIChtYXNrW2tleV0gJiYgdGhpcy5zaGFwZVtrZXldKSB7CiAgICAgICAgICBzaGFwZVtrZXldID0gdGhpcy5zaGFwZVtrZXldOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgc2hhcGU6ICgpID0+IHNoYXBlCiAgICAgIH0pOwogICAgfQogICAgb21pdChtYXNrKSB7CiAgICAgIGNvbnN0IHNoYXBlID0ge307CiAgICAgIHV0aWwub2JqZWN0S2V5cyh0aGlzLnNoYXBlKS5mb3JFYWNoKChrZXkpID0+IHsKICAgICAgICBpZiAoIW1hc2tba2V5XSkgewogICAgICAgICAgc2hhcGVba2V5XSA9IHRoaXMuc2hhcGVba2V5XTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHNoYXBlOiAoKSA9PiBzaGFwZQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICogQGRlcHJlY2F0ZWQKICAgICAqLwogICAgZGVlcFBhcnRpYWwoKSB7CiAgICAgIHJldHVybiBkZWVwUGFydGlhbGlmeSh0aGlzKTsKICAgIH0KICAgIHBhcnRpYWwobWFzaykgewogICAgICBjb25zdCBuZXdTaGFwZSA9IHt9OwogICAgICB1dGlsLm9iamVjdEtleXModGhpcy5zaGFwZSkuZm9yRWFjaCgoa2V5KSA9PiB7CiAgICAgICAgY29uc3QgZmllbGRTY2hlbWEgPSB0aGlzLnNoYXBlW2tleV07CiAgICAgICAgaWYgKG1hc2sgJiYgIW1hc2tba2V5XSkgewogICAgICAgICAgbmV3U2hhcGVba2V5XSA9IGZpZWxkU2NoZW1hOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBuZXdTaGFwZVtrZXldID0gZmllbGRTY2hlbWEub3B0aW9uYWwoKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHNoYXBlOiAoKSA9PiBuZXdTaGFwZQogICAgICB9KTsKICAgIH0KICAgIHJlcXVpcmVkKG1hc2spIHsKICAgICAgY29uc3QgbmV3U2hhcGUgPSB7fTsKICAgICAgdXRpbC5vYmplY3RLZXlzKHRoaXMuc2hhcGUpLmZvckVhY2goKGtleSkgPT4gewogICAgICAgIGlmIChtYXNrICYmICFtYXNrW2tleV0pIHsKICAgICAgICAgIG5ld1NoYXBlW2tleV0gPSB0aGlzLnNoYXBlW2tleV07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvbnN0IGZpZWxkU2NoZW1hID0gdGhpcy5zaGFwZVtrZXldOwogICAgICAgICAgbGV0IG5ld0ZpZWxkID0gZmllbGRTY2hlbWE7CiAgICAgICAgICB3aGlsZSAobmV3RmllbGQgaW5zdGFuY2VvZiBab2RPcHRpb25hbCkgewogICAgICAgICAgICBuZXdGaWVsZCA9IG5ld0ZpZWxkLl9kZWYuaW5uZXJUeXBlOwogICAgICAgICAgfQogICAgICAgICAgbmV3U2hhcGVba2V5XSA9IG5ld0ZpZWxkOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiBuZXcgWm9kT2JqZWN0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgc2hhcGU6ICgpID0+IG5ld1NoYXBlCiAgICAgIH0pOwogICAgfQogICAga2V5b2YoKSB7CiAgICAgIHJldHVybiBjcmVhdGVab2RFbnVtKHV0aWwub2JqZWN0S2V5cyh0aGlzLnNoYXBlKSk7CiAgICB9CiAgfQogIFpvZE9iamVjdC5jcmVhdGUgPSAoc2hhcGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICBzaGFwZTogKCkgPT4gc2hhcGUsCiAgICAgIHVua25vd25LZXlzOiAic3RyaXAiLAogICAgICBjYXRjaGFsbDogWm9kTmV2ZXIuY3JlYXRlKCksCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kT2JqZWN0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgWm9kT2JqZWN0LnN0cmljdENyZWF0ZSA9IChzaGFwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE9iamVjdCh7CiAgICAgIHNoYXBlOiAoKSA9PiBzaGFwZSwKICAgICAgdW5rbm93bktleXM6ICJzdHJpY3QiLAogICAgICBjYXRjaGFsbDogWm9kTmV2ZXIuY3JlYXRlKCksCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kT2JqZWN0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgWm9kT2JqZWN0LmxhenljcmVhdGUgPSAoc2hhcGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RPYmplY3QoewogICAgICBzaGFwZSwKICAgICAgdW5rbm93bktleXM6ICJzdHJpcCIsCiAgICAgIGNhdGNoYWxsOiBab2ROZXZlci5jcmVhdGUoKSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPYmplY3QsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RVbmlvbiBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5fZGVmLm9wdGlvbnM7CiAgICAgIGZ1bmN0aW9uIGhhbmRsZVJlc3VsdHMocmVzdWx0cykgewogICAgICAgIGZvciAoY29uc3QgcmVzdWx0IG9mIHJlc3VsdHMpIHsKICAgICAgICAgIGlmIChyZXN1bHQucmVzdWx0LnN0YXR1cyA9PT0gInZhbGlkIikgewogICAgICAgICAgICByZXR1cm4gcmVzdWx0LnJlc3VsdDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZm9yIChjb25zdCByZXN1bHQgb2YgcmVzdWx0cykgewogICAgICAgICAgaWYgKHJlc3VsdC5yZXN1bHQuc3RhdHVzID09PSAiZGlydHkiKSB7CiAgICAgICAgICAgIGN0eC5jb21tb24uaXNzdWVzLnB1c2goLi4ucmVzdWx0LmN0eC5jb21tb24uaXNzdWVzKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5yZXN1bHQ7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IHVuaW9uRXJyb3JzID0gcmVzdWx0cy5tYXAoKHJlc3VsdCkgPT4gbmV3IFpvZEVycm9yKHJlc3VsdC5jdHguY29tbW9uLmlzc3VlcykpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdW5pb24sCiAgICAgICAgICB1bmlvbkVycm9ycwogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKG9wdGlvbnMubWFwKGFzeW5jIChvcHRpb24pID0+IHsKICAgICAgICAgIGNvbnN0IGNoaWxkQ3R4ID0gewogICAgICAgICAgICAuLi5jdHgsCiAgICAgICAgICAgIGNvbW1vbjogewogICAgICAgICAgICAgIC4uLmN0eC5jb21tb24sCiAgICAgICAgICAgICAgaXNzdWVzOiBbXQogICAgICAgICAgICB9LAogICAgICAgICAgICBwYXJlbnQ6IG51bGwKICAgICAgICAgIH07CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICByZXN1bHQ6IGF3YWl0IG9wdGlvbi5fcGFyc2VBc3luYyh7CiAgICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgICAgICAgcGFyZW50OiBjaGlsZEN0eAogICAgICAgICAgICB9KSwKICAgICAgICAgICAgY3R4OiBjaGlsZEN0eAogICAgICAgICAgfTsKICAgICAgICB9KSkudGhlbihoYW5kbGVSZXN1bHRzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBsZXQgZGlydHkgPSB2b2lkIDA7CiAgICAgICAgY29uc3QgaXNzdWVzID0gW107CiAgICAgICAgZm9yIChjb25zdCBvcHRpb24gb2Ygb3B0aW9ucykgewogICAgICAgICAgY29uc3QgY2hpbGRDdHggPSB7CiAgICAgICAgICAgIC4uLmN0eCwKICAgICAgICAgICAgY29tbW9uOiB7CiAgICAgICAgICAgICAgLi4uY3R4LmNvbW1vbiwKICAgICAgICAgICAgICBpc3N1ZXM6IFtdCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHBhcmVudDogbnVsbAogICAgICAgICAgfTsKICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG9wdGlvbi5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGNoaWxkQ3R4CiAgICAgICAgICB9KTsKICAgICAgICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSAidmFsaWQiKSB7CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICB9IGVsc2UgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICJkaXJ0eSIgJiYgIWRpcnR5KSB7CiAgICAgICAgICAgIGRpcnR5ID0geyByZXN1bHQsIGN0eDogY2hpbGRDdHggfTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChjaGlsZEN0eC5jb21tb24uaXNzdWVzLmxlbmd0aCkgewogICAgICAgICAgICBpc3N1ZXMucHVzaChjaGlsZEN0eC5jb21tb24uaXNzdWVzKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGRpcnR5KSB7CiAgICAgICAgICBjdHguY29tbW9uLmlzc3Vlcy5wdXNoKC4uLmRpcnR5LmN0eC5jb21tb24uaXNzdWVzKTsKICAgICAgICAgIHJldHVybiBkaXJ0eS5yZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHVuaW9uRXJyb3JzID0gaXNzdWVzLm1hcCgoaXNzdWVzMikgPT4gbmV3IFpvZEVycm9yKGlzc3VlczIpKTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3VuaW9uLAogICAgICAgICAgdW5pb25FcnJvcnMKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgfQogICAgZ2V0IG9wdGlvbnMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYub3B0aW9uczsKICAgIH0KICB9CiAgWm9kVW5pb24uY3JlYXRlID0gKHR5cGVzLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kVW5pb24oewogICAgICBvcHRpb25zOiB0eXBlcywKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RVbmlvbiwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNvbnN0IGdldERpc2NyaW1pbmF0b3IgPSAodHlwZSkgPT4gewogICAgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RMYXp5KSB7CiAgICAgIHJldHVybiBnZXREaXNjcmltaW5hdG9yKHR5cGUuc2NoZW1hKTsKICAgIH0gZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZEVmZmVjdHMpIHsKICAgICAgcmV0dXJuIGdldERpc2NyaW1pbmF0b3IodHlwZS5pbm5lclR5cGUoKSk7CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RMaXRlcmFsKSB7CiAgICAgIHJldHVybiBbdHlwZS52YWx1ZV07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RFbnVtKSB7CiAgICAgIHJldHVybiB0eXBlLm9wdGlvbnM7CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2ROYXRpdmVFbnVtKSB7CiAgICAgIHJldHVybiB1dGlsLm9iamVjdFZhbHVlcyh0eXBlLmVudW0pOwogICAgfSBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kRGVmYXVsdCkgewogICAgICByZXR1cm4gZ2V0RGlzY3JpbWluYXRvcih0eXBlLl9kZWYuaW5uZXJUeXBlKTsKICAgIH0gZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZFVuZGVmaW5lZCkgewogICAgICByZXR1cm4gW3ZvaWQgMF07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2ROdWxsKSB7CiAgICAgIHJldHVybiBbbnVsbF07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2RPcHRpb25hbCkgewogICAgICByZXR1cm4gW3ZvaWQgMCwgLi4uZ2V0RGlzY3JpbWluYXRvcih0eXBlLnVud3JhcCgpKV07CiAgICB9IGVsc2UgaWYgKHR5cGUgaW5zdGFuY2VvZiBab2ROdWxsYWJsZSkgewogICAgICByZXR1cm4gW251bGwsIC4uLmdldERpc2NyaW1pbmF0b3IodHlwZS51bndyYXAoKSldOwogICAgfSBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kQnJhbmRlZCkgewogICAgICByZXR1cm4gZ2V0RGlzY3JpbWluYXRvcih0eXBlLnVud3JhcCgpKTsKICAgIH0gZWxzZSBpZiAodHlwZSBpbnN0YW5jZW9mIFpvZFJlYWRvbmx5KSB7CiAgICAgIHJldHVybiBnZXREaXNjcmltaW5hdG9yKHR5cGUudW53cmFwKCkpOwogICAgfSBlbHNlIGlmICh0eXBlIGluc3RhbmNlb2YgWm9kQ2F0Y2gpIHsKICAgICAgcmV0dXJuIGdldERpc2NyaW1pbmF0b3IodHlwZS5fZGVmLmlubmVyVHlwZSk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gW107CiAgICB9CiAgfTsKICBjbGFzcyBab2REaXNjcmltaW5hdGVkVW5pb24gZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm9iamVjdCkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm9iamVjdCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IGRpc2NyaW1pbmF0b3IgPSB0aGlzLmRpc2NyaW1pbmF0b3I7CiAgICAgIGNvbnN0IGRpc2NyaW1pbmF0b3JWYWx1ZSA9IGN0eC5kYXRhW2Rpc2NyaW1pbmF0b3JdOwogICAgICBjb25zdCBvcHRpb24gPSB0aGlzLm9wdGlvbnNNYXAuZ2V0KGRpc2NyaW1pbmF0b3JWYWx1ZSk7CiAgICAgIGlmICghb3B0aW9uKSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF91bmlvbl9kaXNjcmltaW5hdG9yLAogICAgICAgICAgb3B0aW9uczogQXJyYXkuZnJvbSh0aGlzLm9wdGlvbnNNYXAua2V5cygpKSwKICAgICAgICAgIHBhdGg6IFtkaXNjcmltaW5hdG9yXQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIG9wdGlvbi5fcGFyc2VBc3luYyh7CiAgICAgICAgICBkYXRhOiBjdHguZGF0YSwKICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gb3B0aW9uLl9wYXJzZVN5bmMoewogICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIGdldCBkaXNjcmltaW5hdG9yKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmRpc2NyaW1pbmF0b3I7CiAgICB9CiAgICBnZXQgb3B0aW9ucygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5vcHRpb25zOwogICAgfQogICAgZ2V0IG9wdGlvbnNNYXAoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYub3B0aW9uc01hcDsKICAgIH0KICAgIC8qKgogICAgICogVGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBkaXNjcmltaW5hdGVkIHVuaW9uIHNjaGVtYS4gSXRzIGJlaGF2aW91ciBpcyB2ZXJ5IHNpbWlsYXIgdG8gdGhhdCBvZiB0aGUgbm9ybWFsIHoudW5pb24oKSBjb25zdHJ1Y3Rvci4KICAgICAqIEhvd2V2ZXIsIGl0IG9ubHkgYWxsb3dzIGEgdW5pb24gb2Ygb2JqZWN0cywgYWxsIG9mIHdoaWNoIG5lZWQgdG8gc2hhcmUgYSBkaXNjcmltaW5hdG9yIHByb3BlcnR5LiBUaGlzIHByb3BlcnR5IG11c3QKICAgICAqIGhhdmUgYSBkaWZmZXJlbnQgdmFsdWUgZm9yIGVhY2ggb2JqZWN0IGluIHRoZSB1bmlvbi4KICAgICAqIEBwYXJhbSBkaXNjcmltaW5hdG9yIHRoZSBuYW1lIG9mIHRoZSBkaXNjcmltaW5hdG9yIHByb3BlcnR5CiAgICAgKiBAcGFyYW0gdHlwZXMgYW4gYXJyYXkgb2Ygb2JqZWN0IHNjaGVtYXMKICAgICAqIEBwYXJhbSBwYXJhbXMKICAgICAqLwogICAgc3RhdGljIGNyZWF0ZShkaXNjcmltaW5hdG9yLCBvcHRpb25zLCBwYXJhbXMpIHsKICAgICAgY29uc3Qgb3B0aW9uc01hcCA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgIGZvciAoY29uc3QgdHlwZSBvZiBvcHRpb25zKSB7CiAgICAgICAgY29uc3QgZGlzY3JpbWluYXRvclZhbHVlcyA9IGdldERpc2NyaW1pbmF0b3IodHlwZS5zaGFwZVtkaXNjcmltaW5hdG9yXSk7CiAgICAgICAgaWYgKCFkaXNjcmltaW5hdG9yVmFsdWVzLmxlbmd0aCkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBBIGRpc2NyaW1pbmF0b3IgdmFsdWUgZm9yIGtleSBcYCR7ZGlzY3JpbWluYXRvcn1cYCBjb3VsZCBub3QgYmUgZXh0cmFjdGVkIGZyb20gYWxsIHNjaGVtYSBvcHRpb25zYCk7CiAgICAgICAgfQogICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgZGlzY3JpbWluYXRvclZhbHVlcykgewogICAgICAgICAgaWYgKG9wdGlvbnNNYXAuaGFzKHZhbHVlKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERpc2NyaW1pbmF0b3IgcHJvcGVydHkgJHtTdHJpbmcoZGlzY3JpbWluYXRvcil9IGhhcyBkdXBsaWNhdGUgdmFsdWUgJHtTdHJpbmcodmFsdWUpfWApOwogICAgICAgICAgfQogICAgICAgICAgb3B0aW9uc01hcC5zZXQodmFsdWUsIHR5cGUpOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbmV3IFpvZERpc2NyaW1pbmF0ZWRVbmlvbih7CiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2REaXNjcmltaW5hdGVkVW5pb24sCiAgICAgICAgZGlzY3JpbWluYXRvciwKICAgICAgICBvcHRpb25zLAogICAgICAgIG9wdGlvbnNNYXAsCiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICAgIH0pOwogICAgfQogIH0KICBmdW5jdGlvbiBtZXJnZVZhbHVlcyhhMiwgYikgewogICAgY29uc3QgYVR5cGUgPSBnZXRQYXJzZWRUeXBlKGEyKTsKICAgIGNvbnN0IGJUeXBlID0gZ2V0UGFyc2VkVHlwZShiKTsKICAgIGlmIChhMiA9PT0gYikgewogICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZGF0YTogYTIgfTsKICAgIH0gZWxzZSBpZiAoYVR5cGUgPT09IFpvZFBhcnNlZFR5cGUub2JqZWN0ICYmIGJUeXBlID09PSBab2RQYXJzZWRUeXBlLm9iamVjdCkgewogICAgICBjb25zdCBiS2V5cyA9IHV0aWwub2JqZWN0S2V5cyhiKTsKICAgICAgY29uc3Qgc2hhcmVkS2V5cyA9IHV0aWwub2JqZWN0S2V5cyhhMikuZmlsdGVyKChrZXkpID0+IGJLZXlzLmluZGV4T2Yoa2V5KSAhPT0gLTEpOwogICAgICBjb25zdCBuZXdPYmogPSB7IC4uLmEyLCAuLi5iIH07CiAgICAgIGZvciAoY29uc3Qga2V5IG9mIHNoYXJlZEtleXMpIHsKICAgICAgICBjb25zdCBzaGFyZWRWYWx1ZSA9IG1lcmdlVmFsdWVzKGEyW2tleV0sIGJba2V5XSk7CiAgICAgICAgaWYgKCFzaGFyZWRWYWx1ZS52YWxpZCkgewogICAgICAgICAgcmV0dXJuIHsgdmFsaWQ6IGZhbHNlIH07CiAgICAgICAgfQogICAgICAgIG5ld09ialtrZXldID0gc2hhcmVkVmFsdWUuZGF0YTsKICAgICAgfQogICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZGF0YTogbmV3T2JqIH07CiAgICB9IGVsc2UgaWYgKGFUeXBlID09PSBab2RQYXJzZWRUeXBlLmFycmF5ICYmIGJUeXBlID09PSBab2RQYXJzZWRUeXBlLmFycmF5KSB7CiAgICAgIGlmIChhMi5sZW5ndGggIT09IGIubGVuZ3RoKSB7CiAgICAgICAgcmV0dXJuIHsgdmFsaWQ6IGZhbHNlIH07CiAgICAgIH0KICAgICAgY29uc3QgbmV3QXJyYXkgPSBbXTsKICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGEyLmxlbmd0aDsgaW5kZXgrKykgewogICAgICAgIGNvbnN0IGl0ZW1BID0gYTJbaW5kZXhdOwogICAgICAgIGNvbnN0IGl0ZW1CID0gYltpbmRleF07CiAgICAgICAgY29uc3Qgc2hhcmVkVmFsdWUgPSBtZXJnZVZhbHVlcyhpdGVtQSwgaXRlbUIpOwogICAgICAgIGlmICghc2hhcmVkVmFsdWUudmFsaWQpIHsKICAgICAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSB9OwogICAgICAgIH0KICAgICAgICBuZXdBcnJheS5wdXNoKHNoYXJlZFZhbHVlLmRhdGEpOwogICAgICB9CiAgICAgIHJldHVybiB7IHZhbGlkOiB0cnVlLCBkYXRhOiBuZXdBcnJheSB9OwogICAgfSBlbHNlIGlmIChhVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS5kYXRlICYmIGJUeXBlID09PSBab2RQYXJzZWRUeXBlLmRhdGUgJiYgK2EyID09PSArYikgewogICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZGF0YTogYTIgfTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSB9OwogICAgfQogIH0KICBjbGFzcyBab2RJbnRlcnNlY3Rpb24gZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IHN0YXR1cywgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBoYW5kbGVQYXJzZWQgPSAocGFyc2VkTGVmdCwgcGFyc2VkUmlnaHQpID0+IHsKICAgICAgICBpZiAoaXNBYm9ydGVkKHBhcnNlZExlZnQpIHx8IGlzQWJvcnRlZChwYXJzZWRSaWdodCkpIHsKICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgIH0KICAgICAgICBjb25zdCBtZXJnZWQgPSBtZXJnZVZhbHVlcyhwYXJzZWRMZWZ0LnZhbHVlLCBwYXJzZWRSaWdodC52YWx1ZSk7CiAgICAgICAgaWYgKCFtZXJnZWQudmFsaWQpIHsKICAgICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9pbnRlcnNlY3Rpb25fdHlwZXMKICAgICAgICAgIH0pOwogICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgfQogICAgICAgIGlmIChpc0RpcnR5KHBhcnNlZExlZnQpIHx8IGlzRGlydHkocGFyc2VkUmlnaHQpKSB7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBtZXJnZWQuZGF0YSB9OwogICAgICB9OwogICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYykgewogICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbCiAgICAgICAgICB0aGlzLl9kZWYubGVmdC5fcGFyc2VBc3luYyh7CiAgICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLAogICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICAgIH0pLAogICAgICAgICAgdGhpcy5fZGVmLnJpZ2h0Ll9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSkKICAgICAgICBdKS50aGVuKChbbGVmdCwgcmlnaHRdKSA9PiBoYW5kbGVQYXJzZWQobGVmdCwgcmlnaHQpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gaGFuZGxlUGFyc2VkKHRoaXMuX2RlZi5sZWZ0Ll9wYXJzZVN5bmMoewogICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgfSksIHRoaXMuX2RlZi5yaWdodC5fcGFyc2VTeW5jKHsKICAgICAgICAgIGRhdGE6IGN0eC5kYXRhLAogICAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgIH0pKTsKICAgICAgfQogICAgfQogIH0KICBab2RJbnRlcnNlY3Rpb24uY3JlYXRlID0gKGxlZnQsIHJpZ2h0LCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kSW50ZXJzZWN0aW9uKHsKICAgICAgbGVmdCwKICAgICAgcmlnaHQsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kSW50ZXJzZWN0aW9uLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kVHVwbGUgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IHN0YXR1cywgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuYXJyYXkpIHsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5hcnJheSwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmIChjdHguZGF0YS5sZW5ndGggPCB0aGlzLl9kZWYuaXRlbXMubGVuZ3RoKSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX3NtYWxsLAogICAgICAgICAgbWluaW11bTogdGhpcy5fZGVmLml0ZW1zLmxlbmd0aCwKICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgIHR5cGU6ICJhcnJheSIKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBjb25zdCByZXN0ID0gdGhpcy5fZGVmLnJlc3Q7CiAgICAgIGlmICghcmVzdCAmJiBjdHguZGF0YS5sZW5ndGggPiB0aGlzLl9kZWYuaXRlbXMubGVuZ3RoKSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUudG9vX2JpZywKICAgICAgICAgIG1heGltdW06IHRoaXMuX2RlZi5pdGVtcy5sZW5ndGgsCiAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgICBleGFjdDogZmFsc2UsCiAgICAgICAgICB0eXBlOiAiYXJyYXkiCiAgICAgICAgfSk7CiAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgIH0KICAgICAgY29uc3QgaXRlbXMgPSBbLi4uY3R4LmRhdGFdLm1hcCgoaXRlbSwgaXRlbUluZGV4KSA9PiB7CiAgICAgICAgY29uc3Qgc2NoZW1hID0gdGhpcy5fZGVmLml0ZW1zW2l0ZW1JbmRleF0gfHwgdGhpcy5fZGVmLnJlc3Q7CiAgICAgICAgaWYgKCFzY2hlbWEpCiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICByZXR1cm4gc2NoZW1hLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwgaXRlbSwgY3R4LnBhdGgsIGl0ZW1JbmRleCkpOwogICAgICB9KS5maWx0ZXIoKHgpID0+ICEheCk7CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKGl0ZW1zKS50aGVuKChyZXN1bHRzKSA9PiB7CiAgICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VBcnJheShzdGF0dXMsIHJlc3VsdHMpOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBQYXJzZVN0YXR1cy5tZXJnZUFycmF5KHN0YXR1cywgaXRlbXMpOwogICAgICB9CiAgICB9CiAgICBnZXQgaXRlbXMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYuaXRlbXM7CiAgICB9CiAgICByZXN0KHJlc3QpIHsKICAgICAgcmV0dXJuIG5ldyBab2RUdXBsZSh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIHJlc3QKICAgICAgfSk7CiAgICB9CiAgfQogIFpvZFR1cGxlLmNyZWF0ZSA9IChzY2hlbWFzLCBwYXJhbXMpID0+IHsKICAgIGlmICghQXJyYXkuaXNBcnJheShzY2hlbWFzKSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIllvdSBtdXN0IHBhc3MgYW4gYXJyYXkgb2Ygc2NoZW1hcyB0byB6LnR1cGxlKFsgLi4uIF0pIik7CiAgICB9CiAgICByZXR1cm4gbmV3IFpvZFR1cGxlKHsKICAgICAgaXRlbXM6IHNjaGVtYXMsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kVHVwbGUsCiAgICAgIHJlc3Q6IG51bGwsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RSZWNvcmQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGdldCBrZXlTY2hlbWEoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYua2V5VHlwZTsKICAgIH0KICAgIGdldCB2YWx1ZVNjaGVtYSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZVR5cGU7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm9iamVjdCkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm9iamVjdCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IHBhaXJzID0gW107CiAgICAgIGNvbnN0IGtleVR5cGUgPSB0aGlzLl9kZWYua2V5VHlwZTsKICAgICAgY29uc3QgdmFsdWVUeXBlID0gdGhpcy5fZGVmLnZhbHVlVHlwZTsKICAgICAgZm9yIChjb25zdCBrZXkgaW4gY3R4LmRhdGEpIHsKICAgICAgICBwYWlycy5wdXNoKHsKICAgICAgICAgIGtleToga2V5VHlwZS5fcGFyc2UobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGtleSwgY3R4LnBhdGgsIGtleSkpLAogICAgICAgICAgdmFsdWU6IHZhbHVlVHlwZS5fcGFyc2UobmV3IFBhcnNlSW5wdXRMYXp5UGF0aChjdHgsIGN0eC5kYXRhW2tleV0sIGN0eC5wYXRoLCBrZXkpKSwKICAgICAgICAgIGFsd2F5c1NldDoga2V5IGluIGN0eC5kYXRhCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VPYmplY3RBc3luYyhzdGF0dXMsIHBhaXJzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gUGFyc2VTdGF0dXMubWVyZ2VPYmplY3RTeW5jKHN0YXR1cywgcGFpcnMpOwogICAgICB9CiAgICB9CiAgICBnZXQgZWxlbWVudCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZVR5cGU7CiAgICB9CiAgICBzdGF0aWMgY3JlYXRlKGZpcnN0LCBzZWNvbmQsIHRoaXJkKSB7CiAgICAgIGlmIChzZWNvbmQgaW5zdGFuY2VvZiBab2RUeXBlKSB7CiAgICAgICAgcmV0dXJuIG5ldyBab2RSZWNvcmQoewogICAgICAgICAga2V5VHlwZTogZmlyc3QsCiAgICAgICAgICB2YWx1ZVR5cGU6IHNlY29uZCwKICAgICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kUmVjb3JkLAogICAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyh0aGlyZCkKICAgICAgICB9KTsKICAgICAgfQogICAgICByZXR1cm4gbmV3IFpvZFJlY29yZCh7CiAgICAgICAga2V5VHlwZTogWm9kU3RyaW5nLmNyZWF0ZSgpLAogICAgICAgIHZhbHVlVHlwZTogZmlyc3QsCiAgICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RSZWNvcmQsCiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhzZWNvbmQpCiAgICAgIH0pOwogICAgfQogIH0KICBjbGFzcyBab2RNYXAgZXh0ZW5kcyBab2RUeXBlIHsKICAgIGdldCBrZXlTY2hlbWEoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYua2V5VHlwZTsKICAgIH0KICAgIGdldCB2YWx1ZVNjaGVtYSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZVR5cGU7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5wYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm1hcCkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLm1hcCwKICAgICAgICAgIHJlY2VpdmVkOiBjdHgucGFyc2VkVHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGNvbnN0IGtleVR5cGUgPSB0aGlzLl9kZWYua2V5VHlwZTsKICAgICAgY29uc3QgdmFsdWVUeXBlID0gdGhpcy5fZGVmLnZhbHVlVHlwZTsKICAgICAgY29uc3QgcGFpcnMgPSBbLi4uY3R4LmRhdGEuZW50cmllcygpXS5tYXAoKFtrZXksIHZhbHVlXSwgaW5kZXgpID0+IHsKICAgICAgICByZXR1cm4gewogICAgICAgICAga2V5OiBrZXlUeXBlLl9wYXJzZShuZXcgUGFyc2VJbnB1dExhenlQYXRoKGN0eCwga2V5LCBjdHgucGF0aCwgW2luZGV4LCAia2V5Il0pKSwKICAgICAgICAgIHZhbHVlOiB2YWx1ZVR5cGUuX3BhcnNlKG5ldyBQYXJzZUlucHV0TGF6eVBhdGgoY3R4LCB2YWx1ZSwgY3R4LnBhdGgsIFtpbmRleCwgInZhbHVlIl0pKQogICAgICAgIH07CiAgICAgIH0pOwogICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYykgewogICAgICAgIGNvbnN0IGZpbmFsTWFwID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihhc3luYyAoKSA9PiB7CiAgICAgICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHsKICAgICAgICAgICAgY29uc3Qga2V5ID0gYXdhaXQgcGFpci5rZXk7CiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgcGFpci52YWx1ZTsKICAgICAgICAgICAgaWYgKGtleS5zdGF0dXMgPT09ICJhYm9ydGVkIiB8fCB2YWx1ZS5zdGF0dXMgPT09ICJhYm9ydGVkIikgewogICAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChrZXkuc3RhdHVzID09PSAiZGlydHkiIHx8IHZhbHVlLnN0YXR1cyA9PT0gImRpcnR5IikgewogICAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZpbmFsTWFwLnNldChrZXkudmFsdWUsIHZhbHVlLnZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogZmluYWxNYXAgfTsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBmaW5hbE1hcCA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgICAgICAgZm9yIChjb25zdCBwYWlyIG9mIHBhaXJzKSB7CiAgICAgICAgICBjb25zdCBrZXkgPSBwYWlyLmtleTsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gcGFpci52YWx1ZTsKICAgICAgICAgIGlmIChrZXkuc3RhdHVzID09PSAiYWJvcnRlZCIgfHwgdmFsdWUuc3RhdHVzID09PSAiYWJvcnRlZCIpIHsKICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoa2V5LnN0YXR1cyA9PT0gImRpcnR5IiB8fCB2YWx1ZS5zdGF0dXMgPT09ICJkaXJ0eSIpIHsKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgICBmaW5hbE1hcC5zZXQoa2V5LnZhbHVlLCB2YWx1ZS52YWx1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB7IHN0YXR1czogc3RhdHVzLnZhbHVlLCB2YWx1ZTogZmluYWxNYXAgfTsKICAgICAgfQogICAgfQogIH0KICBab2RNYXAuY3JlYXRlID0gKGtleVR5cGUsIHZhbHVlVHlwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE1hcCh7CiAgICAgIHZhbHVlVHlwZSwKICAgICAga2V5VHlwZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RNYXAsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RTZXQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IHN0YXR1cywgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUuc2V0KSB7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF90eXBlLAogICAgICAgICAgZXhwZWN0ZWQ6IFpvZFBhcnNlZFR5cGUuc2V0LAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgY29uc3QgZGVmID0gdGhpcy5fZGVmOwogICAgICBpZiAoZGVmLm1pblNpemUgIT09IG51bGwpIHsKICAgICAgICBpZiAoY3R4LmRhdGEuc2l6ZSA8IGRlZi5taW5TaXplLnZhbHVlKSB7CiAgICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLnRvb19zbWFsbCwKICAgICAgICAgICAgbWluaW11bTogZGVmLm1pblNpemUudmFsdWUsCiAgICAgICAgICAgIHR5cGU6ICJzZXQiLAogICAgICAgICAgICBpbmNsdXNpdmU6IHRydWUsCiAgICAgICAgICAgIGV4YWN0OiBmYWxzZSwKICAgICAgICAgICAgbWVzc2FnZTogZGVmLm1pblNpemUubWVzc2FnZQogICAgICAgICAgfSk7CiAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGRlZi5tYXhTaXplICE9PSBudWxsKSB7CiAgICAgICAgaWYgKGN0eC5kYXRhLnNpemUgPiBkZWYubWF4U2l6ZS52YWx1ZSkgewogICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS50b29fYmlnLAogICAgICAgICAgICBtYXhpbXVtOiBkZWYubWF4U2l6ZS52YWx1ZSwKICAgICAgICAgICAgdHlwZTogInNldCIsCiAgICAgICAgICAgIGluY2x1c2l2ZTogdHJ1ZSwKICAgICAgICAgICAgZXhhY3Q6IGZhbHNlLAogICAgICAgICAgICBtZXNzYWdlOiBkZWYubWF4U2l6ZS5tZXNzYWdlCiAgICAgICAgICB9KTsKICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCB2YWx1ZVR5cGUgPSB0aGlzLl9kZWYudmFsdWVUeXBlOwogICAgICBmdW5jdGlvbiBmaW5hbGl6ZVNldChlbGVtZW50czIpIHsKICAgICAgICBjb25zdCBwYXJzZWRTZXQgPSAvKiBAX19QVVJFX18gKi8gbmV3IFNldCgpOwogICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbGVtZW50czIpIHsKICAgICAgICAgIGlmIChlbGVtZW50LnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgICAgIGlmIChlbGVtZW50LnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICBwYXJzZWRTZXQuYWRkKGVsZW1lbnQudmFsdWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IHBhcnNlZFNldCB9OwogICAgICB9CiAgICAgIGNvbnN0IGVsZW1lbnRzID0gWy4uLmN0eC5kYXRhLnZhbHVlcygpXS5tYXAoKGl0ZW0sIGkyKSA9PiB2YWx1ZVR5cGUuX3BhcnNlKG5ldyBQYXJzZUlucHV0TGF6eVBhdGgoY3R4LCBpdGVtLCBjdHgucGF0aCwgaTIpKSk7CiAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKGVsZW1lbnRzKS50aGVuKChlbGVtZW50czIpID0+IGZpbmFsaXplU2V0KGVsZW1lbnRzMikpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBmaW5hbGl6ZVNldChlbGVtZW50cyk7CiAgICAgIH0KICAgIH0KICAgIG1pbihtaW5TaXplLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kU2V0KHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgbWluU2l6ZTogeyB2YWx1ZTogbWluU2l6ZSwgbWVzc2FnZTogZXJyb3JVdGlsLnRvU3RyaW5nKG1lc3NhZ2UpIH0KICAgICAgfSk7CiAgICB9CiAgICBtYXgobWF4U2l6ZSwgbWVzc2FnZSkgewogICAgICByZXR1cm4gbmV3IFpvZFNldCh7CiAgICAgICAgLi4udGhpcy5fZGVmLAogICAgICAgIG1heFNpemU6IHsgdmFsdWU6IG1heFNpemUsIG1lc3NhZ2U6IGVycm9yVXRpbC50b1N0cmluZyhtZXNzYWdlKSB9CiAgICAgIH0pOwogICAgfQogICAgc2l6ZShzaXplLCBtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLm1pbihzaXplLCBtZXNzYWdlKS5tYXgoc2l6ZSwgbWVzc2FnZSk7CiAgICB9CiAgICBub25lbXB0eShtZXNzYWdlKSB7CiAgICAgIHJldHVybiB0aGlzLm1pbigxLCBtZXNzYWdlKTsKICAgIH0KICB9CiAgWm9kU2V0LmNyZWF0ZSA9ICh2YWx1ZVR5cGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RTZXQoewogICAgICB2YWx1ZVR5cGUsCiAgICAgIG1pblNpemU6IG51bGwsCiAgICAgIG1heFNpemU6IG51bGwsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kU2V0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kRnVuY3Rpb24gZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICB0aGlzLnZhbGlkYXRlID0gdGhpcy5pbXBsZW1lbnQ7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBjdHggfSA9IHRoaXMuX3Byb2Nlc3NJbnB1dFBhcmFtcyhpbnB1dCk7CiAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5mdW5jdGlvbikgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLmZ1bmN0aW9uLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgZnVuY3Rpb24gbWFrZUFyZ3NJc3N1ZShhcmdzLCBlcnJvcikgewogICAgICAgIHJldHVybiBtYWtlSXNzdWUoewogICAgICAgICAgZGF0YTogYXJncywKICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgZXJyb3JNYXBzOiBbCiAgICAgICAgICAgIGN0eC5jb21tb24uY29udGV4dHVhbEVycm9yTWFwLAogICAgICAgICAgICBjdHguc2NoZW1hRXJyb3JNYXAsCiAgICAgICAgICAgIGdldEVycm9yTWFwKCksCiAgICAgICAgICAgIGVycm9yTWFwCiAgICAgICAgICBdLmZpbHRlcigoeCkgPT4gISF4KSwKICAgICAgICAgIGlzc3VlRGF0YTogewogICAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9hcmd1bWVudHMsCiAgICAgICAgICAgIGFyZ3VtZW50c0Vycm9yOiBlcnJvcgogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CiAgICAgIGZ1bmN0aW9uIG1ha2VSZXR1cm5zSXNzdWUocmV0dXJucywgZXJyb3IpIHsKICAgICAgICByZXR1cm4gbWFrZUlzc3VlKHsKICAgICAgICAgIGRhdGE6IHJldHVybnMsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIGVycm9yTWFwczogWwogICAgICAgICAgICBjdHguY29tbW9uLmNvbnRleHR1YWxFcnJvck1hcCwKICAgICAgICAgICAgY3R4LnNjaGVtYUVycm9yTWFwLAogICAgICAgICAgICBnZXRFcnJvck1hcCgpLAogICAgICAgICAgICBlcnJvck1hcAogICAgICAgICAgXS5maWx0ZXIoKHgpID0+ICEheCksCiAgICAgICAgICBpc3N1ZURhdGE6IHsKICAgICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfcmV0dXJuX3R5cGUsCiAgICAgICAgICAgIHJldHVyblR5cGVFcnJvcjogZXJyb3IKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQogICAgICBjb25zdCBwYXJhbXMgPSB7IGVycm9yTWFwOiBjdHguY29tbW9uLmNvbnRleHR1YWxFcnJvck1hcCB9OwogICAgICBjb25zdCBmbiA9IGN0eC5kYXRhOwogICAgICBpZiAodGhpcy5fZGVmLnJldHVybnMgaW5zdGFuY2VvZiBab2RQcm9taXNlKSB7CiAgICAgICAgY29uc3QgbWUgPSB0aGlzOwogICAgICAgIHJldHVybiBPSyhhc3luYyBmdW5jdGlvbiguLi5hcmdzKSB7CiAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBab2RFcnJvcihbXSk7CiAgICAgICAgICBjb25zdCBwYXJzZWRBcmdzID0gYXdhaXQgbWUuX2RlZi5hcmdzLnBhcnNlQXN5bmMoYXJncywgcGFyYW1zKS5jYXRjaCgoZTIpID0+IHsKICAgICAgICAgICAgZXJyb3IuYWRkSXNzdWUobWFrZUFyZ3NJc3N1ZShhcmdzLCBlMikpOwogICAgICAgICAgICB0aHJvdyBlcnJvcjsKICAgICAgICAgIH0pOwogICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgUmVmbGVjdC5hcHBseShmbiwgdGhpcywgcGFyc2VkQXJncyk7CiAgICAgICAgICBjb25zdCBwYXJzZWRSZXR1cm5zID0gYXdhaXQgbWUuX2RlZi5yZXR1cm5zLl9kZWYudHlwZS5wYXJzZUFzeW5jKHJlc3VsdCwgcGFyYW1zKS5jYXRjaCgoZTIpID0+IHsKICAgICAgICAgICAgZXJyb3IuYWRkSXNzdWUobWFrZVJldHVybnNJc3N1ZShyZXN1bHQsIGUyKSk7CiAgICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgICAgfSk7CiAgICAgICAgICByZXR1cm4gcGFyc2VkUmV0dXJuczsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBtZSA9IHRoaXM7CiAgICAgICAgcmV0dXJuIE9LKGZ1bmN0aW9uKC4uLmFyZ3MpIHsKICAgICAgICAgIGNvbnN0IHBhcnNlZEFyZ3MgPSBtZS5fZGVmLmFyZ3Muc2FmZVBhcnNlKGFyZ3MsIHBhcmFtcyk7CiAgICAgICAgICBpZiAoIXBhcnNlZEFyZ3Muc3VjY2VzcykgewogICAgICAgICAgICB0aHJvdyBuZXcgWm9kRXJyb3IoW21ha2VBcmdzSXNzdWUoYXJncywgcGFyc2VkQXJncy5lcnJvcildKTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IFJlZmxlY3QuYXBwbHkoZm4sIHRoaXMsIHBhcnNlZEFyZ3MuZGF0YSk7CiAgICAgICAgICBjb25zdCBwYXJzZWRSZXR1cm5zID0gbWUuX2RlZi5yZXR1cm5zLnNhZmVQYXJzZShyZXN1bHQsIHBhcmFtcyk7CiAgICAgICAgICBpZiAoIXBhcnNlZFJldHVybnMuc3VjY2VzcykgewogICAgICAgICAgICB0aHJvdyBuZXcgWm9kRXJyb3IoW21ha2VSZXR1cm5zSXNzdWUocmVzdWx0LCBwYXJzZWRSZXR1cm5zLmVycm9yKV0pOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHBhcnNlZFJldHVybnMuZGF0YTsKICAgICAgICB9KTsKICAgICAgfQogICAgfQogICAgcGFyYW1ldGVycygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5hcmdzOwogICAgfQogICAgcmV0dXJuVHlwZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5yZXR1cm5zOwogICAgfQogICAgYXJncyguLi5pdGVtcykgewogICAgICByZXR1cm4gbmV3IFpvZEZ1bmN0aW9uKHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgYXJnczogWm9kVHVwbGUuY3JlYXRlKGl0ZW1zKS5yZXN0KFpvZFVua25vd24uY3JlYXRlKCkpCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJucyhyZXR1cm5UeXBlKSB7CiAgICAgIHJldHVybiBuZXcgWm9kRnVuY3Rpb24oewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICByZXR1cm5zOiByZXR1cm5UeXBlCiAgICAgIH0pOwogICAgfQogICAgaW1wbGVtZW50KGZ1bmMpIHsKICAgICAgY29uc3QgdmFsaWRhdGVkRnVuYyA9IHRoaXMucGFyc2UoZnVuYyk7CiAgICAgIHJldHVybiB2YWxpZGF0ZWRGdW5jOwogICAgfQogICAgc3RyaWN0SW1wbGVtZW50KGZ1bmMpIHsKICAgICAgY29uc3QgdmFsaWRhdGVkRnVuYyA9IHRoaXMucGFyc2UoZnVuYyk7CiAgICAgIHJldHVybiB2YWxpZGF0ZWRGdW5jOwogICAgfQogICAgc3RhdGljIGNyZWF0ZShhcmdzLCByZXR1cm5zLCBwYXJhbXMpIHsKICAgICAgcmV0dXJuIG5ldyBab2RGdW5jdGlvbih7CiAgICAgICAgYXJnczogYXJncyA/IGFyZ3MgOiBab2RUdXBsZS5jcmVhdGUoW10pLnJlc3QoWm9kVW5rbm93bi5jcmVhdGUoKSksCiAgICAgICAgcmV0dXJuczogcmV0dXJucyB8fCBab2RVbmtub3duLmNyZWF0ZSgpLAogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRnVuY3Rpb24sCiAgICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICAgIH0pOwogICAgfQogIH0KICBjbGFzcyBab2RMYXp5IGV4dGVuZHMgWm9kVHlwZSB7CiAgICBnZXQgc2NoZW1hKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmdldHRlcigpOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBjb25zdCBsYXp5U2NoZW1hID0gdGhpcy5fZGVmLmdldHRlcigpOwogICAgICByZXR1cm4gbGF6eVNjaGVtYS5fcGFyc2UoeyBkYXRhOiBjdHguZGF0YSwgcGF0aDogY3R4LnBhdGgsIHBhcmVudDogY3R4IH0pOwogICAgfQogIH0KICBab2RMYXp5LmNyZWF0ZSA9IChnZXR0ZXIsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RMYXp5KHsKICAgICAgZ2V0dGVyLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZExhenksCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RMaXRlcmFsIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgaWYgKGlucHV0LmRhdGEgIT09IHRoaXMuX2RlZi52YWx1ZSkgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIHJlY2VpdmVkOiBjdHguZGF0YSwKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX2xpdGVyYWwsCiAgICAgICAgICBleHBlY3RlZDogdGhpcy5fZGVmLnZhbHVlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgcmV0dXJuIHsgc3RhdHVzOiAidmFsaWQiLCB2YWx1ZTogaW5wdXQuZGF0YSB9OwogICAgfQogICAgZ2V0IHZhbHVlKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnZhbHVlOwogICAgfQogIH0KICBab2RMaXRlcmFsLmNyZWF0ZSA9ICh2YWx1ZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZExpdGVyYWwoewogICAgICB2YWx1ZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RMaXRlcmFsLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgZnVuY3Rpb24gY3JlYXRlWm9kRW51bSh2YWx1ZXMsIHBhcmFtcykgewogICAgcmV0dXJuIG5ldyBab2RFbnVtKHsKICAgICAgdmFsdWVzLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVudW0sCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfQogIGNsYXNzIFpvZEVudW0gZXh0ZW5kcyBab2RUeXBlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogICAgICBfWm9kRW51bV9jYWNoZS5zZXQodGhpcywgdm9pZCAwKTsKICAgIH0KICAgIF9wYXJzZShpbnB1dCkgewogICAgICBpZiAodHlwZW9mIGlucHV0LmRhdGEgIT09ICJzdHJpbmciKSB7CiAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5fZ2V0T3JSZXR1cm5DdHgoaW5wdXQpOwogICAgICAgIGNvbnN0IGV4cGVjdGVkVmFsdWVzID0gdGhpcy5fZGVmLnZhbHVlczsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGV4cGVjdGVkOiB1dGlsLmpvaW5WYWx1ZXMoZXhwZWN0ZWRWYWx1ZXMpLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLAogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmICghX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfWm9kRW51bV9jYWNoZSkpIHsKICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9ab2RFbnVtX2NhY2hlLCBuZXcgU2V0KHRoaXMuX2RlZi52YWx1ZXMpKTsKICAgICAgfQogICAgICBpZiAoIV9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1pvZEVudW1fY2FjaGUpLmhhcyhpbnB1dC5kYXRhKSkgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBjb25zdCBleHBlY3RlZFZhbHVlcyA9IHRoaXMuX2RlZi52YWx1ZXM7CiAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCB7CiAgICAgICAgICByZWNlaXZlZDogY3R4LmRhdGEsCiAgICAgICAgICBjb2RlOiBab2RJc3N1ZUNvZGUuaW52YWxpZF9lbnVtX3ZhbHVlLAogICAgICAgICAgb3B0aW9uczogZXhwZWN0ZWRWYWx1ZXMKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4gT0soaW5wdXQuZGF0YSk7CiAgICB9CiAgICBnZXQgb3B0aW9ucygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi52YWx1ZXM7CiAgICB9CiAgICBnZXQgZW51bSgpIHsKICAgICAgY29uc3QgZW51bVZhbHVlcyA9IHt9OwogICAgICBmb3IgKGNvbnN0IHZhbCBvZiB0aGlzLl9kZWYudmFsdWVzKSB7CiAgICAgICAgZW51bVZhbHVlc1t2YWxdID0gdmFsOwogICAgICB9CiAgICAgIHJldHVybiBlbnVtVmFsdWVzOwogICAgfQogICAgZ2V0IFZhbHVlcygpIHsKICAgICAgY29uc3QgZW51bVZhbHVlcyA9IHt9OwogICAgICBmb3IgKGNvbnN0IHZhbCBvZiB0aGlzLl9kZWYudmFsdWVzKSB7CiAgICAgICAgZW51bVZhbHVlc1t2YWxdID0gdmFsOwogICAgICB9CiAgICAgIHJldHVybiBlbnVtVmFsdWVzOwogICAgfQogICAgZ2V0IEVudW0oKSB7CiAgICAgIGNvbnN0IGVudW1WYWx1ZXMgPSB7fTsKICAgICAgZm9yIChjb25zdCB2YWwgb2YgdGhpcy5fZGVmLnZhbHVlcykgewogICAgICAgIGVudW1WYWx1ZXNbdmFsXSA9IHZhbDsKICAgICAgfQogICAgICByZXR1cm4gZW51bVZhbHVlczsKICAgIH0KICAgIGV4dHJhY3QodmFsdWVzLCBuZXdEZWYgPSB0aGlzLl9kZWYpIHsKICAgICAgcmV0dXJuIFpvZEVudW0uY3JlYXRlKHZhbHVlcywgewogICAgICAgIC4uLnRoaXMuX2RlZiwKICAgICAgICAuLi5uZXdEZWYKICAgICAgfSk7CiAgICB9CiAgICBleGNsdWRlKHZhbHVlcywgbmV3RGVmID0gdGhpcy5fZGVmKSB7CiAgICAgIHJldHVybiBab2RFbnVtLmNyZWF0ZSh0aGlzLm9wdGlvbnMuZmlsdGVyKChvcHQpID0+ICF2YWx1ZXMuaW5jbHVkZXMob3B0KSksIHsKICAgICAgICAuLi50aGlzLl9kZWYsCiAgICAgICAgLi4ubmV3RGVmCiAgICAgIH0pOwogICAgfQogIH0KICBfWm9kRW51bV9jYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgV2Vha01hcCgpOwogIFpvZEVudW0uY3JlYXRlID0gY3JlYXRlWm9kRW51bTsKICBjbGFzcyBab2ROYXRpdmVFbnVtIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgX1pvZE5hdGl2ZUVudW1fY2FjaGUuc2V0KHRoaXMsIHZvaWQgMCk7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgbmF0aXZlRW51bVZhbHVlcyA9IHV0aWwuZ2V0VmFsaWRFbnVtVmFsdWVzKHRoaXMuX2RlZi52YWx1ZXMpOwogICAgICBjb25zdCBjdHggPSB0aGlzLl9nZXRPclJldHVybkN0eChpbnB1dCk7CiAgICAgIGlmIChjdHgucGFyc2VkVHlwZSAhPT0gWm9kUGFyc2VkVHlwZS5zdHJpbmcgJiYgY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUubnVtYmVyKSB7CiAgICAgICAgY29uc3QgZXhwZWN0ZWRWYWx1ZXMgPSB1dGlsLm9iamVjdFZhbHVlcyhuYXRpdmVFbnVtVmFsdWVzKTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGV4cGVjdGVkOiB1dGlsLmpvaW5WYWx1ZXMoZXhwZWN0ZWRWYWx1ZXMpLAogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5wYXJzZWRUeXBlLAogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICB9CiAgICAgIGlmICghX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfWm9kTmF0aXZlRW51bV9jYWNoZSkpIHsKICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9ab2ROYXRpdmVFbnVtX2NhY2hlLCBuZXcgU2V0KHV0aWwuZ2V0VmFsaWRFbnVtVmFsdWVzKHRoaXMuX2RlZi52YWx1ZXMpKSk7CiAgICAgIH0KICAgICAgaWYgKCFfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ab2ROYXRpdmVFbnVtX2NhY2hlKS5oYXMoaW5wdXQuZGF0YSkpIHsKICAgICAgICBjb25zdCBleHBlY3RlZFZhbHVlcyA9IHV0aWwub2JqZWN0VmFsdWVzKG5hdGl2ZUVudW1WYWx1ZXMpOwogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgcmVjZWl2ZWQ6IGN0eC5kYXRhLAogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfZW51bV92YWx1ZSwKICAgICAgICAgIG9wdGlvbnM6IGV4cGVjdGVkVmFsdWVzCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgIH0KICAgICAgcmV0dXJuIE9LKGlucHV0LmRhdGEpOwogICAgfQogICAgZ2V0IGVudW0oKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYudmFsdWVzOwogICAgfQogIH0KICBfWm9kTmF0aXZlRW51bV9jYWNoZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgV2Vha01hcCgpOwogIFpvZE5hdGl2ZUVudW0uY3JlYXRlID0gKHZhbHVlcywgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE5hdGl2ZUVudW0oewogICAgICB2YWx1ZXMsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kTmF0aXZlRW51bSwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZFByb21pc2UgZXh0ZW5kcyBab2RUeXBlIHsKICAgIHVud3JhcCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi50eXBlOwogICAgfQogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgIT09IFpvZFBhcnNlZFR5cGUucHJvbWlzZSAmJiBjdHguY29tbW9uLmFzeW5jID09PSBmYWxzZSkgewogICAgICAgIGFkZElzc3VlVG9Db250ZXh0KGN0eCwgewogICAgICAgICAgY29kZTogWm9kSXNzdWVDb2RlLmludmFsaWRfdHlwZSwKICAgICAgICAgIGV4cGVjdGVkOiBab2RQYXJzZWRUeXBlLnByb21pc2UsCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICBjb25zdCBwcm9taXNpZmllZCA9IGN0eC5wYXJzZWRUeXBlID09PSBab2RQYXJzZWRUeXBlLnByb21pc2UgPyBjdHguZGF0YSA6IFByb21pc2UucmVzb2x2ZShjdHguZGF0YSk7CiAgICAgIHJldHVybiBPSyhwcm9taXNpZmllZC50aGVuKChkYXRhKSA9PiB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi50eXBlLnBhcnNlQXN5bmMoZGF0YSwgewogICAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgICBlcnJvck1hcDogY3R4LmNvbW1vbi5jb250ZXh0dWFsRXJyb3JNYXAKICAgICAgICB9KTsKICAgICAgfSkpOwogICAgfQogIH0KICBab2RQcm9taXNlLmNyZWF0ZSA9IChzY2hlbWEsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RQcm9taXNlKHsKICAgICAgdHlwZTogc2NoZW1hLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZFByb21pc2UsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2RFZmZlY3RzIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBpbm5lclR5cGUoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYuc2NoZW1hOwogICAgfQogICAgc291cmNlVHlwZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5zY2hlbWEuX2RlZi50eXBlTmFtZSA9PT0gWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMgPyB0aGlzLl9kZWYuc2NoZW1hLnNvdXJjZVR5cGUoKSA6IHRoaXMuX2RlZi5zY2hlbWE7CiAgICB9CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgY29uc3QgZWZmZWN0ID0gdGhpcy5fZGVmLmVmZmVjdCB8fCBudWxsOwogICAgICBjb25zdCBjaGVja0N0eCA9IHsKICAgICAgICBhZGRJc3N1ZTogKGFyZykgPT4gewogICAgICAgICAgYWRkSXNzdWVUb0NvbnRleHQoY3R4LCBhcmcpOwogICAgICAgICAgaWYgKGFyZy5mYXRhbCkgewogICAgICAgICAgICBzdGF0dXMuYWJvcnQoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0YXR1cy5kaXJ0eSgpOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgZ2V0IHBhdGgoKSB7CiAgICAgICAgICByZXR1cm4gY3R4LnBhdGg7CiAgICAgICAgfQogICAgICB9OwogICAgICBjaGVja0N0eC5hZGRJc3N1ZSA9IGNoZWNrQ3R4LmFkZElzc3VlLmJpbmQoY2hlY2tDdHgpOwogICAgICBpZiAoZWZmZWN0LnR5cGUgPT09ICJwcmVwcm9jZXNzIikgewogICAgICAgIGNvbnN0IHByb2Nlc3NlZCA9IGVmZmVjdC50cmFuc2Zvcm0oY3R4LmRhdGEsIGNoZWNrQ3R4KTsKICAgICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYykgewogICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwcm9jZXNzZWQpLnRoZW4oYXN5bmMgKHByb2Nlc3NlZDIpID0+IHsKICAgICAgICAgICAgaWYgKHN0YXR1cy52YWx1ZSA9PT0gImFib3J0ZWQiKQogICAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLl9kZWYuc2NoZW1hLl9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgICBkYXRhOiBwcm9jZXNzZWQyLAogICAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgICByZXR1cm4gRElSVFkocmVzdWx0LnZhbHVlKTsKICAgICAgICAgICAgaWYgKHN0YXR1cy52YWx1ZSA9PT0gImRpcnR5IikKICAgICAgICAgICAgICByZXR1cm4gRElSVFkocmVzdWx0LnZhbHVlKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgIH0pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoc3RhdHVzLnZhbHVlID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogcHJvY2Vzc2VkLAogICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICAgIH0pOwogICAgICAgICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICJhYm9ydGVkIikKICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgcmV0dXJuIERJUlRZKHJlc3VsdC52YWx1ZSk7CiAgICAgICAgICBpZiAoc3RhdHVzLnZhbHVlID09PSAiZGlydHkiKQogICAgICAgICAgICByZXR1cm4gRElSVFkocmVzdWx0LnZhbHVlKTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChlZmZlY3QudHlwZSA9PT0gInJlZmluZW1lbnQiKSB7CiAgICAgICAgY29uc3QgZXhlY3V0ZVJlZmluZW1lbnQgPSAoYWNjKSA9PiB7CiAgICAgICAgICBjb25zdCByZXN1bHQgPSBlZmZlY3QucmVmaW5lbWVudChhY2MsIGNoZWNrQ3R4KTsKICAgICAgICAgIGlmIChjdHguY29tbW9uLmFzeW5jKSB7CiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiQXN5bmMgcmVmaW5lbWVudCBlbmNvdW50ZXJlZCBkdXJpbmcgc3luY2hyb25vdXMgcGFyc2Ugb3BlcmF0aW9uLiBVc2UgLnBhcnNlQXN5bmMgaW5zdGVhZC4iKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBhY2M7CiAgICAgICAgfTsKICAgICAgICBpZiAoY3R4LmNvbW1vbi5hc3luYyA9PT0gZmFsc2UpIHsKICAgICAgICAgIGNvbnN0IGlubmVyID0gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAoaW5uZXIuc3RhdHVzID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgaWYgKGlubmVyLnN0YXR1cyA9PT0gImRpcnR5IikKICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICBleGVjdXRlUmVmaW5lbWVudChpbm5lci52YWx1ZSk7CiAgICAgICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IGlubmVyLnZhbHVlIH07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9kZWYuc2NoZW1hLl9wYXJzZUFzeW5jKHsgZGF0YTogY3R4LmRhdGEsIHBhdGg6IGN0eC5wYXRoLCBwYXJlbnQ6IGN0eCB9KS50aGVuKChpbm5lcikgPT4gewogICAgICAgICAgICBpZiAoaW5uZXIuc3RhdHVzID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgICAgIGlmIChpbm5lci5zdGF0dXMgPT09ICJkaXJ0eSIpCiAgICAgICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICAgIHJldHVybiBleGVjdXRlUmVmaW5lbWVudChpbm5lci52YWx1ZSkudGhlbigoKSA9PiB7CiAgICAgICAgICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiBpbm5lci52YWx1ZSB9OwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoZWZmZWN0LnR5cGUgPT09ICJ0cmFuc2Zvcm0iKSB7CiAgICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMgPT09IGZhbHNlKSB7CiAgICAgICAgICBjb25zdCBiYXNlID0gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VTeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAoIWlzVmFsaWQoYmFzZSkpCiAgICAgICAgICAgIHJldHVybiBiYXNlOwogICAgICAgICAgY29uc3QgcmVzdWx0ID0gZWZmZWN0LnRyYW5zZm9ybShiYXNlLnZhbHVlLCBjaGVja0N0eCk7CiAgICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgUHJvbWlzZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFzeW5jaHJvbm91cyB0cmFuc2Zvcm0gZW5jb3VudGVyZWQgZHVyaW5nIHN5bmNocm9ub3VzIHBhcnNlIG9wZXJhdGlvbi4gVXNlIC5wYXJzZUFzeW5jIGluc3RlYWQuYCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4geyBzdGF0dXM6IHN0YXR1cy52YWx1ZSwgdmFsdWU6IHJlc3VsdCB9OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fZGVmLnNjaGVtYS5fcGFyc2VBc3luYyh7IGRhdGE6IGN0eC5kYXRhLCBwYXRoOiBjdHgucGF0aCwgcGFyZW50OiBjdHggfSkudGhlbigoYmFzZSkgPT4gewogICAgICAgICAgICBpZiAoIWlzVmFsaWQoYmFzZSkpCiAgICAgICAgICAgICAgcmV0dXJuIGJhc2U7CiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZWZmZWN0LnRyYW5zZm9ybShiYXNlLnZhbHVlLCBjaGVja0N0eCkpLnRoZW4oKHJlc3VsdCkgPT4gKHsgc3RhdHVzOiBzdGF0dXMudmFsdWUsIHZhbHVlOiByZXN1bHQgfSkpOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHV0aWwuYXNzZXJ0TmV2ZXIoZWZmZWN0KTsKICAgIH0KICB9CiAgWm9kRWZmZWN0cy5jcmVhdGUgPSAoc2NoZW1hLCBlZmZlY3QsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RFZmZlY3RzKHsKICAgICAgc2NoZW1hLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZEVmZmVjdHMsCiAgICAgIGVmZmVjdCwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIFpvZEVmZmVjdHMuY3JlYXRlV2l0aFByZXByb2Nlc3MgPSAocHJlcHJvY2Vzcywgc2NoZW1hLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kRWZmZWN0cyh7CiAgICAgIHNjaGVtYSwKICAgICAgZWZmZWN0OiB7IHR5cGU6ICJwcmVwcm9jZXNzIiwgdHJhbnNmb3JtOiBwcmVwcm9jZXNzIH0sCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRWZmZWN0cywKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE9wdGlvbmFsIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS51bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gT0sodm9pZCAwKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZS5fcGFyc2UoaW5wdXQpOwogICAgfQogICAgdW53cmFwKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZTsKICAgIH0KICB9CiAgWm9kT3B0aW9uYWwuY3JlYXRlID0gKHR5cGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RPcHRpb25hbCh7CiAgICAgIGlubmVyVHlwZTogdHlwZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RPcHRpb25hbCwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGNsYXNzIFpvZE51bGxhYmxlIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcGFyc2VkVHlwZSA9IHRoaXMuX2dldFR5cGUoaW5wdXQpOwogICAgICBpZiAocGFyc2VkVHlwZSA9PT0gWm9kUGFyc2VkVHlwZS5udWxsKSB7CiAgICAgICAgcmV0dXJuIE9LKG51bGwpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLl9kZWYuaW5uZXJUeXBlLl9wYXJzZShpbnB1dCk7CiAgICB9CiAgICB1bndyYXAoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZWYuaW5uZXJUeXBlOwogICAgfQogIH0KICBab2ROdWxsYWJsZS5jcmVhdGUgPSAodHlwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE51bGxhYmxlKHsKICAgICAgaW5uZXJUeXBlOiB0eXBlLAogICAgICB0eXBlTmFtZTogWm9kRmlyc3RQYXJ0eVR5cGVLaW5kLlpvZE51bGxhYmxlLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kRGVmYXVsdCBleHRlbmRzIFpvZFR5cGUgewogICAgX3BhcnNlKGlucHV0KSB7CiAgICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzLl9wcm9jZXNzSW5wdXRQYXJhbXMoaW5wdXQpOwogICAgICBsZXQgZGF0YSA9IGN0eC5kYXRhOwogICAgICBpZiAoY3R4LnBhcnNlZFR5cGUgPT09IFpvZFBhcnNlZFR5cGUudW5kZWZpbmVkKSB7CiAgICAgICAgZGF0YSA9IHRoaXMuX2RlZi5kZWZhdWx0VmFsdWUoKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZS5fcGFyc2UoewogICAgICAgIGRhdGEsCiAgICAgICAgcGF0aDogY3R4LnBhdGgsCiAgICAgICAgcGFyZW50OiBjdHgKICAgICAgfSk7CiAgICB9CiAgICByZW1vdmVEZWZhdWx0KCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZTsKICAgIH0KICB9CiAgWm9kRGVmYXVsdC5jcmVhdGUgPSAodHlwZSwgcGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZERlZmF1bHQoewogICAgICBpbm5lclR5cGU6IHR5cGUsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kRGVmYXVsdCwKICAgICAgZGVmYXVsdFZhbHVlOiB0eXBlb2YgcGFyYW1zLmRlZmF1bHQgPT09ICJmdW5jdGlvbiIgPyBwYXJhbXMuZGVmYXVsdCA6ICgpID0+IHBhcmFtcy5kZWZhdWx0LAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY2xhc3MgWm9kQ2F0Y2ggZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgY29uc3QgbmV3Q3R4ID0gewogICAgICAgIC4uLmN0eCwKICAgICAgICBjb21tb246IHsKICAgICAgICAgIC4uLmN0eC5jb21tb24sCiAgICAgICAgICBpc3N1ZXM6IFtdCiAgICAgICAgfQogICAgICB9OwogICAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9kZWYuaW5uZXJUeXBlLl9wYXJzZSh7CiAgICAgICAgZGF0YTogbmV3Q3R4LmRhdGEsCiAgICAgICAgcGF0aDogbmV3Q3R4LnBhdGgsCiAgICAgICAgcGFyZW50OiB7CiAgICAgICAgICAuLi5uZXdDdHgKICAgICAgICB9CiAgICAgIH0pOwogICAgICBpZiAoaXNBc3luYyhyZXN1bHQpKSB7CiAgICAgICAgcmV0dXJuIHJlc3VsdC50aGVuKChyZXN1bHQyKSA9PiB7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBzdGF0dXM6ICJ2YWxpZCIsCiAgICAgICAgICAgIHZhbHVlOiByZXN1bHQyLnN0YXR1cyA9PT0gInZhbGlkIiA/IHJlc3VsdDIudmFsdWUgOiB0aGlzLl9kZWYuY2F0Y2hWYWx1ZSh7CiAgICAgICAgICAgICAgZ2V0IGVycm9yKCkgewogICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBab2RFcnJvcihuZXdDdHguY29tbW9uLmlzc3Vlcyk7CiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICBpbnB1dDogbmV3Q3R4LmRhdGEKICAgICAgICAgICAgfSkKICAgICAgICAgIH07CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHN0YXR1czogInZhbGlkIiwKICAgICAgICAgIHZhbHVlOiByZXN1bHQuc3RhdHVzID09PSAidmFsaWQiID8gcmVzdWx0LnZhbHVlIDogdGhpcy5fZGVmLmNhdGNoVmFsdWUoewogICAgICAgICAgICBnZXQgZXJyb3IoKSB7CiAgICAgICAgICAgICAgcmV0dXJuIG5ldyBab2RFcnJvcihuZXdDdHguY29tbW9uLmlzc3Vlcyk7CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGlucHV0OiBuZXdDdHguZGF0YQogICAgICAgICAgfSkKICAgICAgICB9OwogICAgICB9CiAgICB9CiAgICByZW1vdmVDYXRjaCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2RlZi5pbm5lclR5cGU7CiAgICB9CiAgfQogIFpvZENhdGNoLmNyZWF0ZSA9ICh0eXBlLCBwYXJhbXMpID0+IHsKICAgIHJldHVybiBuZXcgWm9kQ2F0Y2goewogICAgICBpbm5lclR5cGU6IHR5cGUsCiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kQ2F0Y2gsCiAgICAgIGNhdGNoVmFsdWU6IHR5cGVvZiBwYXJhbXMuY2F0Y2ggPT09ICJmdW5jdGlvbiIgPyBwYXJhbXMuY2F0Y2ggOiAoKSA9PiBwYXJhbXMuY2F0Y2gsCiAgICAgIC4uLnByb2Nlc3NDcmVhdGVQYXJhbXMocGFyYW1zKQogICAgfSk7CiAgfTsKICBjbGFzcyBab2ROYU4gZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCBwYXJzZWRUeXBlID0gdGhpcy5fZ2V0VHlwZShpbnB1dCk7CiAgICAgIGlmIChwYXJzZWRUeXBlICE9PSBab2RQYXJzZWRUeXBlLm5hbikgewogICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuX2dldE9yUmV0dXJuQ3R4KGlucHV0KTsKICAgICAgICBhZGRJc3N1ZVRvQ29udGV4dChjdHgsIHsKICAgICAgICAgIGNvZGU6IFpvZElzc3VlQ29kZS5pbnZhbGlkX3R5cGUsCiAgICAgICAgICBleHBlY3RlZDogWm9kUGFyc2VkVHlwZS5uYW4sCiAgICAgICAgICByZWNlaXZlZDogY3R4LnBhcnNlZFR5cGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSU5WQUxJRDsKICAgICAgfQogICAgICByZXR1cm4geyBzdGF0dXM6ICJ2YWxpZCIsIHZhbHVlOiBpbnB1dC5kYXRhIH07CiAgICB9CiAgfQogIFpvZE5hTi5jcmVhdGUgPSAocGFyYW1zKSA9PiB7CiAgICByZXR1cm4gbmV3IFpvZE5hTih7CiAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kTmFOLAogICAgICAuLi5wcm9jZXNzQ3JlYXRlUGFyYW1zKHBhcmFtcykKICAgIH0pOwogIH07CiAgY29uc3QgQlJBTkQgPSBTeW1ib2woInpvZF9icmFuZCIpOwogIGNsYXNzIFpvZEJyYW5kZWQgZXh0ZW5kcyBab2RUeXBlIHsKICAgIF9wYXJzZShpbnB1dCkgewogICAgICBjb25zdCB7IGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgY29uc3QgZGF0YSA9IGN0eC5kYXRhOwogICAgICByZXR1cm4gdGhpcy5fZGVmLnR5cGUuX3BhcnNlKHsKICAgICAgICBkYXRhLAogICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgIHBhcmVudDogY3R4CiAgICAgIH0pOwogICAgfQogICAgdW53cmFwKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLnR5cGU7CiAgICB9CiAgfQogIGNsYXNzIFpvZFBpcGVsaW5lIGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgeyBzdGF0dXMsIGN0eCB9ID0gdGhpcy5fcHJvY2Vzc0lucHV0UGFyYW1zKGlucHV0KTsKICAgICAgaWYgKGN0eC5jb21tb24uYXN5bmMpIHsKICAgICAgICBjb25zdCBoYW5kbGVBc3luYyA9IGFzeW5jICgpID0+IHsKICAgICAgICAgIGNvbnN0IGluUmVzdWx0ID0gYXdhaXQgdGhpcy5fZGVmLmluLl9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICAgIHBhdGg6IGN0eC5wYXRoLAogICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAoaW5SZXN1bHQuc3RhdHVzID09PSAiYWJvcnRlZCIpCiAgICAgICAgICAgIHJldHVybiBJTlZBTElEOwogICAgICAgICAgaWYgKGluUmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikgewogICAgICAgICAgICBzdGF0dXMuZGlydHkoKTsKICAgICAgICAgICAgcmV0dXJuIERJUlRZKGluUmVzdWx0LnZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kZWYub3V0Ll9wYXJzZUFzeW5jKHsKICAgICAgICAgICAgICBkYXRhOiBpblJlc3VsdC52YWx1ZSwKICAgICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgICBwYXJlbnQ6IGN0eAogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHJldHVybiBoYW5kbGVBc3luYygpOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGluUmVzdWx0ID0gdGhpcy5fZGVmLmluLl9wYXJzZVN5bmMoewogICAgICAgICAgZGF0YTogY3R4LmRhdGEsCiAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgIHBhcmVudDogY3R4CiAgICAgICAgfSk7CiAgICAgICAgaWYgKGluUmVzdWx0LnN0YXR1cyA9PT0gImFib3J0ZWQiKQogICAgICAgICAgcmV0dXJuIElOVkFMSUQ7CiAgICAgICAgaWYgKGluUmVzdWx0LnN0YXR1cyA9PT0gImRpcnR5IikgewogICAgICAgICAgc3RhdHVzLmRpcnR5KCk7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBzdGF0dXM6ICJkaXJ0eSIsCiAgICAgICAgICAgIHZhbHVlOiBpblJlc3VsdC52YWx1ZQogICAgICAgICAgfTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHRoaXMuX2RlZi5vdXQuX3BhcnNlU3luYyh7CiAgICAgICAgICAgIGRhdGE6IGluUmVzdWx0LnZhbHVlLAogICAgICAgICAgICBwYXRoOiBjdHgucGF0aCwKICAgICAgICAgICAgcGFyZW50OiBjdHgKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgc3RhdGljIGNyZWF0ZShhMiwgYikgewogICAgICByZXR1cm4gbmV3IFpvZFBpcGVsaW5lKHsKICAgICAgICBpbjogYTIsCiAgICAgICAgb3V0OiBiLAogICAgICAgIHR5cGVOYW1lOiBab2RGaXJzdFBhcnR5VHlwZUtpbmQuWm9kUGlwZWxpbmUKICAgICAgfSk7CiAgICB9CiAgfQogIGNsYXNzIFpvZFJlYWRvbmx5IGV4dGVuZHMgWm9kVHlwZSB7CiAgICBfcGFyc2UoaW5wdXQpIHsKICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5fZGVmLmlubmVyVHlwZS5fcGFyc2UoaW5wdXQpOwogICAgICBjb25zdCBmcmVlemUgPSAoZGF0YSkgPT4gewogICAgICAgIGlmIChpc1ZhbGlkKGRhdGEpKSB7CiAgICAgICAgICBkYXRhLnZhbHVlID0gT2JqZWN0LmZyZWV6ZShkYXRhLnZhbHVlKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGRhdGE7CiAgICAgIH07CiAgICAgIHJldHVybiBpc0FzeW5jKHJlc3VsdCkgPyByZXN1bHQudGhlbigoZGF0YSkgPT4gZnJlZXplKGRhdGEpKSA6IGZyZWV6ZShyZXN1bHQpOwogICAgfQogICAgdW53cmFwKCkgewogICAgICByZXR1cm4gdGhpcy5fZGVmLmlubmVyVHlwZTsKICAgIH0KICB9CiAgWm9kUmVhZG9ubHkuY3JlYXRlID0gKHR5cGUsIHBhcmFtcykgPT4gewogICAgcmV0dXJuIG5ldyBab2RSZWFkb25seSh7CiAgICAgIGlubmVyVHlwZTogdHlwZSwKICAgICAgdHlwZU5hbWU6IFpvZEZpcnN0UGFydHlUeXBlS2luZC5ab2RSZWFkb25seSwKICAgICAgLi4ucHJvY2Vzc0NyZWF0ZVBhcmFtcyhwYXJhbXMpCiAgICB9KTsKICB9OwogIGZ1bmN0aW9uIGN1c3RvbShjaGVjaywgcGFyYW1zID0ge30sIGZhdGFsKSB7CiAgICBpZiAoY2hlY2spCiAgICAgIHJldHVybiBab2RBbnkuY3JlYXRlKCkuc3VwZXJSZWZpbmUoKGRhdGEsIGN0eCkgPT4gewogICAgICAgIHZhciBfYSwgX2I7CiAgICAgICAgaWYgKCFjaGVjayhkYXRhKSkgewogICAgICAgICAgY29uc3QgcCA9IHR5cGVvZiBwYXJhbXMgPT09ICJmdW5jdGlvbiIgPyBwYXJhbXMoZGF0YSkgOiB0eXBlb2YgcGFyYW1zID09PSAic3RyaW5nIiA/IHsgbWVzc2FnZTogcGFyYW1zIH0gOiBwYXJhbXM7CiAgICAgICAgICBjb25zdCBfZmF0YWwgPSAoX2IgPSAoX2EgPSBwLmZhdGFsKSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiBmYXRhbCkgIT09IG51bGwgJiYgX2IgIT09IHZvaWQgMCA/IF9iIDogdHJ1ZTsKICAgICAgICAgIGNvbnN0IHAyID0gdHlwZW9mIHAgPT09ICJzdHJpbmciID8geyBtZXNzYWdlOiBwIH0gOiBwOwogICAgICAgICAgY3R4LmFkZElzc3VlKHsgY29kZTogImN1c3RvbSIsIC4uLnAyLCBmYXRhbDogX2ZhdGFsIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICByZXR1cm4gWm9kQW55LmNyZWF0ZSgpOwogIH0KICBjb25zdCBsYXRlID0gewogICAgb2JqZWN0OiBab2RPYmplY3QubGF6eWNyZWF0ZQogIH07CiAgdmFyIFpvZEZpcnN0UGFydHlUeXBlS2luZDsKICAoZnVuY3Rpb24oWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMikgewogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kU3RyaW5nIl0gPSAiWm9kU3RyaW5nIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE51bWJlciJdID0gIlpvZE51bWJlciI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2ROYU4iXSA9ICJab2ROYU4iOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQmlnSW50Il0gPSAiWm9kQmlnSW50IjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZEJvb2xlYW4iXSA9ICJab2RCb29sZWFuIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZERhdGUiXSA9ICJab2REYXRlIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFN5bWJvbCJdID0gIlpvZFN5bWJvbCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RVbmRlZmluZWQiXSA9ICJab2RVbmRlZmluZWQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kTnVsbCJdID0gIlpvZE51bGwiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQW55Il0gPSAiWm9kQW55IjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFVua25vd24iXSA9ICJab2RVbmtub3duIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE5ldmVyIl0gPSAiWm9kTmV2ZXIiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kVm9pZCJdID0gIlpvZFZvaWQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQXJyYXkiXSA9ICJab2RBcnJheSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RPYmplY3QiXSA9ICJab2RPYmplY3QiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kVW5pb24iXSA9ICJab2RVbmlvbiI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2REaXNjcmltaW5hdGVkVW5pb24iXSA9ICJab2REaXNjcmltaW5hdGVkVW5pb24iOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kSW50ZXJzZWN0aW9uIl0gPSAiWm9kSW50ZXJzZWN0aW9uIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFR1cGxlIl0gPSAiWm9kVHVwbGUiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kUmVjb3JkIl0gPSAiWm9kUmVjb3JkIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE1hcCJdID0gIlpvZE1hcCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RTZXQiXSA9ICJab2RTZXQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kRnVuY3Rpb24iXSA9ICJab2RGdW5jdGlvbiI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RMYXp5Il0gPSAiWm9kTGF6eSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RMaXRlcmFsIl0gPSAiWm9kTGl0ZXJhbCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RFbnVtIl0gPSAiWm9kRW51bSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RFZmZlY3RzIl0gPSAiWm9kRWZmZWN0cyI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2ROYXRpdmVFbnVtIl0gPSAiWm9kTmF0aXZlRW51bSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RPcHRpb25hbCJdID0gIlpvZE9wdGlvbmFsIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZE51bGxhYmxlIl0gPSAiWm9kTnVsbGFibGUiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kRGVmYXVsdCJdID0gIlpvZERlZmF1bHQiOwogICAgWm9kRmlyc3RQYXJ0eVR5cGVLaW5kMlsiWm9kQ2F0Y2giXSA9ICJab2RDYXRjaCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RQcm9taXNlIl0gPSAiWm9kUHJvbWlzZSI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RCcmFuZGVkIl0gPSAiWm9kQnJhbmRlZCI7CiAgICBab2RGaXJzdFBhcnR5VHlwZUtpbmQyWyJab2RQaXBlbGluZSJdID0gIlpvZFBpcGVsaW5lIjsKICAgIFpvZEZpcnN0UGFydHlUeXBlS2luZDJbIlpvZFJlYWRvbmx5Il0gPSAiWm9kUmVhZG9ubHkiOwogIH0pKFpvZEZpcnN0UGFydHlUeXBlS2luZCB8fCAoWm9kRmlyc3RQYXJ0eVR5cGVLaW5kID0ge30pKTsKICBjb25zdCBpbnN0YW5jZU9mVHlwZSA9IChjbHMsIHBhcmFtcyA9IHsKICAgIG1lc3NhZ2U6IGBJbnB1dCBub3QgaW5zdGFuY2Ugb2YgJHtjbHMubmFtZX1gCiAgfSkgPT4gY3VzdG9tKChkYXRhKSA9PiBkYXRhIGluc3RhbmNlb2YgY2xzLCBwYXJhbXMpOwogIGNvbnN0IHN0cmluZ1R5cGUgPSBab2RTdHJpbmcuY3JlYXRlOwogIGNvbnN0IG51bWJlclR5cGUgPSBab2ROdW1iZXIuY3JlYXRlOwogIGNvbnN0IG5hblR5cGUgPSBab2ROYU4uY3JlYXRlOwogIGNvbnN0IGJpZ0ludFR5cGUgPSBab2RCaWdJbnQuY3JlYXRlOwogIGNvbnN0IGJvb2xlYW5UeXBlID0gWm9kQm9vbGVhbi5jcmVhdGU7CiAgY29uc3QgZGF0ZVR5cGUgPSBab2REYXRlLmNyZWF0ZTsKICBjb25zdCBzeW1ib2xUeXBlID0gWm9kU3ltYm9sLmNyZWF0ZTsKICBjb25zdCB1bmRlZmluZWRUeXBlID0gWm9kVW5kZWZpbmVkLmNyZWF0ZTsKICBjb25zdCBudWxsVHlwZSA9IFpvZE51bGwuY3JlYXRlOwogIGNvbnN0IGFueVR5cGUgPSBab2RBbnkuY3JlYXRlOwogIGNvbnN0IHVua25vd25UeXBlID0gWm9kVW5rbm93bi5jcmVhdGU7CiAgY29uc3QgbmV2ZXJUeXBlID0gWm9kTmV2ZXIuY3JlYXRlOwogIGNvbnN0IHZvaWRUeXBlID0gWm9kVm9pZC5jcmVhdGU7CiAgY29uc3QgYXJyYXlUeXBlID0gWm9kQXJyYXkuY3JlYXRlOwogIGNvbnN0IG9iamVjdFR5cGUgPSBab2RPYmplY3QuY3JlYXRlOwogIGNvbnN0IHN0cmljdE9iamVjdFR5cGUgPSBab2RPYmplY3Quc3RyaWN0Q3JlYXRlOwogIGNvbnN0IHVuaW9uVHlwZSA9IFpvZFVuaW9uLmNyZWF0ZTsKICBjb25zdCBkaXNjcmltaW5hdGVkVW5pb25UeXBlID0gWm9kRGlzY3JpbWluYXRlZFVuaW9uLmNyZWF0ZTsKICBjb25zdCBpbnRlcnNlY3Rpb25UeXBlID0gWm9kSW50ZXJzZWN0aW9uLmNyZWF0ZTsKICBjb25zdCB0dXBsZVR5cGUgPSBab2RUdXBsZS5jcmVhdGU7CiAgY29uc3QgcmVjb3JkVHlwZSA9IFpvZFJlY29yZC5jcmVhdGU7CiAgY29uc3QgbWFwVHlwZSA9IFpvZE1hcC5jcmVhdGU7CiAgY29uc3Qgc2V0VHlwZSA9IFpvZFNldC5jcmVhdGU7CiAgY29uc3QgZnVuY3Rpb25UeXBlID0gWm9kRnVuY3Rpb24uY3JlYXRlOwogIGNvbnN0IGxhenlUeXBlID0gWm9kTGF6eS5jcmVhdGU7CiAgY29uc3QgbGl0ZXJhbFR5cGUgPSBab2RMaXRlcmFsLmNyZWF0ZTsKICBjb25zdCBlbnVtVHlwZSA9IFpvZEVudW0uY3JlYXRlOwogIGNvbnN0IG5hdGl2ZUVudW1UeXBlID0gWm9kTmF0aXZlRW51bS5jcmVhdGU7CiAgY29uc3QgcHJvbWlzZVR5cGUgPSBab2RQcm9taXNlLmNyZWF0ZTsKICBjb25zdCBlZmZlY3RzVHlwZSA9IFpvZEVmZmVjdHMuY3JlYXRlOwogIGNvbnN0IG9wdGlvbmFsVHlwZSA9IFpvZE9wdGlvbmFsLmNyZWF0ZTsKICBjb25zdCBudWxsYWJsZVR5cGUgPSBab2ROdWxsYWJsZS5jcmVhdGU7CiAgY29uc3QgcHJlcHJvY2Vzc1R5cGUgPSBab2RFZmZlY3RzLmNyZWF0ZVdpdGhQcmVwcm9jZXNzOwogIGNvbnN0IHBpcGVsaW5lVHlwZSA9IFpvZFBpcGVsaW5lLmNyZWF0ZTsKICBjb25zdCBvc3RyaW5nID0gKCkgPT4gc3RyaW5nVHlwZSgpLm9wdGlvbmFsKCk7CiAgY29uc3Qgb251bWJlciA9ICgpID0+IG51bWJlclR5cGUoKS5vcHRpb25hbCgpOwogIGNvbnN0IG9ib29sZWFuID0gKCkgPT4gYm9vbGVhblR5cGUoKS5vcHRpb25hbCgpOwogIGNvbnN0IGNvZXJjZSA9IHsKICAgIHN0cmluZzogKGFyZykgPT4gWm9kU3RyaW5nLmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pLAogICAgbnVtYmVyOiAoYXJnKSA9PiBab2ROdW1iZXIuY3JlYXRlKHsgLi4uYXJnLCBjb2VyY2U6IHRydWUgfSksCiAgICBib29sZWFuOiAoYXJnKSA9PiBab2RCb29sZWFuLmNyZWF0ZSh7CiAgICAgIC4uLmFyZywKICAgICAgY29lcmNlOiB0cnVlCiAgICB9KSwKICAgIGJpZ2ludDogKGFyZykgPT4gWm9kQmlnSW50LmNyZWF0ZSh7IC4uLmFyZywgY29lcmNlOiB0cnVlIH0pLAogICAgZGF0ZTogKGFyZykgPT4gWm9kRGF0ZS5jcmVhdGUoeyAuLi5hcmcsIGNvZXJjZTogdHJ1ZSB9KQogIH07CiAgY29uc3QgTkVWRVIgPSBJTlZBTElEOwogIHZhciB6JDEgPSAvKiBAX19QVVJFX18gKi8gT2JqZWN0LmZyZWV6ZSh7CiAgICBfX3Byb3RvX186IG51bGwsCiAgICBkZWZhdWx0RXJyb3JNYXA6IGVycm9yTWFwLAogICAgc2V0RXJyb3JNYXAsCiAgICBnZXRFcnJvck1hcCwKICAgIG1ha2VJc3N1ZSwKICAgIEVNUFRZX1BBVEgsCiAgICBhZGRJc3N1ZVRvQ29udGV4dCwKICAgIFBhcnNlU3RhdHVzLAogICAgSU5WQUxJRCwKICAgIERJUlRZLAogICAgT0ssCiAgICBpc0Fib3J0ZWQsCiAgICBpc0RpcnR5LAogICAgaXNWYWxpZCwKICAgIGlzQXN5bmMsCiAgICBnZXQgdXRpbCgpIHsKICAgICAgcmV0dXJuIHV0aWw7CiAgICB9LAogICAgZ2V0IG9iamVjdFV0aWwoKSB7CiAgICAgIHJldHVybiBvYmplY3RVdGlsOwogICAgfSwKICAgIFpvZFBhcnNlZFR5cGUsCiAgICBnZXRQYXJzZWRUeXBlLAogICAgWm9kVHlwZSwKICAgIGRhdGV0aW1lUmVnZXgsCiAgICBab2RTdHJpbmcsCiAgICBab2ROdW1iZXIsCiAgICBab2RCaWdJbnQsCiAgICBab2RCb29sZWFuLAogICAgWm9kRGF0ZSwKICAgIFpvZFN5bWJvbCwKICAgIFpvZFVuZGVmaW5lZCwKICAgIFpvZE51bGwsCiAgICBab2RBbnksCiAgICBab2RVbmtub3duLAogICAgWm9kTmV2ZXIsCiAgICBab2RWb2lkLAogICAgWm9kQXJyYXksCiAgICBab2RPYmplY3QsCiAgICBab2RVbmlvbiwKICAgIFpvZERpc2NyaW1pbmF0ZWRVbmlvbiwKICAgIFpvZEludGVyc2VjdGlvbiwKICAgIFpvZFR1cGxlLAogICAgWm9kUmVjb3JkLAogICAgWm9kTWFwLAogICAgWm9kU2V0LAogICAgWm9kRnVuY3Rpb24sCiAgICBab2RMYXp5LAogICAgWm9kTGl0ZXJhbCwKICAgIFpvZEVudW0sCiAgICBab2ROYXRpdmVFbnVtLAogICAgWm9kUHJvbWlzZSwKICAgIFpvZEVmZmVjdHMsCiAgICBab2RUcmFuc2Zvcm1lcjogWm9kRWZmZWN0cywKICAgIFpvZE9wdGlvbmFsLAogICAgWm9kTnVsbGFibGUsCiAgICBab2REZWZhdWx0LAogICAgWm9kQ2F0Y2gsCiAgICBab2ROYU4sCiAgICBCUkFORCwKICAgIFpvZEJyYW5kZWQsCiAgICBab2RQaXBlbGluZSwKICAgIFpvZFJlYWRvbmx5LAogICAgY3VzdG9tLAogICAgU2NoZW1hOiBab2RUeXBlLAogICAgWm9kU2NoZW1hOiBab2RUeXBlLAogICAgbGF0ZSwKICAgIGdldCBab2RGaXJzdFBhcnR5VHlwZUtpbmQoKSB7CiAgICAgIHJldHVybiBab2RGaXJzdFBhcnR5VHlwZUtpbmQ7CiAgICB9LAogICAgY29lcmNlLAogICAgYW55OiBhbnlUeXBlLAogICAgYXJyYXk6IGFycmF5VHlwZSwKICAgIGJpZ2ludDogYmlnSW50VHlwZSwKICAgIGJvb2xlYW46IGJvb2xlYW5UeXBlLAogICAgZGF0ZTogZGF0ZVR5cGUsCiAgICBkaXNjcmltaW5hdGVkVW5pb246IGRpc2NyaW1pbmF0ZWRVbmlvblR5cGUsCiAgICBlZmZlY3Q6IGVmZmVjdHNUeXBlLAogICAgImVudW0iOiBlbnVtVHlwZSwKICAgICJmdW5jdGlvbiI6IGZ1bmN0aW9uVHlwZSwKICAgICJpbnN0YW5jZW9mIjogaW5zdGFuY2VPZlR5cGUsCiAgICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvblR5cGUsCiAgICBsYXp5OiBsYXp5VHlwZSwKICAgIGxpdGVyYWw6IGxpdGVyYWxUeXBlLAogICAgbWFwOiBtYXBUeXBlLAogICAgbmFuOiBuYW5UeXBlLAogICAgbmF0aXZlRW51bTogbmF0aXZlRW51bVR5cGUsCiAgICBuZXZlcjogbmV2ZXJUeXBlLAogICAgIm51bGwiOiBudWxsVHlwZSwKICAgIG51bGxhYmxlOiBudWxsYWJsZVR5cGUsCiAgICBudW1iZXI6IG51bWJlclR5cGUsCiAgICBvYmplY3Q6IG9iamVjdFR5cGUsCiAgICBvYm9vbGVhbiwKICAgIG9udW1iZXIsCiAgICBvcHRpb25hbDogb3B0aW9uYWxUeXBlLAogICAgb3N0cmluZywKICAgIHBpcGVsaW5lOiBwaXBlbGluZVR5cGUsCiAgICBwcmVwcm9jZXNzOiBwcmVwcm9jZXNzVHlwZSwKICAgIHByb21pc2U6IHByb21pc2VUeXBlLAogICAgcmVjb3JkOiByZWNvcmRUeXBlLAogICAgc2V0OiBzZXRUeXBlLAogICAgc3RyaWN0T2JqZWN0OiBzdHJpY3RPYmplY3RUeXBlLAogICAgc3RyaW5nOiBzdHJpbmdUeXBlLAogICAgc3ltYm9sOiBzeW1ib2xUeXBlLAogICAgdHJhbnNmb3JtZXI6IGVmZmVjdHNUeXBlLAogICAgdHVwbGU6IHR1cGxlVHlwZSwKICAgICJ1bmRlZmluZWQiOiB1bmRlZmluZWRUeXBlLAogICAgdW5pb246IHVuaW9uVHlwZSwKICAgIHVua25vd246IHVua25vd25UeXBlLAogICAgInZvaWQiOiB2b2lkVHlwZSwKICAgIE5FVkVSLAogICAgWm9kSXNzdWVDb2RlLAogICAgcXVvdGVsZXNzSnNvbiwKICAgIFpvZEVycm9yCiAgfSk7CiAgeiQxLm9iamVjdCh7CiAgICBudWNsZW90aWRlU2VxdWVuY2VzOiB6JDEuYXJyYXkoCiAgICAgIHokMS5vYmplY3QoewogICAgICAgIG5hbWU6IHokMS5zdHJpbmcoKSwKICAgICAgICBzZXF1ZW5jZTogeiQxLnN0cmluZygpCiAgICAgIH0pCiAgICApLAogICAgZ2VuZXM6IHokMS5hcnJheSgKICAgICAgeiQxLm9iamVjdCh7CiAgICAgICAgbmFtZTogeiQxLnN0cmluZygpLAogICAgICAgIHNlcXVlbmNlOiB6JDEuc3RyaW5nKCkKICAgICAgfSkKICAgICkKICB9KTsKICBjb25zdCBvcmRlckJ5VHlwZSA9IHokMS5lbnVtKFsiYXNjZW5kaW5nIiwgImRlc2NlbmRpbmciXSk7CiAgY29uc3Qgb3JkZXJCeSA9IHokMS5vYmplY3QoewogICAgZmllbGQ6IHokMS5zdHJpbmcoKSwKICAgIHR5cGU6IG9yZGVyQnlUeXBlCiAgfSk7CiAgY29uc3QgbGFwaXNCYXNlUmVxdWVzdCA9IHokMS5vYmplY3QoewogICAgbGltaXQ6IHokMS5udW1iZXIoKS5vcHRpb25hbCgpLAogICAgb2Zmc2V0OiB6JDEubnVtYmVyKCkub3B0aW9uYWwoKSwKICAgIGZpZWxkczogeiQxLmFycmF5KHokMS5zdHJpbmcoKSkub3B0aW9uYWwoKSwKICAgIG9yZGVyQnk6IHokMS5hcnJheShvcmRlckJ5KS5vcHRpb25hbCgpCiAgfSkuY2F0Y2hhbGwoeiQxLnVuaW9uKFt6JDEuYm9vbGVhbigpLCB6JDEudW5kZWZpbmVkKCksIHokMS5zdHJpbmcoKSwgeiQxLm51bWJlcigpLCB6JDEubnVsbCgpLCB6JDEuYXJyYXkoeiQxLnN0cmluZygpKV0pKTsKICBsYXBpc0Jhc2VSZXF1ZXN0LmV4dGVuZCh7IG1pblByb3BvcnRpb246IHokMS5udW1iZXIoKS5vcHRpb25hbCgpIH0pOwogIGNvbnN0IG11dGF0aW9uUHJvcG9ydGlvbkNvdW50ID0geiQxLm9iamVjdCh7CiAgICBtdXRhdGlvbjogeiQxLnN0cmluZygpLAogICAgcHJvcG9ydGlvbjogeiQxLm51bWJlcigpLAogICAgY291bnQ6IHokMS5udW1iZXIoKSwKICAgIHNlcXVlbmNlTmFtZTogeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udWxsKCldKSwKICAgIG11dGF0aW9uRnJvbTogeiQxLnN0cmluZygpLAogICAgbXV0YXRpb25UbzogeiQxLnN0cmluZygpLAogICAgcG9zaXRpb246IHokMS5udW1iZXIoKQogIH0pOwogIGNvbnN0IG11dGF0aW9uc1Jlc3BvbnNlID0gbWFrZUxhcGlzUmVzcG9uc2UoeiQxLmFycmF5KG11dGF0aW9uUHJvcG9ydGlvbkNvdW50KSk7CiAgY29uc3QgaW5zZXJ0aW9uQ291bnQgPSB6JDEub2JqZWN0KHsKICAgIGluc2VydGlvbjogeiQxLnN0cmluZygpLAogICAgY291bnQ6IHokMS5udW1iZXIoKSwKICAgIGluc2VydGVkU3ltYm9sczogeiQxLnN0cmluZygpLAogICAgcG9zaXRpb246IHokMS5udW1iZXIoKSwKICAgIHNlcXVlbmNlTmFtZTogeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udWxsKCldKQogIH0pOwogIG1ha2VMYXBpc1Jlc3BvbnNlKHokMS5hcnJheShpbnNlcnRpb25Db3VudCkpOwogIGNvbnN0IGFnZ3JlZ2F0ZWRJdGVtID0geiQxLm9iamVjdCh7IGNvdW50OiB6JDEubnVtYmVyKCkgfSkuY2F0Y2hhbGwoeiQxLnVuaW9uKFt6JDEuc3RyaW5nKCksIHokMS5udW1iZXIoKSwgeiQxLm51bGwoKV0pKTsKICBjb25zdCBhZ2dyZWdhdGVkUmVzcG9uc2UgPSBtYWtlTGFwaXNSZXNwb25zZSh6JDEuYXJyYXkoYWdncmVnYXRlZEl0ZW0pKTsKICBmdW5jdGlvbiBtYWtlTGFwaXNSZXNwb25zZShkYXRhKSB7CiAgICByZXR1cm4geiQxLm9iamVjdCh7CiAgICAgIGRhdGEKICAgIH0pOwogIH0KICBjb25zdCBwcm9ibGVtRGV0YWlsID0geiQxLm9iamVjdCh7CiAgICB0aXRsZTogeiQxLnN0cmluZygpLm9wdGlvbmFsKCksCiAgICBzdGF0dXM6IHokMS5udW1iZXIoKSwKICAgIGRldGFpbDogeiQxLnN0cmluZygpLm9wdGlvbmFsKCksCiAgICB0eXBlOiB6JDEuc3RyaW5nKCksCiAgICBpbnN0YW5jZTogeiQxLnN0cmluZygpLm9wdGlvbmFsKCkKICB9KTsKICBjb25zdCBsYXBpc0Vycm9yID0geiQxLm9iamVjdCh7CiAgICBlcnJvcjogcHJvYmxlbURldGFpbAogIH0pOwogIGNsYXNzIFVua25vd25MYXBpc0Vycm9yIGV4dGVuZHMgRXJyb3IgewogICAgY29uc3RydWN0b3IobWVzc2FnZSwgc3RhdHVzLCByZXF1ZXN0ZWREYXRhKSB7CiAgICAgIHN1cGVyKG1lc3NhZ2UpOwogICAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgICAgdGhpcy5yZXF1ZXN0ZWREYXRhID0gcmVxdWVzdGVkRGF0YTsKICAgICAgdGhpcy5uYW1lID0gIlVua25vd25MYXBpc0Vycm9yIjsKICAgIH0KICB9CiAgY2xhc3MgTGFwaXNFcnJvciBleHRlbmRzIEVycm9yIHsKICAgIGNvbnN0cnVjdG9yKG1lc3NhZ2UsIHN0YXR1cywgcHJvYmxlbURldGFpbDIsIHJlcXVlc3RlZERhdGEpIHsKICAgICAgc3VwZXIobWVzc2FnZSk7CiAgICAgIHRoaXMuc3RhdHVzID0gc3RhdHVzOwogICAgICB0aGlzLnByb2JsZW1EZXRhaWwgPSBwcm9ibGVtRGV0YWlsMjsKICAgICAgdGhpcy5yZXF1ZXN0ZWREYXRhID0gcmVxdWVzdGVkRGF0YTsKICAgICAgdGhpcy5uYW1lID0gIkxhcGlzRXJyb3IiOwogICAgfQogIH0KICBhc3luYyBmdW5jdGlvbiBmZXRjaEFnZ3JlZ2F0ZWQobGFwaXNVcmwsIGJvZHksIHNpZ25hbCkgewogICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChhZ2dyZWdhdGVkRW5kcG9pbnQobGFwaXNVcmwpLCB7CiAgICAgIG1ldGhvZDogIlBPU1QiLAogICAgICBoZWFkZXJzOiB7CiAgICAgICAgIkNvbnRlbnQtVHlwZSI6ICJhcHBsaWNhdGlvbi9qc29uIgogICAgICB9LAogICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShib2R5KSwKICAgICAgc2lnbmFsCiAgICB9KTsKICAgIGF3YWl0IGhhbmRsZUVycm9ycyhyZXNwb25zZSwgImFnZ3JlZ2F0ZWQgZGF0YSIpOwogICAgcmV0dXJuIGFnZ3JlZ2F0ZWRSZXNwb25zZS5wYXJzZShhd2FpdCByZXNwb25zZS5qc29uKCkpOwogIH0KICBhc3luYyBmdW5jdGlvbiBmZXRjaFN1YnN0aXR1dGlvbnNPckRlbGV0aW9ucyhsYXBpc1VybCwgYm9keSwgc2VxdWVuY2VUeXBlLCBzaWduYWwpIHsKICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goc3Vic3RpdHV0aW9uc09yRGVsZXRpb25zRW5kcG9pbnQobGFwaXNVcmwsIHNlcXVlbmNlVHlwZSksIHsKICAgICAgbWV0aG9kOiAiUE9TVCIsCiAgICAgIGhlYWRlcnM6IHsKICAgICAgICAiQ29udGVudC1UeXBlIjogImFwcGxpY2F0aW9uL2pzb24iCiAgICAgIH0sCiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KGJvZHkpLAogICAgICBzaWduYWwKICAgIH0pOwogICAgYXdhaXQgaGFuZGxlRXJyb3JzKHJlc3BvbnNlLCBgJHtzZXF1ZW5jZVR5cGV9IG11dGF0aW9uc2ApOwogICAgcmV0dXJuIG11dGF0aW9uc1Jlc3BvbnNlLnBhcnNlKGF3YWl0IHJlc3BvbnNlLmpzb24oKSk7CiAgfQogIGNvbnN0IGhhbmRsZUVycm9ycyA9IGFzeW5jIChyZXNwb25zZSwgcmVxdWVzdGVkRGF0YSkgPT4gewogICAgaWYgKCFyZXNwb25zZS5vaykgewogICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID49IDQwMCAmJiByZXNwb25zZS5zdGF0dXMgPCA1MDApIHsKICAgICAgICBjb25zdCBqc29uID0gYXdhaXQgcmVzcG9uc2UuanNvbigpOwogICAgICAgIGNvbnN0IGxhcGlzRXJyb3JSZXN1bHQgPSBsYXBpc0Vycm9yLnNhZmVQYXJzZShqc29uKTsKICAgICAgICBpZiAobGFwaXNFcnJvclJlc3VsdC5zdWNjZXNzKSB7CiAgICAgICAgICB0aHJvdyBuZXcgTGFwaXNFcnJvcigKICAgICAgICAgICAgcmVzcG9uc2Uuc3RhdHVzVGV4dCArIGxhcGlzRXJyb3JSZXN1bHQuZGF0YS5lcnJvci5kZXRhaWwsCiAgICAgICAgICAgIHJlc3BvbnNlLnN0YXR1cywKICAgICAgICAgICAgbGFwaXNFcnJvclJlc3VsdC5kYXRhLmVycm9yLAogICAgICAgICAgICByZXF1ZXN0ZWREYXRhCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBwcm9ibGVtRGV0YWlsUmVzdWx0ID0gcHJvYmxlbURldGFpbC5zYWZlUGFyc2UoanNvbik7CiAgICAgICAgaWYgKHByb2JsZW1EZXRhaWxSZXN1bHQuc3VjY2VzcykgewogICAgICAgICAgdGhyb3cgbmV3IExhcGlzRXJyb3IoCiAgICAgICAgICAgIHJlc3BvbnNlLnN0YXR1c1RleHQgKyBwcm9ibGVtRGV0YWlsUmVzdWx0LmRhdGEuZGV0YWlsLAogICAgICAgICAgICByZXNwb25zZS5zdGF0dXMsCiAgICAgICAgICAgIHByb2JsZW1EZXRhaWxSZXN1bHQuZGF0YSwKICAgICAgICAgICAgcmVxdWVzdGVkRGF0YQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgdGhyb3cgbmV3IFVua25vd25MYXBpc0Vycm9yKAogICAgICAgICAgYCR7cmVzcG9uc2Uuc3RhdHVzVGV4dH06ICR7SlNPTi5zdHJpbmdpZnkoanNvbil9YCwKICAgICAgICAgIHJlc3BvbnNlLnN0YXR1cywKICAgICAgICAgIHJlcXVlc3RlZERhdGEKICAgICAgICApOwogICAgICB9CiAgICAgIHRocm93IG5ldyBVbmtub3duTGFwaXNFcnJvcihgJHtyZXNwb25zZS5zdGF0dXNUZXh0fTogJHtyZXNwb25zZS5zdGF0dXN9YCwgcmVzcG9uc2Uuc3RhdHVzLCByZXF1ZXN0ZWREYXRhKTsKICAgIH0KICB9OwogIGNvbnN0IGFnZ3JlZ2F0ZWRFbmRwb2ludCA9IChsYXBpc1VybCkgPT4gYCR7bGFwaXNVcmx9L3NhbXBsZS9hZ2dyZWdhdGVkYDsKICBjb25zdCBzdWJzdGl0dXRpb25zT3JEZWxldGlvbnNFbmRwb2ludCA9IChsYXBpc1VybCwgc2VxdWVuY2VUeXBlKSA9PiB7CiAgICByZXR1cm4gc2VxdWVuY2VUeXBlID09PSAiYW1pbm8gYWNpZCIgPyBgJHtsYXBpc1VybH0vc2FtcGxlL2FtaW5vQWNpZE11dGF0aW9uc2AgOiBgJHtsYXBpc1VybH0vc2FtcGxlL251Y2xlb3RpZGVNdXRhdGlvbnNgOwogIH07CiAgY2xhc3MgRmV0Y2hBZ2dyZWdhdGVkT3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoZmlsdGVyLCBmaWVsZHMgPSBbXSkgewogICAgICB0aGlzLmZpbHRlciA9IGZpbHRlcjsKICAgICAgdGhpcy5maWVsZHMgPSBmaWVsZHM7CiAgICB9CiAgICBhc3luYyBldmFsdWF0ZShsYXBpc1VybCwgc2lnbmFsKSB7CiAgICAgIGNvbnN0IGFnZ3JlZ2F0ZWRSZXNwb25zZTIgPSAoYXdhaXQgZmV0Y2hBZ2dyZWdhdGVkKAogICAgICAgIGxhcGlzVXJsLAogICAgICAgIHsKICAgICAgICAgIC4uLnRoaXMuZmlsdGVyLAogICAgICAgICAgZmllbGRzOiB0aGlzLmZpZWxkcwogICAgICAgIH0sCiAgICAgICAgc2lnbmFsCiAgICAgICkpLmRhdGE7CiAgICAgIGlmIChpc0ZpZWxkc0FycmF5V2l0aENvdW50KGFnZ3JlZ2F0ZWRSZXNwb25zZTIpKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGNvbnRlbnQ6IGFnZ3JlZ2F0ZWRSZXNwb25zZTIKICAgICAgICB9OwogICAgICB9CiAgICAgIHRocm93IG5ldyBFcnJvcigiQWdncmVnYXRlZCByZXNwb25zZSBkb2VzIG5vdCBoYXZlIGNvdW50Iik7CiAgICB9CiAgfQogIGZ1bmN0aW9uIGlzRmllbGRzQXJyYXlXaXRoQ291bnQoZGF0YSkgewogICAgcmV0dXJuIGRhdGEuZXZlcnkoKGl0ZW0pID0+IHR5cGVvZiBpdGVtID09PSAib2JqZWN0IiAmJiAiY291bnQiIGluIGl0ZW0gJiYgdHlwZW9mIGl0ZW0uY291bnQgPT09ICJudW1iZXIiKTsKICB9CiAgY2xhc3MgR3JvdXBCeU9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBmaWVsZCwgYWdncmVnYXRlKSB7CiAgICAgIHRoaXMuY2hpbGQgPSBjaGlsZDsKICAgICAgdGhpcy5maWVsZCA9IGZpZWxkOwogICAgICB0aGlzLmFnZ3JlZ2F0ZSA9IGFnZ3JlZ2F0ZTsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzLCBzaWduYWwpIHsKICAgICAgY29uc3QgY2hpbGRFdmFsdWF0ZWQgPSBhd2FpdCB0aGlzLmNoaWxkLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICBjb25zdCBncm91cGVkID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgZm9yIChjb25zdCByb3cgb2YgY2hpbGRFdmFsdWF0ZWQuY29udGVudCkgewogICAgICAgIGNvbnN0IGtleSA9IHJvd1t0aGlzLmZpZWxkXTsKICAgICAgICBpZiAoIWdyb3VwZWQuaGFzKGtleSkpIHsKICAgICAgICAgIGdyb3VwZWQuc2V0KGtleSwgW10pOwogICAgICAgIH0KICAgICAgICBncm91cGVkLmdldChrZXkpLnB1c2gocm93KTsKICAgICAgfQogICAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXkoKTsKICAgICAgZm9yIChjb25zdCBbLCB2YWx1ZXNdIG9mIGdyb3VwZWQpIHsKICAgICAgICByZXN1bHQucHVzaCh0aGlzLmFnZ3JlZ2F0ZSh2YWx1ZXMpKTsKICAgICAgfQogICAgICByZXR1cm4gewogICAgICAgIGNvbnRlbnQ6IHJlc3VsdAogICAgICB9OwogICAgfQogIH0KICBjbGFzcyBHcm91cEJ5QW5kU3VtT3BlcmF0b3IgZXh0ZW5kcyBHcm91cEJ5T3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoY2hpbGQsIGdyb3VwQnlGaWVsZCwgc3VtRmllbGQpIHsKICAgICAgc3VwZXIoY2hpbGQsIGdyb3VwQnlGaWVsZCwgKHZhbHVlcykgPT4gewogICAgICAgIGxldCBuID0gMDsKICAgICAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIHZhbHVlcykgewogICAgICAgICAgbiArPSB2YWx1ZVtzdW1GaWVsZF07CiAgICAgICAgfQogICAgICAgIHJldHVybiB7CiAgICAgICAgICBbZ3JvdXBCeUZpZWxkXTogdmFsdWVzWzBdW2dyb3VwQnlGaWVsZF0sCiAgICAgICAgICBbc3VtRmllbGRdOiBuCiAgICAgICAgfTsKICAgICAgfSk7CiAgICB9CiAgfQogIGNsYXNzIE1hcE9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBmdW5jKSB7CiAgICAgIHRoaXMuY2hpbGQgPSBjaGlsZDsKICAgICAgdGhpcy5mdW5jID0gZnVuYzsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzLCBzaWduYWwpIHsKICAgICAgY29uc3QgY2hpbGRFdmFsdWF0ZWQgPSBhd2FpdCB0aGlzLmNoaWxkLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICByZXR1cm4gewogICAgICAgIGNvbnRlbnQ6IGNoaWxkRXZhbHVhdGVkLmNvbnRlbnQubWFwKHRoaXMuZnVuYykKICAgICAgfTsKICAgIH0KICB9CiAgY2xhc3MgUmVuYW1lRmllbGRPcGVyYXRvciBleHRlbmRzIE1hcE9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBvbGRGaWVsZE5hbWUsIG5ld0ZpZWxkTmFtZSkgewogICAgICBzdXBlcigKICAgICAgICBjaGlsZCwKICAgICAgICAodmFsdWUpID0+ICh7CiAgICAgICAgICAuLi52YWx1ZSwKICAgICAgICAgIFtuZXdGaWVsZE5hbWVdOiB2YWx1ZVtvbGRGaWVsZE5hbWVdCiAgICAgICAgfSkKICAgICAgKTsKICAgIH0KICB9CiAgY2xhc3MgU29ydE9wZXJhdG9yIHsKICAgIGNvbnN0cnVjdG9yKGNoaWxkLCBjb21wYXJlRm4pIHsKICAgICAgdGhpcy5jaGlsZCA9IGNoaWxkOwogICAgICB0aGlzLmNvbXBhcmVGbiA9IGNvbXBhcmVGbjsKICAgIH0KICAgIGFzeW5jIGV2YWx1YXRlKGxhcGlzLCBzaWduYWwpIHsKICAgICAgY29uc3QgY2hpbGRFdmFsdWF0ZWQgPSBhd2FpdCB0aGlzLmNoaWxkLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICByZXR1cm4gewogICAgICAgIGNvbnRlbnQ6IGNoaWxkRXZhbHVhdGVkLmNvbnRlbnQuc29ydCh0aGlzLmNvbXBhcmVGbikKICAgICAgfTsKICAgIH0KICB9CiAgdmFyIFNFQ09ORFNfQV9NSU5VVEUgPSA2MDsKICB2YXIgU0VDT05EU19BX0hPVVIgPSBTRUNPTkRTX0FfTUlOVVRFICogNjA7CiAgdmFyIFNFQ09ORFNfQV9EQVkgPSBTRUNPTkRTX0FfSE9VUiAqIDI0OwogIHZhciBTRUNPTkRTX0FfV0VFSyA9IFNFQ09ORFNfQV9EQVkgKiA3OwogIHZhciBNSUxMSVNFQ09ORFNfQV9TRUNPTkQgPSAxZTM7CiAgdmFyIE1JTExJU0VDT05EU19BX01JTlVURSA9IFNFQ09ORFNfQV9NSU5VVEUgKiBNSUxMSVNFQ09ORFNfQV9TRUNPTkQ7CiAgdmFyIE1JTExJU0VDT05EU19BX0hPVVIgPSBTRUNPTkRTX0FfSE9VUiAqIE1JTExJU0VDT05EU19BX1NFQ09ORDsKICB2YXIgTUlMTElTRUNPTkRTX0FfREFZID0gU0VDT05EU19BX0RBWSAqIE1JTExJU0VDT05EU19BX1NFQ09ORDsKICB2YXIgTUlMTElTRUNPTkRTX0FfV0VFSyA9IFNFQ09ORFNfQV9XRUVLICogTUlMTElTRUNPTkRTX0FfU0VDT05EOwogIHZhciBNUyA9ICJtaWxsaXNlY29uZCI7CiAgdmFyIFMgPSAic2Vjb25kIjsKICB2YXIgTUlOID0gIm1pbnV0ZSI7CiAgdmFyIEggPSAiaG91ciI7CiAgdmFyIEQgPSAiZGF5IjsKICB2YXIgVyA9ICJ3ZWVrIjsKICB2YXIgTSA9ICJtb250aCI7CiAgdmFyIFEgPSAicXVhcnRlciI7CiAgdmFyIFkgPSAieWVhciI7CiAgdmFyIERBVEUgPSAiZGF0ZSI7CiAgdmFyIEZPUk1BVF9ERUZBVUxUID0gIllZWVktTU0tRERUSEg6bW06c3NaIjsKICB2YXIgSU5WQUxJRF9EQVRFX1NUUklORyA9ICJJbnZhbGlkIERhdGUiOwogIHZhciBSRUdFWF9QQVJTRSA9IC9eKFxkezR9KVstL10/KFxkezEsMn0pP1stL10/KFxkezAsMn0pW1R0XHNdKihcZHsxLDJ9KT86PyhcZHsxLDJ9KT86PyhcZHsxLDJ9KT9bLjpdPyhcZCspPyQvOwogIHZhciBSRUdFWF9GT1JNQVQgPSAvXFsoW15cXV0rKV18WXsxLDR9fE17MSw0fXxEezEsMn18ZHsxLDR9fEh7MSwyfXxoezEsMn18YXxBfG17MSwyfXxzezEsMn18WnsxLDJ9fFNTUy9nOwogIHZhciBlbiA9IHsKICAgIG5hbWU6ICJlbiIsCiAgICB3ZWVrZGF5czogIlN1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Ii5zcGxpdCgiXyIpLAogICAgbW9udGhzOiAiSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlciIuc3BsaXQoIl8iKSwKICAgIG9yZGluYWw6IGZ1bmN0aW9uIG9yZGluYWwobikgewogICAgICB2YXIgczIgPSBbInRoIiwgInN0IiwgIm5kIiwgInJkIl07CiAgICAgIHZhciB2MiA9IG4gJSAxMDA7CiAgICAgIHJldHVybiAiWyIgKyBuICsgKHMyWyh2MiAtIDIwKSAlIDEwXSB8fCBzMlt2Ml0gfHwgczJbMF0pICsgIl0iOwogICAgfQogIH07CiAgdmFyIHBhZFN0YXJ0ID0gZnVuY3Rpb24gcGFkU3RhcnQyKHN0cmluZywgbGVuZ3RoLCBwYWQpIHsKICAgIHZhciBzMiA9IFN0cmluZyhzdHJpbmcpOwogICAgaWYgKCFzMiB8fCBzMi5sZW5ndGggPj0gbGVuZ3RoKSByZXR1cm4gc3RyaW5nOwogICAgcmV0dXJuICIiICsgQXJyYXkobGVuZ3RoICsgMSAtIHMyLmxlbmd0aCkuam9pbihwYWQpICsgc3RyaW5nOwogIH07CiAgdmFyIHBhZFpvbmVTdHIgPSBmdW5jdGlvbiBwYWRab25lU3RyMihpbnN0YW5jZSkgewogICAgdmFyIG5lZ01pbnV0ZXMgPSAtaW5zdGFuY2UudXRjT2Zmc2V0KCk7CiAgICB2YXIgbWludXRlcyA9IE1hdGguYWJzKG5lZ01pbnV0ZXMpOwogICAgdmFyIGhvdXJPZmZzZXQgPSBNYXRoLmZsb29yKG1pbnV0ZXMgLyA2MCk7CiAgICB2YXIgbWludXRlT2Zmc2V0ID0gbWludXRlcyAlIDYwOwogICAgcmV0dXJuIChuZWdNaW51dGVzIDw9IDAgPyAiKyIgOiAiLSIpICsgcGFkU3RhcnQoaG91ck9mZnNldCwgMiwgIjAiKSArICI6IiArIHBhZFN0YXJ0KG1pbnV0ZU9mZnNldCwgMiwgIjAiKTsKICB9OwogIHZhciBtb250aERpZmYgPSBmdW5jdGlvbiBtb250aERpZmYyKGEyLCBiKSB7CiAgICBpZiAoYTIuZGF0ZSgpIDwgYi5kYXRlKCkpIHJldHVybiAtbW9udGhEaWZmMihiLCBhMik7CiAgICB2YXIgd2hvbGVNb250aERpZmYgPSAoYi55ZWFyKCkgLSBhMi55ZWFyKCkpICogMTIgKyAoYi5tb250aCgpIC0gYTIubW9udGgoKSk7CiAgICB2YXIgYW5jaG9yID0gYTIuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYsIE0pOwogICAgdmFyIGMyID0gYiAtIGFuY2hvciA8IDA7CiAgICB2YXIgYW5jaG9yMiA9IGEyLmNsb25lKCkuYWRkKHdob2xlTW9udGhEaWZmICsgKGMyID8gLTEgOiAxKSwgTSk7CiAgICByZXR1cm4gKygtKHdob2xlTW9udGhEaWZmICsgKGIgLSBhbmNob3IpIC8gKGMyID8gYW5jaG9yIC0gYW5jaG9yMiA6IGFuY2hvcjIgLSBhbmNob3IpKSB8fCAwKTsKICB9OwogIHZhciBhYnNGbG9vciA9IGZ1bmN0aW9uIGFic0Zsb29yMihuKSB7CiAgICByZXR1cm4gbiA8IDAgPyBNYXRoLmNlaWwobikgfHwgMCA6IE1hdGguZmxvb3Iobik7CiAgfTsKICB2YXIgcHJldHR5VW5pdCA9IGZ1bmN0aW9uIHByZXR0eVVuaXQyKHUyKSB7CiAgICB2YXIgc3BlY2lhbCA9IHsKICAgICAgTSwKICAgICAgeTogWSwKICAgICAgdzogVywKICAgICAgZDogRCwKICAgICAgRDogREFURSwKICAgICAgaDogSCwKICAgICAgbTogTUlOLAogICAgICBzOiBTLAogICAgICBtczogTVMsCiAgICAgIFEKICAgIH07CiAgICByZXR1cm4gc3BlY2lhbFt1Ml0gfHwgU3RyaW5nKHUyIHx8ICIiKS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL3MkLywgIiIpOwogIH07CiAgdmFyIGlzVW5kZWZpbmVkID0gZnVuY3Rpb24gaXNVbmRlZmluZWQyKHMyKSB7CiAgICByZXR1cm4gczIgPT09IHZvaWQgMDsKICB9OwogIHZhciBVID0gewogICAgczogcGFkU3RhcnQsCiAgICB6OiBwYWRab25lU3RyLAogICAgbTogbW9udGhEaWZmLAogICAgYTogYWJzRmxvb3IsCiAgICBwOiBwcmV0dHlVbml0LAogICAgdTogaXNVbmRlZmluZWQKICB9OwogIHZhciBMID0gImVuIjsKICB2YXIgTHMgPSB7fTsKICBMc1tMXSA9IGVuOwogIHZhciBJU19EQVlKUyA9ICIkaXNEYXlqc09iamVjdCI7CiAgdmFyIGlzRGF5anMgPSBmdW5jdGlvbiBpc0RheWpzMihkKSB7CiAgICByZXR1cm4gZCBpbnN0YW5jZW9mIERheWpzIHx8ICEhKGQgJiYgZFtJU19EQVlKU10pOwogIH07CiAgdmFyIHBhcnNlTG9jYWxlID0gZnVuY3Rpb24gcGFyc2VMb2NhbGUyKHByZXNldCwgb2JqZWN0LCBpc0xvY2FsKSB7CiAgICB2YXIgbDI7CiAgICBpZiAoIXByZXNldCkgcmV0dXJuIEw7CiAgICBpZiAodHlwZW9mIHByZXNldCA9PT0gInN0cmluZyIpIHsKICAgICAgdmFyIHByZXNldExvd2VyID0gcHJlc2V0LnRvTG93ZXJDYXNlKCk7CiAgICAgIGlmIChMc1twcmVzZXRMb3dlcl0pIHsKICAgICAgICBsMiA9IHByZXNldExvd2VyOwogICAgICB9CiAgICAgIGlmIChvYmplY3QpIHsKICAgICAgICBMc1twcmVzZXRMb3dlcl0gPSBvYmplY3Q7CiAgICAgICAgbDIgPSBwcmVzZXRMb3dlcjsKICAgICAgfQogICAgICB2YXIgcHJlc2V0U3BsaXQgPSBwcmVzZXQuc3BsaXQoIi0iKTsKICAgICAgaWYgKCFsMiAmJiBwcmVzZXRTcGxpdC5sZW5ndGggPiAxKSB7CiAgICAgICAgcmV0dXJuIHBhcnNlTG9jYWxlMihwcmVzZXRTcGxpdFswXSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhciBuYW1lID0gcHJlc2V0Lm5hbWU7CiAgICAgIExzW25hbWVdID0gcHJlc2V0OwogICAgICBsMiA9IG5hbWU7CiAgICB9CiAgICBpZiAoIWlzTG9jYWwgJiYgbDIpIEwgPSBsMjsKICAgIHJldHVybiBsMiB8fCAhaXNMb2NhbCAmJiBMOwogIH07CiAgdmFyIGRheWpzID0gZnVuY3Rpb24gZGF5anMyKGRhdGUsIGMyKSB7CiAgICBpZiAoaXNEYXlqcyhkYXRlKSkgewogICAgICByZXR1cm4gZGF0ZS5jbG9uZSgpOwogICAgfQogICAgdmFyIGNmZyA9IHR5cGVvZiBjMiA9PT0gIm9iamVjdCIgPyBjMiA6IHt9OwogICAgY2ZnLmRhdGUgPSBkYXRlOwogICAgY2ZnLmFyZ3MgPSBhcmd1bWVudHM7CiAgICByZXR1cm4gbmV3IERheWpzKGNmZyk7CiAgfTsKICB2YXIgd3JhcHBlciA9IGZ1bmN0aW9uIHdyYXBwZXIyKGRhdGUsIGluc3RhbmNlKSB7CiAgICByZXR1cm4gZGF5anMoZGF0ZSwgewogICAgICBsb2NhbGU6IGluc3RhbmNlLiRMLAogICAgICB1dGM6IGluc3RhbmNlLiR1LAogICAgICB4OiBpbnN0YW5jZS4keCwKICAgICAgJG9mZnNldDogaW5zdGFuY2UuJG9mZnNldAogICAgICAvLyB0b2RvOiByZWZhY3RvcjsgZG8gbm90IHVzZSB0aGlzLiRvZmZzZXQgaW4geW91IGNvZGUKICAgIH0pOwogIH07CiAgdmFyIFV0aWxzID0gVTsKICBVdGlscy5sID0gcGFyc2VMb2NhbGU7CiAgVXRpbHMuaSA9IGlzRGF5anM7CiAgVXRpbHMudyA9IHdyYXBwZXI7CiAgdmFyIHBhcnNlRGF0ZSA9IGZ1bmN0aW9uIHBhcnNlRGF0ZTIoY2ZnKSB7CiAgICB2YXIgZGF0ZSA9IGNmZy5kYXRlLCB1dGMgPSBjZmcudXRjOwogICAgaWYgKGRhdGUgPT09IG51bGwpIHJldHVybiAvKiBAX19QVVJFX18gKi8gbmV3IERhdGUoTmFOKTsKICAgIGlmIChVdGlscy51KGRhdGUpKSByZXR1cm4gLyogQF9fUFVSRV9fICovIG5ldyBEYXRlKCk7CiAgICBpZiAoZGF0ZSBpbnN0YW5jZW9mIERhdGUpIHJldHVybiBuZXcgRGF0ZShkYXRlKTsKICAgIGlmICh0eXBlb2YgZGF0ZSA9PT0gInN0cmluZyIgJiYgIS9aJC9pLnRlc3QoZGF0ZSkpIHsKICAgICAgdmFyIGQgPSBkYXRlLm1hdGNoKFJFR0VYX1BBUlNFKTsKICAgICAgaWYgKGQpIHsKICAgICAgICB2YXIgbTIgPSBkWzJdIC0gMSB8fCAwOwogICAgICAgIHZhciBtcyA9IChkWzddIHx8ICIwIikuc3Vic3RyaW5nKDAsIDMpOwogICAgICAgIGlmICh1dGMpIHsKICAgICAgICAgIHJldHVybiBuZXcgRGF0ZShEYXRlLlVUQyhkWzFdLCBtMiwgZFszXSB8fCAxLCBkWzRdIHx8IDAsIGRbNV0gfHwgMCwgZFs2XSB8fCAwLCBtcykpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IERhdGUoZFsxXSwgbTIsIGRbM10gfHwgMSwgZFs0XSB8fCAwLCBkWzVdIHx8IDAsIGRbNl0gfHwgMCwgbXMpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbmV3IERhdGUoZGF0ZSk7CiAgfTsKICB2YXIgRGF5anMgPSAvKiBAX19QVVJFX18gKi8gZnVuY3Rpb24oKSB7CiAgICBmdW5jdGlvbiBEYXlqczIoY2ZnKSB7CiAgICAgIHRoaXMuJEwgPSBwYXJzZUxvY2FsZShjZmcubG9jYWxlLCBudWxsLCB0cnVlKTsKICAgICAgdGhpcy5wYXJzZShjZmcpOwogICAgICB0aGlzLiR4ID0gdGhpcy4keCB8fCBjZmcueCB8fCB7fTsKICAgICAgdGhpc1tJU19EQVlKU10gPSB0cnVlOwogICAgfQogICAgdmFyIF9wcm90byA9IERheWpzMi5wcm90b3R5cGU7CiAgICBfcHJvdG8ucGFyc2UgPSBmdW5jdGlvbiBwYXJzZShjZmcpIHsKICAgICAgdGhpcy4kZCA9IHBhcnNlRGF0ZShjZmcpOwogICAgICB0aGlzLmluaXQoKTsKICAgIH07CiAgICBfcHJvdG8uaW5pdCA9IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHZhciAkZCA9IHRoaXMuJGQ7CiAgICAgIHRoaXMuJHkgPSAkZC5nZXRGdWxsWWVhcigpOwogICAgICB0aGlzLiRNID0gJGQuZ2V0TW9udGgoKTsKICAgICAgdGhpcy4kRCA9ICRkLmdldERhdGUoKTsKICAgICAgdGhpcy4kVyA9ICRkLmdldERheSgpOwogICAgICB0aGlzLiRIID0gJGQuZ2V0SG91cnMoKTsKICAgICAgdGhpcy4kbSA9ICRkLmdldE1pbnV0ZXMoKTsKICAgICAgdGhpcy4kcyA9ICRkLmdldFNlY29uZHMoKTsKICAgICAgdGhpcy4kbXMgPSAkZC5nZXRNaWxsaXNlY29uZHMoKTsKICAgIH07CiAgICBfcHJvdG8uJHV0aWxzID0gZnVuY3Rpb24gJHV0aWxzKCkgewogICAgICByZXR1cm4gVXRpbHM7CiAgICB9OwogICAgX3Byb3RvLmlzVmFsaWQgPSBmdW5jdGlvbiBpc1ZhbGlkMigpIHsKICAgICAgcmV0dXJuICEodGhpcy4kZC50b1N0cmluZygpID09PSBJTlZBTElEX0RBVEVfU1RSSU5HKTsKICAgIH07CiAgICBfcHJvdG8uaXNTYW1lID0gZnVuY3Rpb24gaXNTYW1lKHRoYXQsIHVuaXRzKSB7CiAgICAgIHZhciBvdGhlciA9IGRheWpzKHRoYXQpOwogICAgICByZXR1cm4gdGhpcy5zdGFydE9mKHVuaXRzKSA8PSBvdGhlciAmJiBvdGhlciA8PSB0aGlzLmVuZE9mKHVuaXRzKTsKICAgIH07CiAgICBfcHJvdG8uaXNBZnRlciA9IGZ1bmN0aW9uIGlzQWZ0ZXIodGhhdCwgdW5pdHMpIHsKICAgICAgcmV0dXJuIGRheWpzKHRoYXQpIDwgdGhpcy5zdGFydE9mKHVuaXRzKTsKICAgIH07CiAgICBfcHJvdG8uaXNCZWZvcmUgPSBmdW5jdGlvbiBpc0JlZm9yZSh0aGF0LCB1bml0cykgewogICAgICByZXR1cm4gdGhpcy5lbmRPZih1bml0cykgPCBkYXlqcyh0aGF0KTsKICAgIH07CiAgICBfcHJvdG8uJGcgPSBmdW5jdGlvbiAkZyhpbnB1dCwgZ2V0LCBzZXQpIHsKICAgICAgaWYgKFV0aWxzLnUoaW5wdXQpKSByZXR1cm4gdGhpc1tnZXRdOwogICAgICByZXR1cm4gdGhpcy5zZXQoc2V0LCBpbnB1dCk7CiAgICB9OwogICAgX3Byb3RvLnVuaXggPSBmdW5jdGlvbiB1bml4KCkgewogICAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLnZhbHVlT2YoKSAvIDFlMyk7CiAgICB9OwogICAgX3Byb3RvLnZhbHVlT2YgPSBmdW5jdGlvbiB2YWx1ZU9mKCkgewogICAgICByZXR1cm4gdGhpcy4kZC5nZXRUaW1lKCk7CiAgICB9OwogICAgX3Byb3RvLnN0YXJ0T2YgPSBmdW5jdGlvbiBzdGFydE9mKHVuaXRzLCBfc3RhcnRPZikgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwogICAgICB2YXIgaXNTdGFydE9mID0gIVV0aWxzLnUoX3N0YXJ0T2YpID8gX3N0YXJ0T2YgOiB0cnVlOwogICAgICB2YXIgdW5pdCA9IFV0aWxzLnAodW5pdHMpOwogICAgICB2YXIgaW5zdGFuY2VGYWN0b3J5ID0gZnVuY3Rpb24gaW5zdGFuY2VGYWN0b3J5MihkLCBtMikgewogICAgICAgIHZhciBpbnMgPSBVdGlscy53KF90aGlzLiR1ID8gRGF0ZS5VVEMoX3RoaXMuJHksIG0yLCBkKSA6IG5ldyBEYXRlKF90aGlzLiR5LCBtMiwgZCksIF90aGlzKTsKICAgICAgICByZXR1cm4gaXNTdGFydE9mID8gaW5zIDogaW5zLmVuZE9mKEQpOwogICAgICB9OwogICAgICB2YXIgaW5zdGFuY2VGYWN0b3J5U2V0ID0gZnVuY3Rpb24gaW5zdGFuY2VGYWN0b3J5U2V0MihtZXRob2QsIHNsaWNlKSB7CiAgICAgICAgdmFyIGFyZ3VtZW50U3RhcnQgPSBbMCwgMCwgMCwgMF07CiAgICAgICAgdmFyIGFyZ3VtZW50RW5kID0gWzIzLCA1OSwgNTksIDk5OV07CiAgICAgICAgcmV0dXJuIFV0aWxzLncoX3RoaXMudG9EYXRlKClbbWV0aG9kXS5hcHBseSgKICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcHJlZmVyLXNwcmVhZAogICAgICAgICAgX3RoaXMudG9EYXRlKCJzIiksCiAgICAgICAgICAoaXNTdGFydE9mID8gYXJndW1lbnRTdGFydCA6IGFyZ3VtZW50RW5kKS5zbGljZShzbGljZSkKICAgICAgICApLCBfdGhpcyk7CiAgICAgIH07CiAgICAgIHZhciAkVyA9IHRoaXMuJFcsICRNID0gdGhpcy4kTSwgJEQgPSB0aGlzLiREOwogICAgICB2YXIgdXRjUGFkID0gInNldCIgKyAodGhpcy4kdSA/ICJVVEMiIDogIiIpOwogICAgICBzd2l0Y2ggKHVuaXQpIHsKICAgICAgICBjYXNlIFk6CiAgICAgICAgICByZXR1cm4gaXNTdGFydE9mID8gaW5zdGFuY2VGYWN0b3J5KDEsIDApIDogaW5zdGFuY2VGYWN0b3J5KDMxLCAxMSk7CiAgICAgICAgY2FzZSBNOgogICAgICAgICAgcmV0dXJuIGlzU3RhcnRPZiA/IGluc3RhbmNlRmFjdG9yeSgxLCAkTSkgOiBpbnN0YW5jZUZhY3RvcnkoMCwgJE0gKyAxKTsKICAgICAgICBjYXNlIFc6IHsKICAgICAgICAgIHZhciB3ZWVrU3RhcnQgPSB0aGlzLiRsb2NhbGUoKS53ZWVrU3RhcnQgfHwgMDsKICAgICAgICAgIHZhciBnYXAgPSAoJFcgPCB3ZWVrU3RhcnQgPyAkVyArIDcgOiAkVykgLSB3ZWVrU3RhcnQ7CiAgICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5KGlzU3RhcnRPZiA/ICREIC0gZ2FwIDogJEQgKyAoNiAtIGdhcCksICRNKTsKICAgICAgICB9CiAgICAgICAgY2FzZSBEOgogICAgICAgIGNhc2UgREFURToKICAgICAgICAgIHJldHVybiBpbnN0YW5jZUZhY3RvcnlTZXQodXRjUGFkICsgIkhvdXJzIiwgMCk7CiAgICAgICAgY2FzZSBIOgogICAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCh1dGNQYWQgKyAiTWludXRlcyIsIDEpOwogICAgICAgIGNhc2UgTUlOOgogICAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCh1dGNQYWQgKyAiU2Vjb25kcyIsIDIpOwogICAgICAgIGNhc2UgUzoKICAgICAgICAgIHJldHVybiBpbnN0YW5jZUZhY3RvcnlTZXQodXRjUGFkICsgIk1pbGxpc2Vjb25kcyIsIDMpOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gdGhpcy5jbG9uZSgpOwogICAgICB9CiAgICB9OwogICAgX3Byb3RvLmVuZE9mID0gZnVuY3Rpb24gZW5kT2YoYXJnKSB7CiAgICAgIHJldHVybiB0aGlzLnN0YXJ0T2YoYXJnLCBmYWxzZSk7CiAgICB9OwogICAgX3Byb3RvLiRzZXQgPSBmdW5jdGlvbiAkc2V0KHVuaXRzLCBfaW50KSB7CiAgICAgIHZhciBfQyREJEMkREFURSRDJE0kQyRZJEM7CiAgICAgIHZhciB1bml0ID0gVXRpbHMucCh1bml0cyk7CiAgICAgIHZhciB1dGNQYWQgPSAic2V0IiArICh0aGlzLiR1ID8gIlVUQyIgOiAiIik7CiAgICAgIHZhciBuYW1lID0gKF9DJEQkQyREQVRFJEMkTSRDJFkkQyA9IHt9LCBfQyREJEMkREFURSRDJE0kQyRZJENbRF0gPSB1dGNQYWQgKyAiRGF0ZSIsIF9DJEQkQyREQVRFJEMkTSRDJFkkQ1tEQVRFXSA9IHV0Y1BhZCArICJEYXRlIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW01dID0gdXRjUGFkICsgIk1vbnRoIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW1ldID0gdXRjUGFkICsgIkZ1bGxZZWFyIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW0hdID0gdXRjUGFkICsgIkhvdXJzIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW01JTl0gPSB1dGNQYWQgKyAiTWludXRlcyIsIF9DJEQkQyREQVRFJEMkTSRDJFkkQ1tTXSA9IHV0Y1BhZCArICJTZWNvbmRzIiwgX0MkRCRDJERBVEUkQyRNJEMkWSRDW01TXSA9IHV0Y1BhZCArICJNaWxsaXNlY29uZHMiLCBfQyREJEMkREFURSRDJE0kQyRZJEMpW3VuaXRdOwogICAgICB2YXIgYXJnID0gdW5pdCA9PT0gRCA/IHRoaXMuJEQgKyAoX2ludCAtIHRoaXMuJFcpIDogX2ludDsKICAgICAgaWYgKHVuaXQgPT09IE0gfHwgdW5pdCA9PT0gWSkgewogICAgICAgIHZhciBkYXRlID0gdGhpcy5jbG9uZSgpLnNldChEQVRFLCAxKTsKICAgICAgICBkYXRlLiRkW25hbWVdKGFyZyk7CiAgICAgICAgZGF0ZS5pbml0KCk7CiAgICAgICAgdGhpcy4kZCA9IGRhdGUuc2V0KERBVEUsIE1hdGgubWluKHRoaXMuJEQsIGRhdGUuZGF5c0luTW9udGgoKSkpLiRkOwogICAgICB9IGVsc2UgaWYgKG5hbWUpIHRoaXMuJGRbbmFtZV0oYXJnKTsKICAgICAgdGhpcy5pbml0KCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKICAgIF9wcm90by5zZXQgPSBmdW5jdGlvbiBzZXQoc3RyaW5nLCBfaW50MikgewogICAgICByZXR1cm4gdGhpcy5jbG9uZSgpLiRzZXQoc3RyaW5nLCBfaW50Mik7CiAgICB9OwogICAgX3Byb3RvLmdldCA9IGZ1bmN0aW9uIGdldCh1bml0KSB7CiAgICAgIHJldHVybiB0aGlzW1V0aWxzLnAodW5pdCldKCk7CiAgICB9OwogICAgX3Byb3RvLmFkZCA9IGZ1bmN0aW9uIGFkZChudW1iZXIsIHVuaXRzKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzLCBfQyRNSU4kQyRIJEMkUyR1bml0OwogICAgICBudW1iZXIgPSBOdW1iZXIobnVtYmVyKTsKICAgICAgdmFyIHVuaXQgPSBVdGlscy5wKHVuaXRzKTsKICAgICAgdmFyIGluc3RhbmNlRmFjdG9yeVNldCA9IGZ1bmN0aW9uIGluc3RhbmNlRmFjdG9yeVNldDIobikgewogICAgICAgIHZhciBkID0gZGF5anMoX3RoaXMyKTsKICAgICAgICByZXR1cm4gVXRpbHMudyhkLmRhdGUoZC5kYXRlKCkgKyBNYXRoLnJvdW5kKG4gKiBudW1iZXIpKSwgX3RoaXMyKTsKICAgICAgfTsKICAgICAgaWYgKHVuaXQgPT09IE0pIHsKICAgICAgICByZXR1cm4gdGhpcy5zZXQoTSwgdGhpcy4kTSArIG51bWJlcik7CiAgICAgIH0KICAgICAgaWYgKHVuaXQgPT09IFkpIHsKICAgICAgICByZXR1cm4gdGhpcy5zZXQoWSwgdGhpcy4keSArIG51bWJlcik7CiAgICAgIH0KICAgICAgaWYgKHVuaXQgPT09IEQpIHsKICAgICAgICByZXR1cm4gaW5zdGFuY2VGYWN0b3J5U2V0KDEpOwogICAgICB9CiAgICAgIGlmICh1bml0ID09PSBXKSB7CiAgICAgICAgcmV0dXJuIGluc3RhbmNlRmFjdG9yeVNldCg3KTsKICAgICAgfQogICAgICB2YXIgc3RlcCA9IChfQyRNSU4kQyRIJEMkUyR1bml0ID0ge30sIF9DJE1JTiRDJEgkQyRTJHVuaXRbTUlOXSA9IE1JTExJU0VDT05EU19BX01JTlVURSwgX0MkTUlOJEMkSCRDJFMkdW5pdFtIXSA9IE1JTExJU0VDT05EU19BX0hPVVIsIF9DJE1JTiRDJEgkQyRTJHVuaXRbU10gPSBNSUxMSVNFQ09ORFNfQV9TRUNPTkQsIF9DJE1JTiRDJEgkQyRTJHVuaXQpW3VuaXRdIHx8IDE7CiAgICAgIHZhciBuZXh0VGltZVN0YW1wID0gdGhpcy4kZC5nZXRUaW1lKCkgKyBudW1iZXIgKiBzdGVwOwogICAgICByZXR1cm4gVXRpbHMudyhuZXh0VGltZVN0YW1wLCB0aGlzKTsKICAgIH07CiAgICBfcHJvdG8uc3VidHJhY3QgPSBmdW5jdGlvbiBzdWJ0cmFjdChudW1iZXIsIHN0cmluZykgewogICAgICByZXR1cm4gdGhpcy5hZGQobnVtYmVyICogLTEsIHN0cmluZyk7CiAgICB9OwogICAgX3Byb3RvLmZvcm1hdCA9IGZ1bmN0aW9uIGZvcm1hdChmb3JtYXRTdHIpIHsKICAgICAgdmFyIF90aGlzMyA9IHRoaXM7CiAgICAgIHZhciBsb2NhbGUgPSB0aGlzLiRsb2NhbGUoKTsKICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkgcmV0dXJuIGxvY2FsZS5pbnZhbGlkRGF0ZSB8fCBJTlZBTElEX0RBVEVfU1RSSU5HOwogICAgICB2YXIgc3RyID0gZm9ybWF0U3RyIHx8IEZPUk1BVF9ERUZBVUxUOwogICAgICB2YXIgem9uZVN0ciA9IFV0aWxzLnoodGhpcyk7CiAgICAgIHZhciAkSCA9IHRoaXMuJEgsICRtID0gdGhpcy4kbSwgJE0gPSB0aGlzLiRNOwogICAgICB2YXIgd2Vla2RheXMgPSBsb2NhbGUud2Vla2RheXMsIG1vbnRocyA9IGxvY2FsZS5tb250aHMsIG1lcmlkaWVtID0gbG9jYWxlLm1lcmlkaWVtOwogICAgICB2YXIgZ2V0U2hvcnQgPSBmdW5jdGlvbiBnZXRTaG9ydDIoYXJyLCBpbmRleCwgZnVsbCwgbGVuZ3RoKSB7CiAgICAgICAgcmV0dXJuIGFyciAmJiAoYXJyW2luZGV4XSB8fCBhcnIoX3RoaXMzLCBzdHIpKSB8fCBmdWxsW2luZGV4XS5zbGljZSgwLCBsZW5ndGgpOwogICAgICB9OwogICAgICB2YXIgZ2V0JEggPSBmdW5jdGlvbiBnZXQkSDIobnVtKSB7CiAgICAgICAgcmV0dXJuIFV0aWxzLnMoJEggJSAxMiB8fCAxMiwgbnVtLCAiMCIpOwogICAgICB9OwogICAgICB2YXIgbWVyaWRpZW1GdW5jID0gbWVyaWRpZW0gfHwgZnVuY3Rpb24oaG91ciwgbWludXRlLCBpc0xvd2VyY2FzZSkgewogICAgICAgIHZhciBtMiA9IGhvdXIgPCAxMiA/ICJBTSIgOiAiUE0iOwogICAgICAgIHJldHVybiBpc0xvd2VyY2FzZSA/IG0yLnRvTG93ZXJDYXNlKCkgOiBtMjsKICAgICAgfTsKICAgICAgdmFyIG1hdGNoZXMgPSBmdW5jdGlvbiBtYXRjaGVzMihtYXRjaCkgewogICAgICAgIHN3aXRjaCAobWF0Y2gpIHsKICAgICAgICAgIGNhc2UgIllZIjoKICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhfdGhpczMuJHkpLnNsaWNlKC0yKTsKICAgICAgICAgIGNhc2UgIllZWVkiOgogICAgICAgICAgICByZXR1cm4gVXRpbHMucyhfdGhpczMuJHksIDQsICIwIik7CiAgICAgICAgICBjYXNlICJNIjoKICAgICAgICAgICAgcmV0dXJuICRNICsgMTsKICAgICAgICAgIGNhc2UgIk1NIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoJE0gKyAxLCAyLCAiMCIpOwogICAgICAgICAgY2FzZSAiTU1NIjoKICAgICAgICAgICAgcmV0dXJuIGdldFNob3J0KGxvY2FsZS5tb250aHNTaG9ydCwgJE0sIG1vbnRocywgMyk7CiAgICAgICAgICBjYXNlICJNTU1NIjoKICAgICAgICAgICAgcmV0dXJuIGdldFNob3J0KG1vbnRocywgJE0pOwogICAgICAgICAgY2FzZSAiRCI6CiAgICAgICAgICAgIHJldHVybiBfdGhpczMuJEQ7CiAgICAgICAgICBjYXNlICJERCI6CiAgICAgICAgICAgIHJldHVybiBVdGlscy5zKF90aGlzMy4kRCwgMiwgIjAiKTsKICAgICAgICAgIGNhc2UgImQiOgogICAgICAgICAgICByZXR1cm4gU3RyaW5nKF90aGlzMy4kVyk7CiAgICAgICAgICBjYXNlICJkZCI6CiAgICAgICAgICAgIHJldHVybiBnZXRTaG9ydChsb2NhbGUud2Vla2RheXNNaW4sIF90aGlzMy4kVywgd2Vla2RheXMsIDIpOwogICAgICAgICAgY2FzZSAiZGRkIjoKICAgICAgICAgICAgcmV0dXJuIGdldFNob3J0KGxvY2FsZS53ZWVrZGF5c1Nob3J0LCBfdGhpczMuJFcsIHdlZWtkYXlzLCAzKTsKICAgICAgICAgIGNhc2UgImRkZGQiOgogICAgICAgICAgICByZXR1cm4gd2Vla2RheXNbX3RoaXMzLiRXXTsKICAgICAgICAgIGNhc2UgIkgiOgogICAgICAgICAgICByZXR1cm4gU3RyaW5nKCRIKTsKICAgICAgICAgIGNhc2UgIkhIIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoJEgsIDIsICIwIik7CiAgICAgICAgICBjYXNlICJoIjoKICAgICAgICAgICAgcmV0dXJuIGdldCRIKDEpOwogICAgICAgICAgY2FzZSAiaGgiOgogICAgICAgICAgICByZXR1cm4gZ2V0JEgoMik7CiAgICAgICAgICBjYXNlICJhIjoKICAgICAgICAgICAgcmV0dXJuIG1lcmlkaWVtRnVuYygkSCwgJG0sIHRydWUpOwogICAgICAgICAgY2FzZSAiQSI6CiAgICAgICAgICAgIHJldHVybiBtZXJpZGllbUZ1bmMoJEgsICRtLCBmYWxzZSk7CiAgICAgICAgICBjYXNlICJtIjoKICAgICAgICAgICAgcmV0dXJuIFN0cmluZygkbSk7CiAgICAgICAgICBjYXNlICJtbSI6CiAgICAgICAgICAgIHJldHVybiBVdGlscy5zKCRtLCAyLCAiMCIpOwogICAgICAgICAgY2FzZSAicyI6CiAgICAgICAgICAgIHJldHVybiBTdHJpbmcoX3RoaXMzLiRzKTsKICAgICAgICAgIGNhc2UgInNzIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoX3RoaXMzLiRzLCAyLCAiMCIpOwogICAgICAgICAgY2FzZSAiU1NTIjoKICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnMoX3RoaXMzLiRtcywgMywgIjAiKTsKICAgICAgICAgIGNhc2UgIloiOgogICAgICAgICAgICByZXR1cm4gem9uZVN0cjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH07CiAgICAgIHJldHVybiBzdHIucmVwbGFjZShSRUdFWF9GT1JNQVQsIGZ1bmN0aW9uKG1hdGNoLCAkMSkgewogICAgICAgIHJldHVybiAkMSB8fCBtYXRjaGVzKG1hdGNoKSB8fCB6b25lU3RyLnJlcGxhY2UoIjoiLCAiIik7CiAgICAgIH0pOwogICAgfTsKICAgIF9wcm90by51dGNPZmZzZXQgPSBmdW5jdGlvbiB1dGNPZmZzZXQoKSB7CiAgICAgIHJldHVybiAtTWF0aC5yb3VuZCh0aGlzLiRkLmdldFRpbWV6b25lT2Zmc2V0KCkgLyAxNSkgKiAxNTsKICAgIH07CiAgICBfcHJvdG8uZGlmZiA9IGZ1bmN0aW9uIGRpZmYoaW5wdXQsIHVuaXRzLCBfZmxvYXQpIHsKICAgICAgdmFyIF90aGlzNCA9IHRoaXM7CiAgICAgIHZhciB1bml0ID0gVXRpbHMucCh1bml0cyk7CiAgICAgIHZhciB0aGF0ID0gZGF5anMoaW5wdXQpOwogICAgICB2YXIgem9uZURlbHRhID0gKHRoYXQudXRjT2Zmc2V0KCkgLSB0aGlzLnV0Y09mZnNldCgpKSAqIE1JTExJU0VDT05EU19BX01JTlVURTsKICAgICAgdmFyIGRpZmYyID0gdGhpcyAtIHRoYXQ7CiAgICAgIHZhciBnZXRNb250aCA9IGZ1bmN0aW9uIGdldE1vbnRoMigpIHsKICAgICAgICByZXR1cm4gVXRpbHMubShfdGhpczQsIHRoYXQpOwogICAgICB9OwogICAgICB2YXIgcmVzdWx0OwogICAgICBzd2l0Y2ggKHVuaXQpIHsKICAgICAgICBjYXNlIFk6CiAgICAgICAgICByZXN1bHQgPSBnZXRNb250aCgpIC8gMTI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIE06CiAgICAgICAgICByZXN1bHQgPSBnZXRNb250aCgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBROgogICAgICAgICAgcmVzdWx0ID0gZ2V0TW9udGgoKSAvIDM7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFc6CiAgICAgICAgICByZXN1bHQgPSAoZGlmZjIgLSB6b25lRGVsdGEpIC8gTUlMTElTRUNPTkRTX0FfV0VFSzsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgRDoKICAgICAgICAgIHJlc3VsdCA9IChkaWZmMiAtIHpvbmVEZWx0YSkgLyBNSUxMSVNFQ09ORFNfQV9EQVk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIEg6CiAgICAgICAgICByZXN1bHQgPSBkaWZmMiAvIE1JTExJU0VDT05EU19BX0hPVVI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIE1JTjoKICAgICAgICAgIHJlc3VsdCA9IGRpZmYyIC8gTUlMTElTRUNPTkRTX0FfTUlOVVRFOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTOgogICAgICAgICAgcmVzdWx0ID0gZGlmZjIgLyBNSUxMSVNFQ09ORFNfQV9TRUNPTkQ7CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgcmVzdWx0ID0gZGlmZjI7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICByZXR1cm4gX2Zsb2F0ID8gcmVzdWx0IDogVXRpbHMuYShyZXN1bHQpOwogICAgfTsKICAgIF9wcm90by5kYXlzSW5Nb250aCA9IGZ1bmN0aW9uIGRheXNJbk1vbnRoKCkgewogICAgICByZXR1cm4gdGhpcy5lbmRPZihNKS4kRDsKICAgIH07CiAgICBfcHJvdG8uJGxvY2FsZSA9IGZ1bmN0aW9uICRsb2NhbGUoKSB7CiAgICAgIHJldHVybiBMc1t0aGlzLiRMXTsKICAgIH07CiAgICBfcHJvdG8ubG9jYWxlID0gZnVuY3Rpb24gbG9jYWxlKHByZXNldCwgb2JqZWN0KSB7CiAgICAgIGlmICghcHJlc2V0KSByZXR1cm4gdGhpcy4kTDsKICAgICAgdmFyIHRoYXQgPSB0aGlzLmNsb25lKCk7CiAgICAgIHZhciBuZXh0TG9jYWxlTmFtZSA9IHBhcnNlTG9jYWxlKHByZXNldCwgb2JqZWN0LCB0cnVlKTsKICAgICAgaWYgKG5leHRMb2NhbGVOYW1lKSB0aGF0LiRMID0gbmV4dExvY2FsZU5hbWU7CiAgICAgIHJldHVybiB0aGF0OwogICAgfTsKICAgIF9wcm90by5jbG9uZSA9IGZ1bmN0aW9uIGNsb25lKCkgewogICAgICByZXR1cm4gVXRpbHMudyh0aGlzLiRkLCB0aGlzKTsKICAgIH07CiAgICBfcHJvdG8udG9EYXRlID0gZnVuY3Rpb24gdG9EYXRlKCkgewogICAgICByZXR1cm4gbmV3IERhdGUodGhpcy52YWx1ZU9mKCkpOwogICAgfTsKICAgIF9wcm90by50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7CiAgICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMudG9JU09TdHJpbmcoKSA6IG51bGw7CiAgICB9OwogICAgX3Byb3RvLnRvSVNPU3RyaW5nID0gZnVuY3Rpb24gdG9JU09TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLiRkLnRvSVNPU3RyaW5nKCk7CiAgICB9OwogICAgX3Byb3RvLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLiRkLnRvVVRDU3RyaW5nKCk7CiAgICB9OwogICAgcmV0dXJuIERheWpzMjsKICB9KCk7CiAgdmFyIHByb3RvID0gRGF5anMucHJvdG90eXBlOwogIGRheWpzLnByb3RvdHlwZSA9IHByb3RvOwogIFtbIiRtcyIsIE1TXSwgWyIkcyIsIFNdLCBbIiRtIiwgTUlOXSwgWyIkSCIsIEhdLCBbIiRXIiwgRF0sIFsiJE0iLCBNXSwgWyIkeSIsIFldLCBbIiREIiwgREFURV1dLmZvckVhY2goZnVuY3Rpb24oZykgewogICAgcHJvdG9bZ1sxXV0gPSBmdW5jdGlvbihpbnB1dCkgewogICAgICByZXR1cm4gdGhpcy4kZyhpbnB1dCwgZ1swXSwgZ1sxXSk7CiAgICB9OwogIH0pOwogIGRheWpzLmV4dGVuZCA9IGZ1bmN0aW9uKHBsdWdpbiwgb3B0aW9uKSB7CiAgICBpZiAoIXBsdWdpbi4kaSkgewogICAgICBwbHVnaW4ob3B0aW9uLCBEYXlqcywgZGF5anMpOwogICAgICBwbHVnaW4uJGkgPSB0cnVlOwogICAgfQogICAgcmV0dXJuIGRheWpzOwogIH07CiAgZGF5anMubG9jYWxlID0gcGFyc2VMb2NhbGU7CiAgZGF5anMuaXNEYXlqcyA9IGlzRGF5anM7CiAgZGF5anMudW5peCA9IGZ1bmN0aW9uKHRpbWVzdGFtcCkgewogICAgcmV0dXJuIGRheWpzKHRpbWVzdGFtcCAqIDFlMyk7CiAgfTsKICBkYXlqcy5lbiA9IExzW0xdOwogIGRheWpzLkxzID0gTHM7CiAgZGF5anMucCA9IHt9OwogIHZhciBhZHZhbmNlZEZvcm1hdCA9IGZ1bmN0aW9uKG8sIGMyKSB7CiAgICB2YXIgcHJvdG8yID0gYzIucHJvdG90eXBlOwogICAgdmFyIG9sZEZvcm1hdCA9IHByb3RvMi5mb3JtYXQ7CiAgICBwcm90bzIuZm9ybWF0ID0gZnVuY3Rpb24oZm9ybWF0U3RyKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CiAgICAgIHZhciBsb2NhbGUgPSB0aGlzLiRsb2NhbGUoKTsKICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkgewogICAgICAgIHJldHVybiBvbGRGb3JtYXQuYmluZCh0aGlzKShmb3JtYXRTdHIpOwogICAgICB9CiAgICAgIHZhciB1dGlscyA9IHRoaXMuJHV0aWxzKCk7CiAgICAgIHZhciBzdHIgPSBmb3JtYXRTdHIgfHwgRk9STUFUX0RFRkFVTFQ7CiAgICAgIHZhciByZXN1bHQgPSBzdHIucmVwbGFjZSgvXFsoW15cXV0rKV18UXx3b3x3d3x3fFdXfFd8enp6fHp8Z2dnZ3xHR0dHfERvfFh8eHxrezEsMn18Uy9nLCBmdW5jdGlvbihtYXRjaCkgewogICAgICAgIHN3aXRjaCAobWF0Y2gpIHsKICAgICAgICAgIGNhc2UgIlEiOgogICAgICAgICAgICByZXR1cm4gTWF0aC5jZWlsKChfdGhpcy4kTSArIDEpIC8gMyk7CiAgICAgICAgICBjYXNlICJEbyI6CiAgICAgICAgICAgIHJldHVybiBsb2NhbGUub3JkaW5hbChfdGhpcy4kRCk7CiAgICAgICAgICBjYXNlICJnZ2dnIjoKICAgICAgICAgICAgcmV0dXJuIF90aGlzLndlZWtZZWFyKCk7CiAgICAgICAgICBjYXNlICJHR0dHIjoKICAgICAgICAgICAgcmV0dXJuIF90aGlzLmlzb1dlZWtZZWFyKCk7CiAgICAgICAgICBjYXNlICJ3byI6CiAgICAgICAgICAgIHJldHVybiBsb2NhbGUub3JkaW5hbChfdGhpcy53ZWVrKCksICJXIik7CiAgICAgICAgICBjYXNlICJ3IjoKICAgICAgICAgIGNhc2UgInd3IjoKICAgICAgICAgICAgcmV0dXJuIHV0aWxzLnMoX3RoaXMud2VlaygpLCBtYXRjaCA9PT0gInciID8gMSA6IDIsICIwIik7CiAgICAgICAgICBjYXNlICJXIjoKICAgICAgICAgIGNhc2UgIldXIjoKICAgICAgICAgICAgcmV0dXJuIHV0aWxzLnMoX3RoaXMuaXNvV2VlaygpLCBtYXRjaCA9PT0gIlciID8gMSA6IDIsICIwIik7CiAgICAgICAgICBjYXNlICJrIjoKICAgICAgICAgIGNhc2UgImtrIjoKICAgICAgICAgICAgcmV0dXJuIHV0aWxzLnMoU3RyaW5nKF90aGlzLiRIID09PSAwID8gMjQgOiBfdGhpcy4kSCksIG1hdGNoID09PSAiayIgPyAxIDogMiwgIjAiKTsKICAgICAgICAgIGNhc2UgIlgiOgogICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihfdGhpcy4kZC5nZXRUaW1lKCkgLyAxZTMpOwogICAgICAgICAgY2FzZSAieCI6CiAgICAgICAgICAgIHJldHVybiBfdGhpcy4kZC5nZXRUaW1lKCk7CiAgICAgICAgICBjYXNlICJ6IjoKICAgICAgICAgICAgcmV0dXJuICJbIiArIF90aGlzLm9mZnNldE5hbWUoKSArICJdIjsKICAgICAgICAgIGNhc2UgInp6eiI6CiAgICAgICAgICAgIHJldHVybiAiWyIgKyBfdGhpcy5vZmZzZXROYW1lKCJsb25nIikgKyAiXSI7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICByZXR1cm4gbWF0Y2g7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIG9sZEZvcm1hdC5iaW5kKHRoaXMpKHJlc3VsdCk7CiAgICB9OwogIH07CiAgdmFyIGlzb1dlZWtQcmV0dHlVbml0ID0gImlzb3dlZWsiOwogIHZhciBpc29XZWVrID0gZnVuY3Rpb24obywgYzIsIGQpIHsKICAgIHZhciBnZXRZZWFyRmlyc3RUaHVyc2RheSA9IGZ1bmN0aW9uIGdldFllYXJGaXJzdFRodXJzZGF5Mih5ZWFyLCBpc1V0YykgewogICAgICB2YXIgeWVhckZpcnN0RGF5ID0gKGlzVXRjID8gZC51dGMgOiBkKSgpLnllYXIoeWVhcikuc3RhcnRPZihZKTsKICAgICAgdmFyIGFkZERpZmZEYXlzID0gNCAtIHllYXJGaXJzdERheS5pc29XZWVrZGF5KCk7CiAgICAgIGlmICh5ZWFyRmlyc3REYXkuaXNvV2Vla2RheSgpID4gNCkgewogICAgICAgIGFkZERpZmZEYXlzICs9IDc7CiAgICAgIH0KICAgICAgcmV0dXJuIHllYXJGaXJzdERheS5hZGQoYWRkRGlmZkRheXMsIEQpOwogICAgfTsKICAgIHZhciBnZXRDdXJyZW50V2Vla1RodXJzZGF5ID0gZnVuY3Rpb24gZ2V0Q3VycmVudFdlZWtUaHVyc2RheTIoaW5zKSB7CiAgICAgIHJldHVybiBpbnMuYWRkKDQgLSBpbnMuaXNvV2Vla2RheSgpLCBEKTsKICAgIH07CiAgICB2YXIgcHJvdG8yID0gYzIucHJvdG90eXBlOwogICAgcHJvdG8yLmlzb1dlZWtZZWFyID0gZnVuY3Rpb24oKSB7CiAgICAgIHZhciBub3dXZWVrVGh1cnNkYXkgPSBnZXRDdXJyZW50V2Vla1RodXJzZGF5KHRoaXMpOwogICAgICByZXR1cm4gbm93V2Vla1RodXJzZGF5LnllYXIoKTsKICAgIH07CiAgICBwcm90bzIuaXNvV2VlayA9IGZ1bmN0aW9uKHdlZWspIHsKICAgICAgaWYgKCF0aGlzLiR1dGlscygpLnUod2VlaykpIHsKICAgICAgICByZXR1cm4gdGhpcy5hZGQoKHdlZWsgLSB0aGlzLmlzb1dlZWsoKSkgKiA3LCBEKTsKICAgICAgfQogICAgICB2YXIgbm93V2Vla1RodXJzZGF5ID0gZ2V0Q3VycmVudFdlZWtUaHVyc2RheSh0aGlzKTsKICAgICAgdmFyIGRpZmZXZWVrVGh1cnNkYXkgPSBnZXRZZWFyRmlyc3RUaHVyc2RheSh0aGlzLmlzb1dlZWtZZWFyKCksIHRoaXMuJHUpOwogICAgICByZXR1cm4gbm93V2Vla1RodXJzZGF5LmRpZmYoZGlmZldlZWtUaHVyc2RheSwgVykgKyAxOwogICAgfTsKICAgIHByb3RvMi5pc29XZWVrZGF5ID0gZnVuY3Rpb24od2VlaykgewogICAgICBpZiAoIXRoaXMuJHV0aWxzKCkudSh3ZWVrKSkgewogICAgICAgIHJldHVybiB0aGlzLmRheSh0aGlzLmRheSgpICUgNyA/IHdlZWsgOiB3ZWVrIC0gNyk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuZGF5KCkgfHwgNzsKICAgIH07CiAgICB2YXIgb2xkU3RhcnRPZiA9IHByb3RvMi5zdGFydE9mOwogICAgcHJvdG8yLnN0YXJ0T2YgPSBmdW5jdGlvbih1bml0cywgc3RhcnRPZikgewogICAgICB2YXIgdXRpbHMgPSB0aGlzLiR1dGlscygpOwogICAgICB2YXIgaXNTdGFydE9mID0gIXV0aWxzLnUoc3RhcnRPZikgPyBzdGFydE9mIDogdHJ1ZTsKICAgICAgdmFyIHVuaXQgPSB1dGlscy5wKHVuaXRzKTsKICAgICAgaWYgKHVuaXQgPT09IGlzb1dlZWtQcmV0dHlVbml0KSB7CiAgICAgICAgcmV0dXJuIGlzU3RhcnRPZiA/IHRoaXMuZGF0ZSh0aGlzLmRhdGUoKSAtICh0aGlzLmlzb1dlZWtkYXkoKSAtIDEpKS5zdGFydE9mKCJkYXkiKSA6IHRoaXMuZGF0ZSh0aGlzLmRhdGUoKSAtIDEgLSAodGhpcy5pc29XZWVrZGF5KCkgLSAxKSArIDcpLmVuZE9mKCJkYXkiKTsKICAgICAgfQogICAgICByZXR1cm4gb2xkU3RhcnRPZi5iaW5kKHRoaXMpKHVuaXRzLCBzdGFydE9mKTsKICAgIH07CiAgfTsKICBkYXlqcy5leHRlbmQoaXNvV2Vlayk7CiAgZGF5anMuZXh0ZW5kKGFkdmFuY2VkRm9ybWF0KTsKICBjb25zdCBGT1JNQVRfSVNPX1dFRUtfWUVBUl9XRUVLID0gIkdHR0ctW1ddV1ciOwogIGNvbnN0IF9UZW1wb3JhbENhY2hlID0gY2xhc3MgX1RlbXBvcmFsQ2FjaGUgewogICAgY29uc3RydWN0b3IoKSB7CiAgICAgIHRoaXMueWVhck1vbnRoRGF5Q2FjaGUgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLnllYXJXZWVrQ2FjaGUgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLnllYXJNb250aENhY2hlID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgdGhpcy55ZWFyQ2FjaGUgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgfQogICAgZ2V0WWVhck1vbnRoRGF5KHMyKSB7CiAgICAgIGlmICghdGhpcy55ZWFyTW9udGhEYXlDYWNoZS5oYXMoczIpKSB7CiAgICAgICAgdGhpcy55ZWFyTW9udGhEYXlDYWNoZS5zZXQoczIsIFllYXJNb250aERheUNsYXNzLnBhcnNlKHMyLCB0aGlzKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMueWVhck1vbnRoRGF5Q2FjaGUuZ2V0KHMyKTsKICAgIH0KICAgIGdldFllYXJNb250aChzMikgewogICAgICBpZiAoIXRoaXMueWVhck1vbnRoQ2FjaGUuaGFzKHMyKSkgewogICAgICAgIHRoaXMueWVhck1vbnRoQ2FjaGUuc2V0KHMyLCBZZWFyTW9udGhDbGFzcy5wYXJzZShzMiwgdGhpcykpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnllYXJNb250aENhY2hlLmdldChzMik7CiAgICB9CiAgICBnZXRZZWFyV2VlayhzMikgewogICAgICBpZiAoIXRoaXMueWVhcldlZWtDYWNoZS5oYXMoczIpKSB7CiAgICAgICAgdGhpcy55ZWFyV2Vla0NhY2hlLnNldChzMiwgWWVhcldlZWtDbGFzcy5wYXJzZShzMiwgdGhpcykpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnllYXJXZWVrQ2FjaGUuZ2V0KHMyKTsKICAgIH0KICAgIGdldFllYXIoczIpIHsKICAgICAgaWYgKCF0aGlzLnllYXJDYWNoZS5oYXMoczIpKSB7CiAgICAgICAgdGhpcy55ZWFyQ2FjaGUuc2V0KHMyLCBZZWFyQ2xhc3MucGFyc2UoczIsIHRoaXMpKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy55ZWFyQ2FjaGUuZ2V0KHMyKTsKICAgIH0KICAgIHN0YXRpYyBnZXRJbnN0YW5jZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuaW5zdGFuY2U7CiAgICB9CiAgfTsKICBfVGVtcG9yYWxDYWNoZS5pbnN0YW5jZSA9IG5ldyBfVGVtcG9yYWxDYWNoZSgpOwogIGxldCBUZW1wb3JhbENhY2hlID0gX1RlbXBvcmFsQ2FjaGU7CiAgY2xhc3MgWWVhck1vbnRoRGF5Q2xhc3MgewogICAgY29uc3RydWN0b3IoeWVhck51bWJlciwgbW9udGhOdW1iZXIsIGRheU51bWJlciwgY2FjaGUpIHsKICAgICAgdGhpcy55ZWFyTnVtYmVyID0geWVhck51bWJlcjsKICAgICAgdGhpcy5tb250aE51bWJlciA9IG1vbnRoTnVtYmVyOwogICAgICB0aGlzLmRheU51bWJlciA9IGRheU51bWJlcjsKICAgICAgdGhpcy5jYWNoZSA9IGNhY2hlOwogICAgICB0aGlzLnR5cGUgPSAiWWVhck1vbnRoRGF5IjsKICAgICAgdGhpcy5kYXRlID0gbmV3IERhdGUodGhpcy55ZWFyTnVtYmVyLCB0aGlzLm1vbnRoTnVtYmVyIC0gMSwgdGhpcy5kYXlOdW1iZXIpOwogICAgICB0aGlzLmRheWpzID0gZGF5anModGhpcy5kYXRlKTsKICAgICAgdGhpcy5kYXRlU3RyaW5nID0gdGhpcy50b1N0cmluZygpOwogICAgfQogICAgZ2V0IHRleHQoKSB7CiAgICAgIHJldHVybiB0aGlzLmRheWpzLmZvcm1hdCgiWVlZWS1NTS1ERCIpOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLnRleHQ7CiAgICB9CiAgICBlbmdsaXNoTmFtZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZGF5anMuZm9ybWF0KCJkZGRkLCBNTU1NIEQsIFlZWVkiKTsKICAgIH0KICAgIGdldCBmaXJzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICBnZXQgbGFzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICBnZXQgeWVhcigpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhcihgJHt0aGlzLnllYXJOdW1iZXJ9YCk7CiAgICB9CiAgICBnZXQgbW9udGgoKSB7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aCh0aGlzLmRheWpzLmZvcm1hdCgiWVlZWS1NTSIpKTsKICAgIH0KICAgIGdldCB3ZWVrKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyV2Vlayh0aGlzLmRheWpzLmZvcm1hdChGT1JNQVRfSVNPX1dFRUtfWUVBUl9XRUVLKSk7CiAgICB9CiAgICBhZGREYXlzKGRheXMpIHsKICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuZGF5anMuYWRkKGRheXMsICJkYXkiKTsKICAgICAgY29uc3QgczIgPSBkYXRlLmZvcm1hdCgiWVlZWS1NTS1ERCIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGhEYXkoczIpOwogICAgfQogICAgbWludXMob3RoZXIpIHsKICAgICAgcmV0dXJuIHRoaXMuZGF5anMuZGlmZihvdGhlci5kYXlqcywgImRheSIpOwogICAgfQogICAgc3RhdGljIHBhcnNlKHMyLCBjYWNoZSkgewogICAgICBjb25zdCBbeWVhciwgbW9udGgsIGRheV0gPSBzMi5zcGxpdCgiLSIpLm1hcCgoczIyKSA9PiBwYXJzZUludChzMjIsIDEwKSk7CiAgICAgIHJldHVybiBuZXcgWWVhck1vbnRoRGF5Q2xhc3MoeWVhciwgbW9udGgsIGRheSwgY2FjaGUpOwogICAgfQogIH0KICBjbGFzcyBZZWFyV2Vla0NsYXNzIHsKICAgIGNvbnN0cnVjdG9yKGlzb1llYXJOdW1iZXIsIGlzb1dlZWtOdW1iZXIsIGNhY2hlKSB7CiAgICAgIHRoaXMuaXNvWWVhck51bWJlciA9IGlzb1llYXJOdW1iZXI7CiAgICAgIHRoaXMuaXNvV2Vla051bWJlciA9IGlzb1dlZWtOdW1iZXI7CiAgICAgIHRoaXMuY2FjaGUgPSBjYWNoZTsKICAgICAgdGhpcy50eXBlID0gIlllYXJXZWVrIjsKICAgICAgdGhpcy5kYXRlU3RyaW5nID0gdGhpcy50b1N0cmluZygpOwogICAgfQogICAgZ2V0IHRleHQoKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmZvcm1hdChGT1JNQVRfSVNPX1dFRUtfWUVBUl9XRUVLKTsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy50ZXh0OwogICAgfQogICAgZW5nbGlzaE5hbWUoKSB7CiAgICAgIHJldHVybiBgV2VlayAke3RoaXMuaXNvV2Vla051bWJlcn0sICR7dGhpcy5pc29ZZWFyTnVtYmVyfWA7CiAgICB9CiAgICBnZXQgZmlyc3REYXkoKSB7CiAgICAgIGNvbnN0IGZpcnN0RGF5ID0gZGF5anMoKS55ZWFyKHRoaXMuaXNvWWVhck51bWJlcikubW9udGgoMSkuZGF0ZSg0KS5pc29XZWVrKHRoaXMuaXNvV2Vla051bWJlcikuc3RhcnRPZigiaXNvV2VlayIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGhEYXkoZmlyc3REYXkuZm9ybWF0KCJZWVlZLU1NLUREIikpOwogICAgfQogICAgZ2V0IGxhc3REYXkoKSB7CiAgICAgIGNvbnN0IGZpcnN0RGF5ID0gZGF5anMoKS55ZWFyKHRoaXMuaXNvWWVhck51bWJlcikuc3RhcnRPZigieWVhciIpLmFkZCgodGhpcy5pc29XZWVrTnVtYmVyIC0gMSkgKiA3LCAiZGF5Iikuc3RhcnRPZigid2VlayIpLmFkZCgxLCAiZGF5Iik7CiAgICAgIGNvbnN0IGxhc3REYXkgPSBmaXJzdERheS5hZGQoNiwgImRheSIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGhEYXkobGFzdERheS5mb3JtYXQoIllZWVktTU0tREQiKSk7CiAgICB9CiAgICBnZXQgeWVhcigpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhcihgJHt0aGlzLmlzb1llYXJOdW1iZXJ9YCk7CiAgICB9CiAgICBhZGRXZWVrcyh3ZWVrcykgewogICAgICBjb25zdCBkYXRlID0gdGhpcy5maXJzdERheS5kYXlqcy5hZGQod2Vla3MsICJ3ZWVrIik7CiAgICAgIGNvbnN0IHMyID0gZGF0ZS5mb3JtYXQoRk9STUFUX0lTT19XRUVLX1lFQVJfV0VFSyk7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJXZWVrKHMyKTsKICAgIH0KICAgIG1pbnVzKG90aGVyKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmRpZmYob3RoZXIuZmlyc3REYXkuZGF5anMsICJ3ZWVrIik7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UoczIsIGNhY2hlKSB7CiAgICAgIGNvbnN0IFt5ZWFyLCB3ZWVrXSA9IHMyLnNwbGl0KCItVyIpLm1hcCgoczIyKSA9PiBwYXJzZUludChzMjIsIDEwKSk7CiAgICAgIHJldHVybiBuZXcgWWVhcldlZWtDbGFzcyh5ZWFyLCB3ZWVrLCBjYWNoZSk7CiAgICB9CiAgfQogIGNsYXNzIFllYXJNb250aENsYXNzIHsKICAgIGNvbnN0cnVjdG9yKHllYXJOdW1iZXIsIG1vbnRoTnVtYmVyLCBjYWNoZSkgewogICAgICB0aGlzLnllYXJOdW1iZXIgPSB5ZWFyTnVtYmVyOwogICAgICB0aGlzLm1vbnRoTnVtYmVyID0gbW9udGhOdW1iZXI7CiAgICAgIHRoaXMuY2FjaGUgPSBjYWNoZTsKICAgICAgdGhpcy50eXBlID0gIlllYXJNb250aCI7CiAgICAgIHRoaXMuZGF0ZVN0cmluZyA9IHRoaXMudG9TdHJpbmcoKTsKICAgIH0KICAgIGdldCB0ZXh0KCkgewogICAgICByZXR1cm4gdGhpcy5maXJzdERheS5kYXlqcy5mb3JtYXQoIllZWVktTU0iKTsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy50ZXh0OwogICAgfQogICAgZW5nbGlzaE5hbWUoKSB7CiAgICAgIHJldHVybiBgJHttb250aE5hbWUodGhpcy5tb250aE51bWJlcil9ICR7dGhpcy55ZWFyTnVtYmVyfWA7CiAgICB9CiAgICBnZXQgZmlyc3REYXkoKSB7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aERheShkYXlqcyhgJHt0aGlzLnllYXJOdW1iZXJ9LSR7dGhpcy5tb250aE51bWJlcn0tMDFgKS5mb3JtYXQoIllZWVktTU0tREQiKSk7CiAgICB9CiAgICBnZXQgbGFzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoRGF5KAogICAgICAgIGRheWpzKGAke3RoaXMueWVhck51bWJlcn0tJHt0aGlzLm1vbnRoTnVtYmVyfS0wMWApLmVuZE9mKCJtb250aCIpLmZvcm1hdCgiWVlZWS1NTS1ERCIpCiAgICAgICk7CiAgICB9CiAgICBnZXQgeWVhcigpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhcihgJHt0aGlzLnllYXJOdW1iZXJ9YCk7CiAgICB9CiAgICBhZGRNb250aHMobW9udGhzKSB7CiAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLmZpcnN0RGF5LmRheWpzLmFkZChtb250aHMsICJtb250aCIpOwogICAgICBjb25zdCBzMiA9IGRhdGUuZm9ybWF0KCJZWVlZLU1NIik7CiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldFllYXJNb250aChzMik7CiAgICB9CiAgICBtaW51cyhvdGhlcikgewogICAgICByZXR1cm4gdGhpcy5maXJzdERheS5kYXlqcy5kaWZmKG90aGVyLmZpcnN0RGF5LmRheWpzLCAibW9udGgiKTsKICAgIH0KICAgIHN0YXRpYyBwYXJzZShzMiwgY2FjaGUpIHsKICAgICAgY29uc3QgW3llYXIsIG1vbnRoXSA9IHMyLnNwbGl0KCItIikubWFwKChzMjIpID0+IHBhcnNlSW50KHMyMiwgMTApKTsKICAgICAgcmV0dXJuIG5ldyBZZWFyTW9udGhDbGFzcyh5ZWFyLCBtb250aCwgY2FjaGUpOwogICAgfQogIH0KICBjbGFzcyBZZWFyQ2xhc3MgewogICAgY29uc3RydWN0b3IoeWVhciwgY2FjaGUpIHsKICAgICAgdGhpcy55ZWFyID0geWVhcjsKICAgICAgdGhpcy5jYWNoZSA9IGNhY2hlOwogICAgICB0aGlzLnR5cGUgPSAiWWVhciI7CiAgICAgIHRoaXMuZGF0ZVN0cmluZyA9IHRoaXMudG9TdHJpbmcoKTsKICAgIH0KICAgIGdldCB0ZXh0KCkgewogICAgICByZXR1cm4gdGhpcy5maXJzdERheS5kYXlqcy5mb3JtYXQoIllZWVkiKTsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy50ZXh0OwogICAgfQogICAgZW5nbGlzaE5hbWUoKSB7CiAgICAgIHJldHVybiB0aGlzLnllYXIudG9TdHJpbmcoKTsKICAgIH0KICAgIGdldCBmaXJzdE1vbnRoKCkgewogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyTW9udGgoYCR7dGhpcy55ZWFyfS0wMWApOwogICAgfQogICAgZ2V0IGxhc3RNb250aCgpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0WWVhck1vbnRoKGAke3RoaXMueWVhcn0tMTJgKTsKICAgIH0KICAgIGdldCBmaXJzdERheSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZmlyc3RNb250aC5maXJzdERheTsKICAgIH0KICAgIGdldCBsYXN0RGF5KCkgewogICAgICByZXR1cm4gdGhpcy5sYXN0TW9udGgubGFzdERheTsKICAgIH0KICAgIGFkZFllYXJzKHllYXJzKSB7CiAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLmZpcnN0RGF5LmRheWpzLmFkZCh5ZWFycywgInllYXIiKTsKICAgICAgY29uc3QgczIgPSBkYXRlLmZvcm1hdCgiWVlZWSIpOwogICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXRZZWFyKHMyKTsKICAgIH0KICAgIG1pbnVzKG90aGVyKSB7CiAgICAgIHJldHVybiB0aGlzLmZpcnN0RGF5LmRheWpzLmRpZmYob3RoZXIuZmlyc3REYXkuZGF5anMsICJ5ZWFyIik7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UoczIsIGNhY2hlKSB7CiAgICAgIGNvbnN0IHllYXIgPSBwYXJzZUludChzMiwgMTApOwogICAgICByZXR1cm4gbmV3IFllYXJDbGFzcyh5ZWFyLCBjYWNoZSk7CiAgICB9CiAgfQogIGZ1bmN0aW9uIG1vbnRoTmFtZShtb250aCkgewogICAgcmV0dXJuIGRheWpzKCkubW9udGgobW9udGggLSAxKS5mb3JtYXQoIk1NTU0iKTsKICB9CiAgZnVuY3Rpb24gdG9UZW1wb3JhbCh0ZW1wb3JhbENsYXNzKSB7CiAgICBzd2l0Y2ggKHRlbXBvcmFsQ2xhc3MudHlwZSkgewogICAgICBjYXNlICJZZWFyTW9udGhEYXkiOgogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiAiWWVhck1vbnRoRGF5IiwKICAgICAgICAgIHllYXJOdW1iZXI6IHRlbXBvcmFsQ2xhc3MueWVhck51bWJlciwKICAgICAgICAgIG1vbnRoTnVtYmVyOiB0ZW1wb3JhbENsYXNzLm1vbnRoTnVtYmVyLAogICAgICAgICAgZGF5TnVtYmVyOiB0ZW1wb3JhbENsYXNzLmRheU51bWJlciwKICAgICAgICAgIGRhdGVTdHJpbmc6IHRlbXBvcmFsQ2xhc3MuZGF0ZVN0cmluZwogICAgICAgIH07CiAgICAgIGNhc2UgIlllYXJXZWVrIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogIlllYXJXZWVrIiwKICAgICAgICAgIGlzb1llYXJOdW1iZXI6IHRlbXBvcmFsQ2xhc3MuaXNvWWVhck51bWJlciwKICAgICAgICAgIGlzb1dlZWtOdW1iZXI6IHRlbXBvcmFsQ2xhc3MuaXNvV2Vla051bWJlciwKICAgICAgICAgIGRhdGVTdHJpbmc6IHRlbXBvcmFsQ2xhc3MuZGF0ZVN0cmluZwogICAgICAgIH07CiAgICAgIGNhc2UgIlllYXJNb250aCI6CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHR5cGU6ICJZZWFyTW9udGgiLAogICAgICAgICAgeWVhck51bWJlcjogdGVtcG9yYWxDbGFzcy55ZWFyTnVtYmVyLAogICAgICAgICAgbW9udGhOdW1iZXI6IHRlbXBvcmFsQ2xhc3MubW9udGhOdW1iZXIsCiAgICAgICAgICBkYXRlU3RyaW5nOiB0ZW1wb3JhbENsYXNzLmRhdGVTdHJpbmcKICAgICAgICB9OwogICAgICBjYXNlICJZZWFyIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogIlllYXIiLAogICAgICAgICAgeWVhcjogdGVtcG9yYWxDbGFzcy55ZWFyLAogICAgICAgICAgZGF0ZVN0cmluZzogdGVtcG9yYWxDbGFzcy5kYXRlU3RyaW5nCiAgICAgICAgfTsKICAgIH0KICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVBbGxEYXlzSW5SYW5nZShzdGFydCwgZW5kKSB7CiAgICBjb25zdCBkYXlzID0gW107CiAgICBjb25zdCBkYXlzSW5CZXR3ZWVuID0gZW5kLm1pbnVzKHN0YXJ0KTsKICAgIGZvciAobGV0IGkyID0gMDsgaTIgPD0gZGF5c0luQmV0d2VlbjsgaTIrKykgewogICAgICBkYXlzLnB1c2goc3RhcnQuYWRkRGF5cyhpMikpOwogICAgfQogICAgcmV0dXJuIGRheXM7CiAgfQogIGZ1bmN0aW9uIGdlbmVyYXRlQWxsV2Vla3NJblJhbmdlKHN0YXJ0LCBlbmQpIHsKICAgIGNvbnN0IHdlZWtzID0gW107CiAgICBjb25zdCB3ZWVrc0luQmV0d2VlbiA9IGVuZC5taW51cyhzdGFydCk7CiAgICBmb3IgKGxldCBpMiA9IDA7IGkyIDw9IHdlZWtzSW5CZXR3ZWVuOyBpMisrKSB7CiAgICAgIHdlZWtzLnB1c2goc3RhcnQuYWRkV2Vla3MoaTIpKTsKICAgIH0KICAgIHJldHVybiB3ZWVrczsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVBbGxNb250aHNJblJhbmdlKHN0YXJ0LCBlbmQpIHsKICAgIGNvbnN0IG1vbnRocyA9IFtdOwogICAgY29uc3QgbW9udGhzSW5CZXR3ZWVuID0gZW5kLm1pbnVzKHN0YXJ0KTsKICAgIGZvciAobGV0IGkyID0gMDsgaTIgPD0gbW9udGhzSW5CZXR3ZWVuOyBpMisrKSB7CiAgICAgIG1vbnRocy5wdXNoKHN0YXJ0LmFkZE1vbnRocyhpMikpOwogICAgfQogICAgcmV0dXJuIG1vbnRoczsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVBbGxZZWFyc0luUmFuZ2Uoc3RhcnQsIGVuZCkgewogICAgY29uc3QgeWVhcnMgPSBbXTsKICAgIGNvbnN0IHllYXJzSW5CZXR3ZWVuID0gZW5kLm1pbnVzKHN0YXJ0KTsKICAgIGZvciAobGV0IGkyID0gMDsgaTIgPD0geWVhcnNJbkJldHdlZW47IGkyKyspIHsKICAgICAgeWVhcnMucHVzaChzdGFydC5hZGRZZWFycyhpMikpOwogICAgfQogICAgcmV0dXJuIHllYXJzOwogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZUFsbEluUmFuZ2Uoc3RhcnQsIGVuZCkgewogICAgaWYgKHN0YXJ0ID09PSBudWxsIHx8IGVuZCA9PT0gbnVsbCkgewogICAgICByZXR1cm4gW107CiAgICB9CiAgICBpZiAoc3RhcnQgaW5zdGFuY2VvZiBZZWFyTW9udGhEYXlDbGFzcyAmJiBlbmQgaW5zdGFuY2VvZiBZZWFyTW9udGhEYXlDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxEYXlzSW5SYW5nZShzdGFydCwgZW5kKTsKICAgIH0KICAgIGlmIChzdGFydCBpbnN0YW5jZW9mIFllYXJXZWVrQ2xhc3MgJiYgZW5kIGluc3RhbmNlb2YgWWVhcldlZWtDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxXZWVrc0luUmFuZ2Uoc3RhcnQsIGVuZCk7CiAgICB9CiAgICBpZiAoc3RhcnQgaW5zdGFuY2VvZiBZZWFyTW9udGhDbGFzcyAmJiBlbmQgaW5zdGFuY2VvZiBZZWFyTW9udGhDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxNb250aHNJblJhbmdlKHN0YXJ0LCBlbmQpOwogICAgfQogICAgaWYgKHN0YXJ0IGluc3RhbmNlb2YgWWVhckNsYXNzICYmIGVuZCBpbnN0YW5jZW9mIFllYXJDbGFzcykgewogICAgICByZXR1cm4gZ2VuZXJhdGVBbGxZZWFyc0luUmFuZ2Uoc3RhcnQsIGVuZCk7CiAgICB9CiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgYXJndW1lbnRzOiBzdGFydCBhbmQgZW5kIG11c3QgYmUgb2YgdGhlIHNhbWUgdHlwZTogJHtzdGFydH0sICR7ZW5kfWApOwogIH0KICBmdW5jdGlvbiBtaW51c1RlbXBvcmFsKGEyLCBiKSB7CiAgICBpZiAoYTIgaW5zdGFuY2VvZiBZZWFyTW9udGhEYXlDbGFzcyAmJiBiIGluc3RhbmNlb2YgWWVhck1vbnRoRGF5Q2xhc3MpIHsKICAgICAgcmV0dXJuIGEyLm1pbnVzKGIpOwogICAgfQogICAgaWYgKGEyIGluc3RhbmNlb2YgWWVhcldlZWtDbGFzcyAmJiBiIGluc3RhbmNlb2YgWWVhcldlZWtDbGFzcykgewogICAgICByZXR1cm4gYTIubWludXMoYik7CiAgICB9CiAgICBpZiAoYTIgaW5zdGFuY2VvZiBZZWFyTW9udGhDbGFzcyAmJiBiIGluc3RhbmNlb2YgWWVhck1vbnRoQ2xhc3MpIHsKICAgICAgcmV0dXJuIGEyLm1pbnVzKGIpOwogICAgfQogICAgaWYgKGEyIGluc3RhbmNlb2YgWWVhckNsYXNzICYmIGIgaW5zdGFuY2VvZiBZZWFyQ2xhc3MpIHsKICAgICAgcmV0dXJuIGEyLm1pbnVzKGIpOwogICAgfQogICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgY29tcGFyZSAke2EyfSBhbmQgJHtifWApOwogIH0KICBmdW5jdGlvbiBjb21wYXJlVGVtcG9yYWwoYTIsIGIpIHsKICAgIGlmIChhMiA9PT0gbnVsbCkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIGlmIChiID09PSBudWxsKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGNvbnN0IGRpZmYgPSBtaW51c1RlbXBvcmFsKGEyLCBiKTsKICAgIGlmIChkaWZmIDwgMCkgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICBpZiAoZGlmZiA+IDApIHsKICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICByZXR1cm4gMDsKICB9CiAgZnVuY3Rpb24gZ2V0TWluTWF4VGVtcG9yYWwodmFsdWVzKSB7CiAgICBsZXQgbWluID0gbnVsbDsKICAgIGxldCBtYXggPSBudWxsOwogICAgZm9yIChjb25zdCB2YWx1ZSBvZiB2YWx1ZXMpIHsKICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKG1pbiA9PT0gbnVsbCB8fCBjb21wYXJlVGVtcG9yYWwodmFsdWUsIG1pbikgPCAwKSB7CiAgICAgICAgbWluID0gdmFsdWU7CiAgICAgIH0KICAgICAgaWYgKG1heCA9PT0gbnVsbCB8fCBjb21wYXJlVGVtcG9yYWwodmFsdWUsIG1heCkgPiAwKSB7CiAgICAgICAgbWF4ID0gdmFsdWU7CiAgICAgIH0KICAgIH0KICAgIGlmIChtaW4gPT09IG51bGwgfHwgbWF4ID09PSBudWxsKSB7CiAgICAgIHJldHVybiB7IG1pbjogbnVsbCwgbWF4OiBudWxsIH07CiAgICB9CiAgICByZXR1cm4geyBtaW4sIG1heCB9OwogIH0KICBmdW5jdGlvbiBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKGRhdGUsIGdyYW51bGFyaXR5KSB7CiAgICBjb25zdCBjYWNoZSA9IFRlbXBvcmFsQ2FjaGUuZ2V0SW5zdGFuY2UoKTsKICAgIGNvbnN0IGRheSA9IGNhY2hlLmdldFllYXJNb250aERheShkYXRlKTsKICAgIHN3aXRjaCAoZ3JhbnVsYXJpdHkpIHsKICAgICAgY2FzZSAiZGF5IjoKICAgICAgICByZXR1cm4gZGF5OwogICAgICBjYXNlICJ3ZWVrIjoKICAgICAgICByZXR1cm4gZGF5LndlZWs7CiAgICAgIGNhc2UgIm1vbnRoIjoKICAgICAgICByZXR1cm4gZGF5Lm1vbnRoOwogICAgICBjYXNlICJ5ZWFyIjoKICAgICAgICByZXR1cm4gZGF5LnllYXI7CiAgICB9CiAgfQogIGZ1bmN0aW9uIGRhdGVSYW5nZUNvbXBhcmUoYTIsIGIpIHsKICAgIGlmIChhMi5kYXRlUmFuZ2UgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICBpZiAoYi5kYXRlUmFuZ2UgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgcmV0dXJuIGNvbXBhcmVUZW1wb3JhbChhMi5kYXRlUmFuZ2UsIGIuZGF0ZVJhbmdlKTsKICB9CiAgZnVuY3Rpb24gbWFwRGF0ZVRvR3JhbnVsYXJpdHlSYW5nZShkYXRhLCBncmFudWxhcml0eSkgewogICAgcmV0dXJuIHsKICAgICAgZGF0ZVJhbmdlOiBkYXRhLmRhdGUgPT09IG51bGwgPyBudWxsIDogcGFyc2VEYXRlU3RyaW5nVG9UZW1wb3JhbChkYXRhLmRhdGUsIGdyYW51bGFyaXR5KSwKICAgICAgY291bnQ6IGRhdGEuY291bnQKICAgIH07CiAgfQogIGNvbnN0IHN1YnN0aXR1dGlvblJlZ2V4ID0gL14oKD88c2VnbWVudD5bQS1aYS16MC05Xy1dKykoPz06KTopPyg/PHZhbHVlQXRSZWZlcmVuY2U+W0EtWmEtel0pPyg/PHBvc2l0aW9uPlxkKykoPzxzdWJzdGl0dXRpb25WYWx1ZT5bQS1aYS16Ll0pPyQvOwogIGNsYXNzIFN1YnN0aXR1dGlvbkNsYXNzIHsKICAgIGNvbnN0cnVjdG9yKHNlZ21lbnQsIHZhbHVlQXRSZWZlcmVuY2UsIHN1YnN0aXR1dGlvblZhbHVlLCBwb3NpdGlvbikgewogICAgICB0aGlzLnNlZ21lbnQgPSBzZWdtZW50OwogICAgICB0aGlzLnZhbHVlQXRSZWZlcmVuY2UgPSB2YWx1ZUF0UmVmZXJlbmNlOwogICAgICB0aGlzLnN1YnN0aXR1dGlvblZhbHVlID0gc3Vic3RpdHV0aW9uVmFsdWU7CiAgICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjsKICAgICAgdGhpcy50eXBlID0gInN1YnN0aXR1dGlvbiI7CiAgICAgIGNvbnN0IHNlZ21lbnRTdHJpbmcgPSB0aGlzLnNlZ21lbnQgPyBgJHt0aGlzLnNlZ21lbnR9OmAgOiAiIjsKICAgICAgY29uc3QgdmFsdWVBdFJlZmVyZW5jZVN0cmluZyA9IHRoaXMudmFsdWVBdFJlZmVyZW5jZSA/IGAke3RoaXMudmFsdWVBdFJlZmVyZW5jZX1gIDogIiI7CiAgICAgIGNvbnN0IHN1YnN0aXR1dGlvblZhbHVlU3RyaW5nID0gdGhpcy5zdWJzdGl0dXRpb25WYWx1ZSA/IGAke3RoaXMuc3Vic3RpdHV0aW9uVmFsdWV9YCA6ICIiOwogICAgICB0aGlzLmNvZGUgPSBgJHtzZWdtZW50U3RyaW5nfSR7dmFsdWVBdFJlZmVyZW5jZVN0cmluZ30ke3RoaXMucG9zaXRpb259JHtzdWJzdGl0dXRpb25WYWx1ZVN0cmluZ31gOwogICAgfQogICAgZXF1YWxzKG90aGVyKSB7CiAgICAgIGlmICghKG90aGVyIGluc3RhbmNlb2YgU3Vic3RpdHV0aW9uQ2xhc3MpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLnNlZ21lbnQgPT09IG90aGVyLnNlZ21lbnQgJiYgdGhpcy52YWx1ZUF0UmVmZXJlbmNlID09PSBvdGhlci52YWx1ZUF0UmVmZXJlbmNlICYmIHRoaXMuc3Vic3RpdHV0aW9uVmFsdWUgPT09IG90aGVyLnN1YnN0aXR1dGlvblZhbHVlICYmIHRoaXMucG9zaXRpb24gPT09IG90aGVyLnBvc2l0aW9uOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLmNvZGU7CiAgICB9CiAgICBzdGF0aWMgcGFyc2UobXV0YXRpb25TdHIpIHsKICAgICAgY29uc3QgbWF0Y2ggPSBtdXRhdGlvblN0ci5tYXRjaChzdWJzdGl0dXRpb25SZWdleCk7CiAgICAgIGlmIChtYXRjaCA9PT0gbnVsbCB8fCBtYXRjaC5ncm91cHMgPT09IHZvaWQgMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHJldHVybiBuZXcgU3Vic3RpdHV0aW9uQ2xhc3MoCiAgICAgICAgbWF0Y2guZ3JvdXBzLnNlZ21lbnQsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnZhbHVlQXRSZWZlcmVuY2UsCiAgICAgICAgbWF0Y2guZ3JvdXBzLnN1YnN0aXR1dGlvblZhbHVlLAogICAgICAgIHBhcnNlSW50KG1hdGNoLmdyb3Vwcy5wb3NpdGlvbiwgMTApCiAgICAgICk7CiAgICB9CiAgfQogIGNvbnN0IGRlbGV0aW9uUmVnZXggPSAvXigoPzxzZWdtZW50PltBLVphLXowLTlfLV0rKSg/PTopOik/KD88dmFsdWVBdFJlZmVyZW5jZT5bQS1aYS16XSk/KD88cG9zaXRpb24+XGQrKSgtKSQvOwogIGNsYXNzIERlbGV0aW9uQ2xhc3MgewogICAgY29uc3RydWN0b3Ioc2VnbWVudCwgdmFsdWVBdFJlZmVyZW5jZSwgcG9zaXRpb24pIHsKICAgICAgdGhpcy5zZWdtZW50ID0gc2VnbWVudDsKICAgICAgdGhpcy52YWx1ZUF0UmVmZXJlbmNlID0gdmFsdWVBdFJlZmVyZW5jZTsKICAgICAgdGhpcy5wb3NpdGlvbiA9IHBvc2l0aW9uOwogICAgICB0aGlzLnR5cGUgPSAiZGVsZXRpb24iOwogICAgICBjb25zdCBzZWdtZW50U3RyaW5nID0gdGhpcy5zZWdtZW50ID8gYCR7dGhpcy5zZWdtZW50fTpgIDogIiI7CiAgICAgIGNvbnN0IHZhbHVlQXRSZWZlcmVuY2VTdHJpbmcgPSB0aGlzLnZhbHVlQXRSZWZlcmVuY2UgPyBgJHt0aGlzLnZhbHVlQXRSZWZlcmVuY2V9YCA6ICIiOwogICAgICB0aGlzLmNvZGUgPSBgJHtzZWdtZW50U3RyaW5nfSR7dmFsdWVBdFJlZmVyZW5jZVN0cmluZ30ke3RoaXMucG9zaXRpb259LWA7CiAgICB9CiAgICBlcXVhbHMob3RoZXIpIHsKICAgICAgaWYgKCEob3RoZXIgaW5zdGFuY2VvZiBEZWxldGlvbkNsYXNzKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5zZWdtZW50ID09PSBvdGhlci5zZWdtZW50ICYmIHRoaXMudmFsdWVBdFJlZmVyZW5jZSA9PT0gb3RoZXIudmFsdWVBdFJlZmVyZW5jZSAmJiB0aGlzLnBvc2l0aW9uID09PSBvdGhlci5wb3NpdGlvbjsKICAgIH0KICAgIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gdGhpcy5jb2RlOwogICAgfQogICAgc3RhdGljIHBhcnNlKG11dGF0aW9uU3RyKSB7CiAgICAgIGNvbnN0IG1hdGNoID0gbXV0YXRpb25TdHIubWF0Y2goZGVsZXRpb25SZWdleCk7CiAgICAgIGlmIChtYXRjaCA9PT0gbnVsbCB8fCBtYXRjaC5ncm91cHMgPT09IHZvaWQgMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHJldHVybiBuZXcgRGVsZXRpb25DbGFzcygKICAgICAgICBtYXRjaC5ncm91cHMuc2VnbWVudCwKICAgICAgICBtYXRjaC5ncm91cHMudmFsdWVBdFJlZmVyZW5jZSwKICAgICAgICBwYXJzZUludChtYXRjaC5ncm91cHMucG9zaXRpb24sIDEwKQogICAgICApOwogICAgfQogIH0KICBmdW5jdGlvbiB0b1N1YnN0aXR1dGlvbk9yRGVsZXRpb24obXV0YXRpb24pIHsKICAgIHN3aXRjaCAobXV0YXRpb24udHlwZSkgewogICAgICBjYXNlICJzdWJzdGl0dXRpb24iOgogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiAic3Vic3RpdHV0aW9uIiwKICAgICAgICAgIGNvZGU6IG11dGF0aW9uLmNvZGUsCiAgICAgICAgICBzZWdtZW50OiBtdXRhdGlvbi5zZWdtZW50LAogICAgICAgICAgcG9zaXRpb246IG11dGF0aW9uLnBvc2l0aW9uLAogICAgICAgICAgdmFsdWVBdFJlZmVyZW5jZTogbXV0YXRpb24udmFsdWVBdFJlZmVyZW5jZSwKICAgICAgICAgIHN1YnN0aXR1dGlvblZhbHVlOiBtdXRhdGlvbi5zdWJzdGl0dXRpb25WYWx1ZQogICAgICAgIH07CiAgICAgIGNhc2UgImRlbGV0aW9uIjoKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogImRlbGV0aW9uIiwKICAgICAgICAgIGNvZGU6IG11dGF0aW9uLmNvZGUsCiAgICAgICAgICBzZWdtZW50OiBtdXRhdGlvbi5zZWdtZW50LAogICAgICAgICAgcG9zaXRpb246IG11dGF0aW9uLnBvc2l0aW9uLAogICAgICAgICAgdmFsdWVBdFJlZmVyZW5jZTogbXV0YXRpb24udmFsdWVBdFJlZmVyZW5jZQogICAgICAgIH07CiAgICB9CiAgfQogIGNsYXNzIEZldGNoU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zT3BlcmF0b3IgewogICAgY29uc3RydWN0b3IoZmlsdGVyLCBzZXF1ZW5jZVR5cGUsIG1pblByb3BvcnRpb24pIHsKICAgICAgdGhpcy5maWx0ZXIgPSBmaWx0ZXI7CiAgICAgIHRoaXMuc2VxdWVuY2VUeXBlID0gc2VxdWVuY2VUeXBlOwogICAgICB0aGlzLm1pblByb3BvcnRpb24gPSBtaW5Qcm9wb3J0aW9uOwogICAgfQogICAgYXN5bmMgZXZhbHVhdGUobGFwaXMsIHNpZ25hbCkgewogICAgICBjb25zdCBtdXRhdGlvbnMgPSBhd2FpdCB0aGlzLmZldGNoTXV0YXRpb25zKGxhcGlzLCBzaWduYWwpOwogICAgICBjb25zdCBjb250ZW50ID0gbXV0YXRpb25zLm1hcCgKICAgICAgICAoeyBjb3VudCwgcHJvcG9ydGlvbiwgbXV0YXRpb25Gcm9tLCBtdXRhdGlvblRvLCBwb3NpdGlvbiwgc2VxdWVuY2VOYW1lIH0pID0+IHsKICAgICAgICAgIGlmIChtdXRhdGlvblRvID09PSAiLSIpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICB0eXBlOiAiZGVsZXRpb24iLAogICAgICAgICAgICAgIG11dGF0aW9uOiBuZXcgRGVsZXRpb25DbGFzcyhzZXF1ZW5jZU5hbWUgPz8gdm9pZCAwLCBtdXRhdGlvbkZyb20sIHBvc2l0aW9uKSwKICAgICAgICAgICAgICBjb3VudCwKICAgICAgICAgICAgICBwcm9wb3J0aW9uCiAgICAgICAgICAgIH07CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICB0eXBlOiAic3Vic3RpdHV0aW9uIiwKICAgICAgICAgICAgbXV0YXRpb246IG5ldyBTdWJzdGl0dXRpb25DbGFzcyhzZXF1ZW5jZU5hbWUgPz8gdm9pZCAwLCBtdXRhdGlvbkZyb20sIG11dGF0aW9uVG8sIHBvc2l0aW9uKSwKICAgICAgICAgICAgY291bnQsCiAgICAgICAgICAgIHByb3BvcnRpb24KICAgICAgICAgIH07CiAgICAgICAgfQogICAgICApOwogICAgICByZXR1cm4geyBjb250ZW50IH07CiAgICB9CiAgICBhc3luYyBmZXRjaE11dGF0aW9ucyhsYXBpcywgc2lnbmFsKSB7CiAgICAgIGNvbnN0IGZpbHRlciA9IHsKICAgICAgICAuLi50aGlzLmZpbHRlciwKICAgICAgICBtaW5Qcm9wb3J0aW9uOiB0aGlzLm1pblByb3BvcnRpb24KICAgICAgfTsKICAgICAgcmV0dXJuIGZldGNoU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zKGxhcGlzLCBmaWx0ZXIsIHRoaXMuc2VxdWVuY2VUeXBlLCBzaWduYWwpLnRoZW4oCiAgICAgICAgKHJlc3BvbnNlKSA9PiByZXNwb25zZS5kYXRhCiAgICAgICk7CiAgICB9CiAgfQogIHZhciBsJDE7CiAgbCQxID0geyBfX2U6IGZ1bmN0aW9uKG4sIGwyLCB1MiwgdCkgewogICAgZm9yICh2YXIgaTIsIG8sIHIyOyBsMiA9IGwyLl9fOyApIGlmICgoaTIgPSBsMi5fX2MpICYmICFpMi5fXykgdHJ5IHsKICAgICAgaWYgKChvID0gaTIuY29uc3RydWN0b3IpICYmIG51bGwgIT0gby5nZXREZXJpdmVkU3RhdGVGcm9tRXJyb3IgJiYgKGkyLnNldFN0YXRlKG8uZ2V0RGVyaXZlZFN0YXRlRnJvbUVycm9yKG4pKSwgcjIgPSBpMi5fX2QpLCBudWxsICE9IGkyLmNvbXBvbmVudERpZENhdGNoICYmIChpMi5jb21wb25lbnREaWRDYXRjaChuLCB0IHx8IHt9KSwgcjIgPSBpMi5fX2QpLCByMikgcmV0dXJuIGkyLl9fRSA9IGkyOwogICAgfSBjYXRjaCAobDMpIHsKICAgICAgbiA9IGwzOwogICAgfQogICAgdGhyb3cgbjsKICB9IH0sICJmdW5jdGlvbiIgPT0gdHlwZW9mIFByb21pc2UgPyBQcm9taXNlLnByb3RvdHlwZS50aGVuLmJpbmQoUHJvbWlzZS5yZXNvbHZlKCkpIDogc2V0VGltZW91dDsKICB2YXIgciwgdSwgaSwgZiA9IFtdLCBjID0gbCQxLCBlID0gYy5fX2IsIGEgPSBjLl9fciwgdiA9IGMuZGlmZmVkLCBsID0gYy5fX2MsIG0gPSBjLnVubW91bnQsIHMgPSBjLl9fOwogIGZ1bmN0aW9uIGooKSB7CiAgICBmb3IgKHZhciBuOyBuID0gZi5zaGlmdCgpOyApIGlmIChuLl9fUCAmJiBuLl9fSCkgdHJ5IHsKICAgICAgbi5fX0guX19oLmZvckVhY2goeiksIG4uX19ILl9faC5mb3JFYWNoKEIpLCBuLl9fSC5fX2ggPSBbXTsKICAgIH0gY2F0Y2ggKHQpIHsKICAgICAgbi5fX0guX19oID0gW10sIGMuX19lKHQsIG4uX192KTsKICAgIH0KICB9CiAgYy5fX2IgPSBmdW5jdGlvbihuKSB7CiAgICByID0gbnVsbCwgZSAmJiBlKG4pOwogIH0sIGMuX18gPSBmdW5jdGlvbihuLCB0KSB7CiAgICBuICYmIHQuX19rICYmIHQuX19rLl9fbSAmJiAobi5fX20gPSB0Ll9fay5fX20pLCBzICYmIHMobiwgdCk7CiAgfSwgYy5fX3IgPSBmdW5jdGlvbihuKSB7CiAgICBhICYmIGEobik7CiAgICB2YXIgaTIgPSAociA9IG4uX19jKS5fX0g7CiAgICBpMiAmJiAodSA9PT0gciA/IChpMi5fX2ggPSBbXSwgci5fX2ggPSBbXSwgaTIuX18uZm9yRWFjaChmdW5jdGlvbihuMikgewogICAgICBuMi5fX04gJiYgKG4yLl9fID0gbjIuX19OKSwgbjIuaSA9IG4yLl9fTiA9IHZvaWQgMDsKICAgIH0pKSA6IChpMi5fX2guZm9yRWFjaCh6KSwgaTIuX19oLmZvckVhY2goQiksIGkyLl9faCA9IFtdLCAwKSksIHUgPSByOwogIH0sIGMuZGlmZmVkID0gZnVuY3Rpb24obikgewogICAgdiAmJiB2KG4pOwogICAgdmFyIHQgPSBuLl9fYzsKICAgIHQgJiYgdC5fX0ggJiYgKHQuX19ILl9faC5sZW5ndGggJiYgKDEgIT09IGYucHVzaCh0KSAmJiBpID09PSBjLnJlcXVlc3RBbmltYXRpb25GcmFtZSB8fCAoKGkgPSBjLnJlcXVlc3RBbmltYXRpb25GcmFtZSkgfHwgdykoaikpLCB0Ll9fSC5fXy5mb3JFYWNoKGZ1bmN0aW9uKG4yKSB7CiAgICAgIG4yLmkgJiYgKG4yLl9fSCA9IG4yLmkpLCBuMi5pID0gdm9pZCAwOwogICAgfSkpLCB1ID0gciA9IG51bGw7CiAgfSwgYy5fX2MgPSBmdW5jdGlvbihuLCB0KSB7CiAgICB0LnNvbWUoZnVuY3Rpb24objIpIHsKICAgICAgdHJ5IHsKICAgICAgICBuMi5fX2guZm9yRWFjaCh6KSwgbjIuX19oID0gbjIuX19oLmZpbHRlcihmdW5jdGlvbihuMykgewogICAgICAgICAgcmV0dXJuICFuMy5fXyB8fCBCKG4zKTsKICAgICAgICB9KTsKICAgICAgfSBjYXRjaCAocjIpIHsKICAgICAgICB0LnNvbWUoZnVuY3Rpb24objMpIHsKICAgICAgICAgIG4zLl9faCAmJiAobjMuX19oID0gW10pOwogICAgICAgIH0pLCB0ID0gW10sIGMuX19lKHIyLCBuMi5fX3YpOwogICAgICB9CiAgICB9KSwgbCAmJiBsKG4sIHQpOwogIH0sIGMudW5tb3VudCA9IGZ1bmN0aW9uKG4pIHsKICAgIG0gJiYgbShuKTsKICAgIHZhciB0LCByMiA9IG4uX19jOwogICAgcjIgJiYgcjIuX19IICYmIChyMi5fX0guX18uZm9yRWFjaChmdW5jdGlvbihuMikgewogICAgICB0cnkgewogICAgICAgIHoobjIpOwogICAgICB9IGNhdGNoIChuMykgewogICAgICAgIHQgPSBuMzsKICAgICAgfQogICAgfSksIHIyLl9fSCA9IHZvaWQgMCwgdCAmJiBjLl9fZSh0LCByMi5fX3YpKTsKICB9OwogIHZhciBrID0gImZ1bmN0aW9uIiA9PSB0eXBlb2YgcmVxdWVzdEFuaW1hdGlvbkZyYW1lOwogIGZ1bmN0aW9uIHcobikgewogICAgdmFyIHQsIHIyID0gZnVuY3Rpb24oKSB7CiAgICAgIGNsZWFyVGltZW91dCh1MiksIGsgJiYgY2FuY2VsQW5pbWF0aW9uRnJhbWUodCksIHNldFRpbWVvdXQobik7CiAgICB9LCB1MiA9IHNldFRpbWVvdXQocjIsIDEwMCk7CiAgICBrICYmICh0ID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHIyKSk7CiAgfQogIGZ1bmN0aW9uIHoobikgewogICAgdmFyIHQgPSByLCB1MiA9IG4uX19jOwogICAgImZ1bmN0aW9uIiA9PSB0eXBlb2YgdTIgJiYgKG4uX19jID0gdm9pZCAwLCB1MigpKSwgciA9IHQ7CiAgfQogIGZ1bmN0aW9uIEIobikgewogICAgdmFyIHQgPSByOwogICAgbi5fX2MgPSBuLl9fKCksIHIgPSB0OwogIH0KICBjbGFzcyBVc2VyRmFjaW5nRXJyb3IgZXh0ZW5kcyBFcnJvciB7CiAgICBjb25zdHJ1Y3RvcihoZWFkbGluZSwgbWVzc2FnZSkgewogICAgICBzdXBlcihtZXNzYWdlKTsKICAgICAgdGhpcy5oZWFkbGluZSA9IGhlYWRsaW5lOwogICAgICB0aGlzLm5hbWUgPSAiVXNlckZhY2luZ0Vycm9yIjsKICAgIH0KICB9CiAgY29uc3Qgc29ydFN1YnN0aXR1dGlvbnNBbmREZWxldGlvbnMgPSAoYTIsIGIpID0+IHsKICAgIGlmIChhMi5zZWdtZW50ICE9PSBiLnNlZ21lbnQpIHsKICAgICAgcmV0dXJuIGNvbXBhcmVTZWdtZW50cyhhMi5zZWdtZW50LCBiLnNlZ21lbnQpOwogICAgfQogICAgaWYgKGEyLnBvc2l0aW9uICE9PSBiLnBvc2l0aW9uKSB7CiAgICAgIHJldHVybiBjb21wYXJlUG9zaXRpb25zKGEyLnBvc2l0aW9uLCBiLnBvc2l0aW9uKTsKICAgIH0KICAgIGNvbnN0IGFJc0RlbGV0aW9uID0gYTIgaW5zdGFuY2VvZiBEZWxldGlvbkNsYXNzOwogICAgY29uc3QgYklzRGVsZXRpb24gPSBiIGluc3RhbmNlb2YgRGVsZXRpb25DbGFzczsKICAgIGlmIChhSXNEZWxldGlvbiAhPT0gYklzRGVsZXRpb24pIHsKICAgICAgcmV0dXJuIGFJc0RlbGV0aW9uID8gMSA6IC0xOwogICAgfQogICAgaWYgKCFhSXNEZWxldGlvbiAmJiAhYklzRGVsZXRpb24pIHsKICAgICAgaWYgKGEyLnN1YnN0aXR1dGlvblZhbHVlICE9PSBiLnN1YnN0aXR1dGlvblZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGNvbXBhcmVTdWJzdGl0dXRpb25WYWx1ZXMoYTIuc3Vic3RpdHV0aW9uVmFsdWUsIGIuc3Vic3RpdHV0aW9uVmFsdWUpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gMDsKICB9OwogIGNvbnN0IGNvbXBhcmVTZWdtZW50cyA9IChhMiwgYikgPT4gewogICAgaWYgKGEyID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgaWYgKGIgPT09IHZvaWQgMCkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIHJldHVybiBhMi5sb2NhbGVDb21wYXJlKGIpOwogIH07CiAgY29uc3QgY29tcGFyZVBvc2l0aW9ucyA9IChhMiwgYikgPT4gewogICAgcmV0dXJuIGEyIC0gYjsKICB9OwogIGNvbnN0IGNvbXBhcmVTdWJzdGl0dXRpb25WYWx1ZXMgPSAoYTIsIGIpID0+IHsKICAgIGlmIChhMiA9PT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGlmIChiID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICByZXR1cm4gYTIubG9jYWxlQ29tcGFyZShiKTsKICB9OwogIGZ1bmN0aW9uIGdldERlZmF1bHRFeHBvcnRGcm9tQ2pzKHgpIHsKICAgIHJldHVybiB4ICYmIHguX19lc01vZHVsZSAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoeCwgImRlZmF1bHQiKSA/IHhbImRlZmF1bHQiXSA6IHg7CiAgfQogIGZ1bmN0aW9uIGNvbW1vbmpzUmVxdWlyZShwYXRoKSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCBkeW5hbWljYWxseSByZXF1aXJlICInICsgcGF0aCArICciLiBQbGVhc2UgY29uZmlndXJlIHRoZSBkeW5hbWljUmVxdWlyZVRhcmdldHMgb3IvYW5kIGlnbm9yZUR5bmFtaWNSZXF1aXJlcyBvcHRpb24gb2YgQHJvbGx1cC9wbHVnaW4tY29tbW9uanMgYXBwcm9wcmlhdGVseSBmb3IgdGhpcyByZXF1aXJlIGNhbGwgdG8gd29yay4nKTsKICB9CiAgdmFyIG9iamVjdF9oYXNoID0geyBleHBvcnRzOiB7fSB9OwogIChmdW5jdGlvbihtb2R1bGUsIGV4cG9ydHMpIHsKICAgICFmdW5jdGlvbihlMikgewogICAgICBtb2R1bGUuZXhwb3J0cyA9IGUyKCk7CiAgICB9KGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gZnVuY3Rpb24gcjIobywgaTIsIHUyKSB7CiAgICAgICAgZnVuY3Rpb24gczIobiwgZTMpIHsKICAgICAgICAgIGlmICghaTJbbl0pIHsKICAgICAgICAgICAgaWYgKCFvW25dKSB7CiAgICAgICAgICAgICAgdmFyIHQgPSAiZnVuY3Rpb24iID09IHR5cGVvZiBjb21tb25qc1JlcXVpcmUgJiYgY29tbW9uanNSZXF1aXJlOwogICAgICAgICAgICAgIGlmICghZTMgJiYgdCkgcmV0dXJuIHQobiwgdHJ1ZSk7CiAgICAgICAgICAgICAgaWYgKGEyKSByZXR1cm4gYTIobiwgdHJ1ZSk7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDYW5ub3QgZmluZCBtb2R1bGUgJyIgKyBuICsgIiciKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlMyA9IGkyW25dID0geyBleHBvcnRzOiB7fSB9OwogICAgICAgICAgICBvW25dWzBdLmNhbGwoZTMuZXhwb3J0cywgZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgICB2YXIgdDIgPSBvW25dWzFdW2U0XTsKICAgICAgICAgICAgICByZXR1cm4gczIodDIgfHwgZTQpOwogICAgICAgICAgICB9LCBlMywgZTMuZXhwb3J0cywgcjIsIG8sIGkyLCB1Mik7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gaTJbbl0uZXhwb3J0czsKICAgICAgICB9CiAgICAgICAgZm9yICh2YXIgYTIgPSAiZnVuY3Rpb24iID09IHR5cGVvZiBjb21tb25qc1JlcXVpcmUgJiYgY29tbW9uanNSZXF1aXJlLCBlMiA9IDA7IGUyIDwgdTIubGVuZ3RoOyBlMisrKSBzMih1MltlMl0pOwogICAgICAgIHJldHVybiBzMjsKICAgICAgfSh7IDE6IFtmdW5jdGlvbih3MiwgYiwgbTIpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUyLCBuLCBzMiwgYzIsIGQsIGgsIHAsIGcsIHkpIHsKICAgICAgICAgIHZhciByMiA9IHcyKCJjcnlwdG8iKTsKICAgICAgICAgIGZ1bmN0aW9uIHQoZTMsIHQyKSB7CiAgICAgICAgICAgIHQyID0gdTIoZTMsIHQyKTsKICAgICAgICAgICAgdmFyIG4yOwogICAgICAgICAgICByZXR1cm4gdm9pZCAwID09PSAobjIgPSAicGFzc3Rocm91Z2giICE9PSB0Mi5hbGdvcml0aG0gPyByMi5jcmVhdGVIYXNoKHQyLmFsZ29yaXRobSkgOiBuZXcgbDIoKSkud3JpdGUgJiYgKG4yLndyaXRlID0gbjIudXBkYXRlLCBuMi5lbmQgPSBuMi51cGRhdGUpLCBmMih0MiwgbjIpLmRpc3BhdGNoKGUzKSwgbjIudXBkYXRlIHx8IG4yLmVuZCgiIiksIG4yLmRpZ2VzdCA/IG4yLmRpZ2VzdCgiYnVmZmVyIiA9PT0gdDIuZW5jb2RpbmcgPyB2b2lkIDAgOiB0Mi5lbmNvZGluZykgOiAoZTMgPSBuMi5yZWFkKCksICJidWZmZXIiICE9PSB0Mi5lbmNvZGluZyA/IGUzLnRvU3RyaW5nKHQyLmVuY29kaW5nKSA6IGUzKTsKICAgICAgICAgIH0KICAgICAgICAgIChtMiA9IGIuZXhwb3J0cyA9IHQpLnNoYTEgPSBmdW5jdGlvbihlMykgewogICAgICAgICAgICByZXR1cm4gdChlMyk7CiAgICAgICAgICB9LCBtMi5rZXlzID0gZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgcmV0dXJuIHQoZTMsIHsgZXhjbHVkZVZhbHVlczogdHJ1ZSwgYWxnb3JpdGhtOiAic2hhMSIsIGVuY29kaW5nOiAiaGV4IiB9KTsKICAgICAgICAgIH0sIG0yLk1ENSA9IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIHJldHVybiB0KGUzLCB7IGFsZ29yaXRobTogIm1kNSIsIGVuY29kaW5nOiAiaGV4IiB9KTsKICAgICAgICAgIH0sIG0yLmtleXNNRDUgPSBmdW5jdGlvbihlMykgewogICAgICAgICAgICByZXR1cm4gdChlMywgeyBhbGdvcml0aG06ICJtZDUiLCBlbmNvZGluZzogImhleCIsIGV4Y2x1ZGVWYWx1ZXM6IHRydWUgfSk7CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIG8gPSByMi5nZXRIYXNoZXMgPyByMi5nZXRIYXNoZXMoKS5zbGljZSgpIDogWyJzaGExIiwgIm1kNSJdLCBpMiA9IChvLnB1c2goInBhc3N0aHJvdWdoIiksIFsiYnVmZmVyIiwgImhleCIsICJiaW5hcnkiLCAiYmFzZTY0Il0pOwogICAgICAgICAgZnVuY3Rpb24gdTIoZTMsIHQyKSB7CiAgICAgICAgICAgIHZhciBuMiA9IHt9OwogICAgICAgICAgICBpZiAobjIuYWxnb3JpdGhtID0gKHQyID0gdDIgfHwge30pLmFsZ29yaXRobSB8fCAic2hhMSIsIG4yLmVuY29kaW5nID0gdDIuZW5jb2RpbmcgfHwgImhleCIsIG4yLmV4Y2x1ZGVWYWx1ZXMgPSAhIXQyLmV4Y2x1ZGVWYWx1ZXMsIG4yLmFsZ29yaXRobSA9IG4yLmFsZ29yaXRobS50b0xvd2VyQ2FzZSgpLCBuMi5lbmNvZGluZyA9IG4yLmVuY29kaW5nLnRvTG93ZXJDYXNlKCksIG4yLmlnbm9yZVVua25vd24gPSB0cnVlID09PSB0Mi5pZ25vcmVVbmtub3duLCBuMi5yZXNwZWN0VHlwZSA9IGZhbHNlICE9PSB0Mi5yZXNwZWN0VHlwZSwgbjIucmVzcGVjdEZ1bmN0aW9uTmFtZXMgPSBmYWxzZSAhPT0gdDIucmVzcGVjdEZ1bmN0aW9uTmFtZXMsIG4yLnJlc3BlY3RGdW5jdGlvblByb3BlcnRpZXMgPSBmYWxzZSAhPT0gdDIucmVzcGVjdEZ1bmN0aW9uUHJvcGVydGllcywgbjIudW5vcmRlcmVkQXJyYXlzID0gdHJ1ZSA9PT0gdDIudW5vcmRlcmVkQXJyYXlzLCBuMi51bm9yZGVyZWRTZXRzID0gZmFsc2UgIT09IHQyLnVub3JkZXJlZFNldHMsIG4yLnVub3JkZXJlZE9iamVjdHMgPSBmYWxzZSAhPT0gdDIudW5vcmRlcmVkT2JqZWN0cywgbjIucmVwbGFjZXIgPSB0Mi5yZXBsYWNlciB8fCB2b2lkIDAsIG4yLmV4Y2x1ZGVLZXlzID0gdDIuZXhjbHVkZUtleXMgfHwgdm9pZCAwLCB2b2lkIDAgPT09IGUzKSB0aHJvdyBuZXcgRXJyb3IoIk9iamVjdCBhcmd1bWVudCByZXF1aXJlZC4iKTsKICAgICAgICAgICAgZm9yICh2YXIgcjMgPSAwOyByMyA8IG8ubGVuZ3RoOyArK3IzKSBvW3IzXS50b0xvd2VyQ2FzZSgpID09PSBuMi5hbGdvcml0aG0udG9Mb3dlckNhc2UoKSAmJiAobjIuYWxnb3JpdGhtID0gb1tyM10pOwogICAgICAgICAgICBpZiAoLTEgPT09IG8uaW5kZXhPZihuMi5hbGdvcml0aG0pKSB0aHJvdyBuZXcgRXJyb3IoJ0FsZ29yaXRobSAiJyArIG4yLmFsZ29yaXRobSArICciICBub3Qgc3VwcG9ydGVkLiBzdXBwb3J0ZWQgdmFsdWVzOiAnICsgby5qb2luKCIsICIpKTsKICAgICAgICAgICAgaWYgKC0xID09PSBpMi5pbmRleE9mKG4yLmVuY29kaW5nKSAmJiAicGFzc3Rocm91Z2giICE9PSBuMi5hbGdvcml0aG0pIHRocm93IG5ldyBFcnJvcignRW5jb2RpbmcgIicgKyBuMi5lbmNvZGluZyArICciICBub3Qgc3VwcG9ydGVkLiBzdXBwb3J0ZWQgdmFsdWVzOiAnICsgaTIuam9pbigiLCAiKSk7CiAgICAgICAgICAgIHJldHVybiBuMjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGEyKGUzKSB7CiAgICAgICAgICAgIGlmICgiZnVuY3Rpb24iID09IHR5cGVvZiBlMykgcmV0dXJuIG51bGwgIT0gL15mdW5jdGlvblxzK1x3KlxzKlwoXHMqXClccyp7XHMrXFtuYXRpdmUgY29kZVxdXHMrfSQvaS5leGVjKEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGUzKSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBmMihvMiwgdDIsIGkzKSB7CiAgICAgICAgICAgIGkzID0gaTMgfHwgW107CiAgICAgICAgICAgIGZ1bmN0aW9uIHUzKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHQyLnVwZGF0ZSA/IHQyLnVwZGF0ZShlMywgInV0ZjgiKSA6IHQyLndyaXRlKGUzLCAidXRmOCIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB7IGRpc3BhdGNoOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB0aGlzWyJfIiArIChudWxsID09PSAoZTMgPSBvMi5yZXBsYWNlciA/IG8yLnJlcGxhY2VyKGUzKSA6IGUzKSA/ICJudWxsIiA6IHR5cGVvZiBlMyldKGUzKTsKICAgICAgICAgICAgfSwgX29iamVjdDogZnVuY3Rpb24odDMpIHsKICAgICAgICAgICAgICB2YXIgbjIsIGUzID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHQzKSwgcjMgPSAvXFtvYmplY3QgKC4qKVxdL2kuZXhlYyhlMyk7CiAgICAgICAgICAgICAgcjMgPSAocjMgPSByMyA/IHIzWzFdIDogInVua25vd246WyIgKyBlMyArICJdIikudG9Mb3dlckNhc2UoKTsKICAgICAgICAgICAgICBpZiAoMCA8PSAoZTMgPSBpMy5pbmRleE9mKHQzKSkpIHJldHVybiB0aGlzLmRpc3BhdGNoKCJbQ0lSQ1VMQVI6IiArIGUzICsgIl0iKTsKICAgICAgICAgICAgICBpZiAoaTMucHVzaCh0MyksIHZvaWQgMCAhPT0gczIgJiYgczIuaXNCdWZmZXIgJiYgczIuaXNCdWZmZXIodDMpKSByZXR1cm4gdTMoImJ1ZmZlcjoiKSwgdTModDMpOwogICAgICAgICAgICAgIGlmICgib2JqZWN0IiA9PT0gcjMgfHwgImZ1bmN0aW9uIiA9PT0gcjMgfHwgImFzeW5jZnVuY3Rpb24iID09PSByMykgcmV0dXJuIGUzID0gT2JqZWN0LmtleXModDMpLCBvMi51bm9yZGVyZWRPYmplY3RzICYmIChlMyA9IGUzLnNvcnQoKSksIGZhbHNlID09PSBvMi5yZXNwZWN0VHlwZSB8fCBhMih0MykgfHwgZTMuc3BsaWNlKDAsIDAsICJwcm90b3R5cGUiLCAiX19wcm90b19fIiwgImNvbnN0cnVjdG9yIiksIG8yLmV4Y2x1ZGVLZXlzICYmIChlMyA9IGUzLmZpbHRlcihmdW5jdGlvbihlNCkgewogICAgICAgICAgICAgICAgcmV0dXJuICFvMi5leGNsdWRlS2V5cyhlNCk7CiAgICAgICAgICAgICAgfSkpLCB1Mygib2JqZWN0OiIgKyBlMy5sZW5ndGggKyAiOiIpLCBuMiA9IHRoaXMsIGUzLmZvckVhY2goZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgICAgIG4yLmRpc3BhdGNoKGU0KSwgdTMoIjoiKSwgbzIuZXhjbHVkZVZhbHVlcyB8fCBuMi5kaXNwYXRjaCh0M1tlNF0pLCB1MygiLCIpOwogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIGlmICghdGhpc1siXyIgKyByM10pIHsKICAgICAgICAgICAgICAgIGlmIChvMi5pZ25vcmVVbmtub3duKSByZXR1cm4gdTMoIlsiICsgcjMgKyAiXSIpOwogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIG9iamVjdCB0eXBlICInICsgcjMgKyAnIicpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0aGlzWyJfIiArIHIzXSh0Myk7CiAgICAgICAgICAgIH0sIF9hcnJheTogZnVuY3Rpb24oZTMsIHQzKSB7CiAgICAgICAgICAgICAgdDMgPSB2b2lkIDAgIT09IHQzID8gdDMgOiBmYWxzZSAhPT0gbzIudW5vcmRlcmVkQXJyYXlzOwogICAgICAgICAgICAgIHZhciBuMiA9IHRoaXM7CiAgICAgICAgICAgICAgaWYgKHUzKCJhcnJheToiICsgZTMubGVuZ3RoICsgIjoiKSwgIXQzIHx8IGUzLmxlbmd0aCA8PSAxKSByZXR1cm4gZTMuZm9yRWFjaChmdW5jdGlvbihlNCkgewogICAgICAgICAgICAgICAgcmV0dXJuIG4yLmRpc3BhdGNoKGU0KTsKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICB2YXIgcjMgPSBbXSwgdDMgPSBlMy5tYXAoZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgICAgIHZhciB0NCA9IG5ldyBsMigpLCBuMyA9IGkzLnNsaWNlKCk7CiAgICAgICAgICAgICAgICByZXR1cm4gZjIobzIsIHQ0LCBuMykuZGlzcGF0Y2goZTQpLCByMyA9IHIzLmNvbmNhdChuMy5zbGljZShpMy5sZW5ndGgpKSwgdDQucmVhZCgpLnRvU3RyaW5nKCk7CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgcmV0dXJuIGkzID0gaTMuY29uY2F0KHIzKSwgdDMuc29ydCgpLCB0aGlzLl9hcnJheSh0MywgZmFsc2UpOwogICAgICAgICAgICB9LCBfZGF0ZTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImRhdGU6IiArIGUzLnRvSlNPTigpKTsKICAgICAgICAgICAgfSwgX3N5bWJvbDogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInN5bWJvbDoiICsgZTMudG9TdHJpbmcoKSk7CiAgICAgICAgICAgIH0sIF9lcnJvcjogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImVycm9yOiIgKyBlMy50b1N0cmluZygpKTsKICAgICAgICAgICAgfSwgX2Jvb2xlYW46IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJib29sOiIgKyBlMy50b1N0cmluZygpKTsKICAgICAgICAgICAgfSwgX3N0cmluZzogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICB1Mygic3RyaW5nOiIgKyBlMy5sZW5ndGggKyAiOiIpLCB1MyhlMy50b1N0cmluZygpKTsKICAgICAgICAgICAgfSwgX2Z1bmN0aW9uOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHUzKCJmbjoiKSwgYTIoZTMpID8gdGhpcy5kaXNwYXRjaCgiW25hdGl2ZV0iKSA6IHRoaXMuZGlzcGF0Y2goZTMudG9TdHJpbmcoKSksIGZhbHNlICE9PSBvMi5yZXNwZWN0RnVuY3Rpb25OYW1lcyAmJiB0aGlzLmRpc3BhdGNoKCJmdW5jdGlvbi1uYW1lOiIgKyBTdHJpbmcoZTMubmFtZSkpLCBvMi5yZXNwZWN0RnVuY3Rpb25Qcm9wZXJ0aWVzICYmIHRoaXMuX29iamVjdChlMyk7CiAgICAgICAgICAgIH0sIF9udW1iZXI6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJudW1iZXI6IiArIGUzLnRvU3RyaW5nKCkpOwogICAgICAgICAgICB9LCBfeG1sOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB1MygieG1sOiIgKyBlMy50b1N0cmluZygpKTsKICAgICAgICAgICAgfSwgX251bGw6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiB1MygiTnVsbCIpOwogICAgICAgICAgICB9LCBfdW5kZWZpbmVkOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoIlVuZGVmaW5lZCIpOwogICAgICAgICAgICB9LCBfcmVnZXhwOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB1MygicmVnZXg6IiArIGUzLnRvU3RyaW5nKCkpOwogICAgICAgICAgICB9LCBfdWludDhhcnJheTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInVpbnQ4YXJyYXk6IiksIHRoaXMuZGlzcGF0Y2goQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZTMpKTsKICAgICAgICAgICAgfSwgX3VpbnQ4Y2xhbXBlZGFycmF5OiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB1MygidWludDhjbGFtcGVkYXJyYXk6IiksIHRoaXMuZGlzcGF0Y2goQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZTMpKTsKICAgICAgICAgICAgfSwgX2ludDhhcnJheTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImludDhhcnJheToiKSwgdGhpcy5kaXNwYXRjaChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChlMykpOwogICAgICAgICAgICB9LCBfdWludDE2YXJyYXk6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJ1aW50MTZhcnJheToiKSwgdGhpcy5kaXNwYXRjaChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChlMykpOwogICAgICAgICAgICB9LCBfaW50MTZhcnJheTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImludDE2YXJyYXk6IiksIHRoaXMuZGlzcGF0Y2goQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZTMpKTsKICAgICAgICAgICAgfSwgX3VpbnQzMmFycmF5OiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB1MygidWludDMyYXJyYXk6IiksIHRoaXMuZGlzcGF0Y2goQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZTMpKTsKICAgICAgICAgICAgfSwgX2ludDMyYXJyYXk6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJpbnQzMmFycmF5OiIpLCB0aGlzLmRpc3BhdGNoKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGUzKSk7CiAgICAgICAgICAgIH0sIF9mbG9hdDMyYXJyYXk6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJmbG9hdDMyYXJyYXk6IiksIHRoaXMuZGlzcGF0Y2goQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZTMpKTsKICAgICAgICAgICAgfSwgX2Zsb2F0NjRhcnJheTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImZsb2F0NjRhcnJheToiKSwgdGhpcy5kaXNwYXRjaChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChlMykpOwogICAgICAgICAgICB9LCBfYXJyYXlidWZmZXI6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJhcnJheWJ1ZmZlcjoiKSwgdGhpcy5kaXNwYXRjaChuZXcgVWludDhBcnJheShlMykpOwogICAgICAgICAgICB9LCBfdXJsOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHJldHVybiB1MygidXJsOiIgKyBlMy50b1N0cmluZygpKTsKICAgICAgICAgICAgfSwgX21hcDogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICB1MygibWFwOiIpOwogICAgICAgICAgICAgIGUzID0gQXJyYXkuZnJvbShlMyk7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2FycmF5KGUzLCBmYWxzZSAhPT0gbzIudW5vcmRlcmVkU2V0cyk7CiAgICAgICAgICAgIH0sIF9zZXQ6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgdTMoInNldDoiKTsKICAgICAgICAgICAgICBlMyA9IEFycmF5LmZyb20oZTMpOwogICAgICAgICAgICAgIHJldHVybiB0aGlzLl9hcnJheShlMywgZmFsc2UgIT09IG8yLnVub3JkZXJlZFNldHMpOwogICAgICAgICAgICB9LCBfZmlsZTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImZpbGU6IiksIHRoaXMuZGlzcGF0Y2goW2UzLm5hbWUsIGUzLnNpemUsIGUzLnR5cGUsIGUzLmxhc3RNb2RmaWVkXSk7CiAgICAgICAgICAgIH0sIF9ibG9iOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICBpZiAobzIuaWdub3JlVW5rbm93bikgcmV0dXJuIHUzKCJbYmxvYl0iKTsKICAgICAgICAgICAgICB0aHJvdyBFcnJvcignSGFzaGluZyBCbG9iIG9iamVjdHMgaXMgY3VycmVudGx5IG5vdCBzdXBwb3J0ZWRcbihzZWUgaHR0cHM6Ly9naXRodWIuY29tL3B1bGVvcy9vYmplY3QtaGFzaC9pc3N1ZXMvMjYpXG5Vc2UgIm9wdGlvbnMucmVwbGFjZXIiIG9yICJvcHRpb25zLmlnbm9yZVVua25vd24iXG4nKTsKICAgICAgICAgICAgfSwgX2RvbXdpbmRvdzogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJkb213aW5kb3ciKTsKICAgICAgICAgICAgfSwgX2JpZ2ludDogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImJpZ2ludDoiICsgZTMudG9TdHJpbmcoKSk7CiAgICAgICAgICAgIH0sIF9wcm9jZXNzOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInByb2Nlc3MiKTsKICAgICAgICAgICAgfSwgX3RpbWVyOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInRpbWVyIik7CiAgICAgICAgICAgIH0sIF9waXBlOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInBpcGUiKTsKICAgICAgICAgICAgfSwgX3RjcDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJ0Y3AiKTsKICAgICAgICAgICAgfSwgX3VkcDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJ1ZHAiKTsKICAgICAgICAgICAgfSwgX3R0eTogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJ0dHkiKTsKICAgICAgICAgICAgfSwgX3N0YXR3YXRjaGVyOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInN0YXR3YXRjaGVyIik7CiAgICAgICAgICAgIH0sIF9zZWN1cmVjb250ZXh0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInNlY3VyZWNvbnRleHQiKTsKICAgICAgICAgICAgfSwgX2Nvbm5lY3Rpb246IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiB1MygiY29ubmVjdGlvbiIpOwogICAgICAgICAgICB9LCBfemxpYjogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJ6bGliIik7CiAgICAgICAgICAgIH0sIF9jb250ZXh0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoImNvbnRleHQiKTsKICAgICAgICAgICAgfSwgX25vZGVzY3JpcHQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiB1Mygibm9kZXNjcmlwdCIpOwogICAgICAgICAgICB9LCBfaHR0cHBhcnNlcjogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJodHRwcGFyc2VyIik7CiAgICAgICAgICAgIH0sIF9kYXRhdmlldzogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJkYXRhdmlldyIpOwogICAgICAgICAgICB9LCBfc2lnbmFsOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInNpZ25hbCIpOwogICAgICAgICAgICB9LCBfZnNldmVudDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUzKCJmc2V2ZW50Iik7CiAgICAgICAgICAgIH0sIF90bHN3cmFwOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gdTMoInRsc3dyYXAiKTsKICAgICAgICAgICAgfSB9OwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gbDIoKSB7CiAgICAgICAgICAgIHJldHVybiB7IGJ1ZjogIiIsIHdyaXRlOiBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHRoaXMuYnVmICs9IGUzOwogICAgICAgICAgICB9LCBlbmQ6IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgdGhpcy5idWYgKz0gZTM7CiAgICAgICAgICAgIH0sIHJlYWQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiB0aGlzLmJ1ZjsKICAgICAgICAgICAgfSB9OwogICAgICAgICAgfQogICAgICAgICAgbTIud3JpdGVUb1N0cmVhbSA9IGZ1bmN0aW9uKGUzLCB0MiwgbjIpIHsKICAgICAgICAgICAgcmV0dXJuIHZvaWQgMCA9PT0gbjIgJiYgKG4yID0gdDIsIHQyID0ge30pLCBmMih0MiA9IHUyKGUzLCB0MiksIG4yKS5kaXNwYXRjaChlMyk7CiAgICAgICAgICB9OwogICAgICAgIH0pLmNhbGwodGhpcywgdzIoImxZcG9JMiIpLCAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygc2VsZiA/IHNlbGYgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDoge30sIHcyKCJidWZmZXIiKS5CdWZmZXIsIGFyZ3VtZW50c1szXSwgYXJndW1lbnRzWzRdLCBhcmd1bWVudHNbNV0sIGFyZ3VtZW50c1s2XSwgIi9mYWtlXzlhNWFhNDlkLmpzIiwgIi8iKTsKICAgICAgfSwgeyBidWZmZXI6IDMsIGNyeXB0bzogNSwgbFlwb0kyOiAxMSB9XSwgMjogW2Z1bmN0aW9uKGUyLCB0LCBmMikgewogICAgICAgICEoZnVuY3Rpb24oZTMsIHQyLCBuLCByMiwgbywgaTIsIHUyLCBzMiwgYTIpIHsKICAgICAgICAgICFmdW5jdGlvbihlNCkgewogICAgICAgICAgICB2YXIgYTMgPSAidW5kZWZpbmVkIiAhPSB0eXBlb2YgVWludDhBcnJheSA/IFVpbnQ4QXJyYXkgOiBBcnJheSwgdDMgPSAiKyIuY2hhckNvZGVBdCgwKSwgbjIgPSAiLyIuY2hhckNvZGVBdCgwKSwgcjMgPSAiMCIuY2hhckNvZGVBdCgwKSwgbzIgPSAiYSIuY2hhckNvZGVBdCgwKSwgaTMgPSAiQSIuY2hhckNvZGVBdCgwKSwgdTMgPSAiLSIuY2hhckNvZGVBdCgwKSwgczMgPSAiXyIuY2hhckNvZGVBdCgwKTsKICAgICAgICAgICAgZnVuY3Rpb24gZjMoZTUpIHsKICAgICAgICAgICAgICBlNSA9IGU1LmNoYXJDb2RlQXQoMCk7CiAgICAgICAgICAgICAgcmV0dXJuIGU1ID09PSB0MyB8fCBlNSA9PT0gdTMgPyA2MiA6IGU1ID09PSBuMiB8fCBlNSA9PT0gczMgPyA2MyA6IGU1IDwgcjMgPyAtMSA6IGU1IDwgcjMgKyAxMCA/IGU1IC0gcjMgKyAyNiArIDI2IDogZTUgPCBpMyArIDI2ID8gZTUgLSBpMyA6IGU1IDwgbzIgKyAyNiA/IGU1IC0gbzIgKyAyNiA6IHZvaWQgMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBlNC50b0J5dGVBcnJheSA9IGZ1bmN0aW9uKGU1KSB7CiAgICAgICAgICAgICAgdmFyIHQ0LCBuMzsKICAgICAgICAgICAgICBpZiAoMCA8IGU1Lmxlbmd0aCAlIDQpIHRocm93IG5ldyBFcnJvcigiSW52YWxpZCBzdHJpbmcuIExlbmd0aCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNCIpOwogICAgICAgICAgICAgIHZhciByNCA9IGU1Lmxlbmd0aCwgcjQgPSAiPSIgPT09IGU1LmNoYXJBdChyNCAtIDIpID8gMiA6ICI9IiA9PT0gZTUuY2hhckF0KHI0IC0gMSkgPyAxIDogMCwgbzMgPSBuZXcgYTMoMyAqIGU1Lmxlbmd0aCAvIDQgLSByNCksIGk0ID0gMCA8IHI0ID8gZTUubGVuZ3RoIC0gNCA6IGU1Lmxlbmd0aCwgdTQgPSAwOwogICAgICAgICAgICAgIGZ1bmN0aW9uIHM0KGU2KSB7CiAgICAgICAgICAgICAgICBvM1t1NCsrXSA9IGU2OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBmb3IgKHQ0ID0gMDsgdDQgPCBpNDsgdDQgKz0gNCwgMCkgczQoKDE2NzExNjgwICYgKG4zID0gZjMoZTUuY2hhckF0KHQ0KSkgPDwgMTggfCBmMyhlNS5jaGFyQXQodDQgKyAxKSkgPDwgMTIgfCBmMyhlNS5jaGFyQXQodDQgKyAyKSkgPDwgNiB8IGYzKGU1LmNoYXJBdCh0NCArIDMpKSkpID4+IDE2KSwgczQoKDY1MjgwICYgbjMpID4+IDgpLCBzNCgyNTUgJiBuMyk7CiAgICAgICAgICAgICAgcmV0dXJuIDIgPT0gcjQgPyBzNCgyNTUgJiAobjMgPSBmMyhlNS5jaGFyQXQodDQpKSA8PCAyIHwgZjMoZTUuY2hhckF0KHQ0ICsgMSkpID4+IDQpKSA6IDEgPT0gcjQgJiYgKHM0KChuMyA9IGYzKGU1LmNoYXJBdCh0NCkpIDw8IDEwIHwgZjMoZTUuY2hhckF0KHQ0ICsgMSkpIDw8IDQgfCBmMyhlNS5jaGFyQXQodDQgKyAyKSkgPj4gMikgPj4gOCAmIDI1NSksIHM0KDI1NSAmIG4zKSksIG8zOwogICAgICAgICAgICB9LCBlNC5mcm9tQnl0ZUFycmF5ID0gZnVuY3Rpb24oZTUpIHsKICAgICAgICAgICAgICB2YXIgdDQsIG4zLCByNCwgbzMsIGk0ID0gZTUubGVuZ3RoICUgMywgdTQgPSAiIjsKICAgICAgICAgICAgICBmdW5jdGlvbiBzNChlNikgewogICAgICAgICAgICAgICAgcmV0dXJuICJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvIi5jaGFyQXQoZTYpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBmb3IgKHQ0ID0gMCwgcjQgPSBlNS5sZW5ndGggLSBpNDsgdDQgPCByNDsgdDQgKz0gMykgbjMgPSAoZTVbdDRdIDw8IDE2KSArIChlNVt0NCArIDFdIDw8IDgpICsgZTVbdDQgKyAyXSwgdTQgKz0gczQoKG8zID0gbjMpID4+IDE4ICYgNjMpICsgczQobzMgPj4gMTIgJiA2MykgKyBzNChvMyA+PiA2ICYgNjMpICsgczQoNjMgJiBvMyk7CiAgICAgICAgICAgICAgc3dpdGNoIChpNCkgewogICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICB1NCA9ICh1NCArPSBzNCgobjMgPSBlNVtlNS5sZW5ndGggLSAxXSkgPj4gMikpICsgczQobjMgPDwgNCAmIDYzKSArICI9PSI7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgICB1NCA9ICh1NCA9ICh1NCArPSBzNCgobjMgPSAoZTVbZTUubGVuZ3RoIC0gMl0gPDwgOCkgKyBlNVtlNS5sZW5ndGggLSAxXSkgPj4gMTApKSArIHM0KG4zID4+IDQgJiA2MykpICsgczQobjMgPDwgMiAmIDYzKSArICI9IjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIHU0OwogICAgICAgICAgICB9OwogICAgICAgICAgfSh2b2lkIDAgPT09IGYyID8gdGhpcy5iYXNlNjRqcyA9IHt9IDogZjIpOwogICAgICAgIH0pLmNhbGwodGhpcywgZTIoImxZcG9JMiIpLCAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygc2VsZiA/IHNlbGYgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDoge30sIGUyKCJidWZmZXIiKS5CdWZmZXIsIGFyZ3VtZW50c1szXSwgYXJndW1lbnRzWzRdLCBhcmd1bWVudHNbNV0sIGFyZ3VtZW50c1s2XSwgIi9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9iYXNlNjQtanMvbGliL2I2NC5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYmFzZTY0LWpzL2xpYiIpOwogICAgICB9LCB7IGJ1ZmZlcjogMywgbFlwb0kyOiAxMSB9XSwgMzogW2Z1bmN0aW9uKE8sIGUyLCBIMikgewogICAgICAgICEoZnVuY3Rpb24oZTMsIG4sIGYyLCByMiwgaCwgcCwgZywgeSwgdzIpIHsKICAgICAgICAgIHZhciBhMiA9IE8oImJhc2U2NC1qcyIpLCBpMiA9IE8oImllZWU3NTQiKTsKICAgICAgICAgIGZ1bmN0aW9uIGYyKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIGYyKSkgcmV0dXJuIG5ldyBmMihlNCwgdDIsIG4yKTsKICAgICAgICAgICAgdmFyIHIzLCBvMiwgaTMsIHUzLCBzMyA9IHR5cGVvZiBlNDsKICAgICAgICAgICAgaWYgKCJiYXNlNjQiID09PSB0MiAmJiAic3RyaW5nIiA9PSBzMykgZm9yIChlNCA9ICh1MyA9IGU0KS50cmltID8gdTMudHJpbSgpIDogdTMucmVwbGFjZSgvXlxzK3xccyskL2csICIiKTsgZTQubGVuZ3RoICUgNCAhPSAwOyApIGU0ICs9ICI9IjsKICAgICAgICAgICAgaWYgKCJudW1iZXIiID09IHMzKSByMyA9IGoyKGU0KTsKICAgICAgICAgICAgZWxzZSBpZiAoInN0cmluZyIgPT0gczMpIHIzID0gZjIuYnl0ZUxlbmd0aChlNCwgdDIpOwogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICBpZiAoIm9iamVjdCIgIT0gczMpIHRocm93IG5ldyBFcnJvcigiRmlyc3QgYXJndW1lbnQgbmVlZHMgdG8gYmUgYSBudW1iZXIsIGFycmF5IG9yIHN0cmluZy4iKTsKICAgICAgICAgICAgICByMyA9IGoyKGU0Lmxlbmd0aCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGYyLl91c2VUeXBlZEFycmF5cyA/IG8yID0gZjIuX2F1Z21lbnQobmV3IFVpbnQ4QXJyYXkocjMpKSA6ICgobzIgPSB0aGlzKS5sZW5ndGggPSByMywgbzIuX2lzQnVmZmVyID0gdHJ1ZSksIGYyLl91c2VUeXBlZEFycmF5cyAmJiAibnVtYmVyIiA9PSB0eXBlb2YgZTQuYnl0ZUxlbmd0aCkgbzIuX3NldChlNCk7CiAgICAgICAgICAgIGVsc2UgaWYgKEModTMgPSBlNCkgfHwgZjIuaXNCdWZmZXIodTMpIHx8IHUzICYmICJvYmplY3QiID09IHR5cGVvZiB1MyAmJiAibnVtYmVyIiA9PSB0eXBlb2YgdTMubGVuZ3RoKSBmb3IgKGkzID0gMDsgaTMgPCByMzsgaTMrKykgZjIuaXNCdWZmZXIoZTQpID8gbzJbaTNdID0gZTQucmVhZFVJbnQ4KGkzKSA6IG8yW2kzXSA9IGU0W2kzXTsKICAgICAgICAgICAgZWxzZSBpZiAoInN0cmluZyIgPT0gczMpIG8yLndyaXRlKGU0LCAwLCB0Mik7CiAgICAgICAgICAgIGVsc2UgaWYgKCJudW1iZXIiID09IHMzICYmICFmMi5fdXNlVHlwZWRBcnJheXMgJiYgIW4yKSBmb3IgKGkzID0gMDsgaTMgPCByMzsgaTMrKykgbzJbaTNdID0gMDsKICAgICAgICAgICAgcmV0dXJuIG8yOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gYihlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICByZXR1cm4gZjIuX2NoYXJzV3JpdHRlbiA9IGMyKGZ1bmN0aW9uKGU1KSB7CiAgICAgICAgICAgICAgZm9yICh2YXIgdDMgPSBbXSwgbjMgPSAwOyBuMyA8IGU1Lmxlbmd0aDsgbjMrKykgdDMucHVzaCgyNTUgJiBlNS5jaGFyQ29kZUF0KG4zKSk7CiAgICAgICAgICAgICAgcmV0dXJuIHQzOwogICAgICAgICAgICB9KHQyKSwgZTQsIG4yLCByMyk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBtMihlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICByZXR1cm4gZjIuX2NoYXJzV3JpdHRlbiA9IGMyKGZ1bmN0aW9uKGU1KSB7CiAgICAgICAgICAgICAgZm9yICh2YXIgdDMsIG4zLCByNCA9IFtdLCBvMiA9IDA7IG8yIDwgZTUubGVuZ3RoOyBvMisrKSBuMyA9IGU1LmNoYXJDb2RlQXQobzIpLCB0MyA9IG4zID4+IDgsIG4zID0gbjMgJSAyNTYsIHI0LnB1c2gobjMpLCByNC5wdXNoKHQzKTsKICAgICAgICAgICAgICByZXR1cm4gcjQ7CiAgICAgICAgICAgIH0odDIpLCBlNCwgbjIsIHIzKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHYyKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgdmFyIHIzID0gIiI7CiAgICAgICAgICAgIG4yID0gTWF0aC5taW4oZTQubGVuZ3RoLCBuMik7CiAgICAgICAgICAgIGZvciAodmFyIG8yID0gdDI7IG8yIDwgbjI7IG8yKyspIHIzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZTRbbzJdKTsKICAgICAgICAgICAgcmV0dXJuIHIzOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gbyhlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICByMyB8fCAoZCgiYm9vbGVhbiIgPT0gdHlwZW9mIG4yLCAibWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbiIpLCBkKG51bGwgIT0gdDIsICJtaXNzaW5nIG9mZnNldCIpLCBkKHQyICsgMSA8IGU0Lmxlbmd0aCwgIlRyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoIikpOwogICAgICAgICAgICB2YXIgbzIsIHIzID0gZTQubGVuZ3RoOwogICAgICAgICAgICBpZiAoIShyMyA8PSB0MikpIHJldHVybiBuMiA/IChvMiA9IGU0W3QyXSwgdDIgKyAxIDwgcjMgJiYgKG8yIHw9IGU0W3QyICsgMV0gPDwgOCkpIDogKG8yID0gZTRbdDJdIDw8IDgsIHQyICsgMSA8IHIzICYmIChvMiB8PSBlNFt0MiArIDFdKSksIG8yOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gdTIoZTQsIHQyLCBuMiwgcjMpIHsKICAgICAgICAgICAgcjMgfHwgKGQoImJvb2xlYW4iID09IHR5cGVvZiBuMiwgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZChudWxsICE9IHQyLCAibWlzc2luZyBvZmZzZXQiKSwgZCh0MiArIDMgPCBlNC5sZW5ndGgsICJUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCIpKTsKICAgICAgICAgICAgdmFyIG8yLCByMyA9IGU0Lmxlbmd0aDsKICAgICAgICAgICAgaWYgKCEocjMgPD0gdDIpKSByZXR1cm4gbjIgPyAodDIgKyAyIDwgcjMgJiYgKG8yID0gZTRbdDIgKyAyXSA8PCAxNiksIHQyICsgMSA8IHIzICYmIChvMiB8PSBlNFt0MiArIDFdIDw8IDgpLCBvMiB8PSBlNFt0Ml0sIHQyICsgMyA8IHIzICYmIChvMiArPSBlNFt0MiArIDNdIDw8IDI0ID4+PiAwKSkgOiAodDIgKyAxIDwgcjMgJiYgKG8yID0gZTRbdDIgKyAxXSA8PCAxNiksIHQyICsgMiA8IHIzICYmIChvMiB8PSBlNFt0MiArIDJdIDw8IDgpLCB0MiArIDMgPCByMyAmJiAobzIgfD0gZTRbdDIgKyAzXSksIG8yICs9IGU0W3QyXSA8PCAyNCA+Pj4gMCksIG8yOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gXyhlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICBpZiAocjMgfHwgKGQoImJvb2xlYW4iID09IHR5cGVvZiBuMiwgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZChudWxsICE9IHQyLCAibWlzc2luZyBvZmZzZXQiKSwgZCh0MiArIDEgPCBlNC5sZW5ndGgsICJUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCIpKSwgIShlNC5sZW5ndGggPD0gdDIpKSByZXR1cm4gcjMgPSBvKGU0LCB0MiwgbjIsIHRydWUpLCAzMjc2OCAmIHIzID8gLTEgKiAoNjU1MzUgLSByMyArIDEpIDogcjM7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBFKGU0LCB0MiwgbjIsIHIzKSB7CiAgICAgICAgICAgIGlmIChyMyB8fCAoZCgiYm9vbGVhbiIgPT0gdHlwZW9mIG4yLCAibWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbiIpLCBkKG51bGwgIT0gdDIsICJtaXNzaW5nIG9mZnNldCIpLCBkKHQyICsgMyA8IGU0Lmxlbmd0aCwgIlRyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoIikpLCAhKGU0Lmxlbmd0aCA8PSB0MikpIHJldHVybiByMyA9IHUyKGU0LCB0MiwgbjIsIHRydWUpLCAyMTQ3NDgzNjQ4ICYgcjMgPyAtMSAqICg0Mjk0OTY3Mjk1IC0gcjMgKyAxKSA6IHIzOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gSShlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICByZXR1cm4gcjMgfHwgKGQoImJvb2xlYW4iID09IHR5cGVvZiBuMiwgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZCh0MiArIDMgPCBlNC5sZW5ndGgsICJUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCIpKSwgaTIucmVhZChlNCwgdDIsIG4yLCAyMywgNCk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBBKGU0LCB0MiwgbjIsIHIzKSB7CiAgICAgICAgICAgIHJldHVybiByMyB8fCAoZCgiYm9vbGVhbiIgPT0gdHlwZW9mIG4yLCAibWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbiIpLCBkKHQyICsgNyA8IGU0Lmxlbmd0aCwgIlRyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoIikpLCBpMi5yZWFkKGU0LCB0MiwgbjIsIDUyLCA4KTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHMyKGU0LCB0MiwgbjIsIHIzLCBvMikgewogICAgICAgICAgICBvMiB8fCAoZChudWxsICE9IHQyLCAibWlzc2luZyB2YWx1ZSIpLCBkKCJib29sZWFuIiA9PSB0eXBlb2YgcjMsICJtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuIiksIGQobnVsbCAhPSBuMiwgIm1pc3Npbmcgb2Zmc2V0IiksIGQobjIgKyAxIDwgZTQubGVuZ3RoLCAidHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoIiksIFkyKHQyLCA2NTUzNSkpOwogICAgICAgICAgICBvMiA9IGU0Lmxlbmd0aDsKICAgICAgICAgICAgaWYgKCEobzIgPD0gbjIpKSBmb3IgKHZhciBpMyA9IDAsIHUzID0gTWF0aC5taW4obzIgLSBuMiwgMik7IGkzIDwgdTM7IGkzKyspIGU0W24yICsgaTNdID0gKHQyICYgMjU1IDw8IDggKiAocjMgPyBpMyA6IDEgLSBpMykpID4+PiA4ICogKHIzID8gaTMgOiAxIC0gaTMpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gbDIoZTQsIHQyLCBuMiwgcjMsIG8yKSB7CiAgICAgICAgICAgIG8yIHx8IChkKG51bGwgIT0gdDIsICJtaXNzaW5nIHZhbHVlIiksIGQoImJvb2xlYW4iID09IHR5cGVvZiByMywgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZChudWxsICE9IG4yLCAibWlzc2luZyBvZmZzZXQiKSwgZChuMiArIDMgPCBlNC5sZW5ndGgsICJ0cnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgiKSwgWTIodDIsIDQyOTQ5NjcyOTUpKTsKICAgICAgICAgICAgbzIgPSBlNC5sZW5ndGg7CiAgICAgICAgICAgIGlmICghKG8yIDw9IG4yKSkgZm9yICh2YXIgaTMgPSAwLCB1MyA9IE1hdGgubWluKG8yIC0gbjIsIDQpOyBpMyA8IHUzOyBpMysrKSBlNFtuMiArIGkzXSA9IHQyID4+PiA4ICogKHIzID8gaTMgOiAzIC0gaTMpICYgMjU1OwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gQjIoZTQsIHQyLCBuMiwgcjMsIG8yKSB7CiAgICAgICAgICAgIG8yIHx8IChkKG51bGwgIT0gdDIsICJtaXNzaW5nIHZhbHVlIiksIGQoImJvb2xlYW4iID09IHR5cGVvZiByMywgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZChudWxsICE9IG4yLCAibWlzc2luZyBvZmZzZXQiKSwgZChuMiArIDEgPCBlNC5sZW5ndGgsICJUcnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgiKSwgRih0MiwgMzI3NjcsIC0zMjc2OCkpLCBlNC5sZW5ndGggPD0gbjIgfHwgczIoZTQsIDAgPD0gdDIgPyB0MiA6IDY1NTM1ICsgdDIgKyAxLCBuMiwgcjMsIG8yKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEwyKGU0LCB0MiwgbjIsIHIzLCBvMikgewogICAgICAgICAgICBvMiB8fCAoZChudWxsICE9IHQyLCAibWlzc2luZyB2YWx1ZSIpLCBkKCJib29sZWFuIiA9PSB0eXBlb2YgcjMsICJtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuIiksIGQobnVsbCAhPSBuMiwgIm1pc3Npbmcgb2Zmc2V0IiksIGQobjIgKyAzIDwgZTQubGVuZ3RoLCAiVHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoIiksIEYodDIsIDIxNDc0ODM2NDcsIC0yMTQ3NDgzNjQ4KSksIGU0Lmxlbmd0aCA8PSBuMiB8fCBsMihlNCwgMCA8PSB0MiA/IHQyIDogNDI5NDk2NzI5NSArIHQyICsgMSwgbjIsIHIzLCBvMik7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBVMihlNCwgdDIsIG4yLCByMywgbzIpIHsKICAgICAgICAgICAgbzIgfHwgKGQobnVsbCAhPSB0MiwgIm1pc3NpbmcgdmFsdWUiKSwgZCgiYm9vbGVhbiIgPT0gdHlwZW9mIHIzLCAibWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbiIpLCBkKG51bGwgIT0gbjIsICJtaXNzaW5nIG9mZnNldCIpLCBkKG4yICsgMyA8IGU0Lmxlbmd0aCwgIlRyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCIpLCBEMih0MiwgMzQwMjgyMzQ2NjM4NTI4ODZlMjIsIC0zNDAyODIzNDY2Mzg1Mjg4NmUyMikpLCBlNC5sZW5ndGggPD0gbjIgfHwgaTIud3JpdGUoZTQsIHQyLCBuMiwgcjMsIDIzLCA0KTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHgoZTQsIHQyLCBuMiwgcjMsIG8yKSB7CiAgICAgICAgICAgIG8yIHx8IChkKG51bGwgIT0gdDIsICJtaXNzaW5nIHZhbHVlIiksIGQoImJvb2xlYW4iID09IHR5cGVvZiByMywgIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4iKSwgZChudWxsICE9IG4yLCAibWlzc2luZyBvZmZzZXQiKSwgZChuMiArIDcgPCBlNC5sZW5ndGgsICJUcnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgiKSwgRDIodDIsIDE3OTc2OTMxMzQ4NjIzMTU3ZTI5MiwgLTE3OTc2OTMxMzQ4NjIzMTU3ZTI5MikpLCBlNC5sZW5ndGggPD0gbjIgfHwgaTIud3JpdGUoZTQsIHQyLCBuMiwgcjMsIDUyLCA4KTsKICAgICAgICAgIH0KICAgICAgICAgIEgyLkJ1ZmZlciA9IGYyLCBIMi5TbG93QnVmZmVyID0gZjIsIEgyLklOU1BFQ1RfTUFYX0JZVEVTID0gNTAsIGYyLnBvb2xTaXplID0gODE5MiwgZjIuX3VzZVR5cGVkQXJyYXlzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgdmFyIGU0ID0gbmV3IEFycmF5QnVmZmVyKDApLCB0MiA9IG5ldyBVaW50OEFycmF5KGU0KTsKICAgICAgICAgICAgICByZXR1cm4gdDIuZm9vID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gNDI7CiAgICAgICAgICAgICAgfSwgNDIgPT09IHQyLmZvbygpICYmICJmdW5jdGlvbiIgPT0gdHlwZW9mIHQyLnN1YmFycmF5OwogICAgICAgICAgICB9IGNhdGNoIChlNSkgewogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgICAgfSgpLCBmMi5pc0VuY29kaW5nID0gZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgc3dpdGNoIChTdHJpbmcoZTQpLnRvTG93ZXJDYXNlKCkpIHsKICAgICAgICAgICAgICBjYXNlICJoZXgiOgogICAgICAgICAgICAgIGNhc2UgInV0ZjgiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi04IjoKICAgICAgICAgICAgICBjYXNlICJhc2NpaSI6CiAgICAgICAgICAgICAgY2FzZSAiYmluYXJ5IjoKICAgICAgICAgICAgICBjYXNlICJiYXNlNjQiOgogICAgICAgICAgICAgIGNhc2UgInJhdyI6CiAgICAgICAgICAgICAgY2FzZSAidWNzMiI6CiAgICAgICAgICAgICAgY2FzZSAidWNzLTIiOgogICAgICAgICAgICAgIGNhc2UgInV0ZjE2bGUiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi0xNmxlIjoKICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0sIGYyLmlzQnVmZmVyID0gZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgcmV0dXJuICEobnVsbCA9PSBlNCB8fCAhZTQuX2lzQnVmZmVyKTsKICAgICAgICAgIH0sIGYyLmJ5dGVMZW5ndGggPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgdmFyIG4yOwogICAgICAgICAgICBzd2l0Y2ggKGU0ICs9ICIiLCB0MiB8fCAidXRmOCIpIHsKICAgICAgICAgICAgICBjYXNlICJoZXgiOgogICAgICAgICAgICAgICAgbjIgPSBlNC5sZW5ndGggLyAyOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAidXRmOCI6CiAgICAgICAgICAgICAgY2FzZSAidXRmLTgiOgogICAgICAgICAgICAgICAgbjIgPSBUKGU0KS5sZW5ndGg7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlICJhc2NpaSI6CiAgICAgICAgICAgICAgY2FzZSAiYmluYXJ5IjoKICAgICAgICAgICAgICBjYXNlICJyYXciOgogICAgICAgICAgICAgICAgbjIgPSBlNC5sZW5ndGg7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlICJiYXNlNjQiOgogICAgICAgICAgICAgICAgbjIgPSBNMihlNCkubGVuZ3RoOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAidWNzMiI6CiAgICAgICAgICAgICAgY2FzZSAidWNzLTIiOgogICAgICAgICAgICAgIGNhc2UgInV0ZjE2bGUiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi0xNmxlIjoKICAgICAgICAgICAgICAgIG4yID0gMiAqIGU0Lmxlbmd0aDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlVua25vd24gZW5jb2RpbmciKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbjI7CiAgICAgICAgICB9LCBmMi5jb25jYXQgPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgaWYgKGQoQyhlNCksICJVc2FnZTogQnVmZmVyLmNvbmNhdChsaXN0LCBbdG90YWxMZW5ndGhdKVxubGlzdCBzaG91bGQgYmUgYW4gQXJyYXkuIiksIDAgPT09IGU0Lmxlbmd0aCkgcmV0dXJuIG5ldyBmMigwKTsKICAgICAgICAgICAgaWYgKDEgPT09IGU0Lmxlbmd0aCkgcmV0dXJuIGU0WzBdOwogICAgICAgICAgICBpZiAoIm51bWJlciIgIT0gdHlwZW9mIHQyKSBmb3IgKG8yID0gdDIgPSAwOyBvMiA8IGU0Lmxlbmd0aDsgbzIrKykgdDIgKz0gZTRbbzJdLmxlbmd0aDsKICAgICAgICAgICAgZm9yICh2YXIgbjIgPSBuZXcgZjIodDIpLCByMyA9IDAsIG8yID0gMDsgbzIgPCBlNC5sZW5ndGg7IG8yKyspIHsKICAgICAgICAgICAgICB2YXIgaTMgPSBlNFtvMl07CiAgICAgICAgICAgICAgaTMuY29weShuMiwgcjMpLCByMyArPSBpMy5sZW5ndGg7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIG4yOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24oZTQsIHQyLCBuMiwgcjMpIHsKICAgICAgICAgICAgaXNGaW5pdGUodDIpID8gaXNGaW5pdGUobjIpIHx8IChyMyA9IG4yLCBuMiA9IHZvaWQgMCkgOiAoYTMgPSByMywgcjMgPSB0MiwgdDIgPSBuMiwgbjIgPSBhMyksIHQyID0gTnVtYmVyKHQyKSB8fCAwOwogICAgICAgICAgICB2YXIgbzIsIGkzLCB1MywgczMsIGEzID0gdGhpcy5sZW5ndGggLSB0MjsKICAgICAgICAgICAgc3dpdGNoICgoIW4yIHx8IGEzIDwgKG4yID0gTnVtYmVyKG4yKSkpICYmIChuMiA9IGEzKSwgcjMgPSBTdHJpbmcocjMgfHwgInV0ZjgiKS50b0xvd2VyQ2FzZSgpKSB7CiAgICAgICAgICAgICAgY2FzZSAiaGV4IjoKICAgICAgICAgICAgICAgIG8yID0gZnVuY3Rpb24oZTUsIHQzLCBuMywgcjQpIHsKICAgICAgICAgICAgICAgICAgbjMgPSBOdW1iZXIobjMpIHx8IDA7CiAgICAgICAgICAgICAgICAgIHZhciBvMyA9IGU1Lmxlbmd0aCAtIG4zOwogICAgICAgICAgICAgICAgICAoIXI0IHx8IG8zIDwgKHI0ID0gTnVtYmVyKHI0KSkpICYmIChyNCA9IG8zKSwgZCgobzMgPSB0My5sZW5ndGgpICUgMiA9PSAwLCAiSW52YWxpZCBoZXggc3RyaW5nIiksIG8zIC8gMiA8IHI0ICYmIChyNCA9IG8zIC8gMik7CiAgICAgICAgICAgICAgICAgIGZvciAodmFyIGk0ID0gMDsgaTQgPCByNDsgaTQrKykgewogICAgICAgICAgICAgICAgICAgIHZhciB1NCA9IHBhcnNlSW50KHQzLnN1YnN0cigyICogaTQsIDIpLCAxNik7CiAgICAgICAgICAgICAgICAgICAgZCghaXNOYU4odTQpLCAiSW52YWxpZCBoZXggc3RyaW5nIiksIGU1W24zICsgaTRdID0gdTQ7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgcmV0dXJuIGYyLl9jaGFyc1dyaXR0ZW4gPSAyICogaTQsIGk0OwogICAgICAgICAgICAgICAgfSh0aGlzLCBlNCwgdDIsIG4yKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgInV0ZjgiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi04IjoKICAgICAgICAgICAgICAgIGkzID0gdGhpcywgdTMgPSB0MiwgczMgPSBuMiwgbzIgPSBmMi5fY2hhcnNXcml0dGVuID0gYzIoVChlNCksIGkzLCB1MywgczMpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAiYXNjaWkiOgogICAgICAgICAgICAgIGNhc2UgImJpbmFyeSI6CiAgICAgICAgICAgICAgICBvMiA9IGIodGhpcywgZTQsIHQyLCBuMik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlICJiYXNlNjQiOgogICAgICAgICAgICAgICAgaTMgPSB0aGlzLCB1MyA9IHQyLCBzMyA9IG4yLCBvMiA9IGYyLl9jaGFyc1dyaXR0ZW4gPSBjMihNMihlNCksIGkzLCB1MywgczMpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAidWNzMiI6CiAgICAgICAgICAgICAgY2FzZSAidWNzLTIiOgogICAgICAgICAgICAgIGNhc2UgInV0ZjE2bGUiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi0xNmxlIjoKICAgICAgICAgICAgICAgIG8yID0gbTIodGhpcywgZTQsIHQyLCBuMik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJVbmtub3duIGVuY29kaW5nIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIG8yOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oZTQsIHQyLCBuMikgewogICAgICAgICAgICB2YXIgcjMsIG8yLCBpMywgdTMsIHMzID0gdGhpczsKICAgICAgICAgICAgaWYgKGU0ID0gU3RyaW5nKGU0IHx8ICJ1dGY4IikudG9Mb3dlckNhc2UoKSwgdDIgPSBOdW1iZXIodDIpIHx8IDAsIChuMiA9IHZvaWQgMCAhPT0gbjIgPyBOdW1iZXIobjIpIDogczMubGVuZ3RoKSA9PT0gdDIpIHJldHVybiAiIjsKICAgICAgICAgICAgc3dpdGNoIChlNCkgewogICAgICAgICAgICAgIGNhc2UgImhleCI6CiAgICAgICAgICAgICAgICByMyA9IGZ1bmN0aW9uKGU1LCB0MywgbjMpIHsKICAgICAgICAgICAgICAgICAgdmFyIHI0ID0gZTUubGVuZ3RoOwogICAgICAgICAgICAgICAgICAoIXQzIHx8IHQzIDwgMCkgJiYgKHQzID0gMCk7CiAgICAgICAgICAgICAgICAgICghbjMgfHwgbjMgPCAwIHx8IHI0IDwgbjMpICYmIChuMyA9IHI0KTsKICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbzMgPSAiIiwgaTQgPSB0MzsgaTQgPCBuMzsgaTQrKykgbzMgKz0gazIoZTVbaTRdKTsKICAgICAgICAgICAgICAgICAgcmV0dXJuIG8zOwogICAgICAgICAgICAgICAgfShzMywgdDIsIG4yKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgInV0ZjgiOgogICAgICAgICAgICAgIGNhc2UgInV0Zi04IjoKICAgICAgICAgICAgICAgIHIzID0gZnVuY3Rpb24oZTUsIHQzLCBuMykgewogICAgICAgICAgICAgICAgICB2YXIgcjQgPSAiIiwgbzMgPSAiIjsKICAgICAgICAgICAgICAgICAgbjMgPSBNYXRoLm1pbihlNS5sZW5ndGgsIG4zKTsKICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaTQgPSB0MzsgaTQgPCBuMzsgaTQrKykgZTVbaTRdIDw9IDEyNyA/IChyNCArPSBOKG8zKSArIFN0cmluZy5mcm9tQ2hhckNvZGUoZTVbaTRdKSwgbzMgPSAiIikgOiBvMyArPSAiJSIgKyBlNVtpNF0udG9TdHJpbmcoMTYpOwogICAgICAgICAgICAgICAgICByZXR1cm4gcjQgKyBOKG8zKTsKICAgICAgICAgICAgICAgIH0oczMsIHQyLCBuMik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlICJhc2NpaSI6CiAgICAgICAgICAgICAgY2FzZSAiYmluYXJ5IjoKICAgICAgICAgICAgICAgIHIzID0gdjIoczMsIHQyLCBuMik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlICJiYXNlNjQiOgogICAgICAgICAgICAgICAgbzIgPSBzMywgdTMgPSBuMiwgcjMgPSAwID09PSAoaTMgPSB0MikgJiYgdTMgPT09IG8yLmxlbmd0aCA/IGEyLmZyb21CeXRlQXJyYXkobzIpIDogYTIuZnJvbUJ5dGVBcnJheShvMi5zbGljZShpMywgdTMpKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgInVjczIiOgogICAgICAgICAgICAgIGNhc2UgInVjcy0yIjoKICAgICAgICAgICAgICBjYXNlICJ1dGYxNmxlIjoKICAgICAgICAgICAgICBjYXNlICJ1dGYtMTZsZSI6CiAgICAgICAgICAgICAgICByMyA9IGZ1bmN0aW9uKGU1LCB0MywgbjMpIHsKICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcjQgPSBlNS5zbGljZSh0MywgbjMpLCBvMyA9ICIiLCBpNCA9IDA7IGk0IDwgcjQubGVuZ3RoOyBpNCArPSAyKSBvMyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHI0W2k0XSArIDI1NiAqIHI0W2k0ICsgMV0pOwogICAgICAgICAgICAgICAgICByZXR1cm4gbzM7CiAgICAgICAgICAgICAgICB9KHMzLCB0MiwgbjIpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiVW5rbm93biBlbmNvZGluZyIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiByMzsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogIkJ1ZmZlciIsIGRhdGE6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHRoaXMuX2FyciB8fCB0aGlzLCAwKSB9OwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbihlNCwgdDIsIG4yLCByMykgewogICAgICAgICAgICBpZiAodDIgPSB0MiB8fCAwLCAocjMgPSByMyB8fCAwID09PSByMyA/IHIzIDogdGhpcy5sZW5ndGgpICE9PSAobjIgPSBuMiB8fCAwKSAmJiAwICE9PSBlNC5sZW5ndGggJiYgMCAhPT0gdGhpcy5sZW5ndGgpIHsKICAgICAgICAgICAgICBkKG4yIDw9IHIzLCAic291cmNlRW5kIDwgc291cmNlU3RhcnQiKSwgZCgwIDw9IHQyICYmIHQyIDwgZTQubGVuZ3RoLCAidGFyZ2V0U3RhcnQgb3V0IG9mIGJvdW5kcyIpLCBkKDAgPD0gbjIgJiYgbjIgPCB0aGlzLmxlbmd0aCwgInNvdXJjZVN0YXJ0IG91dCBvZiBib3VuZHMiKSwgZCgwIDw9IHIzICYmIHIzIDw9IHRoaXMubGVuZ3RoLCAic291cmNlRW5kIG91dCBvZiBib3VuZHMiKSwgcjMgPiB0aGlzLmxlbmd0aCAmJiAocjMgPSB0aGlzLmxlbmd0aCk7CiAgICAgICAgICAgICAgdmFyIG8yID0gKHIzID0gZTQubGVuZ3RoIC0gdDIgPCByMyAtIG4yID8gZTQubGVuZ3RoIC0gdDIgKyBuMiA6IHIzKSAtIG4yOwogICAgICAgICAgICAgIGlmIChvMiA8IDEwMCB8fCAhZjIuX3VzZVR5cGVkQXJyYXlzKSBmb3IgKHZhciBpMyA9IDA7IGkzIDwgbzI7IGkzKyspIGU0W2kzICsgdDJdID0gdGhpc1tpMyArIG4yXTsKICAgICAgICAgICAgICBlbHNlIGU0Ll9zZXQodGhpcy5zdWJhcnJheShuMiwgbjIgKyBvMiksIHQyKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24oZTQsIHQyKSB7CiAgICAgICAgICAgIHZhciBuMiA9IHRoaXMubGVuZ3RoOwogICAgICAgICAgICBpZiAoZTQgPSBTMihlNCwgbjIsIDApLCB0MiA9IFMyKHQyLCBuMiwgbjIpLCBmMi5fdXNlVHlwZWRBcnJheXMpIHJldHVybiBmMi5fYXVnbWVudCh0aGlzLnN1YmFycmF5KGU0LCB0MikpOwogICAgICAgICAgICBmb3IgKHZhciByMyA9IHQyIC0gZTQsIG8yID0gbmV3IGYyKHIzLCB2b2lkIDAsIHRydWUpLCBpMyA9IDA7IGkzIDwgcjM7IGkzKyspIG8yW2kzXSA9IHRoaXNbaTMgKyBlNF07CiAgICAgICAgICAgIHJldHVybiBvMjsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbihlNCkgewogICAgICAgICAgICByZXR1cm4gY29uc29sZS5sb2coIi5nZXQoKSBpcyBkZXByZWNhdGVkLiBBY2Nlc3MgdXNpbmcgYXJyYXkgaW5kZXhlcyBpbnN0ZWFkLiIpLCB0aGlzLnJlYWRVSW50OChlNCk7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24oZTQsIHQyKSB7CiAgICAgICAgICAgIHJldHVybiBjb25zb2xlLmxvZygiLnNldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuIiksIHRoaXMud3JpdGVVSW50OChlNCwgdDIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWRVSW50OCA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICBpZiAodDIgfHwgKGQobnVsbCAhPSBlNCwgIm1pc3Npbmcgb2Zmc2V0IiksIGQoZTQgPCB0aGlzLmxlbmd0aCwgIlRyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoIikpLCAhKGU0ID49IHRoaXMubGVuZ3RoKSkgcmV0dXJuIHRoaXNbZTRdOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWRVSW50MTZMRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gbyh0aGlzLCBlNCwgdHJ1ZSwgdDIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWRVSW50MTZCRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gbyh0aGlzLCBlNCwgZmFsc2UsIHQyKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS5yZWFkVUludDMyTEUgPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgcmV0dXJuIHUyKHRoaXMsIGU0LCB0cnVlLCB0Mik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUucmVhZFVJbnQzMkJFID0gZnVuY3Rpb24oZTQsIHQyKSB7CiAgICAgICAgICAgIHJldHVybiB1Mih0aGlzLCBlNCwgZmFsc2UsIHQyKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS5yZWFkSW50OCA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICBpZiAodDIgfHwgKGQobnVsbCAhPSBlNCwgIm1pc3Npbmcgb2Zmc2V0IiksIGQoZTQgPCB0aGlzLmxlbmd0aCwgIlRyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoIikpLCAhKGU0ID49IHRoaXMubGVuZ3RoKSkgcmV0dXJuIDEyOCAmIHRoaXNbZTRdID8gLTEgKiAoMjU1IC0gdGhpc1tlNF0gKyAxKSA6IHRoaXNbZTRdOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWRJbnQxNkxFID0gZnVuY3Rpb24oZTQsIHQyKSB7CiAgICAgICAgICAgIHJldHVybiBfKHRoaXMsIGU0LCB0cnVlLCB0Mik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUucmVhZEludDE2QkUgPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgcmV0dXJuIF8odGhpcywgZTQsIGZhbHNlLCB0Mik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUucmVhZEludDMyTEUgPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgcmV0dXJuIEUodGhpcywgZTQsIHRydWUsIHQyKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS5yZWFkSW50MzJCRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gRSh0aGlzLCBlNCwgZmFsc2UsIHQyKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS5yZWFkRmxvYXRMRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gSSh0aGlzLCBlNCwgdHJ1ZSwgdDIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWRGbG9hdEJFID0gZnVuY3Rpb24oZTQsIHQyKSB7CiAgICAgICAgICAgIHJldHVybiBJKHRoaXMsIGU0LCBmYWxzZSwgdDIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWREb3VibGVMRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gQSh0aGlzLCBlNCwgdHJ1ZSwgdDIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLnJlYWREb3VibGVCRSA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gQSh0aGlzLCBlNCwgZmFsc2UsIHQyKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS53cml0ZVVJbnQ4ID0gZnVuY3Rpb24oZTQsIHQyLCBuMikgewogICAgICAgICAgICBuMiB8fCAoZChudWxsICE9IGU0LCAibWlzc2luZyB2YWx1ZSIpLCBkKG51bGwgIT0gdDIsICJtaXNzaW5nIG9mZnNldCIpLCBkKHQyIDwgdGhpcy5sZW5ndGgsICJ0cnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgiKSwgWTIoZTQsIDI1NSkpLCB0MiA+PSB0aGlzLmxlbmd0aCB8fCAodGhpc1t0Ml0gPSBlNCk7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUud3JpdGVVSW50MTZMRSA9IGZ1bmN0aW9uKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgczIodGhpcywgZTQsIHQyLCB0cnVlLCBuMik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUud3JpdGVVSW50MTZCRSA9IGZ1bmN0aW9uKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgczIodGhpcywgZTQsIHQyLCBmYWxzZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlVUludDMyTEUgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIGwyKHRoaXMsIGU0LCB0MiwgdHJ1ZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlVUludDMyQkUgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIGwyKHRoaXMsIGU0LCB0MiwgZmFsc2UsIG4yKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIG4yIHx8IChkKG51bGwgIT0gZTQsICJtaXNzaW5nIHZhbHVlIiksIGQobnVsbCAhPSB0MiwgIm1pc3Npbmcgb2Zmc2V0IiksIGQodDIgPCB0aGlzLmxlbmd0aCwgIlRyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCIpLCBGKGU0LCAxMjcsIC0xMjgpKSwgdDIgPj0gdGhpcy5sZW5ndGggfHwgKDAgPD0gZTQgPyB0aGlzLndyaXRlVUludDgoZTQsIHQyLCBuMikgOiB0aGlzLndyaXRlVUludDgoMjU1ICsgZTQgKyAxLCB0MiwgbjIpKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS53cml0ZUludDE2TEUgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIEIyKHRoaXMsIGU0LCB0MiwgdHJ1ZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlSW50MTZCRSA9IGZ1bmN0aW9uKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgQjIodGhpcywgZTQsIHQyLCBmYWxzZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlSW50MzJMRSA9IGZ1bmN0aW9uKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgTDIodGhpcywgZTQsIHQyLCB0cnVlLCBuMik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUud3JpdGVJbnQzMkJFID0gZnVuY3Rpb24oZTQsIHQyLCBuMikgewogICAgICAgICAgICBMMih0aGlzLCBlNCwgdDIsIGZhbHNlLCBuMik7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUud3JpdGVGbG9hdExFID0gZnVuY3Rpb24oZTQsIHQyLCBuMikgewogICAgICAgICAgICBVMih0aGlzLCBlNCwgdDIsIHRydWUsIG4yKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS53cml0ZUZsb2F0QkUgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIFUyKHRoaXMsIGU0LCB0MiwgZmFsc2UsIG4yKTsKICAgICAgICAgIH0sIGYyLnByb3RvdHlwZS53cml0ZURvdWJsZUxFID0gZnVuY3Rpb24oZTQsIHQyLCBuMikgewogICAgICAgICAgICB4KHRoaXMsIGU0LCB0MiwgdHJ1ZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIHgodGhpcywgZTQsIHQyLCBmYWxzZSwgbjIpOwogICAgICAgICAgfSwgZjIucHJvdG90eXBlLmZpbGwgPSBmdW5jdGlvbihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIGlmICh0MiA9IHQyIHx8IDAsIG4yID0gbjIgfHwgdGhpcy5sZW5ndGgsIGQoIm51bWJlciIgPT0gdHlwZW9mIChlNCA9ICJzdHJpbmciID09IHR5cGVvZiAoZTQgPSBlNCB8fCAwKSA/IGU0LmNoYXJDb2RlQXQoMCkgOiBlNCkgJiYgIWlzTmFOKGU0KSwgInZhbHVlIGlzIG5vdCBhIG51bWJlciIpLCBkKHQyIDw9IG4yLCAiZW5kIDwgc3RhcnQiKSwgbjIgIT09IHQyICYmIDAgIT09IHRoaXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgZCgwIDw9IHQyICYmIHQyIDwgdGhpcy5sZW5ndGgsICJzdGFydCBvdXQgb2YgYm91bmRzIiksIGQoMCA8PSBuMiAmJiBuMiA8PSB0aGlzLmxlbmd0aCwgImVuZCBvdXQgb2YgYm91bmRzIik7CiAgICAgICAgICAgICAgZm9yICh2YXIgcjMgPSB0MjsgcjMgPCBuMjsgcjMrKykgdGhpc1tyM10gPSBlNDsKICAgICAgICAgICAgfQogICAgICAgICAgfSwgZjIucHJvdG90eXBlLmluc3BlY3QgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgZm9yICh2YXIgZTQgPSBbXSwgdDIgPSB0aGlzLmxlbmd0aCwgbjIgPSAwOyBuMiA8IHQyOyBuMisrKSBpZiAoZTRbbjJdID0gazIodGhpc1tuMl0pLCBuMiA9PT0gSDIuSU5TUEVDVF9NQVhfQllURVMpIHsKICAgICAgICAgICAgICBlNFtuMiArIDFdID0gIi4uLiI7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuICI8QnVmZmVyICIgKyBlNC5qb2luKCIgIikgKyAiPiI7CiAgICAgICAgICB9LCBmMi5wcm90b3R5cGUudG9BcnJheUJ1ZmZlciA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBpZiAoInVuZGVmaW5lZCIgPT0gdHlwZW9mIFVpbnQ4QXJyYXkpIHRocm93IG5ldyBFcnJvcigiQnVmZmVyLnRvQXJyYXlCdWZmZXIgbm90IHN1cHBvcnRlZCBpbiB0aGlzIGJyb3dzZXIiKTsKICAgICAgICAgICAgaWYgKGYyLl91c2VUeXBlZEFycmF5cykgcmV0dXJuIG5ldyBmMih0aGlzKS5idWZmZXI7CiAgICAgICAgICAgIGZvciAodmFyIGU0ID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5sZW5ndGgpLCB0MiA9IDAsIG4yID0gZTQubGVuZ3RoOyB0MiA8IG4yOyB0MiArPSAxKSBlNFt0Ml0gPSB0aGlzW3QyXTsKICAgICAgICAgICAgcmV0dXJuIGU0LmJ1ZmZlcjsKICAgICAgICAgIH07CiAgICAgICAgICB2YXIgdCA9IGYyLnByb3RvdHlwZTsKICAgICAgICAgIGZ1bmN0aW9uIFMyKGU0LCB0MiwgbjIpIHsKICAgICAgICAgICAgcmV0dXJuICJudW1iZXIiICE9IHR5cGVvZiBlNCA/IG4yIDogdDIgPD0gKGU0ID0gfn5lNCkgPyB0MiA6IDAgPD0gZTQgfHwgMCA8PSAoZTQgKz0gdDIpID8gZTQgOiAwOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gajIoZTQpIHsKICAgICAgICAgICAgcmV0dXJuIChlNCA9IH5+TWF0aC5jZWlsKCtlNCkpIDwgMCA/IDAgOiBlNDsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEMoZTQpIHsKICAgICAgICAgICAgcmV0dXJuIChBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uKGU1KSB7CiAgICAgICAgICAgICAgcmV0dXJuICJbb2JqZWN0IEFycmF5XSIgPT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChlNSk7CiAgICAgICAgICAgIH0pKGU0KTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGsyKGU0KSB7CiAgICAgICAgICAgIHJldHVybiBlNCA8IDE2ID8gIjAiICsgZTQudG9TdHJpbmcoMTYpIDogZTQudG9TdHJpbmcoMTYpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gVChlNCkgewogICAgICAgICAgICBmb3IgKHZhciB0MiA9IFtdLCBuMiA9IDA7IG4yIDwgZTQubGVuZ3RoOyBuMisrKSB7CiAgICAgICAgICAgICAgdmFyIHIzID0gZTQuY2hhckNvZGVBdChuMik7CiAgICAgICAgICAgICAgaWYgKHIzIDw9IDEyNykgdDIucHVzaChlNC5jaGFyQ29kZUF0KG4yKSk7CiAgICAgICAgICAgICAgZWxzZSBmb3IgKHZhciBvMiA9IG4yLCBpMyA9ICg1NTI5NiA8PSByMyAmJiByMyA8PSA1NzM0MyAmJiBuMisrLCBlbmNvZGVVUklDb21wb25lbnQoZTQuc2xpY2UobzIsIG4yICsgMSkpLnN1YnN0cigxKS5zcGxpdCgiJSIpKSwgdTMgPSAwOyB1MyA8IGkzLmxlbmd0aDsgdTMrKykgdDIucHVzaChwYXJzZUludChpM1t1M10sIDE2KSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHQyOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gTTIoZTQpIHsKICAgICAgICAgICAgcmV0dXJuIGEyLnRvQnl0ZUFycmF5KGU0KTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGMyKGU0LCB0MiwgbjIsIHIzKSB7CiAgICAgICAgICAgIGZvciAodmFyIG8yID0gMDsgbzIgPCByMyAmJiAhKG8yICsgbjIgPj0gdDIubGVuZ3RoIHx8IG8yID49IGU0Lmxlbmd0aCk7IG8yKyspIHQyW28yICsgbjJdID0gZTRbbzJdOwogICAgICAgICAgICByZXR1cm4gbzI7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBOKGU0KSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChlNCk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGU1KSB7CiAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoNjU1MzMpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBZMihlNCwgdDIpIHsKICAgICAgICAgICAgZCgibnVtYmVyIiA9PSB0eXBlb2YgZTQsICJjYW5ub3Qgd3JpdGUgYSBub24tbnVtYmVyIGFzIGEgbnVtYmVyIiksIGQoMCA8PSBlNCwgInNwZWNpZmllZCBhIG5lZ2F0aXZlIHZhbHVlIGZvciB3cml0aW5nIGFuIHVuc2lnbmVkIHZhbHVlIiksIGQoZTQgPD0gdDIsICJ2YWx1ZSBpcyBsYXJnZXIgdGhhbiBtYXhpbXVtIHZhbHVlIGZvciB0eXBlIiksIGQoTWF0aC5mbG9vcihlNCkgPT09IGU0LCAidmFsdWUgaGFzIGEgZnJhY3Rpb25hbCBjb21wb25lbnQiKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEYoZTQsIHQyLCBuMikgewogICAgICAgICAgICBkKCJudW1iZXIiID09IHR5cGVvZiBlNCwgImNhbm5vdCB3cml0ZSBhIG5vbi1udW1iZXIgYXMgYSBudW1iZXIiKSwgZChlNCA8PSB0MiwgInZhbHVlIGxhcmdlciB0aGFuIG1heGltdW0gYWxsb3dlZCB2YWx1ZSIpLCBkKG4yIDw9IGU0LCAidmFsdWUgc21hbGxlciB0aGFuIG1pbmltdW0gYWxsb3dlZCB2YWx1ZSIpLCBkKE1hdGguZmxvb3IoZTQpID09PSBlNCwgInZhbHVlIGhhcyBhIGZyYWN0aW9uYWwgY29tcG9uZW50Iik7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBEMihlNCwgdDIsIG4yKSB7CiAgICAgICAgICAgIGQoIm51bWJlciIgPT0gdHlwZW9mIGU0LCAiY2Fubm90IHdyaXRlIGEgbm9uLW51bWJlciBhcyBhIG51bWJlciIpLCBkKGU0IDw9IHQyLCAidmFsdWUgbGFyZ2VyIHRoYW4gbWF4aW11bSBhbGxvd2VkIHZhbHVlIiksIGQobjIgPD0gZTQsICJ2YWx1ZSBzbWFsbGVyIHRoYW4gbWluaW11bSBhbGxvd2VkIHZhbHVlIik7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBkKGU0LCB0MikgewogICAgICAgICAgICBpZiAoIWU0KSB0aHJvdyBuZXcgRXJyb3IodDIgfHwgIkZhaWxlZCBhc3NlcnRpb24iKTsKICAgICAgICAgIH0KICAgICAgICAgIGYyLl9hdWdtZW50ID0gZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgcmV0dXJuIGU0Ll9pc0J1ZmZlciA9IHRydWUsIGU0Ll9nZXQgPSBlNC5nZXQsIGU0Ll9zZXQgPSBlNC5zZXQsIGU0LmdldCA9IHQuZ2V0LCBlNC5zZXQgPSB0LnNldCwgZTQud3JpdGUgPSB0LndyaXRlLCBlNC50b1N0cmluZyA9IHQudG9TdHJpbmcsIGU0LnRvTG9jYWxlU3RyaW5nID0gdC50b1N0cmluZywgZTQudG9KU09OID0gdC50b0pTT04sIGU0LmNvcHkgPSB0LmNvcHksIGU0LnNsaWNlID0gdC5zbGljZSwgZTQucmVhZFVJbnQ4ID0gdC5yZWFkVUludDgsIGU0LnJlYWRVSW50MTZMRSA9IHQucmVhZFVJbnQxNkxFLCBlNC5yZWFkVUludDE2QkUgPSB0LnJlYWRVSW50MTZCRSwgZTQucmVhZFVJbnQzMkxFID0gdC5yZWFkVUludDMyTEUsIGU0LnJlYWRVSW50MzJCRSA9IHQucmVhZFVJbnQzMkJFLCBlNC5yZWFkSW50OCA9IHQucmVhZEludDgsIGU0LnJlYWRJbnQxNkxFID0gdC5yZWFkSW50MTZMRSwgZTQucmVhZEludDE2QkUgPSB0LnJlYWRJbnQxNkJFLCBlNC5yZWFkSW50MzJMRSA9IHQucmVhZEludDMyTEUsIGU0LnJlYWRJbnQzMkJFID0gdC5yZWFkSW50MzJCRSwgZTQucmVhZEZsb2F0TEUgPSB0LnJlYWRGbG9hdExFLCBlNC5yZWFkRmxvYXRCRSA9IHQucmVhZEZsb2F0QkUsIGU0LnJlYWREb3VibGVMRSA9IHQucmVhZERvdWJsZUxFLCBlNC5yZWFkRG91YmxlQkUgPSB0LnJlYWREb3VibGVCRSwgZTQud3JpdGVVSW50OCA9IHQud3JpdGVVSW50OCwgZTQud3JpdGVVSW50MTZMRSA9IHQud3JpdGVVSW50MTZMRSwgZTQud3JpdGVVSW50MTZCRSA9IHQud3JpdGVVSW50MTZCRSwgZTQud3JpdGVVSW50MzJMRSA9IHQud3JpdGVVSW50MzJMRSwgZTQud3JpdGVVSW50MzJCRSA9IHQud3JpdGVVSW50MzJCRSwgZTQud3JpdGVJbnQ4ID0gdC53cml0ZUludDgsIGU0LndyaXRlSW50MTZMRSA9IHQud3JpdGVJbnQxNkxFLCBlNC53cml0ZUludDE2QkUgPSB0LndyaXRlSW50MTZCRSwgZTQud3JpdGVJbnQzMkxFID0gdC53cml0ZUludDMyTEUsIGU0LndyaXRlSW50MzJCRSA9IHQud3JpdGVJbnQzMkJFLCBlNC53cml0ZUZsb2F0TEUgPSB0LndyaXRlRmxvYXRMRSwgZTQud3JpdGVGbG9hdEJFID0gdC53cml0ZUZsb2F0QkUsIGU0LndyaXRlRG91YmxlTEUgPSB0LndyaXRlRG91YmxlTEUsIGU0LndyaXRlRG91YmxlQkUgPSB0LndyaXRlRG91YmxlQkUsIGU0LmZpbGwgPSB0LmZpbGwsIGU0Lmluc3BlY3QgPSB0Lmluc3BlY3QsIGU0LnRvQXJyYXlCdWZmZXIgPSB0LnRvQXJyYXlCdWZmZXIsIGU0OwogICAgICAgICAgfTsKICAgICAgICB9KS5jYWxsKHRoaXMsIE8oImxZcG9JMiIpLCAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygc2VsZiA/IHNlbGYgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDoge30sIE8oImJ1ZmZlciIpLkJ1ZmZlciwgYXJndW1lbnRzWzNdLCBhcmd1bWVudHNbNF0sIGFyZ3VtZW50c1s1XSwgYXJndW1lbnRzWzZdLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9pbmRleC5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnVmZmVyIik7CiAgICAgIH0sIHsgImJhc2U2NC1qcyI6IDIsIGJ1ZmZlcjogMywgaWVlZTc1NDogMTAsIGxZcG9JMjogMTEgfV0sIDQ6IFtmdW5jdGlvbihjMiwgZCwgZTIpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUzLCB0LCBhMiwgbiwgcjIsIG8sIGkyLCB1MiwgczIpIHsKICAgICAgICAgIHZhciBhMiA9IGMyKCJidWZmZXIiKS5CdWZmZXIsIGYyID0gNCwgbDIgPSBuZXcgYTIoZjIpOwogICAgICAgICAgbDIuZmlsbCgwKTsKICAgICAgICAgIGQuZXhwb3J0cyA9IHsgaGFzaDogZnVuY3Rpb24oZTQsIHQyLCBuMiwgcjMpIHsKICAgICAgICAgICAgZm9yICh2YXIgbzIgPSB0MihmdW5jdGlvbihlNSwgdDMpIHsKICAgICAgICAgICAgICBlNS5sZW5ndGggJSBmMiAhPSAwICYmIChuMyA9IGU1Lmxlbmd0aCArIChmMiAtIGU1Lmxlbmd0aCAlIGYyKSwgZTUgPSBhMi5jb25jYXQoW2U1LCBsMl0sIG4zKSk7CiAgICAgICAgICAgICAgZm9yICh2YXIgbjMsIHI0ID0gW10sIG8zID0gdDMgPyBlNS5yZWFkSW50MzJCRSA6IGU1LnJlYWRJbnQzMkxFLCBpNCA9IDA7IGk0IDwgZTUubGVuZ3RoOyBpNCArPSBmMikgcjQucHVzaChvMy5jYWxsKGU1LCBpNCkpOwogICAgICAgICAgICAgIHJldHVybiByNDsKICAgICAgICAgICAgfShlNCA9IGEyLmlzQnVmZmVyKGU0KSA/IGU0IDogbmV3IGEyKGU0KSwgcjMpLCA4ICogZTQubGVuZ3RoKSwgdDIgPSByMywgaTMgPSBuZXcgYTIobjIpLCB1MyA9IHQyID8gaTMud3JpdGVJbnQzMkJFIDogaTMud3JpdGVJbnQzMkxFLCBzMyA9IDA7IHMzIDwgbzIubGVuZ3RoOyBzMysrKSB1My5jYWxsKGkzLCBvMltzM10sIDQgKiBzMywgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiBpMzsKICAgICAgICAgIH0gfTsKICAgICAgICB9KS5jYWxsKHRoaXMsIGMyKCJsWXBvSTIiKSwgInVuZGVmaW5lZCIgIT0gdHlwZW9mIHNlbGYgPyBzZWxmIDogInVuZGVmaW5lZCIgIT0gdHlwZW9mIHdpbmRvdyA/IHdpbmRvdyA6IHt9LCBjMigiYnVmZmVyIikuQnVmZmVyLCBhcmd1bWVudHNbM10sIGFyZ3VtZW50c1s0XSwgYXJndW1lbnRzWzVdLCBhcmd1bWVudHNbNl0sICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkvaGVscGVycy5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkiKTsKICAgICAgfSwgeyBidWZmZXI6IDMsIGxZcG9JMjogMTEgfV0sIDU6IFtmdW5jdGlvbih2MiwgZTIsIF8pIHsKICAgICAgICAhKGZ1bmN0aW9uKGwyLCBjMiwgdTIsIGQsIGgsIHAsIGcsIHksIHcyKSB7CiAgICAgICAgICB2YXIgdTIgPSB2MigiYnVmZmVyIikuQnVmZmVyLCBlMyA9IHYyKCIuL3NoYSIpLCB0ID0gdjIoIi4vc2hhMjU2IiksIG4gPSB2MigiLi9ybmciKSwgYiA9IHsgc2hhMTogZTMsIHNoYTI1NjogdCwgbWQ1OiB2MigiLi9tZDUiKSB9LCBzMiA9IDY0LCBhMiA9IG5ldyB1MihzMik7CiAgICAgICAgICBmdW5jdGlvbiByMihlNCwgbjIpIHsKICAgICAgICAgICAgdmFyIHIzID0gYltlNCA9IGU0IHx8ICJzaGExIl0sIG8yID0gW107CiAgICAgICAgICAgIHJldHVybiByMyB8fCBpMigiYWxnb3JpdGhtOiIsIGU0LCAiaXMgbm90IHlldCBzdXBwb3J0ZWQiKSwgeyB1cGRhdGU6IGZ1bmN0aW9uKGU1KSB7CiAgICAgICAgICAgICAgcmV0dXJuIHUyLmlzQnVmZmVyKGU1KSB8fCAoZTUgPSBuZXcgdTIoZTUpKSwgbzIucHVzaChlNSksIGU1Lmxlbmd0aCwgdGhpczsKICAgICAgICAgICAgfSwgZGlnZXN0OiBmdW5jdGlvbihlNSkgewogICAgICAgICAgICAgIHZhciB0MiA9IHUyLmNvbmNhdChvMiksIHQyID0gbjIgPyBmdW5jdGlvbihlNiwgdDMsIG4zKSB7CiAgICAgICAgICAgICAgICB1Mi5pc0J1ZmZlcih0MykgfHwgKHQzID0gbmV3IHUyKHQzKSksIHUyLmlzQnVmZmVyKG4zKSB8fCAobjMgPSBuZXcgdTIobjMpKSwgdDMubGVuZ3RoID4gczIgPyB0MyA9IGU2KHQzKSA6IHQzLmxlbmd0aCA8IHMyICYmICh0MyA9IHUyLmNvbmNhdChbdDMsIGEyXSwgczIpKTsKICAgICAgICAgICAgICAgIGZvciAodmFyIHI0ID0gbmV3IHUyKHMyKSwgbzMgPSBuZXcgdTIoczIpLCBpMyA9IDA7IGkzIDwgczI7IGkzKyspIHI0W2kzXSA9IDU0IF4gdDNbaTNdLCBvM1tpM10gPSA5MiBeIHQzW2kzXTsKICAgICAgICAgICAgICAgIHJldHVybiBuMyA9IGU2KHUyLmNvbmNhdChbcjQsIG4zXSkpLCBlNih1Mi5jb25jYXQoW28zLCBuM10pKTsKICAgICAgICAgICAgICB9KHIzLCBuMiwgdDIpIDogcjModDIpOwogICAgICAgICAgICAgIHJldHVybiBvMiA9IG51bGwsIGU1ID8gdDIudG9TdHJpbmcoZTUpIDogdDI7CiAgICAgICAgICAgIH0gfTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGkyKCkgewogICAgICAgICAgICB2YXIgZTQgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cykuam9pbigiICIpOwogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoW2U0LCAid2UgYWNjZXB0IHB1bGwgcmVxdWVzdHMiLCAiaHR0cDovL2dpdGh1Yi5jb20vZG9taW5pY3RhcnIvY3J5cHRvLWJyb3dzZXJpZnkiXS5qb2luKCJcbiIpKTsKICAgICAgICAgIH0KICAgICAgICAgIGEyLmZpbGwoMCksIF8uY3JlYXRlSGFzaCA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIHJldHVybiByMihlNCk7CiAgICAgICAgICB9LCBfLmNyZWF0ZUhtYWMgPSByMiwgXy5yYW5kb21CeXRlcyA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICBpZiAoIXQyIHx8ICF0Mi5jYWxsKSByZXR1cm4gbmV3IHUyKG4oZTQpKTsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICB0Mi5jYWxsKHRoaXMsIHZvaWQgMCwgbmV3IHUyKG4oZTQpKSk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGU1KSB7CiAgICAgICAgICAgICAgdDIoZTUpOwogICAgICAgICAgICB9CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIG8sIGYyID0gWyJjcmVhdGVDcmVkZW50aWFscyIsICJjcmVhdGVDaXBoZXIiLCAiY3JlYXRlQ2lwaGVyaXYiLCAiY3JlYXRlRGVjaXBoZXIiLCAiY3JlYXRlRGVjaXBoZXJpdiIsICJjcmVhdGVTaWduIiwgImNyZWF0ZVZlcmlmeSIsICJjcmVhdGVEaWZmaWVIZWxsbWFuIiwgInBia2RmMiJdLCBtMiA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIF9bZTRdID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgaTIoInNvcnJ5LCIsIGU0LCAiaXMgbm90IGltcGxlbWVudGVkIHlldCIpOwogICAgICAgICAgICB9OwogICAgICAgICAgfTsKICAgICAgICAgIGZvciAobyBpbiBmMikgbTIoZjJbb10pOwogICAgICAgIH0pLmNhbGwodGhpcywgdjIoImxZcG9JMiIpLCAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygc2VsZiA/IHNlbGYgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDoge30sIHYyKCJidWZmZXIiKS5CdWZmZXIsIGFyZ3VtZW50c1szXSwgYXJndW1lbnRzWzRdLCBhcmd1bWVudHNbNV0sIGFyZ3VtZW50c1s2XSwgIi9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9jcnlwdG8tYnJvd3NlcmlmeS9pbmRleC5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkiKTsKICAgICAgfSwgeyAiLi9tZDUiOiA2LCAiLi9ybmciOiA3LCAiLi9zaGEiOiA4LCAiLi9zaGEyNTYiOiA5LCBidWZmZXI6IDMsIGxZcG9JMjogMTEgfV0sIDY6IFtmdW5jdGlvbih3MiwgYiwgZTIpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUzLCByMiwgbywgaTIsIHUyLCBhMiwgZjIsIGwyLCB5KSB7CiAgICAgICAgICB2YXIgdCA9IHcyKCIuL2hlbHBlcnMiKTsKICAgICAgICAgIGZ1bmN0aW9uIG4oZTQsIHQyKSB7CiAgICAgICAgICAgIGU0W3QyID4+IDVdIHw9IDEyOCA8PCB0MiAlIDMyLCBlNFsxNCArICh0MiArIDY0ID4+PiA5IDw8IDQpXSA9IHQyOwogICAgICAgICAgICBmb3IgKHZhciBuMiA9IDE3MzI1ODQxOTMsIHIzID0gLTI3MTczMzg3OSwgbzIgPSAtMTczMjU4NDE5NCwgaTMgPSAyNzE3MzM4NzgsIHUzID0gMDsgdTMgPCBlNC5sZW5ndGg7IHUzICs9IDE2KSB7CiAgICAgICAgICAgICAgdmFyIHMzID0gbjIsIGEzID0gcjMsIGYzID0gbzIsIGwzID0gaTMsIG4yID0gYzIobjIsIHIzLCBvMiwgaTMsIGU0W3UzICsgMF0sIDcsIC02ODA4NzY5MzYpLCBpMyA9IGMyKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDFdLCAxMiwgLTM4OTU2NDU4NiksIG8yID0gYzIobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgMl0sIDE3LCA2MDYxMDU4MTkpLCByMyA9IGMyKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDNdLCAyMiwgLTEwNDQ1MjUzMzApOwogICAgICAgICAgICAgIG4yID0gYzIobjIsIHIzLCBvMiwgaTMsIGU0W3UzICsgNF0sIDcsIC0xNzY0MTg4OTcpLCBpMyA9IGMyKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDVdLCAxMiwgMTIwMDA4MDQyNiksIG8yID0gYzIobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgNl0sIDE3LCAtMTQ3MzIzMTM0MSksIHIzID0gYzIocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgN10sIDIyLCAtNDU3MDU5ODMpLCBuMiA9IGMyKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDhdLCA3LCAxNzcwMDM1NDE2KSwgaTMgPSBjMihpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyA5XSwgMTIsIC0xOTU4NDE0NDE3KSwgbzIgPSBjMihvMiwgaTMsIG4yLCByMywgZTRbdTMgKyAxMF0sIDE3LCAtNDIwNjMpLCByMyA9IGMyKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDExXSwgMjIsIC0xOTkwNDA0MTYyKSwgbjIgPSBjMihuMiwgcjMsIG8yLCBpMywgZTRbdTMgKyAxMl0sIDcsIDE4MDQ2MDM2ODIpLCBpMyA9IGMyKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDEzXSwgMTIsIC00MDM0MTEwMSksIG8yID0gYzIobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgMTRdLCAxNywgLTE1MDIwMDIyOTApLCBuMiA9IGQobjIsIHIzID0gYzIocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgMTVdLCAyMiwgMTIzNjUzNTMyOSksIG8yLCBpMywgZTRbdTMgKyAxXSwgNSwgLTE2NTc5NjUxMCksIGkzID0gZChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyA2XSwgOSwgLTEwNjk1MDE2MzIpLCBvMiA9IGQobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgMTFdLCAxNCwgNjQzNzE3NzEzKSwgcjMgPSBkKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDBdLCAyMCwgLTM3Mzg5NzMwMiksIG4yID0gZChuMiwgcjMsIG8yLCBpMywgZTRbdTMgKyA1XSwgNSwgLTcwMTU1ODY5MSksIGkzID0gZChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyAxMF0sIDksIDM4MDE2MDgzKSwgbzIgPSBkKG8yLCBpMywgbjIsIHIzLCBlNFt1MyArIDE1XSwgMTQsIC02NjA0NzgzMzUpLCByMyA9IGQocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgNF0sIDIwLCAtNDA1NTM3ODQ4KSwgbjIgPSBkKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDldLCA1LCA1Njg0NDY0MzgpLCBpMyA9IGQoaTMsIG4yLCByMywgbzIsIGU0W3UzICsgMTRdLCA5LCAtMTAxOTgwMzY5MCksIG8yID0gZChvMiwgaTMsIG4yLCByMywgZTRbdTMgKyAzXSwgMTQsIC0xODczNjM5NjEpLCByMyA9IGQocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgOF0sIDIwLCAxMTYzNTMxNTAxKSwgbjIgPSBkKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDEzXSwgNSwgLTE0NDQ2ODE0NjcpLCBpMyA9IGQoaTMsIG4yLCByMywgbzIsIGU0W3UzICsgMl0sIDksIC01MTQwMzc4NCksIG8yID0gZChvMiwgaTMsIG4yLCByMywgZTRbdTMgKyA3XSwgMTQsIDE3MzUzMjg0NzMpLCBuMiA9IGgobjIsIHIzID0gZChyMywgbzIsIGkzLCBuMiwgZTRbdTMgKyAxMl0sIDIwLCAtMTkyNjYwNzczNCksIG8yLCBpMywgZTRbdTMgKyA1XSwgNCwgLTM3ODU1OCksIGkzID0gaChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyA4XSwgMTEsIC0yMDIyNTc0NDYzKSwgbzIgPSBoKG8yLCBpMywgbjIsIHIzLCBlNFt1MyArIDExXSwgMTYsIDE4MzkwMzA1NjIpLCByMyA9IGgocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgMTRdLCAyMywgLTM1MzA5NTU2KSwgbjIgPSBoKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDFdLCA0LCAtMTUzMDk5MjA2MCksIGkzID0gaChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyA0XSwgMTEsIDEyNzI4OTMzNTMpLCBvMiA9IGgobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgN10sIDE2LCAtMTU1NDk3NjMyKSwgcjMgPSBoKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDEwXSwgMjMsIC0xMDk0NzMwNjQwKSwgbjIgPSBoKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDEzXSwgNCwgNjgxMjc5MTc0KSwgaTMgPSBoKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDBdLCAxMSwgLTM1ODUzNzIyMiksIG8yID0gaChvMiwgaTMsIG4yLCByMywgZTRbdTMgKyAzXSwgMTYsIC03MjI1MjE5NzkpLCByMyA9IGgocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgNl0sIDIzLCA3NjAyOTE4OSksIG4yID0gaChuMiwgcjMsIG8yLCBpMywgZTRbdTMgKyA5XSwgNCwgLTY0MDM2NDQ4NyksIGkzID0gaChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyAxMl0sIDExLCAtNDIxODE1ODM1KSwgbzIgPSBoKG8yLCBpMywgbjIsIHIzLCBlNFt1MyArIDE1XSwgMTYsIDUzMDc0MjUyMCksIG4yID0gcChuMiwgcjMgPSBoKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDJdLCAyMywgLTk5NTMzODY1MSksIG8yLCBpMywgZTRbdTMgKyAwXSwgNiwgLTE5ODYzMDg0NCksIGkzID0gcChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyA3XSwgMTAsIDExMjY4OTE0MTUpLCBvMiA9IHAobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgMTRdLCAxNSwgLTE0MTYzNTQ5MDUpLCByMyA9IHAocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgNV0sIDIxLCAtNTc0MzQwNTUpLCBuMiA9IHAobjIsIHIzLCBvMiwgaTMsIGU0W3UzICsgMTJdLCA2LCAxNzAwNDg1NTcxKSwgaTMgPSBwKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDNdLCAxMCwgLTE4OTQ5ODY2MDYpLCBvMiA9IHAobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgMTBdLCAxNSwgLTEwNTE1MjMpLCByMyA9IHAocjMsIG8yLCBpMywgbjIsIGU0W3UzICsgMV0sIDIxLCAtMjA1NDkyMjc5OSksIG4yID0gcChuMiwgcjMsIG8yLCBpMywgZTRbdTMgKyA4XSwgNiwgMTg3MzMxMzM1OSksIGkzID0gcChpMywgbjIsIHIzLCBvMiwgZTRbdTMgKyAxNV0sIDEwLCAtMzA2MTE3NDQpLCBvMiA9IHAobzIsIGkzLCBuMiwgcjMsIGU0W3UzICsgNl0sIDE1LCAtMTU2MDE5ODM4MCksIHIzID0gcChyMywgbzIsIGkzLCBuMiwgZTRbdTMgKyAxM10sIDIxLCAxMzA5MTUxNjQ5KSwgbjIgPSBwKG4yLCByMywgbzIsIGkzLCBlNFt1MyArIDRdLCA2LCAtMTQ1NTIzMDcwKSwgaTMgPSBwKGkzLCBuMiwgcjMsIG8yLCBlNFt1MyArIDExXSwgMTAsIC0xMTIwMjEwMzc5KSwgbzIgPSBwKG8yLCBpMywgbjIsIHIzLCBlNFt1MyArIDJdLCAxNSwgNzE4Nzg3MjU5KSwgcjMgPSBwKHIzLCBvMiwgaTMsIG4yLCBlNFt1MyArIDldLCAyMSwgLTM0MzQ4NTU1MSksIG4yID0gZyhuMiwgczMpLCByMyA9IGcocjMsIGEzKSwgbzIgPSBnKG8yLCBmMyksIGkzID0gZyhpMywgbDMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBBcnJheShuMiwgcjMsIG8yLCBpMyk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBzMihlNCwgdDIsIG4yLCByMywgbzIsIGkzKSB7CiAgICAgICAgICAgIHJldHVybiBnKCh0MiA9IGcoZyh0MiwgZTQpLCBnKHIzLCBpMykpKSA8PCBvMiB8IHQyID4+PiAzMiAtIG8yLCBuMik7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBjMihlNCwgdDIsIG4yLCByMywgbzIsIGkzLCB1MykgewogICAgICAgICAgICByZXR1cm4gczIodDIgJiBuMiB8IH50MiAmIHIzLCBlNCwgdDIsIG8yLCBpMywgdTMpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZChlNCwgdDIsIG4yLCByMywgbzIsIGkzLCB1MykgewogICAgICAgICAgICByZXR1cm4gczIodDIgJiByMyB8IG4yICYgfnIzLCBlNCwgdDIsIG8yLCBpMywgdTMpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gaChlNCwgdDIsIG4yLCByMywgbzIsIGkzLCB1MykgewogICAgICAgICAgICByZXR1cm4gczIodDIgXiBuMiBeIHIzLCBlNCwgdDIsIG8yLCBpMywgdTMpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gcChlNCwgdDIsIG4yLCByMywgbzIsIGkzLCB1MykgewogICAgICAgICAgICByZXR1cm4gczIobjIgXiAodDIgfCB+cjMpLCBlNCwgdDIsIG8yLCBpMywgdTMpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZyhlNCwgdDIpIHsKICAgICAgICAgICAgdmFyIG4yID0gKDY1NTM1ICYgZTQpICsgKDY1NTM1ICYgdDIpOwogICAgICAgICAgICByZXR1cm4gKGU0ID4+IDE2KSArICh0MiA+PiAxNikgKyAobjIgPj4gMTYpIDw8IDE2IHwgNjU1MzUgJiBuMjsKICAgICAgICAgIH0KICAgICAgICAgIGIuZXhwb3J0cyA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIHJldHVybiB0Lmhhc2goZTQsIG4sIDE2KTsKICAgICAgICAgIH07CiAgICAgICAgfSkuY2FsbCh0aGlzLCB3MigibFlwb0kyIiksICJ1bmRlZmluZWQiICE9IHR5cGVvZiBzZWxmID8gc2VsZiA6ICJ1bmRlZmluZWQiICE9IHR5cGVvZiB3aW5kb3cgPyB3aW5kb3cgOiB7fSwgdzIoImJ1ZmZlciIpLkJ1ZmZlciwgYXJndW1lbnRzWzNdLCBhcmd1bWVudHNbNF0sIGFyZ3VtZW50c1s1XSwgYXJndW1lbnRzWzZdLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2NyeXB0by1icm93c2VyaWZ5L21kNS5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkiKTsKICAgICAgfSwgeyAiLi9oZWxwZXJzIjogNCwgYnVmZmVyOiAzLCBsWXBvSTI6IDExIH1dLCA3OiBbZnVuY3Rpb24oZTIsIGwyLCB0KSB7CiAgICAgICAgIShmdW5jdGlvbihlMywgdDIsIG4sIHIyLCBvLCBpMiwgdTIsIHMyLCBmMikgewogICAgICAgICAgbDIuZXhwb3J0cyA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIGZvciAodmFyIHQzLCBuMiA9IG5ldyBBcnJheShlNCksIHIzID0gMDsgcjMgPCBlNDsgcjMrKykgMCA9PSAoMyAmIHIzKSAmJiAodDMgPSA0Mjk0OTY3Mjk2ICogTWF0aC5yYW5kb20oKSksIG4yW3IzXSA9IHQzID4+PiAoKDMgJiByMykgPDwgMykgJiAyNTU7CiAgICAgICAgICAgIHJldHVybiBuMjsKICAgICAgICAgIH07CiAgICAgICAgfSkuY2FsbCh0aGlzLCBlMigibFlwb0kyIiksICJ1bmRlZmluZWQiICE9IHR5cGVvZiBzZWxmID8gc2VsZiA6ICJ1bmRlZmluZWQiICE9IHR5cGVvZiB3aW5kb3cgPyB3aW5kb3cgOiB7fSwgZTIoImJ1ZmZlciIpLkJ1ZmZlciwgYXJndW1lbnRzWzNdLCBhcmd1bWVudHNbNF0sIGFyZ3VtZW50c1s1XSwgYXJndW1lbnRzWzZdLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2NyeXB0by1icm93c2VyaWZ5L3JuZy5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkiKTsKICAgICAgfSwgeyBidWZmZXI6IDMsIGxZcG9JMjogMTEgfV0sIDg6IFtmdW5jdGlvbihjMiwgZCwgZTIpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUzLCB0LCBuLCByMiwgbywgczIsIGEyLCBmMiwgbDIpIHsKICAgICAgICAgIHZhciBpMiA9IGMyKCIuL2hlbHBlcnMiKTsKICAgICAgICAgIGZ1bmN0aW9uIHUyKGwzLCBjMykgewogICAgICAgICAgICBsM1tjMyA+PiA1XSB8PSAxMjggPDwgMjQgLSBjMyAlIDMyLCBsM1sxNSArIChjMyArIDY0ID4+IDkgPDwgNCldID0gYzM7CiAgICAgICAgICAgIGZvciAodmFyIGU0LCB0MiwgbjIsIHIzID0gQXJyYXkoODApLCBvMiA9IDE3MzI1ODQxOTMsIGkzID0gLTI3MTczMzg3OSwgdTMgPSAtMTczMjU4NDE5NCwgczMgPSAyNzE3MzM4NzgsIGQyID0gLTEwMDk1ODk3NzYsIGggPSAwOyBoIDwgbDMubGVuZ3RoOyBoICs9IDE2KSB7CiAgICAgICAgICAgICAgZm9yICh2YXIgcCA9IG8yLCBnID0gaTMsIHkgPSB1MywgdzIgPSBzMywgYiA9IGQyLCBhMyA9IDA7IGEzIDwgODA7IGEzKyspIHsKICAgICAgICAgICAgICAgIHIzW2EzXSA9IGEzIDwgMTYgPyBsM1toICsgYTNdIDogdjIocjNbYTMgLSAzXSBeIHIzW2EzIC0gOF0gXiByM1thMyAtIDE0XSBeIHIzW2EzIC0gMTZdLCAxKTsKICAgICAgICAgICAgICAgIHZhciBmMyA9IG0yKG0yKHYyKG8yLCA1KSwgKGYzID0gaTMsIHQyID0gdTMsIG4yID0gczMsIChlNCA9IGEzKSA8IDIwID8gZjMgJiB0MiB8IH5mMyAmIG4yIDogIShlNCA8IDQwKSAmJiBlNCA8IDYwID8gZjMgJiB0MiB8IGYzICYgbjIgfCB0MiAmIG4yIDogZjMgXiB0MiBeIG4yKSksIG0yKG0yKGQyLCByM1thM10pLCAoZTQgPSBhMykgPCAyMCA/IDE1MTg1MDAyNDkgOiBlNCA8IDQwID8gMTg1OTc3NTM5MyA6IGU0IDwgNjAgPyAtMTg5NDAwNzU4OCA6IC04OTk0OTc1MTQpKSwgZDIgPSBzMywgczMgPSB1MywgdTMgPSB2MihpMywgMzApLCBpMyA9IG8yLCBvMiA9IGYzOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBvMiA9IG0yKG8yLCBwKSwgaTMgPSBtMihpMywgZyksIHUzID0gbTIodTMsIHkpLCBzMyA9IG0yKHMzLCB3MiksIGQyID0gbTIoZDIsIGIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBBcnJheShvMiwgaTMsIHUzLCBzMywgZDIpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gbTIoZTQsIHQyKSB7CiAgICAgICAgICAgIHZhciBuMiA9ICg2NTUzNSAmIGU0KSArICg2NTUzNSAmIHQyKTsKICAgICAgICAgICAgcmV0dXJuIChlNCA+PiAxNikgKyAodDIgPj4gMTYpICsgKG4yID4+IDE2KSA8PCAxNiB8IDY1NTM1ICYgbjI7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiB2MihlNCwgdDIpIHsKICAgICAgICAgICAgcmV0dXJuIGU0IDw8IHQyIHwgZTQgPj4+IDMyIC0gdDI7CiAgICAgICAgICB9CiAgICAgICAgICBkLmV4cG9ydHMgPSBmdW5jdGlvbihlNCkgewogICAgICAgICAgICByZXR1cm4gaTIuaGFzaChlNCwgdTIsIDIwLCB0cnVlKTsKICAgICAgICAgIH07CiAgICAgICAgfSkuY2FsbCh0aGlzLCBjMigibFlwb0kyIiksICJ1bmRlZmluZWQiICE9IHR5cGVvZiBzZWxmID8gc2VsZiA6ICJ1bmRlZmluZWQiICE9IHR5cGVvZiB3aW5kb3cgPyB3aW5kb3cgOiB7fSwgYzIoImJ1ZmZlciIpLkJ1ZmZlciwgYXJndW1lbnRzWzNdLCBhcmd1bWVudHNbNF0sIGFyZ3VtZW50c1s1XSwgYXJndW1lbnRzWzZdLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2NyeXB0by1icm93c2VyaWZ5L3NoYS5qcyIsICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvY3J5cHRvLWJyb3dzZXJpZnkiKTsKICAgICAgfSwgeyAiLi9oZWxwZXJzIjogNCwgYnVmZmVyOiAzLCBsWXBvSTI6IDExIH1dLCA5OiBbZnVuY3Rpb24oYzIsIGQsIGUyKSB7CiAgICAgICAgIShmdW5jdGlvbihlMywgdCwgbiwgcjIsIHUyLCBzMiwgYTIsIGYyLCBsMikgewogICAgICAgICAgZnVuY3Rpb24gYihlNCwgdDIpIHsKICAgICAgICAgICAgdmFyIG4yID0gKDY1NTM1ICYgZTQpICsgKDY1NTM1ICYgdDIpOwogICAgICAgICAgICByZXR1cm4gKGU0ID4+IDE2KSArICh0MiA+PiAxNikgKyAobjIgPj4gMTYpIDw8IDE2IHwgNjU1MzUgJiBuMjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIG8oZTQsIGwzKSB7CiAgICAgICAgICAgIHZhciBjMywgZDIgPSBuZXcgQXJyYXkoMTExNjM1MjQwOCwgMTg5OTQ0NzQ0MSwgMzA0OTMyMzQ3MSwgMzkyMTAwOTU3MywgOTYxOTg3MTYzLCAxNTA4OTcwOTkzLCAyNDUzNjM1NzQ4LCAyODcwNzYzMjIxLCAzNjI0MzgxMDgwLCAzMTA1OTg0MDEsIDYwNzIyNTI3OCwgMTQyNjg4MTk4NywgMTkyNTA3ODM4OCwgMjE2MjA3ODIwNiwgMjYxNDg4ODEwMywgMzI0ODIyMjU4MCwgMzgzNTM5MDQwMSwgNDAyMjIyNDc3NCwgMjY0MzQ3MDc4LCA2MDQ4MDc2MjgsIDc3MDI1NTk4MywgMTI0OTE1MDEyMiwgMTU1NTA4MTY5MiwgMTk5NjA2NDk4NiwgMjU1NDIyMDg4MiwgMjgyMTgzNDM0OSwgMjk1Mjk5NjgwOCwgMzIxMDMxMzY3MSwgMzMzNjU3MTg5MSwgMzU4NDUyODcxMSwgMTEzOTI2OTkzLCAzMzgyNDE4OTUsIDY2NjMwNzIwNSwgNzczNTI5OTEyLCAxMjk0NzU3MzcyLCAxMzk2MTgyMjkxLCAxNjk1MTgzNzAwLCAxOTg2NjYxMDUxLCAyMTc3MDI2MzUwLCAyNDU2OTU2MDM3LCAyNzMwNDg1OTIxLCAyODIwMzAyNDExLCAzMjU5NzMwODAwLCAzMzQ1NzY0NzcxLCAzNTE2MDY1ODE3LCAzNjAwMzUyODA0LCA0MDk0NTcxOTA5LCAyNzU0MjMzNDQsIDQzMDIyNzczNCwgNTA2OTQ4NjE2LCA2NTkwNjA1NTYsIDg4Mzk5Nzg3NywgOTU4MTM5NTcxLCAxMzIyODIyMjE4LCAxNTM3MDAyMDYzLCAxNzQ3ODczNzc5LCAxOTU1NTYyMjIyLCAyMDI0MTA0ODE1LCAyMjI3NzMwNDUyLCAyMzYxODUyNDI0LCAyNDI4NDM2NDc0LCAyNzU2NzM0MTg3LCAzMjA0MDMxNDc5LCAzMzI5MzI1Mjk4KSwgdDIgPSBuZXcgQXJyYXkoMTc3OTAzMzcwMywgMzE0NDEzNDI3NywgMTAxMzkwNDI0MiwgMjc3MzQ4MDc2MiwgMTM1OTg5MzExOSwgMjYwMDgyMjkyNCwgNTI4NzM0NjM1LCAxNTQxNDU5MjI1KSwgbjIgPSBuZXcgQXJyYXkoNjQpOwogICAgICAgICAgICBlNFtsMyA+PiA1XSB8PSAxMjggPDwgMjQgLSBsMyAlIDMyLCBlNFsxNSArIChsMyArIDY0ID4+IDkgPDwgNCldID0gbDM7CiAgICAgICAgICAgIGZvciAodmFyIHIzLCBvMiwgaCA9IDA7IGggPCBlNC5sZW5ndGg7IGggKz0gMTYpIHsKICAgICAgICAgICAgICBmb3IgKHZhciBpMyA9IHQyWzBdLCB1MyA9IHQyWzFdLCBzMyA9IHQyWzJdLCBwID0gdDJbM10sIGEzID0gdDJbNF0sIGcgPSB0Mls1XSwgeSA9IHQyWzZdLCB3MiA9IHQyWzddLCBmMyA9IDA7IGYzIDwgNjQ7IGYzKyspIG4yW2YzXSA9IGYzIDwgMTYgPyBlNFtmMyArIGhdIDogYihiKGIoKG8yID0gbjJbZjMgLSAyXSwgbTIobzIsIDE3KSBeIG0yKG8yLCAxOSkgXiB2MihvMiwgMTApKSwgbjJbZjMgLSA3XSksIChvMiA9IG4yW2YzIC0gMTVdLCBtMihvMiwgNykgXiBtMihvMiwgMTgpIF4gdjIobzIsIDMpKSksIG4yW2YzIC0gMTZdKSwgYzMgPSBiKGIoYihiKHcyLCBtMihvMiA9IGEzLCA2KSBeIG0yKG8yLCAxMSkgXiBtMihvMiwgMjUpKSwgYTMgJiBnIF4gfmEzICYgeSksIGQyW2YzXSksIG4yW2YzXSksIHIzID0gYihtMihyMyA9IGkzLCAyKSBeIG0yKHIzLCAxMykgXiBtMihyMywgMjIpLCBpMyAmIHUzIF4gaTMgJiBzMyBeIHUzICYgczMpLCB3MiA9IHksIHkgPSBnLCBnID0gYTMsIGEzID0gYihwLCBjMyksIHAgPSBzMywgczMgPSB1MywgdTMgPSBpMywgaTMgPSBiKGMzLCByMyk7CiAgICAgICAgICAgICAgdDJbMF0gPSBiKGkzLCB0MlswXSksIHQyWzFdID0gYih1MywgdDJbMV0pLCB0MlsyXSA9IGIoczMsIHQyWzJdKSwgdDJbM10gPSBiKHAsIHQyWzNdKSwgdDJbNF0gPSBiKGEzLCB0Mls0XSksIHQyWzVdID0gYihnLCB0Mls1XSksIHQyWzZdID0gYih5LCB0Mls2XSksIHQyWzddID0gYih3MiwgdDJbN10pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0MjsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBpMiA9IGMyKCIuL2hlbHBlcnMiKSwgbTIgPSBmdW5jdGlvbihlNCwgdDIpIHsKICAgICAgICAgICAgcmV0dXJuIGU0ID4+PiB0MiB8IGU0IDw8IDMyIC0gdDI7CiAgICAgICAgICB9LCB2MiA9IGZ1bmN0aW9uKGU0LCB0MikgewogICAgICAgICAgICByZXR1cm4gZTQgPj4+IHQyOwogICAgICAgICAgfTsKICAgICAgICAgIGQuZXhwb3J0cyA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIHJldHVybiBpMi5oYXNoKGU0LCBvLCAzMiwgdHJ1ZSk7CiAgICAgICAgICB9OwogICAgICAgIH0pLmNhbGwodGhpcywgYzIoImxZcG9JMiIpLCAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygc2VsZiA/IHNlbGYgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDoge30sIGMyKCJidWZmZXIiKS5CdWZmZXIsIGFyZ3VtZW50c1szXSwgYXJndW1lbnRzWzRdLCBhcmd1bWVudHNbNV0sIGFyZ3VtZW50c1s2XSwgIi9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9jcnlwdG8tYnJvd3NlcmlmeS9zaGEyNTYuanMiLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2NyeXB0by1icm93c2VyaWZ5Iik7CiAgICAgIH0sIHsgIi4vaGVscGVycyI6IDQsIGJ1ZmZlcjogMywgbFlwb0kyOiAxMSB9XSwgMTA6IFtmdW5jdGlvbihlMiwgdCwgZjIpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUzLCB0MiwgbiwgcjIsIG8sIGkyLCB1MiwgczIsIGEyKSB7CiAgICAgICAgICBmMi5yZWFkID0gZnVuY3Rpb24oZTQsIHQzLCBuMiwgcjMsIG8yKSB7CiAgICAgICAgICAgIHZhciBpMywgdTMsIGwyID0gOCAqIG8yIC0gcjMgLSAxLCBjMiA9ICgxIDw8IGwyKSAtIDEsIGQgPSBjMiA+PiAxLCBzMyA9IC03LCBhMyA9IG4yID8gbzIgLSAxIDogMCwgZjMgPSBuMiA/IC0xIDogMSwgbzIgPSBlNFt0MyArIGEzXTsKICAgICAgICAgICAgZm9yIChhMyArPSBmMywgaTMgPSBvMiAmICgxIDw8IC1zMykgLSAxLCBvMiA+Pj0gLXMzLCBzMyArPSBsMjsgMCA8IHMzOyBpMyA9IDI1NiAqIGkzICsgZTRbdDMgKyBhM10sIGEzICs9IGYzLCBzMyAtPSA4KSA7CiAgICAgICAgICAgIGZvciAodTMgPSBpMyAmICgxIDw8IC1zMykgLSAxLCBpMyA+Pj0gLXMzLCBzMyArPSByMzsgMCA8IHMzOyB1MyA9IDI1NiAqIHUzICsgZTRbdDMgKyBhM10sIGEzICs9IGYzLCBzMyAtPSA4KSA7CiAgICAgICAgICAgIGlmICgwID09PSBpMykgaTMgPSAxIC0gZDsKICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgaWYgKGkzID09PSBjMikgcmV0dXJuIHUzID8gTmFOIDogMSAvIDAgKiAobzIgPyAtMSA6IDEpOwogICAgICAgICAgICAgIHUzICs9IE1hdGgucG93KDIsIHIzKSwgaTMgLT0gZDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gKG8yID8gLTEgOiAxKSAqIHUzICogTWF0aC5wb3coMiwgaTMgLSByMyk7CiAgICAgICAgICB9LCBmMi53cml0ZSA9IGZ1bmN0aW9uKGU0LCB0MywgbDIsIG4yLCByMywgYzIpIHsKICAgICAgICAgICAgdmFyIG8yLCBpMywgdTMgPSA4ICogYzIgLSByMyAtIDEsIHMzID0gKDEgPDwgdTMpIC0gMSwgYTMgPSBzMyA+PiAxLCBkID0gMjMgPT09IHIzID8gTWF0aC5wb3coMiwgLTI0KSAtIE1hdGgucG93KDIsIC03NykgOiAwLCBmMyA9IG4yID8gMCA6IGMyIC0gMSwgaCA9IG4yID8gMSA6IC0xLCBjMiA9IHQzIDwgMCB8fCAwID09PSB0MyAmJiAxIC8gdDMgPCAwID8gMSA6IDA7CiAgICAgICAgICAgIGZvciAodDMgPSBNYXRoLmFicyh0MyksIGlzTmFOKHQzKSB8fCB0MyA9PT0gMSAvIDAgPyAoaTMgPSBpc05hTih0MykgPyAxIDogMCwgbzIgPSBzMykgOiAobzIgPSBNYXRoLmZsb29yKE1hdGgubG9nKHQzKSAvIE1hdGguTE4yKSwgdDMgKiAobjIgPSBNYXRoLnBvdygyLCAtbzIpKSA8IDEgJiYgKG8yLS0sIG4yICo9IDIpLCAyIDw9ICh0MyArPSAxIDw9IG8yICsgYTMgPyBkIC8gbjIgOiBkICogTWF0aC5wb3coMiwgMSAtIGEzKSkgKiBuMiAmJiAobzIrKywgbjIgLz0gMiksIHMzIDw9IG8yICsgYTMgPyAoaTMgPSAwLCBvMiA9IHMzKSA6IDEgPD0gbzIgKyBhMyA/IChpMyA9ICh0MyAqIG4yIC0gMSkgKiBNYXRoLnBvdygyLCByMyksIG8yICs9IGEzKSA6IChpMyA9IHQzICogTWF0aC5wb3coMiwgYTMgLSAxKSAqIE1hdGgucG93KDIsIHIzKSwgbzIgPSAwKSk7IDggPD0gcjM7IGU0W2wyICsgZjNdID0gMjU1ICYgaTMsIGYzICs9IGgsIGkzIC89IDI1NiwgcjMgLT0gOCkgOwogICAgICAgICAgICBmb3IgKG8yID0gbzIgPDwgcjMgfCBpMywgdTMgKz0gcjM7IDAgPCB1MzsgZTRbbDIgKyBmM10gPSAyNTUgJiBvMiwgZjMgKz0gaCwgbzIgLz0gMjU2LCB1MyAtPSA4KSA7CiAgICAgICAgICAgIGU0W2wyICsgZjMgLSBoXSB8PSAxMjggKiBjMjsKICAgICAgICAgIH07CiAgICAgICAgfSkuY2FsbCh0aGlzLCBlMigibFlwb0kyIiksICJ1bmRlZmluZWQiICE9IHR5cGVvZiBzZWxmID8gc2VsZiA6ICJ1bmRlZmluZWQiICE9IHR5cGVvZiB3aW5kb3cgPyB3aW5kb3cgOiB7fSwgZTIoImJ1ZmZlciIpLkJ1ZmZlciwgYXJndW1lbnRzWzNdLCBhcmd1bWVudHNbNF0sIGFyZ3VtZW50c1s1XSwgYXJndW1lbnRzWzZdLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCAiL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2llZWU3NTQiKTsKICAgICAgfSwgeyBidWZmZXI6IDMsIGxZcG9JMjogMTEgfV0sIDExOiBbZnVuY3Rpb24oZTIsIGgsIHQpIHsKICAgICAgICAhKGZ1bmN0aW9uKGUzLCB0MiwgbiwgcjIsIG8sIGYyLCBsMiwgYzIsIGQpIHsKICAgICAgICAgIHZhciBpMiwgdTIsIHMyOwogICAgICAgICAgZnVuY3Rpb24gYTIoKSB7CiAgICAgICAgICB9CiAgICAgICAgICAoZTMgPSBoLmV4cG9ydHMgPSB7fSkubmV4dFRpY2sgPSAodTIgPSAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ICYmIHdpbmRvdy5zZXRJbW1lZGlhdGUsIHMyID0gInVuZGVmaW5lZCIgIT0gdHlwZW9mIHdpbmRvdyAmJiB3aW5kb3cucG9zdE1lc3NhZ2UgJiYgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIsIHUyID8gZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5zZXRJbW1lZGlhdGUoZTQpOwogICAgICAgICAgfSA6IHMyID8gKGkyID0gW10sIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwgZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgdmFyIHQzID0gZTQuc291cmNlOwogICAgICAgICAgICB0MyAhPT0gd2luZG93ICYmIG51bGwgIT09IHQzIHx8ICJwcm9jZXNzLXRpY2siICE9PSBlNC5kYXRhIHx8IChlNC5zdG9wUHJvcGFnYXRpb24oKSwgMCA8IGkyLmxlbmd0aCAmJiBpMi5zaGlmdCgpKCkpOwogICAgICAgICAgfSwgdHJ1ZSksIGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIGkyLnB1c2goZTQpLCB3aW5kb3cucG9zdE1lc3NhZ2UoInByb2Nlc3MtdGljayIsICIqIik7CiAgICAgICAgICB9KSA6IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIHNldFRpbWVvdXQoZTQsIDApOwogICAgICAgICAgfSksIGUzLnRpdGxlID0gImJyb3dzZXIiLCBlMy5icm93c2VyID0gdHJ1ZSwgZTMuZW52ID0ge30sIGUzLmFyZ3YgPSBbXSwgZTMub24gPSBhMiwgZTMuYWRkTGlzdGVuZXIgPSBhMiwgZTMub25jZSA9IGEyLCBlMy5vZmYgPSBhMiwgZTMucmVtb3ZlTGlzdGVuZXIgPSBhMiwgZTMucmVtb3ZlQWxsTGlzdGVuZXJzID0gYTIsIGUzLmVtaXQgPSBhMiwgZTMuYmluZGluZyA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigicHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQiKTsKICAgICAgICAgIH0sIGUzLmN3ZCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gIi8iOwogICAgICAgICAgfSwgZTMuY2hkaXIgPSBmdW5jdGlvbihlNCkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoInByb2Nlc3MuY2hkaXIgaXMgbm90IHN1cHBvcnRlZCIpOwogICAgICAgICAgfTsKICAgICAgICB9KS5jYWxsKHRoaXMsIGUyKCJsWXBvSTIiKSwgInVuZGVmaW5lZCIgIT0gdHlwZW9mIHNlbGYgPyBzZWxmIDogInVuZGVmaW5lZCIgIT0gdHlwZW9mIHdpbmRvdyA/IHdpbmRvdyA6IHt9LCBlMigiYnVmZmVyIikuQnVmZmVyLCBhcmd1bWVudHNbM10sIGFyZ3VtZW50c1s0XSwgYXJndW1lbnRzWzVdLCBhcmd1bWVudHNbNl0sICIvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwgIi9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9wcm9jZXNzIik7CiAgICAgIH0sIHsgYnVmZmVyOiAzLCBsWXBvSTI6IDExIH1dIH0sIHt9LCBbMV0pKDEpOwogICAgfSk7CiAgfSkob2JqZWN0X2hhc2gpOwogIHZhciBvYmplY3RfaGFzaEV4cG9ydHMgPSBvYmplY3RfaGFzaC5leHBvcnRzOwogIHZhciBoYXNoID0gLyogQF9fUFVSRV9fICovIGdldERlZmF1bHRFeHBvcnRGcm9tQ2pzKG9iamVjdF9oYXNoRXhwb3J0cyk7CiAgY2xhc3MgTWFwMmRCYXNlIHsKICAgIGNvbnN0cnVjdG9yKHNlcmlhbGl6ZUZpcnN0QXhpcyA9IChrZXkpID0+IHR5cGVvZiBrZXkgPT09ICJzdHJpbmciID8ga2V5IDogaGFzaChrZXkpLCBzZXJpYWxpemVTZWNvbmRBeGlzID0gKGtleSkgPT4gdHlwZW9mIGtleSA9PT0gInN0cmluZyIgPyBrZXkgOiBoYXNoKGtleSksIGluaXRpYWxDb250ZW50KSB7CiAgICAgIHRoaXMuc2VyaWFsaXplRmlyc3RBeGlzID0gc2VyaWFsaXplRmlyc3RBeGlzOwogICAgICB0aGlzLnNlcmlhbGl6ZVNlY29uZEF4aXMgPSBzZXJpYWxpemVTZWNvbmRBeGlzOwogICAgICB0aGlzLmRhdGEgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLmtleXNGaXJzdEF4aXMgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpOwogICAgICB0aGlzLmtleXNTZWNvbmRBeGlzID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICAgICAgaWYgKGluaXRpYWxDb250ZW50KSB7CiAgICAgICAgdGhpcy5rZXlzRmlyc3RBeGlzID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5rZXlzRmlyc3RBeGlzKTsKICAgICAgICB0aGlzLmtleXNTZWNvbmRBeGlzID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5rZXlzU2Vjb25kQXhpcyk7CiAgICAgICAgdGhpcy5kYXRhID0gbmV3IE1hcChpbml0aWFsQ29udGVudC5kYXRhKTsKICAgICAgfQogICAgfQogICAgZ2V0KGtleUZpcnN0QXhpcywga2V5U2Vjb25kQXhpcykgewogICAgICB2YXIgX2E7CiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMgPSB0aGlzLnNlcmlhbGl6ZUZpcnN0QXhpcyhrZXlGaXJzdEF4aXMpOwogICAgICBjb25zdCBzZXJpYWxpemVkS2V5U2Vjb25kQXhpcyA9IHRoaXMuc2VyaWFsaXplU2Vjb25kQXhpcyhrZXlTZWNvbmRBeGlzKTsKICAgICAgcmV0dXJuIChfYSA9IHRoaXMuZGF0YS5nZXQoc2VyaWFsaXplZEtleUZpcnN0QXhpcykpID09IG51bGwgPyB2b2lkIDAgOiBfYS5nZXQoc2VyaWFsaXplZEtleVNlY29uZEF4aXMpOwogICAgfQogICAgZ2V0Um93KGtleSwgZmlsbEVtcHR5V2l0aCkgewogICAgICBjb25zdCBzZXJpYWxpemVkS2V5Rmlyc3RBeGlzID0gdGhpcy5zZXJpYWxpemVGaXJzdEF4aXMoa2V5KTsKICAgICAgY29uc3Qgcm93ID0gdGhpcy5kYXRhLmdldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKTsKICAgICAgaWYgKHJvdyA9PT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIFtdOwogICAgICB9CiAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMua2V5c1NlY29uZEF4aXMua2V5cygpKS5tYXAoKGtleTIpID0+IHJvdy5nZXQoa2V5MikgPz8gZmlsbEVtcHR5V2l0aCk7CiAgICB9CiAgICBzZXQoa2V5Rmlyc3RBeGlzLCBrZXlTZWNvbmRBeGlzLCB2YWx1ZSkgewogICAgICBjb25zdCBzZXJpYWxpemVkS2V5Rmlyc3RBeGlzID0gdGhpcy5zZXJpYWxpemVGaXJzdEF4aXMoa2V5Rmlyc3RBeGlzKTsKICAgICAgY29uc3Qgc2VyaWFsaXplZEtleVNlY29uZEF4aXMgPSB0aGlzLnNlcmlhbGl6ZVNlY29uZEF4aXMoa2V5U2Vjb25kQXhpcyk7CiAgICAgIGlmICghdGhpcy5kYXRhLmhhcyhzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKSkgewogICAgICAgIHRoaXMuZGF0YS5zZXQoc2VyaWFsaXplZEtleUZpcnN0QXhpcywgLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKSk7CiAgICAgIH0KICAgICAgdGhpcy5kYXRhLmdldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzKS5zZXQoc2VyaWFsaXplZEtleVNlY29uZEF4aXMsIHZhbHVlKTsKICAgICAgdGhpcy5rZXlzRmlyc3RBeGlzLnNldChzZXJpYWxpemVkS2V5Rmlyc3RBeGlzLCBrZXlGaXJzdEF4aXMpOwogICAgICB0aGlzLmtleXNTZWNvbmRBeGlzLnNldChzZXJpYWxpemVkS2V5U2Vjb25kQXhpcywga2V5U2Vjb25kQXhpcyk7CiAgICB9CiAgICBkZWxldGVSb3coa2V5KSB7CiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMgPSB0aGlzLnNlcmlhbGl6ZUZpcnN0QXhpcyhrZXkpOwogICAgICB0aGlzLmRhdGEuZGVsZXRlKHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMpOwogICAgICB0aGlzLmtleXNGaXJzdEF4aXMuZGVsZXRlKHNlcmlhbGl6ZWRLZXlGaXJzdEF4aXMpOwogICAgfQogICAgZ2V0Rmlyc3RBeGlzS2V5cygpIHsKICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5rZXlzRmlyc3RBeGlzLnZhbHVlcygpKTsKICAgIH0KICAgIGdldFNlY29uZEF4aXNLZXlzKCkgewogICAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLmtleXNTZWNvbmRBeGlzLnZhbHVlcygpKTsKICAgIH0KICAgIGdldEFzQXJyYXkoZmlsbEVtcHR5V2l0aCkgewogICAgICByZXR1cm4gdGhpcy5nZXRGaXJzdEF4aXNLZXlzKCkubWFwKChmaXJzdEF4aXNLZXkpID0+IHsKICAgICAgICByZXR1cm4gdGhpcy5nZXRTZWNvbmRBeGlzS2V5cygpLm1hcCgoc2Vjb25kQXhpc0tleSkgPT4gewogICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KGZpcnN0QXhpc0tleSwgc2Vjb25kQXhpc0tleSkgPz8gZmlsbEVtcHR5V2l0aDsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9CiAgICBnZXRDb250ZW50cygpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBrZXlzRmlyc3RBeGlzOiB0aGlzLmtleXNGaXJzdEF4aXMsCiAgICAgICAga2V5c1NlY29uZEF4aXM6IHRoaXMua2V5c1NlY29uZEF4aXMsCiAgICAgICAgZGF0YTogdGhpcy5kYXRhCiAgICAgIH07CiAgICB9CiAgfQogIGNvbnN0IE1BWF9OVU1CRVJfT0ZfR1JJRF9DT0xVTU5TID0gMjAwOwogIGFzeW5jIGZ1bmN0aW9uIHF1ZXJ5T3ZlcmFsbE11dGF0aW9uRGF0YSh7CiAgICBsYXBpc0ZpbHRlciwKICAgIHNlcXVlbmNlVHlwZSwKICAgIGxhcGlzLAogICAgZ3JhbnVsYXJpdHksCiAgICBsYXBpc0RhdGVGaWVsZCwKICAgIHNpZ25hbAogIH0pIHsKICAgIGNvbnN0IGFsbERhdGVzID0gYXdhaXQgZ2V0RGF0ZXNJbkRhdGFzZXQobGFwaXNGaWx0ZXIsIGxhcGlzLCBncmFudWxhcml0eSwgbGFwaXNEYXRlRmllbGQsIHNpZ25hbCk7CiAgICBjb25zdCBmaWx0ZXIgPSB7CiAgICAgIC4uLmxhcGlzRmlsdGVyLAogICAgICBbYCR7bGFwaXNEYXRlRmllbGR9RnJvbWBdOiBhbGxEYXRlc1swXS5maXJzdERheS50b1N0cmluZygpLAogICAgICBbYCR7bGFwaXNEYXRlRmllbGR9VG9gXTogYWxsRGF0ZXNbYWxsRGF0ZXMubGVuZ3RoIC0gMV0ubGFzdERheS50b1N0cmluZygpCiAgICB9OwogICAgcmV0dXJuIGZldGNoQW5kUHJlcGFyZVN1YnN0aXR1dGlvbnNPckRlbGV0aW9ucyhmaWx0ZXIsIHNlcXVlbmNlVHlwZSkuZXZhbHVhdGUobGFwaXMsIHNpZ25hbCk7CiAgfQogIGFzeW5jIGZ1bmN0aW9uIHF1ZXJ5TXV0YXRpb25zT3ZlclRpbWVEYXRhKHsKICAgIGxhcGlzRmlsdGVyLAogICAgc2VxdWVuY2VUeXBlLAogICAgbGFwaXMsCiAgICBsYXBpc0RhdGVGaWVsZCwKICAgIGdyYW51bGFyaXR5LAogICAgc2lnbmFsCiAgfSkgewogICAgY29uc3QgYWxsRGF0ZXMgPSBhd2FpdCBnZXREYXRlc0luRGF0YXNldChsYXBpc0ZpbHRlciwgbGFwaXMsIGdyYW51bGFyaXR5LCBsYXBpc0RhdGVGaWVsZCwgc2lnbmFsKTsKICAgIGlmIChhbGxEYXRlcy5sZW5ndGggPiBNQVhfTlVNQkVSX09GX0dSSURfQ09MVU1OUykgewogICAgICB0aHJvdyBuZXcgVXNlckZhY2luZ0Vycm9yKAogICAgICAgICJUb28gbWFueSBkYXRlcyIsCiAgICAgICAgYFRoZSBkYXRhc2V0IHdvdWxkIGNvbnRhaW4gJHthbGxEYXRlcy5sZW5ndGh9IGRhdGUgaW50ZXJ2YWxzLiBQbGVhc2UgcmVkdWNlIHRoZSBudW1iZXIgdG8gYmVsb3cgJHtNQVhfTlVNQkVSX09GX0dSSURfQ09MVU1OU30gdG8gZGlzcGxheSB0aGUgZGF0YS4gWW91IGNhbiBhY2hpZXZlIHRoaXMgYnkgZWl0aGVyIG5hcnJvd2luZyB0aGUgZGF0ZSByYW5nZSBpbiB0aGUgcHJvdmlkZWQgTEFQSVMgZmlsdGVyIG9yIGJ5IHNlbGVjdGluZyBhIGxhcmdlciBncmFudWxhcml0eS5gCiAgICAgICk7CiAgICB9CiAgICBjb25zdCBzdWJRdWVyaWVzID0gYWxsRGF0ZXMubWFwKGFzeW5jIChkYXRlKSA9PiB7CiAgICAgIGNvbnN0IGRhdGVGcm9tID0gZGF0ZS5maXJzdERheS50b1N0cmluZygpOwogICAgICBjb25zdCBkYXRlVG8gPSBkYXRlLmxhc3REYXkudG9TdHJpbmcoKTsKICAgICAgY29uc3QgZmlsdGVyID0gewogICAgICAgIC4uLmxhcGlzRmlsdGVyLAogICAgICAgIFtgJHtsYXBpc0RhdGVGaWVsZH1Gcm9tYF06IGRhdGVGcm9tLAogICAgICAgIFtgJHtsYXBpc0RhdGVGaWVsZH1Ub2BdOiBkYXRlVG8KICAgICAgfTsKICAgICAgY29uc3QgZGF0YTIgPSBhd2FpdCBmZXRjaEFuZFByZXBhcmVTdWJzdGl0dXRpb25zT3JEZWxldGlvbnMoZmlsdGVyLCBzZXF1ZW5jZVR5cGUpLmV2YWx1YXRlKGxhcGlzLCBzaWduYWwpOwogICAgICBjb25zdCB0b3RhbENvdW50UXVlcnkgPSBhd2FpdCBnZXRUb3RhbE51bWJlck9mU2VxdWVuY2VzSW5EYXRlUmFuZ2UoZmlsdGVyKS5ldmFsdWF0ZShsYXBpcywgc2lnbmFsKTsKICAgICAgcmV0dXJuIHsKICAgICAgICBkYXRlLAogICAgICAgIG11dGF0aW9uczogZGF0YTIuY29udGVudCwKICAgICAgICB0b3RhbENvdW50OiB0b3RhbENvdW50UXVlcnkuY29udGVudFswXS5jb3VudAogICAgICB9OwogICAgfSk7CiAgICBjb25zdCBkYXRhID0gYXdhaXQgUHJvbWlzZS5hbGwoc3ViUXVlcmllcyk7CiAgICBjb25zdCBvdmVyYWxsTXV0YXRpb25zRGF0YSA9IChhd2FpdCBxdWVyeU92ZXJhbGxNdXRhdGlvbkRhdGEoewogICAgICBsYXBpc0ZpbHRlciwKICAgICAgc2VxdWVuY2VUeXBlLAogICAgICBsYXBpcywKICAgICAgbGFwaXNEYXRlRmllbGQsCiAgICAgIGdyYW51bGFyaXR5CiAgICB9KSkuY29udGVudDsKICAgIHJldHVybiB7CiAgICAgIG11dGF0aW9uT3ZlclRpbWVEYXRhOiBncm91cEJ5TXV0YXRpb24oZGF0YSwgb3ZlcmFsbE11dGF0aW9uc0RhdGEpLAogICAgICBvdmVyYWxsTXV0YXRpb25EYXRhOiBvdmVyYWxsTXV0YXRpb25zRGF0YQogICAgfTsKICB9CiAgYXN5bmMgZnVuY3Rpb24gZ2V0RGF0ZXNJbkRhdGFzZXQobGFwaXNGaWx0ZXIsIGxhcGlzLCBncmFudWxhcml0eSwgbGFwaXNEYXRlRmllbGQsIHNpZ25hbCkgewogICAgY29uc3QgeyBjb250ZW50OiBhdmFpbGFibGVEYXRlcyB9ID0gYXdhaXQgcXVlcnlBdmFpbGFibGVEYXRlcygKICAgICAgbGFwaXNGaWx0ZXIsCiAgICAgIGxhcGlzLAogICAgICBncmFudWxhcml0eSwKICAgICAgbGFwaXNEYXRlRmllbGQsCiAgICAgIHNpZ25hbAogICAgKTsKICAgIGNvbnN0IHsgZGF0ZUZyb20sIGRhdGVUbyB9ID0gZ2V0RGF0ZVJhbmdlRnJvbUZpbHRlcihsYXBpc0ZpbHRlciwgbGFwaXNEYXRlRmllbGQsIGdyYW51bGFyaXR5KTsKICAgIGNvbnN0IHsgbWluLCBtYXggfSA9IGdldE1pbk1heFRlbXBvcmFsKGF2YWlsYWJsZURhdGVzKTsKICAgIHJldHVybiBnZW5lcmF0ZUFsbEluUmFuZ2UoZGF0ZUZyb20gPz8gbWluLCBkYXRlVG8gPz8gbWF4KTsKICB9CiAgZnVuY3Rpb24gZ2V0RGF0ZVJhbmdlRnJvbUZpbHRlcihsYXBpc0ZpbHRlciwgbGFwaXNEYXRlRmllbGQsIGdyYW51bGFyaXR5KSB7CiAgICBjb25zdCB2YWx1ZUZyb21GaWx0ZXIgPSBsYXBpc0ZpbHRlcltsYXBpc0RhdGVGaWVsZF07CiAgICBpZiAodmFsdWVGcm9tRmlsdGVyKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgZGF0ZUZyb206IHBhcnNlRGF0ZVN0cmluZ1RvVGVtcG9yYWwodmFsdWVGcm9tRmlsdGVyLCBncmFudWxhcml0eSksCiAgICAgICAgZGF0ZVRvOiBwYXJzZURhdGVTdHJpbmdUb1RlbXBvcmFsKHZhbHVlRnJvbUZpbHRlciwgZ3JhbnVsYXJpdHkpCiAgICAgIH07CiAgICB9CiAgICBjb25zdCBtaW5Gcm9tRmlsdGVyID0gbGFwaXNGaWx0ZXJbYCR7bGFwaXNEYXRlRmllbGR9RnJvbWBdOwogICAgY29uc3QgbWF4RnJvbUZpbHRlciA9IGxhcGlzRmlsdGVyW2Ake2xhcGlzRGF0ZUZpZWxkfVRvYF07CiAgICByZXR1cm4gewogICAgICBkYXRlRnJvbTogbWluRnJvbUZpbHRlciA/IHBhcnNlRGF0ZVN0cmluZ1RvVGVtcG9yYWwobWluRnJvbUZpbHRlciwgZ3JhbnVsYXJpdHkpIDogbnVsbCwKICAgICAgZGF0ZVRvOiBtYXhGcm9tRmlsdGVyID8gcGFyc2VEYXRlU3RyaW5nVG9UZW1wb3JhbChtYXhGcm9tRmlsdGVyLCBncmFudWxhcml0eSkgOiBudWxsCiAgICB9OwogIH0KICBmdW5jdGlvbiBxdWVyeUF2YWlsYWJsZURhdGVzKGxhcGlzRmlsdGVyLCBsYXBpcywgZ3JhbnVsYXJpdHksIGxhcGlzRGF0ZUZpZWxkLCBzaWduYWwpIHsKICAgIHJldHVybiBmZXRjaEFuZFByZXBhcmVEYXRlcyhsYXBpc0ZpbHRlciwgZ3JhbnVsYXJpdHksIGxhcGlzRGF0ZUZpZWxkKS5ldmFsdWF0ZShsYXBpcywgc2lnbmFsKTsKICB9CiAgZnVuY3Rpb24gZmV0Y2hBbmRQcmVwYXJlRGF0ZXMoZmlsdGVyLCBncmFudWxhcml0eSwgbGFwaXNEYXRlRmllbGQpIHsKICAgIGNvbnN0IGZldGNoRGF0YSA9IG5ldyBGZXRjaEFnZ3JlZ2F0ZWRPcGVyYXRvcihmaWx0ZXIsIFtsYXBpc0RhdGVGaWVsZF0pOwogICAgY29uc3QgZGF0YVdpdGhGaXhlZERhdGVLZXkgPSBuZXcgUmVuYW1lRmllbGRPcGVyYXRvcihmZXRjaERhdGEsIGxhcGlzRGF0ZUZpZWxkLCAiZGF0ZSIpOwogICAgY29uc3QgbWFwRGF0YSA9IG5ldyBNYXBPcGVyYXRvcihkYXRhV2l0aEZpeGVkRGF0ZUtleSwgKGRhdGEpID0+IG1hcERhdGVUb0dyYW51bGFyaXR5UmFuZ2UoZGF0YSwgZ3JhbnVsYXJpdHkpKTsKICAgIGNvbnN0IGdyb3VwQnlEYXRhID0gbmV3IEdyb3VwQnlBbmRTdW1PcGVyYXRvcihtYXBEYXRhLCAiZGF0ZVJhbmdlIiwgImNvdW50Iik7CiAgICBjb25zdCBzb3J0RGF0YSA9IG5ldyBTb3J0T3BlcmF0b3IoZ3JvdXBCeURhdGEsIGRhdGVSYW5nZUNvbXBhcmUpOwogICAgcmV0dXJuIG5ldyBNYXBPcGVyYXRvcihzb3J0RGF0YSwgKGRhdGEpID0+IGRhdGEuZGF0ZVJhbmdlKTsKICB9CiAgZnVuY3Rpb24gZmV0Y2hBbmRQcmVwYXJlU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zKGZpbHRlciwgc2VxdWVuY2VUeXBlKSB7CiAgICByZXR1cm4gbmV3IEZldGNoU3Vic3RpdHV0aW9uc09yRGVsZXRpb25zT3BlcmF0b3IoZmlsdGVyLCBzZXF1ZW5jZVR5cGUsIDFlLTMpOwogIH0KICBmdW5jdGlvbiBzZXJpYWxpemVTdWJzdGl0dXRpb25PckRlbGV0aW9uKG11dGF0aW9uKSB7CiAgICByZXR1cm4gbXV0YXRpb24uY29kZTsKICB9CiAgZnVuY3Rpb24gc2VyaWFsaXplVGVtcG9yYWwoZGF0ZSkgewogICAgcmV0dXJuIGRhdGUuZGF0ZVN0cmluZzsKICB9CiAgZnVuY3Rpb24gZ3JvdXBCeU11dGF0aW9uKGRhdGEsIG92ZXJhbGxNdXRhdGlvbkRhdGEpIHsKICAgIGNvbnN0IGRhdGFBcnJheSA9IG5ldyBNYXAyZEJhc2UoCiAgICAgIHNlcmlhbGl6ZVN1YnN0aXR1dGlvbk9yRGVsZXRpb24sCiAgICAgIHNlcmlhbGl6ZVRlbXBvcmFsCiAgICApOwogICAgY29uc3QgYWxsRGF0ZXMgPSBkYXRhLm1hcCgobXV0YXRpb25EYXRhKSA9PiBtdXRhdGlvbkRhdGEuZGF0ZSk7CiAgICBjb25zdCBzb3J0ZWRPdmVyYWxsTXV0YXRpb25EYXRhID0gb3ZlcmFsbE11dGF0aW9uRGF0YS5zb3J0KChhMiwgYikgPT4gc29ydFN1YnN0aXR1dGlvbnNBbmREZWxldGlvbnMoYTIubXV0YXRpb24sIGIubXV0YXRpb24pKS5tYXAoKGVudHJ5KSA9PiB7CiAgICAgIHJldHVybiB0b1N1YnN0aXR1dGlvbk9yRGVsZXRpb24oZW50cnkubXV0YXRpb24pOwogICAgfSk7CiAgICBjb25zdCBzb3J0ZWREYXRlcyA9IGFsbERhdGVzLnNvcnQoKGEyLCBiKSA9PiBjb21wYXJlVGVtcG9yYWwoYTIsIGIpKS5tYXAoKGRhdGUpID0+IHRvVGVtcG9yYWwoZGF0ZSkpOwogICAgc29ydGVkT3ZlcmFsbE11dGF0aW9uRGF0YS5mb3JFYWNoKChtdXRhdGlvbkRhdGEpID0+IHsKICAgICAgc29ydGVkRGF0ZXMuZm9yRWFjaCgoZGF0ZSkgPT4gewogICAgICAgIGRhdGFBcnJheS5zZXQobXV0YXRpb25EYXRhLCBkYXRlLCB7CiAgICAgICAgICBjb3VudDogMCwKICAgICAgICAgIHByb3BvcnRpb246IDAsCiAgICAgICAgICB0b3RhbENvdW50OiAwCiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfSk7CiAgICBkYXRhLmZvckVhY2goKG11dGF0aW9uRGF0YSkgPT4gewogICAgICBtdXRhdGlvbkRhdGEubXV0YXRpb25zLmZvckVhY2goKG11dGF0aW9uRW50cnkpID0+IHsKICAgICAgICBjb25zdCBtdXRhdGlvbiA9IHRvU3Vic3RpdHV0aW9uT3JEZWxldGlvbihtdXRhdGlvbkVudHJ5Lm11dGF0aW9uKTsKICAgICAgICBjb25zdCBkYXRlID0gdG9UZW1wb3JhbChtdXRhdGlvbkRhdGEuZGF0ZSk7CiAgICAgICAgaWYgKGRhdGFBcnJheS5nZXQobXV0YXRpb24sIGRhdGUpICE9PSB2b2lkIDApIHsKICAgICAgICAgIGRhdGFBcnJheS5zZXQobXV0YXRpb24sIGRhdGUsIHsKICAgICAgICAgICAgY291bnQ6IG11dGF0aW9uRW50cnkuY291bnQsCiAgICAgICAgICAgIHByb3BvcnRpb246IG11dGF0aW9uRW50cnkucHJvcG9ydGlvbiwKICAgICAgICAgICAgdG90YWxDb3VudDogbXV0YXRpb25EYXRhLnRvdGFsQ291bnQKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9KTsKICAgIHJldHVybiBkYXRhQXJyYXk7CiAgfQogIGZ1bmN0aW9uIGdldFRvdGFsTnVtYmVyT2ZTZXF1ZW5jZXNJbkRhdGVSYW5nZShmaWx0ZXIpIHsKICAgIHJldHVybiBuZXcgRmV0Y2hBZ2dyZWdhdGVkT3BlcmF0b3IoZmlsdGVyKTsKICB9CiAgYXN5bmMgZnVuY3Rpb24gd29ya2VyRnVuY3Rpb24ocXVlcnlGdW5jdGlvbikgewogICAgdHJ5IHsKICAgICAgcG9zdE1lc3NhZ2UoeyBzdGF0dXM6ICJsb2FkaW5nIiB9KTsKICAgICAgY29uc3Qgd29ya2VyUmVzcG9uc2UgPSBhd2FpdCBxdWVyeUZ1bmN0aW9uKCk7CiAgICAgIHBvc3RNZXNzYWdlKHsKICAgICAgICBzdGF0dXM6ICJzdWNjZXNzIiwKICAgICAgICBkYXRhOiB3b3JrZXJSZXNwb25zZQogICAgICB9KTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIHBvc3RNZXNzYWdlKHsgc3RhdHVzOiAiZXJyb3IiLCBlcnJvciB9KTsKICAgIH0KICB9CiAgYXN5bmMgZnVuY3Rpb24gZ2V0TXV0YXRpb25PdmVyVGltZVdvcmtlckZ1bmN0aW9uKGV2ZW50KSB7CiAgICBjb25zdCBtdXRhdGlvbk92ZXJUaW1lRGF0YSA9IGF3YWl0IHF1ZXJ5TXV0YXRpb25zT3ZlclRpbWVEYXRhKGV2ZW50LmRhdGEpOwogICAgY29uc3Qgd29ya2VyUmVzcG9uc2UgPSB7CiAgICAgIG92ZXJhbGxNdXRhdGlvbkRhdGE6IG11dGF0aW9uT3ZlclRpbWVEYXRhLm92ZXJhbGxNdXRhdGlvbkRhdGEsCiAgICAgIG11dGF0aW9uT3ZlclRpbWVTZXJpYWxpemVkOiBtdXRhdGlvbk92ZXJUaW1lRGF0YS5tdXRhdGlvbk92ZXJUaW1lRGF0YS5nZXRDb250ZW50cygpCiAgICB9OwogICAgcmV0dXJuIHdvcmtlclJlc3BvbnNlOwogIH0KICBzZWxmLm9ubWVzc2FnZSA9IGFzeW5jIGZ1bmN0aW9uKGV2ZW50KSB7CiAgICBhd2FpdCB3b3JrZXJGdW5jdGlvbigoKSA9PiBnZXRNdXRhdGlvbk92ZXJUaW1lV29ya2VyRnVuY3Rpb24oZXZlbnQpKTsKICB9Owp9KSgpOwovLyMgc291cmNlTWFwcGluZ1VSTD1tdXRhdGlvbk92ZXJUaW1lV29ya2VyLUJkenFEcXZPLmpzLm1hcAo=";
|
|
8473
|
+
const decodeBase64 = (base64) => Uint8Array.from(atob(base64), (c2) => c2.charCodeAt(0));
|
|
8474
|
+
const blob = typeof self !== "undefined" && self.Blob && new Blob([decodeBase64(encodedJs)], { type: "text/javascript;charset=utf-8" });
|
|
8475
|
+
function WorkerWrapper(options2) {
|
|
8476
|
+
let objURL;
|
|
8477
|
+
try {
|
|
8478
|
+
objURL = blob && (self.URL || self.webkitURL).createObjectURL(blob);
|
|
8479
|
+
if (!objURL) throw "";
|
|
8480
|
+
const worker = new Worker(objURL, {
|
|
8481
|
+
name: options2 == null ? void 0 : options2.name
|
|
8482
|
+
});
|
|
8483
|
+
worker.addEventListener("error", () => {
|
|
8484
|
+
(self.URL || self.webkitURL).revokeObjectURL(objURL);
|
|
8485
|
+
});
|
|
8486
|
+
return worker;
|
|
8487
|
+
} catch (e2) {
|
|
8488
|
+
return new Worker(
|
|
8489
|
+
"data:text/javascript;base64," + encodedJs,
|
|
8490
|
+
{
|
|
8491
|
+
name: options2 == null ? void 0 : options2.name
|
|
8492
|
+
}
|
|
8493
|
+
);
|
|
8494
|
+
} finally {
|
|
8495
|
+
objURL && (self.URL || self.webkitURL).revokeObjectURL(objURL);
|
|
8496
|
+
}
|
|
8497
|
+
}
|
|
8438
8498
|
class Map2dBase {
|
|
8439
|
-
constructor(serializeFirstAxis = (key) => typeof key === "string" ? key : hash(key), serializeSecondAxis = (key) => typeof key === "string" ? key : hash(key)) {
|
|
8499
|
+
constructor(serializeFirstAxis = (key) => typeof key === "string" ? key : hash(key), serializeSecondAxis = (key) => typeof key === "string" ? key : hash(key), initialContent) {
|
|
8440
8500
|
this.serializeFirstAxis = serializeFirstAxis;
|
|
8441
8501
|
this.serializeSecondAxis = serializeSecondAxis;
|
|
8442
8502
|
this.data = /* @__PURE__ */ new Map();
|
|
8443
8503
|
this.keysFirstAxis = /* @__PURE__ */ new Map();
|
|
8444
8504
|
this.keysSecondAxis = /* @__PURE__ */ new Map();
|
|
8505
|
+
if (initialContent) {
|
|
8506
|
+
this.keysFirstAxis = new Map(initialContent.keysFirstAxis);
|
|
8507
|
+
this.keysSecondAxis = new Map(initialContent.keysSecondAxis);
|
|
8508
|
+
this.data = new Map(initialContent.data);
|
|
8509
|
+
}
|
|
8445
8510
|
}
|
|
8446
8511
|
get(keyFirstAxis, keySecondAxis) {
|
|
8447
8512
|
var _a;
|
|
@@ -8485,6 +8550,13 @@ class Map2dBase {
|
|
|
8485
8550
|
});
|
|
8486
8551
|
});
|
|
8487
8552
|
}
|
|
8553
|
+
getContents() {
|
|
8554
|
+
return {
|
|
8555
|
+
keysFirstAxis: this.keysFirstAxis,
|
|
8556
|
+
keysSecondAxis: this.keysSecondAxis,
|
|
8557
|
+
data: this.data
|
|
8558
|
+
};
|
|
8559
|
+
}
|
|
8488
8560
|
}
|
|
8489
8561
|
class Map2dView {
|
|
8490
8562
|
constructor(map) {
|
|
@@ -8538,47 +8610,21 @@ class Map2dView {
|
|
|
8538
8610
|
}
|
|
8539
8611
|
function getFilteredMutationOverTimeData(data, overallMutationData, displayedSegments, displayedMutationTypes, proportionInterval) {
|
|
8540
8612
|
const filteredData = new Map2dView(data);
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
return filteredData;
|
|
8545
|
-
}
|
|
8546
|
-
function filterDisplayedSegments(displayedSegments, data) {
|
|
8547
|
-
displayedSegments.forEach((segment) => {
|
|
8548
|
-
if (!segment.checked) {
|
|
8549
|
-
data.getFirstAxisKeys().forEach((mutation) => {
|
|
8550
|
-
if (mutation.segment === segment.segment) {
|
|
8551
|
-
data.deleteRow(mutation);
|
|
8552
|
-
}
|
|
8553
|
-
});
|
|
8613
|
+
const mutationsToFilterOut = overallMutationData.filter((entry) => {
|
|
8614
|
+
if (entry.proportion < proportionInterval.min || entry.proportion > proportionInterval.max) {
|
|
8615
|
+
return true;
|
|
8554
8616
|
}
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
function filterMutationTypes(displayedMutationTypes, data) {
|
|
8558
|
-
displayedMutationTypes.forEach((mutationType) => {
|
|
8559
|
-
if (!mutationType.checked) {
|
|
8560
|
-
data.getFirstAxisKeys().forEach((mutation) => {
|
|
8561
|
-
if (mutationType.type === mutation.type) {
|
|
8562
|
-
data.deleteRow(mutation);
|
|
8563
|
-
}
|
|
8564
|
-
});
|
|
8617
|
+
if (displayedSegments.some((segment) => segment.segment === entry.mutation.segment && !segment.checked)) {
|
|
8618
|
+
return true;
|
|
8565
8619
|
}
|
|
8620
|
+
return displayedMutationTypes.some(
|
|
8621
|
+
(mutationType) => mutationType.type === entry.mutation.type && !mutationType.checked
|
|
8622
|
+
);
|
|
8566
8623
|
});
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
const overallProportionsByMutation = overallMutationData.content.reduce(
|
|
8570
|
-
(acc, { mutation, proportion }) => ({
|
|
8571
|
-
...acc,
|
|
8572
|
-
[mutation.toString()]: proportion
|
|
8573
|
-
}),
|
|
8574
|
-
{}
|
|
8575
|
-
);
|
|
8576
|
-
data.getFirstAxisKeys().forEach((mutation) => {
|
|
8577
|
-
const overallProportion = overallProportionsByMutation[mutation.toString()] || -1;
|
|
8578
|
-
if (overallProportion < proportionInterval.min || overallProportion > proportionInterval.max) {
|
|
8579
|
-
data.deleteRow(mutation);
|
|
8580
|
-
}
|
|
8624
|
+
mutationsToFilterOut.forEach((entry) => {
|
|
8625
|
+
filteredData.deleteRow(entry.mutation);
|
|
8581
8626
|
});
|
|
8627
|
+
return filteredData;
|
|
8582
8628
|
}
|
|
8583
8629
|
const ColorScaleSelector = ({ colorScale, setColorScale }) => {
|
|
8584
8630
|
const colorDisplayCss = `w-10 h-8 border border-gray-200 mx-2 text-xs flex items-center justify-center`;
|
|
@@ -8673,9 +8719,9 @@ const Tooltip = ({ children, content, position = "bottom" }) => {
|
|
|
8673
8719
|
const MAX_NUMBER_OF_GRID_ROWS = 100;
|
|
8674
8720
|
const MUTATION_CELL_WIDTH_REM = 8;
|
|
8675
8721
|
const MutationsOverTimeGrid = ({ data, colorScale }) => {
|
|
8676
|
-
const allMutations = data.getFirstAxisKeys()
|
|
8722
|
+
const allMutations = data.getFirstAxisKeys();
|
|
8677
8723
|
const shownMutations = allMutations.slice(0, MAX_NUMBER_OF_GRID_ROWS);
|
|
8678
|
-
const dates = data.getSecondAxisKeys()
|
|
8724
|
+
const dates = data.getSecondAxisKeys();
|
|
8679
8725
|
const [showProportionText, setShowProportionText] = h(false);
|
|
8680
8726
|
const gridRef = A(null);
|
|
8681
8727
|
useShowProportion(gridRef, dates.length, setShowProportionText);
|
|
@@ -8763,11 +8809,12 @@ function getTooltipPosition(rowIndex, rows, columnIndex, columns) {
|
|
|
8763
8809
|
return `${tooltipX}-${tooltipY}`;
|
|
8764
8810
|
}
|
|
8765
8811
|
const ProportionCell = ({ value, mutation, date, tooltipPosition, showProportionText, colorScale }) => {
|
|
8812
|
+
const dateClass = toTemporalClass(date);
|
|
8766
8813
|
const tooltipContent = /* @__PURE__ */ u$1("div", { children: [
|
|
8767
|
-
/* @__PURE__ */ u$1("p", { children: /* @__PURE__ */ u$1("span", { className: "font-bold", children:
|
|
8814
|
+
/* @__PURE__ */ u$1("p", { children: /* @__PURE__ */ u$1("span", { className: "font-bold", children: dateClass.englishName() }) }),
|
|
8768
8815
|
/* @__PURE__ */ u$1("p", { children: [
|
|
8769
8816
|
"(",
|
|
8770
|
-
timeIntervalDisplay(
|
|
8817
|
+
timeIntervalDisplay(dateClass),
|
|
8771
8818
|
")"
|
|
8772
8819
|
] }),
|
|
8773
8820
|
/* @__PURE__ */ u$1("p", { children: mutation.code }),
|
|
@@ -8796,115 +8843,19 @@ const ProportionCell = ({ value, mutation, date, tooltipPosition, showProportion
|
|
|
8796
8843
|
) }) });
|
|
8797
8844
|
};
|
|
8798
8845
|
const timeIntervalDisplay = (date) => {
|
|
8799
|
-
if (date instanceof
|
|
8846
|
+
if (date instanceof YearMonthDayClass) {
|
|
8800
8847
|
return date.toString();
|
|
8801
8848
|
}
|
|
8802
8849
|
return `${date.firstDay.toString()} - ${date.lastDay.toString()}`;
|
|
8803
8850
|
};
|
|
8804
8851
|
const MutationCell = ({ mutation }) => {
|
|
8805
|
-
return /* @__PURE__ */ u$1("div", { className: "text-center", children: mutation.
|
|
8852
|
+
return /* @__PURE__ */ u$1("div", { className: "text-center", children: mutation.code });
|
|
8806
8853
|
};
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
return fetchAndPrepareSubstitutionsOrDeletions(lapisFilter, sequenceType).evaluate(lapis, signal);
|
|
8810
|
-
}
|
|
8811
|
-
async function queryMutationsOverTimeData(lapisFilter, sequenceType, lapis, lapisDateField, granularity, signal) {
|
|
8812
|
-
const allDates = await getDatesInDataset(lapisFilter, lapis, granularity, lapisDateField, signal);
|
|
8813
|
-
if (allDates.length > MAX_NUMBER_OF_GRID_COLUMNS) {
|
|
8814
|
-
throw new UserFacingError(
|
|
8815
|
-
"Too many dates",
|
|
8816
|
-
`The dataset would contain ${allDates.length} date intervals. Please reduce the number to below ${MAX_NUMBER_OF_GRID_COLUMNS} to display the data. You can achieve this by either narrowing the date range in the provided LAPIS filter or by selecting a larger granularity.`
|
|
8817
|
-
);
|
|
8818
|
-
}
|
|
8819
|
-
const subQueries = allDates.map(async (date) => {
|
|
8820
|
-
const dateFrom = date.firstDay.toString();
|
|
8821
|
-
const dateTo = date.lastDay.toString();
|
|
8822
|
-
const filter = {
|
|
8823
|
-
...lapisFilter,
|
|
8824
|
-
[`${lapisDateField}From`]: dateFrom,
|
|
8825
|
-
[`${lapisDateField}To`]: dateTo
|
|
8826
|
-
};
|
|
8827
|
-
const data2 = await fetchAndPrepareSubstitutionsOrDeletions(filter, sequenceType).evaluate(lapis, signal);
|
|
8828
|
-
const totalCountQuery = await getTotalNumberOfSequencesInDateRange(filter).evaluate(lapis, signal);
|
|
8829
|
-
return {
|
|
8830
|
-
date,
|
|
8831
|
-
mutations: data2.content,
|
|
8832
|
-
totalCount: totalCountQuery.content[0].count
|
|
8833
|
-
};
|
|
8834
|
-
});
|
|
8835
|
-
const data = await Promise.all(subQueries);
|
|
8836
|
-
return groupByMutation(data);
|
|
8837
|
-
}
|
|
8838
|
-
async function getDatesInDataset(lapisFilter, lapis, granularity, lapisDateField, signal) {
|
|
8839
|
-
const { content: availableDates } = await queryAvailableDates(
|
|
8840
|
-
lapisFilter,
|
|
8841
|
-
lapis,
|
|
8842
|
-
granularity,
|
|
8843
|
-
lapisDateField,
|
|
8844
|
-
signal
|
|
8845
|
-
);
|
|
8846
|
-
const { dateFrom, dateTo } = getDateRangeFromFilter(lapisFilter, lapisDateField, granularity);
|
|
8847
|
-
const { min, max } = getMinMaxTemporal(availableDates);
|
|
8848
|
-
return generateAllInRange(dateFrom ?? min, dateTo ?? max);
|
|
8849
|
-
}
|
|
8850
|
-
function getDateRangeFromFilter(lapisFilter, lapisDateField, granularity) {
|
|
8851
|
-
const valueFromFilter = lapisFilter[lapisDateField];
|
|
8852
|
-
if (valueFromFilter) {
|
|
8853
|
-
return {
|
|
8854
|
-
dateFrom: parseDateStringToTemporal(valueFromFilter, granularity),
|
|
8855
|
-
dateTo: parseDateStringToTemporal(valueFromFilter, granularity)
|
|
8856
|
-
};
|
|
8857
|
-
}
|
|
8858
|
-
const minFromFilter = lapisFilter[`${lapisDateField}From`];
|
|
8859
|
-
const maxFromFilter = lapisFilter[`${lapisDateField}To`];
|
|
8860
|
-
return {
|
|
8861
|
-
dateFrom: minFromFilter ? parseDateStringToTemporal(minFromFilter, granularity) : null,
|
|
8862
|
-
dateTo: maxFromFilter ? parseDateStringToTemporal(maxFromFilter, granularity) : null
|
|
8863
|
-
};
|
|
8854
|
+
function serializeSubstitutionOrDeletion(mutation) {
|
|
8855
|
+
return mutation.code;
|
|
8864
8856
|
}
|
|
8865
|
-
function
|
|
8866
|
-
return
|
|
8867
|
-
}
|
|
8868
|
-
function fetchAndPrepareDates(filter, granularity, lapisDateField) {
|
|
8869
|
-
const fetchData = new FetchAggregatedOperator(filter, [lapisDateField]);
|
|
8870
|
-
const dataWithFixedDateKey = new RenameFieldOperator(fetchData, lapisDateField, "date");
|
|
8871
|
-
const mapData = new MapOperator(dataWithFixedDateKey, (data) => mapDateToGranularityRange(data, granularity));
|
|
8872
|
-
const groupByData = new GroupByAndSumOperator(mapData, "dateRange", "count");
|
|
8873
|
-
const sortData = new SortOperator(groupByData, dateRangeCompare);
|
|
8874
|
-
return new MapOperator(sortData, (data) => data.dateRange);
|
|
8875
|
-
}
|
|
8876
|
-
function fetchAndPrepareSubstitutionsOrDeletions(filter, sequenceType) {
|
|
8877
|
-
return new FetchSubstitutionsOrDeletionsOperator(filter, sequenceType, 1e-3);
|
|
8878
|
-
}
|
|
8879
|
-
function groupByMutation(data) {
|
|
8880
|
-
const dataArray = new Map2dBase(
|
|
8881
|
-
(mutation) => mutation.code,
|
|
8882
|
-
(date) => date.toString()
|
|
8883
|
-
);
|
|
8884
|
-
data.forEach((mutationData) => {
|
|
8885
|
-
mutationData.mutations.forEach((mutationEntry) => {
|
|
8886
|
-
dataArray.set(mutationEntry.mutation, mutationData.date, {
|
|
8887
|
-
count: mutationEntry.count,
|
|
8888
|
-
proportion: mutationEntry.proportion,
|
|
8889
|
-
totalCount: mutationData.totalCount
|
|
8890
|
-
});
|
|
8891
|
-
});
|
|
8892
|
-
});
|
|
8893
|
-
addZeroValuesForDatesWithNoMutationData(dataArray, data);
|
|
8894
|
-
return dataArray;
|
|
8895
|
-
}
|
|
8896
|
-
function addZeroValuesForDatesWithNoMutationData(dataArray, data) {
|
|
8897
|
-
if (dataArray.getFirstAxisKeys().length !== 0) {
|
|
8898
|
-
const someMutation = dataArray.getFirstAxisKeys()[0];
|
|
8899
|
-
data.forEach((mutationData) => {
|
|
8900
|
-
if (mutationData.mutations.length === 0) {
|
|
8901
|
-
dataArray.set(someMutation, mutationData.date, { count: 0, proportion: 0, totalCount: 0 });
|
|
8902
|
-
}
|
|
8903
|
-
});
|
|
8904
|
-
}
|
|
8905
|
-
}
|
|
8906
|
-
function getTotalNumberOfSequencesInDateRange(filter) {
|
|
8907
|
-
return new FetchAggregatedOperator(filter);
|
|
8857
|
+
function serializeTemporal(date) {
|
|
8858
|
+
return date.dateString;
|
|
8908
8859
|
}
|
|
8909
8860
|
const ColorScaleSelectorDropdown = ({
|
|
8910
8861
|
colorScale,
|
|
@@ -8912,6 +8863,43 @@ const ColorScaleSelectorDropdown = ({
|
|
|
8912
8863
|
}) => {
|
|
8913
8864
|
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 }) }) });
|
|
8914
8865
|
};
|
|
8866
|
+
function useWebWorker(messageToWorker, worker) {
|
|
8867
|
+
const [data, setData] = h(void 0);
|
|
8868
|
+
const [error, setError] = h(void 0);
|
|
8869
|
+
const [isLoading, setIsLoading] = h(true);
|
|
8870
|
+
y(() => {
|
|
8871
|
+
worker.onmessage = (event) => {
|
|
8872
|
+
const { status, data: data2, error: error2 } = event.data;
|
|
8873
|
+
switch (status) {
|
|
8874
|
+
case "loading":
|
|
8875
|
+
setIsLoading(true);
|
|
8876
|
+
break;
|
|
8877
|
+
case "success":
|
|
8878
|
+
setData(data2);
|
|
8879
|
+
setError(void 0);
|
|
8880
|
+
setIsLoading(false);
|
|
8881
|
+
break;
|
|
8882
|
+
case "error":
|
|
8883
|
+
setError(error2);
|
|
8884
|
+
setIsLoading(false);
|
|
8885
|
+
break;
|
|
8886
|
+
default:
|
|
8887
|
+
throw new Error(`Unknown status: ${status}`);
|
|
8888
|
+
}
|
|
8889
|
+
};
|
|
8890
|
+
worker.onmessageerror = (event) => {
|
|
8891
|
+
setError(new Error(`Worker received a message that it cannot deserialize: ${event.data}`));
|
|
8892
|
+
setIsLoading(false);
|
|
8893
|
+
};
|
|
8894
|
+
return () => {
|
|
8895
|
+
worker.terminate();
|
|
8896
|
+
};
|
|
8897
|
+
}, []);
|
|
8898
|
+
T(() => {
|
|
8899
|
+
worker.postMessage(messageToWorker);
|
|
8900
|
+
}, [messageToWorker]);
|
|
8901
|
+
return { data, error, isLoading };
|
|
8902
|
+
}
|
|
8915
8903
|
const MutationsOverTime = ({ width, height, ...innerProps }) => {
|
|
8916
8904
|
const size = { height, width };
|
|
8917
8905
|
return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(MutationsOverTimeInner, { ...innerProps }) }) });
|
|
@@ -8924,27 +8912,36 @@ const MutationsOverTimeInner = ({
|
|
|
8924
8912
|
lapisDateField
|
|
8925
8913
|
}) => {
|
|
8926
8914
|
const lapis = x(LapisUrlContext);
|
|
8927
|
-
const { data, error, isLoading } =
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
|
|
8933
|
-
|
|
8915
|
+
const { data, error, isLoading } = useWebWorker(
|
|
8916
|
+
{
|
|
8917
|
+
lapisFilter,
|
|
8918
|
+
sequenceType,
|
|
8919
|
+
granularity,
|
|
8920
|
+
lapisDateField,
|
|
8921
|
+
lapis
|
|
8922
|
+
},
|
|
8923
|
+
new WorkerWrapper()
|
|
8924
|
+
);
|
|
8934
8925
|
if (isLoading) {
|
|
8935
8926
|
return /* @__PURE__ */ u$1(LoadingDisplay, {});
|
|
8936
8927
|
}
|
|
8937
|
-
if (error !==
|
|
8928
|
+
if (error !== void 0) {
|
|
8938
8929
|
return /* @__PURE__ */ u$1(ErrorDisplay, { error });
|
|
8939
8930
|
}
|
|
8940
|
-
if (data === null) {
|
|
8931
|
+
if (data === null || data === void 0) {
|
|
8941
8932
|
return /* @__PURE__ */ u$1(NoDataDisplay, {});
|
|
8942
8933
|
}
|
|
8934
|
+
const { overallMutationData, mutationOverTimeSerialized } = data;
|
|
8935
|
+
const mutationOverTimeData = new Map2dBase(
|
|
8936
|
+
serializeSubstitutionOrDeletion,
|
|
8937
|
+
serializeTemporal,
|
|
8938
|
+
mutationOverTimeSerialized
|
|
8939
|
+
);
|
|
8943
8940
|
return /* @__PURE__ */ u$1(
|
|
8944
8941
|
MutationsOverTimeTabs,
|
|
8945
8942
|
{
|
|
8946
|
-
overallMutationData
|
|
8947
|
-
mutationOverTimeData
|
|
8943
|
+
overallMutationData,
|
|
8944
|
+
mutationOverTimeData,
|
|
8948
8945
|
sequenceType,
|
|
8949
8946
|
views
|
|
8950
8947
|
}
|
|
@@ -8963,17 +8960,22 @@ const MutationsOverTimeTabs = ({
|
|
|
8963
8960
|
{ label: "Substitutions", checked: true, type: "substitution" },
|
|
8964
8961
|
{ label: "Deletions", checked: true, type: "deletion" }
|
|
8965
8962
|
]);
|
|
8966
|
-
const filteredData = T(
|
|
8967
|
-
|
|
8963
|
+
const filteredData = T(() => {
|
|
8964
|
+
return getFilteredMutationOverTimeData(
|
|
8968
8965
|
mutationOverTimeData,
|
|
8969
8966
|
overallMutationData,
|
|
8970
8967
|
displayedSegments,
|
|
8971
8968
|
displayedMutationTypes,
|
|
8972
8969
|
proportionInterval
|
|
8973
|
-
)
|
|
8974
|
-
|
|
8975
|
-
);
|
|
8970
|
+
);
|
|
8971
|
+
}, [mutationOverTimeData, overallMutationData, displayedSegments, displayedMutationTypes, proportionInterval]);
|
|
8976
8972
|
const getTab = (view) => {
|
|
8973
|
+
if (filteredData === void 0) {
|
|
8974
|
+
return {
|
|
8975
|
+
title: "Calculating",
|
|
8976
|
+
content: /* @__PURE__ */ u$1(LoadingDisplay, {})
|
|
8977
|
+
};
|
|
8978
|
+
}
|
|
8977
8979
|
switch (view) {
|
|
8978
8980
|
case "grid":
|
|
8979
8981
|
return {
|
|
@@ -9044,18 +9046,18 @@ const Toolbar = ({
|
|
|
9044
9046
|
] });
|
|
9045
9047
|
};
|
|
9046
9048
|
function getDownloadData(filteredData) {
|
|
9047
|
-
const dates = filteredData.getSecondAxisKeys().
|
|
9048
|
-
return filteredData.getFirstAxisKeys().
|
|
9049
|
+
const dates = filteredData.getSecondAxisKeys().map((date) => toTemporalClass(date));
|
|
9050
|
+
return filteredData.getFirstAxisKeys().map((mutation) => {
|
|
9049
9051
|
return dates.reduce(
|
|
9050
9052
|
(accumulated, date) => {
|
|
9051
9053
|
var _a;
|
|
9052
9054
|
const proportion = ((_a = filteredData.get(mutation, date)) == null ? void 0 : _a.proportion) ?? 0;
|
|
9053
9055
|
return {
|
|
9054
9056
|
...accumulated,
|
|
9055
|
-
[date.
|
|
9057
|
+
[date.dateString]: proportion
|
|
9056
9058
|
};
|
|
9057
9059
|
},
|
|
9058
|
-
{ mutation: mutation.
|
|
9060
|
+
{ mutation: mutation.code }
|
|
9059
9061
|
);
|
|
9060
9062
|
});
|
|
9061
9063
|
}
|
|
@@ -9923,7 +9925,7 @@ const sequenceTypeFromSegment = (possibleSegment, referenceGenome) => {
|
|
|
9923
9925
|
return void 0;
|
|
9924
9926
|
};
|
|
9925
9927
|
const parseAndValidateMutation = (value, referenceGenome) => {
|
|
9926
|
-
const possibleInsertion =
|
|
9928
|
+
const possibleInsertion = InsertionClass.parse(value);
|
|
9927
9929
|
if (possibleInsertion !== null) {
|
|
9928
9930
|
const sequenceType = sequenceTypeFromSegment(possibleInsertion.segment, referenceGenome);
|
|
9929
9931
|
switch (sequenceType) {
|
|
@@ -9935,7 +9937,7 @@ const parseAndValidateMutation = (value, referenceGenome) => {
|
|
|
9935
9937
|
return null;
|
|
9936
9938
|
}
|
|
9937
9939
|
}
|
|
9938
|
-
const possibleDeletion =
|
|
9940
|
+
const possibleDeletion = DeletionClass.parse(value);
|
|
9939
9941
|
if (possibleDeletion !== null) {
|
|
9940
9942
|
const sequenceType = sequenceTypeFromSegment(possibleDeletion.segment, referenceGenome);
|
|
9941
9943
|
switch (sequenceType) {
|
|
@@ -9947,7 +9949,7 @@ const parseAndValidateMutation = (value, referenceGenome) => {
|
|
|
9947
9949
|
return null;
|
|
9948
9950
|
}
|
|
9949
9951
|
}
|
|
9950
|
-
const possibleSubstitution =
|
|
9952
|
+
const possibleSubstitution = SubstitutionClass.parse(value);
|
|
9951
9953
|
if (possibleSubstitution !== null) {
|
|
9952
9954
|
const sequenceType = sequenceTypeFromSegment(possibleSubstitution.segment, referenceGenome);
|
|
9953
9955
|
switch (sequenceType) {
|