@thinkhive/sdk 3.1.0 → 3.3.0

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,263 @@
1
+ /**
2
+ * ThinkHive SDK v3.1 - ROI Analytics API
3
+ *
4
+ * Business ROI & Metrics Engine for calculating financial impact
5
+ */
6
+ /**
7
+ * Industry-specific ROI configuration
8
+ */
9
+ export interface IndustryConfig {
10
+ id: string;
11
+ name: string;
12
+ avgTransactionValue: number;
13
+ avgCustomerLTV: number;
14
+ avgSupportCost: number;
15
+ avgEscalationCost: number;
16
+ avgResolutionTime: number;
17
+ }
18
+ /**
19
+ * Custom industry config input
20
+ */
21
+ export interface CustomIndustryConfig {
22
+ industry?: string;
23
+ avgTransactionValue?: number;
24
+ avgCustomerLTV?: number;
25
+ avgSupportCost?: number;
26
+ avgEscalationCost?: number;
27
+ churnImpactMultiplier?: number;
28
+ avgResolutionTime?: number;
29
+ }
30
+ /**
31
+ * ROI metrics summary
32
+ */
33
+ export interface ROIMetrics {
34
+ roiCategory: string;
35
+ totalFinancialImpact: number;
36
+ revenueProtected: number;
37
+ costSavings: number;
38
+ efficiencyGain: number;
39
+ }
40
+ /**
41
+ * Business impact analysis result
42
+ */
43
+ export interface BusinessImpact {
44
+ impactScore: number;
45
+ revenueRisk: number;
46
+ brandRisk: number;
47
+ complianceRisk: number;
48
+ operationalImpact: number;
49
+ customerSatisfaction: number;
50
+ recommendations: string[];
51
+ roi: ROIMetrics;
52
+ }
53
+ /**
54
+ * ROI summary for a date range
55
+ */
56
+ export interface ROISummary {
57
+ dateRange: {
58
+ start: string;
59
+ end: string;
60
+ };
61
+ traceCount: number;
62
+ successfulInteractions: number;
63
+ failedInteractions: number;
64
+ successRate: number;
65
+ roi: ROIMetrics;
66
+ revenueProtected: number;
67
+ estimatedSavings: number;
68
+ }
69
+ /**
70
+ * Daily trend data point
71
+ */
72
+ export interface TrendDataPoint {
73
+ date: string;
74
+ traceCount: number;
75
+ successCount: number;
76
+ failureCount: number;
77
+ successRate: number;
78
+ avgImpactScore: number;
79
+ }
80
+ /**
81
+ * Correlation finding
82
+ */
83
+ export interface Correlation {
84
+ type: string;
85
+ strength: string;
86
+ coefficient: number;
87
+ confidence: number;
88
+ description: string;
89
+ insight: string;
90
+ recommendation: string;
91
+ }
92
+ /**
93
+ * Pattern cluster
94
+ */
95
+ export interface PatternCluster {
96
+ id: string;
97
+ name: string;
98
+ matchCount: number;
99
+ avgImpactScore: number;
100
+ avgChurnRisk: number;
101
+ trend: string;
102
+ examples: string[];
103
+ }
104
+ /**
105
+ * Correlation analysis result
106
+ */
107
+ export interface CorrelationAnalysis {
108
+ analysisId: string;
109
+ analyzedAt: string;
110
+ traceCount: number;
111
+ timeRange: {
112
+ start: string;
113
+ end: string;
114
+ };
115
+ overallHealthScore: number;
116
+ topInsights: string[];
117
+ recommendations: string[];
118
+ correlations: Correlation[];
119
+ patternClusters: PatternCluster[];
120
+ }
121
+ /**
122
+ * ROI Analytics API client for business impact analysis
123
+ */
124
+ export declare const roiAnalytics: {
125
+ /**
126
+ * Get aggregated ROI summary for traces in date range
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * const summary = await roiAnalytics.summary({
131
+ * startDate: '2024-01-01',
132
+ * endDate: '2024-01-31',
133
+ * });
134
+ * console.log(`Revenue protected: $${summary.revenueProtected}`);
135
+ * ```
136
+ */
137
+ summary(options?: {
138
+ startDate?: string | Date;
139
+ endDate?: string | Date;
140
+ agentId?: string;
141
+ }): Promise<ROISummary>;
142
+ /**
143
+ * Get ROI metrics for a specific agent
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * const agentROI = await roiAnalytics.byAgent('agent_123', {
148
+ * startDate: '2024-01-01',
149
+ * });
150
+ * console.log(`Agent: ${agentROI.agent.name}`);
151
+ * console.log(`ROI: ${agentROI.roi.totalFinancialImpact}`);
152
+ * ```
153
+ */
154
+ byAgent(agentId: string, options?: {
155
+ startDate?: string | Date;
156
+ endDate?: string | Date;
157
+ }): Promise<{
158
+ agent: {
159
+ id: string;
160
+ name: string;
161
+ industry: string;
162
+ };
163
+ industryConfig: Partial<IndustryConfig>;
164
+ roi: ROIMetrics;
165
+ recentImpacts: Array<{
166
+ impactScore: number;
167
+ revenueRisk: number;
168
+ roiCategory: string;
169
+ totalFinancialImpact: number;
170
+ }>;
171
+ }>;
172
+ /**
173
+ * Get ROI trends over time
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * const trends = await roiAnalytics.trends({
178
+ * startDate: '2024-01-01',
179
+ * endDate: '2024-01-31',
180
+ * });
181
+ * for (const day of trends) {
182
+ * console.log(`${day.date}: ${day.successRate}% success`);
183
+ * }
184
+ * ```
185
+ */
186
+ trends(options?: {
187
+ startDate?: string | Date;
188
+ endDate?: string | Date;
189
+ agentId?: string;
190
+ }): Promise<TrendDataPoint[]>;
191
+ /**
192
+ * Calculate ROI for a trace or provided message data
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * // Calculate for existing trace
197
+ * const impact = await roiAnalytics.calculate({
198
+ * traceId: 'trace_abc123',
199
+ * });
200
+ *
201
+ * // Calculate for new data with custom config
202
+ * const impact = await roiAnalytics.calculate({
203
+ * userMessage: 'Help me cancel my subscription',
204
+ * agentResponse: 'I can help with that...',
205
+ * industryConfig: { industry: 'saas', avgCustomerLTV: 10000 },
206
+ * });
207
+ * ```
208
+ */
209
+ calculate(options: {
210
+ traceId?: string;
211
+ userMessage?: string;
212
+ agentResponse?: string;
213
+ industryConfig?: CustomIndustryConfig;
214
+ }): Promise<BusinessImpact>;
215
+ /**
216
+ * Get available industry configurations
217
+ *
218
+ * @example
219
+ * ```typescript
220
+ * const industries = await roiAnalytics.industries();
221
+ * for (const config of industries) {
222
+ * console.log(`${config.name}: $${config.avgCustomerLTV} LTV`);
223
+ * }
224
+ * ```
225
+ */
226
+ industries(): Promise<IndustryConfig[]>;
227
+ /**
228
+ * Get correlation analysis for traces
229
+ *
230
+ * @example
231
+ * ```typescript
232
+ * const analysis = await roiAnalytics.correlations({
233
+ * startDate: '2024-01-01',
234
+ * agentId: 'agent_123',
235
+ * });
236
+ * console.log(`Health score: ${analysis.overallHealthScore}`);
237
+ * for (const insight of analysis.topInsights) {
238
+ * console.log(`- ${insight}`);
239
+ * }
240
+ * ```
241
+ */
242
+ correlations(options?: {
243
+ startDate?: string | Date;
244
+ endDate?: string | Date;
245
+ agentId?: string;
246
+ }): Promise<CorrelationAnalysis>;
247
+ };
248
+ /**
249
+ * Calculate estimated revenue at risk
250
+ */
251
+ export declare function calculateRevenueAtRisk(failureRate: number, avgTransactionValue: number, totalInteractions: number): number;
252
+ /**
253
+ * Calculate estimated savings from automation
254
+ */
255
+ export declare function calculateAutomationSavings(successfulInteractions: number, avgSupportCost: number): number;
256
+ /**
257
+ * Format currency for display
258
+ */
259
+ export declare function formatCurrency(amount: number, currency?: string): string;
260
+ /**
261
+ * Get ROI quality label
262
+ */
263
+ export declare function getROIQuality(totalFinancialImpact: number): 'excellent' | 'good' | 'moderate' | 'poor';
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ /**
3
+ * ThinkHive SDK v3.1 - ROI Analytics API
4
+ *
5
+ * Business ROI & Metrics Engine for calculating financial impact
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.roiAnalytics = void 0;
9
+ exports.calculateRevenueAtRisk = calculateRevenueAtRisk;
10
+ exports.calculateAutomationSavings = calculateAutomationSavings;
11
+ exports.formatCurrency = formatCurrency;
12
+ exports.getROIQuality = getROIQuality;
13
+ const client_1 = require("../core/client");
14
+ // ============================================================================
15
+ // ROI ANALYTICS API CLIENT
16
+ // ============================================================================
17
+ /**
18
+ * ROI Analytics API client for business impact analysis
19
+ */
20
+ exports.roiAnalytics = {
21
+ /**
22
+ * Get aggregated ROI summary for traces in date range
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const summary = await roiAnalytics.summary({
27
+ * startDate: '2024-01-01',
28
+ * endDate: '2024-01-31',
29
+ * });
30
+ * console.log(`Revenue protected: $${summary.revenueProtected}`);
31
+ * ```
32
+ */
33
+ async summary(options = {}) {
34
+ const params = new URLSearchParams();
35
+ if (options.startDate) {
36
+ params.set('startDate', new Date(options.startDate).toISOString());
37
+ }
38
+ if (options.endDate) {
39
+ params.set('endDate', new Date(options.endDate).toISOString());
40
+ }
41
+ if (options.agentId) {
42
+ params.set('agentId', options.agentId);
43
+ }
44
+ const response = await (0, client_1.apiRequest)(`/analytics/roi/summary?${params.toString()}`, { apiVersion: 'v1' });
45
+ return response.data.summary;
46
+ },
47
+ /**
48
+ * Get ROI metrics for a specific agent
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const agentROI = await roiAnalytics.byAgent('agent_123', {
53
+ * startDate: '2024-01-01',
54
+ * });
55
+ * console.log(`Agent: ${agentROI.agent.name}`);
56
+ * console.log(`ROI: ${agentROI.roi.totalFinancialImpact}`);
57
+ * ```
58
+ */
59
+ async byAgent(agentId, options = {}) {
60
+ const params = new URLSearchParams();
61
+ if (options.startDate) {
62
+ params.set('startDate', new Date(options.startDate).toISOString());
63
+ }
64
+ if (options.endDate) {
65
+ params.set('endDate', new Date(options.endDate).toISOString());
66
+ }
67
+ return (0, client_1.apiRequestWithData)(`/analytics/roi/by-agent/${agentId}?${params.toString()}`, { apiVersion: 'v1' });
68
+ },
69
+ /**
70
+ * Get ROI trends over time
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const trends = await roiAnalytics.trends({
75
+ * startDate: '2024-01-01',
76
+ * endDate: '2024-01-31',
77
+ * });
78
+ * for (const day of trends) {
79
+ * console.log(`${day.date}: ${day.successRate}% success`);
80
+ * }
81
+ * ```
82
+ */
83
+ async trends(options = {}) {
84
+ const params = new URLSearchParams();
85
+ if (options.startDate) {
86
+ params.set('startDate', new Date(options.startDate).toISOString());
87
+ }
88
+ if (options.endDate) {
89
+ params.set('endDate', new Date(options.endDate).toISOString());
90
+ }
91
+ if (options.agentId) {
92
+ params.set('agentId', options.agentId);
93
+ }
94
+ const response = await (0, client_1.apiRequest)(`/analytics/roi/trends?${params.toString()}`, { apiVersion: 'v1' });
95
+ return response.data.trends;
96
+ },
97
+ /**
98
+ * Calculate ROI for a trace or provided message data
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * // Calculate for existing trace
103
+ * const impact = await roiAnalytics.calculate({
104
+ * traceId: 'trace_abc123',
105
+ * });
106
+ *
107
+ * // Calculate for new data with custom config
108
+ * const impact = await roiAnalytics.calculate({
109
+ * userMessage: 'Help me cancel my subscription',
110
+ * agentResponse: 'I can help with that...',
111
+ * industryConfig: { industry: 'saas', avgCustomerLTV: 10000 },
112
+ * });
113
+ * ```
114
+ */
115
+ async calculate(options) {
116
+ const response = await (0, client_1.apiRequest)('/analytics/roi/calculate', {
117
+ method: 'POST',
118
+ body: options,
119
+ apiVersion: 'v1',
120
+ });
121
+ return response.data.impact;
122
+ },
123
+ /**
124
+ * Get available industry configurations
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const industries = await roiAnalytics.industries();
129
+ * for (const config of industries) {
130
+ * console.log(`${config.name}: $${config.avgCustomerLTV} LTV`);
131
+ * }
132
+ * ```
133
+ */
134
+ async industries() {
135
+ const response = await (0, client_1.apiRequest)('/analytics/roi/industries', { apiVersion: 'v1' });
136
+ return response.data.industries;
137
+ },
138
+ /**
139
+ * Get correlation analysis for traces
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const analysis = await roiAnalytics.correlations({
144
+ * startDate: '2024-01-01',
145
+ * agentId: 'agent_123',
146
+ * });
147
+ * console.log(`Health score: ${analysis.overallHealthScore}`);
148
+ * for (const insight of analysis.topInsights) {
149
+ * console.log(`- ${insight}`);
150
+ * }
151
+ * ```
152
+ */
153
+ async correlations(options = {}) {
154
+ const params = new URLSearchParams();
155
+ if (options.startDate) {
156
+ params.set('startDate', new Date(options.startDate).toISOString());
157
+ }
158
+ if (options.endDate) {
159
+ params.set('endDate', new Date(options.endDate).toISOString());
160
+ }
161
+ if (options.agentId) {
162
+ params.set('agentId', options.agentId);
163
+ }
164
+ const response = await (0, client_1.apiRequest)(`/analytics/correlations?${params.toString()}`, { apiVersion: 'v1' });
165
+ return response.data.analysis;
166
+ },
167
+ };
168
+ // ============================================================================
169
+ // HELPER FUNCTIONS
170
+ // ============================================================================
171
+ /**
172
+ * Calculate estimated revenue at risk
173
+ */
174
+ function calculateRevenueAtRisk(failureRate, avgTransactionValue, totalInteractions) {
175
+ return failureRate * avgTransactionValue * totalInteractions;
176
+ }
177
+ /**
178
+ * Calculate estimated savings from automation
179
+ */
180
+ function calculateAutomationSavings(successfulInteractions, avgSupportCost) {
181
+ return successfulInteractions * avgSupportCost;
182
+ }
183
+ /**
184
+ * Format currency for display
185
+ */
186
+ function formatCurrency(amount, currency = 'USD') {
187
+ return new Intl.NumberFormat('en-US', {
188
+ style: 'currency',
189
+ currency,
190
+ }).format(amount);
191
+ }
192
+ /**
193
+ * Get ROI quality label
194
+ */
195
+ function getROIQuality(totalFinancialImpact) {
196
+ if (totalFinancialImpact > 100000)
197
+ return 'excellent';
198
+ if (totalFinancialImpact > 50000)
199
+ return 'good';
200
+ if (totalFinancialImpact > 10000)
201
+ return 'moderate';
202
+ return 'poor';
203
+ }
204
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9pLWFuYWx5dGljcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvcm9pLWFuYWx5dGljcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7R0FJRzs7O0FBOFZILHdEQU1DO0FBS0QsZ0VBS0M7QUFLRCx3Q0FLQztBQUtELHNDQU9DO0FBbFlELDJDQUFnRTtBQTZIaEUsK0VBQStFO0FBQy9FLDJCQUEyQjtBQUMzQiwrRUFBK0U7QUFFL0U7O0dBRUc7QUFDVSxRQUFBLFlBQVksR0FBRztJQUMxQjs7Ozs7Ozs7Ozs7T0FXRztJQUNILEtBQUssQ0FBQyxPQUFPLENBQUMsVUFJVixFQUFFO1FBQ0osTUFBTSxNQUFNLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUNyQyxJQUFJLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN0QixNQUFNLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUNyRSxDQUFDO1FBQ0QsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDcEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3BCLE1BQU0sQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN6QyxDQUFDO1FBRUQsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFBLG1CQUFVLEVBQy9CLDBCQUEwQixNQUFNLENBQUMsUUFBUSxFQUFFLEVBQUUsRUFDN0MsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQ3JCLENBQUM7UUFDRixPQUFPLFFBQVEsQ0FBQyxJQUFLLENBQUMsT0FBTyxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7T0FXRztJQUNILEtBQUssQ0FBQyxPQUFPLENBQ1gsT0FBZSxFQUNmLFVBR0ksRUFBRTtRQVlOLE1BQU0sTUFBTSxHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7UUFDckMsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDdEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDckUsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3BCLE1BQU0sQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFFRCxPQUFPLElBQUEsMkJBQWtCLEVBQ3ZCLDJCQUEyQixPQUFPLElBQUksTUFBTSxDQUFDLFFBQVEsRUFBRSxFQUFFLEVBQ3pELEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUNyQixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7O09BYUc7SUFDSCxLQUFLLENBQUMsTUFBTSxDQUFDLFVBSVQsRUFBRTtRQUNKLE1BQU0sTUFBTSxHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7UUFDckMsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDdEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDckUsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3BCLE1BQU0sQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFDRCxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNwQixNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDekMsQ0FBQztRQUVELE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBQSxtQkFBVSxFQUMvQix5QkFBeUIsTUFBTSxDQUFDLFFBQVEsRUFBRSxFQUFFLEVBQzVDLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUNyQixDQUFDO1FBQ0YsT0FBTyxRQUFRLENBQUMsSUFBSyxDQUFDLE1BQU0sQ0FBQztJQUMvQixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7O09BaUJHO0lBQ0gsS0FBSyxDQUFDLFNBQVMsQ0FBQyxPQUtmO1FBQ0MsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFBLG1CQUFVLEVBQy9CLDBCQUEwQixFQUMxQjtZQUNFLE1BQU0sRUFBRSxNQUFNO1lBQ2QsSUFBSSxFQUFFLE9BQU87WUFDYixVQUFVLEVBQUUsSUFBSTtTQUNqQixDQUNGLENBQUM7UUFDRixPQUFPLFFBQVEsQ0FBQyxJQUFLLENBQUMsTUFBTSxDQUFDO0lBQy9CLENBQUM7SUFFRDs7Ozs7Ozs7OztPQVVHO0lBQ0gsS0FBSyxDQUFDLFVBQVU7UUFDZCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUEsbUJBQVUsRUFDL0IsMkJBQTJCLEVBQzNCLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUNyQixDQUFDO1FBQ0YsT0FBTyxRQUFRLENBQUMsSUFBSyxDQUFDLFVBQVUsQ0FBQztJQUNuQyxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDSCxLQUFLLENBQUMsWUFBWSxDQUFDLFVBSWYsRUFBRTtRQUNKLE1BQU0sTUFBTSxHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7UUFDckMsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDdEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDckUsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3BCLE1BQU0sQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFDRCxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNwQixNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDekMsQ0FBQztRQUVELE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBQSxtQkFBVSxFQUMvQiwyQkFBMkIsTUFBTSxDQUFDLFFBQVEsRUFBRSxFQUFFLEVBQzlDLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUNyQixDQUFDO1FBQ0YsT0FBTyxRQUFRLENBQUMsSUFBSyxDQUFDLFFBQVEsQ0FBQztJQUNqQyxDQUFDO0NBQ0YsQ0FBQztBQUVGLCtFQUErRTtBQUMvRSxtQkFBbUI7QUFDbkIsK0VBQStFO0FBRS9FOztHQUVHO0FBQ0gsU0FBZ0Isc0JBQXNCLENBQ3BDLFdBQW1CLEVBQ25CLG1CQUEyQixFQUMzQixpQkFBeUI7SUFFekIsT0FBTyxXQUFXLEdBQUcsbUJBQW1CLEdBQUcsaUJBQWlCLENBQUM7QUFDL0QsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsMEJBQTBCLENBQ3hDLHNCQUE4QixFQUM5QixjQUFzQjtJQUV0QixPQUFPLHNCQUFzQixHQUFHLGNBQWMsQ0FBQztBQUNqRCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixjQUFjLENBQUMsTUFBYyxFQUFFLFFBQVEsR0FBRyxLQUFLO0lBQzdELE9BQU8sSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRTtRQUNwQyxLQUFLLEVBQUUsVUFBVTtRQUNqQixRQUFRO0tBQ1QsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNwQixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixhQUFhLENBQzNCLG9CQUE0QjtJQUU1QixJQUFJLG9CQUFvQixHQUFHLE1BQU07UUFBRSxPQUFPLFdBQVcsQ0FBQztJQUN0RCxJQUFJLG9CQUFvQixHQUFHLEtBQUs7UUFBRSxPQUFPLE1BQU0sQ0FBQztJQUNoRCxJQUFJLG9CQUFvQixHQUFHLEtBQUs7UUFBRSxPQUFPLFVBQVUsQ0FBQztJQUNwRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGlua0hpdmUgU0RLIHYzLjEgLSBST0kgQW5hbHl0aWNzIEFQSVxuICpcbiAqIEJ1c2luZXNzIFJPSSAmIE1ldHJpY3MgRW5naW5lIGZvciBjYWxjdWxhdGluZyBmaW5hbmNpYWwgaW1wYWN0XG4gKi9cblxuaW1wb3J0IHsgYXBpUmVxdWVzdCwgYXBpUmVxdWVzdFdpdGhEYXRhIH0gZnJvbSAnLi4vY29yZS9jbGllbnQnO1xuaW1wb3J0IHR5cGUgeyBBcGlSZXNwb25zZSB9IGZyb20gJy4uL2NvcmUvdHlwZXMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEluZHVzdHJ5LXNwZWNpZmljIFJPSSBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW5kdXN0cnlDb25maWcge1xuICBpZDogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIGF2Z1RyYW5zYWN0aW9uVmFsdWU6IG51bWJlcjtcbiAgYXZnQ3VzdG9tZXJMVFY6IG51bWJlcjtcbiAgYXZnU3VwcG9ydENvc3Q6IG51bWJlcjtcbiAgYXZnRXNjYWxhdGlvbkNvc3Q6IG51bWJlcjtcbiAgYXZnUmVzb2x1dGlvblRpbWU6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBDdXN0b20gaW5kdXN0cnkgY29uZmlnIGlucHV0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ3VzdG9tSW5kdXN0cnlDb25maWcge1xuICBpbmR1c3RyeT86IHN0cmluZztcbiAgYXZnVHJhbnNhY3Rpb25WYWx1ZT86IG51bWJlcjtcbiAgYXZnQ3VzdG9tZXJMVFY/OiBudW1iZXI7XG4gIGF2Z1N1cHBvcnRDb3N0PzogbnVtYmVyO1xuICBhdmdFc2NhbGF0aW9uQ29zdD86IG51bWJlcjtcbiAgY2h1cm5JbXBhY3RNdWx0aXBsaWVyPzogbnVtYmVyO1xuICBhdmdSZXNvbHV0aW9uVGltZT86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBST0kgbWV0cmljcyBzdW1tYXJ5XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUk9JTWV0cmljcyB7XG4gIHJvaUNhdGVnb3J5OiBzdHJpbmc7XG4gIHRvdGFsRmluYW5jaWFsSW1wYWN0OiBudW1iZXI7XG4gIHJldmVudWVQcm90ZWN0ZWQ6IG51bWJlcjtcbiAgY29zdFNhdmluZ3M6IG51bWJlcjtcbiAgZWZmaWNpZW5jeUdhaW46IG51bWJlcjtcbn1cblxuLyoqXG4gKiBCdXNpbmVzcyBpbXBhY3QgYW5hbHlzaXMgcmVzdWx0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQnVzaW5lc3NJbXBhY3Qge1xuICBpbXBhY3RTY29yZTogbnVtYmVyO1xuICByZXZlbnVlUmlzazogbnVtYmVyO1xuICBicmFuZFJpc2s6IG51bWJlcjtcbiAgY29tcGxpYW5jZVJpc2s6IG51bWJlcjtcbiAgb3BlcmF0aW9uYWxJbXBhY3Q6IG51bWJlcjtcbiAgY3VzdG9tZXJTYXRpc2ZhY3Rpb246IG51bWJlcjtcbiAgcmVjb21tZW5kYXRpb25zOiBzdHJpbmdbXTtcbiAgcm9pOiBST0lNZXRyaWNzO1xufVxuXG4vKipcbiAqIFJPSSBzdW1tYXJ5IGZvciBhIGRhdGUgcmFuZ2VcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBST0lTdW1tYXJ5IHtcbiAgZGF0ZVJhbmdlOiB7IHN0YXJ0OiBzdHJpbmc7IGVuZDogc3RyaW5nIH07XG4gIHRyYWNlQ291bnQ6IG51bWJlcjtcbiAgc3VjY2Vzc2Z1bEludGVyYWN0aW9uczogbnVtYmVyO1xuICBmYWlsZWRJbnRlcmFjdGlvbnM6IG51bWJlcjtcbiAgc3VjY2Vzc1JhdGU6IG51bWJlcjtcbiAgcm9pOiBST0lNZXRyaWNzO1xuICByZXZlbnVlUHJvdGVjdGVkOiBudW1iZXI7XG4gIGVzdGltYXRlZFNhdmluZ3M6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBEYWlseSB0cmVuZCBkYXRhIHBvaW50XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHJlbmREYXRhUG9pbnQge1xuICBkYXRlOiBzdHJpbmc7XG4gIHRyYWNlQ291bnQ6IG51bWJlcjtcbiAgc3VjY2Vzc0NvdW50OiBudW1iZXI7XG4gIGZhaWx1cmVDb3VudDogbnVtYmVyO1xuICBzdWNjZXNzUmF0ZTogbnVtYmVyO1xuICBhdmdJbXBhY3RTY29yZTogbnVtYmVyO1xufVxuXG4vKipcbiAqIENvcnJlbGF0aW9uIGZpbmRpbmdcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb3JyZWxhdGlvbiB7XG4gIHR5cGU6IHN0cmluZztcbiAgc3RyZW5ndGg6IHN0cmluZztcbiAgY29lZmZpY2llbnQ6IG51bWJlcjtcbiAgY29uZmlkZW5jZTogbnVtYmVyO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICBpbnNpZ2h0OiBzdHJpbmc7XG4gIHJlY29tbWVuZGF0aW9uOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUGF0dGVybiBjbHVzdGVyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGF0dGVybkNsdXN0ZXIge1xuICBpZDogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIG1hdGNoQ291bnQ6IG51bWJlcjtcbiAgYXZnSW1wYWN0U2NvcmU6IG51bWJlcjtcbiAgYXZnQ2h1cm5SaXNrOiBudW1iZXI7XG4gIHRyZW5kOiBzdHJpbmc7XG4gIGV4YW1wbGVzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBDb3JyZWxhdGlvbiBhbmFseXNpcyByZXN1bHRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb3JyZWxhdGlvbkFuYWx5c2lzIHtcbiAgYW5hbHlzaXNJZDogc3RyaW5nO1xuICBhbmFseXplZEF0OiBzdHJpbmc7XG4gIHRyYWNlQ291bnQ6IG51bWJlcjtcbiAgdGltZVJhbmdlOiB7IHN0YXJ0OiBzdHJpbmc7IGVuZDogc3RyaW5nIH07XG4gIG92ZXJhbGxIZWFsdGhTY29yZTogbnVtYmVyO1xuICB0b3BJbnNpZ2h0czogc3RyaW5nW107XG4gIHJlY29tbWVuZGF0aW9uczogc3RyaW5nW107XG4gIGNvcnJlbGF0aW9uczogQ29ycmVsYXRpb25bXTtcbiAgcGF0dGVybkNsdXN0ZXJzOiBQYXR0ZXJuQ2x1c3RlcltdO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBST0kgQU5BTFlUSUNTIEFQSSBDTElFTlRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBST0kgQW5hbHl0aWNzIEFQSSBjbGllbnQgZm9yIGJ1c2luZXNzIGltcGFjdCBhbmFseXNpc1xuICovXG5leHBvcnQgY29uc3Qgcm9pQW5hbHl0aWNzID0ge1xuICAvKipcbiAgICogR2V0IGFnZ3JlZ2F0ZWQgUk9JIHN1bW1hcnkgZm9yIHRyYWNlcyBpbiBkYXRlIHJhbmdlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3Qgc3VtbWFyeSA9IGF3YWl0IHJvaUFuYWx5dGljcy5zdW1tYXJ5KHtcbiAgICogICBzdGFydERhdGU6ICcyMDI0LTAxLTAxJyxcbiAgICogICBlbmREYXRlOiAnMjAyNC0wMS0zMScsXG4gICAqIH0pO1xuICAgKiBjb25zb2xlLmxvZyhgUmV2ZW51ZSBwcm90ZWN0ZWQ6ICQke3N1bW1hcnkucmV2ZW51ZVByb3RlY3RlZH1gKTtcbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBzdW1tYXJ5KG9wdGlvbnM6IHtcbiAgICBzdGFydERhdGU/OiBzdHJpbmcgfCBEYXRlO1xuICAgIGVuZERhdGU/OiBzdHJpbmcgfCBEYXRlO1xuICAgIGFnZW50SWQ/OiBzdHJpbmc7XG4gIH0gPSB7fSk6IFByb21pc2U8Uk9JU3VtbWFyeT4ge1xuICAgIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoKTtcbiAgICBpZiAob3B0aW9ucy5zdGFydERhdGUpIHtcbiAgICAgIHBhcmFtcy5zZXQoJ3N0YXJ0RGF0ZScsIG5ldyBEYXRlKG9wdGlvbnMuc3RhcnREYXRlKS50b0lTT1N0cmluZygpKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuZW5kRGF0ZSkge1xuICAgICAgcGFyYW1zLnNldCgnZW5kRGF0ZScsIG5ldyBEYXRlKG9wdGlvbnMuZW5kRGF0ZSkudG9JU09TdHJpbmcoKSk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLmFnZW50SWQpIHtcbiAgICAgIHBhcmFtcy5zZXQoJ2FnZW50SWQnLCBvcHRpb25zLmFnZW50SWQpO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXBpUmVxdWVzdDxBcGlSZXNwb25zZTx7IHN1bW1hcnk6IFJPSVN1bW1hcnkgfT4+KFxuICAgICAgYC9hbmFseXRpY3Mvcm9pL3N1bW1hcnk/JHtwYXJhbXMudG9TdHJpbmcoKX1gLFxuICAgICAgeyBhcGlWZXJzaW9uOiAndjEnIH1cbiAgICApO1xuICAgIHJldHVybiByZXNwb25zZS5kYXRhIS5zdW1tYXJ5O1xuICB9LFxuXG4gIC8qKlxuICAgKiBHZXQgUk9JIG1ldHJpY3MgZm9yIGEgc3BlY2lmaWMgYWdlbnRcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBhZ2VudFJPSSA9IGF3YWl0IHJvaUFuYWx5dGljcy5ieUFnZW50KCdhZ2VudF8xMjMnLCB7XG4gICAqICAgc3RhcnREYXRlOiAnMjAyNC0wMS0wMScsXG4gICAqIH0pO1xuICAgKiBjb25zb2xlLmxvZyhgQWdlbnQ6ICR7YWdlbnRST0kuYWdlbnQubmFtZX1gKTtcbiAgICogY29uc29sZS5sb2coYFJPSTogJHthZ2VudFJPSS5yb2kudG90YWxGaW5hbmNpYWxJbXBhY3R9YCk7XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgYnlBZ2VudChcbiAgICBhZ2VudElkOiBzdHJpbmcsXG4gICAgb3B0aW9uczoge1xuICAgICAgc3RhcnREYXRlPzogc3RyaW5nIHwgRGF0ZTtcbiAgICAgIGVuZERhdGU/OiBzdHJpbmcgfCBEYXRlO1xuICAgIH0gPSB7fVxuICApOiBQcm9taXNlPHtcbiAgICBhZ2VudDogeyBpZDogc3RyaW5nOyBuYW1lOiBzdHJpbmc7IGluZHVzdHJ5OiBzdHJpbmcgfTtcbiAgICBpbmR1c3RyeUNvbmZpZzogUGFydGlhbDxJbmR1c3RyeUNvbmZpZz47XG4gICAgcm9pOiBST0lNZXRyaWNzO1xuICAgIHJlY2VudEltcGFjdHM6IEFycmF5PHtcbiAgICAgIGltcGFjdFNjb3JlOiBudW1iZXI7XG4gICAgICByZXZlbnVlUmlzazogbnVtYmVyO1xuICAgICAgcm9pQ2F0ZWdvcnk6IHN0cmluZztcbiAgICAgIHRvdGFsRmluYW5jaWFsSW1wYWN0OiBudW1iZXI7XG4gICAgfT47XG4gIH0+IHtcbiAgICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKCk7XG4gICAgaWYgKG9wdGlvbnMuc3RhcnREYXRlKSB7XG4gICAgICBwYXJhbXMuc2V0KCdzdGFydERhdGUnLCBuZXcgRGF0ZShvcHRpb25zLnN0YXJ0RGF0ZSkudG9JU09TdHJpbmcoKSk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLmVuZERhdGUpIHtcbiAgICAgIHBhcmFtcy5zZXQoJ2VuZERhdGUnLCBuZXcgRGF0ZShvcHRpb25zLmVuZERhdGUpLnRvSVNPU3RyaW5nKCkpO1xuICAgIH1cblxuICAgIHJldHVybiBhcGlSZXF1ZXN0V2l0aERhdGEoXG4gICAgICBgL2FuYWx5dGljcy9yb2kvYnktYWdlbnQvJHthZ2VudElkfT8ke3BhcmFtcy50b1N0cmluZygpfWAsXG4gICAgICB7IGFwaVZlcnNpb246ICd2MScgfVxuICAgICk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBST0kgdHJlbmRzIG92ZXIgdGltZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHRyZW5kcyA9IGF3YWl0IHJvaUFuYWx5dGljcy50cmVuZHMoe1xuICAgKiAgIHN0YXJ0RGF0ZTogJzIwMjQtMDEtMDEnLFxuICAgKiAgIGVuZERhdGU6ICcyMDI0LTAxLTMxJyxcbiAgICogfSk7XG4gICAqIGZvciAoY29uc3QgZGF5IG9mIHRyZW5kcykge1xuICAgKiAgIGNvbnNvbGUubG9nKGAke2RheS5kYXRlfTogJHtkYXkuc3VjY2Vzc1JhdGV9JSBzdWNjZXNzYCk7XG4gICAqIH1cbiAgICogYGBgXG4gICAqL1xuICBhc3luYyB0cmVuZHMob3B0aW9uczoge1xuICAgIHN0YXJ0RGF0ZT86IHN0cmluZyB8IERhdGU7XG4gICAgZW5kRGF0ZT86IHN0cmluZyB8IERhdGU7XG4gICAgYWdlbnRJZD86IHN0cmluZztcbiAgfSA9IHt9KTogUHJvbWlzZTxUcmVuZERhdGFQb2ludFtdPiB7XG4gICAgY29uc3QgcGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcygpO1xuICAgIGlmIChvcHRpb25zLnN0YXJ0RGF0ZSkge1xuICAgICAgcGFyYW1zLnNldCgnc3RhcnREYXRlJywgbmV3IERhdGUob3B0aW9ucy5zdGFydERhdGUpLnRvSVNPU3RyaW5nKCkpO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5lbmREYXRlKSB7XG4gICAgICBwYXJhbXMuc2V0KCdlbmREYXRlJywgbmV3IERhdGUob3B0aW9ucy5lbmREYXRlKS50b0lTT1N0cmluZygpKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuYWdlbnRJZCkge1xuICAgICAgcGFyYW1zLnNldCgnYWdlbnRJZCcsIG9wdGlvbnMuYWdlbnRJZCk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBhcGlSZXF1ZXN0PEFwaVJlc3BvbnNlPHsgdHJlbmRzOiBUcmVuZERhdGFQb2ludFtdIH0+PihcbiAgICAgIGAvYW5hbHl0aWNzL3JvaS90cmVuZHM/JHtwYXJhbXMudG9TdHJpbmcoKX1gLFxuICAgICAgeyBhcGlWZXJzaW9uOiAndjEnIH1cbiAgICApO1xuICAgIHJldHVybiByZXNwb25zZS5kYXRhIS50cmVuZHM7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZSBST0kgZm9yIGEgdHJhY2Ugb3IgcHJvdmlkZWQgbWVzc2FnZSBkYXRhXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gQ2FsY3VsYXRlIGZvciBleGlzdGluZyB0cmFjZVxuICAgKiBjb25zdCBpbXBhY3QgPSBhd2FpdCByb2lBbmFseXRpY3MuY2FsY3VsYXRlKHtcbiAgICogICB0cmFjZUlkOiAndHJhY2VfYWJjMTIzJyxcbiAgICogfSk7XG4gICAqXG4gICAqIC8vIENhbGN1bGF0ZSBmb3IgbmV3IGRhdGEgd2l0aCBjdXN0b20gY29uZmlnXG4gICAqIGNvbnN0IGltcGFjdCA9IGF3YWl0IHJvaUFuYWx5dGljcy5jYWxjdWxhdGUoe1xuICAgKiAgIHVzZXJNZXNzYWdlOiAnSGVscCBtZSBjYW5jZWwgbXkgc3Vic2NyaXB0aW9uJyxcbiAgICogICBhZ2VudFJlc3BvbnNlOiAnSSBjYW4gaGVscCB3aXRoIHRoYXQuLi4nLFxuICAgKiAgIGluZHVzdHJ5Q29uZmlnOiB7IGluZHVzdHJ5OiAnc2FhcycsIGF2Z0N1c3RvbWVyTFRWOiAxMDAwMCB9LFxuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBjYWxjdWxhdGUob3B0aW9uczoge1xuICAgIHRyYWNlSWQ/OiBzdHJpbmc7XG4gICAgdXNlck1lc3NhZ2U/OiBzdHJpbmc7XG4gICAgYWdlbnRSZXNwb25zZT86IHN0cmluZztcbiAgICBpbmR1c3RyeUNvbmZpZz86IEN1c3RvbUluZHVzdHJ5Q29uZmlnO1xuICB9KTogUHJvbWlzZTxCdXNpbmVzc0ltcGFjdD4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXBpUmVxdWVzdDxBcGlSZXNwb25zZTx7IGltcGFjdDogQnVzaW5lc3NJbXBhY3QgfT4+KFxuICAgICAgJy9hbmFseXRpY3Mvcm9pL2NhbGN1bGF0ZScsXG4gICAgICB7XG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICBib2R5OiBvcHRpb25zLFxuICAgICAgICBhcGlWZXJzaW9uOiAndjEnLFxuICAgICAgfVxuICAgICk7XG4gICAgcmV0dXJuIHJlc3BvbnNlLmRhdGEhLmltcGFjdDtcbiAgfSxcblxuICAvKipcbiAgICogR2V0IGF2YWlsYWJsZSBpbmR1c3RyeSBjb25maWd1cmF0aW9uc1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IGluZHVzdHJpZXMgPSBhd2FpdCByb2lBbmFseXRpY3MuaW5kdXN0cmllcygpO1xuICAgKiBmb3IgKGNvbnN0IGNvbmZpZyBvZiBpbmR1c3RyaWVzKSB7XG4gICAqICAgY29uc29sZS5sb2coYCR7Y29uZmlnLm5hbWV9OiAkJHtjb25maWcuYXZnQ3VzdG9tZXJMVFZ9IExUVmApO1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgaW5kdXN0cmllcygpOiBQcm9taXNlPEluZHVzdHJ5Q29uZmlnW10+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGFwaVJlcXVlc3Q8QXBpUmVzcG9uc2U8eyBpbmR1c3RyaWVzOiBJbmR1c3RyeUNvbmZpZ1tdIH0+PihcbiAgICAgICcvYW5hbHl0aWNzL3JvaS9pbmR1c3RyaWVzJyxcbiAgICAgIHsgYXBpVmVyc2lvbjogJ3YxJyB9XG4gICAgKTtcbiAgICByZXR1cm4gcmVzcG9uc2UuZGF0YSEuaW5kdXN0cmllcztcbiAgfSxcblxuICAvKipcbiAgICogR2V0IGNvcnJlbGF0aW9uIGFuYWx5c2lzIGZvciB0cmFjZXNcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBhbmFseXNpcyA9IGF3YWl0IHJvaUFuYWx5dGljcy5jb3JyZWxhdGlvbnMoe1xuICAgKiAgIHN0YXJ0RGF0ZTogJzIwMjQtMDEtMDEnLFxuICAgKiAgIGFnZW50SWQ6ICdhZ2VudF8xMjMnLFxuICAgKiB9KTtcbiAgICogY29uc29sZS5sb2coYEhlYWx0aCBzY29yZTogJHthbmFseXNpcy5vdmVyYWxsSGVhbHRoU2NvcmV9YCk7XG4gICAqIGZvciAoY29uc3QgaW5zaWdodCBvZiBhbmFseXNpcy50b3BJbnNpZ2h0cykge1xuICAgKiAgIGNvbnNvbGUubG9nKGAtICR7aW5zaWdodH1gKTtcbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGNvcnJlbGF0aW9ucyhvcHRpb25zOiB7XG4gICAgc3RhcnREYXRlPzogc3RyaW5nIHwgRGF0ZTtcbiAgICBlbmREYXRlPzogc3RyaW5nIHwgRGF0ZTtcbiAgICBhZ2VudElkPzogc3RyaW5nO1xuICB9ID0ge30pOiBQcm9taXNlPENvcnJlbGF0aW9uQW5hbHlzaXM+IHtcbiAgICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKCk7XG4gICAgaWYgKG9wdGlvbnMuc3RhcnREYXRlKSB7XG4gICAgICBwYXJhbXMuc2V0KCdzdGFydERhdGUnLCBuZXcgRGF0ZShvcHRpb25zLnN0YXJ0RGF0ZSkudG9JU09TdHJpbmcoKSk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLmVuZERhdGUpIHtcbiAgICAgIHBhcmFtcy5zZXQoJ2VuZERhdGUnLCBuZXcgRGF0ZShvcHRpb25zLmVuZERhdGUpLnRvSVNPU3RyaW5nKCkpO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5hZ2VudElkKSB7XG4gICAgICBwYXJhbXMuc2V0KCdhZ2VudElkJywgb3B0aW9ucy5hZ2VudElkKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGFwaVJlcXVlc3Q8QXBpUmVzcG9uc2U8eyBhbmFseXNpczogQ29ycmVsYXRpb25BbmFseXNpcyB9Pj4oXG4gICAgICBgL2FuYWx5dGljcy9jb3JyZWxhdGlvbnM/JHtwYXJhbXMudG9TdHJpbmcoKX1gLFxuICAgICAgeyBhcGlWZXJzaW9uOiAndjEnIH1cbiAgICApO1xuICAgIHJldHVybiByZXNwb25zZS5kYXRhIS5hbmFseXNpcztcbiAgfSxcbn07XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEhFTFBFUiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDYWxjdWxhdGUgZXN0aW1hdGVkIHJldmVudWUgYXQgcmlza1xuICovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlUmV2ZW51ZUF0UmlzayhcbiAgZmFpbHVyZVJhdGU6IG51bWJlcixcbiAgYXZnVHJhbnNhY3Rpb25WYWx1ZTogbnVtYmVyLFxuICB0b3RhbEludGVyYWN0aW9uczogbnVtYmVyXG4pOiBudW1iZXIge1xuICByZXR1cm4gZmFpbHVyZVJhdGUgKiBhdmdUcmFuc2FjdGlvblZhbHVlICogdG90YWxJbnRlcmFjdGlvbnM7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIGVzdGltYXRlZCBzYXZpbmdzIGZyb20gYXV0b21hdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlQXV0b21hdGlvblNhdmluZ3MoXG4gIHN1Y2Nlc3NmdWxJbnRlcmFjdGlvbnM6IG51bWJlcixcbiAgYXZnU3VwcG9ydENvc3Q6IG51bWJlclxuKTogbnVtYmVyIHtcbiAgcmV0dXJuIHN1Y2Nlc3NmdWxJbnRlcmFjdGlvbnMgKiBhdmdTdXBwb3J0Q29zdDtcbn1cblxuLyoqXG4gKiBGb3JtYXQgY3VycmVuY3kgZm9yIGRpc3BsYXlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdEN1cnJlbmN5KGFtb3VudDogbnVtYmVyLCBjdXJyZW5jeSA9ICdVU0QnKTogc3RyaW5nIHtcbiAgcmV0dXJuIG5ldyBJbnRsLk51bWJlckZvcm1hdCgnZW4tVVMnLCB7XG4gICAgc3R5bGU6ICdjdXJyZW5jeScsXG4gICAgY3VycmVuY3ksXG4gIH0pLmZvcm1hdChhbW91bnQpO1xufVxuXG4vKipcbiAqIEdldCBST0kgcXVhbGl0eSBsYWJlbFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Uk9JUXVhbGl0eShcbiAgdG90YWxGaW5hbmNpYWxJbXBhY3Q6IG51bWJlclxuKTogJ2V4Y2VsbGVudCcgfCAnZ29vZCcgfCAnbW9kZXJhdGUnIHwgJ3Bvb3InIHtcbiAgaWYgKHRvdGFsRmluYW5jaWFsSW1wYWN0ID4gMTAwMDAwKSByZXR1cm4gJ2V4Y2VsbGVudCc7XG4gIGlmICh0b3RhbEZpbmFuY2lhbEltcGFjdCA+IDUwMDAwKSByZXR1cm4gJ2dvb2QnO1xuICBpZiAodG90YWxGaW5hbmNpYWxJbXBhY3QgPiAxMDAwMCkgcmV0dXJuICdtb2RlcmF0ZSc7XG4gIHJldHVybiAncG9vcic7XG59XG4iXX0=