@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
package/build/es5/utm.js
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UTM Parameter Extraction & Context Detection
|
|
5
|
+
* Uses native URLSearchParams API for extracting UTM parameters
|
|
6
|
+
* and document.referrer/navigator.userAgent for context inference
|
|
7
|
+
*
|
|
8
|
+
* No ES6 imports - self-contained IIFE that registers on window.LuaUTM
|
|
9
|
+
* Can be loaded standalone via <script> tag or bundled by Rollup
|
|
10
|
+
*/
|
|
11
|
+
;
|
|
12
|
+
(function (root) {
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
// Default timeout for async operations (1 second max as recommended)
|
|
16
|
+
var UTM_TIMEOUT_MS = 1000;
|
|
17
|
+
|
|
18
|
+
// Allowed UTM parameter names
|
|
19
|
+
var UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
|
|
20
|
+
|
|
21
|
+
// Referrer type patterns
|
|
22
|
+
var REFERRER_PATTERNS = {
|
|
23
|
+
google: /google\./i,
|
|
24
|
+
bing: /bing\./i,
|
|
25
|
+
yahoo: /yahoo\./i,
|
|
26
|
+
duckduckgo: /duckduckgo\./i,
|
|
27
|
+
facebook: /facebook\.com|fb\.com/i,
|
|
28
|
+
twitter: /twitter\.com|t\.co|x\.com/i,
|
|
29
|
+
instagram: /instagram\.com/i,
|
|
30
|
+
linkedin: /linkedin\.com/i,
|
|
31
|
+
pinterest: /pinterest\./i,
|
|
32
|
+
tiktok: /tiktok\.com/i,
|
|
33
|
+
youtube: /youtube\.com|youtu\.be/i,
|
|
34
|
+
reddit: /reddit\.com/i
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Referrer category mapping
|
|
38
|
+
var REFERRER_CATEGORIES = {
|
|
39
|
+
search: ['google', 'bing', 'yahoo', 'duckduckgo'],
|
|
40
|
+
social: ['facebook', 'twitter', 'instagram', 'linkedin', 'pinterest', 'tiktok', 'youtube', 'reddit']
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Safely extracts UTM parameters from URL using native URLSearchParams API
|
|
45
|
+
* @param {string} [url] - URL to parse (defaults to window.location.search)
|
|
46
|
+
* @returns {Object} - Object containing UTM parameters
|
|
47
|
+
*/
|
|
48
|
+
function extractUTMParams(url) {
|
|
49
|
+
var result = {};
|
|
50
|
+
try {
|
|
51
|
+
var searchString = url || (typeof window !== 'undefined' ? window.location.search : '');
|
|
52
|
+
if (!searchString) {
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Use native URLSearchParams API
|
|
57
|
+
var params = new URLSearchParams(searchString);
|
|
58
|
+
UTM_PARAMS.forEach(function (param) {
|
|
59
|
+
var value = params.get(param);
|
|
60
|
+
if (value) {
|
|
61
|
+
// Sanitize: only allow alphanumeric, dashes, underscores
|
|
62
|
+
result[param] = sanitizeParam(value);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
} catch (e) {
|
|
66
|
+
// Fallback: return empty object on any error
|
|
67
|
+
console.warn('[Lua UTM] Error extracting UTM params:', e);
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sanitize parameter value to prevent XSS
|
|
74
|
+
* Only allows alphanumeric, dashes, underscores, and spaces
|
|
75
|
+
* @param {string} value - Raw parameter value
|
|
76
|
+
* @returns {string} - Sanitized value
|
|
77
|
+
*/
|
|
78
|
+
function sanitizeParam(value) {
|
|
79
|
+
if (typeof value !== 'string') return '';
|
|
80
|
+
// Remove any HTML tags and special characters
|
|
81
|
+
return value.replace(/<[^>]*>/g, '') // Remove HTML tags
|
|
82
|
+
.replace(/[^\w\s\-_.]/g, '') // Only allow safe characters
|
|
83
|
+
.substring(0, 100) // Limit length
|
|
84
|
+
.trim();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Detect referrer type from document.referrer
|
|
89
|
+
* @returns {Object} - { source: string, category: 'search'|'social'|'email'|'direct'|'other' }
|
|
90
|
+
*/
|
|
91
|
+
function detectReferrer() {
|
|
92
|
+
var result = {
|
|
93
|
+
source: 'direct',
|
|
94
|
+
category: 'direct',
|
|
95
|
+
url: ''
|
|
96
|
+
};
|
|
97
|
+
try {
|
|
98
|
+
if (typeof document === 'undefined' || !document.referrer) {
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
result.url = document.referrer;
|
|
102
|
+
|
|
103
|
+
// Check for email patterns in referrer
|
|
104
|
+
if (/mail\.|email\.|newsletter/i.test(document.referrer)) {
|
|
105
|
+
result.source = 'email';
|
|
106
|
+
result.category = 'email';
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Check against known patterns
|
|
111
|
+
for (var source in REFERRER_PATTERNS) {
|
|
112
|
+
if (REFERRER_PATTERNS[source].test(document.referrer)) {
|
|
113
|
+
result.source = source;
|
|
114
|
+
|
|
115
|
+
// Determine category
|
|
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
|
+
|
|
126
|
+
// Unknown external referrer
|
|
127
|
+
result.source = 'external';
|
|
128
|
+
result.category = 'other';
|
|
129
|
+
} catch (e) {
|
|
130
|
+
console.warn('[Lua UTM] Error detecting referrer:', e);
|
|
131
|
+
}
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get user agent info (for device/browser detection)
|
|
137
|
+
* @returns {Object} - User agent metadata
|
|
138
|
+
*/
|
|
139
|
+
function getUserAgentInfo() {
|
|
140
|
+
var result = {
|
|
141
|
+
raw: '',
|
|
142
|
+
isMobile: false,
|
|
143
|
+
isTablet: false,
|
|
144
|
+
isDesktop: true
|
|
145
|
+
};
|
|
146
|
+
try {
|
|
147
|
+
if (typeof navigator === 'undefined' || !navigator.userAgent) {
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
result.raw = navigator.userAgent;
|
|
151
|
+
|
|
152
|
+
// Mobile detection
|
|
153
|
+
result.isMobile = /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
154
|
+
result.isTablet = /iPad|Android(?!.*Mobile)/i.test(navigator.userAgent);
|
|
155
|
+
result.isDesktop = !result.isMobile && !result.isTablet;
|
|
156
|
+
} catch (e) {
|
|
157
|
+
console.warn('[Lua UTM] Error getting user agent:', e);
|
|
158
|
+
}
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Get full personalization context
|
|
164
|
+
* Combines UTM params, referrer info, and user agent
|
|
165
|
+
* @param {Object} [options] - Configuration options
|
|
166
|
+
* @param {string} [options.url] - Custom URL to parse
|
|
167
|
+
* @returns {Object} - Complete context object
|
|
168
|
+
*/
|
|
169
|
+
function getContext(options) {
|
|
170
|
+
options = options || {};
|
|
171
|
+
var context = {
|
|
172
|
+
utm: extractUTMParams(options.url),
|
|
173
|
+
referrer: detectReferrer(),
|
|
174
|
+
userAgent: getUserAgentInfo(),
|
|
175
|
+
timestamp: Date.now(),
|
|
176
|
+
hasUTM: false,
|
|
177
|
+
primaryIntent: 'unknown'
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// Determine if we have UTM data
|
|
181
|
+
context.hasUTM = Object.keys(context.utm).length > 0;
|
|
182
|
+
|
|
183
|
+
// Infer primary intent
|
|
184
|
+
context.primaryIntent = inferIntent(context);
|
|
185
|
+
return context;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Infer user intent from context
|
|
190
|
+
* Priority: UTM campaign > UTM source > Referrer category
|
|
191
|
+
* @param {Object} context - Full context object
|
|
192
|
+
* @returns {string} - Inferred intent key
|
|
193
|
+
*/
|
|
194
|
+
function inferIntent(context) {
|
|
195
|
+
// Priority 1: UTM campaign tells us the specific intent
|
|
196
|
+
if (context.utm.utm_campaign) {
|
|
197
|
+
var campaign = context.utm.utm_campaign.toLowerCase();
|
|
198
|
+
if (/sale|discount|offer|promo/i.test(campaign)) return 'price-focused';
|
|
199
|
+
if (/gaming|game|esport/i.test(campaign)) return 'gaming';
|
|
200
|
+
if (/work|office|professional|productivity/i.test(campaign)) return 'professional';
|
|
201
|
+
if (/creative|design|art|studio/i.test(campaign)) return 'creative';
|
|
202
|
+
if (/brand|story|about/i.test(campaign)) return 'brand-story';
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Priority 2: UTM source can indicate intent
|
|
206
|
+
if (context.utm.utm_source) {
|
|
207
|
+
var source = context.utm.utm_source.toLowerCase();
|
|
208
|
+
if (/google|bing|yahoo/i.test(source)) return 'search-optimized';
|
|
209
|
+
if (/facebook|instagram|tiktok/i.test(source)) return 'social-visual';
|
|
210
|
+
if (/twitter|x$/i.test(source)) return 'social-brief';
|
|
211
|
+
if (/email|newsletter/i.test(source)) return 'returning-user';
|
|
212
|
+
if (/youtube/i.test(source)) return 'video-engaged';
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Priority 3: Referrer category
|
|
216
|
+
if (context.referrer.category === 'search') return 'search-optimized';
|
|
217
|
+
if (context.referrer.category === 'social') return 'social-visual';
|
|
218
|
+
if (context.referrer.category === 'email') return 'returning-user';
|
|
219
|
+
|
|
220
|
+
// Default
|
|
221
|
+
return 'default';
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Get context with timeout fallback
|
|
226
|
+
* Returns default context if operation takes too long
|
|
227
|
+
* @param {Object} [options] - Configuration options
|
|
228
|
+
* @param {number} [options.timeout] - Timeout in ms (default: 1000)
|
|
229
|
+
* @returns {Promise<Object>} - Context object
|
|
230
|
+
*/
|
|
231
|
+
function getContextAsync(options) {
|
|
232
|
+
options = options || {};
|
|
233
|
+
var timeout = options.timeout || UTM_TIMEOUT_MS;
|
|
234
|
+
return new Promise(function (resolve) {
|
|
235
|
+
var timer = setTimeout(function () {
|
|
236
|
+
// Timeout: return default context
|
|
237
|
+
resolve({
|
|
238
|
+
utm: {},
|
|
239
|
+
referrer: {
|
|
240
|
+
source: 'direct',
|
|
241
|
+
category: 'direct',
|
|
242
|
+
url: ''
|
|
243
|
+
},
|
|
244
|
+
userAgent: {
|
|
245
|
+
raw: '',
|
|
246
|
+
isMobile: false,
|
|
247
|
+
isTablet: false,
|
|
248
|
+
isDesktop: true
|
|
249
|
+
},
|
|
250
|
+
timestamp: Date.now(),
|
|
251
|
+
hasUTM: false,
|
|
252
|
+
primaryIntent: 'default',
|
|
253
|
+
timedOut: true
|
|
254
|
+
});
|
|
255
|
+
}, timeout);
|
|
256
|
+
try {
|
|
257
|
+
var context = getContext(options);
|
|
258
|
+
clearTimeout(timer);
|
|
259
|
+
context.timedOut = false;
|
|
260
|
+
resolve(context);
|
|
261
|
+
} catch (e) {
|
|
262
|
+
clearTimeout(timer);
|
|
263
|
+
resolve({
|
|
264
|
+
utm: {},
|
|
265
|
+
referrer: {
|
|
266
|
+
source: 'direct',
|
|
267
|
+
category: 'direct',
|
|
268
|
+
url: ''
|
|
269
|
+
},
|
|
270
|
+
userAgent: {
|
|
271
|
+
raw: '',
|
|
272
|
+
isMobile: false,
|
|
273
|
+
isTablet: false,
|
|
274
|
+
isDesktop: true
|
|
275
|
+
},
|
|
276
|
+
timestamp: Date.now(),
|
|
277
|
+
hasUTM: false,
|
|
278
|
+
primaryIntent: 'default',
|
|
279
|
+
error: e.message
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// --- Public API ---
|
|
286
|
+
// Register on the global root (window in browser)
|
|
287
|
+
var LuaUTM = {
|
|
288
|
+
extractUTMParams: extractUTMParams,
|
|
289
|
+
sanitizeParam: sanitizeParam,
|
|
290
|
+
detectReferrer: detectReferrer,
|
|
291
|
+
getUserAgentInfo: getUserAgentInfo,
|
|
292
|
+
getContext: getContext,
|
|
293
|
+
getContextAsync: getContextAsync,
|
|
294
|
+
inferIntent: inferIntent,
|
|
295
|
+
UTM_PARAMS: UTM_PARAMS,
|
|
296
|
+
UTM_TIMEOUT_MS: UTM_TIMEOUT_MS,
|
|
297
|
+
REFERRER_PATTERNS: REFERRER_PATTERNS,
|
|
298
|
+
REFERRER_CATEGORIES: REFERRER_CATEGORIES
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// Expose globally
|
|
302
|
+
root.LuaUTM = LuaUTM;
|
|
303
|
+
})(typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : void 0);
|
|
304
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJyb290IiwiVVRNX1RJTUVPVVRfTVMiLCJVVE1fUEFSQU1TIiwiUkVGRVJSRVJfUEFUVEVSTlMiLCJnb29nbGUiLCJiaW5nIiwieWFob28iLCJkdWNrZHVja2dvIiwiZmFjZWJvb2siLCJ0d2l0dGVyIiwiaW5zdGFncmFtIiwibGlua2VkaW4iLCJwaW50ZXJlc3QiLCJ0aWt0b2siLCJ5b3V0dWJlIiwicmVkZGl0IiwiUkVGRVJSRVJfQ0FURUdPUklFUyIsInNlYXJjaCIsInNvY2lhbCIsImV4dHJhY3RVVE1QYXJhbXMiLCJ1cmwiLCJyZXN1bHQiLCJzZWFyY2hTdHJpbmciLCJ3aW5kb3ciLCJsb2NhdGlvbiIsInBhcmFtcyIsIlVSTFNlYXJjaFBhcmFtcyIsImZvckVhY2giLCJwYXJhbSIsInZhbHVlIiwiZ2V0Iiwic2FuaXRpemVQYXJhbSIsImUiLCJjb25zb2xlIiwid2FybiIsInJlcGxhY2UiLCJzdWJzdHJpbmciLCJ0cmltIiwiZGV0ZWN0UmVmZXJyZXIiLCJzb3VyY2UiLCJjYXRlZ29yeSIsImRvY3VtZW50IiwicmVmZXJyZXIiLCJ0ZXN0IiwiaW5kZXhPZiIsImdldFVzZXJBZ2VudEluZm8iLCJyYXciLCJpc01vYmlsZSIsImlzVGFibGV0IiwiaXNEZXNrdG9wIiwibmF2aWdhdG9yIiwidXNlckFnZW50IiwiZ2V0Q29udGV4dCIsIm9wdGlvbnMiLCJjb250ZXh0IiwidXRtIiwidGltZXN0YW1wIiwiRGF0ZSIsIm5vdyIsImhhc1VUTSIsInByaW1hcnlJbnRlbnQiLCJPYmplY3QiLCJrZXlzIiwibGVuZ3RoIiwiaW5mZXJJbnRlbnQiLCJ1dG1fY2FtcGFpZ24iLCJjYW1wYWlnbiIsInRvTG93ZXJDYXNlIiwidXRtX3NvdXJjZSIsImdldENvbnRleHRBc3luYyIsInRpbWVvdXQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInRpbWVyIiwic2V0VGltZW91dCIsInRpbWVkT3V0IiwiY2xlYXJUaW1lb3V0IiwiZXJyb3IiLCJtZXNzYWdlIiwiTHVhVVRNIiwiZ2xvYmFsIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0bS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJcbi8qKlxuICogVVRNIFBhcmFtZXRlciBFeHRyYWN0aW9uICYgQ29udGV4dCBEZXRlY3Rpb25cbiAqIFVzZXMgbmF0aXZlIFVSTFNlYXJjaFBhcmFtcyBBUEkgZm9yIGV4dHJhY3RpbmcgVVRNIHBhcmFtZXRlcnNcbiAqIGFuZCBkb2N1bWVudC5yZWZlcnJlci9uYXZpZ2F0b3IudXNlckFnZW50IGZvciBjb250ZXh0IGluZmVyZW5jZVxuICpcbiAqIE5vIEVTNiBpbXBvcnRzIC0gc2VsZi1jb250YWluZWQgSUlGRSB0aGF0IHJlZ2lzdGVycyBvbiB3aW5kb3cuTHVhVVRNXG4gKiBDYW4gYmUgbG9hZGVkIHN0YW5kYWxvbmUgdmlhIDxzY3JpcHQ+IHRhZyBvciBidW5kbGVkIGJ5IFJvbGx1cFxuICovXG47KGZ1bmN0aW9uIChyb290KSB7XG4gICAgJ3VzZSBzdHJpY3QnXG5cbiAgICAvLyBEZWZhdWx0IHRpbWVvdXQgZm9yIGFzeW5jIG9wZXJhdGlvbnMgKDEgc2Vjb25kIG1heCBhcyByZWNvbW1lbmRlZClcbiAgICB2YXIgVVRNX1RJTUVPVVRfTVMgPSAxMDAwXG5cbiAgICAvLyBBbGxvd2VkIFVUTSBwYXJhbWV0ZXIgbmFtZXNcbiAgICB2YXIgVVRNX1BBUkFNUyA9IFsndXRtX3NvdXJjZScsICd1dG1fbWVkaXVtJywgJ3V0bV9jYW1wYWlnbicsICd1dG1fY29udGVudCcsICd1dG1fdGVybSddXG5cbiAgICAvLyBSZWZlcnJlciB0eXBlIHBhdHRlcm5zXG4gICAgdmFyIFJFRkVSUkVSX1BBVFRFUk5TID0ge1xuICAgICAgICBnb29nbGU6IC9nb29nbGVcXC4vaSxcbiAgICAgICAgYmluZzogL2JpbmdcXC4vaSxcbiAgICAgICAgeWFob286IC95YWhvb1xcLi9pLFxuICAgICAgICBkdWNrZHVja2dvOiAvZHVja2R1Y2tnb1xcLi9pLFxuICAgICAgICBmYWNlYm9vazogL2ZhY2Vib29rXFwuY29tfGZiXFwuY29tL2ksXG4gICAgICAgIHR3aXR0ZXI6IC90d2l0dGVyXFwuY29tfHRcXC5jb3x4XFwuY29tL2ksXG4gICAgICAgIGluc3RhZ3JhbTogL2luc3RhZ3JhbVxcLmNvbS9pLFxuICAgICAgICBsaW5rZWRpbjogL2xpbmtlZGluXFwuY29tL2ksXG4gICAgICAgIHBpbnRlcmVzdDogL3BpbnRlcmVzdFxcLi9pLFxuICAgICAgICB0aWt0b2s6IC90aWt0b2tcXC5jb20vaSxcbiAgICAgICAgeW91dHViZTogL3lvdXR1YmVcXC5jb218eW91dHVcXC5iZS9pLFxuICAgICAgICByZWRkaXQ6IC9yZWRkaXRcXC5jb20vaVxuICAgIH1cblxuICAgIC8vIFJlZmVycmVyIGNhdGVnb3J5IG1hcHBpbmdcbiAgICB2YXIgUkVGRVJSRVJfQ0FURUdPUklFUyA9IHtcbiAgICAgICAgc2VhcmNoOiBbJ2dvb2dsZScsICdiaW5nJywgJ3lhaG9vJywgJ2R1Y2tkdWNrZ28nXSxcbiAgICAgICAgc29jaWFsOiBbJ2ZhY2Vib29rJywgJ3R3aXR0ZXInLCAnaW5zdGFncmFtJywgJ2xpbmtlZGluJywgJ3BpbnRlcmVzdCcsICd0aWt0b2snLCAneW91dHViZScsICdyZWRkaXQnXVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNhZmVseSBleHRyYWN0cyBVVE0gcGFyYW1ldGVycyBmcm9tIFVSTCB1c2luZyBuYXRpdmUgVVJMU2VhcmNoUGFyYW1zIEFQSVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbdXJsXSAtIFVSTCB0byBwYXJzZSAoZGVmYXVsdHMgdG8gd2luZG93LmxvY2F0aW9uLnNlYXJjaClcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSAtIE9iamVjdCBjb250YWluaW5nIFVUTSBwYXJhbWV0ZXJzXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXh0cmFjdFVUTVBhcmFtcyh1cmwpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZhciBzZWFyY2hTdHJpbmcgPSB1cmwgfHwgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93LmxvY2F0aW9uLnNlYXJjaCA6ICcnKVxuXG4gICAgICAgICAgICBpZiAoIXNlYXJjaFN0cmluZykge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVXNlIG5hdGl2ZSBVUkxTZWFyY2hQYXJhbXMgQVBJXG4gICAgICAgICAgICB2YXIgcGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyhzZWFyY2hTdHJpbmcpXG5cbiAgICAgICAgICAgIFVUTV9QQVJBTVMuZm9yRWFjaChmdW5jdGlvbiAocGFyYW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwYXJhbXMuZ2V0KHBhcmFtKVxuICAgICAgICAgICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTYW5pdGl6ZTogb25seSBhbGxvdyBhbHBoYW51bWVyaWMsIGRhc2hlcywgdW5kZXJzY29yZXNcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W3BhcmFtXSA9IHNhbml0aXplUGFyYW0odmFsdWUpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gRmFsbGJhY2s6IHJldHVybiBlbXB0eSBvYmplY3Qgb24gYW55IGVycm9yXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tMdWEgVVRNXSBFcnJvciBleHRyYWN0aW5nIFVUTSBwYXJhbXM6JywgZSlcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTYW5pdGl6ZSBwYXJhbWV0ZXIgdmFsdWUgdG8gcHJldmVudCBYU1NcbiAgICAgKiBPbmx5IGFsbG93cyBhbHBoYW51bWVyaWMsIGRhc2hlcywgdW5kZXJzY29yZXMsIGFuZCBzcGFjZXNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBSYXcgcGFyYW1ldGVyIHZhbHVlXG4gICAgICogQHJldHVybnMge3N0cmluZ30gLSBTYW5pdGl6ZWQgdmFsdWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzYW5pdGl6ZVBhcmFtKHZhbHVlKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSByZXR1cm4gJydcbiAgICAgICAgLy8gUmVtb3ZlIGFueSBIVE1MIHRhZ3MgYW5kIHNwZWNpYWwgY2hhcmFjdGVyc1xuICAgICAgICByZXR1cm4gdmFsdWVcbiAgICAgICAgICAgIC5yZXBsYWNlKC88W14+XSo+L2csICcnKSAvLyBSZW1vdmUgSFRNTCB0YWdzXG4gICAgICAgICAgICAucmVwbGFjZSgvW15cXHdcXHNcXC1fLl0vZywgJycpIC8vIE9ubHkgYWxsb3cgc2FmZSBjaGFyYWN0ZXJzXG4gICAgICAgICAgICAuc3Vic3RyaW5nKDAsIDEwMCkgLy8gTGltaXQgbGVuZ3RoXG4gICAgICAgICAgICAudHJpbSgpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV0ZWN0IHJlZmVycmVyIHR5cGUgZnJvbSBkb2N1bWVudC5yZWZlcnJlclxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IC0geyBzb3VyY2U6IHN0cmluZywgY2F0ZWdvcnk6ICdzZWFyY2gnfCdzb2NpYWwnfCdlbWFpbCd8J2RpcmVjdCd8J290aGVyJyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gZGV0ZWN0UmVmZXJyZXIoKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSB7XG4gICAgICAgICAgICBzb3VyY2U6ICdkaXJlY3QnLFxuICAgICAgICAgICAgY2F0ZWdvcnk6ICdkaXJlY3QnLFxuICAgICAgICAgICAgdXJsOiAnJ1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnIHx8ICFkb2N1bWVudC5yZWZlcnJlcikge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmVzdWx0LnVybCA9IGRvY3VtZW50LnJlZmVycmVyXG5cbiAgICAgICAgICAgIC8vIENoZWNrIGZvciBlbWFpbCBwYXR0ZXJucyBpbiByZWZlcnJlclxuICAgICAgICAgICAgaWYgKC9tYWlsXFwufGVtYWlsXFwufG5ld3NsZXR0ZXIvaS50ZXN0KGRvY3VtZW50LnJlZmVycmVyKSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5zb3VyY2UgPSAnZW1haWwnXG4gICAgICAgICAgICAgICAgcmVzdWx0LmNhdGVnb3J5ID0gJ2VtYWlsJ1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2hlY2sgYWdhaW5zdCBrbm93biBwYXR0ZXJuc1xuICAgICAgICAgICAgZm9yICh2YXIgc291cmNlIGluIFJFRkVSUkVSX1BBVFRFUk5TKSB7XG4gICAgICAgICAgICAgICAgaWYgKFJFRkVSUkVSX1BBVFRFUk5TW3NvdXJjZV0udGVzdChkb2N1bWVudC5yZWZlcnJlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnNvdXJjZSA9IHNvdXJjZVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIERldGVybWluZSBjYXRlZ29yeVxuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBjYXRlZ29yeSBpbiBSRUZFUlJFUl9DQVRFR09SSUVTKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoUkVGRVJSRVJfQ0FURUdPUklFU1tjYXRlZ29yeV0uaW5kZXhPZihzb3VyY2UpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5jYXRlZ29yeSA9IGNhdGVnb3J5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFVua25vd24gZXh0ZXJuYWwgcmVmZXJyZXJcbiAgICAgICAgICAgIHJlc3VsdC5zb3VyY2UgPSAnZXh0ZXJuYWwnXG4gICAgICAgICAgICByZXN1bHQuY2F0ZWdvcnkgPSAnb3RoZXInXG5cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTHVhIFVUTV0gRXJyb3IgZGV0ZWN0aW5nIHJlZmVycmVyOicsIGUpXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHVzZXIgYWdlbnQgaW5mbyAoZm9yIGRldmljZS9icm93c2VyIGRldGVjdGlvbilcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSAtIFVzZXIgYWdlbnQgbWV0YWRhdGFcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRVc2VyQWdlbnRJbmZvKCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0ge1xuICAgICAgICAgICAgcmF3OiAnJyxcbiAgICAgICAgICAgIGlzTW9iaWxlOiBmYWxzZSxcbiAgICAgICAgICAgIGlzVGFibGV0OiBmYWxzZSxcbiAgICAgICAgICAgIGlzRGVza3RvcDogdHJ1ZVxuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yID09PSAndW5kZWZpbmVkJyB8fCAhbmF2aWdhdG9yLnVzZXJBZ2VudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmVzdWx0LnJhdyA9IG5hdmlnYXRvci51c2VyQWdlbnRcblxuICAgICAgICAgICAgLy8gTW9iaWxlIGRldGVjdGlvblxuICAgICAgICAgICAgcmVzdWx0LmlzTW9iaWxlID0gL0FuZHJvaWR8d2ViT1N8aVBob25lfGlQb2R8QmxhY2tCZXJyeXxJRU1vYmlsZXxPcGVyYSBNaW5pL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KVxuICAgICAgICAgICAgcmVzdWx0LmlzVGFibGV0ID0gL2lQYWR8QW5kcm9pZCg/IS4qTW9iaWxlKS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudClcbiAgICAgICAgICAgIHJlc3VsdC5pc0Rlc2t0b3AgPSAhcmVzdWx0LmlzTW9iaWxlICYmICFyZXN1bHQuaXNUYWJsZXRcblxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tMdWEgVVRNXSBFcnJvciBnZXR0aW5nIHVzZXIgYWdlbnQ6JywgZSlcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgZnVsbCBwZXJzb25hbGl6YXRpb24gY29udGV4dFxuICAgICAqIENvbWJpbmVzIFVUTSBwYXJhbXMsIHJlZmVycmVyIGluZm8sIGFuZCB1c2VyIGFnZW50XG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSAtIENvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy51cmxdIC0gQ3VzdG9tIFVSTCB0byBwYXJzZVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IC0gQ29tcGxldGUgY29udGV4dCBvYmplY3RcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRDb250ZXh0KG9wdGlvbnMpIHtcbiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cblxuICAgICAgICB2YXIgY29udGV4dCA9IHtcbiAgICAgICAgICAgIHV0bTogZXh0cmFjdFVUTVBhcmFtcyhvcHRpb25zLnVybCksXG4gICAgICAgICAgICByZWZlcnJlcjogZGV0ZWN0UmVmZXJyZXIoKSxcbiAgICAgICAgICAgIHVzZXJBZ2VudDogZ2V0VXNlckFnZW50SW5mbygpLFxuICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgaGFzVVRNOiBmYWxzZSxcbiAgICAgICAgICAgIHByaW1hcnlJbnRlbnQ6ICd1bmtub3duJ1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lIGlmIHdlIGhhdmUgVVRNIGRhdGFcbiAgICAgICAgY29udGV4dC5oYXNVVE0gPSBPYmplY3Qua2V5cyhjb250ZXh0LnV0bSkubGVuZ3RoID4gMFxuXG4gICAgICAgIC8vIEluZmVyIHByaW1hcnkgaW50ZW50XG4gICAgICAgIGNvbnRleHQucHJpbWFyeUludGVudCA9IGluZmVySW50ZW50KGNvbnRleHQpXG5cbiAgICAgICAgcmV0dXJuIGNvbnRleHRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbmZlciB1c2VyIGludGVudCBmcm9tIGNvbnRleHRcbiAgICAgKiBQcmlvcml0eTogVVRNIGNhbXBhaWduID4gVVRNIHNvdXJjZSA+IFJlZmVycmVyIGNhdGVnb3J5XG4gICAgICogQHBhcmFtIHtPYmplY3R9IGNvbnRleHQgLSBGdWxsIGNvbnRleHQgb2JqZWN0XG4gICAgICogQHJldHVybnMge3N0cmluZ30gLSBJbmZlcnJlZCBpbnRlbnQga2V5XG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5mZXJJbnRlbnQoY29udGV4dCkge1xuICAgICAgICAvLyBQcmlvcml0eSAxOiBVVE0gY2FtcGFpZ24gdGVsbHMgdXMgdGhlIHNwZWNpZmljIGludGVudFxuICAgICAgICBpZiAoY29udGV4dC51dG0udXRtX2NhbXBhaWduKSB7XG4gICAgICAgICAgICB2YXIgY2FtcGFpZ24gPSBjb250ZXh0LnV0bS51dG1fY2FtcGFpZ24udG9Mb3dlckNhc2UoKVxuXG4gICAgICAgICAgICBpZiAoL3NhbGV8ZGlzY291bnR8b2ZmZXJ8cHJvbW8vaS50ZXN0KGNhbXBhaWduKSkgcmV0dXJuICdwcmljZS1mb2N1c2VkJ1xuICAgICAgICAgICAgaWYgKC9nYW1pbmd8Z2FtZXxlc3BvcnQvaS50ZXN0KGNhbXBhaWduKSkgcmV0dXJuICdnYW1pbmcnXG4gICAgICAgICAgICBpZiAoL3dvcmt8b2ZmaWNlfHByb2Zlc3Npb25hbHxwcm9kdWN0aXZpdHkvaS50ZXN0KGNhbXBhaWduKSkgcmV0dXJuICdwcm9mZXNzaW9uYWwnXG4gICAgICAgICAgICBpZiAoL2NyZWF0aXZlfGRlc2lnbnxhcnR8c3R1ZGlvL2kudGVzdChjYW1wYWlnbikpIHJldHVybiAnY3JlYXRpdmUnXG4gICAgICAgICAgICBpZiAoL2JyYW5kfHN0b3J5fGFib3V0L2kudGVzdChjYW1wYWlnbikpIHJldHVybiAnYnJhbmQtc3RvcnknXG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcmlvcml0eSAyOiBVVE0gc291cmNlIGNhbiBpbmRpY2F0ZSBpbnRlbnRcbiAgICAgICAgaWYgKGNvbnRleHQudXRtLnV0bV9zb3VyY2UpIHtcbiAgICAgICAgICAgIHZhciBzb3VyY2UgPSBjb250ZXh0LnV0bS51dG1fc291cmNlLnRvTG93ZXJDYXNlKClcblxuICAgICAgICAgICAgaWYgKC9nb29nbGV8YmluZ3x5YWhvby9pLnRlc3Qoc291cmNlKSkgcmV0dXJuICdzZWFyY2gtb3B0aW1pemVkJ1xuICAgICAgICAgICAgaWYgKC9mYWNlYm9va3xpbnN0YWdyYW18dGlrdG9rL2kudGVzdChzb3VyY2UpKSByZXR1cm4gJ3NvY2lhbC12aXN1YWwnXG4gICAgICAgICAgICBpZiAoL3R3aXR0ZXJ8eCQvaS50ZXN0KHNvdXJjZSkpIHJldHVybiAnc29jaWFsLWJyaWVmJ1xuICAgICAgICAgICAgaWYgKC9lbWFpbHxuZXdzbGV0dGVyL2kudGVzdChzb3VyY2UpKSByZXR1cm4gJ3JldHVybmluZy11c2VyJ1xuICAgICAgICAgICAgaWYgKC95b3V0dWJlL2kudGVzdChzb3VyY2UpKSByZXR1cm4gJ3ZpZGVvLWVuZ2FnZWQnXG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcmlvcml0eSAzOiBSZWZlcnJlciBjYXRlZ29yeVxuICAgICAgICBpZiAoY29udGV4dC5yZWZlcnJlci5jYXRlZ29yeSA9PT0gJ3NlYXJjaCcpIHJldHVybiAnc2VhcmNoLW9wdGltaXplZCdcbiAgICAgICAgaWYgKGNvbnRleHQucmVmZXJyZXIuY2F0ZWdvcnkgPT09ICdzb2NpYWwnKSByZXR1cm4gJ3NvY2lhbC12aXN1YWwnXG4gICAgICAgIGlmIChjb250ZXh0LnJlZmVycmVyLmNhdGVnb3J5ID09PSAnZW1haWwnKSByZXR1cm4gJ3JldHVybmluZy11c2VyJ1xuXG4gICAgICAgIC8vIERlZmF1bHRcbiAgICAgICAgcmV0dXJuICdkZWZhdWx0J1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBjb250ZXh0IHdpdGggdGltZW91dCBmYWxsYmFja1xuICAgICAqIFJldHVybnMgZGVmYXVsdCBjb250ZXh0IGlmIG9wZXJhdGlvbiB0YWtlcyB0b28gbG9uZ1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gLSBDb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMudGltZW91dF0gLSBUaW1lb3V0IGluIG1zIChkZWZhdWx0OiAxMDAwKVxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPE9iamVjdD59IC0gQ29udGV4dCBvYmplY3RcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRDb250ZXh0QXN5bmMob3B0aW9ucykge1xuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICAgICAgICB2YXIgdGltZW91dCA9IG9wdGlvbnMudGltZW91dCB8fCBVVE1fVElNRU9VVF9NU1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgICAgICAgdmFyIHRpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgLy8gVGltZW91dDogcmV0dXJuIGRlZmF1bHQgY29udGV4dFxuICAgICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgICB1dG06IHt9LFxuICAgICAgICAgICAgICAgICAgICByZWZlcnJlcjogeyBzb3VyY2U6ICdkaXJlY3QnLCBjYXRlZ29yeTogJ2RpcmVjdCcsIHVybDogJycgfSxcbiAgICAgICAgICAgICAgICAgICAgdXNlckFnZW50OiB7IHJhdzogJycsIGlzTW9iaWxlOiBmYWxzZSwgaXNUYWJsZXQ6IGZhbHNlLCBpc0Rlc2t0b3A6IHRydWUgfSxcbiAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgICAgICBoYXNVVE06IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBwcmltYXJ5SW50ZW50OiAnZGVmYXVsdCcsXG4gICAgICAgICAgICAgICAgICAgIHRpbWVkT3V0OiB0cnVlXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0sIHRpbWVvdXQpXG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRleHQgPSBnZXRDb250ZXh0KG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKVxuICAgICAgICAgICAgICAgIGNvbnRleHQudGltZWRPdXQgPSBmYWxzZVxuICAgICAgICAgICAgICAgIHJlc29sdmUoY29udGV4dClcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpXG4gICAgICAgICAgICAgICAgcmVzb2x2ZSh7XG4gICAgICAgICAgICAgICAgICAgIHV0bToge30sXG4gICAgICAgICAgICAgICAgICAgIHJlZmVycmVyOiB7IHNvdXJjZTogJ2RpcmVjdCcsIGNhdGVnb3J5OiAnZGlyZWN0JywgdXJsOiAnJyB9LFxuICAgICAgICAgICAgICAgICAgICB1c2VyQWdlbnQ6IHsgcmF3OiAnJywgaXNNb2JpbGU6IGZhbHNlLCBpc1RhYmxldDogZmFsc2UsIGlzRGVza3RvcDogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgICAgICAgICAgICAgICAgIGhhc1VUTTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIHByaW1hcnlJbnRlbnQ6ICdkZWZhdWx0JyxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGUubWVzc2FnZVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgLy8gLS0tIFB1YmxpYyBBUEkgLS0tXG4gICAgLy8gUmVnaXN0ZXIgb24gdGhlIGdsb2JhbCByb290ICh3aW5kb3cgaW4gYnJvd3NlcilcbiAgICB2YXIgTHVhVVRNID0ge1xuICAgICAgICBleHRyYWN0VVRNUGFyYW1zOiBleHRyYWN0VVRNUGFyYW1zLFxuICAgICAgICBzYW5pdGl6ZVBhcmFtOiBzYW5pdGl6ZVBhcmFtLFxuICAgICAgICBkZXRlY3RSZWZlcnJlcjogZGV0ZWN0UmVmZXJyZXIsXG4gICAgICAgIGdldFVzZXJBZ2VudEluZm86IGdldFVzZXJBZ2VudEluZm8sXG4gICAgICAgIGdldENvbnRleHQ6IGdldENvbnRleHQsXG4gICAgICAgIGdldENvbnRleHRBc3luYzogZ2V0Q29udGV4dEFzeW5jLFxuICAgICAgICBpbmZlckludGVudDogaW5mZXJJbnRlbnQsXG4gICAgICAgIFVUTV9QQVJBTVM6IFVUTV9QQVJBTVMsXG4gICAgICAgIFVUTV9USU1FT1VUX01TOiBVVE1fVElNRU9VVF9NUyxcbiAgICAgICAgUkVGRVJSRVJfUEFUVEVSTlM6IFJFRkVSUkVSX1BBVFRFUk5TLFxuICAgICAgICBSRUZFUlJFUl9DQVRFR09SSUVTOiBSRUZFUlJFUl9DQVRFR09SSUVTXG4gICAgfVxuXG4gICAgLy8gRXhwb3NlIGdsb2JhbGx5XG4gICAgcm9vdC5MdWFVVE0gPSBMdWFVVE1cblxufSkodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6IHRoaXMpXG4iXSwibWFwcGluZ3MiOiI7O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUMsQ0FBQyxVQUFVQSxJQUFJLEVBQUU7RUFDZCxZQUFZOztFQUVaO0VBQ0EsSUFBSUMsY0FBYyxHQUFHLElBQUk7O0VBRXpCO0VBQ0EsSUFBSUMsVUFBVSxHQUFHLENBQUMsWUFBWSxFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLFVBQVUsQ0FBQzs7RUFFeEY7RUFDQSxJQUFJQyxpQkFBaUIsR0FBRztJQUNwQkMsTUFBTSxFQUFFLFdBQVc7SUFDbkJDLElBQUksRUFBRSxTQUFTO0lBQ2ZDLEtBQUssRUFBRSxVQUFVO0lBQ2pCQyxVQUFVLEVBQUUsZUFBZTtJQUMzQkMsUUFBUSxFQUFFLHdCQUF3QjtJQUNsQ0MsT0FBTyxFQUFFLDRCQUE0QjtJQUNyQ0MsU0FBUyxFQUFFLGlCQUFpQjtJQUM1QkMsUUFBUSxFQUFFLGdCQUFnQjtJQUMxQkMsU0FBUyxFQUFFLGNBQWM7SUFDekJDLE1BQU0sRUFBRSxjQUFjO0lBQ3RCQyxPQUFPLEVBQUUseUJBQXlCO0lBQ2xDQyxNQUFNLEVBQUU7RUFDWixDQUFDOztFQUVEO0VBQ0EsSUFBSUMsbUJBQW1CLEdBQUc7SUFDdEJDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFlBQVksQ0FBQztJQUNqREMsTUFBTSxFQUFFLENBQUMsVUFBVSxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLFFBQVE7RUFDdkcsQ0FBQzs7RUFFRDtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBU0MsZ0JBQWdCQSxDQUFDQyxHQUFHLEVBQUU7SUFDM0IsSUFBSUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUVmLElBQUk7TUFDQSxJQUFJQyxZQUFZLEdBQUdGLEdBQUcsS0FBSyxPQUFPRyxNQUFNLEtBQUssV0FBVyxHQUFHQSxNQUFNLENBQUNDLFFBQVEsQ0FBQ1AsTUFBTSxHQUFHLEVBQUUsQ0FBQztNQUV2RixJQUFJLENBQUNLLFlBQVksRUFBRTtRQUNmLE9BQU9ELE1BQU07TUFDakI7O01BRUE7TUFDQSxJQUFJSSxNQUFNLEdBQUcsSUFBSUMsZUFBZSxDQUFDSixZQUFZLENBQUM7TUFFOUNwQixVQUFVLENBQUN5QixPQUFPLENBQUMsVUFBVUMsS0FBSyxFQUFFO1FBQ2hDLElBQUlDLEtBQUssR0FBR0osTUFBTSxDQUFDSyxHQUFHLENBQUNGLEtBQUssQ0FBQztRQUM3QixJQUFJQyxLQUFLLEVBQUU7VUFDUDtVQUNBUixNQUFNLENBQUNPLEtBQUssQ0FBQyxHQUFHRyxhQUFhLENBQUNGLEtBQUssQ0FBQztRQUN4QztNQUNKLENBQUMsQ0FBQztJQUNOLENBQUMsQ0FBQyxPQUFPRyxDQUFDLEVBQUU7TUFDUjtNQUNBQyxPQUFPLENBQUNDLElBQUksQ0FBQyx3Q0FBd0MsRUFBRUYsQ0FBQyxDQUFDO0lBQzdEO0lBRUEsT0FBT1gsTUFBTTtFQUNqQjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxTQUFTVSxhQUFhQSxDQUFDRixLQUFLLEVBQUU7SUFDMUIsSUFBSSxPQUFPQSxLQUFLLEtBQUssUUFBUSxFQUFFLE9BQU8sRUFBRTtJQUN4QztJQUNBLE9BQU9BLEtBQUssQ0FDUE0sT0FBTyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUFBLENBQ3hCQSxPQUFPLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQUEsQ0FDNUJDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFBQSxDQUNsQkMsSUFBSSxDQUFDLENBQUM7RUFDZjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtFQUNJLFNBQVNDLGNBQWNBLENBQUEsRUFBRztJQUN0QixJQUFJakIsTUFBTSxHQUFHO01BQ1RrQixNQUFNLEVBQUUsUUFBUTtNQUNoQkMsUUFBUSxFQUFFLFFBQVE7TUFDbEJwQixHQUFHLEVBQUU7SUFDVCxDQUFDO0lBRUQsSUFBSTtNQUNBLElBQUksT0FBT3FCLFFBQVEsS0FBSyxXQUFXLElBQUksQ0FBQ0EsUUFBUSxDQUFDQyxRQUFRLEVBQUU7UUFDdkQsT0FBT3JCLE1BQU07TUFDakI7TUFFQUEsTUFBTSxDQUFDRCxHQUFHLEdBQUdxQixRQUFRLENBQUNDLFFBQVE7O01BRTlCO01BQ0EsSUFBSSw0QkFBNEIsQ0FBQ0MsSUFBSSxDQUFDRixRQUFRLENBQUNDLFFBQVEsQ0FBQyxFQUFFO1FBQ3REckIsTUFBTSxDQUFDa0IsTUFBTSxHQUFHLE9BQU87UUFDdkJsQixNQUFNLENBQUNtQixRQUFRLEdBQUcsT0FBTztRQUN6QixPQUFPbkIsTUFBTTtNQUNqQjs7TUFFQTtNQUNBLEtBQUssSUFBSWtCLE1BQU0sSUFBSXBDLGlCQUFpQixFQUFFO1FBQ2xDLElBQUlBLGlCQUFpQixDQUFDb0MsTUFBTSxDQUFDLENBQUNJLElBQUksQ0FBQ0YsUUFBUSxDQUFDQyxRQUFRLENBQUMsRUFBRTtVQUNuRHJCLE1BQU0sQ0FBQ2tCLE1BQU0sR0FBR0EsTUFBTTs7VUFFdEI7VUFDQSxLQUFLLElBQUlDLFFBQVEsSUFBSXhCLG1CQUFtQixFQUFFO1lBQ3RDLElBQUlBLG1CQUFtQixDQUFDd0IsUUFBUSxDQUFDLENBQUNJLE9BQU8sQ0FBQ0wsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7Y0FDdERsQixNQUFNLENBQUNtQixRQUFRLEdBQUdBLFFBQVE7Y0FDMUI7WUFDSjtVQUNKO1VBRUEsT0FBT25CLE1BQU07UUFDakI7TUFDSjs7TUFFQTtNQUNBQSxNQUFNLENBQUNrQixNQUFNLEdBQUcsVUFBVTtNQUMxQmxCLE1BQU0sQ0FBQ21CLFFBQVEsR0FBRyxPQUFPO0lBRTdCLENBQUMsQ0FBQyxPQUFPUixDQUFDLEVBQUU7TUFDUkMsT0FBTyxDQUFDQyxJQUFJLENBQUMscUNBQXFDLEVBQUVGLENBQUMsQ0FBQztJQUMxRDtJQUVBLE9BQU9YLE1BQU07RUFDakI7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7RUFDSSxTQUFTd0IsZ0JBQWdCQSxDQUFBLEVBQUc7SUFDeEIsSUFBSXhCLE1BQU0sR0FBRztNQUNUeUIsR0FBRyxFQUFFLEVBQUU7TUFDUEMsUUFBUSxFQUFFLEtBQUs7TUFDZkMsUUFBUSxFQUFFLEtBQUs7TUFDZkMsU0FBUyxFQUFFO0lBQ2YsQ0FBQztJQUVELElBQUk7TUFDQSxJQUFJLE9BQU9DLFNBQVMsS0FBSyxXQUFXLElBQUksQ0FBQ0EsU0FBUyxDQUFDQyxTQUFTLEVBQUU7UUFDMUQsT0FBTzlCLE1BQU07TUFDakI7TUFFQUEsTUFBTSxDQUFDeUIsR0FBRyxHQUFHSSxTQUFTLENBQUNDLFNBQVM7O01BRWhDO01BQ0E5QixNQUFNLENBQUMwQixRQUFRLEdBQUcsMkRBQTJELENBQUNKLElBQUksQ0FBQ08sU0FBUyxDQUFDQyxTQUFTLENBQUM7TUFDdkc5QixNQUFNLENBQUMyQixRQUFRLEdBQUcsMkJBQTJCLENBQUNMLElBQUksQ0FBQ08sU0FBUyxDQUFDQyxTQUFTLENBQUM7TUFDdkU5QixNQUFNLENBQUM0QixTQUFTLEdBQUcsQ0FBQzVCLE1BQU0sQ0FBQzBCLFFBQVEsSUFBSSxDQUFDMUIsTUFBTSxDQUFDMkIsUUFBUTtJQUUzRCxDQUFDLENBQUMsT0FBT2hCLENBQUMsRUFBRTtNQUNSQyxPQUFPLENBQUNDLElBQUksQ0FBQyxxQ0FBcUMsRUFBRUYsQ0FBQyxDQUFDO0lBQzFEO0lBRUEsT0FBT1gsTUFBTTtFQUNqQjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLFNBQVMrQixVQUFVQSxDQUFDQyxPQUFPLEVBQUU7SUFDekJBLE9BQU8sR0FBR0EsT0FBTyxJQUFJLENBQUMsQ0FBQztJQUV2QixJQUFJQyxPQUFPLEdBQUc7TUFDVkMsR0FBRyxFQUFFcEMsZ0JBQWdCLENBQUNrQyxPQUFPLENBQUNqQyxHQUFHLENBQUM7TUFDbENzQixRQUFRLEVBQUVKLGNBQWMsQ0FBQyxDQUFDO01BQzFCYSxTQUFTLEVBQUVOLGdCQUFnQixDQUFDLENBQUM7TUFDN0JXLFNBQVMsRUFBRUMsSUFBSSxDQUFDQyxHQUFHLENBQUMsQ0FBQztNQUNyQkMsTUFBTSxFQUFFLEtBQUs7TUFDYkMsYUFBYSxFQUFFO0lBQ25CLENBQUM7O0lBRUQ7SUFDQU4sT0FBTyxDQUFDSyxNQUFNLEdBQUdFLE1BQU0sQ0FBQ0MsSUFBSSxDQUFDUixPQUFPLENBQUNDLEdBQUcsQ0FBQyxDQUFDUSxNQUFNLEdBQUcsQ0FBQzs7SUFFcEQ7SUFDQVQsT0FBTyxDQUFDTSxhQUFhLEdBQUdJLFdBQVcsQ0FBQ1YsT0FBTyxDQUFDO0lBRTVDLE9BQU9BLE9BQU87RUFDbEI7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBU1UsV0FBV0EsQ0FBQ1YsT0FBTyxFQUFFO0lBQzFCO0lBQ0EsSUFBSUEsT0FBTyxDQUFDQyxHQUFHLENBQUNVLFlBQVksRUFBRTtNQUMxQixJQUFJQyxRQUFRLEdBQUdaLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDVSxZQUFZLENBQUNFLFdBQVcsQ0FBQyxDQUFDO01BRXJELElBQUksNEJBQTRCLENBQUN4QixJQUFJLENBQUN1QixRQUFRLENBQUMsRUFBRSxPQUFPLGVBQWU7TUFDdkUsSUFBSSxxQkFBcUIsQ0FBQ3ZCLElBQUksQ0FBQ3VCLFFBQVEsQ0FBQyxFQUFFLE9BQU8sUUFBUTtNQUN6RCxJQUFJLHdDQUF3QyxDQUFDdkIsSUFBSSxDQUFDdUIsUUFBUSxDQUFDLEVBQUUsT0FBTyxjQUFjO01BQ2xGLElBQUksNkJBQTZCLENBQUN2QixJQUFJLENBQUN1QixRQUFRLENBQUMsRUFBRSxPQUFPLFVBQVU7TUFDbkUsSUFBSSxvQkFBb0IsQ0FBQ3ZCLElBQUksQ0FBQ3VCLFFBQVEsQ0FBQyxFQUFFLE9BQU8sYUFBYTtJQUNqRTs7SUFFQTtJQUNBLElBQUlaLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDYSxVQUFVLEVBQUU7TUFDeEIsSUFBSTdCLE1BQU0sR0FBR2UsT0FBTyxDQUFDQyxHQUFHLENBQUNhLFVBQVUsQ0FBQ0QsV0FBVyxDQUFDLENBQUM7TUFFakQsSUFBSSxvQkFBb0IsQ0FBQ3hCLElBQUksQ0FBQ0osTUFBTSxDQUFDLEVBQUUsT0FBTyxrQkFBa0I7TUFDaEUsSUFBSSw0QkFBNEIsQ0FBQ0ksSUFBSSxDQUFDSixNQUFNLENBQUMsRUFBRSxPQUFPLGVBQWU7TUFDckUsSUFBSSxhQUFhLENBQUNJLElBQUksQ0FBQ0osTUFBTSxDQUFDLEVBQUUsT0FBTyxjQUFjO01BQ3JELElBQUksbUJBQW1CLENBQUNJLElBQUksQ0FBQ0osTUFBTSxDQUFDLEVBQUUsT0FBTyxnQkFBZ0I7TUFDN0QsSUFBSSxVQUFVLENBQUNJLElBQUksQ0FBQ0osTUFBTSxDQUFDLEVBQUUsT0FBTyxlQUFlO0lBQ3ZEOztJQUVBO0lBQ0EsSUFBSWUsT0FBTyxDQUFDWixRQUFRLENBQUNGLFFBQVEsS0FBSyxRQUFRLEVBQUUsT0FBTyxrQkFBa0I7SUFDckUsSUFBSWMsT0FBTyxDQUFDWixRQUFRLENBQUNGLFFBQVEsS0FBSyxRQUFRLEVBQUUsT0FBTyxlQUFlO0lBQ2xFLElBQUljLE9BQU8sQ0FBQ1osUUFBUSxDQUFDRixRQUFRLEtBQUssT0FBTyxFQUFFLE9BQU8sZ0JBQWdCOztJQUVsRTtJQUNBLE9BQU8sU0FBUztFQUNwQjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLFNBQVM2QixlQUFlQSxDQUFDaEIsT0FBTyxFQUFFO0lBQzlCQSxPQUFPLEdBQUdBLE9BQU8sSUFBSSxDQUFDLENBQUM7SUFDdkIsSUFBSWlCLE9BQU8sR0FBR2pCLE9BQU8sQ0FBQ2lCLE9BQU8sSUFBSXJFLGNBQWM7SUFFL0MsT0FBTyxJQUFJc0UsT0FBTyxDQUFDLFVBQVVDLE9BQU8sRUFBRTtNQUNsQyxJQUFJQyxLQUFLLEdBQUdDLFVBQVUsQ0FBQyxZQUFZO1FBQy9CO1FBQ0FGLE9BQU8sQ0FBQztVQUNKakIsR0FBRyxFQUFFLENBQUMsQ0FBQztVQUNQYixRQUFRLEVBQUU7WUFBRUgsTUFBTSxFQUFFLFFBQVE7WUFBRUMsUUFBUSxFQUFFLFFBQVE7WUFBRXBCLEdBQUcsRUFBRTtVQUFHLENBQUM7VUFDM0QrQixTQUFTLEVBQUU7WUFBRUwsR0FBRyxFQUFFLEVBQUU7WUFBRUMsUUFBUSxFQUFFLEtBQUs7WUFBRUMsUUFBUSxFQUFFLEtBQUs7WUFBRUMsU0FBUyxFQUFFO1VBQUssQ0FBQztVQUN6RU8sU0FBUyxFQUFFQyxJQUFJLENBQUNDLEdBQUcsQ0FBQyxDQUFDO1VBQ3JCQyxNQUFNLEVBQUUsS0FBSztVQUNiQyxhQUFhLEVBQUUsU0FBUztVQUN4QmUsUUFBUSxFQUFFO1FBQ2QsQ0FBQyxDQUFDO01BQ04sQ0FBQyxFQUFFTCxPQUFPLENBQUM7TUFFWCxJQUFJO1FBQ0EsSUFBSWhCLE9BQU8sR0FBR0YsVUFBVSxDQUFDQyxPQUFPLENBQUM7UUFDakN1QixZQUFZLENBQUNILEtBQUssQ0FBQztRQUNuQm5CLE9BQU8sQ0FBQ3FCLFFBQVEsR0FBRyxLQUFLO1FBQ3hCSCxPQUFPLENBQUNsQixPQUFPLENBQUM7TUFDcEIsQ0FBQyxDQUFDLE9BQU90QixDQUFDLEVBQUU7UUFDUjRDLFlBQVksQ0FBQ0gsS0FBSyxDQUFDO1FBQ25CRCxPQUFPLENBQUM7VUFDSmpCLEdBQUcsRUFBRSxDQUFDLENBQUM7VUFDUGIsUUFBUSxFQUFFO1lBQUVILE1BQU0sRUFBRSxRQUFRO1lBQUVDLFFBQVEsRUFBRSxRQUFRO1lBQUVwQixHQUFHLEVBQUU7VUFBRyxDQUFDO1VBQzNEK0IsU0FBUyxFQUFFO1lBQUVMLEdBQUcsRUFBRSxFQUFFO1lBQUVDLFFBQVEsRUFBRSxLQUFLO1lBQUVDLFFBQVEsRUFBRSxLQUFLO1lBQUVDLFNBQVMsRUFBRTtVQUFLLENBQUM7VUFDekVPLFNBQVMsRUFBRUMsSUFBSSxDQUFDQyxHQUFHLENBQUMsQ0FBQztVQUNyQkMsTUFBTSxFQUFFLEtBQUs7VUFDYkMsYUFBYSxFQUFFLFNBQVM7VUFDeEJpQixLQUFLLEVBQUU3QyxDQUFDLENBQUM4QztRQUNiLENBQUMsQ0FBQztNQUNOO0lBQ0osQ0FBQyxDQUFDO0VBQ047O0VBRUE7RUFDQTtFQUNBLElBQUlDLE1BQU0sR0FBRztJQUNUNUQsZ0JBQWdCLEVBQUVBLGdCQUFnQjtJQUNsQ1ksYUFBYSxFQUFFQSxhQUFhO0lBQzVCTyxjQUFjLEVBQUVBLGNBQWM7SUFDOUJPLGdCQUFnQixFQUFFQSxnQkFBZ0I7SUFDbENPLFVBQVUsRUFBRUEsVUFBVTtJQUN0QmlCLGVBQWUsRUFBRUEsZUFBZTtJQUNoQ0wsV0FBVyxFQUFFQSxXQUFXO0lBQ3hCOUQsVUFBVSxFQUFFQSxVQUFVO0lBQ3RCRCxjQUFjLEVBQUVBLGNBQWM7SUFDOUJFLGlCQUFpQixFQUFFQSxpQkFBaUI7SUFDcENhLG1CQUFtQixFQUFFQTtFQUN6QixDQUFDOztFQUVEO0VBQ0FoQixJQUFJLENBQUMrRSxNQUFNLEdBQUdBLE1BQU07QUFFeEIsQ0FBQyxFQUFFLE9BQU94RCxNQUFNLEtBQUssV0FBVyxHQUFHQSxNQUFNLEdBQUcsT0FBT3lELE1BQU0sS0FBSyxXQUFXLEdBQUdBLE1BQU0sU0FBTyxDQUFDIiwiaWdub3JlTGlzdCI6W119
|