@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.
- package/README.md +552 -0
- package/build/es5/__tests__/ai-personalize.test.js +811 -0
- package/build/es5/__tests__/lua.js +134 -0
- package/build/es5/__tests__/original-roughly.js +197 -0
- package/build/es5/__tests__/original.js +174 -0
- package/build/es5/__tests__/unit.js +72 -0
- package/build/es5/__tests__/weighted-history.test.js +376 -0
- package/build/es5/ai-personalize.js +641 -0
- package/build/es5/index.js +30 -0
- package/build/es5/lua.js +366 -0
- package/build/es5/personalization.js +811 -0
- package/build/es5/prompts/personalization-prompts.js +260 -0
- package/build/es5/storage/weighted-history.js +384 -0
- package/build/es5/stores/browser-cookie.js +25 -0
- package/build/es5/stores/local.js +29 -0
- package/build/es5/stores/memory.js +22 -0
- package/build/es5/utils.js +54 -0
- package/build/es5/utm-personalize.js +817 -0
- package/build/es5/utm.js +304 -0
- package/build/lua.dev.js +1574 -0
- package/build/lua.es.js +1566 -0
- package/build/lua.js +1574 -0
- package/build/lua.min.js +8 -0
- package/package.json +68 -0
|
@@ -0,0 +1,817 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
5
|
+
/**
|
|
6
|
+
* Lua UTM Personalization - Standalone Bundle
|
|
7
|
+
* ============================================
|
|
8
|
+
* Self-contained script combining:
|
|
9
|
+
* - URLSearchParams-based UTM extraction
|
|
10
|
+
* - Referrer & user agent detection
|
|
11
|
+
* - Intent inference engine
|
|
12
|
+
* - DOMPurify-style HTML sanitizer
|
|
13
|
+
* - DOM personalization via data-personalize attributes
|
|
14
|
+
* - Random A/B test fallback when no UTM params present
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* <script src="utm-personalize.js" defer></script>
|
|
18
|
+
*
|
|
19
|
+
* <!-- Then in your HTML use data-personalize attributes: -->
|
|
20
|
+
* <div data-personalize="hero">
|
|
21
|
+
* <h1 data-personalize="headline">Default Headline</h1>
|
|
22
|
+
* <p data-personalize="subheadline">Default subheadline</p>
|
|
23
|
+
* <a href="#" data-personalize="ctaLink">
|
|
24
|
+
* <span data-personalize="ctaLabel">Default CTA</span>
|
|
25
|
+
* </a>
|
|
26
|
+
* </div>
|
|
27
|
+
*
|
|
28
|
+
* The script auto-initializes on DOMContentLoaded.
|
|
29
|
+
* Access the API via window.LuaUTMPersonalize
|
|
30
|
+
*
|
|
31
|
+
* Size target: < 50KB
|
|
32
|
+
* No imports. No dependencies. No build step required.
|
|
33
|
+
*/
|
|
34
|
+
;
|
|
35
|
+
(function (root) {
|
|
36
|
+
'use strict';
|
|
37
|
+
|
|
38
|
+
// ===================================================================
|
|
39
|
+
// 1. UTM PARAMETER EXTRACTION (URLSearchParams API)
|
|
40
|
+
// ===================================================================
|
|
41
|
+
var UTM_TIMEOUT_MS = 1000;
|
|
42
|
+
var UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
|
|
43
|
+
var REFERRER_PATTERNS = {
|
|
44
|
+
google: /google\./i,
|
|
45
|
+
bing: /bing\./i,
|
|
46
|
+
yahoo: /yahoo\./i,
|
|
47
|
+
duckduckgo: /duckduckgo\./i,
|
|
48
|
+
facebook: /facebook\.com|fb\.com/i,
|
|
49
|
+
twitter: /twitter\.com|t\.co|x\.com/i,
|
|
50
|
+
instagram: /instagram\.com/i,
|
|
51
|
+
linkedin: /linkedin\.com/i,
|
|
52
|
+
pinterest: /pinterest\./i,
|
|
53
|
+
tiktok: /tiktok\.com/i,
|
|
54
|
+
youtube: /youtube\.com|youtu\.be/i,
|
|
55
|
+
reddit: /reddit\.com/i
|
|
56
|
+
};
|
|
57
|
+
var REFERRER_CATEGORIES = {
|
|
58
|
+
search: ['google', 'bing', 'yahoo', 'duckduckgo'],
|
|
59
|
+
social: ['facebook', 'twitter', 'instagram', 'linkedin', 'pinterest', 'tiktok', 'youtube', 'reddit']
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Sanitize a UTM parameter value to prevent XSS
|
|
64
|
+
* @param {string} value - Raw parameter value
|
|
65
|
+
* @returns {string} - Sanitized value
|
|
66
|
+
*/
|
|
67
|
+
function sanitizeParam(value) {
|
|
68
|
+
if (typeof value !== 'string') return '';
|
|
69
|
+
return value.replace(/<[^>]*>/g, '').replace(/[^\w\s\-_.]/g, '').substring(0, 100).trim();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Extract UTM parameters from URL using native URLSearchParams API
|
|
74
|
+
* @param {string} [url] - URL search string (defaults to window.location.search)
|
|
75
|
+
* @returns {Object} - Object containing UTM parameters
|
|
76
|
+
*/
|
|
77
|
+
function extractUTMParams(url) {
|
|
78
|
+
var result = {};
|
|
79
|
+
try {
|
|
80
|
+
var searchString = url || (typeof root.location !== 'undefined' ? root.location.search : '');
|
|
81
|
+
if (!searchString) return result;
|
|
82
|
+
var params = new URLSearchParams(searchString);
|
|
83
|
+
UTM_PARAMS.forEach(function (param) {
|
|
84
|
+
var value = params.get(param);
|
|
85
|
+
if (value) {
|
|
86
|
+
result[param] = sanitizeParam(value);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.warn('[Lua UTM] Error extracting UTM params:', e);
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Detect referrer type from document.referrer
|
|
97
|
+
* @returns {Object} - { source, category, url }
|
|
98
|
+
*/
|
|
99
|
+
function detectReferrer() {
|
|
100
|
+
var result = {
|
|
101
|
+
source: 'direct',
|
|
102
|
+
category: 'direct',
|
|
103
|
+
url: ''
|
|
104
|
+
};
|
|
105
|
+
try {
|
|
106
|
+
if (typeof document === 'undefined' || !document.referrer) return result;
|
|
107
|
+
result.url = document.referrer;
|
|
108
|
+
if (/mail\.|email\.|newsletter/i.test(document.referrer)) {
|
|
109
|
+
result.source = 'email';
|
|
110
|
+
result.category = 'email';
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
for (var source in REFERRER_PATTERNS) {
|
|
114
|
+
if (REFERRER_PATTERNS[source].test(document.referrer)) {
|
|
115
|
+
result.source = source;
|
|
116
|
+
for (var category in REFERRER_CATEGORIES) {
|
|
117
|
+
if (REFERRER_CATEGORIES[category].indexOf(source) !== -1) {
|
|
118
|
+
result.category = category;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
result.source = 'external';
|
|
126
|
+
result.category = 'other';
|
|
127
|
+
} catch (e) {
|
|
128
|
+
console.warn('[Lua UTM] Error detecting referrer:', e);
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get user agent info for device detection
|
|
135
|
+
* @returns {Object} - { raw, isMobile, isTablet, isDesktop }
|
|
136
|
+
*/
|
|
137
|
+
function getUserAgentInfo() {
|
|
138
|
+
var result = {
|
|
139
|
+
raw: '',
|
|
140
|
+
isMobile: false,
|
|
141
|
+
isTablet: false,
|
|
142
|
+
isDesktop: true
|
|
143
|
+
};
|
|
144
|
+
try {
|
|
145
|
+
if (typeof navigator === 'undefined' || !navigator.userAgent) return result;
|
|
146
|
+
result.raw = navigator.userAgent;
|
|
147
|
+
result.isMobile = /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
148
|
+
result.isTablet = /iPad|Android(?!.*Mobile)/i.test(navigator.userAgent);
|
|
149
|
+
result.isDesktop = !result.isMobile && !result.isTablet;
|
|
150
|
+
} catch (e) {
|
|
151
|
+
console.warn('[Lua UTM] Error getting user agent:', e);
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Infer user intent from context
|
|
158
|
+
* Priority: UTM campaign > UTM source > Referrer category
|
|
159
|
+
* @param {Object} context - Full context object
|
|
160
|
+
* @returns {string} - Inferred intent key
|
|
161
|
+
*/
|
|
162
|
+
function inferIntent(context) {
|
|
163
|
+
if (context.utm.utm_campaign) {
|
|
164
|
+
var campaign = context.utm.utm_campaign.toLowerCase();
|
|
165
|
+
if (/sale|discount|offer|promo/i.test(campaign)) return 'price-focused';
|
|
166
|
+
if (/gaming|game|esport/i.test(campaign)) return 'gaming';
|
|
167
|
+
if (/work|office|professional|productivity/i.test(campaign)) return 'professional';
|
|
168
|
+
if (/creative|design|art|studio/i.test(campaign)) return 'creative';
|
|
169
|
+
if (/brand|story|about/i.test(campaign)) return 'brand-story';
|
|
170
|
+
}
|
|
171
|
+
if (context.utm.utm_source) {
|
|
172
|
+
var source = context.utm.utm_source.toLowerCase();
|
|
173
|
+
if (/google|bing|yahoo/i.test(source)) return 'search-optimized';
|
|
174
|
+
if (/facebook|instagram|tiktok/i.test(source)) return 'social-visual';
|
|
175
|
+
if (/twitter|x$/i.test(source)) return 'social-brief';
|
|
176
|
+
if (/email|newsletter/i.test(source)) return 'returning-user';
|
|
177
|
+
if (/youtube/i.test(source)) return 'video-engaged';
|
|
178
|
+
}
|
|
179
|
+
if (context.referrer.category === 'search') return 'search-optimized';
|
|
180
|
+
if (context.referrer.category === 'social') return 'social-visual';
|
|
181
|
+
if (context.referrer.category === 'email') return 'returning-user';
|
|
182
|
+
return 'default';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Build full personalization context
|
|
187
|
+
* @param {Object} [options] - { url: string }
|
|
188
|
+
* @returns {Object} - Complete context object
|
|
189
|
+
*/
|
|
190
|
+
function getContext(options) {
|
|
191
|
+
options = options || {};
|
|
192
|
+
var context = {
|
|
193
|
+
utm: extractUTMParams(options.url),
|
|
194
|
+
referrer: detectReferrer(),
|
|
195
|
+
userAgent: getUserAgentInfo(),
|
|
196
|
+
timestamp: Date.now(),
|
|
197
|
+
hasUTM: false,
|
|
198
|
+
primaryIntent: 'unknown'
|
|
199
|
+
};
|
|
200
|
+
context.hasUTM = Object.keys(context.utm).length > 0;
|
|
201
|
+
context.primaryIntent = inferIntent(context);
|
|
202
|
+
return context;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Async context with timeout fallback (1 second max)
|
|
207
|
+
* @param {Object} [options] - { timeout: number, url: string }
|
|
208
|
+
* @returns {Promise<Object>} - Context object
|
|
209
|
+
*/
|
|
210
|
+
function getContextAsync(options) {
|
|
211
|
+
options = options || {};
|
|
212
|
+
var timeout = options.timeout || UTM_TIMEOUT_MS;
|
|
213
|
+
return new Promise(function (resolve) {
|
|
214
|
+
var timer = setTimeout(function () {
|
|
215
|
+
resolve({
|
|
216
|
+
utm: {},
|
|
217
|
+
referrer: {
|
|
218
|
+
source: 'direct',
|
|
219
|
+
category: 'direct',
|
|
220
|
+
url: ''
|
|
221
|
+
},
|
|
222
|
+
userAgent: {
|
|
223
|
+
raw: '',
|
|
224
|
+
isMobile: false,
|
|
225
|
+
isTablet: false,
|
|
226
|
+
isDesktop: true
|
|
227
|
+
},
|
|
228
|
+
timestamp: Date.now(),
|
|
229
|
+
hasUTM: false,
|
|
230
|
+
primaryIntent: 'default',
|
|
231
|
+
timedOut: true
|
|
232
|
+
});
|
|
233
|
+
}, timeout);
|
|
234
|
+
try {
|
|
235
|
+
var context = getContext(options);
|
|
236
|
+
clearTimeout(timer);
|
|
237
|
+
context.timedOut = false;
|
|
238
|
+
resolve(context);
|
|
239
|
+
} catch (e) {
|
|
240
|
+
clearTimeout(timer);
|
|
241
|
+
resolve({
|
|
242
|
+
utm: {},
|
|
243
|
+
referrer: {
|
|
244
|
+
source: 'direct',
|
|
245
|
+
category: 'direct',
|
|
246
|
+
url: ''
|
|
247
|
+
},
|
|
248
|
+
userAgent: {
|
|
249
|
+
raw: '',
|
|
250
|
+
isMobile: false,
|
|
251
|
+
isTablet: false,
|
|
252
|
+
isDesktop: true
|
|
253
|
+
},
|
|
254
|
+
timestamp: Date.now(),
|
|
255
|
+
hasUTM: false,
|
|
256
|
+
primaryIntent: 'default',
|
|
257
|
+
error: e.message
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// ===================================================================
|
|
264
|
+
// 2. DOMPURIFY-STYLE HTML SANITIZER
|
|
265
|
+
// ===================================================================
|
|
266
|
+
|
|
267
|
+
var Sanitizer = function () {
|
|
268
|
+
var ALLOWED_TAGS = {
|
|
269
|
+
'p': true,
|
|
270
|
+
'span': true,
|
|
271
|
+
'strong': true,
|
|
272
|
+
'em': true,
|
|
273
|
+
'b': true,
|
|
274
|
+
'i': true,
|
|
275
|
+
'br': true,
|
|
276
|
+
'a': true,
|
|
277
|
+
'img': true,
|
|
278
|
+
'h1': true,
|
|
279
|
+
'h2': true,
|
|
280
|
+
'h3': true,
|
|
281
|
+
'h4': true,
|
|
282
|
+
'h5': true,
|
|
283
|
+
'h6': true,
|
|
284
|
+
'div': true,
|
|
285
|
+
'section': true,
|
|
286
|
+
'ul': true,
|
|
287
|
+
'ol': true,
|
|
288
|
+
'li': true,
|
|
289
|
+
'blockquote': true,
|
|
290
|
+
'figure': true,
|
|
291
|
+
'figcaption': true
|
|
292
|
+
};
|
|
293
|
+
var ALLOWED_ATTRS = {
|
|
294
|
+
'href': true,
|
|
295
|
+
'src': true,
|
|
296
|
+
'alt': true,
|
|
297
|
+
'class': true,
|
|
298
|
+
'id': true,
|
|
299
|
+
'title': true,
|
|
300
|
+
'target': true,
|
|
301
|
+
'rel': true,
|
|
302
|
+
'width': true,
|
|
303
|
+
'height': true,
|
|
304
|
+
'loading': true
|
|
305
|
+
};
|
|
306
|
+
var DANGEROUS_URI = /^(javascript|vbscript|data):/i;
|
|
307
|
+
var EVENT_HANDLER = /^on/i;
|
|
308
|
+
function hasDOMParser() {
|
|
309
|
+
try {
|
|
310
|
+
return typeof DOMParser !== 'undefined' && new DOMParser();
|
|
311
|
+
} catch (e) {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function escapeText(text) {
|
|
316
|
+
if (!text) return '';
|
|
317
|
+
return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
318
|
+
}
|
|
319
|
+
function escapeAttr(value) {
|
|
320
|
+
if (!value) return '';
|
|
321
|
+
return value.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>');
|
|
322
|
+
}
|
|
323
|
+
function cleanAttributes(element) {
|
|
324
|
+
var attrStr = '';
|
|
325
|
+
var attrs = element.attributes;
|
|
326
|
+
for (var i = 0; i < attrs.length; i++) {
|
|
327
|
+
var name = attrs[i].name.toLowerCase();
|
|
328
|
+
var value = attrs[i].value;
|
|
329
|
+
if (EVENT_HANDLER.test(name)) continue;
|
|
330
|
+
if (!ALLOWED_ATTRS[name]) continue;
|
|
331
|
+
if ((name === 'href' || name === 'src') && DANGEROUS_URI.test(value.trim())) continue;
|
|
332
|
+
if (name === 'target' && value === '_blank') {
|
|
333
|
+
attrStr += ' target="_blank" rel="noopener noreferrer"';
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
attrStr += ' ' + name + '="' + escapeAttr(value) + '"';
|
|
337
|
+
}
|
|
338
|
+
return attrStr;
|
|
339
|
+
}
|
|
340
|
+
function walkAndClean(node) {
|
|
341
|
+
var output = '';
|
|
342
|
+
for (var i = 0; i < node.childNodes.length; i++) {
|
|
343
|
+
var child = node.childNodes[i];
|
|
344
|
+
if (child.nodeType === 3) {
|
|
345
|
+
output += escapeText(child.textContent);
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
if (child.nodeType === 1) {
|
|
349
|
+
var tag = child.tagName.toLowerCase();
|
|
350
|
+
if (tag === 'script' || tag === 'style' || tag === 'iframe' || tag === 'object' || tag === 'embed' || tag === 'form' || tag === 'input' || tag === 'textarea') continue;
|
|
351
|
+
if (ALLOWED_TAGS[tag]) {
|
|
352
|
+
output += '<' + tag + cleanAttributes(child) + '>';
|
|
353
|
+
if (tag !== 'br' && tag !== 'img') {
|
|
354
|
+
output += walkAndClean(child);
|
|
355
|
+
output += '</' + tag + '>';
|
|
356
|
+
}
|
|
357
|
+
} else {
|
|
358
|
+
output += walkAndClean(child);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return output;
|
|
363
|
+
}
|
|
364
|
+
function sanitizeWithDOMParser(dirty) {
|
|
365
|
+
try {
|
|
366
|
+
var doc = new DOMParser().parseFromString(dirty, 'text/html');
|
|
367
|
+
return doc.body ? walkAndClean(doc.body) : '';
|
|
368
|
+
} catch (e) {
|
|
369
|
+
return sanitizeWithRegex(dirty);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function sanitizeWithRegex(html) {
|
|
373
|
+
var 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];
|
|
374
|
+
var sanitized = html;
|
|
375
|
+
patterns.forEach(function (p) {
|
|
376
|
+
sanitized = sanitized.replace(p, '');
|
|
377
|
+
});
|
|
378
|
+
sanitized = sanitized.replace(/<\/?(\w+)([^>]*)>/g, function (match, tagName, attrs) {
|
|
379
|
+
var tag = tagName.toLowerCase();
|
|
380
|
+
if (!ALLOWED_TAGS[tag]) return '';
|
|
381
|
+
if (match.charAt(1) === '/') return '</' + tag + '>';
|
|
382
|
+
var cleanAttrs = '';
|
|
383
|
+
var re = /(\w+)=['"]([^'"]*)['"]/g;
|
|
384
|
+
var m;
|
|
385
|
+
while ((m = re.exec(attrs)) !== null) {
|
|
386
|
+
var n = m[1].toLowerCase();
|
|
387
|
+
if (ALLOWED_ATTRS[n] && !EVENT_HANDLER.test(n)) {
|
|
388
|
+
if ((n === 'href' || n === 'src') && DANGEROUS_URI.test(m[2])) continue;
|
|
389
|
+
cleanAttrs += ' ' + n + '="' + m[2] + '"';
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return '<' + tag + cleanAttrs + '>';
|
|
393
|
+
});
|
|
394
|
+
return sanitized;
|
|
395
|
+
}
|
|
396
|
+
return {
|
|
397
|
+
sanitize: function sanitize(dirty) {
|
|
398
|
+
if (typeof dirty !== 'string' || !dirty.trim()) return '';
|
|
399
|
+
return hasDOMParser() ? sanitizeWithDOMParser(dirty) : sanitizeWithRegex(dirty);
|
|
400
|
+
},
|
|
401
|
+
escapeText: escapeText,
|
|
402
|
+
escapeAttr: escapeAttr
|
|
403
|
+
};
|
|
404
|
+
}();
|
|
405
|
+
|
|
406
|
+
// ===================================================================
|
|
407
|
+
// 3. TEMPLATES & ASSETS
|
|
408
|
+
// ===================================================================
|
|
409
|
+
// NOTE: Templates are NOT provided by this package.
|
|
410
|
+
// Users must provide their own templates via options.templates
|
|
411
|
+
// This keeps the package modular and allows users full control
|
|
412
|
+
// over their content, assets, and personalization strategy.
|
|
413
|
+
|
|
414
|
+
// ===================================================================
|
|
415
|
+
// 4. DOM PERSONALIZATION ENGINE
|
|
416
|
+
// ===================================================================
|
|
417
|
+
|
|
418
|
+
function safeSetText(element, text) {
|
|
419
|
+
if (!element) return;
|
|
420
|
+
element.textContent = text;
|
|
421
|
+
}
|
|
422
|
+
function safeSetHTML(element, html) {
|
|
423
|
+
if (!element) return;
|
|
424
|
+
element.innerHTML = Sanitizer.sanitize(html);
|
|
425
|
+
}
|
|
426
|
+
function findPersonalizeElements(key, searchRoot) {
|
|
427
|
+
searchRoot = searchRoot || (typeof document !== 'undefined' ? document : null);
|
|
428
|
+
if (!searchRoot) return [];
|
|
429
|
+
var selector = key ? '[data-personalize="' + key + '"]' : '[data-personalize]';
|
|
430
|
+
return searchRoot.querySelectorAll(selector);
|
|
431
|
+
}
|
|
432
|
+
function getTemplate(intent, userTemplates) {
|
|
433
|
+
if (!userTemplates || (0, _typeof2.default)(userTemplates) !== 'object') {
|
|
434
|
+
console.warn('[Lua Personalize] No templates provided. Templates must be passed via options.templates');
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
437
|
+
if (userTemplates[intent]) return userTemplates[intent];
|
|
438
|
+
if (userTemplates['default']) return userTemplates['default'];
|
|
439
|
+
var firstKey = Object.keys(userTemplates)[0];
|
|
440
|
+
if (firstKey) {
|
|
441
|
+
console.warn('[Lua Personalize] Intent "' + intent + '" not found, using first available template:', firstKey);
|
|
442
|
+
return userTemplates[firstKey];
|
|
443
|
+
}
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// ===================================================================
|
|
448
|
+
// 5. RANDOM A/B FALLBACK
|
|
449
|
+
// ===================================================================
|
|
450
|
+
|
|
451
|
+
function chooseWeightedRandom(names, weights) {
|
|
452
|
+
if (names.length !== weights.length) return names[0];
|
|
453
|
+
var sum = 0;
|
|
454
|
+
var i;
|
|
455
|
+
for (i = 0; i < weights.length; i++) {
|
|
456
|
+
sum += weights[i];
|
|
457
|
+
}
|
|
458
|
+
var n = Math.random() * sum;
|
|
459
|
+
var limit = 0;
|
|
460
|
+
for (i = 0; i < names.length; i++) {
|
|
461
|
+
limit += weights[i];
|
|
462
|
+
if (n <= limit) return names[i];
|
|
463
|
+
}
|
|
464
|
+
return names[names.length - 1];
|
|
465
|
+
}
|
|
466
|
+
function getRandomFallbackIntent(userTemplates) {
|
|
467
|
+
if (!userTemplates || (0, _typeof2.default)(userTemplates) !== 'object') return null;
|
|
468
|
+
var names = Object.keys(userTemplates);
|
|
469
|
+
if (names.length === 0) return null;
|
|
470
|
+
var weights = [];
|
|
471
|
+
for (var i = 0; i < names.length; i++) {
|
|
472
|
+
weights.push(1);
|
|
473
|
+
}
|
|
474
|
+
return chooseWeightedRandom(names, weights);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// ===================================================================
|
|
478
|
+
// 6. DECISION ENGINE
|
|
479
|
+
// ===================================================================
|
|
480
|
+
|
|
481
|
+
var DecisionEngine = {
|
|
482
|
+
/**
|
|
483
|
+
* Standard (non-AI) decision logic
|
|
484
|
+
* Priority: Custom rules > UTM params > Referrer > Random A/B
|
|
485
|
+
*/
|
|
486
|
+
standardDecide: function standardDecide(context, options) {
|
|
487
|
+
options = options || {};
|
|
488
|
+
var customRules = options.rules || {};
|
|
489
|
+
var userTemplates = options.templates;
|
|
490
|
+
var enableRandomFallback = options.randomFallback !== false;
|
|
491
|
+
if (!userTemplates || (0, _typeof2.default)(userTemplates) !== 'object' || Object.keys(userTemplates).length === 0) {
|
|
492
|
+
console.warn('[Lua Personalize] No templates provided. Templates must be passed via options.templates');
|
|
493
|
+
return {
|
|
494
|
+
template: null,
|
|
495
|
+
intent: 'default',
|
|
496
|
+
source: 'error',
|
|
497
|
+
context: context,
|
|
498
|
+
error: 'No templates provided'
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
var intent = context.primaryIntent;
|
|
502
|
+
var source = 'default';
|
|
503
|
+
if (context.hasUTM) {
|
|
504
|
+
source = 'utm';
|
|
505
|
+
} else if (context.referrer && context.referrer.category !== 'direct') {
|
|
506
|
+
source = 'referrer';
|
|
507
|
+
}
|
|
508
|
+
for (var ruleKey in customRules) {
|
|
509
|
+
var rule = customRules[ruleKey];
|
|
510
|
+
if (typeof rule.match === 'function' && rule.match(context)) {
|
|
511
|
+
intent = rule.intent || ruleKey;
|
|
512
|
+
source = 'custom-rule';
|
|
513
|
+
break;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
if (intent === 'default' && source === 'default' && enableRandomFallback) {
|
|
517
|
+
var randomIntent = getRandomFallbackIntent(userTemplates);
|
|
518
|
+
if (randomIntent) {
|
|
519
|
+
intent = randomIntent;
|
|
520
|
+
source = 'random-ab';
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Record visit to history if available
|
|
525
|
+
if (root.LuaWeightedHistory && typeof root.LuaWeightedHistory.recordVisit === 'function') {
|
|
526
|
+
root.LuaWeightedHistory.recordVisit({
|
|
527
|
+
context: context,
|
|
528
|
+
intent: intent,
|
|
529
|
+
selectedVariant: intent,
|
|
530
|
+
source: source,
|
|
531
|
+
aiDecision: false
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
return {
|
|
535
|
+
template: getTemplate(intent, userTemplates),
|
|
536
|
+
intent: intent,
|
|
537
|
+
source: source,
|
|
538
|
+
context: context
|
|
539
|
+
};
|
|
540
|
+
},
|
|
541
|
+
/**
|
|
542
|
+
* Main decide function - routes to AI or standard engine
|
|
543
|
+
* @param {Object} context - UTM context
|
|
544
|
+
* @param {Object} [options] - Configuration options
|
|
545
|
+
* @param {boolean} [options.enableAI] - Enable AI-powered decisions
|
|
546
|
+
* @param {Object} [options.aiConfig] - AI configuration
|
|
547
|
+
* @returns {Object|Promise<Object>} - Decision result
|
|
548
|
+
*/
|
|
549
|
+
decide: function decide(context, options) {
|
|
550
|
+
options = options || {};
|
|
551
|
+
|
|
552
|
+
// If AI is enabled and configured, try AI decision first
|
|
553
|
+
if (options.enableAI && options.aiConfig && root.LuaAIPersonalize) {
|
|
554
|
+
var self = this;
|
|
555
|
+
var aiModule = root.LuaAIPersonalize;
|
|
556
|
+
var readiness = aiModule.isReady(options.aiConfig);
|
|
557
|
+
if (readiness.ready) {
|
|
558
|
+
return aiModule.decide(context, options).catch(function (error) {
|
|
559
|
+
var fallback = options.aiConfig.fallbackToStandard !== false;
|
|
560
|
+
if (fallback) {
|
|
561
|
+
console.warn('[Lua Personalize] AI failed, using standard engine:', error.message);
|
|
562
|
+
return self.standardDecide(context, options);
|
|
563
|
+
}
|
|
564
|
+
throw error;
|
|
565
|
+
});
|
|
566
|
+
} else {
|
|
567
|
+
console.warn('[Lua Personalize] AI not ready:', readiness.error, '- using standard engine');
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return this.standardDecide(context, options);
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
// ===================================================================
|
|
575
|
+
// 7. DOM APPLICATION (extracted for reuse)
|
|
576
|
+
// ===================================================================
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Apply a decision to the DOM
|
|
580
|
+
* @param {Object} decision - Decision object { template, intent, source, context }
|
|
581
|
+
* @param {Object} [options] - Configuration options
|
|
582
|
+
* @returns {Object} - The decision (pass-through)
|
|
583
|
+
*/
|
|
584
|
+
function applyDecisionToDOM(decision, options) {
|
|
585
|
+
options = options || {};
|
|
586
|
+
var template = decision.template;
|
|
587
|
+
var context = decision.context || {};
|
|
588
|
+
var log = options.log !== false;
|
|
589
|
+
if (!template) {
|
|
590
|
+
console.warn('[Lua Personalize] No template in decision, skipping DOM update');
|
|
591
|
+
return decision;
|
|
592
|
+
}
|
|
593
|
+
var slots = ['image', 'headline', 'subheadline', 'ctaLabel', 'ctaLink'];
|
|
594
|
+
slots.forEach(function (slot) {
|
|
595
|
+
var elements = findPersonalizeElements(slot);
|
|
596
|
+
for (var i = 0; i < elements.length; i++) {
|
|
597
|
+
var el = elements[i];
|
|
598
|
+
var value = template[slot];
|
|
599
|
+
if (!value) continue;
|
|
600
|
+
if (slot === 'image') {
|
|
601
|
+
if (el.tagName === 'IMG') {
|
|
602
|
+
el.src = value;
|
|
603
|
+
el.alt = template.headline || 'Personalized image';
|
|
604
|
+
} else {
|
|
605
|
+
el.style.backgroundImage = 'url(' + value + ')';
|
|
606
|
+
}
|
|
607
|
+
} else if (slot === 'ctaLink') {
|
|
608
|
+
el.href = value;
|
|
609
|
+
} else {
|
|
610
|
+
safeSetText(el, value);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
// Apply to data-personalize="hero" elements
|
|
616
|
+
var heroElements = findPersonalizeElements('hero');
|
|
617
|
+
for (var h = 0; h < heroElements.length; h++) {
|
|
618
|
+
var heroEl = heroElements[h];
|
|
619
|
+
heroEl.setAttribute('data-intent', decision.intent);
|
|
620
|
+
heroEl.setAttribute('data-source', decision.source);
|
|
621
|
+
if (template.image && !heroEl.querySelector('[data-personalize="image"]')) {
|
|
622
|
+
heroEl.style.backgroundImage = 'url(' + template.image + ')';
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
if (log && typeof console !== 'undefined') {
|
|
626
|
+
console.log('[Lua Personalize] Applied:', {
|
|
627
|
+
intent: decision.intent,
|
|
628
|
+
source: decision.source,
|
|
629
|
+
headline: template.headline,
|
|
630
|
+
hasUTM: context.hasUTM,
|
|
631
|
+
utmParams: context.utm || {},
|
|
632
|
+
aiPowered: decision.source === 'ai' || decision.source === 'ai-cached'
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
return decision;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// ===================================================================
|
|
639
|
+
// 8. MAIN PERSONALIZATION FUNCTION
|
|
640
|
+
// ===================================================================
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Apply personalization to the page
|
|
644
|
+
* Scans for data-personalize attributes and injects content
|
|
645
|
+
* Supports AI-powered decisions when enableAI is true
|
|
646
|
+
*
|
|
647
|
+
* @param {Object} [options] - Configuration
|
|
648
|
+
* @param {Object} [options.context] - Pre-computed context
|
|
649
|
+
* @param {Object} [options.rules] - Custom rules
|
|
650
|
+
* @param {Object} options.templates - User-provided templates (REQUIRED)
|
|
651
|
+
* @param {boolean} [options.enableAI] - Enable AI-powered decisions
|
|
652
|
+
* @param {Object} [options.aiConfig] - AI configuration
|
|
653
|
+
* @param {boolean} [options.randomFallback] - Enable random A/B (default: true)
|
|
654
|
+
* @param {boolean} [options.log] - Enable logging (default: true)
|
|
655
|
+
* @returns {Object|Promise<Object>} - Decision result (Promise if AI enabled)
|
|
656
|
+
*/
|
|
657
|
+
function personalize(options) {
|
|
658
|
+
options = options || {};
|
|
659
|
+
|
|
660
|
+
// Templates are required
|
|
661
|
+
if (!options.templates || (0, _typeof2.default)(options.templates) !== 'object' || Object.keys(options.templates).length === 0) {
|
|
662
|
+
console.error('[Lua Personalize] Templates are required. Provide templates via options.templates');
|
|
663
|
+
return {
|
|
664
|
+
template: null,
|
|
665
|
+
intent: 'default',
|
|
666
|
+
source: 'error',
|
|
667
|
+
context: {},
|
|
668
|
+
error: 'No templates provided'
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
var context = options.context || getContext(options);
|
|
672
|
+
var decision = DecisionEngine.decide(context, options);
|
|
673
|
+
|
|
674
|
+
// If decision is a Promise (AI path), handle async
|
|
675
|
+
if (decision && typeof decision.then === 'function') {
|
|
676
|
+
return decision.then(function (aiDecision) {
|
|
677
|
+
return applyDecisionToDOM(aiDecision, options);
|
|
678
|
+
}).catch(function (err) {
|
|
679
|
+
console.warn('[Lua Personalize] AI decision failed, using standard:', err.message);
|
|
680
|
+
var fallbackDecision = DecisionEngine.standardDecide(context, options);
|
|
681
|
+
return applyDecisionToDOM(fallbackDecision, options);
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// Synchronous path
|
|
686
|
+
return applyDecisionToDOM(decision, options);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* Async personalization with timeout fallback
|
|
691
|
+
* Automatically handles AI decisions (which are always async)
|
|
692
|
+
*/
|
|
693
|
+
function personalizeAsync(options) {
|
|
694
|
+
options = options || {};
|
|
695
|
+
return getContextAsync(options).then(function (context) {
|
|
696
|
+
options.context = context;
|
|
697
|
+
return personalize(options);
|
|
698
|
+
}).then(function (decision) {
|
|
699
|
+
return decision;
|
|
700
|
+
}).catch(function (err) {
|
|
701
|
+
console.warn('[Lua Personalize] Async error, using default:', err);
|
|
702
|
+
var ctx = getContext(options);
|
|
703
|
+
var fallback = DecisionEngine.standardDecide(ctx, {
|
|
704
|
+
templates: options.templates
|
|
705
|
+
});
|
|
706
|
+
return applyDecisionToDOM(fallback, options);
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// ===================================================================
|
|
711
|
+
// 9. AUTO-INITIALIZATION
|
|
712
|
+
// ===================================================================
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Auto-initialize personalization on DOMContentLoaded
|
|
716
|
+
* Only runs if data-personalize elements exist in the DOM
|
|
717
|
+
*/
|
|
718
|
+
function autoInit(options) {
|
|
719
|
+
options = options || {};
|
|
720
|
+
function run() {
|
|
721
|
+
var elements = findPersonalizeElements();
|
|
722
|
+
if (elements.length > 0) {
|
|
723
|
+
personalize(options);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
if (typeof document !== 'undefined') {
|
|
727
|
+
if (document.readyState === 'loading') {
|
|
728
|
+
document.addEventListener('DOMContentLoaded', run);
|
|
729
|
+
} else {
|
|
730
|
+
run();
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// ===================================================================
|
|
736
|
+
// 10. PUBLIC API
|
|
737
|
+
// ===================================================================
|
|
738
|
+
|
|
739
|
+
var LuaUTMPersonalize = {
|
|
740
|
+
// UTM extraction
|
|
741
|
+
extractUTMParams: extractUTMParams,
|
|
742
|
+
sanitizeParam: sanitizeParam,
|
|
743
|
+
detectReferrer: detectReferrer,
|
|
744
|
+
getUserAgentInfo: getUserAgentInfo,
|
|
745
|
+
getContext: getContext,
|
|
746
|
+
getContextAsync: getContextAsync,
|
|
747
|
+
inferIntent: inferIntent,
|
|
748
|
+
// Sanitizer
|
|
749
|
+
sanitizer: Sanitizer,
|
|
750
|
+
sanitizeHTML: function sanitizeHTML(html) {
|
|
751
|
+
return Sanitizer.sanitize(html);
|
|
752
|
+
},
|
|
753
|
+
// DOM helpers
|
|
754
|
+
safeSetText: safeSetText,
|
|
755
|
+
safeSetHTML: safeSetHTML,
|
|
756
|
+
findElements: findPersonalizeElements,
|
|
757
|
+
applyDecisionToDOM: applyDecisionToDOM,
|
|
758
|
+
// Templates (users must provide their own via options.templates)
|
|
759
|
+
getTemplate: getTemplate,
|
|
760
|
+
// Decision engine
|
|
761
|
+
engine: DecisionEngine,
|
|
762
|
+
chooseWeightedRandom: chooseWeightedRandom,
|
|
763
|
+
getRandomFallbackIntent: getRandomFallbackIntent,
|
|
764
|
+
// Main API
|
|
765
|
+
personalize: personalize,
|
|
766
|
+
personalizeAsync: personalizeAsync,
|
|
767
|
+
autoInit: autoInit,
|
|
768
|
+
// Constants
|
|
769
|
+
UTM_PARAMS: UTM_PARAMS,
|
|
770
|
+
UTM_TIMEOUT_MS: UTM_TIMEOUT_MS,
|
|
771
|
+
REFERRER_PATTERNS: REFERRER_PATTERNS,
|
|
772
|
+
REFERRER_CATEGORIES: REFERRER_CATEGORIES
|
|
773
|
+
};
|
|
774
|
+
|
|
775
|
+
// Register globally
|
|
776
|
+
root.LuaUTMPersonalize = LuaUTMPersonalize;
|
|
777
|
+
|
|
778
|
+
// Also register individual modules for compatibility
|
|
779
|
+
if (!root.LuaUTM) {
|
|
780
|
+
root.LuaUTM = {
|
|
781
|
+
extractUTMParams: extractUTMParams,
|
|
782
|
+
sanitizeParam: sanitizeParam,
|
|
783
|
+
detectReferrer: detectReferrer,
|
|
784
|
+
getUserAgentInfo: getUserAgentInfo,
|
|
785
|
+
getContext: getContext,
|
|
786
|
+
getContextAsync: getContextAsync,
|
|
787
|
+
inferIntent: inferIntent,
|
|
788
|
+
UTM_PARAMS: UTM_PARAMS,
|
|
789
|
+
UTM_TIMEOUT_MS: UTM_TIMEOUT_MS,
|
|
790
|
+
REFERRER_PATTERNS: REFERRER_PATTERNS,
|
|
791
|
+
REFERRER_CATEGORIES: REFERRER_CATEGORIES
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
if (!root.LuaPersonalize) {
|
|
795
|
+
root.LuaPersonalize = {
|
|
796
|
+
sanitizer: Sanitizer,
|
|
797
|
+
sanitizeHTML: function sanitizeHTML(html) {
|
|
798
|
+
return Sanitizer.sanitize(html);
|
|
799
|
+
},
|
|
800
|
+
safeSetText: safeSetText,
|
|
801
|
+
safeSetHTML: safeSetHTML,
|
|
802
|
+
findElements: findPersonalizeElements,
|
|
803
|
+
applyDecisionToDOM: applyDecisionToDOM,
|
|
804
|
+
getTemplate: getTemplate,
|
|
805
|
+
engine: DecisionEngine,
|
|
806
|
+
personalize: personalize,
|
|
807
|
+
personalizeAsync: personalizeAsync,
|
|
808
|
+
autoInit: autoInit,
|
|
809
|
+
chooseWeightedRandom: chooseWeightedRandom,
|
|
810
|
+
getRandomFallbackIntent: getRandomFallbackIntent
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// Note: autoInit() is NOT called automatically because templates are required
|
|
815
|
+
// Users must call personalize() or personalizeAsync() with their templates
|
|
816
|
+
})(typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : void 0);
|
|
817
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJyb290IiwiVVRNX1RJTUVPVVRfTVMiLCJVVE1fUEFSQU1TIiwiUkVGRVJSRVJfUEFUVEVSTlMiLCJnb29nbGUiLCJiaW5nIiwieWFob28iLCJkdWNrZHVja2dvIiwiZmFjZWJvb2siLCJ0d2l0dGVyIiwiaW5zdGFncmFtIiwibGlua2VkaW4iLCJwaW50ZXJlc3QiLCJ0aWt0b2siLCJ5b3V0dWJlIiwicmVkZGl0IiwiUkVGRVJSRVJfQ0FURUdPUklFUyIsInNlYXJjaCIsInNvY2lhbCIsInNhbml0aXplUGFyYW0iLCJ2YWx1ZSIsInJlcGxhY2UiLCJzdWJzdHJpbmciLCJ0cmltIiwiZXh0cmFjdFVUTVBhcmFtcyIsInVybCIsInJlc3VsdCIsInNlYXJjaFN0cmluZyIsImxvY2F0aW9uIiwicGFyYW1zIiwiVVJMU2VhcmNoUGFyYW1zIiwiZm9yRWFjaCIsInBhcmFtIiwiZ2V0IiwiZSIsImNvbnNvbGUiLCJ3YXJuIiwiZGV0ZWN0UmVmZXJyZXIiLCJzb3VyY2UiLCJjYXRlZ29yeSIsImRvY3VtZW50IiwicmVmZXJyZXIiLCJ0ZXN0IiwiaW5kZXhPZiIsImdldFVzZXJBZ2VudEluZm8iLCJyYXciLCJpc01vYmlsZSIsImlzVGFibGV0IiwiaXNEZXNrdG9wIiwibmF2aWdhdG9yIiwidXNlckFnZW50IiwiaW5mZXJJbnRlbnQiLCJjb250ZXh0IiwidXRtIiwidXRtX2NhbXBhaWduIiwiY2FtcGFpZ24iLCJ0b0xvd2VyQ2FzZSIsInV0bV9zb3VyY2UiLCJnZXRDb250ZXh0Iiwib3B0aW9ucyIsInRpbWVzdGFtcCIsIkRhdGUiLCJub3ciLCJoYXNVVE0iLCJwcmltYXJ5SW50ZW50IiwiT2JqZWN0Iiwia2V5cyIsImxlbmd0aCIsImdldENvbnRleHRBc3luYyIsInRpbWVvdXQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInRpbWVyIiwic2V0VGltZW91dCIsInRpbWVkT3V0IiwiY2xlYXJUaW1lb3V0IiwiZXJyb3IiLCJtZXNzYWdlIiwiU2FuaXRpemVyIiwiQUxMT1dFRF9UQUdTIiwiQUxMT1dFRF9BVFRSUyIsIkRBTkdFUk9VU19VUkkiLCJFVkVOVF9IQU5ETEVSIiwiaGFzRE9NUGFyc2VyIiwiRE9NUGFyc2VyIiwiZXNjYXBlVGV4dCIsInRleHQiLCJlc2NhcGVBdHRyIiwiY2xlYW5BdHRyaWJ1dGVzIiwiZWxlbWVudCIsImF0dHJTdHIiLCJhdHRycyIsImF0dHJpYnV0ZXMiLCJpIiwibmFtZSIsIndhbGtBbmRDbGVhbiIsIm5vZGUiLCJvdXRwdXQiLCJjaGlsZE5vZGVzIiwiY2hpbGQiLCJub2RlVHlwZSIsInRleHRDb250ZW50IiwidGFnIiwidGFnTmFtZSIsInNhbml0aXplV2l0aERPTVBhcnNlciIsImRpcnR5IiwiZG9jIiwicGFyc2VGcm9tU3RyaW5nIiwiYm9keSIsInNhbml0aXplV2l0aFJlZ2V4IiwiaHRtbCIsInBhdHRlcm5zIiwic2FuaXRpemVkIiwicCIsIm1hdGNoIiwiY2hhckF0IiwiY2xlYW5BdHRycyIsInJlIiwibSIsImV4ZWMiLCJuIiwic2FuaXRpemUiLCJzYWZlU2V0VGV4dCIsInNhZmVTZXRIVE1MIiwiaW5uZXJIVE1MIiwiZmluZFBlcnNvbmFsaXplRWxlbWVudHMiLCJrZXkiLCJzZWFyY2hSb290Iiwic2VsZWN0b3IiLCJxdWVyeVNlbGVjdG9yQWxsIiwiZ2V0VGVtcGxhdGUiLCJpbnRlbnQiLCJ1c2VyVGVtcGxhdGVzIiwiX3R5cGVvZjIiLCJkZWZhdWx0IiwiZmlyc3RLZXkiLCJjaG9vc2VXZWlnaHRlZFJhbmRvbSIsIm5hbWVzIiwid2VpZ2h0cyIsInN1bSIsIk1hdGgiLCJyYW5kb20iLCJsaW1pdCIsImdldFJhbmRvbUZhbGxiYWNrSW50ZW50IiwicHVzaCIsIkRlY2lzaW9uRW5naW5lIiwic3RhbmRhcmREZWNpZGUiLCJjdXN0b21SdWxlcyIsInJ1bGVzIiwidGVtcGxhdGVzIiwiZW5hYmxlUmFuZG9tRmFsbGJhY2siLCJyYW5kb21GYWxsYmFjayIsInRlbXBsYXRlIiwicnVsZUtleSIsInJ1bGUiLCJyYW5kb21JbnRlbnQiLCJMdWFXZWlnaHRlZEhpc3RvcnkiLCJyZWNvcmRWaXNpdCIsInNlbGVjdGVkVmFyaWFudCIsImFpRGVjaXNpb24iLCJkZWNpZGUiLCJlbmFibGVBSSIsImFpQ29uZmlnIiwiTHVhQUlQZXJzb25hbGl6ZSIsInNlbGYiLCJhaU1vZHVsZSIsInJlYWRpbmVzcyIsImlzUmVhZHkiLCJyZWFkeSIsImNhdGNoIiwiZmFsbGJhY2siLCJmYWxsYmFja1RvU3RhbmRhcmQiLCJhcHBseURlY2lzaW9uVG9ET00iLCJkZWNpc2lvbiIsImxvZyIsInNsb3RzIiwic2xvdCIsImVsZW1lbnRzIiwiZWwiLCJzcmMiLCJhbHQiLCJoZWFkbGluZSIsInN0eWxlIiwiYmFja2dyb3VuZEltYWdlIiwiaHJlZiIsImhlcm9FbGVtZW50cyIsImgiLCJoZXJvRWwiLCJzZXRBdHRyaWJ1dGUiLCJpbWFnZSIsInF1ZXJ5U2VsZWN0b3IiLCJ1dG1QYXJhbXMiLCJhaVBvd2VyZWQiLCJwZXJzb25hbGl6ZSIsInRoZW4iLCJlcnIiLCJmYWxsYmFja0RlY2lzaW9uIiwicGVyc29uYWxpemVBc3luYyIsImN0eCIsImF1dG9Jbml0IiwicnVuIiwicmVhZHlTdGF0ZSIsImFkZEV2ZW50TGlzdGVuZXIiLCJMdWFVVE1QZXJzb25hbGl6ZSIsInNhbml0aXplciIsInNhbml0aXplSFRNTCIsImZpbmRFbGVtZW50cyIsImVuZ2luZSIsIkx1YVVUTSIsIkx1YVBlcnNvbmFsaXplIiwid2luZG93IiwiZ2xvYmFsIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0bS1wZXJzb25hbGl6ZS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJcbi8qKlxuICogTHVhIFVUTSBQZXJzb25hbGl6YXRpb24gLSBTdGFuZGFsb25lIEJ1bmRsZVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFNlbGYtY29udGFpbmVkIHNjcmlwdCBjb21iaW5pbmc6XG4gKiAgIC0gVVJMU2VhcmNoUGFyYW1zLWJhc2VkIFVUTSBleHRyYWN0aW9uXG4gKiAgIC0gUmVmZXJyZXIgJiB1c2VyIGFnZW50IGRldGVjdGlvblxuICogICAtIEludGVudCBpbmZlcmVuY2UgZW5naW5lXG4gKiAgIC0gRE9NUHVyaWZ5LXN0eWxlIEhUTUwgc2FuaXRpemVyXG4gKiAgIC0gRE9NIHBlcnNvbmFsaXphdGlvbiB2aWEgZGF0YS1wZXJzb25hbGl6ZSBhdHRyaWJ1dGVzXG4gKiAgIC0gUmFuZG9tIEEvQiB0ZXN0IGZhbGxiYWNrIHdoZW4gbm8gVVRNIHBhcmFtcyBwcmVzZW50XG4gKlxuICogVXNhZ2U6XG4gKiAgIDxzY3JpcHQgc3JjPVwidXRtLXBlcnNvbmFsaXplLmpzXCIgZGVmZXI+PC9zY3JpcHQ+XG4gKlxuICogICA8IS0tIFRoZW4gaW4geW91ciBIVE1MIHVzZSBkYXRhLXBlcnNvbmFsaXplIGF0dHJpYnV0ZXM6IC0tPlxuICogICA8ZGl2IGRhdGEtcGVyc29uYWxpemU9XCJoZXJvXCI+XG4gKiAgICAgPGgxIGRhdGEtcGVyc29uYWxpemU9XCJoZWFkbGluZVwiPkRlZmF1bHQgSGVhZGxpbmU8L2gxPlxuICogICAgIDxwIGRhdGEtcGVyc29uYWxpemU9XCJzdWJoZWFkbGluZVwiPkRlZmF1bHQgc3ViaGVhZGxpbmU8L3A+XG4gKiAgICAgPGEgaHJlZj1cIiNcIiBkYXRhLXBlcnNvbmFsaXplPVwiY3RhTGlua1wiPlxuICogICAgICAgPHNwYW4gZGF0YS1wZXJzb25hbGl6ZT1cImN0YUxhYmVsXCI+RGVmYXVsdCBDVEE8L3NwYW4+XG4gKiAgICAgPC9hPlxuICogICA8L2Rpdj5cbiAqXG4gKiBUaGUgc2NyaXB0IGF1dG8taW5pdGlhbGl6ZXMgb24gRE9NQ29udGVudExvYWRlZC5cbiAqIEFjY2VzcyB0aGUgQVBJIHZpYSB3aW5kb3cuTHVhVVRNUGVyc29uYWxpemVcbiAqXG4gKiBTaXplIHRhcmdldDogPCA1MEtCXG4gKiBObyBpbXBvcnRzLiBObyBkZXBlbmRlbmNpZXMuIE5vIGJ1aWxkIHN0ZXAgcmVxdWlyZWQuXG4gKi9cbjsoZnVuY3Rpb24gKHJvb3QpIHtcbiAgICAndXNlIHN0cmljdCdcblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyAxLiBVVE0gUEFSQU1FVEVSIEVYVFJBQ1RJT04gKFVSTFNlYXJjaFBhcmFtcyBBUEkpXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgdmFyIFVUTV9USU1FT1VUX01TID0gMTAwMFxuXG4gICAgdmFyIFVUTV9QQVJBTVMgPSBbJ3V0bV9zb3VyY2UnLCAndXRtX21lZGl1bScsICd1dG1fY2FtcGFpZ24nLCAndXRtX2NvbnRlbnQnLCAndXRtX3Rlcm0nXVxuXG4gICAgdmFyIFJFRkVSUkVSX1BBVFRFUk5TID0ge1xuICAgICAgICBnb29nbGU6IC9nb29nbGVcXC4vaSxcbiAgICAgICAgYmluZzogL2JpbmdcXC4vaSxcbiAgICAgICAgeWFob286IC95YWhvb1xcLi9pLFxuICAgICAgICBkdWNrZHVja2dvOiAvZHVja2R1Y2tnb1xcLi9pLFxuICAgICAgICBmYWNlYm9vazogL2ZhY2Vib29rXFwuY29tfGZiXFwuY29tL2ksXG4gICAgICAgIHR3aXR0ZXI6IC90d2l0dGVyXFwuY29tfHRcXC5jb3x4XFwuY29tL2ksXG4gICAgICAgIGluc3RhZ3JhbTogL2luc3RhZ3JhbVxcLmNvbS9pLFxuICAgICAgICBsaW5rZWRpbjogL2xpbmtlZGluXFwuY29tL2ksXG4gICAgICAgIHBpbnRlcmVzdDogL3BpbnRlcmVzdFxcLi9pLFxuICAgICAgICB0aWt0b2s6IC90aWt0b2tcXC5jb20vaSxcbiAgICAgICAgeW91dHViZTogL3lvdXR1YmVcXC5jb218eW91dHVcXC5iZS9pLFxuICAgICAgICByZWRkaXQ6IC9yZWRkaXRcXC5jb20vaVxuICAgIH1cblxuICAgIHZhciBSRUZFUlJFUl9DQVRFR09SSUVTID0ge1xuICAgICAgICBzZWFyY2g6IFsnZ29vZ2xlJywgJ2JpbmcnLCAneWFob28nLCAnZHVja2R1Y2tnbyddLFxuICAgICAgICBzb2NpYWw6IFsnZmFjZWJvb2snLCAndHdpdHRlcicsICdpbnN0YWdyYW0nLCAnbGlua2VkaW4nLCAncGludGVyZXN0JywgJ3Rpa3RvaycsICd5b3V0dWJlJywgJ3JlZGRpdCddXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2FuaXRpemUgYSBVVE0gcGFyYW1ldGVyIHZhbHVlIHRvIHByZXZlbnQgWFNTXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gUmF3IHBhcmFtZXRlciB2YWx1ZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IC0gU2FuaXRpemVkIHZhbHVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2FuaXRpemVQYXJhbSh2YWx1ZSkge1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJykgcmV0dXJuICcnXG4gICAgICAgIHJldHVybiB2YWx1ZVxuICAgICAgICAgICAgLnJlcGxhY2UoLzxbXj5dKj4vZywgJycpXG4gICAgICAgICAgICAucmVwbGFjZSgvW15cXHdcXHNcXC1fLl0vZywgJycpXG4gICAgICAgICAgICAuc3Vic3RyaW5nKDAsIDEwMClcbiAgICAgICAgICAgIC50cmltKClcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeHRyYWN0IFVUTSBwYXJhbWV0ZXJzIGZyb20gVVJMIHVzaW5nIG5hdGl2ZSBVUkxTZWFyY2hQYXJhbXMgQVBJXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFt1cmxdIC0gVVJMIHNlYXJjaCBzdHJpbmcgKGRlZmF1bHRzIHRvIHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpXG4gICAgICogQHJldHVybnMge09iamVjdH0gLSBPYmplY3QgY29udGFpbmluZyBVVE0gcGFyYW1ldGVyc1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGV4dHJhY3RVVE1QYXJhbXModXJsKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSB7fVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmFyIHNlYXJjaFN0cmluZyA9IHVybCB8fCAodHlwZW9mIHJvb3QubG9jYXRpb24gIT09ICd1bmRlZmluZWQnID8gcm9vdC5sb2NhdGlvbi5zZWFyY2ggOiAnJylcbiAgICAgICAgICAgIGlmICghc2VhcmNoU3RyaW5nKSByZXR1cm4gcmVzdWx0XG5cbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHNlYXJjaFN0cmluZylcblxuICAgICAgICAgICAgVVRNX1BBUkFNUy5mb3JFYWNoKGZ1bmN0aW9uIChwYXJhbSkge1xuICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHBhcmFtcy5nZXQocGFyYW0pXG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtwYXJhbV0gPSBzYW5pdGl6ZVBhcmFtKHZhbHVlKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignW0x1YSBVVE1dIEVycm9yIGV4dHJhY3RpbmcgVVRNIHBhcmFtczonLCBlKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgcmVmZXJyZXIgdHlwZSBmcm9tIGRvY3VtZW50LnJlZmVycmVyXG4gICAgICogQHJldHVybnMge09iamVjdH0gLSB7IHNvdXJjZSwgY2F0ZWdvcnksIHVybCB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gZGV0ZWN0UmVmZXJyZXIoKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSB7IHNvdXJjZTogJ2RpcmVjdCcsIGNhdGVnb3J5OiAnZGlyZWN0JywgdXJsOiAnJyB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJyB8fCAhZG9jdW1lbnQucmVmZXJyZXIpIHJldHVybiByZXN1bHRcblxuICAgICAgICAgICAgcmVzdWx0LnVybCA9IGRvY3VtZW50LnJlZmVycmVyXG5cbiAgICAgICAgICAgIGlmICgvbWFpbFxcLnxlbWFpbFxcLnxuZXdzbGV0dGVyL2kudGVzdChkb2N1bWVudC5yZWZlcnJlcikpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQuc291cmNlID0gJ2VtYWlsJ1xuICAgICAgICAgICAgICAgIHJlc3VsdC5jYXRlZ29yeSA9ICdlbWFpbCdcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAodmFyIHNvdXJjZSBpbiBSRUZFUlJFUl9QQVRURVJOUykge1xuICAgICAgICAgICAgICAgIGlmIChSRUZFUlJFUl9QQVRURVJOU1tzb3VyY2VdLnRlc3QoZG9jdW1lbnQucmVmZXJyZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5zb3VyY2UgPSBzb3VyY2VcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgY2F0ZWdvcnkgaW4gUkVGRVJSRVJfQ0FURUdPUklFUykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFJFRkVSUkVSX0NBVEVHT1JJRVNbY2F0ZWdvcnldLmluZGV4T2Yoc291cmNlKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuY2F0ZWdvcnkgPSBjYXRlZ29yeVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmVzdWx0LnNvdXJjZSA9ICdleHRlcm5hbCdcbiAgICAgICAgICAgIHJlc3VsdC5jYXRlZ29yeSA9ICdvdGhlcidcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIFVUTV0gRXJyb3IgZGV0ZWN0aW5nIHJlZmVycmVyOicsIGUpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdFxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB1c2VyIGFnZW50IGluZm8gZm9yIGRldmljZSBkZXRlY3Rpb25cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSAtIHsgcmF3LCBpc01vYmlsZSwgaXNUYWJsZXQsIGlzRGVza3RvcCB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0VXNlckFnZW50SW5mbygpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHsgcmF3OiAnJywgaXNNb2JpbGU6IGZhbHNlLCBpc1RhYmxldDogZmFsc2UsIGlzRGVza3RvcDogdHJ1ZSB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG5hdmlnYXRvciA9PT0gJ3VuZGVmaW5lZCcgfHwgIW5hdmlnYXRvci51c2VyQWdlbnQpIHJldHVybiByZXN1bHRcbiAgICAgICAgICAgIHJlc3VsdC5yYXcgPSBuYXZpZ2F0b3IudXNlckFnZW50XG4gICAgICAgICAgICByZXN1bHQuaXNNb2JpbGUgPSAvQW5kcm9pZHx3ZWJPU3xpUGhvbmV8aVBvZHxCbGFja0JlcnJ5fElFTW9iaWxlfE9wZXJhIE1pbmkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpXG4gICAgICAgICAgICByZXN1bHQuaXNUYWJsZXQgPSAvaVBhZHxBbmRyb2lkKD8hLipNb2JpbGUpL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KVxuICAgICAgICAgICAgcmVzdWx0LmlzRGVza3RvcCA9ICFyZXN1bHQuaXNNb2JpbGUgJiYgIXJlc3VsdC5pc1RhYmxldFxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tMdWEgVVRNXSBFcnJvciBnZXR0aW5nIHVzZXIgYWdlbnQ6JywgZSlcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5mZXIgdXNlciBpbnRlbnQgZnJvbSBjb250ZXh0XG4gICAgICogUHJpb3JpdHk6IFVUTSBjYW1wYWlnbiA+IFVUTSBzb3VyY2UgPiBSZWZlcnJlciBjYXRlZ29yeVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjb250ZXh0IC0gRnVsbCBjb250ZXh0IG9iamVjdFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IC0gSW5mZXJyZWQgaW50ZW50IGtleVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluZmVySW50ZW50KGNvbnRleHQpIHtcbiAgICAgICAgaWYgKGNvbnRleHQudXRtLnV0bV9jYW1wYWlnbikge1xuICAgICAgICAgICAgdmFyIGNhbXBhaWduID0gY29udGV4dC51dG0udXRtX2NhbXBhaWduLnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgIGlmICgvc2FsZXxkaXNjb3VudHxvZmZlcnxwcm9tby9pLnRlc3QoY2FtcGFpZ24pKSByZXR1cm4gJ3ByaWNlLWZvY3VzZWQnXG4gICAgICAgICAgICBpZiAoL2dhbWluZ3xnYW1lfGVzcG9ydC9pLnRlc3QoY2FtcGFpZ24pKSByZXR1cm4gJ2dhbWluZydcbiAgICAgICAgICAgIGlmICgvd29ya3xvZmZpY2V8cHJvZmVzc2lvbmFsfHByb2R1Y3Rpdml0eS9pLnRlc3QoY2FtcGFpZ24pKSByZXR1cm4gJ3Byb2Zlc3Npb25hbCdcbiAgICAgICAgICAgIGlmICgvY3JlYXRpdmV8ZGVzaWdufGFydHxzdHVkaW8vaS50ZXN0KGNhbXBhaWduKSkgcmV0dXJuICdjcmVhdGl2ZSdcbiAgICAgICAgICAgIGlmICgvYnJhbmR8c3Rvcnl8YWJvdXQvaS50ZXN0KGNhbXBhaWduKSkgcmV0dXJuICdicmFuZC1zdG9yeSdcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjb250ZXh0LnV0bS51dG1fc291cmNlKSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gY29udGV4dC51dG0udXRtX3NvdXJjZS50b0xvd2VyQ2FzZSgpXG4gICAgICAgICAgICBpZiAoL2dvb2dsZXxiaW5nfHlhaG9vL2kudGVzdChzb3VyY2UpKSByZXR1cm4gJ3NlYXJjaC1vcHRpbWl6ZWQnXG4gICAgICAgICAgICBpZiAoL2ZhY2Vib29rfGluc3RhZ3JhbXx0aWt0b2svaS50ZXN0KHNvdXJjZSkpIHJldHVybiAnc29jaWFsLXZpc3VhbCdcbiAgICAgICAgICAgIGlmICgvdHdpdHRlcnx4JC9pLnRlc3Qoc291cmNlKSkgcmV0dXJuICdzb2NpYWwtYnJpZWYnXG4gICAgICAgICAgICBpZiAoL2VtYWlsfG5ld3NsZXR0ZXIvaS50ZXN0KHNvdXJjZSkpIHJldHVybiAncmV0dXJuaW5nLXVzZXInXG4gICAgICAgICAgICBpZiAoL3lvdXR1YmUvaS50ZXN0KHNvdXJjZSkpIHJldHVybiAndmlkZW8tZW5nYWdlZCdcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjb250ZXh0LnJlZmVycmVyLmNhdGVnb3J5ID09PSAnc2VhcmNoJykgcmV0dXJuICdzZWFyY2gtb3B0aW1pemVkJ1xuICAgICAgICBpZiAoY29udGV4dC5yZWZlcnJlci5jYXRlZ29yeSA9PT0gJ3NvY2lhbCcpIHJldHVybiAnc29jaWFsLXZpc3VhbCdcbiAgICAgICAgaWYgKGNvbnRleHQucmVmZXJyZXIuY2F0ZWdvcnkgPT09ICdlbWFpbCcpIHJldHVybiAncmV0dXJuaW5nLXVzZXInXG5cbiAgICAgICAgcmV0dXJuICdkZWZhdWx0J1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEJ1aWxkIGZ1bGwgcGVyc29uYWxpemF0aW9uIGNvbnRleHRcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIC0geyB1cmw6IHN0cmluZyB9XG4gICAgICogQHJldHVybnMge09iamVjdH0gLSBDb21wbGV0ZSBjb250ZXh0IG9iamVjdFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldENvbnRleHQob3B0aW9ucykge1xuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICAgICAgICB2YXIgY29udGV4dCA9IHtcbiAgICAgICAgICAgIHV0bTogZXh0cmFjdFVUTVBhcmFtcyhvcHRpb25zLnVybCksXG4gICAgICAgICAgICByZWZlcnJlcjogZGV0ZWN0UmVmZXJyZXIoKSxcbiAgICAgICAgICAgIHVzZXJBZ2VudDogZ2V0VXNlckFnZW50SW5mbygpLFxuICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgaGFzVVRNOiBmYWxzZSxcbiAgICAgICAgICAgIHByaW1hcnlJbnRlbnQ6ICd1bmtub3duJ1xuICAgICAgICB9XG4gICAgICAgIGNvbnRleHQuaGFzVVRNID0gT2JqZWN0LmtleXMoY29udGV4dC51dG0pLmxlbmd0aCA+IDBcbiAgICAgICAgY29udGV4dC5wcmltYXJ5SW50ZW50ID0gaW5mZXJJbnRlbnQoY29udGV4dClcbiAgICAgICAgcmV0dXJuIGNvbnRleHRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBc3luYyBjb250ZXh0IHdpdGggdGltZW91dCBmYWxsYmFjayAoMSBzZWNvbmQgbWF4KVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gLSB7IHRpbWVvdXQ6IG51bWJlciwgdXJsOiBzdHJpbmcgfVxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPE9iamVjdD59IC0gQ29udGV4dCBvYmplY3RcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRDb250ZXh0QXN5bmMob3B0aW9ucykge1xuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICAgICAgICB2YXIgdGltZW91dCA9IG9wdGlvbnMudGltZW91dCB8fCBVVE1fVElNRU9VVF9NU1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgICAgICAgdmFyIHRpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSh7XG4gICAgICAgICAgICAgICAgICAgIHV0bToge30sXG4gICAgICAgICAgICAgICAgICAgIHJlZmVycmVyOiB7IHNvdXJjZTogJ2RpcmVjdCcsIGNhdGVnb3J5OiAnZGlyZWN0JywgdXJsOiAnJyB9LFxuICAgICAgICAgICAgICAgICAgICB1c2VyQWdlbnQ6IHsgcmF3OiAnJywgaXNNb2JpbGU6IGZhbHNlLCBpc1RhYmxldDogZmFsc2UsIGlzRGVza3RvcDogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgICAgICAgICAgICAgICAgIGhhc1VUTTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIHByaW1hcnlJbnRlbnQ6ICdkZWZhdWx0JyxcbiAgICAgICAgICAgICAgICAgICAgdGltZWRPdXQ6IHRydWVcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSwgdGltZW91dClcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgY29udGV4dCA9IGdldENvbnRleHQob3B0aW9ucylcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpXG4gICAgICAgICAgICAgICAgY29udGV4dC50aW1lZE91dCA9IGZhbHNlXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb250ZXh0KVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lcilcbiAgICAgICAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgICAgICAgICAgdXRtOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgcmVmZXJyZXI6IHsgc291cmNlOiAnZGlyZWN0JywgY2F0ZWdvcnk6ICdkaXJlY3QnLCB1cmw6ICcnIH0sXG4gICAgICAgICAgICAgICAgICAgIHVzZXJBZ2VudDogeyByYXc6ICcnLCBpc01vYmlsZTogZmFsc2UsIGlzVGFibGV0OiBmYWxzZSwgaXNEZXNrdG9wOiB0cnVlIH0sXG4gICAgICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgICAgICAgICAgaGFzVVRNOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgcHJpbWFyeUludGVudDogJ2RlZmF1bHQnLFxuICAgICAgICAgICAgICAgICAgICBlcnJvcjogZS5tZXNzYWdlXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICB9XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gMi4gRE9NUFVSSUZZLVNUWUxFIEhUTUwgU0FOSVRJWkVSXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgdmFyIFNhbml0aXplciA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBBTExPV0VEX1RBR1MgPSB7XG4gICAgICAgICAgICAncCc6IHRydWUsICdzcGFuJzogdHJ1ZSwgJ3N0cm9uZyc6IHRydWUsICdlbSc6IHRydWUsXG4gICAgICAgICAgICAnYic6IHRydWUsICdpJzogdHJ1ZSwgJ2JyJzogdHJ1ZSwgJ2EnOiB0cnVlLCAnaW1nJzogdHJ1ZSxcbiAgICAgICAgICAgICdoMSc6IHRydWUsICdoMic6IHRydWUsICdoMyc6IHRydWUsICdoNCc6IHRydWUsICdoNSc6IHRydWUsICdoNic6IHRydWUsXG4gICAgICAgICAgICAnZGl2JzogdHJ1ZSwgJ3NlY3Rpb24nOiB0cnVlLCAndWwnOiB0cnVlLCAnb2wnOiB0cnVlLCAnbGknOiB0cnVlLFxuICAgICAgICAgICAgJ2Jsb2NrcXVvdGUnOiB0cnVlLCAnZmlndXJlJzogdHJ1ZSwgJ2ZpZ2NhcHRpb24nOiB0cnVlXG4gICAgICAgIH1cblxuICAgICAgICB2YXIgQUxMT1dFRF9BVFRSUyA9IHtcbiAgICAgICAgICAgICdocmVmJzogdHJ1ZSwgJ3NyYyc6IHRydWUsICdhbHQnOiB0cnVlLCAnY2xhc3MnOiB0cnVlLFxuICAgICAgICAgICAgJ2lkJzogdHJ1ZSwgJ3RpdGxlJzogdHJ1ZSwgJ3RhcmdldCc6IHRydWUsICdyZWwnOiB0cnVlLFxuICAgICAgICAgICAgJ3dpZHRoJzogdHJ1ZSwgJ2hlaWdodCc6IHRydWUsICdsb2FkaW5nJzogdHJ1ZVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIERBTkdFUk9VU19VUkkgPSAvXihqYXZhc2NyaXB0fHZic2NyaXB0fGRhdGEpOi9pXG4gICAgICAgIHZhciBFVkVOVF9IQU5ETEVSID0gL15vbi9pXG5cbiAgICAgICAgZnVuY3Rpb24gaGFzRE9NUGFyc2VyKCkge1xuICAgICAgICAgICAgdHJ5IHsgcmV0dXJuIHR5cGVvZiBET01QYXJzZXIgIT09ICd1bmRlZmluZWQnICYmIG5ldyBET01QYXJzZXIoKSB9XG4gICAgICAgICAgICBjYXRjaCAoZSkgeyByZXR1cm4gZmFsc2UgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZXNjYXBlVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICBpZiAoIXRleHQpIHJldHVybiAnJ1xuICAgICAgICAgICAgcmV0dXJuIHRleHQucmVwbGFjZSgvJi9nLCAnJmFtcDsnKS5yZXBsYWNlKC88L2csICcmbHQ7JykucmVwbGFjZSgvPi9nLCAnJmd0OycpXG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBlc2NhcGVBdHRyKHZhbHVlKSB7XG4gICAgICAgICAgICBpZiAoIXZhbHVlKSByZXR1cm4gJydcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZS5yZXBsYWNlKC8mL2csICcmYW1wOycpLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKS5yZXBsYWNlKC8nL2csICcmIzM5OycpLnJlcGxhY2UoLzwvZywgJyZsdDsnKS5yZXBsYWNlKC8+L2csICcmZ3Q7JylcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGNsZWFuQXR0cmlidXRlcyhlbGVtZW50KSB7XG4gICAgICAgICAgICB2YXIgYXR0clN0ciA9ICcnXG4gICAgICAgICAgICB2YXIgYXR0cnMgPSBlbGVtZW50LmF0dHJpYnV0ZXNcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXR0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgbmFtZSA9IGF0dHJzW2ldLm5hbWUudG9Mb3dlckNhc2UoKVxuICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IGF0dHJzW2ldLnZhbHVlXG4gICAgICAgICAgICAgICAgaWYgKEVWRU5UX0hBTkRMRVIudGVzdChuYW1lKSkgY29udGludWVcbiAgICAgICAgICAgICAgICBpZiAoIUFMTE9XRURfQVRUUlNbbmFtZV0pIGNvbnRpbnVlXG4gICAgICAgICAgICAgICAgaWYgKChuYW1lID09PSAnaHJlZicgfHwgbmFtZSA9PT0gJ3NyYycpICYmIERBTkdFUk9VU19VUkkudGVzdCh2YWx1ZS50cmltKCkpKSBjb250aW51ZVxuICAgICAgICAgICAgICAgIGlmIChuYW1lID09PSAndGFyZ2V0JyAmJiB2YWx1ZSA9PT0gJ19ibGFuaycpIHtcbiAgICAgICAgICAgICAgICAgICAgYXR0clN0ciArPSAnIHRhcmdldD1cIl9ibGFua1wiIHJlbD1cIm5vb3BlbmVyIG5vcmVmZXJyZXJcIidcbiAgICAgICAgICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYXR0clN0ciArPSAnICcgKyBuYW1lICsgJz1cIicgKyBlc2NhcGVBdHRyKHZhbHVlKSArICdcIidcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBhdHRyU3RyXG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiB3YWxrQW5kQ2xlYW4obm9kZSkge1xuICAgICAgICAgICAgdmFyIG91dHB1dCA9ICcnXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IG5vZGUuY2hpbGROb2Rlc1tpXVxuICAgICAgICAgICAgICAgIGlmIChjaGlsZC5ub2RlVHlwZSA9PT0gMykgeyBvdXRwdXQgKz0gZXNjYXBlVGV4dChjaGlsZC50ZXh0Q29udGVudCk7IGNvbnRpbnVlIH1cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRhZyA9IGNoaWxkLnRhZ05hbWUudG9Mb3dlckNhc2UoKVxuICAgICAgICAgICAgICAgICAgICBpZiAodGFnID09PSAnc2NyaXB0JyB8fCB0YWcgPT09ICdzdHlsZScgfHwgdGFnID09PSAnaWZyYW1lJyB8fCB0YWcgPT09ICdvYmplY3QnIHx8IHRhZyA9PT0gJ2VtYmVkJyB8fCB0YWcgPT09ICdmb3JtJyB8fCB0YWcgPT09ICdpbnB1dCcgfHwgdGFnID09PSAndGV4dGFyZWEnKSBjb250aW51ZVxuICAgICAgICAgICAgICAgICAgICBpZiAoQUxMT1dFRF9UQUdTW3RhZ10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dCArPSAnPCcgKyB0YWcgKyBjbGVhbkF0dHJpYnV0ZXMoY2hpbGQpICsgJz4nXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGFnICE9PSAnYnInICYmIHRhZyAhPT0gJ2ltZycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQgKz0gd2Fsa0FuZENsZWFuKGNoaWxkKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dCArPSAnPC8nICsgdGFnICsgJz4nXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQgKz0gd2Fsa0FuZENsZWFuKGNoaWxkKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dHB1dFxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gc2FuaXRpemVXaXRoRE9NUGFyc2VyKGRpcnR5KSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBuZXcgRE9NUGFyc2VyKCkucGFyc2VGcm9tU3RyaW5nKGRpcnR5LCAndGV4dC9odG1sJylcbiAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmJvZHkgPyB3YWxrQW5kQ2xlYW4oZG9jLmJvZHkpIDogJydcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2FuaXRpemVXaXRoUmVnZXgoZGlydHkpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBzYW5pdGl6ZVdpdGhSZWdleChodG1sKSB7XG4gICAgICAgICAgICB2YXIgcGF0dGVybnMgPSBbXG4gICAgICAgICAgICAgICAgLzxzY3JpcHRcXGJbXjxdKig/Oig/ITxcXC9zY3JpcHQ+KTxbXjxdKikqPFxcL3NjcmlwdD4vZ2ksXG4gICAgICAgICAgICAgICAgLzxpZnJhbWVcXGJbXjxdKig/Oig/ITxcXC9pZnJhbWU+KTxbXjxdKikqPFxcL2lmcmFtZT4vZ2ksXG4gICAgICAgICAgICAgICAgLzxvYmplY3RcXGJbXjxdKig/Oig/ITxcXC9vYmplY3Q+KTxbXjxdKikqPFxcL29iamVjdD4vZ2ksXG4gICAgICAgICAgICAgICAgLzxlbWJlZFxcYltePl0qPi9naSwgLzxsaW5rXFxiW14+XSo+L2dpLFxuICAgICAgICAgICAgICAgIC88c3R5bGVcXGJbXjxdKig/Oig/ITxcXC9zdHlsZT4pPFtePF0qKSo8XFwvc3R5bGU+L2dpLFxuICAgICAgICAgICAgICAgIC88Zm9ybVxcYltePF0qKD86KD8hPFxcL2Zvcm0+KTxbXjxdKikqPFxcL2Zvcm0+L2dpLFxuICAgICAgICAgICAgICAgIC9qYXZhc2NyaXB0Oi9naSwgL3Zic2NyaXB0Oi9naSwgL2RhdGE6L2dpLCAvb25cXHcrXFxzKj0vZ2lcbiAgICAgICAgICAgIF1cbiAgICAgICAgICAgIHZhciBzYW5pdGl6ZWQgPSBodG1sXG4gICAgICAgICAgICBwYXR0ZXJucy5mb3JFYWNoKGZ1bmN0aW9uIChwKSB7IHNhbml0aXplZCA9IHNhbml0aXplZC5yZXBsYWNlKHAsICcnKSB9KVxuICAgICAgICAgICAgc2FuaXRpemVkID0gc2FuaXRpemVkLnJlcGxhY2UoLzxcXC8/KFxcdyspKFtePl0qKT4vZywgZnVuY3Rpb24gKG1hdGNoLCB0YWdOYW1lLCBhdHRycykge1xuICAgICAgICAgICAgICAgIHZhciB0YWcgPSB0YWdOYW1lLnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgICAgICBpZiAoIUFMTE9XRURfVEFHU1t0YWddKSByZXR1cm4gJydcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2guY2hhckF0KDEpID09PSAnLycpIHJldHVybiAnPC8nICsgdGFnICsgJz4nXG4gICAgICAgICAgICAgICAgdmFyIGNsZWFuQXR0cnMgPSAnJ1xuICAgICAgICAgICAgICAgIHZhciByZSA9IC8oXFx3Kyk9WydcIl0oW14nXCJdKilbJ1wiXS9nXG4gICAgICAgICAgICAgICAgdmFyIG1cbiAgICAgICAgICAgICAgICB3aGlsZSAoKG0gPSByZS5leGVjKGF0dHJzKSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSBtWzFdLnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgICAgICAgICAgaWYgKEFMTE9XRURfQVRUUlNbbl0gJiYgIUVWRU5UX0hBTkRMRVIudGVzdChuKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChuID09PSAnaHJlZicgfHwgbiA9PT0gJ3NyYycpICYmIERBTkdFUk9VU19VUkkudGVzdChtWzJdKSkgY29udGludWVcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFuQXR0cnMgKz0gJyAnICsgbiArICc9XCInICsgbVsyXSArICdcIidcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gJzwnICsgdGFnICsgY2xlYW5BdHRycyArICc+J1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIHJldHVybiBzYW5pdGl6ZWRcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzYW5pdGl6ZTogZnVuY3Rpb24gKGRpcnR5KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkaXJ0eSAhPT0gJ3N0cmluZycgfHwgIWRpcnR5LnRyaW0oKSkgcmV0dXJuICcnXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc0RPTVBhcnNlcigpID8gc2FuaXRpemVXaXRoRE9NUGFyc2VyKGRpcnR5KSA6IHNhbml0aXplV2l0aFJlZ2V4KGRpcnR5KVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVzY2FwZVRleHQ6IGVzY2FwZVRleHQsXG4gICAgICAgICAgICBlc2NhcGVBdHRyOiBlc2NhcGVBdHRyXG4gICAgICAgIH1cbiAgICB9KSgpXG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gMy4gVEVNUExBVEVTICYgQVNTRVRTXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIE5PVEU6IFRlbXBsYXRlcyBhcmUgTk9UIHByb3ZpZGVkIGJ5IHRoaXMgcGFja2FnZS5cbiAgICAvLyBVc2VycyBtdXN0IHByb3ZpZGUgdGhlaXIgb3duIHRlbXBsYXRlcyB2aWEgb3B0aW9ucy50ZW1wbGF0ZXNcbiAgICAvLyBUaGlzIGtlZXBzIHRoZSBwYWNrYWdlIG1vZHVsYXIgYW5kIGFsbG93cyB1c2VycyBmdWxsIGNvbnRyb2xcbiAgICAvLyBvdmVyIHRoZWlyIGNvbnRlbnQsIGFzc2V0cywgYW5kIHBlcnNvbmFsaXphdGlvbiBzdHJhdGVneS5cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyA0LiBET00gUEVSU09OQUxJWkFUSU9OIEVOR0lORVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIGZ1bmN0aW9uIHNhZmVTZXRUZXh0KGVsZW1lbnQsIHRleHQpIHtcbiAgICAgICAgaWYgKCFlbGVtZW50KSByZXR1cm5cbiAgICAgICAgZWxlbWVudC50ZXh0Q29udGVudCA9IHRleHRcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzYWZlU2V0SFRNTChlbGVtZW50LCBodG1sKSB7XG4gICAgICAgIGlmICghZWxlbWVudCkgcmV0dXJuXG4gICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gU2FuaXRpemVyLnNhbml0aXplKGh0bWwpXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZmluZFBlcnNvbmFsaXplRWxlbWVudHMoa2V5LCBzZWFyY2hSb290KSB7XG4gICAgICAgIHNlYXJjaFJvb3QgPSBzZWFyY2hSb290IHx8ICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnID8gZG9jdW1lbnQgOiBudWxsKVxuICAgICAgICBpZiAoIXNlYXJjaFJvb3QpIHJldHVybiBbXVxuICAgICAgICB2YXIgc2VsZWN0b3IgPSBrZXkgPyAnW2RhdGEtcGVyc29uYWxpemU9XCInICsga2V5ICsgJ1wiXScgOiAnW2RhdGEtcGVyc29uYWxpemVdJ1xuICAgICAgICByZXR1cm4gc2VhcmNoUm9vdC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFRlbXBsYXRlKGludGVudCwgdXNlclRlbXBsYXRlcykge1xuICAgICAgICBpZiAoIXVzZXJUZW1wbGF0ZXMgfHwgdHlwZW9mIHVzZXJUZW1wbGF0ZXMgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tMdWEgUGVyc29uYWxpemVdIE5vIHRlbXBsYXRlcyBwcm92aWRlZC4gVGVtcGxhdGVzIG11c3QgYmUgcGFzc2VkIHZpYSBvcHRpb25zLnRlbXBsYXRlcycpXG4gICAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICB9XG4gICAgICAgIGlmICh1c2VyVGVtcGxhdGVzW2ludGVudF0pIHJldHVybiB1c2VyVGVtcGxhdGVzW2ludGVudF1cbiAgICAgICAgaWYgKHVzZXJUZW1wbGF0ZXNbJ2RlZmF1bHQnXSkgcmV0dXJuIHVzZXJUZW1wbGF0ZXNbJ2RlZmF1bHQnXVxuICAgICAgICB2YXIgZmlyc3RLZXkgPSBPYmplY3Qua2V5cyh1c2VyVGVtcGxhdGVzKVswXVxuICAgICAgICBpZiAoZmlyc3RLZXkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignW0x1YSBQZXJzb25hbGl6ZV0gSW50ZW50IFwiJyArIGludGVudCArICdcIiBub3QgZm91bmQsIHVzaW5nIGZpcnN0IGF2YWlsYWJsZSB0ZW1wbGF0ZTonLCBmaXJzdEtleSlcbiAgICAgICAgICAgIHJldHVybiB1c2VyVGVtcGxhdGVzW2ZpcnN0S2V5XVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsXG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIDUuIFJBTkRPTSBBL0IgRkFMTEJBQ0tcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICBmdW5jdGlvbiBjaG9vc2VXZWlnaHRlZFJhbmRvbShuYW1lcywgd2VpZ2h0cykge1xuICAgICAgICBpZiAobmFtZXMubGVuZ3RoICE9PSB3ZWlnaHRzLmxlbmd0aCkgcmV0dXJuIG5hbWVzWzBdXG4gICAgICAgIHZhciBzdW0gPSAwXG4gICAgICAgIHZhciBpXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB3ZWlnaHRzLmxlbmd0aDsgaSsrKSB7IHN1bSArPSB3ZWlnaHRzW2ldIH1cbiAgICAgICAgdmFyIG4gPSBNYXRoLnJhbmRvbSgpICogc3VtXG4gICAgICAgIHZhciBsaW1pdCA9IDBcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IG5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsaW1pdCArPSB3ZWlnaHRzW2ldXG4gICAgICAgICAgICBpZiAobiA8PSBsaW1pdCkgcmV0dXJuIG5hbWVzW2ldXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5hbWVzW25hbWVzLmxlbmd0aCAtIDFdXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0UmFuZG9tRmFsbGJhY2tJbnRlbnQodXNlclRlbXBsYXRlcykge1xuICAgICAgICBpZiAoIXVzZXJUZW1wbGF0ZXMgfHwgdHlwZW9mIHVzZXJUZW1wbGF0ZXMgIT09ICdvYmplY3QnKSByZXR1cm4gbnVsbFxuICAgICAgICB2YXIgbmFtZXMgPSBPYmplY3Qua2V5cyh1c2VyVGVtcGxhdGVzKVxuICAgICAgICBpZiAobmFtZXMubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbFxuICAgICAgICB2YXIgd2VpZ2h0cyA9IFtdXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFtZXMubGVuZ3RoOyBpKyspIHsgd2VpZ2h0cy5wdXNoKDEpIH1cbiAgICAgICAgcmV0dXJuIGNob29zZVdlaWdodGVkUmFuZG9tKG5hbWVzLCB3ZWlnaHRzKVxuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyA2LiBERUNJU0lPTiBFTkdJTkVcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICB2YXIgRGVjaXNpb25FbmdpbmUgPSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTdGFuZGFyZCAobm9uLUFJKSBkZWNpc2lvbiBsb2dpY1xuICAgICAgICAgKiBQcmlvcml0eTogQ3VzdG9tIHJ1bGVzID4gVVRNIHBhcmFtcyA+IFJlZmVycmVyID4gUmFuZG9tIEEvQlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhbmRhcmREZWNpZGU6IGZ1bmN0aW9uIChjb250ZXh0LCBvcHRpb25zKSB7XG4gICAgICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICAgICAgICAgICAgdmFyIGN1c3RvbVJ1bGVzID0gb3B0aW9ucy5ydWxlcyB8fCB7fVxuICAgICAgICAgICAgdmFyIHVzZXJUZW1wbGF0ZXMgPSBvcHRpb25zLnRlbXBsYXRlc1xuICAgICAgICAgICAgdmFyIGVuYWJsZVJhbmRvbUZhbGxiYWNrID0gb3B0aW9ucy5yYW5kb21GYWxsYmFjayAhPT0gZmFsc2VcblxuICAgICAgICAgICAgaWYgKCF1c2VyVGVtcGxhdGVzIHx8IHR5cGVvZiB1c2VyVGVtcGxhdGVzICE9PSAnb2JqZWN0JyB8fCBPYmplY3Qua2V5cyh1c2VyVGVtcGxhdGVzKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tMdWEgUGVyc29uYWxpemVdIE5vIHRlbXBsYXRlcyBwcm92aWRlZC4gVGVtcGxhdGVzIG11c3QgYmUgcGFzc2VkIHZpYSBvcHRpb25zLnRlbXBsYXRlcycpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgdGVtcGxhdGU6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIGludGVudDogJ2RlZmF1bHQnLFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2U6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQ6IGNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiAnTm8gdGVtcGxhdGVzIHByb3ZpZGVkJ1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGludGVudCA9IGNvbnRleHQucHJpbWFyeUludGVudFxuICAgICAgICAgICAgdmFyIHNvdXJjZSA9ICdkZWZhdWx0J1xuXG4gICAgICAgICAgICBpZiAoY29udGV4dC5oYXNVVE0pIHtcbiAgICAgICAgICAgICAgICBzb3VyY2UgPSAndXRtJ1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjb250ZXh0LnJlZmVycmVyICYmIGNvbnRleHQucmVmZXJyZXIuY2F0ZWdvcnkgIT09ICdkaXJlY3QnKSB7XG4gICAgICAgICAgICAgICAgc291cmNlID0gJ3JlZmVycmVyJ1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKHZhciBydWxlS2V5IGluIGN1c3RvbVJ1bGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJ1bGUgPSBjdXN0b21SdWxlc1tydWxlS2V5XVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcnVsZS5tYXRjaCA9PT0gJ2Z1bmN0aW9uJyAmJiBydWxlLm1hdGNoKGNvbnRleHQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGludGVudCA9IHJ1bGUuaW50ZW50IHx8IHJ1bGVLZXlcbiAgICAgICAgICAgICAgICAgICAgc291cmNlID0gJ2N1c3RvbS1ydWxlJ1xuICAgICAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGludGVudCA9PT0gJ2RlZmF1bHQnICYmIHNvdXJjZSA9PT0gJ2RlZmF1bHQnICYmIGVuYWJsZVJhbmRvbUZhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJhbmRvbUludGVudCA9IGdldFJhbmRvbUZhbGxiYWNrSW50ZW50KHVzZXJUZW1wbGF0ZXMpXG4gICAgICAgICAgICAgICAgaWYgKHJhbmRvbUludGVudCkge1xuICAgICAgICAgICAgICAgICAgICBpbnRlbnQgPSByYW5kb21JbnRlbnRcbiAgICAgICAgICAgICAgICAgICAgc291cmNlID0gJ3JhbmRvbS1hYidcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJlY29yZCB2aXNpdCB0byBoaXN0b3J5IGlmIGF2YWlsYWJsZVxuICAgICAgICAgICAgaWYgKHJvb3QuTHVhV2VpZ2h0ZWRIaXN0b3J5ICYmIHR5cGVvZiByb290Lkx1YVdlaWdodGVkSGlzdG9yeS5yZWNvcmRWaXNpdCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHJvb3QuTHVhV2VpZ2h0ZWRIaXN0b3J5LnJlY29yZFZpc2l0KHtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dDogY29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgaW50ZW50OiBpbnRlbnQsXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkVmFyaWFudDogaW50ZW50LFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2U6IHNvdXJjZSxcbiAgICAgICAgICAgICAgICAgICAgYWlEZWNpc2lvbjogZmFsc2VcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHRlbXBsYXRlOiBnZXRUZW1wbGF0ZShpbnRlbnQsIHVzZXJUZW1wbGF0ZXMpLFxuICAgICAgICAgICAgICAgIGludGVudDogaW50ZW50LFxuICAgICAgICAgICAgICAgIHNvdXJjZTogc291cmNlLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IGNvbnRleHRcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogTWFpbiBkZWNpZGUgZnVuY3Rpb24gLSByb3V0ZXMgdG8gQUkgb3Igc3RhbmRhcmQgZW5naW5lXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjb250ZXh0IC0gVVRNIGNvbnRleHRcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSAtIENvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICAgICAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmVuYWJsZUFJXSAtIEVuYWJsZSBBSS1wb3dlcmVkIGRlY2lzaW9uc1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuYWlDb25maWddIC0gQUkgY29uZmlndXJhdGlvblxuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0fFByb21pc2U8T2JqZWN0Pn0gLSBEZWNpc2lvbiByZXN1bHRcbiAgICAgICAgICovXG4gICAgICAgIGRlY2lkZTogZnVuY3Rpb24gKGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG5cbiAgICAgICAgICAgIC8vIElmIEFJIGlzIGVuYWJsZWQgYW5kIGNvbmZpZ3VyZWQsIHRyeSBBSSBkZWNpc2lvbiBmaXJzdFxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZW5hYmxlQUkgJiYgb3B0aW9ucy5haUNvbmZpZyAmJiByb290Lkx1YUFJUGVyc29uYWxpemUpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXNcbiAgICAgICAgICAgICAgICB2YXIgYWlNb2R1bGUgPSByb290Lkx1YUFJUGVyc29uYWxpemVcbiAgICAgICAgICAgICAgICB2YXIgcmVhZGluZXNzID0gYWlNb2R1bGUuaXNSZWFkeShvcHRpb25zLmFpQ29uZmlnKVxuXG4gICAgICAgICAgICAgICAgaWYgKHJlYWRpbmVzcy5yZWFkeSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWlNb2R1bGUuZGVjaWRlKGNvbnRleHQsIG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZhbGxiYWNrID0gb3B0aW9ucy5haUNvbmZpZy5mYWxsYmFja1RvU3RhbmRhcmQgIT09IGZhbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignW0x1YSBQZXJzb25hbGl6ZV0gQUkgZmFpbGVkLCB1c2luZyBzdGFuZGFyZCBlbmdpbmU6JywgZXJyb3IubWVzc2FnZSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuc3RhbmRhcmREZWNpZGUoY29udGV4dCwgb3B0aW9ucylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIFBlcnNvbmFsaXplXSBBSSBub3QgcmVhZHk6JywgcmVhZGluZXNzLmVycm9yLCAnLSB1c2luZyBzdGFuZGFyZCBlbmdpbmUnKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RhbmRhcmREZWNpZGUoY29udGV4dCwgb3B0aW9ucylcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyA3LiBET00gQVBQTElDQVRJT04gKGV4dHJhY3RlZCBmb3IgcmV1c2UpXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgLyoqXG4gICAgICogQXBwbHkgYSBkZWNpc2lvbiB0byB0aGUgRE9NXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRlY2lzaW9uIC0gRGVjaXNpb24gb2JqZWN0IHsgdGVtcGxhdGUsIGludGVudCwgc291cmNlLCBjb250ZXh0IH1cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zXG4gICAgICogQHJldHVybnMge09iamVjdH0gLSBUaGUgZGVjaXNpb24gKHBhc3MtdGhyb3VnaClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcHBseURlY2lzaW9uVG9ET00oZGVjaXNpb24sIG9wdGlvbnMpIHtcbiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgICAgICAgdmFyIHRlbXBsYXRlID0gZGVjaXNpb24udGVtcGxhdGVcbiAgICAgICAgdmFyIGNvbnRleHQgPSBkZWNpc2lvbi5jb250ZXh0IHx8IHt9XG4gICAgICAgIHZhciBsb2cgPSBvcHRpb25zLmxvZyAhPT0gZmFsc2VcblxuICAgICAgICBpZiAoIXRlbXBsYXRlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tMdWEgUGVyc29uYWxpemVdIE5vIHRlbXBsYXRlIGluIGRlY2lzaW9uLCBza2lwcGluZyBET00gdXBkYXRlJylcbiAgICAgICAgICAgIHJldHVybiBkZWNpc2lvblxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNsb3RzID0gWydpbWFnZScsICdoZWFkbGluZScsICdzdWJoZWFkbGluZScsICdjdGFMYWJlbCcsICdjdGFMaW5rJ11cblxuICAgICAgICBzbG90cy5mb3JFYWNoKGZ1bmN0aW9uIChzbG90KSB7XG4gICAgICAgICAgICB2YXIgZWxlbWVudHMgPSBmaW5kUGVyc29uYWxpemVFbGVtZW50cyhzbG90KVxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBlbCA9IGVsZW1lbnRzW2ldXG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gdGVtcGxhdGVbc2xvdF1cbiAgICAgICAgICAgICAgICBpZiAoIXZhbHVlKSBjb250aW51ZVxuXG4gICAgICAgICAgICAgICAgaWYgKHNsb3QgPT09ICdpbWFnZScpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsLnRhZ05hbWUgPT09ICdJTUcnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbC5zcmMgPSB2YWx1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgZWwuYWx0ID0gdGVtcGxhdGUuaGVhZGxpbmUgfHwgJ1BlcnNvbmFsaXplZCBpbWFnZSdcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9ICd1cmwoJyArIHZhbHVlICsgJyknXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHNsb3QgPT09ICdjdGFMaW5rJykge1xuICAgICAgICAgICAgICAgICAgICBlbC5ocmVmID0gdmFsdWVcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzYWZlU2V0VGV4dChlbCwgdmFsdWUpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuXG4gICAgICAgIC8vIEFwcGx5IHRvIGRhdGEtcGVyc29uYWxpemU9XCJoZXJvXCIgZWxlbWVudHNcbiAgICAgICAgdmFyIGhlcm9FbGVtZW50cyA9IGZpbmRQZXJzb25hbGl6ZUVsZW1lbnRzKCdoZXJvJylcbiAgICAgICAgZm9yICh2YXIgaCA9IDA7IGggPCBoZXJvRWxlbWVudHMubGVuZ3RoOyBoKyspIHtcbiAgICAgICAgICAgIHZhciBoZXJvRWwgPSBoZXJvRWxlbWVudHNbaF1cbiAgICAgICAgICAgIGhlcm9FbC5zZXRBdHRyaWJ1dGUoJ2RhdGEtaW50ZW50JywgZGVjaXNpb24uaW50ZW50KVxuICAgICAgICAgICAgaGVyb0VsLnNldEF0dHJpYnV0ZSgnZGF0YS1zb3VyY2UnLCBkZWNpc2lvbi5zb3VyY2UpXG4gICAgICAgICAgICBpZiAodGVtcGxhdGUuaW1hZ2UgJiYgIWhlcm9FbC5xdWVyeVNlbGVjdG9yKCdbZGF0YS1wZXJzb25hbGl6ZT1cImltYWdlXCJdJykpIHtcbiAgICAgICAgICAgICAgICBoZXJvRWwuc3R5bGUuYmFja2dyb3VuZEltYWdlID0gJ3VybCgnICsgdGVtcGxhdGUuaW1hZ2UgKyAnKSdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsb2cgJiYgdHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnW0x1YSBQZXJzb25hbGl6ZV0gQXBwbGllZDonLCB7XG4gICAgICAgICAgICAgICAgaW50ZW50OiBkZWNpc2lvbi5pbnRlbnQsXG4gICAgICAgICAgICAgICAgc291cmNlOiBkZWNpc2lvbi5zb3VyY2UsXG4gICAgICAgICAgICAgICAgaGVhZGxpbmU6IHRlbXBsYXRlLmhlYWRsaW5lLFxuICAgICAgICAgICAgICAgIGhhc1VUTTogY29udGV4dC5oYXNVVE0sXG4gICAgICAgICAgICAgICAgdXRtUGFyYW1zOiBjb250ZXh0LnV0bSB8fCB7fSxcbiAgICAgICAgICAgICAgICBhaVBvd2VyZWQ6IGRlY2lzaW9uLnNvdXJjZSA9PT0gJ2FpJyB8fCBkZWNpc2lvbi5zb3VyY2UgPT09ICdhaS1jYWNoZWQnXG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRlY2lzaW9uXG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIDguIE1BSU4gUEVSU09OQUxJWkFUSU9OIEZVTkNUSU9OXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgLyoqXG4gICAgICogQXBwbHkgcGVyc29uYWxpemF0aW9uIHRvIHRoZSBwYWdlXG4gICAgICogU2NhbnMgZm9yIGRhdGEtcGVyc29uYWxpemUgYXR0cmlidXRlcyBhbmQgaW5qZWN0cyBjb250ZW50XG4gICAgICogU3VwcG9ydHMgQUktcG93ZXJlZCBkZWNpc2lvbnMgd2hlbiBlbmFibGVBSSBpcyB0cnVlXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIC0gQ29uZmlndXJhdGlvblxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5jb250ZXh0XSAtIFByZS1jb21wdXRlZCBjb250ZXh0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLnJ1bGVzXSAtIEN1c3RvbSBydWxlc1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zLnRlbXBsYXRlcyAtIFVzZXItcHJvdmlkZWQgdGVtcGxhdGVzIChSRVFVSVJFRClcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmVuYWJsZUFJXSAtIEVuYWJsZSBBSS1wb3dlcmVkIGRlY2lzaW9uc1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5haUNvbmZpZ10gLSBBSSBjb25maWd1cmF0aW9uXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5yYW5kb21GYWxsYmFja10gLSBFbmFibGUgcmFuZG9tIEEvQiAoZGVmYXVsdDogdHJ1ZSlcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxvZ10gLSBFbmFibGUgbG9nZ2luZyAoZGVmYXVsdDogdHJ1ZSlcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fFByb21pc2U8T2JqZWN0Pn0gLSBEZWNpc2lvbiByZXN1bHQgKFByb21pc2UgaWYgQUkgZW5hYmxlZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwZXJzb25hbGl6ZShvcHRpb25zKSB7XG4gICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG5cbiAgICAgICAgLy8gVGVtcGxhdGVzIGFyZSByZXF1aXJlZFxuICAgICAgICBpZiAoIW9wdGlvbnMudGVtcGxhdGVzIHx8IHR5cGVvZiBvcHRpb25zLnRlbXBsYXRlcyAhPT0gJ29iamVjdCcgfHwgT2JqZWN0LmtleXMob3B0aW9ucy50ZW1wbGF0ZXMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignW0x1YSBQZXJzb25hbGl6ZV0gVGVtcGxhdGVzIGFyZSByZXF1aXJlZC4gUHJvdmlkZSB0ZW1wbGF0ZXMgdmlhIG9wdGlvbnMudGVtcGxhdGVzJylcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdGVtcGxhdGU6IG51bGwsXG4gICAgICAgICAgICAgICAgaW50ZW50OiAnZGVmYXVsdCcsXG4gICAgICAgICAgICAgICAgc291cmNlOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IHt9LFxuICAgICAgICAgICAgICAgIGVycm9yOiAnTm8gdGVtcGxhdGVzIHByb3ZpZGVkJ1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNvbnRleHQgPSBvcHRpb25zLmNvbnRleHQgfHwgZ2V0Q29udGV4dChvcHRpb25zKVxuICAgICAgICB2YXIgZGVjaXNpb24gPSBEZWNpc2lvbkVuZ2luZS5kZWNpZGUoY29udGV4dCwgb3B0aW9ucylcblxuICAgICAgICAvLyBJZiBkZWNpc2lvbiBpcyBhIFByb21pc2UgKEFJIHBhdGgpLCBoYW5kbGUgYXN5bmNcbiAgICAgICAgaWYgKGRlY2lzaW9uICYmIHR5cGVvZiBkZWNpc2lvbi50aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gZGVjaXNpb24udGhlbihmdW5jdGlvbiAoYWlEZWNpc2lvbikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseURlY2lzaW9uVG9ET00oYWlEZWNpc2lvbiwgb3B0aW9ucylcbiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tMdWEgUGVyc29uYWxpemVdIEFJIGRlY2lzaW9uIGZhaWxlZCwgdXNpbmcgc3RhbmRhcmQ6JywgZXJyLm1lc3NhZ2UpXG4gICAgICAgICAgICAgICAgdmFyIGZhbGxiYWNrRGVjaXNpb24gPSBEZWNpc2lvbkVuZ2luZS5zdGFuZGFyZERlY2lkZShjb250ZXh0LCBvcHRpb25zKVxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseURlY2lzaW9uVG9ET00oZmFsbGJhY2tEZWNpc2lvbiwgb3B0aW9ucylcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cblxuICAgICAgICAvLyBTeW5jaHJvbm91cyBwYXRoXG4gICAgICAgIHJldHVybiBhcHBseURlY2lzaW9uVG9ET00oZGVjaXNpb24sIG9wdGlvbnMpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXN5bmMgcGVyc29uYWxpemF0aW9uIHdpdGggdGltZW91dCBmYWxsYmFja1xuICAgICAqIEF1dG9tYXRpY2FsbHkgaGFuZGxlcyBBSSBkZWNpc2lvbnMgKHdoaWNoIGFyZSBhbHdheXMgYXN5bmMpXG4gICAgICovXG4gICAgZnVuY3Rpb24gcGVyc29uYWxpemVBc3luYyhvcHRpb25zKSB7XG4gICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG4gICAgICAgIHJldHVybiBnZXRDb250ZXh0QXN5bmMob3B0aW9ucykudGhlbihmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICAgICAgb3B0aW9ucy5jb250ZXh0ID0gY29udGV4dFxuICAgICAgICAgICAgcmV0dXJuIHBlcnNvbmFsaXplKG9wdGlvbnMpXG4gICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKGRlY2lzaW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gZGVjaXNpb25cbiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIFBlcnNvbmFsaXplXSBBc3luYyBlcnJvciwgdXNpbmcgZGVmYXVsdDonLCBlcnIpXG4gICAgICAgICAgICB2YXIgY3R4ID0gZ2V0Q29udGV4dChvcHRpb25zKVxuICAgICAgICAgICAgdmFyIGZhbGxiYWNrID0gRGVjaXNpb25FbmdpbmUuc3RhbmRhcmREZWNpZGUoY3R4LCB7IHRlbXBsYXRlczogb3B0aW9ucy50ZW1wbGF0ZXMgfSlcbiAgICAgICAgICAgIHJldHVybiBhcHBseURlY2lzaW9uVG9ET00oZmFsbGJhY2ssIG9wdGlvbnMpXG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIDkuIEFVVE8tSU5JVElBTElaQVRJT05cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICAvKipcbiAgICAgKiBBdXRvLWluaXRpYWxpemUgcGVyc29uYWxpemF0aW9uIG9uIERPTUNvbnRlbnRMb2FkZWRcbiAgICAgKiBPbmx5IHJ1bnMgaWYgZGF0YS1wZXJzb25hbGl6ZSBlbGVtZW50cyBleGlzdCBpbiB0aGUgRE9NXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXV0b0luaXQob3B0aW9ucykge1xuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuXG4gICAgICAgIGZ1bmN0aW9uIHJ1bigpIHtcbiAgICAgICAgICAgIHZhciBlbGVtZW50cyA9IGZpbmRQZXJzb25hbGl6ZUVsZW1lbnRzKClcbiAgICAgICAgICAgIGlmIChlbGVtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgcGVyc29uYWxpemUob3B0aW9ucylcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBpZiAoZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnKSB7XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIHJ1bilcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcnVuKClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyAxMC4gUFVCTElDIEFQSVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIHZhciBMdWFVVE1QZXJzb25hbGl6ZSA9IHtcbiAgICAgICAgLy8gVVRNIGV4dHJhY3Rpb25cbiAgICAgICAgZXh0cmFjdFVUTVBhcmFtczogZXh0cmFjdFVUTVBhcmFtcyxcbiAgICAgICAgc2FuaXRpemVQYXJhbTogc2FuaXRpemVQYXJhbSxcbiAgICAgICAgZGV0ZWN0UmVmZXJyZXI6IGRldGVjdFJlZmVycmVyLFxuICAgICAgICBnZXRVc2VyQWdlbnRJbmZvOiBnZXRVc2VyQWdlbnRJbmZvLFxuICAgICAgICBnZXRDb250ZXh0OiBnZXRDb250ZXh0LFxuICAgICAgICBnZXRDb250ZXh0QXN5bmM6IGdldENvbnRleHRBc3luYyxcbiAgICAgICAgaW5mZXJJbnRlbnQ6IGluZmVySW50ZW50LFxuXG4gICAgICAgIC8vIFNhbml0aXplclxuICAgICAgICBzYW5pdGl6ZXI6IFNhbml0aXplcixcbiAgICAgICAgc2FuaXRpemVIVE1MOiBmdW5jdGlvbiAoaHRtbCkgeyByZXR1cm4gU2FuaXRpemVyLnNhbml0aXplKGh0bWwpIH0sXG5cbiAgICAgICAgLy8gRE9NIGhlbHBlcnNcbiAgICAgICAgc2FmZVNldFRleHQ6IHNhZmVTZXRUZXh0LFxuICAgICAgICBzYWZlU2V0SFRNTDogc2FmZVNldEhUTUwsXG4gICAgICAgIGZpbmRFbGVtZW50czogZmluZFBlcnNvbmFsaXplRWxlbWVudHMsXG4gICAgICAgIGFwcGx5RGVjaXNpb25Ub0RPTTogYXBwbHlEZWNpc2lvblRvRE9NLFxuXG4gICAgICAgIC8vIFRlbXBsYXRlcyAodXNlcnMgbXVzdCBwcm92aWRlIHRoZWlyIG93biB2aWEgb3B0aW9ucy50ZW1wbGF0ZXMpXG4gICAgICAgIGdldFRlbXBsYXRlOiBnZXRUZW1wbGF0ZSxcblxuICAgICAgICAvLyBEZWNpc2lvbiBlbmdpbmVcbiAgICAgICAgZW5naW5lOiBEZWNpc2lvbkVuZ2luZSxcbiAgICAgICAgY2hvb3NlV2VpZ2h0ZWRSYW5kb206IGNob29zZVdlaWdodGVkUmFuZG9tLFxuICAgICAgICBnZXRSYW5kb21GYWxsYmFja0ludGVudDogZ2V0UmFuZG9tRmFsbGJhY2tJbnRlbnQsXG5cbiAgICAgICAgLy8gTWFpbiBBUElcbiAgICAgICAgcGVyc29uYWxpemU6IHBlcnNvbmFsaXplLFxuICAgICAgICBwZXJzb25hbGl6ZUFzeW5jOiBwZXJzb25hbGl6ZUFzeW5jLFxuICAgICAgICBhdXRvSW5pdDogYXV0b0luaXQsXG5cbiAgICAgICAgLy8gQ29uc3RhbnRzXG4gICAgICAgIFVUTV9QQVJBTVM6IFVUTV9QQVJBTVMsXG4gICAgICAgIFVUTV9USU1FT1VUX01TOiBVVE1fVElNRU9VVF9NUyxcbiAgICAgICAgUkVGRVJSRVJfUEFUVEVSTlM6IFJFRkVSUkVSX1BBVFRFUk5TLFxuICAgICAgICBSRUZFUlJFUl9DQVRFR09SSUVTOiBSRUZFUlJFUl9DQVRFR09SSUVTXG4gICAgfVxuXG4gICAgLy8gUmVnaXN0ZXIgZ2xvYmFsbHlcbiAgICByb290Lkx1YVVUTVBlcnNvbmFsaXplID0gTHVhVVRNUGVyc29uYWxpemVcblxuICAgIC8vIEFsc28gcmVnaXN0ZXIgaW5kaXZpZHVhbCBtb2R1bGVzIGZvciBjb21wYXRpYmlsaXR5XG4gICAgaWYgKCFyb290Lkx1YVVUTSkge1xuICAgICAgICByb290Lkx1YVVUTSA9IHtcbiAgICAgICAgICAgIGV4dHJhY3RVVE1QYXJhbXM6IGV4dHJhY3RVVE1QYXJhbXMsXG4gICAgICAgICAgICBzYW5pdGl6ZVBhcmFtOiBzYW5pdGl6ZVBhcmFtLFxuICAgICAgICAgICAgZGV0ZWN0UmVmZXJyZXI6IGRldGVjdFJlZmVycmVyLFxuICAgICAgICAgICAgZ2V0VXNlckFnZW50SW5mbzogZ2V0VXNlckFnZW50SW5mbyxcbiAgICAgICAgICAgIGdldENvbnRleHQ6IGdldENvbnRleHQsXG4gICAgICAgICAgICBnZXRDb250ZXh0QXN5bmM6IGdldENvbnRleHRBc3luYyxcbiAgICAgICAgICAgIGluZmVySW50ZW50OiBpbmZlckludGVudCxcbiAgICAgICAgICAgIFVUTV9QQVJBTVM6IFVUTV9QQVJBTVMsXG4gICAgICAgICAgICBVVE1fVElNRU9VVF9NUzogVVRNX1RJTUVPVVRfTVMsXG4gICAgICAgICAgICBSRUZFUlJFUl9QQVRURVJOUzogUkVGRVJSRVJfUEFUVEVSTlMsXG4gICAgICAgICAgICBSRUZFUlJFUl9DQVRFR09SSUVTOiBSRUZFUlJFUl9DQVRFR09SSUVTXG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFyb290Lkx1YVBlcnNvbmFsaXplKSB7XG4gICAgICAgIHJvb3QuTHVhUGVyc29uYWxpemUgPSB7XG4gICAgICAgICAgICBzYW5pdGl6ZXI6IFNhbml0aXplcixcbiAgICAgICAgICAgIHNhbml0aXplSFRNTDogZnVuY3Rpb24gKGh0bWwpIHsgcmV0dXJuIFNhbml0aXplci5zYW5pdGl6ZShodG1sKSB9LFxuICAgICAgICAgICAgc2FmZVNldFRleHQ6IHNhZmVTZXRUZXh0LFxuICAgICAgICAgICAgc2FmZVNldEhUTUw6IHNhZmVTZXRIVE1MLFxuICAgICAgICAgICAgZmluZEVsZW1lbnRzOiBmaW5kUGVyc29uYWxpemVFbGVtZW50cyxcbiAgICAgICAgICAgIGFwcGx5RGVjaXNpb25Ub0RPTTogYXBwbHlEZWNpc2lvblRvRE9NLFxuICAgICAgICAgICAgZ2V0VGVtcGxhdGU6IGdldFRlbXBsYXRlLFxuICAgICAgICAgICAgZW5naW5lOiBEZWNpc2lvbkVuZ2luZSxcbiAgICAgICAgICAgIHBlcnNvbmFsaXplOiBwZXJzb25hbGl6ZSxcbiAgICAgICAgICAgIHBlcnNvbmFsaXplQXN5bmM6IHBlcnNvbmFsaXplQXN5bmMsXG4gICAgICAgICAgICBhdXRvSW5pdDogYXV0b0luaXQsXG4gICAgICAgICAgICBjaG9vc2VXZWlnaHRlZFJhbmRvbTogY2hvb3NlV2VpZ2h0ZWRSYW5kb20sXG4gICAgICAgICAgICBnZXRSYW5kb21GYWxsYmFja0ludGVudDogZ2V0UmFuZG9tRmFsbGJhY2tJbnRlbnRcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vdGU6IGF1dG9Jbml0KCkgaXMgTk9UIGNhbGxlZCBhdXRvbWF0aWNhbGx5IGJlY2F1c2UgdGVtcGxhdGVzIGFyZSByZXF1aXJlZFxuICAgIC8vIFVzZXJzIG11c3QgY2FsbCBwZXJzb25hbGl6ZSgpIG9yIHBlcnNvbmFsaXplQXN5bmMoKSB3aXRoIHRoZWlyIHRlbXBsYXRlc1xuXG59KSh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdGhpcylcbiJdLCJtYXBwaW5ncyI6Ijs7OztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFDLENBQUMsVUFBVUEsSUFBSSxFQUFFO0VBQ2QsWUFBWTs7RUFFWjtFQUNBO0VBQ0E7RUFFQSxJQUFJQyxjQUFjLEdBQUcsSUFBSTtFQUV6QixJQUFJQyxVQUFVLEdBQUcsQ0FBQyxZQUFZLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsVUFBVSxDQUFD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
|