jderobot-ide-interface 0.3.17 → 0.3.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/dist/a5a14e7d119e89dea736.wasm +0 -0
- package/dist/components/Button/Button.styles.d.ts +3 -1
- package/dist/components/ButtonsContainer/ButtonsContainer.styles.d.ts +6 -2
- package/dist/components/Dropdown/Dropdown.styles.d.ts +3 -1
- package/dist/components/Explorer/Explorer.styles.d.ts +9 -3
- package/dist/components/Explorer/file_explorer/FileExplorer.styles.d.ts +3 -1
- package/dist/components/Explorer/file_explorer/MoreActionsMenu.styles.d.ts +12 -4
- package/dist/components/Explorer/file_explorer/TreeNode.styles.d.ts +18 -6
- package/dist/components/FileEditor/FileEditor.d.ts +2 -1
- package/dist/components/FileEditor/FileEditor.styles.d.ts +9 -3
- package/dist/components/FileEditor/IdeInterface.stories.d.ts +5 -0
- package/dist/components/FileEditor/TextEditor.d.ts +2 -1
- package/dist/components/FileEditor/lsp-client.d.ts +1 -0
- package/dist/components/IdeInterface/IdeInterface.d.ts +2 -1
- package/dist/components/IdeInterface/IdeInterface.stories.d.ts +1 -1
- package/dist/components/IdeInterface/IdeInterface.styles.d.ts +67 -1228
- package/dist/components/IdeInterface/TheoryInterface.styles.d.ts +21 -7
- package/dist/components/Modals/EditorKeybindModal.styles.d.ts +3 -1
- package/dist/components/Modals/ErrorModal.styles.d.ts +9 -3
- package/dist/components/Modals/Modal.styles.d.ts +68 -25
- package/dist/components/ProgressBar/ProgressBar.style.d.ts +3 -1
- package/dist/components/StatusBar/StatusBar.style.d.ts +9 -3
- package/dist/components/Theory/Canvas.styles.d.ts +3 -1
- package/dist/components/Theory/CarouselDisplay.styles.d.ts +39 -13
- package/dist/components/Theory/Code.styles.d.ts +3 -1
- package/dist/components/Theory/FormulaSection.styles.d.ts +3 -1
- package/dist/components/Theory/HighlightedSection.styles.d.ts +3 -1
- package/dist/components/Theory/Image.styles.d.ts +3 -1
- package/dist/components/Theory/ImageRow.styles.d.ts +3 -1
- package/dist/components/Theory/Link.styles.d.ts +3 -1
- package/dist/components/Theory/List.styles.d.ts +3 -1
- package/dist/components/Theory/LocalVideo.styles.d.ts +3 -1
- package/dist/components/Theory/NumberedList.styles.d.ts +3 -1
- package/dist/components/Theory/Section.styles.d.ts +6 -2
- package/dist/components/Theory/Subsection.styles.d.ts +6 -2
- package/dist/components/Theory/Subsubsection.styles.d.ts +6 -2
- package/dist/components/Theory/Timeline.styles.d.ts +24 -8
- package/dist/components/Theory/TimelineComparison.styles.d.ts +15 -5
- package/dist/components/Theory/YoutubeVideo.styles.d.ts +1 -1
- package/dist/components/VncViewer/VncViewer.styles.d.ts +12 -4
- package/dist/d94e0a7c7ed2cbcaeba4.html +123 -0
- package/dist/main.js +4071 -1890
- package/dist/node_fs_promises.main.js +13 -0
- package/dist/node_modules_vscode_diff_dist_worker_js_esm.main.js +397 -0
- package/dist/package.json +1 -1
- package/dist/vendors-node_modules_jschardet_index_js.main.js +8224 -0
- package/dist/vendors-node_modules_vscode_diff_dist_index_js.main.js +626 -0
- package/dist/vendors-node_modules_vscode_diff_dist_wire_js.main.js +2233 -0
- package/dist/vendors-node_modules_vscode_iconv-lite-umd_lib_iconv-lite-umd_js.main.js +18 -0
- package/package.json +1 -1
|
@@ -0,0 +1,2233 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(this["webpackChunkjderobot_ide_interface"] = this["webpackChunkjderobot_ide_interface"] || []).push([["vendors-node_modules_vscode_diff_dist_wire_js"],{
|
|
3
|
+
|
|
4
|
+
/***/ "./node_modules/@vscode/diff/dist/diff_wasm_bg-c6YkaZRL.wasm"
|
|
5
|
+
/*!*******************************************************************!*\
|
|
6
|
+
!*** ./node_modules/@vscode/diff/dist/diff_wasm_bg-c6YkaZRL.wasm ***!
|
|
7
|
+
\*******************************************************************/
|
|
8
|
+
(module, __unused_webpack_exports, __webpack_require__) {
|
|
9
|
+
|
|
10
|
+
module.exports = __webpack_require__.p + "a5a14e7d119e89dea736.wasm";
|
|
11
|
+
|
|
12
|
+
/***/ },
|
|
13
|
+
|
|
14
|
+
/***/ "./node_modules/@vscode/diff/dist/wire.js"
|
|
15
|
+
/*!************************************************!*\
|
|
16
|
+
!*** ./node_modules/@vscode/diff/dist/wire.js ***!
|
|
17
|
+
\************************************************/
|
|
18
|
+
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
19
|
+
|
|
20
|
+
__webpack_require__.r(__webpack_exports__);
|
|
21
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
22
|
+
/* harmony export */ D: () => (/* binding */ DefaultLinesDiffComputer),
|
|
23
|
+
/* harmony export */ L: () => (/* binding */ LineRange),
|
|
24
|
+
/* harmony export */ O: () => (/* binding */ OffsetRange),
|
|
25
|
+
/* harmony export */ R: () => (/* binding */ RangeMapping),
|
|
26
|
+
/* harmony export */ a: () => (/* binding */ Range),
|
|
27
|
+
/* harmony export */ b: () => (/* binding */ DetailedLineRangeMapping),
|
|
28
|
+
/* harmony export */ c: () => (/* binding */ LinesDiff),
|
|
29
|
+
/* harmony export */ d: () => (/* binding */ LineRangeMapping),
|
|
30
|
+
/* harmony export */ g: () => (/* binding */ getWasm),
|
|
31
|
+
/* harmony export */ i: () => (/* binding */ initWasm),
|
|
32
|
+
/* harmony export */ l: () => (/* binding */ linesDiffToWire),
|
|
33
|
+
/* harmony export */ w: () => (/* binding */ wireToLinesDiff)
|
|
34
|
+
/* harmony export */ });
|
|
35
|
+
/*---------------------------------------------------------------------------------------------
|
|
36
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
37
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
38
|
+
*--------------------------------------------------------------------------------------------*/
|
|
39
|
+
/**
|
|
40
|
+
* A range of offsets (0-based).
|
|
41
|
+
*/
|
|
42
|
+
class OffsetRange {
|
|
43
|
+
start;
|
|
44
|
+
endExclusive;
|
|
45
|
+
static ofLength(length) {
|
|
46
|
+
return new OffsetRange(0, length);
|
|
47
|
+
}
|
|
48
|
+
static ofStartAndLength(start, length) {
|
|
49
|
+
return new OffsetRange(start, start + length);
|
|
50
|
+
}
|
|
51
|
+
constructor(start, endExclusive) {
|
|
52
|
+
this.start = start;
|
|
53
|
+
this.endExclusive = endExclusive;
|
|
54
|
+
if (start > endExclusive) {
|
|
55
|
+
throw new Error(`Invalid range: [${start}, ${endExclusive})`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
get isEmpty() {
|
|
59
|
+
return this.start === this.endExclusive;
|
|
60
|
+
}
|
|
61
|
+
get length() {
|
|
62
|
+
return this.endExclusive - this.start;
|
|
63
|
+
}
|
|
64
|
+
delta(offset) {
|
|
65
|
+
return new OffsetRange(this.start + offset, this.endExclusive + offset);
|
|
66
|
+
}
|
|
67
|
+
deltaStart(offset) {
|
|
68
|
+
return new OffsetRange(this.start + offset, this.endExclusive);
|
|
69
|
+
}
|
|
70
|
+
deltaEnd(offset) {
|
|
71
|
+
return new OffsetRange(this.start, this.endExclusive + offset);
|
|
72
|
+
}
|
|
73
|
+
equals(other) {
|
|
74
|
+
return this.start === other.start && this.endExclusive === other.endExclusive;
|
|
75
|
+
}
|
|
76
|
+
containsRange(other) {
|
|
77
|
+
return this.start <= other.start && other.endExclusive <= this.endExclusive;
|
|
78
|
+
}
|
|
79
|
+
contains(offset) {
|
|
80
|
+
return this.start <= offset && offset < this.endExclusive;
|
|
81
|
+
}
|
|
82
|
+
join(other) {
|
|
83
|
+
return new OffsetRange(Math.min(this.start, other.start), Math.max(this.endExclusive, other.endExclusive));
|
|
84
|
+
}
|
|
85
|
+
intersect(other) {
|
|
86
|
+
const start = Math.max(this.start, other.start);
|
|
87
|
+
const end = Math.min(this.endExclusive, other.endExclusive);
|
|
88
|
+
if (start <= end) {
|
|
89
|
+
return new OffsetRange(start, end);
|
|
90
|
+
}
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
intersects(other) {
|
|
94
|
+
const start = Math.max(this.start, other.start);
|
|
95
|
+
const end = Math.min(this.endExclusive, other.endExclusive);
|
|
96
|
+
return start < end;
|
|
97
|
+
}
|
|
98
|
+
intersectsOrTouches(other) {
|
|
99
|
+
const start = Math.max(this.start, other.start);
|
|
100
|
+
const end = Math.min(this.endExclusive, other.endExclusive);
|
|
101
|
+
return start <= end;
|
|
102
|
+
}
|
|
103
|
+
slice(arr) {
|
|
104
|
+
return arr.slice(this.start, this.endExclusive);
|
|
105
|
+
}
|
|
106
|
+
toString() {
|
|
107
|
+
return `[${this.start}, ${this.endExclusive})`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
class InfiniteTimeout {
|
|
112
|
+
static instance = new InfiniteTimeout();
|
|
113
|
+
isValid() {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
class DateTimeout {
|
|
118
|
+
timeout;
|
|
119
|
+
startTime = Date.now();
|
|
120
|
+
valid = true;
|
|
121
|
+
constructor(timeout) {
|
|
122
|
+
this.timeout = timeout;
|
|
123
|
+
if (timeout <= 0) {
|
|
124
|
+
throw new Error('timeout must be positive');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
isValid() {
|
|
128
|
+
const valid = Date.now() - this.startTime < this.timeout;
|
|
129
|
+
if (!valid && this.valid) {
|
|
130
|
+
this.valid = false;
|
|
131
|
+
}
|
|
132
|
+
return this.valid;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Represents an offset pair for two sequences.
|
|
137
|
+
*/
|
|
138
|
+
class OffsetPair {
|
|
139
|
+
offset1;
|
|
140
|
+
offset2;
|
|
141
|
+
static zero = new OffsetPair(0, 0);
|
|
142
|
+
static max = new OffsetPair(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
|
143
|
+
constructor(offset1, offset2) {
|
|
144
|
+
this.offset1 = offset1;
|
|
145
|
+
this.offset2 = offset2;
|
|
146
|
+
}
|
|
147
|
+
toString() {
|
|
148
|
+
return `${this.offset1} <-> ${this.offset2}`;
|
|
149
|
+
}
|
|
150
|
+
delta(offset) {
|
|
151
|
+
if (offset === 0) {
|
|
152
|
+
return this;
|
|
153
|
+
}
|
|
154
|
+
return new OffsetPair(this.offset1 + offset, this.offset2 + offset);
|
|
155
|
+
}
|
|
156
|
+
equals(other) {
|
|
157
|
+
return this.offset1 === other.offset1 && this.offset2 === other.offset2;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Represents a diff between two sequences.
|
|
162
|
+
*/
|
|
163
|
+
class SequenceDiff {
|
|
164
|
+
seq1Range;
|
|
165
|
+
seq2Range;
|
|
166
|
+
static invert(sequenceDiffs, doc1Length) {
|
|
167
|
+
const result = [];
|
|
168
|
+
forEachAdjacent(sequenceDiffs, (a, b) => {
|
|
169
|
+
result.push(SequenceDiff.fromOffsetPairs(a ? a.getEndExclusives() : OffsetPair.zero, b ? b.getStarts() : new OffsetPair(doc1Length, (a ? a.seq2Range.endExclusive - a.seq1Range.endExclusive : 0) + doc1Length)));
|
|
170
|
+
});
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
static fromOffsetPairs(start, endExclusive) {
|
|
174
|
+
return new SequenceDiff(new OffsetRange(start.offset1, endExclusive.offset1), new OffsetRange(start.offset2, endExclusive.offset2));
|
|
175
|
+
}
|
|
176
|
+
static assertSorted(sequenceDiffs) {
|
|
177
|
+
let last = undefined;
|
|
178
|
+
for (const cur of sequenceDiffs) {
|
|
179
|
+
if (last) {
|
|
180
|
+
if (!(last.seq1Range.endExclusive <= cur.seq1Range.start && last.seq2Range.endExclusive <= cur.seq2Range.start)) {
|
|
181
|
+
throw new Error('Sequence diffs must be sorted');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
last = cur;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
constructor(seq1Range, seq2Range) {
|
|
188
|
+
this.seq1Range = seq1Range;
|
|
189
|
+
this.seq2Range = seq2Range;
|
|
190
|
+
}
|
|
191
|
+
swap() {
|
|
192
|
+
return new SequenceDiff(this.seq2Range, this.seq1Range);
|
|
193
|
+
}
|
|
194
|
+
toString() {
|
|
195
|
+
return `${this.seq1Range} <-> ${this.seq2Range}`;
|
|
196
|
+
}
|
|
197
|
+
join(other) {
|
|
198
|
+
return new SequenceDiff(this.seq1Range.join(other.seq1Range), this.seq2Range.join(other.seq2Range));
|
|
199
|
+
}
|
|
200
|
+
delta(offset) {
|
|
201
|
+
if (offset === 0) {
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
return new SequenceDiff(this.seq1Range.delta(offset), this.seq2Range.delta(offset));
|
|
205
|
+
}
|
|
206
|
+
deltaStart(offset) {
|
|
207
|
+
if (offset === 0) {
|
|
208
|
+
return this;
|
|
209
|
+
}
|
|
210
|
+
return new SequenceDiff(this.seq1Range.deltaStart(offset), this.seq2Range.deltaStart(offset));
|
|
211
|
+
}
|
|
212
|
+
deltaEnd(offset) {
|
|
213
|
+
if (offset === 0) {
|
|
214
|
+
return this;
|
|
215
|
+
}
|
|
216
|
+
return new SequenceDiff(this.seq1Range.deltaEnd(offset), this.seq2Range.deltaEnd(offset));
|
|
217
|
+
}
|
|
218
|
+
intersectsOrTouches(other) {
|
|
219
|
+
return this.seq1Range.intersectsOrTouches(other.seq1Range) || this.seq2Range.intersectsOrTouches(other.seq2Range);
|
|
220
|
+
}
|
|
221
|
+
intersect(other) {
|
|
222
|
+
const i1 = this.seq1Range.intersect(other.seq1Range);
|
|
223
|
+
const i2 = this.seq2Range.intersect(other.seq2Range);
|
|
224
|
+
if (!i1 || !i2) {
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
return new SequenceDiff(i1, i2);
|
|
228
|
+
}
|
|
229
|
+
getStarts() {
|
|
230
|
+
return new OffsetPair(this.seq1Range.start, this.seq2Range.start);
|
|
231
|
+
}
|
|
232
|
+
getEndExclusives() {
|
|
233
|
+
return new OffsetPair(this.seq1Range.endExclusive, this.seq2Range.endExclusive);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Result of a diff algorithm computation.
|
|
238
|
+
*/
|
|
239
|
+
class DiffAlgorithmResult {
|
|
240
|
+
diffs;
|
|
241
|
+
hitTimeout;
|
|
242
|
+
static trivial(seq1, seq2) {
|
|
243
|
+
return new DiffAlgorithmResult([new SequenceDiff(OffsetRange.ofLength(seq1.length), OffsetRange.ofLength(seq2.length))], false);
|
|
244
|
+
}
|
|
245
|
+
static trivialTimedOut(seq1, seq2) {
|
|
246
|
+
return new DiffAlgorithmResult([new SequenceDiff(OffsetRange.ofLength(seq1.length), OffsetRange.ofLength(seq2.length))], true);
|
|
247
|
+
}
|
|
248
|
+
constructor(diffs, hitTimeout) {
|
|
249
|
+
this.diffs = diffs;
|
|
250
|
+
this.hitTimeout = hitTimeout;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Helper function for iterating with neighbors
|
|
254
|
+
function forEachAdjacent(items, callback) {
|
|
255
|
+
let prev = undefined;
|
|
256
|
+
for (const item of items) {
|
|
257
|
+
callback(prev, item);
|
|
258
|
+
prev = item;
|
|
259
|
+
}
|
|
260
|
+
callback(prev, undefined);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* A 2D array implementation.
|
|
265
|
+
*/
|
|
266
|
+
class Array2D {
|
|
267
|
+
width;
|
|
268
|
+
height;
|
|
269
|
+
array = [];
|
|
270
|
+
constructor(width, height) {
|
|
271
|
+
this.width = width;
|
|
272
|
+
this.height = height;
|
|
273
|
+
this.array = new Array(width * height);
|
|
274
|
+
}
|
|
275
|
+
get(x, y) {
|
|
276
|
+
return this.array[x + y * this.width];
|
|
277
|
+
}
|
|
278
|
+
set(x, y, value) {
|
|
279
|
+
this.array[x + y * this.width] = value;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* A O(MN) diffing algorithm that supports a score function.
|
|
284
|
+
* The algorithm can be improved by processing the 2d array diagonally.
|
|
285
|
+
*/
|
|
286
|
+
class DynamicProgrammingDiffing {
|
|
287
|
+
compute(sequence1, sequence2, timeout = InfiniteTimeout.instance, equalityScore) {
|
|
288
|
+
if (sequence1.length === 0 || sequence2.length === 0) {
|
|
289
|
+
return DiffAlgorithmResult.trivial(sequence1, sequence2);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* lcsLengths.get(i, j): Length of the longest common subsequence of
|
|
293
|
+
* sequence1.substring(0, i + 1) and sequence2.substring(0, j + 1).
|
|
294
|
+
*/
|
|
295
|
+
const lcsLengths = new Array2D(sequence1.length, sequence2.length);
|
|
296
|
+
const directions = new Array2D(sequence1.length, sequence2.length);
|
|
297
|
+
const lengths = new Array2D(sequence1.length, sequence2.length);
|
|
298
|
+
// Initialize lcsLengths
|
|
299
|
+
for (let s1 = 0; s1 < sequence1.length; s1++) {
|
|
300
|
+
for (let s2 = 0; s2 < sequence2.length; s2++) {
|
|
301
|
+
if (!timeout.isValid()) {
|
|
302
|
+
return DiffAlgorithmResult.trivialTimedOut(sequence1, sequence2);
|
|
303
|
+
}
|
|
304
|
+
const horizontalLen = s1 === 0 ? 0 : lcsLengths.get(s1 - 1, s2);
|
|
305
|
+
const verticalLen = s2 === 0 ? 0 : lcsLengths.get(s1, s2 - 1);
|
|
306
|
+
let extendedSeqScore;
|
|
307
|
+
if (sequence1.getElement(s1) === sequence2.getElement(s2)) {
|
|
308
|
+
if (s1 === 0 || s2 === 0) {
|
|
309
|
+
extendedSeqScore = 0;
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
extendedSeqScore = lcsLengths.get(s1 - 1, s2 - 1);
|
|
313
|
+
}
|
|
314
|
+
if (s1 > 0 && s2 > 0 && directions.get(s1 - 1, s2 - 1) === 3) {
|
|
315
|
+
// Prefer consecutive diagonals
|
|
316
|
+
extendedSeqScore += lengths.get(s1 - 1, s2 - 1);
|
|
317
|
+
}
|
|
318
|
+
extendedSeqScore += (equalityScore ? equalityScore(s1, s2) : 1);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
extendedSeqScore = -1;
|
|
322
|
+
}
|
|
323
|
+
const newValue = Math.max(horizontalLen, verticalLen, extendedSeqScore);
|
|
324
|
+
if (newValue === extendedSeqScore) {
|
|
325
|
+
// Prefer diagonals
|
|
326
|
+
const prevLen = s1 > 0 && s2 > 0 ? lengths.get(s1 - 1, s2 - 1) : 0;
|
|
327
|
+
lengths.set(s1, s2, prevLen + 1);
|
|
328
|
+
directions.set(s1, s2, 3);
|
|
329
|
+
}
|
|
330
|
+
else if (newValue === horizontalLen) {
|
|
331
|
+
lengths.set(s1, s2, 0);
|
|
332
|
+
directions.set(s1, s2, 1);
|
|
333
|
+
}
|
|
334
|
+
else if (newValue === verticalLen) {
|
|
335
|
+
lengths.set(s1, s2, 0);
|
|
336
|
+
directions.set(s1, s2, 2);
|
|
337
|
+
}
|
|
338
|
+
lcsLengths.set(s1, s2, newValue);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
// Backtracking
|
|
342
|
+
const result = [];
|
|
343
|
+
let lastAligningPosS1 = sequence1.length;
|
|
344
|
+
let lastAligningPosS2 = sequence2.length;
|
|
345
|
+
function reportDecreasingAligningPositions(s1, s2) {
|
|
346
|
+
if (s1 + 1 !== lastAligningPosS1 || s2 + 1 !== lastAligningPosS2) {
|
|
347
|
+
result.push(new SequenceDiff(new OffsetRange(s1 + 1, lastAligningPosS1), new OffsetRange(s2 + 1, lastAligningPosS2)));
|
|
348
|
+
}
|
|
349
|
+
lastAligningPosS1 = s1;
|
|
350
|
+
lastAligningPosS2 = s2;
|
|
351
|
+
}
|
|
352
|
+
let s1 = sequence1.length - 1;
|
|
353
|
+
let s2 = sequence2.length - 1;
|
|
354
|
+
while (s1 >= 0 && s2 >= 0) {
|
|
355
|
+
if (directions.get(s1, s2) === 3) {
|
|
356
|
+
reportDecreasingAligningPositions(s1, s2);
|
|
357
|
+
s1--;
|
|
358
|
+
s2--;
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
if (directions.get(s1, s2) === 1) {
|
|
362
|
+
s1--;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
s2--;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
reportDecreasingAligningPositions(-1, -1);
|
|
370
|
+
result.reverse();
|
|
371
|
+
return new DiffAlgorithmResult(result, false);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* An O(ND) diff algorithm that has a quadratic space worst-case complexity.
|
|
377
|
+
*/
|
|
378
|
+
class MyersDiffAlgorithm {
|
|
379
|
+
compute(seq1, seq2, timeout = InfiniteTimeout.instance) {
|
|
380
|
+
// Common special cases - early return improves performance dramatically
|
|
381
|
+
if (seq1.length === 0 || seq2.length === 0) {
|
|
382
|
+
return DiffAlgorithmResult.trivial(seq1, seq2);
|
|
383
|
+
}
|
|
384
|
+
const seqX = seq1; // Text on the x axis
|
|
385
|
+
const seqY = seq2; // Text on the y axis
|
|
386
|
+
function getXAfterSnake(x, y) {
|
|
387
|
+
while (x < seqX.length && y < seqY.length && seqX.getElement(x) === seqY.getElement(y)) {
|
|
388
|
+
x++;
|
|
389
|
+
y++;
|
|
390
|
+
}
|
|
391
|
+
return x;
|
|
392
|
+
}
|
|
393
|
+
let d = 0;
|
|
394
|
+
// V[k]: X value of longest d-line that ends in diagonal k.
|
|
395
|
+
// d-line: path from (0,0) to (x,y) that uses exactly d non-diagonals.
|
|
396
|
+
// diagonal k: Set of points (x,y) with x-y = k.
|
|
397
|
+
const V = new FastInt32Array();
|
|
398
|
+
V.set(0, getXAfterSnake(0, 0));
|
|
399
|
+
const paths = new FastArrayNegativeIndices();
|
|
400
|
+
paths.set(0, V.get(0) === 0 ? null : new SnakePath(null, 0, 0, V.get(0)));
|
|
401
|
+
let k = 0;
|
|
402
|
+
loop: while (true) {
|
|
403
|
+
d++;
|
|
404
|
+
if (!timeout.isValid()) {
|
|
405
|
+
return DiffAlgorithmResult.trivialTimedOut(seqX, seqY);
|
|
406
|
+
}
|
|
407
|
+
// The paper has `for (k = -d; k <= d; k += 2)`, but we can ignore diagonals that cannot influence the result.
|
|
408
|
+
const lowerBound = -Math.min(d, seqY.length + (d % 2));
|
|
409
|
+
const upperBound = Math.min(d, seqX.length + (d % 2));
|
|
410
|
+
for (k = lowerBound; k <= upperBound; k += 2) {
|
|
411
|
+
// We can use the X values of (d-1)-lines to compute X value of the longest d-lines.
|
|
412
|
+
const maxXofDLineTop = k === upperBound ? -1 : V.get(k + 1); // Vertical non-diagonal (add symbol in seqX)
|
|
413
|
+
const maxXofDLineLeft = k === lowerBound ? -1 : V.get(k - 1) + 1; // Horizontal non-diagonal (delete symbol in seqX)
|
|
414
|
+
const x = Math.min(Math.max(maxXofDLineTop, maxXofDLineLeft), seqX.length);
|
|
415
|
+
const y = x - k;
|
|
416
|
+
if (x > seqX.length || y > seqY.length) {
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
const newMaxX = getXAfterSnake(x, y);
|
|
420
|
+
V.set(k, newMaxX);
|
|
421
|
+
const lastPath = x === maxXofDLineTop ? paths.get(k + 1) : paths.get(k - 1);
|
|
422
|
+
paths.set(k, newMaxX !== x ? new SnakePath(lastPath, x, y, newMaxX - x) : lastPath);
|
|
423
|
+
if (V.get(k) === seqX.length && V.get(k) - k === seqY.length) {
|
|
424
|
+
break loop;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
let path = paths.get(k);
|
|
429
|
+
const result = [];
|
|
430
|
+
let lastAligningPosS1 = seqX.length;
|
|
431
|
+
let lastAligningPosS2 = seqY.length;
|
|
432
|
+
while (true) {
|
|
433
|
+
const endX = path ? path.x + path.length : 0;
|
|
434
|
+
const endY = path ? path.y + path.length : 0;
|
|
435
|
+
if (endX !== lastAligningPosS1 || endY !== lastAligningPosS2) {
|
|
436
|
+
result.push(new SequenceDiff(new OffsetRange(endX, lastAligningPosS1), new OffsetRange(endY, lastAligningPosS2)));
|
|
437
|
+
}
|
|
438
|
+
if (!path) {
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
lastAligningPosS1 = path.x;
|
|
442
|
+
lastAligningPosS2 = path.y;
|
|
443
|
+
path = path.prev;
|
|
444
|
+
}
|
|
445
|
+
result.reverse();
|
|
446
|
+
return new DiffAlgorithmResult(result, false);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
class SnakePath {
|
|
450
|
+
prev;
|
|
451
|
+
x;
|
|
452
|
+
y;
|
|
453
|
+
length;
|
|
454
|
+
constructor(prev, x, y, length) {
|
|
455
|
+
this.prev = prev;
|
|
456
|
+
this.x = x;
|
|
457
|
+
this.y = y;
|
|
458
|
+
this.length = length;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* An array that supports fast negative indices.
|
|
463
|
+
*/
|
|
464
|
+
class FastInt32Array {
|
|
465
|
+
positiveArr = new Int32Array(10);
|
|
466
|
+
negativeArr = new Int32Array(10);
|
|
467
|
+
get(idx) {
|
|
468
|
+
if (idx < 0) {
|
|
469
|
+
idx = -idx - 1;
|
|
470
|
+
return this.negativeArr[idx];
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
return this.positiveArr[idx];
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
set(idx, value) {
|
|
477
|
+
if (idx < 0) {
|
|
478
|
+
idx = -idx - 1;
|
|
479
|
+
if (idx >= this.negativeArr.length) {
|
|
480
|
+
const arr = this.negativeArr;
|
|
481
|
+
this.negativeArr = new Int32Array(arr.length * 2);
|
|
482
|
+
this.negativeArr.set(arr);
|
|
483
|
+
}
|
|
484
|
+
this.negativeArr[idx] = value;
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
if (idx >= this.positiveArr.length) {
|
|
488
|
+
const arr = this.positiveArr;
|
|
489
|
+
this.positiveArr = new Int32Array(arr.length * 2);
|
|
490
|
+
this.positiveArr.set(arr);
|
|
491
|
+
}
|
|
492
|
+
this.positiveArr[idx] = value;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* An array that supports fast negative indices for objects.
|
|
498
|
+
*/
|
|
499
|
+
class FastArrayNegativeIndices {
|
|
500
|
+
positiveArr = [];
|
|
501
|
+
negativeArr = [];
|
|
502
|
+
get(idx) {
|
|
503
|
+
if (idx < 0) {
|
|
504
|
+
idx = -idx - 1;
|
|
505
|
+
return this.negativeArr[idx];
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
return this.positiveArr[idx];
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
set(idx, value) {
|
|
512
|
+
if (idx < 0) {
|
|
513
|
+
idx = -idx - 1;
|
|
514
|
+
this.negativeArr[idx] = value;
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
this.positiveArr[idx] = value;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function optimizeSequenceDiffs(sequence1, sequence2, sequenceDiffs) {
|
|
523
|
+
let result = sequenceDiffs;
|
|
524
|
+
result = joinSequenceDiffsByShifting(sequence1, sequence2, result);
|
|
525
|
+
// Sometimes, calling this function twice improves the result.
|
|
526
|
+
result = joinSequenceDiffsByShifting(sequence1, sequence2, result);
|
|
527
|
+
result = shiftSequenceDiffs(sequence1, sequence2, result);
|
|
528
|
+
return result;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* This function fixes issues like this:
|
|
532
|
+
* ```
|
|
533
|
+
* import { Baz, Bar } from "foo";
|
|
534
|
+
* ```
|
|
535
|
+
* <->
|
|
536
|
+
* ```
|
|
537
|
+
* import { Baz, Bar, Foo } from "foo";
|
|
538
|
+
* ```
|
|
539
|
+
* Computed diff: [ {Add "," after Bar}, {Add "Foo " after space} }
|
|
540
|
+
* Improved diff: [{Add ", Foo" after Bar}]
|
|
541
|
+
*/
|
|
542
|
+
function joinSequenceDiffsByShifting(sequence1, sequence2, sequenceDiffs) {
|
|
543
|
+
if (sequenceDiffs.length === 0) {
|
|
544
|
+
return sequenceDiffs;
|
|
545
|
+
}
|
|
546
|
+
const result = [];
|
|
547
|
+
result.push(sequenceDiffs[0]);
|
|
548
|
+
// First move them all to the left as much as possible and join them if possible
|
|
549
|
+
for (let i = 1; i < sequenceDiffs.length; i++) {
|
|
550
|
+
const prevResult = result[result.length - 1];
|
|
551
|
+
let cur = sequenceDiffs[i];
|
|
552
|
+
if (cur.seq1Range.isEmpty || cur.seq2Range.isEmpty) {
|
|
553
|
+
const length = cur.seq1Range.start - prevResult.seq1Range.endExclusive;
|
|
554
|
+
let d;
|
|
555
|
+
for (d = 1; d <= length; d++) {
|
|
556
|
+
if (sequence1.getElement(cur.seq1Range.start - d) !== sequence1.getElement(cur.seq1Range.endExclusive - d) ||
|
|
557
|
+
sequence2.getElement(cur.seq2Range.start - d) !== sequence2.getElement(cur.seq2Range.endExclusive - d)) {
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
d--;
|
|
562
|
+
if (d === length) {
|
|
563
|
+
// Merge previous and current diff
|
|
564
|
+
result[result.length - 1] = new SequenceDiff(new OffsetRange(prevResult.seq1Range.start, cur.seq1Range.endExclusive - length), new OffsetRange(prevResult.seq2Range.start, cur.seq2Range.endExclusive - length));
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
cur = cur.delta(-d);
|
|
568
|
+
}
|
|
569
|
+
result.push(cur);
|
|
570
|
+
}
|
|
571
|
+
const result2 = [];
|
|
572
|
+
// Then move them all to the right and join them again if possible
|
|
573
|
+
for (let i = 0; i < result.length - 1; i++) {
|
|
574
|
+
const nextResult = result[i + 1];
|
|
575
|
+
let cur = result[i];
|
|
576
|
+
if (cur.seq1Range.isEmpty || cur.seq2Range.isEmpty) {
|
|
577
|
+
const length = nextResult.seq1Range.start - cur.seq1Range.endExclusive;
|
|
578
|
+
let d;
|
|
579
|
+
for (d = 0; d < length; d++) {
|
|
580
|
+
if (!sequence1.isStronglyEqual(cur.seq1Range.start + d, cur.seq1Range.endExclusive + d) ||
|
|
581
|
+
!sequence2.isStronglyEqual(cur.seq2Range.start + d, cur.seq2Range.endExclusive + d)) {
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if (d === length) {
|
|
586
|
+
// Merge previous and current diff
|
|
587
|
+
result[i + 1] = new SequenceDiff(new OffsetRange(cur.seq1Range.start + length, nextResult.seq1Range.endExclusive), new OffsetRange(cur.seq2Range.start + length, nextResult.seq2Range.endExclusive));
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
if (d > 0) {
|
|
591
|
+
cur = cur.delta(d);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
result2.push(cur);
|
|
595
|
+
}
|
|
596
|
+
if (result.length > 0) {
|
|
597
|
+
result2.push(result[result.length - 1]);
|
|
598
|
+
}
|
|
599
|
+
return result2;
|
|
600
|
+
}
|
|
601
|
+
function shiftSequenceDiffs(sequence1, sequence2, sequenceDiffs) {
|
|
602
|
+
if (!sequence1.getBoundaryScore || !sequence2.getBoundaryScore) {
|
|
603
|
+
return sequenceDiffs;
|
|
604
|
+
}
|
|
605
|
+
for (let i = 0; i < sequenceDiffs.length; i++) {
|
|
606
|
+
const prevDiff = (i > 0 ? sequenceDiffs[i - 1] : undefined);
|
|
607
|
+
const diff = sequenceDiffs[i];
|
|
608
|
+
const nextDiff = (i + 1 < sequenceDiffs.length ? sequenceDiffs[i + 1] : undefined);
|
|
609
|
+
const seq1ValidRange = new OffsetRange(prevDiff ? prevDiff.seq1Range.endExclusive + 1 : 0, nextDiff ? nextDiff.seq1Range.start - 1 : sequence1.length);
|
|
610
|
+
const seq2ValidRange = new OffsetRange(prevDiff ? prevDiff.seq2Range.endExclusive + 1 : 0, nextDiff ? nextDiff.seq2Range.start - 1 : sequence2.length);
|
|
611
|
+
if (diff.seq1Range.isEmpty) {
|
|
612
|
+
sequenceDiffs[i] = shiftDiffToBetterPosition(diff, sequence1, sequence2, seq1ValidRange, seq2ValidRange);
|
|
613
|
+
}
|
|
614
|
+
else if (diff.seq2Range.isEmpty) {
|
|
615
|
+
sequenceDiffs[i] = shiftDiffToBetterPosition(diff.swap(), sequence2, sequence1, seq2ValidRange, seq1ValidRange).swap();
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
return sequenceDiffs;
|
|
619
|
+
}
|
|
620
|
+
function shiftDiffToBetterPosition(diff, sequence1, sequence2, seq1ValidRange, seq2ValidRange) {
|
|
621
|
+
const maxShiftLimit = 100; // To prevent performance issues
|
|
622
|
+
let deltaBefore = 1;
|
|
623
|
+
while (diff.seq1Range.start - deltaBefore >= seq1ValidRange.start &&
|
|
624
|
+
diff.seq2Range.start - deltaBefore >= seq2ValidRange.start &&
|
|
625
|
+
sequence2.isStronglyEqual(diff.seq2Range.start - deltaBefore, diff.seq2Range.endExclusive - deltaBefore) && deltaBefore < maxShiftLimit) {
|
|
626
|
+
deltaBefore++;
|
|
627
|
+
}
|
|
628
|
+
deltaBefore--;
|
|
629
|
+
let deltaAfter = 0;
|
|
630
|
+
while (diff.seq1Range.start + deltaAfter < seq1ValidRange.endExclusive &&
|
|
631
|
+
diff.seq2Range.endExclusive + deltaAfter < seq2ValidRange.endExclusive &&
|
|
632
|
+
sequence2.isStronglyEqual(diff.seq2Range.start + deltaAfter, diff.seq2Range.endExclusive + deltaAfter) && deltaAfter < maxShiftLimit) {
|
|
633
|
+
deltaAfter++;
|
|
634
|
+
}
|
|
635
|
+
if (deltaBefore === 0 && deltaAfter === 0) {
|
|
636
|
+
return diff;
|
|
637
|
+
}
|
|
638
|
+
let bestDelta = 0;
|
|
639
|
+
let bestScore = -1;
|
|
640
|
+
// Find best scored delta
|
|
641
|
+
for (let delta = -deltaBefore; delta <= deltaAfter; delta++) {
|
|
642
|
+
const seq2OffsetStart = diff.seq2Range.start + delta;
|
|
643
|
+
const seq2OffsetEndExclusive = diff.seq2Range.endExclusive + delta;
|
|
644
|
+
const seq1Offset = diff.seq1Range.start + delta;
|
|
645
|
+
const score = sequence1.getBoundaryScore(seq1Offset) + sequence2.getBoundaryScore(seq2OffsetStart) + sequence2.getBoundaryScore(seq2OffsetEndExclusive);
|
|
646
|
+
if (score > bestScore) {
|
|
647
|
+
bestScore = score;
|
|
648
|
+
bestDelta = delta;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return diff.delta(bestDelta);
|
|
652
|
+
}
|
|
653
|
+
function removeShortMatches(sequence1, sequence2, sequenceDiffs) {
|
|
654
|
+
const result = [];
|
|
655
|
+
for (const s of sequenceDiffs) {
|
|
656
|
+
const last = result[result.length - 1];
|
|
657
|
+
if (!last) {
|
|
658
|
+
result.push(s);
|
|
659
|
+
continue;
|
|
660
|
+
}
|
|
661
|
+
if (s.seq1Range.start - last.seq1Range.endExclusive <= 2 || s.seq2Range.start - last.seq2Range.endExclusive <= 2) {
|
|
662
|
+
result[result.length - 1] = new SequenceDiff(last.seq1Range.join(s.seq1Range), last.seq2Range.join(s.seq2Range));
|
|
663
|
+
}
|
|
664
|
+
else {
|
|
665
|
+
result.push(s);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
return result;
|
|
669
|
+
}
|
|
670
|
+
function extendDiffsToEntireWordIfAppropriate(sequence1, sequence2, sequenceDiffs, findParent, force = false) {
|
|
671
|
+
const equalMappings = SequenceDiff.invert(sequenceDiffs, sequence1.length);
|
|
672
|
+
const additional = [];
|
|
673
|
+
let lastPoint = new OffsetPair(0, 0);
|
|
674
|
+
function scanWord(pair, equalMapping) {
|
|
675
|
+
if (pair.offset1 < lastPoint.offset1 || pair.offset2 < lastPoint.offset2) {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
const w1 = findParent(sequence1, pair.offset1);
|
|
679
|
+
const w2 = findParent(sequence2, pair.offset2);
|
|
680
|
+
if (!w1 || !w2) {
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
let w = new SequenceDiff(w1, w2);
|
|
684
|
+
const equalPart = w.intersect(equalMapping);
|
|
685
|
+
let equalChars1 = equalPart.seq1Range.length;
|
|
686
|
+
let equalChars2 = equalPart.seq2Range.length;
|
|
687
|
+
while (equalMappings.length > 0) {
|
|
688
|
+
const next = equalMappings[0];
|
|
689
|
+
const intersects = next.seq1Range.intersects(w.seq1Range) || next.seq2Range.intersects(w.seq2Range);
|
|
690
|
+
if (!intersects) {
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
const v1 = findParent(sequence1, next.seq1Range.start);
|
|
694
|
+
const v2 = findParent(sequence2, next.seq2Range.start);
|
|
695
|
+
const v = new SequenceDiff(v1, v2);
|
|
696
|
+
const equalPartV = v.intersect(next);
|
|
697
|
+
equalChars1 += equalPartV.seq1Range.length;
|
|
698
|
+
equalChars2 += equalPartV.seq2Range.length;
|
|
699
|
+
w = w.join(v);
|
|
700
|
+
if (w.seq1Range.endExclusive >= next.seq1Range.endExclusive) {
|
|
701
|
+
equalMappings.shift();
|
|
702
|
+
}
|
|
703
|
+
else {
|
|
704
|
+
break;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
if ((force && equalChars1 + equalChars2 < w.seq1Range.length + w.seq2Range.length) || equalChars1 + equalChars2 < (w.seq1Range.length + w.seq2Range.length) * 2 / 3) {
|
|
708
|
+
additional.push(w);
|
|
709
|
+
}
|
|
710
|
+
lastPoint = w.getEndExclusives();
|
|
711
|
+
}
|
|
712
|
+
while (equalMappings.length > 0) {
|
|
713
|
+
const next = equalMappings.shift();
|
|
714
|
+
if (next.seq1Range.isEmpty) {
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
scanWord(next.getStarts(), next);
|
|
718
|
+
scanWord(next.getEndExclusives().delta(-1), next);
|
|
719
|
+
}
|
|
720
|
+
const merged = mergeSequenceDiffs(sequenceDiffs, additional);
|
|
721
|
+
return merged;
|
|
722
|
+
}
|
|
723
|
+
function mergeSequenceDiffs(sequenceDiffs1, sequenceDiffs2) {
|
|
724
|
+
const result = [];
|
|
725
|
+
while (sequenceDiffs1.length > 0 || sequenceDiffs2.length > 0) {
|
|
726
|
+
const sd1 = sequenceDiffs1[0];
|
|
727
|
+
const sd2 = sequenceDiffs2[0];
|
|
728
|
+
let next;
|
|
729
|
+
if (sd1 && (!sd2 || sd1.seq1Range.start < sd2.seq1Range.start)) {
|
|
730
|
+
next = sequenceDiffs1.shift();
|
|
731
|
+
}
|
|
732
|
+
else {
|
|
733
|
+
next = sequenceDiffs2.shift();
|
|
734
|
+
}
|
|
735
|
+
if (result.length > 0 && result[result.length - 1].seq1Range.endExclusive >= next.seq1Range.start) {
|
|
736
|
+
result[result.length - 1] = result[result.length - 1].join(next);
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
result.push(next);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
return result;
|
|
743
|
+
}
|
|
744
|
+
function removeVeryShortMatchingLinesBetweenDiffs(sequence1, _sequence2, sequenceDiffs) {
|
|
745
|
+
let diffs = sequenceDiffs;
|
|
746
|
+
if (diffs.length === 0) {
|
|
747
|
+
return diffs;
|
|
748
|
+
}
|
|
749
|
+
let counter = 0;
|
|
750
|
+
let shouldRepeat;
|
|
751
|
+
do {
|
|
752
|
+
shouldRepeat = false;
|
|
753
|
+
const result = [diffs[0]];
|
|
754
|
+
for (let i = 1; i < diffs.length; i++) {
|
|
755
|
+
const cur = diffs[i];
|
|
756
|
+
const lastResult = result[result.length - 1];
|
|
757
|
+
function shouldJoinDiffs(before, after) {
|
|
758
|
+
const unchangedRange = new OffsetRange(lastResult.seq1Range.endExclusive, cur.seq1Range.start);
|
|
759
|
+
const unchangedText = sequence1.getText(unchangedRange);
|
|
760
|
+
const unchangedTextWithoutWs = unchangedText.replace(/\s/g, '');
|
|
761
|
+
if (unchangedTextWithoutWs.length <= 4
|
|
762
|
+
&& (before.seq1Range.length + before.seq2Range.length > 5 || after.seq1Range.length + after.seq2Range.length > 5)) {
|
|
763
|
+
return true;
|
|
764
|
+
}
|
|
765
|
+
return false;
|
|
766
|
+
}
|
|
767
|
+
const shouldJoin = shouldJoinDiffs(lastResult, cur);
|
|
768
|
+
if (shouldJoin) {
|
|
769
|
+
shouldRepeat = true;
|
|
770
|
+
result[result.length - 1] = result[result.length - 1].join(cur);
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
result.push(cur);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
diffs = result;
|
|
777
|
+
} while (counter++ < 10 && shouldRepeat);
|
|
778
|
+
return diffs;
|
|
779
|
+
}
|
|
780
|
+
function removeVeryShortMatchingTextBetweenLongDiffs(sequence1, sequence2, sequenceDiffs) {
|
|
781
|
+
let diffs = sequenceDiffs;
|
|
782
|
+
if (diffs.length === 0) {
|
|
783
|
+
return diffs;
|
|
784
|
+
}
|
|
785
|
+
let counter = 0;
|
|
786
|
+
let shouldRepeat;
|
|
787
|
+
do {
|
|
788
|
+
shouldRepeat = false;
|
|
789
|
+
const result = [diffs[0]];
|
|
790
|
+
for (let i = 1; i < diffs.length; i++) {
|
|
791
|
+
const cur = diffs[i];
|
|
792
|
+
const lastResult = result[result.length - 1];
|
|
793
|
+
function shouldJoinDiffs(before, after) {
|
|
794
|
+
const unchangedRange = new OffsetRange(lastResult.seq1Range.endExclusive, cur.seq1Range.start);
|
|
795
|
+
const unchangedLineCount = sequence1.countLinesIn(unchangedRange);
|
|
796
|
+
if (unchangedLineCount > 5 || unchangedRange.length > 500) {
|
|
797
|
+
return false;
|
|
798
|
+
}
|
|
799
|
+
const unchangedText = sequence1.getText(unchangedRange).trim();
|
|
800
|
+
if (unchangedText.length > 20 || unchangedText.split(/\r\n|\r|\n/).length > 1) {
|
|
801
|
+
return false;
|
|
802
|
+
}
|
|
803
|
+
const beforeLineCount1 = sequence1.countLinesIn(before.seq1Range);
|
|
804
|
+
const beforeSeq1Length = before.seq1Range.length;
|
|
805
|
+
const beforeLineCount2 = sequence2.countLinesIn(before.seq2Range);
|
|
806
|
+
const beforeSeq2Length = before.seq2Range.length;
|
|
807
|
+
const afterLineCount1 = sequence1.countLinesIn(after.seq1Range);
|
|
808
|
+
const afterSeq1Length = after.seq1Range.length;
|
|
809
|
+
const afterLineCount2 = sequence2.countLinesIn(after.seq2Range);
|
|
810
|
+
const afterSeq2Length = after.seq2Range.length;
|
|
811
|
+
const max = 2 * 40 + 50;
|
|
812
|
+
function cap(v) {
|
|
813
|
+
return Math.min(v, max);
|
|
814
|
+
}
|
|
815
|
+
if (Math.pow(Math.pow(cap(beforeLineCount1 * 40 + beforeSeq1Length), 1.5) + Math.pow(cap(beforeLineCount2 * 40 + beforeSeq2Length), 1.5), 1.5)
|
|
816
|
+
+ Math.pow(Math.pow(cap(afterLineCount1 * 40 + afterSeq1Length), 1.5) + Math.pow(cap(afterLineCount2 * 40 + afterSeq2Length), 1.5), 1.5) > ((max ** 1.5) ** 1.5) * 1.3) {
|
|
817
|
+
return true;
|
|
818
|
+
}
|
|
819
|
+
return false;
|
|
820
|
+
}
|
|
821
|
+
const shouldJoin = shouldJoinDiffs(lastResult, cur);
|
|
822
|
+
if (shouldJoin) {
|
|
823
|
+
shouldRepeat = true;
|
|
824
|
+
result[result.length - 1] = result[result.length - 1].join(cur);
|
|
825
|
+
}
|
|
826
|
+
else {
|
|
827
|
+
result.push(cur);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
diffs = result;
|
|
831
|
+
} while (counter++ < 10 && shouldRepeat);
|
|
832
|
+
const newDiffs = [];
|
|
833
|
+
// Remove short suffixes/prefixes
|
|
834
|
+
forEachWithNeighbors(diffs, (prev, cur, next) => {
|
|
835
|
+
let newDiff = cur;
|
|
836
|
+
function shouldMarkAsChanged(text) {
|
|
837
|
+
return text.length > 0 && text.trim().length <= 3 && cur.seq1Range.length + cur.seq2Range.length > 100;
|
|
838
|
+
}
|
|
839
|
+
const fullRange1 = sequence1.extendToFullLines(cur.seq1Range);
|
|
840
|
+
const prefix = sequence1.getText(new OffsetRange(fullRange1.start, cur.seq1Range.start));
|
|
841
|
+
if (shouldMarkAsChanged(prefix)) {
|
|
842
|
+
newDiff = newDiff.deltaStart(-prefix.length);
|
|
843
|
+
}
|
|
844
|
+
const suffix = sequence1.getText(new OffsetRange(cur.seq1Range.endExclusive, fullRange1.endExclusive));
|
|
845
|
+
if (shouldMarkAsChanged(suffix)) {
|
|
846
|
+
newDiff = newDiff.deltaEnd(suffix.length);
|
|
847
|
+
}
|
|
848
|
+
const availableSpace = SequenceDiff.fromOffsetPairs(prev ? prev.getEndExclusives() : OffsetPair.zero, next ? next.getStarts() : OffsetPair.max);
|
|
849
|
+
const intersected = newDiff.intersect(availableSpace);
|
|
850
|
+
if (newDiffs.length > 0 && intersected.getStarts().equals(newDiffs[newDiffs.length - 1].getEndExclusives())) {
|
|
851
|
+
newDiffs[newDiffs.length - 1] = newDiffs[newDiffs.length - 1].join(intersected);
|
|
852
|
+
}
|
|
853
|
+
else {
|
|
854
|
+
newDiffs.push(intersected);
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
return newDiffs;
|
|
858
|
+
}
|
|
859
|
+
function forEachWithNeighbors(items, callback) {
|
|
860
|
+
for (let i = 0; i < items.length; i++) {
|
|
861
|
+
callback(items[i - 1], items[i], items[i + 1]);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
const CharCode$1 = {
|
|
866
|
+
Space: 32,
|
|
867
|
+
Tab: 9,
|
|
868
|
+
};
|
|
869
|
+
class LineSequence {
|
|
870
|
+
trimmedHash;
|
|
871
|
+
lines;
|
|
872
|
+
constructor(trimmedHash, lines) {
|
|
873
|
+
this.trimmedHash = trimmedHash;
|
|
874
|
+
this.lines = lines;
|
|
875
|
+
}
|
|
876
|
+
getElement(offset) {
|
|
877
|
+
return this.trimmedHash[offset];
|
|
878
|
+
}
|
|
879
|
+
get length() {
|
|
880
|
+
return this.trimmedHash.length;
|
|
881
|
+
}
|
|
882
|
+
getBoundaryScore(length) {
|
|
883
|
+
const indentationBefore = length === 0 ? 0 : getIndentation(this.lines[length - 1]);
|
|
884
|
+
const indentationAfter = length === this.lines.length ? 0 : getIndentation(this.lines[length]);
|
|
885
|
+
return 1000 - (indentationBefore + indentationAfter);
|
|
886
|
+
}
|
|
887
|
+
getText(range) {
|
|
888
|
+
return this.lines.slice(range.start, range.endExclusive).join('\n');
|
|
889
|
+
}
|
|
890
|
+
isStronglyEqual(offset1, offset2) {
|
|
891
|
+
return this.lines[offset1] === this.lines[offset2];
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
function getIndentation(str) {
|
|
895
|
+
let i = 0;
|
|
896
|
+
while (i < str.length && (str.charCodeAt(i) === CharCode$1.Space || str.charCodeAt(i) === CharCode$1.Tab)) {
|
|
897
|
+
i++;
|
|
898
|
+
}
|
|
899
|
+
return i;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
const CharCode = {
|
|
903
|
+
LineFeed: 10,
|
|
904
|
+
CarriageReturn: 13,
|
|
905
|
+
Space: 32,
|
|
906
|
+
Tab: 9,
|
|
907
|
+
a: 97,
|
|
908
|
+
z: 122,
|
|
909
|
+
A: 65,
|
|
910
|
+
Z: 90,
|
|
911
|
+
Digit0: 48,
|
|
912
|
+
Digit9: 57,
|
|
913
|
+
Comma: 44,
|
|
914
|
+
Semicolon: 59,
|
|
915
|
+
};
|
|
916
|
+
function isSpace(charCode) {
|
|
917
|
+
return charCode === CharCode.Space || charCode === CharCode.Tab;
|
|
918
|
+
}
|
|
919
|
+
class Range {
|
|
920
|
+
startLineNumber;
|
|
921
|
+
startColumn;
|
|
922
|
+
endLineNumber;
|
|
923
|
+
endColumn;
|
|
924
|
+
constructor(startLineNumber, startColumn, endLineNumber, endColumn) {
|
|
925
|
+
this.startLineNumber = startLineNumber;
|
|
926
|
+
this.startColumn = startColumn;
|
|
927
|
+
this.endLineNumber = endLineNumber;
|
|
928
|
+
this.endColumn = endColumn;
|
|
929
|
+
}
|
|
930
|
+
static fromPositions(start, end) {
|
|
931
|
+
return new Range(start.lineNumber, start.column, end.lineNumber, end.column);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
class Position {
|
|
935
|
+
lineNumber;
|
|
936
|
+
column;
|
|
937
|
+
constructor(lineNumber, column) {
|
|
938
|
+
this.lineNumber = lineNumber;
|
|
939
|
+
this.column = column;
|
|
940
|
+
}
|
|
941
|
+
isBefore(other) {
|
|
942
|
+
if (this.lineNumber < other.lineNumber) {
|
|
943
|
+
return true;
|
|
944
|
+
}
|
|
945
|
+
if (other.lineNumber < this.lineNumber) {
|
|
946
|
+
return false;
|
|
947
|
+
}
|
|
948
|
+
return this.column < other.column;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
class LinesSliceCharSequence {
|
|
952
|
+
lines;
|
|
953
|
+
considerWhitespaceChanges;
|
|
954
|
+
elements = [];
|
|
955
|
+
firstElementOffsetByLineIdx = [];
|
|
956
|
+
lineStartOffsets = [];
|
|
957
|
+
trimmedWsLengthsByLineIdx = [];
|
|
958
|
+
_range;
|
|
959
|
+
constructor(lines, range, considerWhitespaceChanges) {
|
|
960
|
+
this.lines = lines;
|
|
961
|
+
this.considerWhitespaceChanges = considerWhitespaceChanges;
|
|
962
|
+
this._range = range;
|
|
963
|
+
this.firstElementOffsetByLineIdx.push(0);
|
|
964
|
+
for (let lineNumber = this._range.startLineNumber; lineNumber <= this._range.endLineNumber; lineNumber++) {
|
|
965
|
+
let line = lines[lineNumber - 1];
|
|
966
|
+
let lineStartOffset = 0;
|
|
967
|
+
if (lineNumber === this._range.startLineNumber && this._range.startColumn > 1) {
|
|
968
|
+
lineStartOffset = this._range.startColumn - 1;
|
|
969
|
+
line = line.substring(lineStartOffset);
|
|
970
|
+
}
|
|
971
|
+
this.lineStartOffsets.push(lineStartOffset);
|
|
972
|
+
let trimmedWsLength = 0;
|
|
973
|
+
if (!considerWhitespaceChanges) {
|
|
974
|
+
const trimmedStartLine = line.trimStart();
|
|
975
|
+
trimmedWsLength = line.length - trimmedStartLine.length;
|
|
976
|
+
line = trimmedStartLine.trimEnd();
|
|
977
|
+
}
|
|
978
|
+
this.trimmedWsLengthsByLineIdx.push(trimmedWsLength);
|
|
979
|
+
const lineLength = lineNumber === this._range.endLineNumber ? Math.min(this._range.endColumn - 1 - lineStartOffset - trimmedWsLength, line.length) : line.length;
|
|
980
|
+
for (let i = 0; i < lineLength; i++) {
|
|
981
|
+
this.elements.push(line.charCodeAt(i));
|
|
982
|
+
}
|
|
983
|
+
if (lineNumber < this._range.endLineNumber) {
|
|
984
|
+
this.elements.push('\n'.charCodeAt(0));
|
|
985
|
+
this.firstElementOffsetByLineIdx.push(this.elements.length);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
toString() {
|
|
990
|
+
return `Slice: "${this.text}"`;
|
|
991
|
+
}
|
|
992
|
+
get text() {
|
|
993
|
+
return this.getText(new OffsetRange(0, this.length));
|
|
994
|
+
}
|
|
995
|
+
getText(range) {
|
|
996
|
+
return this.elements.slice(range.start, range.endExclusive).map(e => String.fromCharCode(e)).join('');
|
|
997
|
+
}
|
|
998
|
+
getElement(offset) {
|
|
999
|
+
return this.elements[offset];
|
|
1000
|
+
}
|
|
1001
|
+
get length() {
|
|
1002
|
+
return this.elements.length;
|
|
1003
|
+
}
|
|
1004
|
+
getBoundaryScore(length) {
|
|
1005
|
+
const prevCategory = getCategory(length > 0 ? this.elements[length - 1] : -1);
|
|
1006
|
+
const nextCategory = getCategory(length < this.elements.length ? this.elements[length] : -1);
|
|
1007
|
+
if (prevCategory === 7 /* CharBoundaryCategory.LineBreakCR */ && nextCategory === 8 /* CharBoundaryCategory.LineBreakLF */) {
|
|
1008
|
+
// don't break between \r and \n
|
|
1009
|
+
return 0;
|
|
1010
|
+
}
|
|
1011
|
+
if (prevCategory === 8 /* CharBoundaryCategory.LineBreakLF */) {
|
|
1012
|
+
// prefer the linebreak before the change
|
|
1013
|
+
return 150;
|
|
1014
|
+
}
|
|
1015
|
+
let score = 0;
|
|
1016
|
+
if (prevCategory !== nextCategory) {
|
|
1017
|
+
score += 10;
|
|
1018
|
+
if (prevCategory === 0 /* CharBoundaryCategory.WordLower */ && nextCategory === 1 /* CharBoundaryCategory.WordUpper */) {
|
|
1019
|
+
score += 1;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
score += getCategoryBoundaryScore(prevCategory);
|
|
1023
|
+
score += getCategoryBoundaryScore(nextCategory);
|
|
1024
|
+
return score;
|
|
1025
|
+
}
|
|
1026
|
+
translateOffset(offset, preference = 'right') {
|
|
1027
|
+
const i = findLastIdxMonotonous(this.firstElementOffsetByLineIdx, (value) => value <= offset);
|
|
1028
|
+
const lineOffset = offset - this.firstElementOffsetByLineIdx[i];
|
|
1029
|
+
return new Position(this._range.startLineNumber + i, 1 + this.lineStartOffsets[i] + lineOffset + ((lineOffset === 0 && preference === 'left') ? 0 : this.trimmedWsLengthsByLineIdx[i]));
|
|
1030
|
+
}
|
|
1031
|
+
translateRange(range) {
|
|
1032
|
+
const pos1 = this.translateOffset(range.start, 'right');
|
|
1033
|
+
const pos2 = this.translateOffset(range.endExclusive, 'left');
|
|
1034
|
+
if (pos2.isBefore(pos1)) {
|
|
1035
|
+
return Range.fromPositions(pos2, pos2);
|
|
1036
|
+
}
|
|
1037
|
+
return Range.fromPositions(pos1, pos2);
|
|
1038
|
+
}
|
|
1039
|
+
/**
|
|
1040
|
+
* Finds the word that contains the character at the given offset
|
|
1041
|
+
*/
|
|
1042
|
+
findWordContaining(offset) {
|
|
1043
|
+
if (offset < 0 || offset >= this.elements.length) {
|
|
1044
|
+
return undefined;
|
|
1045
|
+
}
|
|
1046
|
+
if (!isWordChar(this.elements[offset])) {
|
|
1047
|
+
return undefined;
|
|
1048
|
+
}
|
|
1049
|
+
// find start
|
|
1050
|
+
let start = offset;
|
|
1051
|
+
while (start > 0 && isWordChar(this.elements[start - 1])) {
|
|
1052
|
+
start--;
|
|
1053
|
+
}
|
|
1054
|
+
// find end
|
|
1055
|
+
let end = offset;
|
|
1056
|
+
while (end < this.elements.length && isWordChar(this.elements[end])) {
|
|
1057
|
+
end++;
|
|
1058
|
+
}
|
|
1059
|
+
return new OffsetRange(start, end);
|
|
1060
|
+
}
|
|
1061
|
+
/** fooBar has the two sub-words foo and bar */
|
|
1062
|
+
findSubWordContaining(offset) {
|
|
1063
|
+
if (offset < 0 || offset >= this.elements.length) {
|
|
1064
|
+
return undefined;
|
|
1065
|
+
}
|
|
1066
|
+
if (!isWordChar(this.elements[offset])) {
|
|
1067
|
+
return undefined;
|
|
1068
|
+
}
|
|
1069
|
+
// find start
|
|
1070
|
+
let start = offset;
|
|
1071
|
+
while (start > 0 && isWordChar(this.elements[start - 1]) && !isUpperCase(this.elements[start])) {
|
|
1072
|
+
start--;
|
|
1073
|
+
}
|
|
1074
|
+
// find end
|
|
1075
|
+
let end = offset;
|
|
1076
|
+
while (end < this.elements.length && isWordChar(this.elements[end]) && !isUpperCase(this.elements[end])) {
|
|
1077
|
+
end++;
|
|
1078
|
+
}
|
|
1079
|
+
return new OffsetRange(start, end);
|
|
1080
|
+
}
|
|
1081
|
+
countLinesIn(range) {
|
|
1082
|
+
return this.translateOffset(range.endExclusive).lineNumber - this.translateOffset(range.start).lineNumber;
|
|
1083
|
+
}
|
|
1084
|
+
isStronglyEqual(offset1, offset2) {
|
|
1085
|
+
return this.elements[offset1] === this.elements[offset2];
|
|
1086
|
+
}
|
|
1087
|
+
extendToFullLines(range) {
|
|
1088
|
+
const start = findLastMonotonous(this.firstElementOffsetByLineIdx, x => x <= range.start) ?? 0;
|
|
1089
|
+
const end = findFirstMonotonous(this.firstElementOffsetByLineIdx, x => range.endExclusive <= x) ?? this.elements.length;
|
|
1090
|
+
return new OffsetRange(start, end);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
function isWordChar(charCode) {
|
|
1094
|
+
return charCode >= CharCode.a && charCode <= CharCode.z
|
|
1095
|
+
|| charCode >= CharCode.A && charCode <= CharCode.Z
|
|
1096
|
+
|| charCode >= CharCode.Digit0 && charCode <= CharCode.Digit9;
|
|
1097
|
+
}
|
|
1098
|
+
function isUpperCase(charCode) {
|
|
1099
|
+
return charCode >= CharCode.A && charCode <= CharCode.Z;
|
|
1100
|
+
}
|
|
1101
|
+
const categoryScore = {
|
|
1102
|
+
[0 /* CharBoundaryCategory.WordLower */]: 0,
|
|
1103
|
+
[1 /* CharBoundaryCategory.WordUpper */]: 0,
|
|
1104
|
+
[2 /* CharBoundaryCategory.WordNumber */]: 0,
|
|
1105
|
+
[3 /* CharBoundaryCategory.End */]: 10,
|
|
1106
|
+
[4 /* CharBoundaryCategory.Other */]: 2,
|
|
1107
|
+
[5 /* CharBoundaryCategory.Separator */]: 30,
|
|
1108
|
+
[6 /* CharBoundaryCategory.Space */]: 3,
|
|
1109
|
+
[7 /* CharBoundaryCategory.LineBreakCR */]: 10,
|
|
1110
|
+
[8 /* CharBoundaryCategory.LineBreakLF */]: 10,
|
|
1111
|
+
};
|
|
1112
|
+
function getCategoryBoundaryScore(category) {
|
|
1113
|
+
return categoryScore[category];
|
|
1114
|
+
}
|
|
1115
|
+
function getCategory(charCode) {
|
|
1116
|
+
if (charCode === CharCode.LineFeed) {
|
|
1117
|
+
return 8 /* CharBoundaryCategory.LineBreakLF */;
|
|
1118
|
+
}
|
|
1119
|
+
else if (charCode === CharCode.CarriageReturn) {
|
|
1120
|
+
return 7 /* CharBoundaryCategory.LineBreakCR */;
|
|
1121
|
+
}
|
|
1122
|
+
else if (isSpace(charCode)) {
|
|
1123
|
+
return 6 /* CharBoundaryCategory.Space */;
|
|
1124
|
+
}
|
|
1125
|
+
else if (charCode >= CharCode.a && charCode <= CharCode.z) {
|
|
1126
|
+
return 0 /* CharBoundaryCategory.WordLower */;
|
|
1127
|
+
}
|
|
1128
|
+
else if (charCode >= CharCode.A && charCode <= CharCode.Z) {
|
|
1129
|
+
return 1 /* CharBoundaryCategory.WordUpper */;
|
|
1130
|
+
}
|
|
1131
|
+
else if (charCode >= CharCode.Digit0 && charCode <= CharCode.Digit9) {
|
|
1132
|
+
return 2 /* CharBoundaryCategory.WordNumber */;
|
|
1133
|
+
}
|
|
1134
|
+
else if (charCode === -1) {
|
|
1135
|
+
return 3 /* CharBoundaryCategory.End */;
|
|
1136
|
+
}
|
|
1137
|
+
else if (charCode === CharCode.Comma || charCode === CharCode.Semicolon) {
|
|
1138
|
+
return 5 /* CharBoundaryCategory.Separator */;
|
|
1139
|
+
}
|
|
1140
|
+
else {
|
|
1141
|
+
return 4 /* CharBoundaryCategory.Other */;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
// Binary search helpers
|
|
1145
|
+
function findLastIdxMonotonous(array, predicate) {
|
|
1146
|
+
let low = 0;
|
|
1147
|
+
let high = array.length - 1;
|
|
1148
|
+
while (low <= high) {
|
|
1149
|
+
const mid = Math.floor((low + high) / 2);
|
|
1150
|
+
if (predicate(array[mid])) {
|
|
1151
|
+
low = mid + 1;
|
|
1152
|
+
}
|
|
1153
|
+
else {
|
|
1154
|
+
high = mid - 1;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
return high;
|
|
1158
|
+
}
|
|
1159
|
+
function findLastMonotonous(array, predicate) {
|
|
1160
|
+
const idx = findLastIdxMonotonous(array, predicate);
|
|
1161
|
+
return idx >= 0 ? array[idx] : undefined;
|
|
1162
|
+
}
|
|
1163
|
+
function findFirstMonotonous(array, predicate) {
|
|
1164
|
+
let low = 0;
|
|
1165
|
+
let high = array.length - 1;
|
|
1166
|
+
while (low <= high) {
|
|
1167
|
+
const mid = Math.floor((low + high) / 2);
|
|
1168
|
+
if (predicate(array[mid])) {
|
|
1169
|
+
high = mid - 1;
|
|
1170
|
+
}
|
|
1171
|
+
else {
|
|
1172
|
+
low = mid + 1;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
return low < array.length ? array[low] : undefined;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* A range of lines (1-based, end is exclusive).
|
|
1180
|
+
*/
|
|
1181
|
+
class LineRange {
|
|
1182
|
+
startLineNumber;
|
|
1183
|
+
endLineNumberExclusive;
|
|
1184
|
+
constructor(startLineNumber, endLineNumberExclusive) {
|
|
1185
|
+
this.startLineNumber = startLineNumber;
|
|
1186
|
+
this.endLineNumberExclusive = endLineNumberExclusive;
|
|
1187
|
+
if (startLineNumber > endLineNumberExclusive) {
|
|
1188
|
+
throw new Error(`Invalid range: ${startLineNumber} > ${endLineNumberExclusive}`);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
get isEmpty() {
|
|
1192
|
+
return this.startLineNumber === this.endLineNumberExclusive;
|
|
1193
|
+
}
|
|
1194
|
+
get length() {
|
|
1195
|
+
return this.endLineNumberExclusive - this.startLineNumber;
|
|
1196
|
+
}
|
|
1197
|
+
join(other) {
|
|
1198
|
+
return new LineRange(Math.min(this.startLineNumber, other.startLineNumber), Math.max(this.endLineNumberExclusive, other.endLineNumberExclusive));
|
|
1199
|
+
}
|
|
1200
|
+
intersectsOrTouches(other) {
|
|
1201
|
+
return this.startLineNumber <= other.endLineNumberExclusive
|
|
1202
|
+
&& other.startLineNumber <= this.endLineNumberExclusive;
|
|
1203
|
+
}
|
|
1204
|
+
toOffsetRange() {
|
|
1205
|
+
return new OffsetRange(this.startLineNumber - 1, this.endLineNumberExclusive - 1);
|
|
1206
|
+
}
|
|
1207
|
+
toString() {
|
|
1208
|
+
return `[${this.startLineNumber}, ${this.endLineNumberExclusive})`;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
/**
|
|
1212
|
+
* A mapping between two ranges.
|
|
1213
|
+
*/
|
|
1214
|
+
class RangeMapping {
|
|
1215
|
+
originalRange;
|
|
1216
|
+
modifiedRange;
|
|
1217
|
+
constructor(originalRange, modifiedRange) {
|
|
1218
|
+
this.originalRange = originalRange;
|
|
1219
|
+
this.modifiedRange = modifiedRange;
|
|
1220
|
+
}
|
|
1221
|
+
toString() {
|
|
1222
|
+
return `${rangeToString(this.originalRange)} <-> ${rangeToString(this.modifiedRange)}`;
|
|
1223
|
+
}
|
|
1224
|
+
static assertSorted(rangeMappings) {
|
|
1225
|
+
for (let i = 1; i < rangeMappings.length; i++) {
|
|
1226
|
+
const prev = rangeMappings[i - 1];
|
|
1227
|
+
const cur = rangeMappings[i];
|
|
1228
|
+
if (!(prev.originalRange.endLineNumber <= cur.originalRange.startLineNumber ||
|
|
1229
|
+
(prev.originalRange.endLineNumber === cur.originalRange.startLineNumber && prev.originalRange.endColumn <= cur.originalRange.startColumn))) {
|
|
1230
|
+
throw new Error('RangeMappings must be sorted');
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
function rangeToString(range) {
|
|
1236
|
+
return `(${range.startLineNumber}:${range.startColumn})-(${range.endLineNumber}:${range.endColumn})`;
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* A mapping between two line ranges.
|
|
1240
|
+
*/
|
|
1241
|
+
class LineRangeMapping {
|
|
1242
|
+
original;
|
|
1243
|
+
modified;
|
|
1244
|
+
constructor(original, modified) {
|
|
1245
|
+
this.original = original;
|
|
1246
|
+
this.modified = modified;
|
|
1247
|
+
}
|
|
1248
|
+
toString() {
|
|
1249
|
+
return `${this.original} <-> ${this.modified}`;
|
|
1250
|
+
}
|
|
1251
|
+
/**
|
|
1252
|
+
* This method assumes that the LineRangeMapping describes a valid diff!
|
|
1253
|
+
* I.e. if one range is empty, the other range cannot be the entire document.
|
|
1254
|
+
* It avoids various problems when the line range points to non-existing line-numbers.
|
|
1255
|
+
*/
|
|
1256
|
+
toRangeMapping2(originalLines, modifiedLines) {
|
|
1257
|
+
const isValidLineNumber = (lineNumber, lines) => {
|
|
1258
|
+
return lineNumber >= 1 && lineNumber <= lines.length;
|
|
1259
|
+
};
|
|
1260
|
+
const normalizePosition = (lineNumber, column, lines) => {
|
|
1261
|
+
if (lineNumber < 1) {
|
|
1262
|
+
return new Position(1, 1);
|
|
1263
|
+
}
|
|
1264
|
+
if (lineNumber > lines.length) {
|
|
1265
|
+
return new Position(lines.length, lines[lines.length - 1].length + 1);
|
|
1266
|
+
}
|
|
1267
|
+
const line = lines[lineNumber - 1];
|
|
1268
|
+
if (column > line.length + 1) {
|
|
1269
|
+
return new Position(lineNumber, line.length + 1);
|
|
1270
|
+
}
|
|
1271
|
+
return new Position(lineNumber, column);
|
|
1272
|
+
};
|
|
1273
|
+
if (isValidLineNumber(this.original.endLineNumberExclusive, originalLines)
|
|
1274
|
+
&& isValidLineNumber(this.modified.endLineNumberExclusive, modifiedLines)) {
|
|
1275
|
+
return new RangeMapping(new Range(this.original.startLineNumber, 1, this.original.endLineNumberExclusive, 1), new Range(this.modified.startLineNumber, 1, this.modified.endLineNumberExclusive, 1));
|
|
1276
|
+
}
|
|
1277
|
+
if (!this.original.isEmpty && !this.modified.isEmpty) {
|
|
1278
|
+
return new RangeMapping(Range.fromPositions(new Position(this.original.startLineNumber, 1), normalizePosition(this.original.endLineNumberExclusive - 1, Number.MAX_SAFE_INTEGER, originalLines)), Range.fromPositions(new Position(this.modified.startLineNumber, 1), normalizePosition(this.modified.endLineNumberExclusive - 1, Number.MAX_SAFE_INTEGER, modifiedLines)));
|
|
1279
|
+
}
|
|
1280
|
+
if (this.original.startLineNumber > 1 && this.modified.startLineNumber > 1) {
|
|
1281
|
+
return new RangeMapping(Range.fromPositions(normalizePosition(this.original.startLineNumber - 1, Number.MAX_SAFE_INTEGER, originalLines), normalizePosition(this.original.endLineNumberExclusive - 1, Number.MAX_SAFE_INTEGER, originalLines)), Range.fromPositions(normalizePosition(this.modified.startLineNumber - 1, Number.MAX_SAFE_INTEGER, modifiedLines), normalizePosition(this.modified.endLineNumberExclusive - 1, Number.MAX_SAFE_INTEGER, modifiedLines)));
|
|
1282
|
+
}
|
|
1283
|
+
// Situation now: one range is empty and one range touches the last line and one range starts at line 1.
|
|
1284
|
+
// This shouldn't happen for valid diffs.
|
|
1285
|
+
throw new Error('Invalid diff: cannot convert to range mapping');
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* A detailed mapping between two line ranges, including inner changes.
|
|
1290
|
+
*/
|
|
1291
|
+
class DetailedLineRangeMapping extends LineRangeMapping {
|
|
1292
|
+
innerChanges;
|
|
1293
|
+
constructor(original, modified, innerChanges) {
|
|
1294
|
+
super(original, modified);
|
|
1295
|
+
this.innerChanges = innerChanges;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Result of a lines diff computation.
|
|
1300
|
+
*/
|
|
1301
|
+
class LinesDiff {
|
|
1302
|
+
changes;
|
|
1303
|
+
moves;
|
|
1304
|
+
hitTimeout;
|
|
1305
|
+
constructor(changes, moves, hitTimeout) {
|
|
1306
|
+
this.changes = changes;
|
|
1307
|
+
this.moves = moves;
|
|
1308
|
+
this.hitTimeout = hitTimeout;
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* Represents text that was moved from one location to another.
|
|
1313
|
+
*/
|
|
1314
|
+
class MovedText {
|
|
1315
|
+
lineRangeMapping;
|
|
1316
|
+
changes;
|
|
1317
|
+
constructor(lineRangeMapping, changes) {
|
|
1318
|
+
this.lineRangeMapping = lineRangeMapping;
|
|
1319
|
+
this.changes = changes;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
* Helper to convert from range mappings to line range mappings.
|
|
1324
|
+
*/
|
|
1325
|
+
function lineRangeMappingFromRangeMappings(alignments, originalLines, modifiedLines, dontAssertStartLine = false) {
|
|
1326
|
+
const changes = [];
|
|
1327
|
+
for (const g of groupAdjacentBy(alignments.map(a => getLineRangeMapping(a, originalLines, modifiedLines)), (a1, a2) => a1.original.intersectsOrTouches(a2.original)
|
|
1328
|
+
|| a1.modified.intersectsOrTouches(a2.modified))) {
|
|
1329
|
+
const first = g[0];
|
|
1330
|
+
const last = g[g.length - 1];
|
|
1331
|
+
changes.push(new DetailedLineRangeMapping(first.original.join(last.original), first.modified.join(last.modified), g.map(a => a.innerChanges[0])));
|
|
1332
|
+
}
|
|
1333
|
+
if (!dontAssertStartLine) {
|
|
1334
|
+
// Assert that the changes are sorted and non-overlapping (but don't throw - just log in debug)
|
|
1335
|
+
for (let i = 1; i < changes.length; i++) {
|
|
1336
|
+
const prev = changes[i - 1];
|
|
1337
|
+
const cur = changes[i];
|
|
1338
|
+
if (prev.original.endLineNumberExclusive > cur.original.startLineNumber ||
|
|
1339
|
+
prev.modified.endLineNumberExclusive > cur.modified.startLineNumber) {
|
|
1340
|
+
// Silently skip validation issue - may be expected in some edge cases
|
|
1341
|
+
break;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
return changes;
|
|
1346
|
+
}
|
|
1347
|
+
function getLineRangeMapping(rangeMapping, originalLines, modifiedLines) {
|
|
1348
|
+
let lineStartDelta = 0;
|
|
1349
|
+
let lineEndDelta = 0;
|
|
1350
|
+
// rangeMapping describes the edit that replaces `rangeMapping.originalRange` with `newText := getText(modifiedLines, rangeMapping.modifiedRange)`.
|
|
1351
|
+
// original: ]xxx \n <- this line is not modified
|
|
1352
|
+
// modified: ]xx \n
|
|
1353
|
+
if (rangeMapping.modifiedRange.endColumn === 1 && rangeMapping.originalRange.endColumn === 1
|
|
1354
|
+
&& rangeMapping.originalRange.startLineNumber + lineStartDelta <= rangeMapping.originalRange.endLineNumber
|
|
1355
|
+
&& rangeMapping.modifiedRange.startLineNumber + lineStartDelta <= rangeMapping.modifiedRange.endLineNumber) {
|
|
1356
|
+
// We can only do this if the range is not empty yet
|
|
1357
|
+
lineEndDelta = -1;
|
|
1358
|
+
}
|
|
1359
|
+
// original: xxx[ \n <- this line is not modified
|
|
1360
|
+
// modified: xxx[ \n
|
|
1361
|
+
if (rangeMapping.modifiedRange.startColumn - 1 >= (modifiedLines[rangeMapping.modifiedRange.startLineNumber - 1]?.length ?? 0)
|
|
1362
|
+
&& rangeMapping.originalRange.startColumn - 1 >= (originalLines[rangeMapping.originalRange.startLineNumber - 1]?.length ?? 0)
|
|
1363
|
+
&& rangeMapping.originalRange.startLineNumber <= rangeMapping.originalRange.endLineNumber + lineEndDelta
|
|
1364
|
+
&& rangeMapping.modifiedRange.startLineNumber <= rangeMapping.modifiedRange.endLineNumber + lineEndDelta) {
|
|
1365
|
+
// We can only do this if the range is not empty yet
|
|
1366
|
+
lineStartDelta = 1;
|
|
1367
|
+
}
|
|
1368
|
+
const originalLineRange = new LineRange(rangeMapping.originalRange.startLineNumber + lineStartDelta, rangeMapping.originalRange.endLineNumber + 1 + lineEndDelta);
|
|
1369
|
+
const modifiedLineRange = new LineRange(rangeMapping.modifiedRange.startLineNumber + lineStartDelta, rangeMapping.modifiedRange.endLineNumber + 1 + lineEndDelta);
|
|
1370
|
+
return new DetailedLineRangeMapping(originalLineRange, modifiedLineRange, [rangeMapping]);
|
|
1371
|
+
}
|
|
1372
|
+
function* groupAdjacentBy(items, shouldBeGrouped) {
|
|
1373
|
+
let currentGroup;
|
|
1374
|
+
let last;
|
|
1375
|
+
for (const item of items) {
|
|
1376
|
+
if (last !== undefined && shouldBeGrouped(last, item)) {
|
|
1377
|
+
currentGroup.push(item);
|
|
1378
|
+
}
|
|
1379
|
+
else {
|
|
1380
|
+
if (currentGroup) {
|
|
1381
|
+
yield currentGroup;
|
|
1382
|
+
}
|
|
1383
|
+
currentGroup = [item];
|
|
1384
|
+
}
|
|
1385
|
+
last = item;
|
|
1386
|
+
}
|
|
1387
|
+
if (currentGroup) {
|
|
1388
|
+
yield currentGroup;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
class ArrayText {
|
|
1392
|
+
lines;
|
|
1393
|
+
constructor(lines) {
|
|
1394
|
+
this.lines = lines;
|
|
1395
|
+
}
|
|
1396
|
+
get lineCount() {
|
|
1397
|
+
return this.lines.length;
|
|
1398
|
+
}
|
|
1399
|
+
getLineContent(lineNumber) {
|
|
1400
|
+
return this.lines[lineNumber - 1];
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
/**
|
|
1405
|
+
* The main diff computer that computes detailed line diffs.
|
|
1406
|
+
*/
|
|
1407
|
+
class DefaultLinesDiffComputer {
|
|
1408
|
+
_dynamicProgrammingDiffing = new DynamicProgrammingDiffing();
|
|
1409
|
+
_myersDiffingAlgorithm = new MyersDiffAlgorithm();
|
|
1410
|
+
computeDiff(originalLines, modifiedLines, options) {
|
|
1411
|
+
// Handle identical single line
|
|
1412
|
+
if (originalLines.length <= 1 && arraysEqual(originalLines, modifiedLines)) {
|
|
1413
|
+
return new LinesDiff([], [], false);
|
|
1414
|
+
}
|
|
1415
|
+
// Handle empty single line - treat as full replacement
|
|
1416
|
+
if (originalLines.length === 1 && originalLines[0].length === 0 || modifiedLines.length === 1 && modifiedLines[0].length === 0) {
|
|
1417
|
+
return new LinesDiff([
|
|
1418
|
+
new DetailedLineRangeMapping(new LineRange(1, originalLines.length + 1), new LineRange(1, modifiedLines.length + 1), [
|
|
1419
|
+
new RangeMapping(new Range(1, 1, originalLines.length, originalLines[originalLines.length - 1].length + 1), new Range(1, 1, modifiedLines.length, modifiedLines[modifiedLines.length - 1].length + 1))
|
|
1420
|
+
])
|
|
1421
|
+
], [], false);
|
|
1422
|
+
}
|
|
1423
|
+
const timeout = options.maxComputationTimeMs === 0 ? InfiniteTimeout.instance : new DateTimeout(options.maxComputationTimeMs);
|
|
1424
|
+
const considerWhitespaceChanges = !options.ignoreTrimWhitespace;
|
|
1425
|
+
// Create perfect hash for lines (trimmed)
|
|
1426
|
+
const perfectHashes = new Map();
|
|
1427
|
+
function getOrCreateHash(text) {
|
|
1428
|
+
let hash = perfectHashes.get(text);
|
|
1429
|
+
if (hash === undefined) {
|
|
1430
|
+
hash = perfectHashes.size;
|
|
1431
|
+
perfectHashes.set(text, hash);
|
|
1432
|
+
}
|
|
1433
|
+
return hash;
|
|
1434
|
+
}
|
|
1435
|
+
const originalLinesHashes = originalLines.map((l) => getOrCreateHash(l.trim()));
|
|
1436
|
+
const modifiedLinesHashes = modifiedLines.map((l) => getOrCreateHash(l.trim()));
|
|
1437
|
+
const sequence1 = new LineSequence(originalLinesHashes, originalLines);
|
|
1438
|
+
const sequence2 = new LineSequence(modifiedLinesHashes, modifiedLines);
|
|
1439
|
+
// Choose algorithm based on size
|
|
1440
|
+
const lineAlignmentResult = (() => {
|
|
1441
|
+
if (sequence1.length + sequence2.length < 1700) {
|
|
1442
|
+
// Use the improved algorithm for small files
|
|
1443
|
+
return this._dynamicProgrammingDiffing.compute(sequence1, sequence2, timeout, (offset1, offset2) => originalLines[offset1] === modifiedLines[offset2]
|
|
1444
|
+
? modifiedLines[offset2].length === 0
|
|
1445
|
+
? 0.1
|
|
1446
|
+
: 1 + Math.log(1 + modifiedLines[offset2].length)
|
|
1447
|
+
: 0.99);
|
|
1448
|
+
}
|
|
1449
|
+
return this._myersDiffingAlgorithm.compute(sequence1, sequence2, timeout);
|
|
1450
|
+
})();
|
|
1451
|
+
let lineAlignments = lineAlignmentResult.diffs;
|
|
1452
|
+
let hitTimeout = lineAlignmentResult.hitTimeout;
|
|
1453
|
+
// Apply heuristics
|
|
1454
|
+
lineAlignments = optimizeSequenceDiffs(sequence1, sequence2, lineAlignments);
|
|
1455
|
+
lineAlignments = removeVeryShortMatchingLinesBetweenDiffs(sequence1, sequence2, lineAlignments);
|
|
1456
|
+
const alignments = [];
|
|
1457
|
+
const scanForWhitespaceChanges = (equalLinesCount) => {
|
|
1458
|
+
if (!considerWhitespaceChanges) {
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1461
|
+
for (let i = 0; i < equalLinesCount; i++) {
|
|
1462
|
+
const seq1Offset = seq1LastStart + i;
|
|
1463
|
+
const seq2Offset = seq2LastStart + i;
|
|
1464
|
+
if (originalLines[seq1Offset] !== modifiedLines[seq2Offset]) {
|
|
1465
|
+
// This is because of whitespace changes, diff these lines
|
|
1466
|
+
const characterDiffs = this._refineDiff(originalLines, modifiedLines, new SequenceDiff(new OffsetRange(seq1Offset, seq1Offset + 1), new OffsetRange(seq2Offset, seq2Offset + 1)), timeout, considerWhitespaceChanges, options);
|
|
1467
|
+
for (const a of characterDiffs.mappings) {
|
|
1468
|
+
alignments.push(a);
|
|
1469
|
+
}
|
|
1470
|
+
if (characterDiffs.hitTimeout) {
|
|
1471
|
+
hitTimeout = true;
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
let seq1LastStart = 0;
|
|
1477
|
+
let seq2LastStart = 0;
|
|
1478
|
+
for (const diff of lineAlignments) {
|
|
1479
|
+
const equalLinesCount = diff.seq1Range.start - seq1LastStart;
|
|
1480
|
+
scanForWhitespaceChanges(equalLinesCount);
|
|
1481
|
+
seq1LastStart = diff.seq1Range.endExclusive;
|
|
1482
|
+
seq2LastStart = diff.seq2Range.endExclusive;
|
|
1483
|
+
const characterDiffs = this._refineDiff(originalLines, modifiedLines, diff, timeout, considerWhitespaceChanges, options);
|
|
1484
|
+
if (characterDiffs.hitTimeout) {
|
|
1485
|
+
hitTimeout = true;
|
|
1486
|
+
}
|
|
1487
|
+
for (const a of characterDiffs.mappings) {
|
|
1488
|
+
alignments.push(a);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
scanForWhitespaceChanges(originalLines.length - seq1LastStart);
|
|
1492
|
+
const original = new ArrayText(originalLines);
|
|
1493
|
+
const modified = new ArrayText(modifiedLines);
|
|
1494
|
+
const changes = lineRangeMappingFromRangeMappings(alignments, original.lines, modified.lines);
|
|
1495
|
+
// TODO: Compute moves if options.computeMoves is true
|
|
1496
|
+
const moves = [];
|
|
1497
|
+
return new LinesDiff(changes, moves, hitTimeout);
|
|
1498
|
+
}
|
|
1499
|
+
_refineDiff(originalLines, modifiedLines, diff, timeout, considerWhitespaceChanges, options) {
|
|
1500
|
+
const lineRangeMapping = toLineRangeMapping(diff);
|
|
1501
|
+
const rangeMapping = lineRangeMapping.toRangeMapping2(originalLines, modifiedLines);
|
|
1502
|
+
const slice1 = new LinesSliceCharSequence(originalLines, rangeMapping.originalRange, considerWhitespaceChanges);
|
|
1503
|
+
const slice2 = new LinesSliceCharSequence(modifiedLines, rangeMapping.modifiedRange, considerWhitespaceChanges);
|
|
1504
|
+
const diffResult = slice1.length + slice2.length < 500
|
|
1505
|
+
? this._dynamicProgrammingDiffing.compute(slice1, slice2, timeout)
|
|
1506
|
+
: this._myersDiffingAlgorithm.compute(slice1, slice2, timeout);
|
|
1507
|
+
let diffs = diffResult.diffs;
|
|
1508
|
+
diffs = optimizeSequenceDiffs(slice1, slice2, diffs);
|
|
1509
|
+
diffs = extendDiffsToEntireWordIfAppropriate(slice1, slice2, diffs, (seq, idx) => seq.findWordContaining(idx));
|
|
1510
|
+
if (options.extendToSubwords) {
|
|
1511
|
+
diffs = extendDiffsToEntireWordIfAppropriate(slice1, slice2, diffs, (seq, idx) => seq.findSubWordContaining(idx), true);
|
|
1512
|
+
}
|
|
1513
|
+
diffs = removeShortMatches(slice1, slice2, diffs);
|
|
1514
|
+
diffs = removeVeryShortMatchingTextBetweenLongDiffs(slice1, slice2, diffs);
|
|
1515
|
+
const result = diffs.map((d) => new RangeMapping(slice1.translateRange(d.seq1Range), slice2.translateRange(d.seq2Range)));
|
|
1516
|
+
return {
|
|
1517
|
+
mappings: result,
|
|
1518
|
+
hitTimeout: diffResult.hitTimeout,
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
function toLineRangeMapping(sequenceDiff) {
|
|
1523
|
+
return new LineRangeMapping(new LineRange(sequenceDiff.seq1Range.start + 1, sequenceDiff.seq1Range.endExclusive + 1), new LineRange(sequenceDiff.seq2Range.start + 1, sequenceDiff.seq2Range.endExclusive + 1));
|
|
1524
|
+
}
|
|
1525
|
+
function arraysEqual(a, b) {
|
|
1526
|
+
if (a.length !== b.length) {
|
|
1527
|
+
return false;
|
|
1528
|
+
}
|
|
1529
|
+
for (let i = 0; i < a.length; i++) {
|
|
1530
|
+
if (a[i] !== b[i]) {
|
|
1531
|
+
return false;
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
return true;
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
/* @ts-self-types="./diff_wasm.d.ts" */
|
|
1538
|
+
|
|
1539
|
+
/**
|
|
1540
|
+
* Compute a diff between two texts.
|
|
1541
|
+
*
|
|
1542
|
+
* # Arguments
|
|
1543
|
+
* * `original` - The original text (lines separated by newlines)
|
|
1544
|
+
* * `modified` - The modified text (lines separated by newlines)
|
|
1545
|
+
* * `options` - Optional diff options (as a JavaScript object)
|
|
1546
|
+
*
|
|
1547
|
+
* # Returns
|
|
1548
|
+
* A `WasmLinesDiff` object containing the changes.
|
|
1549
|
+
* @param {string} original
|
|
1550
|
+
* @param {string} modified
|
|
1551
|
+
* @param {any} options
|
|
1552
|
+
* @returns {any}
|
|
1553
|
+
*/
|
|
1554
|
+
function computeDiff(original, modified, options) {
|
|
1555
|
+
const ptr0 = passStringToWasm0(original, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
1556
|
+
const len0 = WASM_VECTOR_LEN;
|
|
1557
|
+
const ptr1 = passStringToWasm0(modified, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
1558
|
+
const len1 = WASM_VECTOR_LEN;
|
|
1559
|
+
const ret = wasm.computeDiff(ptr0, len0, ptr1, len1, options);
|
|
1560
|
+
if (ret[2]) {
|
|
1561
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
1562
|
+
}
|
|
1563
|
+
return takeFromExternrefTable0(ret[0]);
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
/**
|
|
1567
|
+
* Compute a diff between two arrays of lines.
|
|
1568
|
+
*
|
|
1569
|
+
* # Arguments
|
|
1570
|
+
* * `original_lines` - The original lines (as a JavaScript array of strings)
|
|
1571
|
+
* * `modified_lines` - The modified lines (as a JavaScript array of strings)
|
|
1572
|
+
* * `options` - Optional diff options (as a JavaScript object)
|
|
1573
|
+
*
|
|
1574
|
+
* # Returns
|
|
1575
|
+
* A `WasmLinesDiff` object containing the changes.
|
|
1576
|
+
* @param {any} original_lines
|
|
1577
|
+
* @param {any} modified_lines
|
|
1578
|
+
* @param {any} options
|
|
1579
|
+
* @returns {any}
|
|
1580
|
+
*/
|
|
1581
|
+
function computeDiffLines(original_lines, modified_lines, options) {
|
|
1582
|
+
const ret = wasm.computeDiffLines(original_lines, modified_lines, options);
|
|
1583
|
+
if (ret[2]) {
|
|
1584
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
1585
|
+
}
|
|
1586
|
+
return takeFromExternrefTable0(ret[0]);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
/**
|
|
1590
|
+
* Initialize panic hook for better error messages in the browser console.
|
|
1591
|
+
*/
|
|
1592
|
+
function init() {
|
|
1593
|
+
wasm.init();
|
|
1594
|
+
}
|
|
1595
|
+
function __wbg_get_imports() {
|
|
1596
|
+
const import0 = {
|
|
1597
|
+
__proto__: null,
|
|
1598
|
+
__wbg_Error_ef53bc310eb298a0: function(arg0, arg1) {
|
|
1599
|
+
const ret = Error(getStringFromWasm0(arg0, arg1));
|
|
1600
|
+
return ret;
|
|
1601
|
+
},
|
|
1602
|
+
__wbg_Number_6b506e6536831eaa: function(arg0) {
|
|
1603
|
+
const ret = Number(arg0);
|
|
1604
|
+
return ret;
|
|
1605
|
+
},
|
|
1606
|
+
__wbg_String_8564e559799eccda: function(arg0, arg1) {
|
|
1607
|
+
const ret = String(arg1);
|
|
1608
|
+
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
1609
|
+
const len1 = WASM_VECTOR_LEN;
|
|
1610
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
1611
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
1612
|
+
},
|
|
1613
|
+
__wbg___wbindgen_bigint_get_as_i64_38130e98eecd467d: function(arg0, arg1) {
|
|
1614
|
+
const v = arg1;
|
|
1615
|
+
const ret = typeof(v) === 'bigint' ? v : undefined;
|
|
1616
|
+
getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
|
|
1617
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
|
|
1618
|
+
},
|
|
1619
|
+
__wbg___wbindgen_boolean_get_1a45e2c38d4d41b9: function(arg0) {
|
|
1620
|
+
const v = arg0;
|
|
1621
|
+
const ret = typeof(v) === 'boolean' ? v : undefined;
|
|
1622
|
+
return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
|
|
1623
|
+
},
|
|
1624
|
+
__wbg___wbindgen_debug_string_0accd80f45e5faa2: function(arg0, arg1) {
|
|
1625
|
+
const ret = debugString(arg1);
|
|
1626
|
+
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
1627
|
+
const len1 = WASM_VECTOR_LEN;
|
|
1628
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
1629
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
1630
|
+
},
|
|
1631
|
+
__wbg___wbindgen_in_70a403a56e771704: function(arg0, arg1) {
|
|
1632
|
+
const ret = arg0 in arg1;
|
|
1633
|
+
return ret;
|
|
1634
|
+
},
|
|
1635
|
+
__wbg___wbindgen_is_bigint_6ffd6468a9bc44b9: function(arg0) {
|
|
1636
|
+
const ret = typeof(arg0) === 'bigint';
|
|
1637
|
+
return ret;
|
|
1638
|
+
},
|
|
1639
|
+
__wbg___wbindgen_is_function_754e9f305ff6029e: function(arg0) {
|
|
1640
|
+
const ret = typeof(arg0) === 'function';
|
|
1641
|
+
return ret;
|
|
1642
|
+
},
|
|
1643
|
+
__wbg___wbindgen_is_null_87c3bfe968c6a5ad: function(arg0) {
|
|
1644
|
+
const ret = arg0 === null;
|
|
1645
|
+
return ret;
|
|
1646
|
+
},
|
|
1647
|
+
__wbg___wbindgen_is_object_56732c2bc353f41d: function(arg0) {
|
|
1648
|
+
const val = arg0;
|
|
1649
|
+
const ret = typeof(val) === 'object' && val !== null;
|
|
1650
|
+
return ret;
|
|
1651
|
+
},
|
|
1652
|
+
__wbg___wbindgen_is_undefined_67b456be8673d3d7: function(arg0) {
|
|
1653
|
+
const ret = arg0 === undefined;
|
|
1654
|
+
return ret;
|
|
1655
|
+
},
|
|
1656
|
+
__wbg___wbindgen_jsval_eq_1068e624fa87f6ab: function(arg0, arg1) {
|
|
1657
|
+
const ret = arg0 === arg1;
|
|
1658
|
+
return ret;
|
|
1659
|
+
},
|
|
1660
|
+
__wbg___wbindgen_jsval_loose_eq_2c56564c75129511: function(arg0, arg1) {
|
|
1661
|
+
const ret = arg0 == arg1;
|
|
1662
|
+
return ret;
|
|
1663
|
+
},
|
|
1664
|
+
__wbg___wbindgen_number_get_9bb1761122181af2: function(arg0, arg1) {
|
|
1665
|
+
const obj = arg1;
|
|
1666
|
+
const ret = typeof(obj) === 'number' ? obj : undefined;
|
|
1667
|
+
getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
|
|
1668
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
|
|
1669
|
+
},
|
|
1670
|
+
__wbg___wbindgen_string_get_72bdf95d3ae505b1: function(arg0, arg1) {
|
|
1671
|
+
const obj = arg1;
|
|
1672
|
+
const ret = typeof(obj) === 'string' ? obj : undefined;
|
|
1673
|
+
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
1674
|
+
var len1 = WASM_VECTOR_LEN;
|
|
1675
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
1676
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
1677
|
+
},
|
|
1678
|
+
__wbg___wbindgen_throw_1506f2235d1bdba0: function(arg0, arg1) {
|
|
1679
|
+
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
1680
|
+
},
|
|
1681
|
+
__wbg_call_8a89609d89f6608a: function() { return handleError(function (arg0, arg1) {
|
|
1682
|
+
const ret = arg0.call(arg1);
|
|
1683
|
+
return ret;
|
|
1684
|
+
}, arguments); },
|
|
1685
|
+
__wbg_done_60cf307fcc680536: function(arg0) {
|
|
1686
|
+
const ret = arg0.done;
|
|
1687
|
+
return ret;
|
|
1688
|
+
},
|
|
1689
|
+
__wbg_error_a6fa202b58aa1cd3: function(arg0, arg1) {
|
|
1690
|
+
let deferred0_0;
|
|
1691
|
+
let deferred0_1;
|
|
1692
|
+
try {
|
|
1693
|
+
deferred0_0 = arg0;
|
|
1694
|
+
deferred0_1 = arg1;
|
|
1695
|
+
console.error(getStringFromWasm0(arg0, arg1));
|
|
1696
|
+
} finally {
|
|
1697
|
+
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
|
|
1698
|
+
}
|
|
1699
|
+
},
|
|
1700
|
+
__wbg_get_1f8f054ddbaa7db2: function() { return handleError(function (arg0, arg1) {
|
|
1701
|
+
const ret = Reflect.get(arg0, arg1);
|
|
1702
|
+
return ret;
|
|
1703
|
+
}, arguments); },
|
|
1704
|
+
__wbg_get_unchecked_33f6e5c9e2f2d6b2: function(arg0, arg1) {
|
|
1705
|
+
const ret = arg0[arg1 >>> 0];
|
|
1706
|
+
return ret;
|
|
1707
|
+
},
|
|
1708
|
+
__wbg_get_with_ref_key_6412cf3094599694: function(arg0, arg1) {
|
|
1709
|
+
const ret = arg0[arg1];
|
|
1710
|
+
return ret;
|
|
1711
|
+
},
|
|
1712
|
+
__wbg_instanceof_ArrayBuffer_8f49811467741499: function(arg0) {
|
|
1713
|
+
let result;
|
|
1714
|
+
try {
|
|
1715
|
+
result = arg0 instanceof ArrayBuffer;
|
|
1716
|
+
} catch (_) {
|
|
1717
|
+
result = false;
|
|
1718
|
+
}
|
|
1719
|
+
const ret = result;
|
|
1720
|
+
return ret;
|
|
1721
|
+
},
|
|
1722
|
+
__wbg_instanceof_Uint8Array_86f30649f63ef9c2: function(arg0) {
|
|
1723
|
+
let result;
|
|
1724
|
+
try {
|
|
1725
|
+
result = arg0 instanceof Uint8Array;
|
|
1726
|
+
} catch (_) {
|
|
1727
|
+
result = false;
|
|
1728
|
+
}
|
|
1729
|
+
const ret = result;
|
|
1730
|
+
return ret;
|
|
1731
|
+
},
|
|
1732
|
+
__wbg_isArray_67c2c9c4313f4448: function(arg0) {
|
|
1733
|
+
const ret = Array.isArray(arg0);
|
|
1734
|
+
return ret;
|
|
1735
|
+
},
|
|
1736
|
+
__wbg_isSafeInteger_66acec27e09e99a7: function(arg0) {
|
|
1737
|
+
const ret = Number.isSafeInteger(arg0);
|
|
1738
|
+
return ret;
|
|
1739
|
+
},
|
|
1740
|
+
__wbg_iterator_8732428d309e270e: function() {
|
|
1741
|
+
const ret = Symbol.iterator;
|
|
1742
|
+
return ret;
|
|
1743
|
+
},
|
|
1744
|
+
__wbg_length_4a591ecaa01354d9: function(arg0) {
|
|
1745
|
+
const ret = arg0.length;
|
|
1746
|
+
return ret;
|
|
1747
|
+
},
|
|
1748
|
+
__wbg_length_66f1a4b2e9026940: function(arg0) {
|
|
1749
|
+
const ret = arg0.length;
|
|
1750
|
+
return ret;
|
|
1751
|
+
},
|
|
1752
|
+
__wbg_new_227d7c05414eb861: function() {
|
|
1753
|
+
const ret = new Error();
|
|
1754
|
+
return ret;
|
|
1755
|
+
},
|
|
1756
|
+
__wbg_new_578aeef4b6b94378: function(arg0) {
|
|
1757
|
+
const ret = new Uint8Array(arg0);
|
|
1758
|
+
return ret;
|
|
1759
|
+
},
|
|
1760
|
+
__wbg_new_ce1ab61c1c2b300d: function() {
|
|
1761
|
+
const ret = new Object();
|
|
1762
|
+
return ret;
|
|
1763
|
+
},
|
|
1764
|
+
__wbg_new_d90091b82fdf5b91: function() {
|
|
1765
|
+
const ret = new Array();
|
|
1766
|
+
return ret;
|
|
1767
|
+
},
|
|
1768
|
+
__wbg_next_9e03acdf51c4960d: function(arg0) {
|
|
1769
|
+
const ret = arg0.next;
|
|
1770
|
+
return ret;
|
|
1771
|
+
},
|
|
1772
|
+
__wbg_next_eb8ca7351fa27906: function() { return handleError(function (arg0) {
|
|
1773
|
+
const ret = arg0.next();
|
|
1774
|
+
return ret;
|
|
1775
|
+
}, arguments); },
|
|
1776
|
+
__wbg_prototypesetcall_3249fc62a0fafa30: function(arg0, arg1, arg2) {
|
|
1777
|
+
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
|
|
1778
|
+
},
|
|
1779
|
+
__wbg_set_6be42768c690e380: function(arg0, arg1, arg2) {
|
|
1780
|
+
arg0[arg1] = arg2;
|
|
1781
|
+
},
|
|
1782
|
+
__wbg_set_dca99999bba88a9a: function(arg0, arg1, arg2) {
|
|
1783
|
+
arg0[arg1 >>> 0] = arg2;
|
|
1784
|
+
},
|
|
1785
|
+
__wbg_stack_3b0d974bbf31e44f: function(arg0, arg1) {
|
|
1786
|
+
const ret = arg1.stack;
|
|
1787
|
+
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
1788
|
+
const len1 = WASM_VECTOR_LEN;
|
|
1789
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
1790
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
1791
|
+
},
|
|
1792
|
+
__wbg_value_f3625092ee4b37f4: function(arg0) {
|
|
1793
|
+
const ret = arg0.value;
|
|
1794
|
+
return ret;
|
|
1795
|
+
},
|
|
1796
|
+
__wbindgen_cast_0000000000000001: function(arg0) {
|
|
1797
|
+
// Cast intrinsic for `F64 -> Externref`.
|
|
1798
|
+
const ret = arg0;
|
|
1799
|
+
return ret;
|
|
1800
|
+
},
|
|
1801
|
+
__wbindgen_cast_0000000000000002: function(arg0, arg1) {
|
|
1802
|
+
// Cast intrinsic for `Ref(String) -> Externref`.
|
|
1803
|
+
const ret = getStringFromWasm0(arg0, arg1);
|
|
1804
|
+
return ret;
|
|
1805
|
+
},
|
|
1806
|
+
__wbindgen_cast_0000000000000003: function(arg0) {
|
|
1807
|
+
// Cast intrinsic for `U64 -> Externref`.
|
|
1808
|
+
const ret = BigInt.asUintN(64, arg0);
|
|
1809
|
+
return ret;
|
|
1810
|
+
},
|
|
1811
|
+
__wbindgen_init_externref_table: function() {
|
|
1812
|
+
const table = wasm.__wbindgen_externrefs;
|
|
1813
|
+
const offset = table.grow(4);
|
|
1814
|
+
table.set(0, undefined);
|
|
1815
|
+
table.set(offset + 0, undefined);
|
|
1816
|
+
table.set(offset + 1, null);
|
|
1817
|
+
table.set(offset + 2, true);
|
|
1818
|
+
table.set(offset + 3, false);
|
|
1819
|
+
},
|
|
1820
|
+
};
|
|
1821
|
+
return {
|
|
1822
|
+
__proto__: null,
|
|
1823
|
+
"./diff_wasm_bg.js": import0,
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
function addToExternrefTable0(obj) {
|
|
1828
|
+
const idx = wasm.__externref_table_alloc();
|
|
1829
|
+
wasm.__wbindgen_externrefs.set(idx, obj);
|
|
1830
|
+
return idx;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
function debugString(val) {
|
|
1834
|
+
// primitive types
|
|
1835
|
+
const type = typeof val;
|
|
1836
|
+
if (type == 'number' || type == 'boolean' || val == null) {
|
|
1837
|
+
return `${val}`;
|
|
1838
|
+
}
|
|
1839
|
+
if (type == 'string') {
|
|
1840
|
+
return `"${val}"`;
|
|
1841
|
+
}
|
|
1842
|
+
if (type == 'symbol') {
|
|
1843
|
+
const description = val.description;
|
|
1844
|
+
if (description == null) {
|
|
1845
|
+
return 'Symbol';
|
|
1846
|
+
} else {
|
|
1847
|
+
return `Symbol(${description})`;
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
if (type == 'function') {
|
|
1851
|
+
const name = val.name;
|
|
1852
|
+
if (typeof name == 'string' && name.length > 0) {
|
|
1853
|
+
return `Function(${name})`;
|
|
1854
|
+
} else {
|
|
1855
|
+
return 'Function';
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
// objects
|
|
1859
|
+
if (Array.isArray(val)) {
|
|
1860
|
+
const length = val.length;
|
|
1861
|
+
let debug = '[';
|
|
1862
|
+
if (length > 0) {
|
|
1863
|
+
debug += debugString(val[0]);
|
|
1864
|
+
}
|
|
1865
|
+
for(let i = 1; i < length; i++) {
|
|
1866
|
+
debug += ', ' + debugString(val[i]);
|
|
1867
|
+
}
|
|
1868
|
+
debug += ']';
|
|
1869
|
+
return debug;
|
|
1870
|
+
}
|
|
1871
|
+
// Test for built-in
|
|
1872
|
+
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
|
|
1873
|
+
let className;
|
|
1874
|
+
if (builtInMatches && builtInMatches.length > 1) {
|
|
1875
|
+
className = builtInMatches[1];
|
|
1876
|
+
} else {
|
|
1877
|
+
// Failed to match the standard '[object ClassName]'
|
|
1878
|
+
return toString.call(val);
|
|
1879
|
+
}
|
|
1880
|
+
if (className == 'Object') {
|
|
1881
|
+
// we're a user defined class or Object
|
|
1882
|
+
// JSON.stringify avoids problems with cycles, and is generally much
|
|
1883
|
+
// easier than looping through ownProperties of `val`.
|
|
1884
|
+
try {
|
|
1885
|
+
return 'Object(' + JSON.stringify(val) + ')';
|
|
1886
|
+
} catch (_) {
|
|
1887
|
+
return 'Object';
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
// errors
|
|
1891
|
+
if (val instanceof Error) {
|
|
1892
|
+
return `${val.name}: ${val.message}\n${val.stack}`;
|
|
1893
|
+
}
|
|
1894
|
+
// TODO we could test for more things here, like `Set`s and `Map`s.
|
|
1895
|
+
return className;
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
function getArrayU8FromWasm0(ptr, len) {
|
|
1899
|
+
ptr = ptr >>> 0;
|
|
1900
|
+
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
let cachedDataViewMemory0 = null;
|
|
1904
|
+
function getDataViewMemory0() {
|
|
1905
|
+
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
|
1906
|
+
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
|
1907
|
+
}
|
|
1908
|
+
return cachedDataViewMemory0;
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
function getStringFromWasm0(ptr, len) {
|
|
1912
|
+
return decodeText(ptr >>> 0, len);
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
let cachedUint8ArrayMemory0 = null;
|
|
1916
|
+
function getUint8ArrayMemory0() {
|
|
1917
|
+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
1918
|
+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
|
1919
|
+
}
|
|
1920
|
+
return cachedUint8ArrayMemory0;
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
function handleError(f, args) {
|
|
1924
|
+
try {
|
|
1925
|
+
return f.apply(this, args);
|
|
1926
|
+
} catch (e) {
|
|
1927
|
+
const idx = addToExternrefTable0(e);
|
|
1928
|
+
wasm.__wbindgen_exn_store(idx);
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
function isLikeNone(x) {
|
|
1933
|
+
return x === undefined || x === null;
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
function passStringToWasm0(arg, malloc, realloc) {
|
|
1937
|
+
if (realloc === undefined) {
|
|
1938
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
1939
|
+
const ptr = malloc(buf.length, 1) >>> 0;
|
|
1940
|
+
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
1941
|
+
WASM_VECTOR_LEN = buf.length;
|
|
1942
|
+
return ptr;
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
let len = arg.length;
|
|
1946
|
+
let ptr = malloc(len, 1) >>> 0;
|
|
1947
|
+
|
|
1948
|
+
const mem = getUint8ArrayMemory0();
|
|
1949
|
+
|
|
1950
|
+
let offset = 0;
|
|
1951
|
+
|
|
1952
|
+
for (; offset < len; offset++) {
|
|
1953
|
+
const code = arg.charCodeAt(offset);
|
|
1954
|
+
if (code > 0x7F) break;
|
|
1955
|
+
mem[ptr + offset] = code;
|
|
1956
|
+
}
|
|
1957
|
+
if (offset !== len) {
|
|
1958
|
+
if (offset !== 0) {
|
|
1959
|
+
arg = arg.slice(offset);
|
|
1960
|
+
}
|
|
1961
|
+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
|
1962
|
+
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
|
1963
|
+
const ret = cachedTextEncoder.encodeInto(arg, view);
|
|
1964
|
+
|
|
1965
|
+
offset += ret.written;
|
|
1966
|
+
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1969
|
+
WASM_VECTOR_LEN = offset;
|
|
1970
|
+
return ptr;
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
function takeFromExternrefTable0(idx) {
|
|
1974
|
+
const value = wasm.__wbindgen_externrefs.get(idx);
|
|
1975
|
+
wasm.__externref_table_dealloc(idx);
|
|
1976
|
+
return value;
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
1980
|
+
cachedTextDecoder.decode();
|
|
1981
|
+
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
|
1982
|
+
let numBytesDecoded = 0;
|
|
1983
|
+
function decodeText(ptr, len) {
|
|
1984
|
+
numBytesDecoded += len;
|
|
1985
|
+
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
|
|
1986
|
+
cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
1987
|
+
cachedTextDecoder.decode();
|
|
1988
|
+
numBytesDecoded = len;
|
|
1989
|
+
}
|
|
1990
|
+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
const cachedTextEncoder = new TextEncoder();
|
|
1994
|
+
|
|
1995
|
+
if (!('encodeInto' in cachedTextEncoder)) {
|
|
1996
|
+
cachedTextEncoder.encodeInto = function (arg, view) {
|
|
1997
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
1998
|
+
view.set(buf);
|
|
1999
|
+
return {
|
|
2000
|
+
read: arg.length,
|
|
2001
|
+
written: buf.length
|
|
2002
|
+
};
|
|
2003
|
+
};
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
let WASM_VECTOR_LEN = 0;
|
|
2007
|
+
|
|
2008
|
+
let wasm;
|
|
2009
|
+
function __wbg_finalize_init(instance, module) {
|
|
2010
|
+
wasm = instance.exports;
|
|
2011
|
+
cachedDataViewMemory0 = null;
|
|
2012
|
+
cachedUint8ArrayMemory0 = null;
|
|
2013
|
+
wasm.__wbindgen_start();
|
|
2014
|
+
return wasm;
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
async function __wbg_load(module, imports) {
|
|
2018
|
+
if (typeof Response === 'function' && module instanceof Response) {
|
|
2019
|
+
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
|
2020
|
+
try {
|
|
2021
|
+
return await WebAssembly.instantiateStreaming(module, imports);
|
|
2022
|
+
} catch (e) {
|
|
2023
|
+
const validResponse = module.ok && expectedResponseType(module.type);
|
|
2024
|
+
|
|
2025
|
+
if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
|
|
2026
|
+
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
|
2027
|
+
|
|
2028
|
+
} else { throw e; }
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
const bytes = await module.arrayBuffer();
|
|
2033
|
+
return await WebAssembly.instantiate(bytes, imports);
|
|
2034
|
+
} else {
|
|
2035
|
+
const instance = await WebAssembly.instantiate(module, imports);
|
|
2036
|
+
|
|
2037
|
+
if (instance instanceof WebAssembly.Instance) {
|
|
2038
|
+
return { instance, module };
|
|
2039
|
+
} else {
|
|
2040
|
+
return instance;
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
function expectedResponseType(type) {
|
|
2045
|
+
switch (type) {
|
|
2046
|
+
case 'basic': case 'cors': case 'default': return true;
|
|
2047
|
+
}
|
|
2048
|
+
return false;
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
function initSync(module) {
|
|
2053
|
+
if (wasm !== undefined) return wasm;
|
|
2054
|
+
|
|
2055
|
+
|
|
2056
|
+
if (module !== undefined) {
|
|
2057
|
+
if (Object.getPrototypeOf(module) === Object.prototype) {
|
|
2058
|
+
({module} = module);
|
|
2059
|
+
} else {
|
|
2060
|
+
console.warn('using deprecated parameters for `initSync()`; pass a single object instead');
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
const imports = __wbg_get_imports();
|
|
2065
|
+
if (!(module instanceof WebAssembly.Module)) {
|
|
2066
|
+
module = new WebAssembly.Module(module);
|
|
2067
|
+
}
|
|
2068
|
+
const instance = new WebAssembly.Instance(module, imports);
|
|
2069
|
+
return __wbg_finalize_init(instance);
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
async function __wbg_init(module_or_path) {
|
|
2073
|
+
if (wasm !== undefined) return wasm;
|
|
2074
|
+
|
|
2075
|
+
|
|
2076
|
+
if (module_or_path !== undefined) {
|
|
2077
|
+
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
|
|
2078
|
+
({module_or_path} = module_or_path);
|
|
2079
|
+
} else {
|
|
2080
|
+
console.warn('using deprecated parameters for the initialization function; pass a single object instead');
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
if (module_or_path === undefined) {
|
|
2085
|
+
module_or_path = new URL(new URL(/* asset import */ __webpack_require__(/*! diff_wasm_bg-c6YkaZRL.wasm */ "./node_modules/@vscode/diff/dist/diff_wasm_bg-c6YkaZRL.wasm"), __webpack_require__.b).href);
|
|
2086
|
+
}
|
|
2087
|
+
const imports = __wbg_get_imports();
|
|
2088
|
+
|
|
2089
|
+
if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
|
|
2090
|
+
module_or_path = fetch(module_or_path);
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
const { instance, module } = await __wbg_load(await module_or_path, imports);
|
|
2094
|
+
|
|
2095
|
+
return __wbg_finalize_init(instance);
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
var wasm$1 = /*#__PURE__*/Object.freeze({
|
|
2099
|
+
__proto__: null,
|
|
2100
|
+
computeDiff: computeDiff,
|
|
2101
|
+
computeDiffLines: computeDiffLines,
|
|
2102
|
+
default: __wbg_init,
|
|
2103
|
+
init: init,
|
|
2104
|
+
initSync: initSync
|
|
2105
|
+
});
|
|
2106
|
+
|
|
2107
|
+
/**
|
|
2108
|
+
* WASM module loader.
|
|
2109
|
+
*
|
|
2110
|
+
* Handles async initialization of the WASM module.
|
|
2111
|
+
*/
|
|
2112
|
+
// @ts-ignore -- generated at build time by `npm run build:wasm` (wasm-pack --target web).
|
|
2113
|
+
let wasmModule = null;
|
|
2114
|
+
let initPromise = null;
|
|
2115
|
+
/**
|
|
2116
|
+
* Initialize the WASM module.
|
|
2117
|
+
*
|
|
2118
|
+
* This must be called before using any WASM-based diff functions.
|
|
2119
|
+
* It's safe to call multiple times — subsequent calls are no-ops.
|
|
2120
|
+
*
|
|
2121
|
+
* @returns Promise that resolves when WASM is ready
|
|
2122
|
+
*/
|
|
2123
|
+
async function initWasm() {
|
|
2124
|
+
if (wasmModule) {
|
|
2125
|
+
return wasmModule;
|
|
2126
|
+
}
|
|
2127
|
+
if (initPromise) {
|
|
2128
|
+
return initPromise;
|
|
2129
|
+
}
|
|
2130
|
+
initPromise = (async () => {
|
|
2131
|
+
const wasmUrl = new URL(new URL(/* asset import */ __webpack_require__(/*! diff_wasm_bg-c6YkaZRL.wasm */ "./node_modules/@vscode/diff/dist/diff_wasm_bg-c6YkaZRL.wasm"), __webpack_require__.b).href);
|
|
2132
|
+
// Node's undici fetch does not support file:// URLs, so read bytes ourselves.
|
|
2133
|
+
let source = wasmUrl;
|
|
2134
|
+
if (typeof process !== 'undefined' && process.versions?.node) {
|
|
2135
|
+
const { readFile } = await __webpack_require__.e(/*! import() */ "node_fs_promises").then(__webpack_require__.t.bind(__webpack_require__, /*! node:fs/promises */ "node:fs/promises", 19));
|
|
2136
|
+
source = await readFile(wasmUrl);
|
|
2137
|
+
}
|
|
2138
|
+
await __wbg_init({ module_or_path: source });
|
|
2139
|
+
init();
|
|
2140
|
+
wasmModule = wasm$1;
|
|
2141
|
+
return wasmModule;
|
|
2142
|
+
})();
|
|
2143
|
+
return initPromise;
|
|
2144
|
+
}
|
|
2145
|
+
/**
|
|
2146
|
+
* Get the WASM module synchronously.
|
|
2147
|
+
*
|
|
2148
|
+
* @throws Error if WASM hasn't been initialized yet
|
|
2149
|
+
* @returns The WASM module
|
|
2150
|
+
*/
|
|
2151
|
+
function getWasm() {
|
|
2152
|
+
if (!wasmModule) {
|
|
2153
|
+
throw new Error('WASM not initialized. Call initWasm() first and await it.');
|
|
2154
|
+
}
|
|
2155
|
+
return wasmModule;
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
/**
|
|
2159
|
+
* Conversions between `LinesDiff` (in-memory class instances) and
|
|
2160
|
+
* `WireLinesDiff` (plain JSON-friendly shape used on the worker boundary).
|
|
2161
|
+
*/
|
|
2162
|
+
function linesDiffToWire(diff) {
|
|
2163
|
+
return {
|
|
2164
|
+
changes: diff.changes.map(detailedToWire),
|
|
2165
|
+
moves: diff.moves.map(moveToWire),
|
|
2166
|
+
hitTimeout: diff.hitTimeout,
|
|
2167
|
+
};
|
|
2168
|
+
}
|
|
2169
|
+
function wireToLinesDiff(wire) {
|
|
2170
|
+
const changes = wire.changes.map(wireToDetailed);
|
|
2171
|
+
const moves = wire.moves.map(wireToMove);
|
|
2172
|
+
return new LinesDiff(changes, moves, wire.hitTimeout);
|
|
2173
|
+
}
|
|
2174
|
+
function detailedToWire(m) {
|
|
2175
|
+
return {
|
|
2176
|
+
original: {
|
|
2177
|
+
startLineNumber: m.original.startLineNumber,
|
|
2178
|
+
endLineNumberExclusive: m.original.endLineNumberExclusive,
|
|
2179
|
+
},
|
|
2180
|
+
modified: {
|
|
2181
|
+
startLineNumber: m.modified.startLineNumber,
|
|
2182
|
+
endLineNumberExclusive: m.modified.endLineNumberExclusive,
|
|
2183
|
+
},
|
|
2184
|
+
innerChanges: m.innerChanges ? m.innerChanges.map(rangeMappingToWire) : null,
|
|
2185
|
+
};
|
|
2186
|
+
}
|
|
2187
|
+
function wireToDetailed(m) {
|
|
2188
|
+
const inner = m.innerChanges?.map(wireToRangeMapping);
|
|
2189
|
+
return new DetailedLineRangeMapping(new LineRange(m.original.startLineNumber, m.original.endLineNumberExclusive), new LineRange(m.modified.startLineNumber, m.modified.endLineNumberExclusive), inner);
|
|
2190
|
+
}
|
|
2191
|
+
function rangeMappingToWire(rm) {
|
|
2192
|
+
return {
|
|
2193
|
+
originalStartLine: rm.originalRange.startLineNumber,
|
|
2194
|
+
originalStartColumn: rm.originalRange.startColumn,
|
|
2195
|
+
originalEndLine: rm.originalRange.endLineNumber,
|
|
2196
|
+
originalEndColumn: rm.originalRange.endColumn,
|
|
2197
|
+
modifiedStartLine: rm.modifiedRange.startLineNumber,
|
|
2198
|
+
modifiedStartColumn: rm.modifiedRange.startColumn,
|
|
2199
|
+
modifiedEndLine: rm.modifiedRange.endLineNumber,
|
|
2200
|
+
modifiedEndColumn: rm.modifiedRange.endColumn,
|
|
2201
|
+
};
|
|
2202
|
+
}
|
|
2203
|
+
function wireToRangeMapping(rm) {
|
|
2204
|
+
return new RangeMapping(new Range(rm.originalStartLine, rm.originalStartColumn, rm.originalEndLine, rm.originalEndColumn), new Range(rm.modifiedStartLine, rm.modifiedStartColumn, rm.modifiedEndLine, rm.modifiedEndColumn));
|
|
2205
|
+
}
|
|
2206
|
+
function moveToWire(m) {
|
|
2207
|
+
return {
|
|
2208
|
+
lineRangeMapping: {
|
|
2209
|
+
original: {
|
|
2210
|
+
startLineNumber: m.lineRangeMapping.original.startLineNumber,
|
|
2211
|
+
endLineNumberExclusive: m.lineRangeMapping.original.endLineNumberExclusive,
|
|
2212
|
+
},
|
|
2213
|
+
modified: {
|
|
2214
|
+
startLineNumber: m.lineRangeMapping.modified.startLineNumber,
|
|
2215
|
+
endLineNumberExclusive: m.lineRangeMapping.modified.endLineNumberExclusive,
|
|
2216
|
+
},
|
|
2217
|
+
},
|
|
2218
|
+
changes: m.changes.map(detailedToWire),
|
|
2219
|
+
};
|
|
2220
|
+
}
|
|
2221
|
+
function wireToMove(m) {
|
|
2222
|
+
const lrm = new LineRangeMapping(new LineRange(m.lineRangeMapping.original.startLineNumber, m.lineRangeMapping.original.endLineNumberExclusive), new LineRange(m.lineRangeMapping.modified.startLineNumber, m.lineRangeMapping.modified.endLineNumberExclusive));
|
|
2223
|
+
return new MovedText(lrm, m.changes.map(wireToDetailed));
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
|
|
2227
|
+
//# sourceMappingURL=wire.js.map
|
|
2228
|
+
|
|
2229
|
+
|
|
2230
|
+
/***/ }
|
|
2231
|
+
|
|
2232
|
+
}]);
|
|
2233
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVuZG9ycy1ub2RlX21vZHVsZXNfdnNjb2RlX2RpZmZfZGlzdF93aXJlX2pzLm1haW4uanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsTUFBTSxJQUFJLGFBQWE7QUFDdEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFdBQVcsSUFBSSxrQkFBa0I7QUFDcEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixjQUFjLE1BQU0sYUFBYTtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLGdCQUFnQixNQUFNLGVBQWU7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5Qix1QkFBdUI7QUFDaEQsNkJBQTZCLHVCQUF1QjtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0IsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQyxRQUFRO0FBQ25EO0FBQ0E7QUFDQSxpQ0FBaUMsaUJBQWlCO0FBQ2xEO0FBQ0EsNkVBQTZFO0FBQzdFLGtGQUFrRjtBQUNsRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLFdBQVc7QUFDdkI7QUFDQTtBQUNBO0FBQ0EsWUFBWSxnQkFBZ0I7QUFDNUI7QUFDQSxxQkFBcUIsa0JBQWtCLEdBQUc7QUFDMUMsb0JBQW9CLHNCQUFzQjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLDBCQUEwQjtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLGFBQWE7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQix1QkFBdUI7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QixZQUFZO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLDBCQUEwQjtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMscUJBQXFCO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLGtCQUFrQjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0Isa0JBQWtCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxvQkFBb0Isa0JBQWtCO0FBQ3RDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRCx5Q0FBeUM7QUFDcEc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLGdCQUFnQjtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsVUFBVTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsaUJBQWlCLElBQUksdUJBQXVCO0FBQzFGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLHFCQUFxQixJQUFJLDRCQUE0QjtBQUN4RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixtQ0FBbUMsTUFBTSxrQ0FBa0M7QUFDN0Y7QUFDQTtBQUNBLHdCQUF3QiwwQkFBMEI7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLHNCQUFzQixHQUFHLGtCQUFrQixLQUFLLG9CQUFvQixHQUFHLGdCQUFnQjtBQUN0RztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsZUFBZSxNQUFNLGNBQWM7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0Isb0JBQW9CO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLHFCQUFxQjtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixjQUFjO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsV0FBVyxLQUFLO0FBQ2hCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEtBQUs7QUFDaEIsV0FBVyxLQUFLO0FBQ2hCLFdBQVcsS0FBSztBQUNoQixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNULGtEQUFrRDtBQUNsRDtBQUNBO0FBQ0EsU0FBUyxlQUFlO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0EsU0FBUztBQUNULGlEQUFpRDtBQUNqRDtBQUNBO0FBQ0EsU0FBUyxlQUFlO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULGtEQUFrRDtBQUNsRDtBQUNBO0FBQ0EsU0FBUyxlQUFlO0FBQ3hCO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixJQUFJO0FBQ3ZCO0FBQ0E7QUFDQSxtQkFBbUIsSUFBSTtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWLDZCQUE2QixZQUFZO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0IsS0FBSztBQUNwQyxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsWUFBWTtBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixTQUFTLElBQUksWUFBWSxJQUFJLFVBQVU7QUFDekQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLFdBQVcsY0FBYztBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxtREFBbUQsOEJBQThCO0FBQ2pGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVEQUF1RCw4QkFBOEI7QUFDckY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUE7QUFDQTs7QUFFQSxrQkFBa0IsT0FBTztBQUN6QjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxNQUFNO0FBQ047O0FBRUE7QUFDQSxxQkFBcUI7QUFDckIsVUFBVTtBQUNWO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLFVBQVU7QUFDVix3RUFBd0U7QUFDeEU7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsY0FBYyxnQkFBZ0I7QUFDOUIsVUFBVTtBQUNWLHVGQUF1RjtBQUN2RjtBQUNBOztBQUVBO0FBQ0EseUNBQXlDLDhKQUE2QztBQUN0RjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxZQUFZLG1CQUFtQjs7QUFFL0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDLDhKQUE2QztBQUNyRjtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsV0FBVyxRQUFRLCtKQUEwQjtBQUNqRTtBQUNBO0FBQ0EsMkJBQTJCLHdCQUF3QjtBQUNuRDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRXlQO0FBQ3pQIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vamRlcm9ib3QtaWRlLWludGVyZmFjZS8uL25vZGVfbW9kdWxlcy9AdnNjb2RlL2RpZmYvZGlzdC93aXJlLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiAgQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cbiAqLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuLyoqXG4gKiBBIHJhbmdlIG9mIG9mZnNldHMgKDAtYmFzZWQpLlxuICovXG5jbGFzcyBPZmZzZXRSYW5nZSB7XG4gICAgc3RhcnQ7XG4gICAgZW5kRXhjbHVzaXZlO1xuICAgIHN0YXRpYyBvZkxlbmd0aChsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBPZmZzZXRSYW5nZSgwLCBsZW5ndGgpO1xuICAgIH1cbiAgICBzdGF0aWMgb2ZTdGFydEFuZExlbmd0aChzdGFydCwgbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBuZXcgT2Zmc2V0UmFuZ2Uoc3RhcnQsIHN0YXJ0ICsgbGVuZ3RoKTtcbiAgICB9XG4gICAgY29uc3RydWN0b3Ioc3RhcnQsIGVuZEV4Y2x1c2l2ZSkge1xuICAgICAgICB0aGlzLnN0YXJ0ID0gc3RhcnQ7XG4gICAgICAgIHRoaXMuZW5kRXhjbHVzaXZlID0gZW5kRXhjbHVzaXZlO1xuICAgICAgICBpZiAoc3RhcnQgPiBlbmRFeGNsdXNpdmUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByYW5nZTogWyR7c3RhcnR9LCAke2VuZEV4Y2x1c2l2ZX0pYCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZ2V0IGlzRW1wdHkoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXJ0ID09PSB0aGlzLmVuZEV4Y2x1c2l2ZTtcbiAgICB9XG4gICAgZ2V0IGxlbmd0aCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW5kRXhjbHVzaXZlIC0gdGhpcy5zdGFydDtcbiAgICB9XG4gICAgZGVsdGEob2Zmc2V0KSB7XG4gICAgICAgIHJldHVybiBuZXcgT2Zmc2V0UmFuZ2UodGhpcy5zdGFydCArIG9mZnNldCwgdGhpcy5lbmRFeGNsdXNpdmUgKyBvZmZzZXQpO1xuICAgIH1cbiAgICBkZWx0YVN0YXJ0KG9mZnNldCkge1xuICAgICAgICByZXR1cm4gbmV3IE9mZnNldFJhbmdlKHRoaXMuc3RhcnQgKyBvZmZzZXQsIHRoaXMuZW5kRXhjbHVzaXZlKTtcbiAgICB9XG4gICAgZGVsdGFFbmQob2Zmc2V0KSB7XG4gICAgICAgIHJldHVybiBuZXcgT2Zmc2V0UmFuZ2UodGhpcy5zdGFydCwgdGhpcy5lbmRFeGNsdXNpdmUgKyBvZmZzZXQpO1xuICAgIH1cbiAgICBlcXVhbHMob3RoZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnQgPT09IG90aGVyLnN0YXJ0ICYmIHRoaXMuZW5kRXhjbHVzaXZlID09PSBvdGhlci5lbmRFeGNsdXNpdmU7XG4gICAgfVxuICAgIGNvbnRhaW5zUmFuZ2Uob3RoZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnQgPD0gb3RoZXIuc3RhcnQgJiYgb3RoZXIuZW5kRXhjbHVzaXZlIDw9IHRoaXMuZW5kRXhjbHVzaXZlO1xuICAgIH1cbiAgICBjb250YWlucyhvZmZzZXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnQgPD0gb2Zmc2V0ICYmIG9mZnNldCA8IHRoaXMuZW5kRXhjbHVzaXZlO1xuICAgIH1cbiAgICBqb2luKG90aGVyKSB7XG4gICAgICAgIHJldHVybiBuZXcgT2Zmc2V0UmFuZ2UoTWF0aC5taW4odGhpcy5zdGFydCwgb3RoZXIuc3RhcnQpLCBNYXRoLm1heCh0aGlzLmVuZEV4Y2x1c2l2ZSwgb3RoZXIuZW5kRXhjbHVzaXZlKSk7XG4gICAgfVxuICAgIGludGVyc2VjdChvdGhlcikge1xuICAgICAgICBjb25zdCBzdGFydCA9IE1hdGgubWF4KHRoaXMuc3RhcnQsIG90aGVyLnN0YXJ0KTtcbiAgICAgICAgY29uc3QgZW5kID0gTWF0aC5taW4odGhpcy5lbmRFeGNsdXNpdmUsIG90aGVyLmVuZEV4Y2x1c2l2ZSk7XG4gICAgICAgIGlmIChzdGFydCA8PSBlbmQpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgT2Zmc2V0UmFuZ2Uoc3RhcnQsIGVuZCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgaW50ZXJzZWN0cyhvdGhlcikge1xuICAgICAgICBjb25zdCBzdGFydCA9IE1hdGgubWF4KHRoaXMuc3RhcnQsIG90aGVyLnN0YXJ0KTtcbiAgICAgICAgY29uc3QgZW5kID0gTWF0aC5taW4odGhpcy5lbmRFeGNsdXNpdmUsIG90aGVyLmVuZEV4Y2x1c2l2ZSk7XG4gICAgICAgIHJldHVybiBzdGFydCA8IGVuZDtcbiAgICB9XG4gICAgaW50ZXJzZWN0c09yVG91Y2hlcyhvdGhlcikge1xuICAgICAgICBjb25zdCBzdGFydCA9IE1hdGgubWF4KHRoaXMuc3RhcnQsIG90aGVyLnN0YXJ0KTtcbiAgICAgICAgY29uc3QgZW5kID0gTWF0aC5taW4odGhpcy5lbmRFeGNsdXNpdmUsIG90aGVyLmVuZEV4Y2x1c2l2ZSk7XG4gICAgICAgIHJldHVybiBzdGFydCA8PSBlbmQ7XG4gICAgfVxuICAgIHNsaWNlKGFycikge1xuICAgICAgICByZXR1cm4gYXJyLnNsaWNlKHRoaXMuc3RhcnQsIHRoaXMuZW5kRXhjbHVzaXZlKTtcbiAgICB9XG4gICAgdG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiBgWyR7dGhpcy5zdGFydH0sICR7dGhpcy5lbmRFeGNsdXNpdmV9KWA7XG4gICAgfVxufVxuXG5jbGFzcyBJbmZpbml0ZVRpbWVvdXQge1xuICAgIHN0YXRpYyBpbnN0YW5jZSA9IG5ldyBJbmZpbml0ZVRpbWVvdXQoKTtcbiAgICBpc1ZhbGlkKCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59XG5jbGFzcyBEYXRlVGltZW91dCB7XG4gICAgdGltZW91dDtcbiAgICBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIHZhbGlkID0gdHJ1ZTtcbiAgICBjb25zdHJ1Y3Rvcih0aW1lb3V0KSB7XG4gICAgICAgIHRoaXMudGltZW91dCA9IHRpbWVvdXQ7XG4gICAgICAgIGlmICh0aW1lb3V0IDw9IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndGltZW91dCBtdXN0IGJlIHBvc2l0aXZlJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaXNWYWxpZCgpIHtcbiAgICAgICAgY29uc3QgdmFsaWQgPSBEYXRlLm5vdygpIC0gdGhpcy5zdGFydFRpbWUgPCB0aGlzLnRpbWVvdXQ7XG4gICAgICAgIGlmICghdmFsaWQgJiYgdGhpcy52YWxpZCkge1xuICAgICAgICAgICAgdGhpcy52YWxpZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnZhbGlkO1xuICAgIH1cbn1cbi8qKlxuICogUmVwcmVzZW50cyBhbiBvZmZzZXQgcGFpciBmb3IgdHdvIHNlcXVlbmNlcy5cbiAqL1xuY2xhc3MgT2Zmc2V0UGFpciB7XG4gICAgb2Zmc2V0MTtcbiAgICBvZmZzZXQyO1xuICAgIHN0YXRpYyB6ZXJvID0gbmV3IE9mZnNldFBhaXIoMCwgMCk7XG4gICAgc3RhdGljIG1heCA9IG5ldyBPZmZzZXRQYWlyKE51bWJlci5NQVhfU0FGRV9JTlRFR0VSLCBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUik7XG4gICAgY29uc3RydWN0b3Iob2Zmc2V0MSwgb2Zmc2V0Mikge1xuICAgICAgICB0aGlzLm9mZnNldDEgPSBvZmZzZXQxO1xuICAgICAgICB0aGlzLm9mZnNldDIgPSBvZmZzZXQyO1xuICAgIH1cbiAgICB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIGAke3RoaXMub2Zmc2V0MX0gPC0+ICR7dGhpcy5vZmZzZXQyfWA7XG4gICAgfVxuICAgIGRlbHRhKG9mZnNldCkge1xuICAgICAgICBpZiAob2Zmc2V0ID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IE9mZnNldFBhaXIodGhpcy5vZmZzZXQxICsgb2Zmc2V0LCB0aGlzLm9mZnNldDIgKyBvZmZzZXQpO1xuICAgIH1cbiAgICBlcXVhbHMob3RoZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub2Zmc2V0MSA9PT0gb3RoZXIub2Zmc2V0MSAmJiB0aGlzLm9mZnNldDIgPT09IG90aGVyLm9mZnNldDI7XG4gICAgfVxufVxuLyoqXG4gKiBSZXByZXNlbnRzIGEgZGlmZiBiZXR3ZWVuIHR3byBzZXF1ZW5jZXMuXG4gKi9cbmNsYXNzIFNlcXVlbmNlRGlmZiB7XG4gICAgc2VxMVJhbmdlO1xuICAgIHNlcTJSYW5nZTtcbiAgICBzdGF0aWMgaW52ZXJ0KHNlcXVlbmNlRGlmZnMsIGRvYzFMZW5ndGgpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgICAgIGZvckVhY2hBZGphY2VudChzZXF1ZW5jZURpZmZzLCAoYSwgYikgPT4ge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2goU2VxdWVuY2VEaWZmLmZyb21PZmZzZXRQYWlycyhhID8gYS5nZXRFbmRFeGNsdXNpdmVzKCkgOiBPZmZzZXRQYWlyLnplcm8sIGIgPyBiLmdldFN0YXJ0cygpIDogbmV3IE9mZnNldFBhaXIoZG9jMUxlbmd0aCwgKGEgPyBhLnNlcTJSYW5nZS5lbmRFeGNsdXNpdmUgLSBhLnNlcTFSYW5nZS5lbmRFeGNsdXNpdmUgOiAwKSArIGRvYzFMZW5ndGgpKSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICBzdGF0aWMgZnJvbU9mZnNldFBhaXJzKHN0YXJ0LCBlbmRFeGNsdXNpdmUpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTZXF1ZW5jZURpZmYobmV3IE9mZnNldFJhbmdlKHN0YXJ0Lm9mZnNldDEsIGVuZEV4Y2x1c2l2ZS5vZmZzZXQxKSwgbmV3IE9mZnNldFJhbmdlKHN0YXJ0Lm9mZnNldDIsIGVuZEV4Y2x1c2l2ZS5vZmZzZXQyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBhc3NlcnRTb3J0ZWQoc2VxdWVuY2VEaWZmcykge1xuICAgICAgICBsZXQgbGFzdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgZm9yIChjb25zdCBjdXIgb2Ygc2VxdWVuY2VEaWZmcykge1xuICAgICAgICAgICAgaWYgKGxhc3QpIHtcbiAgICAgICAgICAgICAgICBpZiAoIShsYXN0LnNlcTFSYW5nZS5lbmRFeGNsdXNpdmUgPD0gY3VyLnNlcTFSYW5nZS5zdGFydCAmJiBsYXN0LnNlcTJSYW5nZS5lbmRFeGNsdXNpdmUgPD0gY3VyLnNlcTJSYW5nZS5zdGFydCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTZXF1ZW5jZSBkaWZmcyBtdXN0IGJlIHNvcnRlZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxhc3QgPSBjdXI7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29uc3RydWN0b3Ioc2VxMVJhbmdlLCBzZXEyUmFuZ2UpIHtcbiAgICAgICAgdGhpcy5zZXExUmFuZ2UgPSBzZXExUmFuZ2U7XG4gICAgICAgIHRoaXMuc2VxMlJhbmdlID0gc2VxMlJhbmdlO1xuICAgIH1cbiAgICBzd2FwKCkge1xuICAgICAgICByZXR1cm4gbmV3IFNlcXVlbmNlRGlmZih0aGlzLnNlcTJSYW5nZSwgdGhpcy5zZXExUmFuZ2UpO1xuICAgIH1cbiAgICB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIGAke3RoaXMuc2VxMVJhbmdlfSA8LT4gJHt0aGlzLnNlcTJSYW5nZX1gO1xuICAgIH1cbiAgICBqb2luKG90aGVyKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2VxdWVuY2VEaWZmKHRoaXMuc2VxMVJhbmdlLmpvaW4ob3RoZXIuc2VxMVJhbmdlKSwgdGhpcy5zZXEyUmFuZ2Uuam9pbihvdGhlci5zZXEyUmFuZ2UpKTtcbiAgICB9XG4gICAgZGVsdGEob2Zmc2V0KSB7XG4gICAgICAgIGlmIChvZmZzZXQgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgU2VxdWVuY2VEaWZmKHRoaXMuc2VxMVJhbmdlLmRlbHRhKG9mZnNldCksIHRoaXMuc2VxMlJhbmdlLmRlbHRhKG9mZnNldCkpO1xuICAgIH1cbiAgICBkZWx0YVN0YXJ0KG9mZnNldCkge1xuICAgICAgICBpZiAob2Zmc2V0ID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFNlcXVlbmNlRGlmZih0aGlzLnNlcTFSYW5nZS5kZWx0YVN0YXJ0KG9mZnNldCksIHRoaXMuc2VxMlJhbmdlLmRlbHRhU3RhcnQob2Zmc2V0KSk7XG4gICAgfVxuICAgIGRlbHRhRW5kKG9mZnNldCkge1xuICAgICAgICBpZiAob2Zmc2V0ID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFNlcXVlbmNlRGlmZih0aGlzLnNlcTFSYW5nZS5kZWx0YUVuZChvZmZzZXQpLCB0aGlzLnNlcTJSYW5nZS5kZWx0YUVuZChvZmZzZXQpKTtcbiAgICB9XG4gICAgaW50ZXJzZWN0c09yVG91Y2hlcyhvdGhlcikge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXExUmFuZ2UuaW50ZXJzZWN0c09yVG91Y2hlcyhvdGhlci5zZXExUmFuZ2UpIHx8IHRoaXMuc2VxMlJhbmdlLmludGVyc2VjdHNPclRvdWNoZXMob3RoZXIuc2VxMlJhbmdlKTtcbiAgICB9XG4gICAgaW50ZXJzZWN0KG90aGVyKSB7XG4gICAgICAgIGNvbnN0IGkxID0gdGhpcy5zZXExUmFuZ2UuaW50ZXJzZWN0KG90aGVyLnNlcTFSYW5nZSk7XG4gICAgICAgIGNvbnN0IGkyID0gdGhpcy5zZXEyUmFuZ2UuaW50ZXJzZWN0KG90aGVyLnNlcTJSYW5nZSk7XG4gICAgICAgIGlmICghaTEgfHwgIWkyKSB7XG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgU2VxdWVuY2VEaWZmKGkxLCBpMik7XG4gICAgfVxuICAgIGdldFN0YXJ0cygpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBPZmZzZXRQYWlyKHRoaXMuc2VxMVJhbmdlLnN0YXJ0LCB0aGlzLnNlcTJSYW5nZS5zdGFydCk7XG4gICAgfVxuICAgIGdldEVuZEV4Y2x1c2l2ZXMoKSB7XG4gICAgICAgIHJldHVybiBuZXcgT2Zmc2V0UGFpcih0aGlzLnNlcTFSYW5nZS5lbmRFeGNsdXNpdmUsIHRoaXMuc2VxMlJhbmdlLmVuZEV4Y2x1c2l2ZSk7XG4gICAgfVxufVxuLyoqXG4gKiBSZXN1bHQgb2YgYSBkaWZmIGFsZ29yaXRobSBjb21wdXRhdGlvbi5cbiAqL1xuY2xhc3MgRGlmZkFsZ29yaXRobVJlc3VsdCB7XG4gICAgZGlmZnM7XG4gICAgaGl0VGltZW91dDtcbiAgICBzdGF0aWMgdHJpdmlhbChzZXExLCBzZXEyKSB7XG4gICAgICAgIHJldHVybiBuZXcgRGlmZkFsZ29yaXRobVJlc3VsdChbbmV3IFNlcXVlbmNlRGlmZihPZmZzZXRSYW5nZS5vZkxlbmd0aChzZXExLmxlbmd0aCksIE9mZnNldFJhbmdlLm9mTGVuZ3RoKHNlcTIubGVuZ3RoKSldLCBmYWxzZSk7XG4gICAgfVxuICAgIHN0YXRpYyB0cml2aWFsVGltZWRPdXQoc2VxMSwgc2VxMikge1xuICAgICAgICByZXR1cm4gbmV3IERpZmZBbGdvcml0aG1SZXN1bHQoW25ldyBTZXF1ZW5jZURpZmYoT2Zmc2V0UmFuZ2Uub2ZMZW5ndGgoc2VxMS5sZW5ndGgpLCBPZmZzZXRSYW5nZS5vZkxlbmd0aChzZXEyLmxlbmd0aCkpXSwgdHJ1ZSk7XG4gICAgfVxuICAgIGNvbnN0cnVjdG9yKGRpZmZzLCBoaXRUaW1lb3V0KSB7XG4gICAgICAgIHRoaXMuZGlmZnMgPSBkaWZmcztcbiAgICAgICAgdGhpcy5oaXRUaW1lb3V0ID0gaGl0VGltZW91dDtcbiAgICB9XG59XG4vLyBIZWxwZXIgZnVuY3Rpb24gZm9yIGl0ZXJhdGluZyB3aXRoIG5laWdoYm9yc1xuZnVuY3Rpb24gZm9yRWFjaEFkamFjZW50KGl0ZW1zLCBjYWxsYmFjaykge1xuICAgIGxldCBwcmV2ID0gdW5kZWZpbmVkO1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykge1xuICAgICAgICBjYWxsYmFjayhwcmV2LCBpdGVtKTtcbiAgICAgICAgcHJldiA9IGl0ZW07XG4gICAgfVxuICAgIGNhbGxiYWNrKHByZXYsIHVuZGVmaW5lZCk7XG59XG5cbi8qKlxuICogQSAyRCBhcnJheSBpbXBsZW1lbnRhdGlvbi5cbiAqL1xuY2xhc3MgQXJyYXkyRCB7XG4gICAgd2lkdGg7XG4gICAgaGVpZ2h0O1xuICAgIGFycmF5ID0gW107XG4gICAgY29uc3RydWN0b3Iod2lkdGgsIGhlaWdodCkge1xuICAgICAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICB0aGlzLmFycmF5ID0gbmV3IEFycmF5KHdpZHRoICogaGVpZ2h0KTtcbiAgICB9XG4gICAgZ2V0KHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXJyYXlbeCArIHkgKiB0aGlzLndpZHRoXTtcbiAgICB9XG4gICAgc2V0KHgsIHksIHZhbHVlKSB7XG4gICAgICAgIHRoaXMuYXJyYXlbeCArIHkgKiB0aGlzLndpZHRoXSA9IHZhbHVlO1xuICAgIH1cbn1cbi8qKlxuICogQSBPKE1OKSBkaWZmaW5nIGFsZ29yaXRobSB0aGF0IHN1cHBvcnRzIGEgc2NvcmUgZnVuY3Rpb24uXG4gKiBUaGUgYWxnb3JpdGhtIGNhbiBiZSBpbXByb3ZlZCBieSBwcm9jZXNzaW5nIHRoZSAyZCBhcnJheSBkaWFnb25hbGx5LlxuICovXG5jbGFzcyBEeW5hbWljUHJvZ3JhbW1pbmdEaWZmaW5nIHtcbiAgICBjb21wdXRlKHNlcXVlbmNlMSwgc2VxdWVuY2UyLCB0aW1lb3V0ID0gSW5maW5pdGVUaW1lb3V0Lmluc3RhbmNlLCBlcXVhbGl0eVNjb3JlKSB7XG4gICAgICAgIGlmIChzZXF1ZW5jZTEubGVuZ3RoID09PSAwIHx8IHNlcXVlbmNlMi5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBEaWZmQWxnb3JpdGhtUmVzdWx0LnRyaXZpYWwoc2VxdWVuY2UxLCBzZXF1ZW5jZTIpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBsY3NMZW5ndGhzLmdldChpLCBqKTogTGVuZ3RoIG9mIHRoZSBsb25nZXN0IGNvbW1vbiBzdWJzZXF1ZW5jZSBvZlxuICAgICAgICAgKiBzZXF1ZW5jZTEuc3Vic3RyaW5nKDAsIGkgKyAxKSBhbmQgc2VxdWVuY2UyLnN1YnN0cmluZygwLCBqICsgMSkuXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdCBsY3NMZW5ndGhzID0gbmV3IEFycmF5MkQoc2VxdWVuY2UxLmxlbmd0aCwgc2VxdWVuY2UyLmxlbmd0aCk7XG4gICAgICAgIGNvbnN0IGRpcmVjdGlvbnMgPSBuZXcgQXJyYXkyRChzZXF1ZW5jZTEubGVuZ3RoLCBzZXF1ZW5jZTIubGVuZ3RoKTtcbiAgICAgICAgY29uc3QgbGVuZ3RocyA9IG5ldyBBcnJheTJEKHNlcXVlbmNlMS5sZW5ndGgsIHNlcXVlbmNlMi5sZW5ndGgpO1xuICAgICAgICAvLyBJbml0aWFsaXplIGxjc0xlbmd0aHNcbiAgICAgICAgZm9yIChsZXQgczEgPSAwOyBzMSA8IHNlcXVlbmNlMS5sZW5ndGg7IHMxKyspIHtcbiAgICAgICAgICAgIGZvciAobGV0IHMyID0gMDsgczIgPCBzZXF1ZW5jZTIubGVuZ3RoOyBzMisrKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aW1lb3V0LmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gRGlmZkFsZ29yaXRobVJlc3VsdC50cml2aWFsVGltZWRPdXQoc2VxdWVuY2UxLCBzZXF1ZW5jZTIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBob3Jpem9udGFsTGVuID0gczEgPT09IDAgPyAwIDogbGNzTGVuZ3Rocy5nZXQoczEgLSAxLCBzMik7XG4gICAgICAgICAgICAgICAgY29uc3QgdmVydGljYWxMZW4gPSBzMiA9PT0gMCA/IDAgOiBsY3NMZW5ndGhzLmdldChzMSwgczIgLSAxKTtcbiAgICAgICAgICAgICAgICBsZXQgZXh0ZW5kZWRTZXFTY29yZTtcbiAgICAgICAgICAgICAgICBpZiAoc2VxdWVuY2UxLmdldEVsZW1lbnQoczEpID09PSBzZXF1ZW5jZTIuZ2V0RWxlbWVudChzMikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHMxID09PSAwIHx8IHMyID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBleHRlbmRlZFNlcVNjb3JlID0gMDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuZGVkU2VxU2NvcmUgPSBsY3NMZW5ndGhzLmdldChzMSAtIDEsIHMyIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHMxID4gMCAmJiBzMiA+IDAgJiYgZGlyZWN0aW9ucy5nZXQoczEgLSAxLCBzMiAtIDEpID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBQcmVmZXIgY29uc2VjdXRpdmUgZGlhZ29uYWxzXG4gICAgICAgICAgICAgICAgICAgICAgICBleHRlbmRlZFNlcVNjb3JlICs9IGxlbmd0aHMuZ2V0KHMxIC0gMSwgczIgLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBleHRlbmRlZFNlcVNjb3JlICs9IChlcXVhbGl0eVNjb3JlID8gZXF1YWxpdHlTY29yZShzMSwgczIpIDogMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBleHRlbmRlZFNlcVNjb3JlID0gLTE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IG5ld1ZhbHVlID0gTWF0aC5tYXgoaG9yaXpvbnRhbExlbiwgdmVydGljYWxMZW4sIGV4dGVuZGVkU2VxU2NvcmUpO1xuICAgICAgICAgICAgICAgIGlmIChuZXdWYWx1ZSA9PT0gZXh0ZW5kZWRTZXFTY29yZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQcmVmZXIgZGlhZ29uYWxzXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHByZXZMZW4gPSBzMSA+IDAgJiYgczIgPiAwID8gbGVuZ3Rocy5nZXQoczEgLSAxLCBzMiAtIDEpIDogMDtcbiAgICAgICAgICAgICAgICAgICAgbGVuZ3Rocy5zZXQoczEsIHMyLCBwcmV2TGVuICsgMSk7XG4gICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbnMuc2V0KHMxLCBzMiwgMyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKG5ld1ZhbHVlID09PSBob3Jpem9udGFsTGVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGxlbmd0aHMuc2V0KHMxLCBzMiwgMCk7XG4gICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbnMuc2V0KHMxLCBzMiwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKG5ld1ZhbHVlID09PSB2ZXJ0aWNhbExlbikge1xuICAgICAgICAgICAgICAgICAgICBsZW5ndGhzLnNldChzMSwgczIsIDApO1xuICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb25zLnNldChzMSwgczIsIDIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsY3NMZW5ndGhzLnNldChzMSwgczIsIG5ld1ZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBCYWNrdHJhY2tpbmdcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgICAgIGxldCBsYXN0QWxpZ25pbmdQb3NTMSA9IHNlcXVlbmNlMS5sZW5ndGg7XG4gICAgICAgIGxldCBsYXN0QWxpZ25pbmdQb3NTMiA9IHNlcXVlbmNlMi5sZW5ndGg7XG4gICAgICAgIGZ1bmN0aW9uIHJlcG9ydERlY3JlYXNpbmdBbGlnbmluZ1Bvc2l0aW9ucyhzMSwgczIpIHtcbiAgICAgICAgICAgIGlmIChzMSArIDEgIT09IGxhc3RBbGlnbmluZ1Bvc1MxIHx8IHMyICsgMSAhPT0gbGFzdEFsaWduaW5nUG9zUzIpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChuZXcgU2VxdWVuY2VEaWZmKG5ldyBPZmZzZXRSYW5nZShzMSArIDEsIGxhc3RBbGlnbmluZ1Bvc1MxKSwgbmV3IE9mZnNldFJhbmdlKHMyICsgMSwgbGFzdEFsaWduaW5nUG9zUzIpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsYXN0QWxpZ25pbmdQb3NTMSA9IHMxO1xuICAgICAgICAgICAgbGFzdEFsaWduaW5nUG9zUzIgPSBzMjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgczEgPSBzZXF1ZW5jZTEubGVuZ3RoIC0gMTtcbiAgICAgICAgbGV0IHMyID0gc2VxdWVuY2UyLmxlbmd0aCAtIDE7XG4gICAgICAgIHdoaWxlIChzMSA+PSAwICYmIHMyID49IDApIHtcbiAgICAgICAgICAgIGlmIChkaXJlY3Rpb25zLmdldChzMSwgczIpID09PSAzKSB7XG4gICAgICAgICAgICAgICAgcmVwb3J0RGVjcmVhc2luZ0FsaWduaW5nUG9zaXRpb25zKHMxLCBzMik7XG4gICAgICAgICAgICAgICAgczEtLTtcbiAgICAgICAgICAgICAgICBzMi0tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGRpcmVjdGlvbnMuZ2V0KHMxLCBzMikgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgczEtLTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHMyLS07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJlcG9ydERlY3JlYXNpbmdBbGlnbmluZ1Bvc2l0aW9ucygtMSwgLTEpO1xuICAgICAgICByZXN1bHQucmV2ZXJzZSgpO1xuICAgICAgICByZXR1cm4gbmV3IERpZmZBbGdvcml0aG1SZXN1bHQocmVzdWx0LCBmYWxzZSk7XG4gICAgfVxufVxuXG4vKipcbiAqIEFuIE8oTkQpIGRpZmYgYWxnb3JpdGhtIHRoYXQgaGFzIGEgcXVhZHJhdGljIHNwYWNlIHdvcnN0LWNhc2UgY29tcGxleGl0eS5cbiAqL1xuY2xhc3MgTXllcnNEaWZmQWxnb3JpdGhtIHtcbiAgICBjb21wdXRlKHNlcTEsIHNlcTIsIHRpbWVvdXQgPSBJbmZpbml0ZVRpbWVvdXQuaW5zdGFuY2UpIHtcbiAgICAgICAgLy8gQ29tbW9uIHNwZWNpYWwgY2FzZXMgLSBlYXJseSByZXR1cm4gaW1wcm92ZXMgcGVyZm9ybWFuY2UgZHJhbWF0aWNhbGx5XG4gICAgICAgIGlmIChzZXExLmxlbmd0aCA9PT0gMCB8fCBzZXEyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIERpZmZBbGdvcml0aG1SZXN1bHQudHJpdmlhbChzZXExLCBzZXEyKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzZXFYID0gc2VxMTsgLy8gVGV4dCBvbiB0aGUgeCBheGlzXG4gICAgICAgIGNvbnN0IHNlcVkgPSBzZXEyOyAvLyBUZXh0IG9uIHRoZSB5IGF4aXNcbiAgICAgICAgZnVuY3Rpb24gZ2V0WEFmdGVyU25ha2UoeCwgeSkge1xuICAgICAgICAgICAgd2hpbGUgKHggPCBzZXFYLmxlbmd0aCAmJiB5IDwgc2VxWS5sZW5ndGggJiYgc2VxWC5nZXRFbGVtZW50KHgpID09PSBzZXFZLmdldEVsZW1lbnQoeSkpIHtcbiAgICAgICAgICAgICAgICB4Kys7XG4gICAgICAgICAgICAgICAgeSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHg7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGQgPSAwO1xuICAgICAgICAvLyBWW2tdOiBYIHZhbHVlIG9mIGxvbmdlc3QgZC1saW5lIHRoYXQgZW5kcyBpbiBkaWFnb25hbCBrLlxuICAgICAgICAvLyBkLWxpbmU6IHBhdGggZnJvbSAoMCwwKSB0byAoeCx5KSB0aGF0IHVzZXMgZXhhY3RseSBkIG5vbi1kaWFnb25hbHMuXG4gICAgICAgIC8vIGRpYWdvbmFsIGs6IFNldCBvZiBwb2ludHMgKHgseSkgd2l0aCB4LXkgPSBrLlxuICAgICAgICBjb25zdCBWID0gbmV3IEZhc3RJbnQzMkFycmF5KCk7XG4gICAgICAgIFYuc2V0KDAsIGdldFhBZnRlclNuYWtlKDAsIDApKTtcbiAgICAgICAgY29uc3QgcGF0aHMgPSBuZXcgRmFzdEFycmF5TmVnYXRpdmVJbmRpY2VzKCk7XG4gICAgICAgIHBhdGhzLnNldCgwLCBWLmdldCgwKSA9PT0gMCA/IG51bGwgOiBuZXcgU25ha2VQYXRoKG51bGwsIDAsIDAsIFYuZ2V0KDApKSk7XG4gICAgICAgIGxldCBrID0gMDtcbiAgICAgICAgbG9vcDogd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgIGQrKztcbiAgICAgICAgICAgIGlmICghdGltZW91dC5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRGlmZkFsZ29yaXRobVJlc3VsdC50cml2aWFsVGltZWRPdXQoc2VxWCwgc2VxWSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUaGUgcGFwZXIgaGFzIGBmb3IgKGsgPSAtZDsgayA8PSBkOyBrICs9IDIpYCwgYnV0IHdlIGNhbiBpZ25vcmUgZGlhZ29uYWxzIHRoYXQgY2Fubm90IGluZmx1ZW5jZSB0aGUgcmVzdWx0LlxuICAgICAgICAgICAgY29uc3QgbG93ZXJCb3VuZCA9IC1NYXRoLm1pbihkLCBzZXFZLmxlbmd0aCArIChkICUgMikpO1xuICAgICAgICAgICAgY29uc3QgdXBwZXJCb3VuZCA9IE1hdGgubWluKGQsIHNlcVgubGVuZ3RoICsgKGQgJSAyKSk7XG4gICAgICAgICAgICBmb3IgKGsgPSBsb3dlckJvdW5kOyBrIDw9IHVwcGVyQm91bmQ7IGsgKz0gMikge1xuICAgICAgICAgICAgICAgIC8vIFdlIGNhbiB1c2UgdGhlIFggdmFsdWVzIG9mIChkLTEpLWxpbmVzIHRvIGNvbXB1dGUgWCB2YWx1ZSBvZiB0aGUgbG9uZ2VzdCBkLWxpbmVzLlxuICAgICAgICAgICAgICAgIGNvbnN0IG1heFhvZkRMaW5lVG9wID0gayA9PT0gdXBwZXJCb3VuZCA/IC0xIDogVi5nZXQoayArIDEpOyAvLyBWZXJ0aWNhbCBub24tZGlhZ29uYWwgKGFkZCBzeW1ib2wgaW4gc2VxWClcbiAgICAgICAgICAgICAgICBjb25zdCBtYXhYb2ZETGluZUxlZnQgPSBrID09PSBsb3dlckJvdW5kID8gLTEgOiBWLmdldChrIC0gMSkgKyAxOyAvLyBIb3Jpem9udGFsIG5vbi1kaWFnb25hbCAoZGVsZXRlIHN5bWJvbCBpbiBzZXFYKVxuICAgICAgICAgICAgICAgIGNvbnN0IHggPSBNYXRoLm1pbihNYXRoLm1heChtYXhYb2ZETGluZVRvcCwgbWF4WG9mRExpbmVMZWZ0KSwgc2VxWC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHkgPSB4IC0gaztcbiAgICAgICAgICAgICAgICBpZiAoeCA+IHNlcVgubGVuZ3RoIHx8IHkgPiBzZXFZLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgbmV3TWF4WCA9IGdldFhBZnRlclNuYWtlKHgsIHkpO1xuICAgICAgICAgICAgICAgIFYuc2V0KGssIG5ld01heFgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxhc3RQYXRoID0geCA9PT0gbWF4WG9mRExpbmVUb3AgPyBwYXRocy5nZXQoayArIDEpIDogcGF0aHMuZ2V0KGsgLSAxKTtcbiAgICAgICAgICAgICAgICBwYXRocy5zZXQoaywgbmV3TWF4WCAhPT0geCA/IG5ldyBTbmFrZVBhdGgobGFzdFBhdGgsIHgsIHksIG5ld01heFggLSB4KSA6IGxhc3RQYXRoKTtcbiAgICAgICAgICAgICAgICBpZiAoVi5nZXQoaykgPT09IHNlcVgubGVuZ3RoICYmIFYuZ2V0KGspIC0gayA9PT0gc2VxWS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWsgbG9vcDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHBhdGggPSBwYXRocy5nZXQoayk7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgICAgICBsZXQgbGFzdEFsaWduaW5nUG9zUzEgPSBzZXFYLmxlbmd0aDtcbiAgICAgICAgbGV0IGxhc3RBbGlnbmluZ1Bvc1MyID0gc2VxWS5sZW5ndGg7XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBjb25zdCBlbmRYID0gcGF0aCA/IHBhdGgueCArIHBhdGgubGVuZ3RoIDogMDtcbiAgICAgICAgICAgIGNvbnN0IGVuZFkgPSBwYXRoID8gcGF0aC55ICsgcGF0aC5sZW5ndGggOiAwO1xuICAgICAgICAgICAgaWYgKGVuZFggIT09IGxhc3RBbGlnbmluZ1Bvc1MxIHx8IGVuZFkgIT09IGxhc3RBbGlnbmluZ1Bvc1MyKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2gobmV3IFNlcXVlbmNlRGlmZihuZXcgT2Zmc2V0UmFuZ2UoZW5kWCwgbGFzdEFsaWduaW5nUG9zUzEpLCBuZXcgT2Zmc2V0UmFuZ2UoZW5kWSwgbGFzdEFsaWduaW5nUG9zUzIpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXBhdGgpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxhc3RBbGlnbmluZ1Bvc1MxID0gcGF0aC54O1xuICAgICAgICAgICAgbGFzdEFsaWduaW5nUG9zUzIgPSBwYXRoLnk7XG4gICAgICAgICAgICBwYXRoID0gcGF0aC5wcmV2O1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdC5yZXZlcnNlKCk7XG4gICAgICAgIHJldHVybiBuZXcgRGlmZkFsZ29yaXRobVJlc3VsdChyZXN1bHQsIGZhbHNlKTtcbiAgICB9XG59XG5jbGFzcyBTbmFrZVBhdGgge1xuICAgIHByZXY7XG4gICAgeDtcbiAgICB5O1xuICAgIGxlbmd0aDtcbiAgICBjb25zdHJ1Y3RvcihwcmV2LCB4LCB5LCBsZW5ndGgpIHtcbiAgICAgICAgdGhpcy5wcmV2ID0gcHJldjtcbiAgICAgICAgdGhpcy54ID0geDtcbiAgICAgICAgdGhpcy55ID0geTtcbiAgICAgICAgdGhpcy5sZW5ndGggPSBsZW5ndGg7XG4gICAgfVxufVxuLyoqXG4gKiBBbiBhcnJheSB0aGF0IHN1cHBvcnRzIGZhc3QgbmVnYXRpdmUgaW5kaWNlcy5cbiAqL1xuY2xhc3MgRmFzdEludDMyQXJyYXkge1xuICAgIHBvc2l0aXZlQXJyID0gbmV3IEludDMyQXJyYXkoMTApO1xuICAgIG5lZ2F0aXZlQXJyID0gbmV3IEludDMyQXJyYXkoMTApO1xuICAgIGdldChpZHgpIHtcbiAgICAgICAgaWYgKGlkeCA8IDApIHtcbiAgICAgICAgICAgIGlkeCA9IC1pZHggLSAxO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubmVnYXRpdmVBcnJbaWR4XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBvc2l0aXZlQXJyW2lkeF07XG4gICAgICAgIH1cbiAgICB9XG4gICAgc2V0KGlkeCwgdmFsdWUpIHtcbiAgICAgICAgaWYgKGlkeCA8IDApIHtcbiAgICAgICAgICAgIGlkeCA9IC1pZHggLSAxO1xuICAgICAgICAgICAgaWYgKGlkeCA+PSB0aGlzLm5lZ2F0aXZlQXJyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFyciA9IHRoaXMubmVnYXRpdmVBcnI7XG4gICAgICAgICAgICAgICAgdGhpcy5uZWdhdGl2ZUFyciA9IG5ldyBJbnQzMkFycmF5KGFyci5sZW5ndGggKiAyKTtcbiAgICAgICAgICAgICAgICB0aGlzLm5lZ2F0aXZlQXJyLnNldChhcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5uZWdhdGl2ZUFycltpZHhdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoaWR4ID49IHRoaXMucG9zaXRpdmVBcnIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYXJyID0gdGhpcy5wb3NpdGl2ZUFycjtcbiAgICAgICAgICAgICAgICB0aGlzLnBvc2l0aXZlQXJyID0gbmV3IEludDMyQXJyYXkoYXJyLmxlbmd0aCAqIDIpO1xuICAgICAgICAgICAgICAgIHRoaXMucG9zaXRpdmVBcnIuc2V0KGFycik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnBvc2l0aXZlQXJyW2lkeF0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cbn1cbi8qKlxuICogQW4gYXJyYXkgdGhhdCBzdXBwb3J0cyBmYXN0IG5lZ2F0aXZlIGluZGljZXMgZm9yIG9iamVjdHMuXG4gKi9cbmNsYXNzIEZhc3RBcnJheU5lZ2F0aXZlSW5kaWNlcyB7XG4gICAgcG9zaXRpdmVBcnIgPSBbXTtcbiAgICBuZWdhdGl2ZUFyciA9IFtdO1xuICAgIGdldChpZHgpIHtcbiAgICAgICAgaWYgKGlkeCA8IDApIHtcbiAgICAgICAgICAgIGlkeCA9IC1pZHggLSAxO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubmVnYXRpdmVBcnJbaWR4XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBvc2l0aXZlQXJyW2lkeF07XG4gICAgICAgIH1cbiAgICB9XG4gICAgc2V0KGlkeCwgdmFsdWUpIHtcbiAgICAgICAgaWYgKGlkeCA8IDApIHtcbiAgICAgICAgICAgIGlkeCA9IC1pZHggLSAxO1xuICAgICAgICAgICAgdGhpcy5uZWdhdGl2ZUFycltpZHhdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnBvc2l0aXZlQXJyW2lkeF0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gb3B0aW1pemVTZXF1ZW5jZURpZmZzKHNlcXVlbmNlMSwgc2VxdWVuY2UyLCBzZXF1ZW5jZURpZmZzKSB7XG4gICAgbGV0IHJlc3VsdCA9IHNlcXVlbmNlRGlmZnM7XG4gICAgcmVzdWx0ID0gam9pblNlcXVlbmNlRGlmZnNCeVNoaWZ0aW5nKHNlcXVlbmNlMSwgc2VxdWVuY2UyLCByZXN1bHQpO1xuICAgIC8vIFNvbWV0aW1lcywgY2FsbGluZyB0aGlzIGZ1bmN0aW9uIHR3aWNlIGltcHJvdmVzIHRoZSByZXN1bHQuXG4gICAgcmVzdWx0ID0gam9pblNlcXVlbmNlRGlmZnNCeVNoaWZ0aW5nKHNlcXVlbmNlMSwgc2VxdWVuY2UyLCByZXN1bHQpO1xuICAgIHJlc3VsdCA9IHNoaWZ0U2VxdWVuY2VEaWZmcyhzZXF1ZW5jZTEsIHNlcXVlbmNlMiwgcmVzdWx0KTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIGZpeGVzIGlzc3VlcyBsaWtlIHRoaXM6XG4gKiBgYGBcbiAqIGltcG9ydCB7IEJheiwgQmFyIH0gZnJvbSBcImZvb1wiO1xuICogYGBgXG4gKiA8LT5cbiAqIGBgYFxuICogaW1wb3J0IHsgQmF6LCBCYXIsIEZvbyB9IGZyb20gXCJmb29cIjtcbiAqIGBgYFxuICogQ29tcHV0ZWQgZGlmZjogWyB7QWRkIFwiLFwiIGFmdGVyIEJhcn0sIHtBZGQgXCJGb28gXCIgYWZ0ZXIgc3BhY2V9IH1cbiAqIEltcHJvdmVkIGRpZmY6IFt7QWRkIFwiLCBGb29cIiBhZnRlciBCYXJ9XVxuICovXG5mdW5jdGlvbiBqb2luU2VxdWVuY2VEaWZmc0J5U2hpZnRpbmcoc2VxdWVuY2UxLCBzZXF1ZW5jZTIsIHNlcXVlbmNlRGlmZnMpIHtcbiAgICBpZiAoc2VxdWVuY2VEaWZmcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHNlcXVlbmNlRGlmZnM7XG4gICAgfVxuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIHJlc3VsdC5wdXNoKHNlcXVlbmNlRGlmZnNbMF0pO1xuICAgIC8vIEZpcnN0IG1vdmUgdGhlbSBhbGwgdG8gdGhlIGxlZnQgYXMgbXVjaCBhcyBwb3NzaWJsZSBhbmQgam9pbiB0aGVtIGlmIHBvc3NpYmxlXG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzZXF1ZW5jZURpZmZzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHByZXZSZXN1bHQgPSByZXN1bHRbcmVzdWx0Lmxlbmd0aCAtIDFdO1xuICAgICAgICBsZXQgY3VyID0gc2VxdWVuY2VEaWZmc1tpXTtcbiAgICAgICAgaWYgKGN1ci5zZXExUmFuZ2UuaXNFbXB0eSB8fCBjdXIuc2VxMlJhbmdlLmlzRW1wdHkpIHtcbiAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IGN1ci5zZXExUmFuZ2Uuc3RhcnQgLSBwcmV2UmVzdWx0LnNlcTFSYW5nZS5lbmRFeGNsdXNpdmU7XG4gICAgICAgICAgICBsZXQgZDtcbiAgICAgICAgICAgIGZvciAoZCA9IDE7IGQgPD0gbGVuZ3RoOyBkKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VxdWVuY2UxLmdldEVsZW1lbnQoY3VyLnNlcTFSYW5nZS5zdGFydCAtIGQpICE9PSBzZXF1ZW5jZTEuZ2V0RWxlbWVudChjdXIuc2VxMVJhbmdlLmVuZEV4Y2x1c2l2ZSAtIGQpIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlcXVlbmNlMi5nZXRFbGVtZW50KGN1ci5zZXEyUmFuZ2Uuc3RhcnQgLSBkKSAhPT0gc2VxdWVuY2UyLmdldEVsZW1lbnQoY3VyLnNlcTJSYW5nZS5lbmRFeGNsdXNpdmUgLSBkKSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkLS07XG4gICAgICAgICAgICBpZiAoZCA9PT0gbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgLy8gTWVyZ2UgcHJldmlvdXMgYW5kIGN1cnJlbnQgZGlmZlxuICAgICAgICAgICAgICAgIHJlc3VsdFtyZXN1bHQubGVuZ3RoIC0gMV0gPSBuZXcgU2VxdWVuY2VEaWZmKG5ldyBPZmZzZXRSYW5nZShwcmV2UmVzdWx0LnNlcTFSYW5nZS5zdGFydCwgY3VyLnNlcTFSYW5nZS5lbmRFeGNsdXNpdmUgLSBsZW5ndGgpLCBuZXcgT2Zmc2V0UmFuZ2UocHJldlJlc3VsdC5zZXEyUmFuZ2Uuc3RhcnQsIGN1ci5zZXEyUmFuZ2UuZW5kRXhjbHVzaXZlIC0gbGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXIgPSBjdXIuZGVsdGEoLWQpO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdC5wdXNoKGN1cik7XG4gICAgfVxuICAgIGNvbnN0IHJlc3VsdDIgPSBbXTtcbiAgICAvLyBUaGVuIG1vdmUgdGhlbSBhbGwgdG8gdGhlIHJpZ2h0IGFuZCBqb2luIHRoZW0gYWdhaW4gaWYgcG9zc2libGVcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlc3VsdC5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgY29uc3QgbmV4dFJlc3VsdCA9IHJlc3VsdFtpICsgMV07XG4gICAgICAgIGxldCBjdXIgPSByZXN1bHRbaV07XG4gICAgICAgIGlmIChjdXIuc2VxMVJhbmdlLmlzRW1wdHkgfHwgY3VyLnNlcTJSYW5nZS5pc0VtcHR5KSB7XG4gICAgICAgICAgICBjb25zdCBsZW5ndGggPSBuZXh0UmVzdWx0LnNlcTFSYW5nZS5zdGFydCAtIGN1ci5zZXExUmFuZ2UuZW5kRXhjbHVzaXZlO1xuICAgICAgICAgICAgbGV0IGQ7XG4gICAgICAgICAgICBmb3IgKGQgPSAwOyBkIDwgbGVuZ3RoOyBkKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoIXNlcXVlbmNlMS5pc1N0cm9uZ2x5RXF1YWwoY3VyLnNlcTFSYW5nZS5zdGFydCArIGQsIGN1ci5zZXExUmFuZ2UuZW5kRXhjbHVzaXZlICsgZCkgfHxcbiAgICAgICAgICAgICAgICAgICAgIXNlcXVlbmNlMi5pc1N0cm9uZ2x5RXF1YWwoY3VyLnNlcTJSYW5nZS5zdGFydCArIGQsIGN1ci5zZXEyUmFuZ2UuZW5kRXhjbHVzaXZlICsgZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGQgPT09IGxlbmd0aCkge1xuICAgICAgICAgICAgICAgIC8vIE1lcmdlIHByZXZpb3VzIGFuZCBjdXJyZW50IGRpZmZcbiAgICAgICAgICAgICAgICByZXN1bHRbaSArIDFdID0gbmV3IFNlcXVlbmNlRGlmZihuZXcgT2Zmc2V0UmFuZ2UoY3VyLnNlcTFSYW5nZS5zdGFydCArIGxlbmd0aCwgbmV4dFJlc3VsdC5zZXExUmFuZ2UuZW5kRXhjbHVzaXZlKSwgbmV3IE9mZnNldFJhbmdlKGN1ci5zZXEyUmFuZ2Uuc3RhcnQgKyBsZW5ndGgsIG5leHRSZXN1bHQuc2VxMlJhbmdlLmVuZEV4Y2x1c2l2ZSkpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGQgPiAwKSB7XG4gICAgICAgICAgICAgICAgY3VyID0gY3VyLmRlbHRhKGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJlc3VsdDIucHVzaChjdXIpO1xuICAgIH1cbiAgICBpZiAocmVzdWx0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmVzdWx0Mi5wdXNoKHJlc3VsdFtyZXN1bHQubGVuZ3RoIC0gMV0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0Mjtcbn1cbmZ1bmN0aW9uIHNoaWZ0U2VxdWVuY2VEaWZmcyhzZXF1ZW5jZTEsIHNlcXVlbmNlMiwgc2VxdWVuY2VEaWZmcykge1xuICAgIGlmICghc2VxdWVuY2UxLmdldEJvdW5kYXJ5U2NvcmUgfHwgIXNlcXVlbmNlMi5nZXRCb3VuZGFyeVNjb3JlKSB7XG4gICAgICAgIHJldHVybiBzZXF1ZW5jZURpZmZzO1xuICAgIH1cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlcXVlbmNlRGlmZnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgcHJldkRpZmYgPSAoaSA+IDAgPyBzZXF1ZW5jZURpZmZzW2kgLSAxXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgIGNvbnN0IGRpZmYgPSBzZXF1ZW5jZURpZmZzW2ldO1xuICAgICAgICBjb25zdCBuZXh0RGlmZiA9IChpICsgMSA8IHNlcXVlbmNlRGlmZnMubGVuZ3RoID8gc2VxdWVuY2VEaWZmc1tpICsgMV0gOiB1bmRlZmluZWQpO1xuICAgICAgICBjb25zdCBzZXExVmFsaWRSYW5nZSA9IG5ldyBPZmZzZXRSYW5nZShwcmV2RGlmZiA/IHByZXZEaWZmLnNlcTFSYW5nZS5lbmRFeGNsdXNpdmUgKyAxIDogMCwgbmV4dERpZmYgPyBuZXh0RGlmZi5zZXExUmFuZ2Uuc3RhcnQgLSAxIDogc2VxdWVuY2UxLmxlbmd0aCk7XG4gICAgICAgIGNvbnN0IHNlcTJWYWxpZFJhbmdlID0gbmV3IE9mZnNldFJhbmdlKHByZXZEaWZmID8gcHJldkRpZmYuc2VxMlJhbmdlLmVuZEV4Y2x1c2l2ZSArIDEgOiAwLCBuZXh0RGlmZiA/IG5leHREaWZmLnNlcTJSYW5nZS5zdGFydCAtIDEgOiBzZXF1ZW5jZTIubGVuZ3RoKTtcbiAgICAgICAgaWYgKGRpZmYuc2VxMVJhbmdlLmlzRW1wdHkpIHtcbiAgICAgICAgICAgIHNlcXVlbmNlRGlmZnNbaV0gPSBzaGlmdERpZmZUb0JldHRlclBvc2l0aW9uKGRpZmYsIHNlcXVlbmNlMSwgc2VxdWVuY2UyLCBzZXExVmFsaWRSYW5nZSwgc2VxMlZhbGlkUmFuZ2UpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGRpZmYuc2VxMlJhbmdlLmlzRW1wdHkpIHtcbiAgICAgICAgICAgIHNlcXVlbmNlRGlmZnNbaV0gPSBzaGlmdERpZmZUb0JldHRlclBvc2l0aW9uKGRpZmYuc3dhcCgpLCBzZXF1ZW5jZTIsIHNlcXVlbmNlMSwgc2VxMlZhbGlkUmFuZ2UsIHNlcTFWYWxpZFJhbmdlKS5zd2FwKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHNlcXVlbmNlRGlmZnM7XG59XG5mdW5jdGlvbiBzaGlmdERpZmZUb0JldHRlclBvc2l0aW9uKGRpZmYsIHNlcXVlbmNlMSwgc2VxdWVuY2UyLCBzZXExVmFsaWRSYW5nZSwgc2VxMlZhbGlkUmFuZ2UpIHtcbiAgICBjb25zdCBtYXhTaGlmdExpbWl0ID0gMTAwOyAvLyBUbyBwcmV2ZW50IHBlcmZvcm1hbmNlIGlzc3Vlc1xuICAgIGxldCBkZWx0YUJlZm9yZSA9IDE7XG4gICAgd2hpbGUgKGRpZmYuc2VxMVJhbmdlLnN0YXJ0IC0gZGVsdGFCZWZvcmUgPj0gc2VxMVZhbGlkUmFuZ2Uuc3RhcnQgJiZcbiAgICAgICAgZGlmZi5zZXEyUmFuZ2Uuc3RhcnQgLSBkZWx0YUJlZm9yZSA+PSBzZXEyVmFsaWRSYW5nZS5zdGFydCAmJlxuICAgICAgICBzZXF1ZW5jZTIuaXNTdHJvbmdseUVxdWFsKGRpZmYuc2VxMlJhbmdlLnN0YXJ0IC0gZGVsdGFCZWZvcmUsIGRpZmYuc2VxMlJhbmdlLmVuZEV4Y2x1c2l2ZSAtIGRlbHRhQmVmb3JlKSAmJiBkZWx0YUJlZm9yZSA8IG1heFNoaWZ0TGltaXQpIHtcbiAgICAgICAgZGVsdGFCZWZvcmUrKztcbiAgICB9XG4gICAgZGVsdGFCZWZvcmUtLTtcbiAgICBsZXQgZGVsdGFBZnRlciA9IDA7XG4gICAgd2hpbGUgKGRpZmYuc2VxMVJhbmdlLnN0YXJ0ICsgZGVsdGFBZnRlciA8IHNlcTFWYWxpZFJhbmdlLmVuZEV4Y2x1c2l2ZSAmJlxuICAgICAgICBkaWZmLnNlcTJSYW5nZS5lbmRFeGNsdXNpdmUgKyBkZWx0YUFmdGVyIDwgc2VxMlZhbGlkUmFuZ2UuZW5kRXhjbHVzaXZlICYmXG4gICAgICAgIHNlcXVlbmNlMi5pc1N0cm9uZ2x5RXF1YWwoZGlmZi5zZXEyUmFuZ2Uuc3RhcnQgKyBkZWx0YUFmdGVyLCBkaWZmLnNlcTJSYW5nZS5lbmRFeGNsdXNpdmUgKyBkZWx0YUFmdGVyKSAmJiBkZWx0YUFmdGVyIDwgbWF4U2hpZnRMaW1pdCkge1xuICAgICAgICBkZWx0YUFmdGVyKys7XG4gICAgfVxuICAgIGlmIChkZWx0YUJlZm9yZSA9PT0gMCAmJiBkZWx0YUFmdGVyID09PSAwKSB7XG4gICAgICAgIHJldHVybiBkaWZmO1xuICAgIH1cbiAgICBsZXQgYmVzdERlbHRhID0gMDtcbiAgICBsZXQgYmVzdFNjb3JlID0gLTE7XG4gICAgLy8gRmluZCBiZXN0IHNjb3JlZCBkZWx0YVxuICAgIGZvciAobGV0IGRlbHRhID0gLWRlbHRhQmVmb3JlOyBkZWx0YSA8PSBkZWx0YUFmdGVyOyBkZWx0YSsrKSB7XG4gICAgICAgIGNvbnN0IHNlcTJPZmZzZXRTdGFydCA9IGRpZmYuc2VxMlJhbmdlLnN0YXJ0ICsgZGVsdGE7XG4gICAgICAgIGNvbnN0IHNlcTJPZmZzZXRFbmRFeGNsdXNpdmUgPSBkaWZmLnNlcTJSYW5nZS5lbmRFeGNsdXNpdmUgKyBkZWx0YTtcbiAgICAgICAgY29uc3Qgc2VxMU9mZnNldCA9IGRpZmYuc2VxMVJhbmdlLnN0YXJ0ICsgZGVsdGE7XG4gICAgICAgIGNvbnN0IHNjb3JlID0gc2VxdWVuY2UxLmdldEJvdW5kYXJ5U2NvcmUoc2VxMU9mZnNldCkgKyBzZXF1ZW5jZTIuZ2V0Qm91bmRhcnlTY29yZShzZXEyT2Zmc2V0U3RhcnQpICsgc2VxdWVuY2UyLmdldEJvdW5kYXJ5U2NvcmUoc2VxMk9mZnNldEVuZEV4Y2x1c2l2ZSk7XG4gICAgICAgIGlmIChzY29yZSA+IGJlc3RTY29yZSkge1xuICAgICAgICAgICAgYmVzdFNjb3JlID0gc2NvcmU7XG4gICAgICAgICAgICBiZXN0RGVsdGEgPSBkZWx0YTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGlmZi5kZWx0YShiZXN0RGVsdGEpO1xufVxuZnVuY3Rpb24gcmVtb3ZlU2hvcnRNYXRjaGVzKHNlcXVlbmNlMSwgc2VxdWVuY2UyLCBzZXF1ZW5jZURpZmZzKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgZm9yIChjb25zdCBzIG9mIHNlcXVlbmNlRGlmZnMpIHtcbiAgICAgICAgY29uc3QgbGFzdCA9IHJlc3VsdFtyZXN1bHQubGVuZ3RoIC0gMV07XG4gICAgICAgIGlmICghbGFzdCkge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2gocyk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocy5zZXExUmFuZ2Uuc3RhcnQgLSBsYXN0LnNlcTFSYW5nZS5lbmRFeGNsdXNpdmUgPD0gMiB8fCBzLnNlcTJSYW5nZS5zdGFydCAtIGxhc3Quc2VxMlJhbmdlLmVuZEV4Y2x1c2l2ZSA8PSAyKSB7XG4gICAgICAgICAgICByZXN1bHRbcmVzdWx0Lmxlbmd0aCAtIDFdID0gbmV3IFNlcXVlbmNlRGlmZihsYXN0LnNlcTFSYW5nZS5qb2luKHMuc2VxMVJhbmdlKSwgbGFzdC5zZXEyUmFuZ2Uuam9pbihzLnNlcTJSYW5nZSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2gocyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGV4dGVuZERpZmZzVG9FbnRpcmVXb3JkSWZBcHByb3ByaWF0ZShzZXF1ZW5jZTEsIHNlcXVlbmNlMiwgc2VxdWVuY2VEaWZmcywgZmluZFBhcmVudCwgZm9yY2UgPSBmYWxzZSkge1xuICAgIGNvbnN0IGVxdWFsTWFwcGluZ3MgPSBTZXF1ZW5jZURpZmYuaW52ZXJ0KHNlcXVlbmNlRGlmZnMsIHNlcXVlbmNlMS5sZW5ndGgpO1xuICAgIGNvbnN0IGFkZGl0aW9uYWwgPSBbXTtcbiAgICBsZXQgbGFzdFBvaW50ID0gbmV3IE9mZnNldFBhaXIoMCwgMCk7XG4gICAgZnVuY3Rpb24gc2NhbldvcmQocGFpciwgZXF1YWxNYXBwaW5nKSB7XG4gICAgICAgIGlmIChwYWlyLm9mZnNldDEgPCBsYXN0UG9pbnQub2Zmc2V0MSB8fCBwYWlyLm9mZnNldDIgPCBsYXN0UG9pbnQub2Zmc2V0Mikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHcxID0gZmluZFBhcmVudChzZXF1ZW5jZTEsIHBhaXIub2Zmc2V0MSk7XG4gICAgICAgIGNvbnN0IHcyID0gZmluZFBhcmVudChzZXF1ZW5jZTIsIHBhaXIub2Zmc2V0Mik7XG4gICAgICAgIGlmICghdzEgfHwgIXcyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHcgPSBuZXcgU2VxdWVuY2VEaWZmKHcxLCB3Mik7XG4gICAgICAgIGNvbnN0IGVxdWFsUGFydCA9IHcuaW50ZXJzZWN0KGVxdWFsTWFwcGluZyk7XG4gICAgICAgIGxldCBlcXVhbENoYXJzMSA9IGVxdWFsUGFydC5zZXExUmFuZ2UubGVuZ3RoO1xuICAgICAgICBsZXQgZXF1YWxDaGFyczIgPSBlcXVhbFBhcnQuc2VxMlJhbmdlLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGVxdWFsTWFwcGluZ3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc3QgbmV4dCA9IGVxdWFsTWFwcGluZ3NbMF07XG4gICAgICAgICAgICBjb25zdCBpbnRlcnNlY3RzID0gbmV4dC5zZXExUmFuZ2UuaW50ZXJzZWN0cyh3LnNlcTFSYW5nZSkgfHwgbmV4dC5zZXEyUmFuZ2UuaW50ZXJzZWN0cyh3LnNlcTJSYW5nZSk7XG4gICAgICAgICAgICBpZiAoIWludGVyc2VjdHMpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHYxID0gZmluZFBhcmVudChzZXF1ZW5jZTEsIG5leHQuc2VxMVJhbmdlLnN0YXJ0KTtcbiAgICAgICAgICAgIGNvbnN0IHYyID0gZmluZFBhcmVudChzZXF1ZW5jZTIsIG5leHQuc2VxMlJhbmdlLnN0YXJ0KTtcbiAgICAgICAgICAgIGNvbnN0IHYgPSBuZXcgU2VxdWVuY2VEaWZmKHYxLCB2Mik7XG4gICAgICAgICAgICBjb25zdCBlcXVhbFBhcnRWID0gdi5pbnRlcnNlY3QobmV4dCk7XG4gICAgICAgICAgICBlcXVhbENoYXJzMSArPSBlcXVhbFBhcnRWLnNlcTFSYW5nZS5sZW5ndGg7XG4gICAgICAgICAgICBlcXVhbENoYXJzMiArPSBlcXVhbFBhcnRWLnNlcTJSYW5nZS5sZW5ndGg7XG4gICAgICAgICAgICB3ID0gdy5qb2luKHYpO1xuICAgICAgICAgICAgaWYgKHcuc2VxMVJhbmdlLmVuZEV4Y2x1c2l2ZSA+PSBuZXh0LnNlcTFSYW5nZS5lbmRFeGNsdXNpdmUpIHtcbiAgICAgICAgICAgICAgICBlcXVhbE1hcHBpbmdzLnNoaWZ0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoKGZvcmNlICYmIGVxdWFsQ2hhcnMxICsgZXF1YWxDaGFyczIgPCB3LnNlcTFSYW5nZS5sZW5ndGggKyB3LnNlcTJSYW5nZS5sZW5ndGgpIHx8IGVxdWFsQ2hhcnMxICsgZXF1YWxDaGFyczIgPCAody5zZXExUmFuZ2UubGVuZ3RoICsgdy5zZXEyUmFuZ2UubGVuZ3RoKSAqIDIgLyAzKSB7XG4gICAgICAgICAgICBhZGRpdGlvbmFsLnB1c2godyk7XG4gICAgICAgIH1cbiAgICAgICAgbGFzdFBvaW50ID0gdy5nZXRFbmRFeGNsdXNpdmVzKCk7XG4gICAgfVxuICAgIHdoaWxlIChlcXVhbE1hcHBpbmdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3QgbmV4dCA9IGVxdWFsTWFwcGluZ3Muc2hpZnQoKTtcbiAgICAgICAgaWYgKG5leHQuc2VxMVJhbmdlLmlzRW1wdHkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHNjYW5Xb3JkKG5leHQuZ2V0U3RhcnRzKCksIG5leHQpO1xuICAgICAgICBzY2FuV29yZChuZXh0LmdldEVuZEV4Y2x1c2l2ZXMoKS5kZWx0YSgtMSksIG5leHQpO1xuICAgIH1cbiAgICBjb25zdCBtZXJnZWQgPSBtZXJnZVNlcXVlbmNlRGlmZnMoc2VxdWVuY2VEaWZmcywgYWRkaXRpb25hbCk7XG4gICAgcmV0dXJuIG1lcmdlZDtcbn1cbmZ1bmN0aW9uIG1lcmdlU2VxdWVuY2VEaWZmcyhzZXF1ZW5jZURpZmZzMSwgc2VxdWVuY2VEaWZmczIpIHtcbiAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICB3aGlsZSAoc2VxdWVuY2VEaWZmczEubGVuZ3RoID4gMCB8fCBzZXF1ZW5jZURpZmZzMi5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IHNkMSA9IHNlcXVlbmNlRGlmZnMxWzBdO1xuICAgICAgICBjb25zdCBzZDIgPSBzZXF1ZW5jZURpZmZzMlswXTtcbiAgICAgICAgbGV0IG5leHQ7XG4gICAgICAgIGlmIChzZDEgJiYgKCFzZDIgfHwgc2QxLnNlcTFSYW5nZS5zdGFydCA8IHNkMi5zZXExUmFuZ2Uuc3RhcnQpKSB7XG4gICAgICAgICAgICBuZXh0ID0gc2VxdWVuY2VEaWZmczEuc2hpZnQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5leHQgPSBzZXF1ZW5jZURpZmZzMi5zaGlmdCgpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXN1bHQubGVuZ3RoID4gMCAmJiByZXN1bHRbcmVzdWx0Lmxlbmd0aCAtIDFdLnNlcTFSYW5nZS5lbmRFeGNsdXNpdmUgPj0gbmV4dC5zZXExUmFuZ2Uuc3RhcnQpIHtcbiAgICAgICAgICAgIHJlc3VsdFtyZXN1bHQubGVuZ3RoIC0gMV0gPSByZXN1bHRbcmVzdWx0Lmxlbmd0aCAtIDFdLmpvaW4obmV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaChuZXh0KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuZnVuY3Rpb24gcmVtb3ZlVmVyeVNob3J0TWF0Y2hpbmdMaW5lc0JldHdlZW5EaWZmcyhzZXF1ZW5jZTEsIF9zZXF1ZW5jZTIsIHNlcXVlbmNlRGlmZnMpIHtcbiAgICBsZXQgZGlmZnMgPSBzZXF1ZW5jZURpZmZzO1xuICAgIGlmIChkaWZmcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIGRpZmZzO1xuICAgIH1cbiAgICBsZXQgY291bnRlciA9IDA7XG4gICAgbGV0IHNob3VsZFJlcGVhdDtcbiAgICBkbyB7XG4gICAgICAgIHNob3VsZFJlcGVhdCA9IGZhbHNlO1xuICAgICAgICBjb25zdCByZXN1bHQgPSBbZGlmZnNbMF1dO1xuICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IGRpZmZzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBjdXIgPSBkaWZmc1tpXTtcbiAgICAgICAgICAgIGNvbnN0IGxhc3RSZXN1bHQgPSByZXN1bHRbcmVzdWx0Lmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgZnVuY3Rpb24gc2hvdWxkSm9pbkRpZmZzKGJlZm9yZSwgYWZ0ZXIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB1bmNoYW5nZWRSYW5nZSA9IG5ldyBPZmZzZXRSYW5nZShsYXN0UmVzdWx0LnNlcTFSYW5nZS5lbmRFeGNsdXNpdmUsIGN1ci5zZXExUmFuZ2Uuc3RhcnQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHVuY2hhbmdlZFRleHQgPSBzZXF1ZW5jZTEuZ2V0VGV4dCh1bmNoYW5nZWRSYW5nZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgdW5jaGFuZ2VkVGV4dFdpdGhvdXRXcyA9IHVuY2hhbmdlZFRleHQucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICAgICAgICAgICAgICBpZiAodW5jaGFuZ2VkVGV4dFdpdGhvdXRXcy5sZW5ndGggPD0gNFxuICAgICAgICAgICAgICAgICAgICAmJiAoYmVmb3JlLnNlcTFSYW5nZS5sZW5ndGggKyBiZWZvcmUuc2VxMlJhbmdlLmxlbmd0aCA+IDUgfHwgYWZ0ZXIuc2VxMVJhbmdlLmxlbmd0aCArIGFmdGVyLnNlcTJSYW5nZS5sZW5ndGggPiA1KSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc2hvdWxkSm9pbiA9IHNob3VsZEpvaW5EaWZmcyhsYXN0UmVzdWx0LCBjdXIpO1xuICAgICAgICAgICAgaWYgKHNob3VsZEpvaW4pIHtcbiAgICAgICAgICAgICAgICBzaG91bGRSZXBlYXQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJlc3VsdFtyZXN1bHQubGVuZ3RoIC0gMV0gPSByZXN1bHRbcmVzdWx0Lmxlbmd0aCAtIDFdLmpvaW4oY3VyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGN1cik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZGlmZnMgPSByZXN1bHQ7XG4gICAgfSB3aGlsZSAoY291bnRlcisrIDwgMTAgJiYgc2hvdWxkUmVwZWF0KTtcbiAgICByZXR1cm4gZGlmZnM7XG59XG5mdW5jdGlvbiByZW1vdmVWZXJ5U2hvcnRNYXRjaGluZ1RleHRCZXR3ZWVuTG9uZ0RpZmZzKHNlcXVlbmNlMSwgc2VxdWVuY2UyLCBzZXF1ZW5jZURpZmZzKSB7XG4gICAgbGV0IGRpZmZzID0gc2VxdWVuY2VEaWZmcztcbiAgICBpZiAoZGlmZnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBkaWZmcztcbiAgICB9XG4gICAgbGV0IGNvdW50ZXIgPSAwO1xuICAgIGxldCBzaG91bGRSZXBlYXQ7XG4gICAgZG8ge1xuICAgICAgICBzaG91bGRSZXBlYXQgPSBmYWxzZTtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gW2RpZmZzWzBdXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBkaWZmcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgY3VyID0gZGlmZnNbaV07XG4gICAgICAgICAgICBjb25zdCBsYXN0UmVzdWx0ID0gcmVzdWx0W3Jlc3VsdC5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgIGZ1bmN0aW9uIHNob3VsZEpvaW5EaWZmcyhiZWZvcmUsIGFmdGVyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdW5jaGFuZ2VkUmFuZ2UgPSBuZXcgT2Zmc2V0UmFuZ2UobGFzdFJlc3VsdC5zZXExUmFuZ2UuZW5kRXhjbHVzaXZlLCBjdXIuc2VxMVJhbmdlLnN0YXJ0KTtcbiAgICAgICAgICAgICAgICBjb25zdCB1bmNoYW5nZWRMaW5lQ291bnQgPSBzZXF1ZW5jZTEuY291bnRMaW5lc0luKHVuY2hhbmdlZFJhbmdlKTtcbiAgICAgICAgICAgICAgICBpZiAodW5jaGFuZ2VkTGluZUNvdW50ID4gNSB8fCB1bmNoYW5nZWRSYW5nZS5sZW5ndGggPiA1MDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCB1bmNoYW5nZWRUZXh0ID0gc2VxdWVuY2UxLmdldFRleHQodW5jaGFuZ2VkUmFuZ2UpLnRyaW0oKTtcbiAgICAgICAgICAgICAgICBpZiAodW5jaGFuZ2VkVGV4dC5sZW5ndGggPiAyMCB8fCB1bmNoYW5nZWRUZXh0LnNwbGl0KC9cXHJcXG58XFxyfFxcbi8pLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBiZWZvcmVMaW5lQ291bnQxID0gc2VxdWVuY2UxLmNvdW50TGluZXNJbihiZWZvcmUuc2VxMVJhbmdlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBiZWZvcmVTZXExTGVuZ3RoID0gYmVmb3JlLnNlcTFSYW5nZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgY29uc3QgYmVmb3JlTGluZUNvdW50MiA9IHNlcXVlbmNlMi5jb3VudExpbmVzSW4oYmVmb3JlLnNlcTJSYW5nZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgYmVmb3JlU2VxMkxlbmd0aCA9IGJlZm9yZS5zZXEyUmFuZ2UubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGNvbnN0IGFmdGVyTGluZUNvdW50MSA9IHNlcXVlbmNlMS5jb3VudExpbmVzSW4oYWZ0ZXIuc2VxMVJhbmdlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBhZnRlclNlcTFMZW5ndGggPSBhZnRlci5zZXExUmFuZ2UubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGNvbnN0IGFmdGVyTGluZUNvdW50MiA9IHNlcXVlbmNlMi5jb3VudExpbmVzSW4oYWZ0ZXIuc2VxMlJhbmdlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBhZnRlclNlcTJMZW5ndGggPSBhZnRlci5zZXEyUmFuZ2UubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGNvbnN0IG1heCA9IDIgKiA0MCArIDUwO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGNhcCh2KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLm1pbih2LCBtYXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoTWF0aC5wb3coTWF0aC5wb3coY2FwKGJlZm9yZUxpbmVDb3VudDEgKiA0MCArIGJlZm9yZVNlcTFMZW5ndGgpLCAxLjUpICsgTWF0aC5wb3coY2FwKGJlZm9yZUxpbmVDb3VudDIgKiA0MCArIGJlZm9yZVNlcTJMZW5ndGgpLCAxLjUpLCAxLjUpXG4gICAgICAgICAgICAgICAgICAgICsgTWF0aC5wb3coTWF0aC5wb3coY2FwKGFmdGVyTGluZUNvdW50MSAqIDQwICsgYWZ0ZXJTZXExTGVuZ3RoKSwgMS41KSArIE1hdGgucG93KGNhcChhZnRlckxpbmVDb3VudDIgKiA0MCArIGFmdGVyU2VxMkxlbmd0aCksIDEuNSksIDEuNSkgPiAoKG1heCAqKiAxLjUpICoqIDEuNSkgKiAxLjMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHNob3VsZEpvaW4gPSBzaG91bGRKb2luRGlmZnMobGFzdFJlc3VsdCwgY3VyKTtcbiAgICAgICAgICAgIGlmIChzaG91bGRKb2luKSB7XG4gICAgICAgICAgICAgICAgc2hvdWxkUmVwZWF0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXN1bHRbcmVzdWx0Lmxlbmd0aCAtIDFdID0gcmVzdWx0W3Jlc3VsdC5sZW5ndGggLSAxXS5qb2luKGN1cik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChjdXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGRpZmZzID0gcmVzdWx0O1xuICAgIH0gd2hpbGUgKGNvdW50ZXIrKyA8IDEwICYmIHNob3VsZFJlcGVhdCk7XG4gICAgY29uc3QgbmV3RGlmZnMgPSBbXTtcbiAgICAvLyBSZW1vdmUgc2hvcnQgc3VmZml4ZXMvcHJlZml4ZXNcbiAgICBmb3JFYWNoV2l0aE5laWdoYm9ycyhkaWZmcywgKHByZXYsIGN1ciwgbmV4dCkgPT4ge1xuICAgICAgICBsZXQgbmV3RGlmZiA9IGN1cjtcbiAgICAgICAgZnVuY3Rpb24gc2hvdWxkTWFya0FzQ2hhbmdlZCh0ZXh0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGV4dC5sZW5ndGggPiAwICYmIHRleHQudHJpbSgpLmxlbmd0aCA8PSAzICYmIGN1ci5zZXExUmFuZ2UubGVuZ3RoICsgY3VyLnNlcTJSYW5nZS5sZW5ndGggPiAxMDA7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZnVsbFJhbmdlMSA9IHNlcXVlbmNlMS5leHRlbmRUb0Z1bGxMaW5lcyhjdXIuc2VxMVJhbmdlKTtcbiAgICAgICAgY29uc3QgcHJlZml4ID0gc2VxdWVuY2UxLmdldFRleHQobmV3IE9mZnNldFJhbmdlKGZ1bGxSYW5nZTEuc3RhcnQsIGN1ci5zZXExUmFuZ2Uuc3RhcnQpKTtcbiAgICAgICAgaWYgKHNob3VsZE1hcmtBc0NoYW5nZWQocHJlZml4KSkge1xuICAgICAgICAgICAgbmV3RGlmZiA9IG5ld0RpZmYuZGVsdGFTdGFydCgtcHJlZml4Lmxlbmd0aCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc3VmZml4ID0gc2VxdWVuY2UxLmdldFRleHQobmV3IE9mZnNldFJhbmdlKGN1ci5zZXExUmFuZ2UuZW5kRXhjbHVzaXZlLCBmdWxsUmFuZ2UxLmVuZEV4Y2x1c2l2ZSkpO1xuICAgICAgICBpZiAoc2hvdWxkTWFya0FzQ2hhbmdlZChzdWZmaXgpKSB7XG4gICAgICAgICAgICBuZXdEaWZmID0gbmV3RGlmZi5kZWx0YUVuZChzdWZmaXgubGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhdmFpbGFibGVTcGFjZSA9IFNlcXVlbmNlRGlmZi5mcm9tT2Zmc2V0UGFpcnMocHJldiA/IHByZXYuZ2V0RW5kRXhjbHVzaXZlcygpIDogT2Zmc2V0UGFpci56ZXJvLCBuZXh0ID8gbmV4dC5nZXRTdGFydHMoKSA6IE9mZnNldFBhaXIubWF4KTtcbiAgICAgICAgY29uc3QgaW50ZXJzZWN0ZWQgPSBuZXdEaWZmLmludGVyc2VjdChhdmFpbGFibGVTcGFjZSk7XG4gICAgICAgIGlmIChuZXdEaWZmcy5sZW5ndGggPiAwICYmIGludGVyc2VjdGVkLmdldFN0YXJ0cygpLmVxdWFscyhuZXdEaWZmc1tuZXdEaWZmcy5sZW5ndGggLSAxXS5nZXRFbmRFeGNsdXNpdmVzKCkpKSB7XG4gICAgICAgICAgICBuZXdEaWZmc1tuZXdEaWZmcy5sZW5ndGggLSAxXSA9IG5ld0RpZmZzW25ld0RpZmZzLmxlbmd0aCAtIDFdLmpvaW4oaW50ZXJzZWN0ZWQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbmV3RGlmZnMucHVzaChpbnRlcnNlY3RlZCk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gbmV3RGlmZnM7XG59XG5mdW5jdGlvbiBmb3JFYWNoV2l0aE5laWdoYm9ycyhpdGVtcywgY2FsbGJhY2spIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNhbGxiYWNrKGl0ZW1zW2kgLSAxXSwgaXRlbXNbaV0sIGl0ZW1zW2kgKyAxXSk7XG4gICAgfVxufVxuXG5jb25zdCBDaGFyQ29kZSQxID0ge1xuICAgIFNwYWNlOiAzMixcbiAgICBUYWI6IDksXG59O1xuY2xhc3MgTGluZVNlcXVlbmNlIHtcbiAgICB0cmltbWVkSGFzaDtcbiAgICBsaW5lcztcbiAgICBjb25zdHJ1Y3Rvcih0cmltbWVkSGFzaCwgbGluZXMpIHtcbiAgICAgICAgdGhpcy50cmltbWVkSGFzaCA9IHRyaW1tZWRIYXNoO1xuICAgICAgICB0aGlzLmxpbmVzID0gbGluZXM7XG4gICAgfVxuICAgIGdldEVsZW1lbnQob2Zmc2V0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRyaW1tZWRIYXNoW29mZnNldF07XG4gICAgfVxuICAgIGdldCBsZW5ndGgoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRyaW1tZWRIYXNoLmxlbmd0aDtcbiAgICB9XG4gICAgZ2V0Qm91bmRhcnlTY29yZShsZW5ndGgpIHtcbiAgICAgICAgY29uc3QgaW5kZW50YXRpb25CZWZvcmUgPSBsZW5ndGggPT09IDAgPyAwIDogZ2V0SW5kZW50YXRpb24odGhpcy5saW5lc1tsZW5ndGggLSAxXSk7XG4gICAgICAgIGNvbnN0IGluZGVudGF0aW9uQWZ0ZXIgPSBsZW5ndGggPT09IHRoaXMubGluZXMubGVuZ3RoID8gMCA6IGdldEluZGVudGF0aW9uKHRoaXMubGluZXNbbGVuZ3RoXSk7XG4gICAgICAgIHJldHVybiAxMDAwIC0gKGluZGVudGF0aW9uQmVmb3JlICsgaW5kZW50YXRpb25BZnRlcik7XG4gICAgfVxuICAgIGdldFRleHQocmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGluZXMuc2xpY2UocmFuZ2Uuc3RhcnQsIHJhbmdlLmVuZEV4Y2x1c2l2ZSkuam9pbignXFxuJyk7XG4gICAgfVxuICAgIGlzU3Ryb25nbHlFcXVhbChvZmZzZXQxLCBvZmZzZXQyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxpbmVzW29mZnNldDFdID09PSB0aGlzLmxpbmVzW29mZnNldDJdO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGdldEluZGVudGF0aW9uKHN0cikge1xuICAgIGxldCBpID0gMDtcbiAgICB3aGlsZSAoaSA8IHN0ci5sZW5ndGggJiYgKHN0ci5jaGFyQ29kZUF0KGkpID09PSBDaGFyQ29kZSQxLlNwYWNlIHx8IHN0ci5jaGFyQ29kZUF0KGkpID09PSBDaGFyQ29kZSQxLlRhYikpIHtcbiAgICAgICAgaSsrO1xuICAgIH1cbiAgICByZXR1cm4gaTtcbn1cblxuY29uc3QgQ2hhckNvZGUgPSB7XG4gICAgTGluZUZlZWQ6IDEwLFxuICAgIENhcnJpYWdlUmV0dXJuOiAxMyxcbiAgICBTcGFjZTogMzIsXG4gICAgVGFiOiA5LFxuICAgIGE6IDk3LFxuICAgIHo6IDEyMixcbiAgICBBOiA2NSxcbiAgICBaOiA5MCxcbiAgICBEaWdpdDA6IDQ4LFxuICAgIERpZ2l0OTogNTcsXG4gICAgQ29tbWE6IDQ0LFxuICAgIFNlbWljb2xvbjogNTksXG59O1xuZnVuY3Rpb24gaXNTcGFjZShjaGFyQ29kZSkge1xuICAgIHJldHVybiBjaGFyQ29kZSA9PT0gQ2hhckNvZGUuU3BhY2UgfHwgY2hhckNvZGUgPT09IENoYXJDb2RlLlRhYjtcbn1cbmNsYXNzIFJhbmdlIHtcbiAgICBzdGFydExpbmVOdW1iZXI7XG4gICAgc3RhcnRDb2x1bW47XG4gICAgZW5kTGluZU51bWJlcjtcbiAgICBlbmRDb2x1bW47XG4gICAgY29uc3RydWN0b3Ioc3RhcnRMaW5lTnVtYmVyLCBzdGFydENvbHVtbiwgZW5kTGluZU51bWJlciwgZW5kQ29sdW1uKSB7XG4gICAgICAgIHRoaXMuc3RhcnRMaW5lTnVtYmVyID0gc3RhcnRMaW5lTnVtYmVyO1xuICAgICAgICB0aGlzLnN0YXJ0Q29sdW1uID0gc3RhcnRDb2x1bW47XG4gICAgICAgIHRoaXMuZW5kTGluZU51bWJlciA9IGVuZExpbmVOdW1iZXI7XG4gICAgICAgIHRoaXMuZW5kQ29sdW1uID0gZW5kQ29sdW1uO1xuICAgIH1cbiAgICBzdGF0aWMgZnJvbVBvc2l0aW9ucyhzdGFydCwgZW5kKSB7XG4gICAgICAgIHJldHVybiBuZXcgUmFuZ2Uoc3RhcnQubGluZU51bWJlciwgc3RhcnQuY29sdW1uLCBlbmQubGluZU51bWJlciwgZW5kLmNvbHVtbik7XG4gICAgfVxufVxuY2xhc3MgUG9zaXRpb24ge1xuICAgIGxpbmVOdW1iZXI7XG4gICAgY29sdW1uO1xuICAgIGNvbnN0cnVjdG9yKGxpbmVOdW1iZXIsIGNvbHVtbikge1xuICAgICAgICB0aGlzLmxpbmVOdW1iZXIgPSBsaW5lTnVtYmVyO1xuICAgICAgICB0aGlzLmNvbHVtbiA9IGNvbHVtbjtcbiAgICB9XG4gICAgaXNCZWZvcmUob3RoZXIpIHtcbiAgICAgICAgaWYgKHRoaXMubGluZU51bWJlciA8IG90aGVyLmxpbmVOdW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvdGhlci5saW5lTnVtYmVyIDwgdGhpcy5saW5lTnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuY29sdW1uIDwgb3RoZXIuY29sdW1uO1xuICAgIH1cbn1cbmNsYXNzIExpbmVzU2xpY2VDaGFyU2VxdWVuY2Uge1xuICAgIGxpbmVzO1xuICAgIGNvbnNpZGVyV2hpdGVzcGFjZUNoYW5nZXM7XG4gICAgZWxlbWVudHMgPSBbXTtcbiAgICBmaXJzdEVsZW1lbnRPZmZzZXRCeUxpbmVJZHggPSBbXTtcbiAgICBsaW5lU3RhcnRPZmZzZXRzID0gW107XG4gICAgdHJpbW1lZFdzTGVuZ3Roc0J5TGluZUlkeCA9IFtdO1xuICAgIF9yYW5nZTtcbiAgICBjb25zdHJ1Y3RvcihsaW5lcywgcmFuZ2UsIGNvbnNpZGVyV2hpdGVzcGFjZUNoYW5nZXMpIHtcbiAgICAgICAgdGhpcy5saW5lcyA9IGxpbmVzO1xuICAgICAgICB0aGlzLmNvbnNpZGVyV2hpdGVzcGFjZUNoYW5nZXMgPSBjb25zaWRlcldoaXRlc3BhY2VDaGFuZ2VzO1xuICAgICAgICB0aGlzLl9yYW5nZSA9IHJhbmdlO1xuICAgICAgICB0aGlzLmZpcnN0RWxlbWVudE9mZnNldEJ5TGluZUlkeC5wdXNoKDApO1xuICAgICAgICBmb3IgKGxldCBsaW5lTnVtYmVyID0gdGhpcy5fcmFuZ2Uuc3RhcnRMaW5lTnVtYmVyOyBsaW5lTnVtYmVyIDw9IHRoaXMuX3JhbmdlLmVuZExpbmVOdW1iZXI7IGxpbmVOdW1iZXIrKykge1xuICAgICAgICAgICAgbGV0IGxpbmUgPSBsaW5lc1tsaW5lTnVtYmVyIC0gMV07XG4gICAgICAgICAgICBsZXQgbGluZVN0YXJ0T2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIGlmIChsaW5lTnVtYmVyID09PSB0aGlzLl9yYW5nZS5zdGFydExpbmVOdW1iZXIgJiYgdGhpcy5fcmFuZ2Uuc3RhcnRDb2x1bW4gPiAxKSB7XG4gICAgICAgICAgICAgICAgbGluZVN0YXJ0T2Zmc2V0ID0gdGhpcy5fcmFuZ2Uuc3RhcnRDb2x1bW4gLSAxO1xuICAgICAgICAgICAgICAgIGxpbmUgPSBsaW5lLnN1YnN0cmluZyhsaW5lU3RhcnRPZmZzZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5saW5lU3RhcnRPZmZzZXRzLnB1c2gobGluZVN0YXJ0T2Zmc2V0KTtcbiAgICAgICAgICAgIGxldCB0cmltbWVkV3NMZW5ndGggPSAwO1xuICAgICAgICAgICAgaWYgKCFjb25zaWRlcldoaXRlc3BhY2VDaGFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdHJpbW1lZFN0YXJ0TGluZSA9IGxpbmUudHJpbVN0YXJ0KCk7XG4gICAgICAgICAgICAgICAgdHJpbW1lZFdzTGVuZ3RoID0gbGluZS5sZW5ndGggLSB0cmltbWVkU3RhcnRMaW5lLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBsaW5lID0gdHJpbW1lZFN0YXJ0TGluZS50cmltRW5kKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnRyaW1tZWRXc0xlbmd0aHNCeUxpbmVJZHgucHVzaCh0cmltbWVkV3NMZW5ndGgpO1xuICAgICAgICAgICAgY29uc3QgbGluZUxlbmd0aCA9IGxpbmVOdW1iZXIgPT09IHRoaXMuX3JhbmdlLmVuZExpbmVOdW1iZXIgPyBNYXRoLm1pbih0aGlzLl9yYW5nZS5lbmRDb2x1bW4gLSAxIC0gbGluZVN0YXJ0T2Zmc2V0IC0gdHJpbW1lZFdzTGVuZ3RoLCBsaW5lLmxlbmd0aCkgOiBsaW5lLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGluZUxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50cy5wdXNoKGxpbmUuY2hhckNvZGVBdChpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobGluZU51bWJlciA8IHRoaXMuX3JhbmdlLmVuZExpbmVOdW1iZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVsZW1lbnRzLnB1c2goJ1xcbicuY2hhckNvZGVBdCgwKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJzdEVsZW1lbnRPZmZzZXRCeUxpbmVJZHgucHVzaCh0aGlzLmVsZW1lbnRzLmxlbmd0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgdG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiBgU2xpY2U6IFwiJHt0aGlzLnRleHR9XCJgO1xuICAgIH1cbiAgICBnZXQgdGV4dCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VGV4dChuZXcgT2Zmc2V0UmFuZ2UoMCwgdGhpcy5sZW5ndGgpKTtcbiAgICB9XG4gICAgZ2V0VGV4dChyYW5nZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbGVtZW50cy5zbGljZShyYW5nZS5zdGFydCwgcmFuZ2UuZW5kRXhjbHVzaXZlKS5tYXAoZSA9PiBTdHJpbmcuZnJvbUNoYXJDb2RlKGUpKS5qb2luKCcnKTtcbiAgICB9XG4gICAgZ2V0RWxlbWVudChvZmZzZXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudHNbb2Zmc2V0XTtcbiAgICB9XG4gICAgZ2V0IGxlbmd0aCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudHMubGVuZ3RoO1xuICAgIH1cbiAgICBnZXRCb3VuZGFyeVNjb3JlKGxlbmd0aCkge1xuICAgICAgICBjb25zdCBwcmV2Q2F0ZWdvcnkgPSBnZXRDYXRlZ29yeShsZW5ndGggPiAwID8gdGhpcy5lbGVtZW50c1tsZW5ndGggLSAxXSA6IC0xKTtcbiAgICAgICAgY29uc3QgbmV4dENhdGVnb3J5ID0gZ2V0Q2F0ZWdvcnkobGVuZ3RoIDwgdGhpcy5lbGVtZW50cy5sZW5ndGggPyB0aGlzLmVsZW1lbnRzW2xlbmd0aF0gOiAtMSk7XG4gICAgICAgIGlmIChwcmV2Q2F0ZWdvcnkgPT09IDcgLyogQ2hhckJvdW5kYXJ5Q2F0ZWdvcnkuTGluZUJyZWFrQ1IgKi8gJiYgbmV4dENhdGVnb3J5ID09PSA4IC8qIENoYXJCb3VuZGFyeUNhdGVnb3J5LkxpbmVCcmVha0xGICovKSB7XG4gICAgICAgICAgICAvLyBkb24ndCBicmVhayBiZXR3ZWVuIFxcciBhbmQgXFxuXG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAocHJldkNhdGVnb3J5ID09PSA4IC8qIENoYXJCb3VuZGFyeUNhdGVnb3J5LkxpbmVCcmVha0xGICovKSB7XG4gICAgICAgICAgICAvLyBwcmVmZXIgdGhlIGxpbmVicmVhayBiZWZvcmUgdGhlIGNoYW5nZVxuICAgICAgICAgICAgcmV0dXJuIDE1MDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgc2NvcmUgPSAwO1xuICAgICAgICBpZiAocHJldkNhdGVnb3J5ICE9PSBuZXh0Q2F0ZWdvcnkpIHtcbiAgICAgICAgICAgIHNjb3JlICs9IDEwO1xuICAgICAgICAgICAgaWYgKHByZXZDYXRlZ29yeSA9PT0gMCAvKiBDaGFyQm91bmRhcnlDYXRlZ29yeS5Xb3JkTG93ZXIgKi8gJiYgbmV4dENhdGVnb3J5ID09PSAxIC8qIENoYXJCb3VuZGFyeUNhdGVnb3J5LldvcmRVcHBlciAqLykge1xuICAgICAgICAgICAgICAgIHNjb3JlICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc2NvcmUgKz0gZ2V0Q2F0ZWdvcnlCb3VuZGFyeVNjb3JlKHByZXZDYXRlZ29yeSk7XG4gICAgICAgIHNjb3JlICs9IGdldENhdGVnb3J5Qm91bmRhcnlTY29yZShuZXh0Q2F0ZWdvcnkpO1xuICAgICAgICByZXR1cm4gc2NvcmU7XG4gICAgfVxuICAgIHRyYW5zbGF0ZU9mZnNldChvZmZzZXQsIHByZWZlcmVuY2UgPSAncmlnaHQnKSB7XG4gICAgICAgIGNvbnN0IGkgPSBmaW5kTGFzdElkeE1vbm90b25vdXModGhpcy5maXJzdEVsZW1lbnRPZmZzZXRCeUxpbmVJZHgsICh2YWx1ZSkgPT4gdmFsdWUgPD0gb2Zmc2V0KTtcbiAgICAgICAgY29uc3QgbGluZU9mZnNldCA9IG9mZnNldCAtIHRoaXMuZmlyc3RFbGVtZW50T2Zmc2V0QnlMaW5lSWR4W2ldO1xuICAgICAgICByZXR1cm4gbmV3IFBvc2l0aW9uKHRoaXMuX3JhbmdlLnN0YXJ0TGluZU51bWJlciArIGksIDEgKyB0aGlzLmxpbmVTdGFydE9mZnNldHNbaV0gKyBsaW5lT2Zmc2V0ICsgKChsaW5lT2Zmc2V0ID09PSAwICYmIHByZWZlcmVuY2UgPT09ICdsZWZ0JykgPyAwIDogdGhpcy50cmltbWVkV3NMZW5ndGhzQnlMaW5lSWR4W2ldKSk7XG4gICAgfVxuICAgIHRyYW5zbGF0ZVJhbmdlKHJhbmdlKSB7XG4gICAgICAgIGNvbnN0IHBvczEgPSB0aGlzLnRyYW5zbGF0ZU9mZnNldChyYW5nZS5zdGFydCwgJ3JpZ2h0Jyk7XG4gICAgICAgIGNvbnN0IHBvczIgPSB0aGlzLnRyYW5zbGF0ZU9mZnNldChyYW5nZS5lbmRFeGNsdXNpdmUsICdsZWZ0Jyk7XG4gICAgICAgIGlmIChwb3MyLmlzQmVmb3JlKHBvczEpKSB7XG4gICAgICAgICAgICByZXR1cm4gUmFuZ2UuZnJvbVBvc2l0aW9ucyhwb3MyLCBwb3MyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUmFuZ2UuZnJvbVBvc2l0aW9ucyhwb3MxLCBwb3MyKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRmluZHMgdGhlIHdvcmQgdGhhdCBjb250YWlucyB0aGUgY2hhcmFjdGVyIGF0IHRoZSBnaXZlbiBvZmZzZXRcbiAgICAgKi9cbiAgICBmaW5kV29yZENvbnRhaW5pbmcob2Zmc2V0KSB7XG4gICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IG9mZnNldCA+PSB0aGlzLmVsZW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzV29yZENoYXIodGhpcy5lbGVtZW50c1tvZmZzZXRdKSkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICAvLyBmaW5kIHN0YXJ0XG4gICAgICAgIGxldCBzdGFydCA9IG9mZnNldDtcbiAgICAgICAgd2hpbGUgKHN0YXJ0ID4gMCAmJiBpc1dvcmRDaGFyKHRoaXMuZWxlbWVudHNbc3RhcnQgLSAxXSkpIHtcbiAgICAgICAgICAgIHN0YXJ0LS07XG4gICAgICAgIH1cbiAgICAgICAgLy8gZmluZCBlbmRcbiAgICAgICAgbGV0IGVuZCA9IG9mZnNldDtcbiAgICAgICAgd2hpbGUgKGVuZCA8IHRoaXMuZWxlbWVudHMubGVuZ3RoICYmIGlzV29yZENoYXIodGhpcy5lbGVtZW50c1tlbmRdKSkge1xuICAgICAgICAgICAgZW5kKys7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBPZmZzZXRSYW5nZShzdGFydCwgZW5kKTtcbiAgICB9XG4gICAgLyoqIGZvb0JhciBoYXMgdGhlIHR3byBzdWItd29yZHMgZm9vIGFuZCBiYXIgKi9cbiAgICBmaW5kU3ViV29yZENvbnRhaW5pbmcob2Zmc2V0KSB7XG4gICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IG9mZnNldCA+PSB0aGlzLmVsZW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzV29yZENoYXIodGhpcy5lbGVtZW50c1tvZmZzZXRdKSkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICAvLyBmaW5kIHN0YXJ0XG4gICAgICAgIGxldCBzdGFydCA9IG9mZnNldDtcbiAgICAgICAgd2hpbGUgKHN0YXJ0ID4gMCAmJiBpc1dvcmRDaGFyKHRoaXMuZWxlbWVudHNbc3RhcnQgLSAxXSkgJiYgIWlzVXBwZXJDYXNlKHRoaXMuZWxlbWVudHNbc3RhcnRdKSkge1xuICAgICAgICAgICAgc3RhcnQtLTtcbiAgICAgICAgfVxuICAgICAgICAvLyBmaW5kIGVuZFxuICAgICAgICBsZXQgZW5kID0gb2Zmc2V0O1xuICAgICAgICB3aGlsZSAoZW5kIDwgdGhpcy5lbGVtZW50cy5sZW5ndGggJiYgaXNXb3JkQ2hhcih0aGlzLmVsZW1lbnRzW2VuZF0pICYmICFpc1VwcGVyQ2FzZSh0aGlzLmVsZW1lbnRzW2VuZF0pKSB7XG4gICAgICAgICAgICBlbmQrKztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IE9mZnNldFJhbmdlKHN0YXJ0LCBlbmQpO1xuICAgIH1cbiAgICBjb3VudExpbmVzSW4ocmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRlT2Zmc2V0KHJhbmdlLmVuZEV4Y2x1c2l2ZSkubGluZU51bWJlciAtIHRoaXMudHJhbnNsYXRlT2Zmc2V0KHJhbmdlLnN0YXJ0KS5saW5lTnVtYmVyO1xuICAgIH1cbiAgICBpc1N0cm9uZ2x5RXF1YWwob2Zmc2V0MSwgb2Zmc2V0Mikge1xuICAgICAgICByZXR1cm4gdGhpcy5lbGVtZW50c1tvZmZzZXQxXSA9PT0gdGhpcy5lbGVtZW50c1tvZmZzZXQyXTtcbiAgICB9XG4gICAgZXh0ZW5kVG9GdWxsTGluZXMocmFuZ2UpIHtcbiAgICAgICAgY29uc3Qgc3RhcnQgPSBmaW5kTGFzdE1vbm90b25vdXModGhpcy5maXJzdEVsZW1lbnRPZmZzZXRCeUxpbmVJZHgsIHggPT4geCA8PSByYW5nZS5zdGFydCkgPz8gMDtcbiAgICAgICAgY29uc3QgZW5kID0gZmluZEZpcnN0TW9ub3Rvbm91cyh0aGlzLmZpcnN0RWxlbWVudE9mZnNldEJ5TGluZUlkeCwgeCA9PiByYW5nZS5lbmRFeGNsdXNpdmUgPD0geCkgPz8gdGhpcy5lbGVtZW50cy5sZW5ndGg7XG4gICAgICAgIHJldHVybiBuZXcgT2Zmc2V0UmFuZ2Uoc3RhcnQsIGVuZCk7XG4gICAgfVxufVxuZnVuY3Rpb24gaXNXb3JkQ2hhcihjaGFyQ29kZSkge1xuICAgIHJldHVybiBjaGFyQ29kZSA+PSBDaGFyQ29kZS5hICYmIGNoYXJDb2RlIDw9IENoYXJDb2RlLnpcbiAgICAgICAgfHwgY2hhckNvZGUgPj0gQ2hhckNvZGUuQSAmJiBjaGFyQ29kZSA8PSBDaGFyQ29kZS5aXG4gICAgICAgIHx8IGNoYXJDb2RlID49IENoYXJDb2RlLkRpZ2l0MCAmJiBjaGFyQ29kZSA8PSBDaGFyQ29kZS5EaWdpdDk7XG59XG5mdW5jdGlvbiBpc1VwcGVyQ2FzZShjaGFyQ29kZSkge1xuICAgIHJldHVybiBjaGFyQ29kZSA+PSBDaGFyQ29kZS5BICYmIGNoYXJDb2RlIDw9IENoYXJDb2RlLlo7XG59XG5jb25zdCBjYXRlZ29yeVNjb3JlID0ge1xuICAgIFswIC8qIENoYXJCb3VuZGFyeUNhdGVnb3J5LldvcmRMb3dlciAqL106IDAsXG4gICAgWzEgLyogQ2hhckJvdW5kYXJ5Q2F0ZWdvcnkuV29yZFVwcGVyICovXTogMCxcbiAgICBbMiAvKiBDaGFyQm91bmRhcnlDYXRlZ29yeS5Xb3JkTnVtYmVyICovXTogMCxcbiAgICBbMyAvKiBDaGFyQm91bmRhcnlDYXRlZ29yeS5FbmQgKi9dOiAxMCxcbiAgICBbNCAvKiBDaGFyQm91bmRhcnlDYXRlZ29yeS5PdGhlciAqL106IDIsXG4gICAgWzUgLyogQ2hhckJvdW5kYXJ5Q2F0ZWdvcnkuU2VwYXJhdG9yICovXTogMzAsXG4gICAgWzYgLyogQ2hhckJvdW5kYXJ5Q2F0ZWdvcnkuU3BhY2UgKi9dOiAzLFxuICAgIFs3IC8qIENoYXJCb3VuZGFyeUNhdGVnb3J5LkxpbmVCcmVha0NSICovXTogMTAsXG4gICAgWzggLyogQ2hhckJvdW5kYXJ5Q2F0ZWdvcnkuTGluZUJyZWFrTEYgKi9dOiAxMCxcbn07XG5mdW5jdGlvbiBnZXRDYXRlZ29yeUJvdW5kYXJ5U2NvcmUoY2F0ZWdvcnkpIHtcbiAgICByZXR1cm4gY2F0ZWdvcnlTY29yZVtjYXRlZ29yeV07XG59XG5mdW5jdGlvbiBnZXRDYXRlZ29yeShjaGFyQ29kZSkge1xuICAgIGlmIChjaGFyQ29kZSA9PT0gQ2hhckNvZGUuTGluZUZlZWQpIHtcbiAgICAgICAgcmV0dXJuIDggLyogQ2hhckJvdW5kYXJ5Q2F0ZWdvcnkuTGluZUJyZWFrTEYgKi87XG4gICAgfVxuICAgIGVsc2UgaWYgKGNoYXJDb2RlID09PSBDaGFyQ29kZS5DYXJyaWFnZVJldHVybikge1xuICAgICAgICByZXR1cm4gNyAvKiBDaGFyQm91bmRhcnlDYXRlZ29yeS5MaW5lQnJlYWtDUiAqLztcbiAgICB9XG4gICAgZWxzZSBpZiAoaXNTcGFjZShjaGFyQ29kZSkpIHtcbiAgICAgICAgcmV0dXJuIDYgLyogQ2hhckJvdW5kYXJ5Q2F0ZWdvcnkuU3BhY2UgKi87XG4gICAgfVxuICAgIGVsc2UgaWYgKGNoYXJDb2RlID49IENoYXJDb2RlLmEgJiYgY2hhckNvZGUgPD0gQ2hhckNvZGUueikge1xuICAgICAgICByZXR1cm4gMCAvKiBDaGFyQm91bmRhcnlDYXRlZ29yeS5Xb3JkTG93ZXIgKi87XG4gICAgfVxuICAgIGVsc2UgaWYgKGNoYXJDb2RlID49IENoYXJDb2RlLkEgJiYgY2hhckNvZGUgPD0gQ2hhckNvZGUuWikge1xuICAgICAgICByZXR1cm4gMSAvKiBDaGFyQm91bmRhcnlDYXRlZ29yeS5Xb3JkVXBwZXIgKi87XG4gICAgfVxuICAgIGVsc2UgaWYgKGNoYXJDb2RlID49IENoYXJDb2RlLkRpZ2l0MCAmJiBjaGFyQ29kZSA8PSBDaGFyQ29kZS5EaWdpdDkpIHtcbiAgICAgICAgcmV0dXJuIDIgLyogQ2hhckJvdW5kYXJ5Q2F0ZWdvcnkuV29yZE51bWJlciAqLztcbiAgICB9XG4gICAgZWxzZSBpZiAoY2hhckNvZGUgPT09IC0xKSB7XG4gICAgICAgIHJldHVybiAzIC8qIENoYXJCb3VuZGFyeUNhdGVnb3J5LkVuZCAqLztcbiAgICB9XG4gICAgZWxzZSBpZiAoY2hhckNvZGUgPT09IENoYXJDb2RlLkNvbW1hIHx8IGNoYXJDb2RlID09PSBDaGFyQ29kZS5TZW1pY29sb24pIHtcbiAgICAgICAgcmV0dXJuIDUgLyogQ2hhckJvdW5kYXJ5Q2F0ZWdvcnkuU2VwYXJhdG9yICovO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIDQgLyogQ2hhckJvdW5kYXJ5Q2F0ZWdvcnkuT3RoZXIgKi87XG4gICAgfVxufVxuLy8gQmluYXJ5IHNlYXJjaCBoZWxwZXJzXG5mdW5jdGlvbiBmaW5kTGFzdElkeE1vbm90b25vdXMoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgIGxldCBsb3cgPSAwO1xuICAgIGxldCBoaWdoID0gYXJyYXkubGVuZ3RoIC0gMTtcbiAgICB3aGlsZSAobG93IDw9IGhpZ2gpIHtcbiAgICAgICAgY29uc3QgbWlkID0gTWF0aC5mbG9vcigobG93ICsgaGlnaCkgLyAyKTtcbiAgICAgICAgaWYgKHByZWRpY2F0ZShhcnJheVttaWRdKSkge1xuICAgICAgICAgICAgbG93ID0gbWlkICsgMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGhpZ2ggPSBtaWQgLSAxO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBoaWdoO1xufVxuZnVuY3Rpb24gZmluZExhc3RNb25vdG9ub3VzKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgICBjb25zdCBpZHggPSBmaW5kTGFzdElkeE1vbm90b25vdXMoYXJyYXksIHByZWRpY2F0ZSk7XG4gICAgcmV0dXJuIGlkeCA+PSAwID8gYXJyYXlbaWR4XSA6IHVuZGVmaW5lZDtcbn1cbmZ1bmN0aW9uIGZpbmRGaXJzdE1vbm90b25vdXMoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgIGxldCBsb3cgPSAwO1xuICAgIGxldCBoaWdoID0gYXJyYXkubGVuZ3RoIC0gMTtcbiAgICB3aGlsZSAobG93IDw9IGhpZ2gpIHtcbiAgICAgICAgY29uc3QgbWlkID0gTWF0aC5mbG9vcigobG93ICsgaGlnaCkgLyAyKTtcbiAgICAgICAgaWYgKHByZWRpY2F0ZShhcnJheVttaWRdKSkge1xuICAgICAgICAgICAgaGlnaCA9IG1pZCAtIDE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsb3cgPSBtaWQgKyAxO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBsb3cgPCBhcnJheS5sZW5ndGggPyBhcnJheVtsb3ddIDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIEEgcmFuZ2Ugb2YgbGluZXMgKDEtYmFzZWQsIGVuZCBpcyBleGNsdXNpdmUpLlxuICovXG5jbGFzcyBMaW5lUmFuZ2Uge1xuICAgIHN0YXJ0TGluZU51bWJlcjtcbiAgICBlbmRMaW5lTnVtYmVyRXhjbHVzaXZlO1xuICAgIGNvbnN0cnVjdG9yKHN0YXJ0TGluZU51bWJlciwgZW5kTGluZU51bWJlckV4Y2x1c2l2ZSkge1xuICAgICAgICB0aGlzLnN0YXJ0TGluZU51bWJlciA9IHN0YXJ0TGluZU51bWJlcjtcbiAgICAgICAgdGhpcy5lbmRMaW5lTnVtYmVyRXhjbHVzaXZlID0gZW5kTGluZU51bWJlckV4Y2x1c2l2ZTtcbiAgICAgICAgaWYgKHN0YXJ0TGluZU51bWJlciA+IGVuZExpbmVOdW1iZXJFeGNsdXNpdmUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByYW5nZTogJHtzdGFydExpbmVOdW1iZXJ9ID4gJHtlbmRMaW5lTnVtYmVyRXhjbHVzaXZlfWApO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldCBpc0VtcHR5KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGFydExpbmVOdW1iZXIgPT09IHRoaXMuZW5kTGluZU51bWJlckV4Y2x1c2l2ZTtcbiAgICB9XG4gICAgZ2V0IGxlbmd0aCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSAtIHRoaXMuc3RhcnRMaW5lTnVtYmVyO1xuICAgIH1cbiAgICBqb2luKG90aGVyKSB7XG4gICAgICAgIHJldHVybiBuZXcgTGluZVJhbmdlKE1hdGgubWluKHRoaXMuc3RhcnRMaW5lTnVtYmVyLCBvdGhlci5zdGFydExpbmVOdW1iZXIpLCBNYXRoLm1heCh0aGlzLmVuZExpbmVOdW1iZXJFeGNsdXNpdmUsIG90aGVyLmVuZExpbmVOdW1iZXJFeGNsdXNpdmUpKTtcbiAgICB9XG4gICAgaW50ZXJzZWN0c09yVG91Y2hlcyhvdGhlcikge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGFydExpbmVOdW1iZXIgPD0gb3RoZXIuZW5kTGluZU51bWJlckV4Y2x1c2l2ZVxuICAgICAgICAgICAgJiYgb3RoZXIuc3RhcnRMaW5lTnVtYmVyIDw9IHRoaXMuZW5kTGluZU51bWJlckV4Y2x1c2l2ZTtcbiAgICB9XG4gICAgdG9PZmZzZXRSYW5nZSgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBPZmZzZXRSYW5nZSh0aGlzLnN0YXJ0TGluZU51bWJlciAtIDEsIHRoaXMuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSAtIDEpO1xuICAgIH1cbiAgICB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIGBbJHt0aGlzLnN0YXJ0TGluZU51bWJlcn0sICR7dGhpcy5lbmRMaW5lTnVtYmVyRXhjbHVzaXZlfSlgO1xuICAgIH1cbn1cbi8qKlxuICogQSBtYXBwaW5nIGJldHdlZW4gdHdvIHJhbmdlcy5cbiAqL1xuY2xhc3MgUmFuZ2VNYXBwaW5nIHtcbiAgICBvcmlnaW5hbFJhbmdlO1xuICAgIG1vZGlmaWVkUmFuZ2U7XG4gICAgY29uc3RydWN0b3Iob3JpZ2luYWxSYW5nZSwgbW9kaWZpZWRSYW5nZSkge1xuICAgICAgICB0aGlzLm9yaWdpbmFsUmFuZ2UgPSBvcmlnaW5hbFJhbmdlO1xuICAgICAgICB0aGlzLm1vZGlmaWVkUmFuZ2UgPSBtb2RpZmllZFJhbmdlO1xuICAgIH1cbiAgICB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIGAke3JhbmdlVG9TdHJpbmcodGhpcy5vcmlnaW5hbFJhbmdlKX0gPC0+ICR7cmFuZ2VUb1N0cmluZyh0aGlzLm1vZGlmaWVkUmFuZ2UpfWA7XG4gICAgfVxuICAgIHN0YXRpYyBhc3NlcnRTb3J0ZWQocmFuZ2VNYXBwaW5ncykge1xuICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHJhbmdlTWFwcGluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHByZXYgPSByYW5nZU1hcHBpbmdzW2kgLSAxXTtcbiAgICAgICAgICAgIGNvbnN0IGN1ciA9IHJhbmdlTWFwcGluZ3NbaV07XG4gICAgICAgICAgICBpZiAoIShwcmV2Lm9yaWdpbmFsUmFuZ2UuZW5kTGluZU51bWJlciA8PSBjdXIub3JpZ2luYWxSYW5nZS5zdGFydExpbmVOdW1iZXIgfHxcbiAgICAgICAgICAgICAgICAocHJldi5vcmlnaW5hbFJhbmdlLmVuZExpbmVOdW1iZXIgPT09IGN1ci5vcmlnaW5hbFJhbmdlLnN0YXJ0TGluZU51bWJlciAmJiBwcmV2Lm9yaWdpbmFsUmFuZ2UuZW5kQ29sdW1uIDw9IGN1ci5vcmlnaW5hbFJhbmdlLnN0YXJ0Q29sdW1uKSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JhbmdlTWFwcGluZ3MgbXVzdCBiZSBzb3J0ZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cbmZ1bmN0aW9uIHJhbmdlVG9TdHJpbmcocmFuZ2UpIHtcbiAgICByZXR1cm4gYCgke3JhbmdlLnN0YXJ0TGluZU51bWJlcn06JHtyYW5nZS5zdGFydENvbHVtbn0pLSgke3JhbmdlLmVuZExpbmVOdW1iZXJ9OiR7cmFuZ2UuZW5kQ29sdW1ufSlgO1xufVxuLyoqXG4gKiBBIG1hcHBpbmcgYmV0d2VlbiB0d28gbGluZSByYW5nZXMuXG4gKi9cbmNsYXNzIExpbmVSYW5nZU1hcHBpbmcge1xuICAgIG9yaWdpbmFsO1xuICAgIG1vZGlmaWVkO1xuICAgIGNvbnN0cnVjdG9yKG9yaWdpbmFsLCBtb2RpZmllZCkge1xuICAgICAgICB0aGlzLm9yaWdpbmFsID0gb3JpZ2luYWw7XG4gICAgICAgIHRoaXMubW9kaWZpZWQgPSBtb2RpZmllZDtcbiAgICB9XG4gICAgdG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiBgJHt0aGlzLm9yaWdpbmFsfSA8LT4gJHt0aGlzLm1vZGlmaWVkfWA7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGFzc3VtZXMgdGhhdCB0aGUgTGluZVJhbmdlTWFwcGluZyBkZXNjcmliZXMgYSB2YWxpZCBkaWZmIVxuICAgICAqIEkuZS4gaWYgb25lIHJhbmdlIGlzIGVtcHR5LCB0aGUgb3RoZXIgcmFuZ2UgY2Fubm90IGJlIHRoZSBlbnRpcmUgZG9jdW1lbnQuXG4gICAgICogSXQgYXZvaWRzIHZhcmlvdXMgcHJvYmxlbXMgd2hlbiB0aGUgbGluZSByYW5nZSBwb2ludHMgdG8gbm9uLWV4aXN0aW5nIGxpbmUtbnVtYmVycy5cbiAgICAqL1xuICAgIHRvUmFuZ2VNYXBwaW5nMihvcmlnaW5hbExpbmVzLCBtb2RpZmllZExpbmVzKSB7XG4gICAgICAgIGNvbnN0IGlzVmFsaWRMaW5lTnVtYmVyID0gKGxpbmVOdW1iZXIsIGxpbmVzKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gbGluZU51bWJlciA+PSAxICYmIGxpbmVOdW1iZXIgPD0gbGluZXMubGVuZ3RoO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBub3JtYWxpemVQb3NpdGlvbiA9IChsaW5lTnVtYmVyLCBjb2x1bW4sIGxpbmVzKSA9PiB7XG4gICAgICAgICAgICBpZiAobGluZU51bWJlciA8IDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFBvc2l0aW9uKDEsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGxpbmVOdW1iZXIgPiBsaW5lcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFBvc2l0aW9uKGxpbmVzLmxlbmd0aCwgbGluZXNbbGluZXMubGVuZ3RoIC0gMV0ubGVuZ3RoICsgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBsaW5lID0gbGluZXNbbGluZU51bWJlciAtIDFdO1xuICAgICAgICAgICAgaWYgKGNvbHVtbiA+IGxpbmUubGVuZ3RoICsgMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUG9zaXRpb24obGluZU51bWJlciwgbGluZS5sZW5ndGggKyAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9zaXRpb24obGluZU51bWJlciwgY29sdW1uKTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGlzVmFsaWRMaW5lTnVtYmVyKHRoaXMub3JpZ2luYWwuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSwgb3JpZ2luYWxMaW5lcylcbiAgICAgICAgICAgICYmIGlzVmFsaWRMaW5lTnVtYmVyKHRoaXMubW9kaWZpZWQuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSwgbW9kaWZpZWRMaW5lcykpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmFuZ2VNYXBwaW5nKG5ldyBSYW5nZSh0aGlzLm9yaWdpbmFsLnN0YXJ0TGluZU51bWJlciwgMSwgdGhpcy5vcmlnaW5hbC5lbmRMaW5lTnVtYmVyRXhjbHVzaXZlLCAxKSwgbmV3IFJhbmdlKHRoaXMubW9kaWZpZWQuc3RhcnRMaW5lTnVtYmVyLCAxLCB0aGlzLm1vZGlmaWVkLmVuZExpbmVOdW1iZXJFeGNsdXNpdmUsIDEpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMub3JpZ2luYWwuaXNFbXB0eSAmJiAhdGhpcy5tb2RpZmllZC5pc0VtcHR5KSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFJhbmdlTWFwcGluZyhSYW5nZS5mcm9tUG9zaXRpb25zKG5ldyBQb3NpdGlvbih0aGlzLm9yaWdpbmFsLnN0YXJ0TGluZU51bWJlciwgMSksIG5vcm1hbGl6ZVBvc2l0aW9uKHRoaXMub3JpZ2luYWwuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSAtIDEsIE51bWJlci5NQVhfU0FGRV9JTlRFR0VSLCBvcmlnaW5hbExpbmVzKSksIFJhbmdlLmZyb21Qb3NpdGlvbnMobmV3IFBvc2l0aW9uKHRoaXMubW9kaWZpZWQuc3RhcnRMaW5lTnVtYmVyLCAxKSwgbm9ybWFsaXplUG9zaXRpb24odGhpcy5tb2RpZmllZC5lbmRMaW5lTnVtYmVyRXhjbHVzaXZlIC0gMSwgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIsIG1vZGlmaWVkTGluZXMpKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMub3JpZ2luYWwuc3RhcnRMaW5lTnVtYmVyID4gMSAmJiB0aGlzLm1vZGlmaWVkLnN0YXJ0TGluZU51bWJlciA+IDEpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmFuZ2VNYXBwaW5nKFJhbmdlLmZyb21Qb3NpdGlvbnMobm9ybWFsaXplUG9zaXRpb24odGhpcy5vcmlnaW5hbC5zdGFydExpbmVOdW1iZXIgLSAxLCBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiwgb3JpZ2luYWxMaW5lcyksIG5vcm1hbGl6ZVBvc2l0aW9uKHRoaXMub3JpZ2luYWwuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSAtIDEsIE51bWJlci5NQVhfU0FGRV9JTlRFR0VSLCBvcmlnaW5hbExpbmVzKSksIFJhbmdlLmZyb21Qb3NpdGlvbnMobm9ybWFsaXplUG9zaXRpb24odGhpcy5tb2RpZmllZC5zdGFydExpbmVOdW1iZXIgLSAxLCBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiwgbW9kaWZpZWRMaW5lcyksIG5vcm1hbGl6ZVBvc2l0aW9uKHRoaXMubW9kaWZpZWQuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSAtIDEsIE51bWJlci5NQVhfU0FGRV9JTlRFR0VSLCBtb2RpZmllZExpbmVzKSkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNpdHVhdGlvbiBub3c6IG9uZSByYW5nZSBpcyBlbXB0eSBhbmQgb25lIHJhbmdlIHRvdWNoZXMgdGhlIGxhc3QgbGluZSBhbmQgb25lIHJhbmdlIHN0YXJ0cyBhdCBsaW5lIDEuXG4gICAgICAgIC8vIFRoaXMgc2hvdWxkbid0IGhhcHBlbiBmb3IgdmFsaWQgZGlmZnMuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBkaWZmOiBjYW5ub3QgY29udmVydCB0byByYW5nZSBtYXBwaW5nJyk7XG4gICAgfVxufVxuLyoqXG4gKiBBIGRldGFpbGVkIG1hcHBpbmcgYmV0d2VlbiB0d28gbGluZSByYW5nZXMsIGluY2x1ZGluZyBpbm5lciBjaGFuZ2VzLlxuICovXG5jbGFzcyBEZXRhaWxlZExpbmVSYW5nZU1hcHBpbmcgZXh0ZW5kcyBMaW5lUmFuZ2VNYXBwaW5nIHtcbiAgICBpbm5lckNoYW5nZXM7XG4gICAgY29uc3RydWN0b3Iob3JpZ2luYWwsIG1vZGlmaWVkLCBpbm5lckNoYW5nZXMpIHtcbiAgICAgICAgc3VwZXIob3JpZ2luYWwsIG1vZGlmaWVkKTtcbiAgICAgICAgdGhpcy5pbm5lckNoYW5nZXMgPSBpbm5lckNoYW5nZXM7XG4gICAgfVxufVxuLyoqXG4gKiBSZXN1bHQgb2YgYSBsaW5lcyBkaWZmIGNvbXB1dGF0aW9uLlxuICovXG5jbGFzcyBMaW5lc0RpZmYge1xuICAgIGNoYW5nZXM7XG4gICAgbW92ZXM7XG4gICAgaGl0VGltZW91dDtcbiAgICBjb25zdHJ1Y3RvcihjaGFuZ2VzLCBtb3ZlcywgaGl0VGltZW91dCkge1xuICAgICAgICB0aGlzLmNoYW5nZXMgPSBjaGFuZ2VzO1xuICAgICAgICB0aGlzLm1vdmVzID0gbW92ZXM7XG4gICAgICAgIHRoaXMuaGl0VGltZW91dCA9IGhpdFRpbWVvdXQ7XG4gICAgfVxufVxuLyoqXG4gKiBSZXByZXNlbnRzIHRleHQgdGhhdCB3YXMgbW92ZWQgZnJvbSBvbmUgbG9jYXRpb24gdG8gYW5vdGhlci5cbiAqL1xuY2xhc3MgTW92ZWRUZXh0IHtcbiAgICBsaW5lUmFuZ2VNYXBwaW5nO1xuICAgIGNoYW5nZXM7XG4gICAgY29uc3RydWN0b3IobGluZVJhbmdlTWFwcGluZywgY2hhbmdlcykge1xuICAgICAgICB0aGlzLmxpbmVSYW5nZU1hcHBpbmcgPSBsaW5lUmFuZ2VNYXBwaW5nO1xuICAgICAgICB0aGlzLmNoYW5nZXMgPSBjaGFuZ2VzO1xuICAgIH1cbn1cbi8qKlxuICogSGVscGVyIHRvIGNvbnZlcnQgZnJvbSByYW5nZSBtYXBwaW5ncyB0byBsaW5lIHJhbmdlIG1hcHBpbmdzLlxuICovXG5mdW5jdGlvbiBsaW5lUmFuZ2VNYXBwaW5nRnJvbVJhbmdlTWFwcGluZ3MoYWxpZ25tZW50cywgb3JpZ2luYWxMaW5lcywgbW9kaWZpZWRMaW5lcywgZG9udEFzc2VydFN0YXJ0TGluZSA9IGZhbHNlKSB7XG4gICAgY29uc3QgY2hhbmdlcyA9IFtdO1xuICAgIGZvciAoY29uc3QgZyBvZiBncm91cEFkamFjZW50QnkoYWxpZ25tZW50cy5tYXAoYSA9PiBnZXRMaW5lUmFuZ2VNYXBwaW5nKGEsIG9yaWdpbmFsTGluZXMsIG1vZGlmaWVkTGluZXMpKSwgKGExLCBhMikgPT4gYTEub3JpZ2luYWwuaW50ZXJzZWN0c09yVG91Y2hlcyhhMi5vcmlnaW5hbClcbiAgICAgICAgfHwgYTEubW9kaWZpZWQuaW50ZXJzZWN0c09yVG91Y2hlcyhhMi5tb2RpZmllZCkpKSB7XG4gICAgICAgIGNvbnN0IGZpcnN0ID0gZ1swXTtcbiAgICAgICAgY29uc3QgbGFzdCA9IGdbZy5sZW5ndGggLSAxXTtcbiAgICAgICAgY2hhbmdlcy5wdXNoKG5ldyBEZXRhaWxlZExpbmVSYW5nZU1hcHBpbmcoZmlyc3Qub3JpZ2luYWwuam9pbihsYXN0Lm9yaWdpbmFsKSwgZmlyc3QubW9kaWZpZWQuam9pbihsYXN0Lm1vZGlmaWVkKSwgZy5tYXAoYSA9PiBhLmlubmVyQ2hhbmdlc1swXSkpKTtcbiAgICB9XG4gICAgaWYgKCFkb250QXNzZXJ0U3RhcnRMaW5lKSB7XG4gICAgICAgIC8vIEFzc2VydCB0aGF0IHRoZSBjaGFuZ2VzIGFyZSBzb3J0ZWQgYW5kIG5vbi1vdmVybGFwcGluZyAoYnV0IGRvbid0IHRocm93IC0ganVzdCBsb2cgaW4gZGVidWcpXG4gICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgY2hhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgcHJldiA9IGNoYW5nZXNbaSAtIDFdO1xuICAgICAgICAgICAgY29uc3QgY3VyID0gY2hhbmdlc1tpXTtcbiAgICAgICAgICAgIGlmIChwcmV2Lm9yaWdpbmFsLmVuZExpbmVOdW1iZXJFeGNsdXNpdmUgPiBjdXIub3JpZ2luYWwuc3RhcnRMaW5lTnVtYmVyIHx8XG4gICAgICAgICAgICAgICAgcHJldi5tb2RpZmllZC5lbmRMaW5lTnVtYmVyRXhjbHVzaXZlID4gY3VyLm1vZGlmaWVkLnN0YXJ0TGluZU51bWJlcikge1xuICAgICAgICAgICAgICAgIC8vIFNpbGVudGx5IHNraXAgdmFsaWRhdGlvbiBpc3N1ZSAtIG1heSBiZSBleHBlY3RlZCBpbiBzb21lIGVkZ2UgY2FzZXNcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY2hhbmdlcztcbn1cbmZ1bmN0aW9uIGdldExpbmVSYW5nZU1hcHBpbmcocmFuZ2VNYXBwaW5nLCBvcmlnaW5hbExpbmVzLCBtb2RpZmllZExpbmVzKSB7XG4gICAgbGV0IGxpbmVTdGFydERlbHRhID0gMDtcbiAgICBsZXQgbGluZUVuZERlbHRhID0gMDtcbiAgICAvLyByYW5nZU1hcHBpbmcgZGVzY3JpYmVzIHRoZSBlZGl0IHRoYXQgcmVwbGFjZXMgYHJhbmdlTWFwcGluZy5vcmlnaW5hbFJhbmdlYCB3aXRoIGBuZXdUZXh0IDo9IGdldFRleHQobW9kaWZpZWRMaW5lcywgcmFuZ2VNYXBwaW5nLm1vZGlmaWVkUmFuZ2UpYC5cbiAgICAvLyBvcmlnaW5hbDogXXh4eCBcXG4gPC0gdGhpcyBsaW5lIGlzIG5vdCBtb2RpZmllZFxuICAgIC8vIG1vZGlmaWVkOiBdeHggIFxcblxuICAgIGlmIChyYW5nZU1hcHBpbmcubW9kaWZpZWRSYW5nZS5lbmRDb2x1bW4gPT09IDEgJiYgcmFuZ2VNYXBwaW5nLm9yaWdpbmFsUmFuZ2UuZW5kQ29sdW1uID09PSAxXG4gICAgICAgICYmIHJhbmdlTWFwcGluZy5vcmlnaW5hbFJhbmdlLnN0YXJ0TGluZU51bWJlciArIGxpbmVTdGFydERlbHRhIDw9IHJhbmdlTWFwcGluZy5vcmlnaW5hbFJhbmdlLmVuZExpbmVOdW1iZXJcbiAgICAgICAgJiYgcmFuZ2VNYXBwaW5nLm1vZGlmaWVkUmFuZ2Uuc3RhcnRMaW5lTnVtYmVyICsgbGluZVN0YXJ0RGVsdGEgPD0gcmFuZ2VNYXBwaW5nLm1vZGlmaWVkUmFuZ2UuZW5kTGluZU51bWJlcikge1xuICAgICAgICAvLyBXZSBjYW4gb25seSBkbyB0aGlzIGlmIHRoZSByYW5nZSBpcyBub3QgZW1wdHkgeWV0XG4gICAgICAgIGxpbmVFbmREZWx0YSA9IC0xO1xuICAgIH1cbiAgICAvLyBvcmlnaW5hbDogeHh4WyBcXG4gPC0gdGhpcyBsaW5lIGlzIG5vdCBtb2RpZmllZFxuICAgIC8vIG1vZGlmaWVkOiB4eHhbIFxcblxuICAgIGlmIChyYW5nZU1hcHBpbmcubW9kaWZpZWRSYW5nZS5zdGFydENvbHVtbiAtIDEgPj0gKG1vZGlmaWVkTGluZXNbcmFuZ2VNYXBwaW5nLm1vZGlmaWVkUmFuZ2Uuc3RhcnRMaW5lTnVtYmVyIC0gMV0/Lmxlbmd0aCA/PyAwKVxuICAgICAgICAmJiByYW5nZU1hcHBpbmcub3JpZ2luYWxSYW5nZS5zdGFydENvbHVtbiAtIDEgPj0gKG9yaWdpbmFsTGluZXNbcmFuZ2VNYXBwaW5nLm9yaWdpbmFsUmFuZ2Uuc3RhcnRMaW5lTnVtYmVyIC0gMV0/Lmxlbmd0aCA/PyAwKVxuICAgICAgICAmJiByYW5nZU1hcHBpbmcub3JpZ2luYWxSYW5nZS5zdGFydExpbmVOdW1iZXIgPD0gcmFuZ2VNYXBwaW5nLm9yaWdpbmFsUmFuZ2UuZW5kTGluZU51bWJlciArIGxpbmVFbmREZWx0YVxuICAgICAgICAmJiByYW5nZU1hcHBpbmcubW9kaWZpZWRSYW5nZS5zdGFydExpbmVOdW1iZXIgPD0gcmFuZ2VNYXBwaW5nLm1vZGlmaWVkUmFuZ2UuZW5kTGluZU51bWJlciArIGxpbmVFbmREZWx0YSkge1xuICAgICAgICAvLyBXZSBjYW4gb25seSBkbyB0aGlzIGlmIHRoZSByYW5nZSBpcyBub3QgZW1wdHkgeWV0XG4gICAgICAgIGxpbmVTdGFydERlbHRhID0gMTtcbiAgICB9XG4gICAgY29uc3Qgb3JpZ2luYWxMaW5lUmFuZ2UgPSBuZXcgTGluZVJhbmdlKHJhbmdlTWFwcGluZy5vcmlnaW5hbFJhbmdlLnN0YXJ0TGluZU51bWJlciArIGxpbmVTdGFydERlbHRhLCByYW5nZU1hcHBpbmcub3JpZ2luYWxSYW5nZS5lbmRMaW5lTnVtYmVyICsgMSArIGxpbmVFbmREZWx0YSk7XG4gICAgY29uc3QgbW9kaWZpZWRMaW5lUmFuZ2UgPSBuZXcgTGluZVJhbmdlKHJhbmdlTWFwcGluZy5tb2RpZmllZFJhbmdlLnN0YXJ0TGluZU51bWJlciArIGxpbmVTdGFydERlbHRhLCByYW5nZU1hcHBpbmcubW9kaWZpZWRSYW5nZS5lbmRMaW5lTnVtYmVyICsgMSArIGxpbmVFbmREZWx0YSk7XG4gICAgcmV0dXJuIG5ldyBEZXRhaWxlZExpbmVSYW5nZU1hcHBpbmcob3JpZ2luYWxMaW5lUmFuZ2UsIG1vZGlmaWVkTGluZVJhbmdlLCBbcmFuZ2VNYXBwaW5nXSk7XG59XG5mdW5jdGlvbiogZ3JvdXBBZGphY2VudEJ5KGl0ZW1zLCBzaG91bGRCZUdyb3VwZWQpIHtcbiAgICBsZXQgY3VycmVudEdyb3VwO1xuICAgIGxldCBsYXN0O1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykge1xuICAgICAgICBpZiAobGFzdCAhPT0gdW5kZWZpbmVkICYmIHNob3VsZEJlR3JvdXBlZChsYXN0LCBpdGVtKSkge1xuICAgICAgICAgICAgY3VycmVudEdyb3VwLnB1c2goaXRlbSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudEdyb3VwKSB7XG4gICAgICAgICAgICAgICAgeWllbGQgY3VycmVudEdyb3VwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEdyb3VwID0gW2l0ZW1dO1xuICAgICAgICB9XG4gICAgICAgIGxhc3QgPSBpdGVtO1xuICAgIH1cbiAgICBpZiAoY3VycmVudEdyb3VwKSB7XG4gICAgICAgIHlpZWxkIGN1cnJlbnRHcm91cDtcbiAgICB9XG59XG5jbGFzcyBBcnJheVRleHQge1xuICAgIGxpbmVzO1xuICAgIGNvbnN0cnVjdG9yKGxpbmVzKSB7XG4gICAgICAgIHRoaXMubGluZXMgPSBsaW5lcztcbiAgICB9XG4gICAgZ2V0IGxpbmVDb3VudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGluZXMubGVuZ3RoO1xuICAgIH1cbiAgICBnZXRMaW5lQ29udGVudChsaW5lTnVtYmVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxpbmVzW2xpbmVOdW1iZXIgLSAxXTtcbiAgICB9XG59XG5cbi8qKlxuICogVGhlIG1haW4gZGlmZiBjb21wdXRlciB0aGF0IGNvbXB1dGVzIGRldGFpbGVkIGxpbmUgZGlmZnMuXG4gKi9cbmNsYXNzIERlZmF1bHRMaW5lc0RpZmZDb21wdXRlciB7XG4gICAgX2R5bmFtaWNQcm9ncmFtbWluZ0RpZmZpbmcgPSBuZXcgRHluYW1pY1Byb2dyYW1taW5nRGlmZmluZygpO1xuICAgIF9teWVyc0RpZmZpbmdBbGdvcml0aG0gPSBuZXcgTXllcnNEaWZmQWxnb3JpdGhtKCk7XG4gICAgY29tcHV0ZURpZmYob3JpZ2luYWxMaW5lcywgbW9kaWZpZWRMaW5lcywgb3B0aW9ucykge1xuICAgICAgICAvLyBIYW5kbGUgaWRlbnRpY2FsIHNpbmdsZSBsaW5lXG4gICAgICAgIGlmIChvcmlnaW5hbExpbmVzLmxlbmd0aCA8PSAxICYmIGFycmF5c0VxdWFsKG9yaWdpbmFsTGluZXMsIG1vZGlmaWVkTGluZXMpKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IExpbmVzRGlmZihbXSwgW10sIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBIYW5kbGUgZW1wdHkgc2luZ2xlIGxpbmUgLSB0cmVhdCBhcyBmdWxsIHJlcGxhY2VtZW50XG4gICAgICAgIGlmIChvcmlnaW5hbExpbmVzLmxlbmd0aCA9PT0gMSAmJiBvcmlnaW5hbExpbmVzWzBdLmxlbmd0aCA9PT0gMCB8fCBtb2RpZmllZExpbmVzLmxlbmd0aCA9PT0gMSAmJiBtb2RpZmllZExpbmVzWzBdLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBMaW5lc0RpZmYoW1xuICAgICAgICAgICAgICAgIG5ldyBEZXRhaWxlZExpbmVSYW5nZU1hcHBpbmcobmV3IExpbmVSYW5nZSgxLCBvcmlnaW5hbExpbmVzLmxlbmd0aCArIDEpLCBuZXcgTGluZVJhbmdlKDEsIG1vZGlmaWVkTGluZXMubGVuZ3RoICsgMSksIFtcbiAgICAgICAgICAgICAgICAgICAgbmV3IFJhbmdlTWFwcGluZyhuZXcgUmFuZ2UoMSwgMSwgb3JpZ2luYWxMaW5lcy5sZW5ndGgsIG9yaWdpbmFsTGluZXNbb3JpZ2luYWxMaW5lcy5sZW5ndGggLSAxXS5sZW5ndGggKyAxKSwgbmV3IFJhbmdlKDEsIDEsIG1vZGlmaWVkTGluZXMubGVuZ3RoLCBtb2RpZmllZExpbmVzW21vZGlmaWVkTGluZXMubGVuZ3RoIC0gMV0ubGVuZ3RoICsgMSkpXG4gICAgICAgICAgICAgICAgXSlcbiAgICAgICAgICAgIF0sIFtdLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGltZW91dCA9IG9wdGlvbnMubWF4Q29tcHV0YXRpb25UaW1lTXMgPT09IDAgPyBJbmZpbml0ZVRpbWVvdXQuaW5zdGFuY2UgOiBuZXcgRGF0ZVRpbWVvdXQob3B0aW9ucy5tYXhDb21wdXRhdGlvblRpbWVNcyk7XG4gICAgICAgIGNvbnN0IGNvbnNpZGVyV2hpdGVzcGFjZUNoYW5nZXMgPSAhb3B0aW9ucy5pZ25vcmVUcmltV2hpdGVzcGFjZTtcbiAgICAgICAgLy8gQ3JlYXRlIHBlcmZlY3QgaGFzaCBmb3IgbGluZXMgKHRyaW1tZWQpXG4gICAgICAgIGNvbnN0IHBlcmZlY3RIYXNoZXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIGZ1bmN0aW9uIGdldE9yQ3JlYXRlSGFzaCh0ZXh0KSB7XG4gICAgICAgICAgICBsZXQgaGFzaCA9IHBlcmZlY3RIYXNoZXMuZ2V0KHRleHQpO1xuICAgICAgICAgICAgaWYgKGhhc2ggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGhhc2ggPSBwZXJmZWN0SGFzaGVzLnNpemU7XG4gICAgICAgICAgICAgICAgcGVyZmVjdEhhc2hlcy5zZXQodGV4dCwgaGFzaCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBvcmlnaW5hbExpbmVzSGFzaGVzID0gb3JpZ2luYWxMaW5lcy5tYXAoKGwpID0+IGdldE9yQ3JlYXRlSGFzaChsLnRyaW0oKSkpO1xuICAgICAgICBjb25zdCBtb2RpZmllZExpbmVzSGFzaGVzID0gbW9kaWZpZWRMaW5lcy5tYXAoKGwpID0+IGdldE9yQ3JlYXRlSGFzaChsLnRyaW0oKSkpO1xuICAgICAgICBjb25zdCBzZXF1ZW5jZTEgPSBuZXcgTGluZVNlcXVlbmNlKG9yaWdpbmFsTGluZXNIYXNoZXMsIG9yaWdpbmFsTGluZXMpO1xuICAgICAgICBjb25zdCBzZXF1ZW5jZTIgPSBuZXcgTGluZVNlcXVlbmNlKG1vZGlmaWVkTGluZXNIYXNoZXMsIG1vZGlmaWVkTGluZXMpO1xuICAgICAgICAvLyBDaG9vc2UgYWxnb3JpdGhtIGJhc2VkIG9uIHNpemVcbiAgICAgICAgY29uc3QgbGluZUFsaWdubWVudFJlc3VsdCA9ICgoKSA9PiB7XG4gICAgICAgICAgICBpZiAoc2VxdWVuY2UxLmxlbmd0aCArIHNlcXVlbmNlMi5sZW5ndGggPCAxNzAwKSB7XG4gICAgICAgICAgICAgICAgLy8gVXNlIHRoZSBpbXByb3ZlZCBhbGdvcml0aG0gZm9yIHNtYWxsIGZpbGVzXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2R5bmFtaWNQcm9ncmFtbWluZ0RpZmZpbmcuY29tcHV0ZShzZXF1ZW5jZTEsIHNlcXVlbmNlMiwgdGltZW91dCwgKG9mZnNldDEsIG9mZnNldDIpID0+IG9yaWdpbmFsTGluZXNbb2Zmc2V0MV0gPT09IG1vZGlmaWVkTGluZXNbb2Zmc2V0Ml1cbiAgICAgICAgICAgICAgICAgICAgPyBtb2RpZmllZExpbmVzW29mZnNldDJdLmxlbmd0aCA9PT0gMFxuICAgICAgICAgICAgICAgICAgICAgICAgPyAwLjFcbiAgICAgICAgICAgICAgICAgICAgICAgIDogMSArIE1hdGgubG9nKDEgKyBtb2RpZmllZExpbmVzW29mZnNldDJdLmxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgOiAwLjk5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9teWVyc0RpZmZpbmdBbGdvcml0aG0uY29tcHV0ZShzZXF1ZW5jZTEsIHNlcXVlbmNlMiwgdGltZW91dCk7XG4gICAgICAgIH0pKCk7XG4gICAgICAgIGxldCBsaW5lQWxpZ25tZW50cyA9IGxpbmVBbGlnbm1lbnRSZXN1bHQuZGlmZnM7XG4gICAgICAgIGxldCBoaXRUaW1lb3V0ID0gbGluZUFsaWdubWVudFJlc3VsdC5oaXRUaW1lb3V0O1xuICAgICAgICAvLyBBcHBseSBoZXVyaXN0aWNzXG4gICAgICAgIGxpbmVBbGlnbm1lbnRzID0gb3B0aW1pemVTZXF1ZW5jZURpZmZzKHNlcXVlbmNlMSwgc2VxdWVuY2UyLCBsaW5lQWxpZ25tZW50cyk7XG4gICAgICAgIGxpbmVBbGlnbm1lbnRzID0gcmVtb3ZlVmVyeVNob3J0TWF0Y2hpbmdMaW5lc0JldHdlZW5EaWZmcyhzZXF1ZW5jZTEsIHNlcXVlbmNlMiwgbGluZUFsaWdubWVudHMpO1xuICAgICAgICBjb25zdCBhbGlnbm1lbnRzID0gW107XG4gICAgICAgIGNvbnN0IHNjYW5Gb3JXaGl0ZXNwYWNlQ2hhbmdlcyA9IChlcXVhbExpbmVzQ291bnQpID0+IHtcbiAgICAgICAgICAgIGlmICghY29uc2lkZXJXaGl0ZXNwYWNlQ2hhbmdlcykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXF1YWxMaW5lc0NvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzZXExT2Zmc2V0ID0gc2VxMUxhc3RTdGFydCArIGk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2VxMk9mZnNldCA9IHNlcTJMYXN0U3RhcnQgKyBpO1xuICAgICAgICAgICAgICAgIGlmIChvcmlnaW5hbExpbmVzW3NlcTFPZmZzZXRdICE9PSBtb2RpZmllZExpbmVzW3NlcTJPZmZzZXRdKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYmVjYXVzZSBvZiB3aGl0ZXNwYWNlIGNoYW5nZXMsIGRpZmYgdGhlc2UgbGluZXNcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hhcmFjdGVyRGlmZnMgPSB0aGlzLl9yZWZpbmVEaWZmKG9yaWdpbmFsTGluZXMsIG1vZGlmaWVkTGluZXMsIG5ldyBTZXF1ZW5jZURpZmYobmV3IE9mZnNldFJhbmdlKHNlcTFPZmZzZXQsIHNlcTFPZmZzZXQgKyAxKSwgbmV3IE9mZnNldFJhbmdlKHNlcTJPZmZzZXQsIHNlcTJPZmZzZXQgKyAxKSksIHRpbWVvdXQsIGNvbnNpZGVyV2hpdGVzcGFjZUNoYW5nZXMsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGEgb2YgY2hhcmFjdGVyRGlmZnMubWFwcGluZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsaWdubWVudHMucHVzaChhKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hhcmFjdGVyRGlmZnMuaGl0VGltZW91dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGl0VGltZW91dCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGxldCBzZXExTGFzdFN0YXJ0ID0gMDtcbiAgICAgICAgbGV0IHNlcTJMYXN0U3RhcnQgPSAwO1xuICAgICAgICBmb3IgKGNvbnN0IGRpZmYgb2YgbGluZUFsaWdubWVudHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGVxdWFsTGluZXNDb3VudCA9IGRpZmYuc2VxMVJhbmdlLnN0YXJ0IC0gc2VxMUxhc3RTdGFydDtcbiAgICAgICAgICAgIHNjYW5Gb3JXaGl0ZXNwYWNlQ2hhbmdlcyhlcXVhbExpbmVzQ291bnQpO1xuICAgICAgICAgICAgc2VxMUxhc3RTdGFydCA9IGRpZmYuc2VxMVJhbmdlLmVuZEV4Y2x1c2l2ZTtcbiAgICAgICAgICAgIHNlcTJMYXN0U3RhcnQgPSBkaWZmLnNlcTJSYW5nZS5lbmRFeGNsdXNpdmU7XG4gICAgICAgICAgICBjb25zdCBjaGFyYWN0ZXJEaWZmcyA9IHRoaXMuX3JlZmluZURpZmYob3JpZ2luYWxMaW5lcywgbW9kaWZpZWRMaW5lcywgZGlmZiwgdGltZW91dCwgY29uc2lkZXJXaGl0ZXNwYWNlQ2hhbmdlcywgb3B0aW9ucyk7XG4gICAgICAgICAgICBpZiAoY2hhcmFjdGVyRGlmZnMuaGl0VGltZW91dCkge1xuICAgICAgICAgICAgICAgIGhpdFRpbWVvdXQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChjb25zdCBhIG9mIGNoYXJhY3RlckRpZmZzLm1hcHBpbmdzKSB7XG4gICAgICAgICAgICAgICAgYWxpZ25tZW50cy5wdXNoKGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHNjYW5Gb3JXaGl0ZXNwYWNlQ2hhbmdlcyhvcmlnaW5hbExpbmVzLmxlbmd0aCAtIHNlcTFMYXN0U3RhcnQpO1xuICAgICAgICBjb25zdCBvcmlnaW5hbCA9IG5ldyBBcnJheVRleHQob3JpZ2luYWxMaW5lcyk7XG4gICAgICAgIGNvbnN0IG1vZGlmaWVkID0gbmV3IEFycmF5VGV4dChtb2RpZmllZExpbmVzKTtcbiAgICAgICAgY29uc3QgY2hhbmdlcyA9IGxpbmVSYW5nZU1hcHBpbmdGcm9tUmFuZ2VNYXBwaW5ncyhhbGlnbm1lbnRzLCBvcmlnaW5hbC5saW5lcywgbW9kaWZpZWQubGluZXMpO1xuICAgICAgICAvLyBUT0RPOiBDb21wdXRlIG1vdmVzIGlmIG9wdGlvbnMuY29tcHV0ZU1vdmVzIGlzIHRydWVcbiAgICAgICAgY29uc3QgbW92ZXMgPSBbXTtcbiAgICAgICAgcmV0dXJuIG5ldyBMaW5lc0RpZmYoY2hhbmdlcywgbW92ZXMsIGhpdFRpbWVvdXQpO1xuICAgIH1cbiAgICBfcmVmaW5lRGlmZihvcmlnaW5hbExpbmVzLCBtb2RpZmllZExpbmVzLCBkaWZmLCB0aW1lb3V0LCBjb25zaWRlcldoaXRlc3BhY2VDaGFuZ2VzLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGxpbmVSYW5nZU1hcHBpbmcgPSB0b0xpbmVSYW5nZU1hcHBpbmcoZGlmZik7XG4gICAgICAgIGNvbnN0IHJhbmdlTWFwcGluZyA9IGxpbmVSYW5nZU1hcHBpbmcudG9SYW5nZU1hcHBpbmcyKG9yaWdpbmFsTGluZXMsIG1vZGlmaWVkTGluZXMpO1xuICAgICAgICBjb25zdCBzbGljZTEgPSBuZXcgTGluZXNTbGljZUNoYXJTZXF1ZW5jZShvcmlnaW5hbExpbmVzLCByYW5nZU1hcHBpbmcub3JpZ2luYWxSYW5nZSwgY29uc2lkZXJXaGl0ZXNwYWNlQ2hhbmdlcyk7XG4gICAgICAgIGNvbnN0IHNsaWNlMiA9IG5ldyBMaW5lc1NsaWNlQ2hhclNlcXVlbmNlKG1vZGlmaWVkTGluZXMsIHJhbmdlTWFwcGluZy5tb2RpZmllZFJhbmdlLCBjb25zaWRlcldoaXRlc3BhY2VDaGFuZ2VzKTtcbiAgICAgICAgY29uc3QgZGlmZlJlc3VsdCA9IHNsaWNlMS5sZW5ndGggKyBzbGljZTIubGVuZ3RoIDwgNTAwXG4gICAgICAgICAgICA/IHRoaXMuX2R5bmFtaWNQcm9ncmFtbWluZ0RpZmZpbmcuY29tcHV0ZShzbGljZTEsIHNsaWNlMiwgdGltZW91dClcbiAgICAgICAgICAgIDogdGhpcy5fbXllcnNEaWZmaW5nQWxnb3JpdGhtLmNvbXB1dGUoc2xpY2UxLCBzbGljZTIsIHRpbWVvdXQpO1xuICAgICAgICBsZXQgZGlmZnMgPSBkaWZmUmVzdWx0LmRpZmZzO1xuICAgICAgICBkaWZmcyA9IG9wdGltaXplU2VxdWVuY2VEaWZmcyhzbGljZTEsIHNsaWNlMiwgZGlmZnMpO1xuICAgICAgICBkaWZmcyA9IGV4dGVuZERpZmZzVG9FbnRpcmVXb3JkSWZBcHByb3ByaWF0ZShzbGljZTEsIHNsaWNlMiwgZGlmZnMsIChzZXEsIGlkeCkgPT4gc2VxLmZpbmRXb3JkQ29udGFpbmluZyhpZHgpKTtcbiAgICAgICAgaWYgKG9wdGlvbnMuZXh0ZW5kVG9TdWJ3b3Jkcykge1xuICAgICAgICAgICAgZGlmZnMgPSBleHRlbmREaWZmc1RvRW50aXJlV29yZElmQXBwcm9wcmlhdGUoc2xpY2UxLCBzbGljZTIsIGRpZmZzLCAoc2VxLCBpZHgpID0+IHNlcS5maW5kU3ViV29yZENvbnRhaW5pbmcoaWR4KSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZGlmZnMgPSByZW1vdmVTaG9ydE1hdGNoZXMoc2xpY2UxLCBzbGljZTIsIGRpZmZzKTtcbiAgICAgICAgZGlmZnMgPSByZW1vdmVWZXJ5U2hvcnRNYXRjaGluZ1RleHRCZXR3ZWVuTG9uZ0RpZmZzKHNsaWNlMSwgc2xpY2UyLCBkaWZmcyk7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGRpZmZzLm1hcCgoZCkgPT4gbmV3IFJhbmdlTWFwcGluZyhzbGljZTEudHJhbnNsYXRlUmFuZ2UoZC5zZXExUmFuZ2UpLCBzbGljZTIudHJhbnNsYXRlUmFuZ2UoZC5zZXEyUmFuZ2UpKSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBtYXBwaW5nczogcmVzdWx0LFxuICAgICAgICAgICAgaGl0VGltZW91dDogZGlmZlJlc3VsdC5oaXRUaW1lb3V0LFxuICAgICAgICB9O1xuICAgIH1cbn1cbmZ1bmN0aW9uIHRvTGluZVJhbmdlTWFwcGluZyhzZXF1ZW5jZURpZmYpIHtcbiAgICByZXR1cm4gbmV3IExpbmVSYW5nZU1hcHBpbmcobmV3IExpbmVSYW5nZShzZXF1ZW5jZURpZmYuc2VxMVJhbmdlLnN0YXJ0ICsgMSwgc2VxdWVuY2VEaWZmLnNlcTFSYW5nZS5lbmRFeGNsdXNpdmUgKyAxKSwgbmV3IExpbmVSYW5nZShzZXF1ZW5jZURpZmYuc2VxMlJhbmdlLnN0YXJ0ICsgMSwgc2VxdWVuY2VEaWZmLnNlcTJSYW5nZS5lbmRFeGNsdXNpdmUgKyAxKSk7XG59XG5mdW5jdGlvbiBhcnJheXNFcXVhbChhLCBiKSB7XG4gICAgaWYgKGEubGVuZ3RoICE9PSBiLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoYVtpXSAhPT0gYltpXSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG4vKiBAdHMtc2VsZi10eXBlcz1cIi4vZGlmZl93YXNtLmQudHNcIiAqL1xuXG4vKipcbiAqIENvbXB1dGUgYSBkaWZmIGJldHdlZW4gdHdvIHRleHRzLlxuICpcbiAqICMgQXJndW1lbnRzXG4gKiAqIGBvcmlnaW5hbGAgLSBUaGUgb3JpZ2luYWwgdGV4dCAobGluZXMgc2VwYXJhdGVkIGJ5IG5ld2xpbmVzKVxuICogKiBgbW9kaWZpZWRgIC0gVGhlIG1vZGlmaWVkIHRleHQgKGxpbmVzIHNlcGFyYXRlZCBieSBuZXdsaW5lcylcbiAqICogYG9wdGlvbnNgIC0gT3B0aW9uYWwgZGlmZiBvcHRpb25zIChhcyBhIEphdmFTY3JpcHQgb2JqZWN0KVxuICpcbiAqICMgUmV0dXJuc1xuICogQSBgV2FzbUxpbmVzRGlmZmAgb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNoYW5nZXMuXG4gKiBAcGFyYW0ge3N0cmluZ30gb3JpZ2luYWxcbiAqIEBwYXJhbSB7c3RyaW5nfSBtb2RpZmllZFxuICogQHBhcmFtIHthbnl9IG9wdGlvbnNcbiAqIEByZXR1cm5zIHthbnl9XG4gKi9cbmZ1bmN0aW9uIGNvbXB1dGVEaWZmKG9yaWdpbmFsLCBtb2RpZmllZCwgb3B0aW9ucykge1xuICAgIGNvbnN0IHB0cjAgPSBwYXNzU3RyaW5nVG9XYXNtMChvcmlnaW5hbCwgd2FzbS5fX3diaW5kZ2VuX21hbGxvYywgd2FzbS5fX3diaW5kZ2VuX3JlYWxsb2MpO1xuICAgIGNvbnN0IGxlbjAgPSBXQVNNX1ZFQ1RPUl9MRU47XG4gICAgY29uc3QgcHRyMSA9IHBhc3NTdHJpbmdUb1dhc20wKG1vZGlmaWVkLCB3YXNtLl9fd2JpbmRnZW5fbWFsbG9jLCB3YXNtLl9fd2JpbmRnZW5fcmVhbGxvYyk7XG4gICAgY29uc3QgbGVuMSA9IFdBU01fVkVDVE9SX0xFTjtcbiAgICBjb25zdCByZXQgPSB3YXNtLmNvbXB1dGVEaWZmKHB0cjAsIGxlbjAsIHB0cjEsIGxlbjEsIG9wdGlvbnMpO1xuICAgIGlmIChyZXRbMl0pIHtcbiAgICAgICAgdGhyb3cgdGFrZUZyb21FeHRlcm5yZWZUYWJsZTAocmV0WzFdKTtcbiAgICB9XG4gICAgcmV0dXJuIHRha2VGcm9tRXh0ZXJucmVmVGFibGUwKHJldFswXSk7XG59XG5cbi8qKlxuICogQ29tcHV0ZSBhIGRpZmYgYmV0d2VlbiB0d28gYXJyYXlzIG9mIGxpbmVzLlxuICpcbiAqICMgQXJndW1lbnRzXG4gKiAqIGBvcmlnaW5hbF9saW5lc2AgLSBUaGUgb3JpZ2luYWwgbGluZXMgKGFzIGEgSmF2YVNjcmlwdCBhcnJheSBvZiBzdHJpbmdzKVxuICogKiBgbW9kaWZpZWRfbGluZXNgIC0gVGhlIG1vZGlmaWVkIGxpbmVzIChhcyBhIEphdmFTY3JpcHQgYXJyYXkgb2Ygc3RyaW5ncylcbiAqICogYG9wdGlvbnNgIC0gT3B0aW9uYWwgZGlmZiBvcHRpb25zIChhcyBhIEphdmFTY3JpcHQgb2JqZWN0KVxuICpcbiAqICMgUmV0dXJuc1xuICogQSBgV2FzbUxpbmVzRGlmZmAgb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNoYW5nZXMuXG4gKiBAcGFyYW0ge2FueX0gb3JpZ2luYWxfbGluZXNcbiAqIEBwYXJhbSB7YW55fSBtb2RpZmllZF9saW5lc1xuICogQHBhcmFtIHthbnl9IG9wdGlvbnNcbiAqIEByZXR1cm5zIHthbnl9XG4gKi9cbmZ1bmN0aW9uIGNvbXB1dGVEaWZmTGluZXMob3JpZ2luYWxfbGluZXMsIG1vZGlmaWVkX2xpbmVzLCBvcHRpb25zKSB7XG4gICAgY29uc3QgcmV0ID0gd2FzbS5jb21wdXRlRGlmZkxpbmVzKG9yaWdpbmFsX2xpbmVzLCBtb2RpZmllZF9saW5lcywgb3B0aW9ucyk7XG4gICAgaWYgKHJldFsyXSkge1xuICAgICAgICB0aHJvdyB0YWtlRnJvbUV4dGVybnJlZlRhYmxlMChyZXRbMV0pO1xuICAgIH1cbiAgICByZXR1cm4gdGFrZUZyb21FeHRlcm5yZWZUYWJsZTAocmV0WzBdKTtcbn1cblxuLyoqXG4gKiBJbml0aWFsaXplIHBhbmljIGhvb2sgZm9yIGJldHRlciBlcnJvciBtZXNzYWdlcyBpbiB0aGUgYnJvd3NlciBjb25zb2xlLlxuICovXG5mdW5jdGlvbiBpbml0KCkge1xuICAgIHdhc20uaW5pdCgpO1xufVxuZnVuY3Rpb24gX193YmdfZ2V0X2ltcG9ydHMoKSB7XG4gICAgY29uc3QgaW1wb3J0MCA9IHtcbiAgICAgICAgX19wcm90b19fOiBudWxsLFxuICAgICAgICBfX3diZ19FcnJvcl9lZjUzYmMzMTBlYjI5OGEwOiBmdW5jdGlvbihhcmcwLCBhcmcxKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBFcnJvcihnZXRTdHJpbmdGcm9tV2FzbTAoYXJnMCwgYXJnMSkpO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfTnVtYmVyXzZiNTA2ZTY1MzY4MzFlYWE6IGZ1bmN0aW9uKGFyZzApIHtcbiAgICAgICAgICAgIGNvbnN0IHJldCA9IE51bWJlcihhcmcwKTtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX1N0cmluZ184NTY0ZTU1OTc5OWVjY2RhOiBmdW5jdGlvbihhcmcwLCBhcmcxKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBTdHJpbmcoYXJnMSk7XG4gICAgICAgICAgICBjb25zdCBwdHIxID0gcGFzc1N0cmluZ1RvV2FzbTAocmV0LCB3YXNtLl9fd2JpbmRnZW5fbWFsbG9jLCB3YXNtLl9fd2JpbmRnZW5fcmVhbGxvYyk7XG4gICAgICAgICAgICBjb25zdCBsZW4xID0gV0FTTV9WRUNUT1JfTEVOO1xuICAgICAgICAgICAgZ2V0RGF0YVZpZXdNZW1vcnkwKCkuc2V0SW50MzIoYXJnMCArIDQgKiAxLCBsZW4xLCB0cnVlKTtcbiAgICAgICAgICAgIGdldERhdGFWaWV3TWVtb3J5MCgpLnNldEludDMyKGFyZzAgKyA0ICogMCwgcHRyMSwgdHJ1ZSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX19fd2JpbmRnZW5fYmlnaW50X2dldF9hc19pNjRfMzgxMzBlOThlZWNkNDY3ZDogZnVuY3Rpb24oYXJnMCwgYXJnMSkge1xuICAgICAgICAgICAgY29uc3QgdiA9IGFyZzE7XG4gICAgICAgICAgICBjb25zdCByZXQgPSB0eXBlb2YodikgPT09ICdiaWdpbnQnID8gdiA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGdldERhdGFWaWV3TWVtb3J5MCgpLnNldEJpZ0ludDY0KGFyZzAgKyA4ICogMSwgaXNMaWtlTm9uZShyZXQpID8gQmlnSW50KDApIDogcmV0LCB0cnVlKTtcbiAgICAgICAgICAgIGdldERhdGFWaWV3TWVtb3J5MCgpLnNldEludDMyKGFyZzAgKyA0ICogMCwgIWlzTGlrZU5vbmUocmV0KSwgdHJ1ZSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX19fd2JpbmRnZW5fYm9vbGVhbl9nZXRfMWE0NWUyYzM4ZDRkNDFiOTogZnVuY3Rpb24oYXJnMCkge1xuICAgICAgICAgICAgY29uc3QgdiA9IGFyZzA7XG4gICAgICAgICAgICBjb25zdCByZXQgPSB0eXBlb2YodikgPT09ICdib29sZWFuJyA/IHYgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICByZXR1cm4gaXNMaWtlTm9uZShyZXQpID8gMHhGRkZGRkYgOiByZXQgPyAxIDogMDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfX193YmluZGdlbl9kZWJ1Z19zdHJpbmdfMGFjY2Q4MGY0NWU1ZmFhMjogZnVuY3Rpb24oYXJnMCwgYXJnMSkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gZGVidWdTdHJpbmcoYXJnMSk7XG4gICAgICAgICAgICBjb25zdCBwdHIxID0gcGFzc1N0cmluZ1RvV2FzbTAocmV0LCB3YXNtLl9fd2JpbmRnZW5fbWFsbG9jLCB3YXNtLl9fd2JpbmRnZW5fcmVhbGxvYyk7XG4gICAgICAgICAgICBjb25zdCBsZW4xID0gV0FTTV9WRUNUT1JfTEVOO1xuICAgICAgICAgICAgZ2V0RGF0YVZpZXdNZW1vcnkwKCkuc2V0SW50MzIoYXJnMCArIDQgKiAxLCBsZW4xLCB0cnVlKTtcbiAgICAgICAgICAgIGdldERhdGFWaWV3TWVtb3J5MCgpLnNldEludDMyKGFyZzAgKyA0ICogMCwgcHRyMSwgdHJ1ZSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX19fd2JpbmRnZW5faW5fNzBhNDAzYTU2ZTc3MTcwNDogZnVuY3Rpb24oYXJnMCwgYXJnMSkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gYXJnMCBpbiBhcmcxO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfX193YmluZGdlbl9pc19iaWdpbnRfNmZmZDY0NjhhOWJjNDRiOTogZnVuY3Rpb24oYXJnMCkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gdHlwZW9mKGFyZzApID09PSAnYmlnaW50JztcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX19fd2JpbmRnZW5faXNfZnVuY3Rpb25fNzU0ZTlmMzA1ZmY2MDI5ZTogZnVuY3Rpb24oYXJnMCkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gdHlwZW9mKGFyZzApID09PSAnZnVuY3Rpb24nO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfX193YmluZGdlbl9pc19udWxsXzg3YzNiZmU5NjhjNmE1YWQ6IGZ1bmN0aW9uKGFyZzApIHtcbiAgICAgICAgICAgIGNvbnN0IHJldCA9IGFyZzAgPT09IG51bGw7XG4gICAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICB9LFxuICAgICAgICBfX3diZ19fX3diaW5kZ2VuX2lzX29iamVjdF81NjczMmMyYmMzNTNmNDFkOiBmdW5jdGlvbihhcmcwKSB7XG4gICAgICAgICAgICBjb25zdCB2YWwgPSBhcmcwO1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gdHlwZW9mKHZhbCkgPT09ICdvYmplY3QnICYmIHZhbCAhPT0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX19fd2JpbmRnZW5faXNfdW5kZWZpbmVkXzY3YjQ1NmJlODY3M2QzZDc6IGZ1bmN0aW9uKGFyZzApIHtcbiAgICAgICAgICAgIGNvbnN0IHJldCA9IGFyZzAgPT09IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX19fd2JpbmRnZW5fanN2YWxfZXFfMTA2OGU2MjRmYTg3ZjZhYjogZnVuY3Rpb24oYXJnMCwgYXJnMSkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gYXJnMCA9PT0gYXJnMTtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX19fd2JpbmRnZW5fanN2YWxfbG9vc2VfZXFfMmM1NjU2NGM3NTEyOTUxMTogZnVuY3Rpb24oYXJnMCwgYXJnMSkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gYXJnMCA9PSBhcmcxO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfX193YmluZGdlbl9udW1iZXJfZ2V0XzliYjE3NjExMjIxODFhZjI6IGZ1bmN0aW9uKGFyZzAsIGFyZzEpIHtcbiAgICAgICAgICAgIGNvbnN0IG9iaiA9IGFyZzE7XG4gICAgICAgICAgICBjb25zdCByZXQgPSB0eXBlb2Yob2JqKSA9PT0gJ251bWJlcicgPyBvYmogOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICBnZXREYXRhVmlld01lbW9yeTAoKS5zZXRGbG9hdDY0KGFyZzAgKyA4ICogMSwgaXNMaWtlTm9uZShyZXQpID8gMCA6IHJldCwgdHJ1ZSk7XG4gICAgICAgICAgICBnZXREYXRhVmlld01lbW9yeTAoKS5zZXRJbnQzMihhcmcwICsgNCAqIDAsICFpc0xpa2VOb25lKHJldCksIHRydWUpO1xuICAgICAgICB9LFxuICAgICAgICBfX3diZ19fX3diaW5kZ2VuX3N0cmluZ19nZXRfNzJiZGY5NWQzYWU1MDViMTogZnVuY3Rpb24oYXJnMCwgYXJnMSkge1xuICAgICAgICAgICAgY29uc3Qgb2JqID0gYXJnMTtcbiAgICAgICAgICAgIGNvbnN0IHJldCA9IHR5cGVvZihvYmopID09PSAnc3RyaW5nJyA/IG9iaiA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHZhciBwdHIxID0gaXNMaWtlTm9uZShyZXQpID8gMCA6IHBhc3NTdHJpbmdUb1dhc20wKHJldCwgd2FzbS5fX3diaW5kZ2VuX21hbGxvYywgd2FzbS5fX3diaW5kZ2VuX3JlYWxsb2MpO1xuICAgICAgICAgICAgdmFyIGxlbjEgPSBXQVNNX1ZFQ1RPUl9MRU47XG4gICAgICAgICAgICBnZXREYXRhVmlld01lbW9yeTAoKS5zZXRJbnQzMihhcmcwICsgNCAqIDEsIGxlbjEsIHRydWUpO1xuICAgICAgICAgICAgZ2V0RGF0YVZpZXdNZW1vcnkwKCkuc2V0SW50MzIoYXJnMCArIDQgKiAwLCBwdHIxLCB0cnVlKTtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfX193YmluZGdlbl90aHJvd18xNTA2ZjIyMzVkMWJkYmEwOiBmdW5jdGlvbihhcmcwLCBhcmcxKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZ2V0U3RyaW5nRnJvbVdhc20wKGFyZzAsIGFyZzEpKTtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfY2FsbF84YTg5NjA5ZDg5ZjY2MDhhOiBmdW5jdGlvbigpIHsgcmV0dXJuIGhhbmRsZUVycm9yKGZ1bmN0aW9uIChhcmcwLCBhcmcxKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBhcmcwLmNhbGwoYXJnMSk7XG4gICAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICB9LCBhcmd1bWVudHMpOyB9LFxuICAgICAgICBfX3diZ19kb25lXzYwY2YzMDdmY2M2ODA1MzY6IGZ1bmN0aW9uKGFyZzApIHtcbiAgICAgICAgICAgIGNvbnN0IHJldCA9IGFyZzAuZG9uZTtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX2Vycm9yX2E2ZmEyMDJiNThhYTFjZDM6IGZ1bmN0aW9uKGFyZzAsIGFyZzEpIHtcbiAgICAgICAgICAgIGxldCBkZWZlcnJlZDBfMDtcbiAgICAgICAgICAgIGxldCBkZWZlcnJlZDBfMTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgZGVmZXJyZWQwXzAgPSBhcmcwO1xuICAgICAgICAgICAgICAgIGRlZmVycmVkMF8xID0gYXJnMTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGdldFN0cmluZ0Zyb21XYXNtMChhcmcwLCBhcmcxKSk7XG4gICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIHdhc20uX193YmluZGdlbl9mcmVlKGRlZmVycmVkMF8wLCBkZWZlcnJlZDBfMSwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX2dldF8xZjhmMDU0ZGRiYWE3ZGIyOiBmdW5jdGlvbigpIHsgcmV0dXJuIGhhbmRsZUVycm9yKGZ1bmN0aW9uIChhcmcwLCBhcmcxKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBSZWZsZWN0LmdldChhcmcwLCBhcmcxKTtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sIGFyZ3VtZW50cyk7IH0sXG4gICAgICAgIF9fd2JnX2dldF91bmNoZWNrZWRfMzNmNmU1YzllMmYyZDZiMjogZnVuY3Rpb24oYXJnMCwgYXJnMSkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gYXJnMFthcmcxID4+PiAwXTtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX2dldF93aXRoX3JlZl9rZXlfNjQxMmNmMzA5NDU5OTY5NDogZnVuY3Rpb24oYXJnMCwgYXJnMSkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gYXJnMFthcmcxXTtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX2luc3RhbmNlb2ZfQXJyYXlCdWZmZXJfOGY0OTgxMTQ2Nzc0MTQ5OTogZnVuY3Rpb24oYXJnMCkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gYXJnMCBpbnN0YW5jZW9mIEFycmF5QnVmZmVyO1xuICAgICAgICAgICAgfSBjYXRjaCAoXykge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmV0ID0gcmVzdWx0O1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfaW5zdGFuY2VvZl9VaW50OEFycmF5Xzg2ZjMwNjQ5ZjYzZWY5YzI6IGZ1bmN0aW9uKGFyZzApIHtcbiAgICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGFyZzAgaW5zdGFuY2VvZiBVaW50OEFycmF5O1xuICAgICAgICAgICAgfSBjYXRjaCAoXykge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmV0ID0gcmVzdWx0O1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfaXNBcnJheV82N2MyYzljNDMxM2Y0NDQ4OiBmdW5jdGlvbihhcmcwKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBBcnJheS5pc0FycmF5KGFyZzApO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfaXNTYWZlSW50ZWdlcl82NmFjZWMyN2UwOWU5OWE3OiBmdW5jdGlvbihhcmcwKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBOdW1iZXIuaXNTYWZlSW50ZWdlcihhcmcwKTtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX2l0ZXJhdG9yXzg3MzI0MjhkMzA5ZTI3MGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gU3ltYm9sLml0ZXJhdG9yO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfbGVuZ3RoXzRhNTkxZWNhYTAxMzU0ZDk6IGZ1bmN0aW9uKGFyZzApIHtcbiAgICAgICAgICAgIGNvbnN0IHJldCA9IGFyZzAubGVuZ3RoO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfbGVuZ3RoXzY2ZjFhNGIyZTkwMjY5NDA6IGZ1bmN0aW9uKGFyZzApIHtcbiAgICAgICAgICAgIGNvbnN0IHJldCA9IGFyZzAubGVuZ3RoO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfbmV3XzIyN2Q3YzA1NDE0ZWI4NjE6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gbmV3IEVycm9yKCk7XG4gICAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICB9LFxuICAgICAgICBfX3diZ19uZXdfNTc4YWVlZjRiNmI5NDM3ODogZnVuY3Rpb24oYXJnMCkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gbmV3IFVpbnQ4QXJyYXkoYXJnMCk7XG4gICAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICB9LFxuICAgICAgICBfX3diZ19uZXdfY2UxYWI2MWMxYzJiMzAwZDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBuZXcgT2JqZWN0KCk7XG4gICAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICB9LFxuICAgICAgICBfX3diZ19uZXdfZDkwMDkxYjgyZmRmNWI5MTogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX25leHRfOWUwM2FjZGY1MWM0OTYwZDogZnVuY3Rpb24oYXJnMCkge1xuICAgICAgICAgICAgY29uc3QgcmV0ID0gYXJnMC5uZXh0O1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmdfbmV4dF9lYjhjYTczNTFmYTI3OTA2OiBmdW5jdGlvbigpIHsgcmV0dXJuIGhhbmRsZUVycm9yKGZ1bmN0aW9uIChhcmcwKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBhcmcwLm5leHQoKTtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sIGFyZ3VtZW50cyk7IH0sXG4gICAgICAgIF9fd2JnX3Byb3RvdHlwZXNldGNhbGxfMzI0OWZjNjJhMGZhZmEzMDogZnVuY3Rpb24oYXJnMCwgYXJnMSwgYXJnMikge1xuICAgICAgICAgICAgVWludDhBcnJheS5wcm90b3R5cGUuc2V0LmNhbGwoZ2V0QXJyYXlVOEZyb21XYXNtMChhcmcwLCBhcmcxKSwgYXJnMik7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JnX3NldF82YmU0Mjc2OGM2OTBlMzgwOiBmdW5jdGlvbihhcmcwLCBhcmcxLCBhcmcyKSB7XG4gICAgICAgICAgICBhcmcwW2FyZzFdID0gYXJnMjtcbiAgICAgICAgfSxcbiAgICAgICAgX193Ymdfc2V0X2RjYTk5OTk5YmJhODhhOWE6IGZ1bmN0aW9uKGFyZzAsIGFyZzEsIGFyZzIpIHtcbiAgICAgICAgICAgIGFyZzBbYXJnMSA+Pj4gMF0gPSBhcmcyO1xuICAgICAgICB9LFxuICAgICAgICBfX3diZ19zdGFja18zYjBkOTc0YmJmMzFlNDRmOiBmdW5jdGlvbihhcmcwLCBhcmcxKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBhcmcxLnN0YWNrO1xuICAgICAgICAgICAgY29uc3QgcHRyMSA9IHBhc3NTdHJpbmdUb1dhc20wKHJldCwgd2FzbS5fX3diaW5kZ2VuX21hbGxvYywgd2FzbS5fX3diaW5kZ2VuX3JlYWxsb2MpO1xuICAgICAgICAgICAgY29uc3QgbGVuMSA9IFdBU01fVkVDVE9SX0xFTjtcbiAgICAgICAgICAgIGdldERhdGFWaWV3TWVtb3J5MCgpLnNldEludDMyKGFyZzAgKyA0ICogMSwgbGVuMSwgdHJ1ZSk7XG4gICAgICAgICAgICBnZXREYXRhVmlld01lbW9yeTAoKS5zZXRJbnQzMihhcmcwICsgNCAqIDAsIHB0cjEsIHRydWUpO1xuICAgICAgICB9LFxuICAgICAgICBfX3diZ192YWx1ZV9mMzYyNTA5MmVlNGIzN2Y0OiBmdW5jdGlvbihhcmcwKSB7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBhcmcwLnZhbHVlO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmluZGdlbl9jYXN0XzAwMDAwMDAwMDAwMDAwMDE6IGZ1bmN0aW9uKGFyZzApIHtcbiAgICAgICAgICAgIC8vIENhc3QgaW50cmluc2ljIGZvciBgRjY0IC0+IEV4dGVybnJlZmAuXG4gICAgICAgICAgICBjb25zdCByZXQgPSBhcmcwO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmluZGdlbl9jYXN0XzAwMDAwMDAwMDAwMDAwMDI6IGZ1bmN0aW9uKGFyZzAsIGFyZzEpIHtcbiAgICAgICAgICAgIC8vIENhc3QgaW50cmluc2ljIGZvciBgUmVmKFN0cmluZykgLT4gRXh0ZXJucmVmYC5cbiAgICAgICAgICAgIGNvbnN0IHJldCA9IGdldFN0cmluZ0Zyb21XYXNtMChhcmcwLCBhcmcxKTtcbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9fd2JpbmRnZW5fY2FzdF8wMDAwMDAwMDAwMDAwMDAzOiBmdW5jdGlvbihhcmcwKSB7XG4gICAgICAgICAgICAvLyBDYXN0IGludHJpbnNpYyBmb3IgYFU2NCAtPiBFeHRlcm5yZWZgLlxuICAgICAgICAgICAgY29uc3QgcmV0ID0gQmlnSW50LmFzVWludE4oNjQsIGFyZzApO1xuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSxcbiAgICAgICAgX193YmluZGdlbl9pbml0X2V4dGVybnJlZl90YWJsZTogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBjb25zdCB0YWJsZSA9IHdhc20uX193YmluZGdlbl9leHRlcm5yZWZzO1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gdGFibGUuZ3Jvdyg0KTtcbiAgICAgICAgICAgIHRhYmxlLnNldCgwLCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgdGFibGUuc2V0KG9mZnNldCArIDAsIHVuZGVmaW5lZCk7XG4gICAgICAgICAgICB0YWJsZS5zZXQob2Zmc2V0ICsgMSwgbnVsbCk7XG4gICAgICAgICAgICB0YWJsZS5zZXQob2Zmc2V0ICsgMiwgdHJ1ZSk7XG4gICAgICAgICAgICB0YWJsZS5zZXQob2Zmc2V0ICsgMywgZmFsc2UpO1xuICAgICAgICB9LFxuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgICAgX19wcm90b19fOiBudWxsLFxuICAgICAgICBcIi4vZGlmZl93YXNtX2JnLmpzXCI6IGltcG9ydDAsXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gYWRkVG9FeHRlcm5yZWZUYWJsZTAob2JqKSB7XG4gICAgY29uc3QgaWR4ID0gd2FzbS5fX2V4dGVybnJlZl90YWJsZV9hbGxvYygpO1xuICAgIHdhc20uX193YmluZGdlbl9leHRlcm5yZWZzLnNldChpZHgsIG9iaik7XG4gICAgcmV0dXJuIGlkeDtcbn1cblxuZnVuY3Rpb24gZGVidWdTdHJpbmcodmFsKSB7XG4gICAgLy8gcHJpbWl0aXZlIHR5cGVzXG4gICAgY29uc3QgdHlwZSA9IHR5cGVvZiB2YWw7XG4gICAgaWYgKHR5cGUgPT0gJ251bWJlcicgfHwgdHlwZSA9PSAnYm9vbGVhbicgfHwgdmFsID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuICBgJHt2YWx9YDtcbiAgICB9XG4gICAgaWYgKHR5cGUgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIGBcIiR7dmFsfVwiYDtcbiAgICB9XG4gICAgaWYgKHR5cGUgPT0gJ3N5bWJvbCcpIHtcbiAgICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSB2YWwuZGVzY3JpcHRpb247XG4gICAgICAgIGlmIChkZXNjcmlwdGlvbiA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1N5bWJvbCc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gYFN5bWJvbCgke2Rlc2NyaXB0aW9ufSlgO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICh0eXBlID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY29uc3QgbmFtZSA9IHZhbC5uYW1lO1xuICAgICAgICBpZiAodHlwZW9mIG5hbWUgPT0gJ3N0cmluZycgJiYgbmFtZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICByZXR1cm4gYEZ1bmN0aW9uKCR7bmFtZX0pYDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAnRnVuY3Rpb24nO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIG9iamVjdHNcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKSB7XG4gICAgICAgIGNvbnN0IGxlbmd0aCA9IHZhbC5sZW5ndGg7XG4gICAgICAgIGxldCBkZWJ1ZyA9ICdbJztcbiAgICAgICAgaWYgKGxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGRlYnVnICs9IGRlYnVnU3RyaW5nKHZhbFswXSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGxldCBpID0gMTsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBkZWJ1ZyArPSAnLCAnICsgZGVidWdTdHJpbmcodmFsW2ldKTtcbiAgICAgICAgfVxuICAgICAgICBkZWJ1ZyArPSAnXSc7XG4gICAgICAgIHJldHVybiBkZWJ1ZztcbiAgICB9XG4gICAgLy8gVGVzdCBmb3IgYnVpbHQtaW5cbiAgICBjb25zdCBidWlsdEluTWF0Y2hlcyA9IC9cXFtvYmplY3QgKFteXFxdXSspXFxdLy5leGVjKHRvU3RyaW5nLmNhbGwodmFsKSk7XG4gICAgbGV0IGNsYXNzTmFtZTtcbiAgICBpZiAoYnVpbHRJbk1hdGNoZXMgJiYgYnVpbHRJbk1hdGNoZXMubGVuZ3RoID4gMSkge1xuICAgICAgICBjbGFzc05hbWUgPSBidWlsdEluTWF0Y2hlc1sxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBGYWlsZWQgdG8gbWF0Y2ggdGhlIHN0YW5kYXJkICdbb2JqZWN0IENsYXNzTmFtZV0nXG4gICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKHZhbCk7XG4gICAgfVxuICAgIGlmIChjbGFzc05hbWUgPT0gJ09iamVjdCcpIHtcbiAgICAgICAgLy8gd2UncmUgYSB1c2VyIGRlZmluZWQgY2xhc3Mgb3IgT2JqZWN0XG4gICAgICAgIC8vIEpTT04uc3RyaW5naWZ5IGF2b2lkcyBwcm9ibGVtcyB3aXRoIGN5Y2xlcywgYW5kIGlzIGdlbmVyYWxseSBtdWNoXG4gICAgICAgIC8vIGVhc2llciB0aGFuIGxvb3BpbmcgdGhyb3VnaCBvd25Qcm9wZXJ0aWVzIG9mIGB2YWxgLlxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuICdPYmplY3QoJyArIEpTT04uc3RyaW5naWZ5KHZhbCkgKyAnKSc7XG4gICAgICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgICAgICAgIHJldHVybiAnT2JqZWN0JztcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBlcnJvcnNcbiAgICBpZiAodmFsIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIGAke3ZhbC5uYW1lfTogJHt2YWwubWVzc2FnZX1cXG4ke3ZhbC5zdGFja31gO1xuICAgIH1cbiAgICAvLyBUT0RPIHdlIGNvdWxkIHRlc3QgZm9yIG1vcmUgdGhpbmdzIGhlcmUsIGxpa2UgYFNldGBzIGFuZCBgTWFwYHMuXG4gICAgcmV0dXJuIGNsYXNzTmFtZTtcbn1cblxuZnVuY3Rpb24gZ2V0QXJyYXlVOEZyb21XYXNtMChwdHIsIGxlbikge1xuICAgIHB0ciA9IHB0ciA+Pj4gMDtcbiAgICByZXR1cm4gZ2V0VWludDhBcnJheU1lbW9yeTAoKS5zdWJhcnJheShwdHIgLyAxLCBwdHIgLyAxICsgbGVuKTtcbn1cblxubGV0IGNhY2hlZERhdGFWaWV3TWVtb3J5MCA9IG51bGw7XG5mdW5jdGlvbiBnZXREYXRhVmlld01lbW9yeTAoKSB7XG4gICAgaWYgKGNhY2hlZERhdGFWaWV3TWVtb3J5MCA9PT0gbnVsbCB8fCBjYWNoZWREYXRhVmlld01lbW9yeTAuYnVmZmVyLmRldGFjaGVkID09PSB0cnVlIHx8IChjYWNoZWREYXRhVmlld01lbW9yeTAuYnVmZmVyLmRldGFjaGVkID09PSB1bmRlZmluZWQgJiYgY2FjaGVkRGF0YVZpZXdNZW1vcnkwLmJ1ZmZlciAhPT0gd2FzbS5tZW1vcnkuYnVmZmVyKSkge1xuICAgICAgICBjYWNoZWREYXRhVmlld01lbW9yeTAgPSBuZXcgRGF0YVZpZXcod2FzbS5tZW1vcnkuYnVmZmVyKTtcbiAgICB9XG4gICAgcmV0dXJuIGNhY2hlZERhdGFWaWV3TWVtb3J5MDtcbn1cblxuZnVuY3Rpb24gZ2V0U3RyaW5nRnJvbVdhc20wKHB0ciwgbGVuKSB7XG4gICAgcmV0dXJuIGRlY29kZVRleHQocHRyID4+PiAwLCBsZW4pO1xufVxuXG5sZXQgY2FjaGVkVWludDhBcnJheU1lbW9yeTAgPSBudWxsO1xuZnVuY3Rpb24gZ2V0VWludDhBcnJheU1lbW9yeTAoKSB7XG4gICAgaWYgKGNhY2hlZFVpbnQ4QXJyYXlNZW1vcnkwID09PSBudWxsIHx8IGNhY2hlZFVpbnQ4QXJyYXlNZW1vcnkwLmJ5dGVMZW5ndGggPT09IDApIHtcbiAgICAgICAgY2FjaGVkVWludDhBcnJheU1lbW9yeTAgPSBuZXcgVWludDhBcnJheSh3YXNtLm1lbW9yeS5idWZmZXIpO1xuICAgIH1cbiAgICByZXR1cm4gY2FjaGVkVWludDhBcnJheU1lbW9yeTA7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZUVycm9yKGYsIGFyZ3MpIHtcbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gZi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnN0IGlkeCA9IGFkZFRvRXh0ZXJucmVmVGFibGUwKGUpO1xuICAgICAgICB3YXNtLl9fd2JpbmRnZW5fZXhuX3N0b3JlKGlkeCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpc0xpa2VOb25lKHgpIHtcbiAgICByZXR1cm4geCA9PT0gdW5kZWZpbmVkIHx8IHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIHBhc3NTdHJpbmdUb1dhc20wKGFyZywgbWFsbG9jLCByZWFsbG9jKSB7XG4gICAgaWYgKHJlYWxsb2MgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zdCBidWYgPSBjYWNoZWRUZXh0RW5jb2Rlci5lbmNvZGUoYXJnKTtcbiAgICAgICAgY29uc3QgcHRyID0gbWFsbG9jKGJ1Zi5sZW5ndGgsIDEpID4+PiAwO1xuICAgICAgICBnZXRVaW50OEFycmF5TWVtb3J5MCgpLnN1YmFycmF5KHB0ciwgcHRyICsgYnVmLmxlbmd0aCkuc2V0KGJ1Zik7XG4gICAgICAgIFdBU01fVkVDVE9SX0xFTiA9IGJ1Zi5sZW5ndGg7XG4gICAgICAgIHJldHVybiBwdHI7XG4gICAgfVxuXG4gICAgbGV0IGxlbiA9IGFyZy5sZW5ndGg7XG4gICAgbGV0IHB0ciA9IG1hbGxvYyhsZW4sIDEpID4+PiAwO1xuXG4gICAgY29uc3QgbWVtID0gZ2V0VWludDhBcnJheU1lbW9yeTAoKTtcblxuICAgIGxldCBvZmZzZXQgPSAwO1xuXG4gICAgZm9yICg7IG9mZnNldCA8IGxlbjsgb2Zmc2V0KyspIHtcbiAgICAgICAgY29uc3QgY29kZSA9IGFyZy5jaGFyQ29kZUF0KG9mZnNldCk7XG4gICAgICAgIGlmIChjb2RlID4gMHg3RikgYnJlYWs7XG4gICAgICAgIG1lbVtwdHIgKyBvZmZzZXRdID0gY29kZTtcbiAgICB9XG4gICAgaWYgKG9mZnNldCAhPT0gbGVuKSB7XG4gICAgICAgIGlmIChvZmZzZXQgIT09IDApIHtcbiAgICAgICAgICAgIGFyZyA9IGFyZy5zbGljZShvZmZzZXQpO1xuICAgICAgICB9XG4gICAgICAgIHB0ciA9IHJlYWxsb2MocHRyLCBsZW4sIGxlbiA9IG9mZnNldCArIGFyZy5sZW5ndGggKiAzLCAxKSA+Pj4gMDtcbiAgICAgICAgY29uc3QgdmlldyA9IGdldFVpbnQ4QXJyYXlNZW1vcnkwKCkuc3ViYXJyYXkocHRyICsgb2Zmc2V0LCBwdHIgKyBsZW4pO1xuICAgICAgICBjb25zdCByZXQgPSBjYWNoZWRUZXh0RW5jb2Rlci5lbmNvZGVJbnRvKGFyZywgdmlldyk7XG5cbiAgICAgICAgb2Zmc2V0ICs9IHJldC53cml0dGVuO1xuICAgICAgICBwdHIgPSByZWFsbG9jKHB0ciwgbGVuLCBvZmZzZXQsIDEpID4+PiAwO1xuICAgIH1cblxuICAgIFdBU01fVkVDVE9SX0xFTiA9IG9mZnNldDtcbiAgICByZXR1cm4gcHRyO1xufVxuXG5mdW5jdGlvbiB0YWtlRnJvbUV4dGVybnJlZlRhYmxlMChpZHgpIHtcbiAgICBjb25zdCB2YWx1ZSA9IHdhc20uX193YmluZGdlbl9leHRlcm5yZWZzLmdldChpZHgpO1xuICAgIHdhc20uX19leHRlcm5yZWZfdGFibGVfZGVhbGxvYyhpZHgpO1xuICAgIHJldHVybiB2YWx1ZTtcbn1cblxubGV0IGNhY2hlZFRleHREZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCd1dGYtOCcsIHsgaWdub3JlQk9NOiB0cnVlLCBmYXRhbDogdHJ1ZSB9KTtcbmNhY2hlZFRleHREZWNvZGVyLmRlY29kZSgpO1xuY29uc3QgTUFYX1NBRkFSSV9ERUNPREVfQllURVMgPSAyMTQ2NDM1MDcyO1xubGV0IG51bUJ5dGVzRGVjb2RlZCA9IDA7XG5mdW5jdGlvbiBkZWNvZGVUZXh0KHB0ciwgbGVuKSB7XG4gICAgbnVtQnl0ZXNEZWNvZGVkICs9IGxlbjtcbiAgICBpZiAobnVtQnl0ZXNEZWNvZGVkID49IE1BWF9TQUZBUklfREVDT0RFX0JZVEVTKSB7XG4gICAgICAgIGNhY2hlZFRleHREZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCd1dGYtOCcsIHsgaWdub3JlQk9NOiB0cnVlLCBmYXRhbDogdHJ1ZSB9KTtcbiAgICAgICAgY2FjaGVkVGV4dERlY29kZXIuZGVjb2RlKCk7XG4gICAgICAgIG51bUJ5dGVzRGVjb2RlZCA9IGxlbjtcbiAgICB9XG4gICAgcmV0dXJuIGNhY2hlZFRleHREZWNvZGVyLmRlY29kZShnZXRVaW50OEFycmF5TWVtb3J5MCgpLnN1YmFycmF5KHB0ciwgcHRyICsgbGVuKSk7XG59XG5cbmNvbnN0IGNhY2hlZFRleHRFbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKCk7XG5cbmlmICghKCdlbmNvZGVJbnRvJyBpbiBjYWNoZWRUZXh0RW5jb2RlcikpIHtcbiAgICBjYWNoZWRUZXh0RW5jb2Rlci5lbmNvZGVJbnRvID0gZnVuY3Rpb24gKGFyZywgdmlldykge1xuICAgICAgICBjb25zdCBidWYgPSBjYWNoZWRUZXh0RW5jb2Rlci5lbmNvZGUoYXJnKTtcbiAgICAgICAgdmlldy5zZXQoYnVmKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJlYWQ6IGFyZy5sZW5ndGgsXG4gICAgICAgICAgICB3cml0dGVuOiBidWYubGVuZ3RoXG4gICAgICAgIH07XG4gICAgfTtcbn1cblxubGV0IFdBU01fVkVDVE9SX0xFTiA9IDA7XG5cbmxldCB3YXNtO1xuZnVuY3Rpb24gX193YmdfZmluYWxpemVfaW5pdChpbnN0YW5jZSwgbW9kdWxlKSB7XG4gICAgd2FzbSA9IGluc3RhbmNlLmV4cG9ydHM7XG4gICAgY2FjaGVkRGF0YVZpZXdNZW1vcnkwID0gbnVsbDtcbiAgICBjYWNoZWRVaW50OEFycmF5TWVtb3J5MCA9IG51bGw7XG4gICAgd2FzbS5fX3diaW5kZ2VuX3N0YXJ0KCk7XG4gICAgcmV0dXJuIHdhc207XG59XG5cbmFzeW5jIGZ1bmN0aW9uIF9fd2JnX2xvYWQobW9kdWxlLCBpbXBvcnRzKSB7XG4gICAgaWYgKHR5cGVvZiBSZXNwb25zZSA9PT0gJ2Z1bmN0aW9uJyAmJiBtb2R1bGUgaW5zdGFuY2VvZiBSZXNwb25zZSkge1xuICAgICAgICBpZiAodHlwZW9mIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZyhtb2R1bGUsIGltcG9ydHMpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbGlkUmVzcG9uc2UgPSBtb2R1bGUub2sgJiYgZXhwZWN0ZWRSZXNwb25zZVR5cGUobW9kdWxlLnR5cGUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZhbGlkUmVzcG9uc2UgJiYgbW9kdWxlLmhlYWRlcnMuZ2V0KCdDb250ZW50LVR5cGUnKSAhPT0gJ2FwcGxpY2F0aW9uL3dhc20nKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcImBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZ2AgZmFpbGVkIGJlY2F1c2UgeW91ciBzZXJ2ZXIgZG9lcyBub3Qgc2VydmUgV2FzbSB3aXRoIGBhcHBsaWNhdGlvbi93YXNtYCBNSU1FIHR5cGUuIEZhbGxpbmcgYmFjayB0byBgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGVgIHdoaWNoIGlzIHNsb3dlci4gT3JpZ2luYWwgZXJyb3I6XFxuXCIsIGUpO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIHsgdGhyb3cgZTsgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYnl0ZXMgPSBhd2FpdCBtb2R1bGUuYXJyYXlCdWZmZXIoKTtcbiAgICAgICAgcmV0dXJuIGF3YWl0IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGJ5dGVzLCBpbXBvcnRzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBpbnN0YW5jZSA9IGF3YWl0IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKG1vZHVsZSwgaW1wb3J0cyk7XG5cbiAgICAgICAgaWYgKGluc3RhbmNlIGluc3RhbmNlb2YgV2ViQXNzZW1ibHkuSW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHJldHVybiB7IGluc3RhbmNlLCBtb2R1bGUgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBpbnN0YW5jZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4cGVjdGVkUmVzcG9uc2VUeXBlKHR5cGUpIHtcbiAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICBjYXNlICdiYXNpYyc6IGNhc2UgJ2NvcnMnOiBjYXNlICdkZWZhdWx0JzogcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaW5pdFN5bmMobW9kdWxlKSB7XG4gICAgaWYgKHdhc20gIT09IHVuZGVmaW5lZCkgcmV0dXJuIHdhc207XG5cblxuICAgIGlmIChtb2R1bGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKG1vZHVsZSkgPT09IE9iamVjdC5wcm90b3R5cGUpIHtcbiAgICAgICAgICAgICh7bW9kdWxlfSA9IG1vZHVsZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ3VzaW5nIGRlcHJlY2F0ZWQgcGFyYW1ldGVycyBmb3IgYGluaXRTeW5jKClgOyBwYXNzIGEgc2luZ2xlIG9iamVjdCBpbnN0ZWFkJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBpbXBvcnRzID0gX193YmdfZ2V0X2ltcG9ydHMoKTtcbiAgICBpZiAoIShtb2R1bGUgaW5zdGFuY2VvZiBXZWJBc3NlbWJseS5Nb2R1bGUpKSB7XG4gICAgICAgIG1vZHVsZSA9IG5ldyBXZWJBc3NlbWJseS5Nb2R1bGUobW9kdWxlKTtcbiAgICB9XG4gICAgY29uc3QgaW5zdGFuY2UgPSBuZXcgV2ViQXNzZW1ibHkuSW5zdGFuY2UobW9kdWxlLCBpbXBvcnRzKTtcbiAgICByZXR1cm4gX193YmdfZmluYWxpemVfaW5pdChpbnN0YW5jZSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIF9fd2JnX2luaXQobW9kdWxlX29yX3BhdGgpIHtcbiAgICBpZiAod2FzbSAhPT0gdW5kZWZpbmVkKSByZXR1cm4gd2FzbTtcblxuXG4gICAgaWYgKG1vZHVsZV9vcl9wYXRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZihtb2R1bGVfb3JfcGF0aCkgPT09IE9iamVjdC5wcm90b3R5cGUpIHtcbiAgICAgICAgICAgICh7bW9kdWxlX29yX3BhdGh9ID0gbW9kdWxlX29yX3BhdGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCd1c2luZyBkZXByZWNhdGVkIHBhcmFtZXRlcnMgZm9yIHRoZSBpbml0aWFsaXphdGlvbiBmdW5jdGlvbjsgcGFzcyBhIHNpbmdsZSBvYmplY3QgaW5zdGVhZCcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG1vZHVsZV9vcl9wYXRoID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbW9kdWxlX29yX3BhdGggPSBuZXcgVVJMKG5ldyBVUkwoJ2RpZmZfd2FzbV9iZy1jNllrYVpSTC53YXNtJywgaW1wb3J0Lm1ldGEudXJsKS5ocmVmKTtcbiAgICB9XG4gICAgY29uc3QgaW1wb3J0cyA9IF9fd2JnX2dldF9pbXBvcnRzKCk7XG5cbiAgICBpZiAodHlwZW9mIG1vZHVsZV9vcl9wYXRoID09PSAnc3RyaW5nJyB8fCAodHlwZW9mIFJlcXVlc3QgPT09ICdmdW5jdGlvbicgJiYgbW9kdWxlX29yX3BhdGggaW5zdGFuY2VvZiBSZXF1ZXN0KSB8fCAodHlwZW9mIFVSTCA9PT0gJ2Z1bmN0aW9uJyAmJiBtb2R1bGVfb3JfcGF0aCBpbnN0YW5jZW9mIFVSTCkpIHtcbiAgICAgICAgbW9kdWxlX29yX3BhdGggPSBmZXRjaChtb2R1bGVfb3JfcGF0aCk7XG4gICAgfVxuXG4gICAgY29uc3QgeyBpbnN0YW5jZSwgbW9kdWxlIH0gPSBhd2FpdCBfX3diZ19sb2FkKGF3YWl0IG1vZHVsZV9vcl9wYXRoLCBpbXBvcnRzKTtcblxuICAgIHJldHVybiBfX3diZ19maW5hbGl6ZV9pbml0KGluc3RhbmNlKTtcbn1cblxudmFyIHdhc20kMSA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbiAgICBfX3Byb3RvX186IG51bGwsXG4gICAgY29tcHV0ZURpZmY6IGNvbXB1dGVEaWZmLFxuICAgIGNvbXB1dGVEaWZmTGluZXM6IGNvbXB1dGVEaWZmTGluZXMsXG4gICAgZGVmYXVsdDogX193YmdfaW5pdCxcbiAgICBpbml0OiBpbml0LFxuICAgIGluaXRTeW5jOiBpbml0U3luY1xufSk7XG5cbi8qKlxuICogV0FTTSBtb2R1bGUgbG9hZGVyLlxuICpcbiAqIEhhbmRsZXMgYXN5bmMgaW5pdGlhbGl6YXRpb24gb2YgdGhlIFdBU00gbW9kdWxlLlxuICovXG4vLyBAdHMtaWdub3JlIC0tIGdlbmVyYXRlZCBhdCBidWlsZCB0aW1lIGJ5IGBucG0gcnVuIGJ1aWxkOndhc21gICh3YXNtLXBhY2sgLS10YXJnZXQgd2ViKS5cbmxldCB3YXNtTW9kdWxlID0gbnVsbDtcbmxldCBpbml0UHJvbWlzZSA9IG51bGw7XG4vKipcbiAqIEluaXRpYWxpemUgdGhlIFdBU00gbW9kdWxlLlxuICpcbiAqIFRoaXMgbXVzdCBiZSBjYWxsZWQgYmVmb3JlIHVzaW5nIGFueSBXQVNNLWJhc2VkIGRpZmYgZnVuY3Rpb25zLlxuICogSXQncyBzYWZlIHRvIGNhbGwgbXVsdGlwbGUgdGltZXMg4oCUIHN1YnNlcXVlbnQgY2FsbHMgYXJlIG5vLW9wcy5cbiAqXG4gKiBAcmV0dXJucyBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBXQVNNIGlzIHJlYWR5XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGluaXRXYXNtKCkge1xuICAgIGlmICh3YXNtTW9kdWxlKSB7XG4gICAgICAgIHJldHVybiB3YXNtTW9kdWxlO1xuICAgIH1cbiAgICBpZiAoaW5pdFByb21pc2UpIHtcbiAgICAgICAgcmV0dXJuIGluaXRQcm9taXNlO1xuICAgIH1cbiAgICBpbml0UHJvbWlzZSA9IChhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHdhc21VcmwgPSBuZXcgVVJMKG5ldyBVUkwoJ2RpZmZfd2FzbV9iZy1jNllrYVpSTC53YXNtJywgaW1wb3J0Lm1ldGEudXJsKS5ocmVmKTtcbiAgICAgICAgLy8gTm9kZSdzIHVuZGljaSBmZXRjaCBkb2VzIG5vdCBzdXBwb3J0IGZpbGU6Ly8gVVJMcywgc28gcmVhZCBieXRlcyBvdXJzZWx2ZXMuXG4gICAgICAgIGxldCBzb3VyY2UgPSB3YXNtVXJsO1xuICAgICAgICBpZiAodHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmIHByb2Nlc3MudmVyc2lvbnM/Lm5vZGUpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgcmVhZEZpbGUgfSA9IGF3YWl0IGltcG9ydCgnbm9kZTpmcy9wcm9taXNlcycpO1xuICAgICAgICAgICAgc291cmNlID0gYXdhaXQgcmVhZEZpbGUod2FzbVVybCk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgX193YmdfaW5pdCh7IG1vZHVsZV9vcl9wYXRoOiBzb3VyY2UgfSk7XG4gICAgICAgIGluaXQoKTtcbiAgICAgICAgd2FzbU1vZHVsZSA9IHdhc20kMTtcbiAgICAgICAgcmV0dXJuIHdhc21Nb2R1bGU7XG4gICAgfSkoKTtcbiAgICByZXR1cm4gaW5pdFByb21pc2U7XG59XG4vKipcbiAqIEdldCB0aGUgV0FTTSBtb2R1bGUgc3luY2hyb25vdXNseS5cbiAqXG4gKiBAdGhyb3dzIEVycm9yIGlmIFdBU00gaGFzbid0IGJlZW4gaW5pdGlhbGl6ZWQgeWV0XG4gKiBAcmV0dXJucyBUaGUgV0FTTSBtb2R1bGVcbiAqL1xuZnVuY3Rpb24gZ2V0V2FzbSgpIHtcbiAgICBpZiAoIXdhc21Nb2R1bGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdXQVNNIG5vdCBpbml0aWFsaXplZC4gQ2FsbCBpbml0V2FzbSgpIGZpcnN0IGFuZCBhd2FpdCBpdC4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHdhc21Nb2R1bGU7XG59XG5cbi8qKlxuICogQ29udmVyc2lvbnMgYmV0d2VlbiBgTGluZXNEaWZmYCAoaW4tbWVtb3J5IGNsYXNzIGluc3RhbmNlcykgYW5kXG4gKiBgV2lyZUxpbmVzRGlmZmAgKHBsYWluIEpTT04tZnJpZW5kbHkgc2hhcGUgdXNlZCBvbiB0aGUgd29ya2VyIGJvdW5kYXJ5KS5cbiAqL1xuZnVuY3Rpb24gbGluZXNEaWZmVG9XaXJlKGRpZmYpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBjaGFuZ2VzOiBkaWZmLmNoYW5nZXMubWFwKGRldGFpbGVkVG9XaXJlKSxcbiAgICAgICAgbW92ZXM6IGRpZmYubW92ZXMubWFwKG1vdmVUb1dpcmUpLFxuICAgICAgICBoaXRUaW1lb3V0OiBkaWZmLmhpdFRpbWVvdXQsXG4gICAgfTtcbn1cbmZ1bmN0aW9uIHdpcmVUb0xpbmVzRGlmZih3aXJlKSB7XG4gICAgY29uc3QgY2hhbmdlcyA9IHdpcmUuY2hhbmdlcy5tYXAod2lyZVRvRGV0YWlsZWQpO1xuICAgIGNvbnN0IG1vdmVzID0gd2lyZS5tb3Zlcy5tYXAod2lyZVRvTW92ZSk7XG4gICAgcmV0dXJuIG5ldyBMaW5lc0RpZmYoY2hhbmdlcywgbW92ZXMsIHdpcmUuaGl0VGltZW91dCk7XG59XG5mdW5jdGlvbiBkZXRhaWxlZFRvV2lyZShtKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgb3JpZ2luYWw6IHtcbiAgICAgICAgICAgIHN0YXJ0TGluZU51bWJlcjogbS5vcmlnaW5hbC5zdGFydExpbmVOdW1iZXIsXG4gICAgICAgICAgICBlbmRMaW5lTnVtYmVyRXhjbHVzaXZlOiBtLm9yaWdpbmFsLmVuZExpbmVOdW1iZXJFeGNsdXNpdmUsXG4gICAgICAgIH0sXG4gICAgICAgIG1vZGlmaWVkOiB7XG4gICAgICAgICAgICBzdGFydExpbmVOdW1iZXI6IG0ubW9kaWZpZWQuc3RhcnRMaW5lTnVtYmVyLFxuICAgICAgICAgICAgZW5kTGluZU51bWJlckV4Y2x1c2l2ZTogbS5tb2RpZmllZC5lbmRMaW5lTnVtYmVyRXhjbHVzaXZlLFxuICAgICAgICB9LFxuICAgICAgICBpbm5lckNoYW5nZXM6IG0uaW5uZXJDaGFuZ2VzID8gbS5pbm5lckNoYW5nZXMubWFwKHJhbmdlTWFwcGluZ1RvV2lyZSkgOiBudWxsLFxuICAgIH07XG59XG5mdW5jdGlvbiB3aXJlVG9EZXRhaWxlZChtKSB7XG4gICAgY29uc3QgaW5uZXIgPSBtLmlubmVyQ2hhbmdlcz8ubWFwKHdpcmVUb1JhbmdlTWFwcGluZyk7XG4gICAgcmV0dXJuIG5ldyBEZXRhaWxlZExpbmVSYW5nZU1hcHBpbmcobmV3IExpbmVSYW5nZShtLm9yaWdpbmFsLnN0YXJ0TGluZU51bWJlciwgbS5vcmlnaW5hbC5lbmRMaW5lTnVtYmVyRXhjbHVzaXZlKSwgbmV3IExpbmVSYW5nZShtLm1vZGlmaWVkLnN0YXJ0TGluZU51bWJlciwgbS5tb2RpZmllZC5lbmRMaW5lTnVtYmVyRXhjbHVzaXZlKSwgaW5uZXIpO1xufVxuZnVuY3Rpb24gcmFuZ2VNYXBwaW5nVG9XaXJlKHJtKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgb3JpZ2luYWxTdGFydExpbmU6IHJtLm9yaWdpbmFsUmFuZ2Uuc3RhcnRMaW5lTnVtYmVyLFxuICAgICAgICBvcmlnaW5hbFN0YXJ0Q29sdW1uOiBybS5vcmlnaW5hbFJhbmdlLnN0YXJ0Q29sdW1uLFxuICAgICAgICBvcmlnaW5hbEVuZExpbmU6IHJtLm9yaWdpbmFsUmFuZ2UuZW5kTGluZU51bWJlcixcbiAgICAgICAgb3JpZ2luYWxFbmRDb2x1bW46IHJtLm9yaWdpbmFsUmFuZ2UuZW5kQ29sdW1uLFxuICAgICAgICBtb2RpZmllZFN0YXJ0TGluZTogcm0ubW9kaWZpZWRSYW5nZS5zdGFydExpbmVOdW1iZXIsXG4gICAgICAgIG1vZGlmaWVkU3RhcnRDb2x1bW46IHJtLm1vZGlmaWVkUmFuZ2Uuc3RhcnRDb2x1bW4sXG4gICAgICAgIG1vZGlmaWVkRW5kTGluZTogcm0ubW9kaWZpZWRSYW5nZS5lbmRMaW5lTnVtYmVyLFxuICAgICAgICBtb2RpZmllZEVuZENvbHVtbjogcm0ubW9kaWZpZWRSYW5nZS5lbmRDb2x1bW4sXG4gICAgfTtcbn1cbmZ1bmN0aW9uIHdpcmVUb1JhbmdlTWFwcGluZyhybSkge1xuICAgIHJldHVybiBuZXcgUmFuZ2VNYXBwaW5nKG5ldyBSYW5nZShybS5vcmlnaW5hbFN0YXJ0TGluZSwgcm0ub3JpZ2luYWxTdGFydENvbHVtbiwgcm0ub3JpZ2luYWxFbmRMaW5lLCBybS5vcmlnaW5hbEVuZENvbHVtbiksIG5ldyBSYW5nZShybS5tb2RpZmllZFN0YXJ0TGluZSwgcm0ubW9kaWZpZWRTdGFydENvbHVtbiwgcm0ubW9kaWZpZWRFbmRMaW5lLCBybS5tb2RpZmllZEVuZENvbHVtbikpO1xufVxuZnVuY3Rpb24gbW92ZVRvV2lyZShtKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGluZVJhbmdlTWFwcGluZzoge1xuICAgICAgICAgICAgb3JpZ2luYWw6IHtcbiAgICAgICAgICAgICAgICBzdGFydExpbmVOdW1iZXI6IG0ubGluZVJhbmdlTWFwcGluZy5vcmlnaW5hbC5zdGFydExpbmVOdW1iZXIsXG4gICAgICAgICAgICAgICAgZW5kTGluZU51bWJlckV4Y2x1c2l2ZTogbS5saW5lUmFuZ2VNYXBwaW5nLm9yaWdpbmFsLmVuZExpbmVOdW1iZXJFeGNsdXNpdmUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbW9kaWZpZWQ6IHtcbiAgICAgICAgICAgICAgICBzdGFydExpbmVOdW1iZXI6IG0ubGluZVJhbmdlTWFwcGluZy5tb2RpZmllZC5zdGFydExpbmVOdW1iZXIsXG4gICAgICAgICAgICAgICAgZW5kTGluZU51bWJlckV4Y2x1c2l2ZTogbS5saW5lUmFuZ2VNYXBwaW5nLm1vZGlmaWVkLmVuZExpbmVOdW1iZXJFeGNsdXNpdmUsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBjaGFuZ2VzOiBtLmNoYW5nZXMubWFwKGRldGFpbGVkVG9XaXJlKSxcbiAgICB9O1xufVxuZnVuY3Rpb24gd2lyZVRvTW92ZShtKSB7XG4gICAgY29uc3QgbHJtID0gbmV3IExpbmVSYW5nZU1hcHBpbmcobmV3IExpbmVSYW5nZShtLmxpbmVSYW5nZU1hcHBpbmcub3JpZ2luYWwuc3RhcnRMaW5lTnVtYmVyLCBtLmxpbmVSYW5nZU1hcHBpbmcub3JpZ2luYWwuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSksIG5ldyBMaW5lUmFuZ2UobS5saW5lUmFuZ2VNYXBwaW5nLm1vZGlmaWVkLnN0YXJ0TGluZU51bWJlciwgbS5saW5lUmFuZ2VNYXBwaW5nLm1vZGlmaWVkLmVuZExpbmVOdW1iZXJFeGNsdXNpdmUpKTtcbiAgICByZXR1cm4gbmV3IE1vdmVkVGV4dChscm0sIG0uY2hhbmdlcy5tYXAod2lyZVRvRGV0YWlsZWQpKTtcbn1cblxuZXhwb3J0IHsgRGVmYXVsdExpbmVzRGlmZkNvbXB1dGVyIGFzIEQsIExpbmVSYW5nZSBhcyBMLCBPZmZzZXRSYW5nZSBhcyBPLCBSYW5nZU1hcHBpbmcgYXMgUiwgUmFuZ2UgYXMgYSwgRGV0YWlsZWRMaW5lUmFuZ2VNYXBwaW5nIGFzIGIsIExpbmVzRGlmZiBhcyBjLCBMaW5lUmFuZ2VNYXBwaW5nIGFzIGQsIGdldFdhc20gYXMgZywgaW5pdFdhc20gYXMgaSwgbGluZXNEaWZmVG9XaXJlIGFzIGwsIHdpcmVUb0xpbmVzRGlmZiBhcyB3IH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD13aXJlLmpzLm1hcFxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9
|