sliftutils 1.7.66 → 1.7.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CLAUDE.md +1 -0
  2. package/dist/test.ts.cache +187 -36
  3. package/dist/treeSummary.ts.cache +359 -0
  4. package/index.d.ts +67 -18
  5. package/misc/dist/environment.ts.cache +2 -2
  6. package/misc/dist/getSecret.ts.cache +2 -2
  7. package/misc/dist/strings.ts.cache +2 -2
  8. package/misc/dist/zip.ts.cache +2 -2
  9. package/misc/https/dist/certs.ts.cache +2 -2
  10. package/misc/https/dist/persistentLocalStorage.ts.cache +2 -2
  11. package/package.json +1 -1
  12. package/render-utils/dist/observer.tsx.cache +2 -2
  13. package/storage/ArchivesDisk.d.ts +2 -2
  14. package/storage/ArchivesDisk.ts +3 -2
  15. package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +2 -2
  16. package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +2 -2
  17. package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +2 -2
  18. package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +2 -2
  19. package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +2 -2
  20. package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +2 -2
  21. package/storage/BulkDatabase2/dist/blockCache.ts.cache +2 -2
  22. package/storage/BulkDatabase2/dist/mergeLock.ts.cache +2 -2
  23. package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +2 -2
  24. package/storage/BulkDatabase2/dist/streamLog.ts.cache +2 -2
  25. package/storage/BulkDatabase2/dist/syncClient.ts.cache +2 -2
  26. package/storage/IArchives.d.ts +14 -2
  27. package/storage/IArchives.ts +15 -2
  28. package/storage/backblaze.d.ts +2 -2
  29. package/storage/backblaze.ts +5 -4
  30. package/storage/dist/ArchivesDisk.ts.cache +5 -3
  31. package/storage/dist/FileFolderAPI.tsx.cache +2 -2
  32. package/storage/dist/IArchives.ts.cache +2 -2
  33. package/storage/dist/IndexedDBFileFolderAPI.ts.cache +2 -2
  34. package/storage/dist/JSONStorage.ts.cache +2 -2
  35. package/storage/dist/PendingManager.tsx.cache +2 -2
  36. package/storage/dist/TransactionStorage.ts.cache +2 -2
  37. package/storage/dist/backblaze.ts.cache +6 -5
  38. package/storage/dist/fileSystemPointer.ts.cache +2 -2
  39. package/storage/dist/remoteFileStorage.ts.cache +2 -2
  40. package/storage/remoteStorage/ArchivesRemote.d.ts +2 -2
  41. package/storage/remoteStorage/ArchivesRemote.ts +3 -3
  42. package/storage/remoteStorage/ArchivesUrl.d.ts +2 -2
  43. package/storage/remoteStorage/ArchivesUrl.ts +8 -6
  44. package/storage/remoteStorage/accessStats.d.ts +25 -0
  45. package/storage/remoteStorage/accessStats.ts +86 -0
  46. package/storage/remoteStorage/blobStore.d.ts +3 -3
  47. package/storage/remoteStorage/blobStore.ts +9 -5
  48. package/storage/remoteStorage/createArchives.d.ts +2 -2
  49. package/storage/remoteStorage/createArchives.ts +3 -3
  50. package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +4 -4
  51. package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +11 -7
  52. package/storage/remoteStorage/dist/blobStore.ts.cache +11 -5
  53. package/storage/remoteStorage/dist/cliArgs.ts.cache +2 -2
  54. package/storage/remoteStorage/dist/createArchives.ts.cache +4 -4
  55. package/storage/remoteStorage/dist/deployTakeover.ts.cache +2 -2
  56. package/storage/remoteStorage/dist/intermediateSources.ts.cache +2 -2
  57. package/storage/remoteStorage/dist/remoteConfig.ts.cache +2 -2
  58. package/storage/remoteStorage/dist/sourceWrapper.ts.cache +2 -2
  59. package/storage/remoteStorage/dist/sourcesList.ts.cache +2 -2
  60. package/storage/remoteStorage/dist/storageClientController.ts.cache +2 -2
  61. package/storage/remoteStorage/dist/storageController.ts.cache +52 -15
  62. package/storage/remoteStorage/dist/storageServerState.ts.cache +26 -75
  63. package/storage/remoteStorage/storageController.d.ts +9 -1
  64. package/storage/remoteStorage/storageController.ts +49 -11
  65. package/storage/remoteStorage/storageServerState.d.ts +2 -2
  66. package/storage/remoteStorage/storageServerState.ts +24 -71
  67. package/test-files-cache.json +1 -0
  68. package/test.ts +127 -10
  69. package/treeSummary.d.ts +31 -0
  70. package/treeSummary.ts +331 -54
@@ -0,0 +1,359 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
+ //exports.TreeSummary = void 0;
4
+ const misc_1 = require("socket-function/src/misc");
5
+ const DEFAULT_OUTPUT_COUNT = 100;
6
+ const TRACKED_NODES_PER_OUTPUT = 100;
7
+ const MIN_TRACKED_NODES = 1000;
8
+ const MAX_TRACKED_NODES = 10000;
9
+ const PRUNE_TARGET_DIVISOR = 2;
10
+ const PRUNE_SEARCH_ITERATIONS = 20;
11
+ class TreeSummary {
12
+ constructor(config) {
13
+ this.config = config;
14
+ this.nodeCount = 1;
15
+ this.root = { label: "", children: new Map(), summary: config.createSummary() };
16
+ let outputCount = config.expectedOutputCount || DEFAULT_OUTPUT_COUNT;
17
+ this.maxTrackedNodes = Math.min(Math.max(outputCount * TRACKED_NODES_PER_OUTPUT, MIN_TRACKED_NODES), MAX_TRACKED_NODES);
18
+ }
19
+ add(value) {
20
+ let path = this.config.getPath(value);
21
+ let node = this.root;
22
+ this.config.addToSummary(value, node.summary);
23
+ let pos = 0;
24
+ while (pos < path.length) {
25
+ let child = node.children.get(path[pos]);
26
+ if (!child) {
27
+ child = { label: path.slice(pos), children: new Map(), summary: this.config.createSummary() };
28
+ node.children.set(path[pos], child);
29
+ this.nodeCount++;
30
+ this.config.addToSummary(value, child.summary);
31
+ node = child;
32
+ break;
33
+ }
34
+ let label = child.label;
35
+ let limit = Math.min(label.length, path.length - pos);
36
+ let common = 1;
37
+ while (common < limit && label.charCodeAt(common) === path.charCodeAt(pos + common)) {
38
+ common++;
39
+ }
40
+ if (common < label.length) {
41
+ this.splitNode(child, common);
42
+ }
43
+ this.config.addToSummary(value, child.summary);
44
+ node = child;
45
+ pos += common;
46
+ }
47
+ let selfSummary = node.selfSummary;
48
+ if (!selfSummary) {
49
+ selfSummary = this.config.createSummary();
50
+ node.selfSummary = selfSummary;
51
+ }
52
+ this.config.addToSummary(value, selfSummary);
53
+ if (this.nodeCount > this.maxTrackedNodes) {
54
+ this.prune();
55
+ }
56
+ }
57
+ // Splits a node's edge label at labelPos, inserting a new parent covering the prefix. The prefix node's summary is a merge-clone of the original aggregate, since it covers the exact same set of values.
58
+ splitNode(node, labelPos) {
59
+ let suffix = {
60
+ label: node.label.slice(labelPos),
61
+ children: node.children,
62
+ summary: node.summary,
63
+ selfSummary: node.selfSummary,
64
+ truncatedSummary: node.truncatedSummary,
65
+ };
66
+ let prefixSummary = this.config.createSummary();
67
+ this.config.mergeSummaries(prefixSummary, suffix.summary);
68
+ node.label = node.label.slice(0, labelPos);
69
+ node.summary = prefixSummary;
70
+ node.selfSummary = undefined;
71
+ node.truncatedSummary = undefined;
72
+ node.children = new Map([[suffix.label[0], suffix]]);
73
+ this.nodeCount++;
74
+ }
75
+ getTrackedNodeCount() {
76
+ return this.nodeCount;
77
+ }
78
+ // Starts fully collapsed (one entry for the whole tree) and repeatedly refines the heaviest entry, one split at a time. A split pulls the heaviest branch out as its own entry and leaves the remaining siblings combined in a group entry, so entries are never wasted on light branches. This recomputes from the live per-node summaries, so it always reflects everything added so far.
79
+ getSummaries(maxCount) {
80
+ if (maxCount <= 0) {
81
+ throw new Error(`maxCount must be positive, was ${maxCount}`);
82
+ }
83
+ if (!this.root.selfSummary && !this.root.truncatedSummary && this.root.children.size === 0) {
84
+ return [];
85
+ }
86
+ let entries = [this.subtreeEntry(this.root, "")];
87
+ while (entries.length < maxCount) {
88
+ let bestIndex = -1;
89
+ for (let i = 0; i < entries.length; i++) {
90
+ if (!this.isRefinable(entries[i]))
91
+ continue;
92
+ if (bestIndex === -1 || entries[i].weight > entries[bestIndex].weight) {
93
+ bestIndex = i;
94
+ }
95
+ }
96
+ if (bestIndex === -1)
97
+ break;
98
+ let refined = this.refine(entries[bestIndex]);
99
+ entries.splice(bestIndex, 1, ...refined);
100
+ }
101
+ let output = entries.map(entry => {
102
+ let path = entry.path;
103
+ if (entry.kind !== "self") {
104
+ path += "*";
105
+ }
106
+ return {
107
+ path,
108
+ kind: entry.kind,
109
+ summary: this.buildOutputSummary(entry),
110
+ weight: entry.weight,
111
+ };
112
+ });
113
+ (0, misc_1.sort)(output, entry => entry.path);
114
+ return output;
115
+ }
116
+ isRefinable(entry) {
117
+ if (entry.kind === "self" || entry.kind === "truncated")
118
+ return false;
119
+ if (entry.kind === "group") {
120
+ let members = entry.members;
121
+ if (!members || members.size === 0)
122
+ return false;
123
+ return members.size + (entry.extras && entry.extras.length || 0) >= 2;
124
+ }
125
+ let node = entry.node;
126
+ if (!node)
127
+ return false;
128
+ if (entry.extras && entry.extras.length > 0)
129
+ return true;
130
+ let parts = node.children.size + (node.selfSummary && 1 || 0) + (node.truncatedSummary && 1 || 0);
131
+ return parts >= 2;
132
+ }
133
+ // Replaces one entry with exactly two, so each refinement costs exactly one output slot.
134
+ refine(entry) {
135
+ if (entry.kind === "group") {
136
+ let members = entry.members;
137
+ if (!members) {
138
+ throw new Error(`Group entry missing members at ${entry.path}`);
139
+ }
140
+ return this.splitParts(members, entry.extras || [], entry.path);
141
+ }
142
+ let node = entry.node;
143
+ if (entry.kind !== "subtree" || !node) {
144
+ throw new Error(`Entry is not refinable at ${entry.path}`);
145
+ }
146
+ let extras = entry.extras;
147
+ if (extras && extras.length > 0) {
148
+ // Split off the chain residues as one combined entry, so a long chain of pruning leftovers costs a single slot instead of one per character.
149
+ let weight = 0;
150
+ for (let extra of extras) {
151
+ weight += this.config.getWeight(extra);
152
+ }
153
+ return [
154
+ { kind: "group", path: entry.path, extras, weight },
155
+ this.subtreeEntry(node, entry.nodePath || entry.path),
156
+ ];
157
+ }
158
+ // Children live below the node, so their paths must extend nodePath, never the (possibly shorter) display path.
159
+ let nodePath = entry.nodePath || entry.path;
160
+ let truncatedList = [];
161
+ if (node.truncatedSummary) {
162
+ truncatedList.push(node.truncatedSummary);
163
+ }
164
+ let selfSummary = node.selfSummary;
165
+ if (selfSummary) {
166
+ return [
167
+ { kind: "self", path: nodePath, node, weight: this.config.getWeight(selfSummary) },
168
+ this.entryForParts(node.children, truncatedList, nodePath),
169
+ ];
170
+ }
171
+ return this.splitParts(node.children, truncatedList, nodePath);
172
+ }
173
+ splitParts(children, extras, path) {
174
+ let heaviestChar = "";
175
+ let heaviest;
176
+ for (let [char, child] of children) {
177
+ if (!heaviest || this.config.getWeight(child.summary) > this.config.getWeight(heaviest.summary)) {
178
+ heaviestChar = char;
179
+ heaviest = child;
180
+ }
181
+ }
182
+ if (!heaviest) {
183
+ throw new Error(`Cannot split empty child set at ${path}`);
184
+ }
185
+ let rest = new Map(children);
186
+ rest.delete(heaviestChar);
187
+ return [
188
+ this.subtreeEntry(heaviest, path + heaviest.label),
189
+ this.entryForParts(rest, extras, path),
190
+ ];
191
+ }
192
+ entryForParts(children, extras, path) {
193
+ if (children.size === 0) {
194
+ if (extras.length === 0) {
195
+ throw new Error(`No parts to make an entry from at ${path}`);
196
+ }
197
+ let weight = 0;
198
+ for (let extra of extras) {
199
+ weight += this.config.getWeight(extra);
200
+ }
201
+ return { kind: "truncated", path, extras, weight };
202
+ }
203
+ if (children.size === 1 && extras.length === 0) {
204
+ for (let child of children.values()) {
205
+ return this.subtreeEntry(child, path + child.label);
206
+ }
207
+ }
208
+ let weight = 0;
209
+ for (let extra of extras) {
210
+ weight += this.config.getWeight(extra);
211
+ }
212
+ for (let child of children.values()) {
213
+ weight += this.config.getWeight(child.summary);
214
+ }
215
+ return { kind: "group", path, members: children, extras, weight };
216
+ }
217
+ subtreeEntry(node, path) {
218
+ // Follow single-child chains so paths are maximal shared prefixes instead of single characters. Self/truncated summaries found along the chain are carried on the entry instead of stopping the descent, so pruning leftovers scattered along a chain end up combined instead of each forcing an entry.
219
+ let carried = [];
220
+ let carriedWeight = 0;
221
+ let nodePath = path;
222
+ while (node.children.size === 1) {
223
+ let selfSummary = node.selfSummary;
224
+ if (selfSummary) {
225
+ carried.push(selfSummary);
226
+ carriedWeight += this.config.getWeight(selfSummary);
227
+ }
228
+ let truncated = node.truncatedSummary;
229
+ if (truncated) {
230
+ carried.push(truncated);
231
+ carriedWeight += this.config.getWeight(truncated);
232
+ }
233
+ for (let child of node.children.values()) {
234
+ nodePath += child.label;
235
+ node = child;
236
+ }
237
+ }
238
+ // With nothing carried the entry is just the deep node, so display the full descended prefix.
239
+ if (carried.length === 0) {
240
+ path = nodePath;
241
+ }
242
+ return {
243
+ kind: "subtree",
244
+ path,
245
+ node,
246
+ nodePath,
247
+ extras: carried,
248
+ weight: this.config.getWeight(node.summary) + carriedWeight,
249
+ };
250
+ }
251
+ buildOutputSummary(entry) {
252
+ let result = this.config.createSummary();
253
+ if (entry.kind === "group" || entry.kind === "truncated") {
254
+ for (let extra of entry.extras || []) {
255
+ this.config.mergeSummaries(result, extra);
256
+ }
257
+ if (entry.members) {
258
+ for (let member of entry.members.values()) {
259
+ this.config.mergeSummaries(result, member.summary);
260
+ }
261
+ }
262
+ return result;
263
+ }
264
+ let node = entry.node;
265
+ if (!node) {
266
+ throw new Error(`Entry missing node at ${entry.path}`);
267
+ }
268
+ if (entry.kind === "self") {
269
+ let selfSummary = node.selfSummary;
270
+ if (!selfSummary) {
271
+ throw new Error(`Self entry missing selfSummary at ${entry.path}`);
272
+ }
273
+ this.config.mergeSummaries(result, selfSummary);
274
+ return result;
275
+ }
276
+ for (let extra of entry.extras || []) {
277
+ this.config.mergeSummaries(result, extra);
278
+ }
279
+ this.config.mergeSummaries(result, node.summary);
280
+ return result;
281
+ }
282
+ // Collapses the lightest subtrees until the node count is back under the target. Collapsing a node merges everything below it into its truncatedSummary, keeping the data but dropping the path detail. If those prefixes get heavy again later, new adds rebuild branches there and the next prune takes out whatever stayed light instead.
283
+ prune() {
284
+ let target = Math.floor(this.maxTrackedNodes / PRUNE_TARGET_DIVISOR);
285
+ let need = this.nodeCount - target;
286
+ if (need <= 0)
287
+ return;
288
+ let stats = new Map();
289
+ let measure = (node) => {
290
+ let size = 1;
291
+ for (let child of node.children.values()) {
292
+ size += measure(child).size;
293
+ }
294
+ let result = { size, weight: this.config.getWeight(node.summary) };
295
+ stats.set(node, result);
296
+ return result;
297
+ };
298
+ let rootStats = measure(this.root);
299
+ let getStats = (node) => {
300
+ let stat = stats.get(node);
301
+ if (!stat) {
302
+ throw new Error(`Missing node stats during prune`);
303
+ }
304
+ return stat;
305
+ };
306
+ // Collapsing every maximal subtree whose weight is under a limit frees a monotonically increasing number of nodes, so binary search for the smallest limit that frees enough.
307
+ let freedAt = (limit) => {
308
+ let freed = 0;
309
+ let visit = (node) => {
310
+ if (node.children.size === 0)
311
+ return;
312
+ if (getStats(node).weight <= limit) {
313
+ freed += getStats(node).size - 1;
314
+ return;
315
+ }
316
+ for (let child of node.children.values()) {
317
+ visit(child);
318
+ }
319
+ };
320
+ visit(this.root);
321
+ return freed;
322
+ };
323
+ let low = 0;
324
+ let high = rootStats.weight;
325
+ for (let i = 0; i < PRUNE_SEARCH_ITERATIONS; i++) {
326
+ let mid = (low + high) / 2;
327
+ if (freedAt(mid) >= need) {
328
+ high = mid;
329
+ }
330
+ else {
331
+ low = mid;
332
+ }
333
+ }
334
+ let collapseVisit = (node) => {
335
+ if (node.children.size === 0)
336
+ return;
337
+ if (getStats(node).weight <= high) {
338
+ let truncated = node.truncatedSummary;
339
+ if (!truncated) {
340
+ truncated = this.config.createSummary();
341
+ node.truncatedSummary = truncated;
342
+ }
343
+ for (let child of node.children.values()) {
344
+ this.config.mergeSummaries(truncated, child.summary);
345
+ }
346
+ this.nodeCount -= getStats(node).size - 1;
347
+ node.children.clear();
348
+ return;
349
+ }
350
+ for (let child of node.children.values()) {
351
+ collapseVisit(child);
352
+ }
353
+ };
354
+ collapseVisit(this.root);
355
+ }
356
+ }
357
+ exports.TreeSummary = TreeSummary;
358
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZVN1bW1hcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0cmVlU3VtbWFyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtREFBZ0Q7QUFFaEQsTUFBTSxvQkFBb0IsR0FBRyxHQUFHLENBQUM7QUFDakMsTUFBTSx3QkFBd0IsR0FBRyxHQUFHLENBQUM7QUFDckMsTUFBTSxpQkFBaUIsR0FBRyxJQUFLLENBQUM7QUFDaEMsTUFBTSxpQkFBaUIsR0FBRyxLQUFNLENBQUM7QUFDakMsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLENBQUM7QUFDL0IsTUFBTSx1QkFBdUIsR0FBRyxFQUFFLENBQUM7QUF3Q25DLE1BQWEsV0FBVztJQUtwQixZQUFvQixNQVFuQjtRQVJtQixXQUFNLEdBQU4sTUFBTSxDQVF6QjtRQVhPLGNBQVMsR0FBRyxDQUFDLENBQUM7UUFZbEIsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDO1FBQ2hGLElBQUksV0FBVyxHQUFHLE1BQU0sQ0FBQyxtQkFBbUIsSUFBSSxvQkFBb0IsQ0FBQztRQUNyRSxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEdBQUcsd0JBQXdCLEVBQUUsaUJBQWlCLENBQUMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO0lBQzVILENBQUM7SUFFTSxHQUFHLENBQUMsS0FBUTtRQUNmLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3RDLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFDckIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxPQUFP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QUFJLEtBQUssQ0FBQztnQkFBRSxPQUFPO1lBQ3JDLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxJQUFJLEVBQUUsQ0FBQztnQkFDaEMsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDO2dCQUN0QyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7b0JBQ2IsU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUM7b0JBQ3hDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxTQUFTLENBQUM7Z0JBQ3RDLENBQUM7Z0JBQ0QsS0FBSyxJQUFJLEtBQUssSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7b0JBQ3ZDLElBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ3pELENBQUM7Z0JBQ0QsSUFBSSxDQUFDLFNBQVMsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztnQkFDMUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDdEIsT0FBTztZQUNYLENBQUM7WUFDRCxLQUFLLElBQUksS0FBSyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztnQkFDdkMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3pCLENBQUM7UUFDTCxDQUFDLENBQUM7UUFDRixhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdCLENBQUM7Q0FDSjtBQXBXRCxrQ0FvV0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzb3J0IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvbWlzY1wiO1xuXG5jb25zdCBERUZBVUxUX09VVFBVVF9DT1VOVCA9IDEwMDtcbmNvbnN0IFRSQUNLRURfTk9ERVNfUEVSX09VVFBVVCA9IDEwMDtcbmNvbnN0IE1JTl9UUkFDS0VEX05PREVTID0gMV8wMDA7XG5jb25zdCBNQVhfVFJBQ0tFRF9OT0RFUyA9IDEwXzAwMDtcbmNvbnN0IFBSVU5FX1RBUkdFVF9ESVZJU09SID0gMjtcbmNvbnN0IFBSVU5FX1NFQVJDSF9JVEVSQVRJT05TID0gMjA7XG5cbnR5cGUgVHJlZU5vZGU8Uz4gPSB7XG4gICAgLy8gVGhlIHBhdGggZnJhZ21lbnQgdGhpcyBub2RlIGNvdmVycywgaS5lLiB0aGUgZWRnZSBmcm9tIGl0cyBwYXJlbnQuIENoaWxkcmVuIGFyZSBrZXllZCBieSB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIHRoZWlyIGxhYmVsLlxuICAgIGxhYmVsOiBzdHJpbmc7XG4gICAgY2hpbGRyZW46IE1hcDxzdHJpbmcsIFRyZWVOb2RlPFM+PjtcbiAgICAvLyBBZ2dyZWdhdGUgb2YgZXZlcnkgdmFsdWUgd2hvc2UgcGF0aCBwYXNzZXMgdGhyb3VnaCAob3IgZW5kcyBhdCkgdGhpcyBub2RlLlxuICAgIHN1bW1hcnk6IFM7XG4gICAgLy8gQWdncmVnYXRlIG9mIG9ubHkgdGhlIHZhbHVlcyB3aG9zZSBwYXRoIGVuZHMgZXhhY3RseSBhdCB0aGlzIG5vZGUuXG4gICAgc2VsZlN1bW1hcnk/OiBTO1xuICAgIC8vIEFnZ3JlZ2F0ZSBvZiB2YWx1ZXMgdGhhdCB3ZXJlIGJlbG93IHRoaXMgbm9kZSBiZWZvcmUgcHJ1bmluZyBjb2xsYXBzZWQgdGhlaXIgYnJhbmNoZXMuIFRoZWlyIHBhdGggZGV0YWlsIGlzIGdvbmUsIGJ1dCB0aGVpciBkYXRhIGlzIHByZXNlcnZlZC5cbiAgICB0cnVuY2F0ZWRTdW1tYXJ5PzogUztcbn07XG5cbmV4cG9ydCB0eXBlIFN1bW1hcnlFbnRyeTxTPiA9IHtcbiAgICAvLyBFbmRzIHdpdGggXCIqXCIgdW5sZXNzIHRoZSBlbnRyeSBpcyBhIHNpbmdsZSBleGFjdCBwYXRoIHRoYXQgd2FzIGhlYXZ5IGVub3VnaCB0byBzdGFuZCBvbiBpdHMgb3duLlxuICAgIHBhdGg6IHN0cmluZztcbiAgICAvLyBcInNlbGZcIiA9IHZhbHVlcyB3aG9zZSBwYXRoIGlzIGV4YWN0bHkgcGF0aC4gXCJzdWJ0cmVlXCIgPSBldmVyeSB2YWx1ZSB3aG9zZSBwYXRoIHN0YXJ0cyB3aXRoIHBhdGguIFwiZ3JvdXBcIiA9IHZhbHVlcyB1bmRlciBwYXRoIGtlcHQgY29tYmluZWQgKGxpZ2h0IHNpYmxpbmcgYnJhbmNoZXMsIGNoYWluIGxlZnRvdmVycywgb3IgYm90aCkgYmVjYXVzZSBub25lIHdhcyBoZWF2eSBlbm91Z2ggdG8gZGVzZXJ2ZSBpdHMgb3duIGVudHJ5LiBcInRydW5jYXRlZFwiID0gdmFsdWVzIHVuZGVyIHBhdGggd2hvc2UgZGV0YWlsIHdhcyBwcnVuZWQgYXdheS5cbiAgICBraW5kOiBcInNlbGZcIiB8IFwic3VidHJlZVwiIHwgXCJncm91cFwiIHwgXCJ0cnVuY2F0ZWRcIjtcbiAgICBzdW1tYXJ5OiBTO1xuICAgIHdlaWdodDogbnVtYmVyO1xufTtcblxudHlwZSBQZW5kaW5nRW50cnk8Uz4gPSB7XG4gICAga2luZDogXCJzZWxmXCIgfCBcInN1YnRyZWVcIiB8IFwiZ3JvdXBcIiB8IFwidHJ1bmNhdGVkXCI7XG4gICAgcGF0aDogc3RyaW5nO1xuICAgIG5vZGU/OiBUcmVlTm9kZTxTPjtcbiAgICAvLyBXaGVyZSBub2RlIGFjdHVhbGx5IHNpdHMgd2hlbiBwYXRoIGNvbXByZXNzaW9uIGRlc2NlbmRlZCBhIHNpbmdsZS1jaGlsZCBjaGFpbiBwYXN0IGNhcnJpZWQgcmVzaWR1ZXM7IGVxdWFscyBwYXRoIHdoZW4gbm8gcmVzaWR1ZXMgd2VyZSBjYXJyaWVkLlxuICAgIG5vZGVQYXRoPzogc3RyaW5nO1xuICAgIG1lbWJlcnM/OiBNYXA8c3RyaW5nLCBUcmVlTm9kZTxTPj47XG4gICAgLy8gU2VsZi90cnVuY2F0ZWQgc3VtbWFyaWVzIHRoYXQgc2l0IGJldHdlZW4gcGF0aCBhbmQgbm9kZSAoZm9yIFwic3VidHJlZVwiKSwgb3IgdGhlIGxvb3NlIHN1bW1hcmllcyBvZiBhIGNvbWJpbmVkIGVudHJ5IChmb3IgXCJncm91cFwiL1widHJ1bmNhdGVkXCIpLlxuICAgIGV4dHJhcz86IFNbXTtcbiAgICB3ZWlnaHQ6IG51bWJlcjtcbn07XG5cbnR5cGUgTm9kZVN0YXRzID0ge1xuICAgIHNpemU6IG51bWJlcjtcbiAgICB3ZWlnaHQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCBjbGFzcyBUcmVlU3VtbWFyeTxULCBTPiB7XG4gICAgcHJpdmF0ZSByb290OiBUcmVlTm9kZTxTPjtcbiAgICBwcml2YXRlIG5vZGVDb3VudCA9IDE7XG4gICAgcHJpdmF0ZSBtYXhUcmFja2VkTm9kZXM6IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgY29uZmlnOiB7XG4gICAgICAgIGdldFBhdGg6ICh2YWx1ZTogVCkgPT4gc3RyaW5nO1xuICAgICAgICBjcmVhdGVTdW1tYXJ5OiAoKSA9PiBTO1xuICAgICAgICBhZGRUb1N1bW1hcnk6ICh2YWx1ZTogVCwgc3VtbWFyeTogUykgPT4gdm9pZDtcbiAgICAgICAgbWVyZ2VTdW1tYXJpZXM6ICh0YXJnZXQ6IFMsIHNvdXJjZTogUykgPT4gdm9pZDtcbiAgICAgICAgZ2V0V2VpZ2h0OiAoc3VtbWFyeTogUykgPT4gbnVtYmVyO1xuICAgICAgICAvLyBTaXplcyB0aGUgaW50ZXJuYWwgdHJlZSwgd2hpY2gga2VlcHMgcm91Z2hseSBUUkFDS0VEX05PREVTX1BFUl9PVVRQVVQgdGltZXMgdGhpcyBtYW55IG5vZGVzIHNvIG91dHB1dCBncmFudWxhcml0eSBkZWNpc2lvbnMgaGF2ZSBkZXRhaWwgdG8gd29yayB3aXRoLlxuICAgICAgICBleHBlY3RlZE91dHB1dENvdW50PzogbnVtYmVyO1xuICAgIH0pIHtcbiAgICAgICAgdGhpcy5yb290ID0geyBsYWJlbDogXCJcIiwgY2hpbGRyZW46IG5ldyBNYXAoKSwgc3VtbWFyeTogY29uZmlnLmNyZWF0ZVN1bW1hcnkoKSB9O1xuICAgICAgICBsZXQgb3V0cHV0Q291bnQgPSBjb25maWcuZXhwZWN0ZWRPdXRwdXRDb3VudCB8fCBERUZBVUxUX09VVFBVVF9DT1VOVDtcbiAgICAgICAgdGhpcy5tYXhUcmFja2VkTm9kZXMgPSBNYXRoLm1pbihNYXRoLm1heChvdXRwdXRDb3VudCAqIFRSQUNLRURfTk9ERVNfUEVSX09VVFBVVCwgTUlOX1RSQUNLRURfTk9ERVMpLCBNQVhfVFJBQ0tFRF9OT0RFUyk7XG4gICAgfVxuXG4gICAgcHVibGljIGFkZCh2YWx1ZTogVCkge1xuICAgICAgICBsZXQgcGF0aCA9IHRoaXMuY29uZmlnLmdldFBhdGgodmFsdWUpO1xuICAgICAgICBsZXQgbm9kZSA9IHRoaXMucm9vdDtcbiAgICAgICAgdGhpcy5jb25maWcuYWRkVG9TdW1tYXJ5KHZhbHVlLCBub2RlLnN1bW1hcnkpO1xuICAgICAgICBsZXQgcG9zID0gMDtcbiAgICAgICAgd2hpbGUgKHBvcyA8IHBhdGgubGVuZ3RoKSB7XG4gICAgICAgICAgICBsZXQgY2hpbGQgPSBub2RlLmNoaWxkcmVuLmdldChwYXRoW3Bvc10pO1xuICAgICAgICAgICAgaWYgKCFjaGlsZCkge1xuICAgICAgICAgICAgICAgIGNoaWxkID0geyBsYWJlbDogcGF0aC5zbGljZShwb3MpLCBjaGlsZHJlbjogbmV3IE1hcCgpLCBzdW1tYXJ5OiB0aGlzLmNvbmZpZy5jcmVhdGVTdW1tYXJ5KCkgfTtcbiAgICAgICAgICAgICAgICBub2RlLmNoaWxkcmVuLnNldChwYXRoW3Bvc10sIGNoaWxkKTtcbiAgICAgICAgICAgICAgICB0aGlzLm5vZGVDb3VudCsrO1xuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLmFkZFRvU3VtbWFyeSh2YWx1ZSwgY2hpbGQuc3VtbWFyeSk7XG4gICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGxhYmVsID0gY2hpbGQubGFiZWw7XG4gICAgICAgICAgICBsZXQgbGltaXQgPSBNYXRoLm1pbihsYWJlbC5sZW5ndGgsIHBhdGgubGVuZ3RoIC0gcG9zKTtcbiAgICAgICAgICAgIGxldCBjb21tb24gPSAxO1xuICAgICAgICAgICAgd2hpbGUgKGNvbW1vbiA8IGxpbWl0ICYmIGxhYmVsLmNoYXJDb2RlQXQoY29tbW9uKSA9PT0gcGF0aC5jaGFyQ29kZUF0KHBvcyArIGNvbW1vbikpIHtcbiAgICAgICAgICAgICAgICBjb21tb24rKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb21tb24gPCBsYWJlbC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNwbGl0Tm9kZShjaGlsZCwgY29tbW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmFkZFRvU3VtbWFyeSh2YWx1ZSwgY2hpbGQuc3VtbWFyeSk7XG4gICAgICAgICAgICBub2RlID0gY2hpbGQ7XG4gICAgICAgICAgICBwb3MgKz0gY29tbW9uO1xuICAgICAgICB9XG4gICAgICAgIGxldCBzZWxmU3VtbWFyeSA9IG5vZGUuc2VsZlN1bW1hcnk7XG4gICAgICAgIGlmICghc2VsZlN1bW1hcnkpIHtcbiAgICAgICAgICAgIHNlbGZTdW1tYXJ5ID0gdGhpcy5jb25maWcuY3JlYXRlU3VtbWFyeSgpO1xuICAgICAgICAgICAgbm9kZS5zZWxmU3VtbWFyeSA9IHNlbGZTdW1tYXJ5O1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29uZmlnLmFkZFRvU3VtbWFyeSh2YWx1ZSwgc2VsZlN1bW1hcnkpO1xuICAgICAgICBpZiAodGhpcy5ub2RlQ291bnQgPiB0aGlzLm1heFRyYWNrZWROb2Rlcykge1xuICAgICAgICAgICAgdGhpcy5wcnVuZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gU3BsaXRzIGEgbm9kZSdzIGVkZ2UgbGFiZWwgYXQgbGFiZWxQb3MsIGluc2VydGluZyBhIG5ldyBwYXJlbnQgY292ZXJpbmcgdGhlIHByZWZpeC4gVGhlIHByZWZpeCBub2RlJ3Mgc3VtbWFyeSBpcyBhIG1lcmdlLWNsb25lIG9mIHRoZSBvcmlnaW5hbCBhZ2dyZWdhdGUsIHNpbmNlIGl0IGNvdmVycyB0aGUgZXhhY3Qgc2FtZSBzZXQgb2YgdmFsdWVzLlxuICAgIHByaXZhdGUgc3BsaXROb2RlKG5vZGU6IFRyZWVOb2RlPFM+LCBsYWJlbFBvczogbnVtYmVyKSB7XG4gICAgICAgIGxldCBzdWZmaXg6IFRyZWVOb2RlPFM+ID0ge1xuICAgICAgICAgICAgbGFiZWw6IG5vZGUubGFiZWwuc2xpY2UobGFiZWxQb3MpLFxuICAgICAgICAgICAgY2hpbGRyZW46IG5vZGUuY2hpbGRyZW4sXG4gICAgICAgICAgICBzdW1tYXJ5OiBub2RlLnN1bW1hcnksXG4gICAgICAgICAgICBzZWxmU3VtbWFyeTogbm9kZS5zZWxmU3VtbWFyeSxcbiAgICAgICAgICAgIHRydW5jYXRlZFN1bW1hcnk6IG5vZGUudHJ1bmNhdGVkU3VtbWFyeSxcbiAgICAgICAgfTtcbiAgICAgICAgbGV0IHByZWZpeFN1bW1hcnkgPSB0aGlzLmNvbmZpZy5jcmVhdGVTdW1tYXJ5KCk7XG4gICAgICAgIHRoaXMuY29uZmlnLm1lcmdlU3VtbWFyaWVzKHByZWZpeFN1bW1hcnksIHN1ZmZpeC5zdW1tYXJ5KTtcbiAgICAgICAgbm9kZS5sYWJlbCA9IG5vZGUubGFiZWwuc2xpY2UoMCwgbGFiZWxQb3MpO1xuICAgICAgICBub2RlLnN1bW1hcnkgPSBwcmVmaXhTdW1tYXJ5O1xuICAgICAgICBub2RlLnNlbGZTdW1tYXJ5ID0gdW5kZWZpbmVkO1xuICAgICAgICBub2RlLnRydW5jYXRlZFN1bW1hcnkgPSB1bmRlZmluZWQ7XG4gICAgICAgIG5vZGUuY2hpbGRyZW4gPSBuZXcgTWFwKFtbc3VmZml4LmxhYmVsWzBdLCBzdWZmaXhdXSk7XG4gICAgICAgIHRoaXMubm9kZUNvdW50Kys7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFRyYWNrZWROb2RlQ291bnQoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubm9kZUNvdW50O1xuICAgIH1cblxuICAgIC8vIFN0YXJ0cyBmdWxseSBjb2xsYXBzZWQgKG9uZSBlbnRyeSBmb3IgdGhlIHdob2xlIHRyZWUpIGFuZCByZXBlYXRlZGx5IHJlZmluZXMgdGhlIGhlYXZpZXN0IGVudHJ5LCBvbmUgc3BsaXQgYXQgYSB0aW1lLiBBIHNwbGl0IHB1bGxzIHRoZSBoZWF2aWVzdCBicmFuY2ggb3V0IGFzIGl0cyBvd24gZW50cnkgYW5kIGxlYXZlcyB0aGUgcmVtYWluaW5nIHNpYmxpbmdzIGNvbWJpbmVkIGluIGEgZ3JvdXAgZW50cnksIHNvIGVudHJpZXMgYXJlIG5ldmVyIHdhc3RlZCBvbiBsaWdodCBicmFuY2hlcy4gVGhpcyByZWNvbXB1dGVzIGZyb20gdGhlIGxpdmUgcGVyLW5vZGUgc3VtbWFyaWVzLCBzbyBpdCBhbHdheXMgcmVmbGVjdHMgZXZlcnl0aGluZyBhZGRlZCBzbyBmYXIuXG4gICAgcHVibGljIGdldFN1bW1hcmllcyhtYXhDb3VudDogbnVtYmVyKTogU3VtbWFyeUVudHJ5PFM+W10ge1xuICAgICAgICBpZiAobWF4Q291bnQgPD0gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBtYXhDb3VudCBtdXN0IGJlIHBvc2l0aXZlLCB3YXMgJHttYXhDb3VudH1gKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucm9vdC5zZWxmU3VtbWFyeSAmJiAhdGhpcy5yb290LnRydW5jYXRlZFN1bW1hcnkgJiYgdGhpcy5yb290LmNoaWxkcmVuLnNpemUgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgZW50cmllczogUGVuZGluZ0VudHJ5PFM+W10gPSBbdGhpcy5zdWJ0cmVlRW50cnkodGhpcy5yb290LCBcIlwiKV07XG4gICAgICAgIHdoaWxlIChlbnRyaWVzLmxlbmd0aCA8IG1heENvdW50KSB7XG4gICAgICAgICAgICBsZXQgYmVzdEluZGV4ID0gLTE7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVudHJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaXNSZWZpbmFibGUoZW50cmllc1tpXSkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGlmIChiZXN0SW5kZXggPT09IC0xIHx8IGVudHJpZXNbaV0ud2VpZ2h0ID4gZW50cmllc1tiZXN0SW5kZXhdLndlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICBiZXN0SW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChiZXN0SW5kZXggPT09IC0xKSBicmVhaztcbiAgICAgICAgICAgIGxldCByZWZpbmVkID0gdGhpcy5yZWZpbmUoZW50cmllc1tiZXN0SW5kZXhdKTtcbiAgICAgICAgICAgIGVudHJpZXMuc3BsaWNlKGJlc3RJbmRleCwgMSwgLi4ucmVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IG91dHB1dCA9IGVudHJpZXMubWFwKGVudHJ5ID0+IHtcbiAgICAgICAgICAgIGxldCBwYXRoID0gZW50cnkucGF0aDtcbiAgICAgICAgICAgIGlmIChlbnRyeS5raW5kICE9PSBcInNlbGZcIikge1xuICAgICAgICAgICAgICAgIHBhdGggKz0gXCIqXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgICAgICAga2luZDogZW50cnkua2luZCxcbiAgICAgICAgICAgICAgICBzdW1tYXJ5OiB0aGlzLmJ1aWxkT3V0cHV0U3VtbWFyeShlbnRyeSksXG4gICAgICAgICAgICAgICAgd2VpZ2h0OiBlbnRyeS53ZWlnaHQsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICAgICAgc29ydChvdXRwdXQsIGVudHJ5ID0+IGVudHJ5LnBhdGgpO1xuICAgICAgICByZXR1cm4gb3V0cHV0O1xuICAgIH1cblxuICAgIHByaXZhdGUgaXNSZWZpbmFibGUoZW50cnk6IFBlbmRpbmdFbnRyeTxTPik6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoZW50cnkua2luZCA9PT0gXCJzZWxmXCIgfHwgZW50cnkua2luZCA9PT0gXCJ0cnVuY2F0ZWRcIikgcmV0dXJuIGZhbHNlO1xuICAgICAgICBpZiAoZW50cnkua2luZCA9PT0gXCJncm91cFwiKSB7XG4gICAgICAgICAgICBsZXQgbWVtYmVycyA9IGVudHJ5Lm1lbWJlcnM7XG4gICAgICAgICAgICBpZiAoIW1lbWJlcnMgfHwgbWVtYmVycy5zaXplID09PSAwKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gbWVtYmVycy5zaXplICsgKGVudHJ5LmV4dHJhcyAmJiBlbnRyeS5leHRyYXMubGVuZ3RoIHx8IDApID49IDI7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IG5vZGUgPSBlbnRyeS5ub2RlO1xuICAgICAgICBpZiAoIW5vZGUpIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKGVudHJ5LmV4dHJhcyAmJiBlbnRyeS5leHRyYXMubGVuZ3RoID4gMCkgcmV0dXJuIHRydWU7XG4gICAgICAgIGxldCBwYXJ0cyA9IG5vZGUuY2hpbGRyZW4uc2l6ZSArIChub2RlLnNlbGZTdW1tYXJ5ICYmIDEgfHwgMCkgKyAobm9kZS50cnVuY2F0ZWRTdW1tYXJ5ICYmIDEgfHwgMCk7XG4gICAgICAgIHJldHVybiBwYXJ0cyA+PSAyO1xuICAgIH1cblxuICAgIC8vIFJlcGxhY2VzIG9uZSBlbnRyeSB3aXRoIGV4YWN0bHkgdHdvLCBzbyBlYWNoIHJlZmluZW1lbnQgY29zdHMgZXhhY3RseSBvbmUgb3V0cHV0IHNsb3QuXG4gICAgcHJpdmF0ZSByZWZpbmUoZW50cnk6IFBlbmRpbmdFbnRyeTxTPik6IFBlbmRpbmdFbnRyeTxTPltdIHtcbiAgICAgICAgaWYgKGVudHJ5LmtpbmQgPT09IFwiZ3JvdXBcIikge1xuICAgICAgICAgICAgbGV0IG1lbWJlcnMgPSBlbnRyeS5tZW1iZXJzO1xuICAgICAgICAgICAgaWYgKCFtZW1iZXJzKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBHcm91cCBlbnRyeSBtaXNzaW5nIG1lbWJlcnMgYXQgJHtlbnRyeS5wYXRofWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3BsaXRQYXJ0cyhtZW1iZXJzLCBlbnRyeS5leHRyYXMgfHwgW10sIGVudHJ5LnBhdGgpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBub2RlID0gZW50cnkubm9kZTtcbiAgICAgICAgaWYgKGVudHJ5LmtpbmQgIT09IFwic3VidHJlZVwiIHx8ICFub2RlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEVudHJ5IGlzIG5vdCByZWZpbmFibGUgYXQgJHtlbnRyeS5wYXRofWApO1xuICAgICAgICB9XG4gICAgICAgIGxldCBleHRyYXMgPSBlbnRyeS5leHRyYXM7XG4gICAgICAgIGlmIChleHRyYXMgJiYgZXh0cmFzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIC8vIFNwbGl0IG9mZiB0aGUgY2hhaW4gcmVzaWR1ZXMgYXMgb25lIGNvbWJpbmVkIGVudHJ5LCBzbyBhIGxvbmcgY2hhaW4gb2YgcHJ1bmluZyBsZWZ0b3ZlcnMgY29zdHMgYSBzaW5nbGUgc2xvdCBpbnN0ZWFkIG9mIG9uZSBwZXIgY2hhcmFjdGVyLlxuICAgICAgICAgICAgbGV0IHdlaWdodCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBleHRyYSBvZiBleHRyYXMpIHtcbiAgICAgICAgICAgICAgICB3ZWlnaHQgKz0gdGhpcy5jb25maWcuZ2V0V2VpZ2h0KGV4dHJhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgeyBraW5kOiBcImdyb3VwXCIsIHBhdGg6IGVudHJ5LnBhdGgsIGV4dHJhcywgd2VpZ2h0IH0sXG4gICAgICAgICAgICAgICAgdGhpcy5zdWJ0cmVlRW50cnkobm9kZSwgZW50cnkubm9kZVBhdGggfHwgZW50cnkucGF0aCksXG4gICAgICAgICAgICBdO1xuICAgICAgICB9XG4gICAgICAgIC8vIENoaWxkcmVuIGxpdmUgYmVsb3cgdGhlIG5vZGUsIHNvIHRoZWlyIHBhdGhzIG11c3QgZXh0ZW5kIG5vZGVQYXRoLCBuZXZlciB0aGUgKHBvc3NpYmx5IHNob3J0ZXIpIGRpc3BsYXkgcGF0aC5cbiAgICAgICAgbGV0IG5vZGVQYXRoID0gZW50cnkubm9kZVBhdGggfHwgZW50cnkucGF0aDtcbiAgICAgICAgbGV0IHRydW5jYXRlZExpc3Q6IFNbXSA9IFtdO1xuICAgICAgICBpZiAobm9kZS50cnVuY2F0ZWRTdW1tYXJ5KSB7XG4gICAgICAgICAgICB0cnVuY2F0ZWRMaXN0LnB1c2gobm9kZS50cnVuY2F0ZWRTdW1tYXJ5KTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgc2VsZlN1bW1hcnkgPSBub2RlLnNlbGZTdW1tYXJ5O1xuICAgICAgICBpZiAoc2VsZlN1bW1hcnkpIHtcbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgeyBraW5kOiBcInNlbGZcIiwgcGF0aDogbm9kZVBhdGgsIG5vZGUsIHdlaWdodDogdGhpcy5jb25maWcuZ2V0V2VpZ2h0KHNlbGZTdW1tYXJ5KSB9LFxuICAgICAgICAgICAgICAgIHRoaXMuZW50cnlGb3JQYXJ0cyhub2RlLmNoaWxkcmVuLCB0cnVuY2F0ZWRMaXN0LCBub2RlUGF0aCksXG4gICAgICAgICAgICBdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnNwbGl0UGFydHMobm9kZS5jaGlsZHJlbiwgdHJ1bmNhdGVkTGlzdCwgbm9kZVBhdGgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3BsaXRQYXJ0cyhjaGlsZHJlbjogTWFwPHN0cmluZywgVHJlZU5vZGU8Uz4+LCBleHRyYXM6IFNbXSwgcGF0aDogc3RyaW5nKTogUGVuZGluZ0VudHJ5PFM+W10ge1xuICAgICAgICBsZXQgaGVhdmllc3RDaGFyID0gXCJcIjtcbiAgICAgICAgbGV0IGhlYXZpZXN0OiBUcmVlTm9kZTxTPiB8IHVuZGVmaW5lZDtcbiAgICAgICAgZm9yIChsZXQgW2NoYXIsIGNoaWxkXSBvZiBjaGlsZHJlbikge1xuICAgICAgICAgICAgaWYgKCFoZWF2aWVzdCB8fCB0aGlzLmNvbmZpZy5nZXRXZWlnaHQoY2hpbGQuc3VtbWFyeSkgPiB0aGlzLmNvbmZpZy5nZXRXZWlnaHQoaGVhdmllc3Quc3VtbWFyeSkpIHtcbiAgICAgICAgICAgICAgICBoZWF2aWVzdENoYXIgPSBjaGFyO1xuICAgICAgICAgICAgICAgIGhlYXZpZXN0ID0gY2hpbGQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFoZWF2aWVzdCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3Qgc3BsaXQgZW1wdHkgY2hpbGQgc2V0IGF0ICR7cGF0aH1gKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcmVzdCA9IG5ldyBNYXAoY2hpbGRyZW4pO1xuICAgICAgICByZXN0LmRlbGV0ZShoZWF2aWVzdENoYXIpO1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgdGhpcy5zdWJ0cmVlRW50cnkoaGVhdmllc3QsIHBhdGggKyBoZWF2aWVzdC5sYWJlbCksXG4gICAgICAgICAgICB0aGlzLmVudHJ5Rm9yUGFydHMocmVzdCwgZXh0cmFzLCBwYXRoKSxcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGVudHJ5Rm9yUGFydHMoY2hpbGRyZW46IE1hcDxzdHJpbmcsIFRyZWVOb2RlPFM+PiwgZXh0cmFzOiBTW10sIHBhdGg6IHN0cmluZyk6IFBlbmRpbmdFbnRyeTxTPiB7XG4gICAgICAgIGlmIChjaGlsZHJlbi5zaXplID09PSAwKSB7XG4gICAgICAgICAgICBpZiAoZXh0cmFzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gcGFydHMgdG8gbWFrZSBhbiBlbnRyeSBmcm9tIGF0ICR7cGF0aH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCB3ZWlnaHQgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgZXh0cmEgb2YgZXh0cmFzKSB7XG4gICAgICAgICAgICAgICAgd2VpZ2h0ICs9IHRoaXMuY29uZmlnLmdldFdlaWdodChleHRyYSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4geyBraW5kOiBcInRydW5jYXRlZFwiLCBwYXRoLCBleHRyYXMsIHdlaWdodCB9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGlsZHJlbi5zaXplID09PSAxICYmIGV4dHJhcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGZvciAobGV0IGNoaWxkIG9mIGNoaWxkcmVuLnZhbHVlcygpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3VidHJlZUVudHJ5KGNoaWxkLCBwYXRoICsgY2hpbGQubGFiZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGxldCB3ZWlnaHQgPSAwO1xuICAgICAgICBmb3IgKGxldCBleHRyYSBvZiBleHRyYXMpIHtcbiAgICAgICAgICAgIHdlaWdodCArPSB0aGlzLmNvbmZpZy5nZXRXZWlnaHQoZXh0cmEpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGNoaWxkIG9mIGNoaWxkcmVuLnZhbHVlcygpKSB7XG4gICAgICAgICAgICB3ZWlnaHQgKz0gdGhpcy5jb25maWcuZ2V0V2VpZ2h0KGNoaWxkLnN1bW1hcnkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IGtpbmQ6IFwiZ3JvdXBcIiwgcGF0aCwgbWVtYmVyczogY2hpbGRyZW4sIGV4dHJhcywgd2VpZ2h0IH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdWJ0cmVlRW50cnkobm9kZTogVHJlZU5vZGU8Uz4sIHBhdGg6IHN0cmluZyk6IFBlbmRpbmdFbnRyeTxTPiB7XG4gICAgICAgIC8vIEZvbGxvdyBzaW5nbGUtY2hpbGQgY2hhaW5zIHNvIHBhdGhzIGFyZSBtYXhpbWFsIHNoYXJlZCBwcmVmaXhlcyBpbnN0ZWFkIG9mIHNpbmdsZSBjaGFyYWN0ZXJzLiBTZWxmL3RydW5jYXRlZCBzdW1tYXJpZXMgZm91bmQgYWxvbmcgdGhlIGNoYWluIGFyZSBjYXJyaWVkIG9uIHRoZSBlbnRyeSBpbnN0ZWFkIG9mIHN0b3BwaW5nIHRoZSBkZXNjZW50LCBzbyBwcnVuaW5nIGxlZnRvdmVycyBzY2F0dGVyZWQgYWxvbmcgYSBjaGFpbiBlbmQgdXAgY29tYmluZWQgaW5zdGVhZCBvZiBlYWNoIGZvcmNpbmcgYW4gZW50cnkuXG4gICAgICAgIGxldCBjYXJyaWVkOiBTW10gPSBbXTtcbiAgICAgICAgbGV0IGNhcnJpZWRXZWlnaHQgPSAwO1xuICAgICAgICBsZXQgbm9kZVBhdGggPSBwYXRoO1xuICAgICAgICB3aGlsZSAobm9kZS5jaGlsZHJlbi5zaXplID09PSAxKSB7XG4gICAgICAgICAgICBsZXQgc2VsZlN1bW1hcnkgPSBub2RlLnNlbGZTdW1tYXJ5O1xuICAgICAgICAgICAgaWYgKHNlbGZTdW1tYXJ5KSB7XG4gICAgICAgICAgICAgICAgY2FycmllZC5wdXNoKHNlbGZTdW1tYXJ5KTtcbiAgICAgICAgICAgICAgICBjYXJyaWVkV2VpZ2h0ICs9IHRoaXMuY29uZmlnLmdldFdlaWdodChzZWxmU3VtbWFyeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgdHJ1bmNhdGVkID0gbm9kZS50cnVuY2F0ZWRTdW1tYXJ5O1xuICAgICAgICAgICAgaWYgKHRydW5jYXRlZCkge1xuICAgICAgICAgICAgICAgIGNhcnJpZWQucHVzaCh0cnVuY2F0ZWQpO1xuICAgICAgICAgICAgICAgIGNhcnJpZWRXZWlnaHQgKz0gdGhpcy5jb25maWcuZ2V0V2VpZ2h0KHRydW5jYXRlZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBjaGlsZCBvZiBub2RlLmNoaWxkcmVuLnZhbHVlcygpKSB7XG4gICAgICAgICAgICAgICAgbm9kZVBhdGggKz0gY2hpbGQubGFiZWw7XG4gICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIFdpdGggbm90aGluZyBjYXJyaWVkIHRoZSBlbnRyeSBpcyBqdXN0IHRoZSBkZWVwIG5vZGUsIHNvIGRpc3BsYXkgdGhlIGZ1bGwgZGVzY2VuZGVkIHByZWZpeC5cbiAgICAgICAgaWYgKGNhcnJpZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBwYXRoID0gbm9kZVBhdGg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGtpbmQ6IFwic3VidHJlZVwiLFxuICAgICAgICAgICAgcGF0aCxcbiAgICAgICAgICAgIG5vZGUsXG4gICAgICAgICAgICBub2RlUGF0aCxcbiAgICAgICAgICAgIGV4dHJhczogY2FycmllZCxcbiAgICAgICAgICAgIHdlaWdodDogdGhpcy5jb25maWcuZ2V0V2VpZ2h0KG5vZGUuc3VtbWFyeSkgKyBjYXJyaWVkV2VpZ2h0LFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgYnVpbGRPdXRwdXRTdW1tYXJ5KGVudHJ5OiBQZW5kaW5nRW50cnk8Uz4pOiBTIHtcbiAgICAgICAgbGV0IHJlc3VsdCA9IHRoaXMuY29uZmlnLmNyZWF0ZVN1bW1hcnkoKTtcbiAgICAgICAgaWYgKGVudHJ5LmtpbmQgPT09IFwiZ3JvdXBcIiB8fCBlbnRyeS5raW5kID09PSBcInRydW5jYXRlZFwiKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBleHRyYSBvZiBlbnRyeS5leHRyYXMgfHwgW10pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5tZXJnZVN1bW1hcmllcyhyZXN1bHQsIGV4dHJhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlbnRyeS5tZW1iZXJzKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgbWVtYmVyIG9mIGVudHJ5Lm1lbWJlcnMudmFsdWVzKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWcubWVyZ2VTdW1tYXJpZXMocmVzdWx0LCBtZW1iZXIuc3VtbWFyeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgbm9kZSA9IGVudHJ5Lm5vZGU7XG4gICAgICAgIGlmICghbm9kZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFbnRyeSBtaXNzaW5nIG5vZGUgYXQgJHtlbnRyeS5wYXRofWApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlbnRyeS5raW5kID09PSBcInNlbGZcIikge1xuICAgICAgICAgICAgbGV0IHNlbGZTdW1tYXJ5ID0gbm9kZS5zZWxmU3VtbWFyeTtcbiAgICAgICAgICAgIGlmICghc2VsZlN1bW1hcnkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFNlbGYgZW50cnkgbWlzc2luZyBzZWxmU3VtbWFyeSBhdCAke2VudHJ5LnBhdGh9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5tZXJnZVN1bW1hcmllcyhyZXN1bHQsIHNlbGZTdW1tYXJ5KTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgZXh0cmEgb2YgZW50cnkuZXh0cmFzIHx8IFtdKSB7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5tZXJnZVN1bW1hcmllcyhyZXN1bHQsIGV4dHJhKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbmZpZy5tZXJnZVN1bW1hcmllcyhyZXN1bHQsIG5vZGUuc3VtbWFyeSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLy8gQ29sbGFwc2VzIHRoZSBsaWdodGVzdCBzdWJ0cmVlcyB1bnRpbCB0aGUgbm9kZSBjb3VudCBpcyBiYWNrIHVuZGVyIHRoZSB0YXJnZXQuIENvbGxhcHNpbmcgYSBub2RlIG1lcmdlcyBldmVyeXRoaW5nIGJlbG93IGl0IGludG8gaXRzIHRydW5jYXRlZFN1bW1hcnksIGtlZXBpbmcgdGhlIGRhdGEgYnV0IGRyb3BwaW5nIHRoZSBwYXRoIGRldGFpbC4gSWYgdGhvc2UgcHJlZml4ZXMgZ2V0IGhlYXZ5IGFnYWluIGxhdGVyLCBuZXcgYWRkcyByZWJ1aWxkIGJyYW5jaGVzIHRoZXJlIGFuZCB0aGUgbmV4dCBwcnVuZSB0YWtlcyBvdXQgd2hhdGV2ZXIgc3RheWVkIGxpZ2h0IGluc3RlYWQuXG4gICAgcHJpdmF0ZSBwcnVuZSgpIHtcbiAgICAgICAgbGV0IHRhcmdldCA9IE1hdGguZmxvb3IodGhpcy5tYXhUcmFja2VkTm9kZXMgLyBQUlVORV9UQVJHRVRfRElWSVNPUik7XG4gICAgICAgIGxldCBuZWVkID0gdGhpcy5ub2RlQ291bnQgLSB0YXJnZXQ7XG4gICAgICAgIGlmIChuZWVkIDw9IDApIHJldHVybjtcbiAgICAgICAgbGV0IHN0YXRzID0gbmV3IE1hcDxUcmVlTm9kZTxTPiwgTm9kZVN0YXRzPigpO1xuICAgICAgICBsZXQgbWVhc3VyZSA9IChub2RlOiBUcmVlTm9kZTxTPik6IE5vZGVTdGF0cyA9PiB7XG4gICAgICAgICAgICBsZXQgc2l6ZSA9IDE7XG4gICAgICAgICAgICBmb3IgKGxldCBjaGlsZCBvZiBub2RlLmNoaWxkcmVuLnZhbHVlcygpKSB7XG4gICAgICAgICAgICAgICAgc2l6ZSArPSBtZWFzdXJlKGNoaWxkKS5zaXplO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IHsgc2l6ZSwgd2VpZ2h0OiB0aGlzLmNvbmZpZy5nZXRXZWlnaHQobm9kZS5zdW1tYXJ5KSB9O1xuICAgICAgICAgICAgc3RhdHMuc2V0KG5vZGUsIHJlc3VsdCk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9O1xuICAgICAgICBsZXQgcm9vdFN0YXRzID0gbWVhc3VyZSh0aGlzLnJvb3QpO1xuICAgICAgICBsZXQgZ2V0U3RhdHMgPSAobm9kZTogVHJlZU5vZGU8Uz4pOiBOb2RlU3RhdHMgPT4ge1xuICAgICAgICAgICAgbGV0IHN0YXQgPSBzdGF0cy5nZXQobm9kZSk7XG4gICAgICAgICAgICBpZiAoIXN0YXQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE1pc3Npbmcgbm9kZSBzdGF0cyBkdXJpbmcgcHJ1bmVgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzdGF0O1xuICAgICAgICB9O1xuICAgICAgICAvLyBDb2xsYXBzaW5nIGV2ZXJ5IG1heGltYWwgc3VidHJlZSB3aG9zZSB3ZWlnaHQgaXMgdW5kZXIgYSBsaW1pdCBmcmVlcyBhIG1vbm90b25pY2FsbHkgaW5jcmVhc2luZyBudW1iZXIgb2Ygbm9kZXMsIHNvIGJpbmFyeSBzZWFyY2ggZm9yIHRoZSBzbWFsbGVzdCBsaW1pdCB0aGF0IGZyZWVzIGVub3VnaC5cbiAgICAgICAgbGV0IGZyZWVkQXQgPSAobGltaXQ6IG51bWJlcik6IG51bWJlciA9PiB7XG4gICAgICAgICAgICBsZXQgZnJlZWQgPSAwO1xuICAgICAgICAgICAgbGV0IHZpc2l0ID0gKG5vZGU6IFRyZWVOb2RlPFM+KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGUuY2hpbGRyZW4uc2l6ZSA9PT0gMCkgcmV0dXJuO1xuICAgICAgICAgICAgICAgIGlmIChnZXRTdGF0cyhub2RlKS53ZWlnaHQgPD0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgZnJlZWQgKz0gZ2V0U3RhdHMobm9kZSkuc2l6ZSAtIDE7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgY2hpbGQgb2Ygbm9kZS5jaGlsZHJlbi52YWx1ZXMoKSkge1xuICAgICAgICAgICAgICAgICAgICB2aXNpdChjaGlsZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZpc2l0KHRoaXMucm9vdCk7XG4gICAgICAgICAgICByZXR1cm4gZnJlZWQ7XG4gICAgICAgIH07XG4gICAgICAgIGxldCBsb3cgPSAwO1xuICAgICAgICBsZXQgaGlnaCA9IHJvb3RTdGF0cy53ZWlnaHQ7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgUFJVTkVfU0VBUkNIX0lURVJBVElPTlM7IGkrKykge1xuICAgICAgICAgICAgbGV0IG1pZCA9IChsb3cgKyBoaWdoKSAvIDI7XG4gICAgICAgICAgICBpZiAoZnJlZWRBdChtaWQpID49IG5lZWQpIHtcbiAgICAgICAgICAgICAgICBoaWdoID0gbWlkO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsb3cgPSBtaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGNvbGxhcHNlVmlzaXQgPSAobm9kZTogVHJlZU5vZGU8Uz4pID0+IHtcbiAgICAgICAgICAgIGlmIChub2RlLmNoaWxkcmVuLnNpemUgPT09IDApIHJldHVybjtcbiAgICAgICAgICAgIGlmIChnZXRTdGF0cyhub2RlKS53ZWlnaHQgPD0gaGlnaCkge1xuICAgICAgICAgICAgICAgIGxldCB0cnVuY2F0ZWQgPSBub2RlLnRydW5jYXRlZFN1bW1hcnk7XG4gICAgICAgICAgICAgICAgaWYgKCF0cnVuY2F0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ1bmNhdGVkID0gdGhpcy5jb25maWcuY3JlYXRlU3VtbWFyeSgpO1xuICAgICAgICAgICAgICAgICAgICBub2RlLnRydW5jYXRlZFN1bW1hcnkgPSB0cnVuY2F0ZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAobGV0IGNoaWxkIG9mIG5vZGUuY2hpbGRyZW4udmFsdWVzKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWcubWVyZ2VTdW1tYXJpZXModHJ1bmNhdGVkLCBjaGlsZC5zdW1tYXJ5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5ub2RlQ291bnQgLT0gZ2V0U3RhdHMobm9kZSkuc2l6ZSAtIDE7XG4gICAgICAgICAgICAgICAgbm9kZS5jaGlsZHJlbi5jbGVhcigpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGNoaWxkIG9mIG5vZGUuY2hpbGRyZW4udmFsdWVzKCkpIHtcbiAgICAgICAgICAgICAgICBjb2xsYXBzZVZpc2l0KGNoaWxkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29sbGFwc2VWaXNpdCh0aGlzLnJvb3QpO1xuICAgIH1cbn1cbiJdfQ==
359
+ /* _JS_SOURCE_HASH = "6cc23520550b8de75feb37a36bb0d33aeab003facda37ae7fc99887839e09cab"; */