@cartanova/qgrid-cli 2.4.3 → 2.4.5
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/bundle/dist/application/qgrid/qgrid.frame.js +17 -19
- package/bundle/dist/application/qgrid/qgrid.types.js +3 -2
- package/bundle/dist/application/qgrid/token-subscriber.js +23 -9
- package/bundle/dist/application/qgrid/token-trigger-setup.js +4 -4
- package/bundle/dist/application/qgrid/tool-emulation.js +1 -1
- package/bundle/dist/application/sonamu.generated.js +5 -3
- package/bundle/dist/application/sonamu.generated.sso.js +3 -2
- package/bundle/dist/application/token/token.model.js +8 -3
- package/bundle/dist/application/token/token.types.js +8 -3
- package/bundle/dist/i18n/sd.generated.js +2 -1
- package/bundle/dist/index.js +3 -6
- package/bundle/dist/migrations/20260521134025_alter_request_log_steps_alter1.js +3 -9
- package/bundle/dist/migrations/20260706120000_alter_request_logs_add_image_cost.js +1 -1
- package/bundle/dist/migrations/20260710090000_alter_tokens_add_weight.js +41 -0
- package/bundle/dist/server-bootstrap.js +17 -0
- package/bundle/dist/sonamu.config.js +1 -10
- package/bundle/dist/startup-migrations.js +21 -0
- package/bundle/dist/testing/global.js +93 -5
- package/bundle/dist/testing/test-database-name.js +22 -0
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +24 -27
- package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +43 -0
- package/bundle/dist/utils/providers/openai/codex-worker.js +4 -2
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +220 -49
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +60 -14
- package/bundle/src/application/qgrid/qgrid.frame.ts +24 -25
- package/bundle/src/application/qgrid/qgrid.types.ts +1 -0
- package/bundle/src/application/qgrid/token-subscriber.test.ts +102 -0
- package/bundle/src/application/qgrid/token-subscriber.ts +37 -6
- package/bundle/src/application/qgrid/token-trigger-setup.test.ts +9 -0
- package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -2
- package/bundle/src/application/qgrid/token-weight-migration.test.ts +42 -0
- package/bundle/src/application/qgrid/tool-emulation.ts +6 -1
- package/bundle/src/application/sonamu.generated.http +4 -2
- package/bundle/src/application/sonamu.generated.sso.ts +1 -0
- package/bundle/src/application/sonamu.generated.ts +10 -1
- package/bundle/src/application/token/token.entity.json +17 -1
- package/bundle/src/application/token/token.model.test.ts +43 -0
- package/bundle/src/application/token/token.model.ts +18 -2
- package/bundle/src/application/token/token.types.test.ts +11 -0
- package/bundle/src/application/token/token.types.ts +3 -0
- package/bundle/src/i18n/sd.generated.ts +1 -0
- package/bundle/src/index.ts +2 -5
- package/bundle/src/migrations/20260521134025_alter_request_log_steps_alter1.ts +4 -8
- package/bundle/src/migrations/20260706120000_alter_request_logs_add_image_cost.ts +1 -1
- package/bundle/src/migrations/20260710090000_alter_tokens_add_weight.ts +38 -0
- package/bundle/src/server-bootstrap.test.ts +39 -0
- package/bundle/src/server-bootstrap.ts +21 -0
- package/bundle/src/sonamu.config.ts +0 -12
- package/bundle/src/startup-migrations.test.ts +25 -0
- package/bundle/src/startup-migrations.ts +20 -0
- package/bundle/src/testing/global.test.ts +130 -0
- package/bundle/src/testing/global.ts +143 -13
- package/bundle/src/testing/test-database-name.test.ts +38 -0
- package/bundle/src/testing/test-database-name.ts +21 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +75 -45
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +23 -29
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +1 -1
- package/bundle/src/utils/providers/common/smooth-weighted-round-robin.test.ts +73 -0
- package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +48 -0
- package/bundle/src/utils/providers/openai/codex-worker.test.ts +26 -0
- package/bundle/src/utils/providers/openai/codex-worker.ts +3 -1
- package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +304 -12
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +354 -68
- package/bundle/web-dist/client/assets/{index-DsGDBrrH.js → index-D0dRwMp0.js} +3 -3
- package/bundle/web-dist/client/assets/{logs-C6EMtwDn.js → logs-BMzzMMRA.js} +1 -1
- package/bundle/web-dist/client/assets/routes-XqQHRGxI.js +5 -0
- package/bundle/web-dist/client/assets/{sd.generated-BrUnRt0B.js → sd.generated-WA5SGJYZ.js} +1 -1
- package/bundle/web-dist/client/assets/{services.generated-AsEvHbJ7.js → services.generated-DzZLnb7S.js} +1 -1
- package/bundle/web-dist/client/assets/{show-BSW3PE7Z.js → show-63BsotX6.js} +1 -1
- package/bundle/web-dist/client/assets/tokens-C416mWQ-.js +1 -0
- package/bundle/web-dist/client/assets/use-update-token-mutation-BV6msjuy.js +1 -0
- package/bundle/web-dist/client/index.html +2 -2
- package/bundle/web-dist/server/assets/{lazyRouteComponent-BswulcOx.js → lazyRouteComponent-BrPAFtBA.js} +1 -1
- package/bundle/web-dist/server/assets/{logs-Bk9C0ELo.js → logs-CKM6W3W6.js} +3 -3
- package/bundle/web-dist/server/assets/{routes-D9OiKoqa.js → routes-VY2um2KO.js} +140 -9
- package/bundle/web-dist/server/assets/{sd.generated-DRuQSIKo.js → sd.generated-Cwg2f53z.js} +1 -0
- package/bundle/web-dist/server/assets/{services.generated-Dp0uKgpV.js → services.generated-CsotZP44.js} +5 -5
- package/bundle/web-dist/server/assets/{show-3GokIDEJ.js → show-CV2UFjaH.js} +3 -3
- package/bundle/web-dist/server/assets/{tokens-Cjw6cQxZ.js → tokens-DfGj1y2v.js} +5 -5
- package/bundle/web-dist/server/assets/use-update-token-mutation-BL96w-Pg.js +7 -0
- package/bundle/web-dist/server/entry-server.generated.js +7 -7
- package/package.json +1 -1
- package/skills/qgrid/SKILL.md +1 -1
- package/skills/qgrid/references/anthropic-claude-code-runtime.md +2 -2
- package/skills/qgrid/references/cli-env-and-server-boot.md +9 -9
- package/skills/qgrid/references/decision-rationale.md +23 -0
- package/skills/qgrid/references/openai-codex-runtime.md +4 -3
- package/skills/qgrid/references/prompt-cache-and-usage.md +2 -0
- package/skills/qgrid/references/provider-runtime-differences.md +2 -1
- package/skills/qgrid/references/repo-map.md +2 -0
- package/skills/qgrid/references/token-auth-quota-lifecycle.md +8 -3
- package/skills/qgrid/references/verification-and-debugging.md +3 -0
- package/bundle/web-dist/client/assets/routes-De9iuL80.js +0 -5
- package/bundle/web-dist/client/assets/tokens-BMsL6vk9.js +0 -1
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import "../../../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { QuotaThresholdExceededError } from "../../../application/qgrid/qgrid.types.js";
|
|
3
3
|
import { TokenModel } from "../../../application/token/token.model.js";
|
|
4
|
+
import { SmoothWeightedRoundRobin } from "../common/smooth-weighted-round-robin.js";
|
|
4
5
|
import { CodexAppServerWorker } from "./codex-worker.js";
|
|
5
6
|
import { readOpenAIQuotaUsage } from "./openai-quota.js";
|
|
6
7
|
import { handleChatgptAuthTokensRefresh } from "./openai-refresh.js";
|
|
7
8
|
import { getLogger } from "@logtape/logtape";
|
|
9
|
+
import { readFileSync } from "node:fs";
|
|
10
|
+
import { freemem } from "node:os";
|
|
8
11
|
//#region src/utils/providers/openai/openai-dispatcher.ts
|
|
9
12
|
/**
|
|
10
13
|
* OpenAIDispatcher — codex app-server worker pool + 토큰 라우팅.
|
|
@@ -23,15 +26,55 @@ var ImageGenerationError = class extends Error {
|
|
|
23
26
|
}
|
|
24
27
|
};
|
|
25
28
|
const DEFAULT_EFFORT = "low";
|
|
26
|
-
const
|
|
29
|
+
const MAX_OPENAI_WORKERS_PER_TOKEN = 20;
|
|
30
|
+
const DEFAULT_OPENAI_MIN_WORKERS_PER_TOKEN = 5;
|
|
31
|
+
const DEFAULT_OPENAI_MAX_WORKERS_PER_TOKEN = 15;
|
|
27
32
|
const QUEUE_TIMEOUT_MS = 6e4;
|
|
28
33
|
const MAX_QUEUE_SIZE = 50;
|
|
29
34
|
const SPAWN_INTERVAL_MS = 500;
|
|
35
|
+
const OPENAI_WORKER_BASE_RSS_GIB = .71;
|
|
36
|
+
const OPENAI_WORKER_RSS_GIB = .157;
|
|
37
|
+
function boundedInteger(value, fallback, min, max) {
|
|
38
|
+
const parsed = Number(value);
|
|
39
|
+
if (!Number.isFinite(parsed)) return fallback;
|
|
40
|
+
return Math.max(min, Math.min(Math.floor(parsed), max));
|
|
41
|
+
}
|
|
42
|
+
function boundedNumber(value, fallback, min) {
|
|
43
|
+
const parsed = Number(value);
|
|
44
|
+
if (!Number.isFinite(parsed)) return fallback;
|
|
45
|
+
return Math.max(min, parsed);
|
|
46
|
+
}
|
|
47
|
+
function resolveOpenAIWorkerPoolConfig(env = process.env) {
|
|
48
|
+
const autoscale = env.QGRID_OPENAI_AUTOSCALE !== "false" && env.QGRID_OPENAI_AUTOSCALE !== "0";
|
|
49
|
+
const legacyWorkers = boundedInteger(env.QGRID_WORKERS_PER_TOKEN, DEFAULT_OPENAI_MIN_WORKERS_PER_TOKEN, 1, 20);
|
|
50
|
+
const minWorkersPerToken = boundedInteger(env.QGRID_OPENAI_MIN_WORKERS_PER_TOKEN, legacyWorkers, 1, 20);
|
|
51
|
+
const configuredMax = boundedInteger(env.QGRID_OPENAI_MAX_WORKERS_PER_TOKEN, autoscale ? DEFAULT_OPENAI_MAX_WORKERS_PER_TOKEN : minWorkersPerToken, 1, 20);
|
|
52
|
+
return {
|
|
53
|
+
autoscale,
|
|
54
|
+
minWorkersPerToken,
|
|
55
|
+
maxWorkersPerToken: autoscale ? Math.max(minWorkersPerToken, configuredMax) : minWorkersPerToken,
|
|
56
|
+
scaleIntervalMs: boundedInteger(env.QGRID_OPENAI_SCALE_INTERVAL_MS, 5e3, 250, 3e5),
|
|
57
|
+
scaleDownIdleMs: boundedInteger(env.QGRID_OPENAI_SCALE_DOWN_IDLE_MS, 10 * 6e4, 1e3, 1440 * 6e4),
|
|
58
|
+
maxEstimatedRssGiB: boundedNumber(env.QGRID_OPENAI_MAX_ESTIMATED_RSS_GIB, 16, 1),
|
|
59
|
+
minHostAvailableGiB: boundedNumber(env.QGRID_OPENAI_MIN_HOST_AVAILABLE_GIB, 20, 0)
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function estimateOpenAIWorkerRssGiB(totalWorkers) {
|
|
63
|
+
return OPENAI_WORKER_BASE_RSS_GIB + OPENAI_WORKER_RSS_GIB * totalWorkers;
|
|
64
|
+
}
|
|
65
|
+
function readHostAvailableGiB() {
|
|
66
|
+
try {
|
|
67
|
+
const match = readFileSync("/proc/meminfo", "utf8").match(/^MemAvailable:\s+(\d+)\s+kB$/m);
|
|
68
|
+
if (match?.[1]) return Number(match[1]) / 1024 / 1024;
|
|
69
|
+
} catch {}
|
|
70
|
+
return freemem() / 1024 / 1024 / 1024;
|
|
71
|
+
}
|
|
30
72
|
const THREAD_REUSE_ENABLED = process.env.QGRID_OPENAI_THREAD_REUSE !== "false";
|
|
31
73
|
const REUSE_WORKER_WAIT_MS = 5e3;
|
|
32
74
|
const REUSE_WORKER_POLL_MS = 50;
|
|
33
|
-
|
|
34
|
-
|
|
75
|
+
const OPENAI_WORKER_ID_STRIDE = 100;
|
|
76
|
+
function makeOpenAIWorkerId(tokenId, workerIndex) {
|
|
77
|
+
return tokenId * OPENAI_WORKER_ID_STRIDE + workerIndex;
|
|
35
78
|
}
|
|
36
79
|
function sleep(ms) {
|
|
37
80
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -43,37 +86,64 @@ function quotaThresholdExceededMessage(provider, tokens) {
|
|
|
43
86
|
var OpenAIDispatcher = class OpenAIDispatcher {
|
|
44
87
|
workerPool = /* @__PURE__ */ new Map();
|
|
45
88
|
tokenMetadata = /* @__PURE__ */ new Map();
|
|
46
|
-
rrCursor = 0;
|
|
47
89
|
queue = [];
|
|
90
|
+
poolConfig;
|
|
91
|
+
weightedSelector = new SmoothWeightedRoundRobin();
|
|
92
|
+
workerCursorByToken = /* @__PURE__ */ new Map();
|
|
93
|
+
getHostAvailableGiB;
|
|
48
94
|
draining = false;
|
|
49
95
|
drainAgain = false;
|
|
96
|
+
scalerTimer = null;
|
|
97
|
+
scalingPromise = null;
|
|
98
|
+
lastRequestAt = Date.now();
|
|
99
|
+
stopped = false;
|
|
100
|
+
constructor(poolConfig = resolveOpenAIWorkerPoolConfig(), getHostAvailableGiB = readHostAvailableGiB) {
|
|
101
|
+
this.poolConfig = poolConfig;
|
|
102
|
+
this.getHostAvailableGiB = getHostAvailableGiB;
|
|
103
|
+
}
|
|
50
104
|
async start() {
|
|
105
|
+
this.stopped = false;
|
|
51
106
|
const { rows } = await TokenModel.findMany("A");
|
|
52
107
|
const openaiTokens = rows.filter((t) => t.provider === "openai");
|
|
53
|
-
logger.info(`starting ${openaiTokens.length} openai tokens (${
|
|
108
|
+
logger.info(this.poolConfig.autoscale ? `starting ${openaiTokens.length} openai tokens (${this.poolConfig.minWorkersPerToken}-${this.poolConfig.maxWorkersPerToken} workers each, autoscale)` : `starting ${openaiTokens.length} openai tokens (${this.poolConfig.minWorkersPerToken} workers each)`);
|
|
54
109
|
await Promise.allSettled(openaiTokens.map(async (t) => {
|
|
55
|
-
await this.spawnWorkers(t.id, t.name, t.credentials, t.quota_threshold);
|
|
110
|
+
await this.spawnWorkers(t.id, t.name, t.credentials, t.quota_threshold, t.weight);
|
|
56
111
|
if (!t.active) this.onTokenDeactivated(t.id);
|
|
57
112
|
}));
|
|
113
|
+
if (this.poolConfig.autoscale) {
|
|
114
|
+
this.scalerTimer = setInterval(() => this.requestAutoscaleEvaluation(), this.poolConfig.scaleIntervalMs);
|
|
115
|
+
this.scalerTimer.unref?.();
|
|
116
|
+
}
|
|
58
117
|
}
|
|
59
118
|
async stop() {
|
|
119
|
+
this.stopped = true;
|
|
120
|
+
if (this.scalerTimer) {
|
|
121
|
+
clearInterval(this.scalerTimer);
|
|
122
|
+
this.scalerTimer = null;
|
|
123
|
+
}
|
|
124
|
+
await this.scalingPromise?.catch(() => {});
|
|
60
125
|
this.rejectAllQueued("DISPATCHER_SHUTDOWN");
|
|
61
126
|
const kills = [...this.workerPool.values()].flat().map((w) => w.kill());
|
|
62
127
|
await Promise.allSettled(kills);
|
|
128
|
+
for (const id of this.tokenMetadata.keys()) this.weightedSelector.removeToken(id);
|
|
63
129
|
this.workerPool.clear();
|
|
64
130
|
this.tokenMetadata.clear();
|
|
131
|
+
this.workerCursorByToken.clear();
|
|
132
|
+
this.weightedSelector.resetScores();
|
|
65
133
|
this.rateLimitsCache.clear();
|
|
66
134
|
}
|
|
67
|
-
async onTokenAdded(id, name, credentials, quotaThreshold) {
|
|
68
|
-
this.setTokenMetadata(id, name, quotaThreshold);
|
|
135
|
+
async onTokenAdded(id, name, credentials, quotaThreshold, weight = 1) {
|
|
136
|
+
this.setTokenMetadata(id, name, credentials, quotaThreshold, weight);
|
|
69
137
|
if (this.workerPool.has(id)) return;
|
|
70
|
-
await this.spawnWorkers(id, name, credentials, quotaThreshold);
|
|
138
|
+
await this.spawnWorkers(id, name, credentials, quotaThreshold, weight);
|
|
71
139
|
}
|
|
72
140
|
async onTokenRemoved(id) {
|
|
73
141
|
const workers = this.workerPool.get(id) ?? [];
|
|
74
142
|
const tokenName = workers[0]?.tokenName;
|
|
75
143
|
this.workerPool.delete(id);
|
|
76
144
|
this.tokenMetadata.delete(id);
|
|
145
|
+
this.weightedSelector.removeToken(id);
|
|
146
|
+
this.workerCursorByToken.delete(id);
|
|
77
147
|
this.rateLimitsCache.delete(id);
|
|
78
148
|
await Promise.allSettled(workers.map((w) => w.kill()));
|
|
79
149
|
if (this.getAllReadyActiveWorkers().length === 0) this.rejectAllQueued("NO_OPENAI_WORKERS");
|
|
@@ -82,13 +152,13 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
82
152
|
logger.info(`workers removed: ${label} (${workers.length})`);
|
|
83
153
|
}
|
|
84
154
|
}
|
|
85
|
-
async onTokenUpdated(id, name, credentials, quotaThreshold) {
|
|
155
|
+
async onTokenUpdated(id, name, credentials, quotaThreshold, weight = 1) {
|
|
86
156
|
const existing = this.workerPool.get(id) ?? [];
|
|
87
157
|
const renamed = existing.some((w) => w.tokenName !== name);
|
|
88
|
-
this.setTokenMetadata(id, name, quotaThreshold);
|
|
158
|
+
this.setTokenMetadata(id, name, credentials, quotaThreshold, weight);
|
|
89
159
|
if (renamed) this.rateLimitsCache.delete(id);
|
|
90
160
|
if (existing.length === 0) {
|
|
91
|
-
await this.spawnWorkers(id, name, credentials, quotaThreshold);
|
|
161
|
+
await this.spawnWorkers(id, name, credentials, quotaThreshold, weight);
|
|
92
162
|
return;
|
|
93
163
|
}
|
|
94
164
|
if (existing.every((w) => w.canReuseForToken(name, credentials))) {
|
|
@@ -100,14 +170,18 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
100
170
|
this.workerPool.delete(id);
|
|
101
171
|
this.rateLimitsCache.delete(id);
|
|
102
172
|
await Promise.allSettled(existing.map((w) => w.kill()));
|
|
103
|
-
await this.spawnWorkers(id, name, credentials, quotaThreshold);
|
|
173
|
+
await this.spawnWorkers(id, name, credentials, quotaThreshold, weight);
|
|
104
174
|
}
|
|
105
175
|
onTokenDeactivated(id) {
|
|
106
176
|
const workers = this.workerPool.get(id) ?? [];
|
|
107
177
|
const tokenName = workers[0]?.tokenName;
|
|
178
|
+
const metadata = this.tokenMetadata.get(id);
|
|
179
|
+
if (metadata) metadata.active = false;
|
|
180
|
+
const changed = workers.some((worker) => worker.active);
|
|
108
181
|
workers.forEach((w) => {
|
|
109
182
|
w.active = false;
|
|
110
183
|
});
|
|
184
|
+
if (changed) this.weightedSelector.resetScores();
|
|
111
185
|
if (this.getAllReadyActiveWorkers().length === 0) this.rejectAllQueued("NO_ACTIVE_WORKERS");
|
|
112
186
|
const label = tokenName ?? `token ${id}`;
|
|
113
187
|
logger.info(`workers deactivated: ${label}`);
|
|
@@ -115,9 +189,13 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
115
189
|
onTokenActivated(id) {
|
|
116
190
|
const workers = this.workerPool.get(id) ?? [];
|
|
117
191
|
const tokenName = workers[0]?.tokenName;
|
|
192
|
+
const metadata = this.tokenMetadata.get(id);
|
|
193
|
+
if (metadata) metadata.active = true;
|
|
194
|
+
const changed = workers.some((worker) => !worker.active);
|
|
118
195
|
workers.forEach((w) => {
|
|
119
196
|
w.active = true;
|
|
120
197
|
});
|
|
198
|
+
if (changed) this.weightedSelector.resetScores();
|
|
121
199
|
this.requestDrainQueue();
|
|
122
200
|
const label = tokenName ?? `token ${id}`;
|
|
123
201
|
logger.info(`workers activated: ${label}`);
|
|
@@ -126,12 +204,13 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
126
204
|
const next = new Set(rows.map((r) => r.id));
|
|
127
205
|
for (const id of Array.from(this.workerPool.keys())) if (!next.has(id)) await this.onTokenRemoved(id);
|
|
128
206
|
for (const row of rows) {
|
|
129
|
-
if (this.workerPool.has(row.id)) await this.onTokenUpdated(row.id, row.name, row.credentials, row.quotaThreshold);
|
|
130
|
-
else await this.onTokenAdded(row.id, row.name, row.credentials, row.quotaThreshold);
|
|
207
|
+
if (this.workerPool.has(row.id)) await this.onTokenUpdated(row.id, row.name, row.credentials, row.quotaThreshold, row.weight);
|
|
208
|
+
else await this.onTokenAdded(row.id, row.name, row.credentials, row.quotaThreshold, row.weight);
|
|
131
209
|
this.onTokenActivated(row.id);
|
|
132
210
|
}
|
|
133
211
|
}
|
|
134
212
|
async generate(req) {
|
|
213
|
+
this.lastRequestAt = Date.now();
|
|
135
214
|
const excludedTokenIds = /* @__PURE__ */ new Set();
|
|
136
215
|
const reuseWorker = await this.acquireReuseWorker(req, excludedTokenIds);
|
|
137
216
|
if (reuseWorker) {
|
|
@@ -149,6 +228,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
149
228
|
}, excludedTokenIds);
|
|
150
229
|
}
|
|
151
230
|
async generateStream(req, cb) {
|
|
231
|
+
this.lastRequestAt = Date.now();
|
|
152
232
|
if (req.imageGeneration) throw new ImageGenerationError("gate", "image generation is not supported on the streaming path");
|
|
153
233
|
const excludedTokenIds = /* @__PURE__ */ new Set();
|
|
154
234
|
const reuseWorker = await this.acquireReuseWorker(req, excludedTokenIds);
|
|
@@ -184,7 +264,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
184
264
|
}
|
|
185
265
|
}
|
|
186
266
|
findWorkerById(workerId) {
|
|
187
|
-
for (const workers of this.workerPool.values()) for (const w of workers) if (
|
|
267
|
+
for (const workers of this.workerPool.values()) for (const w of workers) if (makeOpenAIWorkerId(w.tokenId, w.workerIndex) === workerId) return w;
|
|
188
268
|
return null;
|
|
189
269
|
}
|
|
190
270
|
async interruptWorkerTurn(threadId, turnId) {
|
|
@@ -195,16 +275,26 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
195
275
|
const eligibility = await this.resolveTokenEligibility(excludedTokenIds);
|
|
196
276
|
if (eligibility.readyActiveTokenIds.size === 0) return null;
|
|
197
277
|
if (eligibility.eligibleTokenIds.size === 0) this.throwQuotaThresholdExceeded(eligibility);
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
278
|
+
const workersByToken = /* @__PURE__ */ new Map();
|
|
279
|
+
for (const worker of this.getAllReadyActiveWorkers()) {
|
|
280
|
+
if (!eligibility.eligibleTokenIds.has(worker.tokenId) || !worker.hasCapacity) continue;
|
|
281
|
+
const workers = workersByToken.get(worker.tokenId) ?? [];
|
|
282
|
+
workers.push(worker);
|
|
283
|
+
workersByToken.set(worker.tokenId, workers);
|
|
284
|
+
}
|
|
285
|
+
const selectedTokenId = this.weightedSelector.select(new Set(workersByToken.keys()));
|
|
286
|
+
if (selectedTokenId === null) return null;
|
|
287
|
+
const workers = workersByToken.get(selectedTokenId);
|
|
288
|
+
const cursor = this.workerCursorByToken.get(selectedTokenId) ?? 0;
|
|
289
|
+
for (let offset = 0; offset < workers.length; offset++) {
|
|
290
|
+
const index = (cursor + offset) % workers.length;
|
|
291
|
+
const worker = workers[index];
|
|
292
|
+
if (worker.tryAcquireTurn()) {
|
|
293
|
+
this.workerCursorByToken.set(selectedTokenId, (index + 1) % workers.length);
|
|
294
|
+
return worker;
|
|
205
295
|
}
|
|
206
296
|
}
|
|
207
|
-
|
|
297
|
+
throw new Error(`weighted token ${selectedTokenId} lost idle capacity during synchronous acquire`);
|
|
208
298
|
}
|
|
209
299
|
getAllReadyActiveWorkers() {
|
|
210
300
|
return [...this.workerPool.values()].flat().filter((w) => w.isReady && w.active);
|
|
@@ -233,6 +323,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
233
323
|
excludedTokenIds: new Set(excludedTokenIds)
|
|
234
324
|
};
|
|
235
325
|
this.queue.push(item);
|
|
326
|
+
this.requestAutoscaleEvaluation();
|
|
236
327
|
});
|
|
237
328
|
}
|
|
238
329
|
removeFromQueue(item) {
|
|
@@ -250,18 +341,16 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
250
341
|
});
|
|
251
342
|
this.queue = [];
|
|
252
343
|
}
|
|
253
|
-
async drainQueue(
|
|
344
|
+
async drainQueue() {
|
|
254
345
|
if (this.draining) {
|
|
255
346
|
this.drainAgain = true;
|
|
256
347
|
return;
|
|
257
348
|
}
|
|
258
349
|
this.draining = true;
|
|
259
|
-
let worker = releasedWorker;
|
|
260
350
|
try {
|
|
261
351
|
do {
|
|
262
352
|
this.drainAgain = false;
|
|
263
|
-
await this.drainQueueOnce(
|
|
264
|
-
worker = void 0;
|
|
353
|
+
await this.drainQueueOnce();
|
|
265
354
|
} while (this.drainAgain);
|
|
266
355
|
} catch (e) {
|
|
267
356
|
logger.warn(`drainQueue failed: ${e.message}`);
|
|
@@ -269,11 +358,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
269
358
|
this.draining = false;
|
|
270
359
|
}
|
|
271
360
|
}
|
|
272
|
-
async drainQueueOnce(
|
|
273
|
-
if (releasedWorker && this.queue.length > 0 && releasedWorker.isReady && releasedWorker.active && await this.isWorkerEligibleForQueueItem(releasedWorker, this.queue[0]) && releasedWorker.tryAcquireTurn()) {
|
|
274
|
-
this.queue.shift().resolve(releasedWorker);
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
361
|
+
async drainQueueOnce() {
|
|
277
362
|
while (this.queue.length > 0) {
|
|
278
363
|
const next = this.queue[0];
|
|
279
364
|
let worker;
|
|
@@ -297,7 +382,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
297
382
|
return await execute(worker);
|
|
298
383
|
} finally {
|
|
299
384
|
worker.releaseTurn();
|
|
300
|
-
this.requestDrainQueue(
|
|
385
|
+
this.requestDrainQueue();
|
|
301
386
|
}
|
|
302
387
|
}
|
|
303
388
|
buildTurnRequest(req, reuseThreadId) {
|
|
@@ -332,7 +417,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
332
417
|
ttftMs: result.ttftMs,
|
|
333
418
|
model: result.model,
|
|
334
419
|
threadCoord: {
|
|
335
|
-
workerId:
|
|
420
|
+
workerId: makeOpenAIWorkerId(worker.tokenId, worker.workerIndex),
|
|
336
421
|
threadId: result.threadId,
|
|
337
422
|
epoch: worker.epoch
|
|
338
423
|
},
|
|
@@ -353,7 +438,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
353
438
|
...result,
|
|
354
439
|
tokenName: worker.tokenName,
|
|
355
440
|
threadCoord: {
|
|
356
|
-
workerId:
|
|
441
|
+
workerId: makeOpenAIWorkerId(worker.tokenId, worker.workerIndex),
|
|
357
442
|
threadId: resolvedThreadId,
|
|
358
443
|
epoch: worker.epoch
|
|
359
444
|
}
|
|
@@ -362,10 +447,10 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
362
447
|
};
|
|
363
448
|
await worker.executeTurnStream(turnReq, wrappedCb, reuseThreadId);
|
|
364
449
|
}
|
|
365
|
-
async spawnWorkers(tokenId, tokenName, credentials, quotaThreshold) {
|
|
366
|
-
this.setTokenMetadata(tokenId, tokenName, quotaThreshold);
|
|
450
|
+
async spawnWorkers(tokenId, tokenName, credentials, quotaThreshold, weight = 1) {
|
|
451
|
+
this.setTokenMetadata(tokenId, tokenName, credentials, quotaThreshold, weight);
|
|
367
452
|
const workers = [];
|
|
368
|
-
for (let i = 0; i <
|
|
453
|
+
for (let i = 0; i < this.poolConfig.minWorkersPerToken; i++) {
|
|
369
454
|
if (i > 0) await sleep(SPAWN_INTERVAL_MS);
|
|
370
455
|
const worker = await this.spawnSingleWorker(tokenId, tokenName, credentials, i);
|
|
371
456
|
if (worker) workers.push(worker);
|
|
@@ -396,6 +481,92 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
396
481
|
return null;
|
|
397
482
|
}
|
|
398
483
|
}
|
|
484
|
+
async evaluateAutoscaling() {
|
|
485
|
+
if (!this.poolConfig.autoscale || this.stopped) return;
|
|
486
|
+
if (this.queue.length > 0) {
|
|
487
|
+
await this.scaleUpOneStep();
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
if (Date.now() - this.lastRequestAt >= this.poolConfig.scaleDownIdleMs) await this.scaleDownOneStep();
|
|
491
|
+
}
|
|
492
|
+
async scaleUpOneStep() {
|
|
493
|
+
if (!this.poolConfig.autoscale || this.stopped) return;
|
|
494
|
+
await this.runScaling(async () => {
|
|
495
|
+
const candidates = [...this.tokenMetadata.entries()].filter(([tokenId, metadata]) => {
|
|
496
|
+
if (!metadata.active) return false;
|
|
497
|
+
return (this.workerPool.get(tokenId)?.length ?? 0) < this.poolConfig.maxWorkersPerToken;
|
|
498
|
+
});
|
|
499
|
+
if (candidates.length === 0) return;
|
|
500
|
+
const projectedRssGiB = estimateOpenAIWorkerRssGiB(this.workerCount + candidates.length);
|
|
501
|
+
if (projectedRssGiB > this.poolConfig.maxEstimatedRssGiB) {
|
|
502
|
+
logger.warn(`openai autoscale blocked: estimated RSS ${projectedRssGiB.toFixed(2)}GiB exceeds ${this.poolConfig.maxEstimatedRssGiB.toFixed(2)}GiB`);
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
const hostAvailableGiB = this.getHostAvailableGiB();
|
|
506
|
+
if (hostAvailableGiB < this.poolConfig.minHostAvailableGiB) {
|
|
507
|
+
logger.warn(`openai autoscale blocked: host available ${hostAvailableGiB.toFixed(2)}GiB below ${this.poolConfig.minHostAvailableGiB.toFixed(2)}GiB`);
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
const added = (await Promise.all(candidates.map(async ([tokenId, metadata]) => {
|
|
511
|
+
const workers = this.workerPool.get(tokenId) ?? [];
|
|
512
|
+
const workerIndex = this.nextAvailableWorkerIndex(workers);
|
|
513
|
+
if (workerIndex >= this.poolConfig.maxWorkersPerToken) return null;
|
|
514
|
+
const worker = await this.spawnSingleWorker(tokenId, metadata.name, metadata.credentials, workerIndex);
|
|
515
|
+
if (!worker) return null;
|
|
516
|
+
const currentMetadata = this.tokenMetadata.get(tokenId);
|
|
517
|
+
const currentWorkers = this.workerPool.get(tokenId);
|
|
518
|
+
if (!currentMetadata?.active || currentMetadata !== metadata || !currentWorkers || currentWorkers.some((entry) => entry.workerIndex === workerIndex)) {
|
|
519
|
+
await worker.kill().catch(() => {});
|
|
520
|
+
return null;
|
|
521
|
+
}
|
|
522
|
+
currentWorkers.push(worker);
|
|
523
|
+
currentWorkers.sort((a, b) => a.workerIndex - b.workerIndex);
|
|
524
|
+
return worker;
|
|
525
|
+
}))).filter((worker) => worker !== null).length;
|
|
526
|
+
if (added > 0) {
|
|
527
|
+
logger.info(`openai autoscale up: +${added} workers (${this.workerCount} total, queue ${this.queue.length})`);
|
|
528
|
+
this.requestDrainQueue();
|
|
529
|
+
if (this.queue.length > 0) setTimeout(() => this.requestAutoscaleEvaluation(), Math.min(this.poolConfig.scaleIntervalMs, 1e3)).unref?.();
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
async scaleDownOneStep() {
|
|
534
|
+
if (!this.poolConfig.autoscale || this.stopped) return;
|
|
535
|
+
await this.runScaling(async () => {
|
|
536
|
+
const removed = [];
|
|
537
|
+
for (const tokenId of this.tokenMetadata.keys()) {
|
|
538
|
+
const workers = this.workerPool.get(tokenId) ?? [];
|
|
539
|
+
if (workers.length <= this.poolConfig.minWorkersPerToken) continue;
|
|
540
|
+
const worker = workers.toSorted((a, b) => b.workerIndex - a.workerIndex).find((entry) => entry.hasCapacity);
|
|
541
|
+
if (!worker) continue;
|
|
542
|
+
this.workerPool.set(tokenId, workers.filter((entry) => entry !== worker));
|
|
543
|
+
removed.push(worker);
|
|
544
|
+
}
|
|
545
|
+
if (removed.length === 0) return;
|
|
546
|
+
await Promise.allSettled(removed.map((worker) => worker.kill()));
|
|
547
|
+
logger.info(`openai autoscale down: -${removed.length} workers (${this.workerCount} total)`);
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
nextAvailableWorkerIndex(workers) {
|
|
551
|
+
const used = new Set(workers.map((worker) => worker.workerIndex));
|
|
552
|
+
for (let index = 0; index < this.poolConfig.maxWorkersPerToken; index++) if (!used.has(index)) return index;
|
|
553
|
+
return this.poolConfig.maxWorkersPerToken;
|
|
554
|
+
}
|
|
555
|
+
requestAutoscaleEvaluation() {
|
|
556
|
+
if (!this.poolConfig.autoscale || this.stopped) return;
|
|
557
|
+
this.evaluateAutoscaling().catch((e) => logger.warn(`openai autoscale evaluation failed: ${e.message}`));
|
|
558
|
+
}
|
|
559
|
+
async runScaling(task) {
|
|
560
|
+
if (this.scalingPromise) {
|
|
561
|
+
await this.scalingPromise;
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
const scaling = task().finally(() => {
|
|
565
|
+
if (this.scalingPromise === scaling) this.scalingPromise = null;
|
|
566
|
+
});
|
|
567
|
+
this.scalingPromise = scaling;
|
|
568
|
+
await scaling;
|
|
569
|
+
}
|
|
399
570
|
rateLimitsCache = /* @__PURE__ */ new Map();
|
|
400
571
|
static RATE_LIMITS_CACHE_TTL = 6e4;
|
|
401
572
|
async getRateLimitsByTokenId(tokenId) {
|
|
@@ -410,14 +581,18 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
410
581
|
this.rateLimitsCache.set(tokenId, entry);
|
|
411
582
|
return entry;
|
|
412
583
|
}
|
|
413
|
-
requestDrainQueue(
|
|
414
|
-
this.drainQueue(
|
|
584
|
+
requestDrainQueue() {
|
|
585
|
+
this.drainQueue().catch((e) => logger.warn(`drainQueue failed: ${e.message}`));
|
|
415
586
|
}
|
|
416
|
-
setTokenMetadata(id, name, quotaThreshold) {
|
|
587
|
+
setTokenMetadata(id, name, credentials, quotaThreshold, weight) {
|
|
417
588
|
this.tokenMetadata.set(id, {
|
|
418
589
|
name,
|
|
419
|
-
|
|
590
|
+
credentials,
|
|
591
|
+
quotaThreshold,
|
|
592
|
+
weight,
|
|
593
|
+
active: this.tokenMetadata.get(id)?.active ?? true
|
|
420
594
|
});
|
|
595
|
+
this.weightedSelector.setToken(id, weight);
|
|
421
596
|
}
|
|
422
597
|
getQuotaThreshold(tokenId) {
|
|
423
598
|
return this.tokenMetadata.get(tokenId)?.quotaThreshold;
|
|
@@ -481,10 +656,6 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
481
656
|
thresholdedTokenCount
|
|
482
657
|
};
|
|
483
658
|
}
|
|
484
|
-
async isWorkerEligibleForQueueItem(worker, item) {
|
|
485
|
-
if (item.excludedTokenIds.has(worker.tokenId)) return false;
|
|
486
|
-
return this.isTokenQuotaEligible(worker.tokenId, worker.tokenName);
|
|
487
|
-
}
|
|
488
659
|
async isTokenQuotaEligible(tokenId, tokenName, excludedTokenIds) {
|
|
489
660
|
const threshold = this.getQuotaThreshold(tokenId);
|
|
490
661
|
if (threshold === void 0 || threshold === null) return true;
|
|
@@ -596,6 +767,6 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
596
767
|
}
|
|
597
768
|
};
|
|
598
769
|
//#endregion
|
|
599
|
-
export { ImageGenerationError, OpenAIDispatcher };
|
|
770
|
+
export { ImageGenerationError, MAX_OPENAI_WORKERS_PER_TOKEN, OPENAI_WORKER_BASE_RSS_GIB, OPENAI_WORKER_RSS_GIB, OpenAIDispatcher, estimateOpenAIWorkerRssGiB, makeOpenAIWorkerId, resolveOpenAIWorkerPoolConfig };
|
|
600
771
|
|
|
601
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLWRpc3BhdGNoZXIuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLWRpc3BhdGNoZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQUlEaXNwYXRjaGVyIOKAlCBjb2RleCBhcHAtc2VydmVyIHdvcmtlciBwb29sICsg7Yag7YGwIOudvOyasO2MhS5cbiAqXG4gKiAtIO2GoO2BsOuLuSBOIHdvcmtlciAoQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpLCDquLDrs7ggM1xuICogLSBpZGxlIHdvcmtlciByb3VuZC1yb2JpbiDshKDtg50gKyDtgZAg64yA6riwICjsoITrtoAgYnVzeSDsi5wpXG4gKiAtIFRva2VuU3Vic2NyaWJlciDsnbTrsqTtirjroZwgd29ya2VyIHBvb2wg64+Z6riw7ZmUXG4gKiAtIGJhY2twcmVzc3VyZTog7YGQIGZ1bGwg65iQ64qUIHRpbWVvdXQg7IucIFNFUlZFUl9CVVNZXG4gKi9cbmltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCI7XG5cbmltcG9ydCB7IFF1b3RhVGhyZXNob2xkRXhjZWVkZWRFcnJvciB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi9xZ3JpZC9xZ3JpZC50eXBlc1wiO1xuaW1wb3J0IHsgVG9rZW5Nb2RlbCB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi5tb2RlbFwiO1xuaW1wb3J0IHsgdHlwZSBPcGVuQUlDcmVkZW50aWFscyB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi50eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBHZXRBY2NvdW50UmF0ZUxpbWl0c1Jlc3BvbnNlIH0gZnJvbSBcIi4uLy4uLy4uL2NvZGV4LXByb3RvY29sL3YyL0dldEFjY291bnRSYXRlTGltaXRzUmVzcG9uc2VcIjtcbmltcG9ydCB7XG4gIHR5cGUgR2VuZXJhdGVSZXF1ZXN0LFxuICB0eXBlIEdlbmVyYXRlUmVzdWx0LFxuICB0eXBlIEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzLFxuICB0eXBlIFByb3ZpZGVyRGlzcGF0Y2hlcixcbn0gZnJvbSBcIi4uL2NvbW1vbi9wcm92aWRlci1kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBDb2RleEFwcFNlcnZlcldvcmtlciwgdHlwZSBTdHJlYW1DYWxsYmFja3MsIHR5cGUgVHVyblJlcXVlc3QgfSBmcm9tIFwiLi9jb2RleC13b3JrZXJcIjtcbmltcG9ydCB7XG4gIHJlYWRPcGVuQUlRdW90YVVzYWdlLFxuICB0eXBlIE9wZW5BSVF1b3RhVXNhZ2VSZXN1bHQsXG4gIHR5cGUgT3BlbkFJUmF0ZUxpbWl0c1dpdGhNZXRhLFxufSBmcm9tIFwiLi9vcGVuYWktcXVvdGFcIjtcbmltcG9ydCB7IGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCB9IGZyb20gXCIuL29wZW5haS1yZWZyZXNoXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGdldExvZ2dlcihbXCJxZ3JpZFwiLCBcIm9wZW5haS1kaXNwYXRjaGVyXCJdKTtcblxuLy8g7J2066+47KeAIOyDneyEsSDsmpTssq3snbQg6rKM7J207Yq4L+yDneyEseyXkCDsi6TtjKjtlojsnYQg65WM7J2YIOq1rOu2hOyekC5cbi8vIC0gXCJnYXRlXCI6IOyCrOyghCDqsoDspp0g7Iuk7YyoKGNhcGFiaWxpdHkv66qo6424IOupgO2LsOuqqOuLrCDrtojstqnsobEpIOKAlCB0dXJuIOuvuOyLpO2WiS5cbi8vIC0gXCJub3RfY2FsbGVkXCI6IHR1cm4g7J2AIOyEseqzte2WiOycvOuCmCDrqqjrjbjsnbQgaW1hZ2UgdG9vbCDsnYQg7Zi47LacIOyViCDtlagg4oCUIOyerOyLnOuPhCDrrLTsnbUo7ZSE66Gs7ZSE7Yq4IOusuOygnCkuXG4vLyAtIFwiaW5jb21wbGV0ZVwiOiB0b29sIOyLnOuPhOuQkOycvOuCmCDsmYTshLEg7J2066+47KeAIOuvuOuPhOywqSDigJQg7J6s7Iuc64+EIO2bhOuztCjshJzrsoTsuKEg7Iuk7YyoL+qxsOu2gCkuXG5leHBvcnQgdHlwZSBJbWFnZUZhaWx1cmVLaW5kID0gXCJnYXRlXCIgfCBcIm5vdF9jYWxsZWRcIiB8IFwiaW5jb21wbGV0ZVwiO1xuXG5leHBvcnQgY2xhc3MgSW1hZ2VHZW5lcmF0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IGtpbmQ6IEltYWdlRmFpbHVyZUtpbmQsXG4gICAgbWVzc2FnZTogc3RyaW5nLFxuICApIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSBcIkltYWdlR2VuZXJhdGlvbkVycm9yXCI7XG4gIH1cbn1cblxuY29uc3QgREVGQVVMVF9FRkZPUlQgPSBcImxvd1wiO1xuY29uc3QgTUFYX1dPUktFUlNfUEVSX1RPS0VOID0gNTtcbmNvbnN0IFdPUktFUlNfUEVSX1RPS0VOID0gTWF0aC5taW4oXG4gIE51bWJlcihwcm9jZXNzLmVudi5RR1JJRF9XT1JLRVJTX1BFUl9UT0tFTiA/PyAzKSxcbiAgTUFYX1dPUktFUlNfUEVSX1RPS0VOLFxuKTtcbmNvbnN0IFFVRVVFX1RJTUVPVVRfTVMgPSA2MF8wMDA7XG5jb25zdCBNQVhfUVVFVUVfU0laRSA9IDUwO1xuY29uc3QgU1BBV05fSU5URVJWQUxfTVMgPSA1MDA7XG5cbi8vIHRocmVhZCDsnqzsgqzsmqkocHJvbXB0IGNhY2hlIOqzoOyglSkuIOuBhOuptCDquLDsobQgXCLrp6QgdHVybiDsg4ggdGhyZWFkICsgaGlzdG9yeSBpbmplY3RcIiDrj5nsnpEuXG5jb25zdCBUSFJFQURfUkVVU0VfRU5BQkxFRCA9IHByb2Nlc3MuZW52LlFHUklEX09QRU5BSV9USFJFQURfUkVVU0UgIT09IFwiZmFsc2VcIjtcbi8vIOyijO2RnCB3b3JrZXIg6rCAIGJ1c3kg7J28IOuVjCBmcmVlIOulvCDquLDri6TrpqzripQg7LWc64yAIOyLnOqwhC4g7LSI6rO8IOyLnCDsg4ggdGhyZWFkIOuhnCDtj7TrsLEuXG5jb25zdCBSRVVTRV9XT1JLRVJfV0FJVF9NUyA9IDVfMDAwO1xuY29uc3QgUkVVU0VfV09SS0VSX1BPTExfTVMgPSA1MDtcblxuLy8gd29ya2VySWQg7ZWp7ISxOiB0b2tlbklkIOyZgCB3b3JrZXJJbmRleCgwLi40KSDrpbwg7ZWY64KY7J2YIOyViOyglSDsiKvsnpDroZwg7J247L2U65SpLlxuZnVuY3Rpb24gbWFrZVdvcmtlcklkKHRva2VuSWQ6IG51bWJlciwgd29ya2VySW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB0b2tlbklkICogMTAgKyB3b3JrZXJJbmRleDtcbn1cblxuZnVuY3Rpb24gc2xlZXAobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbn1cblxuZnVuY3Rpb24gcXVvdGFUaHJlc2hvbGRFeGNlZWRlZE1lc3NhZ2UoXG4gIHByb3ZpZGVyOiBzdHJpbmcsXG4gIHRva2VuczogQXJyYXk8eyB0b2tlbk5hbWU6IHN0cmluZzsgdGhyZXNob2xkOiBudW1iZXIgfT4sXG4pOiBzdHJpbmcge1xuICBjb25zdCBkZXRhaWxzID0gdG9rZW5zXG4gICAgLm1hcCgodG9rZW4pID0+IGAke3Rva2VuLnRva2VuTmFtZX0gKHRocmVzaG9sZCAke3Rva2VuLnRocmVzaG9sZH0lKWApXG4gICAgLmpvaW4oXCIsIFwiKTtcbiAgcmV0dXJuIGRldGFpbHMubGVuZ3RoID4gMFxuICAgID8gYEFsbCAke3Byb3ZpZGVyfSB0b2tlbnMgZXhjZWVkZWQgcXVvdGEgdGhyZXNob2xkOiAke2RldGFpbHN9YFxuICAgIDogYEFsbCAke3Byb3ZpZGVyfSB0b2tlbnMgZXhjZWVkZWQgcXVvdGEgdGhyZXNob2xkYDtcbn1cblxudHlwZSBRdWV1ZUl0ZW0gPSB7XG4gIHJlc29sdmU6ICh3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyKSA9PiB2b2lkO1xuICByZWplY3Q6IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG4gIHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PjtcbiAgYWJvcnRDbGVhbnVwPzogKCkgPT4gdm9pZDtcbiAgZXhjbHVkZWRUb2tlbklkczogU2V0PG51bWJlcj47XG59O1xuXG50eXBlIFRva2VuTWV0YWRhdGEgPSB7XG4gIG5hbWU6IHN0cmluZztcbiAgcXVvdGFUaHJlc2hvbGQ/OiBudW1iZXIgfCBudWxsO1xufTtcblxudHlwZSBUb2tlbkVsaWdpYmlsaXR5ID0ge1xuICByZWFkeUFjdGl2ZVRva2VuSWRzOiBTZXQ8bnVtYmVyPjtcbiAgZWxpZ2libGVUb2tlbklkczogU2V0PG51bWJlcj47XG4gIG92ZXJUaHJlc2hvbGRUb2tlbnM6IEFycmF5PHsgdG9rZW5OYW1lOiBzdHJpbmc7IHRocmVzaG9sZDogbnVtYmVyIH0+O1xuICB0aHJlc2hvbGRlZFRva2VuQ291bnQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCBjbGFzcyBPcGVuQUlEaXNwYXRjaGVyIGltcGxlbWVudHMgUHJvdmlkZXJEaXNwYXRjaGVyIHtcbiAgd29ya2VyUG9vbCA9IG5ldyBNYXA8bnVtYmVyLCBDb2RleEFwcFNlcnZlcldvcmtlcltdPigpO1xuICB0b2tlbk1ldGFkYXRhID0gbmV3IE1hcDxudW1iZXIsIFRva2VuTWV0YWRhdGE+KCk7XG4gIHJyQ3Vyc29yID0gMDtcbiAgcXVldWU6IFF1ZXVlSXRlbVtdID0gW107XG4gIHByaXZhdGUgZHJhaW5pbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSBkcmFpbkFnYWluID0gZmFsc2U7XG5cbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyByb3dzIH0gPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRNYW55KFwiQVwiKTtcbiAgICBjb25zdCBvcGVuYWlUb2tlbnMgPSByb3dzLmZpbHRlcigodCkgPT4gdC5wcm92aWRlciA9PT0gXCJvcGVuYWlcIik7XG4gICAgbG9nZ2VyLmluZm8oXG4gICAgICBgc3RhcnRpbmcgJHtvcGVuYWlUb2tlbnMubGVuZ3RofSBvcGVuYWkgdG9rZW5zICgke1dPUktFUlNfUEVSX1RPS0VOfSB3b3JrZXJzIGVhY2gpYCxcbiAgICApO1xuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFxuICAgICAgb3BlbmFpVG9rZW5zLm1hcChhc3luYyAodCkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VycyhcbiAgICAgICAgICB0LmlkLFxuICAgICAgICAgIHQubmFtZSxcbiAgICAgICAgICB0LmNyZWRlbnRpYWxzIGFzIE9wZW5BSUNyZWRlbnRpYWxzLFxuICAgICAgICAgIHQucXVvdGFfdGhyZXNob2xkLFxuICAgICAgICApO1xuICAgICAgICBpZiAoIXQuYWN0aXZlKSB0aGlzLm9uVG9rZW5EZWFjdGl2YXRlZCh0LmlkKTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBzdG9wKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMucmVqZWN0QWxsUXVldWVkKFwiRElTUEFUQ0hFUl9TSFVURE9XTlwiKTtcbiAgICBjb25zdCBraWxscyA9IFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5tYXAoKHcpID0+IHcua2lsbCgpKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoa2lsbHMpO1xuICAgIHRoaXMud29ya2VyUG9vbC5jbGVhcigpO1xuICAgIHRoaXMudG9rZW5NZXRhZGF0YS5jbGVhcigpO1xuICAgIHRoaXMucmF0ZUxpbWl0c0NhY2hlLmNsZWFyKCk7XG4gIH1cblxuICAvLyDilIDilIAgVG9rZW4gZXZlbnRzIChmcm9tIFRva2VuU3Vic2NyaWJlcikg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgb25Ub2tlbkFkZGVkKFxuICAgIGlkOiBudW1iZXIsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuc2V0VG9rZW5NZXRhZGF0YShpZCwgbmFtZSwgcXVvdGFUaHJlc2hvbGQpO1xuICAgIGlmICh0aGlzLndvcmtlclBvb2wuaGFzKGlkKSkgcmV0dXJuO1xuICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscywgcXVvdGFUaHJlc2hvbGQpO1xuICB9XG5cbiAgYXN5bmMgb25Ub2tlblJlbW92ZWQoaWQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHdvcmtlcnMgPSB0aGlzLndvcmtlclBvb2wuZ2V0KGlkKSA/PyBbXTtcbiAgICBjb25zdCB0b2tlbk5hbWUgPSB3b3JrZXJzWzBdPy50b2tlbk5hbWU7XG4gICAgdGhpcy53b3JrZXJQb29sLmRlbGV0ZShpZCk7XG4gICAgdGhpcy50b2tlbk1ldGFkYXRhLmRlbGV0ZShpZCk7XG4gICAgdGhpcy5yYXRlTGltaXRzQ2FjaGUuZGVsZXRlKGlkKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQod29ya2Vycy5tYXAoKHcpID0+IHcua2lsbCgpKSk7XG4gICAgaWYgKHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIk5PX09QRU5BSV9XT1JLRVJTXCIpO1xuICAgIH1cbiAgICBpZiAod29ya2Vycy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBsYWJlbCA9IHRva2VuTmFtZSA/PyBgdG9rZW4gJHtpZH1gO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlcnMgcmVtb3ZlZDogJHtsYWJlbH0gKCR7d29ya2Vycy5sZW5ndGh9KWApO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIG9uVG9rZW5VcGRhdGVkKFxuICAgIGlkOiBudW1iZXIsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy53b3JrZXJQb29sLmdldChpZCkgPz8gW107XG4gICAgY29uc3QgcmVuYW1lZCA9IGV4aXN0aW5nLnNvbWUoKHcpID0+IHcudG9rZW5OYW1lICE9PSBuYW1lKTtcbiAgICB0aGlzLnNldFRva2VuTWV0YWRhdGEoaWQsIG5hbWUsIHF1b3RhVGhyZXNob2xkKTtcbiAgICBpZiAocmVuYW1lZCkgdGhpcy5yYXRlTGltaXRzQ2FjaGUuZGVsZXRlKGlkKTtcblxuICAgIGlmIChleGlzdGluZy5sZW5ndGggPT09IDApIHtcbiAgICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscywgcXVvdGFUaHJlc2hvbGQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChleGlzdGluZy5ldmVyeSgodykgPT4gdy5jYW5SZXVzZUZvclRva2VuKG5hbWUsIGNyZWRlbnRpYWxzKSkpIHtcbiAgICAgIGV4aXN0aW5nLmZvckVhY2goKHcpID0+IHcudXBkYXRlVG9rZW5TdGF0ZShuYW1lLCBjcmVkZW50aWFscykpO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlcnMgdXBkYXRlZCBpbi1wbGFjZTogJHtuYW1lfWApO1xuICAgICAgdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMud29ya2VyUG9vbC5kZWxldGUoaWQpO1xuICAgIHRoaXMucmF0ZUxpbWl0c0NhY2hlLmRlbGV0ZShpZCk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKGV4aXN0aW5nLm1hcCgodykgPT4gdy5raWxsKCkpKTtcbiAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VycyhpZCwgbmFtZSwgY3JlZGVudGlhbHMsIHF1b3RhVGhyZXNob2xkKTtcbiAgfVxuXG4gIG9uVG9rZW5EZWFjdGl2YXRlZChpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdO1xuICAgIGNvbnN0IHRva2VuTmFtZSA9IHdvcmtlcnNbMF0/LnRva2VuTmFtZTtcbiAgICB3b3JrZXJzLmZvckVhY2goKHcpID0+IHtcbiAgICAgIHcuYWN0aXZlID0gZmFsc2U7XG4gICAgfSk7XG4gICAgaWYgKHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIk5PX0FDVElWRV9XT1JLRVJTXCIpO1xuICAgIH1cbiAgICBjb25zdCBsYWJlbCA9IHRva2VuTmFtZSA/PyBgdG9rZW4gJHtpZH1gO1xuICAgIGxvZ2dlci5pbmZvKGB3b3JrZXJzIGRlYWN0aXZhdGVkOiAke2xhYmVsfWApO1xuICB9XG5cbiAgb25Ub2tlbkFjdGl2YXRlZChpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdO1xuICAgIGNvbnN0IHRva2VuTmFtZSA9IHdvcmtlcnNbMF0/LnRva2VuTmFtZTtcbiAgICB3b3JrZXJzLmZvckVhY2goKHcpID0+IHtcbiAgICAgIHcuYWN0aXZlID0gdHJ1ZTtcbiAgICB9KTtcbiAgICB0aGlzLnJlcXVlc3REcmFpblF1ZXVlKCk7XG4gICAgY29uc3QgbGFiZWwgPSB0b2tlbk5hbWUgPz8gYHRva2VuICR7aWR9YDtcbiAgICBsb2dnZXIuaW5mbyhgd29ya2VycyBhY3RpdmF0ZWQ6ICR7bGFiZWx9YCk7XG4gIH1cblxuICBhc3luYyByZXBsYWNlVG9rZW5zKFxuICAgIHJvd3M6IEFycmF5PHtcbiAgICAgIGlkOiBudW1iZXI7XG4gICAgICBuYW1lOiBzdHJpbmc7XG4gICAgICBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHM7XG4gICAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGw7XG4gICAgfT4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG5leHQgPSBuZXcgU2V0KHJvd3MubWFwKChyKSA9PiByLmlkKSk7XG4gICAgZm9yIChjb25zdCBpZCBvZiBBcnJheS5mcm9tKHRoaXMud29ya2VyUG9vbC5rZXlzKCkpKSB7XG4gICAgICBpZiAoIW5leHQuaGFzKGlkKSkgYXdhaXQgdGhpcy5vblRva2VuUmVtb3ZlZChpZCk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCByb3cgb2Ygcm93cykge1xuICAgICAgaWYgKHRoaXMud29ya2VyUG9vbC5oYXMocm93LmlkKSkge1xuICAgICAgICBhd2FpdCB0aGlzLm9uVG9rZW5VcGRhdGVkKHJvdy5pZCwgcm93Lm5hbWUsIHJvdy5jcmVkZW50aWFscywgcm93LnF1b3RhVGhyZXNob2xkKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHRoaXMub25Ub2tlbkFkZGVkKHJvdy5pZCwgcm93Lm5hbWUsIHJvdy5jcmVkZW50aWFscywgcm93LnF1b3RhVGhyZXNob2xkKTtcbiAgICAgIH1cbiAgICAgIHRoaXMub25Ub2tlbkFjdGl2YXRlZChyb3cuaWQpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBHZW5lcmF0ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBnZW5lcmF0ZShyZXE6IEdlbmVyYXRlUmVxdWVzdCk6IFByb21pc2U8R2VuZXJhdGVSZXN1bHQ+IHtcbiAgICBjb25zdCBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCk7XG4gICAgLy8gdGhyZWFkIOyerOyCrOyaqSDqsr3roZw6IOyijO2RnCB3b3JrZXIg66W8IOygkOycoO2VtCDquLDsobQgdGhyZWFkIOyXkCB0dXJuIOunjCDsi6TtlokuXG4gICAgY29uc3QgcmV1c2VXb3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVSZXVzZVdvcmtlcihyZXEsIGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmIChyZXVzZVdvcmtlcikge1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIGDihrsgJHtyZXVzZVdvcmtlci50b2tlbk5hbWV9WyR7cmV1c2VXb3JrZXIudG9rZW5JZH1dIChyZXVzZSB0aHJlYWQsICR7cmVxLm1vZGVsfSlgLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVBbmRSZWxlYXNlKHJldXNlV29ya2VyLCAodykgPT5cbiAgICAgICAgdGhpcy5leGVjdXRlVHVybih3LCByZXEsIHJlcS5yZXVzZSEudGhyZWFkSWQpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB3b3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVJZGxlV29ya2VyKGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmICh3b3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3b3JrZXIudG9rZW5OYW1lfVske3dvcmtlci50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0pYCk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsICh3KSA9PiB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lbnF1ZXVlKCh3KSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhg4oaSICR7dy50b2tlbk5hbWV9WyR7dy50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0sIHF1ZXVlZClgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSk7XG4gICAgfSwgZXhjbHVkZWRUb2tlbklkcyk7XG4gIH1cblxuICBhc3luYyBnZW5lcmF0ZVN0cmVhbShyZXE6IEdlbmVyYXRlUmVxdWVzdCwgY2I6IEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8g7J2066+47KeAIOyDneyEseydgCBub24tc3RyZWFtIOyghOyaqShSMik6IGNvZGV4IOqwgCDsnbTrr7jsp4Ag64247YOA66W8IOyjvOyngCDslYrqs6Ag7JmE7ISxIGJhc2U2NCDrpbxcbiAgICAvLyDtlZwg67KI7JeQIOykgOuLpC4g7Iqk7Yq466as67CNIOqyveuhnOuhnCDsnbTrr7jsp4Ag7JqU7LKt7J20IOyYpOuptCDrqoXsi5zsoIEg7JeQ65+sLlxuICAgIGlmIChyZXEuaW1hZ2VHZW5lcmF0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW1hZ2VHZW5lcmF0aW9uRXJyb3IoXCJnYXRlXCIsIFwiaW1hZ2UgZ2VuZXJhdGlvbiBpcyBub3Qgc3VwcG9ydGVkIG9uIHRoZSBzdHJlYW1pbmcgcGF0aFwiKTtcbiAgICB9XG4gICAgY29uc3QgZXhjbHVkZWRUb2tlbklkcyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgIGNvbnN0IHJldXNlV29ya2VyID0gYXdhaXQgdGhpcy5hY3F1aXJlUmV1c2VXb3JrZXIocmVxLCBleGNsdWRlZFRva2VuSWRzKTtcbiAgICBpZiAocmV1c2VXb3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihrsgJHtyZXVzZVdvcmtlci50b2tlbk5hbWV9WyR7cmV1c2VXb3JrZXIudG9rZW5JZH1dIChyZXVzZSB0aHJlYWQsIFtzdHJlYW1dKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2UocmV1c2VXb3JrZXIsICh3KSA9PlxuICAgICAgICB0aGlzLmV4ZWN1dGVTdHJlYW1UdXJuKHcsIHJlcSwgY2IsIHJlcS5yZXVzZSEudGhyZWFkSWQpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB3b3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVJZGxlV29ya2VyKGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmICh3b3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3b3JrZXIudG9rZW5OYW1lfVske3dvcmtlci50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0sIFtzdHJlYW1dKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2Uod29ya2VyLCAodykgPT4gdGhpcy5leGVjdXRlU3RyZWFtVHVybih3LCByZXEsIGNiKSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmVucXVldWUoKHcpID0+IHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3LnRva2VuTmFtZX1bJHt3LnRva2VuSWR9XSAobW9kZWw6ICR7cmVxLm1vZGVsfSwgW3N0cmVhbV0sIHF1ZXVlZClgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVTdHJlYW1UdXJuKHcsIHJlcSwgY2IpO1xuICAgIH0sIGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICB9XG5cbiAgLy8gcmV1c2Ug7KKM7ZGc6rCAIOycoO2aqO2VmOuptCDqt7ggd29ya2VyIOulvCBidXN5IOygkOycoO2VtCDrsJjtmZguIOyXhuqxsOuCmCDtj7TrsLEg64yA7IOB7J2066m0IG51bGwuXG4gIC8vIO2PtOuwsSDsgqzsnKA6IOq4sOuKpSBvZmYgLyDsooztkZwg7JeG7J2MIC8gd29ya2VyIOu2gOyerMK37KO97J2MIC8gZXBvY2gg67aI7J287LmYKHJlc3RhcnQpIC8gdGhyZWFkIOyGjOupuCAvXG4gIC8vICAgICAgICAgICAgYnVzeSDrjIDquLAg7YOA7J6E7JWE7JuDLiBudWxsIOuwmO2ZmCDsi5wg7Zi47Lac67aA64qUIOyDiCB0aHJlYWQg6rK966Gc66GcIOynhO2WiS5cbiAgYXN5bmMgYWNxdWlyZVJldXNlV29ya2VyKFxuICAgIHJlcTogR2VuZXJhdGVSZXF1ZXN0LFxuICAgIGV4Y2x1ZGVkVG9rZW5JZHMgPSBuZXcgU2V0PG51bWJlcj4oKSxcbiAgKTogUHJvbWlzZTxDb2RleEFwcFNlcnZlcldvcmtlciB8IG51bGw+IHtcbiAgICAvLyDsnbTrr7jsp4Ag7JqU7LKt7J2AIO2VreyDgSBjb2xkIHRocmVhZChSOCk6IOyerOyCrOyaqSDsooztkZzqsIAg7J6I7Ja064+EIOqxtOuEiOubtOuLpC5cbiAgICAvLyBiYXNlNjQg6rCAIHRocmVhZCDrqZTrqqjrpqzCt+y6kOyLnCBwcmVmaXgg7JeQIOyDgeyjvO2VmOuKlCDqsoPsnYQg66eJ64qU64ukLlxuICAgIGlmIChyZXEuaW1hZ2VHZW5lcmF0aW9uKSByZXR1cm4gbnVsbDtcbiAgICBpZiAoIVRIUkVBRF9SRVVTRV9FTkFCTEVEIHx8ICFyZXEucmV1c2UpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHsgd29ya2VySWQsIHRocmVhZElkLCBlcG9jaCB9ID0gcmVxLnJldXNlO1xuXG4gICAgY29uc3Qgd29ya2VyID0gdGhpcy5maW5kV29ya2VyQnlJZCh3b3JrZXJJZCk7XG4gICAgaWYgKCF3b3JrZXIgfHwgIXdvcmtlci5pc1JlYWR5IHx8ICF3b3JrZXIuYWN0aXZlKSByZXR1cm4gbnVsbDtcbiAgICBpZiAod29ya2VyLmVwb2NoICE9PSBlcG9jaCkgcmV0dXJuIG51bGw7XG4gICAgaWYgKCF3b3JrZXIuaGFzVGhyZWFkKHRocmVhZElkKSkgcmV0dXJuIG51bGw7XG4gICAgaWYgKCEoYXdhaXQgdGhpcy5pc1Rva2VuUXVvdGFFbGlnaWJsZSh3b3JrZXIudG9rZW5JZCwgd29ya2VyLnRva2VuTmFtZSwgZXhjbHVkZWRUb2tlbklkcykpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBSRVVTRV9XT1JLRVJfV0FJVF9NUztcbiAgICBmb3IgKDs7KSB7XG4gICAgICAvLyByZXN0YXJ0KGVwb2NoIOuzgOqyvSkgLyB0aHJlYWQg7IaM66m47J20IOuMgOq4sCDspJHsl5Ag67Cc7IOd7ZWY66m0IO2PtOuwsS5cbiAgICAgIGlmICh3b3JrZXIuZXBvY2ggIT09IGVwb2NoIHx8ICF3b3JrZXIuaGFzVGhyZWFkKHRocmVhZElkKSkgcmV0dXJuIG51bGw7XG4gICAgICBpZiAod29ya2VyLnRyeUFjcXVpcmVUdXJuKCkpIHJldHVybiB3b3JrZXI7XG4gICAgICBpZiAoRGF0ZS5ub3coKSA+PSBkZWFkbGluZSkgcmV0dXJuIG51bGw7XG4gICAgICBhd2FpdCBzbGVlcChSRVVTRV9XT1JLRVJfUE9MTF9NUyk7XG4gICAgfVxuICB9XG5cbiAgZmluZFdvcmtlckJ5SWQod29ya2VySWQ6IG51bWJlcik6IENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbCB7XG4gICAgZm9yIChjb25zdCB3b3JrZXJzIG9mIHRoaXMud29ya2VyUG9vbC52YWx1ZXMoKSkge1xuICAgICAgZm9yIChjb25zdCB3IG9mIHdvcmtlcnMpIHtcbiAgICAgICAgaWYgKG1ha2VXb3JrZXJJZCh3LnRva2VuSWQsIHcud29ya2VySW5kZXgpID09PSB3b3JrZXJJZCkgcmV0dXJuIHc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgYXN5bmMgaW50ZXJydXB0V29ya2VyVHVybih0aHJlYWRJZDogc3RyaW5nLCB0dXJuSWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGFsbFdvcmtlcnMgPSBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkuZmlsdGVyKCh3KSA9PiB3LmlzUmVhZHkpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChhbGxXb3JrZXJzLm1hcCgodykgPT4gdy5pbnRlcnJ1cHRUdXJuKHRocmVhZElkLCB0dXJuSWQpKSk7XG4gIH1cblxuICAvLyDilIDilIAgV29ya2VyIHNlbGVjdGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgLy8gIOq4sOuzuCByb3VuZC1yb2JpblxuICAvLyBUT0RPOiDstpTtm4Qg64uk66W4IOyVjOqzoOumrOymmOycvOuhnCDrs4Dqsr0g6rCA64ql7ZWY6rKMIOyngOybkFxuICBhc3luYyBhY3F1aXJlSWRsZVdvcmtlcihcbiAgICBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCksXG4gICk6IFByb21pc2U8Q29kZXhBcHBTZXJ2ZXJXb3JrZXIgfCBudWxsPiB7XG4gICAgY29uc3QgZWxpZ2liaWxpdHkgPSBhd2FpdCB0aGlzLnJlc29sdmVUb2tlbkVsaWdpYmlsaXR5KGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmIChlbGlnaWJpbGl0eS5yZWFkeUFjdGl2ZVRva2VuSWRzLnNpemUgPT09IDApIHJldHVybiBudWxsO1xuICAgIGlmIChlbGlnaWJpbGl0eS5lbGlnaWJsZVRva2VuSWRzLnNpemUgPT09IDApIHRoaXMudGhyb3dRdW90YVRocmVzaG9sZEV4Y2VlZGVkKGVsaWdpYmlsaXR5KTtcblxuICAgIGNvbnN0IGFsbFdvcmtlcnMgPSB0aGlzLmdldEFsbFJlYWR5QWN0aXZlV29ya2VycygpLmZpbHRlcigodykgPT5cbiAgICAgIGVsaWdpYmlsaXR5LmVsaWdpYmxlVG9rZW5JZHMuaGFzKHcudG9rZW5JZCksXG4gICAgKTtcbiAgICBpZiAoYWxsV29ya2Vycy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWxsV29ya2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgdyA9IGFsbFdvcmtlcnNbKHRoaXMucnJDdXJzb3IgKyBpKSAlIGFsbFdvcmtlcnMubGVuZ3RoXSE7XG4gICAgICBpZiAody50cnlBY3F1aXJlVHVybigpKSB7XG4gICAgICAgIHRoaXMucnJDdXJzb3IgPSAodGhpcy5yckN1cnNvciArIGkgKyAxKSAlIGFsbFdvcmtlcnMubGVuZ3RoO1xuICAgICAgICByZXR1cm4gdztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBnZXRBbGxSZWFkeUFjdGl2ZVdvcmtlcnMoKTogQ29kZXhBcHBTZXJ2ZXJXb3JrZXJbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSAmJiB3LmFjdGl2ZSk7XG4gIH1cblxuICAvLyDilIDilIAgUXVldWUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgZW5xdWV1ZTxUPihcbiAgICBleGVjdXRlOiAod29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcikgPT4gUHJvbWlzZTxUPixcbiAgICBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCksXG4gICk6IFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGVsaWdpYmlsaXR5ID0gYXdhaXQgdGhpcy5yZXNvbHZlVG9rZW5FbGlnaWJpbGl0eShleGNsdWRlZFRva2VuSWRzKTtcbiAgICBpZiAoZWxpZ2liaWxpdHkucmVhZHlBY3RpdmVUb2tlbklkcy5zaXplID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoXCJOT19PUEVOQUlfV09SS0VSU1wiKTtcbiAgICBpZiAoZWxpZ2liaWxpdHkuZWxpZ2libGVUb2tlbklkcy5zaXplID09PSAwKSB0aGlzLnRocm93UXVvdGFUaHJlc2hvbGRFeGNlZWRlZChlbGlnaWJpbGl0eSk7XG4gICAgaWYgKHRoaXMucXVldWUubGVuZ3RoID49IE1BWF9RVUVVRV9TSVpFKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTRVJWRVJfQlVTWVwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8VD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgaXRlbTogUXVldWVJdGVtID0ge1xuICAgICAgICByZXNvbHZlOiAod29ya2VyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsIGV4ZWN1dGUpKVxuICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSxcbiAgICAgICAgcmVqZWN0OiAoZXJyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfSxcbiAgICAgICAgdGltZXI6IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRoaXMucmVtb3ZlRnJvbVF1ZXVlKGl0ZW0pO1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJTRVJWRVJfQlVTWVwiKSk7XG4gICAgICAgIH0sIFFVRVVFX1RJTUVPVVRfTVMpLFxuICAgICAgICBleGNsdWRlZFRva2VuSWRzOiBuZXcgU2V0KGV4Y2x1ZGVkVG9rZW5JZHMpLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5xdWV1ZS5wdXNoKGl0ZW0pO1xuICAgIH0pO1xuICB9XG5cbiAgcmVtb3ZlRnJvbVF1ZXVlKGl0ZW06IFF1ZXVlSXRlbSk6IHZvaWQge1xuICAgIGNsZWFyVGltZW91dChpdGVtLnRpbWVyKTtcbiAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgY29uc3QgaWR4ID0gdGhpcy5xdWV1ZS5pbmRleE9mKGl0ZW0pO1xuICAgIGlmIChpZHggIT09IC0xKSB0aGlzLnF1ZXVlLnNwbGljZShpZHgsIDEpO1xuICB9XG5cbiAgcmVqZWN0QWxsUXVldWVkKHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgZXJyID0gbmV3IEVycm9yKHJlYXNvbik7XG4gICAgdGhpcy5xdWV1ZS5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQoaXRlbS50aW1lcik7XG4gICAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgICBpdGVtLnJlamVjdChlcnIpO1xuICAgIH0pO1xuICAgIHRoaXMucXVldWUgPSBbXTtcbiAgfVxuXG4gIGFzeW5jIGRyYWluUXVldWUocmVsZWFzZWRXb3JrZXI/OiBDb2RleEFwcFNlcnZlcldvcmtlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmRyYWluaW5nKSB7XG4gICAgICB0aGlzLmRyYWluQWdhaW4gPSB0cnVlO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuZHJhaW5pbmcgPSB0cnVlO1xuICAgIGxldCB3b3JrZXIgPSByZWxlYXNlZFdvcmtlcjtcbiAgICB0cnkge1xuICAgICAgZG8ge1xuICAgICAgICB0aGlzLmRyYWluQWdhaW4gPSBmYWxzZTtcbiAgICAgICAgYXdhaXQgdGhpcy5kcmFpblF1ZXVlT25jZSh3b3JrZXIpO1xuICAgICAgICB3b3JrZXIgPSB1bmRlZmluZWQ7XG4gICAgICB9IHdoaWxlICh0aGlzLmRyYWluQWdhaW4pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci53YXJuKGBkcmFpblF1ZXVlIGZhaWxlZDogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5kcmFpbmluZyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZHJhaW5RdWV1ZU9uY2UocmVsZWFzZWRXb3JrZXI/OiBDb2RleEFwcFNlcnZlcldvcmtlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChcbiAgICAgIHJlbGVhc2VkV29ya2VyICYmXG4gICAgICB0aGlzLnF1ZXVlLmxlbmd0aCA+IDAgJiZcbiAgICAgIHJlbGVhc2VkV29ya2VyLmlzUmVhZHkgJiZcbiAgICAgIHJlbGVhc2VkV29ya2VyLmFjdGl2ZSAmJlxuICAgICAgKGF3YWl0IHRoaXMuaXNXb3JrZXJFbGlnaWJsZUZvclF1ZXVlSXRlbShyZWxlYXNlZFdvcmtlciwgdGhpcy5xdWV1ZVswXSEpKSAmJlxuICAgICAgcmVsZWFzZWRXb3JrZXIudHJ5QWNxdWlyZVR1cm4oKVxuICAgICkge1xuICAgICAgY29uc3QgbmV4dCA9IHRoaXMucXVldWUuc2hpZnQoKSE7XG4gICAgICBuZXh0LnJlc29sdmUocmVsZWFzZWRXb3JrZXIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdoaWxlICh0aGlzLnF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IG5leHQgPSB0aGlzLnF1ZXVlWzBdITtcbiAgICAgIGxldCB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbDtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdvcmtlciA9IGF3YWl0IHRoaXMuYWNxdWlyZUlkbGVXb3JrZXIobmV4dC5leGNsdWRlZFRva2VuSWRzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBRdW90YVRocmVzaG9sZEV4Y2VlZGVkRXJyb3IpIHtcbiAgICAgICAgICB0aGlzLnF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgbmV4dC5yZWplY3QoZSk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIGlmICghd29ya2VyKSBicmVhaztcbiAgICAgIHRoaXMucXVldWUuc2hpZnQoKTtcbiAgICAgIG5leHQucmVzb2x2ZSh3b3JrZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBFeGVjdXRpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgZXhlY3V0ZUFuZFJlbGVhc2U8VD4oXG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcixcbiAgICBleGVjdXRlOiAod29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcikgPT4gUHJvbWlzZTxUPixcbiAgKTogUHJvbWlzZTxUPiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBleGVjdXRlKHdvcmtlcik7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHdvcmtlci5yZWxlYXNlVHVybigpO1xuICAgICAgdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSh3b3JrZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIHJldXNlVGhyZWFkSWQg6rCAIOyeiOycvOuptCDquLDsobQgdGhyZWFkIOyXkCBkZWx0YShyZXVzZUlucHV0KeunjCwg7JeG7Jy866m0IOyDiCB0aHJlYWQg7JeQIOyghOyytFxuICAvLyBwcm9tcHQoY29sZElucHV0KSArIGhpc3RvcnkgaW5qZWN0LiByZXVzZSDqsIAgZGlzcGF0Y2hlciDri6jsl5DshJwg7Y+067Cx65CY66m0IO2bhOyekOuhnCDrlqjslrTsp4Tri6QuXG4gIHByaXZhdGUgYnVpbGRUdXJuUmVxdWVzdChyZXE6IEdlbmVyYXRlUmVxdWVzdCwgcmV1c2VUaHJlYWRJZD86IHN0cmluZyk6IFR1cm5SZXF1ZXN0IHtcbiAgICBjb25zdCByZXVzaW5nID0gcmV1c2VUaHJlYWRJZCAhPT0gdW5kZWZpbmVkO1xuICAgIHJldHVybiB7XG4gICAgICBpbnB1dDogcmV1c2luZyAmJiByZXEucmV1c2VJbnB1dCA/IHJlcS5yZXVzZUlucHV0IDogcmVxLmNvbGRJbnB1dCxcbiAgICAgIGhpc3Rvcnk6IHJldXNpbmcgPyB1bmRlZmluZWQgOiByZXEuY29sZEhpc3RvcnksXG4gICAgICBkZXZlbG9wZXJJbnN0cnVjdGlvbnM6IHJlcS5zeXN0ZW1Qcm9tcHQsXG4gICAgICBvdXRwdXRTY2hlbWE6IHJlcS5vdXRwdXRTY2hlbWEsXG4gICAgICBlZmZvcnQ6IHJlcS5lZmZvcnQgPz8gREVGQVVMVF9FRkZPUlQsXG4gICAgICBtb2RlbDogcmVxLm1vZGVsLFxuICAgICAgdmVyYm9zaXR5OiByZXEudmVyYm9zaXR5LFxuICAgICAgcmVhc29uaW5nU3VtbWFyeTogcmVxLnJlYXNvbmluZ1N1bW1hcnksXG4gICAgICBzZXJ2aWNlVGllcjogcmVxLnNlcnZpY2VUaWVyLFxuICAgICAgaW1hZ2VHZW5lcmF0aW9uOiByZXEuaW1hZ2VHZW5lcmF0aW9uLFxuICAgICAgaW1hZ2VHZW5lcmF0aW9uT3B0aW9uczogcmVxLmltYWdlR2VuZXJhdGlvbk9wdGlvbnMsXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGV4ZWN1dGVUdXJuKFxuICAgIHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIsXG4gICAgcmVxOiBHZW5lcmF0ZVJlcXVlc3QsXG4gICAgcmV1c2VUaHJlYWRJZD86IHN0cmluZyxcbiAgKTogUHJvbWlzZTxHZW5lcmF0ZVJlc3VsdD4ge1xuICAgIC8vIOydtOuvuOyngCDsmpTssq0g7IKs7KCEIOqyjOydtO2KuChSNSk6IOuwsOygleuQnCB3b3JrZXIg7J2YIGNhcGFiaWxpdHkgKyDsoIHsmqkg66qo6424IOupgO2LsOuqqOuLrC5cbiAgICAvLyDrtojstqnsobHsnbTrqbQgdHVybiDsnYQg7Iuk7ZaJ7ZWY7KeAIOyViuqzoCDrqoXsi5zsoIEg7JeQ65+sLlxuICAgIGlmIChyZXEuaW1hZ2VHZW5lcmF0aW9uKSB7XG4gICAgICBjb25zdCByZWFzb24gPSBhd2FpdCB3b3JrZXIuY2hlY2tJbWFnZUdlbmVyYXRpb25TdXBwb3J0KHJlcS5tb2RlbCk7XG4gICAgICBpZiAocmVhc29uKSB0aHJvdyBuZXcgSW1hZ2VHZW5lcmF0aW9uRXJyb3IoXCJnYXRlXCIsIHJlYXNvbik7XG4gICAgfVxuXG4gICAgY29uc3QgdHVyblJlcSA9IHRoaXMuYnVpbGRUdXJuUmVxdWVzdChyZXEsIHJldXNlVGhyZWFkSWQpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdvcmtlci5leGVjdXRlVHVybih0dXJuUmVxLCByZXVzZVRocmVhZElkKTtcblxuICAgIC8vIOydtOuvuOyngCAw6rCcIOyLpO2MqCDrtoTrpZgoUjYpOiB0b29sIOuvuO2YuOy2nCjsnqzsi5zrj4Qg66y07J21KSB2cyDsi5zrj4Qg7ZuEIOuvuOyZhOyEsSjsnqzsi5zrj4Qg7ZuE67O0KS5cbiAgICBpZiAocmVxLmltYWdlR2VuZXJhdGlvbiAmJiAoIXJlc3VsdC5pbWFnZXMgfHwgcmVzdWx0LmltYWdlcy5sZW5ndGggPT09IDApKSB7XG4gICAgICB0aHJvdyByZXN1bHQuaW1hZ2VBdHRlbXB0ZWRcbiAgICAgICAgPyBuZXcgSW1hZ2VHZW5lcmF0aW9uRXJyb3IoXCJpbmNvbXBsZXRlXCIsIFwiaW1hZ2UgdG9vbCByYW4gYnV0IHByb2R1Y2VkIG5vIGNvbXBsZXRlZCBpbWFnZVwiKVxuICAgICAgICA6IG5ldyBJbWFnZUdlbmVyYXRpb25FcnJvcihcIm5vdF9jYWxsZWRcIiwgXCJtb2RlbCBkaWQgbm90IGNhbGwgdGhlIGltYWdlX2dlbmVyYXRpb24gdG9vbFwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdGV4dDogcmVzdWx0LnRleHQsXG4gICAgICB0b2tlbk5hbWU6IHdvcmtlci50b2tlbk5hbWUsXG4gICAgICB1c2FnZTogcmVzdWx0LnVzYWdlLFxuICAgICAgZHVyYXRpb25NczogcmVzdWx0LmR1cmF0aW9uTXMsXG4gICAgICB0dGZ0TXM6IHJlc3VsdC50dGZ0TXMsXG4gICAgICBtb2RlbDogcmVzdWx0Lm1vZGVsLFxuICAgICAgdGhyZWFkQ29vcmQ6IHtcbiAgICAgICAgd29ya2VySWQ6IG1ha2VXb3JrZXJJZCh3b3JrZXIudG9rZW5JZCwgd29ya2VyLndvcmtlckluZGV4KSxcbiAgICAgICAgdGhyZWFkSWQ6IHJlc3VsdC50aHJlYWRJZCxcbiAgICAgICAgZXBvY2g6IHdvcmtlci5lcG9jaCxcbiAgICAgIH0sXG4gICAgICBpbWFnZXM6IHJlc3VsdC5pbWFnZXMsXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGV4ZWN1dGVTdHJlYW1UdXJuKFxuICAgIHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIsXG4gICAgcmVxOiBHZW5lcmF0ZVJlcXVlc3QsXG4gICAgY2I6IEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzLFxuICAgIHJldXNlVGhyZWFkSWQ/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHR1cm5SZXEgPSB0aGlzLmJ1aWxkVHVyblJlcXVlc3QocmVxLCByZXVzZVRocmVhZElkKTtcbiAgICAvLyB3b3JrZXIg7J2YIFR1cm5SZXN1bHQg7JeQIHRva2VuTmFtZS90aHJlYWRDb29yZCDrpbwg67aZ7JesIOyDgeychChHZW5lcmF0ZVJlc3VsdCnroZwg7Jis66aw64ukLlxuICAgIC8vIHRocmVhZElkIOuKlCDsg4ggdGhyZWFkIOuptCBvblRocmVhZElkIOuhnCDtmZXsoJXrkJjrr4DroZwg66+466asIOuztOq0gO2VtCDrkZDqs6Agb25Db21wbGV0ZSDrlYwg7J2964qU64ukLlxuICAgIGxldCByZXNvbHZlZFRocmVhZElkID0gcmV1c2VUaHJlYWRJZCA/PyBcIlwiO1xuICAgIGNvbnN0IHdyYXBwZWRDYjogU3RyZWFtQ2FsbGJhY2tzID0ge1xuICAgICAgLi4uY2IsXG4gICAgICBvblRocmVhZElkOiAodGhyZWFkSWQpID0+IHtcbiAgICAgICAgcmVzb2x2ZWRUaHJlYWRJZCA9IHRocmVhZElkO1xuICAgICAgICBjYi5vblRocmVhZElkPy4odGhyZWFkSWQpO1xuICAgICAgfSxcbiAgICAgIG9uQ29tcGxldGU6IChyZXN1bHQpID0+IHtcbiAgICAgICAgY2Iub25Db21wbGV0ZSh7XG4gICAgICAgICAgLi4ucmVzdWx0LFxuICAgICAgICAgIHRva2VuTmFtZTogd29ya2VyLnRva2VuTmFtZSxcbiAgICAgICAgICB0aHJlYWRDb29yZDoge1xuICAgICAgICAgICAgd29ya2VySWQ6IG1ha2VXb3JrZXJJZCh3b3JrZXIudG9rZW5JZCwgd29ya2VyLndvcmtlckluZGV4KSxcbiAgICAgICAgICAgIHRocmVhZElkOiByZXNvbHZlZFRocmVhZElkLFxuICAgICAgICAgICAgZXBvY2g6IHdvcmtlci5lcG9jaCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgfTtcbiAgICBhd2FpdCB3b3JrZXIuZXhlY3V0ZVR1cm5TdHJlYW0odHVyblJlcSwgd3JhcHBlZENiLCByZXVzZVRocmVhZElkKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBTcGF3biDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBzcGF3bldvcmtlcnMoXG4gICAgdG9rZW5JZDogbnVtYmVyLFxuICAgIHRva2VuTmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuc2V0VG9rZW5NZXRhZGF0YSh0b2tlbklkLCB0b2tlbk5hbWUsIHF1b3RhVGhyZXNob2xkKTtcbiAgICBjb25zdCB3b3JrZXJzOiBDb2RleEFwcFNlcnZlcldvcmtlcltdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBXT1JLRVJTX1BFUl9UT0tFTjsgaSsrKSB7XG4gICAgICBpZiAoaSA+IDApIGF3YWl0IHNsZWVwKFNQQVdOX0lOVEVSVkFMX01TKTtcbiAgICAgIGNvbnN0IHdvcmtlciA9IGF3YWl0IHRoaXMuc3Bhd25TaW5nbGVXb3JrZXIodG9rZW5JZCwgdG9rZW5OYW1lLCBjcmVkZW50aWFscywgaSk7XG4gICAgICBpZiAod29ya2VyKSB3b3JrZXJzLnB1c2god29ya2VyKTtcbiAgICB9XG4gICAgaWYgKHdvcmtlcnMubGVuZ3RoID4gMCkgdGhpcy53b3JrZXJQb29sLnNldCh0b2tlbklkLCB3b3JrZXJzKTtcbiAgfVxuXG4gIGFzeW5jIHNwYXduU2luZ2xlV29ya2VyKFxuICAgIHRva2VuSWQ6IG51bWJlcixcbiAgICB0b2tlbk5hbWU6IHN0cmluZyxcbiAgICBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHMsXG4gICAgd29ya2VySW5kZXg6IG51bWJlcixcbiAgKTogUHJvbWlzZTxDb2RleEFwcFNlcnZlcldvcmtlciB8IG51bGw+IHtcbiAgICBjb25zdCB3b3JrZXIgPSBuZXcgQ29kZXhBcHBTZXJ2ZXJXb3JrZXIoe1xuICAgICAgdG9rZW5JZCxcbiAgICAgIHRva2VuTmFtZSxcbiAgICAgIGFjY2Vzc1Rva2VuOiBjcmVkZW50aWFscy5hY2Nlc3NUb2tlbixcbiAgICAgIGFjY291bnRJZDogY3JlZGVudGlhbHMuYWNjb3VudElkLFxuICAgICAgcGxhblR5cGU6IGNyZWRlbnRpYWxzLnBsYW5UeXBlLFxuICAgICAgd29ya2VySW5kZXgsXG4gICAgfSk7XG5cbiAgICB3b3JrZXIub25SZWFkeSA9ICgpID0+IHRoaXMucmVxdWVzdERyYWluUXVldWUoKTtcblxuICAgIHdvcmtlci5zZXRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihhc3luYyAobWV0aG9kKSA9PiB7XG4gICAgICBpZiAobWV0aG9kID09PSBcImFjY291bnQvY2hhdGdwdEF1dGhUb2tlbnMvcmVmcmVzaFwiKSB7XG4gICAgICAgIHJldHVybiBoYW5kbGVDaGF0Z3B0QXV0aFRva2Vuc1JlZnJlc2godG9rZW5JZCk7XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuaGFuZGxlZCBzZXJ2ZXItcmVxdWVzdDogJHttZXRob2R9YCk7XG4gICAgfSk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgd29ya2VyLmluaXRpYWxpemUoKTtcbiAgICAgIGxvZ2dlci5pbmZvKGB3b3JrZXIgc3Bhd25lZDogJHt0b2tlbk5hbWV9WyR7d29ya2VySW5kZXh9XWApO1xuICAgICAgcmV0dXJuIHdvcmtlcjtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2dnZXIud2Fybihgd29ya2VyIHNwYXduIGZhaWxlZDogJHt0b2tlbk5hbWV9WyR7d29ya2VySW5kZXh9XTogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICAgIGF3YWl0IHdvcmtlci5raWxsKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLy8g4pSA4pSAIFJhdGUgbGltaXRzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIHJhdGVMaW1pdHNDYWNoZSA9IG5ldyBNYXA8bnVtYmVyLCB7IGRhdGE6IEdldEFjY291bnRSYXRlTGltaXRzUmVzcG9uc2U7IGNhY2hlZEF0OiBudW1iZXIgfT4oKTtcbiAgc3RhdGljIHJlYWRvbmx5IFJBVEVfTElNSVRTX0NBQ0hFX1RUTCA9IDYwXzAwMDtcblxuICBhc3luYyBnZXRSYXRlTGltaXRzQnlUb2tlbklkKHRva2VuSWQ6IG51bWJlcik6IFByb21pc2U8T3BlbkFJUmF0ZUxpbWl0c1dpdGhNZXRhPiB7XG4gICAgY29uc3QgY2FjaGVkID0gdGhpcy5yYXRlTGltaXRzQ2FjaGUuZ2V0KHRva2VuSWQpO1xuICAgIGlmIChjYWNoZWQgJiYgRGF0ZS5ub3coKSAtIGNhY2hlZC5jYWNoZWRBdCA8IE9wZW5BSURpc3BhdGNoZXIuUkFURV9MSU1JVFNfQ0FDSEVfVFRMKSB7XG4gICAgICByZXR1cm4gY2FjaGVkO1xuICAgIH1cblxuICAgIGNvbnN0IHdvcmtlciA9ICh0aGlzLndvcmtlclBvb2wuZ2V0KHRva2VuSWQpID8/IFtdKS5maW5kKCh3KSA9PiB3LmlzUmVhZHkpO1xuICAgIGlmICghd29ya2VyKSB0aHJvdyBuZXcgRXJyb3IoXCJubyByZWFkeSBvcGVuYWkgd29ya2Vyc1wiKTtcbiAgICBjb25zdCBkYXRhID0gKGF3YWl0IHdvcmtlci5nZXRSYXRlTGltaXRzKCkpIGFzIEdldEFjY291bnRSYXRlTGltaXRzUmVzcG9uc2U7XG4gICAgY29uc3QgZW50cnkgPSB7IGRhdGEsIGNhY2hlZEF0OiBEYXRlLm5vdygpIH07XG4gICAgdGhpcy5yYXRlTGltaXRzQ2FjaGUuc2V0KHRva2VuSWQsIGVudHJ5KTtcbiAgICByZXR1cm4gZW50cnk7XG4gIH1cblxuICBwcml2YXRlIHJlcXVlc3REcmFpblF1ZXVlKHJlbGVhc2VkV29ya2VyPzogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMuZHJhaW5RdWV1ZShyZWxlYXNlZFdvcmtlcikuY2F0Y2goKGUpID0+XG4gICAgICBsb2dnZXIud2FybihgZHJhaW5RdWV1ZSBmYWlsZWQ6ICR7KGUgYXMgRXJyb3IpLm1lc3NhZ2V9YCksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0VG9rZW5NZXRhZGF0YShpZDogbnVtYmVyLCBuYW1lOiBzdHJpbmcsIHF1b3RhVGhyZXNob2xkPzogbnVtYmVyIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMudG9rZW5NZXRhZGF0YS5zZXQoaWQsIHsgbmFtZSwgcXVvdGFUaHJlc2hvbGQgfSk7XG4gIH1cblxuICBwcml2YXRlIGdldFF1b3RhVGhyZXNob2xkKHRva2VuSWQ6IG51bWJlcik6IG51bWJlciB8IG51bGwgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnRva2VuTWV0YWRhdGEuZ2V0KHRva2VuSWQpPy5xdW90YVRocmVzaG9sZDtcbiAgfVxuXG4gIHByaXZhdGUgaGFzUXVvdGFUaHJlc2hvbGQodG9rZW5JZDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRRdW90YVRocmVzaG9sZCh0b2tlbklkKTtcbiAgICByZXR1cm4gdGhyZXNob2xkICE9PSB1bmRlZmluZWQgJiYgdGhyZXNob2xkICE9PSBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZXNvbHZlVG9rZW5FbGlnaWJpbGl0eShleGNsdWRlZFRva2VuSWRzOiBTZXQ8bnVtYmVyPik6IFByb21pc2U8VG9rZW5FbGlnaWJpbGl0eT4ge1xuICAgIGNvbnN0IHdvcmtlcnMgPSB0aGlzLmdldEFsbFJlYWR5QWN0aXZlV29ya2VycygpO1xuICAgIGNvbnN0IGJ5VG9rZW4gPSBuZXcgTWFwPG51bWJlciwgc3RyaW5nPigpO1xuICAgIGZvciAoY29uc3Qgd29ya2VyIG9mIHdvcmtlcnMpIHtcbiAgICAgIGlmICghYnlUb2tlbi5oYXMod29ya2VyLnRva2VuSWQpKSBieVRva2VuLnNldCh3b3JrZXIudG9rZW5JZCwgd29ya2VyLnRva2VuTmFtZSk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVhZHlBY3RpdmVUb2tlbklkcyA9IG5ldyBTZXQoYnlUb2tlbi5rZXlzKCkpO1xuICAgIGNvbnN0IGVsaWdpYmxlVG9rZW5JZHMgPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgICBjb25zdCBvdmVyVGhyZXNob2xkVG9rZW5zOiBBcnJheTx7IHRva2VuTmFtZTogc3RyaW5nOyB0aHJlc2hvbGQ6IG51bWJlciB9PiA9IFtdO1xuICAgIGxldCB0aHJlc2hvbGRlZFRva2VuQ291bnQgPSAwO1xuXG4gICAgY29uc3QgZW50cmllcyA9IEFycmF5LmZyb20oYnlUb2tlbi5lbnRyaWVzKCkpO1xuICAgIGNvbnN0IGNoZWNrcyA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgIGVudHJpZXMubWFwKGFzeW5jIChbdG9rZW5JZCwgdG9rZW5OYW1lXSkgPT4ge1xuICAgICAgICBpZiAoZXhjbHVkZWRUb2tlbklkcy5oYXModG9rZW5JZCkpIHtcbiAgICAgICAgICB0aHJlc2hvbGRlZFRva2VuQ291bnQrKztcbiAgICAgICAgICByZXR1cm4geyB0b2tlbklkLCB0b2tlbk5hbWUsIGVsaWdpYmxlOiBmYWxzZSB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5oYXNRdW90YVRocmVzaG9sZCh0b2tlbklkKSkge1xuICAgICAgICAgIHJldHVybiB7IHRva2VuSWQsIHRva2VuTmFtZSwgZWxpZ2libGU6IHRydWUgfTtcbiAgICAgICAgfVxuICAgICAgICB0aHJlc2hvbGRlZFRva2VuQ291bnQrKztcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0b2tlbklkLFxuICAgICAgICAgIHRva2VuTmFtZSxcbiAgICAgICAgICBlbGlnaWJsZTogYXdhaXQgdGhpcy5pc1Rva2VuUXVvdGFFbGlnaWJsZSh0b2tlbklkLCB0b2tlbk5hbWUpLFxuICAgICAgICB9O1xuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNoZWNrcy5mb3JFYWNoKChjaGVjaywgaW5kZXgpID0+IHtcbiAgICAgIGlmIChjaGVjay5zdGF0dXMgPT09IFwiZnVsZmlsbGVkXCIpIHtcbiAgICAgICAgaWYgKGNoZWNrLnZhbHVlLmVsaWdpYmxlKSB7XG4gICAgICAgICAgZWxpZ2libGVUb2tlbklkcy5hZGQoY2hlY2sudmFsdWUudG9rZW5JZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRRdW90YVRocmVzaG9sZChjaGVjay52YWx1ZS50b2tlbklkKTtcbiAgICAgICAgICBpZiAodGhyZXNob2xkICE9PSB1bmRlZmluZWQgJiYgdGhyZXNob2xkICE9PSBudWxsKSB7XG4gICAgICAgICAgICBvdmVyVGhyZXNob2xkVG9rZW5zLnB1c2goeyB0b2tlbk5hbWU6IGNoZWNrLnZhbHVlLnRva2VuTmFtZSwgdGhyZXNob2xkIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVudHJ5ID0gZW50cmllc1tpbmRleF07XG4gICAgICBpZiAoZW50cnkpIHtcbiAgICAgICAgY29uc3QgW3Rva2VuSWQsIHRva2VuTmFtZV0gPSBlbnRyeTtcbiAgICAgICAgdGhpcy5sb2dRdW90YUxvb2t1cEZhaWxPcGVuKHRva2VuSWQsIHRva2VuTmFtZSwgU3RyaW5nKGNoZWNrLnJlYXNvbikpO1xuICAgICAgICBlbGlnaWJsZVRva2VuSWRzLmFkZCh0b2tlbklkKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB7IHJlYWR5QWN0aXZlVG9rZW5JZHMsIGVsaWdpYmxlVG9rZW5JZHMsIG92ZXJUaHJlc2hvbGRUb2tlbnMsIHRocmVzaG9sZGVkVG9rZW5Db3VudCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc1dvcmtlckVsaWdpYmxlRm9yUXVldWVJdGVtKFxuICAgIHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIsXG4gICAgaXRlbTogUXVldWVJdGVtLFxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAoaXRlbS5leGNsdWRlZFRva2VuSWRzLmhhcyh3b3JrZXIudG9rZW5JZCkpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdGhpcy5pc1Rva2VuUXVvdGFFbGlnaWJsZSh3b3JrZXIudG9rZW5JZCwgd29ya2VyLnRva2VuTmFtZSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzVG9rZW5RdW90YUVsaWdpYmxlKFxuICAgIHRva2VuSWQ6IG51bWJlcixcbiAgICB0b2tlbk5hbWU6IHN0cmluZyxcbiAgICBleGNsdWRlZFRva2VuSWRzPzogU2V0PG51bWJlcj4sXG4gICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHRocmVzaG9sZCA9IHRoaXMuZ2V0UXVvdGFUaHJlc2hvbGQodG9rZW5JZCk7XG4gICAgaWYgKHRocmVzaG9sZCA9PT0gdW5kZWZpbmVkIHx8IHRocmVzaG9sZCA9PT0gbnVsbCkgcmV0dXJuIHRydWU7XG5cbiAgICBsZXQgcmVzdWx0OiBPcGVuQUlRdW90YVVzYWdlUmVzdWx0O1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCByZWFkT3BlbkFJUXVvdGFVc2FnZSgoKSA9PiB0aGlzLmdldFJhdGVMaW1pdHNCeVRva2VuSWQodG9rZW5JZCkpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMubG9nUXVvdGFMb29rdXBGYWlsT3Blbih0b2tlbklkLCB0b2tlbk5hbWUsIChlIGFzIEVycm9yKS5tZXNzYWdlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmIChyZXN1bHQua2luZCA9PT0gXCJsb29rdXBfZmFpbGVkXCIpIHtcbiAgICAgIHRoaXMubG9nUXVvdGFMb29rdXBGYWlsT3Blbih0b2tlbklkLCB0b2tlbk5hbWUsIHJlc3VsdC5yZWFzb24pO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHJlc3VsdC51dGlsaXphdGlvblBjdCA+PSB0aHJlc2hvbGQpIHtcbiAgICAgIHRoaXMubG9nUXVvdGFPdmVyVGhyZXNob2xkKHRva2VuSWQsIHRva2VuTmFtZSwgdGhyZXNob2xkLCByZXN1bHQpO1xuICAgICAgZXhjbHVkZWRUb2tlbklkcz8uYWRkKHRva2VuSWQpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBsb2dRdW90YU92ZXJUaHJlc2hvbGQoXG4gICAgdG9rZW5JZDogbnVtYmVyLFxuICAgIHRva2VuTmFtZTogc3RyaW5nLFxuICAgIHRocmVzaG9sZDogbnVtYmVyLFxuICAgIHJlc3VsdDogRXh0cmFjdDxPcGVuQUlRdW90YVVzYWdlUmVzdWx0LCB7IGtpbmQ6IFwib2tcIiB9PixcbiAgKTogdm9pZCB7XG4gICAgbG9nZ2VyLmluZm8oXCJxdW90YV90aHJlc2hvbGQgZ2F0ZTogb3Zlcl90aHJlc2hvbGRcIiwge1xuICAgICAgdG9rZW5JZCxcbiAgICAgIHRva2VuTmFtZSxcbiAgICAgIHByb3ZpZGVyOiBcIm9wZW5haVwiLFxuICAgICAgdGhyZXNob2xkLFxuICAgICAgY2FjaGVkVXRpbGl6YXRpb246IHJlc3VsdC51dGlsaXphdGlvblBjdCxcbiAgICAgIGNhY2hlQWdlOiByZXN1bHQuY2FjaGVBZ2VNcyxcbiAgICAgIHdpbmRvd0R1cmF0aW9uTWluczogcmVzdWx0LndpbmRvd0R1cmF0aW9uTWlucyxcbiAgICAgIHJlc2V0c0F0OiByZXN1bHQucmVzZXRzQXQsXG4gICAgICBsaW1pdElkOiByZXN1bHQubGltaXRJZCxcbiAgICAgIHJlYXNvbjogXCJvdmVyX3RocmVzaG9sZFwiLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBsb2dRdW90YUxvb2t1cEZhaWxPcGVuKHRva2VuSWQ6IG51bWJlciwgdG9rZW5OYW1lOiBzdHJpbmcsIHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRRdW90YVRocmVzaG9sZCh0b2tlbklkKTtcbiAgICBsb2dnZXIud2FybihcInF1b3RhX3RocmVzaG9sZCBnYXRlOiBsb29rdXBfZmFpbF9vcGVuXCIsIHtcbiAgICAgIHRva2VuSWQsXG4gICAgICB0b2tlbk5hbWUsXG4gICAgICBwcm92aWRlcjogXCJvcGVuYWlcIixcbiAgICAgIHRocmVzaG9sZCxcbiAgICAgIHJlYXNvbjogXCJsb29rdXBfZmFpbF9vcGVuXCIsXG4gICAgICBsb29rdXBSZWFzb246IHJlYXNvbixcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgdGhyb3dRdW90YVRocmVzaG9sZEV4Y2VlZGVkKGVsaWdpYmlsaXR5OiBUb2tlbkVsaWdpYmlsaXR5KTogbmV2ZXIge1xuICAgIGxvZ2dlci53YXJuKFwicXVvdGFfdGhyZXNob2xkIGdhdGU6IGFsbF9leGNlZWRlZFwiLCB7XG4gICAgICBwcm92aWRlcjogXCJvcGVuYWlcIixcbiAgICAgIHRva2VuQ291bnQ6IGVsaWdpYmlsaXR5LnJlYWR5QWN0aXZlVG9rZW5JZHMuc2l6ZSxcbiAgICAgIHRocmVzaG9sZGVkVG9rZW5Db3VudDogZWxpZ2liaWxpdHkudGhyZXNob2xkZWRUb2tlbkNvdW50LFxuICAgICAgb3ZlclRocmVzaG9sZFRva2VuczogZWxpZ2liaWxpdHkub3ZlclRocmVzaG9sZFRva2VucyxcbiAgICAgIHJlYXNvbjogXCJhbGxfZXhjZWVkZWRcIixcbiAgICB9KTtcbiAgICB0aHJvdyBuZXcgUXVvdGFUaHJlc2hvbGRFeGNlZWRlZEVycm9yKFxuICAgICAgcXVvdGFUaHJlc2hvbGRFeGNlZWRlZE1lc3NhZ2UoXCJvcGVuYWlcIiwgZWxpZ2liaWxpdHkub3ZlclRocmVzaG9sZFRva2VucyksXG4gICAgKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBCcm93c2VyIGxvZ2luIGZsb3cg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcGVuZGluZ0xvZ2luOiB7XG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcjtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgdGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+O1xuICB9IHwgbnVsbCA9IG51bGw7XG5cbiAgYXN5bmMgc3RhcnRCcm93c2VyTG9naW4obmFtZTogc3RyaW5nKTogUHJvbWlzZTx7IGF1dGhVcmw6IHN0cmluZyB9PiB7XG4gICAgaWYgKHRoaXMucGVuZGluZ0xvZ2luKSB7XG4gICAgICB0aGlzLnBlbmRpbmdMb2dpbi53b3JrZXIua2lsbCgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnBlbmRpbmdMb2dpbi50aW1lcik7XG4gICAgICB0aGlzLnBlbmRpbmdMb2dpbiA9IG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgdGVtcElkID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCB3b3JrZXIgPSBuZXcgQ29kZXhBcHBTZXJ2ZXJXb3JrZXIoe1xuICAgICAgdG9rZW5JZDogdGVtcElkLFxuICAgICAgdG9rZW5OYW1lOiBuYW1lLFxuICAgICAgYWNjZXNzVG9rZW46IFwiXCIsXG4gICAgICBhY2NvdW50SWQ6IFwiXCIsXG4gICAgfSk7XG5cbiAgICBjb25zdCBhdXRoVXJsID0gYXdhaXQgd29ya2VyLnN0YXJ0QnJvd3NlckxvZ2luKCk7XG5cbiAgICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMucGVuZGluZ0xvZ2luPy53b3JrZXIgPT09IHdvcmtlcikge1xuICAgICAgICBsb2dnZXIud2FybihgYnJvd3NlciBsb2dpbiB0aW1lb3V0IGZvciAke25hbWV9LCBraWxsaW5nIHdvcmtlcmApO1xuICAgICAgICB3b3JrZXIua2lsbCgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgdGhpcy5wZW5kaW5nTG9naW4gPSBudWxsO1xuICAgICAgfVxuICAgIH0sIDMwMF8wMDApO1xuXG4gICAgdGhpcy5wZW5kaW5nTG9naW4gPSB7IHdvcmtlciwgbmFtZSwgdGltZXIgfTtcbiAgICByZXR1cm4geyBhdXRoVXJsIH07XG4gIH1cblxuICBnZXQgcGVuZGluZ0xvZ2luTmFtZSgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5wZW5kaW5nTG9naW4/Lm5hbWUgPz8gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIGNvbXBsZXRlQnJvd3NlckxvZ2luKCk6IFByb21pc2U8e1xuICAgIGFjY2Vzc1Rva2VuOiBzdHJpbmc7XG4gICAgcmVmcmVzaFRva2VuOiBzdHJpbmc7XG4gICAgaWRUb2tlbj86IHN0cmluZztcbiAgICBhY2NvdW50SWQ6IHN0cmluZztcbiAgfT4ge1xuICAgIGlmICghdGhpcy5wZW5kaW5nTG9naW4pIHRocm93IG5ldyBFcnJvcihcIm5vIHBlbmRpbmcgbG9naW5cIik7XG4gICAgY29uc3QgeyB3b3JrZXIsIHRpbWVyIH0gPSB0aGlzLnBlbmRpbmdMb2dpbjtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB3b3JrZXIud2FpdEZvckJyb3dzZXJMb2dpbkNvbXBsZXRlKCk7XG4gICAgICBjb25zdCBjcmVkcyA9IGF3YWl0IHdvcmtlci5yZWFkTWFuYWdlZENyZWRlbnRpYWxzKCk7XG4gICAgICBpZiAoIWNyZWRzKSB0aHJvdyBuZXcgRXJyb3IoXCJmYWlsZWQgdG8gcmVhZCBjcmVkZW50aWFscyBhZnRlciBsb2dpblwiKTtcbiAgICAgIHJldHVybiBjcmVkcztcbiAgICB9IGZpbmFsbHkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIHRoaXMucGVuZGluZ0xvZ2luID0gbnVsbDtcbiAgICAgIGF3YWl0IHdvcmtlci5raWxsKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBTdGF0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBnZXQgd29ya2VyQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gWy4uLnRoaXMud29ya2VyUG9vbC52YWx1ZXMoKV0uZmxhdCgpLmxlbmd0aDtcbiAgfVxuXG4gIGdldCByZWFkeVdvcmtlckNvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSkubGVuZ3RoO1xuICB9XG5cbiAgZ2V0IHF1ZXVlTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucXVldWUubGVuZ3RoO1xuICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUE0QkEsTUFBTSxTQUFTLFVBQVUsQ0FBQyxTQUFTLG9CQUFvQixDQUFDO0FBUXhELElBQWEsdUJBQWIsY0FBMEMsTUFBTTtDQUM5QyxZQUNFLE1BQ0EsU0FDQTtBQUNBLFFBQU0sUUFBUTtBQUhMLE9BQUEsT0FBQTtBQUlULE9BQUssT0FBTzs7O0FBSWhCLE1BQU0saUJBQWlCO0FBRXZCLE1BQU0sb0JBQW9CLEtBQUssSUFDN0IsT0FBTyxRQUFRLElBQUksMkJBQTJCLEVBQUUsRUFGcEIsRUFJN0I7QUFDRCxNQUFNLG1CQUFtQjtBQUN6QixNQUFNLGlCQUFpQjtBQUN2QixNQUFNLG9CQUFvQjtBQUcxQixNQUFNLHVCQUF1QixRQUFRLElBQUksOEJBQThCO0FBRXZFLE1BQU0sdUJBQXVCO0FBQzdCLE1BQU0sdUJBQXVCO0FBRzdCLFNBQVMsYUFBYSxTQUFpQixhQUE2QjtBQUNsRSxRQUFPLFVBQVUsS0FBSzs7QUFHeEIsU0FBUyxNQUFNLElBQTJCO0FBQ3hDLFFBQU8sSUFBSSxTQUFTLFlBQVksV0FBVyxTQUFTLEdBQUcsQ0FBQzs7QUFHMUQsU0FBUyw4QkFDUCxVQUNBLFFBQ1E7Q0FDUixNQUFNLFVBQVUsT0FDYixLQUFLLFVBQVUsR0FBRyxNQUFNLFVBQVUsY0FBYyxNQUFNLFVBQVUsSUFBSSxDQUNwRSxLQUFLLEtBQUs7QUFDYixRQUFPLFFBQVEsU0FBUyxJQUNwQixPQUFPLFNBQVMsb0NBQW9DLFlBQ3BELE9BQU8sU0FBUzs7QUF1QnRCLElBQWEsbUJBQWIsTUFBYSxpQkFBK0M7Q0FDMUQsNkJBQWEsSUFBSSxLQUFxQztDQUN0RCxnQ0FBZ0IsSUFBSSxLQUE0QjtDQUNoRCxXQUFXO0NBQ1gsUUFBcUIsRUFBRTtDQUN2QixXQUFtQjtDQUNuQixhQUFxQjtDQUVyQixNQUFNLFFBQXVCO0VBQzNCLE1BQU0sRUFBRSxTQUFTLE1BQU0sV0FBVyxTQUFTLElBQUk7RUFDL0MsTUFBTSxlQUFlLEtBQUssUUFBUSxNQUFNLEVBQUUsYUFBYSxTQUFTO0FBQ2hFLFNBQU8sS0FDTCxZQUFZLGFBQWEsT0FBTyxrQkFBa0Isa0JBQWtCLGdCQUNyRTtBQUVELFFBQU0sUUFBUSxXQUNaLGFBQWEsSUFBSSxPQUFPLE1BQU07QUFDNUIsU0FBTSxLQUFLLGFBQ1QsRUFBRSxJQUNGLEVBQUUsTUFDRixFQUFFLGFBQ0YsRUFBRSxnQkFDSDtBQUNELE9BQUksQ0FBQyxFQUFFLE9BQVEsTUFBSyxtQkFBbUIsRUFBRSxHQUFHO0lBQzVDLENBQ0g7O0NBR0gsTUFBTSxPQUFzQjtBQUMxQixPQUFLLGdCQUFnQixzQkFBc0I7RUFDM0MsTUFBTSxRQUFRLENBQUMsR0FBRyxLQUFLLFdBQVcsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssTUFBTSxFQUFFLE1BQU0sQ0FBQztBQUN2RSxRQUFNLFFBQVEsV0FBVyxNQUFNO0FBQy9CLE9BQUssV0FBVyxPQUFPO0FBQ3ZCLE9BQUssY0FBYyxPQUFPO0FBQzFCLE9BQUssZ0JBQWdCLE9BQU87O0NBSzlCLE1BQU0sYUFDSixJQUNBLE1BQ0EsYUFDQSxnQkFDZTtBQUNmLE9BQUssaUJBQWlCLElBQUksTUFBTSxlQUFlO0FBQy9DLE1BQUksS0FBSyxXQUFXLElBQUksR0FBRyxDQUFFO0FBQzdCLFFBQU0sS0FBSyxhQUFhLElBQUksTUFBTSxhQUFhLGVBQWU7O0NBR2hFLE1BQU0sZUFBZSxJQUEyQjtFQUM5QyxNQUFNLFVBQVUsS0FBSyxXQUFXLElBQUksR0FBRyxJQUFJLEVBQUU7RUFDN0MsTUFBTSxZQUFZLFFBQVEsSUFBSTtBQUM5QixPQUFLLFdBQVcsT0FBTyxHQUFHO0FBQzFCLE9BQUssY0FBYyxPQUFPLEdBQUc7QUFDN0IsT0FBSyxnQkFBZ0IsT0FBTyxHQUFHO0FBQy9CLFFBQU0sUUFBUSxXQUFXLFFBQVEsS0FBSyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDdEQsTUFBSSxLQUFLLDBCQUEwQixDQUFDLFdBQVcsRUFDN0MsTUFBSyxnQkFBZ0Isb0JBQW9CO0FBRTNDLE1BQUksUUFBUSxTQUFTLEdBQUc7R0FDdEIsTUFBTSxRQUFRLGFBQWEsU0FBUztBQUNwQyxVQUFPLEtBQUssb0JBQW9CLE1BQU0sSUFBSSxRQUFRLE9BQU8sR0FBRzs7O0NBSWhFLE1BQU0sZUFDSixJQUNBLE1BQ0EsYUFDQSxnQkFDZTtFQUNmLE1BQU0sV0FBVyxLQUFLLFdBQVcsSUFBSSxHQUFHLElBQUksRUFBRTtFQUM5QyxNQUFNLFVBQVUsU0FBUyxNQUFNLE1BQU0sRUFBRSxjQUFjLEtBQUs7QUFDMUQsT0FBSyxpQkFBaUIsSUFBSSxNQUFNLGVBQWU7QUFDL0MsTUFBSSxRQUFTLE1BQUssZ0JBQWdCLE9BQU8sR0FBRztBQUU1QyxNQUFJLFNBQVMsV0FBVyxHQUFHO0FBQ3pCLFNBQU0sS0FBSyxhQUFhLElBQUksTUFBTSxhQUFhLGVBQWU7QUFDOUQ7O0FBR0YsTUFBSSxTQUFTLE9BQU8sTUFBTSxFQUFFLGlCQUFpQixNQUFNLFlBQVksQ0FBQyxFQUFFO0FBQ2hFLFlBQVMsU0FBUyxNQUFNLEVBQUUsaUJBQWlCLE1BQU0sWUFBWSxDQUFDO0FBQzlELFVBQU8sS0FBSyw2QkFBNkIsT0FBTztBQUNoRCxRQUFLLG1CQUFtQjtBQUN4Qjs7QUFHRixPQUFLLFdBQVcsT0FBTyxHQUFHO0FBQzFCLE9BQUssZ0JBQWdCLE9BQU8sR0FBRztBQUMvQixRQUFNLFFBQVEsV0FBVyxTQUFTLEtBQUssTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ3ZELFFBQU0sS0FBSyxhQUFhLElBQUksTUFBTSxhQUFhLGVBQWU7O0NBR2hFLG1CQUFtQixJQUFrQjtFQUNuQyxNQUFNLFVBQVUsS0FBSyxXQUFXLElBQUksR0FBRyxJQUFJLEVBQUU7RUFDN0MsTUFBTSxZQUFZLFFBQVEsSUFBSTtBQUM5QixVQUFRLFNBQVMsTUFBTTtBQUNyQixLQUFFLFNBQVM7SUFDWDtBQUNGLE1BQUksS0FBSywwQkFBMEIsQ0FBQyxXQUFXLEVBQzdDLE1BQUssZ0JBQWdCLG9CQUFvQjtFQUUzQyxNQUFNLFFBQVEsYUFBYSxTQUFTO0FBQ3BDLFNBQU8sS0FBSyx3QkFBd0IsUUFBUTs7Q0FHOUMsaUJBQWlCLElBQWtCO0VBQ2pDLE1BQU0sVUFBVSxLQUFLLFdBQVcsSUFBSSxHQUFHLElBQUksRUFBRTtFQUM3QyxNQUFNLFlBQVksUUFBUSxJQUFJO0FBQzlCLFVBQVEsU0FBUyxNQUFNO0FBQ3JCLEtBQUUsU0FBUztJQUNYO0FBQ0YsT0FBSyxtQkFBbUI7RUFDeEIsTUFBTSxRQUFRLGFBQWEsU0FBUztBQUNwQyxTQUFPLEtBQUssc0JBQXNCLFFBQVE7O0NBRzVDLE1BQU0sY0FDSixNQU1lO0VBQ2YsTUFBTSxPQUFPLElBQUksSUFBSSxLQUFLLEtBQUssTUFBTSxFQUFFLEdBQUcsQ0FBQztBQUMzQyxPQUFLLE1BQU0sTUFBTSxNQUFNLEtBQUssS0FBSyxXQUFXLE1BQU0sQ0FBQyxDQUNqRCxLQUFJLENBQUMsS0FBSyxJQUFJLEdBQUcsQ0FBRSxPQUFNLEtBQUssZUFBZSxHQUFHO0FBR2xELE9BQUssTUFBTSxPQUFPLE1BQU07QUFDdEIsT0FBSSxLQUFLLFdBQVcsSUFBSSxJQUFJLEdBQUcsQ0FDN0IsT0FBTSxLQUFLLGVBQWUsSUFBSSxJQUFJLElBQUksTUFBTSxJQUFJLGFBQWEsSUFBSSxlQUFlO09BRWhGLE9BQU0sS0FBSyxhQUFhLElBQUksSUFBSSxJQUFJLE1BQU0sSUFBSSxhQUFhLElBQUksZUFBZTtBQUVoRixRQUFLLGlCQUFpQixJQUFJLEdBQUc7OztDQU1qQyxNQUFNLFNBQVMsS0FBK0M7RUFDNUQsTUFBTSxtQ0FBbUIsSUFBSSxLQUFhO0VBRTFDLE1BQU0sY0FBYyxNQUFNLEtBQUssbUJBQW1CLEtBQUssaUJBQWlCO0FBQ3hFLE1BQUksYUFBYTtBQUNmLFVBQU8sS0FDTCxLQUFLLFlBQVksVUFBVSxHQUFHLFlBQVksUUFBUSxtQkFBbUIsSUFBSSxNQUFNLEdBQ2hGO0FBQ0QsVUFBTyxLQUFLLGtCQUFrQixjQUFjLE1BQzFDLEtBQUssWUFBWSxHQUFHLEtBQUssSUFBSSxNQUFPLFNBQVMsQ0FDOUM7O0VBR0gsTUFBTSxTQUFTLE1BQU0sS0FBSyxrQkFBa0IsaUJBQWlCO0FBQzdELE1BQUksUUFBUTtBQUNWLFVBQU8sS0FBSyxLQUFLLE9BQU8sVUFBVSxHQUFHLE9BQU8sUUFBUSxZQUFZLElBQUksTUFBTSxHQUFHO0FBQzdFLFVBQU8sS0FBSyxrQkFBa0IsU0FBUyxNQUFNLEtBQUssWUFBWSxHQUFHLElBQUksQ0FBQzs7QUFFeEUsU0FBTyxLQUFLLFNBQVMsTUFBTTtBQUN6QixVQUFPLEtBQUssS0FBSyxFQUFFLFVBQVUsR0FBRyxFQUFFLFFBQVEsWUFBWSxJQUFJLE1BQU0sV0FBVztBQUMzRSxVQUFPLEtBQUssWUFBWSxHQUFHLElBQUk7S0FDOUIsaUJBQWlCOztDQUd0QixNQUFNLGVBQWUsS0FBc0IsSUFBNEM7QUFHckYsTUFBSSxJQUFJLGdCQUNOLE9BQU0sSUFBSSxxQkFBcUIsUUFBUSwwREFBMEQ7RUFFbkcsTUFBTSxtQ0FBbUIsSUFBSSxLQUFhO0VBQzFDLE1BQU0sY0FBYyxNQUFNLEtBQUssbUJBQW1CLEtBQUssaUJBQWlCO0FBQ3hFLE1BQUksYUFBYTtBQUNmLFVBQU8sS0FBSyxLQUFLLFlBQVksVUFBVSxHQUFHLFlBQVksUUFBUSw0QkFBNEI7QUFDMUYsVUFBTyxLQUFLLGtCQUFrQixjQUFjLE1BQzFDLEtBQUssa0JBQWtCLEdBQUcsS0FBSyxJQUFJLElBQUksTUFBTyxTQUFTLENBQ3hEOztFQUdILE1BQU0sU0FBUyxNQUFNLEtBQUssa0JBQWtCLGlCQUFpQjtBQUM3RCxNQUFJLFFBQVE7QUFDVixVQUFPLEtBQUssS0FBSyxPQUFPLFVBQVUsR0FBRyxPQUFPLFFBQVEsWUFBWSxJQUFJLE1BQU0sYUFBYTtBQUN2RixVQUFPLEtBQUssa0JBQWtCLFNBQVMsTUFBTSxLQUFLLGtCQUFrQixHQUFHLEtBQUssR0FBRyxDQUFDOztBQUVsRixTQUFPLEtBQUssU0FBUyxNQUFNO0FBQ3pCLFVBQU8sS0FBSyxLQUFLLEVBQUUsVUFBVSxHQUFHLEVBQUUsUUFBUSxZQUFZLElBQUksTUFBTSxxQkFBcUI7QUFDckYsVUFBTyxLQUFLLGtCQUFrQixHQUFHLEtBQUssR0FBRztLQUN4QyxpQkFBaUI7O0NBTXRCLE1BQU0sbUJBQ0osS0FDQSxtQ0FBbUIsSUFBSSxLQUFhLEVBQ0U7QUFHdEMsTUFBSSxJQUFJLGdCQUFpQixRQUFPO0FBQ2hDLE1BQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLE1BQU8sUUFBTztFQUNoRCxNQUFNLEVBQUUsVUFBVSxVQUFVLFVBQVUsSUFBSTtFQUUxQyxNQUFNLFNBQVMsS0FBSyxlQUFlLFNBQVM7QUFDNUMsTUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLFdBQVcsQ0FBQyxPQUFPLE9BQVEsUUFBTztBQUN6RCxNQUFJLE9BQU8sVUFBVSxNQUFPLFFBQU87QUFDbkMsTUFBSSxDQUFDLE9BQU8sVUFBVSxTQUFTLENBQUUsUUFBTztBQUN4QyxNQUFJLENBQUUsTUFBTSxLQUFLLHFCQUFxQixPQUFPLFNBQVMsT0FBTyxXQUFXLGlCQUFpQixDQUN2RixRQUFPO0VBR1QsTUFBTSxXQUFXLEtBQUssS0FBSyxHQUFHO0FBQzlCLFdBQVM7QUFFUCxPQUFJLE9BQU8sVUFBVSxTQUFTLENBQUMsT0FBTyxVQUFVLFNBQVMsQ0FBRSxRQUFPO0FBQ2xFLE9BQUksT0FBTyxnQkFBZ0IsQ0FBRSxRQUFPO0FBQ3BDLE9BQUksS0FBSyxLQUFLLElBQUksU0FBVSxRQUFPO0FBQ25DLFNBQU0sTUFBTSxxQkFBcUI7OztDQUlyQyxlQUFlLFVBQStDO0FBQzVELE9BQUssTUFBTSxXQUFXLEtBQUssV0FBVyxRQUFRLENBQzVDLE1BQUssTUFBTSxLQUFLLFFBQ2QsS0FBSSxhQUFhLEVBQUUsU0FBUyxFQUFFLFlBQVksS0FBSyxTQUFVLFFBQU87QUFHcEUsU0FBTzs7Q0FHVCxNQUFNLG9CQUFvQixVQUFrQixRQUErQjtFQUN6RSxNQUFNLGFBQWEsQ0FBQyxHQUFHLEtBQUssV0FBVyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxNQUFNLEVBQUUsUUFBUTtBQUNoRixRQUFNLFFBQVEsV0FBVyxXQUFXLEtBQUssTUFBTSxFQUFFLGNBQWMsVUFBVSxPQUFPLENBQUMsQ0FBQzs7Q0FNcEYsTUFBTSxrQkFDSixtQ0FBbUIsSUFBSSxLQUFhLEVBQ0U7RUFDdEMsTUFBTSxjQUFjLE1BQU0sS0FBSyx3QkFBd0IsaUJBQWlCO0FBQ3hFLE1BQUksWUFBWSxvQkFBb0IsU0FBUyxFQUFHLFFBQU87QUFDdkQsTUFBSSxZQUFZLGlCQUFpQixTQUFTLEVBQUcsTUFBSyw0QkFBNEIsWUFBWTtFQUUxRixNQUFNLGFBQWEsS0FBSywwQkFBMEIsQ0FBQyxRQUFRLE1BQ3pELFlBQVksaUJBQWlCLElBQUksRUFBRSxRQUFRLENBQzVDO0FBQ0QsTUFBSSxXQUFXLFdBQVcsRUFBRyxRQUFPO0FBQ3BDLE9BQUssSUFBSSxJQUFJLEdBQUcsSUFBSSxXQUFXLFFBQVEsS0FBSztHQUMxQyxNQUFNLElBQUksWUFBWSxLQUFLLFdBQVcsS0FBSyxXQUFXO0FBQ3RELE9BQUksRUFBRSxnQkFBZ0IsRUFBRTtBQUN0QixTQUFLLFlBQVksS0FBSyxXQUFXLElBQUksS0FBSyxXQUFXO0FBQ3JELFdBQU87OztBQUdYLFNBQU87O0NBR1QsMkJBQW1EO0FBQ2pELFNBQU8sQ0FBQyxHQUFHLEtBQUssV0FBVyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxNQUFNLEVBQUUsV0FBVyxFQUFFLE9BQU87O0NBS2xGLE1BQU0sUUFDSixTQUNBLG1DQUFtQixJQUFJLEtBQWEsRUFDeEI7RUFDWixNQUFNLGNBQWMsTUFBTSxLQUFLLHdCQUF3QixpQkFBaUI7QUFDeEUsTUFBSSxZQUFZLG9CQUFvQixTQUFTLEVBQUcsT0FBTSxJQUFJLE1BQU0sb0JBQW9CO0FBQ3BGLE1BQUksWUFBWSxpQkFBaUIsU0FBUyxFQUFHLE1BQUssNEJBQTRCLFlBQVk7QUFDMUYsTUFBSSxLQUFLLE1BQU0sVUFBVSxlQUN2QixPQUFNLElBQUksTUFBTSxjQUFjO0FBR2hDLFNBQU8sSUFBSSxTQUFZLFNBQVMsV0FBVztHQUN6QyxNQUFNLE9BQWtCO0lBQ3RCLFVBQVUsV0FBVztBQUNuQixrQkFBYSxLQUFLLE1BQU07QUFDeEIsVUFBSyxnQkFBZ0I7QUFDckIsYUFBUSxTQUFTLENBQ2QsV0FBVyxLQUFLLGtCQUFrQixRQUFRLFFBQVEsQ0FBQyxDQUNuRCxLQUFLLFNBQVMsT0FBTzs7SUFFMUIsU0FBUyxRQUFRO0FBQ2Ysa0JBQWEsS0FBSyxNQUFNO0FBQ3hCLFVBQUssZ0JBQWdCO0FBQ3JCLFlBQU8sSUFBSTs7SUFFYixPQUFPLGlCQUFpQjtBQUN0QixVQUFLLGdCQUFnQixLQUFLO0FBQzFCLDRCQUFPLElBQUksTUFBTSxjQUFjLENBQUM7T0FDL0IsaUJBQWlCO0lBQ3BCLGtCQUFrQixJQUFJLElBQUksaUJBQWlCO0lBQzVDO0FBRUQsUUFBSyxNQUFNLEtBQUssS0FBSztJQUNyQjs7Q0FHSixnQkFBZ0IsTUFBdUI7QUFDckMsZUFBYSxLQUFLLE1BQU07QUFDeEIsT0FBSyxnQkFBZ0I7RUFDckIsTUFBTSxNQUFNLEtBQUssTUFBTSxRQUFRLEtBQUs7QUFDcEMsTUFBSSxRQUFRLEdBQUksTUFBSyxNQUFNLE9BQU8sS0FBSyxFQUFFOztDQUczQyxnQkFBZ0IsUUFBc0I7RUFDcEMsTUFBTSxNQUFNLElBQUksTUFBTSxPQUFPO0FBQzdCLE9BQUssTUFBTSxTQUFTLFNBQVM7QUFDM0IsZ0JBQWEsS0FBSyxNQUFNO0FBQ3hCLFFBQUssZ0JBQWdCO0FBQ3JCLFFBQUssT0FBTyxJQUFJO0lBQ2hCO0FBQ0YsT0FBSyxRQUFRLEVBQUU7O0NBR2pCLE1BQU0sV0FBVyxnQkFBc0Q7QUFDckUsTUFBSSxLQUFLLFVBQVU7QUFDakIsUUFBSyxhQUFhO0FBQ2xCOztBQUdGLE9BQUssV0FBVztFQUNoQixJQUFJLFNBQVM7QUFDYixNQUFJO0FBQ0YsTUFBRztBQUNELFNBQUssYUFBYTtBQUNsQixVQUFNLEtBQUssZUFBZSxPQUFPO0FBQ2pDLGFBQVM7WUFDRixLQUFLO1dBQ1AsR0FBRztBQUNWLFVBQU8sS0FBSyxzQkFBdUIsRUFBWSxVQUFVO1lBQ2pEO0FBQ1IsUUFBSyxXQUFXOzs7Q0FJcEIsTUFBYyxlQUFlLGdCQUFzRDtBQUNqRixNQUNFLGtCQUNBLEtBQUssTUFBTSxTQUFTLEtBQ3BCLGVBQWUsV0FDZixlQUFlLFVBQ2QsTUFBTSxLQUFLLDZCQUE2QixnQkFBZ0IsS0FBSyxNQUFNLEdBQUksSUFDeEUsZUFBZSxnQkFBZ0IsRUFDL0I7QUFFQSxHQURhLEtBQUssTUFBTSxPQUFPLENBQzFCLFFBQVEsZUFBZTtBQUM1Qjs7QUFHRixTQUFPLEtBQUssTUFBTSxTQUFTLEdBQUc7R0FDNUIsTUFBTSxPQUFPLEtBQUssTUFBTTtHQUN4QixJQUFJO0FBQ0osT0FBSTtBQUNGLGFBQVMsTUFBTSxLQUFLLGtCQUFrQixLQUFLLGlCQUFpQjtZQUNyRCxHQUFHO0FBQ1YsUUFBSSxhQUFhLDZCQUE2QjtBQUM1QyxVQUFLLE1BQU0sT0FBTztBQUNsQixVQUFLLE9BQU8sRUFBRTtBQUNkOztBQUVGLFVBQU07O0FBRVIsT0FBSSxDQUFDLE9BQVE7QUFDYixRQUFLLE1BQU0sT0FBTztBQUNsQixRQUFLLFFBQVEsT0FBTzs7O0NBTXhCLE1BQU0sa0JBQ0osUUFDQSxTQUNZO0FBQ1osTUFBSTtBQUNGLFVBQU8sTUFBTSxRQUFRLE9BQU87WUFDcEI7QUFDUixVQUFPLGFBQWE7QUFDcEIsUUFBSyxrQkFBa0IsT0FBTzs7O0NBTWxDLGlCQUF5QixLQUFzQixlQUFxQztFQUNsRixNQUFNLFVBQVUsa0JBQWtCO0FBQ2xDLFNBQU87R0FDTCxPQUFPLFdBQVcsSUFBSSxhQUFhLElBQUksYUFBYSxJQUFJO0dBQ3hELFNBQVMsVUFBVSxTQUFZLElBQUk7R0FDbkMsdUJBQXVCLElBQUk7R0FDM0IsY0FBYyxJQUFJO0dBQ2xCLFFBQVEsSUFBSSxVQUFVO0dBQ3RCLE9BQU8sSUFBSTtHQUNYLFdBQVcsSUFBSTtHQUNmLGtCQUFrQixJQUFJO0dBQ3RCLGFBQWEsSUFBSTtHQUNqQixpQkFBaUIsSUFBSTtHQUNyQix3QkFBd0IsSUFBSTtHQUM3Qjs7Q0FHSCxNQUFNLFlBQ0osUUFDQSxLQUNBLGVBQ3lCO0FBR3pCLE1BQUksSUFBSSxpQkFBaUI7R0FDdkIsTUFBTSxTQUFTLE1BQU0sT0FBTyw0QkFBNEIsSUFBSSxNQUFNO0FBQ2xFLE9BQUksT0FBUSxPQUFNLElBQUkscUJBQXFCLFFBQVEsT0FBTzs7RUFHNUQsTUFBTSxVQUFVLEtBQUssaUJBQWlCLEtBQUssY0FBYztFQUN6RCxNQUFNLFNBQVMsTUFBTSxPQUFPLFlBQVksU0FBUyxjQUFjO0FBRy9ELE1BQUksSUFBSSxvQkFBb0IsQ0FBQyxPQUFPLFVBQVUsT0FBTyxPQUFPLFdBQVcsR0FDckUsT0FBTSxPQUFPLGlCQUNULElBQUkscUJBQXFCLGNBQWMsaURBQWlELEdBQ3hGLElBQUkscUJBQXFCLGNBQWMsK0NBQStDO0FBRzVGLFNBQU87R0FDTCxNQUFNLE9BQU87R0FDYixXQUFXLE9BQU87R0FDbEIsT0FBTyxPQUFPO0dBQ2QsWUFBWSxPQUFPO0dBQ25CLFFBQVEsT0FBTztHQUNmLE9BQU8sT0FBTztHQUNkLGFBQWE7SUFDWCxVQUFVLGFBQWEsT0FBTyxTQUFTLE9BQU8sWUFBWTtJQUMxRCxVQUFVLE9BQU87SUFDakIsT0FBTyxPQUFPO0lBQ2Y7R0FDRCxRQUFRLE9BQU87R0FDaEI7O0NBR0gsTUFBTSxrQkFDSixRQUNBLEtBQ0EsSUFDQSxlQUNlO0VBQ2YsTUFBTSxVQUFVLEtBQUssaUJBQWlCLEtBQUssY0FBYztFQUd6RCxJQUFJLG1CQUFtQixpQkFBaUI7RUFDeEMsTUFBTSxZQUE2QjtHQUNqQyxHQUFHO0dBQ0gsYUFBYSxhQUFhO0FBQ3hCLHVCQUFtQjtBQUNuQixPQUFHLGFBQWEsU0FBUzs7R0FFM0IsYUFBYSxXQUFXO0FBQ3RCLE9BQUcsV0FBVztLQUNaLEdBQUc7S0FDSCxXQUFXLE9BQU87S0FDbEIsYUFBYTtNQUNYLFVBQVUsYUFBYSxPQUFPLFNBQVMsT0FBTyxZQUFZO01BQzFELFVBQVU7TUFDVixPQUFPLE9BQU87TUFDZjtLQUNGLENBQUM7O0dBRUw7QUFDRCxRQUFNLE9BQU8sa0JBQWtCLFNBQVMsV0FBVyxjQUFjOztDQUtuRSxNQUFNLGFBQ0osU0FDQSxXQUNBLGFBQ0EsZ0JBQ2U7QUFDZixPQUFLLGlCQUFpQixTQUFTLFdBQVcsZUFBZTtFQUN6RCxNQUFNLFVBQWtDLEVBQUU7QUFDMUMsT0FBSyxJQUFJLElBQUksR0FBRyxJQUFJLG1CQUFtQixLQUFLO0FBQzFDLE9BQUksSUFBSSxFQUFHLE9BQU0sTUFBTSxrQkFBa0I7R0FDekMsTUFBTSxTQUFTLE1BQU0sS0FBSyxrQkFBa0IsU0FBUyxXQUFXLGFBQWEsRUFBRTtBQUMvRSxPQUFJLE9BQVEsU0FBUSxLQUFLLE9BQU87O0FBRWxDLE1BQUksUUFBUSxTQUFTLEVBQUcsTUFBSyxXQUFXLElBQUksU0FBUyxRQUFROztDQUcvRCxNQUFNLGtCQUNKLFNBQ0EsV0FDQSxhQUNBLGFBQ3NDO0VBQ3RDLE1BQU0sU0FBUyxJQUFJLHFCQUFxQjtHQUN0QztHQUNBO0dBQ0EsYUFBYSxZQUFZO0dBQ3pCLFdBQVcsWUFBWTtHQUN2QixVQUFVLFlBQVk7R0FDdEI7R0FDRCxDQUFDO0FBRUYsU0FBTyxnQkFBZ0IsS0FBSyxtQkFBbUI7QUFFL0MsU0FBTyx3QkFBd0IsT0FBTyxXQUFXO0FBQy9DLE9BQUksV0FBVyxvQ0FDYixRQUFPLCtCQUErQixRQUFRO0FBRWhELFNBQU0sSUFBSSxNQUFNLDZCQUE2QixTQUFTO0lBQ3REO0FBRUYsTUFBSTtBQUNGLFNBQU0sT0FBTyxZQUFZO0FBQ3pCLFVBQU8sS0FBSyxtQkFBbUIsVUFBVSxHQUFHLFlBQVksR0FBRztBQUMzRCxVQUFPO1dBQ0EsR0FBRztBQUNWLFVBQU8sS0FBSyx3QkFBd0IsVUFBVSxHQUFHLFlBQVksS0FBTSxFQUFZLFVBQVU7QUFDekYsU0FBTSxPQUFPLE1BQU0sQ0FBQyxZQUFZLEdBQUc7QUFDbkMsVUFBTzs7O0NBTVgsa0NBQWtCLElBQUksS0FBdUU7Q0FDN0YsT0FBZ0Isd0JBQXdCO0NBRXhDLE1BQU0sdUJBQXVCLFNBQW9EO0VBQy9FLE1BQU0sU0FBUyxLQUFLLGdCQUFnQixJQUFJLFFBQVE7QUFDaEQsTUFBSSxVQUFVLEtBQUssS0FBSyxHQUFHLE9BQU8sV0FBVyxpQkFBaUIsc0JBQzVELFFBQU87RUFHVCxNQUFNLFVBQVUsS0FBSyxXQUFXLElBQUksUUFBUSxJQUFJLEVBQUUsRUFBRSxNQUFNLE1BQU0sRUFBRSxRQUFRO0FBQzFFLE1BQUksQ0FBQyxPQUFRLE9BQU0sSUFBSSxNQUFNLDBCQUEwQjtFQUV2RCxNQUFNLFFBQVE7R0FBRSxNQURGLE1BQU0sT0FBTyxlQUFlO0dBQ3BCLFVBQVUsS0FBSyxLQUFLO0dBQUU7QUFDNUMsT0FBSyxnQkFBZ0IsSUFBSSxTQUFTLE1BQU07QUFDeEMsU0FBTzs7Q0FHVCxrQkFBMEIsZ0JBQTZDO0FBQ3JFLEVBQUssS0FBSyxXQUFXLGVBQWUsQ0FBQyxPQUFPLE1BQzFDLE9BQU8sS0FBSyxzQkFBdUIsRUFBWSxVQUFVLENBQzFEOztDQUdILGlCQUF5QixJQUFZLE1BQWMsZ0JBQXNDO0FBQ3ZGLE9BQUssY0FBYyxJQUFJLElBQUk7R0FBRTtHQUFNO0dBQWdCLENBQUM7O0NBR3RELGtCQUEwQixTQUE0QztBQUNwRSxTQUFPLEtBQUssY0FBYyxJQUFJLFFBQVEsRUFBRTs7Q0FHMUMsa0JBQTBCLFNBQTBCO0VBQ2xELE1BQU0sWUFBWSxLQUFLLGtCQUFrQixRQUFRO0FBQ2pELFNBQU8sY0FBYyxVQUFhLGNBQWM7O0NBR2xELE1BQWMsd0JBQXdCLGtCQUEwRDtFQUM5RixNQUFNLFVBQVUsS0FBSywwQkFBMEI7RUFDL0MsTUFBTSwwQkFBVSxJQUFJLEtBQXFCO0FBQ3pDLE9BQUssTUFBTSxVQUFVLFFBQ25CLEtBQUksQ0FBQyxRQUFRLElBQUksT0FBTyxRQUFRLENBQUUsU0FBUSxJQUFJLE9BQU8sU0FBUyxPQUFPLFVBQVU7RUFHakYsTUFBTSxzQkFBc0IsSUFBSSxJQUFJLFFBQVEsTUFBTSxDQUFDO0VBQ25ELE1BQU0sbUNBQW1CLElBQUksS0FBYTtFQUMxQyxNQUFNLHNCQUF1RSxFQUFFO0VBQy9FLElBQUksd0JBQXdCO0VBRTVCLE1BQU0sVUFBVSxNQUFNLEtBQUssUUFBUSxTQUFTLENBQUM7QUFtQjdDLEdBbEJlLE1BQU0sUUFBUSxXQUMzQixRQUFRLElBQUksT0FBTyxDQUFDLFNBQVMsZUFBZTtBQUMxQyxPQUFJLGlCQUFpQixJQUFJLFFBQVEsRUFBRTtBQUNqQztBQUNBLFdBQU87S0FBRTtLQUFTO0tBQVcsVUFBVTtLQUFPOztBQUVoRCxPQUFJLENBQUMsS0FBSyxrQkFBa0IsUUFBUSxDQUNsQyxRQUFPO0lBQUU7SUFBUztJQUFXLFVBQVU7SUFBTTtBQUUvQztBQUNBLFVBQU87SUFDTDtJQUNBO0lBQ0EsVUFBVSxNQUFNLEtBQUsscUJBQXFCLFNBQVMsVUFBVTtJQUM5RDtJQUNELENBQ0gsRUFFTSxTQUFTLE9BQU8sVUFBVTtBQUMvQixPQUFJLE1BQU0sV0FBVyxhQUFhO0FBQ2hDLFFBQUksTUFBTSxNQUFNLFNBQ2Qsa0JBQWlCLElBQUksTUFBTSxNQUFNLFFBQVE7U0FDcEM7S0FDTCxNQUFNLFlBQVksS0FBSyxrQkFBa0IsTUFBTSxNQUFNLFFBQVE7QUFDN0QsU0FBSSxjQUFjLFVBQWEsY0FBYyxLQUMzQyxxQkFBb0IsS0FBSztNQUFFLFdBQVcsTUFBTSxNQUFNO01BQVc7TUFBVyxDQUFDOztBQUc3RTs7R0FHRixNQUFNLFFBQVEsUUFBUTtBQUN0QixPQUFJLE9BQU87SUFDVCxNQUFNLENBQUMsU0FBUyxhQUFhO0FBQzdCLFNBQUssdUJBQXVCLFNBQVMsV0FBVyxPQUFPLE1BQU0sT0FBTyxDQUFDO0FBQ3JFLHFCQUFpQixJQUFJLFFBQVE7O0lBRS9CO0FBRUYsU0FBTztHQUFFO0dBQXFCO0dBQWtCO0dBQXFCO0dBQXVCOztDQUc5RixNQUFjLDZCQUNaLFFBQ0EsTUFDa0I7QUFDbEIsTUFBSSxLQUFLLGlCQUFpQixJQUFJLE9BQU8sUUFBUSxDQUFFLFFBQU87QUFDdEQsU0FBTyxLQUFLLHFCQUFxQixPQUFPLFNBQVMsT0FBTyxVQUFVOztDQUdwRSxNQUFjLHFCQUNaLFNBQ0EsV0FDQSxrQkFDa0I7RUFDbEIsTUFBTSxZQUFZLEtBQUssa0JBQWtCLFFBQVE7QUFDakQsTUFBSSxjQUFjLFVBQWEsY0FBYyxLQUFNLFFBQU87RUFFMUQsSUFBSTtBQUNKLE1BQUk7QUFDRixZQUFTLE1BQU0sMkJBQTJCLEtBQUssdUJBQXVCLFFBQVEsQ0FBQztXQUN4RSxHQUFHO0FBQ1YsUUFBSyx1QkFBdUIsU0FBUyxXQUFZLEVBQVksUUFBUTtBQUNyRSxVQUFPOztBQUdULE1BQUksT0FBTyxTQUFTLGlCQUFpQjtBQUNuQyxRQUFLLHVCQUF1QixTQUFTLFdBQVcsT0FBTyxPQUFPO0FBQzlELFVBQU87O0FBR1QsTUFBSSxPQUFPLGtCQUFrQixXQUFXO0FBQ3RDLFFBQUssc0JBQXNCLFNBQVMsV0FBVyxXQUFXLE9BQU87QUFDakUscUJBQWtCLElBQUksUUFBUTtBQUM5QixVQUFPOztBQUdULFNBQU87O0NBR1Qsc0JBQ0UsU0FDQSxXQUNBLFdBQ0EsUUFDTTtBQUNOLFNBQU8sS0FBSyx3Q0FBd0M7R0FDbEQ7R0FDQTtHQUNBLFVBQVU7R0FDVjtHQUNBLG1CQUFtQixPQUFPO0dBQzFCLFVBQVUsT0FBTztHQUNqQixvQkFBb0IsT0FBTztHQUMzQixVQUFVLE9BQU87R0FDakIsU0FBUyxPQUFPO0dBQ2hCLFFBQVE7R0FDVCxDQUFDOztDQUdKLHVCQUErQixTQUFpQixXQUFtQixRQUFzQjtFQUN2RixNQUFNLFlBQVksS0FBSyxrQkFBa0IsUUFBUTtBQUNqRCxTQUFPLEtBQUssMENBQTBDO0dBQ3BEO0dBQ0E7R0FDQSxVQUFVO0dBQ1Y7R0FDQSxRQUFRO0dBQ1IsY0FBYztHQUNmLENBQUM7O0NBR0osNEJBQW9DLGFBQXNDO0FBQ3hFLFNBQU8sS0FBSyxzQ0FBc0M7R0FDaEQsVUFBVTtHQUNWLFlBQVksWUFBWSxvQkFBb0I7R0FDNUMsdUJBQXVCLFlBQVk7R0FDbkMscUJBQXFCLFlBQVk7R0FDakMsUUFBUTtHQUNULENBQUM7QUFDRixRQUFNLElBQUksNEJBQ1IsOEJBQThCLFVBQVUsWUFBWSxvQkFBb0IsQ0FDekU7O0NBS0gsZUFJVztDQUVYLE1BQU0sa0JBQWtCLE1BQTRDO0FBQ2xFLE1BQUksS0FBSyxjQUFjO0FBQ3JCLFFBQUssYUFBYSxPQUFPLE1BQU0sQ0FBQyxZQUFZLEdBQUc7QUFDL0MsZ0JBQWEsS0FBSyxhQUFhLE1BQU07QUFDckMsUUFBSyxlQUFlOztFQUl0QixNQUFNLFNBQVMsSUFBSSxxQkFBcUI7R0FDdEMsU0FGYSxLQUFLLEtBQUs7R0FHdkIsV0FBVztHQUNYLGFBQWE7R0FDYixXQUFXO0dBQ1osQ0FBQztFQUVGLE1BQU0sVUFBVSxNQUFNLE9BQU8sbUJBQW1CO0FBVWhELE9BQUssZUFBZTtHQUFFO0dBQVE7R0FBTSxPQVJ0QixpQkFBaUI7QUFDN0IsUUFBSSxLQUFLLGNBQWMsV0FBVyxRQUFRO0FBQ3hDLFlBQU8sS0FBSyw2QkFBNkIsS0FBSyxrQkFBa0I7QUFDaEUsWUFBTyxNQUFNLENBQUMsWUFBWSxHQUFHO0FBQzdCLFVBQUssZUFBZTs7TUFFckIsSUFBUTtHQUVnQztBQUMzQyxTQUFPLEVBQUUsU0FBUzs7Q0FHcEIsSUFBSSxtQkFBa0M7QUFDcEMsU0FBTyxLQUFLLGNBQWMsUUFBUTs7Q0FHcEMsTUFBTSx1QkFLSDtBQUNELE1BQUksQ0FBQyxLQUFLLGFBQWMsT0FBTSxJQUFJLE1BQU0sbUJBQW1CO0VBQzNELE1BQU0sRUFBRSxRQUFRLFVBQVUsS0FBSztBQUUvQixNQUFJO0FBQ0YsU0FBTSxPQUFPLDZCQUE2QjtHQUMxQyxNQUFNLFFBQVEsTUFBTSxPQUFPLHdCQUF3QjtBQUNuRCxPQUFJLENBQUMsTUFBTyxPQUFNLElBQUksTUFBTSx5Q0FBeUM7QUFDckUsVUFBTztZQUNDO0FBQ1IsZ0JBQWEsTUFBTTtBQUNuQixRQUFLLGVBQWU7QUFDcEIsU0FBTSxPQUFPLE1BQU0sQ0FBQyxZQUFZLEdBQUc7OztDQU12QyxJQUFJLGNBQXNCO0FBQ3hCLFNBQU8sQ0FBQyxHQUFHLEtBQUssV0FBVyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUM7O0NBRzlDLElBQUksbUJBQTJCO0FBQzdCLFNBQU8sQ0FBQyxHQUFHLEtBQUssV0FBVyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxNQUFNLEVBQUUsUUFBUSxDQUFDOztDQUd2RSxJQUFJLGNBQXNCO0FBQ3hCLFNBQU8sS0FBSyxNQUFNIn0=
|
|
772
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLWRpc3BhdGNoZXIuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLWRpc3BhdGNoZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQUlEaXNwYXRjaGVyIOKAlCBjb2RleCBhcHAtc2VydmVyIHdvcmtlciBwb29sICsg7Yag7YGwIOudvOyasO2MhS5cbiAqXG4gKiAtIO2GoO2BsOuLuSBOIHdvcmtlciAoQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpLCDquLDrs7ggM1xuICogLSBpZGxlIHdvcmtlciByb3VuZC1yb2JpbiDshKDtg50gKyDtgZAg64yA6riwICjsoITrtoAgYnVzeSDsi5wpXG4gKiAtIFRva2VuU3Vic2NyaWJlciDsnbTrsqTtirjroZwgd29ya2VyIHBvb2wg64+Z6riw7ZmUXG4gKiAtIGJhY2twcmVzc3VyZTog7YGQIGZ1bGwg65iQ64qUIHRpbWVvdXQg7IucIFNFUlZFUl9CVVNZXG4gKi9cbmltcG9ydCB7IHJlYWRGaWxlU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBmcmVlbWVtIH0gZnJvbSBcIm5vZGU6b3NcIjtcblxuaW1wb3J0IHsgZ2V0TG9nZ2VyIH0gZnJvbSBcIkBsb2d0YXBlL2xvZ3RhcGVcIjtcblxuaW1wb3J0IHsgUXVvdGFUaHJlc2hvbGRFeGNlZWRlZEVycm9yIH0gZnJvbSBcIi4uLy4uLy4uL2FwcGxpY2F0aW9uL3FncmlkL3FncmlkLnR5cGVzXCI7XG5pbXBvcnQgeyBUb2tlbk1vZGVsIH0gZnJvbSBcIi4uLy4uLy4uL2FwcGxpY2F0aW9uL3Rva2VuL3Rva2VuLm1vZGVsXCI7XG5pbXBvcnQgeyB0eXBlIE9wZW5BSUNyZWRlbnRpYWxzIH0gZnJvbSBcIi4uLy4uLy4uL2FwcGxpY2F0aW9uL3Rva2VuL3Rva2VuLnR5cGVzXCI7XG5pbXBvcnQgeyB0eXBlIEdldEFjY291bnRSYXRlTGltaXRzUmVzcG9uc2UgfSBmcm9tIFwiLi4vLi4vLi4vY29kZXgtcHJvdG9jb2wvdjIvR2V0QWNjb3VudFJhdGVMaW1pdHNSZXNwb25zZVwiO1xuaW1wb3J0IHtcbiAgdHlwZSBHZW5lcmF0ZVJlcXVlc3QsXG4gIHR5cGUgR2VuZXJhdGVSZXN1bHQsXG4gIHR5cGUgR2VuZXJhdGVTdHJlYW1DYWxsYmFja3MsXG4gIHR5cGUgUHJvdmlkZXJEaXNwYXRjaGVyLFxufSBmcm9tIFwiLi4vY29tbW9uL3Byb3ZpZGVyLWRpc3BhdGNoZXJcIjtcbmltcG9ydCB7IFNtb290aFdlaWdodGVkUm91bmRSb2JpbiB9IGZyb20gXCIuLi9jb21tb24vc21vb3RoLXdlaWdodGVkLXJvdW5kLXJvYmluXCI7XG5pbXBvcnQgeyBDb2RleEFwcFNlcnZlcldvcmtlciwgdHlwZSBTdHJlYW1DYWxsYmFja3MsIHR5cGUgVHVyblJlcXVlc3QgfSBmcm9tIFwiLi9jb2RleC13b3JrZXJcIjtcbmltcG9ydCB7XG4gIHJlYWRPcGVuQUlRdW90YVVzYWdlLFxuICB0eXBlIE9wZW5BSVF1b3RhVXNhZ2VSZXN1bHQsXG4gIHR5cGUgT3BlbkFJUmF0ZUxpbWl0c1dpdGhNZXRhLFxufSBmcm9tIFwiLi9vcGVuYWktcXVvdGFcIjtcbmltcG9ydCB7IGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCB9IGZyb20gXCIuL29wZW5haS1yZWZyZXNoXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGdldExvZ2dlcihbXCJxZ3JpZFwiLCBcIm9wZW5haS1kaXNwYXRjaGVyXCJdKTtcblxuLy8g7J2066+47KeAIOyDneyEsSDsmpTssq3snbQg6rKM7J207Yq4L+yDneyEseyXkCDsi6TtjKjtlojsnYQg65WM7J2YIOq1rOu2hOyekC5cbi8vIC0gXCJnYXRlXCI6IOyCrOyghCDqsoDspp0g7Iuk7YyoKGNhcGFiaWxpdHkv66qo6424IOupgO2LsOuqqOuLrCDrtojstqnsobEpIOKAlCB0dXJuIOuvuOyLpO2WiS5cbi8vIC0gXCJub3RfY2FsbGVkXCI6IHR1cm4g7J2AIOyEseqzte2WiOycvOuCmCDrqqjrjbjsnbQgaW1hZ2UgdG9vbCDsnYQg7Zi47LacIOyViCDtlagg4oCUIOyerOyLnOuPhCDrrLTsnbUo7ZSE66Gs7ZSE7Yq4IOusuOygnCkuXG4vLyAtIFwiaW5jb21wbGV0ZVwiOiB0b29sIOyLnOuPhOuQkOycvOuCmCDsmYTshLEg7J2066+47KeAIOuvuOuPhOywqSDigJQg7J6s7Iuc64+EIO2bhOuztCjshJzrsoTsuKEg7Iuk7YyoL+qxsOu2gCkuXG5leHBvcnQgdHlwZSBJbWFnZUZhaWx1cmVLaW5kID0gXCJnYXRlXCIgfCBcIm5vdF9jYWxsZWRcIiB8IFwiaW5jb21wbGV0ZVwiO1xuXG5leHBvcnQgY2xhc3MgSW1hZ2VHZW5lcmF0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IGtpbmQ6IEltYWdlRmFpbHVyZUtpbmQsXG4gICAgbWVzc2FnZTogc3RyaW5nLFxuICApIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSBcIkltYWdlR2VuZXJhdGlvbkVycm9yXCI7XG4gIH1cbn1cblxuY29uc3QgREVGQVVMVF9FRkZPUlQgPSBcImxvd1wiO1xuZXhwb3J0IGNvbnN0IE1BWF9PUEVOQUlfV09SS0VSU19QRVJfVE9LRU4gPSAyMDtcbmNvbnN0IERFRkFVTFRfT1BFTkFJX01JTl9XT1JLRVJTX1BFUl9UT0tFTiA9IDU7XG5jb25zdCBERUZBVUxUX09QRU5BSV9NQVhfV09SS0VSU19QRVJfVE9LRU4gPSAxNTtcbmNvbnN0IFFVRVVFX1RJTUVPVVRfTVMgPSA2MF8wMDA7XG5jb25zdCBNQVhfUVVFVUVfU0laRSA9IDUwO1xuY29uc3QgU1BBV05fSU5URVJWQUxfTVMgPSA1MDA7XG5cbmV4cG9ydCBjb25zdCBPUEVOQUlfV09SS0VSX0JBU0VfUlNTX0dJQiA9IDAuNzE7XG5leHBvcnQgY29uc3QgT1BFTkFJX1dPUktFUl9SU1NfR0lCID0gMC4xNTc7XG5cbmV4cG9ydCB0eXBlIE9wZW5BSVdvcmtlclBvb2xDb25maWcgPSB7XG4gIGF1dG9zY2FsZTogYm9vbGVhbjtcbiAgbWluV29ya2Vyc1BlclRva2VuOiBudW1iZXI7XG4gIG1heFdvcmtlcnNQZXJUb2tlbjogbnVtYmVyO1xuICBzY2FsZUludGVydmFsTXM6IG51bWJlcjtcbiAgc2NhbGVEb3duSWRsZU1zOiBudW1iZXI7XG4gIG1heEVzdGltYXRlZFJzc0dpQjogbnVtYmVyO1xuICBtaW5Ib3N0QXZhaWxhYmxlR2lCOiBudW1iZXI7XG59O1xuXG5mdW5jdGlvbiBib3VuZGVkSW50ZWdlcihcbiAgdmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgZmFsbGJhY2s6IG51bWJlcixcbiAgbWluOiBudW1iZXIsXG4gIG1heDogbnVtYmVyLFxuKTogbnVtYmVyIHtcbiAgY29uc3QgcGFyc2VkID0gTnVtYmVyKHZhbHVlKTtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUocGFyc2VkKSkgcmV0dXJuIGZhbGxiYWNrO1xuICByZXR1cm4gTWF0aC5tYXgobWluLCBNYXRoLm1pbihNYXRoLmZsb29yKHBhcnNlZCksIG1heCkpO1xufVxuXG5mdW5jdGlvbiBib3VuZGVkTnVtYmVyKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQsIGZhbGxiYWNrOiBudW1iZXIsIG1pbjogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgcGFyc2VkID0gTnVtYmVyKHZhbHVlKTtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUocGFyc2VkKSkgcmV0dXJuIGZhbGxiYWNrO1xuICByZXR1cm4gTWF0aC5tYXgobWluLCBwYXJzZWQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZU9wZW5BSVdvcmtlclBvb2xDb25maWcoXG4gIGVudjogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPiA9IHByb2Nlc3MuZW52LFxuKTogT3BlbkFJV29ya2VyUG9vbENvbmZpZyB7XG4gIGNvbnN0IGF1dG9zY2FsZSA9IGVudi5RR1JJRF9PUEVOQUlfQVVUT1NDQUxFICE9PSBcImZhbHNlXCIgJiYgZW52LlFHUklEX09QRU5BSV9BVVRPU0NBTEUgIT09IFwiMFwiO1xuICBjb25zdCBsZWdhY3lXb3JrZXJzID0gYm91bmRlZEludGVnZXIoXG4gICAgZW52LlFHUklEX1dPUktFUlNfUEVSX1RPS0VOLFxuICAgIERFRkFVTFRfT1BFTkFJX01JTl9XT1JLRVJTX1BFUl9UT0tFTixcbiAgICAxLFxuICAgIE1BWF9PUEVOQUlfV09SS0VSU19QRVJfVE9LRU4sXG4gICk7XG4gIGNvbnN0IG1pbldvcmtlcnNQZXJUb2tlbiA9IGJvdW5kZWRJbnRlZ2VyKFxuICAgIGVudi5RR1JJRF9PUEVOQUlfTUlOX1dPUktFUlNfUEVSX1RPS0VOLFxuICAgIGxlZ2FjeVdvcmtlcnMsXG4gICAgMSxcbiAgICBNQVhfT1BFTkFJX1dPUktFUlNfUEVSX1RPS0VOLFxuICApO1xuICBjb25zdCBjb25maWd1cmVkTWF4ID0gYm91bmRlZEludGVnZXIoXG4gICAgZW52LlFHUklEX09QRU5BSV9NQVhfV09SS0VSU19QRVJfVE9LRU4sXG4gICAgYXV0b3NjYWxlID8gREVGQVVMVF9PUEVOQUlfTUFYX1dPUktFUlNfUEVSX1RPS0VOIDogbWluV29ya2Vyc1BlclRva2VuLFxuICAgIDEsXG4gICAgTUFYX09QRU5BSV9XT1JLRVJTX1BFUl9UT0tFTixcbiAgKTtcblxuICByZXR1cm4ge1xuICAgIGF1dG9zY2FsZSxcbiAgICBtaW5Xb3JrZXJzUGVyVG9rZW4sXG4gICAgbWF4V29ya2Vyc1BlclRva2VuOiBhdXRvc2NhbGVcbiAgICAgID8gTWF0aC5tYXgobWluV29ya2Vyc1BlclRva2VuLCBjb25maWd1cmVkTWF4KVxuICAgICAgOiBtaW5Xb3JrZXJzUGVyVG9rZW4sXG4gICAgc2NhbGVJbnRlcnZhbE1zOiBib3VuZGVkSW50ZWdlcihlbnYuUUdSSURfT1BFTkFJX1NDQUxFX0lOVEVSVkFMX01TLCA1XzAwMCwgMjUwLCAzMDBfMDAwKSxcbiAgICBzY2FsZURvd25JZGxlTXM6IGJvdW5kZWRJbnRlZ2VyKFxuICAgICAgZW52LlFHUklEX09QRU5BSV9TQ0FMRV9ET1dOX0lETEVfTVMsXG4gICAgICAxMCAqIDYwXzAwMCxcbiAgICAgIDFfMDAwLFxuICAgICAgMjQgKiA2MCAqIDYwXzAwMCxcbiAgICApLFxuICAgIG1heEVzdGltYXRlZFJzc0dpQjogYm91bmRlZE51bWJlcihlbnYuUUdSSURfT1BFTkFJX01BWF9FU1RJTUFURURfUlNTX0dJQiwgMTYsIDEpLFxuICAgIG1pbkhvc3RBdmFpbGFibGVHaUI6IGJvdW5kZWROdW1iZXIoZW52LlFHUklEX09QRU5BSV9NSU5fSE9TVF9BVkFJTEFCTEVfR0lCLCAyMCwgMCksXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlc3RpbWF0ZU9wZW5BSVdvcmtlclJzc0dpQih0b3RhbFdvcmtlcnM6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBPUEVOQUlfV09SS0VSX0JBU0VfUlNTX0dJQiArIE9QRU5BSV9XT1JLRVJfUlNTX0dJQiAqIHRvdGFsV29ya2Vycztcbn1cblxuZnVuY3Rpb24gcmVhZEhvc3RBdmFpbGFibGVHaUIoKTogbnVtYmVyIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBtYXRjaCA9IHJlYWRGaWxlU3luYyhcIi9wcm9jL21lbWluZm9cIiwgXCJ1dGY4XCIpLm1hdGNoKC9eTWVtQXZhaWxhYmxlOlxccysoXFxkKylcXHMra0IkL20pO1xuICAgIGlmIChtYXRjaD8uWzFdKSByZXR1cm4gTnVtYmVyKG1hdGNoWzFdKSAvIDEwMjQgLyAxMDI0O1xuICB9IGNhdGNoIHt9XG4gIHJldHVybiBmcmVlbWVtKCkgLyAxMDI0IC8gMTAyNCAvIDEwMjQ7XG59XG5cbi8vIHRocmVhZCDsnqzsgqzsmqkocHJvbXB0IGNhY2hlIOqzoOyglSkuIOuBhOuptCDquLDsobQgXCLrp6QgdHVybiDsg4ggdGhyZWFkICsgaGlzdG9yeSBpbmplY3RcIiDrj5nsnpEuXG5jb25zdCBUSFJFQURfUkVVU0VfRU5BQkxFRCA9IHByb2Nlc3MuZW52LlFHUklEX09QRU5BSV9USFJFQURfUkVVU0UgIT09IFwiZmFsc2VcIjtcbi8vIOyijO2RnCB3b3JrZXIg6rCAIGJ1c3kg7J28IOuVjCBmcmVlIOulvCDquLDri6TrpqzripQg7LWc64yAIOyLnOqwhC4g7LSI6rO8IOyLnCDsg4ggdGhyZWFkIOuhnCDtj7TrsLEuXG5jb25zdCBSRVVTRV9XT1JLRVJfV0FJVF9NUyA9IDVfMDAwO1xuY29uc3QgUkVVU0VfV09SS0VSX1BPTExfTVMgPSA1MDtcblxuLy8gd29ya2VySWQg7ZWp7ISxOiB0b2tlbklkIOyZgCB3b3JrZXJJbmRleCgwLi4xOSkg66W8IO2VmOuCmOydmCDslYjsoJUg7Iir7J6Q66GcIOyduOy9lOuUqS5cbmNvbnN0IE9QRU5BSV9XT1JLRVJfSURfU1RSSURFID0gMTAwO1xuZXhwb3J0IGZ1bmN0aW9uIG1ha2VPcGVuQUlXb3JrZXJJZCh0b2tlbklkOiBudW1iZXIsIHdvcmtlckluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gdG9rZW5JZCAqIE9QRU5BSV9XT1JLRVJfSURfU1RSSURFICsgd29ya2VySW5kZXg7XG59XG5cbmZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG59XG5cbmZ1bmN0aW9uIHF1b3RhVGhyZXNob2xkRXhjZWVkZWRNZXNzYWdlKFxuICBwcm92aWRlcjogc3RyaW5nLFxuICB0b2tlbnM6IEFycmF5PHsgdG9rZW5OYW1lOiBzdHJpbmc7IHRocmVzaG9sZDogbnVtYmVyIH0+LFxuKTogc3RyaW5nIHtcbiAgY29uc3QgZGV0YWlscyA9IHRva2Vuc1xuICAgIC5tYXAoKHRva2VuKSA9PiBgJHt0b2tlbi50b2tlbk5hbWV9ICh0aHJlc2hvbGQgJHt0b2tlbi50aHJlc2hvbGR9JSlgKVxuICAgIC5qb2luKFwiLCBcIik7XG4gIHJldHVybiBkZXRhaWxzLmxlbmd0aCA+IDBcbiAgICA/IGBBbGwgJHtwcm92aWRlcn0gdG9rZW5zIGV4Y2VlZGVkIHF1b3RhIHRocmVzaG9sZDogJHtkZXRhaWxzfWBcbiAgICA6IGBBbGwgJHtwcm92aWRlcn0gdG9rZW5zIGV4Y2VlZGVkIHF1b3RhIHRocmVzaG9sZGA7XG59XG5cbnR5cGUgUXVldWVJdGVtID0ge1xuICByZXNvbHZlOiAod29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcikgPT4gdm9pZDtcbiAgcmVqZWN0OiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkO1xuICB0aW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD47XG4gIGFib3J0Q2xlYW51cD86ICgpID0+IHZvaWQ7XG4gIGV4Y2x1ZGVkVG9rZW5JZHM6IFNldDxudW1iZXI+O1xufTtcblxudHlwZSBUb2tlbk1ldGFkYXRhID0ge1xuICBuYW1lOiBzdHJpbmc7XG4gIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscztcbiAgcXVvdGFUaHJlc2hvbGQ/OiBudW1iZXIgfCBudWxsO1xuICB3ZWlnaHQ6IG51bWJlcjtcbiAgYWN0aXZlOiBib29sZWFuO1xufTtcblxudHlwZSBUb2tlbkVsaWdpYmlsaXR5ID0ge1xuICByZWFkeUFjdGl2ZVRva2VuSWRzOiBTZXQ8bnVtYmVyPjtcbiAgZWxpZ2libGVUb2tlbklkczogU2V0PG51bWJlcj47XG4gIG92ZXJUaHJlc2hvbGRUb2tlbnM6IEFycmF5PHsgdG9rZW5OYW1lOiBzdHJpbmc7IHRocmVzaG9sZDogbnVtYmVyIH0+O1xuICB0aHJlc2hvbGRlZFRva2VuQ291bnQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCBjbGFzcyBPcGVuQUlEaXNwYXRjaGVyIGltcGxlbWVudHMgUHJvdmlkZXJEaXNwYXRjaGVyIHtcbiAgd29ya2VyUG9vbCA9IG5ldyBNYXA8bnVtYmVyLCBDb2RleEFwcFNlcnZlcldvcmtlcltdPigpO1xuICB0b2tlbk1ldGFkYXRhID0gbmV3IE1hcDxudW1iZXIsIFRva2VuTWV0YWRhdGE+KCk7XG4gIHF1ZXVlOiBRdWV1ZUl0ZW1bXSA9IFtdO1xuICByZWFkb25seSBwb29sQ29uZmlnOiBPcGVuQUlXb3JrZXJQb29sQ29uZmlnO1xuICBwcml2YXRlIHJlYWRvbmx5IHdlaWdodGVkU2VsZWN0b3IgPSBuZXcgU21vb3RoV2VpZ2h0ZWRSb3VuZFJvYmluKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgd29ya2VyQ3Vyc29yQnlUb2tlbiA9IG5ldyBNYXA8bnVtYmVyLCBudW1iZXI+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZ2V0SG9zdEF2YWlsYWJsZUdpQjogKCkgPT4gbnVtYmVyO1xuICBwcml2YXRlIGRyYWluaW5nID0gZmFsc2U7XG4gIHByaXZhdGUgZHJhaW5BZ2FpbiA9IGZhbHNlO1xuICBwcml2YXRlIHNjYWxlclRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRJbnRlcnZhbD4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBzY2FsaW5nUHJvbWlzZTogUHJvbWlzZTx2b2lkPiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGxhc3RSZXF1ZXN0QXQgPSBEYXRlLm5vdygpO1xuICBwcml2YXRlIHN0b3BwZWQgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwb29sQ29uZmlnOiBPcGVuQUlXb3JrZXJQb29sQ29uZmlnID0gcmVzb2x2ZU9wZW5BSVdvcmtlclBvb2xDb25maWcoKSxcbiAgICBnZXRIb3N0QXZhaWxhYmxlR2lCOiAoKSA9PiBudW1iZXIgPSByZWFkSG9zdEF2YWlsYWJsZUdpQixcbiAgKSB7XG4gICAgdGhpcy5wb29sQ29uZmlnID0gcG9vbENvbmZpZztcbiAgICB0aGlzLmdldEhvc3RBdmFpbGFibGVHaUIgPSBnZXRIb3N0QXZhaWxhYmxlR2lCO1xuICB9XG5cbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5zdG9wcGVkID0gZmFsc2U7XG4gICAgY29uc3QgeyByb3dzIH0gPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRNYW55KFwiQVwiKTtcbiAgICBjb25zdCBvcGVuYWlUb2tlbnMgPSByb3dzLmZpbHRlcigodCkgPT4gdC5wcm92aWRlciA9PT0gXCJvcGVuYWlcIik7XG4gICAgbG9nZ2VyLmluZm8oXG4gICAgICB0aGlzLnBvb2xDb25maWcuYXV0b3NjYWxlXG4gICAgICAgID8gYHN0YXJ0aW5nICR7b3BlbmFpVG9rZW5zLmxlbmd0aH0gb3BlbmFpIHRva2VucyAoJHt0aGlzLnBvb2xDb25maWcubWluV29ya2Vyc1BlclRva2VufS0ke3RoaXMucG9vbENvbmZpZy5tYXhXb3JrZXJzUGVyVG9rZW59IHdvcmtlcnMgZWFjaCwgYXV0b3NjYWxlKWBcbiAgICAgICAgOiBgc3RhcnRpbmcgJHtvcGVuYWlUb2tlbnMubGVuZ3RofSBvcGVuYWkgdG9rZW5zICgke3RoaXMucG9vbENvbmZpZy5taW5Xb3JrZXJzUGVyVG9rZW59IHdvcmtlcnMgZWFjaClgLFxuICAgICk7XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoXG4gICAgICBvcGVuYWlUb2tlbnMubWFwKGFzeW5jICh0KSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKFxuICAgICAgICAgIHQuaWQsXG4gICAgICAgICAgdC5uYW1lLFxuICAgICAgICAgIHQuY3JlZGVudGlhbHMgYXMgT3BlbkFJQ3JlZGVudGlhbHMsXG4gICAgICAgICAgdC5xdW90YV90aHJlc2hvbGQsXG4gICAgICAgICAgdC53ZWlnaHQsXG4gICAgICAgICk7XG4gICAgICAgIGlmICghdC5hY3RpdmUpIHRoaXMub25Ub2tlbkRlYWN0aXZhdGVkKHQuaWQpO1xuICAgICAgfSksXG4gICAgKTtcblxuICAgIGlmICh0aGlzLnBvb2xDb25maWcuYXV0b3NjYWxlKSB7XG4gICAgICB0aGlzLnNjYWxlclRpbWVyID0gc2V0SW50ZXJ2YWwoXG4gICAgICAgICgpID0+IHRoaXMucmVxdWVzdEF1dG9zY2FsZUV2YWx1YXRpb24oKSxcbiAgICAgICAgdGhpcy5wb29sQ29uZmlnLnNjYWxlSW50ZXJ2YWxNcyxcbiAgICAgICk7XG4gICAgICB0aGlzLnNjYWxlclRpbWVyLnVucmVmPy4oKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBzdG9wKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuc3RvcHBlZCA9IHRydWU7XG4gICAgaWYgKHRoaXMuc2NhbGVyVGltZXIpIHtcbiAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5zY2FsZXJUaW1lcik7XG4gICAgICB0aGlzLnNjYWxlclRpbWVyID0gbnVsbDtcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5zY2FsaW5nUHJvbWlzZT8uY2F0Y2goKCkgPT4ge30pO1xuICAgIHRoaXMucmVqZWN0QWxsUXVldWVkKFwiRElTUEFUQ0hFUl9TSFVURE9XTlwiKTtcbiAgICBjb25zdCBraWxscyA9IFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5tYXAoKHcpID0+IHcua2lsbCgpKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoa2lsbHMpO1xuICAgIGZvciAoY29uc3QgaWQgb2YgdGhpcy50b2tlbk1ldGFkYXRhLmtleXMoKSkgdGhpcy53ZWlnaHRlZFNlbGVjdG9yLnJlbW92ZVRva2VuKGlkKTtcbiAgICB0aGlzLndvcmtlclBvb2wuY2xlYXIoKTtcbiAgICB0aGlzLnRva2VuTWV0YWRhdGEuY2xlYXIoKTtcbiAgICB0aGlzLndvcmtlckN1cnNvckJ5VG9rZW4uY2xlYXIoKTtcbiAgICB0aGlzLndlaWdodGVkU2VsZWN0b3IucmVzZXRTY29yZXMoKTtcbiAgICB0aGlzLnJhdGVMaW1pdHNDYWNoZS5jbGVhcigpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFRva2VuIGV2ZW50cyAoZnJvbSBUb2tlblN1YnNjcmliZXIpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGFzeW5jIG9uVG9rZW5BZGRlZChcbiAgICBpZDogbnVtYmVyLFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHMsXG4gICAgcXVvdGFUaHJlc2hvbGQ/OiBudW1iZXIgfCBudWxsLFxuICAgIHdlaWdodCA9IDEsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuc2V0VG9rZW5NZXRhZGF0YShpZCwgbmFtZSwgY3JlZGVudGlhbHMsIHF1b3RhVGhyZXNob2xkLCB3ZWlnaHQpO1xuICAgIGlmICh0aGlzLndvcmtlclBvb2wuaGFzKGlkKSkgcmV0dXJuO1xuICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscywgcXVvdGFUaHJlc2hvbGQsIHdlaWdodCk7XG4gIH1cblxuICBhc3luYyBvblRva2VuUmVtb3ZlZChpZDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdO1xuICAgIGNvbnN0IHRva2VuTmFtZSA9IHdvcmtlcnNbMF0/LnRva2VuTmFtZTtcbiAgICB0aGlzLndvcmtlclBvb2wuZGVsZXRlKGlkKTtcbiAgICB0aGlzLnRva2VuTWV0YWRhdGEuZGVsZXRlKGlkKTtcbiAgICB0aGlzLndlaWdodGVkU2VsZWN0b3IucmVtb3ZlVG9rZW4oaWQpO1xuICAgIHRoaXMud29ya2VyQ3Vyc29yQnlUb2tlbi5kZWxldGUoaWQpO1xuICAgIHRoaXMucmF0ZUxpbWl0c0NhY2hlLmRlbGV0ZShpZCk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKHdvcmtlcnMubWFwKCh3KSA9PiB3LmtpbGwoKSkpO1xuICAgIGlmICh0aGlzLmdldEFsbFJlYWR5QWN0aXZlV29ya2VycygpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5yZWplY3RBbGxRdWV1ZWQoXCJOT19PUEVOQUlfV09SS0VSU1wiKTtcbiAgICB9XG4gICAgaWYgKHdvcmtlcnMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgbGFiZWwgPSB0b2tlbk5hbWUgPz8gYHRva2VuICR7aWR9YDtcbiAgICAgIGxvZ2dlci5pbmZvKGB3b3JrZXJzIHJlbW92ZWQ6ICR7bGFiZWx9ICgke3dvcmtlcnMubGVuZ3RofSlgKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBvblRva2VuVXBkYXRlZChcbiAgICBpZDogbnVtYmVyLFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHMsXG4gICAgcXVvdGFUaHJlc2hvbGQ/OiBudW1iZXIgfCBudWxsLFxuICAgIHdlaWdodCA9IDEsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy53b3JrZXJQb29sLmdldChpZCkgPz8gW107XG4gICAgY29uc3QgcmVuYW1lZCA9IGV4aXN0aW5nLnNvbWUoKHcpID0+IHcudG9rZW5OYW1lICE9PSBuYW1lKTtcbiAgICB0aGlzLnNldFRva2VuTWV0YWRhdGEoaWQsIG5hbWUsIGNyZWRlbnRpYWxzLCBxdW90YVRocmVzaG9sZCwgd2VpZ2h0KTtcbiAgICBpZiAocmVuYW1lZCkgdGhpcy5yYXRlTGltaXRzQ2FjaGUuZGVsZXRlKGlkKTtcblxuICAgIGlmIChleGlzdGluZy5sZW5ndGggPT09IDApIHtcbiAgICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscywgcXVvdGFUaHJlc2hvbGQsIHdlaWdodCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGV4aXN0aW5nLmV2ZXJ5KCh3KSA9PiB3LmNhblJldXNlRm9yVG9rZW4obmFtZSwgY3JlZGVudGlhbHMpKSkge1xuICAgICAgZXhpc3RpbmcuZm9yRWFjaCgodykgPT4gdy51cGRhdGVUb2tlblN0YXRlKG5hbWUsIGNyZWRlbnRpYWxzKSk7XG4gICAgICBsb2dnZXIuaW5mbyhgd29ya2VycyB1cGRhdGVkIGluLXBsYWNlOiAke25hbWV9YCk7XG4gICAgICB0aGlzLnJlcXVlc3REcmFpblF1ZXVlKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy53b3JrZXJQb29sLmRlbGV0ZShpZCk7XG4gICAgdGhpcy5yYXRlTGltaXRzQ2FjaGUuZGVsZXRlKGlkKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoZXhpc3RpbmcubWFwKCh3KSA9PiB3LmtpbGwoKSkpO1xuICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscywgcXVvdGFUaHJlc2hvbGQsIHdlaWdodCk7XG4gIH1cblxuICBvblRva2VuRGVhY3RpdmF0ZWQoaWQ6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHdvcmtlcnMgPSB0aGlzLndvcmtlclBvb2wuZ2V0KGlkKSA/PyBbXTtcbiAgICBjb25zdCB0b2tlbk5hbWUgPSB3b3JrZXJzWzBdPy50b2tlbk5hbWU7XG4gICAgY29uc3QgbWV0YWRhdGEgPSB0aGlzLnRva2VuTWV0YWRhdGEuZ2V0KGlkKTtcbiAgICBpZiAobWV0YWRhdGEpIG1ldGFkYXRhLmFjdGl2ZSA9IGZhbHNlO1xuICAgIGNvbnN0IGNoYW5nZWQgPSB3b3JrZXJzLnNvbWUoKHdvcmtlcikgPT4gd29ya2VyLmFjdGl2ZSk7XG4gICAgd29ya2Vycy5mb3JFYWNoKCh3KSA9PiB7XG4gICAgICB3LmFjdGl2ZSA9IGZhbHNlO1xuICAgIH0pO1xuICAgIGlmIChjaGFuZ2VkKSB0aGlzLndlaWdodGVkU2VsZWN0b3IucmVzZXRTY29yZXMoKTtcbiAgICBpZiAodGhpcy5nZXRBbGxSZWFkeUFjdGl2ZVdvcmtlcnMoKS5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMucmVqZWN0QWxsUXVldWVkKFwiTk9fQUNUSVZFX1dPUktFUlNcIik7XG4gICAgfVxuICAgIGNvbnN0IGxhYmVsID0gdG9rZW5OYW1lID8/IGB0b2tlbiAke2lkfWA7XG4gICAgbG9nZ2VyLmluZm8oYHdvcmtlcnMgZGVhY3RpdmF0ZWQ6ICR7bGFiZWx9YCk7XG4gIH1cblxuICBvblRva2VuQWN0aXZhdGVkKGlkOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCB3b3JrZXJzID0gdGhpcy53b3JrZXJQb29sLmdldChpZCkgPz8gW107XG4gICAgY29uc3QgdG9rZW5OYW1lID0gd29ya2Vyc1swXT8udG9rZW5OYW1lO1xuICAgIGNvbnN0IG1ldGFkYXRhID0gdGhpcy50b2tlbk1ldGFkYXRhLmdldChpZCk7XG4gICAgaWYgKG1ldGFkYXRhKSBtZXRhZGF0YS5hY3RpdmUgPSB0cnVlO1xuICAgIGNvbnN0IGNoYW5nZWQgPSB3b3JrZXJzLnNvbWUoKHdvcmtlcikgPT4gIXdvcmtlci5hY3RpdmUpO1xuICAgIHdvcmtlcnMuZm9yRWFjaCgodykgPT4ge1xuICAgICAgdy5hY3RpdmUgPSB0cnVlO1xuICAgIH0pO1xuICAgIGlmIChjaGFuZ2VkKSB0aGlzLndlaWdodGVkU2VsZWN0b3IucmVzZXRTY29yZXMoKTtcbiAgICB0aGlzLnJlcXVlc3REcmFpblF1ZXVlKCk7XG4gICAgY29uc3QgbGFiZWwgPSB0b2tlbk5hbWUgPz8gYHRva2VuICR7aWR9YDtcbiAgICBsb2dnZXIuaW5mbyhgd29ya2VycyBhY3RpdmF0ZWQ6ICR7bGFiZWx9YCk7XG4gIH1cblxuICBhc3luYyByZXBsYWNlVG9rZW5zKFxuICAgIHJvd3M6IEFycmF5PHtcbiAgICAgIGlkOiBudW1iZXI7XG4gICAgICBuYW1lOiBzdHJpbmc7XG4gICAgICBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHM7XG4gICAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGw7XG4gICAgICB3ZWlnaHQ6IG51bWJlcjtcbiAgICB9PixcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgbmV4dCA9IG5ldyBTZXQocm93cy5tYXAoKHIpID0+IHIuaWQpKTtcbiAgICBmb3IgKGNvbnN0IGlkIG9mIEFycmF5LmZyb20odGhpcy53b3JrZXJQb29sLmtleXMoKSkpIHtcbiAgICAgIGlmICghbmV4dC5oYXMoaWQpKSBhd2FpdCB0aGlzLm9uVG9rZW5SZW1vdmVkKGlkKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHJvdyBvZiByb3dzKSB7XG4gICAgICBpZiAodGhpcy53b3JrZXJQb29sLmhhcyhyb3cuaWQpKSB7XG4gICAgICAgIGF3YWl0IHRoaXMub25Ub2tlblVwZGF0ZWQoXG4gICAgICAgICAgcm93LmlkLFxuICAgICAgICAgIHJvdy5uYW1lLFxuICAgICAgICAgIHJvdy5jcmVkZW50aWFscyxcbiAgICAgICAgICByb3cucXVvdGFUaHJlc2hvbGQsXG4gICAgICAgICAgcm93LndlaWdodCxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHRoaXMub25Ub2tlbkFkZGVkKHJvdy5pZCwgcm93Lm5hbWUsIHJvdy5jcmVkZW50aWFscywgcm93LnF1b3RhVGhyZXNob2xkLCByb3cud2VpZ2h0KTtcbiAgICAgIH1cbiAgICAgIHRoaXMub25Ub2tlbkFjdGl2YXRlZChyb3cuaWQpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBHZW5lcmF0ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBnZW5lcmF0ZShyZXE6IEdlbmVyYXRlUmVxdWVzdCk6IFByb21pc2U8R2VuZXJhdGVSZXN1bHQ+IHtcbiAgICB0aGlzLmxhc3RSZXF1ZXN0QXQgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IGV4Y2x1ZGVkVG9rZW5JZHMgPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgICAvLyB0aHJlYWQg7J6s7IKs7JqpIOqyveuhnDog7KKM7ZGcIHdvcmtlciDrpbwg7KCQ7Jyg7ZW0IOq4sOyhtCB0aHJlYWQg7JeQIHR1cm4g66eMIOyLpO2WiS5cbiAgICBjb25zdCByZXVzZVdvcmtlciA9IGF3YWl0IHRoaXMuYWNxdWlyZVJldXNlV29ya2VyKHJlcSwgZXhjbHVkZWRUb2tlbklkcyk7XG4gICAgaWYgKHJldXNlV29ya2VyKSB7XG4gICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgYOKGuyAke3JldXNlV29ya2VyLnRva2VuTmFtZX1bJHtyZXVzZVdvcmtlci50b2tlbklkfV0gKHJldXNlIHRocmVhZCwgJHtyZXEubW9kZWx9KWAsXG4gICAgICApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2UocmV1c2VXb3JrZXIsICh3KSA9PlxuICAgICAgICB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSwgcmVxLnJldXNlIS50aHJlYWRJZCksXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHdvcmtlciA9IGF3YWl0IHRoaXMuYWNxdWlyZUlkbGVXb3JrZXIoZXhjbHVkZWRUb2tlbklkcyk7XG4gICAgaWYgKHdvcmtlcikge1xuICAgICAgbG9nZ2VyLmluZm8oYOKGkiAke3dvcmtlci50b2tlbk5hbWV9WyR7d29ya2VyLnRva2VuSWR9XSAobW9kZWw6ICR7cmVxLm1vZGVsfSlgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVBbmRSZWxlYXNlKHdvcmtlciwgKHcpID0+IHRoaXMuZXhlY3V0ZVR1cm4odywgcmVxKSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmVucXVldWUoKHcpID0+IHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3LnRva2VuTmFtZX1bJHt3LnRva2VuSWR9XSAobW9kZWw6ICR7cmVxLm1vZGVsfSwgcXVldWVkKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZVR1cm4odywgcmVxKTtcbiAgICB9LCBleGNsdWRlZFRva2VuSWRzKTtcbiAgfVxuXG4gIGFzeW5jIGdlbmVyYXRlU3RyZWFtKHJlcTogR2VuZXJhdGVSZXF1ZXN0LCBjYjogR2VuZXJhdGVTdHJlYW1DYWxsYmFja3MpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmxhc3RSZXF1ZXN0QXQgPSBEYXRlLm5vdygpO1xuICAgIC8vIOydtOuvuOyngCDsg53shLHsnYAgbm9uLXN0cmVhbSDsoITsmqkoUjIpOiBjb2RleCDqsIAg7J2066+47KeAIOuNuO2DgOulvCDso7zsp4Ag7JWK6rOgIOyZhOyEsSBiYXNlNjQg66W8XG4gICAgLy8g7ZWcIOuyiOyXkCDspIDri6QuIOyKpO2KuOumrOuwjSDqsr3roZzroZwg7J2066+47KeAIOyalOyyreydtCDsmKTrqbQg66qF7Iuc7KCBIOyXkOufrC5cbiAgICBpZiAocmVxLmltYWdlR2VuZXJhdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEltYWdlR2VuZXJhdGlvbkVycm9yKFxuICAgICAgICBcImdhdGVcIixcbiAgICAgICAgXCJpbWFnZSBnZW5lcmF0aW9uIGlzIG5vdCBzdXBwb3J0ZWQgb24gdGhlIHN0cmVhbWluZyBwYXRoXCIsXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCk7XG4gICAgY29uc3QgcmV1c2VXb3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVSZXVzZVdvcmtlcihyZXEsIGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmIChyZXVzZVdvcmtlcikge1xuICAgICAgbG9nZ2VyLmluZm8oYOKGuyAke3JldXNlV29ya2VyLnRva2VuTmFtZX1bJHtyZXVzZVdvcmtlci50b2tlbklkfV0gKHJldXNlIHRocmVhZCwgW3N0cmVhbV0pYCk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZShyZXVzZVdvcmtlciwgKHcpID0+XG4gICAgICAgIHRoaXMuZXhlY3V0ZVN0cmVhbVR1cm4odywgcmVxLCBjYiwgcmVxLnJldXNlIS50aHJlYWRJZCksXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHdvcmtlciA9IGF3YWl0IHRoaXMuYWNxdWlyZUlkbGVXb3JrZXIoZXhjbHVkZWRUb2tlbklkcyk7XG4gICAgaWYgKHdvcmtlcikge1xuICAgICAgbG9nZ2VyLmluZm8oYOKGkiAke3dvcmtlci50b2tlbk5hbWV9WyR7d29ya2VyLnRva2VuSWR9XSAobW9kZWw6ICR7cmVxLm1vZGVsfSwgW3N0cmVhbV0pYCk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsICh3KSA9PiB0aGlzLmV4ZWN1dGVTdHJlYW1UdXJuKHcsIHJlcSwgY2IpKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZW5xdWV1ZSgodykgPT4ge1xuICAgICAgbG9nZ2VyLmluZm8oYOKGkiAke3cudG9rZW5OYW1lfVske3cudG9rZW5JZH1dIChtb2RlbDogJHtyZXEubW9kZWx9LCBbc3RyZWFtXSwgcXVldWVkKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZVN0cmVhbVR1cm4odywgcmVxLCBjYik7XG4gICAgfSwgZXhjbHVkZWRUb2tlbklkcyk7XG4gIH1cblxuICAvLyByZXVzZSDsooztkZzqsIAg7Jyg7Zqo7ZWY66m0IOq3uCB3b3JrZXIg66W8IGJ1c3kg7KCQ7Jyg7ZW0IOuwmO2ZmC4g7JeG6rGw64KYIO2PtOuwsSDrjIDsg4HsnbTrqbQgbnVsbC5cbiAgLy8g7Y+067CxIOyCrOycoDog6riw64qlIG9mZiAvIOyijO2RnCDsl4bsnYwgLyB3b3JrZXIg67aA7J6swrfso73snYwgLyBlcG9jaCDrtojsnbzsuZgocmVzdGFydCkgLyB0aHJlYWQg7IaM66m4IC9cbiAgLy8gICAgICAgICAgICBidXN5IOuMgOq4sCDtg4DsnoTslYTsm4MuIG51bGwg67CY7ZmYIOyLnCDtmLjstpzrtoDripQg7IOIIHRocmVhZCDqsr3roZzroZwg7KeE7ZaJLlxuICBhc3luYyBhY3F1aXJlUmV1c2VXb3JrZXIoXG4gICAgcmVxOiBHZW5lcmF0ZVJlcXVlc3QsXG4gICAgZXhjbHVkZWRUb2tlbklkcyA9IG5ldyBTZXQ8bnVtYmVyPigpLFxuICApOiBQcm9taXNlPENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbD4ge1xuICAgIC8vIOydtOuvuOyngCDsmpTssq3snYAg7ZWt7IOBIGNvbGQgdGhyZWFkKFI4KTog7J6s7IKs7JqpIOyijO2RnOqwgCDsnojslrTrj4Qg6rG064SI65u064ukLlxuICAgIC8vIGJhc2U2NCDqsIAgdGhyZWFkIOuplOuqqOumrMK37LqQ7IucIHByZWZpeCDsl5Ag7IOB7KO87ZWY64qUIOqyg+ydhCDrp4nripTri6QuXG4gICAgaWYgKHJlcS5pbWFnZUdlbmVyYXRpb24pIHJldHVybiBudWxsO1xuICAgIGlmICghVEhSRUFEX1JFVVNFX0VOQUJMRUQgfHwgIXJlcS5yZXVzZSkgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgeyB3b3JrZXJJZCwgdGhyZWFkSWQsIGVwb2NoIH0gPSByZXEucmV1c2U7XG5cbiAgICBjb25zdCB3b3JrZXIgPSB0aGlzLmZpbmRXb3JrZXJCeUlkKHdvcmtlcklkKTtcbiAgICBpZiAoIXdvcmtlciB8fCAhd29ya2VyLmlzUmVhZHkgfHwgIXdvcmtlci5hY3RpdmUpIHJldHVybiBudWxsO1xuICAgIGlmICh3b3JrZXIuZXBvY2ggIT09IGVwb2NoKSByZXR1cm4gbnVsbDtcbiAgICBpZiAoIXdvcmtlci5oYXNUaHJlYWQodGhyZWFkSWQpKSByZXR1cm4gbnVsbDtcbiAgICBpZiAoIShhd2FpdCB0aGlzLmlzVG9rZW5RdW90YUVsaWdpYmxlKHdvcmtlci50b2tlbklkLCB3b3JrZXIudG9rZW5OYW1lLCBleGNsdWRlZFRva2VuSWRzKSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIFJFVVNFX1dPUktFUl9XQUlUX01TO1xuICAgIGZvciAoOzspIHtcbiAgICAgIC8vIHJlc3RhcnQoZXBvY2gg67OA6rK9KSAvIHRocmVhZCDshozrqbjsnbQg64yA6riwIOykkeyXkCDrsJzsg53tlZjrqbQg7Y+067CxLlxuICAgICAgaWYgKHdvcmtlci5lcG9jaCAhPT0gZXBvY2ggfHwgIXdvcmtlci5oYXNUaHJlYWQodGhyZWFkSWQpKSByZXR1cm4gbnVsbDtcbiAgICAgIGlmICh3b3JrZXIudHJ5QWNxdWlyZVR1cm4oKSkgcmV0dXJuIHdvcmtlcjtcbiAgICAgIGlmIChEYXRlLm5vdygpID49IGRlYWRsaW5lKSByZXR1cm4gbnVsbDtcbiAgICAgIGF3YWl0IHNsZWVwKFJFVVNFX1dPUktFUl9QT0xMX01TKTtcbiAgICB9XG4gIH1cblxuICBmaW5kV29ya2VyQnlJZCh3b3JrZXJJZDogbnVtYmVyKTogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIgfCBudWxsIHtcbiAgICBmb3IgKGNvbnN0IHdvcmtlcnMgb2YgdGhpcy53b3JrZXJQb29sLnZhbHVlcygpKSB7XG4gICAgICBmb3IgKGNvbnN0IHcgb2Ygd29ya2Vycykge1xuICAgICAgICBpZiAobWFrZU9wZW5BSVdvcmtlcklkKHcudG9rZW5JZCwgdy53b3JrZXJJbmRleCkgPT09IHdvcmtlcklkKSByZXR1cm4gdztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBhc3luYyBpbnRlcnJ1cHRXb3JrZXJUdXJuKHRocmVhZElkOiBzdHJpbmcsIHR1cm5JZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgYWxsV29ya2VycyA9IFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKGFsbFdvcmtlcnMubWFwKCh3KSA9PiB3LmludGVycnVwdFR1cm4odGhyZWFkSWQsIHR1cm5JZCkpKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBXb3JrZXIgc2VsZWN0aW9uIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICAvLyBRdW90YS1lbGlnaWJsZSBpZGxlIHRva2Vu7J2EIHdlaWdodOuhnCDqs6Drpbgg65KkLCDqt7ggdG9rZW4g7JWI7JeQ7IScIHdvcmtlcuulvCDsiJztmZjtlZzri6QuXG4gIGFzeW5jIGFjcXVpcmVJZGxlV29ya2VyKFxuICAgIGV4Y2x1ZGVkVG9rZW5JZHMgPSBuZXcgU2V0PG51bWJlcj4oKSxcbiAgKTogUHJvbWlzZTxDb2RleEFwcFNlcnZlcldvcmtlciB8IG51bGw+IHtcbiAgICBjb25zdCBlbGlnaWJpbGl0eSA9IGF3YWl0IHRoaXMucmVzb2x2ZVRva2VuRWxpZ2liaWxpdHkoZXhjbHVkZWRUb2tlbklkcyk7XG4gICAgaWYgKGVsaWdpYmlsaXR5LnJlYWR5QWN0aXZlVG9rZW5JZHMuc2l6ZSA9PT0gMCkgcmV0dXJuIG51bGw7XG4gICAgaWYgKGVsaWdpYmlsaXR5LmVsaWdpYmxlVG9rZW5JZHMuc2l6ZSA9PT0gMCkgdGhpcy50aHJvd1F1b3RhVGhyZXNob2xkRXhjZWVkZWQoZWxpZ2liaWxpdHkpO1xuXG4gICAgY29uc3Qgd29ya2Vyc0J5VG9rZW4gPSBuZXcgTWFwPG51bWJlciwgQ29kZXhBcHBTZXJ2ZXJXb3JrZXJbXT4oKTtcbiAgICBmb3IgKGNvbnN0IHdvcmtlciBvZiB0aGlzLmdldEFsbFJlYWR5QWN0aXZlV29ya2VycygpKSB7XG4gICAgICBpZiAoIWVsaWdpYmlsaXR5LmVsaWdpYmxlVG9rZW5JZHMuaGFzKHdvcmtlci50b2tlbklkKSB8fCAhd29ya2VyLmhhc0NhcGFjaXR5KSBjb250aW51ZTtcbiAgICAgIGNvbnN0IHdvcmtlcnMgPSB3b3JrZXJzQnlUb2tlbi5nZXQod29ya2VyLnRva2VuSWQpID8/IFtdO1xuICAgICAgd29ya2Vycy5wdXNoKHdvcmtlcik7XG4gICAgICB3b3JrZXJzQnlUb2tlbi5zZXQod29ya2VyLnRva2VuSWQsIHdvcmtlcnMpO1xuICAgIH1cblxuICAgIGNvbnN0IHNlbGVjdGVkVG9rZW5JZCA9IHRoaXMud2VpZ2h0ZWRTZWxlY3Rvci5zZWxlY3QobmV3IFNldCh3b3JrZXJzQnlUb2tlbi5rZXlzKCkpKTtcbiAgICBpZiAoc2VsZWN0ZWRUb2tlbklkID09PSBudWxsKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCB3b3JrZXJzID0gd29ya2Vyc0J5VG9rZW4uZ2V0KHNlbGVjdGVkVG9rZW5JZCkhO1xuICAgIGNvbnN0IGN1cnNvciA9IHRoaXMud29ya2VyQ3Vyc29yQnlUb2tlbi5nZXQoc2VsZWN0ZWRUb2tlbklkKSA/PyAwO1xuICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IHdvcmtlcnMubGVuZ3RoOyBvZmZzZXQrKykge1xuICAgICAgY29uc3QgaW5kZXggPSAoY3Vyc29yICsgb2Zmc2V0KSAlIHdvcmtlcnMubGVuZ3RoO1xuICAgICAgY29uc3Qgd29ya2VyID0gd29ya2Vyc1tpbmRleF0hO1xuICAgICAgaWYgKHdvcmtlci50cnlBY3F1aXJlVHVybigpKSB7XG4gICAgICAgIHRoaXMud29ya2VyQ3Vyc29yQnlUb2tlbi5zZXQoc2VsZWN0ZWRUb2tlbklkLCAoaW5kZXggKyAxKSAlIHdvcmtlcnMubGVuZ3RoKTtcbiAgICAgICAgcmV0dXJuIHdvcmtlcjtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYHdlaWdodGVkIHRva2VuICR7c2VsZWN0ZWRUb2tlbklkfSBsb3N0IGlkbGUgY2FwYWNpdHkgZHVyaW5nIHN5bmNocm9ub3VzIGFjcXVpcmVgLFxuICAgICk7XG4gIH1cblxuICBnZXRBbGxSZWFkeUFjdGl2ZVdvcmtlcnMoKTogQ29kZXhBcHBTZXJ2ZXJXb3JrZXJbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSAmJiB3LmFjdGl2ZSk7XG4gIH1cblxuICAvLyDilIDilIAgUXVldWUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgZW5xdWV1ZTxUPihcbiAgICBleGVjdXRlOiAod29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcikgPT4gUHJvbWlzZTxUPixcbiAgICBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCksXG4gICk6IFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGVsaWdpYmlsaXR5ID0gYXdhaXQgdGhpcy5yZXNvbHZlVG9rZW5FbGlnaWJpbGl0eShleGNsdWRlZFRva2VuSWRzKTtcbiAgICBpZiAoZWxpZ2liaWxpdHkucmVhZHlBY3RpdmVUb2tlbklkcy5zaXplID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoXCJOT19PUEVOQUlfV09SS0VSU1wiKTtcbiAgICBpZiAoZWxpZ2liaWxpdHkuZWxpZ2libGVUb2tlbklkcy5zaXplID09PSAwKSB0aGlzLnRocm93UXVvdGFUaHJlc2hvbGRFeGNlZWRlZChlbGlnaWJpbGl0eSk7XG4gICAgaWYgKHRoaXMucXVldWUubGVuZ3RoID49IE1BWF9RVUVVRV9TSVpFKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTRVJWRVJfQlVTWVwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8VD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgaXRlbTogUXVldWVJdGVtID0ge1xuICAgICAgICByZXNvbHZlOiAod29ya2VyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsIGV4ZWN1dGUpKVxuICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSxcbiAgICAgICAgcmVqZWN0OiAoZXJyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfSxcbiAgICAgICAgdGltZXI6IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRoaXMucmVtb3ZlRnJvbVF1ZXVlKGl0ZW0pO1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJTRVJWRVJfQlVTWVwiKSk7XG4gICAgICAgIH0sIFFVRVVFX1RJTUVPVVRfTVMpLFxuICAgICAgICBleGNsdWRlZFRva2VuSWRzOiBuZXcgU2V0KGV4Y2x1ZGVkVG9rZW5JZHMpLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5xdWV1ZS5wdXNoKGl0ZW0pO1xuICAgICAgdGhpcy5yZXF1ZXN0QXV0b3NjYWxlRXZhbHVhdGlvbigpO1xuICAgIH0pO1xuICB9XG5cbiAgcmVtb3ZlRnJvbVF1ZXVlKGl0ZW06IFF1ZXVlSXRlbSk6IHZvaWQge1xuICAgIGNsZWFyVGltZW91dChpdGVtLnRpbWVyKTtcbiAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgY29uc3QgaWR4ID0gdGhpcy5xdWV1ZS5pbmRleE9mKGl0ZW0pO1xuICAgIGlmIChpZHggIT09IC0xKSB0aGlzLnF1ZXVlLnNwbGljZShpZHgsIDEpO1xuICB9XG5cbiAgcmVqZWN0QWxsUXVldWVkKHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgZXJyID0gbmV3IEVycm9yKHJlYXNvbik7XG4gICAgdGhpcy5xdWV1ZS5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQoaXRlbS50aW1lcik7XG4gICAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgICBpdGVtLnJlamVjdChlcnIpO1xuICAgIH0pO1xuICAgIHRoaXMucXVldWUgPSBbXTtcbiAgfVxuXG4gIGFzeW5jIGRyYWluUXVldWUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuZHJhaW5pbmcpIHtcbiAgICAgIHRoaXMuZHJhaW5BZ2FpbiA9IHRydWU7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5kcmFpbmluZyA9IHRydWU7XG4gICAgdHJ5IHtcbiAgICAgIGRvIHtcbiAgICAgICAgdGhpcy5kcmFpbkFnYWluID0gZmFsc2U7XG4gICAgICAgIGF3YWl0IHRoaXMuZHJhaW5RdWV1ZU9uY2UoKTtcbiAgICAgIH0gd2hpbGUgKHRoaXMuZHJhaW5BZ2Fpbik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbG9nZ2VyLndhcm4oYGRyYWluUXVldWUgZmFpbGVkOiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmRyYWluaW5nID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBkcmFpblF1ZXVlT25jZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB3aGlsZSAodGhpcy5xdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBuZXh0ID0gdGhpcy5xdWV1ZVswXSE7XG4gICAgICBsZXQgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlciB8IG51bGw7XG4gICAgICB0cnkge1xuICAgICAgICB3b3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVJZGxlV29ya2VyKG5leHQuZXhjbHVkZWRUb2tlbklkcyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChlIGluc3RhbmNlb2YgUXVvdGFUaHJlc2hvbGRFeGNlZWRlZEVycm9yKSB7XG4gICAgICAgICAgdGhpcy5xdWV1ZS5zaGlmdCgpO1xuICAgICAgICAgIG5leHQucmVqZWN0KGUpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgICBpZiAoIXdvcmtlcikgYnJlYWs7XG4gICAgICB0aGlzLnF1ZXVlLnNoaWZ0KCk7XG4gICAgICBuZXh0LnJlc29sdmUod29ya2VyKTtcbiAgICB9XG4gIH1cblxuICAvLyDilIDilIAgRXhlY3V0aW9uIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGFzeW5jIGV4ZWN1dGVBbmRSZWxlYXNlPFQ+KFxuICAgIHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIsXG4gICAgZXhlY3V0ZTogKHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpID0+IFByb21pc2U8VD4sXG4gICk6IFByb21pc2U8VD4ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgZXhlY3V0ZSh3b3JrZXIpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB3b3JrZXIucmVsZWFzZVR1cm4oKTtcbiAgICAgIHRoaXMucmVxdWVzdERyYWluUXVldWUoKTtcbiAgICB9XG4gIH1cblxuICAvLyByZXVzZVRocmVhZElkIOqwgCDsnojsnLzrqbQg6riw7KG0IHRocmVhZCDsl5AgZGVsdGEocmV1c2VJbnB1dCnrp4wsIOyXhuycvOuptCDsg4ggdGhyZWFkIOyXkCDsoITssrRcbiAgLy8gcHJvbXB0KGNvbGRJbnB1dCkgKyBoaXN0b3J5IGluamVjdC4gcmV1c2Ug6rCAIGRpc3BhdGNoZXIg64uo7JeQ7IScIO2PtOuwseuQmOuptCDtm4TsnpDroZwg65ao7Ja07KeE64ukLlxuICBwcml2YXRlIGJ1aWxkVHVyblJlcXVlc3QocmVxOiBHZW5lcmF0ZVJlcXVlc3QsIHJldXNlVGhyZWFkSWQ/OiBzdHJpbmcpOiBUdXJuUmVxdWVzdCB7XG4gICAgY29uc3QgcmV1c2luZyA9IHJldXNlVGhyZWFkSWQgIT09IHVuZGVmaW5lZDtcbiAgICByZXR1cm4ge1xuICAgICAgaW5wdXQ6IHJldXNpbmcgJiYgcmVxLnJldXNlSW5wdXQgPyByZXEucmV1c2VJbnB1dCA6IHJlcS5jb2xkSW5wdXQsXG4gICAgICBoaXN0b3J5OiByZXVzaW5nID8gdW5kZWZpbmVkIDogcmVxLmNvbGRIaXN0b3J5LFxuICAgICAgZGV2ZWxvcGVySW5zdHJ1Y3Rpb25zOiByZXEuc3lzdGVtUHJvbXB0LFxuICAgICAgb3V0cHV0U2NoZW1hOiByZXEub3V0cHV0U2NoZW1hLFxuICAgICAgZWZmb3J0OiByZXEuZWZmb3J0ID8/IERFRkFVTFRfRUZGT1JULFxuICAgICAgbW9kZWw6IHJlcS5tb2RlbCxcbiAgICAgIHZlcmJvc2l0eTogcmVxLnZlcmJvc2l0eSxcbiAgICAgIHJlYXNvbmluZ1N1bW1hcnk6IHJlcS5yZWFzb25pbmdTdW1tYXJ5LFxuICAgICAgc2VydmljZVRpZXI6IHJlcS5zZXJ2aWNlVGllcixcbiAgICAgIGltYWdlR2VuZXJhdGlvbjogcmVxLmltYWdlR2VuZXJhdGlvbixcbiAgICAgIGltYWdlR2VuZXJhdGlvbk9wdGlvbnM6IHJlcS5pbWFnZUdlbmVyYXRpb25PcHRpb25zLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBleGVjdXRlVHVybihcbiAgICB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyLFxuICAgIHJlcTogR2VuZXJhdGVSZXF1ZXN0LFxuICAgIHJldXNlVGhyZWFkSWQ/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8R2VuZXJhdGVSZXN1bHQ+IHtcbiAgICAvLyDsnbTrr7jsp4Ag7JqU7LKtIOyCrOyghCDqsozsnbTtirgoUjUpOiDrsLDsoJXrkJwgd29ya2VyIOydmCBjYXBhYmlsaXR5ICsg7KCB7JqpIOuqqOuNuCDrqYDti7Drqqjri6wuXG4gICAgLy8g67aI7Lap7KGx7J2066m0IHR1cm4g7J2EIOyLpO2Wie2VmOyngCDslYrqs6Ag66qF7Iuc7KCBIOyXkOufrC5cbiAgICBpZiAocmVxLmltYWdlR2VuZXJhdGlvbikge1xuICAgICAgY29uc3QgcmVhc29uID0gYXdhaXQgd29ya2VyLmNoZWNrSW1hZ2VHZW5lcmF0aW9uU3VwcG9ydChyZXEubW9kZWwpO1xuICAgICAgaWYgKHJlYXNvbikgdGhyb3cgbmV3IEltYWdlR2VuZXJhdGlvbkVycm9yKFwiZ2F0ZVwiLCByZWFzb24pO1xuICAgIH1cblxuICAgIGNvbnN0IHR1cm5SZXEgPSB0aGlzLmJ1aWxkVHVyblJlcXVlc3QocmVxLCByZXVzZVRocmVhZElkKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3b3JrZXIuZXhlY3V0ZVR1cm4odHVyblJlcSwgcmV1c2VUaHJlYWRJZCk7XG5cbiAgICAvLyDsnbTrr7jsp4AgMOqwnCDsi6TtjKgg67aE66WYKFI2KTogdG9vbCDrr7jtmLjstpwo7J6s7Iuc64+EIOustOydtSkgdnMg7Iuc64+EIO2bhCDrr7jsmYTshLEo7J6s7Iuc64+EIO2bhOuztCkuXG4gICAgaWYgKHJlcS5pbWFnZUdlbmVyYXRpb24gJiYgKCFyZXN1bHQuaW1hZ2VzIHx8IHJlc3VsdC5pbWFnZXMubGVuZ3RoID09PSAwKSkge1xuICAgICAgdGhyb3cgcmVzdWx0LmltYWdlQXR0ZW1wdGVkXG4gICAgICAgID8gbmV3IEltYWdlR2VuZXJhdGlvbkVycm9yKFwiaW5jb21wbGV0ZVwiLCBcImltYWdlIHRvb2wgcmFuIGJ1dCBwcm9kdWNlZCBubyBjb21wbGV0ZWQgaW1hZ2VcIilcbiAgICAgICAgOiBuZXcgSW1hZ2VHZW5lcmF0aW9uRXJyb3IoXCJub3RfY2FsbGVkXCIsIFwibW9kZWwgZGlkIG5vdCBjYWxsIHRoZSBpbWFnZV9nZW5lcmF0aW9uIHRvb2xcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRleHQ6IHJlc3VsdC50ZXh0LFxuICAgICAgdG9rZW5OYW1lOiB3b3JrZXIudG9rZW5OYW1lLFxuICAgICAgdXNhZ2U6IHJlc3VsdC51c2FnZSxcbiAgICAgIGR1cmF0aW9uTXM6IHJlc3VsdC5kdXJhdGlvbk1zLFxuICAgICAgdHRmdE1zOiByZXN1bHQudHRmdE1zLFxuICAgICAgbW9kZWw6IHJlc3VsdC5tb2RlbCxcbiAgICAgIHRocmVhZENvb3JkOiB7XG4gICAgICAgIHdvcmtlcklkOiBtYWtlT3BlbkFJV29ya2VySWQod29ya2VyLnRva2VuSWQsIHdvcmtlci53b3JrZXJJbmRleCksXG4gICAgICAgIHRocmVhZElkOiByZXN1bHQudGhyZWFkSWQsXG4gICAgICAgIGVwb2NoOiB3b3JrZXIuZXBvY2gsXG4gICAgICB9LFxuICAgICAgaW1hZ2VzOiByZXN1bHQuaW1hZ2VzLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBleGVjdXRlU3RyZWFtVHVybihcbiAgICB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyLFxuICAgIHJlcTogR2VuZXJhdGVSZXF1ZXN0LFxuICAgIGNiOiBHZW5lcmF0ZVN0cmVhbUNhbGxiYWNrcyxcbiAgICByZXVzZVRocmVhZElkPzogc3RyaW5nLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB0dXJuUmVxID0gdGhpcy5idWlsZFR1cm5SZXF1ZXN0KHJlcSwgcmV1c2VUaHJlYWRJZCk7XG4gICAgLy8gd29ya2VyIOydmCBUdXJuUmVzdWx0IOyXkCB0b2tlbk5hbWUvdGhyZWFkQ29vcmQg66W8IOu2meyXrCDsg4HsnIQoR2VuZXJhdGVSZXN1bHQp66GcIOyYrOumsOuLpC5cbiAgICAvLyB0aHJlYWRJZCDripQg7IOIIHRocmVhZCDrqbQgb25UaHJlYWRJZCDroZwg7ZmV7KCV65CY66+A66GcIOuvuOumrCDrs7TqtIDtlbQg65GQ6rOgIG9uQ29tcGxldGUg65WMIOydveuKlOuLpC5cbiAgICBsZXQgcmVzb2x2ZWRUaHJlYWRJZCA9IHJldXNlVGhyZWFkSWQgPz8gXCJcIjtcbiAgICBjb25zdCB3cmFwcGVkQ2I6IFN0cmVhbUNhbGxiYWNrcyA9IHtcbiAgICAgIC4uLmNiLFxuICAgICAgb25UaHJlYWRJZDogKHRocmVhZElkKSA9PiB7XG4gICAgICAgIHJlc29sdmVkVGhyZWFkSWQgPSB0aHJlYWRJZDtcbiAgICAgICAgY2Iub25UaHJlYWRJZD8uKHRocmVhZElkKTtcbiAgICAgIH0sXG4gICAgICBvbkNvbXBsZXRlOiAocmVzdWx0KSA9PiB7XG4gICAgICAgIGNiLm9uQ29tcGxldGUoe1xuICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgICB0b2tlbk5hbWU6IHdvcmtlci50b2tlbk5hbWUsXG4gICAgICAgICAgdGhyZWFkQ29vcmQ6IHtcbiAgICAgICAgICAgIHdvcmtlcklkOiBtYWtlT3BlbkFJV29ya2VySWQod29ya2VyLnRva2VuSWQsIHdvcmtlci53b3JrZXJJbmRleCksXG4gICAgICAgICAgICB0aHJlYWRJZDogcmVzb2x2ZWRUaHJlYWRJZCxcbiAgICAgICAgICAgIGVwb2NoOiB3b3JrZXIuZXBvY2gsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgIH07XG4gICAgYXdhaXQgd29ya2VyLmV4ZWN1dGVUdXJuU3RyZWFtKHR1cm5SZXEsIHdyYXBwZWRDYiwgcmV1c2VUaHJlYWRJZCk7XG4gIH1cblxuICAvLyDilIDilIAgU3Bhd24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgc3Bhd25Xb3JrZXJzKFxuICAgIHRva2VuSWQ6IG51bWJlcixcbiAgICB0b2tlbk5hbWU6IHN0cmluZyxcbiAgICBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHMsXG4gICAgcXVvdGFUaHJlc2hvbGQ/OiBudW1iZXIgfCBudWxsLFxuICAgIHdlaWdodCA9IDEsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuc2V0VG9rZW5NZXRhZGF0YSh0b2tlbklkLCB0b2tlbk5hbWUsIGNyZWRlbnRpYWxzLCBxdW90YVRocmVzaG9sZCwgd2VpZ2h0KTtcbiAgICBjb25zdCB3b3JrZXJzOiBDb2RleEFwcFNlcnZlcldvcmtlcltdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnBvb2xDb25maWcubWluV29ya2Vyc1BlclRva2VuOyBpKyspIHtcbiAgICAgIGlmIChpID4gMCkgYXdhaXQgc2xlZXAoU1BBV05fSU5URVJWQUxfTVMpO1xuICAgICAgY29uc3Qgd29ya2VyID0gYXdhaXQgdGhpcy5zcGF3blNpbmdsZVdvcmtlcih0b2tlbklkLCB0b2tlbk5hbWUsIGNyZWRlbnRpYWxzLCBpKTtcbiAgICAgIGlmICh3b3JrZXIpIHdvcmtlcnMucHVzaCh3b3JrZXIpO1xuICAgIH1cbiAgICBpZiAod29ya2Vycy5sZW5ndGggPiAwKSB0aGlzLndvcmtlclBvb2wuc2V0KHRva2VuSWQsIHdvcmtlcnMpO1xuICB9XG5cbiAgYXN5bmMgc3Bhd25TaW5nbGVXb3JrZXIoXG4gICAgdG9rZW5JZDogbnVtYmVyLFxuICAgIHRva2VuTmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICB3b3JrZXJJbmRleDogbnVtYmVyLFxuICApOiBQcm9taXNlPENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbD4ge1xuICAgIGNvbnN0IHdvcmtlciA9IG5ldyBDb2RleEFwcFNlcnZlcldvcmtlcih7XG4gICAgICB0b2tlbklkLFxuICAgICAgdG9rZW5OYW1lLFxuICAgICAgYWNjZXNzVG9rZW46IGNyZWRlbnRpYWxzLmFjY2Vzc1Rva2VuLFxuICAgICAgYWNjb3VudElkOiBjcmVkZW50aWFscy5hY2NvdW50SWQsXG4gICAgICBwbGFuVHlwZTogY3JlZGVudGlhbHMucGxhblR5cGUsXG4gICAgICB3b3JrZXJJbmRleCxcbiAgICB9KTtcblxuICAgIHdvcmtlci5vblJlYWR5ID0gKCkgPT4gdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSgpO1xuXG4gICAgd29ya2VyLnNldFNlcnZlclJlcXVlc3RIYW5kbGVyKGFzeW5jIChtZXRob2QpID0+IHtcbiAgICAgIGlmIChtZXRob2QgPT09IFwiYWNjb3VudC9jaGF0Z3B0QXV0aFRva2Vucy9yZWZyZXNoXCIpIHtcbiAgICAgICAgcmV0dXJuIGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCh0b2tlbklkKTtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5oYW5kbGVkIHNlcnZlci1yZXF1ZXN0OiAke21ldGhvZH1gKTtcbiAgICB9KTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB3b3JrZXIuaW5pdGlhbGl6ZSgpO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlciBzcGF3bmVkOiAke3Rva2VuTmFtZX1bJHt3b3JrZXJJbmRleH1dYCk7XG4gICAgICByZXR1cm4gd29ya2VyO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci53YXJuKGB3b3JrZXIgc3Bhd24gZmFpbGVkOiAke3Rva2VuTmFtZX1bJHt3b3JrZXJJbmRleH1dOiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICAgICAgYXdhaXQgd29ya2VyLmtpbGwoKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICBhc3luYyBldmFsdWF0ZUF1dG9zY2FsaW5nKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5wb29sQ29uZmlnLmF1dG9zY2FsZSB8fCB0aGlzLnN0b3BwZWQpIHJldHVybjtcbiAgICBpZiAodGhpcy5xdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICBhd2FpdCB0aGlzLnNjYWxlVXBPbmVTdGVwKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChEYXRlLm5vdygpIC0gdGhpcy5sYXN0UmVxdWVzdEF0ID49IHRoaXMucG9vbENvbmZpZy5zY2FsZURvd25JZGxlTXMpIHtcbiAgICAgIGF3YWl0IHRoaXMuc2NhbGVEb3duT25lU3RlcCgpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHNjYWxlVXBPbmVTdGVwKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5wb29sQ29uZmlnLmF1dG9zY2FsZSB8fCB0aGlzLnN0b3BwZWQpIHJldHVybjtcbiAgICBhd2FpdCB0aGlzLnJ1blNjYWxpbmcoYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgY2FuZGlkYXRlcyA9IFsuLi50aGlzLnRva2VuTWV0YWRhdGEuZW50cmllcygpXS5maWx0ZXIoKFt0b2tlbklkLCBtZXRhZGF0YV0pID0+IHtcbiAgICAgICAgaWYgKCFtZXRhZGF0YS5hY3RpdmUpIHJldHVybiBmYWxzZTtcbiAgICAgICAgcmV0dXJuICh0aGlzLndvcmtlclBvb2wuZ2V0KHRva2VuSWQpPy5sZW5ndGggPz8gMCkgPCB0aGlzLnBvb2xDb25maWcubWF4V29ya2Vyc1BlclRva2VuO1xuICAgICAgfSk7XG4gICAgICBpZiAoY2FuZGlkYXRlcy5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgICAgY29uc3QgcHJvamVjdGVkV29ya2VyQ291bnQgPSB0aGlzLndvcmtlckNvdW50ICsgY2FuZGlkYXRlcy5sZW5ndGg7XG4gICAgICBjb25zdCBwcm9qZWN0ZWRSc3NHaUIgPSBlc3RpbWF0ZU9wZW5BSVdvcmtlclJzc0dpQihwcm9qZWN0ZWRXb3JrZXJDb3VudCk7XG4gICAgICBpZiAocHJvamVjdGVkUnNzR2lCID4gdGhpcy5wb29sQ29uZmlnLm1heEVzdGltYXRlZFJzc0dpQikge1xuICAgICAgICBsb2dnZXIud2FybihcbiAgICAgICAgICBgb3BlbmFpIGF1dG9zY2FsZSBibG9ja2VkOiBlc3RpbWF0ZWQgUlNTICR7cHJvamVjdGVkUnNzR2lCLnRvRml4ZWQoMil9R2lCIGV4Y2VlZHMgJHt0aGlzLnBvb2xDb25maWcubWF4RXN0aW1hdGVkUnNzR2lCLnRvRml4ZWQoMil9R2lCYCxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBob3N0QXZhaWxhYmxlR2lCID0gdGhpcy5nZXRIb3N0QXZhaWxhYmxlR2lCKCk7XG4gICAgICBpZiAoaG9zdEF2YWlsYWJsZUdpQiA8IHRoaXMucG9vbENvbmZpZy5taW5Ib3N0QXZhaWxhYmxlR2lCKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICAgIGBvcGVuYWkgYXV0b3NjYWxlIGJsb2NrZWQ6IGhvc3QgYXZhaWxhYmxlICR7aG9zdEF2YWlsYWJsZUdpQi50b0ZpeGVkKDIpfUdpQiBiZWxvdyAke3RoaXMucG9vbENvbmZpZy5taW5Ib3N0QXZhaWxhYmxlR2lCLnRvRml4ZWQoMil9R2lCYCxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzcGF3bmVkID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGNhbmRpZGF0ZXMubWFwKGFzeW5jIChbdG9rZW5JZCwgbWV0YWRhdGFdKSA9PiB7XG4gICAgICAgICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQodG9rZW5JZCkgPz8gW107XG4gICAgICAgICAgY29uc3Qgd29ya2VySW5kZXggPSB0aGlzLm5leHRBdmFpbGFibGVXb3JrZXJJbmRleCh3b3JrZXJzKTtcbiAgICAgICAgICBpZiAod29ya2VySW5kZXggPj0gdGhpcy5wb29sQ29uZmlnLm1heFdvcmtlcnNQZXJUb2tlbikgcmV0dXJuIG51bGw7XG4gICAgICAgICAgY29uc3Qgd29ya2VyID0gYXdhaXQgdGhpcy5zcGF3blNpbmdsZVdvcmtlcihcbiAgICAgICAgICAgIHRva2VuSWQsXG4gICAgICAgICAgICBtZXRhZGF0YS5uYW1lLFxuICAgICAgICAgICAgbWV0YWRhdGEuY3JlZGVudGlhbHMsXG4gICAgICAgICAgICB3b3JrZXJJbmRleCxcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICghd29ya2VyKSByZXR1cm4gbnVsbDtcblxuICAgICAgICAgIGNvbnN0IGN1cnJlbnRNZXRhZGF0YSA9IHRoaXMudG9rZW5NZXRhZGF0YS5nZXQodG9rZW5JZCk7XG4gICAgICAgICAgY29uc3QgY3VycmVudFdvcmtlcnMgPSB0aGlzLndvcmtlclBvb2wuZ2V0KHRva2VuSWQpO1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICFjdXJyZW50TWV0YWRhdGE/LmFjdGl2ZSB8fFxuICAgICAgICAgICAgY3VycmVudE1ldGFkYXRhICE9PSBtZXRhZGF0YSB8fFxuICAgICAgICAgICAgIWN1cnJlbnRXb3JrZXJzIHx8XG4gICAgICAgICAgICBjdXJyZW50V29ya2Vycy5zb21lKChlbnRyeSkgPT4gZW50cnkud29ya2VySW5kZXggPT09IHdvcmtlckluZGV4KVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgYXdhaXQgd29ya2VyLmtpbGwoKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgY3VycmVudFdvcmtlcnMucHVzaCh3b3JrZXIpO1xuICAgICAgICAgIGN1cnJlbnRXb3JrZXJzLnNvcnQoKGEsIGIpID0+IGEud29ya2VySW5kZXggLSBiLndvcmtlckluZGV4KTtcbiAgICAgICAgICByZXR1cm4gd29ya2VyO1xuICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGFkZGVkID0gc3Bhd25lZC5maWx0ZXIoKHdvcmtlcikgPT4gd29ya2VyICE9PSBudWxsKS5sZW5ndGg7XG4gICAgICBpZiAoYWRkZWQgPiAwKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICAgIGBvcGVuYWkgYXV0b3NjYWxlIHVwOiArJHthZGRlZH0gd29ya2VycyAoJHt0aGlzLndvcmtlckNvdW50fSB0b3RhbCwgcXVldWUgJHt0aGlzLnF1ZXVlLmxlbmd0aH0pYCxcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSgpO1xuICAgICAgICBpZiAodGhpcy5xdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KFxuICAgICAgICAgICAgKCkgPT4gdGhpcy5yZXF1ZXN0QXV0b3NjYWxlRXZhbHVhdGlvbigpLFxuICAgICAgICAgICAgTWF0aC5taW4odGhpcy5wb29sQ29uZmlnLnNjYWxlSW50ZXJ2YWxNcywgMV8wMDApLFxuICAgICAgICAgICk7XG4gICAgICAgICAgdGltZXIudW5yZWY/LigpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBzY2FsZURvd25PbmVTdGVwKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5wb29sQ29uZmlnLmF1dG9zY2FsZSB8fCB0aGlzLnN0b3BwZWQpIHJldHVybjtcbiAgICBhd2FpdCB0aGlzLnJ1blNjYWxpbmcoYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcmVtb3ZlZDogQ29kZXhBcHBTZXJ2ZXJXb3JrZXJbXSA9IFtdO1xuICAgICAgZm9yIChjb25zdCB0b2tlbklkIG9mIHRoaXMudG9rZW5NZXRhZGF0YS5rZXlzKCkpIHtcbiAgICAgICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQodG9rZW5JZCkgPz8gW107XG4gICAgICAgIGlmICh3b3JrZXJzLmxlbmd0aCA8PSB0aGlzLnBvb2xDb25maWcubWluV29ya2Vyc1BlclRva2VuKSBjb250aW51ZTtcblxuICAgICAgICBjb25zdCB3b3JrZXIgPSB3b3JrZXJzXG4gICAgICAgICAgLnRvU29ydGVkKChhLCBiKSA9PiBiLndvcmtlckluZGV4IC0gYS53b3JrZXJJbmRleClcbiAgICAgICAgICAuZmluZCgoZW50cnkpID0+IGVudHJ5Lmhhc0NhcGFjaXR5KTtcbiAgICAgICAgaWYgKCF3b3JrZXIpIGNvbnRpbnVlO1xuXG4gICAgICAgIHRoaXMud29ya2VyUG9vbC5zZXQoXG4gICAgICAgICAgdG9rZW5JZCxcbiAgICAgICAgICB3b3JrZXJzLmZpbHRlcigoZW50cnkpID0+IGVudHJ5ICE9PSB3b3JrZXIpLFxuICAgICAgICApO1xuICAgICAgICByZW1vdmVkLnB1c2god29ya2VyKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHJlbW92ZWQubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQocmVtb3ZlZC5tYXAoKHdvcmtlcikgPT4gd29ya2VyLmtpbGwoKSkpO1xuICAgICAgbG9nZ2VyLmluZm8oYG9wZW5haSBhdXRvc2NhbGUgZG93bjogLSR7cmVtb3ZlZC5sZW5ndGh9IHdvcmtlcnMgKCR7dGhpcy53b3JrZXJDb3VudH0gdG90YWwpYCk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIG5leHRBdmFpbGFibGVXb3JrZXJJbmRleCh3b3JrZXJzOiBDb2RleEFwcFNlcnZlcldvcmtlcltdKTogbnVtYmVyIHtcbiAgICBjb25zdCB1c2VkID0gbmV3IFNldCh3b3JrZXJzLm1hcCgod29ya2VyKSA9PiB3b3JrZXIud29ya2VySW5kZXgpKTtcbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdGhpcy5wb29sQ29uZmlnLm1heFdvcmtlcnNQZXJUb2tlbjsgaW5kZXgrKykge1xuICAgICAgaWYgKCF1c2VkLmhhcyhpbmRleCkpIHJldHVybiBpbmRleDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMucG9vbENvbmZpZy5tYXhXb3JrZXJzUGVyVG9rZW47XG4gIH1cblxuICBwcml2YXRlIHJlcXVlc3RBdXRvc2NhbGVFdmFsdWF0aW9uKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5wb29sQ29uZmlnLmF1dG9zY2FsZSB8fCB0aGlzLnN0b3BwZWQpIHJldHVybjtcbiAgICB2b2lkIHRoaXMuZXZhbHVhdGVBdXRvc2NhbGluZygpLmNhdGNoKChlKSA9PlxuICAgICAgbG9nZ2VyLndhcm4oYG9wZW5haSBhdXRvc2NhbGUgZXZhbHVhdGlvbiBmYWlsZWQ6ICR7KGUgYXMgRXJyb3IpLm1lc3NhZ2V9YCksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcnVuU2NhbGluZyh0YXNrOiAoKSA9PiBQcm9taXNlPHZvaWQ+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuc2NhbGluZ1Byb21pc2UpIHtcbiAgICAgIGF3YWl0IHRoaXMuc2NhbGluZ1Byb21pc2U7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHNjYWxpbmcgPSB0YXNrKCkuZmluYWxseSgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5zY2FsaW5nUHJvbWlzZSA9PT0gc2NhbGluZykgdGhpcy5zY2FsaW5nUHJvbWlzZSA9IG51bGw7XG4gICAgfSk7XG4gICAgdGhpcy5zY2FsaW5nUHJvbWlzZSA9IHNjYWxpbmc7XG4gICAgYXdhaXQgc2NhbGluZztcbiAgfVxuXG4gIC8vIOKUgOKUgCBSYXRlIGxpbWl0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICByYXRlTGltaXRzQ2FjaGUgPSBuZXcgTWFwPG51bWJlciwgeyBkYXRhOiBHZXRBY2NvdW50UmF0ZUxpbWl0c1Jlc3BvbnNlOyBjYWNoZWRBdDogbnVtYmVyIH0+KCk7XG4gIHN0YXRpYyByZWFkb25seSBSQVRFX0xJTUlUU19DQUNIRV9UVEwgPSA2MF8wMDA7XG5cbiAgYXN5bmMgZ2V0UmF0ZUxpbWl0c0J5VG9rZW5JZCh0b2tlbklkOiBudW1iZXIpOiBQcm9taXNlPE9wZW5BSVJhdGVMaW1pdHNXaXRoTWV0YT4ge1xuICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMucmF0ZUxpbWl0c0NhY2hlLmdldCh0b2tlbklkKTtcbiAgICBpZiAoY2FjaGVkICYmIERhdGUubm93KCkgLSBjYWNoZWQuY2FjaGVkQXQgPCBPcGVuQUlEaXNwYXRjaGVyLlJBVEVfTElNSVRTX0NBQ0hFX1RUTCkge1xuICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICB9XG5cbiAgICBjb25zdCB3b3JrZXIgPSAodGhpcy53b3JrZXJQb29sLmdldCh0b2tlbklkKSA/PyBbXSkuZmluZCgodykgPT4gdy5pc1JlYWR5KTtcbiAgICBpZiAoIXdvcmtlcikgdGhyb3cgbmV3IEVycm9yKFwibm8gcmVhZHkgb3BlbmFpIHdvcmtlcnNcIik7XG4gICAgY29uc3QgZGF0YSA9IChhd2FpdCB3b3JrZXIuZ2V0UmF0ZUxpbWl0cygpKSBhcyBHZXRBY2NvdW50UmF0ZUxpbWl0c1Jlc3BvbnNlO1xuICAgIGNvbnN0IGVudHJ5ID0geyBkYXRhLCBjYWNoZWRBdDogRGF0ZS5ub3coKSB9O1xuICAgIHRoaXMucmF0ZUxpbWl0c0NhY2hlLnNldCh0b2tlbklkLCBlbnRyeSk7XG4gICAgcmV0dXJuIGVudHJ5O1xuICB9XG5cbiAgcHJpdmF0ZSByZXF1ZXN0RHJhaW5RdWV1ZSgpOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMuZHJhaW5RdWV1ZSgpLmNhdGNoKChlKSA9PiBsb2dnZXIud2FybihgZHJhaW5RdWV1ZSBmYWlsZWQ6ICR7KGUgYXMgRXJyb3IpLm1lc3NhZ2V9YCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRUb2tlbk1ldGFkYXRhKFxuICAgIGlkOiBudW1iZXIsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICBxdW90YVRocmVzaG9sZDogbnVtYmVyIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgICB3ZWlnaHQ6IG51bWJlcixcbiAgKTogdm9pZCB7XG4gICAgdGhpcy50b2tlbk1ldGFkYXRhLnNldChpZCwge1xuICAgICAgbmFtZSxcbiAgICAgIGNyZWRlbnRpYWxzLFxuICAgICAgcXVvdGFUaHJlc2hvbGQsXG4gICAgICB3ZWlnaHQsXG4gICAgICBhY3RpdmU6IHRoaXMudG9rZW5NZXRhZGF0YS5nZXQoaWQpPy5hY3RpdmUgPz8gdHJ1ZSxcbiAgICB9KTtcbiAgICB0aGlzLndlaWdodGVkU2VsZWN0b3Iuc2V0VG9rZW4oaWQsIHdlaWdodCk7XG4gIH1cblxuICBwcml2YXRlIGdldFF1b3RhVGhyZXNob2xkKHRva2VuSWQ6IG51bWJlcik6IG51bWJlciB8IG51bGwgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnRva2VuTWV0YWRhdGEuZ2V0KHRva2VuSWQpPy5xdW90YVRocmVzaG9sZDtcbiAgfVxuXG4gIHByaXZhdGUgaGFzUXVvdGFUaHJlc2hvbGQodG9rZW5JZDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRRdW90YVRocmVzaG9sZCh0b2tlbklkKTtcbiAgICByZXR1cm4gdGhyZXNob2xkICE9PSB1bmRlZmluZWQgJiYgdGhyZXNob2xkICE9PSBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZXNvbHZlVG9rZW5FbGlnaWJpbGl0eShleGNsdWRlZFRva2VuSWRzOiBTZXQ8bnVtYmVyPik6IFByb21pc2U8VG9rZW5FbGlnaWJpbGl0eT4ge1xuICAgIGNvbnN0IHdvcmtlcnMgPSB0aGlzLmdldEFsbFJlYWR5QWN0aXZlV29ya2VycygpO1xuICAgIGNvbnN0IGJ5VG9rZW4gPSBuZXcgTWFwPG51bWJlciwgc3RyaW5nPigpO1xuICAgIGZvciAoY29uc3Qgd29ya2VyIG9mIHdvcmtlcnMpIHtcbiAgICAgIGlmICghYnlUb2tlbi5oYXMod29ya2VyLnRva2VuSWQpKSBieVRva2VuLnNldCh3b3JrZXIudG9rZW5JZCwgd29ya2VyLnRva2VuTmFtZSk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVhZHlBY3RpdmVUb2tlbklkcyA9IG5ldyBTZXQoYnlUb2tlbi5rZXlzKCkpO1xuICAgIGNvbnN0IGVsaWdpYmxlVG9rZW5JZHMgPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgICBjb25zdCBvdmVyVGhyZXNob2xkVG9rZW5zOiBBcnJheTx7IHRva2VuTmFtZTogc3RyaW5nOyB0aHJlc2hvbGQ6IG51bWJlciB9PiA9IFtdO1xuICAgIGxldCB0aHJlc2hvbGRlZFRva2VuQ291bnQgPSAwO1xuXG4gICAgY29uc3QgZW50cmllcyA9IEFycmF5LmZyb20oYnlUb2tlbi5lbnRyaWVzKCkpO1xuICAgIGNvbnN0IGNoZWNrcyA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgIGVudHJpZXMubWFwKGFzeW5jIChbdG9rZW5JZCwgdG9rZW5OYW1lXSkgPT4ge1xuICAgICAgICBpZiAoZXhjbHVkZWRUb2tlbklkcy5oYXModG9rZW5JZCkpIHtcbiAgICAgICAgICB0aHJlc2hvbGRlZFRva2VuQ291bnQrKztcbiAgICAgICAgICByZXR1cm4geyB0b2tlbklkLCB0b2tlbk5hbWUsIGVsaWdpYmxlOiBmYWxzZSB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5oYXNRdW90YVRocmVzaG9sZCh0b2tlbklkKSkge1xuICAgICAgICAgIHJldHVybiB7IHRva2VuSWQsIHRva2VuTmFtZSwgZWxpZ2libGU6IHRydWUgfTtcbiAgICAgICAgfVxuICAgICAgICB0aHJlc2hvbGRlZFRva2VuQ291bnQrKztcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0b2tlbklkLFxuICAgICAgICAgIHRva2VuTmFtZSxcbiAgICAgICAgICBlbGlnaWJsZTogYXdhaXQgdGhpcy5pc1Rva2VuUXVvdGFFbGlnaWJsZSh0b2tlbklkLCB0b2tlbk5hbWUpLFxuICAgICAgICB9O1xuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNoZWNrcy5mb3JFYWNoKChjaGVjaywgaW5kZXgpID0+IHtcbiAgICAgIGlmIChjaGVjay5zdGF0dXMgPT09IFwiZnVsZmlsbGVkXCIpIHtcbiAgICAgICAgaWYgKGNoZWNrLnZhbHVlLmVsaWdpYmxlKSB7XG4gICAgICAgICAgZWxpZ2libGVUb2tlbklkcy5hZGQoY2hlY2sudmFsdWUudG9rZW5JZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRRdW90YVRocmVzaG9sZChjaGVjay52YWx1ZS50b2tlbklkKTtcbiAgICAgICAgICBpZiAodGhyZXNob2xkICE9PSB1bmRlZmluZWQgJiYgdGhyZXNob2xkICE9PSBudWxsKSB7XG4gICAgICAgICAgICBvdmVyVGhyZXNob2xkVG9rZW5zLnB1c2goeyB0b2tlbk5hbWU6IGNoZWNrLnZhbHVlLnRva2VuTmFtZSwgdGhyZXNob2xkIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVudHJ5ID0gZW50cmllc1tpbmRleF07XG4gICAgICBpZiAoZW50cnkpIHtcbiAgICAgICAgY29uc3QgW3Rva2VuSWQsIHRva2VuTmFtZV0gPSBlbnRyeTtcbiAgICAgICAgdGhpcy5sb2dRdW90YUxvb2t1cEZhaWxPcGVuKHRva2VuSWQsIHRva2VuTmFtZSwgU3RyaW5nKGNoZWNrLnJlYXNvbikpO1xuICAgICAgICBlbGlnaWJsZVRva2VuSWRzLmFkZCh0b2tlbklkKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB7IHJlYWR5QWN0aXZlVG9rZW5JZHMsIGVsaWdpYmxlVG9rZW5JZHMsIG92ZXJUaHJlc2hvbGRUb2tlbnMsIHRocmVzaG9sZGVkVG9rZW5Db3VudCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc1Rva2VuUXVvdGFFbGlnaWJsZShcbiAgICB0b2tlbklkOiBudW1iZXIsXG4gICAgdG9rZW5OYW1lOiBzdHJpbmcsXG4gICAgZXhjbHVkZWRUb2tlbklkcz86IFNldDxudW1iZXI+LFxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCB0aHJlc2hvbGQgPSB0aGlzLmdldFF1b3RhVGhyZXNob2xkKHRva2VuSWQpO1xuICAgIGlmICh0aHJlc2hvbGQgPT09IHVuZGVmaW5lZCB8fCB0aHJlc2hvbGQgPT09IG51bGwpIHJldHVybiB0cnVlO1xuXG4gICAgbGV0IHJlc3VsdDogT3BlbkFJUXVvdGFVc2FnZVJlc3VsdDtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgcmVhZE9wZW5BSVF1b3RhVXNhZ2UoKCkgPT4gdGhpcy5nZXRSYXRlTGltaXRzQnlUb2tlbklkKHRva2VuSWQpKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aGlzLmxvZ1F1b3RhTG9va3VwRmFpbE9wZW4odG9rZW5JZCwgdG9rZW5OYW1lLCAoZSBhcyBFcnJvcikubWVzc2FnZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAocmVzdWx0LmtpbmQgPT09IFwibG9va3VwX2ZhaWxlZFwiKSB7XG4gICAgICB0aGlzLmxvZ1F1b3RhTG9va3VwRmFpbE9wZW4odG9rZW5JZCwgdG9rZW5OYW1lLCByZXN1bHQucmVhc29uKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmIChyZXN1bHQudXRpbGl6YXRpb25QY3QgPj0gdGhyZXNob2xkKSB7XG4gICAgICB0aGlzLmxvZ1F1b3RhT3ZlclRocmVzaG9sZCh0b2tlbklkLCB0b2tlbk5hbWUsIHRocmVzaG9sZCwgcmVzdWx0KTtcbiAgICAgIGV4Y2x1ZGVkVG9rZW5JZHM/LmFkZCh0b2tlbklkKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHByaXZhdGUgbG9nUXVvdGFPdmVyVGhyZXNob2xkKFxuICAgIHRva2VuSWQ6IG51bWJlcixcbiAgICB0b2tlbk5hbWU6IHN0cmluZyxcbiAgICB0aHJlc2hvbGQ6IG51bWJlcixcbiAgICByZXN1bHQ6IEV4dHJhY3Q8T3BlbkFJUXVvdGFVc2FnZVJlc3VsdCwgeyBraW5kOiBcIm9rXCIgfT4sXG4gICk6IHZvaWQge1xuICAgIGxvZ2dlci5pbmZvKFwicXVvdGFfdGhyZXNob2xkIGdhdGU6IG92ZXJfdGhyZXNob2xkXCIsIHtcbiAgICAgIHRva2VuSWQsXG4gICAgICB0b2tlbk5hbWUsXG4gICAgICBwcm92aWRlcjogXCJvcGVuYWlcIixcbiAgICAgIHRocmVzaG9sZCxcbiAgICAgIGNhY2hlZFV0aWxpemF0aW9uOiByZXN1bHQudXRpbGl6YXRpb25QY3QsXG4gICAgICBjYWNoZUFnZTogcmVzdWx0LmNhY2hlQWdlTXMsXG4gICAgICB3aW5kb3dEdXJhdGlvbk1pbnM6IHJlc3VsdC53aW5kb3dEdXJhdGlvbk1pbnMsXG4gICAgICByZXNldHNBdDogcmVzdWx0LnJlc2V0c0F0LFxuICAgICAgbGltaXRJZDogcmVzdWx0LmxpbWl0SWQsXG4gICAgICByZWFzb246IFwib3Zlcl90aHJlc2hvbGRcIixcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgbG9nUXVvdGFMb29rdXBGYWlsT3Blbih0b2tlbklkOiBudW1iZXIsIHRva2VuTmFtZTogc3RyaW5nLCByZWFzb246IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IHRocmVzaG9sZCA9IHRoaXMuZ2V0UXVvdGFUaHJlc2hvbGQodG9rZW5JZCk7XG4gICAgbG9nZ2VyLndhcm4oXCJxdW90YV90aHJlc2hvbGQgZ2F0ZTogbG9va3VwX2ZhaWxfb3BlblwiLCB7XG4gICAgICB0b2tlbklkLFxuICAgICAgdG9rZW5OYW1lLFxuICAgICAgcHJvdmlkZXI6IFwib3BlbmFpXCIsXG4gICAgICB0aHJlc2hvbGQsXG4gICAgICByZWFzb246IFwibG9va3VwX2ZhaWxfb3BlblwiLFxuICAgICAgbG9va3VwUmVhc29uOiByZWFzb24sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHRocm93UXVvdGFUaHJlc2hvbGRFeGNlZWRlZChlbGlnaWJpbGl0eTogVG9rZW5FbGlnaWJpbGl0eSk6IG5ldmVyIHtcbiAgICBsb2dnZXIud2FybihcInF1b3RhX3RocmVzaG9sZCBnYXRlOiBhbGxfZXhjZWVkZWRcIiwge1xuICAgICAgcHJvdmlkZXI6IFwib3BlbmFpXCIsXG4gICAgICB0b2tlbkNvdW50OiBlbGlnaWJpbGl0eS5yZWFkeUFjdGl2ZVRva2VuSWRzLnNpemUsXG4gICAgICB0aHJlc2hvbGRlZFRva2VuQ291bnQ6IGVsaWdpYmlsaXR5LnRocmVzaG9sZGVkVG9rZW5Db3VudCxcbiAgICAgIG92ZXJUaHJlc2hvbGRUb2tlbnM6IGVsaWdpYmlsaXR5Lm92ZXJUaHJlc2hvbGRUb2tlbnMsXG4gICAgICByZWFzb246IFwiYWxsX2V4Y2VlZGVkXCIsXG4gICAgfSk7XG4gICAgdGhyb3cgbmV3IFF1b3RhVGhyZXNob2xkRXhjZWVkZWRFcnJvcihcbiAgICAgIHF1b3RhVGhyZXNob2xkRXhjZWVkZWRNZXNzYWdlKFwib3BlbmFpXCIsIGVsaWdpYmlsaXR5Lm92ZXJUaHJlc2hvbGRUb2tlbnMpLFxuICAgICk7XG4gIH1cblxuICAvLyDilIDilIAgQnJvd3NlciBsb2dpbiBmbG93IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIHBlbmRpbmdMb2dpbjoge1xuICAgIHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXI7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PjtcbiAgfSB8IG51bGwgPSBudWxsO1xuXG4gIGFzeW5jIHN0YXJ0QnJvd3NlckxvZ2luKG5hbWU6IHN0cmluZyk6IFByb21pc2U8eyBhdXRoVXJsOiBzdHJpbmcgfT4ge1xuICAgIGlmICh0aGlzLnBlbmRpbmdMb2dpbikge1xuICAgICAgdGhpcy5wZW5kaW5nTG9naW4ud29ya2VyLmtpbGwoKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5wZW5kaW5nTG9naW4udGltZXIpO1xuICAgICAgdGhpcy5wZW5kaW5nTG9naW4gPSBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHRlbXBJZCA9IERhdGUubm93KCk7XG4gICAgY29uc3Qgd29ya2VyID0gbmV3IENvZGV4QXBwU2VydmVyV29ya2VyKHtcbiAgICAgIHRva2VuSWQ6IHRlbXBJZCxcbiAgICAgIHRva2VuTmFtZTogbmFtZSxcbiAgICAgIGFjY2Vzc1Rva2VuOiBcIlwiLFxuICAgICAgYWNjb3VudElkOiBcIlwiLFxuICAgIH0pO1xuXG4gICAgY29uc3QgYXV0aFVybCA9IGF3YWl0IHdvcmtlci5zdGFydEJyb3dzZXJMb2dpbigpO1xuXG4gICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGlmICh0aGlzLnBlbmRpbmdMb2dpbj8ud29ya2VyID09PSB3b3JrZXIpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oYGJyb3dzZXIgbG9naW4gdGltZW91dCBmb3IgJHtuYW1lfSwga2lsbGluZyB3b3JrZXJgKTtcbiAgICAgICAgd29ya2VyLmtpbGwoKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICAgIHRoaXMucGVuZGluZ0xvZ2luID0gbnVsbDtcbiAgICAgIH1cbiAgICB9LCAzMDBfMDAwKTtcblxuICAgIHRoaXMucGVuZGluZ0xvZ2luID0geyB3b3JrZXIsIG5hbWUsIHRpbWVyIH07XG4gICAgcmV0dXJuIHsgYXV0aFVybCB9O1xuICB9XG5cbiAgZ2V0IHBlbmRpbmdMb2dpbk5hbWUoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMucGVuZGluZ0xvZ2luPy5uYW1lID8/IG51bGw7XG4gIH1cblxuICBhc3luYyBjb21wbGV0ZUJyb3dzZXJMb2dpbigpOiBQcm9taXNlPHtcbiAgICBhY2Nlc3NUb2tlbjogc3RyaW5nO1xuICAgIHJlZnJlc2hUb2tlbjogc3RyaW5nO1xuICAgIGlkVG9rZW4/OiBzdHJpbmc7XG4gICAgYWNjb3VudElkOiBzdHJpbmc7XG4gIH0+IHtcbiAgICBpZiAoIXRoaXMucGVuZGluZ0xvZ2luKSB0aHJvdyBuZXcgRXJyb3IoXCJubyBwZW5kaW5nIGxvZ2luXCIpO1xuICAgIGNvbnN0IHsgd29ya2VyLCB0aW1lciB9ID0gdGhpcy5wZW5kaW5nTG9naW47XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgd29ya2VyLndhaXRGb3JCcm93c2VyTG9naW5Db21wbGV0ZSgpO1xuICAgICAgY29uc3QgY3JlZHMgPSBhd2FpdCB3b3JrZXIucmVhZE1hbmFnZWRDcmVkZW50aWFscygpO1xuICAgICAgaWYgKCFjcmVkcykgdGhyb3cgbmV3IEVycm9yKFwiZmFpbGVkIHRvIHJlYWQgY3JlZGVudGlhbHMgYWZ0ZXIgbG9naW5cIik7XG4gICAgICByZXR1cm4gY3JlZHM7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICB0aGlzLnBlbmRpbmdMb2dpbiA9IG51bGw7XG4gICAgICBhd2FpdCB3b3JrZXIua2lsbCgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICB9XG4gIH1cblxuICAvLyDilIDilIAgU3RhdHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgZ2V0IHdvcmtlckNvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5sZW5ndGg7XG4gIH1cblxuICBnZXQgcmVhZHlXb3JrZXJDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkuZmlsdGVyKCh3KSA9PiB3LmlzUmVhZHkpLmxlbmd0aDtcbiAgfVxuXG4gIGdldCBxdWV1ZUxlbmd0aCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlLmxlbmd0aDtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZ0NBLE1BQU0sU0FBUyxVQUFVLENBQUMsU0FBUyxvQkFBb0IsQ0FBQztBQVF4RCxJQUFhLHVCQUFiLGNBQTBDLE1BQU07Q0FDOUMsWUFDRSxNQUNBLFNBQ0E7QUFDQSxRQUFNLFFBQVE7QUFITCxPQUFBLE9BQUE7QUFJVCxPQUFLLE9BQU87OztBQUloQixNQUFNLGlCQUFpQjtBQUN2QixNQUFhLCtCQUErQjtBQUM1QyxNQUFNLHVDQUF1QztBQUM3QyxNQUFNLHVDQUF1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
|