@sochdb/sochdb 0.4.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.
Files changed (78) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +3349 -0
  3. package/_bin/aarch64-apple-darwin/libsochdb_storage.dylib +0 -0
  4. package/_bin/aarch64-apple-darwin/sochdb-bulk +0 -0
  5. package/_bin/aarch64-apple-darwin/sochdb-grpc-server +0 -0
  6. package/_bin/aarch64-apple-darwin/sochdb-server +0 -0
  7. package/_bin/x86_64-pc-windows-msvc/sochdb-bulk.exe +0 -0
  8. package/_bin/x86_64-pc-windows-msvc/sochdb-grpc-server.exe +0 -0
  9. package/_bin/x86_64-pc-windows-msvc/sochdb_storage.dll +0 -0
  10. package/_bin/x86_64-unknown-linux-gnu/libsochdb_storage.so +0 -0
  11. package/_bin/x86_64-unknown-linux-gnu/sochdb-bulk +0 -0
  12. package/_bin/x86_64-unknown-linux-gnu/sochdb-grpc-server +0 -0
  13. package/_bin/x86_64-unknown-linux-gnu/sochdb-server +0 -0
  14. package/bin/sochdb-bulk.js +80 -0
  15. package/bin/sochdb-grpc-server.js +80 -0
  16. package/bin/sochdb-server.js +84 -0
  17. package/dist/cjs/analytics.js +196 -0
  18. package/dist/cjs/database.js +929 -0
  19. package/dist/cjs/embedded/database.js +236 -0
  20. package/dist/cjs/embedded/ffi/bindings.js +113 -0
  21. package/dist/cjs/embedded/ffi/library-finder.js +135 -0
  22. package/dist/cjs/embedded/index.js +14 -0
  23. package/dist/cjs/embedded/transaction.js +172 -0
  24. package/dist/cjs/errors.js +71 -0
  25. package/dist/cjs/format.js +176 -0
  26. package/dist/cjs/grpc-client.js +328 -0
  27. package/dist/cjs/index.js +75 -0
  28. package/dist/cjs/ipc-client.js +504 -0
  29. package/dist/cjs/query.js +154 -0
  30. package/dist/cjs/server-manager.js +295 -0
  31. package/dist/cjs/sql-engine.js +874 -0
  32. package/dist/esm/analytics.js +196 -0
  33. package/dist/esm/database.js +931 -0
  34. package/dist/esm/embedded/database.js +239 -0
  35. package/dist/esm/embedded/ffi/bindings.js +142 -0
  36. package/dist/esm/embedded/ffi/library-finder.js +135 -0
  37. package/dist/esm/embedded/index.js +14 -0
  38. package/dist/esm/embedded/transaction.js +176 -0
  39. package/dist/esm/errors.js +71 -0
  40. package/dist/esm/format.js +179 -0
  41. package/dist/esm/grpc-client.js +333 -0
  42. package/dist/esm/index.js +75 -0
  43. package/dist/esm/ipc-client.js +505 -0
  44. package/dist/esm/query.js +159 -0
  45. package/dist/esm/server-manager.js +295 -0
  46. package/dist/esm/sql-engine.js +875 -0
  47. package/dist/types/analytics.d.ts +66 -0
  48. package/dist/types/analytics.d.ts.map +1 -0
  49. package/dist/types/database.d.ts +523 -0
  50. package/dist/types/database.d.ts.map +1 -0
  51. package/dist/types/embedded/database.d.ts +105 -0
  52. package/dist/types/embedded/database.d.ts.map +1 -0
  53. package/dist/types/embedded/ffi/bindings.d.ts +24 -0
  54. package/dist/types/embedded/ffi/bindings.d.ts.map +1 -0
  55. package/dist/types/embedded/ffi/library-finder.d.ts +17 -0
  56. package/dist/types/embedded/ffi/library-finder.d.ts.map +1 -0
  57. package/dist/types/embedded/index.d.ts +9 -0
  58. package/dist/types/embedded/index.d.ts.map +1 -0
  59. package/dist/types/embedded/transaction.d.ts +21 -0
  60. package/dist/types/embedded/transaction.d.ts.map +1 -0
  61. package/dist/types/errors.d.ts +36 -0
  62. package/dist/types/errors.d.ts.map +1 -0
  63. package/dist/types/format.d.ts +117 -0
  64. package/dist/types/format.d.ts.map +1 -0
  65. package/dist/types/grpc-client.d.ts +120 -0
  66. package/dist/types/grpc-client.d.ts.map +1 -0
  67. package/dist/types/index.d.ts +50 -0
  68. package/dist/types/index.d.ts.map +1 -0
  69. package/dist/types/ipc-client.d.ts +177 -0
  70. package/dist/types/ipc-client.d.ts.map +1 -0
  71. package/dist/types/query.d.ts +85 -0
  72. package/dist/types/query.d.ts.map +1 -0
  73. package/dist/types/server-manager.d.ts +29 -0
  74. package/dist/types/server-manager.d.ts.map +1 -0
  75. package/dist/types/sql-engine.d.ts +100 -0
  76. package/dist/types/sql-engine.d.ts.map +1 -0
  77. package/package.json +90 -0
  78. package/scripts/postinstall.js +50 -0
@@ -0,0 +1,875 @@
1
+ "use strict";
2
+ /**
3
+ * SQL Engine for SochDB JavaScript SDK
4
+ *
5
+ * Provides SQL support on top of the KV storage backend.
6
+ * Tables are stored as:
7
+ * - Schema: _sql/tables/{table_name}/schema -> JSON schema definition
8
+ * - Rows: _sql/tables/{table_name}/rows/{row_id} -> JSON row data
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.SQLExecutor = exports.SQLParser = void 0;
14
+ // Copyright 2025 Sushanth (https://github.com/sushanthpy)
15
+ //
16
+ // Licensed under the Apache License, Version 2.0 (the "License");
17
+ // you may not use this file except in compliance with the License.
18
+ // You may obtain a copy of the License at
19
+ //
20
+ // http://www.apache.org/licenses/LICENSE-2.0
21
+ const uuid_1 = require("uuid");
22
+ /**
23
+ * Simple SQL parser for DDL and DML operations.
24
+ */
25
+ class SQLParser {
26
+ /**
27
+ * Parse a SQL statement.
28
+ */
29
+ static parse(sql) {
30
+ sql = sql.trim();
31
+ const upper = sql.toUpperCase();
32
+ if (upper.startsWith('CREATE TABLE')) {
33
+ return SQLParser.parseCreateTable(sql);
34
+ }
35
+ else if (upper.startsWith('CREATE INDEX')) {
36
+ return SQLParser.parseCreateIndex(sql);
37
+ }
38
+ else if (upper.startsWith('DROP TABLE')) {
39
+ return SQLParser.parseDropTable(sql);
40
+ }
41
+ else if (upper.startsWith('DROP INDEX')) {
42
+ return SQLParser.parseDropIndex(sql);
43
+ }
44
+ else if (upper.startsWith('INSERT')) {
45
+ return SQLParser.parseInsert(sql);
46
+ }
47
+ else if (upper.startsWith('SELECT')) {
48
+ return SQLParser.parseSelect(sql);
49
+ }
50
+ else if (upper.startsWith('UPDATE')) {
51
+ return SQLParser.parseUpdate(sql);
52
+ }
53
+ else if (upper.startsWith('DELETE')) {
54
+ return SQLParser.parseDelete(sql);
55
+ }
56
+ else {
57
+ throw new Error(`Unsupported SQL statement: ${sql.substring(0, 50)}`);
58
+ }
59
+ }
60
+ static parseCreateTable(sql) {
61
+ const match = sql.match(/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(\w+)\s*\((.*)\)/is);
62
+ if (!match) {
63
+ throw new Error(`Invalid CREATE TABLE: ${sql}`);
64
+ }
65
+ const tableName = match[1];
66
+ const colsStr = match[2];
67
+ const columns = [];
68
+ let primaryKey;
69
+ const colDefs = SQLParser.splitColumns(colsStr);
70
+ for (const colDef of colDefs) {
71
+ const trimmed = colDef.trim();
72
+ if (!trimmed)
73
+ continue;
74
+ // Check for PRIMARY KEY constraint
75
+ if (trimmed.toUpperCase().startsWith('PRIMARY KEY')) {
76
+ const pkMatch = trimmed.match(/PRIMARY\s+KEY\s*\((\w+)\)/i);
77
+ if (pkMatch) {
78
+ primaryKey = pkMatch[1];
79
+ }
80
+ continue;
81
+ }
82
+ // Parse column: name TYPE [PRIMARY KEY] [NOT NULL] [DEFAULT value]
83
+ const parts = trimmed.split(/\s+/);
84
+ if (parts.length < 2)
85
+ continue;
86
+ const colName = parts[0];
87
+ let colType = parts[1].toUpperCase();
88
+ // Normalize types
89
+ if (['INTEGER', 'INT', 'BIGINT', 'SMALLINT'].includes(colType)) {
90
+ colType = 'INT';
91
+ }
92
+ else if (['VARCHAR', 'CHAR', 'STRING', 'TEXT'].includes(colType)) {
93
+ colType = 'TEXT';
94
+ }
95
+ else if (['REAL', 'DOUBLE', 'FLOAT', 'DECIMAL', 'NUMERIC'].includes(colType)) {
96
+ colType = 'FLOAT';
97
+ }
98
+ else if (['BOOLEAN', 'BOOL'].includes(colType)) {
99
+ colType = 'BOOL';
100
+ }
101
+ else if (['BLOB', 'BYTES', 'BINARY'].includes(colType)) {
102
+ colType = 'BLOB';
103
+ }
104
+ const colUpper = trimmed.toUpperCase();
105
+ const isPk = colUpper.includes('PRIMARY KEY');
106
+ const nullable = !colUpper.includes('NOT NULL');
107
+ if (isPk) {
108
+ primaryKey = colName;
109
+ }
110
+ columns.push({
111
+ name: colName,
112
+ type: colType,
113
+ nullable,
114
+ primaryKey: isPk,
115
+ });
116
+ }
117
+ return {
118
+ operation: 'CREATE_TABLE',
119
+ data: { table: tableName, columns, primaryKey },
120
+ };
121
+ }
122
+ static splitColumns(colsStr) {
123
+ const result = [];
124
+ let current = '';
125
+ let depth = 0;
126
+ for (const char of colsStr) {
127
+ if (char === '(') {
128
+ depth++;
129
+ current += char;
130
+ }
131
+ else if (char === ')') {
132
+ depth--;
133
+ current += char;
134
+ }
135
+ else if (char === ',' && depth === 0) {
136
+ result.push(current);
137
+ current = '';
138
+ }
139
+ else {
140
+ current += char;
141
+ }
142
+ }
143
+ if (current.trim()) {
144
+ result.push(current);
145
+ }
146
+ return result;
147
+ }
148
+ static parseDropTable(sql) {
149
+ const match = sql.match(/DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?(\w+)/i);
150
+ if (!match) {
151
+ throw new Error(`Invalid DROP TABLE: ${sql}`);
152
+ }
153
+ return { operation: 'DROP_TABLE', data: { table: match[1] } };
154
+ }
155
+ static parseCreateIndex(sql) {
156
+ // CREATE INDEX idx_name ON table_name(column_name)
157
+ const match = sql.match(/CREATE\s+INDEX\s+(\w+)\s+ON\s+(\w+)\s*\(\s*(\w+)\s*\)/i);
158
+ if (!match) {
159
+ throw new Error(`Invalid CREATE INDEX syntax: ${sql}`);
160
+ }
161
+ return {
162
+ operation: 'CREATE_INDEX',
163
+ data: {
164
+ indexName: match[1],
165
+ table: match[2],
166
+ column: match[3],
167
+ },
168
+ };
169
+ }
170
+ static parseDropIndex(sql) {
171
+ // DROP INDEX idx_name ON table_name
172
+ const match = sql.match(/DROP\s+INDEX\s+(\w+)\s+ON\s+(\w+)/i);
173
+ if (!match) {
174
+ throw new Error(`Invalid DROP INDEX syntax: ${sql}`);
175
+ }
176
+ return {
177
+ operation: 'DROP_INDEX',
178
+ data: {
179
+ indexName: match[1],
180
+ table: match[2],
181
+ },
182
+ };
183
+ }
184
+ static parseInsert(sql) {
185
+ // INSERT INTO table (col1, col2) VALUES (val1, val2)
186
+ let match = sql.match(/INSERT\s+INTO\s+(\w+)\s*\(([^)]+)\)\s*VALUES\s*\((.+)\)/is);
187
+ if (match) {
188
+ const table = match[1];
189
+ const columns = match[2].split(',').map((c) => c.trim());
190
+ const values = SQLParser.parseValues(match[3]);
191
+ return { operation: 'INSERT', data: { table, columns, values } };
192
+ }
193
+ // INSERT INTO table VALUES (val1, val2)
194
+ match = sql.match(/INSERT\s+INTO\s+(\w+)\s+VALUES\s*\((.+)\)/is);
195
+ if (match) {
196
+ const table = match[1];
197
+ const values = SQLParser.parseValues(match[2]);
198
+ return { operation: 'INSERT', data: { table, columns: null, values } };
199
+ }
200
+ throw new Error(`Invalid INSERT: ${sql}`);
201
+ }
202
+ static parseValues(valuesStr) {
203
+ const values = [];
204
+ let current = '';
205
+ let inString = false;
206
+ let stringChar = null;
207
+ for (const char of valuesStr) {
208
+ if ((char === '"' || char === "'") && !inString) {
209
+ inString = true;
210
+ stringChar = char;
211
+ current += char;
212
+ }
213
+ else if (char === stringChar && inString) {
214
+ inString = false;
215
+ stringChar = null;
216
+ current += char;
217
+ }
218
+ else if (char === ',' && !inString) {
219
+ values.push(SQLParser.parseValue(current.trim()));
220
+ current = '';
221
+ }
222
+ else {
223
+ current += char;
224
+ }
225
+ }
226
+ if (current.trim()) {
227
+ values.push(SQLParser.parseValue(current.trim()));
228
+ }
229
+ return values;
230
+ }
231
+ static parseValue(valStr) {
232
+ if (!valStr || valStr.toUpperCase() === 'NULL') {
233
+ return null;
234
+ }
235
+ // String literals
236
+ if ((valStr.startsWith("'") && valStr.endsWith("'")) ||
237
+ (valStr.startsWith('"') && valStr.endsWith('"'))) {
238
+ return valStr.slice(1, -1);
239
+ }
240
+ // Boolean
241
+ if (valStr.toUpperCase() === 'TRUE')
242
+ return true;
243
+ if (valStr.toUpperCase() === 'FALSE')
244
+ return false;
245
+ // Numbers
246
+ if (valStr.includes('.')) {
247
+ const num = parseFloat(valStr);
248
+ if (!isNaN(num))
249
+ return num;
250
+ }
251
+ const intVal = parseInt(valStr, 10);
252
+ if (!isNaN(intVal))
253
+ return intVal;
254
+ return valStr;
255
+ }
256
+ static parseSelect(sql) {
257
+ // Extract table name first
258
+ const tableMatch = sql.match(/FROM\s+(\w+)/i);
259
+ if (!tableMatch) {
260
+ throw new Error(`Invalid SELECT: ${sql}`);
261
+ }
262
+ const table = tableMatch[1];
263
+ // Extract columns
264
+ const colsMatch = sql.match(/SELECT\s+(.+?)\s+FROM/is);
265
+ let columns = ['*'];
266
+ if (colsMatch) {
267
+ const colsStr = colsMatch[1].trim();
268
+ columns = colsStr === '*' ? ['*'] : colsStr.split(',').map((c) => c.trim());
269
+ }
270
+ // Extract WHERE clause
271
+ let conditions = [];
272
+ const whereMatch = sql.match(/WHERE\s+(.+?)(?:\s+ORDER|\s+LIMIT|\s+OFFSET|$)/is);
273
+ if (whereMatch) {
274
+ conditions = SQLParser.parseWhere(whereMatch[1]);
275
+ }
276
+ // Extract ORDER BY
277
+ let orderBy = [];
278
+ const orderMatch = sql.match(/ORDER\s+BY\s+(.+?)(?:\s+LIMIT|\s+OFFSET|$)/i);
279
+ if (orderMatch) {
280
+ for (const part of orderMatch[1].split(',')) {
281
+ const trimmed = part.trim();
282
+ if (trimmed.toUpperCase().endsWith(' DESC')) {
283
+ orderBy.push([trimmed.slice(0, -5).trim(), 'DESC']);
284
+ }
285
+ else if (trimmed.toUpperCase().endsWith(' ASC')) {
286
+ orderBy.push([trimmed.slice(0, -4).trim(), 'ASC']);
287
+ }
288
+ else {
289
+ orderBy.push([trimmed, 'ASC']);
290
+ }
291
+ }
292
+ }
293
+ // Extract LIMIT
294
+ let limit;
295
+ const limitMatch = sql.match(/LIMIT\s+(\d+)/i);
296
+ if (limitMatch) {
297
+ limit = parseInt(limitMatch[1], 10);
298
+ }
299
+ // Extract OFFSET
300
+ let offset;
301
+ const offsetMatch = sql.match(/OFFSET\s+(\d+)/i);
302
+ if (offsetMatch) {
303
+ offset = parseInt(offsetMatch[1], 10);
304
+ }
305
+ return {
306
+ operation: 'SELECT',
307
+ data: { table, columns, where: conditions, orderBy, limit, offset },
308
+ };
309
+ }
310
+ static parseWhere(whereClause) {
311
+ const conditions = [];
312
+ const parts = whereClause.split(/\s+AND\s+/i);
313
+ for (const part of parts) {
314
+ const match = part.match(/(\w+)\s*(=|!=|<>|>=|<=|>|<|LIKE|NOT\s+LIKE)\s*(.+)/i);
315
+ if (match) {
316
+ const col = match[1];
317
+ let op = match[2].toUpperCase().replace(/\s+/g, '_');
318
+ if (op === '<>')
319
+ op = '!=';
320
+ const val = SQLParser.parseValue(match[3].trim());
321
+ conditions.push([col, op, val]);
322
+ }
323
+ }
324
+ return conditions;
325
+ }
326
+ static parseUpdate(sql) {
327
+ const match = sql.match(/UPDATE\s+(\w+)\s+SET\s+(.+?)(?:\s+WHERE\s+(.+))?$/is);
328
+ if (!match) {
329
+ throw new Error(`Invalid UPDATE: ${sql}`);
330
+ }
331
+ const table = match[1];
332
+ const setClause = match[2];
333
+ const whereClause = match[3];
334
+ // Parse SET clause
335
+ const updates = {};
336
+ for (const part of setClause.split(',')) {
337
+ const eqMatch = part.match(/\s*(\w+)\s*=\s*(.+)\s*/);
338
+ if (eqMatch) {
339
+ updates[eqMatch[1]] = SQLParser.parseValue(eqMatch[2].trim());
340
+ }
341
+ }
342
+ let conditions = [];
343
+ if (whereClause) {
344
+ conditions = SQLParser.parseWhere(whereClause);
345
+ }
346
+ return { operation: 'UPDATE', data: { table, updates, where: conditions } };
347
+ }
348
+ static parseDelete(sql) {
349
+ const match = sql.match(/DELETE\s+FROM\s+(\w+)(?:\s+WHERE\s+(.+))?$/is);
350
+ if (!match) {
351
+ throw new Error(`Invalid DELETE: ${sql}`);
352
+ }
353
+ const table = match[1];
354
+ let conditions = [];
355
+ if (match[2]) {
356
+ conditions = SQLParser.parseWhere(match[2]);
357
+ }
358
+ return { operation: 'DELETE', data: { table, where: conditions } };
359
+ }
360
+ }
361
+ exports.SQLParser = SQLParser;
362
+ /**
363
+ * SQL Executor that operates on a KV database.
364
+ */
365
+ class SQLExecutor {
366
+ db;
367
+ // Key prefixes for SQL data
368
+ TABLE_PREFIX = '_sql/tables/';
369
+ SCHEMA_SUFFIX = '/schema';
370
+ ROWS_PREFIX = '/rows/';
371
+ INDEX_PREFIX = '/indexes/';
372
+ constructor(db) {
373
+ this.db = db;
374
+ }
375
+ /**
376
+ * Execute a SQL statement.
377
+ */
378
+ async execute(sql) {
379
+ const { operation, data } = SQLParser.parse(sql);
380
+ switch (operation) {
381
+ case 'CREATE_TABLE':
382
+ return this.createTable(data);
383
+ case 'DROP_TABLE':
384
+ return this.dropTable(data);
385
+ case 'CREATE_INDEX':
386
+ return this.createIndex(data);
387
+ case 'DROP_INDEX':
388
+ return this.dropIndex(data);
389
+ case 'INSERT':
390
+ return this.insert(data);
391
+ case 'SELECT':
392
+ return this.select(data);
393
+ case 'UPDATE':
394
+ return this.update(data);
395
+ case 'DELETE':
396
+ return this.deleteRows(data);
397
+ default:
398
+ throw new Error(`Unknown operation: ${operation}`);
399
+ }
400
+ }
401
+ schemaKey(table) {
402
+ return this.TABLE_PREFIX + table + this.SCHEMA_SUFFIX;
403
+ }
404
+ rowKey(table, rowId) {
405
+ return this.TABLE_PREFIX + table + this.ROWS_PREFIX + rowId;
406
+ }
407
+ rowPrefix(table) {
408
+ return this.TABLE_PREFIX + table + this.ROWS_PREFIX;
409
+ }
410
+ indexMetaKey(table, indexName) {
411
+ return this.TABLE_PREFIX + table + this.INDEX_PREFIX + indexName + '/meta';
412
+ }
413
+ indexPrefix(table, indexName) {
414
+ return this.TABLE_PREFIX + table + this.INDEX_PREFIX + indexName + '/';
415
+ }
416
+ indexKey(table, indexName, columnValue, rowId) {
417
+ return this.TABLE_PREFIX + table + this.INDEX_PREFIX + indexName + '/' + columnValue + '/' + rowId;
418
+ }
419
+ indexValuePrefix(table, indexName, columnValue) {
420
+ return this.TABLE_PREFIX + table + this.INDEX_PREFIX + indexName + '/' + columnValue + '/';
421
+ }
422
+ async getSchema(table) {
423
+ const data = await this.db.get(this.schemaKey(table));
424
+ if (!data)
425
+ return null;
426
+ return JSON.parse(data.toString());
427
+ }
428
+ async getIndexes(table) {
429
+ // Returns map of index_name -> column_name
430
+ const indexes = {};
431
+ const prefix = this.TABLE_PREFIX + table + this.INDEX_PREFIX;
432
+ const pairs = await this.db.scan(prefix);
433
+ for (const { key, value } of pairs) {
434
+ const keyStr = key.toString();
435
+ if (keyStr.endsWith('/meta')) {
436
+ const info = JSON.parse(value.toString());
437
+ const parts = keyStr.split('/');
438
+ if (parts.length >= 5) {
439
+ const indexName = parts[parts.length - 2];
440
+ indexes[indexName] = info.column;
441
+ }
442
+ }
443
+ }
444
+ return indexes;
445
+ }
446
+ async hasIndexForColumn(table, column) {
447
+ const indexes = await this.getIndexes(table);
448
+ for (const [indexName, indexCol] of Object.entries(indexes)) {
449
+ if (indexCol === column) {
450
+ return { has: true, name: indexName };
451
+ }
452
+ }
453
+ return { has: false, name: '' };
454
+ }
455
+ async lookupByIndex(table, indexName, value) {
456
+ const prefix = this.indexValuePrefix(table, indexName, value);
457
+ const pairs = await this.db.scan(prefix);
458
+ return pairs.map(p => p.value.toString());
459
+ }
460
+ async updateIndex(table, indexName, column, oldRow, newRow, rowId) {
461
+ const oldVal = oldRow[column];
462
+ const newVal = newRow[column];
463
+ if (oldVal === newVal) {
464
+ return;
465
+ }
466
+ // Remove old index entry
467
+ if (oldVal != null) {
468
+ const oldKey = this.indexKey(table, indexName, String(oldVal), rowId);
469
+ await this.db.delete(oldKey);
470
+ }
471
+ // Add new index entry
472
+ if (newVal != null) {
473
+ const newKey = this.indexKey(table, indexName, String(newVal), rowId);
474
+ await this.db.put(newKey, rowId);
475
+ }
476
+ }
477
+ findIndexedEqualityCondition(table, conditions, indexes) {
478
+ for (const [col, op, val] of conditions) {
479
+ if (op === '=' && Object.values(indexes).includes(col)) {
480
+ return [col, val];
481
+ }
482
+ }
483
+ return null;
484
+ }
485
+ async createTable(data) {
486
+ const table = data.table;
487
+ const columns = data.columns;
488
+ const primaryKey = data.primaryKey;
489
+ // Check if table exists
490
+ if (await this.getSchema(table)) {
491
+ throw new Error(`Table '${table}' already exists`);
492
+ }
493
+ const schema = { name: table, columns, primaryKey };
494
+ await this.db.put(this.schemaKey(table), JSON.stringify(schema));
495
+ return { rows: [], columns: [], rowsAffected: 0 };
496
+ }
497
+ async dropTable(data) {
498
+ const table = data.table;
499
+ // Delete all indexes first
500
+ const indexes = await this.getIndexes(table);
501
+ for (const indexName of Object.keys(indexes)) {
502
+ const idxPrefix = this.indexPrefix(table, indexName);
503
+ const idxPairs = await this.db.scan(idxPrefix);
504
+ for (const { key } of idxPairs) {
505
+ await this.db.delete(key);
506
+ }
507
+ await this.db.delete(this.indexMetaKey(table, indexName));
508
+ }
509
+ // Delete all rows
510
+ const prefix = this.rowPrefix(table);
511
+ const rows = await this.db.scan(prefix);
512
+ let rowsDeleted = 0;
513
+ for (const { key } of rows) {
514
+ await this.db.delete(key);
515
+ rowsDeleted++;
516
+ }
517
+ // Delete schema
518
+ await this.db.delete(this.schemaKey(table));
519
+ return { rows: [], columns: [], rowsAffected: rowsDeleted };
520
+ }
521
+ async createIndex(data) {
522
+ const indexName = data.indexName;
523
+ const table = data.table;
524
+ const column = data.column;
525
+ const schema = await this.getSchema(table);
526
+ if (!schema) {
527
+ throw new Error(`Table '${table}' does not exist`);
528
+ }
529
+ // Check column exists
530
+ if (!schema.columns.some(c => c.name === column)) {
531
+ throw new Error(`Column '${column}' does not exist in table '${table}'`);
532
+ }
533
+ // Check index doesn't already exist
534
+ const metaKey = this.indexMetaKey(table, indexName);
535
+ const existing = await this.db.get(metaKey);
536
+ if (existing) {
537
+ throw new Error(`Index '${indexName}' already exists on table '${table}'`);
538
+ }
539
+ // Store index metadata
540
+ const meta = { column, table };
541
+ await this.db.put(metaKey, JSON.stringify(meta));
542
+ // Build index from existing rows
543
+ const prefix = this.rowPrefix(table);
544
+ const pairs = await this.db.scan(prefix);
545
+ let indexedCount = 0;
546
+ for (const { value } of pairs) {
547
+ const row = JSON.parse(value.toString());
548
+ const rowId = row['_id'];
549
+ const colValue = row[column];
550
+ if (colValue != null) {
551
+ const idxKey = this.indexKey(table, indexName, String(colValue), rowId);
552
+ await this.db.put(idxKey, rowId);
553
+ indexedCount++;
554
+ }
555
+ }
556
+ return { rows: [], columns: [], rowsAffected: indexedCount };
557
+ }
558
+ async dropIndex(data) {
559
+ const indexName = data.indexName;
560
+ const table = data.table;
561
+ // Delete all index entries
562
+ const idxPrefix = this.indexPrefix(table, indexName);
563
+ const pairs = await this.db.scan(idxPrefix);
564
+ let deleted = 0;
565
+ for (const { key } of pairs) {
566
+ await this.db.delete(key);
567
+ deleted++;
568
+ }
569
+ // Delete index metadata
570
+ await this.db.delete(this.indexMetaKey(table, indexName));
571
+ return { rows: [], columns: [], rowsAffected: deleted };
572
+ }
573
+ async insert(data) {
574
+ const table = data.table;
575
+ let columns = data.columns;
576
+ const values = data.values;
577
+ const schema = await this.getSchema(table);
578
+ if (!schema) {
579
+ throw new Error(`Table '${table}' does not exist`);
580
+ }
581
+ // If no columns specified, use schema order
582
+ if (!columns) {
583
+ columns = schema.columns.map((c) => c.name);
584
+ }
585
+ if (columns.length !== values.length) {
586
+ throw new Error(`Column count (${columns.length}) doesn't match value count (${values.length})`);
587
+ }
588
+ // Create row object
589
+ const row = {};
590
+ for (let i = 0; i < columns.length; i++) {
591
+ row[columns[i]] = values[i];
592
+ }
593
+ // Generate row ID
594
+ let rowId;
595
+ if (schema.primaryKey && schema.primaryKey in row) {
596
+ rowId = String(row[schema.primaryKey]);
597
+ }
598
+ else {
599
+ rowId = (0, uuid_1.v4)();
600
+ }
601
+ row['_id'] = rowId;
602
+ await this.db.put(this.rowKey(table, rowId), JSON.stringify(row));
603
+ // Maintain indexes
604
+ const indexes = await this.getIndexes(table);
605
+ for (const [indexName, indexCol] of Object.entries(indexes)) {
606
+ if (row[indexCol] != null) {
607
+ const idxKey = this.indexKey(table, indexName, String(row[indexCol]), rowId);
608
+ await this.db.put(idxKey, rowId);
609
+ }
610
+ }
611
+ return { rows: [], columns: [], rowsAffected: 1 };
612
+ }
613
+ async select(data) {
614
+ const table = data.table;
615
+ let columns = data.columns;
616
+ const conditions = data.where;
617
+ const orderBy = data.orderBy;
618
+ const limit = data.limit;
619
+ const offset = data.offset;
620
+ const schema = await this.getSchema(table);
621
+ if (!schema) {
622
+ throw new Error(`Table '${table}' does not exist`);
623
+ }
624
+ // Get column names
625
+ if (columns.length === 1 && columns[0] === '*') {
626
+ columns = schema.columns.map((c) => c.name);
627
+ }
628
+ // Scan all rows
629
+ const prefix = this.rowPrefix(table);
630
+ const scanResults = await this.db.scan(prefix);
631
+ let rows = [];
632
+ for (const { value } of scanResults) {
633
+ const row = JSON.parse(value.toString());
634
+ // Apply WHERE conditions
635
+ if (this.matchesConditions(row, conditions)) {
636
+ // Project columns
637
+ const projected = {};
638
+ for (const col of columns) {
639
+ if (col in row) {
640
+ projected[col] = row[col];
641
+ }
642
+ }
643
+ rows.push(projected);
644
+ }
645
+ }
646
+ // Apply ORDER BY
647
+ if (orderBy && orderBy.length > 0) {
648
+ rows.sort((a, b) => {
649
+ for (const [col, direction] of orderBy) {
650
+ const aVal = a[col];
651
+ const bVal = b[col];
652
+ // Handle nulls
653
+ if (aVal === null || aVal === undefined)
654
+ return 1;
655
+ if (bVal === null || bVal === undefined)
656
+ return -1;
657
+ let cmp = 0;
658
+ if (aVal < bVal)
659
+ cmp = -1;
660
+ else if (aVal > bVal)
661
+ cmp = 1;
662
+ if (direction === 'DESC')
663
+ cmp = -cmp;
664
+ if (cmp !== 0)
665
+ return cmp;
666
+ }
667
+ return 0;
668
+ });
669
+ }
670
+ // Apply OFFSET and LIMIT
671
+ if (offset && offset > 0) {
672
+ rows = rows.slice(offset);
673
+ }
674
+ if (limit !== undefined && limit > 0) {
675
+ rows = rows.slice(0, limit);
676
+ }
677
+ return { rows, columns, rowsAffected: 0 };
678
+ }
679
+ matchesConditions(row, conditions) {
680
+ for (const [col, op, val] of conditions) {
681
+ const rowVal = row[col];
682
+ switch (op) {
683
+ case '=':
684
+ if (rowVal !== val)
685
+ return false;
686
+ break;
687
+ case '!=':
688
+ if (rowVal === val)
689
+ return false;
690
+ break;
691
+ case '>':
692
+ if (rowVal === null || rowVal === undefined || rowVal <= val)
693
+ return false;
694
+ break;
695
+ case '>=':
696
+ if (rowVal === null || rowVal === undefined || rowVal < val)
697
+ return false;
698
+ break;
699
+ case '<':
700
+ if (rowVal === null || rowVal === undefined || rowVal >= val)
701
+ return false;
702
+ break;
703
+ case '<=':
704
+ if (rowVal === null || rowVal === undefined || rowVal > val)
705
+ return false;
706
+ break;
707
+ case 'LIKE': {
708
+ if (rowVal === null || rowVal === undefined)
709
+ return false;
710
+ const pattern = String(val).replace(/%/g, '.*').replace(/_/g, '.');
711
+ if (!new RegExp(`^${pattern}$`, 'i').test(String(rowVal)))
712
+ return false;
713
+ break;
714
+ }
715
+ case 'NOT_LIKE': {
716
+ if (rowVal === null || rowVal === undefined)
717
+ return true;
718
+ const pattern = String(val).replace(/%/g, '.*').replace(/_/g, '.');
719
+ if (new RegExp(`^${pattern}$`, 'i').test(String(rowVal)))
720
+ return false;
721
+ break;
722
+ }
723
+ }
724
+ }
725
+ return true;
726
+ }
727
+ async update(data) {
728
+ const table = data.table;
729
+ const updates = data.updates;
730
+ const conditions = data.where;
731
+ const schema = await this.getSchema(table);
732
+ if (!schema) {
733
+ throw new Error(`Table '${table}' does not exist`);
734
+ }
735
+ const indexes = await this.getIndexes(table);
736
+ let rowsAffected = 0;
737
+ // Try index-accelerated path
738
+ const indexedCond = this.findIndexedEqualityCondition(table, conditions, indexes);
739
+ if (indexedCond) {
740
+ // Index-accelerated UPDATE
741
+ const [col, val] = indexedCond;
742
+ const indexResult = await this.hasIndexForColumn(table, col);
743
+ if (indexResult.has) {
744
+ const rowIds = await this.lookupByIndex(table, indexResult.name, String(val));
745
+ for (const rowId of rowIds) {
746
+ const key = this.rowKey(table, rowId);
747
+ const value = await this.db.get(key);
748
+ if (!value)
749
+ continue;
750
+ const oldRow = JSON.parse(value.toString());
751
+ // Apply all WHERE conditions (not just the indexed one)
752
+ if (!this.matchesConditions(oldRow, conditions)) {
753
+ continue;
754
+ }
755
+ // Apply updates
756
+ const newRow = { ...oldRow };
757
+ for (const [ucol, uval] of Object.entries(updates)) {
758
+ newRow[ucol] = uval;
759
+ }
760
+ // Update indexes for changed columns
761
+ for (const [idxName, idxCol] of Object.entries(indexes)) {
762
+ if (idxCol in updates) {
763
+ await this.updateIndex(table, idxName, idxCol, oldRow, newRow, rowId);
764
+ }
765
+ }
766
+ await this.db.put(key, JSON.stringify(newRow));
767
+ rowsAffected++;
768
+ }
769
+ }
770
+ }
771
+ else {
772
+ // Fallback: full table scan
773
+ const prefix = this.rowPrefix(table);
774
+ const scanResults = await this.db.scan(prefix);
775
+ for (const { key, value } of scanResults) {
776
+ const oldRow = JSON.parse(value.toString());
777
+ // Apply WHERE conditions
778
+ if (this.matchesConditions(oldRow, conditions)) {
779
+ // Apply updates
780
+ const newRow = { ...oldRow };
781
+ for (const [col, val] of Object.entries(updates)) {
782
+ newRow[col] = val;
783
+ }
784
+ const rowId = oldRow['_id'];
785
+ // Update indexes for changed columns
786
+ for (const [idxName, idxCol] of Object.entries(indexes)) {
787
+ if (idxCol in updates) {
788
+ await this.updateIndex(table, idxName, idxCol, oldRow, newRow, rowId);
789
+ }
790
+ }
791
+ await this.db.put(key, JSON.stringify(newRow));
792
+ rowsAffected++;
793
+ }
794
+ }
795
+ }
796
+ return { rows: [], columns: [], rowsAffected };
797
+ }
798
+ async deleteRows(data) {
799
+ const table = data.table;
800
+ const conditions = data.where;
801
+ const schema = await this.getSchema(table);
802
+ if (!schema) {
803
+ throw new Error(`Table '${table}' does not exist`);
804
+ }
805
+ const indexes = await this.getIndexes(table);
806
+ let rowsAffected = 0;
807
+ // Try index-accelerated path
808
+ const indexedCond = this.findIndexedEqualityCondition(table, conditions, indexes);
809
+ if (indexedCond) {
810
+ // Index-accelerated DELETE
811
+ const [col, val] = indexedCond;
812
+ const indexResult = await this.hasIndexForColumn(table, col);
813
+ if (indexResult.has) {
814
+ const rowIds = await this.lookupByIndex(table, indexResult.name, String(val));
815
+ const keysToDelete = [];
816
+ const rowsToDelete = [];
817
+ for (const rowId of rowIds) {
818
+ const key = this.rowKey(table, rowId);
819
+ const value = await this.db.get(key);
820
+ if (!value)
821
+ continue;
822
+ const row = JSON.parse(value.toString());
823
+ // Apply all WHERE conditions (not just the indexed one)
824
+ if (this.matchesConditions(row, conditions)) {
825
+ keysToDelete.push(Buffer.from(key));
826
+ rowsToDelete.push({ row, rowId });
827
+ }
828
+ }
829
+ // Delete rows and update indexes
830
+ for (let i = 0; i < keysToDelete.length; i++) {
831
+ const key = keysToDelete[i];
832
+ const { row, rowId } = rowsToDelete[i];
833
+ // Remove from all indexes
834
+ for (const [idxName, idxCol] of Object.entries(indexes)) {
835
+ const emptyRow = {};
836
+ await this.updateIndex(table, idxName, idxCol, row, emptyRow, rowId);
837
+ }
838
+ await this.db.delete(key);
839
+ rowsAffected++;
840
+ }
841
+ }
842
+ }
843
+ else {
844
+ // Fallback: full table scan
845
+ const prefix = this.rowPrefix(table);
846
+ const scanResults = await this.db.scan(prefix);
847
+ const keysToDelete = [];
848
+ const rowsToDelete = [];
849
+ for (const { key, value } of scanResults) {
850
+ const row = JSON.parse(value.toString());
851
+ // Apply WHERE conditions
852
+ if (this.matchesConditions(row, conditions)) {
853
+ const rowId = row['_id'];
854
+ keysToDelete.push(key);
855
+ rowsToDelete.push({ row, rowId });
856
+ }
857
+ }
858
+ // Delete collected rows and update indexes
859
+ for (let i = 0; i < keysToDelete.length; i++) {
860
+ const key = keysToDelete[i];
861
+ const { row, rowId } = rowsToDelete[i];
862
+ // Remove from all indexes
863
+ for (const [idxName, idxCol] of Object.entries(indexes)) {
864
+ const emptyRow = {};
865
+ await this.updateIndex(table, idxName, idxCol, row, emptyRow, rowId);
866
+ }
867
+ await this.db.delete(key);
868
+ rowsAffected++;
869
+ }
870
+ }
871
+ return { rows: [], columns: [], rowsAffected };
872
+ }
873
+ }
874
+ exports.SQLExecutor = SQLExecutor;
875
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3FsLWVuZ2luZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zcWwtZW5naW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7O0dBU0c7OztBQUVILDBEQUEwRDtBQUMxRCxFQUFFO0FBQ0Ysa0VBQWtFO0FBQ2xFLG1FQUFtRTtBQUNuRSwwQ0FBMEM7QUFDMUMsRUFBRTtBQUNGLGlEQUFpRDtBQUVqRCwrQkFBb0M7QUFrRHBDOztHQUVHO0FBQ0gsTUFBYSxTQUFTO0lBQ3BCOztPQUVHO0lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFXO1FBQ3RCLEdBQUcsR0FBRyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDakIsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBRWhDLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO1lBQ3JDLE9BQU8sU0FBUyxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3pDLENBQUM7YUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztZQUM1QyxPQUFPLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN6QyxDQUFDO2FBQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7WUFDMUMsT0FBTyxTQUFTLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7YUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUMxQyxPQUFPLFNBQVMsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkMsQ0FBQzthQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ3RDLE9BQU8sU0FBUyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNwQyxDQUFDO2FBQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDdEMsT0FBTyxTQUFTLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3BDLENBQUM7YUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztZQUN0QyxPQUFPLFNBQVMsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEMsQ0FBQzthQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ3RDLE9BQU8sU0FBUyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNwQyxDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN4RSxDQUFDO0lBQ0gsQ0FBQztJQUVPLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFXO1FBQ3pDLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQ3JCLDhEQUE4RCxDQUMvRCxDQUFDO1FBQ0YsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNsRCxDQUFDO1FBRUQsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNCLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN6QixNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7UUFDN0IsSUFBSSxVQUE4QixDQUFDO1FBRW5DLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFaEQsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUM3QixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDLE9BQU87Z0JBQUUsU0FBUztZQUV2QixtQ0FBbUM7WUFDbkMsSUFBSSxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUM7Z0JBQ3BELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsNEJBQTRCLENBQUMsQ0FBQztnQkFDNUQsSUFBSSxPQUFPLEVBQUUsQ0FBQztvQkFDWixVQUFVLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUMxQixDQUFDO2dCQUNELFNBQVM7WUFDWCxDQUFDO1lBRUQsbUVBQW1FO1lBQ25FLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbkMsSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUM7Z0JBQUUsU0FBUztZQUUvQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDekIsSUFBSSxPQUFPLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBRXJDLGtCQUFrQjtZQUNsQixJQUFJLENBQUMsU0FBUyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQy9ELE9BQU8sR0FBRyxLQUFLLENBQUM7WUFDbEIsQ0FBQztpQkFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ25FLE9BQU8sR0FBRyxNQUFNLENBQUM7WUFDbkIsQ0FBQztpQkFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUMvRSxPQUFPLEdBQUcsT0FBTyxDQUFDO1lBQ3BCLENBQUM7aUJBQU0sSUFBSSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDakQsT0FBTyxHQUFHLE1BQU0sQ0FBQztZQUNuQixDQUFDO2lCQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUN6RCxPQUFPLEdBQUcsTUFBTSxDQUFDO1lBQ25CLENBQUM7WUFFRCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDdkMsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUM5QyxNQUFNLFFBQVEsR0FBRyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7WUFFaEQsSUFBSSxJQUFJLEVBQUUsQ0FBQztnQkFDVCxVQUFVLEdBQUcsT0FBTyxDQUFDO1lBQ3ZCLENBQUM7WUFFRCxPQUFPLENBQUMsSUFBSSxDQUFDO2dCQUNYLElBQUksRUFBRSxPQUFPO2dCQUNiLElBQUksRUFBRSxPQUFPO2dCQUNiLFFBQVE7Z0JBQ1IsVUFBVSxFQUFFLElBQUk7YUFDakIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE9BQU87WUFDTCxTQUFTLEVBQUUsY0FBYztZQUN6QixJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUU7U0FDaEQsQ0FBQztJQUNKLENBQUM7SUFFTyxNQUFNLENBQUMsWUFBWSxDQUFDLE9BQWU7UUFDekMsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFDO1FBQzVCLElBQUksT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNqQixJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7UUFFZCxLQUFLLE1BQU0sSUFBSSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQzNCLElBQUksSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO2dCQUNqQixLQUFLLEVBQUUsQ0FBQztnQkFDUixPQUFPLElBQUksSUFBSSxDQUFDO1lBQ2xCLENBQUM7aUJBQU0sSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7Z0JBQ3hCLEtBQUssRUFBRSxDQUFDO2dCQUNSLE9BQU8sSUFBSSxJQUFJLENBQUM7WUFDbEIsQ0FBQztpQkFBTSxJQUFJLElBQUksS0FBSyxHQUFHLElBQUksS0FBSyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUN2QyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUNyQixPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2YsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE9BQU8sSUFBSSxJQUFJLENBQUM7WUFDbEIsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQ25CLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDdkIsQ0FBQztRQUVELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFTyxNQUFNLENBQUMsY0FBYyxDQUFDLEdBQVc7UUFDdkMsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO1FBQ3BFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDaEQsQ0FBQztRQUNELE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO0lBQ2hFLENBQUM7SUFFTyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsR0FBVztRQUN6QyxtREFBbUQ7UUFDbkQsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO1FBQ2xGLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0NBQWdDLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDekQsQ0FBQztRQUNELE9BQU87WUFDTCxTQUFTLEVBQUUsY0FBYztZQUN6QixJQUFJLEVBQUU7Z0JBQ0osU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7Z0JBQ25CLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUNmLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2FBQ2pCO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFTyxNQUFNLENBQUMsY0FBYyxDQUFDLEdBQVc7UUFDdkMsb0NBQW9DO1FBQ3BDLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUM5RCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZELENBQUM7UUFDRCxPQUFPO1lBQ0wsU0FBUyxFQUFFLFlBQVk7WUFDdkIsSUFBSSxFQUFFO2dCQUNKLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUNuQixLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQzthQUNoQjtTQUNGLENBQUM7SUFDSixDQUFDO0lBRU8sTUFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFXO1FBQ3BDLHFEQUFxRDtRQUNyRCxJQUFJLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUNuQiwyREFBMkQsQ0FDNUQsQ0FBQztRQUVGLElBQUksS0FBSyxFQUFFLENBQUM7WUFDVixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkIsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ3pELE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDL0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQ25FLENBQUM7UUFFRCx3Q0FBd0M7UUFDeEMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsNkNBQTZDLENBQUMsQ0FBQztRQUNqRSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1YsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3ZCLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDL0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQztRQUN6RSxDQUFDO1FBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQkFBbUIsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRU8sTUFBTSxDQUFDLFdBQVcsQ0FBQyxTQUFpQjtRQUMxQyxNQUFNLE1BQU0sR0FBVSxFQUFFLENBQUM7UUFDekIsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQztRQUNyQixJQUFJLFVBQVUsR0FBa0IsSUFBSSxDQUFDO1FBRXJDLEtBQUssTUFBTSxJQUFJLElBQUksU0FBUyxFQUFFLENBQUM7WUFDN0IsSUFBSSxDQUFDLElBQUksS0FBSyxHQUFHLElBQUksSUFBSSxLQUFLLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ2hELFFBQVEsR0FBRyxJQUFJLENBQUM7Z0JBQ2hCLFVBQVUsR0FBRyxJQUFJLENBQUM7Z0JBQ2xCLE9BQU8sSUFBSSxJQUFJLENBQUM7WUFDbEIsQ0FBQztpQkFBTSxJQUFJLElBQUksS0FBSyxVQUFVLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQzNDLFFBQVEsR0FBRyxLQUFLLENBQUM7Z0JBQ2pCLFVBQVUsR0FBRyxJQUFJLENBQUM7Z0JBQ2xCLE9BQU8sSUFBSSxJQUFJLENBQUM7WUFDbEIsQ0FBQztpQkFBTSxJQUFJLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDckMsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xELE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDZixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sT0FBTyxJQUFJLElBQUksQ0FBQztZQUNsQixDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7WUFDbkIsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDcEQsQ0FBQztRQUVELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFTyxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQWM7UUFDdEMsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsV0FBVyxFQUFFLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDL0MsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBRUQsa0JBQWtCO1FBQ2xCLElBQ0UsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDaEQsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsRUFDaEQsQ0FBQztZQUNELE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3QixDQUFDO1FBRUQsVUFBVTtRQUNWLElBQUksTUFBTSxDQUFDLFdBQVcsRUFBRSxLQUFLLE1BQU07WUFBRSxPQUFPLElBQUksQ0FBQztRQUNqRCxJQUFJLE1BQU0sQ0FBQyxXQUFXLEVBQUUsS0FBSyxPQUFPO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFFbkQsVUFBVTtRQUNWLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3pCLE1BQU0sR0FBRyxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMvQixJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQztnQkFBRSxPQUFPLEdBQUcsQ0FBQztRQUM5QixDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztZQUFFLE9BQU8sTUFBTSxDQUFDO1FBRWxDLE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFTyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQVc7UUFDcEMsMkJBQTJCO1FBQzNCLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDOUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsbUJBQW1CLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDNUMsQ0FBQztRQUNELE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUU1QixrQkFBa0I7UUFDbEIsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1FBQ3ZELElBQUksT0FBTyxHQUFhLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDOUIsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNkLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNwQyxPQUFPLEdBQUcsT0FBTyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzlFLENBQUM7UUFFRCx1QkFBdUI7UUFDdkIsSUFBSSxVQUFVLEdBQWlDLEVBQUUsQ0FBQztRQUNsRCxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLGtEQUFrRCxDQUFDLENBQUM7UUFDakYsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLFVBQVUsR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25ELENBQUM7UUFFRCxtQkFBbUI7UUFDbkIsSUFBSSxPQUFPLEdBQTRCLEVBQUUsQ0FBQztRQUMxQyxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7UUFDNUUsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLEtBQUssTUFBTSxJQUFJLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUM1QyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQzVCLElBQUksT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO29CQUM1QyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUN0RCxDQUFDO3FCQUFNLElBQUksT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO29CQUNsRCxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUNyRCxDQUFDO3FCQUFNLENBQUM7b0JBQ04sT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUNqQyxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCxnQkFBZ0I7UUFDaEIsSUFBSSxLQUF5QixDQUFDO1FBQzlCLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUMvQyxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ2YsS0FBSyxHQUFHLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDdEMsQ0FBQztRQUVELGlCQUFpQjtRQUNqQixJQUFJLE1BQTBCLENBQUM7UUFDL0IsTUFBTSxXQUFXLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ2pELElBQUksV0FBVyxFQUFFLENBQUM7WUFDaEIsTUFBTSxHQUFHLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDeEMsQ0FBQztRQUVELE9BQU87WUFDTCxTQUFTLEVBQUUsUUFBUTtZQUNuQixJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUU7U0FDcEUsQ0FBQztJQUNKLENBQUM7SUFFTyxNQUFNLENBQUMsVUFBVSxDQUFDLFdBQW1CO1FBQzNDLE1BQU0sVUFBVSxHQUFpQyxFQUFFLENBQUM7UUFDcEQsTUFBTSxLQUFLLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUU5QyxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ3pCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMscURBQXFELENBQUMsQ0FBQztZQUNoRixJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUNWLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDckIsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7Z0JBQ3JELElBQUksRUFBRSxLQUFLLElBQUk7b0JBQUUsRUFBRSxHQUFHLElBQUksQ0FBQztnQkFDM0IsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztnQkFDbEQsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUNsQyxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFFTyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQVc7UUFDcEMsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxxREFBcUQsQ0FBQyxDQUFDO1FBQy9FLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsbUJBQW1CLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDNUMsQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QixNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0IsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRTdCLG1CQUFtQjtRQUNuQixNQUFNLE9BQU8sR0FBd0IsRUFBRSxDQUFDO1FBQ3hDLEtBQUssTUFBTSxJQUFJLElBQUksU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3hDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztZQUNyRCxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ2hFLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxVQUFVLEdBQWlDLEVBQUUsQ0FBQztRQUNsRCxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ2hCLFVBQVUsR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2pELENBQUM7UUFFRCxPQUFPLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFBRSxDQUFDO0lBQzlFLENBQUM7SUFFTyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQVc7UUFDcEMsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1FBQ3hFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsbUJBQW1CLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDNUMsQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QixJQUFJLFVBQVUsR0FBaUMsRUFBRSxDQUFDO1FBQ2xELElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDYixVQUFVLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxDQUFDO1FBRUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFBRSxDQUFDO0lBQ3JFLENBQUM7Q0FDRjtBQTdXRCw4QkE2V0M7QUFZRDs7R0FFRztBQUNILE1BQWEsV0FBVztJQUNkLEVBQUUsQ0FBb0I7SUFFOUIsNEJBQTRCO0lBQ1gsWUFBWSxHQUFHLGNBQWMsQ0FBQztJQUM5QixhQUFhLEdBQUcsU0FBUyxDQUFDO0lBQzFCLFdBQVcsR0FBRyxRQUFRLENBQUM7SUFDdkIsWUFBWSxHQUFHLFdBQVcsQ0FBQztJQUU1QyxZQUFZLEVBQXFCO1FBQy9CLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBQ2YsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFXO1FBQ3ZCLE1BQU0sRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUVqRCxRQUFRLFNBQVMsRUFBRSxDQUFDO1lBQ2xCLEtBQUssY0FBYztnQkFDakIsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hDLEtBQUssWUFBWTtnQkFDZixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUIsS0FBSyxjQUFjO2dCQUNqQixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDaEMsS0FBSyxZQUFZO2dCQUNmLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM5QixLQUFLLFFBQVE7Z0JBQ1gsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNCLEtBQUssUUFBUTtnQkFDWCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDM0IsS0FBSyxRQUFRO2dCQUNYLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMzQixLQUFLLFFBQVE7Z0JBQ1gsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQy9CO2dCQUNFLE1BQU0sSUFBSSxLQUFLLENBQUMsc0JBQXNCLFNBQVMsRUFBRSxDQUFDLENBQUM7UUFDdkQsQ0FBQztJQUNILENBQUM7SUFFTyxTQUFTLENBQUMsS0FBYTtRQUM3QixPQUFPLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7SUFDeEQsQ0FBQztJQUVPLE1BQU0sQ0FBQyxLQUFhLEVBQUUsS0FBYTtRQUN6QyxPQUFPLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO0lBQzlELENBQUM7SUFFTyxTQUFTLENBQUMsS0FBYTtRQUM3QixPQUFPLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDdEQsQ0FBQztJQUVPLFlBQVksQ0FBQyxLQUFhLEVBQUUsU0FBaUI7UUFDbkQsT0FBTyxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxHQUFHLFNBQVMsR0FBRyxPQUFPLENBQUM7SUFDN0UsQ0FBQztJQUVPLFdBQVcsQ0FBQyxLQUFhLEVBQUUsU0FBaUI7UUFDbEQsT0FBTyxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxHQUFHLFNBQVMsR0FBRyxHQUFHLENBQUM7SUFDekUsQ0FBQztJQUVPLFFBQVEsQ0FBQyxLQUFhLEVBQUUsU0FBaUIsRUFBRSxXQUFtQixFQUFFLEtBQWE7UUFDbkYsT0FBTyxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxHQUFHLFNBQVMsR0FBRyxHQUFHLEdBQUcsV0FBVyxHQUFHLEdBQUcsR0FBRyxLQUFLLENBQUM7SUFDckcsQ0FBQztJQUVPLGdCQUFnQixDQUFDLEtBQWEsRUFBRSxTQUFpQixFQUFFLFdBQW1CO1FBQzVFLE9BQU8sSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksR0FBRyxTQUFTLEdBQUcsR0FBRyxHQUFHLFdBQVcsR0FBRyxHQUFHLENBQUM7SUFDN0YsQ0FBQztJQUVPLEtBQUssQ0FBQyxTQUFTLENBQUMsS0FBYTtRQUNuQyxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUN0RCxJQUFJLENBQUMsSUFBSTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRU8sS0FBSyxDQUFDLFVBQVUsQ0FBQyxLQUFhO1FBQ3BDLDJDQUEyQztRQUMzQyxNQUFNLE9BQU8sR0FBMkIsRUFBRSxDQUFDO1FBQzNDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDN0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUV6QyxLQUFLLE1BQU0sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksS0FBSyxFQUFFLENBQUM7WUFDbkMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzlCLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUM3QixNQUFNLElBQUksR0FBYyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO2dCQUNyRCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNoQyxJQUFJLEtBQUssQ0FBQyxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUM7b0JBQ3RCLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO29CQUMxQyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztnQkFDbkMsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVPLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxLQUFhLEVBQUUsTUFBYztRQUMzRCxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDN0MsS0FBSyxNQUFNLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUM1RCxJQUFJLFFBQVEsS0FBSyxNQUFNLEVBQUUsQ0FBQztnQkFDeEIsT0FBTyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDO1lBQ3hDLENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFFTyxLQUFLLENBQUMsYUFBYSxDQUFDLEtBQWEsRUFBRSxTQUFpQixFQUFFLEtBQWE7UUFDekUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDOUQsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN6QyxPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVPLEtBQUssQ0FBQyxXQUFXLENBQ3ZCLEtBQWEsRUFDYixTQUFpQixFQUNqQixNQUFjLEVBQ2QsTUFBMkIsRUFDM0IsTUFBMkIsRUFDM0IsS0FBYTtRQUViLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5QixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFOUIsSUFBSSxNQUFNLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDdEIsT0FBTztRQUNULENBQUM7UUFFRCx5QkFBeUI7UUFDekIsSUFBSSxNQUFNLElBQUksSUFBSSxFQUFFLENBQUM7WUFDbkIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN0RSxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQy9CLENBQUM7UUFFRCxzQkFBc0I7UUFDdEIsSUFBSSxNQUFNLElBQUksSUFBSSxFQUFFLENBQUM7WUFDbkIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN0RSxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNuQyxDQUFDO0lBQ0gsQ0FBQztJQUVPLDRCQUE0QixDQUNsQyxLQUFhLEVBQ2IsVUFBd0MsRUFDeEMsT0FBK0I7UUFFL0IsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUN4QyxJQUFJLEVBQUUsS0FBSyxHQUFHLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDdkQsT0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUNwQixDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVPLEtBQUssQ0FBQyxXQUFXLENBQUMsSUFBeUI7UUFDakQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUN6QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBbUIsQ0FBQztRQUN6QyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO1FBRW5DLHdCQUF3QjtRQUN4QixJQUFJLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ2hDLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxLQUFLLGtCQUFrQixDQUFDLENBQUM7UUFDckQsQ0FBQztRQUVELE1BQU0sTUFBTSxHQUFnQixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDO1FBQ2pFLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFFakUsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsQ0FBQyxFQUFFLENBQUM7SUFDcEQsQ0FBQztJQUVPLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBeUI7UUFDL0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUV6QiwyQkFBMkI7UUFDM0IsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzdDLEtBQUssTUFBTSxTQUFTLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQzdDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3JELE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDL0MsS0FBSyxNQUFNLEVBQUUsR0FBRyxFQUFFLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQy9CLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDNUIsQ0FBQztZQUNELE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUM1RCxDQUFDO1FBRUQsa0JBQWtCO1FBQ2xCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDckMsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN4QyxJQUFJLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFFcEIsS0FBSyxNQUFNLEVBQUUsR0FBRyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUM7WUFDM0IsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUMxQixXQUFXLEVBQUUsQ0FBQztRQUNoQixDQUFDO1FBRUQsZ0JBQWdCO1FBQ2hCLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBRTVDLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxDQUFDO0lBQzlELENBQUM7SUFFTyxLQUFLLENBQUMsV0FBVyxDQUFDLElBQXlCO1FBQ2pELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDakMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUN6QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBRTNCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixNQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsS0FBSyxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3JELENBQUM7UUFFRCxzQkFBc0I7UUFDdEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ2pELE1BQU0sSUFBSSxLQUFLLENBQUMsV0FBVyxNQUFNLDhCQUE4QixLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQzNFLENBQUM7UUFFRCxvQ0FBb0M7UUFDcEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDcEQsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM1QyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ2IsTUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLFNBQVMsOEJBQThCLEtBQUssR0FBRyxDQUFDLENBQUM7UUFDN0UsQ0FBQztRQUVELHVCQUF1QjtRQUN2QixNQUFNLElBQUksR0FBYyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUMxQyxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFFakQsaUNBQWlDO1FBQ2pDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDckMsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN6QyxJQUFJLFlBQVksR0FBRyxDQUFDLENBQUM7UUFFckIsS0FBSyxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksS0FBSyxFQUFFLENBQUM7WUFDOUIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUN6QyxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDekIsTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRTdCLElBQUksUUFBUSxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUNyQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUN4RSxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDakMsWUFBWSxFQUFFLENBQUM7WUFDakIsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsQ0FBQztJQUMvRCxDQUFDO0lBRU8sS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUF5QjtRQUMvQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO1FBQ2pDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUM7UUFFekIsMkJBQTJCO1FBQzNCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3JELE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDNUMsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDO1FBRWhCLEtBQUssTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQzVCLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDMUIsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBRUQsd0JBQXdCO1FBQ3hCLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUUxRCxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsQ0FBQztJQUMxRCxDQUFDO0lBRU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUF5QjtRQUM1QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQ3pCLElBQUksT0FBTyxHQUFHLElBQUksQ0FBQyxPQUEwQixDQUFDO1FBQzlDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFlLENBQUM7UUFFcEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxLQUFLLGtCQUFrQixDQUFDLENBQUM7UUFDckQsQ0FBQztRQUVELDRDQUE0QztRQUM1QyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5QyxDQUFDO1FBRUQsSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNyQyxNQUFNLElBQUksS0FBSyxDQUNiLGlCQUFpQixPQUFPLENBQUMsTUFBTSxnQ0FBZ0MsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUNoRixDQUFDO1FBQ0osQ0FBQztRQUVELG9CQUFvQjtRQUNwQixNQUFNLEdBQUcsR0FBd0IsRUFBRSxDQUFDO1FBQ3BDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDeEMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QixDQUFDO1FBRUQsa0JBQWtCO1FBQ2xCLElBQUksS0FBYSxDQUFDO1FBQ2xCLElBQUksTUFBTSxDQUFDLFVBQVUsSUFBSSxNQUFNLENBQUMsVUFBVSxJQUFJLEdBQUcsRUFBRSxDQUFDO1lBQ2xELEtBQUssR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBQ3pDLENBQUM7YUFBTSxDQUFDO1lBQ04sS0FBSyxHQUFHLElBQUEsU0FBTSxHQUFFLENBQUM7UUFDbkIsQ0FBQztRQUNELEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUM7UUFFbkIsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFbEUsbUJBQW1CO1FBQ25CLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QyxLQUFLLE1BQU0sQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQzVELElBQUksR0FBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUMxQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUM3RSxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNuQyxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ3BELENBQUM7SUFFTyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQXlCO1FBQzVDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDekIsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQW1CLENBQUM7UUFDdkMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQXFDLENBQUM7UUFDOUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQWtDLENBQUM7UUFDeEQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQTJCLENBQUM7UUFDL0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQTRCLENBQUM7UUFFakQsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxLQUFLLGtCQUFrQixDQUFDLENBQUM7UUFDckQsQ0FBQztRQUVELG1CQUFtQjtRQUNuQixJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztZQUMvQyxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5QyxDQUFDO1FBRUQsZ0JBQWdCO1FBQ2hCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDckMsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMvQyxJQUFJLElBQUksR0FBK0IsRUFBRSxDQUFDO1FBRTFDLEtBQUssTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ3BDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFFekMseUJBQXlCO1lBQ3pCLElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDO2dCQUM1QyxrQkFBa0I7Z0JBQ2xCLE1BQU0sU0FBUyxHQUF3QixFQUFFLENBQUM7Z0JBQzFDLEtBQUssTUFBTSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7b0JBQzFCLElBQUksR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO3dCQUNmLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQzVCLENBQUM7Z0JBQ0gsQ0FBQztnQkFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3ZCLENBQUM7UUFDSCxDQUFDO1FBRUQsaUJBQWlCO1FBQ2pCLElBQUksT0FBTyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDakIsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxJQUFJLE9BQU8sRUFBRSxDQUFDO29CQUN2QyxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQ3BCLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFFcEIsZUFBZTtvQkFDZixJQUFJLElBQUksS0FBSyxJQUFJLElBQUksSUFBSSxLQUFLLFNBQVM7d0JBQUUsT0FBTyxDQUFDLENBQUM7b0JBQ2xELElBQUksSUFBSSxLQUFLLElBQUksSUFBSSxJQUFJLEtBQUssU0FBUzt3QkFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO29CQUVuRCxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7b0JBQ1osSUFBSSxJQUFJLEdBQUcsSUFBSTt3QkFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUM7eUJBQ3JCLElBQUksSUFBSSxHQUFHLElBQUk7d0JBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQztvQkFFOUIsSUFBSSxTQUFTLEtBQUssTUFBTTt3QkFBRSxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUM7b0JBQ3JDLElBQUksR0FBRyxLQUFLLENBQUM7d0JBQUUsT0FBTyxHQUFHLENBQUM7Z0JBQzVCLENBQUM7Z0JBQ0QsT0FBTyxDQUFDLENBQUM7WUFDWCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCx5QkFBeUI7UUFDekIsSUFBSSxNQUFNLElBQUksTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3pCLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzVCLENBQUM7UUFDRCxJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3JDLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUM5QixDQUFDO1FBRUQsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQzVDLENBQUM7SUFFTyxpQkFBaUIsQ0FDdkIsR0FBd0IsRUFDeEIsVUFBd0M7UUFFeEMsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUN4QyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7WUFFeEIsUUFBUSxFQUFFLEVBQUUsQ0FBQztnQkFDWCxLQUFLLEdBQUc7b0JBQ04sSUFBSSxNQUFNLEtBQUssR0FBRzt3QkFBRSxPQUFPLEtBQUssQ0FBQztvQkFDakMsTUFBTTtnQkFDUixLQUFLLElBQUk7b0JBQ1AsSUFBSSxNQUFNLEtBQUssR0FBRzt3QkFBRSxPQUFPLEtBQUssQ0FBQztvQkFDakMsTUFBTTtnQkFDUixLQUFLLEdBQUc7b0JBQ04sSUFBSSxNQUFNLEtBQUssSUFBSSxJQUFJLE1BQU0sS0FBSyxTQUFTLElBQUksTUFBTSxJQUFJLEdBQUc7d0JBQUUsT0FBTyxLQUFLLENBQUM7b0JBQzNFLE1BQU07Z0JBQ1IsS0FBSyxJQUFJO29CQUNQLElBQUksTUFBTSxLQUFLLElBQUksSUFBSSxNQUFNLEtBQUssU0FBUyxJQUFJLE1BQU0sR0FBRyxHQUFHO3dCQUFFLE9BQU8sS0FBSyxDQUFDO29CQUMxRSxNQUFNO2dCQUNSLEtBQUssR0FBRztvQkFDTixJQUFJLE1BQU0sS0FBSyxJQUFJLElBQUksTUFBTSxLQUFLLFNBQVMsSUFBSSxNQUFNLElBQUksR0FBRzt3QkFBRSxPQUFPLEtBQUssQ0FBQztvQkFDM0UsTUFBTTtnQkFDUixLQUFLLElBQUk7b0JBQ1AsSUFBSSxNQUFNLEtBQUssSUFBSSxJQUFJLE1BQU0sS0FBSyxTQUFTLElBQUksTUFBTSxHQUFHLEdBQUc7d0JBQUUsT0FBTyxLQUFLLENBQUM7b0JBQzFFLE1BQU07Z0JBQ1IsS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDO29CQUNaLElBQUksTUFBTSxLQUFLLElBQUksSUFBSSxNQUFNLEtBQUssU0FBUzt3QkFBRSxPQUFPLEtBQUssQ0FBQztvQkFDMUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztvQkFDbkUsSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLElBQUksT0FBTyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQzt3QkFBRSxPQUFPLEtBQUssQ0FBQztvQkFDeEUsTUFBTTtnQkFDUixDQUFDO2dCQUNELEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQztvQkFDaEIsSUFBSSxNQUFNLEtBQUssSUFBSSxJQUFJLE1BQU0sS0FBSyxTQUFTO3dCQUFFLE9BQU8sSUFBSSxDQUFDO29CQUN6RCxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO29CQUNuRSxJQUFJLElBQUksTUFBTSxDQUFDLElBQUksT0FBTyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQzt3QkFBRSxPQUFPLEtBQUssQ0FBQztvQkFDdkUsTUFBTTtnQkFDUixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQXlCO1FBQzVDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDekIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQThCLENBQUM7UUFDcEQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQXFDLENBQUM7UUFFOUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxLQUFLLGtCQUFrQixDQUFDLENBQUM7UUFDckQsQ0FBQztRQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QyxJQUFJLFlBQVksR0FBRyxDQUFDLENBQUM7UUFFckIsNkJBQTZCO1FBQzdCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRWxGLElBQUksV0FBVyxFQUFFLENBQUM7WUFDaEIsMkJBQTJCO1lBQzNCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEdBQUcsV0FBVyxDQUFDO1lBQy9CLE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztZQUU3RCxJQUFJLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDcEIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUU5RSxLQUFLLE1BQU0sS0FBSyxJQUFJLE1BQU0sRUFBRSxDQUFDO29CQUMzQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztvQkFDdEMsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDckMsSUFBSSxDQUFDLEtBQUs7d0JBQUUsU0FBUztvQkFFckIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztvQkFFNUMsd0RBQXdEO29CQUN4RCxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDO3dCQUNoRCxTQUFTO29CQUNYLENBQUM7b0JBRUQsZ0JBQWdCO29CQUNoQixNQUFNLE1BQU0sR0FBRyxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUM7b0JBQzdCLEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7d0JBQ25ELE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUM7b0JBQ3RCLENBQUM7b0JBRUQscUNBQXFDO29CQUNyQyxLQUFLLE1BQU0sQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO3dCQUN4RCxJQUFJLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQzs0QkFDdEIsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7d0JBQ3hFLENBQUM7b0JBQ0gsQ0FBQztvQkFFRCxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7b0JBQy9DLFlBQVksRUFBRSxDQUFDO2dCQUNqQixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7YUFBTSxDQUFDO1lBQ04sNEJBQTRCO1lBQzVCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDckMsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUUvQyxLQUFLLE1BQU0sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksV0FBVyxFQUFFLENBQUM7Z0JBQ3pDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7Z0JBRTVDLHlCQUF5QjtnQkFDekIsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxFQUFFLENBQUM7b0JBQy9DLGdCQUFnQjtvQkFDaEIsTUFBTSxNQUFNLEdBQUcsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO29CQUM3QixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO3dCQUNqRCxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDO29CQUNwQixDQUFDO29CQUVELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFFNUIscUNBQXFDO29CQUNyQyxLQUFLLE1BQU0sQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO3dCQUN4RCxJQUFJLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQzs0QkFDdEIsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7d0JBQ3hFLENBQUM7b0JBQ0gsQ0FBQztvQkFFRCxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7b0JBQy9DLFlBQVksRUFBRSxDQUFDO2dCQUNqQixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLFlBQVksRUFBRSxDQUFDO0lBQ2pELENBQUM7SUFFTyxLQUFLLENBQUMsVUFBVSxDQUFDLElBQXlCO1FBQ2hELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDekIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQXFDLENBQUM7UUFFOUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxLQUFLLGtCQUFrQixDQUFDLENBQUM7UUFDckQsQ0FBQztRQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QyxJQUFJLFlBQVksR0FBRyxDQUFDLENBQUM7UUFFckIsNkJBQTZCO1FBQzdCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRWxGLElBQUksV0FBVyxFQUFFLENBQUM7WUFDaEIsMkJBQTJCO1lBQzNCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEdBQUcsV0FBVyxDQUFDO1lBQy9CLE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztZQUU3RCxJQUFJLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDcEIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUM5RSxNQUFNLFlBQVksR0FBYSxFQUFFLENBQUM7Z0JBQ2xDLE1BQU0sWUFBWSxHQUF1RCxFQUFFLENBQUM7Z0JBRTVFLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxFQUFFLENBQUM7b0JBQzNCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO29CQUN0QyxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUNyQyxJQUFJLENBQUMsS0FBSzt3QkFBRSxTQUFTO29CQUVyQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO29CQUV6Qyx3REFBd0Q7b0JBQ3hELElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDO3dCQUM1QyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQzt3QkFDcEMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO29CQUNwQyxDQUFDO2dCQUNILENBQUM7Z0JBRUQsaUNBQWlDO2dCQUNqQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO29CQUM3QyxNQUFNLEdBQUcsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQzVCLE1BQU0sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUV2QywwQkFBMEI7b0JBQzFCLEtBQUssTUFBTSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7d0JBQ3hELE1BQU0sUUFBUSxHQUF3QixFQUFFLENBQUM7d0JBQ3pDLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO29CQUN2RSxDQUFDO29CQUVELE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQzFCLFlBQVksRUFBRSxDQUFDO2dCQUNqQixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7YUFBTSxDQUFDO1lBQ04sNEJBQTRCO1lBQzVCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDckMsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMvQyxNQUFNLFlBQVksR0FBYSxFQUFFLENBQUM7WUFDbEMsTUFBTSxZQUFZLEdBQXVELEVBQUUsQ0FBQztZQUU1RSxLQUFLLE1BQU0sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksV0FBVyxFQUFFLENBQUM7Z0JBQ3pDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7Z0JBRXpDLHlCQUF5QjtnQkFDekIsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxFQUFFLENBQUM7b0JBQzVDLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDekIsWUFBWSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDdkIsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO2dCQUNwQyxDQUFDO1lBQ0gsQ0FBQztZQUVELDJDQUEyQztZQUMzQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUM3QyxNQUFNLEdBQUcsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzVCLE1BQU0sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUV2QywwQkFBMEI7Z0JBQzFCLEtBQUssTUFBTSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7b0JBQ3hELE1BQU0sUUFBUSxHQUF3QixFQUFFLENBQUM7b0JBQ3pDLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUN2RSxDQUFDO2dCQUVELE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzFCLFlBQVksRUFBRSxDQUFDO1lBQ2pCLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsQ0FBQztJQUNqRCxDQUFDO0NBQ0Y7QUEvbEJELGtDQStsQkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNRTCBFbmdpbmUgZm9yIFNvY2hEQiBKYXZhU2NyaXB0IFNES1xuICpcbiAqIFByb3ZpZGVzIFNRTCBzdXBwb3J0IG9uIHRvcCBvZiB0aGUgS1Ygc3RvcmFnZSBiYWNrZW5kLlxuICogVGFibGVzIGFyZSBzdG9yZWQgYXM6XG4gKiAgIC0gU2NoZW1hOiBfc3FsL3RhYmxlcy97dGFibGVfbmFtZX0vc2NoZW1hIC0+IEpTT04gc2NoZW1hIGRlZmluaXRpb25cbiAqICAgLSBSb3dzOiBfc3FsL3RhYmxlcy97dGFibGVfbmFtZX0vcm93cy97cm93X2lkfSAtPiBKU09OIHJvdyBkYXRhXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cblxuLy8gQ29weXJpZ2h0IDIwMjUgU3VzaGFudGggKGh0dHBzOi8vZ2l0aHViLmNvbS9zdXNoYW50aHB5KVxuLy9cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4vLyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4vLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbi8vXG4vLyAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cbmltcG9ydCB7IHY0IGFzIHV1aWR2NCB9IGZyb20gJ3V1aWQnO1xuXG4vKipcbiAqIFJlc3VsdCBvZiBhIFNRTCBxdWVyeSBleGVjdXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU1FMUXVlcnlSZXN1bHQge1xuICAvKiogUmVzdWx0IHJvd3MgKi9cbiAgcm93czogQXJyYXk8UmVjb3JkPHN0cmluZywgYW55Pj47XG4gIC8qKiBDb2x1bW4gbmFtZXMgKi9cbiAgY29sdW1uczogc3RyaW5nW107XG4gIC8qKiBOdW1iZXIgb2Ygcm93cyBhZmZlY3RlZCAoZm9yIElOU0VSVC9VUERBVEUvREVMRVRFKSAqL1xuICByb3dzQWZmZWN0ZWQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBDb2x1bW4gZGVmaW5pdGlvbiBmb3IgYSB0YWJsZS5cbiAqL1xuaW50ZXJmYWNlIENvbHVtbiB7XG4gIG5hbWU6IHN0cmluZztcbiAgdHlwZTogc3RyaW5nOyAvLyBJTlQsIFRFWFQsIEZMT0FULCBCT09MLCBCTE9CXG4gIG51bGxhYmxlOiBib29sZWFuO1xuICBwcmltYXJ5S2V5OiBib29sZWFuO1xuICBkZWZhdWx0PzogYW55O1xufVxuXG4vKipcbiAqIFRhYmxlIHNjaGVtYSBkZWZpbml0aW9uLlxuICovXG5pbnRlcmZhY2UgVGFibGVTY2hlbWEge1xuICBuYW1lOiBzdHJpbmc7XG4gIGNvbHVtbnM6IENvbHVtbltdO1xuICBwcmltYXJ5S2V5Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEluZGV4IG1ldGFkYXRhLlxuICovXG5pbnRlcmZhY2UgSW5kZXhJbmZvIHtcbiAgY29sdW1uOiBzdHJpbmc7XG4gIHRhYmxlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUGFyc2VkIFNRTCBvcGVyYXRpb24gcmVzdWx0LlxuICovXG50eXBlIFBhcnNlZFNRTCA9IHtcbiAgb3BlcmF0aW9uOiBzdHJpbmc7XG4gIGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT47XG59O1xuXG4vKipcbiAqIFNpbXBsZSBTUUwgcGFyc2VyIGZvciBEREwgYW5kIERNTCBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgY2xhc3MgU1FMUGFyc2VyIHtcbiAgLyoqXG4gICAqIFBhcnNlIGEgU1FMIHN0YXRlbWVudC5cbiAgICovXG4gIHN0YXRpYyBwYXJzZShzcWw6IHN0cmluZyk6IFBhcnNlZFNRTCB7XG4gICAgc3FsID0gc3FsLnRyaW0oKTtcbiAgICBjb25zdCB1cHBlciA9IHNxbC50b1VwcGVyQ2FzZSgpO1xuXG4gICAgaWYgKHVwcGVyLnN0YXJ0c1dpdGgoJ0NSRUFURSBUQUJMRScpKSB7XG4gICAgICByZXR1cm4gU1FMUGFyc2VyLnBhcnNlQ3JlYXRlVGFibGUoc3FsKTtcbiAgICB9IGVsc2UgaWYgKHVwcGVyLnN0YXJ0c1dpdGgoJ0NSRUFURSBJTkRFWCcpKSB7XG4gICAgICByZXR1cm4gU1FMUGFyc2VyLnBhcnNlQ3JlYXRlSW5kZXgoc3FsKTtcbiAgICB9IGVsc2UgaWYgKHVwcGVyLnN0YXJ0c1dpdGgoJ0RST1AgVEFCTEUnKSkge1xuICAgICAgcmV0dXJuIFNRTFBhcnNlci5wYXJzZURyb3BUYWJsZShzcWwpO1xuICAgIH0gZWxzZSBpZiAodXBwZXIuc3RhcnRzV2l0aCgnRFJPUCBJTkRFWCcpKSB7XG4gICAgICByZXR1cm4gU1FMUGFyc2VyLnBhcnNlRHJvcEluZGV4KHNxbCk7XG4gICAgfSBlbHNlIGlmICh1cHBlci5zdGFydHNXaXRoKCdJTlNFUlQnKSkge1xuICAgICAgcmV0dXJuIFNRTFBhcnNlci5wYXJzZUluc2VydChzcWwpO1xuICAgIH0gZWxzZSBpZiAodXBwZXIuc3RhcnRzV2l0aCgnU0VMRUNUJykpIHtcbiAgICAgIHJldHVybiBTUUxQYXJzZXIucGFyc2VTZWxlY3Qoc3FsKTtcbiAgICB9IGVsc2UgaWYgKHVwcGVyLnN0YXJ0c1dpdGgoJ1VQREFURScpKSB7XG4gICAgICByZXR1cm4gU1FMUGFyc2VyLnBhcnNlVXBkYXRlKHNxbCk7XG4gICAgfSBlbHNlIGlmICh1cHBlci5zdGFydHNXaXRoKCdERUxFVEUnKSkge1xuICAgICAgcmV0dXJuIFNRTFBhcnNlci5wYXJzZURlbGV0ZShzcWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIFNRTCBzdGF0ZW1lbnQ6ICR7c3FsLnN1YnN0cmluZygwLCA1MCl9YCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VDcmVhdGVUYWJsZShzcWw6IHN0cmluZyk6IFBhcnNlZFNRTCB7XG4gICAgY29uc3QgbWF0Y2ggPSBzcWwubWF0Y2goXG4gICAgICAvQ1JFQVRFXFxzK1RBQkxFXFxzKyg/OklGXFxzK05PVFxccytFWElTVFNcXHMrKT8oXFx3KylcXHMqXFwoKC4qKVxcKS9pc1xuICAgICk7XG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIENSRUFURSBUQUJMRTogJHtzcWx9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgdGFibGVOYW1lID0gbWF0Y2hbMV07XG4gICAgY29uc3QgY29sc1N0ciA9IG1hdGNoWzJdO1xuICAgIGNvbnN0IGNvbHVtbnM6IENvbHVtbltdID0gW107XG4gICAgbGV0IHByaW1hcnlLZXk6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IGNvbERlZnMgPSBTUUxQYXJzZXIuc3BsaXRDb2x1bW5zKGNvbHNTdHIpO1xuXG4gICAgZm9yIChjb25zdCBjb2xEZWYgb2YgY29sRGVmcykge1xuICAgICAgY29uc3QgdHJpbW1lZCA9IGNvbERlZi50cmltKCk7XG4gICAgICBpZiAoIXRyaW1tZWQpIGNvbnRpbnVlO1xuXG4gICAgICAvLyBDaGVjayBmb3IgUFJJTUFSWSBLRVkgY29uc3RyYWludFxuICAgICAgaWYgKHRyaW1tZWQudG9VcHBlckNhc2UoKS5zdGFydHNXaXRoKCdQUklNQVJZIEtFWScpKSB7XG4gICAgICAgIGNvbnN0IHBrTWF0Y2ggPSB0cmltbWVkLm1hdGNoKC9QUklNQVJZXFxzK0tFWVxccypcXCgoXFx3KylcXCkvaSk7XG4gICAgICAgIGlmIChwa01hdGNoKSB7XG4gICAgICAgICAgcHJpbWFyeUtleSA9IHBrTWF0Y2hbMV07XG4gICAgICAgIH1cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIFBhcnNlIGNvbHVtbjogbmFtZSBUWVBFIFtQUklNQVJZIEtFWV0gW05PVCBOVUxMXSBbREVGQVVMVCB2YWx1ZV1cbiAgICAgIGNvbnN0IHBhcnRzID0gdHJpbW1lZC5zcGxpdCgvXFxzKy8pO1xuICAgICAgaWYgKHBhcnRzLmxlbmd0aCA8IDIpIGNvbnRpbnVlO1xuXG4gICAgICBjb25zdCBjb2xOYW1lID0gcGFydHNbMF07XG4gICAgICBsZXQgY29sVHlwZSA9IHBhcnRzWzFdLnRvVXBwZXJDYXNlKCk7XG5cbiAgICAgIC8vIE5vcm1hbGl6ZSB0eXBlc1xuICAgICAgaWYgKFsnSU5URUdFUicsICdJTlQnLCAnQklHSU5UJywgJ1NNQUxMSU5UJ10uaW5jbHVkZXMoY29sVHlwZSkpIHtcbiAgICAgICAgY29sVHlwZSA9ICdJTlQnO1xuICAgICAgfSBlbHNlIGlmIChbJ1ZBUkNIQVInLCAnQ0hBUicsICdTVFJJTkcnLCAnVEVYVCddLmluY2x1ZGVzKGNvbFR5cGUpKSB7XG4gICAgICAgIGNvbFR5cGUgPSAnVEVYVCc7XG4gICAgICB9IGVsc2UgaWYgKFsnUkVBTCcsICdET1VCTEUnLCAnRkxPQVQnLCAnREVDSU1BTCcsICdOVU1FUklDJ10uaW5jbHVkZXMoY29sVHlwZSkpIHtcbiAgICAgICAgY29sVHlwZSA9ICdGTE9BVCc7XG4gICAgICB9IGVsc2UgaWYgKFsnQk9PTEVBTicsICdCT09MJ10uaW5jbHVkZXMoY29sVHlwZSkpIHtcbiAgICAgICAgY29sVHlwZSA9ICdCT09MJztcbiAgICAgIH0gZWxzZSBpZiAoWydCTE9CJywgJ0JZVEVTJywgJ0JJTkFSWSddLmluY2x1ZGVzKGNvbFR5cGUpKSB7XG4gICAgICAgIGNvbFR5cGUgPSAnQkxPQic7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvbFVwcGVyID0gdHJpbW1lZC50b1VwcGVyQ2FzZSgpO1xuICAgICAgY29uc3QgaXNQayA9IGNvbFVwcGVyLmluY2x1ZGVzKCdQUklNQVJZIEtFWScpO1xuICAgICAgY29uc3QgbnVsbGFibGUgPSAhY29sVXBwZXIuaW5jbHVkZXMoJ05PVCBOVUxMJyk7XG5cbiAgICAgIGlmIChpc1BrKSB7XG4gICAgICAgIHByaW1hcnlLZXkgPSBjb2xOYW1lO1xuICAgICAgfVxuXG4gICAgICBjb2x1bW5zLnB1c2goe1xuICAgICAgICBuYW1lOiBjb2xOYW1lLFxuICAgICAgICB0eXBlOiBjb2xUeXBlLFxuICAgICAgICBudWxsYWJsZSxcbiAgICAgICAgcHJpbWFyeUtleTogaXNQayxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBvcGVyYXRpb246ICdDUkVBVEVfVEFCTEUnLFxuICAgICAgZGF0YTogeyB0YWJsZTogdGFibGVOYW1lLCBjb2x1bW5zLCBwcmltYXJ5S2V5IH0sXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIHNwbGl0Q29sdW1ucyhjb2xzU3RyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgcmVzdWx0OiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBjdXJyZW50ID0gJyc7XG4gICAgbGV0IGRlcHRoID0gMDtcblxuICAgIGZvciAoY29uc3QgY2hhciBvZiBjb2xzU3RyKSB7XG4gICAgICBpZiAoY2hhciA9PT0gJygnKSB7XG4gICAgICAgIGRlcHRoKys7XG4gICAgICAgIGN1cnJlbnQgKz0gY2hhcjtcbiAgICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gJyknKSB7XG4gICAgICAgIGRlcHRoLS07XG4gICAgICAgIGN1cnJlbnQgKz0gY2hhcjtcbiAgICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gJywnICYmIGRlcHRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGN1cnJlbnQpO1xuICAgICAgICBjdXJyZW50ID0gJyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjdXJyZW50ICs9IGNoYXI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGN1cnJlbnQudHJpbSgpKSB7XG4gICAgICByZXN1bHQucHVzaChjdXJyZW50KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VEcm9wVGFibGUoc3FsOiBzdHJpbmcpOiBQYXJzZWRTUUwge1xuICAgIGNvbnN0IG1hdGNoID0gc3FsLm1hdGNoKC9EUk9QXFxzK1RBQkxFXFxzKyg/OklGXFxzK0VYSVNUU1xccyspPyhcXHcrKS9pKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgRFJPUCBUQUJMRTogJHtzcWx9YCk7XG4gICAgfVxuICAgIHJldHVybiB7IG9wZXJhdGlvbjogJ0RST1BfVEFCTEUnLCBkYXRhOiB7IHRhYmxlOiBtYXRjaFsxXSB9IH07XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZUNyZWF0ZUluZGV4KHNxbDogc3RyaW5nKTogUGFyc2VkU1FMIHtcbiAgICAvLyBDUkVBVEUgSU5ERVggaWR4X25hbWUgT04gdGFibGVfbmFtZShjb2x1bW5fbmFtZSlcbiAgICBjb25zdCBtYXRjaCA9IHNxbC5tYXRjaCgvQ1JFQVRFXFxzK0lOREVYXFxzKyhcXHcrKVxccytPTlxccysoXFx3KylcXHMqXFwoXFxzKihcXHcrKVxccypcXCkvaSk7XG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIENSRUFURSBJTkRFWCBzeW50YXg6ICR7c3FsfWApO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgb3BlcmF0aW9uOiAnQ1JFQVRFX0lOREVYJyxcbiAgICAgIGRhdGE6IHtcbiAgICAgICAgaW5kZXhOYW1lOiBtYXRjaFsxXSxcbiAgICAgICAgdGFibGU6IG1hdGNoWzJdLFxuICAgICAgICBjb2x1bW46IG1hdGNoWzNdLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VEcm9wSW5kZXgoc3FsOiBzdHJpbmcpOiBQYXJzZWRTUUwge1xuICAgIC8vIERST1AgSU5ERVggaWR4X25hbWUgT04gdGFibGVfbmFtZVxuICAgIGNvbnN0IG1hdGNoID0gc3FsLm1hdGNoKC9EUk9QXFxzK0lOREVYXFxzKyhcXHcrKVxccytPTlxccysoXFx3KykvaSk7XG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIERST1AgSU5ERVggc3ludGF4OiAke3NxbH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIG9wZXJhdGlvbjogJ0RST1BfSU5ERVgnLFxuICAgICAgZGF0YToge1xuICAgICAgICBpbmRleE5hbWU6IG1hdGNoWzFdLFxuICAgICAgICB0YWJsZTogbWF0Y2hbMl0sXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZUluc2VydChzcWw6IHN0cmluZyk6IFBhcnNlZFNRTCB7XG4gICAgLy8gSU5TRVJUIElOVE8gdGFibGUgKGNvbDEsIGNvbDIpIFZBTFVFUyAodmFsMSwgdmFsMilcbiAgICBsZXQgbWF0Y2ggPSBzcWwubWF0Y2goXG4gICAgICAvSU5TRVJUXFxzK0lOVE9cXHMrKFxcdyspXFxzKlxcKChbXildKylcXClcXHMqVkFMVUVTXFxzKlxcKCguKylcXCkvaXNcbiAgICApO1xuXG4gICAgaWYgKG1hdGNoKSB7XG4gICAgICBjb25zdCB0YWJsZSA9IG1hdGNoWzFdO1xuICAgICAgY29uc3QgY29sdW1ucyA9IG1hdGNoWzJdLnNwbGl0KCcsJykubWFwKChjKSA9PiBjLnRyaW0oKSk7XG4gICAgICBjb25zdCB2YWx1ZXMgPSBTUUxQYXJzZXIucGFyc2VWYWx1ZXMobWF0Y2hbM10pO1xuICAgICAgcmV0dXJuIHsgb3BlcmF0aW9uOiAnSU5TRVJUJywgZGF0YTogeyB0YWJsZSwgY29sdW1ucywgdmFsdWVzIH0gfTtcbiAgICB9XG5cbiAgICAvLyBJTlNFUlQgSU5UTyB0YWJsZSBWQUxVRVMgKHZhbDEsIHZhbDIpXG4gICAgbWF0Y2ggPSBzcWwubWF0Y2goL0lOU0VSVFxccytJTlRPXFxzKyhcXHcrKVxccytWQUxVRVNcXHMqXFwoKC4rKVxcKS9pcyk7XG4gICAgaWYgKG1hdGNoKSB7XG4gICAgICBjb25zdCB0YWJsZSA9IG1hdGNoWzFdO1xuICAgICAgY29uc3QgdmFsdWVzID0gU1FMUGFyc2VyLnBhcnNlVmFsdWVzKG1hdGNoWzJdKTtcbiAgICAgIHJldHVybiB7IG9wZXJhdGlvbjogJ0lOU0VSVCcsIGRhdGE6IHsgdGFibGUsIGNvbHVtbnM6IG51bGwsIHZhbHVlcyB9IH07XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIElOU0VSVDogJHtzcWx9YCk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZVZhbHVlcyh2YWx1ZXNTdHI6IHN0cmluZyk6IGFueVtdIHtcbiAgICBjb25zdCB2YWx1ZXM6IGFueVtdID0gW107XG4gICAgbGV0IGN1cnJlbnQgPSAnJztcbiAgICBsZXQgaW5TdHJpbmcgPSBmYWxzZTtcbiAgICBsZXQgc3RyaW5nQ2hhcjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICBmb3IgKGNvbnN0IGNoYXIgb2YgdmFsdWVzU3RyKSB7XG4gICAgICBpZiAoKGNoYXIgPT09ICdcIicgfHwgY2hhciA9PT0gXCInXCIpICYmICFpblN0cmluZykge1xuICAgICAgICBpblN0cmluZyA9IHRydWU7XG4gICAgICAgIHN0cmluZ0NoYXIgPSBjaGFyO1xuICAgICAgICBjdXJyZW50ICs9IGNoYXI7XG4gICAgICB9IGVsc2UgaWYgKGNoYXIgPT09IHN0cmluZ0NoYXIgJiYgaW5TdHJpbmcpIHtcbiAgICAgICAgaW5TdHJpbmcgPSBmYWxzZTtcbiAgICAgICAgc3RyaW5nQ2hhciA9IG51bGw7XG4gICAgICAgIGN1cnJlbnQgKz0gY2hhcjtcbiAgICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gJywnICYmICFpblN0cmluZykge1xuICAgICAgICB2YWx1ZXMucHVzaChTUUxQYXJzZXIucGFyc2VWYWx1ZShjdXJyZW50LnRyaW0oKSkpO1xuICAgICAgICBjdXJyZW50ID0gJyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjdXJyZW50ICs9IGNoYXI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGN1cnJlbnQudHJpbSgpKSB7XG4gICAgICB2YWx1ZXMucHVzaChTUUxQYXJzZXIucGFyc2VWYWx1ZShjdXJyZW50LnRyaW0oKSkpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZXM7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZVZhbHVlKHZhbFN0cjogc3RyaW5nKTogYW55IHtcbiAgICBpZiAoIXZhbFN0ciB8fCB2YWxTdHIudG9VcHBlckNhc2UoKSA9PT0gJ05VTEwnKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBTdHJpbmcgbGl0ZXJhbHNcbiAgICBpZiAoXG4gICAgICAodmFsU3RyLnN0YXJ0c1dpdGgoXCInXCIpICYmIHZhbFN0ci5lbmRzV2l0aChcIidcIikpIHx8XG4gICAgICAodmFsU3RyLnN0YXJ0c1dpdGgoJ1wiJykgJiYgdmFsU3RyLmVuZHNXaXRoKCdcIicpKVxuICAgICkge1xuICAgICAgcmV0dXJuIHZhbFN0ci5zbGljZSgxLCAtMSk7XG4gICAgfVxuXG4gICAgLy8gQm9vbGVhblxuICAgIGlmICh2YWxTdHIudG9VcHBlckNhc2UoKSA9PT0gJ1RSVUUnKSByZXR1cm4gdHJ1ZTtcbiAgICBpZiAodmFsU3RyLnRvVXBwZXJDYXNlKCkgPT09ICdGQUxTRScpIHJldHVybiBmYWxzZTtcblxuICAgIC8vIE51bWJlcnNcbiAgICBpZiAodmFsU3RyLmluY2x1ZGVzKCcuJykpIHtcbiAgICAgIGNvbnN0IG51bSA9IHBhcnNlRmxvYXQodmFsU3RyKTtcbiAgICAgIGlmICghaXNOYU4obnVtKSkgcmV0dXJuIG51bTtcbiAgICB9XG4gICAgY29uc3QgaW50VmFsID0gcGFyc2VJbnQodmFsU3RyLCAxMCk7XG4gICAgaWYgKCFpc05hTihpbnRWYWwpKSByZXR1cm4gaW50VmFsO1xuXG4gICAgcmV0dXJuIHZhbFN0cjtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIHBhcnNlU2VsZWN0KHNxbDogc3RyaW5nKTogUGFyc2VkU1FMIHtcbiAgICAvLyBFeHRyYWN0IHRhYmxlIG5hbWUgZmlyc3RcbiAgICBjb25zdCB0YWJsZU1hdGNoID0gc3FsLm1hdGNoKC9GUk9NXFxzKyhcXHcrKS9pKTtcbiAgICBpZiAoIXRhYmxlTWF0Y2gpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBTRUxFQ1Q6ICR7c3FsfWApO1xuICAgIH1cbiAgICBjb25zdCB0YWJsZSA9IHRhYmxlTWF0Y2hbMV07XG5cbiAgICAvLyBFeHRyYWN0IGNvbHVtbnNcbiAgICBjb25zdCBjb2xzTWF0Y2ggPSBzcWwubWF0Y2goL1NFTEVDVFxccysoLis/KVxccytGUk9NL2lzKTtcbiAgICBsZXQgY29sdW1uczogc3RyaW5nW10gPSBbJyonXTtcbiAgICBpZiAoY29sc01hdGNoKSB7XG4gICAgICBjb25zdCBjb2xzU3RyID0gY29sc01hdGNoWzFdLnRyaW0oKTtcbiAgICAgIGNvbHVtbnMgPSBjb2xzU3RyID09PSAnKicgPyBbJyonXSA6IGNvbHNTdHIuc3BsaXQoJywnKS5tYXAoKGMpID0+IGMudHJpbSgpKTtcbiAgICB9XG5cbiAgICAvLyBFeHRyYWN0IFdIRVJFIGNsYXVzZVxuICAgIGxldCBjb25kaXRpb25zOiBBcnJheTxbc3RyaW5nLCBzdHJpbmcsIGFueV0+ID0gW107XG4gICAgY29uc3Qgd2hlcmVNYXRjaCA9IHNxbC5tYXRjaCgvV0hFUkVcXHMrKC4rPykoPzpcXHMrT1JERVJ8XFxzK0xJTUlUfFxccytPRkZTRVR8JCkvaXMpO1xuICAgIGlmICh3aGVyZU1hdGNoKSB7XG4gICAgICBjb25kaXRpb25zID0gU1FMUGFyc2VyLnBhcnNlV2hlcmUod2hlcmVNYXRjaFsxXSk7XG4gICAgfVxuXG4gICAgLy8gRXh0cmFjdCBPUkRFUiBCWVxuICAgIGxldCBvcmRlckJ5OiBBcnJheTxbc3RyaW5nLCBzdHJpbmddPiA9IFtdO1xuICAgIGNvbnN0IG9yZGVyTWF0Y2ggPSBzcWwubWF0Y2goL09SREVSXFxzK0JZXFxzKyguKz8pKD86XFxzK0xJTUlUfFxccytPRkZTRVR8JCkvaSk7XG4gICAgaWYgKG9yZGVyTWF0Y2gpIHtcbiAgICAgIGZvciAoY29uc3QgcGFydCBvZiBvcmRlck1hdGNoWzFdLnNwbGl0KCcsJykpIHtcbiAgICAgICAgY29uc3QgdHJpbW1lZCA9IHBhcnQudHJpbSgpO1xuICAgICAgICBpZiAodHJpbW1lZC50b1VwcGVyQ2FzZSgpLmVuZHNXaXRoKCcgREVTQycpKSB7XG4gICAgICAgICAgb3JkZXJCeS5wdXNoKFt0cmltbWVkLnNsaWNlKDAsIC01KS50cmltKCksICdERVNDJ10pO1xuICAgICAgICB9IGVsc2UgaWYgKHRyaW1tZWQudG9VcHBlckNhc2UoKS5lbmRzV2l0aCgnIEFTQycpKSB7XG4gICAgICAgICAgb3JkZXJCeS5wdXNoKFt0cmltbWVkLnNsaWNlKDAsIC00KS50cmltKCksICdBU0MnXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb3JkZXJCeS5wdXNoKFt0cmltbWVkLCAnQVNDJ10pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRXh0cmFjdCBMSU1JVFxuICAgIGxldCBsaW1pdDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IGxpbWl0TWF0Y2ggPSBzcWwubWF0Y2goL0xJTUlUXFxzKyhcXGQrKS9pKTtcbiAgICBpZiAobGltaXRNYXRjaCkge1xuICAgICAgbGltaXQgPSBwYXJzZUludChsaW1pdE1hdGNoWzFdLCAxMCk7XG4gICAgfVxuXG4gICAgLy8gRXh0cmFjdCBPRkZTRVRcbiAgICBsZXQgb2Zmc2V0OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgY29uc3Qgb2Zmc2V0TWF0Y2ggPSBzcWwubWF0Y2goL09GRlNFVFxccysoXFxkKykvaSk7XG4gICAgaWYgKG9mZnNldE1hdGNoKSB7XG4gICAgICBvZmZzZXQgPSBwYXJzZUludChvZmZzZXRNYXRjaFsxXSwgMTApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBvcGVyYXRpb246ICdTRUxFQ1QnLFxuICAgICAgZGF0YTogeyB0YWJsZSwgY29sdW1ucywgd2hlcmU6IGNvbmRpdGlvbnMsIG9yZGVyQnksIGxpbWl0LCBvZmZzZXQgfSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VXaGVyZSh3aGVyZUNsYXVzZTogc3RyaW5nKTogQXJyYXk8W3N0cmluZywgc3RyaW5nLCBhbnldPiB7XG4gICAgY29uc3QgY29uZGl0aW9uczogQXJyYXk8W3N0cmluZywgc3RyaW5nLCBhbnldPiA9IFtdO1xuICAgIGNvbnN0IHBhcnRzID0gd2hlcmVDbGF1c2Uuc3BsaXQoL1xccytBTkRcXHMrL2kpO1xuXG4gICAgZm9yIChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgICBjb25zdCBtYXRjaCA9IHBhcnQubWF0Y2goLyhcXHcrKVxccyooPXwhPXw8Pnw+PXw8PXw+fDx8TElLRXxOT1RcXHMrTElLRSlcXHMqKC4rKS9pKTtcbiAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICBjb25zdCBjb2wgPSBtYXRjaFsxXTtcbiAgICAgICAgbGV0IG9wID0gbWF0Y2hbMl0udG9VcHBlckNhc2UoKS5yZXBsYWNlKC9cXHMrL2csICdfJyk7XG4gICAgICAgIGlmIChvcCA9PT0gJzw+Jykgb3AgPSAnIT0nO1xuICAgICAgICBjb25zdCB2YWwgPSBTUUxQYXJzZXIucGFyc2VWYWx1ZShtYXRjaFszXS50cmltKCkpO1xuICAgICAgICBjb25kaXRpb25zLnB1c2goW2NvbCwgb3AsIHZhbF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb25kaXRpb25zO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VVcGRhdGUoc3FsOiBzdHJpbmcpOiBQYXJzZWRTUUwge1xuICAgIGNvbnN0IG1hdGNoID0gc3FsLm1hdGNoKC9VUERBVEVcXHMrKFxcdyspXFxzK1NFVFxccysoLis/KSg/OlxccytXSEVSRVxccysoLispKT8kL2lzKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgVVBEQVRFOiAke3NxbH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCB0YWJsZSA9IG1hdGNoWzFdO1xuICAgIGNvbnN0IHNldENsYXVzZSA9IG1hdGNoWzJdO1xuICAgIGNvbnN0IHdoZXJlQ2xhdXNlID0gbWF0Y2hbM107XG5cbiAgICAvLyBQYXJzZSBTRVQgY2xhdXNlXG4gICAgY29uc3QgdXBkYXRlczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgIGZvciAoY29uc3QgcGFydCBvZiBzZXRDbGF1c2Uuc3BsaXQoJywnKSkge1xuICAgICAgY29uc3QgZXFNYXRjaCA9IHBhcnQubWF0Y2goL1xccyooXFx3KylcXHMqPVxccyooLispXFxzKi8pO1xuICAgICAgaWYgKGVxTWF0Y2gpIHtcbiAgICAgICAgdXBkYXRlc1tlcU1hdGNoWzFdXSA9IFNRTFBhcnNlci5wYXJzZVZhbHVlKGVxTWF0Y2hbMl0udHJpbSgpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgY29uZGl0aW9uczogQXJyYXk8W3N0cmluZywgc3RyaW5nLCBhbnldPiA9IFtdO1xuICAgIGlmICh3aGVyZUNsYXVzZSkge1xuICAgICAgY29uZGl0aW9ucyA9IFNRTFBhcnNlci5wYXJzZVdoZXJlKHdoZXJlQ2xhdXNlKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBvcGVyYXRpb246ICdVUERBVEUnLCBkYXRhOiB7IHRhYmxlLCB1cGRhdGVzLCB3aGVyZTogY29uZGl0aW9ucyB9IH07XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZURlbGV0ZShzcWw6IHN0cmluZyk6IFBhcnNlZFNRTCB7XG4gICAgY29uc3QgbWF0Y2ggPSBzcWwubWF0Y2goL0RFTEVURVxccytGUk9NXFxzKyhcXHcrKSg/OlxccytXSEVSRVxccysoLispKT8kL2lzKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgREVMRVRFOiAke3NxbH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCB0YWJsZSA9IG1hdGNoWzFdO1xuICAgIGxldCBjb25kaXRpb25zOiBBcnJheTxbc3RyaW5nLCBzdHJpbmcsIGFueV0+ID0gW107XG4gICAgaWYgKG1hdGNoWzJdKSB7XG4gICAgICBjb25kaXRpb25zID0gU1FMUGFyc2VyLnBhcnNlV2hlcmUobWF0Y2hbMl0pO1xuICAgIH1cblxuICAgIHJldHVybiB7IG9wZXJhdGlvbjogJ0RFTEVURScsIGRhdGE6IHsgdGFibGUsIHdoZXJlOiBjb25kaXRpb25zIH0gfTtcbiAgfVxufVxuXG4vKipcbiAqIEludGVyZmFjZSBmb3IgZGF0YWJhc2Ugb3BlcmF0aW9ucyByZXF1aXJlZCBieSBTUUxFeGVjdXRvci5cbiAqL1xuaW50ZXJmYWNlIERhdGFiYXNlSW50ZXJmYWNlIHtcbiAgZ2V0KGtleTogQnVmZmVyIHwgc3RyaW5nKTogUHJvbWlzZTxCdWZmZXIgfCBudWxsPjtcbiAgcHV0KGtleTogQnVmZmVyIHwgc3RyaW5nLCB2YWx1ZTogQnVmZmVyIHwgc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbiAgZGVsZXRlKGtleTogQnVmZmVyIHwgc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbiAgc2NhbihwcmVmaXg6IHN0cmluZyk6IFByb21pc2U8QXJyYXk8eyBrZXk6IEJ1ZmZlcjsgdmFsdWU6IEJ1ZmZlciB9Pj47XG59XG5cbi8qKlxuICogU1FMIEV4ZWN1dG9yIHRoYXQgb3BlcmF0ZXMgb24gYSBLViBkYXRhYmFzZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFNRTEV4ZWN1dG9yIHtcbiAgcHJpdmF0ZSBkYjogRGF0YWJhc2VJbnRlcmZhY2U7XG5cbiAgLy8gS2V5IHByZWZpeGVzIGZvciBTUUwgZGF0YVxuICBwcml2YXRlIHJlYWRvbmx5IFRBQkxFX1BSRUZJWCA9ICdfc3FsL3RhYmxlcy8nO1xuICBwcml2YXRlIHJlYWRvbmx5IFNDSEVNQV9TVUZGSVggPSAnL3NjaGVtYSc7XG4gIHByaXZhdGUgcmVhZG9ubHkgUk9XU19QUkVGSVggPSAnL3Jvd3MvJztcbiAgcHJpdmF0ZSByZWFkb25seSBJTkRFWF9QUkVGSVggPSAnL2luZGV4ZXMvJztcblxuICBjb25zdHJ1Y3RvcihkYjogRGF0YWJhc2VJbnRlcmZhY2UpIHtcbiAgICB0aGlzLmRiID0gZGI7XG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZSBhIFNRTCBzdGF0ZW1lbnQuXG4gICAqL1xuICBhc3luYyBleGVjdXRlKHNxbDogc3RyaW5nKTogUHJvbWlzZTxTUUxRdWVyeVJlc3VsdD4ge1xuICAgIGNvbnN0IHsgb3BlcmF0aW9uLCBkYXRhIH0gPSBTUUxQYXJzZXIucGFyc2Uoc3FsKTtcblxuICAgIHN3aXRjaCAob3BlcmF0aW9uKSB7XG4gICAgICBjYXNlICdDUkVBVEVfVEFCTEUnOlxuICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVUYWJsZShkYXRhKTtcbiAgICAgIGNhc2UgJ0RST1BfVEFCTEUnOlxuICAgICAgICByZXR1cm4gdGhpcy5kcm9wVGFibGUoZGF0YSk7XG4gICAgICBjYXNlICdDUkVBVEVfSU5ERVgnOlxuICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVJbmRleChkYXRhKTtcbiAgICAgIGNhc2UgJ0RST1BfSU5ERVgnOlxuICAgICAgICByZXR1cm4gdGhpcy5kcm9wSW5kZXgoZGF0YSk7XG4gICAgICBjYXNlICdJTlNFUlQnOlxuICAgICAgICByZXR1cm4gdGhpcy5pbnNlcnQoZGF0YSk7XG4gICAgICBjYXNlICdTRUxFQ1QnOlxuICAgICAgICByZXR1cm4gdGhpcy5zZWxlY3QoZGF0YSk7XG4gICAgICBjYXNlICdVUERBVEUnOlxuICAgICAgICByZXR1cm4gdGhpcy51cGRhdGUoZGF0YSk7XG4gICAgICBjYXNlICdERUxFVEUnOlxuICAgICAgICByZXR1cm4gdGhpcy5kZWxldGVSb3dzKGRhdGEpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIG9wZXJhdGlvbjogJHtvcGVyYXRpb259YCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzY2hlbWFLZXkodGFibGU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuVEFCTEVfUFJFRklYICsgdGFibGUgKyB0aGlzLlNDSEVNQV9TVUZGSVg7XG4gIH1cblxuICBwcml2YXRlIHJvd0tleSh0YWJsZTogc3RyaW5nLCByb3dJZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5UQUJMRV9QUkVGSVggKyB0YWJsZSArIHRoaXMuUk9XU19QUkVGSVggKyByb3dJZDtcbiAgfVxuXG4gIHByaXZhdGUgcm93UHJlZml4KHRhYmxlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLlRBQkxFX1BSRUZJWCArIHRhYmxlICsgdGhpcy5ST1dTX1BSRUZJWDtcbiAgfVxuXG4gIHByaXZhdGUgaW5kZXhNZXRhS2V5KHRhYmxlOiBzdHJpbmcsIGluZGV4TmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5UQUJMRV9QUkVGSVggKyB0YWJsZSArIHRoaXMuSU5ERVhfUFJFRklYICsgaW5kZXhOYW1lICsgJy9tZXRhJztcbiAgfVxuXG4gIHByaXZhdGUgaW5kZXhQcmVmaXgodGFibGU6IHN0cmluZywgaW5kZXhOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLlRBQkxFX1BSRUZJWCArIHRhYmxlICsgdGhpcy5JTkRFWF9QUkVGSVggKyBpbmRleE5hbWUgKyAnLyc7XG4gIH1cblxuICBwcml2YXRlIGluZGV4S2V5KHRhYmxlOiBzdHJpbmcsIGluZGV4TmFtZTogc3RyaW5nLCBjb2x1bW5WYWx1ZTogc3RyaW5nLCByb3dJZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5UQUJMRV9QUkVGSVggKyB0YWJsZSArIHRoaXMuSU5ERVhfUFJFRklYICsgaW5kZXhOYW1lICsgJy8nICsgY29sdW1uVmFsdWUgKyAnLycgKyByb3dJZDtcbiAgfVxuXG4gIHByaXZhdGUgaW5kZXhWYWx1ZVByZWZpeCh0YWJsZTogc3RyaW5nLCBpbmRleE5hbWU6IHN0cmluZywgY29sdW1uVmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuVEFCTEVfUFJFRklYICsgdGFibGUgKyB0aGlzLklOREVYX1BSRUZJWCArIGluZGV4TmFtZSArICcvJyArIGNvbHVtblZhbHVlICsgJy8nO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRTY2hlbWEodGFibGU6IHN0cmluZyk6IFByb21pc2U8VGFibGVTY2hlbWEgfCBudWxsPiB7XG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMuZGIuZ2V0KHRoaXMuc2NoZW1hS2V5KHRhYmxlKSk7XG4gICAgaWYgKCFkYXRhKSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShkYXRhLnRvU3RyaW5nKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRJbmRleGVzKHRhYmxlOiBzdHJpbmcpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+IHtcbiAgICAvLyBSZXR1cm5zIG1hcCBvZiBpbmRleF9uYW1lIC0+IGNvbHVtbl9uYW1lXG4gICAgY29uc3QgaW5kZXhlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgIGNvbnN0IHByZWZpeCA9IHRoaXMuVEFCTEVfUFJFRklYICsgdGFibGUgKyB0aGlzLklOREVYX1BSRUZJWDtcbiAgICBjb25zdCBwYWlycyA9IGF3YWl0IHRoaXMuZGIuc2NhbihwcmVmaXgpO1xuXG4gICAgZm9yIChjb25zdCB7IGtleSwgdmFsdWUgfSBvZiBwYWlycykge1xuICAgICAgY29uc3Qga2V5U3RyID0ga2V5LnRvU3RyaW5nKCk7XG4gICAgICBpZiAoa2V5U3RyLmVuZHNXaXRoKCcvbWV0YScpKSB7XG4gICAgICAgIGNvbnN0IGluZm86IEluZGV4SW5mbyA9IEpTT04ucGFyc2UodmFsdWUudG9TdHJpbmcoKSk7XG4gICAgICAgIGNvbnN0IHBhcnRzID0ga2V5U3RyLnNwbGl0KCcvJyk7XG4gICAgICAgIGlmIChwYXJ0cy5sZW5ndGggPj0gNSkge1xuICAgICAgICAgIGNvbnN0IGluZGV4TmFtZSA9IHBhcnRzW3BhcnRzLmxlbmd0aCAtIDJdO1xuICAgICAgICAgIGluZGV4ZXNbaW5kZXhOYW1lXSA9IGluZm8uY29sdW1uO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGluZGV4ZXM7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGhhc0luZGV4Rm9yQ29sdW1uKHRhYmxlOiBzdHJpbmcsIGNvbHVtbjogc3RyaW5nKTogUHJvbWlzZTx7IGhhczogYm9vbGVhbjsgbmFtZTogc3RyaW5nIH0+IHtcbiAgICBjb25zdCBpbmRleGVzID0gYXdhaXQgdGhpcy5nZXRJbmRleGVzKHRhYmxlKTtcbiAgICBmb3IgKGNvbnN0IFtpbmRleE5hbWUsIGluZGV4Q29sXSBvZiBPYmplY3QuZW50cmllcyhpbmRleGVzKSkge1xuICAgICAgaWYgKGluZGV4Q29sID09PSBjb2x1bW4pIHtcbiAgICAgICAgcmV0dXJuIHsgaGFzOiB0cnVlLCBuYW1lOiBpbmRleE5hbWUgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHsgaGFzOiBmYWxzZSwgbmFtZTogJycgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9va3VwQnlJbmRleCh0YWJsZTogc3RyaW5nLCBpbmRleE5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmluZGV4VmFsdWVQcmVmaXgodGFibGUsIGluZGV4TmFtZSwgdmFsdWUpO1xuICAgIGNvbnN0IHBhaXJzID0gYXdhaXQgdGhpcy5kYi5zY2FuKHByZWZpeCk7XG4gICAgcmV0dXJuIHBhaXJzLm1hcChwID0+IHAudmFsdWUudG9TdHJpbmcoKSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUluZGV4KFxuICAgIHRhYmxlOiBzdHJpbmcsXG4gICAgaW5kZXhOYW1lOiBzdHJpbmcsXG4gICAgY29sdW1uOiBzdHJpbmcsXG4gICAgb2xkUm93OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIG5ld1JvdzogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICByb3dJZDogc3RyaW5nXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG9sZFZhbCA9IG9sZFJvd1tjb2x1bW5dO1xuICAgIGNvbnN0IG5ld1ZhbCA9IG5ld1Jvd1tjb2x1bW5dO1xuXG4gICAgaWYgKG9sZFZhbCA9PT0gbmV3VmFsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUmVtb3ZlIG9sZCBpbmRleCBlbnRyeVxuICAgIGlmIChvbGRWYWwgIT0gbnVsbCkge1xuICAgICAgY29uc3Qgb2xkS2V5ID0gdGhpcy5pbmRleEtleSh0YWJsZSwgaW5kZXhOYW1lLCBTdHJpbmcob2xkVmFsKSwgcm93SWQpO1xuICAgICAgYXdhaXQgdGhpcy5kYi5kZWxldGUob2xkS2V5KTtcbiAgICB9XG5cbiAgICAvLyBBZGQgbmV3IGluZGV4IGVudHJ5XG4gICAgaWYgKG5ld1ZhbCAhPSBudWxsKSB7XG4gICAgICBjb25zdCBuZXdLZXkgPSB0aGlzLmluZGV4S2V5KHRhYmxlLCBpbmRleE5hbWUsIFN0cmluZyhuZXdWYWwpLCByb3dJZCk7XG4gICAgICBhd2FpdCB0aGlzLmRiLnB1dChuZXdLZXksIHJvd0lkKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZpbmRJbmRleGVkRXF1YWxpdHlDb25kaXRpb24oXG4gICAgdGFibGU6IHN0cmluZyxcbiAgICBjb25kaXRpb25zOiBBcnJheTxbc3RyaW5nLCBzdHJpbmcsIGFueV0+LFxuICAgIGluZGV4ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cbiAgKTogW3N0cmluZywgYW55XSB8IG51bGwge1xuICAgIGZvciAoY29uc3QgW2NvbCwgb3AsIHZhbF0gb2YgY29uZGl0aW9ucykge1xuICAgICAgaWYgKG9wID09PSAnPScgJiYgT2JqZWN0LnZhbHVlcyhpbmRleGVzKS5pbmNsdWRlcyhjb2wpKSB7XG4gICAgICAgIHJldHVybiBbY29sLCB2YWxdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY3JlYXRlVGFibGUoZGF0YTogUmVjb3JkPHN0cmluZywgYW55Pik6IFByb21pc2U8U1FMUXVlcnlSZXN1bHQ+IHtcbiAgICBjb25zdCB0YWJsZSA9IGRhdGEudGFibGU7XG4gICAgY29uc3QgY29sdW1ucyA9IGRhdGEuY29sdW1ucyBhcyBDb2x1bW5bXTtcbiAgICBjb25zdCBwcmltYXJ5S2V5ID0gZGF0YS5wcmltYXJ5S2V5O1xuXG4gICAgLy8gQ2hlY2sgaWYgdGFibGUgZXhpc3RzXG4gICAgaWYgKGF3YWl0IHRoaXMuZ2V0U2NoZW1hKHRhYmxlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUYWJsZSAnJHt0YWJsZX0nIGFscmVhZHkgZXhpc3RzYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2NoZW1hOiBUYWJsZVNjaGVtYSA9IHsgbmFtZTogdGFibGUsIGNvbHVtbnMsIHByaW1hcnlLZXkgfTtcbiAgICBhd2FpdCB0aGlzLmRiLnB1dCh0aGlzLnNjaGVtYUtleSh0YWJsZSksIEpTT04uc3RyaW5naWZ5KHNjaGVtYSkpO1xuXG4gICAgcmV0dXJuIHsgcm93czogW10sIGNvbHVtbnM6IFtdLCByb3dzQWZmZWN0ZWQ6IDAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZHJvcFRhYmxlKGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQcm9taXNlPFNRTFF1ZXJ5UmVzdWx0PiB7XG4gICAgY29uc3QgdGFibGUgPSBkYXRhLnRhYmxlO1xuXG4gICAgLy8gRGVsZXRlIGFsbCBpbmRleGVzIGZpcnN0XG4gICAgY29uc3QgaW5kZXhlcyA9IGF3YWl0IHRoaXMuZ2V0SW5kZXhlcyh0YWJsZSk7XG4gICAgZm9yIChjb25zdCBpbmRleE5hbWUgb2YgT2JqZWN0LmtleXMoaW5kZXhlcykpIHtcbiAgICAgIGNvbnN0IGlkeFByZWZpeCA9IHRoaXMuaW5kZXhQcmVmaXgodGFibGUsIGluZGV4TmFtZSk7XG4gICAgICBjb25zdCBpZHhQYWlycyA9IGF3YWl0IHRoaXMuZGIuc2NhbihpZHhQcmVmaXgpO1xuICAgICAgZm9yIChjb25zdCB7IGtleSB9IG9mIGlkeFBhaXJzKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuZGIuZGVsZXRlKGtleSk7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZSh0aGlzLmluZGV4TWV0YUtleSh0YWJsZSwgaW5kZXhOYW1lKSk7XG4gICAgfVxuXG4gICAgLy8gRGVsZXRlIGFsbCByb3dzXG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5yb3dQcmVmaXgodGFibGUpO1xuICAgIGNvbnN0IHJvd3MgPSBhd2FpdCB0aGlzLmRiLnNjYW4ocHJlZml4KTtcbiAgICBsZXQgcm93c0RlbGV0ZWQgPSAwO1xuXG4gICAgZm9yIChjb25zdCB7IGtleSB9IG9mIHJvd3MpIHtcbiAgICAgIGF3YWl0IHRoaXMuZGIuZGVsZXRlKGtleSk7XG4gICAgICByb3dzRGVsZXRlZCsrO1xuICAgIH1cblxuICAgIC8vIERlbGV0ZSBzY2hlbWFcbiAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZSh0aGlzLnNjaGVtYUtleSh0YWJsZSkpO1xuXG4gICAgcmV0dXJuIHsgcm93czogW10sIGNvbHVtbnM6IFtdLCByb3dzQWZmZWN0ZWQ6IHJvd3NEZWxldGVkIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNyZWF0ZUluZGV4KGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQcm9taXNlPFNRTFF1ZXJ5UmVzdWx0PiB7XG4gICAgY29uc3QgaW5kZXhOYW1lID0gZGF0YS5pbmRleE5hbWU7XG4gICAgY29uc3QgdGFibGUgPSBkYXRhLnRhYmxlO1xuICAgIGNvbnN0IGNvbHVtbiA9IGRhdGEuY29sdW1uO1xuXG4gICAgY29uc3Qgc2NoZW1hID0gYXdhaXQgdGhpcy5nZXRTY2hlbWEodGFibGUpO1xuICAgIGlmICghc2NoZW1hKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRhYmxlICcke3RhYmxlfScgZG9lcyBub3QgZXhpc3RgKTtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBjb2x1bW4gZXhpc3RzXG4gICAgaWYgKCFzY2hlbWEuY29sdW1ucy5zb21lKGMgPT4gYy5uYW1lID09PSBjb2x1bW4pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvbHVtbiAnJHtjb2x1bW59JyBkb2VzIG5vdCBleGlzdCBpbiB0YWJsZSAnJHt0YWJsZX0nYCk7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaW5kZXggZG9lc24ndCBhbHJlYWR5IGV4aXN0XG4gICAgY29uc3QgbWV0YUtleSA9IHRoaXMuaW5kZXhNZXRhS2V5KHRhYmxlLCBpbmRleE5hbWUpO1xuICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgdGhpcy5kYi5nZXQobWV0YUtleSk7XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEluZGV4ICcke2luZGV4TmFtZX0nIGFscmVhZHkgZXhpc3RzIG9uIHRhYmxlICcke3RhYmxlfSdgKTtcbiAgICB9XG5cbiAgICAvLyBTdG9yZSBpbmRleCBtZXRhZGF0YVxuICAgIGNvbnN0IG1ldGE6IEluZGV4SW5mbyA9IHsgY29sdW1uLCB0YWJsZSB9O1xuICAgIGF3YWl0IHRoaXMuZGIucHV0KG1ldGFLZXksIEpTT04uc3RyaW5naWZ5KG1ldGEpKTtcblxuICAgIC8vIEJ1aWxkIGluZGV4IGZyb20gZXhpc3Rpbmcgcm93c1xuICAgIGNvbnN0IHByZWZpeCA9IHRoaXMucm93UHJlZml4KHRhYmxlKTtcbiAgICBjb25zdCBwYWlycyA9IGF3YWl0IHRoaXMuZGIuc2NhbihwcmVmaXgpO1xuICAgIGxldCBpbmRleGVkQ291bnQgPSAwO1xuXG4gICAgZm9yIChjb25zdCB7IHZhbHVlIH0gb2YgcGFpcnMpIHtcbiAgICAgIGNvbnN0IHJvdyA9IEpTT04ucGFyc2UodmFsdWUudG9TdHJpbmcoKSk7XG4gICAgICBjb25zdCByb3dJZCA9IHJvd1snX2lkJ107XG4gICAgICBjb25zdCBjb2xWYWx1ZSA9IHJvd1tjb2x1bW5dO1xuXG4gICAgICBpZiAoY29sVmFsdWUgIT0gbnVsbCkge1xuICAgICAgICBjb25zdCBpZHhLZXkgPSB0aGlzLmluZGV4S2V5KHRhYmxlLCBpbmRleE5hbWUsIFN0cmluZyhjb2xWYWx1ZSksIHJvd0lkKTtcbiAgICAgICAgYXdhaXQgdGhpcy5kYi5wdXQoaWR4S2V5LCByb3dJZCk7XG4gICAgICAgIGluZGV4ZWRDb3VudCsrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7IHJvd3M6IFtdLCBjb2x1bW5zOiBbXSwgcm93c0FmZmVjdGVkOiBpbmRleGVkQ291bnQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZHJvcEluZGV4KGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQcm9taXNlPFNRTFF1ZXJ5UmVzdWx0PiB7XG4gICAgY29uc3QgaW5kZXhOYW1lID0gZGF0YS5pbmRleE5hbWU7XG4gICAgY29uc3QgdGFibGUgPSBkYXRhLnRhYmxlO1xuXG4gICAgLy8gRGVsZXRlIGFsbCBpbmRleCBlbnRyaWVzXG4gICAgY29uc3QgaWR4UHJlZml4ID0gdGhpcy5pbmRleFByZWZpeCh0YWJsZSwgaW5kZXhOYW1lKTtcbiAgICBjb25zdCBwYWlycyA9IGF3YWl0IHRoaXMuZGIuc2NhbihpZHhQcmVmaXgpO1xuICAgIGxldCBkZWxldGVkID0gMDtcblxuICAgIGZvciAoY29uc3QgeyBrZXkgfSBvZiBwYWlycykge1xuICAgICAgYXdhaXQgdGhpcy5kYi5kZWxldGUoa2V5KTtcbiAgICAgIGRlbGV0ZWQrKztcbiAgICB9XG5cbiAgICAvLyBEZWxldGUgaW5kZXggbWV0YWRhdGFcbiAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZSh0aGlzLmluZGV4TWV0YUtleSh0YWJsZSwgaW5kZXhOYW1lKSk7XG5cbiAgICByZXR1cm4geyByb3dzOiBbXSwgY29sdW1uczogW10sIHJvd3NBZmZlY3RlZDogZGVsZXRlZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpbnNlcnQoZGF0YTogUmVjb3JkPHN0cmluZywgYW55Pik6IFByb21pc2U8U1FMUXVlcnlSZXN1bHQ+IHtcbiAgICBjb25zdCB0YWJsZSA9IGRhdGEudGFibGU7XG4gICAgbGV0IGNvbHVtbnMgPSBkYXRhLmNvbHVtbnMgYXMgc3RyaW5nW10gfCBudWxsO1xuICAgIGNvbnN0IHZhbHVlcyA9IGRhdGEudmFsdWVzIGFzIGFueVtdO1xuXG4gICAgY29uc3Qgc2NoZW1hID0gYXdhaXQgdGhpcy5nZXRTY2hlbWEodGFibGUpO1xuICAgIGlmICghc2NoZW1hKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRhYmxlICcke3RhYmxlfScgZG9lcyBub3QgZXhpc3RgKTtcbiAgICB9XG5cbiAgICAvLyBJZiBubyBjb2x1bW5zIHNwZWNpZmllZCwgdXNlIHNjaGVtYSBvcmRlclxuICAgIGlmICghY29sdW1ucykge1xuICAgICAgY29sdW1ucyA9IHNjaGVtYS5jb2x1bW5zLm1hcCgoYykgPT4gYy5uYW1lKTtcbiAgICB9XG5cbiAgICBpZiAoY29sdW1ucy5sZW5ndGggIT09IHZhbHVlcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYENvbHVtbiBjb3VudCAoJHtjb2x1bW5zLmxlbmd0aH0pIGRvZXNuJ3QgbWF0Y2ggdmFsdWUgY291bnQgKCR7dmFsdWVzLmxlbmd0aH0pYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgcm93IG9iamVjdFxuICAgIGNvbnN0IHJvdzogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29sdW1ucy5sZW5ndGg7IGkrKykge1xuICAgICAgcm93W2NvbHVtbnNbaV1dID0gdmFsdWVzW2ldO1xuICAgIH1cblxuICAgIC8vIEdlbmVyYXRlIHJvdyBJRFxuICAgIGxldCByb3dJZDogc3RyaW5nO1xuICAgIGlmIChzY2hlbWEucHJpbWFyeUtleSAmJiBzY2hlbWEucHJpbWFyeUtleSBpbiByb3cpIHtcbiAgICAgIHJvd0lkID0gU3RyaW5nKHJvd1tzY2hlbWEucHJpbWFyeUtleV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByb3dJZCA9IHV1aWR2NCgpO1xuICAgIH1cbiAgICByb3dbJ19pZCddID0gcm93SWQ7XG5cbiAgICBhd2FpdCB0aGlzLmRiLnB1dCh0aGlzLnJvd0tleSh0YWJsZSwgcm93SWQpLCBKU09OLnN0cmluZ2lmeShyb3cpKTtcblxuICAgIC8vIE1haW50YWluIGluZGV4ZXNcbiAgICBjb25zdCBpbmRleGVzID0gYXdhaXQgdGhpcy5nZXRJbmRleGVzKHRhYmxlKTtcbiAgICBmb3IgKGNvbnN0IFtpbmRleE5hbWUsIGluZGV4Q29sXSBvZiBPYmplY3QuZW50cmllcyhpbmRleGVzKSkge1xuICAgICAgaWYgKHJvd1tpbmRleENvbF0gIT0gbnVsbCkge1xuICAgICAgICBjb25zdCBpZHhLZXkgPSB0aGlzLmluZGV4S2V5KHRhYmxlLCBpbmRleE5hbWUsIFN0cmluZyhyb3dbaW5kZXhDb2xdKSwgcm93SWQpO1xuICAgICAgICBhd2FpdCB0aGlzLmRiLnB1dChpZHhLZXksIHJvd0lkKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyByb3dzOiBbXSwgY29sdW1uczogW10sIHJvd3NBZmZlY3RlZDogMSB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzZWxlY3QoZGF0YTogUmVjb3JkPHN0cmluZywgYW55Pik6IFByb21pc2U8U1FMUXVlcnlSZXN1bHQ+IHtcbiAgICBjb25zdCB0YWJsZSA9IGRhdGEudGFibGU7XG4gICAgbGV0IGNvbHVtbnMgPSBkYXRhLmNvbHVtbnMgYXMgc3RyaW5nW107XG4gICAgY29uc3QgY29uZGl0aW9ucyA9IGRhdGEud2hlcmUgYXMgQXJyYXk8W3N0cmluZywgc3RyaW5nLCBhbnldPjtcbiAgICBjb25zdCBvcmRlckJ5ID0gZGF0YS5vcmRlckJ5IGFzIEFycmF5PFtzdHJpbmcsIHN0cmluZ10+O1xuICAgIGNvbnN0IGxpbWl0ID0gZGF0YS5saW1pdCBhcyBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgY29uc3Qgb2Zmc2V0ID0gZGF0YS5vZmZzZXQgYXMgbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gICAgY29uc3Qgc2NoZW1hID0gYXdhaXQgdGhpcy5nZXRTY2hlbWEodGFibGUpO1xuICAgIGlmICghc2NoZW1hKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRhYmxlICcke3RhYmxlfScgZG9lcyBub3QgZXhpc3RgKTtcbiAgICB9XG5cbiAgICAvLyBHZXQgY29sdW1uIG5hbWVzXG4gICAgaWYgKGNvbHVtbnMubGVuZ3RoID09PSAxICYmIGNvbHVtbnNbMF0gPT09ICcqJykge1xuICAgICAgY29sdW1ucyA9IHNjaGVtYS5jb2x1bW5zLm1hcCgoYykgPT4gYy5uYW1lKTtcbiAgICB9XG5cbiAgICAvLyBTY2FuIGFsbCByb3dzXG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5yb3dQcmVmaXgodGFibGUpO1xuICAgIGNvbnN0IHNjYW5SZXN1bHRzID0gYXdhaXQgdGhpcy5kYi5zY2FuKHByZWZpeCk7XG4gICAgbGV0IHJvd3M6IEFycmF5PFJlY29yZDxzdHJpbmcsIGFueT4+ID0gW107XG5cbiAgICBmb3IgKGNvbnN0IHsgdmFsdWUgfSBvZiBzY2FuUmVzdWx0cykge1xuICAgICAgY29uc3Qgcm93ID0gSlNPTi5wYXJzZSh2YWx1ZS50b1N0cmluZygpKTtcblxuICAgICAgLy8gQXBwbHkgV0hFUkUgY29uZGl0aW9uc1xuICAgICAgaWYgKHRoaXMubWF0Y2hlc0NvbmRpdGlvbnMocm93LCBjb25kaXRpb25zKSkge1xuICAgICAgICAvLyBQcm9qZWN0IGNvbHVtbnNcbiAgICAgICAgY29uc3QgcHJvamVjdGVkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgICAgIGZvciAoY29uc3QgY29sIG9mIGNvbHVtbnMpIHtcbiAgICAgICAgICBpZiAoY29sIGluIHJvdykge1xuICAgICAgICAgICAgcHJvamVjdGVkW2NvbF0gPSByb3dbY29sXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcm93cy5wdXNoKHByb2plY3RlZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQXBwbHkgT1JERVIgQllcbiAgICBpZiAob3JkZXJCeSAmJiBvcmRlckJ5Lmxlbmd0aCA+IDApIHtcbiAgICAgIHJvd3Muc29ydCgoYSwgYikgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IFtjb2wsIGRpcmVjdGlvbl0gb2Ygb3JkZXJCeSkge1xuICAgICAgICAgIGNvbnN0IGFWYWwgPSBhW2NvbF07XG4gICAgICAgICAgY29uc3QgYlZhbCA9IGJbY29sXTtcblxuICAgICAgICAgIC8vIEhhbmRsZSBudWxsc1xuICAgICAgICAgIGlmIChhVmFsID09PSBudWxsIHx8IGFWYWwgPT09IHVuZGVmaW5lZCkgcmV0dXJuIDE7XG4gICAgICAgICAgaWYgKGJWYWwgPT09IG51bGwgfHwgYlZhbCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gLTE7XG5cbiAgICAgICAgICBsZXQgY21wID0gMDtcbiAgICAgICAgICBpZiAoYVZhbCA8IGJWYWwpIGNtcCA9IC0xO1xuICAgICAgICAgIGVsc2UgaWYgKGFWYWwgPiBiVmFsKSBjbXAgPSAxO1xuXG4gICAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gJ0RFU0MnKSBjbXAgPSAtY21wO1xuICAgICAgICAgIGlmIChjbXAgIT09IDApIHJldHVybiBjbXA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBBcHBseSBPRkZTRVQgYW5kIExJTUlUXG4gICAgaWYgKG9mZnNldCAmJiBvZmZzZXQgPiAwKSB7XG4gICAgICByb3dzID0gcm93cy5zbGljZShvZmZzZXQpO1xuICAgIH1cbiAgICBpZiAobGltaXQgIT09IHVuZGVmaW5lZCAmJiBsaW1pdCA+IDApIHtcbiAgICAgIHJvd3MgPSByb3dzLnNsaWNlKDAsIGxpbWl0KTtcbiAgICB9XG5cbiAgICByZXR1cm4geyByb3dzLCBjb2x1bW5zLCByb3dzQWZmZWN0ZWQ6IDAgfTtcbiAgfVxuXG4gIHByaXZhdGUgbWF0Y2hlc0NvbmRpdGlvbnMoXG4gICAgcm93OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIGNvbmRpdGlvbnM6IEFycmF5PFtzdHJpbmcsIHN0cmluZywgYW55XT5cbiAgKTogYm9vbGVhbiB7XG4gICAgZm9yIChjb25zdCBbY29sLCBvcCwgdmFsXSBvZiBjb25kaXRpb25zKSB7XG4gICAgICBjb25zdCByb3dWYWwgPSByb3dbY29sXTtcblxuICAgICAgc3dpdGNoIChvcCkge1xuICAgICAgICBjYXNlICc9JzpcbiAgICAgICAgICBpZiAocm93VmFsICE9PSB2YWwpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnIT0nOlxuICAgICAgICAgIGlmIChyb3dWYWwgPT09IHZhbCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICc+JzpcbiAgICAgICAgICBpZiAocm93VmFsID09PSBudWxsIHx8IHJvd1ZhbCA9PT0gdW5kZWZpbmVkIHx8IHJvd1ZhbCA8PSB2YWwpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnPj0nOlxuICAgICAgICAgIGlmIChyb3dWYWwgPT09IG51bGwgfHwgcm93VmFsID09PSB1bmRlZmluZWQgfHwgcm93VmFsIDwgdmFsKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJzwnOlxuICAgICAgICAgIGlmIChyb3dWYWwgPT09IG51bGwgfHwgcm93VmFsID09PSB1bmRlZmluZWQgfHwgcm93VmFsID49IHZhbCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICc8PSc6XG4gICAgICAgICAgaWYgKHJvd1ZhbCA9PT0gbnVsbCB8fCByb3dWYWwgPT09IHVuZGVmaW5lZCB8fCByb3dWYWwgPiB2YWwpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnTElLRSc6IHtcbiAgICAgICAgICBpZiAocm93VmFsID09PSBudWxsIHx8IHJvd1ZhbCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgY29uc3QgcGF0dGVybiA9IFN0cmluZyh2YWwpLnJlcGxhY2UoLyUvZywgJy4qJykucmVwbGFjZSgvXy9nLCAnLicpO1xuICAgICAgICAgIGlmICghbmV3IFJlZ0V4cChgXiR7cGF0dGVybn0kYCwgJ2knKS50ZXN0KFN0cmluZyhyb3dWYWwpKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ05PVF9MSUtFJzoge1xuICAgICAgICAgIGlmIChyb3dWYWwgPT09IG51bGwgfHwgcm93VmFsID09PSB1bmRlZmluZWQpIHJldHVybiB0cnVlO1xuICAgICAgICAgIGNvbnN0IHBhdHRlcm4gPSBTdHJpbmcodmFsKS5yZXBsYWNlKC8lL2csICcuKicpLnJlcGxhY2UoL18vZywgJy4nKTtcbiAgICAgICAgICBpZiAobmV3IFJlZ0V4cChgXiR7cGF0dGVybn0kYCwgJ2knKS50ZXN0KFN0cmluZyhyb3dWYWwpKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGUoZGF0YTogUmVjb3JkPHN0cmluZywgYW55Pik6IFByb21pc2U8U1FMUXVlcnlSZXN1bHQ+IHtcbiAgICBjb25zdCB0YWJsZSA9IGRhdGEudGFibGU7XG4gICAgY29uc3QgdXBkYXRlcyA9IGRhdGEudXBkYXRlcyBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSBkYXRhLndoZXJlIGFzIEFycmF5PFtzdHJpbmcsIHN0cmluZywgYW55XT47XG5cbiAgICBjb25zdCBzY2hlbWEgPSBhd2FpdCB0aGlzLmdldFNjaGVtYSh0YWJsZSk7XG4gICAgaWYgKCFzY2hlbWEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGFibGUgJyR7dGFibGV9JyBkb2VzIG5vdCBleGlzdGApO1xuICAgIH1cblxuICAgIGNvbnN0IGluZGV4ZXMgPSBhd2FpdCB0aGlzLmdldEluZGV4ZXModGFibGUpO1xuICAgIGxldCByb3dzQWZmZWN0ZWQgPSAwO1xuXG4gICAgLy8gVHJ5IGluZGV4LWFjY2VsZXJhdGVkIHBhdGhcbiAgICBjb25zdCBpbmRleGVkQ29uZCA9IHRoaXMuZmluZEluZGV4ZWRFcXVhbGl0eUNvbmRpdGlvbih0YWJsZSwgY29uZGl0aW9ucywgaW5kZXhlcyk7XG5cbiAgICBpZiAoaW5kZXhlZENvbmQpIHtcbiAgICAgIC8vIEluZGV4LWFjY2VsZXJhdGVkIFVQREFURVxuICAgICAgY29uc3QgW2NvbCwgdmFsXSA9IGluZGV4ZWRDb25kO1xuICAgICAgY29uc3QgaW5kZXhSZXN1bHQgPSBhd2FpdCB0aGlzLmhhc0luZGV4Rm9yQ29sdW1uKHRhYmxlLCBjb2wpO1xuICAgICAgXG4gICAgICBpZiAoaW5kZXhSZXN1bHQuaGFzKSB7XG4gICAgICAgIGNvbnN0IHJvd0lkcyA9IGF3YWl0IHRoaXMubG9va3VwQnlJbmRleCh0YWJsZSwgaW5kZXhSZXN1bHQubmFtZSwgU3RyaW5nKHZhbCkpO1xuICAgICAgICBcbiAgICAgICAgZm9yIChjb25zdCByb3dJZCBvZiByb3dJZHMpIHtcbiAgICAgICAgICBjb25zdCBrZXkgPSB0aGlzLnJvd0tleSh0YWJsZSwgcm93SWQpO1xuICAgICAgICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgdGhpcy5kYi5nZXQoa2V5KTtcbiAgICAgICAgICBpZiAoIXZhbHVlKSBjb250aW51ZTtcblxuICAgICAgICAgIGNvbnN0IG9sZFJvdyA9IEpTT04ucGFyc2UodmFsdWUudG9TdHJpbmcoKSk7XG5cbiAgICAgICAgICAvLyBBcHBseSBhbGwgV0hFUkUgY29uZGl0aW9ucyAobm90IGp1c3QgdGhlIGluZGV4ZWQgb25lKVxuICAgICAgICAgIGlmICghdGhpcy5tYXRjaGVzQ29uZGl0aW9ucyhvbGRSb3csIGNvbmRpdGlvbnMpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBBcHBseSB1cGRhdGVzXG4gICAgICAgICAgY29uc3QgbmV3Um93ID0geyAuLi5vbGRSb3cgfTtcbiAgICAgICAgICBmb3IgKGNvbnN0IFt1Y29sLCB1dmFsXSBvZiBPYmplY3QuZW50cmllcyh1cGRhdGVzKSkge1xuICAgICAgICAgICAgbmV3Um93W3Vjb2xdID0gdXZhbDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBVcGRhdGUgaW5kZXhlcyBmb3IgY2hhbmdlZCBjb2x1bW5zXG4gICAgICAgICAgZm9yIChjb25zdCBbaWR4TmFtZSwgaWR4Q29sXSBvZiBPYmplY3QuZW50cmllcyhpbmRleGVzKSkge1xuICAgICAgICAgICAgaWYgKGlkeENvbCBpbiB1cGRhdGVzKSB7XG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMudXBkYXRlSW5kZXgodGFibGUsIGlkeE5hbWUsIGlkeENvbCwgb2xkUm93LCBuZXdSb3csIHJvd0lkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhd2FpdCB0aGlzLmRiLnB1dChrZXksIEpTT04uc3RyaW5naWZ5KG5ld1JvdykpO1xuICAgICAgICAgIHJvd3NBZmZlY3RlZCsrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEZhbGxiYWNrOiBmdWxsIHRhYmxlIHNjYW5cbiAgICAgIGNvbnN0IHByZWZpeCA9IHRoaXMucm93UHJlZml4KHRhYmxlKTtcbiAgICAgIGNvbnN0IHNjYW5SZXN1bHRzID0gYXdhaXQgdGhpcy5kYi5zY2FuKHByZWZpeCk7XG5cbiAgICAgIGZvciAoY29uc3QgeyBrZXksIHZhbHVlIH0gb2Ygc2NhblJlc3VsdHMpIHtcbiAgICAgICAgY29uc3Qgb2xkUm93ID0gSlNPTi5wYXJzZSh2YWx1ZS50b1N0cmluZygpKTtcblxuICAgICAgICAvLyBBcHBseSBXSEVSRSBjb25kaXRpb25zXG4gICAgICAgIGlmICh0aGlzLm1hdGNoZXNDb25kaXRpb25zKG9sZFJvdywgY29uZGl0aW9ucykpIHtcbiAgICAgICAgICAvLyBBcHBseSB1cGRhdGVzXG4gICAgICAgICAgY29uc3QgbmV3Um93ID0geyAuLi5vbGRSb3cgfTtcbiAgICAgICAgICBmb3IgKGNvbnN0IFtjb2wsIHZhbF0gb2YgT2JqZWN0LmVudHJpZXModXBkYXRlcykpIHtcbiAgICAgICAgICAgIG5ld1Jvd1tjb2xdID0gdmFsO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHJvd0lkID0gb2xkUm93WydfaWQnXTtcblxuICAgICAgICAgIC8vIFVwZGF0ZSBpbmRleGVzIGZvciBjaGFuZ2VkIGNvbHVtbnNcbiAgICAgICAgICBmb3IgKGNvbnN0IFtpZHhOYW1lLCBpZHhDb2xdIG9mIE9iamVjdC5lbnRyaWVzKGluZGV4ZXMpKSB7XG4gICAgICAgICAgICBpZiAoaWR4Q29sIGluIHVwZGF0ZXMpIHtcbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVJbmRleCh0YWJsZSwgaWR4TmFtZSwgaWR4Q29sLCBvbGRSb3csIG5ld1Jvdywgcm93SWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGF3YWl0IHRoaXMuZGIucHV0KGtleSwgSlNPTi5zdHJpbmdpZnkobmV3Um93KSk7XG4gICAgICAgICAgcm93c0FmZmVjdGVkKys7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyByb3dzOiBbXSwgY29sdW1uczogW10sIHJvd3NBZmZlY3RlZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBkZWxldGVSb3dzKGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQcm9taXNlPFNRTFF1ZXJ5UmVzdWx0PiB7XG4gICAgY29uc3QgdGFibGUgPSBkYXRhLnRhYmxlO1xuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSBkYXRhLndoZXJlIGFzIEFycmF5PFtzdHJpbmcsIHN0cmluZywgYW55XT47XG5cbiAgICBjb25zdCBzY2hlbWEgPSBhd2FpdCB0aGlzLmdldFNjaGVtYSh0YWJsZSk7XG4gICAgaWYgKCFzY2hlbWEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGFibGUgJyR7dGFibGV9JyBkb2VzIG5vdCBleGlzdGApO1xuICAgIH1cblxuICAgIGNvbnN0IGluZGV4ZXMgPSBhd2FpdCB0aGlzLmdldEluZGV4ZXModGFibGUpO1xuICAgIGxldCByb3dzQWZmZWN0ZWQgPSAwO1xuXG4gICAgLy8gVHJ5IGluZGV4LWFjY2VsZXJhdGVkIHBhdGhcbiAgICBjb25zdCBpbmRleGVkQ29uZCA9IHRoaXMuZmluZEluZGV4ZWRFcXVhbGl0eUNvbmRpdGlvbih0YWJsZSwgY29uZGl0aW9ucywgaW5kZXhlcyk7XG5cbiAgICBpZiAoaW5kZXhlZENvbmQpIHtcbiAgICAgIC8vIEluZGV4LWFjY2VsZXJhdGVkIERFTEVURVxuICAgICAgY29uc3QgW2NvbCwgdmFsXSA9IGluZGV4ZWRDb25kO1xuICAgICAgY29uc3QgaW5kZXhSZXN1bHQgPSBhd2FpdCB0aGlzLmhhc0luZGV4Rm9yQ29sdW1uKHRhYmxlLCBjb2wpO1xuICAgICAgXG4gICAgICBpZiAoaW5kZXhSZXN1bHQuaGFzKSB7XG4gICAgICAgIGNvbnN0IHJvd0lkcyA9IGF3YWl0IHRoaXMubG9va3VwQnlJbmRleCh0YWJsZSwgaW5kZXhSZXN1bHQubmFtZSwgU3RyaW5nKHZhbCkpO1xuICAgICAgICBjb25zdCBrZXlzVG9EZWxldGU6IEJ1ZmZlcltdID0gW107XG4gICAgICAgIGNvbnN0IHJvd3NUb0RlbGV0ZTogQXJyYXk8eyByb3c6IFJlY29yZDxzdHJpbmcsIGFueT47IHJvd0lkOiBzdHJpbmcgfT4gPSBbXTtcblxuICAgICAgICBmb3IgKGNvbnN0IHJvd0lkIG9mIHJvd0lkcykge1xuICAgICAgICAgIGNvbnN0IGtleSA9IHRoaXMucm93S2V5KHRhYmxlLCByb3dJZCk7XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCB0aGlzLmRiLmdldChrZXkpO1xuICAgICAgICAgIGlmICghdmFsdWUpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgY29uc3Qgcm93ID0gSlNPTi5wYXJzZSh2YWx1ZS50b1N0cmluZygpKTtcblxuICAgICAgICAgIC8vIEFwcGx5IGFsbCBXSEVSRSBjb25kaXRpb25zIChub3QganVzdCB0aGUgaW5kZXhlZCBvbmUpXG4gICAgICAgICAgaWYgKHRoaXMubWF0Y2hlc0NvbmRpdGlvbnMocm93LCBjb25kaXRpb25zKSkge1xuICAgICAgICAgICAga2V5c1RvRGVsZXRlLnB1c2goQnVmZmVyLmZyb20oa2V5KSk7XG4gICAgICAgICAgICByb3dzVG9EZWxldGUucHVzaCh7IHJvdywgcm93SWQgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVsZXRlIHJvd3MgYW5kIHVwZGF0ZSBpbmRleGVzXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5c1RvRGVsZXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgY29uc3Qga2V5ID0ga2V5c1RvRGVsZXRlW2ldO1xuICAgICAgICAgIGNvbnN0IHsgcm93LCByb3dJZCB9ID0gcm93c1RvRGVsZXRlW2ldO1xuXG4gICAgICAgICAgLy8gUmVtb3ZlIGZyb20gYWxsIGluZGV4ZXNcbiAgICAgICAgICBmb3IgKGNvbnN0IFtpZHhOYW1lLCBpZHhDb2xdIG9mIE9iamVjdC5lbnRyaWVzKGluZGV4ZXMpKSB7XG4gICAgICAgICAgICBjb25zdCBlbXB0eVJvdzogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgICAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVJbmRleCh0YWJsZSwgaWR4TmFtZSwgaWR4Q29sLCByb3csIGVtcHR5Um93LCByb3dJZCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYXdhaXQgdGhpcy5kYi5kZWxldGUoa2V5KTtcbiAgICAgICAgICByb3dzQWZmZWN0ZWQrKztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBGYWxsYmFjazogZnVsbCB0YWJsZSBzY2FuXG4gICAgICBjb25zdCBwcmVmaXggPSB0aGlzLnJvd1ByZWZpeCh0YWJsZSk7XG4gICAgICBjb25zdCBzY2FuUmVzdWx0cyA9IGF3YWl0IHRoaXMuZGIuc2NhbihwcmVmaXgpO1xuICAgICAgY29uc3Qga2V5c1RvRGVsZXRlOiBCdWZmZXJbXSA9IFtdO1xuICAgICAgY29uc3Qgcm93c1RvRGVsZXRlOiBBcnJheTx7IHJvdzogUmVjb3JkPHN0cmluZywgYW55Pjsgcm93SWQ6IHN0cmluZyB9PiA9IFtdO1xuXG4gICAgICBmb3IgKGNvbnN0IHsga2V5LCB2YWx1ZSB9IG9mIHNjYW5SZXN1bHRzKSB7XG4gICAgICAgIGNvbnN0IHJvdyA9IEpTT04ucGFyc2UodmFsdWUudG9TdHJpbmcoKSk7XG5cbiAgICAgICAgLy8gQXBwbHkgV0hFUkUgY29uZGl0aW9uc1xuICAgICAgICBpZiAodGhpcy5tYXRjaGVzQ29uZGl0aW9ucyhyb3csIGNvbmRpdGlvbnMpKSB7XG4gICAgICAgICAgY29uc3Qgcm93SWQgPSByb3dbJ19pZCddO1xuICAgICAgICAgIGtleXNUb0RlbGV0ZS5wdXNoKGtleSk7XG4gICAgICAgICAgcm93c1RvRGVsZXRlLnB1c2goeyByb3csIHJvd0lkIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIERlbGV0ZSBjb2xsZWN0ZWQgcm93cyBhbmQgdXBkYXRlIGluZGV4ZXNcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5c1RvRGVsZXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGtleSA9IGtleXNUb0RlbGV0ZVtpXTtcbiAgICAgICAgY29uc3QgeyByb3csIHJvd0lkIH0gPSByb3dzVG9EZWxldGVbaV07XG5cbiAgICAgICAgLy8gUmVtb3ZlIGZyb20gYWxsIGluZGV4ZXNcbiAgICAgICAgZm9yIChjb25zdCBbaWR4TmFtZSwgaWR4Q29sXSBvZiBPYmplY3QuZW50cmllcyhpbmRleGVzKSkge1xuICAgICAgICAgIGNvbnN0IGVtcHR5Um93OiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVJbmRleCh0YWJsZSwgaWR4TmFtZSwgaWR4Q29sLCByb3csIGVtcHR5Um93LCByb3dJZCk7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZShrZXkpO1xuICAgICAgICByb3dzQWZmZWN0ZWQrKztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyByb3dzOiBbXSwgY29sdW1uczogW10sIHJvd3NBZmZlY3RlZCB9O1xuICB9XG59XG4iXX0=