gitlab-ci-local 4.65.0 → 4.66.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.
package/src/job.js DELETED
@@ -1,1463 +0,0 @@
1
- import chalk from "chalk-template";
2
- import * as dotenv from "dotenv";
3
- import fs from "fs-extra";
4
- import prettyHrtime from "pretty-hrtime";
5
- import split2 from "split2";
6
- import { Utils } from "./utils.js";
7
- import assert, { AssertionError } from "assert";
8
- import { Mutex } from "./mutex.js";
9
- import execa from "execa";
10
- import { GitlabRunnerCPUsPresetValue, GitlabRunnerMemoryPresetValue, GitlabRunnerPresetValues } from "./gitlab-preset.js";
11
- import { handler } from "./handler.js";
12
- import * as yaml from "js-yaml";
13
- import { Parser } from "./parser.js";
14
- import { resolveIncludeLocal, validateIncludeLocal } from "./parser-includes.js";
15
- import { globbySync } from "globby";
16
- import terminalLink from "terminal-link";
17
- import * as crypto from "crypto";
18
- import * as path from "path";
19
- const GCL_SHELL_PROMPT_PLACEHOLDER = "<gclShellPromptPlaceholder>";
20
- const isGlob = (str) => /[*?{}(|)[\]]/.test(str);
21
- const dateFormatter = new Intl.DateTimeFormat(undefined, {
22
- year: undefined,
23
- month: undefined,
24
- hour: "numeric",
25
- minute: "numeric",
26
- second: "numeric",
27
- hour12: false,
28
- });
29
- export class Job {
30
- generateJobId() {
31
- return Math.floor(Math.random() * 1000000);
32
- }
33
- static illegalJobNames = new Set([
34
- "include", "local_configuration", "image", "services",
35
- "stages", "before_script", "default",
36
- "after_script", "variables", "cache", "workflow", "page:deploy",
37
- ]);
38
- argv;
39
- name;
40
- baseName;
41
- dependencies;
42
- environment;
43
- jobId;
44
- rules;
45
- allowFailure;
46
- when;
47
- exists;
48
- pipelineIid;
49
- gitData;
50
- inherit;
51
- _dotenvVariables = {};
52
- _prescriptsExitCode = null;
53
- _afterScriptsExitCode = 0;
54
- _coveragePercent = null;
55
- _running = false;
56
- _containerId = null;
57
- _serviceNetworkId = null;
58
- _longRunningSilentTimeout = -1;
59
- _producers = null;
60
- _jobNamePad = null;
61
- _ciProjectDir = null;
62
- _startTime;
63
- _endTime;
64
- _filesToRm = [];
65
- _globalVariables = {};
66
- _variables = {};
67
- _containersToClean = [];
68
- _containerVolumeNames = [];
69
- jobData;
70
- writeStreams;
71
- constructor(opt) {
72
- const jobData = opt.data;
73
- const jobVariables = jobData.variables ?? {};
74
- const variablesFromFiles = opt.variablesFromFiles;
75
- const argv = opt.argv;
76
- const cwd = argv.cwd;
77
- const argvVariables = argv.variable;
78
- const expandVariables = opt.expandVariables ?? true;
79
- this.argv = argv;
80
- this.writeStreams = opt.writeStreams;
81
- this.gitData = opt.gitData;
82
- this.name = opt.name;
83
- this.baseName = opt.baseName;
84
- this.jobId = this.generateJobId();
85
- this.jobData = opt.data;
86
- this.pipelineIid = opt.pipelineIid;
87
- this._globalVariables = opt.globalVariables;
88
- this.inherit = {};
89
- this.inherit.variables = this.jobData.inherit?.variables ?? true;
90
- this.when = jobData.when || "on_success";
91
- this.exists = jobData.exists || [];
92
- this.allowFailure = jobData.allow_failure ?? false;
93
- this.dependencies = jobData.dependencies || null;
94
- this.rules = jobData.rules || null;
95
- this.environment = typeof jobData.environment === "string" ? { name: jobData.environment } : (jobData.environment ? { ...jobData.environment } : jobData.environment);
96
- const matrixVariables = opt.matrixVariables ?? {};
97
- const fileVariables = Utils.findEnvMatchedVariables(variablesFromFiles, this.fileVariablesDir);
98
- const predefinedVariables = this._predefinedVariables(opt);
99
- this._variables = { ...predefinedVariables, ...this.globalVariables, ...jobVariables, ...matrixVariables, ...fileVariables, ...argvVariables };
100
- if (this.rules && expandVariables) {
101
- const expanded = Utils.expandVariables(this._variables);
102
- // Expand variables in rules:changes
103
- this.rules.forEach((rule, ruleIdx, rules) => {
104
- const changes = Array.isArray(rule.changes) ? rule.changes : rule.changes?.paths;
105
- if (!changes) {
106
- return;
107
- }
108
- changes.forEach((change, changeIdx, changes) => {
109
- changes[changeIdx] = Utils.expandText(change, expanded);
110
- });
111
- rules[ruleIdx].changes = changes;
112
- });
113
- // Expand variables in rules:exists
114
- this.rules.forEach((rule, ruleIdx, rules) => {
115
- const exists = Array.isArray(rule.exists) ? rule.exists : null;
116
- if (!exists) {
117
- return;
118
- }
119
- exists.forEach((exist, existId, exists) => {
120
- exists[existId] = Utils.expandText(exist, expanded);
121
- });
122
- rules[ruleIdx].exists = exists;
123
- });
124
- }
125
- let ruleVariables;
126
- // Set {when, allowFailure} based on rules result
127
- if (this.rules) {
128
- const ruleResult = Utils.getRulesResult({ argv, cwd, rules: this.rules, variables: this._variables }, this.gitData, this.when, this.allowFailure);
129
- this.when = ruleResult.when;
130
- this.allowFailure = ruleResult.allowFailure;
131
- ruleVariables = ruleResult.variables;
132
- if (ruleResult.needs) {
133
- this.jobData["needs"] = ruleResult.needs;
134
- }
135
- this._variables = { ...this._variables, ...ruleVariables, ...argvVariables };
136
- }
137
- // Find environment matched variables
138
- if (this.environment && expandVariables) {
139
- const expanded = Utils.expandVariables(this._variables);
140
- const envNameBeforeExpansion = this.environment.name;
141
- this.environment.name = Utils.expandText(this.environment.name, expanded);
142
- if (this.environment.name !== envNameBeforeExpansion) {
143
- // Regenerate CI_ENVIRONMENT_SLUG based on env name if it changed after expansion
144
- predefinedVariables["CI_ENVIRONMENT_SLUG"] = this._generateEnvironmentSlug(this.environment.name);
145
- }
146
- this.environment.url = Utils.expandText(this.environment.url, expanded);
147
- }
148
- const envMatchedVariables = Utils.findEnvMatchedVariables(variablesFromFiles, this.fileVariablesDir, this.environment);
149
- const userDefinedVariables = { ...this.globalVariables, ...jobVariables, ...matrixVariables, ...ruleVariables, ...envMatchedVariables, ...argvVariables };
150
- this.discourageOverridingOfPredefinedVariables(predefinedVariables, userDefinedVariables, argv.ignorePredefinedVars);
151
- // Merge and expand after finding env matched variables
152
- this._variables = { ...predefinedVariables, ...userDefinedVariables };
153
- // Delete variables the user intentionally wants unset
154
- for (const unsetVariable of argv.unsetVariables) {
155
- delete this._variables[unsetVariable];
156
- }
157
- // Set GCL_PROJECT_DIR_ON_HOST if docker image
158
- if (this.imageName(this._variables)) {
159
- this._variables = { ...this._variables, ...{ GCL_PROJECT_DIR_ON_HOST: cwd } };
160
- }
161
- assert(this.scripts || this.trigger, chalk `{blueBright ${this.name}} must have script specified`);
162
- assert(!(this.interactive && !this.argv.shellExecutorNoImage), chalk `${this.formattedJobName} @Interactive decorator cannot be used with --no-shell-executor-no-image`);
163
- if (this.interactive && (this.when !== "manual" || this.imageName(this._variables) !== null)) {
164
- throw new AssertionError({ message: `${this.formattedJobName} @Interactive decorator cannot have image: and must be when:manual` });
165
- }
166
- if (this.injectSSHAgent && this.imageName(this._variables) === null) {
167
- throw new AssertionError({ message: `${this.formattedJobName} @InjectSSHAgent can only be used with image:` });
168
- }
169
- const expanded = Utils.expandVariables(this._variables);
170
- for (const [i, c] of Object.entries(this.cache)) {
171
- c.policy = Utils.expandText(c.policy, expanded);
172
- assert(["pull", "push", "pull-push"].includes(c.policy), chalk `{blue ${this.name}} cache[${i}].policy is not 'pull', 'push' or 'pull-push'`);
173
- assert(["on_success", "on_failure", "always"].includes(c.when), chalk `{blue ${this.name}} cache[${i}].when is not 'on_success', 'on_failure' or 'always'`);
174
- assert(Array.isArray(c.paths), chalk `{blue ${this.name}} cache[${i}].paths must be array`);
175
- }
176
- for (const [i, s] of Object.entries(this.services)) {
177
- assert(s.name, chalk `{blue ${this.name}} services[${i}].name is undefined`);
178
- assert(!s.command || Array.isArray(s.command), chalk `{blue ${this.name}} services[${i}].command must be an array`);
179
- assert(!s.entrypoint || Array.isArray(s.entrypoint), chalk `{blue ${this.name}} services[${i}].entrypoint must be an array`);
180
- }
181
- assert(!this.artifacts?.paths || Array.isArray(this.artifacts.paths), chalk `{blue ${this.name}} artifacts.paths must be an array`);
182
- if (this.imageName(this._variables) && argv.mountCache) {
183
- for (const c of this.cache) {
184
- c.paths.forEach((p) => {
185
- const path = Utils.expandText(p, expanded);
186
- assert(!path.includes("*"), chalk `{blue ${this.name}} cannot have * in cache paths, when --mount-cache is enabled`);
187
- });
188
- }
189
- }
190
- }
191
- /**
192
- * Warn when overriding of predefined variables is detected
193
- */
194
- discourageOverridingOfPredefinedVariables(predefinedVariables, userDefinedVariables, whiteListedPredefinedVariablesKeys) {
195
- const predefinedVariablesKeys = Object.keys(predefinedVariables);
196
- const userDefinedVariablesKeys = Object.keys(userDefinedVariables);
197
- const overridingOfPredefinedVariables = userDefinedVariablesKeys.filter(ele => predefinedVariablesKeys.includes(ele) && !whiteListedPredefinedVariablesKeys.includes(ele));
198
- if (overridingOfPredefinedVariables.length == 0) {
199
- return;
200
- }
201
- const linkToGitlab = "https://gitlab.com/gitlab-org/gitlab/-/blob/v17.7.1-ee/doc/ci/variables/predefined_variables.md?plain=1&ref_type=tags#L15-16";
202
- this.writeStreams.memoStdout(chalk `
203
- {bgYellowBright WARN } ${terminalLink("Avoid overriding predefined variables", linkToGitlab)} [{bold ${overridingOfPredefinedVariables}}] as it can cause the pipeline to behave unexpectedly.
204
- If you know what you're doing and would like to suppress this warning, use one of the following methods:
205
- \t• via cli options
206
- \t\t• --ignore-predefined-vars ${overridingOfPredefinedVariables}
207
- \t• via environment variable
208
- \t\t• GCL_IGNORE_PREDEFINED_VARS=${overridingOfPredefinedVariables}
209
- `);
210
- }
211
- /**
212
- * Get the predefinedVariables that's enriched with the additional info that's only available when constructing
213
- */
214
- _predefinedVariables(opt) {
215
- const argv = this.argv;
216
- const cwd = argv.cwd;
217
- const stateDir = this.argv.stateDir;
218
- const gitData = this.gitData;
219
- let ciBuildsDir;
220
- if (this.jobData["image"]) {
221
- ciBuildsDir = "/builds";
222
- this.ciProjectDir = `${ciBuildsDir}/${gitData.remote.group}/${gitData.remote.project}`;
223
- }
224
- else if (argv.shellIsolation) {
225
- ciBuildsDir = `${cwd}/${stateDir}/builds/${this.safeJobName}`;
226
- this.ciProjectDir = ciBuildsDir;
227
- }
228
- else {
229
- ciBuildsDir = cwd;
230
- this.ciProjectDir = ciBuildsDir;
231
- }
232
- const predefinedVariables = opt.predefinedVariables;
233
- predefinedVariables["CI_JOB_ID"] = `${this.jobId}`;
234
- predefinedVariables["CI_PIPELINE_ID"] = `${this.pipelineIid + 1000}`;
235
- predefinedVariables["CI_PIPELINE_IID"] = `${this.pipelineIid}`;
236
- predefinedVariables["CI_JOB_NAME"] = `${this.name}`;
237
- predefinedVariables["CI_JOB_NAME_SLUG"] = `${this.name.replace(/[^a-z\d]+/ig, "-").replace(/^-/, "").slice(0, 63).replace(/-$/, "").toLowerCase()}`;
238
- predefinedVariables["CI_JOB_STAGE"] = `${this.stage}`;
239
- predefinedVariables["CI_BUILDS_DIR"] = ciBuildsDir;
240
- predefinedVariables["CI_PROJECT_DIR"] = this.ciProjectDir;
241
- predefinedVariables["CI_JOB_URL"] = `${predefinedVariables["CI_SERVER_URL"]}/${gitData.remote.group}/${gitData.remote.project}/-/jobs/${this.jobId}`; // Changes on rerun.
242
- predefinedVariables["CI_PIPELINE_URL"] = `${predefinedVariables["CI_SERVER_URL"]}/${gitData.remote.group}/${gitData.remote.project}/pipelines/${this.pipelineIid}`;
243
- predefinedVariables["CI_ENVIRONMENT_NAME"] = this.environment?.name ?? "";
244
- predefinedVariables["CI_ENVIRONMENT_SLUG"] = this.environment?.name ? this._generateEnvironmentSlug(this.environment.name) : "";
245
- predefinedVariables["CI_ENVIRONMENT_URL"] = this.environment?.url ?? "";
246
- predefinedVariables["CI_ENVIRONMENT_TIER"] = this.environment?.deployment_tier ?? "";
247
- predefinedVariables["CI_ENVIRONMENT_ACTION"] = this.environment?.action ?? "";
248
- if (opt.nodeIndex !== null) {
249
- predefinedVariables["CI_NODE_INDEX"] = `${opt.nodeIndex}`;
250
- }
251
- predefinedVariables["CI_NODE_TOTAL"] = `${opt.nodesTotal}`;
252
- predefinedVariables["CI_REGISTRY"] = predefinedVariables["CI_REGISTRY"] = this.argv.registry ? Utils.gclRegistryPrefix : `local-registry.${this.gitData.remote.host}`;
253
- predefinedVariables["CI_REGISTRY_IMAGE"] = `$CI_REGISTRY/${predefinedVariables["CI_PROJECT_PATH"].toLowerCase()}`;
254
- return predefinedVariables;
255
- }
256
- /**
257
- * Generates a compliant slug for an environment name.
258
- * See: https://gitlab.com/gitlab-org/gitlab/-/blob/fc31e7ac344e53ebae182ea1dca183bdc0e2ea71/lib/gitlab/slug/environment.rb
259
- *
260
- * The slug:
261
- * - Contains only lowercase letters (a-z), numbers (0-9), and '-'.
262
- * - Begins with a letter.
263
- * - Has a maximum length of 24 characters.
264
- * - Does not end with '-'.
265
- *
266
- * @param name The original environment name.
267
- * @returns A compliant environment slug.
268
- */
269
- _generateEnvironmentSlug(name) {
270
- // 1. Lowercase, replace non-alphanumeric with '-', and squeeze repeating '-'
271
- let slug = name
272
- .toLowerCase()
273
- .replace(/[^a-z0-9]/g, "-")
274
- .replace(/-+/g, "-");
275
- // 2. Must start with a letter
276
- if (!/^[a-z]/.test(slug)) {
277
- slug = `env-${slug}`;
278
- }
279
- // 3. If it's too long or was modified, shorten and add a hash suffix
280
- if (slug.length > 24 || slug !== name) {
281
- // Truncate to 17 chars (leaving room for '-' + 6-char hash)
282
- slug = slug.slice(0, 17);
283
- // Ensure it ends with a dash before adding the suffix
284
- if (!slug.endsWith("-")) {
285
- slug += "-";
286
- }
287
- // Create the 6-char suffix from a hash of the *original* name
288
- const hexHash = crypto
289
- .createHash("sha256")
290
- .update(name)
291
- .digest("hex");
292
- // Use BigInt for safe conversion from hex -> base36
293
- const suffix = BigInt(`0x${hexHash}`).toString(36).slice(-6);
294
- return slug + suffix;
295
- }
296
- // 4. If it was short and unmodified, just ensure it doesn't end with '-'
297
- return slug.replace(/-$/, "");
298
- }
299
- get jobStatus() {
300
- if (this.preScriptsExitCode == null)
301
- return "pending";
302
- if (this.preScriptsExitCode == 0)
303
- return "success";
304
- let allowedExitCodes = [0];
305
- const allowFailure = this.allowFailure;
306
- switch (typeof allowFailure) {
307
- case "boolean":
308
- if (allowFailure) {
309
- allowedExitCodes = [this.preScriptsExitCode];
310
- }
311
- break;
312
- case "object":
313
- if (!Array.isArray(allowFailure.exit_codes)) {
314
- allowedExitCodes = [allowFailure.exit_codes];
315
- }
316
- else {
317
- allowedExitCodes = allowFailure.exit_codes;
318
- }
319
- break;
320
- default:
321
- throw new Error(`Unexpected type: ${typeof allowFailure}`);
322
- }
323
- return allowedExitCodes.includes(this.preScriptsExitCode) ? "warning" : "failed";
324
- }
325
- get artifactsToSource() {
326
- if (this.jobData["gclArtifactsToSource"] != null)
327
- return this.jobData["gclArtifactsToSource"];
328
- return this.argv.artifactsToSource;
329
- }
330
- get prettyDuration() {
331
- if (this._endTime) {
332
- return prettyHrtime(this._endTime);
333
- }
334
- return this._startTime ?
335
- prettyHrtime(process.hrtime(this._startTime)) :
336
- "0 ms";
337
- }
338
- get formattedJobName() {
339
- let prefix = "";
340
- if (this.argv.childPipelineDepth > 0)
341
- prefix = "\t".repeat(this.argv.childPipelineDepth) + `[${this.argv.variable.GCL_TRIGGERER}] -> `;
342
- const timestampPrefix = this.argv.showTimestamps ?
343
- `[${dateFormatter.format(new Date())} ${this.prettyDuration.padStart(7)}] ` :
344
- "";
345
- // [16:33:19 1.37 min] my-job > hello world
346
- return chalk `${timestampPrefix}{blueBright ${prefix}${this.name.padEnd(this.jobNamePad)}}`;
347
- }
348
- get safeJobName() {
349
- return Utils.safeDockerString(this.name);
350
- }
351
- get needs() {
352
- return this.jobData["needs"] ?? null;
353
- }
354
- get buildVolumeName() {
355
- return `gcl-${this.safeJobName}-${this.jobId}-build`;
356
- }
357
- get tmpVolumeName() {
358
- return `gcl-${this.safeJobName}-${this.jobId}-tmp`;
359
- }
360
- get services() {
361
- const services = [];
362
- if (!this.jobData["services"])
363
- return [];
364
- for (const service of Object.values(this.jobData["services"])) {
365
- const expanded = Utils.expandVariables({ ...this._variables, ...this._dotenvVariables, ...service["variables"] });
366
- let serviceName = Utils.expandText(service["name"], expanded);
367
- if (serviceName == "")
368
- continue;
369
- serviceName = serviceName.includes(":") ? serviceName : `${serviceName}:latest`;
370
- services.push({
371
- name: serviceName,
372
- entrypoint: service["entrypoint"] ?? null,
373
- command: service["command"] ?? null,
374
- variables: expanded,
375
- alias: Utils.expandText(service["alias"], expanded) ?? null,
376
- });
377
- }
378
- return services;
379
- }
380
- set ciProjectDir(ciProjectDir) {
381
- assert(this._ciProjectDir == null, "this._ciProjectDir can only be set once");
382
- this._ciProjectDir = ciProjectDir;
383
- }
384
- get ciProjectDir() {
385
- assert(this._ciProjectDir, "attempted to access this._ciProjectDir before it is initialized");
386
- return this._ciProjectDir;
387
- }
388
- set jobNamePad(jobNamePad) {
389
- assert(this._jobNamePad == null, "this._jobNamePad can only be set once");
390
- this._jobNamePad = jobNamePad;
391
- }
392
- get jobNamePad() {
393
- return this._jobNamePad ?? 0;
394
- }
395
- get producers() {
396
- return this._producers;
397
- }
398
- set producers(producers) {
399
- assert(this._producers == null, "this._producers can only be set once");
400
- this._producers = producers;
401
- }
402
- get stage() {
403
- return this.jobData["stage"] || "test";
404
- }
405
- get interactive() {
406
- return this.jobData["gclInteractive"] || false;
407
- }
408
- get injectSSHAgent() {
409
- return this.jobData["gclInjectSSHAgent"] || false;
410
- }
411
- get description() {
412
- return this.jobData["gclDescription"] ?? "";
413
- }
414
- get artifacts() {
415
- return this.jobData["artifacts"];
416
- }
417
- deleteArtifacts() {
418
- delete this.jobData["artifacts"];
419
- }
420
- get cache() {
421
- return this.jobData["cache"] || [];
422
- }
423
- async getUniqueCacheName(cwd, expanded, cacheIndex) {
424
- const getCachePrefix = (index) => {
425
- const prefix = this.jobData["cache"][index]["key"]["prefix"];
426
- if (prefix) {
427
- return `${index}_${Utils.expandText(prefix, expanded)}-`;
428
- }
429
- const filenames = this.jobData["cache"][index]["key"]["files"].map((p) => {
430
- const expandP = Utils.expandText(p, expanded);
431
- return expandP.split(".")[0];
432
- }).join("_");
433
- return `${index}_${filenames}-`;
434
- };
435
- const key = this.jobData["cache"][cacheIndex].key;
436
- if (typeof key === "string" || key == null) {
437
- return Utils.expandText(key ?? "default", expanded);
438
- }
439
- const files = key["files"].map((f) => {
440
- let path = Utils.expandText(f, expanded);
441
- if (path.startsWith(`${this.ciProjectDir}/`)) {
442
- path = path.slice(`${this.ciProjectDir}/`.length);
443
- }
444
- return `${cwd}/${path}`;
445
- });
446
- return getCachePrefix(cacheIndex) + await Utils.checksumFiles(cwd, files);
447
- }
448
- get beforeScripts() {
449
- const beforeScripts = this.jobData["before_script"] || [];
450
- return typeof beforeScripts === "string" ? [beforeScripts] : beforeScripts;
451
- }
452
- get afterScripts() {
453
- const afterScripts = this.jobData["after_script"] || [];
454
- return typeof afterScripts === "string" ? [afterScripts] : afterScripts;
455
- }
456
- get scripts() {
457
- const script = this.jobData["script"];
458
- return typeof script === "string" ? [script] : script;
459
- }
460
- get trigger() {
461
- return this.jobData["trigger"];
462
- }
463
- async startTriggerPipeline() {
464
- this.writeStreams.memoStdout(chalk `{bgYellowBright WARN } downstream pipeline is experimental in gitlab-ci-local\n`);
465
- await this.fetchTriggerInclude();
466
- const variablesForDownstreamPipeline = Object.entries({ ...this.globalVariables, ...this.jobData.variables }).map(([key, value]) => `${key}=${value}`);
467
- const gclTriggerer = this.argv.variable["GCL_TRIGGERER"] ?
468
- `${this.argv.variable["GCL_TRIGGERER"]} -> ${this.name}` :
469
- this.name;
470
- await handler({
471
- ...Object.fromEntries(this.argv.map),
472
- file: `${this.argv.stateDir}/includes/triggers/${this.name}.yml`,
473
- variable: [
474
- chalk `GCL_TRIGGERER=${gclTriggerer}`,
475
- "CI_PIPELINE_SOURCE=parent_pipeline",
476
- ].concat(variablesForDownstreamPipeline),
477
- }, this.writeStreams, [], this.argv.childPipelineDepth + 1);
478
- }
479
- get preScriptsExitCode() {
480
- return this._prescriptsExitCode;
481
- }
482
- get afterScriptsExitCode() {
483
- return this._afterScriptsExitCode;
484
- }
485
- get started() {
486
- return this._running || this._prescriptsExitCode !== null;
487
- }
488
- get finished() {
489
- return !this._running && this._prescriptsExitCode !== null;
490
- }
491
- get coveragePercent() {
492
- return this._coveragePercent;
493
- }
494
- get fileVariablesDir() {
495
- return `/tmp/gitlab-ci-local-file-variables-${this._variables["CI_PROJECT_PATH_SLUG"]}-${this.jobId}`;
496
- }
497
- get globalVariables() {
498
- if (this.inherit.variables === false) {
499
- return {};
500
- }
501
- else if (Array.isArray(this.inherit.variables)) {
502
- const inheritVariables = this.inherit.variables;
503
- return Object.fromEntries(Object.entries(this._globalVariables).filter(([k]) => inheritVariables.includes(k)));
504
- }
505
- return this._globalVariables;
506
- }
507
- async start() {
508
- if (this.trigger) {
509
- await this.startTriggerPipeline();
510
- this._prescriptsExitCode = 0; // NOTE: so that `this.finished` will implicitly be set to true
511
- return;
512
- }
513
- this._running = true;
514
- const argv = this.argv;
515
- this._startTime = process.hrtime();
516
- this._variables["CI_JOB_STARTED_AT"] = new Date().toISOString().split(".")[0] + "Z";
517
- const writeStreams = this.writeStreams;
518
- this._dotenvVariables = await this.initProducerReportsDotenvVariables(writeStreams, Utils.expandVariables(this._variables));
519
- const expanded = Utils.unscape$$Variables(Utils.expandVariables({ ...this._variables, ...this._dotenvVariables }));
520
- const imageName = this.imageName(expanded);
521
- const helperImageName = argv.helperImage;
522
- const safeJobName = this.safeJobName;
523
- const outputLogFilePath = `${argv.cwd}/${argv.stateDir}/output/${safeJobName}.log`;
524
- await fs.ensureFile(outputLogFilePath);
525
- await fs.truncate(outputLogFilePath);
526
- if (!this.interactive) {
527
- writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright starting} ${imageName ?? "shell"} ({yellow ${this.stage}})\n`);
528
- }
529
- if (imageName) {
530
- await this.pullImage(writeStreams, imageName);
531
- const buildVolumeName = this.buildVolumeName;
532
- const tmpVolumeName = this.tmpVolumeName;
533
- const fileVariablesDir = this.fileVariablesDir;
534
- const volumePromises = [];
535
- volumePromises.push(Utils.spawn([this.argv.containerExecutable, "volume", "create", `${buildVolumeName}`], argv.cwd));
536
- volumePromises.push(Utils.spawn([this.argv.containerExecutable, "volume", "create", `${tmpVolumeName}`], argv.cwd));
537
- this._containerVolumeNames.push(buildVolumeName);
538
- this._containerVolumeNames.push(tmpVolumeName);
539
- await Promise.all(volumePromises);
540
- const time = process.hrtime();
541
- this.refreshLongRunningSilentTimeout(writeStreams);
542
- let chownOpt = "0:0";
543
- let chmodOpt = "a+rw";
544
- if (!this.argv.umask) {
545
- const { stdout } = await Utils.spawn([this.argv.containerExecutable, "run", "--rm", "--entrypoint", "sh", imageName, "-c", "echo \"$(id -u):$(id -g)\""]);
546
- chownOpt = stdout;
547
- if (chownOpt == "0:0") {
548
- chmodOpt = "g-w";
549
- }
550
- }
551
- if (helperImageName) {
552
- await this.pullImage(writeStreams, helperImageName);
553
- }
554
- const helperContainerArgs = [
555
- this.argv.containerExecutable, "create", "--user=0:0",
556
- `--volume=${buildVolumeName}:${this.ciProjectDir}`,
557
- `--volume=${tmpVolumeName}:${this.fileVariablesDir}`,
558
- ];
559
- if (this.argv.caFile) {
560
- const caFilePath = path.isAbsolute(this.argv.caFile) ? this.argv.caFile : path.resolve(this.argv.cwd, this.argv.caFile);
561
- if (await fs.pathExists(caFilePath)) {
562
- helperContainerArgs.push(`--volume=${caFilePath}:/etc/ssl/certs/ca-certificates.crt:ro`);
563
- }
564
- }
565
- helperContainerArgs.push(`${helperImageName}`, "sh", "-c", `chown ${chownOpt} -R ${this.ciProjectDir} && chmod ${chmodOpt} -R ${this.ciProjectDir} && chown ${chownOpt} -R /tmp/ && chmod ${chmodOpt} -R /tmp/`);
566
- const { stdout: containerId } = await Utils.spawn(helperContainerArgs, argv.cwd);
567
- this._containersToClean.push(containerId);
568
- if (await fs.pathExists(fileVariablesDir)) {
569
- await Utils.spawn([this.argv.containerExecutable, "cp", `${fileVariablesDir}/.`, `${containerId}:${fileVariablesDir}`], argv.cwd);
570
- this.refreshLongRunningSilentTimeout(writeStreams);
571
- }
572
- await Utils.spawn([this.argv.containerExecutable, "cp", `${argv.stateDir}/builds/.docker/.`, `${containerId}:${this.ciProjectDir}`], argv.cwd);
573
- await Utils.spawn([this.argv.containerExecutable, "start", "--attach", containerId], argv.cwd);
574
- await Utils.spawn([this.argv.containerExecutable, "rm", "-vf", containerId], argv.cwd);
575
- const endTime = process.hrtime(time);
576
- writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright copied to ${this.argv.containerExecutable} volumes} in {magenta ${prettyHrtime(endTime)}}\n`);
577
- }
578
- if (this.services?.length) {
579
- // `host` and `none` networks do not work with services because aliases only work for
580
- // user defined networks.
581
- for (const network of this.argv.network) {
582
- if (["host", "none"].includes(network)) {
583
- throw new AssertionError({ message: `Cannot add service network alias with network mode '${network}'` });
584
- }
585
- }
586
- await this.createDockerNetwork(`gitlab-ci-local-${this.jobId}`);
587
- await Promise.all(this.services.map(async (service, serviceIndex) => {
588
- const serviceName = service.name;
589
- await this.pullImage(writeStreams, serviceName);
590
- const serviceContainerId = await this.startService(writeStreams, Utils.expandVariables({ ...expanded, ...service.variables }), service);
591
- const serviceContainerLogFile = `${argv.cwd}/${argv.stateDir}/services-output/${this.safeJobName}/${serviceName}-${serviceIndex}.log`;
592
- await this.serviceHealthCheck(writeStreams, service, serviceIndex, serviceContainerLogFile);
593
- const { stdout, stderr } = await Utils.spawn([this.argv.containerExecutable, "logs", serviceContainerId]);
594
- await fs.ensureFile(serviceContainerLogFile);
595
- await fs.promises.writeFile(serviceContainerLogFile, `### stdout ###\n${stdout}\n### stderr ###\n${stderr}\n`);
596
- }));
597
- }
598
- await this.execPreScripts(expanded);
599
- if (this._prescriptsExitCode == null)
600
- throw Error("this._prescriptsExitCode must be defined!");
601
- await this.execAfterScripts(expanded);
602
- this._running = false;
603
- this._endTime = this._endTime ?? process.hrtime(this._startTime);
604
- this.printFinishedString();
605
- await this.copyCacheOut(this.writeStreams, expanded);
606
- await this.copyArtifactsOut(this.writeStreams, expanded);
607
- if (this.jobData["coverage"]) {
608
- this._coveragePercent = await Utils.getCoveragePercent(argv.cwd, argv.stateDir, this.jobData["coverage"], safeJobName);
609
- }
610
- }
611
- async cleanupResources() {
612
- clearTimeout(this._longRunningSilentTimeout);
613
- if (!this.argv.cleanup)
614
- return;
615
- if (this._containersToClean.length > 0) {
616
- try {
617
- await Utils.spawn([this.argv.containerExecutable, "rm", "-vf", ...this._containersToClean]);
618
- }
619
- catch (e) {
620
- assert(e instanceof Error, "e is not instanceof Error");
621
- }
622
- }
623
- if (this._serviceNetworkId) {
624
- try {
625
- await Utils.spawn([this.argv.containerExecutable, "network", "rm", `${this._serviceNetworkId}`]);
626
- }
627
- catch (e) {
628
- assert(e instanceof Error, "e is not instanceof Error");
629
- }
630
- }
631
- if (this._containerVolumeNames.length > 0) {
632
- try {
633
- await Utils.spawn([this.argv.containerExecutable, "volume", "rm", ...this._containerVolumeNames]);
634
- }
635
- catch (e) {
636
- assert(e instanceof Error, "e is not instanceof Error");
637
- }
638
- }
639
- const rmPromises = [];
640
- for (const file of this._filesToRm) {
641
- rmPromises.push(fs.rm(file, { recursive: true, force: true }));
642
- }
643
- await Promise.all(rmPromises);
644
- const fileVariablesDir = this.fileVariablesDir;
645
- try {
646
- await fs.rm(fileVariablesDir, { recursive: true, force: true });
647
- }
648
- catch (e) {
649
- assert(e instanceof Error, "e is not instanceof Error");
650
- }
651
- }
652
- generateInjectSSHAgentOptions() {
653
- if (!this.injectSSHAgent) {
654
- return "";
655
- }
656
- if (process.platform === "darwin" || /^darwin/.exec(process.env.OSTYPE ?? "")) {
657
- return "--env SSH_AUTH_SOCK=/run/host-services/ssh-auth.sock -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock";
658
- }
659
- return `--env SSH_AUTH_SOCK=${process.env.SSH_AUTH_SOCK} -v ${process.env.SSH_AUTH_SOCK}:${process.env.SSH_AUTH_SOCK}`;
660
- }
661
- generateScriptCommands(scripts) {
662
- let cmd = "";
663
- scripts.forEach((script) => {
664
- const split = script.split(/\r?\n/);
665
- const multilineText = split.length > 1 ? " # collapsed multi-line command" : "";
666
- const text = split[0]?.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/[$]/g, "\\$");
667
- if (this.interactive) {
668
- cmd += chalk `echo "{green $ ${text}${multilineText}}"\n`;
669
- }
670
- else {
671
- // Print command echo'ed with $GCL_SHELL_PROMPT_PLACEHOLDER
672
- cmd += `echo "${GCL_SHELL_PROMPT_PLACEHOLDER} ${text}${multilineText}"\n`;
673
- }
674
- // Execute actual script
675
- cmd += `${script}\n`;
676
- });
677
- return cmd;
678
- }
679
- async mountCacheCmd(writeStreams, expanded) {
680
- if (this.imageName(expanded) && !this.argv.mountCache)
681
- return [];
682
- const cmd = [];
683
- for (const [index, c] of this.cache.entries()) {
684
- const uniqueCacheName = await this.getUniqueCacheName(this.argv.cwd, expanded, index);
685
- c.paths.forEach((p) => {
686
- const path = Utils.expandText(p, expanded);
687
- writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright mounting cache} for path ${path}\n`);
688
- const cacheMount = Utils.safeDockerString(`gcl-${expanded.CI_PROJECT_PATH_SLUG}-${uniqueCacheName}`);
689
- cmd.push("-v", `${cacheMount}:${this.ciProjectDir}/${path}`);
690
- });
691
- }
692
- return cmd;
693
- }
694
- async execPreScripts(expanded) {
695
- const prescripts = this.beforeScripts.concat(this.scripts);
696
- expanded["CI_JOB_STATUS"] = "running";
697
- this._prescriptsExitCode = await this.execScripts(prescripts, expanded, "");
698
- expanded["CI_JOB_STATUS"] = this._prescriptsExitCode === 0 ? "success" : "failed";
699
- this.printExitedString(this._prescriptsExitCode);
700
- }
701
- async execAfterScripts(expanded) {
702
- const message = "Running after script...";
703
- this._afterScriptsExitCode = await this.execScripts(this.afterScripts, expanded, message);
704
- this.printAfterScriptExitedString(this._afterScriptsExitCode);
705
- }
706
- async execScripts(scripts, expanded, message) {
707
- const cwd = this.argv.cwd;
708
- const stateDir = this.argv.stateDir;
709
- const safeJobName = this.safeJobName;
710
- const outputFilesPath = `${cwd}/${stateDir}/output/${safeJobName}.log`;
711
- const buildVolumeName = this.buildVolumeName;
712
- const tmpVolumeName = this.tmpVolumeName;
713
- const imageName = this.imageName(expanded);
714
- const writeStreams = this.writeStreams;
715
- if (scripts.length === 0 || scripts[0] == null)
716
- return 0;
717
- if (message.length > 0)
718
- writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright ${message}}\n`);
719
- await fs.remove(`${cwd}/${stateDir}/artifacts/${safeJobName}`);
720
- // Copy git tracked files to build folder if shell isolation enabled.
721
- if (!imageName && this.argv.shellIsolation) {
722
- await Utils.rsyncTrackedFiles(cwd, stateDir, `${safeJobName}`);
723
- }
724
- if (this.interactive) {
725
- let iCmd = "set -eo pipefail\n";
726
- iCmd += this.generateScriptCommands(scripts);
727
- const interactiveCp = execa(iCmd, {
728
- cwd,
729
- shell: "bash",
730
- stdio: ["inherit", "inherit", "inherit"],
731
- env: { ...expanded, ...process.env },
732
- });
733
- return new Promise((resolve, reject) => {
734
- void interactiveCp.on("exit", (code) => resolve(code ?? 0));
735
- void interactiveCp.on("error", (err) => reject(err));
736
- });
737
- }
738
- if (this.argv.registry) {
739
- expanded["CI_REGISTRY_USER"] = expanded["CI_REGISTRY_USER"] ?? `${Utils.gclRegistryPrefix}.user`;
740
- expanded["CI_REGISTRY_PASSWORD"] = expanded["CI_REGISTRY_PASSWORD"] ?? `${Utils.gclRegistryPrefix}.password`;
741
- }
742
- this.refreshLongRunningSilentTimeout(writeStreams);
743
- if (imageName && !this._containerId) {
744
- let dockerCmd = `${this.argv.containerExecutable} create --interactive ${this.generateInjectSSHAgentOptions()} `;
745
- if (this.argv.privileged) {
746
- dockerCmd += "--privileged ";
747
- }
748
- for (const device of this.argv.device) {
749
- dockerCmd += `--device ${device} `;
750
- }
751
- if (this.argv.ulimit !== null) {
752
- dockerCmd += `--ulimit nofile=${this.argv.ulimit} `;
753
- }
754
- if (this.argv.umask) {
755
- dockerCmd += "--user 0:0 ";
756
- }
757
- if (this.argv.userns != undefined) {
758
- dockerCmd += `--userns=${this.argv.userns} `;
759
- }
760
- if (this.argv.containerMacAddress) {
761
- dockerCmd += `--mac-address "${this.argv.containerMacAddress}" `;
762
- }
763
- const imageUser = this.imageUser(expanded);
764
- if (imageUser) {
765
- dockerCmd += `--user ${imageUser} `;
766
- }
767
- if (this.argv.containerEmulate) {
768
- const runnerName = this.argv.containerEmulate;
769
- if (!GitlabRunnerPresetValues.includes(runnerName)) {
770
- throw new Error("Invalid gitlab runner to emulate.");
771
- }
772
- const memoryConfig = GitlabRunnerMemoryPresetValue[runnerName];
773
- const cpuConfig = GitlabRunnerCPUsPresetValue[runnerName];
774
- dockerCmd += `--memory=${memoryConfig}m `;
775
- dockerCmd += `--kernel-memory=${memoryConfig}m `;
776
- dockerCmd += `--cpus=${cpuConfig} `;
777
- }
778
- // host and none networks have to be specified using --network, since they cannot be used with
779
- // `docker network connect`.
780
- for (const network of this.argv.network) {
781
- if (["host", "none"].includes(network)) {
782
- dockerCmd += `--network ${network} `;
783
- }
784
- }
785
- // The default podman network mode is not `bridge`, which means a `podman network connect` call will fail
786
- // when connecting user defined networks. The workaround is to use a user defined network on container
787
- // creation.
788
- //
789
- // See https://github.com/containers/podman/issues/19577
790
- //
791
- // This should not clash with the `host` and `none` networks above, since service creation should have
792
- // failed when using `host` or `none` networks.
793
- if (this._serviceNetworkId) {
794
- // `build` alias: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27060
795
- dockerCmd += `--network ${this._serviceNetworkId} --network-alias build `;
796
- }
797
- if (this.argv.registry) {
798
- dockerCmd += `--network ${Utils.gclRegistryPrefix}.net `;
799
- dockerCmd += `--volume ${Utils.gclRegistryPrefix}.certs:/etc/containers/certs.d:ro `;
800
- dockerCmd += `--volume ${Utils.gclRegistryPrefix}.certs:/etc/docker/certs.d:ro `;
801
- }
802
- dockerCmd += `--volume ${buildVolumeName}:${this.ciProjectDir} `;
803
- dockerCmd += `--volume ${tmpVolumeName}:${this.fileVariablesDir} `;
804
- dockerCmd += `--workdir ${this.ciProjectDir} `;
805
- for (const volume of this.argv.volume) {
806
- dockerCmd += `--volume ${volume} `;
807
- }
808
- for (const extraHost of this.argv.extraHost) {
809
- dockerCmd += `--add-host=${extraHost} `;
810
- }
811
- if (this.argv.caFile) {
812
- const caFilePath = path.isAbsolute(this.argv.caFile) ? this.argv.caFile : path.resolve(this.argv.cwd, this.argv.caFile);
813
- if (await fs.pathExists(caFilePath)) {
814
- dockerCmd += `--volume ${caFilePath}:/etc/ssl/certs/ca-certificates.crt:ro `;
815
- expanded["SSL_CERT_FILE"] = "/etc/ssl/certs/ca-certificates.crt";
816
- expanded["SSL_CERT_DIR"] = "/etc/ssl/certs";
817
- }
818
- else {
819
- writeStreams.stderr(chalk `{yellow WARNING: CA file not found: ${caFilePath}}\n`);
820
- }
821
- }
822
- for (const [key, val] of Object.entries(expanded)) {
823
- // Replacing `'` with `'\''` to correctly handle single quotes(if `val` contains `'`) in shell commands
824
- dockerCmd += ` -e '${key}=${val.toString().replace(/'/g, "'\\''")}' \\\n`;
825
- }
826
- if (this.imageEntrypoint) {
827
- dockerCmd += `--entrypoint ${Utils.safeBashString(this.imageEntrypoint[0])} `;
828
- }
829
- dockerCmd += `${(await this.mountCacheCmd(writeStreams, expanded)).join(" ")} `;
830
- dockerCmd += `${imageName} `;
831
- if (this.imageEntrypoint?.length ?? 0 > 1) {
832
- this.imageEntrypoint?.slice(1).forEach((e) => {
833
- dockerCmd += `${Utils.safeBashString(e)} `;
834
- });
835
- }
836
- dockerCmd += "sh -c \"\n";
837
- dockerCmd += "if [ -x /usr/local/bin/bash ]; then\n";
838
- dockerCmd += "\texec /usr/local/bin/bash \n";
839
- dockerCmd += "elif [ -x /usr/bin/bash ]; then\n";
840
- dockerCmd += "\texec /usr/bin/bash \n";
841
- dockerCmd += "elif [ -x /bin/bash ]; then\n";
842
- dockerCmd += "\texec /bin/bash \n";
843
- dockerCmd += "elif [ -x /usr/local/bin/sh ]; then\n";
844
- dockerCmd += "\texec /usr/local/bin/sh \n";
845
- dockerCmd += "elif [ -x /usr/bin/sh ]; then\n";
846
- dockerCmd += "\texec /usr/bin/sh \n";
847
- dockerCmd += "elif [ -x /bin/sh ]; then\n";
848
- dockerCmd += "\texec /bin/sh \n";
849
- dockerCmd += "elif [ -x /busybox/sh ]; then\n";
850
- dockerCmd += "\texec /busybox/sh \n";
851
- dockerCmd += "else\n";
852
- dockerCmd += "\techo shell not found\n";
853
- dockerCmd += "\texit 1\n";
854
- dockerCmd += "fi\n\"";
855
- const { stdout: containerId } = await Utils.bash(dockerCmd, cwd);
856
- for (const network of this.argv.network) {
857
- // Special network names that do not work with `docker network connect`
858
- if (["host", "none"].includes(network)) {
859
- continue;
860
- }
861
- await Utils.spawn([this.argv.containerExecutable, "network", "connect", network, `${containerId}`]);
862
- }
863
- this._containerId = containerId;
864
- this._containersToClean.push(this._containerId);
865
- }
866
- await this.copyCacheIn(writeStreams, expanded);
867
- await this.copyArtifactsIn(writeStreams);
868
- let cmd = "set -eo pipefail\n";
869
- cmd += "exec 0< /dev/null\n";
870
- if (!imageName && this.argv.shellIsolation) {
871
- cmd += `cd ${stateDir}/builds/${safeJobName}/\n`;
872
- }
873
- if (imageName) {
874
- cmd += `cd ${this.ciProjectDir} \n`;
875
- if (expanded["CI_JOB_STATUS"] != "running") {
876
- // Ensures the env `CI_JOB_STATUS` is passed to the after_script context
877
- cmd += `export CI_JOB_STATUS=${expanded["CI_JOB_STATUS"]}\n`;
878
- }
879
- }
880
- cmd += this.generateScriptCommands(scripts);
881
- cmd += "exit 0\n";
882
- const jobScriptFile = `${cwd}/${stateDir}/scripts/${safeJobName}_${this.jobId}`;
883
- await fs.outputFile(jobScriptFile, cmd, "utf-8");
884
- await fs.chmod(jobScriptFile, "0755");
885
- this._filesToRm.push(jobScriptFile);
886
- if (imageName) {
887
- await Utils.spawn([this.argv.containerExecutable, "cp", `${stateDir}/scripts/${safeJobName}_${this.jobId}`, `${this._containerId}:/gcl-cmd`], cwd);
888
- }
889
- const cp = execa(this._containerId ? `${this.argv.containerExecutable} start --attach -i ${this._containerId}` : "bash", {
890
- cwd,
891
- shell: "bash",
892
- env: imageName ? process.env : expanded,
893
- });
894
- // eslint-disable-next-line no-control-regex
895
- const sectionRegex = /\x1b\[0Ksection_(start|end):(\d+):([^\s[]+)(?:\[[^\]]*\])?\r\x1b\[0K/;
896
- const sectionStartTimes = new Map();
897
- const outFunc = (line, stream, colorize) => {
898
- this.refreshLongRunningSilentTimeout(writeStreams);
899
- const m = sectionRegex.exec(line);
900
- let isSection = false;
901
- if (m) {
902
- isSection = true;
903
- if (m[1] === "start") {
904
- sectionStartTimes.set(m[3], Date.now());
905
- line = chalk `{cyanBright ${m[3]}_started}`;
906
- }
907
- else {
908
- const elapsed = Date.now() - (sectionStartTimes.get(m[3]) ?? Date.now());
909
- line = chalk `{cyanBright ${m[3]}} took {magenta ${elapsed}ms}`;
910
- sectionStartTimes.delete(m[3]);
911
- }
912
- }
913
- stream(`${this.formattedJobName} `);
914
- if (line.startsWith(GCL_SHELL_PROMPT_PLACEHOLDER)) {
915
- // replace the GCL_SHELL_PROMPT_PLACEHOLDER with `$` and make the SHELL_PROMPT line green color
916
- line = line.slice(GCL_SHELL_PROMPT_PLACEHOLDER.length);
917
- line = chalk `{green $${line}}`;
918
- }
919
- else if (!isSection) {
920
- stream(`${colorize(">")} `);
921
- }
922
- stream(`${line}\n`);
923
- fs.appendFileSync(outputFilesPath, `${line}\n`);
924
- };
925
- const quiet = this.argv.quiet;
926
- return await new Promise((resolve, reject) => {
927
- if (!quiet) {
928
- cp.stdout?.pipe(split2()).on("data", (e) => outFunc(e, writeStreams.stdout.bind(writeStreams), (s) => chalk `{greenBright ${s}}`));
929
- cp.stderr?.pipe(split2()).on("data", (e) => outFunc(e, writeStreams.stderr.bind(writeStreams), (s) => chalk `{redBright ${s}}`));
930
- }
931
- void cp.on("exit", (code) => {
932
- clearTimeout(this._longRunningSilentTimeout);
933
- return resolve(code ?? 0);
934
- });
935
- void cp.on("error", (err) => {
936
- clearTimeout(this._longRunningSilentTimeout);
937
- return reject(err);
938
- });
939
- if (imageName) {
940
- cp.stdin?.end(". /gcl-cmd");
941
- }
942
- else {
943
- cp.stdin?.end(`./${stateDir}/scripts/${safeJobName}_${this.jobId}`);
944
- }
945
- });
946
- }
947
- imageName(vars = {}) {
948
- if (this.argv.forceShellExecutor) {
949
- return null;
950
- }
951
- const image = this.jobData["image"];
952
- if (!image) {
953
- if (this.argv.shellExecutorNoImage) {
954
- return null;
955
- }
956
- else {
957
- // https://docs.gitlab.com/ee/ci/runners/hosted_runners/linux.html#container-images
958
- return this.argv.defaultImage;
959
- }
960
- }
961
- const expanded = Utils.expandVariables(vars);
962
- const imageName = Utils.expandText(image.name, expanded);
963
- return imageName.includes(":") ? imageName : `${imageName}:latest`;
964
- }
965
- imageUser(vars = {}) {
966
- const image = this.jobData["image"];
967
- if (!image)
968
- return null;
969
- if (!image["docker"])
970
- return null;
971
- return Utils.expandText(image["docker"]["user"], vars);
972
- }
973
- get imageEntrypoint() {
974
- const image = this.jobData["image"];
975
- if (!image?.entrypoint) {
976
- return null;
977
- }
978
- assert(Array.isArray(image.entrypoint), "image:entrypoint must be an array");
979
- return image.entrypoint;
980
- }
981
- async validateCiDependencyProxyServerAuthentication(imageName) {
982
- const CI_DEPENDENCY_PROXY_SERVER = this._variables["CI_DEPENDENCY_PROXY_SERVER"];
983
- if (!imageName.startsWith(CI_DEPENDENCY_PROXY_SERVER)) {
984
- return;
985
- }
986
- try {
987
- await Utils.spawn([this.argv.containerExecutable, "login", CI_DEPENDENCY_PROXY_SERVER]);
988
- }
989
- catch (e) {
990
- const errMsg = `Please authenticate to the Dependency Proxy (${CI_DEPENDENCY_PROXY_SERVER}) https://docs.gitlab.com/ee/user/packages/dependency_proxy/#authenticate-with-the-dependency-proxy`;
991
- if (this.argv.containerExecutable == "docker") {
992
- assert(!e.stderr.includes("Cannot perform an interactive login"), errMsg);
993
- }
994
- else if (this.argv.containerExecutable == "podman") {
995
- assert(!e.stderr.includes("Username: Error: getting username and password: reading username: EOF"), errMsg);
996
- }
997
- throw e;
998
- }
999
- }
1000
- async pullImage(writeStreams, imageToPull) {
1001
- const pullPolicy = this.argv.pullPolicy;
1002
- const actualPull = async () => {
1003
- await this.validateCiDependencyProxyServerAuthentication(imageToPull);
1004
- const time = process.hrtime();
1005
- await Utils.spawn([this.argv.containerExecutable, "pull", imageToPull]);
1006
- const endTime = process.hrtime(time);
1007
- writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright pulled} ${imageToPull} in {magenta ${prettyHrtime(endTime)}}\n`);
1008
- this.refreshLongRunningSilentTimeout(writeStreams);
1009
- };
1010
- if (pullPolicy === "always") {
1011
- await actualPull();
1012
- return;
1013
- }
1014
- try {
1015
- await Utils.spawn([this.argv.containerExecutable, "image", "inspect", imageToPull]);
1016
- }
1017
- catch {
1018
- await actualPull();
1019
- }
1020
- }
1021
- async initProducerReportsDotenvVariables(writeStreams, expanded) {
1022
- const cwd = this.argv.cwd;
1023
- const stateDir = this.argv.stateDir;
1024
- const producers = this.producers;
1025
- let producerReportsEnvs = {};
1026
- for (const producer of producers ?? []) {
1027
- const producerDotenv = Utils.expandText(producer.dotenv, expanded);
1028
- if (producerDotenv === null)
1029
- continue;
1030
- const safeProducerName = Utils.safeDockerString(producer.name);
1031
- const dotenvFolder = `${cwd}/${stateDir}/artifacts/${safeProducerName}/.gitlab-ci-reports/dotenv/`;
1032
- if (await fs.pathExists(dotenvFolder)) {
1033
- const dotenvFiles = (await Utils.spawn(["find", ".", "-type", "f"], dotenvFolder)).stdout.split("\n");
1034
- for (const dotenvFile of dotenvFiles) {
1035
- if (dotenvFile == "")
1036
- continue;
1037
- const producerReportEnv = dotenv.parse(await fs.readFile(`${dotenvFolder}/${dotenvFile}`));
1038
- producerReportsEnvs = { ...producerReportsEnvs, ...producerReportEnv };
1039
- }
1040
- }
1041
- else {
1042
- writeStreams.stderr(chalk `${this.formattedJobName} {yellow reports.dotenv produced by '${producer.name}' could not be found}\n`);
1043
- }
1044
- }
1045
- return producerReportsEnvs;
1046
- }
1047
- async copyCacheIn(writeStreams, expanded) {
1048
- if (this.argv.mountCache && this.imageName(expanded))
1049
- return;
1050
- if ((!this.imageName(expanded) && !this.argv.shellIsolation) || this.cache.length === 0)
1051
- return;
1052
- const cwd = this.argv.cwd;
1053
- const stateDir = this.argv.stateDir;
1054
- for (const [index, c] of this.cache.entries()) {
1055
- if (!["pull", "pull-push"].includes(c.policy))
1056
- return;
1057
- const time = process.hrtime();
1058
- const cacheName = await this.getUniqueCacheName(cwd, expanded, index);
1059
- const cacheFolder = `${cwd}/${stateDir}/cache/${cacheName}`;
1060
- if (!await fs.pathExists(cacheFolder)) {
1061
- continue;
1062
- }
1063
- await Mutex.exclusive(cacheName, async () => {
1064
- await this.copyIn(cacheFolder);
1065
- });
1066
- const endTime = process.hrtime(time);
1067
- writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright imported cache '${cacheName}'} in {magenta ${prettyHrtime(endTime)}}\n`);
1068
- }
1069
- }
1070
- async copyArtifactsIn(writeStreams) {
1071
- if ((!this.imageName(this._variables) && !this.argv.shellIsolation) || (this.producers ?? []).length === 0)
1072
- return;
1073
- const cwd = this.argv.cwd;
1074
- const stateDir = this.argv.stateDir;
1075
- const time = process.hrtime();
1076
- const promises = [];
1077
- for (const producer of this.producers ?? []) {
1078
- const producerSafeName = Utils.safeDockerString(producer.name);
1079
- const artifactFolder = `${cwd}/${stateDir}/artifacts/${producerSafeName}`;
1080
- if (!await fs.pathExists(artifactFolder)) {
1081
- await fs.mkdirp(artifactFolder);
1082
- }
1083
- const readdir = await fs.readdir(artifactFolder);
1084
- if (readdir.length === 0) {
1085
- writeStreams.stderr(chalk `${this.formattedJobName} {yellow artifacts from {blueBright ${producerSafeName}} was empty}\n`);
1086
- }
1087
- promises.push(this.copyIn(artifactFolder));
1088
- }
1089
- await Promise.all(promises);
1090
- const endTime = process.hrtime(time);
1091
- writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright imported artifacts} in {magenta ${prettyHrtime(endTime)}}\n`);
1092
- }
1093
- copyIn(source) {
1094
- const safeJobName = this.safeJobName;
1095
- if (!this.imageName(this._variables) && this.argv.shellIsolation) {
1096
- return Utils.spawn(["rsync", "-a", `${source}/.`, `${this.argv.cwd}/${this.argv.stateDir}/builds/${safeJobName}`]);
1097
- }
1098
- return Utils.spawn([this.argv.containerExecutable, "cp", `${source}/.`, `${this._containerId}:${this.ciProjectDir}`]);
1099
- }
1100
- async copyCacheOut(writeStreams, expanded) {
1101
- if (this.argv.mountCache && this.imageName(expanded))
1102
- return;
1103
- if ((!this.imageName(expanded) && !this.argv.shellIsolation) || this.cache.length === 0)
1104
- return;
1105
- const cwd = this.argv.cwd;
1106
- const stateDir = this.argv.stateDir;
1107
- const cachePath = this.imageName(expanded) ? "/cache" : "../../cache";
1108
- let time, endTime;
1109
- for (const [index, c] of this.cache.entries()) {
1110
- if (!["push", "pull-push"].includes(c.policy))
1111
- return;
1112
- if ("on_success" === c.when && this.jobStatus !== "success")
1113
- return;
1114
- if ("on_failure" === c.when && this.jobStatus === "success")
1115
- return;
1116
- const cacheName = await this.getUniqueCacheName(cwd, expanded, index);
1117
- let paths = "";
1118
- for (const path of c.paths) {
1119
- if (!Utils.isSubpath(path, this.argv.cwd, this.argv.cwd))
1120
- continue;
1121
- paths += " " + Utils.expandText(path, expanded).replace(`${expanded.CI_PROJECT_DIR}/`, "");
1122
- }
1123
- time = process.hrtime();
1124
- let cmd = "shopt -s globstar nullglob dotglob\n";
1125
- cmd += `mkdir -p ${Utils.safeBashString(cachePath + "/" + cacheName)}\n`;
1126
- cmd += `rsync -Ra ${paths} ${Utils.safeBashString(cachePath + "/" + cacheName + "/.")} || true\n`;
1127
- await Mutex.exclusive(cacheName, async () => {
1128
- await this.copyOut(cmd, stateDir, "cache", []);
1129
- });
1130
- endTime = process.hrtime(time);
1131
- for (const __path of c.paths) {
1132
- const _path = Utils.expandText(__path, expanded);
1133
- if (!Utils.isSubpath(_path, this.argv.cwd, this.argv.cwd)) {
1134
- writeStreams.stdout(chalk `{yellow WARNING: processPath: artifact path is not a subpath of project directory: ${_path}}\n`);
1135
- continue;
1136
- }
1137
- let path = _path;
1138
- if (isGlob(path) && !path.endsWith("*")) {
1139
- path = `${path}/**`;
1140
- }
1141
- let numOfFiles = globbySync(path, {
1142
- dot: true,
1143
- onlyFiles: false,
1144
- cwd: `${this.argv.cwd}/${stateDir}/cache/${cacheName}`,
1145
- }).length;
1146
- if (numOfFiles == 0) {
1147
- writeStreams.stdout(chalk `{yellow WARNING: ${path}: no matching files. Ensure that the artifact path is relative to the working directory}\n`);
1148
- continue;
1149
- }
1150
- if (!isGlob(path))
1151
- numOfFiles++; // add one because the pattern itself is a folder
1152
- writeStreams.stdout(`${_path}: found ${numOfFiles} artifact files and directories\n`);
1153
- }
1154
- writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright cache created in '${stateDir}/cache/${cacheName}'} in {magenta ${prettyHrtime(endTime)}}\n`);
1155
- }
1156
- }
1157
- async copyArtifactsOut(writeStreams, expanded) {
1158
- // TODO: update the condition to support when:on_success / when:on_failure
1159
- if (this.jobStatus !== "success" && this.artifacts?.when !== "always")
1160
- return;
1161
- if (!this.artifacts)
1162
- return;
1163
- if ((this.artifacts.paths?.length ?? 0) === 0 && this.artifacts.reports?.dotenv == null)
1164
- return;
1165
- const safeJobName = this.safeJobName;
1166
- const cwd = this.argv.cwd;
1167
- const stateDir = this.argv.stateDir;
1168
- let artifactsPath;
1169
- if (!this.argv.shellIsolation && !this.imageName(expanded)) {
1170
- artifactsPath = `${stateDir}/artifacts`;
1171
- }
1172
- else if (this.imageName(expanded)) {
1173
- artifactsPath = "/artifacts";
1174
- }
1175
- else {
1176
- artifactsPath = "../../artifacts";
1177
- }
1178
- let time, endTime;
1179
- let cpCmd = "shopt -s globstar nullglob dotglob\n";
1180
- cpCmd += `mkdir -p ${artifactsPath}/${safeJobName}\n`;
1181
- cpCmd += "rsync --exclude '.gitlab-ci-local/**' -Ra ";
1182
- for (const artifactExcludePath of this.artifacts?.exclude ?? []) {
1183
- const expandedPath = Utils.expandText(artifactExcludePath, expanded).replace(`${expanded.CI_PROJECT_DIR}/`, "");
1184
- cpCmd += `--exclude '${expandedPath}' `;
1185
- }
1186
- for (const artifactPath of this.artifacts?.paths ?? []) {
1187
- const expandedPath = Utils.expandText(artifactPath, expanded).replace(`${expanded.CI_PROJECT_DIR}/`, "");
1188
- cpCmd += `${expandedPath} `;
1189
- }
1190
- cpCmd += `${artifactsPath}/${safeJobName}/. || true\n`;
1191
- const reportDotenv = Utils.expandText(this.artifacts.reports?.dotenv ?? null, expanded);
1192
- const reportDotenvs = (typeof reportDotenv === "string") ? // normalize to string[] for easier handling
1193
- [reportDotenv] :
1194
- reportDotenv;
1195
- if (reportDotenvs != null) {
1196
- reportDotenvs.forEach((reportDotenv) => {
1197
- cpCmd += `mkdir -p ${artifactsPath}/${safeJobName}/.gitlab-ci-reports/dotenv\n`;
1198
- cpCmd += `if [ -f ${reportDotenv} ]; then\n`;
1199
- cpCmd += ` rsync -Ra ${reportDotenv} ${artifactsPath}/${safeJobName}/.gitlab-ci-reports/dotenv/.\n`;
1200
- cpCmd += "fi\n";
1201
- });
1202
- }
1203
- time = process.hrtime();
1204
- const dockerCmdExtras = this.argv.mountCache ? await this.mountCacheCmd(writeStreams, expanded) : [];
1205
- await this.copyOut(cpCmd, stateDir, "artifacts", dockerCmdExtras);
1206
- endTime = process.hrtime(time);
1207
- for (const reportDotenv of reportDotenvs ?? []) {
1208
- if (await fs.pathExists(`${cwd}/${stateDir}/artifacts/${safeJobName}/.gitlab-ci-reports/dotenv/${reportDotenv}`))
1209
- continue;
1210
- writeStreams.stderr(chalk `${this.formattedJobName} {yellow artifact reports dotenv '${reportDotenv}' could not be found}\n`);
1211
- }
1212
- const readdir = await fs.readdir(`${cwd}/${stateDir}/artifacts/${safeJobName}`);
1213
- if (readdir.length === 0) {
1214
- writeStreams.stdout(chalk `${this.formattedJobName} {yellow !! no artifacts was copied !!}\n`);
1215
- }
1216
- else {
1217
- writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright exported artifacts} in {magenta ${prettyHrtime(endTime)}}\n`);
1218
- }
1219
- if (this.artifactsToSource && (this.argv.shellIsolation || this.imageName(expanded))) {
1220
- time = process.hrtime();
1221
- await Utils.spawn(["rsync", "--exclude=/.gitlab-ci-reports/", "-a", `${cwd}/${stateDir}/artifacts/${safeJobName}/.`, cwd]);
1222
- if (reportDotenv != null) {
1223
- await Utils.spawn(["rsync", "-a", `${cwd}/${stateDir}/artifacts/${safeJobName}/.gitlab-ci-reports/dotenv/.`, cwd]);
1224
- }
1225
- endTime = process.hrtime(time);
1226
- writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright copied artifacts to cwd} in {magenta ${prettyHrtime(endTime)}}\n`);
1227
- }
1228
- }
1229
- async copyOut(cmd, stateDir, type, dockerCmdExtras) {
1230
- const safeJobName = this.safeJobName;
1231
- const buildVolumeName = this.buildVolumeName;
1232
- const cwd = this.argv.cwd;
1233
- const helperImageName = this.argv.helperImage;
1234
- await fs.mkdirp(`${cwd}/${stateDir}/${type}`);
1235
- if (this.imageName(this._variables)) {
1236
- const { stdout: containerId } = await Utils.bash(`${this.argv.containerExecutable} create -i ${dockerCmdExtras.join(" ")} -v ${buildVolumeName}:${this.ciProjectDir} -w ${this.ciProjectDir} ${helperImageName} bash -c "${cmd.replace(/"/g, "\\\"")}"`, cwd);
1237
- this._containersToClean.push(containerId);
1238
- await Utils.spawn([this.argv.containerExecutable, "start", containerId, "--attach"]);
1239
- await Utils.spawn([this.argv.containerExecutable, "cp", `${containerId}:/${type}/.`, `${stateDir}/${type}/.`], cwd);
1240
- }
1241
- else if (this.argv.shellIsolation) {
1242
- await Utils.bash(`bash -eo pipefail -c "${cmd}"`, `${cwd}/${stateDir}/builds/${safeJobName}`);
1243
- }
1244
- else if (!this.argv.shellIsolation) {
1245
- await Utils.bash(`bash -eo pipefail -c "${cmd}"`, `${cwd}`);
1246
- }
1247
- }
1248
- refreshLongRunningSilentTimeout(writeStreams) {
1249
- clearTimeout(this._longRunningSilentTimeout);
1250
- this._longRunningSilentTimeout = setTimeout(() => {
1251
- writeStreams.stdout(chalk `${this.formattedJobName} {grey > still running...}\n`);
1252
- this.refreshLongRunningSilentTimeout(writeStreams);
1253
- }, 10000);
1254
- }
1255
- getFinishedString() {
1256
- return chalk `${this.formattedJobName} {magentaBright finished} in {magenta ${this.prettyDuration}}`;
1257
- }
1258
- printFinishedString() {
1259
- if (this.jobStatus !== "success")
1260
- return;
1261
- this.writeStreams.stdout(`${this.getFinishedString()}\n`);
1262
- }
1263
- printExitedString(code) {
1264
- const writeStreams = this.writeStreams;
1265
- const finishedStr = this.getFinishedString();
1266
- // Won't print if jobStatus is "success" because that will be printed via the `printFinishedString()`
1267
- if (this.jobStatus === "warning") {
1268
- writeStreams.stderr(chalk `${finishedStr} {black.bgYellowBright WARN ${code.toString()} }\n`);
1269
- }
1270
- else if (this.jobStatus === "failed") {
1271
- writeStreams.stderr(chalk `${finishedStr} {black.bgRed FAIL ${code.toString()} }\n`);
1272
- }
1273
- }
1274
- printAfterScriptExitedString(code) {
1275
- const writeStreams = this.writeStreams;
1276
- const finishedStr = this.getFinishedString();
1277
- if (code !== 0) {
1278
- writeStreams.stderr(chalk `${finishedStr} {black.bgYellowBright WARN ${code.toString()} } after_script\n`);
1279
- }
1280
- }
1281
- async createDockerNetwork(networkName) {
1282
- const { stdout: networkId } = await Utils.spawn([this.argv.containerExecutable, "network", "create", `${networkName}`]);
1283
- this._serviceNetworkId = networkId;
1284
- }
1285
- async startService(writeStreams, expanded, service) {
1286
- const cwd = this.argv.cwd;
1287
- let dockerCmd = `${this.argv.containerExecutable} create --interactive `;
1288
- this.refreshLongRunningSilentTimeout(writeStreams);
1289
- if (this.argv.umask) {
1290
- dockerCmd += "--user 0:0 ";
1291
- }
1292
- if (this.argv.userns != undefined) {
1293
- dockerCmd += `--userns=${this.argv.userns} `;
1294
- }
1295
- if (this.argv.privileged) {
1296
- dockerCmd += "--privileged ";
1297
- }
1298
- for (const device of this.argv.device) {
1299
- dockerCmd += `--device ${device} `;
1300
- }
1301
- if (this.argv.ulimit !== null) {
1302
- dockerCmd += `--ulimit nofile=${this.argv.ulimit} `;
1303
- }
1304
- for (const volume of this.argv.volume) {
1305
- dockerCmd += `--volume ${volume} `;
1306
- }
1307
- for (const extraHost of this.argv.extraHost) {
1308
- dockerCmd += `--add-host=${extraHost} `;
1309
- }
1310
- if (this.argv.caFile) {
1311
- const caFilePath = path.isAbsolute(this.argv.caFile) ? this.argv.caFile : path.resolve(this.argv.cwd, this.argv.caFile);
1312
- if (await fs.pathExists(caFilePath)) {
1313
- dockerCmd += `--volume ${caFilePath}:/etc/ssl/certs/ca-certificates.crt:ro `;
1314
- expanded["SSL_CERT_FILE"] = "/etc/ssl/certs/ca-certificates.crt";
1315
- expanded["SSL_CERT_DIR"] = "/etc/ssl/certs";
1316
- }
1317
- }
1318
- const serviceAlias = service.alias;
1319
- const serviceName = service.name;
1320
- const serviceNameWithoutVersion = serviceName.replace(/(.*)(:.*)/, "$1");
1321
- const aliases = new Set();
1322
- aliases.add(serviceNameWithoutVersion.replaceAll("/", "-"));
1323
- aliases.add(serviceNameWithoutVersion.replaceAll("/", "__"));
1324
- if (serviceAlias) {
1325
- aliases.add(serviceAlias);
1326
- }
1327
- for (const [key, val] of Object.entries(expanded)) {
1328
- // Replacing `'` with `'\''` to correctly handle single quotes(if `val` contains `'`) in shell commands
1329
- dockerCmd += ` -e '${key}=${val.toString().replace(/'/g, "'\\''")}' \\\n`;
1330
- }
1331
- const serviceEntrypoint = service.entrypoint;
1332
- if (serviceEntrypoint) {
1333
- dockerCmd += `--entrypoint ${Utils.safeBashString(serviceEntrypoint[0])} `;
1334
- }
1335
- dockerCmd += `--volume ${this.buildVolumeName}:${this.ciProjectDir} `;
1336
- dockerCmd += `--volume ${this.tmpVolumeName}:${this.fileVariablesDir} `;
1337
- // The default podman network mode is not `bridge`, which means a `podman network connect` call will fail
1338
- // when connecting user defined networks. The workaround is to use a user defined network on container
1339
- // creation.
1340
- //
1341
- // See https://github.com/containers/podman/issues/19577
1342
- dockerCmd += `--network ${this._serviceNetworkId} `;
1343
- for (const alias of aliases) {
1344
- dockerCmd += `--network-alias ${alias} `;
1345
- }
1346
- dockerCmd += `${serviceName} `;
1347
- if (serviceEntrypoint?.length ?? 0 > 1) {
1348
- serviceEntrypoint?.slice(1).forEach((e) => {
1349
- dockerCmd += `${Utils.safeBashString(e)} `;
1350
- });
1351
- }
1352
- (service.command ?? []).forEach((e) => dockerCmd += `"${e.replace(/\$/g, "\\$")}" `);
1353
- const time = process.hrtime();
1354
- const { stdout: containerId } = await Utils.bash(dockerCmd, cwd);
1355
- this._containersToClean.push(containerId);
1356
- for (const network of this.argv.network) {
1357
- await Utils.spawn([this.argv.containerExecutable, "network", "connect", network, `${containerId}`]);
1358
- }
1359
- await Utils.spawn([this.argv.containerExecutable, "start", `${containerId}`]);
1360
- const endTime = process.hrtime(time);
1361
- writeStreams.stdout(chalk `${this.formattedJobName} {magentaBright started service image: ${serviceName} with aliases: ${Array.from(aliases).join(", ")}} in {magenta ${prettyHrtime(endTime)}}\n`);
1362
- return containerId;
1363
- }
1364
- async serviceHealthCheck(writeStreams, service, serviceIndex, serviceContainerLogFile) {
1365
- const serviceAlias = service.alias;
1366
- const serviceName = service.name;
1367
- const waitImageName = this.argv.waitImage;
1368
- const { stdout } = await Utils.spawn([this.argv.containerExecutable, "image", "inspect", serviceName]);
1369
- const imageInspect = JSON.parse(stdout);
1370
- // Copied from the startService block. Important thing is that the aliases match
1371
- const serviceNameWithoutVersion = serviceName.replace(/(.*)(:.*)/, "$1");
1372
- const aliases = [serviceNameWithoutVersion.replaceAll("/", "-"), serviceNameWithoutVersion.replaceAll("/", "__")];
1373
- if (serviceAlias) {
1374
- aliases.push(serviceAlias);
1375
- }
1376
- const uniqueAlias = aliases[aliases.length - 1];
1377
- if ((imageInspect[0]?.Config?.ExposedPorts ?? null) === null) {
1378
- return writeStreams.stderr(chalk `${this.formattedJobName} {yellow Could not find exposed tcp ports ${serviceName}}\n`);
1379
- }
1380
- const time = process.hrtime();
1381
- try {
1382
- // Iterate over each port defined in the image, and try to connect to the alias
1383
- await Promise.any(Object.keys(imageInspect[0].Config.ExposedPorts).map((port) => {
1384
- if (!port.endsWith("/tcp"))
1385
- return;
1386
- const portNum = parseInt(port.replace("/tcp", ""));
1387
- const containerName = `gcl-wait-for-it-${this.jobId}-${serviceIndex}-${portNum}`;
1388
- const spawnCmd = [this.argv.containerExecutable, "run", "--rm", `--name=${containerName}`, "--network", `${this._serviceNetworkId}`, `${waitImageName}`, `${uniqueAlias}:${portNum}`, "-t", "30"];
1389
- this._containersToClean.push(containerName);
1390
- return Utils.spawn(spawnCmd);
1391
- }));
1392
- const endTime = process.hrtime(time);
1393
- writeStreams.stdout(chalk `${this.formattedJobName} {greenBright service image: ${serviceName} healthcheck passed in {green ${prettyHrtime(endTime)}}}\n`);
1394
- }
1395
- catch (e) {
1396
- if (!(e instanceof AggregateError))
1397
- throw e;
1398
- e.errors.forEach((singleError) => {
1399
- writeStreams.stdout(chalk `${this.formattedJobName} {redBright service image: ${serviceName} healthcheck failed}\n`);
1400
- singleError.message.split(/\r?\n/g).forEach((line) => {
1401
- writeStreams.stdout(chalk `${this.formattedJobName} {redBright ${line}}\n`);
1402
- });
1403
- writeStreams.stdout(chalk `${this.formattedJobName} {redBright also see (${serviceContainerLogFile})}\n`);
1404
- });
1405
- }
1406
- finally {
1407
- // Kill all wait-for-it containers, when one have been successful
1408
- await Promise.allSettled(Object.keys(imageInspect[0].Config.ExposedPorts).map((port) => {
1409
- if (!port.endsWith("/tcp"))
1410
- return;
1411
- const portNum = parseInt(port.replace("/tcp", ""));
1412
- return Utils.spawn([this.argv.containerExecutable, "rm", "-vf", `gcl-wait-for-it-${this.jobId}-${serviceIndex}-${portNum}`]);
1413
- }));
1414
- }
1415
- }
1416
- async fetchTriggerInclude() {
1417
- const { cwd, stateDir } = this.argv;
1418
- fs.mkdirpSync(`${cwd}/${stateDir}/includes/triggers`);
1419
- let contents = {};
1420
- for (const include of this.jobData.trigger?.include ?? []) {
1421
- if (include["local"]) {
1422
- const expandedInclude = Utils.expandText(include["local"], this._variables);
1423
- validateIncludeLocal(expandedInclude);
1424
- const files = await resolveIncludeLocal(expandedInclude, cwd);
1425
- if (files.length == 0) {
1426
- throw new AssertionError({ message: `Local include file \`${include["local"]}\` specified in \`.${this.name}\` cannot be found!` });
1427
- }
1428
- for (const file of files) {
1429
- const content = await Parser.loadYaml(file, {});
1430
- contents = {
1431
- ...contents,
1432
- ...content,
1433
- };
1434
- }
1435
- }
1436
- else if (include["artifact"]) {
1437
- const content = await Parser.loadYaml(`${cwd}/${stateDir}/artifacts/${include["job"]}/${include["artifact"]}`, {});
1438
- contents = {
1439
- ...contents,
1440
- ...content,
1441
- };
1442
- }
1443
- else if (include["project"]) {
1444
- this.writeStreams.memoStdout(chalk `{bgYellowBright WARN } \`{blueBright ${this.name}.trigger.include.*.project}\` will be no-op. It is currently not implemented\n`);
1445
- }
1446
- else if (include["template"]) {
1447
- this.writeStreams.memoStdout(chalk `{bgYellowBright WARN } \`{blueBright ${this.name}.trigger.include.*.template}\` will be no-op. It is currently not implemented\n`);
1448
- }
1449
- }
1450
- const target = `${cwd}/${stateDir}/includes/triggers/${this.name}.yml`;
1451
- fs.writeFileSync(target, yaml.dump(contents));
1452
- }
1453
- }
1454
- export async function cleanupJobResources(jobs) {
1455
- if (!jobs)
1456
- return;
1457
- const promises = [];
1458
- for (const job of jobs) {
1459
- promises.push(job.cleanupResources());
1460
- }
1461
- await Promise.all(promises);
1462
- }
1463
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiam9iLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ25DLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUMxQixPQUFPLFlBQVksTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQzVCLE9BQU8sRUFBQyxLQUFLLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFHakMsT0FBTyxNQUFNLEVBQUUsRUFBQyxjQUFjLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFDOUMsT0FBTyxFQUFDLEtBQUssRUFBQyxNQUFNLFlBQVksQ0FBQztBQUVqQyxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFFMUIsT0FBTyxFQUFDLDJCQUEyQixFQUFFLDZCQUE2QixFQUFFLHdCQUF3QixFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDeEgsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUNyQyxPQUFPLEtBQUssSUFBSSxNQUFNLFNBQVMsQ0FBQztBQUNoQyxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sYUFBYSxDQUFDO0FBQ25DLE9BQU8sRUFBQyxtQkFBbUIsRUFBRSxvQkFBb0IsRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQy9FLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFDbEMsT0FBTyxZQUFZLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBRTdCLE1BQU0sNEJBQTRCLEdBQUcsNkJBQTZCLENBQUM7QUEwQ25FLE1BQU0sTUFBTSxHQUFHLENBQUMsR0FBVyxFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBRXpELE1BQU0sYUFBYSxHQUFHLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUU7SUFDckQsSUFBSSxFQUFFLFNBQVM7SUFDZixLQUFLLEVBQUUsU0FBUztJQUNoQixJQUFJLEVBQUUsU0FBUztJQUNmLE1BQU0sRUFBRSxTQUFTO0lBQ2pCLE1BQU0sRUFBRSxTQUFTO0lBQ2pCLE1BQU0sRUFBRSxLQUFLO0NBQ2hCLENBQUMsQ0FBQztBQVlILE1BQU0sT0FBTyxHQUFHO0lBQ0osYUFBYTtRQUNqQixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFFRCxNQUFNLENBQVUsZUFBZSxHQUFHLElBQUksR0FBRyxDQUFDO1FBQ3RDLFNBQVMsRUFBRSxxQkFBcUIsRUFBRSxPQUFPLEVBQUUsVUFBVTtRQUNyRCxRQUFRLEVBQUUsZUFBZSxFQUFFLFNBQVM7UUFDcEMsY0FBYyxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLGFBQWE7S0FDbEUsQ0FBQyxDQUFDO0lBRU0sSUFBSSxDQUFPO0lBQ1gsSUFBSSxDQUFTO0lBQ2IsUUFBUSxDQUFTO0lBQ2pCLFlBQVksQ0FBa0I7SUFDOUIsV0FBVyxDQUE2RjtJQUN4RyxLQUFLLENBQVM7SUFDZCxLQUFLLENBQWE7SUFFbEIsWUFBWSxDQUVuQjtJQUNPLElBQUksQ0FBUztJQUNiLE1BQU0sQ0FBVztJQUNqQixXQUFXLENBQVM7SUFDcEIsT0FBTyxDQUFVO0lBQ2pCLE9BQU8sQ0FFZDtJQUVNLGdCQUFnQixHQUE0QixFQUFFLENBQUM7SUFDL0MsbUJBQW1CLEdBQWtCLElBQUksQ0FBQztJQUMxQyxxQkFBcUIsR0FBRyxDQUFDLENBQUM7SUFDMUIsZ0JBQWdCLEdBQWtCLElBQUksQ0FBQztJQUN2QyxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ2pCLFlBQVksR0FBa0IsSUFBSSxDQUFDO0lBQ25DLGlCQUFpQixHQUFrQixJQUFJLENBQUM7SUFDeEMseUJBQXlCLEdBQW1CLENBQUMsQ0FBUSxDQUFDO0lBQ3RELFVBQVUsR0FBbUQsSUFBSSxDQUFDO0lBQ2xFLFdBQVcsR0FBa0IsSUFBSSxDQUFDO0lBQ2xDLGFBQWEsR0FBa0IsSUFBSSxDQUFDO0lBQ3BDLFVBQVUsQ0FBb0I7SUFDOUIsUUFBUSxDQUFvQjtJQUVuQixVQUFVLEdBQWEsRUFBRSxDQUFDO0lBQzFCLGdCQUFnQixHQUE0QixFQUFFLENBQUM7SUFDL0MsVUFBVSxHQUE0QixFQUFFLENBQUM7SUFDekMsa0JBQWtCLEdBQWEsRUFBRSxDQUFDO0lBQ2xDLHFCQUFxQixHQUFhLEVBQUUsQ0FBQztJQUNyQyxPQUFPLENBQU07SUFDYixZQUFZLENBQWU7SUFFNUMsWUFBYSxHQUFlO1FBQ3hCLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDekIsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUM7UUFDN0MsTUFBTSxrQkFBa0IsR0FBRyxHQUFHLENBQUMsa0JBQWtCLENBQUM7UUFDbEQsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQztRQUN0QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQ3JCLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDcEMsTUFBTSxlQUFlLEdBQUcsR0FBRyxDQUFDLGVBQWUsSUFBSSxJQUFJLENBQUM7UUFFcEQsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFlBQVksR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDO1FBQ3JDLElBQUksQ0FBQyxPQUFPLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQztRQUMzQixJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDO1FBQzdCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ2xDLElBQUksQ0FBQyxPQUFPLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQztRQUN4QixJQUFJLENBQUMsV0FBVyxHQUFHLEdBQUcsQ0FBQyxXQUFXLENBQUM7UUFDbkMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEdBQUcsQ0FBQyxlQUFlLENBQUM7UUFFNUMsSUFBSSxDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDbEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsU0FBUyxJQUFJLElBQUksQ0FBQztRQUVqRSxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLElBQUksWUFBWSxDQUFDO1FBQ3pDLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUM7UUFDbkMsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUMsYUFBYSxJQUFJLEtBQUssQ0FBQztRQUNuRCxJQUFJLENBQUMsWUFBWSxHQUFHLE9BQU8sQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDO1FBQ2pELElBQUksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUM7UUFDbkMsSUFBSSxDQUFDLFdBQVcsR0FBRyxPQUFPLE9BQU8sQ0FBQyxXQUFXLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFDLElBQUksRUFBRSxPQUFPLENBQUMsV0FBVyxFQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsRUFBQyxHQUFHLE9BQU8sQ0FBQyxXQUFXLEVBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRWxLLE1BQU0sZUFBZSxHQUFHLEdBQUcsQ0FBQyxlQUFlLElBQUksRUFBRSxDQUFDO1FBQ2xELE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxrQkFBa0IsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUMvRixNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMzRCxJQUFJLENBQUMsVUFBVSxHQUFHLEVBQUMsR0FBRyxtQkFBbUIsRUFBRSxHQUFHLElBQUksQ0FBQyxlQUFlLEVBQUUsR0FBRyxZQUFZLEVBQUUsR0FBRyxlQUFlLEVBQUUsR0FBRyxhQUFhLEVBQUUsR0FBRyxhQUFhLEVBQUMsQ0FBQztRQUU3SSxJQUFJLElBQUksQ0FBQyxLQUFLLElBQUksZUFBZSxFQUFFLENBQUM7WUFDaEMsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFFeEQsb0NBQW9DO1lBQ3BDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRTtnQkFDeEMsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDO2dCQUNqRixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7b0JBQ1gsT0FBTztnQkFDWCxDQUFDO2dCQUVELE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxFQUFFO29CQUMzQyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQzVELENBQUMsQ0FBQyxDQUFDO2dCQUNILEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1lBQ3JDLENBQUMsQ0FBQyxDQUFDO1lBRUgsbUNBQW1DO1lBQ25DLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRTtnQkFDeEMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDL0QsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUNWLE9BQU87Z0JBQ1gsQ0FBQztnQkFDRCxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtvQkFDdEMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUN4RCxDQUFDLENBQUMsQ0FBQztnQkFDSCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztZQUNuQyxDQUFDLENBQUMsQ0FBQztRQUNQLENBQUM7UUFFRCxJQUFJLGFBQW1ELENBQUM7UUFDeEQsaURBQWlEO1FBQ2pELElBQUksSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2IsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLGNBQWMsQ0FBQyxFQUFDLElBQUksRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUMsRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ2hKLElBQUksQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQztZQUM1QixJQUFJLENBQUMsWUFBWSxHQUFHLFVBQVUsQ0FBQyxZQUFZLENBQUM7WUFDNUMsYUFBYSxHQUFHLFVBQVUsQ0FBQyxTQUFTLENBQUM7WUFDckMsSUFBSSxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ25CLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQztZQUM3QyxDQUFDO1lBQ0QsSUFBSSxDQUFDLFVBQVUsR0FBRyxFQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxHQUFHLGFBQWEsRUFBRSxHQUFHLGFBQWEsRUFBQyxDQUFDO1FBQy9FLENBQUM7UUFFRCxxQ0FBcUM7UUFDckMsSUFBSSxJQUFJLENBQUMsV0FBVyxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sc0JBQXNCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7WUFDckQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztZQUMxRSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxLQUFLLHNCQUFzQixFQUFFLENBQUM7Z0JBQ25ELGlGQUFpRjtnQkFDakYsbUJBQW1CLENBQUMscUJBQXFCLENBQUMsR0FBRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN0RyxDQUFDO1lBQ0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUM1RSxDQUFDO1FBQ0QsTUFBTSxtQkFBbUIsR0FBRyxLQUFLLENBQUMsdUJBQXVCLENBQUMsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUV2SCxNQUFNLG9CQUFvQixHQUFHLEVBQUMsR0FBRyxJQUFJLENBQUMsZUFBZSxFQUFFLEdBQUcsWUFBWSxFQUFFLEdBQUcsZUFBZSxFQUFFLEdBQUcsYUFBYSxFQUFFLEdBQUcsbUJBQW1CLEVBQUUsR0FBRyxhQUFhLEVBQUMsQ0FBQztRQUN4SixJQUFJLENBQUMseUNBQXlDLENBQUMsbUJBQW1CLEVBQUUsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFFckgsdURBQXVEO1FBQ3ZELElBQUksQ0FBQyxVQUFVLEdBQUcsRUFBQyxHQUFHLG1CQUFtQixFQUFFLEdBQUcsb0JBQW9CLEVBQUMsQ0FBQztRQUNwRSxzREFBc0Q7UUFDdEQsS0FBSyxNQUFNLGFBQWEsSUFBSSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDOUMsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzFDLENBQUM7UUFDRCw4Q0FBOEM7UUFDOUMsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxVQUFVLEdBQUcsRUFBQyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsR0FBRyxFQUFDLHVCQUF1QixFQUFFLEdBQUcsRUFBQyxFQUFDLENBQUM7UUFDOUUsQ0FBQztRQUVELE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFBLGVBQWUsSUFBSSxDQUFDLElBQUksOEJBQThCLENBQUMsQ0FBQztRQUVsRyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEVBQUUsS0FBSyxDQUFBLEdBQUcsSUFBSSxDQUFDLGdCQUFnQiwwRUFBMEUsQ0FBQyxDQUFDO1FBRXhLLElBQUksSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDM0YsTUFBTSxJQUFJLGNBQWMsQ0FBQyxFQUFDLE9BQU8sRUFBRSxHQUFHLElBQUksQ0FBQyxnQkFBZ0Isb0VBQW9FLEVBQUMsQ0FBQyxDQUFDO1FBQ3RJLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxjQUFjLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDbEUsTUFBTSxJQUFJLGNBQWMsQ0FBQyxFQUFDLE9BQU8sRUFBRSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsK0NBQStDLEVBQUMsQ0FBQyxDQUFDO1FBQ2pILENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUN4RCxLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBTSxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNuRCxDQUFDLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNoRCxNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsS0FBSyxDQUFBLFNBQVMsSUFBSSxDQUFDLElBQUksV0FBVyxDQUFDLCtDQUErQyxDQUFDLENBQUM7WUFDN0ksTUFBTSxDQUFDLENBQUMsWUFBWSxFQUFFLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQSxTQUFTLElBQUksQ0FBQyxJQUFJLFdBQVcsQ0FBQyxzREFBc0QsQ0FBQyxDQUFDO1lBQzNKLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxLQUFLLENBQUEsU0FBUyxJQUFJLENBQUMsSUFBSSxXQUFXLENBQUMsdUJBQXVCLENBQUMsQ0FBQztRQUMvRixDQUFDO1FBRUQsS0FBSyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDdEQsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFBLFNBQVMsSUFBSSxDQUFDLElBQUksY0FBYyxDQUFDLHFCQUFxQixDQUFDLENBQUM7WUFDNUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUEsU0FBUyxJQUFJLENBQUMsSUFBSSxjQUFjLENBQUMsNEJBQTRCLENBQUMsQ0FBQztZQUNuSCxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxFQUFFLEtBQUssQ0FBQSxTQUFTLElBQUksQ0FBQyxJQUFJLGNBQWMsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1FBQ2hJLENBQUM7UUFFRCxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEtBQUssSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUUsS0FBSyxDQUFBLFNBQVMsSUFBSSxDQUFDLElBQUksb0NBQW9DLENBQUMsQ0FBQztRQUVuSSxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNyRCxLQUFLLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDekIsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtvQkFDbEIsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7b0JBQzNDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxDQUFBLFNBQVMsSUFBSSxDQUFDLElBQUksK0RBQStELENBQUMsQ0FBQztnQkFDeEgsQ0FBQyxDQUFDLENBQUM7WUFDUCxDQUFDO1FBQ0wsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNLLHlDQUF5QyxDQUFFLG1CQUE2QyxFQUFFLG9CQUE4QyxFQUFFLGtDQUE0QztRQUMxTCxNQUFNLHVCQUF1QixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNqRSxNQUFNLHdCQUF3QixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUVuRSxNQUFNLCtCQUErQixHQUFHLHdCQUF3QixDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLHVCQUF1QixDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzNLLElBQUksK0JBQStCLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQzlDLE9BQU87UUFDWCxDQUFDO1FBRUQsTUFBTSxZQUFZLEdBQUcsOEhBQThILENBQUM7UUFDcEosSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFBOzBCQUNoQixZQUFZLENBQUMsdUNBQXVDLEVBQUUsWUFBWSxDQUFDLFdBQVcsK0JBQStCOzs7aUNBR3RHLCtCQUErQjs7bUNBRTdCLCtCQUErQjtDQUNqRSxDQUFDLENBQUM7SUFDQyxDQUFDO0lBRUQ7O09BRUc7SUFDSyxvQkFBb0IsQ0FBRSxHQUFlO1FBQ3pDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFDdkIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQztRQUNyQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUNwQyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBRTdCLElBQUksV0FBbUIsQ0FBQztRQUN4QixJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUN4QixXQUFXLEdBQUcsU0FBUyxDQUFDO1lBQ3hCLElBQUksQ0FBQyxZQUFZLEdBQUcsR0FBRyxXQUFXLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUMzRixDQUFDO2FBQU0sSUFBSSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDN0IsV0FBVyxHQUFHLEdBQUcsR0FBRyxJQUFJLFFBQVEsV0FBVyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDOUQsSUFBSSxDQUFDLFlBQVksR0FBRyxXQUFXLENBQUM7UUFDcEMsQ0FBQzthQUFNLENBQUM7WUFDSixXQUFXLEdBQUcsR0FBRyxDQUFDO1lBQ2xCLElBQUksQ0FBQyxZQUFZLEdBQUcsV0FBVyxDQUFDO1FBQ3BDLENBQUM7UUFFRCxNQUFNLG1CQUFtQixHQUFHLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQztRQUVwRCxtQkFBbUIsQ0FBQyxXQUFXLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNuRCxtQkFBbUIsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLEVBQUUsQ0FBQztRQUNyRSxtQkFBbUIsQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQy9ELG1CQUFtQixDQUFDLGFBQWEsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3BELG1CQUFtQixDQUFDLGtCQUFrQixDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQztRQUNwSixtQkFBbUIsQ0FBQyxjQUFjLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN0RCxtQkFBbUIsQ0FBQyxlQUFlLENBQUMsR0FBRyxXQUFXLENBQUM7UUFDbkQsbUJBQW1CLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQzFELG1CQUFtQixDQUFDLFlBQVksQ0FBQyxHQUFHLEdBQUcsbUJBQW1CLENBQUMsZUFBZSxDQUFDLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLFdBQVcsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsb0JBQW9CO1FBQzFLLG1CQUFtQixDQUFDLGlCQUFpQixDQUFDLEdBQUcsR0FBRyxtQkFBbUIsQ0FBQyxlQUFlLENBQUMsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sY0FBYyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkssbUJBQW1CLENBQUMscUJBQXFCLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUM7UUFDMUUsbUJBQW1CLENBQUMscUJBQXFCLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNoSSxtQkFBbUIsQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsR0FBRyxJQUFJLEVBQUUsQ0FBQztRQUN4RSxtQkFBbUIsQ0FBQyxxQkFBcUIsQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsZUFBZSxJQUFJLEVBQUUsQ0FBQztRQUNyRixtQkFBbUIsQ0FBQyx1QkFBdUIsQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUU5RSxJQUFJLEdBQUcsQ0FBQyxTQUFTLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDekIsbUJBQW1CLENBQUMsZUFBZSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDOUQsQ0FBQztRQUNELG1CQUFtQixDQUFDLGVBQWUsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQzNELG1CQUFtQixDQUFDLGFBQWEsQ0FBQyxHQUFHLG1CQUFtQixDQUFDLGFBQWEsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLGtCQUFrQixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN0SyxtQkFBbUIsQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLGdCQUFnQixtQkFBbUIsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7UUFDbEgsT0FBTyxtQkFBbUIsQ0FBQztJQUMvQixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7OztPQVlHO0lBQ0ssd0JBQXdCLENBQUUsSUFBWTtRQUMxQyw2RUFBNkU7UUFDN0UsSUFBSSxJQUFJLEdBQUcsSUFBSTthQUNWLFdBQVcsRUFBRTthQUNiLE9BQU8sQ0FBQyxZQUFZLEVBQUUsR0FBRyxDQUFDO2FBQzFCLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFFekIsOEJBQThCO1FBQzlCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDdkIsSUFBSSxHQUFHLE9BQU8sSUFBSSxFQUFFLENBQUM7UUFDekIsQ0FBQztRQUVELHFFQUFxRTtRQUNyRSxJQUFJLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxJQUFJLElBQUksS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUNwQyw0REFBNEQ7WUFDNUQsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBRXpCLHNEQUFzRDtZQUN0RCxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN0QixJQUFJLElBQUksR0FBRyxDQUFDO1lBQ2hCLENBQUM7WUFFRCw4REFBOEQ7WUFDOUQsTUFBTSxPQUFPLEdBQUcsTUFBTTtpQkFDakIsVUFBVSxDQUFDLFFBQVEsQ0FBQztpQkFDcEIsTUFBTSxDQUFDLElBQUksQ0FBQztpQkFDWixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFbkIsb0RBQW9EO1lBQ3BELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLE9BQU8sRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTdELE9BQU8sSUFBSSxHQUFHLE1BQU0sQ0FBQztRQUN6QixDQUFDO1FBRUQseUVBQXlFO1FBQ3pFLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVELElBQUksU0FBUztRQUNULElBQUksSUFBSSxDQUFDLGtCQUFrQixJQUFJLElBQUk7WUFBRSxPQUFPLFNBQVMsQ0FBQztRQUN0RCxJQUFJLElBQUksQ0FBQyxrQkFBa0IsSUFBSSxDQUFDO1lBQUUsT0FBTyxTQUFTLENBQUM7UUFFbkQsSUFBSSxnQkFBZ0IsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDdkMsUUFBUSxPQUFPLFlBQVksRUFBRSxDQUFDO1lBQzFCLEtBQUssU0FBUztnQkFDVixJQUFJLFlBQVksRUFBRSxDQUFDO29CQUNmLGdCQUFnQixHQUFHLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7Z0JBQ2pELENBQUM7Z0JBQ0QsTUFBTTtZQUNWLEtBQUssUUFBUTtnQkFDVCxJQUFJLENBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztvQkFDM0MsZ0JBQWdCLEdBQUcsQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ2pELENBQUM7cUJBQU0sQ0FBQztvQkFDSixnQkFBZ0IsR0FBRyxZQUFZLENBQUMsVUFBVSxDQUFDO2dCQUMvQyxDQUFDO2dCQUNELE1BQU07WUFDVjtnQkFDSSxNQUFNLElBQUksS0FBSyxDQUFDLHFCQUFxQixPQUFPLFlBQVksRUFBRSxDQUFDLENBQUM7UUFDcEUsQ0FBQztRQUVELE9BQU8sZ0JBQWdCLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztJQUNyRixDQUFDO0lBRUQsSUFBSSxpQkFBaUI7UUFDakIsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLHNCQUFzQixDQUFDLElBQUksSUFBSTtZQUFFLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQzlGLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztJQUN2QyxDQUFDO0lBRUQsSUFBSSxjQUFjO1FBQ2QsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDaEIsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNwQixZQUFZLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQy9DLE1BQU0sQ0FBQztJQUNmLENBQUM7SUFFRCxJQUFJLGdCQUFnQjtRQUNoQixJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUM7UUFDaEIsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLENBQUM7WUFBRSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLE9BQU8sQ0FBQztRQUN2SSxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzlDLElBQUksYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzdFLEVBQUUsQ0FBQztRQUVQLCtDQUErQztRQUMvQyxPQUFPLEtBQUssQ0FBQSxHQUFHLGVBQWUsZUFBZSxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUM7SUFDL0YsQ0FBQztJQUVELElBQUksV0FBVztRQUNYLE9BQU8sS0FBSyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQsSUFBSSxLQUFLO1FBQ0wsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQztJQUN6QyxDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2YsT0FBTyxPQUFPLElBQUksQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLEtBQUssUUFBUSxDQUFDO0lBQ3pELENBQUM7SUFFRCxJQUFJLGFBQWE7UUFDYixPQUFPLE9BQU8sSUFBSSxDQUFDLFdBQVcsSUFBSSxJQUFJLENBQUMsS0FBSyxNQUFNLENBQUM7SUFDdkQsQ0FBQztJQUVELElBQUksUUFBUTtRQUNSLE1BQU0sUUFBUSxHQUFjLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUM7WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUV6QyxLQUFLLE1BQU0sT0FBTyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDakUsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLGVBQWUsQ0FBQyxFQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsRUFBQyxDQUFDLENBQUM7WUFDaEgsSUFBSSxXQUFXLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDOUQsSUFBSSxXQUFXLElBQUksRUFBRTtnQkFBRSxTQUFTO1lBQ2hDLFdBQVcsR0FBRyxXQUFXLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsV0FBVyxTQUFTLENBQUM7WUFDaEYsUUFBUSxDQUFDLElBQUksQ0FBQztnQkFDVixJQUFJLEVBQUUsV0FBVztnQkFDakIsVUFBVSxFQUFFLE9BQU8sQ0FBQyxZQUFZLENBQUMsSUFBSSxJQUFJO2dCQUN6QyxPQUFPLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLElBQUk7Z0JBQ25DLFNBQVMsRUFBRSxRQUFRO2dCQUNuQixLQUFLLEVBQUUsS0FBSyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsUUFBUSxDQUFDLElBQUksSUFBSTthQUM5RCxDQUFDLENBQUM7UUFDUCxDQUFDO1FBQ0QsT0FBTyxRQUFRLENBQUM7SUFDcEIsQ0FBQztJQUVELElBQUksWUFBWSxDQUFFLFlBQW9CO1FBQ2xDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxJQUFJLElBQUksRUFBRSx5Q0FBeUMsQ0FBQyxDQUFDO1FBQzlFLElBQUksQ0FBQyxhQUFhLEdBQUcsWUFBWSxDQUFDO0lBQ3RDLENBQUM7SUFDRCxJQUFJLFlBQVk7UUFDWixNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxpRUFBaUUsQ0FBQyxDQUFDO1FBQzlGLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQztJQUM5QixDQUFDO0lBRUQsSUFBSSxVQUFVLENBQUUsVUFBa0I7UUFDOUIsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksSUFBSSxFQUFFLHVDQUF1QyxDQUFDLENBQUM7UUFDMUUsSUFBSSxDQUFDLFdBQVcsR0FBRyxVQUFVLENBQUM7SUFDbEMsQ0FBQztJQUVELElBQUksVUFBVTtRQUNWLE9BQU8sSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUVELElBQUksU0FBUztRQUNULE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUMzQixDQUFDO0lBRUQsSUFBSSxTQUFTLENBQUUsU0FBeUQ7UUFDcEUsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLElBQUksSUFBSSxFQUFFLHNDQUFzQyxDQUFDLENBQUM7UUFDeEUsSUFBSSxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUM7SUFDaEMsQ0FBQztJQUVELElBQUksS0FBSztRQUNMLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxNQUFNLENBQUM7SUFDM0MsQ0FBQztJQUVELElBQUksV0FBVztRQUNYLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEtBQUssQ0FBQztJQUNuRCxDQUFDO0lBRUQsSUFBSSxjQUFjO1FBQ2QsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLElBQUksS0FBSyxDQUFDO0lBQ3RELENBQUM7SUFFRCxJQUFJLFdBQVc7UUFDWCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDaEQsQ0FBQztJQUVELElBQUksU0FBUztRQUNULE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQsZUFBZTtRQUNYLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQsSUFBSSxLQUFLO1FBQ0wsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN2QyxDQUFDO0lBRU0sS0FBSyxDQUFDLGtCQUFrQixDQUFFLEdBQVcsRUFBRSxRQUFpQyxFQUFFLFVBQWtCO1FBQy9GLE1BQU0sY0FBYyxHQUFHLENBQUMsS0FBYSxFQUFFLEVBQUU7WUFDckMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM3RCxJQUFJLE1BQU0sRUFBRSxDQUFDO2dCQUNULE9BQU8sR0FBRyxLQUFLLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLEdBQUcsQ0FBQztZQUM3RCxDQUFDO1lBRUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRTtnQkFDN0UsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQzlDLE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNqQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDYixPQUFPLEdBQUcsS0FBSyxJQUFJLFNBQVMsR0FBRyxDQUFDO1FBQ3BDLENBQUMsQ0FBQztRQUVGLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsR0FBRyxDQUFDO1FBRWxELElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxJQUFJLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUN6QyxPQUFPLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFJLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBRUQsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQVMsRUFBRSxFQUFFO1lBQ3pDLElBQUksSUFBSSxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3pDLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLElBQUksQ0FBQyxZQUFZLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQzNDLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDLFlBQVksR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RELENBQUM7WUFDRCxPQUFPLEdBQUcsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQzVCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxjQUFjLENBQUMsVUFBVSxDQUFDLEdBQUcsTUFBTSxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUM5RSxDQUFDO0lBRUQsSUFBSSxhQUFhO1FBQ2IsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDMUQsT0FBTyxPQUFPLGFBQWEsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQztJQUMvRSxDQUFDO0lBRUQsSUFBSSxZQUFZO1FBQ1osTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDeEQsT0FBTyxPQUFPLFlBQVksS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQztJQUM1RSxDQUFDO0lBRUQsSUFBSSxPQUFPO1FBQ1AsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN0QyxPQUFPLE9BQU8sTUFBTSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQzFELENBQUM7SUFFRCxJQUFJLE9BQU87UUFDUCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELEtBQUssQ0FBQyxvQkFBb0I7UUFDdEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFBLGtGQUFrRixDQUFDLENBQUM7UUFDdEgsTUFBTSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUNqQyxNQUFNLDhCQUE4QixHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBQyxHQUFHLElBQUksQ0FBQyxlQUFlLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsR0FBRyxJQUFJLEtBQUssRUFBRSxDQUFDLENBQUM7UUFFckosTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQztZQUN0RCxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQzFELElBQUksQ0FBQyxJQUFJLENBQUM7UUFDZCxNQUFNLE9BQU8sQ0FBQztZQUNWLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztZQUNwQyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsc0JBQXNCLElBQUksQ0FBQyxJQUFJLE1BQU07WUFDaEUsUUFBUSxFQUFFO2dCQUNOLEtBQUssQ0FBQSxpQkFBaUIsWUFBWSxFQUFFO2dCQUNwQyxvQ0FBb0M7YUFDdkMsQ0FBQyxNQUFNLENBQUMsOEJBQThCLENBQUM7U0FDM0MsRUFBRSxJQUFJLENBQUMsWUFBWSxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFRCxJQUFJLGtCQUFrQjtRQUNsQixPQUFPLElBQUksQ0FBQyxtQkFBbUIsQ0FBQztJQUNwQyxDQUFDO0lBRUQsSUFBSSxvQkFBb0I7UUFDcEIsT0FBTyxJQUFJLENBQUMscUJBQXFCLENBQUM7SUFDdEMsQ0FBQztJQUVELElBQUksT0FBTztRQUNQLE9BQU8sSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEtBQUssSUFBSSxDQUFDO0lBQzlELENBQUM7SUFFRCxJQUFJLFFBQVE7UUFDUixPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEtBQUssSUFBSSxDQUFDO0lBQy9ELENBQUM7SUFFRCxJQUFJLGVBQWU7UUFDZixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztJQUNqQyxDQUFDO0lBRUQsSUFBSSxnQkFBZ0I7UUFDaEIsT0FBTyx1Q0FBdUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUMxRyxDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2YsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUNuQyxPQUFPLEVBQUUsQ0FBQztRQUNkLENBQUM7YUFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQy9DLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDaEQsT0FBTyxNQUFNLENBQUMsV0FBVyxDQUNyQixNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUN0RixDQUFDO1FBQ04sQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDO0lBQ2pDLENBQUM7SUFFRCxLQUFLLENBQUMsS0FBSztRQUNQLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2YsTUFBTSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztZQUNsQyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsQ0FBQyxDQUFDLENBQUMsK0RBQStEO1lBQzdGLE9BQU87UUFDWCxDQUFDO1FBRUQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7UUFFckIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztRQUN2QixJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNuQyxJQUFJLENBQUMsVUFBVSxDQUFDLG1CQUFtQixDQUFDLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDO1FBQ3BGLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDdkMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLE1BQU0sSUFBSSxDQUFDLGtDQUFrQyxDQUFDLFlBQVksRUFBRSxLQUFLLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBQzVILE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLEVBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixFQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pILE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDM0MsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUN6QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO1FBRXJDLE1BQU0saUJBQWlCLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxRQUFRLFdBQVcsV0FBVyxNQUFNLENBQUM7UUFDbkYsTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDdkMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFFckMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNwQixZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsNkJBQTZCLFNBQVMsSUFBSSxPQUFPLGFBQWEsSUFBSSxDQUFDLEtBQUssTUFBTSxDQUFDLENBQUM7UUFDckksQ0FBQztRQUVELElBQUksU0FBUyxFQUFFLENBQUM7WUFDWixNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBRTlDLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUM7WUFDN0MsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztZQUN6QyxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztZQUUvQyxNQUFNLGNBQWMsR0FBRyxFQUFFLENBQUM7WUFDMUIsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLEdBQUcsZUFBZSxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUN0SCxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsR0FBRyxhQUFhLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3BILElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDakQsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUMvQyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7WUFFbEMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQywrQkFBK0IsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUVuRCxJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUM7WUFDckIsSUFBSSxRQUFRLEdBQUcsTUFBTSxDQUFDO1lBQ3RCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNuQixNQUFNLEVBQUMsTUFBTSxFQUFDLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSw0QkFBNEIsQ0FBQyxDQUFDLENBQUM7Z0JBQ3hKLFFBQVEsR0FBRyxNQUFNLENBQUM7Z0JBQ2xCLElBQUksUUFBUSxJQUFJLEtBQUssRUFBRSxDQUFDO29CQUNwQixRQUFRLEdBQUcsS0FBSyxDQUFDO2dCQUNyQixDQUFDO1lBQ0wsQ0FBQztZQUNELElBQUksZUFBZSxFQUFFLENBQUM7Z0JBQ2xCLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsZUFBZSxDQUFDLENBQUM7WUFDeEQsQ0FBQztZQUVELE1BQU0sbUJBQW1CLEdBQUc7Z0JBQ3hCLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsUUFBUSxFQUFFLFlBQVk7Z0JBQ3JELFlBQVksZUFBZSxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7Z0JBQ2xELFlBQVksYUFBYSxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTthQUN2RCxDQUFDO1lBRUYsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNuQixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ3hILElBQUksTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7b0JBQ2xDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxZQUFZLFVBQVUsd0NBQXdDLENBQUMsQ0FBQztnQkFDN0YsQ0FBQztZQUNMLENBQUM7WUFFRCxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsR0FBRyxlQUFlLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFNBQVMsUUFBUSxPQUFPLElBQUksQ0FBQyxZQUFZLGFBQWEsUUFBUSxPQUFPLElBQUksQ0FBQyxZQUFZLGFBQWEsUUFBUSxzQkFBc0IsUUFBUSxXQUFXLENBQUMsQ0FBQztZQUVqTixNQUFNLEVBQUMsTUFBTSxFQUFFLFdBQVcsRUFBQyxHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDL0UsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUMxQyxJQUFJLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUM7Z0JBQ3hDLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLEdBQUcsZ0JBQWdCLElBQUksRUFBRSxHQUFHLFdBQVcsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNsSSxJQUFJLENBQUMsK0JBQStCLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDdkQsQ0FBQztZQUNELE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLFFBQVEsbUJBQW1CLEVBQUUsR0FBRyxXQUFXLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQy9JLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDL0YsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFdBQVcsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN2RixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3JDLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFBLEdBQUcsSUFBSSxDQUFDLGdCQUFnQiw2QkFBNkIsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIseUJBQXlCLFlBQVksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEssQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsQ0FBQztZQUN4QixxRkFBcUY7WUFDckYseUJBQXlCO1lBQ3pCLEtBQUssTUFBTSxPQUFPLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDdEMsSUFBSSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztvQkFDckMsTUFBTSxJQUFJLGNBQWMsQ0FBQyxFQUFDLE9BQU8sRUFBRSx1REFBdUQsT0FBTyxHQUFHLEVBQUMsQ0FBQyxDQUFDO2dCQUMzRyxDQUFDO1lBQ0wsQ0FBQztZQUVELE1BQU0sSUFBSSxDQUFDLG1CQUFtQixDQUFDLG1CQUFtQixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUVoRSxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQ2IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsRUFBRTtnQkFDOUMsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztnQkFDakMsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksRUFBRSxXQUFXLENBQUMsQ0FBQztnQkFDaEQsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFBQyxHQUFHLFFBQVEsRUFBRSxHQUFHLE9BQU8sQ0FBQyxTQUFTLEVBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUN0SSxNQUFNLHVCQUF1QixHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsUUFBUSxvQkFBb0IsSUFBSSxDQUFDLFdBQVcsSUFBSSxXQUFXLElBQUksWUFBWSxNQUFNLENBQUM7Z0JBQ3RJLE1BQU0sSUFBSSxDQUFDLGtCQUFrQixDQUFDLFlBQVksRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLHVCQUF1QixDQUFDLENBQUM7Z0JBQzVGLE1BQU0sRUFBQyxNQUFNLEVBQUUsTUFBTSxFQUFDLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxNQUFNLEVBQUUsa0JBQWtCLENBQUMsQ0FBQyxDQUFDO2dCQUN4RyxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsdUJBQXVCLENBQUMsQ0FBQztnQkFDN0MsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyx1QkFBdUIsRUFBRSxtQkFBbUIsTUFBTSxxQkFBcUIsTUFBTSxJQUFJLENBQUMsQ0FBQztZQUNuSCxDQUFDLENBQUMsQ0FDTCxDQUFDO1FBQ04sQ0FBQztRQUVELE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNwQyxJQUFJLElBQUksQ0FBQyxtQkFBbUIsSUFBSSxJQUFJO1lBQUUsTUFBTSxLQUFLLENBQUMsMkNBQTJDLENBQUMsQ0FBQztRQUUvRixNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUV0QyxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztRQUN0QixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDakUsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFFM0IsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDckQsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQztRQUV6RCxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUMzQixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsTUFBTSxLQUFLLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDM0gsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsZ0JBQWdCO1FBQ2xCLFlBQVksQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUU3QyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPO1lBQUUsT0FBTztRQUUvQixJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDckMsSUFBSSxDQUFDO2dCQUNELE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7WUFDaEcsQ0FBQztZQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ1QsTUFBTSxDQUFDLENBQUMsWUFBWSxLQUFLLEVBQUUsMkJBQTJCLENBQUMsQ0FBQztZQUM1RCxDQUFDO1FBQ0wsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDO2dCQUNELE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNyRyxDQUFDO1lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDVCxNQUFNLENBQUMsQ0FBQyxZQUFZLEtBQUssRUFBRSwyQkFBMkIsQ0FBQyxDQUFDO1lBQzVELENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3hDLElBQUksQ0FBQztnQkFDRCxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDO1lBQ3RHLENBQUM7WUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNULE1BQU0sQ0FBQyxDQUFDLFlBQVksS0FBSyxFQUFFLDJCQUEyQixDQUFDLENBQUM7WUFDNUQsQ0FBQztRQUNMLENBQUM7UUFFRCxNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUM7UUFDdEIsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDakMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBQyxDQUFDLENBQUMsQ0FBQztRQUNqRSxDQUFDO1FBQ0QsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRTlCLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDO1FBQy9DLElBQUksQ0FBQztZQUNELE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSxFQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBQyxDQUFDLENBQUM7UUFDbEUsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDVCxNQUFNLENBQUMsQ0FBQyxZQUFZLEtBQUssRUFBRSwyQkFBMkIsQ0FBQyxDQUFDO1FBQzVELENBQUM7SUFDTCxDQUFDO0lBRU8sNkJBQTZCO1FBQ2pDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDdkIsT0FBTyxFQUFFLENBQUM7UUFDZCxDQUFDO1FBQ0QsSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLFFBQVEsSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDNUUsT0FBTywySEFBMkgsQ0FBQztRQUN2SSxDQUFDO1FBQ0QsT0FBTyx1QkFBdUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUMzSCxDQUFDO0lBRU8sc0JBQXNCLENBQUUsT0FBaUI7UUFDN0MsSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ2IsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3ZCLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDcEMsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLGlDQUFpQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDaEYsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQzNGLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNuQixHQUFHLElBQUksS0FBSyxDQUFBLGtCQUFrQixJQUFJLEdBQUcsYUFBYSxNQUFNLENBQUM7WUFDN0QsQ0FBQztpQkFBTSxDQUFDO2dCQUNKLDJEQUEyRDtnQkFDM0QsR0FBRyxJQUFJLFNBQVMsNEJBQTRCLElBQUksSUFBSSxHQUFHLGFBQWEsS0FBSyxDQUFDO1lBQzlFLENBQUM7WUFDRCx3QkFBd0I7WUFDeEIsR0FBRyxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUM7UUFDekIsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLEdBQUcsQ0FBQztJQUNmLENBQUM7SUFFTyxLQUFLLENBQUMsYUFBYSxDQUFFLFlBQTBCLEVBQUUsUUFBaUM7UUFDdEYsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFFakUsTUFBTSxHQUFHLEdBQWEsRUFBRSxDQUFDO1FBQ3pCLEtBQUssTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDNUMsTUFBTSxlQUFlLEdBQUcsTUFBTSxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3RGLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7Z0JBQ2xCLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUMzQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsNENBQTRDLElBQUksSUFBSSxDQUFDLENBQUM7Z0JBQ3ZHLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLFFBQVEsQ0FBQyxvQkFBb0IsSUFBSSxlQUFlLEVBQUUsQ0FBQyxDQUFDO2dCQUNyRyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxHQUFHLFVBQVUsSUFBSSxJQUFJLENBQUMsWUFBWSxJQUFJLElBQUksRUFBRSxDQUFDLENBQUM7WUFDakUsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDZixDQUFDO0lBRU8sS0FBSyxDQUFDLGNBQWMsQ0FBRSxRQUFpQztRQUMzRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDM0QsUUFBUSxDQUFDLGVBQWUsQ0FBQyxHQUFHLFNBQVMsQ0FBQztRQUV0QyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDNUUsUUFBUSxDQUFDLGVBQWUsQ0FBQyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO1FBRWxGLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRU8sS0FBSyxDQUFDLGdCQUFnQixDQUFFLFFBQWlDO1FBQzdELE1BQU0sT0FBTyxHQUFHLHlCQUF5QixDQUFDO1FBQzFDLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUYsSUFBSSxDQUFDLDRCQUE0QixDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFFTyxLQUFLLENBQUMsV0FBVyxDQUFFLE9BQWlCLEVBQUUsUUFBaUMsRUFBRSxPQUFlO1FBQzVGLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQzFCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ3BDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDckMsTUFBTSxlQUFlLEdBQUcsR0FBRyxHQUFHLElBQUksUUFBUSxXQUFXLFdBQVcsTUFBTSxDQUFDO1FBQ3ZFLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUM7UUFDN0MsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztRQUN6QyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzNDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFFdkMsSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSTtZQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRXpELElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDO1lBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLG1CQUFtQixPQUFPLEtBQUssQ0FBQyxDQUFDO1FBRTFHLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEdBQUcsSUFBSSxRQUFRLGNBQWMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUUvRCxxRUFBcUU7UUFDckUsSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3pDLE1BQU0sS0FBSyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRSxRQUFRLEVBQUUsR0FBRyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ25FLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNuQixJQUFJLElBQUksR0FBRyxvQkFBb0IsQ0FBQztZQUNoQyxJQUFJLElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRTdDLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUU7Z0JBQzlCLEdBQUc7Z0JBQ0gsS0FBSyxFQUFFLE1BQU07Z0JBQ2IsS0FBSyxFQUFFLENBQUMsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUM7Z0JBQ3hDLEdBQUcsRUFBRSxFQUFDLEdBQUcsUUFBUSxFQUFFLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBQzthQUNyQyxDQUFDLENBQUM7WUFDSCxPQUFPLElBQUksT0FBTyxDQUFTLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO2dCQUMzQyxLQUFLLGFBQWEsQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzVELEtBQUssYUFBYSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3pELENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNyQixRQUFRLENBQUMsa0JBQWtCLENBQUMsR0FBRyxRQUFRLENBQUMsa0JBQWtCLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxpQkFBaUIsT0FBTyxDQUFDO1lBQ2pHLFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixXQUFXLENBQUM7UUFDakgsQ0FBQztRQUVELElBQUksQ0FBQywrQkFBK0IsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUVuRCxJQUFJLFNBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNsQyxJQUFJLFNBQVMsR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLHlCQUF5QixJQUFJLENBQUMsNkJBQTZCLEVBQUUsR0FBRyxDQUFDO1lBQ2pILElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDdkIsU0FBUyxJQUFJLGVBQWUsQ0FBQztZQUNqQyxDQUFDO1lBRUQsS0FBSyxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNwQyxTQUFTLElBQUksWUFBWSxNQUFNLEdBQUcsQ0FBQztZQUN2QyxDQUFDO1lBRUQsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDNUIsU0FBUyxJQUFJLG1CQUFtQixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDO1lBQ3hELENBQUM7WUFFRCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2xCLFNBQVMsSUFBSSxhQUFhLENBQUM7WUFDL0IsQ0FBQztZQUVELElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksU0FBUyxFQUFFLENBQUM7Z0JBQ2hDLFNBQVMsSUFBSSxZQUFZLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUM7WUFDakQsQ0FBQztZQUVELElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO2dCQUNoQyxTQUFTLElBQUksa0JBQWtCLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLElBQUksQ0FBQztZQUNyRSxDQUFDO1lBRUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMzQyxJQUFJLFNBQVMsRUFBRSxDQUFDO2dCQUNaLFNBQVMsSUFBSSxVQUFVLFNBQVMsR0FBRyxDQUFDO1lBQ3hDLENBQUM7WUFFRCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDN0IsTUFBTSxVQUFVLEdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztnQkFFdEQsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO29CQUNqRCxNQUFNLElBQUksS0FBSyxDQUFDLG1DQUFtQyxDQUFDLENBQUM7Z0JBQ3pELENBQUM7Z0JBRUQsTUFBTSxZQUFZLEdBQUcsNkJBQTZCLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQy9ELE1BQU0sU0FBUyxHQUFHLDJCQUEyQixDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUUxRCxTQUFTLElBQUksWUFBWSxZQUFZLElBQUksQ0FBQztnQkFDMUMsU0FBUyxJQUFJLG1CQUFtQixZQUFZLElBQUksQ0FBQztnQkFDakQsU0FBUyxJQUFJLFVBQVUsU0FBUyxHQUFHLENBQUM7WUFDeEMsQ0FBQztZQUVELDhGQUE4RjtZQUM5Riw0QkFBNEI7WUFDNUIsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUN0QyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO29CQUNyQyxTQUFTLElBQUksYUFBYSxPQUFPLEdBQUcsQ0FBQztnQkFDekMsQ0FBQztZQUNMLENBQUM7WUFDRCx5R0FBeUc7WUFDekcsc0dBQXNHO1lBQ3RHLFlBQVk7WUFDWixFQUFFO1lBQ0Ysd0RBQXdEO1lBQ3hELEVBQUU7WUFDRixzR0FBc0c7WUFDdEcsK0NBQStDO1lBQy9DLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7Z0JBQ3pCLDRFQUE0RTtnQkFDNUUsU0FBUyxJQUFJLGFBQWEsSUFBSSxDQUFDLGlCQUFpQix5QkFBeUIsQ0FBQztZQUM5RSxDQUFDO1lBRUQsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNyQixTQUFTLElBQUksYUFBYSxLQUFLLENBQUMsaUJBQWlCLE9BQU8sQ0FBQztnQkFDekQsU0FBUyxJQUFJLFlBQVksS0FBSyxDQUFDLGlCQUFpQixvQ0FBb0MsQ0FBQztnQkFDckYsU0FBUyxJQUFJLFlBQVksS0FBSyxDQUFDLGlCQUFpQixnQ0FBZ0MsQ0FBQztZQUNyRixDQUFDO1lBRUQsU0FBUyxJQUFJLFlBQVksZUFBZSxJQUFJLElBQUksQ0FBQyxZQUFZLEdBQUcsQ0FBQztZQUNqRSxTQUFTLElBQUksWUFBWSxhQUFhLElBQUksSUFBSSxDQUFDLGdCQUFnQixHQUFHLENBQUM7WUFDbkUsU0FBUyxJQUFJLGFBQWEsSUFBSSxDQUFDLFlBQVksR0FBRyxDQUFDO1lBRS9DLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDcEMsU0FBUyxJQUFJLFlBQVksTUFBTSxHQUFHLENBQUM7WUFDdkMsQ0FBQztZQUVELEtBQUssTUFBTSxTQUFTLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDMUMsU0FBUyxJQUFJLGNBQWMsU0FBUyxHQUFHLENBQUM7WUFDNUMsQ0FBQztZQUVELElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDbkIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUN4SCxJQUFJLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO29CQUNsQyxTQUFTLElBQUksWUFBWSxVQUFVLHlDQUF5QyxDQUFDO29CQUM3RSxRQUFRLENBQUMsZUFBZSxDQUFDLEdBQUcsb0NBQW9DLENBQUM7b0JBQ2pFLFFBQVEsQ0FBQyxjQUFjLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQztnQkFDaEQsQ0FBQztxQkFBTSxDQUFDO29CQUNKLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFBLHVDQUF1QyxVQUFVLEtBQUssQ0FBQyxDQUFDO2dCQUNyRixDQUFDO1lBQ0wsQ0FBQztZQUVELEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hELHVHQUF1RztnQkFDdkcsU0FBUyxJQUFJLFNBQVMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUM7WUFDL0UsQ0FBQztZQUVELElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUN2QixTQUFTLElBQUksZ0JBQWdCLEtBQUssQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7WUFDbEYsQ0FBQztZQUVELFNBQVMsSUFBSSxHQUFHLENBQUMsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDO1lBQ2hGLFNBQVMsSUFBSSxHQUFHLFNBQVMsR0FBRyxDQUFDO1lBRTdCLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN4QyxJQUFJLENBQUMsZUFBZSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtvQkFDekMsU0FBUyxJQUFJLEdBQUcsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO2dCQUMvQyxDQUFDLENBQUMsQ0FBQztZQUNQLENBQUM7WUFFRCxTQUFTLElBQUksWUFBWSxDQUFDO1lBQzFCLFNBQVMsSUFBSSx1Q0FBdUMsQ0FBQztZQUNyRCxTQUFTLElBQUksK0JBQStCLENBQUM7WUFDN0MsU0FBUyxJQUFJLG1DQUFtQyxDQUFDO1lBQ2pELFNBQVMsSUFBSSx5QkFBeUIsQ0FBQztZQUN2QyxTQUFTLElBQUksK0JBQStCLENBQUM7WUFDN0MsU0FBUyxJQUFJLHFCQUFxQixDQUFDO1lBQ25DLFNBQVMsSUFBSSx1Q0FBdUMsQ0FBQztZQUNyRCxTQUFTLElBQUksNkJBQTZCLENBQUM7WUFDM0MsU0FBUyxJQUFJLGlDQUFpQyxDQUFDO1lBQy9DLFNBQVMsSUFBSSx1QkFBdUIsQ0FBQztZQUNyQyxTQUFTLElBQUksNkJBQTZCLENBQUM7WUFDM0MsU0FBUyxJQUFJLG1CQUFtQixDQUFDO1lBQ2pDLFNBQVMsSUFBSSxpQ0FBaUMsQ0FBQztZQUMvQyxTQUFTLElBQUksdUJBQXVCLENBQUM7WUFDckMsU0FBUyxJQUFJLFFBQVEsQ0FBQztZQUN0QixTQUFTLElBQUksMEJBQTBCLENBQUM7WUFDeEMsU0FBUyxJQUFJLFlBQVksQ0FBQztZQUMxQixTQUFTLElBQUksUUFBUSxDQUFDO1lBRXRCLE1BQU0sRUFBQyxNQUFNLEVBQUUsV0FBVyxFQUFDLEdBQUcsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUUvRCxLQUFLLE1BQU0sT0FBTyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ3RDLHVFQUF1RTtnQkFDdkUsSUFBSSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztvQkFDckMsU0FBUztnQkFDYixDQUFDO2dCQUNELE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsR0FBRyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDeEcsQ0FBQztZQUVELElBQUksQ0FBQyxZQUFZLEdBQUcsV0FBVyxDQUFDO1lBQ2hDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3BELENBQUM7UUFFRCxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQy9DLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUV6QyxJQUFJLEdBQUcsR0FBRyxvQkFBb0IsQ0FBQztRQUMvQixHQUFHLElBQUkscUJBQXFCLENBQUM7UUFFN0IsSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3pDLEdBQUcsSUFBSSxNQUFNLFFBQVEsV0FBVyxXQUFXLEtBQUssQ0FBQztRQUNyRCxDQUFDO1FBRUQsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNaLEdBQUcsSUFBSSxNQUFNLElBQUksQ0FBQyxZQUFZLEtBQUssQ0FBQztZQUVwQyxJQUFJLFFBQVEsQ0FBQyxlQUFlLENBQUMsSUFBSSxTQUFTLEVBQUUsQ0FBQztnQkFDekMsd0VBQXdFO2dCQUN4RSxHQUFHLElBQUksd0JBQXdCLFFBQVEsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDO1lBQ2pFLENBQUM7UUFDTCxDQUFDO1FBQ0QsR0FBRyxJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUU1QyxHQUFHLElBQUksVUFBVSxDQUFDO1FBRWxCLE1BQU0sYUFBYSxHQUFHLEdBQUcsR0FBRyxJQUFJLFFBQVEsWUFBWSxXQUFXLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2hGLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ2pELE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFcEMsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNaLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLEdBQUcsUUFBUSxZQUFZLFdBQVcsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsWUFBWSxXQUFXLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUN2SixDQUFDO1FBRUQsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsc0JBQXNCLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFO1lBQ3JILEdBQUc7WUFDSCxLQUFLLEVBQUUsTUFBTTtZQUNiLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFFBQVE7U0FDMUMsQ0FBQyxDQUFDO1FBRUgsNENBQTRDO1FBQzVDLE1BQU0sWUFBWSxHQUFHLHNFQUFzRSxDQUFDO1FBQzVGLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7UUFFcEQsTUFBTSxPQUFPLEdBQUcsQ0FBQyxJQUFZLEVBQUUsTUFBNkIsRUFBRSxRQUFpQyxFQUFFLEVBQUU7WUFDL0YsSUFBSSxDQUFDLCtCQUErQixDQUFDLFlBQVksQ0FBQyxDQUFDO1lBRW5ELE1BQU0sQ0FBQyxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbEMsSUFBSSxTQUFTLEdBQUcsS0FBSyxDQUFDO1lBQ3RCLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ0osU0FBUyxHQUFHLElBQUksQ0FBQztnQkFDakIsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssT0FBTyxFQUFFLENBQUM7b0JBQ25CLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7b0JBQ3hDLElBQUksR0FBRyxLQUFLLENBQUEsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQztnQkFDL0MsQ0FBQztxQkFBTSxDQUFDO29CQUNKLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztvQkFDekUsSUFBSSxHQUFHLEtBQUssQ0FBQSxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsbUJBQW1CLE9BQU8sS0FBSyxDQUFDO29CQUMvRCxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ25DLENBQUM7WUFDTCxDQUFDO1lBRUQsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixHQUFHLENBQUMsQ0FBQztZQUNwQyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsNEJBQTRCLENBQUMsRUFBRSxDQUFDO2dCQUNoRCwrRkFBK0Y7Z0JBQy9GLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLDRCQUE0QixDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUN2RCxJQUFJLEdBQUcsS0FBSyxDQUFBLFdBQVcsSUFBSSxHQUFHLENBQUM7WUFDbkMsQ0FBQztpQkFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ3BCLE1BQU0sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDaEMsQ0FBQztZQUNELE1BQU0sQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLENBQUM7WUFDcEIsRUFBRSxDQUFDLGNBQWMsQ0FBQyxlQUFlLEVBQUUsR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDO1FBQ3BELENBQUMsQ0FBQztRQUVGLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBRTlCLE9BQU8sTUFBTSxJQUFJLE9BQU8sQ0FBUyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNqRCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ1QsRUFBRSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUEsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDMUksRUFBRSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUEsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDNUksQ0FBQztZQUNELEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRTtnQkFDeEIsWUFBWSxDQUFDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO2dCQUM3QyxPQUFPLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUM7WUFBQSxDQUFDLENBQzlCLENBQUM7WUFDRixLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUU7Z0JBQ3hCLFlBQVksQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsQ0FBQztnQkFDN0MsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdkIsQ0FBQyxDQUFDLENBQUM7WUFFSCxJQUFJLFNBQVMsRUFBRSxDQUFDO2dCQUNaLEVBQUUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ2hDLENBQUM7aUJBQU0sQ0FBQztnQkFDSixFQUFFLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxLQUFLLFFBQVEsWUFBWSxXQUFXLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDeEUsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLFNBQVMsQ0FBRSxPQUFnQyxFQUFFO1FBQ2pELElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQy9CLE9BQU8sSUFBSSxDQUFDO1FBQ2hCLENBQUM7UUFDRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3BDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNULElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO2dCQUNqQyxPQUFPLElBQUksQ0FBQztZQUNoQixDQUFDO2lCQUFNLENBQUM7Z0JBQ0osbUZBQW1GO2dCQUNuRixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO1lBQ2xDLENBQUM7UUFDTCxDQUFDO1FBQ0QsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3QyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDekQsT0FBTyxTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEdBQUcsU0FBUyxTQUFTLENBQUM7SUFDdkUsQ0FBQztJQUVPLFNBQVMsQ0FBRSxPQUFnQyxFQUFFO1FBQ2pELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDcEMsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPLElBQUksQ0FBQztRQUN4QixJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQztZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ2xDLE9BQU8sS0FBSyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVELElBQUksZUFBZTtRQUNmLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFcEMsSUFBSSxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsQ0FBQztZQUNyQixPQUFPLElBQUksQ0FBQztRQUNoQixDQUFDO1FBQ0QsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxFQUFFLG1DQUFtQyxDQUFDLENBQUM7UUFDN0UsT0FBTyxLQUFLLENBQUMsVUFBVSxDQUFDO0lBQzVCLENBQUM7SUFFTyxLQUFLLENBQUMsNkNBQTZDLENBQUUsU0FBaUI7UUFDMUUsTUFBTSwwQkFBMEIsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLDRCQUE0QixDQUFDLENBQUM7UUFDakYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsMEJBQTBCLENBQUMsRUFBRSxDQUFDO1lBQ3BELE9BQU87UUFDWCxDQUFDO1FBQ0QsSUFBSSxDQUFDO1lBQ0QsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxPQUFPLEVBQUUsMEJBQTBCLENBQUMsQ0FBQyxDQUFDO1FBQzVGLENBQUM7UUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO1lBQ2QsTUFBTSxNQUFNLEdBQUcsZ0RBQWdELDBCQUEwQixxR0FBcUcsQ0FBQztZQUMvTCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQzVDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLHFDQUFxQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDOUUsQ0FBQztpQkFBTSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ25ELE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLHVFQUF1RSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDaEgsQ0FBQztZQUNELE1BQU0sQ0FBQyxDQUFDO1FBQ1osQ0FBQztJQUNMLENBQUM7SUFFTyxLQUFLLENBQUMsU0FBUyxDQUFFLFlBQTBCLEVBQUUsV0FBbUI7UUFDcEUsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7UUFDeEMsTUFBTSxVQUFVLEdBQUcsS0FBSyxJQUFJLEVBQUU7WUFDMUIsTUFBTSxJQUFJLENBQUMsNkNBQTZDLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDdEUsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzlCLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7WUFDeEUsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNyQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsMkJBQTJCLFdBQVcsZ0JBQWdCLFlBQVksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbkksSUFBSSxDQUFDLCtCQUErQixDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3ZELENBQUMsQ0FBQztRQUVGLElBQUksVUFBVSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzFCLE1BQU0sVUFBVSxFQUFFLENBQUM7WUFDbkIsT0FBTztRQUNYLENBQUM7UUFDRCxJQUFJLENBQUM7WUFDRCxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUN4RixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ0wsTUFBTSxVQUFVLEVBQUUsQ0FBQztRQUN2QixDQUFDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBRSxZQUEwQixFQUFFLFFBQWlDO1FBQzNHLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQzFCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ3BDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDakMsSUFBSSxtQkFBbUIsR0FBRyxFQUFFLENBQUM7UUFDN0IsS0FBSyxNQUFNLFFBQVEsSUFBSSxTQUFTLElBQUksRUFBRSxFQUFFLENBQUM7WUFDckMsTUFBTSxjQUFjLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ25FLElBQUksY0FBYyxLQUFLLElBQUk7Z0JBQUUsU0FBUztZQUV0QyxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDL0QsTUFBTSxZQUFZLEdBQUcsR0FBRyxHQUFHLElBQUksUUFBUSxjQUFjLGdCQUFnQiw2QkFBNkIsQ0FBQztZQUNuRyxJQUFJLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO2dCQUNwQyxNQUFNLFdBQVcsR0FBRyxDQUFDLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDdEcsS0FBSyxNQUFNLFVBQVUsSUFBSSxXQUFXLEVBQUUsQ0FBQztvQkFDbkMsSUFBSSxVQUFVLElBQUksRUFBRTt3QkFBRSxTQUFTO29CQUMvQixNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLEdBQUcsWUFBWSxJQUFJLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQztvQkFDM0YsbUJBQW1CLEdBQUcsRUFBQyxHQUFHLG1CQUFtQixFQUFFLEdBQUcsaUJBQWlCLEVBQUMsQ0FBQztnQkFDekUsQ0FBQztZQUNMLENBQUM7aUJBQU0sQ0FBQztnQkFDSixZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQSxHQUFHLElBQUksQ0FBQyxnQkFBZ0Isd0NBQXdDLFFBQVEsQ0FBQyxJQUFJLHlCQUF5QixDQUFDLENBQUM7WUFDckksQ0FBQztRQUVMLENBQUM7UUFDRCxPQUFPLG1CQUFtQixDQUFDO0lBQy9CLENBQUM7SUFFTyxLQUFLLENBQUMsV0FBVyxDQUFFLFlBQTBCLEVBQUUsUUFBaUM7UUFDcEYsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQztZQUFFLE9BQU87UUFDN0QsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUFFLE9BQU87UUFFaEcsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDMUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7UUFFcEMsS0FBSyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQztZQUM1QyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7Z0JBQUUsT0FBTztZQUV0RCxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDOUIsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN0RSxNQUFNLFdBQVcsR0FBRyxHQUFHLEdBQUcsSUFBSSxRQUFRLFVBQVUsU0FBUyxFQUFFLENBQUM7WUFDNUQsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO2dCQUNwQyxTQUFTO1lBQ2IsQ0FBQztZQUVELE1BQU0sS0FBSyxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ3hDLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNuQyxDQUFDLENBQUMsQ0FBQztZQUNILE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDckMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLG1DQUFtQyxTQUFTLGtCQUFrQixZQUFZLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQy9JLENBQUM7SUFDTCxDQUFDO0lBRU8sS0FBSyxDQUFDLGVBQWUsQ0FBRSxZQUEwQjtRQUNyRCxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDO1lBQUUsT0FBTztRQUVuSCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztRQUMxQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUNwQyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDOUIsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFDO1FBQ3BCLEtBQUssTUFBTSxRQUFRLElBQUksSUFBSSxDQUFDLFNBQVMsSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUMxQyxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDL0QsTUFBTSxjQUFjLEdBQUcsR0FBRyxHQUFHLElBQUksUUFBUSxjQUFjLGdCQUFnQixFQUFFLENBQUM7WUFDMUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO2dCQUN2QyxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDcEMsQ0FBQztZQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUNqRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ3ZCLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFBLEdBQUcsSUFBSSxDQUFDLGdCQUFnQix1Q0FBdUMsZ0JBQWdCLGdCQUFnQixDQUFDLENBQUM7WUFDOUgsQ0FBQztZQUVELFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1FBQy9DLENBQUM7UUFDRCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDNUIsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNyQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsbURBQW1ELFlBQVksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEksQ0FBQztJQUVELE1BQU0sQ0FBRSxNQUFjO1FBQ2xCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDckMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDL0QsT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0sSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLFdBQVcsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3ZILENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0sSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzFILENBQUM7SUFFTyxLQUFLLENBQUMsWUFBWSxDQUFFLFlBQTBCLEVBQUUsUUFBaUM7UUFDckYsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQztZQUFFLE9BQU87UUFDN0QsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUFFLE9BQU87UUFFaEcsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDMUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDcEMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUM7UUFFdEUsSUFBSSxJQUFJLEVBQUUsT0FBTyxDQUFDO1FBQ2xCLEtBQUssTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDNUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO2dCQUFFLE9BQU87WUFDdEQsSUFBSSxZQUFZLEtBQUssQ0FBQyxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVM7Z0JBQUUsT0FBTztZQUNwRSxJQUFJLFlBQVksS0FBSyxDQUFDLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUztnQkFBRSxPQUFPO1lBQ3BFLE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFdEUsSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO1lBQ2YsS0FBSyxNQUFNLElBQUksSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ3pCLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztvQkFBRSxTQUFTO2dCQUVuRSxLQUFLLElBQUksR0FBRyxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxjQUFjLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMvRixDQUFDO1lBRUQsSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN4QixJQUFJLEdBQUcsR0FBRyxzQ0FBc0MsQ0FBQztZQUNqRCxHQUFHLElBQUksWUFBWSxLQUFLLENBQUMsY0FBYyxDQUFDLFNBQVMsR0FBRyxHQUFHLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQztZQUN6RSxHQUFHLElBQUksYUFBYSxLQUFLLElBQUksS0FBSyxDQUFDLGNBQWMsQ0FBQyxTQUFTLEdBQUcsR0FBRyxHQUFHLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1lBRWxHLE1BQU0sS0FBSyxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ3hDLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNuRCxDQUFDLENBQUMsQ0FBQztZQUNILE9BQU8sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRS9CLEtBQUssTUFBTSxNQUFNLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUMzQixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztnQkFDakQsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDeEQsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUEsc0ZBQXNGLEtBQUssS0FBSyxDQUFDLENBQUM7b0JBQzNILFNBQVM7Z0JBQ2IsQ0FBQztnQkFFRCxJQUFJLElBQUksR0FBRyxLQUFLLENBQUM7Z0JBQ2pCLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUN0QyxJQUFJLEdBQUcsR0FBRyxJQUFJLEtBQUssQ0FBQztnQkFDeEIsQ0FBQztnQkFFRCxJQUFJLFVBQVUsR0FBRyxVQUFVLENBQUMsSUFBSSxFQUFFO29CQUM5QixHQUFHLEVBQUUsSUFBSTtvQkFDVCxTQUFTLEVBQUUsS0FBSztvQkFDaEIsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksUUFBUSxVQUFVLFNBQVMsRUFBRTtpQkFDekQsQ0FBQyxDQUFDLE1BQU0sQ0FBQztnQkFFVixJQUFJLFVBQVUsSUFBSSxDQUFDLEVBQUUsQ0FBQztvQkFDbEIsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUEsb0JBQW9CLElBQUksNEZBQTRGLENBQUMsQ0FBQztvQkFDL0ksU0FBUztnQkFDYixDQUFDO2dCQUVELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO29CQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsaURBQWlEO2dCQUVsRixZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsS0FBSyxXQUFXLFVBQVUsbUNBQW1DLENBQUMsQ0FBQztZQUMxRixDQUFDO1lBQ0QsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLHFDQUFxQyxRQUFRLFVBQVUsU0FBUyxrQkFBa0IsWUFBWSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuSyxDQUFDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBRSxZQUEwQixFQUFFLFFBQWlDO1FBQ3pGLDBFQUEwRTtRQUMxRSxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxLQUFLLFFBQVE7WUFBRSxPQUFPO1FBQzlFLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU87UUFDNUIsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxJQUFJLElBQUk7WUFBRSxPQUFPO1FBRWhHLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDckMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDMUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDcEMsSUFBSSxhQUFxQixDQUFDO1FBRTFCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztZQUN6RCxhQUFhLEdBQUcsR0FBRyxRQUFRLFlBQVksQ0FBQztRQUM1QyxDQUFDO2FBQU0sSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDbEMsYUFBYSxHQUFHLFlBQVksQ0FBQztRQUNqQyxDQUFDO2FBQU0sQ0FBQztZQUNKLGFBQWEsR0FBRyxpQkFBaUIsQ0FBQztRQUN0QyxDQUFDO1FBRUQsSUFBSSxJQUFJLEVBQUUsT0FBTyxDQUFDO1FBQ2xCLElBQUksS0FBSyxHQUFHLHNDQUFzQyxDQUFDO1FBQ25ELEtBQUssSUFBSSxZQUFZLGFBQWEsSUFBSSxXQUFXLElBQUksQ0FBQztRQUN0RCxLQUFLLElBQUksNENBQTRDLENBQUM7UUFDdEQsS0FBSyxNQUFNLG1CQUFtQixJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsT0FBTyxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQzlELE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUMsbUJBQW1CLEVBQUUsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsUUFBUSxDQUFDLGNBQWMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ2hILEtBQUssSUFBSSxjQUFjLFlBQVksSUFBSSxDQUFDO1FBQzVDLENBQUM7UUFDRCxLQUFLLE1BQU0sWUFBWSxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsS0FBSyxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQ3JELE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxjQUFjLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUN6RyxLQUFLLElBQUksR0FBRyxZQUFZLEdBQUcsQ0FBQztRQUNoQyxDQUFDO1FBQ0QsS0FBSyxJQUFJLEdBQUcsYUFBYSxJQUFJLFdBQVcsY0FBYyxDQUFDO1FBQ3ZELE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxJQUFJLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztRQUN4RixNQUFNLGFBQWEsR0FBb0IsQ0FBQyxPQUFPLFlBQVksS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsNENBQTRDO1lBQ3BILENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztZQUNoQixZQUFZLENBQUM7UUFDakIsSUFBSSxhQUFhLElBQUksSUFBSSxFQUFFLENBQUM7WUFDeEIsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO2dCQUNuQyxLQUFLLElBQUksWUFBWSxhQUFhLElBQUksV0FBVyw4QkFBOEIsQ0FBQztnQkFDaEYsS0FBSyxJQUFJLFdBQVcsWUFBWSxZQUFZLENBQUM7Z0JBQzdDLEtBQUssSUFBSSxlQUFlLFlBQVksSUFBSSxhQUFhLElBQUksV0FBVyxnQ0FBZ0MsQ0FBQztnQkFDckcsS0FBSyxJQUFJLE1BQU0sQ0FBQztZQUNwQixDQUFDLENBQUMsQ0FBQztRQUNQLENBQUM7UUFFRCxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3hCLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDckcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQ2xFLE9BQU8sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRS9CLEtBQUssTUFBTSxZQUFZLElBQUksYUFBYSxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQzdDLElBQUksTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLEdBQUcsR0FBRyxJQUFJLFFBQVEsY0FBYyxXQUFXLDhCQUE4QixZQUFZLEVBQUUsQ0FBQztnQkFBRSxTQUFTO1lBQzNILFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFBLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixxQ0FBcUMsWUFBWSx5QkFBeUIsQ0FBQyxDQUFDO1FBQ2pJLENBQUM7UUFFRCxNQUFNLE9BQU8sR0FBRyxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxHQUFHLElBQUksUUFBUSxjQUFjLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDaEYsSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3ZCLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFBLEdBQUcsSUFBSSxDQUFDLGdCQUFnQiwyQ0FBMkMsQ0FBQyxDQUFDO1FBQ2xHLENBQUM7YUFBTSxDQUFDO1lBQ0osWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLG1EQUFtRCxZQUFZLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3BJLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ25GLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDeEIsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLGdDQUFnQyxFQUFFLElBQUksRUFBRSxHQUFHLEdBQUcsSUFBSSxRQUFRLGNBQWMsV0FBVyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUMzSCxJQUFJLFlBQVksSUFBSSxJQUFJLEVBQUUsQ0FBQztnQkFDdkIsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLEdBQUcsSUFBSSxRQUFRLGNBQWMsV0FBVyw4QkFBOEIsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3ZILENBQUM7WUFDRCxPQUFPLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMvQixZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQSxHQUFHLElBQUksQ0FBQyxnQkFBZ0Isd0RBQXdELFlBQVksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekksQ0FBQztJQUNMLENBQUM7SUFFTyxLQUFLLENBQUMsT0FBTyxDQUFFLEdBQVcsRUFBRSxRQUFnQixFQUFFLElBQTJCLEVBQUUsZUFBeUI7UUFDeEcsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUNyQyxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDO1FBQzdDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQzFCLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDO1FBRTlDLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEdBQUcsSUFBSSxRQUFRLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQztRQUU5QyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDbEMsTUFBTSxFQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUMsR0FBRyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixjQUFjLGVBQWUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sZUFBZSxJQUFJLElBQUksQ0FBQyxZQUFZLE9BQU8sSUFBSSxDQUFDLFlBQVksSUFBSSxlQUFlLGFBQWEsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUM1UCxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQzFDLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBQ3JGLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLEdBQUcsV0FBVyxLQUFLLElBQUksSUFBSSxFQUFFLEdBQUcsUUFBUSxJQUFJLElBQUksSUFBSSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDeEgsQ0FBQzthQUFNLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUNsQyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMseUJBQXlCLEdBQUcsR0FBRyxFQUFFLEdBQUcsR0FBRyxJQUFJLFFBQVEsV0FBVyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ2xHLENBQUM7YUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUNuQyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMseUJBQXlCLEdBQUcsR0FBRyxFQUFFLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNoRSxDQUFDO0lBQ0wsQ0FBQztJQUVPLCtCQUErQixDQUFFLFlBQTBCO1FBQy9ELFlBQVksQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUM3QyxJQUFJLENBQUMseUJBQXlCLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUM3QyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsOEJBQThCLENBQUMsQ0FBQztZQUNqRixJQUFJLENBQUMsK0JBQStCLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdkQsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2QsQ0FBQztJQUVPLGlCQUFpQjtRQUNyQixPQUFPLEtBQUssQ0FBQSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IseUNBQXlDLElBQUksQ0FBQyxjQUFjLEdBQUcsQ0FBQztJQUN4RyxDQUFDO0lBRU8sbUJBQW1CO1FBQ3ZCLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTO1lBQUUsT0FBTztRQUN6QyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBRU8saUJBQWlCLENBQUUsSUFBWTtRQUNuQyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQ3ZDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBRTdDLHFHQUFxRztRQUNyRyxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDL0IsWUFBWSxDQUFDLE1BQU0sQ0FDZixLQUFLLENBQUEsR0FBRyxXQUFXLGdDQUFnQyxJQUFJLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FDM0UsQ0FBQztRQUNOLENBQUM7YUFBTSxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDckMsWUFBWSxDQUFDLE1BQU0sQ0FDZixLQUFLLENBQUEsR0FBRyxXQUFXLHVCQUF1QixJQUFJLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FDbEUsQ0FBQztRQUNOLENBQUM7SUFDTCxDQUFDO0lBRU8sNEJBQTRCLENBQUUsSUFBWTtRQUM5QyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQ3ZDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBRTdDLElBQUksSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ2IsWUFBWSxDQUFDLE1BQU0sQ0FDZixLQUFLLENBQUEsR0FBRyxXQUFXLGdDQUFnQyxJQUFJLENBQUMsUUFBUSxFQUFFLG1CQUFtQixDQUN4RixDQUFDO1FBQ04sQ0FBQztJQUNMLENBQUM7SUFFTyxLQUFLLENBQUMsbUJBQW1CLENBQUUsV0FBbUI7UUFDbEQsTUFBTSxFQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUMsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsR0FBRyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDdEgsSUFBSSxDQUFDLGlCQUFpQixHQUFHLFNBQVMsQ0FBQztJQUN2QyxDQUFDO0lBRU8sS0FBSyxDQUFDLFlBQVksQ0FBRSxZQUEwQixFQUFFLFFBQWlDLEVBQUUsT0FBZ0I7UUFDdkcsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDMUIsSUFBSSxTQUFTLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQix3QkFBd0IsQ0FBQztRQUN6RSxJQUFJLENBQUMsK0JBQStCLENBQUMsWUFBWSxDQUFDLENBQUM7UUFFbkQsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2xCLFNBQVMsSUFBSSxhQUFhLENBQUM7UUFDL0IsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksU0FBUyxFQUFFLENBQUM7WUFDaEMsU0FBUyxJQUFJLFlBQVksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQztRQUNqRCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3ZCLFNBQVMsSUFBSSxlQUFlLENBQUM7UUFDakMsQ0FBQztRQUVELEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNwQyxTQUFTLElBQUksWUFBWSxNQUFNLEdBQUcsQ0FBQztRQUN2QyxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUM1QixTQUFTLElBQUksbUJBQW1CLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUM7UUFDeEQsQ0FBQztRQUVELEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNwQyxTQUFTLElBQUksWUFBWSxNQUFNLEdBQUcsQ0FBQztRQUN2QyxDQUFDO1FBRUQsS0FBSyxNQUFNLFNBQVMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzFDLFNBQVMsSUFBSSxjQUFjLFNBQVMsR0FBRyxDQUFDO1FBQzVDLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbkIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3hILElBQUksTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7Z0JBQ2xDLFNBQVMsSUFBSSxZQUFZLFVBQVUseUNBQXlDLENBQUM7Z0JBQzdFLFFBQVEsQ0FBQyxlQUFlLENBQUMsR0FBRyxvQ0FBb0MsQ0FBQztnQkFDakUsUUFBUSxDQUFDLGNBQWMsQ0FBQyxHQUFHLGdCQUFnQixDQUFDO1lBQ2hELENBQUM7UUFDTCxDQUFDO1FBRUQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztRQUNuQyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQ2pDLE1BQU0seUJBQXlCLEdBQUcsV0FBVyxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDekUsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUNsQyxPQUFPLENBQUMsR0FBRyxDQUFDLHlCQUF5QixDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM1RCxPQUFPLENBQUMsR0FBRyxDQUFDLHlCQUF5QixDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUM3RCxJQUFJLFlBQVksRUFBRSxDQUFDO1lBQ2YsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUM5QixDQUFDO1FBRUQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztZQUNoRCx1R0FBdUc7WUFDdkcsU0FBUyxJQUFJLFNBQVMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUM7UUFDL0UsQ0FBQztRQUVELE1BQU0saUJBQWlCLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztRQUM3QyxJQUFJLGlCQUFpQixFQUFFLENBQUM7WUFDcEIsU0FBUyxJQUFJLGdCQUFnQixLQUFLLENBQUMsY0FBYyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUMvRSxDQUFDO1FBQ0QsU0FBUyxJQUFJLFlBQVksSUFBSSxDQUFDLGVBQWUsSUFBSSxJQUFJLENBQUMsWUFBWSxHQUFHLENBQUM7UUFDdEUsU0FBUyxJQUFJLFlBQVksSUFBSSxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsQ0FBQztRQUV4RSx5R0FBeUc7UUFDekcsc0dBQXNHO1FBQ3RHLFlBQVk7UUFDWixFQUFFO1FBQ0Ysd0RBQXdEO1FBQ3hELFNBQVMsSUFBSSxhQUFhLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxDQUFDO1FBQ3BELEtBQUssTUFBTSxLQUFLLElBQUksT0FBTyxFQUFFLENBQUM7WUFDMUIsU0FBUyxJQUFJLG1CQUFtQixLQUFLLEdBQUcsQ0FBQztRQUM3QyxDQUFDO1FBRUQsU0FBUyxJQUFJLEdBQUcsV0FBVyxHQUFHLENBQUM7UUFFL0IsSUFBSSxpQkFBaUIsRUFBRSxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3JDLGlCQUFpQixFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtnQkFDdEMsU0FBUyxJQUFJLEdBQUcsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO1lBQy9DLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQztRQUNELENBQUMsT0FBTyxDQUFDLE9BQU8sSUFBSSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVyRixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7UUFFOUIsTUFBTSxFQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUMsR0FBRyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQy9ELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFMUMsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3RDLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsR0FBRyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDeEcsQ0FBQztRQUVELE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsT0FBTyxFQUFFLEdBQUcsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTlFLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDckMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLDBDQUEwQyxXQUFXLGtCQUFrQixLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLFlBQVksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFbk0sT0FBTyxXQUFXLENBQUM7SUFDdkIsQ0FBQztJQUVPLEtBQUssQ0FBQyxrQkFBa0IsQ0FBRSxZQUEwQixFQUFFLE9BQWdCLEVBQUUsWUFBb0IsRUFBRSx1QkFBK0I7UUFDakksTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztRQUNuQyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQ2pDLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO1FBRTFDLE1BQU0sRUFBQyxNQUFNLEVBQUMsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUNyRyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRXhDLGdGQUFnRjtRQUNoRixNQUFNLHlCQUF5QixHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3pFLE1BQU0sT0FBTyxHQUFHLENBQUMseUJBQXlCLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSx5QkFBeUIsQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDbEgsSUFBSSxZQUFZLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDL0IsQ0FBQztRQUVELE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRWhELElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLFlBQVksSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUMzRCxPQUFPLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFBLEdBQUcsSUFBSSxDQUFDLGdCQUFnQiw2Q0FBNkMsV0FBVyxLQUFLLENBQUMsQ0FBQztRQUMzSCxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzlCLElBQUksQ0FBQztZQUNELCtFQUErRTtZQUMvRSxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO2dCQUM1RSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7b0JBQUUsT0FBTztnQkFDbkMsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ25ELE1BQU0sYUFBYSxHQUFHLG1CQUFtQixJQUFJLENBQUMsS0FBSyxJQUFJLFlBQVksSUFBSSxPQUFPLEVBQUUsQ0FBQztnQkFDakYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsVUFBVSxhQUFhLEVBQUUsRUFBRSxXQUFXLEVBQUUsR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsRUFBRSxHQUFHLGFBQWEsRUFBRSxFQUFFLEdBQUcsV0FBVyxJQUFJLE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDbE0sSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztnQkFDNUMsT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2pDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDSixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3JDLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFBLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixnQ0FBZ0MsV0FBVyxpQ0FBaUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5SixDQUFDO1FBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztZQUNkLElBQUksQ0FBQyxDQUFDLENBQUMsWUFBWSxjQUFjLENBQUM7Z0JBQUUsTUFBTSxDQUFDLENBQUM7WUFDNUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxXQUFrQixFQUFFLEVBQUU7Z0JBQ3BDLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFBLEdBQUcsSUFBSSxDQUFDLGdCQUFnQiw4QkFBOEIsV0FBVyx3QkFBd0IsQ0FBQyxDQUFDO2dCQUNwSCxXQUFXLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFZLEVBQUUsRUFBRTtvQkFDekQsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLGlCQUFpQixJQUFJLEtBQUssQ0FBQyxDQUFDO2dCQUNqRixDQUFDLENBQUMsQ0FBQztnQkFDSCxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IseUJBQXlCLHVCQUF1QixNQUFNLENBQUMsQ0FBQztZQUM3RyxDQUFDLENBQUMsQ0FBQztRQUNQLENBQUM7Z0JBQVMsQ0FBQztZQUNQLGlFQUFpRTtZQUNqRSxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO2dCQUNuRixJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7b0JBQUUsT0FBTztnQkFDbkMsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ25ELE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxtQkFBbUIsSUFBSSxDQUFDLEtBQUssSUFBSSxZQUFZLElBQUksT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2pJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDUixDQUFDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxtQkFBbUI7UUFDN0IsTUFBTSxFQUFDLEdBQUcsRUFBRSxRQUFRLEVBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBRWxDLEVBQUUsQ0FBQyxVQUFVLENBQUMsR0FBRyxHQUFHLElBQUksUUFBUSxvQkFBb0IsQ0FBQyxDQUFDO1FBRXRELElBQUksUUFBUSxHQUFRLEVBQUUsQ0FBQztRQUV2QixLQUFLLE1BQU0sT0FBTyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUN4RCxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNuQixNQUFNLGVBQWUsR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQzVFLG9CQUFvQixDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUN0QyxNQUFNLEtBQUssR0FBRyxNQUFNLG1CQUFtQixDQUFDLGVBQWUsRUFBRSxHQUFHLENBQUMsQ0FBQztnQkFDOUQsSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDO29CQUNwQixNQUFNLElBQUksY0FBYyxDQUFDLEVBQUMsT0FBTyxFQUFFLHdCQUF3QixPQUFPLENBQUMsT0FBTyxDQUFDLHNCQUFzQixJQUFJLENBQUMsSUFBSSxxQkFBcUIsRUFBQyxDQUFDLENBQUM7Z0JBQ3RJLENBQUM7Z0JBRUQsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztvQkFDdkIsTUFBTSxPQUFPLEdBQUcsTUFBTSxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztvQkFDaEQsUUFBUSxHQUFHO3dCQUNQLEdBQUcsUUFBUTt3QkFDWCxHQUFHLE9BQU87cUJBQ2IsQ0FBQztnQkFDTixDQUFDO1lBQ0wsQ0FBQztpQkFBTSxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO2dCQUM3QixNQUFNLE9BQU8sR0FBRyxNQUFNLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxHQUFHLElBQUksUUFBUSxjQUFjLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDbkgsUUFBUSxHQUFHO29CQUNQLEdBQUcsUUFBUTtvQkFDWCxHQUFHLE9BQU87aUJBQ2IsQ0FBQztZQUNOLENBQUM7aUJBQU0sSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztnQkFDNUIsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFBLHlDQUF5QyxJQUFJLENBQUMsSUFBSSxnRkFBZ0YsQ0FBQyxDQUFDO1lBRTFLLENBQUM7aUJBQU0sSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztnQkFDN0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFBLHlDQUF5QyxJQUFJLENBQUMsSUFBSSxpRkFBaUYsQ0FBQyxDQUFDO1lBQzNLLENBQUM7UUFDTCxDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsR0FBRyxHQUFHLElBQUksUUFBUSxzQkFBc0IsSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDO1FBQ3ZFLEVBQUUsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUNsRCxDQUFDOztBQUdMLE1BQU0sQ0FBQyxLQUFLLFVBQVUsbUJBQW1CLENBQUUsSUFBb0I7SUFDM0QsSUFBSSxDQUFDLElBQUk7UUFBRSxPQUFPO0lBQ2xCLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQztJQUNwQixLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3JCLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBQ0QsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ2hDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrLXRlbXBsYXRlXCI7XG5pbXBvcnQgKiBhcyBkb3RlbnYgZnJvbSBcImRvdGVudlwiO1xuaW1wb3J0IGZzIGZyb20gXCJmcy1leHRyYVwiO1xuaW1wb3J0IHByZXR0eUhydGltZSBmcm9tIFwicHJldHR5LWhydGltZVwiO1xuaW1wb3J0IHNwbGl0MiBmcm9tIFwic3BsaXQyXCI7XG5pbXBvcnQge1V0aWxzfSBmcm9tIFwiLi91dGlscy5qc1wiO1xuaW1wb3J0IHtXcml0ZVN0cmVhbXN9IGZyb20gXCIuL3dyaXRlLXN0cmVhbXMuanNcIjtcbmltcG9ydCB7R2l0RGF0YX0gZnJvbSBcIi4vZ2l0LWRhdGEuanNcIjtcbmltcG9ydCBhc3NlcnQsIHtBc3NlcnRpb25FcnJvcn0gZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IHtNdXRleH0gZnJvbSBcIi4vbXV0ZXguanNcIjtcbmltcG9ydCB7QXJndn0gZnJvbSBcIi4vYXJndi5qc1wiO1xuaW1wb3J0IGV4ZWNhIGZyb20gXCJleGVjYVwiO1xuaW1wb3J0IHtDSUNEVmFyaWFibGV9IGZyb20gXCIuL3ZhcmlhYmxlcy1mcm9tLWZpbGVzLmpzXCI7XG5pbXBvcnQge0dpdGxhYlJ1bm5lckNQVXNQcmVzZXRWYWx1ZSwgR2l0bGFiUnVubmVyTWVtb3J5UHJlc2V0VmFsdWUsIEdpdGxhYlJ1bm5lclByZXNldFZhbHVlc30gZnJvbSBcIi4vZ2l0bGFiLXByZXNldC5qc1wiO1xuaW1wb3J0IHtoYW5kbGVyfSBmcm9tIFwiLi9oYW5kbGVyLmpzXCI7XG5pbXBvcnQgKiBhcyB5YW1sIGZyb20gXCJqcy15YW1sXCI7XG5pbXBvcnQge1BhcnNlcn0gZnJvbSBcIi4vcGFyc2VyLmpzXCI7XG5pbXBvcnQge3Jlc29sdmVJbmNsdWRlTG9jYWwsIHZhbGlkYXRlSW5jbHVkZUxvY2FsfSBmcm9tIFwiLi9wYXJzZXItaW5jbHVkZXMuanNcIjtcbmltcG9ydCB7Z2xvYmJ5U3luY30gZnJvbSBcImdsb2JieVwiO1xuaW1wb3J0IHRlcm1pbmFsTGluayBmcm9tIFwidGVybWluYWwtbGlua1wiO1xuaW1wb3J0ICogYXMgY3J5cHRvIGZyb20gXCJjcnlwdG9cIjtcbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcblxuY29uc3QgR0NMX1NIRUxMX1BST01QVF9QTEFDRUhPTERFUiA9IFwiPGdjbFNoZWxsUHJvbXB0UGxhY2Vob2xkZXI+XCI7XG5pbnRlcmZhY2UgSm9iT3B0aW9ucyB7XG4gICAgYXJndjogQXJndjtcbiAgICB3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcztcbiAgICBkYXRhOiBhbnk7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIGJhc2VOYW1lOiBzdHJpbmc7XG4gICAgcGlwZWxpbmVJaWQ6IG51bWJlcjtcbiAgICBnaXREYXRhOiBHaXREYXRhO1xuICAgIGdsb2JhbFZhcmlhYmxlczoge1tuYW1lOiBzdHJpbmddOiBzdHJpbmd9O1xuICAgIHZhcmlhYmxlc0Zyb21GaWxlczoge1tuYW1lOiBzdHJpbmddOiBDSUNEVmFyaWFibGV9O1xuICAgIHByZWRlZmluZWRWYXJpYWJsZXM6IHtbbmFtZTogc3RyaW5nXTogYW55fTtcbiAgICBtYXRyaXhWYXJpYWJsZXM6IHtba2V5OiBzdHJpbmddOiBzdHJpbmd9IHwgbnVsbDtcbiAgICBub2RlSW5kZXg6IG51bWJlciB8IG51bGw7XG4gICAgbm9kZXNUb3RhbDogbnVtYmVyO1xuICAgIGV4cGFuZFZhcmlhYmxlczogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIENhY2hlIHtcbiAgICBwb2xpY3k6IFwicHVsbFwiIHwgXCJwdWxsLXB1c2hcIiB8IFwicHVzaFwiO1xuICAgIGtleTogc3RyaW5nIHwge2ZpbGVzOiBzdHJpbmdbXX07XG4gICAgcGF0aHM6IHN0cmluZ1tdO1xuICAgIHdoZW46IFwib25fc3VjY2Vzc1wiIHwgXCJvbl9mYWlsdXJlXCIgfCBcImFsd2F5c1wiO1xufVxuXG5pbnRlcmZhY2UgU2VydmljZSB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIGVudHJ5cG9pbnQ6IHN0cmluZ1tdIHwgbnVsbDtcbiAgICBjb21tYW5kOiBzdHJpbmdbXSB8IG51bGw7XG4gICAgYWxpYXM6IHN0cmluZyB8IG51bGw7XG4gICAgdmFyaWFibGVzOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ307XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmVlZCB7XG4gICAgam9iOiBzdHJpbmc7XG4gICAgYXJ0aWZhY3RzOiBib29sZWFuO1xuICAgIG9wdGlvbmFsPzogYm9vbGVhbjtcbiAgICByZWY/OiBzdHJpbmc7XG4gICAgcGlwZWxpbmU/OiBzdHJpbmc7XG4gICAgcHJvamVjdD86IHN0cmluZztcbn1cblxuY29uc3QgaXNHbG9iID0gKHN0cjogc3RyaW5nKSA9PiAvWyo/e30ofClbXFxdXS8udGVzdChzdHIpO1xuXG5jb25zdCBkYXRlRm9ybWF0dGVyID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQodW5kZWZpbmVkLCB7XG4gICAgeWVhcjogdW5kZWZpbmVkLFxuICAgIG1vbnRoOiB1bmRlZmluZWQsXG4gICAgaG91cjogXCJudW1lcmljXCIsXG4gICAgbWludXRlOiBcIm51bWVyaWNcIixcbiAgICBzZWNvbmQ6IFwibnVtZXJpY1wiLFxuICAgIGhvdXIxMjogZmFsc2UsXG59KTtcblxuZXhwb3J0IHR5cGUgSm9iUnVsZSA9IHtcbiAgICBpZj86IHN0cmluZztcbiAgICB3aGVuPzogc3RyaW5nO1xuICAgIGNoYW5nZXM/OiBzdHJpbmdbXSB8IHtwYXRoczogc3RyaW5nW119O1xuICAgIGV4aXN0cz86IHN0cmluZ1tdO1xuICAgIGFsbG93X2ZhaWx1cmU/OiBib29sZWFuO1xuICAgIHZhcmlhYmxlcz86IHtbbmFtZTogc3RyaW5nXTogc3RyaW5nfTtcbiAgICBuZWVkcz86IGFueVtdO1xufTtcblxuZXhwb3J0IGNsYXNzIEpvYiB7XG4gICAgcHJpdmF0ZSBnZW5lcmF0ZUpvYklkICgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTAwMDAwMCk7XG4gICAgfVxuXG4gICAgc3RhdGljIHJlYWRvbmx5IGlsbGVnYWxKb2JOYW1lcyA9IG5ldyBTZXQoW1xuICAgICAgICBcImluY2x1ZGVcIiwgXCJsb2NhbF9jb25maWd1cmF0aW9uXCIsIFwiaW1hZ2VcIiwgXCJzZXJ2aWNlc1wiLFxuICAgICAgICBcInN0YWdlc1wiLCBcImJlZm9yZV9zY3JpcHRcIiwgXCJkZWZhdWx0XCIsXG4gICAgICAgIFwiYWZ0ZXJfc2NyaXB0XCIsIFwidmFyaWFibGVzXCIsIFwiY2FjaGVcIiwgXCJ3b3JrZmxvd1wiLCBcInBhZ2U6ZGVwbG95XCIsXG4gICAgXSk7XG5cbiAgICByZWFkb25seSBhcmd2OiBBcmd2O1xuICAgIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgICByZWFkb25seSBiYXNlTmFtZTogc3RyaW5nO1xuICAgIHJlYWRvbmx5IGRlcGVuZGVuY2llczogc3RyaW5nW10gfCBudWxsO1xuICAgIHJlYWRvbmx5IGVudmlyb25tZW50Pzoge25hbWU6IHN0cmluZzsgdXJsOiBzdHJpbmcgfCBudWxsOyBkZXBsb3ltZW50X3RpZXI6IHN0cmluZyB8IG51bGw7IGFjdGlvbjogc3RyaW5nIHwgbnVsbH07XG4gICAgcmVhZG9ubHkgam9iSWQ6IG51bWJlcjtcbiAgICByZWFkb25seSBydWxlcz86IEpvYlJ1bGVbXTtcblxuICAgIHJlYWRvbmx5IGFsbG93RmFpbHVyZTogYm9vbGVhbiB8IHtcbiAgICAgICAgZXhpdF9jb2RlczogbnVtYmVyIHwgbnVtYmVyW107XG4gICAgfTtcbiAgICByZWFkb25seSB3aGVuOiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgZXhpc3RzOiBzdHJpbmdbXTtcbiAgICByZWFkb25seSBwaXBlbGluZUlpZDogbnVtYmVyO1xuICAgIHJlYWRvbmx5IGdpdERhdGE6IEdpdERhdGE7XG4gICAgcmVhZG9ubHkgaW5oZXJpdDoge1xuICAgICAgICB2YXJpYWJsZXM/OiBib29sZWFuIHwgc3RyaW5nW107XG4gICAgfTtcblxuICAgIHByaXZhdGUgX2RvdGVudlZhcmlhYmxlczoge1trZXk6IHN0cmluZ106IHN0cmluZ30gPSB7fTtcbiAgICBwcml2YXRlIF9wcmVzY3JpcHRzRXhpdENvZGU6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX2FmdGVyU2NyaXB0c0V4aXRDb2RlID0gMDtcbiAgICBwcml2YXRlIF9jb3ZlcmFnZVBlcmNlbnQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX3J1bm5pbmcgPSBmYWxzZTtcbiAgICBwcml2YXRlIF9jb250YWluZXJJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBfc2VydmljZU5ldHdvcmtJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBfbG9uZ1J1bm5pbmdTaWxlbnRUaW1lb3V0OiBOb2RlSlMuVGltZW91dCA9IC0xIGFzIGFueTtcbiAgICBwcml2YXRlIF9wcm9kdWNlcnM6IHtuYW1lOiBzdHJpbmc7IGRvdGVudjogc3RyaW5nIHwgbnVsbH1bXSB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX2pvYk5hbWVQYWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX2NpUHJvamVjdERpcjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBfc3RhcnRUaW1lPzogW251bWJlciwgbnVtYmVyXTtcbiAgICBwcml2YXRlIF9lbmRUaW1lPzogW251bWJlciwgbnVtYmVyXTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2ZpbGVzVG9SbTogc3RyaW5nW10gPSBbXTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9nbG9iYWxWYXJpYWJsZXM6IHtba2V5OiBzdHJpbmddOiBzdHJpbmd9ID0ge307XG4gICAgcHJpdmF0ZSByZWFkb25seSBfdmFyaWFibGVzOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSA9IHt9O1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NvbnRhaW5lcnNUb0NsZWFuOiBzdHJpbmdbXSA9IFtdO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NvbnRhaW5lclZvbHVtZU5hbWVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgam9iRGF0YTogYW55O1xuICAgIHByaXZhdGUgcmVhZG9ubHkgd3JpdGVTdHJlYW1zOiBXcml0ZVN0cmVhbXM7XG5cbiAgICBjb25zdHJ1Y3RvciAob3B0OiBKb2JPcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGpvYkRhdGEgPSBvcHQuZGF0YTtcbiAgICAgICAgY29uc3Qgam9iVmFyaWFibGVzID0gam9iRGF0YS52YXJpYWJsZXMgPz8ge307XG4gICAgICAgIGNvbnN0IHZhcmlhYmxlc0Zyb21GaWxlcyA9IG9wdC52YXJpYWJsZXNGcm9tRmlsZXM7XG4gICAgICAgIGNvbnN0IGFyZ3YgPSBvcHQuYXJndjtcbiAgICAgICAgY29uc3QgY3dkID0gYXJndi5jd2Q7XG4gICAgICAgIGNvbnN0IGFyZ3ZWYXJpYWJsZXMgPSBhcmd2LnZhcmlhYmxlO1xuICAgICAgICBjb25zdCBleHBhbmRWYXJpYWJsZXMgPSBvcHQuZXhwYW5kVmFyaWFibGVzID8/IHRydWU7XG5cbiAgICAgICAgdGhpcy5hcmd2ID0gYXJndjtcbiAgICAgICAgdGhpcy53cml0ZVN0cmVhbXMgPSBvcHQud3JpdGVTdHJlYW1zO1xuICAgICAgICB0aGlzLmdpdERhdGEgPSBvcHQuZ2l0RGF0YTtcbiAgICAgICAgdGhpcy5uYW1lID0gb3B0Lm5hbWU7XG4gICAgICAgIHRoaXMuYmFzZU5hbWUgPSBvcHQuYmFzZU5hbWU7XG4gICAgICAgIHRoaXMuam9iSWQgPSB0aGlzLmdlbmVyYXRlSm9iSWQoKTtcbiAgICAgICAgdGhpcy5qb2JEYXRhID0gb3B0LmRhdGE7XG4gICAgICAgIHRoaXMucGlwZWxpbmVJaWQgPSBvcHQucGlwZWxpbmVJaWQ7XG4gICAgICAgIHRoaXMuX2dsb2JhbFZhcmlhYmxlcyA9IG9wdC5nbG9iYWxWYXJpYWJsZXM7XG5cbiAgICAgICAgdGhpcy5pbmhlcml0ID0ge307XG4gICAgICAgIHRoaXMuaW5oZXJpdC52YXJpYWJsZXMgPSB0aGlzLmpvYkRhdGEuaW5oZXJpdD8udmFyaWFibGVzID8/IHRydWU7XG5cbiAgICAgICAgdGhpcy53aGVuID0gam9iRGF0YS53aGVuIHx8IFwib25fc3VjY2Vzc1wiO1xuICAgICAgICB0aGlzLmV4aXN0cyA9IGpvYkRhdGEuZXhpc3RzIHx8IFtdO1xuICAgICAgICB0aGlzLmFsbG93RmFpbHVyZSA9IGpvYkRhdGEuYWxsb3dfZmFpbHVyZSA/PyBmYWxzZTtcbiAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXMgPSBqb2JEYXRhLmRlcGVuZGVuY2llcyB8fCBudWxsO1xuICAgICAgICB0aGlzLnJ1bGVzID0gam9iRGF0YS5ydWxlcyB8fCBudWxsO1xuICAgICAgICB0aGlzLmVudmlyb25tZW50ID0gdHlwZW9mIGpvYkRhdGEuZW52aXJvbm1lbnQgPT09IFwic3RyaW5nXCIgPyB7bmFtZTogam9iRGF0YS5lbnZpcm9ubWVudH0gOiAoam9iRGF0YS5lbnZpcm9ubWVudCA/IHsuLi5qb2JEYXRhLmVudmlyb25tZW50fSA6IGpvYkRhdGEuZW52aXJvbm1lbnQpO1xuXG4gICAgICAgIGNvbnN0IG1hdHJpeFZhcmlhYmxlcyA9IG9wdC5tYXRyaXhWYXJpYWJsZXMgPz8ge307XG4gICAgICAgIGNvbnN0IGZpbGVWYXJpYWJsZXMgPSBVdGlscy5maW5kRW52TWF0Y2hlZFZhcmlhYmxlcyh2YXJpYWJsZXNGcm9tRmlsZXMsIHRoaXMuZmlsZVZhcmlhYmxlc0Rpcik7XG4gICAgICAgIGNvbnN0IHByZWRlZmluZWRWYXJpYWJsZXMgPSB0aGlzLl9wcmVkZWZpbmVkVmFyaWFibGVzKG9wdCk7XG4gICAgICAgIHRoaXMuX3ZhcmlhYmxlcyA9IHsuLi5wcmVkZWZpbmVkVmFyaWFibGVzLCAuLi50aGlzLmdsb2JhbFZhcmlhYmxlcywgLi4uam9iVmFyaWFibGVzLCAuLi5tYXRyaXhWYXJpYWJsZXMsIC4uLmZpbGVWYXJpYWJsZXMsIC4uLmFyZ3ZWYXJpYWJsZXN9O1xuXG4gICAgICAgIGlmICh0aGlzLnJ1bGVzICYmIGV4cGFuZFZhcmlhYmxlcykge1xuICAgICAgICAgICAgY29uc3QgZXhwYW5kZWQgPSBVdGlscy5leHBhbmRWYXJpYWJsZXModGhpcy5fdmFyaWFibGVzKTtcblxuICAgICAgICAgICAgLy8gRXhwYW5kIHZhcmlhYmxlcyBpbiBydWxlczpjaGFuZ2VzXG4gICAgICAgICAgICB0aGlzLnJ1bGVzLmZvckVhY2goKHJ1bGUsIHJ1bGVJZHgsIHJ1bGVzKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2hhbmdlcyA9IEFycmF5LmlzQXJyYXkocnVsZS5jaGFuZ2VzKSA/IHJ1bGUuY2hhbmdlcyA6IHJ1bGUuY2hhbmdlcz8ucGF0aHM7XG4gICAgICAgICAgICAgICAgaWYgKCFjaGFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjaGFuZ2VzLmZvckVhY2goKGNoYW5nZSwgY2hhbmdlSWR4LCBjaGFuZ2VzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZXNbY2hhbmdlSWR4XSA9IFV0aWxzLmV4cGFuZFRleHQoY2hhbmdlLCBleHBhbmRlZCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcnVsZXNbcnVsZUlkeF0uY2hhbmdlcyA9IGNoYW5nZXM7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gRXhwYW5kIHZhcmlhYmxlcyBpbiBydWxlczpleGlzdHNcbiAgICAgICAgICAgIHRoaXMucnVsZXMuZm9yRWFjaCgocnVsZSwgcnVsZUlkeCwgcnVsZXMpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBleGlzdHMgPSBBcnJheS5pc0FycmF5KHJ1bGUuZXhpc3RzKSA/IHJ1bGUuZXhpc3RzIDogbnVsbDtcbiAgICAgICAgICAgICAgICBpZiAoIWV4aXN0cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGV4aXN0cy5mb3JFYWNoKChleGlzdCwgZXhpc3RJZCwgZXhpc3RzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGV4aXN0c1tleGlzdElkXSA9IFV0aWxzLmV4cGFuZFRleHQoZXhpc3QsIGV4cGFuZGVkKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBydWxlc1tydWxlSWR4XS5leGlzdHMgPSBleGlzdHM7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBydWxlVmFyaWFibGVzOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ30gfCB1bmRlZmluZWQ7XG4gICAgICAgIC8vIFNldCB7d2hlbiwgYWxsb3dGYWlsdXJlfSBiYXNlZCBvbiBydWxlcyByZXN1bHRcbiAgICAgICAgaWYgKHRoaXMucnVsZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHJ1bGVSZXN1bHQgPSBVdGlscy5nZXRSdWxlc1Jlc3VsdCh7YXJndiwgY3dkLCBydWxlczogdGhpcy5ydWxlcywgdmFyaWFibGVzOiB0aGlzLl92YXJpYWJsZXN9LCB0aGlzLmdpdERhdGEsIHRoaXMud2hlbiwgdGhpcy5hbGxvd0ZhaWx1cmUpO1xuICAgICAgICAgICAgdGhpcy53aGVuID0gcnVsZVJlc3VsdC53aGVuO1xuICAgICAgICAgICAgdGhpcy5hbGxvd0ZhaWx1cmUgPSBydWxlUmVzdWx0LmFsbG93RmFpbHVyZTtcbiAgICAgICAgICAgIHJ1bGVWYXJpYWJsZXMgPSBydWxlUmVzdWx0LnZhcmlhYmxlcztcbiAgICAgICAgICAgIGlmIChydWxlUmVzdWx0Lm5lZWRzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5qb2JEYXRhW1wibmVlZHNcIl0gPSBydWxlUmVzdWx0Lm5lZWRzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdmFyaWFibGVzID0gey4uLnRoaXMuX3ZhcmlhYmxlcywgLi4ucnVsZVZhcmlhYmxlcywgLi4uYXJndlZhcmlhYmxlc307XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaW5kIGVudmlyb25tZW50IG1hdGNoZWQgdmFyaWFibGVzXG4gICAgICAgIGlmICh0aGlzLmVudmlyb25tZW50ICYmIGV4cGFuZFZhcmlhYmxlcykge1xuICAgICAgICAgICAgY29uc3QgZXhwYW5kZWQgPSBVdGlscy5leHBhbmRWYXJpYWJsZXModGhpcy5fdmFyaWFibGVzKTtcbiAgICAgICAgICAgIGNvbnN0IGVudk5hbWVCZWZvcmVFeHBhbnNpb24gPSB0aGlzLmVudmlyb25tZW50Lm5hbWU7XG4gICAgICAgICAgICB0aGlzLmVudmlyb25tZW50Lm5hbWUgPSBVdGlscy5leHBhbmRUZXh0KHRoaXMuZW52aXJvbm1lbnQubmFtZSwgZXhwYW5kZWQpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZW52aXJvbm1lbnQubmFtZSAhPT0gZW52TmFtZUJlZm9yZUV4cGFuc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlZ2VuZXJhdGUgQ0lfRU5WSVJPTk1FTlRfU0xVRyBiYXNlZCBvbiBlbnYgbmFtZSBpZiBpdCBjaGFuZ2VkIGFmdGVyIGV4cGFuc2lvblxuICAgICAgICAgICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9FTlZJUk9OTUVOVF9TTFVHXCJdID0gdGhpcy5fZ2VuZXJhdGVFbnZpcm9ubWVudFNsdWcodGhpcy5lbnZpcm9ubWVudC5uYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZW52aXJvbm1lbnQudXJsID0gVXRpbHMuZXhwYW5kVGV4dCh0aGlzLmVudmlyb25tZW50LnVybCwgZXhwYW5kZWQpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGVudk1hdGNoZWRWYXJpYWJsZXMgPSBVdGlscy5maW5kRW52TWF0Y2hlZFZhcmlhYmxlcyh2YXJpYWJsZXNGcm9tRmlsZXMsIHRoaXMuZmlsZVZhcmlhYmxlc0RpciwgdGhpcy5lbnZpcm9ubWVudCk7XG5cbiAgICAgICAgY29uc3QgdXNlckRlZmluZWRWYXJpYWJsZXMgPSB7Li4udGhpcy5nbG9iYWxWYXJpYWJsZXMsIC4uLmpvYlZhcmlhYmxlcywgLi4ubWF0cml4VmFyaWFibGVzLCAuLi5ydWxlVmFyaWFibGVzLCAuLi5lbnZNYXRjaGVkVmFyaWFibGVzLCAuLi5hcmd2VmFyaWFibGVzfTtcbiAgICAgICAgdGhpcy5kaXNjb3VyYWdlT3ZlcnJpZGluZ09mUHJlZGVmaW5lZFZhcmlhYmxlcyhwcmVkZWZpbmVkVmFyaWFibGVzLCB1c2VyRGVmaW5lZFZhcmlhYmxlcywgYXJndi5pZ25vcmVQcmVkZWZpbmVkVmFycyk7XG5cbiAgICAgICAgLy8gTWVyZ2UgYW5kIGV4cGFuZCBhZnRlciBmaW5kaW5nIGVudiBtYXRjaGVkIHZhcmlhYmxlc1xuICAgICAgICB0aGlzLl92YXJpYWJsZXMgPSB7Li4ucHJlZGVmaW5lZFZhcmlhYmxlcywgLi4udXNlckRlZmluZWRWYXJpYWJsZXN9O1xuICAgICAgICAvLyBEZWxldGUgdmFyaWFibGVzIHRoZSB1c2VyIGludGVudGlvbmFsbHkgd2FudHMgdW5zZXRcbiAgICAgICAgZm9yIChjb25zdCB1bnNldFZhcmlhYmxlIG9mIGFyZ3YudW5zZXRWYXJpYWJsZXMpIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl92YXJpYWJsZXNbdW5zZXRWYXJpYWJsZV07XG4gICAgICAgIH1cbiAgICAgICAgLy8gU2V0IEdDTF9QUk9KRUNUX0RJUl9PTl9IT1NUIGlmIGRvY2tlciBpbWFnZVxuICAgICAgICBpZiAodGhpcy5pbWFnZU5hbWUodGhpcy5fdmFyaWFibGVzKSkge1xuICAgICAgICAgICAgdGhpcy5fdmFyaWFibGVzID0gey4uLnRoaXMuX3ZhcmlhYmxlcywgLi4ue0dDTF9QUk9KRUNUX0RJUl9PTl9IT1NUOiBjd2R9fTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFzc2VydCh0aGlzLnNjcmlwdHMgfHwgdGhpcy50cmlnZ2VyLCBjaGFsa2B7Ymx1ZUJyaWdodCAke3RoaXMubmFtZX19IG11c3QgaGF2ZSBzY3JpcHQgc3BlY2lmaWVkYCk7XG5cbiAgICAgICAgYXNzZXJ0KCEodGhpcy5pbnRlcmFjdGl2ZSAmJiAhdGhpcy5hcmd2LnNoZWxsRXhlY3V0b3JOb0ltYWdlKSwgY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IEBJbnRlcmFjdGl2ZSBkZWNvcmF0b3IgY2Fubm90IGJlIHVzZWQgd2l0aCAtLW5vLXNoZWxsLWV4ZWN1dG9yLW5vLWltYWdlYCk7XG5cbiAgICAgICAgaWYgKHRoaXMuaW50ZXJhY3RpdmUgJiYgKHRoaXMud2hlbiAhPT0gXCJtYW51YWxcIiB8fCB0aGlzLmltYWdlTmFtZSh0aGlzLl92YXJpYWJsZXMpICE9PSBudWxsKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKHttZXNzYWdlOiBgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IEBJbnRlcmFjdGl2ZSBkZWNvcmF0b3IgY2Fubm90IGhhdmUgaW1hZ2U6IGFuZCBtdXN0IGJlIHdoZW46bWFudWFsYH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuaW5qZWN0U1NIQWdlbnQgJiYgdGhpcy5pbWFnZU5hbWUodGhpcy5fdmFyaWFibGVzKSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKHttZXNzYWdlOiBgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IEBJbmplY3RTU0hBZ2VudCBjYW4gb25seSBiZSB1c2VkIHdpdGggaW1hZ2U6YH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZXhwYW5kZWQgPSBVdGlscy5leHBhbmRWYXJpYWJsZXModGhpcy5fdmFyaWFibGVzKTtcbiAgICAgICAgZm9yIChjb25zdCBbaSwgY10gb2YgT2JqZWN0LmVudHJpZXM8YW55Pih0aGlzLmNhY2hlKSkge1xuICAgICAgICAgICAgYy5wb2xpY3kgPSBVdGlscy5leHBhbmRUZXh0KGMucG9saWN5LCBleHBhbmRlZCk7XG4gICAgICAgICAgICBhc3NlcnQoW1wicHVsbFwiLCBcInB1c2hcIiwgXCJwdWxsLXB1c2hcIl0uaW5jbHVkZXMoYy5wb2xpY3kpLCBjaGFsa2B7Ymx1ZSAke3RoaXMubmFtZX19IGNhY2hlWyR7aX1dLnBvbGljeSBpcyBub3QgJ3B1bGwnLCAncHVzaCcgb3IgJ3B1bGwtcHVzaCdgKTtcbiAgICAgICAgICAgIGFzc2VydChbXCJvbl9zdWNjZXNzXCIsIFwib25fZmFpbHVyZVwiLCBcImFsd2F5c1wiXS5pbmNsdWRlcyhjLndoZW4pLCBjaGFsa2B7Ymx1ZSAke3RoaXMubmFtZX19IGNhY2hlWyR7aX1dLndoZW4gaXMgbm90ICdvbl9zdWNjZXNzJywgJ29uX2ZhaWx1cmUnIG9yICdhbHdheXMnYCk7XG4gICAgICAgICAgICBhc3NlcnQoQXJyYXkuaXNBcnJheShjLnBhdGhzKSwgY2hhbGtge2JsdWUgJHt0aGlzLm5hbWV9fSBjYWNoZVske2l9XS5wYXRocyBtdXN0IGJlIGFycmF5YCk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IFtpLCBzXSBvZiBPYmplY3QuZW50cmllczxhbnk+KHRoaXMuc2VydmljZXMpKSB7XG4gICAgICAgICAgICBhc3NlcnQocy5uYW1lLCBjaGFsa2B7Ymx1ZSAke3RoaXMubmFtZX19IHNlcnZpY2VzWyR7aX1dLm5hbWUgaXMgdW5kZWZpbmVkYCk7XG4gICAgICAgICAgICBhc3NlcnQoIXMuY29tbWFuZCB8fCBBcnJheS5pc0FycmF5KHMuY29tbWFuZCksIGNoYWxrYHtibHVlICR7dGhpcy5uYW1lfX0gc2VydmljZXNbJHtpfV0uY29tbWFuZCBtdXN0IGJlIGFuIGFycmF5YCk7XG4gICAgICAgICAgICBhc3NlcnQoIXMuZW50cnlwb2ludCB8fCBBcnJheS5pc0FycmF5KHMuZW50cnlwb2ludCksIGNoYWxrYHtibHVlICR7dGhpcy5uYW1lfX0gc2VydmljZXNbJHtpfV0uZW50cnlwb2ludCBtdXN0IGJlIGFuIGFycmF5YCk7XG4gICAgICAgIH1cblxuICAgICAgICBhc3NlcnQoIXRoaXMuYXJ0aWZhY3RzPy5wYXRocyB8fCBBcnJheS5pc0FycmF5KHRoaXMuYXJ0aWZhY3RzLnBhdGhzKSwgY2hhbGtge2JsdWUgJHt0aGlzLm5hbWV9fSBhcnRpZmFjdHMucGF0aHMgbXVzdCBiZSBhbiBhcnJheWApO1xuXG4gICAgICAgIGlmICh0aGlzLmltYWdlTmFtZSh0aGlzLl92YXJpYWJsZXMpICYmIGFyZ3YubW91bnRDYWNoZSkge1xuICAgICAgICAgICAgZm9yIChjb25zdCBjIG9mIHRoaXMuY2FjaGUpIHtcbiAgICAgICAgICAgICAgICBjLnBhdGhzLmZvckVhY2goKHApID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGF0aCA9IFV0aWxzLmV4cGFuZFRleHQocCwgZXhwYW5kZWQpO1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQoIXBhdGguaW5jbHVkZXMoXCIqXCIpLCBjaGFsa2B7Ymx1ZSAke3RoaXMubmFtZX19IGNhbm5vdCBoYXZlICogaW4gY2FjaGUgcGF0aHMsIHdoZW4gLS1tb3VudC1jYWNoZSBpcyBlbmFibGVkYCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAgV2FybiB3aGVuIG92ZXJyaWRpbmcgb2YgcHJlZGVmaW5lZCB2YXJpYWJsZXMgaXMgZGV0ZWN0ZWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGRpc2NvdXJhZ2VPdmVycmlkaW5nT2ZQcmVkZWZpbmVkVmFyaWFibGVzIChwcmVkZWZpbmVkVmFyaWFibGVzOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ30sIHVzZXJEZWZpbmVkVmFyaWFibGVzOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ30sIHdoaXRlTGlzdGVkUHJlZGVmaW5lZFZhcmlhYmxlc0tleXM6IHN0cmluZ1tdKSB7XG4gICAgICAgIGNvbnN0IHByZWRlZmluZWRWYXJpYWJsZXNLZXlzID0gT2JqZWN0LmtleXMocHJlZGVmaW5lZFZhcmlhYmxlcyk7XG4gICAgICAgIGNvbnN0IHVzZXJEZWZpbmVkVmFyaWFibGVzS2V5cyA9IE9iamVjdC5rZXlzKHVzZXJEZWZpbmVkVmFyaWFibGVzKTtcblxuICAgICAgICBjb25zdCBvdmVycmlkaW5nT2ZQcmVkZWZpbmVkVmFyaWFibGVzID0gdXNlckRlZmluZWRWYXJpYWJsZXNLZXlzLmZpbHRlcihlbGUgPT4gcHJlZGVmaW5lZFZhcmlhYmxlc0tleXMuaW5jbHVkZXMoZWxlKSAmJiAhd2hpdGVMaXN0ZWRQcmVkZWZpbmVkVmFyaWFibGVzS2V5cy5pbmNsdWRlcyhlbGUpKTtcbiAgICAgICAgaWYgKG92ZXJyaWRpbmdPZlByZWRlZmluZWRWYXJpYWJsZXMubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGxpbmtUb0dpdGxhYiA9IFwiaHR0cHM6Ly9naXRsYWIuY29tL2dpdGxhYi1vcmcvZ2l0bGFiLy0vYmxvYi92MTcuNy4xLWVlL2RvYy9jaS92YXJpYWJsZXMvcHJlZGVmaW5lZF92YXJpYWJsZXMubWQ/cGxhaW49MSZyZWZfdHlwZT10YWdzI0wxNS0xNlwiO1xuICAgICAgICB0aGlzLndyaXRlU3RyZWFtcy5tZW1vU3Rkb3V0KGNoYWxrYFxue2JnWWVsbG93QnJpZ2h0ICBXQVJOIH0gJHt0ZXJtaW5hbExpbmsoXCJBdm9pZCBvdmVycmlkaW5nIHByZWRlZmluZWQgdmFyaWFibGVzXCIsIGxpbmtUb0dpdGxhYil9IFt7Ym9sZCAke292ZXJyaWRpbmdPZlByZWRlZmluZWRWYXJpYWJsZXN9fV0gYXMgaXQgY2FuIGNhdXNlIHRoZSBwaXBlbGluZSB0byBiZWhhdmUgdW5leHBlY3RlZGx5LlxuSWYgeW91IGtub3cgd2hhdCB5b3UncmUgZG9pbmcgYW5kIHdvdWxkIGxpa2UgdG8gc3VwcHJlc3MgdGhpcyB3YXJuaW5nLCB1c2Ugb25lIG9mIHRoZSBmb2xsb3dpbmcgbWV0aG9kczpcblxcdOKAoiB2aWEgY2xpIG9wdGlvbnNcblxcdFxcdOKAoiAtLWlnbm9yZS1wcmVkZWZpbmVkLXZhcnMgJHtvdmVycmlkaW5nT2ZQcmVkZWZpbmVkVmFyaWFibGVzfVxuXFx04oCiIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZVxuXFx0XFx04oCiIEdDTF9JR05PUkVfUFJFREVGSU5FRF9WQVJTPSR7b3ZlcnJpZGluZ09mUHJlZGVmaW5lZFZhcmlhYmxlc31cbmApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgcHJlZGVmaW5lZFZhcmlhYmxlcyB0aGF0J3MgZW5yaWNoZWQgd2l0aCB0aGUgYWRkaXRpb25hbCBpbmZvIHRoYXQncyBvbmx5IGF2YWlsYWJsZSB3aGVuIGNvbnN0cnVjdGluZ1xuICAgICAqL1xuICAgIHByaXZhdGUgX3ByZWRlZmluZWRWYXJpYWJsZXMgKG9wdDogSm9iT3B0aW9ucykge1xuICAgICAgICBjb25zdCBhcmd2ID0gdGhpcy5hcmd2O1xuICAgICAgICBjb25zdCBjd2QgPSBhcmd2LmN3ZDtcbiAgICAgICAgY29uc3Qgc3RhdGVEaXIgPSB0aGlzLmFyZ3Yuc3RhdGVEaXI7XG4gICAgICAgIGNvbnN0IGdpdERhdGEgPSB0aGlzLmdpdERhdGE7XG5cbiAgICAgICAgbGV0IGNpQnVpbGRzRGlyOiBzdHJpbmc7XG4gICAgICAgIGlmICh0aGlzLmpvYkRhdGFbXCJpbWFnZVwiXSkge1xuICAgICAgICAgICAgY2lCdWlsZHNEaXIgPSBcIi9idWlsZHNcIjtcbiAgICAgICAgICAgIHRoaXMuY2lQcm9qZWN0RGlyID0gYCR7Y2lCdWlsZHNEaXJ9LyR7Z2l0RGF0YS5yZW1vdGUuZ3JvdXB9LyR7Z2l0RGF0YS5yZW1vdGUucHJvamVjdH1gO1xuICAgICAgICB9IGVsc2UgaWYgKGFyZ3Yuc2hlbGxJc29sYXRpb24pIHtcbiAgICAgICAgICAgIGNpQnVpbGRzRGlyID0gYCR7Y3dkfS8ke3N0YXRlRGlyfS9idWlsZHMvJHt0aGlzLnNhZmVKb2JOYW1lfWA7XG4gICAgICAgICAgICB0aGlzLmNpUHJvamVjdERpciA9IGNpQnVpbGRzRGlyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2lCdWlsZHNEaXIgPSBjd2Q7XG4gICAgICAgICAgICB0aGlzLmNpUHJvamVjdERpciA9IGNpQnVpbGRzRGlyO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcHJlZGVmaW5lZFZhcmlhYmxlcyA9IG9wdC5wcmVkZWZpbmVkVmFyaWFibGVzO1xuXG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9KT0JfSURcIl0gPSBgJHt0aGlzLmpvYklkfWA7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9QSVBFTElORV9JRFwiXSA9IGAke3RoaXMucGlwZWxpbmVJaWQgKyAxMDAwfWA7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9QSVBFTElORV9JSURcIl0gPSBgJHt0aGlzLnBpcGVsaW5lSWlkfWA7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9KT0JfTkFNRVwiXSA9IGAke3RoaXMubmFtZX1gO1xuICAgICAgICBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfSk9CX05BTUVfU0xVR1wiXSA9IGAke3RoaXMubmFtZS5yZXBsYWNlKC9bXmEtelxcZF0rL2lnLCBcIi1cIikucmVwbGFjZSgvXi0vLCBcIlwiKS5zbGljZSgwLCA2MykucmVwbGFjZSgvLSQvLCBcIlwiKS50b0xvd2VyQ2FzZSgpfWA7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9KT0JfU1RBR0VcIl0gPSBgJHt0aGlzLnN0YWdlfWA7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9CVUlMRFNfRElSXCJdID0gY2lCdWlsZHNEaXI7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9QUk9KRUNUX0RJUlwiXSA9IHRoaXMuY2lQcm9qZWN0RGlyO1xuICAgICAgICBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfSk9CX1VSTFwiXSA9IGAke3ByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9TRVJWRVJfVVJMXCJdfS8ke2dpdERhdGEucmVtb3RlLmdyb3VwfS8ke2dpdERhdGEucmVtb3RlLnByb2plY3R9Ly0vam9icy8ke3RoaXMuam9iSWR9YDsgLy8gQ2hhbmdlcyBvbiByZXJ1bi5cbiAgICAgICAgcHJlZGVmaW5lZFZhcmlhYmxlc1tcIkNJX1BJUEVMSU5FX1VSTFwiXSA9IGAke3ByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9TRVJWRVJfVVJMXCJdfS8ke2dpdERhdGEucmVtb3RlLmdyb3VwfS8ke2dpdERhdGEucmVtb3RlLnByb2plY3R9L3BpcGVsaW5lcy8ke3RoaXMucGlwZWxpbmVJaWR9YDtcbiAgICAgICAgcHJlZGVmaW5lZFZhcmlhYmxlc1tcIkNJX0VOVklST05NRU5UX05BTUVcIl0gPSB0aGlzLmVudmlyb25tZW50Py5uYW1lID8/IFwiXCI7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9FTlZJUk9OTUVOVF9TTFVHXCJdID0gdGhpcy5lbnZpcm9ubWVudD8ubmFtZSA/IHRoaXMuX2dlbmVyYXRlRW52aXJvbm1lbnRTbHVnKHRoaXMuZW52aXJvbm1lbnQubmFtZSkgOiBcIlwiO1xuICAgICAgICBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfRU5WSVJPTk1FTlRfVVJMXCJdID0gdGhpcy5lbnZpcm9ubWVudD8udXJsID8/IFwiXCI7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9FTlZJUk9OTUVOVF9USUVSXCJdID0gdGhpcy5lbnZpcm9ubWVudD8uZGVwbG95bWVudF90aWVyID8/IFwiXCI7XG4gICAgICAgIHByZWRlZmluZWRWYXJpYWJsZXNbXCJDSV9FTlZJUk9OTUVOVF9BQ1RJT05cIl0gPSB0aGlzLmVudmlyb25tZW50Py5hY3Rpb24gPz8gXCJcIjtcblxuICAgICAgICBpZiAob3B0Lm5vZGVJbmRleCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcHJlZGVmaW5lZFZhcmlhYmxlc1tcIkNJX05PREVfSU5ERVhcIl0gPSBgJHtvcHQubm9kZUluZGV4fWA7XG4gICAgICAgIH1cbiAgICAgICAgcHJlZGVmaW5lZFZhcmlhYmxlc1tcIkNJX05PREVfVE9UQUxcIl0gPSBgJHtvcHQubm9kZXNUb3RhbH1gO1xuICAgICAgICBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfUkVHSVNUUllcIl0gPSBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfUkVHSVNUUllcIl0gPSB0aGlzLmFyZ3YucmVnaXN0cnkgPyBVdGlscy5nY2xSZWdpc3RyeVByZWZpeCA6IGBsb2NhbC1yZWdpc3RyeS4ke3RoaXMuZ2l0RGF0YS5yZW1vdGUuaG9zdH1gO1xuICAgICAgICBwcmVkZWZpbmVkVmFyaWFibGVzW1wiQ0lfUkVHSVNUUllfSU1BR0VcIl0gPSBgJENJX1JFR0lTVFJZLyR7cHJlZGVmaW5lZFZhcmlhYmxlc1tcIkNJX1BST0pFQ1RfUEFUSFwiXS50b0xvd2VyQ2FzZSgpfWA7XG4gICAgICAgIHJldHVybiBwcmVkZWZpbmVkVmFyaWFibGVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlcyBhIGNvbXBsaWFudCBzbHVnIGZvciBhbiBlbnZpcm9ubWVudCBuYW1lLlxuICAgICAqIFNlZTogaHR0cHM6Ly9naXRsYWIuY29tL2dpdGxhYi1vcmcvZ2l0bGFiLy0vYmxvYi9mYzMxZTdhYzM0NGU1M2ViYWUxODJlYTFkY2ExODNiZGMwZTJlYTcxL2xpYi9naXRsYWIvc2x1Zy9lbnZpcm9ubWVudC5yYlxuICAgICAqXG4gICAgICogVGhlIHNsdWc6XG4gICAgICogLSBDb250YWlucyBvbmx5IGxvd2VyY2FzZSBsZXR0ZXJzIChhLXopLCBudW1iZXJzICgwLTkpLCBhbmQgJy0nLlxuICAgICAqIC0gQmVnaW5zIHdpdGggYSBsZXR0ZXIuXG4gICAgICogLSBIYXMgYSBtYXhpbXVtIGxlbmd0aCBvZiAyNCBjaGFyYWN0ZXJzLlxuICAgICAqIC0gRG9lcyBub3QgZW5kIHdpdGggJy0nLlxuICAgICAqXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG9yaWdpbmFsIGVudmlyb25tZW50IG5hbWUuXG4gICAgICogQHJldHVybnMgQSBjb21wbGlhbnQgZW52aXJvbm1lbnQgc2x1Zy5cbiAgICAgKi9cbiAgICBwcml2YXRlIF9nZW5lcmF0ZUVudmlyb25tZW50U2x1ZyAobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgLy8gMS4gTG93ZXJjYXNlLCByZXBsYWNlIG5vbi1hbHBoYW51bWVyaWMgd2l0aCAnLScsIGFuZCBzcXVlZXplIHJlcGVhdGluZyAnLSdcbiAgICAgICAgbGV0IHNsdWcgPSBuYW1lXG4gICAgICAgICAgICAudG9Mb3dlckNhc2UoKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1teYS16MC05XS9nLCBcIi1cIilcbiAgICAgICAgICAgIC5yZXBsYWNlKC8tKy9nLCBcIi1cIik7XG5cbiAgICAgICAgLy8gMi4gTXVzdCBzdGFydCB3aXRoIGEgbGV0dGVyXG4gICAgICAgIGlmICghL15bYS16XS8udGVzdChzbHVnKSkge1xuICAgICAgICAgICAgc2x1ZyA9IGBlbnYtJHtzbHVnfWA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAzLiBJZiBpdCdzIHRvbyBsb25nIG9yIHdhcyBtb2RpZmllZCwgc2hvcnRlbiBhbmQgYWRkIGEgaGFzaCBzdWZmaXhcbiAgICAgICAgaWYgKHNsdWcubGVuZ3RoID4gMjQgfHwgc2x1ZyAhPT0gbmFtZSkge1xuICAgICAgICAgICAgLy8gVHJ1bmNhdGUgdG8gMTcgY2hhcnMgKGxlYXZpbmcgcm9vbSBmb3IgJy0nICsgNi1jaGFyIGhhc2gpXG4gICAgICAgICAgICBzbHVnID0gc2x1Zy5zbGljZSgwLCAxNyk7XG5cbiAgICAgICAgICAgIC8vIEVuc3VyZSBpdCBlbmRzIHdpdGggYSBkYXNoIGJlZm9yZSBhZGRpbmcgdGhlIHN1ZmZpeFxuICAgICAgICAgICAgaWYgKCFzbHVnLmVuZHNXaXRoKFwiLVwiKSkge1xuICAgICAgICAgICAgICAgIHNsdWcgKz0gXCItXCI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSB0aGUgNi1jaGFyIHN1ZmZpeCBmcm9tIGEgaGFzaCBvZiB0aGUgKm9yaWdpbmFsKiBuYW1lXG4gICAgICAgICAgICBjb25zdCBoZXhIYXNoID0gY3J5cHRvXG4gICAgICAgICAgICAgICAgLmNyZWF0ZUhhc2goXCJzaGEyNTZcIilcbiAgICAgICAgICAgICAgICAudXBkYXRlKG5hbWUpXG4gICAgICAgICAgICAgICAgLmRpZ2VzdChcImhleFwiKTtcblxuICAgICAgICAgICAgLy8gVXNlIEJpZ0ludCBmb3Igc2FmZSBjb252ZXJzaW9uIGZyb20gaGV4IC0+IGJhc2UzNlxuICAgICAgICAgICAgY29uc3Qgc3VmZml4ID0gQmlnSW50KGAweCR7aGV4SGFzaH1gKS50b1N0cmluZygzNikuc2xpY2UoLTYpO1xuXG4gICAgICAgICAgICByZXR1cm4gc2x1ZyArIHN1ZmZpeDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDQuIElmIGl0IHdhcyBzaG9ydCBhbmQgdW5tb2RpZmllZCwganVzdCBlbnN1cmUgaXQgZG9lc24ndCBlbmQgd2l0aCAnLSdcbiAgICAgICAgcmV0dXJuIHNsdWcucmVwbGFjZSgvLSQvLCBcIlwiKTtcbiAgICB9XG5cbiAgICBnZXQgam9iU3RhdHVzICgpIHtcbiAgICAgICAgaWYgKHRoaXMucHJlU2NyaXB0c0V4aXRDb2RlID09IG51bGwpIHJldHVybiBcInBlbmRpbmdcIjtcbiAgICAgICAgaWYgKHRoaXMucHJlU2NyaXB0c0V4aXRDb2RlID09IDApIHJldHVybiBcInN1Y2Nlc3NcIjtcblxuICAgICAgICBsZXQgYWxsb3dlZEV4aXRDb2RlcyA9IFswXTtcbiAgICAgICAgY29uc3QgYWxsb3dGYWlsdXJlID0gdGhpcy5hbGxvd0ZhaWx1cmU7XG4gICAgICAgIHN3aXRjaCAodHlwZW9mIGFsbG93RmFpbHVyZSkge1xuICAgICAgICAgICAgY2FzZSBcImJvb2xlYW5cIjpcbiAgICAgICAgICAgICAgICBpZiAoYWxsb3dGYWlsdXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIGFsbG93ZWRFeGl0Q29kZXMgPSBbdGhpcy5wcmVTY3JpcHRzRXhpdENvZGVdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJvYmplY3RcIjpcbiAgICAgICAgICAgICAgICBpZiAoISBBcnJheS5pc0FycmF5KGFsbG93RmFpbHVyZS5leGl0X2NvZGVzKSkge1xuICAgICAgICAgICAgICAgICAgICBhbGxvd2VkRXhpdENvZGVzID0gW2FsbG93RmFpbHVyZS5leGl0X2NvZGVzXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhbGxvd2VkRXhpdENvZGVzID0gYWxsb3dGYWlsdXJlLmV4aXRfY29kZXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgdHlwZTogICR7dHlwZW9mIGFsbG93RmFpbHVyZX1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhbGxvd2VkRXhpdENvZGVzLmluY2x1ZGVzKHRoaXMucHJlU2NyaXB0c0V4aXRDb2RlKSA/IFwid2FybmluZ1wiIDogXCJmYWlsZWRcIjtcbiAgICB9XG5cbiAgICBnZXQgYXJ0aWZhY3RzVG9Tb3VyY2UgKCkge1xuICAgICAgICBpZiAodGhpcy5qb2JEYXRhW1wiZ2NsQXJ0aWZhY3RzVG9Tb3VyY2VcIl0gIT0gbnVsbCkgcmV0dXJuIHRoaXMuam9iRGF0YVtcImdjbEFydGlmYWN0c1RvU291cmNlXCJdO1xuICAgICAgICByZXR1cm4gdGhpcy5hcmd2LmFydGlmYWN0c1RvU291cmNlO1xuICAgIH1cblxuICAgIGdldCBwcmV0dHlEdXJhdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLl9lbmRUaW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJldHR5SHJ0aW1lKHRoaXMuX2VuZFRpbWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX3N0YXJ0VGltZSA/XG4gICAgICAgICAgICBwcmV0dHlIcnRpbWUocHJvY2Vzcy5ocnRpbWUodGhpcy5fc3RhcnRUaW1lKSkgOlxuICAgICAgICAgICAgXCIwIG1zXCI7XG4gICAgfVxuXG4gICAgZ2V0IGZvcm1hdHRlZEpvYk5hbWUgKCkge1xuICAgICAgICBsZXQgcHJlZml4ID0gXCJcIjtcbiAgICAgICAgaWYgKHRoaXMuYXJndi5jaGlsZFBpcGVsaW5lRGVwdGggPiAwKSBwcmVmaXggPSBcIlxcdFwiLnJlcGVhdCh0aGlzLmFyZ3YuY2hpbGRQaXBlbGluZURlcHRoKSArIGBbJHt0aGlzLmFyZ3YudmFyaWFibGUuR0NMX1RSSUdHRVJFUn1dIC0+IGA7XG4gICAgICAgIGNvbnN0IHRpbWVzdGFtcFByZWZpeCA9IHRoaXMuYXJndi5zaG93VGltZXN0YW1wcyA/XG4gICAgICAgICAgICBgWyR7ZGF0ZUZvcm1hdHRlci5mb3JtYXQobmV3IERhdGUoKSl9ICR7dGhpcy5wcmV0dHlEdXJhdGlvbi5wYWRTdGFydCg3KX1dIGAgOlxuICAgICAgICAgICAgXCJcIjtcblxuICAgICAgICAvLyBbMTY6MzM6MTkgMS4zNyBtaW5dIG15LWpvYiAgICAgPiBoZWxsbyB3b3JsZFxuICAgICAgICByZXR1cm4gY2hhbGtgJHt0aW1lc3RhbXBQcmVmaXh9e2JsdWVCcmlnaHQgJHtwcmVmaXh9JHt0aGlzLm5hbWUucGFkRW5kKHRoaXMuam9iTmFtZVBhZCl9fWA7XG4gICAgfVxuXG4gICAgZ2V0IHNhZmVKb2JOYW1lICgpIHtcbiAgICAgICAgcmV0dXJuIFV0aWxzLnNhZmVEb2NrZXJTdHJpbmcodGhpcy5uYW1lKTtcbiAgICB9XG5cbiAgICBnZXQgbmVlZHMgKCk6IE5lZWRbXSB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5qb2JEYXRhW1wibmVlZHNcIl0gPz8gbnVsbDtcbiAgICB9XG5cbiAgICBnZXQgYnVpbGRWb2x1bWVOYW1lICgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYGdjbC0ke3RoaXMuc2FmZUpvYk5hbWV9LSR7dGhpcy5qb2JJZH0tYnVpbGRgO1xuICAgIH1cblxuICAgIGdldCB0bXBWb2x1bWVOYW1lICgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYGdjbC0ke3RoaXMuc2FmZUpvYk5hbWV9LSR7dGhpcy5qb2JJZH0tdG1wYDtcbiAgICB9XG5cbiAgICBnZXQgc2VydmljZXMgKCk6IFNlcnZpY2VbXSB7XG4gICAgICAgIGNvbnN0IHNlcnZpY2VzOiBTZXJ2aWNlW10gPSBbXTtcbiAgICAgICAgaWYgKCF0aGlzLmpvYkRhdGFbXCJzZXJ2aWNlc1wiXSkgcmV0dXJuIFtdO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc2VydmljZSBvZiBPYmplY3QudmFsdWVzPGFueT4odGhpcy5qb2JEYXRhW1wic2VydmljZXNcIl0pKSB7XG4gICAgICAgICAgICBjb25zdCBleHBhbmRlZCA9IFV0aWxzLmV4cGFuZFZhcmlhYmxlcyh7Li4udGhpcy5fdmFyaWFibGVzLCAuLi50aGlzLl9kb3RlbnZWYXJpYWJsZXMsIC4uLnNlcnZpY2VbXCJ2YXJpYWJsZXNcIl19KTtcbiAgICAgICAgICAgIGxldCBzZXJ2aWNlTmFtZSA9IFV0aWxzLmV4cGFuZFRleHQoc2VydmljZVtcIm5hbWVcIl0sIGV4cGFuZGVkKTtcbiAgICAgICAgICAgIGlmIChzZXJ2aWNlTmFtZSA9PSBcIlwiKSBjb250aW51ZTtcbiAgICAgICAgICAgIHNlcnZpY2VOYW1lID0gc2VydmljZU5hbWUuaW5jbHVkZXMoXCI6XCIpID8gc2VydmljZU5hbWUgOiBgJHtzZXJ2aWNlTmFtZX06bGF0ZXN0YDtcbiAgICAgICAgICAgIHNlcnZpY2VzLnB1c2goe1xuICAgICAgICAgICAgICAgIG5hbWU6IHNlcnZpY2VOYW1lLFxuICAgICAgICAgICAgICAgIGVudHJ5cG9pbnQ6IHNlcnZpY2VbXCJlbnRyeXBvaW50XCJdID8/IG51bGwsXG4gICAgICAgICAgICAgICAgY29tbWFuZDogc2VydmljZVtcImNvbW1hbmRcIl0gPz8gbnVsbCxcbiAgICAgICAgICAgICAgICB2YXJpYWJsZXM6IGV4cGFuZGVkLFxuICAgICAgICAgICAgICAgIGFsaWFzOiBVdGlscy5leHBhbmRUZXh0KHNlcnZpY2VbXCJhbGlhc1wiXSwgZXhwYW5kZWQpID8/IG51bGwsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2VydmljZXM7XG4gICAgfVxuXG4gICAgc2V0IGNpUHJvamVjdERpciAoY2lQcm9qZWN0RGlyOiBzdHJpbmcpIHtcbiAgICAgICAgYXNzZXJ0KHRoaXMuX2NpUHJvamVjdERpciA9PSBudWxsLCBcInRoaXMuX2NpUHJvamVjdERpciBjYW4gb25seSBiZSBzZXQgb25jZVwiKTtcbiAgICAgICAgdGhpcy5fY2lQcm9qZWN0RGlyID0gY2lQcm9qZWN0RGlyO1xuICAgIH1cbiAgICBnZXQgY2lQcm9qZWN0RGlyICgpIHtcbiAgICAgICAgYXNzZXJ0KHRoaXMuX2NpUHJvamVjdERpciwgXCJhdHRlbXB0ZWQgdG8gYWNjZXNzIHRoaXMuX2NpUHJvamVjdERpciBiZWZvcmUgaXQgaXMgaW5pdGlhbGl6ZWRcIik7XG4gICAgICAgIHJldHVybiB0aGlzLl9jaVByb2plY3REaXI7XG4gICAgfVxuXG4gICAgc2V0IGpvYk5hbWVQYWQgKGpvYk5hbWVQYWQ6IG51bWJlcikge1xuICAgICAgICBhc3NlcnQodGhpcy5fam9iTmFtZVBhZCA9PSBudWxsLCBcInRoaXMuX2pvYk5hbWVQYWQgY2FuIG9ubHkgYmUgc2V0IG9uY2VcIik7XG4gICAgICAgIHRoaXMuX2pvYk5hbWVQYWQgPSBqb2JOYW1lUGFkO1xuICAgIH1cblxuICAgIGdldCBqb2JOYW1lUGFkICgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5fam9iTmFtZVBhZCA/PyAwO1xuICAgIH1cblxuICAgIGdldCBwcm9kdWNlcnMgKCk6IHtuYW1lOiBzdHJpbmc7IGRvdGVudjogc3RyaW5nIHwgbnVsbH1bXSB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5fcHJvZHVjZXJzO1xuICAgIH1cblxuICAgIHNldCBwcm9kdWNlcnMgKHByb2R1Y2Vyczoge25hbWU6IHN0cmluZzsgZG90ZW52OiBzdHJpbmcgfCBudWxsfVtdIHwgbnVsbCkge1xuICAgICAgICBhc3NlcnQodGhpcy5fcHJvZHVjZXJzID09IG51bGwsIFwidGhpcy5fcHJvZHVjZXJzIGNhbiBvbmx5IGJlIHNldCBvbmNlXCIpO1xuICAgICAgICB0aGlzLl9wcm9kdWNlcnMgPSBwcm9kdWNlcnM7XG4gICAgfVxuXG4gICAgZ2V0IHN0YWdlICgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5qb2JEYXRhW1wic3RhZ2VcIl0gfHwgXCJ0ZXN0XCI7XG4gICAgfVxuXG4gICAgZ2V0IGludGVyYWN0aXZlICgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuam9iRGF0YVtcImdjbEludGVyYWN0aXZlXCJdIHx8IGZhbHNlO1xuICAgIH1cblxuICAgIGdldCBpbmplY3RTU0hBZ2VudCAoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmpvYkRhdGFbXCJnY2xJbmplY3RTU0hBZ2VudFwiXSB8fCBmYWxzZTtcbiAgICB9XG5cbiAgICBnZXQgZGVzY3JpcHRpb24gKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLmpvYkRhdGFbXCJnY2xEZXNjcmlwdGlvblwiXSA/PyBcIlwiO1xuICAgIH1cblxuICAgIGdldCBhcnRpZmFjdHMgKCk6IHtwYXRoczogc3RyaW5nW107IGV4Y2x1ZGU/OiBzdHJpbmdbXTsgcmVwb3J0cz86IHtkb3RlbnY/OiBzdHJpbmd9OyB3aGVuPzogc3RyaW5nfSB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5qb2JEYXRhW1wiYXJ0aWZhY3RzXCJdO1xuICAgIH1cblxuICAgIGRlbGV0ZUFydGlmYWN0cyAoKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmpvYkRhdGFbXCJhcnRpZmFjdHNcIl07XG4gICAgfVxuXG4gICAgZ2V0IGNhY2hlICgpOiBDYWNoZVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuam9iRGF0YVtcImNhY2hlXCJdIHx8IFtdO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRVbmlxdWVDYWNoZU5hbWUgKGN3ZDogc3RyaW5nLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30sIGNhY2hlSW5kZXg6IG51bWJlcikge1xuICAgICAgICBjb25zdCBnZXRDYWNoZVByZWZpeCA9IChpbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwcmVmaXggPSB0aGlzLmpvYkRhdGFbXCJjYWNoZVwiXVtpbmRleF1bXCJrZXlcIl1bXCJwcmVmaXhcIl07XG4gICAgICAgICAgICBpZiAocHJlZml4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGAke2luZGV4fV8ke1V0aWxzLmV4cGFuZFRleHQocHJlZml4LCBleHBhbmRlZCl9LWA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGZpbGVuYW1lcyA9IHRoaXMuam9iRGF0YVtcImNhY2hlXCJdW2luZGV4XVtcImtleVwiXVtcImZpbGVzXCJdLm1hcCgocDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXhwYW5kUCA9IFV0aWxzLmV4cGFuZFRleHQocCwgZXhwYW5kZWQpO1xuICAgICAgICAgICAgICAgIHJldHVybiBleHBhbmRQLnNwbGl0KFwiLlwiKVswXTtcbiAgICAgICAgICAgIH0pLmpvaW4oXCJfXCIpO1xuICAgICAgICAgICAgcmV0dXJuIGAke2luZGV4fV8ke2ZpbGVuYW1lc30tYDtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBrZXkgPSB0aGlzLmpvYkRhdGFbXCJjYWNoZVwiXVtjYWNoZUluZGV4XS5rZXk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBrZXkgPT09IFwic3RyaW5nXCIgfHwga2V5ID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBVdGlscy5leHBhbmRUZXh0KGtleSA/PyBcImRlZmF1bHRcIiwgZXhwYW5kZWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZmlsZXMgPSBrZXlbXCJmaWxlc1wiXS5tYXAoKGY6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgbGV0IHBhdGggPSBVdGlscy5leHBhbmRUZXh0KGYsIGV4cGFuZGVkKTtcbiAgICAgICAgICAgIGlmIChwYXRoLnN0YXJ0c1dpdGgoYCR7dGhpcy5jaVByb2plY3REaXJ9L2ApKSB7XG4gICAgICAgICAgICAgICAgcGF0aCA9IHBhdGguc2xpY2UoYCR7dGhpcy5jaVByb2plY3REaXJ9L2AubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBgJHtjd2R9LyR7cGF0aH1gO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGdldENhY2hlUHJlZml4KGNhY2hlSW5kZXgpICsgYXdhaXQgVXRpbHMuY2hlY2tzdW1GaWxlcyhjd2QsIGZpbGVzKTtcbiAgICB9XG5cbiAgICBnZXQgYmVmb3JlU2NyaXB0cyAoKTogc3RyaW5nW10ge1xuICAgICAgICBjb25zdCBiZWZvcmVTY3JpcHRzID0gdGhpcy5qb2JEYXRhW1wiYmVmb3JlX3NjcmlwdFwiXSB8fCBbXTtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBiZWZvcmVTY3JpcHRzID09PSBcInN0cmluZ1wiID8gW2JlZm9yZVNjcmlwdHNdIDogYmVmb3JlU2NyaXB0cztcbiAgICB9XG5cbiAgICBnZXQgYWZ0ZXJTY3JpcHRzICgpOiBzdHJpbmdbXSB7XG4gICAgICAgIGNvbnN0IGFmdGVyU2NyaXB0cyA9IHRoaXMuam9iRGF0YVtcImFmdGVyX3NjcmlwdFwiXSB8fCBbXTtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBhZnRlclNjcmlwdHMgPT09IFwic3RyaW5nXCIgPyBbYWZ0ZXJTY3JpcHRzXSA6IGFmdGVyU2NyaXB0cztcbiAgICB9XG5cbiAgICBnZXQgc2NyaXB0cyAoKTogc3RyaW5nW10ge1xuICAgICAgICBjb25zdCBzY3JpcHQgPSB0aGlzLmpvYkRhdGFbXCJzY3JpcHRcIl07XG4gICAgICAgIHJldHVybiB0eXBlb2Ygc2NyaXB0ID09PSBcInN0cmluZ1wiID8gW3NjcmlwdF0gOiBzY3JpcHQ7XG4gICAgfVxuXG4gICAgZ2V0IHRyaWdnZXIgKCk6IGFueSB7XG4gICAgICAgIHJldHVybiB0aGlzLmpvYkRhdGFbXCJ0cmlnZ2VyXCJdO1xuICAgIH1cblxuICAgIGFzeW5jIHN0YXJ0VHJpZ2dlclBpcGVsaW5lICgpIHtcbiAgICAgICAgdGhpcy53cml0ZVN0cmVhbXMubWVtb1N0ZG91dChjaGFsa2B7YmdZZWxsb3dCcmlnaHQgIFdBUk4gfSBkb3duc3RyZWFtIHBpcGVsaW5lIGlzIGV4cGVyaW1lbnRhbCBpbiBnaXRsYWItY2ktbG9jYWxcXG5gKTtcbiAgICAgICAgYXdhaXQgdGhpcy5mZXRjaFRyaWdnZXJJbmNsdWRlKCk7XG4gICAgICAgIGNvbnN0IHZhcmlhYmxlc0ZvckRvd25zdHJlYW1QaXBlbGluZSA9IE9iamVjdC5lbnRyaWVzKHsuLi50aGlzLmdsb2JhbFZhcmlhYmxlcywgLi4udGhpcy5qb2JEYXRhLnZhcmlhYmxlc30pLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBgJHtrZXl9PSR7dmFsdWV9YCk7XG5cbiAgICAgICAgY29uc3QgZ2NsVHJpZ2dlcmVyID0gdGhpcy5hcmd2LnZhcmlhYmxlW1wiR0NMX1RSSUdHRVJFUlwiXSA/XG4gICAgICAgICAgICBgJHt0aGlzLmFyZ3YudmFyaWFibGVbXCJHQ0xfVFJJR0dFUkVSXCJdfSAtPiAke3RoaXMubmFtZX1gIDpcbiAgICAgICAgICAgIHRoaXMubmFtZTtcbiAgICAgICAgYXdhaXQgaGFuZGxlcih7XG4gICAgICAgICAgICAuLi5PYmplY3QuZnJvbUVudHJpZXModGhpcy5hcmd2Lm1hcCksXG4gICAgICAgICAgICBmaWxlOiBgJHt0aGlzLmFyZ3Yuc3RhdGVEaXJ9L2luY2x1ZGVzL3RyaWdnZXJzLyR7dGhpcy5uYW1lfS55bWxgLFxuICAgICAgICAgICAgdmFyaWFibGU6IFtcbiAgICAgICAgICAgICAgICBjaGFsa2BHQ0xfVFJJR0dFUkVSPSR7Z2NsVHJpZ2dlcmVyfWAsXG4gICAgICAgICAgICAgICAgXCJDSV9QSVBFTElORV9TT1VSQ0U9cGFyZW50X3BpcGVsaW5lXCIsXG4gICAgICAgICAgICBdLmNvbmNhdCh2YXJpYWJsZXNGb3JEb3duc3RyZWFtUGlwZWxpbmUpLFxuICAgICAgICB9LCB0aGlzLndyaXRlU3RyZWFtcywgW10sIHRoaXMuYXJndi5jaGlsZFBpcGVsaW5lRGVwdGggKyAxKTtcbiAgICB9XG5cbiAgICBnZXQgcHJlU2NyaXB0c0V4aXRDb2RlICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ByZXNjcmlwdHNFeGl0Q29kZTtcbiAgICB9XG5cbiAgICBnZXQgYWZ0ZXJTY3JpcHRzRXhpdENvZGUgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYWZ0ZXJTY3JpcHRzRXhpdENvZGU7XG4gICAgfVxuXG4gICAgZ2V0IHN0YXJ0ZWQgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcnVubmluZyB8fCB0aGlzLl9wcmVzY3JpcHRzRXhpdENvZGUgIT09IG51bGw7XG4gICAgfVxuXG4gICAgZ2V0IGZpbmlzaGVkICgpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLl9ydW5uaW5nICYmIHRoaXMuX3ByZXNjcmlwdHNFeGl0Q29kZSAhPT0gbnVsbDtcbiAgICB9XG5cbiAgICBnZXQgY292ZXJhZ2VQZXJjZW50ICgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvdmVyYWdlUGVyY2VudDtcbiAgICB9XG5cbiAgICBnZXQgZmlsZVZhcmlhYmxlc0RpciAoKSB7XG4gICAgICAgIHJldHVybiBgL3RtcC9naXRsYWItY2ktbG9jYWwtZmlsZS12YXJpYWJsZXMtJHt0aGlzLl92YXJpYWJsZXNbXCJDSV9QUk9KRUNUX1BBVEhfU0xVR1wiXX0tJHt0aGlzLmpvYklkfWA7XG4gICAgfVxuXG4gICAgZ2V0IGdsb2JhbFZhcmlhYmxlcyAoKSB7XG4gICAgICAgIGlmICh0aGlzLmluaGVyaXQudmFyaWFibGVzID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5pbmhlcml0LnZhcmlhYmxlcykpIHtcbiAgICAgICAgICAgIGNvbnN0IGluaGVyaXRWYXJpYWJsZXMgPSB0aGlzLmluaGVyaXQudmFyaWFibGVzO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgICAgICAgICAgICBPYmplY3QuZW50cmllcyh0aGlzLl9nbG9iYWxWYXJpYWJsZXMpLmZpbHRlcigoW2tdKSA9PiBpbmhlcml0VmFyaWFibGVzLmluY2x1ZGVzKGspKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2dsb2JhbFZhcmlhYmxlcztcbiAgICB9XG5cbiAgICBhc3luYyBzdGFydCAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLnRyaWdnZXIpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuc3RhcnRUcmlnZ2VyUGlwZWxpbmUoKTtcbiAgICAgICAgICAgIHRoaXMuX3ByZXNjcmlwdHNFeGl0Q29kZSA9IDA7IC8vIE5PVEU6IHNvIHRoYXQgYHRoaXMuZmluaXNoZWRgIHdpbGwgaW1wbGljaXRseSBiZSBzZXQgdG8gdHJ1ZVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcnVubmluZyA9IHRydWU7XG5cbiAgICAgICAgY29uc3QgYXJndiA9IHRoaXMuYXJndjtcbiAgICAgICAgdGhpcy5fc3RhcnRUaW1lID0gcHJvY2Vzcy5ocnRpbWUoKTtcbiAgICAgICAgdGhpcy5fdmFyaWFibGVzW1wiQ0lfSk9CX1NUQVJURURfQVRcIl0gPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkuc3BsaXQoXCIuXCIpWzBdICsgXCJaXCI7XG4gICAgICAgIGNvbnN0IHdyaXRlU3RyZWFtcyA9IHRoaXMud3JpdGVTdHJlYW1zO1xuICAgICAgICB0aGlzLl9kb3RlbnZWYXJpYWJsZXMgPSBhd2FpdCB0aGlzLmluaXRQcm9kdWNlclJlcG9ydHNEb3RlbnZWYXJpYWJsZXMod3JpdGVTdHJlYW1zLCBVdGlscy5leHBhbmRWYXJpYWJsZXModGhpcy5fdmFyaWFibGVzKSk7XG4gICAgICAgIGNvbnN0IGV4cGFuZGVkID0gVXRpbHMudW5zY2FwZSQkVmFyaWFibGVzKFV0aWxzLmV4cGFuZFZhcmlhYmxlcyh7Li4udGhpcy5fdmFyaWFibGVzLCAuLi50aGlzLl9kb3RlbnZWYXJpYWJsZXN9KSk7XG4gICAgICAgIGNvbnN0IGltYWdlTmFtZSA9IHRoaXMuaW1hZ2VOYW1lKGV4cGFuZGVkKTtcbiAgICAgICAgY29uc3QgaGVscGVySW1hZ2VOYW1lID0gYXJndi5oZWxwZXJJbWFnZTtcbiAgICAgICAgY29uc3Qgc2FmZUpvYk5hbWUgPSB0aGlzLnNhZmVKb2JOYW1lO1xuXG4gICAgICAgIGNvbnN0IG91dHB1dExvZ0ZpbGVQYXRoID0gYCR7YXJndi5jd2R9LyR7YXJndi5zdGF0ZURpcn0vb3V0cHV0LyR7c2FmZUpvYk5hbWV9LmxvZ2A7XG4gICAgICAgIGF3YWl0IGZzLmVuc3VyZUZpbGUob3V0cHV0TG9nRmlsZVBhdGgpO1xuICAgICAgICBhd2FpdCBmcy50cnVuY2F0ZShvdXRwdXRMb2dGaWxlUGF0aCk7XG5cbiAgICAgICAgaWYgKCF0aGlzLmludGVyYWN0aXZlKSB7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7bWFnZW50YUJyaWdodCBzdGFydGluZ30gJHtpbWFnZU5hbWUgPz8gXCJzaGVsbFwifSAoe3llbGxvdyAke3RoaXMuc3RhZ2V9fSlcXG5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpbWFnZU5hbWUpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucHVsbEltYWdlKHdyaXRlU3RyZWFtcywgaW1hZ2VOYW1lKTtcblxuICAgICAgICAgICAgY29uc3QgYnVpbGRWb2x1bWVOYW1lID0gdGhpcy5idWlsZFZvbHVtZU5hbWU7XG4gICAgICAgICAgICBjb25zdCB0bXBWb2x1bWVOYW1lID0gdGhpcy50bXBWb2x1bWVOYW1lO1xuICAgICAgICAgICAgY29uc3QgZmlsZVZhcmlhYmxlc0RpciA9IHRoaXMuZmlsZVZhcmlhYmxlc0RpcjtcblxuICAgICAgICAgICAgY29uc3Qgdm9sdW1lUHJvbWlzZXMgPSBbXTtcbiAgICAgICAgICAgIHZvbHVtZVByb21pc2VzLnB1c2goVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcInZvbHVtZVwiLCBcImNyZWF0ZVwiLCBgJHtidWlsZFZvbHVtZU5hbWV9YF0sIGFyZ3YuY3dkKSk7XG4gICAgICAgICAgICB2b2x1bWVQcm9taXNlcy5wdXNoKFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJ2b2x1bWVcIiwgXCJjcmVhdGVcIiwgYCR7dG1wVm9sdW1lTmFtZX1gXSwgYXJndi5jd2QpKTtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lclZvbHVtZU5hbWVzLnB1c2goYnVpbGRWb2x1bWVOYW1lKTtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lclZvbHVtZU5hbWVzLnB1c2godG1wVm9sdW1lTmFtZSk7XG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbCh2b2x1bWVQcm9taXNlcyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHRpbWUgPSBwcm9jZXNzLmhydGltZSgpO1xuICAgICAgICAgICAgdGhpcy5yZWZyZXNoTG9uZ1J1bm5pbmdTaWxlbnRUaW1lb3V0KHdyaXRlU3RyZWFtcyk7XG5cbiAgICAgICAgICAgIGxldCBjaG93bk9wdCA9IFwiMDowXCI7XG4gICAgICAgICAgICBsZXQgY2htb2RPcHQgPSBcImErcndcIjtcbiAgICAgICAgICAgIGlmICghdGhpcy5hcmd2LnVtYXNrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qge3N0ZG91dH0gPSBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwicnVuXCIsIFwiLS1ybVwiLCBcIi0tZW50cnlwb2ludFwiLCBcInNoXCIsIGltYWdlTmFtZSwgXCItY1wiLCBcImVjaG8gXFxcIiQoaWQgLXUpOiQoaWQgLWcpXFxcIlwiXSk7XG4gICAgICAgICAgICAgICAgY2hvd25PcHQgPSBzdGRvdXQ7XG4gICAgICAgICAgICAgICAgaWYgKGNob3duT3B0ID09IFwiMDowXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2htb2RPcHQgPSBcImctd1wiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChoZWxwZXJJbWFnZU5hbWUpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnB1bGxJbWFnZSh3cml0ZVN0cmVhbXMsIGhlbHBlckltYWdlTmFtZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGhlbHBlckNvbnRhaW5lckFyZ3MgPSBbXG4gICAgICAgICAgICAgICAgdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwiY3JlYXRlXCIsIFwiLS11c2VyPTA6MFwiLFxuICAgICAgICAgICAgICAgIGAtLXZvbHVtZT0ke2J1aWxkVm9sdW1lTmFtZX06JHt0aGlzLmNpUHJvamVjdERpcn1gLFxuICAgICAgICAgICAgICAgIGAtLXZvbHVtZT0ke3RtcFZvbHVtZU5hbWV9OiR7dGhpcy5maWxlVmFyaWFibGVzRGlyfWAsXG4gICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5hcmd2LmNhRmlsZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNhRmlsZVBhdGggPSBwYXRoLmlzQWJzb2x1dGUodGhpcy5hcmd2LmNhRmlsZSkgPyB0aGlzLmFyZ3YuY2FGaWxlIDogcGF0aC5yZXNvbHZlKHRoaXMuYXJndi5jd2QsIHRoaXMuYXJndi5jYUZpbGUpO1xuICAgICAgICAgICAgICAgIGlmIChhd2FpdCBmcy5wYXRoRXhpc3RzKGNhRmlsZVBhdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGhlbHBlckNvbnRhaW5lckFyZ3MucHVzaChgLS12b2x1bWU9JHtjYUZpbGVQYXRofTovZXRjL3NzbC9jZXJ0cy9jYS1jZXJ0aWZpY2F0ZXMuY3J0OnJvYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBoZWxwZXJDb250YWluZXJBcmdzLnB1c2goYCR7aGVscGVySW1hZ2VOYW1lfWAsIFwic2hcIiwgXCItY1wiLCBgY2hvd24gJHtjaG93bk9wdH0gLVIgJHt0aGlzLmNpUHJvamVjdERpcn0gJiYgY2htb2QgJHtjaG1vZE9wdH0gLVIgJHt0aGlzLmNpUHJvamVjdERpcn0gJiYgY2hvd24gJHtjaG93bk9wdH0gLVIgL3RtcC8gJiYgY2htb2QgJHtjaG1vZE9wdH0gLVIgL3RtcC9gKTtcblxuICAgICAgICAgICAgY29uc3Qge3N0ZG91dDogY29udGFpbmVySWR9ID0gYXdhaXQgVXRpbHMuc3Bhd24oaGVscGVyQ29udGFpbmVyQXJncywgYXJndi5jd2QpO1xuICAgICAgICAgICAgdGhpcy5fY29udGFpbmVyc1RvQ2xlYW4ucHVzaChjb250YWluZXJJZCk7XG4gICAgICAgICAgICBpZiAoYXdhaXQgZnMucGF0aEV4aXN0cyhmaWxlVmFyaWFibGVzRGlyKSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJjcFwiLCBgJHtmaWxlVmFyaWFibGVzRGlyfS8uYCwgYCR7Y29udGFpbmVySWR9OiR7ZmlsZVZhcmlhYmxlc0Rpcn1gXSwgYXJndi5jd2QpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVmcmVzaExvbmdSdW5uaW5nU2lsZW50VGltZW91dCh3cml0ZVN0cmVhbXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcImNwXCIsIGAke2FyZ3Yuc3RhdGVEaXJ9L2J1aWxkcy8uZG9ja2VyLy5gLCBgJHtjb250YWluZXJJZH06JHt0aGlzLmNpUHJvamVjdERpcn1gXSwgYXJndi5jd2QpO1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcInN0YXJ0XCIsIFwiLS1hdHRhY2hcIiwgY29udGFpbmVySWRdLCBhcmd2LmN3ZCk7XG4gICAgICAgICAgICBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwicm1cIiwgXCItdmZcIiwgY29udGFpbmVySWRdLCBhcmd2LmN3ZCk7XG4gICAgICAgICAgICBjb25zdCBlbmRUaW1lID0gcHJvY2Vzcy5ocnRpbWUodGltZSk7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7bWFnZW50YUJyaWdodCBjb3BpZWQgdG8gJHt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZX0gdm9sdW1lc30gaW4ge21hZ2VudGEgJHtwcmV0dHlIcnRpbWUoZW5kVGltZSl9fVxcbmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc2VydmljZXM/Lmxlbmd0aCkge1xuICAgICAgICAgICAgLy8gYGhvc3RgIGFuZCBgbm9uZWAgbmV0d29ya3MgZG8gbm90IHdvcmsgd2l0aCBzZXJ2aWNlcyBiZWNhdXNlIGFsaWFzZXMgb25seSB3b3JrIGZvclxuICAgICAgICAgICAgLy8gdXNlciBkZWZpbmVkIG5ldHdvcmtzLlxuICAgICAgICAgICAgZm9yIChjb25zdCBuZXR3b3JrIG9mIHRoaXMuYXJndi5uZXR3b3JrKSB7XG4gICAgICAgICAgICAgICAgaWYgKFtcImhvc3RcIiwgXCJub25lXCJdLmluY2x1ZGVzKG5ldHdvcmspKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBBc3NlcnRpb25FcnJvcih7bWVzc2FnZTogYENhbm5vdCBhZGQgc2VydmljZSBuZXR3b3JrIGFsaWFzIHdpdGggbmV0d29yayBtb2RlICcke25ldHdvcmt9J2B9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlRG9ja2VyTmV0d29yayhgZ2l0bGFiLWNpLWxvY2FsLSR7dGhpcy5qb2JJZH1gKTtcblxuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICAgICAgdGhpcy5zZXJ2aWNlcy5tYXAoYXN5bmMgKHNlcnZpY2UsIHNlcnZpY2VJbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzZXJ2aWNlTmFtZSA9IHNlcnZpY2UubmFtZTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wdWxsSW1hZ2Uod3JpdGVTdHJlYW1zLCBzZXJ2aWNlTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNlcnZpY2VDb250YWluZXJJZCA9IGF3YWl0IHRoaXMuc3RhcnRTZXJ2aWNlKHdyaXRlU3RyZWFtcywgVXRpbHMuZXhwYW5kVmFyaWFibGVzKHsuLi5leHBhbmRlZCwgLi4uc2VydmljZS52YXJpYWJsZXN9KSwgc2VydmljZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNlcnZpY2VDb250YWluZXJMb2dGaWxlID0gYCR7YXJndi5jd2R9LyR7YXJndi5zdGF0ZURpcn0vc2VydmljZXMtb3V0cHV0LyR7dGhpcy5zYWZlSm9iTmFtZX0vJHtzZXJ2aWNlTmFtZX0tJHtzZXJ2aWNlSW5kZXh9LmxvZ2A7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VydmljZUhlYWx0aENoZWNrKHdyaXRlU3RyZWFtcywgc2VydmljZSwgc2VydmljZUluZGV4LCBzZXJ2aWNlQ29udGFpbmVyTG9nRmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHtzdGRvdXQsIHN0ZGVycn0gPSBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwibG9nc1wiLCBzZXJ2aWNlQ29udGFpbmVySWRdKTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgZnMuZW5zdXJlRmlsZShzZXJ2aWNlQ29udGFpbmVyTG9nRmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGZzLnByb21pc2VzLndyaXRlRmlsZShzZXJ2aWNlQ29udGFpbmVyTG9nRmlsZSwgYCMjIyBzdGRvdXQgIyMjXFxuJHtzdGRvdXR9XFxuIyMjIHN0ZGVyciAjIyNcXG4ke3N0ZGVycn1cXG5gKTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLmV4ZWNQcmVTY3JpcHRzKGV4cGFuZGVkKTtcbiAgICAgICAgaWYgKHRoaXMuX3ByZXNjcmlwdHNFeGl0Q29kZSA9PSBudWxsKSB0aHJvdyBFcnJvcihcInRoaXMuX3ByZXNjcmlwdHNFeGl0Q29kZSBtdXN0IGJlIGRlZmluZWQhXCIpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuZXhlY0FmdGVyU2NyaXB0cyhleHBhbmRlZCk7XG5cbiAgICAgICAgdGhpcy5fcnVubmluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9lbmRUaW1lID0gdGhpcy5fZW5kVGltZSA/PyBwcm9jZXNzLmhydGltZSh0aGlzLl9zdGFydFRpbWUpO1xuICAgICAgICB0aGlzLnByaW50RmluaXNoZWRTdHJpbmcoKTtcblxuICAgICAgICBhd2FpdCB0aGlzLmNvcHlDYWNoZU91dCh0aGlzLndyaXRlU3RyZWFtcywgZXhwYW5kZWQpO1xuICAgICAgICBhd2FpdCB0aGlzLmNvcHlBcnRpZmFjdHNPdXQodGhpcy53cml0ZVN0cmVhbXMsIGV4cGFuZGVkKTtcblxuICAgICAgICBpZiAodGhpcy5qb2JEYXRhW1wiY292ZXJhZ2VcIl0pIHtcbiAgICAgICAgICAgIHRoaXMuX2NvdmVyYWdlUGVyY2VudCA9IGF3YWl0IFV0aWxzLmdldENvdmVyYWdlUGVyY2VudChhcmd2LmN3ZCwgYXJndi5zdGF0ZURpciwgdGhpcy5qb2JEYXRhW1wiY292ZXJhZ2VcIl0sIHNhZmVKb2JOYW1lKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGNsZWFudXBSZXNvdXJjZXMgKCkge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5fbG9uZ1J1bm5pbmdTaWxlbnRUaW1lb3V0KTtcblxuICAgICAgICBpZiAoIXRoaXMuYXJndi5jbGVhbnVwKSByZXR1cm47XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbnRhaW5lcnNUb0NsZWFuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcInJtXCIsIFwiLXZmXCIsIC4uLnRoaXMuX2NvbnRhaW5lcnNUb0NsZWFuXSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0KGUgaW5zdGFuY2VvZiBFcnJvciwgXCJlIGlzIG5vdCBpbnN0YW5jZW9mIEVycm9yXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX3NlcnZpY2VOZXR3b3JrSWQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcIm5ldHdvcmtcIiwgXCJybVwiLCBgJHt0aGlzLl9zZXJ2aWNlTmV0d29ya0lkfWBdKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQoZSBpbnN0YW5jZW9mIEVycm9yLCBcImUgaXMgbm90IGluc3RhbmNlb2YgRXJyb3JcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fY29udGFpbmVyVm9sdW1lTmFtZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwidm9sdW1lXCIsIFwicm1cIiwgLi4udGhpcy5fY29udGFpbmVyVm9sdW1lTmFtZXNdKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQoZSBpbnN0YW5jZW9mIEVycm9yLCBcImUgaXMgbm90IGluc3RhbmNlb2YgRXJyb3JcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBybVByb21pc2VzID0gW107XG4gICAgICAgIGZvciAoY29uc3QgZmlsZSBvZiB0aGlzLl9maWxlc1RvUm0pIHtcbiAgICAgICAgICAgIHJtUHJvbWlzZXMucHVzaChmcy5ybShmaWxlLCB7cmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZX0pKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChybVByb21pc2VzKTtcblxuICAgICAgICBjb25zdCBmaWxlVmFyaWFibGVzRGlyID0gdGhpcy5maWxlVmFyaWFibGVzRGlyO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgZnMucm0oZmlsZVZhcmlhYmxlc0Rpciwge3JlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWV9KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgYXNzZXJ0KGUgaW5zdGFuY2VvZiBFcnJvciwgXCJlIGlzIG5vdCBpbnN0YW5jZW9mIEVycm9yXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZW5lcmF0ZUluamVjdFNTSEFnZW50T3B0aW9ucyAoKSB7XG4gICAgICAgIGlmICghdGhpcy5pbmplY3RTU0hBZ2VudCkge1xuICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09IFwiZGFyd2luXCIgfHwgL15kYXJ3aW4vLmV4ZWMocHJvY2Vzcy5lbnYuT1NUWVBFID8/IFwiXCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gXCItLWVudiBTU0hfQVVUSF9TT0NLPS9ydW4vaG9zdC1zZXJ2aWNlcy9zc2gtYXV0aC5zb2NrIC12IC9ydW4vaG9zdC1zZXJ2aWNlcy9zc2gtYXV0aC5zb2NrOi9ydW4vaG9zdC1zZXJ2aWNlcy9zc2gtYXV0aC5zb2NrXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGAtLWVudiBTU0hfQVVUSF9TT0NLPSR7cHJvY2Vzcy5lbnYuU1NIX0FVVEhfU09DS30gLXYgJHtwcm9jZXNzLmVudi5TU0hfQVVUSF9TT0NLfToke3Byb2Nlc3MuZW52LlNTSF9BVVRIX1NPQ0t9YDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdlbmVyYXRlU2NyaXB0Q29tbWFuZHMgKHNjcmlwdHM6IHN0cmluZ1tdKSB7XG4gICAgICAgIGxldCBjbWQgPSBcIlwiO1xuICAgICAgICBzY3JpcHRzLmZvckVhY2goKHNjcmlwdCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3BsaXQgPSBzY3JpcHQuc3BsaXQoL1xccj9cXG4vKTtcbiAgICAgICAgICAgIGNvbnN0IG11bHRpbGluZVRleHQgPSBzcGxpdC5sZW5ndGggPiAxID8gXCIgIyBjb2xsYXBzZWQgbXVsdGktbGluZSBjb21tYW5kXCIgOiBcIlwiO1xuICAgICAgICAgICAgY29uc3QgdGV4dCA9IHNwbGl0WzBdPy5yZXBsYWNlKC9cXFxcL2csIFwiXFxcXFxcXFxcIikucmVwbGFjZSgvXCIvZywgXCJcXFxcXFxcIlwiKS5yZXBsYWNlKC9bJF0vZywgXCJcXFxcJFwiKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmludGVyYWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgY21kICs9IGNoYWxrYGVjaG8gXCJ7Z3JlZW4gJCAke3RleHR9JHttdWx0aWxpbmVUZXh0fX1cIlxcbmA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFByaW50IGNvbW1hbmQgZWNobydlZCB3aXRoICRHQ0xfU0hFTExfUFJPTVBUX1BMQUNFSE9MREVSXG4gICAgICAgICAgICAgICAgY21kICs9IGBlY2hvIFwiJHtHQ0xfU0hFTExfUFJPTVBUX1BMQUNFSE9MREVSfSAke3RleHR9JHttdWx0aWxpbmVUZXh0fVwiXFxuYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgYWN0dWFsIHNjcmlwdFxuICAgICAgICAgICAgY21kICs9IGAke3NjcmlwdH1cXG5gO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNtZDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIG1vdW50Q2FjaGVDbWQgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30pIHtcbiAgICAgICAgaWYgKHRoaXMuaW1hZ2VOYW1lKGV4cGFuZGVkKSAmJiAhdGhpcy5hcmd2Lm1vdW50Q2FjaGUpIHJldHVybiBbXTtcblxuICAgICAgICBjb25zdCBjbWQ6IHN0cmluZ1tdID0gW107XG4gICAgICAgIGZvciAoY29uc3QgW2luZGV4LCBjXSBvZiB0aGlzLmNhY2hlLmVudHJpZXMoKSkge1xuICAgICAgICAgICAgY29uc3QgdW5pcXVlQ2FjaGVOYW1lID0gYXdhaXQgdGhpcy5nZXRVbmlxdWVDYWNoZU5hbWUodGhpcy5hcmd2LmN3ZCwgZXhwYW5kZWQsIGluZGV4KTtcbiAgICAgICAgICAgIGMucGF0aHMuZm9yRWFjaCgocCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhdGggPSBVdGlscy5leHBhbmRUZXh0KHAsIGV4cGFuZGVkKTtcbiAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7bWFnZW50YUJyaWdodCBtb3VudGluZyBjYWNoZX0gZm9yIHBhdGggJHtwYXRofVxcbmApO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNhY2hlTW91bnQgPSBVdGlscy5zYWZlRG9ja2VyU3RyaW5nKGBnY2wtJHtleHBhbmRlZC5DSV9QUk9KRUNUX1BBVEhfU0xVR30tJHt1bmlxdWVDYWNoZU5hbWV9YCk7XG4gICAgICAgICAgICAgICAgY21kLnB1c2goXCItdlwiLCBgJHtjYWNoZU1vdW50fToke3RoaXMuY2lQcm9qZWN0RGlyfS8ke3BhdGh9YCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY21kO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZXhlY1ByZVNjcmlwdHMgKGV4cGFuZGVkOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBwcmVzY3JpcHRzID0gdGhpcy5iZWZvcmVTY3JpcHRzLmNvbmNhdCh0aGlzLnNjcmlwdHMpO1xuICAgICAgICBleHBhbmRlZFtcIkNJX0pPQl9TVEFUVVNcIl0gPSBcInJ1bm5pbmdcIjtcblxuICAgICAgICB0aGlzLl9wcmVzY3JpcHRzRXhpdENvZGUgPSBhd2FpdCB0aGlzLmV4ZWNTY3JpcHRzKHByZXNjcmlwdHMsIGV4cGFuZGVkLCBcIlwiKTtcbiAgICAgICAgZXhwYW5kZWRbXCJDSV9KT0JfU1RBVFVTXCJdID0gdGhpcy5fcHJlc2NyaXB0c0V4aXRDb2RlID09PSAwID8gXCJzdWNjZXNzXCIgOiBcImZhaWxlZFwiO1xuXG4gICAgICAgIHRoaXMucHJpbnRFeGl0ZWRTdHJpbmcodGhpcy5fcHJlc2NyaXB0c0V4aXRDb2RlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGV4ZWNBZnRlclNjcmlwdHMgKGV4cGFuZGVkOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBtZXNzYWdlID0gXCJSdW5uaW5nIGFmdGVyIHNjcmlwdC4uLlwiO1xuICAgICAgICB0aGlzLl9hZnRlclNjcmlwdHNFeGl0Q29kZSA9IGF3YWl0IHRoaXMuZXhlY1NjcmlwdHModGhpcy5hZnRlclNjcmlwdHMsIGV4cGFuZGVkLCBtZXNzYWdlKTtcblxuICAgICAgICB0aGlzLnByaW50QWZ0ZXJTY3JpcHRFeGl0ZWRTdHJpbmcodGhpcy5fYWZ0ZXJTY3JpcHRzRXhpdENvZGUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZXhlY1NjcmlwdHMgKHNjcmlwdHM6IHN0cmluZ1tdLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30sIG1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgICAgIGNvbnN0IGN3ZCA9IHRoaXMuYXJndi5jd2Q7XG4gICAgICAgIGNvbnN0IHN0YXRlRGlyID0gdGhpcy5hcmd2LnN0YXRlRGlyO1xuICAgICAgICBjb25zdCBzYWZlSm9iTmFtZSA9IHRoaXMuc2FmZUpvYk5hbWU7XG4gICAgICAgIGNvbnN0IG91dHB1dEZpbGVzUGF0aCA9IGAke2N3ZH0vJHtzdGF0ZURpcn0vb3V0cHV0LyR7c2FmZUpvYk5hbWV9LmxvZ2A7XG4gICAgICAgIGNvbnN0IGJ1aWxkVm9sdW1lTmFtZSA9IHRoaXMuYnVpbGRWb2x1bWVOYW1lO1xuICAgICAgICBjb25zdCB0bXBWb2x1bWVOYW1lID0gdGhpcy50bXBWb2x1bWVOYW1lO1xuICAgICAgICBjb25zdCBpbWFnZU5hbWUgPSB0aGlzLmltYWdlTmFtZShleHBhbmRlZCk7XG4gICAgICAgIGNvbnN0IHdyaXRlU3RyZWFtcyA9IHRoaXMud3JpdGVTdHJlYW1zO1xuXG4gICAgICAgIGlmIChzY3JpcHRzLmxlbmd0aCA9PT0gMCB8fCBzY3JpcHRzWzBdID09IG51bGwpIHJldHVybiAwO1xuXG4gICAgICAgIGlmIChtZXNzYWdlLmxlbmd0aCA+IDApIHdyaXRlU3RyZWFtcy5zdGRvdXQoY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IHttYWdlbnRhQnJpZ2h0ICR7bWVzc2FnZX19XFxuYCk7XG5cbiAgICAgICAgYXdhaXQgZnMucmVtb3ZlKGAke2N3ZH0vJHtzdGF0ZURpcn0vYXJ0aWZhY3RzLyR7c2FmZUpvYk5hbWV9YCk7XG5cbiAgICAgICAgLy8gQ29weSBnaXQgdHJhY2tlZCBmaWxlcyB0byBidWlsZCBmb2xkZXIgaWYgc2hlbGwgaXNvbGF0aW9uIGVuYWJsZWQuXG4gICAgICAgIGlmICghaW1hZ2VOYW1lICYmIHRoaXMuYXJndi5zaGVsbElzb2xhdGlvbikge1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMucnN5bmNUcmFja2VkRmlsZXMoY3dkLCBzdGF0ZURpciwgYCR7c2FmZUpvYk5hbWV9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5pbnRlcmFjdGl2ZSkge1xuICAgICAgICAgICAgbGV0IGlDbWQgPSBcInNldCAtZW8gcGlwZWZhaWxcXG5cIjtcbiAgICAgICAgICAgIGlDbWQgKz0gdGhpcy5nZW5lcmF0ZVNjcmlwdENvbW1hbmRzKHNjcmlwdHMpO1xuXG4gICAgICAgICAgICBjb25zdCBpbnRlcmFjdGl2ZUNwID0gZXhlY2EoaUNtZCwge1xuICAgICAgICAgICAgICAgIGN3ZCxcbiAgICAgICAgICAgICAgICBzaGVsbDogXCJiYXNoXCIsXG4gICAgICAgICAgICAgICAgc3RkaW86IFtcImluaGVyaXRcIiwgXCJpbmhlcml0XCIsIFwiaW5oZXJpdFwiXSxcbiAgICAgICAgICAgICAgICBlbnY6IHsuLi5leHBhbmRlZCwgLi4ucHJvY2Vzcy5lbnZ9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8bnVtYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgdm9pZCBpbnRlcmFjdGl2ZUNwLm9uKFwiZXhpdFwiLCAoY29kZSkgPT4gcmVzb2x2ZShjb2RlID8/IDApKTtcbiAgICAgICAgICAgICAgICB2b2lkIGludGVyYWN0aXZlQ3Aub24oXCJlcnJvclwiLCAoZXJyKSA9PiByZWplY3QoZXJyKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmFyZ3YucmVnaXN0cnkpIHtcbiAgICAgICAgICAgIGV4cGFuZGVkW1wiQ0lfUkVHSVNUUllfVVNFUlwiXSA9IGV4cGFuZGVkW1wiQ0lfUkVHSVNUUllfVVNFUlwiXSA/PyBgJHtVdGlscy5nY2xSZWdpc3RyeVByZWZpeH0udXNlcmA7XG4gICAgICAgICAgICBleHBhbmRlZFtcIkNJX1JFR0lTVFJZX1BBU1NXT1JEXCJdID0gZXhwYW5kZWRbXCJDSV9SRUdJU1RSWV9QQVNTV09SRFwiXSA/PyBgJHtVdGlscy5nY2xSZWdpc3RyeVByZWZpeH0ucGFzc3dvcmRgO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yZWZyZXNoTG9uZ1J1bm5pbmdTaWxlbnRUaW1lb3V0KHdyaXRlU3RyZWFtcyk7XG5cbiAgICAgICAgaWYgKGltYWdlTmFtZSAmJiAhdGhpcy5fY29udGFpbmVySWQpIHtcbiAgICAgICAgICAgIGxldCBkb2NrZXJDbWQgPSBgJHt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZX0gY3JlYXRlIC0taW50ZXJhY3RpdmUgJHt0aGlzLmdlbmVyYXRlSW5qZWN0U1NIQWdlbnRPcHRpb25zKCl9IGA7XG4gICAgICAgICAgICBpZiAodGhpcy5hcmd2LnByaXZpbGVnZWQpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCItLXByaXZpbGVnZWQgXCI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAoY29uc3QgZGV2aWNlIG9mIHRoaXMuYXJndi5kZXZpY2UpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tZGV2aWNlICR7ZGV2aWNlfSBgO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5hcmd2LnVsaW1pdCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS11bGltaXQgbm9maWxlPSR7dGhpcy5hcmd2LnVsaW1pdH0gYDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuYXJndi51bWFzaykge1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBcIi0tdXNlciAwOjAgXCI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmFyZ3YudXNlcm5zICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS11c2VybnM9JHt0aGlzLmFyZ3YudXNlcm5zfSBgO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5hcmd2LmNvbnRhaW5lck1hY0FkZHJlc3MpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tbWFjLWFkZHJlc3MgXCIke3RoaXMuYXJndi5jb250YWluZXJNYWNBZGRyZXNzfVwiIGA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGltYWdlVXNlciA9IHRoaXMuaW1hZ2VVc2VyKGV4cGFuZGVkKTtcbiAgICAgICAgICAgIGlmIChpbWFnZVVzZXIpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdXNlciAke2ltYWdlVXNlcn0gYDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuYXJndi5jb250YWluZXJFbXVsYXRlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcnVubmVyTmFtZTogc3RyaW5nID0gdGhpcy5hcmd2LmNvbnRhaW5lckVtdWxhdGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIUdpdGxhYlJ1bm5lclByZXNldFZhbHVlcy5pbmNsdWRlcyhydW5uZXJOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIGdpdGxhYiBydW5uZXIgdG8gZW11bGF0ZS5cIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgbWVtb3J5Q29uZmlnID0gR2l0bGFiUnVubmVyTWVtb3J5UHJlc2V0VmFsdWVbcnVubmVyTmFtZV07XG4gICAgICAgICAgICAgICAgY29uc3QgY3B1Q29uZmlnID0gR2l0bGFiUnVubmVyQ1BVc1ByZXNldFZhbHVlW3J1bm5lck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLW1lbW9yeT0ke21lbW9yeUNvbmZpZ31tIGA7XG4gICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLWtlcm5lbC1tZW1vcnk9JHttZW1vcnlDb25maWd9bSBgO1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS1jcHVzPSR7Y3B1Q29uZmlnfSBgO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBob3N0IGFuZCBub25lIG5ldHdvcmtzIGhhdmUgdG8gYmUgc3BlY2lmaWVkIHVzaW5nIC0tbmV0d29yaywgc2luY2UgdGhleSBjYW5ub3QgYmUgdXNlZCB3aXRoXG4gICAgICAgICAgICAvLyBgZG9ja2VyIG5ldHdvcmsgY29ubmVjdGAuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5ldHdvcmsgb2YgdGhpcy5hcmd2Lm5ldHdvcmspIHtcbiAgICAgICAgICAgICAgICBpZiAoW1wiaG9zdFwiLCBcIm5vbmVcIl0uaW5jbHVkZXMobmV0d29yaykpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLW5ldHdvcmsgJHtuZXR3b3JrfSBgO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFRoZSBkZWZhdWx0IHBvZG1hbiBuZXR3b3JrIG1vZGUgaXMgbm90IGBicmlkZ2VgLCB3aGljaCBtZWFucyBhIGBwb2RtYW4gbmV0d29yayBjb25uZWN0YCBjYWxsIHdpbGwgZmFpbFxuICAgICAgICAgICAgLy8gd2hlbiBjb25uZWN0aW5nIHVzZXIgZGVmaW5lZCBuZXR3b3Jrcy4gVGhlIHdvcmthcm91bmQgaXMgdG8gdXNlIGEgdXNlciBkZWZpbmVkIG5ldHdvcmsgb24gY29udGFpbmVyXG4gICAgICAgICAgICAvLyBjcmVhdGlvbi5cbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2NvbnRhaW5lcnMvcG9kbWFuL2lzc3Vlcy8xOTU3N1xuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIFRoaXMgc2hvdWxkIG5vdCBjbGFzaCB3aXRoIHRoZSBgaG9zdGAgYW5kIGBub25lYCBuZXR3b3JrcyBhYm92ZSwgc2luY2Ugc2VydmljZSBjcmVhdGlvbiBzaG91bGQgaGF2ZVxuICAgICAgICAgICAgLy8gZmFpbGVkIHdoZW4gdXNpbmcgYGhvc3RgIG9yIGBub25lYCBuZXR3b3Jrcy5cbiAgICAgICAgICAgIGlmICh0aGlzLl9zZXJ2aWNlTmV0d29ya0lkKSB7XG4gICAgICAgICAgICAgICAgLy8gYGJ1aWxkYCBhbGlhczogaHR0cHM6Ly9naXRsYWIuY29tL2dpdGxhYi1vcmcvZ2l0bGFiLXJ1bm5lci8tL2lzc3Vlcy8yNzA2MFxuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS1uZXR3b3JrICR7dGhpcy5fc2VydmljZU5ldHdvcmtJZH0gLS1uZXR3b3JrLWFsaWFzIGJ1aWxkIGA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmFyZ3YucmVnaXN0cnkpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tbmV0d29yayAke1V0aWxzLmdjbFJlZ2lzdHJ5UHJlZml4fS5uZXQgYDtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7VXRpbHMuZ2NsUmVnaXN0cnlQcmVmaXh9LmNlcnRzOi9ldGMvY29udGFpbmVycy9jZXJ0cy5kOnJvIGA7XG4gICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLXZvbHVtZSAke1V0aWxzLmdjbFJlZ2lzdHJ5UHJlZml4fS5jZXJ0czovZXRjL2RvY2tlci9jZXJ0cy5kOnJvIGA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS12b2x1bWUgJHtidWlsZFZvbHVtZU5hbWV9OiR7dGhpcy5jaVByb2plY3REaXJ9IGA7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7dG1wVm9sdW1lTmFtZX06JHt0aGlzLmZpbGVWYXJpYWJsZXNEaXJ9IGA7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0td29ya2RpciAke3RoaXMuY2lQcm9qZWN0RGlyfSBgO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHZvbHVtZSBvZiB0aGlzLmFyZ3Yudm9sdW1lKSB7XG4gICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLXZvbHVtZSAke3ZvbHVtZX0gYDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChjb25zdCBleHRyYUhvc3Qgb2YgdGhpcy5hcmd2LmV4dHJhSG9zdCkge1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgLS1hZGQtaG9zdD0ke2V4dHJhSG9zdH0gYDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuYXJndi5jYUZpbGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjYUZpbGVQYXRoID0gcGF0aC5pc0Fic29sdXRlKHRoaXMuYXJndi5jYUZpbGUpID8gdGhpcy5hcmd2LmNhRmlsZSA6IHBhdGgucmVzb2x2ZSh0aGlzLmFyZ3YuY3dkLCB0aGlzLmFyZ3YuY2FGaWxlKTtcbiAgICAgICAgICAgICAgICBpZiAoYXdhaXQgZnMucGF0aEV4aXN0cyhjYUZpbGVQYXRoKSkge1xuICAgICAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7Y2FGaWxlUGF0aH06L2V0Yy9zc2wvY2VydHMvY2EtY2VydGlmaWNhdGVzLmNydDpybyBgO1xuICAgICAgICAgICAgICAgICAgICBleHBhbmRlZFtcIlNTTF9DRVJUX0ZJTEVcIl0gPSBcIi9ldGMvc3NsL2NlcnRzL2NhLWNlcnRpZmljYXRlcy5jcnRcIjtcbiAgICAgICAgICAgICAgICAgICAgZXhwYW5kZWRbXCJTU0xfQ0VSVF9ESVJcIl0gPSBcIi9ldGMvc3NsL2NlcnRzXCI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZGVycihjaGFsa2B7eWVsbG93IFdBUk5JTkc6IENBIGZpbGUgbm90IGZvdW5kOiAke2NhRmlsZVBhdGh9fVxcbmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWxdIG9mIE9iamVjdC5lbnRyaWVzKGV4cGFuZGVkKSkge1xuICAgICAgICAgICAgICAgIC8vIFJlcGxhY2luZyBgJ2Agd2l0aCBgJ1xcJydgIHRvIGNvcnJlY3RseSBoYW5kbGUgc2luZ2xlIHF1b3RlcyhpZiBgdmFsYCBjb250YWlucyBgJ2ApIGluIHNoZWxsIGNvbW1hbmRzXG4gICAgICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAgIC1lICcke2tleX09JHt2YWwudG9TdHJpbmcoKS5yZXBsYWNlKC8nL2csIFwiJ1xcXFwnJ1wiKX0nIFxcXFxcXG5gO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5pbWFnZUVudHJ5cG9pbnQpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tZW50cnlwb2ludCAke1V0aWxzLnNhZmVCYXNoU3RyaW5nKHRoaXMuaW1hZ2VFbnRyeXBvaW50WzBdKX0gYDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAkeyhhd2FpdCB0aGlzLm1vdW50Q2FjaGVDbWQod3JpdGVTdHJlYW1zLCBleHBhbmRlZCkpLmpvaW4oXCIgXCIpfSBgO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAke2ltYWdlTmFtZX0gYDtcblxuICAgICAgICAgICAgaWYgKHRoaXMuaW1hZ2VFbnRyeXBvaW50Py5sZW5ndGggPz8gMCA+IDEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmltYWdlRW50cnlwb2ludD8uc2xpY2UoMSkuZm9yRWFjaCgoZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYCR7VXRpbHMuc2FmZUJhc2hTdHJpbmcoZSl9IGA7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcInNoIC1jIFxcXCJcXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcImlmIFsgLXggL3Vzci9sb2NhbC9iaW4vYmFzaCBdOyB0aGVuXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJcXHRleGVjIC91c3IvbG9jYWwvYmluL2Jhc2ggXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJlbGlmIFsgLXggL3Vzci9iaW4vYmFzaCBdOyB0aGVuXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJcXHRleGVjIC91c3IvYmluL2Jhc2ggXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJlbGlmIFsgLXggL2Jpbi9iYXNoIF07IHRoZW5cXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcIlxcdGV4ZWMgL2Jpbi9iYXNoIFxcblwiO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiZWxpZiBbIC14IC91c3IvbG9jYWwvYmluL3NoIF07IHRoZW5cXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcIlxcdGV4ZWMgL3Vzci9sb2NhbC9iaW4vc2ggXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJlbGlmIFsgLXggL3Vzci9iaW4vc2ggXTsgdGhlblxcblwiO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiXFx0ZXhlYyAvdXNyL2Jpbi9zaCBcXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcImVsaWYgWyAteCAvYmluL3NoIF07IHRoZW5cXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcIlxcdGV4ZWMgL2Jpbi9zaCBcXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcImVsaWYgWyAteCAvYnVzeWJveC9zaCBdOyB0aGVuXFxuXCI7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCJcXHRleGVjIC9idXN5Ym94L3NoIFxcblwiO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiZWxzZVxcblwiO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiXFx0ZWNobyBzaGVsbCBub3QgZm91bmRcXG5cIjtcbiAgICAgICAgICAgIGRvY2tlckNtZCArPSBcIlxcdGV4aXQgMVxcblwiO1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiZmlcXG5cXFwiXCI7XG5cbiAgICAgICAgICAgIGNvbnN0IHtzdGRvdXQ6IGNvbnRhaW5lcklkfSA9IGF3YWl0IFV0aWxzLmJhc2goZG9ja2VyQ21kLCBjd2QpO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5ldHdvcmsgb2YgdGhpcy5hcmd2Lm5ldHdvcmspIHtcbiAgICAgICAgICAgICAgICAvLyBTcGVjaWFsIG5ldHdvcmsgbmFtZXMgdGhhdCBkbyBub3Qgd29yayB3aXRoIGBkb2NrZXIgbmV0d29yayBjb25uZWN0YFxuICAgICAgICAgICAgICAgIGlmIChbXCJob3N0XCIsIFwibm9uZVwiXS5pbmNsdWRlcyhuZXR3b3JrKSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcIm5ldHdvcmtcIiwgXCJjb25uZWN0XCIsIG5ldHdvcmssIGAke2NvbnRhaW5lcklkfWBdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fY29udGFpbmVySWQgPSBjb250YWluZXJJZDtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lcnNUb0NsZWFuLnB1c2godGhpcy5fY29udGFpbmVySWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5jb3B5Q2FjaGVJbih3cml0ZVN0cmVhbXMsIGV4cGFuZGVkKTtcbiAgICAgICAgYXdhaXQgdGhpcy5jb3B5QXJ0aWZhY3RzSW4od3JpdGVTdHJlYW1zKTtcblxuICAgICAgICBsZXQgY21kID0gXCJzZXQgLWVvIHBpcGVmYWlsXFxuXCI7XG4gICAgICAgIGNtZCArPSBcImV4ZWMgMDwgL2Rldi9udWxsXFxuXCI7XG5cbiAgICAgICAgaWYgKCFpbWFnZU5hbWUgJiYgdGhpcy5hcmd2LnNoZWxsSXNvbGF0aW9uKSB7XG4gICAgICAgICAgICBjbWQgKz0gYGNkICR7c3RhdGVEaXJ9L2J1aWxkcy8ke3NhZmVKb2JOYW1lfS9cXG5gO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGltYWdlTmFtZSkge1xuICAgICAgICAgICAgY21kICs9IGBjZCAke3RoaXMuY2lQcm9qZWN0RGlyfSBcXG5gO1xuXG4gICAgICAgICAgICBpZiAoZXhwYW5kZWRbXCJDSV9KT0JfU1RBVFVTXCJdICE9IFwicnVubmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgLy8gRW5zdXJlcyB0aGUgZW52IGBDSV9KT0JfU1RBVFVTYCBpcyBwYXNzZWQgdG8gdGhlIGFmdGVyX3NjcmlwdCBjb250ZXh0XG4gICAgICAgICAgICAgICAgY21kICs9IGBleHBvcnQgQ0lfSk9CX1NUQVRVUz0ke2V4cGFuZGVkW1wiQ0lfSk9CX1NUQVRVU1wiXX1cXG5gO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNtZCArPSB0aGlzLmdlbmVyYXRlU2NyaXB0Q29tbWFuZHMoc2NyaXB0cyk7XG5cbiAgICAgICAgY21kICs9IFwiZXhpdCAwXFxuXCI7XG5cbiAgICAgICAgY29uc3Qgam9iU2NyaXB0RmlsZSA9IGAke2N3ZH0vJHtzdGF0ZURpcn0vc2NyaXB0cy8ke3NhZmVKb2JOYW1lfV8ke3RoaXMuam9iSWR9YDtcbiAgICAgICAgYXdhaXQgZnMub3V0cHV0RmlsZShqb2JTY3JpcHRGaWxlLCBjbWQsIFwidXRmLThcIik7XG4gICAgICAgIGF3YWl0IGZzLmNobW9kKGpvYlNjcmlwdEZpbGUsIFwiMDc1NVwiKTtcbiAgICAgICAgdGhpcy5fZmlsZXNUb1JtLnB1c2goam9iU2NyaXB0RmlsZSk7XG5cbiAgICAgICAgaWYgKGltYWdlTmFtZSkge1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcImNwXCIsIGAke3N0YXRlRGlyfS9zY3JpcHRzLyR7c2FmZUpvYk5hbWV9XyR7dGhpcy5qb2JJZH1gLCBgJHt0aGlzLl9jb250YWluZXJJZH06L2djbC1jbWRgXSwgY3dkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNwID0gZXhlY2EodGhpcy5fY29udGFpbmVySWQgPyBgJHt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZX0gc3RhcnQgLS1hdHRhY2ggLWkgJHt0aGlzLl9jb250YWluZXJJZH1gIDogXCJiYXNoXCIsIHtcbiAgICAgICAgICAgIGN3ZCxcbiAgICAgICAgICAgIHNoZWxsOiBcImJhc2hcIixcbiAgICAgICAgICAgIGVudjogaW1hZ2VOYW1lID8gcHJvY2Vzcy5lbnYgOiBleHBhbmRlZCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnRyb2wtcmVnZXhcbiAgICAgICAgY29uc3Qgc2VjdGlvblJlZ2V4ID0gL1xceDFiXFxbMEtzZWN0aW9uXyhzdGFydHxlbmQpOihcXGQrKTooW15cXHNbXSspKD86XFxbW15cXF1dKlxcXSk/XFxyXFx4MWJcXFswSy87XG4gICAgICAgIGNvbnN0IHNlY3Rpb25TdGFydFRpbWVzID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcblxuICAgICAgICBjb25zdCBvdXRGdW5jID0gKGxpbmU6IHN0cmluZywgc3RyZWFtOiAodHh0OiBzdHJpbmcpID0+IHZvaWQsIGNvbG9yaXplOiAoc3RyOiBzdHJpbmcpID0+IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZWZyZXNoTG9uZ1J1bm5pbmdTaWxlbnRUaW1lb3V0KHdyaXRlU3RyZWFtcyk7XG5cbiAgICAgICAgICAgIGNvbnN0IG0gPSBzZWN0aW9uUmVnZXguZXhlYyhsaW5lKTtcbiAgICAgICAgICAgIGxldCBpc1NlY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChtKSB7XG4gICAgICAgICAgICAgICAgaXNTZWN0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAobVsxXSA9PT0gXCJzdGFydFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb25TdGFydFRpbWVzLnNldChtWzNdLCBEYXRlLm5vdygpKTtcbiAgICAgICAgICAgICAgICAgICAgbGluZSA9IGNoYWxrYHtjeWFuQnJpZ2h0ICR7bVszXX1fc3RhcnRlZH1gO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVsYXBzZWQgPSBEYXRlLm5vdygpIC0gKHNlY3Rpb25TdGFydFRpbWVzLmdldChtWzNdKSA/PyBEYXRlLm5vdygpKTtcbiAgICAgICAgICAgICAgICAgICAgbGluZSA9IGNoYWxrYHtjeWFuQnJpZ2h0ICR7bVszXX19IHRvb2sge21hZ2VudGEgJHtlbGFwc2VkfW1zfWA7XG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb25TdGFydFRpbWVzLmRlbGV0ZShtWzNdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN0cmVhbShgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IGApO1xuICAgICAgICAgICAgaWYgKGxpbmUuc3RhcnRzV2l0aChHQ0xfU0hFTExfUFJPTVBUX1BMQUNFSE9MREVSKSkge1xuICAgICAgICAgICAgICAgIC8vIHJlcGxhY2UgdGhlIEdDTF9TSEVMTF9QUk9NUFRfUExBQ0VIT0xERVIgd2l0aCBgJGAgYW5kIG1ha2UgdGhlIFNIRUxMX1BST01QVCBsaW5lIGdyZWVuIGNvbG9yXG4gICAgICAgICAgICAgICAgbGluZSA9IGxpbmUuc2xpY2UoR0NMX1NIRUxMX1BST01QVF9QTEFDRUhPTERFUi5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIGxpbmUgPSBjaGFsa2B7Z3JlZW4gJCR7bGluZX19YDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzU2VjdGlvbikge1xuICAgICAgICAgICAgICAgIHN0cmVhbShgJHtjb2xvcml6ZShcIj5cIil9IGApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3RyZWFtKGAke2xpbmV9XFxuYCk7XG4gICAgICAgICAgICBmcy5hcHBlbmRGaWxlU3luYyhvdXRwdXRGaWxlc1BhdGgsIGAke2xpbmV9XFxuYCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgcXVpZXQgPSB0aGlzLmFyZ3YucXVpZXQ7XG5cbiAgICAgICAgcmV0dXJuIGF3YWl0IG5ldyBQcm9taXNlPG51bWJlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFxdWlldCkge1xuICAgICAgICAgICAgICAgIGNwLnN0ZG91dD8ucGlwZShzcGxpdDIoKSkub24oXCJkYXRhXCIsIChlOiBzdHJpbmcpID0+IG91dEZ1bmMoZSwgd3JpdGVTdHJlYW1zLnN0ZG91dC5iaW5kKHdyaXRlU3RyZWFtcyksIChzKSA9PiBjaGFsa2B7Z3JlZW5CcmlnaHQgJHtzfX1gKSk7XG4gICAgICAgICAgICAgICAgY3Auc3RkZXJyPy5waXBlKHNwbGl0MigpKS5vbihcImRhdGFcIiwgKGU6IHN0cmluZykgPT4gb3V0RnVuYyhlLCB3cml0ZVN0cmVhbXMuc3RkZXJyLmJpbmQod3JpdGVTdHJlYW1zKSwgKHMpID0+IGNoYWxrYHtyZWRCcmlnaHQgJHtzfX1gKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2b2lkIGNwLm9uKFwiZXhpdFwiLCAoY29kZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl9sb25nUnVubmluZ1NpbGVudFRpbWVvdXQpO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKGNvZGUgPz8gMCk7fSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB2b2lkIGNwLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl9sb25nUnVubmluZ1NpbGVudFRpbWVvdXQpO1xuICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoaW1hZ2VOYW1lKSB7XG4gICAgICAgICAgICAgICAgY3Auc3RkaW4/LmVuZChcIi4gL2djbC1jbWRcIik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNwLnN0ZGluPy5lbmQoYC4vJHtzdGF0ZURpcn0vc2NyaXB0cy8ke3NhZmVKb2JOYW1lfV8ke3RoaXMuam9iSWR9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW1hZ2VOYW1lICh2YXJzOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSA9IHt9KTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIGlmICh0aGlzLmFyZ3YuZm9yY2VTaGVsbEV4ZWN1dG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuam9iRGF0YVtcImltYWdlXCJdO1xuICAgICAgICBpZiAoIWltYWdlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hcmd2LnNoZWxsRXhlY3V0b3JOb0ltYWdlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vZG9jcy5naXRsYWIuY29tL2VlL2NpL3J1bm5lcnMvaG9zdGVkX3J1bm5lcnMvbGludXguaHRtbCNjb250YWluZXItaW1hZ2VzXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYXJndi5kZWZhdWx0SW1hZ2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZXhwYW5kZWQgPSBVdGlscy5leHBhbmRWYXJpYWJsZXModmFycyk7XG4gICAgICAgIGNvbnN0IGltYWdlTmFtZSA9IFV0aWxzLmV4cGFuZFRleHQoaW1hZ2UubmFtZSwgZXhwYW5kZWQpO1xuICAgICAgICByZXR1cm4gaW1hZ2VOYW1lLmluY2x1ZGVzKFwiOlwiKSA/IGltYWdlTmFtZSA6IGAke2ltYWdlTmFtZX06bGF0ZXN0YDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGltYWdlVXNlciAodmFyczoge1trZXk6IHN0cmluZ106IHN0cmluZ30gPSB7fSk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuam9iRGF0YVtcImltYWdlXCJdO1xuICAgICAgICBpZiAoIWltYWdlKSByZXR1cm4gbnVsbDtcbiAgICAgICAgaWYgKCFpbWFnZVtcImRvY2tlclwiXSkgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiBVdGlscy5leHBhbmRUZXh0KGltYWdlW1wiZG9ja2VyXCJdW1widXNlclwiXSwgdmFycyk7XG4gICAgfVxuXG4gICAgZ2V0IGltYWdlRW50cnlwb2ludCAoKTogc3RyaW5nW10gfCBudWxsIHtcbiAgICAgICAgY29uc3QgaW1hZ2UgPSB0aGlzLmpvYkRhdGFbXCJpbWFnZVwiXTtcblxuICAgICAgICBpZiAoIWltYWdlPy5lbnRyeXBvaW50KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBhc3NlcnQoQXJyYXkuaXNBcnJheShpbWFnZS5lbnRyeXBvaW50KSwgXCJpbWFnZTplbnRyeXBvaW50IG11c3QgYmUgYW4gYXJyYXlcIik7XG4gICAgICAgIHJldHVybiBpbWFnZS5lbnRyeXBvaW50O1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgdmFsaWRhdGVDaURlcGVuZGVuY3lQcm94eVNlcnZlckF1dGhlbnRpY2F0aW9uIChpbWFnZU5hbWU6IHN0cmluZykge1xuICAgICAgICBjb25zdCBDSV9ERVBFTkRFTkNZX1BST1hZX1NFUlZFUiA9IHRoaXMuX3ZhcmlhYmxlc1tcIkNJX0RFUEVOREVOQ1lfUFJPWFlfU0VSVkVSXCJdO1xuICAgICAgICBpZiAoIWltYWdlTmFtZS5zdGFydHNXaXRoKENJX0RFUEVOREVOQ1lfUFJPWFlfU0VSVkVSKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwibG9naW5cIiwgQ0lfREVQRU5ERU5DWV9QUk9YWV9TRVJWRVJdKTtcbiAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgICBjb25zdCBlcnJNc2cgPSBgUGxlYXNlIGF1dGhlbnRpY2F0ZSB0byB0aGUgRGVwZW5kZW5jeSBQcm94eSAoJHtDSV9ERVBFTkRFTkNZX1BST1hZX1NFUlZFUn0pIGh0dHBzOi8vZG9jcy5naXRsYWIuY29tL2VlL3VzZXIvcGFja2FnZXMvZGVwZW5kZW5jeV9wcm94eS8jYXV0aGVudGljYXRlLXdpdGgtdGhlLWRlcGVuZGVuY3ktcHJveHlgO1xuICAgICAgICAgICAgaWYgKHRoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlID09IFwiZG9ja2VyXCIpIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQoIWUuc3RkZXJyLmluY2x1ZGVzKFwiQ2Fubm90IHBlcmZvcm0gYW4gaW50ZXJhY3RpdmUgbG9naW5cIiksIGVyck1zZyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlID09IFwicG9kbWFuXCIpIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQoIWUuc3RkZXJyLmluY2x1ZGVzKFwiVXNlcm5hbWU6IEVycm9yOiBnZXR0aW5nIHVzZXJuYW1lIGFuZCBwYXNzd29yZDogcmVhZGluZyB1c2VybmFtZTogRU9GXCIpLCBlcnJNc2cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcHVsbEltYWdlICh3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcywgaW1hZ2VUb1B1bGw6IHN0cmluZykge1xuICAgICAgICBjb25zdCBwdWxsUG9saWN5ID0gdGhpcy5hcmd2LnB1bGxQb2xpY3k7XG4gICAgICAgIGNvbnN0IGFjdHVhbFB1bGwgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnZhbGlkYXRlQ2lEZXBlbmRlbmN5UHJveHlTZXJ2ZXJBdXRoZW50aWNhdGlvbihpbWFnZVRvUHVsbCk7XG4gICAgICAgICAgICBjb25zdCB0aW1lID0gcHJvY2Vzcy5ocnRpbWUoKTtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJwdWxsXCIsIGltYWdlVG9QdWxsXSk7XG4gICAgICAgICAgICBjb25zdCBlbmRUaW1lID0gcHJvY2Vzcy5ocnRpbWUodGltZSk7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7bWFnZW50YUJyaWdodCBwdWxsZWR9ICR7aW1hZ2VUb1B1bGx9IGluIHttYWdlbnRhICR7cHJldHR5SHJ0aW1lKGVuZFRpbWUpfX1cXG5gKTtcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaExvbmdSdW5uaW5nU2lsZW50VGltZW91dCh3cml0ZVN0cmVhbXMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChwdWxsUG9saWN5ID09PSBcImFsd2F5c1wiKSB7XG4gICAgICAgICAgICBhd2FpdCBhY3R1YWxQdWxsKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJpbWFnZVwiLCBcImluc3BlY3RcIiwgaW1hZ2VUb1B1bGxdKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICBhd2FpdCBhY3R1YWxQdWxsKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGluaXRQcm9kdWNlclJlcG9ydHNEb3RlbnZWYXJpYWJsZXMgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30pIHtcbiAgICAgICAgY29uc3QgY3dkID0gdGhpcy5hcmd2LmN3ZDtcbiAgICAgICAgY29uc3Qgc3RhdGVEaXIgPSB0aGlzLmFyZ3Yuc3RhdGVEaXI7XG4gICAgICAgIGNvbnN0IHByb2R1Y2VycyA9IHRoaXMucHJvZHVjZXJzO1xuICAgICAgICBsZXQgcHJvZHVjZXJSZXBvcnRzRW52cyA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IHByb2R1Y2VyIG9mIHByb2R1Y2VycyA/PyBbXSkge1xuICAgICAgICAgICAgY29uc3QgcHJvZHVjZXJEb3RlbnYgPSBVdGlscy5leHBhbmRUZXh0KHByb2R1Y2VyLmRvdGVudiwgZXhwYW5kZWQpO1xuICAgICAgICAgICAgaWYgKHByb2R1Y2VyRG90ZW52ID09PSBudWxsKSBjb250aW51ZTtcblxuICAgICAgICAgICAgY29uc3Qgc2FmZVByb2R1Y2VyTmFtZSA9IFV0aWxzLnNhZmVEb2NrZXJTdHJpbmcocHJvZHVjZXIubmFtZSk7XG4gICAgICAgICAgICBjb25zdCBkb3RlbnZGb2xkZXIgPSBgJHtjd2R9LyR7c3RhdGVEaXJ9L2FydGlmYWN0cy8ke3NhZmVQcm9kdWNlck5hbWV9Ly5naXRsYWItY2ktcmVwb3J0cy9kb3RlbnYvYDtcbiAgICAgICAgICAgIGlmIChhd2FpdCBmcy5wYXRoRXhpc3RzKGRvdGVudkZvbGRlcikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkb3RlbnZGaWxlcyA9IChhd2FpdCBVdGlscy5zcGF3bihbXCJmaW5kXCIsIFwiLlwiLCBcIi10eXBlXCIsIFwiZlwiXSwgZG90ZW52Rm9sZGVyKSkuc3Rkb3V0LnNwbGl0KFwiXFxuXCIpO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZG90ZW52RmlsZSBvZiBkb3RlbnZGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZG90ZW52RmlsZSA9PSBcIlwiKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJvZHVjZXJSZXBvcnRFbnYgPSBkb3RlbnYucGFyc2UoYXdhaXQgZnMucmVhZEZpbGUoYCR7ZG90ZW52Rm9sZGVyfS8ke2RvdGVudkZpbGV9YCkpO1xuICAgICAgICAgICAgICAgICAgICBwcm9kdWNlclJlcG9ydHNFbnZzID0gey4uLnByb2R1Y2VyUmVwb3J0c0VudnMsIC4uLnByb2R1Y2VyUmVwb3J0RW52fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IHt5ZWxsb3cgcmVwb3J0cy5kb3RlbnYgcHJvZHVjZWQgYnkgJyR7cHJvZHVjZXIubmFtZX0nIGNvdWxkIG5vdCBiZSBmb3VuZH1cXG5gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwcm9kdWNlclJlcG9ydHNFbnZzO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29weUNhY2hlSW4gKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30pIHtcbiAgICAgICAgaWYgKHRoaXMuYXJndi5tb3VudENhY2hlICYmIHRoaXMuaW1hZ2VOYW1lKGV4cGFuZGVkKSkgcmV0dXJuO1xuICAgICAgICBpZiAoKCF0aGlzLmltYWdlTmFtZShleHBhbmRlZCkgJiYgIXRoaXMuYXJndi5zaGVsbElzb2xhdGlvbikgfHwgdGhpcy5jYWNoZS5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgICAgICBjb25zdCBjd2QgPSB0aGlzLmFyZ3YuY3dkO1xuICAgICAgICBjb25zdCBzdGF0ZURpciA9IHRoaXMuYXJndi5zdGF0ZURpcjtcblxuICAgICAgICBmb3IgKGNvbnN0IFtpbmRleCwgY10gb2YgdGhpcy5jYWNoZS5lbnRyaWVzKCkpIHtcbiAgICAgICAgICAgIGlmICghW1wicHVsbFwiLCBcInB1bGwtcHVzaFwiXS5pbmNsdWRlcyhjLnBvbGljeSkpIHJldHVybjtcblxuICAgICAgICAgICAgY29uc3QgdGltZSA9IHByb2Nlc3MuaHJ0aW1lKCk7XG4gICAgICAgICAgICBjb25zdCBjYWNoZU5hbWUgPSBhd2FpdCB0aGlzLmdldFVuaXF1ZUNhY2hlTmFtZShjd2QsIGV4cGFuZGVkLCBpbmRleCk7XG4gICAgICAgICAgICBjb25zdCBjYWNoZUZvbGRlciA9IGAke2N3ZH0vJHtzdGF0ZURpcn0vY2FjaGUvJHtjYWNoZU5hbWV9YDtcbiAgICAgICAgICAgIGlmICghYXdhaXQgZnMucGF0aEV4aXN0cyhjYWNoZUZvbGRlcikpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYXdhaXQgTXV0ZXguZXhjbHVzaXZlKGNhY2hlTmFtZSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY29weUluKGNhY2hlRm9sZGVyKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uc3QgZW5kVGltZSA9IHByb2Nlc3MuaHJ0aW1lKHRpbWUpO1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge21hZ2VudGFCcmlnaHQgaW1wb3J0ZWQgY2FjaGUgJyR7Y2FjaGVOYW1lfSd9IGluIHttYWdlbnRhICR7cHJldHR5SHJ0aW1lKGVuZFRpbWUpfX1cXG5gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29weUFydGlmYWN0c0luICh3cml0ZVN0cmVhbXM6IFdyaXRlU3RyZWFtcykge1xuICAgICAgICBpZiAoKCF0aGlzLmltYWdlTmFtZSh0aGlzLl92YXJpYWJsZXMpICYmICF0aGlzLmFyZ3Yuc2hlbGxJc29sYXRpb24pIHx8ICh0aGlzLnByb2R1Y2VycyA/PyBbXSkubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgICAgICAgY29uc3QgY3dkID0gdGhpcy5hcmd2LmN3ZDtcbiAgICAgICAgY29uc3Qgc3RhdGVEaXIgPSB0aGlzLmFyZ3Yuc3RhdGVEaXI7XG4gICAgICAgIGNvbnN0IHRpbWUgPSBwcm9jZXNzLmhydGltZSgpO1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHByb2R1Y2VyIG9mIHRoaXMucHJvZHVjZXJzID8/IFtdKSB7XG4gICAgICAgICAgICBjb25zdCBwcm9kdWNlclNhZmVOYW1lID0gVXRpbHMuc2FmZURvY2tlclN0cmluZyhwcm9kdWNlci5uYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IGFydGlmYWN0Rm9sZGVyID0gYCR7Y3dkfS8ke3N0YXRlRGlyfS9hcnRpZmFjdHMvJHtwcm9kdWNlclNhZmVOYW1lfWA7XG4gICAgICAgICAgICBpZiAoIWF3YWl0IGZzLnBhdGhFeGlzdHMoYXJ0aWZhY3RGb2xkZXIpKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgZnMubWtkaXJwKGFydGlmYWN0Rm9sZGVyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcmVhZGRpciA9IGF3YWl0IGZzLnJlYWRkaXIoYXJ0aWZhY3RGb2xkZXIpO1xuICAgICAgICAgICAgaWYgKHJlYWRkaXIubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZGVycihjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge3llbGxvdyBhcnRpZmFjdHMgZnJvbSB7Ymx1ZUJyaWdodCAke3Byb2R1Y2VyU2FmZU5hbWV9fSB3YXMgZW1wdHl9XFxuYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5jb3B5SW4oYXJ0aWZhY3RGb2xkZXIpKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgICAgIGNvbnN0IGVuZFRpbWUgPSBwcm9jZXNzLmhydGltZSh0aW1lKTtcbiAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge21hZ2VudGFCcmlnaHQgaW1wb3J0ZWQgYXJ0aWZhY3RzfSBpbiB7bWFnZW50YSAke3ByZXR0eUhydGltZShlbmRUaW1lKX19XFxuYCk7XG4gICAgfVxuXG4gICAgY29weUluIChzb3VyY2U6IHN0cmluZykge1xuICAgICAgICBjb25zdCBzYWZlSm9iTmFtZSA9IHRoaXMuc2FmZUpvYk5hbWU7XG4gICAgICAgIGlmICghdGhpcy5pbWFnZU5hbWUodGhpcy5fdmFyaWFibGVzKSAmJiB0aGlzLmFyZ3Yuc2hlbGxJc29sYXRpb24pIHtcbiAgICAgICAgICAgIHJldHVybiBVdGlscy5zcGF3bihbXCJyc3luY1wiLCBcIi1hXCIsIGAke3NvdXJjZX0vLmAsIGAke3RoaXMuYXJndi5jd2R9LyR7dGhpcy5hcmd2LnN0YXRlRGlyfS9idWlsZHMvJHtzYWZlSm9iTmFtZX1gXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJjcFwiLCBgJHtzb3VyY2V9Ly5gLCBgJHt0aGlzLl9jb250YWluZXJJZH06JHt0aGlzLmNpUHJvamVjdERpcn1gXSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjb3B5Q2FjaGVPdXQgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30pIHtcbiAgICAgICAgaWYgKHRoaXMuYXJndi5tb3VudENhY2hlICYmIHRoaXMuaW1hZ2VOYW1lKGV4cGFuZGVkKSkgcmV0dXJuO1xuICAgICAgICBpZiAoKCF0aGlzLmltYWdlTmFtZShleHBhbmRlZCkgJiYgIXRoaXMuYXJndi5zaGVsbElzb2xhdGlvbikgfHwgdGhpcy5jYWNoZS5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgICAgICBjb25zdCBjd2QgPSB0aGlzLmFyZ3YuY3dkO1xuICAgICAgICBjb25zdCBzdGF0ZURpciA9IHRoaXMuYXJndi5zdGF0ZURpcjtcbiAgICAgICAgY29uc3QgY2FjaGVQYXRoID0gdGhpcy5pbWFnZU5hbWUoZXhwYW5kZWQpID8gXCIvY2FjaGVcIiA6IFwiLi4vLi4vY2FjaGVcIjtcblxuICAgICAgICBsZXQgdGltZSwgZW5kVGltZTtcbiAgICAgICAgZm9yIChjb25zdCBbaW5kZXgsIGNdIG9mIHRoaXMuY2FjaGUuZW50cmllcygpKSB7XG4gICAgICAgICAgICBpZiAoIVtcInB1c2hcIiwgXCJwdWxsLXB1c2hcIl0uaW5jbHVkZXMoYy5wb2xpY3kpKSByZXR1cm47XG4gICAgICAgICAgICBpZiAoXCJvbl9zdWNjZXNzXCIgPT09IGMud2hlbiAmJiB0aGlzLmpvYlN0YXR1cyAhPT0gXCJzdWNjZXNzXCIpIHJldHVybjtcbiAgICAgICAgICAgIGlmIChcIm9uX2ZhaWx1cmVcIiA9PT0gYy53aGVuICYmIHRoaXMuam9iU3RhdHVzID09PSBcInN1Y2Nlc3NcIikgcmV0dXJuO1xuICAgICAgICAgICAgY29uc3QgY2FjaGVOYW1lID0gYXdhaXQgdGhpcy5nZXRVbmlxdWVDYWNoZU5hbWUoY3dkLCBleHBhbmRlZCwgaW5kZXgpO1xuXG4gICAgICAgICAgICBsZXQgcGF0aHMgPSBcIlwiO1xuICAgICAgICAgICAgZm9yIChjb25zdCBwYXRoIG9mIGMucGF0aHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIVV0aWxzLmlzU3VicGF0aChwYXRoLCB0aGlzLmFyZ3YuY3dkLCB0aGlzLmFyZ3YuY3dkKSkgY29udGludWU7XG5cbiAgICAgICAgICAgICAgICBwYXRocyArPSBcIiBcIiArIFV0aWxzLmV4cGFuZFRleHQocGF0aCwgZXhwYW5kZWQpLnJlcGxhY2UoYCR7ZXhwYW5kZWQuQ0lfUFJPSkVDVF9ESVJ9L2AsIFwiXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aW1lID0gcHJvY2Vzcy5ocnRpbWUoKTtcbiAgICAgICAgICAgIGxldCBjbWQgPSBcInNob3B0IC1zIGdsb2JzdGFyIG51bGxnbG9iIGRvdGdsb2JcXG5cIjtcbiAgICAgICAgICAgIGNtZCArPSBgbWtkaXIgLXAgJHtVdGlscy5zYWZlQmFzaFN0cmluZyhjYWNoZVBhdGggKyBcIi9cIiArIGNhY2hlTmFtZSl9XFxuYDtcbiAgICAgICAgICAgIGNtZCArPSBgcnN5bmMgLVJhICR7cGF0aHN9ICR7VXRpbHMuc2FmZUJhc2hTdHJpbmcoY2FjaGVQYXRoICsgXCIvXCIgKyBjYWNoZU5hbWUgKyBcIi8uXCIpfSB8fCB0cnVlXFxuYDtcblxuICAgICAgICAgICAgYXdhaXQgTXV0ZXguZXhjbHVzaXZlKGNhY2hlTmFtZSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY29weU91dChjbWQsIHN0YXRlRGlyLCBcImNhY2hlXCIsIFtdKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZW5kVGltZSA9IHByb2Nlc3MuaHJ0aW1lKHRpbWUpO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IF9fcGF0aCBvZiBjLnBhdGhzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgX3BhdGggPSBVdGlscy5leHBhbmRUZXh0KF9fcGF0aCwgZXhwYW5kZWQpO1xuICAgICAgICAgICAgICAgIGlmICghVXRpbHMuaXNTdWJwYXRoKF9wYXRoLCB0aGlzLmFyZ3YuY3dkLCB0aGlzLmFyZ3YuY3dkKSkge1xuICAgICAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYHt5ZWxsb3cgV0FSTklORzogcHJvY2Vzc1BhdGg6IGFydGlmYWN0IHBhdGggaXMgbm90IGEgc3VicGF0aCBvZiBwcm9qZWN0IGRpcmVjdG9yeTogJHtfcGF0aH19XFxuYCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCBwYXRoID0gX3BhdGg7XG4gICAgICAgICAgICAgICAgaWYgKGlzR2xvYihwYXRoKSAmJiAhcGF0aC5lbmRzV2l0aChcIipcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0aCA9IGAke3BhdGh9LyoqYDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgbnVtT2ZGaWxlcyA9IGdsb2JieVN5bmMocGF0aCwge1xuICAgICAgICAgICAgICAgICAgICBkb3Q6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIG9ubHlGaWxlczogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGN3ZDogYCR7dGhpcy5hcmd2LmN3ZH0vJHtzdGF0ZURpcn0vY2FjaGUvJHtjYWNoZU5hbWV9YCxcbiAgICAgICAgICAgICAgICB9KS5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBpZiAobnVtT2ZGaWxlcyA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRvdXQoY2hhbGtge3llbGxvdyBXQVJOSU5HOiAke3BhdGh9OiBubyBtYXRjaGluZyBmaWxlcy4gRW5zdXJlIHRoYXQgdGhlIGFydGlmYWN0IHBhdGggaXMgcmVsYXRpdmUgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5fVxcbmApO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzR2xvYihwYXRoKSkgbnVtT2ZGaWxlcysrOyAvLyBhZGQgb25lIGJlY2F1c2UgdGhlIHBhdHRlcm4gaXRzZWxmIGlzIGEgZm9sZGVyXG5cbiAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGAke19wYXRofTogZm91bmQgJHtudW1PZkZpbGVzfSBhcnRpZmFjdCBmaWxlcyBhbmQgZGlyZWN0b3JpZXNcXG5gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRvdXQoY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IHttYWdlbnRhQnJpZ2h0IGNhY2hlIGNyZWF0ZWQgaW4gJyR7c3RhdGVEaXJ9L2NhY2hlLyR7Y2FjaGVOYW1lfSd9IGluIHttYWdlbnRhICR7cHJldHR5SHJ0aW1lKGVuZFRpbWUpfX1cXG5gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29weUFydGlmYWN0c091dCAod3JpdGVTdHJlYW1zOiBXcml0ZVN0cmVhbXMsIGV4cGFuZGVkOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSkge1xuICAgICAgICAvLyBUT0RPOiB1cGRhdGUgdGhlIGNvbmRpdGlvbiB0byBzdXBwb3J0IHdoZW46b25fc3VjY2VzcyAvIHdoZW46b25fZmFpbHVyZVxuICAgICAgICBpZiAodGhpcy5qb2JTdGF0dXMgIT09IFwic3VjY2Vzc1wiICYmIHRoaXMuYXJ0aWZhY3RzPy53aGVuICE9PSBcImFsd2F5c1wiKSByZXR1cm47XG4gICAgICAgIGlmICghdGhpcy5hcnRpZmFjdHMpIHJldHVybjtcbiAgICAgICAgaWYgKCh0aGlzLmFydGlmYWN0cy5wYXRocz8ubGVuZ3RoID8/IDApID09PSAwICYmIHRoaXMuYXJ0aWZhY3RzLnJlcG9ydHM/LmRvdGVudiA9PSBudWxsKSByZXR1cm47XG5cbiAgICAgICAgY29uc3Qgc2FmZUpvYk5hbWUgPSB0aGlzLnNhZmVKb2JOYW1lO1xuICAgICAgICBjb25zdCBjd2QgPSB0aGlzLmFyZ3YuY3dkO1xuICAgICAgICBjb25zdCBzdGF0ZURpciA9IHRoaXMuYXJndi5zdGF0ZURpcjtcbiAgICAgICAgbGV0IGFydGlmYWN0c1BhdGg6IHN0cmluZztcblxuICAgICAgICBpZiAoIXRoaXMuYXJndi5zaGVsbElzb2xhdGlvbiAmJiAhdGhpcy5pbWFnZU5hbWUoZXhwYW5kZWQpKSB7XG4gICAgICAgICAgICBhcnRpZmFjdHNQYXRoID0gYCR7c3RhdGVEaXJ9L2FydGlmYWN0c2A7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5pbWFnZU5hbWUoZXhwYW5kZWQpKSB7XG4gICAgICAgICAgICBhcnRpZmFjdHNQYXRoID0gXCIvYXJ0aWZhY3RzXCI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhcnRpZmFjdHNQYXRoID0gXCIuLi8uLi9hcnRpZmFjdHNcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB0aW1lLCBlbmRUaW1lO1xuICAgICAgICBsZXQgY3BDbWQgPSBcInNob3B0IC1zIGdsb2JzdGFyIG51bGxnbG9iIGRvdGdsb2JcXG5cIjtcbiAgICAgICAgY3BDbWQgKz0gYG1rZGlyIC1wICR7YXJ0aWZhY3RzUGF0aH0vJHtzYWZlSm9iTmFtZX1cXG5gO1xuICAgICAgICBjcENtZCArPSBcInJzeW5jIC0tZXhjbHVkZSAnLmdpdGxhYi1jaS1sb2NhbC8qKicgLVJhIFwiO1xuICAgICAgICBmb3IgKGNvbnN0IGFydGlmYWN0RXhjbHVkZVBhdGggb2YgdGhpcy5hcnRpZmFjdHM/LmV4Y2x1ZGUgPz8gW10pIHtcbiAgICAgICAgICAgIGNvbnN0IGV4cGFuZGVkUGF0aCA9IFV0aWxzLmV4cGFuZFRleHQoYXJ0aWZhY3RFeGNsdWRlUGF0aCwgZXhwYW5kZWQpLnJlcGxhY2UoYCR7ZXhwYW5kZWQuQ0lfUFJPSkVDVF9ESVJ9L2AsIFwiXCIpO1xuICAgICAgICAgICAgY3BDbWQgKz0gYC0tZXhjbHVkZSAnJHtleHBhbmRlZFBhdGh9JyBgO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3QgYXJ0aWZhY3RQYXRoIG9mIHRoaXMuYXJ0aWZhY3RzPy5wYXRocyA/PyBbXSkge1xuICAgICAgICAgICAgY29uc3QgZXhwYW5kZWRQYXRoID0gVXRpbHMuZXhwYW5kVGV4dChhcnRpZmFjdFBhdGgsIGV4cGFuZGVkKS5yZXBsYWNlKGAke2V4cGFuZGVkLkNJX1BST0pFQ1RfRElSfS9gLCBcIlwiKTtcbiAgICAgICAgICAgIGNwQ21kICs9IGAke2V4cGFuZGVkUGF0aH0gYDtcbiAgICAgICAgfVxuICAgICAgICBjcENtZCArPSBgJHthcnRpZmFjdHNQYXRofS8ke3NhZmVKb2JOYW1lfS8uIHx8IHRydWVcXG5gO1xuICAgICAgICBjb25zdCByZXBvcnREb3RlbnYgPSBVdGlscy5leHBhbmRUZXh0KHRoaXMuYXJ0aWZhY3RzLnJlcG9ydHM/LmRvdGVudiA/PyBudWxsLCBleHBhbmRlZCk7XG4gICAgICAgIGNvbnN0IHJlcG9ydERvdGVudnM6IHN0cmluZ1tdIHwgbnVsbCA9ICh0eXBlb2YgcmVwb3J0RG90ZW52ID09PSBcInN0cmluZ1wiKSA/IC8vIG5vcm1hbGl6ZSB0byBzdHJpbmdbXSBmb3IgZWFzaWVyIGhhbmRsaW5nXG4gICAgICAgICAgICBbcmVwb3J0RG90ZW52XSA6XG4gICAgICAgICAgICByZXBvcnREb3RlbnY7XG4gICAgICAgIGlmIChyZXBvcnREb3RlbnZzICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJlcG9ydERvdGVudnMuZm9yRWFjaCgocmVwb3J0RG90ZW52KSA9PiB7XG4gICAgICAgICAgICAgICAgY3BDbWQgKz0gYG1rZGlyIC1wICR7YXJ0aWZhY3RzUGF0aH0vJHtzYWZlSm9iTmFtZX0vLmdpdGxhYi1jaS1yZXBvcnRzL2RvdGVudlxcbmA7XG4gICAgICAgICAgICAgICAgY3BDbWQgKz0gYGlmIFsgLWYgJHtyZXBvcnREb3RlbnZ9IF07IHRoZW5cXG5gO1xuICAgICAgICAgICAgICAgIGNwQ21kICs9IGAgIHJzeW5jIC1SYSAke3JlcG9ydERvdGVudn0gJHthcnRpZmFjdHNQYXRofS8ke3NhZmVKb2JOYW1lfS8uZ2l0bGFiLWNpLXJlcG9ydHMvZG90ZW52Ly5cXG5gO1xuICAgICAgICAgICAgICAgIGNwQ21kICs9IFwiZmlcXG5cIjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGltZSA9IHByb2Nlc3MuaHJ0aW1lKCk7XG4gICAgICAgIGNvbnN0IGRvY2tlckNtZEV4dHJhcyA9IHRoaXMuYXJndi5tb3VudENhY2hlID8gYXdhaXQgdGhpcy5tb3VudENhY2hlQ21kKHdyaXRlU3RyZWFtcywgZXhwYW5kZWQpIDogW107XG4gICAgICAgIGF3YWl0IHRoaXMuY29weU91dChjcENtZCwgc3RhdGVEaXIsIFwiYXJ0aWZhY3RzXCIsIGRvY2tlckNtZEV4dHJhcyk7XG4gICAgICAgIGVuZFRpbWUgPSBwcm9jZXNzLmhydGltZSh0aW1lKTtcblxuICAgICAgICBmb3IgKGNvbnN0IHJlcG9ydERvdGVudiBvZiByZXBvcnREb3RlbnZzID8/IFtdKSB7XG4gICAgICAgICAgICBpZiAoYXdhaXQgZnMucGF0aEV4aXN0cyhgJHtjd2R9LyR7c3RhdGVEaXJ9L2FydGlmYWN0cy8ke3NhZmVKb2JOYW1lfS8uZ2l0bGFiLWNpLXJlcG9ydHMvZG90ZW52LyR7cmVwb3J0RG90ZW52fWApKSBjb250aW51ZTtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IHt5ZWxsb3cgYXJ0aWZhY3QgcmVwb3J0cyBkb3RlbnYgJyR7cmVwb3J0RG90ZW52fScgY291bGQgbm90IGJlIGZvdW5kfVxcbmApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVhZGRpciA9IGF3YWl0IGZzLnJlYWRkaXIoYCR7Y3dkfS8ke3N0YXRlRGlyfS9hcnRpZmFjdHMvJHtzYWZlSm9iTmFtZX1gKTtcbiAgICAgICAgaWYgKHJlYWRkaXIubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7eWVsbG93ICEhIG5vIGFydGlmYWN0cyB3YXMgY29waWVkICEhfVxcbmApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge21hZ2VudGFCcmlnaHQgZXhwb3J0ZWQgYXJ0aWZhY3RzfSBpbiB7bWFnZW50YSAke3ByZXR0eUhydGltZShlbmRUaW1lKX19XFxuYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5hcnRpZmFjdHNUb1NvdXJjZSAmJiAodGhpcy5hcmd2LnNoZWxsSXNvbGF0aW9uIHx8IHRoaXMuaW1hZ2VOYW1lKGV4cGFuZGVkKSkpIHtcbiAgICAgICAgICAgIHRpbWUgPSBwcm9jZXNzLmhydGltZSgpO1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW1wicnN5bmNcIiwgXCItLWV4Y2x1ZGU9Ly5naXRsYWItY2ktcmVwb3J0cy9cIiwgXCItYVwiLCBgJHtjd2R9LyR7c3RhdGVEaXJ9L2FydGlmYWN0cy8ke3NhZmVKb2JOYW1lfS8uYCwgY3dkXSk7XG4gICAgICAgICAgICBpZiAocmVwb3J0RG90ZW52ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBVdGlscy5zcGF3bihbXCJyc3luY1wiLCBcIi1hXCIsIGAke2N3ZH0vJHtzdGF0ZURpcn0vYXJ0aWZhY3RzLyR7c2FmZUpvYk5hbWV9Ly5naXRsYWItY2ktcmVwb3J0cy9kb3RlbnYvLmAsIGN3ZF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZW5kVGltZSA9IHByb2Nlc3MuaHJ0aW1lKHRpbWUpO1xuICAgICAgICAgICAgd3JpdGVTdHJlYW1zLnN0ZG91dChjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge21hZ2VudGFCcmlnaHQgY29waWVkIGFydGlmYWN0cyB0byBjd2R9IGluIHttYWdlbnRhICR7cHJldHR5SHJ0aW1lKGVuZFRpbWUpfX1cXG5gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29weU91dCAoY21kOiBzdHJpbmcsIHN0YXRlRGlyOiBzdHJpbmcsIHR5cGU6IFwiYXJ0aWZhY3RzXCIgfCBcImNhY2hlXCIsIGRvY2tlckNtZEV4dHJhczogc3RyaW5nW10pIHtcbiAgICAgICAgY29uc3Qgc2FmZUpvYk5hbWUgPSB0aGlzLnNhZmVKb2JOYW1lO1xuICAgICAgICBjb25zdCBidWlsZFZvbHVtZU5hbWUgPSB0aGlzLmJ1aWxkVm9sdW1lTmFtZTtcbiAgICAgICAgY29uc3QgY3dkID0gdGhpcy5hcmd2LmN3ZDtcbiAgICAgICAgY29uc3QgaGVscGVySW1hZ2VOYW1lID0gdGhpcy5hcmd2LmhlbHBlckltYWdlO1xuXG4gICAgICAgIGF3YWl0IGZzLm1rZGlycChgJHtjd2R9LyR7c3RhdGVEaXJ9LyR7dHlwZX1gKTtcblxuICAgICAgICBpZiAodGhpcy5pbWFnZU5hbWUodGhpcy5fdmFyaWFibGVzKSkge1xuICAgICAgICAgICAgY29uc3Qge3N0ZG91dDogY29udGFpbmVySWR9ID0gYXdhaXQgVXRpbHMuYmFzaChgJHt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZX0gY3JlYXRlIC1pICR7ZG9ja2VyQ21kRXh0cmFzLmpvaW4oXCIgXCIpfSAtdiAke2J1aWxkVm9sdW1lTmFtZX06JHt0aGlzLmNpUHJvamVjdERpcn0gLXcgJHt0aGlzLmNpUHJvamVjdERpcn0gJHtoZWxwZXJJbWFnZU5hbWV9IGJhc2ggLWMgXCIke2NtZC5yZXBsYWNlKC9cIi9nLCBcIlxcXFxcXFwiXCIpfVwiYCwgY3dkKTtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lcnNUb0NsZWFuLnB1c2goY29udGFpbmVySWQpO1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcInN0YXJ0XCIsIGNvbnRhaW5lcklkLCBcIi0tYXR0YWNoXCJdKTtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJjcFwiLCBgJHtjb250YWluZXJJZH06LyR7dHlwZX0vLmAsIGAke3N0YXRlRGlyfS8ke3R5cGV9Ly5gXSwgY3dkKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmFyZ3Yuc2hlbGxJc29sYXRpb24pIHtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLmJhc2goYGJhc2ggLWVvIHBpcGVmYWlsIC1jIFwiJHtjbWR9XCJgLCBgJHtjd2R9LyR7c3RhdGVEaXJ9L2J1aWxkcy8ke3NhZmVKb2JOYW1lfWApO1xuICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmFyZ3Yuc2hlbGxJc29sYXRpb24pIHtcbiAgICAgICAgICAgIGF3YWl0IFV0aWxzLmJhc2goYGJhc2ggLWVvIHBpcGVmYWlsIC1jIFwiJHtjbWR9XCJgLCBgJHtjd2R9YCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHJlZnJlc2hMb25nUnVubmluZ1NpbGVudFRpbWVvdXQgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl9sb25nUnVubmluZ1NpbGVudFRpbWVvdXQpO1xuICAgICAgICB0aGlzLl9sb25nUnVubmluZ1NpbGVudFRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRvdXQoY2hhbGtgJHt0aGlzLmZvcm1hdHRlZEpvYk5hbWV9IHtncmV5ID4gc3RpbGwgcnVubmluZy4uLn1cXG5gKTtcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaExvbmdSdW5uaW5nU2lsZW50VGltZW91dCh3cml0ZVN0cmVhbXMpO1xuICAgICAgICB9LCAxMDAwMCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRGaW5pc2hlZFN0cmluZyAoKSB7XG4gICAgICAgIHJldHVybiBjaGFsa2Ake3RoaXMuZm9ybWF0dGVkSm9iTmFtZX0ge21hZ2VudGFCcmlnaHQgZmluaXNoZWR9IGluIHttYWdlbnRhICR7dGhpcy5wcmV0dHlEdXJhdGlvbn19YDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByaW50RmluaXNoZWRTdHJpbmcgKCkge1xuICAgICAgICBpZiAodGhpcy5qb2JTdGF0dXMgIT09IFwic3VjY2Vzc1wiKSByZXR1cm47XG4gICAgICAgIHRoaXMud3JpdGVTdHJlYW1zLnN0ZG91dChgJHt0aGlzLmdldEZpbmlzaGVkU3RyaW5nKCl9XFxuYCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcmludEV4aXRlZFN0cmluZyAoY29kZTogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IHdyaXRlU3RyZWFtcyA9IHRoaXMud3JpdGVTdHJlYW1zO1xuICAgICAgICBjb25zdCBmaW5pc2hlZFN0ciA9IHRoaXMuZ2V0RmluaXNoZWRTdHJpbmcoKTtcblxuICAgICAgICAvLyBXb24ndCBwcmludCBpZiBqb2JTdGF0dXMgaXMgXCJzdWNjZXNzXCIgYmVjYXVzZSB0aGF0IHdpbGwgYmUgcHJpbnRlZCB2aWEgdGhlIGBwcmludEZpbmlzaGVkU3RyaW5nKClgXG4gICAgICAgIGlmICh0aGlzLmpvYlN0YXR1cyA9PT0gXCJ3YXJuaW5nXCIpIHtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoXG4gICAgICAgICAgICAgICAgY2hhbGtgJHtmaW5pc2hlZFN0cn0ge2JsYWNrLmJnWWVsbG93QnJpZ2h0ICBXQVJOICR7Y29kZS50b1N0cmluZygpfSB9XFxuYCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5qb2JTdGF0dXMgPT09IFwiZmFpbGVkXCIpIHtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoXG4gICAgICAgICAgICAgICAgY2hhbGtgJHtmaW5pc2hlZFN0cn0ge2JsYWNrLmJnUmVkICBGQUlMICR7Y29kZS50b1N0cmluZygpfSB9XFxuYCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHByaW50QWZ0ZXJTY3JpcHRFeGl0ZWRTdHJpbmcgKGNvZGU6IG51bWJlcikge1xuICAgICAgICBjb25zdCB3cml0ZVN0cmVhbXMgPSB0aGlzLndyaXRlU3RyZWFtcztcbiAgICAgICAgY29uc3QgZmluaXNoZWRTdHIgPSB0aGlzLmdldEZpbmlzaGVkU3RyaW5nKCk7XG5cbiAgICAgICAgaWYgKGNvZGUgIT09IDApIHtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtcy5zdGRlcnIoXG4gICAgICAgICAgICAgICAgY2hhbGtgJHtmaW5pc2hlZFN0cn0ge2JsYWNrLmJnWWVsbG93QnJpZ2h0ICBXQVJOICR7Y29kZS50b1N0cmluZygpfSB9IGFmdGVyX3NjcmlwdFxcbmAsXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjcmVhdGVEb2NrZXJOZXR3b3JrIChuZXR3b3JrTmFtZTogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IHtzdGRvdXQ6IG5ldHdvcmtJZH0gPSBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwibmV0d29ya1wiLCBcImNyZWF0ZVwiLCBgJHtuZXR3b3JrTmFtZX1gXSk7XG4gICAgICAgIHRoaXMuX3NlcnZpY2VOZXR3b3JrSWQgPSBuZXR3b3JrSWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBzdGFydFNlcnZpY2UgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBleHBhbmRlZDoge1trZXk6IHN0cmluZ106IHN0cmluZ30sIHNlcnZpY2U6IFNlcnZpY2UpIHtcbiAgICAgICAgY29uc3QgY3dkID0gdGhpcy5hcmd2LmN3ZDtcbiAgICAgICAgbGV0IGRvY2tlckNtZCA9IGAke3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlfSBjcmVhdGUgLS1pbnRlcmFjdGl2ZSBgO1xuICAgICAgICB0aGlzLnJlZnJlc2hMb25nUnVubmluZ1NpbGVudFRpbWVvdXQod3JpdGVTdHJlYW1zKTtcblxuICAgICAgICBpZiAodGhpcy5hcmd2LnVtYXNrKSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gXCItLXVzZXIgMDowIFwiO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuYXJndi51c2VybnMgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdXNlcm5zPSR7dGhpcy5hcmd2LnVzZXJuc30gYDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmFyZ3YucHJpdmlsZWdlZCkge1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IFwiLS1wcml2aWxlZ2VkIFwiO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCBkZXZpY2Ugb2YgdGhpcy5hcmd2LmRldmljZSkge1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLWRldmljZSAke2RldmljZX0gYDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmFyZ3YudWxpbWl0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdWxpbWl0IG5vZmlsZT0ke3RoaXMuYXJndi51bGltaXR9IGA7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IHZvbHVtZSBvZiB0aGlzLmFyZ3Yudm9sdW1lKSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7dm9sdW1lfSBgO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCBleHRyYUhvc3Qgb2YgdGhpcy5hcmd2LmV4dHJhSG9zdCkge1xuICAgICAgICAgICAgZG9ja2VyQ21kICs9IGAtLWFkZC1ob3N0PSR7ZXh0cmFIb3N0fSBgO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuYXJndi5jYUZpbGUpIHtcbiAgICAgICAgICAgIGNvbnN0IGNhRmlsZVBhdGggPSBwYXRoLmlzQWJzb2x1dGUodGhpcy5hcmd2LmNhRmlsZSkgPyB0aGlzLmFyZ3YuY2FGaWxlIDogcGF0aC5yZXNvbHZlKHRoaXMuYXJndi5jd2QsIHRoaXMuYXJndi5jYUZpbGUpO1xuICAgICAgICAgICAgaWYgKGF3YWl0IGZzLnBhdGhFeGlzdHMoY2FGaWxlUGF0aCkpIHtcbiAgICAgICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7Y2FGaWxlUGF0aH06L2V0Yy9zc2wvY2VydHMvY2EtY2VydGlmaWNhdGVzLmNydDpybyBgO1xuICAgICAgICAgICAgICAgIGV4cGFuZGVkW1wiU1NMX0NFUlRfRklMRVwiXSA9IFwiL2V0Yy9zc2wvY2VydHMvY2EtY2VydGlmaWNhdGVzLmNydFwiO1xuICAgICAgICAgICAgICAgIGV4cGFuZGVkW1wiU1NMX0NFUlRfRElSXCJdID0gXCIvZXRjL3NzbC9jZXJ0c1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc2VydmljZUFsaWFzID0gc2VydmljZS5hbGlhcztcbiAgICAgICAgY29uc3Qgc2VydmljZU5hbWUgPSBzZXJ2aWNlLm5hbWU7XG4gICAgICAgIGNvbnN0IHNlcnZpY2VOYW1lV2l0aG91dFZlcnNpb24gPSBzZXJ2aWNlTmFtZS5yZXBsYWNlKC8oLiopKDouKikvLCBcIiQxXCIpO1xuICAgICAgICBjb25zdCBhbGlhc2VzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICAgIGFsaWFzZXMuYWRkKHNlcnZpY2VOYW1lV2l0aG91dFZlcnNpb24ucmVwbGFjZUFsbChcIi9cIiwgXCItXCIpKTtcbiAgICAgICAgYWxpYXNlcy5hZGQoc2VydmljZU5hbWVXaXRob3V0VmVyc2lvbi5yZXBsYWNlQWxsKFwiL1wiLCBcIl9fXCIpKTtcbiAgICAgICAgaWYgKHNlcnZpY2VBbGlhcykge1xuICAgICAgICAgICAgYWxpYXNlcy5hZGQoc2VydmljZUFsaWFzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiBPYmplY3QuZW50cmllcyhleHBhbmRlZCkpIHtcbiAgICAgICAgICAgIC8vIFJlcGxhY2luZyBgJ2Agd2l0aCBgJ1xcJydgIHRvIGNvcnJlY3RseSBoYW5kbGUgc2luZ2xlIHF1b3RlcyhpZiBgdmFsYCBjb250YWlucyBgJ2ApIGluIHNoZWxsIGNvbW1hbmRzXG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYCAgLWUgJyR7a2V5fT0ke3ZhbC50b1N0cmluZygpLnJlcGxhY2UoLycvZywgXCInXFxcXCcnXCIpfScgXFxcXFxcbmA7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzZXJ2aWNlRW50cnlwb2ludCA9IHNlcnZpY2UuZW50cnlwb2ludDtcbiAgICAgICAgaWYgKHNlcnZpY2VFbnRyeXBvaW50KSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tZW50cnlwb2ludCAke1V0aWxzLnNhZmVCYXNoU3RyaW5nKHNlcnZpY2VFbnRyeXBvaW50WzBdKX0gYDtcbiAgICAgICAgfVxuICAgICAgICBkb2NrZXJDbWQgKz0gYC0tdm9sdW1lICR7dGhpcy5idWlsZFZvbHVtZU5hbWV9OiR7dGhpcy5jaVByb2plY3REaXJ9IGA7XG4gICAgICAgIGRvY2tlckNtZCArPSBgLS12b2x1bWUgJHt0aGlzLnRtcFZvbHVtZU5hbWV9OiR7dGhpcy5maWxlVmFyaWFibGVzRGlyfSBgO1xuXG4gICAgICAgIC8vIFRoZSBkZWZhdWx0IHBvZG1hbiBuZXR3b3JrIG1vZGUgaXMgbm90IGBicmlkZ2VgLCB3aGljaCBtZWFucyBhIGBwb2RtYW4gbmV0d29yayBjb25uZWN0YCBjYWxsIHdpbGwgZmFpbFxuICAgICAgICAvLyB3aGVuIGNvbm5lY3RpbmcgdXNlciBkZWZpbmVkIG5ldHdvcmtzLiBUaGUgd29ya2Fyb3VuZCBpcyB0byB1c2UgYSB1c2VyIGRlZmluZWQgbmV0d29yayBvbiBjb250YWluZXJcbiAgICAgICAgLy8gY3JlYXRpb24uXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vY29udGFpbmVycy9wb2RtYW4vaXNzdWVzLzE5NTc3XG4gICAgICAgIGRvY2tlckNtZCArPSBgLS1uZXR3b3JrICR7dGhpcy5fc2VydmljZU5ldHdvcmtJZH0gYDtcbiAgICAgICAgZm9yIChjb25zdCBhbGlhcyBvZiBhbGlhc2VzKSB7XG4gICAgICAgICAgICBkb2NrZXJDbWQgKz0gYC0tbmV0d29yay1hbGlhcyAke2FsaWFzfSBgO1xuICAgICAgICB9XG5cbiAgICAgICAgZG9ja2VyQ21kICs9IGAke3NlcnZpY2VOYW1lfSBgO1xuXG4gICAgICAgIGlmIChzZXJ2aWNlRW50cnlwb2ludD8ubGVuZ3RoID8/IDAgPiAxKSB7XG4gICAgICAgICAgICBzZXJ2aWNlRW50cnlwb2ludD8uc2xpY2UoMSkuZm9yRWFjaCgoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGRvY2tlckNtZCArPSBgJHtVdGlscy5zYWZlQmFzaFN0cmluZyhlKX0gYDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIChzZXJ2aWNlLmNvbW1hbmQgPz8gW10pLmZvckVhY2goKGUpID0+IGRvY2tlckNtZCArPSBgXCIke2UucmVwbGFjZSgvXFwkL2csIFwiXFxcXCRcIil9XCIgYCk7XG5cbiAgICAgICAgY29uc3QgdGltZSA9IHByb2Nlc3MuaHJ0aW1lKCk7XG5cbiAgICAgICAgY29uc3Qge3N0ZG91dDogY29udGFpbmVySWR9ID0gYXdhaXQgVXRpbHMuYmFzaChkb2NrZXJDbWQsIGN3ZCk7XG4gICAgICAgIHRoaXMuX2NvbnRhaW5lcnNUb0NsZWFuLnB1c2goY29udGFpbmVySWQpO1xuXG4gICAgICAgIGZvciAoY29uc3QgbmV0d29yayBvZiB0aGlzLmFyZ3YubmV0d29yaykge1xuICAgICAgICAgICAgYXdhaXQgVXRpbHMuc3Bhd24oW3RoaXMuYXJndi5jb250YWluZXJFeGVjdXRhYmxlLCBcIm5ldHdvcmtcIiwgXCJjb25uZWN0XCIsIG5ldHdvcmssIGAke2NvbnRhaW5lcklkfWBdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJzdGFydFwiLCBgJHtjb250YWluZXJJZH1gXSk7XG5cbiAgICAgICAgY29uc3QgZW5kVGltZSA9IHByb2Nlc3MuaHJ0aW1lKHRpbWUpO1xuICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7bWFnZW50YUJyaWdodCBzdGFydGVkIHNlcnZpY2UgaW1hZ2U6ICR7c2VydmljZU5hbWV9IHdpdGggYWxpYXNlczogJHtBcnJheS5mcm9tKGFsaWFzZXMpLmpvaW4oXCIsIFwiKX19IGluIHttYWdlbnRhICR7cHJldHR5SHJ0aW1lKGVuZFRpbWUpfX1cXG5gKTtcblxuICAgICAgICByZXR1cm4gY29udGFpbmVySWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBzZXJ2aWNlSGVhbHRoQ2hlY2sgKHdyaXRlU3RyZWFtczogV3JpdGVTdHJlYW1zLCBzZXJ2aWNlOiBTZXJ2aWNlLCBzZXJ2aWNlSW5kZXg6IG51bWJlciwgc2VydmljZUNvbnRhaW5lckxvZ0ZpbGU6IHN0cmluZykge1xuICAgICAgICBjb25zdCBzZXJ2aWNlQWxpYXMgPSBzZXJ2aWNlLmFsaWFzO1xuICAgICAgICBjb25zdCBzZXJ2aWNlTmFtZSA9IHNlcnZpY2UubmFtZTtcbiAgICAgICAgY29uc3Qgd2FpdEltYWdlTmFtZSA9IHRoaXMuYXJndi53YWl0SW1hZ2U7XG5cbiAgICAgICAgY29uc3Qge3N0ZG91dH0gPSBhd2FpdCBVdGlscy5zcGF3bihbdGhpcy5hcmd2LmNvbnRhaW5lckV4ZWN1dGFibGUsIFwiaW1hZ2VcIiwgXCJpbnNwZWN0XCIsIHNlcnZpY2VOYW1lXSk7XG4gICAgICAgIGNvbnN0IGltYWdlSW5zcGVjdCA9IEpTT04ucGFyc2Uoc3Rkb3V0KTtcblxuICAgICAgICAvLyBDb3BpZWQgZnJvbSB0aGUgc3RhcnRTZXJ2aWNlIGJsb2NrLiBJbXBvcnRhbnQgdGhpbmcgaXMgdGhhdCB0aGUgYWxpYXNlcyBtYXRjaFxuICAgICAgICBjb25zdCBzZXJ2aWNlTmFtZVdpdGhvdXRWZXJzaW9uID0gc2VydmljZU5hbWUucmVwbGFjZSgvKC4qKSg6LiopLywgXCIkMVwiKTtcbiAgICAgICAgY29uc3QgYWxpYXNlcyA9IFtzZXJ2aWNlTmFtZVdpdGhvdXRWZXJzaW9uLnJlcGxhY2VBbGwoXCIvXCIsIFwiLVwiKSwgc2VydmljZU5hbWVXaXRob3V0VmVyc2lvbi5yZXBsYWNlQWxsKFwiL1wiLCBcIl9fXCIpXTtcbiAgICAgICAgaWYgKHNlcnZpY2VBbGlhcykge1xuICAgICAgICAgICAgYWxpYXNlcy5wdXNoKHNlcnZpY2VBbGlhcyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB1bmlxdWVBbGlhcyA9IGFsaWFzZXNbYWxpYXNlcy5sZW5ndGggLSAxXTtcblxuICAgICAgICBpZiAoKGltYWdlSW5zcGVjdFswXT8uQ29uZmlnPy5FeHBvc2VkUG9ydHMgPz8gbnVsbCkgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB3cml0ZVN0cmVhbXMuc3RkZXJyKGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7eWVsbG93IENvdWxkIG5vdCBmaW5kIGV4cG9zZWQgdGNwIHBvcnRzICR7c2VydmljZU5hbWV9fVxcbmApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdGltZSA9IHByb2Nlc3MuaHJ0aW1lKCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBJdGVyYXRlIG92ZXIgZWFjaCBwb3J0IGRlZmluZWQgaW4gdGhlIGltYWdlLCBhbmQgdHJ5IHRvIGNvbm5lY3QgdG8gdGhlIGFsaWFzXG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFueShPYmplY3Qua2V5cyhpbWFnZUluc3BlY3RbMF0uQ29uZmlnLkV4cG9zZWRQb3J0cykubWFwKChwb3J0KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFwb3J0LmVuZHNXaXRoKFwiL3RjcFwiKSkgcmV0dXJuO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvcnROdW0gPSBwYXJzZUludChwb3J0LnJlcGxhY2UoXCIvdGNwXCIsIFwiXCIpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjb250YWluZXJOYW1lID0gYGdjbC13YWl0LWZvci1pdC0ke3RoaXMuam9iSWR9LSR7c2VydmljZUluZGV4fS0ke3BvcnROdW19YDtcbiAgICAgICAgICAgICAgICBjb25zdCBzcGF3bkNtZCA9IFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJydW5cIiwgXCItLXJtXCIsIGAtLW5hbWU9JHtjb250YWluZXJOYW1lfWAsIFwiLS1uZXR3b3JrXCIsIGAke3RoaXMuX3NlcnZpY2VOZXR3b3JrSWR9YCwgYCR7d2FpdEltYWdlTmFtZX1gLCBgJHt1bmlxdWVBbGlhc306JHtwb3J0TnVtfWAsIFwiLXRcIiwgXCIzMFwiXTtcbiAgICAgICAgICAgICAgICB0aGlzLl9jb250YWluZXJzVG9DbGVhbi5wdXNoKGNvbnRhaW5lck5hbWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBVdGlscy5zcGF3bihzcGF3bkNtZCk7XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICBjb25zdCBlbmRUaW1lID0gcHJvY2Vzcy5ocnRpbWUodGltZSk7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7Z3JlZW5CcmlnaHQgc2VydmljZSBpbWFnZTogJHtzZXJ2aWNlTmFtZX0gaGVhbHRoY2hlY2sgcGFzc2VkIGluIHtncmVlbiAke3ByZXR0eUhydGltZShlbmRUaW1lKX19fVxcbmApO1xuICAgICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBBZ2dyZWdhdGVFcnJvcikpIHRocm93IGU7XG4gICAgICAgICAgICBlLmVycm9ycy5mb3JFYWNoKChzaW5nbGVFcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7cmVkQnJpZ2h0IHNlcnZpY2UgaW1hZ2U6ICR7c2VydmljZU5hbWV9IGhlYWx0aGNoZWNrIGZhaWxlZH1cXG5gKTtcbiAgICAgICAgICAgICAgICBzaW5nbGVFcnJvci5tZXNzYWdlLnNwbGl0KC9cXHI/XFxuL2cpLmZvckVhY2goKGxpbmU6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7cmVkQnJpZ2h0ICAgJHtsaW5lfX1cXG5gKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB3cml0ZVN0cmVhbXMuc3Rkb3V0KGNoYWxrYCR7dGhpcy5mb3JtYXR0ZWRKb2JOYW1lfSB7cmVkQnJpZ2h0IGFsc28gc2VlICgke3NlcnZpY2VDb250YWluZXJMb2dGaWxlfSl9XFxuYCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIC8vIEtpbGwgYWxsIHdhaXQtZm9yLWl0IGNvbnRhaW5lcnMsIHdoZW4gb25lIGhhdmUgYmVlbiBzdWNjZXNzZnVsXG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoT2JqZWN0LmtleXMoaW1hZ2VJbnNwZWN0WzBdLkNvbmZpZy5FeHBvc2VkUG9ydHMpLm1hcCgocG9ydCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghcG9ydC5lbmRzV2l0aChcIi90Y3BcIikpIHJldHVybjtcbiAgICAgICAgICAgICAgICBjb25zdCBwb3J0TnVtID0gcGFyc2VJbnQocG9ydC5yZXBsYWNlKFwiL3RjcFwiLCBcIlwiKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFV0aWxzLnNwYXduKFt0aGlzLmFyZ3YuY29udGFpbmVyRXhlY3V0YWJsZSwgXCJybVwiLCBcIi12ZlwiLCBgZ2NsLXdhaXQtZm9yLWl0LSR7dGhpcy5qb2JJZH0tJHtzZXJ2aWNlSW5kZXh9LSR7cG9ydE51bX1gXSk7XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGZldGNoVHJpZ2dlckluY2x1ZGUgKCkge1xuICAgICAgICBjb25zdCB7Y3dkLCBzdGF0ZURpcn0gPSB0aGlzLmFyZ3Y7XG5cbiAgICAgICAgZnMubWtkaXJwU3luYyhgJHtjd2R9LyR7c3RhdGVEaXJ9L2luY2x1ZGVzL3RyaWdnZXJzYCk7XG5cbiAgICAgICAgbGV0IGNvbnRlbnRzOiBhbnkgPSB7fTtcblxuICAgICAgICBmb3IgKGNvbnN0IGluY2x1ZGUgb2YgdGhpcy5qb2JEYXRhLnRyaWdnZXI/LmluY2x1ZGUgPz8gW10pIHtcbiAgICAgICAgICAgIGlmIChpbmNsdWRlW1wibG9jYWxcIl0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBleHBhbmRlZEluY2x1ZGUgPSBVdGlscy5leHBhbmRUZXh0KGluY2x1ZGVbXCJsb2NhbFwiXSwgdGhpcy5fdmFyaWFibGVzKTtcbiAgICAgICAgICAgICAgICB2YWxpZGF0ZUluY2x1ZGVMb2NhbChleHBhbmRlZEluY2x1ZGUpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgcmVzb2x2ZUluY2x1ZGVMb2NhbChleHBhbmRlZEluY2x1ZGUsIGN3ZCk7XG4gICAgICAgICAgICAgICAgaWYgKGZpbGVzLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBBc3NlcnRpb25FcnJvcih7bWVzc2FnZTogYExvY2FsIGluY2x1ZGUgZmlsZSBcXGAke2luY2x1ZGVbXCJsb2NhbFwiXX1cXGAgc3BlY2lmaWVkIGluIFxcYC4ke3RoaXMubmFtZX1cXGAgY2Fubm90IGJlIGZvdW5kIWB9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IFBhcnNlci5sb2FkWWFtbChmaWxlLCB7fSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uY29udGVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jb250ZW50LFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaW5jbHVkZVtcImFydGlmYWN0XCJdKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IFBhcnNlci5sb2FkWWFtbChgJHtjd2R9LyR7c3RhdGVEaXJ9L2FydGlmYWN0cy8ke2luY2x1ZGVbXCJqb2JcIl19LyR7aW5jbHVkZVtcImFydGlmYWN0XCJdfWAsIHt9KTtcbiAgICAgICAgICAgICAgICBjb250ZW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgLi4uY29udGVudHMsXG4gICAgICAgICAgICAgICAgICAgIC4uLmNvbnRlbnQsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaW5jbHVkZVtcInByb2plY3RcIl0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLndyaXRlU3RyZWFtcy5tZW1vU3Rkb3V0KGNoYWxrYHtiZ1llbGxvd0JyaWdodCAgV0FSTiB9IFxcYHtibHVlQnJpZ2h0ICR7dGhpcy5uYW1lfS50cmlnZ2VyLmluY2x1ZGUuKi5wcm9qZWN0fVxcYCB3aWxsIGJlIG5vLW9wLiBJdCBpcyBjdXJyZW50bHkgbm90IGltcGxlbWVudGVkXFxuYCk7XG5cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaW5jbHVkZVtcInRlbXBsYXRlXCJdKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53cml0ZVN0cmVhbXMubWVtb1N0ZG91dChjaGFsa2B7YmdZZWxsb3dCcmlnaHQgIFdBUk4gfSBcXGB7Ymx1ZUJyaWdodCAke3RoaXMubmFtZX0udHJpZ2dlci5pbmNsdWRlLioudGVtcGxhdGV9XFxgIHdpbGwgYmUgbm8tb3AuIEl0IGlzIGN1cnJlbnRseSBub3QgaW1wbGVtZW50ZWRcXG5gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCB0YXJnZXQgPSBgJHtjd2R9LyR7c3RhdGVEaXJ9L2luY2x1ZGVzL3RyaWdnZXJzLyR7dGhpcy5uYW1lfS55bWxgO1xuICAgICAgICBmcy53cml0ZUZpbGVTeW5jKHRhcmdldCwgeWFtbC5kdW1wKGNvbnRlbnRzKSk7XG4gICAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2xlYW51cEpvYlJlc291cmNlcyAoam9icz86IEl0ZXJhYmxlPEpvYj4pIHtcbiAgICBpZiAoIWpvYnMpIHJldHVybjtcbiAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuICAgIGZvciAoY29uc3Qgam9iIG9mIGpvYnMpIHtcbiAgICAgICAgcHJvbWlzZXMucHVzaChqb2IuY2xlYW51cFJlc291cmNlcygpKTtcbiAgICB9XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xufVxuIl19