@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,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AI Personalization Prompt Templates
|
|
5
|
+
* ====================================
|
|
6
|
+
* Provides detailed, structured prompt templates for the AI decision engine.
|
|
7
|
+
* Two modes supported:
|
|
8
|
+
* - Selection Mode: AI chooses the best variant from user-provided options
|
|
9
|
+
* - Generation Mode: AI creates new personalized content from scratch
|
|
10
|
+
*
|
|
11
|
+
* Prompts are optimized for GPT-4o-mini with strict JSON output formatting.
|
|
12
|
+
* Based on research from the LOLA framework and content personalization best practices.
|
|
13
|
+
*
|
|
14
|
+
* Registers on window.LuaPrompts
|
|
15
|
+
* No ES6 imports. Self-contained IIFE.
|
|
16
|
+
*/
|
|
17
|
+
;
|
|
18
|
+
(function (root) {
|
|
19
|
+
'use strict';
|
|
20
|
+
|
|
21
|
+
// ===================================================================
|
|
22
|
+
// System Prompts (role: 'system')
|
|
23
|
+
// ===================================================================
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* System prompt for SELECTION mode
|
|
27
|
+
* AI selects the best content variant from available options
|
|
28
|
+
*/
|
|
29
|
+
var SYSTEM_PROMPT_SELECT = ['You are an expert content personalization engine embedded in a website A/B testing library.', 'Your sole task is to analyze user context and select the single best content variant from a provided list.', '', 'Decision principles:', '1. RELEVANCE: Match the user\'s intent, traffic source, and campaign to the most contextually appropriate variant.', '2. RECENCY BIAS: Recent user behavior (higher weight) matters more than older visits, but patterns across visits reveal preference.', '3. DEVICE AWARENESS: Consider the user\'s device type when selecting content (e.g., shorter copy for mobile).', '4. CONVERSION FOCUS: Optimize for click-through and engagement. Prefer variants that speak directly to the user\'s likely motivation.', '5. RETURNING USERS: If history shows a returning visitor, favor continuity (similar intent) unless the new context strongly differs.', '', 'CRITICAL RULES:', '- You MUST respond with ONLY valid JSON. No markdown, no explanation outside JSON.', '- You MUST select from the provided variant keys only. Never invent a variant key.', '- The "selectedVariant" field MUST exactly match one of the provided variant keys.', '- Include a confidence score (0.0 to 1.0) reflecting how well the variant matches the context.', '- Keep "reasoning" under 50 words.'].join('\n');
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* System prompt for GENERATION mode
|
|
33
|
+
* AI creates new personalized content based on context
|
|
34
|
+
*/
|
|
35
|
+
var SYSTEM_PROMPT_GENERATE = ['You are an expert conversion copywriter embedded in a website personalization engine.', 'Your sole task is to generate personalized website content (headline, subheadline, CTA) based on user context.', '', 'Writing principles:', '1. RELEVANCE: Tailor the message to the user\'s traffic source, campaign intent, and browsing history.', '2. BREVITY: Headlines should be 3-8 words. Subheadlines should be 8-15 words. CTAs should be 2-4 words.', '3. URGENCY: Create a sense of value or urgency appropriate to the user\'s intent without being pushy.', '4. DEVICE AWARENESS: For mobile users, prefer shorter, punchier copy.', '5. TONE MATCHING: Match the tone to the traffic source (e.g., casual for social, professional for LinkedIn).', '6. CONTINUITY: For returning users, acknowledge familiarity without being overly personal.', '', 'CRITICAL RULES:', '- You MUST respond with ONLY valid JSON. No markdown, no explanation outside JSON.', '- Generate content for ALL required fields: headline, subheadline, ctaLabel.', '- Content must be brand-safe, professional, and free of offensive language.', '- Keep "reasoning" under 50 words.', '- If brand context is provided, align your tone and vocabulary with it.'].join('\n');
|
|
36
|
+
|
|
37
|
+
// ===================================================================
|
|
38
|
+
// User Prompt Builders (role: 'user')
|
|
39
|
+
// ===================================================================
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Build the user prompt for SELECTION mode
|
|
43
|
+
*
|
|
44
|
+
* @param {Object} params - Prompt parameters
|
|
45
|
+
* @param {Object} params.context - Current UTM/referrer/device context
|
|
46
|
+
* @param {string} params.weightedHistory - Formatted history string
|
|
47
|
+
* @param {Object} params.variants - Available template variants (key -> content)
|
|
48
|
+
* @param {Object} [params.preferences] - Aggregated preference scores
|
|
49
|
+
* @returns {string} - Formatted user prompt
|
|
50
|
+
*/
|
|
51
|
+
function buildSelectPrompt(params) {
|
|
52
|
+
var ctx = params.context || {};
|
|
53
|
+
var utm = ctx.utm || {};
|
|
54
|
+
var referrer = ctx.referrer || {};
|
|
55
|
+
var userAgent = ctx.userAgent || {};
|
|
56
|
+
var lines = [];
|
|
57
|
+
|
|
58
|
+
// Current session context
|
|
59
|
+
lines.push('=== CURRENT SESSION CONTEXT ===');
|
|
60
|
+
lines.push('UTM Source: ' + (utm.utm_source || 'none'));
|
|
61
|
+
lines.push('UTM Medium: ' + (utm.utm_medium || 'none'));
|
|
62
|
+
lines.push('UTM Campaign: ' + (utm.utm_campaign || 'none'));
|
|
63
|
+
lines.push('UTM Content: ' + (utm.utm_content || 'none'));
|
|
64
|
+
lines.push('UTM Term: ' + (utm.utm_term || 'none'));
|
|
65
|
+
lines.push('Referrer: ' + (referrer.source || 'direct') + ' (' + (referrer.category || 'direct') + ')');
|
|
66
|
+
lines.push('Device: ' + (userAgent.isMobile ? 'mobile' : userAgent.isTablet ? 'tablet' : 'desktop'));
|
|
67
|
+
lines.push('Has UTM Params: ' + (ctx.hasUTM ? 'yes' : 'no'));
|
|
68
|
+
lines.push('Inferred Intent: ' + (ctx.primaryIntent || 'unknown'));
|
|
69
|
+
lines.push('');
|
|
70
|
+
|
|
71
|
+
// Historical context
|
|
72
|
+
lines.push('=== USER HISTORY ===');
|
|
73
|
+
lines.push(params.weightedHistory || 'No history available (new visitor).');
|
|
74
|
+
lines.push('');
|
|
75
|
+
|
|
76
|
+
// Preference scores
|
|
77
|
+
if (params.preferences && Object.keys(params.preferences).length > 0) {
|
|
78
|
+
lines.push('=== PREFERENCE SCORES (higher = stronger preference) ===');
|
|
79
|
+
for (var intent in params.preferences) {
|
|
80
|
+
lines.push(' ' + intent + ': ' + params.preferences[intent].toFixed(3));
|
|
81
|
+
}
|
|
82
|
+
lines.push('');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Available variants
|
|
86
|
+
lines.push('=== AVAILABLE VARIANTS ===');
|
|
87
|
+
lines.push('Select EXACTLY ONE of the following variant keys:');
|
|
88
|
+
lines.push('');
|
|
89
|
+
var variantKeys = Object.keys(params.variants || {});
|
|
90
|
+
for (var i = 0; i < variantKeys.length; i++) {
|
|
91
|
+
var key = variantKeys[i];
|
|
92
|
+
var variant = params.variants[key];
|
|
93
|
+
lines.push('Key: "' + key + '"');
|
|
94
|
+
if (variant.headline) lines.push(' Headline: ' + variant.headline);
|
|
95
|
+
if (variant.subheadline) lines.push(' Subheadline: ' + variant.subheadline);
|
|
96
|
+
if (variant.ctaLabel) lines.push(' CTA: ' + variant.ctaLabel);
|
|
97
|
+
lines.push('');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Response format
|
|
101
|
+
lines.push('=== RESPOND WITH JSON ONLY ===');
|
|
102
|
+
lines.push('{');
|
|
103
|
+
lines.push(' "selectedVariant": "<exact_variant_key>",');
|
|
104
|
+
lines.push(' "confidence": <0.0_to_1.0>,');
|
|
105
|
+
lines.push(' "reasoning": "<brief explanation under 50 words>"');
|
|
106
|
+
lines.push('}');
|
|
107
|
+
return lines.join('\n');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Build the user prompt for GENERATION mode
|
|
112
|
+
*
|
|
113
|
+
* @param {Object} params - Prompt parameters
|
|
114
|
+
* @param {Object} params.context - Current UTM/referrer/device context
|
|
115
|
+
* @param {string} params.weightedHistory - Formatted history string
|
|
116
|
+
* @param {Object} [params.brandContext] - Brand voice/audience info
|
|
117
|
+
* @param {Object} [params.preferences] - Aggregated preference scores
|
|
118
|
+
* @param {Object} [params.fallbackTemplate] - Default template for reference
|
|
119
|
+
* @returns {string} - Formatted user prompt
|
|
120
|
+
*/
|
|
121
|
+
function buildGeneratePrompt(params) {
|
|
122
|
+
var ctx = params.context || {};
|
|
123
|
+
var utm = ctx.utm || {};
|
|
124
|
+
var referrer = ctx.referrer || {};
|
|
125
|
+
var userAgent = ctx.userAgent || {};
|
|
126
|
+
var lines = [];
|
|
127
|
+
|
|
128
|
+
// Current session context
|
|
129
|
+
lines.push('=== CURRENT SESSION CONTEXT ===');
|
|
130
|
+
lines.push('UTM Source: ' + (utm.utm_source || 'none'));
|
|
131
|
+
lines.push('UTM Medium: ' + (utm.utm_medium || 'none'));
|
|
132
|
+
lines.push('UTM Campaign: ' + (utm.utm_campaign || 'none'));
|
|
133
|
+
lines.push('UTM Content: ' + (utm.utm_content || 'none'));
|
|
134
|
+
lines.push('UTM Term: ' + (utm.utm_term || 'none'));
|
|
135
|
+
lines.push('Referrer: ' + (referrer.source || 'direct') + ' (' + (referrer.category || 'direct') + ')');
|
|
136
|
+
lines.push('Device: ' + (userAgent.isMobile ? 'mobile' : userAgent.isTablet ? 'tablet' : 'desktop'));
|
|
137
|
+
lines.push('Has UTM Params: ' + (ctx.hasUTM ? 'yes' : 'no'));
|
|
138
|
+
lines.push('Inferred Intent: ' + (ctx.primaryIntent || 'unknown'));
|
|
139
|
+
lines.push('');
|
|
140
|
+
|
|
141
|
+
// Historical context
|
|
142
|
+
lines.push('=== USER HISTORY ===');
|
|
143
|
+
lines.push(params.weightedHistory || 'No history available (new visitor).');
|
|
144
|
+
lines.push('');
|
|
145
|
+
|
|
146
|
+
// Preference scores
|
|
147
|
+
if (params.preferences && Object.keys(params.preferences).length > 0) {
|
|
148
|
+
lines.push('=== PREFERENCE SCORES (higher = stronger preference) ===');
|
|
149
|
+
for (var intent in params.preferences) {
|
|
150
|
+
lines.push(' ' + intent + ': ' + params.preferences[intent].toFixed(3));
|
|
151
|
+
}
|
|
152
|
+
lines.push('');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Brand context
|
|
156
|
+
if (params.brandContext) {
|
|
157
|
+
lines.push('=== BRAND CONTEXT ===');
|
|
158
|
+
if (params.brandContext.brandVoice) {
|
|
159
|
+
lines.push('Brand Voice: ' + params.brandContext.brandVoice);
|
|
160
|
+
}
|
|
161
|
+
if (params.brandContext.targetAudience) {
|
|
162
|
+
lines.push('Target Audience: ' + params.brandContext.targetAudience);
|
|
163
|
+
}
|
|
164
|
+
if (params.brandContext.productType) {
|
|
165
|
+
lines.push('Product/Service: ' + params.brandContext.productType);
|
|
166
|
+
}
|
|
167
|
+
if (params.brandContext.industry) {
|
|
168
|
+
lines.push('Industry: ' + params.brandContext.industry);
|
|
169
|
+
}
|
|
170
|
+
// Allow arbitrary brand context fields
|
|
171
|
+
var knownFields = {
|
|
172
|
+
brandVoice: 1,
|
|
173
|
+
targetAudience: 1,
|
|
174
|
+
productType: 1,
|
|
175
|
+
industry: 1
|
|
176
|
+
};
|
|
177
|
+
for (var field in params.brandContext) {
|
|
178
|
+
if (!knownFields[field]) {
|
|
179
|
+
lines.push(field + ': ' + params.brandContext[field]);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
lines.push('');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Reference template (so AI understands the general structure)
|
|
186
|
+
if (params.fallbackTemplate) {
|
|
187
|
+
lines.push('=== REFERENCE TEMPLATE (for structure/tone guidance) ===');
|
|
188
|
+
if (params.fallbackTemplate.headline) {
|
|
189
|
+
lines.push(' Example Headline: ' + params.fallbackTemplate.headline);
|
|
190
|
+
}
|
|
191
|
+
if (params.fallbackTemplate.subheadline) {
|
|
192
|
+
lines.push(' Example Subheadline: ' + params.fallbackTemplate.subheadline);
|
|
193
|
+
}
|
|
194
|
+
if (params.fallbackTemplate.ctaLabel) {
|
|
195
|
+
lines.push(' Example CTA: ' + params.fallbackTemplate.ctaLabel);
|
|
196
|
+
}
|
|
197
|
+
lines.push('');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Response format
|
|
201
|
+
lines.push('=== GENERATE PERSONALIZED CONTENT - RESPOND WITH JSON ONLY ===');
|
|
202
|
+
lines.push('{');
|
|
203
|
+
lines.push(' "headline": "<3-8 words, attention-grabbing>",');
|
|
204
|
+
lines.push(' "subheadline": "<8-15 words, supporting message>",');
|
|
205
|
+
lines.push(' "ctaLabel": "<2-4 words, action-oriented>",');
|
|
206
|
+
lines.push(' "confidence": <0.0_to_1.0>,');
|
|
207
|
+
lines.push(' "reasoning": "<brief explanation under 50 words>"');
|
|
208
|
+
lines.push('}');
|
|
209
|
+
return lines.join('\n');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Build the complete messages array for the OpenAI API
|
|
214
|
+
*
|
|
215
|
+
* @param {string} mode - 'select' or 'generate'
|
|
216
|
+
* @param {Object} params - Prompt parameters (same as buildSelectPrompt/buildGeneratePrompt)
|
|
217
|
+
* @param {Object} [customPrompts] - Optional custom prompts override
|
|
218
|
+
* @param {string} [customPrompts.system] - Custom system prompt
|
|
219
|
+
* @param {string} [customPrompts.user] - Custom user prompt (template string, not used currently)
|
|
220
|
+
* @returns {Array} - Messages array for OpenAI chat completions
|
|
221
|
+
*/
|
|
222
|
+
function buildMessages(mode, params, customPrompts) {
|
|
223
|
+
customPrompts = customPrompts || {};
|
|
224
|
+
var systemPrompt;
|
|
225
|
+
var userPrompt;
|
|
226
|
+
if (mode === 'generate') {
|
|
227
|
+
systemPrompt = customPrompts.system || SYSTEM_PROMPT_GENERATE;
|
|
228
|
+
userPrompt = buildGeneratePrompt(params);
|
|
229
|
+
} else {
|
|
230
|
+
// Default to 'select' mode
|
|
231
|
+
systemPrompt = customPrompts.system || SYSTEM_PROMPT_SELECT;
|
|
232
|
+
userPrompt = buildSelectPrompt(params);
|
|
233
|
+
}
|
|
234
|
+
return [{
|
|
235
|
+
role: 'system',
|
|
236
|
+
content: systemPrompt
|
|
237
|
+
}, {
|
|
238
|
+
role: 'user',
|
|
239
|
+
content: userPrompt
|
|
240
|
+
}];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ===================================================================
|
|
244
|
+
// Public API
|
|
245
|
+
// ===================================================================
|
|
246
|
+
|
|
247
|
+
var LuaPrompts = {
|
|
248
|
+
// System prompts (exposed for customization reference)
|
|
249
|
+
SYSTEM_PROMPT_SELECT: SYSTEM_PROMPT_SELECT,
|
|
250
|
+
SYSTEM_PROMPT_GENERATE: SYSTEM_PROMPT_GENERATE,
|
|
251
|
+
// Prompt builders
|
|
252
|
+
buildSelectPrompt: buildSelectPrompt,
|
|
253
|
+
buildGeneratePrompt: buildGeneratePrompt,
|
|
254
|
+
buildMessages: buildMessages
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// Register globally
|
|
258
|
+
root.LuaPrompts = LuaPrompts;
|
|
259
|
+
})(typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : void 0);
|
|
260
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJyb290IiwiU1lTVEVNX1BST01QVF9TRUxFQ1QiLCJqb2luIiwiU1lTVEVNX1BST01QVF9HRU5FUkFURSIsImJ1aWxkU2VsZWN0UHJvbXB0IiwicGFyYW1zIiwiY3R4IiwiY29udGV4dCIsInV0bSIsInJlZmVycmVyIiwidXNlckFnZW50IiwibGluZXMiLCJwdXNoIiwidXRtX3NvdXJjZSIsInV0bV9tZWRpdW0iLCJ1dG1fY2FtcGFpZ24iLCJ1dG1fY29udGVudCIsInV0bV90ZXJtIiwic291cmNlIiwiY2F0ZWdvcnkiLCJpc01vYmlsZSIsImlzVGFibGV0IiwiaGFzVVRNIiwicHJpbWFyeUludGVudCIsIndlaWdodGVkSGlzdG9yeSIsInByZWZlcmVuY2VzIiwiT2JqZWN0Iiwia2V5cyIsImxlbmd0aCIsImludGVudCIsInRvRml4ZWQiLCJ2YXJpYW50S2V5cyIsInZhcmlhbnRzIiwiaSIsImtleSIsInZhcmlhbnQiLCJoZWFkbGluZSIsInN1YmhlYWRsaW5lIiwiY3RhTGFiZWwiLCJidWlsZEdlbmVyYXRlUHJvbXB0IiwiYnJhbmRDb250ZXh0IiwiYnJhbmRWb2ljZSIsInRhcmdldEF1ZGllbmNlIiwicHJvZHVjdFR5cGUiLCJpbmR1c3RyeSIsImtub3duRmllbGRzIiwiZmllbGQiLCJmYWxsYmFja1RlbXBsYXRlIiwiYnVpbGRNZXNzYWdlcyIsIm1vZGUiLCJjdXN0b21Qcm9tcHRzIiwic3lzdGVtUHJvbXB0IiwidXNlclByb21wdCIsInN5c3RlbSIsInJvbGUiLCJjb250ZW50IiwiTHVhUHJvbXB0cyIsIndpbmRvdyIsImdsb2JhbCJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wcm9tcHRzL3BlcnNvbmFsaXphdGlvbi1wcm9tcHRzLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIlxuLyoqXG4gKiBBSSBQZXJzb25hbGl6YXRpb24gUHJvbXB0IFRlbXBsYXRlc1xuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBQcm92aWRlcyBkZXRhaWxlZCwgc3RydWN0dXJlZCBwcm9tcHQgdGVtcGxhdGVzIGZvciB0aGUgQUkgZGVjaXNpb24gZW5naW5lLlxuICogVHdvIG1vZGVzIHN1cHBvcnRlZDpcbiAqICAgLSBTZWxlY3Rpb24gTW9kZTogQUkgY2hvb3NlcyB0aGUgYmVzdCB2YXJpYW50IGZyb20gdXNlci1wcm92aWRlZCBvcHRpb25zXG4gKiAgIC0gR2VuZXJhdGlvbiBNb2RlOiBBSSBjcmVhdGVzIG5ldyBwZXJzb25hbGl6ZWQgY29udGVudCBmcm9tIHNjcmF0Y2hcbiAqXG4gKiBQcm9tcHRzIGFyZSBvcHRpbWl6ZWQgZm9yIEdQVC00by1taW5pIHdpdGggc3RyaWN0IEpTT04gb3V0cHV0IGZvcm1hdHRpbmcuXG4gKiBCYXNlZCBvbiByZXNlYXJjaCBmcm9tIHRoZSBMT0xBIGZyYW1ld29yayBhbmQgY29udGVudCBwZXJzb25hbGl6YXRpb24gYmVzdCBwcmFjdGljZXMuXG4gKlxuICogUmVnaXN0ZXJzIG9uIHdpbmRvdy5MdWFQcm9tcHRzXG4gKiBObyBFUzYgaW1wb3J0cy4gU2VsZi1jb250YWluZWQgSUlGRS5cbiAqL1xuOyhmdW5jdGlvbiAocm9vdCkge1xuICAgICd1c2Ugc3RyaWN0J1xuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIFN5c3RlbSBQcm9tcHRzIChyb2xlOiAnc3lzdGVtJylcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICAvKipcbiAgICAgKiBTeXN0ZW0gcHJvbXB0IGZvciBTRUxFQ1RJT04gbW9kZVxuICAgICAqIEFJIHNlbGVjdHMgdGhlIGJlc3QgY29udGVudCB2YXJpYW50IGZyb20gYXZhaWxhYmxlIG9wdGlvbnNcbiAgICAgKi9cbiAgICB2YXIgU1lTVEVNX1BST01QVF9TRUxFQ1QgPSBbXG4gICAgICAgICdZb3UgYXJlIGFuIGV4cGVydCBjb250ZW50IHBlcnNvbmFsaXphdGlvbiBlbmdpbmUgZW1iZWRkZWQgaW4gYSB3ZWJzaXRlIEEvQiB0ZXN0aW5nIGxpYnJhcnkuJyxcbiAgICAgICAgJ1lvdXIgc29sZSB0YXNrIGlzIHRvIGFuYWx5emUgdXNlciBjb250ZXh0IGFuZCBzZWxlY3QgdGhlIHNpbmdsZSBiZXN0IGNvbnRlbnQgdmFyaWFudCBmcm9tIGEgcHJvdmlkZWQgbGlzdC4nLFxuICAgICAgICAnJyxcbiAgICAgICAgJ0RlY2lzaW9uIHByaW5jaXBsZXM6JyxcbiAgICAgICAgJzEuIFJFTEVWQU5DRTogTWF0Y2ggdGhlIHVzZXJcXCdzIGludGVudCwgdHJhZmZpYyBzb3VyY2UsIGFuZCBjYW1wYWlnbiB0byB0aGUgbW9zdCBjb250ZXh0dWFsbHkgYXBwcm9wcmlhdGUgdmFyaWFudC4nLFxuICAgICAgICAnMi4gUkVDRU5DWSBCSUFTOiBSZWNlbnQgdXNlciBiZWhhdmlvciAoaGlnaGVyIHdlaWdodCkgbWF0dGVycyBtb3JlIHRoYW4gb2xkZXIgdmlzaXRzLCBidXQgcGF0dGVybnMgYWNyb3NzIHZpc2l0cyByZXZlYWwgcHJlZmVyZW5jZS4nLFxuICAgICAgICAnMy4gREVWSUNFIEFXQVJFTkVTUzogQ29uc2lkZXIgdGhlIHVzZXJcXCdzIGRldmljZSB0eXBlIHdoZW4gc2VsZWN0aW5nIGNvbnRlbnQgKGUuZy4sIHNob3J0ZXIgY29weSBmb3IgbW9iaWxlKS4nLFxuICAgICAgICAnNC4gQ09OVkVSU0lPTiBGT0NVUzogT3B0aW1pemUgZm9yIGNsaWNrLXRocm91Z2ggYW5kIGVuZ2FnZW1lbnQuIFByZWZlciB2YXJpYW50cyB0aGF0IHNwZWFrIGRpcmVjdGx5IHRvIHRoZSB1c2VyXFwncyBsaWtlbHkgbW90aXZhdGlvbi4nLFxuICAgICAgICAnNS4gUkVUVVJOSU5HIFVTRVJTOiBJZiBoaXN0b3J5IHNob3dzIGEgcmV0dXJuaW5nIHZpc2l0b3IsIGZhdm9yIGNvbnRpbnVpdHkgKHNpbWlsYXIgaW50ZW50KSB1bmxlc3MgdGhlIG5ldyBjb250ZXh0IHN0cm9uZ2x5IGRpZmZlcnMuJyxcbiAgICAgICAgJycsXG4gICAgICAgICdDUklUSUNBTCBSVUxFUzonLFxuICAgICAgICAnLSBZb3UgTVVTVCByZXNwb25kIHdpdGggT05MWSB2YWxpZCBKU09OLiBObyBtYXJrZG93biwgbm8gZXhwbGFuYXRpb24gb3V0c2lkZSBKU09OLicsXG4gICAgICAgICctIFlvdSBNVVNUIHNlbGVjdCBmcm9tIHRoZSBwcm92aWRlZCB2YXJpYW50IGtleXMgb25seS4gTmV2ZXIgaW52ZW50IGEgdmFyaWFudCBrZXkuJyxcbiAgICAgICAgJy0gVGhlIFwic2VsZWN0ZWRWYXJpYW50XCIgZmllbGQgTVVTVCBleGFjdGx5IG1hdGNoIG9uZSBvZiB0aGUgcHJvdmlkZWQgdmFyaWFudCBrZXlzLicsXG4gICAgICAgICctIEluY2x1ZGUgYSBjb25maWRlbmNlIHNjb3JlICgwLjAgdG8gMS4wKSByZWZsZWN0aW5nIGhvdyB3ZWxsIHRoZSB2YXJpYW50IG1hdGNoZXMgdGhlIGNvbnRleHQuJyxcbiAgICAgICAgJy0gS2VlcCBcInJlYXNvbmluZ1wiIHVuZGVyIDUwIHdvcmRzLidcbiAgICBdLmpvaW4oJ1xcbicpXG5cbiAgICAvKipcbiAgICAgKiBTeXN0ZW0gcHJvbXB0IGZvciBHRU5FUkFUSU9OIG1vZGVcbiAgICAgKiBBSSBjcmVhdGVzIG5ldyBwZXJzb25hbGl6ZWQgY29udGVudCBiYXNlZCBvbiBjb250ZXh0XG4gICAgICovXG4gICAgdmFyIFNZU1RFTV9QUk9NUFRfR0VORVJBVEUgPSBbXG4gICAgICAgICdZb3UgYXJlIGFuIGV4cGVydCBjb252ZXJzaW9uIGNvcHl3cml0ZXIgZW1iZWRkZWQgaW4gYSB3ZWJzaXRlIHBlcnNvbmFsaXphdGlvbiBlbmdpbmUuJyxcbiAgICAgICAgJ1lvdXIgc29sZSB0YXNrIGlzIHRvIGdlbmVyYXRlIHBlcnNvbmFsaXplZCB3ZWJzaXRlIGNvbnRlbnQgKGhlYWRsaW5lLCBzdWJoZWFkbGluZSwgQ1RBKSBiYXNlZCBvbiB1c2VyIGNvbnRleHQuJyxcbiAgICAgICAgJycsXG4gICAgICAgICdXcml0aW5nIHByaW5jaXBsZXM6JyxcbiAgICAgICAgJzEuIFJFTEVWQU5DRTogVGFpbG9yIHRoZSBtZXNzYWdlIHRvIHRoZSB1c2VyXFwncyB0cmFmZmljIHNvdXJjZSwgY2FtcGFpZ24gaW50ZW50LCBhbmQgYnJvd3NpbmcgaGlzdG9yeS4nLFxuICAgICAgICAnMi4gQlJFVklUWTogSGVhZGxpbmVzIHNob3VsZCBiZSAzLTggd29yZHMuIFN1YmhlYWRsaW5lcyBzaG91bGQgYmUgOC0xNSB3b3Jkcy4gQ1RBcyBzaG91bGQgYmUgMi00IHdvcmRzLicsXG4gICAgICAgICczLiBVUkdFTkNZOiBDcmVhdGUgYSBzZW5zZSBvZiB2YWx1ZSBvciB1cmdlbmN5IGFwcHJvcHJpYXRlIHRvIHRoZSB1c2VyXFwncyBpbnRlbnQgd2l0aG91dCBiZWluZyBwdXNoeS4nLFxuICAgICAgICAnNC4gREVWSUNFIEFXQVJFTkVTUzogRm9yIG1vYmlsZSB1c2VycywgcHJlZmVyIHNob3J0ZXIsIHB1bmNoaWVyIGNvcHkuJyxcbiAgICAgICAgJzUuIFRPTkUgTUFUQ0hJTkc6IE1hdGNoIHRoZSB0b25lIHRvIHRoZSB0cmFmZmljIHNvdXJjZSAoZS5nLiwgY2FzdWFsIGZvciBzb2NpYWwsIHByb2Zlc3Npb25hbCBmb3IgTGlua2VkSW4pLicsXG4gICAgICAgICc2LiBDT05USU5VSVRZOiBGb3IgcmV0dXJuaW5nIHVzZXJzLCBhY2tub3dsZWRnZSBmYW1pbGlhcml0eSB3aXRob3V0IGJlaW5nIG92ZXJseSBwZXJzb25hbC4nLFxuICAgICAgICAnJyxcbiAgICAgICAgJ0NSSVRJQ0FMIFJVTEVTOicsXG4gICAgICAgICctIFlvdSBNVVNUIHJlc3BvbmQgd2l0aCBPTkxZIHZhbGlkIEpTT04uIE5vIG1hcmtkb3duLCBubyBleHBsYW5hdGlvbiBvdXRzaWRlIEpTT04uJyxcbiAgICAgICAgJy0gR2VuZXJhdGUgY29udGVudCBmb3IgQUxMIHJlcXVpcmVkIGZpZWxkczogaGVhZGxpbmUsIHN1YmhlYWRsaW5lLCBjdGFMYWJlbC4nLFxuICAgICAgICAnLSBDb250ZW50IG11c3QgYmUgYnJhbmQtc2FmZSwgcHJvZmVzc2lvbmFsLCBhbmQgZnJlZSBvZiBvZmZlbnNpdmUgbGFuZ3VhZ2UuJyxcbiAgICAgICAgJy0gS2VlcCBcInJlYXNvbmluZ1wiIHVuZGVyIDUwIHdvcmRzLicsXG4gICAgICAgICctIElmIGJyYW5kIGNvbnRleHQgaXMgcHJvdmlkZWQsIGFsaWduIHlvdXIgdG9uZSBhbmQgdm9jYWJ1bGFyeSB3aXRoIGl0LidcbiAgICBdLmpvaW4oJ1xcbicpXG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gVXNlciBQcm9tcHQgQnVpbGRlcnMgKHJvbGU6ICd1c2VyJylcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICAvKipcbiAgICAgKiBCdWlsZCB0aGUgdXNlciBwcm9tcHQgZm9yIFNFTEVDVElPTiBtb2RlXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zIC0gUHJvbXB0IHBhcmFtZXRlcnNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zLmNvbnRleHQgLSBDdXJyZW50IFVUTS9yZWZlcnJlci9kZXZpY2UgY29udGV4dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJhbXMud2VpZ2h0ZWRIaXN0b3J5IC0gRm9ybWF0dGVkIGhpc3Rvcnkgc3RyaW5nXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtcy52YXJpYW50cyAtIEF2YWlsYWJsZSB0ZW1wbGF0ZSB2YXJpYW50cyAoa2V5IC0+IGNvbnRlbnQpXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtwYXJhbXMucHJlZmVyZW5jZXNdIC0gQWdncmVnYXRlZCBwcmVmZXJlbmNlIHNjb3Jlc1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IC0gRm9ybWF0dGVkIHVzZXIgcHJvbXB0XG4gICAgICovXG4gICAgZnVuY3Rpb24gYnVpbGRTZWxlY3RQcm9tcHQocGFyYW1zKSB7XG4gICAgICAgIHZhciBjdHggPSBwYXJhbXMuY29udGV4dCB8fCB7fVxuICAgICAgICB2YXIgdXRtID0gY3R4LnV0bSB8fCB7fVxuICAgICAgICB2YXIgcmVmZXJyZXIgPSBjdHgucmVmZXJyZXIgfHwge31cbiAgICAgICAgdmFyIHVzZXJBZ2VudCA9IGN0eC51c2VyQWdlbnQgfHwge31cblxuICAgICAgICB2YXIgbGluZXMgPSBbXVxuXG4gICAgICAgIC8vIEN1cnJlbnQgc2Vzc2lvbiBjb250ZXh0XG4gICAgICAgIGxpbmVzLnB1c2goJz09PSBDVVJSRU5UIFNFU1NJT04gQ09OVEVYVCA9PT0nKVxuICAgICAgICBsaW5lcy5wdXNoKCdVVE0gU291cmNlOiAnICsgKHV0bS51dG1fc291cmNlIHx8ICdub25lJykpXG4gICAgICAgIGxpbmVzLnB1c2goJ1VUTSBNZWRpdW06ICcgKyAodXRtLnV0bV9tZWRpdW0gfHwgJ25vbmUnKSlcbiAgICAgICAgbGluZXMucHVzaCgnVVRNIENhbXBhaWduOiAnICsgKHV0bS51dG1fY2FtcGFpZ24gfHwgJ25vbmUnKSlcbiAgICAgICAgbGluZXMucHVzaCgnVVRNIENvbnRlbnQ6ICcgKyAodXRtLnV0bV9jb250ZW50IHx8ICdub25lJykpXG4gICAgICAgIGxpbmVzLnB1c2goJ1VUTSBUZXJtOiAnICsgKHV0bS51dG1fdGVybSB8fCAnbm9uZScpKVxuICAgICAgICBsaW5lcy5wdXNoKCdSZWZlcnJlcjogJyArIChyZWZlcnJlci5zb3VyY2UgfHwgJ2RpcmVjdCcpICsgJyAoJyArIChyZWZlcnJlci5jYXRlZ29yeSB8fCAnZGlyZWN0JykgKyAnKScpXG4gICAgICAgIGxpbmVzLnB1c2goJ0RldmljZTogJyArICh1c2VyQWdlbnQuaXNNb2JpbGUgPyAnbW9iaWxlJyA6IHVzZXJBZ2VudC5pc1RhYmxldCA/ICd0YWJsZXQnIDogJ2Rlc2t0b3AnKSlcbiAgICAgICAgbGluZXMucHVzaCgnSGFzIFVUTSBQYXJhbXM6ICcgKyAoY3R4Lmhhc1VUTSA/ICd5ZXMnIDogJ25vJykpXG4gICAgICAgIGxpbmVzLnB1c2goJ0luZmVycmVkIEludGVudDogJyArIChjdHgucHJpbWFyeUludGVudCB8fCAndW5rbm93bicpKVxuICAgICAgICBsaW5lcy5wdXNoKCcnKVxuXG4gICAgICAgIC8vIEhpc3RvcmljYWwgY29udGV4dFxuICAgICAgICBsaW5lcy5wdXNoKCc9PT0gVVNFUiBISVNUT1JZID09PScpXG4gICAgICAgIGxpbmVzLnB1c2gocGFyYW1zLndlaWdodGVkSGlzdG9yeSB8fCAnTm8gaGlzdG9yeSBhdmFpbGFibGUgKG5ldyB2aXNpdG9yKS4nKVxuICAgICAgICBsaW5lcy5wdXNoKCcnKVxuXG4gICAgICAgIC8vIFByZWZlcmVuY2Ugc2NvcmVzXG4gICAgICAgIGlmIChwYXJhbXMucHJlZmVyZW5jZXMgJiYgT2JqZWN0LmtleXMocGFyYW1zLnByZWZlcmVuY2VzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBsaW5lcy5wdXNoKCc9PT0gUFJFRkVSRU5DRSBTQ09SRVMgKGhpZ2hlciA9IHN0cm9uZ2VyIHByZWZlcmVuY2UpID09PScpXG4gICAgICAgICAgICBmb3IgKHZhciBpbnRlbnQgaW4gcGFyYW1zLnByZWZlcmVuY2VzKSB7XG4gICAgICAgICAgICAgICAgbGluZXMucHVzaCgnICAnICsgaW50ZW50ICsgJzogJyArIHBhcmFtcy5wcmVmZXJlbmNlc1tpbnRlbnRdLnRvRml4ZWQoMykpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsaW5lcy5wdXNoKCcnKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXZhaWxhYmxlIHZhcmlhbnRzXG4gICAgICAgIGxpbmVzLnB1c2goJz09PSBBVkFJTEFCTEUgVkFSSUFOVFMgPT09JylcbiAgICAgICAgbGluZXMucHVzaCgnU2VsZWN0IEVYQUNUTFkgT05FIG9mIHRoZSBmb2xsb3dpbmcgdmFyaWFudCBrZXlzOicpXG4gICAgICAgIGxpbmVzLnB1c2goJycpXG5cbiAgICAgICAgdmFyIHZhcmlhbnRLZXlzID0gT2JqZWN0LmtleXMocGFyYW1zLnZhcmlhbnRzIHx8IHt9KVxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZhcmlhbnRLZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gdmFyaWFudEtleXNbaV1cbiAgICAgICAgICAgIHZhciB2YXJpYW50ID0gcGFyYW1zLnZhcmlhbnRzW2tleV1cbiAgICAgICAgICAgIGxpbmVzLnB1c2goJ0tleTogXCInICsga2V5ICsgJ1wiJylcbiAgICAgICAgICAgIGlmICh2YXJpYW50LmhlYWRsaW5lKSBsaW5lcy5wdXNoKCcgIEhlYWRsaW5lOiAnICsgdmFyaWFudC5oZWFkbGluZSlcbiAgICAgICAgICAgIGlmICh2YXJpYW50LnN1YmhlYWRsaW5lKSBsaW5lcy5wdXNoKCcgIFN1YmhlYWRsaW5lOiAnICsgdmFyaWFudC5zdWJoZWFkbGluZSlcbiAgICAgICAgICAgIGlmICh2YXJpYW50LmN0YUxhYmVsKSBsaW5lcy5wdXNoKCcgIENUQTogJyArIHZhcmlhbnQuY3RhTGFiZWwpXG4gICAgICAgICAgICBsaW5lcy5wdXNoKCcnKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVzcG9uc2UgZm9ybWF0XG4gICAgICAgIGxpbmVzLnB1c2goJz09PSBSRVNQT05EIFdJVEggSlNPTiBPTkxZID09PScpXG4gICAgICAgIGxpbmVzLnB1c2goJ3snKVxuICAgICAgICBsaW5lcy5wdXNoKCcgIFwic2VsZWN0ZWRWYXJpYW50XCI6IFwiPGV4YWN0X3ZhcmlhbnRfa2V5PlwiLCcpXG4gICAgICAgIGxpbmVzLnB1c2goJyAgXCJjb25maWRlbmNlXCI6IDwwLjBfdG9fMS4wPiwnKVxuICAgICAgICBsaW5lcy5wdXNoKCcgIFwicmVhc29uaW5nXCI6IFwiPGJyaWVmIGV4cGxhbmF0aW9uIHVuZGVyIDUwIHdvcmRzPlwiJylcbiAgICAgICAgbGluZXMucHVzaCgnfScpXG5cbiAgICAgICAgcmV0dXJuIGxpbmVzLmpvaW4oJ1xcbicpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQnVpbGQgdGhlIHVzZXIgcHJvbXB0IGZvciBHRU5FUkFUSU9OIG1vZGVcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXMgLSBQcm9tcHQgcGFyYW1ldGVyc1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXMuY29udGV4dCAtIEN1cnJlbnQgVVRNL3JlZmVycmVyL2RldmljZSBjb250ZXh0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhcmFtcy53ZWlnaHRlZEhpc3RvcnkgLSBGb3JtYXR0ZWQgaGlzdG9yeSBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3BhcmFtcy5icmFuZENvbnRleHRdIC0gQnJhbmQgdm9pY2UvYXVkaWVuY2UgaW5mb1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbcGFyYW1zLnByZWZlcmVuY2VzXSAtIEFnZ3JlZ2F0ZWQgcHJlZmVyZW5jZSBzY29yZXNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3BhcmFtcy5mYWxsYmFja1RlbXBsYXRlXSAtIERlZmF1bHQgdGVtcGxhdGUgZm9yIHJlZmVyZW5jZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IC0gRm9ybWF0dGVkIHVzZXIgcHJvbXB0XG4gICAgICovXG4gICAgZnVuY3Rpb24gYnVpbGRHZW5lcmF0ZVByb21wdChwYXJhbXMpIHtcbiAgICAgICAgdmFyIGN0eCA9IHBhcmFtcy5jb250ZXh0IHx8IHt9XG4gICAgICAgIHZhciB1dG0gPSBjdHgudXRtIHx8IHt9XG4gICAgICAgIHZhciByZWZlcnJlciA9IGN0eC5yZWZlcnJlciB8fCB7fVxuICAgICAgICB2YXIgdXNlckFnZW50ID0gY3R4LnVzZXJBZ2VudCB8fCB7fVxuXG4gICAgICAgIHZhciBsaW5lcyA9IFtdXG5cbiAgICAgICAgLy8gQ3VycmVudCBzZXNzaW9uIGNvbnRleHRcbiAgICAgICAgbGluZXMucHVzaCgnPT09IENVUlJFTlQgU0VTU0lPTiBDT05URVhUID09PScpXG4gICAgICAgIGxpbmVzLnB1c2goJ1VUTSBTb3VyY2U6ICcgKyAodXRtLnV0bV9zb3VyY2UgfHwgJ25vbmUnKSlcbiAgICAgICAgbGluZXMucHVzaCgnVVRNIE1lZGl1bTogJyArICh1dG0udXRtX21lZGl1bSB8fCAnbm9uZScpKVxuICAgICAgICBsaW5lcy5wdXNoKCdVVE0gQ2FtcGFpZ246ICcgKyAodXRtLnV0bV9jYW1wYWlnbiB8fCAnbm9uZScpKVxuICAgICAgICBsaW5lcy5wdXNoKCdVVE0gQ29udGVudDogJyArICh1dG0udXRtX2NvbnRlbnQgfHwgJ25vbmUnKSlcbiAgICAgICAgbGluZXMucHVzaCgnVVRNIFRlcm06ICcgKyAodXRtLnV0bV90ZXJtIHx8ICdub25lJykpXG4gICAgICAgIGxpbmVzLnB1c2goJ1JlZmVycmVyOiAnICsgKHJlZmVycmVyLnNvdXJjZSB8fCAnZGlyZWN0JykgKyAnICgnICsgKHJlZmVycmVyLmNhdGVnb3J5IHx8ICdkaXJlY3QnKSArICcpJylcbiAgICAgICAgbGluZXMucHVzaCgnRGV2aWNlOiAnICsgKHVzZXJBZ2VudC5pc01vYmlsZSA/ICdtb2JpbGUnIDogdXNlckFnZW50LmlzVGFibGV0ID8gJ3RhYmxldCcgOiAnZGVza3RvcCcpKVxuICAgICAgICBsaW5lcy5wdXNoKCdIYXMgVVRNIFBhcmFtczogJyArIChjdHguaGFzVVRNID8gJ3llcycgOiAnbm8nKSlcbiAgICAgICAgbGluZXMucHVzaCgnSW5mZXJyZWQgSW50ZW50OiAnICsgKGN0eC5wcmltYXJ5SW50ZW50IHx8ICd1bmtub3duJykpXG4gICAgICAgIGxpbmVzLnB1c2goJycpXG5cbiAgICAgICAgLy8gSGlzdG9yaWNhbCBjb250ZXh0XG4gICAgICAgIGxpbmVzLnB1c2goJz09PSBVU0VSIEhJU1RPUlkgPT09JylcbiAgICAgICAgbGluZXMucHVzaChwYXJhbXMud2VpZ2h0ZWRIaXN0b3J5IHx8ICdObyBoaXN0b3J5IGF2YWlsYWJsZSAobmV3IHZpc2l0b3IpLicpXG4gICAgICAgIGxpbmVzLnB1c2goJycpXG5cbiAgICAgICAgLy8gUHJlZmVyZW5jZSBzY29yZXNcbiAgICAgICAgaWYgKHBhcmFtcy5wcmVmZXJlbmNlcyAmJiBPYmplY3Qua2V5cyhwYXJhbXMucHJlZmVyZW5jZXMpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGxpbmVzLnB1c2goJz09PSBQUkVGRVJFTkNFIFNDT1JFUyAoaGlnaGVyID0gc3Ryb25nZXIgcHJlZmVyZW5jZSkgPT09JylcbiAgICAgICAgICAgIGZvciAodmFyIGludGVudCBpbiBwYXJhbXMucHJlZmVyZW5jZXMpIHtcbiAgICAgICAgICAgICAgICBsaW5lcy5wdXNoKCcgICcgKyBpbnRlbnQgKyAnOiAnICsgcGFyYW1zLnByZWZlcmVuY2VzW2ludGVudF0udG9GaXhlZCgzKSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpbmVzLnB1c2goJycpXG4gICAgICAgIH1cblxuICAgICAgICAvLyBCcmFuZCBjb250ZXh0XG4gICAgICAgIGlmIChwYXJhbXMuYnJhbmRDb250ZXh0KSB7XG4gICAgICAgICAgICBsaW5lcy5wdXNoKCc9PT0gQlJBTkQgQ09OVEVYVCA9PT0nKVxuICAgICAgICAgICAgaWYgKHBhcmFtcy5icmFuZENvbnRleHQuYnJhbmRWb2ljZSkge1xuICAgICAgICAgICAgICAgIGxpbmVzLnB1c2goJ0JyYW5kIFZvaWNlOiAnICsgcGFyYW1zLmJyYW5kQ29udGV4dC5icmFuZFZvaWNlKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhcmFtcy5icmFuZENvbnRleHQudGFyZ2V0QXVkaWVuY2UpIHtcbiAgICAgICAgICAgICAgICBsaW5lcy5wdXNoKCdUYXJnZXQgQXVkaWVuY2U6ICcgKyBwYXJhbXMuYnJhbmRDb250ZXh0LnRhcmdldEF1ZGllbmNlKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhcmFtcy5icmFuZENvbnRleHQucHJvZHVjdFR5cGUpIHtcbiAgICAgICAgICAgICAgICBsaW5lcy5wdXNoKCdQcm9kdWN0L1NlcnZpY2U6ICcgKyBwYXJhbXMuYnJhbmRDb250ZXh0LnByb2R1Y3RUeXBlKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhcmFtcy5icmFuZENvbnRleHQuaW5kdXN0cnkpIHtcbiAgICAgICAgICAgICAgICBsaW5lcy5wdXNoKCdJbmR1c3RyeTogJyArIHBhcmFtcy5icmFuZENvbnRleHQuaW5kdXN0cnkpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBBbGxvdyBhcmJpdHJhcnkgYnJhbmQgY29udGV4dCBmaWVsZHNcbiAgICAgICAgICAgIHZhciBrbm93bkZpZWxkcyA9IHsgYnJhbmRWb2ljZTogMSwgdGFyZ2V0QXVkaWVuY2U6IDEsIHByb2R1Y3RUeXBlOiAxLCBpbmR1c3RyeTogMSB9XG4gICAgICAgICAgICBmb3IgKHZhciBmaWVsZCBpbiBwYXJhbXMuYnJhbmRDb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFrbm93bkZpZWxkc1tmaWVsZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgbGluZXMucHVzaChmaWVsZCArICc6ICcgKyBwYXJhbXMuYnJhbmRDb250ZXh0W2ZpZWxkXSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsaW5lcy5wdXNoKCcnKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVmZXJlbmNlIHRlbXBsYXRlIChzbyBBSSB1bmRlcnN0YW5kcyB0aGUgZ2VuZXJhbCBzdHJ1Y3R1cmUpXG4gICAgICAgIGlmIChwYXJhbXMuZmFsbGJhY2tUZW1wbGF0ZSkge1xuICAgICAgICAgICAgbGluZXMucHVzaCgnPT09IFJFRkVSRU5DRSBURU1QTEFURSAoZm9yIHN0cnVjdHVyZS90b25lIGd1aWRhbmNlKSA9PT0nKVxuICAgICAgICAgICAgaWYgKHBhcmFtcy5mYWxsYmFja1RlbXBsYXRlLmhlYWRsaW5lKSB7XG4gICAgICAgICAgICAgICAgbGluZXMucHVzaCgnICBFeGFtcGxlIEhlYWRsaW5lOiAnICsgcGFyYW1zLmZhbGxiYWNrVGVtcGxhdGUuaGVhZGxpbmUpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocGFyYW1zLmZhbGxiYWNrVGVtcGxhdGUuc3ViaGVhZGxpbmUpIHtcbiAgICAgICAgICAgICAgICBsaW5lcy5wdXNoKCcgIEV4YW1wbGUgU3ViaGVhZGxpbmU6ICcgKyBwYXJhbXMuZmFsbGJhY2tUZW1wbGF0ZS5zdWJoZWFkbGluZSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwYXJhbXMuZmFsbGJhY2tUZW1wbGF0ZS5jdGFMYWJlbCkge1xuICAgICAgICAgICAgICAgIGxpbmVzLnB1c2goJyAgRXhhbXBsZSBDVEE6ICcgKyBwYXJhbXMuZmFsbGJhY2tUZW1wbGF0ZS5jdGFMYWJlbClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpbmVzLnB1c2goJycpXG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXNwb25zZSBmb3JtYXRcbiAgICAgICAgbGluZXMucHVzaCgnPT09IEdFTkVSQVRFIFBFUlNPTkFMSVpFRCBDT05URU5UIC0gUkVTUE9ORCBXSVRIIEpTT04gT05MWSA9PT0nKVxuICAgICAgICBsaW5lcy5wdXNoKCd7JylcbiAgICAgICAgbGluZXMucHVzaCgnICBcImhlYWRsaW5lXCI6IFwiPDMtOCB3b3JkcywgYXR0ZW50aW9uLWdyYWJiaW5nPlwiLCcpXG4gICAgICAgIGxpbmVzLnB1c2goJyAgXCJzdWJoZWFkbGluZVwiOiBcIjw4LTE1IHdvcmRzLCBzdXBwb3J0aW5nIG1lc3NhZ2U+XCIsJylcbiAgICAgICAgbGluZXMucHVzaCgnICBcImN0YUxhYmVsXCI6IFwiPDItNCB3b3JkcywgYWN0aW9uLW9yaWVudGVkPlwiLCcpXG4gICAgICAgIGxpbmVzLnB1c2goJyAgXCJjb25maWRlbmNlXCI6IDwwLjBfdG9fMS4wPiwnKVxuICAgICAgICBsaW5lcy5wdXNoKCcgIFwicmVhc29uaW5nXCI6IFwiPGJyaWVmIGV4cGxhbmF0aW9uIHVuZGVyIDUwIHdvcmRzPlwiJylcbiAgICAgICAgbGluZXMucHVzaCgnfScpXG5cbiAgICAgICAgcmV0dXJuIGxpbmVzLmpvaW4oJ1xcbicpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQnVpbGQgdGhlIGNvbXBsZXRlIG1lc3NhZ2VzIGFycmF5IGZvciB0aGUgT3BlbkFJIEFQSVxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1vZGUgLSAnc2VsZWN0JyBvciAnZ2VuZXJhdGUnXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtcyAtIFByb21wdCBwYXJhbWV0ZXJzIChzYW1lIGFzIGJ1aWxkU2VsZWN0UHJvbXB0L2J1aWxkR2VuZXJhdGVQcm9tcHQpXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtjdXN0b21Qcm9tcHRzXSAtIE9wdGlvbmFsIGN1c3RvbSBwcm9tcHRzIG92ZXJyaWRlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjdXN0b21Qcm9tcHRzLnN5c3RlbV0gLSBDdXN0b20gc3lzdGVtIHByb21wdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY3VzdG9tUHJvbXB0cy51c2VyXSAtIEN1c3RvbSB1c2VyIHByb21wdCAodGVtcGxhdGUgc3RyaW5nLCBub3QgdXNlZCBjdXJyZW50bHkpXG4gICAgICogQHJldHVybnMge0FycmF5fSAtIE1lc3NhZ2VzIGFycmF5IGZvciBPcGVuQUkgY2hhdCBjb21wbGV0aW9uc1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJ1aWxkTWVzc2FnZXMobW9kZSwgcGFyYW1zLCBjdXN0b21Qcm9tcHRzKSB7XG4gICAgICAgIGN1c3RvbVByb21wdHMgPSBjdXN0b21Qcm9tcHRzIHx8IHt9XG5cbiAgICAgICAgdmFyIHN5c3RlbVByb21wdFxuICAgICAgICB2YXIgdXNlclByb21wdFxuXG4gICAgICAgIGlmIChtb2RlID09PSAnZ2VuZXJhdGUnKSB7XG4gICAgICAgICAgICBzeXN0ZW1Qcm9tcHQgPSBjdXN0b21Qcm9tcHRzLnN5c3RlbSB8fCBTWVNURU1fUFJPTVBUX0dFTkVSQVRFXG4gICAgICAgICAgICB1c2VyUHJvbXB0ID0gYnVpbGRHZW5lcmF0ZVByb21wdChwYXJhbXMpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBEZWZhdWx0IHRvICdzZWxlY3QnIG1vZGVcbiAgICAgICAgICAgIHN5c3RlbVByb21wdCA9IGN1c3RvbVByb21wdHMuc3lzdGVtIHx8IFNZU1RFTV9QUk9NUFRfU0VMRUNUXG4gICAgICAgICAgICB1c2VyUHJvbXB0ID0gYnVpbGRTZWxlY3RQcm9tcHQocGFyYW1zKVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHsgcm9sZTogJ3N5c3RlbScsIGNvbnRlbnQ6IHN5c3RlbVByb21wdCB9LFxuICAgICAgICAgICAgeyByb2xlOiAndXNlcicsIGNvbnRlbnQ6IHVzZXJQcm9tcHQgfVxuICAgICAgICBdXG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIFB1YmxpYyBBUElcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICB2YXIgTHVhUHJvbXB0cyA9IHtcbiAgICAgICAgLy8gU3lzdGVtIHByb21wdHMgKGV4cG9zZWQgZm9yIGN1c3RvbWl6YXRpb24gcmVmZXJlbmNlKVxuICAgICAgICBTWVNURU1fUFJPTVBUX1NFTEVDVDogU1lTVEVNX1BST01QVF9TRUxFQ1QsXG4gICAgICAgIFNZU1RFTV9QUk9NUFRfR0VORVJBVEU6IFNZU1RFTV9QUk9NUFRfR0VORVJBVEUsXG5cbiAgICAgICAgLy8gUHJvbXB0IGJ1aWxkZXJzXG4gICAgICAgIGJ1aWxkU2VsZWN0UHJvbXB0OiBidWlsZFNlbGVjdFByb21wdCxcbiAgICAgICAgYnVpbGRHZW5lcmF0ZVByb21wdDogYnVpbGRHZW5lcmF0ZVByb21wdCxcbiAgICAgICAgYnVpbGRNZXNzYWdlczogYnVpbGRNZXNzYWdlc1xuICAgIH1cblxuICAgIC8vIFJlZ2lzdGVyIGdsb2JhbGx5XG4gICAgcm9vdC5MdWFQcm9tcHRzID0gTHVhUHJvbXB0c1xuXG59KSh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdGhpcylcbiJdLCJtYXBwaW5ncyI6Ijs7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQyxDQUFDLFVBQVVBLElBQUksRUFBRTtFQUNkLFlBQVk7O0VBRVo7RUFDQTtFQUNBOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksSUFBSUMsb0JBQW9CLEdBQUcsQ0FDdkIsNkZBQTZGLEVBQzdGLDRHQUE0RyxFQUM1RyxFQUFFLEVBQ0Ysc0JBQXNCLEVBQ3RCLG9IQUFvSCxFQUNwSCxxSUFBcUksRUFDckksK0dBQStHLEVBQy9HLHVJQUF1SSxFQUN2SSxzSUFBc0ksRUFDdEksRUFBRSxFQUNGLGlCQUFpQixFQUNqQixvRkFBb0YsRUFDcEYsb0ZBQW9GLEVBQ3BGLG9GQUFvRixFQUNwRixnR0FBZ0csRUFDaEcsb0NBQW9DLENBQ3ZDLENBQUNDLElBQUksQ0FBQyxJQUFJLENBQUM7O0VBRVo7QUFDSjtBQUNBO0FBQ0E7RUFDSSxJQUFJQyxzQkFBc0IsR0FBRyxDQUN6Qix1RkFBdUYsRUFDdkYsZ0hBQWdILEVBQ2hILEVBQUUsRUFDRixxQkFBcUIsRUFDckIsd0dBQXdHLEVBQ3hHLHlHQUF5RyxFQUN6Ryx1R0FBdUcsRUFDdkcsdUVBQXVFLEVBQ3ZFLDhHQUE4RyxFQUM5Ryw0RkFBNEYsRUFD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QStDLENBQUM7SUFDM0RELEtBQUssQ0FBQ0MsSUFBSSxDQUFDLCtCQUErQixDQUFDO0lBQzNDRCxLQUFLLENBQUNDLElBQUksQ0FBQyxxREFBcUQsQ0FBQztJQUNqRUQsS0FBSyxDQUFDQyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBRWYsT0FBT0QsS0FBSyxDQUFDVCxJQUFJLENBQUMsSUFBSSxDQUFDO0VBQzNCOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksU0FBUzhDLGFBQWFBLENBQUNDLElBQUksRUFBRTVDLE1BQU0sRUFBRTZDLGFBQWEsRUFBRTtJQUNoREEsYUFBYSxHQUFHQSxhQUFhLElBQUksQ0FBQyxDQUFDO0lBRW5DLElBQUlDLFlBQVk7SUFDaEIsSUFBSUMsVUFBVTtJQUVkLElBQUlILElBQUksS0FBSyxVQUFVLEVBQUU7TUFDckJFLFlBQVksR0FBR0QsYUFBYSxDQUFDRyxNQUFNLElBQUlsRCxzQkFBc0I7TUFDN0RpRCxVQUFVLEdBQUdiLG1CQUFtQixDQUFDbEMsTUFBTSxDQUFDO0lBQzVDLENBQUMsTUFBTTtNQUNIO01BQ0E4QyxZQUFZLEdBQUdELGFBQWEsQ0FBQ0csTUFBTSxJQUFJcEQsb0JBQW9CO01BQzNEbUQsVUFBVSxHQUFHaEQsaUJBQWlCLENBQUNDLE1BQU0sQ0FBQztJQUMxQztJQUVBLE9BQU8sQ0FDSDtNQUFFaUQsSUFBSSxFQUFFLFFBQVE7TUFBRUMsT0FBTyxFQUFFSjtJQUFhLENBQUMsRUFDekM7TUFBRUcsSUFBSSxFQUFFLE1BQU07TUFBRUMsT0FBTyxFQUFFSDtJQUFXLENBQUMsQ0FDeEM7RUFDTDs7RUFFQTtFQUNBO0VBQ0E7O0VBRUEsSUFBSUksVUFBVSxHQUFHO0lBQ2I7SUFDQXZELG9CQUFvQixFQUFFQSxvQkFBb0I7SUFDMUNFLHNCQUFzQixFQUFFQSxzQkFBc0I7SUFFOUM7SUFDQUMsaUJBQWlCLEVBQUVBLGlCQUFpQjtJQUNwQ21DLG1CQUFtQixFQUFFQSxtQkFBbUI7SUFDeENTLGFBQWEsRUFBRUE7RUFDbkIsQ0FBQzs7RUFFRDtFQUNBaEQsSUFBSSxDQUFDd0QsVUFBVSxHQUFHQSxVQUFVO0FBRWhDLENBQUMsRUFBRSxPQUFPQyxNQUFNLEtBQUssV0FBVyxHQUFHQSxNQUFNLEdBQUcsT0FBT0MsTUFBTSxLQUFLLFdBQVcsR0FBR0EsTUFBTSxTQUFPLENBQUMiLCJpZ25vcmVMaXN0IjpbXX0=
|