@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,811 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
5
+ /**
6
+ * DOM Personalization Engine
7
+ * Handles content injection with data-personalize attributes
8
+ * Uses textContent for text, DOMPurify-style sanitized HTML for rich content
9
+ *
10
+ * No ES6 imports - self-contained IIFE that registers on window.LuaPersonalize
11
+ * Depends on window.LuaUTM (from utm.js) for context extraction
12
+ * Falls back to random A/B test when no UTM params are present
13
+ */
14
+ ;
15
+ (function (root) {
16
+ 'use strict';
17
+
18
+ // ===================================================================
19
+ // DOMPurify-style HTML Sanitizer (inline, OWASP-recommended approach)
20
+ // Provides safe HTML injection without external dependencies
21
+ // ===================================================================
22
+
23
+ /**
24
+ * Inline DOMPurify-style sanitizer
25
+ * Uses the browser's DOMParser to safely parse and sanitize HTML
26
+ * Falls back to regex-based sanitization if DOMParser unavailable
27
+ */
28
+ var Sanitizer = function () {
29
+ // Allowed HTML tags (safe for content injection)
30
+ var ALLOWED_TAGS = {
31
+ 'p': true,
32
+ 'span': true,
33
+ 'strong': true,
34
+ 'em': true,
35
+ 'b': true,
36
+ 'i': true,
37
+ 'br': true,
38
+ 'a': true,
39
+ 'img': true,
40
+ 'h1': true,
41
+ 'h2': true,
42
+ 'h3': true,
43
+ 'h4': true,
44
+ 'h5': true,
45
+ 'h6': true,
46
+ 'div': true,
47
+ 'section': true,
48
+ 'ul': true,
49
+ 'ol': true,
50
+ 'li': true,
51
+ 'blockquote': true,
52
+ 'figure': true,
53
+ 'figcaption': true
54
+ };
55
+
56
+ // Allowed HTML attributes (safe subset)
57
+ var ALLOWED_ATTRS = {
58
+ 'href': true,
59
+ 'src': true,
60
+ 'alt': true,
61
+ 'class': true,
62
+ 'id': true,
63
+ 'title': true,
64
+ 'target': true,
65
+ 'rel': true,
66
+ 'width': true,
67
+ 'height': true,
68
+ 'loading': true
69
+ };
70
+
71
+ // Dangerous URI schemes
72
+ var DANGEROUS_URI = /^(javascript|vbscript|data):/i;
73
+
74
+ // Event handler pattern (onclick, onerror, onload, etc.)
75
+ var EVENT_HANDLER = /^on/i;
76
+
77
+ /**
78
+ * Check if DOMParser is available (modern browsers)
79
+ * @returns {boolean}
80
+ */
81
+ function hasDOMParser() {
82
+ try {
83
+ return typeof DOMParser !== 'undefined' && new DOMParser();
84
+ } catch (e) {
85
+ return false;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Sanitize HTML using DOMParser (preferred, secure method)
91
+ * Parses HTML into a DOM tree, walks nodes, and rebuilds safe HTML
92
+ * @param {string} dirty - Untrusted HTML string
93
+ * @returns {string} - Sanitized HTML string
94
+ */
95
+ function sanitizeWithDOMParser(dirty) {
96
+ if (typeof dirty !== 'string' || !dirty.trim()) return '';
97
+ try {
98
+ var parser = new DOMParser();
99
+ var doc = parser.parseFromString(dirty, 'text/html');
100
+ var body = doc.body;
101
+ if (!body) return '';
102
+ return walkAndClean(body);
103
+ } catch (e) {
104
+ console.warn('[Lua Sanitizer] DOMParser failed, using fallback:', e);
105
+ return sanitizeWithRegex(dirty);
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Recursively walk DOM nodes and build clean HTML
111
+ * @param {Node} node - DOM node to process
112
+ * @returns {string} - Cleaned HTML string
113
+ */
114
+ function walkAndClean(node) {
115
+ var output = '';
116
+ for (var i = 0; i < node.childNodes.length; i++) {
117
+ var child = node.childNodes[i];
118
+
119
+ // Text node - safe to include
120
+ if (child.nodeType === 3) {
121
+ output += escapeText(child.textContent);
122
+ continue;
123
+ }
124
+
125
+ // Element node
126
+ if (child.nodeType === 1) {
127
+ var tagName = child.tagName.toLowerCase();
128
+
129
+ // Skip disallowed tags entirely (including children)
130
+ if (tagName === 'script' || tagName === 'style' || tagName === 'iframe' || tagName === 'object' || tagName === 'embed' || tagName === 'form' || tagName === 'input' || tagName === 'textarea') {
131
+ continue;
132
+ }
133
+
134
+ // If tag is allowed, include it with filtered attributes
135
+ if (ALLOWED_TAGS[tagName]) {
136
+ output += '<' + tagName;
137
+ output += cleanAttributes(child);
138
+ output += '>';
139
+
140
+ // Self-closing tags
141
+ if (tagName === 'br' || tagName === 'img') {
142
+ continue;
143
+ }
144
+
145
+ // Recurse into children
146
+ output += walkAndClean(child);
147
+ output += '</' + tagName + '>';
148
+ } else {
149
+ // Tag not allowed - include children only (strip the tag)
150
+ output += walkAndClean(child);
151
+ }
152
+ }
153
+ }
154
+ return output;
155
+ }
156
+
157
+ /**
158
+ * Filter element attributes to only allowed ones
159
+ * @param {Element} element - DOM element
160
+ * @returns {string} - Attribute string
161
+ */
162
+ function cleanAttributes(element) {
163
+ var attrStr = '';
164
+ var attrs = element.attributes;
165
+ for (var i = 0; i < attrs.length; i++) {
166
+ var attr = attrs[i];
167
+ var name = attr.name.toLowerCase();
168
+ var value = attr.value;
169
+
170
+ // Skip event handlers (onclick, onerror, etc.)
171
+ if (EVENT_HANDLER.test(name)) continue;
172
+
173
+ // Skip disallowed attributes
174
+ if (!ALLOWED_ATTRS[name]) continue;
175
+
176
+ // Check URI safety for href/src
177
+ if ((name === 'href' || name === 'src') && DANGEROUS_URI.test(value.trim())) {
178
+ continue;
179
+ }
180
+
181
+ // Add rel="noopener noreferrer" for external links
182
+ if (name === 'target' && value === '_blank') {
183
+ attrStr += ' target="_blank" rel="noopener noreferrer"';
184
+ continue;
185
+ }
186
+ attrStr += ' ' + name + '="' + escapeAttr(value) + '"';
187
+ }
188
+ return attrStr;
189
+ }
190
+
191
+ /**
192
+ * Escape text content for safe HTML inclusion
193
+ * @param {string} text - Raw text
194
+ * @returns {string} - Escaped text
195
+ */
196
+ function escapeText(text) {
197
+ if (!text) return '';
198
+ return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
199
+ }
200
+
201
+ /**
202
+ * Escape attribute value for safe HTML inclusion
203
+ * @param {string} value - Raw attribute value
204
+ * @returns {string} - Escaped attribute value
205
+ */
206
+ function escapeAttr(value) {
207
+ if (!value) return '';
208
+ return value.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
209
+ }
210
+
211
+ /**
212
+ * Fallback regex-based sanitizer for environments without DOMParser
213
+ * @param {string} html - Raw HTML string
214
+ * @returns {string} - Sanitized HTML
215
+ */
216
+ function sanitizeWithRegex(html) {
217
+ if (typeof html !== 'string') return '';
218
+ var DANGEROUS_PATTERNS = [/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, /<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, /<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi, /<embed\b[^>]*>/gi, /<link\b[^>]*>/gi, /<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, /<form\b[^<]*(?:(?!<\/form>)<[^<]*)*<\/form>/gi, /javascript:/gi, /vbscript:/gi, /data:/gi, /on\w+\s*=/gi];
219
+ var sanitized = html;
220
+ DANGEROUS_PATTERNS.forEach(function (pattern) {
221
+ sanitized = sanitized.replace(pattern, '');
222
+ });
223
+
224
+ // Remove disallowed tags but keep their text content
225
+ sanitized = sanitized.replace(/<\/?(\w+)([^>]*)>/g, function (match, tagName, attrs) {
226
+ var tag = tagName.toLowerCase();
227
+ if (!ALLOWED_TAGS[tag]) return '';
228
+
229
+ // For closing tags, just return the closing tag
230
+ if (match.charAt(1) === '/') return '</' + tag + '>';
231
+
232
+ // Filter attributes
233
+ var cleanAttrs = '';
234
+ var attrRegex = /(\w+)=['"]([^'"]*)['"]/g;
235
+ var attrMatch;
236
+ while ((attrMatch = attrRegex.exec(attrs)) !== null) {
237
+ var attrName = attrMatch[1].toLowerCase();
238
+ if (ALLOWED_ATTRS[attrName] && !EVENT_HANDLER.test(attrName)) {
239
+ var val = attrMatch[2];
240
+ if ((attrName === 'href' || attrName === 'src') && DANGEROUS_URI.test(val)) {
241
+ continue;
242
+ }
243
+ cleanAttrs += ' ' + attrName + '="' + val + '"';
244
+ }
245
+ }
246
+ return '<' + tag + cleanAttrs + '>';
247
+ });
248
+ return sanitized;
249
+ }
250
+
251
+ // Public sanitizer API
252
+ return {
253
+ /**
254
+ * Sanitize HTML string (main entry point)
255
+ * Uses DOMParser when available, regex fallback otherwise
256
+ * @param {string} dirty - Untrusted HTML
257
+ * @returns {string} - Sanitized HTML
258
+ */
259
+ sanitize: function sanitize(dirty) {
260
+ if (typeof dirty !== 'string') return '';
261
+ if (!dirty.trim()) return '';
262
+ if (hasDOMParser()) {
263
+ return sanitizeWithDOMParser(dirty);
264
+ }
265
+ return sanitizeWithRegex(dirty);
266
+ },
267
+ escapeText: escapeText,
268
+ escapeAttr: escapeAttr
269
+ };
270
+ }();
271
+
272
+ // ===================================================================
273
+ // Templates & Assets
274
+ // ===================================================================
275
+ // NOTE: Templates are NOT provided by this package.
276
+ // Users must provide their own templates via options.templates
277
+ // This keeps the package modular and allows users full control
278
+ // over their content, assets, and personalization strategy.
279
+
280
+ // ===================================================================
281
+ // DOM Interaction (safe methods - never raw innerHTML)
282
+ // ===================================================================
283
+
284
+ /**
285
+ * Safely set text content on an element (no HTML parsing)
286
+ * @param {Element} element - DOM element
287
+ * @param {string} text - Text to set
288
+ */
289
+ function safeSetText(element, text) {
290
+ if (!element) return;
291
+ element.textContent = text;
292
+ }
293
+
294
+ /**
295
+ * Safely set HTML content on an element (DOMPurify-sanitized)
296
+ * @param {Element} element - DOM element
297
+ * @param {string} html - HTML to set (will be sanitized)
298
+ */
299
+ function safeSetHTML(element, html) {
300
+ if (!element) return;
301
+ element.innerHTML = Sanitizer.sanitize(html);
302
+ }
303
+
304
+ /**
305
+ * Find all elements with data-personalize attribute
306
+ * @param {string} [key] - Optional specific key to find
307
+ * @param {Element} [searchRoot] - Root element to search from (default: document)
308
+ * @returns {NodeList|Array} - Matching elements
309
+ */
310
+ function findPersonalizeElements(key, searchRoot) {
311
+ searchRoot = searchRoot || (typeof document !== 'undefined' ? document : null);
312
+ if (!searchRoot) return [];
313
+ var selector = key ? '[data-personalize="' + key + '"]' : '[data-personalize]';
314
+ return searchRoot.querySelectorAll(selector);
315
+ }
316
+
317
+ /**
318
+ * Get template for a given intent
319
+ * Templates must be provided by the user via options.templates
320
+ * Falls back to 'default' template if intent not found
321
+ * @param {string} intent - Intent key
322
+ * @param {Object} userTemplates - User-provided templates (required)
323
+ * @returns {Object|null} - Template data or null if no templates provided
324
+ */
325
+ function getTemplate(intent, userTemplates) {
326
+ if (!userTemplates || (0, _typeof2.default)(userTemplates) !== 'object') {
327
+ console.warn('[Lua Personalize] No templates provided. Templates must be passed via options.templates');
328
+ return null;
329
+ }
330
+
331
+ // Try to get the intent template
332
+ if (userTemplates[intent]) {
333
+ return userTemplates[intent];
334
+ }
335
+
336
+ // Fall back to 'default' template if available
337
+ if (userTemplates['default']) {
338
+ return userTemplates['default'];
339
+ }
340
+
341
+ // If no default, return the first available template
342
+ var firstKey = Object.keys(userTemplates)[0];
343
+ if (firstKey) {
344
+ console.warn('[Lua Personalize] Intent "' + intent + '" not found, using first available template:', firstKey);
345
+ return userTemplates[firstKey];
346
+ }
347
+ return null;
348
+ }
349
+
350
+ // ===================================================================
351
+ // Random A/B Fallback (used when no UTM params are present)
352
+ // ===================================================================
353
+
354
+ /**
355
+ * Simple weighted random selection for A/B fallback
356
+ * @param {Array} names - Array of bucket/template names
357
+ * @param {Array} weights - Corresponding weights
358
+ * @returns {string} - Selected name
359
+ */
360
+ function chooseWeightedRandom(names, weights) {
361
+ if (names.length !== weights.length) return names[0];
362
+ var sum = 0;
363
+ var i;
364
+ for (i = 0; i < weights.length; i++) {
365
+ sum += weights[i];
366
+ }
367
+ var n = Math.random() * sum;
368
+ var limit = 0;
369
+ for (i = 0; i < names.length; i++) {
370
+ limit += weights[i];
371
+ if (n <= limit) return names[i];
372
+ }
373
+ return names[names.length - 1];
374
+ }
375
+
376
+ /**
377
+ * Get a random template key from user-provided templates
378
+ * Used as fallback when no UTM/referrer context is available
379
+ * @param {Object} userTemplates - User-provided templates (required)
380
+ * @returns {string|null} - Random template intent key or null if no templates
381
+ */
382
+ function getRandomFallbackIntent(userTemplates) {
383
+ if (!userTemplates || (0, _typeof2.default)(userTemplates) !== 'object') {
384
+ return null;
385
+ }
386
+ var names = Object.keys(userTemplates);
387
+ if (names.length === 0) {
388
+ return null;
389
+ }
390
+ var weights = [];
391
+ for (var i = 0; i < names.length; i++) {
392
+ weights.push(1); // Equal weight by default
393
+ }
394
+ return chooseWeightedRandom(names, weights);
395
+ }
396
+
397
+ // ===================================================================
398
+ // Decision Engine
399
+ // ===================================================================
400
+
401
+ /**
402
+ * Personalization Decision Engine
403
+ * Determines which content to show based on context
404
+ * Priority: AI (if enabled) -> UTM params -> Referrer -> Random A/B fallback
405
+ */
406
+ var DecisionEngine = {
407
+ /**
408
+ * Standard (non-AI) decision logic
409
+ * @param {Object} context - Context from LuaUTM.getContext()
410
+ * @param {Object} [options] - Configuration options
411
+ * @param {Object} [options.rules] - Custom matching rules
412
+ * @param {Object} options.templates - User-provided templates (REQUIRED)
413
+ * @param {boolean} [options.randomFallback] - Enable random A/B fallback (default: true)
414
+ * @returns {Object} - { template, intent, source }
415
+ */
416
+ standardDecide: function standardDecide(context, options) {
417
+ options = options || {};
418
+ var customRules = options.rules || {};
419
+ var userTemplates = options.templates;
420
+ var enableRandomFallback = options.randomFallback !== false;
421
+
422
+ // Templates are required - warn if not provided
423
+ if (!userTemplates || (0, _typeof2.default)(userTemplates) !== 'object' || Object.keys(userTemplates).length === 0) {
424
+ console.warn('[Lua Personalize] No templates provided. Templates must be passed via options.templates');
425
+ return {
426
+ template: null,
427
+ intent: 'default',
428
+ source: 'error',
429
+ context: context,
430
+ error: 'No templates provided'
431
+ };
432
+ }
433
+ var intent = context.primaryIntent;
434
+ var source = 'default';
435
+
436
+ // Determine the source of the decision
437
+ if (context.hasUTM) {
438
+ source = 'utm';
439
+ } else if (context.referrer && context.referrer.category !== 'direct') {
440
+ source = 'referrer';
441
+ }
442
+
443
+ // Check custom rules first (highest priority)
444
+ for (var ruleKey in customRules) {
445
+ var rule = customRules[ruleKey];
446
+ if (typeof rule.match === 'function' && rule.match(context)) {
447
+ intent = rule.intent || ruleKey;
448
+ source = 'custom-rule';
449
+ break;
450
+ }
451
+ }
452
+
453
+ // If intent is still 'default' and random fallback is enabled,
454
+ // pick a random template for A/B testing
455
+ if (intent === 'default' && source === 'default' && enableRandomFallback) {
456
+ var randomIntent = getRandomFallbackIntent(userTemplates);
457
+ if (randomIntent) {
458
+ intent = randomIntent;
459
+ source = 'random-ab';
460
+ }
461
+ }
462
+
463
+ // Record visit to history if LuaWeightedHistory is available
464
+ if (root.LuaWeightedHistory && typeof root.LuaWeightedHistory.recordVisit === 'function') {
465
+ root.LuaWeightedHistory.recordVisit({
466
+ context: context,
467
+ intent: intent,
468
+ selectedVariant: intent,
469
+ source: source,
470
+ aiDecision: false
471
+ });
472
+ }
473
+ return {
474
+ template: getTemplate(intent, userTemplates),
475
+ intent: intent,
476
+ source: source,
477
+ context: context
478
+ };
479
+ },
480
+ /**
481
+ * Main decide function - routes to AI or standard engine
482
+ * @param {Object} context - Context from LuaUTM.getContext()
483
+ * @param {Object} [options] - Configuration options
484
+ * @param {boolean} [options.enableAI] - Enable AI-powered decisions
485
+ * @param {Object} [options.aiConfig] - AI configuration
486
+ * @returns {Object|Promise<Object>} - Decision result (Promise if AI enabled)
487
+ */
488
+ decide: function decide(context, options) {
489
+ options = options || {};
490
+
491
+ // If AI is enabled and configured, try AI decision first
492
+ if (options.enableAI && options.aiConfig && root.LuaAIPersonalize) {
493
+ var self = this;
494
+ var aiModule = root.LuaAIPersonalize;
495
+ var readiness = aiModule.isReady(options.aiConfig);
496
+ if (readiness.ready) {
497
+ return aiModule.decide(context, options).catch(function (error) {
498
+ // AI failed - fall back to standard engine
499
+ var fallback = options.aiConfig.fallbackToStandard !== false;
500
+ if (fallback) {
501
+ console.warn('[Lua Personalize] AI failed, using standard engine:', error.message);
502
+ return self.standardDecide(context, options);
503
+ }
504
+ throw error;
505
+ });
506
+ } else {
507
+ console.warn('[Lua Personalize] AI not ready:', readiness.error, '- using standard engine');
508
+ }
509
+ }
510
+
511
+ // Standard decision (synchronous)
512
+ return this.standardDecide(context, options);
513
+ }
514
+ };
515
+
516
+ // ===================================================================
517
+ // Personalization Application
518
+ // ===================================================================
519
+
520
+ // ===================================================================
521
+ // DOM Application (extracted for reuse by both sync and async paths)
522
+ // ===================================================================
523
+
524
+ /**
525
+ * Apply a decision to the DOM
526
+ * Injects content into elements with data-personalize attributes
527
+ *
528
+ * @param {Object} decision - Decision object { template, intent, source, context }
529
+ * @param {Object} [options] - Configuration options
530
+ * @param {boolean} [options.log] - Enable console logging
531
+ * @returns {Object} - The decision (pass-through)
532
+ */
533
+ function applyDecisionToDOM(decision, options) {
534
+ options = options || {};
535
+ var template = decision.template;
536
+ var context = decision.context || {};
537
+ var log = options.log !== false;
538
+ if (!template) {
539
+ console.warn('[Lua Personalize] No template in decision, skipping DOM update');
540
+ return decision;
541
+ }
542
+
543
+ // Find and update each personalize slot in the DOM
544
+ var slots = ['image', 'headline', 'subheadline', 'ctaLabel', 'ctaLink'];
545
+ slots.forEach(function (slot) {
546
+ var elements = findPersonalizeElements(slot);
547
+ for (var i = 0; i < elements.length; i++) {
548
+ var element = elements[i];
549
+ var value = template[slot];
550
+ if (!value) continue;
551
+ if (slot === 'image') {
552
+ // For images, set background-image or src attribute
553
+ if (element.tagName === 'IMG') {
554
+ element.src = value;
555
+ element.alt = template.headline || 'Personalized image';
556
+ } else {
557
+ element.style.backgroundImage = 'url(' + value + ')';
558
+ }
559
+ } else if (slot === 'ctaLink') {
560
+ // For links, set href attribute
561
+ element.href = value;
562
+ } else {
563
+ // For text content, use textContent (safe, no HTML parsing)
564
+ safeSetText(element, value);
565
+ }
566
+ }
567
+ });
568
+
569
+ // Apply to generic 'hero' sections with data-personalize="hero"
570
+ var heroElements = findPersonalizeElements('hero');
571
+ for (var h = 0; h < heroElements.length; h++) {
572
+ var heroEl = heroElements[h];
573
+ heroEl.setAttribute('data-intent', decision.intent);
574
+ heroEl.setAttribute('data-source', decision.source);
575
+
576
+ // If hero has a background image slot, apply it
577
+ if (template.image && !heroEl.querySelector('[data-personalize="image"]')) {
578
+ heroEl.style.backgroundImage = 'url(' + template.image + ')';
579
+ }
580
+ }
581
+
582
+ // Log the personalization decision (for debugging/demo)
583
+ if (log && typeof console !== 'undefined') {
584
+ console.log('[Lua Personalize] Applied:', {
585
+ intent: decision.intent,
586
+ source: decision.source,
587
+ headline: template.headline,
588
+ hasUTM: context.hasUTM,
589
+ utmParams: context.utm || {},
590
+ aiPowered: decision.source === 'ai' || decision.source === 'ai-cached'
591
+ });
592
+ }
593
+ return decision;
594
+ }
595
+
596
+ // ===================================================================
597
+ // Context Resolution
598
+ // ===================================================================
599
+
600
+ /**
601
+ * Resolve context from available sources
602
+ * @param {Object} [options] - Options with optional context
603
+ * @returns {Object} - Resolved context
604
+ */
605
+ function resolveContext(options) {
606
+ if (options && options.context) {
607
+ return options.context;
608
+ }
609
+ if (root.LuaUTM && typeof root.LuaUTM.getContext === 'function') {
610
+ return root.LuaUTM.getContext();
611
+ }
612
+
613
+ // No UTM module available - create minimal default context
614
+ return {
615
+ utm: {},
616
+ referrer: {
617
+ source: 'direct',
618
+ category: 'direct',
619
+ url: ''
620
+ },
621
+ userAgent: {
622
+ raw: '',
623
+ isMobile: false,
624
+ isTablet: false,
625
+ isDesktop: true
626
+ },
627
+ timestamp: Date.now(),
628
+ hasUTM: false,
629
+ primaryIntent: 'default'
630
+ };
631
+ }
632
+
633
+ // ===================================================================
634
+ // Main Personalization Functions
635
+ // ===================================================================
636
+
637
+ /**
638
+ * Apply personalization to the page via data-personalize attributes
639
+ * Main entry point for personalization
640
+ *
641
+ * Supported data-personalize values:
642
+ * - "hero" : Generic hero section (sets data-intent, data-source)
643
+ * - "image" : Image slot (sets src or background-image)
644
+ * - "headline" : Headline text
645
+ * - "subheadline" : Subheadline text
646
+ * - "ctaLabel" : CTA button text
647
+ * - "ctaLink" : CTA link href
648
+ *
649
+ * @param {Object} [options] - Configuration options
650
+ * @param {Object} [options.context] - Pre-computed UTM context
651
+ * @param {Object} [options.rules] - Custom matching rules
652
+ * @param {Object} options.templates - User-provided templates (REQUIRED)
653
+ * @param {boolean} [options.enableAI] - Enable AI-powered decisions
654
+ * @param {Object} [options.aiConfig] - AI configuration (required if enableAI is true)
655
+ * @param {boolean} [options.randomFallback] - Enable random A/B fallback (default: true)
656
+ * @param {boolean} [options.log] - Enable console logging (default: true)
657
+ * @returns {Object|Promise<Object>} - Result with applied decision (Promise if AI enabled)
658
+ */
659
+ function personalize(options) {
660
+ options = options || {};
661
+
662
+ // Templates are required
663
+ if (!options.templates || (0, _typeof2.default)(options.templates) !== 'object' || Object.keys(options.templates).length === 0) {
664
+ console.error('[Lua Personalize] Templates are required. Provide templates via options.templates');
665
+ return {
666
+ template: null,
667
+ intent: 'default',
668
+ source: 'error',
669
+ context: {},
670
+ error: 'No templates provided'
671
+ };
672
+ }
673
+ var context = resolveContext(options);
674
+ var decision = DecisionEngine.decide(context, options);
675
+
676
+ // If decision is a Promise (AI path), handle async flow
677
+ if (decision && typeof decision.then === 'function') {
678
+ return decision.then(function (aiDecision) {
679
+ return applyDecisionToDOM(aiDecision, options);
680
+ }).catch(function (err) {
681
+ console.warn('[Lua Personalize] AI decision failed, using standard:', err.message);
682
+ // Fallback to standard decision + DOM application
683
+ var fallbackDecision = DecisionEngine.standardDecide(context, options);
684
+ return applyDecisionToDOM(fallbackDecision, options);
685
+ });
686
+ }
687
+
688
+ // Synchronous path (standard engine)
689
+ return applyDecisionToDOM(decision, options);
690
+ }
691
+
692
+ /**
693
+ * Async personalization with timeout fallback
694
+ * Uses LuaUTM.getContextAsync for non-blocking UTM extraction
695
+ * Automatically handles AI decisions (which are always async)
696
+ *
697
+ * @param {Object} [options] - Configuration options
698
+ * @returns {Promise<Object>} - Result with applied decision
699
+ */
700
+ function personalizeAsync(options) {
701
+ options = options || {};
702
+
703
+ // Use async context getter if available
704
+ if (root.LuaUTM && typeof root.LuaUTM.getContextAsync === 'function') {
705
+ return root.LuaUTM.getContextAsync(options).then(function (context) {
706
+ options.context = context;
707
+ return personalize(options);
708
+ }).then(function (decision) {
709
+ // Ensure we always return a resolved promise
710
+ return decision;
711
+ }).catch(function (err) {
712
+ console.warn('[Lua Personalize] Async error, using default:', err);
713
+ // Force standard engine fallback
714
+ var fallbackOptions = {
715
+ templates: options.templates,
716
+ context: resolveContext(options),
717
+ log: options.log
718
+ };
719
+ var fallbackDecision = DecisionEngine.standardDecide(fallbackOptions.context, fallbackOptions);
720
+ return applyDecisionToDOM(fallbackDecision, fallbackOptions);
721
+ });
722
+ }
723
+
724
+ // Wrap synchronous/AI personalization in a promise
725
+ try {
726
+ var result = personalize(options);
727
+ // If result is a promise (AI path), return it directly
728
+ if (result && typeof result.then === 'function') {
729
+ return result;
730
+ }
731
+ return Promise.resolve(result);
732
+ } catch (err) {
733
+ console.warn('[Lua Personalize] Error, using default:', err);
734
+ var defaultContext = {
735
+ utm: {},
736
+ referrer: {
737
+ source: 'direct',
738
+ category: 'direct',
739
+ url: ''
740
+ },
741
+ userAgent: {
742
+ raw: '',
743
+ isMobile: false,
744
+ isTablet: false,
745
+ isDesktop: true
746
+ },
747
+ timestamp: Date.now(),
748
+ hasUTM: false,
749
+ primaryIntent: 'default'
750
+ };
751
+ var fallback = DecisionEngine.standardDecide(defaultContext, {
752
+ templates: options.templates
753
+ });
754
+ return Promise.resolve(applyDecisionToDOM(fallback, options));
755
+ }
756
+ }
757
+
758
+ /**
759
+ * Auto-initialize personalization when DOM is ready
760
+ * Scans for data-personalize attributes and applies content
761
+ * @param {Object} [options] - Configuration options
762
+ */
763
+ function autoInit(options) {
764
+ options = options || {};
765
+ function run() {
766
+ // Check if there are any data-personalize elements on the page
767
+ var elements = findPersonalizeElements();
768
+ if (elements.length > 0) {
769
+ personalize(options);
770
+ }
771
+ }
772
+
773
+ // Wait for DOM ready
774
+ if (typeof document !== 'undefined') {
775
+ if (document.readyState === 'loading') {
776
+ document.addEventListener('DOMContentLoaded', run);
777
+ } else {
778
+ run();
779
+ }
780
+ }
781
+ }
782
+
783
+ // ===================================================================
784
+ // Public API - Register on window.LuaPersonalize
785
+ // ===================================================================
786
+
787
+ var LuaPersonalize = {
788
+ // Note: Templates are NOT provided by this package
789
+ // Users must provide their own templates via options.templates
790
+ sanitizer: Sanitizer,
791
+ sanitizeHTML: function sanitizeHTML(html) {
792
+ return Sanitizer.sanitize(html);
793
+ },
794
+ safeSetText: safeSetText,
795
+ safeSetHTML: safeSetHTML,
796
+ findElements: findPersonalizeElements,
797
+ getTemplate: getTemplate,
798
+ engine: DecisionEngine,
799
+ personalize: personalize,
800
+ personalizeAsync: personalizeAsync,
801
+ autoInit: autoInit,
802
+ chooseWeightedRandom: chooseWeightedRandom,
803
+ getRandomFallbackIntent: getRandomFallbackIntent,
804
+ applyDecisionToDOM: applyDecisionToDOM,
805
+ resolveContext: resolveContext
806
+ };
807
+
808
+ // Expose globally
809
+ root.LuaPersonalize = LuaPersonalize;
810
+ })(typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : void 0);
811
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJyb290IiwiU2FuaXRpemVyIiwiQUxMT1dFRF9UQUdTIiwiQUxMT1dFRF9BVFRSUyIsIkRBTkdFUk9VU19VUkkiLCJFVkVOVF9IQU5ETEVSIiwiaGFzRE9NUGFyc2VyIiwiRE9NUGFyc2VyIiwiZSIsInNhbml0aXplV2l0aERPTVBhcnNlciIsImRpcnR5IiwidHJpbSIsInBhcnNlciIsImRvYyIsInBhcnNlRnJvbVN0cmluZyIsImJvZHkiLCJ3YWxrQW5kQ2xlYW4iLCJjb25zb2xlIiwid2FybiIsInNhbml0aXplV2l0aFJlZ2V4Iiwibm9kZSIsIm91dHB1dCIsImkiLCJjaGlsZE5vZGVzIiwibGVuZ3RoIiwiY2hpbGQiLCJub2RlVHlwZSIsImVzY2FwZVRleHQiLCJ0ZXh0Q29udGVudCIsInRhZ05hbWUiLCJ0b0xvd2VyQ2FzZSIsImNsZWFuQXR0cmlidXRlcyIsImVsZW1lbnQiLCJhdHRyU3RyIiwiYXR0cnMiLCJhdHRyaWJ1dGVzIiwiYXR0ciIsIm5hbWUiLCJ2YWx1ZSIsInRlc3QiLCJlc2NhcGVBdHRyIiwidGV4dCIsInJlcGxhY2UiLCJodG1sIiwiREFOR0VST1VTX1BBVFRFUk5TIiwic2FuaXRpemVkIiwiZm9yRWFjaCIsInBhdHRlcm4iLCJtYXRjaCIsInRhZyIsImNoYXJBdCIsImNsZWFuQXR0cnMiLCJhdHRyUmVnZXgiLCJhdHRyTWF0Y2giLCJleGVjIiwiYXR0ck5hbWUiLCJ2YWwiLCJzYW5pdGl6ZSIsInNhZmVTZXRUZXh0Iiwic2FmZVNldEhUTUwiLCJpbm5lckhUTUwiLCJmaW5kUGVyc29uYWxpemVFbGVtZW50cyIsImtleSIsInNlYXJjaFJvb3QiLCJkb2N1bWVudCIsInNlbGVjdG9yIiwicXVlcnlTZWxlY3RvckFsbCIsImdldFRlbXBsYXRlIiwiaW50ZW50IiwidXNlclRlbXBsYXRlcyIsIl90eXBlb2YyIiwiZGVmYXVsdCIsImZpcnN0S2V5IiwiT2JqZWN0Iiwia2V5cyIsImNob29zZVdlaWdodGVkUmFuZG9tIiwibmFtZXMiLCJ3ZWlnaHRzIiwic3VtIiwibiIsIk1hdGgiLCJyYW5kb20iLCJsaW1pdCIsImdldFJhbmRvbUZhbGxiYWNrSW50ZW50IiwicHVzaCIsIkRlY2lzaW9uRW5naW5lIiwic3RhbmRhcmREZWNpZGUiLCJjb250ZXh0Iiwib3B0aW9ucyIsImN1c3RvbVJ1bGVzIiwicnVsZXMiLCJ0ZW1wbGF0ZXMiLCJlbmFibGVSYW5kb21GYWxsYmFjayIsInJhbmRvbUZhbGxiYWNrIiwidGVtcGxhdGUiLCJzb3VyY2UiLCJlcnJvciIsInByaW1hcnlJbnRlbnQiLCJoYXNVVE0iLCJyZWZlcnJlciIsImNhdGVnb3J5IiwicnVsZUtleSIsInJ1bGUiLCJyYW5kb21JbnRlbnQiLCJMdWFXZWlnaHRlZEhpc3RvcnkiLCJyZWNvcmRWaXNpdCIsInNlbGVjdGVkVmFyaWFudCIsImFpRGVjaXNpb24iLCJkZWNpZGUiLCJlbmFibGVBSSIsImFpQ29uZmlnIiwiTHVhQUlQZXJzb25hbGl6ZSIsInNlbGYiLCJhaU1vZHVsZSIsInJlYWRpbmVzcyIsImlzUmVhZHkiLCJyZWFkeSIsImNhdGNoIiwiZmFsbGJhY2siLCJmYWxsYmFja1RvU3RhbmRhcmQiLCJtZXNzYWdlIiwiYXBwbHlEZWNpc2lvblRvRE9NIiwiZGVjaXNpb24iLCJsb2ciLCJzbG90cyIsInNsb3QiLCJlbGVtZW50cyIsInNyYyIsImFsdCIsImhlYWRsaW5lIiwic3R5bGUiLCJiYWNrZ3JvdW5kSW1hZ2UiLCJocmVmIiwiaGVyb0VsZW1lbnRzIiwiaCIsImhlcm9FbCIsInNldEF0dHJpYnV0ZSIsImltYWdlIiwicXVlcnlTZWxlY3RvciIsInV0bVBhcmFtcyIsInV0bSIsImFpUG93ZXJlZCIsInJlc29sdmVDb250ZXh0IiwiTHVhVVRNIiwiZ2V0Q29udGV4dCIsInVybCIsInVzZXJBZ2VudCIsInJhdyIsImlzTW9iaWxlIiwiaXNUYWJsZXQiLCJpc0Rlc2t0b3AiLCJ0aW1lc3RhbXAiLCJEYXRlIiwibm93IiwicGVyc29uYWxpemUiLCJ0aGVuIiwiZXJyIiwiZmFsbGJhY2tEZWNpc2lvbiIsInBlcnNvbmFsaXplQXN5bmMiLCJnZXRDb250ZXh0QXN5bmMiLCJmYWxsYmFja09wdGlvbnMiLCJyZXN1bHQiLCJQcm9taXNlIiwicmVzb2x2ZSIsImRlZmF1bHRDb250ZXh0IiwiYXV0b0luaXQiLCJydW4iLCJyZWFkeVN0YXRlIiwiYWRkRXZlbnRMaXN0ZW5lciIsIkx1YVBlcnNvbmFsaXplIiwic2FuaXRpemVyIiwic2FuaXRpemVIVE1MIiwiZmluZEVsZW1lbnRzIiwiZW5naW5lIiwid2luZG93IiwiZ2xvYmFsIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BlcnNvbmFsaXphdGlvbi5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJcbi8qKlxuICogRE9NIFBlcnNvbmFsaXphdGlvbiBFbmdpbmVcbiAqIEhhbmRsZXMgY29udGVudCBpbmplY3Rpb24gd2l0aCBkYXRhLXBlcnNvbmFsaXplIGF0dHJpYnV0ZXNcbiAqIFVzZXMgdGV4dENvbnRlbnQgZm9yIHRleHQsIERPTVB1cmlmeS1zdHlsZSBzYW5pdGl6ZWQgSFRNTCBmb3IgcmljaCBjb250ZW50XG4gKlxuICogTm8gRVM2IGltcG9ydHMgLSBzZWxmLWNvbnRhaW5lZCBJSUZFIHRoYXQgcmVnaXN0ZXJzIG9uIHdpbmRvdy5MdWFQZXJzb25hbGl6ZVxuICogRGVwZW5kcyBvbiB3aW5kb3cuTHVhVVRNIChmcm9tIHV0bS5qcykgZm9yIGNvbnRleHQgZXh0cmFjdGlvblxuICogRmFsbHMgYmFjayB0byByYW5kb20gQS9CIHRlc3Qgd2hlbiBubyBVVE0gcGFyYW1zIGFyZSBwcmVzZW50XG4gKi9cbjsoZnVuY3Rpb24gKHJvb3QpIHtcbiAgICAndXNlIHN0cmljdCdcblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBET01QdXJpZnktc3R5bGUgSFRNTCBTYW5pdGl6ZXIgKGlubGluZSwgT1dBU1AtcmVjb21tZW5kZWQgYXBwcm9hY2gpXG4gICAgLy8gUHJvdmlkZXMgc2FmZSBIVE1MIGluamVjdGlvbiB3aXRob3V0IGV4dGVybmFsIGRlcGVuZGVuY2llc1xuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIC8qKlxuICAgICAqIElubGluZSBET01QdXJpZnktc3R5bGUgc2FuaXRpemVyXG4gICAgICogVXNlcyB0aGUgYnJvd3NlcidzIERPTVBhcnNlciB0byBzYWZlbHkgcGFyc2UgYW5kIHNhbml0aXplIEhUTUxcbiAgICAgKiBGYWxscyBiYWNrIHRvIHJlZ2V4LWJhc2VkIHNhbml0aXphdGlvbiBpZiBET01QYXJzZXIgdW5hdmFpbGFibGVcbiAgICAgKi9cbiAgICB2YXIgU2FuaXRpemVyID0gKGZ1bmN0aW9uICgpIHtcblxuICAgICAgICAvLyBBbGxvd2VkIEhUTUwgdGFncyAoc2FmZSBmb3IgY29udGVudCBpbmplY3Rpb24pXG4gICAgICAgIHZhciBBTExPV0VEX1RBR1MgPSB7XG4gICAgICAgICAgICAncCc6IHRydWUsICdzcGFuJzogdHJ1ZSwgJ3N0cm9uZyc6IHRydWUsICdlbSc6IHRydWUsXG4gICAgICAgICAgICAnYic6IHRydWUsICdpJzogdHJ1ZSwgJ2JyJzogdHJ1ZSwgJ2EnOiB0cnVlLCAnaW1nJzogdHJ1ZSxcbiAgICAgICAgICAgICdoMSc6IHRydWUsICdoMic6IHRydWUsICdoMyc6IHRydWUsICdoNCc6IHRydWUsICdoNSc6IHRydWUsICdoNic6IHRydWUsXG4gICAgICAgICAgICAnZGl2JzogdHJ1ZSwgJ3NlY3Rpb24nOiB0cnVlLCAndWwnOiB0cnVlLCAnb2wnOiB0cnVlLCAnbGknOiB0cnVlLFxuICAgICAgICAgICAgJ2Jsb2NrcXVvdGUnOiB0cnVlLCAnZmlndXJlJzogdHJ1ZSwgJ2ZpZ2NhcHRpb24nOiB0cnVlXG4gICAgICAgIH1cblxuICAgICAgICAvLyBBbGxvd2VkIEhUTUwgYXR0cmlidXRlcyAoc2FmZSBzdWJzZXQpXG4gICAgICAgIHZhciBBTExPV0VEX0FUVFJTID0ge1xuICAgICAgICAgICAgJ2hyZWYnOiB0cnVlLCAnc3JjJzogdHJ1ZSwgJ2FsdCc6IHRydWUsICdjbGFzcyc6IHRydWUsXG4gICAgICAgICAgICAnaWQnOiB0cnVlLCAndGl0bGUnOiB0cnVlLCAndGFyZ2V0JzogdHJ1ZSwgJ3JlbCc6IHRydWUsXG4gICAgICAgICAgICAnd2lkdGgnOiB0cnVlLCAnaGVpZ2h0JzogdHJ1ZSwgJ2xvYWRpbmcnOiB0cnVlXG4gICAgICAgIH1cblxuICAgICAgICAvLyBEYW5nZXJvdXMgVVJJIHNjaGVtZXNcbiAgICAgICAgdmFyIERBTkdFUk9VU19VUkkgPSAvXihqYXZhc2NyaXB0fHZic2NyaXB0fGRhdGEpOi9pXG5cbiAgICAgICAgLy8gRXZlbnQgaGFuZGxlciBwYXR0ZXJuIChvbmNsaWNrLCBvbmVycm9yLCBvbmxvYWQsIGV0Yy4pXG4gICAgICAgIHZhciBFVkVOVF9IQU5ETEVSID0gL15vbi9pXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENoZWNrIGlmIERPTVBhcnNlciBpcyBhdmFpbGFibGUgKG1vZGVybiBicm93c2VycylcbiAgICAgICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBoYXNET01QYXJzZXIoKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgRE9NUGFyc2VyICE9PSAndW5kZWZpbmVkJyAmJiBuZXcgRE9NUGFyc2VyKClcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTYW5pdGl6ZSBIVE1MIHVzaW5nIERPTVBhcnNlciAocHJlZmVycmVkLCBzZWN1cmUgbWV0aG9kKVxuICAgICAgICAgKiBQYXJzZXMgSFRNTCBpbnRvIGEgRE9NIHRyZWUsIHdhbGtzIG5vZGVzLCBhbmQgcmVidWlsZHMgc2FmZSBIVE1MXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBkaXJ0eSAtIFVudHJ1c3RlZCBIVE1MIHN0cmluZ1xuICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIFNhbml0aXplZCBIVE1MIHN0cmluZ1xuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gc2FuaXRpemVXaXRoRE9NUGFyc2VyKGRpcnR5KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRpcnR5ICE9PSAnc3RyaW5nJyB8fCAhZGlydHkudHJpbSgpKSByZXR1cm4gJydcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyc2VyID0gbmV3IERPTVBhcnNlcigpXG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IHBhcnNlci5wYXJzZUZyb21TdHJpbmcoZGlydHksICd0ZXh0L2h0bWwnKVxuICAgICAgICAgICAgICAgIHZhciBib2R5ID0gZG9jLmJvZHlcblxuICAgICAgICAgICAgICAgIGlmICghYm9keSkgcmV0dXJuICcnXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gd2Fsa0FuZENsZWFuKGJvZHkpXG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIFNhbml0aXplcl0gRE9NUGFyc2VyIGZhaWxlZCwgdXNpbmcgZmFsbGJhY2s6JywgZSlcbiAgICAgICAgICAgICAgICByZXR1cm4gc2FuaXRpemVXaXRoUmVnZXgoZGlydHkpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogUmVjdXJzaXZlbHkgd2FsayBET00gbm9kZXMgYW5kIGJ1aWxkIGNsZWFuIEhUTUxcbiAgICAgICAgICogQHBhcmFtIHtOb2RlfSBub2RlIC0gRE9NIG5vZGUgdG8gcHJvY2Vzc1xuICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIENsZWFuZWQgSFRNTCBzdHJpbmdcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIHdhbGtBbmRDbGVhbihub2RlKSB7XG4gICAgICAgICAgICB2YXIgb3V0cHV0ID0gJydcblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBub2RlLmNoaWxkTm9kZXNbaV1cblxuICAgICAgICAgICAgICAgIC8vIFRleHQgbm9kZSAtIHNhZmUgdG8gaW5jbHVkZVxuICAgICAgICAgICAgICAgIGlmIChjaGlsZC5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgKz0gZXNjYXBlVGV4dChjaGlsZC50ZXh0Q29udGVudClcbiAgICAgICAgICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBFbGVtZW50IG5vZGVcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBjaGlsZC50YWdOYW1lLnRvTG93ZXJDYXNlKClcblxuICAgICAgICAgICAgICAgICAgICAvLyBTa2lwIGRpc2FsbG93ZWQgdGFncyBlbnRpcmVseSAoaW5jbHVkaW5nIGNoaWxkcmVuKVxuICAgICAgICAgICAgICAgICAgICBpZiAodGFnTmFtZSA9PT0gJ3NjcmlwdCcgfHwgdGFnTmFtZSA9PT0gJ3N0eWxlJyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9PT0gJ2lmcmFtZScgfHwgdGFnTmFtZSA9PT0gJ29iamVjdCcgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPT09ICdlbWJlZCcgfHwgdGFnTmFtZSA9PT0gJ2Zvcm0nIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID09PSAnaW5wdXQnIHx8IHRhZ05hbWUgPT09ICd0ZXh0YXJlYScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0YWcgaXMgYWxsb3dlZCwgaW5jbHVkZSBpdCB3aXRoIGZpbHRlcmVkIGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICAgICAgaWYgKEFMTE9XRURfVEFHU1t0YWdOYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0ICs9ICc8JyArIHRhZ05hbWVcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dCArPSBjbGVhbkF0dHJpYnV0ZXMoY2hpbGQpXG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQgKz0gJz4nXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNlbGYtY2xvc2luZyB0YWdzXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGFnTmFtZSA9PT0gJ2JyJyB8fCB0YWdOYW1lID09PSAnaW1nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlY3Vyc2UgaW50byBjaGlsZHJlblxuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0ICs9IHdhbGtBbmRDbGVhbihjaGlsZClcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dCArPSAnPC8nICsgdGFnTmFtZSArICc+J1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGFnIG5vdCBhbGxvd2VkIC0gaW5jbHVkZSBjaGlsZHJlbiBvbmx5IChzdHJpcCB0aGUgdGFnKVxuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0ICs9IHdhbGtBbmRDbGVhbihjaGlsZClcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG91dHB1dFxuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZpbHRlciBlbGVtZW50IGF0dHJpYnV0ZXMgdG8gb25seSBhbGxvd2VkIG9uZXNcbiAgICAgICAgICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50IC0gRE9NIGVsZW1lbnRcbiAgICAgICAgICogQHJldHVybnMge3N0cmluZ30gLSBBdHRyaWJ1dGUgc3RyaW5nXG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBjbGVhbkF0dHJpYnV0ZXMoZWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIGF0dHJTdHIgPSAnJ1xuICAgICAgICAgICAgdmFyIGF0dHJzID0gZWxlbWVudC5hdHRyaWJ1dGVzXG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXR0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgYXR0ciA9IGF0dHJzW2ldXG4gICAgICAgICAgICAgICAgdmFyIG5hbWUgPSBhdHRyLm5hbWUudG9Mb3dlckNhc2UoKVxuICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IGF0dHIudmFsdWVcblxuICAgICAgICAgICAgICAgIC8vIFNraXAgZXZlbnQgaGFuZGxlcnMgKG9uY2xpY2ssIG9uZXJyb3IsIGV0Yy4pXG4gICAgICAgICAgICAgICAgaWYgKEVWRU5UX0hBTkRMRVIudGVzdChuYW1lKSkgY29udGludWVcblxuICAgICAgICAgICAgICAgIC8vIFNraXAgZGlzYWxsb3dlZCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKCFBTExPV0VEX0FUVFJTW25hbWVdKSBjb250aW51ZVxuXG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgVVJJIHNhZmV0eSBmb3IgaHJlZi9zcmNcbiAgICAgICAgICAgICAgICBpZiAoKG5hbWUgPT09ICdocmVmJyB8fCBuYW1lID09PSAnc3JjJykgJiYgREFOR0VST1VTX1VSSS50ZXN0KHZhbHVlLnRyaW0oKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBBZGQgcmVsPVwibm9vcGVuZXIgbm9yZWZlcnJlclwiIGZvciBleHRlcm5hbCBsaW5rc1xuICAgICAgICAgICAgICAgIGlmIChuYW1lID09PSAndGFyZ2V0JyAmJiB2YWx1ZSA9PT0gJ19ibGFuaycpIHtcbiAgICAgICAgICAgICAgICAgICAgYXR0clN0ciArPSAnIHRhcmdldD1cIl9ibGFua1wiIHJlbD1cIm5vb3BlbmVyIG5vcmVmZXJyZXJcIidcbiAgICAgICAgICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBhdHRyU3RyICs9ICcgJyArIG5hbWUgKyAnPVwiJyArIGVzY2FwZUF0dHIodmFsdWUpICsgJ1wiJ1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gYXR0clN0clxuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVzY2FwZSB0ZXh0IGNvbnRlbnQgZm9yIHNhZmUgSFRNTCBpbmNsdXNpb25cbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBSYXcgdGV4dFxuICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIEVzY2FwZWQgdGV4dFxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gZXNjYXBlVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICBpZiAoIXRleHQpIHJldHVybiAnJ1xuICAgICAgICAgICAgcmV0dXJuIHRleHRcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvJi9nLCAnJmFtcDsnKVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC88L2csICcmbHQ7JylcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvPi9nLCAnJmd0OycpXG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogRXNjYXBlIGF0dHJpYnV0ZSB2YWx1ZSBmb3Igc2FmZSBIVE1MIGluY2x1c2lvblxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBSYXcgYXR0cmlidXRlIHZhbHVlXG4gICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IC0gRXNjYXBlZCBhdHRyaWJ1dGUgdmFsdWVcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIGVzY2FwZUF0dHIodmFsdWUpIHtcbiAgICAgICAgICAgIGlmICghdmFsdWUpIHJldHVybiAnJ1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoLyYvZywgJyZhbXA7JylcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvXCIvZywgJyZxdW90OycpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoLycvZywgJyYjMzk7JylcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvPC9nLCAnJmx0OycpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoLz4vZywgJyZndDsnKVxuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZhbGxiYWNrIHJlZ2V4LWJhc2VkIHNhbml0aXplciBmb3IgZW52aXJvbm1lbnRzIHdpdGhvdXQgRE9NUGFyc2VyXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBodG1sIC0gUmF3IEhUTUwgc3RyaW5nXG4gICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IC0gU2FuaXRpemVkIEhUTUxcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIHNhbml0aXplV2l0aFJlZ2V4KGh0bWwpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaHRtbCAhPT0gJ3N0cmluZycpIHJldHVybiAnJ1xuXG4gICAgICAgICAgICB2YXIgREFOR0VST1VTX1BBVFRFUk5TID0gW1xuICAgICAgICAgICAgICAgIC88c2NyaXB0XFxiW148XSooPzooPyE8XFwvc2NyaXB0Pik8W148XSopKjxcXC9zY3JpcHQ+L2dpLFxuICAgICAgICAgICAgICAgIC88aWZyYW1lXFxiW148XSooPzooPyE8XFwvaWZyYW1lPik8W148XSopKjxcXC9pZnJhbWU+L2dpLFxuICAgICAgICAgICAgICAgIC88b2JqZWN0XFxiW148XSooPzooPyE8XFwvb2JqZWN0Pik8W148XSopKjxcXC9vYmplY3Q+L2dpLFxuICAgICAgICAgICAgICAgIC88ZW1iZWRcXGJbXj5dKj4vZ2ksXG4gICAgICAgICAgICAgICAgLzxsaW5rXFxiW14+XSo+L2dpLFxuICAgICAgICAgICAgICAgIC88c3R5bGVcXGJbXjxdKig/Oig/ITxcXC9zdHlsZT4pPFtePF0qKSo8XFwvc3R5bGU+L2dpLFxuICAgICAgICAgICAgICAgIC88Zm9ybVxcYltePF0qKD86KD8hPFxcL2Zvcm0+KTxbXjxdKikqPFxcL2Zvcm0+L2dpLFxuICAgICAgICAgICAgICAgIC9qYXZhc2NyaXB0Oi9naSxcbiAgICAgICAgICAgICAgICAvdmJzY3JpcHQ6L2dpLFxuICAgICAgICAgICAgICAgIC9kYXRhOi9naSxcbiAgICAgICAgICAgICAgICAvb25cXHcrXFxzKj0vZ2lcbiAgICAgICAgICAgIF1cblxuICAgICAgICAgICAgdmFyIHNhbml0aXplZCA9IGh0bWxcblxuICAgICAgICAgICAgREFOR0VST1VTX1BBVFRFUk5TLmZvckVhY2goZnVuY3Rpb24gKHBhdHRlcm4pIHtcbiAgICAgICAgICAgICAgICBzYW5pdGl6ZWQgPSBzYW5pdGl6ZWQucmVwbGFjZShwYXR0ZXJuLCAnJylcbiAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgIC8vIFJlbW92ZSBkaXNhbGxvd2VkIHRhZ3MgYnV0IGtlZXAgdGhlaXIgdGV4dCBjb250ZW50XG4gICAgICAgICAgICBzYW5pdGl6ZWQgPSBzYW5pdGl6ZWQucmVwbGFjZSgvPFxcLz8oXFx3KykoW14+XSopPi9nLCBmdW5jdGlvbiAobWF0Y2gsIHRhZ05hbWUsIGF0dHJzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRhZyA9IHRhZ05hbWUudG9Mb3dlckNhc2UoKVxuICAgICAgICAgICAgICAgIGlmICghQUxMT1dFRF9UQUdTW3RhZ10pIHJldHVybiAnJ1xuXG4gICAgICAgICAgICAgICAgLy8gRm9yIGNsb3NpbmcgdGFncywganVzdCByZXR1cm4gdGhlIGNsb3NpbmcgdGFnXG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoLmNoYXJBdCgxKSA9PT0gJy8nKSByZXR1cm4gJzwvJyArIHRhZyArICc+J1xuXG4gICAgICAgICAgICAgICAgLy8gRmlsdGVyIGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICB2YXIgY2xlYW5BdHRycyA9ICcnXG4gICAgICAgICAgICAgICAgdmFyIGF0dHJSZWdleCA9IC8oXFx3Kyk9WydcIl0oW14nXCJdKilbJ1wiXS9nXG4gICAgICAgICAgICAgICAgdmFyIGF0dHJNYXRjaFxuXG4gICAgICAgICAgICAgICAgd2hpbGUgKChhdHRyTWF0Y2ggPSBhdHRyUmVnZXguZXhlYyhhdHRycykpICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhdHRyTmFtZSA9IGF0dHJNYXRjaFsxXS50b0xvd2VyQ2FzZSgpXG4gICAgICAgICAgICAgICAgICAgIGlmIChBTExPV0VEX0FUVFJTW2F0dHJOYW1lXSAmJiAhRVZFTlRfSEFORExFUi50ZXN0KGF0dHJOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbCA9IGF0dHJNYXRjaFsyXVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChhdHRyTmFtZSA9PT0gJ2hyZWYnIHx8IGF0dHJOYW1lID09PSAnc3JjJykgJiYgREFOR0VST1VTX1VSSS50ZXN0KHZhbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYW5BdHRycyArPSAnICcgKyBhdHRyTmFtZSArICc9XCInICsgdmFsICsgJ1wiJ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuICc8JyArIHRhZyArIGNsZWFuQXR0cnMgKyAnPidcbiAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgIHJldHVybiBzYW5pdGl6ZWRcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFB1YmxpYyBzYW5pdGl6ZXIgQVBJXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNhbml0aXplIEhUTUwgc3RyaW5nIChtYWluIGVudHJ5IHBvaW50KVxuICAgICAgICAgICAgICogVXNlcyBET01QYXJzZXIgd2hlbiBhdmFpbGFibGUsIHJlZ2V4IGZhbGxiYWNrIG90aGVyd2lzZVxuICAgICAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IGRpcnR5IC0gVW50cnVzdGVkIEhUTUxcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IC0gU2FuaXRpemVkIEhUTUxcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2FuaXRpemU6IGZ1bmN0aW9uIChkaXJ0eSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZGlydHkgIT09ICdzdHJpbmcnKSByZXR1cm4gJydcbiAgICAgICAgICAgICAgICBpZiAoIWRpcnR5LnRyaW0oKSkgcmV0dXJuICcnXG5cbiAgICAgICAgICAgICAgICBpZiAoaGFzRE9NUGFyc2VyKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNhbml0aXplV2l0aERPTVBhcnNlcihkaXJ0eSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNhbml0aXplV2l0aFJlZ2V4KGRpcnR5KVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZXNjYXBlVGV4dDogZXNjYXBlVGV4dCxcbiAgICAgICAgICAgIGVzY2FwZUF0dHI6IGVzY2FwZUF0dHJcbiAgICAgICAgfVxuICAgIH0pKClcblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBUZW1wbGF0ZXMgJiBBc3NldHNcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gTk9URTogVGVtcGxhdGVzIGFyZSBOT1QgcHJvdmlkZWQgYnkgdGhpcyBwYWNrYWdlLlxuICAgIC8vIFVzZXJzIG11c3QgcHJvdmlkZSB0aGVpciBvd24gdGVtcGxhdGVzIHZpYSBvcHRpb25zLnRlbXBsYXRlc1xuICAgIC8vIFRoaXMga2VlcHMgdGhlIHBhY2thZ2UgbW9kdWxhciBhbmQgYWxsb3dzIHVzZXJzIGZ1bGwgY29udHJvbFxuICAgIC8vIG92ZXIgdGhlaXIgY29udGVudCwgYXNzZXRzLCBhbmQgcGVyc29uYWxpemF0aW9uIHN0cmF0ZWd5LlxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIERPTSBJbnRlcmFjdGlvbiAoc2FmZSBtZXRob2RzIC0gbmV2ZXIgcmF3IGlubmVySFRNTClcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICAvKipcbiAgICAgKiBTYWZlbHkgc2V0IHRleHQgY29udGVudCBvbiBhbiBlbGVtZW50IChubyBIVE1MIHBhcnNpbmcpXG4gICAgICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50IC0gRE9NIGVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dCAtIFRleHQgdG8gc2V0XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2FmZVNldFRleHQoZWxlbWVudCwgdGV4dCkge1xuICAgICAgICBpZiAoIWVsZW1lbnQpIHJldHVyblxuICAgICAgICBlbGVtZW50LnRleHRDb250ZW50ID0gdGV4dFxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNhZmVseSBzZXQgSFRNTCBjb250ZW50IG9uIGFuIGVsZW1lbnQgKERPTVB1cmlmeS1zYW5pdGl6ZWQpXG4gICAgICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50IC0gRE9NIGVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaHRtbCAtIEhUTUwgdG8gc2V0ICh3aWxsIGJlIHNhbml0aXplZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzYWZlU2V0SFRNTChlbGVtZW50LCBodG1sKSB7XG4gICAgICAgIGlmICghZWxlbWVudCkgcmV0dXJuXG4gICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gU2FuaXRpemVyLnNhbml0aXplKGh0bWwpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmluZCBhbGwgZWxlbWVudHMgd2l0aCBkYXRhLXBlcnNvbmFsaXplIGF0dHJpYnV0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBba2V5XSAtIE9wdGlvbmFsIHNwZWNpZmljIGtleSB0byBmaW5kXG4gICAgICogQHBhcmFtIHtFbGVtZW50fSBbc2VhcmNoUm9vdF0gLSBSb290IGVsZW1lbnQgdG8gc2VhcmNoIGZyb20gKGRlZmF1bHQ6IGRvY3VtZW50KVxuICAgICAqIEByZXR1cm5zIHtOb2RlTGlzdHxBcnJheX0gLSBNYXRjaGluZyBlbGVtZW50c1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbmRQZXJzb25hbGl6ZUVsZW1lbnRzKGtleSwgc2VhcmNoUm9vdCkge1xuICAgICAgICBzZWFyY2hSb290ID0gc2VhcmNoUm9vdCB8fCAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyA/IGRvY3VtZW50IDogbnVsbClcbiAgICAgICAgaWYgKCFzZWFyY2hSb290KSByZXR1cm4gW11cblxuICAgICAgICB2YXIgc2VsZWN0b3IgPSBrZXlcbiAgICAgICAgICAgID8gJ1tkYXRhLXBlcnNvbmFsaXplPVwiJyArIGtleSArICdcIl0nXG4gICAgICAgICAgICA6ICdbZGF0YS1wZXJzb25hbGl6ZV0nXG5cbiAgICAgICAgcmV0dXJuIHNlYXJjaFJvb3QucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcilcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGVtcGxhdGUgZm9yIGEgZ2l2ZW4gaW50ZW50XG4gICAgICogVGVtcGxhdGVzIG11c3QgYmUgcHJvdmlkZWQgYnkgdGhlIHVzZXIgdmlhIG9wdGlvbnMudGVtcGxhdGVzXG4gICAgICogRmFsbHMgYmFjayB0byAnZGVmYXVsdCcgdGVtcGxhdGUgaWYgaW50ZW50IG5vdCBmb3VuZFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpbnRlbnQgLSBJbnRlbnQga2V5XG4gICAgICogQHBhcmFtIHtPYmplY3R9IHVzZXJUZW1wbGF0ZXMgLSBVc2VyLXByb3ZpZGVkIHRlbXBsYXRlcyAocmVxdWlyZWQpXG4gICAgICogQHJldHVybnMge09iamVjdHxudWxsfSAtIFRlbXBsYXRlIGRhdGEgb3IgbnVsbCBpZiBubyB0ZW1wbGF0ZXMgcHJvdmlkZWRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRUZW1wbGF0ZShpbnRlbnQsIHVzZXJUZW1wbGF0ZXMpIHtcbiAgICAgICAgaWYgKCF1c2VyVGVtcGxhdGVzIHx8IHR5cGVvZiB1c2VyVGVtcGxhdGVzICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIFBlcnNvbmFsaXplXSBObyB0ZW1wbGF0ZXMgcHJvdmlkZWQuIFRlbXBsYXRlcyBtdXN0IGJlIHBhc3NlZCB2aWEgb3B0aW9ucy50ZW1wbGF0ZXMnKVxuICAgICAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyeSB0byBnZXQgdGhlIGludGVudCB0ZW1wbGF0ZVxuICAgICAgICBpZiAodXNlclRlbXBsYXRlc1tpbnRlbnRdKSB7XG4gICAgICAgICAgICByZXR1cm4gdXNlclRlbXBsYXRlc1tpbnRlbnRdXG4gICAgICAgIH1cblxuICAgICAgICAvLyBGYWxsIGJhY2sgdG8gJ2RlZmF1bHQnIHRlbXBsYXRlIGlmIGF2YWlsYWJsZVxuICAgICAgICBpZiAodXNlclRlbXBsYXRlc1snZGVmYXVsdCddKSB7XG4gICAgICAgICAgICByZXR1cm4gdXNlclRlbXBsYXRlc1snZGVmYXVsdCddXG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBubyBkZWZhdWx0LCByZXR1cm4gdGhlIGZpcnN0IGF2YWlsYWJsZSB0ZW1wbGF0ZVxuICAgICAgICB2YXIgZmlyc3RLZXkgPSBPYmplY3Qua2V5cyh1c2VyVGVtcGxhdGVzKVswXVxuICAgICAgICBpZiAoZmlyc3RLZXkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignW0x1YSBQZXJzb25hbGl6ZV0gSW50ZW50IFwiJyArIGludGVudCArICdcIiBub3QgZm91bmQsIHVzaW5nIGZpcnN0IGF2YWlsYWJsZSB0ZW1wbGF0ZTonLCBmaXJzdEtleSlcbiAgICAgICAgICAgIHJldHVybiB1c2VyVGVtcGxhdGVzW2ZpcnN0S2V5XVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGxcbiAgICB9XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gUmFuZG9tIEEvQiBGYWxsYmFjayAodXNlZCB3aGVuIG5vIFVUTSBwYXJhbXMgYXJlIHByZXNlbnQpXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgLyoqXG4gICAgICogU2ltcGxlIHdlaWdodGVkIHJhbmRvbSBzZWxlY3Rpb24gZm9yIEEvQiBmYWxsYmFja1xuICAgICAqIEBwYXJhbSB7QXJyYXl9IG5hbWVzIC0gQXJyYXkgb2YgYnVja2V0L3RlbXBsYXRlIG5hbWVzXG4gICAgICogQHBhcmFtIHtBcnJheX0gd2VpZ2h0cyAtIENvcnJlc3BvbmRpbmcgd2VpZ2h0c1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IC0gU2VsZWN0ZWQgbmFtZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNob29zZVdlaWdodGVkUmFuZG9tKG5hbWVzLCB3ZWlnaHRzKSB7XG4gICAgICAgIGlmIChuYW1lcy5sZW5ndGggIT09IHdlaWdodHMubGVuZ3RoKSByZXR1cm4gbmFtZXNbMF1cbiAgICAgICAgdmFyIHN1bSA9IDBcbiAgICAgICAgdmFyIGlcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHdlaWdodHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHN1bSArPSB3ZWlnaHRzW2ldXG4gICAgICAgIH1cbiAgICAgICAgdmFyIG4gPSBNYXRoLnJhbmRvbSgpICogc3VtXG4gICAgICAgIHZhciBsaW1pdCA9IDBcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IG5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsaW1pdCArPSB3ZWlnaHRzW2ldXG4gICAgICAgICAgICBpZiAobiA8PSBsaW1pdCkgcmV0dXJuIG5hbWVzW2ldXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5hbWVzW25hbWVzLmxlbmd0aCAtIDFdXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGEgcmFuZG9tIHRlbXBsYXRlIGtleSBmcm9tIHVzZXItcHJvdmlkZWQgdGVtcGxhdGVzXG4gICAgICogVXNlZCBhcyBmYWxsYmFjayB3aGVuIG5vIFVUTS9yZWZlcnJlciBjb250ZXh0IGlzIGF2YWlsYWJsZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB1c2VyVGVtcGxhdGVzIC0gVXNlci1wcm92aWRlZCB0ZW1wbGF0ZXMgKHJlcXVpcmVkKVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gLSBSYW5kb20gdGVtcGxhdGUgaW50ZW50IGtleSBvciBudWxsIGlmIG5vIHRlbXBsYXRlc1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFJhbmRvbUZhbGxiYWNrSW50ZW50KHVzZXJUZW1wbGF0ZXMpIHtcbiAgICAgICAgaWYgKCF1c2VyVGVtcGxhdGVzIHx8IHR5cGVvZiB1c2VyVGVtcGxhdGVzICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBuYW1lcyA9IE9iamVjdC5rZXlzKHVzZXJUZW1wbGF0ZXMpXG4gICAgICAgIGlmIChuYW1lcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsXG4gICAgICAgIH1cblxuICAgICAgICB2YXIgd2VpZ2h0cyA9IFtdXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHdlaWdodHMucHVzaCgxKSAvLyBFcXVhbCB3ZWlnaHQgYnkgZGVmYXVsdFxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjaG9vc2VXZWlnaHRlZFJhbmRvbShuYW1lcywgd2VpZ2h0cylcbiAgICB9XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gRGVjaXNpb24gRW5naW5lXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgLyoqXG4gICAgICogUGVyc29uYWxpemF0aW9uIERlY2lzaW9uIEVuZ2luZVxuICAgICAqIERldGVybWluZXMgd2hpY2ggY29udGVudCB0byBzaG93IGJhc2VkIG9uIGNvbnRleHRcbiAgICAgKiBQcmlvcml0eTogQUkgKGlmIGVuYWJsZWQpIC0+IFVUTSBwYXJhbXMgLT4gUmVmZXJyZXIgLT4gUmFuZG9tIEEvQiBmYWxsYmFja1xuICAgICAqL1xuICAgIHZhciBEZWNpc2lvbkVuZ2luZSA9IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFN0YW5kYXJkIChub24tQUkpIGRlY2lzaW9uIGxvZ2ljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjb250ZXh0IC0gQ29udGV4dCBmcm9tIEx1YVVUTS5nZXRDb250ZXh0KClcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSAtIENvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMucnVsZXNdIC0gQ3VzdG9tIG1hdGNoaW5nIHJ1bGVzXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zLnRlbXBsYXRlcyAtIFVzZXItcHJvdmlkZWQgdGVtcGxhdGVzIChSRVFVSVJFRClcbiAgICAgICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5yYW5kb21GYWxsYmFja10gLSBFbmFibGUgcmFuZG9tIEEvQiBmYWxsYmFjayAoZGVmYXVsdDogdHJ1ZSlcbiAgICAgICAgICogQHJldHVybnMge09iamVjdH0gLSB7IHRlbXBsYXRlLCBpbnRlbnQsIHNvdXJjZSB9XG4gICAgICAgICAqL1xuICAgICAgICBzdGFuZGFyZERlY2lkZTogZnVuY3Rpb24gKGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG4gICAgICAgICAgICB2YXIgY3VzdG9tUnVsZXMgPSBvcHRpb25zLnJ1bGVzIHx8IHt9XG4gICAgICAgICAgICB2YXIgdXNlclRlbXBsYXRlcyA9IG9wdGlvbnMudGVtcGxhdGVzXG4gICAgICAgICAgICB2YXIgZW5hYmxlUmFuZG9tRmFsbGJhY2sgPSBvcHRpb25zLnJhbmRvbUZhbGxiYWNrICE9PSBmYWxzZVxuXG4gICAgICAgICAgICAvLyBUZW1wbGF0ZXMgYXJlIHJlcXVpcmVkIC0gd2FybiBpZiBub3QgcHJvdmlkZWRcbiAgICAgICAgICAgIGlmICghdXNlclRlbXBsYXRlcyB8fCB0eXBlb2YgdXNlclRlbXBsYXRlcyAhPT0gJ29iamVjdCcgfHwgT2JqZWN0LmtleXModXNlclRlbXBsYXRlcykubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIFBlcnNvbmFsaXplXSBObyB0ZW1wbGF0ZXMgcHJvdmlkZWQuIFRlbXBsYXRlcyBtdXN0IGJlIHBhc3NlZCB2aWEgb3B0aW9ucy50ZW1wbGF0ZXMnKVxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICBpbnRlbnQ6ICdkZWZhdWx0JyxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0OiBjb250ZXh0LFxuICAgICAgICAgICAgICAgICAgICBlcnJvcjogJ05vIHRlbXBsYXRlcyBwcm92aWRlZCdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBpbnRlbnQgPSBjb250ZXh0LnByaW1hcnlJbnRlbnRcbiAgICAgICAgICAgIHZhciBzb3VyY2UgPSAnZGVmYXVsdCdcblxuICAgICAgICAgICAgLy8gRGV0ZXJtaW5lIHRoZSBzb3VyY2Ugb2YgdGhlIGRlY2lzaW9uXG4gICAgICAgICAgICBpZiAoY29udGV4dC5oYXNVVE0pIHtcbiAgICAgICAgICAgICAgICBzb3VyY2UgPSAndXRtJ1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjb250ZXh0LnJlZmVycmVyICYmIGNvbnRleHQucmVmZXJyZXIuY2F0ZWdvcnkgIT09ICdkaXJlY3QnKSB7XG4gICAgICAgICAgICAgICAgc291cmNlID0gJ3JlZmVycmVyJ1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBjdXN0b20gcnVsZXMgZmlyc3QgKGhpZ2hlc3QgcHJpb3JpdHkpXG4gICAgICAgICAgICBmb3IgKHZhciBydWxlS2V5IGluIGN1c3RvbVJ1bGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJ1bGUgPSBjdXN0b21SdWxlc1tydWxlS2V5XVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcnVsZS5tYXRjaCA9PT0gJ2Z1bmN0aW9uJyAmJiBydWxlLm1hdGNoKGNvbnRleHQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGludGVudCA9IHJ1bGUuaW50ZW50IHx8IHJ1bGVLZXlcbiAgICAgICAgICAgICAgICAgICAgc291cmNlID0gJ2N1c3RvbS1ydWxlJ1xuICAgICAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgaW50ZW50IGlzIHN0aWxsICdkZWZhdWx0JyBhbmQgcmFuZG9tIGZhbGxiYWNrIGlzIGVuYWJsZWQsXG4gICAgICAgICAgICAvLyBwaWNrIGEgcmFuZG9tIHRlbXBsYXRlIGZvciBBL0IgdGVzdGluZ1xuICAgICAgICAgICAgaWYgKGludGVudCA9PT0gJ2RlZmF1bHQnICYmIHNvdXJjZSA9PT0gJ2RlZmF1bHQnICYmIGVuYWJsZVJhbmRvbUZhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJhbmRvbUludGVudCA9IGdldFJhbmRvbUZhbGxiYWNrSW50ZW50KHVzZXJUZW1wbGF0ZXMpXG4gICAgICAgICAgICAgICAgaWYgKHJhbmRvbUludGVudCkge1xuICAgICAgICAgICAgICAgICAgICBpbnRlbnQgPSByYW5kb21JbnRlbnRcbiAgICAgICAgICAgICAgICAgICAgc291cmNlID0gJ3JhbmRvbS1hYidcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJlY29yZCB2aXNpdCB0byBoaXN0b3J5IGlmIEx1YVdlaWdodGVkSGlzdG9yeSBpcyBhdmFpbGFibGVcbiAgICAgICAgICAgIGlmIChyb290Lkx1YVdlaWdodGVkSGlzdG9yeSAmJiB0eXBlb2Ygcm9vdC5MdWFXZWlnaHRlZEhpc3RvcnkucmVjb3JkVmlzaXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICByb290Lkx1YVdlaWdodGVkSGlzdG9yeS5yZWNvcmRWaXNpdCh7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQ6IGNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgIGludGVudDogaW50ZW50LFxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZFZhcmlhbnQ6IGludGVudCxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlOiBzb3VyY2UsXG4gICAgICAgICAgICAgICAgICAgIGFpRGVjaXNpb246IGZhbHNlXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZTogZ2V0VGVtcGxhdGUoaW50ZW50LCB1c2VyVGVtcGxhdGVzKSxcbiAgICAgICAgICAgICAgICBpbnRlbnQ6IGludGVudCxcbiAgICAgICAgICAgICAgICBzb3VyY2U6IHNvdXJjZSxcbiAgICAgICAgICAgICAgICBjb250ZXh0OiBjb250ZXh0XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE1haW4gZGVjaWRlIGZ1bmN0aW9uIC0gcm91dGVzIHRvIEFJIG9yIHN0YW5kYXJkIGVuZ2luZVxuICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gY29udGV4dCAtIENvbnRleHQgZnJvbSBMdWFVVE0uZ2V0Q29udGV4dCgpXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gLSBDb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICAgICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5lbmFibGVBSV0gLSBFbmFibGUgQUktcG93ZXJlZCBkZWNpc2lvbnNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmFpQ29uZmlnXSAtIEFJIGNvbmZpZ3VyYXRpb25cbiAgICAgICAgICogQHJldHVybnMge09iamVjdHxQcm9taXNlPE9iamVjdD59IC0gRGVjaXNpb24gcmVzdWx0IChQcm9taXNlIGlmIEFJIGVuYWJsZWQpXG4gICAgICAgICAqL1xuICAgICAgICBkZWNpZGU6IGZ1bmN0aW9uIChjb250ZXh0LCBvcHRpb25zKSB7XG4gICAgICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuXG4gICAgICAgICAgICAvLyBJZiBBSSBpcyBlbmFibGVkIGFuZCBjb25maWd1cmVkLCB0cnkgQUkgZGVjaXNpb24gZmlyc3RcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmVuYWJsZUFJICYmIG9wdGlvbnMuYWlDb25maWcgJiYgcm9vdC5MdWFBSVBlcnNvbmFsaXplKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzXG4gICAgICAgICAgICAgICAgdmFyIGFpTW9kdWxlID0gcm9vdC5MdWFBSVBlcnNvbmFsaXplXG4gICAgICAgICAgICAgICAgdmFyIHJlYWRpbmVzcyA9IGFpTW9kdWxlLmlzUmVhZHkob3B0aW9ucy5haUNvbmZpZylcblxuICAgICAgICAgICAgICAgIGlmIChyZWFkaW5lc3MucmVhZHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFpTW9kdWxlLmRlY2lkZShjb250ZXh0LCBvcHRpb25zKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFJIGZhaWxlZCAtIGZhbGwgYmFjayB0byBzdGFuZGFyZCBlbmdpbmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZmFsbGJhY2sgPSBvcHRpb25zLmFpQ29uZmlnLmZhbGxiYWNrVG9TdGFuZGFyZCAhPT0gZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmFsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIFBlcnNvbmFsaXplXSBBSSBmYWlsZWQsIHVzaW5nIHN0YW5kYXJkIGVuZ2luZTonLCBlcnJvci5tZXNzYWdlKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2VsZi5zdGFuZGFyZERlY2lkZShjb250ZXh0LCBvcHRpb25zKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tMdWEgUGVyc29uYWxpemVdIEFJIG5vdCByZWFkeTonLCByZWFkaW5lc3MuZXJyb3IsICctIHVzaW5nIHN0YW5kYXJkIGVuZ2luZScpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTdGFuZGFyZCBkZWNpc2lvbiAoc3luY2hyb25vdXMpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdGFuZGFyZERlY2lkZShjb250ZXh0LCBvcHRpb25zKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIFBlcnNvbmFsaXphdGlvbiBBcHBsaWNhdGlvblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBET00gQXBwbGljYXRpb24gKGV4dHJhY3RlZCBmb3IgcmV1c2UgYnkgYm90aCBzeW5jIGFuZCBhc3luYyBwYXRocylcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICAvKipcbiAgICAgKiBBcHBseSBhIGRlY2lzaW9uIHRvIHRoZSBET01cbiAgICAgKiBJbmplY3RzIGNvbnRlbnQgaW50byBlbGVtZW50cyB3aXRoIGRhdGEtcGVyc29uYWxpemUgYXR0cmlidXRlc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRlY2lzaW9uIC0gRGVjaXNpb24gb2JqZWN0IHsgdGVtcGxhdGUsIGludGVudCwgc291cmNlLCBjb250ZXh0IH1cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sb2ddIC0gRW5hYmxlIGNvbnNvbGUgbG9nZ2luZ1xuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IC0gVGhlIGRlY2lzaW9uIChwYXNzLXRocm91Z2gpXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXBwbHlEZWNpc2lvblRvRE9NKGRlY2lzaW9uLCBvcHRpb25zKSB7XG4gICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG4gICAgICAgIHZhciB0ZW1wbGF0ZSA9IGRlY2lzaW9uLnRlbXBsYXRlXG4gICAgICAgIHZhciBjb250ZXh0ID0gZGVjaXNpb24uY29udGV4dCB8fCB7fVxuICAgICAgICB2YXIgbG9nID0gb3B0aW9ucy5sb2cgIT09IGZhbHNlXG5cbiAgICAgICAgaWYgKCF0ZW1wbGF0ZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIFBlcnNvbmFsaXplXSBObyB0ZW1wbGF0ZSBpbiBkZWNpc2lvbiwgc2tpcHBpbmcgRE9NIHVwZGF0ZScpXG4gICAgICAgICAgICByZXR1cm4gZGVjaXNpb25cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZpbmQgYW5kIHVwZGF0ZSBlYWNoIHBlcnNvbmFsaXplIHNsb3QgaW4gdGhlIERPTVxuICAgICAgICB2YXIgc2xvdHMgPSBbJ2ltYWdlJywgJ2hlYWRsaW5lJywgJ3N1YmhlYWRsaW5lJywgJ2N0YUxhYmVsJywgJ2N0YUxpbmsnXVxuXG4gICAgICAgIHNsb3RzLmZvckVhY2goZnVuY3Rpb24gKHNsb3QpIHtcbiAgICAgICAgICAgIHZhciBlbGVtZW50cyA9IGZpbmRQZXJzb25hbGl6ZUVsZW1lbnRzKHNsb3QpXG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgZWxlbWVudCA9IGVsZW1lbnRzW2ldXG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gdGVtcGxhdGVbc2xvdF1cbiAgICAgICAgICAgICAgICBpZiAoIXZhbHVlKSBjb250aW51ZVxuXG4gICAgICAgICAgICAgICAgaWYgKHNsb3QgPT09ICdpbWFnZScpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRm9yIGltYWdlcywgc2V0IGJhY2tncm91bmQtaW1hZ2Ugb3Igc3JjIGF0dHJpYnV0ZVxuICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lID09PSAnSU1HJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zcmMgPSB2YWx1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hbHQgPSB0ZW1wbGF0ZS5oZWFkbGluZSB8fCAnUGVyc29uYWxpemVkIGltYWdlJ1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kSW1hZ2UgPSAndXJsKCcgKyB2YWx1ZSArICcpJ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzbG90ID09PSAnY3RhTGluaycpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRm9yIGxpbmtzLCBzZXQgaHJlZiBhdHRyaWJ1dGVcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5ocmVmID0gdmFsdWVcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBGb3IgdGV4dCBjb250ZW50LCB1c2UgdGV4dENvbnRlbnQgKHNhZmUsIG5vIEhUTUwgcGFyc2luZylcbiAgICAgICAgICAgICAgICAgICAgc2FmZVNldFRleHQoZWxlbWVudCwgdmFsdWUpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuXG4gICAgICAgIC8vIEFwcGx5IHRvIGdlbmVyaWMgJ2hlcm8nIHNlY3Rpb25zIHdpdGggZGF0YS1wZXJzb25hbGl6ZT1cImhlcm9cIlxuICAgICAgICB2YXIgaGVyb0VsZW1lbnRzID0gZmluZFBlcnNvbmFsaXplRWxlbWVudHMoJ2hlcm8nKVxuICAgICAgICBmb3IgKHZhciBoID0gMDsgaCA8IGhlcm9FbGVtZW50cy5sZW5ndGg7IGgrKykge1xuICAgICAgICAgICAgdmFyIGhlcm9FbCA9IGhlcm9FbGVtZW50c1toXVxuICAgICAgICAgICAgaGVyb0VsLnNldEF0dHJpYnV0ZSgnZGF0YS1pbnRlbnQnLCBkZWNpc2lvbi5pbnRlbnQpXG4gICAgICAgICAgICBoZXJvRWwuc2V0QXR0cmlidXRlKCdkYXRhLXNvdXJjZScsIGRlY2lzaW9uLnNvdXJjZSlcblxuICAgICAgICAgICAgLy8gSWYgaGVybyBoYXMgYSBiYWNrZ3JvdW5kIGltYWdlIHNsb3QsIGFwcGx5IGl0XG4gICAgICAgICAgICBpZiAodGVtcGxhdGUuaW1hZ2UgJiYgIWhlcm9FbC5xdWVyeVNlbGVjdG9yKCdbZGF0YS1wZXJzb25hbGl6ZT1cImltYWdlXCJdJykpIHtcbiAgICAgICAgICAgICAgICBoZXJvRWwuc3R5bGUuYmFja2dyb3VuZEltYWdlID0gJ3VybCgnICsgdGVtcGxhdGUuaW1hZ2UgKyAnKSdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIExvZyB0aGUgcGVyc29uYWxpemF0aW9uIGRlY2lzaW9uIChmb3IgZGVidWdnaW5nL2RlbW8pXG4gICAgICAgIGlmIChsb2cgJiYgdHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnW0x1YSBQZXJzb25hbGl6ZV0gQXBwbGllZDonLCB7XG4gICAgICAgICAgICAgICAgaW50ZW50OiBkZWNpc2lvbi5pbnRlbnQsXG4gICAgICAgICAgICAgICAgc291cmNlOiBkZWNpc2lvbi5zb3VyY2UsXG4gICAgICAgICAgICAgICAgaGVhZGxpbmU6IHRlbXBsYXRlLmhlYWRsaW5lLFxuICAgICAgICAgICAgICAgIGhhc1VUTTogY29udGV4dC5oYXNVVE0sXG4gICAgICAgICAgICAgICAgdXRtUGFyYW1zOiBjb250ZXh0LnV0bSB8fCB7fSxcbiAgICAgICAgICAgICAgICBhaVBvd2VyZWQ6IGRlY2lzaW9uLnNvdXJjZSA9PT0gJ2FpJyB8fCBkZWNpc2lvbi5zb3VyY2UgPT09ICdhaS1jYWNoZWQnXG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRlY2lzaW9uXG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIENvbnRleHQgUmVzb2x1dGlvblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmUgY29udGV4dCBmcm9tIGF2YWlsYWJsZSBzb3VyY2VzXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSAtIE9wdGlvbnMgd2l0aCBvcHRpb25hbCBjb250ZXh0XG4gICAgICogQHJldHVybnMge09iamVjdH0gLSBSZXNvbHZlZCBjb250ZXh0XG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVzb2x2ZUNvbnRleHQob3B0aW9ucykge1xuICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLmNvbnRleHQpIHtcbiAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmNvbnRleHRcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyb290Lkx1YVVUTSAmJiB0eXBlb2Ygcm9vdC5MdWFVVE0uZ2V0Q29udGV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIHJvb3QuTHVhVVRNLmdldENvbnRleHQoKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gTm8gVVRNIG1vZHVsZSBhdmFpbGFibGUgLSBjcmVhdGUgbWluaW1hbCBkZWZhdWx0IGNvbnRleHRcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHV0bToge30sXG4gICAgICAgICAgICByZWZlcnJlcjogeyBzb3VyY2U6ICdkaXJlY3QnLCBjYXRlZ29yeTogJ2RpcmVjdCcsIHVybDogJycgfSxcbiAgICAgICAgICAgIHVzZXJBZ2VudDogeyByYXc6ICcnLCBpc01vYmlsZTogZmFsc2UsIGlzVGFibGV0OiBmYWxzZSwgaXNEZXNrdG9wOiB0cnVlIH0sXG4gICAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgICAgICAgICBoYXNVVE06IGZhbHNlLFxuICAgICAgICAgICAgcHJpbWFyeUludGVudDogJ2RlZmF1bHQnXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gTWFpbiBQZXJzb25hbGl6YXRpb24gRnVuY3Rpb25zXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgLyoqXG4gICAgICogQXBwbHkgcGVyc29uYWxpemF0aW9uIHRvIHRoZSBwYWdlIHZpYSBkYXRhLXBlcnNvbmFsaXplIGF0dHJpYnV0ZXNcbiAgICAgKiBNYWluIGVudHJ5IHBvaW50IGZvciBwZXJzb25hbGl6YXRpb25cbiAgICAgKlxuICAgICAqIFN1cHBvcnRlZCBkYXRhLXBlcnNvbmFsaXplIHZhbHVlczpcbiAgICAgKiAgIC0gXCJoZXJvXCIgICAgICAgIDogR2VuZXJpYyBoZXJvIHNlY3Rpb24gKHNldHMgZGF0YS1pbnRlbnQsIGRhdGEtc291cmNlKVxuICAgICAqICAgLSBcImltYWdlXCIgICAgICAgOiBJbWFnZSBzbG90IChzZXRzIHNyYyBvciBiYWNrZ3JvdW5kLWltYWdlKVxuICAgICAqICAgLSBcImhlYWRsaW5lXCIgICAgOiBIZWFkbGluZSB0ZXh0XG4gICAgICogICAtIFwic3ViaGVhZGxpbmVcIiA6IFN1YmhlYWRsaW5lIHRleHRcbiAgICAgKiAgIC0gXCJjdGFMYWJlbFwiICAgIDogQ1RBIGJ1dHRvbiB0ZXh0XG4gICAgICogICAtIFwiY3RhTGlua1wiICAgICA6IENUQSBsaW5rIGhyZWZcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gLSBDb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuY29udGV4dF0gLSBQcmUtY29tcHV0ZWQgVVRNIGNvbnRleHRcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMucnVsZXNdIC0gQ3VzdG9tIG1hdGNoaW5nIHJ1bGVzXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMudGVtcGxhdGVzIC0gVXNlci1wcm92aWRlZCB0ZW1wbGF0ZXMgKFJFUVVJUkVEKVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMuZW5hYmxlQUldIC0gRW5hYmxlIEFJLXBvd2VyZWQgZGVjaXNpb25zXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmFpQ29uZmlnXSAtIEFJIGNvbmZpZ3VyYXRpb24gKHJlcXVpcmVkIGlmIGVuYWJsZUFJIGlzIHRydWUpXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5yYW5kb21GYWxsYmFja10gLSBFbmFibGUgcmFuZG9tIEEvQiBmYWxsYmFjayAoZGVmYXVsdDogdHJ1ZSlcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxvZ10gLSBFbmFibGUgY29uc29sZSBsb2dnaW5nIChkZWZhdWx0OiB0cnVlKVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R8UHJvbWlzZTxPYmplY3Q+fSAtIFJlc3VsdCB3aXRoIGFwcGxpZWQgZGVjaXNpb24gKFByb21pc2UgaWYgQUkgZW5hYmxlZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwZXJzb25hbGl6ZShvcHRpb25zKSB7XG4gICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG5cbiAgICAgICAgLy8gVGVtcGxhdGVzIGFyZSByZXF1aXJlZFxuICAgICAgICBpZiAoIW9wdGlvbnMudGVtcGxhdGVzIHx8IHR5cGVvZiBvcHRpb25zLnRlbXBsYXRlcyAhPT0gJ29iamVjdCcgfHwgT2JqZWN0LmtleXMob3B0aW9ucy50ZW1wbGF0ZXMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignW0x1YSBQZXJzb25hbGl6ZV0gVGVtcGxhdGVzIGFyZSByZXF1aXJlZC4gUHJvdmlkZSB0ZW1wbGF0ZXMgdmlhIG9wdGlvbnMudGVtcGxhdGVzJylcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdGVtcGxhdGU6IG51bGwsXG4gICAgICAgICAgICAgICAgaW50ZW50OiAnZGVmYXVsdCcsXG4gICAgICAgICAgICAgICAgc291cmNlOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IHt9LFxuICAgICAgICAgICAgICAgIGVycm9yOiAnTm8gdGVtcGxhdGVzIHByb3ZpZGVkJ1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNvbnRleHQgPSByZXNvbHZlQ29udGV4dChvcHRpb25zKVxuICAgICAgICB2YXIgZGVjaXNpb24gPSBEZWNpc2lvbkVuZ2luZS5kZWNpZGUoY29udGV4dCwgb3B0aW9ucylcblxuICAgICAgICAvLyBJZiBkZWNpc2lvbiBpcyBhIFByb21pc2UgKEFJIHBhdGgpLCBoYW5kbGUgYXN5bmMgZmxvd1xuICAgICAgICBpZiAoZGVjaXNpb24gJiYgdHlwZW9mIGRlY2lzaW9uLnRoZW4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiBkZWNpc2lvbi50aGVuKGZ1bmN0aW9uIChhaURlY2lzaW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5RGVjaXNpb25Ub0RPTShhaURlY2lzaW9uLCBvcHRpb25zKVxuICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignW0x1YSBQZXJzb25hbGl6ZV0gQUkgZGVjaXNpb24gZmFpbGVkLCB1c2luZyBzdGFuZGFyZDonLCBlcnIubWVzc2FnZSlcbiAgICAgICAgICAgICAgICAvLyBGYWxsYmFjayB0byBzdGFuZGFyZCBkZWNpc2lvbiArIERPTSBhcHBsaWNhdGlvblxuICAgICAgICAgICAgICAgIHZhciBmYWxsYmFja0RlY2lzaW9uID0gRGVjaXNpb25FbmdpbmUuc3RhbmRhcmREZWNpZGUoY29udGV4dCwgb3B0aW9ucylcbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHlEZWNpc2lvblRvRE9NKGZhbGxiYWNrRGVjaXNpb24sIG9wdGlvbnMpXG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3luY2hyb25vdXMgcGF0aCAoc3RhbmRhcmQgZW5naW5lKVxuICAgICAgICByZXR1cm4gYXBwbHlEZWNpc2lvblRvRE9NKGRlY2lzaW9uLCBvcHRpb25zKVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFzeW5jIHBlcnNvbmFsaXphdGlvbiB3aXRoIHRpbWVvdXQgZmFsbGJhY2tcbiAgICAgKiBVc2VzIEx1YVVUTS5nZXRDb250ZXh0QXN5bmMgZm9yIG5vbi1ibG9ja2luZyBVVE0gZXh0cmFjdGlvblxuICAgICAqIEF1dG9tYXRpY2FsbHkgaGFuZGxlcyBBSSBkZWNpc2lvbnMgKHdoaWNoIGFyZSBhbHdheXMgYXN5bmMpXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zXG4gICAgICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0Pn0gLSBSZXN1bHQgd2l0aCBhcHBsaWVkIGRlY2lzaW9uXG4gICAgICovXG4gICAgZnVuY3Rpb24gcGVyc29uYWxpemVBc3luYyhvcHRpb25zKSB7XG4gICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG5cbiAgICAgICAgLy8gVXNlIGFzeW5jIGNvbnRleHQgZ2V0dGVyIGlmIGF2YWlsYWJsZVxuICAgICAgICBpZiAocm9vdC5MdWFVVE0gJiYgdHlwZW9mIHJvb3QuTHVhVVRNLmdldENvbnRleHRBc3luYyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIHJvb3QuTHVhVVRNLmdldENvbnRleHRBc3luYyhvcHRpb25zKS50aGVuKGZ1bmN0aW9uIChjb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgb3B0aW9ucy5jb250ZXh0ID0gY29udGV4dFxuICAgICAgICAgICAgICAgIHJldHVybiBwZXJzb25hbGl6ZShvcHRpb25zKVxuICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoZGVjaXNpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBFbnN1cmUgd2UgYWx3YXlzIHJldHVybiBhIHJlc29sdmVkIHByb21pc2VcbiAgICAgICAgICAgICAgICByZXR1cm4gZGVjaXNpb25cbiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tMdWEgUGVyc29uYWxpemVdIEFzeW5jIGVycm9yLCB1c2luZyBkZWZhdWx0OicsIGVycilcbiAgICAgICAgICAgICAgICAvLyBGb3JjZSBzdGFuZGFyZCBlbmdpbmUgZmFsbGJhY2tcbiAgICAgICAgICAgICAgICB2YXIgZmFsbGJhY2tPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZXM6IG9wdGlvbnMudGVtcGxhdGVzLFxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0OiByZXNvbHZlQ29udGV4dChvcHRpb25zKSxcbiAgICAgICAgICAgICAgICAgICAgbG9nOiBvcHRpb25zLmxvZ1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZmFsbGJhY2tEZWNpc2lvbiA9IERlY2lzaW9uRW5naW5lLnN0YW5kYXJkRGVjaWRlKGZhbGxiYWNrT3B0aW9ucy5jb250ZXh0LCBmYWxsYmFja09wdGlvbnMpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5RGVjaXNpb25Ub0RPTShmYWxsYmFja0RlY2lzaW9uLCBmYWxsYmFja09wdGlvbnMpXG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gV3JhcCBzeW5jaHJvbm91cy9BSSBwZXJzb25hbGl6YXRpb24gaW4gYSBwcm9taXNlXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gcGVyc29uYWxpemUob3B0aW9ucylcbiAgICAgICAgICAgIC8vIElmIHJlc3VsdCBpcyBhIHByb21pc2UgKEFJIHBhdGgpLCByZXR1cm4gaXQgZGlyZWN0bHlcbiAgICAgICAgICAgIGlmIChyZXN1bHQgJiYgdHlwZW9mIHJlc3VsdC50aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHQpXG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIFBlcnNvbmFsaXplXSBFcnJvciwgdXNpbmcgZGVmYXVsdDonLCBlcnIpXG4gICAgICAgICAgICB2YXIgZGVmYXVsdENvbnRleHQgPSB7XG4gICAgICAgICAgICAgICAgdXRtOiB7fSxcbiAgICAgICAgICAgICAgICByZWZlcnJlcjogeyBzb3VyY2U6ICdkaXJlY3QnLCBjYXRlZ29yeTogJ2RpcmVjdCcsIHVybDogJycgfSxcbiAgICAgICAgICAgICAgICB1c2VyQWdlbnQ6IHsgcmF3OiAnJywgaXNNb2JpbGU6IGZhbHNlLCBpc1RhYmxldDogZmFsc2UsIGlzRGVza3RvcDogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgICAgICBoYXNVVE06IGZhbHNlLFxuICAgICAgICAgICAgICAgIHByaW1hcnlJbnRlbnQ6ICdkZWZhdWx0J1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGZhbGxiYWNrID0gRGVjaXNpb25FbmdpbmUuc3RhbmRhcmREZWNpZGUoZGVmYXVsdENvbnRleHQsIHsgdGVtcGxhdGVzOiBvcHRpb25zLnRlbXBsYXRlcyB9KVxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShhcHBseURlY2lzaW9uVG9ET00oZmFsbGJhY2ssIG9wdGlvbnMpKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXV0by1pbml0aWFsaXplIHBlcnNvbmFsaXphdGlvbiB3aGVuIERPTSBpcyByZWFkeVxuICAgICAqIFNjYW5zIGZvciBkYXRhLXBlcnNvbmFsaXplIGF0dHJpYnV0ZXMgYW5kIGFwcGxpZXMgY29udGVudFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gLSBDb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhdXRvSW5pdChvcHRpb25zKSB7XG4gICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG5cbiAgICAgICAgZnVuY3Rpb24gcnVuKCkge1xuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBkYXRhLXBlcnNvbmFsaXplIGVsZW1lbnRzIG9uIHRoZSBwYWdlXG4gICAgICAgICAgICB2YXIgZWxlbWVudHMgPSBmaW5kUGVyc29uYWxpemVFbGVtZW50cygpXG4gICAgICAgICAgICBpZiAoZWxlbWVudHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHBlcnNvbmFsaXplKG9wdGlvbnMpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXYWl0IGZvciBET00gcmVhZHlcbiAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnbG9hZGluZycpIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgcnVuKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBydW4oKVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIFB1YmxpYyBBUEkgLSBSZWdpc3RlciBvbiB3aW5kb3cuTHVhUGVyc29uYWxpemVcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICB2YXIgTHVhUGVyc29uYWxpemUgPSB7XG4gICAgICAgIC8vIE5vdGU6IFRlbXBsYXRlcyBhcmUgTk9UIHByb3ZpZGVkIGJ5IHRoaXMgcGFja2FnZVxuICAgICAgICAvLyBVc2VycyBtdXN0IHByb3ZpZGUgdGhlaXIgb3duIHRlbXBsYXRlcyB2aWEgb3B0aW9ucy50ZW1wbGF0ZXNcbiAgICAgICAgc2FuaXRpemVyOiBTYW5pdGl6ZXIsXG4gICAgICAgIHNhbml0aXplSFRNTDogZnVuY3Rpb24gKGh0bWwpIHsgcmV0dXJuIFNhbml0aXplci5zYW5pdGl6ZShodG1sKSB9LFxuICAgICAgICBzYWZlU2V0VGV4dDogc2FmZVNldFRleHQsXG4gICAgICAgIHNhZmVTZXRIVE1MOiBzYWZlU2V0SFRNTCxcbiAgICAgICAgZmluZEVsZW1lbnRzOiBmaW5kUGVyc29uYWxpemVFbGVtZW50cyxcbiAgICAgICAgZ2V0VGVtcGxhdGU6IGdldFRlbXBsYXRlLFxuICAgICAgICBlbmdpbmU6IERlY2lzaW9uRW5naW5lLFxuICAgICAgICBwZXJzb25hbGl6ZTogcGVyc29uYWxpemUsXG4gICAgICAgIHBlcnNvbmFsaXplQXN5bmM6IHBlcnNvbmFsaXplQXN5bmMsXG4gICAgICAgIGF1dG9Jbml0OiBhdXRvSW5pdCxcbiAgICAgICAgY2hvb3NlV2VpZ2h0ZWRSYW5kb206IGNob29zZVdlaWdodGVkUmFuZG9tLFxuICAgICAgICBnZXRSYW5kb21GYWxsYmFja0ludGVudDogZ2V0UmFuZG9tRmFsbGJhY2tJbnRlbnQsXG4gICAgICAgIGFwcGx5RGVjaXNpb25Ub0RPTTogYXBwbHlEZWNpc2lvblRvRE9NLFxuICAgICAgICByZXNvbHZlQ29udGV4dDogcmVzb2x2ZUNvbnRleHRcbiAgICB9XG5cbiAgICAvLyBFeHBvc2UgZ2xvYmFsbHlcbiAgICByb290Lkx1YVBlcnNvbmFsaXplID0gTHVhUGVyc29uYWxpemVcblxufSkodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6IHRoaXMpXG4iXSwibWFwcGluZ3MiOiI7Ozs7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFDLENBQUMsVUFBVUEsSUFBSSxFQUFFO0VBQ2QsWUFBWTs7RUFFWjtFQUNBO0VBQ0E7RUFDQTs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksSUFBSUMsU0FBUyxHQUFJLFlBQVk7SUFFekI7SUFDQSxJQUFJQyxZQUFZLEdBQUc7TUFDZixHQUFHLEVBQUUsSUFBSTtNQUFFLE1BQU0sRUFBRSxJQUFJO01BQUUsUUFBUSxFQUFFLElBQUk7TUFBRSxJQUFJLEVBQUUsSUFBSTtNQUNuRCxHQUFHLEVBQUUsSUFBSTtNQUFFLEdBQUcsRUFBRSxJQUFJO01BQUUsSUFBSSxFQUFFLElBQUk7TUFBRSxHQUFHLEVBQUUsSUFBSTtNQUFFLEtBQUssRUFBRSxJQUFJO01BQ3hELElBQUksRUFBRSxJQUFJO01BQUUsSUFBSSxFQUFFLElBQUk7TUFBRSxJQUFJLEVBQUUsSUFBSTtNQUFFLElBQUksRUFBRSxJQUFJO01BQUUsSUFBSSxFQUFFLElBQUk7TUFBRSxJQUFJLEVBQUUsSUFBSTtNQUN0RSxLQUFLLEVBQUUsSUFBSTtNQUFFLFNBQVMsRUFBRSxJQUFJO01BQUUsSUFBSSxFQUFFLElBQUk7TUFBRSxJQUFJLEVBQUUsSUFBSTtNQUFFLElBQUksRUFBRSxJQUFJO01BQ2hFLFlBQVksRUFBRSxJQUFJO01BQUUsUUFBUSxFQUFFLElBQUk7TUFBRSxZQUFZLEVBQUU7SUFDdEQsQ0FBQzs7SUFFRDtJQUNBLElBQUlDLGFBQWEsR0FBRztNQUNoQixNQUFNLEVBQUUsSUFBSTtNQUFFLEtBQUssRUFBRSxJQUFJO01BQUUsS0FBSyxFQUFFLElBQUk7TUFBRSxPQUFPLEVBQUUsSUFBSTtNQUNyRCxJQUFJLEVBQUUsSUFBSTtNQUFFLE9BQU8sRUFBRSxJQUFJO01BQUUsUUFBUSxFQUFFLElBQUk7TUFBRSxLQUFLLEVBQUUsSUFBSTtNQUN0RCxPQUFPLEVBQUUsSUFBSTtNQUFFLFFBQVEsRUFBRSxJQUFJO01BQUUsU0FBUyxFQUFFO0lBQzlDLENBQUM7O0lBRUQ7SUFDQSxJQUFJQyxhQUFhLEdBQUcsK0JBQStCOztJQUVuRDtJQUNBLElBQUlDLGFBQWEsR0FBRyxNQUFNOztJQUUxQjtBQUNSO0FBQ0E7QUFDQTtJQUNRLFNBQVNDLFlBQVlBLENBQUEsRUFBRztNQUNwQixJQUFJO1FBQ0EsT0FBTyxPQUFPQyxTQUFTLEtBQUssV0FBVyxJQUFJLElBQUlBLFNBQVMsQ0FBQyxDQUFDO01BQzlELENBQUMsQ0FBQyxPQUFPQyxDQUFDLEVBQUU7UUFDUixPQUFPLEtBQUs7TUFDaEI7SUFDSjs7SUFFQTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDUSxTQUFTQyxxQkFBcUJBLENBQUNDLEtBQUssRUFBRTtNQUNsQyxJQUFJLE9BQU9BLEtBQUssS0FBSyxRQUFRLElBQUksQ0FBQ0EsS0FBSyxDQUFDQyxJQUFJLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRTtNQUV6RCxJQUFJO1FBQ0EsSUFBSUMsTUFBTSxHQUFHLElBQUlMLFNBQVMsQ0FBQyxDQUFDO1FBQzVCLElBQUlNLEdBQUcsR0FBR0QsTUFBTSxDQUFDRSxlQUFlLENBQUNKLEtBQUssRUFBRSxXQUFXLENBQUM7UUFDcEQsSUFBSUssSUFBSSxHQUFHRixHQUFHLENBQUNFLElBQUk7UUFFbkIsSUFBSSxDQUFDQSxJQUFJLEVBQUUsT0FBTyxFQUFFO1FBRXBCLE9BQU9DLFlBQVksQ0FBQ0QsSUFBSSxDQUFDO01BQzdCLENBQUMsQ0FBQyxPQUFPUCxDQUFDLEVBQUU7UUFDUlMsT0FBTyxDQUFDQyxJQUFJLENBQUMsbURBQW1ELEVBQUVWLENBQUMsQ0FBQztRQUNwRSxPQUFPVyxpQkFBaUIsQ0FBQ1QsS0FBSyxDQUFDO01BQ25DO0lBQ0o7O0lBRUE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtJQUNRLFNBQVNNLFlBQVlBLENBQUNJLElBQUksRUFBRTtNQUN4QixJQUFJQyxNQUFNLEdBQUcsRUFBRTtNQUVmLEtBQUssSUFBSUMsQ0FBQyxHQUFHLENBQUMsRUFBRUEsQ0FBQyxHQUFHRixJQUFJLENBQUNHLFVBQVUsQ0FBQ0MsTUFBTSxFQUFFRixDQUFDLEVBQUUsRUFBRTtRQUM3QyxJQUFJRyxLQUFLLEdBQUdMLElBQUksQ0FBQ0csVUFBVSxDQUFDRCxDQUFDLENBQUM7O1FBRTlCO1FBQ0EsSUFBSUcsS0FBSyxDQUFDQyxRQUFRLEtBQUssQ0FBQyxFQUFFO1VBQ3RCTCxNQUFNLElBQUlNLFVBQVUsQ0FBQ0YsS0FBSyxDQUFDRyxXQUFXLENBQUM7VUFDdkM7UUFDSjs7UUFFQTtRQUNBLElBQUlILEtBQUssQ0FBQ0MsUUFBUSxLQUFLLENBQUMsRUFBRTtVQUN0QixJQUFJRyxPQUFPLEdBQUdKLEtBQUssQ0FBQ0ksT0FBTyxDQUFDQyxXQUFXLENBQUMsQ0FBQzs7VUFFekM7VUFDQSxJQUFJRCxPQUFPLEtBQUssUUFBUSxJQUFJQSxPQUFPLEtBQUssT0FBTyxJQUMzQ0EsT0FBTyxLQUFLLFFBQVEsSUFBSUEsT0FBTyxLQUFLLFFBQVEsSUFDNUNBLE9BQU8sS0FBSyxPQUFPLElBQUlBLE9BQU8sS0FBSyxNQUFNLElBQ3pDQSxPQUFPLEtBQUssT0FBTyxJQUFJQSxPQUFPLEtBQUssVUFBVSxFQUFFO1lBQy9DO1VBQ0o7O1VBRUE7VUFDQSxJQUFJM0IsWUFBWSxDQUFDMkIsT0FBTyxDQUFDLEVBQUU7WUFDdkJSLE1BQU0sSUFBSSxHQUFHLEdBQUdRLE9BQU87WUFDdkJSLE1BQU0sSUFBSVUsZUFBZSxDQUFDTixLQUFLLENBQUM7WUFDaENKLE1BQU0sSUFBSSxHQUFHOztZQUViO1lBQ0EsSUFBSVEsT0FBTyxLQUFLLElBQUksSUFBSUEsT0FBTyxLQUFLLEtBQUssRUFBRTtjQUN2QztZQUNKOztZQUVBO1lBQ0FSLE1BQU0sSUFBSUwsWUFBWSxDQUFDUyxLQUFLLENBQUM7WUFDN0JKLE1BQU0sSUFBSSxJQUFJLEdBQUdRLE9BQU8sR0FBRyxHQUFHO1VBQ2xDLENBQUMsTUFBTTtZQUNIO1lBQ0FSLE1BQU0sSUFBSUwsWUFBWSxDQUFDUyxLQUFLLENBQUM7VUFDakM7UUFDSjtNQUNKO01BRUEsT0FBT0osTUFBTTtJQUNqQjs7SUFFQTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0lBQ1EsU0FBU1UsZUFBZUEsQ0FBQ0MsT0FBTyxFQUFFO01BQzlCLElBQUlDLE9BQU8sR0FBRyxFQUFFO01BQ2hCLElBQUlDLEtBQUssR0FBR0YsT0FBTyxDQUFDRyxVQUFVO01BRTlCLEtBQUssSUFBSWIsQ0FBQyxHQUFHLENBQUMsRUFBRUEsQ0FBQyxHQUFHWSxLQUFLLENBQUNWLE1BQU0sRUFBRUYsQ0FBQyxFQUFFLEVBQUU7UUFDbkMsSUFBSWMsSUFBSSxHQUFHRixLQUFLLENBQUNaLENBQUMsQ0FBQztRQUNuQixJQUFJZSxJQUFJLEdBQUdELElBQUksQ0FBQ0MsSUFBSSxDQUFDUCxXQUFXLENBQUMsQ0FBQztRQUNsQyxJQUFJUSxLQUFLLEdBQUdGLElBQUksQ0FBQ0UsS0FBSzs7UUFFdEI7UUFDQSxJQUFJakMsYUFBYSxDQUFDa0MsSUFBSSxDQUFDRixJQUFJLENBQUMsRUFBRTs7UUFFOUI7UUFDQSxJQUFJLENBQUNsQyxhQUFhLENBQUNrQyxJQUFJLENBQUMsRUFBRTs7UUFFMUI7UUFDQSxJQUFJLENBQUNBLElBQUksS0FBSyxNQUFNLElBQUlBLElBQUksS0FBSyxLQUFLLEtBQUtqQyxhQUFhLENBQUNtQyxJQUFJLENBQUNELEtBQUssQ0FBQzNCLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRTtVQUN6RTtRQUNKOztRQUVBO1FBQ0EsSUFBSTBCLElBQUksS0FBSyxRQUFRLElBQUlDLEtBQUssS0FBSyxRQUFRLEVBQUU7VUFDekNMLE9BQU8sSUFBSSw0Q0FBNEM7VUFDdkQ7UUFDSjtRQUVBQSxPQUFPLElBQUksR0FBRyxHQUFHSSxJQUFJLEdBQUcsSUFBSSxHQUFHRyxVQUFVLENBQUNGLEtBQUssQ0FBQyxHQUFHLEdBQUc7TUFDMUQ7TUFFQSxPQUFPTCxPQUFPO0lBQ2xCOztJQUVBO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7SUFDUSxTQUFTTixVQUFVQSxDQUFDYyxJQUFJLEVBQUU7TUFDdEIsSUFBSSxDQUFDQSxJQUFJLEVBQUUsT0FBTyxFQUFFO01BQ3BCLE9BQU9BLElBQUksQ0FDTkMsT0FBTyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FDdEJBLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQ3JCQSxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQztJQUM5Qjs7SUFFQTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0lBQ1EsU0FBU0YsVUFBVUEsQ0FBQ0YsS0FBSyxFQUFFO01BQ3ZCLElBQUksQ0FBQ0EsS0FBSyxFQUFFLE9BQU8sRUFBRTtNQUNyQixPQUFPQSxLQUFLLENBQ1BJLE9BQU8sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQ3RCQSxPQUFPLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUN2QkEsT0FBTyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FDdEJBLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQ3JCQSxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQztJQUM5Qjs7SUFFQTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0lBQ1EsU0FBU3ZCLGlCQUFpQkEsQ0FBQ3dCLElBQUksRUFBRTtNQUM3QixJQUFJLE9BQU9BLElBQUksS0FBSyxRQUFRLEVBQUUsT0FBTyxFQUFFO01BRXZDLElBQUlDLGtCQUFrQixHQUFHLENBQ3JCLHFEQUFxRCxFQUNyRCxxREFBcUQsRUFDckQscURBQXFELEVBQ3JELGtCQUFrQixFQUNsQixpQkFBaUIsRUFDakIsa0RBQWtELEVBQ2xELCtDQUErQyxFQUMvQyxlQUFlLEVBQ2YsYUFBYSxFQUNiLFNBQVMsRUFDVCxhQUFhLENBQ2hCO01BRUQsSUFBSUMsU0FBUyxHQUFHRixJQUFJO01BRXBCQyxrQkFBa0IsQ0FBQ0UsT0FBTyxDQUFDLFVBQVVDLE9BQU8sRUFBRTtRQUMxQ0YsU0FBUyxHQUFHQSxTQUFTLENBQUNILE9BQU8sQ0FBQ0ssT0FBTyxFQUFFLEVBQUUsQ0FBQztNQUM5QyxDQUFDLENBQUM7O01BRUY7TUFDQUYsU0FBUyxHQUFHQSxTQUFTLENBQUNILE9BQU8sQ0FBQyxvQkFBb0IsRUFBRSxVQUFVTSxLQUFLLEVBQUVuQixPQUFPLEVBQUVLLEtBQUssRUFBRTtRQUNqRixJQUFJZSxHQUFHLEdBQUdwQixPQUFPLENBQUNDLFdBQVcsQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQzVCLFlBQVksQ0FBQytDLEdBQUcsQ0FBQyxFQUFFLE9BQU8sRUFBRTs7UUFFakM7UUFDQSxJQUFJRCxLQUFLLENBQUNFLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUUsT0FBTyxJQUFJLEdBQUdELEdBQUcsR0FBRyxHQUFHOztRQUVwRDtRQUNBLElBQUlFLFVBQVUsR0FBRyxFQUFFO1FBQ25CLElBQUlDLFNBQVMsR0FBRyx5QkFBeUI7UUFDekMsSUFBSUMsU0FBUztRQUViLE9BQU8sQ0FBQ0EsU0FBUyxHQUFHRCxTQUFTLENBQUNFLElBQUksQ0FBQ3BCLEtBQUssQ0FBQyxNQUFNLElBQUksRUFBRTtVQUNqRCxJQUFJcUIsUUFBUSxHQUFHRixTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUN2QixXQUFXLENBQUMsQ0FBQztVQUN6QyxJQUFJM0IsYUFBYSxDQUFDb0QsUUFBUSxDQUFDLElBQUksQ0FBQ2xELGFBQWEsQ0FBQ2tDLElBQUksQ0FBQ2dCLFFBQVEsQ0FBQyxFQUFFO1lBQzFELElBQUlDLEdBQUcsR0FBR0gsU0FBUyxDQUFDLENBQUMsQ0FBQztZQUN0QixJQUFJLENBQUNFLFFBQVEsS0FBSyxNQUFNLElBQUlBLFFBQVEsS0FBSyxLQUFLLEtBQUtuRCxhQUFhLENBQUNtQyxJQUFJLENBQUNpQixHQUFHLENBQUMsRUFBRTtjQUN4RTtZQUNKO1lBQ0FMLFVBQVUsSUFBSSxHQUFHLEdBQUdJLFFBQVEsR0FBRyxJQUFJLEdBQUdDLEdBQUcsR0FBRyxHQUFHO1VBQ25EO1FBQ0o7UUFFQSxPQUFPLEdBQUcsR0FBR1AsR0FBRyxHQUFHRSxVQUFVLEdBQUcsR0FBRztNQUN2QyxDQUFDLENBQUM7TUFFRixPQUFPTixTQUFTO0lBQ3BCOztJQUVBO0lBQ0EsT0FBTztNQUNIO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtNQUNZWSxRQUFRLEVBQUUsU0FBVkEsUUFBUUEsQ0FBWS9DLEtBQUssRUFBRTtRQUN2QixJQUFJLE9BQU9BLEtBQUssS0FBSyxRQUFRLEVBQUUsT0FBTyxFQUFFO1FBQ3hDLElBQUksQ0FBQ0EsS0FBSyxDQUFDQyxJQUFJLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRTtRQUU1QixJQUFJTCxZQUFZLENBQUMsQ0FBQyxFQUFFO1VBQ2hCLE9BQU9HLHFCQUFxQixDQUFDQyxLQUFLLENBQUM7UUFDdkM7UUFDQSxPQUFPUyxpQkFBaUIsQ0FBQ1QsS0FBSyxDQUFDO01BQ25DLENBQUM7TUFFRGlCLFVBQVUsRUFBRUEsVUFBVTtNQUN0QmEsVUFBVSxFQUFFQTtJQUNoQixDQUFDO0VBQ0wsQ0FBQyxDQUFFLENBQUM7O0VBRUo7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0VBRUE7RUFDQTtFQUNBOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7RUFDSSxTQUFTa0IsV0FBV0EsQ0FBQzFCLE9BQU8sRUFBRVMsSUFBSSxFQUFFO0lBQ2hDLElBQUksQ0FBQ1QsT0FBTyxFQUFFO0lBQ2RBLE9BQU8sQ0FBQ0osV0FBVyxHQUFHYSxJQUFJO0VBQzlCOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7RUFDSSxTQUFTa0IsV0FBV0EsQ0FBQzNCLE9BQU8sRUFBRVcsSUFBSSxFQUFFO0lBQ2hDLElBQUksQ0FBQ1gsT0FBTyxFQUFFO0lBQ2RBLE9BQU8sQ0FBQzRCLFNBQVMsR0FBRzNELFNBQVMsQ0FBQ3dELFFBQVEsQ0FBQ2QsSUFBSSxDQUFDO0VBQ2hEOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLFNBQVNrQix1QkFBdUJBLENBQUNDLEdBQUcsRUFBRUMsVUFBVSxFQUFFO0lBQzlDQSxVQUFVLEdBQUdBLFVBQVUsS0FBSyxPQUFPQyxRQUFRLEtBQUssV0FBVyxHQUFHQSxRQUFRLEdBQUcsSUFBSSxDQUFDO0lBQzlFLElBQUksQ0FBQ0QsVUFBVSxFQUFFLE9BQU8sRUFBRTtJQUUxQixJQUFJRSxRQUFRLEdBQUdILEdBQUcsR0FDWixxQkFBcUIsR0FBR0EsR0FBRyxHQUFHLElBQUksR0FDbEMsb0JBQW9CO0lBRTFCLE9BQU9DLFVBQVUsQ0FBQ0csZ0JBQWdCLENBQUNELFFBQVEsQ0FBQztFQUNoRDs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBU0UsV0FBV0EsQ0FBQ0MsTUFBTSxFQUFFQyxhQUFhLEVBQUU7SUFDeEMsSUFBSSxDQUFDQSxhQUFhLElBQUksSUFBQUMsUUFBQSxDQUFBQyxPQUFBLEVBQU9GLGFBQWEsTUFBSyxRQUFRLEVBQUU7TUFDckRwRCxPQUFPLENBQUNDLElBQUksQ0FBQyx5RkFBeUYsQ0FBQztNQUN2RyxPQUFPLElBQUk7SUFDZjs7SUFFQTtJQUNBLElBQUltRCxhQUFhLENBQUNELE1BQU0sQ0FBQyxFQUFFO01BQ3ZCLE9BQU9DLGFBQWEsQ0FBQ0QsTUFBTSxDQUFDO0lBQ2hDOztJQUVBO0lBQ0EsSUFBSUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxFQUFFO01BQzFCLE9BQU9BLGFBQWEsQ0FBQyxTQUFTLENBQUM7SUFDbkM7O0lBRUE7SUFDQSxJQUFJRyxRQUFRLEdBQUdDLE1BQU0sQ0FBQ0MsSUFBSSxDQUFDTCxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUMsSUFBSUcsUUFBUSxFQUFFO01BQ1Z2RCxPQUFPLENBQUNDLElBQUksQ0FBQyw0QkFBNEIsR0FBR2tELE1BQU0sR0FBRyw4Q0FBOEMsRUFBRUksUUFBUSxDQUFDO01BQzlHLE9BQU9ILGFBQWEsQ0FBQ0csUUFBUSxDQUFDO0lBQ2xDO0lBRUEsT0FBTyxJQUFJO0VBQ2Y7O0VBRUE7RUFDQTtFQUNBOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLFNBQVNHLG9CQUFvQkEsQ0FBQ0MsS0FBSyxFQUFFQyxPQUFPLEVBQUU7SUFDMUMsSUFBSUQsS0FBSyxDQUFDcEQsTUFBTSxLQUFLcUQsT0FBTyxDQUFDckQsTUFBTSxFQUFFLE9BQU9vRCxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3BELElBQUlFLEdBQUcsR0FBRyxDQUFDO0lBQ1gsSUFBSXhELENBQUM7SUFDTCxLQUFLQSxDQUFDLEdBQUcsQ0FBQyxFQUFFQSxDQUFDLEdBQUd1RCxPQUFPLENBQUNyRCxNQUFNLEVBQUVGLENBQUMsRUFBRSxFQUFFO01BQ2pDd0QsR0FBRyxJQUFJRCxPQUFPLENBQUN2RCxDQUFDLENBQUM7SUFDckI7SUFDQSxJQUFJeUQsQ0FBQyxHQUFHQyxJQUFJLENBQUNDLE1BQU0sQ0FBQyxDQUFDLEdBQUdILEdBQUc7SUFDM0IsSUFBSUksS0FBSyxHQUFHLENBQUM7SUFDYixLQUFLNUQsQ0FBQyxHQUFHLENBQUMsRUFBRUEsQ0FBQyxHQUFHc0QsS0FBSyxDQUFDcEQsTUFBTSxFQUFFRixDQUFDLEVBQUUsRUFBRTtNQUMvQjRELEtBQUssSUFBSUwsT0FBTyxDQUFDdkQsQ0FBQyxDQUFDO01BQ25CLElBQUl5RCxDQUFDLElBQUlHLEtBQUssRUFBRSxPQUFPTixLQUFLLENBQUN0RCxDQUFDLENBQUM7SUFDbkM7SUFDQSxPQUFPc0QsS0FBSyxDQUFDQSxLQUFLLENBQUNwRCxNQUFNLEdBQUcsQ0FBQyxDQUFDO0VBQ2xDOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLFNBQVMyRCx1QkFBdUJBLENBQUNkLGFBQWEsRUFBRTtJQUM1QyxJQUFJLENBQUNBLGFBQWEsSUFBSSxJQUFBQyxRQUFBLENBQUFDLE9BQUEsRUFBT0YsYUFBYSxNQUFLLFFBQVEsRUFBRTtNQUNyRCxPQUFPLElBQUk7SUFDZjtJQUVBLElBQUlPLEtBQUssR0FBR0gsTUFBTSxDQUFDQyxJQUFJLENBQUNMLGFBQWEsQ0FBQztJQUN0QyxJQUFJTyxLQUFLLENBQUNwRCxNQUFNLEtBQUssQ0FBQyxFQUFFO01BQ3BCLE9BQU8sSUFBSTtJQUNmO0lBRUEsSUFBSXFELE9BQU8sR0FBRyxFQUFFO0lBQ2hCLEtBQUssSUFBSXZELENBQUMsR0FBRyxDQUFDLEVBQUVBLENBQUMsR0FBR3NELEtBQUssQ0FBQ3BELE1BQU0sRUFBRUYsQ0FBQyxFQUFFLEVBQUU7TUFDbkN1RCxPQUFPLENBQUNPLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBQztJQUNwQjtJQUNBLE9BQU9ULG9CQUFvQixDQUFDQyxLQUFLLEVBQUVDLE9BQU8sQ0FBQztFQUMvQzs7RUFFQTtFQUNBO0VBQ0E7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtFQUNJLElBQUlRLGNBQWMsR0FBRztJQUNqQjtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDUUMsY0FBYyxFQUFFLFNBQWhCQSxjQUFjQSxDQUFZQyxPQUFPLEVBQUVDLE9BQU8sRUFBRTtNQUN4Q0EsT0FBTyxHQUFHQSxPQUFPLElBQUksQ0FBQyxDQUFDO01BQ3ZCLElBQUlDLFdBQVcsR0FBR0QsT0FBTyxDQUFDRSxLQUFLLElBQUksQ0FBQyxDQUFDO01BQ3JDLElBQUlyQixhQUFhLEdBQUdtQixPQUFPLENBQUNHLFNBQVM7TUFDckMsSUFBSUMsb0JBQW9CLEdBQUdKLE9BQU8sQ0FBQ0ssY0FBYyxLQUFLLEtBQUs7O01BRTNEO01BQ0EsSUFBSSxDQUFDeEIsYUFBYSxJQUFJLElBQUFDLFFBQUEsQ0FBQUMsT0FBQSxFQUFPRixhQUFhLE1BQUssUUFBUSxJQUFJSSxNQUFNLENBQUNDLElBQUksQ0FBQ0wsYUFBYSxDQUFDLENBQUM3QyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ2hHUCxPQUFPLENBQUNDLElBQUksQ0FBQyx5RkFBeUYsQ0FBQztRQUN2RyxPQUFPO1VBQ0g0RSxRQUFRLEVBQUUsSUFBSTtVQUNkMUIsTUFBTSxFQUFFLFNBQVM7VUFDakIyQixNQUFNLEVBQUUsT0FBTztVQUNmUixPQUFPLEVBQUVBLE9BQU87VUFDaEJTLEtBQUssRUFBRTtRQUNYLENBQUM7TUFDTDtNQUVBLElBQUk1QixNQUFNLEdBQUdtQixPQUFPLENBQUNVLGFBQWE7TUFDbEMsSUFBSUYsTUFBTSxHQUFHLFNBQVM7O01BRXRCO01BQ0EsSUFBSVIsT0FBTyxDQUFDVyxNQUFNLEVBQUU7UUFDaEJILE1BQU0sR0FBRyxLQUFLO01BQ2xCLENBQUMsTUFBTSxJQUFJUixPQUFPLENBQUNZLFFBQVEsSUFBSVosT0FBTyxDQUFDWSxRQUFRLENBQUNDLFFBQVEsS0FBSyxRQUFRLEVBQUU7UUFDbkVMLE1BQU0sR0FBRyxVQUFVO01BQ3ZCOztNQUVBO01BQ0EsS0FBSyxJQUFJTSxPQUFPLElBQUlaLFdBQVcsRUFBRTtRQUM3QixJQUFJYSxJQUFJLEdBQUdiLFdBQVcsQ0FBQ1ksT0FBTyxDQUFDO1FBQy9CLElBQUksT0FBT0MsSUFBSSxDQUFDdEQsS0FBSyxLQUFLLFVBQVUsSUFBSXNELElBQUksQ0FBQ3RELEtBQUssQ0FBQ3VDLE9BQU8sQ0FBQyxFQUFFO1VBQ3pEbkIsTUFBTSxHQUFHa0MsSUFBSSxDQUFDbEMsTUFBTSxJQUFJaUMsT0FBTztVQUMvQk4sTUFBTSxHQUFHLGFBQWE7VUFDdEI7UUFDSjtNQUNKOztNQUVBO01BQ0E7TUFDQSxJQUFJM0IsTUFBTSxLQUFLLFNBQVMsSUFBSTJCLE1BQU0sS0FBSyxTQUFTLElBQUlILG9CQUFvQixFQUFFO1FBQ3RFLElBQUlXLFlBQVksR0FBR3BCLHVCQUF1QixDQUFDZCxhQUFhLENBQUM7UUFDekQsSUFBSWtDLFlBQVksRUFBRTtVQUNkbkMsTUFBTSxHQUFHbUMsWUFBWTtVQUNyQlIsTUFBTSxHQUFHLFdBQVc7UUFDeEI7TUFDSjs7TUFFQTtNQUNBLElBQUkvRixJQUFJLENBQUN3RyxrQkFBa0IsSUFBSSxPQUFPeEcsSUFBSSxDQUFDd0csa0JBQWtCLENBQUNDLFdBQVcsS0FBSyxVQUFVLEVBQUU7UUFDdEZ6RyxJQUFJLENBQUN3RyxrQkFBa0IsQ0FBQ0MsV0FBVyxDQUFDO1VBQ2hDbEIsT0FBTyxFQUFFQSxPQUFPO1VBQ2hCbkIsTUFBTSxFQUFFQSxNQUFNO1VBQ2RzQyxlQUFlLEVBQUV0QyxNQUFNO1VBQ3ZCMkIsTUFBTSxFQUFFQSxNQUFNO1VBQ2RZLFVBQVUsRUFBRTtRQUNoQixDQUFDLENBQUM7TUFDTjtNQUVBLE9BQU87UUFDSGIsUUFBUSxFQUFFM0IsV0FBVyxDQUFDQyxNQUFNLEVBQUVDLGFBQWEsQ0FBQztRQUM1Q0QsTUFBTSxFQUFFQSxNQUFNO1FBQ2QyQixNQUFNLEVBQUVBLE1BQU07UUFDZFIsT0FBTyxFQUFFQTtNQUNiLENBQUM7SUFDTCxDQUFDO0lBRUQ7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtJQUNRcUIsTUFBTSxFQUFFLFNBQVJBLE1BQU1BLENBQVlyQixPQUFPLEVBQUVDLE9BQU8sRUFBRTtNQUNoQ0EsT0FBTyxHQUFHQSxPQUFPLElBQUksQ0FBQyxDQUFDOztNQUV2QjtNQUNBLElBQUlBLE9BQU8sQ0FBQ3FCLFFBQVEsSUFBSXJCLE9BQU8sQ0FBQ3NCLFFBQVEsSUFBSTlHLElBQUksQ0FBQytHLGdCQUFnQixFQUFFO1FBQy9ELElBQUlDLElBQUksR0FBRyxJQUFJO1FBQ2YsSUFBSUMsUUFBUSxHQUFHakgsSUFBSSxDQUFDK0csZ0JBQWdCO1FBQ3BDLElBQUlHLFNBQVMsR0FBR0QsUUFBUSxDQUFDRSxPQUFPLENBQUMzQixPQUFPLENBQUNzQixRQUFRLENBQUM7UUFFbEQsSUFBSUksU0FBUyxDQUFDRSxLQUFLLEVBQUU7VUFDakIsT0FBT0gsUUFBUSxDQUFDTCxNQUFNLENBQUNyQixPQUFPLEVBQUVDLE9BQU8sQ0FBQyxDQUNuQzZCLEtBQUssQ0FBQyxVQUFVckIsS0FBSyxFQUFFO1lBQ3BCO1lBQ0EsSUFBSXNCLFFBQVEsR0FBRzlCLE9BQU8sQ0FBQ3NCLFFBQVEsQ0FBQ1Msa0JBQWtCLEtBQUssS0FBSztZQUM1RCxJQUFJRCxRQUFRLEVBQUU7Y0FDVnJHLE9BQU8sQ0FBQ0MsSUFBSSxDQUFDLHFEQUFxRCxFQUFFOEUsS0FBSyxDQUFDd0IsT0FBTyxDQUFDO2NBQ2xGLE9BQU9SLElBQUksQ0FBQzFCLGNBQWMsQ0FBQ0MsT0FBTyxFQUFFQyxPQUFPLENBQUM7WUFDaEQ7WUFDQSxNQUFNUSxLQUFLO1VBQ2YsQ0FBQyxDQUFDO1FBQ1YsQ0FBQyxNQUFNO1VBQ0gvRSxPQUFPLENBQUNDLElBQUksQ0FBQyxpQ0FBaUMsRUFBRWdHLFNBQVMsQ0FBQ2xCLEtBQUssRUFBRSx5QkFBeUIsQ0FBQztRQUMvRjtNQUNKOztNQUVBO01BQ0EsT0FBTyxJQUFJLENBQUNWLGNBQWMsQ0FBQ0MsT0FBTyxFQUFFQyxPQUFPLENBQUM7SUFDaEQ7RUFDSixDQUFDOztFQUVEO0VBQ0E7RUFDQTs7RUFFQTtFQUNBO0VBQ0E7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBU2lDLGtCQUFrQkEsQ0FBQ0MsUUFBUSxFQUFFbEMsT0FBTyxFQUFFO0lBQzNDQSxPQUFPLEdBQUdBLE9BQU8sSUFBSSxDQUFDLENBQUM7SUFDdkIsSUFBSU0sUUFBUSxHQUFHNEIsUUFBUSxDQUFDNUIsUUFBUTtJQUNoQyxJQUFJUCxPQUFPLEdBQUdtQyxRQUFRLENBQUNuQyxPQUFPLElBQUksQ0FBQyxDQUFDO0lBQ3BDLElBQUlvQyxHQUFHLEdBQUduQyxPQUFPLENBQUNtQyxHQUFHLEtBQUssS0FBSztJQUUvQixJQUFJLENBQUM3QixRQUFRLEVBQUU7TUFDWDdFLE9BQU8sQ0FBQ0MsSUFBSSxDQUFDLGdFQUFnRSxDQUFDO01BQzlFLE9BQU93RyxRQUFRO0lBQ25COztJQUVBO0lBQ0EsSUFBSUUsS0FBSyxHQUFHLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLFNBQVMsQ0FBQztJQUV2RUEsS0FBSyxDQUFDOUUsT0FBTyxDQUFDLFVBQVUrRSxJQUFJLEVBQUU7TUFDMUIsSUFBSUMsUUFBUSxHQUFHakUsdUJBQXVCLENBQUNnRSxJQUFJLENBQUM7TUFFNUMsS0FBSyxJQUFJdkcsQ0FBQyxHQUFHLENBQUMsRUFBRUEsQ0FBQyxHQUFHd0csUUFBUSxDQUFDdEcsTUFBTSxFQUFFRixDQUFDLEVBQUUsRUFBRTtRQUN0QyxJQUFJVSxPQUFPLEdBQUc4RixRQUFRLENBQUN4RyxDQUFDLENBQUM7UUFDekIsSUFBSWdCLEtBQUssR0FBR3dELFFBQVEsQ0FBQytCLElBQUksQ0FBQztRQUMxQixJQUFJLENBQUN2RixLQUFLLEVBQUU7UUFFWixJQUFJdUYsSUFBSSxLQUFLLE9BQU8sRUFBRTtVQUNsQjtVQUNBLElBQUk3RixPQUFPLENBQUNILE9BQU8sS0FBSyxLQUFLLEVBQUU7WUFDM0JHLE9BQU8sQ0FBQytGLEdBQUcsR0FBR3pGLEtBQUs7WUFDbkJOLE9BQU8sQ0FBQ2dHLEdBQUcsR0FBR2xDLFFBQVEsQ0FBQ21DLFFBQVEsSUFBSSxvQkFBb0I7VUFDM0QsQ0FBQyxNQUFNO1lBQ0hqRyxPQUFPLENBQUNrRyxLQUFLLENBQUNDLGVBQWUsR0FBRyxNQUFNLEdBQUc3RixLQUFLLEdBQUcsR0FBRztVQUN4RDtRQUNKLENBQUMsTUFBTSxJQUFJdUYsSUFBSSxLQUFLLFNBQVMsRUFBRTtVQUMzQjtVQUNBN0YsT0FBTyxDQUFDb0csSUFBSSxHQUFHOUYsS0FBSztRQUN4QixDQUFDLE1BQU07VUFDSDtVQUNBb0IsV0FBVyxDQUFDMUIsT0FBTyxFQUFFTSxLQUFLLENBQUM7UUFDL0I7TUFDSjtJQUNKLENBQUMsQ0FBQzs7SUFFRjtJQUNBLElBQUkrRixZQUFZLEdBQUd4RSx1QkFBdUIsQ0FBQyxNQUFNLENBQUM7SUFDbEQsS0FBSyxJQUFJeUUsQ0FBQyxHQUFHLENBQUMsRUFBRUEsQ0FBQyxHQUFHRCxZQUFZLENBQUM3RyxNQUFNLEVBQUU4RyxDQUFDLEVBQUUsRUFBRTtNQUMxQyxJQUFJQyxNQUFNLEdBQUdGLFlBQVksQ0FBQ0MsQ0FBQyxDQUFDO01BQzVCQyxNQUFNLENBQUNDLFlBQVksQ0FBQyxhQUFhLEVBQUVkLFFBQVEsQ0FBQ3RELE1BQU0sQ0FBQztNQUNuRG1FLE1BQU0sQ0FBQ0MsWUFBWSxDQUFDLGFBQWEsRUFBRWQsUUFBUSxDQUFDM0IsTUFBTSxDQUFDOztNQUVuRDtNQUNBLElBQUlELFFBQVEsQ0FBQzJDLEtBQUssSUFBSSxDQUFDRixNQUFNLENBQUNHLGFBQWEsQ0FBQyw0QkFBNEIsQ0FBQyxFQUFFO1FBQ3ZFSCxNQUFNLENBQUNMLEtBQUssQ0FBQ0MsZUFBZSxHQUFHLE1BQU0sR0FBR3JDLFFBQVEsQ0FBQzJDLEtBQUssR0FBRyxHQUFHO01BQ2hFO0lBQ0o7O0lBRUE7SUFDQSxJQUFJZCxHQUFHLElBQUksT0FBTzFHLE9BQU8sS0FBSyxXQUFXLEVBQUU7TUFDdkNBLE9BQU8sQ0FBQzBHLEdBQUcsQ0FBQyw0QkFBNEIsRUFBRTtRQUN0Q3ZELE1BQU0sRUFBRXNELFFBQVEsQ0FBQ3RELE1BQU07UUFDdkIyQixNQUFNLEVBQUUyQixRQUFRLENBQUMzQixNQUFNO1FBQ3ZCa0MsUUFBUSxFQUFFbkMsUUFBUSxDQUFDbUMsUUFBUTtRQUMzQi9CLE1BQU0sRUFBRVgsT0FBTyxDQUFDVyxNQUFNO1FBQ3RCeUMsU0FBUyxFQUFFcEQsT0FBTyxDQUFDcUQsR0FBRyxJQUFJLENBQUMsQ0FBQztRQUM1QkMsU0FBUyxFQUFFbkIsUUFBUSxDQUFDM0IsTUFBTSxLQUFLLElBQUksSUFBSTJCLFFBQVEsQ0FBQzNCLE1BQU0sS0FBSztNQUMvRCxDQUFDLENBQUM7SUFDTjtJQUVBLE9BQU8yQixRQUFRO0VBQ25COztFQUVBO0VBQ0E7RUFDQTs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBU29CLGNBQWNBLENBQUN0RCxPQUFPLEVBQUU7SUFDN0IsSUFBSUEsT0FBTyxJQUFJQSxPQUFPLENBQUNELE9BQU8sRUFBRTtNQUM1QixPQUFPQyxPQUFPLENBQUNELE9BQU87SUFDMUI7SUFFQSxJQUFJdkYsSUFBSSxDQUFDK0ksTUFBTSxJQUFJLE9BQU8vSSxJQUFJLENBQUMrSSxNQUFNLENBQUNDLFVBQVUsS0FBSyxVQUFVLEVBQUU7TUFDN0QsT0FBT2hKLElBQUksQ0FBQytJLE1BQU0sQ0FBQ0MsVUFBVSxDQUFDLENBQUM7SUFDbkM7O0lBRUE7SUFDQSxPQUFPO01BQ0hKLEdBQUcsRUFBRSxDQUFDLENBQUM7TUFDUHpDLFFBQVEsRUFBRTtRQUFFSixNQUFNLEVBQUUsUUFBUTtRQUFFSyxRQUFRLEVBQUUsUUFBUTtRQUFFNkMsR0FBRyxFQUFFO01BQUcsQ0FBQztNQUMzREMsU0FBUyxFQUFFO1FBQUVDLEdBQUcsRUFBRSxFQUFFO1FBQUVDLFFBQVEsRUFBRSxLQUFLO1FBQUVDLFFBQVEsRUFBRSxLQUFLO1FBQUVDLFNBQVMsRUFBRTtNQUFLLENBQUM7TUFDekVDLFNBQVMsRUFBRUMsSUFBSSxDQUFDQyxHQUFHLENBQUMsQ0FBQztNQUNyQnZELE1BQU0sRUFBRSxLQUFLO01BQ2JELGFBQWEsRUFBRTtJQUNuQixDQUFDO0VBQ0w7O0VBRUE7RUFDQTtFQUNBOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBU3lELFdBQVdBLENBQUNsRSxPQUFPLEVBQUU7SUFDMUJBLE9BQU8sR0FBR0EsT0FBTyxJQUFJLENBQUMsQ0FBQzs7SUFFdkI7SUFDQSxJQUFJLENBQUNBLE9BQU8sQ0FBQ0csU0FBUyxJQUFJLElBQUFyQixRQUFBLENBQUFDLE9BQUEsRUFBT2lCLE9BQU8sQ0FBQ0csU0FBUyxNQUFLLFFBQVEsSUFBSWxCLE1BQU0sQ0FBQ0MsSUFBSSxDQUFDYyxPQUFPLENBQUNHLFNBQVMsQ0FBQyxDQUFDbkUsTUFBTSxLQUFLLENBQUMsRUFBRTtNQUM1R1AsT0FBTyxDQUFDK0UsS0FBSyxDQUFDLG1GQUFtRixDQUFDO01BQ2xHLE9BQU87UUFDSEYsUUFBUSxFQUFFLElBQUk7UUFDZDFCLE1BQU0sRUFBRSxTQUFTO1FBQ2pCMkIsTUFBTSxFQUFFLE9BQU87UUFDZlIsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNYUyxLQUFLLEVBQUU7TUFDWCxDQUFDO0lBQ0w7SUFFQSxJQUFJVCxPQUFPLEdBQUd1RCxjQUFjLENBQUN0RCxPQUFPLENBQUM7SUFDckMsSUFBSWtDLFFBQVEsR0FBR3JDLGNBQWMsQ0FBQ3VCLE1BQU0sQ0FBQ3JCLE9BQU8sRUFBRUMsT0FBTyxDQUFDOztJQUV0RDtJQUNBLElBQUlrQyxRQUFRLElBQUksT0FBT0EsUUFBUSxDQUFDaUMsSUFBSSxLQUFLLFVBQVUsRUFBRTtNQUNqRCxPQUFPakMsUUFBUSxDQUFDaUMsSUFBSSxDQUFDLFVBQVVoRCxVQUFVLEVBQUU7UUFDdkMsT0FBT2Msa0JBQWtCLENBQUNkLFVBQVUsRUFBRW5CLE9BQU8sQ0FBQztNQUNsRCxDQUFDLENBQUMsQ0FBQzZCLEtBQUssQ0FBQyxVQUFVdUMsR0FBRyxFQUFFO1FBQ3BCM0ksT0FBTyxDQUFDQyxJQUFJLENBQUMsdURBQXVELEVBQUUwSSxHQUFHLENBQUNwQyxPQUFPLENBQUM7UUFDbEY7UUFDQSxJQUFJcUMsZ0JBQWdCLEdBQUd4RSxjQUFjLENBQUNDLGNBQWMsQ0FBQ0MsT0FBTyxFQUFFQyxPQUFPLENBQUM7UUFDdEUsT0FBT2lDLGtCQUFrQixDQUFDb0MsZ0JBQWdCLEVBQUVyRSxPQUFPLENBQUM7TUFDeEQsQ0FBQyxDQUFDO0lBQ047O0lBRUE7SUFDQSxPQUFPaUMsa0JBQWtCLENBQUNDLFFBQVEsRUFBRWxDLE9BQU8sQ0FBQztFQUNoRDs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBU3NFLGdCQUFnQkEsQ0FBQ3RFLE9BQU8sRUFBRTtJQUMvQkEsT0FBTyxHQUFHQSxPQUFPLElBQUksQ0FBQyxDQUFDOztJQUV2QjtJQUNBLElBQUl4RixJQUFJLENBQUMrSSxNQUFNLElBQUksT0FBTy9JLElBQUksQ0FBQytJLE1BQU0sQ0FBQ2dCLGVBQWUsS0FBSyxVQUFVLEVBQUU7TUFDbEUsT0FBTy9KLElBQUksQ0FBQytJLE1BQU0sQ0FBQ2dCLGVBQWUsQ0FBQ3ZFLE9BQU8sQ0FBQyxDQUFDbUUsSUFBSSxDQUFDLFVBQVVwRSxPQUFPLEVBQUU7UUFDaEVDLE9BQU8sQ0FBQ0QsT0FBTyxHQUFHQSxPQUFPO1FBQ3pCLE9BQU9tRSxXQUFXLENBQUNsRSxPQUFPLENBQUM7TUFDL0IsQ0FBQyxDQUFDLENBQUNtRSxJQUFJLENBQUMsVUFBVWpDLFFBQVEsRUFBRTtRQUN4QjtRQUNBLE9BQU9BLFFBQVE7TUFDbkIsQ0FBQyxDQUFDLENBQUNMLEtBQUssQ0FBQyxVQUFVdUMsR0FBRyxFQUFFO1FBQ3BCM0ksT0FBTyxDQUFDQyxJQUFJLENBQUMsK0NBQStDLEVBQUUwSSxHQUFHLENBQUM7UUFDbEU7UUFDQSxJQUFJSSxlQUFlLEdBQUc7VUFDbEJyRSxTQUFTLEVBQUVILE9BQU8sQ0FBQ0csU0FBUztVQUM1QkosT0FBTyxFQUFFdUQsY0FBYyxDQUFDdEQsT0FBTyxDQUFDO1VBQ2hDbUMsR0FBRyxFQUFFbkMsT0FBTyxDQUFDbUM7UUFDakIsQ0FBQztRQUNELElBQUlrQyxnQkFBZ0IsR0FBR3hFLGNBQWMsQ0FBQ0MsY0FBYyxDQUFDMEUsZUFBZSxDQUFDekUsT0FBTyxFQUFFeUUsZUFBZSxDQUFDO1FBQzlGLE9BQU92QyxrQkFBa0IsQ0FBQ29DLGdCQUFnQixFQUFFRyxlQUFlLENBQUM7TUFDaEUsQ0FBQyxDQUFDO0lBQ047O0lBRUE7SUFDQSxJQUFJO01BQ0EsSUFBSUMsTUFBTSxHQUFHUCxXQUFXLENBQUNsRSxPQUFPLENBQUM7TUFDakM7TUFDQSxJQUFJeUUsTUFBTSxJQUFJLE9BQU9BLE1BQU0sQ0FBQ04sSUFBSSxLQUFLLFVBQVUsRUFBRTtRQUM3QyxPQUFPTSxNQUFNO01BQ2pCO01BQ0EsT0FBT0MsT0FBTyxDQUFDQyxPQUFPLENBQUNGLE1BQU0sQ0FBQztJQUNsQyxDQUFDLENBQUMsT0FBT0wsR0FBRyxFQUFFO01BQ1YzSSxPQUFPLENBQUNDLElBQUksQ0FBQyx5Q0FBeUMsRUFBRTBJLEdBQUcsQ0FBQztNQUM1RCxJQUFJUSxjQUFjLEdBQUc7UUFDakJ4QixHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQ1B6QyxRQUFRLEVBQUU7VUFBRUosTUFBTSxFQUFFLFFBQVE7VUFBRUssUUFBUSxFQUFFLFFBQVE7VUFBRTZDLEdBQUcsRUFBRTtRQUFHLENBQUM7UUFDM0RDLFNBQVMsRUFBRTtVQUFFQyxHQUFHLEVBQUUsRUFBRTtVQUFFQyxRQUFRLEVBQUUsS0FBSztVQUFFQyxRQUFRLEVBQUUsS0FBSztVQUFFQyxTQUFTLEVBQUU7UUFBSyxDQUFDO1FBQ3pFQyxTQUFTLEVBQUVDLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUM7UUFDckJ2RCxNQUFNLEVBQUUsS0FBSztRQUNiRCxhQUFhLEVBQUU7TUFDbkIsQ0FBQztNQUNELElBQUlxQixRQUFRLEdBQUdqQyxjQUFjLENBQUNDLGNBQWMsQ0FBQzhFLGNBQWMsRUFBRTtRQUFFekUsU0FBUyxFQUFFSCxPQUFPLENBQUNHO01BQVUsQ0FBQyxDQUFDO01BQzlGLE9BQU91RSxPQUFPLENBQUNDLE9BQU8sQ0FBQzFDLGtCQUFrQixDQUFDSCxRQUFRLEVBQUU5QixPQUFPLENBQUMsQ0FBQztJQUNqRTtFQUNKOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7RUFDSSxTQUFTNkUsUUFBUUEsQ0FBQzdFLE9BQU8sRUFBRTtJQUN2QkEsT0FBTyxHQUFHQSxPQUFPLElBQUksQ0FBQyxDQUFDO0lBRXZCLFNBQVM4RSxHQUFHQSxDQUFBLEVBQUc7TUFDWDtNQUNBLElBQUl4QyxRQUFRLEdBQUdqRSx1QkFBdUIsQ0FBQyxDQUFDO01BQ3hDLElBQUlpRSxRQUFRLENBQUN0RyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQ3JCa0ksV0FBVyxDQUFDbEUsT0FBTyxDQUFDO01BQ3hCO0lBQ0o7O0lBRUE7SUFDQSxJQUFJLE9BQU94QixRQUFRLEtBQUssV0FBVyxFQUFFO01BQ2pDLElBQUlBLFFBQVEsQ0FBQ3VHLFVBQVUsS0FBSyxTQUFTLEVBQUU7UUFDbkN2RyxRQUFRLENBQUN3RyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRUYsR0FBRyxDQUFDO01BQ3RELENBQUMsTUFBTTtRQUNIQSxHQUFHLENBQUMsQ0FBQztNQUNUO0lBQ0o7RUFDSjs7RUFFQTtFQUNBO0VBQ0E7O0VBRUEsSUFBSUcsY0FBYyxHQUFHO0lBQ2pCO0lBQ0E7SUFDQUMsU0FBUyxFQUFFekssU0FBUztJQUNwQjBLLFlBQVksRUFBRSxTQUFkQSxZQUFZQSxDQUFZaEksSUFBSSxFQUFFO01BQUUsT0FBTzFDLFNBQVMsQ0FBQ3dELFFBQVEsQ0FBQ2QsSUFBSSxDQUFDO0lBQUMsQ0FBQztJQUNqRWUsV0FBVyxFQUFFQSxXQUFXO0lBQ3hCQyxXQUFXLEVBQUVBLFdBQVc7SUFDeEJpSCxZQUFZLEVBQUUvRyx1QkFBdUI7SUFDckNNLFdBQVcsRUFBRUEsV0FBVztJQUN4QjBHLE1BQU0sRUFBRXhGLGNBQWM7SUFDdEJxRSxXQUFXLEVBQUVBLFdBQVc7SUFDeEJJLGdCQUFnQixFQUFFQSxnQkFBZ0I7SUFDbENPLFFBQVEsRUFBRUEsUUFBUTtJQUNsQjFGLG9CQUFvQixFQUFFQSxvQkFBb0I7SUFDMUNRLHVCQUF1QixFQUFFQSx1QkFBdUI7SUFDaERzQyxrQkFBa0IsRUFBRUEsa0JBQWtCO0lBQ3RDcUIsY0FBYyxFQUFFQTtFQUNwQixDQUFDOztFQUVEO0VBQ0E5SSxJQUFJLENBQUN5SyxjQUFjLEdBQUdBLGNBQWM7QUFFeEMsQ0FBQyxFQUFFLE9BQU9LLE1BQU0sS0FBSyxXQUFXLEdBQUdBLE1BQU0sR0FBRyxPQUFPQyxNQUFNLEtBQUssV0FBVyxHQUFHQSxNQUFNLFNBQU8sQ0FBQyIsImlnbm9yZUxpc3QiOltdfQ==