@bitgo-beta/sdk-coin-tempo 1.0.1-beta.31 → 1.0.1-beta.310

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 (51) hide show
  1. package/dist/src/index.d.ts +1 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +2 -1
  4. package/dist/src/lib/constants.d.ts +21 -1
  5. package/dist/src/lib/constants.d.ts.map +1 -1
  6. package/dist/src/lib/constants.js +25 -5
  7. package/dist/src/lib/index.d.ts +4 -0
  8. package/dist/src/lib/index.d.ts.map +1 -1
  9. package/dist/src/lib/index.js +5 -1
  10. package/dist/src/lib/keyPair.d.ts +5 -25
  11. package/dist/src/lib/keyPair.d.ts.map +1 -1
  12. package/dist/src/lib/keyPair.js +9 -97
  13. package/dist/src/lib/tip20Abi.d.ts +98 -0
  14. package/dist/src/lib/tip20Abi.d.ts.map +1 -0
  15. package/dist/src/lib/tip20Abi.js +62 -0
  16. package/dist/src/lib/transaction.d.ts +144 -0
  17. package/dist/src/lib/transaction.d.ts.map +1 -0
  18. package/dist/src/lib/transaction.js +216 -0
  19. package/dist/src/lib/transactionBuilder.d.ts +139 -0
  20. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  21. package/dist/src/lib/transactionBuilder.js +408 -0
  22. package/dist/src/lib/types.d.ts +27 -0
  23. package/dist/src/lib/types.d.ts.map +1 -0
  24. package/dist/src/lib/types.js +3 -0
  25. package/dist/src/lib/utils.d.ts +70 -7
  26. package/dist/src/lib/utils.d.ts.map +1 -1
  27. package/dist/src/lib/utils.js +148 -16
  28. package/dist/src/register.d.ts.map +1 -1
  29. package/dist/src/register.js +5 -1
  30. package/dist/src/tempo.d.ts +95 -41
  31. package/dist/src/tempo.d.ts.map +1 -1
  32. package/dist/src/tempo.js +447 -76
  33. package/dist/src/tip20Token.d.ts +83 -0
  34. package/dist/src/tip20Token.d.ts.map +1 -0
  35. package/dist/src/tip20Token.js +202 -0
  36. package/dist/test/integration/tip20.d.ts +7 -0
  37. package/dist/test/integration/tip20.d.ts.map +1 -0
  38. package/dist/test/integration/tip20.js +178 -0
  39. package/dist/test/resources/tempo.d.ts +61 -0
  40. package/dist/test/resources/tempo.d.ts.map +1 -0
  41. package/dist/test/resources/tempo.js +79 -0
  42. package/dist/test/unit/index.js +172 -3
  43. package/dist/test/unit/tempo.d.ts +2 -0
  44. package/dist/test/unit/tempo.d.ts.map +1 -0
  45. package/dist/test/unit/tempo.js +207 -0
  46. package/dist/test/unit/transactionBuilder.d.ts +2 -0
  47. package/dist/test/unit/transactionBuilder.d.ts.map +1 -0
  48. package/dist/test/unit/transactionBuilder.js +858 -0
  49. package/dist/test/unit/utils.js +6 -5
  50. package/dist/tsconfig.tsbuildinfo +1 -1
  51. package/package.json +12 -7
@@ -0,0 +1,858 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const assert_1 = __importDefault(require("assert"));
7
+ const mocha_1 = require("mocha");
8
+ const ethers_1 = require("ethers");
9
+ const transactionBuilder_1 = require("../../src/lib/transactionBuilder");
10
+ const transaction_1 = require("../../src/lib/transaction");
11
+ const utils_1 = require("../../src/lib/utils");
12
+ const constants_1 = require("../../src/lib/constants");
13
+ const statics_1 = require("@bitgo-beta/statics");
14
+ const ttempo_1 = require("../../src/ttempo");
15
+ const sdk_api_1 = require("@bitgo-beta/sdk-api");
16
+ const sdk_test_1 = require("@bitgo-beta/sdk-test");
17
+ const tempo_1 = require("../resources/tempo");
18
+ const mockCoinConfig = statics_1.coins.get('ttempo');
19
+ (0, mocha_1.describe)('TIP-20 Utilities', () => {
20
+ (0, mocha_1.describe)('amountToTip20Units', () => {
21
+ (0, mocha_1.it)('should convert decimal amount to 6-decimal units', () => {
22
+ assert_1.default.strictEqual((0, utils_1.amountToTip20Units)('1.5'), 1500000n);
23
+ assert_1.default.strictEqual((0, utils_1.amountToTip20Units)('100'), 100000000n);
24
+ assert_1.default.strictEqual((0, utils_1.amountToTip20Units)('0.000001'), 1n);
25
+ });
26
+ (0, mocha_1.it)('should throw error for invalid amount', () => {
27
+ assert_1.default.throws(() => (0, utils_1.amountToTip20Units)('invalid'), /Invalid amount format/);
28
+ });
29
+ });
30
+ (0, mocha_1.describe)('tip20UnitsToAmount', () => {
31
+ (0, mocha_1.it)('should convert 6-decimal units to human-readable amount', () => {
32
+ assert_1.default.strictEqual((0, utils_1.tip20UnitsToAmount)(1500000n), '1.5');
33
+ assert_1.default.strictEqual((0, utils_1.tip20UnitsToAmount)(100000000n), '100.0');
34
+ assert_1.default.strictEqual((0, utils_1.tip20UnitsToAmount)(1n), '0.000001');
35
+ });
36
+ });
37
+ (0, mocha_1.describe)('stringToBytes32', () => {
38
+ (0, mocha_1.it)('should convert string to bytes32', () => {
39
+ const result = (0, utils_1.stringToBytes32)('12345');
40
+ assert_1.default.strictEqual(result.length, 66);
41
+ assert_1.default.ok(result.startsWith('0x'));
42
+ });
43
+ (0, mocha_1.it)('should throw error for string longer than 32 bytes', () => {
44
+ assert_1.default.throws(() => (0, utils_1.stringToBytes32)('a'.repeat(33)), /Memo too long/);
45
+ });
46
+ });
47
+ (0, mocha_1.describe)('encodeTip20TransferWithMemo', () => {
48
+ (0, mocha_1.it)('should encode transferWithMemo call', () => {
49
+ const to = ethers_1.ethers.utils.getAddress('0x742d35cc6634c0532925a3b844bc9e7595f0beb1');
50
+ const encoded = (0, utils_1.encodeTip20TransferWithMemo)(to, 1500000n, '12345');
51
+ assert_1.default.ok(encoded.startsWith('0x'));
52
+ assert_1.default.ok(encoded.length > 10);
53
+ });
54
+ });
55
+ (0, mocha_1.describe)('isValidTip20Amount', () => {
56
+ (0, mocha_1.it)('should validate amounts correctly', () => {
57
+ assert_1.default.strictEqual((0, utils_1.isValidTip20Amount)('1.5'), true);
58
+ assert_1.default.strictEqual((0, utils_1.isValidTip20Amount)('invalid'), false);
59
+ assert_1.default.strictEqual((0, utils_1.isValidTip20Amount)('-5'), false);
60
+ });
61
+ });
62
+ });
63
+ (0, mocha_1.describe)('TIP-20 Transaction Builder', () => {
64
+ const mockToken = ethers_1.ethers.utils.getAddress('0x1234567890123456789012345678901234567890');
65
+ const mockRecipient = ethers_1.ethers.utils.getAddress('0x742d35cc6634c0532925a3b844bc9e7595f0beb1');
66
+ const mockFeeToken = ethers_1.ethers.utils.getAddress('0xabcdefabcdefabcdefabcdefabcdefabcdefabcd');
67
+ (0, mocha_1.describe)('addOperation', () => {
68
+ (0, mocha_1.it)('should add operation with and without memo', () => {
69
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
70
+ builder.addOperation({ token: mockToken, to: mockRecipient, amount: '100' });
71
+ builder.addOperation({ token: mockToken, to: mockRecipient, amount: '50', memo: '1' });
72
+ const operations = builder.getOperations();
73
+ assert_1.default.strictEqual(operations.length, 2);
74
+ assert_1.default.strictEqual(operations[0].memo, undefined);
75
+ assert_1.default.strictEqual(operations[1].memo, '1');
76
+ });
77
+ (0, mocha_1.it)('should throw error for invalid addresses', () => {
78
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
79
+ assert_1.default.throws(() => builder.addOperation({ token: '0xinvalid', to: mockRecipient, amount: '100' }), /Invalid token address/);
80
+ assert_1.default.throws(() => builder.addOperation({ token: mockToken, to: '0xinvalid', amount: '100' }), /Invalid recipient address/);
81
+ });
82
+ (0, mocha_1.it)('should throw error for invalid amount', () => {
83
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
84
+ assert_1.default.throws(() => builder.addOperation({ token: mockToken, to: mockRecipient, amount: 'invalid-amount' }), /Invalid amount/);
85
+ });
86
+ (0, mocha_1.it)('should throw error for invalid (non-numeric) memo', () => {
87
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
88
+ assert_1.default.throws(() => builder.addOperation({ token: mockToken, to: mockRecipient, amount: '100', memo: 'INV-001' }), /Invalid memo/);
89
+ });
90
+ });
91
+ (0, mocha_1.describe)('feeToken', () => {
92
+ (0, mocha_1.it)('should set and get fee token', () => {
93
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
94
+ builder.feeToken(mockFeeToken);
95
+ assert_1.default.strictEqual(builder.getFeeToken(), mockFeeToken);
96
+ });
97
+ (0, mocha_1.it)('should throw error for invalid fee token address', () => {
98
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
99
+ assert_1.default.throws(() => builder.feeToken('invalid-address'), /Invalid fee token address/);
100
+ });
101
+ });
102
+ (0, mocha_1.describe)('Transaction parameters', () => {
103
+ (0, mocha_1.it)('should set nonce, gas, maxFeePerGas, and maxPriorityFeePerGas', () => {
104
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
105
+ builder.nonce(42).gas(500000n).maxFeePerGas(1000000000n).maxPriorityFeePerGas(500000000n);
106
+ assert_1.default.strictEqual(builder._nonce, 42);
107
+ assert_1.default.strictEqual(builder._gas, 500000n);
108
+ assert_1.default.strictEqual(builder._maxFeePerGas, 1000000000n);
109
+ assert_1.default.strictEqual(builder._maxPriorityFeePerGas, 500000000n);
110
+ });
111
+ (0, mocha_1.it)('should throw error for invalid nonce and gas', () => {
112
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
113
+ assert_1.default.throws(() => builder.nonce(-1), /Invalid nonce/);
114
+ assert_1.default.throws(() => builder.gas(0n), /Invalid gas limit/);
115
+ });
116
+ });
117
+ (0, mocha_1.describe)('Method chaining', () => {
118
+ (0, mocha_1.it)('should support fluent interface', () => {
119
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
120
+ const result = builder
121
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100', memo: '5' })
122
+ .feeToken(mockFeeToken)
123
+ .nonce(10)
124
+ .gas(400000n)
125
+ .maxFeePerGas(2000000000n)
126
+ .maxPriorityFeePerGas(1000000000n);
127
+ assert_1.default.strictEqual(result, builder);
128
+ });
129
+ });
130
+ });
131
+ (0, mocha_1.describe)('TIP-20 Constants', () => {
132
+ (0, mocha_1.it)('should have correct decimal places', () => {
133
+ assert_1.default.strictEqual(constants_1.TIP20_DECIMALS, 6);
134
+ });
135
+ });
136
+ (0, mocha_1.describe)('TIP-20 Transaction Build', () => {
137
+ const mockToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.alphaUSD.address);
138
+ const mockRecipient = ethers_1.ethers.utils.getAddress(tempo_1.TEST_RECIPIENT_ADDRESS);
139
+ const mockFeeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.betaUSD.address);
140
+ (0, mocha_1.describe)('Build Transaction', () => {
141
+ (0, mocha_1.it)('should build single-operation transaction', async () => {
142
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
143
+ builder
144
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100', memo: '1' })
145
+ .feeToken(mockFeeToken)
146
+ .nonce(0)
147
+ .gas(100000n)
148
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
149
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
150
+ const tx = (await builder.build());
151
+ assert_1.default.ok(tx instanceof transaction_1.Tip20Transaction);
152
+ assert_1.default.strictEqual(tx.getOperationCount(), 1);
153
+ assert_1.default.strictEqual(tx.getFeeToken(), mockFeeToken);
154
+ });
155
+ (0, mocha_1.it)('should build batch transaction with multiple operations', async () => {
156
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
157
+ builder
158
+ .addOperation({ token: tempo_1.TESTNET_TOKENS.alphaUSD.address, to: mockRecipient, amount: '10', memo: '1' })
159
+ .addOperation({ token: tempo_1.TESTNET_TOKENS.betaUSD.address, to: mockRecipient, amount: '20', memo: '2' })
160
+ .addOperation({ token: tempo_1.TESTNET_TOKENS.thetaUSD.address, to: mockRecipient, amount: '30', memo: '3' })
161
+ .feeToken(mockFeeToken)
162
+ .nonce(42)
163
+ .gas(300000n)
164
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
165
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
166
+ const tx = (await builder.build());
167
+ assert_1.default.ok(tx instanceof transaction_1.Tip20Transaction);
168
+ assert_1.default.strictEqual(tx.getOperationCount(), 3);
169
+ assert_1.default.strictEqual(tx.isBatch(), true);
170
+ });
171
+ (0, mocha_1.it)('should build transaction without fee token', async () => {
172
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
173
+ builder
174
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '50' })
175
+ .nonce(1)
176
+ .gas(100000n)
177
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
178
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
179
+ const tx = (await builder.build());
180
+ assert_1.default.ok(tx instanceof transaction_1.Tip20Transaction);
181
+ assert_1.default.strictEqual(tx.getFeeToken(), undefined);
182
+ });
183
+ });
184
+ (0, mocha_1.describe)('Build Validation Errors', () => {
185
+ (0, mocha_1.it)('should throw error when no operations added', async () => {
186
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
187
+ builder.nonce(0).gas(100000n).maxFeePerGas(1000000000n).maxPriorityFeePerGas(500000000n);
188
+ await assert_1.default.rejects(async () => await builder.build(), /At least one operation or raw call is required/);
189
+ });
190
+ (0, mocha_1.it)('should throw error when nonce not set', async () => {
191
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
192
+ builder
193
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
194
+ .gas(100000n)
195
+ .maxFeePerGas(1000000000n)
196
+ .maxPriorityFeePerGas(500000000n);
197
+ await assert_1.default.rejects(async () => await builder.build(), tempo_1.ERROR_MESSAGES.missingNonce);
198
+ });
199
+ (0, mocha_1.it)('should throw error when gas not set', async () => {
200
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
201
+ builder
202
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
203
+ .nonce(0)
204
+ .maxFeePerGas(1000000000n)
205
+ .maxPriorityFeePerGas(500000000n);
206
+ await assert_1.default.rejects(async () => await builder.build(), tempo_1.ERROR_MESSAGES.missingGas);
207
+ });
208
+ (0, mocha_1.it)('should throw error when maxFeePerGas not set', async () => {
209
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
210
+ builder
211
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
212
+ .nonce(0)
213
+ .gas(100000n)
214
+ .maxPriorityFeePerGas(500000000n);
215
+ await assert_1.default.rejects(async () => await builder.build(), tempo_1.ERROR_MESSAGES.missingMaxFeePerGas);
216
+ });
217
+ (0, mocha_1.it)('should throw error when maxPriorityFeePerGas not set', async () => {
218
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
219
+ builder
220
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
221
+ .nonce(0)
222
+ .gas(100000n)
223
+ .maxFeePerGas(1000000000n);
224
+ await assert_1.default.rejects(async () => await builder.build(), tempo_1.ERROR_MESSAGES.missingMaxPriorityFeePerGas);
225
+ });
226
+ });
227
+ (0, mocha_1.describe)('Round-Trip: Build -> Serialize -> Operations Check', () => {
228
+ (0, mocha_1.it)('should preserve operation data through build', async () => {
229
+ const operations = [{ token: mockToken, to: mockRecipient, amount: '123', memo: '1' }];
230
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
231
+ builder
232
+ .addOperation(operations[0])
233
+ .feeToken(mockFeeToken)
234
+ .nonce(10)
235
+ .gas(150000n)
236
+ .maxFeePerGas(2000000000n)
237
+ .maxPriorityFeePerGas(1000000000n);
238
+ const tx = (await builder.build());
239
+ const txOps = tx.getOperations();
240
+ assert_1.default.strictEqual(txOps.length, 1);
241
+ assert_1.default.strictEqual(txOps[0].token, operations[0].token);
242
+ assert_1.default.strictEqual(txOps[0].to, operations[0].to);
243
+ assert_1.default.strictEqual(txOps[0].amount, operations[0].amount);
244
+ assert_1.default.strictEqual(txOps[0].memo, operations[0].memo);
245
+ });
246
+ });
247
+ (0, mocha_1.describe)('Build -> Serialize -> Sign Flow', () => {
248
+ (0, mocha_1.it)('should produce serializable unsigned transaction', async () => {
249
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
250
+ builder
251
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '50', memo: '2' })
252
+ .feeToken(mockFeeToken)
253
+ .nonce(5)
254
+ .gas(100000n)
255
+ .maxFeePerGas(2000000000n)
256
+ .maxPriorityFeePerGas(1000000000n);
257
+ const tx = (await builder.build());
258
+ const unsignedHex = await tx.serialize();
259
+ assert_1.default.ok(unsignedHex.startsWith(constants_1.AA_TRANSACTION_TYPE));
260
+ assert_1.default.ok(/^0x[0-9a-f]+$/i.test(unsignedHex));
261
+ });
262
+ (0, mocha_1.it)('should support full sign and broadcast flow', async () => {
263
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
264
+ builder
265
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '75', memo: '3' })
266
+ .feeToken(mockFeeToken)
267
+ .nonce(123)
268
+ .gas(120000n)
269
+ .maxFeePerGas(2500000000n)
270
+ .maxPriorityFeePerGas(1200000000n);
271
+ const tx = (await builder.build());
272
+ const unsignedHex = await tx.serialize();
273
+ tx.setSignature(tempo_1.SIGNATURE_TEST_DATA.validSignature);
274
+ const broadcastHex = await tx.toBroadcastFormat();
275
+ assert_1.default.ok(broadcastHex.startsWith(constants_1.AA_TRANSACTION_TYPE));
276
+ assert_1.default.ok(broadcastHex.length > unsignedHex.length, 'Signed should be longer');
277
+ });
278
+ });
279
+ (0, mocha_1.describe)('Transaction JSON Representation', () => {
280
+ (0, mocha_1.it)('should produce consistent JSON from built transaction', async () => {
281
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
282
+ builder
283
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100', memo: '4' })
284
+ .feeToken(mockFeeToken)
285
+ .nonce(50)
286
+ .gas(200000n)
287
+ .maxFeePerGas(3000000000n)
288
+ .maxPriorityFeePerGas(1500000000n);
289
+ const tx = (await builder.build());
290
+ const json = tx.toJson();
291
+ assert_1.default.strictEqual(json.type, constants_1.AA_TRANSACTION_TYPE);
292
+ assert_1.default.strictEqual(json.nonce, 50);
293
+ assert_1.default.strictEqual(json.gas, '200000');
294
+ assert_1.default.strictEqual(json.maxFeePerGas, '3000000000');
295
+ assert_1.default.strictEqual(json.maxPriorityFeePerGas, '1500000000');
296
+ assert_1.default.strictEqual(json.callCount, 1);
297
+ assert_1.default.strictEqual(json.feeToken, mockFeeToken);
298
+ });
299
+ });
300
+ (0, mocha_1.describe)('Transaction id getter', () => {
301
+ (0, mocha_1.it)('unsigned and signed transactions should have different ids', async () => {
302
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
303
+ builder
304
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '10' })
305
+ .nonce(1)
306
+ .gas(100000n)
307
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
308
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
309
+ const tx = (await builder.build());
310
+ const unsignedId = tx.id;
311
+ tx.setSignature(tempo_1.SIGNATURE_TEST_DATA.validSignature);
312
+ const signedId = tx.id;
313
+ assert_1.default.notStrictEqual(unsignedId, signedId, 'Signed and unsigned tx should have different ids');
314
+ });
315
+ });
316
+ (0, mocha_1.describe)('outputs / inputs population', () => {
317
+ (0, mocha_1.it)('should expose outputs with base-unit value and token address as coin', async () => {
318
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
319
+ builder
320
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '1.5', memo: '7' })
321
+ .nonce(0)
322
+ .gas(100000n)
323
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
324
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
325
+ const tx = (await builder.build());
326
+ assert_1.default.strictEqual(tx.outputs.length, 1);
327
+ assert_1.default.strictEqual(tx.outputs[0].address, mockRecipient);
328
+ // 1.5 tokens * 10^6 = 1_500_000 base units
329
+ assert_1.default.strictEqual(tx.outputs[0].value, '1500000');
330
+ // coin is the token contract address, not the chain name
331
+ assert_1.default.strictEqual(tx.outputs[0].coin?.toLowerCase(), mockToken.toLowerCase());
332
+ });
333
+ (0, mocha_1.it)('should expose a single input with the total in base units', async () => {
334
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
335
+ builder
336
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '1.5' })
337
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '3.5' })
338
+ .nonce(0)
339
+ .gas(100000n)
340
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
341
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
342
+ const tx = (await builder.build());
343
+ assert_1.default.strictEqual(tx.inputs.length, 1);
344
+ assert_1.default.strictEqual(tx.inputs[0].address, '');
345
+ // (1.5 + 3.5) tokens * 10^6 = 5_000_000 base units
346
+ assert_1.default.strictEqual(tx.inputs[0].value, '5000000');
347
+ });
348
+ });
349
+ (0, mocha_1.describe)('Round-Trip: Build -> Serialize -> From (deserialization)', () => {
350
+ (0, mocha_1.it)('should round-trip a single-operation transaction without a signature', async () => {
351
+ const operation = { token: mockToken, to: mockRecipient, amount: '25.5', memo: '12345' };
352
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
353
+ builder
354
+ .addOperation(operation)
355
+ .feeToken(mockFeeToken)
356
+ .nonce(7)
357
+ .gas(150000n)
358
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
359
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
360
+ const originalTx = (await builder.build());
361
+ const serialized = await originalTx.serialize();
362
+ // Deserialize via from()
363
+ const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
364
+ builder2.from(serialized);
365
+ const restoredTx = (await builder2.build());
366
+ const ops = restoredTx.getOperations();
367
+ assert_1.default.strictEqual(ops.length, 1);
368
+ assert_1.default.strictEqual(ops[0].token.toLowerCase(), operation.token.toLowerCase());
369
+ assert_1.default.strictEqual(ops[0].to.toLowerCase(), operation.to.toLowerCase());
370
+ assert_1.default.strictEqual(ops[0].amount, operation.amount);
371
+ assert_1.default.strictEqual(ops[0].memo, operation.memo);
372
+ assert_1.default.strictEqual(restoredTx.getFeeToken()?.toLowerCase(), mockFeeToken.toLowerCase());
373
+ });
374
+ (0, mocha_1.it)('should round-trip a batch transaction', async () => {
375
+ // Use amounts that match tip20UnitsToAmount output: ethers formatUnits always includes decimal
376
+ const operations = [
377
+ { token: tempo_1.TESTNET_TOKENS.alphaUSD.address, to: mockRecipient, amount: '10.0', memo: '1' },
378
+ { token: tempo_1.TESTNET_TOKENS.betaUSD.address, to: mockRecipient, amount: '20.0', memo: '2' },
379
+ ];
380
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
381
+ builder
382
+ .addOperation(operations[0])
383
+ .addOperation(operations[1])
384
+ .nonce(42)
385
+ .gas(250000n)
386
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
387
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
388
+ const originalTx = (await builder.build());
389
+ const serialized = await originalTx.serialize();
390
+ const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
391
+ builder2.from(serialized);
392
+ const restoredTx = (await builder2.build());
393
+ assert_1.default.strictEqual(restoredTx.getOperationCount(), 2);
394
+ assert_1.default.ok(restoredTx.isBatch());
395
+ const json = restoredTx.toJson();
396
+ assert_1.default.strictEqual(json.nonce, 42);
397
+ assert_1.default.strictEqual(json.gas, '250000');
398
+ assert_1.default.strictEqual(json.maxFeePerGas, tempo_1.TX_PARAMS.defaultMaxFeePerGas.toString());
399
+ assert_1.default.strictEqual(json.maxPriorityFeePerGas, tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas.toString());
400
+ const ops = restoredTx.getOperations();
401
+ for (let i = 0; i < operations.length; i++) {
402
+ assert_1.default.strictEqual(ops[i].token.toLowerCase(), operations[i].token.toLowerCase());
403
+ assert_1.default.strictEqual(ops[i].to.toLowerCase(), mockRecipient.toLowerCase());
404
+ assert_1.default.strictEqual(ops[i].amount, operations[i].amount);
405
+ assert_1.default.strictEqual(ops[i].memo, operations[i].memo);
406
+ }
407
+ });
408
+ (0, mocha_1.it)('should round-trip a signed transaction and preserve the signature', async () => {
409
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
410
+ builder
411
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '5' })
412
+ .nonce(99)
413
+ .gas(100000n)
414
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
415
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
416
+ const tx = (await builder.build());
417
+ tx.setSignature(tempo_1.SIGNATURE_TEST_DATA.validSignature);
418
+ const signedHex = await tx.toBroadcastFormat();
419
+ // Deserialize the signed transaction
420
+ const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
421
+ builder2.from(signedHex);
422
+ const restoredTx = (await builder2.build());
423
+ const sig = restoredTx.getSignature();
424
+ assert_1.default.ok(sig !== undefined, 'Signature should be preserved');
425
+ assert_1.default.strictEqual(sig.yParity, tempo_1.SIGNATURE_TEST_DATA.validSignature.yParity);
426
+ });
427
+ (0, mocha_1.it)('should produce the same tx id after a serialization round-trip', async () => {
428
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
429
+ builder
430
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100.0', memo: '99' })
431
+ .nonce(3)
432
+ .gas(100000n)
433
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
434
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
435
+ const originalTx = (await builder.build());
436
+ const serialized = await originalTx.serialize();
437
+ const originalId = originalTx.id;
438
+ const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
439
+ builder2.from(serialized);
440
+ const restoredTx = (await builder2.build());
441
+ assert_1.default.strictEqual(restoredTx.id, originalId);
442
+ const originalJson = originalTx.toJson();
443
+ const restoredJson = restoredTx.toJson();
444
+ assert_1.default.strictEqual(restoredJson.nonce, originalJson.nonce);
445
+ assert_1.default.strictEqual(restoredJson.gas, originalJson.gas);
446
+ assert_1.default.strictEqual(restoredJson.maxFeePerGas, originalJson.maxFeePerGas);
447
+ assert_1.default.strictEqual(restoredJson.maxPriorityFeePerGas, originalJson.maxPriorityFeePerGas);
448
+ assert_1.default.strictEqual(restoredJson.feeToken, originalJson.feeToken);
449
+ assert_1.default.strictEqual(restoredJson.callCount, originalJson.callCount);
450
+ const originalOps = originalTx.getOperations();
451
+ const restoredOps = restoredTx.getOperations();
452
+ assert_1.default.strictEqual(restoredOps.length, originalOps.length);
453
+ assert_1.default.strictEqual(restoredOps[0].token.toLowerCase(), originalOps[0].token.toLowerCase());
454
+ assert_1.default.strictEqual(restoredOps[0].to.toLowerCase(), originalOps[0].to.toLowerCase());
455
+ assert_1.default.strictEqual(restoredOps[0].amount, originalOps[0].amount);
456
+ assert_1.default.strictEqual(restoredOps[0].memo, originalOps[0].memo);
457
+ const restoredSerialized = await restoredTx.serialize();
458
+ assert_1.default.strictEqual(restoredSerialized, serialized);
459
+ });
460
+ });
461
+ });
462
+ (0, mocha_1.describe)('Tempo coin - parseTransaction / verifyTransaction', () => {
463
+ let bitgo;
464
+ let coin;
465
+ const mockToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.alphaUSD.address);
466
+ const mockRecipient = ethers_1.ethers.utils.getAddress(tempo_1.TEST_RECIPIENT_ADDRESS);
467
+ (0, mocha_1.before)(function () {
468
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
469
+ bitgo.safeRegister('ttempo', (bg) => {
470
+ const mockStaticsCoin = {
471
+ name: 'ttempo',
472
+ fullName: 'Testnet Tempo',
473
+ network: { type: 'testnet' },
474
+ features: [],
475
+ };
476
+ return ttempo_1.Ttempo.createInstance(bg, mockStaticsCoin);
477
+ });
478
+ bitgo.initializeTestVars();
479
+ coin = bitgo.coin('ttempo');
480
+ });
481
+ async function buildSerializedTx(operations, nonce = 0) {
482
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
483
+ for (const op of operations) {
484
+ builder.addOperation(op);
485
+ }
486
+ builder
487
+ .nonce(nonce)
488
+ .gas(100000n)
489
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
490
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
491
+ const tx = (await builder.build());
492
+ return tx.serialize();
493
+ }
494
+ (0, mocha_1.describe)('parseTransaction', () => {
495
+ (0, mocha_1.it)('should parse a single-operation transaction into outputs', async () => {
496
+ const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '50', memo: '1' }]);
497
+ const parsed = await coin.parseTransaction({ txHex });
498
+ assert_1.default.ok(Array.isArray(parsed.outputs), 'outputs should be an array');
499
+ assert_1.default.strictEqual(parsed.outputs.length, 1);
500
+ assert_1.default.strictEqual(parsed.outputs[0].address.toLowerCase(), mockRecipient.toLowerCase());
501
+ // 50 tokens * 10^6 = 50_000_000 base units
502
+ assert_1.default.strictEqual(parsed.outputs[0].amount, '50000000');
503
+ });
504
+ (0, mocha_1.it)('should return empty object when no txHex is provided', async () => {
505
+ const parsed = await coin.parseTransaction({});
506
+ assert_1.default.deepStrictEqual(parsed, {});
507
+ });
508
+ });
509
+ (0, mocha_1.describe)('verifyTransaction', () => {
510
+ (0, mocha_1.it)('should return true when no recipients are specified', async () => {
511
+ const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '10' }]);
512
+ const result = await coin.verifyTransaction({
513
+ txPrebuild: { txHex },
514
+ txParams: {},
515
+ });
516
+ assert_1.default.strictEqual(result, true);
517
+ });
518
+ (0, mocha_1.it)('should return true when recipients match operations', async () => {
519
+ const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '100' }]);
520
+ const result = await coin.verifyTransaction({
521
+ txPrebuild: { txHex },
522
+ txParams: {
523
+ recipients: [{ address: mockRecipient, amount: '100000000' }], // 100 * 10^6 base units
524
+ },
525
+ });
526
+ assert_1.default.strictEqual(result, true);
527
+ });
528
+ (0, mocha_1.it)('should throw when recipient address does not match', async () => {
529
+ const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '100' }]);
530
+ const wrongAddress = ethers_1.ethers.utils.getAddress('0x1111111111111111111111111111111111111111');
531
+ await assert_1.default.rejects(() => coin.verifyTransaction({
532
+ txPrebuild: { txHex },
533
+ txParams: { recipients: [{ address: wrongAddress, amount: '100000000' }] },
534
+ }), /recipient mismatch/);
535
+ });
536
+ (0, mocha_1.it)('should throw when recipient amount does not match', async () => {
537
+ const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '100' }]);
538
+ await assert_1.default.rejects(() => coin.verifyTransaction({
539
+ txPrebuild: { txHex },
540
+ txParams: { recipients: [{ address: mockRecipient, amount: '999' }] },
541
+ }), /amount mismatch/);
542
+ });
543
+ (0, mocha_1.it)('should throw when operation count differs from recipient count', async () => {
544
+ const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '10' }]);
545
+ await assert_1.default.rejects(() => coin.verifyTransaction({
546
+ txPrebuild: { txHex },
547
+ txParams: {
548
+ recipients: [
549
+ { address: mockRecipient, amount: '10000000' },
550
+ { address: mockRecipient, amount: '10000000' },
551
+ ],
552
+ },
553
+ }), /operation\(s\)/);
554
+ });
555
+ (0, mocha_1.it)('should return true when no txHex is provided', async () => {
556
+ const result = await coin.verifyTransaction({ txPrebuild: {}, txParams: {} });
557
+ assert_1.default.strictEqual(result, true);
558
+ });
559
+ });
560
+ (0, mocha_1.describe)('verifyTransaction with feeToken', () => {
561
+ (0, mocha_1.it)('should verify transaction with matching fee token', async () => {
562
+ const feeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.betaUSD.address);
563
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
564
+ builder
565
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
566
+ .feeToken(feeToken)
567
+ .nonce(0)
568
+ .gas(100000n)
569
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
570
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
571
+ const tx = (await builder.build());
572
+ const txHex = await tx.serialize();
573
+ const result = await coin.verifyTransaction({
574
+ txPrebuild: { txHex },
575
+ txParams: { feeToken: feeToken },
576
+ });
577
+ assert_1.default.strictEqual(result, true);
578
+ });
579
+ (0, mocha_1.it)('should throw when fee token does not match', async () => {
580
+ const feeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.betaUSD.address);
581
+ const wrongFeeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.alphaUSD.address);
582
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
583
+ builder
584
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
585
+ .feeToken(feeToken)
586
+ .nonce(0)
587
+ .gas(100000n)
588
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
589
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
590
+ const tx = (await builder.build());
591
+ const txHex = await tx.serialize();
592
+ await assert_1.default.rejects(() => coin.verifyTransaction({
593
+ txPrebuild: { txHex },
594
+ txParams: { feeToken: wrongFeeToken },
595
+ }), /Fee token mismatch/);
596
+ });
597
+ (0, mocha_1.it)('should throw when fee token is expected but transaction has none', async () => {
598
+ const expectedFeeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.betaUSD.address);
599
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
600
+ builder
601
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
602
+ .nonce(0)
603
+ .gas(100000n)
604
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
605
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
606
+ const tx = (await builder.build());
607
+ const txHex = await tx.serialize();
608
+ await assert_1.default.rejects(() => coin.verifyTransaction({
609
+ txPrebuild: { txHex },
610
+ txParams: { feeToken: expectedFeeToken },
611
+ }), /Fee token mismatch/);
612
+ });
613
+ (0, mocha_1.it)('should pass verification when no fee token is specified in params', async () => {
614
+ const feeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.betaUSD.address);
615
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
616
+ builder
617
+ .addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
618
+ .feeToken(feeToken)
619
+ .nonce(0)
620
+ .gas(100000n)
621
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
622
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
623
+ const tx = (await builder.build());
624
+ const txHex = await tx.serialize();
625
+ // No feeToken in txParams - should not verify, just pass
626
+ const result = await coin.verifyTransaction({
627
+ txPrebuild: { txHex },
628
+ txParams: {},
629
+ });
630
+ assert_1.default.strictEqual(result, true);
631
+ });
632
+ });
633
+ });
634
+ (0, mocha_1.describe)('Raw Contract Call Builder', () => {
635
+ const mockContract = ethers_1.ethers.utils.getAddress('0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef');
636
+ const mockCalldata = '0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b844bc454e4438f44e0000000000000000000000000000000000000000000000000000000000989680';
637
+ (0, mocha_1.describe)('addRawCall', () => {
638
+ (0, mocha_1.it)('should add a raw call and return it via getRawCalls()', () => {
639
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
640
+ builder.addRawCall({ to: mockContract, data: mockCalldata });
641
+ const rawCalls = builder.getRawCalls();
642
+ assert_1.default.strictEqual(rawCalls.length, 1);
643
+ assert_1.default.strictEqual(rawCalls[0].to, mockContract);
644
+ assert_1.default.strictEqual(rawCalls[0].data, mockCalldata);
645
+ });
646
+ (0, mocha_1.it)('should support chaining addRawCall', () => {
647
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
648
+ const result = builder.addRawCall({ to: mockContract, data: mockCalldata });
649
+ assert_1.default.strictEqual(result, builder);
650
+ });
651
+ (0, mocha_1.it)('should throw for invalid contract address', () => {
652
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
653
+ assert_1.default.throws(() => builder.addRawCall({ to: '0xinvalid', data: mockCalldata }), /Invalid contract address/);
654
+ });
655
+ (0, mocha_1.it)('should throw for empty calldata', () => {
656
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
657
+ assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: '0x' }), /Invalid calldata/);
658
+ });
659
+ (0, mocha_1.it)('should throw for non-hex calldata', () => {
660
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
661
+ assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: 'not-hex-data' }), /Invalid calldata/);
662
+ });
663
+ (0, mocha_1.it)('should throw for calldata missing 0x prefix', () => {
664
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
665
+ assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: 'a9059cbb' }), /Invalid calldata/);
666
+ });
667
+ (0, mocha_1.it)('should throw for odd-length hex calldata', () => {
668
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
669
+ assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: '0xabc' }), /Invalid calldata/);
670
+ });
671
+ (0, mocha_1.it)('should throw for invalid value string', () => {
672
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
673
+ assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: mockCalldata, value: '1e18' }), /Invalid value/);
674
+ });
675
+ (0, mocha_1.it)('should throw for negative value', () => {
676
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
677
+ assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: mockCalldata, value: '-1' }), /Invalid value/);
678
+ });
679
+ (0, mocha_1.it)('should allow raw-call-only transaction (no operations)', async () => {
680
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
681
+ builder
682
+ .addRawCall({ to: mockContract, data: mockCalldata })
683
+ .nonce(0)
684
+ .gas(100000n)
685
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
686
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
687
+ const tx = (await builder.build());
688
+ assert_1.default.ok(tx instanceof transaction_1.Tip20Transaction);
689
+ assert_1.default.strictEqual(tx.getOperations().length, 0);
690
+ assert_1.default.strictEqual(tx.getRawCalls().length, 1);
691
+ assert_1.default.strictEqual(tx.getOperationCount(), 1);
692
+ });
693
+ });
694
+ (0, mocha_1.describe)('Round-Trip: Build -> Serialize -> From (raw call deserialization)', () => {
695
+ (0, mocha_1.it)('should preserve raw call calldata through a round-trip', async () => {
696
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
697
+ builder
698
+ .addRawCall({ to: mockContract, data: mockCalldata })
699
+ .nonce(5)
700
+ .gas(150000n)
701
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
702
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
703
+ const originalTx = (await builder.build());
704
+ const serialized = await originalTx.serialize();
705
+ const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
706
+ builder2.from(serialized);
707
+ const restoredTx = (await builder2.build());
708
+ assert_1.default.strictEqual(restoredTx.getOperations().length, 0);
709
+ const rawCalls = restoredTx.getRawCalls();
710
+ assert_1.default.strictEqual(rawCalls.length, 1);
711
+ assert_1.default.strictEqual(rawCalls[0].to.toLowerCase(), mockContract.toLowerCase());
712
+ assert_1.default.strictEqual(rawCalls[0].data.toLowerCase(), mockCalldata.toLowerCase());
713
+ });
714
+ (0, mocha_1.it)('should preserve calldata through a signed round-trip', async () => {
715
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
716
+ builder
717
+ .addRawCall({ to: mockContract, data: mockCalldata })
718
+ .nonce(7)
719
+ .gas(120000n)
720
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
721
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
722
+ const tx = (await builder.build());
723
+ tx.setSignature(tempo_1.SIGNATURE_TEST_DATA.validSignature);
724
+ const signedHex = await tx.toBroadcastFormat();
725
+ const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
726
+ builder2.from(signedHex);
727
+ const restoredTx = (await builder2.build());
728
+ const rawCalls = restoredTx.getRawCalls();
729
+ assert_1.default.strictEqual(rawCalls.length, 1);
730
+ assert_1.default.strictEqual(rawCalls[0].data.toLowerCase(), mockCalldata.toLowerCase());
731
+ const sig = restoredTx.getSignature();
732
+ assert_1.default.ok(sig !== undefined);
733
+ assert_1.default.strictEqual(sig.yParity, tempo_1.SIGNATURE_TEST_DATA.validSignature.yParity);
734
+ });
735
+ (0, mocha_1.it)('should preserve raw call tx id through a round-trip', async () => {
736
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
737
+ builder
738
+ .addRawCall({ to: mockContract, data: mockCalldata })
739
+ .nonce(3)
740
+ .gas(100000n)
741
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
742
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
743
+ const originalTx = (await builder.build());
744
+ const serialized = await originalTx.serialize();
745
+ const originalId = originalTx.id;
746
+ const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
747
+ builder2.from(serialized);
748
+ const restoredTx = (await builder2.build());
749
+ assert_1.default.strictEqual(restoredTx.id, originalId);
750
+ });
751
+ });
752
+ (0, mocha_1.describe)('Raw call toJson and outputs', () => {
753
+ (0, mocha_1.it)('should expose raw call contract address as output', async () => {
754
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
755
+ builder
756
+ .addRawCall({ to: mockContract, data: mockCalldata, value: '0' })
757
+ .nonce(2)
758
+ .gas(200000n)
759
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
760
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
761
+ const tx = (await builder.build());
762
+ assert_1.default.strictEqual(tx.outputs.length, 1);
763
+ assert_1.default.strictEqual(tx.outputs[0].address.toLowerCase(), mockContract.toLowerCase());
764
+ });
765
+ (0, mocha_1.it)('should include rawCalls in toJson() output', async () => {
766
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
767
+ builder
768
+ .addRawCall({ to: mockContract, data: mockCalldata })
769
+ .nonce(0)
770
+ .gas(100000n)
771
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
772
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
773
+ const tx = (await builder.build());
774
+ const json = tx.toJson();
775
+ assert_1.default.ok(Array.isArray(json.rawCalls));
776
+ assert_1.default.strictEqual(json.rawCalls.length, 1);
777
+ assert_1.default.strictEqual(json.rawCalls[0].to, mockContract);
778
+ assert_1.default.strictEqual(json.rawCalls[0].data, mockCalldata);
779
+ });
780
+ });
781
+ });
782
+ (0, mocha_1.describe)('Tempo coin - verifyTransaction with raw calls', () => {
783
+ let bitgo;
784
+ let coin;
785
+ const mockContract = ethers_1.ethers.utils.getAddress('0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef');
786
+ const mockCalldata = '0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b844bc454e4438f44e0000000000000000000000000000000000000000000000000000000000989680';
787
+ (0, mocha_1.before)(function () {
788
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
789
+ bitgo.safeRegister('ttempo', (bg) => {
790
+ const mockStaticsCoin = {
791
+ name: 'ttempo',
792
+ fullName: 'Testnet Tempo',
793
+ network: { type: 'testnet' },
794
+ features: [],
795
+ };
796
+ return ttempo_1.Ttempo.createInstance(bg, mockStaticsCoin);
797
+ });
798
+ bitgo.initializeTestVars();
799
+ coin = bitgo.coin('ttempo');
800
+ });
801
+ async function buildRawCallTx(contract, calldata, nonce = 0) {
802
+ const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
803
+ builder
804
+ .addRawCall({ to: contract, data: calldata })
805
+ .nonce(nonce)
806
+ .gas(150000n)
807
+ .maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
808
+ .maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
809
+ const tx = (await builder.build());
810
+ return tx.serialize();
811
+ }
812
+ (0, mocha_1.it)('should verify a raw call transaction when recipient data matches', async () => {
813
+ const txHex = await buildRawCallTx(mockContract, mockCalldata);
814
+ const result = await coin.verifyTransaction({
815
+ txPrebuild: { txHex },
816
+ txParams: {
817
+ recipients: [{ address: mockContract, amount: '0', data: mockCalldata }],
818
+ },
819
+ });
820
+ assert_1.default.strictEqual(result, true);
821
+ });
822
+ (0, mocha_1.it)('should throw when raw call address does not match recipient', async () => {
823
+ const txHex = await buildRawCallTx(mockContract, mockCalldata);
824
+ const wrongAddress = ethers_1.ethers.utils.getAddress('0x1111111111111111111111111111111111111111');
825
+ await assert_1.default.rejects(() => coin.verifyTransaction({
826
+ txPrebuild: { txHex },
827
+ txParams: { recipients: [{ address: wrongAddress, amount: '0', data: mockCalldata }] },
828
+ }), /address mismatch/);
829
+ });
830
+ (0, mocha_1.it)('should throw when raw call calldata does not match', async () => {
831
+ const txHex = await buildRawCallTx(mockContract, mockCalldata);
832
+ const wrongCalldata = '0xdeadbeef01020304';
833
+ await assert_1.default.rejects(() => coin.verifyTransaction({
834
+ txPrebuild: { txHex },
835
+ txParams: { recipients: [{ address: mockContract, amount: '0', data: wrongCalldata }] },
836
+ }), /calldata mismatch/);
837
+ });
838
+ (0, mocha_1.it)('should throw when recipient count does not match call count', async () => {
839
+ const txHex = await buildRawCallTx(mockContract, mockCalldata);
840
+ await assert_1.default.rejects(() => coin.verifyTransaction({
841
+ txPrebuild: { txHex },
842
+ txParams: {
843
+ recipients: [
844
+ { address: mockContract, amount: '0', data: mockCalldata },
845
+ { address: mockContract, amount: '0', data: mockCalldata },
846
+ ],
847
+ },
848
+ }), /call\(s\)/);
849
+ });
850
+ (0, mocha_1.it)('should parse a raw call transaction and expose the contract as an output', async () => {
851
+ const txHex = await buildRawCallTx(mockContract, mockCalldata);
852
+ const parsed = await coin.parseTransaction({ txHex });
853
+ assert_1.default.ok(Array.isArray(parsed.outputs));
854
+ assert_1.default.strictEqual(parsed.outputs.length, 1);
855
+ assert_1.default.strictEqual(parsed.outputs[0].address.toLowerCase(), mockContract.toLowerCase());
856
+ });
857
+ });
858
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25CdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L3RyYW5zYWN0aW9uQnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG9EQUE0QjtBQUM1QixpQ0FBNkM7QUFDN0MsbUNBQWdDO0FBQ2hDLHlFQUEyRTtBQUMzRSwyREFBNkQ7QUFDN0QsK0NBTTZCO0FBQzdCLHVEQUE4RTtBQUM5RSxpREFBNEM7QUFDNUMsNkNBQTBDO0FBQzFDLGlEQUErQztBQUMvQyxtREFBK0Q7QUFFL0QsOENBTTRCO0FBRTVCLE1BQU0sY0FBYyxHQUFHLGVBQUssQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7QUFFM0MsSUFBQSxnQkFBUSxFQUFDLGtCQUFrQixFQUFFLEdBQUcsRUFBRTtJQUNoQyxJQUFBLGdCQUFRLEVBQUMsb0JBQW9CLEVBQUUsR0FBRyxFQUFFO1FBQ2xDLElBQUEsVUFBRSxFQUFDLGtEQUFrRCxFQUFFLEdBQUcsRUFBRTtZQUMxRCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFBLDBCQUFrQixFQUFDLEtBQUssQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3hELGdCQUFNLENBQUMsV0FBVyxDQUFDLElBQUEsMEJBQWtCLEVBQUMsS0FBSyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDMUQsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsSUFBQSwwQkFBa0IsRUFBQyxVQUFVLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN6RCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLHVDQUF1QyxFQUFFLEdBQUcsRUFBRTtZQUMvQyxnQkFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFBLDBCQUFrQixFQUFDLFNBQVMsQ0FBQyxFQUFFLHVCQUF1QixDQUFDLENBQUM7UUFDOUUsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsZ0JBQVEsRUFBQyxvQkFBb0IsRUFBRSxHQUFHLEVBQUU7UUFDbEMsSUFBQSxVQUFFLEVBQUMseURBQXlELEVBQUUsR0FBRyxFQUFFO1lBQ2pFLGdCQUFNLENBQUMsV0FBVyxDQUFDLElBQUEsMEJBQWtCLEVBQUMsUUFBUSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDeEQsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsSUFBQSwwQkFBa0IsRUFBQyxVQUFVLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUM1RCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFBLDBCQUFrQixFQUFDLEVBQUUsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ3pELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLGdCQUFRLEVBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFO1FBQy9CLElBQUEsVUFBRSxFQUFDLGtDQUFrQyxFQUFFLEdBQUcsRUFBRTtZQUMxQyxNQUFNLE1BQU0sR0FBRyxJQUFBLHVCQUFlLEVBQUMsT0FBTyxDQUFDLENBQUM7WUFDeEMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztZQUN0QyxnQkFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDckMsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFBLFVBQUUsRUFBQyxvREFBb0QsRUFBRSxHQUFHLEVBQUU7WUFDNUQsZ0JBQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBQSx1QkFBZSxFQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxlQUFlLENBQUMsQ0FBQztRQUN4RSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBQSxnQkFBUSxFQUFDLDZCQUE2QixFQUFFLEdBQUcsRUFBRTtRQUMzQyxJQUFBLFVBQUUsRUFBQyxxQ0FBcUMsRUFBRSxHQUFHLEVBQUU7WUFDN0MsTUFBTSxFQUFFLEdBQUcsZUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsNENBQTRDLENBQUMsQ0FBQztZQUNqRixNQUFNLE9BQU8sR0FBRyxJQUFBLG1DQUEyQixFQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDbkUsZ0JBQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3BDLGdCQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDakMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsZ0JBQVEsRUFBQyxvQkFBb0IsRUFBRSxHQUFHLEVBQUU7UUFDbEMsSUFBQSxVQUFFLEVBQUMsbUNBQW1DLEVBQUUsR0FBRyxFQUFFO1lBQzNDLGdCQUFNLENBQUMsV0FBVyxDQUFDLElBQUEsMEJBQWtCLEVBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDcEQsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsSUFBQSwwQkFBa0IsRUFBQyxTQUFTLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN6RCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFBLDBCQUFrQixFQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3RELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUEsZ0JBQVEsRUFBQyw0QkFBNEIsRUFBRSxHQUFHLEVBQUU7SUFDMUMsTUFBTSxTQUFTLEdBQUcsZUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsNENBQTRDLENBQUMsQ0FBQztJQUN4RixNQUFNLGFBQWEsR0FBRyxlQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO0lBQzVGLE1BQU0sWUFBWSxHQUFHLGVBQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLDRDQUE0QyxDQUFDLENBQUM7SUFFM0YsSUFBQSxnQkFBUSxFQUFDLGNBQWMsRUFBRSxHQUFHLEVBQUU7UUFDNUIsSUFBQSxVQUFFLEVBQUMsNENBQTRDLEVBQUUsR0FBRyxFQUFFO1lBQ3BELE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTyxDQUFDLFlBQVksQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUM3RSxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFFdkYsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzNDLGdCQUFNLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDekMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztZQUNsRCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQzlDLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMsMENBQTBDLEVBQUUsR0FBRyxFQUFFO1lBQ2xELE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsZ0JBQU0sQ0FBQyxNQUFNLENBQ1gsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxFQUFFLEtBQUssRUFBRSxXQUFrQixFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQzNGLHVCQUF1QixDQUN4QixDQUFDO1lBQ0YsZ0JBQU0sQ0FBQyxNQUFNLENBQ1gsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLFdBQWtCLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQ3ZGLDJCQUEyQixDQUM1QixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFBLFVBQUUsRUFBQyx1Q0FBdUMsRUFBRSxHQUFHLEVBQUU7WUFDL0MsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxnQkFBTSxDQUFDLE1BQU0sQ0FDWCxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLEVBQzdGLGdCQUFnQixDQUNqQixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFBLFVBQUUsRUFBQyxtREFBbUQsRUFBRSxHQUFHLEVBQUU7WUFDM0QsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxnQkFBTSxDQUFDLE1BQU0sQ0FDWCxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQ25HLGNBQWMsQ0FDZixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsZ0JBQVEsRUFBQyxVQUFVLEVBQUUsR0FBRyxFQUFFO1FBQ3hCLElBQUEsVUFBRSxFQUFDLDhCQUE4QixFQUFFLEdBQUcsRUFBRTtZQUN0QyxNQUFNLE9BQU8sR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzVELE9BQU8sQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDL0IsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzFELENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMsa0RBQWtELEVBQUUsR0FBRyxFQUFFO1lBQzFELE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsZ0JBQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLDJCQUEyQixDQUFDLENBQUM7UUFDeEYsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsZ0JBQVEsRUFBQyx3QkFBd0IsRUFBRSxHQUFHLEVBQUU7UUFDdEMsSUFBQSxVQUFFLEVBQUMsK0RBQStELEVBQUUsR0FBRyxFQUFFO1lBQ3ZFLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBRTFGLGdCQUFNLENBQUMsV0FBVyxDQUFFLE9BQWUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDaEQsZ0JBQU0sQ0FBQyxXQUFXLENBQUUsT0FBZSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNuRCxnQkFBTSxDQUFDLFdBQVcsQ0FBRSxPQUFlLENBQUMsYUFBYSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ2hFLGdCQUFNLENBQUMsV0FBVyxDQUFFLE9BQWUsQ0FBQyxxQkFBcUIsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUN6RSxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLDhDQUE4QyxFQUFFLEdBQUcsRUFBRTtZQUN0RCxNQUFNLE9BQU8sR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzVELGdCQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxlQUFlLENBQUMsQ0FBQztZQUN4RCxnQkFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLG1CQUFtQixDQUFDLENBQUM7UUFDNUQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsZ0JBQVEsRUFBQyxpQkFBaUIsRUFBRSxHQUFHLEVBQUU7UUFDL0IsSUFBQSxVQUFFLEVBQUMsaUNBQWlDLEVBQUUsR0FBRyxFQUFFO1lBQ3pDLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsTUFBTSxNQUFNLEdBQUcsT0FBTztpQkFDbkIsWUFBWSxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDO2lCQUMvRSxRQUFRLENBQUMsWUFBWSxDQUFDO2lCQUN0QixLQUFLLENBQUMsRUFBRSxDQUFDO2lCQUNULEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLFdBQVcsQ0FBQztpQkFDekIsb0JBQW9CLENBQUMsV0FBVyxDQUFDLENBQUM7WUFFckMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUEsZ0JBQVEsRUFBQyxrQkFBa0IsRUFBRSxHQUFHLEVBQUU7SUFDaEMsSUFBQSxVQUFFLEVBQUMsb0NBQW9DLEVBQUUsR0FBRyxFQUFFO1FBQzVDLGdCQUFNLENBQUMsV0FBVyxDQUFDLDBCQUFjLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEMsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUEsZ0JBQVEsRUFBQywwQkFBMEIsRUFBRSxHQUFHLEVBQUU7SUFDeEMsTUFBTSxTQUFTLEdBQUcsZUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsc0JBQWMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDM0UsTUFBTSxhQUFhLEdBQUcsZUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsOEJBQXNCLENBQUMsQ0FBQztJQUN0RSxNQUFNLFlBQVksR0FBRyxlQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxzQkFBYyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUU3RSxJQUFBLGdCQUFRLEVBQUMsbUJBQW1CLEVBQUUsR0FBRyxFQUFFO1FBQ2pDLElBQUEsVUFBRSxFQUFDLDJDQUEyQyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ3pELE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTztpQkFDSixZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUM7aUJBQy9FLFFBQVEsQ0FBQyxZQUFZLENBQUM7aUJBQ3RCLEtBQUssQ0FBQyxDQUFDLENBQUM7aUJBQ1IsR0FBRyxDQUFDLE9BQU8sQ0FBQztpQkFDWixZQUFZLENBQUMsaUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQztpQkFDM0Msb0JBQW9CLENBQUMsaUJBQVMsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1lBRS9ELE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFFdkQsZ0JBQU0sQ0FBQyxFQUFFLENBQUMsRUFBRSxZQUFZLDhCQUFnQixDQUFDLENBQUM7WUFDMUMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLGlCQUFpQixFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDOUMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ3JELENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMseURBQXlELEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDdkUsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxPQUFPO2lCQUNKLFlBQVksQ0FBQyxFQUFFLEtBQUssRUFBRSxzQkFBYyxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQztpQkFDcEcsWUFBWSxDQUFDLEVBQUUsS0FBSyxFQUFFLHNCQUFjLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDO2lCQUNuRyxZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsc0JBQWMsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUM7aUJBQ3BHLFFBQVEsQ0FBQyxZQUFZLENBQUM7aUJBQ3RCLEtBQUssQ0FBQyxFQUFFLENBQUM7aUJBQ1QsR0FBRyxDQUFDLE9BQU8sQ0FBQztpQkFDWixZQUFZLENBQUMsaUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQztpQkFDM0Msb0JBQW9CLENBQUMsaUJBQVMsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1lBRS9ELE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFFdkQsZ0JBQU0sQ0FBQyxFQUFFLENBQUMsRUFBRSxZQUFZLDhCQUFnQixDQUFDLENBQUM7WUFDMUMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLGlCQUFpQixFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDOUMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3pDLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMsNENBQTRDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDMUQsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxPQUFPO2lCQUNKLFlBQVksQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUM7aUJBQ25FLEtBQUssQ0FBQyxDQUFDLENBQUM7aUJBQ1IsR0FBRyxDQUFDLE9BQU8sQ0FBQztpQkFDWixZQUFZLENBQUMsaUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQztpQkFDM0Msb0JBQW9CLENBQUMsaUJBQVMsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1lBRS9ELE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFFdkQsZ0JBQU0sQ0FBQyxFQUFFLENBQUMsRUFBRSxZQUFZLDhCQUFnQixDQUFDLENBQUM7WUFDMUMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ2xELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLGdCQUFRLEVBQUMseUJBQXlCLEVBQUUsR0FBRyxFQUFFO1FBQ3ZDLElBQUEsVUFBRSxFQUFDLDZDQUE2QyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzNELE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3pGLE1BQU0sZ0JBQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxnREFBZ0QsQ0FBQyxDQUFDO1FBQzVHLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMsdUNBQXVDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDckQsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxPQUFPO2lCQUNKLFlBQVksQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUM7aUJBQ3BFLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLFdBQVcsQ0FBQztpQkFDekIsb0JBQW9CLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEMsTUFBTSxnQkFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLHNCQUFjLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdkYsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFBLFVBQUUsRUFBQyxxQ0FBcUMsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNuRCxNQUFNLE9BQU8sR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzVELE9BQU87aUJBQ0osWUFBWSxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQztpQkFDcEUsS0FBSyxDQUFDLENBQUMsQ0FBQztpQkFDUixZQUFZLENBQUMsV0FBVyxDQUFDO2lCQUN6QixvQkFBb0IsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNwQyxNQUFNLGdCQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsc0JBQWMsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNyRixDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLDhDQUE4QyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzVELE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTztpQkFDSixZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDO2lCQUNwRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2lCQUNSLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osb0JBQW9CLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEMsTUFBTSxnQkFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLHNCQUFjLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUM5RixDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLHNEQUFzRCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ3BFLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTztpQkFDSixZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDO2lCQUNwRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2lCQUNSLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQzdCLE1BQU0sZ0JBQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxzQkFBYyxDQUFDLDJCQUEyQixDQUFDLENBQUM7UUFDdEcsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsZ0JBQVEsRUFBQyxvREFBb0QsRUFBRSxHQUFHLEVBQUU7UUFDbEUsSUFBQSxVQUFFLEVBQUMsOENBQThDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDNUQsTUFBTSxVQUFVLEdBQUcsQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBRXZGLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTztpQkFDSixZQUFZLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUMzQixRQUFRLENBQUMsWUFBWSxDQUFDO2lCQUN0QixLQUFLLENBQUMsRUFBRSxDQUFDO2lCQUNULEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLFdBQVcsQ0FBQztpQkFDekIsb0JBQW9CLENBQUMsV0FBVyxDQUFDLENBQUM7WUFFckMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztZQUN2RCxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsYUFBYSxFQUFFLENBQUM7WUFFakMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNwQyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN4RCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNsRCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMxRCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4RCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBQSxnQkFBUSxFQUFDLGlDQUFpQyxFQUFFLEdBQUcsRUFBRTtRQUMvQyxJQUFBLFVBQUUsRUFBQyxrREFBa0QsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNoRSxNQUFNLE9BQU8sR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzVELE9BQU87aUJBQ0osWUFBWSxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDO2lCQUM5RSxRQUFRLENBQUMsWUFBWSxDQUFDO2lCQUN0QixLQUFLLENBQUMsQ0FBQyxDQUFDO2lCQUNSLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLFdBQVcsQ0FBQztpQkFDekIsb0JBQW9CLENBQUMsV0FBVyxDQUFDLENBQUM7WUFFckMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztZQUN2RCxNQUFNLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUV6QyxnQkFBTSxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLCtCQUFtQixDQUFDLENBQUMsQ0FBQztZQUN2RCxnQkFBTSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUNoRCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLDZDQUE2QyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzNELE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTztpQkFDSixZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUM7aUJBQzlFLFFBQVEsQ0FBQyxZQUFZLENBQUM7aUJBQ3RCLEtBQUssQ0FBQyxHQUFHLENBQUM7aUJBQ1YsR0FBRyxDQUFDLE9BQU8sQ0FBQztpQkFDWixZQUFZLENBQUMsV0FBVyxDQUFDO2lCQUN6QixvQkFBb0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUVyQyxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFxQixDQUFDO1lBQ3ZELE1BQU0sV0FBVyxHQUFHLE1BQU0sRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBRXpDLEVBQUUsQ0FBQyxZQUFZLENBQUMsMkJBQW1CLENBQUMsY0FBYyxDQUFDLENBQUM7WUFFcEQsTUFBTSxZQUFZLEdBQUcsTUFBTSxFQUFFLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUNsRCxnQkFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLCtCQUFtQixDQUFDLENBQUMsQ0FBQztZQUN4RCxnQkFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLFdBQVcsQ0FBQyxNQUFNLEVBQUUseUJBQXlCLENBQUMsQ0FBQztRQUNqRixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBQSxnQkFBUSxFQUFDLGlDQUFpQyxFQUFFLEdBQUcsRUFBRTtRQUMvQyxJQUFBLFVBQUUsRUFBQyx1REFBdUQsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNyRSxNQUFNLE9BQU8sR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzVELE9BQU87aUJBQ0osWUFBWSxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDO2lCQUMvRSxRQUFRLENBQUMsWUFBWSxDQUFDO2lCQUN0QixLQUFLLENBQUMsRUFBRSxDQUFDO2lCQUNULEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLFdBQVcsQ0FBQztpQkFDekIsb0JBQW9CLENBQUMsV0FBVyxDQUFDLENBQUM7WUFFckMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztZQUN2RCxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7WUFFekIsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSwrQkFBbUIsQ0FBQyxDQUFDO1lBQ25ELGdCQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDbkMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUN2QyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQ3BELGdCQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxZQUFZLENBQUMsQ0FBQztZQUM1RCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3RDLGdCQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDbEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsZ0JBQVEsRUFBQyx1QkFBdUIsRUFBRSxHQUFHLEVBQUU7UUFDckMsSUFBQSxVQUFFLEVBQUMsNERBQTRELEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDMUUsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxPQUFPO2lCQUNKLFlBQVksQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUM7aUJBQ25FLEtBQUssQ0FBQyxDQUFDLENBQUM7aUJBQ1IsR0FBRyxDQUFDLE9BQU8sQ0FBQztpQkFDWixZQUFZLENBQUMsaUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQztpQkFDM0Msb0JBQW9CLENBQUMsaUJBQVMsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1lBRS9ELE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFDdkQsTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUV6QixFQUFFLENBQUMsWUFBWSxDQUFDLDJCQUFtQixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ3BELE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFFdkIsZ0JBQU0sQ0FBQyxjQUFjLENBQUMsVUFBVSxFQUFFLFFBQVEsRUFBRSxrREFBa0QsQ0FBQyxDQUFDO1FBQ2xHLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLGdCQUFRLEVBQUMsNkJBQTZCLEVBQUUsR0FBRyxFQUFFO1FBQzNDLElBQUEsVUFBRSxFQUFDLHNFQUFzRSxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ3BGLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTztpQkFDSixZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUM7aUJBQy9FLEtBQUssQ0FBQyxDQUFDLENBQUM7aUJBQ1IsR0FBRyxDQUFDLE9BQU8sQ0FBQztpQkFDWixZQUFZLENBQUMsaUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQztpQkFDM0Msb0JBQW9CLENBQUMsaUJBQVMsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1lBRS9ELE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFDdkQsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDekMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDekQsMkNBQTJDO1lBQzNDLGdCQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ25ELHlEQUF5RDtZQUN6RCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsRUFBRSxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUNqRixDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLDJEQUEyRCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ3pFLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTztpQkFDSixZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDO2lCQUNwRSxZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDO2lCQUNwRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2lCQUNSLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLGlCQUFTLENBQUMsbUJBQW1CLENBQUM7aUJBQzNDLG9CQUFvQixDQUFDLGlCQUFTLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUUvRCxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFxQixDQUFDO1lBQ3ZELGdCQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3hDLGdCQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzdDLG1EQUFtRDtZQUNuRCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNwRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBQSxnQkFBUSxFQUFDLDBEQUEwRCxFQUFFLEdBQUcsRUFBRTtRQUN4RSxJQUFBLFVBQUUsRUFBQyxzRUFBc0UsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNwRixNQUFNLFNBQVMsR0FBRyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQztZQUV6RixNQUFNLE9BQU8sR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzVELE9BQU87aUJBQ0osWUFBWSxDQUFDLFNBQVMsQ0FBQztpQkFDdkIsUUFBUSxDQUFDLFlBQVksQ0FBQztpQkFDdEIsS0FBSyxDQUFDLENBQUMsQ0FBQztpQkFDUixHQUFHLENBQUMsT0FBTyxDQUFDO2lCQUNaLFlBQVksQ0FBQyxpQkFBUyxDQUFDLG1CQUFtQixDQUFDO2lCQUMzQyxvQkFBb0IsQ0FBQyxpQkFBUyxDQUFDLDJCQUEyQixDQUFDLENBQUM7WUFFL0QsTUFBTSxVQUFVLEdBQUcsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztZQUMvRCxNQUFNLFVBQVUsR0FBRyxNQUFNLFVBQVUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUVoRCx5QkFBeUI7WUFDekIsTUFBTSxRQUFRLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM3RCxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQzFCLE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxRQUFRLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFFaEUsTUFBTSxHQUFHLEdBQUcsVUFBVSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3ZDLGdCQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDbEMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsRUFBRSxTQUFTLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFDOUUsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFDeEUsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDcEQsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDaEQsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxFQUFFLFdBQVcsRUFBRSxFQUFFLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQzFGLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMsdUNBQXVDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDckQsK0ZBQStGO1lBQy9GLE1BQU0sVUFBVSxHQUFHO2dCQUNqQixFQUFFLEtBQUssRUFBRSxzQkFBYyxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUU7Z0JBQ3hGLEVBQUUsS0FBSyxFQUFFLHNCQUFjLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRTthQUN4RixDQUFDO1lBRUYsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxPQUFPO2lCQUNKLFlBQVksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQzNCLFlBQVksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQzNCLEtBQUssQ0FBQyxFQUFFLENBQUM7aUJBQ1QsR0FBRyxDQUFDLE9BQU8sQ0FBQztpQkFDWixZQUFZLENBQUMsaUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQztpQkFDM0Msb0JBQW9CLENBQUMsaUJBQVMsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1lBRS9ELE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFDL0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxVQUFVLENBQUMsU0FBUyxFQUFFLENBQUM7WUFFaEQsTUFBTSxRQUFRLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM3RCxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQzFCLE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxRQUFRLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFFaEUsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLGlCQUFpQixFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDdEQsZ0JBQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFFaEMsTUFBTSxJQUFJLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2pDLGdCQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDbkMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUN2QyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLGlCQUFTLENBQUMsbUJBQW1CLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUNoRixnQkFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsaUJBQVMsQ0FBQywyQkFBMkIsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBRWhHLE1BQU0sR0FBRyxHQUFHLFVBQVUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUN2QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUMzQyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztnQkFDbEYsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsRUFBRSxhQUFhLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztnQkFDekUsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ3hELGdCQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3RELENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLG1FQUFtRSxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ2pGLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTztpQkFDSixZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDO2lCQUNsRSxLQUFLLENBQUMsRUFBRSxDQUFDO2lCQUNULEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLGlCQUFTLENBQUMsbUJBQW1CLENBQUM7aUJBQzNDLG9CQUFvQixDQUFDLGlCQUFTLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUUvRCxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFxQixDQUFDO1lBQ3ZELEVBQUUsQ0FBQyxZQUFZLENBQUMsMkJBQW1CLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDcEQsTUFBTSxTQUFTLEdBQUcsTUFBTSxFQUFFLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUUvQyxxQ0FBcUM7WUFDckMsTUFBTSxRQUFRLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM3RCxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3pCLE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxRQUFRLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFFaEUsTUFBTSxHQUFHLEdBQUcsVUFBVSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3RDLGdCQUFNLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxTQUFTLEVBQUUsK0JBQStCLENBQUMsQ0FBQztZQUM5RCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFJLENBQUMsT0FBTyxFQUFFLDJCQUFtQixDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvRSxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLGdFQUFnRSxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzlFLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTztpQkFDSixZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUM7aUJBQ2xGLEtBQUssQ0FBQyxDQUFDLENBQUM7aUJBQ1IsR0FBRyxDQUFDLE9BQU8sQ0FBQztpQkFDWixZQUFZLENBQUMsaUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQztpQkFDM0Msb0JBQW9CLENBQUMsaUJBQVMsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1lBRS9ELE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFDL0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxVQUFVLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDaEQsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUVqQyxNQUFNLFFBQVEsR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzdELFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDMUIsTUFBTSxVQUFVLEdBQUcsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztZQUVoRSxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBRTlDLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN6QyxNQUFNLFlBQVksR0FBRyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDekMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDM0QsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdkQsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDekUsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLG9CQUFvQixFQUFFLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1lBQ3pGLGdCQUFNLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2pFLGdCQUFNLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBRW5FLE1BQU0sV0FBVyxHQUFHLFVBQVUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUMvQyxNQUFNLFdBQVcsR0FBRyxVQUFVLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDL0MsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDM0QsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFDM0YsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFDckYsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDakUsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7WUFFN0QsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLFVBQVUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN4RCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUNyRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFBLGdCQUFRLEVBQUMsbURBQW1ELEVBQUUsR0FBRyxFQUFFO0lBQ2pFLElBQUksS0FBbUIsQ0FBQztJQUN4QixJQUFJLElBQVMsQ0FBQztJQUVkLE1BQU0sU0FBUyxHQUFHLGVBQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLHNCQUFjLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzNFLE1BQU0sYUFBYSxHQUFHLGVBQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLDhCQUFzQixDQUFDLENBQUM7SUFFdEUsSUFBQSxjQUFNLEVBQUM7UUFDTCxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQVEsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELEtBQUssQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBYSxFQUFFLEVBQUU7WUFDN0MsTUFBTSxlQUFlLEdBQUc7Z0JBQ3RCLElBQUksRUFBRSxRQUFRO2dCQUNkLFFBQVEsRUFBRSxlQUFlO2dCQUN6QixPQUFPLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFO2dCQUM1QixRQUFRLEVBQUUsRUFBRTthQUNOLENBQUM7WUFDVCxPQUFPLGVBQU0sQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQ3BELENBQUMsQ0FBQyxDQUFDO1FBQ0gsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0IsSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDOUIsQ0FBQyxDQUFDLENBQUM7SUFFSCxLQUFLLFVBQVUsaUJBQWlCLENBQzlCLFVBQTBFLEVBQzFFLEtBQUssR0FBRyxDQUFDO1FBRVQsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxlQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDakUsS0FBSyxNQUFNLEVBQUUsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUM1QixPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzNCLENBQUM7UUFDRCxPQUFPO2FBQ0osS0FBSyxDQUFDLEtBQUssQ0FBQzthQUNaLEdBQUcsQ0FBQyxPQUFPLENBQUM7YUFDWixZQUFZLENBQUMsaUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQzthQUMzQyxvQkFBb0IsQ0FBQyxpQkFBUyxDQUFDLDJCQUEyQixDQUFDLENBQUM7UUFDL0QsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztRQUN2RCxPQUFPLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUN4QixDQUFDO0lBRUQsSUFBQSxnQkFBUSxFQUFDLGtCQUFrQixFQUFFLEdBQUcsRUFBRTtRQUNoQyxJQUFBLFVBQUUsRUFBQywwREFBMEQsRUFBRSxLQUFLLElBQUksRUFBRTtZQUN4RSxNQUFNLEtBQUssR0FBRyxNQUFNLGlCQUFpQixDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzFHLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUN0RCxnQkFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSw0QkFBNEIsQ0FBQyxDQUFDO1lBQ3ZFLGdCQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzdDLGdCQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxFQUFFLGFBQWEsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ3pGLDJDQUEyQztZQUMzQyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQztRQUMzRCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLHNEQUFzRCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ3BFLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQy9DLGdCQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNyQyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBQSxnQkFBUSxFQUFDLG1CQUFtQixFQUFFLEdBQUcsRUFBRTtRQUNqQyxJQUFBLFVBQUUsRUFBQyxxREFBcUQsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNuRSxNQUFNLEtBQUssR0FBRyxNQUFNLGlCQUFpQixDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMvRixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztnQkFDMUMsVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFO2dCQUNyQixRQUFRLEVBQUUsRUFBRTthQUNiLENBQUMsQ0FBQztZQUNILGdCQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNuQyxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLHFEQUFxRCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ25FLE1BQU0sS0FBSyxHQUFHLE1BQU0saUJBQWlCLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2hHLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDO2dCQUMxQyxVQUFVLEVBQUUsRUFBRSxLQUFLLEVBQUU7Z0JBQ3JCLFFBQVEsRUFBRTtvQkFDUixVQUFVLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxDQUFDLEVBQUUsd0JBQXdCO2lCQUN4RjthQUNGLENBQUMsQ0FBQztZQUNILGdCQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNuQyxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLG9EQUFvRCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ2xFLE1BQU0sS0FBSyxHQUFHLE1BQU0saUJBQWlCLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2hHLE1BQU0sWUFBWSxHQUFHLGVBQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLDRDQUE0QyxDQUFDLENBQUM7WUFDM0YsTUFBTSxnQkFBTSxDQUFDLE9BQU8sQ0FDbEIsR0FBRyxFQUFFLENBQ0gsSUFBSSxDQUFDLGlCQUFpQixDQUFDO2dCQUNyQixVQUFVLEVBQUUsRUFBRSxLQUFLLEVBQUU7Z0JBQ3JCLFFBQVEsRUFBRSxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRTthQUMzRSxDQUFDLEVBQ0osb0JBQW9CLENBQ3JCLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLG1EQUFtRCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ2pFLE1BQU0sS0FBSyxHQUFHLE1BQU0saUJBQWlCLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2hHLE1BQU0sZ0JBQU0sQ0FBQyxPQUFPLENBQ2xCLEdBQUcsRUFBRSxDQUNILElBQUksQ0FBQyxpQkFBaUIsQ0FBQztnQkFDckIsVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFO2dCQUNyQixRQUFRLEVBQUUsRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUU7YUFDdEUsQ0FBQyxFQUNKLGlCQUFpQixDQUNsQixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFBLFVBQUUsRUFBQyxnRUFBZ0UsRUFBRSxLQUFLLElBQUksRUFBRTtZQUM5RSxNQUFNLEtBQUssR0FBRyxNQUFNLGlCQUFpQixDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMvRixNQUFNLGdCQUFNLENBQUMsT0FBTyxDQUNsQixHQUFHLEVBQUUsQ0FDSCxJQUFJLENBQUMsaUJBQWlCLENBQUM7Z0JBQ3JCLFVBQVUsRUFBRSxFQUFFLEtBQUssRUFBRTtnQkFDckIsUUFBUSxFQUFFO29CQUNSLFVBQVUsRUFBRTt3QkFDVixFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRTt3QkFDOUMsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUU7cUJBQy9DO2lCQUNGO2FBQ0YsQ0FBQyxFQUNKLGdCQUFnQixDQUNqQixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFBLFVBQUUsRUFBQyw4Q0FBOEMsRUFBRSxLQUFLLElBQUksRUFBRTtZQUM1RCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDOUUsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ25DLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLGdCQUFRLEVBQUMsaUNBQWlDLEVBQUUsR0FBRyxFQUFFO1FBQy9DLElBQUEsVUFBRSxFQUFDLG1EQUFtRCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ2pFLE1BQU0sUUFBUSxHQUFHLGVBQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLHNCQUFjLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pFLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsZUFBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBQ2pFLE9BQU87aUJBQ0osWUFBWSxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQztpQkFDcEUsUUFBUSxDQUFDLFFBQVEsQ0FBQztpQkFDbEIsS0FBSyxDQUFDLENBQUMsQ0FBQztpQkFDUixHQUFHLENBQUMsT0FBTyxDQUFDO2lCQUNaLFlBQVksQ0FBQyxpQkFBUyxDQUFDLG1CQUFtQixDQUFDO2lCQUMzQyxvQkFBb0IsQ0FBQyxpQkFBUyxDQUFDLDJCQUEyQixDQUFDLENBQUM7WUFDL0QsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztZQUN2RCxNQUFNLEtBQUssR0FBRyxNQUFNLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUVuQyxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztnQkFDMUMsVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFO2dCQUNyQixRQUFRLEVBQUUsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFO2FBQ2pDLENBQUMsQ0FBQztZQUNILGdCQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNuQyxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLDRDQUE0QyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzFELE1BQU0sUUFBUSxHQUFHLGVBQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLHNCQUFjLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pFLE1BQU0sYUFBYSxHQUFHLGVBQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLHNCQUFjLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQy9FLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsZUFBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBQ2pFLE9BQU87aUJBQ0osWUFBWSxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQztpQkFDcEUsUUFBUSxDQUFDLFFBQVEsQ0FBQztpQkFDbEIsS0FBSyxDQUFDLENBQUMsQ0FBQztpQkFDUixHQUFHLENBQUMsT0FBTyxDQUFDO2lCQUNaLFlBQVksQ0FBQyxpQkFBUyxDQUFDLG1CQUFtQixDQUFDO2lCQUMzQyxvQkFBb0IsQ0FBQyxpQkFBUyxDQUFDLDJCQUEyQixDQUFDLENBQUM7WUFDL0QsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztZQUN2RCxNQUFNLEtBQUssR0FBRyxNQUFNLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUVuQyxNQUFNLGdCQUFNLENBQUMsT0FBTyxDQUNsQixHQUFHLEVBQUUsQ0FDSCxJQUFJLENBQUMsaUJBQWlCLENBQUM7Z0JBQ3JCLFVBQVUsRUFBRSxFQUFFLEtBQUssRUFBRTtnQkFDckIsUUFBUSxFQUFFLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBRTthQUN0QyxDQUFDLEVBQ0osb0JBQW9CLENBQ3JCLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLGtFQUFrRSxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ2hGLE1BQU0sZ0JBQWdCLEdBQUcsZUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsc0JBQWMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDakYsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxlQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDakUsT0FBTztpQkFDSixZQUFZLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDO2lCQUNwRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2lCQUNSLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLGlCQUFTLENBQUMsbUJBQW1CLENBQUM7aUJBQzNDLG9CQUFvQixDQUFDLGlCQUFTLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUMvRCxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFxQixDQUFDO1lBQ3ZELE1BQU0sS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBRW5DLE1BQU0sZ0JBQU0sQ0FBQyxPQUFPLENBQ2xCLEdBQUcsRUFBRSxDQUNILElBQUksQ0FBQyxpQkFBaUIsQ0FBQztnQkFDckIsVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFO2dCQUNyQixRQUFRLEVBQUUsRUFBRSxRQUFRLEVBQUUsZ0JBQWdCLEVBQUU7YUFDekMsQ0FBQyxFQUNKLG9CQUFvQixDQUNyQixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFBLFVBQUUsRUFBQyxtRUFBbUUsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNqRixNQUFNLFFBQVEsR0FBRyxlQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxzQkFBYyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN6RSxNQUFNLE9BQU8sR0FBRyxJQUFJLDRDQUF1QixDQUFDLGVBQUssQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztZQUNqRSxPQUFPO2lCQUNKLFlBQVksQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUM7aUJBQ3BFLFFBQVEsQ0FBQyxRQUFRLENBQUM7aUJBQ2xCLEtBQUssQ0FBQyxDQUFDLENBQUM7aUJBQ1IsR0FBRyxDQUFDLE9BQU8sQ0FBQztpQkFDWixZQUFZLENBQUMsaUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQztpQkFDM0Msb0JBQW9CLENBQUMsaUJBQVMsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1lBQy9ELE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFDdkQsTUFBTSxLQUFLLEdBQUcsTUFBTSxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUM7WUFFbkMseURBQXlEO1lBQ3pELE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDO2dCQUMxQyxVQUFVLEVBQUUsRUFBRSxLQUFLLEVBQUU7Z0JBQ3JCLFFBQVEsRUFBRSxFQUFFO2FBQ2IsQ0FBQyxDQUFDO1lBQ0gsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ25DLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUEsZ0JBQVEsRUFBQywyQkFBMkIsRUFBRSxHQUFHLEVBQUU7SUFDekMsTUFBTSxZQUFZLEdBQUcsZUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsNENBQTRDLENBQUMsQ0FBQztJQUMzRixNQUFNLFlBQVksR0FDaEIsNElBQTRJLENBQUM7SUFFL0ksSUFBQSxnQkFBUSxFQUFDLFlBQVksRUFBRSxHQUFHLEVBQUU7UUFDMUIsSUFBQSxVQUFFLEVBQUMsdURBQXVELEVBQUUsR0FBRyxFQUFFO1lBQy9ELE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7WUFFN0QsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3ZDLGdCQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDdkMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxZQUFZLENBQUMsQ0FBQztZQUNqRCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ3JELENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMsb0NBQW9DLEVBQUUsR0FBRyxFQUFFO1lBQzVDLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7WUFDNUUsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMsMkNBQTJDLEVBQUUsR0FBRyxFQUFFO1lBQ25ELE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsZ0JBQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDLEVBQUUsMEJBQTBCLENBQUMsQ0FBQztRQUMvRyxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLGlDQUFpQyxFQUFFLEdBQUcsRUFBRTtZQUN6QyxNQUFNLE9BQU8sR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzVELGdCQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLGtCQUFrQixDQUFDLENBQUM7UUFDaEcsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFBLFVBQUUsRUFBQyxtQ0FBbUMsRUFBRSxHQUFHLEVBQUU7WUFDM0MsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxnQkFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLENBQUMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFHLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMsNkNBQTZDLEVBQUUsR0FBRyxFQUFFO1lBQ3JELE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsZ0JBQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztRQUN0RyxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLDBDQUEwQyxFQUFFLEdBQUcsRUFBRTtZQUNsRCxNQUFNLE9BQU8sR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzVELGdCQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLGtCQUFrQixDQUFDLENBQUM7UUFDbkcsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFBLFVBQUUsRUFBQyx1Q0FBdUMsRUFBRSxHQUFHLEVBQUU7WUFDL0MsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxnQkFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQ3BILENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMsaUNBQWlDLEVBQUUsR0FBRyxFQUFFO1lBQ3pDLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsZ0JBQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxlQUFlLENBQUMsQ0FBQztRQUNsSCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLHdEQUF3RCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ3RFLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTztpQkFDSixVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQztpQkFDcEQsS0FBSyxDQUFDLENBQUMsQ0FBQztpQkFDUixHQUFHLENBQUMsT0FBTyxDQUFDO2lCQUNaLFlBQVksQ0FBQyxpQkFBUyxDQUFDLG1CQUFtQixDQUFDO2lCQUMzQyxvQkFBb0IsQ0FBQyxpQkFBUyxDQUFDLDJCQUEyQixDQUFDLENBQUM7WUFFL0QsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztZQUN2RCxnQkFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLFlBQVksOEJBQWdCLENBQUMsQ0FBQztZQUMxQyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2pELGdCQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDL0MsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLGlCQUFpQixFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDaEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsZ0JBQVEsRUFBQyxtRUFBbUUsRUFBRSxHQUFHLEVBQUU7UUFDakYsSUFBQSxVQUFFLEVBQUMsd0RBQXdELEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDdEUsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxPQUFPO2lCQUNKLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDO2lCQUNwRCxLQUFLLENBQUMsQ0FBQyxDQUFDO2lCQUNSLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLGlCQUFTLENBQUMsbUJBQW1CLENBQUM7aUJBQzNDLG9CQUFvQixDQUFDLGlCQUFTLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUUvRCxNQUFNLFVBQVUsR0FBRyxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFxQixDQUFDO1lBQy9ELE1BQU0sVUFBVSxHQUFHLE1BQU0sVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBRWhELE1BQU0sUUFBUSxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDN0QsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUMxQixNQUFNLFVBQVUsR0FBRyxDQUFDLE1BQU0sUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFxQixDQUFDO1lBRWhFLGdCQUFNLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDekQsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzFDLGdCQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDdkMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsRUFBRSxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUM3RSxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ2pGLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMsc0RBQXNELEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDcEUsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxPQUFPO2lCQUNKLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDO2lCQUNwRCxLQUFLLENBQUMsQ0FBQyxDQUFDO2lCQUNSLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLGlCQUFTLENBQUMsbUJBQW1CLENBQUM7aUJBQzNDLG9CQUFvQixDQUFDLGlCQUFTLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUUvRCxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFxQixDQUFDO1lBQ3ZELEVBQUUsQ0FBQyxZQUFZLENBQUMsMkJBQW1CLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDcEQsTUFBTSxTQUFTLEdBQUcsTUFBTSxFQUFFLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUUvQyxNQUFNLFFBQVEsR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzdELFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDekIsTUFBTSxVQUFVLEdBQUcsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztZQUVoRSxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDMUMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN2QyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQy9FLE1BQU0sR0FBRyxHQUFHLFVBQVUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN0QyxnQkFBTSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssU0FBUyxDQUFDLENBQUM7WUFDN0IsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsR0FBSSxDQUFDLE9BQU8sRUFBRSwyQkFBbUIsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDL0UsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFBLFVBQUUsRUFBQyxxREFBcUQsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNuRSxNQUFNLE9BQU8sR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzVELE9BQU87aUJBQ0osVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLENBQUM7aUJBQ3BELEtBQUssQ0FBQyxDQUFDLENBQUM7aUJBQ1IsR0FBRyxDQUFDLE9BQU8sQ0FBQztpQkFDWixZQUFZLENBQUMsaUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQztpQkFDM0Msb0JBQW9CLENBQUMsaUJBQVMsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1lBRS9ELE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQXFCLENBQUM7WUFDL0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxVQUFVLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDaEQsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUVqQyxNQUFNLFFBQVEsR0FBRyxJQUFJLDRDQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzdELFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDMUIsTUFBTSxVQUFVLEdBQUcsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztZQUVoRSxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ2hELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLGdCQUFRLEVBQUMsNkJBQTZCLEVBQUUsR0FBRyxFQUFFO1FBQzNDLElBQUEsVUFBRSxFQUFDLG1EQUFtRCxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ2pFLE1BQU0sT0FBTyxHQUFHLElBQUksNENBQXVCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUQsT0FBTztpQkFDSixVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDO2lCQUNoRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2lCQUNSLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLGlCQUFTLENBQUMsbUJBQW1CLENBQUM7aUJBQzNDLG9CQUFvQixDQUFDLGlCQUFTLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUUvRCxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFxQixDQUFDO1lBQ3ZELGdCQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3pDLGdCQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxFQUFFLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ3RGLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBQSxVQUFFLEVBQUMsNENBQTRDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDMUQsTUFBTSxPQUFPLEdBQUcsSUFBSSw0Q0FBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM1RCxPQUFPO2lCQUNKLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDO2lCQUNwRCxLQUFLLENBQUMsQ0FBQyxDQUFDO2lCQUNSLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1osWUFBWSxDQUFDLGlCQUFTLENBQUMsbUJBQW1CLENBQUM7aUJBQzNDLG9CQUFvQixDQUFDLGlCQUFTLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUUvRCxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFxQixDQUFDO1lBQ3ZELE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUV6QixnQkFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBQ3hDLGdCQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzVDLGdCQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQ3RELGdCQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzFELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUEsZ0JBQVEsRUFBQywrQ0FBK0MsRUFBRSxHQUFHLEVBQUU7SUFDN0QsSUFBSSxLQUFtQixDQUFDO0lBQ3hCLElBQUksSUFBUyxDQUFDO0lBRWQsTUFBTSxZQUFZLEdBQUcsZUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsNENBQTRDLENBQUMsQ0FBQztJQUMzRixNQUFNLFlBQVksR0FDaEIsNElBQTRJLENBQUM7SUFFL0ksSUFBQSxjQUFNLEVBQUM7UUFDTCxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQVEsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELEtBQUssQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBYSxFQUFFLEVBQUU7WUFDN0MsTUFBTSxlQUFlLEdBQUc7Z0JBQ3RCLElBQUksRUFBRSxRQUFRO2dCQUNkLFFBQVEsRUFBRSxlQUFlO2dCQUN6QixPQUFPLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFO2dCQUM1QixRQUFRLEVBQUUsRUFBRTthQUNOLENBQUM7WUFDVCxPQUFPLGVBQU0sQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQ3BELENBQUMsQ0FBQyxDQUFDO1FBQ0gsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0IsSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDOUIsQ0FBQyxDQUFDLENBQUM7SUFFSCxLQUFLLFVBQVUsY0FBYyxDQUFDLFFBQWdCLEVBQUUsUUFBZ0IsRUFBRSxLQUFLLEdBQUcsQ0FBQztRQUN6RSxNQUFNLE9BQU8sR0FBRyxJQUFJLDRDQUF1QixDQUFDLGVBQUssQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUNqRSxPQUFPO2FBQ0osVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUM7YUFDNUMsS0FBSyxDQUFDLEtBQUssQ0FBQzthQUNaLEdBQUcsQ0FBQyxPQUFPLENBQUM7YUFDWixZQUFZLENBQUMsaUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQzthQUMzQyxvQkFBb0IsQ0FBQyxpQkFBUyxDQUFDLDJCQUEyQixDQUFDLENBQUM7UUFDL0QsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBcUIsQ0FBQztRQUN2RCxPQUFPLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUN4QixDQUFDO0lBRUQsSUFBQSxVQUFFLEVBQUMsa0VBQWtFLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDaEYsTUFBTSxLQUFLLEdBQUcsTUFBTSxjQUFjLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQy9ELE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDO1lBQzFDLFVBQVUsRUFBRSxFQUFFLEtBQUssRUFBRTtZQUNyQixRQUFRLEVBQUU7Z0JBQ1IsVUFBVSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDO2FBQ3pFO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ25DLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBQSxVQUFFLEVBQUMsNkRBQTZELEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDM0UsTUFBTSxLQUFLLEdBQUcsTUFBTSxjQUFjLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQy9ELE1BQU0sWUFBWSxHQUFHLGVBQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLDRDQUE0QyxDQUFDLENBQUM7UUFDM0YsTUFBTSxnQkFBTSxDQUFDLE9BQU8sQ0FDbEIsR0FBRyxFQUFFLENBQ0gsSUFBSSxDQUFDLGlCQUFpQixDQUFDO1lBQ3JCLFVBQVUsRUFBRSxFQUFFLEtBQUssRUFBRTtZQUNyQixRQUFRLEVBQUUsRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLENBQUMsRUFBRTtTQUN2RixDQUFDLEVBQ0osa0JBQWtCLENBQ25CLENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsVUFBRSxFQUFDLG9EQUFvRCxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ2xFLE1BQU0sS0FBSyxHQUFHLE1BQU0sY0FBYyxDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQztRQUMvRCxNQUFNLGFBQWEsR0FBRyxvQkFBb0IsQ0FBQztRQUMzQyxNQUFNLGdCQUFNLENBQUMsT0FBTyxDQUNsQixHQUFHLEVBQUUsQ0FDSCxJQUFJLENBQUMsaUJBQWlCLENBQUM7WUFDckIsVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFO1lBQ3JCLFFBQVEsRUFBRSxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsQ0FBQyxFQUFFO1NBQ3hGLENBQUMsRUFDSixtQkFBbUIsQ0FDcEIsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBQSxVQUFFLEVBQUMsNkRBQTZELEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDM0UsTUFBTSxLQUFLLEdBQUcsTUFBTSxjQUFjLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQy9ELE1BQU0sZ0JBQU0sQ0FBQyxPQUFPLENBQ2xCLEdBQUcsRUFBRSxDQUNILElBQUksQ0FBQyxpQkFBaUIsQ0FBQztZQUNyQixVQUFVLEVBQUUsRUFBRSxLQUFLLEVBQUU7WUFDckIsUUFBUSxFQUFFO2dCQUNSLFVBQVUsRUFBRTtvQkFDVixFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFO29CQUMxRCxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFO2lCQUMzRDthQUNGO1NBQ0YsQ0FBQyxFQUNKLFdBQVcsQ0FDWixDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLFVBQUUsRUFBQywwRUFBMEUsRUFBRSxLQUFLLElBQUksRUFBRTtRQUN4RixNQUFNLEtBQUssR0FBRyxNQUFNLGNBQWMsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDL0QsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELGdCQUFNLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDekMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDN0MsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLEVBQUUsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDMUYsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7IGRlc2NyaWJlLCBpdCwgYmVmb3JlIH0gZnJvbSAnbW9jaGEnO1xuaW1wb3J0IHsgZXRoZXJzIH0gZnJvbSAnZXRoZXJzJztcbmltcG9ydCB7IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyIH0gZnJvbSAnLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbkJ1aWxkZXInO1xuaW1wb3J0IHsgVGlwMjBUcmFuc2FjdGlvbiB9IGZyb20gJy4uLy4uL3NyYy9saWIvdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHtcbiAgYW1vdW50VG9UaXAyMFVuaXRzLFxuICB0aXAyMFVuaXRzVG9BbW91bnQsXG4gIHN0cmluZ1RvQnl0ZXMzMixcbiAgZW5jb2RlVGlwMjBUcmFuc2ZlcldpdGhNZW1vLFxuICBpc1ZhbGlkVGlwMjBBbW91bnQsXG59IGZyb20gJy4uLy4uL3NyYy9saWIvdXRpbHMnO1xuaW1wb3J0IHsgVElQMjBfREVDSU1BTFMsIEFBX1RSQU5TQUNUSU9OX1RZUEUgfSBmcm9tICcuLi8uLi9zcmMvbGliL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBjb2lucyB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IHsgVHRlbXBvIH0gZnJvbSAnLi4vLi4vc3JjL3R0ZW1wbyc7XG5pbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1hcGknO1xuaW1wb3J0IHsgVGVzdEJpdEdvLCBUZXN0Qml0R29BUEkgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstdGVzdCc7XG5pbXBvcnQgeyBCaXRHb0Jhc2UgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQge1xuICBURVNUTkVUX1RPS0VOUyxcbiAgVFhfUEFSQU1TLFxuICBFUlJPUl9NRVNTQUdFUyxcbiAgU0lHTkFUVVJFX1RFU1RfREFUQSxcbiAgVEVTVF9SRUNJUElFTlRfQUREUkVTUyxcbn0gZnJvbSAnLi4vcmVzb3VyY2VzL3RlbXBvJztcblxuY29uc3QgbW9ja0NvaW5Db25maWcgPSBjb2lucy5nZXQoJ3R0ZW1wbycpO1xuXG5kZXNjcmliZSgnVElQLTIwIFV0aWxpdGllcycsICgpID0+IHtcbiAgZGVzY3JpYmUoJ2Ftb3VudFRvVGlwMjBVbml0cycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGNvbnZlcnQgZGVjaW1hbCBhbW91bnQgdG8gNi1kZWNpbWFsIHVuaXRzJywgKCkgPT4ge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGFtb3VudFRvVGlwMjBVbml0cygnMS41JyksIDE1MDAwMDBuKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChhbW91bnRUb1RpcDIwVW5pdHMoJzEwMCcpLCAxMDAwMDAwMDBuKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChhbW91bnRUb1RpcDIwVW5pdHMoJzAuMDAwMDAxJyksIDFuKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGludmFsaWQgYW1vdW50JywgKCkgPT4ge1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBhbW91bnRUb1RpcDIwVW5pdHMoJ2ludmFsaWQnKSwgL0ludmFsaWQgYW1vdW50IGZvcm1hdC8pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndGlwMjBVbml0c1RvQW1vdW50JywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgY29udmVydCA2LWRlY2ltYWwgdW5pdHMgdG8gaHVtYW4tcmVhZGFibGUgYW1vdW50JywgKCkgPT4ge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRpcDIwVW5pdHNUb0Ftb3VudCgxNTAwMDAwbiksICcxLjUnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0aXAyMFVuaXRzVG9BbW91bnQoMTAwMDAwMDAwbiksICcxMDAuMCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRpcDIwVW5pdHNUb0Ftb3VudCgxbiksICcwLjAwMDAwMScpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc3RyaW5nVG9CeXRlczMyJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgY29udmVydCBzdHJpbmcgdG8gYnl0ZXMzMicsICgpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHN0cmluZ1RvQnl0ZXMzMignMTIzNDUnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQubGVuZ3RoLCA2Nik7XG4gICAgICBhc3NlcnQub2socmVzdWx0LnN0YXJ0c1dpdGgoJzB4JykpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3Igc3RyaW5nIGxvbmdlciB0aGFuIDMyIGJ5dGVzJywgKCkgPT4ge1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBzdHJpbmdUb0J5dGVzMzIoJ2EnLnJlcGVhdCgzMykpLCAvTWVtbyB0b28gbG9uZy8pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZW5jb2RlVGlwMjBUcmFuc2ZlcldpdGhNZW1vJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZW5jb2RlIHRyYW5zZmVyV2l0aE1lbW8gY2FsbCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHRvID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoJzB4NzQyZDM1Y2M2NjM0YzA1MzI5MjVhM2I4NDRiYzllNzU5NWYwYmViMScpO1xuICAgICAgY29uc3QgZW5jb2RlZCA9IGVuY29kZVRpcDIwVHJhbnNmZXJXaXRoTWVtbyh0bywgMTUwMDAwMG4sICcxMjM0NScpO1xuICAgICAgYXNzZXJ0Lm9rKGVuY29kZWQuc3RhcnRzV2l0aCgnMHgnKSk7XG4gICAgICBhc3NlcnQub2soZW5jb2RlZC5sZW5ndGggPiAxMCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdpc1ZhbGlkVGlwMjBBbW91bnQnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSBhbW91bnRzIGNvcnJlY3RseScsICgpID0+IHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1ZhbGlkVGlwMjBBbW91bnQoJzEuNScpLCB0cnVlKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1ZhbGlkVGlwMjBBbW91bnQoJ2ludmFsaWQnKSwgZmFsc2UpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVmFsaWRUaXAyMEFtb3VudCgnLTUnKSwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnVElQLTIwIFRyYW5zYWN0aW9uIEJ1aWxkZXInLCAoKSA9PiB7XG4gIGNvbnN0IG1vY2tUb2tlbiA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKCcweDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAnKTtcbiAgY29uc3QgbW9ja1JlY2lwaWVudCA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKCcweDc0MmQzNWNjNjYzNGMwNTMyOTI1YTNiODQ0YmM5ZTc1OTVmMGJlYjEnKTtcbiAgY29uc3QgbW9ja0ZlZVRva2VuID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoJzB4YWJjZGVmYWJjZGVmYWJjZGVmYWJjZGVmYWJjZGVmYWJjZGVmYWJjZCcpO1xuXG4gIGRlc2NyaWJlKCdhZGRPcGVyYXRpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBhZGQgb3BlcmF0aW9uIHdpdGggYW5kIHdpdGhvdXQgbWVtbycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlci5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJyB9KTtcbiAgICAgIGJ1aWxkZXIuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzUwJywgbWVtbzogJzEnIH0pO1xuXG4gICAgICBjb25zdCBvcGVyYXRpb25zID0gYnVpbGRlci5nZXRPcGVyYXRpb25zKCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwob3BlcmF0aW9ucy5sZW5ndGgsIDIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG9wZXJhdGlvbnNbMF0ubWVtbywgdW5kZWZpbmVkKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvcGVyYXRpb25zWzFdLm1lbW8sICcxJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciBpbnZhbGlkIGFkZHJlc3NlcycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgKCkgPT4gYnVpbGRlci5hZGRPcGVyYXRpb24oeyB0b2tlbjogJzB4aW52YWxpZCcgYXMgYW55LCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJyB9KSxcbiAgICAgICAgL0ludmFsaWQgdG9rZW4gYWRkcmVzcy9cbiAgICAgICk7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiBidWlsZGVyLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiAnMHhpbnZhbGlkJyBhcyBhbnksIGFtb3VudDogJzEwMCcgfSksXG4gICAgICAgIC9JbnZhbGlkIHJlY2lwaWVudCBhZGRyZXNzL1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGludmFsaWQgYW1vdW50JywgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiBidWlsZGVyLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICdpbnZhbGlkLWFtb3VudCcgfSksXG4gICAgICAgIC9JbnZhbGlkIGFtb3VudC9cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciBpbnZhbGlkIChub24tbnVtZXJpYykgbWVtbycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgKCkgPT4gYnVpbGRlci5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJywgbWVtbzogJ0lOVi0wMDEnIH0pLFxuICAgICAgICAvSW52YWxpZCBtZW1vL1xuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2ZlZVRva2VuJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgc2V0IGFuZCBnZXQgZmVlIHRva2VuJywgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyLmZlZVRva2VuKG1vY2tGZWVUb2tlbik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYnVpbGRlci5nZXRGZWVUb2tlbigpLCBtb2NrRmVlVG9rZW4pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgaW52YWxpZCBmZWUgdG9rZW4gYWRkcmVzcycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBidWlsZGVyLmZlZVRva2VuKCdpbnZhbGlkLWFkZHJlc3MnKSwgL0ludmFsaWQgZmVlIHRva2VuIGFkZHJlc3MvKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1RyYW5zYWN0aW9uIHBhcmFtZXRlcnMnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBzZXQgbm9uY2UsIGdhcywgbWF4RmVlUGVyR2FzLCBhbmQgbWF4UHJpb3JpdHlGZWVQZXJHYXMnLCAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXIubm9uY2UoNDIpLmdhcyg1MDAwMDBuKS5tYXhGZWVQZXJHYXMoMTAwMDAwMDAwMG4pLm1heFByaW9yaXR5RmVlUGVyR2FzKDUwMDAwMDAwMG4pO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoKGJ1aWxkZXIgYXMgYW55KS5fbm9uY2UsIDQyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCgoYnVpbGRlciBhcyBhbnkpLl9nYXMsIDUwMDAwMG4pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKChidWlsZGVyIGFzIGFueSkuX21heEZlZVBlckdhcywgMTAwMDAwMDAwMG4pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKChidWlsZGVyIGFzIGFueSkuX21heFByaW9yaXR5RmVlUGVyR2FzLCA1MDAwMDAwMDBuKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGludmFsaWQgbm9uY2UgYW5kIGdhcycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBidWlsZGVyLm5vbmNlKC0xKSwgL0ludmFsaWQgbm9uY2UvKTtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gYnVpbGRlci5nYXMoMG4pLCAvSW52YWxpZCBnYXMgbGltaXQvKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ01ldGhvZCBjaGFpbmluZycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHN1cHBvcnQgZmx1ZW50IGludGVyZmFjZScsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMCcsIG1lbW86ICc1JyB9KVxuICAgICAgICAuZmVlVG9rZW4obW9ja0ZlZVRva2VuKVxuICAgICAgICAubm9uY2UoMTApXG4gICAgICAgIC5nYXMoNDAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcygyMDAwMDAwMDAwbilcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKDEwMDAwMDAwMDBuKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgYnVpbGRlcik7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdUSVAtMjAgQ29uc3RhbnRzJywgKCkgPT4ge1xuICBpdCgnc2hvdWxkIGhhdmUgY29ycmVjdCBkZWNpbWFsIHBsYWNlcycsICgpID0+IHtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoVElQMjBfREVDSU1BTFMsIDYpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnVElQLTIwIFRyYW5zYWN0aW9uIEJ1aWxkJywgKCkgPT4ge1xuICBjb25zdCBtb2NrVG9rZW4gPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcyhURVNUTkVUX1RPS0VOUy5hbHBoYVVTRC5hZGRyZXNzKTtcbiAgY29uc3QgbW9ja1JlY2lwaWVudCA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKFRFU1RfUkVDSVBJRU5UX0FERFJFU1MpO1xuICBjb25zdCBtb2NrRmVlVG9rZW4gPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcyhURVNUTkVUX1RPS0VOUy5iZXRhVVNELmFkZHJlc3MpO1xuXG4gIGRlc2NyaWJlKCdCdWlsZCBUcmFuc2FjdGlvbicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGJ1aWxkIHNpbmdsZS1vcGVyYXRpb24gdHJhbnNhY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAnLCBtZW1vOiAnMScgfSlcbiAgICAgICAgLmZlZVRva2VuKG1vY2tGZWVUb2tlbilcbiAgICAgICAgLm5vbmNlKDApXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG5cbiAgICAgIGFzc2VydC5vayh0eCBpbnN0YW5jZW9mIFRpcDIwVHJhbnNhY3Rpb24pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmdldE9wZXJhdGlvbkNvdW50KCksIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmdldEZlZVRva2VuKCksIG1vY2tGZWVUb2tlbik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGJhdGNoIHRyYW5zYWN0aW9uIHdpdGggbXVsdGlwbGUgb3BlcmF0aW9ucycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IFRFU1RORVRfVE9LRU5TLmFscGhhVVNELmFkZHJlc3MsIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMCcsIG1lbW86ICcxJyB9KVxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IFRFU1RORVRfVE9LRU5TLmJldGFVU0QuYWRkcmVzcywgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzIwJywgbWVtbzogJzInIH0pXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogVEVTVE5FVF9UT0tFTlMudGhldGFVU0QuYWRkcmVzcywgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzMwJywgbWVtbzogJzMnIH0pXG4gICAgICAgIC5mZWVUb2tlbihtb2NrRmVlVG9rZW4pXG4gICAgICAgIC5ub25jZSg0MilcbiAgICAgICAgLmdhcygzMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcblxuICAgICAgYXNzZXJ0Lm9rKHR4IGluc3RhbmNlb2YgVGlwMjBUcmFuc2FjdGlvbik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHguZ2V0T3BlcmF0aW9uQ291bnQoKSwgMyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHguaXNCYXRjaCgpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgdHJhbnNhY3Rpb24gd2l0aG91dCBmZWUgdG9rZW4nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICc1MCcgfSlcbiAgICAgICAgLm5vbmNlKDEpXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG5cbiAgICAgIGFzc2VydC5vayh0eCBpbnN0YW5jZW9mIFRpcDIwVHJhbnNhY3Rpb24pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmdldEZlZVRva2VuKCksIHVuZGVmaW5lZCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdCdWlsZCBWYWxpZGF0aW9uIEVycm9ycycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gbm8gb3BlcmF0aW9ucyBhZGRlZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlci5ub25jZSgwKS5nYXMoMTAwMDAwbikubWF4RmVlUGVyR2FzKDEwMDAwMDAwMDBuKS5tYXhQcmlvcml0eUZlZVBlckdhcyg1MDAwMDAwMDBuKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSwgL0F0IGxlYXN0IG9uZSBvcGVyYXRpb24gb3IgcmF3IGNhbGwgaXMgcmVxdWlyZWQvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBub25jZSBub3Qgc2V0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJyB9KVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoMTAwMDAwMDAwMG4pXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyg1MDAwMDAwMDBuKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSwgRVJST1JfTUVTU0FHRVMubWlzc2luZ05vbmNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBnYXMgbm90IHNldCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMCcgfSlcbiAgICAgICAgLm5vbmNlKDApXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoMTAwMDAwMDAwMG4pXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyg1MDAwMDAwMDBuKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSwgRVJST1JfTUVTU0FHRVMubWlzc2luZ0dhcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gbWF4RmVlUGVyR2FzIG5vdCBzZXQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAnIH0pXG4gICAgICAgIC5ub25jZSgwKVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyg1MDAwMDAwMDBuKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSwgRVJST1JfTUVTU0FHRVMubWlzc2luZ01heEZlZVBlckdhcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gbWF4UHJpb3JpdHlGZWVQZXJHYXMgbm90IHNldCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMCcgfSlcbiAgICAgICAgLm5vbmNlKDApXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcygxMDAwMDAwMDAwbik7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhhc3luYyAoKSA9PiBhd2FpdCBidWlsZGVyLmJ1aWxkKCksIEVSUk9SX01FU1NBR0VTLm1pc3NpbmdNYXhQcmlvcml0eUZlZVBlckdhcyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSb3VuZC1UcmlwOiBCdWlsZCAtPiBTZXJpYWxpemUgLT4gT3BlcmF0aW9ucyBDaGVjaycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHByZXNlcnZlIG9wZXJhdGlvbiBkYXRhIHRocm91Z2ggYnVpbGQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBvcGVyYXRpb25zID0gW3sgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEyMycsIG1lbW86ICcxJyB9XTtcblxuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24ob3BlcmF0aW9uc1swXSlcbiAgICAgICAgLmZlZVRva2VuKG1vY2tGZWVUb2tlbilcbiAgICAgICAgLm5vbmNlKDEwKVxuICAgICAgICAuZ2FzKDE1MDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoMjAwMDAwMDAwMG4pXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcygxMDAwMDAwMDAwbik7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IHR4T3BzID0gdHguZ2V0T3BlcmF0aW9ucygpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHhPcHMubGVuZ3RoLCAxKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eE9wc1swXS50b2tlbiwgb3BlcmF0aW9uc1swXS50b2tlbik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHhPcHNbMF0udG8sIG9wZXJhdGlvbnNbMF0udG8pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4T3BzWzBdLmFtb3VudCwgb3BlcmF0aW9uc1swXS5hbW91bnQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4T3BzWzBdLm1lbW8sIG9wZXJhdGlvbnNbMF0ubWVtbyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdCdWlsZCAtPiBTZXJpYWxpemUgLT4gU2lnbiBGbG93JywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgcHJvZHVjZSBzZXJpYWxpemFibGUgdW5zaWduZWQgdHJhbnNhY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICc1MCcsIG1lbW86ICcyJyB9KVxuICAgICAgICAuZmVlVG9rZW4obW9ja0ZlZVRva2VuKVxuICAgICAgICAubm9uY2UoNSlcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKDIwMDAwMDAwMDBuKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoMTAwMDAwMDAwMG4pO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCB1bnNpZ25lZEhleCA9IGF3YWl0IHR4LnNlcmlhbGl6ZSgpO1xuXG4gICAgICBhc3NlcnQub2sodW5zaWduZWRIZXguc3RhcnRzV2l0aChBQV9UUkFOU0FDVElPTl9UWVBFKSk7XG4gICAgICBhc3NlcnQub2soL14weFswLTlhLWZdKyQvaS50ZXN0KHVuc2lnbmVkSGV4KSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN1cHBvcnQgZnVsbCBzaWduIGFuZCBicm9hZGNhc3QgZmxvdycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzc1JywgbWVtbzogJzMnIH0pXG4gICAgICAgIC5mZWVUb2tlbihtb2NrRmVlVG9rZW4pXG4gICAgICAgIC5ub25jZSgxMjMpXG4gICAgICAgIC5nYXMoMTIwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcygyNTAwMDAwMDAwbilcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKDEyMDAwMDAwMDBuKTtcblxuICAgICAgY29uc3QgdHggPSAoYXdhaXQgYnVpbGRlci5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3QgdW5zaWduZWRIZXggPSBhd2FpdCB0eC5zZXJpYWxpemUoKTtcblxuICAgICAgdHguc2V0U2lnbmF0dXJlKFNJR05BVFVSRV9URVNUX0RBVEEudmFsaWRTaWduYXR1cmUpO1xuXG4gICAgICBjb25zdCBicm9hZGNhc3RIZXggPSBhd2FpdCB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgYXNzZXJ0Lm9rKGJyb2FkY2FzdEhleC5zdGFydHNXaXRoKEFBX1RSQU5TQUNUSU9OX1RZUEUpKTtcbiAgICAgIGFzc2VydC5vayhicm9hZGNhc3RIZXgubGVuZ3RoID4gdW5zaWduZWRIZXgubGVuZ3RoLCAnU2lnbmVkIHNob3VsZCBiZSBsb25nZXInKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1RyYW5zYWN0aW9uIEpTT04gUmVwcmVzZW50YXRpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGNvbnNpc3RlbnQgSlNPTiBmcm9tIGJ1aWx0IHRyYW5zYWN0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJywgbWVtbzogJzQnIH0pXG4gICAgICAgIC5mZWVUb2tlbihtb2NrRmVlVG9rZW4pXG4gICAgICAgIC5ub25jZSg1MClcbiAgICAgICAgLmdhcygyMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKDMwMDAwMDAwMDBuKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoMTUwMDAwMDAwMG4pO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBqc29uID0gdHgudG9Kc29uKCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChqc29uLnR5cGUsIEFBX1RSQU5TQUNUSU9OX1RZUEUpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb24ubm9uY2UsIDUwKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChqc29uLmdhcywgJzIwMDAwMCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb24ubWF4RmVlUGVyR2FzLCAnMzAwMDAwMDAwMCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb24ubWF4UHJpb3JpdHlGZWVQZXJHYXMsICcxNTAwMDAwMDAwJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoanNvbi5jYWxsQ291bnQsIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb24uZmVlVG9rZW4sIG1vY2tGZWVUb2tlbik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUcmFuc2FjdGlvbiBpZCBnZXR0ZXInLCAoKSA9PiB7XG4gICAgaXQoJ3Vuc2lnbmVkIGFuZCBzaWduZWQgdHJhbnNhY3Rpb25zIHNob3VsZCBoYXZlIGRpZmZlcmVudCBpZHMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMCcgfSlcbiAgICAgICAgLm5vbmNlKDEpXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCB1bnNpZ25lZElkID0gdHguaWQ7XG5cbiAgICAgIHR4LnNldFNpZ25hdHVyZShTSUdOQVRVUkVfVEVTVF9EQVRBLnZhbGlkU2lnbmF0dXJlKTtcbiAgICAgIGNvbnN0IHNpZ25lZElkID0gdHguaWQ7XG5cbiAgICAgIGFzc2VydC5ub3RTdHJpY3RFcXVhbCh1bnNpZ25lZElkLCBzaWduZWRJZCwgJ1NpZ25lZCBhbmQgdW5zaWduZWQgdHggc2hvdWxkIGhhdmUgZGlmZmVyZW50IGlkcycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnb3V0cHV0cyAvIGlucHV0cyBwb3B1bGF0aW9uJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZXhwb3NlIG91dHB1dHMgd2l0aCBiYXNlLXVuaXQgdmFsdWUgYW5kIHRva2VuIGFkZHJlc3MgYXMgY29pbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEuNScsIG1lbW86ICc3JyB9KVxuICAgICAgICAubm9uY2UoMClcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eC5vdXRwdXRzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHgub3V0cHV0c1swXS5hZGRyZXNzLCBtb2NrUmVjaXBpZW50KTtcbiAgICAgIC8vIDEuNSB0b2tlbnMgKiAxMF42ID0gMV81MDBfMDAwIGJhc2UgdW5pdHNcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eC5vdXRwdXRzWzBdLnZhbHVlLCAnMTUwMDAwMCcpO1xuICAgICAgLy8gY29pbiBpcyB0aGUgdG9rZW4gY29udHJhY3QgYWRkcmVzcywgbm90IHRoZSBjaGFpbiBuYW1lXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHgub3V0cHV0c1swXS5jb2luPy50b0xvd2VyQ2FzZSgpLCBtb2NrVG9rZW4udG9Mb3dlckNhc2UoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGV4cG9zZSBhIHNpbmdsZSBpbnB1dCB3aXRoIHRoZSB0b3RhbCBpbiBiYXNlIHVuaXRzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMS41JyB9KVxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzMuNScgfSlcbiAgICAgICAgLm5vbmNlKDApXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHguaW5wdXRzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHguaW5wdXRzWzBdLmFkZHJlc3MsICcnKTtcbiAgICAgIC8vICgxLjUgKyAzLjUpIHRva2VucyAqIDEwXjYgPSA1XzAwMF8wMDAgYmFzZSB1bml0c1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmlucHV0c1swXS52YWx1ZSwgJzUwMDAwMDAnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JvdW5kLVRyaXA6IEJ1aWxkIC0+IFNlcmlhbGl6ZSAtPiBGcm9tIChkZXNlcmlhbGl6YXRpb24pJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgcm91bmQtdHJpcCBhIHNpbmdsZS1vcGVyYXRpb24gdHJhbnNhY3Rpb24gd2l0aG91dCBhIHNpZ25hdHVyZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IG9wZXJhdGlvbiA9IHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzI1LjUnLCBtZW1vOiAnMTIzNDUnIH07XG5cbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKG9wZXJhdGlvbilcbiAgICAgICAgLmZlZVRva2VuKG1vY2tGZWVUb2tlbilcbiAgICAgICAgLm5vbmNlKDcpXG4gICAgICAgIC5nYXMoMTUwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCBvcmlnaW5hbFR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSBhd2FpdCBvcmlnaW5hbFR4LnNlcmlhbGl6ZSgpO1xuXG4gICAgICAvLyBEZXNlcmlhbGl6ZSB2aWEgZnJvbSgpXG4gICAgICBjb25zdCBidWlsZGVyMiA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyMi5mcm9tKHNlcmlhbGl6ZWQpO1xuICAgICAgY29uc3QgcmVzdG9yZWRUeCA9IChhd2FpdCBidWlsZGVyMi5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuXG4gICAgICBjb25zdCBvcHMgPSByZXN0b3JlZFR4LmdldE9wZXJhdGlvbnMoKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvcHMubGVuZ3RoLCAxKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvcHNbMF0udG9rZW4udG9Mb3dlckNhc2UoKSwgb3BlcmF0aW9uLnRva2VuLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG9wc1swXS50by50b0xvd2VyQ2FzZSgpLCBvcGVyYXRpb24udG8udG9Mb3dlckNhc2UoKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwob3BzWzBdLmFtb3VudCwgb3BlcmF0aW9uLmFtb3VudCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwob3BzWzBdLm1lbW8sIG9wZXJhdGlvbi5tZW1vKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN0b3JlZFR4LmdldEZlZVRva2VuKCk/LnRvTG93ZXJDYXNlKCksIG1vY2tGZWVUb2tlbi50b0xvd2VyQ2FzZSgpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcm91bmQtdHJpcCBhIGJhdGNoIHRyYW5zYWN0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gVXNlIGFtb3VudHMgdGhhdCBtYXRjaCB0aXAyMFVuaXRzVG9BbW91bnQgb3V0cHV0OiBldGhlcnMgZm9ybWF0VW5pdHMgYWx3YXlzIGluY2x1ZGVzIGRlY2ltYWxcbiAgICAgIGNvbnN0IG9wZXJhdGlvbnMgPSBbXG4gICAgICAgIHsgdG9rZW46IFRFU1RORVRfVE9LRU5TLmFscGhhVVNELmFkZHJlc3MsIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMC4wJywgbWVtbzogJzEnIH0sXG4gICAgICAgIHsgdG9rZW46IFRFU1RORVRfVE9LRU5TLmJldGFVU0QuYWRkcmVzcywgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzIwLjAnLCBtZW1vOiAnMicgfSxcbiAgICAgIF07XG5cbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKG9wZXJhdGlvbnNbMF0pXG4gICAgICAgIC5hZGRPcGVyYXRpb24ob3BlcmF0aW9uc1sxXSlcbiAgICAgICAgLm5vbmNlKDQyKVxuICAgICAgICAuZ2FzKDI1MDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMpXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcblxuICAgICAgY29uc3Qgb3JpZ2luYWxUeCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBzZXJpYWxpemVkID0gYXdhaXQgb3JpZ2luYWxUeC5zZXJpYWxpemUoKTtcblxuICAgICAgY29uc3QgYnVpbGRlcjIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlcjIuZnJvbShzZXJpYWxpemVkKTtcbiAgICAgIGNvbnN0IHJlc3RvcmVkVHggPSAoYXdhaXQgYnVpbGRlcjIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3RvcmVkVHguZ2V0T3BlcmF0aW9uQ291bnQoKSwgMik7XG4gICAgICBhc3NlcnQub2socmVzdG9yZWRUeC5pc0JhdGNoKCkpO1xuXG4gICAgICBjb25zdCBqc29uID0gcmVzdG9yZWRUeC50b0pzb24oKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChqc29uLm5vbmNlLCA0Mik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoanNvbi5nYXMsICcyNTAwMDAnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChqc29uLm1heEZlZVBlckdhcywgVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMudG9TdHJpbmcoKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoanNvbi5tYXhQcmlvcml0eUZlZVBlckdhcywgVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcy50b1N0cmluZygpKTtcblxuICAgICAgY29uc3Qgb3BzID0gcmVzdG9yZWRUeC5nZXRPcGVyYXRpb25zKCk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9wZXJhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG9wc1tpXS50b2tlbi50b0xvd2VyQ2FzZSgpLCBvcGVyYXRpb25zW2ldLnRva2VuLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwob3BzW2ldLnRvLnRvTG93ZXJDYXNlKCksIG1vY2tSZWNpcGllbnQudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvcHNbaV0uYW1vdW50LCBvcGVyYXRpb25zW2ldLmFtb3VudCk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvcHNbaV0ubWVtbywgb3BlcmF0aW9uc1tpXS5tZW1vKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcm91bmQtdHJpcCBhIHNpZ25lZCB0cmFuc2FjdGlvbiBhbmQgcHJlc2VydmUgdGhlIHNpZ25hdHVyZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzUnIH0pXG4gICAgICAgIC5ub25jZSg5OSlcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIHR4LnNldFNpZ25hdHVyZShTSUdOQVRVUkVfVEVTVF9EQVRBLnZhbGlkU2lnbmF0dXJlKTtcbiAgICAgIGNvbnN0IHNpZ25lZEhleCA9IGF3YWl0IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIC8vIERlc2VyaWFsaXplIHRoZSBzaWduZWQgdHJhbnNhY3Rpb25cbiAgICAgIGNvbnN0IGJ1aWxkZXIyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXIyLmZyb20oc2lnbmVkSGV4KTtcbiAgICAgIGNvbnN0IHJlc3RvcmVkVHggPSAoYXdhaXQgYnVpbGRlcjIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcblxuICAgICAgY29uc3Qgc2lnID0gcmVzdG9yZWRUeC5nZXRTaWduYXR1cmUoKTtcbiAgICAgIGFzc2VydC5vayhzaWcgIT09IHVuZGVmaW5lZCwgJ1NpZ25hdHVyZSBzaG91bGQgYmUgcHJlc2VydmVkJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2lnIS55UGFyaXR5LCBTSUdOQVRVUkVfVEVTVF9EQVRBLnZhbGlkU2lnbmF0dXJlLnlQYXJpdHkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIHRoZSBzYW1lIHR4IGlkIGFmdGVyIGEgc2VyaWFsaXphdGlvbiByb3VuZC10cmlwJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwLjAnLCBtZW1vOiAnOTknIH0pXG4gICAgICAgIC5ub25jZSgzKVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMpXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcblxuICAgICAgY29uc3Qgb3JpZ2luYWxUeCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBzZXJpYWxpemVkID0gYXdhaXQgb3JpZ2luYWxUeC5zZXJpYWxpemUoKTtcbiAgICAgIGNvbnN0IG9yaWdpbmFsSWQgPSBvcmlnaW5hbFR4LmlkO1xuXG4gICAgICBjb25zdCBidWlsZGVyMiA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyMi5mcm9tKHNlcmlhbGl6ZWQpO1xuICAgICAgY29uc3QgcmVzdG9yZWRUeCA9IChhd2FpdCBidWlsZGVyMi5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRUeC5pZCwgb3JpZ2luYWxJZCk7XG5cbiAgICAgIGNvbnN0IG9yaWdpbmFsSnNvbiA9IG9yaWdpbmFsVHgudG9Kc29uKCk7XG4gICAgICBjb25zdCByZXN0b3JlZEpzb24gPSByZXN0b3JlZFR4LnRvSnNvbigpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3RvcmVkSnNvbi5ub25jZSwgb3JpZ2luYWxKc29uLm5vbmNlKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN0b3JlZEpzb24uZ2FzLCBvcmlnaW5hbEpzb24uZ2FzKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN0b3JlZEpzb24ubWF4RmVlUGVyR2FzLCBvcmlnaW5hbEpzb24ubWF4RmVlUGVyR2FzKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN0b3JlZEpzb24ubWF4UHJpb3JpdHlGZWVQZXJHYXMsIG9yaWdpbmFsSnNvbi5tYXhQcmlvcml0eUZlZVBlckdhcyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRKc29uLmZlZVRva2VuLCBvcmlnaW5hbEpzb24uZmVlVG9rZW4pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3RvcmVkSnNvbi5jYWxsQ291bnQsIG9yaWdpbmFsSnNvbi5jYWxsQ291bnQpO1xuXG4gICAgICBjb25zdCBvcmlnaW5hbE9wcyA9IG9yaWdpbmFsVHguZ2V0T3BlcmF0aW9ucygpO1xuICAgICAgY29uc3QgcmVzdG9yZWRPcHMgPSByZXN0b3JlZFR4LmdldE9wZXJhdGlvbnMoKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN0b3JlZE9wcy5sZW5ndGgsIG9yaWdpbmFsT3BzLmxlbmd0aCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRPcHNbMF0udG9rZW4udG9Mb3dlckNhc2UoKSwgb3JpZ2luYWxPcHNbMF0udG9rZW4udG9Mb3dlckNhc2UoKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRPcHNbMF0udG8udG9Mb3dlckNhc2UoKSwgb3JpZ2luYWxPcHNbMF0udG8udG9Mb3dlckNhc2UoKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRPcHNbMF0uYW1vdW50LCBvcmlnaW5hbE9wc1swXS5hbW91bnQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3RvcmVkT3BzWzBdLm1lbW8sIG9yaWdpbmFsT3BzWzBdLm1lbW8pO1xuXG4gICAgICBjb25zdCByZXN0b3JlZFNlcmlhbGl6ZWQgPSBhd2FpdCByZXN0b3JlZFR4LnNlcmlhbGl6ZSgpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3RvcmVkU2VyaWFsaXplZCwgc2VyaWFsaXplZCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdUZW1wbyBjb2luIC0gcGFyc2VUcmFuc2FjdGlvbiAvIHZlcmlmeVRyYW5zYWN0aW9uJywgKCkgPT4ge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGNvaW46IGFueTtcblxuICBjb25zdCBtb2NrVG9rZW4gPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcyhURVNUTkVUX1RPS0VOUy5hbHBoYVVTRC5hZGRyZXNzKTtcbiAgY29uc3QgbW9ja1JlY2lwaWVudCA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKFRFU1RfUkVDSVBJRU5UX0FERFJFU1MpO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAnbW9jaycgfSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0dGVtcG8nLCAoYmc6IEJpdEdvQmFzZSkgPT4ge1xuICAgICAgY29uc3QgbW9ja1N0YXRpY3NDb2luID0ge1xuICAgICAgICBuYW1lOiAndHRlbXBvJyxcbiAgICAgICAgZnVsbE5hbWU6ICdUZXN0bmV0IFRlbXBvJyxcbiAgICAgICAgbmV0d29yazogeyB0eXBlOiAndGVzdG5ldCcgfSxcbiAgICAgICAgZmVhdHVyZXM6IFtdLFxuICAgICAgfSBhcyBhbnk7XG4gICAgICByZXR1cm4gVHRlbXBvLmNyZWF0ZUluc3RhbmNlKGJnLCBtb2NrU3RhdGljc0NvaW4pO1xuICAgIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIGNvaW4gPSBiaXRnby5jb2luKCd0dGVtcG8nKTtcbiAgfSk7XG5cbiAgYXN5bmMgZnVuY3Rpb24gYnVpbGRTZXJpYWxpemVkVHgoXG4gICAgb3BlcmF0aW9uczogeyB0b2tlbjogc3RyaW5nOyB0bzogc3RyaW5nOyBhbW91bnQ6IHN0cmluZzsgbWVtbz86IHN0cmluZyB9W10sXG4gICAgbm9uY2UgPSAwXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihjb2lucy5nZXQoJ3R0ZW1wbycpKTtcbiAgICBmb3IgKGNvbnN0IG9wIG9mIG9wZXJhdGlvbnMpIHtcbiAgICAgIGJ1aWxkZXIuYWRkT3BlcmF0aW9uKG9wKTtcbiAgICB9XG4gICAgYnVpbGRlclxuICAgICAgLm5vbmNlKG5vbmNlKVxuICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcbiAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgcmV0dXJuIHR4LnNlcmlhbGl6ZSgpO1xuICB9XG5cbiAgZGVzY3JpYmUoJ3BhcnNlVHJhbnNhY3Rpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBhIHNpbmdsZS1vcGVyYXRpb24gdHJhbnNhY3Rpb24gaW50byBvdXRwdXRzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZFNlcmlhbGl6ZWRUeChbeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnNTAnLCBtZW1vOiAnMScgfV0pO1xuICAgICAgY29uc3QgcGFyc2VkID0gYXdhaXQgY29pbi5wYXJzZVRyYW5zYWN0aW9uKHsgdHhIZXggfSk7XG4gICAgICBhc3NlcnQub2soQXJyYXkuaXNBcnJheShwYXJzZWQub3V0cHV0cyksICdvdXRwdXRzIHNob3VsZCBiZSBhbiBhcnJheScpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5vdXRwdXRzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLm91dHB1dHNbMF0uYWRkcmVzcy50b0xvd2VyQ2FzZSgpLCBtb2NrUmVjaXBpZW50LnRvTG93ZXJDYXNlKCkpO1xuICAgICAgLy8gNTAgdG9rZW5zICogMTBeNiA9IDUwXzAwMF8wMDAgYmFzZSB1bml0c1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5vdXRwdXRzWzBdLmFtb3VudCwgJzUwMDAwMDAwJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBlbXB0eSBvYmplY3Qgd2hlbiBubyB0eEhleCBpcyBwcm92aWRlZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IGF3YWl0IGNvaW4ucGFyc2VUcmFuc2FjdGlvbih7fSk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBhcnNlZCwge30pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndmVyaWZ5VHJhbnNhY3Rpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSB3aGVuIG5vIHJlY2lwaWVudHMgYXJlIHNwZWNpZmllZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRTZXJpYWxpemVkVHgoW3sgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwJyB9XSk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9LFxuICAgICAgICB0eFBhcmFtczoge30sXG4gICAgICB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSB3aGVuIHJlY2lwaWVudHMgbWF0Y2ggb3BlcmF0aW9ucycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRTZXJpYWxpemVkVHgoW3sgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMCcgfV0pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAwMDAwMDAnIH1dLCAvLyAxMDAgKiAxMF42IGJhc2UgdW5pdHNcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gcmVjaXBpZW50IGFkZHJlc3MgZG9lcyBub3QgbWF0Y2gnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkU2VyaWFsaXplZFR4KFt7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAnIH1dKTtcbiAgICAgIGNvbnN0IHdyb25nQWRkcmVzcyA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKCcweDExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEnKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAoKSA9PlxuICAgICAgICAgIGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9LFxuICAgICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogd3JvbmdBZGRyZXNzLCBhbW91bnQ6ICcxMDAwMDAwMDAnIH1dIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgIC9yZWNpcGllbnQgbWlzbWF0Y2gvXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIHJlY2lwaWVudCBhbW91bnQgZG9lcyBub3QgbWF0Y2gnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkU2VyaWFsaXplZFR4KFt7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAnIH1dKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAoKSA9PlxuICAgICAgICAgIGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9LFxuICAgICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnOTk5JyB9XSB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICAvYW1vdW50IG1pc21hdGNoL1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBvcGVyYXRpb24gY291bnQgZGlmZmVycyBmcm9tIHJlY2lwaWVudCBjb3VudCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRTZXJpYWxpemVkVHgoW3sgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwJyB9XSk7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICAgICAgICB7IGFkZHJlc3M6IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMDAwMDAwJyB9LFxuICAgICAgICAgICAgICAgIHsgYWRkcmVzczogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwMDAwMDAnIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICAvb3BlcmF0aW9uXFwoc1xcKS9cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIHdoZW4gbm8gdHhIZXggaXMgcHJvdmlkZWQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQcmVidWlsZDoge30sIHR4UGFyYW1zOiB7fSB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHRydWUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndmVyaWZ5VHJhbnNhY3Rpb24gd2l0aCBmZWVUb2tlbicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHZlcmlmeSB0cmFuc2FjdGlvbiB3aXRoIG1hdGNoaW5nIGZlZSB0b2tlbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZlZVRva2VuID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoVEVTVE5FVF9UT0tFTlMuYmV0YVVTRC5hZGRyZXNzKTtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIoY29pbnMuZ2V0KCd0dGVtcG8nKSk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJyB9KVxuICAgICAgICAuZmVlVG9rZW4oZmVlVG9rZW4pXG4gICAgICAgIC5ub25jZSgwKVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMpXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgdHguc2VyaWFsaXplKCk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0sXG4gICAgICAgIHR4UGFyYW1zOiB7IGZlZVRva2VuOiBmZWVUb2tlbiB9LFxuICAgICAgfSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBmZWUgdG9rZW4gZG9lcyBub3QgbWF0Y2gnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBmZWVUb2tlbiA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKFRFU1RORVRfVE9LRU5TLmJldGFVU0QuYWRkcmVzcyk7XG4gICAgICBjb25zdCB3cm9uZ0ZlZVRva2VuID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoVEVTVE5FVF9UT0tFTlMuYWxwaGFVU0QuYWRkcmVzcyk7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKGNvaW5zLmdldCgndHRlbXBvJykpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMCcgfSlcbiAgICAgICAgLmZlZVRva2VuKGZlZVRva2VuKVxuICAgICAgICAubm9uY2UoMClcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IHR4LnNlcmlhbGl6ZSgpO1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgICAgIHR4UGFyYW1zOiB7IGZlZVRva2VuOiB3cm9uZ0ZlZVRva2VuIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgIC9GZWUgdG9rZW4gbWlzbWF0Y2gvXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGZlZSB0b2tlbiBpcyBleHBlY3RlZCBidXQgdHJhbnNhY3Rpb24gaGFzIG5vbmUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBleHBlY3RlZEZlZVRva2VuID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoVEVTVE5FVF9UT0tFTlMuYmV0YVVTRC5hZGRyZXNzKTtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIoY29pbnMuZ2V0KCd0dGVtcG8nKSk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJyB9KVxuICAgICAgICAubm9uY2UoMClcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IHR4LnNlcmlhbGl6ZSgpO1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgICAgIHR4UGFyYW1zOiB7IGZlZVRva2VuOiBleHBlY3RlZEZlZVRva2VuIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgIC9GZWUgdG9rZW4gbWlzbWF0Y2gvXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwYXNzIHZlcmlmaWNhdGlvbiB3aGVuIG5vIGZlZSB0b2tlbiBpcyBzcGVjaWZpZWQgaW4gcGFyYW1zJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZmVlVG9rZW4gPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcyhURVNUTkVUX1RPS0VOUy5iZXRhVVNELmFkZHJlc3MpO1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihjb2lucy5nZXQoJ3R0ZW1wbycpKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAnIH0pXG4gICAgICAgIC5mZWVUb2tlbihmZWVUb2tlbilcbiAgICAgICAgLm5vbmNlKDApXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuICAgICAgY29uc3QgdHggPSAoYXdhaXQgYnVpbGRlci5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCB0eC5zZXJpYWxpemUoKTtcblxuICAgICAgLy8gTm8gZmVlVG9rZW4gaW4gdHhQYXJhbXMgLSBzaG91bGQgbm90IHZlcmlmeSwganVzdCBwYXNzXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9LFxuICAgICAgICB0eFBhcmFtczoge30sXG4gICAgICB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHRydWUpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnUmF3IENvbnRyYWN0IENhbGwgQnVpbGRlcicsICgpID0+IHtcbiAgY29uc3QgbW9ja0NvbnRyYWN0ID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoJzB4ZGVhZGJlZWZkZWFkYmVlZmRlYWRiZWVmZGVhZGJlZWZkZWFkYmVlZicpO1xuICBjb25zdCBtb2NrQ2FsbGRhdGEgPVxuICAgICcweGE5MDU5Y2JiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNzQyZDM1Y2M2NjM0YzA1MzI5MjVhM2I4NDRiYzQ1NGU0NDM4ZjQ0ZTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA5ODk2ODAnO1xuXG4gIGRlc2NyaWJlKCdhZGRSYXdDYWxsJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgYWRkIGEgcmF3IGNhbGwgYW5kIHJldHVybiBpdCB2aWEgZ2V0UmF3Q2FsbHMoKScsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlci5hZGRSYXdDYWxsKHsgdG86IG1vY2tDb250cmFjdCwgZGF0YTogbW9ja0NhbGxkYXRhIH0pO1xuXG4gICAgICBjb25zdCByYXdDYWxscyA9IGJ1aWxkZXIuZ2V0UmF3Q2FsbHMoKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyYXdDYWxscy5sZW5ndGgsIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJhd0NhbGxzWzBdLnRvLCBtb2NrQ29udHJhY3QpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJhd0NhbGxzWzBdLmRhdGEsIG1vY2tDYWxsZGF0YSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN1cHBvcnQgY2hhaW5pbmcgYWRkUmF3Q2FsbCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYnVpbGRlci5hZGRSYXdDYWxsKHsgdG86IG1vY2tDb250cmFjdCwgZGF0YTogbW9ja0NhbGxkYXRhIH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgYnVpbGRlcik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBpbnZhbGlkIGNvbnRyYWN0IGFkZHJlc3MnLCAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gYnVpbGRlci5hZGRSYXdDYWxsKHsgdG86ICcweGludmFsaWQnLCBkYXRhOiBtb2NrQ2FsbGRhdGEgfSksIC9JbnZhbGlkIGNvbnRyYWN0IGFkZHJlc3MvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIGVtcHR5IGNhbGxkYXRhJywgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IGJ1aWxkZXIuYWRkUmF3Q2FsbCh7IHRvOiBtb2NrQ29udHJhY3QsIGRhdGE6ICcweCcgfSksIC9JbnZhbGlkIGNhbGxkYXRhLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBub24taGV4IGNhbGxkYXRhJywgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IGJ1aWxkZXIuYWRkUmF3Q2FsbCh7IHRvOiBtb2NrQ29udHJhY3QsIGRhdGE6ICdub3QtaGV4LWRhdGEnIH0pLCAvSW52YWxpZCBjYWxsZGF0YS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgY2FsbGRhdGEgbWlzc2luZyAweCBwcmVmaXgnLCAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gYnVpbGRlci5hZGRSYXdDYWxsKHsgdG86IG1vY2tDb250cmFjdCwgZGF0YTogJ2E5MDU5Y2JiJyB9KSwgL0ludmFsaWQgY2FsbGRhdGEvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIG9kZC1sZW5ndGggaGV4IGNhbGxkYXRhJywgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IGJ1aWxkZXIuYWRkUmF3Q2FsbCh7IHRvOiBtb2NrQ29udHJhY3QsIGRhdGE6ICcweGFiYycgfSksIC9JbnZhbGlkIGNhbGxkYXRhLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBpbnZhbGlkIHZhbHVlIHN0cmluZycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBidWlsZGVyLmFkZFJhd0NhbGwoeyB0bzogbW9ja0NvbnRyYWN0LCBkYXRhOiBtb2NrQ2FsbGRhdGEsIHZhbHVlOiAnMWUxOCcgfSksIC9JbnZhbGlkIHZhbHVlLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBuZWdhdGl2ZSB2YWx1ZScsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBidWlsZGVyLmFkZFJhd0NhbGwoeyB0bzogbW9ja0NvbnRyYWN0LCBkYXRhOiBtb2NrQ2FsbGRhdGEsIHZhbHVlOiAnLTEnIH0pLCAvSW52YWxpZCB2YWx1ZS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBhbGxvdyByYXctY2FsbC1vbmx5IHRyYW5zYWN0aW9uIChubyBvcGVyYXRpb25zKScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkUmF3Q2FsbCh7IHRvOiBtb2NrQ29udHJhY3QsIGRhdGE6IG1vY2tDYWxsZGF0YSB9KVxuICAgICAgICAubm9uY2UoMClcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGFzc2VydC5vayh0eCBpbnN0YW5jZW9mIFRpcDIwVHJhbnNhY3Rpb24pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmdldE9wZXJhdGlvbnMoKS5sZW5ndGgsIDApO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmdldFJhd0NhbGxzKCkubGVuZ3RoLCAxKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eC5nZXRPcGVyYXRpb25Db3VudCgpLCAxKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JvdW5kLVRyaXA6IEJ1aWxkIC0+IFNlcmlhbGl6ZSAtPiBGcm9tIChyYXcgY2FsbCBkZXNlcmlhbGl6YXRpb24pJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgcHJlc2VydmUgcmF3IGNhbGwgY2FsbGRhdGEgdGhyb3VnaCBhIHJvdW5kLXRyaXAnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZFJhd0NhbGwoeyB0bzogbW9ja0NvbnRyYWN0LCBkYXRhOiBtb2NrQ2FsbGRhdGEgfSlcbiAgICAgICAgLm5vbmNlKDUpXG4gICAgICAgIC5nYXMoMTUwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCBvcmlnaW5hbFR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSBhd2FpdCBvcmlnaW5hbFR4LnNlcmlhbGl6ZSgpO1xuXG4gICAgICBjb25zdCBidWlsZGVyMiA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyMi5mcm9tKHNlcmlhbGl6ZWQpO1xuICAgICAgY29uc3QgcmVzdG9yZWRUeCA9IChhd2FpdCBidWlsZGVyMi5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRUeC5nZXRPcGVyYXRpb25zKCkubGVuZ3RoLCAwKTtcbiAgICAgIGNvbnN0IHJhd0NhbGxzID0gcmVzdG9yZWRUeC5nZXRSYXdDYWxscygpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJhd0NhbGxzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmF3Q2FsbHNbMF0udG8udG9Mb3dlckNhc2UoKSwgbW9ja0NvbnRyYWN0LnRvTG93ZXJDYXNlKCkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJhd0NhbGxzWzBdLmRhdGEudG9Mb3dlckNhc2UoKSwgbW9ja0NhbGxkYXRhLnRvTG93ZXJDYXNlKCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcmVzZXJ2ZSBjYWxsZGF0YSB0aHJvdWdoIGEgc2lnbmVkIHJvdW5kLXRyaXAnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZFJhd0NhbGwoeyB0bzogbW9ja0NvbnRyYWN0LCBkYXRhOiBtb2NrQ2FsbGRhdGEgfSlcbiAgICAgICAgLm5vbmNlKDcpXG4gICAgICAgIC5nYXMoMTIwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICB0eC5zZXRTaWduYXR1cmUoU0lHTkFUVVJFX1RFU1RfREFUQS52YWxpZFNpZ25hdHVyZSk7XG4gICAgICBjb25zdCBzaWduZWRIZXggPSBhd2FpdCB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgICBjb25zdCBidWlsZGVyMiA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyMi5mcm9tKHNpZ25lZEhleCk7XG4gICAgICBjb25zdCByZXN0b3JlZFR4ID0gKGF3YWl0IGJ1aWxkZXIyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG5cbiAgICAgIGNvbnN0IHJhd0NhbGxzID0gcmVzdG9yZWRUeC5nZXRSYXdDYWxscygpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJhd0NhbGxzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmF3Q2FsbHNbMF0uZGF0YS50b0xvd2VyQ2FzZSgpLCBtb2NrQ2FsbGRhdGEudG9Mb3dlckNhc2UoKSk7XG4gICAgICBjb25zdCBzaWcgPSByZXN0b3JlZFR4LmdldFNpZ25hdHVyZSgpO1xuICAgICAgYXNzZXJ0Lm9rKHNpZyAhPT0gdW5kZWZpbmVkKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaWchLnlQYXJpdHksIFNJR05BVFVSRV9URVNUX0RBVEEudmFsaWRTaWduYXR1cmUueVBhcml0eSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHByZXNlcnZlIHJhdyBjYWxsIHR4IGlkIHRocm91Z2ggYSByb3VuZC10cmlwJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRSYXdDYWxsKHsgdG86IG1vY2tDb250cmFjdCwgZGF0YTogbW9ja0NhbGxkYXRhIH0pXG4gICAgICAgIC5ub25jZSgzKVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMpXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcblxuICAgICAgY29uc3Qgb3JpZ2luYWxUeCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBzZXJpYWxpemVkID0gYXdhaXQgb3JpZ2luYWxUeC5zZXJpYWxpemUoKTtcbiAgICAgIGNvbnN0IG9yaWdpbmFsSWQgPSBvcmlnaW5hbFR4LmlkO1xuXG4gICAgICBjb25zdCBidWlsZGVyMiA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyMi5mcm9tKHNlcmlhbGl6ZWQpO1xuICAgICAgY29uc3QgcmVzdG9yZWRUeCA9IChhd2FpdCBidWlsZGVyMi5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRUeC5pZCwgb3JpZ2luYWxJZCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSYXcgY2FsbCB0b0pzb24gYW5kIG91dHB1dHMnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBleHBvc2UgcmF3IGNhbGwgY29udHJhY3QgYWRkcmVzcyBhcyBvdXRwdXQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZFJhd0NhbGwoeyB0bzogbW9ja0NvbnRyYWN0LCBkYXRhOiBtb2NrQ2FsbGRhdGEsIHZhbHVlOiAnMCcgfSlcbiAgICAgICAgLm5vbmNlKDIpXG4gICAgICAgIC5nYXMoMjAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHgub3V0cHV0cy5sZW5ndGgsIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4Lm91dHB1dHNbMF0uYWRkcmVzcy50b0xvd2VyQ2FzZSgpLCBtb2NrQ29udHJhY3QudG9Mb3dlckNhc2UoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGluY2x1ZGUgcmF3Q2FsbHMgaW4gdG9Kc29uKCkgb3V0cHV0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRSYXdDYWxsKHsgdG86IG1vY2tDb250cmFjdCwgZGF0YTogbW9ja0NhbGxkYXRhIH0pXG4gICAgICAgIC5ub25jZSgwKVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMpXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcblxuICAgICAgY29uc3QgdHggPSAoYXdhaXQgYnVpbGRlci5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3QganNvbiA9IHR4LnRvSnNvbigpO1xuXG4gICAgICBhc3NlcnQub2soQXJyYXkuaXNBcnJheShqc29uLnJhd0NhbGxzKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoanNvbi5yYXdDYWxscy5sZW5ndGgsIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb24ucmF3Q2FsbHNbMF0udG8sIG1vY2tDb250cmFjdCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoanNvbi5yYXdDYWxsc1swXS5kYXRhLCBtb2NrQ2FsbGRhdGEpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnVGVtcG8gY29pbiAtIHZlcmlmeVRyYW5zYWN0aW9uIHdpdGggcmF3IGNhbGxzJywgKCkgPT4ge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGNvaW46IGFueTtcblxuICBjb25zdCBtb2NrQ29udHJhY3QgPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcygnMHhkZWFkYmVlZmRlYWRiZWVmZGVhZGJlZWZkZWFkYmVlZmRlYWRiZWVmJyk7XG4gIGNvbnN0IG1vY2tDYWxsZGF0YSA9XG4gICAgJzB4YTkwNTljYmIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA3NDJkMzVjYzY2MzRjMDUzMjkyNWEzYjg0NGJjNDU0ZTQ0MzhmNDRlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDk4OTY4MCc7XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBiaXRnby5zYWZlUmVnaXN0ZXIoJ3R0ZW1wbycsIChiZzogQml0R29CYXNlKSA9PiB7XG4gICAgICBjb25zdCBtb2NrU3RhdGljc0NvaW4gPSB7XG4gICAgICAgIG5hbWU6ICd0dGVtcG8nLFxuICAgICAgICBmdWxsTmFtZTogJ1Rlc3RuZXQgVGVtcG8nLFxuICAgICAgICBuZXR3b3JrOiB7IHR5cGU6ICd0ZXN0bmV0JyB9LFxuICAgICAgICBmZWF0dXJlczogW10sXG4gICAgICB9IGFzIGFueTtcbiAgICAgIHJldHVybiBUdGVtcG8uY3JlYXRlSW5zdGFuY2UoYmcsIG1vY2tTdGF0aWNzQ29pbik7XG4gICAgfSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgY29pbiA9IGJpdGdvLmNvaW4oJ3R0ZW1wbycpO1xuICB9KTtcblxuICBhc3luYyBmdW5jdGlvbiBidWlsZFJhd0NhbGxUeChjb250cmFjdDogc3RyaW5nLCBjYWxsZGF0YTogc3RyaW5nLCBub25jZSA9IDApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIoY29pbnMuZ2V0KCd0dGVtcG8nKSk7XG4gICAgYnVpbGRlclxuICAgICAgLmFkZFJhd0NhbGwoeyB0bzogY29udHJhY3QsIGRhdGE6IGNhbGxkYXRhIH0pXG4gICAgICAubm9uY2Uobm9uY2UpXG4gICAgICAuZ2FzKDE1MDAwMG4pXG4gICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICByZXR1cm4gdHguc2VyaWFsaXplKCk7XG4gIH1cblxuICBpdCgnc2hvdWxkIHZlcmlmeSBhIHJhdyBjYWxsIHRyYW5zYWN0aW9uIHdoZW4gcmVjaXBpZW50IGRhdGEgbWF0Y2hlcycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkUmF3Q2FsbFR4KG1vY2tDb250cmFjdCwgbW9ja0NhbGxkYXRhKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IG1vY2tDb250cmFjdCwgYW1vdW50OiAnMCcsIGRhdGE6IG1vY2tDYWxsZGF0YSB9XSxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgdHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdGhyb3cgd2hlbiByYXcgY2FsbCBhZGRyZXNzIGRvZXMgbm90IG1hdGNoIHJlY2lwaWVudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkUmF3Q2FsbFR4KG1vY2tDb250cmFjdCwgbW9ja0NhbGxkYXRhKTtcbiAgICBjb25zdCB3cm9uZ0FkZHJlc3MgPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcygnMHgxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExJyk7XG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAoKSA9PlxuICAgICAgICBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0sXG4gICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogd3JvbmdBZGRyZXNzLCBhbW91bnQ6ICcwJywgZGF0YTogbW9ja0NhbGxkYXRhIH1dIH0sXG4gICAgICAgIH0pLFxuICAgICAgL2FkZHJlc3MgbWlzbWF0Y2gvXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIHJhdyBjYWxsIGNhbGxkYXRhIGRvZXMgbm90IG1hdGNoJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRSYXdDYWxsVHgobW9ja0NvbnRyYWN0LCBtb2NrQ2FsbGRhdGEpO1xuICAgIGNvbnN0IHdyb25nQ2FsbGRhdGEgPSAnMHhkZWFkYmVlZjAxMDIwMzA0JztcbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+XG4gICAgICAgIGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgICB0eFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBtb2NrQ29udHJhY3QsIGFtb3VudDogJzAnLCBkYXRhOiB3cm9uZ0NhbGxkYXRhIH1dIH0sXG4gICAgICAgIH0pLFxuICAgICAgL2NhbGxkYXRhIG1pc21hdGNoL1xuICAgICk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdGhyb3cgd2hlbiByZWNpcGllbnQgY291bnQgZG9lcyBub3QgbWF0Y2ggY2FsbCBjb3VudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkUmF3Q2FsbFR4KG1vY2tDb250cmFjdCwgbW9ja0NhbGxkYXRhKTtcbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+XG4gICAgICAgIGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAgICB7IGFkZHJlc3M6IG1vY2tDb250cmFjdCwgYW1vdW50OiAnMCcsIGRhdGE6IG1vY2tDYWxsZGF0YSB9LFxuICAgICAgICAgICAgICB7IGFkZHJlc3M6IG1vY2tDb250cmFjdCwgYW1vdW50OiAnMCcsIGRhdGE6IG1vY2tDYWxsZGF0YSB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgIC9jYWxsXFwoc1xcKS9cbiAgICApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHBhcnNlIGEgcmF3IGNhbGwgdHJhbnNhY3Rpb24gYW5kIGV4cG9zZSB0aGUgY29udHJhY3QgYXMgYW4gb3V0cHV0JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRSYXdDYWxsVHgobW9ja0NvbnRyYWN0LCBtb2NrQ2FsbGRhdGEpO1xuICAgIGNvbnN0IHBhcnNlZCA9IGF3YWl0IGNvaW4ucGFyc2VUcmFuc2FjdGlvbih7IHR4SGV4IH0pO1xuICAgIGFzc2VydC5vayhBcnJheS5pc0FycmF5KHBhcnNlZC5vdXRwdXRzKSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5vdXRwdXRzLmxlbmd0aCwgMSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5vdXRwdXRzWzBdLmFkZHJlc3MudG9Mb3dlckNhc2UoKSwgbW9ja0NvbnRyYWN0LnRvTG93ZXJDYXNlKCkpO1xuICB9KTtcbn0pO1xuIl19