sonamu 0.8.25 → 0.8.26

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.
@@ -6,6 +6,9 @@ import { Sonamu } from "../api/sonamu.js";
6
6
  /** contract/ 디렉터리 절대 경로 반환 (apiRootPath 기준) */ function getContractDir() {
7
7
  return path.join(Sonamu.apiRootPath, "..", "..", "contract");
8
8
  }
9
+ /** 프로젝트 루트 경로 반환 */ function getProjectRoot() {
10
+ return path.join(Sonamu.apiRootPath, "..", "..");
11
+ }
9
12
  /** 경로가 contract/ 디렉터리 내부인지 검증 */ function assertInsideContractDir(filePath) {
10
13
  const contractDir = getContractDir();
11
14
  const resolved = path.resolve(contractDir, filePath);
@@ -14,8 +17,8 @@ import { Sonamu } from "../api/sonamu.js";
14
17
  }
15
18
  }
16
19
  /** 파일명에서 CddFileType 판별 */ function detectFileType(fileName) {
17
- if (fileName.endsWith(".contract.json")) return "contract";
18
- if (fileName.endsWith(".spec.json")) return "spec";
20
+ if (fileName.endsWith(".contract.md")) return "contract";
21
+ if (fileName.endsWith(".rules.json")) return "rules";
19
22
  return undefined;
20
23
  }
21
24
  /** 디렉터리를 재귀 탐색하여 CddTreeNode 트리를 생성 */ function scanDirectory(dirPath, relativeTo) {
@@ -27,16 +30,19 @@ import { Sonamu } from "../api/sonamu.js";
27
30
  const fullPath = path.join(dirPath, entry.name);
28
31
  const relPath = path.relative(relativeTo, fullPath);
29
32
  if (entry.isDirectory()) {
33
+ if (entry.name === "rules") continue;
30
34
  const children = scanDirectory(fullPath, relativeTo);
31
- nodes.push({
32
- name: entry.name,
33
- path: relPath,
34
- type: "directory",
35
- children
36
- });
35
+ if (children.length > 0) {
36
+ nodes.push({
37
+ name: entry.name,
38
+ path: relPath,
39
+ type: "directory",
40
+ children
41
+ });
42
+ }
37
43
  } else if (entry.isFile()) {
38
44
  const fileType = detectFileType(entry.name);
39
- if (fileType) {
45
+ if (fileType && fileType !== "rules") {
40
46
  nodes.push({
41
47
  name: entry.name,
42
48
  path: relPath,
@@ -62,32 +68,21 @@ import { Sonamu } from "../api/sonamu.js";
62
68
  tree
63
69
  };
64
70
  }
65
- /** schema ID로 schema 파일을 찾아 반환 */ function resolveSchema(schemaId) {
66
- const contractDir = getContractDir();
67
- const schemaPath = path.join(contractDir, "schemas", `${schemaId}.schema.json`);
68
- if (!fs.existsSync(schemaPath)) return null;
69
- const raw = fs.readFileSync(schemaPath, "utf-8");
70
- return JSON.parse(raw);
71
- }
72
- /** JSON 파일의 전체 내용을 읽어 schema와 함께 envelope로 반환 */ export function readContent(filePath) {
71
+ /** 파일 내용을 읽어 반환 (contract.md markdown 원문, rules.json → JSON 문자열) */ export function readContent(filePath) {
73
72
  assertInsideContractDir(filePath);
74
73
  const contractDir = getContractDir();
75
74
  const absPath = path.resolve(contractDir, filePath);
76
75
  if (!fs.existsSync(absPath)) {
77
76
  throw new Error(`파일을 찾을 수 없습니다: ${filePath}`);
78
77
  }
79
- const raw = fs.readFileSync(absPath, "utf-8");
80
- const document = JSON.parse(raw);
78
+ const content = fs.readFileSync(absPath, "utf-8");
81
79
  const fileType = detectFileType(path.basename(filePath));
82
- const schemaId = typeof document.schema === "string" ? document.schema : null;
83
- const schema = schemaId ? resolveSchema(schemaId) : null;
84
80
  return {
85
- document,
86
- schema,
81
+ content,
87
82
  fileType: fileType ?? "contract"
88
83
  };
89
84
  }
90
- /** JSON 파일을 외부 에디터로 직접 편집 */ export async function editContent(filePath) {
85
+ /** 파일을 외부 에디터로 직접 편집 */ export async function editContent(filePath) {
91
86
  assertInsideContractDir(filePath);
92
87
  const contractDir = getContractDir();
93
88
  const absPath = path.resolve(contractDir, filePath);
@@ -161,243 +156,272 @@ import { Sonamu } from "../api/sonamu.js";
161
156
  });
162
157
  });
163
158
  }
164
- /* ========================================================================
165
- * Schema 관리 API
166
- * ======================================================================== */ /** contract/schemas/ 디렉터리 내 .schema.json 파일 경로 목록 반환 */ function scanSchemaFiles() {
167
- const schemasDir = path.join(getContractDir(), "schemas");
168
- if (!fs.existsSync(schemasDir)) return [];
169
- return fs.readdirSync(schemasDir, {
170
- withFileTypes: true
171
- }).filter((e)=>e.isFile() && e.name.endsWith(".schema.json")).map((e)=>({
172
- absPath: path.join(schemasDir, e.name),
173
- relPath: `schemas/${e.name}`,
174
- fileName: e.name
175
- }));
159
+ /** 소스 파일을 외부 에디터로 열기 (대기하지 않음) */ export function openSourceFile(filePath) {
160
+ const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(Sonamu.apiRootPath, filePath);
161
+ if (!fs.existsSync(absPath)) {
162
+ throw new Error(`파일을 찾을 수 없습니다: ${filePath}`);
163
+ }
164
+ const editor = resolveEditorCli({
165
+ wait: false
166
+ });
167
+ const child = spawn(editor.bin, [
168
+ ...editor.args,
169
+ absPath
170
+ ], {
171
+ stdio: "ignore",
172
+ detached: true
173
+ });
174
+ child.unref();
176
175
  }
177
- /** 특정 schemaId를 참조하는 contract/spec 문서들을 재귀 수집 */ function collectSchemaReferences(schemaId, dirPath, relativeTo) {
178
- if (!fs.existsSync(dirPath)) return [];
179
- const refs = [];
180
- const entries = fs.readdirSync(dirPath, {
176
+ /* ========================================================================
177
+ * Rules API
178
+ * ======================================================================== */ /** contract/rules/ 디렉터리 내 .rules.json 파일 목록 반환 */ export function listRules() {
179
+ const contractDir = getContractDir();
180
+ const rulesDir = path.join(contractDir, "rules");
181
+ if (!fs.existsSync(rulesDir)) return {
182
+ rules: []
183
+ };
184
+ const entries = fs.readdirSync(rulesDir, {
181
185
  withFileTypes: true
182
186
  });
187
+ const rules = [];
183
188
  for (const entry of entries){
184
- const fullPath = path.join(dirPath, entry.name);
185
- if (entry.isDirectory()) {
186
- if (entry.name === "schemas") continue;
187
- refs.push(...collectSchemaReferences(schemaId, fullPath, relativeTo));
188
- } else if (entry.isFile()) {
189
- const fileType = detectFileType(entry.name);
190
- if (!fileType) continue;
191
- try {
192
- const raw = fs.readFileSync(fullPath, "utf-8");
193
- const doc = JSON.parse(raw);
194
- if (doc.schema === schemaId) {
195
- refs.push({
196
- path: path.relative(relativeTo, fullPath),
197
- fileType,
198
- name: entry.name
199
- });
200
- }
201
- } catch {
202
- // JSON 파싱 실패 시 무시
203
- }
204
- }
205
- }
206
- return refs;
207
- }
208
- /** schema 파일명에서 기대되는 id 추출 */ function expectedSchemaId(fileName) {
209
- return fileName.replace(/\.schema\.json$/, "");
210
- }
211
- /** schemas/ 하위 경로가 contract/schemas/ 내부인지 검증 */ function assertInsideSchemaDir(schemaKey) {
212
- const schemasDir = path.join(getContractDir(), "schemas");
213
- const resolved = path.resolve(schemasDir, `${schemaKey}.schema.json`);
214
- if (!resolved.startsWith(schemasDir + path.sep) && resolved !== schemasDir) {
215
- throw new Error(`유효하지 않은 스키마 키입니다: ${schemaKey}`);
216
- }
217
- }
218
- /** schema 목록 반환 */ export function listSchemas() {
219
- const contractDir = getContractDir();
220
- const files = scanSchemaFiles();
221
- const schemas = [];
222
- for (const file of files){
223
- const key = expectedSchemaId(file.fileName);
189
+ if (!entry.isFile() || !entry.name.endsWith(".rules.json")) continue;
190
+ const key = entry.name.replace(/\.rules\.json$/, "");
191
+ const relPath = `rules/${entry.name}`;
192
+ const absPath = path.join(rulesDir, entry.name);
224
193
  try {
225
- const raw = fs.readFileSync(file.absPath, "utf-8");
226
- const schema = JSON.parse(raw);
227
- const refs = collectSchemaReferences(schema.id, contractDir, contractDir);
228
- schemas.push({
194
+ const raw = fs.readFileSync(absPath, "utf-8");
195
+ const doc = JSON.parse(raw);
196
+ rules.push({
229
197
  key,
230
- id: schema.id,
231
- path: file.relPath,
232
- type: schema.type,
233
- fieldCount: schema.fields.length,
234
- referenceCount: refs.length,
235
- hasIdMismatch: schema.id !== key
198
+ path: relPath,
199
+ description: typeof doc.description === "string" ? doc.description : "",
200
+ ruleCount: Array.isArray(doc.rules) ? doc.rules.length : 0
236
201
  });
237
202
  } catch (err) {
238
- schemas.push({
203
+ rules.push({
239
204
  key,
240
- id: key,
241
- path: file.relPath,
242
- type: "contract",
243
- fieldCount: 0,
244
- referenceCount: 0,
245
- hasIdMismatch: false,
205
+ path: relPath,
206
+ description: "",
207
+ ruleCount: 0,
246
208
  parseError: err instanceof Error ? err.message : String(err)
247
209
  });
248
210
  }
249
211
  }
250
212
  return {
251
- schemas
213
+ rules
252
214
  };
253
215
  }
254
- /** schema 상세 반환 (파일명 기반 key로 조회) */ export function readSchema(schemaKey) {
255
- assertInsideSchemaDir(schemaKey);
216
+ /** rules 파일 상세 반환 */ export function readRule(ruleKey) {
256
217
  const contractDir = getContractDir();
257
- const absPath = path.join(contractDir, "schemas", `${schemaKey}.schema.json`);
218
+ const absPath = path.join(contractDir, "rules", `${ruleKey}.rules.json`);
258
219
  if (!fs.existsSync(absPath)) {
259
- throw new Error(`스키마를 찾을 수 없습니다: ${schemaKey}`);
220
+ throw new Error(`Rules 파일을 찾을 수 없습니다: ${ruleKey}`);
260
221
  }
261
222
  const raw = fs.readFileSync(absPath, "utf-8");
262
- const schema = JSON.parse(raw);
263
- const relPath = path.relative(contractDir, absPath);
264
- const references = collectSchemaReferences(schema.id, contractDir, contractDir);
223
+ const doc = JSON.parse(raw);
265
224
  return {
266
- key: schemaKey,
267
- path: relPath,
268
- schema,
269
- references,
270
- hasIdMismatch: schema.id !== schemaKey
225
+ key: ruleKey,
226
+ path: `rules/${ruleKey}.rules.json`,
227
+ description: typeof doc.description === "string" ? doc.description : "",
228
+ rules: Array.isArray(doc.rules) ? doc.rules : []
271
229
  };
272
230
  }
273
- /** schema 파일을 외부 에디터로 편집 (파일명 기반 key로 조회) */ export async function editSchema(schemaKey) {
274
- assertInsideSchemaDir(schemaKey);
231
+ /** rules 파일에 규칙 추가 */ export function addRule(req) {
275
232
  const contractDir = getContractDir();
276
- const absPath = path.join(contractDir, "schemas", `${schemaKey}.schema.json`);
233
+ const rulesDir = path.join(contractDir, "rules");
234
+ const absPath = path.join(rulesDir, `${req.ruleKey}.rules.json`);
277
235
  if (!fs.existsSync(absPath)) {
278
- throw new Error(`스키마를 찾을 수 없습니다: ${schemaKey}`);
236
+ throw new Error(`Rules 파일을 찾을 수 없습니다: ${req.ruleKey}`);
279
237
  }
280
- const editor = resolveEditorCli();
281
- await runEditor(editor, absPath);
238
+ const raw = fs.readFileSync(absPath, "utf-8");
239
+ const doc = JSON.parse(raw);
240
+ const rules = Array.isArray(doc.rules) ? doc.rules : [];
241
+ const nextId = generateNextRuleId(rules);
242
+ const newEntry = {
243
+ id: nextId,
244
+ when: req.when,
245
+ instruction: req.instruction
246
+ };
247
+ if (req.examples && req.examples.length > 0) {
248
+ newEntry.examples = req.examples;
249
+ }
250
+ rules.push(newEntry);
251
+ doc.rules = rules;
252
+ fs.writeFileSync(absPath, `${JSON.stringify(doc, null, 2)}\n`, "utf-8");
282
253
  return {
283
- success: true,
284
- schemaKey
254
+ key: req.ruleKey,
255
+ path: `rules/${req.ruleKey}.rules.json`,
256
+ description: typeof doc.description === "string" ? doc.description : "",
257
+ rules
285
258
  };
286
259
  }
287
- const VALID_SPEC_STATUSES = new Set([
288
- "draft",
289
- "specifying",
290
- "implementing",
291
- "validating",
292
- "done"
293
- ]);
294
- /** 모든 contract/spec 문서를 스캔하여 대시보드 통계를 반환 */ export function getDashboard() {
295
- const contractDir = getContractDir();
296
- if (!fs.existsSync(contractDir)) {
297
- return {
298
- exists: false,
299
- stats: {
300
- totalContracts: 0,
301
- totalSpecs: 0,
302
- statusDistribution: {
303
- draft: 0,
304
- specifying: 0,
305
- implementing: 0,
306
- validating: 0,
307
- done: 0
308
- }
309
- },
310
- documents: []
311
- };
260
+ /** 기존 id 패턴을 분석하여 다음 순번 id 생성 */ function generateNextRuleId(rules) {
261
+ if (rules.length === 0) return "R-001";
262
+ const numericPattern = /^(.+?)(\d+)$/;
263
+ let bestPrefix = "R-";
264
+ let maxNum = 0;
265
+ for (const rule of rules){
266
+ const match = numericPattern.exec(rule.id);
267
+ if (match) {
268
+ const prefix = match[1];
269
+ const num = Number.parseInt(match[2], 10);
270
+ if (num > maxNum) {
271
+ bestPrefix = prefix;
272
+ maxNum = num;
273
+ }
274
+ }
312
275
  }
313
- const documents = [];
314
- const statusDistribution = {
315
- draft: 0,
316
- specifying: 0,
317
- implementing: 0,
318
- validating: 0,
319
- done: 0
320
- };
321
- function scanForDashboard(dirPath) {
322
- const entries = fs.readdirSync(dirPath, {
323
- withFileTypes: true
324
- });
325
- for (const entry of entries){
326
- const fullPath = path.join(dirPath, entry.name);
327
- if (entry.isDirectory()) {
328
- if (entry.name === "schemas") continue;
329
- scanForDashboard(fullPath);
330
- } else if (entry.isFile()) {
331
- const fileType = detectFileType(entry.name);
332
- if (!fileType) continue;
333
- const relPath = path.relative(contractDir, fullPath);
334
- try {
335
- const raw = fs.readFileSync(fullPath, "utf-8");
336
- const doc = JSON.parse(raw);
337
- const summary = {
338
- path: relPath,
339
- name: entry.name,
340
- fileType,
341
- schemaId: typeof doc.schema === "string" ? doc.schema : undefined,
342
- lastModified: typeof doc.lastModified === "string" ? doc.lastModified : undefined
343
- };
344
- if (fileType === "contract") {
345
- const features = doc.features;
346
- if (features && typeof features === "object" && !Array.isArray(features)) {
347
- summary.featureCount = Object.keys(features).length;
348
- }
349
- } else {
350
- const status = typeof doc.status === "string" ? doc.status : "draft";
351
- summary.status = VALID_SPEC_STATUSES.has(status) ? status : "draft";
352
- statusDistribution[summary.status]++;
353
- if (Array.isArray(doc.acceptanceCriteria)) {
354
- summary.acceptanceCriteriaCount = doc.acceptanceCriteria.length;
355
- }
356
- if (Array.isArray(doc.sources)) {
357
- summary.sourceCount = doc.sources.length;
358
- }
276
+ const nextNum = maxNum + 1;
277
+ const padLen = Math.max(3, String(maxNum).length);
278
+ return `${bestPrefix}${String(nextNum).padStart(padLen, "0")}`;
279
+ }
280
+ /* ========================================================================
281
+ * AC API (modules/cdd ac-list 파싱 로직 복사)
282
+ * ======================================================================== */ /** describe/test 패턴 파싱 */ function parseAcEntries(content) {
283
+ const entries = [];
284
+ const lines = content.split("\n");
285
+ let currentDescribe = null;
286
+ let describeDepth = 0;
287
+ let braceDepth = 0;
288
+ let pendingTestAs = false;
289
+ let testAsBraceDepth = 0;
290
+ let testAsNeedName = false;
291
+ for (const line of lines){
292
+ const trimmed = line.trim();
293
+ const describeMatch = trimmed.match(/^describe\(["'`](.+?)["'`]/);
294
+ if (describeMatch) {
295
+ currentDescribe = describeMatch[1];
296
+ describeDepth = braceDepth;
297
+ }
298
+ const testMatch = trimmed.match(/^(?:test|it)\(["'`](.+?)["'`]/);
299
+ if (testMatch) {
300
+ entries.push({
301
+ describe: currentDescribe,
302
+ test: testMatch[1]
303
+ });
304
+ }
305
+ if (!pendingTestAs && trimmed.match(/^testAs\s*\(/)) {
306
+ const inlineMatch = trimmed.match(/^testAs\s*\(\s*\{[^}]*\}\s*,\s*["'`](.+?)["'`]/);
307
+ if (inlineMatch) {
308
+ entries.push({
309
+ describe: currentDescribe,
310
+ test: inlineMatch[1]
311
+ });
312
+ } else {
313
+ pendingTestAs = true;
314
+ testAsBraceDepth = 0;
315
+ testAsNeedName = false;
316
+ for (const ch of trimmed){
317
+ if (ch === "{") testAsBraceDepth++;
318
+ if (ch === "}") testAsBraceDepth--;
319
+ }
320
+ if (testAsBraceDepth <= 0) {
321
+ testAsNeedName = true;
322
+ const nameMatch = trimmed.match(/}\s*,\s*["'`](.+?)["'`]/);
323
+ if (nameMatch) {
324
+ entries.push({
325
+ describe: currentDescribe,
326
+ test: nameMatch[1]
327
+ });
328
+ pendingTestAs = false;
329
+ testAsNeedName = false;
330
+ }
331
+ }
332
+ }
333
+ } else if (pendingTestAs) {
334
+ if (!testAsNeedName) {
335
+ for (const ch of trimmed){
336
+ if (ch === "{") testAsBraceDepth++;
337
+ if (ch === "}") testAsBraceDepth--;
338
+ }
339
+ if (testAsBraceDepth <= 0) {
340
+ testAsNeedName = true;
341
+ const nameMatch = trimmed.match(/}\s*,\s*["'`](.+?)["'`]/);
342
+ if (nameMatch) {
343
+ entries.push({
344
+ describe: currentDescribe,
345
+ test: nameMatch[1]
346
+ });
347
+ pendingTestAs = false;
348
+ testAsNeedName = false;
359
349
  }
360
- documents.push(summary);
361
- } catch (err) {
362
- documents.push({
363
- path: relPath,
364
- name: entry.name,
365
- fileType,
366
- parseError: err instanceof Error ? err.message : String(err)
350
+ }
351
+ } else {
352
+ const nameMatch = trimmed.match(/^["'`](.+?)["'`]/);
353
+ if (nameMatch) {
354
+ entries.push({
355
+ describe: currentDescribe,
356
+ test: nameMatch[1]
367
357
  });
358
+ pendingTestAs = false;
359
+ testAsNeedName = false;
360
+ }
361
+ }
362
+ }
363
+ for (const ch of trimmed){
364
+ if (ch === "{") braceDepth++;
365
+ if (ch === "}") {
366
+ braceDepth--;
367
+ if (currentDescribe && braceDepth <= describeDepth) {
368
+ currentDescribe = null;
368
369
  }
369
370
  }
370
371
  }
371
372
  }
372
- scanForDashboard(contractDir);
373
- const totalContracts = documents.filter((d)=>d.fileType === "contract" && !d.parseError).length;
374
- const totalSpecs = documents.filter((d)=>d.fileType === "spec" && !d.parseError).length;
373
+ return entries;
374
+ }
375
+ /** 프로젝트 *.test.ts 파일을 스캔하여 AC 목록 반환 */ export function getAcList() {
376
+ const projectRoot = getProjectRoot();
377
+ const files = findTestFiles(projectRoot);
378
+ const acFiles = [];
379
+ for (const absPath of files){
380
+ const content = fs.readFileSync(absPath, "utf-8");
381
+ const entries = parseAcEntries(content);
382
+ if (entries.length > 0) {
383
+ acFiles.push({
384
+ path: path.relative(projectRoot, absPath),
385
+ entries
386
+ });
387
+ }
388
+ }
389
+ const total = acFiles.reduce((sum, f)=>sum + f.entries.length, 0);
375
390
  return {
376
- exists: true,
377
- stats: {
378
- totalContracts,
379
- totalSpecs,
380
- statusDistribution
381
- },
382
- documents
391
+ files: acFiles,
392
+ total
383
393
  };
384
394
  }
385
- /** 소스 파일을 외부 에디터로 열기 (대기하지 않음) */ export function openSourceFile(filePath) {
386
- const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(Sonamu.apiRootPath, filePath);
387
- if (!fs.existsSync(absPath)) {
388
- throw new Error(`파일을 찾을 수 없습니다: ${filePath}`);
395
+ /** *.test.ts 파일을 재귀 탐색 (node_modules, dist 제외) */ function findTestFiles(dir) {
396
+ const results = [];
397
+ const IGNORE = new Set([
398
+ "node_modules",
399
+ "dist",
400
+ ".git",
401
+ "contract"
402
+ ]);
403
+ function walk(currentDir) {
404
+ let entries;
405
+ try {
406
+ entries = fs.readdirSync(currentDir, {
407
+ withFileTypes: true
408
+ });
409
+ } catch {
410
+ return;
411
+ }
412
+ for (const entry of entries){
413
+ if (IGNORE.has(entry.name)) continue;
414
+ const fullPath = path.join(currentDir, entry.name);
415
+ if (entry.isDirectory()) {
416
+ walk(fullPath);
417
+ } else if (entry.isFile() && entry.name.endsWith(".test.ts")) {
418
+ results.push(fullPath);
419
+ }
420
+ }
389
421
  }
390
- const editor = resolveEditorCli({
391
- wait: false
392
- });
393
- const child = spawn(editor.bin, [
394
- ...editor.args,
395
- absPath
396
- ], {
397
- stdio: "ignore",
398
- detached: true
399
- });
400
- child.unref();
422
+ walk(dir);
423
+ results.sort();
424
+ return results;
401
425
  }
402
426
 
403
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91aS9jZGQtc2VydmljZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzcGF3biB9IGZyb20gXCJjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgb3MgZnJvbSBcIm9zXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgU29uYW11IH0gZnJvbSBcIi4uL2FwaS9zb25hbXVcIjtcbmltcG9ydCB0eXBlIHtcbiAgQ2RkQ29udGVudEVudmVsb3BlLFxuICBDZGREYXNoYm9hcmREYXRhLFxuICBDZGREb2N1bWVudFN1bW1hcnksXG4gIENkZEZpbGVUeXBlLFxuICBDZGRTY2hlbWEsXG4gIENkZFNjaGVtYURldGFpbEVudmVsb3BlLFxuICBDZGRTY2hlbWFSZWZlcmVuY2UsXG4gIENkZFNjaGVtYVN1bW1hcnksXG4gIENkZFNwZWNTdGF0dXMsXG4gIENkZFRyZWVOb2RlLFxufSBmcm9tIFwiLi9jZGQtdHlwZXNcIjtcblxuZXhwb3J0IHR5cGUge1xuICBDZGRDb250ZW50RW52ZWxvcGUsXG4gIENkZERhc2hib2FyZERhdGEsXG4gIENkZERvY3VtZW50U3VtbWFyeSxcbiAgQ2RkRmlsZVR5cGUsXG4gIENkZFNjaGVtYSxcbiAgQ2RkU2NoZW1hRGV0YWlsRW52ZWxvcGUsXG4gIENkZFNjaGVtYUZpZWxkLFxuICBDZGRTY2hlbWFGaWVsZFR5cGUsXG4gIENkZFNjaGVtYVJlZmVyZW5jZSxcbiAgQ2RkU2NoZW1hU3VtbWFyeSxcbiAgQ2RkU3BlY1N0YXR1cyxcbiAgQ2RkVHJlZU5vZGUsXG59IGZyb20gXCIuL2NkZC10eXBlc1wiO1xuXG4vKiogY29udHJhY3QvIOuUlOugie2EsOumrCDsoIjrjIAg6rK966GcIOuwmO2ZmCAoYXBpUm9vdFBhdGgg6riw7KSAKSAqL1xuZnVuY3Rpb24gZ2V0Q29udHJhY3REaXIoKTogc3RyaW5nIHtcbiAgcmV0dXJuIHBhdGguam9pbihTb25hbXUuYXBpUm9vdFBhdGgsIFwiLi5cIiwgXCIuLlwiLCBcImNvbnRyYWN0XCIpO1xufVxuXG4vKiog6rK966Gc6rCAIGNvbnRyYWN0LyDrlJTroInthLDrpqwg64K067aA7J247KeAIOqygOymnSAqL1xuZnVuY3Rpb24gYXNzZXJ0SW5zaWRlQ29udHJhY3REaXIoZmlsZVBhdGg6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCBjb250cmFjdERpciA9IGdldENvbnRyYWN0RGlyKCk7XG4gIGNvbnN0IHJlc29sdmVkID0gcGF0aC5yZXNvbHZlKGNvbnRyYWN0RGlyLCBmaWxlUGF0aCk7XG4gIGlmICghcmVzb2x2ZWQuc3RhcnRzV2l0aChjb250cmFjdERpciArIHBhdGguc2VwKSAmJiByZXNvbHZlZCAhPT0gY29udHJhY3REaXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYOqyveuhnOqwgCBjb250cmFjdC8g65SU66CJ7YSw66asIOuwluydhCDssLjsobDtlanri4jri6Q6ICR7ZmlsZVBhdGh9YCk7XG4gIH1cbn1cblxuLyoqIO2MjOydvOuqheyXkOyEnCBDZGRGaWxlVHlwZSDtjJDrs4QgKi9cbmZ1bmN0aW9uIGRldGVjdEZpbGVUeXBlKGZpbGVOYW1lOiBzdHJpbmcpOiBDZGRGaWxlVHlwZSB8IHVuZGVmaW5lZCB7XG4gIGlmIChmaWxlTmFtZS5lbmRzV2l0aChcIi5jb250cmFjdC5qc29uXCIpKSByZXR1cm4gXCJjb250cmFjdFwiO1xuICBpZiAoZmlsZU5hbWUuZW5kc1dpdGgoXCIuc3BlYy5qc29uXCIpKSByZXR1cm4gXCJzcGVjXCI7XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKiDrlJTroInthLDrpqzrpbwg7J6s6reAIO2DkOyDie2VmOyXrCBDZGRUcmVlTm9kZSDtirjrpqzrpbwg7IOd7ISxICovXG5mdW5jdGlvbiBzY2FuRGlyZWN0b3J5KGRpclBhdGg6IHN0cmluZywgcmVsYXRpdmVUbzogc3RyaW5nKTogQ2RkVHJlZU5vZGVbXSB7XG4gIGNvbnN0IGVudHJpZXMgPSBmcy5yZWFkZGlyU3luYyhkaXJQYXRoLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gIGNvbnN0IG5vZGVzOiBDZGRUcmVlTm9kZVtdID0gW107XG5cbiAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4oZGlyUGF0aCwgZW50cnkubmFtZSk7XG4gICAgY29uc3QgcmVsUGF0aCA9IHBhdGgucmVsYXRpdmUocmVsYXRpdmVUbywgZnVsbFBhdGgpO1xuXG4gICAgaWYgKGVudHJ5LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIGNvbnN0IGNoaWxkcmVuID0gc2NhbkRpcmVjdG9yeShmdWxsUGF0aCwgcmVsYXRpdmVUbyk7XG4gICAgICBub2Rlcy5wdXNoKHtcbiAgICAgICAgbmFtZTogZW50cnkubmFtZSxcbiAgICAgICAgcGF0aDogcmVsUGF0aCxcbiAgICAgICAgdHlwZTogXCJkaXJlY3RvcnlcIixcbiAgICAgICAgY2hpbGRyZW4sXG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGVudHJ5LmlzRmlsZSgpKSB7XG4gICAgICBjb25zdCBmaWxlVHlwZSA9IGRldGVjdEZpbGVUeXBlKGVudHJ5Lm5hbWUpO1xuICAgICAgaWYgKGZpbGVUeXBlKSB7XG4gICAgICAgIG5vZGVzLnB1c2goe1xuICAgICAgICAgIG5hbWU6IGVudHJ5Lm5hbWUsXG4gICAgICAgICAgcGF0aDogcmVsUGF0aCxcbiAgICAgICAgICB0eXBlOiBcImZpbGVcIixcbiAgICAgICAgICBmaWxlVHlwZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5vZGVzO1xufVxuXG4vKiogY29udHJhY3QvIOuUlOugie2EsOumrOydmCDtirjrpqwg6rWs7KGw66W8IOuwmO2ZmCAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENkZFRyZWUoKTogeyBleGlzdHM6IGJvb2xlYW47IHRyZWU6IENkZFRyZWVOb2RlW10gfSB7XG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGNvbnRyYWN0RGlyKSkge1xuICAgIHJldHVybiB7IGV4aXN0czogZmFsc2UsIHRyZWU6IFtdIH07XG4gIH1cbiAgY29uc3QgdHJlZSA9IHNjYW5EaXJlY3RvcnkoY29udHJhY3REaXIsIGNvbnRyYWN0RGlyKTtcbiAgcmV0dXJuIHsgZXhpc3RzOiB0cnVlLCB0cmVlIH07XG59XG5cbi8qKiBzY2hlbWEgSUTroZwgc2NoZW1hIO2MjOydvOydhCDssL7slYQg67CY7ZmYICovXG5mdW5jdGlvbiByZXNvbHZlU2NoZW1hKHNjaGVtYUlkOiBzdHJpbmcpOiBDZGRTY2hlbWEgfCBudWxsIHtcbiAgY29uc3QgY29udHJhY3REaXIgPSBnZXRDb250cmFjdERpcigpO1xuICBjb25zdCBzY2hlbWFQYXRoID0gcGF0aC5qb2luKGNvbnRyYWN0RGlyLCBcInNjaGVtYXNcIiwgYCR7c2NoZW1hSWR9LnNjaGVtYS5qc29uYCk7XG4gIGlmICghZnMuZXhpc3RzU3luYyhzY2hlbWFQYXRoKSkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IHJhdyA9IGZzLnJlYWRGaWxlU3luYyhzY2hlbWFQYXRoLCBcInV0Zi04XCIpO1xuICByZXR1cm4gSlNPTi5wYXJzZShyYXcpIGFzIENkZFNjaGVtYTtcbn1cblxuLyoqIEpTT04g7YyM7J287J2YIOyghOyytCDrgrTsmqnsnYQg7J297Ja0IHNjaGVtYeyZgCDtlajqu5ggZW52ZWxvcGXroZwg67CY7ZmYICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZENvbnRlbnQoZmlsZVBhdGg6IHN0cmluZyk6IENkZENvbnRlbnRFbnZlbG9wZSB7XG4gIGFzc2VydEluc2lkZUNvbnRyYWN0RGlyKGZpbGVQYXRoKTtcblxuICBjb25zdCBjb250cmFjdERpciA9IGdldENvbnRyYWN0RGlyKCk7XG4gIGNvbnN0IGFic1BhdGggPSBwYXRoLnJlc29sdmUoY29udHJhY3REaXIsIGZpbGVQYXRoKTtcblxuICBpZiAoIWZzLmV4aXN0c1N5bmMoYWJzUGF0aCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYO2MjOydvOydhCDssL7snYQg7IiYIOyXhuyKteuLiOuLpDogJHtmaWxlUGF0aH1gKTtcbiAgfVxuXG4gIGNvbnN0IHJhdyA9IGZzLnJlYWRGaWxlU3luYyhhYnNQYXRoLCBcInV0Zi04XCIpO1xuICBjb25zdCBkb2N1bWVudCA9IEpTT04ucGFyc2UocmF3KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3QgZmlsZVR5cGUgPSBkZXRlY3RGaWxlVHlwZShwYXRoLmJhc2VuYW1lKGZpbGVQYXRoKSk7XG4gIGNvbnN0IHNjaGVtYUlkID0gdHlwZW9mIGRvY3VtZW50LnNjaGVtYSA9PT0gXCJzdHJpbmdcIiA/IGRvY3VtZW50LnNjaGVtYSA6IG51bGw7XG4gIGNvbnN0IHNjaGVtYSA9IHNjaGVtYUlkID8gcmVzb2x2ZVNjaGVtYShzY2hlbWFJZCkgOiBudWxsO1xuXG4gIHJldHVybiB7XG4gICAgZG9jdW1lbnQsXG4gICAgc2NoZW1hLFxuICAgIGZpbGVUeXBlOiBmaWxlVHlwZSA/PyBcImNvbnRyYWN0XCIsXG4gIH07XG59XG5cbi8qKiBKU09OIO2MjOydvOydhCDsmbjrtoAg7JeQ65SU7YSw66GcIOyngeygkSDtjrjsp5EgKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlZGl0Q29udGVudChcbiAgZmlsZVBhdGg6IHN0cmluZyxcbik6IFByb21pc2U8eyBzdWNjZXNzOiBib29sZWFuOyBmaWxlUGF0aDogc3RyaW5nIH0+IHtcbiAgYXNzZXJ0SW5zaWRlQ29udHJhY3REaXIoZmlsZVBhdGgpO1xuXG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgY29uc3QgYWJzUGF0aCA9IHBhdGgucmVzb2x2ZShjb250cmFjdERpciwgZmlsZVBhdGgpO1xuXG4gIGlmICghZnMuZXhpc3RzU3luYyhhYnNQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihg7YyM7J287J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukOiAke2ZpbGVQYXRofWApO1xuICB9XG5cbiAgY29uc3QgZWRpdG9yID0gcmVzb2x2ZUVkaXRvckNsaSgpO1xuICBhd2FpdCBydW5FZGl0b3IoZWRpdG9yLCBhYnNQYXRoKTtcblxuICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBmaWxlUGF0aCB9O1xufVxuXG4vKiog7JeQ65SU7YSw67OEIOyVsSDrsojrk6Qg64K0IENMSSDqsr3roZwgKyAtLXdhaXQg7ZSM656Y6re4IOunpO2VkSAqL1xuY29uc3QgRURJVE9SX0NMSV9NQVA6IFJlY29yZDxzdHJpbmcsIHsgY2xpOiBzdHJpbmc7IHdhaXRGbGFnOiBzdHJpbmcgfT4gPSB7XG4gIFwiVmlzdWFsIFN0dWRpbyBDb2RlXCI6IHsgY2xpOiBcIkNvbnRlbnRzL1Jlc291cmNlcy9hcHAvYmluL2NvZGVcIiwgd2FpdEZsYWc6IFwiLS13YWl0XCIgfSxcbiAgWmVkOiB7IGNsaTogXCJDb250ZW50cy9NYWNPUy9jbGlcIiwgd2FpdEZsYWc6IFwiLS13YWl0XCIgfSxcbiAgQ3Vyc29yOiB7IGNsaTogXCJDb250ZW50cy9SZXNvdXJjZXMvYXBwL2Jpbi9jdXJzb3JcIiwgd2FpdEZsYWc6IFwiLS13YWl0XCIgfSxcbn07XG5cbi8qKiDslbEg67KI65OkIENMSSDqsr3roZzrpbwgcmVzb2x2ZS4gd2FpdD1mYWxzZeydtOuptCAtLXdhaXQg7ZSM656Y6re466W8IOyDneuetSAqL1xuZnVuY3Rpb24gcmVzb2x2ZUVkaXRvckNsaShvcHRpb25zPzogeyB3YWl0PzogYm9vbGVhbiB9KTogeyBiaW46IHN0cmluZzsgYXJnczogc3RyaW5nW10gfSB7XG4gIGNvbnN0IHdhaXQgPSBvcHRpb25zPy53YWl0ID8/IHRydWU7XG4gIGNvbnN0IGFwcE5hbWUgPSBTb25hbXUuY29uZmlnLmV4dGVybmFsRWRpdG9yID8/IFwiVmlzdWFsIFN0dWRpbyBDb2RlXCI7XG4gIGNvbnN0IG1hcHBpbmcgPSBFRElUT1JfQ0xJX01BUFthcHBOYW1lXTtcbiAgaWYgKCFtYXBwaW5nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYOyngOybkOuQmOyngCDslYrripQg7JeQ65SU7YSw7J6F64uI64ukOiAke2FwcE5hbWV9ICjsp4Dsm5A6ICR7T2JqZWN0LmtleXMoRURJVE9SX0NMSV9NQVApLmpvaW4oXCIsIFwiKX0pYCxcbiAgICApO1xuICB9XG5cbiAgY29uc3Qgc2VhcmNoUGF0aHMgPSBbXG4gICAgYC9BcHBsaWNhdGlvbnMvJHthcHBOYW1lfS5hcHBgLFxuICAgIGAke29zLmhvbWVkaXIoKX0vQXBwbGljYXRpb25zLyR7YXBwTmFtZX0uYXBwYCxcbiAgXTtcbiAgY29uc3QgYnVuZGxlUGF0aCA9IHNlYXJjaFBhdGhzLmZpbmQoKHApID0+IGZzLmV4aXN0c1N5bmMocCkpO1xuICBpZiAoIWJ1bmRsZVBhdGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYOyVsSDrsojrk6TsnYQg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7YXBwTmFtZX0gKC9BcHBsaWNhdGlvbnMg7ZmV7J24KWApO1xuICB9XG5cbiAgY29uc3QgY2xpQmluID0gcGF0aC5qb2luKGJ1bmRsZVBhdGgsIG1hcHBpbmcuY2xpKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGNsaUJpbikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYOyXkOuUlO2EsCBDTEnrpbwg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7Y2xpQmlufWApO1xuICB9XG5cbiAgcmV0dXJuIHsgYmluOiBjbGlCaW4sIGFyZ3M6IHdhaXQgPyBbbWFwcGluZy53YWl0RmxhZ10gOiBbXSB9O1xufVxuXG4vKiog7JeQ65SU7YSwIENMSeulvCDsi6TtlontlZjqs6Ag7YOt7J20IOuLq+2ekCDrlYzquYzsp4Ag64yA6riwICovXG5mdW5jdGlvbiBydW5FZGl0b3IoZWRpdG9yOiB7IGJpbjogc3RyaW5nOyBhcmdzOiBzdHJpbmdbXSB9LCBmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgY2hpbGQgPSBzcGF3bihlZGl0b3IuYmluLCBbLi4uZWRpdG9yLmFyZ3MsIGZpbGVQYXRoXSwge1xuICAgICAgc3RkaW86IFwiaW5oZXJpdFwiLFxuICAgIH0pO1xuXG4gICAgY2hpbGQub24oXCJlcnJvclwiLCAoZXJyKSA9PiB7XG4gICAgICByZWplY3QobmV3IEVycm9yKGDsl5DrlJTthLAg7Iuk7ZaJIOyLpO2MqCAoJHtlZGl0b3IuYmlufSk6ICR7ZXJyLm1lc3NhZ2V9YCkpO1xuICAgIH0pO1xuXG4gICAgY2hpbGQub24oXCJjbG9zZVwiLCAoY29kZSkgPT4ge1xuICAgICAgaWYgKGNvZGUgPT09IDApIHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihg7JeQ65SU7YSw6rCAIOu5hOygleyDgSDsooXro4zrkJjsl4jsirXri4jri6QgKGV4aXQgY29kZTogJHtjb2RlfSlgKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFNjaGVtYSDqtIDrpqwgQVBJXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuLyoqIGNvbnRyYWN0L3NjaGVtYXMvIOuUlOugie2EsOumrCDrgrQgLnNjaGVtYS5qc29uIO2MjOydvCDqsr3roZwg66qp66GdIOuwmO2ZmCAqL1xuZnVuY3Rpb24gc2NhblNjaGVtYUZpbGVzKCk6IHsgYWJzUGF0aDogc3RyaW5nOyByZWxQYXRoOiBzdHJpbmc7IGZpbGVOYW1lOiBzdHJpbmcgfVtdIHtcbiAgY29uc3Qgc2NoZW1hc0RpciA9IHBhdGguam9pbihnZXRDb250cmFjdERpcigpLCBcInNjaGVtYXNcIik7XG4gIGlmICghZnMuZXhpc3RzU3luYyhzY2hlbWFzRGlyKSkgcmV0dXJuIFtdO1xuXG4gIHJldHVybiBmc1xuICAgIC5yZWFkZGlyU3luYyhzY2hlbWFzRGlyLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSlcbiAgICAuZmlsdGVyKChlKSA9PiBlLmlzRmlsZSgpICYmIGUubmFtZS5lbmRzV2l0aChcIi5zY2hlbWEuanNvblwiKSlcbiAgICAubWFwKChlKSA9PiAoe1xuICAgICAgYWJzUGF0aDogcGF0aC5qb2luKHNjaGVtYXNEaXIsIGUubmFtZSksXG4gICAgICByZWxQYXRoOiBgc2NoZW1hcy8ke2UubmFtZX1gLFxuICAgICAgZmlsZU5hbWU6IGUubmFtZSxcbiAgICB9KSk7XG59XG5cbi8qKiDtirnsoJUgc2NoZW1hSWTrpbwg7LC47KGw7ZWY64qUIGNvbnRyYWN0L3NwZWMg66y47ISc65Ok7J2EIOyerOq3gCDsiJjsp5EgKi9cbmZ1bmN0aW9uIGNvbGxlY3RTY2hlbWFSZWZlcmVuY2VzKFxuICBzY2hlbWFJZDogc3RyaW5nLFxuICBkaXJQYXRoOiBzdHJpbmcsXG4gIHJlbGF0aXZlVG86IHN0cmluZyxcbik6IENkZFNjaGVtYVJlZmVyZW5jZVtdIHtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGRpclBhdGgpKSByZXR1cm4gW107XG4gIGNvbnN0IHJlZnM6IENkZFNjaGVtYVJlZmVyZW5jZVtdID0gW107XG4gIGNvbnN0IGVudHJpZXMgPSBmcy5yZWFkZGlyU3luYyhkaXJQYXRoLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG5cbiAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4oZGlyUGF0aCwgZW50cnkubmFtZSk7XG4gICAgaWYgKGVudHJ5LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIGlmIChlbnRyeS5uYW1lID09PSBcInNjaGVtYXNcIikgY29udGludWU7XG4gICAgICByZWZzLnB1c2goLi4uY29sbGVjdFNjaGVtYVJlZmVyZW5jZXMoc2NoZW1hSWQsIGZ1bGxQYXRoLCByZWxhdGl2ZVRvKSk7XG4gICAgfSBlbHNlIGlmIChlbnRyeS5pc0ZpbGUoKSkge1xuICAgICAgY29uc3QgZmlsZVR5cGUgPSBkZXRlY3RGaWxlVHlwZShlbnRyeS5uYW1lKTtcbiAgICAgIGlmICghZmlsZVR5cGUpIGNvbnRpbnVlO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmF3ID0gZnMucmVhZEZpbGVTeW5jKGZ1bGxQYXRoLCBcInV0Zi04XCIpO1xuICAgICAgICBjb25zdCBkb2MgPSBKU09OLnBhcnNlKHJhdykgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICAgIGlmIChkb2Muc2NoZW1hID09PSBzY2hlbWFJZCkge1xuICAgICAgICAgIHJlZnMucHVzaCh7XG4gICAgICAgICAgICBwYXRoOiBwYXRoLnJlbGF0aXZlKHJlbGF0aXZlVG8sIGZ1bGxQYXRoKSxcbiAgICAgICAgICAgIGZpbGVUeXBlLFxuICAgICAgICAgICAgbmFtZTogZW50cnkubmFtZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIEpTT04g7YyM7IuxIOyLpO2MqCDsi5wg66y07IucXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiByZWZzO1xufVxuXG4vKiogc2NoZW1hIO2MjOydvOuqheyXkOyEnCDquLDrjIDrkJjripQgaWQg7LaU7LacICovXG5mdW5jdGlvbiBleHBlY3RlZFNjaGVtYUlkKGZpbGVOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gZmlsZU5hbWUucmVwbGFjZSgvXFwuc2NoZW1hXFwuanNvbiQvLCBcIlwiKTtcbn1cblxuLyoqIHNjaGVtYXMvIO2VmOychCDqsr3roZzqsIAgY29udHJhY3Qvc2NoZW1hcy8g64K067aA7J247KeAIOqygOymnSAqL1xuZnVuY3Rpb24gYXNzZXJ0SW5zaWRlU2NoZW1hRGlyKHNjaGVtYUtleTogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IHNjaGVtYXNEaXIgPSBwYXRoLmpvaW4oZ2V0Q29udHJhY3REaXIoKSwgXCJzY2hlbWFzXCIpO1xuICBjb25zdCByZXNvbHZlZCA9IHBhdGgucmVzb2x2ZShzY2hlbWFzRGlyLCBgJHtzY2hlbWFLZXl9LnNjaGVtYS5qc29uYCk7XG4gIGlmICghcmVzb2x2ZWQuc3RhcnRzV2l0aChzY2hlbWFzRGlyICsgcGF0aC5zZXApICYmIHJlc29sdmVkICE9PSBzY2hlbWFzRGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGDsnKDtmqjtlZjsp4Ag7JWK7J2AIOyKpO2CpOuniCDtgqTsnoXri4jri6Q6ICR7c2NoZW1hS2V5fWApO1xuICB9XG59XG5cbi8qKiBzY2hlbWEg66qp66GdIOuwmO2ZmCAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpc3RTY2hlbWFzKCk6IHsgc2NoZW1hczogQ2RkU2NoZW1hU3VtbWFyeVtdIH0ge1xuICBjb25zdCBjb250cmFjdERpciA9IGdldENvbnRyYWN0RGlyKCk7XG4gIGNvbnN0IGZpbGVzID0gc2NhblNjaGVtYUZpbGVzKCk7XG4gIGNvbnN0IHNjaGVtYXM6IENkZFNjaGVtYVN1bW1hcnlbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgIGNvbnN0IGtleSA9IGV4cGVjdGVkU2NoZW1hSWQoZmlsZS5maWxlTmFtZSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJhdyA9IGZzLnJlYWRGaWxlU3luYyhmaWxlLmFic1BhdGgsIFwidXRmLThcIik7XG4gICAgICBjb25zdCBzY2hlbWEgPSBKU09OLnBhcnNlKHJhdykgYXMgQ2RkU2NoZW1hO1xuICAgICAgY29uc3QgcmVmcyA9IGNvbGxlY3RTY2hlbWFSZWZlcmVuY2VzKHNjaGVtYS5pZCwgY29udHJhY3REaXIsIGNvbnRyYWN0RGlyKTtcbiAgICAgIHNjaGVtYXMucHVzaCh7XG4gICAgICAgIGtleSxcbiAgICAgICAgaWQ6IHNjaGVtYS5pZCxcbiAgICAgICAgcGF0aDogZmlsZS5yZWxQYXRoLFxuICAgICAgICB0eXBlOiBzY2hlbWEudHlwZSxcbiAgICAgICAgZmllbGRDb3VudDogc2NoZW1hLmZpZWxkcy5sZW5ndGgsXG4gICAgICAgIHJlZmVyZW5jZUNvdW50OiByZWZzLmxlbmd0aCxcbiAgICAgICAgaGFzSWRNaXNtYXRjaDogc2NoZW1hLmlkICE9PSBrZXksXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHNjaGVtYXMucHVzaCh7XG4gICAgICAgIGtleSxcbiAgICAgICAgaWQ6IGtleSxcbiAgICAgICAgcGF0aDogZmlsZS5yZWxQYXRoLFxuICAgICAgICB0eXBlOiBcImNvbnRyYWN0XCIsXG4gICAgICAgIGZpZWxkQ291bnQ6IDAsXG4gICAgICAgIHJlZmVyZW5jZUNvdW50OiAwLFxuICAgICAgICBoYXNJZE1pc21hdGNoOiBmYWxzZSxcbiAgICAgICAgcGFyc2VFcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgc2NoZW1hcyB9O1xufVxuXG4vKiogc2NoZW1hIOyDgeyEuCDrsJjtmZggKO2MjOydvOuqhSDquLDrsJgga2V566GcIOyhsO2ajCkgKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkU2NoZW1hKHNjaGVtYUtleTogc3RyaW5nKTogQ2RkU2NoZW1hRGV0YWlsRW52ZWxvcGUge1xuICBhc3NlcnRJbnNpZGVTY2hlbWFEaXIoc2NoZW1hS2V5KTtcblxuICBjb25zdCBjb250cmFjdERpciA9IGdldENvbnRyYWN0RGlyKCk7XG4gIGNvbnN0IGFic1BhdGggPSBwYXRoLmpvaW4oY29udHJhY3REaXIsIFwic2NoZW1hc1wiLCBgJHtzY2hlbWFLZXl9LnNjaGVtYS5qc29uYCk7XG5cbiAgaWYgKCFmcy5leGlzdHNTeW5jKGFic1BhdGgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGDsiqTtgqTrp4jrpbwg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7c2NoZW1hS2V5fWApO1xuICB9XG5cbiAgY29uc3QgcmF3ID0gZnMucmVhZEZpbGVTeW5jKGFic1BhdGgsIFwidXRmLThcIik7XG4gIGNvbnN0IHNjaGVtYSA9IEpTT04ucGFyc2UocmF3KSBhcyBDZGRTY2hlbWE7XG4gIGNvbnN0IHJlbFBhdGggPSBwYXRoLnJlbGF0aXZlKGNvbnRyYWN0RGlyLCBhYnNQYXRoKTtcbiAgY29uc3QgcmVmZXJlbmNlcyA9IGNvbGxlY3RTY2hlbWFSZWZlcmVuY2VzKHNjaGVtYS5pZCwgY29udHJhY3REaXIsIGNvbnRyYWN0RGlyKTtcblxuICByZXR1cm4ge1xuICAgIGtleTogc2NoZW1hS2V5LFxuICAgIHBhdGg6IHJlbFBhdGgsXG4gICAgc2NoZW1hLFxuICAgIHJlZmVyZW5jZXMsXG4gICAgaGFzSWRNaXNtYXRjaDogc2NoZW1hLmlkICE9PSBzY2hlbWFLZXksXG4gIH07XG59XG5cbi8qKiBzY2hlbWEg7YyM7J287J2EIOyZuOu2gCDsl5DrlJTthLDroZwg7Y647KeRICjtjIzsnbzrqoUg6riw67CYIGtleeuhnCDsobDtmowpICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZWRpdFNjaGVtYShcbiAgc2NoZW1hS2V5OiBzdHJpbmcsXG4pOiBQcm9taXNlPHsgc3VjY2VzczogYm9vbGVhbjsgc2NoZW1hS2V5OiBzdHJpbmcgfT4ge1xuICBhc3NlcnRJbnNpZGVTY2hlbWFEaXIoc2NoZW1hS2V5KTtcblxuICBjb25zdCBjb250cmFjdERpciA9IGdldENvbnRyYWN0RGlyKCk7XG4gIGNvbnN0IGFic1BhdGggPSBwYXRoLmpvaW4oY29udHJhY3REaXIsIFwic2NoZW1hc1wiLCBgJHtzY2hlbWFLZXl9LnNjaGVtYS5qc29uYCk7XG5cbiAgaWYgKCFmcy5leGlzdHNTeW5jKGFic1BhdGgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGDsiqTtgqTrp4jrpbwg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7c2NoZW1hS2V5fWApO1xuICB9XG5cbiAgY29uc3QgZWRpdG9yID0gcmVzb2x2ZUVkaXRvckNsaSgpO1xuICBhd2FpdCBydW5FZGl0b3IoZWRpdG9yLCBhYnNQYXRoKTtcblxuICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBzY2hlbWFLZXkgfTtcbn1cblxuY29uc3QgVkFMSURfU1BFQ19TVEFUVVNFUyA9IG5ldyBTZXQ8Q2RkU3BlY1N0YXR1cz4oW1xuICBcImRyYWZ0XCIsXG4gIFwic3BlY2lmeWluZ1wiLFxuICBcImltcGxlbWVudGluZ1wiLFxuICBcInZhbGlkYXRpbmdcIixcbiAgXCJkb25lXCIsXG5dKTtcblxuLyoqIOuqqOuToCBjb250cmFjdC9zcGVjIOusuOyEnOulvCDsiqTsupTtlZjsl6wg64yA7Iuc67O065OcIO2GteqzhOulvCDrsJjtmZggKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXREYXNoYm9hcmQoKTogQ2RkRGFzaGJvYXJkRGF0YSB7XG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGNvbnRyYWN0RGlyKSkge1xuICAgIHJldHVybiB7XG4gICAgICBleGlzdHM6IGZhbHNlLFxuICAgICAgc3RhdHM6IHtcbiAgICAgICAgdG90YWxDb250cmFjdHM6IDAsXG4gICAgICAgIHRvdGFsU3BlY3M6IDAsXG4gICAgICAgIHN0YXR1c0Rpc3RyaWJ1dGlvbjogeyBkcmFmdDogMCwgc3BlY2lmeWluZzogMCwgaW1wbGVtZW50aW5nOiAwLCB2YWxpZGF0aW5nOiAwLCBkb25lOiAwIH0sXG4gICAgICB9LFxuICAgICAgZG9jdW1lbnRzOiBbXSxcbiAgICB9O1xuICB9XG5cbiAgY29uc3QgZG9jdW1lbnRzOiBDZGREb2N1bWVudFN1bW1hcnlbXSA9IFtdO1xuICBjb25zdCBzdGF0dXNEaXN0cmlidXRpb246IFJlY29yZDxDZGRTcGVjU3RhdHVzLCBudW1iZXI+ID0ge1xuICAgIGRyYWZ0OiAwLFxuICAgIHNwZWNpZnlpbmc6IDAsXG4gICAgaW1wbGVtZW50aW5nOiAwLFxuICAgIHZhbGlkYXRpbmc6IDAsXG4gICAgZG9uZTogMCxcbiAgfTtcblxuICBmdW5jdGlvbiBzY2FuRm9yRGFzaGJvYXJkKGRpclBhdGg6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGVudHJpZXMgPSBmcy5yZWFkZGlyU3luYyhkaXJQYXRoLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGguam9pbihkaXJQYXRoLCBlbnRyeS5uYW1lKTtcbiAgICAgIGlmIChlbnRyeS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgIGlmIChlbnRyeS5uYW1lID09PSBcInNjaGVtYXNcIikgY29udGludWU7XG4gICAgICAgIHNjYW5Gb3JEYXNoYm9hcmQoZnVsbFBhdGgpO1xuICAgICAgfSBlbHNlIGlmIChlbnRyeS5pc0ZpbGUoKSkge1xuICAgICAgICBjb25zdCBmaWxlVHlwZSA9IGRldGVjdEZpbGVUeXBlKGVudHJ5Lm5hbWUpO1xuICAgICAgICBpZiAoIWZpbGVUeXBlKSBjb250aW51ZTtcbiAgICAgICAgY29uc3QgcmVsUGF0aCA9IHBhdGgucmVsYXRpdmUoY29udHJhY3REaXIsIGZ1bGxQYXRoKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByYXcgPSBmcy5yZWFkRmlsZVN5bmMoZnVsbFBhdGgsIFwidXRmLThcIik7XG4gICAgICAgICAgY29uc3QgZG9jID0gSlNPTi5wYXJzZShyYXcpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gICAgICAgICAgY29uc3Qgc3VtbWFyeTogQ2RkRG9jdW1lbnRTdW1tYXJ5ID0ge1xuICAgICAgICAgICAgcGF0aDogcmVsUGF0aCxcbiAgICAgICAgICAgIG5hbWU6IGVudHJ5Lm5hbWUsXG4gICAgICAgICAgICBmaWxlVHlwZSxcbiAgICAgICAgICAgIHNjaGVtYUlkOiB0eXBlb2YgZG9jLnNjaGVtYSA9PT0gXCJzdHJpbmdcIiA/IGRvYy5zY2hlbWEgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBsYXN0TW9kaWZpZWQ6IHR5cGVvZiBkb2MubGFzdE1vZGlmaWVkID09PSBcInN0cmluZ1wiID8gZG9jLmxhc3RNb2RpZmllZCA6IHVuZGVmaW5lZCxcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgaWYgKGZpbGVUeXBlID09PSBcImNvbnRyYWN0XCIpIHtcbiAgICAgICAgICAgIGNvbnN0IGZlYXR1cmVzID0gZG9jLmZlYXR1cmVzO1xuICAgICAgICAgICAgaWYgKGZlYXR1cmVzICYmIHR5cGVvZiBmZWF0dXJlcyA9PT0gXCJvYmplY3RcIiAmJiAhQXJyYXkuaXNBcnJheShmZWF0dXJlcykpIHtcbiAgICAgICAgICAgICAgc3VtbWFyeS5mZWF0dXJlQ291bnQgPSBPYmplY3Qua2V5cyhmZWF0dXJlcykubGVuZ3RoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBzdGF0dXMgPSB0eXBlb2YgZG9jLnN0YXR1cyA9PT0gXCJzdHJpbmdcIiA/IGRvYy5zdGF0dXMgOiBcImRyYWZ0XCI7XG4gICAgICAgICAgICBzdW1tYXJ5LnN0YXR1cyA9IFZBTElEX1NQRUNfU1RBVFVTRVMuaGFzKHN0YXR1cyBhcyBDZGRTcGVjU3RhdHVzKVxuICAgICAgICAgICAgICA/IChzdGF0dXMgYXMgQ2RkU3BlY1N0YXR1cylcbiAgICAgICAgICAgICAgOiBcImRyYWZ0XCI7XG4gICAgICAgICAgICBzdGF0dXNEaXN0cmlidXRpb25bc3VtbWFyeS5zdGF0dXNdKys7XG5cbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGRvYy5hY2NlcHRhbmNlQ3JpdGVyaWEpKSB7XG4gICAgICAgICAgICAgIHN1bW1hcnkuYWNjZXB0YW5jZUNyaXRlcmlhQ291bnQgPSBkb2MuYWNjZXB0YW5jZUNyaXRlcmlhLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGRvYy5zb3VyY2VzKSkge1xuICAgICAgICAgICAgICBzdW1tYXJ5LnNvdXJjZUNvdW50ID0gZG9jLnNvdXJjZXMubGVuZ3RoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGRvY3VtZW50cy5wdXNoKHN1bW1hcnkpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBkb2N1bWVudHMucHVzaCh7XG4gICAgICAgICAgICBwYXRoOiByZWxQYXRoLFxuICAgICAgICAgICAgbmFtZTogZW50cnkubmFtZSxcbiAgICAgICAgICAgIGZpbGVUeXBlLFxuICAgICAgICAgICAgcGFyc2VFcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc2NhbkZvckRhc2hib2FyZChjb250cmFjdERpcik7XG5cbiAgY29uc3QgdG90YWxDb250cmFjdHMgPSBkb2N1bWVudHMuZmlsdGVyKChkKSA9PiBkLmZpbGVUeXBlID09PSBcImNvbnRyYWN0XCIgJiYgIWQucGFyc2VFcnJvcikubGVuZ3RoO1xuICBjb25zdCB0b3RhbFNwZWNzID0gZG9jdW1lbnRzLmZpbHRlcigoZCkgPT4gZC5maWxlVHlwZSA9PT0gXCJzcGVjXCIgJiYgIWQucGFyc2VFcnJvcikubGVuZ3RoO1xuXG4gIHJldHVybiB7XG4gICAgZXhpc3RzOiB0cnVlLFxuICAgIHN0YXRzOiB7IHRvdGFsQ29udHJhY3RzLCB0b3RhbFNwZWNzLCBzdGF0dXNEaXN0cmlidXRpb24gfSxcbiAgICBkb2N1bWVudHMsXG4gIH07XG59XG5cbi8qKiDshozsiqQg7YyM7J287J2EIOyZuOu2gCDsl5DrlJTthLDroZwg7Je06riwICjrjIDquLDtlZjsp4Ag7JWK7J2MKSAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9wZW5Tb3VyY2VGaWxlKGZpbGVQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3QgYWJzUGF0aCA9IHBhdGguaXNBYnNvbHV0ZShmaWxlUGF0aCkgPyBmaWxlUGF0aCA6IHBhdGgucmVzb2x2ZShTb25hbXUuYXBpUm9vdFBhdGgsIGZpbGVQYXRoKTtcblxuICBpZiAoIWZzLmV4aXN0c1N5bmMoYWJzUGF0aCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYO2MjOydvOydhCDssL7snYQg7IiYIOyXhuyKteuLiOuLpDogJHtmaWxlUGF0aH1gKTtcbiAgfVxuXG4gIGNvbnN0IGVkaXRvciA9IHJlc29sdmVFZGl0b3JDbGkoeyB3YWl0OiBmYWxzZSB9KTtcbiAgY29uc3QgY2hpbGQgPSBzcGF3bihlZGl0b3IuYmluLCBbLi4uZWRpdG9yLmFyZ3MsIGFic1BhdGhdLCB7XG4gICAgc3RkaW86IFwiaWdub3JlXCIsXG4gICAgZGV0YWNoZWQ6IHRydWUsXG4gIH0pO1xuICBjaGlsZC51bnJlZigpO1xufVxuIl0sIm5hbWVzIjpbInNwYXduIiwiZnMiLCJvcyIsInBhdGgiLCJTb25hbXUiLCJnZXRDb250cmFjdERpciIsImpvaW4iLCJhcGlSb290UGF0aCIsImFzc2VydEluc2lkZUNvbnRyYWN0RGlyIiwiZmlsZVBhdGgiLCJjb250cmFjdERpciIsInJlc29sdmVkIiwicmVzb2x2ZSIsInN0YXJ0c1dpdGgiLCJzZXAiLCJFcnJvciIsImRldGVjdEZpbGVUeXBlIiwiZmlsZU5hbWUiLCJlbmRzV2l0aCIsInVuZGVmaW5lZCIsInNjYW5EaXJlY3RvcnkiLCJkaXJQYXRoIiwicmVsYXRpdmVUbyIsImVudHJpZXMiLCJyZWFkZGlyU3luYyIsIndpdGhGaWxlVHlwZXMiLCJub2RlcyIsImVudHJ5IiwiZnVsbFBhdGgiLCJuYW1lIiwicmVsUGF0aCIsInJlbGF0aXZlIiwiaXNEaXJlY3RvcnkiLCJjaGlsZHJlbiIsInB1c2giLCJ0eXBlIiwiaXNGaWxlIiwiZmlsZVR5cGUiLCJnZXRDZGRUcmVlIiwiZXhpc3RzU3luYyIsImV4aXN0cyIsInRyZWUiLCJyZXNvbHZlU2NoZW1hIiwic2NoZW1hSWQiLCJzY2hlbWFQYXRoIiwicmF3IiwicmVhZEZpbGVTeW5jIiwiSlNPTiIsInBhcnNlIiwicmVhZENvbnRlbnQiLCJhYnNQYXRoIiwiZG9jdW1lbnQiLCJiYXNlbmFtZSIsInNjaGVtYSIsImVkaXRDb250ZW50IiwiZWRpdG9yIiwicmVzb2x2ZUVkaXRvckNsaSIsInJ1bkVkaXRvciIsInN1Y2Nlc3MiLCJFRElUT1JfQ0xJX01BUCIsImNsaSIsIndhaXRGbGFnIiwiWmVkIiwiQ3Vyc29yIiwib3B0aW9ucyIsIndhaXQiLCJhcHBOYW1lIiwiY29uZmlnIiwiZXh0ZXJuYWxFZGl0b3IiLCJtYXBwaW5nIiwiT2JqZWN0Iiwia2V5cyIsInNlYXJjaFBhdGhzIiwiaG9tZWRpciIsImJ1bmRsZVBhdGgiLCJmaW5kIiwicCIsImNsaUJpbiIsImJpbiIsImFyZ3MiLCJQcm9taXNlIiwicmVqZWN0IiwiY2hpbGQiLCJzdGRpbyIsIm9uIiwiZXJyIiwibWVzc2FnZSIsImNvZGUiLCJzY2FuU2NoZW1hRmlsZXMiLCJzY2hlbWFzRGlyIiwiZmlsdGVyIiwiZSIsIm1hcCIsImNvbGxlY3RTY2hlbWFSZWZlcmVuY2VzIiwicmVmcyIsImRvYyIsImV4cGVjdGVkU2NoZW1hSWQiLCJyZXBsYWNlIiwiYXNzZXJ0SW5zaWRlU2NoZW1hRGlyIiwic2NoZW1hS2V5IiwibGlzdFNjaGVtYXMiLCJmaWxlcyIsInNjaGVtYXMiLCJmaWxlIiwia2V5IiwiaWQiLCJmaWVsZENvdW50IiwiZmllbGRzIiwibGVuZ3RoIiwicmVmZXJlbmNlQ291bnQiLCJoYXNJZE1pc21hdGNoIiwicGFyc2VFcnJvciIsIlN0cmluZyIsInJlYWRTY2hlbWEiLCJyZWZlcmVuY2VzIiwiZWRpdFNjaGVtYSIsIlZBTElEX1NQRUNfU1RBVFVTRVMiLCJTZXQiLCJnZXREYXNoYm9hcmQiLCJzdGF0cyIsInRvdGFsQ29udHJhY3RzIiwidG90YWxTcGVjcyIsInN0YXR1c0Rpc3RyaWJ1dGlvbiIsImRyYWZ0Iiwic3BlY2lmeWluZyIsImltcGxlbWVudGluZyIsInZhbGlkYXRpbmciLCJkb25lIiwiZG9jdW1lbnRzIiwic2NhbkZvckRhc2hib2FyZCIsInN1bW1hcnkiLCJsYXN0TW9kaWZpZWQiLCJmZWF0dXJlcyIsIkFycmF5IiwiaXNBcnJheSIsImZlYXR1cmVDb3VudCIsInN0YXR1cyIsImhhcyIsImFjY2VwdGFuY2VDcml0ZXJpYSIsImFjY2VwdGFuY2VDcml0ZXJpYUNvdW50Iiwic291cmNlcyIsInNvdXJjZUNvdW50IiwiZCIsIm9wZW5Tb3VyY2VGaWxlIiwiaXNBYnNvbHV0ZSIsImRldGFjaGVkIiwidW5yZWYiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLEtBQUssUUFBUSxnQkFBZ0I7QUFDdEMsT0FBT0MsUUFBUSxLQUFLO0FBQ3BCLE9BQU9DLFFBQVEsS0FBSztBQUNwQixPQUFPQyxVQUFVLE9BQU87QUFDeEIsU0FBU0MsTUFBTSxRQUFRLG1CQUFnQjtBQTZCdkMsNkNBQTZDLEdBQzdDLFNBQVNDO0lBQ1AsT0FBT0YsS0FBS0csSUFBSSxDQUFDRixPQUFPRyxXQUFXLEVBQUUsTUFBTSxNQUFNO0FBQ25EO0FBRUEsK0JBQStCLEdBQy9CLFNBQVNDLHdCQUF3QkMsUUFBZ0I7SUFDL0MsTUFBTUMsY0FBY0w7SUFDcEIsTUFBTU0sV0FBV1IsS0FBS1MsT0FBTyxDQUFDRixhQUFhRDtJQUMzQyxJQUFJLENBQUNFLFNBQVNFLFVBQVUsQ0FBQ0gsY0FBY1AsS0FBS1csR0FBRyxLQUFLSCxhQUFhRCxhQUFhO1FBQzVFLE1BQU0sSUFBSUssTUFBTSxDQUFDLDZCQUE2QixFQUFFTixVQUFVO0lBQzVEO0FBQ0Y7QUFFQSx5QkFBeUIsR0FDekIsU0FBU08sZUFBZUMsUUFBZ0I7SUFDdEMsSUFBSUEsU0FBU0MsUUFBUSxDQUFDLG1CQUFtQixPQUFPO0lBQ2hELElBQUlELFNBQVNDLFFBQVEsQ0FBQyxlQUFlLE9BQU87SUFDNUMsT0FBT0M7QUFDVDtBQUVBLHFDQUFxQyxHQUNyQyxTQUFTQyxjQUFjQyxPQUFlLEVBQUVDLFVBQWtCO0lBQ3hELE1BQU1DLFVBQVV0QixHQUFHdUIsV0FBVyxDQUFDSCxTQUFTO1FBQUVJLGVBQWU7SUFBSztJQUM5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
427
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91aS9jZGQtc2VydmljZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzcGF3biB9IGZyb20gXCJjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgb3MgZnJvbSBcIm9zXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgU29uYW11IH0gZnJvbSBcIi4uL2FwaS9zb25hbXVcIjtcbmltcG9ydCB0eXBlIHtcbiAgQ2RkQWNFbnRyeSxcbiAgQ2RkQWNGaWxlLFxuICBDZGRBY0xpc3RSZXN1bHQsXG4gIENkZEFkZFJ1bGVSZXF1ZXN0LFxuICBDZGRDb250ZW50UmVzdWx0LFxuICBDZGRGaWxlVHlwZSxcbiAgQ2RkUnVsZURldGFpbCxcbiAgQ2RkUnVsZUVudHJ5LFxuICBDZGRSdWxlU3VtbWFyeSxcbiAgQ2RkVHJlZU5vZGUsXG59IGZyb20gXCIuL2NkZC10eXBlc1wiO1xuXG5leHBvcnQgdHlwZSB7XG4gIENkZEFjRW50cnksXG4gIENkZEFjRmlsZSxcbiAgQ2RkQWNMaXN0UmVzdWx0LFxuICBDZGRBZGRSdWxlUmVxdWVzdCxcbiAgQ2RkQ29udGVudFJlc3VsdCxcbiAgQ2RkRmlsZVR5cGUsXG4gIENkZFJ1bGVEZXRhaWwsXG4gIENkZFJ1bGVFbnRyeSxcbiAgQ2RkUnVsZVN1bW1hcnksXG4gIENkZFRyZWVOb2RlLFxufSBmcm9tIFwiLi9jZGQtdHlwZXNcIjtcblxuLyoqIGNvbnRyYWN0LyDrlJTroInthLDrpqwg7KCI64yAIOqyveuhnCDrsJjtmZggKGFwaVJvb3RQYXRoIOq4sOykgCkgKi9cbmZ1bmN0aW9uIGdldENvbnRyYWN0RGlyKCk6IHN0cmluZyB7XG4gIHJldHVybiBwYXRoLmpvaW4oU29uYW11LmFwaVJvb3RQYXRoLCBcIi4uXCIsIFwiLi5cIiwgXCJjb250cmFjdFwiKTtcbn1cblxuLyoqIO2UhOuhnOygne2KuCDro6jtirgg6rK966GcIOuwmO2ZmCAqL1xuZnVuY3Rpb24gZ2V0UHJvamVjdFJvb3QoKTogc3RyaW5nIHtcbiAgcmV0dXJuIHBhdGguam9pbihTb25hbXUuYXBpUm9vdFBhdGgsIFwiLi5cIiwgXCIuLlwiKTtcbn1cblxuLyoqIOqyveuhnOqwgCBjb250cmFjdC8g65SU66CJ7YSw66asIOuCtOu2gOyduOyngCDqsoDspp0gKi9cbmZ1bmN0aW9uIGFzc2VydEluc2lkZUNvbnRyYWN0RGlyKGZpbGVQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3QgY29udHJhY3REaXIgPSBnZXRDb250cmFjdERpcigpO1xuICBjb25zdCByZXNvbHZlZCA9IHBhdGgucmVzb2x2ZShjb250cmFjdERpciwgZmlsZVBhdGgpO1xuICBpZiAoIXJlc29sdmVkLnN0YXJ0c1dpdGgoY29udHJhY3REaXIgKyBwYXRoLnNlcCkgJiYgcmVzb2x2ZWQgIT09IGNvbnRyYWN0RGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGDqsr3roZzqsIAgY29udHJhY3QvIOuUlOugie2EsOumrCDrsJbsnYQg7LC47KGw7ZWp64uI64ukOiAke2ZpbGVQYXRofWApO1xuICB9XG59XG5cbi8qKiDtjIzsnbzrqoXsl5DshJwgQ2RkRmlsZVR5cGUg7YyQ67OEICovXG5mdW5jdGlvbiBkZXRlY3RGaWxlVHlwZShmaWxlTmFtZTogc3RyaW5nKTogQ2RkRmlsZVR5cGUgfCB1bmRlZmluZWQge1xuICBpZiAoZmlsZU5hbWUuZW5kc1dpdGgoXCIuY29udHJhY3QubWRcIikpIHJldHVybiBcImNvbnRyYWN0XCI7XG4gIGlmIChmaWxlTmFtZS5lbmRzV2l0aChcIi5ydWxlcy5qc29uXCIpKSByZXR1cm4gXCJydWxlc1wiO1xuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKiog65SU66CJ7YSw66as66W8IOyerOq3gCDtg5Dsg4ntlZjsl6wgQ2RkVHJlZU5vZGUg7Yq466as66W8IOyDneyEsSAqL1xuZnVuY3Rpb24gc2NhbkRpcmVjdG9yeShkaXJQYXRoOiBzdHJpbmcsIHJlbGF0aXZlVG86IHN0cmluZyk6IENkZFRyZWVOb2RlW10ge1xuICBjb25zdCBlbnRyaWVzID0gZnMucmVhZGRpclN5bmMoZGlyUGF0aCwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pO1xuICBjb25zdCBub2RlczogQ2RkVHJlZU5vZGVbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgIGNvbnN0IGZ1bGxQYXRoID0gcGF0aC5qb2luKGRpclBhdGgsIGVudHJ5Lm5hbWUpO1xuICAgIGNvbnN0IHJlbFBhdGggPSBwYXRoLnJlbGF0aXZlKHJlbGF0aXZlVG8sIGZ1bGxQYXRoKTtcblxuICAgIGlmIChlbnRyeS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBpZiAoZW50cnkubmFtZSA9PT0gXCJydWxlc1wiKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IGNoaWxkcmVuID0gc2NhbkRpcmVjdG9yeShmdWxsUGF0aCwgcmVsYXRpdmVUbyk7XG4gICAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICBub2Rlcy5wdXNoKHtcbiAgICAgICAgICBuYW1lOiBlbnRyeS5uYW1lLFxuICAgICAgICAgIHBhdGg6IHJlbFBhdGgsXG4gICAgICAgICAgdHlwZTogXCJkaXJlY3RvcnlcIixcbiAgICAgICAgICBjaGlsZHJlbixcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChlbnRyeS5pc0ZpbGUoKSkge1xuICAgICAgY29uc3QgZmlsZVR5cGUgPSBkZXRlY3RGaWxlVHlwZShlbnRyeS5uYW1lKTtcbiAgICAgIGlmIChmaWxlVHlwZSAmJiBmaWxlVHlwZSAhPT0gXCJydWxlc1wiKSB7XG4gICAgICAgIG5vZGVzLnB1c2goe1xuICAgICAgICAgIG5hbWU6IGVudHJ5Lm5hbWUsXG4gICAgICAgICAgcGF0aDogcmVsUGF0aCxcbiAgICAgICAgICB0eXBlOiBcImZpbGVcIixcbiAgICAgICAgICBmaWxlVHlwZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5vZGVzO1xufVxuXG4vKiogY29udHJhY3QvIOuUlOugie2EsOumrOydmCDtirjrpqwg6rWs7KGw66W8IOuwmO2ZmCAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENkZFRyZWUoKTogeyBleGlzdHM6IGJvb2xlYW47IHRyZWU6IENkZFRyZWVOb2RlW10gfSB7XG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGNvbnRyYWN0RGlyKSkge1xuICAgIHJldHVybiB7IGV4aXN0czogZmFsc2UsIHRyZWU6IFtdIH07XG4gIH1cbiAgY29uc3QgdHJlZSA9IHNjYW5EaXJlY3RvcnkoY29udHJhY3REaXIsIGNvbnRyYWN0RGlyKTtcbiAgcmV0dXJuIHsgZXhpc3RzOiB0cnVlLCB0cmVlIH07XG59XG5cbi8qKiDtjIzsnbwg64K07Jqp7J2EIOydveyWtCDrsJjtmZggKGNvbnRyYWN0Lm1kIOKGkiBtYXJrZG93biDsm5DrrLgsIHJ1bGVzLmpzb24g4oaSIEpTT04g66y47J6Q7Je0KSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlYWRDb250ZW50KGZpbGVQYXRoOiBzdHJpbmcpOiBDZGRDb250ZW50UmVzdWx0IHtcbiAgYXNzZXJ0SW5zaWRlQ29udHJhY3REaXIoZmlsZVBhdGgpO1xuXG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgY29uc3QgYWJzUGF0aCA9IHBhdGgucmVzb2x2ZShjb250cmFjdERpciwgZmlsZVBhdGgpO1xuXG4gIGlmICghZnMuZXhpc3RzU3luYyhhYnNQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihg7YyM7J287J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukOiAke2ZpbGVQYXRofWApO1xuICB9XG5cbiAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhhYnNQYXRoLCBcInV0Zi04XCIpO1xuICBjb25zdCBmaWxlVHlwZSA9IGRldGVjdEZpbGVUeXBlKHBhdGguYmFzZW5hbWUoZmlsZVBhdGgpKTtcblxuICByZXR1cm4ge1xuICAgIGNvbnRlbnQsXG4gICAgZmlsZVR5cGU6IGZpbGVUeXBlID8/IFwiY29udHJhY3RcIixcbiAgfTtcbn1cblxuLyoqIO2MjOydvOydhCDsmbjrtoAg7JeQ65SU7YSw66GcIOyngeygkSDtjrjsp5EgKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlZGl0Q29udGVudChcbiAgZmlsZVBhdGg6IHN0cmluZyxcbik6IFByb21pc2U8eyBzdWNjZXNzOiBib29sZWFuOyBmaWxlUGF0aDogc3RyaW5nIH0+IHtcbiAgYXNzZXJ0SW5zaWRlQ29udHJhY3REaXIoZmlsZVBhdGgpO1xuXG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgY29uc3QgYWJzUGF0aCA9IHBhdGgucmVzb2x2ZShjb250cmFjdERpciwgZmlsZVBhdGgpO1xuXG4gIGlmICghZnMuZXhpc3RzU3luYyhhYnNQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihg7YyM7J287J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukOiAke2ZpbGVQYXRofWApO1xuICB9XG5cbiAgY29uc3QgZWRpdG9yID0gcmVzb2x2ZUVkaXRvckNsaSgpO1xuICBhd2FpdCBydW5FZGl0b3IoZWRpdG9yLCBhYnNQYXRoKTtcblxuICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBmaWxlUGF0aCB9O1xufVxuXG4vKiog7JeQ65SU7YSw67OEIOyVsSDrsojrk6Qg64K0IENMSSDqsr3roZwgKyAtLXdhaXQg7ZSM656Y6re4IOunpO2VkSAqL1xuY29uc3QgRURJVE9SX0NMSV9NQVA6IFJlY29yZDxzdHJpbmcsIHsgY2xpOiBzdHJpbmc7IHdhaXRGbGFnOiBzdHJpbmcgfT4gPSB7XG4gIFwiVmlzdWFsIFN0dWRpbyBDb2RlXCI6IHsgY2xpOiBcIkNvbnRlbnRzL1Jlc291cmNlcy9hcHAvYmluL2NvZGVcIiwgd2FpdEZsYWc6IFwiLS13YWl0XCIgfSxcbiAgWmVkOiB7IGNsaTogXCJDb250ZW50cy9NYWNPUy9jbGlcIiwgd2FpdEZsYWc6IFwiLS13YWl0XCIgfSxcbiAgQ3Vyc29yOiB7IGNsaTogXCJDb250ZW50cy9SZXNvdXJjZXMvYXBwL2Jpbi9jdXJzb3JcIiwgd2FpdEZsYWc6IFwiLS13YWl0XCIgfSxcbn07XG5cbi8qKiDslbEg67KI65OkIENMSSDqsr3roZzrpbwgcmVzb2x2ZS4gd2FpdD1mYWxzZeydtOuptCAtLXdhaXQg7ZSM656Y6re466W8IOyDneuetSAqL1xuZnVuY3Rpb24gcmVzb2x2ZUVkaXRvckNsaShvcHRpb25zPzogeyB3YWl0PzogYm9vbGVhbiB9KTogeyBiaW46IHN0cmluZzsgYXJnczogc3RyaW5nW10gfSB7XG4gIGNvbnN0IHdhaXQgPSBvcHRpb25zPy53YWl0ID8/IHRydWU7XG4gIGNvbnN0IGFwcE5hbWUgPSBTb25hbXUuY29uZmlnLmV4dGVybmFsRWRpdG9yID8/IFwiVmlzdWFsIFN0dWRpbyBDb2RlXCI7XG4gIGNvbnN0IG1hcHBpbmcgPSBFRElUT1JfQ0xJX01BUFthcHBOYW1lXTtcbiAgaWYgKCFtYXBwaW5nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYOyngOybkOuQmOyngCDslYrripQg7JeQ65SU7YSw7J6F64uI64ukOiAke2FwcE5hbWV9ICjsp4Dsm5A6ICR7T2JqZWN0LmtleXMoRURJVE9SX0NMSV9NQVApLmpvaW4oXCIsIFwiKX0pYCxcbiAgICApO1xuICB9XG5cbiAgY29uc3Qgc2VhcmNoUGF0aHMgPSBbXG4gICAgYC9BcHBsaWNhdGlvbnMvJHthcHBOYW1lfS5hcHBgLFxuICAgIGAke29zLmhvbWVkaXIoKX0vQXBwbGljYXRpb25zLyR7YXBwTmFtZX0uYXBwYCxcbiAgXTtcbiAgY29uc3QgYnVuZGxlUGF0aCA9IHNlYXJjaFBhdGhzLmZpbmQoKHApID0+IGZzLmV4aXN0c1N5bmMocCkpO1xuICBpZiAoIWJ1bmRsZVBhdGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYOyVsSDrsojrk6TsnYQg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7YXBwTmFtZX0gKC9BcHBsaWNhdGlvbnMg7ZmV7J24KWApO1xuICB9XG5cbiAgY29uc3QgY2xpQmluID0gcGF0aC5qb2luKGJ1bmRsZVBhdGgsIG1hcHBpbmcuY2xpKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGNsaUJpbikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYOyXkOuUlO2EsCBDTEnrpbwg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7Y2xpQmlufWApO1xuICB9XG5cbiAgcmV0dXJuIHsgYmluOiBjbGlCaW4sIGFyZ3M6IHdhaXQgPyBbbWFwcGluZy53YWl0RmxhZ10gOiBbXSB9O1xufVxuXG4vKiog7JeQ65SU7YSwIENMSeulvCDsi6TtlontlZjqs6Ag7YOt7J20IOuLq+2ekCDrlYzquYzsp4Ag64yA6riwICovXG5mdW5jdGlvbiBydW5FZGl0b3IoZWRpdG9yOiB7IGJpbjogc3RyaW5nOyBhcmdzOiBzdHJpbmdbXSB9LCBmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgY2hpbGQgPSBzcGF3bihlZGl0b3IuYmluLCBbLi4uZWRpdG9yLmFyZ3MsIGZpbGVQYXRoXSwge1xuICAgICAgc3RkaW86IFwiaW5oZXJpdFwiLFxuICAgIH0pO1xuXG4gICAgY2hpbGQub24oXCJlcnJvclwiLCAoZXJyKSA9PiB7XG4gICAgICByZWplY3QobmV3IEVycm9yKGDsl5DrlJTthLAg7Iuk7ZaJIOyLpO2MqCAoJHtlZGl0b3IuYmlufSk6ICR7ZXJyLm1lc3NhZ2V9YCkpO1xuICAgIH0pO1xuXG4gICAgY2hpbGQub24oXCJjbG9zZVwiLCAoY29kZSkgPT4ge1xuICAgICAgaWYgKGNvZGUgPT09IDApIHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihg7JeQ65SU7YSw6rCAIOu5hOygleyDgSDsooXro4zrkJjsl4jsirXri4jri6QgKGV4aXQgY29kZTogJHtjb2RlfSlgKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKiog7IaM7IqkIO2MjOydvOydhCDsmbjrtoAg7JeQ65SU7YSw66GcIOyXtOq4sCAo64yA6riw7ZWY7KeAIOyViuydjCkgKi9cbmV4cG9ydCBmdW5jdGlvbiBvcGVuU291cmNlRmlsZShmaWxlUGF0aDogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IGFic1BhdGggPSBwYXRoLmlzQWJzb2x1dGUoZmlsZVBhdGgpID8gZmlsZVBhdGggOiBwYXRoLnJlc29sdmUoU29uYW11LmFwaVJvb3RQYXRoLCBmaWxlUGF0aCk7XG5cbiAgaWYgKCFmcy5leGlzdHNTeW5jKGFic1BhdGgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGDtjIzsnbzsnYQg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7ZmlsZVBhdGh9YCk7XG4gIH1cblxuICBjb25zdCBlZGl0b3IgPSByZXNvbHZlRWRpdG9yQ2xpKHsgd2FpdDogZmFsc2UgfSk7XG4gIGNvbnN0IGNoaWxkID0gc3Bhd24oZWRpdG9yLmJpbiwgWy4uLmVkaXRvci5hcmdzLCBhYnNQYXRoXSwge1xuICAgIHN0ZGlvOiBcImlnbm9yZVwiLFxuICAgIGRldGFjaGVkOiB0cnVlLFxuICB9KTtcbiAgY2hpbGQudW5yZWYoKTtcbn1cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBSdWxlcyBBUElcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG4vKiogY29udHJhY3QvcnVsZXMvIOuUlOugie2EsOumrCDrgrQgLnJ1bGVzLmpzb24g7YyM7J28IOuqqeuhnSDrsJjtmZggKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXN0UnVsZXMoKTogeyBydWxlczogQ2RkUnVsZVN1bW1hcnlbXSB9IHtcbiAgY29uc3QgY29udHJhY3REaXIgPSBnZXRDb250cmFjdERpcigpO1xuICBjb25zdCBydWxlc0RpciA9IHBhdGguam9pbihjb250cmFjdERpciwgXCJydWxlc1wiKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKHJ1bGVzRGlyKSkgcmV0dXJuIHsgcnVsZXM6IFtdIH07XG5cbiAgY29uc3QgZW50cmllcyA9IGZzLnJlYWRkaXJTeW5jKHJ1bGVzRGlyLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gIGNvbnN0IHJ1bGVzOiBDZGRSdWxlU3VtbWFyeVtdID0gW107XG5cbiAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgaWYgKCFlbnRyeS5pc0ZpbGUoKSB8fCAhZW50cnkubmFtZS5lbmRzV2l0aChcIi5ydWxlcy5qc29uXCIpKSBjb250aW51ZTtcblxuICAgIGNvbnN0IGtleSA9IGVudHJ5Lm5hbWUucmVwbGFjZSgvXFwucnVsZXNcXC5qc29uJC8sIFwiXCIpO1xuICAgIGNvbnN0IHJlbFBhdGggPSBgcnVsZXMvJHtlbnRyeS5uYW1lfWA7XG4gICAgY29uc3QgYWJzUGF0aCA9IHBhdGguam9pbihydWxlc0RpciwgZW50cnkubmFtZSk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmF3ID0gZnMucmVhZEZpbGVTeW5jKGFic1BhdGgsIFwidXRmLThcIik7XG4gICAgICBjb25zdCBkb2MgPSBKU09OLnBhcnNlKHJhdykgYXMgeyBkZXNjcmlwdGlvbj86IHN0cmluZzsgcnVsZXM/OiB1bmtub3duW10gfTtcbiAgICAgIHJ1bGVzLnB1c2goe1xuICAgICAgICBrZXksXG4gICAgICAgIHBhdGg6IHJlbFBhdGgsXG4gICAgICAgIGRlc2NyaXB0aW9uOiB0eXBlb2YgZG9jLmRlc2NyaXB0aW9uID09PSBcInN0cmluZ1wiID8gZG9jLmRlc2NyaXB0aW9uIDogXCJcIixcbiAgICAgICAgcnVsZUNvdW50OiBBcnJheS5pc0FycmF5KGRvYy5ydWxlcykgPyBkb2MucnVsZXMubGVuZ3RoIDogMCxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgcnVsZXMucHVzaCh7XG4gICAgICAgIGtleSxcbiAgICAgICAgcGF0aDogcmVsUGF0aCxcbiAgICAgICAgZGVzY3JpcHRpb246IFwiXCIsXG4gICAgICAgIHJ1bGVDb3VudDogMCxcbiAgICAgICAgcGFyc2VFcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgcnVsZXMgfTtcbn1cblxuLyoqIHJ1bGVzIO2MjOydvCDsg4HshLgg67CY7ZmYICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZFJ1bGUocnVsZUtleTogc3RyaW5nKTogQ2RkUnVsZURldGFpbCB7XG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgY29uc3QgYWJzUGF0aCA9IHBhdGguam9pbihjb250cmFjdERpciwgXCJydWxlc1wiLCBgJHtydWxlS2V5fS5ydWxlcy5qc29uYCk7XG5cbiAgaWYgKCFmcy5leGlzdHNTeW5jKGFic1BhdGgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBSdWxlcyDtjIzsnbzsnYQg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7cnVsZUtleX1gKTtcbiAgfVxuXG4gIGNvbnN0IHJhdyA9IGZzLnJlYWRGaWxlU3luYyhhYnNQYXRoLCBcInV0Zi04XCIpO1xuICBjb25zdCBkb2MgPSBKU09OLnBhcnNlKHJhdykgYXMgeyBkZXNjcmlwdGlvbj86IHN0cmluZzsgcnVsZXM/OiBDZGRSdWxlRW50cnlbXSB9O1xuXG4gIHJldHVybiB7XG4gICAga2V5OiBydWxlS2V5LFxuICAgIHBhdGg6IGBydWxlcy8ke3J1bGVLZXl9LnJ1bGVzLmpzb25gLFxuICAgIGRlc2NyaXB0aW9uOiB0eXBlb2YgZG9jLmRlc2NyaXB0aW9uID09PSBcInN0cmluZ1wiID8gZG9jLmRlc2NyaXB0aW9uIDogXCJcIixcbiAgICBydWxlczogQXJyYXkuaXNBcnJheShkb2MucnVsZXMpID8gZG9jLnJ1bGVzIDogW10sXG4gIH07XG59XG5cbi8qKiBydWxlcyDtjIzsnbzsl5Ag6rec7LmZIOy2lOqwgCAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZFJ1bGUocmVxOiBDZGRBZGRSdWxlUmVxdWVzdCk6IENkZFJ1bGVEZXRhaWwge1xuICBjb25zdCBjb250cmFjdERpciA9IGdldENvbnRyYWN0RGlyKCk7XG4gIGNvbnN0IHJ1bGVzRGlyID0gcGF0aC5qb2luKGNvbnRyYWN0RGlyLCBcInJ1bGVzXCIpO1xuICBjb25zdCBhYnNQYXRoID0gcGF0aC5qb2luKHJ1bGVzRGlyLCBgJHtyZXEucnVsZUtleX0ucnVsZXMuanNvbmApO1xuXG4gIGlmICghZnMuZXhpc3RzU3luYyhhYnNQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgUnVsZXMg7YyM7J287J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukOiAke3JlcS5ydWxlS2V5fWApO1xuICB9XG5cbiAgY29uc3QgcmF3ID0gZnMucmVhZEZpbGVTeW5jKGFic1BhdGgsIFwidXRmLThcIik7XG4gIGNvbnN0IGRvYyA9IEpTT04ucGFyc2UocmF3KSBhcyB7IGRlc2NyaXB0aW9uPzogc3RyaW5nOyBydWxlcz86IENkZFJ1bGVFbnRyeVtdIH07XG4gIGNvbnN0IHJ1bGVzOiBDZGRSdWxlRW50cnlbXSA9IEFycmF5LmlzQXJyYXkoZG9jLnJ1bGVzKSA/IGRvYy5ydWxlcyA6IFtdO1xuXG4gIGNvbnN0IG5leHRJZCA9IGdlbmVyYXRlTmV4dFJ1bGVJZChydWxlcyk7XG4gIGNvbnN0IG5ld0VudHJ5OiBDZGRSdWxlRW50cnkgPSB7XG4gICAgaWQ6IG5leHRJZCxcbiAgICB3aGVuOiByZXEud2hlbixcbiAgICBpbnN0cnVjdGlvbjogcmVxLmluc3RydWN0aW9uLFxuICB9O1xuICBpZiAocmVxLmV4YW1wbGVzICYmIHJlcS5leGFtcGxlcy5sZW5ndGggPiAwKSB7XG4gICAgbmV3RW50cnkuZXhhbXBsZXMgPSByZXEuZXhhbXBsZXM7XG4gIH1cblxuICBydWxlcy5wdXNoKG5ld0VudHJ5KTtcbiAgZG9jLnJ1bGVzID0gcnVsZXM7XG5cbiAgZnMud3JpdGVGaWxlU3luYyhhYnNQYXRoLCBgJHtKU09OLnN0cmluZ2lmeShkb2MsIG51bGwsIDIpfVxcbmAsIFwidXRmLThcIik7XG5cbiAgcmV0dXJuIHtcbiAgICBrZXk6IHJlcS5ydWxlS2V5LFxuICAgIHBhdGg6IGBydWxlcy8ke3JlcS5ydWxlS2V5fS5ydWxlcy5qc29uYCxcbiAgICBkZXNjcmlwdGlvbjogdHlwZW9mIGRvYy5kZXNjcmlwdGlvbiA9PT0gXCJzdHJpbmdcIiA/IGRvYy5kZXNjcmlwdGlvbiA6IFwiXCIsXG4gICAgcnVsZXMsXG4gIH07XG59XG5cbi8qKiDquLDsobQgaWQg7Yyo7YS07J2EIOu2hOyEne2VmOyXrCDri6TsnYwg7Iic67KIIGlkIOyDneyEsSAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVOZXh0UnVsZUlkKHJ1bGVzOiBDZGRSdWxlRW50cnlbXSk6IHN0cmluZyB7XG4gIGlmIChydWxlcy5sZW5ndGggPT09IDApIHJldHVybiBcIlItMDAxXCI7XG5cbiAgY29uc3QgbnVtZXJpY1BhdHRlcm4gPSAvXiguKz8pKFxcZCspJC87XG4gIGxldCBiZXN0UHJlZml4ID0gXCJSLVwiO1xuICBsZXQgbWF4TnVtID0gMDtcblxuICBmb3IgKGNvbnN0IHJ1bGUgb2YgcnVsZXMpIHtcbiAgICBjb25zdCBtYXRjaCA9IG51bWVyaWNQYXR0ZXJuLmV4ZWMocnVsZS5pZCk7XG4gICAgaWYgKG1hdGNoKSB7XG4gICAgICBjb25zdCBwcmVmaXggPSBtYXRjaFsxXTtcbiAgICAgIGNvbnN0IG51bSA9IE51bWJlci5wYXJzZUludChtYXRjaFsyXSwgMTApO1xuICAgICAgaWYgKG51bSA+IG1heE51bSkge1xuICAgICAgICBiZXN0UHJlZml4ID0gcHJlZml4O1xuICAgICAgICBtYXhOdW0gPSBudW07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc3QgbmV4dE51bSA9IG1heE51bSArIDE7XG4gIGNvbnN0IHBhZExlbiA9IE1hdGgubWF4KDMsIFN0cmluZyhtYXhOdW0pLmxlbmd0aCk7XG4gIHJldHVybiBgJHtiZXN0UHJlZml4fSR7U3RyaW5nKG5leHROdW0pLnBhZFN0YXJ0KHBhZExlbiwgXCIwXCIpfWA7XG59XG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQUMgQVBJIChtb2R1bGVzL2NkZCBhYy1saXN0IO2MjOyLsSDroZzsp4Eg67O17IKsKVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cbi8qKiBkZXNjcmliZS90ZXN0IO2MqO2EtCDtjIzsi7EgKi9cbmZ1bmN0aW9uIHBhcnNlQWNFbnRyaWVzKGNvbnRlbnQ6IHN0cmluZyk6IENkZEFjRW50cnlbXSB7XG4gIGNvbnN0IGVudHJpZXM6IENkZEFjRW50cnlbXSA9IFtdO1xuICBjb25zdCBsaW5lcyA9IGNvbnRlbnQuc3BsaXQoXCJcXG5cIik7XG5cbiAgbGV0IGN1cnJlbnREZXNjcmliZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIGxldCBkZXNjcmliZURlcHRoID0gMDtcbiAgbGV0IGJyYWNlRGVwdGggPSAwO1xuICBsZXQgcGVuZGluZ1Rlc3RBcyA9IGZhbHNlO1xuICBsZXQgdGVzdEFzQnJhY2VEZXB0aCA9IDA7XG4gIGxldCB0ZXN0QXNOZWVkTmFtZSA9IGZhbHNlO1xuXG4gIGZvciAoY29uc3QgbGluZSBvZiBsaW5lcykge1xuICAgIGNvbnN0IHRyaW1tZWQgPSBsaW5lLnRyaW0oKTtcblxuICAgIGNvbnN0IGRlc2NyaWJlTWF0Y2ggPSB0cmltbWVkLm1hdGNoKC9eZGVzY3JpYmVcXChbXCInYF0oLis/KVtcIidgXS8pO1xuICAgIGlmIChkZXNjcmliZU1hdGNoKSB7XG4gICAgICBjdXJyZW50RGVzY3JpYmUgPSBkZXNjcmliZU1hdGNoWzFdO1xuICAgICAgZGVzY3JpYmVEZXB0aCA9IGJyYWNlRGVwdGg7XG4gICAgfVxuXG4gICAgY29uc3QgdGVzdE1hdGNoID0gdHJpbW1lZC5tYXRjaCgvXig/OnRlc3R8aXQpXFwoW1wiJ2BdKC4rPylbXCInYF0vKTtcbiAgICBpZiAodGVzdE1hdGNoKSB7XG4gICAgICBlbnRyaWVzLnB1c2goe1xuICAgICAgICBkZXNjcmliZTogY3VycmVudERlc2NyaWJlLFxuICAgICAgICB0ZXN0OiB0ZXN0TWF0Y2hbMV0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoIXBlbmRpbmdUZXN0QXMgJiYgdHJpbW1lZC5tYXRjaCgvXnRlc3RBc1xccypcXCgvKSkge1xuICAgICAgY29uc3QgaW5saW5lTWF0Y2ggPSB0cmltbWVkLm1hdGNoKC9edGVzdEFzXFxzKlxcKFxccypcXHtbXn1dKlxcfVxccyosXFxzKltcIidgXSguKz8pW1wiJ2BdLyk7XG4gICAgICBpZiAoaW5saW5lTWF0Y2gpIHtcbiAgICAgICAgZW50cmllcy5wdXNoKHsgZGVzY3JpYmU6IGN1cnJlbnREZXNjcmliZSwgdGVzdDogaW5saW5lTWF0Y2hbMV0gfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZW5kaW5nVGVzdEFzID0gdHJ1ZTtcbiAgICAgICAgdGVzdEFzQnJhY2VEZXB0aCA9IDA7XG4gICAgICAgIHRlc3RBc05lZWROYW1lID0gZmFsc2U7XG4gICAgICAgIGZvciAoY29uc3QgY2ggb2YgdHJpbW1lZCkge1xuICAgICAgICAgIGlmIChjaCA9PT0gXCJ7XCIpIHRlc3RBc0JyYWNlRGVwdGgrKztcbiAgICAgICAgICBpZiAoY2ggPT09IFwifVwiKSB0ZXN0QXNCcmFjZURlcHRoLS07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRlc3RBc0JyYWNlRGVwdGggPD0gMCkge1xuICAgICAgICAgIHRlc3RBc05lZWROYW1lID0gdHJ1ZTtcbiAgICAgICAgICBjb25zdCBuYW1lTWF0Y2ggPSB0cmltbWVkLm1hdGNoKC99XFxzKixcXHMqW1wiJ2BdKC4rPylbXCInYF0vKTtcbiAgICAgICAgICBpZiAobmFtZU1hdGNoKSB7XG4gICAgICAgICAgICBlbnRyaWVzLnB1c2goeyBkZXNjcmliZTogY3VycmVudERlc2NyaWJlLCB0ZXN0OiBuYW1lTWF0Y2hbMV0gfSk7XG4gICAgICAgICAgICBwZW5kaW5nVGVzdEFzID0gZmFsc2U7XG4gICAgICAgICAgICB0ZXN0QXNOZWVkTmFtZSA9IGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocGVuZGluZ1Rlc3RBcykge1xuICAgICAgaWYgKCF0ZXN0QXNOZWVkTmFtZSkge1xuICAgICAgICBmb3IgKGNvbnN0IGNoIG9mIHRyaW1tZWQpIHtcbiAgICAgICAgICBpZiAoY2ggPT09IFwie1wiKSB0ZXN0QXNCcmFjZURlcHRoKys7XG4gICAgICAgICAgaWYgKGNoID09PSBcIn1cIikgdGVzdEFzQnJhY2VEZXB0aC0tO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0ZXN0QXNCcmFjZURlcHRoIDw9IDApIHtcbiAgICAgICAgICB0ZXN0QXNOZWVkTmFtZSA9IHRydWU7XG4gICAgICAgICAgY29uc3QgbmFtZU1hdGNoID0gdHJpbW1lZC5tYXRjaCgvfVxccyosXFxzKltcIidgXSguKz8pW1wiJ2BdLyk7XG4gICAgICAgICAgaWYgKG5hbWVNYXRjaCkge1xuICAgICAgICAgICAgZW50cmllcy5wdXNoKHsgZGVzY3JpYmU6IGN1cnJlbnREZXNjcmliZSwgdGVzdDogbmFtZU1hdGNoWzFdIH0pO1xuICAgICAgICAgICAgcGVuZGluZ1Rlc3RBcyA9IGZhbHNlO1xuICAgICAgICAgICAgdGVzdEFzTmVlZE5hbWUgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IG5hbWVNYXRjaCA9IHRyaW1tZWQubWF0Y2goL15bXCInYF0oLis/KVtcIidgXS8pO1xuICAgICAgICBpZiAobmFtZU1hdGNoKSB7XG4gICAgICAgICAgZW50cmllcy5wdXNoKHsgZGVzY3JpYmU6IGN1cnJlbnREZXNjcmliZSwgdGVzdDogbmFtZU1hdGNoWzFdIH0pO1xuICAgICAgICAgIHBlbmRpbmdUZXN0QXMgPSBmYWxzZTtcbiAgICAgICAgICB0ZXN0QXNOZWVkTmFtZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBjaCBvZiB0cmltbWVkKSB7XG4gICAgICBpZiAoY2ggPT09IFwie1wiKSBicmFjZURlcHRoKys7XG4gICAgICBpZiAoY2ggPT09IFwifVwiKSB7XG4gICAgICAgIGJyYWNlRGVwdGgtLTtcbiAgICAgICAgaWYgKGN1cnJlbnREZXNjcmliZSAmJiBicmFjZURlcHRoIDw9IGRlc2NyaWJlRGVwdGgpIHtcbiAgICAgICAgICBjdXJyZW50RGVzY3JpYmUgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGVudHJpZXM7XG59XG5cbi8qKiDtlITroZzsoJ3tirgg64K0ICoudGVzdC50cyDtjIzsnbzsnYQg7Iqk7LqU7ZWY7JesIEFDIOuqqeuhnSDrsJjtmZggKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBY0xpc3QoKTogQ2RkQWNMaXN0UmVzdWx0IHtcbiAgY29uc3QgcHJvamVjdFJvb3QgPSBnZXRQcm9qZWN0Um9vdCgpO1xuICBjb25zdCBmaWxlcyA9IGZpbmRUZXN0RmlsZXMocHJvamVjdFJvb3QpO1xuXG4gIGNvbnN0IGFjRmlsZXM6IENkZEFjRmlsZVtdID0gW107XG4gIGZvciAoY29uc3QgYWJzUGF0aCBvZiBmaWxlcykge1xuICAgIGNvbnN0IGNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmMoYWJzUGF0aCwgXCJ1dGYtOFwiKTtcbiAgICBjb25zdCBlbnRyaWVzID0gcGFyc2VBY0VudHJpZXMoY29udGVudCk7XG4gICAgaWYgKGVudHJpZXMubGVuZ3RoID4gMCkge1xuICAgICAgYWNGaWxlcy5wdXNoKHtcbiAgICAgICAgcGF0aDogcGF0aC5yZWxhdGl2ZShwcm9qZWN0Um9vdCwgYWJzUGF0aCksXG4gICAgICAgIGVudHJpZXMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBjb25zdCB0b3RhbCA9IGFjRmlsZXMucmVkdWNlKChzdW0sIGYpID0+IHN1bSArIGYuZW50cmllcy5sZW5ndGgsIDApO1xuICByZXR1cm4geyBmaWxlczogYWNGaWxlcywgdG90YWwgfTtcbn1cblxuLyoqICoudGVzdC50cyDtjIzsnbzsnYQg7J6s6reAIO2DkOyDiSAobm9kZV9tb2R1bGVzLCBkaXN0IOygnOyZuCkgKi9cbmZ1bmN0aW9uIGZpbmRUZXN0RmlsZXMoZGlyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHJlc3VsdHM6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IElHTk9SRSA9IG5ldyBTZXQoW1wibm9kZV9tb2R1bGVzXCIsIFwiZGlzdFwiLCBcIi5naXRcIiwgXCJjb250cmFjdFwiXSk7XG5cbiAgZnVuY3Rpb24gd2FsayhjdXJyZW50RGlyOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBsZXQgZW50cmllczogZnMuRGlyZW50W107XG4gICAgdHJ5IHtcbiAgICAgIGVudHJpZXMgPSBmcy5yZWFkZGlyU3luYyhjdXJyZW50RGlyLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgaWYgKElHTk9SRS5oYXMoZW50cnkubmFtZSkpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4oY3VycmVudERpciwgZW50cnkubmFtZSk7XG4gICAgICBpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICB3YWxrKGZ1bGxQYXRoKTtcbiAgICAgIH0gZWxzZSBpZiAoZW50cnkuaXNGaWxlKCkgJiYgZW50cnkubmFtZS5lbmRzV2l0aChcIi50ZXN0LnRzXCIpKSB7XG4gICAgICAgIHJlc3VsdHMucHVzaChmdWxsUGF0aCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgd2FsayhkaXIpO1xuICByZXN1bHRzLnNvcnQoKTtcbiAgcmV0dXJuIHJlc3VsdHM7XG59XG4iXSwibmFtZXMiOlsic3Bhd24iLCJmcyIsIm9zIiwicGF0aCIsIlNvbmFtdSIsImdldENvbnRyYWN0RGlyIiwiam9pbiIsImFwaVJvb3RQYXRoIiwiZ2V0UHJvamVjdFJvb3QiLCJhc3NlcnRJbnNpZGVDb250cmFjdERpciIsImZpbGVQYXRoIiwiY29udHJhY3REaXIiLCJyZXNvbHZlZCIsInJlc29sdmUiLCJzdGFydHNXaXRoIiwic2VwIiwiRXJyb3IiLCJkZXRlY3RGaWxlVHlwZSIsImZpbGVOYW1lIiwiZW5kc1dpdGgiLCJ1bmRlZmluZWQiLCJzY2FuRGlyZWN0b3J5IiwiZGlyUGF0aCIsInJlbGF0aXZlVG8iLCJlbnRyaWVzIiwicmVhZGRpclN5bmMiLCJ3aXRoRmlsZVR5cGVzIiwibm9kZXMiLCJlbnRyeSIsImZ1bGxQYXRoIiwibmFtZSIsInJlbFBhdGgiLCJyZWxhdGl2ZSIsImlzRGlyZWN0b3J5IiwiY2hpbGRyZW4iLCJsZW5ndGgiLCJwdXNoIiwidHlwZSIsImlzRmlsZSIsImZpbGVUeXBlIiwiZ2V0Q2RkVHJlZSIsImV4aXN0c1N5bmMiLCJleGlzdHMiLCJ0cmVlIiwicmVhZENvbnRlbnQiLCJhYnNQYXRoIiwiY29udGVudCIsInJlYWRGaWxlU3luYyIsImJhc2VuYW1lIiwiZWRpdENvbnRlbnQiLCJlZGl0b3IiLCJyZXNvbHZlRWRpdG9yQ2xpIiwicnVuRWRpdG9yIiwic3VjY2VzcyIsIkVESVRPUl9DTElfTUFQIiwiY2xpIiwid2FpdEZsYWciLCJaZWQiLCJDdXJzb3IiLCJvcHRpb25zIiwid2FpdCIsImFwcE5hbWUiLCJjb25maWciLCJleHRlcm5hbEVkaXRvciIsIm1hcHBpbmciLCJPYmplY3QiLCJrZXlzIiwic2VhcmNoUGF0aHMiLCJob21lZGlyIiwiYnVuZGxlUGF0aCIsImZpbmQiLCJwIiwiY2xpQmluIiwiYmluIiwiYXJncyIsIlByb21pc2UiLCJyZWplY3QiLCJjaGlsZCIsInN0ZGlvIiwib24iLCJlcnIiLCJtZXNzYWdlIiwiY29kZSIsIm9wZW5Tb3VyY2VGaWxlIiwiaXNBYnNvbHV0ZSIsImRldGFjaGVkIiwidW5yZWYiLCJsaXN0UnVsZXMiLCJydWxlc0RpciIsInJ1bGVzIiwia2V5IiwicmVwbGFjZSIsInJhdyIsImRvYyIsIkpTT04iLCJwYXJzZSIsImRlc2NyaXB0aW9uIiwicnVsZUNvdW50IiwiQXJyYXkiLCJpc0FycmF5IiwicGFyc2VFcnJvciIsIlN0cmluZyIsInJlYWRSdWxlIiwicnVsZUtleSIsImFkZFJ1bGUiLCJyZXEiLCJuZXh0SWQiLCJnZW5lcmF0ZU5leHRSdWxlSWQiLCJuZXdFbnRyeSIsImlkIiwid2hlbiIsImluc3RydWN0aW9uIiwiZXhhbXBsZXMiLCJ3cml0ZUZpbGVTeW5jIiwic3RyaW5naWZ5IiwibnVtZXJpY1BhdHRlcm4iLCJiZXN0UHJlZml4IiwibWF4TnVtIiwicnVsZSIsIm1hdGNoIiwiZXhlYyIsInByZWZpeCIsIm51bSIsIk51bWJlciIsInBhcnNlSW50IiwibmV4dE51bSIsInBhZExlbiIsIk1hdGgiLCJtYXgiLCJwYWRTdGFydCIsInBhcnNlQWNFbnRyaWVzIiwibGluZXMiLCJzcGxpdCIsImN1cnJlbnREZXNjcmliZSIsImRlc2NyaWJlRGVwdGgiLCJicmFjZURlcHRoIiwicGVuZGluZ1Rlc3RBcyIsInRlc3RBc0JyYWNlRGVwdGgiLCJ0ZXN0QXNOZWVkTmFtZSIsImxpbmUiLCJ0cmltbWVkIiwidHJpbSIsImRlc2NyaWJlTWF0Y2giLCJ0ZXN0TWF0Y2giLCJkZXNjcmliZSIsInRlc3QiLCJpbmxpbmVNYXRjaCIsImNoIiwibmFtZU1hdGNoIiwiZ2V0QWNMaXN0IiwicHJvamVjdFJvb3QiLCJmaWxlcyIsImZpbmRUZXN0RmlsZXMiLCJhY0ZpbGVzIiwidG90YWwiLCJyZWR1Y2UiLCJzdW0iLCJmIiwiZGlyIiwicmVzdWx0cyIsIklHTk9SRSIsIlNldCIsIndhbGsiLCJjdXJyZW50RGlyIiwiaGFzIiwic29ydCJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBSyxRQUFRLGdCQUFnQjtBQUN0QyxPQUFPQyxRQUFRLEtBQUs7QUFDcEIsT0FBT0MsUUFBUSxLQUFLO0FBQ3BCLE9BQU9DLFVBQVUsT0FBTztBQUN4QixTQUFTQyxNQUFNLFFBQVEsbUJBQWdCO0FBMkJ2Qyw2Q0FBNkMsR0FDN0MsU0FBU0M7SUFDUCxPQUFPRixLQUFLRyxJQUFJLENBQUNGLE9BQU9HLFdBQVcsRUFBRSxNQUFNLE1BQU07QUFDbkQ7QUFFQSxrQkFBa0IsR0FDbEIsU0FBU0M7SUFDUCxPQUFPTCxLQUFLRyxJQUFJLENBQUNGLE9BQU9HLFdBQVcsRUFBRSxNQUFNO0FBQzdDO0FBRUEsK0JBQStCLEdBQy9CLFNBQVNFLHdCQUF3QkMsUUFBZ0I7SUFDL0MsTUFBTUMsY0FBY047SUFDcEIsTUFBTU8sV0FBV1QsS0FBS1UsT0FBTyxDQUFDRixhQUFhRDtJQUMzQyxJQUFJLENBQUNFLFNBQVNFLFVBQVUsQ0FBQ0gsY0FBY1IsS0FBS1ksR0FBRyxLQUFLSCxhQUFhRCxhQUFhO1FBQzVFLE1BQU0sSUFBSUssTUFBTSxDQUFDLDZCQUE2QixFQUFFTixVQUFVO0lBQzVEO0FBQ0Y7QUFFQSx5QkFBeUIsR0FDekIsU0FBU08sZUFBZUMsUUFBZ0I7SUFDdEMsSUFBSUEsU0FBU0MsUUFBUSxDQUFDLGlCQUFpQixPQUFPO0lBQzlDLElBQUlELFNBQVNDLFFBQVEsQ0FBQyxnQkFBZ0IsT0FBTztJQUM3QyxPQUFPQztBQUNUO0FBRUEscUNBQXFDLEdBQ3JDLFNBQVNDLGNBQWNDLE9BQWUsRUFBRUMsVUFBa0I7SUFDeEQsTUFBTUMsVUFBVXZCLEdBQUd3QixXQUFXLENBQUNILFNBQVM7UUFBRUksZUFBZTtJQUFLO0lBQzlELE1BQU1DLFFBQXVCLEVBQUU7SUFFL0IsS0FBSyxNQUFNQyxTQUFTSixRQUFTO1FBQzNCLE1BQU1L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