@mnemonica/tactica 0.1.15 → 0.2.0

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.
@@ -0,0 +1,568 @@
1
+ 'use strict';
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.CreationGraphBuilder = void 0;
37
+ const path = __importStar(require("path"));
38
+ const ts = __importStar(require("typescript"));
39
+ /**
40
+ * Inside-out creation walker (instrumentation walker plan, Phase 3).
41
+ *
42
+ * Starts at the certain points — instantiation usages carrying a
43
+ * holderScopeId — then walks OUTWARD: who invokes or references the holder,
44
+ * crossing files through the module graph (barrels chased the same way
45
+ * ModuleGraphBuilder.resolveOrigin does), until no callers remain. Terminals
46
+ * are the starters (application entry points). The walk never assumes a
47
+ * linear Trie (decision 1: strictChain:false permits cycles/out-of-order
48
+ * construction), so traversal is cycle-guarded DFS, and every anchor records
49
+ * which constructor expression was actually used.
50
+ *
51
+ * Deliberate approximations (no getTypeChecker(), name-based only):
52
+ * - Namespace imports (`import * as ns`): when the namespace's source module
53
+ * exposes the holder's export, ANY reference to the alias counts as a
54
+ * caller reference.
55
+ * - Method scopes bind to their CLASS name (callers reference the class);
56
+ * instance-method call sites (`obj.method()`) are not distinguishable
57
+ * without the checker.
58
+ * - Any non-declaration identifier counts as a reference (invocations,
59
+ * pass-as-arg, rebinding); type-position references are not filtered.
60
+ * - Module scopes end the invocation walk, but a terminal module still
61
+ * gains its IMPORTERS as callers: entry modules hand classes to the
62
+ * framework as values (a bootstrap call receiving the root module),
63
+ * which no call-walk can see — the import relation bridges them to
64
+ * the center.
65
+ */
66
+ class CreationGraphBuilder {
67
+ constructor(moduleGraph, scopeAnalysis, scopeWalker, sourceFiles) {
68
+ /** filePath -> (identifier text -> reference locations), built lazily per file */
69
+ this.referencesByFile = new Map();
70
+ this.moduleGraph = moduleGraph;
71
+ this.scopeAnalysis = scopeAnalysis;
72
+ this.scopeWalker = scopeWalker;
73
+ this.sourceFiles = sourceFiles;
74
+ }
75
+ /**
76
+ * Build the creation graph from the analyzer's usages (holderScopeId
77
+ * already attached). Always returns a graph, empty arrays when nothing
78
+ * creates mnemonica instances.
79
+ */
80
+ build(usages) {
81
+ const anchors = this.collectAnchors(usages);
82
+ const nodes = new Map();
83
+ const edges = [];
84
+ const seenEdges = new Set();
85
+ // scopeIds with at least one caller — everyone else is a starter
86
+ const called = new Set();
87
+ const visited = new Set();
88
+ const work = anchors.map(anchor => anchor.holderScopeId);
89
+ const addEdge = (caller, callee) => {
90
+ const key = `${caller}\n${callee}`;
91
+ if (seenEdges.has(key)) {
92
+ return;
93
+ }
94
+ seenEdges.add(key);
95
+ edges.push({ caller, callee });
96
+ called.add(callee);
97
+ };
98
+ while (work.length > 0) {
99
+ const scopeId = work.pop();
100
+ if (!scopeId || visited.has(scopeId)) {
101
+ continue;
102
+ }
103
+ visited.add(scopeId);
104
+ const scope = this.scopeAnalysis.scopes.get(scopeId);
105
+ if (!scope) {
106
+ continue;
107
+ }
108
+ nodes.set(scopeId, CreationGraphBuilder.nodeOf(scope));
109
+ if (scope.kind === 'module') {
110
+ // Module scopes END the invocation walk — nobody invokes a
111
+ // module (a module-scope creation is labeled rooted on the
112
+ // anchor instead). But entry modules hand their classes to
113
+ // the framework as VALUES (a bootstrap call receiving the
114
+ // root module, or framework metadata listing controllers),
115
+ // invisible to
116
+ // call-walking — so a terminal module still gains its
117
+ // IMPORTERS as callers: main.ts importing AppModule yields
118
+ // the main.ts → app.module edge the pure call graph misses.
119
+ for (const importer of this.importersOf(scope.filePath)) {
120
+ addEdge(importer, scopeId);
121
+ if (!visited.has(importer)) {
122
+ work.push(importer);
123
+ }
124
+ }
125
+ continue;
126
+ }
127
+ const bindingName = CreationGraphBuilder.bindingNameOf(scope);
128
+ if (!bindingName) {
129
+ // Anonymous holder (file:line label): never referenced by name
130
+ continue;
131
+ }
132
+ // Plan-sketch refinement: same-file references are followed for
133
+ // EVERY holder, exported or not — an exported function can also be
134
+ // called from its own module, and both paths lead outward.
135
+ const sameFileCallers = this.callersOf(scope.filePath, bindingName);
136
+ const crossFileCallers = this.findCrossFileCallers(scope, bindingName);
137
+ for (const caller of [...sameFileCallers, ...crossFileCallers]) {
138
+ // Direct recursion (f calls f) adds no outward information
139
+ if (caller === scopeId) {
140
+ continue;
141
+ }
142
+ addEdge(caller, scopeId);
143
+ if (!visited.has(caller)) {
144
+ work.push(caller);
145
+ }
146
+ }
147
+ }
148
+ for (const node of nodes.values()) {
149
+ node.starter = !called.has(node.scopeId);
150
+ }
151
+ const result = {
152
+ nodes: Array.from(nodes.values()),
153
+ edges,
154
+ anchors,
155
+ };
156
+ return result;
157
+ }
158
+ /**
159
+ * One anchor per instantiation usage with a known holder scope.
160
+ */
161
+ collectAnchors(usages) {
162
+ const anchors = [];
163
+ for (const [typePath, usageList] of usages) {
164
+ for (const usage of usageList) {
165
+ if (usage.kind !== 'instantiation' || !usage.holderScopeId) {
166
+ continue;
167
+ }
168
+ const holderScope = this.scopeAnalysis.scopes.get(usage.holderScopeId);
169
+ if (!holderScope) {
170
+ continue;
171
+ }
172
+ const anchor = {
173
+ location: usage.location,
174
+ holderScopeId: usage.holderScopeId,
175
+ typePath,
176
+ };
177
+ if (usage.constructorText) {
178
+ anchor.constructorText = usage.constructorText;
179
+ }
180
+ if (holderScope.kind === 'module') {
181
+ // Plan: module-scope creation is a rooted instance —
182
+ // legitimate root or developer error; labeled, not policed
183
+ anchor.rooted = true;
184
+ }
185
+ const variable = this.matchAnchorVariable(usage, typePath, holderScope);
186
+ if (variable) {
187
+ anchor.variable = variable.name;
188
+ const [terminatedAt] = variable.reassignments;
189
+ if (terminatedAt) {
190
+ anchor.terminatedAt = terminatedAt;
191
+ }
192
+ }
193
+ anchors.push(anchor);
194
+ }
195
+ }
196
+ return anchors;
197
+ }
198
+ /**
199
+ * Same-line heuristic for the anchor's variable: the variable declared in
200
+ * the holder scope on the same line as the creation, whose typePath (when
201
+ * known) matches the created type.
202
+ */
203
+ matchAnchorVariable(usage, typePath, holderScope) {
204
+ const usageLine = CreationGraphBuilder.lineOf(usage.location);
205
+ if (usageLine === undefined) {
206
+ return undefined;
207
+ }
208
+ for (const variable of this.scopeAnalysis.variables.values()) {
209
+ if (variable.scopeId !== holderScope.scopeId) {
210
+ continue;
211
+ }
212
+ if (CreationGraphBuilder.lineOf(variable.declaration) !== usageLine) {
213
+ continue;
214
+ }
215
+ if (variable.typePath && variable.typePath !== typePath) {
216
+ continue;
217
+ }
218
+ return variable;
219
+ }
220
+ return undefined;
221
+ }
222
+ /**
223
+ * Parse the 1-based line out of a file.ts:Line:Col location string.
224
+ */
225
+ static lineOf(location) {
226
+ const lastColon = location.lastIndexOf(':');
227
+ const prevColon = location.lastIndexOf(':', lastColon - 1);
228
+ if (lastColon < 0 || prevColon < 0) {
229
+ return undefined;
230
+ }
231
+ const line = Number(location.slice(prevColon + 1, lastColon));
232
+ const result = Number.isFinite(line) ? line : undefined;
233
+ return result;
234
+ }
235
+ static nodeOf(scope) {
236
+ const node = {
237
+ scopeId: scope.scopeId,
238
+ name: scope.name,
239
+ kind: scope.kind,
240
+ filePath: scope.filePath,
241
+ location: scope.location,
242
+ starter: false,
243
+ };
244
+ return node;
245
+ }
246
+ /**
247
+ * The name a scope is reachable by: functions/arrows take their scope
248
+ * name; methods take their class (the part before '.') — that is what
249
+ * callers reference. Anonymous holders (file:line labels) and module
250
+ * scopes have no binding name.
251
+ */
252
+ static bindingNameOf(scope) {
253
+ if (scope.kind === 'module') {
254
+ return undefined;
255
+ }
256
+ // Anonymous label is `${filePath}:${line}` — a name can never contain '/'
257
+ if (scope.name.startsWith(`${scope.filePath}:`)) {
258
+ return undefined;
259
+ }
260
+ if (scope.kind === 'method') {
261
+ const dotIndex = scope.name.indexOf('.');
262
+ if (dotIndex < 0) {
263
+ // Method of an anonymous class — no binding name
264
+ return undefined;
265
+ }
266
+ const result = scope.name.slice(0, dotIndex);
267
+ return result;
268
+ }
269
+ return scope.name;
270
+ }
271
+ /**
272
+ * Scope ids referencing `bindingName` inside one file (invocations,
273
+ * pass-as-arg, rebindings — any non-declaration identifier).
274
+ */
275
+ callersOf(filePath, bindingName) {
276
+ const references = this.referencesIn(filePath, bindingName);
277
+ const callers = [];
278
+ for (const location of references) {
279
+ const callerScopeId = this.scopeWalker.findHolderScopeId(location);
280
+ if (callerScopeId) {
281
+ callers.push(callerScopeId);
282
+ }
283
+ }
284
+ return callers;
285
+ }
286
+ /**
287
+ * Callers in OTHER modules, followed through the module graph when the
288
+ * holder's binding is exported (the plan's "if f is exported" branch,
289
+ * including the barrel chase).
290
+ */
291
+ findCrossFileCallers(scope, bindingName) {
292
+ const holderModule = this.moduleGraph.modules.get(scope.filePath);
293
+ if (!holderModule) {
294
+ return [];
295
+ }
296
+ // The exported binding whose LOCAL name is the scope's binding name.
297
+ // Plain exports present under their own name; `export { X as Y }` and
298
+ // `export default X` carry the local name in importAlias.
299
+ const exported = holderModule.exportedBindings.find(binding => !binding.isReExport && (binding.importAlias ?? binding.name) === bindingName);
300
+ if (!exported) {
301
+ return [];
302
+ }
303
+ const callers = [];
304
+ for (const importer of this.moduleGraph.modules.values()) {
305
+ if (importer.filePath === scope.filePath) {
306
+ continue;
307
+ }
308
+ for (const imported of importer.importedBindings) {
309
+ // Re-exports create no local identifier to reference; external
310
+ // packages (node_modules) are never walked
311
+ if (imported.isReExport || imported.external) {
312
+ continue;
313
+ }
314
+ const localName = this.importReferencesHolder(imported, exported, scope.filePath);
315
+ if (!localName) {
316
+ continue;
317
+ }
318
+ const importerCallers = this.callersOf(importer.filePath, localName);
319
+ callers.push(...importerCallers);
320
+ }
321
+ }
322
+ return callers;
323
+ }
324
+ /**
325
+ * Modules importing bindings whose ORIGIN is `filePath` — the
326
+ * exports-and-usage bridge for terminal module scopes. Any binding kind
327
+ * counts (named, default, re-export): resolveImportOrigin chases barrels
328
+ * to the declaring module; namespace imports and external packages never
329
+ * resolve, so neither connects. Returned as module-scope scopeIds — a
330
+ * module's scopeId IS its resolved filePath.
331
+ */
332
+ importersOf(filePath) {
333
+ const importers = [];
334
+ for (const importer of this.moduleGraph.modules.values()) {
335
+ if (importer.filePath === filePath) {
336
+ continue;
337
+ }
338
+ const depends = importer.importedBindings.some(imported => {
339
+ const origin = this.resolveImportOrigin(imported);
340
+ const result = origin !== undefined && origin.module.filePath === filePath;
341
+ return result;
342
+ });
343
+ if (depends) {
344
+ importers.push(importer.filePath);
345
+ }
346
+ }
347
+ return importers;
348
+ }
349
+ /**
350
+ * The local identifier an import binding presents for reference search,
351
+ * when the binding resolves to the holder's export — undefined otherwise.
352
+ */
353
+ importReferencesHolder(imported, holderExport, holderFilePath) {
354
+ if (imported.importKind === 'namespace') {
355
+ // Namespace approximation: when the alias's source module exposes
356
+ // the holder's export, any reference to the alias counts
357
+ const exposes = this.namespaceExposes(imported.sourceModule, holderExport.name, holderFilePath);
358
+ const result = exposes ? imported.name : undefined;
359
+ return result;
360
+ }
361
+ const origin = this.resolveImportOrigin(imported);
362
+ if (!origin) {
363
+ return undefined;
364
+ }
365
+ if (origin.module.filePath !== holderFilePath || origin.binding.name !== holderExport.name) {
366
+ return undefined;
367
+ }
368
+ return imported.name;
369
+ }
370
+ /**
371
+ * True when a namespace import's source module exposes `exportedName`
372
+ * whose origin is the holder's module. Expressed as resolving a synthetic
373
+ * named binding, so star barrels and named re-exports are chased by the
374
+ * same machinery as plain imports.
375
+ */
376
+ namespaceExposes(sourceModule, exportedName, holderFilePath) {
377
+ const synthetic = {
378
+ name: exportedName,
379
+ kind: 'unknown',
380
+ sourceModule,
381
+ isReExport: true,
382
+ };
383
+ const origin = this.resolveImportOrigin(synthetic);
384
+ if (!origin) {
385
+ return false;
386
+ }
387
+ const result = origin.module.filePath === holderFilePath && origin.binding.name === exportedName;
388
+ return result;
389
+ }
390
+ /**
391
+ * Chase an import binding to the module that actually declares it,
392
+ * following re-export chains (barrels). Same shape as
393
+ * ModuleGraphBuilder.resolveOrigin, run here over the BUILT graph
394
+ * (sourceModule values are already resolved absolute paths).
395
+ * Cycle-guarded; undefined when the origin is external or the chain loops.
396
+ */
397
+ resolveImportOrigin(binding, visited = new Set()) {
398
+ const sourcePath = path.resolve(binding.sourceModule);
399
+ if (visited.has(sourcePath)) {
400
+ return undefined;
401
+ }
402
+ visited.add(sourcePath);
403
+ const sourceModuleInfo = this.moduleGraph.modules.get(sourcePath);
404
+ if (!sourceModuleInfo) {
405
+ return undefined;
406
+ }
407
+ // The name to look up in the source module's export list
408
+ const lookupKey = binding.importKind === 'default'
409
+ ? 'default'
410
+ : binding.importAlias ?? binding.name;
411
+ for (const exported of sourceModuleInfo.exportedBindings) {
412
+ if (exported.name !== lookupKey) {
413
+ continue;
414
+ }
415
+ if (!exported.isReExport) {
416
+ const result = { module: sourceModuleInfo, binding: exported };
417
+ return result;
418
+ }
419
+ const chased = this.resolveImportOrigin(exported, visited);
420
+ return chased;
421
+ }
422
+ // `export * from './y'` barrels: the name may live behind a star
423
+ for (const exported of sourceModuleInfo.exportedBindings) {
424
+ if (!exported.isReExport || exported.importKind !== 'namespace' || exported.name !== '*') {
425
+ continue;
426
+ }
427
+ const chased = this.resolveImportOrigin({
428
+ name: lookupKey,
429
+ kind: 'unknown',
430
+ sourceModule: exported.sourceModule,
431
+ isReExport: true,
432
+ }, visited);
433
+ if (chased) {
434
+ return chased;
435
+ }
436
+ }
437
+ return undefined;
438
+ }
439
+ /**
440
+ * All references to `name` in a file as location strings. The per-file
441
+ * index is built lazily in ONE pass (every identifier bucketed by text)
442
+ * and cached.
443
+ */
444
+ referencesIn(filePath, name) {
445
+ let byName = this.referencesByFile.get(filePath);
446
+ if (!byName) {
447
+ byName = new Map();
448
+ const sourceFile = this.sourceFiles.get(filePath);
449
+ if (sourceFile) {
450
+ CreationGraphBuilder.collectReferences(sourceFile, byName);
451
+ }
452
+ this.referencesByFile.set(filePath, byName);
453
+ }
454
+ const result = byName.get(name) ?? [];
455
+ return result;
456
+ }
457
+ /**
458
+ * Bucket every identifier reference by name. Declaration and wiring
459
+ * positions are NOT references: import/export specifiers, declaration
460
+ * names, property-access `.name`, and property-assignment keys go into a
461
+ * skip set of NODES — program files can be unbound, so parent-pointer
462
+ * checks are impossible (the scopes walker precedent, Phase 2).
463
+ * ShorthandPropertyAssignment names DO count: `{ foo }` is a genuine
464
+ * reference to foo.
465
+ */
466
+ static collectReferences(sourceFile, byName) {
467
+ const skip = new Set();
468
+ const filePath = path.resolve(sourceFile.fileName);
469
+ const visit = (node) => {
470
+ CreationGraphBuilder.registerSkips(node, skip);
471
+ if (ts.isIdentifier(node) && !skip.has(node)) {
472
+ const list = byName.get(node.text) ?? [];
473
+ if (list.length === 0) {
474
+ byName.set(node.text, list);
475
+ }
476
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
477
+ list.push(`${filePath}:${line + 1}:${character + 1}`);
478
+ }
479
+ ts.forEachChild(node, visit);
480
+ };
481
+ visit(sourceFile);
482
+ }
483
+ /**
484
+ * Register the identifier nodes that must NOT count as references when
485
+ * `node` is a wiring/declaration construct. Runs on the parent before
486
+ * descending, so the skip set is populated before the identifier nodes
487
+ * themselves are visited.
488
+ */
489
+ static registerSkips(node, skip) {
490
+ // import … from './x'
491
+ if (ts.isImportDeclaration(node)) {
492
+ const { importClause } = node;
493
+ if (!importClause) {
494
+ return;
495
+ }
496
+ if (importClause.name) {
497
+ skip.add(importClause.name);
498
+ }
499
+ const { namedBindings } = importClause;
500
+ if (namedBindings && ts.isNamedImports(namedBindings)) {
501
+ for (const element of namedBindings.elements) {
502
+ if (element.propertyName) {
503
+ skip.add(element.propertyName);
504
+ }
505
+ skip.add(element.name);
506
+ }
507
+ }
508
+ if (namedBindings && ts.isNamespaceImport(namedBindings)) {
509
+ skip.add(namedBindings.name);
510
+ }
511
+ return;
512
+ }
513
+ // import x = require('./y')
514
+ if (ts.isImportEqualsDeclaration(node)) {
515
+ skip.add(node.name);
516
+ return;
517
+ }
518
+ // export { X } [from './y'] / export * as ns from './y' — export wiring
519
+ // alone is not a caller; an importer's usage creates the edge instead
520
+ if (ts.isExportDeclaration(node)) {
521
+ const { exportClause } = node;
522
+ if (exportClause && ts.isNamedExports(exportClause)) {
523
+ for (const element of exportClause.elements) {
524
+ if (element.propertyName) {
525
+ skip.add(element.propertyName);
526
+ }
527
+ skip.add(element.name);
528
+ }
529
+ }
530
+ if (exportClause && ts.isNamespaceExport(exportClause)) {
531
+ skip.add(exportClause.name);
532
+ }
533
+ return;
534
+ }
535
+ // export default foo — same export-wiring rule
536
+ if (ts.isExportAssignment(node) && ts.isIdentifier(node.expression)) {
537
+ skip.add(node.expression);
538
+ return;
539
+ }
540
+ // obj.name — the `.name` part is property wiring, not a reference
541
+ if (ts.isPropertyAccessExpression(node)) {
542
+ skip.add(node.name);
543
+ return;
544
+ }
545
+ // { name: value } — the key is not a reference. Shorthand `{ name }`
546
+ // IS a reference: ShorthandPropertyAssignment never matches here.
547
+ if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) {
548
+ skip.add(node.name);
549
+ return;
550
+ }
551
+ if (ts.isShorthandPropertyAssignment(node)) {
552
+ return;
553
+ }
554
+ // { x: a } destructuring — `x` is property wiring (`a` is the declared
555
+ // name, skipped by the generic declaration branch below)
556
+ if (ts.isBindingElement(node) && node.propertyName && ts.isIdentifier(node.propertyName)) {
557
+ skip.add(node.propertyName);
558
+ }
559
+ // Declaration names: `function f`, `class C`, `const x`, parameters,
560
+ // methods, enum members… — being declared is not being referenced
561
+ const named = node;
562
+ if ('name' in node && named.name && ts.isIdentifier(named.name)) {
563
+ skip.add(named.name);
564
+ }
565
+ }
566
+ }
567
+ exports.CreationGraphBuilder = CreationGraphBuilder;
568
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRpb24tZ3JhcGguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY3JlYXRpb24tZ3JhcGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFYiwyQ0FBNkI7QUFDN0IsK0NBQWlDO0FBT2pDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBCRztBQUNILE1BQWEsb0JBQW9CO0lBU2hDLFlBQ0MsV0FBd0IsRUFDeEIsYUFBNEIsRUFDNUIsV0FBNkIsRUFDN0IsV0FBdUM7UUFQeEMsa0ZBQWtGO1FBQzFFLHFCQUFnQixHQUFHLElBQUksR0FBRyxFQUFpQyxDQUFDO1FBUW5FLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFDO1FBQ25DLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFFLE1BQWdDO1FBQ3RDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFNUMsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQTZCLENBQUM7UUFDbkQsTUFBTSxLQUFLLEdBQXdCLEVBQUUsQ0FBQztRQUN0QyxNQUFNLFNBQVMsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQ3BDLGlFQUFpRTtRQUNqRSxNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQ2pDLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDbEMsTUFBTSxJQUFJLEdBQWEsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUVuRSxNQUFNLE9BQU8sR0FBRyxDQUFDLE1BQWMsRUFBRSxNQUFjLEVBQVEsRUFBRTtZQUN4RCxNQUFNLEdBQUcsR0FBRyxHQUFHLE1BQU0sS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUNuQyxJQUFJLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDeEIsT0FBTztZQUNSLENBQUM7WUFDRCxTQUFTLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ25CLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUMvQixNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BCLENBQUMsQ0FBQztRQUVGLE9BQU8sSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN4QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDM0IsSUFBSSxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ3RDLFNBQVM7WUFDVixDQUFDO1lBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNyQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDckQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNaLFNBQVM7WUFDVixDQUFDO1lBQ0QsS0FBSyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsb0JBQW9CLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFFdkQsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO2dCQUM3QiwyREFBMkQ7Z0JBQzNELDJEQUEyRDtnQkFDM0QsMkRBQTJEO2dCQUMzRCwwREFBMEQ7Z0JBQzFELDJEQUEyRDtnQkFDM0QsZUFBZTtnQkFDZixzREFBc0Q7Z0JBQ3RELDJEQUEyRDtnQkFDM0QsNERBQTREO2dCQUM1RCxLQUFLLE1BQU0sUUFBUSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7b0JBQ3pELE9BQU8sQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7b0JBQzNCLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7d0JBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7b0JBQ3JCLENBQUM7Z0JBQ0YsQ0FBQztnQkFDRCxTQUFTO1lBQ1YsQ0FBQztZQUVELE1BQU0sV0FBVyxHQUFHLG9CQUFvQixDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM5RCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ2xCLCtEQUErRDtnQkFDL0QsU0FBUztZQUNWLENBQUM7WUFFRCxnRUFBZ0U7WUFDaEUsbUVBQW1FO1lBQ25FLDJEQUEyRDtZQUMzRCxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDcEUsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ3ZFLEtBQUssTUFBTSxNQUFNLElBQUksQ0FBRSxHQUFHLGVBQWUsRUFBRSxHQUFHLGdCQUFnQixDQUFFLEVBQUUsQ0FBQztnQkFDbEUsMkRBQTJEO2dCQUMzRCxJQUFJLE1BQU0sS0FBSyxPQUFPLEVBQUUsQ0FBQztvQkFDeEIsU0FBUztnQkFDVixDQUFDO2dCQUNELE9BQU8sQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBQ3pCLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7b0JBQzFCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ25CLENBQUM7WUFDRixDQUFDO1FBQ0YsQ0FBQztRQUVELEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDbkMsSUFBSSxDQUFDLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFDLENBQUM7UUFFRCxNQUFNLE1BQU0sR0FBa0I7WUFDN0IsS0FBSyxFQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2xDLEtBQUs7WUFDTCxPQUFPO1NBQ1AsQ0FBQztRQUNGLE9BQU8sTUFBTSxDQUFDO0lBQ2YsQ0FBQztJQUVEOztPQUVHO0lBQ0ssY0FBYyxDQUFFLE1BQWdDO1FBQ3ZELE1BQU0sT0FBTyxHQUFxQixFQUFFLENBQUM7UUFDckMsS0FBSyxNQUFNLENBQUUsUUFBUSxFQUFFLFNBQVMsQ0FBRSxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQzlDLEtBQUssTUFBTSxLQUFLLElBQUksU0FBUyxFQUFFLENBQUM7Z0JBQy9CLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxlQUFlLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxFQUFFLENBQUM7b0JBQzVELFNBQVM7Z0JBQ1YsQ0FBQztnQkFDRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUN2RSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7b0JBQ2xCLFNBQVM7Z0JBQ1YsQ0FBQztnQkFDRCxNQUFNLE1BQU0sR0FBbUI7b0JBQzlCLFFBQVEsRUFBUSxLQUFLLENBQUMsUUFBUTtvQkFDOUIsYUFBYSxFQUFHLEtBQUssQ0FBQyxhQUFhO29CQUNuQyxRQUFRO2lCQUNSLENBQUM7Z0JBQ0YsSUFBSSxLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7b0JBQzNCLE1BQU0sQ0FBQyxlQUFlLEdBQUcsS0FBSyxDQUFDLGVBQWUsQ0FBQztnQkFDaEQsQ0FBQztnQkFDRCxJQUFJLFdBQVcsQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7b0JBQ25DLHFEQUFxRDtvQkFDckQsMkRBQTJEO29CQUMzRCxNQUFNLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztnQkFDdEIsQ0FBQztnQkFDRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxXQUFXLENBQUMsQ0FBQztnQkFDeEUsSUFBSSxRQUFRLEVBQUUsQ0FBQztvQkFDZCxNQUFNLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUM7b0JBQ2hDLE1BQU0sQ0FBRSxZQUFZLENBQUUsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDO29CQUNoRCxJQUFJLFlBQVksRUFBRSxDQUFDO3dCQUNsQixNQUFNLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztvQkFDcEMsQ0FBQztnQkFDRixDQUFDO2dCQUNELE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEIsQ0FBQztRQUNGLENBQUM7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNoQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLG1CQUFtQixDQUMxQixLQUFnQixFQUNoQixRQUFnQixFQUNoQixXQUFzQjtRQUV0QixNQUFNLFNBQVMsR0FBRyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzlELElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzdCLE9BQU8sU0FBUyxDQUFDO1FBQ2xCLENBQUM7UUFDRCxLQUFLLE1BQU0sUUFBUSxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDOUQsSUFBSSxRQUFRLENBQUMsT0FBTyxLQUFLLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDOUMsU0FBUztZQUNWLENBQUM7WUFDRCxJQUFJLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ3JFLFNBQVM7WUFDVixDQUFDO1lBQ0QsSUFBSSxRQUFRLENBQUMsUUFBUSxJQUFJLFFBQVEsQ0FBQyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3pELFNBQVM7WUFDVixDQUFDO1lBQ0QsT0FBTyxRQUFRLENBQUM7UUFDakIsQ0FBQztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ2xCLENBQUM7SUFFRDs7T0FFRztJQUNLLE1BQU0sQ0FBQyxNQUFNLENBQUUsUUFBZ0I7UUFDdEMsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM1QyxNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxTQUFTLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDM0QsSUFBSSxTQUFTLEdBQUcsQ0FBQyxJQUFJLFNBQVMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNwQyxPQUFPLFNBQVMsQ0FBQztRQUNsQixDQUFDO1FBQ0QsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBQzlELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ3hELE9BQU8sTUFBTSxDQUFDO0lBQ2YsQ0FBQztJQUVPLE1BQU0sQ0FBQyxNQUFNLENBQUUsS0FBZ0I7UUFDdEMsTUFBTSxJQUFJLEdBQXNCO1lBQy9CLE9BQU8sRUFBSSxLQUFLLENBQUMsT0FBTztZQUN4QixJQUFJLEVBQU8sS0FBSyxDQUFDLElBQUk7WUFDckIsSUFBSSxFQUFPLEtBQUssQ0FBQyxJQUFJO1lBQ3JCLFFBQVEsRUFBRyxLQUFLLENBQUMsUUFBUTtZQUN6QixRQUFRLEVBQUcsS0FBSyxDQUFDLFFBQVE7WUFDekIsT0FBTyxFQUFJLEtBQUs7U0FDaEIsQ0FBQztRQUNGLE9BQU8sSUFBSSxDQUFDO0lBQ2IsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssTUFBTSxDQUFDLGFBQWEsQ0FBRSxLQUFnQjtRQUM3QyxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDN0IsT0FBTyxTQUFTLENBQUM7UUFDbEIsQ0FBQztRQUNELDBFQUEwRTtRQUMxRSxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsS0FBSyxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNqRCxPQUFPLFNBQVMsQ0FBQztRQUNsQixDQUFDO1FBQ0QsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzdCLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3pDLElBQUksUUFBUSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUNsQixpREFBaUQ7Z0JBQ2pELE9BQU8sU0FBUyxDQUFDO1lBQ2xCLENBQUM7WUFDRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDN0MsT0FBTyxNQUFNLENBQUM7UUFDZixDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDO0lBQ25CLENBQUM7SUFFRDs7O09BR0c7SUFDSyxTQUFTLENBQUUsUUFBZ0IsRUFBRSxXQUFtQjtRQUN2RCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUM1RCxNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7UUFDN0IsS0FBSyxNQUFNLFFBQVEsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNuQyxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ25FLElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ25CLE9BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDN0IsQ0FBQztRQUNGLENBQUM7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNoQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLG9CQUFvQixDQUFFLEtBQWdCLEVBQUUsV0FBbUI7UUFDbEUsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNsRSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDbkIsT0FBTyxFQUFFLENBQUM7UUFDWCxDQUFDO1FBQ0QscUVBQXFFO1FBQ3JFLHNFQUFzRTtRQUN0RSwwREFBMEQ7UUFDMUQsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUM3RCxDQUFDLE9BQU8sQ0FBQyxVQUFVLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxXQUFXLENBQUMsQ0FBQztRQUMvRSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDZixPQUFPLEVBQUUsQ0FBQztRQUNYLENBQUM7UUFFRCxNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7UUFDN0IsS0FBSyxNQUFNLFFBQVEsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQzFELElBQUksUUFBUSxDQUFDLFFBQVEsS0FBSyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQzFDLFNBQVM7WUFDVixDQUFDO1lBQ0QsS0FBSyxNQUFNLFFBQVEsSUFBSSxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDbEQsK0RBQStEO2dCQUMvRCwyQ0FBMkM7Z0JBQzNDLElBQUksUUFBUSxDQUFDLFVBQVUsSUFBSSxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7b0JBQzlDLFNBQVM7Z0JBQ1YsQ0FBQztnQkFDRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMsUUFBUSxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ2xGLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztvQkFDaEIsU0FBUztnQkFDVixDQUFDO2dCQUNELE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQztnQkFDckUsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLGVBQWUsQ0FBQyxDQUFDO1lBQ2xDLENBQUM7UUFDRixDQUFDO1FBQ0QsT0FBTyxPQUFPLENBQUM7SUFDaEIsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSyxXQUFXLENBQUUsUUFBZ0I7UUFDcEMsTUFBTSxTQUFTLEdBQWEsRUFBRSxDQUFDO1FBQy9CLEtBQUssTUFBTSxRQUFRLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUMxRCxJQUFJLFFBQVEsQ0FBQyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3BDLFNBQVM7WUFDVixDQUFDO1lBQ0QsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRTtnQkFDekQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNsRCxNQUFNLE1BQU0sR0FBRyxNQUFNLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQztnQkFDM0UsT0FBTyxNQUFNLENBQUM7WUFDZixDQUFDLENBQUMsQ0FBQztZQUNILElBQUksT0FBTyxFQUFFLENBQUM7Z0JBQ2IsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDbkMsQ0FBQztRQUNGLENBQUM7UUFDRCxPQUFPLFNBQVMsQ0FBQztJQUNsQixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssc0JBQXNCLENBQzdCLFFBQXVCLEVBQ3ZCLFlBQTJCLEVBQzNCLGNBQXNCO1FBRXRCLElBQUksUUFBUSxDQUFDLFVBQVUsS0FBSyxXQUFXLEVBQUUsQ0FBQztZQUN6QyxrRUFBa0U7WUFDbEUseURBQXlEO1lBQ3pELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxJQUFJLEVBQUUsY0FBYyxDQUFDLENBQUM7WUFDaEcsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7WUFDbkQsT0FBTyxNQUFNLENBQUM7UUFDZixDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2xELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNiLE9BQU8sU0FBUyxDQUFDO1FBQ2xCLENBQUM7UUFDRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxLQUFLLGNBQWMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDNUYsT0FBTyxTQUFTLENBQUM7UUFDbEIsQ0FBQztRQUNELE9BQU8sUUFBUSxDQUFDLElBQUksQ0FBQztJQUN0QixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxnQkFBZ0IsQ0FBRSxZQUFvQixFQUFFLFlBQW9CLEVBQUUsY0FBc0I7UUFDM0YsTUFBTSxTQUFTLEdBQWtCO1lBQ2hDLElBQUksRUFBUyxZQUFZO1lBQ3pCLElBQUksRUFBUyxTQUFTO1lBQ3RCLFlBQVk7WUFDWixVQUFVLEVBQUcsSUFBSTtTQUNqQixDQUFDO1FBQ0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNiLE9BQU8sS0FBSyxDQUFDO1FBQ2QsQ0FBQztRQUNELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxLQUFLLGNBQWMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxZQUFZLENBQUM7UUFDakcsT0FBTyxNQUFNLENBQUM7SUFDZixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ssbUJBQW1CLENBQzFCLE9BQXNCLEVBQ3RCLFVBQVUsSUFBSSxHQUFHLEVBQVU7UUFFM0IsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEQsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDN0IsT0FBTyxTQUFTLENBQUM7UUFDbEIsQ0FBQztRQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFeEIsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDbEUsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDdkIsT0FBTyxTQUFTLENBQUM7UUFDbEIsQ0FBQztRQUVELHlEQUF5RDtRQUN6RCxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsVUFBVSxLQUFLLFNBQVM7WUFDakQsQ0FBQyxDQUFDLFNBQVM7WUFDWCxDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDO1FBRXZDLEtBQUssTUFBTSxRQUFRLElBQUksZ0JBQWdCLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMxRCxJQUFJLFFBQVEsQ0FBQyxJQUFJLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ2pDLFNBQVM7WUFDVixDQUFDO1lBQ0QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDMUIsTUFBTSxNQUFNLEdBQUcsRUFBRSxNQUFNLEVBQUcsZ0JBQWdCLEVBQUUsT0FBTyxFQUFHLFFBQVEsRUFBRSxDQUFDO2dCQUNqRSxPQUFPLE1BQU0sQ0FBQztZQUNmLENBQUM7WUFDRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQzNELE9BQU8sTUFBTSxDQUFDO1FBQ2YsQ0FBQztRQUVELGlFQUFpRTtRQUNqRSxLQUFLLE1BQU0sUUFBUSxJQUFJLGdCQUFnQixDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDMUQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLElBQUksUUFBUSxDQUFDLFVBQVUsS0FBSyxXQUFXLElBQUksUUFBUSxDQUFDLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQztnQkFDMUYsU0FBUztZQUNWLENBQUM7WUFDRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUM7Z0JBQ3ZDLElBQUksRUFBVyxTQUFTO2dCQUN4QixJQUFJLEVBQVcsU0FBUztnQkFDeEIsWUFBWSxFQUFHLFFBQVEsQ0FBQyxZQUFZO2dCQUNwQyxVQUFVLEVBQUssSUFBSTthQUNuQixFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ1osSUFBSSxNQUFNLEVBQUUsQ0FBQztnQkFDWixPQUFPLE1BQU0sQ0FBQztZQUNmLENBQUM7UUFDRixDQUFDO1FBRUQsT0FBTyxTQUFTLENBQUM7SUFDbEIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxZQUFZLENBQUUsUUFBZ0IsRUFBRSxJQUFZO1FBQ25ELElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2IsTUFBTSxHQUFHLElBQUksR0FBRyxFQUFvQixDQUFDO1lBQ3JDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2xELElBQUksVUFBVSxFQUFFLENBQUM7Z0JBQ2hCLG9CQUFvQixDQUFDLGlCQUFpQixDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUM1RCxDQUFDO1lBQ0QsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDN0MsQ0FBQztRQUNELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3RDLE9BQU8sTUFBTSxDQUFDO0lBQ2YsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0ssTUFBTSxDQUFDLGlCQUFpQixDQUFFLFVBQXlCLEVBQUUsTUFBNkI7UUFDekYsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQVcsQ0FBQztRQUNoQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVuRCxNQUFNLEtBQUssR0FBRyxDQUFDLElBQWEsRUFBUSxFQUFFO1lBQ3JDLG9CQUFvQixDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDL0MsSUFBSSxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUM5QyxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ3pDLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDdkIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUM3QixDQUFDO2dCQUNELE1BQU0sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEdBQUcsVUFBVSxDQUFDLDZCQUE2QixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztnQkFDaEcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLFFBQVEsSUFBSSxJQUFJLEdBQUcsQ0FBQyxJQUFJLFNBQVMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZELENBQUM7WUFDRCxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztRQUM5QixDQUFDLENBQUM7UUFDRixLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssTUFBTSxDQUFDLGFBQWEsQ0FBRSxJQUFhLEVBQUUsSUFBa0I7UUFDOUQsc0JBQXNCO1FBQ3RCLElBQUksRUFBRSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDbEMsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLElBQUksQ0FBQztZQUM5QixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ25CLE9BQU87WUFDUixDQUFDO1lBQ0QsSUFBSSxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ3ZCLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzdCLENBQUM7WUFDRCxNQUFNLEVBQUUsYUFBYSxFQUFFLEdBQUcsWUFBWSxDQUFDO1lBQ3ZDLElBQUksYUFBYSxJQUFJLEVBQUUsQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztnQkFDdkQsS0FBSyxNQUFNLE9BQU8sSUFBSSxhQUFhLENBQUMsUUFBUSxFQUFFLENBQUM7b0JBQzlDLElBQUksT0FBTyxDQUFDLFlBQVksRUFBRSxDQUFDO3dCQUMxQixJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztvQkFDaEMsQ0FBQztvQkFDRCxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDeEIsQ0FBQztZQUNGLENBQUM7WUFDRCxJQUFJLGFBQWEsSUFBSSxFQUFFLENBQUMsaUJBQWlCLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztnQkFDMUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUIsQ0FBQztZQUNELE9BQU87UUFDUixDQUFDO1FBQ0QsNEJBQTRCO1FBQzVCLElBQUksRUFBRSxDQUFDLHlCQUF5QixDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDeEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDcEIsT0FBTztRQUNSLENBQUM7UUFDRCx3RUFBd0U7UUFDeEUsc0VBQXNFO1FBQ3RFLElBQUksRUFBRSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDbEMsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLElBQUksQ0FBQztZQUM5QixJQUFJLFlBQVksSUFBSSxFQUFFLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7Z0JBQ3JELEtBQUssTUFBTSxPQUFPLElBQUksWUFBWSxDQUFDLFFBQVEsRUFBRSxDQUFDO29CQUM3QyxJQUFJLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQzt3QkFDMUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7b0JBQ2hDLENBQUM7b0JBQ0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3hCLENBQUM7WUFDRixDQUFDO1lBQ0QsSUFBSSxZQUFZLElBQUksRUFBRSxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7Z0JBQ3hELElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzdCLENBQUM7WUFDRCxPQUFPO1FBQ1IsQ0FBQztRQUNELCtDQUErQztRQUMvQyxJQUFJLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ3JFLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQzFCLE9BQU87UUFDUixDQUFDO1FBQ0Qsa0VBQWtFO1FBQ2xFLElBQUksRUFBRSxDQUFDLDBCQUEwQixDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDekMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDcEIsT0FBTztRQUNSLENBQUM7UUFDRCxxRUFBcUU7UUFDckUsa0VBQWtFO1FBQ2xFLElBQUksRUFBRSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDakUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDcEIsT0FBTztRQUNSLENBQUM7UUFDRCxJQUFJLEVBQUUsQ0FBQyw2QkFBNkIsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQzVDLE9BQU87UUFDUixDQUFDO1FBQ0QsdUVBQXVFO1FBQ3ZFLHlEQUF5RDtRQUN6RCxJQUFJLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7WUFDMUYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDN0IsQ0FBQztRQUNELHFFQUFxRTtRQUNyRSxrRUFBa0U7UUFDbEUsTUFBTSxLQUFLLEdBQUcsSUFBMkIsQ0FBQztRQUMxQyxJQUFJLE1BQU0sSUFBSSxJQUFJLElBQUksS0FBSyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ2pFLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3RCLENBQUM7SUFDRixDQUFDO0NBQ0Q7QUF6aUJELG9EQXlpQkMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyB0cyBmcm9tICd0eXBlc2NyaXB0JztcbmltcG9ydCB7IExvY2FsU2NvcGVXYWxrZXIgfSBmcm9tICcuL3Njb3Blcyc7XG5pbXBvcnQge1xuXHRDcmVhdGlvbkFuY2hvciwgQ3JlYXRpb25HcmFwaCwgQ3JlYXRpb25HcmFwaEVkZ2UsIENyZWF0aW9uR3JhcGhOb2RlLCBNb2R1bGVCaW5kaW5nLCBNb2R1bGVHcmFwaCwgTW9kdWxlSW5mbyxcblx0U2NvcGVBbmFseXNpcywgU2NvcGVJbmZvLCBTY29wZVZhcmlhYmxlLCBVc2FnZUluZm9cbn0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogSW5zaWRlLW91dCBjcmVhdGlvbiB3YWxrZXIgKGluc3RydW1lbnRhdGlvbiB3YWxrZXIgcGxhbiwgUGhhc2UgMykuXG4gKlxuICogU3RhcnRzIGF0IHRoZSBjZXJ0YWluIHBvaW50cyDigJQgaW5zdGFudGlhdGlvbiB1c2FnZXMgY2FycnlpbmcgYVxuICogaG9sZGVyU2NvcGVJZCDigJQgdGhlbiB3YWxrcyBPVVRXQVJEOiB3aG8gaW52b2tlcyBvciByZWZlcmVuY2VzIHRoZSBob2xkZXIsXG4gKiBjcm9zc2luZyBmaWxlcyB0aHJvdWdoIHRoZSBtb2R1bGUgZ3JhcGggKGJhcnJlbHMgY2hhc2VkIHRoZSBzYW1lIHdheVxuICogTW9kdWxlR3JhcGhCdWlsZGVyLnJlc29sdmVPcmlnaW4gZG9lcyksIHVudGlsIG5vIGNhbGxlcnMgcmVtYWluLiBUZXJtaW5hbHNcbiAqIGFyZSB0aGUgc3RhcnRlcnMgKGFwcGxpY2F0aW9uIGVudHJ5IHBvaW50cykuIFRoZSB3YWxrIG5ldmVyIGFzc3VtZXMgYVxuICogbGluZWFyIFRyaWUgKGRlY2lzaW9uIDE6IHN0cmljdENoYWluOmZhbHNlIHBlcm1pdHMgY3ljbGVzL291dC1vZi1vcmRlclxuICogY29uc3RydWN0aW9uKSwgc28gdHJhdmVyc2FsIGlzIGN5Y2xlLWd1YXJkZWQgREZTLCBhbmQgZXZlcnkgYW5jaG9yIHJlY29yZHNcbiAqIHdoaWNoIGNvbnN0cnVjdG9yIGV4cHJlc3Npb24gd2FzIGFjdHVhbGx5IHVzZWQuXG4gKlxuICogRGVsaWJlcmF0ZSBhcHByb3hpbWF0aW9ucyAobm8gZ2V0VHlwZUNoZWNrZXIoKSwgbmFtZS1iYXNlZCBvbmx5KTpcbiAqIC0gTmFtZXNwYWNlIGltcG9ydHMgKGBpbXBvcnQgKiBhcyBuc2ApOiB3aGVuIHRoZSBuYW1lc3BhY2UncyBzb3VyY2UgbW9kdWxlXG4gKiAgIGV4cG9zZXMgdGhlIGhvbGRlcidzIGV4cG9ydCwgQU5ZIHJlZmVyZW5jZSB0byB0aGUgYWxpYXMgY291bnRzIGFzIGFcbiAqICAgY2FsbGVyIHJlZmVyZW5jZS5cbiAqIC0gTWV0aG9kIHNjb3BlcyBiaW5kIHRvIHRoZWlyIENMQVNTIG5hbWUgKGNhbGxlcnMgcmVmZXJlbmNlIHRoZSBjbGFzcyk7XG4gKiAgIGluc3RhbmNlLW1ldGhvZCBjYWxsIHNpdGVzIChgb2JqLm1ldGhvZCgpYCkgYXJlIG5vdCBkaXN0aW5ndWlzaGFibGVcbiAqICAgd2l0aG91dCB0aGUgY2hlY2tlci5cbiAqIC0gQW55IG5vbi1kZWNsYXJhdGlvbiBpZGVudGlmaWVyIGNvdW50cyBhcyBhIHJlZmVyZW5jZSAoaW52b2NhdGlvbnMsXG4gKiAgIHBhc3MtYXMtYXJnLCByZWJpbmRpbmcpOyB0eXBlLXBvc2l0aW9uIHJlZmVyZW5jZXMgYXJlIG5vdCBmaWx0ZXJlZC5cbiAqIC0gTW9kdWxlIHNjb3BlcyBlbmQgdGhlIGludm9jYXRpb24gd2FsaywgYnV0IGEgdGVybWluYWwgbW9kdWxlIHN0aWxsXG4gKiAgIGdhaW5zIGl0cyBJTVBPUlRFUlMgYXMgY2FsbGVyczogZW50cnkgbW9kdWxlcyBoYW5kIGNsYXNzZXMgdG8gdGhlXG4gKiAgIGZyYW1ld29yayBhcyB2YWx1ZXMgKGEgYm9vdHN0cmFwIGNhbGwgcmVjZWl2aW5nIHRoZSByb290IG1vZHVsZSksXG4gKiAgIHdoaWNoIG5vIGNhbGwtd2FsayBjYW4gc2VlIOKAlCB0aGUgaW1wb3J0IHJlbGF0aW9uIGJyaWRnZXMgdGhlbSB0b1xuICogICB0aGUgY2VudGVyLlxuICovXG5leHBvcnQgY2xhc3MgQ3JlYXRpb25HcmFwaEJ1aWxkZXIge1xuXHRwcml2YXRlIG1vZHVsZUdyYXBoOiBNb2R1bGVHcmFwaDtcblx0cHJpdmF0ZSBzY29wZUFuYWx5c2lzOiBTY29wZUFuYWx5c2lzO1xuXHRwcml2YXRlIHNjb3BlV2Fsa2VyOiBMb2NhbFNjb3BlV2Fsa2VyO1xuXHQvKiogS2V5ZWQgYnkgcGF0aC5yZXNvbHZlKHNvdXJjZUZpbGUuZmlsZU5hbWUpLCBtYXRjaGluZyBzY29wZUlkcyAqL1xuXHRwcml2YXRlIHNvdXJjZUZpbGVzOiBNYXA8c3RyaW5nLCB0cy5Tb3VyY2VGaWxlPjtcblx0LyoqIGZpbGVQYXRoIC0+IChpZGVudGlmaWVyIHRleHQgLT4gcmVmZXJlbmNlIGxvY2F0aW9ucyksIGJ1aWx0IGxhemlseSBwZXIgZmlsZSAqL1xuXHRwcml2YXRlIHJlZmVyZW5jZXNCeUZpbGUgPSBuZXcgTWFwPHN0cmluZywgTWFwPHN0cmluZywgc3RyaW5nW10+PigpO1xuXG5cdGNvbnN0cnVjdG9yIChcblx0XHRtb2R1bGVHcmFwaDogTW9kdWxlR3JhcGgsXG5cdFx0c2NvcGVBbmFseXNpczogU2NvcGVBbmFseXNpcyxcblx0XHRzY29wZVdhbGtlcjogTG9jYWxTY29wZVdhbGtlcixcblx0XHRzb3VyY2VGaWxlczogTWFwPHN0cmluZywgdHMuU291cmNlRmlsZT5cblx0KSB7XG5cdFx0dGhpcy5tb2R1bGVHcmFwaCA9IG1vZHVsZUdyYXBoO1xuXHRcdHRoaXMuc2NvcGVBbmFseXNpcyA9IHNjb3BlQW5hbHlzaXM7XG5cdFx0dGhpcy5zY29wZVdhbGtlciA9IHNjb3BlV2Fsa2VyO1xuXHRcdHRoaXMuc291cmNlRmlsZXMgPSBzb3VyY2VGaWxlcztcblx0fVxuXG5cdC8qKlxuXHQgKiBCdWlsZCB0aGUgY3JlYXRpb24gZ3JhcGggZnJvbSB0aGUgYW5hbHl6ZXIncyB1c2FnZXMgKGhvbGRlclNjb3BlSWRcblx0ICogYWxyZWFkeSBhdHRhY2hlZCkuIEFsd2F5cyByZXR1cm5zIGEgZ3JhcGgsIGVtcHR5IGFycmF5cyB3aGVuIG5vdGhpbmdcblx0ICogY3JlYXRlcyBtbmVtb25pY2EgaW5zdGFuY2VzLlxuXHQgKi9cblx0YnVpbGQgKHVzYWdlczogTWFwPHN0cmluZywgVXNhZ2VJbmZvW10+KTogQ3JlYXRpb25HcmFwaCB7XG5cdFx0Y29uc3QgYW5jaG9ycyA9IHRoaXMuY29sbGVjdEFuY2hvcnModXNhZ2VzKTtcblxuXHRcdGNvbnN0IG5vZGVzID0gbmV3IE1hcDxzdHJpbmcsIENyZWF0aW9uR3JhcGhOb2RlPigpO1xuXHRcdGNvbnN0IGVkZ2VzOiBDcmVhdGlvbkdyYXBoRWRnZVtdID0gW107XG5cdFx0Y29uc3Qgc2VlbkVkZ2VzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cdFx0Ly8gc2NvcGVJZHMgd2l0aCBhdCBsZWFzdCBvbmUgY2FsbGVyIOKAlCBldmVyeW9uZSBlbHNlIGlzIGEgc3RhcnRlclxuXHRcdGNvbnN0IGNhbGxlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXHRcdGNvbnN0IHZpc2l0ZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcblx0XHRjb25zdCB3b3JrOiBzdHJpbmdbXSA9IGFuY2hvcnMubWFwKGFuY2hvciA9PiBhbmNob3IuaG9sZGVyU2NvcGVJZCk7XG5cblx0XHRjb25zdCBhZGRFZGdlID0gKGNhbGxlcjogc3RyaW5nLCBjYWxsZWU6IHN0cmluZyk6IHZvaWQgPT4ge1xuXHRcdFx0Y29uc3Qga2V5ID0gYCR7Y2FsbGVyfVxcbiR7Y2FsbGVlfWA7XG5cdFx0XHRpZiAoc2VlbkVkZ2VzLmhhcyhrZXkpKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHNlZW5FZGdlcy5hZGQoa2V5KTtcblx0XHRcdGVkZ2VzLnB1c2goeyBjYWxsZXIsIGNhbGxlZSB9KTtcblx0XHRcdGNhbGxlZC5hZGQoY2FsbGVlKTtcblx0XHR9O1xuXG5cdFx0d2hpbGUgKHdvcmsubGVuZ3RoID4gMCkge1xuXHRcdFx0Y29uc3Qgc2NvcGVJZCA9IHdvcmsucG9wKCk7XG5cdFx0XHRpZiAoIXNjb3BlSWQgfHwgdmlzaXRlZC5oYXMoc2NvcGVJZCkpIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHR2aXNpdGVkLmFkZChzY29wZUlkKTtcblx0XHRcdGNvbnN0IHNjb3BlID0gdGhpcy5zY29wZUFuYWx5c2lzLnNjb3Blcy5nZXQoc2NvcGVJZCk7XG5cdFx0XHRpZiAoIXNjb3BlKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0bm9kZXMuc2V0KHNjb3BlSWQsIENyZWF0aW9uR3JhcGhCdWlsZGVyLm5vZGVPZihzY29wZSkpO1xuXG5cdFx0XHRpZiAoc2NvcGUua2luZCA9PT0gJ21vZHVsZScpIHtcblx0XHRcdFx0Ly8gTW9kdWxlIHNjb3BlcyBFTkQgdGhlIGludm9jYXRpb24gd2FsayDigJQgbm9ib2R5IGludm9rZXMgYVxuXHRcdFx0XHQvLyBtb2R1bGUgKGEgbW9kdWxlLXNjb3BlIGNyZWF0aW9uIGlzIGxhYmVsZWQgcm9vdGVkIG9uIHRoZVxuXHRcdFx0XHQvLyBhbmNob3IgaW5zdGVhZCkuIEJ1dCBlbnRyeSBtb2R1bGVzIGhhbmQgdGhlaXIgY2xhc3NlcyB0b1xuXHRcdFx0XHQvLyB0aGUgZnJhbWV3b3JrIGFzIFZBTFVFUyAoYSBib290c3RyYXAgY2FsbCByZWNlaXZpbmcgdGhlXG5cdFx0XHRcdC8vIHJvb3QgbW9kdWxlLCBvciBmcmFtZXdvcmsgbWV0YWRhdGEgbGlzdGluZyBjb250cm9sbGVycyksXG5cdFx0XHRcdC8vIGludmlzaWJsZSB0b1xuXHRcdFx0XHQvLyBjYWxsLXdhbGtpbmcg4oCUIHNvIGEgdGVybWluYWwgbW9kdWxlIHN0aWxsIGdhaW5zIGl0c1xuXHRcdFx0XHQvLyBJTVBPUlRFUlMgYXMgY2FsbGVyczogbWFpbi50cyBpbXBvcnRpbmcgQXBwTW9kdWxlIHlpZWxkc1xuXHRcdFx0XHQvLyB0aGUgbWFpbi50cyDihpIgYXBwLm1vZHVsZSBlZGdlIHRoZSBwdXJlIGNhbGwgZ3JhcGggbWlzc2VzLlxuXHRcdFx0XHRmb3IgKGNvbnN0IGltcG9ydGVyIG9mIHRoaXMuaW1wb3J0ZXJzT2Yoc2NvcGUuZmlsZVBhdGgpKSB7XG5cdFx0XHRcdFx0YWRkRWRnZShpbXBvcnRlciwgc2NvcGVJZCk7XG5cdFx0XHRcdFx0aWYgKCF2aXNpdGVkLmhhcyhpbXBvcnRlcikpIHtcblx0XHRcdFx0XHRcdHdvcmsucHVzaChpbXBvcnRlcik7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCBiaW5kaW5nTmFtZSA9IENyZWF0aW9uR3JhcGhCdWlsZGVyLmJpbmRpbmdOYW1lT2Yoc2NvcGUpO1xuXHRcdFx0aWYgKCFiaW5kaW5nTmFtZSkge1xuXHRcdFx0XHQvLyBBbm9ueW1vdXMgaG9sZGVyIChmaWxlOmxpbmUgbGFiZWwpOiBuZXZlciByZWZlcmVuY2VkIGJ5IG5hbWVcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFBsYW4tc2tldGNoIHJlZmluZW1lbnQ6IHNhbWUtZmlsZSByZWZlcmVuY2VzIGFyZSBmb2xsb3dlZCBmb3Jcblx0XHRcdC8vIEVWRVJZIGhvbGRlciwgZXhwb3J0ZWQgb3Igbm90IOKAlCBhbiBleHBvcnRlZCBmdW5jdGlvbiBjYW4gYWxzbyBiZVxuXHRcdFx0Ly8gY2FsbGVkIGZyb20gaXRzIG93biBtb2R1bGUsIGFuZCBib3RoIHBhdGhzIGxlYWQgb3V0d2FyZC5cblx0XHRcdGNvbnN0IHNhbWVGaWxlQ2FsbGVycyA9IHRoaXMuY2FsbGVyc09mKHNjb3BlLmZpbGVQYXRoLCBiaW5kaW5nTmFtZSk7XG5cdFx0XHRjb25zdCBjcm9zc0ZpbGVDYWxsZXJzID0gdGhpcy5maW5kQ3Jvc3NGaWxlQ2FsbGVycyhzY29wZSwgYmluZGluZ05hbWUpO1xuXHRcdFx0Zm9yIChjb25zdCBjYWxsZXIgb2YgWyAuLi5zYW1lRmlsZUNhbGxlcnMsIC4uLmNyb3NzRmlsZUNhbGxlcnMgXSkge1xuXHRcdFx0XHQvLyBEaXJlY3QgcmVjdXJzaW9uIChmIGNhbGxzIGYpIGFkZHMgbm8gb3V0d2FyZCBpbmZvcm1hdGlvblxuXHRcdFx0XHRpZiAoY2FsbGVyID09PSBzY29wZUlkKSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0YWRkRWRnZShjYWxsZXIsIHNjb3BlSWQpO1xuXHRcdFx0XHRpZiAoIXZpc2l0ZWQuaGFzKGNhbGxlcikpIHtcblx0XHRcdFx0XHR3b3JrLnB1c2goY2FsbGVyKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGZvciAoY29uc3Qgbm9kZSBvZiBub2Rlcy52YWx1ZXMoKSkge1xuXHRcdFx0bm9kZS5zdGFydGVyID0gIWNhbGxlZC5oYXMobm9kZS5zY29wZUlkKTtcblx0XHR9XG5cblx0XHRjb25zdCByZXN1bHQ6IENyZWF0aW9uR3JhcGggPSB7XG5cdFx0XHRub2RlcyA6IEFycmF5LmZyb20obm9kZXMudmFsdWVzKCkpLFxuXHRcdFx0ZWRnZXMsXG5cdFx0XHRhbmNob3JzLFxuXHRcdH07XG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fVxuXG5cdC8qKlxuXHQgKiBPbmUgYW5jaG9yIHBlciBpbnN0YW50aWF0aW9uIHVzYWdlIHdpdGggYSBrbm93biBob2xkZXIgc2NvcGUuXG5cdCAqL1xuXHRwcml2YXRlIGNvbGxlY3RBbmNob3JzICh1c2FnZXM6IE1hcDxzdHJpbmcsIFVzYWdlSW5mb1tdPik6IENyZWF0aW9uQW5jaG9yW10ge1xuXHRcdGNvbnN0IGFuY2hvcnM6IENyZWF0aW9uQW5jaG9yW10gPSBbXTtcblx0XHRmb3IgKGNvbnN0IFsgdHlwZVBhdGgsIHVzYWdlTGlzdCBdIG9mIHVzYWdlcykge1xuXHRcdFx0Zm9yIChjb25zdCB1c2FnZSBvZiB1c2FnZUxpc3QpIHtcblx0XHRcdFx0aWYgKHVzYWdlLmtpbmQgIT09ICdpbnN0YW50aWF0aW9uJyB8fCAhdXNhZ2UuaG9sZGVyU2NvcGVJZCkge1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNvbnN0IGhvbGRlclNjb3BlID0gdGhpcy5zY29wZUFuYWx5c2lzLnNjb3Blcy5nZXQodXNhZ2UuaG9sZGVyU2NvcGVJZCk7XG5cdFx0XHRcdGlmICghaG9sZGVyU2NvcGUpIHtcblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb25zdCBhbmNob3I6IENyZWF0aW9uQW5jaG9yID0ge1xuXHRcdFx0XHRcdGxvY2F0aW9uICAgICAgOiB1c2FnZS5sb2NhdGlvbixcblx0XHRcdFx0XHRob2xkZXJTY29wZUlkIDogdXNhZ2UuaG9sZGVyU2NvcGVJZCxcblx0XHRcdFx0XHR0eXBlUGF0aCxcblx0XHRcdFx0fTtcblx0XHRcdFx0aWYgKHVzYWdlLmNvbnN0cnVjdG9yVGV4dCkge1xuXHRcdFx0XHRcdGFuY2hvci5jb25zdHJ1Y3RvclRleHQgPSB1c2FnZS5jb25zdHJ1Y3RvclRleHQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKGhvbGRlclNjb3BlLmtpbmQgPT09ICdtb2R1bGUnKSB7XG5cdFx0XHRcdFx0Ly8gUGxhbjogbW9kdWxlLXNjb3BlIGNyZWF0aW9uIGlzIGEgcm9vdGVkIGluc3RhbmNlIOKAlFxuXHRcdFx0XHRcdC8vIGxlZ2l0aW1hdGUgcm9vdCBvciBkZXZlbG9wZXIgZXJyb3I7IGxhYmVsZWQsIG5vdCBwb2xpY2VkXG5cdFx0XHRcdFx0YW5jaG9yLnJvb3RlZCA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0Y29uc3QgdmFyaWFibGUgPSB0aGlzLm1hdGNoQW5jaG9yVmFyaWFibGUodXNhZ2UsIHR5cGVQYXRoLCBob2xkZXJTY29wZSk7XG5cdFx0XHRcdGlmICh2YXJpYWJsZSkge1xuXHRcdFx0XHRcdGFuY2hvci52YXJpYWJsZSA9IHZhcmlhYmxlLm5hbWU7XG5cdFx0XHRcdFx0Y29uc3QgWyB0ZXJtaW5hdGVkQXQgXSA9IHZhcmlhYmxlLnJlYXNzaWdubWVudHM7XG5cdFx0XHRcdFx0aWYgKHRlcm1pbmF0ZWRBdCkge1xuXHRcdFx0XHRcdFx0YW5jaG9yLnRlcm1pbmF0ZWRBdCA9IHRlcm1pbmF0ZWRBdDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0YW5jaG9ycy5wdXNoKGFuY2hvcik7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBhbmNob3JzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNhbWUtbGluZSBoZXVyaXN0aWMgZm9yIHRoZSBhbmNob3IncyB2YXJpYWJsZTogdGhlIHZhcmlhYmxlIGRlY2xhcmVkIGluXG5cdCAqIHRoZSBob2xkZXIgc2NvcGUgb24gdGhlIHNhbWUgbGluZSBhcyB0aGUgY3JlYXRpb24sIHdob3NlIHR5cGVQYXRoICh3aGVuXG5cdCAqIGtub3duKSBtYXRjaGVzIHRoZSBjcmVhdGVkIHR5cGUuXG5cdCAqL1xuXHRwcml2YXRlIG1hdGNoQW5jaG9yVmFyaWFibGUgKFxuXHRcdHVzYWdlOiBVc2FnZUluZm8sXG5cdFx0dHlwZVBhdGg6IHN0cmluZyxcblx0XHRob2xkZXJTY29wZTogU2NvcGVJbmZvXG5cdCk6IFNjb3BlVmFyaWFibGUgfCB1bmRlZmluZWQge1xuXHRcdGNvbnN0IHVzYWdlTGluZSA9IENyZWF0aW9uR3JhcGhCdWlsZGVyLmxpbmVPZih1c2FnZS5sb2NhdGlvbik7XG5cdFx0aWYgKHVzYWdlTGluZSA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHRmb3IgKGNvbnN0IHZhcmlhYmxlIG9mIHRoaXMuc2NvcGVBbmFseXNpcy52YXJpYWJsZXMudmFsdWVzKCkpIHtcblx0XHRcdGlmICh2YXJpYWJsZS5zY29wZUlkICE9PSBob2xkZXJTY29wZS5zY29wZUlkKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0aWYgKENyZWF0aW9uR3JhcGhCdWlsZGVyLmxpbmVPZih2YXJpYWJsZS5kZWNsYXJhdGlvbikgIT09IHVzYWdlTGluZSkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdGlmICh2YXJpYWJsZS50eXBlUGF0aCAmJiB2YXJpYWJsZS50eXBlUGF0aCAhPT0gdHlwZVBhdGgpIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gdmFyaWFibGU7XG5cdFx0fVxuXHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdH1cblxuXHQvKipcblx0ICogUGFyc2UgdGhlIDEtYmFzZWQgbGluZSBvdXQgb2YgYSBmaWxlLnRzOkxpbmU6Q29sIGxvY2F0aW9uIHN0cmluZy5cblx0ICovXG5cdHByaXZhdGUgc3RhdGljIGxpbmVPZiAobG9jYXRpb246IHN0cmluZyk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG5cdFx0Y29uc3QgbGFzdENvbG9uID0gbG9jYXRpb24ubGFzdEluZGV4T2YoJzonKTtcblx0XHRjb25zdCBwcmV2Q29sb24gPSBsb2NhdGlvbi5sYXN0SW5kZXhPZignOicsIGxhc3RDb2xvbiAtIDEpO1xuXHRcdGlmIChsYXN0Q29sb24gPCAwIHx8IHByZXZDb2xvbiA8IDApIHtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdGNvbnN0IGxpbmUgPSBOdW1iZXIobG9jYXRpb24uc2xpY2UocHJldkNvbG9uICsgMSwgbGFzdENvbG9uKSk7XG5cdFx0Y29uc3QgcmVzdWx0ID0gTnVtYmVyLmlzRmluaXRlKGxpbmUpID8gbGluZSA6IHVuZGVmaW5lZDtcblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9XG5cblx0cHJpdmF0ZSBzdGF0aWMgbm9kZU9mIChzY29wZTogU2NvcGVJbmZvKTogQ3JlYXRpb25HcmFwaE5vZGUge1xuXHRcdGNvbnN0IG5vZGU6IENyZWF0aW9uR3JhcGhOb2RlID0ge1xuXHRcdFx0c2NvcGVJZCAgOiBzY29wZS5zY29wZUlkLFxuXHRcdFx0bmFtZSAgICAgOiBzY29wZS5uYW1lLFxuXHRcdFx0a2luZCAgICAgOiBzY29wZS5raW5kLFxuXHRcdFx0ZmlsZVBhdGggOiBzY29wZS5maWxlUGF0aCxcblx0XHRcdGxvY2F0aW9uIDogc2NvcGUubG9jYXRpb24sXG5cdFx0XHRzdGFydGVyICA6IGZhbHNlLFxuXHRcdH07XG5cdFx0cmV0dXJuIG5vZGU7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIG5hbWUgYSBzY29wZSBpcyByZWFjaGFibGUgYnk6IGZ1bmN0aW9ucy9hcnJvd3MgdGFrZSB0aGVpciBzY29wZVxuXHQgKiBuYW1lOyBtZXRob2RzIHRha2UgdGhlaXIgY2xhc3MgKHRoZSBwYXJ0IGJlZm9yZSAnLicpIOKAlCB0aGF0IGlzIHdoYXRcblx0ICogY2FsbGVycyByZWZlcmVuY2UuIEFub255bW91cyBob2xkZXJzIChmaWxlOmxpbmUgbGFiZWxzKSBhbmQgbW9kdWxlXG5cdCAqIHNjb3BlcyBoYXZlIG5vIGJpbmRpbmcgbmFtZS5cblx0ICovXG5cdHByaXZhdGUgc3RhdGljIGJpbmRpbmdOYW1lT2YgKHNjb3BlOiBTY29wZUluZm8pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuXHRcdGlmIChzY29wZS5raW5kID09PSAnbW9kdWxlJykge1xuXHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0Ly8gQW5vbnltb3VzIGxhYmVsIGlzIGAke2ZpbGVQYXRofToke2xpbmV9YCDigJQgYSBuYW1lIGNhbiBuZXZlciBjb250YWluICcvJ1xuXHRcdGlmIChzY29wZS5uYW1lLnN0YXJ0c1dpdGgoYCR7c2NvcGUuZmlsZVBhdGh9OmApKSB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHRpZiAoc2NvcGUua2luZCA9PT0gJ21ldGhvZCcpIHtcblx0XHRcdGNvbnN0IGRvdEluZGV4ID0gc2NvcGUubmFtZS5pbmRleE9mKCcuJyk7XG5cdFx0XHRpZiAoZG90SW5kZXggPCAwKSB7XG5cdFx0XHRcdC8vIE1ldGhvZCBvZiBhbiBhbm9ueW1vdXMgY2xhc3Mg4oCUIG5vIGJpbmRpbmcgbmFtZVxuXHRcdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgcmVzdWx0ID0gc2NvcGUubmFtZS5zbGljZSgwLCBkb3RJbmRleCk7XG5cdFx0XHRyZXR1cm4gcmVzdWx0O1xuXHRcdH1cblx0XHRyZXR1cm4gc2NvcGUubmFtZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTY29wZSBpZHMgcmVmZXJlbmNpbmcgYGJpbmRpbmdOYW1lYCBpbnNpZGUgb25lIGZpbGUgKGludm9jYXRpb25zLFxuXHQgKiBwYXNzLWFzLWFyZywgcmViaW5kaW5ncyDigJQgYW55IG5vbi1kZWNsYXJhdGlvbiBpZGVudGlmaWVyKS5cblx0ICovXG5cdHByaXZhdGUgY2FsbGVyc09mIChmaWxlUGF0aDogc3RyaW5nLCBiaW5kaW5nTmFtZTogc3RyaW5nKTogc3RyaW5nW10ge1xuXHRcdGNvbnN0IHJlZmVyZW5jZXMgPSB0aGlzLnJlZmVyZW5jZXNJbihmaWxlUGF0aCwgYmluZGluZ05hbWUpO1xuXHRcdGNvbnN0IGNhbGxlcnM6IHN0cmluZ1tdID0gW107XG5cdFx0Zm9yIChjb25zdCBsb2NhdGlvbiBvZiByZWZlcmVuY2VzKSB7XG5cdFx0XHRjb25zdCBjYWxsZXJTY29wZUlkID0gdGhpcy5zY29wZVdhbGtlci5maW5kSG9sZGVyU2NvcGVJZChsb2NhdGlvbik7XG5cdFx0XHRpZiAoY2FsbGVyU2NvcGVJZCkge1xuXHRcdFx0XHRjYWxsZXJzLnB1c2goY2FsbGVyU2NvcGVJZCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBjYWxsZXJzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbGxlcnMgaW4gT1RIRVIgbW9kdWxlcywgZm9sbG93ZWQgdGhyb3VnaCB0aGUgbW9kdWxlIGdyYXBoIHdoZW4gdGhlXG5cdCAqIGhvbGRlcidzIGJpbmRpbmcgaXMgZXhwb3J0ZWQgKHRoZSBwbGFuJ3MgXCJpZiBmIGlzIGV4cG9ydGVkXCIgYnJhbmNoLFxuXHQgKiBpbmNsdWRpbmcgdGhlIGJhcnJlbCBjaGFzZSkuXG5cdCAqL1xuXHRwcml2YXRlIGZpbmRDcm9zc0ZpbGVDYWxsZXJzIChzY29wZTogU2NvcGVJbmZvLCBiaW5kaW5nTmFtZTogc3RyaW5nKTogc3RyaW5nW10ge1xuXHRcdGNvbnN0IGhvbGRlck1vZHVsZSA9IHRoaXMubW9kdWxlR3JhcGgubW9kdWxlcy5nZXQoc2NvcGUuZmlsZVBhdGgpO1xuXHRcdGlmICghaG9sZGVyTW9kdWxlKSB7XG5cdFx0XHRyZXR1cm4gW107XG5cdFx0fVxuXHRcdC8vIFRoZSBleHBvcnRlZCBiaW5kaW5nIHdob3NlIExPQ0FMIG5hbWUgaXMgdGhlIHNjb3BlJ3MgYmluZGluZyBuYW1lLlxuXHRcdC8vIFBsYWluIGV4cG9ydHMgcHJlc2VudCB1bmRlciB0aGVpciBvd24gbmFtZTsgYGV4cG9ydCB7IFggYXMgWSB9YCBhbmRcblx0XHQvLyBgZXhwb3J0IGRlZmF1bHQgWGAgY2FycnkgdGhlIGxvY2FsIG5hbWUgaW4gaW1wb3J0QWxpYXMuXG5cdFx0Y29uc3QgZXhwb3J0ZWQgPSBob2xkZXJNb2R1bGUuZXhwb3J0ZWRCaW5kaW5ncy5maW5kKGJpbmRpbmcgPT5cblx0XHRcdCFiaW5kaW5nLmlzUmVFeHBvcnQgJiYgKGJpbmRpbmcuaW1wb3J0QWxpYXMgPz8gYmluZGluZy5uYW1lKSA9PT0gYmluZGluZ05hbWUpO1xuXHRcdGlmICghZXhwb3J0ZWQpIHtcblx0XHRcdHJldHVybiBbXTtcblx0XHR9XG5cblx0XHRjb25zdCBjYWxsZXJzOiBzdHJpbmdbXSA9IFtdO1xuXHRcdGZvciAoY29uc3QgaW1wb3J0ZXIgb2YgdGhpcy5tb2R1bGVHcmFwaC5tb2R1bGVzLnZhbHVlcygpKSB7XG5cdFx0XHRpZiAoaW1wb3J0ZXIuZmlsZVBhdGggPT09IHNjb3BlLmZpbGVQYXRoKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0Zm9yIChjb25zdCBpbXBvcnRlZCBvZiBpbXBvcnRlci5pbXBvcnRlZEJpbmRpbmdzKSB7XG5cdFx0XHRcdC8vIFJlLWV4cG9ydHMgY3JlYXRlIG5vIGxvY2FsIGlkZW50aWZpZXIgdG8gcmVmZXJlbmNlOyBleHRlcm5hbFxuXHRcdFx0XHQvLyBwYWNrYWdlcyAobm9kZV9tb2R1bGVzKSBhcmUgbmV2ZXIgd2Fsa2VkXG5cdFx0XHRcdGlmIChpbXBvcnRlZC5pc1JlRXhwb3J0IHx8IGltcG9ydGVkLmV4dGVybmFsKSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0Y29uc3QgbG9jYWxOYW1lID0gdGhpcy5pbXBvcnRSZWZlcmVuY2VzSG9sZGVyKGltcG9ydGVkLCBleHBvcnRlZCwgc2NvcGUuZmlsZVBhdGgpO1xuXHRcdFx0XHRpZiAoIWxvY2FsTmFtZSkge1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNvbnN0IGltcG9ydGVyQ2FsbGVycyA9IHRoaXMuY2FsbGVyc09mKGltcG9ydGVyLmZpbGVQYXRoLCBsb2NhbE5hbWUpO1xuXHRcdFx0XHRjYWxsZXJzLnB1c2goLi4uaW1wb3J0ZXJDYWxsZXJzKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGNhbGxlcnM7XG5cdH1cblxuXHQvKipcblx0ICogTW9kdWxlcyBpbXBvcnRpbmcgYmluZGluZ3Mgd2hvc2UgT1JJR0lOIGlzIGBmaWxlUGF0aGAg4oCUIHRoZVxuXHQgKiBleHBvcnRzLWFuZC11c2FnZSBicmlkZ2UgZm9yIHRlcm1pbmFsIG1vZHVsZSBzY29wZXMuIEFueSBiaW5kaW5nIGtpbmRcblx0ICogY291bnRzIChuYW1lZCwgZGVmYXVsdCwgcmUtZXhwb3J0KTogcmVzb2x2ZUltcG9ydE9yaWdpbiBjaGFzZXMgYmFycmVsc1xuXHQgKiB0byB0aGUgZGVjbGFyaW5nIG1vZHVsZTsgbmFtZXNwYWNlIGltcG9ydHMgYW5kIGV4dGVybmFsIHBhY2thZ2VzIG5ldmVyXG5cdCAqIHJlc29sdmUsIHNvIG5laXRoZXIgY29ubmVjdHMuIFJldHVybmVkIGFzIG1vZHVsZS1zY29wZSBzY29wZUlkcyDigJQgYVxuXHQgKiBtb2R1bGUncyBzY29wZUlkIElTIGl0cyByZXNvbHZlZCBmaWxlUGF0aC5cblx0ICovXG5cdHByaXZhdGUgaW1wb3J0ZXJzT2YgKGZpbGVQYXRoOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG5cdFx0Y29uc3QgaW1wb3J0ZXJzOiBzdHJpbmdbXSA9IFtdO1xuXHRcdGZvciAoY29uc3QgaW1wb3J0ZXIgb2YgdGhpcy5tb2R1bGVHcmFwaC5tb2R1bGVzLnZhbHVlcygpKSB7XG5cdFx0XHRpZiAoaW1wb3J0ZXIuZmlsZVBhdGggPT09IGZpbGVQYXRoKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgZGVwZW5kcyA9IGltcG9ydGVyLmltcG9ydGVkQmluZGluZ3Muc29tZShpbXBvcnRlZCA9PiB7XG5cdFx0XHRcdGNvbnN0IG9yaWdpbiA9IHRoaXMucmVzb2x2ZUltcG9ydE9yaWdpbihpbXBvcnRlZCk7XG5cdFx0XHRcdGNvbnN0IHJlc3VsdCA9IG9yaWdpbiAhPT0gdW5kZWZpbmVkICYmIG9yaWdpbi5tb2R1bGUuZmlsZVBhdGggPT09IGZpbGVQYXRoO1xuXHRcdFx0XHRyZXR1cm4gcmVzdWx0O1xuXHRcdFx0fSk7XG5cdFx0XHRpZiAoZGVwZW5kcykge1xuXHRcdFx0XHRpbXBvcnRlcnMucHVzaChpbXBvcnRlci5maWxlUGF0aCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBpbXBvcnRlcnM7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIGxvY2FsIGlkZW50aWZpZXIgYW4gaW1wb3J0IGJpbmRpbmcgcHJlc2VudHMgZm9yIHJlZmVyZW5jZSBzZWFyY2gsXG5cdCAqIHdoZW4gdGhlIGJpbmRpbmcgcmVzb2x2ZXMgdG8gdGhlIGhvbGRlcidzIGV4cG9ydCDigJQgdW5kZWZpbmVkIG90aGVyd2lzZS5cblx0ICovXG5cdHByaXZhdGUgaW1wb3J0UmVmZXJlbmNlc0hvbGRlciAoXG5cdFx0aW1wb3J0ZWQ6IE1vZHVsZUJpbmRpbmcsXG5cdFx0aG9sZGVyRXhwb3J0OiBNb2R1bGVCaW5kaW5nLFxuXHRcdGhvbGRlckZpbGVQYXRoOiBzdHJpbmdcblx0KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcblx0XHRpZiAoaW1wb3J0ZWQuaW1wb3J0S2luZCA9PT0gJ25hbWVzcGFjZScpIHtcblx0XHRcdC8vIE5hbWVzcGFjZSBhcHByb3hpbWF0aW9uOiB3aGVuIHRoZSBhbGlhcydzIHNvdXJjZSBtb2R1bGUgZXhwb3Nlc1xuXHRcdFx0Ly8gdGhlIGhvbGRlcidzIGV4cG9ydCwgYW55IHJlZmVyZW5jZSB0byB0aGUgYWxpYXMgY291bnRzXG5cdFx0XHRjb25zdCBleHBvc2VzID0gdGhpcy5uYW1lc3BhY2VFeHBvc2VzKGltcG9ydGVkLnNvdXJjZU1vZHVsZSwgaG9sZGVyRXhwb3J0Lm5hbWUsIGhvbGRlckZpbGVQYXRoKTtcblx0XHRcdGNvbnN0IHJlc3VsdCA9IGV4cG9zZXMgPyBpbXBvcnRlZC5uYW1lIDogdW5kZWZpbmVkO1xuXHRcdFx0cmV0dXJuIHJlc3VsdDtcblx0XHR9XG5cdFx0Y29uc3Qgb3JpZ2luID0gdGhpcy5yZXNvbHZlSW1wb3J0T3JpZ2luKGltcG9ydGVkKTtcblx0XHRpZiAoIW9yaWdpbikge1xuXHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0aWYgKG9yaWdpbi5tb2R1bGUuZmlsZVBhdGggIT09IGhvbGRlckZpbGVQYXRoIHx8IG9yaWdpbi5iaW5kaW5nLm5hbWUgIT09IGhvbGRlckV4cG9ydC5uYW1lKSB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHRyZXR1cm4gaW1wb3J0ZWQubmFtZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUcnVlIHdoZW4gYSBuYW1lc3BhY2UgaW1wb3J0J3Mgc291cmNlIG1vZHVsZSBleHBvc2VzIGBleHBvcnRlZE5hbWVgXG5cdCAqIHdob3NlIG9yaWdpbiBpcyB0aGUgaG9sZGVyJ3MgbW9kdWxlLiBFeHByZXNzZWQgYXMgcmVzb2x2aW5nIGEgc3ludGhldGljXG5cdCAqIG5hbWVkIGJpbmRpbmcsIHNvIHN0YXIgYmFycmVscyBhbmQgbmFtZWQgcmUtZXhwb3J0cyBhcmUgY2hhc2VkIGJ5IHRoZVxuXHQgKiBzYW1lIG1hY2hpbmVyeSBhcyBwbGFpbiBpbXBvcnRzLlxuXHQgKi9cblx0cHJpdmF0ZSBuYW1lc3BhY2VFeHBvc2VzIChzb3VyY2VNb2R1bGU6IHN0cmluZywgZXhwb3J0ZWROYW1lOiBzdHJpbmcsIGhvbGRlckZpbGVQYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcblx0XHRjb25zdCBzeW50aGV0aWM6IE1vZHVsZUJpbmRpbmcgPSB7XG5cdFx0XHRuYW1lICAgICAgIDogZXhwb3J0ZWROYW1lLFxuXHRcdFx0a2luZCAgICAgICA6ICd1bmtub3duJyxcblx0XHRcdHNvdXJjZU1vZHVsZSxcblx0XHRcdGlzUmVFeHBvcnQgOiB0cnVlLFxuXHRcdH07XG5cdFx0Y29uc3Qgb3JpZ2luID0gdGhpcy5yZXNvbHZlSW1wb3J0T3JpZ2luKHN5bnRoZXRpYyk7XG5cdFx0aWYgKCFvcmlnaW4pIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0Y29uc3QgcmVzdWx0ID0gb3JpZ2luLm1vZHVsZS5maWxlUGF0aCA9PT0gaG9sZGVyRmlsZVBhdGggJiYgb3JpZ2luLmJpbmRpbmcubmFtZSA9PT0gZXhwb3J0ZWROYW1lO1xuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHQvKipcblx0ICogQ2hhc2UgYW4gaW1wb3J0IGJpbmRpbmcgdG8gdGhlIG1vZHVsZSB0aGF0IGFjdHVhbGx5IGRlY2xhcmVzIGl0LFxuXHQgKiBmb2xsb3dpbmcgcmUtZXhwb3J0IGNoYWlucyAoYmFycmVscykuIFNhbWUgc2hhcGUgYXNcblx0ICogTW9kdWxlR3JhcGhCdWlsZGVyLnJlc29sdmVPcmlnaW4sIHJ1biBoZXJlIG92ZXIgdGhlIEJVSUxUIGdyYXBoXG5cdCAqIChzb3VyY2VNb2R1bGUgdmFsdWVzIGFyZSBhbHJlYWR5IHJlc29sdmVkIGFic29sdXRlIHBhdGhzKS5cblx0ICogQ3ljbGUtZ3VhcmRlZDsgdW5kZWZpbmVkIHdoZW4gdGhlIG9yaWdpbiBpcyBleHRlcm5hbCBvciB0aGUgY2hhaW4gbG9vcHMuXG5cdCAqL1xuXHRwcml2YXRlIHJlc29sdmVJbXBvcnRPcmlnaW4gKFxuXHRcdGJpbmRpbmc6IE1vZHVsZUJpbmRpbmcsXG5cdFx0dmlzaXRlZCA9IG5ldyBTZXQ8c3RyaW5nPigpXG5cdCk6IHsgbW9kdWxlOiBNb2R1bGVJbmZvOyBiaW5kaW5nOiBNb2R1bGVCaW5kaW5nIH0gfCB1bmRlZmluZWQge1xuXHRcdGNvbnN0IHNvdXJjZVBhdGggPSBwYXRoLnJlc29sdmUoYmluZGluZy5zb3VyY2VNb2R1bGUpO1xuXHRcdGlmICh2aXNpdGVkLmhhcyhzb3VyY2VQYXRoKSkge1xuXHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0dmlzaXRlZC5hZGQoc291cmNlUGF0aCk7XG5cblx0XHRjb25zdCBzb3VyY2VNb2R1bGVJbmZvID0gdGhpcy5tb2R1bGVHcmFwaC5tb2R1bGVzLmdldChzb3VyY2VQYXRoKTtcblx0XHRpZiAoIXNvdXJjZU1vZHVsZUluZm8pIHtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fVxuXG5cdFx0Ly8gVGhlIG5hbWUgdG8gbG9vayB1cCBpbiB0aGUgc291cmNlIG1vZHVsZSdzIGV4cG9ydCBsaXN0XG5cdFx0Y29uc3QgbG9va3VwS2V5ID0gYmluZGluZy5pbXBvcnRLaW5kID09PSAnZGVmYXVsdCdcblx0XHRcdD8gJ2RlZmF1bHQnXG5cdFx0XHQ6IGJpbmRpbmcuaW1wb3J0QWxpYXMgPz8gYmluZGluZy5uYW1lO1xuXG5cdFx0Zm9yIChjb25zdCBleHBvcnRlZCBvZiBzb3VyY2VNb2R1bGVJbmZvLmV4cG9ydGVkQmluZGluZ3MpIHtcblx0XHRcdGlmIChleHBvcnRlZC5uYW1lICE9PSBsb29rdXBLZXkpIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIWV4cG9ydGVkLmlzUmVFeHBvcnQpIHtcblx0XHRcdFx0Y29uc3QgcmVzdWx0ID0geyBtb2R1bGUgOiBzb3VyY2VNb2R1bGVJbmZvLCBiaW5kaW5nIDogZXhwb3J0ZWQgfTtcblx0XHRcdFx0cmV0dXJuIHJlc3VsdDtcblx0XHRcdH1cblx0XHRcdGNvbnN0IGNoYXNlZCA9IHRoaXMucmVzb2x2ZUltcG9ydE9yaWdpbihleHBvcnRlZCwgdmlzaXRlZCk7XG5cdFx0XHRyZXR1cm4gY2hhc2VkO1xuXHRcdH1cblxuXHRcdC8vIGBleHBvcnQgKiBmcm9tICcuL3knYCBiYXJyZWxzOiB0aGUgbmFtZSBtYXkgbGl2ZSBiZWhpbmQgYSBzdGFyXG5cdFx0Zm9yIChjb25zdCBleHBvcnRlZCBvZiBzb3VyY2VNb2R1bGVJbmZvLmV4cG9ydGVkQmluZGluZ3MpIHtcblx0XHRcdGlmICghZXhwb3J0ZWQuaXNSZUV4cG9ydCB8fCBleHBvcnRlZC5pbXBvcnRLaW5kICE9PSAnbmFtZXNwYWNlJyB8fCBleHBvcnRlZC5uYW1lICE9PSAnKicpIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHRjb25zdCBjaGFzZWQgPSB0aGlzLnJlc29sdmVJbXBvcnRPcmlnaW4oe1xuXHRcdFx0XHRuYW1lICAgICAgICAgOiBsb29rdXBLZXksXG5cdFx0XHRcdGtpbmQgICAgICAgICA6ICd1bmtub3duJyxcblx0XHRcdFx0c291cmNlTW9kdWxlIDogZXhwb3J0ZWQuc291cmNlTW9kdWxlLFxuXHRcdFx0XHRpc1JlRXhwb3J0ICAgOiB0cnVlLFxuXHRcdFx0fSwgdmlzaXRlZCk7XG5cdFx0XHRpZiAoY2hhc2VkKSB7XG5cdFx0XHRcdHJldHVybiBjaGFzZWQ7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbGwgcmVmZXJlbmNlcyB0byBgbmFtZWAgaW4gYSBmaWxlIGFzIGxvY2F0aW9uIHN0cmluZ3MuIFRoZSBwZXItZmlsZVxuXHQgKiBpbmRleCBpcyBidWlsdCBsYXppbHkgaW4gT05FIHBhc3MgKGV2ZXJ5IGlkZW50aWZpZXIgYnVja2V0ZWQgYnkgdGV4dClcblx0ICogYW5kIGNhY2hlZC5cblx0ICovXG5cdHByaXZhdGUgcmVmZXJlbmNlc0luIChmaWxlUGF0aDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG5cdFx0bGV0IGJ5TmFtZSA9IHRoaXMucmVmZXJlbmNlc0J5RmlsZS5nZXQoZmlsZVBhdGgpO1xuXHRcdGlmICghYnlOYW1lKSB7XG5cdFx0XHRieU5hbWUgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nW10+KCk7XG5cdFx0XHRjb25zdCBzb3VyY2VGaWxlID0gdGhpcy5zb3VyY2VGaWxlcy5nZXQoZmlsZVBhdGgpO1xuXHRcdFx0aWYgKHNvdXJjZUZpbGUpIHtcblx0XHRcdFx0Q3JlYXRpb25HcmFwaEJ1aWxkZXIuY29sbGVjdFJlZmVyZW5jZXMoc291cmNlRmlsZSwgYnlOYW1lKTtcblx0XHRcdH1cblx0XHRcdHRoaXMucmVmZXJlbmNlc0J5RmlsZS5zZXQoZmlsZVBhdGgsIGJ5TmFtZSk7XG5cdFx0fVxuXHRcdGNvbnN0IHJlc3VsdCA9IGJ5TmFtZS5nZXQobmFtZSkgPz8gW107XG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fVxuXG5cdC8qKlxuXHQgKiBCdWNrZXQgZXZlcnkgaWRlbnRpZmllciByZWZlcmVuY2UgYnkgbmFtZS4gRGVjbGFyYXRpb24gYW5kIHdpcmluZ1xuXHQgKiBwb3NpdGlvbnMgYXJlIE5PVCByZWZlcmVuY2VzOiBpbXBvcnQvZXhwb3J0IHNwZWNpZmllcnMsIGRlY2xhcmF0aW9uXG5cdCAqIG5hbWVzLCBwcm9wZXJ0eS1hY2Nlc3MgYC5uYW1lYCwgYW5kIHByb3BlcnR5LWFzc2lnbm1lbnQga2V5cyBnbyBpbnRvIGFcblx0ICogc2tpcCBzZXQgb2YgTk9ERVMg4oCUIHByb2dyYW0gZmlsZXMgY2FuIGJlIHVuYm91bmQsIHNvIHBhcmVudC1wb2ludGVyXG5cdCAqIGNoZWNrcyBhcmUgaW1wb3NzaWJsZSAodGhlIHNjb3BlcyB3YWxrZXIgcHJlY2VkZW50LCBQaGFzZSAyKS5cblx0ICogU2hvcnRoYW5kUHJvcGVydHlBc3NpZ25tZW50IG5hbWVzIERPIGNvdW50OiBgeyBmb28gfWAgaXMgYSBnZW51aW5lXG5cdCAqIHJlZmVyZW5jZSB0byBmb28uXG5cdCAqL1xuXHRwcml2YXRlIHN0YXRpYyBjb2xsZWN0UmVmZXJlbmNlcyAoc291cmNlRmlsZTogdHMuU291cmNlRmlsZSwgYnlOYW1lOiBNYXA8c3RyaW5nLCBzdHJpbmdbXT4pOiB2b2lkIHtcblx0XHRjb25zdCBza2lwID0gbmV3IFNldDx0cy5Ob2RlPigpO1xuXHRcdGNvbnN0IGZpbGVQYXRoID0gcGF0aC5yZXNvbHZlKHNvdXJjZUZpbGUuZmlsZU5hbWUpO1xuXG5cdFx0Y29uc3QgdmlzaXQgPSAobm9kZTogdHMuTm9kZSk6IHZvaWQgPT4ge1xuXHRcdFx0Q3JlYXRpb25HcmFwaEJ1aWxkZXIucmVnaXN0ZXJTa2lwcyhub2RlLCBza2lwKTtcblx0XHRcdGlmICh0cy5pc0lkZW50aWZpZXIobm9kZSkgJiYgIXNraXAuaGFzKG5vZGUpKSB7XG5cdFx0XHRcdGNvbnN0IGxpc3QgPSBieU5hbWUuZ2V0KG5vZGUudGV4dCkgPz8gW107XG5cdFx0XHRcdGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0XHRcdGJ5TmFtZS5zZXQobm9kZS50ZXh0LCBsaXN0KTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb25zdCB7IGxpbmUsIGNoYXJhY3RlciB9ID0gc291cmNlRmlsZS5nZXRMaW5lQW5kQ2hhcmFjdGVyT2ZQb3NpdGlvbihub2RlLmdldFN0YXJ0KHNvdXJjZUZpbGUpKTtcblx0XHRcdFx0bGlzdC5wdXNoKGAke2ZpbGVQYXRofToke2xpbmUgKyAxfToke2NoYXJhY3RlciArIDF9YCk7XG5cdFx0XHR9XG5cdFx0XHR0cy5mb3JFYWNoQ2hpbGQobm9kZSwgdmlzaXQpO1xuXHRcdH07XG5cdFx0dmlzaXQoc291cmNlRmlsZSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXIgdGhlIGlkZW50aWZpZXIgbm9kZXMgdGhhdCBtdXN0IE5PVCBjb3VudCBhcyByZWZlcmVuY2VzIHdoZW5cblx0ICogYG5vZGVgIGlzIGEgd2lyaW5nL2RlY2xhcmF0aW9uIGNvbnN0cnVjdC4gUnVucyBvbiB0aGUgcGFyZW50IGJlZm9yZVxuXHQgKiBkZXNjZW5kaW5nLCBzbyB0aGUgc2tpcCBzZXQgaXMgcG9wdWxhdGVkIGJlZm9yZSB0aGUgaWRlbnRpZmllciBub2Rlc1xuXHQgKiB0aGVtc2VsdmVzIGFyZSB2aXNpdGVkLlxuXHQgKi9cblx0cHJpdmF0ZSBzdGF0aWMgcmVnaXN0ZXJTa2lwcyAobm9kZTogdHMuTm9kZSwgc2tpcDogU2V0PHRzLk5vZGU+KTogdm9pZCB7XG5cdFx0Ly8gaW1wb3J0IOKApiBmcm9tICcuL3gnXG5cdFx0aWYgKHRzLmlzSW1wb3J0RGVjbGFyYXRpb24obm9kZSkpIHtcblx0XHRcdGNvbnN0IHsgaW1wb3J0Q2xhdXNlIH0gPSBub2RlO1xuXHRcdFx0aWYgKCFpbXBvcnRDbGF1c2UpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0aWYgKGltcG9ydENsYXVzZS5uYW1lKSB7XG5cdFx0XHRcdHNraXAuYWRkKGltcG9ydENsYXVzZS5uYW1lKTtcblx0XHRcdH1cblx0XHRcdGNvbnN0IHsgbmFtZWRCaW5kaW5ncyB9ID0gaW1wb3J0Q2xhdXNlO1xuXHRcdFx0aWYgKG5hbWVkQmluZGluZ3MgJiYgdHMuaXNOYW1lZEltcG9ydHMobmFtZWRCaW5kaW5ncykpIHtcblx0XHRcdFx0Zm9yIChjb25zdCBlbGVtZW50IG9mIG5hbWVkQmluZGluZ3MuZWxlbWVudHMpIHtcblx0XHRcdFx0XHRpZiAoZWxlbWVudC5wcm9wZXJ0eU5hbWUpIHtcblx0XHRcdFx0XHRcdHNraXAuYWRkKGVsZW1lbnQucHJvcGVydHlOYW1lKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0c2tpcC5hZGQoZWxlbWVudC5uYW1lKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0aWYgKG5hbWVkQmluZGluZ3MgJiYgdHMuaXNOYW1lc3BhY2VJbXBvcnQobmFtZWRCaW5kaW5ncykpIHtcblx0XHRcdFx0c2tpcC5hZGQobmFtZWRCaW5kaW5ncy5uYW1lKTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0Ly8gaW1wb3J0IHggPSByZXF1aXJlKCcuL3knKVxuXHRcdGlmICh0cy5pc0ltcG9ydEVxdWFsc0RlY2xhcmF0aW9uKG5vZGUpKSB7XG5cdFx0XHRza2lwLmFkZChub2RlLm5hbWUpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHQvLyBleHBvcnQgeyBYIH0gW2Zyb20gJy4veSddIC8gZXhwb3J0ICogYXMgbnMgZnJvbSAnLi95JyDigJQgZXhwb3J0IHdpcmluZ1xuXHRcdC8vIGFsb25lIGlzIG5vdCBhIGNhbGxlcjsgYW4gaW1wb3J0ZXIncyB1c2FnZSBjcmVhdGVzIHRoZSBlZGdlIGluc3RlYWRcblx0XHRpZiAodHMuaXNFeHBvcnREZWNsYXJhdGlvbihub2RlKSkge1xuXHRcdFx0Y29uc3QgeyBleHBvcnRDbGF1c2UgfSA9IG5vZGU7XG5cdFx0XHRpZiAoZXhwb3J0Q2xhdXNlICYmIHRzLmlzTmFtZWRFeHBvcnRzKGV4cG9ydENsYXVzZSkpIHtcblx0XHRcdFx0Zm9yIChjb25zdCBlbGVtZW50IG9mIGV4cG9ydENsYXVzZS5lbGVtZW50cykge1xuXHRcdFx0XHRcdGlmIChlbGVtZW50LnByb3BlcnR5TmFtZSkge1xuXHRcdFx0XHRcdFx0c2tpcC5hZGQoZWxlbWVudC5wcm9wZXJ0eU5hbWUpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRza2lwLmFkZChlbGVtZW50Lm5hbWUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAoZXhwb3J0Q2xhdXNlICYmIHRzLmlzTmFtZXNwYWNlRXhwb3J0KGV4cG9ydENsYXVzZSkpIHtcblx0XHRcdFx0c2tpcC5hZGQoZXhwb3J0Q2xhdXNlLm5hbWUpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHQvLyBleHBvcnQgZGVmYXVsdCBmb28g4oCUIHNhbWUgZXhwb3J0LXdpcmluZyBydWxlXG5cdFx0aWYgKHRzLmlzRXhwb3J0QXNzaWdubWVudChub2RlKSAmJiB0cy5pc0lkZW50aWZpZXIobm9kZS5leHByZXNzaW9uKSkge1xuXHRcdFx0c2tpcC5hZGQobm9kZS5leHByZXNzaW9uKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0Ly8gb2JqLm5hbWUg4oCUIHRoZSBgLm5hbWVgIHBhcnQgaXMgcHJvcGVydHkgd2lyaW5nLCBub3QgYSByZWZlcmVuY2Vcblx0XHRpZiAodHMuaXNQcm9wZXJ0eUFjY2Vzc0V4cHJlc3Npb24obm9kZSkpIHtcblx0XHRcdHNraXAuYWRkKG5vZGUubmFtZSk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdC8vIHsgbmFtZTogdmFsdWUgfSDigJQgdGhlIGtleSBpcyBub3QgYSByZWZlcmVuY2UuIFNob3J0aGFuZCBgeyBuYW1lIH1gXG5cdFx0Ly8gSVMgYSByZWZlcmVuY2U6IFNob3J0aGFuZFByb3BlcnR5QXNzaWdubWVudCBuZXZlciBtYXRjaGVzIGhlcmUuXG5cdFx0aWYgKHRzLmlzUHJvcGVydHlBc3NpZ25tZW50KG5vZGUpICYmIHRzLmlzSWRlbnRpZmllcihub2RlLm5hbWUpKSB7XG5cdFx0XHRza2lwLmFkZChub2RlLm5hbWUpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRpZiAodHMuaXNTaG9ydGhhbmRQcm9wZXJ0eUFzc2lnbm1lbnQobm9kZSkpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0Ly8geyB4OiBhIH0gZGVzdHJ1Y3R1cmluZyDigJQgYHhgIGlzIHByb3BlcnR5IHdpcmluZyAoYGFgIGlzIHRoZSBkZWNsYXJlZFxuXHRcdC8vIG5hbWUsIHNraXBwZWQgYnkgdGhlIGdlbmVyaWMgZGVjbGFyYXRpb24gYnJhbmNoIGJlbG93KVxuXHRcdGlmICh0cy5pc0JpbmRpbmdFbGVtZW50KG5vZGUpICYmIG5vZGUucHJvcGVydHlOYW1lICYmIHRzLmlzSWRlbnRpZmllcihub2RlLnByb3BlcnR5TmFtZSkpIHtcblx0XHRcdHNraXAuYWRkKG5vZGUucHJvcGVydHlOYW1lKTtcblx0XHR9XG5cdFx0Ly8gRGVjbGFyYXRpb24gbmFtZXM6IGBmdW5jdGlvbiBmYCwgYGNsYXNzIENgLCBgY29uc3QgeGAsIHBhcmFtZXRlcnMsXG5cdFx0Ly8gbWV0aG9kcywgZW51bSBtZW1iZXJz4oCmIOKAlCBiZWluZyBkZWNsYXJlZCBpcyBub3QgYmVpbmcgcmVmZXJlbmNlZFxuXHRcdGNvbnN0IG5hbWVkID0gbm9kZSBhcyB0cy5OYW1lZERlY2xhcmF0aW9uO1xuXHRcdGlmICgnbmFtZScgaW4gbm9kZSAmJiBuYW1lZC5uYW1lICYmIHRzLmlzSWRlbnRpZmllcihuYW1lZC5uYW1lKSkge1xuXHRcdFx0c2tpcC5hZGQobmFtZWQubmFtZSk7XG5cdFx0fVxuXHR9XG59XG4iXX0=