@garrix82/reactgenie-lib 1.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.
Files changed (85) hide show
  1. package/.env.example +22 -0
  2. package/.github/workflows/publish.yml +20 -0
  3. package/LICENSE.txt +201 -0
  4. package/README.md +621 -0
  5. package/babel.config.js +29 -0
  6. package/dist/adapters/__tests__/expo-router-adapter.test.d.ts +1 -0
  7. package/dist/adapters/expo-router-adapter.d.ts +16 -0
  8. package/dist/adapters/expo-router-adapter.js +521 -0
  9. package/dist/adapters/navigation-adapter.d.ts +20 -0
  10. package/dist/adapters/navigation-adapter.js +137 -0
  11. package/dist/audio-visualizer.d.ts +14 -0
  12. package/dist/audio-visualizer.js +123 -0
  13. package/dist/current-selection.d.ts +27 -0
  14. package/dist/current-selection.js +94 -0
  15. package/dist/errors.d.ts +19 -0
  16. package/dist/errors.js +37 -0
  17. package/dist/genie/DateTime.d.ts +66 -0
  18. package/dist/genie/DateTime.js +399 -0
  19. package/dist/genie/TimeDelta.d.ts +35 -0
  20. package/dist/genie/TimeDelta.js +169 -0
  21. package/dist/genie-view-wrapper.d.ts +1 -0
  22. package/dist/genie-view-wrapper.js +377 -0
  23. package/dist/hooks/__tests__/useSpeechRecognition.test.d.ts +1 -0
  24. package/dist/hooks/useSpeechRecognition.d.ts +28 -0
  25. package/dist/hooks/useSpeechRecognition.js +118 -0
  26. package/dist/index.d.ts +30 -0
  27. package/dist/index.js +469 -0
  28. package/dist/logger.d.ts +23 -0
  29. package/dist/logger.js +597 -0
  30. package/dist/logger.remote.test.d.ts +0 -0
  31. package/dist/modality-provider-v2.d.ts +28 -0
  32. package/dist/modality-provider-v2.js +1321 -0
  33. package/dist/modality-provider.d.ts +22 -0
  34. package/dist/modality-provider.js +373 -0
  35. package/dist/native-visibility.d.ts +28 -0
  36. package/dist/native-visibility.js +50 -0
  37. package/dist/platform/VoiceRecognitionBar.d.ts +17 -0
  38. package/dist/platform/VoiceRecognitionBar.js +332 -0
  39. package/dist/platform/components.d.ts +32 -0
  40. package/dist/platform/components.js +351 -0
  41. package/dist/platform/events.d.ts +31 -0
  42. package/dist/platform/events.js +274 -0
  43. package/dist/platform/index.d.ts +3 -0
  44. package/dist/platform/index.js +39 -0
  45. package/dist/platform/types.d.ts +79 -0
  46. package/dist/platform/types.js +97 -0
  47. package/dist/react-decorators.d.ts +87 -0
  48. package/dist/react-decorators.js +368 -0
  49. package/dist/shared-store.d.ts +74 -0
  50. package/dist/shared-store.js +589 -0
  51. package/dist/speech-recognition/__tests__/speech-recognition-groq-transport.test.d.ts +1 -0
  52. package/dist/speech-recognition/__tests__/speech-recognition-native.test.d.ts +1 -0
  53. package/dist/speech-recognition/__tests__/speech-recognition-openai-native.test.d.ts +1 -0
  54. package/dist/speech-recognition/__tests__/speech-recognition-openai.test.d.ts +1 -0
  55. package/dist/speech-recognition/__tests__/speech-recognition-unified-import.test.d.ts +0 -0
  56. package/dist/speech-recognition/__tests__/speech-recognition-unified.test.d.ts +1 -0
  57. package/dist/speech-recognition/speech-recognition-groq.d.ts +21 -0
  58. package/dist/speech-recognition/speech-recognition-groq.js +409 -0
  59. package/dist/speech-recognition/speech-recognition-mlx.d.ts +15 -0
  60. package/dist/speech-recognition/speech-recognition-mlx.js +393 -0
  61. package/dist/speech-recognition/speech-recognition-native.d.ts +24 -0
  62. package/dist/speech-recognition/speech-recognition-native.js +632 -0
  63. package/dist/speech-recognition/speech-recognition-openai-native.d.ts +40 -0
  64. package/dist/speech-recognition/speech-recognition-openai-native.js +653 -0
  65. package/dist/speech-recognition/speech-recognition-openai.d.ts +39 -0
  66. package/dist/speech-recognition/speech-recognition-openai.js +718 -0
  67. package/dist/speech-recognition/speech-recognition-unified.d.ts +93 -0
  68. package/dist/speech-recognition/speech-recognition-unified.js +589 -0
  69. package/dist/speech-recognition/utils/groq-transcription.d.ts +41 -0
  70. package/dist/speech-recognition/utils/groq-transcription.js +382 -0
  71. package/dist/speech-recognition.d.ts +7 -0
  72. package/dist/speech-recognition.js +61 -0
  73. package/dist/voice-pipeline-telemetry.d.ts +26 -0
  74. package/dist/voice-pipeline-telemetry.js +15 -0
  75. package/garrix82-reactgenie-lib-1.3.0.tgz +0 -0
  76. package/metro/index.js +3 -0
  77. package/metro/with-genie-registry.js +47 -0
  78. package/package.json +111 -0
  79. package/scripts/dry-run.js +23 -0
  80. package/scripts/generate-genie-registry.js +278 -0
  81. package/scripts/log-file-test.js +51 -0
  82. package/scripts/parse.js +26 -0
  83. package/scripts/prompt.js +19 -0
  84. package/scripts/set-script.js +200 -0
  85. package/tsconfig.json +36 -0
@@ -0,0 +1,589 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.UnifiedSpeechRecognizer = void 0;
7
+ Object.defineProperty(exports, "getGroqSpeechCapabilities", {
8
+ enumerable: true,
9
+ get: function () {
10
+ return _speechRecognitionGroq.getGroqSpeechCapabilities;
11
+ }
12
+ });
13
+ Object.defineProperty(exports, "getOpenAISpeechCapabilities", {
14
+ enumerable: true,
15
+ get: function () {
16
+ return _speechRecognitionOpenai.getOpenAISpeechCapabilities;
17
+ }
18
+ });
19
+ exports.getSpeechRecognitionConfig = getSpeechRecognitionConfig;
20
+ exports.getSpeechRecognitionStatus = getSpeechRecognitionStatus;
21
+ Object.defineProperty(exports, "isGroqSpeechAvailable", {
22
+ enumerable: true,
23
+ get: function () {
24
+ return _speechRecognitionGroq.isGroqSpeechAvailable;
25
+ }
26
+ });
27
+ Object.defineProperty(exports, "isOpenAISpeechAvailable", {
28
+ enumerable: true,
29
+ get: function () {
30
+ return _speechRecognitionOpenai.isOpenAISpeechAvailable;
31
+ }
32
+ });
33
+ exports.isWebSpeechAvailable = void 0;
34
+ exports.selectSpeechRecognitionMethod = selectSpeechRecognitionMethod;
35
+ var _react = _interopRequireDefault(require("react"));
36
+ var _reactNative = require("react-native");
37
+ var _speechRecognition = require("../speech-recognition");
38
+ var _speechRecognitionGroq = require("./speech-recognition-groq");
39
+ var _speechRecognitionMlx = require("./speech-recognition-mlx");
40
+ var _speechRecognitionOpenai = require("./speech-recognition-openai");
41
+ var _logger = _interopRequireDefault(require("../logger"));
42
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
43
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
44
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
45
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
46
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
47
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /**
48
+ * Unified Speech Recognition Component
49
+ * Automatically selects best speech recognition method based on:
50
+ * 1. Platform (Web vs Native)
51
+ * 2. Environment configuration
52
+ * 3. Feature availability
53
+ */
54
+ /**
55
+ * Configuration for speech recognition.
56
+ * Resolved from in-code defaults + explicit runtime overrides passed via props.
57
+ */
58
+
59
+ function normalizeProvider(value) {
60
+ if (!value) return undefined;
61
+ const normalized = value.trim().toLowerCase();
62
+ if (normalized === "groq") return "groq";
63
+ if (normalized === "openai") return "openai";
64
+ return undefined;
65
+ }
66
+ const DEFAULT_REALTIME_MODEL = "gpt-4o-transcribe";
67
+ const DEFAULT_TRANSLATION_MODEL = "gpt-4.1-mini";
68
+ const DEFAULT_OPENAI_AUTO_STOP_ON_VAD_SILENCE = false;
69
+ const DEFAULT_OPENAI_VAD_SILENCE_DURATION_MS = 2000;
70
+ const DEFAULT_OPENAI_PREWARM_ON_MOUNT = true;
71
+ function getRuntimeEnvValue(key) {
72
+ try {
73
+ const env = typeof process !== "undefined" ? process.env : undefined;
74
+ const value = env?.[key];
75
+ if (typeof value !== "string") return undefined;
76
+ const trimmed = value.trim();
77
+ return trimmed.length > 0 ? trimmed : undefined;
78
+ } catch {
79
+ return undefined;
80
+ }
81
+ }
82
+ function parseBooleanEnv(key, fallback) {
83
+ const raw = getRuntimeEnvValue(key);
84
+ if (!raw) return fallback;
85
+ const normalized = raw.toLowerCase();
86
+ if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") {
87
+ return true;
88
+ }
89
+ if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") {
90
+ return false;
91
+ }
92
+ return fallback;
93
+ }
94
+ function parseNumberEnv(key, fallback) {
95
+ const raw = getRuntimeEnvValue(key);
96
+ if (!raw) return fallback;
97
+ const parsed = Number(raw);
98
+ if (!Number.isFinite(parsed)) return fallback;
99
+ return parsed;
100
+ }
101
+ const toOpenAIEndpointsFromBaseUrl = baseUrl => {
102
+ const trimmed = (baseUrl || "").trim().replace(/\/+$/, "");
103
+ if (!trimmed) {
104
+ return {
105
+ transcriptionSessionEndpoint: undefined,
106
+ translationEndpoint: undefined
107
+ };
108
+ }
109
+ return {
110
+ transcriptionSessionEndpoint: `${trimmed}/openai/v1/realtime/transcription_sessions`,
111
+ translationEndpoint: `${trimmed}/openai/v1/speech/translate-to-english`
112
+ };
113
+ };
114
+ function resolveOpenAIConfig(config) {
115
+ const defaults = {
116
+ realtimeModel: DEFAULT_REALTIME_MODEL,
117
+ translationModel: DEFAULT_TRANSLATION_MODEL,
118
+ vadEnabled: true,
119
+ autoStopOnVadSilence: parseBooleanEnv("OPENAI_AUTO_STOP_ON_VAD_SILENCE", DEFAULT_OPENAI_AUTO_STOP_ON_VAD_SILENCE),
120
+ vadThreshold: 0.7,
121
+ vadPrefixPaddingMs: 400,
122
+ vadSilenceDurationMs: parseNumberEnv("OPENAI_VAD_SILENCE_DURATION_MS", DEFAULT_OPENAI_VAD_SILENCE_DURATION_MS),
123
+ vadIdleTimeoutMs: 6000,
124
+ prewarmOnMount: parseBooleanEnv("OPENAI_PREWARM_ON_MOUNT", DEFAULT_OPENAI_PREWARM_ON_MOUNT)
125
+ };
126
+ const nested = config?.openai || {};
127
+ const endpointBase = nested.proxyBaseUrl;
128
+ const derivedEndpoints = toOpenAIEndpointsFromBaseUrl(endpointBase);
129
+ return _objectSpread(_objectSpread(_objectSpread({}, defaults), nested), {}, {
130
+ transcriptionSessionEndpoint: nested.transcriptionSessionEndpoint || derivedEndpoints.transcriptionSessionEndpoint,
131
+ translationEndpoint: nested.translationEndpoint || derivedEndpoints.translationEndpoint,
132
+ realtimeWebRtcUrl: nested.realtimeWebRtcUrl,
133
+ realtimeModel: nested.realtimeModel || defaults.realtimeModel,
134
+ translationModel: nested.translationModel || defaults.translationModel,
135
+ vadEnabled: nested.vadEnabled ?? defaults.vadEnabled,
136
+ autoStopOnVadSilence: nested.autoStopOnVadSilence ?? defaults.autoStopOnVadSilence,
137
+ vadThreshold: nested.vadThreshold ?? defaults.vadThreshold,
138
+ vadPrefixPaddingMs: nested.vadPrefixPaddingMs ?? defaults.vadPrefixPaddingMs,
139
+ vadSilenceDurationMs: nested.vadSilenceDurationMs ?? defaults.vadSilenceDurationMs,
140
+ vadIdleTimeoutMs: nested.vadIdleTimeoutMs ?? defaults.vadIdleTimeoutMs,
141
+ prewarmOnMount: nested.prewarmOnMount ?? defaults.prewarmOnMount
142
+ });
143
+ }
144
+ function resolveGroqConfig(config) {
145
+ const defaults = {
146
+ enabled: true,
147
+ stream: true
148
+ };
149
+ return _objectSpread(_objectSpread({}, defaults), config?.groq || {});
150
+ }
151
+ function resolveLocalModelConfig(config) {
152
+ const defaults = {
153
+ enabledOnWeb: false,
154
+ baseUrl: "http://127.0.0.1:8000",
155
+ mode: "oneshot",
156
+ model: "large-v3-turbo"
157
+ };
158
+ return _objectSpread(_objectSpread({}, defaults), config?.localModel || {});
159
+ }
160
+
161
+ /**
162
+ * Load speech recognition config from defaults + explicit overrides.
163
+ */
164
+ function getSpeechRecognitionConfig(overrides) {
165
+ const defaults = {
166
+ provider: "groq",
167
+ fallbackToWebSpeech: true,
168
+ groq: resolveGroqConfig(),
169
+ openai: resolveOpenAIConfig(),
170
+ localModel: resolveLocalModelConfig()
171
+ };
172
+ const merged = _objectSpread(_objectSpread(_objectSpread({}, defaults), overrides || {}), {}, {
173
+ provider: normalizeProvider(overrides?.provider) || normalizeProvider(defaults.provider) || "groq"
174
+ });
175
+ return _objectSpread(_objectSpread({}, merged), {}, {
176
+ groq: resolveGroqConfig(merged),
177
+ openai: resolveOpenAIConfig(merged),
178
+ localModel: resolveLocalModelConfig(merged)
179
+ });
180
+ }
181
+
182
+ /**
183
+ * Check if Web Speech API is available
184
+ */
185
+ function checkWebSpeechAvailability() {
186
+ if (typeof window === "undefined") {
187
+ return false;
188
+ }
189
+ return "webkitSpeechRecognition" in window || "SpeechRecognition" in window;
190
+ }
191
+ const isWebSpeechAvailable = exports.isWebSpeechAvailable = checkWebSpeechAvailability;
192
+ const normalizeLanguageTag = lang => {
193
+ const normalized = (lang || "en").trim().toLowerCase();
194
+ return normalized.length > 0 ? normalized : "en";
195
+ };
196
+ const toShortLanguageCode = lang => lang.split("-")[0];
197
+ const toWebSpeechLocale = lang => {
198
+ if (lang.startsWith("en")) return "en-US";
199
+ if (lang.startsWith("de")) return "de-DE";
200
+ return lang;
201
+ };
202
+
203
+ /**
204
+ * Types of speech recognition methods
205
+ */
206
+
207
+ let nativeSpeechModuleCache;
208
+ let openAiNativeSpeechModuleCache;
209
+ function getNativeSpeechModule() {
210
+ if (nativeSpeechModuleCache !== undefined) {
211
+ return nativeSpeechModuleCache;
212
+ }
213
+ try {
214
+ // Keep native module lazy to avoid loading native-only dependencies on web.
215
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
216
+ nativeSpeechModuleCache = require("./speech-recognition-native");
217
+ } catch (error) {
218
+ nativeSpeechModuleCache = null;
219
+ _logger.default.debug("Native speech module unavailable:", error);
220
+ }
221
+ return nativeSpeechModuleCache;
222
+ }
223
+ function isNativeRecognizerAvailable() {
224
+ const nativeModule = getNativeSpeechModule();
225
+ return !!nativeModule?.isNativeSpeechAvailable?.();
226
+ }
227
+ function getOpenAINativeSpeechModule() {
228
+ if (openAiNativeSpeechModuleCache !== undefined) {
229
+ return openAiNativeSpeechModuleCache;
230
+ }
231
+ try {
232
+ // Keep native module lazy to avoid loading native-only dependencies on web.
233
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
234
+ openAiNativeSpeechModuleCache = require("./speech-recognition-openai-native");
235
+ } catch (error) {
236
+ openAiNativeSpeechModuleCache = null;
237
+ _logger.default.debug("OpenAI native speech module unavailable:", error);
238
+ }
239
+ return openAiNativeSpeechModuleCache;
240
+ }
241
+ function isOpenAINativeRecognizerAvailable() {
242
+ const nativeModule = getOpenAINativeSpeechModule();
243
+ return !!nativeModule?.isOpenAINativeSpeechAvailable?.();
244
+ }
245
+
246
+ /**
247
+ * Determine which speech recognition method to use
248
+ */
249
+ function selectSpeechRecognitionMethod(config, clientSecret) {
250
+ const isWeb = _reactNative.Platform.OS === "web";
251
+ const isNative = _reactNative.Platform.OS === "ios" || _reactNative.Platform.OS === "android";
252
+ const isWebClientRuntime = isWeb && typeof window !== "undefined";
253
+ const shouldWarnUnavailable = isWebClientRuntime;
254
+ const provider = normalizeProvider(config.provider) || "groq";
255
+ const groq = resolveGroqConfig(config);
256
+ const openai = resolveOpenAIConfig(config);
257
+ const localModel = resolveLocalModelConfig(config);
258
+ const hasGroqKey = !!(clientSecret || groq.apiKey);
259
+ if (provider === "openai") {
260
+ if (isNative) {
261
+ if (openai.transcriptionSessionEndpoint && isOpenAINativeRecognizerAvailable()) {
262
+ _logger.default.info("✅ Using OpenAI Native Realtime (WebRTC)");
263
+ return "openai-native";
264
+ }
265
+ if (shouldWarnUnavailable) {
266
+ _logger.default.warn("⚠️ OpenAI native speech unavailable. Configure OPENAI_TRANSCRIPTION_SESSION_ENDPOINT and install react-native-webrtc.");
267
+ }
268
+ return "none";
269
+ }
270
+ if (isWeb) {
271
+ if (openai.transcriptionSessionEndpoint && (0, _speechRecognitionOpenai.isOpenAISpeechAvailable)()) {
272
+ _logger.default.info("✅ Using OpenAI Web Realtime (WebRTC)");
273
+ return "openai-web";
274
+ }
275
+ if (shouldWarnUnavailable) {
276
+ _logger.default.warn("⚠️ OpenAI web speech unavailable");
277
+ }
278
+ return "none";
279
+ }
280
+ }
281
+
282
+ // Native platforms: Use native Groq implementation
283
+ if (isNative) {
284
+ if (groq.enabled && hasGroqKey && isNativeRecognizerAvailable()) {
285
+ _logger.default.info("✅ Using Groq Native (expo-audio)");
286
+ return "groq-native";
287
+ }
288
+ if (shouldWarnUnavailable) {
289
+ _logger.default.warn("⚠️ No speech recognition available on native (install expo-audio + expo-file-system and run a dev client build)");
290
+ }
291
+ return "none";
292
+ }
293
+
294
+ // Web platform: Can use both, prefer based on config
295
+ if (isWeb) {
296
+ if (localModel.enabledOnWeb && localModel.baseUrl) {
297
+ _logger.default.info("✅ Using Local MLX Whisper server");
298
+ return "mlx-local";
299
+ }
300
+
301
+ // Use Groq if enabled and available
302
+ if (groq.enabled && hasGroqKey && (0, _speechRecognitionGroq.isGroqSpeechAvailable)()) {
303
+ _logger.default.info("✅ Using Groq Web (Enabled and available)");
304
+ return "groq-web";
305
+ }
306
+
307
+ // Fallback to Web Speech API
308
+ if (config.fallbackToWebSpeech && isWebSpeechAvailable()) {
309
+ _logger.default.info("✅ Using Web Speech API (Fallback)");
310
+ return "webspeech";
311
+ }
312
+ }
313
+ if (shouldWarnUnavailable) {
314
+ _logger.default.warn("⚠️ No speech recognition method available");
315
+ }
316
+ return "none";
317
+ }
318
+
319
+ /**
320
+ * Unified Speech Recognizer Component
321
+ * Automatically selects and uses the best speech recognition method
322
+ */
323
+ const UnifiedSpeechRecognizer = ({
324
+ shouldListen,
325
+ speechStatusCallback,
326
+ speechResultCallback,
327
+ speechTranslationCallback,
328
+ speechReadyCallback,
329
+ waveformPreviewCallback,
330
+ clientSecret,
331
+ language = "en",
332
+ onError,
333
+ requestContextProvider,
334
+ config
335
+ }) => {
336
+ // Get configuration
337
+ const resolvedConfig = getSpeechRecognitionConfig(config);
338
+ const isWebClientRuntime = _reactNative.Platform.OS === "web" && typeof window !== "undefined";
339
+ const normalizedLanguage = normalizeLanguageTag(language);
340
+ const apiLanguage = toShortLanguageCode(normalizedLanguage);
341
+ const webSpeechLanguage = toWebSpeechLocale(normalizedLanguage);
342
+
343
+ // Determine which method to use
344
+ const method = selectSpeechRecognitionMethod(resolvedConfig, clientSecret);
345
+ if (isWebClientRuntime) {
346
+ _logger.default.debug("Selected speech recognition method:", method);
347
+ }
348
+ const groqConfig = resolveGroqConfig(resolvedConfig);
349
+ const openaiConfig = resolveOpenAIConfig(resolvedConfig);
350
+ const localModelConfig = resolveLocalModelConfig(resolvedConfig);
351
+ const finalGroqApiKey = clientSecret || groqConfig.apiKey || "";
352
+ const groqApiBaseUrl = groqConfig.apiBaseUrl;
353
+ const groqTranscriptionEndpoint = groqConfig.transcriptionEndpoint;
354
+ const streamGroq = groqConfig.stream;
355
+ if (groqConfig.enabled && !finalGroqApiKey) {
356
+ _logger.default.warn("Groq speech is enabled but no API key was provided. Pass a non-secret client key or disable Groq speech.");
357
+ }
358
+
359
+ // Error handler with fallback
360
+ const handleError = error => {
361
+ _logger.default.error("Speech recognition error:", error);
362
+ if (onError) {
363
+ onError(error);
364
+ }
365
+
366
+ // If Groq fails and fallback is enabled, we could switch to Web Speech
367
+ // (This would require more complex state management)
368
+ };
369
+
370
+ // Render appropriate component based on method
371
+ switch (method) {
372
+ case "openai-native":
373
+ {
374
+ if (!openaiConfig.transcriptionSessionEndpoint) {
375
+ _logger.default.error("OpenAI transcription session endpoint is required but not provided");
376
+ return null;
377
+ }
378
+ const openaiNativeModule = getOpenAINativeSpeechModule();
379
+ if (!openaiNativeModule?.OpenAINativeSpeechRecognizer) {
380
+ _logger.default.error("OpenAI native speech module unavailable. Install react-native-webrtc and use a native/dev build.");
381
+ return null;
382
+ }
383
+ const OpenAINativeSpeechRecognizer = openaiNativeModule.OpenAINativeSpeechRecognizer;
384
+ return /*#__PURE__*/_react.default.createElement(OpenAINativeSpeechRecognizer, {
385
+ shouldListen: shouldListen,
386
+ speechStatusCallback: speechStatusCallback,
387
+ speechResultCallback: speechResultCallback,
388
+ speechTranslationCallback: speechTranslationCallback,
389
+ speechReadyCallback: speechReadyCallback,
390
+ clientSecret: finalGroqApiKey,
391
+ openaiTranscriptionSessionEndpoint: openaiConfig.transcriptionSessionEndpoint,
392
+ openaiTranslationEndpoint: openaiConfig.translationEndpoint,
393
+ openaiRealtimeWebRtcUrl: openaiConfig.realtimeWebRtcUrl,
394
+ openaiRealtimeModel: openaiConfig.realtimeModel,
395
+ openaiTranslationModel: openaiConfig.translationModel,
396
+ openaiVadEnabled: openaiConfig.vadEnabled,
397
+ openaiAutoStopOnVadSilence: openaiConfig.autoStopOnVadSilence,
398
+ openaiVadThreshold: openaiConfig.vadThreshold,
399
+ openaiVadPrefixPaddingMs: openaiConfig.vadPrefixPaddingMs,
400
+ openaiVadSilenceDurationMs: openaiConfig.vadSilenceDurationMs,
401
+ openaiVadIdleTimeoutMs: openaiConfig.vadIdleTimeoutMs,
402
+ openaiPrewarmOnMount: openaiConfig.prewarmOnMount,
403
+ language: apiLanguage,
404
+ requestContextProvider: requestContextProvider,
405
+ onError: handleError
406
+ });
407
+ }
408
+ case "openai-web":
409
+ if (!openaiConfig.transcriptionSessionEndpoint) {
410
+ _logger.default.error("OpenAI transcription session endpoint is required but not provided");
411
+ return null;
412
+ }
413
+ return /*#__PURE__*/_react.default.createElement(_speechRecognitionOpenai.OpenAISpeechRecognizer, {
414
+ shouldListen: shouldListen,
415
+ speechStatusCallback: speechStatusCallback,
416
+ speechResultCallback: speechResultCallback,
417
+ speechTranslationCallback: speechTranslationCallback,
418
+ speechReadyCallback: speechReadyCallback,
419
+ clientSecret: finalGroqApiKey,
420
+ openaiTranscriptionSessionEndpoint: openaiConfig.transcriptionSessionEndpoint,
421
+ openaiTranslationEndpoint: openaiConfig.translationEndpoint,
422
+ openaiRealtimeWebRtcUrl: openaiConfig.realtimeWebRtcUrl,
423
+ openaiRealtimeModel: openaiConfig.realtimeModel,
424
+ openaiTranslationModel: openaiConfig.translationModel,
425
+ openaiVadEnabled: openaiConfig.vadEnabled,
426
+ openaiAutoStopOnVadSilence: openaiConfig.autoStopOnVadSilence,
427
+ openaiVadThreshold: openaiConfig.vadThreshold,
428
+ openaiVadPrefixPaddingMs: openaiConfig.vadPrefixPaddingMs,
429
+ openaiVadSilenceDurationMs: openaiConfig.vadSilenceDurationMs,
430
+ openaiVadIdleTimeoutMs: openaiConfig.vadIdleTimeoutMs,
431
+ openaiPrewarmOnMount: openaiConfig.prewarmOnMount,
432
+ language: apiLanguage,
433
+ requestContextProvider: requestContextProvider,
434
+ onError: handleError
435
+ });
436
+ case "groq-native":
437
+ {
438
+ if (!finalGroqApiKey) {
439
+ _logger.default.error("Groq API key is required but not provided");
440
+ return null;
441
+ }
442
+ const nativeModule = getNativeSpeechModule();
443
+ if (!nativeModule?.NativeSpeechRecognizer) {
444
+ _logger.default.error("Native speech module is unavailable. Install expo-audio + expo-file-system and use a dev client build.");
445
+ return null;
446
+ }
447
+ const NativeSpeechRecognizer = nativeModule.NativeSpeechRecognizer;
448
+ return /*#__PURE__*/_react.default.createElement(NativeSpeechRecognizer, {
449
+ shouldListen: shouldListen,
450
+ speechStatusCallback: speechStatusCallback,
451
+ speechResultCallback: speechResultCallback,
452
+ speechTranslationCallback: speechTranslationCallback,
453
+ clientSecret: finalGroqApiKey,
454
+ groqApiBaseUrl: groqApiBaseUrl,
455
+ groqTranscriptionEndpoint: groqTranscriptionEndpoint,
456
+ stream: streamGroq,
457
+ language: apiLanguage,
458
+ onError: handleError
459
+ });
460
+ }
461
+ case "groq-web":
462
+ if (!finalGroqApiKey) {
463
+ _logger.default.error("Groq API key is required but not provided");
464
+ return null;
465
+ }
466
+ return /*#__PURE__*/_react.default.createElement(_speechRecognitionGroq.GroqSpeechRecognizer, {
467
+ shouldListen: shouldListen,
468
+ speechStatusCallback: speechStatusCallback,
469
+ speechResultCallback: speechResultCallback,
470
+ speechTranslationCallback: speechTranslationCallback,
471
+ clientSecret: finalGroqApiKey,
472
+ groqApiBaseUrl: groqApiBaseUrl,
473
+ groqTranscriptionEndpoint: groqTranscriptionEndpoint,
474
+ stream: streamGroq,
475
+ language: apiLanguage,
476
+ onError: handleError
477
+ });
478
+ case "mlx-local":
479
+ {
480
+ const effectiveUrl = localModelConfig.baseUrl;
481
+ if (!effectiveUrl) {
482
+ _logger.default.error("Local whisper URL is required but not provided");
483
+ return null;
484
+ }
485
+ return /*#__PURE__*/_react.default.createElement(_speechRecognitionMlx.MLXSpeechRecognizer, {
486
+ shouldListen: shouldListen,
487
+ speechStatusCallback: speechStatusCallback,
488
+ speechResultCallback: speechResultCallback,
489
+ language: apiLanguage,
490
+ onError: handleError,
491
+ baseUrl: effectiveUrl,
492
+ mode: localModelConfig.mode,
493
+ modelName: localModelConfig.model
494
+ });
495
+ }
496
+ case "webspeech":
497
+ return /*#__PURE__*/_react.default.createElement(_speechRecognition.SpeechRecognizer, {
498
+ shouldListen: shouldListen,
499
+ speechStatusCallback: speechStatusCallback,
500
+ speechResultCallback: speechResultCallback,
501
+ language: webSpeechLanguage
502
+ });
503
+ case "none":
504
+ default:
505
+ if (isWebClientRuntime) {
506
+ _logger.default.warn("No speech recognition available");
507
+ }
508
+ return null;
509
+ }
510
+ };
511
+
512
+ /**
513
+ * Get speech recognition status and capabilities
514
+ */
515
+ exports.UnifiedSpeechRecognizer = UnifiedSpeechRecognizer;
516
+ function getSpeechRecognitionStatus(overrides) {
517
+ const config = getSpeechRecognitionConfig(overrides);
518
+ const method = selectSpeechRecognitionMethod(config);
519
+ const localModel = resolveLocalModelConfig(config);
520
+ return {
521
+ method,
522
+ config,
523
+ capabilities: {
524
+ groq: (0, _speechRecognitionGroq.getGroqSpeechCapabilities)(),
525
+ openai: (0, _speechRecognitionOpenai.getOpenAISpeechCapabilities)(),
526
+ webSpeech: {
527
+ available: isWebSpeechAvailable(),
528
+ platform: _reactNative.Platform.OS
529
+ },
530
+ localModel: {
531
+ enabled: !!localModel.enabledOnWeb,
532
+ url: localModel.baseUrl,
533
+ mode: localModel.mode || "oneshot"
534
+ }
535
+ },
536
+ recommendations: getRecommendations(method, config)
537
+ };
538
+ }
539
+
540
+ /**
541
+ * Get recommendations for improving speech recognition
542
+ */
543
+ function getRecommendations(method, config) {
544
+ const recommendations = [];
545
+ if (method === "none") {
546
+ recommendations.push("No speech recognition available");
547
+ if (!config.groq?.apiKey && config.provider !== "openai") {
548
+ recommendations.push("Provide a Groq client secret via config or disable Groq speech");
549
+ }
550
+ if (_reactNative.Platform.OS === "web") {
551
+ if (!(0, _speechRecognitionGroq.isGroqSpeechAvailable)()) {
552
+ recommendations.push("Browser does not support MediaRecorder API");
553
+ }
554
+ if (!isWebSpeechAvailable()) {
555
+ recommendations.push("Browser does not support Web Speech API");
556
+ }
557
+ } else {
558
+ recommendations.push("Install expo-audio + expo-file-system and use a dev client build");
559
+ }
560
+ }
561
+ if (method === "webspeech") {
562
+ recommendations.push("Using Web Speech API (free but less accurate)");
563
+ recommendations.push("Enable Groq speech for better accuracy");
564
+ }
565
+ if (method === "groq-web") {
566
+ recommendations.push("Using Groq Web (high accuracy, best for web)");
567
+ }
568
+ if (method === "groq-native") {
569
+ recommendations.push("Using Groq Native capture (expo-audio)");
570
+ }
571
+ if (method === "openai-web") {
572
+ recommendations.push("Using OpenAI Web Realtime with server VAD");
573
+ }
574
+ if (method === "openai-native") {
575
+ recommendations.push("Using OpenAI Native Realtime with PCM stream");
576
+ }
577
+ if (method === "mlx-local") {
578
+ recommendations.push("Using Local MLX Whisper server (fast, offline)");
579
+ if (!config.localModel?.baseUrl) {
580
+ recommendations.push("Set LOCAL_WHISPER_URL to point at your server");
581
+ }
582
+ }
583
+ return recommendations;
584
+ }
585
+
586
+ // Export for convenience
587
+ // Default export
588
+ var _default = exports.default = UnifiedSpeechRecognizer;
589
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9yZWFjdE5hdGl2ZSIsIl9zcGVlY2hSZWNvZ25pdGlvbiIsIl9zcGVlY2hSZWNvZ25pdGlvbkdyb3EiLCJfc3BlZWNoUmVjb2duaXRpb25NbHgiLCJfc3BlZWNoUmVjb2duaXRpb25PcGVuYWkiLCJfbG9nZ2VyIiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0Iiwib3duS2V5cyIsInIiLCJ0IiwiT2JqZWN0Iiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzIiwiZGVmaW5lUHJvcGVydGllcyIsImRlZmluZVByb3BlcnR5IiwiX3RvUHJvcGVydHlLZXkiLCJ2YWx1ZSIsImNvbmZpZ3VyYWJsZSIsIndyaXRhYmxlIiwiaSIsIl90b1ByaW1pdGl2ZSIsIlN5bWJvbCIsInRvUHJpbWl0aXZlIiwiY2FsbCIsIlR5cGVFcnJvciIsIlN0cmluZyIsIk51bWJlciIsIm5vcm1hbGl6ZVByb3ZpZGVyIiwidW5kZWZpbmVkIiwibm9ybWFsaXplZCIsInRyaW0iLCJ0b0xvd2VyQ2FzZSIsIkRFRkFVTFRfUkVBTFRJTUVfTU9ERUwiLCJERUZBVUxUX1RSQU5TTEFUSU9OX01PREVMIiwiREVGQVVMVF9PUEVOQUlfQVVUT19TVE9QX09OX1ZBRF9TSUxFTkNFIiwiREVGQVVMVF9PUEVOQUlfVkFEX1NJTEVOQ0VfRFVSQVRJT05fTVMiLCJERUZBVUxUX09QRU5BSV9QUkVXQVJNX09OX01PVU5UIiwiZ2V0UnVudGltZUVudlZhbHVlIiwia2V5IiwiZW52IiwicHJvY2VzcyIsInRyaW1tZWQiLCJwYXJzZUJvb2xlYW5FbnYiLCJmYWxsYmFjayIsInJhdyIsInBhcnNlTnVtYmVyRW52IiwicGFyc2VkIiwiaXNGaW5pdGUiLCJ0b09wZW5BSUVuZHBvaW50c0Zyb21CYXNlVXJsIiwiYmFzZVVybCIsInJlcGxhY2UiLCJ0cmFuc2NyaXB0aW9uU2Vzc2lvbkVuZHBvaW50IiwidHJhbnNsYXRpb25FbmRwb2ludCIsInJlc29sdmVPcGVuQUlDb25maWciLCJjb25maWciLCJkZWZhdWx0cyIsInJlYWx0aW1lTW9kZWwiLCJ0cmFuc2xhdGlvbk1vZGVsIiwidmFkRW5hYmxlZCIsImF1dG9TdG9wT25WYWRTaWxlbmNlIiwidmFkVGhyZXNob2xkIiwidmFkUHJlZml4UGFkZGluZ01zIiwidmFkU2lsZW5jZUR1cmF0aW9uTXMiLCJ2YWRJZGxlVGltZW91dE1zIiwicHJld2FybU9uTW91bnQiLCJuZXN0ZWQiLCJvcGVuYWkiLCJlbmRwb2ludEJhc2UiLCJwcm94eUJhc2VVcmwiLCJkZXJpdmVkRW5kcG9pbnRzIiwicmVhbHRpbWVXZWJSdGNVcmwiLCJyZXNvbHZlR3JvcUNvbmZpZyIsImVuYWJsZWQiLCJzdHJlYW0iLCJncm9xIiwicmVzb2x2ZUxvY2FsTW9kZWxDb25maWciLCJlbmFibGVkT25XZWIiLCJtb2RlIiwibW9kZWwiLCJsb2NhbE1vZGVsIiwiZ2V0U3BlZWNoUmVjb2duaXRpb25Db25maWciLCJvdmVycmlkZXMiLCJwcm92aWRlciIsImZhbGxiYWNrVG9XZWJTcGVlY2giLCJtZXJnZWQiLCJjaGVja1dlYlNwZWVjaEF2YWlsYWJpbGl0eSIsIndpbmRvdyIsImlzV2ViU3BlZWNoQXZhaWxhYmxlIiwiZXhwb3J0cyIsIm5vcm1hbGl6ZUxhbmd1YWdlVGFnIiwibGFuZyIsInRvU2hvcnRMYW5ndWFnZUNvZGUiLCJzcGxpdCIsInRvV2ViU3BlZWNoTG9jYWxlIiwic3RhcnRzV2l0aCIsIm5hdGl2ZVNwZWVjaE1vZHVsZUNhY2hlIiwib3BlbkFpTmF0aXZlU3BlZWNoTW9kdWxlQ2FjaGUiLCJnZXROYXRpdmVTcGVlY2hNb2R1bGUiLCJlcnJvciIsImxvZ2dlciIsImRlYnVnIiwiaXNOYXRpdmVSZWNvZ25pemVyQXZhaWxhYmxlIiwibmF0aXZlTW9kdWxlIiwiaXNOYXRpdmVTcGVlY2hBdmFpbGFibGUiLCJnZXRPcGVuQUlOYXRpdmVTcGVlY2hNb2R1bGUiLCJpc09wZW5BSU5hdGl2ZVJlY29nbml6ZXJBdmFpbGFibGUiLCJpc09wZW5BSU5hdGl2ZVNwZWVjaEF2YWlsYWJsZSIsInNlbGVjdFNwZWVjaFJlY29nbml0aW9uTWV0aG9kIiwiY2xpZW50U2VjcmV0IiwiaXNXZWIiLCJQbGF0Zm9ybSIsIk9TIiwiaXNOYXRpdmUiLCJpc1dlYkNsaWVudFJ1bnRpbWUiLCJzaG91bGRXYXJuVW5hdmFpbGFibGUiLCJoYXNHcm9xS2V5IiwiYXBpS2V5IiwiaW5mbyIsIndhcm4iLCJpc09wZW5BSVNwZWVjaEF2YWlsYWJsZSIsImlzR3JvcVNwZWVjaEF2YWlsYWJsZSIsIlVuaWZpZWRTcGVlY2hSZWNvZ25pemVyIiwic2hvdWxkTGlzdGVuIiwic3BlZWNoU3RhdHVzQ2FsbGJhY2siLCJzcGVlY2hSZXN1bHRDYWxsYmFjayIsInNwZWVjaFRyYW5zbGF0aW9uQ2FsbGJhY2siLCJzcGVlY2hSZWFkeUNhbGxiYWNrIiwid2F2ZWZvcm1QcmV2aWV3Q2FsbGJhY2siLCJsYW5ndWFnZSIsIm9uRXJyb3IiLCJyZXF1ZXN0Q29udGV4dFByb3ZpZGVyIiwicmVzb2x2ZWRDb25maWciLCJub3JtYWxpemVkTGFuZ3VhZ2UiLCJhcGlMYW5ndWFnZSIsIndlYlNwZWVjaExhbmd1YWdlIiwibWV0aG9kIiwiZ3JvcUNvbmZpZyIsIm9wZW5haUNvbmZpZyIsImxvY2FsTW9kZWxDb25maWciLCJmaW5hbEdyb3FBcGlLZXkiLCJncm9xQXBpQmFzZVVybCIsImFwaUJhc2VVcmwiLCJncm9xVHJhbnNjcmlwdGlvbkVuZHBvaW50IiwidHJhbnNjcmlwdGlvbkVuZHBvaW50Iiwic3RyZWFtR3JvcSIsImhhbmRsZUVycm9yIiwib3BlbmFpTmF0aXZlTW9kdWxlIiwiT3BlbkFJTmF0aXZlU3BlZWNoUmVjb2duaXplciIsImNyZWF0ZUVsZW1lbnQiLCJvcGVuYWlUcmFuc2NyaXB0aW9uU2Vzc2lvbkVuZHBvaW50Iiwib3BlbmFpVHJhbnNsYXRpb25FbmRwb2ludCIsIm9wZW5haVJlYWx0aW1lV2ViUnRjVXJsIiwib3BlbmFpUmVhbHRpbWVNb2RlbCIsIm9wZW5haVRyYW5zbGF0aW9uTW9kZWwiLCJvcGVuYWlWYWRFbmFibGVkIiwib3BlbmFpQXV0b1N0b3BPblZhZFNpbGVuY2UiLCJvcGVuYWlWYWRUaHJlc2hvbGQiLCJvcGVuYWlWYWRQcmVmaXhQYWRkaW5nTXMiLCJvcGVuYWlWYWRTaWxlbmNlRHVyYXRpb25NcyIsIm9wZW5haVZhZElkbGVUaW1lb3V0TXMiLCJvcGVuYWlQcmV3YXJtT25Nb3VudCIsIk9wZW5BSVNwZWVjaFJlY29nbml6ZXIiLCJOYXRpdmVTcGVlY2hSZWNvZ25pemVyIiwiR3JvcVNwZWVjaFJlY29nbml6ZXIiLCJlZmZlY3RpdmVVcmwiLCJNTFhTcGVlY2hSZWNvZ25pemVyIiwibW9kZWxOYW1lIiwiU3BlZWNoUmVjb2duaXplciIsImdldFNwZWVjaFJlY29nbml0aW9uU3RhdHVzIiwiY2FwYWJpbGl0aWVzIiwiZ2V0R3JvcVNwZWVjaENhcGFiaWxpdGllcyIsImdldE9wZW5BSVNwZWVjaENhcGFiaWxpdGllcyIsIndlYlNwZWVjaCIsImF2YWlsYWJsZSIsInBsYXRmb3JtIiwidXJsIiwicmVjb21tZW5kYXRpb25zIiwiZ2V0UmVjb21tZW5kYXRpb25zIiwiX2RlZmF1bHQiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc3BlZWNoLXJlY29nbml0aW9uL3NwZWVjaC1yZWNvZ25pdGlvbi11bmlmaWVkLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFVuaWZpZWQgU3BlZWNoIFJlY29nbml0aW9uIENvbXBvbmVudFxuICogQXV0b21hdGljYWxseSBzZWxlY3RzIGJlc3Qgc3BlZWNoIHJlY29nbml0aW9uIG1ldGhvZCBiYXNlZCBvbjpcbiAqIDEuIFBsYXRmb3JtIChXZWIgdnMgTmF0aXZlKVxuICogMi4gRW52aXJvbm1lbnQgY29uZmlndXJhdGlvblxuICogMy4gRmVhdHVyZSBhdmFpbGFiaWxpdHlcbiAqL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBQbGF0Zm9ybSB9IGZyb20gXCJyZWFjdC1uYXRpdmVcIjtcbmltcG9ydCB7IFNwZWVjaFJlY29nbml6ZXIgYXMgV2ViU3BlZWNoUmVjb2duaXplciB9IGZyb20gXCIuLi9zcGVlY2gtcmVjb2duaXRpb25cIjtcbmltcG9ydCB7XG4gIEdyb3FTcGVlY2hSZWNvZ25pemVyLFxuICBpc0dyb3FTcGVlY2hBdmFpbGFibGUsXG4gIGdldEdyb3FTcGVlY2hDYXBhYmlsaXRpZXMsXG59IGZyb20gXCIuL3NwZWVjaC1yZWNvZ25pdGlvbi1ncm9xXCI7XG5pbXBvcnQge1xuICBNTFhTcGVlY2hSZWNvZ25pemVyLFxuICB0eXBlIExvY2FsV2hpc3Blck1vZGUsXG59IGZyb20gXCIuL3NwZWVjaC1yZWNvZ25pdGlvbi1tbHhcIjtcbmltcG9ydCB7XG4gIE9wZW5BSVNwZWVjaFJlY29nbml6ZXIsXG4gIGlzT3BlbkFJU3BlZWNoQXZhaWxhYmxlLFxuICBnZXRPcGVuQUlTcGVlY2hDYXBhYmlsaXRpZXMsXG59IGZyb20gXCIuL3NwZWVjaC1yZWNvZ25pdGlvbi1vcGVuYWlcIjtcbmltcG9ydCBsb2dnZXIgZnJvbSBcIi4uL2xvZ2dlclwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFVuaWZpZWRTcGVlY2hSZWNvZ25pemVyUHJvcHMge1xuICBzaG91bGRMaXN0ZW46IGJvb2xlYW47XG4gIHNwZWVjaFN0YXR1c0NhbGxiYWNrOiAoc3RhdHVzOiBib29sZWFuLCB0cmFuc2NyaXB0OiBzdHJpbmcpID0+IHZvaWQ7XG4gIHNwZWVjaFJlc3VsdENhbGxiYWNrOiAocmVzdWx0OiBzdHJpbmcpID0+IHZvaWQ7XG4gIHNwZWVjaFRyYW5zbGF0aW9uQ2FsbGJhY2s/OiAodHJhbnNsYXRpb246IHN0cmluZykgPT4gdm9pZDtcbiAgc3BlZWNoUmVhZHlDYWxsYmFjaz86IChyZWFkeTogYm9vbGVhbikgPT4gdm9pZDtcbiAgd2F2ZWZvcm1QcmV2aWV3Q2FsbGJhY2s/OiAod2F2ZWZvcm06IG51bWJlcltdKSA9PiB2b2lkO1xuICBjbGllbnRTZWNyZXQ/OiBzdHJpbmc7XG4gIGxhbmd1YWdlPzogc3RyaW5nO1xuICBvbkVycm9yPzogKGVycm9yOiBFcnJvcikgPT4gdm9pZDtcbiAgcmVxdWVzdENvbnRleHRQcm92aWRlcj86ICgpID0+XG4gICAgfCB7XG4gICAgICAgIHRocmVhZElkPzogc3RyaW5nIHwgbnVsbDtcbiAgICAgICAgdHVybklkPzogc3RyaW5nIHwgbnVsbDtcbiAgICAgICAgc2Vzc2lvbklkPzogc3RyaW5nIHwgbnVtYmVyIHwgbnVsbDtcbiAgICAgICAgc2VudHJ5VHJhY2U/OiBzdHJpbmcgfCBudWxsO1xuICAgICAgICBiYWdnYWdlPzogc3RyaW5nIHwgbnVsbDtcbiAgICAgIH1cbiAgICB8IG51bGxcbiAgICB8IHVuZGVmaW5lZDtcbiAgLy8gT3B0aW9uYWwgcnVudGltZSBjb25maWcgb3ZlcnJpZGVzXG4gIGNvbmZpZz86IFNwZWVjaFJlY29nbml0aW9uQ29uZmlnO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdyb3FDb25maWdQcm9wcyB7XG4gIGVuYWJsZWQ/OiBib29sZWFuO1xuICBhcGlLZXk/OiBzdHJpbmc7XG4gIGFwaUJhc2VVcmw/OiBzdHJpbmc7XG4gIHRyYW5zY3JpcHRpb25FbmRwb2ludD86IHN0cmluZztcbiAgc3RyZWFtPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlDb25maWdQcm9wcyB7XG4gIHByb3h5QmFzZVVybD86IHN0cmluZztcbiAgdHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludD86IHN0cmluZztcbiAgdHJhbnNsYXRpb25FbmRwb2ludD86IHN0cmluZztcbiAgcmVhbHRpbWVXZWJSdGNVcmw/OiBzdHJpbmc7XG4gIHJlYWx0aW1lTW9kZWw/OiBcImdwdC00by10cmFuc2NyaWJlXCIgfCBcImdwdC00by1taW5pLXRyYW5zY3JpYmVcIjtcbiAgdHJhbnNsYXRpb25Nb2RlbD86IHN0cmluZztcbiAgdmFkRW5hYmxlZD86IGJvb2xlYW47XG4gIGF1dG9TdG9wT25WYWRTaWxlbmNlPzogYm9vbGVhbjtcbiAgdmFkVGhyZXNob2xkPzogbnVtYmVyO1xuICB2YWRQcmVmaXhQYWRkaW5nTXM/OiBudW1iZXI7XG4gIHZhZFNpbGVuY2VEdXJhdGlvbk1zPzogbnVtYmVyO1xuICB2YWRJZGxlVGltZW91dE1zPzogbnVtYmVyO1xuICBwcmV3YXJtT25Nb3VudD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9jYWxNb2RlbENvbmZpZ1Byb3BzIHtcbiAgZW5hYmxlZE9uV2ViPzogYm9vbGVhbjtcbiAgYmFzZVVybD86IHN0cmluZztcbiAgbW9kZT86IExvY2FsV2hpc3Blck1vZGU7XG4gIG1vZGVsPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIHNwZWVjaCByZWNvZ25pdGlvbi5cbiAqIFJlc29sdmVkIGZyb20gaW4tY29kZSBkZWZhdWx0cyArIGV4cGxpY2l0IHJ1bnRpbWUgb3ZlcnJpZGVzIHBhc3NlZCB2aWEgcHJvcHMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3BlZWNoUmVjb2duaXRpb25Db25maWcge1xuICAvLyBTcGVlY2ggcHJvdmlkZXJcbiAgcHJvdmlkZXI/OiBcImdyb3FcIiB8IFwib3BlbmFpXCI7XG4gIC8vIEZhbGxiYWNrIHRvIHdlYiBzcGVlY2ggaWYgR3JvcSBmYWlsc1xuICBmYWxsYmFja1RvV2ViU3BlZWNoPzogYm9vbGVhbjtcbiAgLy8gUHJvdmlkZXItc3BlY2lmaWMgbmVzdGVkIGNvbmZpZ3NcbiAgZ3JvcT86IEdyb3FDb25maWdQcm9wcztcbiAgb3BlbmFpPzogT3BlbkFJQ29uZmlnUHJvcHM7XG4gIGxvY2FsTW9kZWw/OiBMb2NhbE1vZGVsQ29uZmlnUHJvcHM7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVByb3ZpZGVyKFxuICB2YWx1ZT86IHN0cmluZyxcbik6IFwiZ3JvcVwiIHwgXCJvcGVuYWlcIiB8IHVuZGVmaW5lZCB7XG4gIGlmICghdmFsdWUpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSB2YWx1ZS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgaWYgKG5vcm1hbGl6ZWQgPT09IFwiZ3JvcVwiKSByZXR1cm4gXCJncm9xXCI7XG4gIGlmIChub3JtYWxpemVkID09PSBcIm9wZW5haVwiKSByZXR1cm4gXCJvcGVuYWlcIjtcbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuY29uc3QgREVGQVVMVF9SRUFMVElNRV9NT0RFTDogT3BlbkFJQ29uZmlnUHJvcHNbXCJyZWFsdGltZU1vZGVsXCJdID1cbiAgXCJncHQtNG8tdHJhbnNjcmliZVwiO1xuY29uc3QgREVGQVVMVF9UUkFOU0xBVElPTl9NT0RFTCA9IFwiZ3B0LTQuMS1taW5pXCI7XG5jb25zdCBERUZBVUxUX09QRU5BSV9BVVRPX1NUT1BfT05fVkFEX1NJTEVOQ0UgPSBmYWxzZTtcbmNvbnN0IERFRkFVTFRfT1BFTkFJX1ZBRF9TSUxFTkNFX0RVUkFUSU9OX01TID0gMjAwMDtcbmNvbnN0IERFRkFVTFRfT1BFTkFJX1BSRVdBUk1fT05fTU9VTlQgPSB0cnVlO1xuXG5mdW5jdGlvbiBnZXRSdW50aW1lRW52VmFsdWUoa2V5OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICB0cnkge1xuICAgIGNvbnN0IGVudiA9IHR5cGVvZiBwcm9jZXNzICE9PSBcInVuZGVmaW5lZFwiID8gcHJvY2Vzcy5lbnYgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgdmFsdWUgPSBlbnY/LltrZXldO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgY29uc3QgdHJpbW1lZCA9IHZhbHVlLnRyaW0oKTtcbiAgICByZXR1cm4gdHJpbW1lZC5sZW5ndGggPiAwID8gdHJpbW1lZCA6IHVuZGVmaW5lZDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZUJvb2xlYW5FbnYoXG4gIGtleTogc3RyaW5nLFxuICBmYWxsYmFjazogYm9vbGVhblxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IHJhdyA9IGdldFJ1bnRpbWVFbnZWYWx1ZShrZXkpO1xuICBpZiAoIXJhdykgcmV0dXJuIGZhbGxiYWNrO1xuICBjb25zdCBub3JtYWxpemVkID0gcmF3LnRvTG93ZXJDYXNlKCk7XG4gIGlmIChub3JtYWxpemVkID09PSBcInRydWVcIiB8fCBub3JtYWxpemVkID09PSBcIjFcIiB8fCBub3JtYWxpemVkID09PSBcInllc1wiIHx8IG5vcm1hbGl6ZWQgPT09IFwib25cIikge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIGlmIChub3JtYWxpemVkID09PSBcImZhbHNlXCIgfHwgbm9ybWFsaXplZCA9PT0gXCIwXCIgfHwgbm9ybWFsaXplZCA9PT0gXCJub1wiIHx8IG5vcm1hbGl6ZWQgPT09IFwib2ZmXCIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIGZhbGxiYWNrO1xufVxuXG5mdW5jdGlvbiBwYXJzZU51bWJlckVudihcbiAga2V5OiBzdHJpbmcsXG4gIGZhbGxiYWNrOiBudW1iZXJcbik6IG51bWJlciB7XG4gIGNvbnN0IHJhdyA9IGdldFJ1bnRpbWVFbnZWYWx1ZShrZXkpO1xuICBpZiAoIXJhdykgcmV0dXJuIGZhbGxiYWNrO1xuICBjb25zdCBwYXJzZWQgPSBOdW1iZXIocmF3KTtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUocGFyc2VkKSkgcmV0dXJuIGZhbGxiYWNrO1xuICByZXR1cm4gcGFyc2VkO1xufVxuXG5jb25zdCB0b09wZW5BSUVuZHBvaW50c0Zyb21CYXNlVXJsID0gKGJhc2VVcmw/OiBzdHJpbmcpID0+IHtcbiAgY29uc3QgdHJpbW1lZCA9IChiYXNlVXJsIHx8IFwiXCIpLnRyaW0oKS5yZXBsYWNlKC9cXC8rJC8sIFwiXCIpO1xuICBpZiAoIXRyaW1tZWQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludDogdW5kZWZpbmVkLFxuICAgICAgdHJhbnNsYXRpb25FbmRwb2ludDogdW5kZWZpbmVkLFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHtcbiAgICB0cmFuc2NyaXB0aW9uU2Vzc2lvbkVuZHBvaW50OiBgJHt0cmltbWVkfS9vcGVuYWkvdjEvcmVhbHRpbWUvdHJhbnNjcmlwdGlvbl9zZXNzaW9uc2AsXG4gICAgdHJhbnNsYXRpb25FbmRwb2ludDogYCR7dHJpbW1lZH0vb3BlbmFpL3YxL3NwZWVjaC90cmFuc2xhdGUtdG8tZW5nbGlzaGAsXG4gIH07XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlT3BlbkFJQ29uZmlnKFxuICBjb25maWc/OiBQYXJ0aWFsPFNwZWVjaFJlY29nbml0aW9uQ29uZmlnPixcbik6IE9wZW5BSUNvbmZpZ1Byb3BzIHtcbiAgY29uc3QgZGVmYXVsdHM6IE9wZW5BSUNvbmZpZ1Byb3BzID0ge1xuICAgIHJlYWx0aW1lTW9kZWw6IERFRkFVTFRfUkVBTFRJTUVfTU9ERUwsXG4gICAgdHJhbnNsYXRpb25Nb2RlbDogREVGQVVMVF9UUkFOU0xBVElPTl9NT0RFTCxcbiAgICB2YWRFbmFibGVkOiB0cnVlLFxuICAgIGF1dG9TdG9wT25WYWRTaWxlbmNlOiBwYXJzZUJvb2xlYW5FbnYoXG4gICAgICBcIk9QRU5BSV9BVVRPX1NUT1BfT05fVkFEX1NJTEVOQ0VcIixcbiAgICAgIERFRkFVTFRfT1BFTkFJX0FVVE9fU1RPUF9PTl9WQURfU0lMRU5DRVxuICAgICksXG4gICAgdmFkVGhyZXNob2xkOiAwLjcsXG4gICAgdmFkUHJlZml4UGFkZGluZ01zOiA0MDAsXG4gICAgdmFkU2lsZW5jZUR1cmF0aW9uTXM6IHBhcnNlTnVtYmVyRW52KFxuICAgICAgXCJPUEVOQUlfVkFEX1NJTEVOQ0VfRFVSQVRJT05fTVNcIixcbiAgICAgIERFRkFVTFRfT1BFTkFJX1ZBRF9TSUxFTkNFX0RVUkFUSU9OX01TXG4gICAgKSxcbiAgICB2YWRJZGxlVGltZW91dE1zOiA2MDAwLFxuICAgIHByZXdhcm1Pbk1vdW50OiBwYXJzZUJvb2xlYW5FbnYoXG4gICAgICBcIk9QRU5BSV9QUkVXQVJNX09OX01PVU5UXCIsXG4gICAgICBERUZBVUxUX09QRU5BSV9QUkVXQVJNX09OX01PVU5UXG4gICAgKSxcbiAgfTtcblxuICBjb25zdCBuZXN0ZWQgPSBjb25maWc/Lm9wZW5haSB8fCB7fTtcbiAgY29uc3QgZW5kcG9pbnRCYXNlID0gbmVzdGVkLnByb3h5QmFzZVVybDtcbiAgY29uc3QgZGVyaXZlZEVuZHBvaW50cyA9IHRvT3BlbkFJRW5kcG9pbnRzRnJvbUJhc2VVcmwoZW5kcG9pbnRCYXNlKTtcblxuICByZXR1cm4ge1xuICAgIC4uLmRlZmF1bHRzLFxuICAgIC4uLm5lc3RlZCxcbiAgICB0cmFuc2NyaXB0aW9uU2Vzc2lvbkVuZHBvaW50OlxuICAgICAgbmVzdGVkLnRyYW5zY3JpcHRpb25TZXNzaW9uRW5kcG9pbnQgfHxcbiAgICAgIGRlcml2ZWRFbmRwb2ludHMudHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludCxcbiAgICB0cmFuc2xhdGlvbkVuZHBvaW50OlxuICAgICAgbmVzdGVkLnRyYW5zbGF0aW9uRW5kcG9pbnQgfHwgZGVyaXZlZEVuZHBvaW50cy50cmFuc2xhdGlvbkVuZHBvaW50LFxuICAgIHJlYWx0aW1lV2ViUnRjVXJsOiBuZXN0ZWQucmVhbHRpbWVXZWJSdGNVcmwsXG4gICAgcmVhbHRpbWVNb2RlbDogbmVzdGVkLnJlYWx0aW1lTW9kZWwgfHwgZGVmYXVsdHMucmVhbHRpbWVNb2RlbCxcbiAgICB0cmFuc2xhdGlvbk1vZGVsOiBuZXN0ZWQudHJhbnNsYXRpb25Nb2RlbCB8fCBkZWZhdWx0cy50cmFuc2xhdGlvbk1vZGVsLFxuICAgIHZhZEVuYWJsZWQ6IG5lc3RlZC52YWRFbmFibGVkID8/IGRlZmF1bHRzLnZhZEVuYWJsZWQsXG4gICAgYXV0b1N0b3BPblZhZFNpbGVuY2U6XG4gICAgICBuZXN0ZWQuYXV0b1N0b3BPblZhZFNpbGVuY2UgPz8gZGVmYXVsdHMuYXV0b1N0b3BPblZhZFNpbGVuY2UsXG4gICAgdmFkVGhyZXNob2xkOiBuZXN0ZWQudmFkVGhyZXNob2xkID8/IGRlZmF1bHRzLnZhZFRocmVzaG9sZCxcbiAgICB2YWRQcmVmaXhQYWRkaW5nTXM6XG4gICAgICBuZXN0ZWQudmFkUHJlZml4UGFkZGluZ01zID8/IGRlZmF1bHRzLnZhZFByZWZpeFBhZGRpbmdNcyxcbiAgICB2YWRTaWxlbmNlRHVyYXRpb25NczpcbiAgICAgIG5lc3RlZC52YWRTaWxlbmNlRHVyYXRpb25NcyA/PyBkZWZhdWx0cy52YWRTaWxlbmNlRHVyYXRpb25NcyxcbiAgICB2YWRJZGxlVGltZW91dE1zOlxuICAgICAgbmVzdGVkLnZhZElkbGVUaW1lb3V0TXMgPz8gZGVmYXVsdHMudmFkSWRsZVRpbWVvdXRNcyxcbiAgICBwcmV3YXJtT25Nb3VudDpcbiAgICAgIG5lc3RlZC5wcmV3YXJtT25Nb3VudCA/PyBkZWZhdWx0cy5wcmV3YXJtT25Nb3VudCxcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUdyb3FDb25maWcoXG4gIGNvbmZpZz86IFBhcnRpYWw8U3BlZWNoUmVjb2duaXRpb25Db25maWc+LFxuKTogR3JvcUNvbmZpZ1Byb3BzIHtcbiAgY29uc3QgZGVmYXVsdHM6IEdyb3FDb25maWdQcm9wcyA9IHtcbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIHN0cmVhbTogdHJ1ZSxcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIC4uLmRlZmF1bHRzLFxuICAgIC4uLihjb25maWc/Lmdyb3EgfHwge30pLFxuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTG9jYWxNb2RlbENvbmZpZyhcbiAgY29uZmlnPzogUGFydGlhbDxTcGVlY2hSZWNvZ25pdGlvbkNvbmZpZz4sXG4pOiBMb2NhbE1vZGVsQ29uZmlnUHJvcHMge1xuICBjb25zdCBkZWZhdWx0czogTG9jYWxNb2RlbENvbmZpZ1Byb3BzID0ge1xuICAgIGVuYWJsZWRPbldlYjogZmFsc2UsXG4gICAgYmFzZVVybDogXCJodHRwOi8vMTI3LjAuMC4xOjgwMDBcIixcbiAgICBtb2RlOiBcIm9uZXNob3RcIixcbiAgICBtb2RlbDogXCJsYXJnZS12My10dXJib1wiLFxuICB9O1xuXG4gIHJldHVybiB7XG4gICAgLi4uZGVmYXVsdHMsXG4gICAgLi4uKGNvbmZpZz8ubG9jYWxNb2RlbCB8fCB7fSksXG4gIH07XG59XG5cbi8qKlxuICogTG9hZCBzcGVlY2ggcmVjb2duaXRpb24gY29uZmlnIGZyb20gZGVmYXVsdHMgKyBleHBsaWNpdCBvdmVycmlkZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTcGVlY2hSZWNvZ25pdGlvbkNvbmZpZyhcbiAgb3ZlcnJpZGVzPzogUGFydGlhbDxTcGVlY2hSZWNvZ25pdGlvbkNvbmZpZz4sXG4pOiBTcGVlY2hSZWNvZ25pdGlvbkNvbmZpZyB7XG4gIGNvbnN0IGRlZmF1bHRzOiBTcGVlY2hSZWNvZ25pdGlvbkNvbmZpZyA9IHtcbiAgICBwcm92aWRlcjogXCJncm9xXCIsXG4gICAgZmFsbGJhY2tUb1dlYlNwZWVjaDogdHJ1ZSxcbiAgICBncm9xOiByZXNvbHZlR3JvcUNvbmZpZygpLFxuICAgIG9wZW5haTogcmVzb2x2ZU9wZW5BSUNvbmZpZygpLFxuICAgIGxvY2FsTW9kZWw6IHJlc29sdmVMb2NhbE1vZGVsQ29uZmlnKCksXG4gIH07XG5cbiAgY29uc3QgbWVyZ2VkOiBTcGVlY2hSZWNvZ25pdGlvbkNvbmZpZyA9IHtcbiAgICAuLi5kZWZhdWx0cyxcbiAgICAuLi4ob3ZlcnJpZGVzIHx8IHt9KSxcbiAgICBwcm92aWRlcjpcbiAgICAgIG5vcm1hbGl6ZVByb3ZpZGVyKG92ZXJyaWRlcz8ucHJvdmlkZXIpIHx8XG4gICAgICBub3JtYWxpemVQcm92aWRlcihkZWZhdWx0cy5wcm92aWRlcikgfHxcbiAgICAgIFwiZ3JvcVwiLFxuICB9O1xuXG4gIHJldHVybiB7XG4gICAgLi4ubWVyZ2VkLFxuICAgIGdyb3E6IHJlc29sdmVHcm9xQ29uZmlnKG1lcmdlZCksXG4gICAgb3BlbmFpOiByZXNvbHZlT3BlbkFJQ29uZmlnKG1lcmdlZCksXG4gICAgbG9jYWxNb2RlbDogcmVzb2x2ZUxvY2FsTW9kZWxDb25maWcobWVyZ2VkKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBXZWIgU3BlZWNoIEFQSSBpcyBhdmFpbGFibGVcbiAqL1xuZnVuY3Rpb24gY2hlY2tXZWJTcGVlY2hBdmFpbGFiaWxpdHkoKTogYm9vbGVhbiB7XG4gIGlmICh0eXBlb2Ygd2luZG93ID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIFwid2Via2l0U3BlZWNoUmVjb2duaXRpb25cIiBpbiB3aW5kb3cgfHwgXCJTcGVlY2hSZWNvZ25pdGlvblwiIGluIHdpbmRvdztcbn1cblxuZXhwb3J0IGNvbnN0IGlzV2ViU3BlZWNoQXZhaWxhYmxlID0gY2hlY2tXZWJTcGVlY2hBdmFpbGFiaWxpdHk7XG5cbmNvbnN0IG5vcm1hbGl6ZUxhbmd1YWdlVGFnID0gKGxhbmc/OiBzdHJpbmcpID0+IHtcbiAgY29uc3Qgbm9ybWFsaXplZCA9IChsYW5nIHx8IFwiZW5cIikudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gIHJldHVybiBub3JtYWxpemVkLmxlbmd0aCA+IDAgPyBub3JtYWxpemVkIDogXCJlblwiO1xufTtcblxuY29uc3QgdG9TaG9ydExhbmd1YWdlQ29kZSA9IChsYW5nOiBzdHJpbmcpID0+IGxhbmcuc3BsaXQoXCItXCIpWzBdO1xuXG5jb25zdCB0b1dlYlNwZWVjaExvY2FsZSA9IChsYW5nOiBzdHJpbmcpID0+IHtcbiAgaWYgKGxhbmcuc3RhcnRzV2l0aChcImVuXCIpKSByZXR1cm4gXCJlbi1VU1wiO1xuICBpZiAobGFuZy5zdGFydHNXaXRoKFwiZGVcIikpIHJldHVybiBcImRlLURFXCI7XG4gIHJldHVybiBsYW5nO1xufTtcblxuLyoqXG4gKiBUeXBlcyBvZiBzcGVlY2ggcmVjb2duaXRpb24gbWV0aG9kc1xuICovXG50eXBlIFNwZWVjaFJlY29nbml0aW9uTW9kZSA9XG4gIHwgXCJvcGVuYWktd2ViXCJcbiAgfCBcIm9wZW5haS1uYXRpdmVcIlxuICB8IFwiZ3JvcS13ZWJcIlxuICB8IFwiZ3JvcS1uYXRpdmVcIlxuICB8IFwid2Vic3BlZWNoXCJcbiAgfCBcIm1seC1sb2NhbFwiXG4gIHwgXCJub25lXCI7XG5cbnR5cGUgTmF0aXZlU3BlZWNoTW9kdWxlID0gdHlwZW9mIGltcG9ydChcIi4vc3BlZWNoLXJlY29nbml0aW9uLW5hdGl2ZVwiKTtcbmxldCBuYXRpdmVTcGVlY2hNb2R1bGVDYWNoZTogTmF0aXZlU3BlZWNoTW9kdWxlIHwgbnVsbCB8IHVuZGVmaW5lZDtcbnR5cGUgT3BlbkFJTmF0aXZlU3BlZWNoTW9kdWxlID0gdHlwZW9mIGltcG9ydChcIi4vc3BlZWNoLXJlY29nbml0aW9uLW9wZW5haS1uYXRpdmVcIik7XG5sZXQgb3BlbkFpTmF0aXZlU3BlZWNoTW9kdWxlQ2FjaGU6IE9wZW5BSU5hdGl2ZVNwZWVjaE1vZHVsZSB8IG51bGwgfCB1bmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGdldE5hdGl2ZVNwZWVjaE1vZHVsZSgpOiBOYXRpdmVTcGVlY2hNb2R1bGUgfCBudWxsIHtcbiAgaWYgKG5hdGl2ZVNwZWVjaE1vZHVsZUNhY2hlICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gbmF0aXZlU3BlZWNoTW9kdWxlQ2FjaGU7XG4gIH1cblxuICB0cnkge1xuICAgIC8vIEtlZXAgbmF0aXZlIG1vZHVsZSBsYXp5IHRvIGF2b2lkIGxvYWRpbmcgbmF0aXZlLW9ubHkgZGVwZW5kZW5jaWVzIG9uIHdlYi5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlc1xuICAgIG5hdGl2ZVNwZWVjaE1vZHVsZUNhY2hlID0gcmVxdWlyZShcIi4vc3BlZWNoLXJlY29nbml0aW9uLW5hdGl2ZVwiKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBuYXRpdmVTcGVlY2hNb2R1bGVDYWNoZSA9IG51bGw7XG4gICAgbG9nZ2VyLmRlYnVnKFwiTmF0aXZlIHNwZWVjaCBtb2R1bGUgdW5hdmFpbGFibGU6XCIsIGVycm9yKTtcbiAgfVxuXG4gIHJldHVybiBuYXRpdmVTcGVlY2hNb2R1bGVDYWNoZTtcbn1cblxuZnVuY3Rpb24gaXNOYXRpdmVSZWNvZ25pemVyQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICBjb25zdCBuYXRpdmVNb2R1bGUgPSBnZXROYXRpdmVTcGVlY2hNb2R1bGUoKTtcbiAgcmV0dXJuICEhbmF0aXZlTW9kdWxlPy5pc05hdGl2ZVNwZWVjaEF2YWlsYWJsZT8uKCk7XG59XG5cbmZ1bmN0aW9uIGdldE9wZW5BSU5hdGl2ZVNwZWVjaE1vZHVsZSgpOiBPcGVuQUlOYXRpdmVTcGVlY2hNb2R1bGUgfCBudWxsIHtcbiAgaWYgKG9wZW5BaU5hdGl2ZVNwZWVjaE1vZHVsZUNhY2hlICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gb3BlbkFpTmF0aXZlU3BlZWNoTW9kdWxlQ2FjaGU7XG4gIH1cblxuICB0cnkge1xuICAgIC8vIEtlZXAgbmF0aXZlIG1vZHVsZSBsYXp5IHRvIGF2b2lkIGxvYWRpbmcgbmF0aXZlLW9ubHkgZGVwZW5kZW5jaWVzIG9uIHdlYi5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlc1xuICAgIG9wZW5BaU5hdGl2ZVNwZWVjaE1vZHVsZUNhY2hlID0gcmVxdWlyZShcIi4vc3BlZWNoLXJlY29nbml0aW9uLW9wZW5haS1uYXRpdmVcIik7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgb3BlbkFpTmF0aXZlU3BlZWNoTW9kdWxlQ2FjaGUgPSBudWxsO1xuICAgIGxvZ2dlci5kZWJ1ZyhcIk9wZW5BSSBuYXRpdmUgc3BlZWNoIG1vZHVsZSB1bmF2YWlsYWJsZTpcIiwgZXJyb3IpO1xuICB9XG5cbiAgcmV0dXJuIG9wZW5BaU5hdGl2ZVNwZWVjaE1vZHVsZUNhY2hlO1xufVxuXG5mdW5jdGlvbiBpc09wZW5BSU5hdGl2ZVJlY29nbml6ZXJBdmFpbGFibGUoKTogYm9vbGVhbiB7XG4gIGNvbnN0IG5hdGl2ZU1vZHVsZSA9IGdldE9wZW5BSU5hdGl2ZVNwZWVjaE1vZHVsZSgpO1xuICByZXR1cm4gISFuYXRpdmVNb2R1bGU/LmlzT3BlbkFJTmF0aXZlU3BlZWNoQXZhaWxhYmxlPy4oKTtcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hpY2ggc3BlZWNoIHJlY29nbml0aW9uIG1ldGhvZCB0byB1c2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlbGVjdFNwZWVjaFJlY29nbml0aW9uTWV0aG9kKFxuICBjb25maWc6IFNwZWVjaFJlY29nbml0aW9uQ29uZmlnLFxuICBjbGllbnRTZWNyZXQ/OiBzdHJpbmcsXG4pOiBTcGVlY2hSZWNvZ25pdGlvbk1vZGUge1xuICBjb25zdCBpc1dlYiA9IFBsYXRmb3JtLk9TID09PSBcIndlYlwiO1xuICBjb25zdCBpc05hdGl2ZSA9IFBsYXRmb3JtLk9TID09PSBcImlvc1wiIHx8IFBsYXRmb3JtLk9TID09PSBcImFuZHJvaWRcIjtcbiAgY29uc3QgaXNXZWJDbGllbnRSdW50aW1lID0gaXNXZWIgJiYgdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIjtcbiAgY29uc3Qgc2hvdWxkV2FyblVuYXZhaWxhYmxlID0gaXNXZWJDbGllbnRSdW50aW1lO1xuICBjb25zdCBwcm92aWRlciA9IG5vcm1hbGl6ZVByb3ZpZGVyKGNvbmZpZy5wcm92aWRlcikgfHwgXCJncm9xXCI7XG4gIGNvbnN0IGdyb3EgPSByZXNvbHZlR3JvcUNvbmZpZyhjb25maWcpO1xuICBjb25zdCBvcGVuYWkgPSByZXNvbHZlT3BlbkFJQ29uZmlnKGNvbmZpZyk7XG4gIGNvbnN0IGxvY2FsTW9kZWwgPSByZXNvbHZlTG9jYWxNb2RlbENvbmZpZyhjb25maWcpO1xuXG4gIGNvbnN0IGhhc0dyb3FLZXkgPSAhIShjbGllbnRTZWNyZXQgfHwgZ3JvcS5hcGlLZXkpO1xuXG4gIGlmIChwcm92aWRlciA9PT0gXCJvcGVuYWlcIikge1xuICAgIGlmIChpc05hdGl2ZSkge1xuICAgICAgaWYgKFxuICAgICAgICBvcGVuYWkudHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludCAmJlxuICAgICAgICBpc09wZW5BSU5hdGl2ZVJlY29nbml6ZXJBdmFpbGFibGUoKVxuICAgICAgKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKFwi4pyFIFVzaW5nIE9wZW5BSSBOYXRpdmUgUmVhbHRpbWUgKFdlYlJUQylcIik7XG4gICAgICAgIHJldHVybiBcIm9wZW5haS1uYXRpdmVcIjtcbiAgICAgIH1cbiAgICAgIGlmIChzaG91bGRXYXJuVW5hdmFpbGFibGUpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgXCLimqDvuI8gT3BlbkFJIG5hdGl2ZSBzcGVlY2ggdW5hdmFpbGFibGUuIENvbmZpZ3VyZSBPUEVOQUlfVFJBTlNDUklQVElPTl9TRVNTSU9OX0VORFBPSU5UIGFuZCBpbnN0YWxsIHJlYWN0LW5hdGl2ZS13ZWJydGMuXCIsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gXCJub25lXCI7XG4gICAgfVxuXG4gICAgaWYgKGlzV2ViKSB7XG4gICAgICBpZiAob3BlbmFpLnRyYW5zY3JpcHRpb25TZXNzaW9uRW5kcG9pbnQgJiYgaXNPcGVuQUlTcGVlY2hBdmFpbGFibGUoKSkge1xuICAgICAgICBsb2dnZXIuaW5mbyhcIuKchSBVc2luZyBPcGVuQUkgV2ViIFJlYWx0aW1lIChXZWJSVEMpXCIpO1xuICAgICAgICByZXR1cm4gXCJvcGVuYWktd2ViXCI7XG4gICAgICB9XG4gICAgICBpZiAoc2hvdWxkV2FyblVuYXZhaWxhYmxlKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKFwi4pqg77iPIE9wZW5BSSB3ZWIgc3BlZWNoIHVuYXZhaWxhYmxlXCIpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFwibm9uZVwiO1xuICAgIH1cbiAgfVxuXG4gIC8vIE5hdGl2ZSBwbGF0Zm9ybXM6IFVzZSBuYXRpdmUgR3JvcSBpbXBsZW1lbnRhdGlvblxuICBpZiAoaXNOYXRpdmUpIHtcbiAgICBpZiAoZ3JvcS5lbmFibGVkICYmIGhhc0dyb3FLZXkgJiYgaXNOYXRpdmVSZWNvZ25pemVyQXZhaWxhYmxlKCkpIHtcbiAgICAgIGxvZ2dlci5pbmZvKFwi4pyFIFVzaW5nIEdyb3EgTmF0aXZlIChleHBvLWF1ZGlvKVwiKTtcbiAgICAgIHJldHVybiBcImdyb3EtbmF0aXZlXCI7XG4gICAgfVxuICAgIGlmIChzaG91bGRXYXJuVW5hdmFpbGFibGUpIHtcbiAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICBcIuKaoO+4jyBObyBzcGVlY2ggcmVjb2duaXRpb24gYXZhaWxhYmxlIG9uIG5hdGl2ZSAoaW5zdGFsbCBleHBvLWF1ZGlvICsgZXhwby1maWxlLXN5c3RlbSBhbmQgcnVuIGEgZGV2IGNsaWVudCBidWlsZClcIixcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBcIm5vbmVcIjtcbiAgfVxuXG4gIC8vIFdlYiBwbGF0Zm9ybTogQ2FuIHVzZSBib3RoLCBwcmVmZXIgYmFzZWQgb24gY29uZmlnXG4gIGlmIChpc1dlYikge1xuICAgIGlmIChsb2NhbE1vZGVsLmVuYWJsZWRPbldlYiAmJiBsb2NhbE1vZGVsLmJhc2VVcmwpIHtcbiAgICAgIGxvZ2dlci5pbmZvKFwi4pyFIFVzaW5nIExvY2FsIE1MWCBXaGlzcGVyIHNlcnZlclwiKTtcbiAgICAgIHJldHVybiBcIm1seC1sb2NhbFwiO1xuICAgIH1cblxuICAgIC8vIFVzZSBHcm9xIGlmIGVuYWJsZWQgYW5kIGF2YWlsYWJsZVxuICAgIGlmIChncm9xLmVuYWJsZWQgJiYgaGFzR3JvcUtleSAmJiBpc0dyb3FTcGVlY2hBdmFpbGFibGUoKSkge1xuICAgICAgbG9nZ2VyLmluZm8oXCLinIUgVXNpbmcgR3JvcSBXZWIgKEVuYWJsZWQgYW5kIGF2YWlsYWJsZSlcIik7XG4gICAgICByZXR1cm4gXCJncm9xLXdlYlwiO1xuICAgIH1cblxuICAgIC8vIEZhbGxiYWNrIHRvIFdlYiBTcGVlY2ggQVBJXG4gICAgaWYgKGNvbmZpZy5mYWxsYmFja1RvV2ViU3BlZWNoICYmIGlzV2ViU3BlZWNoQXZhaWxhYmxlKCkpIHtcbiAgICAgIGxvZ2dlci5pbmZvKFwi4pyFIFVzaW5nIFdlYiBTcGVlY2ggQVBJIChGYWxsYmFjaylcIik7XG4gICAgICByZXR1cm4gXCJ3ZWJzcGVlY2hcIjtcbiAgICB9XG4gIH1cbiAgaWYgKHNob3VsZFdhcm5VbmF2YWlsYWJsZSkge1xuICAgIGxvZ2dlci53YXJuKFwi4pqg77iPIE5vIHNwZWVjaCByZWNvZ25pdGlvbiBtZXRob2QgYXZhaWxhYmxlXCIpO1xuICB9XG4gIHJldHVybiBcIm5vbmVcIjtcbn1cblxuLyoqXG4gKiBVbmlmaWVkIFNwZWVjaCBSZWNvZ25pemVyIENvbXBvbmVudFxuICogQXV0b21hdGljYWxseSBzZWxlY3RzIGFuZCB1c2VzIHRoZSBiZXN0IHNwZWVjaCByZWNvZ25pdGlvbiBtZXRob2RcbiAqL1xuZXhwb3J0IGNvbnN0IFVuaWZpZWRTcGVlY2hSZWNvZ25pemVyOiBSZWFjdC5GQzxcbiAgVW5pZmllZFNwZWVjaFJlY29nbml6ZXJQcm9wc1xuPiA9ICh7XG4gIHNob3VsZExpc3RlbixcbiAgc3BlZWNoU3RhdHVzQ2FsbGJhY2ssXG4gIHNwZWVjaFJlc3VsdENhbGxiYWNrLFxuICBzcGVlY2hUcmFuc2xhdGlvbkNhbGxiYWNrLFxuICBzcGVlY2hSZWFkeUNhbGxiYWNrLFxuICB3YXZlZm9ybVByZXZpZXdDYWxsYmFjayxcbiAgY2xpZW50U2VjcmV0LFxuICBsYW5ndWFnZSA9IFwiZW5cIixcbiAgb25FcnJvcixcbiAgcmVxdWVzdENvbnRleHRQcm92aWRlcixcbiAgY29uZmlnLFxufTogVW5pZmllZFNwZWVjaFJlY29nbml6ZXJQcm9wcykgPT4ge1xuICAvLyBHZXQgY29uZmlndXJhdGlvblxuICBjb25zdCByZXNvbHZlZENvbmZpZyA9IGdldFNwZWVjaFJlY29nbml0aW9uQ29uZmlnKGNvbmZpZyk7XG4gIGNvbnN0IGlzV2ViQ2xpZW50UnVudGltZSA9XG4gICAgUGxhdGZvcm0uT1MgPT09IFwid2ViXCIgJiYgdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIjtcbiAgY29uc3Qgbm9ybWFsaXplZExhbmd1YWdlID0gbm9ybWFsaXplTGFuZ3VhZ2VUYWcobGFuZ3VhZ2UpO1xuICBjb25zdCBhcGlMYW5ndWFnZSA9IHRvU2hvcnRMYW5ndWFnZUNvZGUobm9ybWFsaXplZExhbmd1YWdlKTtcbiAgY29uc3Qgd2ViU3BlZWNoTGFuZ3VhZ2UgPSB0b1dlYlNwZWVjaExvY2FsZShub3JtYWxpemVkTGFuZ3VhZ2UpO1xuXG4gIC8vIERldGVybWluZSB3aGljaCBtZXRob2QgdG8gdXNlXG4gIGNvbnN0IG1ldGhvZCA9IHNlbGVjdFNwZWVjaFJlY29nbml0aW9uTWV0aG9kKHJlc29sdmVkQ29uZmlnLCBjbGllbnRTZWNyZXQpO1xuICBpZiAoaXNXZWJDbGllbnRSdW50aW1lKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwiU2VsZWN0ZWQgc3BlZWNoIHJlY29nbml0aW9uIG1ldGhvZDpcIiwgbWV0aG9kKTtcbiAgfVxuICBjb25zdCBncm9xQ29uZmlnID0gcmVzb2x2ZUdyb3FDb25maWcocmVzb2x2ZWRDb25maWcpO1xuICBjb25zdCBvcGVuYWlDb25maWcgPSByZXNvbHZlT3BlbkFJQ29uZmlnKHJlc29sdmVkQ29uZmlnKTtcbiAgY29uc3QgbG9jYWxNb2RlbENvbmZpZyA9IHJlc29sdmVMb2NhbE1vZGVsQ29uZmlnKHJlc29sdmVkQ29uZmlnKTtcblxuICBjb25zdCBmaW5hbEdyb3FBcGlLZXkgPSBjbGllbnRTZWNyZXQgfHwgZ3JvcUNvbmZpZy5hcGlLZXkgfHwgXCJcIjtcbiAgY29uc3QgZ3JvcUFwaUJhc2VVcmwgPSBncm9xQ29uZmlnLmFwaUJhc2VVcmw7XG4gIGNvbnN0IGdyb3FUcmFuc2NyaXB0aW9uRW5kcG9pbnQgPSBncm9xQ29uZmlnLnRyYW5zY3JpcHRpb25FbmRwb2ludDtcbiAgY29uc3Qgc3RyZWFtR3JvcSA9IGdyb3FDb25maWcuc3RyZWFtO1xuXG4gIGlmIChncm9xQ29uZmlnLmVuYWJsZWQgJiYgIWZpbmFsR3JvcUFwaUtleSkge1xuICAgIGxvZ2dlci53YXJuKFxuICAgICAgXCJHcm9xIHNwZWVjaCBpcyBlbmFibGVkIGJ1dCBubyBBUEkga2V5IHdhcyBwcm92aWRlZC4gUGFzcyBhIG5vbi1zZWNyZXQgY2xpZW50IGtleSBvciBkaXNhYmxlIEdyb3Egc3BlZWNoLlwiLFxuICAgICk7XG4gIH1cblxuICAvLyBFcnJvciBoYW5kbGVyIHdpdGggZmFsbGJhY2tcbiAgY29uc3QgaGFuZGxlRXJyb3IgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgbG9nZ2VyLmVycm9yKFwiU3BlZWNoIHJlY29nbml0aW9uIGVycm9yOlwiLCBlcnJvcik7XG5cbiAgICBpZiAob25FcnJvcikge1xuICAgICAgb25FcnJvcihlcnJvcik7XG4gICAgfVxuXG4gICAgLy8gSWYgR3JvcSBmYWlscyBhbmQgZmFsbGJhY2sgaXMgZW5hYmxlZCwgd2UgY291bGQgc3dpdGNoIHRvIFdlYiBTcGVlY2hcbiAgICAvLyAoVGhpcyB3b3VsZCByZXF1aXJlIG1vcmUgY29tcGxleCBzdGF0ZSBtYW5hZ2VtZW50KVxuICB9O1xuXG4gIC8vIFJlbmRlciBhcHByb3ByaWF0ZSBjb21wb25lbnQgYmFzZWQgb24gbWV0aG9kXG4gIHN3aXRjaCAobWV0aG9kKSB7XG4gICAgY2FzZSBcIm9wZW5haS1uYXRpdmVcIjoge1xuICAgICAgaWYgKCFvcGVuYWlDb25maWcudHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludCkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgICAgXCJPcGVuQUkgdHJhbnNjcmlwdGlvbiBzZXNzaW9uIGVuZHBvaW50IGlzIHJlcXVpcmVkIGJ1dCBub3QgcHJvdmlkZWRcIixcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG9wZW5haU5hdGl2ZU1vZHVsZSA9IGdldE9wZW5BSU5hdGl2ZVNwZWVjaE1vZHVsZSgpO1xuICAgICAgaWYgKCFvcGVuYWlOYXRpdmVNb2R1bGU/Lk9wZW5BSU5hdGl2ZVNwZWVjaFJlY29nbml6ZXIpIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgIFwiT3BlbkFJIG5hdGl2ZSBzcGVlY2ggbW9kdWxlIHVuYXZhaWxhYmxlLiBJbnN0YWxsIHJlYWN0LW5hdGl2ZS13ZWJydGMgYW5kIHVzZSBhIG5hdGl2ZS9kZXYgYnVpbGQuXCIsXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBPcGVuQUlOYXRpdmVTcGVlY2hSZWNvZ25pemVyID1cbiAgICAgICAgb3BlbmFpTmF0aXZlTW9kdWxlLk9wZW5BSU5hdGl2ZVNwZWVjaFJlY29nbml6ZXI7XG5cbiAgICAgIHJldHVybiAoXG4gICAgICAgIDxPcGVuQUlOYXRpdmVTcGVlY2hSZWNvZ25pemVyXG4gICAgICAgICAgc2hvdWxkTGlzdGVuPXtzaG91bGRMaXN0ZW59XG4gICAgICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2s9e3NwZWVjaFN0YXR1c0NhbGxiYWNrfVxuICAgICAgICAgIHNwZWVjaFJlc3VsdENhbGxiYWNrPXtzcGVlY2hSZXN1bHRDYWxsYmFja31cbiAgICAgICAgICBzcGVlY2hUcmFuc2xhdGlvbkNhbGxiYWNrPXtzcGVlY2hUcmFuc2xhdGlvbkNhbGxiYWNrfVxuICAgICAgICAgIHNwZWVjaFJlYWR5Q2FsbGJhY2s9e3NwZWVjaFJlYWR5Q2FsbGJhY2t9XG4gICAgICAgICAgY2xpZW50U2VjcmV0PXtmaW5hbEdyb3FBcGlLZXl9XG4gICAgICAgICAgb3BlbmFpVHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludD17XG4gICAgICAgICAgICBvcGVuYWlDb25maWcudHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludFxuICAgICAgICAgIH1cbiAgICAgICAgICBvcGVuYWlUcmFuc2xhdGlvbkVuZHBvaW50PXtvcGVuYWlDb25maWcudHJhbnNsYXRpb25FbmRwb2ludH1cbiAgICAgICAgICBvcGVuYWlSZWFsdGltZVdlYlJ0Y1VybD17b3BlbmFpQ29uZmlnLnJlYWx0aW1lV2ViUnRjVXJsfVxuICAgICAgICAgIG9wZW5haVJlYWx0aW1lTW9kZWw9e29wZW5haUNvbmZpZy5yZWFsdGltZU1vZGVsfVxuICAgICAgICAgIG9wZW5haVRyYW5zbGF0aW9uTW9kZWw9e29wZW5haUNvbmZpZy50cmFuc2xhdGlvbk1vZGVsfVxuICAgICAgICAgIG9wZW5haVZhZEVuYWJsZWQ9e29wZW5haUNvbmZpZy52YWRFbmFibGVkfVxuICAgICAgICAgIG9wZW5haUF1dG9TdG9wT25WYWRTaWxlbmNlPXtcbiAgICAgICAgICAgIG9wZW5haUNvbmZpZy5hdXRvU3RvcE9uVmFkU2lsZW5jZVxuICAgICAgICAgIH1cbiAgICAgICAgICBvcGVuYWlWYWRUaHJlc2hvbGQ9e29wZW5haUNvbmZpZy52YWRUaHJlc2hvbGR9XG4gICAgICAgICAgb3BlbmFpVmFkUHJlZml4UGFkZGluZ01zPXtvcGVuYWlDb25maWcudmFkUHJlZml4UGFkZGluZ01zfVxuICAgICAgICAgIG9wZW5haVZhZFNpbGVuY2VEdXJhdGlvbk1zPXtcbiAgICAgICAgICAgIG9wZW5haUNvbmZpZy52YWRTaWxlbmNlRHVyYXRpb25Nc1xuICAgICAgICAgIH1cbiAgICAgICAgICBvcGVuYWlWYWRJZGxlVGltZW91dE1zPXtvcGVuYWlDb25maWcudmFkSWRsZVRpbWVvdXRNc31cbiAgICAgICAgICBvcGVuYWlQcmV3YXJtT25Nb3VudD17b3BlbmFpQ29uZmlnLnByZXdhcm1Pbk1vdW50fVxuICAgICAgICAgIGxhbmd1YWdlPXthcGlMYW5ndWFnZX1cbiAgICAgICAgICByZXF1ZXN0Q29udGV4dFByb3ZpZGVyPXtyZXF1ZXN0Q29udGV4dFByb3ZpZGVyfVxuICAgICAgICAgIG9uRXJyb3I9e2hhbmRsZUVycm9yfVxuICAgICAgICAvPlxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjYXNlIFwib3BlbmFpLXdlYlwiOlxuICAgICAgaWYgKCFvcGVuYWlDb25maWcudHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludCkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgICAgXCJPcGVuQUkgdHJhbnNjcmlwdGlvbiBzZXNzaW9uIGVuZHBvaW50IGlzIHJlcXVpcmVkIGJ1dCBub3QgcHJvdmlkZWRcIixcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAoXG4gICAgICAgIDxPcGVuQUlTcGVlY2hSZWNvZ25pemVyXG4gICAgICAgICAgc2hvdWxkTGlzdGVuPXtzaG91bGRMaXN0ZW59XG4gICAgICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2s9e3NwZWVjaFN0YXR1c0NhbGxiYWNrfVxuICAgICAgICAgIHNwZWVjaFJlc3VsdENhbGxiYWNrPXtzcGVlY2hSZXN1bHRDYWxsYmFja31cbiAgICAgICAgICBzcGVlY2hUcmFuc2xhdGlvbkNhbGxiYWNrPXtzcGVlY2hUcmFuc2xhdGlvbkNhbGxiYWNrfVxuICAgICAgICAgIHNwZWVjaFJlYWR5Q2FsbGJhY2s9e3NwZWVjaFJlYWR5Q2FsbGJhY2t9XG4gICAgICAgICAgY2xpZW50U2VjcmV0PXtmaW5hbEdyb3FBcGlLZXl9XG4gICAgICAgICAgb3BlbmFpVHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludD17XG4gICAgICAgICAgICBvcGVuYWlDb25maWcudHJhbnNjcmlwdGlvblNlc3Npb25FbmRwb2ludFxuICAgICAgICAgIH1cbiAgICAgICAgICBvcGVuYWlUcmFuc2xhdGlvbkVuZHBvaW50PXtvcGVuYWlDb25maWcudHJhbnNsYXRpb25FbmRwb2ludH1cbiAgICAgICAgICBvcGVuYWlSZWFsdGltZVdlYlJ0Y1VybD17b3BlbmFpQ29uZmlnLnJlYWx0aW1lV2ViUnRjVXJsfVxuICAgICAgICAgIG9wZW5haVJlYWx0aW1lTW9kZWw9e29wZW5haUNvbmZpZy5yZWFsdGltZU1vZGVsfVxuICAgICAgICAgIG9wZW5haVRyYW5zbGF0aW9uTW9kZWw9e29wZW5haUNvbmZpZy50cmFuc2xhdGlvbk1vZGVsfVxuICAgICAgICAgIG9wZW5haVZhZEVuYWJsZWQ9e29wZW5haUNvbmZpZy52YWRFbmFibGVkfVxuICAgICAgICAgIG9wZW5haUF1dG9TdG9wT25WYWRTaWxlbmNlPXtcbiAgICAgICAgICAgIG9wZW5haUNvbmZpZy5hdXRvU3RvcE9uVmFkU2lsZW5jZVxuICAgICAgICAgIH1cbiAgICAgICAgICBvcGVuYWlWYWRUaHJlc2hvbGQ9e29wZW5haUNvbmZpZy52YWRUaHJlc2hvbGR9XG4gICAgICAgICAgb3BlbmFpVmFkUHJlZml4UGFkZGluZ01zPXtvcGVuYWlDb25maWcudmFkUHJlZml4UGFkZGluZ01zfVxuICAgICAgICAgIG9wZW5haVZhZFNpbGVuY2VEdXJhdGlvbk1zPXtcbiAgICAgICAgICAgIG9wZW5haUNvbmZpZy52YWRTaWxlbmNlRHVyYXRpb25Nc1xuICAgICAgICAgIH1cbiAgICAgICAgICBvcGVuYWlWYWRJZGxlVGltZW91dE1zPXtvcGVuYWlDb25maWcudmFkSWRsZVRpbWVvdXRNc31cbiAgICAgICAgICBvcGVuYWlQcmV3YXJtT25Nb3VudD17b3BlbmFpQ29uZmlnLnByZXdhcm1Pbk1vdW50fVxuICAgICAgICAgIGxhbmd1YWdlPXthcGlMYW5ndWFnZX1cbiAgICAgICAgICByZXF1ZXN0Q29udGV4dFByb3ZpZGVyPXtyZXF1ZXN0Q29udGV4dFByb3ZpZGVyfVxuICAgICAgICAgIG9uRXJyb3I9e2hhbmRsZUVycm9yfVxuICAgICAgICAvPlxuICAgICAgKTtcblxuICAgIGNhc2UgXCJncm9xLW5hdGl2ZVwiOiB7XG4gICAgICBpZiAoIWZpbmFsR3JvcUFwaUtleSkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXCJHcm9xIEFQSSBrZXkgaXMgcmVxdWlyZWQgYnV0IG5vdCBwcm92aWRlZFwiKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG5hdGl2ZU1vZHVsZSA9IGdldE5hdGl2ZVNwZWVjaE1vZHVsZSgpO1xuICAgICAgaWYgKCFuYXRpdmVNb2R1bGU/Lk5hdGl2ZVNwZWVjaFJlY29nbml6ZXIpIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgIFwiTmF0aXZlIHNwZWVjaCBtb2R1bGUgaXMgdW5hdmFpbGFibGUuIEluc3RhbGwgZXhwby1hdWRpbyArIGV4cG8tZmlsZS1zeXN0ZW0gYW5kIHVzZSBhIGRldiBjbGllbnQgYnVpbGQuXCIsXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBOYXRpdmVTcGVlY2hSZWNvZ25pemVyID0gbmF0aXZlTW9kdWxlLk5hdGl2ZVNwZWVjaFJlY29nbml6ZXI7XG4gICAgICByZXR1cm4gKFxuICAgICAgICA8TmF0aXZlU3BlZWNoUmVjb2duaXplclxuICAgICAgICAgIHNob3VsZExpc3Rlbj17c2hvdWxkTGlzdGVufVxuICAgICAgICAgIHNwZWVjaFN0YXR1c0NhbGxiYWNrPXtzcGVlY2hTdGF0dXNDYWxsYmFja31cbiAgICAgICAgICBzcGVlY2hSZXN1bHRDYWxsYmFjaz17c3BlZWNoUmVzdWx0Q2FsbGJhY2t9XG4gICAgICAgICAgc3BlZWNoVHJhbnNsYXRpb25DYWxsYmFjaz17c3BlZWNoVHJhbnNsYXRpb25DYWxsYmFja31cbiAgICAgICAgICBjbGllbnRTZWNyZXQ9e2ZpbmFsR3JvcUFwaUtleX1cbiAgICAgICAgICBncm9xQXBpQmFzZVVybD17Z3JvcUFwaUJhc2VVcmx9XG4gICAgICAgICAgZ3JvcVRyYW5zY3JpcHRpb25FbmRwb2ludD17Z3JvcVRyYW5zY3JpcHRpb25FbmRwb2ludH1cbiAgICAgICAgICBzdHJlYW09e3N0cmVhbUdyb3F9XG4gICAgICAgICAgbGFuZ3VhZ2U9e2FwaUxhbmd1YWdlfVxuICAgICAgICAgIG9uRXJyb3I9e2hhbmRsZUVycm9yfVxuICAgICAgICAvPlxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjYXNlIFwiZ3JvcS13ZWJcIjpcbiAgICAgIGlmICghZmluYWxHcm9xQXBpS2V5KSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihcIkdyb3EgQVBJIGtleSBpcyByZXF1aXJlZCBidXQgbm90IHByb3ZpZGVkXCIpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIHJldHVybiAoXG4gICAgICAgIDxHcm9xU3BlZWNoUmVjb2duaXplclxuICAgICAgICAgIHNob3VsZExpc3Rlbj17c2hvdWxkTGlzdGVufVxuICAgICAgICAgIHNwZWVjaFN0YXR1c0NhbGxiYWNrPXtzcGVlY2hTdGF0dXNDYWxsYmFja31cbiAgICAgICAgICBzcGVlY2hSZXN1bHRDYWxsYmFjaz17c3BlZWNoUmVzdWx0Q2FsbGJhY2t9XG4gICAgICAgICAgc3BlZWNoVHJhbnNsYXRpb25DYWxsYmFjaz17c3BlZWNoVHJhbnNsYXRpb25DYWxsYmFja31cbiAgICAgICAgICBjbGllbnRTZWNyZXQ9e2ZpbmFsR3JvcUFwaUtleX1cbiAgICAgICAgICBncm9xQXBpQmFzZVVybD17Z3JvcUFwaUJhc2VVcmx9XG4gICAgICAgICAgZ3JvcVRyYW5zY3JpcHRpb25FbmRwb2ludD17Z3JvcVRyYW5zY3JpcHRpb25FbmRwb2ludH1cbiAgICAgICAgICBzdHJlYW09e3N0cmVhbUdyb3F9XG4gICAgICAgICAgbGFuZ3VhZ2U9e2FwaUxhbmd1YWdlfVxuICAgICAgICAgIG9uRXJyb3I9e2hhbmRsZUVycm9yfVxuICAgICAgICAvPlxuICAgICAgKTtcblxuICAgIGNhc2UgXCJtbHgtbG9jYWxcIjoge1xuICAgICAgY29uc3QgZWZmZWN0aXZlVXJsID0gbG9jYWxNb2RlbENvbmZpZy5iYXNlVXJsO1xuICAgICAgaWYgKCFlZmZlY3RpdmVVcmwpIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKFwiTG9jYWwgd2hpc3BlciBVUkwgaXMgcmVxdWlyZWQgYnV0IG5vdCBwcm92aWRlZFwiKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAoXG4gICAgICAgIDxNTFhTcGVlY2hSZWNvZ25pemVyXG4gICAgICAgICAgc2hvdWxkTGlzdGVuPXtzaG91bGRMaXN0ZW59XG4gICAgICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2s9e3NwZWVjaFN0YXR1c0NhbGxiYWNrfVxuICAgICAgICAgIHNwZWVjaFJlc3VsdENhbGxiYWNrPXtzcGVlY2hSZXN1bHRDYWxsYmFja31cbiAgICAgICAgICBsYW5ndWFnZT17YXBpTGFuZ3VhZ2V9XG4gICAgICAgICAgb25FcnJvcj17aGFuZGxlRXJyb3J9XG4gICAgICAgICAgYmFzZVVybD17ZWZmZWN0aXZlVXJsfVxuICAgICAgICAgIG1vZGU9e2xvY2FsTW9kZWxDb25maWcubW9kZX1cbiAgICAgICAgICBtb2RlbE5hbWU9e2xvY2FsTW9kZWxDb25maWcubW9kZWx9XG4gICAgICAgIC8+XG4gICAgICApO1xuICAgIH1cblxuICAgIGNhc2UgXCJ3ZWJzcGVlY2hcIjpcbiAgICAgIHJldHVybiAoXG4gICAgICAgIDxXZWJTcGVlY2hSZWNvZ25pemVyXG4gICAgICAgICAgc2hvdWxkTGlzdGVuPXtzaG91bGRMaXN0ZW59XG4gICAgICAgICAgc3BlZWNoU3RhdHVzQ2FsbGJhY2s9e3NwZWVjaFN0YXR1c0NhbGxiYWNrfVxuICAgICAgICAgIHNwZWVjaFJlc3VsdENhbGxiYWNrPXtzcGVlY2hSZXN1bHRDYWxsYmFja31cbiAgICAgICAgICBsYW5ndWFnZT17d2ViU3BlZWNoTGFuZ3VhZ2V9XG4gICAgICAgIC8+XG4gICAgICApO1xuXG4gICAgY2FzZSBcIm5vbmVcIjpcbiAgICBkZWZhdWx0OlxuICAgICAgaWYgKGlzV2ViQ2xpZW50UnVudGltZSkge1xuICAgICAgICBsb2dnZXIud2FybihcIk5vIHNwZWVjaCByZWNvZ25pdGlvbiBhdmFpbGFibGVcIik7XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgfVxufTtcblxuLyoqXG4gKiBHZXQgc3BlZWNoIHJlY29nbml0aW9uIHN0YXR1cyBhbmQgY2FwYWJpbGl0aWVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTcGVlY2hSZWNvZ25pdGlvblN0YXR1cyhcbiAgb3ZlcnJpZGVzPzogUGFydGlhbDxTcGVlY2hSZWNvZ25pdGlvbkNvbmZpZz4sXG4pIHtcbiAgY29uc3QgY29uZmlnID0gZ2V0U3BlZWNoUmVjb2duaXRpb25Db25maWcob3ZlcnJpZGVzKTtcbiAgY29uc3QgbWV0aG9kID0gc2VsZWN0U3BlZWNoUmVjb2duaXRpb25NZXRob2QoY29uZmlnKTtcbiAgY29uc3QgbG9jYWxNb2RlbCA9IHJlc29sdmVMb2NhbE1vZGVsQ29uZmlnKGNvbmZpZyk7XG5cbiAgcmV0dXJuIHtcbiAgICBtZXRob2QsXG4gICAgY29uZmlnLFxuICAgIGNhcGFiaWxpdGllczoge1xuICAgICAgZ3JvcTogZ2V0R3JvcVNwZWVjaENhcGFiaWxpdGllcygpLFxuICAgICAgb3BlbmFpOiBnZXRPcGVuQUlTcGVlY2hDYXBhYmlsaXRpZXMoKSxcbiAgICAgIHdlYlNwZWVjaDoge1xuICAgICAgICBhdmFpbGFibGU6IGlzV2ViU3BlZWNoQXZhaWxhYmxlKCksXG4gICAgICAgIHBsYXRmb3JtOiBQbGF0Zm9ybS5PUyxcbiAgICAgIH0sXG4gICAgICBsb2NhbE1vZGVsOiB7XG4gICAgICAgIGVuYWJsZWQ6ICEhbG9jYWxNb2RlbC5lbmFibGVkT25XZWIsXG4gICAgICAgIHVybDogbG9jYWxNb2RlbC5iYXNlVXJsLFxuICAgICAgICBtb2RlOiBsb2NhbE1vZGVsLm1vZGUgfHwgXCJvbmVzaG90XCIsXG4gICAgICB9LFxuICAgIH0sXG4gICAgcmVjb21tZW5kYXRpb25zOiBnZXRSZWNvbW1lbmRhdGlvbnMobWV0aG9kLCBjb25maWcpLFxuICB9O1xufVxuXG4vKipcbiAqIEdldCByZWNvbW1lbmRhdGlvbnMgZm9yIGltcHJvdmluZyBzcGVlY2ggcmVjb2duaXRpb25cbiAqL1xuZnVuY3Rpb24gZ2V0UmVjb21tZW5kYXRpb25zKFxuICBtZXRob2Q6XG4gICAgfCBcIm9wZW5haS13ZWJcIlxuICAgIHwgXCJvcGVuYWktbmF0aXZlXCJcbiAgICB8IFwiZ3JvcS13ZWJcIlxuICAgIHwgXCJncm9xLW5hdGl2ZVwiXG4gICAgfCBcIndlYnNwZWVjaFwiXG4gICAgfCBcIm1seC1sb2NhbFwiXG4gICAgfCBcIm5vbmVcIixcbiAgY29uZmlnOiBTcGVlY2hSZWNvZ25pdGlvbkNvbmZpZyxcbik6IHN0cmluZ1tdIHtcbiAgY29uc3QgcmVjb21tZW5kYXRpb25zOiBzdHJpbmdbXSA9IFtdO1xuXG4gIGlmIChtZXRob2QgPT09IFwibm9uZVwiKSB7XG4gICAgcmVjb21tZW5kYXRpb25zLnB1c2goXCJObyBzcGVlY2ggcmVjb2duaXRpb24gYXZhaWxhYmxlXCIpO1xuXG4gICAgaWYgKCFjb25maWcuZ3JvcT8uYXBpS2V5ICYmIGNvbmZpZy5wcm92aWRlciAhPT0gXCJvcGVuYWlcIikge1xuICAgICAgcmVjb21tZW5kYXRpb25zLnB1c2goXG4gICAgICAgIFwiUHJvdmlkZSBhIEdyb3EgY2xpZW50IHNlY3JldCB2aWEgY29uZmlnIG9yIGRpc2FibGUgR3JvcSBzcGVlY2hcIixcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKFBsYXRmb3JtLk9TID09PSBcIndlYlwiKSB7XG4gICAgICBpZiAoIWlzR3JvcVNwZWVjaEF2YWlsYWJsZSgpKSB7XG4gICAgICAgIHJlY29tbWVuZGF0aW9ucy5wdXNoKFwiQnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IE1lZGlhUmVjb3JkZXIgQVBJXCIpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWlzV2ViU3BlZWNoQXZhaWxhYmxlKCkpIHtcbiAgICAgICAgcmVjb21tZW5kYXRpb25zLnB1c2goXCJCcm93c2VyIGRvZXMgbm90IHN1cHBvcnQgV2ViIFNwZWVjaCBBUElcIik7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlY29tbWVuZGF0aW9ucy5wdXNoKFxuICAgICAgICBcIkluc3RhbGwgZXhwby1hdWRpbyArIGV4cG8tZmlsZS1zeXN0ZW0gYW5kIHVzZSBhIGRldiBjbGllbnQgYnVpbGRcIixcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgaWYgKG1ldGhvZCA9PT0gXCJ3ZWJzcGVlY2hcIikge1xuICAgIHJlY29tbWVuZGF0aW9ucy5wdXNoKFwiVXNpbmcgV2ViIFNwZWVjaCBBUEkgKGZyZWUgYnV0IGxlc3MgYWNjdXJhdGUpXCIpO1xuICAgIHJlY29tbWVuZGF0aW9ucy5wdXNoKFwiRW5hYmxlIEdyb3Egc3BlZWNoIGZvciBiZXR0ZXIgYWNjdXJhY3lcIik7XG4gIH1cblxuICBpZiAobWV0aG9kID09PSBcImdyb3Etd2ViXCIpIHtcbiAgICByZWNvbW1lbmRhdGlvbnMucHVzaChcIlVzaW5nIEdyb3EgV2ViIChoaWdoIGFjY3VyYWN5LCBiZXN0IGZvciB3ZWIpXCIpO1xuICB9XG5cbiAgaWYgKG1ldGhvZCA9PT0gXCJncm9xLW5hdGl2ZVwiKSB7XG4gICAgcmVjb21tZW5kYXRpb25zLnB1c2goXCJVc2luZyBHcm9xIE5hdGl2ZSBjYXB0dXJlIChleHBvLWF1ZGlvKVwiKTtcbiAgfVxuXG4gIGlmIChtZXRob2QgPT09IFwib3BlbmFpLXdlYlwiKSB7XG4gICAgcmVjb21tZW5kYXRpb25zLnB1c2goXCJVc2luZyBPcGVuQUkgV2ViIFJlYWx0aW1lIHdpdGggc2VydmVyIFZBRFwiKTtcbiAgfVxuXG4gIGlmIChtZXRob2QgPT09IFwib3BlbmFpLW5hdGl2ZVwiKSB7XG4gICAgcmVjb21tZW5kYXRpb25zLnB1c2goXCJVc2luZyBPcGVuQUkgTmF0aXZlIFJlYWx0aW1lIHdpdGggUENNIHN0cmVhbVwiKTtcbiAgfVxuXG4gIGlmIChtZXRob2QgPT09IFwibWx4LWxvY2FsXCIpIHtcbiAgICByZWNvbW1lbmRhdGlvbnMucHVzaChcIlVzaW5nIExvY2FsIE1MWCBXaGlzcGVyIHNlcnZlciAoZmFzdCwgb2ZmbGluZSlcIik7XG4gICAgaWYgKCFjb25maWcubG9jYWxNb2RlbD8uYmFzZVVybCkge1xuICAgICAgcmVjb21tZW5kYXRpb25zLnB1c2goXCJTZXQgTE9DQUxfV0hJU1BFUl9VUkwgdG8gcG9pbnQgYXQgeW91ciBzZXJ2ZXJcIik7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlY29tbWVuZGF0aW9ucztcbn1cblxuLy8gRXhwb3J0IGZvciBjb252ZW5pZW5jZVxuZXhwb3J0IHtcbiAgaXNHcm9xU3BlZWNoQXZhaWxhYmxlLFxuICBnZXRHcm9xU3BlZWNoQ2FwYWJpbGl0aWVzLFxuICBpc09wZW5BSVNwZWVjaEF2YWlsYWJsZSxcbiAgZ2V0T3BlbkFJU3BlZWNoQ2FwYWJpbGl0aWVzLFxufTtcblxuLy8gRGVmYXVsdCBleHBvcnRcbmV4cG9ydCBkZWZhdWx0IFVuaWZpZWRTcGVlY2hSZWNvZ25pemVyO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBUUEsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsWUFBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsa0JBQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLHNCQUFBLEdBQUFILE9BQUE7QUFLQSxJQUFBSSxxQkFBQSxHQUFBSixPQUFBO0FBSUEsSUFBQUssd0JBQUEsR0FBQUwsT0FBQTtBQUtBLElBQUFNLE9BQUEsR0FBQVAsc0JBQUEsQ0FBQUMsT0FBQTtBQUErQixTQUFBRCx1QkFBQVEsQ0FBQSxXQUFBQSxDQUFBLElBQUFBLENBQUEsQ0FBQUMsVUFBQSxHQUFBRCxDQUFBLEtBQUFFLE9BQUEsRUFBQUYsQ0FBQTtBQUFBLFNBQUFHLFFBQUFILENBQUEsRUFBQUksQ0FBQSxRQUFBQyxDQUFBLEdBQUFDLE1BQUEsQ0FBQUMsSUFBQSxDQUFBUCxDQUFBLE9BQUFNLE1BQUEsQ0FBQUUscUJBQUEsUUFBQUMsQ0FBQSxHQUFBSCxNQUFBLENBQUFFLHFCQUFBLENBQUFSLENBQUEsR0FBQUksQ0FBQSxLQUFBSyxDQUFBLEdBQUFBLENBQUEsQ0FBQUMsTUFBQSxXQUFBTixDQUFBLFdBQUFFLE1BQUEsQ0FBQUssd0JBQUEsQ0FBQVgsQ0FBQSxFQUFBSSxDQUFBLEVBQUFRLFVBQUEsT0FBQVAsQ0FBQSxDQUFBUSxJQUFBLENBQUFDLEtBQUEsQ0FBQVQsQ0FBQSxFQUFBSSxDQUFBLFlBQUFKLENBQUE7QUFBQSxTQUFBVSxjQUFBZixDQUFBLGFBQUFJLENBQUEsTUFBQUEsQ0FBQSxHQUFBWSxTQUFBLENBQUFDLE1BQUEsRUFBQWIsQ0FBQSxVQUFBQyxDQUFBLFdBQUFXLFNBQUEsQ0FBQVosQ0FBQSxJQUFBWSxTQUFBLENBQUFaLENBQUEsUUFBQUEsQ0FBQSxPQUFBRCxPQUFBLENBQUFHLE1BQUEsQ0FBQUQsQ0FBQSxPQUFBYSxPQUFBLFdBQUFkLENBQUEsSUFBQWUsZUFBQSxDQUFBbkIsQ0FBQSxFQUFBSSxDQUFBLEVBQUFDLENBQUEsQ0FBQUQsQ0FBQSxTQUFBRSxNQUFBLENBQUFjLHlCQUFBLEdBQUFkLE1BQUEsQ0FBQWUsZ0JBQUEsQ0FBQXJCLENBQUEsRUFBQU0sTUFBQSxDQUFBYyx5QkFBQSxDQUFBZixDQUFBLEtBQUFGLE9BQUEsQ0FBQUcsTUFBQSxDQUFBRCxDQUFBLEdBQUFhLE9BQUEsV0FBQWQsQ0FBQSxJQUFBRSxNQUFBLENBQUFnQixjQUFBLENBQUF0QixDQUFBLEVBQUFJLENBQUEsRUFBQUUsTUFBQSxDQUFBSyx3QkFBQSxDQUFBTixDQUFBLEVBQUFELENBQUEsaUJBQUFKLENBQUE7QUFBQSxTQUFBbUIsZ0JBQUFuQixDQUFBLEVBQUFJLENBQUEsRUFBQUMsQ0FBQSxZQUFBRCxDQUFBLEdBQUFtQixjQUFBLENBQUFuQixDQUFBLE1BQUFKLENBQUEsR0FBQU0sTUFBQSxDQUFBZ0IsY0FBQSxDQUFBdEIsQ0FBQSxFQUFBSSxDQUFBLElBQUFvQixLQUFBLEVBQUFuQixDQUFBLEVBQUFPLFVBQUEsTUFBQWEsWUFBQSxNQUFBQyxRQUFBLFVBQUExQixDQUFBLENBQUFJLENBQUEsSUFBQUMsQ0FBQSxFQUFBTCxDQUFBO0FBQUEsU0FBQXVCLGVBQUFsQixDQUFBLFFBQUFzQixDQUFBLEdBQUFDLFlBQUEsQ0FBQXZCLENBQUEsdUNBQUFzQixDQUFBLEdBQUFBLENBQUEsR0FBQUEsQ0FBQTtBQUFBLFNBQUFDLGFBQUF2QixDQUFBLEVBQUFELENBQUEsMkJBQUFDLENBQUEsS0FBQUEsQ0FBQSxTQUFBQSxDQUFBLE1BQUFMLENBQUEsR0FBQUssQ0FBQSxDQUFBd0IsTUFBQSxDQUFBQyxXQUFBLGtCQUFBOUIsQ0FBQSxRQUFBMkIsQ0FBQSxHQUFBM0IsQ0FBQSxDQUFBK0IsSUFBQSxDQUFBMUIsQ0FBQSxFQUFBRCxDQUFBLHVDQUFBdUIsQ0FBQSxTQUFBQSxDQUFBLFlBQUFLLFNBQUEseUVBQUE1QixDQUFBLEdBQUE2QixNQUFBLEdBQUFDLE1BQUEsRUFBQTdCLENBQUEsS0F6Qi9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBNEVBO0FBQ0E7QUFDQTtBQUNBOztBQVlBLFNBQVM4QixpQkFBaUJBLENBQ3hCWCxLQUFjLEVBQ2lCO0VBQy9CLElBQUksQ0FBQ0EsS0FBSyxFQUFFLE9BQU9ZLFNBQVM7RUFDNUIsTUFBTUMsVUFBVSxHQUFHYixLQUFLLENBQUNjLElBQUksQ0FBQyxDQUFDLENBQUNDLFdBQVcsQ0FBQyxDQUFDO0VBQzdDLElBQUlGLFVBQVUsS0FBSyxNQUFNLEVBQUUsT0FBTyxNQUFNO0VBQ3hDLElBQUlBLFVBQVUsS0FBSyxRQUFRLEVBQUUsT0FBTyxRQUFRO0VBQzVDLE9BQU9ELFNBQVM7QUFDbEI7QUFFQSxNQUFNSSxzQkFBMEQsR0FDOUQsbUJBQW1CO0FBQ3JCLE1BQU1DLHlCQUF5QixHQUFHLGNBQWM7QUFDaEQsTUFBTUMsdUNBQXVDLEdBQUcsS0FBSztBQUNyRCxNQUFNQyxzQ0FBc0MsR0FBRyxJQUFJO0FBQ25ELE1BQU1DLCtCQUErQixHQUFHLElBQUk7QUFFNUMsU0FBU0Msa0JBQWtCQSxDQUFDQyxHQUFXLEVBQXNCO0VBQzNELElBQUk7SUFDRixNQUFNQyxHQUFHLEdBQUcsT0FBT0MsT0FBTyxLQUFLLFdBQVcsR0FBR0EsT0FBTyxDQUFDRCxHQUFHLEdBQUdYLFNBQVM7SUFDcEUsTUFBTVosS0FBSyxHQUFHdUIsR0FBRyxHQUFHRCxHQUFHLENBQUM7SUFDeEIsSUFBSSxPQUFPdEIsS0FBSyxLQUFLLFFBQVEsRUFBRSxPQUFPWSxTQUFTO0lBQy9DLE1BQU1hLE9BQU8sR0FBR3pCLEtBQUssQ0FBQ2MsSUFBSSxDQUFDLENBQUM7SUFDNUIsT0FBT1csT0FBTyxDQUFDaEMsTUFBTSxHQUFHLENBQUMsR0FBR2dDLE9BQU8sR0FBR2IsU0FBUztFQUNqRCxDQUFDLENBQUMsTUFBTTtJQUNOLE9BQU9BLFNBQVM7RUFDbEI7QUFDRjtBQUVBLFNBQVNjLGVBQWVBLENBQ3RCSixHQUFXLEVBQ1hLLFFBQWlCLEVBQ1I7RUFDVCxNQUFNQyxHQUFHLEdBQUdQLGtCQUFrQixDQUFDQyxHQUFHLENBQUM7RUFDbkMsSUFBSSxDQUFDTSxHQUFHLEVBQUUsT0FBT0QsUUFBUTtFQUN6QixNQUFNZCxVQUFVLEdBQUdlLEdBQUcsQ0FBQ2IsV0FBVyxDQUFDLENBQUM7RUFDcEMsSUFBSUYsVUFBVSxLQUFLLE1BQU0sSUFBSUEsVUFBVSxLQUFLLEdBQUcsSUFBSUEsVUFBVSxLQUFLLEtBQUssSUFBSUEsVUFBVSxLQUFLLElBQUksRUFBRTtJQUM5RixPQUFPLElBQUk7RUFDYjtFQUNBLElBQUlBLFVBQVUsS0FBSyxPQUFPLElBQUlBLFVBQVUsS0FBSyxHQUFHLElBQUlBLFVBQVUsS0FBSyxJQUFJLElBQUlBLFVBQVUsS0FBSyxLQUFLLEVBQUU7SUFDL0YsT0FBTyxLQUFLO0VBQ2Q7RUFDQSxPQUFPYyxRQUFRO0FBQ2pCO0FBRUEsU0FBU0UsY0FBY0EsQ0FDckJQLEdBQVcsRUFDWEssUUFBZ0IsRUFDUjtFQUNSLE1BQU1DLEdBQUcsR0FBR1Asa0JBQWtCLENBQUNDLEdBQUcsQ0FBQztFQUNuQyxJQUFJLENBQUNNLEdBQUcsRUFBRSxPQUFPRCxRQUFRO0VBQ3pCLE1BQU1HLE1BQU0sR0FBR3BCLE1BQU0sQ0FBQ2tCLEdBQUcsQ0FBQztFQUMxQixJQUFJLENBQUNsQixNQUFNLENBQUNxQixRQUFRLENBQUNELE1BQU0sQ0FBQyxFQUFFLE9BQU9ILFFBQVE7RUFDN0MsT0FBT0csTUFBTTtBQUNmO0FBRUEsTUFBTUUsNEJBQTRCLEdBQUlDLE9BQWdCLElBQUs7RUFDekQsTUFBTVIsT0FBTyxHQUFHLENBQUNRLE9BQU8sSUFBSSxFQUFFLEVBQUVuQixJQUFJLENBQUMsQ0FBQyxDQUFDb0IsT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7RUFDMUQsSUFBSSxDQUFDVCxPQUFPLEVBQUU7SUFDWixPQUFPO01BQ0xVLDRCQUE0QixFQUFFdkIsU0FBUztNQUN2Q3dCLG1CQUFtQixFQUFFeEI7SUFDdkIsQ0FBQztFQUNIO0VBQ0EsT0FBTztJQUNMdUIsNEJBQTRCLEVBQUUsR0FBR1YsT0FBTyw0Q0FBNEM7SUFDcEZXLG1CQUFtQixFQUFFLEdBQUdYLE9BQU87RUFDakMsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTWSxtQkFBbUJBLENBQzFCQyxNQUF5QyxFQUN0QjtFQUNuQixNQUFNQyxRQUEyQixHQUFHO0lBQ2xDQyxhQUFhLEVBQUV4QixzQkFBc0I7SUFDckN5QixnQkFBZ0IsRUFBRXhCLHlCQUF5QjtJQUMzQ3lCLFVBQVUsRUFBRSxJQUFJO0lBQ2hCQyxvQkFBb0IsRUFBRWpCLGVBQWUsQ0FDbkMsaUNBQWlDLEVBQ2pDUix1Q0FDRixDQUFDO0lBQ0QwQixZQUFZLEVBQUUsR0FBRztJQUNqQkMsa0JBQWtCLEVBQUUsR0FBRztJQUN2QkMsb0JBQW9CLEVBQUVqQixjQUFjLENBQ2xDLGdDQUFnQyxFQUNoQ1Ysc0NBQ0YsQ0FBQztJQUNENEIsZ0JBQWdCLEVBQUUsSUFBSTtJQUN0QkMsY0FBYyxFQUFFdEIsZUFBZSxDQUM3Qix5QkFBeUIsRUFDekJOLCtCQUNGO0VBQ0YsQ0FBQztFQUVELE1BQU02QixNQUFNLEdBQUdYLE1BQU0sRUFBRVksTUFBTSxJQUFJLENBQUMsQ0FBQztFQUNuQyxNQUFNQyxZQUFZLEdBQUdGLE1BQU0sQ0FBQ0csWUFBWTtFQUN4QyxNQUFNQyxnQkFBZ0IsR0FBR3JCLDRCQUE0QixDQUFDbUIsWUFBWSxDQUFDO0VBRW5FLE9BQUE1RCxhQUFBLENBQUFBLGFBQUEsQ0FBQUEsYUFBQSxLQUNLZ0QsUUFBUSxHQUNSVSxNQUFNO0lBQ1RkLDRCQUE0QixFQUMxQmMsTUFBTSxDQUFDZCw0QkFBNEIsSUFDbkNrQixnQkFBZ0IsQ0FBQ2xCLDRCQUE0QjtJQUMvQ0MsbUJBQW1CLEVBQ2pCYSxNQUFNLENBQUNiLG1CQUFtQixJQUFJaUIsZ0JBQWdCLENBQUNqQixtQkFBbUI7SUFDcEVrQixpQkFBaUIsRUFBRUwsTUFBTSxDQUFDSyxpQkFBaUI7SUFDM0NkLGFBQWEsRUFBRVMsTUFBTSxDQUFDVCxhQUFhLElBQUlELFFBQVEsQ0FBQ0MsYUFBYTtJQUM3REMsZ0JBQWdCLEVBQUVRLE1BQU0sQ0FBQ1IsZ0JBQWdCLElBQUlGLFFBQVEsQ0FBQ0UsZ0JBQWdCO0lBQ3RFQyxVQUFVLEVBQUVPLE1BQU0sQ0FBQ1AsVUFBVSxJQUFJSCxRQUFRLENBQUNHLFVBQVU7SUFDcERDLG9CQUFvQixFQUNsQk0sTUFBTSxDQUFDTixvQkFBb0IsSUFBSUosUUFBUSxDQUFDSSxvQkFBb0I7SUFDOURDLFlBQVksRUFBRUssTUFBTSxDQUFDTCxZQUFZLElBQUlMLFFBQVEsQ0FBQ0ssWUFBWTtJQUMxREMsa0JBQWtCLEVBQ2hCSSxNQUFNLENBQUNKLGtCQUFrQixJQUFJTixRQUFRLENBQUNNLGtCQUFrQjtJQUMxREMsb0JBQW9CLEVBQ2xCRyxNQUFNLENBQUNILG9CQUFvQixJQUFJUCxRQUFRLENBQUNPLG9CQUFvQjtJQUM5REMsZ0JBQWdCLEVBQ2RFLE1BQU0sQ0FBQ0YsZ0JBQWdCLElBQUlSLFFBQVEsQ0FBQ1EsZ0JBQWdCO0lBQ3REQyxjQUFjLEVBQ1pDLE1BQU0sQ0FBQ0QsY0FBYyxJQUFJVCxRQUFRLENBQUNTO0VBQWM7QUFFdEQ7QUFFQSxTQUFTTyxpQkFBaUJBLENBQ3hCakIsTUFBeUMsRUFDeEI7RUFDakIsTUFBTUMsUUFBeUIsR0FBRztJQUNoQ2lCLE9BQU8sRUFBRSxJQUFJO0lBQ2JDLE1BQU0sRUFBRTtFQUNWLENBQUM7RUFFRCxPQUFBbEUsYUFBQSxDQUFBQSxhQUFBLEtBQ0tnRCxRQUFRLEdBQ1BELE1BQU0sRUFBRW9CLElBQUksSUFBSSxDQUFDLENBQUM7QUFFMUI7QUFFQSxTQUFTQyx1QkFBdUJBLENBQzlCckIsTUFBeUMsRUFDbEI7RUFDdkIsTUFBTUMsUUFBK0IsR0FBRztJQUN0Q3FCLFlBQVksRUFBRSxLQUFLO0lBQ25CM0IsT0FBTyxFQUFFLHVCQUF1QjtJQUNoQzRCLElBQUksRUFBRSxTQUFTO0lBQ2ZDLEtBQUssRUFBRTtFQUNULENBQUM7RUFFRCxPQUFBdkUsYUFBQSxDQUFBQSxhQUFBLEtBQ0tnRCxRQUFRLEdBQ1BELE1BQU0sRUFBRXlCLFVBQVUsSUFBSSxDQUFDLENBQUM7QUFFaEM7O0FBRUE7QUFDQTtBQUNBO0FBQ08sU0FBU0MsMEJBQTBCQSxDQUN4Q0MsU0FBNEMsRUFDbkI7RUFDekIsTUFBTTFCLFFBQWlDLEdBQUc7SUFDeEMyQixRQUFRLEVBQUUsTUFBTTtJQUNoQkMsbUJBQW1CLEVBQUUsSUFBSTtJQUN6QlQsSUFBSSxFQUFFSCxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3pCTCxNQUFNLEVBQUViLG1CQUFtQixDQUFDLENBQUM7SUFDN0IwQixVQUFVLEVBQUVKLHVCQUF1QixDQUFDO0VBQ3RDLENBQUM7RUFFRCxNQUFNUyxNQUErQixHQUFBN0UsYUFBQSxDQUFBQSxhQUFBLENBQUFBLGFBQUEsS0FDaENnRCxRQUFRLEdBQ1AwQixTQUFTLElBQUksQ0FBQyxDQUFDO0lBQ25CQyxRQUFRLEVBQ052RCxpQkFBaUIsQ0FBQ3NELFNBQVMsRUFBRUMsUUFBUSxDQUFDLElBQ3RDdkQsaUJBQWlCLENBQUM0QixRQUFRLENBQUMyQixRQUFRLENBQUMsSUFDcEM7RUFBTSxFQUNUO0VBRUQsT0FBQTNFLGFBQUEsQ0FBQUEsYUFBQSxLQUNLNkUsTUFBTTtJQUNUVixJQUFJLEVBQUVILGlCQUFpQixDQUFDYSxNQUFNLENBQUM7SUFDL0JsQixNQUFNLEVBQUViLG1CQUFtQixDQUFDK0IsTUFBTSxDQUFDO0lBQ25DTCxVQUFVLEVBQUVKLHVCQUF1QixDQUFDUyxNQUFNO0VBQUM7QUFFL0M7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBU0MsMEJBQTBCQSxDQUFBLEVBQVk7RUFDN0MsSUFBSSxPQUFPQyxNQUFNLEtBQUssV0FBVyxFQUFFO0lBQ2pDLE9BQU8sS0FBSztFQUNkO0VBRUEsT0FBTyx5QkFBeUIsSUFBSUEsTUFBTSxJQUFJLG1CQUFtQixJQUFJQSxNQUFNO0FBQzdFO0FBRU8sTUFBTUMsb0JBQW9CLEdBQUFDLE9BQUEsQ0FBQUQsb0JBQUEsR0FBR0YsMEJBQTBCO0FBRTlELE1BQU1JLG9CQUFvQixHQUFJQyxJQUFhLElBQUs7RUFDOUMsTUFBTTdELFVBQVUsR0FBRyxDQUFDNkQsSUFBSSxJQUFJLElBQUksRUFBRTVELElBQUksQ0FBQyxDQUFDLENBQUNDLFdBQVcsQ0FBQyxDQUFDO0VBQ3RELE9BQU9GLFVBQVUsQ0FBQ3BCLE1BQU0sR0FBRyxDQUFDLEdBQUdvQixVQUFVLEdBQUcsSUFBSTtBQUNsRCxDQUFDO0FBRUQsTUFBTThELG1CQUFtQixHQUFJRCxJQUFZLElBQUtBLElBQUksQ0FBQ0UsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVoRSxNQUFNQyxpQkFBaUIsR0FBSUgsSUFBWSxJQUFLO0VBQzFDLElBQUlBLElBQUksQ0FBQ0ksVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sT0FBTztFQUN6QyxJQUFJSixJQUFJLENBQUNJLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLE9BQU87RUFDekMsT0FBT0osSUFBSTtBQUNiLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQVdBLElBQUlLLHVCQUE4RDtBQUVsRSxJQUFJQyw2QkFBMEU7QUFFOUUsU0FBU0MscUJBQXFCQSxDQUFBLEVBQThCO0VBQzFELElBQUlGLHVCQUF1QixLQUFLbkUsU0FBUyxFQUFFO0lBQ3pDLE9BQU9tRSx1QkFBdUI7RUFDaEM7RUFFQSxJQUFJO0lBQ0Y7SUFDQTtJQUNBQSx1QkFBdUIsR0FBRzlHLE9BQU8sQ0FBQyw2QkFBNkIsQ0FBQztFQUNsRSxDQUFDLENBQUMsT0FBT2lILEtBQUssRUFBRTtJQUNkSCx1QkFBdUIsR0FBRyxJQUFJO0lBQzlCSSxlQUFNLENBQUNDLEtBQUssQ0FBQyxtQ0FBbUMsRUFBRUYsS0FBSyxDQUFDO0VBQzFEO0VBRUEsT0FBT0gsdUJBQXVCO0FBQ2hDO0FBRUEsU0FBU00sMkJBQTJCQSxDQUFBLEVBQVk7RUFDOUMsTUFBTUMsWUFBWSxHQUFHTCxxQkFBcUIsQ0FBQyxDQUFDO0VBQzVDLE9BQU8sQ0FBQyxDQUFDSyxZQUFZLEVBQUVDLHVCQUF1QixHQUFHLENBQUM7QUFDcEQ7QUFFQSxTQUFTQywyQkFBMkJBLENBQUEsRUFBb0M7RUFDdEUsSUFBSVIsNkJBQTZCLEtBQUtwRSxTQUFTLEVBQUU7SUFDL0MsT0FBT29FLDZCQUE2QjtFQUN0QztFQUVBLElBQUk7SUFDRjtJQUNBO0lBQ0FBLDZCQUE2QixHQUFHL0csT0FBTyxDQUFDLG9DQUFvQyxDQUFDO0VBQy9FLENBQUMsQ0FBQyxPQUFPaUgsS0FBSyxFQUFFO0lBQ2RGLDZCQUE2QixHQUFHLElBQUk7SUFDcENHLGVBQU0sQ0FBQ0MsS0FBSyxDQUFDLDBDQUEwQyxFQUFFRixLQUFLLENBQUM7RUFDakU7RUFFQSxPQUFPRiw2QkFBNkI7QUFDdEM7QUFFQSxTQUFTUyxpQ0FBaUNBLENBQUEsRUFBWTtFQUNwRCxNQUFNSCxZQUFZLEdBQUdFLDJCQUEyQixDQUFDLENBQUM7RUFDbEQsT0FBTyxDQUFDLENBQUNGLFlBQVksRUFBRUksNkJBQTZCLEdBQUcsQ0FBQztBQUMxRDs7QUFFQTtBQUNBO0FBQ0E7QUFDTyxTQUFTQyw2QkFBNkJBLENBQzNDckQsTUFBK0IsRUFDL0JzRCxZQUFxQixFQUNFO0VBQ3ZCLE1BQU1DLEtBQUssR0FBR0MscUJBQVEsQ0FBQ0MsRUFBRSxLQUFLLEtBQUs7RUFDbkMsTUFBTUMsUUFBUSxHQUFHRixxQkFBUSxDQUFDQyxFQUFFLEtBQUssS0FBSyxJQUFJRCxxQkFBUSxDQUFDQyxFQUFFLEtBQUssU0FBUztFQUNuRSxNQUFNRSxrQkFBa0IsR0FBR0osS0FBSyxJQUFJLE9BQU92QixNQUFNLEtBQUssV0FBVztFQUNqRSxNQUFNNEIscUJBQXFCLEdBQUdELGtCQUFrQjtFQUNoRCxNQUFNL0IsUUFBUSxHQUFHdkQsaUJBQWlCLENBQUMyQixNQUFNLENBQUM0QixRQUFRLENBQUMsSUFBSSxNQUFNO0VBQzdELE1BQU1SLElBQUksR0FBR0gsaUJBQWlCLENBQUNqQixNQUFNLENBQUM7RUFDdEMsTUFBTVksTUFBTSxHQUFHYixtQkFBbUIsQ0FBQ0MsTUFBTSxDQUFDO0VBQzFDLE1BQU15QixVQUFVLEdBQUdKLHVCQUF1QixDQUFDckIsTUFBTSxDQUFDO0VBRWxELE1BQU02RCxVQUFVLEdBQUcsQ0FBQyxFQUFFUCxZQUFZLElBQUlsQyxJQUFJLENBQUMwQyxNQUFNLENBQUM7RUFFbEQsSUFBSWxDLFFBQVEsS0FBSyxRQUFRLEVBQUU7SUFDekIsSUFBSThCLFFBQVEsRUFBRTtNQUNaLElBQ0U5QyxNQUFNLENBQUNmLDRCQUE0QixJQUNuQ3NELGlDQUFpQyxDQUFDLENBQUMsRUFDbkM7UUFDQU4sZUFBTSxDQUFDa0IsSUFBSSxDQUFDLHlDQUF5QyxDQUFDO1FBQ3RELE9BQU8sZUFBZTtNQUN4QjtNQUNBLElBQUlILHFCQUFxQixFQUFFO1FBQ3pCZixlQUFNLENBQUNtQixJQUFJLENBQ1QsdUhBQ0YsQ0FBQztNQUNIO01BQ0EsT0FBTyxNQUFNO0lBQ2Y7SUFFQSxJQUFJVCxLQUFLLEVBQUU7TUFDVCxJQUFJM0MsTUFBTSxDQUFDZiw0QkFBNEIsSUFBSSxJQUFBb0UsZ0RBQXVCLEVBQUMsQ0FBQyxFQUFFO1FBQ3BFcEIsZUFBTSxDQUFDa0IsSUFBSSxDQUFDLHNDQUFzQyxDQUFDO1FBQ25ELE9BQU8sWUFBWTtNQUNyQjtNQUNBLElBQUlILHFCQUFxQixFQUFFO1FBQ3pCZixlQUFNLENBQUNtQixJQUFJLENBQUMsa0NBQWtDLENBQUM7TUFDakQ7TUFDQSxPQUFPLE1BQU07SUFDZjtFQUNGOztFQUVBO0VBQ0EsSUFBSU4sUUFBUSxFQUFFO0lBQ1osSUFBSXRDLElBQUksQ0FBQ0YsT0FBTyxJQUFJMkMsVUFBVSxJQUFJZCwyQkFBMkIsQ0FBQyxDQUFDLEVBQUU7TUFDL0RGLGVBQU0sQ0FBQ2tCLElBQUksQ0FBQyxrQ0FBa0MsQ0FBQztNQUMvQyxPQUFPLGFBQWE7SUFDdEI7SUFDQSxJQUFJSCxxQkFBcUIsRUFBRTtNQUN6QmYsZUFBTSxDQUFDbUIsSUFBSSxDQUNULGlIQUNGLENBQUM7SUFDSDtJQUNBLE9BQU8sTUFBTTtFQUNmOztFQUVBO0VBQ0EsSUFBSVQsS0FBSyxFQUFFO0lBQ1QsSUFBSTlCLFVBQVUsQ0FBQ0gsWUFBWSxJQUFJRyxVQUFVLENBQUM5QixPQUFPLEVBQUU7TUFDakRrRCxlQUFNLENBQUNrQixJQUFJLENBQUMsa0NBQWtDLENBQUM7TUFDL0MsT0FBTyxXQUFXO0lBQ3BCOztJQUVBO0lBQ0EsSUFBSTNDLElBQUksQ0FBQ0YsT0FBTyxJQUFJMkMsVUFBVSxJQUFJLElBQUFLLDRDQUFxQixFQUFDLENBQUMsRUFBRTtNQUN6RHJCLGVBQU0sQ0FBQ2tCLElBQUksQ0FBQywwQ0FBMEMsQ0FBQztNQUN2RCxPQUFPLFVBQVU7SUFDbkI7O0lBRUE7SUFDQSxJQUFJL0QsTUFBTSxDQUFDNkIsbUJBQW1CLElBQUlJLG9CQUFvQixDQUFDLENBQUMsRUFBRTtNQUN4RFksZUFBTSxDQUFDa0IsSUFBSSxDQUFDLG1DQUFtQyxDQUFDO01BQ2hELE9BQU8sV0FBVztJQUNwQjtFQUNGO0VBQ0EsSUFBSUgscUJBQXFCLEVBQUU7SUFDekJmLGVBQU0sQ0FBQ21CLElBQUksQ0FBQywyQ0FBMkMsQ0FBQztFQUMxRDtFQUNBLE9BQU8sTUFBTTtBQUNmOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sTUFBTUcsdUJBRVosR0FBR0EsQ0FBQztFQUNIQyxZQUFZO0VBQ1pDLG9CQUFvQjtFQUNwQkMsb0JBQW9CO0VBQ3BCQyx5QkFBeUI7RUFDekJDLG1CQUFtQjtFQUNuQkMsdUJBQXVCO0VBQ3ZCbkIsWUFBWTtFQUNab0IsUUFBUSxHQUFHLElBQUk7RUFDZkMsT0FBTztFQUNQQyxzQkFBc0I7RUFDdEI1RTtBQUM0QixDQUFDLEtBQUs7RUFDbEM7RUFDQSxNQUFNNkUsY0FBYyxHQUFHbkQsMEJBQTBCLENBQUMxQixNQUFNLENBQUM7RUFDekQsTUFBTTJELGtCQUFrQixHQUN0QkgscUJBQVEsQ0FBQ0MsRUFBRSxLQUFLLEtBQUssSUFBSSxPQUFPekIsTUFBTSxLQUFLLFdBQVc7RUFDeEQsTUFBTThDLGtCQUFrQixHQUFHM0Msb0JBQW9CLENBQUN1QyxRQUFRLENBQUM7RUFDekQsTUFBTUssV0FBVyxHQUFHMUMsbUJBQW1CLENBQUN5QyxrQkFBa0IsQ0FBQztFQUMzRCxNQUFNRSxpQkFBaUIsR0FBR3pDLGlCQUFpQixDQUFDdUMsa0JBQWtCLENBQUM7O0VBRS9EO0VBQ0EsTUFBTUcsTUFBTSxHQUFHNUIsNkJBQTZCLENBQUN3QixjQUFjLEVBQUV2QixZQUFZLENBQUM7RUFDMUUsSUFBSUssa0JBQWtCLEVBQUU7SUFDdEJkLGVBQU0sQ0FBQ0MsS0FBSyxDQUFDLHFDQUFxQyxFQUFFbUMsTUFBTSxDQUFDO0VBQzdEO0VBQ0EsTUFBTUMsVUFBVSxHQUFHakUsaUJBQWlCLENBQUM0RCxjQUFjLENBQUM7RUFDcEQsTUFBTU0sWUFBWSxHQUFHcEYsbUJBQW1CLENBQUM4RSxjQUFjLENBQUM7RUFDeEQsTUFBTU8sZ0JBQWdCLEdBQUcvRCx1QkFBdUIsQ0FBQ3dELGNBQWMsQ0FBQztFQUVoRSxNQUFNUSxlQUFlLEdBQUcvQixZQUFZLElBQUk0QixVQUFVLENBQUNwQixNQUFNLElBQUksRUFBRTtFQUMvRCxNQUFNd0IsY0FBYyxHQUFHSixVQUFVLENBQUNLLFVBQVU7RUFDNUMsTUFBTUMseUJBQXlCLEdBQUdOLFVBQVUsQ0FBQ08scUJBQXFCO0VBQ2xFLE1BQU1DLFVBQVUsR0FBR1IsVUFBVSxDQUFDL0QsTUFBTTtFQUVwQyxJQUFJK0QsVUFBVSxDQUFDaEUsT0FBTyxJQUFJLENBQUNtRSxlQUFlLEVBQUU7SUFDMUN4QyxlQUFNLENBQUNtQixJQUFJLENBQ1QsMEdBQ0YsQ0FBQztFQUNIOztFQUVBO0VBQ0EsTUFBTTJCLFdBQVcsR0FBSS9DLEtBQVksSUFBSztJQUNwQ0MsZUFBTSxDQUFDRCxLQUFLLENBQUMsMkJBQTJCLEVBQUVBLEtBQUssQ0FBQztJQUVoRCxJQUFJK0IsT0FBTyxFQUFFO01BQ1hBLE9BQU8sQ0FBQy9CLEtBQUssQ0FBQztJQUNoQjs7SUFFQTtJQUNBO0VBQ0YsQ0FBQzs7RUFFRDtFQUNBLFFBQVFxQyxNQUFNO0lBQ1osS0FBSyxlQUFlO01BQUU7UUFDcEIsSUFBSSxDQUFDRSxZQUFZLENBQUN0Riw0QkFBNEIsRUFBRTtVQUM5Q2dELGVBQU0sQ0FBQ0QsS0FBSyxDQUNWLG9FQUNGLENBQUM7VUFDRCxPQUFPLElBQUk7UUFDYjtRQUVBLE1BQU1nRCxrQkFBa0IsR0FBRzFDLDJCQUEyQixDQUFDLENBQUM7UUFDeEQsSUFBSSxDQUFDMEMsa0JBQWtCLEVBQUVDLDRCQUE0QixFQUFFO1VBQ3JEaEQsZUFBTSxDQUFDRCxLQUFLLENBQ1Ysa0dBQ0YsQ0FBQztVQUNELE9BQU8sSUFBSTtRQUNiO1FBRUEsTUFBTWlELDRCQUE0QixHQUNoQ0Qsa0JBQWtCLENBQUNDLDRCQUE0QjtRQUVqRCxvQkFDRXBLLE1BQUEsQ0FBQVcsT0FBQSxDQUFBMEosYUFBQSxDQUFDRCw0QkFBNEI7VUFDM0J6QixZQUFZLEVBQUVBLFlBQWE7VUFDM0JDLG9CQUFvQixFQUFFQSxvQkFBcUI7VUFDM0NDLG9CQUFvQixFQUFFQSxvQkFBcUI7VUFDM0NDLHlCQUF5QixFQUFFQSx5QkFBMEI7VUFDckRDLG1CQUFtQixFQUFFQSxtQkFBb0I7VUFDekNsQixZQUFZLEVBQUUrQixlQUFnQjtVQUM5QlUsa0NBQWtDLEVBQ2hDWixZQUFZLENBQUN0Riw0QkFDZDtVQUNEbUcseUJBQXlCLEVBQUViLFlBQVksQ0FBQ3JGLG1CQUFvQjtVQUM1RG1HLHVCQUF1QixFQUFFZCxZQUFZLENBQUNuRSxpQkFBa0I7VUFDeERrRixtQkFBbUIsRUFBRWYsWUFBWSxDQUFDakYsYUFBYztVQUNoRGlHLHNCQUFzQixFQUFFaEIsWUFBWSxDQUFDaEYsZ0JBQWlCO1VBQ3REaUcsZ0JBQWdCLEVBQUVqQixZQUFZLENBQUMvRSxVQUFXO1VBQzFDaUcsMEJBQTBCLEVBQ3hCbEIsWUFBWSxDQUFDOUUsb0JBQ2Q7VUFDRGlHLGtCQUFrQixFQUFFbkIsWUFBWSxDQUFDN0UsWUFBYTtVQUM5Q2lHLHdCQUF3QixFQUFFcEIsWUFBWSxDQUFDNUUsa0JBQW1CO1VBQzFEaUcsMEJBQTBCLEVBQ3hCckIsWUFBWSxDQUFDM0Usb0JBQ2Q7VUFDRGlHLHNCQUFzQixFQUFFdEIsWUFBWSxDQUFDMUUsZ0JBQWlCO1VBQ3REaUcsb0JBQW9CLEVBQUV2QixZQUFZLENBQUN6RSxjQUFlO1VBQ2xEZ0UsUUFBUSxFQUFFSyxXQUFZO1VBQ3RCSCxzQkFBc0IsRUFBRUEsc0JBQXVCO1VBQy9DRCxPQUFPLEVBQUVnQjtRQUFZLENBQ3RCLENBQUM7TUFFTjtJQUVBLEtBQUssWUFBWTtNQUNmLElBQUksQ0FBQ1IsWUFBWSxDQUFDdEYsNEJBQTRCLEVBQUU7UUFDOUNnRCxlQUFNLENBQUNELEtBQUssQ0FDVixvRUFDRixDQUFDO1FBQ0QsT0FBTyxJQUFJO01BQ2I7TUFFQSxvQkFDRW5ILE1BQUEsQ0FBQVcsT0FBQSxDQUFBMEosYUFBQSxDQUFDOUosd0JBQUEsQ0FBQTJLLHNCQUFzQjtRQUNyQnZDLFlBQVksRUFBRUEsWUFBYTtRQUMzQkMsb0JBQW9CLEVBQUVBLG9CQUFxQjtRQUMzQ0Msb0JBQW9CLEVBQUVBLG9CQUFxQjtRQUMzQ0MseUJBQXlCLEVBQUVBLHlCQUEwQjtRQUNyREMsbUJBQW1CLEVBQUVBLG1CQUFvQjtRQUN6Q2xCLFlBQVksRUFBRStCLGVBQWdCO1FBQzlCVSxrQ0FBa0MsRUFDaENaLFlBQVksQ0FBQ3RGLDRCQUNkO1FBQ0RtRyx5QkFBeUIsRUFBRWIsWUFBWSxDQUFDckYsbUJBQW9CO1FBQzVEbUcsdUJBQXVCLEVBQUVkLFlBQVksQ0FBQ25FLGlCQUFrQjtRQUN4RGtGLG1CQUFtQixFQUFFZixZQUFZLENBQUNqRixhQUFjO1FBQ2hEaUcsc0JBQXNCLEVBQUVoQixZQUFZLENBQUNoRixnQkFBaUI7UUFDdERpRyxnQkFBZ0IsRUFBRWpCLFlBQVksQ0FBQy9FLFVBQVc7UUFDMUNpRywwQkFBMEIsRUFDeEJsQixZQUFZLENBQUM5RSxvQkFDZDtRQUNEaUcsa0JBQWtCLEVBQUVuQixZQUFZLENBQUM3RSxZQUFhO1FBQzlDaUcsd0JBQXdCLEVBQUVwQixZQUFZLENBQUM1RSxrQkFBbUI7UUFDMURpRywwQkFBMEIsRUFDeEJyQixZQUFZLENBQUMzRSxvQkFDZDtRQUNEaUcsc0JBQXNCLEVBQUV0QixZQUFZLENBQUMxRSxnQkFBaUI7UUFDdERpRyxvQkFBb0IsRUFBRXZCLFlBQVksQ0FBQ3pFLGNBQWU7UUFDbERnRSxRQUFRLEVBQUVLLFdBQVk7UUFDdEJILHNCQUFzQixFQUFFQSxzQkFBdUI7UUFDL0NELE9BQU8sRUFBRWdCO01BQVksQ0FDdEIsQ0FBQztJQUdOLEtBQUssYUFBYTtNQUFFO1FBQ2xCLElBQUksQ0FBQ04sZUFBZSxFQUFFO1VBQ3BCeEMsZUFBTSxDQUFDRCxLQUFLLENBQUMsMkNBQTJDLENBQUM7VUFDekQsT0FBTyxJQUFJO1FBQ2I7UUFFQSxNQUFNSSxZQUFZLEdBQUdMLHFCQUFxQixDQUFDLENBQUM7UUFDNUMsSUFBSSxDQUFDSyxZQUFZLEVBQUU0RCxzQkFBc0IsRUFBRTtVQUN6Qy9ELGVBQU0sQ0FBQ0QsS0FBSyxDQUNWLHdHQUNGLENBQUM7VUFDRCxPQUFPLElBQUk7UUFDYjtRQUVBLE1BQU1nRSxzQkFBc0IsR0FBRzVELFlBQVksQ0FBQzRELHNCQUFzQjtRQUNsRSxvQkFDRW5MLE1BQUEsQ0FBQVcsT0FBQSxDQUFBMEosYUFBQSxDQUFDYyxzQkFBc0I7VUFDckJ4QyxZQUFZLEVBQUVBLFlBQWE7VUFDM0JDLG9CQUFvQixFQUFFQSxvQkFBcUI7VUFDM0NDLG9CQUFvQixFQUFFQSxvQkFBcUI7VUFDM0NDLHlCQUF5QixFQUFFQSx5QkFBMEI7VUFDckRqQixZQUFZLEVBQUUrQixlQUFnQjtVQUM5QkMsY0FBYyxFQUFFQSxjQUFlO1VBQy9CRSx5QkFBeUIsRUFBRUEseUJBQTBCO1VBQ3JEckUsTUFBTSxFQUFFdUUsVUFBVztVQUNuQmhCLFFBQVEsRUFBRUssV0FBWTtVQUN0QkosT0FBTyxFQUFFZ0I7UUFBWSxDQUN0QixDQUFDO01BRU47SUFFQSxLQUFLLFVBQVU7TUFDYixJQUFJLENBQUNOLGVBQWUsRUFBRTtRQUNwQnhDLGVBQU0sQ0FBQ0QsS0FBSyxDQUFDLDJDQUEyQyxDQUFDO1FBQ3pELE9BQU8sSUFBSTtNQUNiO01BQ0Esb0JBQ0VuSCxNQUFBLENBQUFXLE9BQUEsQ0FBQTBKLGFBQUEsQ0FBQ2hLLHNCQUFBLENBQUErSyxvQkFBb0I7UUFDbkJ6QyxZQUFZLEVBQUVBLFlBQWE7UUFDM0JDLG9CQUFvQixFQUFFQSxvQkFBcUI7UUFDM0NDLG9CQUFvQixFQUFFQSxvQkFBcUI7UUFDM0NDLHlCQUF5QixFQUFFQSx5QkFBMEI7UUFDckRqQixZQUFZLEVBQUUrQixlQUFnQjtRQUM5QkMsY0FBYyxFQUFFQSxjQUFlO1FBQy9CRSx5QkFBeUIsRUFBRUEseUJBQTBCO1FBQ3JEckUsTUFBTSxFQUFFdUUsVUFBVztRQUNuQmhCLFFBQVEsRUFBRUssV0FBWTtRQUN0QkosT0FBTyxFQUFFZ0I7TUFBWSxDQUN0QixDQUFDO0lBR04sS0FBSyxXQUFXO01BQUU7UUFDaEIsTUFBTW1CLFlBQVksR0FBRzFCLGdCQUFnQixDQUFDekYsT0FBTztRQUM3QyxJQUFJLENBQUNtSCxZQUFZLEVBQUU7VUFDakJqRSxlQUFNLENBQUNELEtBQUssQ0FBQyxnREFBZ0QsQ0FBQztVQUM5RCxPQUFPLElBQUk7UUFDYjtRQUVBLG9CQUNFbkgsTUFBQSxDQUFBVyxPQUFBLENBQUEwSixhQUFBLENBQUMvSixxQkFBQSxDQUFBZ0wsbUJBQW1CO1VBQ2xCM0MsWUFBWSxFQUFFQSxZQUFhO1VBQzNCQyxvQkFBb0IsRUFBRUEsb0JBQXFCO1VBQzNDQyxvQkFBb0IsRUFBRUEsb0JBQXFCO1VBQzNDSSxRQUFRLEVBQUVLLFdBQVk7VUFDdEJKLE9BQU8sRUFBRWdCLFdBQVk7VUFDckJoRyxPQUFPLEVBQUVtSCxZQUFhO1VBQ3RCdkYsSUFBSSxFQUFFNkQsZ0JBQWdCLENBQUM3RCxJQUFLO1VBQzVCeUYsU0FBUyxFQUFFNUIsZ0JBQWdCLENBQUM1RDtRQUFNLENBQ25DLENBQUM7TUFFTjtJQUVBLEtBQUssV0FBVztNQUNkLG9CQUNFL0YsTUFBQSxDQUFBVyxPQUFBLENBQUEwSixhQUFBLENBQUNqSyxrQkFBQSxDQUFBb0wsZ0JBQW1CO1FBQ2xCN0MsWUFBWSxFQUFFQSxZQUFhO1FBQzNCQyxvQkFBb0IsRUFBRUEsb0JBQXFCO1FBQzNDQyxvQkFBb0IsRUFBRUEsb0JBQXFCO1FBQzNDSSxRQUFRLEVBQUVNO01BQWtCLENBQzdCLENBQUM7SUFHTixLQUFLLE1BQU07SUFDWDtNQUNFLElBQUlyQixrQkFBa0IsRUFBRTtRQUN0QmQsZUFBTSxDQUFDbUIsSUFBSSxDQUFDLGlDQUFpQyxDQUFDO01BQ2hEO01BQ0EsT0FBTyxJQUFJO0VBQ2Y7QUFDRixDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUZBOUIsT0FBQSxDQUFBaUMsdUJBQUEsR0FBQUEsdUJBQUE7QUFHTyxTQUFTK0MsMEJBQTBCQSxDQUN4Q3ZGLFNBQTRDLEVBQzVDO0VBQ0EsTUFBTTNCLE1BQU0sR0FBRzBCLDBCQUEwQixDQUFDQyxTQUFTLENBQUM7RUFDcEQsTUFBTXNELE1BQU0sR0FBRzVCLDZCQUE2QixDQUFDckQsTUFBTSxDQUFDO0VBQ3BELE1BQU15QixVQUFVLEdBQUdKLHVCQUF1QixDQUFDckIsTUFBTSxDQUFDO0VBRWxELE9BQU87SUFDTGlGLE1BQU07SUFDTmpGLE1BQU07SUFDTm1ILFlBQVksRUFBRTtNQUNaL0YsSUFBSSxFQUFFLElBQUFnRyxnREFBeUIsRUFBQyxDQUFDO01BQ2pDeEcsTUFBTSxFQUFFLElBQUF5RyxvREFBMkIsRUFBQyxDQUFDO01BQ3JDQyxTQUFTLEVBQUU7UUFDVEMsU0FBUyxFQUFFdEYsb0JBQW9CLENBQUMsQ0FBQztRQUNqQ3VGLFFBQVEsRUFBRWhFLHFCQUFRLENBQUNDO01BQ3JCLENBQUM7TUFDRGhDLFVBQVUsRUFBRTtRQUNWUCxPQUFPLEVBQUUsQ0FBQyxDQUFDTyxVQUFVLENBQUNILFlBQVk7UUFDbENtRyxHQUFHLEVBQUVoRyxVQUFVLENBQUM5QixPQUFPO1FBQ3ZCNEIsSUFBSSxFQUFFRSxVQUFVLENBQUNGLElBQUksSUFBSTtNQUMzQjtJQUNGLENBQUM7SUFDRG1HLGVBQWUsRUFBRUMsa0JBQWtCLENBQUMxQyxNQUFNLEVBQUVqRixNQUFNO0VBQ3BELENBQUM7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTMkgsa0JBQWtCQSxDQUN6QjFDLE1BT1UsRUFDVmpGLE1BQStCLEVBQ3JCO0VBQ1YsTUFBTTBILGVBQXlCLEdBQUcsRUFBRTtFQUVwQyxJQUFJekMsTUFBTSxLQUFLLE1BQU0sRUFBRTtJQUNyQnlDLGVBQWUsQ0FBQzNLLElBQUksQ0FBQyxpQ0FBaUMsQ0FBQztJQUV2RCxJQUFJLENBQUNpRCxNQUFNLENBQUNvQixJQUFJLEVBQUUwQyxNQUFNLElBQUk5RCxNQUFNLENBQUM0QixRQUFRLEtBQUssUUFBUSxFQUFFO01BQ3hEOEYsZUFBZSxDQUFDM0ssSUFBSSxDQUNsQixnRUFDRixDQUFDO0lBQ0g7SUFFQSxJQUFJeUcscUJBQVEsQ0FBQ0MsRUFBRSxLQUFLLEtBQUssRUFBRTtNQUN6QixJQUFJLENBQUMsSUFBQVMsNENBQXFCLEVBQUMsQ0FBQyxFQUFFO1FBQzVCd0QsZUFBZSxDQUFDM0ssSUFBSSxDQUFDLDRDQUE0QyxDQUFDO01BQ3BFO01BRUEsSUFBSSxDQUFDa0Ysb0JBQW9CLENBQUMsQ0FBQyxFQUFFO1FBQzNCeUYsZUFBZSxDQUFDM0ssSUFBSSxDQUFDLHlDQUF5QyxDQUFDO01BQ2pFO0lBQ0YsQ0FBQyxNQUFNO01BQ0wySyxlQUFlLENBQUMzSyxJQUFJLENBQ2xCLGtFQUNGLENBQUM7SUFDSDtFQUNGO0VBRUEsSUFBSWtJLE1BQU0sS0FBSyxXQUFXLEVBQUU7SUFDMUJ5QyxlQUFlLENBQUMzSyxJQUFJLENBQUMsK0NBQStDLENBQUM7SUFDckUySyxlQUFlLENBQUMzSyxJQUFJLENBQUMsd0NBQXdDLENBQUM7RUFDaEU7RUFFQSxJQUFJa0ksTUFBTSxLQUFLLFVBQVUsRUFBRTtJQUN6QnlDLGVBQWUsQ0FBQzNLLElBQUksQ0FBQyw4Q0FBOEMsQ0FBQztFQUN0RTtFQUVBLElBQUlrSSxNQUFNLEtBQUssYUFBYSxFQUFFO0lBQzVCeUMsZUFBZSxDQUFDM0ssSUFBSSxDQUFDLHdDQUF3QyxDQUFDO0VBQ2hFO0VBRUEsSUFBSWtJLE1BQU0sS0FBSyxZQUFZLEVBQUU7SUFDM0J5QyxlQUFlLENBQUMzSyxJQUFJLENBQUMsMkNBQTJDLENBQUM7RUFDbkU7RUFFQSxJQUFJa0ksTUFBTSxLQUFLLGVBQWUsRUFBRTtJQUM5QnlDLGVBQWUsQ0FBQzNLLElBQUksQ0FBQyw4Q0FBOEMsQ0FBQztFQUN0RTtFQUVBLElBQUlrSSxNQUFNLEtBQUssV0FBVyxFQUFFO0lBQzFCeUMsZUFBZSxDQUFDM0ssSUFBSSxDQUFDLGdEQUFnRCxDQUFDO0lBQ3RFLElBQUksQ0FBQ2lELE1BQU0sQ0FBQ3lCLFVBQVUsRUFBRTlCLE9BQU8sRUFBRTtNQUMvQitILGVBQWUsQ0FBQzNLLElBQUksQ0FBQywrQ0FBK0MsQ0FBQztJQUN2RTtFQUNGO0VBRUEsT0FBTzJLLGVBQWU7QUFDeEI7O0FBRUE7QUFRQTtBQUFBLElBQUFFLFFBQUEsR0FBQTFGLE9BQUEsQ0FBQTlGLE9BQUEsR0FDZStILHVCQUF1QiIsImlnbm9yZUxpc3QiOltdfQ==