sonamu 0.9.20 → 0.10.1
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/dist/_virtual/_rolldown/runtime.js +36 -0
- package/dist/ai/agents/agent.js +5 -7
- package/dist/ai/agents/index.js +1 -2
- package/dist/ai/agents/types.js +1 -1
- package/dist/ai/index.js +1 -2
- package/dist/ai/providers/rtzr/api.js +2 -3
- package/dist/ai/providers/rtzr/error.js +14 -29
- package/dist/ai/providers/rtzr/index.js +1 -2
- package/dist/ai/providers/rtzr/model.js +13 -20
- package/dist/ai/providers/rtzr/options.js +2 -3
- package/dist/ai/providers/rtzr/provider.js +2 -3
- package/dist/ai/providers/rtzr/utils.js +12 -21
- package/dist/api/base-frame.js +4 -4
- package/dist/api/caster.js +21 -38
- package/dist/api/code-converters.js +41 -98
- package/dist/api/config.d.ts +1 -10
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +9 -8
- package/dist/api/context.js +2 -3
- package/dist/api/decorators.js +80 -116
- package/dist/api/index.js +2 -3
- package/dist/api/secret.js +6 -10
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +210 -406
- package/dist/api/validator.js +5 -8
- package/dist/api/websocket-helpers.js +22 -33
- package/dist/auth/audit-log/builders.d.ts.map +1 -1
- package/dist/auth/audit-log/builders.js +4 -3
- package/dist/auth/audit-log/client-ip.d.ts +3 -0
- package/dist/auth/audit-log/client-ip.d.ts.map +1 -0
- package/dist/auth/audit-log/client-ip.js +27 -0
- package/dist/auth/audit-log/events.d.ts +1 -0
- package/dist/auth/audit-log/events.d.ts.map +1 -1
- package/dist/auth/audit-log/events.js +2 -2
- package/dist/auth/audit-log/plugin.js +30 -61
- package/dist/auth/audit-log-ingestor.d.ts.map +1 -1
- package/dist/auth/audit-log-ingestor.js +26 -43
- package/dist/auth/auth-generator.js +16 -41
- package/dist/auth/better-auth-entities.js +3 -4
- package/dist/auth/better-auth-request.d.ts +3 -0
- package/dist/auth/better-auth-request.d.ts.map +1 -0
- package/dist/auth/better-auth-request.js +23 -0
- package/dist/auth/index.js +2 -3
- package/dist/auth/knex-adapter.js +18 -45
- package/dist/auth/plugins/entity-definitions/admin.js +2 -2
- package/dist/auth/plugins/entity-definitions/anonymous.js +2 -2
- package/dist/auth/plugins/entity-definitions/api-key.js +2 -2
- package/dist/auth/plugins/entity-definitions/audit-log.js +2 -2
- package/dist/auth/plugins/entity-definitions/index.js +2 -3
- package/dist/auth/plugins/entity-definitions/jwt.js +2 -2
- package/dist/auth/plugins/entity-definitions/organization.js +2 -2
- package/dist/auth/plugins/entity-definitions/passkey.js +2 -2
- package/dist/auth/plugins/entity-definitions/phone-number.js +2 -2
- package/dist/auth/plugins/entity-definitions/sso.js +2 -2
- package/dist/auth/plugins/entity-definitions/two-factor.js +2 -2
- package/dist/auth/plugins/entity-definitions/types.js +1 -1
- package/dist/auth/plugins/entity-definitions/username.js +2 -2
- package/dist/auth/plugins/index.js +1 -2
- package/dist/auth/plugins/wrappers/admin.js +2 -3
- package/dist/auth/plugins/wrappers/anonymous.js +2 -3
- package/dist/auth/plugins/wrappers/api-key.js +2 -3
- package/dist/auth/plugins/wrappers/index.js +1 -2
- package/dist/auth/plugins/wrappers/jwt.js +2 -3
- package/dist/auth/plugins/wrappers/organization.js +2 -3
- package/dist/auth/plugins/wrappers/passkey.js +2 -3
- package/dist/auth/plugins/wrappers/phone-number.js +2 -3
- package/dist/auth/plugins/wrappers/sso.js +2 -3
- package/dist/auth/plugins/wrappers/two-factor.js +2 -3
- package/dist/auth/plugins/wrappers/username.js +2 -3
- package/dist/bin/build-config.js +2 -2
- package/dist/bin/cli.js +152 -259
- package/dist/bin/fixture.d.ts.map +1 -1
- package/dist/bin/fixture.js +55 -97
- package/dist/bin/hmr-hook-register.js +3 -3
- package/dist/bin/migrate-targets.d.ts +3 -0
- package/dist/bin/migrate-targets.d.ts.map +1 -0
- package/dist/bin/migrate-targets.js +11 -0
- package/dist/bin/test-command.js +25 -55
- package/dist/bin/ts-loader-register.js +5 -6
- package/dist/bin/ts-loader-registration.js +6 -13
- package/dist/cache/cache-manager.js +3 -4
- package/dist/cache/decorator.js +11 -21
- package/dist/cache/drivers.js +2 -3
- package/dist/cache/index.js +2 -3
- package/dist/cache/types.js +1 -1
- package/dist/cache-control/cache-control.js +21 -34
- package/dist/cache-control/types.js +1 -1
- package/dist/compress/compress.js +10 -10
- package/dist/compress/index.js +1 -2
- package/dist/compress/types.js +1 -1
- package/dist/cone/cone-generator.js +25 -63
- package/dist/database/_batch_update.js +26 -46
- package/dist/database/base-model.js +44 -97
- package/dist/database/base-model.types.js +1 -1
- package/dist/database/db.d.ts +8 -14
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +127 -72
- package/dist/database/knex.js +5 -8
- package/dist/database/puri-subset.types.js +1 -1
- package/dist/database/puri-wrapper.js +11 -15
- package/dist/database/puri.js +117 -234
- package/dist/database/puri.types.js +3 -4
- package/dist/database/transaction-context.js +4 -5
- package/dist/database/upsert-builder.js +109 -176
- package/dist/dict/en.d.ts +1 -0
- package/dist/dict/en.d.ts.map +1 -1
- package/dist/dict/en.js +4 -4
- package/dist/dict/index.js +2 -3
- package/dist/dict/ko.d.ts +1 -0
- package/dist/dict/ko.d.ts.map +1 -1
- package/dist/dict/ko.js +4 -4
- package/dist/dict/rc-keys.js +3 -4
- package/dist/dict/sd.js +8 -19
- package/dist/dict/sonamu-dictionary.js +141 -284
- package/dist/dict/types.js +1 -1
- package/dist/dict/utils.js +4 -5
- package/dist/entity/entity-manager.d.ts +2 -2
- package/dist/entity/entity-manager.js +34 -82
- package/dist/entity/entity-template-cone.js +33 -66
- package/dist/entity/entity.js +157 -311
- package/dist/env.d.ts +14 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +75 -0
- package/dist/exceptions/error-handler.js +2 -3
- package/dist/exceptions/so-exceptions.js +7 -5
- package/dist/filter/index.js +1 -2
- package/dist/filter/types.js +3 -4
- package/dist/filter/utils.js +21 -54
- package/dist/index.js +9 -8
- package/dist/logger/category.js +6 -12
- package/dist/logger/configure.js +23 -34
- package/dist/migration/code-generation.js +147 -315
- package/dist/migration/index-where-predicate.js +52 -144
- package/dist/migration/migration-set.js +19 -33
- package/dist/migration/migrator.d.ts +2 -0
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +69 -53
- package/dist/migration/postgresql-schema-reader.js +126 -225
- package/dist/migration/slack-confirm.d.ts +1 -0
- package/dist/migration/slack-confirm.d.ts.map +1 -1
- package/dist/migration/slack-confirm.js +28 -38
- package/dist/migration/types.js +1 -1
- package/dist/naite/messaging-types.js +1 -1
- package/dist/naite/naite-reporter.js +15 -32
- package/dist/naite/naite.js +43 -76
- package/dist/ssr/index.js +6 -9
- package/dist/ssr/registry.js +10 -18
- package/dist/ssr/renderer.js +10 -21
- package/dist/ssr/types.js +1 -1
- package/dist/storage/base-file.js +5 -10
- package/dist/storage/buffered-file.js +3 -4
- package/dist/storage/drivers.js +2 -3
- package/dist/storage/index.js +2 -3
- package/dist/storage/s3-driver.js +5 -9
- package/dist/storage/storage-manager.js +5 -5
- package/dist/storage/types.js +1 -1
- package/dist/storage/uploaded-file.js +4 -6
- package/dist/stream/index.js +1 -2
- package/dist/stream/sse.js +8 -13
- package/dist/stream/ws-audience-resolver.js +5 -5
- package/dist/stream/ws-audience.js +3 -4
- package/dist/stream/ws-cluster-bus.js +3 -4
- package/dist/stream/ws-core.js +1 -1
- package/dist/stream/ws-delivery.js +11 -25
- package/dist/stream/ws-local-connection-store.js +9 -18
- package/dist/stream/ws-presence-store.js +43 -97
- package/dist/stream/ws-registry.js +17 -22
- package/dist/stream/ws-telemetry-memory.js +38 -45
- package/dist/stream/ws-telemetry-trace.js +4 -6
- package/dist/stream/ws-telemetry.js +82 -135
- package/dist/stream/ws.js +47 -91
- package/dist/syncer/api-parser.js +81 -147
- package/dist/syncer/checksum.js +14 -32
- package/dist/syncer/code-generator.js +29 -47
- package/dist/syncer/entity-operations.js +17 -27
- package/dist/syncer/event-batcher.js +8 -15
- package/dist/syncer/file-patterns.js +3 -4
- package/dist/syncer/file-tracking.js +6 -10
- package/dist/syncer/index.js +1 -2
- package/dist/syncer/module-loader.js +10 -26
- package/dist/syncer/syncer-actions.js +19 -37
- package/dist/syncer/syncer.js +46 -98
- package/dist/syncer/watcher.js +12 -26
- package/dist/tasks/decorator.js +7 -11
- package/dist/tasks/step-wrapper.js +7 -8
- package/dist/tasks/workflow-manager.js +18 -25
- package/dist/template/entity-converter.js +40 -64
- package/dist/template/helpers.js +32 -63
- package/dist/template/implementations/entity.template.js +7 -11
- package/dist/template/implementations/entry-server.template.js +2 -3
- package/dist/template/implementations/generated.template.js +25 -51
- package/dist/template/implementations/generated_http.template.js +31 -58
- package/dist/template/implementations/generated_sso.template.js +45 -85
- package/dist/template/implementations/init_types.template.js +4 -7
- package/dist/template/implementations/model.template.js +5 -10
- package/dist/template/implementations/model_test.template.js +2 -3
- package/dist/template/implementations/queries.template.js +4 -7
- package/dist/template/implementations/sd.template.js +17 -35
- package/dist/template/implementations/services.template.js +18 -30
- package/dist/template/implementations/view_form.template.js +72 -125
- package/dist/template/implementations/view_id_all_select.template.js +2 -3
- package/dist/template/implementations/view_list.template.js +86 -143
- package/dist/template/implementations/view_search_input.template.js +2 -3
- package/dist/template/index.js +5 -8
- package/dist/template/template-manager.js +13 -26
- package/dist/template/template-types.js +2 -3
- package/dist/template/template.js +7 -11
- package/dist/template/zod-converter.js +173 -348
- package/dist/testing/_relation-graph.js +18 -37
- package/dist/testing/bootstrap.js +5 -8
- package/dist/testing/data-explorer.js +34 -78
- package/dist/testing/dev-test-routes.js +54 -60
- package/dist/testing/dev-vitest-manager.js +33 -84
- package/dist/testing/faker-mappings.js +3 -4
- package/dist/testing/fixture-generator.d.ts +2 -1
- package/dist/testing/fixture-generator.d.ts.map +1 -1
- package/dist/testing/fixture-generator.js +159 -321
- package/dist/testing/fixture-loader.js +2 -2
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +124 -227
- package/dist/testing/global-setup.d.ts.map +1 -1
- package/dist/testing/global-setup.js +29 -17
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +5 -4
- package/dist/testing/naite-vitest-reporter.js +2 -3
- package/dist/testing/parallel-db-manager.js +5 -3
- package/dist/testing/vitest-helpers.d.ts.map +1 -1
- package/dist/testing/vitest-helpers.js +15 -12
- package/dist/types/types.d.ts +14 -14
- package/dist/types/types.js +27 -50
- package/dist/ui/ai-api.js +6 -11
- package/dist/ui/ai-client.js +86 -134
- package/dist/ui/api.js +100 -196
- package/dist/ui/cdd-service.js +78 -130
- package/dist/ui/cdd-types.js +1 -1
- package/dist/ui-web/assets/{index-Df8q-fhb.js → index-DFStGyd0.js} +49 -49
- package/dist/ui-web/assets/index-Dx4ap5i4.css +1 -0
- package/dist/ui-web/index.html +2 -2
- package/dist/utils/async-utils.js +13 -25
- package/dist/utils/class-name.js +3 -4
- package/dist/utils/console-util.js +11 -26
- package/dist/utils/controller.d.ts.map +1 -1
- package/dist/utils/controller.js +14 -12
- package/dist/utils/esm-utils.js +5 -8
- package/dist/utils/formatter.js +10 -22
- package/dist/utils/fs-utils.js +14 -25
- package/dist/utils/lodash-able.js +3 -4
- package/dist/utils/model.js +7 -14
- package/dist/utils/object-utils.js +41 -73
- package/dist/utils/path-utils.js +5 -9
- package/dist/utils/process-utils.js +4 -7
- package/dist/utils/sql-parser.js +6 -13
- package/dist/utils/type-utils.js +16 -26
- package/dist/utils/utils.js +18 -40
- package/dist/utils/zod-error.js +9 -16
- package/dist/vector/chunking.js +24 -37
- package/dist/vector/config.js +2 -2
- package/dist/vector/embedding.js +8 -19
- package/dist/vector/index.js +1 -2
- package/dist/vector/types.js +1 -1
- package/package.json +8 -8
- package/src/__tests__/env.test.ts +127 -0
- package/src/api/__tests__/config.test.ts +10 -1
- package/src/api/config.ts +4 -12
- package/src/api/sonamu.ts +28 -33
- package/src/auth/audit-log/builders.ts +3 -0
- package/src/auth/audit-log/client-ip.ts +38 -0
- package/src/auth/audit-log/events.ts +1 -0
- package/src/auth/audit-log-ingestor.ts +22 -15
- package/src/auth/better-auth-request.ts +20 -0
- package/src/bin/__tests__/migrate-targets.test.ts +28 -0
- package/src/bin/__tests__/test-command.test.ts +82 -1
- package/src/bin/cli.ts +9 -18
- package/src/bin/fixture.ts +5 -4
- package/src/bin/migrate-targets.ts +7 -0
- package/src/bin/test-command.ts +2 -2
- package/src/database/__tests__/db.test.ts +175 -0
- package/src/database/db.ts +193 -71
- package/src/dict/en.ts +2 -0
- package/src/dict/ko.ts +2 -0
- package/src/env.ts +123 -0
- package/src/migration/__tests__/migrator.test.ts +149 -0
- package/src/migration/migrator.ts +74 -17
- package/src/migration/slack-confirm.ts +21 -0
- package/src/skills/sonamu/database.md +1 -1
- package/src/skills/sonamu/puri.md +33 -0
- package/src/skills/sonamu/testing-devrunner.md +1 -1
- package/src/stream/ws-telemetry-memory.ts +2 -2
- package/src/syncer/checksum.ts +7 -12
- package/src/testing/fixture-generator.ts +2 -1
- package/src/testing/fixture-manager.ts +3 -4
- package/src/testing/global-setup.ts +42 -18
- package/src/testing/index.ts +1 -0
- package/src/testing/vitest-helpers.ts +14 -0
- package/src/utils/controller.ts +14 -7
- package/tsdown.api.config.ts +6 -0
- package/dist/_virtual/rolldown_runtime.js +0 -39
- package/dist/ui-web/assets/index-D4rYm-Xz.css +0 -1
package/dist/api/sonamu.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { __esmMin } from "../_virtual/
|
|
1
|
+
import { __esmMin } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { getSonamuEnvironment, init_env, readAllEnvironmentSnapshots } from "../env.js";
|
|
2
3
|
import { DB, init_db } from "../database/db.js";
|
|
3
4
|
import { BASE_FIELD_MAPPINGS, init_better_auth_entities } from "../auth/better-auth-entities.js";
|
|
5
|
+
import { convertFastifyHeadersToStandard, init_utils, merge } from "../utils/utils.js";
|
|
6
|
+
import { createBetterAuthRequest, init_better_auth_request } from "../auth/better-auth-request.js";
|
|
4
7
|
import { CachePresets, applyCacheHeaders, init_cache_control } from "../cache-control/cache-control.js";
|
|
5
8
|
import { init_compress, toFastifyCompressOption } from "../compress/compress.js";
|
|
6
9
|
import { SD, init_sd, setSDConfig } from "../dict/sd.js";
|
|
@@ -12,22 +15,18 @@ import { WebSocketRuntime, init_ws } from "../stream/ws.js";
|
|
|
12
15
|
import { centerText, init_console_util } from "../utils/console-util.js";
|
|
13
16
|
import { init_controller, isDaemonServer } from "../utils/controller.js";
|
|
14
17
|
import { exists, fileExists, init_fs_utils } from "../utils/fs-utils.js";
|
|
15
|
-
import { convertFastifyHeadersToStandard, init_utils, merge } from "../utils/utils.js";
|
|
16
18
|
import { getSecrets, init_secret } from "./secret.js";
|
|
17
19
|
import { createWebSocketReplyStub, init_websocket_helpers, resolveIntegratedViteHmrOptions, resolveWebSocketCloseDescriptor, resolveWebSocketPluginOptions } from "./websocket-helpers.js";
|
|
18
20
|
import { AsyncLocalStorage } from "async_hooks";
|
|
19
21
|
import { dispose } from "@logtape/logtape";
|
|
20
|
-
import fs from "fs/promises";
|
|
21
22
|
import path from "path";
|
|
23
|
+
import fs from "fs/promises";
|
|
22
24
|
import chalk from "chalk";
|
|
23
25
|
import os from "os";
|
|
24
26
|
import mime, { lookup } from "mime-types";
|
|
25
|
-
|
|
26
27
|
//#region src/api/sonamu.ts
|
|
27
28
|
function getWebSocketTelemetryContext(ws) {
|
|
28
|
-
if (!isTelemetryContextProvider(ws)) {
|
|
29
|
-
return {};
|
|
30
|
-
}
|
|
29
|
+
if (!isTelemetryContextProvider(ws)) return {};
|
|
31
30
|
return ws.getTelemetryContext();
|
|
32
31
|
}
|
|
33
32
|
function isTelemetryContextProvider(ws) {
|
|
@@ -38,29 +37,26 @@ function isTelemetryContextProvider(ws) {
|
|
|
38
37
|
*/
|
|
39
38
|
function defaultKeyGenerator(file) {
|
|
40
39
|
const ext = mime.extension(file.mimetype) || "bin";
|
|
41
|
-
|
|
42
|
-
const random = Math.random().toString(36).slice(2, 8);
|
|
43
|
-
return `uploads/${timestamp}-${random}.${ext}`;
|
|
40
|
+
return `uploads/${Date.now()}-${Math.random().toString(36).slice(2, 8)}.${ext}`;
|
|
44
41
|
}
|
|
45
42
|
function formatTime(ms) {
|
|
46
|
-
|
|
47
|
-
return ` (${formatted})`;
|
|
43
|
+
return ` (${ms >= 1e3 ? `${(ms / 1e3).toFixed(2)}s` : `${Math.round(ms)}ms`})`;
|
|
48
44
|
}
|
|
49
45
|
function isLocalHost(host) {
|
|
50
46
|
return LOCAL_HOSTS.has(host) || host.endsWith(".local");
|
|
51
47
|
}
|
|
52
48
|
function runGuards({ guards, config, request, api }) {
|
|
53
|
-
for (const guard of guards ?? [])
|
|
54
|
-
config.guardHandler(guard, request, api);
|
|
55
|
-
}
|
|
49
|
+
for (const guard of guards ?? []) config.guardHandler(guard, request, api);
|
|
56
50
|
}
|
|
57
51
|
var SonamuClass, Sonamu, LOCAL_HOSTS;
|
|
58
52
|
var init_sonamu = __esmMin((() => {
|
|
59
53
|
init_better_auth_entities();
|
|
54
|
+
init_better_auth_request();
|
|
60
55
|
init_cache_control();
|
|
61
56
|
init_compress();
|
|
62
57
|
init_db();
|
|
63
58
|
init_sd();
|
|
59
|
+
init_env();
|
|
64
60
|
init_so_exceptions();
|
|
65
61
|
init_buffered_file();
|
|
66
62
|
init_uploaded_file();
|
|
@@ -78,33 +74,26 @@ var init_sonamu = __esmMin((() => {
|
|
|
78
74
|
asyncLocalStorage = new AsyncLocalStorage();
|
|
79
75
|
getContext() {
|
|
80
76
|
const store = this.asyncLocalStorage.getStore();
|
|
81
|
-
if (store?.context)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
naiteStore: new Map()
|
|
95
|
-
};
|
|
96
|
-
} else {
|
|
97
|
-
throw new Error("Sonamu cannot find context");
|
|
98
|
-
}
|
|
77
|
+
if (store?.context) return store.context;
|
|
78
|
+
if (process.env.NODE_ENV === "test") return {
|
|
79
|
+
transport: "http",
|
|
80
|
+
request: null,
|
|
81
|
+
reply: null,
|
|
82
|
+
headers: {},
|
|
83
|
+
createSSE: (schema) => createMockSSEFactory(schema),
|
|
84
|
+
locale: "",
|
|
85
|
+
user: null,
|
|
86
|
+
session: null,
|
|
87
|
+
naiteStore: /* @__PURE__ */ new Map()
|
|
88
|
+
};
|
|
89
|
+
else throw new Error("Sonamu cannot find context");
|
|
99
90
|
}
|
|
100
91
|
_apiRootPath = null;
|
|
101
92
|
set apiRootPath(apiRootPath) {
|
|
102
93
|
this._apiRootPath = apiRootPath;
|
|
103
94
|
}
|
|
104
95
|
get apiRootPath() {
|
|
105
|
-
if (this._apiRootPath === null)
|
|
106
|
-
throw new Error("Sonamu has not been initialized");
|
|
107
|
-
}
|
|
96
|
+
if (this._apiRootPath === null) throw new Error("Sonamu has not been initialized");
|
|
108
97
|
return this._apiRootPath;
|
|
109
98
|
}
|
|
110
99
|
get appRootPath() {
|
|
@@ -115,9 +104,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
115
104
|
this._dbConfig = dbConfig;
|
|
116
105
|
}
|
|
117
106
|
get dbConfig() {
|
|
118
|
-
if (this._dbConfig === null)
|
|
119
|
-
throw new Error("Sonamu has not been initialized");
|
|
120
|
-
}
|
|
107
|
+
if (this._dbConfig === null) throw new Error("Sonamu has not been initialized");
|
|
121
108
|
return this._dbConfig;
|
|
122
109
|
}
|
|
123
110
|
_syncer = null;
|
|
@@ -125,9 +112,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
125
112
|
this._syncer = syncer;
|
|
126
113
|
}
|
|
127
114
|
get syncer() {
|
|
128
|
-
if (this._syncer === null)
|
|
129
|
-
throw new Error("Sonamu has not been initialized");
|
|
130
|
-
}
|
|
115
|
+
if (this._syncer === null) throw new Error("Sonamu has not been initialized");
|
|
131
116
|
return this._syncer;
|
|
132
117
|
}
|
|
133
118
|
_config = null;
|
|
@@ -135,9 +120,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
135
120
|
this._config = config;
|
|
136
121
|
}
|
|
137
122
|
get config() {
|
|
138
|
-
if (this._config === null)
|
|
139
|
-
throw new Error("Sonamu has not been initialized");
|
|
140
|
-
}
|
|
123
|
+
if (this._config === null) throw new Error("Sonamu has not been initialized");
|
|
141
124
|
return this._config;
|
|
142
125
|
}
|
|
143
126
|
secrets = getSecrets();
|
|
@@ -146,9 +129,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
146
129
|
* StorageManager 인스턴스
|
|
147
130
|
*/
|
|
148
131
|
get storage() {
|
|
149
|
-
if (!this._storage)
|
|
150
|
-
throw new Error("Storage has not been initialized. Check storage config.");
|
|
151
|
-
}
|
|
132
|
+
if (!this._storage) throw new Error("Storage has not been initialized. Check storage config.");
|
|
152
133
|
return this._storage;
|
|
153
134
|
}
|
|
154
135
|
_cache = null;
|
|
@@ -156,23 +137,17 @@ var init_sonamu = __esmMin((() => {
|
|
|
156
137
|
* CacheManager 인스턴스 (BentoCache)
|
|
157
138
|
*/
|
|
158
139
|
get cache() {
|
|
159
|
-
if (!this._cache)
|
|
160
|
-
throw new Error("Cache has not been initialized. Check cache config in sonamu.config.ts.");
|
|
161
|
-
}
|
|
140
|
+
if (!this._cache) throw new Error("Cache has not been initialized. Check cache config in sonamu.config.ts.");
|
|
162
141
|
return this._cache;
|
|
163
142
|
}
|
|
164
143
|
_workflows = null;
|
|
165
144
|
get workflows() {
|
|
166
|
-
if (this._workflows === null)
|
|
167
|
-
throw new Error("Sonamu has not been initialized");
|
|
168
|
-
}
|
|
145
|
+
if (this._workflows === null) throw new Error("Sonamu has not been initialized");
|
|
169
146
|
return this._workflows;
|
|
170
147
|
}
|
|
171
148
|
_auth = null;
|
|
172
149
|
get auth() {
|
|
173
|
-
if (!this._auth)
|
|
174
|
-
throw new Error("Auth has not been initialized. Check auth config in sonamu.config.ts.");
|
|
175
|
-
}
|
|
150
|
+
if (!this._auth) throw new Error("Auth has not been initialized. Check auth config in sonamu.config.ts.");
|
|
176
151
|
return this._auth;
|
|
177
152
|
}
|
|
178
153
|
_devVitestManager = null;
|
|
@@ -183,11 +158,9 @@ var init_sonamu = __esmMin((() => {
|
|
|
183
158
|
this._devVitestManager = manager;
|
|
184
159
|
}
|
|
185
160
|
_websocketRuntime = null;
|
|
186
|
-
websocketPluginServers = new WeakSet();
|
|
161
|
+
websocketPluginServers = /* @__PURE__ */ new WeakSet();
|
|
187
162
|
get websocketRuntime() {
|
|
188
|
-
if (!this._websocketRuntime)
|
|
189
|
-
throw new Error("WebSocket runtime has not been initialized.");
|
|
190
|
-
}
|
|
163
|
+
if (!this._websocketRuntime) throw new Error("WebSocket runtime has not been initialized.");
|
|
191
164
|
return this._websocketRuntime;
|
|
192
165
|
}
|
|
193
166
|
set websocketRuntime(runtime) {
|
|
@@ -196,30 +169,30 @@ var init_sonamu = __esmMin((() => {
|
|
|
196
169
|
watcher = null;
|
|
197
170
|
server = null;
|
|
198
171
|
async initForTesting() {
|
|
199
|
-
await this.init(true, false,
|
|
172
|
+
await this.init(true, false, void 0, true);
|
|
200
173
|
}
|
|
201
174
|
async init(doSilent = false, enableSync = true, apiRootPath, forTesting = false) {
|
|
202
175
|
this.forTesting = forTesting;
|
|
203
|
-
if (this.isInitialized)
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
176
|
+
if (this.isInitialized) return;
|
|
206
177
|
const initStart = performance.now();
|
|
207
178
|
const { findApiRootPath } = await import("../utils/utils.js");
|
|
208
179
|
this.apiRootPath = apiRootPath ?? findApiRootPath();
|
|
180
|
+
const baseEnvBeforeConfigLoad = { ...process.env };
|
|
209
181
|
const configStart = performance.now();
|
|
210
182
|
const { loadConfig } = await import("./config.js");
|
|
211
183
|
this.config = await loadConfig(this.apiRootPath);
|
|
212
184
|
const configTime = performance.now() - configStart;
|
|
213
185
|
setSDConfig(this.config.i18n);
|
|
214
186
|
this.config.database.database = this.config.database.database ?? "pg";
|
|
187
|
+
this.config.database.defaultOptions = this.config.database.defaultOptions ?? {};
|
|
215
188
|
this.config.database.defaultOptions.client = this.config.database.database ?? "pg";
|
|
216
189
|
const { configureLogTape } = await import("../logger/configure.js");
|
|
217
|
-
if (this.config.logging !== false) {
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
const
|
|
221
|
-
this.dbConfig = DB
|
|
222
|
-
DB
|
|
190
|
+
if (this.config.logging !== false) await configureLogTape({ ...this.config.logging });
|
|
191
|
+
const { DB } = await import("../database/db.js");
|
|
192
|
+
const { isLocal: isLocalEnvironment } = await import("../utils/controller.js");
|
|
193
|
+
const environmentSnapshots = isLocalEnvironment() ? readAllEnvironmentSnapshots(this.apiRootPath, baseEnvBeforeConfigLoad) : void 0;
|
|
194
|
+
this.dbConfig = DB.generateDBConfig(this.config.database, this.config.projectName, environmentSnapshots);
|
|
195
|
+
DB.setConfig(this.dbConfig);
|
|
223
196
|
const { EntityManager } = await import("../entity/entity-manager.js");
|
|
224
197
|
await EntityManager.autoload(doSilent);
|
|
225
198
|
await this.initializeCache(this.config.server.cache, forTesting);
|
|
@@ -260,15 +233,13 @@ var init_sonamu = __esmMin((() => {
|
|
|
260
233
|
_initElapsed = 0;
|
|
261
234
|
_configElapsed = 0;
|
|
262
235
|
async createServer(initOptions) {
|
|
263
|
-
if (!this.isInitialized)
|
|
264
|
-
await this.init(initOptions?.doSilent, initOptions?.enableSync);
|
|
265
|
-
}
|
|
236
|
+
if (!this.isInitialized) await this.init(initOptions?.doSilent, initOptions?.enableSync);
|
|
266
237
|
const options = this.config.server;
|
|
267
238
|
const { default: fastify } = await import("fastify");
|
|
268
239
|
const { getLogTapeFastifyLogger } = await import("@logtape/fastify");
|
|
269
240
|
const server = fastify({
|
|
270
241
|
...options.fastify,
|
|
271
|
-
logger: this.config.logging !== false ? getLogTapeFastifyLogger({ category: this.config.logging?.fastifyCategory ?? ["fastify"] }) :
|
|
242
|
+
logger: this.config.logging !== false ? getLogTapeFastifyLogger({ category: this.config.logging?.fastifyCategory ?? ["fastify"] }) : void 0
|
|
272
243
|
});
|
|
273
244
|
this.server = server;
|
|
274
245
|
this.websocketRuntime = new WebSocketRuntime(options.websocket);
|
|
@@ -276,26 +247,18 @@ var init_sonamu = __esmMin((() => {
|
|
|
276
247
|
const { StorageManager } = await import("../storage/storage-manager.js");
|
|
277
248
|
this._storage = new StorageManager(options.storage);
|
|
278
249
|
}
|
|
279
|
-
if (options.plugins)
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
if (options.auth) {
|
|
283
|
-
await this.registerBetterAuth(server, options.auth);
|
|
284
|
-
}
|
|
250
|
+
if (options.plugins) await this.registerPlugins(server, options.plugins);
|
|
251
|
+
if (options.auth) await this.registerBetterAuth(server, options.auth);
|
|
285
252
|
await this.withFastify(server, options.apiConfig, {
|
|
286
253
|
enableSync: initOptions?.enableSync,
|
|
287
254
|
doSilent: initOptions?.doSilent
|
|
288
255
|
});
|
|
289
256
|
await this.boot(server, options);
|
|
290
|
-
if (!initOptions?.doSilent)
|
|
291
|
-
this.printStartupSummary();
|
|
292
|
-
}
|
|
257
|
+
if (!initOptions?.doSilent) this.printStartupSummary();
|
|
293
258
|
return server;
|
|
294
259
|
}
|
|
295
260
|
async withFastify(server, config, options) {
|
|
296
|
-
if (!this.isInitialized)
|
|
297
|
-
await this.init(options?.doSilent, options?.enableSync);
|
|
298
|
-
}
|
|
261
|
+
if (!this.isInitialized) await this.init(options?.doSilent, options?.enableSync);
|
|
299
262
|
this.server = server;
|
|
300
263
|
this.websocketRuntime ??= new WebSocketRuntime(this.config.server.websocket);
|
|
301
264
|
const timezone = this.config.api.timezone;
|
|
@@ -305,9 +268,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
305
268
|
const DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";
|
|
306
269
|
server.setReplySerializer((payload) => {
|
|
307
270
|
return JSON.stringify(payload, (_key, value) => {
|
|
308
|
-
if (typeof value === "string" && ISO_DATE_REGEX.test(value))
|
|
309
|
-
return formatInTimeZone(new Date(value), timezone, DATE_FORMAT);
|
|
310
|
-
}
|
|
271
|
+
if (typeof value === "string" && ISO_DATE_REGEX.test(value)) return formatInTimeZone(new Date(value), timezone, DATE_FORMAT);
|
|
311
272
|
return value;
|
|
312
273
|
});
|
|
313
274
|
});
|
|
@@ -341,19 +302,14 @@ var init_sonamu = __esmMin((() => {
|
|
|
341
302
|
threshold: pluginCompress.threshold,
|
|
342
303
|
encodings: pluginCompress.encodings,
|
|
343
304
|
customTypes: pluginCompress.customTypes
|
|
344
|
-
} :
|
|
305
|
+
} : void 0;
|
|
345
306
|
if (isLocal()) {
|
|
346
307
|
const disableIntegratedWeb = process.env.SONAMU_DISABLE_INTEGRATED_WEB === "yes";
|
|
347
|
-
if (hasWeb && !disableIntegratedWeb)
|
|
348
|
-
|
|
349
|
-
} else {
|
|
350
|
-
this.setupDevServer(server, config);
|
|
351
|
-
}
|
|
308
|
+
if (hasWeb && !disableIntegratedWeb) await this.setupDevServerWithVite(server, webPath, config);
|
|
309
|
+
else this.setupDevServer(server, config);
|
|
352
310
|
} else {
|
|
353
311
|
for (const api of this.syncer.apis) {
|
|
354
|
-
if (this.syncer.models[api.modelName] ===
|
|
355
|
-
throw new Error(`정의되지 않은 모델에 접근 ${api.modelName}`);
|
|
356
|
-
}
|
|
312
|
+
if (this.syncer.models[api.modelName] === void 0) throw new Error(`정의되지 않은 모델에 접근 ${api.modelName}`);
|
|
357
313
|
if (api.websocketOptions) {
|
|
358
314
|
server.route({
|
|
359
315
|
method: "GET",
|
|
@@ -382,26 +338,17 @@ var init_sonamu = __esmMin((() => {
|
|
|
382
338
|
*/
|
|
383
339
|
handleDevApiRequest(request, config) {
|
|
384
340
|
const matchedApi = this.findMatchedApi(request);
|
|
385
|
-
if (!matchedApi)
|
|
386
|
-
|
|
387
|
-
}
|
|
388
|
-
if (matchedApi.websocketOptions) {
|
|
389
|
-
return this.createWebSocketUpgradeRequiredHandler();
|
|
390
|
-
}
|
|
341
|
+
if (!matchedApi) throw new NotFoundException(SD("error.api.notFound"));
|
|
342
|
+
if (matchedApi.websocketOptions) return this.createWebSocketUpgradeRequiredHandler();
|
|
391
343
|
return this.createApiHandler(matchedApi, config);
|
|
392
344
|
}
|
|
393
345
|
findMatchedApi(request) {
|
|
394
346
|
const url = this.getPathnameFromUrl(request.url);
|
|
395
347
|
const method = request.method;
|
|
396
|
-
if (!url.startsWith(this.config.api.route.prefix))
|
|
397
|
-
return undefined;
|
|
398
|
-
}
|
|
348
|
+
if (!url.startsWith(this.config.api.route.prefix)) return;
|
|
399
349
|
return this.syncer.apis.find((api) => {
|
|
400
|
-
if (this.syncer.models[api.modelName] ===
|
|
401
|
-
|
|
402
|
-
}
|
|
403
|
-
const apiMethod = api.options.httpMethod ?? "GET";
|
|
404
|
-
if (apiMethod !== method) return false;
|
|
350
|
+
if (this.syncer.models[api.modelName] === void 0) return false;
|
|
351
|
+
if ((api.options.httpMethod ?? "GET") !== method) return false;
|
|
405
352
|
const fullPath = this.config.api.route.prefix + api.path;
|
|
406
353
|
return this.isPathPatternMatch(fullPath, url);
|
|
407
354
|
});
|
|
@@ -416,9 +363,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
416
363
|
url: `${this.config.api.route.prefix}/*`,
|
|
417
364
|
handler: async (request, reply) => {
|
|
418
365
|
const handler = this.handleDevApiRequest(request, config);
|
|
419
|
-
if (handler)
|
|
420
|
-
return handler(request, reply);
|
|
421
|
-
}
|
|
366
|
+
if (handler) return handler(request, reply);
|
|
422
367
|
throw new NotFoundException(SD("error.api.notFound"));
|
|
423
368
|
},
|
|
424
369
|
wsHandler: async (connection, request) => {
|
|
@@ -436,9 +381,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
436
381
|
url: `${this.config.api.route.prefix}/*`,
|
|
437
382
|
handler: async (request, reply) => {
|
|
438
383
|
const handler = this.handleDevApiRequest(request, config);
|
|
439
|
-
if (handler)
|
|
440
|
-
return handler(request, reply);
|
|
441
|
-
}
|
|
384
|
+
if (handler) return handler(request, reply);
|
|
442
385
|
throw new NotFoundException(SD("error.api.notFound"));
|
|
443
386
|
}
|
|
444
387
|
});
|
|
@@ -465,9 +408,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
465
408
|
appType: "custom"
|
|
466
409
|
});
|
|
467
410
|
server.use((req, res, next) => {
|
|
468
|
-
if (req.url?.startsWith(this.config.api.route.prefix) || req.url?.startsWith("/sonamu-ui"))
|
|
469
|
-
return next();
|
|
470
|
-
}
|
|
411
|
+
if (req.url?.startsWith(this.config.api.route.prefix) || req.url?.startsWith("/sonamu-ui")) return next();
|
|
471
412
|
return this.viteServer.middlewares(req, res, next);
|
|
472
413
|
});
|
|
473
414
|
server.route({
|
|
@@ -475,9 +416,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
475
416
|
url: `${this.config.api.route.prefix}/*`,
|
|
476
417
|
handler: async (request, reply) => {
|
|
477
418
|
const result = this.handleDevApiRequest(request, config);
|
|
478
|
-
if (result)
|
|
479
|
-
return result(request, reply);
|
|
480
|
-
}
|
|
419
|
+
if (result) return result(request, reply);
|
|
481
420
|
throw new NotFoundException(SD("error.api.notFound"));
|
|
482
421
|
},
|
|
483
422
|
wsHandler: async (connection, request) => {
|
|
@@ -495,9 +434,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
495
434
|
url: `${this.config.api.route.prefix}/*`,
|
|
496
435
|
handler: async (request, reply) => {
|
|
497
436
|
const result = this.handleDevApiRequest(request, config);
|
|
498
|
-
if (result)
|
|
499
|
-
return result(request, reply);
|
|
500
|
-
}
|
|
437
|
+
if (result) return result(request, reply);
|
|
501
438
|
throw new NotFoundException(SD("error.api.notFound"));
|
|
502
439
|
}
|
|
503
440
|
});
|
|
@@ -515,8 +452,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
515
452
|
return html;
|
|
516
453
|
}
|
|
517
454
|
try {
|
|
518
|
-
|
|
519
|
-
let template = await fs$1.readFile(path.join(this.viteServer.config.root, "index.html"), "utf-8");
|
|
455
|
+
let template = await (await import("node:fs/promises")).readFile(path.join(this.viteServer.config.root, "index.html"), "utf-8");
|
|
520
456
|
template = await this.viteServer.transformIndexHtml(url, template);
|
|
521
457
|
reply.type("text/html");
|
|
522
458
|
return template;
|
|
@@ -531,11 +467,9 @@ var init_sonamu = __esmMin((() => {
|
|
|
531
467
|
server.addHook("onClose", async () => {
|
|
532
468
|
await this.viteServer.close();
|
|
533
469
|
});
|
|
534
|
-
const chalk
|
|
535
|
-
if ("port" in hmr) {
|
|
536
|
-
|
|
537
|
-
}
|
|
538
|
-
console.log(chalk$1.dim("✓ Vite dev server integrated"));
|
|
470
|
+
const chalk = (await import("chalk")).default;
|
|
471
|
+
if ("port" in hmr) console.log(chalk.dim(`✓ Vite HMR using dedicated websocket port ${hmr.port} to avoid Fastify websocket conflicts`));
|
|
472
|
+
console.log(chalk.dim("✓ Vite dev server integrated"));
|
|
539
473
|
}
|
|
540
474
|
async setupStaticWebServer(server, config, globalCompressOptions) {
|
|
541
475
|
const webDistPath = path.join(this.apiRootPath, "web-dist", "client");
|
|
@@ -551,14 +485,10 @@ var init_sonamu = __esmMin((() => {
|
|
|
551
485
|
console.warn(`⚠ SSR entry not found: ${ssrEntryPath}`);
|
|
552
486
|
console.warn(" SSR will be disabled. Only CSR will work.");
|
|
553
487
|
}
|
|
554
|
-
if (ssrAvailable) {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
} else {
|
|
559
|
-
console.warn(`⚠ SSR routes not found: ${ssrRoutesPath}`);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
488
|
+
if (ssrAvailable) if (await exists(ssrRoutesPath)) {
|
|
489
|
+
await import(ssrRoutesPath);
|
|
490
|
+
console.log("✓ SSR routes loaded");
|
|
491
|
+
} else console.warn(`⚠ SSR routes not found: ${ssrRoutesPath}`);
|
|
562
492
|
server.get("/assets/:filename", async (request, reply) => {
|
|
563
493
|
const requestedFile = request.params.filename;
|
|
564
494
|
const assetsDir = path.join(webDistPath, "assets");
|
|
@@ -584,11 +514,10 @@ var init_sonamu = __esmMin((() => {
|
|
|
584
514
|
};
|
|
585
515
|
if (/^index-[a-f0-9]+\.(js|css)$/.test(normalizedRequestedFile)) {
|
|
586
516
|
const ext = normalizedRequestedFile.split(".").pop();
|
|
587
|
-
const
|
|
588
|
-
const currentFile = files.find((f) => f.startsWith("index-") && f.endsWith(`.${ext}`));
|
|
517
|
+
const currentFile = (await fs.readdir(assetsDir)).find((f) => f.startsWith("index-") && f.endsWith(`.${ext}`));
|
|
589
518
|
if (currentFile) {
|
|
590
|
-
const filePath
|
|
591
|
-
const content = await fs.readFile(filePath
|
|
519
|
+
const filePath = path.join(assetsDir, currentFile);
|
|
520
|
+
const content = await fs.readFile(filePath);
|
|
592
521
|
reply.type(ext === "js" ? "application/javascript" : "text/css");
|
|
593
522
|
applyCacheHeaders(reply, getCacheControlForAsset());
|
|
594
523
|
return reply.send(content);
|
|
@@ -599,9 +528,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
599
528
|
const content = await fs.readFile(filePath);
|
|
600
529
|
const ext = normalizedRequestedFile.split(".").pop();
|
|
601
530
|
reply.type(ext === "js" ? "application/javascript" : ext === "css" ? "text/css" : "");
|
|
602
|
-
if (normalizedRequestedFile.includes("-"))
|
|
603
|
-
applyCacheHeaders(reply, getCacheControlForAsset());
|
|
604
|
-
}
|
|
531
|
+
if (normalizedRequestedFile.includes("-")) applyCacheHeaders(reply, getCacheControlForAsset());
|
|
605
532
|
return reply.send(content);
|
|
606
533
|
}
|
|
607
534
|
reply.status(404).send();
|
|
@@ -610,21 +537,18 @@ var init_sonamu = __esmMin((() => {
|
|
|
610
537
|
const { getSSRRoutes } = await import("../ssr/index.js");
|
|
611
538
|
const { renderSSR } = await import("../ssr/renderer.js");
|
|
612
539
|
const ssrRoutes = getSSRRoutes();
|
|
613
|
-
for (const route of ssrRoutes) {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
}
|
|
626
|
-
});
|
|
627
|
-
}
|
|
540
|
+
for (const route of ssrRoutes) server.route({
|
|
541
|
+
method: ["GET", "HEAD"],
|
|
542
|
+
url: route.path,
|
|
543
|
+
compress: toFastifyCompressOption(route.compress ?? true, globalCompressOptions),
|
|
544
|
+
handler: async (request, reply) => {
|
|
545
|
+
const url = request.url;
|
|
546
|
+
console.log(`[SSR] Matched route: ${route.path}`);
|
|
547
|
+
const html = await renderSSR(url, route, this.extractPathParams(route.path, url), request, reply, config);
|
|
548
|
+
reply.type("text/html");
|
|
549
|
+
return html;
|
|
550
|
+
}
|
|
551
|
+
});
|
|
628
552
|
}
|
|
629
553
|
server.route({
|
|
630
554
|
method: ["GET", "HEAD"],
|
|
@@ -642,9 +566,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
642
566
|
method: request.method
|
|
643
567
|
};
|
|
644
568
|
const csrCacheConfig = config.cacheControlHandler(csrCacheReq);
|
|
645
|
-
if (csrCacheConfig)
|
|
646
|
-
applyCacheHeaders(reply, csrCacheConfig);
|
|
647
|
-
}
|
|
569
|
+
if (csrCacheConfig) applyCacheHeaders(reply, csrCacheConfig);
|
|
648
570
|
}
|
|
649
571
|
const requestPath = this.getPathnameFromUrl(request.url);
|
|
650
572
|
const safeFilePath = this.resolvePathWithinBaseDir(webDistPath, requestPath);
|
|
@@ -686,43 +608,34 @@ var init_sonamu = __esmMin((() => {
|
|
|
686
608
|
const parts = request.parts({ limits: api.uploadOptions.limits });
|
|
687
609
|
const fields = {};
|
|
688
610
|
if (api.uploadOptions.consume === "buffer" || !api.uploadOptions.consume) {
|
|
689
|
-
for await (const part of parts) {
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
} else if (part.type === "field") {
|
|
694
|
-
fields[part.fieldname] = String(part.value);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
611
|
+
for await (const part of parts) if (part.type === "file") {
|
|
612
|
+
const buffer = await part.toBuffer();
|
|
613
|
+
files.bufferedFiles.push(new BufferedFile(part, buffer));
|
|
614
|
+
} else if (part.type === "field") fields[part.fieldname] = String(part.value);
|
|
697
615
|
} else if (api.uploadOptions.consume === "stream") {
|
|
698
616
|
const diskName = api.uploadOptions.destination;
|
|
699
617
|
const disk = this.storage.use(diskName);
|
|
700
618
|
const keyGenerator = api.uploadOptions.keyGenerator ?? this.config.server.storage?.keyGenerator ?? defaultKeyGenerator;
|
|
701
|
-
for await (const part of parts) {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
} else if (part.type === "field") {
|
|
720
|
-
fields[part.fieldname] = String(part.value);
|
|
721
|
-
}
|
|
722
|
-
}
|
|
619
|
+
for await (const part of parts) if (part.type === "file") {
|
|
620
|
+
const key = await keyGenerator({
|
|
621
|
+
filename: part.filename,
|
|
622
|
+
mimetype: part.mimetype
|
|
623
|
+
});
|
|
624
|
+
await disk.putStream(key, part.file, { contentType: part.mimetype });
|
|
625
|
+
const url = await disk.getUrl(key);
|
|
626
|
+
const signedUrl = await disk.getSignedUrl(key);
|
|
627
|
+
files.uploadedFiles.push(new UploadedFile({
|
|
628
|
+
filename: part.filename,
|
|
629
|
+
mimetype: part.mimetype,
|
|
630
|
+
size: part.file.bytesRead,
|
|
631
|
+
url,
|
|
632
|
+
signedUrl,
|
|
633
|
+
key,
|
|
634
|
+
diskName
|
|
635
|
+
}));
|
|
636
|
+
} else if (part.type === "field") fields[part.fieldname] = String(part.value);
|
|
723
637
|
}
|
|
724
|
-
const
|
|
725
|
-
const parsed = qs.default.parse(fields);
|
|
638
|
+
const parsed = (await import("qs")).default.parse(fields);
|
|
726
639
|
Object.assign(body, parsed);
|
|
727
640
|
}
|
|
728
641
|
const { fastifyCaster } = await import("./caster.js");
|
|
@@ -734,30 +647,20 @@ var init_sonamu = __esmMin((() => {
|
|
|
734
647
|
const messages = humanizeZodError(e).map((issue) => issue.message).join(" ");
|
|
735
648
|
const { BadRequestException } = await import("../exceptions/so-exceptions.js");
|
|
736
649
|
throw new BadRequestException(messages, { zodError: e });
|
|
737
|
-
} else
|
|
738
|
-
throw e;
|
|
739
|
-
}
|
|
650
|
+
} else throw e;
|
|
740
651
|
}
|
|
741
652
|
reply.type(api.options.contentType ?? "application/json");
|
|
742
653
|
const apiCacheConfig = this.getApiCacheControl(api, request, config);
|
|
743
|
-
if (apiCacheConfig)
|
|
744
|
-
applyCacheHeaders(reply, apiCacheConfig);
|
|
745
|
-
}
|
|
654
|
+
if (apiCacheConfig) applyCacheHeaders(reply, apiCacheConfig);
|
|
746
655
|
if (api.uploadOptions) {
|
|
747
656
|
const consume = api.uploadOptions.consume ?? "buffer";
|
|
748
|
-
if (consume === "buffer")
|
|
749
|
-
|
|
750
|
-
} else if (consume === "stream") {
|
|
751
|
-
context.uploadedFiles = files.uploadedFiles;
|
|
752
|
-
}
|
|
657
|
+
if (consume === "buffer") context.bufferedFiles = files.bufferedFiles;
|
|
658
|
+
else if (consume === "stream") context.uploadedFiles = files.uploadedFiles;
|
|
753
659
|
}
|
|
754
660
|
const { ApiParamType } = await import("../types/types.js");
|
|
755
661
|
const args = api.parameters.map((param) => {
|
|
756
|
-
if (ApiParamType.isContext(param.type))
|
|
757
|
-
|
|
758
|
-
} else {
|
|
759
|
-
return reqBody[param.name];
|
|
760
|
-
}
|
|
662
|
+
if (ApiParamType.isContext(param.type)) return context;
|
|
663
|
+
else return reqBody[param.name];
|
|
761
664
|
});
|
|
762
665
|
return this.invokeModelMethod(api, args, reply);
|
|
763
666
|
});
|
|
@@ -787,8 +690,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
787
690
|
socket.close(1008, "WebSocket route not found");
|
|
788
691
|
return;
|
|
789
692
|
}
|
|
790
|
-
|
|
791
|
-
await handler({ socket }, request);
|
|
693
|
+
await this.createWebSocketHandler(matchedApi, config)({ socket }, request);
|
|
792
694
|
}
|
|
793
695
|
createWebSocketHandler(api, config) {
|
|
794
696
|
return async (connection, request) => {
|
|
@@ -799,12 +701,6 @@ var init_sonamu = __esmMin((() => {
|
|
|
799
701
|
let traceContext = {};
|
|
800
702
|
try {
|
|
801
703
|
traceContext = this.websocketRuntime.telemetryController.createConnectionContext({ headers: request.headers });
|
|
802
|
-
runGuards({
|
|
803
|
-
guards: api.options.guards,
|
|
804
|
-
config,
|
|
805
|
-
request,
|
|
806
|
-
api
|
|
807
|
-
});
|
|
808
704
|
preRegisterPhase = "query";
|
|
809
705
|
const reqBody = await this.parseWebSocketRequestParams(api, request);
|
|
810
706
|
preRegisterPhase = "register";
|
|
@@ -821,13 +717,19 @@ var init_sonamu = __esmMin((() => {
|
|
|
821
717
|
});
|
|
822
718
|
const scopedWs = this.createScopedWebSocketConnection(rawWs, () => wsContext);
|
|
823
719
|
wsContext = await this.createWebSocketContext(config, request, scopedWs);
|
|
720
|
+
await this.asyncLocalStorage.run({ context: wsContext }, async () => {
|
|
721
|
+
runGuards({
|
|
722
|
+
guards: api.options.guards,
|
|
723
|
+
config,
|
|
724
|
+
request,
|
|
725
|
+
api
|
|
726
|
+
});
|
|
727
|
+
});
|
|
824
728
|
this.websocketRuntime.activateConnection(rawWs.id);
|
|
825
729
|
preRegisterPhase = "handler";
|
|
826
730
|
const { ApiParamType } = await import("../types/types.js");
|
|
827
731
|
const args = api.parameters.map((param) => {
|
|
828
|
-
if (ApiParamType.isContext(param.type))
|
|
829
|
-
return wsContext;
|
|
830
|
-
}
|
|
732
|
+
if (ApiParamType.isContext(param.type)) return wsContext;
|
|
831
733
|
return reqBody[param.name];
|
|
832
734
|
});
|
|
833
735
|
await this.asyncLocalStorage.run({ context: wsContext }, async () => {
|
|
@@ -835,26 +737,21 @@ var init_sonamu = __esmMin((() => {
|
|
|
835
737
|
});
|
|
836
738
|
} catch (error) {
|
|
837
739
|
const closeDescriptor = resolveWebSocketCloseDescriptor(error);
|
|
838
|
-
if (!rawWs) {
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
if (rawWs) {
|
|
854
|
-
rawWs.close(closeDescriptor.code, closeDescriptor.reason);
|
|
855
|
-
} else if (socket.readyState < 2) {
|
|
856
|
-
socket.close(closeDescriptor.code, closeDescriptor.reason);
|
|
857
|
-
}
|
|
740
|
+
if (!rawWs) this.websocketRuntime.telemetryController.emit({
|
|
741
|
+
name: "ws.connection.rejected",
|
|
742
|
+
level: closeDescriptor.logLevel === "warn" ? "warn" : "error",
|
|
743
|
+
detail: {
|
|
744
|
+
reason: preRegisterPhase,
|
|
745
|
+
code: closeDescriptor.code,
|
|
746
|
+
path: api.path
|
|
747
|
+
},
|
|
748
|
+
traceId: traceContext.traceId,
|
|
749
|
+
spanId: traceContext.spanId,
|
|
750
|
+
parentSpanId: traceContext.parentSpanId,
|
|
751
|
+
sampled: traceContext.sampled
|
|
752
|
+
});
|
|
753
|
+
if (rawWs) rawWs.close(closeDescriptor.code, closeDescriptor.reason);
|
|
754
|
+
else if (socket.readyState < 2) socket.close(closeDescriptor.code, closeDescriptor.reason);
|
|
858
755
|
if (this.server?.log) {
|
|
859
756
|
const payload = {
|
|
860
757
|
err: error,
|
|
@@ -862,18 +759,10 @@ var init_sonamu = __esmMin((() => {
|
|
|
862
759
|
methodName: api.methodName,
|
|
863
760
|
path: api.path
|
|
864
761
|
};
|
|
865
|
-
if (closeDescriptor.logLevel === "warn")
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
}
|
|
870
|
-
} else {
|
|
871
|
-
if (closeDescriptor.logLevel === "warn") {
|
|
872
|
-
console.warn(closeDescriptor.reason, error);
|
|
873
|
-
} else {
|
|
874
|
-
console.error(closeDescriptor.reason, error);
|
|
875
|
-
}
|
|
876
|
-
}
|
|
762
|
+
if (closeDescriptor.logLevel === "warn") this.server.log.warn(payload, closeDescriptor.reason);
|
|
763
|
+
else this.server.log.error(payload, closeDescriptor.reason);
|
|
764
|
+
} else if (closeDescriptor.logLevel === "warn") console.warn(closeDescriptor.reason, error);
|
|
765
|
+
else console.error(closeDescriptor.reason, error);
|
|
877
766
|
}
|
|
878
767
|
};
|
|
879
768
|
}
|
|
@@ -881,9 +770,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
881
770
|
const telemetryController = this._websocketRuntime?.telemetryController;
|
|
882
771
|
const runInContext = (callback) => {
|
|
883
772
|
const context = getContext();
|
|
884
|
-
if (!context)
|
|
885
|
-
return callback();
|
|
886
|
-
}
|
|
773
|
+
if (!context) return callback();
|
|
887
774
|
return this.asyncLocalStorage.run({ context }, callback);
|
|
888
775
|
};
|
|
889
776
|
return {
|
|
@@ -1019,28 +906,18 @@ var init_sonamu = __esmMin((() => {
|
|
|
1019
906
|
const patternParts = pattern.split("/").filter(Boolean);
|
|
1020
907
|
const urlParts = this.getPathnameFromUrl(url).split("/").filter(Boolean);
|
|
1021
908
|
const params = {};
|
|
1022
|
-
for (let i = 0; i < patternParts.length; i++)
|
|
1023
|
-
if (patternParts[i].startsWith(":")) {
|
|
1024
|
-
params[patternParts[i].slice(1)] = urlParts[i];
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
909
|
+
for (let i = 0; i < patternParts.length; i++) if (patternParts[i].startsWith(":")) params[patternParts[i].slice(1)] = urlParts[i];
|
|
1027
910
|
return params;
|
|
1028
911
|
}
|
|
1029
912
|
isPathPatternMatch(pattern, url) {
|
|
1030
913
|
const patternParts = pattern.split("/").filter(Boolean);
|
|
1031
914
|
const urlParts = this.getPathnameFromUrl(url).split("/").filter(Boolean);
|
|
1032
|
-
if (patternParts.length !== urlParts.length)
|
|
1033
|
-
return false;
|
|
1034
|
-
}
|
|
915
|
+
if (patternParts.length !== urlParts.length) return false;
|
|
1035
916
|
for (let i = 0; i < patternParts.length; i++) {
|
|
1036
917
|
const patternPart = patternParts[i];
|
|
1037
918
|
const urlPart = urlParts[i];
|
|
1038
|
-
if (patternPart.startsWith(":"))
|
|
1039
|
-
|
|
1040
|
-
}
|
|
1041
|
-
if (patternPart !== urlPart) {
|
|
1042
|
-
return false;
|
|
1043
|
-
}
|
|
919
|
+
if (patternPart.startsWith(":")) continue;
|
|
920
|
+
if (patternPart !== urlPart) return false;
|
|
1044
921
|
}
|
|
1045
922
|
return true;
|
|
1046
923
|
}
|
|
@@ -1050,15 +927,11 @@ var init_sonamu = __esmMin((() => {
|
|
|
1050
927
|
resolvePathWithinBaseDir(baseDir, inputPath) {
|
|
1051
928
|
try {
|
|
1052
929
|
const decoded = decodeURIComponent(inputPath).replace(/\\/g, "/");
|
|
1053
|
-
if (decoded.includes("\0"))
|
|
1054
|
-
return null;
|
|
1055
|
-
}
|
|
930
|
+
if (decoded.includes("\0")) return null;
|
|
1056
931
|
const relativePath = decoded.replace(/^\/+/, "");
|
|
1057
932
|
const resolvedPath = path.resolve(baseDir, relativePath);
|
|
1058
933
|
const relativeFromBase = path.relative(baseDir, resolvedPath);
|
|
1059
|
-
if (relativeFromBase.startsWith("..") || path.isAbsolute(relativeFromBase))
|
|
1060
|
-
return null;
|
|
1061
|
-
}
|
|
934
|
+
if (relativeFromBase.startsWith("..") || path.isAbsolute(relativeFromBase)) return null;
|
|
1062
935
|
return resolvedPath;
|
|
1063
936
|
} catch {
|
|
1064
937
|
return null;
|
|
@@ -1069,9 +942,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
1069
942
|
* 우선순위: 개별 지정 > cacheControlHandler
|
|
1070
943
|
*/
|
|
1071
944
|
getApiCacheControl(api, request, config) {
|
|
1072
|
-
if (api.options.cacheControl)
|
|
1073
|
-
return api.options.cacheControl;
|
|
1074
|
-
}
|
|
945
|
+
if (api.options.cacheControl) return api.options.cacheControl;
|
|
1075
946
|
if (config.cacheControlHandler) {
|
|
1076
947
|
const cacheReq = {
|
|
1077
948
|
type: "api",
|
|
@@ -1095,9 +966,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
1095
966
|
const { ApiParamType } = await import("../types/types.js");
|
|
1096
967
|
let paramsIndex = 0;
|
|
1097
968
|
const args = api.parameters.map((param) => {
|
|
1098
|
-
if (ApiParamType.isContext(param.type))
|
|
1099
|
-
return context;
|
|
1100
|
-
}
|
|
969
|
+
if (ApiParamType.isContext(param.type)) return context;
|
|
1101
970
|
return params[paramsIndex++];
|
|
1102
971
|
});
|
|
1103
972
|
return this.invokeModelMethod(api, args, reply);
|
|
@@ -1115,18 +984,17 @@ var init_sonamu = __esmMin((() => {
|
|
|
1115
984
|
const locale = this.detectLocale(request.headers["accept-language"], this.config.i18n.supportedLocales) ?? this.config.i18n.defaultLocale;
|
|
1116
985
|
const headers = convertFastifyHeadersToStandard(request.headers);
|
|
1117
986
|
const session = await this._auth?.api.getSession({ headers }) ?? null;
|
|
1118
|
-
|
|
987
|
+
return await Promise.resolve(config.contextProvider({
|
|
1119
988
|
transport: "http",
|
|
1120
989
|
request,
|
|
1121
990
|
reply,
|
|
1122
991
|
headers: request.headers,
|
|
1123
992
|
createSSE,
|
|
1124
|
-
naiteStore: new Map(),
|
|
993
|
+
naiteStore: /* @__PURE__ */ new Map(),
|
|
1125
994
|
locale,
|
|
1126
995
|
user: session?.user ?? null,
|
|
1127
996
|
session: session?.session ?? null
|
|
1128
997
|
}, request, reply));
|
|
1129
|
-
return context;
|
|
1130
998
|
}
|
|
1131
999
|
async createWebSocketContext(config, request, ws) {
|
|
1132
1000
|
const locale = this.detectLocale(request.headers["accept-language"], this.config.i18n.supportedLocales) ?? this.config.i18n.defaultLocale;
|
|
@@ -1137,19 +1005,17 @@ var init_sonamu = __esmMin((() => {
|
|
|
1137
1005
|
request,
|
|
1138
1006
|
headers: request.headers,
|
|
1139
1007
|
ws,
|
|
1140
|
-
naiteStore: new Map(),
|
|
1008
|
+
naiteStore: /* @__PURE__ */ new Map(),
|
|
1141
1009
|
locale,
|
|
1142
1010
|
user: session?.user ?? null,
|
|
1143
1011
|
session: session?.session ?? null
|
|
1144
1012
|
};
|
|
1145
|
-
if (config.websocketContextProvider) {
|
|
1146
|
-
return { ...await Promise.resolve(config.websocketContextProvider(defaultContext, request)) };
|
|
1147
|
-
}
|
|
1013
|
+
if (config.websocketContextProvider) return { ...await Promise.resolve(config.websocketContextProvider(defaultContext, request)) };
|
|
1148
1014
|
const replyStub = createWebSocketReplyStub();
|
|
1149
1015
|
const createSSE = (_events) => {
|
|
1150
1016
|
throw new Error("createSSE is not available in websocket context. Define websocketContextProvider if your context setup depends on SSE helpers.");
|
|
1151
1017
|
};
|
|
1152
|
-
const
|
|
1018
|
+
const { transport: _transport, reply: _reply, createSSE: _createSSE, bufferedFiles: _bufferedFiles, uploadedFiles: _uploadedFiles, ...rest } = await Promise.resolve(config.contextProvider({
|
|
1153
1019
|
transport: "http",
|
|
1154
1020
|
request,
|
|
1155
1021
|
reply: replyStub,
|
|
@@ -1160,7 +1026,6 @@ var init_sonamu = __esmMin((() => {
|
|
|
1160
1026
|
user: defaultContext.user,
|
|
1161
1027
|
session: defaultContext.session
|
|
1162
1028
|
}, request, replyStub));
|
|
1163
|
-
const { transport: _transport, reply: _reply, createSSE: _createSSE, bufferedFiles: _bufferedFiles, uploadedFiles: _uploadedFiles, ...rest } = httpLikeContext;
|
|
1164
1029
|
return {
|
|
1165
1030
|
...rest,
|
|
1166
1031
|
transport: "ws",
|
|
@@ -1174,12 +1039,11 @@ var init_sonamu = __esmMin((() => {
|
|
|
1174
1039
|
* @example "ko-KR,ko;q=0.9,en;q=0.8" → "ko"
|
|
1175
1040
|
*/
|
|
1176
1041
|
detectLocale(acceptLanguage, supported) {
|
|
1177
|
-
if (!acceptLanguage) return
|
|
1178
|
-
|
|
1042
|
+
if (!acceptLanguage) return void 0;
|
|
1043
|
+
return acceptLanguage.split(",").map((lang) => {
|
|
1179
1044
|
const [code] = lang.split(";");
|
|
1180
1045
|
return code.trim().split("-")[0];
|
|
1181
|
-
});
|
|
1182
|
-
return langs.find((lang) => supported.includes(lang));
|
|
1046
|
+
}).find((lang) => supported.includes(lang));
|
|
1183
1047
|
}
|
|
1184
1048
|
async startWatcher() {
|
|
1185
1049
|
const { setupWatcher } = await import("../syncer/watcher.js");
|
|
@@ -1202,7 +1066,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
1202
1066
|
console.log(chalk.black.bgGreen(centerText(msg)));
|
|
1203
1067
|
}
|
|
1204
1068
|
async runScript(fn) {
|
|
1205
|
-
await this.init(true, false,
|
|
1069
|
+
await this.init(true, false, void 0, false);
|
|
1206
1070
|
try {
|
|
1207
1071
|
await fn();
|
|
1208
1072
|
} finally {
|
|
@@ -1210,9 +1074,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
1210
1074
|
}
|
|
1211
1075
|
}
|
|
1212
1076
|
async registerPlugins(server, plugins) {
|
|
1213
|
-
if (!plugins)
|
|
1214
|
-
return;
|
|
1215
|
-
}
|
|
1077
|
+
if (!plugins) return;
|
|
1216
1078
|
if (plugins.compress) {
|
|
1217
1079
|
const compressPlugin = (await import("@fastify/compress")).default;
|
|
1218
1080
|
const defaultOptions = {
|
|
@@ -1223,14 +1085,11 @@ var init_sonamu = __esmMin((() => {
|
|
|
1223
1085
|
"deflate"
|
|
1224
1086
|
]
|
|
1225
1087
|
};
|
|
1226
|
-
if (plugins.compress === true)
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
...plugins.compress
|
|
1232
|
-
});
|
|
1233
|
-
}
|
|
1088
|
+
if (plugins.compress === true) server.register(compressPlugin, defaultOptions);
|
|
1089
|
+
else server.register(compressPlugin, {
|
|
1090
|
+
...defaultOptions,
|
|
1091
|
+
...plugins.compress
|
|
1092
|
+
});
|
|
1234
1093
|
}
|
|
1235
1094
|
const pluginsModules = {
|
|
1236
1095
|
cors: "@fastify/cors",
|
|
@@ -1243,56 +1102,34 @@ var init_sonamu = __esmMin((() => {
|
|
|
1243
1102
|
const registerPlugin = async (key, pluginName) => {
|
|
1244
1103
|
const option = plugins[key];
|
|
1245
1104
|
if (!option) return;
|
|
1246
|
-
if (option === true)
|
|
1247
|
-
|
|
1248
|
-
} else {
|
|
1249
|
-
server.register((await import(pluginName)).default, option);
|
|
1250
|
-
}
|
|
1105
|
+
if (option === true) server.register((await import(pluginName)).default);
|
|
1106
|
+
else server.register((await import(pluginName)).default, option);
|
|
1251
1107
|
};
|
|
1252
|
-
for (const [key, pluginName] of Object.entries(pluginsModules))
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
if (plugins.ws) {
|
|
1256
|
-
await this.ensureWebSocketPlugin(server);
|
|
1257
|
-
}
|
|
1258
|
-
if (plugins.custom) {
|
|
1259
|
-
plugins.custom(server);
|
|
1260
|
-
}
|
|
1108
|
+
for (const [key, pluginName] of Object.entries(pluginsModules)) await registerPlugin(key, pluginName);
|
|
1109
|
+
if (plugins.ws) await this.ensureWebSocketPlugin(server);
|
|
1110
|
+
if (plugins.custom) plugins.custom(server);
|
|
1261
1111
|
}
|
|
1262
1112
|
async ensureWebSocketPlugin(server) {
|
|
1263
|
-
if (this.websocketPluginServers.has(server))
|
|
1264
|
-
return;
|
|
1265
|
-
}
|
|
1113
|
+
if (this.websocketPluginServers.has(server)) return;
|
|
1266
1114
|
const pluginOption = this.config.server.plugins?.ws;
|
|
1267
|
-
if (!pluginOption)
|
|
1268
|
-
return;
|
|
1269
|
-
}
|
|
1115
|
+
if (!pluginOption) return;
|
|
1270
1116
|
const websocketPlugin = (await import("@fastify/websocket")).default;
|
|
1271
1117
|
const resolvedPluginOptions = resolveWebSocketPluginOptions({ rawPluginOption: pluginOption });
|
|
1272
|
-
if (resolvedPluginOptions)
|
|
1273
|
-
|
|
1274
|
-
} else {
|
|
1275
|
-
await server.register(websocketPlugin);
|
|
1276
|
-
}
|
|
1118
|
+
if (resolvedPluginOptions) await server.register(websocketPlugin, resolvedPluginOptions);
|
|
1119
|
+
else await server.register(websocketPlugin);
|
|
1277
1120
|
this.websocketPluginServers.add(server);
|
|
1278
1121
|
this.warnOnPotentialWebSocketTimeoutConflicts(server);
|
|
1279
1122
|
}
|
|
1280
1123
|
warnOnPotentialWebSocketTimeoutConflicts(server) {
|
|
1281
1124
|
const heartbeats = this.syncer.apis.map((api) => api.websocketOptions?.heartbeat ?? 3e4).filter((heartbeat) => heartbeat > 0);
|
|
1282
|
-
if (heartbeats.length === 0)
|
|
1283
|
-
return;
|
|
1284
|
-
}
|
|
1125
|
+
if (heartbeats.length === 0) return;
|
|
1285
1126
|
const keepAliveTimeout = this.config.server.fastify?.keepAliveTimeout;
|
|
1286
|
-
if (!keepAliveTimeout || keepAliveTimeout <= 0)
|
|
1287
|
-
return;
|
|
1288
|
-
}
|
|
1127
|
+
if (!keepAliveTimeout || keepAliveTimeout <= 0) return;
|
|
1289
1128
|
const largestHeartbeat = Math.max(...heartbeats);
|
|
1290
|
-
if (largestHeartbeat >= keepAliveTimeout) {
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
}, "WebSocket heartbeat is greater than or equal to keepAliveTimeout; align infrastructure idle timeouts to avoid unexpected disconnects.");
|
|
1295
|
-
}
|
|
1129
|
+
if (largestHeartbeat >= keepAliveTimeout) server.log.warn({
|
|
1130
|
+
keepAliveTimeout,
|
|
1131
|
+
largestHeartbeat
|
|
1132
|
+
}, "WebSocket heartbeat is greater than or equal to keepAliveTimeout; align infrastructure idle timeouts to avoid unexpected disconnects.");
|
|
1296
1133
|
}
|
|
1297
1134
|
/**
|
|
1298
1135
|
* better-auth 라우트를 등록합니다.
|
|
@@ -1305,23 +1142,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
1305
1142
|
method: ["GET", "POST"],
|
|
1306
1143
|
url: `${basePath}/*`,
|
|
1307
1144
|
handler: async (request, reply) => {
|
|
1308
|
-
const
|
|
1309
|
-
const headers = convertFastifyHeadersToStandard(request.headers);
|
|
1310
|
-
const IP_HEADERS = [
|
|
1311
|
-
"cf-connecting-ip",
|
|
1312
|
-
"x-forwarded-for",
|
|
1313
|
-
"x-real-ip",
|
|
1314
|
-
"x-vercel-forwarded-for"
|
|
1315
|
-
];
|
|
1316
|
-
if (request.ip && !IP_HEADERS.some((h) => headers.has(h))) {
|
|
1317
|
-
headers.set("x-real-ip", request.ip);
|
|
1318
|
-
}
|
|
1319
|
-
const req = new Request(url.toString(), {
|
|
1320
|
-
method: request.method,
|
|
1321
|
-
headers,
|
|
1322
|
-
...request.body ? { body: JSON.stringify(request.body) } : {}
|
|
1323
|
-
});
|
|
1324
|
-
const response = await this.auth.handler(req);
|
|
1145
|
+
const response = await this.auth.handler(createBetterAuthRequest(request, options.advanced?.ipAddress?.ipAddressHeaders));
|
|
1325
1146
|
reply.status(response.status);
|
|
1326
1147
|
response.headers.forEach((value, key) => {
|
|
1327
1148
|
reply.header(key, value);
|
|
@@ -1331,11 +1152,10 @@ var init_sonamu = __esmMin((() => {
|
|
|
1331
1152
|
});
|
|
1332
1153
|
}
|
|
1333
1154
|
async printStartupSummary() {
|
|
1334
|
-
const chalk
|
|
1335
|
-
const
|
|
1336
|
-
const
|
|
1337
|
-
const
|
|
1338
|
-
const green = (msg) => console.log(chalk$1.green(`✓ ${msg}`));
|
|
1155
|
+
const chalk = (await import("chalk")).default;
|
|
1156
|
+
const activePreset = getSonamuEnvironment();
|
|
1157
|
+
const dim = (msg) => console.log(chalk.dim(`✓ ${msg}`));
|
|
1158
|
+
const green = (msg) => console.log(chalk.green(`✓ ${msg}`));
|
|
1339
1159
|
dim(`Config loaded${formatTime(this._configElapsed)}`);
|
|
1340
1160
|
green("DB");
|
|
1341
1161
|
const { isLocal } = await import("../utils/controller.js");
|
|
@@ -1344,22 +1164,14 @@ var init_sonamu = __esmMin((() => {
|
|
|
1344
1164
|
for (const name of presetNames) {
|
|
1345
1165
|
const conn = this.dbConfig[name].connection;
|
|
1346
1166
|
const host = conn?.host ?? "localhost";
|
|
1347
|
-
const addr = `@ ${host}:${conn?.port ?? 5432}/${conn?.database ??
|
|
1167
|
+
const addr = `@ ${host}:${conn?.port ?? 5432}/${conn?.database ?? "(unknown)"}`;
|
|
1348
1168
|
const padded = name.padEnd(maxLen);
|
|
1349
|
-
const remoteTag = isLocal() && !isLocalHost(host) ? chalk
|
|
1350
|
-
if (name === activePreset) {
|
|
1351
|
-
|
|
1352
|
-
} else {
|
|
1353
|
-
console.log(chalk$1.dim(` ${padded} ${addr}`) + remoteTag);
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
if (this.config.server.auth) {
|
|
1357
|
-
const basePath = this.config.server.auth.basePath ?? "/api/auth";
|
|
1358
|
-
dim(`Auth: better-auth at ${basePath}/*`);
|
|
1359
|
-
}
|
|
1360
|
-
if (this.config.api.timezone) {
|
|
1361
|
-
dim(`Timezone: ${this.config.api.timezone}`);
|
|
1169
|
+
const remoteTag = isLocal() && !isLocalHost(host) ? chalk.yellow(` \u26a0 remote`) : "";
|
|
1170
|
+
if (name === activePreset) console.log(chalk.green(` \u25b8 ${padded} ${addr}`) + remoteTag);
|
|
1171
|
+
else console.log(chalk.dim(` ${padded} ${addr}`) + remoteTag);
|
|
1362
1172
|
}
|
|
1173
|
+
if (this.config.server.auth) dim(`Auth: better-auth at ${this.config.server.auth.basePath ?? "/api/auth"}/*`);
|
|
1174
|
+
if (this.config.api.timezone) dim(`Timezone: ${this.config.api.timezone}`);
|
|
1363
1175
|
green(`Sonamu ready${formatTime(this._initElapsed)}`);
|
|
1364
1176
|
}
|
|
1365
1177
|
async initializeCache(config, forTesting) {
|
|
@@ -1381,21 +1193,17 @@ var init_sonamu = __esmMin((() => {
|
|
|
1381
1193
|
async initializeWorkflows(options) {
|
|
1382
1194
|
const { WorkflowManager } = await import("../tasks/workflow-manager.js");
|
|
1383
1195
|
this._workflows = new WorkflowManager(DB.getDBConfig("w"));
|
|
1384
|
-
if (!options)
|
|
1385
|
-
return;
|
|
1386
|
-
}
|
|
1196
|
+
if (!options) return;
|
|
1387
1197
|
const enableWorker = options.enableWorker ?? isDaemonServer();
|
|
1388
1198
|
const defaultWorkerOptions = {
|
|
1389
1199
|
concurrency: os.cpus().length - 1,
|
|
1390
1200
|
usePubSub: true,
|
|
1391
1201
|
listenDelay: 500
|
|
1392
1202
|
};
|
|
1393
|
-
if (enableWorker) {
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
});
|
|
1398
|
-
}
|
|
1203
|
+
if (enableWorker) this.workflows.setupWorker({
|
|
1204
|
+
...defaultWorkerOptions,
|
|
1205
|
+
...options.workerOptions
|
|
1206
|
+
});
|
|
1399
1207
|
}
|
|
1400
1208
|
async boot(server, options) {
|
|
1401
1209
|
const port = options.listen?.port ?? 3e3;
|
|
@@ -1416,9 +1224,7 @@ var init_sonamu = __esmMin((() => {
|
|
|
1416
1224
|
};
|
|
1417
1225
|
process.on("SIGINT", shutdown);
|
|
1418
1226
|
process.on("SIGTERM", shutdown);
|
|
1419
|
-
if (options.lifecycle?.onError)
|
|
1420
|
-
server.setErrorHandler(options.lifecycle?.onError);
|
|
1421
|
-
}
|
|
1227
|
+
if (options.lifecycle?.onError) server.setErrorHandler(options.lifecycle?.onError);
|
|
1422
1228
|
server.listen({
|
|
1423
1229
|
port,
|
|
1424
1230
|
host
|
|
@@ -1426,17 +1232,15 @@ var init_sonamu = __esmMin((() => {
|
|
|
1426
1232
|
await this.workflows.startWorker();
|
|
1427
1233
|
await options.lifecycle?.onStart?.(server);
|
|
1428
1234
|
}).catch(async (err) => {
|
|
1429
|
-
const chalk
|
|
1430
|
-
console.error(chalk
|
|
1235
|
+
const chalk = (await import("chalk")).default;
|
|
1236
|
+
console.error(chalk.red("Failed to start server:", err));
|
|
1431
1237
|
await shutdown();
|
|
1432
1238
|
});
|
|
1433
1239
|
}
|
|
1434
1240
|
async destroy() {
|
|
1435
1241
|
const { BaseModel } = await import("../database/base-model.js");
|
|
1436
1242
|
await BaseModel.destroy();
|
|
1437
|
-
if (this._websocketRuntime)
|
|
1438
|
-
await this._websocketRuntime.shutdown();
|
|
1439
|
-
}
|
|
1243
|
+
if (this._websocketRuntime) await this._websocketRuntime.shutdown();
|
|
1440
1244
|
this._websocketRuntime = null;
|
|
1441
1245
|
await Promise.allSettled([
|
|
1442
1246
|
this._workflows?.destroy() ?? Promise.resolve(),
|
|
@@ -1448,15 +1252,15 @@ var init_sonamu = __esmMin((() => {
|
|
|
1448
1252
|
}
|
|
1449
1253
|
};
|
|
1450
1254
|
Sonamu = new SonamuClass();
|
|
1451
|
-
LOCAL_HOSTS = new Set([
|
|
1255
|
+
LOCAL_HOSTS = /* @__PURE__ */ new Set([
|
|
1452
1256
|
"localhost",
|
|
1453
1257
|
"127.0.0.1",
|
|
1454
1258
|
"0.0.0.0",
|
|
1455
1259
|
"::1"
|
|
1456
1260
|
]);
|
|
1457
1261
|
}));
|
|
1458
|
-
|
|
1459
1262
|
//#endregion
|
|
1460
1263
|
init_sonamu();
|
|
1461
1264
|
export { Sonamu, createWebSocketReplyStub, init_sonamu, resolveWebSocketCloseDescriptor, resolveWebSocketPluginOptions };
|
|
1462
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29uYW11LmpzIiwibmFtZXMiOlsiREIiLCJhdXRoT3B0aW9uczogQmV0dGVyQXV0aE9wdGlvbnMiLCJnbG9iYWxDb21wcmVzc09wdGlvbnM6IENvbXByZXNzT3B0aW9ucyB8IHVuZGVmaW5lZCIsImZzIiwiY2hhbGsiLCJjYWNoZVJlcTogQ2FjaGVDb250cm9sUmVxdWVzdCIsImZpbGVQYXRoIiwiY3NyQ2FjaGVSZXE6IENhY2hlQ29udHJvbFJlcXVlc3QiLCJtaW1lTG9va3VwIiwiY29udGV4dDogQ29udGV4dCIsInJlcUJvZHk6IHtcbiAgICAgICAgICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xuICAgICAgICB9IiwiZmlsZXM6IHtcbiAgICAgICAgICBidWZmZXJlZEZpbGVzOiBCdWZmZXJlZEZpbGVbXTtcbiAgICAgICAgICB1cGxvYWRlZEZpbGVzOiBVcGxvYWRlZEZpbGVbXTtcbiAgICAgICAgfSIsImZpZWxkczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiIsImtleUdlbmVyYXRvcjogS2V5R2VuZXJhdG9yIiwid3NDb250ZXh0OiBXZWJTb2NrZXRDb250ZXh0IHwgbnVsbCIsInJhd1dzOiBSZXR1cm5UeXBlPFdlYlNvY2tldFJ1bnRpbWVbXCJyZWdpc3RlckNvbm5lY3Rpb25cIl0+IHwgbnVsbCIsInByZVJlZ2lzdGVyUGhhc2U6IFwiZ3VhcmRcIiB8IFwicXVlcnlcIiB8IFwicmVnaXN0ZXJcIiB8IFwiaGFuZGxlclwiIiwidHJhY2VDb250ZXh0OiBXZWJTb2NrZXRUZWxlbWV0cnlDb25uZWN0aW9uQ29udGV4dCIsInBhcmFtczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiIsImxvZ3RhcGVEaXNwb3NlIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwaS9zb25hbXUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQXN5bmNMb2NhbFN0b3JhZ2UgfSBmcm9tIFwiYXN5bmNfaG9va3NcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IHR5cGUgSW5jb21pbmdNZXNzYWdlLCB0eXBlIFNlcnZlciwgdHlwZSBTZXJ2ZXJSZXNwb25zZSB9IGZyb20gXCJodHRwXCI7XG5pbXBvcnQgb3MgZnJvbSBcIm9zXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuXG5pbXBvcnQgdHlwZSB7fSBmcm9tIFwiQGZhc3RpZnkvd2Vic29ja2V0XCI7XG5pbXBvcnQgeyBkaXNwb3NlIGFzIGxvZ3RhcGVEaXNwb3NlIH0gZnJvbSBcIkBsb2d0YXBlL2xvZ3RhcGVcIjtcbmltcG9ydCB7IHR5cGUgQXV0aCwgdHlwZSBCZXR0ZXJBdXRoT3B0aW9ucyB9IGZyb20gXCJiZXR0ZXItYXV0aFwiO1xuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiO1xuaW1wb3J0IHsgdHlwZSBGU1dhdGNoZXIgfSBmcm9tIFwiY2hva2lkYXJcIjtcbmltcG9ydCB7IHR5cGUgRmFzdGlmeUluc3RhbmNlLCB0eXBlIEZhc3RpZnlSZXBseSwgdHlwZSBGYXN0aWZ5UmVxdWVzdCB9IGZyb20gXCJmYXN0aWZ5XCI7XG5pbXBvcnQgbWltZSwgeyBsb29rdXAgYXMgbWltZUxvb2t1cCB9IGZyb20gXCJtaW1lLXR5cGVzXCI7XG5pbXBvcnQgeyB0eXBlIFdlYlNvY2tldCB9IGZyb20gXCJ3c1wiO1xuaW1wb3J0IHsgdHlwZSBab2RPYmplY3QgfSBmcm9tIFwiem9kXCI7XG5cbmltcG9ydCB7IEJBU0VfRklFTERfTUFQUElOR1MgfSBmcm9tIFwiLi4vYXV0aC9iZXR0ZXItYXV0aC1lbnRpdGllc1wiO1xuaW1wb3J0IHsgYXBwbHlDYWNoZUhlYWRlcnMsIENhY2hlUHJlc2V0cyB9IGZyb20gXCIuLi9jYWNoZS1jb250cm9sL2NhY2hlLWNvbnRyb2xcIjtcbmltcG9ydCB7IHR5cGUgQ2FjaGVDb250cm9sQ29uZmlnLCB0eXBlIENhY2hlQ29udHJvbFJlcXVlc3QgfSBmcm9tIFwiLi4vY2FjaGUtY29udHJvbC90eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBDYWNoZUNvbmZpZywgdHlwZSBDYWNoZU1hbmFnZXIgfSBmcm9tIFwiLi4vY2FjaGUvdHlwZXNcIjtcbmltcG9ydCB7IHRvRmFzdGlmeUNvbXByZXNzT3B0aW9uIH0gZnJvbSBcIi4uL2NvbXByZXNzL2NvbXByZXNzXCI7XG5pbXBvcnQgeyB0eXBlIENvbXByZXNzT3B0aW9ucyB9IGZyb20gXCIuLi9jb21wcmVzcy90eXBlc1wiO1xuaW1wb3J0IHsgREIgfSBmcm9tIFwiLi4vZGF0YWJhc2UvZGJcIjtcbmltcG9ydCB7IHR5cGUgU29uYW11REJDb25maWcgfSBmcm9tIFwiLi4vZGF0YWJhc2UvZGJcIjtcbmltcG9ydCB7IFNELCBzZXRTRENvbmZpZyB9IGZyb20gXCIuLi9kaWN0L3NkXCI7XG5pbXBvcnQgeyB0eXBlIExvY2FsaXplZFN0cmluZyB9IGZyb20gXCIuLi9kaWN0L3R5cGVzXCI7XG5pbXBvcnQgeyBOb3RGb3VuZEV4Y2VwdGlvbiB9IGZyb20gXCIuLi9leGNlcHRpb25zL3NvLWV4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IEJ1ZmZlcmVkRmlsZSB9IGZyb20gXCIuLi9zdG9yYWdlL2J1ZmZlcmVkLWZpbGVcIjtcbmltcG9ydCB7IHR5cGUgU3RvcmFnZU1hbmFnZXIgfSBmcm9tIFwiLi4vc3RvcmFnZS9zdG9yYWdlLW1hbmFnZXJcIjtcbmltcG9ydCB7IHR5cGUgS2V5R2VuZXJhdG9yIH0gZnJvbSBcIi4uL3N0b3JhZ2UvdHlwZXNcIjtcbmltcG9ydCB7IFVwbG9hZGVkRmlsZSB9IGZyb20gXCIuLi9zdG9yYWdlL3VwbG9hZGVkLWZpbGVcIjtcbmltcG9ydCB7IGNyZWF0ZU1vY2tTU0VGYWN0b3J5IH0gZnJvbSBcIi4uL3N0cmVhbS9zc2VcIjtcbmltcG9ydCB7IFdlYlNvY2tldFJ1bnRpbWUsIHR5cGUgV2ViU29ja2V0Q29ubmVjdGlvbiwgdHlwZSBXZWJTb2NrZXRFdmVudE1hcCB9IGZyb20gXCIuLi9zdHJlYW0vd3NcIjtcbmltcG9ydCB7XG4gIHR5cGUgVGVsZW1ldHJ5Q29udGV4dFByb3ZpZGVyLFxuICB0eXBlIFdlYlNvY2tldFRlbGVtZXRyeUNvbm5lY3Rpb25Db250ZXh0LFxufSBmcm9tIFwiLi4vc3RyZWFtL3dzLXRlbGVtZXRyeVwiO1xuaW1wb3J0IHsgdHlwZSBTeW5jZXIgfSBmcm9tIFwiLi4vc3luY2VyL3N5bmNlclwiO1xuaW1wb3J0IHsgdHlwZSBXb3JrZmxvd01hbmFnZXIgfSBmcm9tIFwiLi4vdGFza3Mvd29ya2Zsb3ctbWFuYWdlclwiO1xuaW1wb3J0IHsgdHlwZSBEZXZWaXRlc3RNYW5hZ2VyIH0gZnJvbSBcIi4uL3Rlc3RpbmcvZGV2LXZpdGVzdC1tYW5hZ2VyXCI7XG5pbXBvcnQgeyB0eXBlIFNvbmFtdUZhc3RpZnlDb25maWcgfSBmcm9tIFwiLi4vdHlwZXMvdHlwZXNcIjtcbmltcG9ydCB7IGNlbnRlclRleHQgfSBmcm9tIFwiLi4vdXRpbHMvY29uc29sZS11dGlsXCI7XG5pbXBvcnQgeyBpc0RhZW1vblNlcnZlciB9IGZyb20gXCIuLi91dGlscy9jb250cm9sbGVyXCI7XG5pbXBvcnQgeyBleGlzdHMsIGZpbGVFeGlzdHMgfSBmcm9tIFwiLi4vdXRpbHMvZnMtdXRpbHNcIjtcbmltcG9ydCB7IHR5cGUgQWJzb2x1dGVQYXRoIH0gZnJvbSBcIi4uL3V0aWxzL3BhdGgtdXRpbHNcIjtcbmltcG9ydCB7IGNvbnZlcnRGYXN0aWZ5SGVhZGVyc1RvU3RhbmRhcmQsIG1lcmdlIH0gZnJvbSBcIi4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyB0eXBlIFNvbmFtdUNvbmZpZywgdHlwZSBTb25hbXVTZXJ2ZXJPcHRpb25zLCB0eXBlIFNvbmFtdVRhc2tPcHRpb25zIH0gZnJvbSBcIi4vY29uZmlnXCI7XG5pbXBvcnQgeyB0eXBlIENvbnRleHQsIHR5cGUgUnVudGltZUNvbnRleHQsIHR5cGUgV2ViU29ja2V0Q29udGV4dCB9IGZyb20gXCIuL2NvbnRleHRcIjtcbmltcG9ydCB7IHR5cGUgRXh0ZW5kZWRBcGkgfSBmcm9tIFwiLi9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBnZXRTZWNyZXRzIH0gZnJvbSBcIi4vc2VjcmV0XCI7XG5pbXBvcnQgeyB0eXBlIFNvbmFtdVNlY3JldHMgfSBmcm9tIFwiLi9zZWNyZXRcIjtcbmltcG9ydCB7XG4gIGNyZWF0ZVdlYlNvY2tldFJlcGx5U3R1YixcbiAgcmVzb2x2ZVdlYlNvY2tldENsb3NlRGVzY3JpcHRvcixcbiAgcmVzb2x2ZVdlYlNvY2tldFBsdWdpbk9wdGlvbnMsXG4gIHJlc29sdmVJbnRlZ3JhdGVkVml0ZUhtck9wdGlvbnMsXG59IGZyb20gXCIuL3dlYnNvY2tldC1oZWxwZXJzXCI7XG5cbmV4cG9ydCB7XG4gIGNyZWF0ZVdlYlNvY2tldFJlcGx5U3R1YixcbiAgcmVzb2x2ZVdlYlNvY2tldENsb3NlRGVzY3JpcHRvcixcbiAgcmVzb2x2ZVdlYlNvY2tldFBsdWdpbk9wdGlvbnMsXG59IGZyb20gXCIuL3dlYnNvY2tldC1oZWxwZXJzXCI7XG5cbmNsYXNzIFNvbmFtdUNsYXNzIHtcbiAgcHVibGljIGlzSW5pdGlhbGl6ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHVibGljIGZvclRlc3Rpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHVibGljIGFzeW5jTG9jYWxTdG9yYWdlOiBBc3luY0xvY2FsU3RvcmFnZTx7XG4gICAgY29udGV4dDogUnVudGltZUNvbnRleHQ7XG4gIH0+ID0gbmV3IEFzeW5jTG9jYWxTdG9yYWdlKCk7XG5cbiAgcHVibGljIGdldENvbnRleHQ8VCBleHRlbmRzIFJ1bnRpbWVDb250ZXh0ID0gQ29udGV4dD4oKTogVCB7XG4gICAgY29uc3Qgc3RvcmUgPSB0aGlzLmFzeW5jTG9jYWxTdG9yYWdlLmdldFN0b3JlKCk7XG4gICAgaWYgKHN0b3JlPy5jb250ZXh0KSB7XG4gICAgICByZXR1cm4gc3RvcmUuY29udGV4dCBhcyBUO1xuICAgIH1cblxuICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gXCJ0ZXN0XCIpIHtcbiAgICAgIC8vIO2FjOyKpO2MhSDtmZjqsr3sl5DshJwg7Luo7YWN7Iqk7Yq46rCAIOyjvOyeheuQmOyngCDslYrsnYAg6rK97JqwIOu5iCDsu6jthY3siqTtirgg66as7YS0XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0cmFuc3BvcnQ6IFwiaHR0cFwiLFxuICAgICAgICByZXF1ZXN0OiBudWxsLFxuICAgICAgICByZXBseTogbnVsbCxcbiAgICAgICAgaGVhZGVyczoge30sXG4gICAgICAgIGNyZWF0ZVNTRTogKHNjaGVtYTogWm9kT2JqZWN0KSA9PiBjcmVhdGVNb2NrU1NFRmFjdG9yeShzY2hlbWEpLFxuICAgICAgICBsb2NhbGU6IFwiXCIsXG4gICAgICAgIHVzZXI6IG51bGwsXG4gICAgICAgIHNlc3Npb246IG51bGwsXG4gICAgICAgIG5haXRlU3RvcmU6IG5ldyBNYXA8c3RyaW5nLCBhbnk+KCksXG4gICAgICB9IGFzIHVua25vd24gYXMgVDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGNhbm5vdCBmaW5kIGNvbnRleHRcIik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfYXBpUm9vdFBhdGg6IEFic29sdXRlUGF0aCB8IG51bGwgPSBudWxsO1xuICBzZXQgYXBpUm9vdFBhdGgoYXBpUm9vdFBhdGg6IEFic29sdXRlUGF0aCkge1xuICAgIHRoaXMuX2FwaVJvb3RQYXRoID0gYXBpUm9vdFBhdGg7XG4gIH1cbiAgZ2V0IGFwaVJvb3RQYXRoKCk6IEFic29sdXRlUGF0aCB7XG4gICAgaWYgKHRoaXMuX2FwaVJvb3RQYXRoID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb25hbXUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fYXBpUm9vdFBhdGg7XG4gIH1cbiAgZ2V0IGFwcFJvb3RQYXRoKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYXBpUm9vdFBhdGguc3BsaXQocGF0aC5zZXApLnNsaWNlKDAsIC0xKS5qb2luKHBhdGguc2VwKTtcbiAgfVxuXG4gIHByaXZhdGUgX2RiQ29uZmlnOiBTb25hbXVEQkNvbmZpZyB8IG51bGwgPSBudWxsO1xuICBzZXQgZGJDb25maWcoZGJDb25maWc6IFNvbmFtdURCQ29uZmlnKSB7XG4gICAgdGhpcy5fZGJDb25maWcgPSBkYkNvbmZpZztcbiAgfVxuICBnZXQgZGJDb25maWcoKTogU29uYW11REJDb25maWcge1xuICAgIGlmICh0aGlzLl9kYkNvbmZpZyA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2RiQ29uZmlnO1xuICB9XG5cbiAgcHJpdmF0ZSBfc3luY2VyOiBTeW5jZXIgfCBudWxsID0gbnVsbDtcbiAgc2V0IHN5bmNlcihzeW5jZXI6IFN5bmNlcikge1xuICAgIHRoaXMuX3N5bmNlciA9IHN5bmNlcjtcbiAgfVxuICBnZXQgc3luY2VyKCk6IFN5bmNlciB7XG4gICAgaWYgKHRoaXMuX3N5bmNlciA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3N5bmNlcjtcbiAgfVxuXG4gIHByaXZhdGUgX2NvbmZpZzogU29uYW11Q29uZmlnIHwgbnVsbCA9IG51bGw7XG4gIHNldCBjb25maWcoY29uZmlnOiBTb25hbXVDb25maWcpIHtcbiAgICB0aGlzLl9jb25maWcgPSBjb25maWc7XG4gIH1cbiAgZ2V0IGNvbmZpZygpOiBTb25hbXVDb25maWcge1xuICAgIGlmICh0aGlzLl9jb25maWcgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jb25maWc7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgc2VjcmV0czogU29uYW11U2VjcmV0cyA9IGdldFNlY3JldHMoKTtcblxuICBwcml2YXRlIF9zdG9yYWdlOiBTdG9yYWdlTWFuYWdlciB8IG51bGwgPSBudWxsO1xuICAvKipcbiAgICogU3RvcmFnZU1hbmFnZXIg7J247Iqk7YS07IqkXG4gICAqL1xuICBnZXQgc3RvcmFnZSgpOiBTdG9yYWdlTWFuYWdlciB7XG4gICAgaWYgKCF0aGlzLl9zdG9yYWdlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTdG9yYWdlIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZC4gQ2hlY2sgc3RvcmFnZSBjb25maWcuXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fc3RvcmFnZTtcbiAgfVxuXG4gIHByaXZhdGUgX2NhY2hlOiBDYWNoZU1hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIENhY2hlTWFuYWdlciDsnbjsiqTthLTsiqQgKEJlbnRvQ2FjaGUpXG4gICAqL1xuICBnZXQgY2FjaGUoKTogQ2FjaGVNYW5hZ2VyIHtcbiAgICBpZiAoIXRoaXMuX2NhY2hlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYWNoZSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWQuIENoZWNrIGNhY2hlIGNvbmZpZyBpbiBzb25hbXUuY29uZmlnLnRzLlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2NhY2hlO1xuICB9XG5cbiAgcHJpdmF0ZSBfd29ya2Zsb3dzOiBXb3JrZmxvd01hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgZ2V0IHdvcmtmbG93cygpOiBXb3JrZmxvd01hbmFnZXIge1xuICAgIGlmICh0aGlzLl93b3JrZmxvd3MgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3dvcmtmbG93cztcbiAgfVxuXG4gIHByaXZhdGUgX2F1dGg6IEF1dGg8QmV0dGVyQXV0aE9wdGlvbnM+IHwgbnVsbCA9IG51bGw7XG4gIGdldCBhdXRoKCk6IEF1dGg8QmV0dGVyQXV0aE9wdGlvbnM+IHtcbiAgICBpZiAoIXRoaXMuX2F1dGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkF1dGggaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkLiBDaGVjayBhdXRoIGNvbmZpZyBpbiBzb25hbXUuY29uZmlnLnRzLlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2F1dGg7XG4gIH1cblxuICBwcml2YXRlIF9kZXZWaXRlc3RNYW5hZ2VyOiBEZXZWaXRlc3RNYW5hZ2VyIHwgbnVsbCA9IG51bGw7XG4gIGdldCBkZXZWaXRlc3RNYW5hZ2VyKCk6IERldlZpdGVzdE1hbmFnZXIgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fZGV2Vml0ZXN0TWFuYWdlcjtcbiAgfVxuICBzZXQgZGV2Vml0ZXN0TWFuYWdlcihtYW5hZ2VyOiBEZXZWaXRlc3RNYW5hZ2VyIHwgbnVsbCkge1xuICAgIHRoaXMuX2RldlZpdGVzdE1hbmFnZXIgPSBtYW5hZ2VyO1xuICB9XG5cbiAgLy8gU29uYW116rCAIHJ1bnRpbWXsnYQg7KeB7KCRIOyGjOycoO2VtCByZWdpc3RyeS9jb25uZWN0aW9uIGxpZmVjeWNsZeydhCDslaDtlIzrpqzsvIDsnbTshZgg7IiY66qF7KO86riw7JmAIOuPmeq4sO2ZlO2VqFxuICBwcml2YXRlIF93ZWJzb2NrZXRSdW50aW1lOiBXZWJTb2NrZXRSdW50aW1lIHwgbnVsbCA9IG51bGw7XG4gIC8vIOqwmeydgCBGYXN0aWZ5IOyduOyKpO2EtOyKpOyXkCBAZmFzdGlmeS93ZWJzb2NrZXTsnYQg7KSR67O1IOuTseuhne2VmOuKlCDqsoPsnYQgV2Vha1NldOycvOuhnCDssKjri6jtlahcbiAgcHJpdmF0ZSByZWFkb25seSB3ZWJzb2NrZXRQbHVnaW5TZXJ2ZXJzID0gbmV3IFdlYWtTZXQ8XG4gICAgRmFzdGlmeUluc3RhbmNlPFNlcnZlciwgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZT5cbiAgPigpO1xuICBnZXQgd2Vic29ja2V0UnVudGltZSgpOiBXZWJTb2NrZXRSdW50aW1lIHtcbiAgICBpZiAoIXRoaXMuX3dlYnNvY2tldFJ1bnRpbWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIldlYlNvY2tldCBydW50aW1lIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZC5cIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRSdW50aW1lO1xuICB9XG4gIHNldCB3ZWJzb2NrZXRSdW50aW1lKHJ1bnRpbWU6IFdlYlNvY2tldFJ1bnRpbWUgfCBudWxsKSB7XG4gICAgdGhpcy5fd2Vic29ja2V0UnVudGltZSA9IHJ1bnRpbWU7XG4gIH1cblxuICAvLyBITVIg7LKY66asOiDtjIzsnbwg7Iuc7Iqk7YWcIOqwkOyLnCArIEhNUi9zeW5jIOyCrOydtO2BtCDsi6TtlonsnYAgd2F0Y2hlciDrqqjrk4jroZwg7JyE7J6E7ZWp64uI64ukLlxuICBwdWJsaWMgd2F0Y2hlcjogRlNXYXRjaGVyIHwgbnVsbCA9IG51bGw7XG5cbiAgcHVibGljIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlIHwgbnVsbCA9IG51bGw7XG5cbiAgYXN5bmMgaW5pdEZvclRlc3RpbmcoKSB7XG4gICAgYXdhaXQgdGhpcy5pbml0KHRydWUsIGZhbHNlLCB1bmRlZmluZWQsIHRydWUpO1xuICB9XG5cbiAgYXN5bmMgaW5pdChcbiAgICBkb1NpbGVudDogYm9vbGVhbiA9IGZhbHNlLFxuICAgIGVuYWJsZVN5bmM6IGJvb2xlYW4gPSB0cnVlLFxuICAgIGFwaVJvb3RQYXRoPzogQWJzb2x1dGVQYXRoLFxuICAgIGZvclRlc3Rpbmc6IGJvb2xlYW4gPSBmYWxzZSxcbiAgKSB7XG4gICAgdGhpcy5mb3JUZXN0aW5nID0gZm9yVGVzdGluZztcblxuICAgIGlmICh0aGlzLmlzSW5pdGlhbGl6ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBpbml0U3RhcnQgPSBwZXJmb3JtYW5jZS5ub3coKTtcblxuICAgIC8vIEFQSSDro6jtirgg7Yyo7IqkXG4gICAgY29uc3QgeyBmaW5kQXBpUm9vdFBhdGggfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL3V0aWxzXCIpO1xuICAgIHRoaXMuYXBpUm9vdFBhdGggPSBhcGlSb290UGF0aCA/PyBmaW5kQXBpUm9vdFBhdGgoKTtcblxuICAgIC8vIOyEpOygleydhCDroZzrlKntlZjripQg6rKD67aA7YSwIOyLnOyekVxuICAgIGNvbnN0IGNvbmZpZ1N0YXJ0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgY29uc3QgeyBsb2FkQ29uZmlnIH0gPSBhd2FpdCBpbXBvcnQoXCIuL2NvbmZpZ1wiKTtcbiAgICB0aGlzLmNvbmZpZyA9IGF3YWl0IGxvYWRDb25maWcodGhpcy5hcGlSb290UGF0aCk7XG4gICAgY29uc3QgY29uZmlnVGltZSA9IHBlcmZvcm1hbmNlLm5vdygpIC0gY29uZmlnU3RhcnQ7XG4gICAgc2V0U0RDb25maWcodGhpcy5jb25maWcuaTE4bik7XG4gICAgLy8gc29uYW11LmNvbmZpZy50cyDquLDrs7jqsJIg7ISk7KCVXG4gICAgdGhpcy5jb25maWcuZGF0YWJhc2UuZGF0YWJhc2UgPSB0aGlzLmNvbmZpZy5kYXRhYmFzZS5kYXRhYmFzZSA/PyBcInBnXCI7XG4gICAgdGhpcy5jb25maWcuZGF0YWJhc2UuZGVmYXVsdE9wdGlvbnMuY2xpZW50ID0gdGhpcy5jb25maWcuZGF0YWJhc2UuZGF0YWJhc2UgPz8gXCJwZ1wiO1xuXG4gICAgLy8g66Gc6rmFIOyEpOyglVxuICAgIGNvbnN0IHsgY29uZmlndXJlTG9nVGFwZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vbG9nZ2VyL2NvbmZpZ3VyZVwiKTtcbiAgICBpZiAodGhpcy5jb25maWcubG9nZ2luZyAhPT0gZmFsc2UpIHtcbiAgICAgIGF3YWl0IGNvbmZpZ3VyZUxvZ1RhcGUoe1xuICAgICAgICAuLi50aGlzLmNvbmZpZy5sb2dnaW5nLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gREIg66Gc65OcXG4gICAgY29uc3QgeyBEQiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZGF0YWJhc2UvZGJcIik7XG4gICAgdGhpcy5kYkNvbmZpZyA9IERCLmdlbmVyYXRlREJDb25maWcodGhpcy5jb25maWcuZGF0YWJhc2UpO1xuICAgIERCLnNldENvbmZpZyh0aGlzLmRiQ29uZmlnKTtcblxuICAgIC8vIEVudGl0eSDroZzrk5xcbiAgICAvLyDthYzsiqTtirjsl5DshJzrj4QgRW50aXR5IOygleuztOuKlCDtlYTsmpTtlanri4jri6QuXG4gICAgLy8gdXBzZXJ06rCAIOygnOuMgOuhnCDsnpHrj5ntlZjroKTrqbQgZW50aXR57J2YIHVuaXF1ZSBpbmRleCDsoJXrs7TqsIAg7ZWE7JqU7ZWY6riwIOuVjOusuOyeheuLiOuLpC5cbiAgICBjb25zdCB7IEVudGl0eU1hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiKTtcbiAgICBhd2FpdCBFbnRpdHlNYW5hZ2VyLmF1dG9sb2FkKGRvU2lsZW50KTtcblxuICAgIC8vIENhY2hlIOy0iOq4sO2ZlFxuICAgIGF3YWl0IHRoaXMuaW5pdGlhbGl6ZUNhY2hlKHRoaXMuY29uZmlnLnNlcnZlci5jYWNoZSwgZm9yVGVzdGluZyk7XG5cbiAgICAvLyBCZXR0ZXJBdXRoIOy0iOq4sO2ZlFxuICAgIGNvbnN0IGF1dGhDb25maWcgPSB0aGlzLmNvbmZpZy5zZXJ2ZXIuYXV0aDtcbiAgICBpZiAoYXV0aENvbmZpZykge1xuICAgICAgLy8g7IKs7Jqp7J6QIOyEpOygleqzvCDquLDrs7jqsJLsnYQgbWVyZ2VcbiAgICAgIGNvbnN0IG1lcmdlZEZpZWxkTWFwcGluZ3MgPSBtZXJnZShCQVNFX0ZJRUxEX01BUFBJTkdTLCBhdXRoQ29uZmlnKTtcblxuICAgICAgLy8gYmV0dGVyLWF1dGgg7J247Iqk7YS07IqkIOyDneyEsVxuICAgICAgY29uc3QgeyBiZXR0ZXJBdXRoIH0gPSBhd2FpdCBpbXBvcnQoXCJiZXR0ZXItYXV0aFwiKTtcbiAgICAgIGNvbnN0IHsgc29uYW11S25leEFkYXB0ZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL2F1dGgva25leC1hZGFwdGVyXCIpO1xuXG4gICAgICBjb25zdCBhdXRoT3B0aW9uczogQmV0dGVyQXV0aE9wdGlvbnMgPSB7XG4gICAgICAgIGRhdGFiYXNlOiBzb25hbXVLbmV4QWRhcHRlcigpLFxuICAgICAgICAuLi5tZXJnZWRGaWVsZE1hcHBpbmdzLFxuICAgICAgfTtcbiAgICAgIHRoaXMuX2F1dGggPSBiZXR0ZXJBdXRoKGF1dGhPcHRpb25zKTtcbiAgICB9XG5cbiAgICAvLyDthYzsiqTtjIXsnbgg6rK97JqwIOyLse2BrCDsl4bsnbQg7KSR64uoXG4gICAgaWYgKGZvclRlc3RpbmcpIHtcbiAgICAgIHRoaXMuaXNJbml0aWFsaXplZCA9IHRydWU7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVGFzayDrk7HroZ1cbiAgICBhd2FpdCB0aGlzLmluaXRpYWxpemVXb3JrZmxvd3ModGhpcy5jb25maWcudGFza3MpO1xuXG4gICAgLy8gU3luY2VyXG4gICAgY29uc3QgeyBTeW5jZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3N5bmNlci9zeW5jZXJcIik7XG4gICAgdGhpcy5zeW5jZXIgPSBuZXcgU3luY2VyKCk7XG5cbiAgICAvLyBBdXRvbG9hZDogTW9kZWxzIC8gVHlwZXMgLyBBUElzIC8gV29ya2Zsb3dzIC8gVGVtcGxhdGVzIC8gU1NSIFJvdXRlc1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkVHlwZXMoKTtcbiAgICBhd2FpdCB0aGlzLnN5bmNlci5hdXRvbG9hZE1vZGVscygpO1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkQXBpcygpO1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkV29ya2Zsb3dzKCk7XG4gICAgY29uc3QgeyBUZW1wbGF0ZU1hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3RlbXBsYXRlXCIpO1xuICAgIGF3YWl0IFRlbXBsYXRlTWFuYWdlci5hdXRvbG9hZCgpO1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkU3NyUm91dGVzKCk7XG5cbiAgICBjb25zdCB7IGlzTG9jYWwsIGlzVGVzdCwgaXNIb3RSZWxvYWRTZXJ2ZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL2NvbnRyb2xsZXJcIik7XG4gICAgaWYgKGlzTG9jYWwoKSAmJiAhaXNUZXN0KCkgJiYgaXNIb3RSZWxvYWRTZXJ2ZXIoKSAmJiBlbmFibGVTeW5jKSB7XG4gICAgICBhd2FpdCB0aGlzLnN5bmNlci5zeW5jKCk7XG4gICAgICBhd2FpdCB0aGlzLnN0YXJ0V2F0Y2hlcigpO1xuICAgIH1cblxuICAgIHRoaXMuaXNJbml0aWFsaXplZCA9IHRydWU7XG4gICAgdGhpcy5faW5pdEVsYXBzZWQgPSBwZXJmb3JtYW5jZS5ub3coKSAtIGluaXRTdGFydDtcbiAgICB0aGlzLl9jb25maWdFbGFwc2VkID0gY29uZmlnVGltZTtcbiAgfVxuXG4gIHByaXZhdGUgX2luaXRFbGFwc2VkID0gMDtcbiAgcHJpdmF0ZSBfY29uZmlnRWxhcHNlZCA9IDA7XG5cbiAgYXN5bmMgY3JlYXRlU2VydmVyKGluaXRPcHRpb25zPzogeyBlbmFibGVTeW5jPzogYm9vbGVhbjsgZG9TaWxlbnQ/OiBib29sZWFuIH0pIHtcbiAgICBpZiAoIXRoaXMuaXNJbml0aWFsaXplZCkge1xuICAgICAgYXdhaXQgdGhpcy5pbml0KGluaXRPcHRpb25zPy5kb1NpbGVudCwgaW5pdE9wdGlvbnM/LmVuYWJsZVN5bmMpO1xuICAgIH1cblxuICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLmNvbmZpZy5zZXJ2ZXI7XG4gICAgY29uc3QgeyBkZWZhdWx0OiBmYXN0aWZ5IH0gPSBhd2FpdCBpbXBvcnQoXCJmYXN0aWZ5XCIpO1xuICAgIGNvbnN0IHsgZ2V0TG9nVGFwZUZhc3RpZnlMb2dnZXIgfSA9IGF3YWl0IGltcG9ydChcIkBsb2d0YXBlL2Zhc3RpZnlcIik7XG4gICAgY29uc3Qgc2VydmVyID0gZmFzdGlmeSh7XG4gICAgICAuLi5vcHRpb25zLmZhc3RpZnksXG4gICAgICBsb2dnZXI6XG4gICAgICAgIHRoaXMuY29uZmlnLmxvZ2dpbmcgIT09IGZhbHNlXG4gICAgICAgICAgPyBnZXRMb2dUYXBlRmFzdGlmeUxvZ2dlcih7XG4gICAgICAgICAgICAgIGNhdGVnb3J5OiB0aGlzLmNvbmZpZy5sb2dnaW5nPy5mYXN0aWZ5Q2F0ZWdvcnkgPz8gW1wiZmFzdGlmeVwiXSxcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG4gICAgdGhpcy53ZWJzb2NrZXRSdW50aW1lID0gbmV3IFdlYlNvY2tldFJ1bnRpbWUob3B0aW9ucy53ZWJzb2NrZXQpO1xuXG4gICAgLy8gU3RvcmFnZSDshKTsoJUg4oaSIFN0b3JhZ2VNYW5hZ2VyIOyDneyEsVxuICAgIGlmIChvcHRpb25zLnN0b3JhZ2UpIHtcbiAgICAgIGNvbnN0IHsgU3RvcmFnZU1hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3N0b3JhZ2Uvc3RvcmFnZS1tYW5hZ2VyXCIpO1xuICAgICAgdGhpcy5fc3RvcmFnZSA9IG5ldyBTdG9yYWdlTWFuYWdlcihvcHRpb25zLnN0b3JhZ2UpO1xuICAgIH1cblxuICAgIC8vIO2UjOufrOq3uOyduCDrk7HroZ1cbiAgICBpZiAob3B0aW9ucy5wbHVnaW5zKSB7XG4gICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyUGx1Z2lucyhzZXJ2ZXIsIG9wdGlvbnMucGx1Z2lucyk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuYXV0aCkge1xuICAgICAgYXdhaXQgdGhpcy5yZWdpc3RlckJldHRlckF1dGgoc2VydmVyLCBvcHRpb25zLmF1dGgpO1xuICAgIH1cblxuICAgIC8vIEFQSSDrnbzsmrDtjIUg7ISk7KCVXG4gICAgYXdhaXQgdGhpcy53aXRoRmFzdGlmeShzZXJ2ZXIsIG9wdGlvbnMuYXBpQ29uZmlnLCB7XG4gICAgICBlbmFibGVTeW5jOiBpbml0T3B0aW9ucz8uZW5hYmxlU3luYyxcbiAgICAgIGRvU2lsZW50OiBpbml0T3B0aW9ucz8uZG9TaWxlbnQsXG4gICAgfSk7XG5cbiAgICAvLyDshJzrsoQg7Iuc7J6RXG4gICAgYXdhaXQgdGhpcy5ib290KHNlcnZlciwgb3B0aW9ucyk7XG5cbiAgICBpZiAoIWluaXRPcHRpb25zPy5kb1NpbGVudCkge1xuICAgICAgdGhpcy5wcmludFN0YXJ0dXBTdW1tYXJ5KCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlcnZlcjtcbiAgfVxuXG4gIGFzeW5jIHdpdGhGYXN0aWZ5KFxuICAgIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlPFNlcnZlciwgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZT4sXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICAgIG9wdGlvbnM/OiB7XG4gICAgICBlbmFibGVTeW5jPzogYm9vbGVhbjtcbiAgICAgIGRvU2lsZW50PzogYm9vbGVhbjtcbiAgICB9LFxuICApIHtcbiAgICBpZiAoIXRoaXMuaXNJbml0aWFsaXplZCkge1xuICAgICAgYXdhaXQgdGhpcy5pbml0KG9wdGlvbnM/LmRvU2lsZW50LCBvcHRpb25zPy5lbmFibGVTeW5jKTtcbiAgICB9XG5cbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcbiAgICB0aGlzLndlYnNvY2tldFJ1bnRpbWUgPz89IG5ldyBXZWJTb2NrZXRSdW50aW1lKHRoaXMuY29uZmlnLnNlcnZlci53ZWJzb2NrZXQpO1xuXG4gICAgLy8gdGltZXpvbmUg7ISk7KCVXG4gICAgY29uc3QgdGltZXpvbmUgPSB0aGlzLmNvbmZpZy5hcGkudGltZXpvbmU7XG4gICAgaWYgKHRpbWV6b25lKSB7XG4gICAgICAvLyDtg4DsnoTsobTsl5Ag66ee6rKMIOydkeuLtSDrgqDsp5wg7Iqk7Yq466eB7J2EIOuzgO2ZmO2VtOyjvOyWtOyVvCDtlanri4jri6QuXG4gICAgICAvLyDqsIDroLkgdGltZXpvbmXsnbQgXCJBc2lhL1Nlb3VsXCIg7J2066m0XG4gICAgICAvLyBcIjIwMjUtMTEtMjFUMDA6MDA6MDAuMDAwWlwiIOulvCBcIjIwMjUtMTEtMjFUMDk6MDA6MDArMDk6MDBcIiDsnLzroZwg67OA7ZmY7ZW07KO87Ja07JW8IO2VqeuLiOuLpC5cbiAgICAgIGNvbnN0IHsgZm9ybWF0SW5UaW1lWm9uZSB9ID0gYXdhaXQgaW1wb3J0KFwiZGF0ZS1mbnMtdHpcIik7XG5cbiAgICAgIC8vIElTTyA4NjAxIOuCoOynnCDtmJXsi50g7KCV6rec7IudICjsmIg6IDIwMjQtMDEtMTVUMDk6MzA6MDAuMDAwWilcbiAgICAgIGNvbnN0IElTT19EQVRFX1JFR0VYID0gL15cXGR7NH0tXFxkezJ9LVxcZHsyfVRcXGR7Mn06XFxkezJ9OlxcZHsyfShcXC5cXGR7M30pP1okLztcblxuICAgICAgLy8gVOulvCDrkZjrn6zsi7wg7J6R7J2A65Sw7Ji07ZGc6rCAIOyXhuuLpOuptCBcIjIwMjUtMTEtMTkxNzYzNTQ2MTg5MDAwMTg6NTY6MjkrMDk6MDBcIuyZgCDqsJnsnYAg6rKw6rO86rCAIOuCmOyYteuLiOuLpC5cbiAgICAgIC8vIOydtOuKlCBkYXRlLWZucyDtirnsnoXri4jri6QuXG4gICAgICAvLyDsnbTroIfqsowg7ZW064+EIOq0nOywruyKteuLiOuLpC4gXCIyMDI1LTExLTE5VDE4OjU2OjI5KzA5OjAwXCIg66qo7JaR7Jy866GcIOyemCDrgpjsmLXri4jri6QuXG4gICAgICBjb25zdCBEQVRFX0ZPUk1BVCA9IFwieXl5eS1NTS1kZCdUJ0hIOm1tOnNzWFhYXCI7XG5cbiAgICAgIHNlcnZlci5zZXRSZXBseVNlcmlhbGl6ZXIoKHBheWxvYWQpID0+IHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHBheWxvYWQsIChfa2V5LCB2YWx1ZSkgPT4ge1xuICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiYgSVNPX0RBVEVfUkVHRVgudGVzdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXRJblRpbWVab25lKFxuICAgICAgICAgICAgICBuZXcgRGF0ZSh2YWx1ZSksXG4gICAgICAgICAgICAgIHRpbWV6b25lIGFzIGAke3N0cmluZ30vJHtzdHJpbmd9YCxcbiAgICAgICAgICAgICAgREFURV9GT1JNQVQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgICAvLyBUaW1lem9uZSDroZzqt7jripQgcHJpbnRTdGFydHVwU3VtbWFyeeyXkOyEnCDthrXtlakg7Lac66ClXG4gICAgfVxuXG4gICAgLy8g7KCE7LK0IOudvOyasO2MhSDrpqzsiqTtirhcbiAgICBzZXJ2ZXIuZ2V0KFxuICAgICAgYCR7dGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeH0vcm91dGVzYCxcbiAgICAgIGFzeW5jIChfcmVxdWVzdCwgX3JlcGx5KTogUHJvbWlzZTx0eXBlb2YgdGhpcy5zeW5jZXIuYXBpcz4gPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zeW5jZXIuYXBpcztcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIEhlYWx0aGNoZWNrIEFQSVxuICAgIHNlcnZlci5nZXQoXG4gICAgICBgJHt0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4fS9oZWFsdGhjaGVja2AsXG4gICAgICBhc3luYyAoX3JlcXVlc3QsIF9yZXBseSk6IFByb21pc2U8c3RyaW5nPiA9PiB7XG4gICAgICAgIHJldHVybiBcIm9rXCI7XG4gICAgICB9LFxuICAgICk7XG5cbiAgICAvLyBTb25hbXUgVUkgQVBJICjroZzsu6wg7ZmY6rK97JeQ7ISc66eMKVxuICAgIGNvbnN0IHsgaXNMb2NhbCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvY29udHJvbGxlclwiKTtcbiAgICBpZiAoaXNMb2NhbCgpKSB7XG4gICAgICBjb25zdCB7IHNvbmFtdVVJQXBpUGx1Z2luIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi91aS9hcGlcIik7XG4gICAgICBzZXJ2ZXIucmVnaXN0ZXIoc29uYW11VUlBcGlQbHVnaW4pO1xuICAgIH1cblxuICAgIC8vIERldlJ1bm5lciDthYzsiqTtirgg7JeU65Oc7Y+s7J247Yq4ICjroZzsu6wg7ZmY6rK9ICsgZGV2UnVubmVyIO2ZnOyEse2ZlCDsi5wpXG4gICAgaWYgKGlzTG9jYWwoKSAmJiB0aGlzLmNvbmZpZy50ZXN0Py5kZXZSdW5uZXI/LmVuYWJsZWQpIHtcbiAgICAgIGNvbnN0IHsgcmVnaXN0ZXJEZXZUZXN0Um91dGVzIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi90ZXN0aW5nL2Rldi10ZXN0LXJvdXRlc1wiKTtcbiAgICAgIGF3YWl0IHJlZ2lzdGVyRGV2VGVzdFJvdXRlcyhzZXJ2ZXIsIHRoaXMuY29uZmlnLnRlc3QuZGV2UnVubmVyKTtcbiAgICB9XG5cbiAgICBjb25zdCB3ZWJQYXRoID0gcGF0aC5qb2luKHRoaXMuYXBwUm9vdFBhdGgsIFwid2ViXCIpO1xuICAgIGNvbnN0IGhhc1dlYiA9IGF3YWl0IGV4aXN0cyh3ZWJQYXRoKTtcblxuICAgIC8vIOyghOyXrSBjb21wcmVzcyDsmLXshZgg6rOE7IKwIChyb3V0ZS5jb21wcmVzczogdHJ1ZeydvCDrlYwg7IKs7JqpKVxuICAgIGNvbnN0IHBsdWdpbkNvbXByZXNzID0gdGhpcy5jb25maWcuc2VydmVyLnBsdWdpbnM/LmNvbXByZXNzO1xuICAgIGNvbnN0IGdsb2JhbENvbXByZXNzT3B0aW9uczogQ29tcHJlc3NPcHRpb25zIHwgdW5kZWZpbmVkID0gcGx1Z2luQ29tcHJlc3NcbiAgICAgID8gcGx1Z2luQ29tcHJlc3MgPT09IHRydWVcbiAgICAgICAgPyB7IHRocmVzaG9sZDogMTAyNCwgZW5jb2RpbmdzOiBbXCJiclwiLCBcImd6aXBcIiwgXCJkZWZsYXRlXCJdIH1cbiAgICAgICAgOiB7XG4gICAgICAgICAgICB0aHJlc2hvbGQ6IHBsdWdpbkNvbXByZXNzLnRocmVzaG9sZCxcbiAgICAgICAgICAgIGVuY29kaW5nczogcGx1Z2luQ29tcHJlc3MuZW5jb2RpbmdzLFxuICAgICAgICAgICAgY3VzdG9tVHlwZXM6IHBsdWdpbkNvbXByZXNzLmN1c3RvbVR5cGVzLFxuICAgICAgICAgIH1cbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgaWYgKGlzTG9jYWwoKSkge1xuICAgICAgLy8g66Gc7LusIOqwnOuwnCDtmZjqsr06IGNhdGNoLWFsbOuhnCBBUEnrpbwg64+Z7KCBIOunpOy5re2VmOyXrCBITVLsnYQg7KeA7JuQ7ZWp64uI64ukLlxuICAgICAgLy8gU09OQU1VX0RJU0FCTEVfSU5URUdSQVRFRF9XRUI9eWVz66GcIOyEpOygle2VmOuptCBkZXZfYXBpIOuqqOuTnOyXkOyEnCBWaXRlIO2Gte2VqeydhCDruYTtmZzshLHtmZTtlaAg7IiYIOyeiOyKteuLiOuLpC5cbiAgICAgIGNvbnN0IGRpc2FibGVJbnRlZ3JhdGVkV2ViID0gcHJvY2Vzcy5lbnYuU09OQU1VX0RJU0FCTEVfSU5URUdSQVRFRF9XRUIgPT09IFwieWVzXCI7XG4gICAgICBpZiAoaGFzV2ViICYmICFkaXNhYmxlSW50ZWdyYXRlZFdlYikge1xuICAgICAgICBhd2FpdCB0aGlzLnNldHVwRGV2U2VydmVyV2l0aFZpdGUoc2VydmVyLCB3ZWJQYXRoLCBjb25maWcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zZXR1cERldlNlcnZlcihzZXJ2ZXIsIGNvbmZpZyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIO2UhOuhnOuNleyFmCDtmZjqsr06IOqwnOuzhCBBUEkg65287Jqw7Yq4ICsg7KCV7KCBIO2MjOydvCDshJzruZlcbiAgICAgIGZvciAoY29uc3QgYXBpIG9mIHRoaXMuc3luY2VyLmFwaXMpIHtcbiAgICAgICAgaWYgKHRoaXMuc3luY2VyLm1vZGVsc1thcGkubW9kZWxOYW1lXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGDsoJXsnZjrkJjsp4Ag7JWK7J2AIOuqqOuNuOyXkCDsoJHqt7wgJHthcGkubW9kZWxOYW1lfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQHdlYnNvY2tldCByb3V0ZeuKlCB3c0hhbmRsZXLroZwg65Ox66Gd7ZWY6rOgLCDqsJnsnYAgcGF0aOydmCDsnbzrsJggSFRUUCBHRVTsnYAgNDI2IOydkeuLteycvOuhnCB1cGdyYWRl66W8IOqwleygnO2VqFxuICAgICAgICBpZiAoYXBpLndlYnNvY2tldE9wdGlvbnMpIHtcbiAgICAgICAgICBzZXJ2ZXIucm91dGUoe1xuICAgICAgICAgICAgbWV0aG9kOiBcIkdFVFwiLFxuICAgICAgICAgICAgdXJsOiB0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4ICsgYXBpLnBhdGgsXG4gICAgICAgICAgICBoYW5kbGVyOiB0aGlzLmNyZWF0ZVdlYlNvY2tldFVwZ3JhZGVSZXF1aXJlZEhhbmRsZXIoKSxcbiAgICAgICAgICAgIHdzSGFuZGxlcjogdGhpcy5jcmVhdGVXZWJTb2NrZXRIYW5kbGVyKGFwaSwgY29uZmlnKSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICAgICAgbWV0aG9kOiBhcGkub3B0aW9ucy5odHRwTWV0aG9kID8/IFwiR0VUXCIsXG4gICAgICAgICAgdXJsOiB0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4ICsgYXBpLnBhdGgsXG4gICAgICAgICAgaGFuZGxlcjogdGhpcy5jcmVhdGVBcGlIYW5kbGVyKGFwaSwgY29uZmlnKSxcbiAgICAgICAgICBjb21wcmVzczogdG9GYXN0aWZ5Q29tcHJlc3NPcHRpb24oYXBpLm9wdGlvbnMuY29tcHJlc3MsIGdsb2JhbENvbXByZXNzT3B0aW9ucyksXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICAvLyDtlITroZzrjZXshZjsl5DshJzripQgd2ViIOyGjOyKpChhcHBSb290L3dlYikg7Jyg66y07JmAIOustOq0gO2VmOqyjCxcbiAgICAgIC8vIGFwaS93ZWItZGlzdCDsobTsnqwg7Jes67aA66W8IHNldHVwU3RhdGljV2ViU2VydmVyIOuCtOu2gOyXkOyEnCDtjJDri6jtlanri4jri6QuXG4gICAgICBhd2FpdCB0aGlzLnNldHVwU3RhdGljV2ViU2VydmVyKHNlcnZlciwgY29uZmlnLCBnbG9iYWxDb21wcmVzc09wdGlvbnMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBkZXYg66qo65OcIOqzte2GtTogY2F0Y2gtYWxs7JeQ7IScIHN5bmNlci5hcGlz66W8IOuPmeyggeycvOuhnCDtg5Dsg4ntlZjsl6wgQVBJIOyalOyyreydhCDsspjrpqztlanri4jri6QuXG4gICAqIHNlcnZlci5yb3V0ZSgp66GcIOqwnOuzhCDrk7HroZ3tlZjrqbQgaGFuZGxlcuqwgCDqs6DsoJXrkJjslrQgSE1S7J20IOuPmeyeke2VmOyngCDslYrsnLzrr4DroZwsXG4gICAqIOunpCDsmpTssq3rp4jri6Qgc3luY2VyLmFwaXPrpbwg7KGw7ZqM7ZWY64qUIOydtCDrsKnsi53snYQg7IKs7Jqp7ZWp64uI64ukLlxuICAgKlxuICAgKiDsmpTssq3snbQgL2FwaSjsoJXtmZXtnojripQgdGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeCnroZwg7Iuc7J6R7ZWY7KeAIOyViuuKlCDqsr3smrDrnbzrqbQgbnVsbOydhCDrsJjtmZjtlZjrqbAg64Gd64OF64uI64ukLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVEZXZBcGlSZXF1ZXN0KFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgKTogKChyZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCwgcmVwbHk6IEZhc3RpZnlSZXBseSkgPT4gUHJvbWlzZTx1bmtub3duPikgfCBudWxsIHtcbiAgICBjb25zdCBtYXRjaGVkQXBpID0gdGhpcy5maW5kTWF0Y2hlZEFwaShyZXF1ZXN0KTtcblxuICAgIGlmICghbWF0Y2hlZEFwaSkge1xuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKFNEKFwiZXJyb3IuYXBpLm5vdEZvdW5kXCIpKTtcbiAgICB9XG5cbiAgICAvLyB3ZWJzb2NrZXQgcm91dGXrpbwg7J2867CYIEhUVFDroZwg7KeB7KCRIO2YuOy2nO2VnCDqsr3smrAgNDI27J2EIOuPjOugpOykmCB1cGdyYWRlIOyXhuydtCDsoJHqt7ztlZjripQg6rKD7J2EIOywqOuLqO2VqFxuICAgIGlmIChtYXRjaGVkQXBpLndlYnNvY2tldE9wdGlvbnMpIHtcbiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZVdlYlNvY2tldFVwZ3JhZGVSZXF1aXJlZEhhbmRsZXIoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jcmVhdGVBcGlIYW5kbGVyKG1hdGNoZWRBcGksIGNvbmZpZyk7XG4gIH1cblxuICBwcml2YXRlIGZpbmRNYXRjaGVkQXBpKHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0KTogRXh0ZW5kZWRBcGkgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHVybCA9IHRoaXMuZ2V0UGF0aG5hbWVGcm9tVXJsKHJlcXVlc3QudXJsKTtcbiAgICBjb25zdCBtZXRob2QgPSByZXF1ZXN0Lm1ldGhvZDtcblxuICAgIGlmICghdXJsLnN0YXJ0c1dpdGgodGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeCkpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3luY2VyLmFwaXMuZmluZCgoYXBpKSA9PiB7XG4gICAgICBpZiAodGhpcy5zeW5jZXIubW9kZWxzW2FwaS5tb2RlbE5hbWVdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgY29uc3QgYXBpTWV0aG9kID0gYXBpLm9wdGlvbnMuaHR0cE1ldGhvZCA/PyBcIkdFVFwiO1xuICAgICAgaWYgKGFwaU1ldGhvZCAhPT0gbWV0aG9kKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIGNvbnN0IGZ1bGxQYXRoID0gdGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeCArIGFwaS5wYXRoO1xuICAgICAgcmV0dXJuIHRoaXMuaXNQYXRoUGF0dGVybk1hdGNoKGZ1bGxQYXRoLCB1cmwpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIGRldiBhcGkg66qo65OcOiBWaXRlIOyXhuydtCBBUEkg64+Z7KCBIOudvOyasO2MheunjCDsoJzqs7Xtlanri4jri6QuXG4gICAqIEhNUuydhCDsnITtlbQgY2F0Y2gtYWxs7JeQ7IScIOunpCDsmpTssq3rp4jri6Qgc3luY2VyLmFwaXPrpbwg7KGw7ZqM7ZWp64uI64ukLlxuICAgKi9cbiAgcHJpdmF0ZSBzZXR1cERldlNlcnZlcihcbiAgICBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZTxTZXJ2ZXIsIEluY29taW5nTWVzc2FnZSwgU2VydmVyUmVzcG9uc2U+LFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgKTogdm9pZCB7XG4gICAgLy8gdXBncmFkZeuKlCDsi6Tsp4jsoIHsnLzroZwgR0VU7JeQ7ISc66eMIOyEseumve2VmOuvgOuhnCBHRVQgKyB3c0hhbmRsZXIg7JmAIOq3uCDsmbggbWV0aG9k66W8IOuzhOuPhCByb3V0ZeuhnCDrtoTrpqztlahcbiAgICBzZXJ2ZXIucm91dGUoe1xuICAgICAgbWV0aG9kOiBcIkdFVFwiLFxuICAgICAgdXJsOiBgJHt0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4fS8qYCxcbiAgICAgIGhhbmRsZXI6IGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICBjb25zdCBoYW5kbGVyID0gdGhpcy5oYW5kbGVEZXZBcGlSZXF1ZXN0KHJlcXVlc3QsIGNvbmZpZyk7XG4gICAgICAgIGlmIChoYW5kbGVyKSB7XG4gICAgICAgICAgcmV0dXJuIGhhbmRsZXIocmVxdWVzdCwgcmVwbHkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIOuTseuhneuQnCBBUEnsmYAg7J287LmY7ZWY7KeAIOyViuuKlCDsmpTssq3sl5Ag64yA7ZWcIGZhbGxiYWNr7J6F64uI64ukLlxuICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oU0QoXCJlcnJvci5hcGkubm90Rm91bmRcIikpO1xuICAgICAgfSxcbiAgICAgIHdzSGFuZGxlcjogYXN5bmMgKGNvbm5lY3Rpb24sIHJlcXVlc3QpID0+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5oYW5kbGVEZXZXZWJTb2NrZXRSZXF1ZXN0KGNvbm5lY3Rpb24uc29ja2V0LCByZXF1ZXN0LCBjb25maWcpO1xuICAgICAgfSxcbiAgICB9KTtcblxuICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICBtZXRob2Q6IFtcIkhFQURcIiwgXCJQT1NUXCIsIFwiUFVUXCIsIFwiREVMRVRFXCIsIFwiUEFUQ0hcIl0sXG4gICAgICB1cmw6IGAke3RoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXh9LypgLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSB0aGlzLmhhbmRsZURldkFwaVJlcXVlc3QocmVxdWVzdCwgY29uZmlnKTtcbiAgICAgICAgaWYgKGhhbmRsZXIpIHtcbiAgICAgICAgICByZXR1cm4gaGFuZGxlcihyZXF1ZXN0LCByZXBseSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKFNEKFwiZXJyb3IuYXBpLm5vdEZvdW5kXCIpKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHZpdGVTZXJ2ZXI6IGFueSA9IG51bGw7XG5cbiAgLyoqXG4gICAqIGRldiBhbGwg66qo65OcOiBWaXRlIERldiBTZXJ2ZXLrpbwg7Ya17ZWp7ZWY7JesIEFQSSArIFNTUiArIENTUuydhCDrqqjrkZAg7KCc6rO17ZWp64uI64ukLlxuICAgKiBBUEkg64+Z7KCBIOunpOy5reydgCBoYW5kbGVEZXZBcGlSZXF1ZXN066W8IOqzteycoO2VqeuLiOuLpC5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc2V0dXBEZXZTZXJ2ZXJXaXRoVml0ZShcbiAgICBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZTxTZXJ2ZXIsIEluY29taW5nTWVzc2FnZSwgU2VydmVyUmVzcG9uc2U+LFxuICAgIHdlYlBhdGg6IHN0cmluZyxcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIEBmYXN0aWZ5L21pZGRpZSDrk7HroZ0gKENvbm5lY3Qtc3R5bGUgbWlkZGxld2FyZSDsp4Dsm5ApXG4gICAgYXdhaXQgc2VydmVyLnJlZ2lzdGVyKChhd2FpdCBpbXBvcnQoXCJAZmFzdGlmeS9taWRkaWVcIikpLmRlZmF1bHQpO1xuXG4gICAgY29uc3Qgdml0ZSA9IGF3YWl0IGltcG9ydChcInZpdGVcIik7XG4gICAgLy8gQGZhc3RpZnkvd2Vic29ja2V0IO2UjOufrOq3uOyduOydtCDtmZzshLHtmZTrkJjrqbQgSE1SIHdlYnNvY2tldOqzvCBzZXJ2ZXIgc29ja2V07J20IOy2qeuPjO2VmOuvgOuhnCBkZWRpY2F0ZWQg7Y+s7Yq466GcIOu2hOumrO2VqFxuICAgIGNvbnN0IHJlcXVpcmVzRGVkaWNhdGVkSG1yU2VydmVyID0gQm9vbGVhbih0aGlzLmNvbmZpZy5zZXJ2ZXIucGx1Z2lucz8ud3MpO1xuICAgIGNvbnN0IGhtciA9IHJlc29sdmVJbnRlZ3JhdGVkVml0ZUhtck9wdGlvbnMoe1xuICAgICAgaHR0cFNlcnZlcjogc2VydmVyLnNlcnZlcixcbiAgICAgIHJlcXVpcmVzRGVkaWNhdGVkV2ViU29ja2V0U2VydmVyOiByZXF1aXJlc0RlZGljYXRlZEhtclNlcnZlcixcbiAgICB9KTtcblxuICAgIHRoaXMudml0ZVNlcnZlciA9IGF3YWl0IHZpdGUuY3JlYXRlU2VydmVyKHtcbiAgICAgIHJvb3Q6IHdlYlBhdGgsXG4gICAgICBzZXJ2ZXI6IHtcbiAgICAgICAgbWlkZGxld2FyZU1vZGU6IHRydWUsXG4gICAgICAgIGhtcixcbiAgICAgIH0sXG4gICAgICBhcHBUeXBlOiBcImN1c3RvbVwiLFxuICAgIH0pO1xuXG4gICAgLy8gVml0ZSBtaWRkbGV3YXJlIOuTseuhnSAoVml0ZSDsl5DshYsg7LKY66asKVxuICAgIHNlcnZlci51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAvLyBBUEnsmYAgU29uYW11IFVJ64qUIEZhc3RpZnkg65287Jqw7Yq46rCAIOyymOumrO2VmOuPhOuhnSBza2lwXG4gICAgICBpZiAocmVxLnVybD8uc3RhcnRzV2l0aCh0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4KSB8fCByZXEudXJsPy5zdGFydHNXaXRoKFwiL3NvbmFtdS11aVwiKSkge1xuICAgICAgICByZXR1cm4gbmV4dCgpO1xuICAgICAgfVxuICAgICAgLy8g64KY66i47KeA64qUIFZpdGUgbWlkZGxld2FyZeuhnCDsoITri6xcbiAgICAgIHJldHVybiB0aGlzLnZpdGVTZXJ2ZXIubWlkZGxld2FyZXMocmVxLCByZXMsIG5leHQpO1xuICAgIH0pO1xuXG4gICAgLy8gV1MgdXBncmFkZSDqsr3roZwoR0VUKeyZgCDsnbzrsJggSFRUUCDrqZTshJzrk5zrpbwg67OE64+EIHJvdXRl66GcIOu2hOumrO2VtCB3ZWJzb2NrZXQgcm91dGXqsIAgSFRNTCBmYWxsYmFja+yXkCDrqLntnojsp4Ag7JWK64+E66GdIO2VqFxuICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICB1cmw6IGAke3RoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXh9LypgLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuaGFuZGxlRGV2QXBpUmVxdWVzdChyZXF1ZXN0LCBjb25maWcpO1xuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdChyZXF1ZXN0LCByZXBseSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKFNEKFwiZXJyb3IuYXBpLm5vdEZvdW5kXCIpKTtcbiAgICAgIH0sXG4gICAgICB3c0hhbmRsZXI6IGFzeW5jIChjb25uZWN0aW9uLCByZXF1ZXN0KSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMuaGFuZGxlRGV2V2ViU29ja2V0UmVxdWVzdChjb25uZWN0aW9uLnNvY2tldCwgcmVxdWVzdCwgY29uZmlnKTtcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBzZXJ2ZXIucm91dGUoe1xuICAgICAgbWV0aG9kOiBbXCJIRUFEXCIsIFwiUE9TVFwiLCBcIlBVVFwiLCBcIkRFTEVURVwiLCBcIlBBVENIXCJdLFxuICAgICAgdXJsOiBgJHt0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4fS8qYCxcbiAgICAgIGhhbmRsZXI6IGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmhhbmRsZURldkFwaVJlcXVlc3QocmVxdWVzdCwgY29uZmlnKTtcbiAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgIHJldHVybiByZXN1bHQocmVxdWVzdCwgcmVwbHkpO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihTRChcImVycm9yLmFwaS5ub3RGb3VuZFwiKSk7XG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gY2F0Y2gtYWxsIOudvOyasO2KuOyXkOyEnCBTU1IvQ1NSIOyymOumrFxuICAgIC8vIOqwnOuwnCDtmZjqsr3sl5DshJzripQg65287Jqw7Yq467OEIGNvbXByZXNzIOyYteyFmOydhCDtj6zquLDtlZjqs6AgSE1SIOydtOygkOydhCDst6jtlanri4jri6QuXG4gICAgc2VydmVyLnJvdXRlKHtcbiAgICAgIG1ldGhvZDogW1wiR0VUXCIsIFwiSEVBRFwiXSxcbiAgICAgIHVybDogXCIvKlwiLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IHVybCA9IHJlcXVlc3QudXJsO1xuXG4gICAgICAgIC8vIDEuIFNTUiDrnbzsmrDtirgg7LKY66asXG4gICAgICAgIGNvbnN0IHsgbWF0Y2hTU1JSb3V0ZSwgcmVuZGVyU1NSIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9zc3JcIik7XG4gICAgICAgIGNvbnN0IHNzck1hdGNoID0gbWF0Y2hTU1JSb3V0ZSh1cmwpO1xuICAgICAgICBpZiAoc3NyTWF0Y2gpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgW1NTUl0gTWF0Y2hlZCByb3V0ZTogJHtzc3JNYXRjaC5yb3V0ZS5wYXRofWApO1xuICAgICAgICAgIGNvbnN0IGh0bWwgPSBhd2FpdCByZW5kZXJTU1IoXG4gICAgICAgICAgICB1cmwsXG4gICAgICAgICAgICBzc3JNYXRjaC5yb3V0ZSxcbiAgICAgICAgICAgIHNzck1hdGNoLnBhcmFtcyxcbiAgICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgICByZXBseSxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIHRoaXMudml0ZVNlcnZlcixcbiAgICAgICAgICApO1xuICAgICAgICAgIHJlcGx5LnR5cGUoXCJ0ZXh0L2h0bWxcIik7XG4gICAgICAgICAgcmV0dXJuIGh0bWw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAyLiBDU1IgZmFsbGJhY2tcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBmcyA9IGF3YWl0IGltcG9ydChcIm5vZGU6ZnMvcHJvbWlzZXNcIik7XG4gICAgICAgICAgbGV0IHRlbXBsYXRlID0gYXdhaXQgZnMucmVhZEZpbGUoXG4gICAgICAgICAgICBwYXRoLmpvaW4odGhpcy52aXRlU2VydmVyLmNvbmZpZy5yb290LCBcImluZGV4Lmh0bWxcIiksXG4gICAgICAgICAgICBcInV0Zi04XCIsXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0ZW1wbGF0ZSA9IGF3YWl0IHRoaXMudml0ZVNlcnZlci50cmFuc2Zvcm1JbmRleEh0bWwodXJsLCB0ZW1wbGF0ZSk7XG5cbiAgICAgICAgICByZXBseS50eXBlKFwidGV4dC9odG1sXCIpO1xuICAgICAgICAgIHJldHVybiB0ZW1wbGF0ZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHRoaXMudml0ZVNlcnZlci5zc3JGaXhTdGFja3RyYWNlKGUgYXMgRXJyb3IpO1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgICAgcmVwbHkuc3RhdHVzKDUwMCk7XG4gICAgICAgICAgcmV0dXJuIChlIGFzIEVycm9yKS5tZXNzYWdlO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8g7ISc67KEIOyiheujjCDsi5wgVml0ZeuPhCDsooXro4xcbiAgICBzZXJ2ZXIuYWRkSG9vayhcIm9uQ2xvc2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgdGhpcy52aXRlU2VydmVyLmNsb3NlKCk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBjaGFsayA9IChhd2FpdCBpbXBvcnQoXCJjaGFsa1wiKSkuZGVmYXVsdDtcbiAgICBpZiAoXCJwb3J0XCIgaW4gaG1yKSB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgY2hhbGsuZGltKFxuICAgICAgICAgIGDinJMgVml0ZSBITVIgdXNpbmcgZGVkaWNhdGVkIHdlYnNvY2tldCBwb3J0ICR7aG1yLnBvcnR9IHRvIGF2b2lkIEZhc3RpZnkgd2Vic29ja2V0IGNvbmZsaWN0c2AsXG4gICAgICAgICksXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhjaGFsay5kaW0oXCLinJMgVml0ZSBkZXYgc2VydmVyIGludGVncmF0ZWRcIikpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzZXR1cFN0YXRpY1dlYlNlcnZlcihcbiAgICBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZTxTZXJ2ZXIsIEluY29taW5nTWVzc2FnZSwgU2VydmVyUmVzcG9uc2U+LFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgICBnbG9iYWxDb21wcmVzc09wdGlvbnM6IENvbXByZXNzT3B0aW9ucyB8IHVuZGVmaW5lZCxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8g6rK966GcIOuqhe2Zle2ZlDogYXBpL3dlYi1kaXN0L2NsaWVudCAo7KCV7KCBIO2MjOydvCksIGFwaS93ZWItZGlzdC9zZXJ2ZXIgKFNTUiBlbnRyeSksIGFwaS9kaXN0L3NzciAoU1NSIHJvdXRlcyAtIEFQSSDshozsnKApXG4gICAgY29uc3Qgd2ViRGlzdFBhdGggPSBwYXRoLmpvaW4odGhpcy5hcGlSb290UGF0aCwgXCJ3ZWItZGlzdFwiLCBcImNsaWVudFwiKTtcbiAgICBjb25zdCBzc3JQYXRoID0gcGF0aC5qb2luKHRoaXMuYXBpUm9vdFBhdGgsIFwid2ViLWRpc3RcIiwgXCJzZXJ2ZXJcIik7XG4gICAgY29uc3Qgc3NyRW50cnlQYXRoID0gcGF0aC5qb2luKHNzclBhdGgsIFwiZW50cnktc2VydmVyLmdlbmVyYXRlZC5qc1wiKTtcbiAgICBjb25zdCBzc3JSb3V0ZXNQYXRoID0gcGF0aC5qb2luKHRoaXMuYXBpUm9vdFBhdGgsIFwiZGlzdFwiLCBcInNzclwiLCBcInJvdXRlcy5qc1wiKTtcblxuICAgIGlmICghKGF3YWl0IGV4aXN0cyh3ZWJEaXN0UGF0aCkpKSB7XG4gICAgICBjb25zb2xlLndhcm4oYOKaoCBXZWIgZGlzdCBub3QgZm91bmQ6ICR7d2ViRGlzdFBhdGh9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gU1NSIGVudHJ5IOyhtOyerCDsl6zrtoAg7ZmV7J24XG4gICAgY29uc3Qgc3NyQXZhaWxhYmxlID0gYXdhaXQgZXhpc3RzKHNzckVudHJ5UGF0aCk7XG5cbiAgICBpZiAoIXNzckF2YWlsYWJsZSkge1xuICAgICAgY29uc29sZS53YXJuKGDimqAgU1NSIGVudHJ5IG5vdCBmb3VuZDogJHtzc3JFbnRyeVBhdGh9YCk7XG4gICAgICBjb25zb2xlLndhcm4oXCIgIFNTUiB3aWxsIGJlIGRpc2FibGVkLiBPbmx5IENTUiB3aWxsIHdvcmsuXCIpO1xuICAgIH1cblxuICAgIC8vIFNTUiDrnbzsmrDtirgg66Gc65OcIChwcm9kdWN0aW9u7JeQ7ISc66eMLCDsgqzsmqnsnpAg7ZSE66Gc7KCd7Yq47J2YIHNzci9yb3V0ZXMudHMpXG4gICAgaWYgKHNzckF2YWlsYWJsZSkge1xuICAgICAgaWYgKGF3YWl0IGV4aXN0cyhzc3JSb3V0ZXNQYXRoKSkge1xuICAgICAgICAvLyB0cy1sb2FkZXLrnbzrqbQgXCJmaWxlOi8vXCLroZwg7Iuc7J6R7ZWY64qUIGZ1bGx5LXJlc29sdmVkIHBhdGjrp4wg67Cb6riw7JeQIOydtOulvCDsspjrpqztlbTso7zripQgaW1wb3J0TWVtYmVyc+ulvCDsgqzsmqntlbTslbwg7ZaI6rKg7KeA66eMLFxuICAgICAgICAvLyDsl6zquLDripQg7ZSE66Gc642V7IWYIO2ZmOqyveyXkOyEnCBsb2FkZXIg7JeG7J20IOuPjOyVhOqwgOq4sCDrlYzrrLjsl5AgXCLsp4Tsp5wganMg7YyM7J28XCLsnZggXCLqt7jrg6VcIiDsoIjrjIDqsr3roZzrpbwg67CU66GcIGltcG9ydO2VtOuPhCDrkKnri4jri6QuXG4gICAgICAgIC8vIOydtCDrgrTsmqnsnYAg7J20IO2VqOyImCDrgrTsl5DshJwg7JWE656Y7JeQIOuCmOyYrCDri6TrpbggaW1wb3J0IO2YuOy2nOyXkOuPhCDrj5nsnbztlZjqsowg7KCB7Jqp65Cp64uI64ukLlxuICAgICAgICBhd2FpdCBpbXBvcnQoc3NyUm91dGVzUGF0aCk7XG4gICAgICAgIGNvbnNvbGUubG9nKFwi4pyTIFNTUiByb3V0ZXMgbG9hZGVkXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS53YXJuKGDimqAgU1NSIHJvdXRlcyBub3QgZm91bmQ6ICR7c3NyUm91dGVzUGF0aH1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyDroaTrp4Eg7JeF642w7J207Yq4IOuMgOydkTogYXNzZXQgaGFzaCDrtojsnbzsuZgg7IucIO2YhOyerCDrsoTsoIQg7KeB7KCRIOyEnOu5mVxuICAgIHNlcnZlci5nZXQoXCIvYXNzZXRzLzpmaWxlbmFtZVwiLCBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgIGNvbnN0IHJlcXVlc3RlZEZpbGUgPSAocmVxdWVzdC5wYXJhbXMgYXMgeyBmaWxlbmFtZTogc3RyaW5nIH0pLmZpbGVuYW1lO1xuICAgICAgY29uc3QgYXNzZXRzRGlyID0gcGF0aC5qb2luKHdlYkRpc3RQYXRoLCBcImFzc2V0c1wiKTtcbiAgICAgIGNvbnN0IHNhZmVGaWxlUGF0aCA9IHRoaXMucmVzb2x2ZVBhdGhXaXRoaW5CYXNlRGlyKGFzc2V0c0RpciwgcmVxdWVzdGVkRmlsZSk7XG4gICAgICBpZiAoc2FmZUZpbGVQYXRoID09PSBudWxsKSB7XG4gICAgICAgIHJlcGx5LnN0YXR1cyg0MDMpLnNlbmQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3Qgbm9ybWFsaXplZFJlcXVlc3RlZEZpbGUgPSBwYXRoLnJlbGF0aXZlKGFzc2V0c0Rpciwgc2FmZUZpbGVQYXRoKS5yZXBsYWNlKC9cXFxcL2csIFwiL1wiKTtcblxuICAgICAgY29uc3QgYXNzZXRQYXRoID0gYC9hc3NldHMvJHtub3JtYWxpemVkUmVxdWVzdGVkRmlsZX1gO1xuXG4gICAgICAvLyBDYWNoZS1Db250cm9sIO2XpOuNlCDqsrDsoJVcbiAgICAgIGNvbnN0IGdldENhY2hlQ29udHJvbEZvckFzc2V0ID0gKCk6IENhY2hlQ29udHJvbENvbmZpZyA9PiB7XG4gICAgICAgIGNvbnN0IGNhY2hlUmVxOiBDYWNoZUNvbnRyb2xSZXF1ZXN0ID0ge1xuICAgICAgICAgIHR5cGU6IFwiYXNzZXRzXCIsXG4gICAgICAgICAgdXJsOiByZXF1ZXN0LnVybCxcbiAgICAgICAgICBwYXRoOiBhc3NldFBhdGgsXG4gICAgICAgICAgbWV0aG9kOiByZXF1ZXN0Lm1ldGhvZCxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyDsgqzsmqnsnpAg7KCV7J2YIO2VuOuTpOufrCDsmrDshKBcbiAgICAgICAgaWYgKGNvbmZpZy5jYWNoZUNvbnRyb2xIYW5kbGVyKSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gY29uZmlnLmNhY2hlQ29udHJvbEhhbmRsZXIoY2FjaGVSZXEpO1xuICAgICAgICAgIGlmIChyZXN1bHQpIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyDquLDrs7jqsJI6IGltbXV0YWJsZVxuICAgICAgICByZXR1cm4gQ2FjaGVQcmVzZXRzLmltbXV0YWJsZTtcbiAgICAgIH07XG5cbiAgICAgIC8vIGluZGV4LSouanMg65iQ64qUIGluZGV4LSouY3NzIOyalOyyreyduCDqsr3smrBcbiAgICAgIGlmICgvXmluZGV4LVthLWYwLTldK1xcLihqc3xjc3MpJC8udGVzdChub3JtYWxpemVkUmVxdWVzdGVkRmlsZSkpIHtcbiAgICAgICAgY29uc3QgZXh0ID0gbm9ybWFsaXplZFJlcXVlc3RlZEZpbGUuc3BsaXQoXCIuXCIpLnBvcCgpO1xuICAgICAgICBjb25zdCBmaWxlcyA9IGF3YWl0IGZzLnJlYWRkaXIoYXNzZXRzRGlyKTtcbiAgICAgICAgY29uc3QgY3VycmVudEZpbGUgPSBmaWxlcy5maW5kKChmKSA9PiBmLnN0YXJ0c1dpdGgoXCJpbmRleC1cIikgJiYgZi5lbmRzV2l0aChgLiR7ZXh0fWApKTtcblxuICAgICAgICBpZiAoY3VycmVudEZpbGUpIHtcbiAgICAgICAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGguam9pbihhc3NldHNEaXIsIGN1cnJlbnRGaWxlKTtcbiAgICAgICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUoZmlsZVBhdGgpO1xuICAgICAgICAgIHJlcGx5LnR5cGUoZXh0ID09PSBcImpzXCIgPyBcImFwcGxpY2F0aW9uL2phdmFzY3JpcHRcIiA6IFwidGV4dC9jc3NcIik7XG4gICAgICAgICAgYXBwbHlDYWNoZUhlYWRlcnMocmVwbHksIGdldENhY2hlQ29udHJvbEZvckFzc2V0KCkpO1xuICAgICAgICAgIHJldHVybiByZXBseS5zZW5kKGNvbnRlbnQpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIOydvOuwmCDtjIzsnbwg7ISc67mZXG4gICAgICBjb25zdCBmaWxlUGF0aCA9IHNhZmVGaWxlUGF0aDtcbiAgICAgIGlmIChhd2FpdCBleGlzdHMoZmlsZVBhdGgpKSB7XG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShmaWxlUGF0aCk7XG4gICAgICAgIGNvbnN0IGV4dCA9IG5vcm1hbGl6ZWRSZXF1ZXN0ZWRGaWxlLnNwbGl0KFwiLlwiKS5wb3AoKTtcbiAgICAgICAgcmVwbHkudHlwZShleHQgPT09IFwianNcIiA/IFwiYXBwbGljYXRpb24vamF2YXNjcmlwdFwiIDogZXh0ID09PSBcImNzc1wiID8gXCJ0ZXh0L2Nzc1wiIDogXCJcIik7XG4gICAgICAgIGlmIChub3JtYWxpemVkUmVxdWVzdGVkRmlsZS5pbmNsdWRlcyhcIi1cIikpIHtcbiAgICAgICAgICBhcHBseUNhY2hlSGVhZGVycyhyZXBseSwgZ2V0Q2FjaGVDb250cm9sRm9yQXNzZXQoKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcGx5LnNlbmQoY29udGVudCk7XG4gICAgICB9XG5cbiAgICAgIHJlcGx5LnN0YXR1cyg0MDQpLnNlbmQoKTtcbiAgICB9KTtcblxuICAgIC8vIFNTUiDrnbzsmrDtirgg6rCc67OEIOuTseuhnSAoY29tcHJlc3Mg7Ji17IWY7J20IOudvOyasO2KuOuzhOuhnCDsoIHsmqnrkJjrj4TroZ0pXG4gICAgaWYgKHNzckF2YWlsYWJsZSkge1xuICAgICAgY29uc3QgeyBnZXRTU1JSb3V0ZXMgfSA9IGF3YWl0IGltcG9ydChcIi4uL3NzclwiKTtcbiAgICAgIGNvbnN0IHsgcmVuZGVyU1NSIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9zc3IvcmVuZGVyZXJcIik7XG4gICAgICBjb25zdCBzc3JSb3V0ZXMgPSBnZXRTU1JSb3V0ZXMoKTtcblxuICAgICAgZm9yIChjb25zdCByb3V0ZSBvZiBzc3JSb3V0ZXMpIHtcbiAgICAgICAgc2VydmVyLnJvdXRlKHtcbiAgICAgICAgICBtZXRob2Q6IFtcIkdFVFwiLCBcIkhFQURcIl0sXG4gICAgICAgICAgdXJsOiByb3V0ZS5wYXRoLFxuICAgICAgICAgIGNvbXByZXNzOiB0b0Zhc3RpZnlDb21wcmVzc09wdGlvbihyb3V0ZS5jb21wcmVzcyA/PyB0cnVlLCBnbG9iYWxDb21wcmVzc09wdGlvbnMpLFxuICAgICAgICAgIGhhbmRsZXI6IGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdXJsID0gcmVxdWVzdC51cmw7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgW1NTUl0gTWF0Y2hlZCByb3V0ZTogJHtyb3V0ZS5wYXRofWApO1xuXG4gICAgICAgICAgICBjb25zdCBwYXJhbXMgPSB0aGlzLmV4dHJhY3RQYXRoUGFyYW1zKHJvdXRlLnBhdGgsIHVybCk7XG4gICAgICAgICAgICBjb25zdCBodG1sID0gYXdhaXQgcmVuZGVyU1NSKHVybCwgcm91dGUsIHBhcmFtcywgcmVxdWVzdCwgcmVwbHksIGNvbmZpZyk7XG5cbiAgICAgICAgICAgIHJlcGx5LnR5cGUoXCJ0ZXh0L2h0bWxcIik7XG4gICAgICAgICAgICByZXR1cm4gaHRtbDtcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDU1Igb3IgU3RhdGljIEZpbGUgRmFsbGJhY2sgKFNTUiDrnbzsmrDtirjsl5Ag66ek7Lmt65CY7KeAIOyViuuKlCDrqqjrk6Ag7JqU7LKtKVxuICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICBtZXRob2Q6IFtcIkdFVFwiLCBcIkhFQURcIl0sXG4gICAgICB1cmw6IFwiKlwiLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIC8vIC9hcGksIC9zb25hbXUtdWnripQgNDA0IOq3uOuMgOuhnFxuICAgICAgICBpZiAocmVxdWVzdC51cmwuc3RhcnRzV2l0aChcIi9hcGlcIikgfHwgcmVxdWVzdC51cmwuc3RhcnRzV2l0aChcIi9zb25hbXUtdWlcIikpIHtcbiAgICAgICAgICByZXBseS5zdGF0dXMoNDA0KS5zZW5kKCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ1NS7JqpIENhY2hlLUNvbnRyb2wg7Zek642UIOyEpOyglVxuICAgICAgICBpZiAoY29uZmlnLmNhY2hlQ29udHJvbEhhbmRsZXIpIHtcbiAgICAgICAgICBjb25zdCBjc3JDYWNoZVJlcTogQ2FjaGVDb250cm9sUmVxdWVzdCA9IHtcbiAgICAgICAgICAgIHR5cGU6IFwiY3NyXCIsXG4gICAgICAgICAgICB1cmw6IHJlcXVlc3QudXJsLFxuICAgICAgICAgICAgcGF0aDogcmVxdWVzdC51cmwuc3BsaXQoXCI/XCIpWzBdLFxuICAgICAgICAgICAgbWV0aG9kOiByZXF1ZXN0Lm1ldGhvZCxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGNvbnN0IGNzckNhY2hlQ29uZmlnID0gY29uZmlnLmNhY2hlQ29udHJvbEhhbmRsZXIoY3NyQ2FjaGVSZXEpO1xuXG4gICAgICAgICAgaWYgKGNzckNhY2hlQ29uZmlnKSB7XG4gICAgICAgICAgICBhcHBseUNhY2hlSGVhZGVycyhyZXBseSwgY3NyQ2FjaGVDb25maWcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIOygleyggSDtjIzsnbzsnbQg7KG07J6s7ZWgIOqyveyasCwg7KCV7KCBIO2MjOydvOydhCDrqLzsoIAg7ISc67mZ7ZW07JW87ZWoXG4gICAgICAgIGNvbnN0IHJlcXVlc3RQYXRoID0gdGhpcy5nZXRQYXRobmFtZUZyb21VcmwocmVxdWVzdC51cmwpO1xuICAgICAgICBjb25zdCBzYWZlRmlsZVBhdGggPSB0aGlzLnJlc29sdmVQYXRoV2l0aGluQmFzZURpcih3ZWJEaXN0UGF0aCwgcmVxdWVzdFBhdGgpO1xuICAgICAgICBpZiAoc2FmZUZpbGVQYXRoID09PSBudWxsKSB7XG4gICAgICAgICAgcmVwbHkuc3RhdHVzKDQwMykuc2VuZCgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYXdhaXQgZmlsZUV4aXN0cyhzYWZlRmlsZVBhdGgpKSB7XG4gICAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKHNhZmVGaWxlUGF0aCk7XG4gICAgICAgICAgcmV0dXJuIHJlcGx5LnR5cGUobWltZUxvb2t1cChzYWZlRmlsZVBhdGgpIHx8IFwiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtXCIpLnNlbmQoY29udGVudCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDU1IgZmFsbGJhY2s6IGluZGV4Lmh0bWwg7ISc67mZXG4gICAgICAgIGNvbnN0IGluZGV4UGF0aCA9IHBhdGguam9pbih3ZWJEaXN0UGF0aCwgXCJpbmRleC5odG1sXCIpO1xuICAgICAgICByZXR1cm4gcmVwbHkudHlwZShcInRleHQvaHRtbFwiKS5zZW5kKGF3YWl0IGZzLnJlYWRGaWxlKGluZGV4UGF0aCwgXCJ1dGYtOFwiKSk7XG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc29sZS5sb2coYOKckyBTdGF0aWMgd2ViIHNlcnZlciBjb25maWd1cmVkIHdpdGggJHtzc3JBdmFpbGFibGUgPyBcIlNTUlwiIDogXCJDU1Igb25seVwifSBzdXBwb3J0YCk7XG4gIH1cblxuICBjcmVhdGVBcGlIYW5kbGVyKFxuICAgIGFwaTogRXh0ZW5kZWRBcGksXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICApOiAocmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsIHJlcGx5OiBGYXN0aWZ5UmVwbHkpID0+IFByb21pc2U8dW5rbm93bj4ge1xuICAgIHJldHVybiBhc3luYyAocmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsIHJlcGx5OiBGYXN0aWZ5UmVwbHkpOiBQcm9taXNlPHVua25vd24+ID0+IHtcbiAgICAgIC8vIENvbnRleHQg7IOd7ISxXG4gICAgICBjb25zdCBjb250ZXh0OiBDb250ZXh0ID0gYXdhaXQgdGhpcy5jcmVhdGVDb250ZXh0KGNvbmZpZywgcmVxdWVzdCwgcmVwbHkpO1xuXG4gICAgICByZXR1cm4gdGhpcy5hc3luY0xvY2FsU3RvcmFnZS5ydW4oeyBjb250ZXh0IH0sIGFzeW5jICgpID0+IHtcbiAgICAgICAgLy8gZ3VhcmRzIOyymOumrFxuICAgICAgICBydW5HdWFyZHMoe1xuICAgICAgICAgIGd1YXJkczogYXBpLm9wdGlvbnMuZ3VhcmRzLFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgIGFwaSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8g7YyM652866+47YSwIOygleuztOuhnCB6b2Qg7Iqk7YKk66eIIOu5jOuTnFxuICAgICAgICBjb25zdCB7IGdldFpvZE9iamVjdEZyb21BcGkgfSA9IGF3YWl0IGltcG9ydChcIi4vY29kZS1jb252ZXJ0ZXJzXCIpO1xuICAgICAgICBjb25zdCBSZXFUeXBlID0gZ2V0Wm9kT2JqZWN0RnJvbUFwaShhcGksIHRoaXMuc3luY2VyLnR5cGVzKTtcblxuICAgICAgICAvLyByZXF1ZXN0IO2MjOyLsVxuICAgICAgICBjb25zdCB3aGljaCA9IGFwaS5vcHRpb25zLmh0dHBNZXRob2QgPT09IFwiR0VUXCIgPyBcInF1ZXJ5XCIgOiBcImJvZHlcIjtcbiAgICAgICAgbGV0IHJlcUJvZHk6IHtcbiAgICAgICAgICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xuICAgICAgICB9O1xuICAgICAgICAvLyDtjIzsnbwg7JeF66Gc65OcIOyeiOuKlCDqsr3smrAg7J6E7IucIOuNsOydtO2EsFxuICAgICAgICBjb25zdCBmaWxlczoge1xuICAgICAgICAgIGJ1ZmZlcmVkRmlsZXM6IEJ1ZmZlcmVkRmlsZVtdO1xuICAgICAgICAgIHVwbG9hZGVkRmlsZXM6IFVwbG9hZGVkRmlsZVtdO1xuICAgICAgICB9ID0ge1xuICAgICAgICAgIGJ1ZmZlcmVkRmlsZXM6IFtdLFxuICAgICAgICAgIHVwbG9hZGVkRmlsZXM6IFtdLFxuICAgICAgICB9O1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgYm9keSA9IChyZXF1ZXN0W3doaWNoXSA/PyB7fSkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICAgICAgaWYgKGFwaS51cGxvYWRPcHRpb25zKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJ0cyA9IHJlcXVlc3QucGFydHMoe1xuICAgICAgICAgICAgICBsaW1pdHM6IGFwaS51cGxvYWRPcHRpb25zLmxpbWl0cyxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBGb3JtRGF0YeydmCBmaWVsZOuTpOydhCDsnoTsi5zroZwg7KCA7J6lXG4gICAgICAgICAgICBjb25zdCBmaWVsZHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICAgICAgICAgICAgaWYgKGFwaS51cGxvYWRPcHRpb25zLmNvbnN1bWUgPT09IFwiYnVmZmVyXCIgfHwgIWFwaS51cGxvYWRPcHRpb25zLmNvbnN1bWUpIHtcbiAgICAgICAgICAgICAgLy8gQnVmZmVyIOuqqOuTnDog66mU66qo66as7JeQIOuhnOuTnFxuICAgICAgICAgICAgICBmb3IgYXdhaXQgKGNvbnN0IHBhcnQgb2YgcGFydHMpIHtcbiAgICAgICAgICAgICAgICBpZiAocGFydC50eXBlID09PSBcImZpbGVcIikge1xuICAgICAgICAgICAgICAgICAgLy8gQ1JJVElDQUw6IO2MjOydvCDsiqTtirjrprzsnYQg7KaJ7IucIGNvbnN1bWXtlbTslbwg64uk7J2MIHBhcnTroZwg64SY7Ja06rCIIOyImCDsnojsnYxcbiAgICAgICAgICAgICAgICAgIC8vIOydtCDtmLjstpzsnbQg7JeG7Jy866m0IOyiheyihSBtdWx0aXBhcnQg7YyM7Iux7J20IHBlbmRpbmcg7IOB7YOc66GcIO2DgOyehOyVhOybgyDrsJzsg51cbiAgICAgICAgICAgICAgICAgIGNvbnN0IGJ1ZmZlciA9IGF3YWl0IHBhcnQudG9CdWZmZXIoKTtcbiAgICAgICAgICAgICAgICAgIGZpbGVzLmJ1ZmZlcmVkRmlsZXMucHVzaChuZXcgQnVmZmVyZWRGaWxlKHBhcnQsIGJ1ZmZlcikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocGFydC50eXBlID09PSBcImZpZWxkXCIpIHtcbiAgICAgICAgICAgICAgICAgIGZpZWxkc1twYXJ0LmZpZWxkbmFtZV0gPSBTdHJpbmcocGFydC52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGFwaS51cGxvYWRPcHRpb25zLmNvbnN1bWUgPT09IFwic3RyZWFtXCIpIHtcbiAgICAgICAgICAgICAgLy8gU3RyZWFtIOuqqOuTnDog7KaJ7IucIOyggOyepeyGjOuhnCDsiqTtirjrpqzrsI1cbiAgICAgICAgICAgICAgY29uc3QgZGlza05hbWUgPSBhcGkudXBsb2FkT3B0aW9ucy5kZXN0aW5hdGlvbjtcbiAgICAgICAgICAgICAgY29uc3QgZGlzayA9IHRoaXMuc3RvcmFnZS51c2UoZGlza05hbWUpO1xuXG4gICAgICAgICAgICAgIC8vIOyasOyEoOyInOychDog642w7L2U66CI7J207YSwID4g7KCE7JetIOyEpOyglSA+IOq4sOuzuOqwklxuICAgICAgICAgICAgICBjb25zdCBrZXlHZW5lcmF0b3I6IEtleUdlbmVyYXRvciA9XG4gICAgICAgICAgICAgICAgYXBpLnVwbG9hZE9wdGlvbnMua2V5R2VuZXJhdG9yID8/XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcuc2VydmVyLnN0b3JhZ2U/LmtleUdlbmVyYXRvciA/P1xuICAgICAgICAgICAgICAgIGRlZmF1bHRLZXlHZW5lcmF0b3I7XG5cbiAgICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBhcnQudHlwZSA9PT0gXCJmaWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGtleSA9IGF3YWl0IGtleUdlbmVyYXRvcih7XG4gICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lOiBwYXJ0LmZpbGVuYW1lLFxuICAgICAgICAgICAgICAgICAgICBtaW1ldHlwZTogcGFydC5taW1ldHlwZSxcbiAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICBhd2FpdCBkaXNrLnB1dFN0cmVhbShrZXksIHBhcnQuZmlsZSwge1xuICAgICAgICAgICAgICAgICAgICBjb250ZW50VHlwZTogcGFydC5taW1ldHlwZSxcbiAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSBhd2FpdCBkaXNrLmdldFVybChrZXkpO1xuICAgICAgICAgICAgICAgICAgY29uc3Qgc2lnbmVkVXJsID0gYXdhaXQgZGlzay5nZXRTaWduZWRVcmwoa2V5KTtcblxuICAgICAgICAgICAgICAgICAgZmlsZXMudXBsb2FkZWRGaWxlcy5wdXNoKFxuICAgICAgICAgICAgICAgICAgICBuZXcgVXBsb2FkZWRGaWxlKHtcbiAgICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZTogcGFydC5maWxlbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBtaW1ldHlwZTogcGFydC5taW1ldHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICBzaXplOiBwYXJ0LmZpbGUuYnl0ZXNSZWFkLFxuICAgICAgICAgICAgICAgICAgICAgIHVybCxcbiAgICAgICAgICAgICAgICAgICAgICBzaWduZWRVcmwsXG4gICAgICAgICAgICAgICAgICAgICAga2V5LFxuICAgICAgICAgICAgICAgICAgICAgIGRpc2tOYW1lLFxuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwYXJ0LnR5cGUgPT09IFwiZmllbGRcIikge1xuICAgICAgICAgICAgICAgICAgZmllbGRzW3BhcnQuZmllbGRuYW1lXSA9IFN0cmluZyhwYXJ0LnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gcXProZwg7KSR7LKpIOq1rOyhsCDtjIzsi7E6IHBhcmFtc1tjYXRlZ29yeV0g4oaSIHsgcGFyYW1zOiB7IGNhdGVnb3J5OiBcInRlc3RcIiB9IH1cbiAgICAgICAgICAgIGNvbnN0IHFzID0gYXdhaXQgaW1wb3J0KFwicXNcIik7XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSBxcy5kZWZhdWx0LnBhcnNlKGZpZWxkcyk7XG4gICAgICAgICAgICBPYmplY3QuYXNzaWduKGJvZHksIHBhcnNlZCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgeyBmYXN0aWZ5Q2FzdGVyIH0gPSBhd2FpdCBpbXBvcnQoXCIuL2Nhc3RlclwiKTtcbiAgICAgICAgICByZXFCb2R5ID0gZmFzdGlmeUNhc3RlcihSZXFUeXBlKS5wYXJzZShib2R5KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGNvbnN0IHsgWm9kRXJyb3IgfSA9IGF3YWl0IGltcG9ydChcInpvZFwiKTtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFpvZEVycm9yKSB7XG4gICAgICAgICAgICBjb25zdCB7IGh1bWFuaXplWm9kRXJyb3IgfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL3pvZC1lcnJvclwiKTtcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gaHVtYW5pemVab2RFcnJvcihlKVxuICAgICAgICAgICAgICAubWFwKChpc3N1ZSkgPT4gaXNzdWUubWVzc2FnZSlcbiAgICAgICAgICAgICAgLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgY29uc3QgeyBCYWRSZXF1ZXN0RXhjZXB0aW9uIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9leGNlcHRpb25zL3NvLWV4Y2VwdGlvbnNcIik7XG4gICAgICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihtZXNzYWdlcyBhcyBMb2NhbGl6ZWRTdHJpbmcsIHtcbiAgICAgICAgICAgICAgem9kRXJyb3I6IGUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb250ZW50LVR5cGVcbiAgICAgICAgcmVwbHkudHlwZShhcGkub3B0aW9ucy5jb250ZW50VHlwZSA/PyBcImFwcGxpY2F0aW9uL2pzb25cIik7XG5cbiAgICAgICAgLy8gQ2FjaGUtQ29udHJvbCDtl6TrjZQg7ISk7KCVXG4gICAgICAgIGNvbnN0IGFwaUNhY2hlQ29uZmlnID0gdGhpcy5nZXRBcGlDYWNoZUNvbnRyb2woYXBpLCByZXF1ZXN0LCBjb25maWcpO1xuICAgICAgICBpZiAoYXBpQ2FjaGVDb25maWcpIHtcbiAgICAgICAgICBhcHBseUNhY2hlSGVhZGVycyhyZXBseSwgYXBpQ2FjaGVDb25maWcpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8g7JeF66Gc65OcIOyYteyFmOydtCDsnojripQg6rK97JqwIO2MjOydvCDrjbDsnbTthLDrpbwgQ29udGV4dOyXkCDstpTqsIBcbiAgICAgICAgaWYgKGFwaS51cGxvYWRPcHRpb25zKSB7XG4gICAgICAgICAgY29uc3QgY29uc3VtZSA9IGFwaS51cGxvYWRPcHRpb25zLmNvbnN1bWUgPz8gXCJidWZmZXJcIjtcbiAgICAgICAgICBpZiAoY29uc3VtZSA9PT0gXCJidWZmZXJcIikge1xuICAgICAgICAgICAgY29udGV4dC5idWZmZXJlZEZpbGVzID0gZmlsZXMuYnVmZmVyZWRGaWxlcztcbiAgICAgICAgICB9IGVsc2UgaWYgKGNvbnN1bWUgPT09IFwic3RyZWFtXCIpIHtcbiAgICAgICAgICAgIGNvbnRleHQudXBsb2FkZWRGaWxlcyA9IGZpbGVzLnVwbG9hZGVkRmlsZXM7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8g66qo6424IOuplOyGjOuTnCBhcmdzIOyDneyEse2VmOyXrCDtmLjstpxcbiAgICAgICAgY29uc3QgeyBBcGlQYXJhbVR5cGUgfSA9IGF3YWl0IGltcG9ydChcIi4uL3R5cGVzL3R5cGVzXCIpO1xuICAgICAgICBjb25zdCBhcmdzID0gYXBpLnBhcmFtZXRlcnMubWFwKChwYXJhbSkgPT4ge1xuICAgICAgICAgIC8vIENvbnRleHQg7J247KCd7IWYXG4gICAgICAgICAgaWYgKEFwaVBhcmFtVHlwZS5pc0NvbnRleHQocGFyYW0udHlwZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBjb250ZXh0O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gcmVxQm9keVtwYXJhbS5uYW1lXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmludm9rZU1vZGVsTWV0aG9kKGFwaSwgYXJncywgcmVwbHkpO1xuICAgICAgfSk7XG4gICAgfTtcbiAgfVxuXG4gIC8vIFdTIHBhdGjrpbwg7J2867CYIEhUVFAgR0VU7Jy866GcIO2YuOy2nO2VnCDqsr3smrAgNDI2ICsgVXBncmFkZSDtl6TrjZTroZwg66qF7Iuc7KCB7Jy866GcIHdlYnNvY2tldCDsoJHsho3snYQg7Jyg64+E7ZWoXG4gIHByaXZhdGUgY3JlYXRlV2ViU29ja2V0VXBncmFkZVJlcXVpcmVkSGFuZGxlcigpIHtcbiAgICByZXR1cm4gYXN5bmMgKF9yZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCwgcmVwbHk6IEZhc3RpZnlSZXBseSk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgcmVwbHkuaGVhZGVyKFwiY29ubmVjdGlvblwiLCBcIlVwZ3JhZGVcIikuaGVhZGVyKFwidXBncmFkZVwiLCBcIndlYnNvY2tldFwiKS5zdGF0dXMoNDI2KS5zZW5kKHtcbiAgICAgICAgbWVzc2FnZTogXCJXZWJTb2NrZXQgdXBncmFkZSByZXF1aXJlZFwiLFxuICAgICAgfSk7XG4gICAgfTtcbiAgfVxuXG4gIC8vIGRldiDrqqjrk5zsnZggY2F0Y2gtYWxsIHdzSGFuZGxlcuyXkOyEnCDsi6TsoJwgV1MgQVBJ66GcIOuUlOyKpO2MqOy5mO2VqC4g66ek7Lmt65CY64qUIHJvdXRl6rCAIOyXhuycvOuptCAxMDA466GcIOuLq+ydjFxuICBwcml2YXRlIGFzeW5jIGhhbmRsZURldldlYlNvY2tldFJlcXVlc3QoXG4gICAgc29ja2V0OiBXZWJTb2NrZXQsXG4gICAgcmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBtYXRjaGVkQXBpID0gdGhpcy5maW5kTWF0Y2hlZEFwaShyZXF1ZXN0KTtcbiAgICBpZiAoIW1hdGNoZWRBcGk/LndlYnNvY2tldE9wdGlvbnMpIHtcbiAgICAgIGNvbnN0IHRyYWNlQ29udGV4dCA9IHRoaXMud2Vic29ja2V0UnVudGltZS50ZWxlbWV0cnlDb250cm9sbGVyLmNyZWF0ZUNvbm5lY3Rpb25Db250ZXh0KHtcbiAgICAgICAgaGVhZGVyczogcmVxdWVzdC5oZWFkZXJzLFxuICAgICAgfSk7XG4gICAgICB0aGlzLndlYnNvY2tldFJ1bnRpbWUudGVsZW1ldHJ5Q29udHJvbGxlci5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5jb25uZWN0aW9uLnJlamVjdGVkXCIsXG4gICAgICAgIGxldmVsOiBcIndhcm5cIixcbiAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgcmVhc29uOiBcInJvdXRlTm90Rm91bmRcIixcbiAgICAgICAgICBwYXRoOiByZXF1ZXN0LnVybCxcbiAgICAgICAgfSxcbiAgICAgICAgdHJhY2VJZDogdHJhY2VDb250ZXh0LnRyYWNlSWQsXG4gICAgICAgIHNwYW5JZDogdHJhY2VDb250ZXh0LnNwYW5JZCxcbiAgICAgICAgcGFyZW50U3BhbklkOiB0cmFjZUNvbnRleHQucGFyZW50U3BhbklkLFxuICAgICAgICBzYW1wbGVkOiB0cmFjZUNvbnRleHQuc2FtcGxlZCxcbiAgICAgIH0pO1xuICAgICAgc29ja2V0LmNsb3NlKDEwMDgsIFwiV2ViU29ja2V0IHJvdXRlIG5vdCBmb3VuZFwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBoYW5kbGVyID0gdGhpcy5jcmVhdGVXZWJTb2NrZXRIYW5kbGVyKG1hdGNoZWRBcGksIGNvbmZpZyk7XG4gICAgYXdhaXQgaGFuZGxlcih7IHNvY2tldCB9LCByZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIFdTIHJvdXRlIO2VuOuTpOufrOydmCDsi6Ttlokg7Iic7ISc66W8IOqzoOygle2VqDpcbiAgLy8gMSkgZ3VhcmTrpbwgY29ubmVjdGlvbiDrk7HroZ0g7J207KCE7JeQIOuPjOugpCDsnbjspp0g7Iuk7YyoIOyLnCDrtoDrtoQg65Ox66GdIOyDge2DnOulvCDrgqjquLDsp4Ag7JWK7J2MXG4gIC8vIDIpIHF1ZXJ5IHBhcmFtIO2MjOyLseuPhCBhY3RpdmF0aW9uIOyghOyXkCDrgZ3rgrQgaGFuZHNoYWtlIOyLpO2MqOqwgCByZWdpc3RyeeyXkCDrhbjstpzrkJjsp4Ag7JWK6rKMIO2VqFxuICAvLyAzKSBgYWN0aXZlOiBmYWxzZWDroZwg66i87KCAIOuTseuhne2VmOqzoCwgY29udGV4dCDspIDruYTqsIAg64Gd64KcIOuSpCBgYWN0aXZhdGUoKWDtlbQg67iM66Gc65Oc7LqQ7Iqk7Yq46rCAIOy0iOq4sO2ZlCDspJHqsIQg7IOB7YOc66W8IOuztOyngCDrqrvtlZjqsowg7ZWoXG4gIC8vIOyXkOufrCDrsJzsg50g7Iuc7JeQ64qUIHJlc29sdmVXZWJTb2NrZXRDbG9zZURlc2NyaXB0b3Ig7KCV7LGF7JeQIOuUsOudvCBjbG9zZSBjb2Rl66W8IOunpO2Vke2VqFxuICBwcml2YXRlIGNyZWF0ZVdlYlNvY2tldEhhbmRsZXIoYXBpOiBFeHRlbmRlZEFwaSwgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnKSB7XG4gICAgcmV0dXJuIGFzeW5jIChcbiAgICAgIGNvbm5lY3Rpb246IHtcbiAgICAgICAgc29ja2V0OiBXZWJTb2NrZXQ7XG4gICAgICB9LFxuICAgICAgcmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsXG4gICAgKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICBjb25zdCBzb2NrZXQgPSBjb25uZWN0aW9uLnNvY2tldDtcbiAgICAgIGxldCB3c0NvbnRleHQ6IFdlYlNvY2tldENvbnRleHQgfCBudWxsID0gbnVsbDtcbiAgICAgIGxldCByYXdXczogUmV0dXJuVHlwZTxXZWJTb2NrZXRSdW50aW1lW1wicmVnaXN0ZXJDb25uZWN0aW9uXCJdPiB8IG51bGwgPSBudWxsO1xuICAgICAgbGV0IHByZVJlZ2lzdGVyUGhhc2U6IFwiZ3VhcmRcIiB8IFwicXVlcnlcIiB8IFwicmVnaXN0ZXJcIiB8IFwiaGFuZGxlclwiID0gXCJndWFyZFwiO1xuICAgICAgbGV0IHRyYWNlQ29udGV4dDogV2ViU29ja2V0VGVsZW1ldHJ5Q29ubmVjdGlvbkNvbnRleHQgPSB7fTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgdHJhY2VDb250ZXh0ID0gdGhpcy53ZWJzb2NrZXRSdW50aW1lLnRlbGVtZXRyeUNvbnRyb2xsZXIuY3JlYXRlQ29ubmVjdGlvbkNvbnRleHQoe1xuICAgICAgICAgIGhlYWRlcnM6IHJlcXVlc3QuaGVhZGVycyxcbiAgICAgICAgfSk7XG4gICAgICAgIHJ1bkd1YXJkcyh7XG4gICAgICAgICAgZ3VhcmRzOiBhcGkub3B0aW9ucy5ndWFyZHMsXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgYXBpLFxuICAgICAgICB9KTtcblxuICAgICAgICBwcmVSZWdpc3RlclBoYXNlID0gXCJxdWVyeVwiO1xuICAgICAgICBjb25zdCByZXFCb2R5ID0gYXdhaXQgdGhpcy5wYXJzZVdlYlNvY2tldFJlcXVlc3RQYXJhbXMoYXBpLCByZXF1ZXN0KTtcbiAgICAgICAgcHJlUmVnaXN0ZXJQaGFzZSA9IFwicmVnaXN0ZXJcIjtcbiAgICAgICAgcmF3V3MgPSB0aGlzLndlYnNvY2tldFJ1bnRpbWUucmVnaXN0ZXJDb25uZWN0aW9uKHNvY2tldCwge1xuICAgICAgICAgIG91dEV2ZW50czogYXBpLndlYnNvY2tldE9wdGlvbnMhLm91dEV2ZW50cyxcbiAgICAgICAgICBpbkV2ZW50czogYXBpLndlYnNvY2tldE9wdGlvbnMhLmluRXZlbnRzLFxuICAgICAgICAgIG5hbWVzcGFjZTogYXBpLndlYnNvY2tldE9wdGlvbnMhLm5hbWVzcGFjZSxcbiAgICAgICAgICBoZWFydGJlYXQ6IGFwaS53ZWJzb2NrZXRPcHRpb25zIS5oZWFydGJlYXQsXG4gICAgICAgICAgYWN0aXZlOiBmYWxzZSxcbiAgICAgICAgICB0cmFjZUlkOiB0cmFjZUNvbnRleHQudHJhY2VJZCxcbiAgICAgICAgICBzcGFuSWQ6IHRyYWNlQ29udGV4dC5zcGFuSWQsXG4gICAgICAgICAgcGFyZW50U3BhbklkOiB0cmFjZUNvbnRleHQucGFyZW50U3BhbklkLFxuICAgICAgICAgIHNhbXBsZWQ6IHRyYWNlQ29udGV4dC5zYW1wbGVkLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBzY29wZWRXcyA9IHRoaXMuY3JlYXRlU2NvcGVkV2ViU29ja2V0Q29ubmVjdGlvbihyYXdXcywgKCkgPT4gd3NDb250ZXh0KTtcbiAgICAgICAgd3NDb250ZXh0ID0gYXdhaXQgdGhpcy5jcmVhdGVXZWJTb2NrZXRDb250ZXh0KGNvbmZpZywgcmVxdWVzdCwgc2NvcGVkV3MpO1xuICAgICAgICB0aGlzLndlYnNvY2tldFJ1bnRpbWUuYWN0aXZhdGVDb25uZWN0aW9uKHJhd1dzLmlkKTtcbiAgICAgICAgcHJlUmVnaXN0ZXJQaGFzZSA9IFwiaGFuZGxlclwiO1xuXG4gICAgICAgIGNvbnN0IHsgQXBpUGFyYW1UeXBlIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi90eXBlcy90eXBlc1wiKTtcbiAgICAgICAgY29uc3QgYXJncyA9IGFwaS5wYXJhbWV0ZXJzLm1hcCgocGFyYW0pID0+IHtcbiAgICAgICAgICBpZiAoQXBpUGFyYW1UeXBlLmlzQ29udGV4dChwYXJhbS50eXBlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHdzQ29udGV4dDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gcmVxQm9keVtwYXJhbS5uYW1lXTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5hc3luY0xvY2FsU3RvcmFnZS5ydW4oeyBjb250ZXh0OiB3c0NvbnRleHQgfSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGF3YWl0IHRoaXMuaW52b2tlTW9kZWxNZXRob2QoYXBpLCBhcmdzKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zdCBjbG9zZURlc2NyaXB0b3IgPSByZXNvbHZlV2ViU29ja2V0Q2xvc2VEZXNjcmlwdG9yKGVycm9yKTtcbiAgICAgICAgaWYgKCFyYXdXcykge1xuICAgICAgICAgIHRoaXMud2Vic29ja2V0UnVudGltZS50ZWxlbWV0cnlDb250cm9sbGVyLmVtaXQoe1xuICAgICAgICAgICAgbmFtZTogXCJ3cy5jb25uZWN0aW9uLnJlamVjdGVkXCIsXG4gICAgICAgICAgICBsZXZlbDogY2xvc2VEZXNjcmlwdG9yLmxvZ0xldmVsID09PSBcIndhcm5cIiA/IFwid2FyblwiIDogXCJlcnJvclwiLFxuICAgICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICAgIHJlYXNvbjogcHJlUmVnaXN0ZXJQaGFzZSxcbiAgICAgICAgICAgICAgY29kZTogY2xvc2VEZXNjcmlwdG9yLmNvZGUsXG4gICAgICAgICAgICAgIHBhdGg6IGFwaS5wYXRoLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRyYWNlSWQ6IHRyYWNlQ29udGV4dC50cmFjZUlkLFxuICAgICAgICAgICAgc3BhbklkOiB0cmFjZUNvbnRleHQuc3BhbklkLFxuICAgICAgICAgICAgcGFyZW50U3BhbklkOiB0cmFjZUNvbnRleHQucGFyZW50U3BhbklkLFxuICAgICAgICAgICAgc2FtcGxlZDogdHJhY2VDb250ZXh0LnNhbXBsZWQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmF3V3MpIHtcbiAgICAgICAgICByYXdXcy5jbG9zZShjbG9zZURlc2NyaXB0b3IuY29kZSwgY2xvc2VEZXNjcmlwdG9yLnJlYXNvbik7XG4gICAgICAgIH0gZWxzZSBpZiAoc29ja2V0LnJlYWR5U3RhdGUgPCAyKSB7XG4gICAgICAgICAgc29ja2V0LmNsb3NlKGNsb3NlRGVzY3JpcHRvci5jb2RlLCBjbG9zZURlc2NyaXB0b3IucmVhc29uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnNlcnZlcj8ubG9nKSB7XG4gICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgIGVycjogZXJyb3IsXG4gICAgICAgICAgICBtb2RlbE5hbWU6IGFwaS5tb2RlbE5hbWUsXG4gICAgICAgICAgICBtZXRob2ROYW1lOiBhcGkubWV0aG9kTmFtZSxcbiAgICAgICAgICAgIHBhdGg6IGFwaS5wYXRoLFxuICAgICAgICAgIH07XG4gICAgICAgICAgaWYgKGNsb3NlRGVzY3JpcHRvci5sb2dMZXZlbCA9PT0gXCJ3YXJuXCIpIHtcbiAgICAgICAgICAgIHRoaXMuc2VydmVyLmxvZy53YXJuKHBheWxvYWQsIGNsb3NlRGVzY3JpcHRvci5yZWFzb24pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNlcnZlci5sb2cuZXJyb3IocGF5bG9hZCwgY2xvc2VEZXNjcmlwdG9yLnJlYXNvbik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChjbG9zZURlc2NyaXB0b3IubG9nTGV2ZWwgPT09IFwid2FyblwiKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oY2xvc2VEZXNjcmlwdG9yLnJlYXNvbiwgZXJyb3IpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGNsb3NlRGVzY3JpcHRvci5yZWFzb24sIGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLy8gb25NZXNzYWdlL29uQ2xvc2Xsspjrn7wg64uk66W4IHRpY2vsl5DshJwg7Iuk7ZaJ65CY64qUIGNhbGxiYWNr7J2AIEFMUyBjb250ZXh06rCAIOuBiuq4sOuvgOuhnCB3cmFwcGVy7JeQ7IScIGBhc3luY0xvY2FsU3RvcmFnZS5ydW5g7Jy866GcIOuLpOyLnCDqsJDsi7gg67O17JuQ7ZWoXG4gIC8vIHB1Ymxpc2gvam9pbi9sZWF2ZS9zZXRVc2VySWQg6rCZ7J2AIOymieyLnCDsi6TtlokgQVBJ64qUIOuLqOyInCDsnITsnoTrp4wg7ZWY6rOgLCBkZWZlcnJlZCBjYWxsYmFja+yXkOunjCBjb250ZXh0IOuzteybkOydhCDsoIHsmqntlahcbiAgcHJpdmF0ZSBjcmVhdGVTY29wZWRXZWJTb2NrZXRDb25uZWN0aW9uPFxuICAgIFRPdXQgZXh0ZW5kcyBXZWJTb2NrZXRFdmVudE1hcCxcbiAgICBUSW4gZXh0ZW5kcyBXZWJTb2NrZXRFdmVudE1hcCxcbiAgPihcbiAgICB3czogV2ViU29ja2V0Q29ubmVjdGlvbjxUT3V0LCBUSW4+LFxuICAgIGdldENvbnRleHQ6ICgpID0+IFdlYlNvY2tldENvbnRleHQgfCBudWxsLFxuICApOiBXZWJTb2NrZXRDb25uZWN0aW9uPFRPdXQsIFRJbj4ge1xuICAgIGNvbnN0IHRlbGVtZXRyeUNvbnRyb2xsZXIgPSB0aGlzLl93ZWJzb2NrZXRSdW50aW1lPy50ZWxlbWV0cnlDb250cm9sbGVyO1xuICAgIGNvbnN0IHJ1bkluQ29udGV4dCA9IDxUPihjYWxsYmFjazogKCkgPT4gVCk6IFQgPT4ge1xuICAgICAgY29uc3QgY29udGV4dCA9IGdldENvbnRleHQoKTtcbiAgICAgIGlmICghY29udGV4dCkge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuYXN5bmNMb2NhbFN0b3JhZ2UucnVuKHsgY29udGV4dCB9LCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICBnZXQgaWQoKSB7XG4gICAgICAgIHJldHVybiB3cy5pZDtcbiAgICAgIH0sXG4gICAgICBnZXQgbmFtZXNwYWNlKCkge1xuICAgICAgICByZXR1cm4gd3MubmFtZXNwYWNlO1xuICAgICAgfSxcbiAgICAgIGdldCBjbG9zZWQoKSB7XG4gICAgICAgIHJldHVybiB3cy5jbG9zZWQ7XG4gICAgICB9LFxuICAgICAgZ2V0IHVzZXJJZCgpIHtcbiAgICAgICAgcmV0dXJuIHdzLnVzZXJJZDtcbiAgICAgIH0sXG4gICAgICB0cmFuc3BvcnQ6IFwid3NcIixcbiAgICAgIHB1Ymxpc2hVbnR5cGVkKGV2ZW50LCBkYXRhKSB7XG4gICAgICAgIHdzLnB1Ymxpc2hVbnR5cGVkKGV2ZW50LCBkYXRhKTtcbiAgICAgIH0sXG4gICAgICBjbG9zZShjb2RlLCByZWFzb24pIHtcbiAgICAgICAgd3MuY2xvc2UoY29kZSwgcmVhc29uKTtcbiAgICAgIH0sXG4gICAgICBvbkNsb3NlKGNhbGxiYWNrKSB7XG4gICAgICAgIHdzLm9uQ2xvc2UoKCkgPT4gcnVuSW5Db250ZXh0KGNhbGxiYWNrKSk7XG4gICAgICB9LFxuICAgICAgb25NZXNzYWdlKGV2ZW50LCBoYW5kbGVyKSB7XG4gICAgICAgIHdzLm9uTWVzc2FnZShldmVudCwgKGRhdGEsIG1lc3NhZ2VUcmFjZUNvbnRleHQpID0+XG4gICAgICAgICAgcnVuSW5Db250ZXh0KGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50TmFtZSA9IFN0cmluZyhldmVudCk7XG4gICAgICAgICAgICBjb25zdCB0cmFjZUNvbnRleHQgPSBtZXNzYWdlVHJhY2VDb250ZXh0ID8/IGdldFdlYlNvY2tldFRlbGVtZXRyeUNvbnRleHQod3MpO1xuICAgICAgICAgICAgY29uc3Qgc3RhcnRlZEF0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG5cbiAgICAgICAgICAgIHRlbGVtZXRyeUNvbnRyb2xsZXI/LmVtaXQoe1xuICAgICAgICAgICAgICBuYW1lOiBcIndzLmhhbmRsZXIuc3RhcnRlZFwiLFxuICAgICAgICAgICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgICAgICAgICBjb25uZWN0aW9uSWQ6IHdzLmlkLFxuICAgICAgICAgICAgICBuYW1lc3BhY2U6IHdzLm5hbWVzcGFjZSxcbiAgICAgICAgICAgICAgdXNlcklkOiB3cy51c2VySWQsXG4gICAgICAgICAgICAgIGRldGFpbDogeyBldmVudDogZXZlbnROYW1lIH0sXG4gICAgICAgICAgICAgIC4uLnRyYWNlQ29udGV4dCxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBoYW5kbGVyKGRhdGEsIG1lc3NhZ2VUcmFjZUNvbnRleHQpO1xuICAgICAgICAgICAgICBjb25zdCBkdXJhdGlvbk1zID0gcGVyZm9ybWFuY2Uubm93KCkgLSBzdGFydGVkQXQ7XG4gICAgICAgICAgICAgIHRlbGVtZXRyeUNvbnRyb2xsZXI/LmVtaXQoe1xuICAgICAgICAgICAgICAgIG5hbWU6IFwid3MuaGFuZGxlci5jb21wbGV0ZWRcIixcbiAgICAgICAgICAgICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25JZDogd3MuaWQsXG4gICAgICAgICAgICAgICAgbmFtZXNwYWNlOiB3cy5uYW1lc3BhY2UsXG4gICAgICAgICAgICAgICAgdXNlcklkOiB3cy51c2VySWQsXG4gICAgICAgICAgICAgICAgZGV0YWlsOiB7IGV2ZW50OiBldmVudE5hbWUgfSxcbiAgICAgICAgICAgICAgICAuLi50cmFjZUNvbnRleHQsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB0ZWxlbWV0cnlDb250cm9sbGVyPy5yZWNvcmRTcGFuKHtcbiAgICAgICAgICAgICAgICBvcGVyYXRpb25OYW1lOiBcIndzLm1lc3NhZ2UucHJvY2Vzc1wiLFxuICAgICAgICAgICAgICAgIGtpbmQ6IFwiaW50ZXJuYWxcIixcbiAgICAgICAgICAgICAgICBkdXJhdGlvbk1zLFxuICAgICAgICAgICAgICAgIHN0YXR1czogXCJ1bnNldFwiLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25JZDogd3MuaWQsXG4gICAgICAgICAgICAgICAgbmFtZXNwYWNlOiB3cy5uYW1lc3BhY2UsXG4gICAgICAgICAgICAgICAgdXNlcklkOiB3cy51c2VySWQsXG4gICAgICAgICAgICAgICAgYXR0cmlidXRlczogeyBldmVudDogZXZlbnROYW1lIH0sXG4gICAgICAgICAgICAgICAgLi4udHJhY2VDb250ZXh0LFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGR1cmF0aW9uTXMgPSBwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0ZWRBdDtcbiAgICAgICAgICAgICAgdGVsZW1ldHJ5Q29udHJvbGxlcj8uZW1pdCh7XG4gICAgICAgICAgICAgICAgbmFtZTogXCJ3cy5oYW5kbGVyLmZhaWxlZFwiLFxuICAgICAgICAgICAgICAgIGxldmVsOiBcImVycm9yXCIsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbklkOiB3cy5pZCxcbiAgICAgICAgICAgICAgICBuYW1lc3BhY2U6IHdzLm5hbWVzcGFjZSxcbiAgICAgICAgICAgICAgICB1c2VySWQ6IHdzLnVzZXJJZCxcbiAgICAgICAgICAgICAgICBkZXRhaWw6IHsgZXZlbnQ6IGV2ZW50TmFtZSB9LFxuICAgICAgICAgICAgICAgIC4uLnRyYWNlQ29udGV4dCxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHRlbGVtZXRyeUNvbnRyb2xsZXI/LnJlY29yZFNwYW4oe1xuICAgICAgICAgICAgICAgIG9wZXJhdGlvbk5hbWU6IFwid3MubWVzc2FnZS5wcm9jZXNzXCIsXG4gICAgICAgICAgICAgICAga2luZDogXCJpbnRlcm5hbFwiLFxuICAgICAgICAgICAgICAgIGR1cmF0aW9uTXMsXG4gICAgICAgICAgICAgICAgc3RhdHVzOiBcImVycm9yXCIsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbklkOiB3cy5pZCxcbiAgICAgICAgICAgICAgICBuYW1lc3BhY2U6IHdzLm5hbWVzcGFjZSxcbiAgICAgICAgICAgICAgICB1c2VySWQ6IHdzLnVzZXJJZCxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiB7IGV2ZW50OiBldmVudE5hbWUgfSxcbiAgICAgICAgICAgICAgICBlcnJvclR5cGU6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5uYW1lIDogdHlwZW9mIGVycm9yLFxuICAgICAgICAgICAgICAgIC4uLnRyYWNlQ29udGV4dCxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgfSxcbiAgICAgIHB1Ymxpc2goZXZlbnQsIGRhdGEpIHtcbiAgICAgICAgd3MucHVibGlzaChldmVudCwgZGF0YSk7XG4gICAgICB9LFxuICAgICAgd2FpdEZvckNsb3NlKCkge1xuICAgICAgICByZXR1cm4gd3Mud2FpdEZvckNsb3NlKCk7XG4gICAgICB9LFxuICAgICAgam9pbihyb29tSWQpIHtcbiAgICAgICAgd3Muam9pbihyb29tSWQpO1xuICAgICAgfSxcbiAgICAgIGxlYXZlKHJvb21JZCkge1xuICAgICAgICB3cy5sZWF2ZShyb29tSWQpO1xuICAgICAgfSxcbiAgICAgIHNldFVzZXJJZCh1c2VySWQpIHtcbiAgICAgICAgd3Muc2V0VXNlcklkKHVzZXJJZCk7XG4gICAgICB9LFxuICAgICAgY2xlYXJVc2VySWQoKSB7XG4gICAgICAgIHdzLmNsZWFyVXNlcklkKCk7XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHBhcnNlV2ViU29ja2V0UmVxdWVzdFBhcmFtcyhcbiAgICBhcGk6IEV4dGVuZGVkQXBpLFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gICAgY29uc3QgeyBnZXRab2RPYmplY3RGcm9tQXBpIH0gPSBhd2FpdCBpbXBvcnQoXCIuL2NvZGUtY29udmVydGVyc1wiKTtcbiAgICBjb25zdCBSZXFUeXBlID0gZ2V0Wm9kT2JqZWN0RnJvbUFwaShhcGksIHRoaXMuc3luY2VyLnR5cGVzKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IGZhc3RpZnlDYXN0ZXIgfSA9IGF3YWl0IGltcG9ydChcIi4vY2FzdGVyXCIpO1xuICAgICAgcmV0dXJuIGZhc3RpZnlDYXN0ZXIoUmVxVHlwZSkucGFyc2UoKHJlcXVlc3QucXVlcnkgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zdCB7IFpvZEVycm9yIH0gPSBhd2FpdCBpbXBvcnQoXCJ6b2RcIik7XG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIFpvZEVycm9yKSB7XG4gICAgICAgIGNvbnN0IHsgaHVtYW5pemVab2RFcnJvciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvem9kLWVycm9yXCIpO1xuICAgICAgICBjb25zdCBtZXNzYWdlcyA9IGh1bWFuaXplWm9kRXJyb3IoZSlcbiAgICAgICAgICAubWFwKChpc3N1ZSkgPT4gaXNzdWUubWVzc2FnZSlcbiAgICAgICAgICAuam9pbihcIiBcIik7XG4gICAgICAgIGNvbnN0IHsgQmFkUmVxdWVzdEV4Y2VwdGlvbiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZXhjZXB0aW9ucy9zby1leGNlcHRpb25zXCIpO1xuICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihtZXNzYWdlcyBhcyBMb2NhbGl6ZWRTdHJpbmcsIHtcbiAgICAgICAgICB6b2RFcnJvcjogZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFVSTOyXkOyEnCBwYXRoIHBhcmFtc+ulvCDstpTstpztlanri4jri6QuXG4gICAqIOyYiDogcGF0dGVybj1cIi9hZG1pbi9jb21wYW5pZXMvOmNvbXBhbnlJZFwiLCB1cmw9XCIvYWRtaW4vY29tcGFuaWVzLzEyM1wiIOKGkiB7IGNvbXBhbnlJZDogXCIxMjNcIiB9XG4gICAqL1xuICBwcml2YXRlIGV4dHJhY3RQYXRoUGFyYW1zKHBhdHRlcm46IHN0cmluZywgdXJsOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICBjb25zdCBwYXR0ZXJuUGFydHMgPSBwYXR0ZXJuLnNwbGl0KFwiL1wiKS5maWx0ZXIoQm9vbGVhbik7XG4gICAgY29uc3QgdXJsUGFydHMgPSB0aGlzLmdldFBhdGhuYW1lRnJvbVVybCh1cmwpLnNwbGl0KFwiL1wiKS5maWx0ZXIoQm9vbGVhbik7XG4gICAgY29uc3QgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm5QYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHBhdHRlcm5QYXJ0c1tpXS5zdGFydHNXaXRoKFwiOlwiKSkge1xuICAgICAgICBwYXJhbXNbcGF0dGVyblBhcnRzW2ldLnNsaWNlKDEpXSA9IHVybFBhcnRzW2ldO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcGFyYW1zO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1BhdGhQYXR0ZXJuTWF0Y2gocGF0dGVybjogc3RyaW5nLCB1cmw6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHBhdHRlcm5QYXJ0cyA9IHBhdHRlcm4uc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcbiAgICBjb25zdCB1cmxQYXJ0cyA9IHRoaXMuZ2V0UGF0aG5hbWVGcm9tVXJsKHVybCkuc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcblxuICAgIGlmIChwYXR0ZXJuUGFydHMubGVuZ3RoICE9PSB1cmxQYXJ0cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm5QYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgcGF0dGVyblBhcnQgPSBwYXR0ZXJuUGFydHNbaV07XG4gICAgICBjb25zdCB1cmxQYXJ0ID0gdXJsUGFydHNbaV07XG4gICAgICBpZiAocGF0dGVyblBhcnQuc3RhcnRzV2l0aChcIjpcIikpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAocGF0dGVyblBhcnQgIT09IHVybFBhcnQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQYXRobmFtZUZyb21VcmwodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB1cmwuc3BsaXQoXCI/XCIpWzBdO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlUGF0aFdpdGhpbkJhc2VEaXIoYmFzZURpcjogc3RyaW5nLCBpbnB1dFBhdGg6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZWNvZGVkID0gZGVjb2RlVVJJQ29tcG9uZW50KGlucHV0UGF0aCkucmVwbGFjZSgvXFxcXC9nLCBcIi9cIik7XG4gICAgICBpZiAoZGVjb2RlZC5pbmNsdWRlcyhcIlxcMFwiKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IGRlY29kZWQucmVwbGFjZSgvXlxcLysvLCBcIlwiKTtcbiAgICAgIGNvbnN0IHJlc29sdmVkUGF0aCA9IHBhdGgucmVzb2x2ZShiYXNlRGlyLCByZWxhdGl2ZVBhdGgpO1xuICAgICAgY29uc3QgcmVsYXRpdmVGcm9tQmFzZSA9IHBhdGgucmVsYXRpdmUoYmFzZURpciwgcmVzb2x2ZWRQYXRoKTtcbiAgICAgIGlmIChyZWxhdGl2ZUZyb21CYXNlLnN0YXJ0c1dpdGgoXCIuLlwiKSB8fCBwYXRoLmlzQWJzb2x1dGUocmVsYXRpdmVGcm9tQmFzZSkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzb2x2ZWRQYXRoO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFQSSDsnZHri7Xsl5Ag7KCB7Jqp7ZWgIENhY2hlLUNvbnRyb2wg7ISk7KCV7J2EIOqysOygle2VqeuLiOuLpC5cbiAgICog7Jqw7ISg7Iic7JyEOiDqsJzrs4Qg7KeA7KCVID4gY2FjaGVDb250cm9sSGFuZGxlclxuICAgKi9cbiAgcHJpdmF0ZSBnZXRBcGlDYWNoZUNvbnRyb2woXG4gICAgYXBpOiBFeHRlbmRlZEFwaSxcbiAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICkge1xuICAgIC8vIOuNsOy9lOugiOydtO2EsCDshKTsoJUg7Jqw7ISgXG4gICAgaWYgKGFwaS5vcHRpb25zLmNhY2hlQ29udHJvbCkge1xuICAgICAgcmV0dXJuIGFwaS5vcHRpb25zLmNhY2hlQ29udHJvbDtcbiAgICB9XG5cbiAgICAvLyDsoITsl60g7ZW465Ok65+sXG4gICAgaWYgKGNvbmZpZy5jYWNoZUNvbnRyb2xIYW5kbGVyKSB7XG4gICAgICBjb25zdCBjYWNoZVJlcTogQ2FjaGVDb250cm9sUmVxdWVzdCA9IHtcbiAgICAgICAgdHlwZTogXCJhcGlcIixcbiAgICAgICAgdXJsOiByZXF1ZXN0LnVybCxcbiAgICAgICAgcGF0aDogcmVxdWVzdC5yb3V0ZU9wdGlvbnM/LnVybCA/PyByZXF1ZXN0LnVybC5zcGxpdChcIj9cIilbMF0sXG4gICAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICAgIGFwaSxcbiAgICAgIH07XG4gICAgICBjb25zdCByZXN1bHQgPSBjb25maWcuY2FjaGVDb250cm9sSGFuZGxlcihjYWNoZVJlcSk7XG4gICAgICBpZiAocmVzdWx0KSByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFNTUuyaqSBBUEkg7Zi47LacIChIVFRQIOyYpOuyhO2XpOuTnCDsl4bsnbQg7KeB7KCRIO2YuOy2nClcbiAgICogY3JlYXRlQXBpSGFuZGxlcuydmCDroZzsp4HsnYQg7J6s7IKs7Jqp7ZWY65CYLCByZXF1ZXN0IO2MjOyLsSDrjIDsi6AgcGFyYW1zIOyngeygkSDsgqzsmqlcbiAgICovXG4gIGFzeW5jIGludm9rZUFwaUZvclNTUihcbiAgICBhcGk6IEV4dGVuZGVkQXBpLFxuICAgIHBhcmFtczogYW55W10sXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgIHJlcGx5OiBGYXN0aWZ5UmVwbHksXG4gICk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgIC8vIENvbnRleHQg7IOd7ISxICjquLDsobQg66mU7IaM65OcIOyerOyCrOyaqSlcbiAgICBjb25zdCBjb250ZXh0ID0gYXdhaXQgdGhpcy5jcmVhdGVDb250ZXh0KGNvbmZpZywgcmVxdWVzdCwgcmVwbHkpO1xuXG4gICAgcmV0dXJuIHRoaXMuYXN5bmNMb2NhbFN0b3JhZ2UucnVuKHsgY29udGV4dCB9LCBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBhcmdzIOyDneyEsTogQ29udGV4dCDtjIzrnbzrr7jthLDripQg7KO87J6FLCDrgpjrqLjsp4DripQgcGFyYW1z7JeQ7IScIOqwgOyguOyYpOq4sFxuICAgICAgY29uc3QgeyBBcGlQYXJhbVR5cGUgfSA9IGF3YWl0IGltcG9ydChcIi4uL3R5cGVzL3R5cGVzXCIpO1xuICAgICAgbGV0IHBhcmFtc0luZGV4ID0gMDtcbiAgICAgIGNvbnN0IGFyZ3MgPSBhcGkucGFyYW1ldGVycy5tYXAoKHBhcmFtKSA9PiB7XG4gICAgICAgIGlmIChBcGlQYXJhbVR5cGUuaXNDb250ZXh0KHBhcmFtLnR5cGUpKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBhcmFtc1twYXJhbXNJbmRleCsrXTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyDrqqjrjbgg66mU7ISc65OcIO2YuOy2nCAo6riw7KG0IOuplOyEnOuTnCDsnqzsgqzsmqkpXG4gICAgICByZXR1cm4gdGhpcy5pbnZva2VNb2RlbE1ldGhvZChhcGksIGFyZ3MsIHJlcGx5KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFdTIOqyveuhnOyXkOyEnOuKlCBIVFRQIHJlcGx56rCAIOyXhuycvOuvgOuhnCByZXBseeulvCBvcHRpb25hbOuhnCDrsJvslYQg6rO17Ya1IO2YuOy2nCDqsr3roZzrpbwg7Jyg7KeA7ZWoXG4gIGFzeW5jIGludm9rZU1vZGVsTWV0aG9kKFxuICAgIGFwaTogRXh0ZW5kZWRBcGksXG4gICAgYXJnczogdW5rbm93bltdLFxuICAgIHJlcGx5PzogRmFzdGlmeVJlcGx5LFxuICApOiBQcm9taXNlPHVua25vd24+IHtcbiAgICBjb25zdCBtb2RlbCA9IHRoaXMuc3luY2VyLm1vZGVsc1thcGkubW9kZWxOYW1lXTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCAobW9kZWwgYXMgYW55KVthcGkubWV0aG9kTmFtZV0uYXBwbHkobW9kZWwsIGFyZ3MpO1xuICAgIHJlcGx5Py50eXBlKGFwaS5vcHRpb25zLmNvbnRlbnRUeXBlID8/IFwiYXBwbGljYXRpb24vanNvblwiKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBhc3luYyBjcmVhdGVDb250ZXh0KFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICByZXBseTogRmFzdGlmeVJlcGx5LFxuICApOiBQcm9taXNlPENvbnRleHQ+IHtcbiAgICAvLyBjcmVhdGVTU0VGYWN0b3J5IO2VqOyImOyXkCDrr7jrpqwgcmVxdWVzdOydmCBzb2NrZXTqs7wgcmVwbHnrpbwg67CU7J2465SpLlxuICAgIGNvbnN0IHsgY3JlYXRlU1NFRmFjdG9yeSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3RyZWFtL3NzZVwiKTtcbiAgICBjb25zdCBjcmVhdGVTU0UgPSAoPFQgZXh0ZW5kcyBab2RPYmplY3Q+KFxuICAgICAgX3JlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgICAgX3JlcGx5OiBGYXN0aWZ5UmVwbHksXG4gICAgICBfZXZlbnRzOiBULFxuICAgICkgPT4gY3JlYXRlU1NFRmFjdG9yeShfcmVxdWVzdC5zb2NrZXQsIF9yZXBseSwgX2V2ZW50cykpLmJpbmQobnVsbCwgcmVxdWVzdCwgcmVwbHkpO1xuXG4gICAgLy8gbG9jYWxlIOqwkOyngFxuICAgIGNvbnN0IGxvY2FsZSA9XG4gICAgICB0aGlzLmRldGVjdExvY2FsZShyZXF1ZXN0LmhlYWRlcnNbXCJhY2NlcHQtbGFuZ3VhZ2VcIl0sIHRoaXMuY29uZmlnLmkxOG4uc3VwcG9ydGVkTG9jYWxlcykgPz9cbiAgICAgIHRoaXMuY29uZmlnLmkxOG4uZGVmYXVsdExvY2FsZTtcblxuICAgIC8vIGF1dGggY29udGV4dCDstpTqsIBcbiAgICBjb25zdCBoZWFkZXJzID0gY29udmVydEZhc3RpZnlIZWFkZXJzVG9TdGFuZGFyZChyZXF1ZXN0LmhlYWRlcnMpO1xuICAgIGNvbnN0IHNlc3Npb24gPSAoYXdhaXQgdGhpcy5fYXV0aD8uYXBpLmdldFNlc3Npb24oeyBoZWFkZXJzIH0pKSA/PyBudWxsO1xuXG4gICAgY29uc3QgY29udGV4dDogQ29udGV4dCA9IGF3YWl0IFByb21pc2UucmVzb2x2ZShcbiAgICAgIGNvbmZpZy5jb250ZXh0UHJvdmlkZXIoXG4gICAgICAgIHtcbiAgICAgICAgICB0cmFuc3BvcnQ6IFwiaHR0cFwiLFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgcmVwbHksXG4gICAgICAgICAgaGVhZGVyczogcmVxdWVzdC5oZWFkZXJzLFxuICAgICAgICAgIGNyZWF0ZVNTRSxcbiAgICAgICAgICBuYWl0ZVN0b3JlOiBuZXcgTWFwKCksXG4gICAgICAgICAgbG9jYWxlLFxuICAgICAgICAgIC8vIGF1dGhcbiAgICAgICAgICB1c2VyOiBzZXNzaW9uPy51c2VyID8/IG51bGwsXG4gICAgICAgICAgc2Vzc2lvbjogc2Vzc2lvbj8uc2Vzc2lvbiA/PyBudWxsLFxuICAgICAgICB9LFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICByZXBseSxcbiAgICAgICksXG4gICAgKTtcbiAgICByZXR1cm4gY29udGV4dDtcbiAgfVxuXG4gIC8vIHNlc3Npb24vbG9jYWxlL3N0b3JlIOqwmeydgCDqs7XthrUgc3RhdGXripQgSFRUUCBjb250ZXh07JmAIOqzteycoO2VmOuQmCwgcmVwbHkvY3JlYXRlU1NFIOqwmeydgCBIVFRQIOyghOyaqSBoZWxwZXLripQg64W47Lac7ZWY7KeAIOyViuydjFxuICAvLyDsgqzsmqnsnpDqsIAgd2Vic29ja2V0Q29udGV4dFByb3ZpZGVy66W8IOyjvOuptCDqt7jrjIDroZwg7JyE7J6E7ZWY6rOgLCDsl4bsnLzrqbQg6riw7KG0IGNvbnRleHRQcm92aWRlcuulvCByZXBseS9TU0Ugc3R1YuqzvCDtlajqu5gg7J6s7Zmc7Jqp7ZWoXG4gIGFzeW5jIGNyZWF0ZVdlYlNvY2tldENvbnRleHQoXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgIHdzOiBXZWJTb2NrZXRDb250ZXh0W1wid3NcIl0sXG4gICk6IFByb21pc2U8V2ViU29ja2V0Q29udGV4dD4ge1xuICAgIGNvbnN0IGxvY2FsZSA9XG4gICAgICB0aGlzLmRldGVjdExvY2FsZShyZXF1ZXN0LmhlYWRlcnNbXCJhY2NlcHQtbGFuZ3VhZ2VcIl0sIHRoaXMuY29uZmlnLmkxOG4uc3VwcG9ydGVkTG9jYWxlcykgPz9cbiAgICAgIHRoaXMuY29uZmlnLmkxOG4uZGVmYXVsdExvY2FsZTtcblxuICAgIGNvbnN0IGhlYWRlcnMgPSBjb252ZXJ0RmFzdGlmeUhlYWRlcnNUb1N0YW5kYXJkKHJlcXVlc3QuaGVhZGVycyk7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IChhd2FpdCB0aGlzLl9hdXRoPy5hcGkuZ2V0U2Vzc2lvbih7IGhlYWRlcnMgfSkpID8/IG51bGw7XG5cbiAgICBjb25zdCBkZWZhdWx0Q29udGV4dCA9IHtcbiAgICAgIHRyYW5zcG9ydDogXCJ3c1wiIGFzIGNvbnN0LFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGhlYWRlcnM6IHJlcXVlc3QuaGVhZGVycyxcbiAgICAgIHdzLFxuICAgICAgbmFpdGVTdG9yZTogbmV3IE1hcCgpLFxuICAgICAgbG9jYWxlLFxuICAgICAgdXNlcjogc2Vzc2lvbj8udXNlciA/PyBudWxsLFxuICAgICAgc2Vzc2lvbjogc2Vzc2lvbj8uc2Vzc2lvbiA/PyBudWxsLFxuICAgIH07XG5cbiAgICBpZiAoY29uZmlnLndlYnNvY2tldENvbnRleHRQcm92aWRlcikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uKGF3YWl0IFByb21pc2UucmVzb2x2ZShjb25maWcud2Vic29ja2V0Q29udGV4dFByb3ZpZGVyKGRlZmF1bHRDb250ZXh0LCByZXF1ZXN0KSkpLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyByZXBseS9jcmVhdGVTU0Xsl5Ag7J2Y7KG07ZWY64qUIGNvbnRleHRQcm92aWRlcuqwgCDsnojsnLzrqbQg7KaJ7IucIOyXkOufrOulvCDrjZjsoLggdHJhbnNwb3J0IG1pc3VzZeulvCDruajrpqwg65Oc65+s64OEXG4gICAgY29uc3QgcmVwbHlTdHViID0gY3JlYXRlV2ViU29ja2V0UmVwbHlTdHViKCk7XG4gICAgY29uc3QgY3JlYXRlU1NFID0gPFQgZXh0ZW5kcyBab2RPYmplY3Q+KF9ldmVudHM6IFQpID0+IHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJjcmVhdGVTU0UgaXMgbm90IGF2YWlsYWJsZSBpbiB3ZWJzb2NrZXQgY29udGV4dC4gRGVmaW5lIHdlYnNvY2tldENvbnRleHRQcm92aWRlciBpZiB5b3VyIGNvbnRleHQgc2V0dXAgZGVwZW5kcyBvbiBTU0UgaGVscGVycy5cIixcbiAgICAgICk7XG4gICAgfTtcbiAgICBjb25zdCBodHRwTGlrZUNvbnRleHQgPSBhd2FpdCBQcm9taXNlLnJlc29sdmUoXG4gICAgICBjb25maWcuY29udGV4dFByb3ZpZGVyKFxuICAgICAgICB7XG4gICAgICAgICAgdHJhbnNwb3J0OiBcImh0dHBcIixcbiAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgIHJlcGx5OiByZXBseVN0dWIsXG4gICAgICAgICAgaGVhZGVyczogcmVxdWVzdC5oZWFkZXJzLFxuICAgICAgICAgIGNyZWF0ZVNTRSxcbiAgICAgICAgICBuYWl0ZVN0b3JlOiBkZWZhdWx0Q29udGV4dC5uYWl0ZVN0b3JlLFxuICAgICAgICAgIGxvY2FsZSxcbiAgICAgICAgICB1c2VyOiBkZWZhdWx0Q29udGV4dC51c2VyLFxuICAgICAgICAgIHNlc3Npb246IGRlZmF1bHRDb250ZXh0LnNlc3Npb24sXG4gICAgICAgIH0sXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHJlcGx5U3R1YixcbiAgICAgICksXG4gICAgKTtcblxuICAgIGNvbnN0IHtcbiAgICAgIHRyYW5zcG9ydDogX3RyYW5zcG9ydCxcbiAgICAgIHJlcGx5OiBfcmVwbHksXG4gICAgICBjcmVhdGVTU0U6IF9jcmVhdGVTU0UsXG4gICAgICBidWZmZXJlZEZpbGVzOiBfYnVmZmVyZWRGaWxlcyxcbiAgICAgIHVwbG9hZGVkRmlsZXM6IF91cGxvYWRlZEZpbGVzLFxuICAgICAgLi4ucmVzdFxuICAgIH0gPSBodHRwTGlrZUNvbnRleHQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ucmVzdCxcbiAgICAgIHRyYW5zcG9ydDogXCJ3c1wiLFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGhlYWRlcnM6IHJlcXVlc3QuaGVhZGVycyxcbiAgICAgIHdzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQWNjZXB0LUxhbmd1YWdlIO2XpOuNlOyXkOyEnCDsp4Dsm5DtlZjripQgbG9jYWxl7J2EIOywvuyKteuLiOuLpC5cbiAgICogQGV4YW1wbGUgXCJrby1LUixrbztxPTAuOSxlbjtxPTAuOFwiIOKGkiBcImtvXCJcbiAgICovXG4gIHByaXZhdGUgZGV0ZWN0TG9jYWxlKFxuICAgIGFjY2VwdExhbmd1YWdlOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgc3VwcG9ydGVkOiBzdHJpbmdbXSxcbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIWFjY2VwdExhbmd1YWdlKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgLy8gQWNjZXB0LUxhbmd1YWdlOiBrby1LUixrbztxPTAuOSxlbjtxPTAuOFxuICAgIGNvbnN0IGxhbmdzID0gYWNjZXB0TGFuZ3VhZ2Uuc3BsaXQoXCIsXCIpLm1hcCgobGFuZykgPT4ge1xuICAgICAgY29uc3QgW2NvZGVdID0gbGFuZy5zcGxpdChcIjtcIik7XG4gICAgICByZXR1cm4gY29kZS50cmltKCkuc3BsaXQoXCItXCIpWzBdOyAvLyBrby1LUiDihpIga29cbiAgICB9KTtcblxuICAgIHJldHVybiBsYW5ncy5maW5kKChsYW5nKSA9PiBzdXBwb3J0ZWQuaW5jbHVkZXMobGFuZykpO1xuICB9XG5cbiAgYXN5bmMgc3RhcnRXYXRjaGVyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIHdhdGNoZXIg66qo65OI7J2AIGZpbGUtcGF0dGVybnMg4oaSIFNvbmFtdSDsiJztmZjsnYQg7ZS87ZWY6riwIOychO2VtCBkeW5hbWljIGltcG9ydCDtlanri4jri6QuXG4gICAgY29uc3QgeyBzZXR1cFdhdGNoZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3N5bmNlci93YXRjaGVyXCIpO1xuICAgIHRoaXMud2F0Y2hlciA9IGF3YWl0IHNldHVwV2F0Y2hlcigoZmlsZUV2ZW50cykgPT4gdGhpcy5ydW5IbXJTeW5jQ3ljbGUoZmlsZUV2ZW50cykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdhdGNoZXLqsIAgMTAwbXMgYmF0Y2jroZwg66qo7J2AIGZpbGVFdmVudHMg7ZWY64KY7JeQIOuMgO2VtCDtlZwg67KI7J2YIEhNUi9zeW5jIOyCrOydtO2BtOydhCDrj5Xri4jri6QuXG4gICAqIGJhdGNoIO2BkOyeiSDrjZXsl5Ag7ZWcIOyLnOygkOyXkCDtlZjrgpjrp4wg7Iuk7ZaJ65Co7J20IOuztOyepeuQqeuLiOuLpCAoZXZlbnQtYmF0Y2hlcuqwgCDsp4HroKztmZQpLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBydW5IbXJTeW5jQ3ljbGUoZmlsZUV2ZW50czogTWFwPEFic29sdXRlUGF0aCwgXCJjaGFuZ2VcIiB8IFwiYWRkXCI+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgc3RhcnRlZEF0ID0gRGF0ZS5ub3coKTtcblxuICAgIGZvciAoY29uc3QgW2ZpbGVQYXRoLCBldmVudF0gb2YgZmlsZUV2ZW50cykge1xuICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcGF0aC5yZWxhdGl2ZSh0aGlzLmFwcFJvb3RQYXRoLCBmaWxlUGF0aCk7XG4gICAgICBjb25zb2xlLmxvZyhjaGFsay5ib2xkKGBEZXRlY3RlZCgke2V2ZW50fSk6ICR7Y2hhbGsuYmx1ZShyZWxhdGl2ZVBhdGgpfWApKTtcbiAgICB9XG5cbiAgICAvLyDrs7jssrQ6IOuzgOqyvSDtnaHsiJggKyDssrTtgazshKwg6rCx7IugLlxuICAgIGF3YWl0IHRoaXMuc3luY2VyLmhtckFuZFN5bmMoZmlsZUV2ZW50cyk7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIucmVuZXdDaGVja3N1bXMoKTtcblxuICAgIGNvbnN0IHRvdGFsVGltZSA9IERhdGUubm93KCkgLSBzdGFydGVkQXQ7XG4gICAgY29uc3QgbXNnID0gYEhNUiBEb25lISAke2NoYWxrLmJvbGQud2hpdGUoYCR7dG90YWxUaW1lfW1zYCl9YDtcbiAgICBjb25zb2xlLmxvZyhjaGFsay5ibGFjay5iZ0dyZWVuKGNlbnRlclRleHQobXNnKSkpO1xuICB9XG5cbiAgLypcbiAgICAgQSBmdW5jdGlvbiB0aGF0IGF1dG9tYXRpY2FsbHkgaGFuZGxlcyBpbml0IGFuZCBkZXN0cm95IHdoZW4gdXNpbmcgU29uYW11IHZpYSBzY3JpcHRzLlxuICAqL1xuICBhc3luYyBydW5TY3JpcHQoZm46ICgpID0+IFByb21pc2U8dm9pZD4pIHtcbiAgICBhd2FpdCB0aGlzLmluaXQodHJ1ZSwgZmFsc2UsIHVuZGVmaW5lZCwgZmFsc2UpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmbigpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZ2lzdGVyUGx1Z2lucyhzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSwgcGx1Z2luczogU29uYW11U2VydmVyT3B0aW9uc1tcInBsdWdpbnNcIl0pIHtcbiAgICBpZiAoIXBsdWdpbnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBjb21wcmVzcyDtlIzrn6zqt7jsnbjsnYAg64uk66W4IO2UjOufrOq3uOyduOuztOuLpCDrqLzsoIAg65Ox66Gd65CY7Ja07JW8IO2VqeuLiOuLpC5cbiAgICBpZiAocGx1Z2lucy5jb21wcmVzcykge1xuICAgICAgY29uc3QgY29tcHJlc3NQbHVnaW4gPSAoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvY29tcHJlc3NcIikpLmRlZmF1bHQ7XG4gICAgICBjb25zdCBkZWZhdWx0T3B0aW9ucyA9IHtcbiAgICAgICAgdGhyZXNob2xkOiAxMDI0LFxuICAgICAgICBlbmNvZGluZ3M6IFtcImJyXCIsIFwiZ3ppcFwiLCBcImRlZmxhdGVcIl0gYXMgKFwiYnJcIiB8IFwiZ3ppcFwiIHwgXCJkZWZsYXRlXCIpW10sXG4gICAgICB9O1xuXG4gICAgICBpZiAocGx1Z2lucy5jb21wcmVzcyA9PT0gdHJ1ZSkge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoY29tcHJlc3NQbHVnaW4sIGRlZmF1bHRPcHRpb25zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlcnZlci5yZWdpc3Rlcihjb21wcmVzc1BsdWdpbiwge1xuICAgICAgICAgIC4uLmRlZmF1bHRPcHRpb25zLFxuICAgICAgICAgIC4uLnBsdWdpbnMuY29tcHJlc3MsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHBsdWdpbnNNb2R1bGVzID0ge1xuICAgICAgY29yczogXCJAZmFzdGlmeS9jb3JzXCIsXG4gICAgICBmb3JtYm9keTogXCJAZmFzdGlmeS9mb3JtYm9keVwiLFxuICAgICAgbXVsdGlwYXJ0OiBcIkBmYXN0aWZ5L211bHRpcGFydFwiLFxuICAgICAgcXM6IFwiZmFzdGlmeS1xc1wiLFxuICAgICAgc3NlOiBcImZhc3RpZnktc3NlLXYyXCIsXG4gICAgICBzdGF0aWM6IFwiQGZhc3RpZnkvc3RhdGljXCIsXG4gICAgfSBhcyBjb25zdDtcblxuICAgIGNvbnN0IHJlZ2lzdGVyUGx1Z2luID0gYXN5bmMgPEsgZXh0ZW5kcyBrZXlvZiBOb25OdWxsYWJsZTx0eXBlb2YgcGx1Z2lucz4+KFxuICAgICAga2V5OiBLLFxuICAgICAgcGx1Z2luTmFtZTogc3RyaW5nLFxuICAgICkgPT4ge1xuICAgICAgY29uc3Qgb3B0aW9uID0gcGx1Z2luc1trZXldO1xuICAgICAgaWYgKCFvcHRpb24pIHJldHVybjtcblxuICAgICAgaWYgKG9wdGlvbiA9PT0gdHJ1ZSkge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoKGF3YWl0IGltcG9ydChwbHVnaW5OYW1lKSkuZGVmYXVsdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoKGF3YWl0IGltcG9ydChwbHVnaW5OYW1lKSkuZGVmYXVsdCwgb3B0aW9uKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZm9yIChjb25zdCBba2V5LCBwbHVnaW5OYW1lXSBvZiBPYmplY3QuZW50cmllcyhwbHVnaW5zTW9kdWxlcykpIHtcbiAgICAgIGF3YWl0IHJlZ2lzdGVyUGx1Z2luKGtleSBhcyBrZXlvZiB0eXBlb2YgcGx1Z2lucywgcGx1Z2luTmFtZSk7XG4gICAgfVxuXG4gICAgaWYgKHBsdWdpbnMud3MpIHtcbiAgICAgIGF3YWl0IHRoaXMuZW5zdXJlV2ViU29ja2V0UGx1Z2luKHNlcnZlcik7XG4gICAgfVxuXG4gICAgaWYgKHBsdWdpbnMuY3VzdG9tKSB7XG4gICAgICBwbHVnaW5zLmN1c3RvbShzZXJ2ZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEBmYXN0aWZ5L3dlYnNvY2tldOydgCBwbHVnaW5zLndz6rCAIOyEpOygleuQnCDqsr3smrDsl5Drp4wg65Ox66Gd7ZWY6rOgLCDqsJnsnYAgc2VydmVy7JeQIOykkeuztSDrk7HroZ3rkJjsp4Ag7JWK64+E66GdIFdlYWtTZXTsnLzroZwg6riw66Gd7ZWoXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlV2ViU29ja2V0UGx1Z2luKFxuICAgIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlPFNlcnZlciwgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZT4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLndlYnNvY2tldFBsdWdpblNlcnZlcnMuaGFzKHNlcnZlcikpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwbHVnaW5PcHRpb24gPSB0aGlzLmNvbmZpZy5zZXJ2ZXIucGx1Z2lucz8ud3M7XG4gICAgaWYgKCFwbHVnaW5PcHRpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB3ZWJzb2NrZXRQbHVnaW4gPSAoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvd2Vic29ja2V0XCIpKS5kZWZhdWx0O1xuICAgIGNvbnN0IHJlc29sdmVkUGx1Z2luT3B0aW9ucyA9IHJlc29sdmVXZWJTb2NrZXRQbHVnaW5PcHRpb25zKHtcbiAgICAgIHJhd1BsdWdpbk9wdGlvbjogcGx1Z2luT3B0aW9uLFxuICAgIH0pO1xuICAgIGlmIChyZXNvbHZlZFBsdWdpbk9wdGlvbnMpIHtcbiAgICAgIGF3YWl0IHNlcnZlci5yZWdpc3Rlcih3ZWJzb2NrZXRQbHVnaW4sIHJlc29sdmVkUGx1Z2luT3B0aW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHNlcnZlci5yZWdpc3Rlcih3ZWJzb2NrZXRQbHVnaW4pO1xuICAgIH1cblxuICAgIHRoaXMud2Vic29ja2V0UGx1Z2luU2VydmVycy5hZGQoc2VydmVyKTtcbiAgICB0aGlzLndhcm5PblBvdGVudGlhbFdlYlNvY2tldFRpbWVvdXRDb25mbGljdHMoc2VydmVyKTtcbiAgfVxuXG4gIC8vIGhlYXJ0YmVhdCBpbnRlcnZhbOydtCBGYXN0aWZ5IGtlZXBBbGl2ZVRpbWVvdXQg7J207IOB7J2066m0IOyduO2UhOudvOqwgCDrqLzsoIAgaWRsZSDsl7DqsrDsnYQg64GK7J2EIOyImCDsnojslrQg6rK96rOg66eMIOuCqOq4sOqzoCDrhJjslrTqsJBcbiAgcHJpdmF0ZSB3YXJuT25Qb3RlbnRpYWxXZWJTb2NrZXRUaW1lb3V0Q29uZmxpY3RzKFxuICAgIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlPFNlcnZlciwgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZT4sXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGhlYXJ0YmVhdHMgPSB0aGlzLnN5bmNlci5hcGlzXG4gICAgICAubWFwKChhcGkpID0+IGFwaS53ZWJzb2NrZXRPcHRpb25zPy5oZWFydGJlYXQgPz8gMzAwMDApXG4gICAgICAuZmlsdGVyKChoZWFydGJlYXQpID0+IGhlYXJ0YmVhdCA+IDApO1xuXG4gICAgaWYgKGhlYXJ0YmVhdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qga2VlcEFsaXZlVGltZW91dCA9IHRoaXMuY29uZmlnLnNlcnZlci5mYXN0aWZ5Py5rZWVwQWxpdmVUaW1lb3V0O1xuICAgIGlmICgha2VlcEFsaXZlVGltZW91dCB8fCBrZWVwQWxpdmVUaW1lb3V0IDw9IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBsYXJnZXN0SGVhcnRiZWF0ID0gTWF0aC5tYXgoLi4uaGVhcnRiZWF0cyk7XG4gICAgaWYgKGxhcmdlc3RIZWFydGJlYXQgPj0ga2VlcEFsaXZlVGltZW91dCkge1xuICAgICAgc2VydmVyLmxvZy53YXJuKFxuICAgICAgICB7XG4gICAgICAgICAga2VlcEFsaXZlVGltZW91dCxcbiAgICAgICAgICBsYXJnZXN0SGVhcnRiZWF0LFxuICAgICAgICB9LFxuICAgICAgICBcIldlYlNvY2tldCBoZWFydGJlYXQgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGtlZXBBbGl2ZVRpbWVvdXQ7IGFsaWduIGluZnJhc3RydWN0dXJlIGlkbGUgdGltZW91dHMgdG8gYXZvaWQgdW5leHBlY3RlZCBkaXNjb25uZWN0cy5cIixcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIGJldHRlci1hdXRoIOudvOyasO2KuOulvCDrk7HroZ3tlanri4jri6QuXG4gICAqIC9hcGkvYXV0aC8qIOqyveuhnOuhnCDsnbjspp0gQVBJ6rCAIOyekOuPmSDrk7HroZ3rkKnri4jri6QuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlZ2lzdGVyQmV0dGVyQXV0aChcbiAgICBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSxcbiAgICBvcHRpb25zOiBOb25OdWxsYWJsZTxTb25hbXVTZXJ2ZXJPcHRpb25zW1wiYXV0aFwiXT4sXG4gICkge1xuICAgIGlmICghb3B0aW9ucykgcmV0dXJuO1xuXG4gICAgY29uc3QgYmFzZVBhdGggPSBvcHRpb25zLmJhc2VQYXRoID8/IFwiL2FwaS9hdXRoXCI7XG5cbiAgICAvLyBiZXR0ZXItYXV0aCDrnbzsmrDtirgg65Ox66GdXG4gICAgc2VydmVyLnJvdXRlKHtcbiAgICAgIG1ldGhvZDogW1wiR0VUXCIsIFwiUE9TVFwiXSxcbiAgICAgIHVybDogYCR7YmFzZVBhdGh9LypgLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwocmVxdWVzdC51cmwsIGBodHRwOi8vJHtyZXF1ZXN0LmhlYWRlcnMuaG9zdH1gKTtcbiAgICAgICAgY29uc3QgaGVhZGVycyA9IGNvbnZlcnRGYXN0aWZ5SGVhZGVyc1RvU3RhbmRhcmQocmVxdWVzdC5oZWFkZXJzKTtcblxuICAgICAgICAvLyBJUCDtl6TrjZQgZmFsbGJhY2s6IO2UhOuhneyLnOqwgCDtkZzspIAgSVAg7Zek642U66W8IOyjvOyehe2VmOyngCDslYrripQg7ZmY6rK97JeQ7ISc64+EXG4gICAgICAgIC8vIGJldHRlci1hdXRoL2luZnJh7J2YIGdldENsaWVudElwRnJvbVJlcXVlc3QoKeqwgCBJUOulvCDsnbjsi53tlaAg7IiYIOyeiOuPhOuhnVxuICAgICAgICAvLyBGYXN0aWZ56rCAIHJlc29sdmXtlZwgcmVxdWVzdC5pcOulvCB4LXJlYWwtaXDroZwg7KO87J6F7ZWc64ukLlxuICAgICAgICBjb25zdCBJUF9IRUFERVJTID0gW1xuICAgICAgICAgIFwiY2YtY29ubmVjdGluZy1pcFwiLFxuICAgICAgICAgIFwieC1mb3J3YXJkZWQtZm9yXCIsXG4gICAgICAgICAgXCJ4LXJlYWwtaXBcIixcbiAgICAgICAgICBcIngtdmVyY2VsLWZvcndhcmRlZC1mb3JcIixcbiAgICAgICAgXTtcbiAgICAgICAgaWYgKHJlcXVlc3QuaXAgJiYgIUlQX0hFQURFUlMuc29tZSgoaCkgPT4gaGVhZGVycy5oYXMoaCkpKSB7XG4gICAgICAgICAgaGVhZGVycy5zZXQoXCJ4LXJlYWwtaXBcIiwgcmVxdWVzdC5pcCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXEgPSBuZXcgUmVxdWVzdCh1cmwudG9TdHJpbmcoKSwge1xuICAgICAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICAgICAgaGVhZGVycyxcbiAgICAgICAgICAuLi4ocmVxdWVzdC5ib2R5ID8geyBib2R5OiBKU09OLnN0cmluZ2lmeShyZXF1ZXN0LmJvZHkpIH0gOiB7fSksXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5hdXRoLmhhbmRsZXIocmVxKTtcblxuICAgICAgICByZXBseS5zdGF0dXMocmVzcG9uc2Uuc3RhdHVzKTtcbiAgICAgICAgcmVzcG9uc2UuaGVhZGVycy5mb3JFYWNoKCh2YWx1ZTogc3RyaW5nLCBrZXk6IHN0cmluZykgPT4ge1xuICAgICAgICAgIHJlcGx5LmhlYWRlcihrZXksIHZhbHVlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXBseS5zZW5kKHJlc3BvbnNlLmJvZHkgPyBhd2FpdCByZXNwb25zZS50ZXh0KCkgOiBudWxsKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHByaW50U3RhcnR1cFN1bW1hcnkoKSB7XG4gICAgY29uc3QgY2hhbGsgPSAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQ7XG4gICAgY29uc3QgZW52ID0gcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPz8gXCJkZXZlbG9wbWVudFwiO1xuICAgIGNvbnN0IGFjdGl2ZVByZXNldCA9IGVudiA9PT0gXCJwcm9kdWN0aW9uXCIgPyBcInByb2R1Y3Rpb25fbWFzdGVyXCIgOiBcImRldmVsb3BtZW50X21hc3RlclwiO1xuXG4gICAgY29uc3QgZGltID0gKG1zZzogc3RyaW5nKSA9PiBjb25zb2xlLmxvZyhjaGFsay5kaW0oYOKckyAke21zZ31gKSk7XG4gICAgY29uc3QgZ3JlZW4gPSAobXNnOiBzdHJpbmcpID0+IGNvbnNvbGUubG9nKGNoYWxrLmdyZWVuKGDinJMgJHttc2d9YCkpO1xuXG4gICAgZGltKGBDb25maWcgbG9hZGVkJHtmb3JtYXRUaW1lKHRoaXMuX2NvbmZpZ0VsYXBzZWQpfWApO1xuXG4gICAgLy8gREIgcHJlc2V0IOuqqeuhnVxuICAgIGdyZWVuKFwiREJcIik7XG4gICAgY29uc3QgeyBpc0xvY2FsIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi91dGlscy9jb250cm9sbGVyXCIpO1xuICAgIGNvbnN0IHByZXNldE5hbWVzID0gT2JqZWN0LmtleXModGhpcy5kYkNvbmZpZykgYXMgKGtleW9mIFNvbmFtdURCQ29uZmlnKVtdO1xuICAgIGNvbnN0IG1heExlbiA9IE1hdGgubWF4KC4uLnByZXNldE5hbWVzLm1hcCgobikgPT4gbi5sZW5ndGgpKTtcbiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgcHJlc2V0TmFtZXMpIHtcbiAgICAgIGNvbnN0IGNvbm4gPSB0aGlzLmRiQ29uZmlnW25hbWVdLmNvbm5lY3Rpb24gYXNcbiAgICAgICAgfCB7IGhvc3Q/OiBzdHJpbmc7IHBvcnQ/OiBudW1iZXI7IGRhdGFiYXNlPzogc3RyaW5nIH1cbiAgICAgICAgfCB1bmRlZmluZWQ7XG4gICAgICBjb25zdCBob3N0ID0gY29ubj8uaG9zdCA/PyBcImxvY2FsaG9zdFwiO1xuICAgICAgY29uc3QgYWRkciA9IGBAICR7aG9zdH06JHtjb25uPy5wb3J0ID8/IDU0MzJ9LyR7Y29ubj8uZGF0YWJhc2UgPz8gdGhpcy5jb25maWcuZGF0YWJhc2UubmFtZX1gO1xuICAgICAgY29uc3QgcGFkZGVkID0gbmFtZS5wYWRFbmQobWF4TGVuKTtcbiAgICAgIGNvbnN0IHJlbW90ZVRhZyA9IGlzTG9jYWwoKSAmJiAhaXNMb2NhbEhvc3QoaG9zdCkgPyBjaGFsay55ZWxsb3coYCBcXHUyNmEwIHJlbW90ZWApIDogXCJcIjtcblxuICAgICAgaWYgKG5hbWUgPT09IGFjdGl2ZVByZXNldCkge1xuICAgICAgICBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihgICBcXHUyNWI4ICR7cGFkZGVkfSAke2FkZHJ9YCkgKyByZW1vdGVUYWcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coY2hhbGsuZGltKGAgICAgJHtwYWRkZWR9ICR7YWRkcn1gKSArIHJlbW90ZVRhZyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY29uZmlnLnNlcnZlci5hdXRoKSB7XG4gICAgICBjb25zdCBiYXNlUGF0aCA9IHRoaXMuY29uZmlnLnNlcnZlci5hdXRoLmJhc2VQYXRoID8/IFwiL2FwaS9hdXRoXCI7XG4gICAgICBkaW0oYEF1dGg6IGJldHRlci1hdXRoIGF0ICR7YmFzZVBhdGh9LypgKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuY29uZmlnLmFwaS50aW1lem9uZSkge1xuICAgICAgZGltKGBUaW1lem9uZTogJHt0aGlzLmNvbmZpZy5hcGkudGltZXpvbmV9YCk7XG4gICAgfVxuICAgIGdyZWVuKGBTb25hbXUgcmVhZHkke2Zvcm1hdFRpbWUodGhpcy5faW5pdEVsYXBzZWQpfWApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpbml0aWFsaXplQ2FjaGUoY29uZmlnOiBDYWNoZUNvbmZpZyB8IHVuZGVmaW5lZCwgZm9yVGVzdGluZzogYm9vbGVhbikge1xuICAgIGNvbnN0IHsgc2V0Q2FjaGVNYW5hZ2VyUmVmIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9jYWNoZS9kZWNvcmF0b3JcIik7XG5cbiAgICAvLyDthYzsiqTtirgg7ZmY6rK97JeQ7IScIOuplOuqqOumrCDrk5zrnbzsnbTrsoQg7J6Q64+ZIOyCrOyaqVxuICAgIGlmIChmb3JUZXN0aW5nKSB7XG4gICAgICBjb25zdCB7IGNyZWF0ZVRlc3RDYWNoZU1hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL2NhY2hlL2NhY2hlLW1hbmFnZXJcIik7XG4gICAgICB0aGlzLl9jYWNoZSA9IGNyZWF0ZVRlc3RDYWNoZU1hbmFnZXIoKTtcbiAgICAgIHNldENhY2hlTWFuYWdlclJlZih0aGlzLl9jYWNoZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8g7ISk7KCV7J20IOyXhuycvOuptCDsupDsi5wg67mE7Zmc7ISx7ZmUXG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgIHNldENhY2hlTWFuYWdlclJlZihudWxsKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyDshKTsoJXsl5Ag65Sw6528IENhY2hlTWFuYWdlciDsg53shLFcbiAgICBjb25zdCB7IGNyZWF0ZUNhY2hlTWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vY2FjaGUvY2FjaGUtbWFuYWdlclwiKTtcbiAgICB0aGlzLl9jYWNoZSA9IGNyZWF0ZUNhY2hlTWFuYWdlcihjb25maWcpO1xuICAgIHNldENhY2hlTWFuYWdlclJlZih0aGlzLl9jYWNoZSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemVXb3JrZmxvd3Mob3B0aW9uczogU29uYW11VGFza09wdGlvbnMgfCB1bmRlZmluZWQpIHtcbiAgICBjb25zdCB7IFdvcmtmbG93TWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdGFza3Mvd29ya2Zsb3ctbWFuYWdlclwiKTtcbiAgICAvLyBOT1RFOiBAc29uYW11LWtpdC90YXNrcyDslYjsl5DshKAga25leCBjb25maWfrpbwg7IiY7KCV7ZWY6riwIOuVjOusuOyXkCBjb25uZWN0aW9u7J20IOyVhOuLjCBjb25maWcg7Ke466GcIOuztOuDheuLiOuLpC5cbiAgICB0aGlzLl93b3JrZmxvd3MgPSBuZXcgV29ya2Zsb3dNYW5hZ2VyKERCLmdldERCQ29uZmlnKFwid1wiKSk7XG4gICAgaWYgKCFvcHRpb25zKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZW5hYmxlV29ya2VyID0gb3B0aW9ucy5lbmFibGVXb3JrZXIgPz8gaXNEYWVtb25TZXJ2ZXIoKTtcbiAgICBjb25zdCBkZWZhdWx0V29ya2VyT3B0aW9ucyA9IHtcbiAgICAgIGNvbmN1cnJlbmN5OiBvcy5jcHVzKCkubGVuZ3RoIC0gMSxcbiAgICAgIHVzZVB1YlN1YjogdHJ1ZSxcbiAgICAgIGxpc3RlbkRlbGF5OiA1MDAsXG4gICAgfTtcblxuICAgIGlmIChlbmFibGVXb3JrZXIpIHtcbiAgICAgIHRoaXMud29ya2Zsb3dzLnNldHVwV29ya2VyKHtcbiAgICAgICAgLi4uZGVmYXVsdFdvcmtlck9wdGlvbnMsXG4gICAgICAgIC4uLm9wdGlvbnMud29ya2VyT3B0aW9ucyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYm9vdChzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSwgb3B0aW9uczogU29uYW11U2VydmVyT3B0aW9ucykge1xuICAgIGNvbnN0IHBvcnQgPSBvcHRpb25zLmxpc3Rlbj8ucG9ydCA/PyAzMDAwO1xuICAgIGNvbnN0IGhvc3QgPSBvcHRpb25zLmxpc3Rlbj8uaG9zdCA/PyBcImxvY2FsaG9zdFwiO1xuXG4gICAgc2VydmVyLmFkZEhvb2soXCJvbkNsb3NlXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IG9wdGlvbnMubGlmZWN5Y2xlPy5vblNodXRkb3duPy4oc2VydmVyKTtcbiAgICAgIGF3YWl0IHRoaXMud29ya2Zsb3dzLmRlc3Ryb3koKTtcbiAgICAgIGF3YWl0IHRoaXMuZGVzdHJveSgpO1xuICAgIH0pO1xuXG4gICAgY29uc3Qgc2h1dGRvd24gPSBhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBzZXJ2ZXIuY2xvc2UoKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDApO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBkdXJpbmcgc2h1dGRvd246XCIsIGVycik7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJvY2Vzcy5vbihcIlNJR0lOVFwiLCBzaHV0ZG93bik7XG4gICAgcHJvY2Vzcy5vbihcIlNJR1RFUk1cIiwgc2h1dGRvd24pO1xuXG4gICAgaWYgKG9wdGlvbnMubGlmZWN5Y2xlPy5vbkVycm9yKSB7XG4gICAgICBzZXJ2ZXIuc2V0RXJyb3JIYW5kbGVyKG9wdGlvbnMubGlmZWN5Y2xlPy5vbkVycm9yKTtcbiAgICB9XG5cbiAgICBzZXJ2ZXJcbiAgICAgIC5saXN0ZW4oeyBwb3J0LCBob3N0IH0pXG4gICAgICAudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMud29ya2Zsb3dzLnN0YXJ0V29ya2VyKCk7XG4gICAgICAgIGF3YWl0IG9wdGlvbnMubGlmZWN5Y2xlPy5vblN0YXJ0Py4oc2VydmVyKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goYXN5bmMgKGVycikgPT4ge1xuICAgICAgICBjb25zdCBjaGFsayA9IChhd2FpdCBpbXBvcnQoXCJjaGFsa1wiKSkuZGVmYXVsdDtcbiAgICAgICAgY29uc29sZS5lcnJvcihjaGFsay5yZWQoXCJGYWlsZWQgdG8gc3RhcnQgc2VydmVyOlwiLCBlcnIpKTtcbiAgICAgICAgYXdhaXQgc2h1dGRvd24oKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZGVzdHJveSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IEJhc2VNb2RlbCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZGF0YWJhc2UvYmFzZS1tb2RlbFwiKTtcbiAgICAvLyDrqLzsoIAg7LKY66as7ZW07JW87ZWoLlxuICAgIGF3YWl0IEJhc2VNb2RlbC5kZXN0cm95KCk7XG4gICAgLy8gV2ViU29ja2V0IHNodXRkb3duIGZpcnN0IHRvIGZsdXNoIHRlbGVtZXRyeVxuICAgIGlmICh0aGlzLl93ZWJzb2NrZXRSdW50aW1lKSB7XG4gICAgICBhd2FpdCB0aGlzLl93ZWJzb2NrZXRSdW50aW1lLnNodXRkb3duKCk7XG4gICAgfVxuICAgIHRoaXMuX3dlYnNvY2tldFJ1bnRpbWUgPSBudWxsO1xuICAgIC8vIFRoZW4gc2h1dCBkb3duIHJlbWFpbmluZyByZXNvdXJjZXMgaW4gcGFyYWxsZWxcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoW1xuICAgICAgdGhpcy5fd29ya2Zsb3dzPy5kZXN0cm95KCkgPz8gUHJvbWlzZS5yZXNvbHZlKCksXG4gICAgICB0aGlzLl9jYWNoZT8uZGlzY29ubmVjdCgpID8/IFByb21pc2UucmVzb2x2ZSgpLFxuICAgICAgdGhpcy5fZGV2Vml0ZXN0TWFuYWdlcj8uc2h1dGRvd24oKSA/PyBQcm9taXNlLnJlc29sdmUoKSxcbiAgICAgIHRoaXMud2F0Y2hlcj8uY2xvc2UoKSA/PyBQcm9taXNlLnJlc29sdmUoKSxcbiAgICBdKTtcbiAgICAvLyBMb2dUYXBlIGRpc3Bvc2UgYWZ0ZXIgV1Mgc2h1dGRvd24gc28gdGVsZW1ldHJ5IHJlY29yZHMgYXJlIGZsdXNoZWQgZmlyc3RcbiAgICBhd2FpdCBsb2d0YXBlRGlzcG9zZSgpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldFdlYlNvY2tldFRlbGVtZXRyeUNvbnRleHQoXG4gIHdzOiBXZWJTb2NrZXRDb25uZWN0aW9uPFdlYlNvY2tldEV2ZW50TWFwLCBXZWJTb2NrZXRFdmVudE1hcD4sXG4pOiBXZWJTb2NrZXRUZWxlbWV0cnlDb25uZWN0aW9uQ29udGV4dCB7XG4gIGlmICghaXNUZWxlbWV0cnlDb250ZXh0UHJvdmlkZXIod3MpKSB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgcmV0dXJuIHdzLmdldFRlbGVtZXRyeUNvbnRleHQoKTtcbn1cblxuZnVuY3Rpb24gaXNUZWxlbWV0cnlDb250ZXh0UHJvdmlkZXIoXG4gIHdzOiBXZWJTb2NrZXRDb25uZWN0aW9uPFdlYlNvY2tldEV2ZW50TWFwLCBXZWJTb2NrZXRFdmVudE1hcD4sXG4pOiB3cyBpcyBXZWJTb2NrZXRDb25uZWN0aW9uPFdlYlNvY2tldEV2ZW50TWFwLCBXZWJTb2NrZXRFdmVudE1hcD4gJiBUZWxlbWV0cnlDb250ZXh0UHJvdmlkZXIge1xuICByZXR1cm4gXCJnZXRUZWxlbWV0cnlDb250ZXh0XCIgaW4gd3MgJiYgdHlwZW9mIHdzLmdldFRlbGVtZXRyeUNvbnRleHQgPT09IFwiZnVuY3Rpb25cIjtcbn1cblxuZXhwb3J0IGNvbnN0IFNvbmFtdSA9IG5ldyBTb25hbXVDbGFzcygpO1xuXG4vKipcbiAqIHN0cmVhbSDrqqjrk5zsl5DshJwg7YKkIOyDneyEsSDtlajsiJjqsIAg7KeA7KCV65CY7KeAIOyViuyVmOydhCDrlYwg7IKs7Jqp7ZWY64qUIOq4sOuzuCDtlajsiJjsnoXri4jri6QuXG4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRLZXlHZW5lcmF0b3IoZmlsZTogeyBmaWxlbmFtZTogc3RyaW5nOyBtaW1ldHlwZTogc3RyaW5nIH0pOiBzdHJpbmcge1xuICBjb25zdCBleHQgPSBtaW1lLmV4dGVuc2lvbihmaWxlLm1pbWV0eXBlKSB8fCBcImJpblwiO1xuICBjb25zdCB0aW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICBjb25zdCByYW5kb20gPSBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zbGljZSgyLCA4KTtcbiAgcmV0dXJuIGB1cGxvYWRzLyR7dGltZXN0YW1wfS0ke3JhbmRvbX0uJHtleHR9YDtcbn1cblxuZnVuY3Rpb24gZm9ybWF0VGltZShtczogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgZm9ybWF0dGVkID0gbXMgPj0gMTAwMCA/IGAkeyhtcyAvIDEwMDApLnRvRml4ZWQoMil9c2AgOiBgJHtNYXRoLnJvdW5kKG1zKX1tc2A7XG4gIHJldHVybiBgICgke2Zvcm1hdHRlZH0pYDtcbn1cblxuY29uc3QgTE9DQUxfSE9TVFMgPSBuZXcgU2V0KFtcImxvY2FsaG9zdFwiLCBcIjEyNy4wLjAuMVwiLCBcIjAuMC4wLjBcIiwgXCI6OjFcIl0pO1xuZnVuY3Rpb24gaXNMb2NhbEhvc3QoaG9zdDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBMT0NBTF9IT1NUUy5oYXMoaG9zdCkgfHwgaG9zdC5lbmRzV2l0aChcIi5sb2NhbFwiKTtcbn1cblxuLy8gYC5ldmVyeSgpYOqwgCDssqsgZ3VhcmQg7J207ZuEIOyInO2ajOulvCDrqYjstpTripQg66y47KCc6rCAIOyeiOyWtCBgZm9yLi4ub2Zg66GcIOuqqOuToCBndWFyZOulvCDsiJzshJzrjIDroZwg7Iuk7ZaJ7ZWY64+E66GdIOqzoOygle2VqFxuZnVuY3Rpb24gcnVuR3VhcmRzKHtcbiAgZ3VhcmRzLFxuICBjb25maWcsXG4gIHJlcXVlc3QsXG4gIGFwaSxcbn06IHtcbiAgZ3VhcmRzOiBFeHRlbmRlZEFwaVtcIm9wdGlvbnNcIl1bXCJndWFyZHNcIl0gfCB1bmRlZmluZWQ7XG4gIGNvbmZpZzogUGljazxTb25hbXVGYXN0aWZ5Q29uZmlnLCBcImd1YXJkSGFuZGxlclwiPjtcbiAgcmVxdWVzdDogRmFzdGlmeVJlcXVlc3Q7XG4gIGFwaTogRXh0ZW5kZWRBcGk7XG59KTogdm9pZCB7XG4gIGZvciAoY29uc3QgZ3VhcmQgb2YgZ3VhcmRzID8/IFtdKSB7XG4gICAgY29uZmlnLmd1YXJkSGFuZGxlcihndWFyZCwgcmVxdWVzdCwgYXBpKTtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXE3REEsU0FBUyw2QkFDUCxJQUNxQztBQUNyQyxLQUFJLENBQUMsMkJBQTJCLEdBQUcsRUFBRTtBQUNuQyxTQUFPLEVBQUU7O0FBR1gsUUFBTyxHQUFHLHFCQUFxQjs7QUFHakMsU0FBUywyQkFDUCxJQUM0RjtBQUM1RixRQUFPLHlCQUF5QixNQUFNLE9BQU8sR0FBRyx3QkFBd0I7Ozs7O0FBUTFFLFNBQVMsb0JBQW9CLE1BQXNEO0NBQ2pGLE1BQU0sTUFBTSxLQUFLLFVBQVUsS0FBSyxTQUFTLElBQUk7Q0FDN0MsTUFBTSxZQUFZLEtBQUssS0FBSztDQUM1QixNQUFNLFNBQVMsS0FBSyxRQUFRLENBQUMsU0FBUyxHQUFHLENBQUMsTUFBTSxHQUFHLEVBQUU7QUFDckQsUUFBTyxXQUFXLFVBQVUsR0FBRyxPQUFPLEdBQUc7O0FBRzNDLFNBQVMsV0FBVyxJQUFvQjtDQUN0QyxNQUFNLFlBQVksTUFBTSxNQUFPLElBQUksS0FBSyxLQUFNLFFBQVEsRUFBRSxDQUFDLEtBQUssR0FBRyxLQUFLLE1BQU0sR0FBRyxDQUFDO0FBQ2hGLFFBQU8sS0FBSyxVQUFVOztBQUl4QixTQUFTLFlBQVksTUFBdUI7QUFDMUMsUUFBTyxZQUFZLElBQUksS0FBSyxJQUFJLEtBQUssU0FBUyxTQUFTOztBQUl6RCxTQUFTLFVBQVUsRUFDakIsUUFDQSxRQUNBLFNBQ0EsT0FNTztBQUNQLE1BQUssTUFBTSxTQUFTLFVBQVUsRUFBRSxFQUFFO0FBQ2hDLFNBQU8sYUFBYSxPQUFPLFNBQVMsSUFBSTs7Ozs7NEJBeDlEdUI7cUJBQ2M7Z0JBR2xCO1VBRTNCO1VBRVM7cUJBRW1CO3FCQUNSO3FCQUdBO1dBQ0g7VUFDNkM7b0JBUy9DO2tCQUNFO2dCQUNFO2FBRWlCO2NBSWxDO3lCQU9UO0NBUXZCLGNBQU4sTUFBa0I7RUFDaEIsQUFBTyxnQkFBeUI7RUFDaEMsQUFBTyxhQUFzQjtFQUM3QixBQUFPLG9CQUVGLElBQUksbUJBQW1CO0VBRTVCLEFBQU8sYUFBb0Q7R0FDekQsTUFBTSxRQUFRLEtBQUssa0JBQWtCLFVBQVU7QUFDL0MsT0FBSSxPQUFPLFNBQVM7QUFDbEIsV0FBTyxNQUFNOztBQUdmLE9BQUksUUFBUSxJQUFJLGFBQWEsUUFBUTtBQUVuQyxXQUFPO0tBQ0wsV0FBVztLQUNYLFNBQVM7S0FDVCxPQUFPO0tBQ1AsU0FBUyxFQUFFO0tBQ1gsWUFBWSxXQUFzQixxQkFBcUIsT0FBTztLQUM5RCxRQUFRO0tBQ1IsTUFBTTtLQUNOLFNBQVM7S0FDVCxZQUFZLElBQUksS0FBa0I7S0FDbkM7VUFDSTtBQUNMLFVBQU0sSUFBSSxNQUFNLDZCQUE2Qjs7O0VBSWpELEFBQVEsZUFBb0M7RUFDNUMsSUFBSSxZQUFZLGFBQTJCO0FBQ3pDLFFBQUssZUFBZTs7RUFFdEIsSUFBSSxjQUE0QjtBQUM5QixPQUFJLEtBQUssaUJBQWlCLE1BQU07QUFDOUIsVUFBTSxJQUFJLE1BQU0sa0NBQWtDOztBQUVwRCxVQUFPLEtBQUs7O0VBRWQsSUFBSSxjQUFzQjtBQUN4QixVQUFPLEtBQUssWUFBWSxNQUFNLEtBQUssSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEtBQUssSUFBSTs7RUFHckUsQUFBUSxZQUFtQztFQUMzQyxJQUFJLFNBQVMsVUFBMEI7QUFDckMsUUFBSyxZQUFZOztFQUVuQixJQUFJLFdBQTJCO0FBQzdCLE9BQUksS0FBSyxjQUFjLE1BQU07QUFDM0IsVUFBTSxJQUFJLE1BQU0sa0NBQWtDOztBQUVwRCxVQUFPLEtBQUs7O0VBR2QsQUFBUSxVQUF5QjtFQUNqQyxJQUFJLE9BQU8sUUFBZ0I7QUFDekIsUUFBSyxVQUFVOztFQUVqQixJQUFJLFNBQWlCO0FBQ25CLE9BQUksS0FBSyxZQUFZLE1BQU07QUFDekIsVUFBTSxJQUFJLE1BQU0sa0NBQWtDOztBQUVwRCxVQUFPLEtBQUs7O0VBR2QsQUFBUSxVQUErQjtFQUN2QyxJQUFJLE9BQU8sUUFBc0I7QUFDL0IsUUFBSyxVQUFVOztFQUVqQixJQUFJLFNBQXVCO0FBQ3pCLE9BQUksS0FBSyxZQUFZLE1BQU07QUFDekIsVUFBTSxJQUFJLE1BQU0sa0NBQWtDOztBQUVwRCxVQUFPLEtBQUs7O0VBR2QsQUFBZ0IsVUFBeUIsWUFBWTtFQUVyRCxBQUFRLFdBQWtDOzs7O0VBSTFDLElBQUksVUFBMEI7QUFDNUIsT0FBSSxDQUFDLEtBQUssVUFBVTtBQUNsQixVQUFNLElBQUksTUFBTSwwREFBMEQ7O0FBRTVFLFVBQU8sS0FBSzs7RUFHZCxBQUFRLFNBQThCOzs7O0VBSXRDLElBQUksUUFBc0I7QUFDeEIsT0FBSSxDQUFDLEtBQUssUUFBUTtBQUNoQixVQUFNLElBQUksTUFBTSwwRUFBMEU7O0FBRTVGLFVBQU8sS0FBSzs7RUFHZCxBQUFRLGFBQXFDO0VBQzdDLElBQUksWUFBNkI7QUFDL0IsT0FBSSxLQUFLLGVBQWUsTUFBTTtBQUM1QixVQUFNLElBQUksTUFBTSxrQ0FBa0M7O0FBR3BELFVBQU8sS0FBSzs7RUFHZCxBQUFRLFFBQXdDO0VBQ2hELElBQUksT0FBZ0M7QUFDbEMsT0FBSSxDQUFDLEtBQUssT0FBTztBQUNmLFVBQU0sSUFBSSxNQUFNLHdFQUF3RTs7QUFFMUYsVUFBTyxLQUFLOztFQUdkLEFBQVEsb0JBQTZDO0VBQ3JELElBQUksbUJBQTRDO0FBQzlDLFVBQU8sS0FBSzs7RUFFZCxJQUFJLGlCQUFpQixTQUFrQztBQUNyRCxRQUFLLG9CQUFvQjs7RUFJM0IsQUFBUSxvQkFBNkM7RUFFckQsQUFBaUIseUJBQXlCLElBQUksU0FFM0M7RUFDSCxJQUFJLG1CQUFxQztBQUN2QyxPQUFJLENBQUMsS0FBSyxtQkFBbUI7QUFDM0IsVUFBTSxJQUFJLE1BQU0sOENBQThDOztBQUVoRSxVQUFPLEtBQUs7O0VBRWQsSUFBSSxpQkFBaUIsU0FBa0M7QUFDckQsUUFBSyxvQkFBb0I7O0VBSTNCLEFBQU8sVUFBNEI7RUFFbkMsQUFBTyxTQUFpQztFQUV4QyxNQUFNLGlCQUFpQjtBQUNyQixTQUFNLEtBQUssS0FBSyxNQUFNLE9BQU8sV0FBVyxLQUFLOztFQUcvQyxNQUFNLEtBQ0osV0FBb0IsT0FDcEIsYUFBc0IsTUFDdEIsYUFDQSxhQUFzQixPQUN0QjtBQUNBLFFBQUssYUFBYTtBQUVsQixPQUFJLEtBQUssZUFBZTtBQUN0Qjs7R0FHRixNQUFNLFlBQVksWUFBWSxLQUFLO0dBR25DLE1BQU0sRUFBRSxvQkFBb0IsTUFBTSxPQUFPO0FBQ3pDLFFBQUssY0FBYyxlQUFlLGlCQUFpQjtHQUduRCxNQUFNLGNBQWMsWUFBWSxLQUFLO0dBQ3JDLE1BQU0sRUFBRSxlQUFlLE1BQU0sT0FBTztBQUNwQyxRQUFLLFNBQVMsTUFBTSxXQUFXLEtBQUssWUFBWTtHQUNoRCxNQUFNLGFBQWEsWUFBWSxLQUFLLEdBQUc7QUFDdkMsZUFBWSxLQUFLLE9BQU8sS0FBSztBQUU3QixRQUFLLE9BQU8sU0FBUyxXQUFXLEtBQUssT0FBTyxTQUFTLFlBQVk7QUFDakUsUUFBSyxPQUFPLFNBQVMsZUFBZSxTQUFTLEtBQUssT0FBTyxTQUFTLFlBQVk7R0FHOUUsTUFBTSxFQUFFLHFCQUFxQixNQUFNLE9BQU87QUFDMUMsT0FBSSxLQUFLLE9BQU8sWUFBWSxPQUFPO0FBQ2pDLFVBQU0saUJBQWlCLEVBQ3JCLEdBQUcsS0FBSyxPQUFPLFNBQ2hCLENBQUM7O0dBSUosTUFBTSxFQUFFLGFBQU8sTUFBTSxPQUFPO0FBQzVCLFFBQUssV0FBV0EsS0FBRyxpQkFBaUIsS0FBSyxPQUFPLFNBQVM7QUFDekQsUUFBRyxVQUFVLEtBQUssU0FBUztHQUszQixNQUFNLEVBQUUsa0JBQWtCLE1BQU0sT0FBTztBQUN2QyxTQUFNLGNBQWMsU0FBUyxTQUFTO0FBR3RDLFNBQU0sS0FBSyxnQkFBZ0IsS0FBSyxPQUFPLE9BQU8sT0FBTyxXQUFXO0dBR2hFLE1BQU0sYUFBYSxLQUFLLE9BQU8sT0FBTztBQUN0QyxPQUFJLFlBQVk7SUFFZCxNQUFNLHNCQUFzQixNQUFNLHFCQUFxQixXQUFXO0lBR2xFLE1BQU0sRUFBRSxlQUFlLE1BQU0sT0FBTztJQUNwQyxNQUFNLEVBQUUsc0JBQXNCLE1BQU0sT0FBTztJQUUzQyxNQUFNQyxjQUFpQztLQUNyQyxVQUFVLG1CQUFtQjtLQUM3QixHQUFHO0tBQ0o7QUFDRCxTQUFLLFFBQVEsV0FBVyxZQUFZOztBQUl0QyxPQUFJLFlBQVk7QUFDZCxTQUFLLGdCQUFnQjtBQUNyQjs7QUFJRixTQUFNLEtBQUssb0JBQW9CLEtBQUssT0FBTyxNQUFNO0dBR2pELE1BQU0sRUFBRSxXQUFXLE1BQU0sT0FBTztBQUNoQyxRQUFLLFNBQVMsSUFBSSxRQUFRO0FBRzFCLFNBQU0sS0FBSyxPQUFPLGVBQWU7QUFDakMsU0FBTSxLQUFLLE9BQU8sZ0JBQWdCO0FBQ2xDLFNBQU0sS0FBSyxPQUFPLGNBQWM7QUFDaEMsU0FBTSxLQUFLLE9BQU8sbUJBQW1CO0dBQ3JDLE1BQU0sRUFBRSxvQkFBb0IsTUFBTSxPQUFPO0FBQ3pDLFNBQU0sZ0JBQWdCLFVBQVU7QUFDaEMsU0FBTSxLQUFLLE9BQU8sbUJBQW1CO0dBRXJDLE1BQU0sRUFBRSxTQUFTLFFBQVEsc0JBQXNCLE1BQU0sT0FBTztBQUM1RCxPQUFJLFNBQVMsSUFBSSxDQUFDLFFBQVEsSUFBSSxtQkFBbUIsSUFBSSxZQUFZO0FBQy9ELFVBQU0sS0FBSyxPQUFPLE1BQU07QUFDeEIsVUFBTSxLQUFLLGNBQWM7O0FBRzNCLFFBQUssZ0JBQWdCO0FBQ3JCLFFBQUssZUFBZSxZQUFZLEtBQUssR0FBRztBQUN4QyxRQUFLLGlCQUFpQjs7RUFHeEIsQUFBUSxlQUFlO0VBQ3ZCLEFBQVEsaUJBQWlCO0VBRXpCLE1BQU0sYUFBYSxhQUE0RDtBQUM3RSxPQUFJLENBQUMsS0FBSyxlQUFlO0FBQ3ZCLFVBQU0sS0FBSyxLQUFLLGFBQWEsVUFBVSxhQUFhLFdBQVc7O0dBR2pFLE1BQU0sVUFBVSxLQUFLLE9BQU87R0FDNUIsTUFBTSxFQUFFLFNBQVMsWUFBWSxNQUFNLE9BQU87R0FDMUMsTUFBTSxFQUFFLDRCQUE0QixNQUFNLE9BQU87R0FDakQsTUFBTSxTQUFTLFFBQVE7SUFDckIsR0FBRyxRQUFRO0lBQ1gsUUFDRSxLQUFLLE9BQU8sWUFBWSxRQUNwQix3QkFBd0IsRUFDdEIsVUFBVSxLQUFLLE9BQU8sU0FBUyxtQkFBbUIsQ0FBQyxVQUFVLEVBQzlELENBQUMsR0FDRjtJQUNQLENBQUM7QUFDRixRQUFLLFNBQVM7QUFDZCxRQUFLLG1CQUFtQixJQUFJLGlCQUFpQixRQUFRLFVBQVU7QUFHL0QsT0FBSSxRQUFRLFNBQVM7SUFDbkIsTUFBTSxFQUFFLG1CQUFtQixNQUFNLE9BQU87QUFDeEMsU0FBSyxXQUFXLElBQUksZUFBZSxRQUFRLFFBQVE7O0FBSXJELE9BQUksUUFBUSxTQUFTO0FBQ25CLFVBQU0sS0FBSyxnQkFBZ0IsUUFBUSxRQUFRLFFBQVE7O0FBR3JELE9BQUksUUFBUSxNQUFNO0FBQ2hCLFVBQU0sS0FBSyxtQkFBbUIsUUFBUSxRQUFRLEtBQUs7O0FBSXJELFNBQU0sS0FBSyxZQUFZLFFBQVEsUUFBUSxXQUFXO0lBQ2hELFlBQVksYUFBYTtJQUN6QixVQUFVLGFBQWE7SUFDeEIsQ0FBQztBQUdGLFNBQU0sS0FBSyxLQUFLLFFBQVEsUUFBUTtBQUVoQyxPQUFJLENBQUMsYUFBYSxVQUFVO0FBQzFCLFNBQUsscUJBQXFCOztBQUc1QixVQUFPOztFQUdULE1BQU0sWUFDSixRQUNBLFFBQ0EsU0FJQTtBQUNBLE9BQUksQ0FBQyxLQUFLLGVBQWU7QUFDdkIsVUFBTSxLQUFLLEtBQUssU0FBUyxVQUFVLFNBQVMsV0FBVzs7QUFHekQsUUFBSyxTQUFTO0FBQ2QsUUFBSyxxQkFBcUIsSUFBSSxpQkFBaUIsS0FBSyxPQUFPLE9BQU8sVUFBVTtHQUc1RSxNQUFNLFdBQVcsS0FBSyxPQUFPLElBQUk7QUFDakMsT0FBSSxVQUFVO0lBSVosTUFBTSxFQUFFLHFCQUFxQixNQUFNLE9BQU87SUFHMUMsTUFBTSxpQkFBaUI7SUFLdkIsTUFBTSxjQUFjO0FBRXBCLFdBQU8sb0JBQW9CLFlBQVk7QUFDckMsWUFBTyxLQUFLLFVBQVUsVUFBVSxNQUFNLFVBQVU7QUFDOUMsVUFBSSxPQUFPLFVBQVUsWUFBWSxlQUFlLEtBQUssTUFBTSxFQUFFO0FBQzNELGNBQU8saUJBQ0wsSUFBSSxLQUFLLE1BQU0sRUFDZixVQUNBLFlBQ0Q7O0FBRUgsYUFBTztPQUNQO01BQ0Y7O0FBS0osVUFBTyxJQUNMLEdBQUcsS0FBSyxPQUFPLElBQUksTUFBTSxPQUFPLFVBQ2hDLE9BQU8sVUFBVSxXQUE2QztBQUM1RCxXQUFPLEtBQUssT0FBTztLQUV0QjtBQUdELFVBQU8sSUFDTCxHQUFHLEtBQUssT0FBTyxJQUFJLE1BQU0sT0FBTyxlQUNoQyxPQUFPLFVBQVUsV0FBNEI7QUFDM0MsV0FBTztLQUVWO0dBR0QsTUFBTSxFQUFFLFlBQVksTUFBTSxPQUFPO0FBQ2pDLE9BQUksU0FBUyxFQUFFO0lBQ2IsTUFBTSxFQUFFLHNCQUFzQixNQUFNLE9BQU87QUFDM0MsV0FBTyxTQUFTLGtCQUFrQjs7QUFJcEMsT0FBSSxTQUFTLElBQUksS0FBSyxPQUFPLE1BQU0sV0FBVyxTQUFTO0lBQ3JELE1BQU0sRUFBRSwwQkFBMEIsTUFBTSxPQUFPO0FBQy9DLFVBQU0sc0JBQXNCLFFBQVEsS0FBSyxPQUFPLEtBQUssVUFBVTs7R0FHakUsTUFBTSxVQUFVLEtBQUssS0FBSyxLQUFLLGFBQWEsTUFBTTtHQUNsRCxNQUFNLFNBQVMsTUFBTSxPQUFPLFFBQVE7R0FHcEMsTUFBTSxpQkFBaUIsS0FBSyxPQUFPLE9BQU8sU0FBUztHQUNuRCxNQUFNQyx3QkFBcUQsaUJBQ3ZELG1CQUFtQixPQUNqQjtJQUFFLFdBQVc7SUFBTSxXQUFXO0tBQUM7S0FBTTtLQUFRO0tBQVU7SUFBRSxHQUN6RDtJQUNFLFdBQVcsZUFBZTtJQUMxQixXQUFXLGVBQWU7SUFDMUIsYUFBYSxlQUFlO0lBQzdCLEdBQ0g7QUFFSixPQUFJLFNBQVMsRUFBRTtJQUdiLE1BQU0sdUJBQXVCLFFBQVEsSUFBSSxrQ0FBa0M7QUFDM0UsUUFBSSxVQUFVLENBQUMsc0JBQXNCO0FBQ25DLFdBQU0sS0FBSyx1QkFBdUIsUUFBUSxTQUFTLE9BQU87V0FDckQ7QUFDTCxVQUFLLGVBQWUsUUFBUSxPQUFPOztVQUVoQztBQUVMLFNBQUssTUFBTSxPQUFPLEtBQUssT0FBTyxNQUFNO0FBQ2xDLFNBQUksS0FBSyxPQUFPLE9BQU8sSUFBSSxlQUFlLFdBQVc7QUFDbkQsWUFBTSxJQUFJLE1BQU0sa0JBQWtCLElBQUksWUFBWTs7QUFJcEQsU0FBSSxJQUFJLGtCQUFrQjtBQUN4QixhQUFPLE1BQU07T0FDWCxRQUFRO09BQ1IsS0FBSyxLQUFLLE9BQU8sSUFBSSxNQUFNLFNBQVMsSUFBSTtPQUN4QyxTQUFTLEtBQUssdUNBQXVDO09BQ3JELFdBQVcsS0FBSyx1QkFBdUIsS0FBSyxPQUFPO09BQ3BELENBQUM7QUFDRjs7QUFHRixZQUFPLE1BQU07TUFDWCxRQUFRLElBQUksUUFBUSxjQUFjO01BQ2xDLEtBQUssS0FBSyxPQUFPLElBQUksTUFBTSxTQUFTLElBQUk7TUFDeEMsU0FBUyxLQUFLLGlCQUFpQixLQUFLLE9BQU87TUFDM0MsVUFBVSx3QkFBd0IsSUFBSSxRQUFRLFVBQVUsc0JBQXNCO01BQy9FLENBQUM7O0FBS0osVUFBTSxLQUFLLHFCQUFxQixRQUFRLFFBQVEsc0JBQXNCOzs7Ozs7Ozs7O0VBVzFFLEFBQVEsb0JBQ04sU0FDQSxRQUM2RTtHQUM3RSxNQUFNLGFBQWEsS0FBSyxlQUFlLFFBQVE7QUFFL0MsT0FBSSxDQUFDLFlBQVk7QUFDZixVQUFNLElBQUksa0JBQWtCLEdBQUcscUJBQXFCLENBQUM7O0FBSXZELE9BQUksV0FBVyxrQkFBa0I7QUFDL0IsV0FBTyxLQUFLLHVDQUF1Qzs7QUFHckQsVUFBTyxLQUFLLGlCQUFpQixZQUFZLE9BQU87O0VBR2xELEFBQVEsZUFBZSxTQUFrRDtHQUN2RSxNQUFNLE1BQU0sS0FBSyxtQkFBbUIsUUFBUSxJQUFJO0dBQ2hELE1BQU0sU0FBUyxRQUFRO0FBRXZCLE9BQUksQ0FBQyxJQUFJLFdBQVcsS0FBSyxPQUFPLElBQUksTUFBTSxPQUFPLEVBQUU7QUFDakQsV0FBTzs7QUFHVCxVQUFPLEtBQUssT0FBTyxLQUFLLE1BQU0sUUFBUTtBQUNwQyxRQUFJLEtBQUssT0FBTyxPQUFPLElBQUksZUFBZSxXQUFXO0FBQ25ELFlBQU87O0lBRVQsTUFBTSxZQUFZLElBQUksUUFBUSxjQUFjO0FBQzVDLFFBQUksY0FBYyxPQUFRLFFBQU87SUFFakMsTUFBTSxXQUFXLEtBQUssT0FBTyxJQUFJLE1BQU0sU0FBUyxJQUFJO0FBQ3BELFdBQU8sS0FBSyxtQkFBbUIsVUFBVSxJQUFJO0tBQzdDOzs7Ozs7RUFPSixBQUFRLGVBQ04sUUFDQSxRQUNNO0FBRU4sVUFBTyxNQUFNO0lBQ1gsUUFBUTtJQUNSLEtBQUssR0FBRyxLQUFLLE9BQU8sSUFBSSxNQUFNLE9BQU87SUFDckMsU0FBUyxPQUFPLFNBQVMsVUFBVTtLQUNqQyxNQUFNLFVBQVUsS0FBSyxvQkFBb0IsU0FBUyxPQUFPO0FBQ3pELFNBQUksU0FBUztBQUNYLGFBQU8sUUFBUSxTQUFTLE1BQU07O0FBR2hDLFdBQU0sSUFBSSxrQkFBa0IsR0FBRyxxQkFBcUIsQ0FBQzs7SUFFdkQsV0FBVyxPQUFPLFlBQVksWUFBWTtBQUN4QyxXQUFNLEtBQUssMEJBQTBCLFdBQVcsUUFBUSxTQUFTLE9BQU87O0lBRTNFLENBQUM7QUFFRixVQUFPLE1BQU07SUFDWCxRQUFRO0tBQUM7S0FBUTtLQUFRO0tBQU87S0FBVTtLQUFRO0lBQ2xELEtBQUssR0FBRyxLQUFLLE9BQU8sSUFBSSxNQUFNLE9BQU87SUFDckMsU0FBUyxPQUFPLFNBQVMsVUFBVTtLQUNqQyxNQUFNLFVBQVUsS0FBSyxvQkFBb0IsU0FBUyxPQUFPO0FBQ3pELFNBQUksU0FBUztBQUNYLGFBQU8sUUFBUSxTQUFTLE1BQU07O0FBRWhDLFdBQU0sSUFBSSxrQkFBa0IsR0FBRyxxQkFBcUIsQ0FBQzs7SUFFeEQsQ0FBQzs7RUFHSixBQUFRLGFBQWtCOzs7OztFQU0xQixNQUFjLHVCQUNaLFFBQ0EsU0FDQSxRQUNlO0FBRWYsU0FBTSxPQUFPLFVBQVUsTUFBTSxPQUFPLG9CQUFvQixRQUFRO0dBRWhFLE1BQU0sT0FBTyxNQUFNLE9BQU87R0FFMUIsTUFBTSw2QkFBNkIsUUFBUSxLQUFLLE9BQU8sT0FBTyxTQUFTLEdBQUc7R0FDMUUsTUFBTSxNQUFNLGdDQUFnQztJQUMxQyxZQUFZLE9BQU87SUFDbkIsa0NBQWtDO0lBQ25DLENBQUM7QUFFRixRQUFLLGFBQWEsTUFBTSxLQUFLLGFBQWE7SUFDeEMsTUFBTTtJQUNOLFFBQVE7S0FDTixnQkFBZ0I7S0FDaEI7S0FDRDtJQUNELFNBQVM7SUFDVixDQUFDO0FBR0YsVUFBTyxLQUFLLEtBQUssS0FBSyxTQUFTO0FBRTdCLFFBQUksSUFBSSxLQUFLLFdBQVcsS0FBSyxPQUFPLElBQUksTUFBTSxPQUFPLElBQUksSUFBSSxLQUFLLFdBQVcsYUFBYSxFQUFFO0FBQzFGLFlBQU8sTUFBTTs7QUFHZixXQUFPLEtBQUssV0FBVyxZQUFZLEtBQUssS0FBSyxLQUFLO0tBQ2xEO0FBR0YsVUFBTyxNQUFNO0lBQ1gsUUFBUTtJQUNSLEtBQUssR0FBRyxLQUFLLE9BQU8sSUFBSSxNQUFNLE9BQU87SUFDckMsU0FBUyxPQUFPLFNBQVMsVUFBVTtLQUNqQyxNQUFNLFNBQVMsS0FBSyxvQkFBb0IsU0FBUyxPQUFPO0FBQ3hELFNBQUksUUFBUTtBQUNWLGFBQU8sT0FBTyxTQUFTLE1BQU07O0FBRS9CLFdBQU0sSUFBSSxrQkFBa0IsR0FBRyxxQkFBcUIsQ0FBQzs7SUFFdkQsV0FBVyxPQUFPLFlBQVksWUFBWTtBQUN4QyxXQUFNLEtBQUssMEJBQTBCLFdBQVcsUUFBUSxTQUFTLE9BQU87O0lBRTNFLENBQUM7QUFFRixVQUFPLE1BQU07SUFDWCxRQUFRO0tBQUM7S0FBUTtLQUFRO0tBQU87S0FBVTtLQUFRO0lBQ2xELEtBQUssR0FBRyxLQUFLLE9BQU8sSUFBSSxNQUFNLE9BQU87SUFDckMsU0FBUyxPQUFPLFNBQVMsVUFBVTtLQUNqQyxNQUFNLFNBQVMsS0FBSyxvQkFBb0IsU0FBUyxPQUFPO0FBQ3hELFNBQUksUUFBUTtBQUNWLGFBQU8sT0FBTyxTQUFTLE1BQU07O0FBRS9CLFdBQU0sSUFBSSxrQkFBa0IsR0FBRyxxQkFBcUIsQ0FBQzs7SUFFeEQsQ0FBQztBQUlGLFVBQU8sTUFBTTtJQUNYLFFBQVEsQ0FBQyxPQUFPLE9BQU87SUFDdkIsS0FBSztJQUNMLFNBQVMsT0FBTyxTQUFTLFVBQVU7S0FDakMsTUFBTSxNQUFNLFFBQVE7S0FHcEIsTUFBTSxFQUFFLGVBQWUsY0FBYyxNQUFNLE9BQU87S0FDbEQsTUFBTSxXQUFXLGNBQWMsSUFBSTtBQUNuQyxTQUFJLFVBQVU7QUFDWixjQUFRLElBQUksd0JBQXdCLFNBQVMsTUFBTSxPQUFPO01BQzFELE1BQU0sT0FBTyxNQUFNLFVBQ2pCLEtBQ0EsU0FBUyxPQUNULFNBQVMsUUFDVCxTQUNBLE9BQ0EsUUFDQSxLQUFLLFdBQ047QUFDRCxZQUFNLEtBQUssWUFBWTtBQUN2QixhQUFPOztBQUlULFNBQUk7TUFDRixNQUFNQyxPQUFLLE1BQU0sT0FBTztNQUN4QixJQUFJLFdBQVcsTUFBTUEsS0FBRyxTQUN0QixLQUFLLEtBQUssS0FBSyxXQUFXLE9BQU8sTUFBTSxhQUFhLEVBQ3BELFFBQ0Q7QUFDRCxpQkFBVyxNQUFNLEtBQUssV0FBVyxtQkFBbUIsS0FBSyxTQUFTO0FBRWxFLFlBQU0sS0FBSyxZQUFZO0FBQ3ZCLGFBQU87Y0FDQSxHQUFHO0FBQ1YsV0FBSyxXQUFXLGlCQUFpQixFQUFXO0FBQzVDLGNBQVEsTUFBTSxFQUFFO0FBQ2hCLFlBQU0sT0FBTyxJQUFJO0FBQ2pCLGFBQVEsRUFBWTs7O0lBR3pCLENBQUM7QUFHRixVQUFPLFFBQVEsV0FBVyxZQUFZO0FBQ3BDLFVBQU0sS0FBSyxXQUFXLE9BQU87S0FDN0I7R0FFRixNQUFNQyxXQUFTLE1BQU0sT0FBTyxVQUFVO0FBQ3RDLE9BQUksVUFBVSxLQUFLO0FBQ2pCLFlBQVEsSUFDTkEsUUFBTSxJQUNKLDZDQUE2QyxJQUFJLEtBQUssdUNBQ3ZELENBQ0Y7O0FBRUgsV0FBUSxJQUFJQSxRQUFNLElBQUksK0JBQStCLENBQUM7O0VBR3hELE1BQWMscUJBQ1osUUFDQSxRQUNBLHVCQUNlO0dBRWYsTUFBTSxjQUFjLEtBQUssS0FBSyxLQUFLLGFBQWEsWUFBWSxTQUFTO0dBQ3JFLE1BQU0sVUFBVSxLQUFLLEtBQUssS0FBSyxhQUFhLFlBQVksU0FBUztHQUNqRSxNQUFNLGVBQWUsS0FBSyxLQUFLLFNBQVMsNEJBQTRCO0dBQ3BFLE1BQU0sZ0JBQWdCLEtBQUssS0FBSyxLQUFLLGFBQWEsUUFBUSxPQUFPLFlBQVk7QUFFN0UsT0FBSSxDQUFFLE1BQU0sT0FBTyxZQUFZLEVBQUc7QUFDaEMsWUFBUSxLQUFLLHlCQUF5QixjQUFjO0FBQ3BEOztHQUlGLE1BQU0sZUFBZSxNQUFNLE9BQU8sYUFBYTtBQUUvQyxPQUFJLENBQUMsY0FBYztBQUNqQixZQUFRLEtBQUssMEJBQTBCLGVBQWU7QUFDdEQsWUFBUSxLQUFLLDhDQUE4Qzs7QUFJN0QsT0FBSSxjQUFjO0FBQ2hCLFFBQUksTUFBTSxPQUFPLGNBQWMsRUFBRTtBQUkvQixXQUFNLE9BQU87QUFDYixhQUFRLElBQUksc0JBQXNCO1dBQzdCO0FBQ0wsYUFBUSxLQUFLLDJCQUEyQixnQkFBZ0I7OztBQUs1RCxVQUFPLElBQUkscUJBQXFCLE9BQU8sU0FBUyxVQUFVO0lBQ3hELE1BQU0sZ0JBQWlCLFFBQVEsT0FBZ0M7SUFDL0QsTUFBTSxZQUFZLEtBQUssS0FBSyxhQUFhLFNBQVM7SUFDbEQsTUFBTSxlQUFlLEtBQUsseUJBQXlCLFdBQVcsY0FBYztBQUM1RSxRQUFJLGlCQUFpQixNQUFNO0FBQ3pCLFdBQU0sT0FBTyxJQUFJLENBQUMsTUFBTTtBQUN4Qjs7SUFFRixNQUFNLDBCQUEwQixLQUFLLFNBQVMsV0FBVyxhQUFhLENBQUMsUUFBUSxPQUFPLElBQUk7SUFFMUYsTUFBTSxZQUFZLFdBQVc7SUFHN0IsTUFBTSxnQ0FBb0Q7S0FDeEQsTUFBTUMsV0FBZ0M7TUFDcEMsTUFBTTtNQUNOLEtBQUssUUFBUTtNQUNiLE1BQU07TUFDTixRQUFRLFFBQVE7TUFDakI7QUFHRCxTQUFJLE9BQU8scUJBQXFCO01BQzlCLE1BQU0sU0FBUyxPQUFPLG9CQUFvQixTQUFTO0FBQ25ELFVBQUksT0FBUSxRQUFPOztBQUlyQixZQUFPLGFBQWE7O0FBSXRCLFFBQUksOEJBQThCLEtBQUssd0JBQXdCLEVBQUU7S0FDL0QsTUFBTSxNQUFNLHdCQUF3QixNQUFNLElBQUksQ0FBQyxLQUFLO0tBQ3BELE1BQU0sUUFBUSxNQUFNLEdBQUcsUUFBUSxVQUFVO0tBQ3pDLE1BQU0sY0FBYyxNQUFNLE1BQU0sTUFBTSxFQUFFLFdBQVcsU0FBUyxJQUFJLEVBQUUsU0FBUyxJQUFJLE1BQU0sQ0FBQztBQUV0RixTQUFJLGFBQWE7TUFDZixNQUFNQyxhQUFXLEtBQUssS0FBSyxXQUFXLFlBQVk7TUFDbEQsTUFBTSxVQUFVLE1BQU0sR0FBRyxTQUFTQSxXQUFTO0FBQzNDLFlBQU0sS0FBSyxRQUFRLE9BQU8sMkJBQTJCLFdBQVc7QUFDaEUsd0JBQWtCLE9BQU8seUJBQXlCLENBQUM7QUFDbkQsYUFBTyxNQUFNLEtBQUssUUFBUTs7O0lBSzlCLE1BQU0sV0FBVztBQUNqQixRQUFJLE1BQU0sT0FBTyxTQUFTLEVBQUU7S0FDMUIsTUFBTSxVQUFVLE1BQU0sR0FBRyxTQUFTLFNBQVM7S0FDM0MsTUFBTSxNQUFNLHdCQUF3QixNQUFNLElBQUksQ0FBQyxLQUFLO0FBQ3BELFdBQU0sS0FBSyxRQUFRLE9BQU8sMkJBQTJCLFFBQVEsUUFBUSxhQUFhLEdBQUc7QUFDckYsU0FBSSx3QkFBd0IsU0FBUyxJQUFJLEVBQUU7QUFDekMsd0JBQWtCLE9BQU8seUJBQXlCLENBQUM7O0FBRXJELFlBQU8sTUFBTSxLQUFLLFFBQVE7O0FBRzVCLFVBQU0sT0FBTyxJQUFJLENBQUMsTUFBTTtLQUN4QjtBQUdGLE9BQUksY0FBYztJQUNoQixNQUFNLEVBQUUsaUJBQWlCLE1BQU0sT0FBTztJQUN0QyxNQUFNLEVBQUUsY0FBYyxNQUFNLE9BQU87SUFDbkMsTUFBTSxZQUFZLGNBQWM7QUFFaEMsU0FBSyxNQUFNLFNBQVMsV0FBVztBQUM3QixZQUFPLE1BQU07TUFDWCxRQUFRLENBQUMsT0FBTyxPQUFPO01BQ3ZCLEtBQUssTUFBTTtNQUNYLFVBQVUsd0JBQXdCLE1BQU0sWUFBWSxNQUFNLHNCQUFzQjtNQUNoRixTQUFTLE9BQU8sU0FBUyxVQUFVO09BQ2pDLE1BQU0sTUFBTSxRQUFRO0FBQ3BCLGVBQVEsSUFBSSx3QkFBd0IsTUFBTSxPQUFPO09BRWpELE1BQU0sU0FBUyxLQUFLLGtCQUFrQixNQUFNLE1BQU0sSUFBSTtPQUN0RCxNQUFNLE9BQU8sTUFBTSxVQUFVLEtBQUssT0FBTyxRQUFRLFNBQVMsT0FBTyxPQUFPO0FBRXhFLGFBQU0sS0FBSyxZQUFZO0FBQ3ZCLGNBQU87O01BRVYsQ0FBQzs7O0FBS04sVUFBTyxNQUFNO0lBQ1gsUUFBUSxDQUFDLE9BQU8sT0FBTztJQUN2QixLQUFLO0lBQ0wsU0FBUyxPQUFPLFNBQVMsVUFBVTtBQUVqQyxTQUFJLFFBQVEsSUFBSSxXQUFXLE9BQU8sSUFBSSxRQUFRLElBQUksV0FBVyxhQUFhLEVBQUU7QUFDMUUsWUFBTSxPQUFPLElBQUksQ0FBQyxNQUFNO0FBQ3hCOztBQUlGLFNBQUksT0FBTyxxQkFBcUI7TUFDOUIsTUFBTUMsY0FBbUM7T0FDdkMsTUFBTTtPQUNOLEtBQUssUUFBUTtPQUNiLE1BQU0sUUFBUSxJQUFJLE1BQU0sSUFBSSxDQUFDO09BQzdCLFFBQVEsUUFBUTtPQUNqQjtNQUNELE1BQU0saUJBQWlCLE9BQU8sb0JBQW9CLFlBQVk7QUFFOUQsVUFBSSxnQkFBZ0I7QUFDbEIseUJBQWtCLE9BQU8sZUFBZTs7O0tBSzVDLE1BQU0sY0FBYyxLQUFLLG1CQUFtQixRQUFRLElBQUk7S0FDeEQsTUFBTSxlQUFlLEtBQUsseUJBQXlCLGFBQWEsWUFBWTtBQUM1RSxTQUFJLGlCQUFpQixNQUFNO0FBQ3pCLFlBQU0sT0FBTyxJQUFJLENBQUMsTUFBTTtBQUN4Qjs7QUFFRixTQUFJLE1BQU0sV0FBVyxhQUFhLEVBQUU7TUFDbEMsTUFBTSxVQUFVLE1BQU0sR0FBRyxTQUFTLGFBQWE7QUFDL0MsYUFBTyxNQUFNLEtBQUtDLE9BQVcsYUFBYSxJQUFJLDJCQUEyQixDQUFDLEtBQUssUUFBUTs7S0FJekYsTUFBTSxZQUFZLEtBQUssS0FBSyxhQUFhLGFBQWE7QUFDdEQsWUFBTyxNQUFNLEtBQUssWUFBWSxDQUFDLEtBQUssTUFBTSxHQUFHLFNBQVMsV0FBVyxRQUFRLENBQUM7O0lBRTdFLENBQUM7QUFFRixXQUFRLElBQUksdUNBQXVDLGVBQWUsUUFBUSxXQUFXLFVBQVU7O0VBR2pHLGlCQUNFLEtBQ0EsUUFDb0U7QUFDcEUsVUFBTyxPQUFPLFNBQXlCLFVBQTBDO0lBRS9FLE1BQU1DLFVBQW1CLE1BQU0sS0FBSyxjQUFjLFFBQVEsU0FBUyxNQUFNO0FBRXpFLFdBQU8sS0FBSyxrQkFBa0IsSUFBSSxFQUFFLFNBQVMsRUFBRSxZQUFZO0FBRXpELGVBQVU7TUFDUixRQUFRLElBQUksUUFBUTtNQUNwQjtNQUNBO01BQ0E7TUFDRCxDQUFDO0tBR0YsTUFBTSxFQUFFLHdCQUF3QixNQUFNLE9BQU87S0FDN0MsTUFBTSxVQUFVLG9CQUFvQixLQUFLLEtBQUssT0FBTyxNQUFNO0tBRzNELE1BQU0sUUFBUSxJQUFJLFFBQVEsZUFBZSxRQUFRLFVBQVU7S0FDM0QsSUFBSUM7S0FJSixNQUFNQyxRQUdGO01BQ0YsZUFBZSxFQUFFO01BQ2pCLGVBQWUsRUFBRTtNQUNsQjtBQUVELFNBQUk7TUFDRixNQUFNLE9BQVEsUUFBUSxVQUFVLEVBQUU7QUFDbEMsVUFBSSxJQUFJLGVBQWU7T0FDckIsTUFBTSxRQUFRLFFBQVEsTUFBTSxFQUMxQixRQUFRLElBQUksY0FBYyxRQUMzQixDQUFDO09BR0YsTUFBTUMsU0FBaUMsRUFBRTtBQUV6QyxXQUFJLElBQUksY0FBYyxZQUFZLFlBQVksQ0FBQyxJQUFJLGNBQWMsU0FBUztBQUV4RSxtQkFBVyxNQUFNLFFBQVEsT0FBTztBQUM5QixhQUFJLEtBQUssU0FBUyxRQUFRO1VBR3hCLE1BQU0sU0FBUyxNQUFNLEtBQUssVUFBVTtBQUNwQyxnQkFBTSxjQUFjLEtBQUssSUFBSSxhQUFhLE1BQU0sT0FBTyxDQUFDO29CQUMvQyxLQUFLLFNBQVMsU0FBUztBQUNoQyxpQkFBTyxLQUFLLGFBQWEsT0FBTyxLQUFLLE1BQU07OztrQkFHdEMsSUFBSSxjQUFjLFlBQVksVUFBVTtRQUVqRCxNQUFNLFdBQVcsSUFBSSxjQUFjO1FBQ25DLE1BQU0sT0FBTyxLQUFLLFFBQVEsSUFBSSxTQUFTO1FBR3ZDLE1BQU1DLGVBQ0osSUFBSSxjQUFjLGdCQUNsQixLQUFLLE9BQU8sT0FBTyxTQUFTLGdCQUM1QjtBQUVGLG1CQUFXLE1BQU0sUUFBUSxPQUFPO0FBQzlCLGFBQUksS0FBSyxTQUFTLFFBQVE7VUFDeEIsTUFBTSxNQUFNLE1BQU0sYUFBYTtXQUM3QixVQUFVLEtBQUs7V0FDZixVQUFVLEtBQUs7V0FDaEIsQ0FBQztBQUVGLGdCQUFNLEtBQUssVUFBVSxLQUFLLEtBQUssTUFBTSxFQUNuQyxhQUFhLEtBQUssVUFDbkIsQ0FBQztVQUVGLE1BQU0sTUFBTSxNQUFNLEtBQUssT0FBTyxJQUFJO1VBQ2xDLE1BQU0sWUFBWSxNQUFNLEtBQUssYUFBYSxJQUFJO0FBRTlDLGdCQUFNLGNBQWMsS0FDbEIsSUFBSSxhQUFhO1dBQ2YsVUFBVSxLQUFLO1dBQ2YsVUFBVSxLQUFLO1dBQ2YsTUFBTSxLQUFLLEtBQUs7V0FDaEI7V0FDQTtXQUNBO1dBQ0E7V0FDRCxDQUFDLENBQ0g7b0JBQ1EsS0FBSyxTQUFTLFNBQVM7QUFDaEMsaUJBQU8sS0FBSyxhQUFhLE9BQU8sS0FBSyxNQUFNOzs7O09BTWpELE1BQU0sS0FBSyxNQUFNLE9BQU87T0FDeEIsTUFBTSxTQUFTLEdBQUcsUUFBUSxNQUFNLE9BQU87QUFDdkMsY0FBTyxPQUFPLE1BQU0sT0FBTzs7TUFHN0IsTUFBTSxFQUFFLGtCQUFrQixNQUFNLE9BQU87QUFDdkMsZ0JBQVUsY0FBYyxRQUFRLENBQUMsTUFBTSxLQUFLO2NBQ3JDLEdBQUc7TUFDVixNQUFNLEVBQUUsYUFBYSxNQUFNLE9BQU87QUFDbEMsVUFBSSxhQUFhLFVBQVU7T0FDekIsTUFBTSxFQUFFLHFCQUFxQixNQUFNLE9BQU87T0FDMUMsTUFBTSxXQUFXLGlCQUFpQixFQUFFLENBQ2pDLEtBQUssVUFBVSxNQUFNLFFBQVEsQ0FDN0IsS0FBSyxJQUFJO09BQ1osTUFBTSxFQUFFLHdCQUF3QixNQUFNLE9BQU87QUFDN0MsYUFBTSxJQUFJLG9CQUFvQixVQUE2QixFQUN6RCxVQUFVLEdBQ1gsQ0FBQzthQUNHO0FBQ0wsYUFBTTs7O0FBS1YsV0FBTSxLQUFLLElBQUksUUFBUSxlQUFlLG1CQUFtQjtLQUd6RCxNQUFNLGlCQUFpQixLQUFLLG1CQUFtQixLQUFLLFNBQVMsT0FBTztBQUNwRSxTQUFJLGdCQUFnQjtBQUNsQix3QkFBa0IsT0FBTyxlQUFlOztBQUkxQyxTQUFJLElBQUksZUFBZTtNQUNyQixNQUFNLFVBQVUsSUFBSSxjQUFjLFdBQVc7QUFDN0MsVUFBSSxZQUFZLFVBQVU7QUFDeEIsZUFBUSxnQkFBZ0IsTUFBTTtpQkFDckIsWUFBWSxVQUFVO0FBQy9CLGVBQVEsZ0JBQWdCLE1BQU07OztLQUtsQyxNQUFNLEVBQUUsaUJBQWlCLE1BQU0sT0FBTztLQUN0QyxNQUFNLE9BQU8sSUFBSSxXQUFXLEtBQUssVUFBVTtBQUV6QyxVQUFJLGFBQWEsVUFBVSxNQUFNLEtBQUssRUFBRTtBQUN0QyxjQUFPO2FBQ0Y7QUFDTCxjQUFPLFFBQVEsTUFBTTs7T0FFdkI7QUFFRixZQUFPLEtBQUssa0JBQWtCLEtBQUssTUFBTSxNQUFNO01BQy9DOzs7RUFLTixBQUFRLHdDQUF3QztBQUM5QyxVQUFPLE9BQU8sVUFBMEIsVUFBdUM7QUFDN0UsVUFBTSxPQUFPLGNBQWMsVUFBVSxDQUFDLE9BQU8sV0FBVyxZQUFZLENBQUMsT0FBTyxJQUFJLENBQUMsS0FBSyxFQUNwRixTQUFTLDhCQUNWLENBQUM7OztFQUtOLE1BQWMsMEJBQ1osUUFDQSxTQUNBLFFBQ2U7R0FDZixNQUFNLGFBQWEsS0FBSyxlQUFlLFFBQVE7QUFDL0MsT0FBSSxDQUFDLFlBQVksa0JBQWtCO0lBQ2pDLE1BQU0sZUFBZSxLQUFLLGlCQUFpQixvQkFBb0Isd0JBQXdCLEVBQ3JGLFNBQVMsUUFBUSxTQUNsQixDQUFDO0FBQ0YsU0FBSyxpQkFBaUIsb0JBQW9CLEtBQUs7S0FDN0MsTUFBTTtLQUNOLE9BQU87S0FDUCxRQUFRO01BQ04sUUFBUTtNQUNSLE1BQU0sUUFBUTtNQUNmO0tBQ0QsU0FBUyxhQUFhO0tBQ3RCLFFBQVEsYUFBYTtLQUNyQixjQUFjLGFBQWE7S0FDM0IsU0FBUyxhQUFhO0tBQ3ZCLENBQUM7QUFDRixXQUFPLE1BQU0sTUFBTSw0QkFBNEI7QUFDL0M7O0dBR0YsTUFBTSxVQUFVLEtBQUssdUJBQXVCLFlBQVksT0FBTztBQUMvRCxTQUFNLFFBQVEsRUFBRSxRQUFRLEVBQUUsUUFBUTs7RUFRcEMsQUFBUSx1QkFBdUIsS0FBa0IsUUFBNkI7QUFDNUUsVUFBTyxPQUNMLFlBR0EsWUFDa0I7SUFDbEIsTUFBTSxTQUFTLFdBQVc7SUFDMUIsSUFBSUMsWUFBcUM7SUFDekMsSUFBSUMsUUFBbUU7SUFDdkUsSUFBSUMsbUJBQStEO0lBQ25FLElBQUlDLGVBQW9ELEVBQUU7QUFFMUQsUUFBSTtBQUNGLG9CQUFlLEtBQUssaUJBQWlCLG9CQUFvQix3QkFBd0IsRUFDL0UsU0FBUyxRQUFRLFNBQ2xCLENBQUM7QUFDRixlQUFVO01BQ1IsUUFBUSxJQUFJLFFBQVE7TUFDcEI7TUFDQTtNQUNBO01BQ0QsQ0FBQztBQUVGLHdCQUFtQjtLQUNuQixNQUFNLFVBQVUsTUFBTSxLQUFLLDRCQUE0QixLQUFLLFFBQVE7QUFDcEUsd0JBQW1CO0FBQ25CLGFBQVEsS0FBSyxpQkFBaUIsbUJBQW1CLFFBQVE7TUFDdkQsV0FBVyxJQUFJLGlCQUFrQjtNQUNqQyxVQUFVLElBQUksaUJBQWtCO01BQ2hDLFdBQVcsSUFBSSxpQkFBa0I7TUFDakMsV0FBVyxJQUFJLGlCQUFrQjtNQUNqQyxRQUFRO01BQ1IsU0FBUyxhQUFhO01BQ3RCLFFBQVEsYUFBYTtNQUNyQixjQUFjLGFBQWE7TUFDM0IsU0FBUyxhQUFhO01BQ3ZCLENBQUM7S0FFRixNQUFNLFdBQVcsS0FBSyxnQ0FBZ0MsYUFBYSxVQUFVO0FBQzdFLGlCQUFZLE1BQU0sS0FBSyx1QkFBdUIsUUFBUSxTQUFTLFNBQVM7QUFDeEUsVUFBSyxpQkFBaUIsbUJBQW1CLE1BQU0sR0FBRztBQUNsRCx3QkFBbUI7S0FFbkIsTUFBTSxFQUFFLGlCQUFpQixNQUFNLE9BQU87S0FDdEMsTUFBTSxPQUFPLElBQUksV0FBVyxLQUFLLFVBQVU7QUFDekMsVUFBSSxhQUFhLFVBQVUsTUFBTSxLQUFLLEVBQUU7QUFDdEMsY0FBTzs7QUFHVCxhQUFPLFFBQVEsTUFBTTtPQUNyQjtBQUVGLFdBQU0sS0FBSyxrQkFBa0IsSUFBSSxFQUFFLFNBQVMsV0FBVyxFQUFFLFlBQVk7QUFDbkUsWUFBTSxLQUFLLGtCQUFrQixLQUFLLEtBQUs7T0FDdkM7YUFDSyxPQUFPO0tBQ2QsTUFBTSxrQkFBa0IsZ0NBQWdDLE1BQU07QUFDOUQsU0FBSSxDQUFDLE9BQU87QUFDVixXQUFLLGlCQUFpQixvQkFBb0IsS0FBSztPQUM3QyxNQUFNO09BQ04sT0FBTyxnQkFBZ0IsYUFBYSxTQUFTLFNBQVM7T0FDdEQsUUFBUTtRQUNOLFFBQVE7UUFDUixNQUFNLGdCQUFnQjtRQUN0QixNQUFNLElBQUk7UUFDWDtPQUNELFNBQVMsYUFBYTtPQUN0QixRQUFRLGFBQWE7T0FDckIsY0FBYyxhQUFhO09BQzNCLFNBQVMsYUFBYTtPQUN2QixDQUFDOztBQUdKLFNBQUksT0FBTztBQUNULFlBQU0sTUFBTSxnQkFBZ0IsTUFBTSxnQkFBZ0IsT0FBTztnQkFDaEQsT0FBTyxhQUFhLEdBQUc7QUFDaEMsYUFBTyxNQUFNLGdCQUFnQixNQUFNLGdCQUFnQixPQUFPOztBQUc1RCxTQUFJLEtBQUssUUFBUSxLQUFLO01BQ3BCLE1BQU0sVUFBVTtPQUNkLEtBQUs7T0FDTCxXQUFXLElBQUk7T0FDZixZQUFZLElBQUk7T0FDaEIsTUFBTSxJQUFJO09BQ1g7QUFDRCxVQUFJLGdCQUFnQixhQUFhLFFBQVE7QUFDdkMsWUFBSyxPQUFPLElBQUksS0FBSyxTQUFTLGdCQUFnQixPQUFPO2FBQ2hEO0FBQ0wsWUFBSyxPQUFPLElBQUksTUFBTSxTQUFTLGdCQUFnQixPQUFPOztZQUVuRDtBQUNMLFVBQUksZ0JBQWdCLGFBQWEsUUFBUTtBQUN2QyxlQUFRLEtBQUssZ0JBQWdCLFFBQVEsTUFBTTthQUN0QztBQUNMLGVBQVEsTUFBTSxnQkFBZ0IsUUFBUSxNQUFNOzs7Ozs7RUFTdEQsQUFBUSxnQ0FJTixJQUNBLFlBQ2dDO0dBQ2hDLE1BQU0sc0JBQXNCLEtBQUssbUJBQW1CO0dBQ3BELE1BQU0sZ0JBQW1CLGFBQXlCO0lBQ2hELE1BQU0sVUFBVSxZQUFZO0FBQzVCLFFBQUksQ0FBQyxTQUFTO0FBQ1osWUFBTyxVQUFVOztBQUduQixXQUFPLEtBQUssa0JBQWtCLElBQUksRUFBRSxTQUFTLEVBQUUsU0FBUzs7QUFHMUQsVUFBTztJQUNMLElBQUksS0FBSztBQUNQLFlBQU8sR0FBRzs7SUFFWixJQUFJLFlBQVk7QUFDZCxZQUFPLEdBQUc7O0lBRVosSUFBSSxTQUFTO0FBQ1gsWUFBTyxHQUFHOztJQUVaLElBQUksU0FBUztBQUNYLFlBQU8sR0FBRzs7SUFFWixXQUFXO0lBQ1gsZUFBZSxPQUFPLE1BQU07QUFDMUIsUUFBRyxlQUFlLE9BQU8sS0FBSzs7SUFFaEMsTUFBTSxNQUFNLFFBQVE7QUFDbEIsUUFBRyxNQUFNLE1BQU0sT0FBTzs7SUFFeEIsUUFBUSxVQUFVO0FBQ2hCLFFBQUcsY0FBYyxhQUFhLFNBQVMsQ0FBQzs7SUFFMUMsVUFBVSxPQUFPLFNBQVM7QUFDeEIsUUFBRyxVQUFVLFFBQVEsTUFBTSx3QkFDekIsYUFBYSxZQUFZO01BQ3ZCLE1BQU0sWUFBWSxPQUFPLE1BQU07TUFDL0IsTUFBTSxlQUFlLHVCQUF1Qiw2QkFBNkIsR0FBRztNQUM1RSxNQUFNLFlBQVksWUFBWSxLQUFLO0FBRW5DLDJCQUFxQixLQUFLO09BQ3hCLE1BQU07T0FDTixPQUFPO09BQ1AsY0FBYyxHQUFHO09BQ2pCLFdBQVcsR0FBRztPQUNkLFFBQVEsR0FBRztPQUNYLFFBQVEsRUFBRSxPQUFPLFdBQVc7T0FDNUIsR0FBRztPQUNKLENBQUM7QUFFRixVQUFJO09BQ0YsTUFBTSxTQUFTLE1BQU0sUUFBUSxNQUFNLG9CQUFvQjtPQUN2RCxNQUFNLGFBQWEsWUFBWSxLQUFLLEdBQUc7QUFDdkMsNEJBQXFCLEtBQUs7UUFDeEIsTUFBTTtRQUNOLE9BQU87UUFDUCxjQUFjLEdBQUc7UUFDakIsV0FBVyxHQUFHO1FBQ2QsUUFBUSxHQUFHO1FBQ1gsUUFBUSxFQUFFLE9BQU8sV0FBVztRQUM1QixHQUFHO1FBQ0osQ0FBQztBQUNGLDRCQUFxQixXQUFXO1FBQzlCLGVBQWU7UUFDZixNQUFNO1FBQ047UUFDQSxRQUFRO1FBQ1IsY0FBYyxHQUFHO1FBQ2pCLFdBQVcsR0FBRztRQUNkLFFBQVEsR0FBRztRQUNYLFlBQVksRUFBRSxPQUFPLFdBQVc7UUFDaEMsR0FBRztRQUNKLENBQUM7QUFDRixjQUFPO2VBQ0EsT0FBTztPQUNkLE1BQU0sYUFBYSxZQUFZLEtBQUssR0FBRztBQUN2Qyw0QkFBcUIsS0FBSztRQUN4QixNQUFNO1FBQ04sT0FBTztRQUNQLGNBQWMsR0FBRztRQUNqQixXQUFXLEdBQUc7UUFDZCxRQUFRLEdBQUc7UUFDWCxRQUFRLEVBQUUsT0FBTyxXQUFXO1FBQzVCLEdBQUc7UUFDSixDQUFDO0FBQ0YsNEJBQXFCLFdBQVc7UUFDOUIsZUFBZTtRQUNmLE1BQU07UUFDTjtRQUNBLFFBQVE7UUFDUixjQUFjLEdBQUc7UUFDakIsV0FBVyxHQUFHO1FBQ2QsUUFBUSxHQUFHO1FBQ1gsWUFBWSxFQUFFLE9BQU8sV0FBVztRQUNoQyxXQUFXLGlCQUFpQixRQUFRLE1BQU0sT0FBTyxPQUFPO1FBQ3hELEdBQUc7UUFDSixDQUFDO0FBQ0YsYUFBTTs7T0FFUixDQUNIOztJQUVILFFBQVEsT0FBTyxNQUFNO0FBQ25CLFFBQUcsUUFBUSxPQUFPLEtBQUs7O0lBRXpCLGVBQWU7QUFDYixZQUFPLEdBQUcsY0FBYzs7SUFFMUIsS0FBSyxRQUFRO0FBQ1gsUUFBRyxLQUFLLE9BQU87O0lBRWpCLE1BQU0sUUFBUTtBQUNaLFFBQUcsTUFBTSxPQUFPOztJQUVsQixVQUFVLFFBQVE7QUFDaEIsUUFBRyxVQUFVLE9BQU87O0lBRXRCLGNBQWM7QUFDWixRQUFHLGFBQWE7O0lBRW5COztFQUdILE1BQWMsNEJBQ1osS0FDQSxTQUNrQztHQUNsQyxNQUFNLEVBQUUsd0JBQXdCLE1BQU0sT0FBTztHQUM3QyxNQUFNLFVBQVUsb0JBQW9CLEtBQUssS0FBSyxPQUFPLE1BQU07QUFFM0QsT0FBSTtJQUNGLE1BQU0sRUFBRSxrQkFBa0IsTUFBTSxPQUFPO0FBQ3ZDLFdBQU8sY0FBYyxRQUFRLENBQUMsTUFBTyxRQUFRLFNBQVMsRUFBRSxDQUE2QjtZQUM5RSxHQUFHO0lBQ1YsTUFBTSxFQUFFLGFBQWEsTUFBTSxPQUFPO0FBQ2xDLFFBQUksYUFBYSxVQUFVO0tBQ3pCLE1BQU0sRUFBRSxxQkFBcUIsTUFBTSxPQUFPO0tBQzFDLE1BQU0sV0FBVyxpQkFBaUIsRUFBRSxDQUNqQyxLQUFLLFVBQVUsTUFBTSxRQUFRLENBQzdCLEtBQUssSUFBSTtLQUNaLE1BQU0sRUFBRSx3QkFBd0IsTUFBTSxPQUFPO0FBQzdDLFdBQU0sSUFBSSxvQkFBb0IsVUFBNkIsRUFDekQsVUFBVSxHQUNYLENBQUM7O0FBR0osVUFBTTs7Ozs7OztFQVFWLEFBQVEsa0JBQWtCLFNBQWlCLEtBQXFDO0dBQzlFLE1BQU0sZUFBZSxRQUFRLE1BQU0sSUFBSSxDQUFDLE9BQU8sUUFBUTtHQUN2RCxNQUFNLFdBQVcsS0FBSyxtQkFBbUIsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLE9BQU8sUUFBUTtHQUN4RSxNQUFNQyxTQUFpQyxFQUFFO0FBRXpDLFFBQUssSUFBSSxJQUFJLEdBQUcsSUFBSSxhQUFhLFFBQVEsS0FBSztBQUM1QyxRQUFJLGFBQWEsR0FBRyxXQUFXLElBQUksRUFBRTtBQUNuQyxZQUFPLGFBQWEsR0FBRyxNQUFNLEVBQUUsSUFBSSxTQUFTOzs7QUFHaEQsVUFBTzs7RUFHVCxBQUFRLG1CQUFtQixTQUFpQixLQUFzQjtHQUNoRSxNQUFNLGVBQWUsUUFBUSxNQUFNLElBQUksQ0FBQyxPQUFPLFFBQVE7R0FDdkQsTUFBTSxXQUFXLEtBQUssbUJBQW1CLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxPQUFPLFFBQVE7QUFFeEUsT0FBSSxhQUFhLFdBQVcsU0FBUyxRQUFRO0FBQzNDLFdBQU87O0FBR1QsUUFBSyxJQUFJLElBQUksR0FBRyxJQUFJLGFBQWEsUUFBUSxLQUFLO0lBQzVDLE1BQU0sY0FBYyxhQUFhO0lBQ2pDLE1BQU0sVUFBVSxTQUFTO0FBQ3pCLFFBQUksWUFBWSxXQUFXLElBQUksRUFBRTtBQUMvQjs7QUFFRixRQUFJLGdCQUFnQixTQUFTO0FBQzNCLFlBQU87OztBQUlYLFVBQU87O0VBR1QsQUFBUSxtQkFBbUIsS0FBcUI7QUFDOUMsVUFBTyxJQUFJLE1BQU0sSUFBSSxDQUFDOztFQUd4QixBQUFRLHlCQUF5QixTQUFpQixXQUFrQztBQUNsRixPQUFJO0lBQ0YsTUFBTSxVQUFVLG1CQUFtQixVQUFVLENBQUMsUUFBUSxPQUFPLElBQUk7QUFDakUsUUFBSSxRQUFRLFNBQVMsS0FBSyxFQUFFO0FBQzFCLFlBQU87O0lBRVQsTUFBTSxlQUFlLFFBQVEsUUFBUSxRQUFRLEdBQUc7SUFDaEQsTUFBTSxlQUFlLEtBQUssUUFBUSxTQUFTLGFBQWE7SUFDeEQsTUFBTSxtQkFBbUIsS0FBSyxTQUFTLFNBQVMsYUFBYTtBQUM3RCxRQUFJLGlCQUFpQixXQUFXLEtBQUssSUFBSSxLQUFLLFdBQVcsaUJBQWlCLEVBQUU7QUFDMUUsWUFBTzs7QUFFVCxXQUFPO1dBQ0Q7QUFDTixXQUFPOzs7Ozs7O0VBUVgsQUFBUSxtQkFDTixLQUNBLFNBQ0EsUUFDQTtBQUVBLE9BQUksSUFBSSxRQUFRLGNBQWM7QUFDNUIsV0FBTyxJQUFJLFFBQVE7O0FBSXJCLE9BQUksT0FBTyxxQkFBcUI7SUFDOUIsTUFBTWIsV0FBZ0M7S0FDcEMsTUFBTTtLQUNOLEtBQUssUUFBUTtLQUNiLE1BQU0sUUFBUSxjQUFjLE9BQU8sUUFBUSxJQUFJLE1BQU0sSUFBSSxDQUFDO0tBQzFELFFBQVEsUUFBUTtLQUNoQjtLQUNEO0lBQ0QsTUFBTSxTQUFTLE9BQU8sb0JBQW9CLFNBQVM7QUFDbkQsUUFBSSxPQUFRLFFBQU87O0FBR3JCLFVBQU87Ozs7OztFQU9ULE1BQU0sZ0JBQ0osS0FDQSxRQUNBLFFBQ0EsU0FDQSxPQUNrQjtHQUVsQixNQUFNLFVBQVUsTUFBTSxLQUFLLGNBQWMsUUFBUSxTQUFTLE1BQU07QUFFaEUsVUFBTyxLQUFLLGtCQUFrQixJQUFJLEVBQUUsU0FBUyxFQUFFLFlBQVk7SUFFekQsTUFBTSxFQUFFLGlCQUFpQixNQUFNLE9BQU87SUFDdEMsSUFBSSxjQUFjO0lBQ2xCLE1BQU0sT0FBTyxJQUFJLFdBQVcsS0FBSyxVQUFVO0FBQ3pDLFNBQUksYUFBYSxVQUFVLE1BQU0sS0FBSyxFQUFFO0FBQ3RDLGFBQU87O0FBRVQsWUFBTyxPQUFPO01BQ2Q7QUFHRixXQUFPLEtBQUssa0JBQWtCLEtBQUssTUFBTSxNQUFNO0tBQy9DOztFQUlKLE1BQU0sa0JBQ0osS0FDQSxNQUNBLE9BQ2tCO0dBQ2xCLE1BQU0sUUFBUSxLQUFLLE9BQU8sT0FBTyxJQUFJO0dBQ3JDLE1BQU0sU0FBUyxNQUFPLE1BQWMsSUFBSSxZQUFZLE1BQU0sT0FBTyxLQUFLO0FBQ3RFLFVBQU8sS0FBSyxJQUFJLFFBQVEsZUFBZSxtQkFBbUI7QUFFMUQsVUFBTzs7RUFHVCxNQUFNLGNBQ0osUUFDQSxTQUNBLE9BQ2tCO0dBRWxCLE1BQU0sRUFBRSxxQkFBcUIsTUFBTSxPQUFPO0dBQzFDLE1BQU0sY0FDSixVQUNBLFFBQ0EsWUFDRyxpQkFBaUIsU0FBUyxRQUFRLFFBQVEsUUFBUSxFQUFFLEtBQUssTUFBTSxTQUFTLE1BQU07R0FHbkYsTUFBTSxTQUNKLEtBQUssYUFBYSxRQUFRLFFBQVEsb0JBQW9CLEtBQUssT0FBTyxLQUFLLGlCQUFpQixJQUN4RixLQUFLLE9BQU8sS0FBSztHQUduQixNQUFNLFVBQVUsZ0NBQWdDLFFBQVEsUUFBUTtHQUNoRSxNQUFNLFVBQVcsTUFBTSxLQUFLLE9BQU8sSUFBSSxXQUFXLEVBQUUsU0FBUyxDQUFDLElBQUs7R0FFbkUsTUFBTUksVUFBbUIsTUFBTSxRQUFRLFFBQ3JDLE9BQU8sZ0JBQ0w7SUFDRSxXQUFXO0lBQ1g7SUFDQTtJQUNBLFNBQVMsUUFBUTtJQUNqQjtJQUNBLFlBQVksSUFBSSxLQUFLO0lBQ3JCO0lBRUEsTUFBTSxTQUFTLFFBQVE7SUFDdkIsU0FBUyxTQUFTLFdBQVc7SUFDOUIsRUFDRCxTQUNBLE1BQ0QsQ0FDRjtBQUNELFVBQU87O0VBS1QsTUFBTSx1QkFDSixRQUNBLFNBQ0EsSUFDMkI7R0FDM0IsTUFBTSxTQUNKLEtBQUssYUFBYSxRQUFRLFFBQVEsb0JBQW9CLEtBQUssT0FBTyxLQUFLLGlCQUFpQixJQUN4RixLQUFLLE9BQU8sS0FBSztHQUVuQixNQUFNLFVBQVUsZ0NBQWdDLFFBQVEsUUFBUTtHQUNoRSxNQUFNLFVBQVcsTUFBTSxLQUFLLE9BQU8sSUFBSSxXQUFXLEVBQUUsU0FBUyxDQUFDLElBQUs7R0FFbkUsTUFBTSxpQkFBaUI7SUFDckIsV0FBVztJQUNYO0lBQ0EsU0FBUyxRQUFRO0lBQ2pCO0lBQ0EsWUFBWSxJQUFJLEtBQUs7SUFDckI7SUFDQSxNQUFNLFNBQVMsUUFBUTtJQUN2QixTQUFTLFNBQVMsV0FBVztJQUM5QjtBQUVELE9BQUksT0FBTywwQkFBMEI7QUFDbkMsV0FBTyxFQUNMLEdBQUksTUFBTSxRQUFRLFFBQVEsT0FBTyx5QkFBeUIsZ0JBQWdCLFFBQVEsQ0FBQyxFQUNwRjs7R0FJSCxNQUFNLFlBQVksMEJBQTBCO0dBQzVDLE1BQU0sYUFBa0MsWUFBZTtBQUNyRCxVQUFNLElBQUksTUFDUixpSUFDRDs7R0FFSCxNQUFNLGtCQUFrQixNQUFNLFFBQVEsUUFDcEMsT0FBTyxnQkFDTDtJQUNFLFdBQVc7SUFDWDtJQUNBLE9BQU87SUFDUCxTQUFTLFFBQVE7SUFDakI7SUFDQSxZQUFZLGVBQWU7SUFDM0I7SUFDQSxNQUFNLGVBQWU7SUFDckIsU0FBUyxlQUFlO0lBQ3pCLEVBQ0QsU0FDQSxVQUNELENBQ0Y7R0FFRCxNQUFNLEVBQ0osV0FBVyxZQUNYLE9BQU8sUUFDUCxXQUFXLFlBQ1gsZUFBZSxnQkFDZixlQUFlLGdCQUNmLEdBQUcsU0FDRDtBQUVKLFVBQU87SUFDTCxHQUFHO0lBQ0gsV0FBVztJQUNYO0lBQ0EsU0FBUyxRQUFRO0lBQ2pCO0lBQ0Q7Ozs7OztFQU9ILEFBQVEsYUFDTixnQkFDQSxXQUNvQjtBQUNwQixPQUFJLENBQUMsZUFBZ0IsUUFBTztHQUc1QixNQUFNLFFBQVEsZUFBZSxNQUFNLElBQUksQ0FBQyxLQUFLLFNBQVM7SUFDcEQsTUFBTSxDQUFDLFFBQVEsS0FBSyxNQUFNLElBQUk7QUFDOUIsV0FBTyxLQUFLLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQztLQUM5QjtBQUVGLFVBQU8sTUFBTSxNQUFNLFNBQVMsVUFBVSxTQUFTLEtBQUssQ0FBQzs7RUFHdkQsTUFBTSxlQUE4QjtHQUVsQyxNQUFNLEVBQUUsaUJBQWlCLE1BQU0sT0FBTztBQUN0QyxRQUFLLFVBQVUsTUFBTSxjQUFjLGVBQWUsS0FBSyxnQkFBZ0IsV0FBVyxDQUFDOzs7Ozs7RUFPckYsTUFBYyxnQkFBZ0IsWUFBZ0U7R0FDNUYsTUFBTSxZQUFZLEtBQUssS0FBSztBQUU1QixRQUFLLE1BQU0sQ0FBQyxVQUFVLFVBQVUsWUFBWTtJQUMxQyxNQUFNLGVBQWUsS0FBSyxTQUFTLEtBQUssYUFBYSxTQUFTO0FBQzlELFlBQVEsSUFBSSxNQUFNLEtBQUssWUFBWSxNQUFNLEtBQUssTUFBTSxLQUFLLGFBQWEsR0FBRyxDQUFDOztBQUk1RSxTQUFNLEtBQUssT0FBTyxXQUFXLFdBQVc7QUFDeEMsU0FBTSxLQUFLLE9BQU8sZ0JBQWdCO0dBRWxDLE1BQU0sWUFBWSxLQUFLLEtBQUssR0FBRztHQUMvQixNQUFNLE1BQU0sYUFBYSxNQUFNLEtBQUssTUFBTSxHQUFHLFVBQVUsSUFBSTtBQUMzRCxXQUFRLElBQUksTUFBTSxNQUFNLFFBQVEsV0FBVyxJQUFJLENBQUMsQ0FBQzs7RUFNbkQsTUFBTSxVQUFVLElBQXlCO0FBQ3ZDLFNBQU0sS0FBSyxLQUFLLE1BQU0sT0FBTyxXQUFXLE1BQU07QUFDOUMsT0FBSTtBQUNGLFVBQU0sSUFBSTthQUNGO0FBQ1IsVUFBTSxLQUFLLFNBQVM7OztFQUl4QixNQUFjLGdCQUFnQixRQUF5QixTQUF5QztBQUM5RixPQUFJLENBQUMsU0FBUztBQUNaOztBQUlGLE9BQUksUUFBUSxVQUFVO0lBQ3BCLE1BQU0sa0JBQWtCLE1BQU0sT0FBTyxzQkFBc0I7SUFDM0QsTUFBTSxpQkFBaUI7S0FDckIsV0FBVztLQUNYLFdBQVc7TUFBQztNQUFNO01BQVE7TUFBVTtLQUNyQztBQUVELFFBQUksUUFBUSxhQUFhLE1BQU07QUFDN0IsWUFBTyxTQUFTLGdCQUFnQixlQUFlO1dBQzFDO0FBQ0wsWUFBTyxTQUFTLGdCQUFnQjtNQUM5QixHQUFHO01BQ0gsR0FBRyxRQUFRO01BQ1osQ0FBQzs7O0dBSU4sTUFBTSxpQkFBaUI7SUFDckIsTUFBTTtJQUNOLFVBQVU7SUFDVixXQUFXO0lBQ1gsSUFBSTtJQUNKLEtBQUs7SUFDTCxRQUFRO0lBQ1Q7R0FFRCxNQUFNLGlCQUFpQixPQUNyQixLQUNBLGVBQ0c7SUFDSCxNQUFNLFNBQVMsUUFBUTtBQUN2QixRQUFJLENBQUMsT0FBUTtBQUViLFFBQUksV0FBVyxNQUFNO0FBQ25CLFlBQU8sVUFBVSxNQUFNLE9BQU8sYUFBYSxRQUFRO1dBQzlDO0FBQ0wsWUFBTyxVQUFVLE1BQU0sT0FBTyxhQUFhLFNBQVMsT0FBTzs7O0FBSS9ELFFBQUssTUFBTSxDQUFDLEtBQUssZUFBZSxPQUFPLFFBQVEsZUFBZSxFQUFFO0FBQzlELFVBQU0sZUFBZSxLQUE2QixXQUFXOztBQUcvRCxPQUFJLFFBQVEsSUFBSTtBQUNkLFVBQU0sS0FBSyxzQkFBc0IsT0FBTzs7QUFHMUMsT0FBSSxRQUFRLFFBQVE7QUFDbEIsWUFBUSxPQUFPLE9BQU87OztFQUsxQixNQUFjLHNCQUNaLFFBQ2U7QUFDZixPQUFJLEtBQUssdUJBQXVCLElBQUksT0FBTyxFQUFFO0FBQzNDOztHQUdGLE1BQU0sZUFBZSxLQUFLLE9BQU8sT0FBTyxTQUFTO0FBQ2pELE9BQUksQ0FBQyxjQUFjO0FBQ2pCOztHQUdGLE1BQU0sbUJBQW1CLE1BQU0sT0FBTyx1QkFBdUI7R0FDN0QsTUFBTSx3QkFBd0IsOEJBQThCLEVBQzFELGlCQUFpQixjQUNsQixDQUFDO0FBQ0YsT0FBSSx1QkFBdUI7QUFDekIsVUFBTSxPQUFPLFNBQVMsaUJBQWlCLHNCQUFzQjtVQUN4RDtBQUNMLFVBQU0sT0FBTyxTQUFTLGdCQUFnQjs7QUFHeEMsUUFBSyx1QkFBdUIsSUFBSSxPQUFPO0FBQ3ZDLFFBQUsseUNBQXlDLE9BQU87O0VBSXZELEFBQVEseUNBQ04sUUFDTTtHQUNOLE1BQU0sYUFBYSxLQUFLLE9BQU8sS0FDNUIsS0FBSyxRQUFRLElBQUksa0JBQWtCLGFBQWEsSUFBTSxDQUN0RCxRQUFRLGNBQWMsWUFBWSxFQUFFO0FBRXZDLE9BQUksV0FBVyxXQUFXLEdBQUc7QUFDM0I7O0dBR0YsTUFBTSxtQkFBbUIsS0FBSyxPQUFPLE9BQU8sU0FBUztBQUNyRCxPQUFJLENBQUMsb0JBQW9CLG9CQUFvQixHQUFHO0FBQzlDOztHQUdGLE1BQU0sbUJBQW1CLEtBQUssSUFBSSxHQUFHLFdBQVc7QUFDaEQsT0FBSSxvQkFBb0Isa0JBQWtCO0FBQ3hDLFdBQU8sSUFBSSxLQUNUO0tBQ0U7S0FDQTtLQUNELEVBQ0Qsd0lBQ0Q7Ozs7Ozs7RUFRTCxNQUFjLG1CQUNaLFFBQ0EsU0FDQTtBQUNBLE9BQUksQ0FBQyxRQUFTO0dBRWQsTUFBTSxXQUFXLFFBQVEsWUFBWTtBQUdyQyxVQUFPLE1BQU07SUFDWCxRQUFRLENBQUMsT0FBTyxPQUFPO0lBQ3ZCLEtBQUssR0FBRyxTQUFTO0lBQ2pCLFNBQVMsT0FBTyxTQUFTLFVBQVU7S0FDakMsTUFBTSxNQUFNLElBQUksSUFBSSxRQUFRLEtBQUssVUFBVSxRQUFRLFFBQVEsT0FBTztLQUNsRSxNQUFNLFVBQVUsZ0NBQWdDLFFBQVEsUUFBUTtLQUtoRSxNQUFNLGFBQWE7TUFDakI7TUFDQTtNQUNBO01BQ0E7TUFDRDtBQUNELFNBQUksUUFBUSxNQUFNLENBQUMsV0FBVyxNQUFNLE1BQU0sUUFBUSxJQUFJLEVBQUUsQ0FBQyxFQUFFO0FBQ3pELGNBQVEsSUFBSSxhQUFhLFFBQVEsR0FBRzs7S0FHdEMsTUFBTSxNQUFNLElBQUksUUFBUSxJQUFJLFVBQVUsRUFBRTtNQUN0QyxRQUFRLFFBQVE7TUFDaEI7TUFDQSxHQUFJLFFBQVEsT0FBTyxFQUFFLE1BQU0sS0FBSyxVQUFVLFFBQVEsS0FBSyxFQUFFLEdBQUcsRUFBRTtNQUMvRCxDQUFDO0tBRUYsTUFBTSxXQUFXLE1BQU0sS0FBSyxLQUFLLFFBQVEsSUFBSTtBQUU3QyxXQUFNLE9BQU8sU0FBUyxPQUFPO0FBQzdCLGNBQVMsUUFBUSxTQUFTLE9BQWUsUUFBZ0I7QUFDdkQsWUFBTSxPQUFPLEtBQUssTUFBTTtPQUN4QjtBQUNGLFlBQU8sTUFBTSxLQUFLLFNBQVMsT0FBTyxNQUFNLFNBQVMsTUFBTSxHQUFHLEtBQUs7O0lBRWxFLENBQUM7O0VBR0osTUFBYyxzQkFBc0I7R0FDbEMsTUFBTUwsV0FBUyxNQUFNLE9BQU8sVUFBVTtHQUN0QyxNQUFNLE1BQU0sUUFBUSxJQUFJLFlBQVk7R0FDcEMsTUFBTSxlQUFlLFFBQVEsZUFBZSxzQkFBc0I7R0FFbEUsTUFBTSxPQUFPLFFBQWdCLFFBQVEsSUFBSUEsUUFBTSxJQUFJLEtBQUssTUFBTSxDQUFDO0dBQy9ELE1BQU0sU0FBUyxRQUFnQixRQUFRLElBQUlBLFFBQU0sTUFBTSxLQUFLLE1BQU0sQ0FBQztBQUVuRSxPQUFJLGdCQUFnQixXQUFXLEtBQUssZUFBZSxHQUFHO0FBR3RELFNBQU0sS0FBSztHQUNYLE1BQU0sRUFBRSxZQUFZLE1BQU0sT0FBTztHQUNqQyxNQUFNLGNBQWMsT0FBTyxLQUFLLEtBQUssU0FBUztHQUM5QyxNQUFNLFNBQVMsS0FBSyxJQUFJLEdBQUcsWUFBWSxLQUFLLE1BQU0sRUFBRSxPQUFPLENBQUM7QUFDNUQsUUFBSyxNQUFNLFFBQVEsYUFBYTtJQUM5QixNQUFNLE9BQU8sS0FBSyxTQUFTLE1BQU07SUFHakMsTUFBTSxPQUFPLE1BQU0sUUFBUTtJQUMzQixNQUFNLE9BQU8sS0FBSyxLQUFLLEdBQUcsTUFBTSxRQUFRLEtBQUssR0FBRyxNQUFNLFlBQVksS0FBSyxPQUFPLFNBQVM7SUFDdkYsTUFBTSxTQUFTLEtBQUssT0FBTyxPQUFPO0lBQ2xDLE1BQU0sWUFBWSxTQUFTLElBQUksQ0FBQyxZQUFZLEtBQUssR0FBR0EsUUFBTSxPQUFPLGlCQUFpQixHQUFHO0FBRXJGLFFBQUksU0FBUyxjQUFjO0FBQ3pCLGFBQVEsSUFBSUEsUUFBTSxNQUFNLFlBQVksT0FBTyxHQUFHLE9BQU8sR0FBRyxVQUFVO1dBQzdEO0FBQ0wsYUFBUSxJQUFJQSxRQUFNLElBQUksT0FBTyxPQUFPLEdBQUcsT0FBTyxHQUFHLFVBQVU7OztBQUkvRCxPQUFJLEtBQUssT0FBTyxPQUFPLE1BQU07SUFDM0IsTUFBTSxXQUFXLEtBQUssT0FBTyxPQUFPLEtBQUssWUFBWTtBQUNyRCxRQUFJLHdCQUF3QixTQUFTLElBQUk7O0FBRTNDLE9BQUksS0FBSyxPQUFPLElBQUksVUFBVTtBQUM1QixRQUFJLGFBQWEsS0FBSyxPQUFPLElBQUksV0FBVzs7QUFFOUMsU0FBTSxlQUFlLFdBQVcsS0FBSyxhQUFhLEdBQUc7O0VBR3ZELE1BQWMsZ0JBQWdCLFFBQWlDLFlBQXFCO0dBQ2xGLE1BQU0sRUFBRSx1QkFBdUIsTUFBTSxPQUFPO0FBRzVDLE9BQUksWUFBWTtJQUNkLE1BQU0sRUFBRSwyQkFBMkIsTUFBTSxPQUFPO0FBQ2hELFNBQUssU0FBUyx3QkFBd0I7QUFDdEMsdUJBQW1CLEtBQUssT0FBTztBQUMvQjs7QUFJRixPQUFJLENBQUMsUUFBUTtBQUNYLHVCQUFtQixLQUFLO0FBQ3hCOztHQUlGLE1BQU0sRUFBRSx1QkFBdUIsTUFBTSxPQUFPO0FBQzVDLFFBQUssU0FBUyxtQkFBbUIsT0FBTztBQUN4QyxzQkFBbUIsS0FBSyxPQUFPOztFQUdqQyxNQUFjLG9CQUFvQixTQUF3QztHQUN4RSxNQUFNLEVBQUUsb0JBQW9CLE1BQU0sT0FBTztBQUV6QyxRQUFLLGFBQWEsSUFBSSxnQkFBZ0IsR0FBRyxZQUFZLElBQUksQ0FBQztBQUMxRCxPQUFJLENBQUMsU0FBUztBQUNaOztHQUdGLE1BQU0sZUFBZSxRQUFRLGdCQUFnQixnQkFBZ0I7R0FDN0QsTUFBTSx1QkFBdUI7SUFDM0IsYUFBYSxHQUFHLE1BQU0sQ0FBQyxTQUFTO0lBQ2hDLFdBQVc7SUFDWCxhQUFhO0lBQ2Q7QUFFRCxPQUFJLGNBQWM7QUFDaEIsU0FBSyxVQUFVLFlBQVk7S0FDekIsR0FBRztLQUNILEdBQUcsUUFBUTtLQUNaLENBQUM7OztFQUlOLE1BQWMsS0FBSyxRQUF5QixTQUE4QjtHQUN4RSxNQUFNLE9BQU8sUUFBUSxRQUFRLFFBQVE7R0FDckMsTUFBTSxPQUFPLFFBQVEsUUFBUSxRQUFRO0FBRXJDLFVBQU8sUUFBUSxXQUFXLFlBQVk7QUFDcEMsVUFBTSxRQUFRLFdBQVcsYUFBYSxPQUFPO0FBQzdDLFVBQU0sS0FBSyxVQUFVLFNBQVM7QUFDOUIsVUFBTSxLQUFLLFNBQVM7S0FDcEI7R0FFRixNQUFNLFdBQVcsWUFBWTtBQUMzQixRQUFJO0FBQ0YsV0FBTSxPQUFPLE9BQU87QUFDcEIsYUFBUSxLQUFLLEVBQUU7YUFDUixLQUFLO0FBQ1osYUFBUSxNQUFNLDBCQUEwQixJQUFJO0FBQzVDLGFBQVEsS0FBSyxFQUFFOzs7QUFJbkIsV0FBUSxHQUFHLFVBQVUsU0FBUztBQUM5QixXQUFRLEdBQUcsV0FBVyxTQUFTO0FBRS9CLE9BQUksUUFBUSxXQUFXLFNBQVM7QUFDOUIsV0FBTyxnQkFBZ0IsUUFBUSxXQUFXLFFBQVE7O0FBR3BELFVBQ0csT0FBTztJQUFFO0lBQU07SUFBTSxDQUFDLENBQ3RCLEtBQUssWUFBWTtBQUNoQixVQUFNLEtBQUssVUFBVSxhQUFhO0FBQ2xDLFVBQU0sUUFBUSxXQUFXLFVBQVUsT0FBTztLQUMxQyxDQUNELE1BQU0sT0FBTyxRQUFRO0lBQ3BCLE1BQU1BLFdBQVMsTUFBTSxPQUFPLFVBQVU7QUFDdEMsWUFBUSxNQUFNQSxRQUFNLElBQUksMkJBQTJCLElBQUksQ0FBQztBQUN4RCxVQUFNLFVBQVU7S0FDaEI7O0VBR04sTUFBTSxVQUF5QjtHQUM3QixNQUFNLEVBQUUsY0FBYyxNQUFNLE9BQU87QUFFbkMsU0FBTSxVQUFVLFNBQVM7QUFFekIsT0FBSSxLQUFLLG1CQUFtQjtBQUMxQixVQUFNLEtBQUssa0JBQWtCLFVBQVU7O0FBRXpDLFFBQUssb0JBQW9CO0FBRXpCLFNBQU0sUUFBUSxXQUFXO0lBQ3ZCLEtBQUssWUFBWSxTQUFTLElBQUksUUFBUSxTQUFTO0lBQy9DLEtBQUssUUFBUSxZQUFZLElBQUksUUFBUSxTQUFTO0lBQzlDLEtBQUssbUJBQW1CLFVBQVUsSUFBSSxRQUFRLFNBQVM7SUFDdkQsS0FBSyxTQUFTLE9BQU8sSUFBSSxRQUFRLFNBQVM7SUFDM0MsQ0FBQztBQUVGLFNBQU1lLFNBQWdCOzs7Q0FvQmIsU0FBUyxJQUFJLGFBQWE7Q0FpQmpDLGNBQWMsSUFBSSxJQUFJO0VBQUM7RUFBYTtFQUFhO0VBQVc7RUFBTSxDQUFDIn0=
|
|
1265
|
+
|
|
1266
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29uYW11LmpzIiwibmFtZXMiOlsibWltZUxvb2t1cCIsImxvZ3RhcGVEaXNwb3NlIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwaS9zb25hbXUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQXN5bmNMb2NhbFN0b3JhZ2UgfSBmcm9tIFwiYXN5bmNfaG9va3NcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IHR5cGUgSW5jb21pbmdNZXNzYWdlLCB0eXBlIFNlcnZlciwgdHlwZSBTZXJ2ZXJSZXNwb25zZSB9IGZyb20gXCJodHRwXCI7XG5pbXBvcnQgb3MgZnJvbSBcIm9zXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuXG5pbXBvcnQgdHlwZSB7fSBmcm9tIFwiQGZhc3RpZnkvd2Vic29ja2V0XCI7XG5pbXBvcnQgeyBkaXNwb3NlIGFzIGxvZ3RhcGVEaXNwb3NlIH0gZnJvbSBcIkBsb2d0YXBlL2xvZ3RhcGVcIjtcbmltcG9ydCB7IHR5cGUgQXV0aCwgdHlwZSBCZXR0ZXJBdXRoT3B0aW9ucyB9IGZyb20gXCJiZXR0ZXItYXV0aFwiO1xuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiO1xuaW1wb3J0IHsgdHlwZSBGU1dhdGNoZXIgfSBmcm9tIFwiY2hva2lkYXJcIjtcbmltcG9ydCB7IHR5cGUgRmFzdGlmeUluc3RhbmNlLCB0eXBlIEZhc3RpZnlSZXBseSwgdHlwZSBGYXN0aWZ5UmVxdWVzdCB9IGZyb20gXCJmYXN0aWZ5XCI7XG5pbXBvcnQgbWltZSwgeyBsb29rdXAgYXMgbWltZUxvb2t1cCB9IGZyb20gXCJtaW1lLXR5cGVzXCI7XG5pbXBvcnQgeyB0eXBlIFdlYlNvY2tldCB9IGZyb20gXCJ3c1wiO1xuaW1wb3J0IHsgdHlwZSBab2RPYmplY3QgfSBmcm9tIFwiem9kXCI7XG5cbmltcG9ydCB7IEJBU0VfRklFTERfTUFQUElOR1MgfSBmcm9tIFwiLi4vYXV0aC9iZXR0ZXItYXV0aC1lbnRpdGllc1wiO1xuaW1wb3J0IHsgY3JlYXRlQmV0dGVyQXV0aFJlcXVlc3QgfSBmcm9tIFwiLi4vYXV0aC9iZXR0ZXItYXV0aC1yZXF1ZXN0XCI7XG5pbXBvcnQgeyBhcHBseUNhY2hlSGVhZGVycywgQ2FjaGVQcmVzZXRzIH0gZnJvbSBcIi4uL2NhY2hlLWNvbnRyb2wvY2FjaGUtY29udHJvbFwiO1xuaW1wb3J0IHsgdHlwZSBDYWNoZUNvbnRyb2xDb25maWcsIHR5cGUgQ2FjaGVDb250cm9sUmVxdWVzdCB9IGZyb20gXCIuLi9jYWNoZS1jb250cm9sL3R5cGVzXCI7XG5pbXBvcnQgeyB0eXBlIENhY2hlQ29uZmlnLCB0eXBlIENhY2hlTWFuYWdlciB9IGZyb20gXCIuLi9jYWNoZS90eXBlc1wiO1xuaW1wb3J0IHsgdG9GYXN0aWZ5Q29tcHJlc3NPcHRpb24gfSBmcm9tIFwiLi4vY29tcHJlc3MvY29tcHJlc3NcIjtcbmltcG9ydCB7IHR5cGUgQ29tcHJlc3NPcHRpb25zIH0gZnJvbSBcIi4uL2NvbXByZXNzL3R5cGVzXCI7XG5pbXBvcnQgeyBEQiB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgdHlwZSBTb25hbXVEQkNvbmZpZyB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgU0QsIHNldFNEQ29uZmlnIH0gZnJvbSBcIi4uL2RpY3Qvc2RcIjtcbmltcG9ydCB7IHR5cGUgTG9jYWxpemVkU3RyaW5nIH0gZnJvbSBcIi4uL2RpY3QvdHlwZXNcIjtcbmltcG9ydCB7IGdldFNvbmFtdUVudmlyb25tZW50LCByZWFkQWxsRW52aXJvbm1lbnRTbmFwc2hvdHMgfSBmcm9tIFwiLi4vZW52XCI7XG5pbXBvcnQgeyBOb3RGb3VuZEV4Y2VwdGlvbiB9IGZyb20gXCIuLi9leGNlcHRpb25zL3NvLWV4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IEJ1ZmZlcmVkRmlsZSB9IGZyb20gXCIuLi9zdG9yYWdlL2J1ZmZlcmVkLWZpbGVcIjtcbmltcG9ydCB7IHR5cGUgU3RvcmFnZU1hbmFnZXIgfSBmcm9tIFwiLi4vc3RvcmFnZS9zdG9yYWdlLW1hbmFnZXJcIjtcbmltcG9ydCB7IHR5cGUgS2V5R2VuZXJhdG9yIH0gZnJvbSBcIi4uL3N0b3JhZ2UvdHlwZXNcIjtcbmltcG9ydCB7IFVwbG9hZGVkRmlsZSB9IGZyb20gXCIuLi9zdG9yYWdlL3VwbG9hZGVkLWZpbGVcIjtcbmltcG9ydCB7IGNyZWF0ZU1vY2tTU0VGYWN0b3J5IH0gZnJvbSBcIi4uL3N0cmVhbS9zc2VcIjtcbmltcG9ydCB7IFdlYlNvY2tldFJ1bnRpbWUsIHR5cGUgV2ViU29ja2V0Q29ubmVjdGlvbiwgdHlwZSBXZWJTb2NrZXRFdmVudE1hcCB9IGZyb20gXCIuLi9zdHJlYW0vd3NcIjtcbmltcG9ydCB7XG4gIHR5cGUgVGVsZW1ldHJ5Q29udGV4dFByb3ZpZGVyLFxuICB0eXBlIFdlYlNvY2tldFRlbGVtZXRyeUNvbm5lY3Rpb25Db250ZXh0LFxufSBmcm9tIFwiLi4vc3RyZWFtL3dzLXRlbGVtZXRyeVwiO1xuaW1wb3J0IHsgdHlwZSBTeW5jZXIgfSBmcm9tIFwiLi4vc3luY2VyL3N5bmNlclwiO1xuaW1wb3J0IHsgdHlwZSBXb3JrZmxvd01hbmFnZXIgfSBmcm9tIFwiLi4vdGFza3Mvd29ya2Zsb3ctbWFuYWdlclwiO1xuaW1wb3J0IHsgdHlwZSBEZXZWaXRlc3RNYW5hZ2VyIH0gZnJvbSBcIi4uL3Rlc3RpbmcvZGV2LXZpdGVzdC1tYW5hZ2VyXCI7XG5pbXBvcnQgeyB0eXBlIFNvbmFtdUZhc3RpZnlDb25maWcgfSBmcm9tIFwiLi4vdHlwZXMvdHlwZXNcIjtcbmltcG9ydCB7IGNlbnRlclRleHQgfSBmcm9tIFwiLi4vdXRpbHMvY29uc29sZS11dGlsXCI7XG5pbXBvcnQgeyBpc0RhZW1vblNlcnZlciB9IGZyb20gXCIuLi91dGlscy9jb250cm9sbGVyXCI7XG5pbXBvcnQgeyBleGlzdHMsIGZpbGVFeGlzdHMgfSBmcm9tIFwiLi4vdXRpbHMvZnMtdXRpbHNcIjtcbmltcG9ydCB7IHR5cGUgQWJzb2x1dGVQYXRoIH0gZnJvbSBcIi4uL3V0aWxzL3BhdGgtdXRpbHNcIjtcbmltcG9ydCB7IGNvbnZlcnRGYXN0aWZ5SGVhZGVyc1RvU3RhbmRhcmQsIG1lcmdlIH0gZnJvbSBcIi4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyB0eXBlIFNvbmFtdUNvbmZpZywgdHlwZSBTb25hbXVTZXJ2ZXJPcHRpb25zLCB0eXBlIFNvbmFtdVRhc2tPcHRpb25zIH0gZnJvbSBcIi4vY29uZmlnXCI7XG5pbXBvcnQgeyB0eXBlIENvbnRleHQsIHR5cGUgUnVudGltZUNvbnRleHQsIHR5cGUgV2ViU29ja2V0Q29udGV4dCB9IGZyb20gXCIuL2NvbnRleHRcIjtcbmltcG9ydCB7IHR5cGUgRXh0ZW5kZWRBcGkgfSBmcm9tIFwiLi9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBnZXRTZWNyZXRzIH0gZnJvbSBcIi4vc2VjcmV0XCI7XG5pbXBvcnQgeyB0eXBlIFNvbmFtdVNlY3JldHMgfSBmcm9tIFwiLi9zZWNyZXRcIjtcbmltcG9ydCB7XG4gIGNyZWF0ZVdlYlNvY2tldFJlcGx5U3R1YixcbiAgcmVzb2x2ZVdlYlNvY2tldENsb3NlRGVzY3JpcHRvcixcbiAgcmVzb2x2ZVdlYlNvY2tldFBsdWdpbk9wdGlvbnMsXG4gIHJlc29sdmVJbnRlZ3JhdGVkVml0ZUhtck9wdGlvbnMsXG59IGZyb20gXCIuL3dlYnNvY2tldC1oZWxwZXJzXCI7XG5cbmV4cG9ydCB7XG4gIGNyZWF0ZVdlYlNvY2tldFJlcGx5U3R1YixcbiAgcmVzb2x2ZVdlYlNvY2tldENsb3NlRGVzY3JpcHRvcixcbiAgcmVzb2x2ZVdlYlNvY2tldFBsdWdpbk9wdGlvbnMsXG59IGZyb20gXCIuL3dlYnNvY2tldC1oZWxwZXJzXCI7XG5cbmNsYXNzIFNvbmFtdUNsYXNzIHtcbiAgcHVibGljIGlzSW5pdGlhbGl6ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHVibGljIGZvclRlc3Rpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHVibGljIGFzeW5jTG9jYWxTdG9yYWdlOiBBc3luY0xvY2FsU3RvcmFnZTx7XG4gICAgY29udGV4dDogUnVudGltZUNvbnRleHQ7XG4gIH0+ID0gbmV3IEFzeW5jTG9jYWxTdG9yYWdlKCk7XG5cbiAgcHVibGljIGdldENvbnRleHQ8VCBleHRlbmRzIFJ1bnRpbWVDb250ZXh0ID0gQ29udGV4dD4oKTogVCB7XG4gICAgY29uc3Qgc3RvcmUgPSB0aGlzLmFzeW5jTG9jYWxTdG9yYWdlLmdldFN0b3JlKCk7XG4gICAgaWYgKHN0b3JlPy5jb250ZXh0KSB7XG4gICAgICByZXR1cm4gc3RvcmUuY29udGV4dCBhcyBUO1xuICAgIH1cblxuICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gXCJ0ZXN0XCIpIHtcbiAgICAgIC8vIO2FjOyKpO2MhSDtmZjqsr3sl5DshJwg7Luo7YWN7Iqk7Yq46rCAIOyjvOyeheuQmOyngCDslYrsnYAg6rK97JqwIOu5iCDsu6jthY3siqTtirgg66as7YS0XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0cmFuc3BvcnQ6IFwiaHR0cFwiLFxuICAgICAgICByZXF1ZXN0OiBudWxsLFxuICAgICAgICByZXBseTogbnVsbCxcbiAgICAgICAgaGVhZGVyczoge30sXG4gICAgICAgIGNyZWF0ZVNTRTogKHNjaGVtYTogWm9kT2JqZWN0KSA9PiBjcmVhdGVNb2NrU1NFRmFjdG9yeShzY2hlbWEpLFxuICAgICAgICBsb2NhbGU6IFwiXCIsXG4gICAgICAgIHVzZXI6IG51bGwsXG4gICAgICAgIHNlc3Npb246IG51bGwsXG4gICAgICAgIG5haXRlU3RvcmU6IG5ldyBNYXA8c3RyaW5nLCBhbnk+KCksXG4gICAgICB9IGFzIHVua25vd24gYXMgVDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGNhbm5vdCBmaW5kIGNvbnRleHRcIik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfYXBpUm9vdFBhdGg6IEFic29sdXRlUGF0aCB8IG51bGwgPSBudWxsO1xuICBzZXQgYXBpUm9vdFBhdGgoYXBpUm9vdFBhdGg6IEFic29sdXRlUGF0aCkge1xuICAgIHRoaXMuX2FwaVJvb3RQYXRoID0gYXBpUm9vdFBhdGg7XG4gIH1cbiAgZ2V0IGFwaVJvb3RQYXRoKCk6IEFic29sdXRlUGF0aCB7XG4gICAgaWYgKHRoaXMuX2FwaVJvb3RQYXRoID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb25hbXUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fYXBpUm9vdFBhdGg7XG4gIH1cbiAgZ2V0IGFwcFJvb3RQYXRoKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYXBpUm9vdFBhdGguc3BsaXQocGF0aC5zZXApLnNsaWNlKDAsIC0xKS5qb2luKHBhdGguc2VwKTtcbiAgfVxuXG4gIHByaXZhdGUgX2RiQ29uZmlnOiBTb25hbXVEQkNvbmZpZyB8IG51bGwgPSBudWxsO1xuICBzZXQgZGJDb25maWcoZGJDb25maWc6IFNvbmFtdURCQ29uZmlnKSB7XG4gICAgdGhpcy5fZGJDb25maWcgPSBkYkNvbmZpZztcbiAgfVxuICBnZXQgZGJDb25maWcoKTogU29uYW11REJDb25maWcge1xuICAgIGlmICh0aGlzLl9kYkNvbmZpZyA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2RiQ29uZmlnO1xuICB9XG5cbiAgcHJpdmF0ZSBfc3luY2VyOiBTeW5jZXIgfCBudWxsID0gbnVsbDtcbiAgc2V0IHN5bmNlcihzeW5jZXI6IFN5bmNlcikge1xuICAgIHRoaXMuX3N5bmNlciA9IHN5bmNlcjtcbiAgfVxuICBnZXQgc3luY2VyKCk6IFN5bmNlciB7XG4gICAgaWYgKHRoaXMuX3N5bmNlciA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3N5bmNlcjtcbiAgfVxuXG4gIHByaXZhdGUgX2NvbmZpZzogU29uYW11Q29uZmlnIHwgbnVsbCA9IG51bGw7XG4gIHNldCBjb25maWcoY29uZmlnOiBTb25hbXVDb25maWcpIHtcbiAgICB0aGlzLl9jb25maWcgPSBjb25maWc7XG4gIH1cbiAgZ2V0IGNvbmZpZygpOiBTb25hbXVDb25maWcge1xuICAgIGlmICh0aGlzLl9jb25maWcgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jb25maWc7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgc2VjcmV0czogU29uYW11U2VjcmV0cyA9IGdldFNlY3JldHMoKTtcblxuICBwcml2YXRlIF9zdG9yYWdlOiBTdG9yYWdlTWFuYWdlciB8IG51bGwgPSBudWxsO1xuICAvKipcbiAgICogU3RvcmFnZU1hbmFnZXIg7J247Iqk7YS07IqkXG4gICAqL1xuICBnZXQgc3RvcmFnZSgpOiBTdG9yYWdlTWFuYWdlciB7XG4gICAgaWYgKCF0aGlzLl9zdG9yYWdlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTdG9yYWdlIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZC4gQ2hlY2sgc3RvcmFnZSBjb25maWcuXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fc3RvcmFnZTtcbiAgfVxuXG4gIHByaXZhdGUgX2NhY2hlOiBDYWNoZU1hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIENhY2hlTWFuYWdlciDsnbjsiqTthLTsiqQgKEJlbnRvQ2FjaGUpXG4gICAqL1xuICBnZXQgY2FjaGUoKTogQ2FjaGVNYW5hZ2VyIHtcbiAgICBpZiAoIXRoaXMuX2NhY2hlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYWNoZSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWQuIENoZWNrIGNhY2hlIGNvbmZpZyBpbiBzb25hbXUuY29uZmlnLnRzLlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2NhY2hlO1xuICB9XG5cbiAgcHJpdmF0ZSBfd29ya2Zsb3dzOiBXb3JrZmxvd01hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgZ2V0IHdvcmtmbG93cygpOiBXb3JrZmxvd01hbmFnZXIge1xuICAgIGlmICh0aGlzLl93b3JrZmxvd3MgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3dvcmtmbG93cztcbiAgfVxuXG4gIHByaXZhdGUgX2F1dGg6IEF1dGg8QmV0dGVyQXV0aE9wdGlvbnM+IHwgbnVsbCA9IG51bGw7XG4gIGdldCBhdXRoKCk6IEF1dGg8QmV0dGVyQXV0aE9wdGlvbnM+IHtcbiAgICBpZiAoIXRoaXMuX2F1dGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkF1dGggaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkLiBDaGVjayBhdXRoIGNvbmZpZyBpbiBzb25hbXUuY29uZmlnLnRzLlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2F1dGg7XG4gIH1cblxuICBwcml2YXRlIF9kZXZWaXRlc3RNYW5hZ2VyOiBEZXZWaXRlc3RNYW5hZ2VyIHwgbnVsbCA9IG51bGw7XG4gIGdldCBkZXZWaXRlc3RNYW5hZ2VyKCk6IERldlZpdGVzdE1hbmFnZXIgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fZGV2Vml0ZXN0TWFuYWdlcjtcbiAgfVxuICBzZXQgZGV2Vml0ZXN0TWFuYWdlcihtYW5hZ2VyOiBEZXZWaXRlc3RNYW5hZ2VyIHwgbnVsbCkge1xuICAgIHRoaXMuX2RldlZpdGVzdE1hbmFnZXIgPSBtYW5hZ2VyO1xuICB9XG5cbiAgLy8gU29uYW116rCAIHJ1bnRpbWXsnYQg7KeB7KCRIOyGjOycoO2VtCByZWdpc3RyeS9jb25uZWN0aW9uIGxpZmVjeWNsZeydhCDslaDtlIzrpqzsvIDsnbTshZgg7IiY66qF7KO86riw7JmAIOuPmeq4sO2ZlO2VqFxuICBwcml2YXRlIF93ZWJzb2NrZXRSdW50aW1lOiBXZWJTb2NrZXRSdW50aW1lIHwgbnVsbCA9IG51bGw7XG4gIC8vIOqwmeydgCBGYXN0aWZ5IOyduOyKpO2EtOyKpOyXkCBAZmFzdGlmeS93ZWJzb2NrZXTsnYQg7KSR67O1IOuTseuhne2VmOuKlCDqsoPsnYQgV2Vha1NldOycvOuhnCDssKjri6jtlahcbiAgcHJpdmF0ZSByZWFkb25seSB3ZWJzb2NrZXRQbHVnaW5TZXJ2ZXJzID0gbmV3IFdlYWtTZXQ8XG4gICAgRmFzdGlmeUluc3RhbmNlPFNlcnZlciwgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZT5cbiAgPigpO1xuICBnZXQgd2Vic29ja2V0UnVudGltZSgpOiBXZWJTb2NrZXRSdW50aW1lIHtcbiAgICBpZiAoIXRoaXMuX3dlYnNvY2tldFJ1bnRpbWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIldlYlNvY2tldCBydW50aW1lIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZC5cIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRSdW50aW1lO1xuICB9XG4gIHNldCB3ZWJzb2NrZXRSdW50aW1lKHJ1bnRpbWU6IFdlYlNvY2tldFJ1bnRpbWUgfCBudWxsKSB7XG4gICAgdGhpcy5fd2Vic29ja2V0UnVudGltZSA9IHJ1bnRpbWU7XG4gIH1cblxuICAvLyBITVIg7LKY66asOiDtjIzsnbwg7Iuc7Iqk7YWcIOqwkOyLnCArIEhNUi9zeW5jIOyCrOydtO2BtCDsi6TtlonsnYAgd2F0Y2hlciDrqqjrk4jroZwg7JyE7J6E7ZWp64uI64ukLlxuICBwdWJsaWMgd2F0Y2hlcjogRlNXYXRjaGVyIHwgbnVsbCA9IG51bGw7XG5cbiAgcHVibGljIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlIHwgbnVsbCA9IG51bGw7XG5cbiAgYXN5bmMgaW5pdEZvclRlc3RpbmcoKSB7XG4gICAgYXdhaXQgdGhpcy5pbml0KHRydWUsIGZhbHNlLCB1bmRlZmluZWQsIHRydWUpO1xuICB9XG5cbiAgYXN5bmMgaW5pdChcbiAgICBkb1NpbGVudDogYm9vbGVhbiA9IGZhbHNlLFxuICAgIGVuYWJsZVN5bmM6IGJvb2xlYW4gPSB0cnVlLFxuICAgIGFwaVJvb3RQYXRoPzogQWJzb2x1dGVQYXRoLFxuICAgIGZvclRlc3Rpbmc6IGJvb2xlYW4gPSBmYWxzZSxcbiAgKSB7XG4gICAgdGhpcy5mb3JUZXN0aW5nID0gZm9yVGVzdGluZztcblxuICAgIGlmICh0aGlzLmlzSW5pdGlhbGl6ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBpbml0U3RhcnQgPSBwZXJmb3JtYW5jZS5ub3coKTtcblxuICAgIC8vIEFQSSDro6jtirgg7Yyo7IqkXG4gICAgY29uc3QgeyBmaW5kQXBpUm9vdFBhdGggfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL3V0aWxzXCIpO1xuICAgIHRoaXMuYXBpUm9vdFBhdGggPSBhcGlSb290UGF0aCA/PyBmaW5kQXBpUm9vdFBhdGgoKTtcbiAgICBjb25zdCBiYXNlRW52QmVmb3JlQ29uZmlnTG9hZCA9IHsgLi4ucHJvY2Vzcy5lbnYgfTtcblxuICAgIC8vIOyEpOygleydhCDroZzrlKntlZjripQg6rKD67aA7YSwIOyLnOyekVxuICAgIGNvbnN0IGNvbmZpZ1N0YXJ0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgY29uc3QgeyBsb2FkQ29uZmlnIH0gPSBhd2FpdCBpbXBvcnQoXCIuL2NvbmZpZ1wiKTtcbiAgICB0aGlzLmNvbmZpZyA9IGF3YWl0IGxvYWRDb25maWcodGhpcy5hcGlSb290UGF0aCk7XG4gICAgY29uc3QgY29uZmlnVGltZSA9IHBlcmZvcm1hbmNlLm5vdygpIC0gY29uZmlnU3RhcnQ7XG4gICAgc2V0U0RDb25maWcodGhpcy5jb25maWcuaTE4bik7XG4gICAgLy8gc29uYW11LmNvbmZpZy50cyDquLDrs7jqsJIg7ISk7KCVXG4gICAgdGhpcy5jb25maWcuZGF0YWJhc2UuZGF0YWJhc2UgPSB0aGlzLmNvbmZpZy5kYXRhYmFzZS5kYXRhYmFzZSA/PyBcInBnXCI7XG4gICAgdGhpcy5jb25maWcuZGF0YWJhc2UuZGVmYXVsdE9wdGlvbnMgPSB0aGlzLmNvbmZpZy5kYXRhYmFzZS5kZWZhdWx0T3B0aW9ucyA/PyB7fTtcbiAgICB0aGlzLmNvbmZpZy5kYXRhYmFzZS5kZWZhdWx0T3B0aW9ucy5jbGllbnQgPSB0aGlzLmNvbmZpZy5kYXRhYmFzZS5kYXRhYmFzZSA/PyBcInBnXCI7XG5cbiAgICAvLyDroZzquYUg7ISk7KCVXG4gICAgY29uc3QgeyBjb25maWd1cmVMb2dUYXBlIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9sb2dnZXIvY29uZmlndXJlXCIpO1xuICAgIGlmICh0aGlzLmNvbmZpZy5sb2dnaW5nICE9PSBmYWxzZSkge1xuICAgICAgYXdhaXQgY29uZmlndXJlTG9nVGFwZSh7XG4gICAgICAgIC4uLnRoaXMuY29uZmlnLmxvZ2dpbmcsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBEQiDroZzrk5xcbiAgICBjb25zdCB7IERCIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9kYXRhYmFzZS9kYlwiKTtcbiAgICBjb25zdCB7IGlzTG9jYWw6IGlzTG9jYWxFbnZpcm9ubWVudCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvY29udHJvbGxlclwiKTtcbiAgICBjb25zdCBlbnZpcm9ubWVudFNuYXBzaG90cyA9IGlzTG9jYWxFbnZpcm9ubWVudCgpXG4gICAgICA/IHJlYWRBbGxFbnZpcm9ubWVudFNuYXBzaG90cyh0aGlzLmFwaVJvb3RQYXRoLCBiYXNlRW52QmVmb3JlQ29uZmlnTG9hZClcbiAgICAgIDogdW5kZWZpbmVkO1xuICAgIHRoaXMuZGJDb25maWcgPSBEQi5nZW5lcmF0ZURCQ29uZmlnKFxuICAgICAgdGhpcy5jb25maWcuZGF0YWJhc2UsXG4gICAgICB0aGlzLmNvbmZpZy5wcm9qZWN0TmFtZSxcbiAgICAgIGVudmlyb25tZW50U25hcHNob3RzLFxuICAgICk7XG4gICAgREIuc2V0Q29uZmlnKHRoaXMuZGJDb25maWcpO1xuXG4gICAgLy8gRW50aXR5IOuhnOuTnFxuICAgIC8vIO2FjOyKpO2KuOyXkOyEnOuPhCBFbnRpdHkg7KCV67O064qUIO2VhOyalO2VqeuLiOuLpC5cbiAgICAvLyB1cHNlcnTqsIAg7KCc64yA66GcIOyekeuPme2VmOugpOuptCBlbnRpdHnsnZggdW5pcXVlIGluZGV4IOygleuztOqwgCDtlYTsmpTtlZjquLAg65WM66y47J6F64uI64ukLlxuICAgIGNvbnN0IHsgRW50aXR5TWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCIpO1xuICAgIGF3YWl0IEVudGl0eU1hbmFnZXIuYXV0b2xvYWQoZG9TaWxlbnQpO1xuXG4gICAgLy8gQ2FjaGUg7LSI6riw7ZmUXG4gICAgYXdhaXQgdGhpcy5pbml0aWFsaXplQ2FjaGUodGhpcy5jb25maWcuc2VydmVyLmNhY2hlLCBmb3JUZXN0aW5nKTtcblxuICAgIC8vIEJldHRlckF1dGgg7LSI6riw7ZmUXG4gICAgY29uc3QgYXV0aENvbmZpZyA9IHRoaXMuY29uZmlnLnNlcnZlci5hdXRoO1xuICAgIGlmIChhdXRoQ29uZmlnKSB7XG4gICAgICAvLyDsgqzsmqnsnpAg7ISk7KCV6rO8IOq4sOuzuOqwkuydhCBtZXJnZVxuICAgICAgY29uc3QgbWVyZ2VkRmllbGRNYXBwaW5ncyA9IG1lcmdlKEJBU0VfRklFTERfTUFQUElOR1MsIGF1dGhDb25maWcpO1xuXG4gICAgICAvLyBiZXR0ZXItYXV0aCDsnbjsiqTthLTsiqQg7IOd7ISxXG4gICAgICBjb25zdCB7IGJldHRlckF1dGggfSA9IGF3YWl0IGltcG9ydChcImJldHRlci1hdXRoXCIpO1xuICAgICAgY29uc3QgeyBzb25hbXVLbmV4QWRhcHRlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vYXV0aC9rbmV4LWFkYXB0ZXJcIik7XG5cbiAgICAgIGNvbnN0IGF1dGhPcHRpb25zOiBCZXR0ZXJBdXRoT3B0aW9ucyA9IHtcbiAgICAgICAgZGF0YWJhc2U6IHNvbmFtdUtuZXhBZGFwdGVyKCksXG4gICAgICAgIC4uLm1lcmdlZEZpZWxkTWFwcGluZ3MsXG4gICAgICB9O1xuICAgICAgdGhpcy5fYXV0aCA9IGJldHRlckF1dGgoYXV0aE9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8vIO2FjOyKpO2MheyduCDqsr3smrAg7Iux7YGsIOyXhuydtCDspJHri6hcbiAgICBpZiAoZm9yVGVzdGluZykge1xuICAgICAgdGhpcy5pc0luaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBUYXNrIOuTseuhnVxuICAgIGF3YWl0IHRoaXMuaW5pdGlhbGl6ZVdvcmtmbG93cyh0aGlzLmNvbmZpZy50YXNrcyk7XG5cbiAgICAvLyBTeW5jZXJcbiAgICBjb25zdCB7IFN5bmNlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3luY2VyL3N5bmNlclwiKTtcbiAgICB0aGlzLnN5bmNlciA9IG5ldyBTeW5jZXIoKTtcblxuICAgIC8vIEF1dG9sb2FkOiBNb2RlbHMgLyBUeXBlcyAvIEFQSXMgLyBXb3JrZmxvd3MgLyBUZW1wbGF0ZXMgLyBTU1IgUm91dGVzXG4gICAgYXdhaXQgdGhpcy5zeW5jZXIuYXV0b2xvYWRUeXBlcygpO1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkTW9kZWxzKCk7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIuYXV0b2xvYWRBcGlzKCk7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIuYXV0b2xvYWRXb3JrZmxvd3MoKTtcbiAgICBjb25zdCB7IFRlbXBsYXRlTWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdGVtcGxhdGVcIik7XG4gICAgYXdhaXQgVGVtcGxhdGVNYW5hZ2VyLmF1dG9sb2FkKCk7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIuYXV0b2xvYWRTc3JSb3V0ZXMoKTtcblxuICAgIGNvbnN0IHsgaXNMb2NhbCwgaXNUZXN0LCBpc0hvdFJlbG9hZFNlcnZlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvY29udHJvbGxlclwiKTtcbiAgICBpZiAoaXNMb2NhbCgpICYmICFpc1Rlc3QoKSAmJiBpc0hvdFJlbG9hZFNlcnZlcigpICYmIGVuYWJsZVN5bmMpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3luY2VyLnN5bmMoKTtcbiAgICAgIGF3YWl0IHRoaXMuc3RhcnRXYXRjaGVyKCk7XG4gICAgfVxuXG4gICAgdGhpcy5pc0luaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB0aGlzLl9pbml0RWxhcHNlZCA9IHBlcmZvcm1hbmNlLm5vdygpIC0gaW5pdFN0YXJ0O1xuICAgIHRoaXMuX2NvbmZpZ0VsYXBzZWQgPSBjb25maWdUaW1lO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW5pdEVsYXBzZWQgPSAwO1xuICBwcml2YXRlIF9jb25maWdFbGFwc2VkID0gMDtcblxuICBhc3luYyBjcmVhdGVTZXJ2ZXIoaW5pdE9wdGlvbnM/OiB7IGVuYWJsZVN5bmM/OiBib29sZWFuOyBkb1NpbGVudD86IGJvb2xlYW4gfSkge1xuICAgIGlmICghdGhpcy5pc0luaXRpYWxpemVkKSB7XG4gICAgICBhd2FpdCB0aGlzLmluaXQoaW5pdE9wdGlvbnM/LmRvU2lsZW50LCBpbml0T3B0aW9ucz8uZW5hYmxlU3luYyk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMuY29uZmlnLnNlcnZlcjtcbiAgICBjb25zdCB7IGRlZmF1bHQ6IGZhc3RpZnkgfSA9IGF3YWl0IGltcG9ydChcImZhc3RpZnlcIik7XG4gICAgY29uc3QgeyBnZXRMb2dUYXBlRmFzdGlmeUxvZ2dlciB9ID0gYXdhaXQgaW1wb3J0KFwiQGxvZ3RhcGUvZmFzdGlmeVwiKTtcbiAgICBjb25zdCBzZXJ2ZXIgPSBmYXN0aWZ5KHtcbiAgICAgIC4uLm9wdGlvbnMuZmFzdGlmeSxcbiAgICAgIGxvZ2dlcjpcbiAgICAgICAgdGhpcy5jb25maWcubG9nZ2luZyAhPT0gZmFsc2VcbiAgICAgICAgICA/IGdldExvZ1RhcGVGYXN0aWZ5TG9nZ2VyKHtcbiAgICAgICAgICAgICAgY2F0ZWdvcnk6IHRoaXMuY29uZmlnLmxvZ2dpbmc/LmZhc3RpZnlDYXRlZ29yeSA/PyBbXCJmYXN0aWZ5XCJdLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICB9KTtcbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcbiAgICB0aGlzLndlYnNvY2tldFJ1bnRpbWUgPSBuZXcgV2ViU29ja2V0UnVudGltZShvcHRpb25zLndlYnNvY2tldCk7XG5cbiAgICAvLyBTdG9yYWdlIOyEpOyglSDihpIgU3RvcmFnZU1hbmFnZXIg7IOd7ISxXG4gICAgaWYgKG9wdGlvbnMuc3RvcmFnZSkge1xuICAgICAgY29uc3QgeyBTdG9yYWdlTWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3RvcmFnZS9zdG9yYWdlLW1hbmFnZXJcIik7XG4gICAgICB0aGlzLl9zdG9yYWdlID0gbmV3IFN0b3JhZ2VNYW5hZ2VyKG9wdGlvbnMuc3RvcmFnZSk7XG4gICAgfVxuXG4gICAgLy8g7ZSM65+s6re47J24IOuTseuhnVxuICAgIGlmIChvcHRpb25zLnBsdWdpbnMpIHtcbiAgICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJQbHVnaW5zKHNlcnZlciwgb3B0aW9ucy5wbHVnaW5zKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5hdXRoKSB7XG4gICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyQmV0dGVyQXV0aChzZXJ2ZXIsIG9wdGlvbnMuYXV0aCk7XG4gICAgfVxuXG4gICAgLy8gQVBJIOudvOyasO2MhSDshKTsoJVcbiAgICBhd2FpdCB0aGlzLndpdGhGYXN0aWZ5KHNlcnZlciwgb3B0aW9ucy5hcGlDb25maWcsIHtcbiAgICAgIGVuYWJsZVN5bmM6IGluaXRPcHRpb25zPy5lbmFibGVTeW5jLFxuICAgICAgZG9TaWxlbnQ6IGluaXRPcHRpb25zPy5kb1NpbGVudCxcbiAgICB9KTtcblxuICAgIC8vIOyEnOuyhCDsi5zsnpFcbiAgICBhd2FpdCB0aGlzLmJvb3Qoc2VydmVyLCBvcHRpb25zKTtcblxuICAgIGlmICghaW5pdE9wdGlvbnM/LmRvU2lsZW50KSB7XG4gICAgICB0aGlzLnByaW50U3RhcnR1cFN1bW1hcnkoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VydmVyO1xuICB9XG5cbiAgYXN5bmMgd2l0aEZhc3RpZnkoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2U8U2VydmVyLCBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlPixcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIGVuYWJsZVN5bmM/OiBib29sZWFuO1xuICAgICAgZG9TaWxlbnQ/OiBib29sZWFuO1xuICAgIH0sXG4gICkge1xuICAgIGlmICghdGhpcy5pc0luaXRpYWxpemVkKSB7XG4gICAgICBhd2FpdCB0aGlzLmluaXQob3B0aW9ucz8uZG9TaWxlbnQsIG9wdGlvbnM/LmVuYWJsZVN5bmMpO1xuICAgIH1cblxuICAgIHRoaXMuc2VydmVyID0gc2VydmVyO1xuICAgIHRoaXMud2Vic29ja2V0UnVudGltZSA/Pz0gbmV3IFdlYlNvY2tldFJ1bnRpbWUodGhpcy5jb25maWcuc2VydmVyLndlYnNvY2tldCk7XG5cbiAgICAvLyB0aW1lem9uZSDshKTsoJVcbiAgICBjb25zdCB0aW1lem9uZSA9IHRoaXMuY29uZmlnLmFwaS50aW1lem9uZTtcbiAgICBpZiAodGltZXpvbmUpIHtcbiAgICAgIC8vIO2DgOyehOyhtOyXkCDrp57qsowg7J2R64u1IOuCoOynnCDsiqTtirjrp4HsnYQg67OA7ZmY7ZW07KO87Ja07JW8IO2VqeuLiOuLpC5cbiAgICAgIC8vIOqwgOuguSB0aW1lem9uZeydtCBcIkFzaWEvU2VvdWxcIiDsnbTrqbRcbiAgICAgIC8vIFwiMjAyNS0xMS0yMVQwMDowMDowMC4wMDBaXCIg66W8IFwiMjAyNS0xMS0yMVQwOTowMDowMCswOTowMFwiIOycvOuhnCDrs4DtmZjtlbTso7zslrTslbwg7ZWp64uI64ukLlxuICAgICAgY29uc3QgeyBmb3JtYXRJblRpbWVab25lIH0gPSBhd2FpdCBpbXBvcnQoXCJkYXRlLWZucy10elwiKTtcblxuICAgICAgLy8gSVNPIDg2MDEg64Kg7KecIO2YleyLnSDsoJXqt5zsi50gKOyYiDogMjAyNC0wMS0xNVQwOTozMDowMC4wMDBaKVxuICAgICAgY29uc3QgSVNPX0RBVEVfUkVHRVggPSAvXlxcZHs0fS1cXGR7Mn0tXFxkezJ9VFxcZHsyfTpcXGR7Mn06XFxkezJ9KFxcLlxcZHszfSk/WiQvO1xuXG4gICAgICAvLyBU66W8IOuRmOufrOyLvCDsnpHsnYDrlLDsmLTtkZzqsIAg7JeG64uk66m0IFwiMjAyNS0xMS0xOTE3NjM1NDYxODkwMDAxODo1NjoyOSswOTowMFwi7JmAIOqwmeydgCDqsrDqs7zqsIAg64KY7Ji164uI64ukLlxuICAgICAgLy8g7J2064qUIGRhdGUtZm5zIO2KueyeheuLiOuLpC5cbiAgICAgIC8vIOydtOugh+qyjCDtlbTrj4Qg6rSc7LCu7Iq164uI64ukLiBcIjIwMjUtMTEtMTlUMTg6NTY6MjkrMDk6MDBcIiDrqqjslpHsnLzroZwg7J6YIOuCmOyYteuLiOuLpC5cbiAgICAgIGNvbnN0IERBVEVfRk9STUFUID0gXCJ5eXl5LU1NLWRkJ1QnSEg6bW06c3NYWFhcIjtcblxuICAgICAgc2VydmVyLnNldFJlcGx5U2VyaWFsaXplcigocGF5bG9hZCkgPT4ge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocGF5bG9hZCwgKF9rZXksIHZhbHVlKSA9PiB7XG4gICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiBJU09fREFURV9SRUdFWC50ZXN0KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdEluVGltZVpvbmUoXG4gICAgICAgICAgICAgIG5ldyBEYXRlKHZhbHVlKSxcbiAgICAgICAgICAgICAgdGltZXpvbmUgYXMgYCR7c3RyaW5nfS8ke3N0cmluZ31gLFxuICAgICAgICAgICAgICBEQVRFX0ZPUk1BVCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIC8vIFRpbWV6b25lIOuhnOq3uOuKlCBwcmludFN0YXJ0dXBTdW1tYXJ57JeQ7IScIO2Gte2VqSDstpzroKVcbiAgICB9XG5cbiAgICAvLyDsoITssrQg65287Jqw7YyFIOumrOyKpO2KuFxuICAgIHNlcnZlci5nZXQoXG4gICAgICBgJHt0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4fS9yb3V0ZXNgLFxuICAgICAgYXN5bmMgKF9yZXF1ZXN0LCBfcmVwbHkpOiBQcm9taXNlPHR5cGVvZiB0aGlzLnN5bmNlci5hcGlzPiA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnN5bmNlci5hcGlzO1xuICAgICAgfSxcbiAgICApO1xuXG4gICAgLy8gSGVhbHRoY2hlY2sgQVBJXG4gICAgc2VydmVyLmdldChcbiAgICAgIGAke3RoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXh9L2hlYWx0aGNoZWNrYCxcbiAgICAgIGFzeW5jIChfcmVxdWVzdCwgX3JlcGx5KTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcbiAgICAgICAgcmV0dXJuIFwib2tcIjtcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIFNvbmFtdSBVSSBBUEkgKOuhnOy7rCDtmZjqsr3sl5DshJzrp4wpXG4gICAgY29uc3QgeyBpc0xvY2FsIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi91dGlscy9jb250cm9sbGVyXCIpO1xuICAgIGlmIChpc0xvY2FsKCkpIHtcbiAgICAgIGNvbnN0IHsgc29uYW11VUlBcGlQbHVnaW4gfSA9IGF3YWl0IGltcG9ydChcIi4uL3VpL2FwaVwiKTtcbiAgICAgIHNlcnZlci5yZWdpc3Rlcihzb25hbXVVSUFwaVBsdWdpbik7XG4gICAgfVxuXG4gICAgLy8gRGV2UnVubmVyIO2FjOyKpO2KuCDsl5Trk5ztj6zsnbjtirggKOuhnOy7rCDtmZjqsr0gKyBkZXZSdW5uZXIg7Zmc7ISx7ZmUIOyLnClcbiAgICBpZiAoaXNMb2NhbCgpICYmIHRoaXMuY29uZmlnLnRlc3Q/LmRldlJ1bm5lcj8uZW5hYmxlZCkge1xuICAgICAgY29uc3QgeyByZWdpc3RlckRldlRlc3RSb3V0ZXMgfSA9IGF3YWl0IGltcG9ydChcIi4uL3Rlc3RpbmcvZGV2LXRlc3Qtcm91dGVzXCIpO1xuICAgICAgYXdhaXQgcmVnaXN0ZXJEZXZUZXN0Um91dGVzKHNlcnZlciwgdGhpcy5jb25maWcudGVzdC5kZXZSdW5uZXIpO1xuICAgIH1cblxuICAgIGNvbnN0IHdlYlBhdGggPSBwYXRoLmpvaW4odGhpcy5hcHBSb290UGF0aCwgXCJ3ZWJcIik7XG4gICAgY29uc3QgaGFzV2ViID0gYXdhaXQgZXhpc3RzKHdlYlBhdGgpO1xuXG4gICAgLy8g7KCE7JetIGNvbXByZXNzIOyYteyFmCDqs4TsgrAgKHJvdXRlLmNvbXByZXNzOiB0cnVl7J28IOuVjCDsgqzsmqkpXG4gICAgY29uc3QgcGx1Z2luQ29tcHJlc3MgPSB0aGlzLmNvbmZpZy5zZXJ2ZXIucGx1Z2lucz8uY29tcHJlc3M7XG4gICAgY29uc3QgZ2xvYmFsQ29tcHJlc3NPcHRpb25zOiBDb21wcmVzc09wdGlvbnMgfCB1bmRlZmluZWQgPSBwbHVnaW5Db21wcmVzc1xuICAgICAgPyBwbHVnaW5Db21wcmVzcyA9PT0gdHJ1ZVxuICAgICAgICA/IHsgdGhyZXNob2xkOiAxMDI0LCBlbmNvZGluZ3M6IFtcImJyXCIsIFwiZ3ppcFwiLCBcImRlZmxhdGVcIl0gfVxuICAgICAgICA6IHtcbiAgICAgICAgICAgIHRocmVzaG9sZDogcGx1Z2luQ29tcHJlc3MudGhyZXNob2xkLFxuICAgICAgICAgICAgZW5jb2RpbmdzOiBwbHVnaW5Db21wcmVzcy5lbmNvZGluZ3MsXG4gICAgICAgICAgICBjdXN0b21UeXBlczogcGx1Z2luQ29tcHJlc3MuY3VzdG9tVHlwZXMsXG4gICAgICAgICAgfVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAoaXNMb2NhbCgpKSB7XG4gICAgICAvLyDroZzsu6wg6rCc67CcIO2ZmOqyvTogY2F0Y2gtYWxs66GcIEFQSeulvCDrj5nsoIEg66ek7Lmt7ZWY7JesIEhNUuydhCDsp4Dsm5Dtlanri4jri6QuXG4gICAgICAvLyBTT05BTVVfRElTQUJMRV9JTlRFR1JBVEVEX1dFQj15ZXProZwg7ISk7KCV7ZWY66m0IGRldl9hcGkg66qo65Oc7JeQ7IScIFZpdGUg7Ya17ZWp7J2EIOu5hO2ZnOyEse2ZlO2VoCDsiJgg7J6I7Iq164uI64ukLlxuICAgICAgY29uc3QgZGlzYWJsZUludGVncmF0ZWRXZWIgPSBwcm9jZXNzLmVudi5TT05BTVVfRElTQUJMRV9JTlRFR1JBVEVEX1dFQiA9PT0gXCJ5ZXNcIjtcbiAgICAgIGlmIChoYXNXZWIgJiYgIWRpc2FibGVJbnRlZ3JhdGVkV2ViKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc2V0dXBEZXZTZXJ2ZXJXaXRoVml0ZShzZXJ2ZXIsIHdlYlBhdGgsIGNvbmZpZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnNldHVwRGV2U2VydmVyKHNlcnZlciwgY29uZmlnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8g7ZSE66Gc642V7IWYIO2ZmOqyvTog6rCc67OEIEFQSSDrnbzsmrDtirggKyDsoJXsoIEg7YyM7J28IOyEnOu5mVxuICAgICAgZm9yIChjb25zdCBhcGkgb2YgdGhpcy5zeW5jZXIuYXBpcykge1xuICAgICAgICBpZiAodGhpcy5zeW5jZXIubW9kZWxzW2FwaS5tb2RlbE5hbWVdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYOygleydmOuQmOyngCDslYrsnYAg66qo64247JeQIOygkeq3vCAke2FwaS5tb2RlbE5hbWV9YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBAd2Vic29ja2V0IHJvdXRl64qUIHdzSGFuZGxlcuuhnCDrk7HroZ3tlZjqs6AsIOqwmeydgCBwYXRo7J2YIOydvOuwmCBIVFRQIEdFVOydgCA0MjYg7J2R64u17Jy866GcIHVwZ3JhZGXrpbwg6rCV7KCc7ZWoXG4gICAgICAgIGlmIChhcGkud2Vic29ja2V0T3B0aW9ucykge1xuICAgICAgICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICAgICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICAgICAgICB1cmw6IHRoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXggKyBhcGkucGF0aCxcbiAgICAgICAgICAgIGhhbmRsZXI6IHRoaXMuY3JlYXRlV2ViU29ja2V0VXBncmFkZVJlcXVpcmVkSGFuZGxlcigpLFxuICAgICAgICAgICAgd3NIYW5kbGVyOiB0aGlzLmNyZWF0ZVdlYlNvY2tldEhhbmRsZXIoYXBpLCBjb25maWcpLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgc2VydmVyLnJvdXRlKHtcbiAgICAgICAgICBtZXRob2Q6IGFwaS5vcHRpb25zLmh0dHBNZXRob2QgPz8gXCJHRVRcIixcbiAgICAgICAgICB1cmw6IHRoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXggKyBhcGkucGF0aCxcbiAgICAgICAgICBoYW5kbGVyOiB0aGlzLmNyZWF0ZUFwaUhhbmRsZXIoYXBpLCBjb25maWcpLFxuICAgICAgICAgIGNvbXByZXNzOiB0b0Zhc3RpZnlDb21wcmVzc09wdGlvbihhcGkub3B0aW9ucy5jb21wcmVzcywgZ2xvYmFsQ29tcHJlc3NPcHRpb25zKSxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIO2UhOuhnOuNleyFmOyXkOyEnOuKlCB3ZWIg7IaM7IqkKGFwcFJvb3Qvd2ViKSDsnKDrrLTsmYAg66y06rSA7ZWY6rKMLFxuICAgICAgLy8gYXBpL3dlYi1kaXN0IOyhtOyerCDsl6zrtoDrpbwgc2V0dXBTdGF0aWNXZWJTZXJ2ZXIg64K067aA7JeQ7IScIO2MkOuLqO2VqeuLiOuLpC5cbiAgICAgIGF3YWl0IHRoaXMuc2V0dXBTdGF0aWNXZWJTZXJ2ZXIoc2VydmVyLCBjb25maWcsIGdsb2JhbENvbXByZXNzT3B0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIGRldiDrqqjrk5wg6rO17Ya1OiBjYXRjaC1hbGzsl5DshJwgc3luY2VyLmFwaXPrpbwg64+Z7KCB7Jy866GcIO2DkOyDie2VmOyXrCBBUEkg7JqU7LKt7J2EIOyymOumrO2VqeuLiOuLpC5cbiAgICogc2VydmVyLnJvdXRlKCnroZwg6rCc67OEIOuTseuhne2VmOuptCBoYW5kbGVy6rCAIOqzoOygleuQmOyWtCBITVLsnbQg64+Z7J6R7ZWY7KeAIOyViuycvOuvgOuhnCxcbiAgICog66ekIOyalOyyreuniOuLpCBzeW5jZXIuYXBpc+ulvCDsobDtmoztlZjripQg7J20IOuwqeyLneydhCDsgqzsmqntlanri4jri6QuXG4gICAqXG4gICAqIOyalOyyreydtCAvYXBpKOygle2Zle2eiOuKlCB0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4KeuhnCDsi5zsnpHtlZjsp4Ag7JWK64qUIOqyveyasOudvOuptCBudWxs7J2EIOuwmO2ZmO2VmOupsCDrgZ3rg4Xri4jri6QuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZURldkFwaVJlcXVlc3QoXG4gICAgcmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICApOiAoKHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LCByZXBseTogRmFzdGlmeVJlcGx5KSA9PiBQcm9taXNlPHVua25vd24+KSB8IG51bGwge1xuICAgIGNvbnN0IG1hdGNoZWRBcGkgPSB0aGlzLmZpbmRNYXRjaGVkQXBpKHJlcXVlc3QpO1xuXG4gICAgaWYgKCFtYXRjaGVkQXBpKSB7XG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oU0QoXCJlcnJvci5hcGkubm90Rm91bmRcIikpO1xuICAgIH1cblxuICAgIC8vIHdlYnNvY2tldCByb3V0ZeulvCDsnbzrsJggSFRUUOuhnCDsp4HsoJEg7Zi47Lac7ZWcIOqyveyasCA0MjbsnYQg64+M66Ck7KSYIHVwZ3JhZGUg7JeG7J20IOygkeq3vO2VmOuKlCDqsoPsnYQg7LCo64uo7ZWoXG4gICAgaWYgKG1hdGNoZWRBcGkud2Vic29ja2V0T3B0aW9ucykge1xuICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlV2ViU29ja2V0VXBncmFkZVJlcXVpcmVkSGFuZGxlcigpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNyZWF0ZUFwaUhhbmRsZXIobWF0Y2hlZEFwaSwgY29uZmlnKTtcbiAgfVxuXG4gIHByaXZhdGUgZmluZE1hdGNoZWRBcGkocmVxdWVzdDogRmFzdGlmeVJlcXVlc3QpOiBFeHRlbmRlZEFwaSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgdXJsID0gdGhpcy5nZXRQYXRobmFtZUZyb21VcmwocmVxdWVzdC51cmwpO1xuICAgIGNvbnN0IG1ldGhvZCA9IHJlcXVlc3QubWV0aG9kO1xuXG4gICAgaWYgKCF1cmwuc3RhcnRzV2l0aCh0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4KSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zeW5jZXIuYXBpcy5maW5kKChhcGkpID0+IHtcbiAgICAgIGlmICh0aGlzLnN5bmNlci5tb2RlbHNbYXBpLm1vZGVsTmFtZV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBjb25zdCBhcGlNZXRob2QgPSBhcGkub3B0aW9ucy5odHRwTWV0aG9kID8/IFwiR0VUXCI7XG4gICAgICBpZiAoYXBpTWV0aG9kICE9PSBtZXRob2QpIHJldHVybiBmYWxzZTtcblxuICAgICAgY29uc3QgZnVsbFBhdGggPSB0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4ICsgYXBpLnBhdGg7XG4gICAgICByZXR1cm4gdGhpcy5pc1BhdGhQYXR0ZXJuTWF0Y2goZnVsbFBhdGgsIHVybCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogZGV2IGFwaSDrqqjrk5w6IFZpdGUg7JeG7J20IEFQSSDrj5nsoIEg65287Jqw7YyF66eMIOygnOqzte2VqeuLiOuLpC5cbiAgICogSE1S7J2EIOychO2VtCBjYXRjaC1hbGzsl5DshJwg66ekIOyalOyyreuniOuLpCBzeW5jZXIuYXBpc+ulvCDsobDtmoztlanri4jri6QuXG4gICAqL1xuICBwcml2YXRlIHNldHVwRGV2U2VydmVyKFxuICAgIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlPFNlcnZlciwgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZT4sXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICApOiB2b2lkIHtcbiAgICAvLyB1cGdyYWRl64qUIOyLpOyniOyggeycvOuhnCBHRVTsl5DshJzrp4wg7ISx66a97ZWY66+A66GcIEdFVCArIHdzSGFuZGxlciDsmYAg6re4IOyZuCBtZXRob2Trpbwg67OE64+EIHJvdXRl66GcIOu2hOumrO2VqFxuICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICB1cmw6IGAke3RoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXh9LypgLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSB0aGlzLmhhbmRsZURldkFwaVJlcXVlc3QocmVxdWVzdCwgY29uZmlnKTtcbiAgICAgICAgaWYgKGhhbmRsZXIpIHtcbiAgICAgICAgICByZXR1cm4gaGFuZGxlcihyZXF1ZXN0LCByZXBseSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8g65Ox66Gd65CcIEFQSeyZgCDsnbzsuZjtlZjsp4Ag7JWK64qUIOyalOyyreyXkCDrjIDtlZwgZmFsbGJhY2vsnoXri4jri6QuXG4gICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihTRChcImVycm9yLmFwaS5ub3RGb3VuZFwiKSk7XG4gICAgICB9LFxuICAgICAgd3NIYW5kbGVyOiBhc3luYyAoY29ubmVjdGlvbiwgcmVxdWVzdCkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLmhhbmRsZURldldlYlNvY2tldFJlcXVlc3QoY29ubmVjdGlvbi5zb2NrZXQsIHJlcXVlc3QsIGNvbmZpZyk7XG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgc2VydmVyLnJvdXRlKHtcbiAgICAgIG1ldGhvZDogW1wiSEVBRFwiLCBcIlBPU1RcIiwgXCJQVVRcIiwgXCJERUxFVEVcIiwgXCJQQVRDSFwiXSxcbiAgICAgIHVybDogYCR7dGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeH0vKmAsXG4gICAgICBoYW5kbGVyOiBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgY29uc3QgaGFuZGxlciA9IHRoaXMuaGFuZGxlRGV2QXBpUmVxdWVzdChyZXF1ZXN0LCBjb25maWcpO1xuICAgICAgICBpZiAoaGFuZGxlcikge1xuICAgICAgICAgIHJldHVybiBoYW5kbGVyKHJlcXVlc3QsIHJlcGx5KTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oU0QoXCJlcnJvci5hcGkubm90Rm91bmRcIikpO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgdml0ZVNlcnZlcjogYW55ID0gbnVsbDtcblxuICAvKipcbiAgICogZGV2IGFsbCDrqqjrk5w6IFZpdGUgRGV2IFNlcnZlcuulvCDthrXtlantlZjsl6wgQVBJICsgU1NSICsgQ1NS7J2EIOuqqOuRkCDsoJzqs7Xtlanri4jri6QuXG4gICAqIEFQSSDrj5nsoIEg66ek7Lmt7J2AIGhhbmRsZURldkFwaVJlcXVlc3Trpbwg6rO17Jyg7ZWp64uI64ukLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBzZXR1cERldlNlcnZlcldpdGhWaXRlKFxuICAgIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlPFNlcnZlciwgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZT4sXG4gICAgd2ViUGF0aDogc3RyaW5nLFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gQGZhc3RpZnkvbWlkZGllIOuTseuhnSAoQ29ubmVjdC1zdHlsZSBtaWRkbGV3YXJlIOyngOybkClcbiAgICBhd2FpdCBzZXJ2ZXIucmVnaXN0ZXIoKGF3YWl0IGltcG9ydChcIkBmYXN0aWZ5L21pZGRpZVwiKSkuZGVmYXVsdCk7XG5cbiAgICBjb25zdCB2aXRlID0gYXdhaXQgaW1wb3J0KFwidml0ZVwiKTtcbiAgICAvLyBAZmFzdGlmeS93ZWJzb2NrZXQg7ZSM65+s6re47J247J20IO2ZnOyEse2ZlOuQmOuptCBITVIgd2Vic29ja2V06rO8IHNlcnZlciBzb2NrZXTsnbQg7Lap64+M7ZWY66+A66GcIGRlZGljYXRlZCDtj6ztirjroZwg67aE66as7ZWoXG4gICAgY29uc3QgcmVxdWlyZXNEZWRpY2F0ZWRIbXJTZXJ2ZXIgPSBCb29sZWFuKHRoaXMuY29uZmlnLnNlcnZlci5wbHVnaW5zPy53cyk7XG4gICAgY29uc3QgaG1yID0gcmVzb2x2ZUludGVncmF0ZWRWaXRlSG1yT3B0aW9ucyh7XG4gICAgICBodHRwU2VydmVyOiBzZXJ2ZXIuc2VydmVyLFxuICAgICAgcmVxdWlyZXNEZWRpY2F0ZWRXZWJTb2NrZXRTZXJ2ZXI6IHJlcXVpcmVzRGVkaWNhdGVkSG1yU2VydmVyLFxuICAgIH0pO1xuXG4gICAgdGhpcy52aXRlU2VydmVyID0gYXdhaXQgdml0ZS5jcmVhdGVTZXJ2ZXIoe1xuICAgICAgcm9vdDogd2ViUGF0aCxcbiAgICAgIHNlcnZlcjoge1xuICAgICAgICBtaWRkbGV3YXJlTW9kZTogdHJ1ZSxcbiAgICAgICAgaG1yLFxuICAgICAgfSxcbiAgICAgIGFwcFR5cGU6IFwiY3VzdG9tXCIsXG4gICAgfSk7XG5cbiAgICAvLyBWaXRlIG1pZGRsZXdhcmUg65Ox66GdIChWaXRlIOyXkOyFiyDsspjrpqwpXG4gICAgc2VydmVyLnVzZSgocmVxLCByZXMsIG5leHQpID0+IHtcbiAgICAgIC8vIEFQSeyZgCBTb25hbXUgVUnripQgRmFzdGlmeSDrnbzsmrDtirjqsIAg7LKY66as7ZWY64+E66GdIHNraXBcbiAgICAgIGlmIChyZXEudXJsPy5zdGFydHNXaXRoKHRoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXgpIHx8IHJlcS51cmw/LnN0YXJ0c1dpdGgoXCIvc29uYW11LXVpXCIpKSB7XG4gICAgICAgIHJldHVybiBuZXh0KCk7XG4gICAgICB9XG4gICAgICAvLyDrgpjrqLjsp4DripQgVml0ZSBtaWRkbGV3YXJl66GcIOyghOuLrFxuICAgICAgcmV0dXJuIHRoaXMudml0ZVNlcnZlci5taWRkbGV3YXJlcyhyZXEsIHJlcywgbmV4dCk7XG4gICAgfSk7XG5cbiAgICAvLyBXUyB1cGdyYWRlIOqyveuhnChHRVQp7JmAIOydvOuwmCBIVFRQIOuplOyEnOuTnOulvCDrs4Trj4Qgcm91dGXroZwg67aE66as7ZW0IHdlYnNvY2tldCByb3V0ZeqwgCBIVE1MIGZhbGxiYWNr7JeQIOuoue2eiOyngCDslYrrj4TroZ0g7ZWoXG4gICAgc2VydmVyLnJvdXRlKHtcbiAgICAgIG1ldGhvZDogXCJHRVRcIixcbiAgICAgIHVybDogYCR7dGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeH0vKmAsXG4gICAgICBoYW5kbGVyOiBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5oYW5kbGVEZXZBcGlSZXF1ZXN0KHJlcXVlc3QsIGNvbmZpZyk7XG4gICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0KHJlcXVlc3QsIHJlcGx5KTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oU0QoXCJlcnJvci5hcGkubm90Rm91bmRcIikpO1xuICAgICAgfSxcbiAgICAgIHdzSGFuZGxlcjogYXN5bmMgKGNvbm5lY3Rpb24sIHJlcXVlc3QpID0+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5oYW5kbGVEZXZXZWJTb2NrZXRSZXF1ZXN0KGNvbm5lY3Rpb24uc29ja2V0LCByZXF1ZXN0LCBjb25maWcpO1xuICAgICAgfSxcbiAgICB9KTtcblxuICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICBtZXRob2Q6IFtcIkhFQURcIiwgXCJQT1NUXCIsIFwiUFVUXCIsIFwiREVMRVRFXCIsIFwiUEFUQ0hcIl0sXG4gICAgICB1cmw6IGAke3RoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXh9LypgLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuaGFuZGxlRGV2QXBpUmVxdWVzdChyZXF1ZXN0LCBjb25maWcpO1xuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdChyZXF1ZXN0LCByZXBseSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKFNEKFwiZXJyb3IuYXBpLm5vdEZvdW5kXCIpKTtcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyBjYXRjaC1hbGwg65287Jqw7Yq47JeQ7IScIFNTUi9DU1Ig7LKY66asXG4gICAgLy8g6rCc67CcIO2ZmOqyveyXkOyEnOuKlCDrnbzsmrDtirjrs4QgY29tcHJlc3Mg7Ji17IWY7J2EIO2PrOq4sO2VmOqzoCBITVIg7J207KCQ7J2EIOy3qO2VqeuLiOuLpC5cbiAgICBzZXJ2ZXIucm91dGUoe1xuICAgICAgbWV0aG9kOiBbXCJHRVRcIiwgXCJIRUFEXCJdLFxuICAgICAgdXJsOiBcIi8qXCIsXG4gICAgICBoYW5kbGVyOiBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgY29uc3QgdXJsID0gcmVxdWVzdC51cmw7XG5cbiAgICAgICAgLy8gMS4gU1NSIOudvOyasO2KuCDsspjrpqxcbiAgICAgICAgY29uc3QgeyBtYXRjaFNTUlJvdXRlLCByZW5kZXJTU1IgfSA9IGF3YWl0IGltcG9ydChcIi4uL3NzclwiKTtcbiAgICAgICAgY29uc3Qgc3NyTWF0Y2ggPSBtYXRjaFNTUlJvdXRlKHVybCk7XG4gICAgICAgIGlmIChzc3JNYXRjaCkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGBbU1NSXSBNYXRjaGVkIHJvdXRlOiAke3Nzck1hdGNoLnJvdXRlLnBhdGh9YCk7XG4gICAgICAgICAgY29uc3QgaHRtbCA9IGF3YWl0IHJlbmRlclNTUihcbiAgICAgICAgICAgIHVybCxcbiAgICAgICAgICAgIHNzck1hdGNoLnJvdXRlLFxuICAgICAgICAgICAgc3NyTWF0Y2gucGFyYW1zLFxuICAgICAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgICAgIHJlcGx5LFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgdGhpcy52aXRlU2VydmVyLFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmVwbHkudHlwZShcInRleHQvaHRtbFwiKTtcbiAgICAgICAgICByZXR1cm4gaHRtbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDIuIENTUiBmYWxsYmFja1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGZzID0gYXdhaXQgaW1wb3J0KFwibm9kZTpmcy9wcm9taXNlc1wiKTtcbiAgICAgICAgICBsZXQgdGVtcGxhdGUgPSBhd2FpdCBmcy5yZWFkRmlsZShcbiAgICAgICAgICAgIHBhdGguam9pbih0aGlzLnZpdGVTZXJ2ZXIuY29uZmlnLnJvb3QsIFwiaW5kZXguaHRtbFwiKSxcbiAgICAgICAgICAgIFwidXRmLThcIixcbiAgICAgICAgICApO1xuICAgICAgICAgIHRlbXBsYXRlID0gYXdhaXQgdGhpcy52aXRlU2VydmVyLnRyYW5zZm9ybUluZGV4SHRtbCh1cmwsIHRlbXBsYXRlKTtcblxuICAgICAgICAgIHJlcGx5LnR5cGUoXCJ0ZXh0L2h0bWxcIik7XG4gICAgICAgICAgcmV0dXJuIHRlbXBsYXRlO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgdGhpcy52aXRlU2VydmVyLnNzckZpeFN0YWNrdHJhY2UoZSBhcyBFcnJvcik7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgICByZXBseS5zdGF0dXMoNTAwKTtcbiAgICAgICAgICByZXR1cm4gKGUgYXMgRXJyb3IpLm1lc3NhZ2U7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyDshJzrsoQg7KKF66OMIOyLnCBWaXRl64+EIOyiheujjFxuICAgIHNlcnZlci5hZGRIb29rKFwib25DbG9zZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCB0aGlzLnZpdGVTZXJ2ZXIuY2xvc2UoKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IGNoYWxrID0gKGF3YWl0IGltcG9ydChcImNoYWxrXCIpKS5kZWZhdWx0O1xuICAgIGlmIChcInBvcnRcIiBpbiBobXIpIHtcbiAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICBjaGFsay5kaW0oXG4gICAgICAgICAgYOKckyBWaXRlIEhNUiB1c2luZyBkZWRpY2F0ZWQgd2Vic29ja2V0IHBvcnQgJHtobXIucG9ydH0gdG8gYXZvaWQgRmFzdGlmeSB3ZWJzb2NrZXQgY29uZmxpY3RzYCxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKGNoYWxrLmRpbShcIuKckyBWaXRlIGRldiBzZXJ2ZXIgaW50ZWdyYXRlZFwiKSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHNldHVwU3RhdGljV2ViU2VydmVyKFxuICAgIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlPFNlcnZlciwgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZT4sXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICAgIGdsb2JhbENvbXByZXNzT3B0aW9uczogQ29tcHJlc3NPcHRpb25zIHwgdW5kZWZpbmVkLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyDqsr3roZwg66qF7ZmV7ZmUOiBhcGkvd2ViLWRpc3QvY2xpZW50ICjsoJXsoIEg7YyM7J28KSwgYXBpL3dlYi1kaXN0L3NlcnZlciAoU1NSIGVudHJ5KSwgYXBpL2Rpc3Qvc3NyIChTU1Igcm91dGVzIC0gQVBJIOyGjOycoClcbiAgICBjb25zdCB3ZWJEaXN0UGF0aCA9IHBhdGguam9pbih0aGlzLmFwaVJvb3RQYXRoLCBcIndlYi1kaXN0XCIsIFwiY2xpZW50XCIpO1xuICAgIGNvbnN0IHNzclBhdGggPSBwYXRoLmpvaW4odGhpcy5hcGlSb290UGF0aCwgXCJ3ZWItZGlzdFwiLCBcInNlcnZlclwiKTtcbiAgICBjb25zdCBzc3JFbnRyeVBhdGggPSBwYXRoLmpvaW4oc3NyUGF0aCwgXCJlbnRyeS1zZXJ2ZXIuZ2VuZXJhdGVkLmpzXCIpO1xuICAgIGNvbnN0IHNzclJvdXRlc1BhdGggPSBwYXRoLmpvaW4odGhpcy5hcGlSb290UGF0aCwgXCJkaXN0XCIsIFwic3NyXCIsIFwicm91dGVzLmpzXCIpO1xuXG4gICAgaWYgKCEoYXdhaXQgZXhpc3RzKHdlYkRpc3RQYXRoKSkpIHtcbiAgICAgIGNvbnNvbGUud2Fybihg4pqgIFdlYiBkaXN0IG5vdCBmb3VuZDogJHt3ZWJEaXN0UGF0aH1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBTU1IgZW50cnkg7KG07J6sIOyXrOu2gCDtmZXsnbhcbiAgICBjb25zdCBzc3JBdmFpbGFibGUgPSBhd2FpdCBleGlzdHMoc3NyRW50cnlQYXRoKTtcblxuICAgIGlmICghc3NyQXZhaWxhYmxlKSB7XG4gICAgICBjb25zb2xlLndhcm4oYOKaoCBTU1IgZW50cnkgbm90IGZvdW5kOiAke3NzckVudHJ5UGF0aH1gKTtcbiAgICAgIGNvbnNvbGUud2FybihcIiAgU1NSIHdpbGwgYmUgZGlzYWJsZWQuIE9ubHkgQ1NSIHdpbGwgd29yay5cIik7XG4gICAgfVxuXG4gICAgLy8gU1NSIOudvOyasO2KuCDroZzrk5wgKHByb2R1Y3Rpb27sl5DshJzrp4wsIOyCrOyaqeyekCDtlITroZzsoJ3tirjsnZggc3NyL3JvdXRlcy50cylcbiAgICBpZiAoc3NyQXZhaWxhYmxlKSB7XG4gICAgICBpZiAoYXdhaXQgZXhpc3RzKHNzclJvdXRlc1BhdGgpKSB7XG4gICAgICAgIC8vIHRzLWxvYWRlcuudvOuptCBcImZpbGU6Ly9cIuuhnCDsi5zsnpHtlZjripQgZnVsbHktcmVzb2x2ZWQgcGF0aOunjCDrsJvquLDsl5Ag7J2066W8IOyymOumrO2VtOyjvOuKlCBpbXBvcnRNZW1iZXJz66W8IOyCrOyaqe2VtOyVvCDtlojqsqDsp4Drp4wsXG4gICAgICAgIC8vIOyXrOq4sOuKlCDtlITroZzrjZXshZgg7ZmY6rK97JeQ7IScIGxvYWRlciDsl4bsnbQg64+M7JWE6rCA6riwIOuVjOusuOyXkCBcIuynhOynnCBqcyDtjIzsnbxcIuydmCBcIuq3uOuDpVwiIOygiOuMgOqyveuhnOulvCDrsJTroZwgaW1wb3J07ZW064+EIOuQqeuLiOuLpC5cbiAgICAgICAgLy8g7J20IOuCtOyaqeydgCDsnbQg7ZWo7IiYIOuCtOyXkOyEnCDslYTrnpjsl5Ag64KY7JisIOuLpOuluCBpbXBvcnQg7Zi47Lac7JeQ64+EIOuPmeydvO2VmOqyjCDsoIHsmqnrkKnri4jri6QuXG4gICAgICAgIGF3YWl0IGltcG9ydChzc3JSb3V0ZXNQYXRoKTtcbiAgICAgICAgY29uc29sZS5sb2coXCLinJMgU1NSIHJvdXRlcyBsb2FkZWRcIik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLndhcm4oYOKaoCBTU1Igcm91dGVzIG5vdCBmb3VuZDogJHtzc3JSb3V0ZXNQYXRofWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIOuhpOungSDsl4XrjbDsnbTtirgg64yA7J2ROiBhc3NldCBoYXNoIOu2iOydvOy5mCDsi5wg7ZiE7J6sIOuyhOyghCDsp4HsoJEg7ISc67mZXG4gICAgc2VydmVyLmdldChcIi9hc3NldHMvOmZpbGVuYW1lXCIsIGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgY29uc3QgcmVxdWVzdGVkRmlsZSA9IChyZXF1ZXN0LnBhcmFtcyBhcyB7IGZpbGVuYW1lOiBzdHJpbmcgfSkuZmlsZW5hbWU7XG4gICAgICBjb25zdCBhc3NldHNEaXIgPSBwYXRoLmpvaW4od2ViRGlzdFBhdGgsIFwiYXNzZXRzXCIpO1xuICAgICAgY29uc3Qgc2FmZUZpbGVQYXRoID0gdGhpcy5yZXNvbHZlUGF0aFdpdGhpbkJhc2VEaXIoYXNzZXRzRGlyLCByZXF1ZXN0ZWRGaWxlKTtcbiAgICAgIGlmIChzYWZlRmlsZVBhdGggPT09IG51bGwpIHtcbiAgICAgICAgcmVwbHkuc3RhdHVzKDQwMykuc2VuZCgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCBub3JtYWxpemVkUmVxdWVzdGVkRmlsZSA9IHBhdGgucmVsYXRpdmUoYXNzZXRzRGlyLCBzYWZlRmlsZVBhdGgpLnJlcGxhY2UoL1xcXFwvZywgXCIvXCIpO1xuXG4gICAgICBjb25zdCBhc3NldFBhdGggPSBgL2Fzc2V0cy8ke25vcm1hbGl6ZWRSZXF1ZXN0ZWRGaWxlfWA7XG5cbiAgICAgIC8vIENhY2hlLUNvbnRyb2wg7Zek642UIOqysOyglVxuICAgICAgY29uc3QgZ2V0Q2FjaGVDb250cm9sRm9yQXNzZXQgPSAoKTogQ2FjaGVDb250cm9sQ29uZmlnID0+IHtcbiAgICAgICAgY29uc3QgY2FjaGVSZXE6IENhY2hlQ29udHJvbFJlcXVlc3QgPSB7XG4gICAgICAgICAgdHlwZTogXCJhc3NldHNcIixcbiAgICAgICAgICB1cmw6IHJlcXVlc3QudXJsLFxuICAgICAgICAgIHBhdGg6IGFzc2V0UGF0aCxcbiAgICAgICAgICBtZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIOyCrOyaqeyekCDsoJXsnZgg7ZW465Ok65+sIOyasOyEoFxuICAgICAgICBpZiAoY29uZmlnLmNhY2hlQ29udHJvbEhhbmRsZXIpIHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBjb25maWcuY2FjaGVDb250cm9sSGFuZGxlcihjYWNoZVJlcSk7XG4gICAgICAgICAgaWYgKHJlc3VsdCkgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIOq4sOuzuOqwkjogaW1tdXRhYmxlXG4gICAgICAgIHJldHVybiBDYWNoZVByZXNldHMuaW1tdXRhYmxlO1xuICAgICAgfTtcblxuICAgICAgLy8gaW5kZXgtKi5qcyDrmJDripQgaW5kZXgtKi5jc3Mg7JqU7LKt7J24IOqyveyasFxuICAgICAgaWYgKC9eaW5kZXgtW2EtZjAtOV0rXFwuKGpzfGNzcykkLy50ZXN0KG5vcm1hbGl6ZWRSZXF1ZXN0ZWRGaWxlKSkge1xuICAgICAgICBjb25zdCBleHQgPSBub3JtYWxpemVkUmVxdWVzdGVkRmlsZS5zcGxpdChcIi5cIikucG9wKCk7XG4gICAgICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgZnMucmVhZGRpcihhc3NldHNEaXIpO1xuICAgICAgICBjb25zdCBjdXJyZW50RmlsZSA9IGZpbGVzLmZpbmQoKGYpID0+IGYuc3RhcnRzV2l0aChcImluZGV4LVwiKSAmJiBmLmVuZHNXaXRoKGAuJHtleHR9YCkpO1xuXG4gICAgICAgIGlmIChjdXJyZW50RmlsZSkge1xuICAgICAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5qb2luKGFzc2V0c0RpciwgY3VycmVudEZpbGUpO1xuICAgICAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShmaWxlUGF0aCk7XG4gICAgICAgICAgcmVwbHkudHlwZShleHQgPT09IFwianNcIiA/IFwiYXBwbGljYXRpb24vamF2YXNjcmlwdFwiIDogXCJ0ZXh0L2Nzc1wiKTtcbiAgICAgICAgICBhcHBseUNhY2hlSGVhZGVycyhyZXBseSwgZ2V0Q2FjaGVDb250cm9sRm9yQXNzZXQoKSk7XG4gICAgICAgICAgcmV0dXJuIHJlcGx5LnNlbmQoY29udGVudCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8g7J2867CYIO2MjOydvCDshJzruZlcbiAgICAgIGNvbnN0IGZpbGVQYXRoID0gc2FmZUZpbGVQYXRoO1xuICAgICAgaWYgKGF3YWl0IGV4aXN0cyhmaWxlUGF0aCkpIHtcbiAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVQYXRoKTtcbiAgICAgICAgY29uc3QgZXh0ID0gbm9ybWFsaXplZFJlcXVlc3RlZEZpbGUuc3BsaXQoXCIuXCIpLnBvcCgpO1xuICAgICAgICByZXBseS50eXBlKGV4dCA9PT0gXCJqc1wiID8gXCJhcHBsaWNhdGlvbi9qYXZhc2NyaXB0XCIgOiBleHQgPT09IFwiY3NzXCIgPyBcInRleHQvY3NzXCIgOiBcIlwiKTtcbiAgICAgICAgaWYgKG5vcm1hbGl6ZWRSZXF1ZXN0ZWRGaWxlLmluY2x1ZGVzKFwiLVwiKSkge1xuICAgICAgICAgIGFwcGx5Q2FjaGVIZWFkZXJzKHJlcGx5LCBnZXRDYWNoZUNvbnRyb2xGb3JBc3NldCgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVwbHkuc2VuZChjb250ZW50KTtcbiAgICAgIH1cblxuICAgICAgcmVwbHkuc3RhdHVzKDQwNCkuc2VuZCgpO1xuICAgIH0pO1xuXG4gICAgLy8gU1NSIOudvOyasO2KuCDqsJzrs4Qg65Ox66GdIChjb21wcmVzcyDsmLXshZjsnbQg65287Jqw7Yq467OE66GcIOyggeyaqeuQmOuPhOuhnSlcbiAgICBpZiAoc3NyQXZhaWxhYmxlKSB7XG4gICAgICBjb25zdCB7IGdldFNTUlJvdXRlcyB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3NyXCIpO1xuICAgICAgY29uc3QgeyByZW5kZXJTU1IgfSA9IGF3YWl0IGltcG9ydChcIi4uL3Nzci9yZW5kZXJlclwiKTtcbiAgICAgIGNvbnN0IHNzclJvdXRlcyA9IGdldFNTUlJvdXRlcygpO1xuXG4gICAgICBmb3IgKGNvbnN0IHJvdXRlIG9mIHNzclJvdXRlcykge1xuICAgICAgICBzZXJ2ZXIucm91dGUoe1xuICAgICAgICAgIG1ldGhvZDogW1wiR0VUXCIsIFwiSEVBRFwiXSxcbiAgICAgICAgICB1cmw6IHJvdXRlLnBhdGgsXG4gICAgICAgICAgY29tcHJlc3M6IHRvRmFzdGlmeUNvbXByZXNzT3B0aW9uKHJvdXRlLmNvbXByZXNzID8/IHRydWUsIGdsb2JhbENvbXByZXNzT3B0aW9ucyksXG4gICAgICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB1cmwgPSByZXF1ZXN0LnVybDtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBbU1NSXSBNYXRjaGVkIHJvdXRlOiAke3JvdXRlLnBhdGh9YCk7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IHRoaXMuZXh0cmFjdFBhdGhQYXJhbXMocm91dGUucGF0aCwgdXJsKTtcbiAgICAgICAgICAgIGNvbnN0IGh0bWwgPSBhd2FpdCByZW5kZXJTU1IodXJsLCByb3V0ZSwgcGFyYW1zLCByZXF1ZXN0LCByZXBseSwgY29uZmlnKTtcblxuICAgICAgICAgICAgcmVwbHkudHlwZShcInRleHQvaHRtbFwiKTtcbiAgICAgICAgICAgIHJldHVybiBodG1sO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENTUiBvciBTdGF0aWMgRmlsZSBGYWxsYmFjayAoU1NSIOudvOyasO2KuOyXkCDrp6Tsua3rkJjsp4Ag7JWK64qUIOuqqOuToCDsmpTssq0pXG4gICAgc2VydmVyLnJvdXRlKHtcbiAgICAgIG1ldGhvZDogW1wiR0VUXCIsIFwiSEVBRFwiXSxcbiAgICAgIHVybDogXCIqXCIsXG4gICAgICBoYW5kbGVyOiBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgLy8gL2FwaSwgL3NvbmFtdS11aeuKlCA0MDQg6re464yA66GcXG4gICAgICAgIGlmIChyZXF1ZXN0LnVybC5zdGFydHNXaXRoKFwiL2FwaVwiKSB8fCByZXF1ZXN0LnVybC5zdGFydHNXaXRoKFwiL3NvbmFtdS11aVwiKSkge1xuICAgICAgICAgIHJlcGx5LnN0YXR1cyg0MDQpLnNlbmQoKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDU1LsmqkgQ2FjaGUtQ29udHJvbCDtl6TrjZQg7ISk7KCVXG4gICAgICAgIGlmIChjb25maWcuY2FjaGVDb250cm9sSGFuZGxlcikge1xuICAgICAgICAgIGNvbnN0IGNzckNhY2hlUmVxOiBDYWNoZUNvbnRyb2xSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgdHlwZTogXCJjc3JcIixcbiAgICAgICAgICAgIHVybDogcmVxdWVzdC51cmwsXG4gICAgICAgICAgICBwYXRoOiByZXF1ZXN0LnVybC5zcGxpdChcIj9cIilbMF0sXG4gICAgICAgICAgICBtZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuICAgICAgICAgIH07XG4gICAgICAgICAgY29uc3QgY3NyQ2FjaGVDb25maWcgPSBjb25maWcuY2FjaGVDb250cm9sSGFuZGxlcihjc3JDYWNoZVJlcSk7XG5cbiAgICAgICAgICBpZiAoY3NyQ2FjaGVDb25maWcpIHtcbiAgICAgICAgICAgIGFwcGx5Q2FjaGVIZWFkZXJzKHJlcGx5LCBjc3JDYWNoZUNvbmZpZyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8g7KCV7KCBIO2MjOydvOydtCDsobTsnqztlaAg6rK97JqwLCDsoJXsoIEg7YyM7J287J2EIOuovOyggCDshJzruZntlbTslbztlahcbiAgICAgICAgY29uc3QgcmVxdWVzdFBhdGggPSB0aGlzLmdldFBhdGhuYW1lRnJvbVVybChyZXF1ZXN0LnVybCk7XG4gICAgICAgIGNvbnN0IHNhZmVGaWxlUGF0aCA9IHRoaXMucmVzb2x2ZVBhdGhXaXRoaW5CYXNlRGlyKHdlYkRpc3RQYXRoLCByZXF1ZXN0UGF0aCk7XG4gICAgICAgIGlmIChzYWZlRmlsZVBhdGggPT09IG51bGwpIHtcbiAgICAgICAgICByZXBseS5zdGF0dXMoNDAzKS5zZW5kKCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhd2FpdCBmaWxlRXhpc3RzKHNhZmVGaWxlUGF0aCkpIHtcbiAgICAgICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUoc2FmZUZpbGVQYXRoKTtcbiAgICAgICAgICByZXR1cm4gcmVwbHkudHlwZShtaW1lTG9va3VwKHNhZmVGaWxlUGF0aCkgfHwgXCJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW1cIikuc2VuZChjb250ZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENTUiBmYWxsYmFjazogaW5kZXguaHRtbCDshJzruZlcbiAgICAgICAgY29uc3QgaW5kZXhQYXRoID0gcGF0aC5qb2luKHdlYkRpc3RQYXRoLCBcImluZGV4Lmh0bWxcIik7XG4gICAgICAgIHJldHVybiByZXBseS50eXBlKFwidGV4dC9odG1sXCIpLnNlbmQoYXdhaXQgZnMucmVhZEZpbGUoaW5kZXhQYXRoLCBcInV0Zi04XCIpKTtcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBjb25zb2xlLmxvZyhg4pyTIFN0YXRpYyB3ZWIgc2VydmVyIGNvbmZpZ3VyZWQgd2l0aCAke3NzckF2YWlsYWJsZSA/IFwiU1NSXCIgOiBcIkNTUiBvbmx5XCJ9IHN1cHBvcnRgKTtcbiAgfVxuXG4gIGNyZWF0ZUFwaUhhbmRsZXIoXG4gICAgYXBpOiBFeHRlbmRlZEFwaSxcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICk6IChyZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCwgcmVwbHk6IEZhc3RpZnlSZXBseSkgPT4gUHJvbWlzZTx1bmtub3duPiB7XG4gICAgcmV0dXJuIGFzeW5jIChyZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCwgcmVwbHk6IEZhc3RpZnlSZXBseSk6IFByb21pc2U8dW5rbm93bj4gPT4ge1xuICAgICAgLy8gQ29udGV4dCDsg53shLFcbiAgICAgIGNvbnN0IGNvbnRleHQ6IENvbnRleHQgPSBhd2FpdCB0aGlzLmNyZWF0ZUNvbnRleHQoY29uZmlnLCByZXF1ZXN0LCByZXBseSk7XG5cbiAgICAgIHJldHVybiB0aGlzLmFzeW5jTG9jYWxTdG9yYWdlLnJ1bih7IGNvbnRleHQgfSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAvLyBndWFyZHMg7LKY66asXG4gICAgICAgIHJ1bkd1YXJkcyh7XG4gICAgICAgICAgZ3VhcmRzOiBhcGkub3B0aW9ucy5ndWFyZHMsXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgYXBpLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyDtjIzrnbzrr7jthLAg7KCV67O066GcIHpvZCDsiqTtgqTrp4gg67mM65OcXG4gICAgICAgIGNvbnN0IHsgZ2V0Wm9kT2JqZWN0RnJvbUFwaSB9ID0gYXdhaXQgaW1wb3J0KFwiLi9jb2RlLWNvbnZlcnRlcnNcIik7XG4gICAgICAgIGNvbnN0IFJlcVR5cGUgPSBnZXRab2RPYmplY3RGcm9tQXBpKGFwaSwgdGhpcy5zeW5jZXIudHlwZXMpO1xuXG4gICAgICAgIC8vIHJlcXVlc3Qg7YyM7IuxXG4gICAgICAgIGNvbnN0IHdoaWNoID0gYXBpLm9wdGlvbnMuaHR0cE1ldGhvZCA9PT0gXCJHRVRcIiA/IFwicXVlcnlcIiA6IFwiYm9keVwiO1xuICAgICAgICBsZXQgcmVxQm9keToge1xuICAgICAgICAgIFtrZXk6IHN0cmluZ106IHVua25vd247XG4gICAgICAgIH07XG4gICAgICAgIC8vIO2MjOydvCDsl4XroZzrk5wg7J6I64qUIOqyveyasCDsnoTsi5wg642w7J207YSwXG4gICAgICAgIGNvbnN0IGZpbGVzOiB7XG4gICAgICAgICAgYnVmZmVyZWRGaWxlczogQnVmZmVyZWRGaWxlW107XG4gICAgICAgICAgdXBsb2FkZWRGaWxlczogVXBsb2FkZWRGaWxlW107XG4gICAgICAgIH0gPSB7XG4gICAgICAgICAgYnVmZmVyZWRGaWxlczogW10sXG4gICAgICAgICAgdXBsb2FkZWRGaWxlczogW10sXG4gICAgICAgIH07XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBib2R5ID0gKHJlcXVlc3Rbd2hpY2hdID8/IHt9KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgICAgICBpZiAoYXBpLnVwbG9hZE9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcnRzID0gcmVxdWVzdC5wYXJ0cyh7XG4gICAgICAgICAgICAgIGxpbWl0czogYXBpLnVwbG9hZE9wdGlvbnMubGltaXRzLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIEZvcm1EYXRh7J2YIGZpZWxk65Ok7J2EIOyehOyLnOuhnCDsoIDsnqVcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoYXBpLnVwbG9hZE9wdGlvbnMuY29uc3VtZSA9PT0gXCJidWZmZXJcIiB8fCAhYXBpLnVwbG9hZE9wdGlvbnMuY29uc3VtZSkge1xuICAgICAgICAgICAgICAvLyBCdWZmZXIg66qo65OcOiDrqZTrqqjrpqzsl5Ag66Gc65OcXG4gICAgICAgICAgICAgIGZvciBhd2FpdCAoY29uc3QgcGFydCBvZiBwYXJ0cykge1xuICAgICAgICAgICAgICAgIGlmIChwYXJ0LnR5cGUgPT09IFwiZmlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAvLyBDUklUSUNBTDog7YyM7J28IOyKpO2KuOumvOydhCDsponsi5wgY29uc3VtZe2VtOyVvCDri6TsnYwgcGFydOuhnCDrhJjslrTqsIgg7IiYIOyeiOydjFxuICAgICAgICAgICAgICAgICAgLy8g7J20IO2YuOy2nOydtCDsl4bsnLzrqbQg7KKF7KKFIG11bHRpcGFydCDtjIzsi7HsnbQgcGVuZGluZyDsg4Htg5zroZwg7YOA7J6E7JWE7JuDIOuwnOyDnVxuICAgICAgICAgICAgICAgICAgY29uc3QgYnVmZmVyID0gYXdhaXQgcGFydC50b0J1ZmZlcigpO1xuICAgICAgICAgICAgICAgICAgZmlsZXMuYnVmZmVyZWRGaWxlcy5wdXNoKG5ldyBCdWZmZXJlZEZpbGUocGFydCwgYnVmZmVyKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwYXJ0LnR5cGUgPT09IFwiZmllbGRcIikge1xuICAgICAgICAgICAgICAgICAgZmllbGRzW3BhcnQuZmllbGRuYW1lXSA9IFN0cmluZyhwYXJ0LnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYXBpLnVwbG9hZE9wdGlvbnMuY29uc3VtZSA9PT0gXCJzdHJlYW1cIikge1xuICAgICAgICAgICAgICAvLyBTdHJlYW0g66qo65OcOiDsponsi5wg7KCA7J6l7IaM66GcIOyKpO2KuOumrOuwjVxuICAgICAgICAgICAgICBjb25zdCBkaXNrTmFtZSA9IGFwaS51cGxvYWRPcHRpb25zLmRlc3RpbmF0aW9uO1xuICAgICAgICAgICAgICBjb25zdCBkaXNrID0gdGhpcy5zdG9yYWdlLnVzZShkaXNrTmFtZSk7XG5cbiAgICAgICAgICAgICAgLy8g7Jqw7ISg7Iic7JyEOiDrjbDsvZTroIjsnbTthLAgPiDsoITsl60g7ISk7KCVID4g6riw67O46rCSXG4gICAgICAgICAgICAgIGNvbnN0IGtleUdlbmVyYXRvcjogS2V5R2VuZXJhdG9yID1cbiAgICAgICAgICAgICAgICBhcGkudXBsb2FkT3B0aW9ucy5rZXlHZW5lcmF0b3IgPz9cbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5zZXJ2ZXIuc3RvcmFnZT8ua2V5R2VuZXJhdG9yID8/XG4gICAgICAgICAgICAgICAgZGVmYXVsdEtleUdlbmVyYXRvcjtcblxuICAgICAgICAgICAgICBmb3IgYXdhaXQgKGNvbnN0IHBhcnQgb2YgcGFydHMpIHtcbiAgICAgICAgICAgICAgICBpZiAocGFydC50eXBlID09PSBcImZpbGVcIikge1xuICAgICAgICAgICAgICAgICAgY29uc3Qga2V5ID0gYXdhaXQga2V5R2VuZXJhdG9yKHtcbiAgICAgICAgICAgICAgICAgICAgZmlsZW5hbWU6IHBhcnQuZmlsZW5hbWUsXG4gICAgICAgICAgICAgICAgICAgIG1pbWV0eXBlOiBwYXJ0Lm1pbWV0eXBlLFxuICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgIGF3YWl0IGRpc2sucHV0U3RyZWFtKGtleSwgcGFydC5maWxlLCB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlOiBwYXJ0Lm1pbWV0eXBlLFxuICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IHVybCA9IGF3YWl0IGRpc2suZ2V0VXJsKGtleSk7XG4gICAgICAgICAgICAgICAgICBjb25zdCBzaWduZWRVcmwgPSBhd2FpdCBkaXNrLmdldFNpZ25lZFVybChrZXkpO1xuXG4gICAgICAgICAgICAgICAgICBmaWxlcy51cGxvYWRlZEZpbGVzLnB1c2goXG4gICAgICAgICAgICAgICAgICAgIG5ldyBVcGxvYWRlZEZpbGUoe1xuICAgICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lOiBwYXJ0LmZpbGVuYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIG1pbWV0eXBlOiBwYXJ0Lm1pbWV0eXBlLFxuICAgICAgICAgICAgICAgICAgICAgIHNpemU6IHBhcnQuZmlsZS5ieXRlc1JlYWQsXG4gICAgICAgICAgICAgICAgICAgICAgdXJsLFxuICAgICAgICAgICAgICAgICAgICAgIHNpZ25lZFVybCxcbiAgICAgICAgICAgICAgICAgICAgICBrZXksXG4gICAgICAgICAgICAgICAgICAgICAgZGlza05hbWUsXG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBhcnQudHlwZSA9PT0gXCJmaWVsZFwiKSB7XG4gICAgICAgICAgICAgICAgICBmaWVsZHNbcGFydC5maWVsZG5hbWVdID0gU3RyaW5nKHBhcnQudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBxc+uhnCDspJHssqkg6rWs7KGwIO2MjOyLsTogcGFyYW1zW2NhdGVnb3J5XSDihpIgeyBwYXJhbXM6IHsgY2F0ZWdvcnk6IFwidGVzdFwiIH0gfVxuICAgICAgICAgICAgY29uc3QgcXMgPSBhd2FpdCBpbXBvcnQoXCJxc1wiKTtcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHFzLmRlZmF1bHQucGFyc2UoZmllbGRzKTtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oYm9keSwgcGFyc2VkKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCB7IGZhc3RpZnlDYXN0ZXIgfSA9IGF3YWl0IGltcG9ydChcIi4vY2FzdGVyXCIpO1xuICAgICAgICAgIHJlcUJvZHkgPSBmYXN0aWZ5Q2FzdGVyKFJlcVR5cGUpLnBhcnNlKGJvZHkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgY29uc3QgeyBab2RFcnJvciB9ID0gYXdhaXQgaW1wb3J0KFwiem9kXCIpO1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgWm9kRXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgaHVtYW5pemVab2RFcnJvciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvem9kLWVycm9yXCIpO1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZXMgPSBodW1hbml6ZVpvZEVycm9yKGUpXG4gICAgICAgICAgICAgIC5tYXAoKGlzc3VlKSA9PiBpc3N1ZS5tZXNzYWdlKVxuICAgICAgICAgICAgICAuam9pbihcIiBcIik7XG4gICAgICAgICAgICBjb25zdCB7IEJhZFJlcXVlc3RFeGNlcHRpb24gfSA9IGF3YWl0IGltcG9ydChcIi4uL2V4Y2VwdGlvbnMvc28tZXhjZXB0aW9uc1wiKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKG1lc3NhZ2VzIGFzIExvY2FsaXplZFN0cmluZywge1xuICAgICAgICAgICAgICB6b2RFcnJvcjogZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbnRlbnQtVHlwZVxuICAgICAgICByZXBseS50eXBlKGFwaS5vcHRpb25zLmNvbnRlbnRUeXBlID8/IFwiYXBwbGljYXRpb24vanNvblwiKTtcblxuICAgICAgICAvLyBDYWNoZS1Db250cm9sIO2XpOuNlCDshKTsoJVcbiAgICAgICAgY29uc3QgYXBpQ2FjaGVDb25maWcgPSB0aGlzLmdldEFwaUNhY2hlQ29udHJvbChhcGksIHJlcXVlc3QsIGNvbmZpZyk7XG4gICAgICAgIGlmIChhcGlDYWNoZUNvbmZpZykge1xuICAgICAgICAgIGFwcGx5Q2FjaGVIZWFkZXJzKHJlcGx5LCBhcGlDYWNoZUNvbmZpZyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyDsl4XroZzrk5wg7Ji17IWY7J20IOyeiOuKlCDqsr3smrAg7YyM7J28IOuNsOydtO2EsOulvCBDb250ZXh07JeQIOy2lOqwgFxuICAgICAgICBpZiAoYXBpLnVwbG9hZE9wdGlvbnMpIHtcbiAgICAgICAgICBjb25zdCBjb25zdW1lID0gYXBpLnVwbG9hZE9wdGlvbnMuY29uc3VtZSA/PyBcImJ1ZmZlclwiO1xuICAgICAgICAgIGlmIChjb25zdW1lID09PSBcImJ1ZmZlclwiKSB7XG4gICAgICAgICAgICBjb250ZXh0LmJ1ZmZlcmVkRmlsZXMgPSBmaWxlcy5idWZmZXJlZEZpbGVzO1xuICAgICAgICAgIH0gZWxzZSBpZiAoY29uc3VtZSA9PT0gXCJzdHJlYW1cIikge1xuICAgICAgICAgICAgY29udGV4dC51cGxvYWRlZEZpbGVzID0gZmlsZXMudXBsb2FkZWRGaWxlcztcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyDrqqjrjbgg66mU7IaM65OcIGFyZ3Mg7IOd7ISx7ZWY7JesIO2YuOy2nFxuICAgICAgICBjb25zdCB7IEFwaVBhcmFtVHlwZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdHlwZXMvdHlwZXNcIik7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBhcGkucGFyYW1ldGVycy5tYXAoKHBhcmFtKSA9PiB7XG4gICAgICAgICAgLy8gQ29udGV4dCDsnbjsoJ3shZhcbiAgICAgICAgICBpZiAoQXBpUGFyYW1UeXBlLmlzQ29udGV4dChwYXJhbS50eXBlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiByZXFCb2R5W3BhcmFtLm5hbWVdO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuaW52b2tlTW9kZWxNZXRob2QoYXBpLCBhcmdzLCByZXBseSk7XG4gICAgICB9KTtcbiAgICB9O1xuICB9XG5cbiAgLy8gV1MgcGF0aOulvCDsnbzrsJggSFRUUCBHRVTsnLzroZwg7Zi47Lac7ZWcIOqyveyasCA0MjYgKyBVcGdyYWRlIO2XpOuNlOuhnCDrqoXsi5zsoIHsnLzroZwgd2Vic29ja2V0IOygkeyGjeydhCDsnKDrj4TtlahcbiAgcHJpdmF0ZSBjcmVhdGVXZWJTb2NrZXRVcGdyYWRlUmVxdWlyZWRIYW5kbGVyKCkge1xuICAgIHJldHVybiBhc3luYyAoX3JlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LCByZXBseTogRmFzdGlmeVJlcGx5KTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICByZXBseS5oZWFkZXIoXCJjb25uZWN0aW9uXCIsIFwiVXBncmFkZVwiKS5oZWFkZXIoXCJ1cGdyYWRlXCIsIFwid2Vic29ja2V0XCIpLnN0YXR1cyg0MjYpLnNlbmQoe1xuICAgICAgICBtZXNzYWdlOiBcIldlYlNvY2tldCB1cGdyYWRlIHJlcXVpcmVkXCIsXG4gICAgICB9KTtcbiAgICB9O1xuICB9XG5cbiAgLy8gZGV2IOuqqOuTnOydmCBjYXRjaC1hbGwgd3NIYW5kbGVy7JeQ7IScIOyLpOygnCBXUyBBUEnroZwg65SU7Iqk7Yyo7LmY7ZWoLiDrp6Tsua3rkJjripQgcm91dGXqsIAg7JeG7Jy866m0IDEwMDjroZwg64ur7J2MXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlRGV2V2ViU29ja2V0UmVxdWVzdChcbiAgICBzb2NrZXQ6IFdlYlNvY2tldCxcbiAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG1hdGNoZWRBcGkgPSB0aGlzLmZpbmRNYXRjaGVkQXBpKHJlcXVlc3QpO1xuICAgIGlmICghbWF0Y2hlZEFwaT8ud2Vic29ja2V0T3B0aW9ucykge1xuICAgICAgY29uc3QgdHJhY2VDb250ZXh0ID0gdGhpcy53ZWJzb2NrZXRSdW50aW1lLnRlbGVtZXRyeUNvbnRyb2xsZXIuY3JlYXRlQ29ubmVjdGlvbkNvbnRleHQoe1xuICAgICAgICBoZWFkZXJzOiByZXF1ZXN0LmhlYWRlcnMsXG4gICAgICB9KTtcbiAgICAgIHRoaXMud2Vic29ja2V0UnVudGltZS50ZWxlbWV0cnlDb250cm9sbGVyLmVtaXQoe1xuICAgICAgICBuYW1lOiBcIndzLmNvbm5lY3Rpb24ucmVqZWN0ZWRcIixcbiAgICAgICAgbGV2ZWw6IFwid2FyblwiLFxuICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICByZWFzb246IFwicm91dGVOb3RGb3VuZFwiLFxuICAgICAgICAgIHBhdGg6IHJlcXVlc3QudXJsLFxuICAgICAgICB9LFxuICAgICAgICB0cmFjZUlkOiB0cmFjZUNvbnRleHQudHJhY2VJZCxcbiAgICAgICAgc3BhbklkOiB0cmFjZUNvbnRleHQuc3BhbklkLFxuICAgICAgICBwYXJlbnRTcGFuSWQ6IHRyYWNlQ29udGV4dC5wYXJlbnRTcGFuSWQsXG4gICAgICAgIHNhbXBsZWQ6IHRyYWNlQ29udGV4dC5zYW1wbGVkLFxuICAgICAgfSk7XG4gICAgICBzb2NrZXQuY2xvc2UoMTAwOCwgXCJXZWJTb2NrZXQgcm91dGUgbm90IGZvdW5kXCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGhhbmRsZXIgPSB0aGlzLmNyZWF0ZVdlYlNvY2tldEhhbmRsZXIobWF0Y2hlZEFwaSwgY29uZmlnKTtcbiAgICBhd2FpdCBoYW5kbGVyKHsgc29ja2V0IH0sIHJlcXVlc3QpO1xuICB9XG5cbiAgLy8gV1Mgcm91dGUg7ZW465Ok65+s7J2YIOyLpO2WiSDsiJzshJzrpbwg6rOg7KCV7ZWoOlxuICAvLyAxKSBndWFyZOulvCBjb25uZWN0aW9uIOuTseuhnSDsnbTsoITsl5Ag64+M66CkIOyduOymnSDsi6TtjKgg7IucIOu2gOu2hCDrk7HroZ0g7IOB7YOc66W8IOuCqOq4sOyngCDslYrsnYxcbiAgLy8gMikgcXVlcnkgcGFyYW0g7YyM7Iux64+EIGFjdGl2YXRpb24g7KCE7JeQIOuBneuCtCBoYW5kc2hha2Ug7Iuk7Yyo6rCAIHJlZ2lzdHJ57JeQIOuFuOy2nOuQmOyngCDslYrqsowg7ZWoXG4gIC8vIDMpIGBhY3RpdmU6IGZhbHNlYOuhnCDrqLzsoIAg65Ox66Gd7ZWY6rOgLCBjb250ZXh0IOykgOu5hOqwgCDrgZ3rgpwg65KkIGBhY3RpdmF0ZSgpYO2VtCDruIzroZzrk5zsupDsiqTtirjqsIAg7LSI6riw7ZmUIOykkeqwhCDsg4Htg5zrpbwg67O07KeAIOuqu+2VmOqyjCDtlahcbiAgLy8g7JeQ65+sIOuwnOyDnSDsi5zsl5DripQgcmVzb2x2ZVdlYlNvY2tldENsb3NlRGVzY3JpcHRvciDsoJXssYXsl5Ag65Sw6528IGNsb3NlIGNvZGXrpbwg66ek7ZWR7ZWoXG4gIHByaXZhdGUgY3JlYXRlV2ViU29ja2V0SGFuZGxlcihhcGk6IEV4dGVuZGVkQXBpLCBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcpIHtcbiAgICByZXR1cm4gYXN5bmMgKFxuICAgICAgY29ubmVjdGlvbjoge1xuICAgICAgICBzb2NrZXQ6IFdlYlNvY2tldDtcbiAgICAgIH0sXG4gICAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICApOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgIGNvbnN0IHNvY2tldCA9IGNvbm5lY3Rpb24uc29ja2V0O1xuICAgICAgbGV0IHdzQ29udGV4dDogV2ViU29ja2V0Q29udGV4dCB8IG51bGwgPSBudWxsO1xuICAgICAgbGV0IHJhd1dzOiBSZXR1cm5UeXBlPFdlYlNvY2tldFJ1bnRpbWVbXCJyZWdpc3RlckNvbm5lY3Rpb25cIl0+IHwgbnVsbCA9IG51bGw7XG4gICAgICBsZXQgcHJlUmVnaXN0ZXJQaGFzZTogXCJndWFyZFwiIHwgXCJxdWVyeVwiIHwgXCJyZWdpc3RlclwiIHwgXCJoYW5kbGVyXCIgPSBcImd1YXJkXCI7XG4gICAgICBsZXQgdHJhY2VDb250ZXh0OiBXZWJTb2NrZXRUZWxlbWV0cnlDb25uZWN0aW9uQ29udGV4dCA9IHt9O1xuXG4gICAgICB0cnkge1xuICAgICAgICB0cmFjZUNvbnRleHQgPSB0aGlzLndlYnNvY2tldFJ1bnRpbWUudGVsZW1ldHJ5Q29udHJvbGxlci5jcmVhdGVDb25uZWN0aW9uQ29udGV4dCh7XG4gICAgICAgICAgaGVhZGVyczogcmVxdWVzdC5oZWFkZXJzLFxuICAgICAgICB9KTtcblxuICAgICAgICBwcmVSZWdpc3RlclBoYXNlID0gXCJxdWVyeVwiO1xuICAgICAgICBjb25zdCByZXFCb2R5ID0gYXdhaXQgdGhpcy5wYXJzZVdlYlNvY2tldFJlcXVlc3RQYXJhbXMoYXBpLCByZXF1ZXN0KTtcbiAgICAgICAgcHJlUmVnaXN0ZXJQaGFzZSA9IFwicmVnaXN0ZXJcIjtcbiAgICAgICAgcmF3V3MgPSB0aGlzLndlYnNvY2tldFJ1bnRpbWUucmVnaXN0ZXJDb25uZWN0aW9uKHNvY2tldCwge1xuICAgICAgICAgIG91dEV2ZW50czogYXBpLndlYnNvY2tldE9wdGlvbnMhLm91dEV2ZW50cyxcbiAgICAgICAgICBpbkV2ZW50czogYXBpLndlYnNvY2tldE9wdGlvbnMhLmluRXZlbnRzLFxuICAgICAgICAgIG5hbWVzcGFjZTogYXBpLndlYnNvY2tldE9wdGlvbnMhLm5hbWVzcGFjZSxcbiAgICAgICAgICBoZWFydGJlYXQ6IGFwaS53ZWJzb2NrZXRPcHRpb25zIS5oZWFydGJlYXQsXG4gICAgICAgICAgYWN0aXZlOiBmYWxzZSxcbiAgICAgICAgICB0cmFjZUlkOiB0cmFjZUNvbnRleHQudHJhY2VJZCxcbiAgICAgICAgICBzcGFuSWQ6IHRyYWNlQ29udGV4dC5zcGFuSWQsXG4gICAgICAgICAgcGFyZW50U3BhbklkOiB0cmFjZUNvbnRleHQucGFyZW50U3BhbklkLFxuICAgICAgICAgIHNhbXBsZWQ6IHRyYWNlQ29udGV4dC5zYW1wbGVkLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBzY29wZWRXcyA9IHRoaXMuY3JlYXRlU2NvcGVkV2ViU29ja2V0Q29ubmVjdGlvbihyYXdXcywgKCkgPT4gd3NDb250ZXh0KTtcbiAgICAgICAgd3NDb250ZXh0ID0gYXdhaXQgdGhpcy5jcmVhdGVXZWJTb2NrZXRDb250ZXh0KGNvbmZpZywgcmVxdWVzdCwgc2NvcGVkV3MpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuYXN5bmNMb2NhbFN0b3JhZ2UucnVuKHsgY29udGV4dDogd3NDb250ZXh0IH0sIGFzeW5jICgpID0+IHtcbiAgICAgICAgICBydW5HdWFyZHMoe1xuICAgICAgICAgICAgZ3VhcmRzOiBhcGkub3B0aW9ucy5ndWFyZHMsXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgICAgYXBpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLndlYnNvY2tldFJ1bnRpbWUuYWN0aXZhdGVDb25uZWN0aW9uKHJhd1dzLmlkKTtcbiAgICAgICAgcHJlUmVnaXN0ZXJQaGFzZSA9IFwiaGFuZGxlclwiO1xuXG4gICAgICAgIGNvbnN0IHsgQXBpUGFyYW1UeXBlIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi90eXBlcy90eXBlc1wiKTtcbiAgICAgICAgY29uc3QgYXJncyA9IGFwaS5wYXJhbWV0ZXJzLm1hcCgocGFyYW0pID0+IHtcbiAgICAgICAgICBpZiAoQXBpUGFyYW1UeXBlLmlzQ29udGV4dChwYXJhbS50eXBlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHdzQ29udGV4dDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gcmVxQm9keVtwYXJhbS5uYW1lXTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5hc3luY0xvY2FsU3RvcmFnZS5ydW4oeyBjb250ZXh0OiB3c0NvbnRleHQgfSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGF3YWl0IHRoaXMuaW52b2tlTW9kZWxNZXRob2QoYXBpLCBhcmdzKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zdCBjbG9zZURlc2NyaXB0b3IgPSByZXNvbHZlV2ViU29ja2V0Q2xvc2VEZXNjcmlwdG9yKGVycm9yKTtcbiAgICAgICAgaWYgKCFyYXdXcykge1xuICAgICAgICAgIHRoaXMud2Vic29ja2V0UnVudGltZS50ZWxlbWV0cnlDb250cm9sbGVyLmVtaXQoe1xuICAgICAgICAgICAgbmFtZTogXCJ3cy5jb25uZWN0aW9uLnJlamVjdGVkXCIsXG4gICAgICAgICAgICBsZXZlbDogY2xvc2VEZXNjcmlwdG9yLmxvZ0xldmVsID09PSBcIndhcm5cIiA/IFwid2FyblwiIDogXCJlcnJvclwiLFxuICAgICAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgICAgIHJlYXNvbjogcHJlUmVnaXN0ZXJQaGFzZSxcbiAgICAgICAgICAgICAgY29kZTogY2xvc2VEZXNjcmlwdG9yLmNvZGUsXG4gICAgICAgICAgICAgIHBhdGg6IGFwaS5wYXRoLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRyYWNlSWQ6IHRyYWNlQ29udGV4dC50cmFjZUlkLFxuICAgICAgICAgICAgc3BhbklkOiB0cmFjZUNvbnRleHQuc3BhbklkLFxuICAgICAgICAgICAgcGFyZW50U3BhbklkOiB0cmFjZUNvbnRleHQucGFyZW50U3BhbklkLFxuICAgICAgICAgICAgc2FtcGxlZDogdHJhY2VDb250ZXh0LnNhbXBsZWQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmF3V3MpIHtcbiAgICAgICAgICByYXdXcy5jbG9zZShjbG9zZURlc2NyaXB0b3IuY29kZSwgY2xvc2VEZXNjcmlwdG9yLnJlYXNvbik7XG4gICAgICAgIH0gZWxzZSBpZiAoc29ja2V0LnJlYWR5U3RhdGUgPCAyKSB7XG4gICAgICAgICAgc29ja2V0LmNsb3NlKGNsb3NlRGVzY3JpcHRvci5jb2RlLCBjbG9zZURlc2NyaXB0b3IucmVhc29uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnNlcnZlcj8ubG9nKSB7XG4gICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgIGVycjogZXJyb3IsXG4gICAgICAgICAgICBtb2RlbE5hbWU6IGFwaS5tb2RlbE5hbWUsXG4gICAgICAgICAgICBtZXRob2ROYW1lOiBhcGkubWV0aG9kTmFtZSxcbiAgICAgICAgICAgIHBhdGg6IGFwaS5wYXRoLFxuICAgICAgICAgIH07XG4gICAgICAgICAgaWYgKGNsb3NlRGVzY3JpcHRvci5sb2dMZXZlbCA9PT0gXCJ3YXJuXCIpIHtcbiAgICAgICAgICAgIHRoaXMuc2VydmVyLmxvZy53YXJuKHBheWxvYWQsIGNsb3NlRGVzY3JpcHRvci5yZWFzb24pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNlcnZlci5sb2cuZXJyb3IocGF5bG9hZCwgY2xvc2VEZXNjcmlwdG9yLnJlYXNvbik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChjbG9zZURlc2NyaXB0b3IubG9nTGV2ZWwgPT09IFwid2FyblwiKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oY2xvc2VEZXNjcmlwdG9yLnJlYXNvbiwgZXJyb3IpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGNsb3NlRGVzY3JpcHRvci5yZWFzb24sIGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLy8gb25NZXNzYWdlL29uQ2xvc2Xsspjrn7wg64uk66W4IHRpY2vsl5DshJwg7Iuk7ZaJ65CY64qUIGNhbGxiYWNr7J2AIEFMUyBjb250ZXh06rCAIOuBiuq4sOuvgOuhnCB3cmFwcGVy7JeQ7IScIGBhc3luY0xvY2FsU3RvcmFnZS5ydW5g7Jy866GcIOuLpOyLnCDqsJDsi7gg67O17JuQ7ZWoXG4gIC8vIHB1Ymxpc2gvam9pbi9sZWF2ZS9zZXRVc2VySWQg6rCZ7J2AIOymieyLnCDsi6TtlokgQVBJ64qUIOuLqOyInCDsnITsnoTrp4wg7ZWY6rOgLCBkZWZlcnJlZCBjYWxsYmFja+yXkOunjCBjb250ZXh0IOuzteybkOydhCDsoIHsmqntlahcbiAgcHJpdmF0ZSBjcmVhdGVTY29wZWRXZWJTb2NrZXRDb25uZWN0aW9uPFxuICAgIFRPdXQgZXh0ZW5kcyBXZWJTb2NrZXRFdmVudE1hcCxcbiAgICBUSW4gZXh0ZW5kcyBXZWJTb2NrZXRFdmVudE1hcCxcbiAgPihcbiAgICB3czogV2ViU29ja2V0Q29ubmVjdGlvbjxUT3V0LCBUSW4+LFxuICAgIGdldENvbnRleHQ6ICgpID0+IFdlYlNvY2tldENvbnRleHQgfCBudWxsLFxuICApOiBXZWJTb2NrZXRDb25uZWN0aW9uPFRPdXQsIFRJbj4ge1xuICAgIGNvbnN0IHRlbGVtZXRyeUNvbnRyb2xsZXIgPSB0aGlzLl93ZWJzb2NrZXRSdW50aW1lPy50ZWxlbWV0cnlDb250cm9sbGVyO1xuICAgIGNvbnN0IHJ1bkluQ29udGV4dCA9IDxUPihjYWxsYmFjazogKCkgPT4gVCk6IFQgPT4ge1xuICAgICAgY29uc3QgY29udGV4dCA9IGdldENvbnRleHQoKTtcbiAgICAgIGlmICghY29udGV4dCkge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuYXN5bmNMb2NhbFN0b3JhZ2UucnVuKHsgY29udGV4dCB9LCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICBnZXQgaWQoKSB7XG4gICAgICAgIHJldHVybiB3cy5pZDtcbiAgICAgIH0sXG4gICAgICBnZXQgbmFtZXNwYWNlKCkge1xuICAgICAgICByZXR1cm4gd3MubmFtZXNwYWNlO1xuICAgICAgfSxcbiAgICAgIGdldCBjbG9zZWQoKSB7XG4gICAgICAgIHJldHVybiB3cy5jbG9zZWQ7XG4gICAgICB9LFxuICAgICAgZ2V0IHVzZXJJZCgpIHtcbiAgICAgICAgcmV0dXJuIHdzLnVzZXJJZDtcbiAgICAgIH0sXG4gICAgICB0cmFuc3BvcnQ6IFwid3NcIixcbiAgICAgIHB1Ymxpc2hVbnR5cGVkKGV2ZW50LCBkYXRhKSB7XG4gICAgICAgIHdzLnB1Ymxpc2hVbnR5cGVkKGV2ZW50LCBkYXRhKTtcbiAgICAgIH0sXG4gICAgICBjbG9zZShjb2RlLCByZWFzb24pIHtcbiAgICAgICAgd3MuY2xvc2UoY29kZSwgcmVhc29uKTtcbiAgICAgIH0sXG4gICAgICBvbkNsb3NlKGNhbGxiYWNrKSB7XG4gICAgICAgIHdzLm9uQ2xvc2UoKCkgPT4gcnVuSW5Db250ZXh0KGNhbGxiYWNrKSk7XG4gICAgICB9LFxuICAgICAgb25NZXNzYWdlKGV2ZW50LCBoYW5kbGVyKSB7XG4gICAgICAgIHdzLm9uTWVzc2FnZShldmVudCwgKGRhdGEsIG1lc3NhZ2VUcmFjZUNvbnRleHQpID0+XG4gICAgICAgICAgcnVuSW5Db250ZXh0KGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50TmFtZSA9IFN0cmluZyhldmVudCk7XG4gICAgICAgICAgICBjb25zdCB0cmFjZUNvbnRleHQgPSBtZXNzYWdlVHJhY2VDb250ZXh0ID8/IGdldFdlYlNvY2tldFRlbGVtZXRyeUNvbnRleHQod3MpO1xuICAgICAgICAgICAgY29uc3Qgc3RhcnRlZEF0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG5cbiAgICAgICAgICAgIHRlbGVtZXRyeUNvbnRyb2xsZXI/LmVtaXQoe1xuICAgICAgICAgICAgICBuYW1lOiBcIndzLmhhbmRsZXIuc3RhcnRlZFwiLFxuICAgICAgICAgICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgICAgICAgICBjb25uZWN0aW9uSWQ6IHdzLmlkLFxuICAgICAgICAgICAgICBuYW1lc3BhY2U6IHdzLm5hbWVzcGFjZSxcbiAgICAgICAgICAgICAgdXNlcklkOiB3cy51c2VySWQsXG4gICAgICAgICAgICAgIGRldGFpbDogeyBldmVudDogZXZlbnROYW1lIH0sXG4gICAgICAgICAgICAgIC4uLnRyYWNlQ29udGV4dCxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBoYW5kbGVyKGRhdGEsIG1lc3NhZ2VUcmFjZUNvbnRleHQpO1xuICAgICAgICAgICAgICBjb25zdCBkdXJhdGlvbk1zID0gcGVyZm9ybWFuY2Uubm93KCkgLSBzdGFydGVkQXQ7XG4gICAgICAgICAgICAgIHRlbGVtZXRyeUNvbnRyb2xsZXI/LmVtaXQoe1xuICAgICAgICAgICAgICAgIG5hbWU6IFwid3MuaGFuZGxlci5jb21wbGV0ZWRcIixcbiAgICAgICAgICAgICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25JZDogd3MuaWQsXG4gICAgICAgICAgICAgICAgbmFtZXNwYWNlOiB3cy5uYW1lc3BhY2UsXG4gICAgICAgICAgICAgICAgdXNlcklkOiB3cy51c2VySWQsXG4gICAgICAgICAgICAgICAgZGV0YWlsOiB7IGV2ZW50OiBldmVudE5hbWUgfSxcbiAgICAgICAgICAgICAgICAuLi50cmFjZUNvbnRleHQsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB0ZWxlbWV0cnlDb250cm9sbGVyPy5yZWNvcmRTcGFuKHtcbiAgICAgICAgICAgICAgICBvcGVyYXRpb25OYW1lOiBcIndzLm1lc3NhZ2UucHJvY2Vzc1wiLFxuICAgICAgICAgICAgICAgIGtpbmQ6IFwiaW50ZXJuYWxcIixcbiAgICAgICAgICAgICAgICBkdXJhdGlvbk1zLFxuICAgICAgICAgICAgICAgIHN0YXR1czogXCJ1bnNldFwiLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25JZDogd3MuaWQsXG4gICAgICAgICAgICAgICAgbmFtZXNwYWNlOiB3cy5uYW1lc3BhY2UsXG4gICAgICAgICAgICAgICAgdXNlcklkOiB3cy51c2VySWQsXG4gICAgICAgICAgICAgICAgYXR0cmlidXRlczogeyBldmVudDogZXZlbnROYW1lIH0sXG4gICAgICAgICAgICAgICAgLi4udHJhY2VDb250ZXh0LFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGR1cmF0aW9uTXMgPSBwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0ZWRBdDtcbiAgICAgICAgICAgICAgdGVsZW1ldHJ5Q29udHJvbGxlcj8uZW1pdCh7XG4gICAgICAgICAgICAgICAgbmFtZTogXCJ3cy5oYW5kbGVyLmZhaWxlZFwiLFxuICAgICAgICAgICAgICAgIGxldmVsOiBcImVycm9yXCIsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbklkOiB3cy5pZCxcbiAgICAgICAgICAgICAgICBuYW1lc3BhY2U6IHdzLm5hbWVzcGFjZSxcbiAgICAgICAgICAgICAgICB1c2VySWQ6IHdzLnVzZXJJZCxcbiAgICAgICAgICAgICAgICBkZXRhaWw6IHsgZXZlbnQ6IGV2ZW50TmFtZSB9LFxuICAgICAgICAgICAgICAgIC4uLnRyYWNlQ29udGV4dCxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHRlbGVtZXRyeUNvbnRyb2xsZXI/LnJlY29yZFNwYW4oe1xuICAgICAgICAgICAgICAgIG9wZXJhdGlvbk5hbWU6IFwid3MubWVzc2FnZS5wcm9jZXNzXCIsXG4gICAgICAgICAgICAgICAga2luZDogXCJpbnRlcm5hbFwiLFxuICAgICAgICAgICAgICAgIGR1cmF0aW9uTXMsXG4gICAgICAgICAgICAgICAgc3RhdHVzOiBcImVycm9yXCIsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbklkOiB3cy5pZCxcbiAgICAgICAgICAgICAgICBuYW1lc3BhY2U6IHdzLm5hbWVzcGFjZSxcbiAgICAgICAgICAgICAgICB1c2VySWQ6IHdzLnVzZXJJZCxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiB7IGV2ZW50OiBldmVudE5hbWUgfSxcbiAgICAgICAgICAgICAgICBlcnJvclR5cGU6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5uYW1lIDogdHlwZW9mIGVycm9yLFxuICAgICAgICAgICAgICAgIC4uLnRyYWNlQ29udGV4dCxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgfSxcbiAgICAgIHB1Ymxpc2goZXZlbnQsIGRhdGEpIHtcbiAgICAgICAgd3MucHVibGlzaChldmVudCwgZGF0YSk7XG4gICAgICB9LFxuICAgICAgd2FpdEZvckNsb3NlKCkge1xuICAgICAgICByZXR1cm4gd3Mud2FpdEZvckNsb3NlKCk7XG4gICAgICB9LFxuICAgICAgam9pbihyb29tSWQpIHtcbiAgICAgICAgd3Muam9pbihyb29tSWQpO1xuICAgICAgfSxcbiAgICAgIGxlYXZlKHJvb21JZCkge1xuICAgICAgICB3cy5sZWF2ZShyb29tSWQpO1xuICAgICAgfSxcbiAgICAgIHNldFVzZXJJZCh1c2VySWQpIHtcbiAgICAgICAgd3Muc2V0VXNlcklkKHVzZXJJZCk7XG4gICAgICB9LFxuICAgICAgY2xlYXJVc2VySWQoKSB7XG4gICAgICAgIHdzLmNsZWFyVXNlcklkKCk7XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHBhcnNlV2ViU29ja2V0UmVxdWVzdFBhcmFtcyhcbiAgICBhcGk6IEV4dGVuZGVkQXBpLFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gICAgY29uc3QgeyBnZXRab2RPYmplY3RGcm9tQXBpIH0gPSBhd2FpdCBpbXBvcnQoXCIuL2NvZGUtY29udmVydGVyc1wiKTtcbiAgICBjb25zdCBSZXFUeXBlID0gZ2V0Wm9kT2JqZWN0RnJvbUFwaShhcGksIHRoaXMuc3luY2VyLnR5cGVzKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IGZhc3RpZnlDYXN0ZXIgfSA9IGF3YWl0IGltcG9ydChcIi4vY2FzdGVyXCIpO1xuICAgICAgcmV0dXJuIGZhc3RpZnlDYXN0ZXIoUmVxVHlwZSkucGFyc2UoKHJlcXVlc3QucXVlcnkgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zdCB7IFpvZEVycm9yIH0gPSBhd2FpdCBpbXBvcnQoXCJ6b2RcIik7XG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIFpvZEVycm9yKSB7XG4gICAgICAgIGNvbnN0IHsgaHVtYW5pemVab2RFcnJvciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvem9kLWVycm9yXCIpO1xuICAgICAgICBjb25zdCBtZXNzYWdlcyA9IGh1bWFuaXplWm9kRXJyb3IoZSlcbiAgICAgICAgICAubWFwKChpc3N1ZSkgPT4gaXNzdWUubWVzc2FnZSlcbiAgICAgICAgICAuam9pbihcIiBcIik7XG4gICAgICAgIGNvbnN0IHsgQmFkUmVxdWVzdEV4Y2VwdGlvbiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZXhjZXB0aW9ucy9zby1leGNlcHRpb25zXCIpO1xuICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihtZXNzYWdlcyBhcyBMb2NhbGl6ZWRTdHJpbmcsIHtcbiAgICAgICAgICB6b2RFcnJvcjogZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFVSTOyXkOyEnCBwYXRoIHBhcmFtc+ulvCDstpTstpztlanri4jri6QuXG4gICAqIOyYiDogcGF0dGVybj1cIi9hZG1pbi9jb21wYW5pZXMvOmNvbXBhbnlJZFwiLCB1cmw9XCIvYWRtaW4vY29tcGFuaWVzLzEyM1wiIOKGkiB7IGNvbXBhbnlJZDogXCIxMjNcIiB9XG4gICAqL1xuICBwcml2YXRlIGV4dHJhY3RQYXRoUGFyYW1zKHBhdHRlcm46IHN0cmluZywgdXJsOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICBjb25zdCBwYXR0ZXJuUGFydHMgPSBwYXR0ZXJuLnNwbGl0KFwiL1wiKS5maWx0ZXIoQm9vbGVhbik7XG4gICAgY29uc3QgdXJsUGFydHMgPSB0aGlzLmdldFBhdGhuYW1lRnJvbVVybCh1cmwpLnNwbGl0KFwiL1wiKS5maWx0ZXIoQm9vbGVhbik7XG4gICAgY29uc3QgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm5QYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHBhdHRlcm5QYXJ0c1tpXS5zdGFydHNXaXRoKFwiOlwiKSkge1xuICAgICAgICBwYXJhbXNbcGF0dGVyblBhcnRzW2ldLnNsaWNlKDEpXSA9IHVybFBhcnRzW2ldO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcGFyYW1zO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1BhdGhQYXR0ZXJuTWF0Y2gocGF0dGVybjogc3RyaW5nLCB1cmw6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHBhdHRlcm5QYXJ0cyA9IHBhdHRlcm4uc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcbiAgICBjb25zdCB1cmxQYXJ0cyA9IHRoaXMuZ2V0UGF0aG5hbWVGcm9tVXJsKHVybCkuc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcblxuICAgIGlmIChwYXR0ZXJuUGFydHMubGVuZ3RoICE9PSB1cmxQYXJ0cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm5QYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgcGF0dGVyblBhcnQgPSBwYXR0ZXJuUGFydHNbaV07XG4gICAgICBjb25zdCB1cmxQYXJ0ID0gdXJsUGFydHNbaV07XG4gICAgICBpZiAocGF0dGVyblBhcnQuc3RhcnRzV2l0aChcIjpcIikpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAocGF0dGVyblBhcnQgIT09IHVybFBhcnQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQYXRobmFtZUZyb21VcmwodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB1cmwuc3BsaXQoXCI/XCIpWzBdO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlUGF0aFdpdGhpbkJhc2VEaXIoYmFzZURpcjogc3RyaW5nLCBpbnB1dFBhdGg6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZWNvZGVkID0gZGVjb2RlVVJJQ29tcG9uZW50KGlucHV0UGF0aCkucmVwbGFjZSgvXFxcXC9nLCBcIi9cIik7XG4gICAgICBpZiAoZGVjb2RlZC5pbmNsdWRlcyhcIlxcMFwiKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IGRlY29kZWQucmVwbGFjZSgvXlxcLysvLCBcIlwiKTtcbiAgICAgIGNvbnN0IHJlc29sdmVkUGF0aCA9IHBhdGgucmVzb2x2ZShiYXNlRGlyLCByZWxhdGl2ZVBhdGgpO1xuICAgICAgY29uc3QgcmVsYXRpdmVGcm9tQmFzZSA9IHBhdGgucmVsYXRpdmUoYmFzZURpciwgcmVzb2x2ZWRQYXRoKTtcbiAgICAgIGlmIChyZWxhdGl2ZUZyb21CYXNlLnN0YXJ0c1dpdGgoXCIuLlwiKSB8fCBwYXRoLmlzQWJzb2x1dGUocmVsYXRpdmVGcm9tQmFzZSkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzb2x2ZWRQYXRoO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFQSSDsnZHri7Xsl5Ag7KCB7Jqp7ZWgIENhY2hlLUNvbnRyb2wg7ISk7KCV7J2EIOqysOygle2VqeuLiOuLpC5cbiAgICog7Jqw7ISg7Iic7JyEOiDqsJzrs4Qg7KeA7KCVID4gY2FjaGVDb250cm9sSGFuZGxlclxuICAgKi9cbiAgcHJpdmF0ZSBnZXRBcGlDYWNoZUNvbnRyb2woXG4gICAgYXBpOiBFeHRlbmRlZEFwaSxcbiAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICkge1xuICAgIC8vIOuNsOy9lOugiOydtO2EsCDshKTsoJUg7Jqw7ISgXG4gICAgaWYgKGFwaS5vcHRpb25zLmNhY2hlQ29udHJvbCkge1xuICAgICAgcmV0dXJuIGFwaS5vcHRpb25zLmNhY2hlQ29udHJvbDtcbiAgICB9XG5cbiAgICAvLyDsoITsl60g7ZW465Ok65+sXG4gICAgaWYgKGNvbmZpZy5jYWNoZUNvbnRyb2xIYW5kbGVyKSB7XG4gICAgICBjb25zdCBjYWNoZVJlcTogQ2FjaGVDb250cm9sUmVxdWVzdCA9IHtcbiAgICAgICAgdHlwZTogXCJhcGlcIixcbiAgICAgICAgdXJsOiByZXF1ZXN0LnVybCxcbiAgICAgICAgcGF0aDogcmVxdWVzdC5yb3V0ZU9wdGlvbnM/LnVybCA/PyByZXF1ZXN0LnVybC5zcGxpdChcIj9cIilbMF0sXG4gICAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICAgIGFwaSxcbiAgICAgIH07XG4gICAgICBjb25zdCByZXN1bHQgPSBjb25maWcuY2FjaGVDb250cm9sSGFuZGxlcihjYWNoZVJlcSk7XG4gICAgICBpZiAocmVzdWx0KSByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFNTUuyaqSBBUEkg7Zi47LacIChIVFRQIOyYpOuyhO2XpOuTnCDsl4bsnbQg7KeB7KCRIO2YuOy2nClcbiAgICogY3JlYXRlQXBpSGFuZGxlcuydmCDroZzsp4HsnYQg7J6s7IKs7Jqp7ZWY65CYLCByZXF1ZXN0IO2MjOyLsSDrjIDsi6AgcGFyYW1zIOyngeygkSDsgqzsmqlcbiAgICovXG4gIGFzeW5jIGludm9rZUFwaUZvclNTUihcbiAgICBhcGk6IEV4dGVuZGVkQXBpLFxuICAgIHBhcmFtczogYW55W10sXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgIHJlcGx5OiBGYXN0aWZ5UmVwbHksXG4gICk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgIC8vIENvbnRleHQg7IOd7ISxICjquLDsobQg66mU7IaM65OcIOyerOyCrOyaqSlcbiAgICBjb25zdCBjb250ZXh0ID0gYXdhaXQgdGhpcy5jcmVhdGVDb250ZXh0KGNvbmZpZywgcmVxdWVzdCwgcmVwbHkpO1xuXG4gICAgcmV0dXJuIHRoaXMuYXN5bmNMb2NhbFN0b3JhZ2UucnVuKHsgY29udGV4dCB9LCBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBhcmdzIOyDneyEsTogQ29udGV4dCDtjIzrnbzrr7jthLDripQg7KO87J6FLCDrgpjrqLjsp4DripQgcGFyYW1z7JeQ7IScIOqwgOyguOyYpOq4sFxuICAgICAgY29uc3QgeyBBcGlQYXJhbVR5cGUgfSA9IGF3YWl0IGltcG9ydChcIi4uL3R5cGVzL3R5cGVzXCIpO1xuICAgICAgbGV0IHBhcmFtc0luZGV4ID0gMDtcbiAgICAgIGNvbnN0IGFyZ3MgPSBhcGkucGFyYW1ldGVycy5tYXAoKHBhcmFtKSA9PiB7XG4gICAgICAgIGlmIChBcGlQYXJhbVR5cGUuaXNDb250ZXh0KHBhcmFtLnR5cGUpKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBhcmFtc1twYXJhbXNJbmRleCsrXTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyDrqqjrjbgg66mU7ISc65OcIO2YuOy2nCAo6riw7KG0IOuplOyEnOuTnCDsnqzsgqzsmqkpXG4gICAgICByZXR1cm4gdGhpcy5pbnZva2VNb2RlbE1ldGhvZChhcGksIGFyZ3MsIHJlcGx5KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFdTIOqyveuhnOyXkOyEnOuKlCBIVFRQIHJlcGx56rCAIOyXhuycvOuvgOuhnCByZXBseeulvCBvcHRpb25hbOuhnCDrsJvslYQg6rO17Ya1IO2YuOy2nCDqsr3roZzrpbwg7Jyg7KeA7ZWoXG4gIGFzeW5jIGludm9rZU1vZGVsTWV0aG9kKFxuICAgIGFwaTogRXh0ZW5kZWRBcGksXG4gICAgYXJnczogdW5rbm93bltdLFxuICAgIHJlcGx5PzogRmFzdGlmeVJlcGx5LFxuICApOiBQcm9taXNlPHVua25vd24+IHtcbiAgICBjb25zdCBtb2RlbCA9IHRoaXMuc3luY2VyLm1vZGVsc1thcGkubW9kZWxOYW1lXTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCAobW9kZWwgYXMgYW55KVthcGkubWV0aG9kTmFtZV0uYXBwbHkobW9kZWwsIGFyZ3MpO1xuICAgIHJlcGx5Py50eXBlKGFwaS5vcHRpb25zLmNvbnRlbnRUeXBlID8/IFwiYXBwbGljYXRpb24vanNvblwiKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBhc3luYyBjcmVhdGVDb250ZXh0KFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICByZXBseTogRmFzdGlmeVJlcGx5LFxuICApOiBQcm9taXNlPENvbnRleHQ+IHtcbiAgICAvLyBjcmVhdGVTU0VGYWN0b3J5IO2VqOyImOyXkCDrr7jrpqwgcmVxdWVzdOydmCBzb2NrZXTqs7wgcmVwbHnrpbwg67CU7J2465SpLlxuICAgIGNvbnN0IHsgY3JlYXRlU1NFRmFjdG9yeSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3RyZWFtL3NzZVwiKTtcbiAgICBjb25zdCBjcmVhdGVTU0UgPSAoPFQgZXh0ZW5kcyBab2RPYmplY3Q+KFxuICAgICAgX3JlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgICAgX3JlcGx5OiBGYXN0aWZ5UmVwbHksXG4gICAgICBfZXZlbnRzOiBULFxuICAgICkgPT4gY3JlYXRlU1NFRmFjdG9yeShfcmVxdWVzdC5zb2NrZXQsIF9yZXBseSwgX2V2ZW50cykpLmJpbmQobnVsbCwgcmVxdWVzdCwgcmVwbHkpO1xuXG4gICAgLy8gbG9jYWxlIOqwkOyngFxuICAgIGNvbnN0IGxvY2FsZSA9XG4gICAgICB0aGlzLmRldGVjdExvY2FsZShyZXF1ZXN0LmhlYWRlcnNbXCJhY2NlcHQtbGFuZ3VhZ2VcIl0sIHRoaXMuY29uZmlnLmkxOG4uc3VwcG9ydGVkTG9jYWxlcykgPz9cbiAgICAgIHRoaXMuY29uZmlnLmkxOG4uZGVmYXVsdExvY2FsZTtcblxuICAgIC8vIGF1dGggY29udGV4dCDstpTqsIBcbiAgICBjb25zdCBoZWFkZXJzID0gY29udmVydEZhc3RpZnlIZWFkZXJzVG9TdGFuZGFyZChyZXF1ZXN0LmhlYWRlcnMpO1xuICAgIGNvbnN0IHNlc3Npb24gPSAoYXdhaXQgdGhpcy5fYXV0aD8uYXBpLmdldFNlc3Npb24oeyBoZWFkZXJzIH0pKSA/PyBudWxsO1xuXG4gICAgY29uc3QgY29udGV4dDogQ29udGV4dCA9IGF3YWl0IFByb21pc2UucmVzb2x2ZShcbiAgICAgIGNvbmZpZy5jb250ZXh0UHJvdmlkZXIoXG4gICAgICAgIHtcbiAgICAgICAgICB0cmFuc3BvcnQ6IFwiaHR0cFwiLFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgcmVwbHksXG4gICAgICAgICAgaGVhZGVyczogcmVxdWVzdC5oZWFkZXJzLFxuICAgICAgICAgIGNyZWF0ZVNTRSxcbiAgICAgICAgICBuYWl0ZVN0b3JlOiBuZXcgTWFwKCksXG4gICAgICAgICAgbG9jYWxlLFxuICAgICAgICAgIC8vIGF1dGhcbiAgICAgICAgICB1c2VyOiBzZXNzaW9uPy51c2VyID8/IG51bGwsXG4gICAgICAgICAgc2Vzc2lvbjogc2Vzc2lvbj8uc2Vzc2lvbiA/PyBudWxsLFxuICAgICAgICB9LFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICByZXBseSxcbiAgICAgICksXG4gICAgKTtcbiAgICByZXR1cm4gY29udGV4dDtcbiAgfVxuXG4gIC8vIHNlc3Npb24vbG9jYWxlL3N0b3JlIOqwmeydgCDqs7XthrUgc3RhdGXripQgSFRUUCBjb250ZXh07JmAIOqzteycoO2VmOuQmCwgcmVwbHkvY3JlYXRlU1NFIOqwmeydgCBIVFRQIOyghOyaqSBoZWxwZXLripQg64W47Lac7ZWY7KeAIOyViuydjFxuICAvLyDsgqzsmqnsnpDqsIAgd2Vic29ja2V0Q29udGV4dFByb3ZpZGVy66W8IOyjvOuptCDqt7jrjIDroZwg7JyE7J6E7ZWY6rOgLCDsl4bsnLzrqbQg6riw7KG0IGNvbnRleHRQcm92aWRlcuulvCByZXBseS9TU0Ugc3R1YuqzvCDtlajqu5gg7J6s7Zmc7Jqp7ZWoXG4gIGFzeW5jIGNyZWF0ZVdlYlNvY2tldENvbnRleHQoXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgIHdzOiBXZWJTb2NrZXRDb250ZXh0W1wid3NcIl0sXG4gICk6IFByb21pc2U8V2ViU29ja2V0Q29udGV4dD4ge1xuICAgIGNvbnN0IGxvY2FsZSA9XG4gICAgICB0aGlzLmRldGVjdExvY2FsZShyZXF1ZXN0LmhlYWRlcnNbXCJhY2NlcHQtbGFuZ3VhZ2VcIl0sIHRoaXMuY29uZmlnLmkxOG4uc3VwcG9ydGVkTG9jYWxlcykgPz9cbiAgICAgIHRoaXMuY29uZmlnLmkxOG4uZGVmYXVsdExvY2FsZTtcblxuICAgIGNvbnN0IGhlYWRlcnMgPSBjb252ZXJ0RmFzdGlmeUhlYWRlcnNUb1N0YW5kYXJkKHJlcXVlc3QuaGVhZGVycyk7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IChhd2FpdCB0aGlzLl9hdXRoPy5hcGkuZ2V0U2Vzc2lvbih7IGhlYWRlcnMgfSkpID8/IG51bGw7XG5cbiAgICBjb25zdCBkZWZhdWx0Q29udGV4dCA9IHtcbiAgICAgIHRyYW5zcG9ydDogXCJ3c1wiIGFzIGNvbnN0LFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGhlYWRlcnM6IHJlcXVlc3QuaGVhZGVycyxcbiAgICAgIHdzLFxuICAgICAgbmFpdGVTdG9yZTogbmV3IE1hcCgpLFxuICAgICAgbG9jYWxlLFxuICAgICAgdXNlcjogc2Vzc2lvbj8udXNlciA/PyBudWxsLFxuICAgICAgc2Vzc2lvbjogc2Vzc2lvbj8uc2Vzc2lvbiA/PyBudWxsLFxuICAgIH07XG5cbiAgICBpZiAoY29uZmlnLndlYnNvY2tldENvbnRleHRQcm92aWRlcikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uKGF3YWl0IFByb21pc2UucmVzb2x2ZShjb25maWcud2Vic29ja2V0Q29udGV4dFByb3ZpZGVyKGRlZmF1bHRDb250ZXh0LCByZXF1ZXN0KSkpLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyByZXBseS9jcmVhdGVTU0Xsl5Ag7J2Y7KG07ZWY64qUIGNvbnRleHRQcm92aWRlcuqwgCDsnojsnLzrqbQg7KaJ7IucIOyXkOufrOulvCDrjZjsoLggdHJhbnNwb3J0IG1pc3VzZeulvCDruajrpqwg65Oc65+s64OEXG4gICAgY29uc3QgcmVwbHlTdHViID0gY3JlYXRlV2ViU29ja2V0UmVwbHlTdHViKCk7XG4gICAgY29uc3QgY3JlYXRlU1NFID0gPFQgZXh0ZW5kcyBab2RPYmplY3Q+KF9ldmVudHM6IFQpID0+IHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJjcmVhdGVTU0UgaXMgbm90IGF2YWlsYWJsZSBpbiB3ZWJzb2NrZXQgY29udGV4dC4gRGVmaW5lIHdlYnNvY2tldENvbnRleHRQcm92aWRlciBpZiB5b3VyIGNvbnRleHQgc2V0dXAgZGVwZW5kcyBvbiBTU0UgaGVscGVycy5cIixcbiAgICAgICk7XG4gICAgfTtcbiAgICBjb25zdCBodHRwTGlrZUNvbnRleHQgPSBhd2FpdCBQcm9taXNlLnJlc29sdmUoXG4gICAgICBjb25maWcuY29udGV4dFByb3ZpZGVyKFxuICAgICAgICB7XG4gICAgICAgICAgdHJhbnNwb3J0OiBcImh0dHBcIixcbiAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgIHJlcGx5OiByZXBseVN0dWIsXG4gICAgICAgICAgaGVhZGVyczogcmVxdWVzdC5oZWFkZXJzLFxuICAgICAgICAgIGNyZWF0ZVNTRSxcbiAgICAgICAgICBuYWl0ZVN0b3JlOiBkZWZhdWx0Q29udGV4dC5uYWl0ZVN0b3JlLFxuICAgICAgICAgIGxvY2FsZSxcbiAgICAgICAgICB1c2VyOiBkZWZhdWx0Q29udGV4dC51c2VyLFxuICAgICAgICAgIHNlc3Npb246IGRlZmF1bHRDb250ZXh0LnNlc3Npb24sXG4gICAgICAgIH0sXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHJlcGx5U3R1YixcbiAgICAgICksXG4gICAgKTtcblxuICAgIGNvbnN0IHtcbiAgICAgIHRyYW5zcG9ydDogX3RyYW5zcG9ydCxcbiAgICAgIHJlcGx5OiBfcmVwbHksXG4gICAgICBjcmVhdGVTU0U6IF9jcmVhdGVTU0UsXG4gICAgICBidWZmZXJlZEZpbGVzOiBfYnVmZmVyZWRGaWxlcyxcbiAgICAgIHVwbG9hZGVkRmlsZXM6IF91cGxvYWRlZEZpbGVzLFxuICAgICAgLi4ucmVzdFxuICAgIH0gPSBodHRwTGlrZUNvbnRleHQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ucmVzdCxcbiAgICAgIHRyYW5zcG9ydDogXCJ3c1wiLFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGhlYWRlcnM6IHJlcXVlc3QuaGVhZGVycyxcbiAgICAgIHdzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQWNjZXB0LUxhbmd1YWdlIO2XpOuNlOyXkOyEnCDsp4Dsm5DtlZjripQgbG9jYWxl7J2EIOywvuyKteuLiOuLpC5cbiAgICogQGV4YW1wbGUgXCJrby1LUixrbztxPTAuOSxlbjtxPTAuOFwiIOKGkiBcImtvXCJcbiAgICovXG4gIHByaXZhdGUgZGV0ZWN0TG9jYWxlKFxuICAgIGFjY2VwdExhbmd1YWdlOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgc3VwcG9ydGVkOiBzdHJpbmdbXSxcbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIWFjY2VwdExhbmd1YWdlKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgLy8gQWNjZXB0LUxhbmd1YWdlOiBrby1LUixrbztxPTAuOSxlbjtxPTAuOFxuICAgIGNvbnN0IGxhbmdzID0gYWNjZXB0TGFuZ3VhZ2Uuc3BsaXQoXCIsXCIpLm1hcCgobGFuZykgPT4ge1xuICAgICAgY29uc3QgW2NvZGVdID0gbGFuZy5zcGxpdChcIjtcIik7XG4gICAgICByZXR1cm4gY29kZS50cmltKCkuc3BsaXQoXCItXCIpWzBdOyAvLyBrby1LUiDihpIga29cbiAgICB9KTtcblxuICAgIHJldHVybiBsYW5ncy5maW5kKChsYW5nKSA9PiBzdXBwb3J0ZWQuaW5jbHVkZXMobGFuZykpO1xuICB9XG5cbiAgYXN5bmMgc3RhcnRXYXRjaGVyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIHdhdGNoZXIg66qo65OI7J2AIGZpbGUtcGF0dGVybnMg4oaSIFNvbmFtdSDsiJztmZjsnYQg7ZS87ZWY6riwIOychO2VtCBkeW5hbWljIGltcG9ydCDtlanri4jri6QuXG4gICAgY29uc3QgeyBzZXR1cFdhdGNoZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3N5bmNlci93YXRjaGVyXCIpO1xuICAgIHRoaXMud2F0Y2hlciA9IGF3YWl0IHNldHVwV2F0Y2hlcigoZmlsZUV2ZW50cykgPT4gdGhpcy5ydW5IbXJTeW5jQ3ljbGUoZmlsZUV2ZW50cykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdhdGNoZXLqsIAgMTAwbXMgYmF0Y2jroZwg66qo7J2AIGZpbGVFdmVudHMg7ZWY64KY7JeQIOuMgO2VtCDtlZwg67KI7J2YIEhNUi9zeW5jIOyCrOydtO2BtOydhCDrj5Xri4jri6QuXG4gICAqIGJhdGNoIO2BkOyeiSDrjZXsl5Ag7ZWcIOyLnOygkOyXkCDtlZjrgpjrp4wg7Iuk7ZaJ65Co7J20IOuztOyepeuQqeuLiOuLpCAoZXZlbnQtYmF0Y2hlcuqwgCDsp4HroKztmZQpLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBydW5IbXJTeW5jQ3ljbGUoZmlsZUV2ZW50czogTWFwPEFic29sdXRlUGF0aCwgXCJjaGFuZ2VcIiB8IFwiYWRkXCI+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgc3RhcnRlZEF0ID0gRGF0ZS5ub3coKTtcblxuICAgIGZvciAoY29uc3QgW2ZpbGVQYXRoLCBldmVudF0gb2YgZmlsZUV2ZW50cykge1xuICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcGF0aC5yZWxhdGl2ZSh0aGlzLmFwcFJvb3RQYXRoLCBmaWxlUGF0aCk7XG4gICAgICBjb25zb2xlLmxvZyhjaGFsay5ib2xkKGBEZXRlY3RlZCgke2V2ZW50fSk6ICR7Y2hhbGsuYmx1ZShyZWxhdGl2ZVBhdGgpfWApKTtcbiAgICB9XG5cbiAgICAvLyDrs7jssrQ6IOuzgOqyvSDtnaHsiJggKyDssrTtgazshKwg6rCx7IugLlxuICAgIGF3YWl0IHRoaXMuc3luY2VyLmhtckFuZFN5bmMoZmlsZUV2ZW50cyk7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIucmVuZXdDaGVja3N1bXMoKTtcblxuICAgIGNvbnN0IHRvdGFsVGltZSA9IERhdGUubm93KCkgLSBzdGFydGVkQXQ7XG4gICAgY29uc3QgbXNnID0gYEhNUiBEb25lISAke2NoYWxrLmJvbGQud2hpdGUoYCR7dG90YWxUaW1lfW1zYCl9YDtcbiAgICBjb25zb2xlLmxvZyhjaGFsay5ibGFjay5iZ0dyZWVuKGNlbnRlclRleHQobXNnKSkpO1xuICB9XG5cbiAgLypcbiAgICAgQSBmdW5jdGlvbiB0aGF0IGF1dG9tYXRpY2FsbHkgaGFuZGxlcyBpbml0IGFuZCBkZXN0cm95IHdoZW4gdXNpbmcgU29uYW11IHZpYSBzY3JpcHRzLlxuICAqL1xuICBhc3luYyBydW5TY3JpcHQoZm46ICgpID0+IFByb21pc2U8dm9pZD4pIHtcbiAgICBhd2FpdCB0aGlzLmluaXQodHJ1ZSwgZmFsc2UsIHVuZGVmaW5lZCwgZmFsc2UpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmbigpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZ2lzdGVyUGx1Z2lucyhzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSwgcGx1Z2luczogU29uYW11U2VydmVyT3B0aW9uc1tcInBsdWdpbnNcIl0pIHtcbiAgICBpZiAoIXBsdWdpbnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBjb21wcmVzcyDtlIzrn6zqt7jsnbjsnYAg64uk66W4IO2UjOufrOq3uOyduOuztOuLpCDrqLzsoIAg65Ox66Gd65CY7Ja07JW8IO2VqeuLiOuLpC5cbiAgICBpZiAocGx1Z2lucy5jb21wcmVzcykge1xuICAgICAgY29uc3QgY29tcHJlc3NQbHVnaW4gPSAoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvY29tcHJlc3NcIikpLmRlZmF1bHQ7XG4gICAgICBjb25zdCBkZWZhdWx0T3B0aW9ucyA9IHtcbiAgICAgICAgdGhyZXNob2xkOiAxMDI0LFxuICAgICAgICBlbmNvZGluZ3M6IFtcImJyXCIsIFwiZ3ppcFwiLCBcImRlZmxhdGVcIl0gYXMgKFwiYnJcIiB8IFwiZ3ppcFwiIHwgXCJkZWZsYXRlXCIpW10sXG4gICAgICB9O1xuXG4gICAgICBpZiAocGx1Z2lucy5jb21wcmVzcyA9PT0gdHJ1ZSkge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoY29tcHJlc3NQbHVnaW4sIGRlZmF1bHRPcHRpb25zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlcnZlci5yZWdpc3Rlcihjb21wcmVzc1BsdWdpbiwge1xuICAgICAgICAgIC4uLmRlZmF1bHRPcHRpb25zLFxuICAgICAgICAgIC4uLnBsdWdpbnMuY29tcHJlc3MsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHBsdWdpbnNNb2R1bGVzID0ge1xuICAgICAgY29yczogXCJAZmFzdGlmeS9jb3JzXCIsXG4gICAgICBmb3JtYm9keTogXCJAZmFzdGlmeS9mb3JtYm9keVwiLFxuICAgICAgbXVsdGlwYXJ0OiBcIkBmYXN0aWZ5L211bHRpcGFydFwiLFxuICAgICAgcXM6IFwiZmFzdGlmeS1xc1wiLFxuICAgICAgc3NlOiBcImZhc3RpZnktc3NlLXYyXCIsXG4gICAgICBzdGF0aWM6IFwiQGZhc3RpZnkvc3RhdGljXCIsXG4gICAgfSBhcyBjb25zdDtcblxuICAgIGNvbnN0IHJlZ2lzdGVyUGx1Z2luID0gYXN5bmMgPEsgZXh0ZW5kcyBrZXlvZiBOb25OdWxsYWJsZTx0eXBlb2YgcGx1Z2lucz4+KFxuICAgICAga2V5OiBLLFxuICAgICAgcGx1Z2luTmFtZTogc3RyaW5nLFxuICAgICkgPT4ge1xuICAgICAgY29uc3Qgb3B0aW9uID0gcGx1Z2luc1trZXldO1xuICAgICAgaWYgKCFvcHRpb24pIHJldHVybjtcblxuICAgICAgaWYgKG9wdGlvbiA9PT0gdHJ1ZSkge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoKGF3YWl0IGltcG9ydChwbHVnaW5OYW1lKSkuZGVmYXVsdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoKGF3YWl0IGltcG9ydChwbHVnaW5OYW1lKSkuZGVmYXVsdCwgb3B0aW9uKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZm9yIChjb25zdCBba2V5LCBwbHVnaW5OYW1lXSBvZiBPYmplY3QuZW50cmllcyhwbHVnaW5zTW9kdWxlcykpIHtcbiAgICAgIGF3YWl0IHJlZ2lzdGVyUGx1Z2luKGtleSBhcyBrZXlvZiB0eXBlb2YgcGx1Z2lucywgcGx1Z2luTmFtZSk7XG4gICAgfVxuXG4gICAgaWYgKHBsdWdpbnMud3MpIHtcbiAgICAgIGF3YWl0IHRoaXMuZW5zdXJlV2ViU29ja2V0UGx1Z2luKHNlcnZlcik7XG4gICAgfVxuXG4gICAgaWYgKHBsdWdpbnMuY3VzdG9tKSB7XG4gICAgICBwbHVnaW5zLmN1c3RvbShzZXJ2ZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEBmYXN0aWZ5L3dlYnNvY2tldOydgCBwbHVnaW5zLndz6rCAIOyEpOygleuQnCDqsr3smrDsl5Drp4wg65Ox66Gd7ZWY6rOgLCDqsJnsnYAgc2VydmVy7JeQIOykkeuztSDrk7HroZ3rkJjsp4Ag7JWK64+E66GdIFdlYWtTZXTsnLzroZwg6riw66Gd7ZWoXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlV2ViU29ja2V0UGx1Z2luKFxuICAgIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlPFNlcnZlciwgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZT4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLndlYnNvY2tldFBsdWdpblNlcnZlcnMuaGFzKHNlcnZlcikpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwbHVnaW5PcHRpb24gPSB0aGlzLmNvbmZpZy5zZXJ2ZXIucGx1Z2lucz8ud3M7XG4gICAgaWYgKCFwbHVnaW5PcHRpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB3ZWJzb2NrZXRQbHVnaW4gPSAoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvd2Vic29ja2V0XCIpKS5kZWZhdWx0O1xuICAgIGNvbnN0IHJlc29sdmVkUGx1Z2luT3B0aW9ucyA9IHJlc29sdmVXZWJTb2NrZXRQbHVnaW5PcHRpb25zKHtcbiAgICAgIHJhd1BsdWdpbk9wdGlvbjogcGx1Z2luT3B0aW9uLFxuICAgIH0pO1xuICAgIGlmIChyZXNvbHZlZFBsdWdpbk9wdGlvbnMpIHtcbiAgICAgIGF3YWl0IHNlcnZlci5yZWdpc3Rlcih3ZWJzb2NrZXRQbHVnaW4sIHJlc29sdmVkUGx1Z2luT3B0aW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHNlcnZlci5yZWdpc3Rlcih3ZWJzb2NrZXRQbHVnaW4pO1xuICAgIH1cblxuICAgIHRoaXMud2Vic29ja2V0UGx1Z2luU2VydmVycy5hZGQoc2VydmVyKTtcbiAgICB0aGlzLndhcm5PblBvdGVudGlhbFdlYlNvY2tldFRpbWVvdXRDb25mbGljdHMoc2VydmVyKTtcbiAgfVxuXG4gIC8vIGhlYXJ0YmVhdCBpbnRlcnZhbOydtCBGYXN0aWZ5IGtlZXBBbGl2ZVRpbWVvdXQg7J207IOB7J2066m0IOyduO2UhOudvOqwgCDrqLzsoIAgaWRsZSDsl7DqsrDsnYQg64GK7J2EIOyImCDsnojslrQg6rK96rOg66eMIOuCqOq4sOqzoCDrhJjslrTqsJBcbiAgcHJpdmF0ZSB3YXJuT25Qb3RlbnRpYWxXZWJTb2NrZXRUaW1lb3V0Q29uZmxpY3RzKFxuICAgIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlPFNlcnZlciwgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZT4sXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGhlYXJ0YmVhdHMgPSB0aGlzLnN5bmNlci5hcGlzXG4gICAgICAubWFwKChhcGkpID0+IGFwaS53ZWJzb2NrZXRPcHRpb25zPy5oZWFydGJlYXQgPz8gMzAwMDApXG4gICAgICAuZmlsdGVyKChoZWFydGJlYXQpID0+IGhlYXJ0YmVhdCA+IDApO1xuXG4gICAgaWYgKGhlYXJ0YmVhdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qga2VlcEFsaXZlVGltZW91dCA9IHRoaXMuY29uZmlnLnNlcnZlci5mYXN0aWZ5Py5rZWVwQWxpdmVUaW1lb3V0O1xuICAgIGlmICgha2VlcEFsaXZlVGltZW91dCB8fCBrZWVwQWxpdmVUaW1lb3V0IDw9IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBsYXJnZXN0SGVhcnRiZWF0ID0gTWF0aC5tYXgoLi4uaGVhcnRiZWF0cyk7XG4gICAgaWYgKGxhcmdlc3RIZWFydGJlYXQgPj0ga2VlcEFsaXZlVGltZW91dCkge1xuICAgICAgc2VydmVyLmxvZy53YXJuKFxuICAgICAgICB7XG4gICAgICAgICAga2VlcEFsaXZlVGltZW91dCxcbiAgICAgICAgICBsYXJnZXN0SGVhcnRiZWF0LFxuICAgICAgICB9LFxuICAgICAgICBcIldlYlNvY2tldCBoZWFydGJlYXQgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGtlZXBBbGl2ZVRpbWVvdXQ7IGFsaWduIGluZnJhc3RydWN0dXJlIGlkbGUgdGltZW91dHMgdG8gYXZvaWQgdW5leHBlY3RlZCBkaXNjb25uZWN0cy5cIixcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIGJldHRlci1hdXRoIOudvOyasO2KuOulvCDrk7HroZ3tlanri4jri6QuXG4gICAqIC9hcGkvYXV0aC8qIOqyveuhnOuhnCDsnbjspp0gQVBJ6rCAIOyekOuPmSDrk7HroZ3rkKnri4jri6QuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlZ2lzdGVyQmV0dGVyQXV0aChcbiAgICBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSxcbiAgICBvcHRpb25zOiBOb25OdWxsYWJsZTxTb25hbXVTZXJ2ZXJPcHRpb25zW1wiYXV0aFwiXT4sXG4gICkge1xuICAgIGlmICghb3B0aW9ucykgcmV0dXJuO1xuXG4gICAgY29uc3QgYmFzZVBhdGggPSBvcHRpb25zLmJhc2VQYXRoID8/IFwiL2FwaS9hdXRoXCI7XG5cbiAgICAvLyBiZXR0ZXItYXV0aCDrnbzsmrDtirgg65Ox66GdXG4gICAgc2VydmVyLnJvdXRlKHtcbiAgICAgIG1ldGhvZDogW1wiR0VUXCIsIFwiUE9TVFwiXSxcbiAgICAgIHVybDogYCR7YmFzZVBhdGh9LypgLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5hdXRoLmhhbmRsZXIoXG4gICAgICAgICAgY3JlYXRlQmV0dGVyQXV0aFJlcXVlc3QocmVxdWVzdCwgb3B0aW9ucy5hZHZhbmNlZD8uaXBBZGRyZXNzPy5pcEFkZHJlc3NIZWFkZXJzKSxcbiAgICAgICAgKTtcblxuICAgICAgICByZXBseS5zdGF0dXMocmVzcG9uc2Uuc3RhdHVzKTtcbiAgICAgICAgcmVzcG9uc2UuaGVhZGVycy5mb3JFYWNoKCh2YWx1ZTogc3RyaW5nLCBrZXk6IHN0cmluZykgPT4ge1xuICAgICAgICAgIHJlcGx5LmhlYWRlcihrZXksIHZhbHVlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXBseS5zZW5kKHJlc3BvbnNlLmJvZHkgPyBhd2FpdCByZXNwb25zZS50ZXh0KCkgOiBudWxsKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHByaW50U3RhcnR1cFN1bW1hcnkoKSB7XG4gICAgY29uc3QgY2hhbGsgPSAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQ7XG4gICAgY29uc3QgYWN0aXZlUHJlc2V0ID0gZ2V0U29uYW11RW52aXJvbm1lbnQoKTtcblxuICAgIGNvbnN0IGRpbSA9IChtc2c6IHN0cmluZykgPT4gY29uc29sZS5sb2coY2hhbGsuZGltKGDinJMgJHttc2d9YCkpO1xuICAgIGNvbnN0IGdyZWVuID0gKG1zZzogc3RyaW5nKSA9PiBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihg4pyTICR7bXNnfWApKTtcblxuICAgIGRpbShgQ29uZmlnIGxvYWRlZCR7Zm9ybWF0VGltZSh0aGlzLl9jb25maWdFbGFwc2VkKX1gKTtcblxuICAgIC8vIERCIHByZXNldCDrqqnroZ1cbiAgICBncmVlbihcIkRCXCIpO1xuICAgIGNvbnN0IHsgaXNMb2NhbCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvY29udHJvbGxlclwiKTtcbiAgICBjb25zdCBwcmVzZXROYW1lcyA9IE9iamVjdC5rZXlzKHRoaXMuZGJDb25maWcpIGFzIChrZXlvZiBTb25hbXVEQkNvbmZpZylbXTtcbiAgICBjb25zdCBtYXhMZW4gPSBNYXRoLm1heCguLi5wcmVzZXROYW1lcy5tYXAoKG4pID0+IG4ubGVuZ3RoKSk7XG4gICAgZm9yIChjb25zdCBuYW1lIG9mIHByZXNldE5hbWVzKSB7XG4gICAgICBjb25zdCBjb25uID0gdGhpcy5kYkNvbmZpZ1tuYW1lXS5jb25uZWN0aW9uIGFzXG4gICAgICAgIHwgeyBob3N0Pzogc3RyaW5nOyBwb3J0PzogbnVtYmVyOyBkYXRhYmFzZT86IHN0cmluZyB9XG4gICAgICAgIHwgdW5kZWZpbmVkO1xuICAgICAgY29uc3QgaG9zdCA9IGNvbm4/Lmhvc3QgPz8gXCJsb2NhbGhvc3RcIjtcbiAgICAgIGNvbnN0IGFkZHIgPSBgQCAke2hvc3R9OiR7Y29ubj8ucG9ydCA/PyA1NDMyfS8ke2Nvbm4/LmRhdGFiYXNlID8/IFwiKHVua25vd24pXCJ9YDtcbiAgICAgIGNvbnN0IHBhZGRlZCA9IG5hbWUucGFkRW5kKG1heExlbik7XG4gICAgICBjb25zdCByZW1vdGVUYWcgPSBpc0xvY2FsKCkgJiYgIWlzTG9jYWxIb3N0KGhvc3QpID8gY2hhbGsueWVsbG93KGAgXFx1MjZhMCByZW1vdGVgKSA6IFwiXCI7XG5cbiAgICAgIGlmIChuYW1lID09PSBhY3RpdmVQcmVzZXQpIHtcbiAgICAgICAgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oYCAgXFx1MjViOCAke3BhZGRlZH0gJHthZGRyfWApICsgcmVtb3RlVGFnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmRpbShgICAgICR7cGFkZGVkfSAke2FkZHJ9YCkgKyByZW1vdGVUYWcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZy5zZXJ2ZXIuYXV0aCkge1xuICAgICAgY29uc3QgYmFzZVBhdGggPSB0aGlzLmNvbmZpZy5zZXJ2ZXIuYXV0aC5iYXNlUGF0aCA/PyBcIi9hcGkvYXV0aFwiO1xuICAgICAgZGltKGBBdXRoOiBiZXR0ZXItYXV0aCBhdCAke2Jhc2VQYXRofS8qYCk7XG4gICAgfVxuICAgIGlmICh0aGlzLmNvbmZpZy5hcGkudGltZXpvbmUpIHtcbiAgICAgIGRpbShgVGltZXpvbmU6ICR7dGhpcy5jb25maWcuYXBpLnRpbWV6b25lfWApO1xuICAgIH1cbiAgICBncmVlbihgU29uYW11IHJlYWR5JHtmb3JtYXRUaW1lKHRoaXMuX2luaXRFbGFwc2VkKX1gKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaW5pdGlhbGl6ZUNhY2hlKGNvbmZpZzogQ2FjaGVDb25maWcgfCB1bmRlZmluZWQsIGZvclRlc3Rpbmc6IGJvb2xlYW4pIHtcbiAgICBjb25zdCB7IHNldENhY2hlTWFuYWdlclJlZiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vY2FjaGUvZGVjb3JhdG9yXCIpO1xuXG4gICAgLy8g7YWM7Iqk7Yq4IO2ZmOqyveyXkOyEnCDrqZTrqqjrpqwg65Oc65287J2067KEIOyekOuPmSDsgqzsmqlcbiAgICBpZiAoZm9yVGVzdGluZykge1xuICAgICAgY29uc3QgeyBjcmVhdGVUZXN0Q2FjaGVNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9jYWNoZS9jYWNoZS1tYW5hZ2VyXCIpO1xuICAgICAgdGhpcy5fY2FjaGUgPSBjcmVhdGVUZXN0Q2FjaGVNYW5hZ2VyKCk7XG4gICAgICBzZXRDYWNoZU1hbmFnZXJSZWYodGhpcy5fY2FjaGUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIOyEpOygleydtCDsl4bsnLzrqbQg7LqQ7IucIOu5hO2ZnOyEse2ZlFxuICAgIGlmICghY29uZmlnKSB7XG4gICAgICBzZXRDYWNoZU1hbmFnZXJSZWYobnVsbCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8g7ISk7KCV7JeQIOuUsOudvCBDYWNoZU1hbmFnZXIg7IOd7ISxXG4gICAgY29uc3QgeyBjcmVhdGVDYWNoZU1hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL2NhY2hlL2NhY2hlLW1hbmFnZXJcIik7XG4gICAgdGhpcy5fY2FjaGUgPSBjcmVhdGVDYWNoZU1hbmFnZXIoY29uZmlnKTtcbiAgICBzZXRDYWNoZU1hbmFnZXJSZWYodGhpcy5fY2FjaGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpbml0aWFsaXplV29ya2Zsb3dzKG9wdGlvbnM6IFNvbmFtdVRhc2tPcHRpb25zIHwgdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgeyBXb3JrZmxvd01hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3Rhc2tzL3dvcmtmbG93LW1hbmFnZXJcIik7XG4gICAgLy8gTk9URTogQHNvbmFtdS1raXQvdGFza3Mg7JWI7JeQ7ISgIGtuZXggY29uZmln66W8IOyImOygle2VmOq4sCDrlYzrrLjsl5AgY29ubmVjdGlvbuydtCDslYTri4wgY29uZmlnIOynuOuhnCDrs7Trg4Xri4jri6QuXG4gICAgdGhpcy5fd29ya2Zsb3dzID0gbmV3IFdvcmtmbG93TWFuYWdlcihEQi5nZXREQkNvbmZpZyhcIndcIikpO1xuICAgIGlmICghb3B0aW9ucykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGVuYWJsZVdvcmtlciA9IG9wdGlvbnMuZW5hYmxlV29ya2VyID8/IGlzRGFlbW9uU2VydmVyKCk7XG4gICAgY29uc3QgZGVmYXVsdFdvcmtlck9wdGlvbnMgPSB7XG4gICAgICBjb25jdXJyZW5jeTogb3MuY3B1cygpLmxlbmd0aCAtIDEsXG4gICAgICB1c2VQdWJTdWI6IHRydWUsXG4gICAgICBsaXN0ZW5EZWxheTogNTAwLFxuICAgIH07XG5cbiAgICBpZiAoZW5hYmxlV29ya2VyKSB7XG4gICAgICB0aGlzLndvcmtmbG93cy5zZXR1cFdvcmtlcih7XG4gICAgICAgIC4uLmRlZmF1bHRXb3JrZXJPcHRpb25zLFxuICAgICAgICAuLi5vcHRpb25zLndvcmtlck9wdGlvbnMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJvb3Qoc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UsIG9wdGlvbnM6IFNvbmFtdVNlcnZlck9wdGlvbnMpIHtcbiAgICBjb25zdCBwb3J0ID0gb3B0aW9ucy5saXN0ZW4/LnBvcnQgPz8gMzAwMDtcbiAgICBjb25zdCBob3N0ID0gb3B0aW9ucy5saXN0ZW4/Lmhvc3QgPz8gXCJsb2NhbGhvc3RcIjtcblxuICAgIHNlcnZlci5hZGRIb29rKFwib25DbG9zZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBvcHRpb25zLmxpZmVjeWNsZT8ub25TaHV0ZG93bj8uKHNlcnZlcik7XG4gICAgICBhd2FpdCB0aGlzLndvcmtmbG93cy5kZXN0cm95KCk7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3koKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHNodXRkb3duID0gYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgc2VydmVyLmNsb3NlKCk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgZHVyaW5nIHNodXRkb3duOlwiLCBlcnIpO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHByb2Nlc3Mub24oXCJTSUdJTlRcIiwgc2h1dGRvd24pO1xuICAgIHByb2Nlc3Mub24oXCJTSUdURVJNXCIsIHNodXRkb3duKTtcblxuICAgIGlmIChvcHRpb25zLmxpZmVjeWNsZT8ub25FcnJvcikge1xuICAgICAgc2VydmVyLnNldEVycm9ySGFuZGxlcihvcHRpb25zLmxpZmVjeWNsZT8ub25FcnJvcik7XG4gICAgfVxuXG4gICAgc2VydmVyXG4gICAgICAubGlzdGVuKHsgcG9ydCwgaG9zdCB9KVxuICAgICAgLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLndvcmtmbG93cy5zdGFydFdvcmtlcigpO1xuICAgICAgICBhd2FpdCBvcHRpb25zLmxpZmVjeWNsZT8ub25TdGFydD8uKHNlcnZlcik7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGFzeW5jIChlcnIpID0+IHtcbiAgICAgICAgY29uc3QgY2hhbGsgPSAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQ7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoY2hhbGsucmVkKFwiRmFpbGVkIHRvIHN0YXJ0IHNlcnZlcjpcIiwgZXJyKSk7XG4gICAgICAgIGF3YWl0IHNodXRkb3duKCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGRlc3Ryb3koKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBCYXNlTW9kZWwgfSA9IGF3YWl0IGltcG9ydChcIi4uL2RhdGFiYXNlL2Jhc2UtbW9kZWxcIik7XG4gICAgLy8g66i87KCAIOyymOumrO2VtOyVvO2VqC5cbiAgICBhd2FpdCBCYXNlTW9kZWwuZGVzdHJveSgpO1xuICAgIC8vIFdlYlNvY2tldCBzaHV0ZG93biBmaXJzdCB0byBmbHVzaCB0ZWxlbWV0cnlcbiAgICBpZiAodGhpcy5fd2Vic29ja2V0UnVudGltZSkge1xuICAgICAgYXdhaXQgdGhpcy5fd2Vic29ja2V0UnVudGltZS5zaHV0ZG93bigpO1xuICAgIH1cbiAgICB0aGlzLl93ZWJzb2NrZXRSdW50aW1lID0gbnVsbDtcbiAgICAvLyBUaGVuIHNodXQgZG93biByZW1haW5pbmcgcmVzb3VyY2VzIGluIHBhcmFsbGVsXG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFtcbiAgICAgIHRoaXMuX3dvcmtmbG93cz8uZGVzdHJveSgpID8/IFByb21pc2UucmVzb2x2ZSgpLFxuICAgICAgdGhpcy5fY2FjaGU/LmRpc2Nvbm5lY3QoKSA/PyBQcm9taXNlLnJlc29sdmUoKSxcbiAgICAgIHRoaXMuX2RldlZpdGVzdE1hbmFnZXI/LnNodXRkb3duKCkgPz8gUHJvbWlzZS5yZXNvbHZlKCksXG4gICAgICB0aGlzLndhdGNoZXI/LmNsb3NlKCkgPz8gUHJvbWlzZS5yZXNvbHZlKCksXG4gICAgXSk7XG4gICAgLy8gTG9nVGFwZSBkaXNwb3NlIGFmdGVyIFdTIHNodXRkb3duIHNvIHRlbGVtZXRyeSByZWNvcmRzIGFyZSBmbHVzaGVkIGZpcnN0XG4gICAgYXdhaXQgbG9ndGFwZURpc3Bvc2UoKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRXZWJTb2NrZXRUZWxlbWV0cnlDb250ZXh0KFxuICB3czogV2ViU29ja2V0Q29ubmVjdGlvbjxXZWJTb2NrZXRFdmVudE1hcCwgV2ViU29ja2V0RXZlbnRNYXA+LFxuKTogV2ViU29ja2V0VGVsZW1ldHJ5Q29ubmVjdGlvbkNvbnRleHQge1xuICBpZiAoIWlzVGVsZW1ldHJ5Q29udGV4dFByb3ZpZGVyKHdzKSkge1xuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIHJldHVybiB3cy5nZXRUZWxlbWV0cnlDb250ZXh0KCk7XG59XG5cbmZ1bmN0aW9uIGlzVGVsZW1ldHJ5Q29udGV4dFByb3ZpZGVyKFxuICB3czogV2ViU29ja2V0Q29ubmVjdGlvbjxXZWJTb2NrZXRFdmVudE1hcCwgV2ViU29ja2V0RXZlbnRNYXA+LFxuKTogd3MgaXMgV2ViU29ja2V0Q29ubmVjdGlvbjxXZWJTb2NrZXRFdmVudE1hcCwgV2ViU29ja2V0RXZlbnRNYXA+ICYgVGVsZW1ldHJ5Q29udGV4dFByb3ZpZGVyIHtcbiAgcmV0dXJuIFwiZ2V0VGVsZW1ldHJ5Q29udGV4dFwiIGluIHdzICYmIHR5cGVvZiB3cy5nZXRUZWxlbWV0cnlDb250ZXh0ID09PSBcImZ1bmN0aW9uXCI7XG59XG5cbmV4cG9ydCBjb25zdCBTb25hbXUgPSBuZXcgU29uYW11Q2xhc3MoKTtcblxuLyoqXG4gKiBzdHJlYW0g66qo65Oc7JeQ7IScIO2CpCDsg53shLEg7ZWo7IiY6rCAIOyngOygleuQmOyngCDslYrslZjsnYQg65WMIOyCrOyaqe2VmOuKlCDquLDrs7gg7ZWo7IiY7J6F64uI64ukLlxuICovXG5mdW5jdGlvbiBkZWZhdWx0S2V5R2VuZXJhdG9yKGZpbGU6IHsgZmlsZW5hbWU6IHN0cmluZzsgbWltZXR5cGU6IHN0cmluZyB9KTogc3RyaW5nIHtcbiAgY29uc3QgZXh0ID0gbWltZS5leHRlbnNpb24oZmlsZS5taW1ldHlwZSkgfHwgXCJiaW5cIjtcbiAgY29uc3QgdGltZXN0YW1wID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgcmFuZG9tID0gTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc2xpY2UoMiwgOCk7XG4gIHJldHVybiBgdXBsb2Fkcy8ke3RpbWVzdGFtcH0tJHtyYW5kb219LiR7ZXh0fWA7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFRpbWUobXM6IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IGZvcm1hdHRlZCA9IG1zID49IDEwMDAgPyBgJHsobXMgLyAxMDAwKS50b0ZpeGVkKDIpfXNgIDogYCR7TWF0aC5yb3VuZChtcyl9bXNgO1xuICByZXR1cm4gYCAoJHtmb3JtYXR0ZWR9KWA7XG59XG5cbmNvbnN0IExPQ0FMX0hPU1RTID0gbmV3IFNldChbXCJsb2NhbGhvc3RcIiwgXCIxMjcuMC4wLjFcIiwgXCIwLjAuMC4wXCIsIFwiOjoxXCJdKTtcbmZ1bmN0aW9uIGlzTG9jYWxIb3N0KGhvc3Q6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gTE9DQUxfSE9TVFMuaGFzKGhvc3QpIHx8IGhvc3QuZW5kc1dpdGgoXCIubG9jYWxcIik7XG59XG5cbi8vIGAuZXZlcnkoKWDqsIAg7LKrIGd1YXJkIOydtO2bhCDsiJztmozrpbwg66mI7LaU64qUIOusuOygnOqwgCDsnojslrQgYGZvci4uLm9mYOuhnCDrqqjrk6AgZ3VhcmTrpbwg7Iic7ISc64yA66GcIOyLpO2Wie2VmOuPhOuhnSDqs6DsoJXtlahcbmZ1bmN0aW9uIHJ1bkd1YXJkcyh7XG4gIGd1YXJkcyxcbiAgY29uZmlnLFxuICByZXF1ZXN0LFxuICBhcGksXG59OiB7XG4gIGd1YXJkczogRXh0ZW5kZWRBcGlbXCJvcHRpb25zXCJdW1wiZ3VhcmRzXCJdIHwgdW5kZWZpbmVkO1xuICBjb25maWc6IFBpY2s8U29uYW11RmFzdGlmeUNvbmZpZywgXCJndWFyZEhhbmRsZXJcIj47XG4gIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0O1xuICBhcGk6IEV4dGVuZGVkQXBpO1xufSk6IHZvaWQge1xuICBmb3IgKGNvbnN0IGd1YXJkIG9mIGd1YXJkcyA/PyBbXSkge1xuICAgIGNvbmZpZy5ndWFyZEhhbmRsZXIoZ3VhcmQsIHJlcXVlc3QsIGFwaSk7XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZzdEQSxTQUFTLDZCQUNQLElBQ3FDO0NBQ3JDLElBQUksQ0FBQywyQkFBMkIsRUFBRSxHQUNoQyxPQUFPLENBQUM7Q0FHVixPQUFPLEdBQUcsb0JBQW9CO0FBQ2hDO0FBRUEsU0FBUywyQkFDUCxJQUM0RjtDQUM1RixPQUFPLHlCQUF5QixNQUFNLE9BQU8sR0FBRyx3QkFBd0I7QUFDMUU7Ozs7QUFPQSxTQUFTLG9CQUFvQixNQUFzRDtDQUNqRixNQUFNLE1BQU0sS0FBSyxVQUFVLEtBQUssUUFBUSxLQUFLO0NBRzdDLE9BQU8sV0FGVyxLQUFLLElBRUwsRUFBVSxHQURiLEtBQUssT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FDcEIsRUFBTyxHQUFHO0FBQzNDO0FBRUEsU0FBUyxXQUFXLElBQW9CO0NBRXRDLE9BQU8sS0FEVyxNQUFNLE1BQU8sSUFBSSxLQUFLLElBQUEsQ0FBTSxRQUFRLENBQUMsRUFBRSxLQUFLLEdBQUcsS0FBSyxNQUFNLEVBQUUsRUFBRSxJQUMxRDtBQUN4QjtBQUdBLFNBQVMsWUFBWSxNQUF1QjtDQUMxQyxPQUFPLFlBQVksSUFBSSxJQUFJLEtBQUssS0FBSyxTQUFTLFFBQVE7QUFDeEQ7QUFHQSxTQUFTLFVBQVUsRUFDakIsUUFDQSxRQUNBLFNBQ0EsT0FNTztDQUNQLEtBQUssTUFBTSxTQUFTLFVBQVUsQ0FBQyxHQUM3QixPQUFPLGFBQWEsT0FBTyxTQUFTLEdBQUc7QUFFM0M7OzsyQkFyOURrRTswQkFDRztvQkFDVztlQUdsQjtTQUUzQjtTQUVTO1VBRThCO29CQUNYO29CQUNSO29CQUdBO1VBQ0g7U0FDNkM7bUJBUy9DO2lCQUNFO2VBQ0U7WUFFaUI7YUFJbEM7d0JBT1Q7Q0FRdEIsY0FBTixNQUFrQjtFQUNoQixnQkFBZ0M7RUFDaEMsYUFBNkI7RUFDN0Isb0JBRUssSUFBSSxrQkFBa0I7RUFFM0IsYUFBMkQ7R0FDekQsTUFBTSxRQUFRLEtBQUssa0JBQWtCLFNBQVM7R0FDOUMsSUFBSSxPQUFPLFNBQ1QsT0FBTyxNQUFNO0dBR2YsSUFBSSxRQUFRLElBQUksYUFBYSxRQUUzQixPQUFPO0lBQ0wsV0FBVztJQUNYLFNBQVM7SUFDVCxPQUFPO0lBQ1AsU0FBUyxDQUFDO0lBQ1YsWUFBWSxXQUFzQixxQkFBcUIsTUFBTTtJQUM3RCxRQUFRO0lBQ1IsTUFBTTtJQUNOLFNBQVM7SUFDVCw0QkFBWSxJQUFJLElBQWlCO0dBQ25DO1FBRUEsTUFBTSxJQUFJLE1BQU0sNEJBQTRCO0VBRWhEO0VBRUEsZUFBNEM7RUFDNUMsSUFBSSxZQUFZLGFBQTJCO0dBQ3pDLEtBQUssZUFBZTtFQUN0QjtFQUNBLElBQUksY0FBNEI7R0FDOUIsSUFBSSxLQUFLLGlCQUFpQixNQUN4QixNQUFNLElBQUksTUFBTSxpQ0FBaUM7R0FFbkQsT0FBTyxLQUFLO0VBQ2Q7RUFDQSxJQUFJLGNBQXNCO0dBQ3hCLE9BQU8sS0FBSyxZQUFZLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDLENBQUMsS0FBSyxLQUFLLEdBQUc7RUFDcEU7RUFFQSxZQUEyQztFQUMzQyxJQUFJLFNBQVMsVUFBMEI7R0FDckMsS0FBSyxZQUFZO0VBQ25CO0VBQ0EsSUFBSSxXQUEyQjtHQUM3QixJQUFJLEtBQUssY0FBYyxNQUNyQixNQUFNLElBQUksTUFBTSxpQ0FBaUM7R0FFbkQsT0FBTyxLQUFLO0VBQ2Q7RUFFQSxVQUFpQztFQUNqQyxJQUFJLE9BQU8sUUFBZ0I7R0FDekIsS0FBSyxVQUFVO0VBQ2pCO0VBQ0EsSUFBSSxTQUFpQjtHQUNuQixJQUFJLEtBQUssWUFBWSxNQUNuQixNQUFNLElBQUksTUFBTSxpQ0FBaUM7R0FFbkQsT0FBTyxLQUFLO0VBQ2Q7RUFFQSxVQUF1QztFQUN2QyxJQUFJLE9BQU8sUUFBc0I7R0FDL0IsS0FBSyxVQUFVO0VBQ2pCO0VBQ0EsSUFBSSxTQUF1QjtHQUN6QixJQUFJLEtBQUssWUFBWSxNQUNuQixNQUFNLElBQUksTUFBTSxpQ0FBaUM7R0FFbkQsT0FBTyxLQUFLO0VBQ2Q7RUFFQSxVQUF5QyxXQUFXO0VBRXBELFdBQTBDOzs7O0VBSTFDLElBQUksVUFBMEI7R0FDNUIsSUFBSSxDQUFDLEtBQUssVUFDUixNQUFNLElBQUksTUFBTSx5REFBeUQ7R0FFM0UsT0FBTyxLQUFLO0VBQ2Q7RUFFQSxTQUFzQzs7OztFQUl0QyxJQUFJLFFBQXNCO0dBQ3hCLElBQUksQ0FBQyxLQUFLLFFBQ1IsTUFBTSxJQUFJLE1BQU0seUVBQXlFO0dBRTNGLE9BQU8sS0FBSztFQUNkO0VBRUEsYUFBNkM7RUFDN0MsSUFBSSxZQUE2QjtHQUMvQixJQUFJLEtBQUssZUFBZSxNQUN0QixNQUFNLElBQUksTUFBTSxpQ0FBaUM7R0FHbkQsT0FBTyxLQUFLO0VBQ2Q7RUFFQSxRQUFnRDtFQUNoRCxJQUFJLE9BQWdDO0dBQ2xDLElBQUksQ0FBQyxLQUFLLE9BQ1IsTUFBTSxJQUFJLE1BQU0sdUVBQXVFO0dBRXpGLE9BQU8sS0FBSztFQUNkO0VBRUEsb0JBQXFEO0VBQ3JELElBQUksbUJBQTRDO0dBQzlDLE9BQU8sS0FBSztFQUNkO0VBQ0EsSUFBSSxpQkFBaUIsU0FBa0M7R0FDckQsS0FBSyxvQkFBb0I7RUFDM0I7RUFHQSxvQkFBcUQ7RUFFckQseUNBQTBDLElBQUksUUFFNUM7RUFDRixJQUFJLG1CQUFxQztHQUN2QyxJQUFJLENBQUMsS0FBSyxtQkFDUixNQUFNLElBQUksTUFBTSw2Q0FBNkM7R0FFL0QsT0FBTyxLQUFLO0VBQ2Q7RUFDQSxJQUFJLGlCQUFpQixTQUFrQztHQUNyRCxLQUFLLG9CQUFvQjtFQUMzQjtFQUdBLFVBQW1DO0VBRW5DLFNBQXdDO0VBRXhDLE1BQU0saUJBQWlCO0dBQ3JCLE1BQU0sS0FBSyxLQUFLLE1BQU0sT0FBTyxRQUFXLElBQUk7RUFDOUM7RUFFQSxNQUFNLEtBQ0osV0FBb0IsT0FDcEIsYUFBc0IsTUFDdEIsYUFDQSxhQUFzQixPQUN0QjtHQUNBLEtBQUssYUFBYTtHQUVsQixJQUFJLEtBQUssZUFDUDtHQUdGLE1BQU0sWUFBWSxZQUFZLElBQUk7R0FHbEMsTUFBTSxFQUFFLG9CQUFvQixNQUFNLE9BQU87R0FDekMsS0FBSyxjQUFjLGVBQWUsZ0JBQWdCO0dBQ2xELE1BQU0sMEJBQTBCLEVBQUUsR0FBRyxRQUFRLElBQUk7R0FHakQsTUFBTSxjQUFjLFlBQVksSUFBSTtHQUNwQyxNQUFNLEVBQUUsZUFBZSxNQUFNLE9BQU87R0FDcEMsS0FBSyxTQUFTLE1BQU0sV0FBVyxLQUFLLFdBQVc7R0FDL0MsTUFBTSxhQUFhLFlBQVksSUFBSSxJQUFJO0dBQ3ZDLFlBQVksS0FBSyxPQUFPLElBQUk7R0FFNUIsS0FBSyxPQUFPLFNBQVMsV0FBVyxLQUFLLE9BQU8sU0FBUyxZQUFZO0dBQ2pFLEtBQUssT0FBTyxTQUFTLGlCQUFpQixLQUFLLE9BQU8sU0FBUyxrQkFBa0IsQ0FBQztHQUM5RSxLQUFLLE9BQU8sU0FBUyxlQUFlLFNBQVMsS0FBSyxPQUFPLFNBQVMsWUFBWTtHQUc5RSxNQUFNLEVBQUUscUJBQXFCLE1BQU0sT0FBTztHQUMxQyxJQUFJLEtBQUssT0FBTyxZQUFZLE9BQzFCLE1BQU0saUJBQWlCLEVBQ3JCLEdBQUcsS0FBSyxPQUFPLFFBQ2pCLENBQUM7R0FJSCxNQUFNLEVBQUUsT0FBTyxNQUFNLE9BQU87R0FDNUIsTUFBTSxFQUFFLFNBQVMsdUJBQXVCLE1BQU0sT0FBTztHQUNyRCxNQUFNLHVCQUF1QixtQkFBbUIsSUFDNUMsNEJBQTRCLEtBQUssYUFBYSx1QkFBdUIsSUFDckU7R0FDSixLQUFLLFdBQVcsR0FBRyxpQkFDakIsS0FBSyxPQUFPLFVBQ1osS0FBSyxPQUFPLGFBQ1osb0JBQ0Y7R0FDQSxHQUFHLFVBQVUsS0FBSyxRQUFRO0dBSzFCLE1BQU0sRUFBRSxrQkFBa0IsTUFBTSxPQUFPO0dBQ3ZDLE1BQU0sY0FBYyxTQUFTLFFBQVE7R0FHckMsTUFBTSxLQUFLLGdCQUFnQixLQUFLLE9BQU8sT0FBTyxPQUFPLFVBQVU7R0FHL0QsTUFBTSxhQUFhLEtBQUssT0FBTyxPQUFPO0dBQ3RDLElBQUksWUFBWTtJQUVkLE1BQU0sc0JBQXNCLE1BQU0scUJBQXFCLFVBQVU7SUFHakUsTUFBTSxFQUFFLGVBQWUsTUFBTSxPQUFPO0lBQ3BDLE1BQU0sRUFBRSxzQkFBc0IsTUFBTSxPQUFPO0lBRTNDLE1BQU0sY0FBaUM7S0FDckMsVUFBVSxrQkFBa0I7S0FDNUIsR0FBRztJQUNMO0lBQ0EsS0FBSyxRQUFRLFdBQVcsV0FBVztHQUNyQztHQUdBLElBQUksWUFBWTtJQUNkLEtBQUssZ0JBQWdCO0lBQ3JCO0dBQ0Y7R0FHQSxNQUFNLEtBQUssb0JBQW9CLEtBQUssT0FBTyxLQUFLO0dBR2hELE1BQU0sRUFBRSxXQUFXLE1BQU0sT0FBTztHQUNoQyxLQUFLLFNBQVMsSUFBSSxPQUFPO0dBR3pCLE1BQU0sS0FBSyxPQUFPLGNBQWM7R0FDaEMsTUFBTSxLQUFLLE9BQU8sZUFBZTtHQUNqQyxNQUFNLEtBQUssT0FBTyxhQUFhO0dBQy9CLE1BQU0sS0FBSyxPQUFPLGtCQUFrQjtHQUNwQyxNQUFNLEVBQUUsb0JBQW9CLE1BQU0sT0FBTztHQUN6QyxNQUFNLGdCQUFnQixTQUFTO0dBQy9CLE1BQU0sS0FBSyxPQUFPLGtCQUFrQjtHQUVwQyxNQUFNLEVBQUUsU0FBUyxRQUFRLHNCQUFzQixNQUFNLE9BQU87R0FDNUQsSUFBSSxRQUFRLEtBQUssQ0FBQyxPQUFPLEtBQUssa0JBQWtCLEtBQUssWUFBWTtJQUMvRCxNQUFNLEtBQUssT0FBTyxLQUFLO0lBQ3ZCLE1BQU0sS0FBSyxhQUFhO0dBQzFCO0dBRUEsS0FBSyxnQkFBZ0I7R0FDckIsS0FBSyxlQUFlLFlBQVksSUFBSSxJQUFJO0dBQ3hDLEtBQUssaUJBQWlCO0VBQ3hCO0VBRUEsZUFBdUI7RUFDdkIsaUJBQXlCO0VBRXpCLE1BQU0sYUFBYSxhQUE0RDtHQUM3RSxJQUFJLENBQUMsS0FBSyxlQUNSLE1BQU0sS0FBSyxLQUFLLGFBQWEsVUFBVSxhQUFhLFVBQVU7R0FHaEUsTUFBTSxVQUFVLEtBQUssT0FBTztHQUM1QixNQUFNLEVBQUUsU0FBUyxZQUFZLE1BQU0sT0FBTztHQUMxQyxNQUFNLEVBQUUsNEJBQTRCLE1BQU0sT0FBTztHQUNqRCxNQUFNLFNBQVMsUUFBUTtJQUNyQixHQUFHLFFBQVE7SUFDWCxRQUNFLEtBQUssT0FBTyxZQUFZLFFBQ3BCLHdCQUF3QixFQUN0QixVQUFVLEtBQUssT0FBTyxTQUFTLG1CQUFtQixDQUFDLFNBQVMsRUFDOUQsQ0FBQyxJQUNEO0dBQ1IsQ0FBQztHQUNELEtBQUssU0FBUztHQUNkLEtBQUssbUJBQW1CLElBQUksaUJBQWlCLFFBQVEsU0FBUztHQUc5RCxJQUFJLFFBQVEsU0FBUztJQUNuQixNQUFNLEVBQUUsbUJBQW1CLE1BQU0sT0FBTztJQUN4QyxLQUFLLFdBQVcsSUFBSSxlQUFlLFFBQVEsT0FBTztHQUNwRDtHQUdBLElBQUksUUFBUSxTQUNWLE1BQU0sS0FBSyxnQkFBZ0IsUUFBUSxRQUFRLE9BQU87R0FHcEQsSUFBSSxRQUFRLE1BQ1YsTUFBTSxLQUFLLG1CQUFtQixRQUFRLFFBQVEsSUFBSTtHQUlwRCxNQUFNLEtBQUssWUFBWSxRQUFRLFFBQVEsV0FBVztJQUNoRCxZQUFZLGFBQWE7SUFDekIsVUFBVSxhQUFhO0dBQ3pCLENBQUM7R0FHRCxNQUFNLEtBQUssS0FBSyxRQUFRLE9BQU87R0FFL0IsSUFBSSxDQUFDLGFBQWEsVUFDaEIsS0FBSyxvQkFBb0I7R0FHM0IsT0FBTztFQUNUO0VBRUEsTUFBTSxZQUNKLFFBQ0EsUUFDQSxTQUlBO0dBQ0EsSUFBSSxDQUFDLEtBQUssZUFDUixNQUFNLEtBQUssS0FBSyxTQUFTLFVBQVUsU0FBUyxVQUFVO0dBR3hELEtBQUssU0FBUztHQUNkLEtBQUsscUJBQXFCLElBQUksaUJBQWlCLEtBQUssT0FBTyxPQUFPLFNBQVM7R0FHM0UsTUFBTSxXQUFXLEtBQUssT0FBTyxJQUFJO0dBQ2pDLElBQUksVUFBVTtJQUlaLE1BQU0sRUFBRSxxQkFBcUIsTUFBTSxPQUFPO0lBRzFDLE1BQU0saUJBQWlCO0lBS3ZCLE1BQU0sY0FBYztJQUVwQixPQUFPLG9CQUFvQixZQUFZO0tBQ3JDLE9BQU8sS0FBSyxVQUFVLFVBQVUsTUFBTSxVQUFVO01BQzlDLElBQUksT0FBTyxVQUFVLFlBQVksZUFBZSxLQUFLLEtBQUssR0FDeEQsT0FBTyxpQkFDTCxJQUFJLEtBQUssS0FBSyxHQUNkLFVBQ0EsV0FDRjtNQUVGLE9BQU87S0FDVCxDQUFDO0lBQ0gsQ0FBQztHQUVIO0dBR0EsT0FBTyxJQUNMLEdBQUcsS0FBSyxPQUFPLElBQUksTUFBTSxPQUFPLFVBQ2hDLE9BQU8sVUFBVSxXQUE2QztJQUM1RCxPQUFPLEtBQUssT0FBTztHQUNyQixDQUNGO0dBR0EsT0FBTyxJQUNMLEdBQUcsS0FBSyxPQUFPLElBQUksTUFBTSxPQUFPLGVBQ2hDLE9BQU8sVUFBVSxXQUE0QjtJQUMzQyxPQUFPO0dBQ1QsQ0FDRjtHQUdBLE1BQU0sRUFBRSxZQUFZLE1BQU0sT0FBTztHQUNqQyxJQUFJLFFBQVEsR0FBRztJQUNiLE1BQU0sRUFBRSxzQkFBc0IsTUFBTSxPQUFPO0lBQzNDLE9BQU8sU0FBUyxpQkFBaUI7R0FDbkM7R0FHQSxJQUFJLFFBQVEsS0FBSyxLQUFLLE9BQU8sTUFBTSxXQUFXLFNBQVM7SUFDckQsTUFBTSxFQUFFLDBCQUEwQixNQUFNLE9BQU87SUFDL0MsTUFBTSxzQkFBc0IsUUFBUSxLQUFLLE9BQU8sS0FBSyxTQUFTO0dBQ2hFO0dBRUEsTUFBTSxVQUFVLEtBQUssS0FBSyxLQUFLLGFBQWEsS0FBSztHQUNqRCxNQUFNLFNBQVMsTUFBTSxPQUFPLE9BQU87R0FHbkMsTUFBTSxpQkFBaUIsS0FBSyxPQUFPLE9BQU8sU0FBUztHQUNuRCxNQUFNLHdCQUFxRCxpQkFDdkQsbUJBQW1CLE9BQ2pCO0lBQUUsV0FBVztJQUFNLFdBQVc7S0FBQztLQUFNO0tBQVE7SUFBUztHQUFFLElBQ3hEO0lBQ0UsV0FBVyxlQUFlO0lBQzFCLFdBQVcsZUFBZTtJQUMxQixhQUFhLGVBQWU7R0FDOUIsSUFDRjtHQUVKLElBQUksUUFBUSxHQUFHO0lBR2IsTUFBTSx1QkFBdUIsUUFBUSxJQUFJLGtDQUFrQztJQUMzRSxJQUFJLFVBQVUsQ0FBQyxzQkFDYixNQUFNLEtBQUssdUJBQXVCLFFBQVEsU0FBUyxNQUFNO1NBRXpELEtBQUssZUFBZSxRQUFRLE1BQU07R0FFdEMsT0FBTztJQUVMLEtBQUssTUFBTSxPQUFPLEtBQUssT0FBTyxNQUFNO0tBQ2xDLElBQUksS0FBSyxPQUFPLE9BQU8sSUFBSSxlQUFlLFFBQ3hDLE1BQU0sSUFBSSxNQUFNLGtCQUFrQixJQUFJLFdBQVc7S0FJbkQsSUFBSSxJQUFJLGtCQUFrQjtNQUN4QixPQUFPLE1BQU07T0FDWCxRQUFRO09BQ1IsS0FBSyxLQUFLLE9BQU8sSUFBSSxNQUFNLFNBQVMsSUFBSTtPQUN4QyxTQUFTLEtBQUssc0NBQXNDO09BQ3BELFdBQVcsS0FBSyx1QkFBdUIsS0FBSyxNQUFNO01BQ3BELENBQUM7TUFDRDtLQUNGO0tBRUEsT0FBTyxNQUFNO01BQ1gsUUFBUSxJQUFJLFFBQVEsY0FBYztNQUNsQyxLQUFLLEtBQUssT0FBTyxJQUFJLE1BQU0sU0FBUyxJQUFJO01BQ3hDLFNBQVMsS0FBSyxpQkFBaUIsS0FBSyxNQUFNO01BQzFDLFVBQVUsd0JBQXdCLElBQUksUUFBUSxVQUFVLHFCQUFxQjtLQUMvRSxDQUFDO0lBQ0g7SUFJQSxNQUFNLEtBQUsscUJBQXFCLFFBQVEsUUFBUSxxQkFBcUI7R0FDdkU7RUFDRjs7Ozs7Ozs7RUFTQSxvQkFDRSxTQUNBLFFBQzZFO0dBQzdFLE1BQU0sYUFBYSxLQUFLLGVBQWUsT0FBTztHQUU5QyxJQUFJLENBQUMsWUFDSCxNQUFNLElBQUksa0JBQWtCLEdBQUcsb0JBQW9CLENBQUM7R0FJdEQsSUFBSSxXQUFXLGtCQUNiLE9BQU8sS0FBSyxzQ0FBc0M7R0FHcEQsT0FBTyxLQUFLLGlCQUFpQixZQUFZLE1BQU07RUFDakQ7RUFFQSxlQUF1QixTQUFrRDtHQUN2RSxNQUFNLE1BQU0sS0FBSyxtQkFBbUIsUUFBUSxHQUFHO0dBQy9DLE1BQU0sU0FBUyxRQUFRO0dBRXZCLElBQUksQ0FBQyxJQUFJLFdBQVcsS0FBSyxPQUFPLElBQUksTUFBTSxNQUFNLEdBQzlDO0dBR0YsT0FBTyxLQUFLLE9BQU8sS0FBSyxNQUFNLFFBQVE7SUFDcEMsSUFBSSxLQUFLLE9BQU8sT0FBTyxJQUFJLGVBQWUsUUFDeEMsT0FBTztJQUdULEtBRGtCLElBQUksUUFBUSxjQUFjLFdBQzFCLFFBQVEsT0FBTztJQUVqQyxNQUFNLFdBQVcsS0FBSyxPQUFPLElBQUksTUFBTSxTQUFTLElBQUk7SUFDcEQsT0FBTyxLQUFLLG1CQUFtQixVQUFVLEdBQUc7R0FDOUMsQ0FBQztFQUNIOzs7OztFQU1BLGVBQ0UsUUFDQSxRQUNNO0dBRU4sT0FBTyxNQUFNO0lBQ1gsUUFBUTtJQUNSLEtBQUssR0FBRyxLQUFLLE9BQU8sSUFBSSxNQUFNLE9BQU87SUFDckMsU0FBUyxPQUFPLFNBQVMsVUFBVTtLQUNqQyxNQUFNLFVBQVUsS0FBSyxvQkFBb0IsU0FBUyxNQUFNO0tBQ3hELElBQUksU0FDRixPQUFPLFFBQVEsU0FBUyxLQUFLO0tBRy9CLE1BQU0sSUFBSSxrQkFBa0IsR0FBRyxvQkFBb0IsQ0FBQztJQUN0RDtJQUNBLFdBQVcsT0FBTyxZQUFZLFlBQVk7S0FDeEMsTUFBTSxLQUFLLDBCQUEwQixXQUFXLFFBQVEsU0FBUyxNQUFNO0lBQ3pFO0dBQ0YsQ0FBQztHQUVELE9BQU8sTUFBTTtJQUNYLFFBQVE7S0FBQztLQUFRO0tBQVE7S0FBTztLQUFVO0lBQU87SUFDakQsS0FBSyxHQUFHLEtBQUssT0FBTyxJQUFJLE1BQU0sT0FBTztJQUNyQyxTQUFTLE9BQU8sU0FBUyxVQUFVO0tBQ2pDLE1BQU0sVUFBVSxLQUFLLG9CQUFvQixTQUFTLE1BQU07S0FDeEQsSUFBSSxTQUNGLE9BQU8sUUFBUSxTQUFTLEtBQUs7S0FFL0IsTUFBTSxJQUFJLGtCQUFrQixHQUFHLG9CQUFvQixDQUFDO0lBQ3REO0dBQ0YsQ0FBQztFQUNIO0VBRUEsYUFBMEI7Ozs7O0VBTTFCLE1BQWMsdUJBQ1osUUFDQSxTQUNBLFFBQ2U7R0FFZixNQUFNLE9BQU8sVUFBVSxNQUFNLE9BQU8sbUJBQUEsQ0FBb0IsT0FBTztHQUUvRCxNQUFNLE9BQU8sTUFBTSxPQUFPO0dBRTFCLE1BQU0sNkJBQTZCLFFBQVEsS0FBSyxPQUFPLE9BQU8sU0FBUyxFQUFFO0dBQ3pFLE1BQU0sTUFBTSxnQ0FBZ0M7SUFDMUMsWUFBWSxPQUFPO0lBQ25CLGtDQUFrQztHQUNwQyxDQUFDO0dBRUQsS0FBSyxhQUFhLE1BQU0sS0FBSyxhQUFhO0lBQ3hDLE1BQU07SUFDTixRQUFRO0tBQ04sZ0JBQWdCO0tBQ2hCO0lBQ0Y7SUFDQSxTQUFTO0dBQ1gsQ0FBQztHQUdELE9BQU8sS0FBSyxLQUFLLEtBQUssU0FBUztJQUU3QixJQUFJLElBQUksS0FBSyxXQUFXLEtBQUssT0FBTyxJQUFJLE1BQU0sTUFBTSxLQUFLLElBQUksS0FBSyxXQUFXLFlBQVksR0FDdkYsT0FBTyxLQUFLO0lBR2QsT0FBTyxLQUFLLFdBQVcsWUFBWSxLQUFLLEtBQUssSUFBSTtHQUNuRCxDQUFDO0dBR0QsT0FBTyxNQUFNO0lBQ1gsUUFBUTtJQUNSLEtBQUssR0FBRyxLQUFLLE9BQU8sSUFBSSxNQUFNLE9BQU87SUFDckMsU0FBUyxPQUFPLFNBQVMsVUFBVTtLQUNqQyxNQUFNLFNBQVMsS0FBSyxvQkFBb0IsU0FBUyxNQUFNO0tBQ3ZELElBQUksUUFDRixPQUFPLE9BQU8sU0FBUyxLQUFLO0tBRTlCLE1BQU0sSUFBSSxrQkFBa0IsR0FBRyxvQkFBb0IsQ0FBQztJQUN0RDtJQUNBLFdBQVcsT0FBTyxZQUFZLFlBQVk7S0FDeEMsTUFBTSxLQUFLLDBCQUEwQixXQUFXLFFBQVEsU0FBUyxNQUFNO0lBQ3pFO0dBQ0YsQ0FBQztHQUVELE9BQU8sTUFBTTtJQUNYLFFBQVE7S0FBQztLQUFRO0tBQVE7S0FBTztLQUFVO0lBQU87SUFDakQsS0FBSyxHQUFHLEtBQUssT0FBTyxJQUFJLE1BQU0sT0FBTztJQUNyQyxTQUFTLE9BQU8sU0FBUyxVQUFVO0tBQ2pDLE1BQU0sU0FBUyxLQUFLLG9CQUFvQixTQUFTLE1BQU07S0FDdkQsSUFBSSxRQUNGLE9BQU8sT0FBTyxTQUFTLEtBQUs7S0FFOUIsTUFBTSxJQUFJLGtCQUFrQixHQUFHLG9CQUFvQixDQUFDO0lBQ3REO0dBQ0YsQ0FBQztHQUlELE9BQU8sTUFBTTtJQUNYLFFBQVEsQ0FBQyxPQUFPLE1BQU07SUFDdEIsS0FBSztJQUNMLFNBQVMsT0FBTyxTQUFTLFVBQVU7S0FDakMsTUFBTSxNQUFNLFFBQVE7S0FHcEIsTUFBTSxFQUFFLGVBQWUsY0FBYyxNQUFNLE9BQU87S0FDbEQsTUFBTSxXQUFXLGNBQWMsR0FBRztLQUNsQyxJQUFJLFVBQVU7TUFDWixRQUFRLElBQUksd0JBQXdCLFNBQVMsTUFBTSxNQUFNO01BQ3pELE1BQU0sT0FBTyxNQUFNLFVBQ2pCLEtBQ0EsU0FBUyxPQUNULFNBQVMsUUFDVCxTQUNBLE9BQ0EsUUFDQSxLQUFLLFVBQ1A7TUFDQSxNQUFNLEtBQUssV0FBVztNQUN0QixPQUFPO0tBQ1Q7S0FHQSxJQUFJO01BRUYsSUFBSSxXQUFXLE9BQU0sTUFESixPQUFPLG9CQUNILENBQUcsU0FDdEIsS0FBSyxLQUFLLEtBQUssV0FBVyxPQUFPLE1BQU0sWUFBWSxHQUNuRCxPQUNGO01BQ0EsV0FBVyxNQUFNLEtBQUssV0FBVyxtQkFBbUIsS0FBSyxRQUFRO01BRWpFLE1BQU0sS0FBSyxXQUFXO01BQ3RCLE9BQU87S0FDVCxTQUFTLEdBQUc7TUFDVixLQUFLLFdBQVcsaUJBQWlCLENBQVU7TUFDM0MsUUFBUSxNQUFNLENBQUM7TUFDZixNQUFNLE9BQU8sR0FBRztNQUNoQixPQUFRLEVBQVk7S0FDdEI7SUFDRjtHQUNGLENBQUM7R0FHRCxPQUFPLFFBQVEsV0FBVyxZQUFZO0lBQ3BDLE1BQU0sS0FBSyxXQUFXLE1BQU07R0FDOUIsQ0FBQztHQUVELE1BQU0sU0FBUyxNQUFNLE9BQU8sU0FBQSxDQUFVO0dBQ3RDLElBQUksVUFBVSxLQUNaLFFBQVEsSUFDTixNQUFNLElBQ0osNkNBQTZDLElBQUksS0FBSyxzQ0FDeEQsQ0FDRjtHQUVGLFFBQVEsSUFBSSxNQUFNLElBQUksOEJBQThCLENBQUM7RUFDdkQ7RUFFQSxNQUFjLHFCQUNaLFFBQ0EsUUFDQSx1QkFDZTtHQUVmLE1BQU0sY0FBYyxLQUFLLEtBQUssS0FBSyxhQUFhLFlBQVksUUFBUTtHQUNwRSxNQUFNLFVBQVUsS0FBSyxLQUFLLEtBQUssYUFBYSxZQUFZLFFBQVE7R0FDaEUsTUFBTSxlQUFlLEtBQUssS0FBSyxTQUFTLDJCQUEyQjtHQUNuRSxNQUFNLGdCQUFnQixLQUFLLEtBQUssS0FBSyxhQUFhLFFBQVEsT0FBTyxXQUFXO0dBRTVFLElBQUksQ0FBRSxNQUFNLE9BQU8sV0FBVyxHQUFJO0lBQ2hDLFFBQVEsS0FBSyx5QkFBeUIsYUFBYTtJQUNuRDtHQUNGO0dBR0EsTUFBTSxlQUFlLE1BQU0sT0FBTyxZQUFZO0dBRTlDLElBQUksQ0FBQyxjQUFjO0lBQ2pCLFFBQVEsS0FBSywwQkFBMEIsY0FBYztJQUNyRCxRQUFRLEtBQUssNkNBQTZDO0dBQzVEO0dBR0EsSUFBSSxjQUNGLElBQUksTUFBTSxPQUFPLGFBQWEsR0FBRztJQUkvQixNQUFNLE9BQU87SUFDYixRQUFRLElBQUkscUJBQXFCO0dBQ25DLE9BQ0UsUUFBUSxLQUFLLDJCQUEyQixlQUFlO0dBSzNELE9BQU8sSUFBSSxxQkFBcUIsT0FBTyxTQUFTLFVBQVU7SUFDeEQsTUFBTSxnQkFBaUIsUUFBUSxPQUFnQztJQUMvRCxNQUFNLFlBQVksS0FBSyxLQUFLLGFBQWEsUUFBUTtJQUNqRCxNQUFNLGVBQWUsS0FBSyx5QkFBeUIsV0FBVyxhQUFhO0lBQzNFLElBQUksaUJBQWlCLE1BQU07S0FDekIsTUFBTSxPQUFPLEdBQUcsQ0FBQyxDQUFDLEtBQUs7S0FDdkI7SUFDRjtJQUNBLE1BQU0sMEJBQTBCLEtBQUssU0FBUyxXQUFXLFlBQVksQ0FBQyxDQUFDLFFBQVEsT0FBTyxHQUFHO0lBRXpGLE1BQU0sWUFBWSxXQUFXO0lBRzdCLE1BQU0sZ0NBQW9EO0tBQ3hELE1BQU0sV0FBZ0M7TUFDcEMsTUFBTTtNQUNOLEtBQUssUUFBUTtNQUNiLE1BQU07TUFDTixRQUFRLFFBQVE7S0FDbEI7S0FHQSxJQUFJLE9BQU8scUJBQXFCO01BQzlCLE1BQU0sU0FBUyxPQUFPLG9CQUFvQixRQUFRO01BQ2xELElBQUksUUFBUSxPQUFPO0tBQ3JCO0tBR0EsT0FBTyxhQUFhO0lBQ3RCO0lBR0EsSUFBSSw4QkFBOEIsS0FBSyx1QkFBdUIsR0FBRztLQUMvRCxNQUFNLE1BQU0sd0JBQXdCLE1BQU0sR0FBRyxDQUFDLENBQUMsSUFBSTtLQUVuRCxNQUFNLGVBQWMsTUFEQSxHQUFHLFFBQVEsU0FBUyxFQUNwQixDQUFNLE1BQU0sTUFBTSxFQUFFLFdBQVcsUUFBUSxLQUFLLEVBQUUsU0FBUyxJQUFJLEtBQUssQ0FBQztLQUVyRixJQUFJLGFBQWE7TUFDZixNQUFNLFdBQVcsS0FBSyxLQUFLLFdBQVcsV0FBVztNQUNqRCxNQUFNLFVBQVUsTUFBTSxHQUFHLFNBQVMsUUFBUTtNQUMxQyxNQUFNLEtBQUssUUFBUSxPQUFPLDJCQUEyQixVQUFVO01BQy9ELGtCQUFrQixPQUFPLHdCQUF3QixDQUFDO01BQ2xELE9BQU8sTUFBTSxLQUFLLE9BQU87S0FDM0I7SUFDRjtJQUdBLE1BQU0sV0FBVztJQUNqQixJQUFJLE1BQU0sT0FBTyxRQUFRLEdBQUc7S0FDMUIsTUFBTSxVQUFVLE1BQU0sR0FBRyxTQUFTLFFBQVE7S0FDMUMsTUFBTSxNQUFNLHdCQUF3QixNQUFNLEdBQUcsQ0FBQyxDQUFDLElBQUk7S0FDbkQsTUFBTSxLQUFLLFFBQVEsT0FBTywyQkFBMkIsUUFBUSxRQUFRLGFBQWEsRUFBRTtLQUNwRixJQUFJLHdCQUF3QixTQUFTLEdBQUcsR0FDdEMsa0JBQWtCLE9BQU8sd0JBQXdCLENBQUM7S0FFcEQsT0FBTyxNQUFNLEtBQUssT0FBTztJQUMzQjtJQUVBLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxLQUFLO0dBQ3pCLENBQUM7R0FHRCxJQUFJLGNBQWM7SUFDaEIsTUFBTSxFQUFFLGlCQUFpQixNQUFNLE9BQU87SUFDdEMsTUFBTSxFQUFFLGNBQWMsTUFBTSxPQUFPO0lBQ25DLE1BQU0sWUFBWSxhQUFhO0lBRS9CLEtBQUssTUFBTSxTQUFTLFdBQ2xCLE9BQU8sTUFBTTtLQUNYLFFBQVEsQ0FBQyxPQUFPLE1BQU07S0FDdEIsS0FBSyxNQUFNO0tBQ1gsVUFBVSx3QkFBd0IsTUFBTSxZQUFZLE1BQU0scUJBQXFCO0tBQy9FLFNBQVMsT0FBTyxTQUFTLFVBQVU7TUFDakMsTUFBTSxNQUFNLFFBQVE7TUFDcEIsUUFBUSxJQUFJLHdCQUF3QixNQUFNLE1BQU07TUFHaEQsTUFBTSxPQUFPLE1BQU0sVUFBVSxLQUFLLE9BRG5CLEtBQUssa0JBQWtCLE1BQU0sTUFBTSxHQUNULEdBQVEsU0FBUyxPQUFPLE1BQU07TUFFdkUsTUFBTSxLQUFLLFdBQVc7TUFDdEIsT0FBTztLQUNUO0lBQ0YsQ0FBQztHQUVMO0dBR0EsT0FBTyxNQUFNO0lBQ1gsUUFBUSxDQUFDLE9BQU8sTUFBTTtJQUN0QixLQUFLO0lBQ0wsU0FBUyxPQUFPLFNBQVMsVUFBVTtLQUVqQyxJQUFJLFFBQVEsSUFBSSxXQUFXLE1BQU0sS0FBSyxRQUFRLElBQUksV0FBVyxZQUFZLEdBQUc7TUFDMUUsTUFBTSxPQUFPLEdBQUcsQ0FBQyxDQUFDLEtBQUs7TUFDdkI7S0FDRjtLQUdBLElBQUksT0FBTyxxQkFBcUI7TUFDOUIsTUFBTSxjQUFtQztPQUN2QyxNQUFNO09BQ04sS0FBSyxRQUFRO09BQ2IsTUFBTSxRQUFRLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztPQUM3QixRQUFRLFFBQVE7TUFDbEI7TUFDQSxNQUFNLGlCQUFpQixPQUFPLG9CQUFvQixXQUFXO01BRTdELElBQUksZ0JBQ0Ysa0JBQWtCLE9BQU8sY0FBYztLQUUzQztLQUdBLE1BQU0sY0FBYyxLQUFLLG1CQUFtQixRQUFRLEdBQUc7S0FDdkQsTUFBTSxlQUFlLEtBQUsseUJBQXlCLGFBQWEsV0FBVztLQUMzRSxJQUFJLGlCQUFpQixNQUFNO01BQ3pCLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxLQUFLO01BQ3ZCO0tBQ0Y7S0FDQSxJQUFJLE1BQU0sV0FBVyxZQUFZLEdBQUc7TUFDbEMsTUFBTSxVQUFVLE1BQU0sR0FBRyxTQUFTLFlBQVk7TUFDOUMsT0FBTyxNQUFNLEtBQUtBLE9BQVcsWUFBWSxLQUFLLDBCQUEwQixDQUFDLENBQUMsS0FBSyxPQUFPO0tBQ3hGO0tBR0EsTUFBTSxZQUFZLEtBQUssS0FBSyxhQUFhLFlBQVk7S0FDckQsT0FBTyxNQUFNLEtBQUssV0FBVyxDQUFDLENBQUMsS0FBSyxNQUFNLEdBQUcsU0FBUyxXQUFXLE9BQU8sQ0FBQztJQUMzRTtHQUNGLENBQUM7R0FFRCxRQUFRLElBQUksdUNBQXVDLGVBQWUsUUFBUSxXQUFXLFNBQVM7RUFDaEc7RUFFQSxpQkFDRSxLQUNBLFFBQ29FO0dBQ3BFLE9BQU8sT0FBTyxTQUF5QixVQUEwQztJQUUvRSxNQUFNLFVBQW1CLE1BQU0sS0FBSyxjQUFjLFFBQVEsU0FBUyxLQUFLO0lBRXhFLE9BQU8sS0FBSyxrQkFBa0IsSUFBSSxFQUFFLFFBQVEsR0FBRyxZQUFZO0tBRXpELFVBQVU7TUFDUixRQUFRLElBQUksUUFBUTtNQUNwQjtNQUNBO01BQ0E7S0FDRixDQUFDO0tBR0QsTUFBTSxFQUFFLHdCQUF3QixNQUFNLE9BQU87S0FDN0MsTUFBTSxVQUFVLG9CQUFvQixLQUFLLEtBQUssT0FBTyxLQUFLO0tBRzFELE1BQU0sUUFBUSxJQUFJLFFBQVEsZUFBZSxRQUFRLFVBQVU7S0FDM0QsSUFBSTtLQUlKLE1BQU0sUUFHRjtNQUNGLGVBQWUsQ0FBQztNQUNoQixlQUFlLENBQUM7S0FDbEI7S0FFQSxJQUFJO01BQ0YsTUFBTSxPQUFRLFFBQVEsVUFBVSxDQUFDO01BQ2pDLElBQUksSUFBSSxlQUFlO09BQ3JCLE1BQU0sUUFBUSxRQUFRLE1BQU0sRUFDMUIsUUFBUSxJQUFJLGNBQWMsT0FDNUIsQ0FBQztPQUdELE1BQU0sU0FBaUMsQ0FBQztPQUV4QyxJQUFJLElBQUksY0FBYyxZQUFZLFlBQVksQ0FBQyxJQUFJLGNBQWMsU0FFL0Q7bUJBQVcsTUFBTSxRQUFRLE9BQ3ZCLElBQUksS0FBSyxTQUFTLFFBQVE7U0FHeEIsTUFBTSxTQUFTLE1BQU0sS0FBSyxTQUFTO1NBQ25DLE1BQU0sY0FBYyxLQUFLLElBQUksYUFBYSxNQUFNLE1BQU0sQ0FBQztRQUN6RCxPQUFPLElBQUksS0FBSyxTQUFTLFNBQ3ZCLE9BQU8sS0FBSyxhQUFhLE9BQU8sS0FBSyxLQUFLO09BRTlDLE9BQ0ssSUFBSSxJQUFJLGNBQWMsWUFBWSxVQUFVO1FBRWpELE1BQU0sV0FBVyxJQUFJLGNBQWM7UUFDbkMsTUFBTSxPQUFPLEtBQUssUUFBUSxJQUFJLFFBQVE7UUFHdEMsTUFBTSxlQUNKLElBQUksY0FBYyxnQkFDbEIsS0FBSyxPQUFPLE9BQU8sU0FBUyxnQkFDNUI7UUFFRixXQUFXLE1BQU0sUUFBUSxPQUN2QixJQUFJLEtBQUssU0FBUyxRQUFRO1NBQ3hCLE1BQU0sTUFBTSxNQUFNLGFBQWE7VUFDN0IsVUFBVSxLQUFLO1VBQ2YsVUFBVSxLQUFLO1NBQ2pCLENBQUM7U0FFRCxNQUFNLEtBQUssVUFBVSxLQUFLLEtBQUssTUFBTSxFQUNuQyxhQUFhLEtBQUssU0FDcEIsQ0FBQztTQUVELE1BQU0sTUFBTSxNQUFNLEtBQUssT0FBTyxHQUFHO1NBQ2pDLE1BQU0sWUFBWSxNQUFNLEtBQUssYUFBYSxHQUFHO1NBRTdDLE1BQU0sY0FBYyxLQUNsQixJQUFJLGFBQWE7VUFDZixVQUFVLEtBQUs7VUFDZixVQUFVLEtBQUs7VUFDZixNQUFNLEtBQUssS0FBSztVQUNoQjtVQUNBO1VBQ0E7VUFDQTtTQUNGLENBQUMsQ0FDSDtRQUNGLE9BQU8sSUFBSSxLQUFLLFNBQVMsU0FDdkIsT0FBTyxLQUFLLGFBQWEsT0FBTyxLQUFLLEtBQUs7T0FHaEQ7T0FJQSxNQUFNLFVBQVMsTUFERSxPQUFPLE1BQ1QsQ0FBRyxRQUFRLE1BQU0sTUFBTTtPQUN0QyxPQUFPLE9BQU8sTUFBTSxNQUFNO01BQzVCO01BRUEsTUFBTSxFQUFFLGtCQUFrQixNQUFNLE9BQU87TUFDdkMsVUFBVSxjQUFjLE9BQU8sQ0FBQyxDQUFDLE1BQU0sSUFBSTtLQUM3QyxTQUFTLEdBQUc7TUFDVixNQUFNLEVBQUUsYUFBYSxNQUFNLE9BQU87TUFDbEMsSUFBSSxhQUFhLFVBQVU7T0FDekIsTUFBTSxFQUFFLHFCQUFxQixNQUFNLE9BQU87T0FDMUMsTUFBTSxXQUFXLGlCQUFpQixDQUFDLENBQUMsQ0FDakMsS0FBSyxVQUFVLE1BQU0sT0FBTyxDQUFDLENBQzdCLEtBQUssR0FBRztPQUNYLE1BQU0sRUFBRSx3QkFBd0IsTUFBTSxPQUFPO09BQzdDLE1BQU0sSUFBSSxvQkFBb0IsVUFBNkIsRUFDekQsVUFBVSxFQUNaLENBQUM7TUFDSCxPQUNFLE1BQU07S0FFVjtLQUdBLE1BQU0sS0FBSyxJQUFJLFFBQVEsZUFBZSxrQkFBa0I7S0FHeEQsTUFBTSxpQkFBaUIsS0FBSyxtQkFBbUIsS0FBSyxTQUFTLE1BQU07S0FDbkUsSUFBSSxnQkFDRixrQkFBa0IsT0FBTyxjQUFjO0tBSXpDLElBQUksSUFBSSxlQUFlO01BQ3JCLE1BQU0sVUFBVSxJQUFJLGNBQWMsV0FBVztNQUM3QyxJQUFJLFlBQVksVUFDZCxRQUFRLGdCQUFnQixNQUFNO1dBQ3pCLElBQUksWUFBWSxVQUNyQixRQUFRLGdCQUFnQixNQUFNO0tBRWxDO0tBR0EsTUFBTSxFQUFFLGlCQUFpQixNQUFNLE9BQU87S0FDdEMsTUFBTSxPQUFPLElBQUksV0FBVyxLQUFLLFVBQVU7TUFFekMsSUFBSSxhQUFhLFVBQVUsTUFBTSxJQUFJLEdBQ25DLE9BQU87V0FFUCxPQUFPLFFBQVEsTUFBTTtLQUV6QixDQUFDO0tBRUQsT0FBTyxLQUFLLGtCQUFrQixLQUFLLE1BQU0sS0FBSztJQUNoRCxDQUFDO0dBQ0g7RUFDRjtFQUdBLHdDQUFnRDtHQUM5QyxPQUFPLE9BQU8sVUFBMEIsVUFBdUM7SUFDN0UsTUFBTSxPQUFPLGNBQWMsU0FBUyxDQUFDLENBQUMsT0FBTyxXQUFXLFdBQVcsQ0FBQyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsS0FBSyxFQUNwRixTQUFTLDZCQUNYLENBQUM7R0FDSDtFQUNGO0VBR0EsTUFBYywwQkFDWixRQUNBLFNBQ0EsUUFDZTtHQUNmLE1BQU0sYUFBYSxLQUFLLGVBQWUsT0FBTztHQUM5QyxJQUFJLENBQUMsWUFBWSxrQkFBa0I7SUFDakMsTUFBTSxlQUFlLEtBQUssaUJBQWlCLG9CQUFvQix3QkFBd0IsRUFDckYsU0FBUyxRQUFRLFFBQ25CLENBQUM7SUFDRCxLQUFLLGlCQUFpQixvQkFBb0IsS0FBSztLQUM3QyxNQUFNO0tBQ04sT0FBTztLQUNQLFFBQVE7TUFDTixRQUFRO01BQ1IsTUFBTSxRQUFRO0tBQ2hCO0tBQ0EsU0FBUyxhQUFhO0tBQ3RCLFFBQVEsYUFBYTtLQUNyQixjQUFjLGFBQWE7S0FDM0IsU0FBUyxhQUFhO0lBQ3hCLENBQUM7SUFDRCxPQUFPLE1BQU0sTUFBTSwyQkFBMkI7SUFDOUM7R0FDRjtHQUdBLE1BRGdCLEtBQUssdUJBQXVCLFlBQVksTUFDbEQsQ0FBQSxDQUFRLEVBQUUsT0FBTyxHQUFHLE9BQU87RUFDbkM7RUFPQSx1QkFBK0IsS0FBa0IsUUFBNkI7R0FDNUUsT0FBTyxPQUNMLFlBR0EsWUFDa0I7SUFDbEIsTUFBTSxTQUFTLFdBQVc7SUFDMUIsSUFBSSxZQUFxQztJQUN6QyxJQUFJLFFBQW1FO0lBQ3ZFLElBQUksbUJBQStEO0lBQ25FLElBQUksZUFBb0QsQ0FBQztJQUV6RCxJQUFJO0tBQ0YsZUFBZSxLQUFLLGlCQUFpQixvQkFBb0Isd0JBQXdCLEVBQy9FLFNBQVMsUUFBUSxRQUNuQixDQUFDO0tBRUQsbUJBQW1CO0tBQ25CLE1BQU0sVUFBVSxNQUFNLEtBQUssNEJBQTRCLEtBQUssT0FBTztLQUNuRSxtQkFBbUI7S0FDbkIsUUFBUSxLQUFLLGlCQUFpQixtQkFBbUIsUUFBUTtNQUN2RCxXQUFXLElBQUksaUJBQWtCO01BQ2pDLFVBQVUsSUFBSSxpQkFBa0I7TUFDaEMsV0FBVyxJQUFJLGlCQUFrQjtNQUNqQyxXQUFXLElBQUksaUJBQWtCO01BQ2pDLFFBQVE7TUFDUixTQUFTLGFBQWE7TUFDdEIsUUFBUSxhQUFhO01BQ3JCLGNBQWMsYUFBYTtNQUMzQixTQUFTLGFBQWE7S0FDeEIsQ0FBQztLQUVELE1BQU0sV0FBVyxLQUFLLGdDQUFnQyxhQUFhLFNBQVM7S0FDNUUsWUFBWSxNQUFNLEtBQUssdUJBQXVCLFFBQVEsU0FBUyxRQUFRO0tBRXZFLE1BQU0sS0FBSyxrQkFBa0IsSUFBSSxFQUFFLFNBQVMsVUFBVSxHQUFHLFlBQVk7TUFDbkUsVUFBVTtPQUNSLFFBQVEsSUFBSSxRQUFRO09BQ3BCO09BQ0E7T0FDQTtNQUNGLENBQUM7S0FDSCxDQUFDO0tBRUQsS0FBSyxpQkFBaUIsbUJBQW1CLE1BQU0sRUFBRTtLQUNqRCxtQkFBbUI7S0FFbkIsTUFBTSxFQUFFLGlCQUFpQixNQUFNLE9BQU87S0FDdEMsTUFBTSxPQUFPLElBQUksV0FBVyxLQUFLLFVBQVU7TUFDekMsSUFBSSxhQUFhLFVBQVUsTUFBTSxJQUFJLEdBQ25DLE9BQU87TUFHVCxPQUFPLFFBQVEsTUFBTTtLQUN2QixDQUFDO0tBRUQsTUFBTSxLQUFLLGtCQUFrQixJQUFJLEVBQUUsU0FBUyxVQUFVLEdBQUcsWUFBWTtNQUNuRSxNQUFNLEtBQUssa0JBQWtCLEtBQUssSUFBSTtLQUN4QyxDQUFDO0lBQ0gsU0FBUyxPQUFPO0tBQ2QsTUFBTSxrQkFBa0IsZ0NBQWdDLEtBQUs7S0FDN0QsSUFBSSxDQUFDLE9BQ0gsS0FBSyxpQkFBaUIsb0JBQW9CLEtBQUs7TUFDN0MsTUFBTTtNQUNOLE9BQU8sZ0JBQWdCLGFBQWEsU0FBUyxTQUFTO01BQ3RELFFBQVE7T0FDTixRQUFRO09BQ1IsTUFBTSxnQkFBZ0I7T0FDdEIsTUFBTSxJQUFJO01BQ1o7TUFDQSxTQUFTLGFBQWE7TUFDdEIsUUFBUSxhQUFhO01BQ3JCLGNBQWMsYUFBYTtNQUMzQixTQUFTLGFBQWE7S0FDeEIsQ0FBQztLQUdILElBQUksT0FDRixNQUFNLE1BQU0sZ0JBQWdCLE1BQU0sZ0JBQWdCLE1BQU07VUFDbkQsSUFBSSxPQUFPLGFBQWEsR0FDN0IsT0FBTyxNQUFNLGdCQUFnQixNQUFNLGdCQUFnQixNQUFNO0tBRzNELElBQUksS0FBSyxRQUFRLEtBQUs7TUFDcEIsTUFBTSxVQUFVO09BQ2QsS0FBSztPQUNMLFdBQVcsSUFBSTtPQUNmLFlBQVksSUFBSTtPQUNoQixNQUFNLElBQUk7TUFDWjtNQUNBLElBQUksZ0JBQWdCLGFBQWEsUUFDL0IsS0FBSyxPQUFPLElBQUksS0FBSyxTQUFTLGdCQUFnQixNQUFNO1dBRXBELEtBQUssT0FBTyxJQUFJLE1BQU0sU0FBUyxnQkFBZ0IsTUFBTTtLQUV6RCxPQUNFLElBQUksZ0JBQWdCLGFBQWEsUUFDL0IsUUFBUSxLQUFLLGdCQUFnQixRQUFRLEtBQUs7VUFFMUMsUUFBUSxNQUFNLGdCQUFnQixRQUFRLEtBQUs7SUFHakQ7R0FDRjtFQUNGO0VBSUEsZ0NBSUUsSUFDQSxZQUNnQztHQUNoQyxNQUFNLHNCQUFzQixLQUFLLG1CQUFtQjtHQUNwRCxNQUFNLGdCQUFtQixhQUF5QjtJQUNoRCxNQUFNLFVBQVUsV0FBVztJQUMzQixJQUFJLENBQUMsU0FDSCxPQUFPLFNBQVM7SUFHbEIsT0FBTyxLQUFLLGtCQUFrQixJQUFJLEVBQUUsUUFBUSxHQUFHLFFBQVE7R0FDekQ7R0FFQSxPQUFPO0lBQ0wsSUFBSSxLQUFLO0tBQ1AsT0FBTyxHQUFHO0lBQ1o7SUFDQSxJQUFJLFlBQVk7S0FDZCxPQUFPLEdBQUc7SUFDWjtJQUNBLElBQUksU0FBUztLQUNYLE9BQU8sR0FBRztJQUNaO0lBQ0EsSUFBSSxTQUFTO0tBQ1gsT0FBTyxHQUFHO0lBQ1o7SUFDQSxXQUFXO0lBQ1gsZUFBZSxPQUFPLE1BQU07S0FDMUIsR0FBRyxlQUFlLE9BQU8sSUFBSTtJQUMvQjtJQUNBLE1BQU0sTUFBTSxRQUFRO0tBQ2xCLEdBQUcsTUFBTSxNQUFNLE1BQU07SUFDdkI7SUFDQSxRQUFRLFVBQVU7S0FDaEIsR0FBRyxjQUFjLGFBQWEsUUFBUSxDQUFDO0lBQ3pDO0lBQ0EsVUFBVSxPQUFPLFNBQVM7S0FDeEIsR0FBRyxVQUFVLFFBQVEsTUFBTSx3QkFDekIsYUFBYSxZQUFZO01BQ3ZCLE1BQU0sWUFBWSxPQUFPLEtBQUs7TUFDOUIsTUFBTSxlQUFlLHVCQUF1Qiw2QkFBNkIsRUFBRTtNQUMzRSxNQUFNLFlBQVksWUFBWSxJQUFJO01BRWxDLHFCQUFxQixLQUFLO09BQ3hCLE1BQU07T0FDTixPQUFPO09BQ1AsY0FBYyxHQUFHO09BQ2pCLFdBQVcsR0FBRztPQUNkLFFBQVEsR0FBRztPQUNYLFFBQVEsRUFBRSxPQUFPLFVBQVU7T0FDM0IsR0FBRztNQUNMLENBQUM7TUFFRCxJQUFJO09BQ0YsTUFBTSxTQUFTLE1BQU0sUUFBUSxNQUFNLG1CQUFtQjtPQUN0RCxNQUFNLGFBQWEsWUFBWSxJQUFJLElBQUk7T0FDdkMscUJBQXFCLEtBQUs7UUFDeEIsTUFBTTtRQUNOLE9BQU87UUFDUCxjQUFjLEdBQUc7UUFDakIsV0FBVyxHQUFHO1FBQ2QsUUFBUSxHQUFHO1FBQ1gsUUFBUSxFQUFFLE9BQU8sVUFBVTtRQUMzQixHQUFHO09BQ0wsQ0FBQztPQUNELHFCQUFxQixXQUFXO1FBQzlCLGVBQWU7UUFDZixNQUFNO1FBQ047UUFDQSxRQUFRO1FBQ1IsY0FBYyxHQUFHO1FBQ2pCLFdBQVcsR0FBRztRQUNkLFFBQVEsR0FBRztRQUNYLFlBQVksRUFBRSxPQUFPLFVBQVU7UUFDL0IsR0FBRztPQUNMLENBQUM7T0FDRCxPQUFPO01BQ1QsU0FBUyxPQUFPO09BQ2QsTUFBTSxhQUFhLFlBQVksSUFBSSxJQUFJO09BQ3ZDLHFCQUFxQixLQUFLO1FBQ3hCLE1BQU07UUFDTixPQUFPO1FBQ1AsY0FBYyxHQUFHO1FBQ2pCLFdBQVcsR0FBRztRQUNkLFFBQVEsR0FBRztRQUNYLFFBQVEsRUFBRSxPQUFPLFVBQVU7UUFDM0IsR0FBRztPQUNMLENBQUM7T0FDRCxxQkFBcUIsV0FBVztRQUM5QixlQUFlO1FBQ2YsTUFBTTtRQUNOO1FBQ0EsUUFBUTtRQUNSLGNBQWMsR0FBRztRQUNqQixXQUFXLEdBQUc7UUFDZCxRQUFRLEdBQUc7UUFDWCxZQUFZLEVBQUUsT0FBTyxVQUFVO1FBQy9CLFdBQVcsaUJBQWlCLFFBQVEsTUFBTSxPQUFPLE9BQU87UUFDeEQsR0FBRztPQUNMLENBQUM7T0FDRCxNQUFNO01BQ1I7S0FDRixDQUFDLENBQ0g7SUFDRjtJQUNBLFFBQVEsT0FBTyxNQUFNO0tBQ25CLEdBQUcsUUFBUSxPQUFPLElBQUk7SUFDeEI7SUFDQSxlQUFlO0tBQ2IsT0FBTyxHQUFHLGFBQWE7SUFDekI7SUFDQSxLQUFLLFFBQVE7S0FDWCxHQUFHLEtBQUssTUFBTTtJQUNoQjtJQUNBLE1BQU0sUUFBUTtLQUNaLEdBQUcsTUFBTSxNQUFNO0lBQ2pCO0lBQ0EsVUFBVSxRQUFRO0tBQ2hCLEdBQUcsVUFBVSxNQUFNO0lBQ3JCO0lBQ0EsY0FBYztLQUNaLEdBQUcsWUFBWTtJQUNqQjtHQUNGO0VBQ0Y7RUFFQSxNQUFjLDRCQUNaLEtBQ0EsU0FDa0M7R0FDbEMsTUFBTSxFQUFFLHdCQUF3QixNQUFNLE9BQU87R0FDN0MsTUFBTSxVQUFVLG9CQUFvQixLQUFLLEtBQUssT0FBTyxLQUFLO0dBRTFELElBQUk7SUFDRixNQUFNLEVBQUUsa0JBQWtCLE1BQU0sT0FBTztJQUN2QyxPQUFPLGNBQWMsT0FBTyxDQUFDLENBQUMsTUFBTyxRQUFRLFNBQVMsQ0FBQyxDQUE2QjtHQUN0RixTQUFTLEdBQUc7SUFDVixNQUFNLEVBQUUsYUFBYSxNQUFNLE9BQU87SUFDbEMsSUFBSSxhQUFhLFVBQVU7S0FDekIsTUFBTSxFQUFFLHFCQUFxQixNQUFNLE9BQU87S0FDMUMsTUFBTSxXQUFXLGlCQUFpQixDQUFDLENBQUMsQ0FDakMsS0FBSyxVQUFVLE1BQU0sT0FBTyxDQUFDLENBQzdCLEtBQUssR0FBRztLQUNYLE1BQU0sRUFBRSx3QkFBd0IsTUFBTSxPQUFPO0tBQzdDLE1BQU0sSUFBSSxvQkFBb0IsVUFBNkIsRUFDekQsVUFBVSxFQUNaLENBQUM7SUFDSDtJQUVBLE1BQU07R0FDUjtFQUNGOzs7OztFQU1BLGtCQUEwQixTQUFpQixLQUFxQztHQUM5RSxNQUFNLGVBQWUsUUFBUSxNQUFNLEdBQUcsQ0FBQyxDQUFDLE9BQU8sT0FBTztHQUN0RCxNQUFNLFdBQVcsS0FBSyxtQkFBbUIsR0FBRyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxPQUFPLE9BQU87R0FDdkUsTUFBTSxTQUFpQyxDQUFDO0dBRXhDLEtBQUssSUFBSSxJQUFJLEdBQUcsSUFBSSxhQUFhLFFBQVEsS0FDdkMsSUFBSSxhQUFhLEVBQUUsQ0FBQyxXQUFXLEdBQUcsR0FDaEMsT0FBTyxhQUFhLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxTQUFTO0dBR2hELE9BQU87RUFDVDtFQUVBLG1CQUEyQixTQUFpQixLQUFzQjtHQUNoRSxNQUFNLGVBQWUsUUFBUSxNQUFNLEdBQUcsQ0FBQyxDQUFDLE9BQU8sT0FBTztHQUN0RCxNQUFNLFdBQVcsS0FBSyxtQkFBbUIsR0FBRyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxPQUFPLE9BQU87R0FFdkUsSUFBSSxhQUFhLFdBQVcsU0FBUyxRQUNuQyxPQUFPO0dBR1QsS0FBSyxJQUFJLElBQUksR0FBRyxJQUFJLGFBQWEsUUFBUSxLQUFLO0lBQzVDLE1BQU0sY0FBYyxhQUFhO0lBQ2pDLE1BQU0sVUFBVSxTQUFTO0lBQ3pCLElBQUksWUFBWSxXQUFXLEdBQUcsR0FDNUI7SUFFRixJQUFJLGdCQUFnQixTQUNsQixPQUFPO0dBRVg7R0FFQSxPQUFPO0VBQ1Q7RUFFQSxtQkFBMkIsS0FBcUI7R0FDOUMsT0FBTyxJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7RUFDeEI7RUFFQSx5QkFBaUMsU0FBaUIsV0FBa0M7R0FDbEYsSUFBSTtJQUNGLE1BQU0sVUFBVSxtQkFBbUIsU0FBUyxDQUFDLENBQUMsUUFBUSxPQUFPLEdBQUc7SUFDaEUsSUFBSSxRQUFRLFNBQVMsSUFBSSxHQUN2QixPQUFPO0lBRVQsTUFBTSxlQUFlLFFBQVEsUUFBUSxRQUFRLEVBQUU7SUFDL0MsTUFBTSxlQUFlLEtBQUssUUFBUSxTQUFTLFlBQVk7SUFDdkQsTUFBTSxtQkFBbUIsS0FBSyxTQUFTLFNBQVMsWUFBWTtJQUM1RCxJQUFJLGlCQUFpQixXQUFXLElBQUksS0FBSyxLQUFLLFdBQVcsZ0JBQWdCLEdBQ3ZFLE9BQU87SUFFVCxPQUFPO0dBQ1QsUUFBUTtJQUNOLE9BQU87R0FDVDtFQUNGOzs7OztFQU1BLG1CQUNFLEtBQ0EsU0FDQSxRQUNBO0dBRUEsSUFBSSxJQUFJLFFBQVEsY0FDZCxPQUFPLElBQUksUUFBUTtHQUlyQixJQUFJLE9BQU8scUJBQXFCO0lBQzlCLE1BQU0sV0FBZ0M7S0FDcEMsTUFBTTtLQUNOLEtBQUssUUFBUTtLQUNiLE1BQU0sUUFBUSxjQUFjLE9BQU8sUUFBUSxJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7S0FDMUQsUUFBUSxRQUFRO0tBQ2hCO0lBQ0Y7SUFDQSxNQUFNLFNBQVMsT0FBTyxvQkFBb0IsUUFBUTtJQUNsRCxJQUFJLFFBQVEsT0FBTztHQUNyQjtHQUVBLE9BQU87RUFDVDs7Ozs7RUFNQSxNQUFNLGdCQUNKLEtBQ0EsUUFDQSxRQUNBLFNBQ0EsT0FDa0I7R0FFbEIsTUFBTSxVQUFVLE1BQU0sS0FBSyxjQUFjLFFBQVEsU0FBUyxLQUFLO0dBRS9ELE9BQU8sS0FBSyxrQkFBa0IsSUFBSSxFQUFFLFFBQVEsR0FBRyxZQUFZO0lBRXpELE1BQU0sRUFBRSxpQkFBaUIsTUFBTSxPQUFPO0lBQ3RDLElBQUksY0FBYztJQUNsQixNQUFNLE9BQU8sSUFBSSxXQUFXLEtBQUssVUFBVTtLQUN6QyxJQUFJLGFBQWEsVUFBVSxNQUFNLElBQUksR0FDbkMsT0FBTztLQUVULE9BQU8sT0FBTztJQUNoQixDQUFDO0lBR0QsT0FBTyxLQUFLLGtCQUFrQixLQUFLLE1BQU0sS0FBSztHQUNoRCxDQUFDO0VBQ0g7RUFHQSxNQUFNLGtCQUNKLEtBQ0EsTUFDQSxPQUNrQjtHQUNsQixNQUFNLFFBQVEsS0FBSyxPQUFPLE9BQU8sSUFBSTtHQUNyQyxNQUFNLFNBQVMsTUFBTyxNQUFjLElBQUksV0FBVyxDQUFDLE1BQU0sT0FBTyxJQUFJO0dBQ3JFLE9BQU8sS0FBSyxJQUFJLFFBQVEsZUFBZSxrQkFBa0I7R0FFekQsT0FBTztFQUNUO0VBRUEsTUFBTSxjQUNKLFFBQ0EsU0FDQSxPQUNrQjtHQUVsQixNQUFNLEVBQUUscUJBQXFCLE1BQU0sT0FBTztHQUMxQyxNQUFNLGNBQ0osVUFDQSxRQUNBLFlBQ0csaUJBQWlCLFNBQVMsUUFBUSxRQUFRLE9BQU8sRUFBQSxDQUFHLEtBQUssTUFBTSxTQUFTLEtBQUs7R0FHbEYsTUFBTSxTQUNKLEtBQUssYUFBYSxRQUFRLFFBQVEsb0JBQW9CLEtBQUssT0FBTyxLQUFLLGdCQUFnQixLQUN2RixLQUFLLE9BQU8sS0FBSztHQUduQixNQUFNLFVBQVUsZ0NBQWdDLFFBQVEsT0FBTztHQUMvRCxNQUFNLFVBQVcsTUFBTSxLQUFLLE9BQU8sSUFBSSxXQUFXLEVBQUUsUUFBUSxDQUFDLEtBQU07R0FvQm5FLE9BQU8sTUFsQndCLFFBQVEsUUFDckMsT0FBTyxnQkFDTDtJQUNFLFdBQVc7SUFDWDtJQUNBO0lBQ0EsU0FBUyxRQUFRO0lBQ2pCO0lBQ0EsNEJBQVksSUFBSSxJQUFJO0lBQ3BCO0lBRUEsTUFBTSxTQUFTLFFBQVE7SUFDdkIsU0FBUyxTQUFTLFdBQVc7R0FDL0IsR0FDQSxTQUNBLEtBQ0YsQ0FDRjtFQUVGO0VBSUEsTUFBTSx1QkFDSixRQUNBLFNBQ0EsSUFDMkI7R0FDM0IsTUFBTSxTQUNKLEtBQUssYUFBYSxRQUFRLFFBQVEsb0JBQW9CLEtBQUssT0FBTyxLQUFLLGdCQUFnQixLQUN2RixLQUFLLE9BQU8sS0FBSztHQUVuQixNQUFNLFVBQVUsZ0NBQWdDLFFBQVEsT0FBTztHQUMvRCxNQUFNLFVBQVcsTUFBTSxLQUFLLE9BQU8sSUFBSSxXQUFXLEVBQUUsUUFBUSxDQUFDLEtBQU07R0FFbkUsTUFBTSxpQkFBaUI7SUFDckIsV0FBVztJQUNYO0lBQ0EsU0FBUyxRQUFRO0lBQ2pCO0lBQ0EsNEJBQVksSUFBSSxJQUFJO0lBQ3BCO0lBQ0EsTUFBTSxTQUFTLFFBQVE7SUFDdkIsU0FBUyxTQUFTLFdBQVc7R0FDL0I7R0FFQSxJQUFJLE9BQU8sMEJBQ1QsT0FBTyxFQUNMLEdBQUksTUFBTSxRQUFRLFFBQVEsT0FBTyx5QkFBeUIsZ0JBQWdCLE9BQU8sQ0FBQyxFQUNwRjtHQUlGLE1BQU0sWUFBWSx5QkFBeUI7R0FDM0MsTUFBTSxhQUFrQyxZQUFlO0lBQ3JELE1BQU0sSUFBSSxNQUNSLGdJQUNGO0dBQ0Y7R0FtQkEsTUFBTSxFQUNKLFdBQVcsWUFDWCxPQUFPLFFBQ1AsV0FBVyxZQUNYLGVBQWUsZ0JBQ2YsZUFBZSxnQkFDZixHQUFHLFNBQ0QsTUF6QjBCLFFBQVEsUUFDcEMsT0FBTyxnQkFDTDtJQUNFLFdBQVc7SUFDWDtJQUNBLE9BQU87SUFDUCxTQUFTLFFBQVE7SUFDakI7SUFDQSxZQUFZLGVBQWU7SUFDM0I7SUFDQSxNQUFNLGVBQWU7SUFDckIsU0FBUyxlQUFlO0dBQzFCLEdBQ0EsU0FDQSxTQUNGLENBQ0Y7R0FXQSxPQUFPO0lBQ0wsR0FBRztJQUNILFdBQVc7SUFDWDtJQUNBLFNBQVMsUUFBUTtJQUNqQjtHQUNGO0VBQ0Y7Ozs7O0VBTUEsYUFDRSxnQkFDQSxXQUNvQjtHQUNwQixJQUFJLENBQUMsZ0JBQWdCLE9BQU87R0FRNUIsT0FMYyxlQUFlLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSyxTQUFTO0lBQ3BELE1BQU0sQ0FBQyxRQUFRLEtBQUssTUFBTSxHQUFHO0lBQzdCLE9BQU8sS0FBSyxLQUFLLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0dBQ2hDLENBRU8sQ0FBQSxDQUFNLE1BQU0sU0FBUyxVQUFVLFNBQVMsSUFBSSxDQUFDO0VBQ3REO0VBRUEsTUFBTSxlQUE4QjtHQUVsQyxNQUFNLEVBQUUsaUJBQWlCLE1BQU0sT0FBTztHQUN0QyxLQUFLLFVBQVUsTUFBTSxjQUFjLGVBQWUsS0FBSyxnQkFBZ0IsVUFBVSxDQUFDO0VBQ3BGOzs7OztFQU1BLE1BQWMsZ0JBQWdCLFlBQWdFO0dBQzVGLE1BQU0sWUFBWSxLQUFLLElBQUk7R0FFM0IsS0FBSyxNQUFNLENBQUMsVUFBVSxVQUFVLFlBQVk7SUFDMUMsTUFBTSxlQUFlLEtBQUssU0FBUyxLQUFLLGFBQWEsUUFBUTtJQUM3RCxRQUFRLElBQUksTUFBTSxLQUFLLFlBQVksTUFBTSxLQUFLLE1BQU0sS0FBSyxZQUFZLEdBQUcsQ0FBQztHQUMzRTtHQUdBLE1BQU0sS0FBSyxPQUFPLFdBQVcsVUFBVTtHQUN2QyxNQUFNLEtBQUssT0FBTyxlQUFlO0dBRWpDLE1BQU0sWUFBWSxLQUFLLElBQUksSUFBSTtHQUMvQixNQUFNLE1BQU0sYUFBYSxNQUFNLEtBQUssTUFBTSxHQUFHLFVBQVUsR0FBRztHQUMxRCxRQUFRLElBQUksTUFBTSxNQUFNLFFBQVEsV0FBVyxHQUFHLENBQUMsQ0FBQztFQUNsRDtFQUtBLE1BQU0sVUFBVSxJQUF5QjtHQUN2QyxNQUFNLEtBQUssS0FBSyxNQUFNLE9BQU8sUUFBVyxLQUFLO0dBQzdDLElBQUk7SUFDRixNQUFNLEdBQUc7R0FDWCxVQUFVO0lBQ1IsTUFBTSxLQUFLLFFBQVE7R0FDckI7RUFDRjtFQUVBLE1BQWMsZ0JBQWdCLFFBQXlCLFNBQXlDO0dBQzlGLElBQUksQ0FBQyxTQUNIO0dBSUYsSUFBSSxRQUFRLFVBQVU7SUFDcEIsTUFBTSxrQkFBa0IsTUFBTSxPQUFPLHFCQUFBLENBQXNCO0lBQzNELE1BQU0saUJBQWlCO0tBQ3JCLFdBQVc7S0FDWCxXQUFXO01BQUM7TUFBTTtNQUFRO0tBQVM7SUFDckM7SUFFQSxJQUFJLFFBQVEsYUFBYSxNQUN2QixPQUFPLFNBQVMsZ0JBQWdCLGNBQWM7U0FFOUMsT0FBTyxTQUFTLGdCQUFnQjtLQUM5QixHQUFHO0tBQ0gsR0FBRyxRQUFRO0lBQ2IsQ0FBQztHQUVMO0dBRUEsTUFBTSxpQkFBaUI7SUFDckIsTUFBTTtJQUNOLFVBQVU7SUFDVixXQUFXO0lBQ1gsSUFBSTtJQUNKLEtBQUs7SUFDTCxRQUFRO0dBQ1Y7R0FFQSxNQUFNLGlCQUFpQixPQUNyQixLQUNBLGVBQ0c7SUFDSCxNQUFNLFNBQVMsUUFBUTtJQUN2QixJQUFJLENBQUMsUUFBUTtJQUViLElBQUksV0FBVyxNQUNiLE9BQU8sVUFBVSxNQUFNLE9BQU8sWUFBQSxDQUFhLE9BQU87U0FFbEQsT0FBTyxVQUFVLE1BQU0sT0FBTyxZQUFBLENBQWEsU0FBUyxNQUFNO0dBRTlEO0dBRUEsS0FBSyxNQUFNLENBQUMsS0FBSyxlQUFlLE9BQU8sUUFBUSxjQUFjLEdBQzNELE1BQU0sZUFBZSxLQUE2QixVQUFVO0dBRzlELElBQUksUUFBUSxJQUNWLE1BQU0sS0FBSyxzQkFBc0IsTUFBTTtHQUd6QyxJQUFJLFFBQVEsUUFDVixRQUFRLE9BQU8sTUFBTTtFQUV6QjtFQUdBLE1BQWMsc0JBQ1osUUFDZTtHQUNmLElBQUksS0FBSyx1QkFBdUIsSUFBSSxNQUFNLEdBQ3hDO0dBR0YsTUFBTSxlQUFlLEtBQUssT0FBTyxPQUFPLFNBQVM7R0FDakQsSUFBSSxDQUFDLGNBQ0g7R0FHRixNQUFNLG1CQUFtQixNQUFNLE9BQU8sc0JBQUEsQ0FBdUI7R0FDN0QsTUFBTSx3QkFBd0IsOEJBQThCLEVBQzFELGlCQUFpQixhQUNuQixDQUFDO0dBQ0QsSUFBSSx1QkFDRixNQUFNLE9BQU8sU0FBUyxpQkFBaUIscUJBQXFCO1FBRTVELE1BQU0sT0FBTyxTQUFTLGVBQWU7R0FHdkMsS0FBSyx1QkFBdUIsSUFBSSxNQUFNO0dBQ3RDLEtBQUsseUNBQXlDLE1BQU07RUFDdEQ7RUFHQSx5Q0FDRSxRQUNNO0dBQ04sTUFBTSxhQUFhLEtBQUssT0FBTyxLQUM1QixLQUFLLFFBQVEsSUFBSSxrQkFBa0IsYUFBYSxHQUFLLENBQUMsQ0FDdEQsUUFBUSxjQUFjLFlBQVksQ0FBQztHQUV0QyxJQUFJLFdBQVcsV0FBVyxHQUN4QjtHQUdGLE1BQU0sbUJBQW1CLEtBQUssT0FBTyxPQUFPLFNBQVM7R0FDckQsSUFBSSxDQUFDLG9CQUFvQixvQkFBb0IsR0FDM0M7R0FHRixNQUFNLG1CQUFtQixLQUFLLElBQUksR0FBRyxVQUFVO0dBQy9DLElBQUksb0JBQW9CLGtCQUN0QixPQUFPLElBQUksS0FDVDtJQUNFO0lBQ0E7R0FDRixHQUNBLHVJQUNGO0VBRUo7Ozs7O0VBTUEsTUFBYyxtQkFDWixRQUNBLFNBQ0E7R0FDQSxJQUFJLENBQUMsU0FBUztHQUVkLE1BQU0sV0FBVyxRQUFRLFlBQVk7R0FHckMsT0FBTyxNQUFNO0lBQ1gsUUFBUSxDQUFDLE9BQU8sTUFBTTtJQUN0QixLQUFLLEdBQUcsU0FBUztJQUNqQixTQUFTLE9BQU8sU0FBUyxVQUFVO0tBQ2pDLE1BQU0sV0FBVyxNQUFNLEtBQUssS0FBSyxRQUMvQix3QkFBd0IsU0FBUyxRQUFRLFVBQVUsV0FBVyxnQkFBZ0IsQ0FDaEY7S0FFQSxNQUFNLE9BQU8sU0FBUyxNQUFNO0tBQzVCLFNBQVMsUUFBUSxTQUFTLE9BQWUsUUFBZ0I7TUFDdkQsTUFBTSxPQUFPLEtBQUssS0FBSztLQUN6QixDQUFDO0tBQ0QsT0FBTyxNQUFNLEtBQUssU0FBUyxPQUFPLE1BQU0sU0FBUyxLQUFLLElBQUksSUFBSTtJQUNoRTtHQUNGLENBQUM7RUFDSDtFQUVBLE1BQWMsc0JBQXNCO0dBQ2xDLE1BQU0sU0FBUyxNQUFNLE9BQU8sU0FBQSxDQUFVO0dBQ3RDLE1BQU0sZUFBZSxxQkFBcUI7R0FFMUMsTUFBTSxPQUFPLFFBQWdCLFFBQVEsSUFBSSxNQUFNLElBQUksS0FBSyxLQUFLLENBQUM7R0FDOUQsTUFBTSxTQUFTLFFBQWdCLFFBQVEsSUFBSSxNQUFNLE1BQU0sS0FBSyxLQUFLLENBQUM7R0FFbEUsSUFBSSxnQkFBZ0IsV0FBVyxLQUFLLGNBQWMsR0FBRztHQUdyRCxNQUFNLElBQUk7R0FDVixNQUFNLEVBQUUsWUFBWSxNQUFNLE9BQU87R0FDakMsTUFBTSxjQUFjLE9BQU8sS0FBSyxLQUFLLFFBQVE7R0FDN0MsTUFBTSxTQUFTLEtBQUssSUFBSSxHQUFHLFlBQVksS0FBSyxNQUFNLEVBQUUsTUFBTSxDQUFDO0dBQzNELEtBQUssTUFBTSxRQUFRLGFBQWE7SUFDOUIsTUFBTSxPQUFPLEtBQUssU0FBUyxLQUFLLENBQUM7SUFHakMsTUFBTSxPQUFPLE1BQU0sUUFBUTtJQUMzQixNQUFNLE9BQU8sS0FBSyxLQUFLLEdBQUcsTUFBTSxRQUFRLEtBQUssR0FBRyxNQUFNLFlBQVk7SUFDbEUsTUFBTSxTQUFTLEtBQUssT0FBTyxNQUFNO0lBQ2pDLE1BQU0sWUFBWSxRQUFRLEtBQUssQ0FBQyxZQUFZLElBQUksSUFBSSxNQUFNLE9BQU8sZ0JBQWdCLElBQUk7SUFFckYsSUFBSSxTQUFTLGNBQ1gsUUFBUSxJQUFJLE1BQU0sTUFBTSxZQUFZLE9BQU8sR0FBRyxNQUFNLElBQUksU0FBUztTQUVqRSxRQUFRLElBQUksTUFBTSxJQUFJLE9BQU8sT0FBTyxHQUFHLE1BQU0sSUFBSSxTQUFTO0dBRTlEO0dBRUEsSUFBSSxLQUFLLE9BQU8sT0FBTyxNQUVyQixJQUFJLHdCQURhLEtBQUssT0FBTyxPQUFPLEtBQUssWUFBWSxZQUNoQixHQUFHO0dBRTFDLElBQUksS0FBSyxPQUFPLElBQUksVUFDbEIsSUFBSSxhQUFhLEtBQUssT0FBTyxJQUFJLFVBQVU7R0FFN0MsTUFBTSxlQUFlLFdBQVcsS0FBSyxZQUFZLEdBQUc7RUFDdEQ7RUFFQSxNQUFjLGdCQUFnQixRQUFpQyxZQUFxQjtHQUNsRixNQUFNLEVBQUUsdUJBQXVCLE1BQU0sT0FBTztHQUc1QyxJQUFJLFlBQVk7SUFDZCxNQUFNLEVBQUUsMkJBQTJCLE1BQU0sT0FBTztJQUNoRCxLQUFLLFNBQVMsdUJBQXVCO0lBQ3JDLG1CQUFtQixLQUFLLE1BQU07SUFDOUI7R0FDRjtHQUdBLElBQUksQ0FBQyxRQUFRO0lBQ1gsbUJBQW1CLElBQUk7SUFDdkI7R0FDRjtHQUdBLE1BQU0sRUFBRSx1QkFBdUIsTUFBTSxPQUFPO0dBQzVDLEtBQUssU0FBUyxtQkFBbUIsTUFBTTtHQUN2QyxtQkFBbUIsS0FBSyxNQUFNO0VBQ2hDO0VBRUEsTUFBYyxvQkFBb0IsU0FBd0M7R0FDeEUsTUFBTSxFQUFFLG9CQUFvQixNQUFNLE9BQU87R0FFekMsS0FBSyxhQUFhLElBQUksZ0JBQWdCLEdBQUcsWUFBWSxHQUFHLENBQUM7R0FDekQsSUFBSSxDQUFDLFNBQ0g7R0FHRixNQUFNLGVBQWUsUUFBUSxnQkFBZ0IsZUFBZTtHQUM1RCxNQUFNLHVCQUF1QjtJQUMzQixhQUFhLEdBQUcsS0FBSyxDQUFDLENBQUMsU0FBUztJQUNoQyxXQUFXO0lBQ1gsYUFBYTtHQUNmO0dBRUEsSUFBSSxjQUNGLEtBQUssVUFBVSxZQUFZO0lBQ3pCLEdBQUc7SUFDSCxHQUFHLFFBQVE7R0FDYixDQUFDO0VBRUw7RUFFQSxNQUFjLEtBQUssUUFBeUIsU0FBOEI7R0FDeEUsTUFBTSxPQUFPLFFBQVEsUUFBUSxRQUFRO0dBQ3JDLE1BQU0sT0FBTyxRQUFRLFFBQVEsUUFBUTtHQUVyQyxPQUFPLFFBQVEsV0FBVyxZQUFZO0lBQ3BDLE1BQU0sUUFBUSxXQUFXLGFBQWEsTUFBTTtJQUM1QyxNQUFNLEtBQUssVUFBVSxRQUFRO0lBQzdCLE1BQU0sS0FBSyxRQUFRO0dBQ3JCLENBQUM7R0FFRCxNQUFNLFdBQVcsWUFBWTtJQUMzQixJQUFJO0tBQ0YsTUFBTSxPQUFPLE1BQU07S0FDbkIsUUFBUSxLQUFLLENBQUM7SUFDaEIsU0FBUyxLQUFLO0tBQ1osUUFBUSxNQUFNLDBCQUEwQixHQUFHO0tBQzNDLFFBQVEsS0FBSyxDQUFDO0lBQ2hCO0dBQ0Y7R0FFQSxRQUFRLEdBQUcsVUFBVSxRQUFRO0dBQzdCLFFBQVEsR0FBRyxXQUFXLFFBQVE7R0FFOUIsSUFBSSxRQUFRLFdBQVcsU0FDckIsT0FBTyxnQkFBZ0IsUUFBUSxXQUFXLE9BQU87R0FHbkQsT0FDRyxPQUFPO0lBQUU7SUFBTTtHQUFLLENBQUMsQ0FBQyxDQUN0QixLQUFLLFlBQVk7SUFDaEIsTUFBTSxLQUFLLFVBQVUsWUFBWTtJQUNqQyxNQUFNLFFBQVEsV0FBVyxVQUFVLE1BQU07R0FDM0MsQ0FBQyxDQUFDLENBQ0QsTUFBTSxPQUFPLFFBQVE7SUFDcEIsTUFBTSxTQUFTLE1BQU0sT0FBTyxTQUFBLENBQVU7SUFDdEMsUUFBUSxNQUFNLE1BQU0sSUFBSSwyQkFBMkIsR0FBRyxDQUFDO0lBQ3ZELE1BQU0sU0FBUztHQUNqQixDQUFDO0VBQ0w7RUFFQSxNQUFNLFVBQXlCO0dBQzdCLE1BQU0sRUFBRSxjQUFjLE1BQU0sT0FBTztHQUVuQyxNQUFNLFVBQVUsUUFBUTtHQUV4QixJQUFJLEtBQUssbUJBQ1AsTUFBTSxLQUFLLGtCQUFrQixTQUFTO0dBRXhDLEtBQUssb0JBQW9CO0dBRXpCLE1BQU0sUUFBUSxXQUFXO0lBQ3ZCLEtBQUssWUFBWSxRQUFRLEtBQUssUUFBUSxRQUFRO0lBQzlDLEtBQUssUUFBUSxXQUFXLEtBQUssUUFBUSxRQUFRO0lBQzdDLEtBQUssbUJBQW1CLFNBQVMsS0FBSyxRQUFRLFFBQVE7SUFDdEQsS0FBSyxTQUFTLE1BQU0sS0FBSyxRQUFRLFFBQVE7R0FDM0MsQ0FBQztHQUVELE1BQU1DLFFBQWU7RUFDdkI7Q0FDRjtDQWtCYSxTQUFTLElBQUksWUFBWTtDQWlCaEMsOEJBQWMsSUFBSSxJQUFJO0VBQUM7RUFBYTtFQUFhO0VBQVc7Q0FBSyxDQUFDIn0=
|