@okeyamy/lua 5.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,641 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
5
+ /**
6
+ * AI-Powered Personalization Engine
7
+ * ==================================
8
+ * Integrates OpenAI GPT models with the Lua personalization system.
9
+ * Works alongside the existing decision engine as an optional enhancement.
10
+ *
11
+ * Supports two connection modes:
12
+ * 1. Direct OpenAI API (user provides apiKey) - uses https://api.openai.com/v1/chat/completions
13
+ * 2. Proxy URL (user provides apiUrl pointing to their backend)
14
+ *
15
+ * Supports two personalization modes:
16
+ * - 'select': AI chooses the best variant from user-provided templates
17
+ * - 'generate': AI creates new personalized content from scratch
18
+ *
19
+ * Depends on:
20
+ * - window.LuaWeightedHistory (from storage/weighted-history.js)
21
+ * - window.LuaPrompts (from prompts/personalization-prompts.js)
22
+ * - window.LuaUTM or window.LuaUTMPersonalize (for context, optional)
23
+ *
24
+ * Registers on window.LuaAIPersonalize
25
+ * No ES6 imports. Self-contained IIFE.
26
+ */
27
+ ;
28
+ (function (root) {
29
+ 'use strict';
30
+
31
+ // ===================================================================
32
+ // Constants & Defaults
33
+ // ===================================================================
34
+ var OPENAI_BASE_URL = 'https://api.openai.com/v1/chat/completions';
35
+ var DEFAULT_MODEL = 'gpt-4o-mini';
36
+ var DEFAULT_TIMEOUT = 5000;
37
+ var DEFAULT_MAX_TOKENS = 500;
38
+ var DEFAULT_TEMPERATURE = 0.7;
39
+ var DEFAULT_MAX_RETRIES = 1;
40
+ var CACHE_KEY_PREFIX = 'lua_ai_cache_';
41
+ var DEFAULT_CACHE_DURATION = 3600000; // 1 hour
42
+
43
+ // ===================================================================
44
+ // Configuration Validator
45
+ // ===================================================================
46
+
47
+ /**
48
+ * Validate and normalize AI configuration
49
+ * @param {Object} config - Raw AI configuration
50
+ * @returns {Object} - Normalized configuration with defaults applied
51
+ */
52
+ function normalizeConfig(config) {
53
+ if (!config || (0, _typeof2.default)(config) !== 'object') {
54
+ return {
55
+ valid: false,
56
+ error: 'AI config must be an object'
57
+ };
58
+ }
59
+
60
+ // Must have either apiKey or apiUrl
61
+ var hasApiKey = typeof config.apiKey === 'string' && config.apiKey.trim().length > 0;
62
+ var hasApiUrl = typeof config.apiUrl === 'string' && config.apiUrl.trim().length > 0;
63
+ if (!hasApiKey && !hasApiUrl) {
64
+ return {
65
+ valid: false,
66
+ error: 'AI config requires either "apiKey" (for direct OpenAI) or "apiUrl" (for proxy endpoint)'
67
+ };
68
+ }
69
+ return {
70
+ valid: true,
71
+ // Connection
72
+ apiKey: hasApiKey ? config.apiKey.trim() : null,
73
+ apiUrl: hasApiUrl ? config.apiUrl.trim() : OPENAI_BASE_URL,
74
+ useDirectApi: hasApiKey && !hasApiUrl,
75
+ // Model settings
76
+ model: config.model || DEFAULT_MODEL,
77
+ temperature: typeof config.temperature === 'number' ? config.temperature : DEFAULT_TEMPERATURE,
78
+ maxTokens: typeof config.maxTokens === 'number' ? config.maxTokens : DEFAULT_MAX_TOKENS,
79
+ // Behavior
80
+ mode: config.mode === 'generate' ? 'generate' : 'select',
81
+ timeout: typeof config.timeout === 'number' ? config.timeout : DEFAULT_TIMEOUT,
82
+ maxRetries: typeof config.maxRetries === 'number' ? config.maxRetries : DEFAULT_MAX_RETRIES,
83
+ fallbackToStandard: config.fallbackToStandard !== false,
84
+ // Caching
85
+ cacheDecisions: config.cacheDecisions !== false,
86
+ cacheDuration: typeof config.cacheDuration === 'number' ? config.cacheDuration : DEFAULT_CACHE_DURATION,
87
+ // History
88
+ historyEnabled: config.historyEnabled !== false,
89
+ historyDecayRate: typeof config.historyDecayRate === 'number' ? config.historyDecayRate : 0.9,
90
+ maxHistorySize: typeof config.maxHistorySize === 'number' ? config.maxHistorySize : 10,
91
+ // Brand context (for generate mode)
92
+ brandContext: config.brandContext || null,
93
+ // Custom prompts
94
+ customPrompts: config.customPrompts || {}
95
+ };
96
+ }
97
+
98
+ // ===================================================================
99
+ // Cache Management
100
+ // ===================================================================
101
+
102
+ /**
103
+ * Generate a cache key from the context (hash-like identifier)
104
+ * @param {Object} context - Current UTM context
105
+ * @param {string} mode - 'select' or 'generate'
106
+ * @returns {string} - Cache key
107
+ */
108
+ function buildCacheKey(context, mode) {
109
+ var parts = [mode];
110
+ if (context.utm) {
111
+ if (context.utm.utm_source) parts.push('s:' + context.utm.utm_source);
112
+ if (context.utm.utm_medium) parts.push('m:' + context.utm.utm_medium);
113
+ if (context.utm.utm_campaign) parts.push('c:' + context.utm.utm_campaign);
114
+ }
115
+ if (context.referrer) {
116
+ parts.push('r:' + (context.referrer.source || 'direct'));
117
+ }
118
+ if (context.userAgent) {
119
+ parts.push('d:' + (context.userAgent.isMobile ? 'mob' : context.userAgent.isTablet ? 'tab' : 'desk'));
120
+ }
121
+ return CACHE_KEY_PREFIX + parts.join('_');
122
+ }
123
+
124
+ /**
125
+ * Read a cached AI decision
126
+ * @param {string} cacheKey - Cache key
127
+ * @param {number} cacheDuration - Max age in ms
128
+ * @returns {Object|null} - Cached decision or null if expired/missing
129
+ */
130
+ function readCache(cacheKey, cacheDuration) {
131
+ try {
132
+ if (typeof localStorage === 'undefined') return null;
133
+ var raw = localStorage.getItem(cacheKey);
134
+ if (!raw) return null;
135
+ var cached = JSON.parse(raw);
136
+ if (!cached || !cached.timestamp || !cached.decision) return null;
137
+
138
+ // Check expiry
139
+ var age = Date.now() - cached.timestamp;
140
+ if (age > cacheDuration) {
141
+ localStorage.removeItem(cacheKey);
142
+ return null;
143
+ }
144
+ return cached.decision;
145
+ } catch (e) {
146
+ return null;
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Write an AI decision to cache
152
+ * @param {string} cacheKey - Cache key
153
+ * @param {Object} decision - Decision to cache
154
+ */
155
+ function writeCache(cacheKey, decision) {
156
+ try {
157
+ if (typeof localStorage === 'undefined') return;
158
+ localStorage.setItem(cacheKey, JSON.stringify({
159
+ timestamp: Date.now(),
160
+ decision: decision
161
+ }));
162
+ } catch (e) {
163
+ console.warn('[Lua AI] Failed to write cache:', e);
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Clear all AI decision caches
169
+ */
170
+ function clearCache() {
171
+ try {
172
+ if (typeof localStorage === 'undefined') return;
173
+ var keysToRemove = [];
174
+ for (var i = 0; i < localStorage.length; i++) {
175
+ var key = localStorage.key(i);
176
+ if (key && key.indexOf(CACHE_KEY_PREFIX) === 0) {
177
+ keysToRemove.push(key);
178
+ }
179
+ }
180
+ for (var j = 0; j < keysToRemove.length; j++) {
181
+ localStorage.removeItem(keysToRemove[j]);
182
+ }
183
+ } catch (e) {
184
+ console.warn('[Lua AI] Failed to clear cache:', e);
185
+ }
186
+ }
187
+
188
+ // ===================================================================
189
+ // API Communication
190
+ // ===================================================================
191
+
192
+ /**
193
+ * Call the OpenAI API (direct or via proxy)
194
+ * @param {Array} messages - Chat messages array
195
+ * @param {Object} config - Normalized AI config
196
+ * @returns {Promise<Object>} - Parsed AI response
197
+ */
198
+ function callOpenAI(messages, config) {
199
+ var url = config.useDirectApi ? OPENAI_BASE_URL : config.apiUrl;
200
+ var headers = {
201
+ 'Content-Type': 'application/json'
202
+ };
203
+
204
+ // Add Authorization header for direct API access
205
+ if (config.useDirectApi && config.apiKey) {
206
+ headers['Authorization'] = 'Bearer ' + config.apiKey;
207
+ }
208
+ var body = {
209
+ model: config.model,
210
+ messages: messages,
211
+ temperature: config.temperature,
212
+ max_tokens: config.maxTokens,
213
+ response_format: {
214
+ type: 'json_object'
215
+ }
216
+ };
217
+
218
+ // Create abort controller for timeout
219
+ var controller = null;
220
+ var timeoutId = null;
221
+ if (typeof AbortController !== 'undefined') {
222
+ controller = new AbortController();
223
+ timeoutId = setTimeout(function () {
224
+ controller.abort();
225
+ }, config.timeout);
226
+ }
227
+ var fetchOptions = {
228
+ method: 'POST',
229
+ headers: headers,
230
+ body: JSON.stringify(body)
231
+ };
232
+ if (controller) {
233
+ fetchOptions.signal = controller.signal;
234
+ }
235
+ return fetch(url, fetchOptions).then(function (response) {
236
+ if (timeoutId) clearTimeout(timeoutId);
237
+ if (!response.ok) {
238
+ return response.text().then(function (text) {
239
+ throw new Error('API request failed (' + response.status + '): ' + text.substring(0, 200));
240
+ });
241
+ }
242
+ return response.json();
243
+ }).then(function (data) {
244
+ // Parse OpenAI response structure
245
+ if (data && data.choices && data.choices[0] && data.choices[0].message) {
246
+ var content = data.choices[0].message.content;
247
+ try {
248
+ return JSON.parse(content);
249
+ } catch (e) {
250
+ // Try to extract JSON from content if it's wrapped in markdown
251
+ var jsonMatch = content.match(/\{[\s\S]*\}/);
252
+ if (jsonMatch) {
253
+ return JSON.parse(jsonMatch[0]);
254
+ }
255
+ throw new Error('Failed to parse AI response as JSON: ' + content.substring(0, 200));
256
+ }
257
+ }
258
+
259
+ // If the response IS the parsed content (proxy might forward differently)
260
+ if (data && (data.selectedVariant || data.headline)) {
261
+ return data;
262
+ }
263
+ throw new Error('Unexpected API response structure');
264
+ }).catch(function (error) {
265
+ if (timeoutId) clearTimeout(timeoutId);
266
+ if (error.name === 'AbortError') {
267
+ throw new Error('AI request timed out after ' + config.timeout + 'ms');
268
+ }
269
+ throw error;
270
+ });
271
+ }
272
+
273
+ /**
274
+ * Call OpenAI with retry logic
275
+ * @param {Array} messages - Chat messages
276
+ * @param {Object} config - Normalized config
277
+ * @param {number} [attempt] - Current attempt number
278
+ * @returns {Promise<Object>} - Parsed AI response
279
+ */
280
+ function callWithRetry(messages, config, attempt) {
281
+ attempt = attempt || 0;
282
+ return callOpenAI(messages, config).catch(function (error) {
283
+ if (attempt < config.maxRetries) {
284
+ console.warn('[Lua AI] Retry attempt ' + (attempt + 1) + ':', error.message);
285
+ // Exponential backoff: 500ms, 1000ms, 2000ms...
286
+ return new Promise(function (resolve) {
287
+ setTimeout(function () {
288
+ resolve(callWithRetry(messages, config, attempt + 1));
289
+ }, 500 * Math.pow(2, attempt));
290
+ });
291
+ }
292
+ throw error;
293
+ });
294
+ }
295
+
296
+ // ===================================================================
297
+ // Response Validation
298
+ // ===================================================================
299
+
300
+ /**
301
+ * Validate a SELECTION mode response
302
+ * @param {Object} response - Parsed AI response
303
+ * @param {Object} variants - Available variants (to validate key exists)
304
+ * @returns {Object} - { valid: boolean, error?: string }
305
+ */
306
+ function validateSelectResponse(response, variants) {
307
+ if (!response || (0, _typeof2.default)(response) !== 'object') {
308
+ return {
309
+ valid: false,
310
+ error: 'Response is not an object'
311
+ };
312
+ }
313
+ if (!response.selectedVariant || typeof response.selectedVariant !== 'string') {
314
+ return {
315
+ valid: false,
316
+ error: 'Missing or invalid "selectedVariant" field'
317
+ };
318
+ }
319
+
320
+ // Check that the selected variant actually exists
321
+ if (!variants[response.selectedVariant]) {
322
+ return {
323
+ valid: false,
324
+ error: 'Selected variant "' + response.selectedVariant + '" does not exist in templates'
325
+ };
326
+ }
327
+ return {
328
+ valid: true
329
+ };
330
+ }
331
+
332
+ /**
333
+ * Validate a GENERATION mode response
334
+ * @param {Object} response - Parsed AI response
335
+ * @returns {Object} - { valid: boolean, error?: string }
336
+ */
337
+ function validateGenerateResponse(response) {
338
+ if (!response || (0, _typeof2.default)(response) !== 'object') {
339
+ return {
340
+ valid: false,
341
+ error: 'Response is not an object'
342
+ };
343
+ }
344
+ if (!response.headline || typeof response.headline !== 'string') {
345
+ return {
346
+ valid: false,
347
+ error: 'Missing or invalid "headline" field'
348
+ };
349
+ }
350
+ if (!response.subheadline || typeof response.subheadline !== 'string') {
351
+ return {
352
+ valid: false,
353
+ error: 'Missing or invalid "subheadline" field'
354
+ };
355
+ }
356
+ if (!response.ctaLabel || typeof response.ctaLabel !== 'string') {
357
+ return {
358
+ valid: false,
359
+ error: 'Missing or invalid "ctaLabel" field'
360
+ };
361
+ }
362
+ return {
363
+ valid: true
364
+ };
365
+ }
366
+
367
+ // ===================================================================
368
+ // AI Decision Engine
369
+ // ===================================================================
370
+
371
+ /**
372
+ * Main AI decision function
373
+ * Gathers context, builds prompts, calls API, validates response
374
+ *
375
+ * @param {Object} context - Current UTM/referrer/device context
376
+ * @param {Object} options - Full options object
377
+ * @param {Object} options.templates - User-provided templates (REQUIRED)
378
+ * @param {Object} options.aiConfig - AI configuration (REQUIRED)
379
+ * @param {boolean} [options.log] - Enable logging (default: true)
380
+ * @returns {Promise<Object>} - Decision result { template, intent, source, context, aiResponse }
381
+ */
382
+ function aiDecide(context, options) {
383
+ var config = normalizeConfig(options.aiConfig);
384
+ if (!config.valid) {
385
+ return Promise.reject(new Error('[Lua AI] ' + config.error));
386
+ }
387
+ var templates = options.templates || {};
388
+ var log = options.log !== false;
389
+
390
+ // Check cache first
391
+ if (config.cacheDecisions) {
392
+ var cacheKey = buildCacheKey(context, config.mode);
393
+ var cached = readCache(cacheKey, config.cacheDuration);
394
+ if (cached) {
395
+ if (log) {
396
+ console.log('[Lua AI] Using cached decision:', cached.intent);
397
+ }
398
+ cached.source = 'ai-cached';
399
+ return Promise.resolve(cached);
400
+ }
401
+ }
402
+
403
+ // Get weighted history
404
+ var HistoryModule = root.LuaWeightedHistory;
405
+ var weightedHistory = '';
406
+ var preferences = {};
407
+ var history = null;
408
+ if (config.historyEnabled && HistoryModule) {
409
+ history = HistoryModule.getHistory();
410
+ var weighted = HistoryModule.buildWeightedContext(history, {
411
+ decayRate: config.historyDecayRate
412
+ });
413
+ preferences = HistoryModule.aggregatePreferences(weighted);
414
+ weightedHistory = HistoryModule.formatForPrompt(weighted);
415
+ }
416
+
417
+ // Get prompt module
418
+ var PromptsModule = root.LuaPrompts;
419
+ if (!PromptsModule) {
420
+ return Promise.reject(new Error('[Lua AI] LuaPrompts module not loaded. Include prompts/personalization-prompts.js'));
421
+ }
422
+
423
+ // Build prompt parameters
424
+ var promptParams = {
425
+ context: context,
426
+ weightedHistory: weightedHistory,
427
+ preferences: preferences
428
+ };
429
+ if (config.mode === 'select') {
430
+ promptParams.variants = templates;
431
+ } else {
432
+ // Generate mode
433
+ promptParams.brandContext = config.brandContext;
434
+ promptParams.fallbackTemplate = templates['default'] || templates[Object.keys(templates)[0]] || null;
435
+ }
436
+
437
+ // Build messages
438
+ var messages = PromptsModule.buildMessages(config.mode, promptParams, config.customPrompts);
439
+ var startTime = Date.now();
440
+
441
+ // Call AI
442
+ return callWithRetry(messages, config).then(function (aiResponse) {
443
+ var latency = Date.now() - startTime;
444
+ var decision;
445
+ if (config.mode === 'select') {
446
+ // Validate selection
447
+ var selectValidation = validateSelectResponse(aiResponse, templates);
448
+ if (!selectValidation.valid) {
449
+ throw new Error('Invalid AI selection: ' + selectValidation.error);
450
+ }
451
+ decision = {
452
+ template: templates[aiResponse.selectedVariant],
453
+ intent: aiResponse.selectedVariant,
454
+ source: 'ai',
455
+ context: context,
456
+ aiResponse: {
457
+ confidence: aiResponse.confidence || null,
458
+ reasoning: aiResponse.reasoning || null,
459
+ latency: latency,
460
+ model: config.model,
461
+ mode: 'select',
462
+ cached: false
463
+ }
464
+ };
465
+ } else {
466
+ // Validate generation
467
+ var genValidation = validateGenerateResponse(aiResponse);
468
+ if (!genValidation.valid) {
469
+ throw new Error('Invalid AI generation: ' + genValidation.error);
470
+ }
471
+
472
+ // Build a template from generated content
473
+ var generatedTemplate = {
474
+ headline: aiResponse.headline,
475
+ subheadline: aiResponse.subheadline,
476
+ ctaLabel: aiResponse.ctaLabel,
477
+ ctaLink: templates['default'] && templates['default'].ctaLink || '/shop',
478
+ image: templates['default'] && templates['default'].image || null
479
+ };
480
+ decision = {
481
+ template: generatedTemplate,
482
+ intent: 'ai-generated',
483
+ source: 'ai',
484
+ context: context,
485
+ aiResponse: {
486
+ confidence: aiResponse.confidence || null,
487
+ reasoning: aiResponse.reasoning || null,
488
+ latency: latency,
489
+ model: config.model,
490
+ mode: 'generate',
491
+ cached: false
492
+ }
493
+ };
494
+ }
495
+
496
+ // Cache the decision
497
+ if (config.cacheDecisions) {
498
+ writeCache(buildCacheKey(context, config.mode), decision);
499
+ }
500
+
501
+ // Record visit to history
502
+ if (config.historyEnabled && HistoryModule) {
503
+ HistoryModule.recordVisit({
504
+ context: context,
505
+ intent: decision.intent,
506
+ selectedVariant: decision.intent,
507
+ source: 'ai',
508
+ aiDecision: true
509
+ }, {
510
+ maxHistorySize: config.maxHistorySize
511
+ });
512
+ }
513
+ if (log) {
514
+ console.log('[Lua AI] Decision made:', {
515
+ mode: config.mode,
516
+ intent: decision.intent,
517
+ source: 'ai',
518
+ confidence: decision.aiResponse.confidence,
519
+ latency: latency + 'ms',
520
+ model: config.model
521
+ });
522
+ }
523
+ return decision;
524
+ }).catch(function (error) {
525
+ var latency = Date.now() - startTime;
526
+ if (log) {
527
+ console.warn('[Lua AI] Error after ' + latency + 'ms:', error.message);
528
+ }
529
+ throw error;
530
+ });
531
+ }
532
+
533
+ // ===================================================================
534
+ // Integration Helpers
535
+ // ===================================================================
536
+
537
+ /**
538
+ * High-level AI personalize function
539
+ * Wraps aiDecide with full context gathering and DOM application
540
+ * Designed to be called from the main personalize() function
541
+ *
542
+ * @param {Object} options - Full personalization options
543
+ * @param {Object} options.templates - User templates (REQUIRED)
544
+ * @param {Object} options.aiConfig - AI configuration (REQUIRED)
545
+ * @param {Object} [options.context] - Pre-computed context
546
+ * @param {boolean} [options.log] - Enable logging
547
+ * @returns {Promise<Object>} - Decision result
548
+ */
549
+ function personalizeWithAI(options) {
550
+ options = options || {};
551
+
552
+ // Get context
553
+ var context = options.context;
554
+ if (!context) {
555
+ // Try to get context from UTM modules
556
+ var utmModule = root.LuaUTMPersonalize || root.LuaUTM;
557
+ if (utmModule && typeof utmModule.getContext === 'function') {
558
+ context = utmModule.getContext();
559
+ } else {
560
+ context = {
561
+ utm: {},
562
+ referrer: {
563
+ source: 'direct',
564
+ category: 'direct',
565
+ url: ''
566
+ },
567
+ userAgent: {
568
+ raw: '',
569
+ isMobile: false,
570
+ isTablet: false,
571
+ isDesktop: true
572
+ },
573
+ timestamp: Date.now(),
574
+ hasUTM: false,
575
+ primaryIntent: 'default'
576
+ };
577
+ }
578
+ }
579
+ return aiDecide(context, options);
580
+ }
581
+
582
+ /**
583
+ * Quick check: is AI properly configured and ready?
584
+ * @param {Object} aiConfig - AI config to check
585
+ * @returns {Object} - { ready: boolean, error?: string }
586
+ */
587
+ function isReady(aiConfig) {
588
+ var config = normalizeConfig(aiConfig);
589
+ if (!config.valid) {
590
+ return {
591
+ ready: false,
592
+ error: config.error
593
+ };
594
+ }
595
+
596
+ // Check dependencies
597
+ if (!root.LuaPrompts) {
598
+ return {
599
+ ready: false,
600
+ error: 'LuaPrompts module not loaded'
601
+ };
602
+ }
603
+
604
+ // History is optional but recommended
605
+ if (!root.LuaWeightedHistory) {
606
+ console.warn('[Lua AI] LuaWeightedHistory not loaded. History features disabled.');
607
+ }
608
+ return {
609
+ ready: true
610
+ };
611
+ }
612
+
613
+ // ===================================================================
614
+ // Public API
615
+ // ===================================================================
616
+
617
+ var LuaAIPersonalize = {
618
+ // Core
619
+ decide: aiDecide,
620
+ personalizeWithAI: personalizeWithAI,
621
+ isReady: isReady,
622
+ // Configuration
623
+ normalizeConfig: normalizeConfig,
624
+ // API communication
625
+ callOpenAI: callOpenAI,
626
+ // Validation
627
+ validateSelectResponse: validateSelectResponse,
628
+ validateGenerateResponse: validateGenerateResponse,
629
+ // Cache
630
+ clearCache: clearCache,
631
+ // Constants
632
+ OPENAI_BASE_URL: OPENAI_BASE_URL,
633
+ DEFAULT_MODEL: DEFAULT_MODEL,
634
+ DEFAULT_TIMEOUT: DEFAULT_TIMEOUT,
635
+ DEFAULT_CACHE_DURATION: DEFAULT_CACHE_DURATION
636
+ };
637
+
638
+ // Register globally
639
+ root.LuaAIPersonalize = LuaAIPersonalize;
640
+ })(typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : void 0);
641
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJyb290IiwiT1BFTkFJX0JBU0VfVVJMIiwiREVGQVVMVF9NT0RFTCIsIkRFRkFVTFRfVElNRU9VVCIsIkRFRkFVTFRfTUFYX1RPS0VOUyIsIkRFRkFVTFRfVEVNUEVSQVRVUkUiLCJERUZBVUxUX01BWF9SRVRSSUVTIiwiQ0FDSEVfS0VZX1BSRUZJWCIsIkRFRkFVTFRfQ0FDSEVfRFVSQVRJT04iLCJub3JtYWxpemVDb25maWciLCJjb25maWciLCJfdHlwZW9mMiIsImRlZmF1bHQiLCJ2YWxpZCIsImVycm9yIiwiaGFzQXBpS2V5IiwiYXBpS2V5IiwidHJpbSIsImxlbmd0aCIsImhhc0FwaVVybCIsImFwaVVybCIsInVzZURpcmVjdEFwaSIsIm1vZGVsIiwidGVtcGVyYXR1cmUiLCJtYXhUb2tlbnMiLCJtb2RlIiwidGltZW91dCIsIm1heFJldHJpZXMiLCJmYWxsYmFja1RvU3RhbmRhcmQiLCJjYWNoZURlY2lzaW9ucyIsImNhY2hlRHVyYXRpb24iLCJoaXN0b3J5RW5hYmxlZCIsImhpc3RvcnlEZWNheVJhdGUiLCJtYXhIaXN0b3J5U2l6ZSIsImJyYW5kQ29udGV4dCIsImN1c3RvbVByb21wdHMiLCJidWlsZENhY2hlS2V5IiwiY29udGV4dCIsInBhcnRzIiwidXRtIiwidXRtX3NvdXJjZSIsInB1c2giLCJ1dG1fbWVkaXVtIiwidXRtX2NhbXBhaWduIiwicmVmZXJyZXIiLCJzb3VyY2UiLCJ1c2VyQWdlbnQiLCJpc01vYmlsZSIsImlzVGFibGV0Iiwiam9pbiIsInJlYWRDYWNoZSIsImNhY2hlS2V5IiwibG9jYWxTdG9yYWdlIiwicmF3IiwiZ2V0SXRlbSIsImNhY2hlZCIsIkpTT04iLCJwYXJzZSIsInRpbWVzdGFtcCIsImRlY2lzaW9uIiwiYWdlIiwiRGF0ZSIsIm5vdyIsInJlbW92ZUl0ZW0iLCJlIiwid3JpdGVDYWNoZSIsInNldEl0ZW0iLCJzdHJpbmdpZnkiLCJjb25zb2xlIiwid2FybiIsImNsZWFyQ2FjaGUiLCJrZXlzVG9SZW1vdmUiLCJpIiwia2V5IiwiaW5kZXhPZiIsImoiLCJjYWxsT3BlbkFJIiwibWVzc2FnZXMiLCJ1cmwiLCJoZWFkZXJzIiwiYm9keSIsIm1heF90b2tlbnMiLCJyZXNwb25zZV9mb3JtYXQiLCJ0eXBlIiwiY29udHJvbGxlciIsInRpbWVvdXRJZCIsIkFib3J0Q29udHJvbGxlciIsInNldFRpbWVvdXQiLCJhYm9ydCIsImZldGNoT3B0aW9ucyIsIm1ldGhvZCIsInNpZ25hbCIsImZldGNoIiwidGhlbiIsInJlc3BvbnNlIiwiY2xlYXJUaW1lb3V0Iiwib2siLCJ0ZXh0IiwiRXJyb3IiLCJzdGF0dXMiLCJzdWJzdHJpbmciLCJqc29uIiwiZGF0YSIsImNob2ljZXMiLCJtZXNzYWdlIiwiY29udGVudCIsImpzb25NYXRjaCIsIm1hdGNoIiwic2VsZWN0ZWRWYXJpYW50IiwiaGVhZGxpbmUiLCJjYXRjaCIsIm5hbWUiLCJjYWxsV2l0aFJldHJ5IiwiYXR0ZW1wdCIsIlByb21pc2UiLCJyZXNvbHZlIiwiTWF0aCIsInBvdyIsInZhbGlkYXRlU2VsZWN0UmVzcG9uc2UiLCJ2YXJpYW50cyIsInZhbGlkYXRlR2VuZXJhdGVSZXNwb25zZSIsInN1YmhlYWRsaW5lIiwiY3RhTGFiZWwiLCJhaURlY2lkZSIsIm9wdGlvbnMiLCJhaUNvbmZpZyIsInJlamVjdCIsInRlbXBsYXRlcyIsImxvZyIsImludGVudCIsIkhpc3RvcnlNb2R1bGUiLCJMdWFXZWlnaHRlZEhpc3RvcnkiLCJ3ZWlnaHRlZEhpc3RvcnkiLCJwcmVmZXJlbmNlcyIsImhpc3RvcnkiLCJnZXRIaXN0b3J5Iiwid2VpZ2h0ZWQiLCJidWlsZFdlaWdodGVkQ29udGV4dCIsImRlY2F5UmF0ZSIsImFnZ3JlZ2F0ZVByZWZlcmVuY2VzIiwiZm9ybWF0Rm9yUHJvbXB0IiwiUHJvbXB0c01vZHVsZSIsIkx1YVByb21wdHMiLCJwcm9tcHRQYXJhbXMiLCJmYWxsYmFja1RlbXBsYXRlIiwiT2JqZWN0Iiwia2V5cyIsImJ1aWxkTWVzc2FnZXMiLCJzdGFydFRpbWUiLCJhaVJlc3BvbnNlIiwibGF0ZW5jeSIsInNlbGVjdFZhbGlkYXRpb24iLCJ0ZW1wbGF0ZSIsImNvbmZpZGVuY2UiLCJyZWFzb25pbmciLCJnZW5WYWxpZGF0aW9uIiwiZ2VuZXJhdGVkVGVtcGxhdGUiLCJjdGFMaW5rIiwiaW1hZ2UiLCJyZWNvcmRWaXNpdCIsImFpRGVjaXNpb24iLCJwZXJzb25hbGl6ZVdpdGhBSSIsInV0bU1vZHVsZSIsIkx1YVVUTVBlcnNvbmFsaXplIiwiTHVhVVRNIiwiZ2V0Q29udGV4dCIsImNhdGVnb3J5IiwiaXNEZXNrdG9wIiwiaGFzVVRNIiwicHJpbWFyeUludGVudCIsImlzUmVhZHkiLCJyZWFkeSIsIkx1YUFJUGVyc29uYWxpemUiLCJkZWNpZGUiLCJ3aW5kb3ciLCJnbG9iYWwiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvYWktcGVyc29uYWxpemUuanMiXSwic291cmNlc0NvbnRlbnQiOlsiXG4vKipcbiAqIEFJLVBvd2VyZWQgUGVyc29uYWxpemF0aW9uIEVuZ2luZVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogSW50ZWdyYXRlcyBPcGVuQUkgR1BUIG1vZGVscyB3aXRoIHRoZSBMdWEgcGVyc29uYWxpemF0aW9uIHN5c3RlbS5cbiAqIFdvcmtzIGFsb25nc2lkZSB0aGUgZXhpc3RpbmcgZGVjaXNpb24gZW5naW5lIGFzIGFuIG9wdGlvbmFsIGVuaGFuY2VtZW50LlxuICpcbiAqIFN1cHBvcnRzIHR3byBjb25uZWN0aW9uIG1vZGVzOlxuICogICAxLiBEaXJlY3QgT3BlbkFJIEFQSSAodXNlciBwcm92aWRlcyBhcGlLZXkpIC0gdXNlcyBodHRwczovL2FwaS5vcGVuYWkuY29tL3YxL2NoYXQvY29tcGxldGlvbnNcbiAqICAgMi4gUHJveHkgVVJMICh1c2VyIHByb3ZpZGVzIGFwaVVybCBwb2ludGluZyB0byB0aGVpciBiYWNrZW5kKVxuICpcbiAqIFN1cHBvcnRzIHR3byBwZXJzb25hbGl6YXRpb24gbW9kZXM6XG4gKiAgIC0gJ3NlbGVjdCc6IEFJIGNob29zZXMgdGhlIGJlc3QgdmFyaWFudCBmcm9tIHVzZXItcHJvdmlkZWQgdGVtcGxhdGVzXG4gKiAgIC0gJ2dlbmVyYXRlJzogQUkgY3JlYXRlcyBuZXcgcGVyc29uYWxpemVkIGNvbnRlbnQgZnJvbSBzY3JhdGNoXG4gKlxuICogRGVwZW5kcyBvbjpcbiAqICAgLSB3aW5kb3cuTHVhV2VpZ2h0ZWRIaXN0b3J5IChmcm9tIHN0b3JhZ2Uvd2VpZ2h0ZWQtaGlzdG9yeS5qcylcbiAqICAgLSB3aW5kb3cuTHVhUHJvbXB0cyAoZnJvbSBwcm9tcHRzL3BlcnNvbmFsaXphdGlvbi1wcm9tcHRzLmpzKVxuICogICAtIHdpbmRvdy5MdWFVVE0gb3Igd2luZG93Lkx1YVVUTVBlcnNvbmFsaXplIChmb3IgY29udGV4dCwgb3B0aW9uYWwpXG4gKlxuICogUmVnaXN0ZXJzIG9uIHdpbmRvdy5MdWFBSVBlcnNvbmFsaXplXG4gKiBObyBFUzYgaW1wb3J0cy4gU2VsZi1jb250YWluZWQgSUlGRS5cbiAqL1xuOyhmdW5jdGlvbiAocm9vdCkge1xuICAgICd1c2Ugc3RyaWN0J1xuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIENvbnN0YW50cyAmIERlZmF1bHRzXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgdmFyIE9QRU5BSV9CQVNFX1VSTCA9ICdodHRwczovL2FwaS5vcGVuYWkuY29tL3YxL2NoYXQvY29tcGxldGlvbnMnXG4gICAgdmFyIERFRkFVTFRfTU9ERUwgPSAnZ3B0LTRvLW1pbmknXG4gICAgdmFyIERFRkFVTFRfVElNRU9VVCA9IDUwMDBcbiAgICB2YXIgREVGQVVMVF9NQVhfVE9LRU5TID0gNTAwXG4gICAgdmFyIERFRkFVTFRfVEVNUEVSQVRVUkUgPSAwLjdcbiAgICB2YXIgREVGQVVMVF9NQVhfUkVUUklFUyA9IDFcbiAgICB2YXIgQ0FDSEVfS0VZX1BSRUZJWCA9ICdsdWFfYWlfY2FjaGVfJ1xuICAgIHZhciBERUZBVUxUX0NBQ0hFX0RVUkFUSU9OID0gMzYwMDAwMCAvLyAxIGhvdXJcblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBDb25maWd1cmF0aW9uIFZhbGlkYXRvclxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIC8qKlxuICAgICAqIFZhbGlkYXRlIGFuZCBub3JtYWxpemUgQUkgY29uZmlndXJhdGlvblxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgLSBSYXcgQUkgY29uZmlndXJhdGlvblxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IC0gTm9ybWFsaXplZCBjb25maWd1cmF0aW9uIHdpdGggZGVmYXVsdHMgYXBwbGllZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZUNvbmZpZyhjb25maWcpIHtcbiAgICAgICAgaWYgKCFjb25maWcgfHwgdHlwZW9mIGNvbmZpZyAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSwgZXJyb3I6ICdBSSBjb25maWcgbXVzdCBiZSBhbiBvYmplY3QnIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE11c3QgaGF2ZSBlaXRoZXIgYXBpS2V5IG9yIGFwaVVybFxuICAgICAgICB2YXIgaGFzQXBpS2V5ID0gdHlwZW9mIGNvbmZpZy5hcGlLZXkgPT09ICdzdHJpbmcnICYmIGNvbmZpZy5hcGlLZXkudHJpbSgpLmxlbmd0aCA+IDBcbiAgICAgICAgdmFyIGhhc0FwaVVybCA9IHR5cGVvZiBjb25maWcuYXBpVXJsID09PSAnc3RyaW5nJyAmJiBjb25maWcuYXBpVXJsLnRyaW0oKS5sZW5ndGggPiAwXG5cbiAgICAgICAgaWYgKCFoYXNBcGlLZXkgJiYgIWhhc0FwaVVybCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB2YWxpZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgZXJyb3I6ICdBSSBjb25maWcgcmVxdWlyZXMgZWl0aGVyIFwiYXBpS2V5XCIgKGZvciBkaXJlY3QgT3BlbkFJKSBvciBcImFwaVVybFwiIChmb3IgcHJveHkgZW5kcG9pbnQpJ1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHZhbGlkOiB0cnVlLFxuXG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uXG4gICAgICAgICAgICBhcGlLZXk6IGhhc0FwaUtleSA/IGNvbmZpZy5hcGlLZXkudHJpbSgpIDogbnVsbCxcbiAgICAgICAgICAgIGFwaVVybDogaGFzQXBpVXJsID8gY29uZmlnLmFwaVVybC50cmltKCkgOiBPUEVOQUlfQkFTRV9VUkwsXG4gICAgICAgICAgICB1c2VEaXJlY3RBcGk6IGhhc0FwaUtleSAmJiAhaGFzQXBpVXJsLFxuXG4gICAgICAgICAgICAvLyBNb2RlbCBzZXR0aW5nc1xuICAgICAgICAgICAgbW9kZWw6IGNvbmZpZy5tb2RlbCB8fCBERUZBVUxUX01PREVMLFxuICAgICAgICAgICAgdGVtcGVyYXR1cmU6IHR5cGVvZiBjb25maWcudGVtcGVyYXR1cmUgPT09ICdudW1iZXInID8gY29uZmlnLnRlbXBlcmF0dXJlIDogREVGQVVMVF9URU1QRVJBVFVSRSxcbiAgICAgICAgICAgIG1heFRva2VuczogdHlwZW9mIGNvbmZpZy5tYXhUb2tlbnMgPT09ICdudW1iZXInID8gY29uZmlnLm1heFRva2VucyA6IERFRkFVTFRfTUFYX1RPS0VOUyxcblxuICAgICAgICAgICAgLy8gQmVoYXZpb3JcbiAgICAgICAgICAgIG1vZGU6IGNvbmZpZy5tb2RlID09PSAnZ2VuZXJhdGUnID8gJ2dlbmVyYXRlJyA6ICdzZWxlY3QnLFxuICAgICAgICAgICAgdGltZW91dDogdHlwZW9mIGNvbmZpZy50aW1lb3V0ID09PSAnbnVtYmVyJyA/IGNvbmZpZy50aW1lb3V0IDogREVGQVVMVF9USU1FT1VULFxuICAgICAgICAgICAgbWF4UmV0cmllczogdHlwZW9mIGNvbmZpZy5tYXhSZXRyaWVzID09PSAnbnVtYmVyJyA/IGNvbmZpZy5tYXhSZXRyaWVzIDogREVGQVVMVF9NQVhfUkVUUklFUyxcbiAgICAgICAgICAgIGZhbGxiYWNrVG9TdGFuZGFyZDogY29uZmlnLmZhbGxiYWNrVG9TdGFuZGFyZCAhPT0gZmFsc2UsXG5cbiAgICAgICAgICAgIC8vIENhY2hpbmdcbiAgICAgICAgICAgIGNhY2hlRGVjaXNpb25zOiBjb25maWcuY2FjaGVEZWNpc2lvbnMgIT09IGZhbHNlLFxuICAgICAgICAgICAgY2FjaGVEdXJhdGlvbjogdHlwZW9mIGNvbmZpZy5jYWNoZUR1cmF0aW9uID09PSAnbnVtYmVyJyA/IGNvbmZpZy5jYWNoZUR1cmF0aW9uIDogREVGQVVMVF9DQUNIRV9EVVJBVElPTixcblxuICAgICAgICAgICAgLy8gSGlzdG9yeVxuICAgICAgICAgICAgaGlzdG9yeUVuYWJsZWQ6IGNvbmZpZy5oaXN0b3J5RW5hYmxlZCAhPT0gZmFsc2UsXG4gICAgICAgICAgICBoaXN0b3J5RGVjYXlSYXRlOiB0eXBlb2YgY29uZmlnLmhpc3RvcnlEZWNheVJhdGUgPT09ICdudW1iZXInID8gY29uZmlnLmhpc3RvcnlEZWNheVJhdGUgOiAwLjksXG4gICAgICAgICAgICBtYXhIaXN0b3J5U2l6ZTogdHlwZW9mIGNvbmZpZy5tYXhIaXN0b3J5U2l6ZSA9PT0gJ251bWJlcicgPyBjb25maWcubWF4SGlzdG9yeVNpemUgOiAxMCxcblxuICAgICAgICAgICAgLy8gQnJhbmQgY29udGV4dCAoZm9yIGdlbmVyYXRlIG1vZGUpXG4gICAgICAgICAgICBicmFuZENvbnRleHQ6IGNvbmZpZy5icmFuZENvbnRleHQgfHwgbnVsbCxcblxuICAgICAgICAgICAgLy8gQ3VzdG9tIHByb21wdHNcbiAgICAgICAgICAgIGN1c3RvbVByb21wdHM6IGNvbmZpZy5jdXN0b21Qcm9tcHRzIHx8IHt9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gQ2FjaGUgTWFuYWdlbWVudFxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgY2FjaGUga2V5IGZyb20gdGhlIGNvbnRleHQgKGhhc2gtbGlrZSBpZGVudGlmaWVyKVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjb250ZXh0IC0gQ3VycmVudCBVVE0gY29udGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtb2RlIC0gJ3NlbGVjdCcgb3IgJ2dlbmVyYXRlJ1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IC0gQ2FjaGUga2V5XG4gICAgICovXG4gICAgZnVuY3Rpb24gYnVpbGRDYWNoZUtleShjb250ZXh0LCBtb2RlKSB7XG4gICAgICAgIHZhciBwYXJ0cyA9IFttb2RlXVxuXG4gICAgICAgIGlmIChjb250ZXh0LnV0bSkge1xuICAgICAgICAgICAgaWYgKGNvbnRleHQudXRtLnV0bV9zb3VyY2UpIHBhcnRzLnB1c2goJ3M6JyArIGNvbnRleHQudXRtLnV0bV9zb3VyY2UpXG4gICAgICAgICAgICBpZiAoY29udGV4dC51dG0udXRtX21lZGl1bSkgcGFydHMucHVzaCgnbTonICsgY29udGV4dC51dG0udXRtX21lZGl1bSlcbiAgICAgICAgICAgIGlmIChjb250ZXh0LnV0bS51dG1fY2FtcGFpZ24pIHBhcnRzLnB1c2goJ2M6JyArIGNvbnRleHQudXRtLnV0bV9jYW1wYWlnbilcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjb250ZXh0LnJlZmVycmVyKSB7XG4gICAgICAgICAgICBwYXJ0cy5wdXNoKCdyOicgKyAoY29udGV4dC5yZWZlcnJlci5zb3VyY2UgfHwgJ2RpcmVjdCcpKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbnRleHQudXNlckFnZW50KSB7XG4gICAgICAgICAgICBwYXJ0cy5wdXNoKCdkOicgKyAoY29udGV4dC51c2VyQWdlbnQuaXNNb2JpbGUgPyAnbW9iJyA6IGNvbnRleHQudXNlckFnZW50LmlzVGFibGV0ID8gJ3RhYicgOiAnZGVzaycpKVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIENBQ0hFX0tFWV9QUkVGSVggKyBwYXJ0cy5qb2luKCdfJylcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWFkIGEgY2FjaGVkIEFJIGRlY2lzaW9uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNhY2hlS2V5IC0gQ2FjaGUga2V5XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGNhY2hlRHVyYXRpb24gLSBNYXggYWdlIGluIG1zXG4gICAgICogQHJldHVybnMge09iamVjdHxudWxsfSAtIENhY2hlZCBkZWNpc2lvbiBvciBudWxsIGlmIGV4cGlyZWQvbWlzc2luZ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlYWRDYWNoZShjYWNoZUtleSwgY2FjaGVEdXJhdGlvbikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBsb2NhbFN0b3JhZ2UgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gbnVsbFxuICAgICAgICAgICAgdmFyIHJhdyA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKGNhY2hlS2V5KVxuICAgICAgICAgICAgaWYgKCFyYXcpIHJldHVybiBudWxsXG5cbiAgICAgICAgICAgIHZhciBjYWNoZWQgPSBKU09OLnBhcnNlKHJhdylcbiAgICAgICAgICAgIGlmICghY2FjaGVkIHx8ICFjYWNoZWQudGltZXN0YW1wIHx8ICFjYWNoZWQuZGVjaXNpb24pIHJldHVybiBudWxsXG5cbiAgICAgICAgICAgIC8vIENoZWNrIGV4cGlyeVxuICAgICAgICAgICAgdmFyIGFnZSA9IERhdGUubm93KCkgLSBjYWNoZWQudGltZXN0YW1wXG4gICAgICAgICAgICBpZiAoYWdlID4gY2FjaGVEdXJhdGlvbikge1xuICAgICAgICAgICAgICAgIGxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKGNhY2hlS2V5KVxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBjYWNoZWQuZGVjaXNpb25cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlIGFuIEFJIGRlY2lzaW9uIHRvIGNhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNhY2hlS2V5IC0gQ2FjaGUga2V5XG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRlY2lzaW9uIC0gRGVjaXNpb24gdG8gY2FjaGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cml0ZUNhY2hlKGNhY2hlS2V5LCBkZWNpc2lvbikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBsb2NhbFN0b3JhZ2UgPT09ICd1bmRlZmluZWQnKSByZXR1cm5cbiAgICAgICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKGNhY2hlS2V5LCBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgIGRlY2lzaW9uOiBkZWNpc2lvblxuICAgICAgICAgICAgfSkpXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignW0x1YSBBSV0gRmFpbGVkIHRvIHdyaXRlIGNhY2hlOicsIGUpXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGVhciBhbGwgQUkgZGVjaXNpb24gY2FjaGVzXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xlYXJDYWNoZSgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbG9jYWxTdG9yYWdlID09PSAndW5kZWZpbmVkJykgcmV0dXJuXG4gICAgICAgICAgICB2YXIga2V5c1RvUmVtb3ZlID0gW11cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbG9jYWxTdG9yYWdlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IGxvY2FsU3RvcmFnZS5rZXkoaSlcbiAgICAgICAgICAgICAgICBpZiAoa2V5ICYmIGtleS5pbmRleE9mKENBQ0hFX0tFWV9QUkVGSVgpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleXNUb1JlbW92ZS5wdXNoKGtleSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGtleXNUb1JlbW92ZS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKGtleXNUb1JlbW92ZVtqXSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIEFJXSBGYWlsZWQgdG8gY2xlYXIgY2FjaGU6JywgZSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBBUEkgQ29tbXVuaWNhdGlvblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIC8qKlxuICAgICAqIENhbGwgdGhlIE9wZW5BSSBBUEkgKGRpcmVjdCBvciB2aWEgcHJveHkpXG4gICAgICogQHBhcmFtIHtBcnJheX0gbWVzc2FnZXMgLSBDaGF0IG1lc3NhZ2VzIGFycmF5XG4gICAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIE5vcm1hbGl6ZWQgQUkgY29uZmlnXG4gICAgICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0Pn0gLSBQYXJzZWQgQUkgcmVzcG9uc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjYWxsT3BlbkFJKG1lc3NhZ2VzLCBjb25maWcpIHtcbiAgICAgICAgdmFyIHVybCA9IGNvbmZpZy51c2VEaXJlY3RBcGkgPyBPUEVOQUlfQkFTRV9VUkwgOiBjb25maWcuYXBpVXJsXG5cbiAgICAgICAgdmFyIGhlYWRlcnMgPSB7XG4gICAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nXG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgQXV0aG9yaXphdGlvbiBoZWFkZXIgZm9yIGRpcmVjdCBBUEkgYWNjZXNzXG4gICAgICAgIGlmIChjb25maWcudXNlRGlyZWN0QXBpICYmIGNvbmZpZy5hcGlLZXkpIHtcbiAgICAgICAgICAgIGhlYWRlcnNbJ0F1dGhvcml6YXRpb24nXSA9ICdCZWFyZXIgJyArIGNvbmZpZy5hcGlLZXlcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBib2R5ID0ge1xuICAgICAgICAgICAgbW9kZWw6IGNvbmZpZy5tb2RlbCxcbiAgICAgICAgICAgIG1lc3NhZ2VzOiBtZXNzYWdlcyxcbiAgICAgICAgICAgIHRlbXBlcmF0dXJlOiBjb25maWcudGVtcGVyYXR1cmUsXG4gICAgICAgICAgICBtYXhfdG9rZW5zOiBjb25maWcubWF4VG9rZW5zLFxuICAgICAgICAgICAgcmVzcG9uc2VfZm9ybWF0OiB7IHR5cGU6ICdqc29uX29iamVjdCcgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3JlYXRlIGFib3J0IGNvbnRyb2xsZXIgZm9yIHRpbWVvdXRcbiAgICAgICAgdmFyIGNvbnRyb2xsZXIgPSBudWxsXG4gICAgICAgIHZhciB0aW1lb3V0SWQgPSBudWxsXG5cbiAgICAgICAgaWYgKHR5cGVvZiBBYm9ydENvbnRyb2xsZXIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpXG4gICAgICAgICAgICB0aW1lb3V0SWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBjb250cm9sbGVyLmFib3J0KClcbiAgICAgICAgICAgIH0sIGNvbmZpZy50aW1lb3V0KVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGZldGNoT3B0aW9ucyA9IHtcbiAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgaGVhZGVyczogaGVhZGVycyxcbiAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KGJvZHkpXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29udHJvbGxlcikge1xuICAgICAgICAgICAgZmV0Y2hPcHRpb25zLnNpZ25hbCA9IGNvbnRyb2xsZXIuc2lnbmFsXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmV0Y2godXJsLCBmZXRjaE9wdGlvbnMpXG4gICAgICAgICAgICAudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICBpZiAodGltZW91dElkKSBjbGVhclRpbWVvdXQodGltZW91dElkKVxuXG4gICAgICAgICAgICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpLnRoZW4oZnVuY3Rpb24gKHRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQVBJIHJlcXVlc3QgZmFpbGVkICgnICsgcmVzcG9uc2Uuc3RhdHVzICsgJyk6ICcgKyB0ZXh0LnN1YnN0cmluZygwLCAyMDApKVxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAvLyBQYXJzZSBPcGVuQUkgcmVzcG9uc2Ugc3RydWN0dXJlXG4gICAgICAgICAgICAgICAgaWYgKGRhdGEgJiYgZGF0YS5jaG9pY2VzICYmIGRhdGEuY2hvaWNlc1swXSAmJiBkYXRhLmNob2ljZXNbMF0ubWVzc2FnZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY29udGVudCA9IGRhdGEuY2hvaWNlc1swXS5tZXNzYWdlLmNvbnRlbnRcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKGNvbnRlbnQpXG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRyeSB0byBleHRyYWN0IEpTT04gZnJvbSBjb250ZW50IGlmIGl0J3Mgd3JhcHBlZCBpbiBtYXJrZG93blxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGpzb25NYXRjaCA9IGNvbnRlbnQubWF0Y2goL1xce1tcXHNcXFNdKlxcfS8pXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoanNvbk1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoanNvbk1hdGNoWzBdKVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gcGFyc2UgQUkgcmVzcG9uc2UgYXMgSlNPTjogJyArIGNvbnRlbnQuc3Vic3RyaW5nKDAsIDIwMCkpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgcmVzcG9uc2UgSVMgdGhlIHBhcnNlZCBjb250ZW50IChwcm94eSBtaWdodCBmb3J3YXJkIGRpZmZlcmVudGx5KVxuICAgICAgICAgICAgICAgIGlmIChkYXRhICYmIChkYXRhLnNlbGVjdGVkVmFyaWFudCB8fCBkYXRhLmhlYWRsaW5lKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0YVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5leHBlY3RlZCBBUEkgcmVzcG9uc2Ugc3RydWN0dXJlJylcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRpbWVvdXRJZCkgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZClcblxuICAgICAgICAgICAgICAgIGlmIChlcnJvci5uYW1lID09PSAnQWJvcnRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBSSByZXF1ZXN0IHRpbWVkIG91dCBhZnRlciAnICsgY29uZmlnLnRpbWVvdXQgKyAnbXMnKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aHJvdyBlcnJvclxuICAgICAgICAgICAgfSlcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxsIE9wZW5BSSB3aXRoIHJldHJ5IGxvZ2ljXG4gICAgICogQHBhcmFtIHtBcnJheX0gbWVzc2FnZXMgLSBDaGF0IG1lc3NhZ2VzXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIE5vcm1hbGl6ZWQgY29uZmlnXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthdHRlbXB0XSAtIEN1cnJlbnQgYXR0ZW1wdCBudW1iZXJcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxPYmplY3Q+fSAtIFBhcnNlZCBBSSByZXNwb25zZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhbGxXaXRoUmV0cnkobWVzc2FnZXMsIGNvbmZpZywgYXR0ZW1wdCkge1xuICAgICAgICBhdHRlbXB0ID0gYXR0ZW1wdCB8fCAwXG5cbiAgICAgICAgcmV0dXJuIGNhbGxPcGVuQUkobWVzc2FnZXMsIGNvbmZpZykuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICBpZiAoYXR0ZW1wdCA8IGNvbmZpZy5tYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIEFJXSBSZXRyeSBhdHRlbXB0ICcgKyAoYXR0ZW1wdCArIDEpICsgJzonLCBlcnJvci5tZXNzYWdlKVxuICAgICAgICAgICAgICAgIC8vIEV4cG9uZW50aWFsIGJhY2tvZmY6IDUwMG1zLCAxMDAwbXMsIDIwMDBtcy4uLlxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoY2FsbFdpdGhSZXRyeShtZXNzYWdlcywgY29uZmlnLCBhdHRlbXB0ICsgMSkpXG4gICAgICAgICAgICAgICAgICAgIH0sIDUwMCAqIE1hdGgucG93KDIsIGF0dGVtcHQpKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBlcnJvclxuICAgICAgICB9KVxuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBSZXNwb25zZSBWYWxpZGF0aW9uXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgLyoqXG4gICAgICogVmFsaWRhdGUgYSBTRUxFQ1RJT04gbW9kZSByZXNwb25zZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSByZXNwb25zZSAtIFBhcnNlZCBBSSByZXNwb25zZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB2YXJpYW50cyAtIEF2YWlsYWJsZSB2YXJpYW50cyAodG8gdmFsaWRhdGUga2V5IGV4aXN0cylcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSAtIHsgdmFsaWQ6IGJvb2xlYW4sIGVycm9yPzogc3RyaW5nIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB2YWxpZGF0ZVNlbGVjdFJlc3BvbnNlKHJlc3BvbnNlLCB2YXJpYW50cykge1xuICAgICAgICBpZiAoIXJlc3BvbnNlIHx8IHR5cGVvZiByZXNwb25zZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSwgZXJyb3I6ICdSZXNwb25zZSBpcyBub3QgYW4gb2JqZWN0JyB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXJlc3BvbnNlLnNlbGVjdGVkVmFyaWFudCB8fCB0eXBlb2YgcmVzcG9uc2Uuc2VsZWN0ZWRWYXJpYW50ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIHsgdmFsaWQ6IGZhbHNlLCBlcnJvcjogJ01pc3Npbmcgb3IgaW52YWxpZCBcInNlbGVjdGVkVmFyaWFudFwiIGZpZWxkJyB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayB0aGF0IHRoZSBzZWxlY3RlZCB2YXJpYW50IGFjdHVhbGx5IGV4aXN0c1xuICAgICAgICBpZiAoIXZhcmlhbnRzW3Jlc3BvbnNlLnNlbGVjdGVkVmFyaWFudF0pIHtcbiAgICAgICAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSwgZXJyb3I6ICdTZWxlY3RlZCB2YXJpYW50IFwiJyArIHJlc3BvbnNlLnNlbGVjdGVkVmFyaWFudCArICdcIiBkb2VzIG5vdCBleGlzdCBpbiB0ZW1wbGF0ZXMnIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IHZhbGlkOiB0cnVlIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBWYWxpZGF0ZSBhIEdFTkVSQVRJT04gbW9kZSByZXNwb25zZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSByZXNwb25zZSAtIFBhcnNlZCBBSSByZXNwb25zZVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IC0geyB2YWxpZDogYm9vbGVhbiwgZXJyb3I/OiBzdHJpbmcgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHZhbGlkYXRlR2VuZXJhdGVSZXNwb25zZShyZXNwb25zZSkge1xuICAgICAgICBpZiAoIXJlc3BvbnNlIHx8IHR5cGVvZiByZXNwb25zZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSwgZXJyb3I6ICdSZXNwb25zZSBpcyBub3QgYW4gb2JqZWN0JyB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXJlc3BvbnNlLmhlYWRsaW5lIHx8IHR5cGVvZiByZXNwb25zZS5oZWFkbGluZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSwgZXJyb3I6ICdNaXNzaW5nIG9yIGludmFsaWQgXCJoZWFkbGluZVwiIGZpZWxkJyB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXJlc3BvbnNlLnN1YmhlYWRsaW5lIHx8IHR5cGVvZiByZXNwb25zZS5zdWJoZWFkbGluZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSwgZXJyb3I6ICdNaXNzaW5nIG9yIGludmFsaWQgXCJzdWJoZWFkbGluZVwiIGZpZWxkJyB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXJlc3BvbnNlLmN0YUxhYmVsIHx8IHR5cGVvZiByZXNwb25zZS5jdGFMYWJlbCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSwgZXJyb3I6ICdNaXNzaW5nIG9yIGludmFsaWQgXCJjdGFMYWJlbFwiIGZpZWxkJyB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSB9XG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIEFJIERlY2lzaW9uIEVuZ2luZVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIC8qKlxuICAgICAqIE1haW4gQUkgZGVjaXNpb24gZnVuY3Rpb25cbiAgICAgKiBHYXRoZXJzIGNvbnRleHQsIGJ1aWxkcyBwcm9tcHRzLCBjYWxscyBBUEksIHZhbGlkYXRlcyByZXNwb25zZVxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGNvbnRleHQgLSBDdXJyZW50IFVUTS9yZWZlcnJlci9kZXZpY2UgY29udGV4dFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gRnVsbCBvcHRpb25zIG9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zLnRlbXBsYXRlcyAtIFVzZXItcHJvdmlkZWQgdGVtcGxhdGVzIChSRVFVSVJFRClcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucy5haUNvbmZpZyAtIEFJIGNvbmZpZ3VyYXRpb24gKFJFUVVJUkVEKVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMubG9nXSAtIEVuYWJsZSBsb2dnaW5nIChkZWZhdWx0OiB0cnVlKVxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPE9iamVjdD59IC0gRGVjaXNpb24gcmVzdWx0IHsgdGVtcGxhdGUsIGludGVudCwgc291cmNlLCBjb250ZXh0LCBhaVJlc3BvbnNlIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhaURlY2lkZShjb250ZXh0LCBvcHRpb25zKSB7XG4gICAgICAgIHZhciBjb25maWcgPSBub3JtYWxpemVDb25maWcob3B0aW9ucy5haUNvbmZpZylcblxuICAgICAgICBpZiAoIWNvbmZpZy52YWxpZCkge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcignW0x1YSBBSV0gJyArIGNvbmZpZy5lcnJvcikpXG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdGVtcGxhdGVzID0gb3B0aW9ucy50ZW1wbGF0ZXMgfHwge31cbiAgICAgICAgdmFyIGxvZyA9IG9wdGlvbnMubG9nICE9PSBmYWxzZVxuXG4gICAgICAgIC8vIENoZWNrIGNhY2hlIGZpcnN0XG4gICAgICAgIGlmIChjb25maWcuY2FjaGVEZWNpc2lvbnMpIHtcbiAgICAgICAgICAgIHZhciBjYWNoZUtleSA9IGJ1aWxkQ2FjaGVLZXkoY29udGV4dCwgY29uZmlnLm1vZGUpXG4gICAgICAgICAgICB2YXIgY2FjaGVkID0gcmVhZENhY2hlKGNhY2hlS2V5LCBjb25maWcuY2FjaGVEdXJhdGlvbilcbiAgICAgICAgICAgIGlmIChjYWNoZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAobG9nKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdbTHVhIEFJXSBVc2luZyBjYWNoZWQgZGVjaXNpb246JywgY2FjaGVkLmludGVudClcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FjaGVkLnNvdXJjZSA9ICdhaS1jYWNoZWQnXG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShjYWNoZWQpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBHZXQgd2VpZ2h0ZWQgaGlzdG9yeVxuICAgICAgICB2YXIgSGlzdG9yeU1vZHVsZSA9IHJvb3QuTHVhV2VpZ2h0ZWRIaXN0b3J5XG4gICAgICAgIHZhciB3ZWlnaHRlZEhpc3RvcnkgPSAnJ1xuICAgICAgICB2YXIgcHJlZmVyZW5jZXMgPSB7fVxuICAgICAgICB2YXIgaGlzdG9yeSA9IG51bGxcblxuICAgICAgICBpZiAoY29uZmlnLmhpc3RvcnlFbmFibGVkICYmIEhpc3RvcnlNb2R1bGUpIHtcbiAgICAgICAgICAgIGhpc3RvcnkgPSBIaXN0b3J5TW9kdWxlLmdldEhpc3RvcnkoKVxuICAgICAgICAgICAgdmFyIHdlaWdodGVkID0gSGlzdG9yeU1vZHVsZS5idWlsZFdlaWdodGVkQ29udGV4dChoaXN0b3J5LCB7XG4gICAgICAgICAgICAgICAgZGVjYXlSYXRlOiBjb25maWcuaGlzdG9yeURlY2F5UmF0ZVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIHByZWZlcmVuY2VzID0gSGlzdG9yeU1vZHVsZS5hZ2dyZWdhdGVQcmVmZXJlbmNlcyh3ZWlnaHRlZClcbiAgICAgICAgICAgIHdlaWdodGVkSGlzdG9yeSA9IEhpc3RvcnlNb2R1bGUuZm9ybWF0Rm9yUHJvbXB0KHdlaWdodGVkKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gR2V0IHByb21wdCBtb2R1bGVcbiAgICAgICAgdmFyIFByb21wdHNNb2R1bGUgPSByb290Lkx1YVByb21wdHNcblxuICAgICAgICBpZiAoIVByb21wdHNNb2R1bGUpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1tMdWEgQUldIEx1YVByb21wdHMgbW9kdWxlIG5vdCBsb2FkZWQuIEluY2x1ZGUgcHJvbXB0cy9wZXJzb25hbGl6YXRpb24tcHJvbXB0cy5qcycpKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQnVpbGQgcHJvbXB0IHBhcmFtZXRlcnNcbiAgICAgICAgdmFyIHByb21wdFBhcmFtcyA9IHtcbiAgICAgICAgICAgIGNvbnRleHQ6IGNvbnRleHQsXG4gICAgICAgICAgICB3ZWlnaHRlZEhpc3Rvcnk6IHdlaWdodGVkSGlzdG9yeSxcbiAgICAgICAgICAgIHByZWZlcmVuY2VzOiBwcmVmZXJlbmNlc1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbmZpZy5tb2RlID09PSAnc2VsZWN0Jykge1xuICAgICAgICAgICAgcHJvbXB0UGFyYW1zLnZhcmlhbnRzID0gdGVtcGxhdGVzXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBHZW5lcmF0ZSBtb2RlXG4gICAgICAgICAgICBwcm9tcHRQYXJhbXMuYnJhbmRDb250ZXh0ID0gY29uZmlnLmJyYW5kQ29udGV4dFxuICAgICAgICAgICAgcHJvbXB0UGFyYW1zLmZhbGxiYWNrVGVtcGxhdGUgPSB0ZW1wbGF0ZXNbJ2RlZmF1bHQnXSB8fCB0ZW1wbGF0ZXNbT2JqZWN0LmtleXModGVtcGxhdGVzKVswXV0gfHwgbnVsbFxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQnVpbGQgbWVzc2FnZXNcbiAgICAgICAgdmFyIG1lc3NhZ2VzID0gUHJvbXB0c01vZHVsZS5idWlsZE1lc3NhZ2VzKGNvbmZpZy5tb2RlLCBwcm9tcHRQYXJhbXMsIGNvbmZpZy5jdXN0b21Qcm9tcHRzKVxuXG4gICAgICAgIHZhciBzdGFydFRpbWUgPSBEYXRlLm5vdygpXG5cbiAgICAgICAgLy8gQ2FsbCBBSVxuICAgICAgICByZXR1cm4gY2FsbFdpdGhSZXRyeShtZXNzYWdlcywgY29uZmlnKS50aGVuKGZ1bmN0aW9uIChhaVJlc3BvbnNlKSB7XG4gICAgICAgICAgICB2YXIgbGF0ZW5jeSA9IERhdGUubm93KCkgLSBzdGFydFRpbWVcbiAgICAgICAgICAgIHZhciBkZWNpc2lvblxuXG4gICAgICAgICAgICBpZiAoY29uZmlnLm1vZGUgPT09ICdzZWxlY3QnKSB7XG4gICAgICAgICAgICAgICAgLy8gVmFsaWRhdGUgc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgdmFyIHNlbGVjdFZhbGlkYXRpb24gPSB2YWxpZGF0ZVNlbGVjdFJlc3BvbnNlKGFpUmVzcG9uc2UsIHRlbXBsYXRlcylcbiAgICAgICAgICAgICAgICBpZiAoIXNlbGVjdFZhbGlkYXRpb24udmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIEFJIHNlbGVjdGlvbjogJyArIHNlbGVjdFZhbGlkYXRpb24uZXJyb3IpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVjaXNpb24gPSB7XG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlOiB0ZW1wbGF0ZXNbYWlSZXNwb25zZS5zZWxlY3RlZFZhcmlhbnRdLFxuICAgICAgICAgICAgICAgICAgICBpbnRlbnQ6IGFpUmVzcG9uc2Uuc2VsZWN0ZWRWYXJpYW50LFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2U6ICdhaScsXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQ6IGNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgIGFpUmVzcG9uc2U6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZGVuY2U6IGFpUmVzcG9uc2UuY29uZmlkZW5jZSB8fCBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uaW5nOiBhaVJlc3BvbnNlLnJlYXNvbmluZyB8fCBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGF0ZW5jeTogbGF0ZW5jeSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsOiBjb25maWcubW9kZWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RlOiAnc2VsZWN0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlZDogZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gVmFsaWRhdGUgZ2VuZXJhdGlvblxuICAgICAgICAgICAgICAgIHZhciBnZW5WYWxpZGF0aW9uID0gdmFsaWRhdGVHZW5lcmF0ZVJlc3BvbnNlKGFpUmVzcG9uc2UpXG4gICAgICAgICAgICAgICAgaWYgKCFnZW5WYWxpZGF0aW9uLnZhbGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBBSSBnZW5lcmF0aW9uOiAnICsgZ2VuVmFsaWRhdGlvbi5lcnJvcilcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBCdWlsZCBhIHRlbXBsYXRlIGZyb20gZ2VuZXJhdGVkIGNvbnRlbnRcbiAgICAgICAgICAgICAgICB2YXIgZ2VuZXJhdGVkVGVtcGxhdGUgPSB7XG4gICAgICAgICAgICAgICAgICAgIGhlYWRsaW5lOiBhaVJlc3BvbnNlLmhlYWRsaW5lLFxuICAgICAgICAgICAgICAgICAgICBzdWJoZWFkbGluZTogYWlSZXNwb25zZS5zdWJoZWFkbGluZSxcbiAgICAgICAgICAgICAgICAgICAgY3RhTGFiZWw6IGFpUmVzcG9uc2UuY3RhTGFiZWwsXG4gICAgICAgICAgICAgICAgICAgIGN0YUxpbms6ICh0ZW1wbGF0ZXNbJ2RlZmF1bHQnXSAmJiB0ZW1wbGF0ZXNbJ2RlZmF1bHQnXS5jdGFMaW5rKSB8fCAnL3Nob3AnLFxuICAgICAgICAgICAgICAgICAgICBpbWFnZTogKHRlbXBsYXRlc1snZGVmYXVsdCddICYmIHRlbXBsYXRlc1snZGVmYXVsdCddLmltYWdlKSB8fCBudWxsXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVjaXNpb24gPSB7XG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlOiBnZW5lcmF0ZWRUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgaW50ZW50OiAnYWktZ2VuZXJhdGVkJyxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlOiAnYWknLFxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0OiBjb250ZXh0LFxuICAgICAgICAgICAgICAgICAgICBhaVJlc3BvbnNlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25maWRlbmNlOiBhaVJlc3BvbnNlLmNvbmZpZGVuY2UgfHwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbmluZzogYWlSZXNwb25zZS5yZWFzb25pbmcgfHwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhdGVuY3k6IGxhdGVuY3ksXG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RlbDogY29uZmlnLm1vZGVsLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW9kZTogJ2dlbmVyYXRlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlZDogZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2FjaGUgdGhlIGRlY2lzaW9uXG4gICAgICAgICAgICBpZiAoY29uZmlnLmNhY2hlRGVjaXNpb25zKSB7XG4gICAgICAgICAgICAgICAgd3JpdGVDYWNoZShidWlsZENhY2hlS2V5KGNvbnRleHQsIGNvbmZpZy5tb2RlKSwgZGVjaXNpb24pXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJlY29yZCB2aXNpdCB0byBoaXN0b3J5XG4gICAgICAgICAgICBpZiAoY29uZmlnLmhpc3RvcnlFbmFibGVkICYmIEhpc3RvcnlNb2R1bGUpIHtcbiAgICAgICAgICAgICAgICBIaXN0b3J5TW9kdWxlLnJlY29yZFZpc2l0KHtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dDogY29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgaW50ZW50OiBkZWNpc2lvbi5pbnRlbnQsXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkVmFyaWFudDogZGVjaXNpb24uaW50ZW50LFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2U6ICdhaScsXG4gICAgICAgICAgICAgICAgICAgIGFpRGVjaXNpb246IHRydWVcbiAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgIG1heEhpc3RvcnlTaXplOiBjb25maWcubWF4SGlzdG9yeVNpemVcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobG9nKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1tMdWEgQUldIERlY2lzaW9uIG1hZGU6Jywge1xuICAgICAgICAgICAgICAgICAgICBtb2RlOiBjb25maWcubW9kZSxcbiAgICAgICAgICAgICAgICAgICAgaW50ZW50OiBkZWNpc2lvbi5pbnRlbnQsXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZTogJ2FpJyxcbiAgICAgICAgICAgICAgICAgICAgY29uZmlkZW5jZTogZGVjaXNpb24uYWlSZXNwb25zZS5jb25maWRlbmNlLFxuICAgICAgICAgICAgICAgICAgICBsYXRlbmN5OiBsYXRlbmN5ICsgJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgbW9kZWw6IGNvbmZpZy5tb2RlbFxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBkZWNpc2lvblxuXG4gICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgdmFyIGxhdGVuY3kgPSBEYXRlLm5vdygpIC0gc3RhcnRUaW1lXG5cbiAgICAgICAgICAgIGlmIChsb2cpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tMdWEgQUldIEVycm9yIGFmdGVyICcgKyBsYXRlbmN5ICsgJ21zOicsIGVycm9yLm1lc3NhZ2UpXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRocm93IGVycm9yXG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIEludGVncmF0aW9uIEhlbHBlcnNcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICAvKipcbiAgICAgKiBIaWdoLWxldmVsIEFJIHBlcnNvbmFsaXplIGZ1bmN0aW9uXG4gICAgICogV3JhcHMgYWlEZWNpZGUgd2l0aCBmdWxsIGNvbnRleHQgZ2F0aGVyaW5nIGFuZCBET00gYXBwbGljYXRpb25cbiAgICAgKiBEZXNpZ25lZCB0byBiZSBjYWxsZWQgZnJvbSB0aGUgbWFpbiBwZXJzb25hbGl6ZSgpIGZ1bmN0aW9uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIEZ1bGwgcGVyc29uYWxpemF0aW9uIG9wdGlvbnNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucy50ZW1wbGF0ZXMgLSBVc2VyIHRlbXBsYXRlcyAoUkVRVUlSRUQpXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMuYWlDb25maWcgLSBBSSBjb25maWd1cmF0aW9uIChSRVFVSVJFRClcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuY29udGV4dF0gLSBQcmUtY29tcHV0ZWQgY29udGV4dFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMubG9nXSAtIEVuYWJsZSBsb2dnaW5nXG4gICAgICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0Pn0gLSBEZWNpc2lvbiByZXN1bHRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwZXJzb25hbGl6ZVdpdGhBSShvcHRpb25zKSB7XG4gICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG5cbiAgICAgICAgLy8gR2V0IGNvbnRleHRcbiAgICAgICAgdmFyIGNvbnRleHQgPSBvcHRpb25zLmNvbnRleHRcblxuICAgICAgICBpZiAoIWNvbnRleHQpIHtcbiAgICAgICAgICAgIC8vIFRyeSB0byBnZXQgY29udGV4dCBmcm9tIFVUTSBtb2R1bGVzXG4gICAgICAgICAgICB2YXIgdXRtTW9kdWxlID0gcm9vdC5MdWFVVE1QZXJzb25hbGl6ZSB8fCByb290Lkx1YVVUTVxuICAgICAgICAgICAgaWYgKHV0bU1vZHVsZSAmJiB0eXBlb2YgdXRtTW9kdWxlLmdldENvbnRleHQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBjb250ZXh0ID0gdXRtTW9kdWxlLmdldENvbnRleHQoKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb250ZXh0ID0ge1xuICAgICAgICAgICAgICAgICAgICB1dG06IHt9LFxuICAgICAgICAgICAgICAgICAgICByZWZlcnJlcjogeyBzb3VyY2U6ICdkaXJlY3QnLCBjYXRlZ29yeTogJ2RpcmVjdCcsIHVybDogJycgfSxcbiAgICAgICAgICAgICAgICAgICAgdXNlckFnZW50OiB7IHJhdzogJycsIGlzTW9iaWxlOiBmYWxzZSwgaXNUYWJsZXQ6IGZhbHNlLCBpc0Rlc2t0b3A6IHRydWUgfSxcbiAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgICAgICBoYXNVVE06IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBwcmltYXJ5SW50ZW50OiAnZGVmYXVsdCdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYWlEZWNpZGUoY29udGV4dCwgb3B0aW9ucylcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBRdWljayBjaGVjazogaXMgQUkgcHJvcGVybHkgY29uZmlndXJlZCBhbmQgcmVhZHk/XG4gICAgICogQHBhcmFtIHtPYmplY3R9IGFpQ29uZmlnIC0gQUkgY29uZmlnIHRvIGNoZWNrXG4gICAgICogQHJldHVybnMge09iamVjdH0gLSB7IHJlYWR5OiBib29sZWFuLCBlcnJvcj86IHN0cmluZyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNSZWFkeShhaUNvbmZpZykge1xuICAgICAgICB2YXIgY29uZmlnID0gbm9ybWFsaXplQ29uZmlnKGFpQ29uZmlnKVxuICAgICAgICBpZiAoIWNvbmZpZy52YWxpZCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgcmVhZHk6IGZhbHNlLCBlcnJvcjogY29uZmlnLmVycm9yIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGRlcGVuZGVuY2llc1xuICAgICAgICBpZiAoIXJvb3QuTHVhUHJvbXB0cykge1xuICAgICAgICAgICAgcmV0dXJuIHsgcmVhZHk6IGZhbHNlLCBlcnJvcjogJ0x1YVByb21wdHMgbW9kdWxlIG5vdCBsb2FkZWQnIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEhpc3RvcnkgaXMgb3B0aW9uYWwgYnV0IHJlY29tbWVuZGVkXG4gICAgICAgIGlmICghcm9vdC5MdWFXZWlnaHRlZEhpc3RvcnkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignW0x1YSBBSV0gTHVhV2VpZ2h0ZWRIaXN0b3J5IG5vdCBsb2FkZWQuIEhpc3RvcnkgZmVhdHVyZXMgZGlzYWJsZWQuJylcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IHJlYWR5OiB0cnVlIH1cbiAgICB9XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gUHVibGljIEFQSVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIHZhciBMdWFBSVBlcnNvbmFsaXplID0ge1xuICAgICAgICAvLyBDb3JlXG4gICAgICAgIGRlY2lkZTogYWlEZWNpZGUsXG4gICAgICAgIHBlcnNvbmFsaXplV2l0aEFJOiBwZXJzb25hbGl6ZVdpdGhBSSxcbiAgICAgICAgaXNSZWFkeTogaXNSZWFkeSxcblxuICAgICAgICAvLyBDb25maWd1cmF0aW9uXG4gICAgICAgIG5vcm1hbGl6ZUNvbmZpZzogbm9ybWFsaXplQ29uZmlnLFxuXG4gICAgICAgIC8vIEFQSSBjb21tdW5pY2F0aW9uXG4gICAgICAgIGNhbGxPcGVuQUk6IGNhbGxPcGVuQUksXG5cbiAgICAgICAgLy8gVmFsaWRhdGlvblxuICAgICAgICB2YWxpZGF0ZVNlbGVjdFJlc3BvbnNlOiB2YWxpZGF0ZVNlbGVjdFJlc3BvbnNlLFxuICAgICAgICB2YWxpZGF0ZUdlbmVyYXRlUmVzcG9uc2U6IHZhbGlkYXRlR2VuZXJhdGVSZXNwb25zZSxcblxuICAgICAgICAvLyBDYWNoZVxuICAgICAgICBjbGVhckNhY2hlOiBjbGVhckNhY2hlLFxuXG4gICAgICAgIC8vIENvbnN0YW50c1xuICAgICAgICBPUEVOQUlfQkFTRV9VUkw6IE9QRU5BSV9CQVNFX1VSTCxcbiAgICAgICAgREVGQVVMVF9NT0RFTDogREVGQVVMVF9NT0RFTCxcbiAgICAgICAgREVGQVVMVF9USU1FT1VUOiBERUZBVUxUX1RJTUVPVVQsXG4gICAgICAgIERFRkFVTFRfQ0FDSEVfRFVSQVRJT046IERFRkFVTFRfQ0FDSEVfRFVSQVRJT05cbiAgICB9XG5cbiAgICAvLyBSZWdpc3RlciBnbG9iYWxseVxuICAgIHJvb3QuTHVhQUlQZXJzb25hbGl6ZSA9IEx1YUFJUGVyc29uYWxpemVcblxufSkodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6IHRoaXMpXG4iXSwibWFwcGluZ3MiOiI7Ozs7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUMsQ0FBQyxVQUFVQSxJQUFJLEVBQUU7RUFDZCxZQUFZOztFQUVaO0VBQ0E7RUFDQTtFQUVBLElBQUlDLGVBQWUsR0FBRyw0Q0FBNEM7RUFDbEUsSUFBSUMsYUFBYSxHQUFHLGFBQWE7RUFDakMsSUFBSUMsZUFBZSxHQUFHLElBQUk7RUFDMUIsSUFBSUMsa0JBQWtCLEdBQUcsR0FBRztFQUM1QixJQUFJQyxtQkFBbUIsR0FBRyxHQUFHO0VBQzdCLElBQUlDLG1CQUFtQixHQUFHLENBQUM7RUFDM0IsSUFBSUMsZ0JBQWdCLEdBQUcsZUFBZTtFQUN0QyxJQUFJQyxzQkFBc0IsR0FBRyxPQUFPLEVBQUM7O0VBRXJDO0VBQ0E7RUFDQTs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBU0MsZUFBZUEsQ0FBQ0MsTUFBTSxFQUFFO0lBQzdCLElBQUksQ0FBQ0EsTUFBTSxJQUFJLElBQUFDLFFBQUEsQ0FBQUMsT0FBQSxFQUFPRixNQUFNLE1BQUssUUFBUSxFQUFFO01BQ3ZDLE9BQU87UUFBRUcsS0FBSyxFQUFFLEtBQUs7UUFBRUMsS0FBSyxFQUFFO01BQThCLENBQUM7SUFDakU7O0lBRUE7SUFDQSxJQUFJQyxTQUFTLEdBQUcsT0FBT0wsTUFBTSxDQUFDTSxNQUFNLEtBQUssUUFBUSxJQUFJTixNQUFNLENBQUNNLE1BQU0sQ0FBQ0MsSUFBSSxDQUFDLENBQUMsQ0FBQ0MsTUFBTSxHQUFHLENBQUM7SUFDcEYsSUFBSUMsU0FBUyxHQUFHLE9BQU9ULE1BQU0sQ0FBQ1UsTUFBTSxLQUFLLFFBQVEsSUFBSVYsTUFBTSxDQUFDVSxNQUFNLENBQUNILElBQUksQ0FBQyxDQUFDLENBQUNDLE1BQU0sR0FBRyxDQUFDO0lBRXBGLElBQUksQ0FBQ0gsU0FBUyxJQUFJLENBQUNJLFNBQVMsRUFBRTtNQUMxQixPQUFPO1FBQ0hOLEtBQUssRUFBRSxLQUFLO1FBQ1pDLEtBQUssRUFBRTtNQUNYLENBQUM7SUFDTDtJQUVBLE9BQU87TUFDSEQsS0FBSyxFQUFFLElBQUk7TUFFWDtNQUNBRyxNQUFNLEVBQUVELFNBQVMsR0FBR0wsTUFBTSxDQUFDTSxNQUFNLENBQUNDLElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSTtNQUMvQ0csTUFBTSxFQUFFRCxTQUFTLEdBQUdULE1BQU0sQ0FBQ1UsTUFBTSxDQUFDSCxJQUFJLENBQUMsQ0FBQyxHQUFHaEIsZUFBZTtNQUMxRG9CLFlBQVksRUFBRU4sU0FBUyxJQUFJLENBQUNJLFNBQVM7TUFFckM7TUFDQUcsS0FBSyxFQUFFWixNQUFNLENBQUNZLEtBQUssSUFBSXBCLGFBQWE7TUFDcENxQixXQUFXLEVBQUUsT0FBT2IsTUFBTSxDQUFDYSxXQUFXLEtBQUssUUFBUSxHQUFHYixNQUFNLENBQUNhLFdBQVcsR0FBR2xCLG1CQUFtQjtNQUM5Rm1CLFNBQVMsRUFBRSxPQUFPZCxNQUFNLENBQUNjLFNBQVMsS0FBSyxRQUFRLEdBQUdkLE1BQU0sQ0FBQ2MsU0FBUyxHQUFHcEIsa0JBQWtCO01BRXZGO01BQ0FxQixJQUFJLEVBQUVmLE1BQU0sQ0FBQ2UsSUFBSSxLQUFLLFVBQVUsR0FBRyxVQUFVLEdBQUcsUUFBUTtNQUN4REMsT0FBTyxFQUFFLE9BQU9oQixNQUFNLENBQUNnQixPQUFPLEtBQUssUUFBUSxHQUFHaEIsTUFBTSxDQUFDZ0IsT0FBTyxHQUFHdkIsZUFBZTtNQUM5RXdCLFVBQVUsRUFBRSxPQUFPakIsTUFBTSxDQUFDaUIsVUFBVSxLQUFLLFFBQVEsR0FBR2pCLE1BQU0sQ0FBQ2lCLFVBQVUsR0FBR3JCLG1CQUFtQjtNQUMzRnNCLGtCQUFrQixFQUFFbEIsTUFBTSxDQUFDa0Isa0JBQWtCLEtBQUssS0FBSztNQUV2RDtNQUNBQyxjQUFjLEVBQUVuQixNQUFNLENBQUNtQixjQUFjLEtBQUssS0FBSztNQUMvQ0MsYUFBYSxFQUFFLE9BQU9wQixNQUFNLENBQUNvQixhQUFhLEtBQUssUUFBUSxHQUFHcEIsTUFBTSxDQUFDb0IsYUFBYSxHQUFHdEIsc0JBQXNCO01BRXZHO01BQ0F1QixjQUFjLEVBQUVyQixNQUFNLENBQUNxQixjQUFjLEtBQUssS0FBSztNQUMvQ0MsZ0JBQWdCLEVBQUUsT0FBT3RCLE1BQU0sQ0FBQ3NCLGdCQUFnQixLQUFLLFFBQVEsR0FBR3RCLE1BQU0sQ0FBQ3NCLGdCQUFnQixHQUFHLEdBQUc7TUFDN0ZDLGNBQWMsRUFBRSxPQUFPdkIsTUFBTSxDQUFDdUIsY0FBYyxLQUFLLFFBQVEsR0FBR3ZCLE1BQU0sQ0FBQ3VCLGNBQWMsR0FBRyxFQUFFO01BRXRGO01BQ0FDLFlBQVksRUFBRXhCLE1BQU0sQ0FBQ3dCLFlBQVksSUFBSSxJQUFJO01BRXpDO01BQ0FDLGFBQWEsRUFBRXpCLE1BQU0sQ0FBQ3lCLGFBQWEsSUFBSSxDQUFDO0lBQzVDLENBQUM7RUFDTDs7RUFFQTtFQUNBO0VBQ0E7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBU0MsYUFBYUEsQ0FBQ0MsT0FBTyxFQUFFWixJQUFJLEVBQUU7SUFDbEMsSUFBSWEsS0FBSyxHQUFHLENBQUNiLElBQUksQ0FBQztJQUVsQixJQUFJWSxPQUFPLENBQUNFLEdBQUcsRUFBRTtNQUNiLElBQUlGLE9BQU8sQ0FBQ0UsR0FBRyxDQUFDQyxVQUFVLEVBQUVGLEtBQUssQ0FBQ0csSUFBSSxDQUFDLElBQUksR0FBR0osT0FBTyxDQUFDRSxHQUFHLENBQUNDLFVBQVUsQ0FBQztNQUNyRSxJQUFJSCxPQUFPLENBQUNFLEdBQUcsQ0FBQ0csVUFBVSxFQUFFSixLQUFLLENBQUNHLElBQUksQ0FBQyxJQUFJLEdBQUdKLE9BQU8sQ0FBQ0UsR0FBRyxDQUFDRyxVQUFVLENBQUM7TUFDckUsSUFBSUwsT0FBTyxDQUFDRSxHQUFHLENBQUNJLFlBQVksRUFBRUwsS0FBSyxDQUFDRyxJQUFJLENBQUMsSUFBSSxHQUFHSixPQUFPLENBQUNFLEdBQUcsQ0FBQ0ksWUFBWSxDQUFDO0lBQzdFO0lBRUEsSUFBSU4sT0FBTyxDQUFDTyxRQUFRLEVBQUU7TUFDbEJOLEtBQUssQ0FBQ0csSUFBSSxDQUFDLElBQUksSUFBSUosT0FBTyxDQUFDTyxRQUFRLENBQUNDLE1BQU0sSUFBSSxRQUFRLENBQUMsQ0FBQztJQUM1RDtJQUVBLElBQUlSLE9BQU8sQ0FBQ1MsU0FBUyxFQUFFO01BQ25CUixLQUFLLENBQUNHLElBQUksQ0FBQyxJQUFJLElBQUlKLE9BQU8sQ0FBQ1MsU0FBUyxDQUFDQyxRQUFRLEdBQUcsS0FBSyxHQUFHVixPQUFPLENBQUNTLFNBQVMsQ0FBQ0UsUUFBUSxHQUFHLEtBQUssR0FBRyxNQUFNLENBQUMsQ0FBQztJQUN6RztJQUVBLE9BQU96QyxnQkFBZ0IsR0FBRytCLEtBQUssQ0FBQ1csSUFBSSxDQUFDLEdBQUcsQ0FBQztFQUM3Qzs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxTQUFTQyxTQUFTQSxDQUFDQyxRQUFRLEVBQUVyQixhQUFhLEVBQUU7SUFDeEMsSUFBSTtNQUNBLElBQUksT0FBT3NCLFlBQVksS0FBSyxXQUFXLEVBQUUsT0FBTyxJQUFJO01BQ3BELElBQUlDLEdBQUcsR0FBR0QsWUFBWSxDQUFDRSxPQUFPLENBQUNILFFBQVEsQ0FBQztNQUN4QyxJQUFJLENBQUNFLEdBQUcsRUFBRSxPQUFPLElBQUk7TUFFckIsSUFBSUUsTUFBTSxHQUFHQyxJQUFJLENBQUNDLEtBQUssQ0FBQ0osR0FBRyxDQUFDO01BQzVCLElBQUksQ0FBQ0UsTUFBTSxJQUFJLENBQUNBLE1BQU0sQ0FBQ0csU0FBUyxJQUFJLENBQUNILE1BQU0sQ0FBQ0ksUUFBUSxFQUFFLE9BQU8sSUFBSTs7TUFFakU7TUFDQSxJQUFJQyxHQUFHLEdBQUdDLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUMsR0FBR1AsTUFBTSxDQUFDRyxTQUFTO01BQ3ZDLElBQUlFLEdBQUcsR0FBRzlCLGFBQWEsRUFBRTtRQUNyQnNCLFlBQVksQ0FBQ1csVUFBVSxDQUFDWixRQUFRLENBQUM7UUFDakMsT0FBTyxJQUFJO01BQ2Y7TUFFQSxPQUFPSSxNQUFNLENBQUNJLFFBQVE7SUFDMUIsQ0FBQyxDQUFDLE9BQU9LLENBQUMsRUFBRTtNQUNSLE9BQU8sSUFBSTtJQUNmO0VBQ0o7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtFQUNJLFNBQVNDLFVBQVVBLENBQUNkLFFBQVEsRUFBRVEsUUFBUSxFQUFFO0lBQ3BDLElBQUk7TUFDQSxJQUFJLE9BQU9QLFlBQVksS0FBSyxXQUFXLEVBQUU7TUFDekNBLFlBQVksQ0FBQ2MsT0FBTyxDQUFDZixRQUFRLEVBQUVLLElBQUksQ0FBQ1csU0FBUyxDQUFDO1FBQzFDVCxTQUFTLEVBQUVHLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUM7UUFDckJILFFBQVEsRUFBRUE7TUFDZCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUMsQ0FBQyxPQUFPSyxDQUFDLEVBQUU7TUFDUkksT0FBTyxDQUFDQyxJQUFJLENBQUMsaUNBQWlDLEVBQUVMLENBQUMsQ0FBQztJQUN0RDtFQUNKOztFQUVBO0FBQ0o7QUFDQTtFQUNJLFNBQVNNLFVBQVVBLENBQUEsRUFBRztJQUNsQixJQUFJO01BQ0EsSUFBSSxPQUFPbEIsWUFBWSxLQUFLLFdBQVcsRUFBRTtNQUN6QyxJQUFJbUIsWUFBWSxHQUFHLEVBQUU7TUFDckIsS0FBSyxJQUFJQyxDQUFDLEdBQUcsQ0FBQyxFQUFFQSxDQUFDLEdBQUdwQixZQUFZLENBQUNsQyxNQUFNLEVBQUVzRCxDQUFDLEVBQUUsRUFBRTtRQUMxQyxJQUFJQyxHQUFHLEdBQUdyQixZQUFZLENBQUNxQixHQUFHLENBQUNELENBQUMsQ0FBQztRQUM3QixJQUFJQyxHQUFHLElBQUlBLEdBQUcsQ0FBQ0MsT0FBTyxDQUFDbkUsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEVBQUU7VUFDNUNnRSxZQUFZLENBQUM5QixJQUFJLENBQUNnQyxHQUFHLENBQUM7UUFDMUI7TUFDSjtNQUNBLEtBQUssSUFBSUUsQ0FBQyxHQUFHLENBQUMsRUFBRUEsQ0FBQyxHQUFHSixZQUFZLENBQUNyRCxNQUFNLEVBQUV5RCxDQUFDLEVBQUUsRUFBRTtRQUMxQ3ZCLFlBQVksQ0FBQ1csVUFBVSxDQUFDUSxZQUFZLENBQUNJLENBQUMsQ0FBQyxDQUFDO01BQzVDO0lBQ0osQ0FBQyxDQUFDLE9BQU9YLENBQUMsRUFBRTtNQUNSSSxPQUFPLENBQUNDLElBQUksQ0FBQyxpQ0FBaUMsRUFBRUwsQ0FBQyxDQUFDO0lBQ3REO0VBQ0o7O0VBRUE7RUFDQTtFQUNBOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLFNBQVNZLFVBQVVBLENBQUNDLFFBQVEsRUFBRW5FLE1BQU0sRUFBRTtJQUNsQyxJQUFJb0UsR0FBRyxHQUFHcEUsTUFBTSxDQUFDVyxZQUFZLEdBQUdwQixlQUFlLEdBQUdTLE1BQU0sQ0FBQ1UsTUFBTTtJQUUvRCxJQUFJMkQsT0FBTyxHQUFHO01BQ1YsY0FBYyxFQUFFO0lBQ3BCLENBQUM7O0lBRUQ7SUFDQSxJQUFJckUsTUFBTSxDQUFDVyxZQUFZLElBQUlYLE1BQU0sQ0FBQ00sTUFBTSxFQUFFO01BQ3RDK0QsT0FBTyxDQUFDLGVBQWUsQ0FBQyxHQUFHLFNBQVMsR0FBR3JFLE1BQU0sQ0FBQ00sTUFBTTtJQUN4RDtJQUVBLElBQUlnRSxJQUFJLEdBQUc7TUFDUDFELEtBQUssRUFBRVosTUFBTSxDQUFDWSxLQUFLO01BQ25CdUQsUUFBUSxFQUFFQSxRQUFRO01BQ2xCdEQsV0FBVyxFQUFFYixNQUFNLENBQUNhLFdBQVc7TUFDL0IwRCxVQUFVLEVBQUV2RSxNQUFNLENBQUNjLFNBQVM7TUFDNUIwRCxlQUFlLEVBQUU7UUFBRUMsSUFBSSxFQUFFO01BQWM7SUFDM0MsQ0FBQzs7SUFFRDtJQUNBLElBQUlDLFVBQVUsR0FBRyxJQUFJO0lBQ3JCLElBQUlDLFNBQVMsR0FBRyxJQUFJO0lBRXBCLElBQUksT0FBT0MsZUFBZSxLQUFLLFdBQVcsRUFBRTtNQUN4Q0YsVUFBVSxHQUFHLElBQUlFLGVBQWUsQ0FBQyxDQUFDO01BQ2xDRCxTQUFTLEdBQUdFLFVBQVUsQ0FBQyxZQUFZO1FBQy9CSCxVQUFVLENBQUNJLEtBQUssQ0FBQyxDQUFDO01BQ3RCLENBQUMsRUFBRTlFLE1BQU0sQ0FBQ2dCLE9BQU8sQ0FBQztJQUN0QjtJQUVBLElBQUkrRCxZQUFZLEdBQUc7TUFDZkMsTUFBTSxFQUFFLE1BQU07TUFDZFgsT0FBTyxFQUFFQSxPQUFPO01BQ2hCQyxJQUFJLEVBQUV4QixJQUFJLENBQUNXLFNBQVMsQ0FBQ2EsSUFBSTtJQUM3QixDQUFDO0lBRUQsSUFBSUksVUFBVSxFQUFFO01BQ1pLLFlBQVksQ0FBQ0UsTUFBTSxHQUFHUCxVQUFVLENBQUNPLE1BQU07SUFDM0M7SUFFQSxPQUFPQyxLQUFLLENBQUNkLEdBQUcsRUFBRVcsWUFBWSxDQUFDLENBQzFCSSxJQUFJLENBQUMsVUFBVUMsUUFBUSxFQUFFO01BQ3RCLElBQUlULFNBQVMsRUFBRVUsWUFBWSxDQUFDVixTQUFTLENBQUM7TUFFdEMsSUFBSSxDQUFDUyxRQUFRLENBQUNFLEVBQUUsRUFBRTtRQUNkLE9BQU9GLFFBQVEsQ0FBQ0csSUFBSSxDQUFDLENBQUMsQ0FBQ0osSUFBSSxDQUFDLFVBQVVJLElBQUksRUFBRTtVQUN4QyxNQUFNLElBQUlDLEtBQUssQ0FBQyxzQkFBc0IsR0FBR0osUUFBUSxDQUFDSyxNQUFNLEdBQUcsS0FBSyxHQUFHRixJQUFJLENBQUNHLFNBQVMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDOUYsQ0FBQyxDQUFDO01BQ047TUFDQSxPQUFPTixRQUFRLENBQUNPLElBQUksQ0FBQyxDQUFDO0lBQzFCLENBQUMsQ0FBQyxDQUNEUixJQUFJLENBQUMsVUFBVVMsSUFBSSxFQUFFO01BQ2xCO01BQ0EsSUFBSUEsSUFBSSxJQUFJQSxJQUFJLENBQUNDLE9BQU8sSUFBSUQsSUFBSSxDQUFDQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUlELElBQUksQ0FBQ0MsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDQyxPQUFPLEVBQUU7UUFDcEUsSUFBSUMsT0FBTyxHQUFHSCxJQUFJLENBQUNDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQ0MsT0FBTyxDQUFDQyxPQUFPO1FBQzdDLElBQUk7VUFDQSxPQUFPakQsSUFBSSxDQUFDQyxLQUFLLENBQUNnRCxPQUFPLENBQUM7UUFDOUIsQ0FBQyxDQUFDLE9BQU96QyxDQUFDLEVBQUU7VUFDUjtVQUNBLElBQUkwQyxTQUFTLEdBQUdELE9BQU8sQ0FBQ0UsS0FBSyxDQUFDLGFBQWEsQ0FBQztVQUM1QyxJQUFJRCxTQUFTLEVBQUU7WUFDWCxPQUFPbEQsSUFBSSxDQUFDQyxLQUFLLENBQUNpRCxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7VUFDbkM7VUFDQSxNQUFNLElBQUlSLEtBQUssQ0FBQyx1Q0FBdUMsR0FBR08sT0FBTyxDQUFDTCxTQUFTLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ3hGO01BQ0o7O01BRUE7TUFDQSxJQUFJRSxJQUFJLEtBQUtBLElBQUksQ0FBQ00sZUFBZSxJQUFJTixJQUFJLENBQUNPLFFBQVEsQ0FBQyxFQUFFO1FBQ2pELE9BQU9QLElBQUk7TUFDZjtNQUVBLE1BQU0sSUFBSUosS0FBSyxDQUFDLG1DQUFtQyxDQUFDO0lBQ3hELENBQUMsQ0FBQyxDQUNEWSxLQUFLLENBQUMsVUFBVWhHLEtBQUssRUFBRTtNQUNwQixJQUFJdUUsU0FBUyxFQUFFVSxZQUFZLENBQUNWLFNBQVMsQ0FBQztNQUV0QyxJQUFJdkUsS0FBSyxDQUFDaUcsSUFBSSxLQUFLLFlBQVksRUFBRTtRQUM3QixNQUFNLElBQUliLEtBQUssQ0FBQyw2QkFBNkIsR0FBR3hGLE1BQU0sQ0FBQ2dCLE9BQU8sR0FBRyxJQUFJLENBQUM7TUFDMUU7TUFDQSxNQUFNWixLQUFLO0lBQ2YsQ0FBQyxDQUFDO0VBQ1Y7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxTQUFTa0csYUFBYUEsQ0FBQ25DLFFBQVEsRUFBRW5FLE1BQU0sRUFBRXVHLE9BQU8sRUFBRTtJQUM5Q0EsT0FBTyxHQUFHQSxPQUFPLElBQUksQ0FBQztJQUV0QixPQUFPckMsVUFBVSxDQUFDQyxRQUFRLEVBQUVuRSxNQUFNLENBQUMsQ0FBQ29HLEtBQUssQ0FBQyxVQUFVaEcsS0FBSyxFQUFFO01BQ3ZELElBQUltRyxPQUFPLEdBQUd2RyxNQUFNLENBQUNpQixVQUFVLEVBQUU7UUFDN0J5QyxPQUFPLENBQUNDLElBQUksQ0FBQyx5QkFBeUIsSUFBSTRDLE9BQU8sR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLEVBQUVuRyxLQUFLLENBQUMwRixPQUFPLENBQUM7UUFDNUU7UUFDQSxPQUFPLElBQUlVLE9BQU8sQ0FBQyxVQUFVQyxPQUFPLEVBQUU7VUFDbEM1QixVQUFVLENBQUMsWUFBWTtZQUNuQjRCLE9BQU8sQ0FBQ0gsYUFBYSxDQUFDbkMsUUFBUSxFQUFFbkUsTUFBTSxFQUFFdUcsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDO1VBQ3pELENBQUMsRUFBRSxHQUFHLEdBQUdHLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUMsRUFBRUosT0FBTyxDQUFDLENBQUM7UUFDbEMsQ0FBQyxDQUFDO01BQ047TUFDQSxNQUFNbkcsS0FBSztJQUNmLENBQUMsQ0FBQztFQUNOOztFQUVBO0VBQ0E7RUFDQTs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxTQUFTd0csc0JBQXNCQSxDQUFDeEIsUUFBUSxFQUFFeUIsUUFBUSxFQUFFO0lBQ2hELElBQUksQ0FBQ3pCLFFBQVEsSUFBSSxJQUFBbkYsUUFBQSxDQUFBQyxPQUFBLEVBQU9rRixRQUFRLE1BQUssUUFBUSxFQUFFO01BQzNDLE9BQU87UUFBRWpGLEtBQUssRUFBRSxLQUFLO1FBQUVDLEtBQUssRUFBRTtNQUE0QixDQUFDO0lBQy9EO0lBRUEsSUFBSSxDQUFDZ0YsUUFBUSxDQUFDYyxlQUFlLElBQUksT0FBT2QsUUFBUSxDQUFDYyxlQUFlLEtBQUssUUFBUSxFQUFFO01BQzNFLE9BQU87UUFBRS9GLEtBQUssRUFBRSxLQUFLO1FBQUVDLEtBQUssRUFBRTtNQUE2QyxDQUFDO0lBQ2hGOztJQUVBO0lBQ0EsSUFBSSxDQUFDeUcsUUFBUSxDQUFDekIsUUFBUSxDQUFDYyxlQUFlLENBQUMsRUFBRTtNQUNyQyxPQUFPO1FBQUUvRixLQUFLLEVBQUUsS0FBSztRQUFFQyxLQUFLLEVBQUUsb0JBQW9CLEdBQUdnRixRQUFRLENBQUNjLGVBQWUsR0FBRztNQUFnQyxDQUFDO0lBQ3JIO0lBRUEsT0FBTztNQUFFL0YsS0FBSyxFQUFFO0lBQUssQ0FBQztFQUMxQjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBUzJHLHdCQUF3QkEsQ0FBQzFCLFFBQVEsRUFBRTtJQUN4QyxJQUFJLENBQUNBLFFBQVEsSUFBSSxJQUFBbkYsUUFBQSxDQUFBQyxPQUFBLEVBQU9rRixRQUFRLE1BQUssUUFBUSxFQUFFO01BQzNDLE9BQU87UUFBRWpGLEtBQUssRUFBRSxLQUFLO1FBQUVDLEtBQUssRUFBRTtNQUE0QixDQUFDO0lBQy9EO0lBRUEsSUFBSSxDQUFDZ0YsUUFBUSxDQUFDZSxRQUFRLElBQUksT0FBT2YsUUFBUSxDQUFDZSxRQUFRLEtBQUssUUFBUSxFQUFFO01BQzdELE9BQU87UUFBRWhHLEtBQUssRUFBRSxLQUFLO1FBQUVDLEtBQUssRUFBRTtNQUFzQyxDQUFDO0lBQ3pFO0lBRUEsSUFBSSxDQUFDZ0YsUUFBUSxDQUFDMkIsV0FBVyxJQUFJLE9BQU8zQixRQUFRLENBQUMyQixXQUFXLEtBQUssUUFBUSxFQUFFO01BQ25FLE9BQU87UUFBRTVHLEtBQUssRUFBRSxLQUFLO1FBQUVDLEtBQUssRUFBRTtNQUF5QyxDQUFDO0lBQzVFO0lBRUEsSUFBSSxDQUFDZ0YsUUFBUSxDQUFDNEIsUUFBUSxJQUFJLE9BQU81QixRQUFRLENBQUM0QixRQUFRLEtBQUssUUFBUSxFQUFFO01BQzdELE9BQU87UUFBRTdHLEtBQUssRUFBRSxLQUFLO1FBQUVDLEtBQUssRUFBRTtNQUFzQyxDQUFDO0lBQ3pFO0lBRUEsT0FBTztNQUFFRCxLQUFLLEVBQUU7SUFBSyxDQUFDO0VBQzFCOztFQUVBO0VBQ0E7RUFDQTs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBUzhHLFFBQVFBLENBQUN0RixPQUFPLEVBQUV1RixPQUFPLEVBQUU7SUFDaEMsSUFBSWxILE1BQU0sR0FBR0QsZUFBZSxDQUFDbUgsT0FBTyxDQUFDQyxRQUFRLENBQUM7SUFFOUMsSUFBSSxDQUFDbkgsTUFBTSxDQUFDRyxLQUFLLEVBQUU7TUFDZixPQUFPcUcsT0FBTyxDQUFDWSxNQUFNLENBQUMsSUFBSTVCLEtBQUssQ0FBQyxXQUFXLEdBQUd4RixNQUFNLENBQUNJLEtBQUssQ0FBQyxDQUFDO0lBQ2hFO0lBRUEsSUFBSWlILFNBQVMsR0FBR0gsT0FBTyxDQUFDRyxTQUFTLElBQUksQ0FBQyxDQUFDO0lBQ3ZDLElBQUlDLEdBQUcsR0FBR0osT0FBTyxDQUFDSSxHQUFHLEtBQUssS0FBSzs7SUFFL0I7SUFDQSxJQUFJdEgsTUFBTSxDQUFDbUIsY0FBYyxFQUFFO01BQ3ZCLElBQUlzQixRQUFRLEdBQUdmLGFBQWEsQ0FBQ0MsT0FBTyxFQUFFM0IsTUFBTSxDQUFDZSxJQUFJLENBQUM7TUFDbEQsSUFBSThCLE1BQU0sR0FBR0wsU0FBUyxDQUFDQyxRQUFRLEVBQUV6QyxNQUFNLENBQUNvQixhQUFhLENBQUM7TUFDdEQsSUFBSXlCLE1BQU0sRUFBRTtRQUNSLElBQUl5RSxHQUFHLEVBQUU7VUFDTDVELE9BQU8sQ0FBQzRELEdBQUcsQ0FBQyxpQ0FBaUMsRUFBRXpFLE1BQU0sQ0FBQzBFLE1BQU0sQ0FBQztRQUNqRTtRQUNBMUUsTUFBTSxDQUFDVixNQUFNLEdBQUcsV0FBVztRQUMzQixPQUFPcUUsT0FBTyxDQUFDQyxPQUFPLENBQUM1RCxNQUFNLENBQUM7TUFDbEM7SUFDSjs7SUFFQTtJQUNBLElBQUkyRSxhQUFhLEdBQUdsSSxJQUFJLENBQUNtSSxrQkFBa0I7SUFDM0MsSUFBSUMsZUFBZSxHQUFHLEVBQUU7SUFDeEIsSUFBSUMsV0FBVyxHQUFHLENBQUMsQ0FBQztJQUNwQixJQUFJQyxPQUFPLEdBQUcsSUFBSTtJQUVsQixJQUFJNUgsTUFBTSxDQUFDcUIsY0FBYyxJQUFJbUcsYUFBYSxFQUFFO01BQ3hDSSxPQUFPLEdBQUdKLGFBQWEsQ0FBQ0ssVUFBVSxDQUFDLENBQUM7TUFDcEMsSUFBSUMsUUFBUSxHQUFHTixhQUFhLENBQUNPLG9CQUFvQixDQUFDSCxPQUFPLEVBQUU7UUFDdkRJLFNBQVMsRUFBRWhJLE1BQU0sQ0FBQ3NCO01BQ3RCLENBQUMsQ0FBQztNQUNGcUcsV0FBVyxHQUFHSCxhQUFhLENBQUNTLG9CQUFvQixDQUFDSCxRQUFRLENBQUM7TUFDMURKLGVBQWUsR0FBR0YsYUFBYSxDQUFDVSxlQUFlLENBQUNKLFFBQVEsQ0FBQztJQUM3RDs7SUFFQTtJQUNBLElBQUlLLGFBQWEsR0FBRzdJLElBQUksQ0FBQzhJLFVBQVU7SUFFbkMsSUFBSSxDQUFDRCxhQUFhLEVBQUU7TUFDaEIsT0FBTzNCLE9BQU8sQ0FBQ1ksTUFBTSxDQUFDLElBQUk1QixLQUFLLENBQUMsbUZBQW1GLENBQUMsQ0FBQztJQUN6SDs7SUFFQTtJQUNBLElBQUk2QyxZQUFZLEdBQUc7TUFDZjFHLE9BQU8sRUFBRUEsT0FBTztNQUNoQitGLGVBQWUsRUFBRUEsZUFBZTtNQUNoQ0MsV0FBVyxFQUFFQTtJQUNqQixDQUFDO0lBRUQsSUFBSTNILE1BQU0sQ0FBQ2UsSUFBSSxLQUFLLFFBQVEsRUFBRTtNQUMxQnNILFlBQVksQ0FBQ3hCLFFBQVEsR0FBR1EsU0FBUztJQUNyQyxDQUFDLE1BQU07TUFDSDtNQUNBZ0IsWUFBWSxDQUFDN0csWUFBWSxHQUFHeEIsTUFBTSxDQUFDd0IsWUFBWTtNQUMvQzZHLFlBQVksQ0FBQ0MsZ0JBQWdCLEdBQUdqQixTQUFTLENBQUMsU0FBUyxDQUFDLElBQUlBLFNBQVMsQ0FBQ2tCLE1BQU0sQ0FBQ0MsSUFBSSxDQUFDbkIsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJO0lBQ3hHOztJQUVBO0lBQ0EsSUFBSWxELFFBQVEsR0FBR2dFLGFBQWEsQ0FBQ00sYUFBYSxDQUFDekksTUFBTSxDQUFDZSxJQUFJLEVBQUVzSCxZQUFZLEVBQUVySSxNQUFNLENBQUN5QixhQUFhLENBQUM7SUFFM0YsSUFBSWlILFNBQVMsR0FBR3ZGLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUM7O0lBRTFCO0lBQ0EsT0FBT2tELGFBQWEsQ0FBQ25DLFFBQVEsRUFBRW5FLE1BQU0sQ0FBQyxDQUFDbUYsSUFBSSxDQUFDLFVBQVV3RCxVQUFVLEVBQUU7TUFDOUQsSUFBSUMsT0FBTyxHQUFHekYsSUFBSSxDQUFDQyxHQUFHLENBQUMsQ0FBQyxHQUFHc0YsU0FBUztNQUNwQyxJQUFJekYsUUFBUTtNQUVaLElBQUlqRCxNQUFNLENBQUNlLElBQUksS0FBSyxRQUFRLEVBQUU7UUFDMUI7UUFDQSxJQUFJOEgsZ0JBQWdCLEdBQUdqQyxzQkFBc0IsQ0FBQytCLFVBQVUsRUFBRXRCLFNBQVMsQ0FBQztRQUNwRSxJQUFJLENBQUN3QixnQkFBZ0IsQ0FBQzFJLEtBQUssRUFBRTtVQUN6QixNQUFNLElBQUlxRixLQUFLLENBQUMsd0JBQXdCLEdBQUdxRCxnQkFBZ0IsQ0FBQ3pJLEtBQUssQ0FBQztRQUN0RTtRQUVBNkMsUUFBUSxHQUFHO1VBQ1A2RixRQUFRLEVBQUV6QixTQUFTLENBQUNzQixVQUFVLENBQUN6QyxlQUFlLENBQUM7VUFDL0NxQixNQUFNLEVBQUVvQixVQUFVLENBQUN6QyxlQUFlO1VBQ2xDL0QsTUFBTSxFQUFFLElBQUk7VUFDWlIsT0FBTyxFQUFFQSxPQUFPO1VBQ2hCZ0gsVUFBVSxFQUFFO1lBQ1JJLFVBQVUsRUFBRUosVUFBVSxDQUFDSSxVQUFVLElBQUksSUFBSTtZQUN6Q0MsU0FBUyxFQUFFTCxVQUFVLENBQUNLLFNBQVMsSUFBSSxJQUFJO1lBQ3ZDSixPQUFPLEVBQUVBLE9BQU87WUFDaEJoSSxLQUFLLEVBQUVaLE1BQU0sQ0FBQ1ksS0FBSztZQUNuQkcsSUFBSSxFQUFFLFFBQVE7WUFDZDhCLE1BQU0sRUFBRTtVQUNaO1FBQ0osQ0FBQztNQUNMLENBQUMsTUFBTTtRQUNIO1FBQ0EsSUFBSW9HLGFBQWEsR0FBR25DLHdCQUF3QixDQUFDNkIsVUFBVSxDQUFDO1FBQ3hELElBQUksQ0FBQ00sYUFBYSxDQUFDOUksS0FBSyxFQUFFO1VBQ3RCLE1BQU0sSUFBSXFGLEtBQUssQ0FBQyx5QkFBeUIsR0FBR3lELGFBQWEsQ0FBQzdJLEtBQUssQ0FBQztRQUNwRTs7UUFFQTtRQUNBLElBQUk4SSxpQkFBaUIsR0FBRztVQUNwQi9DLFFBQVEsRUFBRXdDLFVBQVUsQ0FBQ3hDLFFBQVE7VUFDN0JZLFdBQVcsRUFBRTRCLFVBQVUsQ0FBQzVCLFdBQVc7VUFDbkNDLFFBQVEsRUFBRTJCLFVBQVUsQ0FBQzNCLFFBQVE7VUFDN0JtQyxPQUFPLEVBQUc5QixTQUFTLENBQUMsU0FBUyxDQUFDLElBQUlBLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQzhCLE9BQU8sSUFBSyxPQUFPO1VBQzFFQyxLQUFLLEVBQUcvQixTQUFTLENBQUMsU0FBUyxDQUFDLElBQUlBLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQytCLEtBQUssSUFBSztRQUNuRSxDQUFDO1FBRURuRyxRQUFRLEdBQUc7VUFDUDZGLFFBQVEsRUFBRUksaUJBQWlCO1VBQzNCM0IsTUFBTSxFQUFFLGNBQWM7VUFDdEJwRixNQUFNLEVBQUUsSUFBSTtVQUNaUixPQUFPLEVBQUVBLE9BQU87VUFDaEJnSCxVQUFVLEVBQUU7WUFDUkksVUFBVSxFQUFFSixVQUFVLENBQUNJLFVBQVUsSUFBSSxJQUFJO1lBQ3pDQyxTQUFTLEVBQUVMLFVBQVUsQ0FBQ0ssU0FBUyxJQUFJLElBQUk7WUFDdkNKLE9BQU8sRUFBRUEsT0FBTztZQUNoQmhJLEtBQUssRUFBRVosTUFBTSxDQUFDWSxLQUFLO1lBQ25CRyxJQUFJLEVBQUUsVUFBVTtZQUNoQjhCLE1BQU0sRUFBRTtVQUNaO1FBQ0osQ0FBQztNQUNMOztNQUVBO01BQ0EsSUFBSTdDLE1BQU0sQ0FBQ21CLGNBQWMsRUFBRTtRQUN2Qm9DLFVBQVUsQ0FBQzdCLGFBQWEsQ0FBQ0MsT0FBTyxFQUFFM0IsTUFBTSxDQUFDZSxJQUFJLENBQUMsRUFBRWtDLFFBQVEsQ0FBQztNQUM3RDs7TUFFQTtNQUNBLElBQUlqRCxNQUFNLENBQUNxQixjQUFjLElBQUltRyxhQUFhLEVBQUU7UUFDeENBLGFBQWEsQ0FBQzZCLFdBQVcsQ0FBQztVQUN0QjFILE9BQU8sRUFBRUEsT0FBTztVQUNoQjRGLE1BQU0sRUFBRXRFLFFBQVEsQ0FBQ3NFLE1BQU07VUFDdkJyQixlQUFlLEVBQUVqRCxRQUFRLENBQUNzRSxNQUFNO1VBQ2hDcEYsTUFBTSxFQUFFLElBQUk7VUFDWm1ILFVBQVUsRUFBRTtRQUNoQixDQUFDLEVBQUU7VUFDQy9ILGNBQWMsRUFBRXZCLE1BQU0sQ0FBQ3VCO1FBQzNCLENBQUMsQ0FBQztNQUNOO01BRUEsSUFBSStGLEdBQUcsRUFBRTtRQUNMNUQsT0FBTyxDQUFDNEQsR0FBRyxDQUFDLHlCQUF5QixFQUFFO1VBQ25DdkcsSUFBSSxFQUFFZixNQUFNLENBQUNlLElBQUk7VUFDakJ3RyxNQUFNLEVBQUV0RSxRQUFRLENBQUNzRSxNQUFNO1VBQ3ZCcEYsTUFBTSxFQUFFLElBQUk7VUFDWjRHLFVBQVUsRUFBRTlGLFFBQVEsQ0FBQzBGLFVBQVUsQ0FBQ0ksVUFBVTtVQUMxQ0gsT0FBTyxFQUFFQSxPQUFPLEdBQUcsSUFBSTtVQUN2QmhJLEtBQUssRUFBRVosTUFBTSxDQUFDWTtRQUNsQixDQUFDLENBQUM7TUFDTjtNQUVBLE9BQU9xQyxRQUFRO0lBRW5CLENBQUMsQ0FBQyxDQUFDbUQsS0FBSyxDQUFDLFVBQVVoRyxLQUFLLEVBQUU7TUFDdEIsSUFBSXdJLE9BQU8sR0FBR3pGLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUMsR0FBR3NGLFNBQVM7TUFFcEMsSUFBSXBCLEdBQUcsRUFBRTtRQUNMNUQsT0FBTyxDQUFDQyxJQUFJLENBQUMsdUJBQXVCLEdBQUdpRixPQUFPLEdBQUcsS0FBSyxFQUFFeEksS0FBSyxDQUFDMEYsT0FBTyxDQUFDO01BQzFFO01BRUEsTUFBTTFGLEtBQUs7SUFDZixDQUFDLENBQUM7RUFDTjs7RUFFQTtFQUNBO0VBQ0E7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBU21KLGlCQUFpQkEsQ0FBQ3JDLE9BQU8sRUFBRTtJQUNoQ0EsT0FBTyxHQUFHQSxPQUFPLElBQUksQ0FBQyxDQUFDOztJQUV2QjtJQUNBLElBQUl2RixPQUFPLEdBQUd1RixPQUFPLENBQUN2RixPQUFPO0lBRTdCLElBQUksQ0FBQ0EsT0FBTyxFQUFFO01BQ1Y7TUFDQSxJQUFJNkgsU0FBUyxHQUFHbEssSUFBSSxDQUFDbUssaUJBQWlCLElBQUluSyxJQUFJLENBQUNvSyxNQUFNO01BQ3JELElBQUlGLFNBQVMsSUFBSSxPQUFPQSxTQUFTLENBQUNHLFVBQVUsS0FBSyxVQUFVLEVBQUU7UUFDekRoSSxPQUFPLEdBQUc2SCxTQUFTLENBQUNHLFVBQVUsQ0FBQyxDQUFDO01BQ3BDLENBQUMsTUFBTTtRQUNIaEksT0FBTyxHQUFHO1VBQ05FLEdBQUcsRUFBRSxDQUFDLENBQUM7VUFDUEssUUFBUSxFQUFFO1lBQUVDLE1BQU0sRUFBRSxRQUFRO1lBQUV5SCxRQUFRLEVBQUUsUUFBUTtZQUFFeEYsR0FBRyxFQUFFO1VBQUcsQ0FBQztVQUMzRGhDLFNBQVMsRUFBRTtZQUFFTyxHQUFHLEVBQUUsRUFBRTtZQUFFTixRQUFRLEVBQUUsS0FBSztZQUFFQyxRQUFRLEVBQUUsS0FBSztZQUFFdUgsU0FBUyxFQUFFO1VBQUssQ0FBQztVQUN6RTdHLFNBQVMsRUFBRUcsSUFBSSxDQUFDQyxHQUFHLENBQUMsQ0FBQztVQUNyQjBHLE1BQU0sRUFBRSxLQUFLO1VBQ2JDLGFBQWEsRUFBRTtRQUNuQixDQUFDO01BQ0w7SUFDSjtJQUVBLE9BQU85QyxRQUFRLENBQUN0RixPQUFPLEVBQUV1RixPQUFPLENBQUM7RUFDckM7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtFQUNJLFNBQVM4QyxPQUFPQSxDQUFDN0MsUUFBUSxFQUFFO0lBQ3ZCLElBQUluSCxNQUFNLEdBQUdELGVBQWUsQ0FBQ29ILFFBQVEsQ0FBQztJQUN0QyxJQUFJLENBQUNuSCxNQUFNLENBQUNHLEtBQUssRUFBRTtNQUNmLE9BQU87UUFBRThKLEtBQUssRUFBRSxLQUFLO1FBQUU3SixLQUFLLEVBQUVKLE1BQU0sQ0FBQ0k7TUFBTSxDQUFDO0lBQ2hEOztJQUVBO0lBQ0EsSUFBSSxDQUFDZCxJQUFJLENBQUM4SSxVQUFVLEVBQUU7TUFDbEIsT0FBTztRQUFFNkIsS0FBSyxFQUFFLEtBQUs7UUFBRTdKLEtBQUssRUFBRTtNQUErQixDQUFDO0lBQ2xFOztJQUVBO0lBQ0EsSUFBSSxDQUFDZCxJQUFJLENBQUNtSSxrQkFBa0IsRUFBRTtNQUMxQi9ELE9BQU8sQ0FBQ0MsSUFBSSxDQUFDLG9FQUFvRSxDQUFDO0lBQ3RGO0lBRUEsT0FBTztNQUFFc0csS0FBSyxFQUFFO0lBQUssQ0FBQztFQUMxQjs7RUFFQTtFQUNBO0VBQ0E7O0VBRUEsSUFBSUMsZ0JBQWdCLEdBQUc7SUFDbkI7SUFDQUMsTUFBTSxFQUFFbEQsUUFBUTtJQUNoQnNDLGlCQUFpQixFQUFFQSxpQkFBaUI7SUFDcENTLE9BQU8sRUFBRUEsT0FBTztJQUVoQjtJQUNBakssZUFBZSxFQUFFQSxlQUFlO0lBRWhDO0lBQ0FtRSxVQUFVLEVBQUVBLFVBQVU7SUFFdEI7SUFDQTBDLHNCQUFzQixFQUFFQSxzQkFBc0I7SUFDOUNFLHdCQUF3QixFQUFFQSx3QkFBd0I7SUFFbEQ7SUFDQWxELFVBQVUsRUFBRUEsVUFBVTtJQUV0QjtJQUNBckUsZUFBZSxFQUFFQSxlQUFlO0lBQ2hDQyxhQUFhLEVBQUVBLGFBQWE7SUFDNUJDLGVBQWUsRUFBRUEsZUFBZTtJQUNoQ0ssc0JBQXNCLEVBQUVBO0VBQzVCLENBQUM7O0VBRUQ7RUFDQVIsSUFBSSxDQUFDNEssZ0JBQWdCLEdBQUdBLGdCQUFnQjtBQUU1QyxDQUFDLEVBQUUsT0FBT0UsTUFBTSxLQUFLLFdBQVcsR0FBR0EsTUFBTSxHQUFHLE9BQU9DLE1BQU0sS0FBSyxXQUFXLEdBQUdBLE1BQU0sU0FBTyxDQUFDIiwiaWdub3JlTGlzdCI6W119