nodeconfigloder 1.0.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,396 @@
1
+ #!/usr/bin/env node
2
+ (function webpackUniversalModuleDefinition(root, factory) {
3
+ if(typeof exports === 'object' && typeof module === 'object')
4
+ module.exports = factory();
5
+ else if(typeof define === 'function' && define.amd)
6
+ define([], factory);
7
+ else if(typeof exports === 'object')
8
+ exports["configloder"] = factory();
9
+ else
10
+ root["configloder"] = factory();
11
+ })(global, () => {
12
+ return /******/ (() => { // webpackBootstrap
13
+ /******/ "use strict";
14
+ /******/ var __webpack_modules__ = ({
15
+
16
+ /***/ "crypto"
17
+ /*!*************************!*\
18
+ !*** external "crypto" ***!
19
+ \*************************/
20
+ (module) {
21
+
22
+ module.exports = require("crypto");
23
+
24
+ /***/ },
25
+
26
+ /***/ "events"
27
+ /*!*************************!*\
28
+ !*** external "events" ***!
29
+ \*************************/
30
+ (module) {
31
+
32
+ module.exports = require("events");
33
+
34
+ /***/ }
35
+
36
+ /******/ });
37
+ /************************************************************************/
38
+ /******/ // The module cache
39
+ /******/ var __webpack_module_cache__ = {};
40
+ /******/
41
+ /******/ // The require function
42
+ /******/ function __webpack_require__(moduleId) {
43
+ /******/ // Check if module is in cache
44
+ /******/ var cachedModule = __webpack_module_cache__[moduleId];
45
+ /******/ if (cachedModule !== undefined) {
46
+ /******/ return cachedModule.exports;
47
+ /******/ }
48
+ /******/ // Check if module exists (development only)
49
+ /******/ if (__webpack_modules__[moduleId] === undefined) {
50
+ /******/ var e = new Error("Cannot find module '" + moduleId + "'");
51
+ /******/ e.code = 'MODULE_NOT_FOUND';
52
+ /******/ throw e;
53
+ /******/ }
54
+ /******/ // Create a new module (and put it into the cache)
55
+ /******/ var module = __webpack_module_cache__[moduleId] = {
56
+ /******/ // no module.id needed
57
+ /******/ // no module.loaded needed
58
+ /******/ exports: {}
59
+ /******/ };
60
+ /******/
61
+ /******/ // Execute the module function
62
+ /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
63
+ /******/
64
+ /******/ // Return the exports of the module
65
+ /******/ return module.exports;
66
+ /******/ }
67
+ /******/
68
+ /************************************************************************/
69
+ /******/ /* webpack/runtime/compat get default export */
70
+ /******/ (() => {
71
+ /******/ // getDefaultExport function for compatibility with non-harmony modules
72
+ /******/ __webpack_require__.n = (module) => {
73
+ /******/ var getter = module && module.__esModule ?
74
+ /******/ () => (module['default']) :
75
+ /******/ () => (module);
76
+ /******/ __webpack_require__.d(getter, { a: getter });
77
+ /******/ return getter;
78
+ /******/ };
79
+ /******/ })();
80
+ /******/
81
+ /******/ /* webpack/runtime/define property getters */
82
+ /******/ (() => {
83
+ /******/ // define getter functions for harmony exports
84
+ /******/ __webpack_require__.d = (exports, definition) => {
85
+ /******/ for(var key in definition) {
86
+ /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
87
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
88
+ /******/ }
89
+ /******/ }
90
+ /******/ };
91
+ /******/ })();
92
+ /******/
93
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
94
+ /******/ (() => {
95
+ /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
96
+ /******/ })();
97
+ /******/
98
+ /******/ /* webpack/runtime/make namespace object */
99
+ /******/ (() => {
100
+ /******/ // define __esModule on exports
101
+ /******/ __webpack_require__.r = (exports) => {
102
+ /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
103
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
104
+ /******/ }
105
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
106
+ /******/ };
107
+ /******/ })();
108
+ /******/
109
+ /************************************************************************/
110
+ var __webpack_exports__ = {};
111
+ // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
112
+ (() => {
113
+ /*!****************************************!*\
114
+ !*** ./configloder/FindDifferences.ts ***!
115
+ \****************************************/
116
+ __webpack_require__.r(__webpack_exports__);
117
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
118
+ /* harmony export */ FindDifferences: () => (/* binding */ FindDifferences),
119
+ /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
120
+ /* harmony export */ });
121
+ /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! events */ "events");
122
+ /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(events__WEBPACK_IMPORTED_MODULE_0__);
123
+ /* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! crypto */ "crypto");
124
+ /* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_1__);
125
+
126
+
127
+ /**
128
+ * 処理名: 差分検出エンジン
129
+ *
130
+ * 処理概要:
131
+ * ハッシュツリーを使用して2つのJSON構造の差分を効率的に検出する。
132
+ * EventEmitterを継承し、差分を'difference'イベントで通知
133
+ *
134
+ * 実装理由:
135
+ * 大規模な設定ファイルの変更検出において、全体比較ではなく
136
+ * ハッシュツリーの活用で計算量を最小化するため
137
+ */
138
+ class FindDifferences extends events__WEBPACK_IMPORTED_MODULE_0__.EventEmitter {
139
+ /**
140
+ * 処理名: コンストラクタ
141
+ *
142
+ * 処理概要:
143
+ * FindDifferencesインスタンスを初期化し、前回のハッシュツリーを空の状態で保持
144
+ *
145
+ * 実装理由:
146
+ * EventEmitterの初期化と、差分検出のための状態を保持するため
147
+ */
148
+ constructor() {
149
+ super();
150
+ this.previousHashTree = { __hash: '' };
151
+ }
152
+ /**
153
+ * 処理名: ハッシュ値計算
154
+ *
155
+ * 処理概要:
156
+ * 与えられた値のSHA256ハッシュを計算する
157
+ *
158
+ * 実装理由:
159
+ * オブジェクトの内容をコンパクトに表現し、変更検出の基盤とするため
160
+ * @param {string} value ハッシュ対象の値
161
+ * @returns {string} ハッシュ文字列
162
+ * @private
163
+ */
164
+ calculateHash(value) {
165
+ return crypto__WEBPACK_IMPORTED_MODULE_1__.createHash('sha256').update(value).digest('hex');
166
+ }
167
+ /**
168
+ * 処理名: ハッシュツリー構築
169
+ *
170
+ * 処理概要:
171
+ * JSONデータから再帰的にハッシュツリーを構築する。
172
+ * 各ノードには__hashキーで当該ノード以下の変更を示すハッシュを保持
173
+ *
174
+ * 実装理由:
175
+ * 差分検出時に__hashの比較だけで下層の探索を短縮するため
176
+ * @param {unknown} data 構築対象のデータ
177
+ * @returns {HashTreeNode} ハッシュツリー
178
+ * @private
179
+ */
180
+ buildHashTree(data) {
181
+ if (typeof data !== 'object' || data === null) {
182
+ // プリミティブ値の場合、そのままハッシュ化
183
+ return {
184
+ __hash: this.calculateHash(JSON.stringify(data)),
185
+ };
186
+ }
187
+ if (Array.isArray(data)) {
188
+ // 配列の場合、各要素のハッシュ値を結合してハッシュ化
189
+ const childHashes = data.map((item) => this.buildHashTree(item));
190
+ const combinedHash = this.calculateHash(childHashes.map((h) => h.__hash).join(''));
191
+ return {
192
+ __hash: combinedHash,
193
+ ...Object.fromEntries(childHashes.map((h, i) => [i.toString(), h])),
194
+ };
195
+ }
196
+ if (typeof data === 'object' && data.type) {
197
+ // type値を持っているobjectの場合、そのままハッシュ化
198
+ return {
199
+ __hash: this.calculateHash(JSON.stringify(data)),
200
+ };
201
+ }
202
+ // オブジェクトの場合、キーと値をソートしてハッシュ化
203
+ const childHashes = Object.keys(data)
204
+ .sort()
205
+ .reduce((tree, key) => {
206
+ tree[key] = this.buildHashTree(data[key]);
207
+ return tree;
208
+ }, {});
209
+ const combinedHash = this.calculateHash(Object.entries(childHashes)
210
+ .map(([key, value]) => `${key}:${value.__hash}`)
211
+ .join(''));
212
+ return { __hash: combinedHash, ...childHashes };
213
+ }
214
+ /**
215
+ * 処理名: 削除・更新キーの処理
216
+ * @param {HashTreeNode} hashTree ハッシュツリー
217
+ * @param {Record<string, unknown>} jsonData JSON データ
218
+ * @param {string} path パス
219
+ * @returns {void}
220
+ * @private
221
+ */
222
+ processExistingKeys(hashTree, jsonData, path) {
223
+ for (const key in hashTree) {
224
+ if (key === '__hash')
225
+ continue;
226
+ const currentPath = path ? `${path}.${key}` : key;
227
+ if (!(key in jsonData)) {
228
+ this.emit('difference', {
229
+ type: 'removed',
230
+ path: currentPath,
231
+ });
232
+ delete hashTree[key];
233
+ }
234
+ else {
235
+ this.processKeyValue(hashTree, jsonData, key, currentPath);
236
+ }
237
+ }
238
+ }
239
+ /**
240
+ * 処理名: キー値の処理
241
+ * @param {HashTreeNode} hashTree ハッシュツリー
242
+ * @param {Record<string, unknown>} jsonData JSON データ
243
+ * @param {string} key キー
244
+ * @param {string} currentPath 現在のパス
245
+ * @returns {void}
246
+ * @private
247
+ */
248
+ processKeyValue(hashTree, jsonData, key, currentPath) {
249
+ const jsonValue = jsonData[key];
250
+ if (typeof jsonValue === 'object' && jsonValue !== null) {
251
+ this.processObjectValue(hashTree, jsonValue, key, currentPath);
252
+ }
253
+ else {
254
+ this.processPrimitiveValue(hashTree, jsonValue, key, currentPath);
255
+ }
256
+ }
257
+ /**
258
+ * 処理名: オブジェクト値の処理
259
+ * @param {HashTreeNode} hashTree ハッシュツリー
260
+ * @param {Record<string, unknown>} jsonValue JSON 値
261
+ * @param {string} key キー
262
+ * @param {string} currentPath 現在のパス
263
+ * @returns {void}
264
+ * @private
265
+ */
266
+ processObjectValue(hashTree, jsonValue, key, currentPath) {
267
+ if (jsonValue.type) {
268
+ const newPrimitiveHash = this.calculateHash(JSON.stringify(jsonValue));
269
+ if (hashTree[key].__hash !== newPrimitiveHash) {
270
+ this.emit('difference', {
271
+ type: 'modified',
272
+ path: currentPath,
273
+ });
274
+ hashTree[key].__hash = newPrimitiveHash;
275
+ }
276
+ }
277
+ else {
278
+ if (!hashTree[key] || typeof hashTree[key] !== 'object') {
279
+ hashTree[key] = { __hash: '' };
280
+ }
281
+ this.findDifferencesAndUpdate(hashTree[key], jsonValue, currentPath);
282
+ }
283
+ }
284
+ /**
285
+ * 処理名: プリミティブ値の処理
286
+ * @param {HashTreeNode} hashTree ハッシュツリー
287
+ * @param {unknown} jsonValue JSON 値
288
+ * @param {string} key キー
289
+ * @param {string} currentPath 現在のパス
290
+ * @returns {void}
291
+ * @private
292
+ */
293
+ processPrimitiveValue(hashTree, jsonValue, key, currentPath) {
294
+ const newPrimitiveHash = this.calculateHash(JSON.stringify(jsonValue));
295
+ if (hashTree[key].__hash !== newPrimitiveHash) {
296
+ this.emit('difference', {
297
+ type: 'modified',
298
+ path: currentPath,
299
+ });
300
+ hashTree[key].__hash = newPrimitiveHash;
301
+ }
302
+ }
303
+ /**
304
+ * 処理名: 追加されたキーの処理
305
+ * @param {HashTreeNode} hashTree ハッシュツリー
306
+ * @param {Record<string, unknown>} jsonData JSON データ
307
+ * @param {string} path パス
308
+ * @returns {void}
309
+ * @private
310
+ */
311
+ processAddedKeys(hashTree, jsonData, path) {
312
+ for (const key in jsonData) {
313
+ const currentPath = path ? `${path}.${key}` : key;
314
+ if (!(key in hashTree)) {
315
+ this.emit('difference', {
316
+ type: 'added',
317
+ path: currentPath,
318
+ });
319
+ const jsonValue = jsonData[key];
320
+ hashTree[key] =
321
+ typeof jsonValue === 'object' && jsonValue !== null
322
+ ? this.buildHashTree(jsonValue)
323
+ : { __hash: this.calculateHash(JSON.stringify(jsonValue)) };
324
+ }
325
+ }
326
+ }
327
+ /**
328
+ * 処理名: 差分検出と更新
329
+ *
330
+ * 処理概要:
331
+ * 前回のハッシュツリーと新しいJSONデータを比較し、
332
+ * 追加・削除・更新されたパスを'difference'イベントで通知
333
+ *
334
+ * 実装理由:
335
+ * ハッシュ値の比較で不要な再帰を避け、変更箇所のみを検出するため
336
+ * @param {HashTreeNode} hashTree ハッシュツリー
337
+ * @param {unknown} jsonData JSON データ
338
+ * @param {string} path パス
339
+ * @returns {void}
340
+ * @private
341
+ */
342
+ findDifferencesAndUpdate(hashTree, jsonData, path = '') {
343
+ const newHash = this.calculateHash(JSON.stringify(jsonData));
344
+ if (hashTree.__hash === newHash) {
345
+ return;
346
+ }
347
+ const data = jsonData;
348
+ this.processExistingKeys(hashTree, data, path);
349
+ this.processAddedKeys(hashTree, data, path);
350
+ hashTree.__hash = this.calculateHash(Object.entries(hashTree)
351
+ .filter(([key]) => key !== '__hash')
352
+ .map(([key, value]) => `${key}:${value.__hash}`)
353
+ .join(''));
354
+ }
355
+ /**
356
+ * 処理名: ハッシュツリー初期化
357
+ *
358
+ * 処理概要:
359
+ * 初回読み込み時にハッシュツリーを構築し、前回状態として保持
360
+ *
361
+ * 実装理由:
362
+ * 次回の差分検出の基準となるベースラインを作成するため
363
+ * @param {unknown} jsonData 初回のJSONデータ
364
+ * @returns {HashTreeNode} 構築されたハッシュツリー
365
+ */
366
+ initialize(jsonData) {
367
+ return (this.previousHashTree = this.buildHashTree(jsonData)); // 初期ハッシュツリー構築
368
+ }
369
+ /**
370
+ * 処理名: 差分検出
371
+ *
372
+ * 処理概要:
373
+ * 新しいJSONデータと前回のハッシュツリーを比較し、
374
+ * 差分を検出して'difference'イベントで通知。
375
+ * 内部的にハッシュツリーを更新して次回検出に備える
376
+ *
377
+ * 実装理由:
378
+ * ファイル監視やリアルタイム変更検出のため、継続的に差分を検出するため
379
+ * @param {unknown} jsonData 新しいJSONデータ
380
+ * @returns {HashTreeNode} 更新上のハッシュツリー
381
+ */
382
+ detectChanges(jsonData) {
383
+ this.findDifferencesAndUpdate(this.previousHashTree, jsonData);
384
+ return this.previousHashTree;
385
+ }
386
+ }
387
+ /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FindDifferences);
388
+
389
+ })();
390
+
391
+ __webpack_exports__ = __webpack_exports__["default"];
392
+ /******/ return __webpack_exports__;
393
+ /******/ })()
394
+ ;
395
+ });
396
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmluZGRpZmZlcmVuY2VzLmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELE87Ozs7Ozs7Ozs7QUNWQSxtQzs7Ozs7Ozs7OztBQ0FBLG1DOzs7Ozs7VUNBQTtVQUNBOztVQUVBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBOztVQUVBO1VBQ0E7O1VBRUE7VUFDQTtVQUNBOzs7OztXQzVCQTtXQUNBO1dBQ0E7V0FDQTtXQUNBO1dBQ0EsaUNBQWlDLFdBQVc7V0FDNUM7V0FDQSxFOzs7OztXQ1BBO1dBQ0E7V0FDQTtXQUNBO1dBQ0EseUNBQXlDLHdDQUF3QztXQUNqRjtXQUNBO1dBQ0EsRTs7Ozs7V0NQQSx3Rjs7Ozs7V0NBQTtXQUNBO1dBQ0E7V0FDQSx1REFBdUQsaUJBQWlCO1dBQ3hFO1dBQ0EsZ0RBQWdELGFBQWE7V0FDN0QsRTs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ05zQztBQUNMO0FBa0JqQzs7Ozs7Ozs7OztHQVVHO0FBQ0ksTUFBTSxlQUFnQixTQUFRLGdEQUFZO0lBRy9DOzs7Ozs7OztPQVFHO0lBQ0g7UUFDRSxLQUFLLEVBQUUsQ0FBQztRQUNSLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUN6QyxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7O09BV0c7SUFDSyxhQUFhLENBQUMsS0FBYTtRQUNqQyxPQUFPLDhDQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakUsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7T0FZRztJQUNLLGFBQWEsQ0FBQyxJQUFhO1FBQ2pDLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLElBQUksS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUM5Qyx1QkFBdUI7WUFDdkIsT0FBTztnQkFDTCxNQUFNLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO2FBQ2pELENBQUM7UUFDSixDQUFDO1FBRUQsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDeEIsNEJBQTRCO1lBQzVCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNqRSxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNuRixPQUFPO2dCQUNMLE1BQU0sRUFBRSxZQUFZO2dCQUNwQixHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDcEQsQ0FBQztRQUNwQixDQUFDO1FBRUQsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLElBQUssSUFBZ0MsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUN2RSxpQ0FBaUM7WUFDakMsT0FBTztnQkFDTCxNQUFNLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO2FBQ2pELENBQUM7UUFDSixDQUFDO1FBRUQsNEJBQTRCO1FBQzVCLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO2FBQ2xDLElBQUksRUFBRTthQUNOLE1BQU0sQ0FBQyxDQUFDLElBQWtDLEVBQUUsR0FBRyxFQUFFLEVBQUU7WUFDbEQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUUsSUFBZ0MsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3ZFLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRVQsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FDckMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUM7YUFDeEIsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsR0FBRyxJQUFJLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQzthQUMvQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQ1osQ0FBQztRQUNGLE9BQU8sRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLEdBQUcsV0FBVyxFQUFFLENBQUM7SUFDbEQsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSyxtQkFBbUIsQ0FDekIsUUFBc0IsRUFDdEIsUUFBaUMsRUFDakMsSUFBWTtRQUVaLEtBQUssTUFBTSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7WUFDM0IsSUFBSSxHQUFHLEtBQUssUUFBUTtnQkFBRSxTQUFTO1lBQy9CLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUVsRCxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksUUFBUSxDQUFDLEVBQUUsQ0FBQztnQkFDdkIsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUU7b0JBQ3RCLElBQUksRUFBRSxTQUFTO29CQUNmLElBQUksRUFBRSxXQUFXO2lCQUNDLENBQUMsQ0FBQztnQkFDdEIsT0FBTyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdkIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxlQUFlLENBQUMsUUFBUSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDN0QsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSyxlQUFlLENBQ3JCLFFBQXNCLEVBQ3RCLFFBQWlDLEVBQ2pDLEdBQVcsRUFDWCxXQUFtQjtRQUVuQixNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDaEMsSUFBSSxPQUFPLFNBQVMsS0FBSyxRQUFRLElBQUksU0FBUyxLQUFLLElBQUksRUFBRSxDQUFDO1lBQ3hELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsU0FBb0MsRUFBRSxHQUFHLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDNUYsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMscUJBQXFCLENBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDcEUsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNLLGtCQUFrQixDQUN4QixRQUFzQixFQUN0QixTQUFrQyxFQUNsQyxHQUFXLEVBQ1gsV0FBbUI7UUFFbkIsSUFBSSxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbkIsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztZQUN2RSxJQUFLLFFBQVEsQ0FBQyxHQUFHLENBQWtCLENBQUMsTUFBTSxLQUFLLGdCQUFnQixFQUFFLENBQUM7Z0JBQ2hFLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFO29CQUN0QixJQUFJLEVBQUUsVUFBVTtvQkFDaEIsSUFBSSxFQUFFLFdBQVc7aUJBQ0MsQ0FBQyxDQUFDO2dCQUNyQixRQUFRLENBQUMsR0FBRyxDQUFrQixDQUFDLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQztZQUM1RCxDQUFDO1FBQ0gsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLE9BQU8sUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLFFBQVEsRUFBRSxDQUFDO2dCQUN4RCxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUM7WUFDakMsQ0FBQztZQUNELElBQUksQ0FBQyx3QkFBd0IsQ0FDM0IsUUFBUSxDQUFDLEdBQUcsQ0FBaUIsRUFDN0IsU0FBUyxFQUNULFdBQVcsQ0FDWixDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNLLHFCQUFxQixDQUMzQixRQUFzQixFQUN0QixTQUFrQixFQUNsQixHQUFXLEVBQ1gsV0FBbUI7UUFFbkIsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUN2RSxJQUFLLFFBQVEsQ0FBQyxHQUFHLENBQWtCLENBQUMsTUFBTSxLQUFLLGdCQUFnQixFQUFFLENBQUM7WUFDaEUsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUU7Z0JBQ3RCLElBQUksRUFBRSxVQUFVO2dCQUNoQixJQUFJLEVBQUUsV0FBVzthQUNDLENBQUMsQ0FBQztZQUNyQixRQUFRLENBQUMsR0FBRyxDQUFrQixDQUFDLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQztRQUM1RCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSyxnQkFBZ0IsQ0FDdEIsUUFBc0IsRUFDdEIsUUFBaUMsRUFDakMsSUFBWTtRQUVaLEtBQUssTUFBTSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7WUFDM0IsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO1lBQ2xELElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUN2QixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRTtvQkFDdEIsSUFBSSxFQUFFLE9BQU87b0JBQ2IsSUFBSSxFQUFFLFdBQVc7aUJBQ0MsQ0FBQyxDQUFDO2dCQUN0QixNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2hDLFFBQVEsQ0FBQyxHQUFHLENBQUM7b0JBQ1gsT0FBTyxTQUFTLEtBQUssUUFBUSxJQUFJLFNBQVMsS0FBSyxJQUFJO3dCQUNqRCxDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUM7d0JBQy9CLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ2xFLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7OztPQWNHO0lBQ0ssd0JBQXdCLENBQzlCLFFBQXNCLEVBQ3RCLFFBQWlCLEVBQ2pCLElBQUksR0FBRyxFQUFFO1FBRVQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDN0QsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQ2hDLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsUUFBbUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsbUJBQW1CLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMvQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUUzQyxRQUFvQyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUMvRCxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQzthQUNyQixNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEtBQUssUUFBUSxDQUFDO2FBQ25DLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEdBQUcsSUFBSyxLQUFzQixDQUFDLE1BQU0sRUFBRSxDQUFDO2FBQ2pFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FDWixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSCxVQUFVLENBQUMsUUFBaUI7UUFDMUIsT0FBTyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxjQUFjO0lBQy9FLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7O09BWUc7SUFDSCxhQUFhLENBQUMsUUFBaUI7UUFDN0IsSUFBSSxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUMvRCxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztJQUMvQixDQUFDO0NBQ0Y7QUFFRCxpRUFBZSxlQUFlLEVBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9jb25maWdsb2Rlci93ZWJwYWNrL3VuaXZlcnNhbE1vZHVsZURlZmluaXRpb24iLCJ3ZWJwYWNrOi8vY29uZmlnbG9kZXIvZXh0ZXJuYWwgbm9kZS1jb21tb25qcyBcImNyeXB0b1wiIiwid2VicGFjazovL2NvbmZpZ2xvZGVyL2V4dGVybmFsIG5vZGUtY29tbW9uanMgXCJldmVudHNcIiIsIndlYnBhY2s6Ly9jb25maWdsb2Rlci93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9jb25maWdsb2Rlci93ZWJwYWNrL3J1bnRpbWUvY29tcGF0IGdldCBkZWZhdWx0IGV4cG9ydCIsIndlYnBhY2s6Ly9jb25maWdsb2Rlci93ZWJwYWNrL3J1bnRpbWUvZGVmaW5lIHByb3BlcnR5IGdldHRlcnMiLCJ3ZWJwYWNrOi8vY29uZmlnbG9kZXIvd2VicGFjay9ydW50aW1lL2hhc093blByb3BlcnR5IHNob3J0aGFuZCIsIndlYnBhY2s6Ly9jb25maWdsb2Rlci93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL2NvbmZpZ2xvZGVyLy4vY29uZmlnbG9kZXIvRmluZERpZmZlcmVuY2VzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiB3ZWJwYWNrVW5pdmVyc2FsTW9kdWxlRGVmaW5pdGlvbihyb290LCBmYWN0b3J5KSB7XG5cdGlmKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0Jylcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKTtcblx0ZWxzZSBpZih0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpXG5cdFx0ZGVmaW5lKFtdLCBmYWN0b3J5KTtcblx0ZWxzZSBpZih0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcpXG5cdFx0ZXhwb3J0c1tcImNvbmZpZ2xvZGVyXCJdID0gZmFjdG9yeSgpO1xuXHRlbHNlXG5cdFx0cm9vdFtcImNvbmZpZ2xvZGVyXCJdID0gZmFjdG9yeSgpO1xufSkoZ2xvYmFsLCAoKSA9PiB7XG5yZXR1cm4gIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiY3J5cHRvXCIpOyIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcImV2ZW50c1wiKTsiLCIvLyBUaGUgbW9kdWxlIGNhY2hlXG52YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307XG5cbi8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG5mdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuXHR2YXIgY2FjaGVkTW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXTtcblx0aWYgKGNhY2hlZE1vZHVsZSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0cmV0dXJuIGNhY2hlZE1vZHVsZS5leHBvcnRzO1xuXHR9XG5cdC8vIENoZWNrIGlmIG1vZHVsZSBleGlzdHMgKGRldmVsb3BtZW50IG9ubHkpXG5cdGlmIChfX3dlYnBhY2tfbW9kdWxlc19fW21vZHVsZUlkXSA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0dmFyIGUgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbW9kdWxlSWQgKyBcIidcIik7XG5cdFx0ZS5jb2RlID0gJ01PRFVMRV9OT1RfRk9VTkQnO1xuXHRcdHRocm93IGU7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0Ly8gbm8gbW9kdWxlLmlkIG5lZWRlZFxuXHRcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0obW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCIvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuX193ZWJwYWNrX3JlcXVpcmVfXy5uID0gKG1vZHVsZSkgPT4ge1xuXHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cblx0XHQoKSA9PiAobW9kdWxlWydkZWZhdWx0J10pIDpcblx0XHQoKSA9PiAobW9kdWxlKTtcblx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgeyBhOiBnZXR0ZXIgfSk7XG5cdHJldHVybiBnZXR0ZXI7XG59OyIsIi8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb25zIGZvciBoYXJtb255IGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7XG5cdGZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7XG5cdFx0fVxuXHR9XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18ubyA9IChvYmosIHByb3ApID0+IChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkiLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgeyBFdmVudEVtaXR0ZXIgfSBmcm9tICdldmVudHMnO1xyXG5pbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnY3J5cHRvJztcclxuXHJcbi8qKlxyXG4gKiDjg4/jg4Pjgrfjg6Xjg4Tjg6rjg7zjga7jg47jg7zjg4nlnotcclxuICovXHJcbmludGVyZmFjZSBIYXNoVHJlZU5vZGUge1xyXG4gIF9faGFzaDogc3RyaW5nO1xyXG4gIFtrZXk6IHN0cmluZ106IHVua25vd247XHJcbn1cclxuXHJcbi8qKlxyXG4gKiDlt67liIbjgqTjg5njg7Pjg4jjga7lnotcclxuICovXHJcbmludGVyZmFjZSBEaWZmZXJlbmNlRXZlbnQge1xyXG4gIHR5cGU6ICdhZGRlZCcgfCAncmVtb3ZlZCcgfCAnbW9kaWZpZWQnO1xyXG4gIHBhdGg6IHN0cmluZztcclxufVxyXG5cclxuLyoqXHJcbiAqIOWHpueQhuWQjTog5beu5YiG5qSc5Ye644Ko44Oz44K444OzXHJcbiAqXHJcbiAqIOWHpueQhuamguimgTpcclxuICog44OP44OD44K344Ol44OE44Oq44O844KS5L2/55So44GX44GmMuOBpOOBrkpTT07mp4vpgKDjga7lt67liIbjgpLlirnnjofnmoTjgavmpJzlh7rjgZnjgovjgIJcclxuICogRXZlbnRFbWl0dGVy44KS57aZ5om/44GX44CB5beu5YiG44KSJ2RpZmZlcmVuY2Un44Kk44OZ44Oz44OI44Gn6YCa55+lXHJcbiAqXHJcbiAqIOWun+ijheeQhueUsTpcclxuICog5aSn6KaP5qih44Gq6Kit5a6a44OV44Kh44Kk44Or44Gu5aSJ5pu05qSc5Ye644Gr44GK44GE44Gm44CB5YWo5L2T5q+U6LyD44Gn44Gv44Gq44GPXHJcbiAqIOODj+ODg+OCt+ODpeODhOODquODvOOBrua0u+eUqOOBp+ioiOeul+mHj+OCkuacgOWwj+WMluOBmeOCi+OBn+OCgVxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEZpbmREaWZmZXJlbmNlcyBleHRlbmRzIEV2ZW50RW1pdHRlciB7XHJcbiAgcHJpdmF0ZSBwcmV2aW91c0hhc2hUcmVlOiBIYXNoVHJlZU5vZGU7XHJcblxyXG4gIC8qKlxyXG4gICAqIOWHpueQhuWQjTog44Kz44Oz44K544OI44Op44Kv44K/XHJcbiAgICpcclxuICAgKiDlh6bnkIbmpoLopoE6XHJcbiAgICogRmluZERpZmZlcmVuY2Vz44Kk44Oz44K544K/44Oz44K544KS5Yid5pyf5YyW44GX44CB5YmN5Zue44Gu44OP44OD44K344Ol44OE44Oq44O844KS56m644Gu54q25oWL44Gn5L+d5oyBXHJcbiAgICpcclxuICAgKiDlrp/oo4XnkIbnlLE6XHJcbiAgICogRXZlbnRFbWl0dGVy44Gu5Yid5pyf5YyW44Go44CB5beu5YiG5qSc5Ye644Gu44Gf44KB44Gu54q25oWL44KS5L+d5oyB44GZ44KL44Gf44KBXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IoKSB7XHJcbiAgICBzdXBlcigpO1xyXG4gICAgdGhpcy5wcmV2aW91c0hhc2hUcmVlID0geyBfX2hhc2g6ICcnIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiDlh6bnkIblkI06IOODj+ODg+OCt+ODpeWApOioiOeul1xyXG4gICAqXHJcbiAgICog5Yem55CG5qaC6KaBOlxyXG4gICAqIOS4juOBiOOCieOCjOOBn+WApOOBrlNIQTI1NuODj+ODg+OCt+ODpeOCkuioiOeul+OBmeOCi1xyXG4gICAqXHJcbiAgICog5a6f6KOF55CG55SxOlxyXG4gICAqIOOCquODluOCuOOCp+OCr+ODiOOBruWGheWuueOCkuOCs+ODs+ODkeOCr+ODiOOBq+ihqOePvuOBl+OAgeWkieabtOaknOWHuuOBruWfuuebpOOBqOOBmeOCi+OBn+OCgVxyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSDjg4/jg4Pjgrfjg6Xlr77osaHjga7lgKRcclxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSDjg4/jg4Pjgrfjg6XmloflrZfliJdcclxuICAgKiBAcHJpdmF0ZVxyXG4gICAqL1xyXG4gIHByaXZhdGUgY2FsY3VsYXRlSGFzaCh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIHJldHVybiBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKHZhbHVlKS5kaWdlc3QoJ2hleCcpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICog5Yem55CG5ZCNOiDjg4/jg4Pjgrfjg6Xjg4Tjg6rjg7zmp4vnr4lcclxuICAgKlxyXG4gICAqIOWHpueQhuamguimgTpcclxuICAgKiBKU09O44OH44O844K/44GL44KJ5YaN5biw55qE44Gr44OP44OD44K344Ol44OE44Oq44O844KS5qeL56+J44GZ44KL44CCXHJcbiAgICog5ZCE44OO44O844OJ44Gr44GvX19oYXNo44Kt44O844Gn5b2T6Kmy44OO44O844OJ5Lul5LiL44Gu5aSJ5pu044KS56S644GZ44OP44OD44K344Ol44KS5L+d5oyBXHJcbiAgICpcclxuICAgKiDlrp/oo4XnkIbnlLE6XHJcbiAgICog5beu5YiG5qSc5Ye65pmC44GrX19oYXNo44Gu5q+U6LyD44Gg44GR44Gn5LiL5bGk44Gu5o6i57Si44KS55+t57iu44GZ44KL44Gf44KBXHJcbiAgICogQHBhcmFtIHt1bmtub3dufSBkYXRhIOani+evieWvvuixoeOBruODh+ODvOOCv1xyXG4gICAqIEByZXR1cm5zIHtIYXNoVHJlZU5vZGV9IOODj+ODg+OCt+ODpeODhOODquODvFxyXG4gICAqIEBwcml2YXRlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZEhhc2hUcmVlKGRhdGE6IHVua25vd24pOiBIYXNoVHJlZU5vZGUge1xyXG4gICAgaWYgKHR5cGVvZiBkYXRhICE9PSAnb2JqZWN0JyB8fCBkYXRhID09PSBudWxsKSB7XHJcbiAgICAgIC8vIOODl+ODquODn+ODhuOCo+ODluWApOOBruWgtOWQiOOAgeOBneOBruOBvuOBvuODj+ODg+OCt+ODpeWMllxyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIF9faGFzaDogdGhpcy5jYWxjdWxhdGVIYXNoKEpTT04uc3RyaW5naWZ5KGRhdGEpKSxcclxuICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkge1xyXG4gICAgICAvLyDphY3liJfjga7loLTlkIjjgIHlkITopoHntKDjga7jg4/jg4Pjgrfjg6XlgKTjgpLntZDlkIjjgZfjgabjg4/jg4Pjgrfjg6XljJZcclxuICAgICAgY29uc3QgY2hpbGRIYXNoZXMgPSBkYXRhLm1hcCgoaXRlbSkgPT4gdGhpcy5idWlsZEhhc2hUcmVlKGl0ZW0pKTtcclxuICAgICAgY29uc3QgY29tYmluZWRIYXNoID0gdGhpcy5jYWxjdWxhdGVIYXNoKGNoaWxkSGFzaGVzLm1hcCgoaCkgPT4gaC5fX2hhc2gpLmpvaW4oJycpKTtcclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBfX2hhc2g6IGNvbWJpbmVkSGFzaCxcclxuICAgICAgICAuLi5PYmplY3QuZnJvbUVudHJpZXMoY2hpbGRIYXNoZXMubWFwKChoLCBpKSA9PiBbaS50b1N0cmluZygpLCBoXSkpLFxyXG4gICAgICB9IGFzIEhhc2hUcmVlTm9kZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZW9mIGRhdGEgPT09ICdvYmplY3QnICYmIChkYXRhIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KS50eXBlKSB7XHJcbiAgICAgIC8vIHR5cGXlgKTjgpLmjIHjgaPjgabjgYTjgotvYmplY3Tjga7loLTlkIjjgIHjgZ3jga7jgb7jgb7jg4/jg4Pjgrfjg6XljJZcclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBfX2hhc2g6IHRoaXMuY2FsY3VsYXRlSGFzaChKU09OLnN0cmluZ2lmeShkYXRhKSksXHJcbiAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLy8g44Kq44OW44K444Kn44Kv44OI44Gu5aC05ZCI44CB44Kt44O844Go5YCk44KS44K944O844OI44GX44Gm44OP44OD44K344Ol5YyWXHJcbiAgICBjb25zdCBjaGlsZEhhc2hlcyA9IE9iamVjdC5rZXlzKGRhdGEpXHJcbiAgICAgIC5zb3J0KClcclxuICAgICAgLnJlZHVjZSgodHJlZTogUmVjb3JkPHN0cmluZywgSGFzaFRyZWVOb2RlPiwga2V5KSA9PiB7XHJcbiAgICAgICAgdHJlZVtrZXldID0gdGhpcy5idWlsZEhhc2hUcmVlKChkYXRhIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtrZXldKTtcclxuICAgICAgICByZXR1cm4gdHJlZTtcclxuICAgICAgfSwge30pO1xyXG5cclxuICAgIGNvbnN0IGNvbWJpbmVkSGFzaCA9IHRoaXMuY2FsY3VsYXRlSGFzaChcclxuICAgICAgT2JqZWN0LmVudHJpZXMoY2hpbGRIYXNoZXMpXHJcbiAgICAgICAgLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBgJHtrZXl9OiR7dmFsdWUuX19oYXNofWApXHJcbiAgICAgICAgLmpvaW4oJycpXHJcbiAgICApO1xyXG4gICAgcmV0dXJuIHsgX19oYXNoOiBjb21iaW5lZEhhc2gsIC4uLmNoaWxkSGFzaGVzIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiDlh6bnkIblkI06IOWJiumZpOODu+abtOaWsOOCreODvOOBruWHpueQhlxyXG4gICAqIEBwYXJhbSB7SGFzaFRyZWVOb2RlfSBoYXNoVHJlZSDjg4/jg4Pjgrfjg6Xjg4Tjg6rjg7xcclxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIHVua25vd24+fSBqc29uRGF0YSBKU09OIOODh+ODvOOCv1xyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIOODkeOCuVxyXG4gICAqIEByZXR1cm5zIHt2b2lkfVxyXG4gICAqIEBwcml2YXRlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBwcm9jZXNzRXhpc3RpbmdLZXlzKFxyXG4gICAgaGFzaFRyZWU6IEhhc2hUcmVlTm9kZSxcclxuICAgIGpzb25EYXRhOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcclxuICAgIHBhdGg6IHN0cmluZ1xyXG4gICk6IHZvaWQge1xyXG4gICAgZm9yIChjb25zdCBrZXkgaW4gaGFzaFRyZWUpIHtcclxuICAgICAgaWYgKGtleSA9PT0gJ19faGFzaCcpIGNvbnRpbnVlO1xyXG4gICAgICBjb25zdCBjdXJyZW50UGF0aCA9IHBhdGggPyBgJHtwYXRofS4ke2tleX1gIDoga2V5O1xyXG5cclxuICAgICAgaWYgKCEoa2V5IGluIGpzb25EYXRhKSkge1xyXG4gICAgICAgIHRoaXMuZW1pdCgnZGlmZmVyZW5jZScsIHtcclxuICAgICAgICAgIHR5cGU6ICdyZW1vdmVkJyxcclxuICAgICAgICAgIHBhdGg6IGN1cnJlbnRQYXRoLFxyXG4gICAgICAgIH0gYXMgRGlmZmVyZW5jZUV2ZW50KTtcclxuICAgICAgICBkZWxldGUgaGFzaFRyZWVba2V5XTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLnByb2Nlc3NLZXlWYWx1ZShoYXNoVHJlZSwganNvbkRhdGEsIGtleSwgY3VycmVudFBhdGgpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiDlh6bnkIblkI06IOOCreODvOWApOOBruWHpueQhlxyXG4gICAqIEBwYXJhbSB7SGFzaFRyZWVOb2RlfSBoYXNoVHJlZSDjg4/jg4Pjgrfjg6Xjg4Tjg6rjg7xcclxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIHVua25vd24+fSBqc29uRGF0YSBKU09OIOODh+ODvOOCv1xyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkg44Kt44O8XHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGN1cnJlbnRQYXRoIOePvuWcqOOBruODkeOCuVxyXG4gICAqIEByZXR1cm5zIHt2b2lkfVxyXG4gICAqIEBwcml2YXRlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBwcm9jZXNzS2V5VmFsdWUoXHJcbiAgICBoYXNoVHJlZTogSGFzaFRyZWVOb2RlLFxyXG4gICAganNvbkRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxyXG4gICAga2V5OiBzdHJpbmcsXHJcbiAgICBjdXJyZW50UGF0aDogc3RyaW5nXHJcbiAgKTogdm9pZCB7XHJcbiAgICBjb25zdCBqc29uVmFsdWUgPSBqc29uRGF0YVtrZXldO1xyXG4gICAgaWYgKHR5cGVvZiBqc29uVmFsdWUgPT09ICdvYmplY3QnICYmIGpzb25WYWx1ZSAhPT0gbnVsbCkge1xyXG4gICAgICB0aGlzLnByb2Nlc3NPYmplY3RWYWx1ZShoYXNoVHJlZSwganNvblZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBrZXksIGN1cnJlbnRQYXRoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMucHJvY2Vzc1ByaW1pdGl2ZVZhbHVlKGhhc2hUcmVlLCBqc29uVmFsdWUsIGtleSwgY3VycmVudFBhdGgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICog5Yem55CG5ZCNOiDjgqrjg5bjgrjjgqfjgq/jg4jlgKTjga7lh6bnkIZcclxuICAgKiBAcGFyYW0ge0hhc2hUcmVlTm9kZX0gaGFzaFRyZWUg44OP44OD44K344Ol44OE44Oq44O8XHJcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0ganNvblZhbHVlIEpTT04g5YCkXHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSDjgq3jg7xcclxuICAgKiBAcGFyYW0ge3N0cmluZ30gY3VycmVudFBhdGgg54++5Zyo44Gu44OR44K5XHJcbiAgICogQHJldHVybnMge3ZvaWR9XHJcbiAgICogQHByaXZhdGVcclxuICAgKi9cclxuICBwcml2YXRlIHByb2Nlc3NPYmplY3RWYWx1ZShcclxuICAgIGhhc2hUcmVlOiBIYXNoVHJlZU5vZGUsXHJcbiAgICBqc29uVmFsdWU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxyXG4gICAga2V5OiBzdHJpbmcsXHJcbiAgICBjdXJyZW50UGF0aDogc3RyaW5nXHJcbiAgKTogdm9pZCB7XHJcbiAgICBpZiAoanNvblZhbHVlLnR5cGUpIHtcclxuICAgICAgY29uc3QgbmV3UHJpbWl0aXZlSGFzaCA9IHRoaXMuY2FsY3VsYXRlSGFzaChKU09OLnN0cmluZ2lmeShqc29uVmFsdWUpKTtcclxuICAgICAgaWYgKChoYXNoVHJlZVtrZXldIGFzIEhhc2hUcmVlTm9kZSkuX19oYXNoICE9PSBuZXdQcmltaXRpdmVIYXNoKSB7XHJcbiAgICAgICAgdGhpcy5lbWl0KCdkaWZmZXJlbmNlJywge1xyXG4gICAgICAgICAgdHlwZTogJ21vZGlmaWVkJyxcclxuICAgICAgICAgIHBhdGg6IGN1cnJlbnRQYXRoLFxyXG4gICAgICAgIH0gYXMgRGlmZmVyZW5jZUV2ZW50KTtcclxuICAgICAgICAoaGFzaFRyZWVba2V5XSBhcyBIYXNoVHJlZU5vZGUpLl9faGFzaCA9IG5ld1ByaW1pdGl2ZUhhc2g7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICghaGFzaFRyZWVba2V5XSB8fCB0eXBlb2YgaGFzaFRyZWVba2V5XSAhPT0gJ29iamVjdCcpIHtcclxuICAgICAgICBoYXNoVHJlZVtrZXldID0geyBfX2hhc2g6ICcnIH07XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5maW5kRGlmZmVyZW5jZXNBbmRVcGRhdGUoXHJcbiAgICAgICAgaGFzaFRyZWVba2V5XSBhcyBIYXNoVHJlZU5vZGUsXHJcbiAgICAgICAganNvblZhbHVlLFxyXG4gICAgICAgIGN1cnJlbnRQYXRoXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiDlh6bnkIblkI06IOODl+ODquODn+ODhuOCo+ODluWApOOBruWHpueQhlxyXG4gICAqIEBwYXJhbSB7SGFzaFRyZWVOb2RlfSBoYXNoVHJlZSDjg4/jg4Pjgrfjg6Xjg4Tjg6rjg7xcclxuICAgKiBAcGFyYW0ge3Vua25vd259IGpzb25WYWx1ZSBKU09OIOWApFxyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkg44Kt44O8XHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGN1cnJlbnRQYXRoIOePvuWcqOOBruODkeOCuVxyXG4gICAqIEByZXR1cm5zIHt2b2lkfVxyXG4gICAqIEBwcml2YXRlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBwcm9jZXNzUHJpbWl0aXZlVmFsdWUoXHJcbiAgICBoYXNoVHJlZTogSGFzaFRyZWVOb2RlLFxyXG4gICAganNvblZhbHVlOiB1bmtub3duLFxyXG4gICAga2V5OiBzdHJpbmcsXHJcbiAgICBjdXJyZW50UGF0aDogc3RyaW5nXHJcbiAgKTogdm9pZCB7XHJcbiAgICBjb25zdCBuZXdQcmltaXRpdmVIYXNoID0gdGhpcy5jYWxjdWxhdGVIYXNoKEpTT04uc3RyaW5naWZ5KGpzb25WYWx1ZSkpO1xyXG4gICAgaWYgKChoYXNoVHJlZVtrZXldIGFzIEhhc2hUcmVlTm9kZSkuX19oYXNoICE9PSBuZXdQcmltaXRpdmVIYXNoKSB7XHJcbiAgICAgIHRoaXMuZW1pdCgnZGlmZmVyZW5jZScsIHtcclxuICAgICAgICB0eXBlOiAnbW9kaWZpZWQnLFxyXG4gICAgICAgIHBhdGg6IGN1cnJlbnRQYXRoLFxyXG4gICAgICB9IGFzIERpZmZlcmVuY2VFdmVudCk7XHJcbiAgICAgIChoYXNoVHJlZVtrZXldIGFzIEhhc2hUcmVlTm9kZSkuX19oYXNoID0gbmV3UHJpbWl0aXZlSGFzaDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIOWHpueQhuWQjTog6L+95Yqg44GV44KM44Gf44Kt44O844Gu5Yem55CGXHJcbiAgICogQHBhcmFtIHtIYXNoVHJlZU5vZGV9IGhhc2hUcmVlIOODj+ODg+OCt+ODpeODhOODquODvFxyXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59IGpzb25EYXRhIEpTT04g44OH44O844K/XHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBhdGgg44OR44K5XHJcbiAgICogQHJldHVybnMge3ZvaWR9XHJcbiAgICogQHByaXZhdGVcclxuICAgKi9cclxuICBwcml2YXRlIHByb2Nlc3NBZGRlZEtleXMoXHJcbiAgICBoYXNoVHJlZTogSGFzaFRyZWVOb2RlLFxyXG4gICAganNvbkRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxyXG4gICAgcGF0aDogc3RyaW5nXHJcbiAgKTogdm9pZCB7XHJcbiAgICBmb3IgKGNvbnN0IGtleSBpbiBqc29uRGF0YSkge1xyXG4gICAgICBjb25zdCBjdXJyZW50UGF0aCA9IHBhdGggPyBgJHtwYXRofS4ke2tleX1gIDoga2V5O1xyXG4gICAgICBpZiAoIShrZXkgaW4gaGFzaFRyZWUpKSB7XHJcbiAgICAgICAgdGhpcy5lbWl0KCdkaWZmZXJlbmNlJywge1xyXG4gICAgICAgICAgdHlwZTogJ2FkZGVkJyxcclxuICAgICAgICAgIHBhdGg6IGN1cnJlbnRQYXRoLFxyXG4gICAgICAgIH0gYXMgRGlmZmVyZW5jZUV2ZW50KTtcclxuICAgICAgICBjb25zdCBqc29uVmFsdWUgPSBqc29uRGF0YVtrZXldO1xyXG4gICAgICAgIGhhc2hUcmVlW2tleV0gPVxyXG4gICAgICAgICAgdHlwZW9mIGpzb25WYWx1ZSA9PT0gJ29iamVjdCcgJiYganNvblZhbHVlICE9PSBudWxsXHJcbiAgICAgICAgICAgID8gdGhpcy5idWlsZEhhc2hUcmVlKGpzb25WYWx1ZSlcclxuICAgICAgICAgICAgOiB7IF9faGFzaDogdGhpcy5jYWxjdWxhdGVIYXNoKEpTT04uc3RyaW5naWZ5KGpzb25WYWx1ZSkpIH07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIOWHpueQhuWQjTog5beu5YiG5qSc5Ye644Go5pu05pawXHJcbiAgICpcclxuICAgKiDlh6bnkIbmpoLopoE6XHJcbiAgICog5YmN5Zue44Gu44OP44OD44K344Ol44OE44Oq44O844Go5paw44GX44GESlNPTuODh+ODvOOCv+OCkuavlOi8g+OBl+OAgVxyXG4gICAqIOi/veWKoOODu+WJiumZpOODu+abtOaWsOOBleOCjOOBn+ODkeOCueOCkidkaWZmZXJlbmNlJ+OCpOODmeODs+ODiOOBp+mAmuefpVxyXG4gICAqXHJcbiAgICog5a6f6KOF55CG55SxOlxyXG4gICAqIOODj+ODg+OCt+ODpeWApOOBruavlOi8g+OBp+S4jeimgeOBquWGjeW4sOOCkumBv+OBkeOAgeWkieabtOeuh+aJgOOBruOBv+OCkuaknOWHuuOBmeOCi+OBn+OCgVxyXG4gICAqIEBwYXJhbSB7SGFzaFRyZWVOb2RlfSBoYXNoVHJlZSDjg4/jg4Pjgrfjg6Xjg4Tjg6rjg7xcclxuICAgKiBAcGFyYW0ge3Vua25vd259IGpzb25EYXRhIEpTT04g44OH44O844K/XHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBhdGgg44OR44K5XHJcbiAgICogQHJldHVybnMge3ZvaWR9XHJcbiAgICogQHByaXZhdGVcclxuICAgKi9cclxuICBwcml2YXRlIGZpbmREaWZmZXJlbmNlc0FuZFVwZGF0ZShcclxuICAgIGhhc2hUcmVlOiBIYXNoVHJlZU5vZGUsXHJcbiAgICBqc29uRGF0YTogdW5rbm93bixcclxuICAgIHBhdGggPSAnJ1xyXG4gICk6IHZvaWQge1xyXG4gICAgY29uc3QgbmV3SGFzaCA9IHRoaXMuY2FsY3VsYXRlSGFzaChKU09OLnN0cmluZ2lmeShqc29uRGF0YSkpO1xyXG4gICAgaWYgKGhhc2hUcmVlLl9faGFzaCA9PT0gbmV3SGFzaCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgZGF0YSA9IGpzb25EYXRhIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xyXG4gICAgdGhpcy5wcm9jZXNzRXhpc3RpbmdLZXlzKGhhc2hUcmVlLCBkYXRhLCBwYXRoKTtcclxuICAgIHRoaXMucHJvY2Vzc0FkZGVkS2V5cyhoYXNoVHJlZSwgZGF0YSwgcGF0aCk7XHJcblxyXG4gICAgKGhhc2hUcmVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KS5fX2hhc2ggPSB0aGlzLmNhbGN1bGF0ZUhhc2goXHJcbiAgICAgIE9iamVjdC5lbnRyaWVzKGhhc2hUcmVlKVxyXG4gICAgICAgIC5maWx0ZXIoKFtrZXldKSA9PiBrZXkgIT09ICdfX2hhc2gnKVxyXG4gICAgICAgIC5tYXAoKFtrZXksIHZhbHVlXSkgPT4gYCR7a2V5fTokeyh2YWx1ZSBhcyBIYXNoVHJlZU5vZGUpLl9faGFzaH1gKVxyXG4gICAgICAgIC5qb2luKCcnKVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIOWHpueQhuWQjTog44OP44OD44K344Ol44OE44Oq44O85Yid5pyf5YyWXHJcbiAgICpcclxuICAgKiDlh6bnkIbmpoLopoE6XHJcbiAgICog5Yid5Zue6Kqt44G/6L6844G/5pmC44Gr44OP44OD44K344Ol44OE44Oq44O844KS5qeL56+J44GX44CB5YmN5Zue54q25oWL44Go44GX44Gm5L+d5oyBXHJcbiAgICpcclxuICAgKiDlrp/oo4XnkIbnlLE6XHJcbiAgICog5qyh5Zue44Gu5beu5YiG5qSc5Ye644Gu5Z+65rqW44Go44Gq44KL44OZ44O844K544Op44Kk44Oz44KS5L2c5oiQ44GZ44KL44Gf44KBXHJcbiAgICogQHBhcmFtIHt1bmtub3dufSBqc29uRGF0YSDliJ3lm57jga5KU09O44OH44O844K/XHJcbiAgICogQHJldHVybnMge0hhc2hUcmVlTm9kZX0g5qeL56+J44GV44KM44Gf44OP44OD44K344Ol44OE44Oq44O8XHJcbiAgICovXHJcbiAgaW5pdGlhbGl6ZShqc29uRGF0YTogdW5rbm93bik6IEhhc2hUcmVlTm9kZSB7XHJcbiAgICByZXR1cm4gKHRoaXMucHJldmlvdXNIYXNoVHJlZSA9IHRoaXMuYnVpbGRIYXNoVHJlZShqc29uRGF0YSkpOyAvLyDliJ3mnJ/jg4/jg4Pjgrfjg6Xjg4Tjg6rjg7zmp4vnr4lcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIOWHpueQhuWQjTog5beu5YiG5qSc5Ye6XHJcbiAgICpcclxuICAgKiDlh6bnkIbmpoLopoE6XHJcbiAgICog5paw44GX44GESlNPTuODh+ODvOOCv+OBqOWJjeWbnuOBruODj+ODg+OCt+ODpeODhOODquODvOOCkuavlOi8g+OBl+OAgVxyXG4gICAqIOW3ruWIhuOCkuaknOWHuuOBl+OBpidkaWZmZXJlbmNlJ+OCpOODmeODs+ODiOOBp+mAmuefpeOAglxyXG4gICAqIOWGhemDqOeahOOBq+ODj+ODg+OCt+ODpeODhOODquODvOOCkuabtOaWsOOBl+OBpuasoeWbnuaknOWHuuOBq+WCmeOBiOOCi1xyXG4gICAqXHJcbiAgICog5a6f6KOF55CG55SxOlxyXG4gICAqIOODleOCoeOCpOODq+ebo+imluOChOODquOCouODq+OCv+OCpOODoOWkieabtOaknOWHuuOBruOBn+OCgeOAgee2mee2mueahOOBq+W3ruWIhuOCkuaknOWHuuOBmeOCi+OBn+OCgVxyXG4gICAqIEBwYXJhbSB7dW5rbm93bn0ganNvbkRhdGEg5paw44GX44GESlNPTuODh+ODvOOCv1xyXG4gICAqIEByZXR1cm5zIHtIYXNoVHJlZU5vZGV9IOabtOaWsOS4iuOBruODj+ODg+OCt+ODpeODhOODquODvFxyXG4gICAqL1xyXG4gIGRldGVjdENoYW5nZXMoanNvbkRhdGE6IHVua25vd24pOiBIYXNoVHJlZU5vZGUge1xyXG4gICAgdGhpcy5maW5kRGlmZmVyZW5jZXNBbmRVcGRhdGUodGhpcy5wcmV2aW91c0hhc2hUcmVlLCBqc29uRGF0YSk7XHJcbiAgICByZXR1cm4gdGhpcy5wcmV2aW91c0hhc2hUcmVlO1xyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGRlZmF1bHQgRmluZERpZmZlcmVuY2VzO1xyXG4iXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbXSwic291cmNlUm9vdCI6IiJ9