@okeyamy/lua 5.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,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=